BitmapHeapScan streaming read user and prelim refactoring

Started by Melanie Plagemanalmost 2 years ago248 messages
#1Melanie Plageman
melanieplageman@gmail.com
11 attachment(s)

Hi,

Attached is a patch set which refactors BitmapHeapScan such that it
can use the streaming read API [1]/messages/by-id/CA+hUKGJkOiOCa+mag4BF+zHo7qo=o9CFheB8=g6uT5TUm2gkvA@mail.gmail.com. It also resolves the long-standing
FIXME in the BitmapHeapScan code suggesting that the skip fetch
optimization should be pushed into the table AMs. Additionally, it
moves table scan initialization to after the index scan and bitmap
initialization.

patches 0001-0002 are assorted cleanup needed later in the set.
patches 0003 moves the table scan initialization to after bitmap creation
patch 0004 is, I think, a bug fix. see [2]/messages/by-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ+opUrXDRXdcfwFZGA@mail.gmail.com.
patches 0005-0006 push the skip fetch optimization into the table AMs
patches 0007-0009 change the control flow of BitmapHeapNext() to match
that required by the streaming read API
patch 0010 is the streaming read code not yet in master
patch 0011 is the actual bitmapheapscan streaming read user.

patches 0001-0009 apply on top of master but 0010 and 0011 must be
applied on top of a commit before a 21d9c3ee4ef74e2 (until a rebased
version of the streaming read API is on the mailing list).

The caveat is that these patches introduce breaking changes to two
table AM functions for bitmapheapscan: table_scan_bitmap_next_block()
and table_scan_bitmap_next_tuple().

A TBMIterateResult used to be threaded through both of these functions
and used in BitmapHeapNext(). This patch set removes all references to
TBMIterateResults from BitmapHeapNext. Because the streaming read API
requires the callback to specify the next block, BitmapHeapNext() can
no longer pass a TBMIterateResult to table_scan_bitmap_next_block().

More subtly, table_scan_bitmap_next_block() used to return false if
there were no more visible tuples on the page or if the block that was
requested was not valid. With these changes,
table_scan_bitmap_next_block() will only return false when the bitmap
has been exhausted and the scan can end. In order to use the streaming
read API, the user must be able to request the blocks it needs without
requiring synchronous feedback per block. Thus, this table AM function
must change its meaning.

I think the way the patches are split up could be improved. I will
think more about this. There are also probably a few mistakes with
which comments are updated in which patches in the set.

- Melanie

[1]: /messages/by-id/CA+hUKGJkOiOCa+mag4BF+zHo7qo=o9CFheB8=g6uT5TUm2gkvA@mail.gmail.com
[2]: /messages/by-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ+opUrXDRXdcfwFZGA@mail.gmail.com

Attachments:

v1-0003-BitmapHeapScan-begin-scan-after-bitmap-setup.patchtext/x-patch; charset=US-ASCII; name=v1-0003-BitmapHeapScan-begin-scan-after-bitmap-setup.patchDownload
From d6dd6eb21dcfbc41208f87d1d81ffe3960130889 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v1 03/11] BitmapHeapScan begin scan after bitmap setup

There is no reason for table_beginscan_bm() to begin the actual scan of
the underlying table in ExecInitBitmapHeapScan(). We can begin the
underlying table scan after the index scan has been completed and the
bitmap built.

The one use of the scan descriptor during initialization was
ExecBitmapHeapInitializeWorker(), which set the scan descriptor snapshot
with one from an array in the parallel state. This overwrote the
snapshot set in table_beginscan_bm().

By saving that worker snapshot as a member in the BitmapHeapScanState
during initialization, it can be restored in table_beginscan_bm() after
returning from the table AM specific begin scan function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 27 ++++++++++++++---------
 src/include/access/tableam.h              | 18 +++++++++------
 src/include/nodes/execnodes.h             |  2 ++
 3 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 76382c91fd7..fd697d16c72 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -191,6 +191,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	node->worker_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -614,7 +625,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -691,7 +703,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -740,6 +753,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->can_skip_fetch = false;
+	scanstate->worker_snapshot = NULL;
 
 	/*
 	 * Miscellaneous initialization
@@ -788,11 +802,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
@@ -931,13 +940,11 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 							   ParallelWorkerContext *pwcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	Snapshot	snapshot;
 
 	Assert(node->ss.ps.state->es_query_dsa != NULL);
 
 	pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
 	node->pstate = pstate;
 
-	snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
-	table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
+	node->worker_snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
 }
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 4d495216f07..77f32a7472d 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -931,6 +931,11 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
+/*
+ * Update snapshot used by the scan.
+ */
+extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
+
 /*
  * table_beginscan_bm is an alternative entry point for setting up a
  * TableScanDesc for a bitmap heap scan.  Although that scan technology is
@@ -938,12 +943,16 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  * make it worth using the same data structure.
  */
 static inline TableScanDesc
-table_beginscan_bm(Relation rel, Snapshot snapshot,
+table_beginscan_bm(Relation rel, Snapshot snapshot, Snapshot worker_snapshot,
 				   int nkeys, struct ScanKeyData *key)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	if (worker_snapshot)
+		table_scan_update_snapshot(result, worker_snapshot);
+	return result;
 }
 
 /*
@@ -1033,11 +1042,6 @@ table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
 										 allow_pagemode);
 }
 
-/*
- * Update snapshot used by the scan.
- */
-extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
-
 /*
  * Return next tuple from `scan`, store in slot.
  */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 444a5f0fd57..00c75fb10e2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1726,6 +1726,7 @@ typedef struct ParallelBitmapHeapState
  *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		worker_snapshot	   snapshot for parallel worker
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1750,6 +1751,7 @@ typedef struct BitmapHeapScanState
 	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	Snapshot	worker_snapshot;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v1-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-patch; charset=US-ASCII; name=v1-0002-BitmapHeapScan-set-can_skip_fetch-later.patchDownload
From 5f915bc84eae56e52b5a61e9b7e691834fdb9680 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v1 02/11] BitmapHeapScan set can_skip_fetch later

There is no reason for BitmapHeapScan to calculate can_skip_fetch in
ExecInitBitmapHeapScan(). Moving it into BitmapHeapNext() is a
preliminary step toward moving can_skip_fetch into table AM specific
code, as we would need to set it after the scan has begun.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d670939246b..76382c91fd7 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,6 +108,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -729,16 +739,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.37.2

v1-0001-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-patch; charset=US-ASCII; name=v1-0001-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchDownload
From 575fb1f93128ebfd8125c769de628f91e0d5c592 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v1 01/11] Remove table_scan_bitmap_next_tuple parameter tbmres

Future commits will remove the input TBMIterateResult from
table_scan_bitmap_next_block() as the streaming read API will be
responsible for iterating through the blocks in the bitmap and not
BitmapHeapNext(). Given that this parameter will not be set from
BitmapHeapNext(), it no longer makes sense to use it as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().
---
 src/backend/access/heap/heapam_handler.c  | 1 -
 src/backend/executor/nodeBitmapHeapscan.c | 2 +-
 src/include/access/tableam.h              | 7 -------
 3 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d15a02b2be7..716d477e271 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2228,7 +2228,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c1e81ebed63..d670939246b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -304,7 +304,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Attempt to fetch tuple from AM.
 			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			if (!table_scan_bitmap_next_tuple(scan, slot))
 			{
 				/* nothing more to look at on this page */
 				node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5f8474871d2..4d495216f07 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -810,15 +810,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -1980,7 +1975,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -1992,7 +1986,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.37.2

v1-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-patch; charset=US-ASCII; name=v1-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchDownload
From d56be7741765d93002649ef912ef4b8256a5b9af Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v1 05/11] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index ab97f308a5f..9372b49bfaa 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -55,7 +55,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -226,7 +226,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			/*
 			 * We can skip fetching the heap page if we don't need any fields
@@ -379,7 +379,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -398,7 +398,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.37.2

v1-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-patch; charset=US-ASCII; name=v1-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchDownload
From a3f62e4299663d418531ae61bb16ea39f0836fac Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v1 04/11] BitmapPrefetch use prefetch block recheck for skip
 fetch

Previously BitmapPrefetch() used the recheck flag for the current block
to determine whether or not it could skip prefetching the proposed
prefetch block. It makes more sense for it to use the recheck flag from
the TBMIterateResult for the prefetch block instead.
---
 src/backend/executor/nodeBitmapHeapscan.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fd697d16c72..ab97f308a5f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -519,7 +519,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * but is true in many cases.
 				 */
 				skip_fetch = (node->can_skip_fetch &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -570,7 +570,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (node->can_skip_fetch &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.37.2

v1-0006-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-patch; charset=US-ASCII; name=v1-0006-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchDownload
From 202b16d3a381210e8dbee69e68a8310be8ee11d2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v1 06/11] Push BitmapHeapScan skip fetch optimization into
 table AM

This resolves the long-standing FIXME in BitmapHeapNext() which said that
the optmization to skip fetching blocks of the underlying table when
none of the column data was needed should be pushed into the table AM
specific code.

heapam_scan_bitmap_next_block() now does the visibility check and
accounting of empty tuples to be returned; while
heapam_scan_bitmap_next_tuple() prepares the slot to return empty
tuples.

The table AM agnostic functions for prefetching still need to know if
skipping fetching is permitted for this scan. However, this dependency
will be removed when that prefetching code is removed in favor of the
upcoming streaming read API.
---
 src/backend/access/heap/heapam.c          |  10 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++++
 src/backend/executor/nodeBitmapHeapscan.c | 100 ++++++----------------
 src/include/access/heapam.h               |   2 +
 src/include/access/tableam.h              |  17 ++--
 src/include/nodes/execnodes.h             |   6 --
 6 files changed, 74 insertions(+), 90 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 707460a5364..7aae1ecf0a9 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -955,6 +955,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->vmbuffer = InvalidBuffer;
+	scan->empty_tuples = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1043,6 +1045,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+	scan->vmbuffer = InvalidBuffer;
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1062,6 +1068,10 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+	scan->vmbuffer = InvalidBuffer;
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 716d477e271..baba09c87c0 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2124,6 +2125,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, and the bitmap entries don't need rechecking, and all tuples on
+	 * the page are visible to our transaction.
+	 */
+	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->empty_tuples >= 0);
+
+		hscan->empty_tuples += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2235,6 +2254,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->empty_tuples > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->empty_tuples--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 9372b49bfaa..c0fb06c9688 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,6 +108,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		bool can_skip_fetch;
 		/*
 		 * We can potentially skip fetching heap pages if we do not need any
 		 * columns of the table, either for checking non-indexable quals or
@@ -115,7 +116,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * the stronger condition that there's no qual or return tlist at all.
 		 * But in most cases it's probably not worth working harder than that.
 		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+		can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
 								node->ss.ps.plan->targetlist == NIL);
 
 		if (!pstate)
@@ -199,7 +200,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	node->ss.ps.state->es_snapshot,
 																	node->worker_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	can_skip_fetch);
 		}
 
 		node->initialized = true;
@@ -207,8 +209,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -228,32 +228,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -307,46 +282,30 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +477,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +529,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +599,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +608,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +652,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -739,8 +694,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +705,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 	scanstate->worker_snapshot = NULL;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f68593..2fc369a18ff 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -73,6 +73,8 @@ typedef struct HeapScanDescData
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	Buffer		vmbuffer;		/* for checking if can skip fetch */
+	int			empty_tuples;	/* count of all NULL tuples to be returned */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
 	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 77f32a7472d..05e700c5055 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,7 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+	SO_CAN_SKIP_FETCH = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -780,10 +781,8 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time). All work
+	 * referencing `tbmres` must be done here.
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -795,11 +794,6 @@ typedef struct TableAmRoutine
 	 * performs prefetching directly using that interface.  This probably
 	 * needs to be rectified at a later point.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -944,11 +938,14 @@ extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot, Snapshot worker_snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, bool can_skip_fetch)
 {
 	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
+	if (can_skip_fetch)
+		flags |= SO_CAN_SKIP_FETCH;
+
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	if (worker_snapshot)
 		table_scan_update_snapshot(result, worker_snapshot);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 00c75fb10e2..9392923eb32 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1711,9 +1711,6 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
  *		pvmbuffer		   ditto, for prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1736,9 +1733,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.37.2

v1-0008-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-patch; charset=US-ASCII; name=v1-0008-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchDownload
From ccd5d688fd5c1dd16908788e0a0abd0f3e64eb77 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v1 08/11] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 19d115de06f..4d55390715c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -76,8 +76,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -90,10 +88,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -111,6 +105,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	if (!node->initialized)
 	{
 		bool can_skip_fetch;
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
 		/*
 		 * We can potentially skip fetching heap pages if we do not need any
 		 * columns of the table, either for checking non-indexable quals or
@@ -129,7 +125,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -182,8 +178,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +201,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	can_skip_fetch);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -219,9 +216,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.37.2

v1-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-patch; charset=US-ASCII; name=v1-0009-Make-table_scan_bitmap_next_block-async-friendly.patchDownload
From 555743e4bc885609d20768f7f2990c6ba69b13a9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:57:07 -0500
Subject: [PATCH v1 09/11] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the known end of the table.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table and for
table_scan_bitmap_next_tuple() to return false if there are no visible
tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API. The table AMs will implement a streaming read API callback
that returns the next block that needs to be fetched. In heap AM's case,
the callback will use the iterator to find the next block to be fetched.
Since choosing the next block will no longer the responsibility of
BitmapHeapNext(), the streaming read control flow requires these changes
to table_scan_bitmap_next_block().
---
 src/backend/access/heap/heapam.c          |  22 ++++
 src/backend/access/heap/heapam_handler.c  |  56 ++++++---
 src/backend/executor/nodeBitmapHeapscan.c | 132 ++++++++--------------
 src/include/access/relscan.h              |   3 +
 src/include/access/tableam.h              |  14 +--
 src/include/nodes/execnodes.h             |  10 +-
 6 files changed, 121 insertions(+), 116 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 88b4aad5820..d8569373987 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -959,6 +959,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->empty_tuples = 0;
 	scan->rs_base.lossy_pages = 0;
 	scan->rs_base.exact_pages = 0;
+	scan->rs_base.shared_tbmiterator = NULL;
+	scan->rs_base.tbmiterator = NULL;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1051,6 +1053,18 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		ReleaseBuffer(scan->vmbuffer);
 	scan->vmbuffer = InvalidBuffer;
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_base.shared_tbmiterator)
+			tbm_end_shared_iterate(scan->rs_base.shared_tbmiterator);
+
+		if (scan->rs_base.tbmiterator)
+			tbm_end_iterate(scan->rs_base.tbmiterator);
+	}
+
+	scan->rs_base.shared_tbmiterator = NULL;
+	scan->rs_base.tbmiterator = NULL;
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1074,6 +1088,14 @@ heap_endscan(TableScanDesc sscan)
 		ReleaseBuffer(scan->vmbuffer);
 	scan->vmbuffer = InvalidBuffer;
 
+	if (sscan->shared_tbmiterator)
+		tbm_end_shared_iterate(sscan->shared_tbmiterator);
+	sscan->shared_tbmiterator = NULL;
+
+	if (sscan->tbmiterator)
+		tbm_end_iterate(sscan->tbmiterator);
+	sscan->tbmiterator = NULL;
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6e85ef7a946..d55ece23a35 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,17 +2114,49 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  bool *recheck, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->empty_tuples == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, and the bitmap entries don't need rechecking, and all tuples on
@@ -2143,16 +2175,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2251,7 +2274,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 			scan->lossy_pages++;
 	}
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 4d55390715c..efc6952e353 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -76,7 +76,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -88,7 +87,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -126,7 +124,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -179,7 +176,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -201,46 +197,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	can_skip_fetch);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		/* Get the first block. if none, end of scan */
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+			goto exit;
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -262,53 +235,46 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
-		 */
-		BitmapPrefetch(node, scan);
-
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
-		}
+			/*
+			 * We prefetch before fetching the current pages. We expect that a
+			 * future streaming read API will do this, so do it now for
+			 * consistency.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
-		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
 			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
 			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
-		/* OK to return this tuple */
-		return slot;
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+			break;
+
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
+exit:
 	BitmapAccumCounters(node, scan);
 	return ExecClearTuple(slot);
 }
@@ -594,12 +560,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -607,13 +569,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -647,14 +608,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
@@ -697,8 +654,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -707,10 +662,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b74e08dd745..bf7ee044268 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/itup.h"
+#include "nodes/tidbitmap.h"
 #include "port/atomics.h"
 #include "storage/buf.h"
 #include "storage/spin.h"
@@ -41,6 +42,8 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
+	TBMIterator *tbmiterator;
+	TBMSharedIterator *shared_tbmiterator;
 	long		exact_pages;
 	long		lossy_pages;
 
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 05e700c5055..b90d9b7f3fa 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -798,7 +798,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   bool *recheck, BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1942,17 +1942,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 bool *recheck, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1962,8 +1961,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 9392923eb32..03973a3f262 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1709,9 +1709,7 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1720,7 +1718,6 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
@@ -1731,8 +1728,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1742,10 +1737,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
+	bool		recheck;
+	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v1-0007-BitmapHeapScan-scan-desc-counts-lossy-and-exact-p.patchtext/x-patch; charset=US-ASCII; name=v1-0007-BitmapHeapScan-scan-desc-counts-lossy-and-exact-p.patchDownload
From 500c84019b982a1e6c8b8dd40240c8510d83c287 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:05:04 -0500
Subject: [PATCH v1 07/11] BitmapHeapScan scan desc counts lossy and exact
 pages

Future commits will remove the TBMIterateResult from BitmapHeapNext(),
pushing it into the table AM-specific code. So we will have to keep
track of the number of lossy and exact pages in the scan descriptor.
Doing this change to lossy/exact page counting in a separate commit just
simplifies the diff.
---
 src/backend/access/heap/heapam.c          |  2 ++
 src/backend/access/heap/heapam_handler.c  |  9 +++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 18 +++++++++++++-----
 src/include/access/relscan.h              |  4 ++++
 4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 7aae1ecf0a9..88b4aad5820 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -957,6 +957,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_strategy = NULL;	/* set in initscan */
 	scan->vmbuffer = InvalidBuffer;
 	scan->empty_tuples = 0;
+	scan->rs_base.lossy_pages = 0;
+	scan->rs_base.exact_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index baba09c87c0..6e85ef7a946 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2242,6 +2242,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	/* Only count exact and lossy pages with visible tuples */
+	if (ntup > 0)
+	{
+		if (tbmres->ntuples >= 0)
+			scan->exact_pages++;
+		else
+			scan->lossy_pages++;
+	}
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c0fb06c9688..19d115de06f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,6 +53,8 @@
 #include "utils/spccache.h"
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
+static inline void BitmapAccumCounters(BitmapHeapScanState *node,
+									   TableScanDesc scan);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 												BlockNumber blockno);
@@ -234,11 +236,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				continue;
 			}
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
 			/* Adjust the prefetch target */
 			BitmapAdjustPrefetchTarget(node);
 		}
@@ -315,9 +312,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
+	BitmapAccumCounters(node, scan);
 	return ExecClearTuple(slot);
 }
 
+static inline void
+BitmapAccumCounters(BitmapHeapScanState *node,
+					TableScanDesc scan)
+{
+	node->exact_pages += scan->exact_pages;
+	scan->exact_pages = 0;
+	node->lossy_pages += scan->lossy_pages;
+	scan->lossy_pages = 0;
+}
+
 /*
  *	BitmapDoneInitializingSharedState - Shared state is initialized
  *
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..b74e08dd745 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -40,6 +40,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	long		exact_pages;
+	long		lossy_pages;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
-- 
2.37.2

v1-0010-Streaming-Read-API.patchtext/x-patch; charset=US-ASCII; name=v1-0010-Streaming-Read-API.patchDownload
From 9eb510c1f2fd4d1b3c831f62af1e4c0f422a0922 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 22 Jul 2023 17:31:54 +1200
Subject: [PATCH v1 10/11] Streaming Read API

---
 contrib/pg_prewarm/pg_prewarm.c          |  40 +-
 src/backend/access/transam/xlogutils.c   |   2 +-
 src/backend/postmaster/bgwriter.c        |   8 +-
 src/backend/postmaster/checkpointer.c    |  15 +-
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 435 ++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 560 +++++++++++++++--------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/backend/storage/smgr/smgr.c          |  49 +-
 src/include/storage/bufmgr.h             |  22 +
 src/include/storage/smgr.h               |   4 +-
 src/include/storage/streaming_read.h     |  45 ++
 src/include/utils/rel.h                  |   6 -
 src/tools/pgindent/typedefs.list         |   2 +
 17 files changed, 986 insertions(+), 238 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/contrib/pg_prewarm/pg_prewarm.c b/contrib/pg_prewarm/pg_prewarm.c
index 8541e4d6e46..9617bf130bd 100644
--- a/contrib/pg_prewarm/pg_prewarm.c
+++ b/contrib/pg_prewarm/pg_prewarm.c
@@ -20,6 +20,7 @@
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
 #include "storage/smgr.h"
+#include "storage/streaming_read.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -38,6 +39,25 @@ typedef enum
 
 static PGIOAlignedBlock blockbuffer;
 
+struct pg_prewarm_streaming_read_private
+{
+	BlockNumber blocknum;
+	int64		last_block;
+};
+
+static BlockNumber
+pg_prewarm_streaming_read_next(PgStreamingRead *pgsr,
+							   void *pgsr_private,
+							   void *per_buffer_data)
+{
+	struct pg_prewarm_streaming_read_private *p = pgsr_private;
+
+	if (p->blocknum <= p->last_block)
+		return p->blocknum++;
+
+	return InvalidBlockNumber;
+}
+
 /*
  * pg_prewarm(regclass, mode text, fork text,
  *			  first_block int8, last_block int8)
@@ -183,18 +203,36 @@ pg_prewarm(PG_FUNCTION_ARGS)
 	}
 	else if (ptype == PREWARM_BUFFER)
 	{
+		struct pg_prewarm_streaming_read_private p;
+		PgStreamingRead *pgsr;
+
 		/*
 		 * In buffer mode, we actually pull the data into shared_buffers.
 		 */
+
+		/* Set up the private state for our streaming buffer read callback. */
+		p.blocknum = first_block;
+		p.last_block = last_block;
+
+		pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+											  &p,
+											  0,
+											  NULL,
+											  BMR_REL(rel),
+											  forkNumber,
+											  pg_prewarm_streaming_read_next);
+
 		for (block = first_block; block <= last_block; ++block)
 		{
 			Buffer		buf;
 
 			CHECK_FOR_INTERRUPTS();
-			buf = ReadBufferExtended(rel, forkNumber, block, RBM_NORMAL, NULL);
+			buf = pg_streaming_read_buffer_get_next(pgsr, NULL);
 			ReleaseBuffer(buf);
 			++blocks_done;
 		}
+		Assert(pg_streaming_read_buffer_get_next(pgsr, NULL) == InvalidBuffer);
+		pg_streaming_read_free(pgsr);
 	}
 
 	/* Close relation, release lock. */
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index aa8667abd10..8775b5789be 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -657,7 +657,7 @@ XLogDropDatabase(Oid dbid)
 	 * This is unnecessarily heavy-handed, as it will close SMgrRelation
 	 * objects for other databases as well. DROP DATABASE occurs seldom enough
 	 * that it's not worth introducing a variant of smgrclose for just this
-	 * purpose. XXX: Or should we rather leave the smgr entries dangling?
+	 * purpose.
 	 */
 	smgrcloseall();
 
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index d7d6cc0cd7b..13e5376619e 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -246,10 +246,12 @@ BackgroundWriterMain(void)
 		if (FirstCallSinceLastCheckpoint())
 		{
 			/*
-			 * After any checkpoint, close all smgr files.  This is so we
-			 * won't hang onto smgr references to deleted files indefinitely.
+			 * After any checkpoint, free all smgr objects.  Otherwise we
+			 * would never do so for dropped relations, as the bgwriter does
+			 * not process shared invalidation messages or call
+			 * AtEOXact_SMgr().
 			 */
-			smgrcloseall();
+			smgrdestroyall();
 		}
 
 		/*
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 5e949fc885b..5d843b61426 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -469,10 +469,12 @@ CheckpointerMain(void)
 				ckpt_performed = CreateRestartPoint(flags);
 
 			/*
-			 * After any checkpoint, close all smgr files.  This is so we
-			 * won't hang onto smgr references to deleted files indefinitely.
+			 * After any checkpoint, free all smgr objects.  Otherwise we
+			 * would never do so for dropped relations, as the checkpointer
+			 * does not process shared invalidation messages or call
+			 * AtEOXact_SMgr().
 			 */
-			smgrcloseall();
+			smgrdestroyall();
 
 			/*
 			 * Indicate checkpoint completion to any waiting backends.
@@ -958,11 +960,8 @@ RequestCheckpoint(int flags)
 		 */
 		CreateCheckPoint(flags | CHECKPOINT_IMMEDIATE);
 
-		/*
-		 * After any checkpoint, close all smgr files.  This is so we won't
-		 * hang onto smgr references to deleted files indefinitely.
-		 */
-		smgrcloseall();
+		/* Free all smgr objects, as CheckpointerMain() normally would. */
+		smgrdestroyall();
 
 		return;
 	}
diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca20..eec03f6f2b4 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 00000000000..bcab44c802f
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 00000000000..39aef2a84a2
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 00000000000..19605090fea
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,435 @@
+#include "postgres.h"
+
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ *
+ * For hits, need_to_complete is false and there is just one block per
+ * range, already pinned and ready for use.
+ *
+ * For misses, need_to_complete is true and buffers[] holds a range of
+ * blocks that are contiguous in storage (though the buffers may not be
+ * contiguous in memory), so we can complete them with a single call to
+ * CompleteReadBuffers().
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		advice_issued;
+	bool		need_complete;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index[MAX_BUFFERS_PER_TRANSFER];
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+} PgStreamingReadRange;
+
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			ios_in_progress_trigger;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			pinned_buffers_trigger;
+	int			next_tail_buffer;
+	bool		finished;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	bool		advice_enabled;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+	int			per_buffer_data_next;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+static PgStreamingRead *
+pg_streaming_read_buffer_alloc_internal(int flags,
+										void *pgsr_private,
+										size_t per_buffer_data_size,
+										BufferAccessStrategy strategy)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = maintenance_io_concurrency;
+	else
+		max_ios = effective_io_concurrency;
+
+	/*
+	 * The desired level of I/O concurrency controls how far ahead we are
+	 * willing to look ahead.  We also clamp it to at least
+	 * MAX_BUFFER_PER_TRANFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/*
+	 * The *_io_concurrency GUCs, we might have 0.  We want to allow at least
+	 * one, to keep our gating logic simple.
+	 */
+	max_ios = Max(max_ios, 1);
+
+	/*
+	 * Don't allow this backend to pin too many buffers.  For now we'll apply
+	 * the limit for the shared buffer pool and the local buffer pool, without
+	 * worrying which it is.
+	 */
+	LimitAdditionalPins(&max_pinned_buffers);
+	LimitAdditionalLocalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * We want to avoid creating ranges that are smaller than they could be
+	 * just because we hit max_pinned_buffers.  We only look ahead when the
+	 * number of pinned buffers falls below this trigger number, or put
+	 * another way, we stop looking ahead when we wouldn't be able to build a
+	 * "full sized" range.
+	 */
+	pgsr->pinned_buffers_trigger =
+		Max(1, (int) max_pinned_buffers - MAX_BUFFERS_PER_TRANSFER);
+
+	/* Space the callback to store extra data along with each block. */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * max_pinned_buffers);
+
+	return pgsr;
+}
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *result;
+
+	result = pg_streaming_read_buffer_alloc_internal(flags,
+													 pgsr_private,
+													 per_buffer_data_size,
+													 strategy);
+	result->callback = next_block_cb;
+	result->bmr = bmr;
+	result->forknum = forknum;
+
+	return result;
+}
+
+/*
+ * Start building a new range.  This is called after the previous one
+ * reached maximum size, or the callback's next block can't be merged with it.
+ *
+ * Since the previous head range has now reached its full potential size, this
+ * is also a good time to issue 'prefetch' advice, because we know that'll
+ * soon be reading.  In future, we could start an actual I/O here.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_new_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If a call to CompleteReadBuffers() will be needed, and we can issue
+	 * advice to the kernel to get the read started.  We suppress it if the
+	 * access pattern appears to be completely sequential, though, because on
+	 * some systems that interfers with the kernel's own sequential read ahead
+	 * heurstics and hurts performance.
+	 */
+	if (pgsr->advice_enabled)
+	{
+		BlockNumber blocknum = head_range->blocknum;
+		int			nblocks = head_range->nblocks;
+
+		if (head_range->need_complete && blocknum != pgsr->seq_blocknum)
+		{
+			SMgrRelation smgr =
+				pgsr->bmr.smgr ? pgsr->bmr.smgr :
+				RelationGetSmgr(pgsr->bmr.rel);
+
+			Assert(!head_range->advice_issued);
+
+			smgrprefetch(smgr, pgsr->forknum, blocknum, nblocks);
+
+			/*
+			 * Count this as an I/O that is concurrently in progress, though
+			 * we don't really know if the kernel generates a physical I/O.
+			 */
+			head_range->advice_issued = true;
+			pgsr->ios_in_progress++;
+		}
+
+		/* Remember the block after this range, for sequence detection. */
+		pgsr->seq_blocknum = blocknum + nblocks;
+	}
+
+	/* Create a new head range.  There must be space. */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	head_range = &pgsr->ranges[pgsr->head];
+	head_range->nblocks = 0;
+
+	return head_range;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	/*
+	 * If we're finished or can't start more I/O, then don't look ahead.
+	 */
+	if (pgsr->finished || pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/*
+	 * We'll also wait until the number of pinned buffers falls below our
+	 * trigger level, so that we have the chance to create a full range.
+	 */
+	if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger)
+		return;
+
+	do
+	{
+		BufferManagerRelation bmr;
+		ForkNumber	forknum;
+		BlockNumber blocknum;
+		Buffer		buffer;
+		bool		found;
+		bool		need_complete;
+		PgStreamingReadRange *head_range;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		head_range = &pgsr->ranges[pgsr->head];
+		if (head_range->nblocks == lengthof(head_range->buffers))
+		{
+			Assert(head_range->need_complete);
+			head_range = pg_streaming_read_new_range(pgsr);
+
+			/*
+			 * Give up now if I/O is saturated, or we wouldn't be able form
+			 * another full range after this due to the pin limit.
+			 */
+			if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger ||
+				pgsr->ios_in_progress == pgsr->max_ios)
+				break;
+		}
+
+		per_buffer_data = (char *) pgsr->per_buffer_data +
+			pgsr->per_buffer_data_size * pgsr->per_buffer_data_next;
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			pgsr->finished = true;
+			break;
+		}
+		bmr = pgsr->bmr;
+		forknum = pgsr->forknum;
+
+		Assert(pgsr->pinned_buffers < pgsr->max_pinned_buffers);
+
+		buffer = PrepareReadBuffer(bmr,
+								   forknum,
+								   blocknum,
+								   pgsr->strategy,
+								   &found);
+		pgsr->pinned_buffers++;
+
+		need_complete = !found;
+
+		/* Is there a head range that we can't extend? */
+		head_range = &pgsr->ranges[pgsr->head];
+		if (head_range->nblocks > 0 &&
+			(!need_complete ||
+			 !head_range->need_complete ||
+			 head_range->blocknum + head_range->nblocks != blocknum))
+		{
+			/* Yes, time to start building a new one. */
+			head_range = pg_streaming_read_new_range(pgsr);
+			Assert(head_range->nblocks == 0);
+		}
+
+		if (head_range->nblocks == 0)
+		{
+			/* Initialize a new range beginning at this block. */
+			head_range->blocknum = blocknum;
+			head_range->need_complete = need_complete;
+			head_range->advice_issued = false;
+		}
+		else
+		{
+			/* We can extend an existing range by one block. */
+			Assert(head_range->blocknum + head_range->nblocks == blocknum);
+			Assert(head_range->need_complete);
+		}
+
+		head_range->per_buffer_data_index[head_range->nblocks] = pgsr->per_buffer_data_next++;
+		head_range->buffers[head_range->nblocks] = buffer;
+		head_range->nblocks++;
+
+		if (pgsr->per_buffer_data_next == pgsr->max_pinned_buffers)
+			pgsr->per_buffer_data_next = 0;
+
+	} while (pgsr->pinned_buffers < pgsr->max_pinned_buffers &&
+			 pgsr->ios_in_progress < pgsr->max_ios);
+
+	if (pgsr->ranges[pgsr->head].nblocks > 0)
+		pg_streaming_read_new_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	pg_streaming_read_look_ahead(pgsr);
+
+	/* See if we have one buffer to return. */
+	while (pgsr->tail != pgsr->head)
+	{
+		PgStreamingReadRange *tail_range;
+
+		tail_range = &pgsr->ranges[pgsr->tail];
+
+		/*
+		 * Do we need to perform an I/O before returning the buffers from this
+		 * range?
+		 */
+		if (tail_range->need_complete)
+		{
+			CompleteReadBuffers(pgsr->bmr,
+								tail_range->buffers,
+								pgsr->forknum,
+								tail_range->blocknum,
+								tail_range->nblocks,
+								false,
+								pgsr->strategy);
+			tail_range->need_complete = false;
+
+			/*
+			 * We don't really know if the kernel generated an physical I/O
+			 * when we issued advice, let alone when it finished, but it has
+			 * certainly finished after a read call returns.
+			 */
+			if (tail_range->advice_issued)
+				pgsr->ios_in_progress--;
+		}
+
+		/* Are there more buffers available in this range? */
+		if (pgsr->next_tail_buffer < tail_range->nblocks)
+		{
+			int			buffer_index;
+			Buffer		buffer;
+
+			buffer_index = pgsr->next_tail_buffer++;
+			buffer = tail_range->buffers[buffer_index];
+
+			Assert(BufferIsValid(buffer));
+
+			/* We are giving away ownership of this pinned buffer. */
+			Assert(pgsr->pinned_buffers > 0);
+			pgsr->pinned_buffers--;
+
+			if (per_buffer_data)
+				*per_buffer_data = (char *) pgsr->per_buffer_data +
+					tail_range->per_buffer_data_index[buffer_index] *
+					pgsr->per_buffer_data_size;
+
+			return buffer;
+		}
+
+		/* Advance tail to next range, if there is one. */
+		if (++pgsr->tail == pgsr->size)
+			pgsr->tail = 0;
+		pgsr->next_tail_buffer = 0;
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead, and unpin anything that wasn't consumed. */
+	pgsr->finished = true;
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7d601bef6dd..2157a97b973 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -472,7 +472,7 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
 								ReadBufferMode mode, BufferAccessStrategy strategy,
 								bool *hit);
@@ -501,7 +501,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -795,15 +795,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
+	buf = ReadBuffer_common(BMR_REL(reln),
 							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+
 	return buf;
 }
 
@@ -827,8 +821,9 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 
 	SMgrRelation smgr = smgropen(rlocator, InvalidBackendId);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
 							 mode, strategy, &hit);
 }
 
@@ -1002,7 +997,7 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 		bool		hit;
 
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
+		buffer = ReadBuffer_common(bmr,
 								   fork, extend_to - 1, mode, strategy,
 								   &hit);
 	}
@@ -1016,18 +1011,11 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
 				  BufferAccessStrategy strategy, bool *hit)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	Buffer		buffer;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1046,175 +1034,339 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		*hit = false;
+
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	buffer = PrepareReadBuffer(bmr,
+							   forkNum,
+							   blockNum,
+							   strategy,
+							   hit);
+
+	/* At this point we do NOT hold any locks. */
 
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+	{
+		/* if we just want zeroes and a lock, we're done */
+		ZeroBuffer(buffer, mode);
+	}
+	else if (!*hit)
+	{
+		/* we might need to perform I/O */
+		CompleteReadBuffers(bmr,
+							&buffer,
+							forkNum,
+							blockNum,
+							1,
+							mode == RBM_ZERO_ON_ERROR,
+							strategy);
+	}
+
+	return buffer;
+}
+
+/*
+ * Prepare to read a block.  The buffer is pinned.  If this is a 'hit', then
+ * the returned buffer can be used immediately.  Otherwise, a physical read
+ * should be completed with CompleteReadBuffers(), or the buffer should be
+ * zeroed with ZeroBuffer().  PrepareReadBuffer() followed by
+ * CompleteReadBuffers() or ZeroBuffer() is equivalent to ReadBuffer(), but
+ * the caller has the opportunity to combine reads of multiple neighboring
+ * blocks into one CompleteReadBuffers() call.
+ *
+ * *foundPtr is set to true for a hit, and false for a miss.
+ */
+Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * CompleteReadBuffers() (so, not for hits, and not for buffers that
+		 * are zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+static inline bool
+CompleteReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
+	{
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+/*
+ * Complete a set reads prepared with PrepareReadBuffers().  The buffers must
+ * cover a cluster of neighboring block numbers.
+ *
+ * Typically this performs one physical vector read covering the block range,
+ * but if some of the buffers have already been read in the meantime by any
+ * backend, zero or multiple reads may be performed.
+ */
+void
+CompleteReadBuffers(BufferManagerRelation bmr,
+					Buffer *buffers,
+					ForkNumber forknum,
+					BlockNumber blocknum,
+					int nblocks,
+					bool zero_on_error,
+					BufferAccessStrategy strategy)
+{
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
+	if (isLocalBuf)
+	{
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
+	}
+	else
+	{
+		io_context = IOContextForStrategy(strategy);
+		io_object = IOOBJECT_RELATION;
+	}
 
 	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
 	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
 	else
+		pgBufferUsage.shared_blks_read += nblocks;
+
+	for (int i = 0; i < nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+#ifdef USE_ASSERT_CHECKING
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		/*
+		 * We could get all the information from buffer headers, but it can be
+		 * expensive to access buffer header cache lines so we make the caller
+		 * provide all the information we need, and assert that it is
+		 * consistent.
+		 */
+		{
+			RelFileLocator xlocator;
+			ForkNumber	xforknum;
+			BlockNumber xblocknum;
+
+			BufferGetTag(buffers[i], &xlocator, &xforknum, &xblocknum);
+			Assert(RelFileLocatorEquals(bmr.smgr->smgr_rlocator.locator, xlocator));
+			Assert(xforknum == forknum);
+			Assert(xblocknum == blocknum + i);
+		}
+#endif
+
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!CompleteReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   CompleteReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
 			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
 			}
 			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-		}
-	}
-
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
-	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
-	}
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
 
-	if (isLocalBuf)
-	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if (zero_on_error || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
 
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
-	}
-	else
-	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
-	}
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
@@ -1228,11 +1380,8 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.  A read should be
+ * performed with CompleteReadBuffers().
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1291,19 +1440,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called PrepareReadBuffer() but not yet CompleteReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1368,19 +1508,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called PrepareReadBuffer() but not yet CompleteReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1412,15 +1543,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1774,7 +1899,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2043,7 +2168,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2066,7 +2191,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2381,7 +2506,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if PrepareReadBuffer() was called and
+		 * CompleteReadBuffers() hasn't been called yet.  We'll check by
+		 * loading the flags without locking.  This is racy, but it's OK to
+		 * return false spuriously: when CompleteReadBuffers() calls
+		 * StartBufferIO(), it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2390,7 +2520,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3458,7 +3588,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -4845,6 +4975,46 @@ ConditionalLockBuffer(Buffer buffer)
 									LW_EXCLUSIVE);
 }
 
+/*
+ * Zero a buffer, and lock it as RBM_ZERO_AND_LOCK or
+ * RBM_ZERO_AND_CLEANUP_LOCK would.  The buffer must be already pinned.  It
+ * does not have to be valid, but it is valid and locked on return.
+ */
+void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * Verify that this backend is pinning the buffer exactly once.
  *
@@ -5197,9 +5367,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5212,6 +5388,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 1be4f4f8daf..717b8f58daf 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -109,10 +109,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -288,7 +287,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -298,9 +297,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca27..739d13293fb 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 563a0be5c74..0d7272e796e 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -147,7 +147,9 @@ smgrshutdown(int code, Datum arg)
 /*
  * smgropen() -- Return an SMgrRelation object, creating it if need be.
  *
- * This does not attempt to actually open the underlying file.
+ * This does not attempt to actually open the underlying files.  The returned
+ * object remains valid at least until AtEOXact_SMgr() is called, or until
+ * smgrdestroy() is called in non-transaction backends.
  */
 SMgrRelation
 smgropen(RelFileLocator rlocator, BackendId backend)
@@ -259,10 +261,10 @@ smgrexists(SMgrRelation reln, ForkNumber forknum)
 }
 
 /*
- * smgrclose() -- Close and delete an SMgrRelation object.
+ * smgrdestroy() -- Delete an SMgrRelation object.
  */
 void
-smgrclose(SMgrRelation reln)
+smgrdestroy(SMgrRelation reln)
 {
 	SMgrRelation *owner;
 	ForkNumber	forknum;
@@ -289,12 +291,14 @@ smgrclose(SMgrRelation reln)
 }
 
 /*
- * smgrrelease() -- Release all resources used by this object.
+ * smgrclose() -- Release all resources used by this object.
  *
- * The object remains valid.
+ * The object remains valid, but is moved to the unknown list where it will
+ * be destroyed by AtEOXact_SMgr().  It may be re-owned if it is accessed by a
+ * relation before then.
  */
 void
-smgrrelease(SMgrRelation reln)
+smgrclose(SMgrRelation reln)
 {
 	for (ForkNumber forknum = 0; forknum <= MAX_FORKNUM; forknum++)
 	{
@@ -302,15 +306,20 @@ smgrrelease(SMgrRelation reln)
 		reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber;
 	}
 	reln->smgr_targblock = InvalidBlockNumber;
+
+	if (reln->smgr_owner)
+	{
+		*reln->smgr_owner = NULL;
+		reln->smgr_owner = NULL;
+		dlist_push_tail(&unowned_relns, &reln->node);
+	}
 }
 
 /*
- * smgrreleaseall() -- Release resources used by all objects.
- *
- * This is called for PROCSIGNAL_BARRIER_SMGRRELEASE.
+ * smgrcloseall() -- Close all objects.
  */
 void
-smgrreleaseall(void)
+smgrcloseall(void)
 {
 	HASH_SEQ_STATUS status;
 	SMgrRelation reln;
@@ -322,14 +331,17 @@ smgrreleaseall(void)
 	hash_seq_init(&status, SMgrRelationHash);
 
 	while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
-		smgrrelease(reln);
+		smgrclose(reln);
 }
 
 /*
- * smgrcloseall() -- Close all existing SMgrRelation objects.
+ * smgrdestroyall() -- Destroy all SMgrRelation objects.
+ *
+ * It must be known that there are no pointers to SMgrRelations, other than
+ * those registered with smgrsetowner().
  */
 void
-smgrcloseall(void)
+smgrdestroyall(void)
 {
 	HASH_SEQ_STATUS status;
 	SMgrRelation reln;
@@ -341,7 +353,7 @@ smgrcloseall(void)
 	hash_seq_init(&status, SMgrRelationHash);
 
 	while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
-		smgrclose(reln);
+		smgrdestroy(reln);
 }
 
 /*
@@ -733,7 +745,8 @@ smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
  * AtEOXact_SMgr
  *
  * This routine is called during transaction commit or abort (it doesn't
- * particularly care which).  All transient SMgrRelation objects are closed.
+ * particularly care which).  All transient SMgrRelation objects are
+ * destroyed.
  *
  * We do this as a compromise between wanting transient SMgrRelations to
  * live awhile (to amortize the costs of blind writes of multiple blocks)
@@ -747,7 +760,7 @@ AtEOXact_SMgr(void)
 	dlist_mutable_iter iter;
 
 	/*
-	 * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
+	 * Zap all unowned SMgrRelations.  We rely on smgrdestroy() to remove each
 	 * one from the list.
 	 */
 	dlist_foreach_modify(iter, &unowned_relns)
@@ -757,7 +770,7 @@ AtEOXact_SMgr(void)
 
 		Assert(rel->smgr_owner == NULL);
 
-		smgrclose(rel);
+		smgrdestroy(rel);
 	}
 }
 
@@ -768,6 +781,6 @@ AtEOXact_SMgr(void)
 bool
 ProcessBarrierSmgrRelease(void)
 {
-	smgrreleaseall();
+	smgrcloseall();
 	return true;
 }
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d3353..a38f1acb37a 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,18 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+extern Buffer PrepareReadBuffer(BufferManagerRelation bmr,
+								ForkNumber forkNum,
+								BlockNumber blockNum,
+								BufferAccessStrategy strategy,
+								bool *foundPtr);
+extern void CompleteReadBuffers(BufferManagerRelation bmr,
+								Buffer *buffers,
+								ForkNumber forknum,
+								BlockNumber blocknum,
+								int nblocks,
+								bool zero_on_error,
+								BufferAccessStrategy strategy);
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -247,9 +265,13 @@ extern void LockBufferForCleanup(Buffer buffer);
 extern bool ConditionalLockBufferForCleanup(Buffer buffer);
 extern bool IsBufferCleanupOK(Buffer buffer);
 extern bool HoldingBufferPinThatDelaysRecovery(void);
+extern void ZeroBuffer(Buffer buffer, ReadBufferMode mode);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 527cd2a0568..d8ffe397faf 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -85,8 +85,8 @@ extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln);
 extern void smgrclose(SMgrRelation reln);
 extern void smgrcloseall(void);
 extern void smgrcloserellocator(RelFileLocatorBackend rlocator);
-extern void smgrrelease(SMgrRelation reln);
-extern void smgrreleaseall(void);
+extern void smgrdestroy(SMgrRelation reln);
+extern void smgrdestroyall(void);
 extern void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
 extern void smgrdosyncall(SMgrRelation *rels, int nrels);
 extern void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 00000000000..40c3408c541
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,45 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index a584b1ddff3..6636cc82c09 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -561,12 +561,6 @@ typedef struct ViewOptions
  *
  * Very little code is authorized to touch rel->rd_smgr directly.  Instead
  * use this function to fetch its value.
- *
- * Note: since a relcache flush can cause the file handle to be closed again,
- * it's unwise to hold onto the pointer returned by this function for any
- * long period.  Recommended practice is to just re-execute RelationGetSmgr
- * each time you need to access the SMgrRelation.  It's quite cheap in
- * comparison to whatever an smgr function is going to do.
  */
 static inline SMgrRelation
 RelationGetSmgr(Relation rel)
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 91433d439b7..8007f17320a 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2094,6 +2094,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
-- 
2.37.2

v1-0011-BitmapHeapScan-uses-streaming-read-API.patchtext/x-patch; charset=US-ASCII; name=v1-0011-BitmapHeapScan-uses-streaming-read-API.patchDownload
From aac60985d6bc70bfedf77a77ee3c512da87bfcb1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:27:57 -0500
Subject: [PATCH v1 11/11] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
---
 src/backend/access/gin/ginget.c           |  15 +-
 src/backend/access/gin/ginscan.c          |   7 +
 src/backend/access/heap/heapam.c          |  71 +++++
 src/backend/access/heap/heapam_handler.c  |  78 +++--
 src/backend/executor/nodeBitmapHeapscan.c | 328 +---------------------
 src/backend/nodes/tidbitmap.c             |  80 +++---
 src/include/access/heapam.h               |   2 +
 src/include/access/tableam.h              |  14 +-
 src/include/nodes/execnodes.h             |  19 --
 src/include/nodes/tidbitmap.h             |   8 +-
 10 files changed, 178 insertions(+), 444 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3ce28078a6f 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,10 @@ restartScanEntry:
 			if (entry->matchBitmap)
 			{
 				if (entry->matchIterator)
+				{
 					tbm_end_iterate(entry->matchIterator);
+					pfree(entry->matchResult);
+				}
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -386,6 +389,7 @@ restartScanEntry:
 		if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
 		{
 			entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+			entry->matchResult = palloc0(TBM_ITERATE_RESULT_SIZE);
 			entry->isFinished = false;
 		}
 	}
@@ -823,21 +827,24 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
+			while ((!BlockNumberIsValid(entry->matchResult->blockno)) ||
 				   (entry->matchResult->ntuples >= 0 &&
 					entry->offset >= entry->matchResult->ntuples) ||
 				   entry->matchResult->blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
 
-				if (entry->matchResult == NULL)
+				tbm_iterate(entry->matchIterator, entry->matchResult);
+				if (!BlockNumberIsValid(entry->matchResult->blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
+					pfree(entry->matchResult);
+					entry->matchResult = NULL;
 					entry->matchIterator = NULL;
 					entry->isFinished = true;
 					break;
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..be27f9fe07e 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -246,7 +246,14 @@ ginFreeScanKeys(GinScanOpaque so)
 		if (entry->list)
 			pfree(entry->list);
 		if (entry->matchIterator)
+		{
 			tbm_end_iterate(entry->matchIterator);
+			if (entry->matchResult)
+			{
+				pfree(entry->matchResult);
+				entry->matchResult = NULL;
+			}
+		}
 		if (entry->matchBitmap)
 			tbm_free(entry->matchBitmap);
 	}
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index d8569373987..86484c6c72a 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -115,6 +115,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next_single(PgStreamingRead *pgsr, void *pgsr_private,
+							void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -335,6 +337,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->pgsr)
+			pg_streaming_read_free(scan->pgsr);
+
+		scan->pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													scan,
+													TBM_ITERATE_RESULT_SIZE,
+													scan->rs_strategy,
+													BMR_REL(scan->rs_base.rs_rd),
+													MAIN_FORKNUM,
+													bitmapheap_pgsr_next_single);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -955,6 +973,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->pgsr = NULL;
 	scan->vmbuffer = InvalidBuffer;
 	scan->empty_tuples = 0;
 	scan->rs_base.lossy_pages = 0;
@@ -1113,6 +1132,13 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->pgsr)
+			pg_streaming_read_free(scan->pgsr);
+		scan->pgsr = NULL;
+	}
+
 	pfree(scan);
 }
 
@@ -10270,3 +10296,48 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next_single(PgStreamingRead *pgsr, void *pgsr_private,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		if (hdesc->rs_base.shared_tbmiterator)
+			tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+		else
+			tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+
+		if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->vmbuffer))
+		{
+			hdesc->empty_tuples += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d55ece23a35..0cd586cd4b8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2113,77 +2113,65 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno)
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
 
+	Assert(hscan->pgsr);
+
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->pgsr, &io_private);
 
-		if (tbmres == NULL)
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->empty_tuples == 0);
-			return false;
+			ReleaseBuffer(hscan->vmbuffer);
+			hscan->vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API will
+		 * only return TBMIterateResults for blocks actually fetched. When we
+		 * skip fetching a block, we keep track of how many empty tuples to
+		 * emit at the end of the BitmapHeapScan. We do not recheck all NULL
+		 * tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->empty_tuples > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, and the bitmap entries don't need rechecking, and all tuples on
-	 * the page are visible to our transaction.
-	 */
-	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->empty_tuples >= 0);
+	tbmres = (TBMIterateResult *) io_private;
 
-		hscan->empty_tuples += tbmres->ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres->blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index efc6952e353..8b7f87a4779 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -56,11 +56,6 @@ static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapAccumCounters(BitmapHeapScanState *node,
 									   TableScanDesc scan);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -124,15 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
 		}
 		else
 		{
@@ -155,20 +141,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
 
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
@@ -176,14 +148,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		if (!scan)
@@ -203,46 +167,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		node->initialized = true;
 
 		/* Get the first block. if none, end of scan */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck))
 			goto exit;
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		BitmapAdjustPrefetchTarget(node);
 	}
 
-	for (;;)
+	do
 	{
 		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We prefetch before fetching the current pages. We expect that a
-			 * future streaming read API will do this, so do it now for
-			 * consistency.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -263,13 +197,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			return slot;
 		}
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
-			break;
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
-	}
+	} while (table_scan_bitmap_next_block(scan, &node->recheck));
 
 	/*
 	 * if we get here it means we are at the end of the scan..
@@ -304,215 +232,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
-		}
-		return;
-	}
-
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
-				 */
-
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
@@ -559,22 +278,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -606,16 +315,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	ExecEndNode(outerPlanState(node));
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 
 	/*
 	 * close heap scan
@@ -654,19 +357,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -706,13 +403,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -796,14 +486,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -835,11 +521,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 0f4850065fb..ccb511fb608 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -180,7 +180,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
 };
 
 /*
@@ -221,7 +220,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
 };
 
 /* Local function prototypes */
@@ -695,8 +693,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 	 * Create the TBMIterator struct, with enough trailing space to serve the
 	 * needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMIterator *) palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -957,20 +954,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -998,6 +996,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -1008,11 +1007,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1028,18 +1027,20 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
+
 /*
  *	tbm_shared_iterate - scan through next page of a TIDBitmap
  *
@@ -1047,10 +1048,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1101,13 +1101,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1117,21 +1117,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1470,8 +1471,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2fc369a18ff..33e8a7e0bba 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -73,6 +74,7 @@ typedef struct HeapScanDescData
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	PgStreamingRead *pgsr;
 	Buffer		vmbuffer;		/* for checking if can skip fetch */
 	int			empty_tuples;	/* count of all NULL tuples to be returned */
 	int			rs_cindex;		/* current tuple's index in vistuples */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b90d9b7f3fa..adde320d1eb 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -788,17 +788,10 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, BlockNumber *blockno);
+	bool		(*scan_bitmap_next_block) (TableScanDesc scan, bool *recheck);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1950,8 +1943,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno)
+table_scan_bitmap_next_block(TableScanDesc scan, bool *recheck)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1961,7 +1953,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, blockno);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 03973a3f262..96afabc67e6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1682,11 +1682,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  *		phs_snapshot_data		snapshot data shared to workers
@@ -1695,10 +1692,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 	char		phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
@@ -1709,16 +1703,10 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
  * ----------------
@@ -1728,20 +1716,13 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
 	bool		recheck;
-	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..672608200ba 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -64,12 +64,16 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
 													dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+#define TBM_ITERATE_RESULT_SIZE \
+	(offsetof(TBMIterateResult, offsets) + \
+	 MaxHeapTuplesPerPage * sizeof(OffsetNumber))
+
 #endif							/* TIDBITMAP_H */
-- 
2.37.2

#2Mark Dilger
mark.dilger@enterprisedb.com
In reply to: Melanie Plageman (#1)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Feb 13, 2024, at 3:11 PM, Melanie Plageman <melanieplageman@gmail.com> wrote:

Thanks for the patch...

Attached is a patch set which refactors BitmapHeapScan such that it
can use the streaming read API [1]. It also resolves the long-standing
FIXME in the BitmapHeapScan code suggesting that the skip fetch
optimization should be pushed into the table AMs. Additionally, it
moves table scan initialization to after the index scan and bitmap
initialization.

patches 0001-0002 are assorted cleanup needed later in the set.
patches 0003 moves the table scan initialization to after bitmap creation
patch 0004 is, I think, a bug fix. see [2].
patches 0005-0006 push the skip fetch optimization into the table AMs
patches 0007-0009 change the control flow of BitmapHeapNext() to match
that required by the streaming read API
patch 0010 is the streaming read code not yet in master
patch 0011 is the actual bitmapheapscan streaming read user.

patches 0001-0009 apply on top of master but 0010 and 0011 must be
applied on top of a commit before a 21d9c3ee4ef74e2 (until a rebased
version of the streaming read API is on the mailing list).

I followed your lead and applied them to 6a8ffe812d194ba6f4f26791b6388a4837d17d6c. `make check` worked fine, though I expect you know that already.

The caveat is that these patches introduce breaking changes to two
table AM functions for bitmapheapscan: table_scan_bitmap_next_block()
and table_scan_bitmap_next_tuple().

You might want an independent perspective on how much of a hassle those breaking changes are, so I took a stab at that. Having written a custom proprietary TAM for postgresql 15 here at EDB, and having ported it and released it for postgresql 16, I thought I'd try porting it to the the above commit with your patches. Even without your patches, I already see breaking changes coming from commit f691f5b80a85c66d715b4340ffabb503eb19393e, which creates a similar amount of breakage for me as does your patches. Dealing with the combined breakage might amount to a day of work, including testing, half of which I think I've already finished. In other words, it doesn't seem like a big deal.

Were postgresql 17 shaping up to be compatible with TAMs written for 16, your patch would change that qualitatively, but since things are already incompatible, I think you're in the clear.

A TBMIterateResult used to be threaded through both of these functions
and used in BitmapHeapNext(). This patch set removes all references to
TBMIterateResults from BitmapHeapNext. Because the streaming read API
requires the callback to specify the next block, BitmapHeapNext() can
no longer pass a TBMIterateResult to table_scan_bitmap_next_block().

More subtly, table_scan_bitmap_next_block() used to return false if
there were no more visible tuples on the page or if the block that was
requested was not valid. With these changes,
table_scan_bitmap_next_block() will only return false when the bitmap
has been exhausted and the scan can end. In order to use the streaming
read API, the user must be able to request the blocks it needs without
requiring synchronous feedback per block. Thus, this table AM function
must change its meaning.

I think the way the patches are split up could be improved. I will
think more about this. There are also probably a few mistakes with
which comments are updated in which patches in the set.

I look forward to the next version of the patch set. Thanks again for working on this.


Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#3Melanie Plageman
melanieplageman@gmail.com
In reply to: Mark Dilger (#2)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, Feb 13, 2024 at 11:34 PM Mark Dilger
<mark.dilger@enterprisedb.com> wrote:

On Feb 13, 2024, at 3:11 PM, Melanie Plageman <melanieplageman@gmail.com> wrote:

Thanks for the patch...

Attached is a patch set which refactors BitmapHeapScan such that it
can use the streaming read API [1]. It also resolves the long-standing
FIXME in the BitmapHeapScan code suggesting that the skip fetch
optimization should be pushed into the table AMs. Additionally, it
moves table scan initialization to after the index scan and bitmap
initialization.

patches 0001-0002 are assorted cleanup needed later in the set.
patches 0003 moves the table scan initialization to after bitmap creation
patch 0004 is, I think, a bug fix. see [2].
patches 0005-0006 push the skip fetch optimization into the table AMs
patches 0007-0009 change the control flow of BitmapHeapNext() to match
that required by the streaming read API
patch 0010 is the streaming read code not yet in master
patch 0011 is the actual bitmapheapscan streaming read user.

patches 0001-0009 apply on top of master but 0010 and 0011 must be
applied on top of a commit before a 21d9c3ee4ef74e2 (until a rebased
version of the streaming read API is on the mailing list).

I followed your lead and applied them to 6a8ffe812d194ba6f4f26791b6388a4837d17d6c. `make check` worked fine, though I expect you know that already.

Thanks for taking a look!

The caveat is that these patches introduce breaking changes to two
table AM functions for bitmapheapscan: table_scan_bitmap_next_block()
and table_scan_bitmap_next_tuple().

You might want an independent perspective on how much of a hassle those breaking changes are, so I took a stab at that. Having written a custom proprietary TAM for postgresql 15 here at EDB, and having ported it and released it for postgresql 16, I thought I'd try porting it to the the above commit with your patches. Even without your patches, I already see breaking changes coming from commit f691f5b80a85c66d715b4340ffabb503eb19393e, which creates a similar amount of breakage for me as does your patches. Dealing with the combined breakage might amount to a day of work, including testing, half of which I think I've already finished. In other words, it doesn't seem like a big deal.

Were postgresql 17 shaping up to be compatible with TAMs written for 16, your patch would change that qualitatively, but since things are already incompatible, I think you're in the clear.

Oh, good to know! I'm very happy to have the perspective of a table AM
author. Just curious, did your table AM implement
table_scan_bitmap_next_block() and table_scan_bitmap_next_tuple(),
and, if so, did you use the TBMIterateResult? Since it is not used in
BitmapHeapNext() in my version, table AMs would have to change how
they use TBMIterateResults anyway. But I assume they could add it to a
table AM specific scan descriptor if they want access to a
TBMIterateResult of their own making in both
table_san_bitmap_next_block() and next_tuple()?

- Melanie

#4Mark Dilger
mark.dilger@enterprisedb.com
In reply to: Melanie Plageman (#3)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Feb 14, 2024, at 6:47 AM, Melanie Plageman <melanieplageman@gmail.com> wrote:

Just curious, did your table AM implement
table_scan_bitmap_next_block() and table_scan_bitmap_next_tuple(),
and, if so, did you use the TBMIterateResult? Since it is not used in
BitmapHeapNext() in my version, table AMs would have to change how
they use TBMIterateResults anyway. But I assume they could add it to a
table AM specific scan descriptor if they want access to a
TBMIterateResult of their own making in both
table_san_bitmap_next_block() and next_tuple()?

My table AM does implement those two functions and does use the TBMIterateResult *tbmres argument, yes. I would deal with the issue in very much the same way that your patches modify heapam. I don't really have any additional comments about that.


Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#5Andres Freund
andres@anarazel.de
In reply to: Melanie Plageman (#1)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2024-02-13 18:11:25 -0500, Melanie Plageman wrote:

Attached is a patch set which refactors BitmapHeapScan such that it
can use the streaming read API [1]. It also resolves the long-standing
FIXME in the BitmapHeapScan code suggesting that the skip fetch
optimization should be pushed into the table AMs. Additionally, it
moves table scan initialization to after the index scan and bitmap
initialization.

Thanks for working on this! While I have some quibbles with details, I think
this is quite a bit of progress in the right direction.

patches 0001-0002 are assorted cleanup needed later in the set.
patches 0003 moves the table scan initialization to after bitmap creation
patch 0004 is, I think, a bug fix. see [2].

I'd not quite call it a bugfix, it's not like it leads to wrong
behaviour. Seems more like an optimization. But whatever :)

The caveat is that these patches introduce breaking changes to two
table AM functions for bitmapheapscan: table_scan_bitmap_next_block()
and table_scan_bitmap_next_tuple().

That's to be expected, I don't think it's worth worrying about. Right now a
bunch of TAMs can't implement bitmap scans, this goes a fair bit towards
allowing that...

From d6dd6eb21dcfbc41208f87d1d81ffe3960130889 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v1 03/11] BitmapHeapScan begin scan after bitmap setup

There is no reason for table_beginscan_bm() to begin the actual scan of
the underlying table in ExecInitBitmapHeapScan(). We can begin the
underlying table scan after the index scan has been completed and the
bitmap built.

The one use of the scan descriptor during initialization was
ExecBitmapHeapInitializeWorker(), which set the scan descriptor snapshot
with one from an array in the parallel state. This overwrote the
snapshot set in table_beginscan_bm().

By saving that worker snapshot as a member in the BitmapHeapScanState
during initialization, it can be restored in table_beginscan_bm() after
returning from the table AM specific begin scan function.

I don't understand what the point of passing two different snapshots to
table_beginscan_bm() is. What does that even mean? Why can't we just use the
correct snapshot initially?

From a3f62e4299663d418531ae61bb16ea39f0836fac Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v1 04/11] BitmapPrefetch use prefetch block recheck for skip
fetch

Previously BitmapPrefetch() used the recheck flag for the current block
to determine whether or not it could skip prefetching the proposed
prefetch block. It makes more sense for it to use the recheck flag from
the TBMIterateResult for the prefetch block instead.

I'd mention the commit that introduced the current logic and link to the
the thread that you started about this.

From d56be7741765d93002649ef912ef4b8256a5b9af Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v1 05/11] Update BitmapAdjustPrefetchIterator parameter type
to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.

Hm - I'm not convinced this is a good direction - doesn't that arguably
*increase* TAM awareness? Perhaps it doesn't make much sense to use bitmap
heap scans in a TAM without blocks, but still.

From 202b16d3a381210e8dbee69e68a8310be8ee11d2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v1 06/11] Push BitmapHeapScan skip fetch optimization into
table AM

This resolves the long-standing FIXME in BitmapHeapNext() which said that
the optmization to skip fetching blocks of the underlying table when
none of the column data was needed should be pushed into the table AM
specific code.

Long-standing? Sure, it's old enough to walk, but we have FIXMEs that are old
enough to drink, at least in some countries. :)

The table AM agnostic functions for prefetching still need to know if
skipping fetching is permitted for this scan. However, this dependency
will be removed when that prefetching code is removed in favor of the
upcoming streaming read API.

---
src/backend/access/heap/heapam.c | 10 +++
src/backend/access/heap/heapam_handler.c | 29 +++++++
src/backend/executor/nodeBitmapHeapscan.c | 100 ++++++----------------
src/include/access/heapam.h | 2 +
src/include/access/tableam.h | 17 ++--
src/include/nodes/execnodes.h | 6 --
6 files changed, 74 insertions(+), 90 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 707460a5364..7aae1ecf0a9 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -955,6 +955,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
scan->rs_base.rs_flags = flags;
scan->rs_base.rs_parallel = parallel_scan;
scan->rs_strategy = NULL;	/* set in initscan */
+	scan->vmbuffer = InvalidBuffer;
+	scan->empty_tuples = 0;

These don't follow the existing naming pattern for HeapScanDescData. While I
explicitly dislike the practice of adding prefixes to struct members, I don't
think mixing conventions within a single struct improves things.

I also think it'd be good to note in comments that the vm buffer currently is
only used for bitmap heap scans, otherwise one might think they'd also be used
for normal scans, where we don't need them, because of the page level flag.

Also, perhaps worth renaming "empty_tuples" to something indicating that it's
the number of empty tuples to be returned later? num_empty_tuples_pending or
such? Or the current "return_empty_tuples".

@@ -1043,6 +1045,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
if (BufferIsValid(scan->rs_cbuf))
ReleaseBuffer(scan->rs_cbuf);

+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+	scan->vmbuffer = InvalidBuffer;

It does not matter one iota here, but personally I prefer moving the write
inside the if, as dirtying the cacheline after we just figured out whe

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 9372b49bfaa..c0fb06c9688 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,6 +108,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
*/
if (!node->initialized)
{
+		bool can_skip_fetch;
/*
* We can potentially skip fetching heap pages if we do not need any
* columns of the table, either for checking non-indexable quals or

Pretty sure pgindent will move this around.

+++ b/src/include/access/tableam.h
@@ -62,6 +62,7 @@ typedef enum ScanOptions

/* unregister snapshot at scan end? */
SO_TEMP_SNAPSHOT = 1 << 9,
+ SO_CAN_SKIP_FETCH = 1 << 10,
} ScanOptions;

Would be nice to add a comment explaining what this flag means.

From 500c84019b982a1e6c8b8dd40240c8510d83c287 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:05:04 -0500
Subject: [PATCH v1 07/11] BitmapHeapScan scan desc counts lossy and exact
pages

Future commits will remove the TBMIterateResult from BitmapHeapNext(),
pushing it into the table AM-specific code. So we will have to keep
track of the number of lossy and exact pages in the scan descriptor.
Doing this change to lossy/exact page counting in a separate commit just
simplifies the diff.

---
src/backend/access/heap/heapam.c | 2 ++
src/backend/access/heap/heapam_handler.c | 9 +++++++++
src/backend/executor/nodeBitmapHeapscan.c | 18 +++++++++++++-----
src/include/access/relscan.h | 4 ++++
4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 7aae1ecf0a9..88b4aad5820 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -957,6 +957,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
scan->rs_strategy = NULL;	/* set in initscan */
scan->vmbuffer = InvalidBuffer;
scan->empty_tuples = 0;
+	scan->rs_base.lossy_pages = 0;
+	scan->rs_base.exact_pages = 0;
/*
* Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index baba09c87c0..6e85ef7a946 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2242,6 +2242,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
Assert(ntup <= MaxHeapTuplesPerPage);
hscan->rs_ntuples = ntup;
+	/* Only count exact and lossy pages with visible tuples */
+	if (ntup > 0)
+	{
+		if (tbmres->ntuples >= 0)
+			scan->exact_pages++;
+		else
+			scan->lossy_pages++;
+	}
+
return ntup > 0;
}
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c0fb06c9688..19d115de06f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,6 +53,8 @@
#include "utils/spccache.h"
static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
+static inline void BitmapAccumCounters(BitmapHeapScanState *node,
+									   TableScanDesc scan);
static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
BlockNumber blockno);
@@ -234,11 +236,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
continue;
}

- if (tbmres->ntuples >= 0)
- node->exact_pages++;
- else
- node->lossy_pages++;
-
/* Adjust the prefetch target */
BitmapAdjustPrefetchTarget(node);
}
@@ -315,9 +312,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
/*
* if we get here it means we are at the end of the scan..
*/
+ BitmapAccumCounters(node, scan);
return ExecClearTuple(slot);
}

+static inline void
+BitmapAccumCounters(BitmapHeapScanState *node,
+					TableScanDesc scan)
+{
+	node->exact_pages += scan->exact_pages;
+	scan->exact_pages = 0;
+	node->lossy_pages += scan->lossy_pages;
+	scan->lossy_pages = 0;
+}
+

I don't think this is quite right - you're calling BitmapAccumCounters() only
when the scan doesn't return anything anymore, but there's no guarantee
that'll ever be reached. E.g. a bitmap heap scan below a limit node. I think
this needs to be in a) ExecEndBitmapHeapScan() b) ExecReScanBitmapHeapScan()

/*
*	BitmapDoneInitializingSharedState - Shared state is initialized
*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..b74e08dd745 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -40,6 +40,10 @@ typedef struct TableScanDescData
ItemPointerData rs_mintid;
ItemPointerData rs_maxtid;
+	/* Only used for Bitmap table scans */
+	long		exact_pages;
+	long		lossy_pages;
+
/*
* Information about type and behaviour of the scan, a bitmask of members
* of the ScanOptions enum (see tableam.h).

I wonder if this really is the best place for the data to be accumulated. This
requires the accounting to be implemented in each AM, which doesn't obviously
seem required. Why can't the accounting continue to live in
nodeBitmapHeapscan.c, to be done after each table_scan_bitmap_next_block()
call?

From 555743e4bc885609d20768f7f2990c6ba69b13a9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:57:07 -0500
Subject: [PATCH v1 09/11] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the known end of the table.

This sounds a bit like the block is actually past the end of the table,
but in reality this happens if the block is past the end of the table as it
was when the scan was started. Somehow that feels significant, but I don't
really know why I think that.

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 88b4aad5820..d8569373987 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -959,6 +959,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
scan->empty_tuples = 0;
scan->rs_base.lossy_pages = 0;
scan->rs_base.exact_pages = 0;
+	scan->rs_base.shared_tbmiterator = NULL;
+	scan->rs_base.tbmiterator = NULL;

/*
* Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1051,6 +1053,18 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
ReleaseBuffer(scan->vmbuffer);
scan->vmbuffer = InvalidBuffer;

+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_base.shared_tbmiterator)
+			tbm_end_shared_iterate(scan->rs_base.shared_tbmiterator);
+
+		if (scan->rs_base.tbmiterator)
+			tbm_end_iterate(scan->rs_base.tbmiterator);
+	}
+
+	scan->rs_base.shared_tbmiterator = NULL;
+	scan->rs_base.tbmiterator = NULL;
+
/*
* reinitialize scan descriptor
*/

If every AM would need to implement this, perhaps this shouldn't be done here,
but in generic code?

--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,17 +2114,49 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
static bool
heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  bool *recheck, BlockNumber *blockno)
{
HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
Buffer		buffer;
Snapshot	snapshot;
int			ntup;
+	TBMIterateResult *tbmres;

hscan->rs_cindex = 0;
hscan->rs_ntuples = 0;

+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->empty_tuples == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);

Hm. Isn't it a problem that we have no CHECK_FOR_INTERRUPTS() in this loop?

@@ -2251,7 +2274,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
scan->lossy_pages++;
}

-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
}

Why can't we fetch the next block immediately?

@@ -201,46 +197,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
can_skip_fetch);
}

-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;

It seems a bit odd that this code modifies the scan descriptor, instead of
passing the iterator, or perhaps better the bitmap itself, to
table_beginscan_bm()?

diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b74e08dd745..bf7ee044268 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@

#include "access/htup_details.h"
#include "access/itup.h"
+#include "nodes/tidbitmap.h"

I'd like to avoid exposing this to everything including relscan.h. I think we
could just forward declare the structs and use them here to avoid that?

From aac60985d6bc70bfedf77a77ee3c512da87bfcb1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:27:57 -0500
Subject: [PATCH v1 11/11] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
---
src/backend/access/gin/ginget.c | 15 +-
src/backend/access/gin/ginscan.c | 7 +
src/backend/access/heap/heapam.c | 71 +++++
src/backend/access/heap/heapam_handler.c | 78 +++--
src/backend/executor/nodeBitmapHeapscan.c | 328 +---------------------
src/backend/nodes/tidbitmap.c | 80 +++---
src/include/access/heapam.h | 2 +
src/include/access/tableam.h | 14 +-
src/include/nodes/execnodes.h | 19 --
src/include/nodes/tidbitmap.h | 8 +-
10 files changed, 178 insertions(+), 444 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3ce28078a6f 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,10 @@ restartScanEntry:
if (entry->matchBitmap)
{
if (entry->matchIterator)
+				{
tbm_end_iterate(entry->matchIterator);
+					pfree(entry->matchResult);
+				}
entry->matchIterator = NULL;
tbm_free(entry->matchBitmap);
entry->matchBitmap = NULL;
@@ -386,6 +389,7 @@ restartScanEntry:
if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
{
entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+			entry->matchResult = palloc0(TBM_ITERATE_RESULT_SIZE);

Do we actually have to use palloc0? TBM_ITERATE_RESULT_SIZE ain't small, so
zeroing all of it isn't free.

+static BlockNumber bitmapheap_pgsr_next_single(PgStreamingRead *pgsr, void *pgsr_private,
+							void *per_buffer_data);

Is it correct to have _single in the name here? Aren't we also using for
parallel scans?

+static BlockNumber
+bitmapheap_pgsr_next_single(PgStreamingRead *pgsr, void *pgsr_private,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		if (hdesc->rs_base.shared_tbmiterator)
+			tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+		else
+			tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+
+		if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->vmbuffer))
+		{
+			hdesc->empty_tuples += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}

Need to check for interrupts somewhere here.

@@ -124,15 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)

There's still a comment in BitmapHeapNext talking about prefetching with two
iterators etc. That seems outdated now.

/*
* tbm_iterate - scan through next page of a TIDBitmap
*
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
*/
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)

Hm - it seems a tad odd that we later have to find out if the scan is done
iterating by checking if blockno is valid, when tbm_iterate already knew. But
I guess the code would be a bit uglier if we needed the result of
tbm_[shared_]iterate(), due to the two functions.

Right now ExecEndBitmapHeapScan() frees the tbm before it does table_endscan()
- which seems problematic, as heap_endscan() will do stuff like
tbm_end_iterate(), which imo shouldn't be called after the tbm has been freed,
even if that works today.

It seems a bit confusing that your changes seem to treat
BitmapHeapScanState->initialized as separate from ->scan, even though afaict
scan should be NULL iff initialized is false and vice versa.

Independent of your patches, but brr, it's ugly that
BitmapShouldInitializeSharedState() blocks.

Greetings,

Andres Freund

#6Melanie Plageman
melanieplageman@gmail.com
In reply to: Andres Freund (#5)
13 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

Thank you so much for this thorough review!!!!

On Wed, Feb 14, 2024 at 2:42 PM Andres Freund <andres@anarazel.de> wrote:

On 2024-02-13 18:11:25 -0500, Melanie Plageman wrote:

From d6dd6eb21dcfbc41208f87d1d81ffe3960130889 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v1 03/11] BitmapHeapScan begin scan after bitmap setup

There is no reason for table_beginscan_bm() to begin the actual scan of
the underlying table in ExecInitBitmapHeapScan(). We can begin the
underlying table scan after the index scan has been completed and the
bitmap built.

The one use of the scan descriptor during initialization was
ExecBitmapHeapInitializeWorker(), which set the scan descriptor snapshot
with one from an array in the parallel state. This overwrote the
snapshot set in table_beginscan_bm().

By saving that worker snapshot as a member in the BitmapHeapScanState
during initialization, it can be restored in table_beginscan_bm() after
returning from the table AM specific begin scan function.

I don't understand what the point of passing two different snapshots to
table_beginscan_bm() is. What does that even mean? Why can't we just use the
correct snapshot initially?

Indeed. Honestly, it was an unlabeled TODO for me. I wasn't quite sure
how to get the same behavior as in master. Fixed in attached v2.

Now the parallel worker still restores and registers that snapshot in
ExecBitmapHeapInitializeWorker() and then saves it in the
BitmapHeapScanState. We then pass SO_TEMP_SNAPSHOT as an extra flag
(to set rs_flags) to table_beginscan_bm() if there is a parallel
worker snapshot saved in the BitmapHeapScanState.

From a3f62e4299663d418531ae61bb16ea39f0836fac Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v1 04/11] BitmapPrefetch use prefetch block recheck for skip
fetch

Previously BitmapPrefetch() used the recheck flag for the current block
to determine whether or not it could skip prefetching the proposed
prefetch block. It makes more sense for it to use the recheck flag from
the TBMIterateResult for the prefetch block instead.

I'd mention the commit that introduced the current logic and link to the
the thread that you started about this.

Done

From d56be7741765d93002649ef912ef4b8256a5b9af Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v1 05/11] Update BitmapAdjustPrefetchIterator parameter type
to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.

Hm - I'm not convinced this is a good direction - doesn't that arguably
*increase* TAM awareness? Perhaps it doesn't make much sense to use bitmap
heap scans in a TAM without blocks, but still.

This is removed in later commits and is an intermediate state to try
and move the TBMIterateResult out of BitmapHeapNext(). I can find
another way to achieve this if it is important.

From 202b16d3a381210e8dbee69e68a8310be8ee11d2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v1 06/11] Push BitmapHeapScan skip fetch optimization into
table AM

This resolves the long-standing FIXME in BitmapHeapNext() which said that
the optmization to skip fetching blocks of the underlying table when
none of the column data was needed should be pushed into the table AM
specific code.

Long-standing? Sure, it's old enough to walk, but we have FIXMEs that are old
enough to drink, at least in some countries. :)

;) I've updated the commit message. Though it is longstanding in that
it predates Melanie + Postgres.

The table AM agnostic functions for prefetching still need to know if
skipping fetching is permitted for this scan. However, this dependency
will be removed when that prefetching code is removed in favor of the
upcoming streaming read API.

---
src/backend/access/heap/heapam.c | 10 +++
src/backend/access/heap/heapam_handler.c | 29 +++++++
src/backend/executor/nodeBitmapHeapscan.c | 100 ++++++----------------
src/include/access/heapam.h | 2 +
src/include/access/tableam.h | 17 ++--
src/include/nodes/execnodes.h | 6 --
6 files changed, 74 insertions(+), 90 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 707460a5364..7aae1ecf0a9 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -955,6 +955,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
scan->rs_base.rs_flags = flags;
scan->rs_base.rs_parallel = parallel_scan;
scan->rs_strategy = NULL;       /* set in initscan */
+     scan->vmbuffer = InvalidBuffer;
+     scan->empty_tuples = 0;

These don't follow the existing naming pattern for HeapScanDescData. While I
explicitly dislike the practice of adding prefixes to struct members, I don't
think mixing conventions within a single struct improves things.

I've updated the names. What does rs even stand for?

I also think it'd be good to note in comments that the vm buffer currently is
only used for bitmap heap scans, otherwise one might think they'd also be used
for normal scans, where we don't need them, because of the page level flag.

Done.

Also, perhaps worth renaming "empty_tuples" to something indicating that it's
the number of empty tuples to be returned later? num_empty_tuples_pending or
such? Or the current "return_empty_tuples".

Done.

@@ -1043,6 +1045,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
if (BufferIsValid(scan->rs_cbuf))
ReleaseBuffer(scan->rs_cbuf);

+     if (BufferIsValid(scan->vmbuffer))
+             ReleaseBuffer(scan->vmbuffer);
+     scan->vmbuffer = InvalidBuffer;

It does not matter one iota here, but personally I prefer moving the write
inside the if, as dirtying the cacheline after we just figured out whe

I've now followed this convention throughout my patchset in the places
where I noticed it.

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 9372b49bfaa..c0fb06c9688 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,6 +108,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
*/
if (!node->initialized)
{
+             bool can_skip_fetch;
/*
* We can potentially skip fetching heap pages if we do not need any
* columns of the table, either for checking non-indexable quals or

Pretty sure pgindent will move this around.

This is gone now, but I have pgindented all the commits so it
shouldn't be a problem again.

+++ b/src/include/access/tableam.h
@@ -62,6 +62,7 @@ typedef enum ScanOptions

/* unregister snapshot at scan end? */
SO_TEMP_SNAPSHOT = 1 << 9,
+ SO_CAN_SKIP_FETCH = 1 << 10,
} ScanOptions;

Would be nice to add a comment explaining what this flag means.

Done.

From 500c84019b982a1e6c8b8dd40240c8510d83c287 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:05:04 -0500
Subject: [PATCH v1 07/11] BitmapHeapScan scan desc counts lossy and exact
pages

Future commits will remove the TBMIterateResult from BitmapHeapNext(),
pushing it into the table AM-specific code. So we will have to keep
track of the number of lossy and exact pages in the scan descriptor.
Doing this change to lossy/exact page counting in a separate commit just
simplifies the diff.

---
src/backend/access/heap/heapam.c | 2 ++
src/backend/access/heap/heapam_handler.c | 9 +++++++++
src/backend/executor/nodeBitmapHeapscan.c | 18 +++++++++++++-----
src/include/access/relscan.h | 4 ++++
4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 7aae1ecf0a9..88b4aad5820 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -957,6 +957,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
scan->rs_strategy = NULL;       /* set in initscan */
scan->vmbuffer = InvalidBuffer;
scan->empty_tuples = 0;
+     scan->rs_base.lossy_pages = 0;
+     scan->rs_base.exact_pages = 0;
/*
* Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index baba09c87c0..6e85ef7a946 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2242,6 +2242,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
Assert(ntup <= MaxHeapTuplesPerPage);
hscan->rs_ntuples = ntup;
+     /* Only count exact and lossy pages with visible tuples */
+     if (ntup > 0)
+     {
+             if (tbmres->ntuples >= 0)
+                     scan->exact_pages++;
+             else
+                     scan->lossy_pages++;
+     }
+
return ntup > 0;
}
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c0fb06c9688..19d115de06f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,6 +53,8 @@
#include "utils/spccache.h"
static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
+static inline void BitmapAccumCounters(BitmapHeapScanState *node,
+                                                                        TableScanDesc scan);
static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
BlockNumber blockno);
@@ -234,11 +236,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
continue;
}
-                     if (tbmres->ntuples >= 0)
-                             node->exact_pages++;
-                     else
-                             node->lossy_pages++;
-
/* Adjust the prefetch target */
BitmapAdjustPrefetchTarget(node);
}
@@ -315,9 +312,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
/*
* if we get here it means we are at the end of the scan..
*/
+     BitmapAccumCounters(node, scan);
return ExecClearTuple(slot);
}
+static inline void
+BitmapAccumCounters(BitmapHeapScanState *node,
+                                     TableScanDesc scan)
+{
+     node->exact_pages += scan->exact_pages;
+     scan->exact_pages = 0;
+     node->lossy_pages += scan->lossy_pages;
+     scan->lossy_pages = 0;
+}
+

I don't think this is quite right - you're calling BitmapAccumCounters() only
when the scan doesn't return anything anymore, but there's no guarantee
that'll ever be reached. E.g. a bitmap heap scan below a limit node. I think
this needs to be in a) ExecEndBitmapHeapScan() b) ExecReScanBitmapHeapScan()

The scan descriptor isn't available in ExecEnd/ReScanBitmapHeapScan().
So, if we count in the scan descriptor we can't accumulate into the
BitmapHeapScanState there. The reason to count in the scan descriptor
is that it is in the table AM where we know if we have a lossy or
exact page -- and we only have the scan descriptor not the
BitmapHeapScanState in the table AM.

I added a call to BitmapAccumCounters before the tuple is returned for
correctness in this version (not ideal, I realize). See below for
thoughts about what we could do instead.

/*
*   BitmapDoneInitializingSharedState - Shared state is initialized
*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..b74e08dd745 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -40,6 +40,10 @@ typedef struct TableScanDescData
ItemPointerData rs_mintid;
ItemPointerData rs_maxtid;
+     /* Only used for Bitmap table scans */
+     long            exact_pages;
+     long            lossy_pages;
+
/*
* Information about type and behaviour of the scan, a bitmask of members
* of the ScanOptions enum (see tableam.h).

I wonder if this really is the best place for the data to be accumulated. This
requires the accounting to be implemented in each AM, which doesn't obviously
seem required. Why can't the accounting continue to live in
nodeBitmapHeapscan.c, to be done after each table_scan_bitmap_next_block()
call?

Yes, I would really prefer not to do it in the table AM. But, we only
count exact and lossy pages for which at least one or more tuples were
visible (change this and you'll see tests fail). So, we need to decide
if we are going to increment the counters somewhere where we have
access to that information. In the case of heap, that is really only
once I have the value of ntup in heapam_scan_bitmap_next_block(). To
get that information back out to BitmapHeapNext(), I considered adding
another parameter to heapam_scan_bitmap_next_block() -- maybe an enum
like this:

/*
* BitmapHeapScans's bitmaps can choose to store per page information in a
* lossy or exact way. Exact pages in the bitmap have the individual tuple
* offsets that need to be visited while lossy pages in the bitmap have only the
* block number of the page.
*/
typedef enum BitmapBlockResolution
{
BITMAP_BLOCK_NO_VISIBLE,
BITMAP_BLOCK_LOSSY,
BITMAP_BLOCK_EXACT,
} BitmapBlockResolution;

which we then use to increment the counter. But while I was writing
this code, I found myself narrating in the comment that the reason
this had to be set inside of the table AM is that only the table AM
knows if it wants to count the block as lossy, exact, or not count it.
So, that made me question if it really should be in the
BitmapHeapScanState.

I also explored passing the table scan descriptor to
show_tidbitmap_info() -- but that had its own problems.

From 555743e4bc885609d20768f7f2990c6ba69b13a9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:57:07 -0500
Subject: [PATCH v1 09/11] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the known end of the table.

This sounds a bit like the block is actually past the end of the table,
but in reality this happens if the block is past the end of the table as it
was when the scan was started. Somehow that feels significant, but I don't
really know why I think that.

I have tried to update the commit message to make it clearer. I was
actually wondering: now that we do table_beginscan_bm() in
BitmapHeapNext() instead of ExecInitBitmapHeapScan(), have we reduced
or eliminated the opportunity for this to be true? initscan() sets
rs_nblocks and that now happens much later.

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 88b4aad5820..d8569373987 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -959,6 +959,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
scan->empty_tuples = 0;
scan->rs_base.lossy_pages = 0;
scan->rs_base.exact_pages = 0;
+     scan->rs_base.shared_tbmiterator = NULL;
+     scan->rs_base.tbmiterator = NULL;

/*
* Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1051,6 +1053,18 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
ReleaseBuffer(scan->vmbuffer);
scan->vmbuffer = InvalidBuffer;

+     if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+     {
+             if (scan->rs_base.shared_tbmiterator)
+                     tbm_end_shared_iterate(scan->rs_base.shared_tbmiterator);
+
+             if (scan->rs_base.tbmiterator)
+                     tbm_end_iterate(scan->rs_base.tbmiterator);
+     }
+
+     scan->rs_base.shared_tbmiterator = NULL;
+     scan->rs_base.tbmiterator = NULL;
+
/*
* reinitialize scan descriptor
*/

If every AM would need to implement this, perhaps this shouldn't be done here,
but in generic code?

Fixed.

--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,17 +2114,49 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
static bool
heapam_scan_bitmap_next_block(TableScanDesc scan,
-                                                       TBMIterateResult *tbmres)
+                                                       bool *recheck, BlockNumber *blockno)
{
HeapScanDesc hscan = (HeapScanDesc) scan;
-     BlockNumber block = tbmres->blockno;
+     BlockNumber block;
Buffer          buffer;
Snapshot        snapshot;
int                     ntup;
+     TBMIterateResult *tbmres;

hscan->rs_cindex = 0;
hscan->rs_ntuples = 0;

+     *blockno = InvalidBlockNumber;
+     *recheck = true;
+
+     do
+     {
+             if (scan->shared_tbmiterator)
+                     tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+             else
+                     tbmres = tbm_iterate(scan->tbmiterator);
+
+             if (tbmres == NULL)
+             {
+                     /* no more entries in the bitmap */
+                     Assert(hscan->empty_tuples == 0);
+                     return false;
+             }
+
+             /*
+              * Ignore any claimed entries past what we think is the end of the
+              * relation. It may have been extended after the start of our scan (we
+              * only hold an AccessShareLock, and it could be inserts from this
+              * backend).  We don't take this optimization in SERIALIZABLE
+              * isolation though, as we need to examine all invisible tuples
+              * reachable by the index.
+              */
+     } while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);

Hm. Isn't it a problem that we have no CHECK_FOR_INTERRUPTS() in this loop?

Yes. fixed.

@@ -2251,7 +2274,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
scan->lossy_pages++;
}

-     return ntup > 0;
+     /*
+      * Return true to indicate that a valid block was found and the bitmap is
+      * not exhausted. If there are no visible tuples on this page,
+      * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+      * return false returning control to this function to advance to the next
+      * block in the bitmap.
+      */
+     return true;
}

Why can't we fetch the next block immediately?

We don't know that we want another block until we've gone through this
page and seen there were no visible tuples, so we'd somehow have to
jump back up to the top of the function to get the next block -- which
is basically what is happening in my revised control flow. We call
heapam_scan_bitmap_next_tuple() and rs_ntuples is 0, so we end up
calling heapam_scan_bitmap_next_block() right away.

@@ -201,46 +197,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
can_skip_fetch);
}

-             node->tbmiterator = tbmiterator;
-             node->shared_tbmiterator = shared_tbmiterator;
+             scan->tbmiterator = tbmiterator;
+             scan->shared_tbmiterator = shared_tbmiterator;

It seems a bit odd that this code modifies the scan descriptor, instead of
passing the iterator, or perhaps better the bitmap itself, to
table_beginscan_bm()?

On rescan we actually will have initialized = false and make new
iterators but have the old scan descriptor. So, we need to be able to
set the iterator in the scan to the new iterator.

diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b74e08dd745..bf7ee044268 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@

#include "access/htup_details.h"
#include "access/itup.h"
+#include "nodes/tidbitmap.h"

I'd like to avoid exposing this to everything including relscan.h. I think we
could just forward declare the structs and use them here to avoid that?

Done

From aac60985d6bc70bfedf77a77ee3c512da87bfcb1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:27:57 -0500
Subject: [PATCH v1 11/11] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
---
src/backend/access/gin/ginget.c | 15 +-
src/backend/access/gin/ginscan.c | 7 +
src/backend/access/heap/heapam.c | 71 +++++
src/backend/access/heap/heapam_handler.c | 78 +++--
src/backend/executor/nodeBitmapHeapscan.c | 328 +---------------------
src/backend/nodes/tidbitmap.c | 80 +++---
src/include/access/heapam.h | 2 +
src/include/access/tableam.h | 14 +-
src/include/nodes/execnodes.h | 19 --
src/include/nodes/tidbitmap.h | 8 +-
10 files changed, 178 insertions(+), 444 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3ce28078a6f 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,10 @@ restartScanEntry:
if (entry->matchBitmap)
{
if (entry->matchIterator)
+                             {
tbm_end_iterate(entry->matchIterator);
+                                     pfree(entry->matchResult);
+                             }
entry->matchIterator = NULL;
tbm_free(entry->matchBitmap);
entry->matchBitmap = NULL;
@@ -386,6 +389,7 @@ restartScanEntry:
if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
{
entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+                     entry->matchResult = palloc0(TBM_ITERATE_RESULT_SIZE);

Do we actually have to use palloc0? TBM_ITERATE_RESULT_SIZE ain't small, so
zeroing all of it isn't free.

Tests actually did fail when I didn't use palloc0.

This code is different now though. There are a few new patches in v2
that 1) make the offsets array in the TBMIterateResult fixed size and
then this makes it possible to 2) make matchResult an inline member of
the GinScanEntry. I have a TODO in the code asking if setting blockno
in the TBMIterateResult to InvalidBlockNumber is sufficient
"resetting".

+static BlockNumber bitmapheap_pgsr_next_single(PgStreamingRead *pgsr, void *pgsr_private,
+                                                     void *per_buffer_data);

Is it correct to have _single in the name here? Aren't we also using for
parallel scans?

Right. I had a separate parallel version and then deleted it. This is now fixed.

+static BlockNumber
+bitmapheap_pgsr_next_single(PgStreamingRead *pgsr, void *pgsr_private,
+                                                     void *per_buffer_data)
+{
+     TBMIterateResult *tbmres = per_buffer_data;
+     HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+     for (;;)
+     {
+             if (hdesc->rs_base.shared_tbmiterator)
+                     tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+             else
+                     tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+             /* no more entries in the bitmap */
+             if (!BlockNumberIsValid(tbmres->blockno))
+                     return InvalidBlockNumber;
+
+             /*
+              * Ignore any claimed entries past what we think is the end of the
+              * relation. It may have been extended after the start of our scan (we
+              * only hold an AccessShareLock, and it could be inserts from this
+              * backend).  We don't take this optimization in SERIALIZABLE
+              * isolation though, as we need to examine all invisible tuples
+              * reachable by the index.
+              */
+             if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+                     continue;
+
+
+             if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+                     !tbmres->recheck &&
+                     VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->vmbuffer))
+             {
+                     hdesc->empty_tuples += tbmres->ntuples;
+                     continue;
+             }
+
+             return tbmres->blockno;
+     }
+
+     /* not reachable */
+     Assert(false);
+}

Need to check for interrupts somewhere here.

Done.

@@ -124,15 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)

There's still a comment in BitmapHeapNext talking about prefetching with two
iterators etc. That seems outdated now.

Fixed.

/*
* tbm_iterate - scan through next page of a TIDBitmap
*
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
*/
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)

Hm - it seems a tad odd that we later have to find out if the scan is done
iterating by checking if blockno is valid, when tbm_iterate already knew. But
I guess the code would be a bit uglier if we needed the result of
tbm_[shared_]iterate(), due to the two functions.

Yes.

Right now ExecEndBitmapHeapScan() frees the tbm before it does table_endscan()
- which seems problematic, as heap_endscan() will do stuff like
tbm_end_iterate(), which imo shouldn't be called after the tbm has been freed,
even if that works today.

I've flipped the order -- I end the scan then free the bitmap.

It seems a bit confusing that your changes seem to treat
BitmapHeapScanState->initialized as separate from ->scan, even though afaict
scan should be NULL iff initialized is false and vice versa.

I thought so too, but it seems on rescan that the node->initialized is
set to false but the scan is reused. So, we want to only make a new
scan descriptor if it is truly the beginning of a new scan.

- Melanie

Attachments:

v2-0011-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchtext/x-patch; charset=US-ASCII; name=v2-0011-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchDownload
From b0417f661ffab18058a392327370eb8690b49c38 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v2 11/13] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 33 +++++-----
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 7 files changed, 107 insertions(+), 87 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..831941271c4 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno to
+	 * InvalidBlockNumber. It seems like this should be okay because that is
+	 * usually what we check before using the matchResult members. But it might
+	 * be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..033d5253394 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c8da3def645..ba6793a749c 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2121,7 +2121,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2134,11 +2134,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		CHECK_FOR_INTERRUPTS();
 
 		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbm_iterate(scan->tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2153,11 +2153,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2165,19 +2165,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * the page are visible to our transaction.
 	 */
 	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2206,7 +2206,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2215,9 +2215,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2270,7 +2270,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/* Only count exact and lossy pages with visible tuples */
 	if (ntup > 0)
 	{
-		if (tbmres->ntuples >= 0)
+		if (tbmres.ntuples >= 0)
 			scan->exact_pages++;
 		else
 			scan->lossy_pages++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index ae837785116..284641fa8ea 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -340,9 +340,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+			TBMIterateResult tbmpre;
+			tbm_iterate(prefetch_iterator, &tbmpre);
 
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
+			if (!BlockNumberIsValid(tbmpre.blockno) || tbmpre.blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
@@ -360,6 +361,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		}
 		else
 		{
+			TBMIterateResult tbmpre;
+
 			/* Release the mutex before iterating */
 			SpinLockRelease(&pstate->mutex);
 
@@ -372,7 +375,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -439,10 +442,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
@@ -464,13 +469,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 */
 
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -485,7 +490,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -504,8 +509,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_shared_iterate(prefetch_iterator);
@@ -515,13 +520,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index f711c056143..b4dcb1cbb88 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -171,7 +171,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -212,7 +211,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
 };
 
 /* Local function prototypes */
@@ -943,20 +941,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -984,6 +983,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -994,11 +994,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1014,16 +1014,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1033,10 +1034,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1087,13 +1087,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1103,21 +1103,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 51d0c74a6b0..e423d92b41c 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae52962..f000c1af28f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.37.2

v2-0012-Streaming-Read-API.patchtext/x-patch; charset=US-ASCII; name=v2-0012-Streaming-Read-API.patchDownload
From d84a520da846da83717b748a2bd30f4185d36ebe Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 22 Jul 2023 17:31:54 +1200
Subject: [PATCH v2 12/13] Streaming Read API

---
 contrib/pg_prewarm/pg_prewarm.c          |  40 +-
 src/backend/access/transam/xlogutils.c   |   2 +-
 src/backend/postmaster/bgwriter.c        |   8 +-
 src/backend/postmaster/checkpointer.c    |  15 +-
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 435 ++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 560 +++++++++++++++--------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/backend/storage/smgr/smgr.c          |  49 +-
 src/include/storage/bufmgr.h             |  22 +
 src/include/storage/smgr.h               |   4 +-
 src/include/storage/streaming_read.h     |  45 ++
 src/include/utils/rel.h                  |   6 -
 src/tools/pgindent/typedefs.list         |   2 +
 17 files changed, 986 insertions(+), 238 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/contrib/pg_prewarm/pg_prewarm.c b/contrib/pg_prewarm/pg_prewarm.c
index 8541e4d6e46..9617bf130bd 100644
--- a/contrib/pg_prewarm/pg_prewarm.c
+++ b/contrib/pg_prewarm/pg_prewarm.c
@@ -20,6 +20,7 @@
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
 #include "storage/smgr.h"
+#include "storage/streaming_read.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -38,6 +39,25 @@ typedef enum
 
 static PGIOAlignedBlock blockbuffer;
 
+struct pg_prewarm_streaming_read_private
+{
+	BlockNumber blocknum;
+	int64		last_block;
+};
+
+static BlockNumber
+pg_prewarm_streaming_read_next(PgStreamingRead *pgsr,
+							   void *pgsr_private,
+							   void *per_buffer_data)
+{
+	struct pg_prewarm_streaming_read_private *p = pgsr_private;
+
+	if (p->blocknum <= p->last_block)
+		return p->blocknum++;
+
+	return InvalidBlockNumber;
+}
+
 /*
  * pg_prewarm(regclass, mode text, fork text,
  *			  first_block int8, last_block int8)
@@ -183,18 +203,36 @@ pg_prewarm(PG_FUNCTION_ARGS)
 	}
 	else if (ptype == PREWARM_BUFFER)
 	{
+		struct pg_prewarm_streaming_read_private p;
+		PgStreamingRead *pgsr;
+
 		/*
 		 * In buffer mode, we actually pull the data into shared_buffers.
 		 */
+
+		/* Set up the private state for our streaming buffer read callback. */
+		p.blocknum = first_block;
+		p.last_block = last_block;
+
+		pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+											  &p,
+											  0,
+											  NULL,
+											  BMR_REL(rel),
+											  forkNumber,
+											  pg_prewarm_streaming_read_next);
+
 		for (block = first_block; block <= last_block; ++block)
 		{
 			Buffer		buf;
 
 			CHECK_FOR_INTERRUPTS();
-			buf = ReadBufferExtended(rel, forkNumber, block, RBM_NORMAL, NULL);
+			buf = pg_streaming_read_buffer_get_next(pgsr, NULL);
 			ReleaseBuffer(buf);
 			++blocks_done;
 		}
+		Assert(pg_streaming_read_buffer_get_next(pgsr, NULL) == InvalidBuffer);
+		pg_streaming_read_free(pgsr);
 	}
 
 	/* Close relation, release lock. */
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index aa8667abd10..8775b5789be 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -657,7 +657,7 @@ XLogDropDatabase(Oid dbid)
 	 * This is unnecessarily heavy-handed, as it will close SMgrRelation
 	 * objects for other databases as well. DROP DATABASE occurs seldom enough
 	 * that it's not worth introducing a variant of smgrclose for just this
-	 * purpose. XXX: Or should we rather leave the smgr entries dangling?
+	 * purpose.
 	 */
 	smgrcloseall();
 
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index d7d6cc0cd7b..13e5376619e 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -246,10 +246,12 @@ BackgroundWriterMain(void)
 		if (FirstCallSinceLastCheckpoint())
 		{
 			/*
-			 * After any checkpoint, close all smgr files.  This is so we
-			 * won't hang onto smgr references to deleted files indefinitely.
+			 * After any checkpoint, free all smgr objects.  Otherwise we
+			 * would never do so for dropped relations, as the bgwriter does
+			 * not process shared invalidation messages or call
+			 * AtEOXact_SMgr().
 			 */
-			smgrcloseall();
+			smgrdestroyall();
 		}
 
 		/*
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 5e949fc885b..5d843b61426 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -469,10 +469,12 @@ CheckpointerMain(void)
 				ckpt_performed = CreateRestartPoint(flags);
 
 			/*
-			 * After any checkpoint, close all smgr files.  This is so we
-			 * won't hang onto smgr references to deleted files indefinitely.
+			 * After any checkpoint, free all smgr objects.  Otherwise we
+			 * would never do so for dropped relations, as the checkpointer
+			 * does not process shared invalidation messages or call
+			 * AtEOXact_SMgr().
 			 */
-			smgrcloseall();
+			smgrdestroyall();
 
 			/*
 			 * Indicate checkpoint completion to any waiting backends.
@@ -958,11 +960,8 @@ RequestCheckpoint(int flags)
 		 */
 		CreateCheckPoint(flags | CHECKPOINT_IMMEDIATE);
 
-		/*
-		 * After any checkpoint, close all smgr files.  This is so we won't
-		 * hang onto smgr references to deleted files indefinitely.
-		 */
-		smgrcloseall();
+		/* Free all smgr objects, as CheckpointerMain() normally would. */
+		smgrdestroyall();
 
 		return;
 	}
diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca20..eec03f6f2b4 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 00000000000..bcab44c802f
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 00000000000..39aef2a84a2
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 00000000000..19605090fea
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,435 @@
+#include "postgres.h"
+
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ *
+ * For hits, need_to_complete is false and there is just one block per
+ * range, already pinned and ready for use.
+ *
+ * For misses, need_to_complete is true and buffers[] holds a range of
+ * blocks that are contiguous in storage (though the buffers may not be
+ * contiguous in memory), so we can complete them with a single call to
+ * CompleteReadBuffers().
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		advice_issued;
+	bool		need_complete;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index[MAX_BUFFERS_PER_TRANSFER];
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+} PgStreamingReadRange;
+
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			ios_in_progress_trigger;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			pinned_buffers_trigger;
+	int			next_tail_buffer;
+	bool		finished;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	bool		advice_enabled;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+	int			per_buffer_data_next;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+static PgStreamingRead *
+pg_streaming_read_buffer_alloc_internal(int flags,
+										void *pgsr_private,
+										size_t per_buffer_data_size,
+										BufferAccessStrategy strategy)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = maintenance_io_concurrency;
+	else
+		max_ios = effective_io_concurrency;
+
+	/*
+	 * The desired level of I/O concurrency controls how far ahead we are
+	 * willing to look ahead.  We also clamp it to at least
+	 * MAX_BUFFER_PER_TRANFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/*
+	 * The *_io_concurrency GUCs, we might have 0.  We want to allow at least
+	 * one, to keep our gating logic simple.
+	 */
+	max_ios = Max(max_ios, 1);
+
+	/*
+	 * Don't allow this backend to pin too many buffers.  For now we'll apply
+	 * the limit for the shared buffer pool and the local buffer pool, without
+	 * worrying which it is.
+	 */
+	LimitAdditionalPins(&max_pinned_buffers);
+	LimitAdditionalLocalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * We want to avoid creating ranges that are smaller than they could be
+	 * just because we hit max_pinned_buffers.  We only look ahead when the
+	 * number of pinned buffers falls below this trigger number, or put
+	 * another way, we stop looking ahead when we wouldn't be able to build a
+	 * "full sized" range.
+	 */
+	pgsr->pinned_buffers_trigger =
+		Max(1, (int) max_pinned_buffers - MAX_BUFFERS_PER_TRANSFER);
+
+	/* Space the callback to store extra data along with each block. */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * max_pinned_buffers);
+
+	return pgsr;
+}
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *result;
+
+	result = pg_streaming_read_buffer_alloc_internal(flags,
+													 pgsr_private,
+													 per_buffer_data_size,
+													 strategy);
+	result->callback = next_block_cb;
+	result->bmr = bmr;
+	result->forknum = forknum;
+
+	return result;
+}
+
+/*
+ * Start building a new range.  This is called after the previous one
+ * reached maximum size, or the callback's next block can't be merged with it.
+ *
+ * Since the previous head range has now reached its full potential size, this
+ * is also a good time to issue 'prefetch' advice, because we know that'll
+ * soon be reading.  In future, we could start an actual I/O here.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_new_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If a call to CompleteReadBuffers() will be needed, and we can issue
+	 * advice to the kernel to get the read started.  We suppress it if the
+	 * access pattern appears to be completely sequential, though, because on
+	 * some systems that interfers with the kernel's own sequential read ahead
+	 * heurstics and hurts performance.
+	 */
+	if (pgsr->advice_enabled)
+	{
+		BlockNumber blocknum = head_range->blocknum;
+		int			nblocks = head_range->nblocks;
+
+		if (head_range->need_complete && blocknum != pgsr->seq_blocknum)
+		{
+			SMgrRelation smgr =
+				pgsr->bmr.smgr ? pgsr->bmr.smgr :
+				RelationGetSmgr(pgsr->bmr.rel);
+
+			Assert(!head_range->advice_issued);
+
+			smgrprefetch(smgr, pgsr->forknum, blocknum, nblocks);
+
+			/*
+			 * Count this as an I/O that is concurrently in progress, though
+			 * we don't really know if the kernel generates a physical I/O.
+			 */
+			head_range->advice_issued = true;
+			pgsr->ios_in_progress++;
+		}
+
+		/* Remember the block after this range, for sequence detection. */
+		pgsr->seq_blocknum = blocknum + nblocks;
+	}
+
+	/* Create a new head range.  There must be space. */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	head_range = &pgsr->ranges[pgsr->head];
+	head_range->nblocks = 0;
+
+	return head_range;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	/*
+	 * If we're finished or can't start more I/O, then don't look ahead.
+	 */
+	if (pgsr->finished || pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/*
+	 * We'll also wait until the number of pinned buffers falls below our
+	 * trigger level, so that we have the chance to create a full range.
+	 */
+	if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger)
+		return;
+
+	do
+	{
+		BufferManagerRelation bmr;
+		ForkNumber	forknum;
+		BlockNumber blocknum;
+		Buffer		buffer;
+		bool		found;
+		bool		need_complete;
+		PgStreamingReadRange *head_range;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		head_range = &pgsr->ranges[pgsr->head];
+		if (head_range->nblocks == lengthof(head_range->buffers))
+		{
+			Assert(head_range->need_complete);
+			head_range = pg_streaming_read_new_range(pgsr);
+
+			/*
+			 * Give up now if I/O is saturated, or we wouldn't be able form
+			 * another full range after this due to the pin limit.
+			 */
+			if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger ||
+				pgsr->ios_in_progress == pgsr->max_ios)
+				break;
+		}
+
+		per_buffer_data = (char *) pgsr->per_buffer_data +
+			pgsr->per_buffer_data_size * pgsr->per_buffer_data_next;
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			pgsr->finished = true;
+			break;
+		}
+		bmr = pgsr->bmr;
+		forknum = pgsr->forknum;
+
+		Assert(pgsr->pinned_buffers < pgsr->max_pinned_buffers);
+
+		buffer = PrepareReadBuffer(bmr,
+								   forknum,
+								   blocknum,
+								   pgsr->strategy,
+								   &found);
+		pgsr->pinned_buffers++;
+
+		need_complete = !found;
+
+		/* Is there a head range that we can't extend? */
+		head_range = &pgsr->ranges[pgsr->head];
+		if (head_range->nblocks > 0 &&
+			(!need_complete ||
+			 !head_range->need_complete ||
+			 head_range->blocknum + head_range->nblocks != blocknum))
+		{
+			/* Yes, time to start building a new one. */
+			head_range = pg_streaming_read_new_range(pgsr);
+			Assert(head_range->nblocks == 0);
+		}
+
+		if (head_range->nblocks == 0)
+		{
+			/* Initialize a new range beginning at this block. */
+			head_range->blocknum = blocknum;
+			head_range->need_complete = need_complete;
+			head_range->advice_issued = false;
+		}
+		else
+		{
+			/* We can extend an existing range by one block. */
+			Assert(head_range->blocknum + head_range->nblocks == blocknum);
+			Assert(head_range->need_complete);
+		}
+
+		head_range->per_buffer_data_index[head_range->nblocks] = pgsr->per_buffer_data_next++;
+		head_range->buffers[head_range->nblocks] = buffer;
+		head_range->nblocks++;
+
+		if (pgsr->per_buffer_data_next == pgsr->max_pinned_buffers)
+			pgsr->per_buffer_data_next = 0;
+
+	} while (pgsr->pinned_buffers < pgsr->max_pinned_buffers &&
+			 pgsr->ios_in_progress < pgsr->max_ios);
+
+	if (pgsr->ranges[pgsr->head].nblocks > 0)
+		pg_streaming_read_new_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	pg_streaming_read_look_ahead(pgsr);
+
+	/* See if we have one buffer to return. */
+	while (pgsr->tail != pgsr->head)
+	{
+		PgStreamingReadRange *tail_range;
+
+		tail_range = &pgsr->ranges[pgsr->tail];
+
+		/*
+		 * Do we need to perform an I/O before returning the buffers from this
+		 * range?
+		 */
+		if (tail_range->need_complete)
+		{
+			CompleteReadBuffers(pgsr->bmr,
+								tail_range->buffers,
+								pgsr->forknum,
+								tail_range->blocknum,
+								tail_range->nblocks,
+								false,
+								pgsr->strategy);
+			tail_range->need_complete = false;
+
+			/*
+			 * We don't really know if the kernel generated an physical I/O
+			 * when we issued advice, let alone when it finished, but it has
+			 * certainly finished after a read call returns.
+			 */
+			if (tail_range->advice_issued)
+				pgsr->ios_in_progress--;
+		}
+
+		/* Are there more buffers available in this range? */
+		if (pgsr->next_tail_buffer < tail_range->nblocks)
+		{
+			int			buffer_index;
+			Buffer		buffer;
+
+			buffer_index = pgsr->next_tail_buffer++;
+			buffer = tail_range->buffers[buffer_index];
+
+			Assert(BufferIsValid(buffer));
+
+			/* We are giving away ownership of this pinned buffer. */
+			Assert(pgsr->pinned_buffers > 0);
+			pgsr->pinned_buffers--;
+
+			if (per_buffer_data)
+				*per_buffer_data = (char *) pgsr->per_buffer_data +
+					tail_range->per_buffer_data_index[buffer_index] *
+					pgsr->per_buffer_data_size;
+
+			return buffer;
+		}
+
+		/* Advance tail to next range, if there is one. */
+		if (++pgsr->tail == pgsr->size)
+			pgsr->tail = 0;
+		pgsr->next_tail_buffer = 0;
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead, and unpin anything that wasn't consumed. */
+	pgsr->finished = true;
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7d601bef6dd..2157a97b973 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -472,7 +472,7 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
 								ReadBufferMode mode, BufferAccessStrategy strategy,
 								bool *hit);
@@ -501,7 +501,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -795,15 +795,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
+	buf = ReadBuffer_common(BMR_REL(reln),
 							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+
 	return buf;
 }
 
@@ -827,8 +821,9 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 
 	SMgrRelation smgr = smgropen(rlocator, InvalidBackendId);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
 							 mode, strategy, &hit);
 }
 
@@ -1002,7 +997,7 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 		bool		hit;
 
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
+		buffer = ReadBuffer_common(bmr,
 								   fork, extend_to - 1, mode, strategy,
 								   &hit);
 	}
@@ -1016,18 +1011,11 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
 				  BufferAccessStrategy strategy, bool *hit)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	Buffer		buffer;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1046,175 +1034,339 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		*hit = false;
+
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	buffer = PrepareReadBuffer(bmr,
+							   forkNum,
+							   blockNum,
+							   strategy,
+							   hit);
+
+	/* At this point we do NOT hold any locks. */
 
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+	{
+		/* if we just want zeroes and a lock, we're done */
+		ZeroBuffer(buffer, mode);
+	}
+	else if (!*hit)
+	{
+		/* we might need to perform I/O */
+		CompleteReadBuffers(bmr,
+							&buffer,
+							forkNum,
+							blockNum,
+							1,
+							mode == RBM_ZERO_ON_ERROR,
+							strategy);
+	}
+
+	return buffer;
+}
+
+/*
+ * Prepare to read a block.  The buffer is pinned.  If this is a 'hit', then
+ * the returned buffer can be used immediately.  Otherwise, a physical read
+ * should be completed with CompleteReadBuffers(), or the buffer should be
+ * zeroed with ZeroBuffer().  PrepareReadBuffer() followed by
+ * CompleteReadBuffers() or ZeroBuffer() is equivalent to ReadBuffer(), but
+ * the caller has the opportunity to combine reads of multiple neighboring
+ * blocks into one CompleteReadBuffers() call.
+ *
+ * *foundPtr is set to true for a hit, and false for a miss.
+ */
+Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * CompleteReadBuffers() (so, not for hits, and not for buffers that
+		 * are zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+static inline bool
+CompleteReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
+	{
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+/*
+ * Complete a set reads prepared with PrepareReadBuffers().  The buffers must
+ * cover a cluster of neighboring block numbers.
+ *
+ * Typically this performs one physical vector read covering the block range,
+ * but if some of the buffers have already been read in the meantime by any
+ * backend, zero or multiple reads may be performed.
+ */
+void
+CompleteReadBuffers(BufferManagerRelation bmr,
+					Buffer *buffers,
+					ForkNumber forknum,
+					BlockNumber blocknum,
+					int nblocks,
+					bool zero_on_error,
+					BufferAccessStrategy strategy)
+{
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
+	if (isLocalBuf)
+	{
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
+	}
+	else
+	{
+		io_context = IOContextForStrategy(strategy);
+		io_object = IOOBJECT_RELATION;
+	}
 
 	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
 	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
 	else
+		pgBufferUsage.shared_blks_read += nblocks;
+
+	for (int i = 0; i < nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+#ifdef USE_ASSERT_CHECKING
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		/*
+		 * We could get all the information from buffer headers, but it can be
+		 * expensive to access buffer header cache lines so we make the caller
+		 * provide all the information we need, and assert that it is
+		 * consistent.
+		 */
+		{
+			RelFileLocator xlocator;
+			ForkNumber	xforknum;
+			BlockNumber xblocknum;
+
+			BufferGetTag(buffers[i], &xlocator, &xforknum, &xblocknum);
+			Assert(RelFileLocatorEquals(bmr.smgr->smgr_rlocator.locator, xlocator));
+			Assert(xforknum == forknum);
+			Assert(xblocknum == blocknum + i);
+		}
+#endif
+
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!CompleteReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   CompleteReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
 			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
 			}
 			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-		}
-	}
-
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
-	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
-	}
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
 
-	if (isLocalBuf)
-	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if (zero_on_error || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
 
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
-	}
-	else
-	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
-	}
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
@@ -1228,11 +1380,8 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.  A read should be
+ * performed with CompleteReadBuffers().
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1291,19 +1440,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called PrepareReadBuffer() but not yet CompleteReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1368,19 +1508,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called PrepareReadBuffer() but not yet CompleteReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1412,15 +1543,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1774,7 +1899,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2043,7 +2168,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2066,7 +2191,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2381,7 +2506,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if PrepareReadBuffer() was called and
+		 * CompleteReadBuffers() hasn't been called yet.  We'll check by
+		 * loading the flags without locking.  This is racy, but it's OK to
+		 * return false spuriously: when CompleteReadBuffers() calls
+		 * StartBufferIO(), it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2390,7 +2520,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3458,7 +3588,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -4845,6 +4975,46 @@ ConditionalLockBuffer(Buffer buffer)
 									LW_EXCLUSIVE);
 }
 
+/*
+ * Zero a buffer, and lock it as RBM_ZERO_AND_LOCK or
+ * RBM_ZERO_AND_CLEANUP_LOCK would.  The buffer must be already pinned.  It
+ * does not have to be valid, but it is valid and locked on return.
+ */
+void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * Verify that this backend is pinning the buffer exactly once.
  *
@@ -5197,9 +5367,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5212,6 +5388,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 1be4f4f8daf..717b8f58daf 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -109,10 +109,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -288,7 +287,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -298,9 +297,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca27..739d13293fb 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 563a0be5c74..0d7272e796e 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -147,7 +147,9 @@ smgrshutdown(int code, Datum arg)
 /*
  * smgropen() -- Return an SMgrRelation object, creating it if need be.
  *
- * This does not attempt to actually open the underlying file.
+ * This does not attempt to actually open the underlying files.  The returned
+ * object remains valid at least until AtEOXact_SMgr() is called, or until
+ * smgrdestroy() is called in non-transaction backends.
  */
 SMgrRelation
 smgropen(RelFileLocator rlocator, BackendId backend)
@@ -259,10 +261,10 @@ smgrexists(SMgrRelation reln, ForkNumber forknum)
 }
 
 /*
- * smgrclose() -- Close and delete an SMgrRelation object.
+ * smgrdestroy() -- Delete an SMgrRelation object.
  */
 void
-smgrclose(SMgrRelation reln)
+smgrdestroy(SMgrRelation reln)
 {
 	SMgrRelation *owner;
 	ForkNumber	forknum;
@@ -289,12 +291,14 @@ smgrclose(SMgrRelation reln)
 }
 
 /*
- * smgrrelease() -- Release all resources used by this object.
+ * smgrclose() -- Release all resources used by this object.
  *
- * The object remains valid.
+ * The object remains valid, but is moved to the unknown list where it will
+ * be destroyed by AtEOXact_SMgr().  It may be re-owned if it is accessed by a
+ * relation before then.
  */
 void
-smgrrelease(SMgrRelation reln)
+smgrclose(SMgrRelation reln)
 {
 	for (ForkNumber forknum = 0; forknum <= MAX_FORKNUM; forknum++)
 	{
@@ -302,15 +306,20 @@ smgrrelease(SMgrRelation reln)
 		reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber;
 	}
 	reln->smgr_targblock = InvalidBlockNumber;
+
+	if (reln->smgr_owner)
+	{
+		*reln->smgr_owner = NULL;
+		reln->smgr_owner = NULL;
+		dlist_push_tail(&unowned_relns, &reln->node);
+	}
 }
 
 /*
- * smgrreleaseall() -- Release resources used by all objects.
- *
- * This is called for PROCSIGNAL_BARRIER_SMGRRELEASE.
+ * smgrcloseall() -- Close all objects.
  */
 void
-smgrreleaseall(void)
+smgrcloseall(void)
 {
 	HASH_SEQ_STATUS status;
 	SMgrRelation reln;
@@ -322,14 +331,17 @@ smgrreleaseall(void)
 	hash_seq_init(&status, SMgrRelationHash);
 
 	while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
-		smgrrelease(reln);
+		smgrclose(reln);
 }
 
 /*
- * smgrcloseall() -- Close all existing SMgrRelation objects.
+ * smgrdestroyall() -- Destroy all SMgrRelation objects.
+ *
+ * It must be known that there are no pointers to SMgrRelations, other than
+ * those registered with smgrsetowner().
  */
 void
-smgrcloseall(void)
+smgrdestroyall(void)
 {
 	HASH_SEQ_STATUS status;
 	SMgrRelation reln;
@@ -341,7 +353,7 @@ smgrcloseall(void)
 	hash_seq_init(&status, SMgrRelationHash);
 
 	while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
-		smgrclose(reln);
+		smgrdestroy(reln);
 }
 
 /*
@@ -733,7 +745,8 @@ smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
  * AtEOXact_SMgr
  *
  * This routine is called during transaction commit or abort (it doesn't
- * particularly care which).  All transient SMgrRelation objects are closed.
+ * particularly care which).  All transient SMgrRelation objects are
+ * destroyed.
  *
  * We do this as a compromise between wanting transient SMgrRelations to
  * live awhile (to amortize the costs of blind writes of multiple blocks)
@@ -747,7 +760,7 @@ AtEOXact_SMgr(void)
 	dlist_mutable_iter iter;
 
 	/*
-	 * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
+	 * Zap all unowned SMgrRelations.  We rely on smgrdestroy() to remove each
 	 * one from the list.
 	 */
 	dlist_foreach_modify(iter, &unowned_relns)
@@ -757,7 +770,7 @@ AtEOXact_SMgr(void)
 
 		Assert(rel->smgr_owner == NULL);
 
-		smgrclose(rel);
+		smgrdestroy(rel);
 	}
 }
 
@@ -768,6 +781,6 @@ AtEOXact_SMgr(void)
 bool
 ProcessBarrierSmgrRelease(void)
 {
-	smgrreleaseall();
+	smgrcloseall();
 	return true;
 }
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d3353..a38f1acb37a 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,18 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+extern Buffer PrepareReadBuffer(BufferManagerRelation bmr,
+								ForkNumber forkNum,
+								BlockNumber blockNum,
+								BufferAccessStrategy strategy,
+								bool *foundPtr);
+extern void CompleteReadBuffers(BufferManagerRelation bmr,
+								Buffer *buffers,
+								ForkNumber forknum,
+								BlockNumber blocknum,
+								int nblocks,
+								bool zero_on_error,
+								BufferAccessStrategy strategy);
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -247,9 +265,13 @@ extern void LockBufferForCleanup(Buffer buffer);
 extern bool ConditionalLockBufferForCleanup(Buffer buffer);
 extern bool IsBufferCleanupOK(Buffer buffer);
 extern bool HoldingBufferPinThatDelaysRecovery(void);
+extern void ZeroBuffer(Buffer buffer, ReadBufferMode mode);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 527cd2a0568..d8ffe397faf 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -85,8 +85,8 @@ extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln);
 extern void smgrclose(SMgrRelation reln);
 extern void smgrcloseall(void);
 extern void smgrcloserellocator(RelFileLocatorBackend rlocator);
-extern void smgrrelease(SMgrRelation reln);
-extern void smgrreleaseall(void);
+extern void smgrdestroy(SMgrRelation reln);
+extern void smgrdestroyall(void);
 extern void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
 extern void smgrdosyncall(SMgrRelation *rels, int nrels);
 extern void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 00000000000..40c3408c541
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,45 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index a584b1ddff3..6636cc82c09 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -561,12 +561,6 @@ typedef struct ViewOptions
  *
  * Very little code is authorized to touch rel->rd_smgr directly.  Instead
  * use this function to fetch its value.
- *
- * Note: since a relcache flush can cause the file handle to be closed again,
- * it's unwise to hold onto the pointer returned by this function for any
- * long period.  Recommended practice is to just re-execute RelationGetSmgr
- * each time you need to access the SMgrRelation.  It's quite cheap in
- * comparison to whatever an smgr function is going to do.
  */
 static inline SMgrRelation
 RelationGetSmgr(Relation rel)
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 91433d439b7..8007f17320a 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2094,6 +2094,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
-- 
2.37.2

v2-0010-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-patch; charset=US-ASCII; name=v2-0010-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From 0ee5aaf02cd59bec3f42a319d37f7b8755a53554 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v2 10/13] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 27 ++++++---------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 0f4850065fb..f711c056143 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,21 +40,12 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "nodes/bitmapset.h"
 #include "nodes/tidbitmap.h"
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -66,7 +57,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -78,7 +69,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -180,7 +171,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -389,7 +380,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -691,12 +682,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1470,8 +1456,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..432fae52962 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.37.2

v2-0013-BitmapHeapScan-uses-streaming-read-API.patchtext/x-patch; charset=US-ASCII; name=v2-0013-BitmapHeapScan-uses-streaming-read-API.patchDownload
From 9473ddcf05c4c3142fbc3fbc2371df2b8a8113e8 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:04:18 -0500
Subject: [PATCH v2 13/13] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
---
 src/backend/access/heap/heapam.c          |  68 +++++
 src/backend/access/heap/heapam_handler.c  |  88 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 343 +---------------------
 src/include/access/heapam.h               |   4 +
 src/include/access/tableam.h              |  14 +-
 src/include/nodes/execnodes.h             |  19 --
 6 files changed, 117 insertions(+), 419 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b93f243c282..c965048af60 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -115,6 +115,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -335,6 +337,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -955,6 +973,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
 
@@ -1093,6 +1112,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10250,3 +10272,49 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (hdesc->rs_base.shared_tbmiterator)
+			tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+		else
+			tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ba6793a749c..53812584774 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2113,79 +2113,65 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno)
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (scan->shared_tbmiterator)
-			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
-		else
-			tbm_iterate(scan->tbmiterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API will
+		 * only return TBMIterateResults for blocks actually fetched. When we
+		 * skip fetching a block, we keep track of how many empty tuples to
+		 * emit at the end of the BitmapHeapScan. We do not recheck all NULL
+		 * tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, and the bitmap entries don't need rechecking, and all tuples on
-	 * the page are visible to our transaction.
-	 */
-	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2206,7 +2192,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2215,9 +2201,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2270,7 +2256,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/* Only count exact and lossy pages with visible tuples */
 	if (ntup > 0)
 	{
-		if (tbmres.ntuples >= 0)
+		if (tbmres->ntuples >= 0)
 			scan->exact_pages++;
 		else
 			scan->lossy_pages++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 284641fa8ea..128621f1306 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -56,11 +56,6 @@ static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapAccumCounters(BitmapHeapScanState *node,
 									   TableScanDesc scan);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -91,14 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -114,15 +101,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
 		}
 		else
 		{
@@ -145,20 +123,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
 
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
@@ -166,14 +130,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		if (!scan)
@@ -216,47 +172,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		node->initialized = true;
 
 		/* Get the first block. if none, end of scan */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck))
 			return ExecClearTuple(slot);
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		BitmapAdjustPrefetchTarget(node);
 	}
 
-	for (;;)
+	do
 	{
 		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We prefetch before fetching the current pages. We expect that a
-			 * future streaming read API will do this, so do it now for
-			 * consistency.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -278,13 +203,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			return slot;
 		}
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
-			break;
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
-	}
+	} while (table_scan_bitmap_next_block(scan, &node->recheck));
 
 	/*
 	 * if we get here it means we are at the end of the scan..
@@ -318,221 +237,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult tbmpre;
-			tbm_iterate(prefetch_iterator, &tbmpre);
-
-			if (!BlockNumberIsValid(tbmpre.blockno) || tbmpre.blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
-		}
-		return;
-	}
-
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			TBMIterateResult tbmpre;
-
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
-				 */
-
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -578,22 +282,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -632,16 +326,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -674,19 +362,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -726,13 +408,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -816,14 +491,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -855,11 +526,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3dfb19ec7d5..1cad9c04f01 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ef1fcc02b1a..56683f9e4aa 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -795,17 +795,10 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, BlockNumber *blockno);
+	bool		(*scan_bitmap_next_block) (TableScanDesc scan, bool *recheck);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1982,8 +1975,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno)
+table_scan_bitmap_next_block(TableScanDesc scan, bool *recheck)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1993,7 +1985,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, blockno);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a59df51dd69..d41a3e134d8 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1682,11 +1682,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  *		phs_snapshot_data		snapshot data shared to workers
@@ -1695,10 +1692,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 	char		phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
@@ -1709,16 +1703,10 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
  *		recheck			   do current page's tuples need recheck
@@ -1729,20 +1717,13 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
 	bool		recheck;
-	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v2-0008-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-patch; charset=US-ASCII; name=v2-0008-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchDownload
From 8632e2b57bd4b532e5cbe94df89f2c1123fed62c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v2 08/13] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3b89e7e6c63..c62f978f5d7 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -76,8 +76,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -90,10 +88,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -110,6 +104,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -118,7 +115,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -171,8 +168,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -218,6 +214,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -231,9 +229,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.37.2

v2-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-patch; charset=US-ASCII; name=v2-0009-Make-table_scan_bitmap_next_block-async-friendly.patchDownload
From 59fdb0423ddc9032380247f987b682944a52d476 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:57:07 -0500
Subject: [PATCH v2 09/13] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the known end of the table when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API. The table AMs will implement a streaming read API callback
that returns the next block that needs to be fetched. In heap AM's case,
the callback will use the iterator to find the next block to be fetched.
Since choosing the next block will no longer the responsibility of
BitmapHeapNext(), the streaming read control flow requires these changes
to table_scan_bitmap_next_block().
---
 src/backend/access/heap/heapam_handler.c  |  58 +++++++--
 src/backend/executor/nodeBitmapHeapscan.c | 148 ++++++++--------------
 src/include/access/relscan.h              |   5 +
 src/include/access/tableam.h              |  47 +++++--
 src/include/nodes/execnodes.h             |  11 +-
 5 files changed, 145 insertions(+), 124 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3af9466b9ca..c8da3def645 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,17 +2114,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  bool *recheck, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, and the bitmap entries don't need rechecking, and all tuples on
@@ -2143,16 +2177,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2251,7 +2276,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 			scan->lossy_pages++;
 	}
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c62f978f5d7..ae837785116 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -76,7 +76,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -88,7 +87,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -116,7 +114,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -169,7 +166,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -214,46 +210,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		/* Get the first block. if none, end of scan */
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+			return ExecClearTuple(slot);
+
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -275,49 +249,41 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
-		 */
-		BitmapPrefetch(node, scan);
-
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
-		}
+			/*
+			 * We prefetch before fetching the current pages. We expect that a
+			 * future streaming read API will do this, so do it now for
+			 * consistency.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
-		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
 			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
 			}
+
+			/* OK to return this tuple */
+			BitmapAccumCounters(node, scan);
+			return slot;
 		}
 
-		/* OK to return this tuple */
-		BitmapAccumCounters(node, scan);
-		return slot;
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+			break;
+
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -608,12 +574,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -621,13 +583,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -658,28 +619,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -712,8 +669,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -722,10 +677,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b74e08dd745..5dea9c7a03d 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -41,6 +44,8 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
 	long		exact_pages;
 	long		lossy_pages;
 
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a3e30c4eda7..ef1fcc02b1a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -804,7 +805,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   bool *recheck, BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -948,6 +949,8 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->lossy_pages = 0;
 	result->exact_pages = 0;
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
 	return result;
 }
 
@@ -1008,6 +1011,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1018,6 +1036,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1941,17 +1974,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 bool *recheck, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1961,8 +1993,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 9392923eb32..a59df51dd69 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1709,9 +1709,7 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1720,10 +1718,10 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
+ *		recheck			   do current page's tuples need recheck
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1731,8 +1729,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1742,10 +1738,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
+	bool		recheck;
+	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v2-0003-BitmapHeapScan-begin-scan-after-bitmap-setup.patchtext/x-patch; charset=US-ASCII; name=v2-0003-BitmapHeapScan-begin-scan-after-bitmap-setup.patchDownload
From 6cfa8fee46a83936789062eedc37d0c06b59dc46 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v2 03/13] BitmapHeapScan begin scan after bitmap setup

There is no reason for table_beginscan_bm() to begin the actual scan of
the underlying table in ExecInitBitmapHeapScan(). We can begin the
underlying table scan after the index scan has been completed and the
bitmap built.

The one use of the scan descriptor during initialization was
ExecBitmapHeapInitializeWorker(), which set the scan descriptor snapshot
with one from an array in the parallel state. This overwrote the
snapshot set in table_beginscan_bm().

By saving that worker snapshot as a member in the BitmapHeapScanState
during initialization, it can be restored in table_beginscan_bm() after
returning from the table AM specific begin scan function.
---
 src/backend/access/table/tableam.c        | 11 ------
 src/backend/executor/nodeBitmapHeapscan.c | 43 +++++++++++++++++------
 src/include/access/tableam.h              | 10 ++----
 src/include/nodes/execnodes.h             |  2 ++
 4 files changed, 38 insertions(+), 28 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 6ed8cca05a1..e78d793f69c 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,17 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-void
-table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot)
-{
-	Assert(IsMVCCSnapshot(snapshot));
-
-	RegisterSnapshot(snapshot);
-	scan->rs_snapshot = snapshot;
-	scan->rs_flags |= SO_TEMP_SNAPSHOT;
-}
-
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 76382c91fd7..be08bd785ae 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -191,6 +191,30 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		if (!scan)
+		{
+			Snapshot	snapshot = node->ss.ps.state->es_snapshot;
+			uint32		extra_flags = 0;
+
+			/*
+			 * Parallel workers must use the snapshot initialized by the
+			 * parallel leader.
+			 */
+			if (node->worker_snapshot)
+			{
+				snapshot = node->worker_snapshot;
+				extra_flags |= SO_TEMP_SNAPSHOT;
+			}
+
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	snapshot,
+																	0,
+																	NULL,
+																	extra_flags);
+		}
+
 		node->initialized = true;
 	}
 
@@ -614,7 +638,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -691,7 +716,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -740,6 +767,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->can_skip_fetch = false;
+	scanstate->worker_snapshot = NULL;
 
 	/*
 	 * Miscellaneous initialization
@@ -788,11 +816,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
@@ -931,13 +954,13 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 							   ParallelWorkerContext *pwcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	Snapshot	snapshot;
 
 	Assert(node->ss.ps.state->es_query_dsa != NULL);
 
 	pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
 	node->pstate = pstate;
 
-	snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
-	table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
+	node->worker_snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
+	Assert(IsMVCCSnapshot(node->worker_snapshot));
+	RegisterSnapshot(node->worker_snapshot);
 }
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 4d495216f07..8ef6b5ca25b 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -939,9 +939,10 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key,
+				   uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
@@ -1033,11 +1034,6 @@ table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
 										 allow_pagemode);
 }
 
-/*
- * Update snapshot used by the scan.
- */
-extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
-
 /*
  * Return next tuple from `scan`, store in slot.
  */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 444a5f0fd57..00c75fb10e2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1726,6 +1726,7 @@ typedef struct ParallelBitmapHeapState
  *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		worker_snapshot	   snapshot for parallel worker
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1750,6 +1751,7 @@ typedef struct BitmapHeapScanState
 	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	Snapshot	worker_snapshot;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v2-0001-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-patch; charset=US-ASCII; name=v2-0001-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchDownload
From 575fb1f93128ebfd8125c769de628f91e0d5c592 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v2 01/13] Remove table_scan_bitmap_next_tuple parameter tbmres

Future commits will remove the input TBMIterateResult from
table_scan_bitmap_next_block() as the streaming read API will be
responsible for iterating through the blocks in the bitmap and not
BitmapHeapNext(). Given that this parameter will not be set from
BitmapHeapNext(), it no longer makes sense to use it as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().
---
 src/backend/access/heap/heapam_handler.c  | 1 -
 src/backend/executor/nodeBitmapHeapscan.c | 2 +-
 src/include/access/tableam.h              | 7 -------
 3 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d15a02b2be7..716d477e271 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2228,7 +2228,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c1e81ebed63..d670939246b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -304,7 +304,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Attempt to fetch tuple from AM.
 			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			if (!table_scan_bitmap_next_tuple(scan, slot))
 			{
 				/* nothing more to look at on this page */
 				node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5f8474871d2..4d495216f07 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -810,15 +810,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -1980,7 +1975,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -1992,7 +1986,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.37.2

v2-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-patch; charset=US-ASCII; name=v2-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchDownload
From 2a11dc5ef62408bb455277eb73c83abc8f9d2bf3 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v2 04/13] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be08bd785ae..c6dfdf8cae9 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -532,7 +532,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * but is true in many cases.
 				 */
 				skip_fetch = (node->can_skip_fetch &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -583,7 +583,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (node->can_skip_fetch &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.37.2

v2-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-patch; charset=US-ASCII; name=v2-0002-BitmapHeapScan-set-can_skip_fetch-later.patchDownload
From 5f915bc84eae56e52b5a61e9b7e691834fdb9680 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v2 02/13] BitmapHeapScan set can_skip_fetch later

There is no reason for BitmapHeapScan to calculate can_skip_fetch in
ExecInitBitmapHeapScan(). Moving it into BitmapHeapNext() is a
preliminary step toward moving can_skip_fetch into table AM specific
code, as we would need to set it after the scan has begun.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d670939246b..76382c91fd7 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,6 +108,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -729,16 +739,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.37.2

v2-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-patch; charset=US-ASCII; name=v2-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchDownload
From d578ca2c47857794622c49319087f53918fe4c6c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v2 05/13] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c6dfdf8cae9..07a218ec03e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -55,7 +55,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -239,7 +239,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			/*
 			 * We can skip fetching the heap page if we don't need any fields
@@ -392,7 +392,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -411,7 +411,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.37.2

v2-0007-BitmapHeapScan-scan-desc-counts-lossy-and-exact-p.patchtext/x-patch; charset=US-ASCII; name=v2-0007-BitmapHeapScan-scan-desc-counts-lossy-and-exact-p.patchDownload
From 224a7e4e8eb7106c1e7159df8ca3d7ede6732be8 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:05:04 -0500
Subject: [PATCH v2 07/13] BitmapHeapScan scan desc counts lossy and exact
 pages

Future commits will remove the TBMIterateResult from BitmapHeapNext(),
pushing it into the table AM-specific code. So we will have to keep
track of the number of lossy and exact pages in the scan descriptor.
Doing this change to lossy/exact page counting in a separate commit just
simplifies the diff.
---
 src/backend/access/heap/heapam_handler.c  |  9 +++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 19 ++++++++++++++-----
 src/include/access/relscan.h              |  4 ++++
 src/include/access/tableam.h              |  6 +++++-
 4 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d775756fa53..3af9466b9ca 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2242,6 +2242,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	/* Only count exact and lossy pages with visible tuples */
+	if (ntup > 0)
+	{
+		if (tbmres->ntuples >= 0)
+			scan->exact_pages++;
+		else
+			scan->lossy_pages++;
+	}
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c884771e826..3b89e7e6c63 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,6 +53,8 @@
 #include "utils/spccache.h"
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
+static inline void BitmapAccumCounters(BitmapHeapScanState *node,
+									   TableScanDesc scan);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 												BlockNumber blockno);
@@ -246,11 +248,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				continue;
 			}
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
 			/* Adjust the prefetch target */
 			BitmapAdjustPrefetchTarget(node);
 		}
@@ -321,15 +318,27 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		}
 
 		/* OK to return this tuple */
+		BitmapAccumCounters(node, scan);
 		return slot;
 	}
 
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
+	BitmapAccumCounters(node, scan);
 	return ExecClearTuple(slot);
 }
 
+static inline void
+BitmapAccumCounters(BitmapHeapScanState *node,
+					TableScanDesc scan)
+{
+	node->exact_pages += scan->exact_pages;
+	scan->exact_pages = 0;
+	node->lossy_pages += scan->lossy_pages;
+	scan->lossy_pages = 0;
+}
+
 /*
  *	BitmapDoneInitializingSharedState - Shared state is initialized
  *
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..b74e08dd745 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -40,6 +40,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	long		exact_pages;
+	long		lossy_pages;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b5d65a9528c..a3e30c4eda7 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -942,9 +942,13 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key,
 				   uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->lossy_pages = 0;
+	result->exact_pages = 0;
+	return result;
 }
 
 /*
-- 
2.37.2

v2-0006-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-patch; charset=US-ASCII; name=v2-0006-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchDownload
From 9104d9c36462119a1875d7620b21d37b994216f9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v2 06/13] Push BitmapHeapScan skip fetch optimization into
 table AM

This resolves the FIXME in BitmapHeapNext() which said that the
optmization to skip fetching blocks of the underlying table when none of
the column data was needed should be pushed into the table AM specific
code.

heapam_scan_bitmap_next_block() now does the visibility check and
accounting of empty tuples to be returned; while
heapam_scan_bitmap_next_tuple() prepares the slot to return empty
tuples.

The table AM agnostic functions for prefetching still need to know if
skipping fetching is permitted for this scan. However, this dependency
will be removed when that prefetching code is removed in favor of the
upcoming streaming read API.
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 ++++++
 src/backend/executor/nodeBitmapHeapscan.c | 115 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  18 ++--
 src/include/nodes/execnodes.h             |   6 --
 6 files changed, 95 insertions(+), 97 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 707460a5364..b93f243c282 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -955,6 +955,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1043,6 +1045,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1062,6 +1070,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 716d477e271..d775756fa53 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2124,6 +2125,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, and the bitmap entries don't need rechecking, and all tuples on
+	 * the page are visible to our transaction.
+	 */
+	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2235,6 +2254,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 07a218ec03e..c884771e826 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,16 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -207,6 +197,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				extra_flags |= SO_TEMP_SNAPSHOT;
 			}
 
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual == NIL && node->ss.ps.plan->targetlist == NIL)
+				extra_flags |= SO_CAN_SKIP_FETCH;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	snapshot,
@@ -220,8 +221,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -241,32 +240,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -320,46 +294,30 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -531,7 +489,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -582,7 +541,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -652,8 +611,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -663,7 +620,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -708,8 +664,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -753,8 +707,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -766,7 +718,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 	scanstate->worker_snapshot = NULL;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f68593..3dfb19ec7d5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8ef6b5ca25b..b5d65a9528c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed.
+	 */
+	SO_CAN_SKIP_FETCH = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -780,10 +787,8 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time). All work
+	 * referencing `tbmres` must be done here.
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -795,11 +800,6 @@ typedef struct TableAmRoutine
 	 * performs prefetching directly using that interface.  This probably
 	 * needs to be rectified at a later point.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 00c75fb10e2..9392923eb32 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1711,9 +1711,6 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
  *		pvmbuffer		   ditto, for prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1736,9 +1733,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.37.2

#7Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#6)
13 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

In the attached v3, I've reordered the commits, updated some errant
comments, and improved the commit messages.

I've also made some updates to the TIDBitmap API that seem like a
clarity improvement to the API in general. These also reduce the diff
for GIN when separating the TBMIterateResult from the
TBM[Shared]Iterator. And these TIDBitmap API changes are now all in
their own commits (previously those were in the same commit as adding
the BitmapHeapScan streaming read user).

The three outstanding issues I see in the patch set are:
1) the lossy and exact page counters issue described in my previous
email
2) the TODO in the TIDBitmap API changes about being sure that setting
TBMIterateResult->blockno to InvalidBlockNumber is sufficient for
indicating an invalid TBMIterateResult (and an exhausted bitmap)
3) the streaming read API is not committed yet, so the last two patches
are not "done"

- Melanie

Attachments:

v3-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From e0cee301b81400209a0e727a3d7daa1f435ba999 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v3 01/13] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.

ExecBitmapHeapInitializeWorker() overwrote the snapshot in the scan
descriptor with the correct one provided by the parallel leader. Since
ExecBitmapHeapInitializeWorker() is now called before the scan
descriptor has been created, save the worker's snapshot in the
BitmapHeapScanState and pass it to table_beginscan_bm().
---
 src/backend/access/table/tableam.c        | 11 ------
 src/backend/executor/nodeBitmapHeapscan.c | 47 ++++++++++++++++++-----
 src/include/access/tableam.h              | 10 ++---
 src/include/nodes/execnodes.h             |  2 +
 4 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 6ed8cca05a1..e78d793f69c 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,17 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-void
-table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot)
-{
-	Assert(IsMVCCSnapshot(snapshot));
-
-	RegisterSnapshot(snapshot);
-	scan->rs_snapshot = snapshot;
-	scan->rs_flags |= SO_TEMP_SNAPSHOT;
-}
-
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c1e81ebed63..44bf38be3c9 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -181,6 +181,34 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			Snapshot	snapshot = node->ss.ps.state->es_snapshot;
+			uint32		extra_flags = 0;
+
+			/*
+			 * Parallel workers must use the snapshot initialized by the
+			 * parallel leader.
+			 */
+			if (node->worker_snapshot)
+			{
+				snapshot = node->worker_snapshot;
+				extra_flags |= SO_TEMP_SNAPSHOT;
+			}
+
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	snapshot,
+																	0,
+																	NULL,
+																	extra_flags);
+		}
+
 		node->initialized = true;
 	}
 
@@ -604,7 +632,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -681,7 +710,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -739,6 +770,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	 */
 	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
 								 node->scan.plan.targetlist == NIL);
+	scanstate->worker_snapshot = NULL;
 
 	/*
 	 * Miscellaneous initialization
@@ -787,11 +819,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
@@ -930,13 +957,13 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 							   ParallelWorkerContext *pwcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	Snapshot	snapshot;
 
 	Assert(node->ss.ps.state->es_query_dsa != NULL);
 
 	pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
 	node->pstate = pstate;
 
-	snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
-	table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
+	node->worker_snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
+	Assert(IsMVCCSnapshot(node->worker_snapshot));
+	RegisterSnapshot(node->worker_snapshot);
 }
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5f8474871d2..5375dd7150f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -944,9 +944,10 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key,
+				   uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
@@ -1038,11 +1039,6 @@ table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
 										 allow_pagemode);
 }
 
-/*
- * Update snapshot used by the scan.
- */
-extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
-
 /*
  * Return next tuple from `scan`, store in slot.
  */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 444a5f0fd57..00c75fb10e2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1726,6 +1726,7 @@ typedef struct ParallelBitmapHeapState
  *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		worker_snapshot	   snapshot for parallel worker
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1750,6 +1751,7 @@ typedef struct BitmapHeapScanState
 	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	Snapshot	worker_snapshot;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v3-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 69cd001bcdade976a51985e714d1b30b090bb388 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v3 02/13] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 44bf38be3c9..a9ba2bdfb88 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,6 +108,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -760,16 +770,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 	scanstate->worker_snapshot = NULL;
 
 	/*
-- 
2.37.2

v3-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-diff; charset=us-asciiDownload
From b29df9592f8b3a3966cf6fab40f56a0c113f3d57 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v3 03/13] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 ++++++
 src/backend/executor/nodeBitmapHeapscan.c | 118 ++++++----------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |   7 ++
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 94 insertions(+), 92 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 707460a5364..b93f243c282 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -955,6 +955,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1043,6 +1045,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1062,6 +1070,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d15a02b2be7..7661acac3a8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2124,6 +2125,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, and the bitmap entries don't need rechecking, and all tuples on
+	 * the page are visible to our transaction.
+	 */
+	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2236,6 +2255,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a9ba2bdfb88..2e4f87ea3a3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,16 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -211,6 +201,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				extra_flags |= SO_TEMP_SNAPSHOT;
 			}
 
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual == NIL && node->ss.ps.plan->targetlist == NIL)
+				extra_flags |= SO_CAN_SKIP_FETCH;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	snapshot,
@@ -224,8 +225,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -245,32 +244,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -318,52 +292,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -535,7 +490,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -586,7 +542,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -656,8 +612,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -667,7 +621,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -712,8 +665,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -757,8 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -770,7 +719,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 	scanstate->worker_snapshot = NULL;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f68593..3dfb19ec7d5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5375dd7150f..c193ea5db43 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed.
+	 */
+	SO_CAN_SKIP_FETCH = 1 << 10,
 }			ScanOptions;
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 00c75fb10e2..6fb4ec07c5f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1711,10 +1711,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1736,9 +1733,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.37.2

v3-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-diff; charset=us-asciiDownload
From 17fc9d4c35e42b6e870b7e7f7c3495114e393e8a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v3 04/13] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2e4f87ea3a3..35ef26221ba 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -484,15 +484,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
-
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -543,7 +537,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.37.2

v3-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-diff; charset=us-asciiDownload
From 67a9fb1848718cabfcfd5c98368ab2aa79a6b213 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v3 05/13] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 35ef26221ba..3439c02e989 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -55,7 +55,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -242,7 +242,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
@@ -351,7 +351,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -370,7 +370,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.37.2

v3-0006-BitmapHeapScan-scan-desc-counts-lossy-and-exact-p.patchtext/x-diff; charset=us-asciiDownload
From efbb311eddc765dd761154e1460e337fc2d29323 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:05:04 -0500
Subject: [PATCH v3 06/13] BitmapHeapScan scan desc counts lossy and exact
 pages

Future commits will remove the TBMIterateResult from BitmapHeapNext(),
pushing it into the table AM-specific code. So we will have to keep
track of the number of lossy and exact pages in the scan descriptor.
Doing this change to lossy/exact page counting in a separate commit just
simplifies the diff.
---
 src/backend/access/heap/heapam_handler.c  |  9 +++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 19 ++++++++++++++-----
 src/include/access/relscan.h              |  4 ++++
 src/include/access/tableam.h              |  6 +++++-
 4 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7661acac3a8..9fc99a87fdf 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2242,6 +2242,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	/* Only count exact and lossy pages with visible tuples */
+	if (ntup > 0)
+	{
+		if (tbmres->ntuples >= 0)
+			scan->exact_pages++;
+		else
+			scan->lossy_pages++;
+	}
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3439c02e989..eee90b8785b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,6 +53,8 @@
 #include "utils/spccache.h"
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
+static inline void BitmapAccumCounters(BitmapHeapScanState *node,
+									   TableScanDesc scan);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 												BlockNumber blockno);
@@ -250,11 +252,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				continue;
 			}
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
 			/* Adjust the prefetch target */
 			BitmapAdjustPrefetchTarget(node);
 		}
@@ -322,15 +319,27 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		}
 
 		/* OK to return this tuple */
+		BitmapAccumCounters(node, scan);
 		return slot;
 	}
 
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
+	BitmapAccumCounters(node, scan);
 	return ExecClearTuple(slot);
 }
 
+static inline void
+BitmapAccumCounters(BitmapHeapScanState *node,
+					TableScanDesc scan)
+{
+	node->exact_pages += scan->exact_pages;
+	scan->exact_pages = 0;
+	node->lossy_pages += scan->lossy_pages;
+	scan->lossy_pages = 0;
+}
+
 /*
  *	BitmapDoneInitializingSharedState - Shared state is initialized
  *
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..b74e08dd745 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -40,6 +40,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	long		exact_pages;
+	long		lossy_pages;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index c193ea5db43..7dfb291800c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -954,9 +954,13 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key,
 				   uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->lossy_pages = 0;
+	result->exact_pages = 0;
+	return result;
 }
 
 /*
-- 
2.37.2

v3-0007-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-diff; charset=us-asciiDownload
From e42eea35eb863303eb0a914b96fe33103e3afcd9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v3 07/13] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index eee90b8785b..a0fe65fde58 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -76,8 +76,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -90,10 +88,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -110,6 +104,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -118,7 +115,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -171,8 +168,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -222,6 +218,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -235,9 +233,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.37.2

v3-0008-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-diff; charset=us-asciiDownload
From eee14d6a4cd7191201b158ed77e79abbefe6349f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v3 08/13] Remove table_scan_bitmap_next_tuple parameter tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 9fc99a87fdf..3af9466b9ca 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2256,7 +2256,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a0fe65fde58..b4333184576 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -293,7 +293,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 7dfb291800c..2dc79583bcf 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -787,10 +787,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -817,15 +814,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -1987,7 +1979,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -1999,7 +1990,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.37.2

v3-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From d579faa35292c4d3730a7fd112606fc419b7886a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:57:07 -0500
Subject: [PATCH v3 09/13] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  58 +++++++--
 src/backend/executor/nodeBitmapHeapscan.c | 148 ++++++++--------------
 src/include/access/relscan.h              |   5 +
 src/include/access/tableam.h              |  58 ++++++---
 src/include/nodes/execnodes.h             |   9 +-
 5 files changed, 150 insertions(+), 128 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3af9466b9ca..c8da3def645 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,17 +2114,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  bool *recheck, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, and the bitmap entries don't need rechecking, and all tuples on
@@ -2143,16 +2177,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2251,7 +2276,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 			scan->lossy_pages++;
 	}
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b4333184576..9109e8ddddf 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -76,7 +76,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -88,7 +87,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -116,7 +114,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -169,7 +166,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -218,46 +214,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		/* Get the first block. if none, end of scan */
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+			return ExecClearTuple(slot);
+
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -279,46 +253,44 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
-
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
-		}
+			/*
+			 * We prefetch before fetching the current pages. We expect that a
+			 * future streaming read API will do this, so do it this way now
+			 * for consistency. Also, this should happen only when we have
+			 * determined there is still something to do on the current page,
+			 * else we may uselessly prefetch the same page we are just about
+			 * to request for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
-		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
 			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
 			}
+
+			/* OK to return this tuple */
+			BitmapAccumCounters(node, scan);
+			return slot;
 		}
 
-		/* OK to return this tuple */
-		BitmapAccumCounters(node, scan);
-		return slot;
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+			break;
+
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -603,12 +575,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -616,13 +584,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -653,28 +620,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -707,8 +670,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -717,10 +678,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b74e08dd745..5dea9c7a03d 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -41,6 +44,8 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
 	long		exact_pages;
 	long		lossy_pages;
 
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2dc79583bcf..f1f5b7ab1d0 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -780,19 +781,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -808,7 +804,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   bool *recheck, BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -952,6 +948,8 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->lossy_pages = 0;
 	result->exact_pages = 0;
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
 	return result;
 }
 
@@ -1012,6 +1010,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1022,6 +1035,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1945,17 +1973,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 bool *recheck, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1965,8 +1992,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6fb4ec07c5f..a59df51dd69 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1709,8 +1709,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1720,10 +1718,10 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
+ *		recheck			   do current page's tuples need recheck
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1731,8 +1729,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1742,10 +1738,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
+	bool		recheck;
+	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v3-0010-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From c2ba82cb19d21f79090598b81aee3184cd45a654 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v3 10/13] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 29 +++++++----------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 0f4850065fb..689a959b467 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,21 +40,12 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "nodes/bitmapset.h"
 #include "nodes/tidbitmap.h"
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -66,7 +57,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -78,7 +69,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -180,7 +171,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -221,7 +212,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -389,7 +380,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -691,12 +682,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1470,8 +1456,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..432fae52962 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.37.2

v3-0011-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchtext/x-diff; charset=us-asciiDownload
From 3f763a0fb8b16a84ef666cd9086402cb01171fab Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v3 11/13] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 33 +++++-----
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 7 files changed, 107 insertions(+), 87 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3aa457a29e1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..033d5253394 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c8da3def645..ba6793a749c 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2121,7 +2121,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2134,11 +2134,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		CHECK_FOR_INTERRUPTS();
 
 		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbm_iterate(scan->tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2153,11 +2153,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2165,19 +2165,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * the page are visible to our transaction.
 	 */
 	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2206,7 +2206,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2215,9 +2215,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2270,7 +2270,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/* Only count exact and lossy pages with visible tuples */
 	if (ntup > 0)
 	{
-		if (tbmres->ntuples >= 0)
+		if (tbmres.ntuples >= 0)
 			scan->exact_pages++;
 		else
 			scan->lossy_pages++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 9109e8ddddf..bcc60d3cf98 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -347,9 +347,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+			TBMIterateResult tbmpre;
+			tbm_iterate(prefetch_iterator, &tbmpre);
 
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
+			if (!BlockNumberIsValid(tbmpre.blockno) || tbmpre.blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
@@ -367,6 +368,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		}
 		else
 		{
+			TBMIterateResult tbmpre;
+
 			/* Release the mutex before iterating */
 			SpinLockRelease(&pstate->mutex);
 
@@ -379,7 +382,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -446,10 +449,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
@@ -465,13 +470,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -486,7 +491,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -505,8 +510,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_shared_iterate(prefetch_iterator);
@@ -516,13 +521,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 689a959b467..b4dcb1cbb88 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -171,7 +171,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -212,7 +211,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -943,20 +941,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -984,6 +983,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -994,11 +994,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1014,16 +1014,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1033,10 +1034,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1087,13 +1087,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1103,21 +1103,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 51d0c74a6b0..e423d92b41c 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae52962..f000c1af28f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.37.2

v3-0012-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From 6b9989da160c8a96a8e70ae276796b460c205ff0 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 22 Jul 2023 17:31:54 +1200
Subject: [PATCH v3 12/13] Streaming Read API

---
 contrib/pg_prewarm/pg_prewarm.c          |  40 +-
 src/backend/access/transam/xlogutils.c   |   2 +-
 src/backend/postmaster/bgwriter.c        |   8 +-
 src/backend/postmaster/checkpointer.c    |  15 +-
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 435 ++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 560 +++++++++++++++--------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/backend/storage/smgr/smgr.c          |  49 +-
 src/include/storage/bufmgr.h             |  22 +
 src/include/storage/smgr.h               |   4 +-
 src/include/storage/streaming_read.h     |  45 ++
 src/include/utils/rel.h                  |   6 -
 src/tools/pgindent/typedefs.list         |   2 +
 17 files changed, 986 insertions(+), 238 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/contrib/pg_prewarm/pg_prewarm.c b/contrib/pg_prewarm/pg_prewarm.c
index 8541e4d6e46..9617bf130bd 100644
--- a/contrib/pg_prewarm/pg_prewarm.c
+++ b/contrib/pg_prewarm/pg_prewarm.c
@@ -20,6 +20,7 @@
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
 #include "storage/smgr.h"
+#include "storage/streaming_read.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -38,6 +39,25 @@ typedef enum
 
 static PGIOAlignedBlock blockbuffer;
 
+struct pg_prewarm_streaming_read_private
+{
+	BlockNumber blocknum;
+	int64		last_block;
+};
+
+static BlockNumber
+pg_prewarm_streaming_read_next(PgStreamingRead *pgsr,
+							   void *pgsr_private,
+							   void *per_buffer_data)
+{
+	struct pg_prewarm_streaming_read_private *p = pgsr_private;
+
+	if (p->blocknum <= p->last_block)
+		return p->blocknum++;
+
+	return InvalidBlockNumber;
+}
+
 /*
  * pg_prewarm(regclass, mode text, fork text,
  *			  first_block int8, last_block int8)
@@ -183,18 +203,36 @@ pg_prewarm(PG_FUNCTION_ARGS)
 	}
 	else if (ptype == PREWARM_BUFFER)
 	{
+		struct pg_prewarm_streaming_read_private p;
+		PgStreamingRead *pgsr;
+
 		/*
 		 * In buffer mode, we actually pull the data into shared_buffers.
 		 */
+
+		/* Set up the private state for our streaming buffer read callback. */
+		p.blocknum = first_block;
+		p.last_block = last_block;
+
+		pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+											  &p,
+											  0,
+											  NULL,
+											  BMR_REL(rel),
+											  forkNumber,
+											  pg_prewarm_streaming_read_next);
+
 		for (block = first_block; block <= last_block; ++block)
 		{
 			Buffer		buf;
 
 			CHECK_FOR_INTERRUPTS();
-			buf = ReadBufferExtended(rel, forkNumber, block, RBM_NORMAL, NULL);
+			buf = pg_streaming_read_buffer_get_next(pgsr, NULL);
 			ReleaseBuffer(buf);
 			++blocks_done;
 		}
+		Assert(pg_streaming_read_buffer_get_next(pgsr, NULL) == InvalidBuffer);
+		pg_streaming_read_free(pgsr);
 	}
 
 	/* Close relation, release lock. */
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index aa8667abd10..8775b5789be 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -657,7 +657,7 @@ XLogDropDatabase(Oid dbid)
 	 * This is unnecessarily heavy-handed, as it will close SMgrRelation
 	 * objects for other databases as well. DROP DATABASE occurs seldom enough
 	 * that it's not worth introducing a variant of smgrclose for just this
-	 * purpose. XXX: Or should we rather leave the smgr entries dangling?
+	 * purpose.
 	 */
 	smgrcloseall();
 
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index d7d6cc0cd7b..13e5376619e 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -246,10 +246,12 @@ BackgroundWriterMain(void)
 		if (FirstCallSinceLastCheckpoint())
 		{
 			/*
-			 * After any checkpoint, close all smgr files.  This is so we
-			 * won't hang onto smgr references to deleted files indefinitely.
+			 * After any checkpoint, free all smgr objects.  Otherwise we
+			 * would never do so for dropped relations, as the bgwriter does
+			 * not process shared invalidation messages or call
+			 * AtEOXact_SMgr().
 			 */
-			smgrcloseall();
+			smgrdestroyall();
 		}
 
 		/*
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 5e949fc885b..5d843b61426 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -469,10 +469,12 @@ CheckpointerMain(void)
 				ckpt_performed = CreateRestartPoint(flags);
 
 			/*
-			 * After any checkpoint, close all smgr files.  This is so we
-			 * won't hang onto smgr references to deleted files indefinitely.
+			 * After any checkpoint, free all smgr objects.  Otherwise we
+			 * would never do so for dropped relations, as the checkpointer
+			 * does not process shared invalidation messages or call
+			 * AtEOXact_SMgr().
 			 */
-			smgrcloseall();
+			smgrdestroyall();
 
 			/*
 			 * Indicate checkpoint completion to any waiting backends.
@@ -958,11 +960,8 @@ RequestCheckpoint(int flags)
 		 */
 		CreateCheckPoint(flags | CHECKPOINT_IMMEDIATE);
 
-		/*
-		 * After any checkpoint, close all smgr files.  This is so we won't
-		 * hang onto smgr references to deleted files indefinitely.
-		 */
-		smgrcloseall();
+		/* Free all smgr objects, as CheckpointerMain() normally would. */
+		smgrdestroyall();
 
 		return;
 	}
diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca20..eec03f6f2b4 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 00000000000..bcab44c802f
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 00000000000..39aef2a84a2
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 00000000000..19605090fea
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,435 @@
+#include "postgres.h"
+
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ *
+ * For hits, need_to_complete is false and there is just one block per
+ * range, already pinned and ready for use.
+ *
+ * For misses, need_to_complete is true and buffers[] holds a range of
+ * blocks that are contiguous in storage (though the buffers may not be
+ * contiguous in memory), so we can complete them with a single call to
+ * CompleteReadBuffers().
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		advice_issued;
+	bool		need_complete;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index[MAX_BUFFERS_PER_TRANSFER];
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+} PgStreamingReadRange;
+
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			ios_in_progress_trigger;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			pinned_buffers_trigger;
+	int			next_tail_buffer;
+	bool		finished;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	bool		advice_enabled;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+	int			per_buffer_data_next;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+static PgStreamingRead *
+pg_streaming_read_buffer_alloc_internal(int flags,
+										void *pgsr_private,
+										size_t per_buffer_data_size,
+										BufferAccessStrategy strategy)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = maintenance_io_concurrency;
+	else
+		max_ios = effective_io_concurrency;
+
+	/*
+	 * The desired level of I/O concurrency controls how far ahead we are
+	 * willing to look ahead.  We also clamp it to at least
+	 * MAX_BUFFER_PER_TRANFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/*
+	 * The *_io_concurrency GUCs, we might have 0.  We want to allow at least
+	 * one, to keep our gating logic simple.
+	 */
+	max_ios = Max(max_ios, 1);
+
+	/*
+	 * Don't allow this backend to pin too many buffers.  For now we'll apply
+	 * the limit for the shared buffer pool and the local buffer pool, without
+	 * worrying which it is.
+	 */
+	LimitAdditionalPins(&max_pinned_buffers);
+	LimitAdditionalLocalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * We want to avoid creating ranges that are smaller than they could be
+	 * just because we hit max_pinned_buffers.  We only look ahead when the
+	 * number of pinned buffers falls below this trigger number, or put
+	 * another way, we stop looking ahead when we wouldn't be able to build a
+	 * "full sized" range.
+	 */
+	pgsr->pinned_buffers_trigger =
+		Max(1, (int) max_pinned_buffers - MAX_BUFFERS_PER_TRANSFER);
+
+	/* Space the callback to store extra data along with each block. */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * max_pinned_buffers);
+
+	return pgsr;
+}
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *result;
+
+	result = pg_streaming_read_buffer_alloc_internal(flags,
+													 pgsr_private,
+													 per_buffer_data_size,
+													 strategy);
+	result->callback = next_block_cb;
+	result->bmr = bmr;
+	result->forknum = forknum;
+
+	return result;
+}
+
+/*
+ * Start building a new range.  This is called after the previous one
+ * reached maximum size, or the callback's next block can't be merged with it.
+ *
+ * Since the previous head range has now reached its full potential size, this
+ * is also a good time to issue 'prefetch' advice, because we know that'll
+ * soon be reading.  In future, we could start an actual I/O here.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_new_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If a call to CompleteReadBuffers() will be needed, and we can issue
+	 * advice to the kernel to get the read started.  We suppress it if the
+	 * access pattern appears to be completely sequential, though, because on
+	 * some systems that interfers with the kernel's own sequential read ahead
+	 * heurstics and hurts performance.
+	 */
+	if (pgsr->advice_enabled)
+	{
+		BlockNumber blocknum = head_range->blocknum;
+		int			nblocks = head_range->nblocks;
+
+		if (head_range->need_complete && blocknum != pgsr->seq_blocknum)
+		{
+			SMgrRelation smgr =
+				pgsr->bmr.smgr ? pgsr->bmr.smgr :
+				RelationGetSmgr(pgsr->bmr.rel);
+
+			Assert(!head_range->advice_issued);
+
+			smgrprefetch(smgr, pgsr->forknum, blocknum, nblocks);
+
+			/*
+			 * Count this as an I/O that is concurrently in progress, though
+			 * we don't really know if the kernel generates a physical I/O.
+			 */
+			head_range->advice_issued = true;
+			pgsr->ios_in_progress++;
+		}
+
+		/* Remember the block after this range, for sequence detection. */
+		pgsr->seq_blocknum = blocknum + nblocks;
+	}
+
+	/* Create a new head range.  There must be space. */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	head_range = &pgsr->ranges[pgsr->head];
+	head_range->nblocks = 0;
+
+	return head_range;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	/*
+	 * If we're finished or can't start more I/O, then don't look ahead.
+	 */
+	if (pgsr->finished || pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/*
+	 * We'll also wait until the number of pinned buffers falls below our
+	 * trigger level, so that we have the chance to create a full range.
+	 */
+	if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger)
+		return;
+
+	do
+	{
+		BufferManagerRelation bmr;
+		ForkNumber	forknum;
+		BlockNumber blocknum;
+		Buffer		buffer;
+		bool		found;
+		bool		need_complete;
+		PgStreamingReadRange *head_range;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		head_range = &pgsr->ranges[pgsr->head];
+		if (head_range->nblocks == lengthof(head_range->buffers))
+		{
+			Assert(head_range->need_complete);
+			head_range = pg_streaming_read_new_range(pgsr);
+
+			/*
+			 * Give up now if I/O is saturated, or we wouldn't be able form
+			 * another full range after this due to the pin limit.
+			 */
+			if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger ||
+				pgsr->ios_in_progress == pgsr->max_ios)
+				break;
+		}
+
+		per_buffer_data = (char *) pgsr->per_buffer_data +
+			pgsr->per_buffer_data_size * pgsr->per_buffer_data_next;
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			pgsr->finished = true;
+			break;
+		}
+		bmr = pgsr->bmr;
+		forknum = pgsr->forknum;
+
+		Assert(pgsr->pinned_buffers < pgsr->max_pinned_buffers);
+
+		buffer = PrepareReadBuffer(bmr,
+								   forknum,
+								   blocknum,
+								   pgsr->strategy,
+								   &found);
+		pgsr->pinned_buffers++;
+
+		need_complete = !found;
+
+		/* Is there a head range that we can't extend? */
+		head_range = &pgsr->ranges[pgsr->head];
+		if (head_range->nblocks > 0 &&
+			(!need_complete ||
+			 !head_range->need_complete ||
+			 head_range->blocknum + head_range->nblocks != blocknum))
+		{
+			/* Yes, time to start building a new one. */
+			head_range = pg_streaming_read_new_range(pgsr);
+			Assert(head_range->nblocks == 0);
+		}
+
+		if (head_range->nblocks == 0)
+		{
+			/* Initialize a new range beginning at this block. */
+			head_range->blocknum = blocknum;
+			head_range->need_complete = need_complete;
+			head_range->advice_issued = false;
+		}
+		else
+		{
+			/* We can extend an existing range by one block. */
+			Assert(head_range->blocknum + head_range->nblocks == blocknum);
+			Assert(head_range->need_complete);
+		}
+
+		head_range->per_buffer_data_index[head_range->nblocks] = pgsr->per_buffer_data_next++;
+		head_range->buffers[head_range->nblocks] = buffer;
+		head_range->nblocks++;
+
+		if (pgsr->per_buffer_data_next == pgsr->max_pinned_buffers)
+			pgsr->per_buffer_data_next = 0;
+
+	} while (pgsr->pinned_buffers < pgsr->max_pinned_buffers &&
+			 pgsr->ios_in_progress < pgsr->max_ios);
+
+	if (pgsr->ranges[pgsr->head].nblocks > 0)
+		pg_streaming_read_new_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	pg_streaming_read_look_ahead(pgsr);
+
+	/* See if we have one buffer to return. */
+	while (pgsr->tail != pgsr->head)
+	{
+		PgStreamingReadRange *tail_range;
+
+		tail_range = &pgsr->ranges[pgsr->tail];
+
+		/*
+		 * Do we need to perform an I/O before returning the buffers from this
+		 * range?
+		 */
+		if (tail_range->need_complete)
+		{
+			CompleteReadBuffers(pgsr->bmr,
+								tail_range->buffers,
+								pgsr->forknum,
+								tail_range->blocknum,
+								tail_range->nblocks,
+								false,
+								pgsr->strategy);
+			tail_range->need_complete = false;
+
+			/*
+			 * We don't really know if the kernel generated an physical I/O
+			 * when we issued advice, let alone when it finished, but it has
+			 * certainly finished after a read call returns.
+			 */
+			if (tail_range->advice_issued)
+				pgsr->ios_in_progress--;
+		}
+
+		/* Are there more buffers available in this range? */
+		if (pgsr->next_tail_buffer < tail_range->nblocks)
+		{
+			int			buffer_index;
+			Buffer		buffer;
+
+			buffer_index = pgsr->next_tail_buffer++;
+			buffer = tail_range->buffers[buffer_index];
+
+			Assert(BufferIsValid(buffer));
+
+			/* We are giving away ownership of this pinned buffer. */
+			Assert(pgsr->pinned_buffers > 0);
+			pgsr->pinned_buffers--;
+
+			if (per_buffer_data)
+				*per_buffer_data = (char *) pgsr->per_buffer_data +
+					tail_range->per_buffer_data_index[buffer_index] *
+					pgsr->per_buffer_data_size;
+
+			return buffer;
+		}
+
+		/* Advance tail to next range, if there is one. */
+		if (++pgsr->tail == pgsr->size)
+			pgsr->tail = 0;
+		pgsr->next_tail_buffer = 0;
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead, and unpin anything that wasn't consumed. */
+	pgsr->finished = true;
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7d601bef6dd..2157a97b973 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -472,7 +472,7 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
 								ReadBufferMode mode, BufferAccessStrategy strategy,
 								bool *hit);
@@ -501,7 +501,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -795,15 +795,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
+	buf = ReadBuffer_common(BMR_REL(reln),
 							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+
 	return buf;
 }
 
@@ -827,8 +821,9 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 
 	SMgrRelation smgr = smgropen(rlocator, InvalidBackendId);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
 							 mode, strategy, &hit);
 }
 
@@ -1002,7 +997,7 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 		bool		hit;
 
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
+		buffer = ReadBuffer_common(bmr,
 								   fork, extend_to - 1, mode, strategy,
 								   &hit);
 	}
@@ -1016,18 +1011,11 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
 				  BufferAccessStrategy strategy, bool *hit)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	Buffer		buffer;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1046,175 +1034,339 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		*hit = false;
+
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	buffer = PrepareReadBuffer(bmr,
+							   forkNum,
+							   blockNum,
+							   strategy,
+							   hit);
+
+	/* At this point we do NOT hold any locks. */
 
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+	{
+		/* if we just want zeroes and a lock, we're done */
+		ZeroBuffer(buffer, mode);
+	}
+	else if (!*hit)
+	{
+		/* we might need to perform I/O */
+		CompleteReadBuffers(bmr,
+							&buffer,
+							forkNum,
+							blockNum,
+							1,
+							mode == RBM_ZERO_ON_ERROR,
+							strategy);
+	}
+
+	return buffer;
+}
+
+/*
+ * Prepare to read a block.  The buffer is pinned.  If this is a 'hit', then
+ * the returned buffer can be used immediately.  Otherwise, a physical read
+ * should be completed with CompleteReadBuffers(), or the buffer should be
+ * zeroed with ZeroBuffer().  PrepareReadBuffer() followed by
+ * CompleteReadBuffers() or ZeroBuffer() is equivalent to ReadBuffer(), but
+ * the caller has the opportunity to combine reads of multiple neighboring
+ * blocks into one CompleteReadBuffers() call.
+ *
+ * *foundPtr is set to true for a hit, and false for a miss.
+ */
+Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * CompleteReadBuffers() (so, not for hits, and not for buffers that
+		 * are zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+static inline bool
+CompleteReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
+	{
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+/*
+ * Complete a set reads prepared with PrepareReadBuffers().  The buffers must
+ * cover a cluster of neighboring block numbers.
+ *
+ * Typically this performs one physical vector read covering the block range,
+ * but if some of the buffers have already been read in the meantime by any
+ * backend, zero or multiple reads may be performed.
+ */
+void
+CompleteReadBuffers(BufferManagerRelation bmr,
+					Buffer *buffers,
+					ForkNumber forknum,
+					BlockNumber blocknum,
+					int nblocks,
+					bool zero_on_error,
+					BufferAccessStrategy strategy)
+{
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
+	if (isLocalBuf)
+	{
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
+	}
+	else
+	{
+		io_context = IOContextForStrategy(strategy);
+		io_object = IOOBJECT_RELATION;
+	}
 
 	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
 	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
 	else
+		pgBufferUsage.shared_blks_read += nblocks;
+
+	for (int i = 0; i < nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+#ifdef USE_ASSERT_CHECKING
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		/*
+		 * We could get all the information from buffer headers, but it can be
+		 * expensive to access buffer header cache lines so we make the caller
+		 * provide all the information we need, and assert that it is
+		 * consistent.
+		 */
+		{
+			RelFileLocator xlocator;
+			ForkNumber	xforknum;
+			BlockNumber xblocknum;
+
+			BufferGetTag(buffers[i], &xlocator, &xforknum, &xblocknum);
+			Assert(RelFileLocatorEquals(bmr.smgr->smgr_rlocator.locator, xlocator));
+			Assert(xforknum == forknum);
+			Assert(xblocknum == blocknum + i);
+		}
+#endif
+
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!CompleteReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   CompleteReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
 			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
 			}
 			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-		}
-	}
-
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
-	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
-	}
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
 
-	if (isLocalBuf)
-	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if (zero_on_error || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
 
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
-	}
-	else
-	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
-	}
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
@@ -1228,11 +1380,8 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.  A read should be
+ * performed with CompleteReadBuffers().
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1291,19 +1440,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called PrepareReadBuffer() but not yet CompleteReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1368,19 +1508,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called PrepareReadBuffer() but not yet CompleteReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1412,15 +1543,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1774,7 +1899,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2043,7 +2168,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2066,7 +2191,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2381,7 +2506,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if PrepareReadBuffer() was called and
+		 * CompleteReadBuffers() hasn't been called yet.  We'll check by
+		 * loading the flags without locking.  This is racy, but it's OK to
+		 * return false spuriously: when CompleteReadBuffers() calls
+		 * StartBufferIO(), it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2390,7 +2520,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3458,7 +3588,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -4845,6 +4975,46 @@ ConditionalLockBuffer(Buffer buffer)
 									LW_EXCLUSIVE);
 }
 
+/*
+ * Zero a buffer, and lock it as RBM_ZERO_AND_LOCK or
+ * RBM_ZERO_AND_CLEANUP_LOCK would.  The buffer must be already pinned.  It
+ * does not have to be valid, but it is valid and locked on return.
+ */
+void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * Verify that this backend is pinning the buffer exactly once.
  *
@@ -5197,9 +5367,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5212,6 +5388,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 1be4f4f8daf..717b8f58daf 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -109,10 +109,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -288,7 +287,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -298,9 +297,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca27..739d13293fb 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 563a0be5c74..0d7272e796e 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -147,7 +147,9 @@ smgrshutdown(int code, Datum arg)
 /*
  * smgropen() -- Return an SMgrRelation object, creating it if need be.
  *
- * This does not attempt to actually open the underlying file.
+ * This does not attempt to actually open the underlying files.  The returned
+ * object remains valid at least until AtEOXact_SMgr() is called, or until
+ * smgrdestroy() is called in non-transaction backends.
  */
 SMgrRelation
 smgropen(RelFileLocator rlocator, BackendId backend)
@@ -259,10 +261,10 @@ smgrexists(SMgrRelation reln, ForkNumber forknum)
 }
 
 /*
- * smgrclose() -- Close and delete an SMgrRelation object.
+ * smgrdestroy() -- Delete an SMgrRelation object.
  */
 void
-smgrclose(SMgrRelation reln)
+smgrdestroy(SMgrRelation reln)
 {
 	SMgrRelation *owner;
 	ForkNumber	forknum;
@@ -289,12 +291,14 @@ smgrclose(SMgrRelation reln)
 }
 
 /*
- * smgrrelease() -- Release all resources used by this object.
+ * smgrclose() -- Release all resources used by this object.
  *
- * The object remains valid.
+ * The object remains valid, but is moved to the unknown list where it will
+ * be destroyed by AtEOXact_SMgr().  It may be re-owned if it is accessed by a
+ * relation before then.
  */
 void
-smgrrelease(SMgrRelation reln)
+smgrclose(SMgrRelation reln)
 {
 	for (ForkNumber forknum = 0; forknum <= MAX_FORKNUM; forknum++)
 	{
@@ -302,15 +306,20 @@ smgrrelease(SMgrRelation reln)
 		reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber;
 	}
 	reln->smgr_targblock = InvalidBlockNumber;
+
+	if (reln->smgr_owner)
+	{
+		*reln->smgr_owner = NULL;
+		reln->smgr_owner = NULL;
+		dlist_push_tail(&unowned_relns, &reln->node);
+	}
 }
 
 /*
- * smgrreleaseall() -- Release resources used by all objects.
- *
- * This is called for PROCSIGNAL_BARRIER_SMGRRELEASE.
+ * smgrcloseall() -- Close all objects.
  */
 void
-smgrreleaseall(void)
+smgrcloseall(void)
 {
 	HASH_SEQ_STATUS status;
 	SMgrRelation reln;
@@ -322,14 +331,17 @@ smgrreleaseall(void)
 	hash_seq_init(&status, SMgrRelationHash);
 
 	while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
-		smgrrelease(reln);
+		smgrclose(reln);
 }
 
 /*
- * smgrcloseall() -- Close all existing SMgrRelation objects.
+ * smgrdestroyall() -- Destroy all SMgrRelation objects.
+ *
+ * It must be known that there are no pointers to SMgrRelations, other than
+ * those registered with smgrsetowner().
  */
 void
-smgrcloseall(void)
+smgrdestroyall(void)
 {
 	HASH_SEQ_STATUS status;
 	SMgrRelation reln;
@@ -341,7 +353,7 @@ smgrcloseall(void)
 	hash_seq_init(&status, SMgrRelationHash);
 
 	while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
-		smgrclose(reln);
+		smgrdestroy(reln);
 }
 
 /*
@@ -733,7 +745,8 @@ smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
  * AtEOXact_SMgr
  *
  * This routine is called during transaction commit or abort (it doesn't
- * particularly care which).  All transient SMgrRelation objects are closed.
+ * particularly care which).  All transient SMgrRelation objects are
+ * destroyed.
  *
  * We do this as a compromise between wanting transient SMgrRelations to
  * live awhile (to amortize the costs of blind writes of multiple blocks)
@@ -747,7 +760,7 @@ AtEOXact_SMgr(void)
 	dlist_mutable_iter iter;
 
 	/*
-	 * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
+	 * Zap all unowned SMgrRelations.  We rely on smgrdestroy() to remove each
 	 * one from the list.
 	 */
 	dlist_foreach_modify(iter, &unowned_relns)
@@ -757,7 +770,7 @@ AtEOXact_SMgr(void)
 
 		Assert(rel->smgr_owner == NULL);
 
-		smgrclose(rel);
+		smgrdestroy(rel);
 	}
 }
 
@@ -768,6 +781,6 @@ AtEOXact_SMgr(void)
 bool
 ProcessBarrierSmgrRelease(void)
 {
-	smgrreleaseall();
+	smgrcloseall();
 	return true;
 }
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d3353..a38f1acb37a 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,18 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+extern Buffer PrepareReadBuffer(BufferManagerRelation bmr,
+								ForkNumber forkNum,
+								BlockNumber blockNum,
+								BufferAccessStrategy strategy,
+								bool *foundPtr);
+extern void CompleteReadBuffers(BufferManagerRelation bmr,
+								Buffer *buffers,
+								ForkNumber forknum,
+								BlockNumber blocknum,
+								int nblocks,
+								bool zero_on_error,
+								BufferAccessStrategy strategy);
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -247,9 +265,13 @@ extern void LockBufferForCleanup(Buffer buffer);
 extern bool ConditionalLockBufferForCleanup(Buffer buffer);
 extern bool IsBufferCleanupOK(Buffer buffer);
 extern bool HoldingBufferPinThatDelaysRecovery(void);
+extern void ZeroBuffer(Buffer buffer, ReadBufferMode mode);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 527cd2a0568..d8ffe397faf 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -85,8 +85,8 @@ extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln);
 extern void smgrclose(SMgrRelation reln);
 extern void smgrcloseall(void);
 extern void smgrcloserellocator(RelFileLocatorBackend rlocator);
-extern void smgrrelease(SMgrRelation reln);
-extern void smgrreleaseall(void);
+extern void smgrdestroy(SMgrRelation reln);
+extern void smgrdestroyall(void);
 extern void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
 extern void smgrdosyncall(SMgrRelation *rels, int nrels);
 extern void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 00000000000..40c3408c541
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,45 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index a584b1ddff3..6636cc82c09 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -561,12 +561,6 @@ typedef struct ViewOptions
  *
  * Very little code is authorized to touch rel->rd_smgr directly.  Instead
  * use this function to fetch its value.
- *
- * Note: since a relcache flush can cause the file handle to be closed again,
- * it's unwise to hold onto the pointer returned by this function for any
- * long period.  Recommended practice is to just re-execute RelationGetSmgr
- * each time you need to access the SMgrRelation.  It's quite cheap in
- * comparison to whatever an smgr function is going to do.
  */
 static inline SMgrRelation
 RelationGetSmgr(Relation rel)
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 91433d439b7..8007f17320a 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2094,6 +2094,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
-- 
2.37.2

v3-0013-BitmapHeapScan-uses-streaming-read-API.patchtext/x-diff; charset=us-asciiDownload
From 6469df2a68926093e40f82df15d85ceacc6e0ca5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:04:18 -0500
Subject: [PATCH v3 13/13] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  68 +++++
 src/backend/access/heap/heapam_handler.c  |  88 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 340 +---------------------
 src/include/access/heapam.h               |   4 +
 src/include/access/tableam.h              |  19 +-
 src/include/nodes/execnodes.h             |  19 --
 6 files changed, 117 insertions(+), 421 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b93f243c282..c965048af60 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -115,6 +115,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -335,6 +337,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -955,6 +973,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
 
@@ -1093,6 +1112,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10250,3 +10272,49 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (hdesc->rs_base.shared_tbmiterator)
+			tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+		else
+			tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ba6793a749c..0237cd52b61 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2113,79 +2113,65 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno)
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (scan->shared_tbmiterator)
-			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
-		else
-			tbm_iterate(scan->tbmiterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, and the bitmap entries don't need rechecking, and all tuples on
-	 * the page are visible to our transaction.
-	 */
-	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2206,7 +2192,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2215,9 +2201,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2270,7 +2256,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/* Only count exact and lossy pages with visible tuples */
 	if (ntup > 0)
 	{
-		if (tbmres.ntuples >= 0)
+		if (tbmres->ntuples >= 0)
 			scan->exact_pages++;
 		else
 			scan->lossy_pages++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index bcc60d3cf98..5fd760a0f66 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -56,11 +56,6 @@ static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapAccumCounters(BitmapHeapScanState *node,
 									   TableScanDesc scan);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -91,14 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -114,15 +101,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
 		}
 		else
 		{
@@ -145,20 +123,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
 
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
@@ -166,14 +130,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -220,50 +176,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		node->initialized = true;
 
 		/* Get the first block. if none, end of scan */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck))
 			return ExecClearTuple(slot);
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		BitmapAdjustPrefetchTarget(node);
 	}
 
-	for (;;)
+	do
 	{
 		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We prefetch before fetching the current pages. We expect that a
-			 * future streaming read API will do this, so do it this way now
-			 * for consistency. Also, this should happen only when we have
-			 * determined there is still something to do on the current page,
-			 * else we may uselessly prefetch the same page we are just about
-			 * to request for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -285,13 +207,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			return slot;
 		}
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno))
-			break;
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
-	}
+	} while (table_scan_bitmap_next_block(scan, &node->recheck));
 
 	/*
 	 * if we get here it means we are at the end of the scan..
@@ -325,215 +241,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult tbmpre;
-			tbm_iterate(prefetch_iterator, &tbmpre);
-
-			if (!BlockNumberIsValid(tbmpre.blockno) || tbmpre.blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
-		}
-		return;
-	}
-
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			TBMIterateResult tbmpre;
-
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -579,22 +286,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -633,16 +330,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -675,19 +366,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -727,13 +412,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -817,14 +495,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -856,11 +530,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3dfb19ec7d5..1cad9c04f01 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index f1f5b7ab1d0..9fad92675f4 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,22 +789,10 @@ typedef struct TableAmRoutine
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, BlockNumber *blockno);
+	bool		(*scan_bitmap_next_block) (TableScanDesc scan, bool *recheck);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1981,8 +1969,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno)
+table_scan_bitmap_next_block(TableScanDesc scan, bool *recheck)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1992,7 +1979,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, blockno);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a59df51dd69..d41a3e134d8 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1682,11 +1682,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  *		phs_snapshot_data		snapshot data shared to workers
@@ -1695,10 +1692,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 	char		phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
@@ -1709,16 +1703,10 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
  *		recheck			   do current page's tuples need recheck
@@ -1729,20 +1717,13 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
 	bool		recheck;
-	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

#8Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#7)
14 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Feb 16, 2024 at 12:35:59PM -0500, Melanie Plageman wrote:

In the attached v3, I've reordered the commits, updated some errant
comments, and improved the commit messages.

I've also made some updates to the TIDBitmap API that seem like a
clarity improvement to the API in general. These also reduce the diff
for GIN when separating the TBMIterateResult from the
TBM[Shared]Iterator. And these TIDBitmap API changes are now all in
their own commits (previously those were in the same commit as adding
the BitmapHeapScan streaming read user).

The three outstanding issues I see in the patch set are:
1) the lossy and exact page counters issue described in my previous
email

I've resolved this. I added a new patch to the set which starts counting
even pages with no visible tuples toward lossy and exact pages. After an
off-list conversation with Andres, it seems that this omission in master
may not have been intentional.

Once we have only two types of pages to differentiate between (lossy and
exact [no longer have to care about "has no visible tuples"]), it is
easy enough to pass a "lossy" boolean paramater to
table_scan_bitmap_next_block(). I've done this in the attached v4.

- Melanie

Attachments:

v4-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From e0cee301b81400209a0e727a3d7daa1f435ba999 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v4 01/14] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.

ExecBitmapHeapInitializeWorker() overwrote the snapshot in the scan
descriptor with the correct one provided by the parallel leader. Since
ExecBitmapHeapInitializeWorker() is now called before the scan
descriptor has been created, save the worker's snapshot in the
BitmapHeapScanState and pass it to table_beginscan_bm().
---
 src/backend/access/table/tableam.c        | 11 ------
 src/backend/executor/nodeBitmapHeapscan.c | 47 ++++++++++++++++++-----
 src/include/access/tableam.h              | 10 ++---
 src/include/nodes/execnodes.h             |  2 +
 4 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 6ed8cca05a1..e78d793f69c 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,17 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-void
-table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot)
-{
-	Assert(IsMVCCSnapshot(snapshot));
-
-	RegisterSnapshot(snapshot);
-	scan->rs_snapshot = snapshot;
-	scan->rs_flags |= SO_TEMP_SNAPSHOT;
-}
-
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c1e81ebed63..44bf38be3c9 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -181,6 +181,34 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			Snapshot	snapshot = node->ss.ps.state->es_snapshot;
+			uint32		extra_flags = 0;
+
+			/*
+			 * Parallel workers must use the snapshot initialized by the
+			 * parallel leader.
+			 */
+			if (node->worker_snapshot)
+			{
+				snapshot = node->worker_snapshot;
+				extra_flags |= SO_TEMP_SNAPSHOT;
+			}
+
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	snapshot,
+																	0,
+																	NULL,
+																	extra_flags);
+		}
+
 		node->initialized = true;
 	}
 
@@ -604,7 +632,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -681,7 +710,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -739,6 +770,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	 */
 	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
 								 node->scan.plan.targetlist == NIL);
+	scanstate->worker_snapshot = NULL;
 
 	/*
 	 * Miscellaneous initialization
@@ -787,11 +819,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
@@ -930,13 +957,13 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 							   ParallelWorkerContext *pwcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	Snapshot	snapshot;
 
 	Assert(node->ss.ps.state->es_query_dsa != NULL);
 
 	pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
 	node->pstate = pstate;
 
-	snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
-	table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
+	node->worker_snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
+	Assert(IsMVCCSnapshot(node->worker_snapshot));
+	RegisterSnapshot(node->worker_snapshot);
 }
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5f8474871d2..5375dd7150f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -944,9 +944,10 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key,
+				   uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
@@ -1038,11 +1039,6 @@ table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
 										 allow_pagemode);
 }
 
-/*
- * Update snapshot used by the scan.
- */
-extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
-
 /*
  * Return next tuple from `scan`, store in slot.
  */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 444a5f0fd57..00c75fb10e2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1726,6 +1726,7 @@ typedef struct ParallelBitmapHeapState
  *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		worker_snapshot	   snapshot for parallel worker
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1750,6 +1751,7 @@ typedef struct BitmapHeapScanState
 	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	Snapshot	worker_snapshot;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v4-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 69cd001bcdade976a51985e714d1b30b090bb388 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v4 02/14] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 44bf38be3c9..a9ba2bdfb88 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,6 +108,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -760,16 +770,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 	scanstate->worker_snapshot = NULL;
 
 	/*
-- 
2.37.2

v4-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-diff; charset=us-asciiDownload
From b29df9592f8b3a3966cf6fab40f56a0c113f3d57 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v4 03/14] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 ++++++
 src/backend/executor/nodeBitmapHeapscan.c | 118 ++++++----------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |   7 ++
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 94 insertions(+), 92 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 707460a5364..b93f243c282 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -955,6 +955,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1043,6 +1045,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1062,6 +1070,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d15a02b2be7..7661acac3a8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2124,6 +2125,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, and the bitmap entries don't need rechecking, and all tuples on
+	 * the page are visible to our transaction.
+	 */
+	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2236,6 +2255,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a9ba2bdfb88..2e4f87ea3a3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,16 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -211,6 +201,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				extra_flags |= SO_TEMP_SNAPSHOT;
 			}
 
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual == NIL && node->ss.ps.plan->targetlist == NIL)
+				extra_flags |= SO_CAN_SKIP_FETCH;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	snapshot,
@@ -224,8 +225,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -245,32 +244,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -318,52 +292,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -535,7 +490,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -586,7 +542,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -656,8 +612,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -667,7 +621,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -712,8 +665,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -757,8 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -770,7 +719,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 	scanstate->worker_snapshot = NULL;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f68593..3dfb19ec7d5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5375dd7150f..c193ea5db43 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed.
+	 */
+	SO_CAN_SKIP_FETCH = 1 << 10,
 }			ScanOptions;
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 00c75fb10e2..6fb4ec07c5f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1711,10 +1711,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1736,9 +1733,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.37.2

v4-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-diff; charset=us-asciiDownload
From 17fc9d4c35e42b6e870b7e7f7c3495114e393e8a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v4 04/14] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2e4f87ea3a3..35ef26221ba 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -484,15 +484,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
-
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -543,7 +537,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.37.2

v4-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-diff; charset=us-asciiDownload
From 67a9fb1848718cabfcfd5c98368ab2aa79a6b213 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v4 05/14] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 35ef26221ba..3439c02e989 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -55,7 +55,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -242,7 +242,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
@@ -351,7 +351,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -370,7 +370,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.37.2

v4-0006-EXPLAIN-Bitmap-table-scan-also-count-no-visible-t.patchtext/x-diff; charset=us-asciiDownload
From 4ad9d2798dff02537d0b5e7b807a5e80c7f0551d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 18:35:28 -0500
Subject: [PATCH v4 06/14] EXPLAIN Bitmap table scan also count no visible
 tuple pages

Previously, bitmap heap scans only counted lossy and exact pages for
explain when there was at least one visible tuple on the page.

heapam_scan_bitmap_next_block() returned true only if there was a
"valid" page with tuples to be processed. However, the lossy and exact
page counters in EXPLAIN should count the number of pages represented in
a lossy or non-lossy way in the constructured bitmap, so it doesn't make
sense to omit pages without visible tuples.
---
 src/backend/executor/nodeBitmapHeapscan.c     | 15 ++++++++++-----
 src/test/regress/expected/partition_prune.out |  4 +++-
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3439c02e989..75e896074bf 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -225,6 +225,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
+		bool valid;
+
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -244,17 +246,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			if (!table_scan_bitmap_next_block(scan, tbmres))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
+			valid = table_scan_bitmap_next_block(scan, tbmres);
 
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
+			if (!valid)
+			{
+				/* AM doesn't think this block is valid, skip */
+				continue;
+			}
+
+
 			/* Adjust the prefetch target */
 			BitmapAdjustPrefetchTarget(node);
 		}
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index 9a4c48c0556..d9ec6492f96 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -2709,6 +2709,7 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a;
                            Index Cond: (a = 1)
                ->  Bitmap Heap Scan on ab_a1_b3 ab_a1_3 (actual rows=0 loops=1)
                      Recheck Cond: (a = 1)
+                     Heap Blocks: exact=1
                      ->  Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1)
                            Index Cond: (a = 1)
          ->  Materialize (actual rows=1 loops=1)
@@ -2724,9 +2725,10 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a;
                                  Index Cond: (a = 1)
                      ->  Bitmap Heap Scan on ab_a1_b3 ab_3 (actual rows=0 loops=1)
                            Recheck Cond: (a = 1)
+                           Heap Blocks: exact=1
                            ->  Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1)
                                  Index Cond: (a = 1)
-(34 rows)
+(36 rows)
 
 table ab;
  a | b 
-- 
2.37.2

v4-0007-table_scan_bitmap_next_block-returns-lossy-or-exa.patchtext/x-diff; charset=us-asciiDownload
From 1d179a330c870ac6cf78cc4be56fb6e48298d093 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v4 07/14] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7661acac3a8..a6e52671d9b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,7 +2114,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2242,6 +2243,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 75e896074bf..054f745eeba 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -225,7 +225,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool valid;
+		bool valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -246,12 +246,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index c193ea5db43..8280035e39f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -796,6 +796,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -811,7 +814,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1952,14 +1956,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1970,7 +1976,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.37.2

v4-0008-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-diff; charset=us-asciiDownload
From b5c9f5aef18124f93886c25fceb56706dcdb813a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v4 08/14] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 054f745eeba..a639d6e7415 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -74,8 +74,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -88,10 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -108,6 +102,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -116,7 +113,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -169,8 +166,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -220,6 +216,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -235,9 +233,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.37.2

v4-0009-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-diff; charset=us-asciiDownload
From 46b086ad26c7c6a832892d91d3da2fd75f0a2039 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v4 09/14] Remove table_scan_bitmap_next_tuple parameter tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a6e52671d9b..5dc9c51ca95 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2250,7 +2250,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a639d6e7415..87991266931 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -301,7 +301,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8280035e39f..8d7c800d157 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -787,10 +787,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -821,15 +818,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -1989,7 +1981,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2001,7 +1992,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.37.2

v4-0010-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From f43d9b0913815b98b2a6216440a2b5e87ad95936 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:57:07 -0500
Subject: [PATCH v4 10/14] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c | 167 +++++++++-------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 ++++++---
 src/include/nodes/execnodes.h             |   9 +-
 5 files changed, 168 insertions(+), 142 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 5dc9c51ca95..a439ddc87bf 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,18 +2114,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, and the bitmap entries don't need rechecking, and all tuples on
@@ -2144,16 +2177,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2245,7 +2269,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 87991266931..3be433ea6e1 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -73,8 +73,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -86,7 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -114,7 +113,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -167,7 +165,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -216,56 +213,29 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
-		node->initialized = true;
-	}
-
-	for (;;)
-	{
-		bool valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
+		node->initialized = true;
 
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
+		/* Get the first block. if none, end of scan */
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			return ExecClearTuple(slot);
 
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
 
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		BitmapAdjustPrefetchTarget(node);
+	}
 
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+	for (;;)
+	{
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -287,45 +257,48 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
-
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
-		}
+			/*
+			 * We prefetch before fetching the current pages. We expect that a
+			 * future streaming read API will do this, so do it this way now
+			 * for consistency. Also, this should happen only when we have
+			 * determined there is still something to do on the current page,
+			 * else we may uselessly prefetch the same page we are just about
+			 * to request for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
-		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
 			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
 			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
-		/* OK to return this tuple */
-		return slot;
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -599,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -612,13 +581,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -649,28 +617,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -703,8 +667,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -713,10 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8d7c800d157..2adead958cb 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -780,19 +781,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -811,8 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -950,9 +946,13 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key,
 				   uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1012,6 +1012,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1022,6 +1037,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1945,19 +1975,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1967,8 +1995,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6fb4ec07c5f..a59df51dd69 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1709,8 +1709,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1720,10 +1718,10 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
+ *		recheck			   do current page's tuples need recheck
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1731,8 +1729,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1742,10 +1738,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
+	bool		recheck;
+	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v4-0011-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From 9c4b0c681205cdb4f48f544832fd0d4cd965f3c5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v4 11/14] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 29 +++++++----------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 0f4850065fb..689a959b467 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,21 +40,12 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "nodes/bitmapset.h"
 #include "nodes/tidbitmap.h"
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -66,7 +57,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -78,7 +69,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -180,7 +171,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -221,7 +212,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -389,7 +380,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -691,12 +682,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1470,8 +1456,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..432fae52962 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.37.2

v4-0012-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchtext/x-diff; charset=us-asciiDownload
From e2bf17c5a936c3d536d9f25150b81d00969963b1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v4 12/14] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 33 +++++-----
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 7 files changed, 107 insertions(+), 87 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3aa457a29e1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..033d5253394 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a439ddc87bf..daa5902e24d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2121,7 +2121,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2134,11 +2134,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		CHECK_FOR_INTERRUPTS();
 
 		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbm_iterate(scan->tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2153,11 +2153,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2165,19 +2165,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * the page are visible to our transaction.
 	 */
 	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2206,7 +2206,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2215,9 +2215,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2267,7 +2267,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	*lossy = tbmres.ntuples < 0;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3be433ea6e1..74b92d4cbf4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -344,9 +344,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+			TBMIterateResult tbmpre;
+			tbm_iterate(prefetch_iterator, &tbmpre);
 
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
+			if (!BlockNumberIsValid(tbmpre.blockno) || tbmpre.blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
@@ -364,6 +365,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		}
 		else
 		{
+			TBMIterateResult tbmpre;
+
 			/* Release the mutex before iterating */
 			SpinLockRelease(&pstate->mutex);
 
@@ -376,7 +379,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -443,10 +446,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
@@ -462,13 +467,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -483,7 +488,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -502,8 +507,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_shared_iterate(prefetch_iterator);
@@ -513,13 +518,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 689a959b467..b4dcb1cbb88 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -171,7 +171,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -212,7 +211,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -943,20 +941,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -984,6 +983,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -994,11 +994,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1014,16 +1014,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1033,10 +1034,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1087,13 +1087,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1103,21 +1103,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 51d0c74a6b0..e423d92b41c 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae52962..f000c1af28f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.37.2

v4-0013-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From 0a6454968309ddaa85653ff9efacd54072f7fc33 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 22 Jul 2023 17:31:54 +1200
Subject: [PATCH v4 13/14] Streaming Read API

---
 contrib/pg_prewarm/pg_prewarm.c          |  40 +-
 src/backend/access/transam/xlogutils.c   |   2 +-
 src/backend/postmaster/bgwriter.c        |   8 +-
 src/backend/postmaster/checkpointer.c    |  15 +-
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 435 ++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 560 +++++++++++++++--------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/backend/storage/smgr/smgr.c          |  49 +-
 src/include/storage/bufmgr.h             |  22 +
 src/include/storage/smgr.h               |   4 +-
 src/include/storage/streaming_read.h     |  45 ++
 src/include/utils/rel.h                  |   6 -
 src/tools/pgindent/typedefs.list         |   2 +
 17 files changed, 986 insertions(+), 238 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/contrib/pg_prewarm/pg_prewarm.c b/contrib/pg_prewarm/pg_prewarm.c
index 8541e4d6e46..9617bf130bd 100644
--- a/contrib/pg_prewarm/pg_prewarm.c
+++ b/contrib/pg_prewarm/pg_prewarm.c
@@ -20,6 +20,7 @@
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
 #include "storage/smgr.h"
+#include "storage/streaming_read.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -38,6 +39,25 @@ typedef enum
 
 static PGIOAlignedBlock blockbuffer;
 
+struct pg_prewarm_streaming_read_private
+{
+	BlockNumber blocknum;
+	int64		last_block;
+};
+
+static BlockNumber
+pg_prewarm_streaming_read_next(PgStreamingRead *pgsr,
+							   void *pgsr_private,
+							   void *per_buffer_data)
+{
+	struct pg_prewarm_streaming_read_private *p = pgsr_private;
+
+	if (p->blocknum <= p->last_block)
+		return p->blocknum++;
+
+	return InvalidBlockNumber;
+}
+
 /*
  * pg_prewarm(regclass, mode text, fork text,
  *			  first_block int8, last_block int8)
@@ -183,18 +203,36 @@ pg_prewarm(PG_FUNCTION_ARGS)
 	}
 	else if (ptype == PREWARM_BUFFER)
 	{
+		struct pg_prewarm_streaming_read_private p;
+		PgStreamingRead *pgsr;
+
 		/*
 		 * In buffer mode, we actually pull the data into shared_buffers.
 		 */
+
+		/* Set up the private state for our streaming buffer read callback. */
+		p.blocknum = first_block;
+		p.last_block = last_block;
+
+		pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+											  &p,
+											  0,
+											  NULL,
+											  BMR_REL(rel),
+											  forkNumber,
+											  pg_prewarm_streaming_read_next);
+
 		for (block = first_block; block <= last_block; ++block)
 		{
 			Buffer		buf;
 
 			CHECK_FOR_INTERRUPTS();
-			buf = ReadBufferExtended(rel, forkNumber, block, RBM_NORMAL, NULL);
+			buf = pg_streaming_read_buffer_get_next(pgsr, NULL);
 			ReleaseBuffer(buf);
 			++blocks_done;
 		}
+		Assert(pg_streaming_read_buffer_get_next(pgsr, NULL) == InvalidBuffer);
+		pg_streaming_read_free(pgsr);
 	}
 
 	/* Close relation, release lock. */
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index aa8667abd10..8775b5789be 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -657,7 +657,7 @@ XLogDropDatabase(Oid dbid)
 	 * This is unnecessarily heavy-handed, as it will close SMgrRelation
 	 * objects for other databases as well. DROP DATABASE occurs seldom enough
 	 * that it's not worth introducing a variant of smgrclose for just this
-	 * purpose. XXX: Or should we rather leave the smgr entries dangling?
+	 * purpose.
 	 */
 	smgrcloseall();
 
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index d7d6cc0cd7b..13e5376619e 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -246,10 +246,12 @@ BackgroundWriterMain(void)
 		if (FirstCallSinceLastCheckpoint())
 		{
 			/*
-			 * After any checkpoint, close all smgr files.  This is so we
-			 * won't hang onto smgr references to deleted files indefinitely.
+			 * After any checkpoint, free all smgr objects.  Otherwise we
+			 * would never do so for dropped relations, as the bgwriter does
+			 * not process shared invalidation messages or call
+			 * AtEOXact_SMgr().
 			 */
-			smgrcloseall();
+			smgrdestroyall();
 		}
 
 		/*
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 5e949fc885b..5d843b61426 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -469,10 +469,12 @@ CheckpointerMain(void)
 				ckpt_performed = CreateRestartPoint(flags);
 
 			/*
-			 * After any checkpoint, close all smgr files.  This is so we
-			 * won't hang onto smgr references to deleted files indefinitely.
+			 * After any checkpoint, free all smgr objects.  Otherwise we
+			 * would never do so for dropped relations, as the checkpointer
+			 * does not process shared invalidation messages or call
+			 * AtEOXact_SMgr().
 			 */
-			smgrcloseall();
+			smgrdestroyall();
 
 			/*
 			 * Indicate checkpoint completion to any waiting backends.
@@ -958,11 +960,8 @@ RequestCheckpoint(int flags)
 		 */
 		CreateCheckPoint(flags | CHECKPOINT_IMMEDIATE);
 
-		/*
-		 * After any checkpoint, close all smgr files.  This is so we won't
-		 * hang onto smgr references to deleted files indefinitely.
-		 */
-		smgrcloseall();
+		/* Free all smgr objects, as CheckpointerMain() normally would. */
+		smgrdestroyall();
 
 		return;
 	}
diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca20..eec03f6f2b4 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 00000000000..bcab44c802f
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 00000000000..39aef2a84a2
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 00000000000..19605090fea
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,435 @@
+#include "postgres.h"
+
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ *
+ * For hits, need_to_complete is false and there is just one block per
+ * range, already pinned and ready for use.
+ *
+ * For misses, need_to_complete is true and buffers[] holds a range of
+ * blocks that are contiguous in storage (though the buffers may not be
+ * contiguous in memory), so we can complete them with a single call to
+ * CompleteReadBuffers().
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		advice_issued;
+	bool		need_complete;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index[MAX_BUFFERS_PER_TRANSFER];
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+} PgStreamingReadRange;
+
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			ios_in_progress_trigger;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			pinned_buffers_trigger;
+	int			next_tail_buffer;
+	bool		finished;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	bool		advice_enabled;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+	int			per_buffer_data_next;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+static PgStreamingRead *
+pg_streaming_read_buffer_alloc_internal(int flags,
+										void *pgsr_private,
+										size_t per_buffer_data_size,
+										BufferAccessStrategy strategy)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = maintenance_io_concurrency;
+	else
+		max_ios = effective_io_concurrency;
+
+	/*
+	 * The desired level of I/O concurrency controls how far ahead we are
+	 * willing to look ahead.  We also clamp it to at least
+	 * MAX_BUFFER_PER_TRANFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/*
+	 * The *_io_concurrency GUCs, we might have 0.  We want to allow at least
+	 * one, to keep our gating logic simple.
+	 */
+	max_ios = Max(max_ios, 1);
+
+	/*
+	 * Don't allow this backend to pin too many buffers.  For now we'll apply
+	 * the limit for the shared buffer pool and the local buffer pool, without
+	 * worrying which it is.
+	 */
+	LimitAdditionalPins(&max_pinned_buffers);
+	LimitAdditionalLocalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * We want to avoid creating ranges that are smaller than they could be
+	 * just because we hit max_pinned_buffers.  We only look ahead when the
+	 * number of pinned buffers falls below this trigger number, or put
+	 * another way, we stop looking ahead when we wouldn't be able to build a
+	 * "full sized" range.
+	 */
+	pgsr->pinned_buffers_trigger =
+		Max(1, (int) max_pinned_buffers - MAX_BUFFERS_PER_TRANSFER);
+
+	/* Space the callback to store extra data along with each block. */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * max_pinned_buffers);
+
+	return pgsr;
+}
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *result;
+
+	result = pg_streaming_read_buffer_alloc_internal(flags,
+													 pgsr_private,
+													 per_buffer_data_size,
+													 strategy);
+	result->callback = next_block_cb;
+	result->bmr = bmr;
+	result->forknum = forknum;
+
+	return result;
+}
+
+/*
+ * Start building a new range.  This is called after the previous one
+ * reached maximum size, or the callback's next block can't be merged with it.
+ *
+ * Since the previous head range has now reached its full potential size, this
+ * is also a good time to issue 'prefetch' advice, because we know that'll
+ * soon be reading.  In future, we could start an actual I/O here.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_new_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If a call to CompleteReadBuffers() will be needed, and we can issue
+	 * advice to the kernel to get the read started.  We suppress it if the
+	 * access pattern appears to be completely sequential, though, because on
+	 * some systems that interfers with the kernel's own sequential read ahead
+	 * heurstics and hurts performance.
+	 */
+	if (pgsr->advice_enabled)
+	{
+		BlockNumber blocknum = head_range->blocknum;
+		int			nblocks = head_range->nblocks;
+
+		if (head_range->need_complete && blocknum != pgsr->seq_blocknum)
+		{
+			SMgrRelation smgr =
+				pgsr->bmr.smgr ? pgsr->bmr.smgr :
+				RelationGetSmgr(pgsr->bmr.rel);
+
+			Assert(!head_range->advice_issued);
+
+			smgrprefetch(smgr, pgsr->forknum, blocknum, nblocks);
+
+			/*
+			 * Count this as an I/O that is concurrently in progress, though
+			 * we don't really know if the kernel generates a physical I/O.
+			 */
+			head_range->advice_issued = true;
+			pgsr->ios_in_progress++;
+		}
+
+		/* Remember the block after this range, for sequence detection. */
+		pgsr->seq_blocknum = blocknum + nblocks;
+	}
+
+	/* Create a new head range.  There must be space. */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	head_range = &pgsr->ranges[pgsr->head];
+	head_range->nblocks = 0;
+
+	return head_range;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	/*
+	 * If we're finished or can't start more I/O, then don't look ahead.
+	 */
+	if (pgsr->finished || pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/*
+	 * We'll also wait until the number of pinned buffers falls below our
+	 * trigger level, so that we have the chance to create a full range.
+	 */
+	if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger)
+		return;
+
+	do
+	{
+		BufferManagerRelation bmr;
+		ForkNumber	forknum;
+		BlockNumber blocknum;
+		Buffer		buffer;
+		bool		found;
+		bool		need_complete;
+		PgStreamingReadRange *head_range;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		head_range = &pgsr->ranges[pgsr->head];
+		if (head_range->nblocks == lengthof(head_range->buffers))
+		{
+			Assert(head_range->need_complete);
+			head_range = pg_streaming_read_new_range(pgsr);
+
+			/*
+			 * Give up now if I/O is saturated, or we wouldn't be able form
+			 * another full range after this due to the pin limit.
+			 */
+			if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger ||
+				pgsr->ios_in_progress == pgsr->max_ios)
+				break;
+		}
+
+		per_buffer_data = (char *) pgsr->per_buffer_data +
+			pgsr->per_buffer_data_size * pgsr->per_buffer_data_next;
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			pgsr->finished = true;
+			break;
+		}
+		bmr = pgsr->bmr;
+		forknum = pgsr->forknum;
+
+		Assert(pgsr->pinned_buffers < pgsr->max_pinned_buffers);
+
+		buffer = PrepareReadBuffer(bmr,
+								   forknum,
+								   blocknum,
+								   pgsr->strategy,
+								   &found);
+		pgsr->pinned_buffers++;
+
+		need_complete = !found;
+
+		/* Is there a head range that we can't extend? */
+		head_range = &pgsr->ranges[pgsr->head];
+		if (head_range->nblocks > 0 &&
+			(!need_complete ||
+			 !head_range->need_complete ||
+			 head_range->blocknum + head_range->nblocks != blocknum))
+		{
+			/* Yes, time to start building a new one. */
+			head_range = pg_streaming_read_new_range(pgsr);
+			Assert(head_range->nblocks == 0);
+		}
+
+		if (head_range->nblocks == 0)
+		{
+			/* Initialize a new range beginning at this block. */
+			head_range->blocknum = blocknum;
+			head_range->need_complete = need_complete;
+			head_range->advice_issued = false;
+		}
+		else
+		{
+			/* We can extend an existing range by one block. */
+			Assert(head_range->blocknum + head_range->nblocks == blocknum);
+			Assert(head_range->need_complete);
+		}
+
+		head_range->per_buffer_data_index[head_range->nblocks] = pgsr->per_buffer_data_next++;
+		head_range->buffers[head_range->nblocks] = buffer;
+		head_range->nblocks++;
+
+		if (pgsr->per_buffer_data_next == pgsr->max_pinned_buffers)
+			pgsr->per_buffer_data_next = 0;
+
+	} while (pgsr->pinned_buffers < pgsr->max_pinned_buffers &&
+			 pgsr->ios_in_progress < pgsr->max_ios);
+
+	if (pgsr->ranges[pgsr->head].nblocks > 0)
+		pg_streaming_read_new_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	pg_streaming_read_look_ahead(pgsr);
+
+	/* See if we have one buffer to return. */
+	while (pgsr->tail != pgsr->head)
+	{
+		PgStreamingReadRange *tail_range;
+
+		tail_range = &pgsr->ranges[pgsr->tail];
+
+		/*
+		 * Do we need to perform an I/O before returning the buffers from this
+		 * range?
+		 */
+		if (tail_range->need_complete)
+		{
+			CompleteReadBuffers(pgsr->bmr,
+								tail_range->buffers,
+								pgsr->forknum,
+								tail_range->blocknum,
+								tail_range->nblocks,
+								false,
+								pgsr->strategy);
+			tail_range->need_complete = false;
+
+			/*
+			 * We don't really know if the kernel generated an physical I/O
+			 * when we issued advice, let alone when it finished, but it has
+			 * certainly finished after a read call returns.
+			 */
+			if (tail_range->advice_issued)
+				pgsr->ios_in_progress--;
+		}
+
+		/* Are there more buffers available in this range? */
+		if (pgsr->next_tail_buffer < tail_range->nblocks)
+		{
+			int			buffer_index;
+			Buffer		buffer;
+
+			buffer_index = pgsr->next_tail_buffer++;
+			buffer = tail_range->buffers[buffer_index];
+
+			Assert(BufferIsValid(buffer));
+
+			/* We are giving away ownership of this pinned buffer. */
+			Assert(pgsr->pinned_buffers > 0);
+			pgsr->pinned_buffers--;
+
+			if (per_buffer_data)
+				*per_buffer_data = (char *) pgsr->per_buffer_data +
+					tail_range->per_buffer_data_index[buffer_index] *
+					pgsr->per_buffer_data_size;
+
+			return buffer;
+		}
+
+		/* Advance tail to next range, if there is one. */
+		if (++pgsr->tail == pgsr->size)
+			pgsr->tail = 0;
+		pgsr->next_tail_buffer = 0;
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead, and unpin anything that wasn't consumed. */
+	pgsr->finished = true;
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7d601bef6dd..2157a97b973 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -472,7 +472,7 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
 								ReadBufferMode mode, BufferAccessStrategy strategy,
 								bool *hit);
@@ -501,7 +501,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -795,15 +795,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
+	buf = ReadBuffer_common(BMR_REL(reln),
 							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+
 	return buf;
 }
 
@@ -827,8 +821,9 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 
 	SMgrRelation smgr = smgropen(rlocator, InvalidBackendId);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
 							 mode, strategy, &hit);
 }
 
@@ -1002,7 +997,7 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 		bool		hit;
 
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
+		buffer = ReadBuffer_common(bmr,
 								   fork, extend_to - 1, mode, strategy,
 								   &hit);
 	}
@@ -1016,18 +1011,11 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
 				  BufferAccessStrategy strategy, bool *hit)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	Buffer		buffer;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1046,175 +1034,339 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		*hit = false;
+
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	buffer = PrepareReadBuffer(bmr,
+							   forkNum,
+							   blockNum,
+							   strategy,
+							   hit);
+
+	/* At this point we do NOT hold any locks. */
 
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+	{
+		/* if we just want zeroes and a lock, we're done */
+		ZeroBuffer(buffer, mode);
+	}
+	else if (!*hit)
+	{
+		/* we might need to perform I/O */
+		CompleteReadBuffers(bmr,
+							&buffer,
+							forkNum,
+							blockNum,
+							1,
+							mode == RBM_ZERO_ON_ERROR,
+							strategy);
+	}
+
+	return buffer;
+}
+
+/*
+ * Prepare to read a block.  The buffer is pinned.  If this is a 'hit', then
+ * the returned buffer can be used immediately.  Otherwise, a physical read
+ * should be completed with CompleteReadBuffers(), or the buffer should be
+ * zeroed with ZeroBuffer().  PrepareReadBuffer() followed by
+ * CompleteReadBuffers() or ZeroBuffer() is equivalent to ReadBuffer(), but
+ * the caller has the opportunity to combine reads of multiple neighboring
+ * blocks into one CompleteReadBuffers() call.
+ *
+ * *foundPtr is set to true for a hit, and false for a miss.
+ */
+Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * CompleteReadBuffers() (so, not for hits, and not for buffers that
+		 * are zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+static inline bool
+CompleteReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
+	{
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+/*
+ * Complete a set reads prepared with PrepareReadBuffers().  The buffers must
+ * cover a cluster of neighboring block numbers.
+ *
+ * Typically this performs one physical vector read covering the block range,
+ * but if some of the buffers have already been read in the meantime by any
+ * backend, zero or multiple reads may be performed.
+ */
+void
+CompleteReadBuffers(BufferManagerRelation bmr,
+					Buffer *buffers,
+					ForkNumber forknum,
+					BlockNumber blocknum,
+					int nblocks,
+					bool zero_on_error,
+					BufferAccessStrategy strategy)
+{
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
+	if (isLocalBuf)
+	{
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
+	}
+	else
+	{
+		io_context = IOContextForStrategy(strategy);
+		io_object = IOOBJECT_RELATION;
+	}
 
 	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
 	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
 	else
+		pgBufferUsage.shared_blks_read += nblocks;
+
+	for (int i = 0; i < nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+#ifdef USE_ASSERT_CHECKING
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		/*
+		 * We could get all the information from buffer headers, but it can be
+		 * expensive to access buffer header cache lines so we make the caller
+		 * provide all the information we need, and assert that it is
+		 * consistent.
+		 */
+		{
+			RelFileLocator xlocator;
+			ForkNumber	xforknum;
+			BlockNumber xblocknum;
+
+			BufferGetTag(buffers[i], &xlocator, &xforknum, &xblocknum);
+			Assert(RelFileLocatorEquals(bmr.smgr->smgr_rlocator.locator, xlocator));
+			Assert(xforknum == forknum);
+			Assert(xblocknum == blocknum + i);
+		}
+#endif
+
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!CompleteReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   CompleteReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
 			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
 			}
 			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-		}
-	}
-
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
-	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
-	}
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
 
-	if (isLocalBuf)
-	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if (zero_on_error || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
 
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
-	}
-	else
-	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
-	}
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
@@ -1228,11 +1380,8 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.  A read should be
+ * performed with CompleteReadBuffers().
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1291,19 +1440,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called PrepareReadBuffer() but not yet CompleteReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1368,19 +1508,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called PrepareReadBuffer() but not yet CompleteReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1412,15 +1543,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1774,7 +1899,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2043,7 +2168,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2066,7 +2191,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2381,7 +2506,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if PrepareReadBuffer() was called and
+		 * CompleteReadBuffers() hasn't been called yet.  We'll check by
+		 * loading the flags without locking.  This is racy, but it's OK to
+		 * return false spuriously: when CompleteReadBuffers() calls
+		 * StartBufferIO(), it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2390,7 +2520,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3458,7 +3588,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -4845,6 +4975,46 @@ ConditionalLockBuffer(Buffer buffer)
 									LW_EXCLUSIVE);
 }
 
+/*
+ * Zero a buffer, and lock it as RBM_ZERO_AND_LOCK or
+ * RBM_ZERO_AND_CLEANUP_LOCK would.  The buffer must be already pinned.  It
+ * does not have to be valid, but it is valid and locked on return.
+ */
+void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * Verify that this backend is pinning the buffer exactly once.
  *
@@ -5197,9 +5367,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5212,6 +5388,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 1be4f4f8daf..717b8f58daf 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -109,10 +109,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -288,7 +287,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -298,9 +297,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca27..739d13293fb 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 563a0be5c74..0d7272e796e 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -147,7 +147,9 @@ smgrshutdown(int code, Datum arg)
 /*
  * smgropen() -- Return an SMgrRelation object, creating it if need be.
  *
- * This does not attempt to actually open the underlying file.
+ * This does not attempt to actually open the underlying files.  The returned
+ * object remains valid at least until AtEOXact_SMgr() is called, or until
+ * smgrdestroy() is called in non-transaction backends.
  */
 SMgrRelation
 smgropen(RelFileLocator rlocator, BackendId backend)
@@ -259,10 +261,10 @@ smgrexists(SMgrRelation reln, ForkNumber forknum)
 }
 
 /*
- * smgrclose() -- Close and delete an SMgrRelation object.
+ * smgrdestroy() -- Delete an SMgrRelation object.
  */
 void
-smgrclose(SMgrRelation reln)
+smgrdestroy(SMgrRelation reln)
 {
 	SMgrRelation *owner;
 	ForkNumber	forknum;
@@ -289,12 +291,14 @@ smgrclose(SMgrRelation reln)
 }
 
 /*
- * smgrrelease() -- Release all resources used by this object.
+ * smgrclose() -- Release all resources used by this object.
  *
- * The object remains valid.
+ * The object remains valid, but is moved to the unknown list where it will
+ * be destroyed by AtEOXact_SMgr().  It may be re-owned if it is accessed by a
+ * relation before then.
  */
 void
-smgrrelease(SMgrRelation reln)
+smgrclose(SMgrRelation reln)
 {
 	for (ForkNumber forknum = 0; forknum <= MAX_FORKNUM; forknum++)
 	{
@@ -302,15 +306,20 @@ smgrrelease(SMgrRelation reln)
 		reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber;
 	}
 	reln->smgr_targblock = InvalidBlockNumber;
+
+	if (reln->smgr_owner)
+	{
+		*reln->smgr_owner = NULL;
+		reln->smgr_owner = NULL;
+		dlist_push_tail(&unowned_relns, &reln->node);
+	}
 }
 
 /*
- * smgrreleaseall() -- Release resources used by all objects.
- *
- * This is called for PROCSIGNAL_BARRIER_SMGRRELEASE.
+ * smgrcloseall() -- Close all objects.
  */
 void
-smgrreleaseall(void)
+smgrcloseall(void)
 {
 	HASH_SEQ_STATUS status;
 	SMgrRelation reln;
@@ -322,14 +331,17 @@ smgrreleaseall(void)
 	hash_seq_init(&status, SMgrRelationHash);
 
 	while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
-		smgrrelease(reln);
+		smgrclose(reln);
 }
 
 /*
- * smgrcloseall() -- Close all existing SMgrRelation objects.
+ * smgrdestroyall() -- Destroy all SMgrRelation objects.
+ *
+ * It must be known that there are no pointers to SMgrRelations, other than
+ * those registered with smgrsetowner().
  */
 void
-smgrcloseall(void)
+smgrdestroyall(void)
 {
 	HASH_SEQ_STATUS status;
 	SMgrRelation reln;
@@ -341,7 +353,7 @@ smgrcloseall(void)
 	hash_seq_init(&status, SMgrRelationHash);
 
 	while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
-		smgrclose(reln);
+		smgrdestroy(reln);
 }
 
 /*
@@ -733,7 +745,8 @@ smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
  * AtEOXact_SMgr
  *
  * This routine is called during transaction commit or abort (it doesn't
- * particularly care which).  All transient SMgrRelation objects are closed.
+ * particularly care which).  All transient SMgrRelation objects are
+ * destroyed.
  *
  * We do this as a compromise between wanting transient SMgrRelations to
  * live awhile (to amortize the costs of blind writes of multiple blocks)
@@ -747,7 +760,7 @@ AtEOXact_SMgr(void)
 	dlist_mutable_iter iter;
 
 	/*
-	 * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
+	 * Zap all unowned SMgrRelations.  We rely on smgrdestroy() to remove each
 	 * one from the list.
 	 */
 	dlist_foreach_modify(iter, &unowned_relns)
@@ -757,7 +770,7 @@ AtEOXact_SMgr(void)
 
 		Assert(rel->smgr_owner == NULL);
 
-		smgrclose(rel);
+		smgrdestroy(rel);
 	}
 }
 
@@ -768,6 +781,6 @@ AtEOXact_SMgr(void)
 bool
 ProcessBarrierSmgrRelease(void)
 {
-	smgrreleaseall();
+	smgrcloseall();
 	return true;
 }
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d3353..a38f1acb37a 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,18 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+extern Buffer PrepareReadBuffer(BufferManagerRelation bmr,
+								ForkNumber forkNum,
+								BlockNumber blockNum,
+								BufferAccessStrategy strategy,
+								bool *foundPtr);
+extern void CompleteReadBuffers(BufferManagerRelation bmr,
+								Buffer *buffers,
+								ForkNumber forknum,
+								BlockNumber blocknum,
+								int nblocks,
+								bool zero_on_error,
+								BufferAccessStrategy strategy);
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -247,9 +265,13 @@ extern void LockBufferForCleanup(Buffer buffer);
 extern bool ConditionalLockBufferForCleanup(Buffer buffer);
 extern bool IsBufferCleanupOK(Buffer buffer);
 extern bool HoldingBufferPinThatDelaysRecovery(void);
+extern void ZeroBuffer(Buffer buffer, ReadBufferMode mode);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 527cd2a0568..d8ffe397faf 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -85,8 +85,8 @@ extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln);
 extern void smgrclose(SMgrRelation reln);
 extern void smgrcloseall(void);
 extern void smgrcloserellocator(RelFileLocatorBackend rlocator);
-extern void smgrrelease(SMgrRelation reln);
-extern void smgrreleaseall(void);
+extern void smgrdestroy(SMgrRelation reln);
+extern void smgrdestroyall(void);
 extern void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
 extern void smgrdosyncall(SMgrRelation *rels, int nrels);
 extern void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 00000000000..40c3408c541
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,45 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index a584b1ddff3..6636cc82c09 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -561,12 +561,6 @@ typedef struct ViewOptions
  *
  * Very little code is authorized to touch rel->rd_smgr directly.  Instead
  * use this function to fetch its value.
- *
- * Note: since a relcache flush can cause the file handle to be closed again,
- * it's unwise to hold onto the pointer returned by this function for any
- * long period.  Recommended practice is to just re-execute RelationGetSmgr
- * each time you need to access the SMgrRelation.  It's quite cheap in
- * comparison to whatever an smgr function is going to do.
  */
 static inline SMgrRelation
 RelationGetSmgr(Relation rel)
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 91433d439b7..8007f17320a 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2094,6 +2094,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
-- 
2.37.2

v4-0014-BitmapHeapScan-uses-streaming-read-API.patchtext/x-diff; charset=us-asciiDownload
From 4c9c90df25b4e421c34913b5da3da071fd4b15e1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:04:18 -0500
Subject: [PATCH v4 14/14] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
---
 src/backend/access/heap/heapam.c          |  68 +++++
 src/backend/access/heap/heapam_handler.c  |  88 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 336 +---------------------
 src/include/access/heapam.h               |   4 +
 src/include/access/tableam.h              |  22 +-
 src/include/nodes/execnodes.h             |  19 --
 6 files changed, 117 insertions(+), 420 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b93f243c282..c965048af60 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -115,6 +115,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -335,6 +337,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -955,6 +973,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
 
@@ -1093,6 +1112,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10250,3 +10272,49 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (hdesc->rs_base.shared_tbmiterator)
+			tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+		else
+			tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index daa5902e24d..cade7edd900 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2113,79 +2113,65 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck, bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (scan->shared_tbmiterator)
-			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
-		else
-			tbm_iterate(scan->tbmiterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, and the bitmap entries don't need rechecking, and all tuples on
-	 * the page are visible to our transaction.
-	 */
-	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2206,7 +2192,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2215,9 +2201,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2267,7 +2253,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres.ntuples < 0;
+	*lossy = tbmres->ntuples < 0;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 74b92d4cbf4..c5a482cc175 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -54,11 +54,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -90,14 +85,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -113,15 +100,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
 		}
 		else
 		{
@@ -144,20 +122,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
 
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
@@ -165,14 +129,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -219,16 +175,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		node->initialized = true;
 
 		/* Get the first block. if none, end of scan */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy))
 			return ExecClearTuple(slot);
 
 		if (lossy)
 			node->lossy_pages++;
 		else
 			node->exact_pages++;
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	for (;;)
@@ -237,37 +190,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We prefetch before fetching the current pages. We expect that a
-			 * future streaming read API will do this, so do it this way now
-			 * for consistency. Also, this should happen only when we have
-			 * determined there is still something to do on the current page,
-			 * else we may uselessly prefetch the same page we are just about
-			 * to request for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -288,17 +210,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			return slot;
 		}
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy))
 			break;
 
 		if (lossy)
 			node->lossy_pages++;
 		else
 			node->exact_pages++;
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -322,215 +240,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult tbmpre;
-			tbm_iterate(prefetch_iterator, &tbmpre);
-
-			if (!BlockNumberIsValid(tbmpre.blockno) || tbmpre.blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
-		}
-		return;
-	}
-
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			TBMIterateResult tbmpre;
-
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -576,22 +285,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -630,16 +329,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -672,19 +365,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -724,13 +411,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -814,14 +494,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -853,11 +529,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3dfb19ec7d5..1cad9c04f01 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2adead958cb..1a7b9db8b40 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -792,23 +792,11 @@ typedef struct TableAmRoutine
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+	bool		(*scan_bitmap_next_block) (TableScanDesc scan, bool *recheck,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1984,8 +1972,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+table_scan_bitmap_next_block(TableScanDesc scan, bool *recheck, bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1995,8 +1982,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, lossy);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a59df51dd69..d41a3e134d8 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1682,11 +1682,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  *		phs_snapshot_data		snapshot data shared to workers
@@ -1695,10 +1692,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 	char		phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
@@ -1709,16 +1703,10 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
  *		recheck			   do current page's tuples need recheck
@@ -1729,20 +1717,13 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
 	bool		recheck;
-	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

#9Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#8)
14 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Feb 26, 2024 at 08:50:28PM -0500, Melanie Plageman wrote:

On Fri, Feb 16, 2024 at 12:35:59PM -0500, Melanie Plageman wrote:

In the attached v3, I've reordered the commits, updated some errant
comments, and improved the commit messages.

I've also made some updates to the TIDBitmap API that seem like a
clarity improvement to the API in general. These also reduce the diff
for GIN when separating the TBMIterateResult from the
TBM[Shared]Iterator. And these TIDBitmap API changes are now all in
their own commits (previously those were in the same commit as adding
the BitmapHeapScan streaming read user).

The three outstanding issues I see in the patch set are:
1) the lossy and exact page counters issue described in my previous
email

I've resolved this. I added a new patch to the set which starts counting
even pages with no visible tuples toward lossy and exact pages. After an
off-list conversation with Andres, it seems that this omission in master
may not have been intentional.

Once we have only two types of pages to differentiate between (lossy and
exact [no longer have to care about "has no visible tuples"]), it is
easy enough to pass a "lossy" boolean paramater to
table_scan_bitmap_next_block(). I've done this in the attached v4.

Thomas posted a new version of the Streaming Read API [1]/messages/by-id/CA+hUKGJtLyxcAEvLhVUhgD4fMQkOu3PDaj8Qb9SR_UsmzgsBpQ@mail.gmail.com, so here is a
rebased v5. This should make it easier to review as it can be applied on
top of master.

- Melanie

[1]: /messages/by-id/CA+hUKGJtLyxcAEvLhVUhgD4fMQkOu3PDaj8Qb9SR_UsmzgsBpQ@mail.gmail.com

Attachments:

v5-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From 5f523e4839c935f3b126b0c388129eb919c82b81 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v5 01/14] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.

ExecBitmapHeapInitializeWorker() overwrote the snapshot in the scan
descriptor with the correct one provided by the parallel leader. Since
ExecBitmapHeapInitializeWorker() is now called before the scan
descriptor has been created, save the worker's snapshot in the
BitmapHeapScanState and pass it to table_beginscan_bm().
---
 src/backend/access/table/tableam.c        | 11 ------
 src/backend/executor/nodeBitmapHeapscan.c | 47 ++++++++++++++++++-----
 src/include/access/tableam.h              | 10 ++---
 src/include/nodes/execnodes.h             |  2 +
 4 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 6ed8cca05a1..e78d793f69c 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,17 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-void
-table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot)
-{
-	Assert(IsMVCCSnapshot(snapshot));
-
-	RegisterSnapshot(snapshot);
-	scan->rs_snapshot = snapshot;
-	scan->rs_flags |= SO_TEMP_SNAPSHOT;
-}
-
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c1e81ebed63..44bf38be3c9 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -181,6 +181,34 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			Snapshot	snapshot = node->ss.ps.state->es_snapshot;
+			uint32		extra_flags = 0;
+
+			/*
+			 * Parallel workers must use the snapshot initialized by the
+			 * parallel leader.
+			 */
+			if (node->worker_snapshot)
+			{
+				snapshot = node->worker_snapshot;
+				extra_flags |= SO_TEMP_SNAPSHOT;
+			}
+
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	snapshot,
+																	0,
+																	NULL,
+																	extra_flags);
+		}
+
 		node->initialized = true;
 	}
 
@@ -604,7 +632,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -681,7 +710,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -739,6 +770,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	 */
 	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
 								 node->scan.plan.targetlist == NIL);
+	scanstate->worker_snapshot = NULL;
 
 	/*
 	 * Miscellaneous initialization
@@ -787,11 +819,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
@@ -930,13 +957,13 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 							   ParallelWorkerContext *pwcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	Snapshot	snapshot;
 
 	Assert(node->ss.ps.state->es_query_dsa != NULL);
 
 	pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
 	node->pstate = pstate;
 
-	snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
-	table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
+	node->worker_snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
+	Assert(IsMVCCSnapshot(node->worker_snapshot));
+	RegisterSnapshot(node->worker_snapshot);
 }
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5f8474871d2..5375dd7150f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -944,9 +944,10 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key,
+				   uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
@@ -1038,11 +1039,6 @@ table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
 										 allow_pagemode);
 }
 
-/*
- * Update snapshot used by the scan.
- */
-extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
-
 /*
  * Return next tuple from `scan`, store in slot.
  */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 444a5f0fd57..00c75fb10e2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1726,6 +1726,7 @@ typedef struct ParallelBitmapHeapState
  *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		worker_snapshot	   snapshot for parallel worker
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1750,6 +1751,7 @@ typedef struct BitmapHeapScanState
 	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	Snapshot	worker_snapshot;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v5-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From c76a0dc384143a23ac58d421df4d4956fee58961 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v5 02/14] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 44bf38be3c9..a9ba2bdfb88 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,6 +108,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -760,16 +770,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 	scanstate->worker_snapshot = NULL;
 
 	/*
-- 
2.37.2

v5-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-diff; charset=us-asciiDownload
From b4148fc01e789700309cb144ca5e68bbcd9c2aa6 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v5 03/14] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 ++++++
 src/backend/executor/nodeBitmapHeapscan.c | 118 ++++++----------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |   7 ++
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 94 insertions(+), 92 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 707460a5364..b93f243c282 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -955,6 +955,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1043,6 +1045,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1062,6 +1070,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 680a50bf8b1..c9b9b4c00f1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2122,6 +2123,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, and the bitmap entries don't need rechecking, and all tuples on
+	 * the page are visible to our transaction.
+	 */
+	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2234,6 +2253,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a9ba2bdfb88..2e4f87ea3a3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -108,16 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -211,6 +201,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				extra_flags |= SO_TEMP_SNAPSHOT;
 			}
 
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual == NIL && node->ss.ps.plan->targetlist == NIL)
+				extra_flags |= SO_CAN_SKIP_FETCH;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	snapshot,
@@ -224,8 +225,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -245,32 +244,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -318,52 +292,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -535,7 +490,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -586,7 +542,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -656,8 +612,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -667,7 +621,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -712,8 +665,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -757,8 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -770,7 +719,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 	scanstate->worker_snapshot = NULL;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f68593..3dfb19ec7d5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5375dd7150f..c193ea5db43 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed.
+	 */
+	SO_CAN_SKIP_FETCH = 1 << 10,
 }			ScanOptions;
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 00c75fb10e2..6fb4ec07c5f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1711,10 +1711,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1736,9 +1733,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.37.2

v5-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-diff; charset=us-asciiDownload
From 3df428a0428b821ed1c19bb19a18e0d3b3d60a4a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v5 04/14] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2e4f87ea3a3..35ef26221ba 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -484,15 +484,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
-
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -543,7 +537,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.37.2

v5-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-diff; charset=us-asciiDownload
From 43d0dd9b5661617bf61562f8c4bc189d66fc62a3 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v5 05/14] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 35ef26221ba..3439c02e989 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -55,7 +55,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -242,7 +242,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
@@ -351,7 +351,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -370,7 +370,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.37.2

v5-0006-EXPLAIN-Bitmap-table-scan-also-count-no-visible-t.patchtext/x-diff; charset=us-asciiDownload
From c0f80d78a1d2a940a825beeb394f8cd025d260c0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 18:35:28 -0500
Subject: [PATCH v5 06/14] EXPLAIN Bitmap table scan also count no visible
 tuple pages

Previously, bitmap heap scans only counted lossy and exact pages for
explain when there was at least one visible tuple on the page.

heapam_scan_bitmap_next_block() returned true only if there was a
"valid" page with tuples to be processed. However, the lossy and exact
page counters in EXPLAIN should count the number of pages represented in
a lossy or non-lossy way in the constructured bitmap, so it doesn't make
sense to omit pages without visible tuples.
---
 src/backend/executor/nodeBitmapHeapscan.c     | 15 ++++++++++-----
 src/test/regress/expected/partition_prune.out |  4 +++-
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3439c02e989..75e896074bf 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -225,6 +225,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
+		bool valid;
+
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -244,17 +246,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			if (!table_scan_bitmap_next_block(scan, tbmres))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
+			valid = table_scan_bitmap_next_block(scan, tbmres);
 
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
+			if (!valid)
+			{
+				/* AM doesn't think this block is valid, skip */
+				continue;
+			}
+
+
 			/* Adjust the prefetch target */
 			BitmapAdjustPrefetchTarget(node);
 		}
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index b41950d923b..7b1b1e97033 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -2812,6 +2812,7 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a;
                            Index Cond: (a = 1)
                ->  Bitmap Heap Scan on ab_a1_b3 ab_a1_3 (actual rows=0 loops=1)
                      Recheck Cond: (a = 1)
+                     Heap Blocks: exact=1
                      ->  Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1)
                            Index Cond: (a = 1)
          ->  Materialize (actual rows=1 loops=1)
@@ -2827,9 +2828,10 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a;
                                  Index Cond: (a = 1)
                      ->  Bitmap Heap Scan on ab_a1_b3 ab_3 (actual rows=0 loops=1)
                            Recheck Cond: (a = 1)
+                           Heap Blocks: exact=1
                            ->  Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1)
                                  Index Cond: (a = 1)
-(34 rows)
+(36 rows)
 
 table ab;
  a | b 
-- 
2.37.2

v5-0007-table_scan_bitmap_next_block-returns-lossy-or-exa.patchtext/x-diff; charset=us-asciiDownload
From 0f9b10773db6b406f2d9a481293a2fd1dfe0669d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v5 07/14] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c9b9b4c00f1..10c1c3b616b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,7 +2112,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2240,6 +2241,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 75e896074bf..054f745eeba 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -225,7 +225,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool valid;
+		bool valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -246,12 +246,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index c193ea5db43..8280035e39f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -796,6 +796,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -811,7 +814,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1952,14 +1956,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1970,7 +1976,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.37.2

v5-0008-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-diff; charset=us-asciiDownload
From 9df8ee50ea111a49a04397db0ff2b77d89eab7a9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v5 08/14] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 054f745eeba..a639d6e7415 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -74,8 +74,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -88,10 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -108,6 +102,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -116,7 +113,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -169,8 +166,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -220,6 +216,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -235,9 +233,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.37.2

v5-0009-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-diff; charset=us-asciiDownload
From 8a31b11113194b26526c3931d98e022f7f1d6603 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v5 09/14] Remove table_scan_bitmap_next_tuple parameter tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 10c1c3b616b..a1ec50ab7a8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2248,7 +2248,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a639d6e7415..87991266931 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -301,7 +301,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8280035e39f..8d7c800d157 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -787,10 +787,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -821,15 +818,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -1989,7 +1981,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2001,7 +1992,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.37.2

v5-0010-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From b89d1e2133e1959750c9081e27dfa21f4fa7e46b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:57:07 -0500
Subject: [PATCH v5 10/14] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c | 167 +++++++++-------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 ++++++---
 src/include/nodes/execnodes.h             |   9 +-
 5 files changed, 168 insertions(+), 142 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a1ec50ab7a8..e038e60cd8f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,18 +2112,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, and the bitmap entries don't need rechecking, and all tuples on
@@ -2142,16 +2175,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2243,7 +2267,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 87991266931..3be433ea6e1 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -73,8 +73,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -86,7 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -114,7 +113,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -167,7 +165,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -216,56 +213,29 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
-		node->initialized = true;
-	}
-
-	for (;;)
-	{
-		bool valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
+		node->initialized = true;
 
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
+		/* Get the first block. if none, end of scan */
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			return ExecClearTuple(slot);
 
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
 
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		BitmapAdjustPrefetchTarget(node);
+	}
 
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+	for (;;)
+	{
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -287,45 +257,48 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
-
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
-		}
+			/*
+			 * We prefetch before fetching the current pages. We expect that a
+			 * future streaming read API will do this, so do it this way now
+			 * for consistency. Also, this should happen only when we have
+			 * determined there is still something to do on the current page,
+			 * else we may uselessly prefetch the same page we are just about
+			 * to request for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
-		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
 			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
 			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
-		/* OK to return this tuple */
-		return slot;
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
+		BitmapAdjustPrefetchIterator(node, node->blockno);
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -599,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -612,13 +581,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -649,28 +617,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -703,8 +667,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -713,10 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8d7c800d157..2adead958cb 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -780,19 +781,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -811,8 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -950,9 +946,13 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key,
 				   uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1012,6 +1012,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1022,6 +1037,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1945,19 +1975,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1967,8 +1995,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6fb4ec07c5f..a59df51dd69 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1709,8 +1709,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1720,10 +1718,10 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
+ *		recheck			   do current page's tuples need recheck
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1731,8 +1729,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1742,10 +1738,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
+	bool		recheck;
+	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

v5-0011-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From c6518284a8c20aa4d9e3e2267ad2dfa0acb2aefa Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v5 11/14] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 29 +++++++----------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..d2bf8f44d50 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1467,8 +1453,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..432fae52962 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.37.2

v5-0012-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchtext/x-diff; charset=us-asciiDownload
From 602ad80e9045384c19387145bff41893945423ab Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v5 12/14] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 33 +++++-----
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 7 files changed, 107 insertions(+), 87 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3aa457a29e1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..033d5253394 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e038e60cd8f..022753e203a 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,7 +2119,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2132,11 +2132,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		CHECK_FOR_INTERRUPTS();
 
 		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbm_iterate(scan->tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2151,11 +2151,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2163,19 +2163,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * the page are visible to our transaction.
 	 */
 	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2204,7 +2204,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2213,9 +2213,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2265,7 +2265,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	*lossy = tbmres.ntuples < 0;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3be433ea6e1..74b92d4cbf4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -344,9 +344,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+			TBMIterateResult tbmpre;
+			tbm_iterate(prefetch_iterator, &tbmpre);
 
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
+			if (!BlockNumberIsValid(tbmpre.blockno) || tbmpre.blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
@@ -364,6 +365,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		}
 		else
 		{
+			TBMIterateResult tbmpre;
+
 			/* Release the mutex before iterating */
 			SpinLockRelease(&pstate->mutex);
 
@@ -376,7 +379,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -443,10 +446,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
@@ -462,13 +467,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -483,7 +488,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -502,8 +507,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_shared_iterate(prefetch_iterator);
@@ -513,13 +518,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index d2bf8f44d50..7d038c2018d 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..3b432263bb0 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae52962..f000c1af28f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.37.2

v5-0013-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From 1b50526e266f2413e04572f8ea5007805e2f20c2 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 26 Feb 2024 23:48:31 +1300
Subject: [PATCH v5 13/14] Streaming Read API

---
 contrib/pg_prewarm/pg_prewarm.c          |  40 +-
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 612 ++++++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 641 ++++++++++++++++-------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/include/storage/bufmgr.h             |  45 ++
 src/include/storage/streaming_read.h     |  52 ++
 src/tools/pgindent/typedefs.list         |   3 +
 11 files changed, 1218 insertions(+), 211 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/contrib/pg_prewarm/pg_prewarm.c b/contrib/pg_prewarm/pg_prewarm.c
index 8541e4d6e46..1cc84bcb0c2 100644
--- a/contrib/pg_prewarm/pg_prewarm.c
+++ b/contrib/pg_prewarm/pg_prewarm.c
@@ -20,6 +20,7 @@
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
 #include "storage/smgr.h"
+#include "storage/streaming_read.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -38,6 +39,25 @@ typedef enum
 
 static PGIOAlignedBlock blockbuffer;
 
+struct pg_prewarm_streaming_read_private
+{
+	BlockNumber blocknum;
+	int64		last_block;
+};
+
+static BlockNumber
+pg_prewarm_streaming_read_next(PgStreamingRead *pgsr,
+							   void *pgsr_private,
+							   void *per_buffer_data)
+{
+	struct pg_prewarm_streaming_read_private *p = pgsr_private;
+
+	if (p->blocknum <= p->last_block)
+		return p->blocknum++;
+
+	return InvalidBlockNumber;
+}
+
 /*
  * pg_prewarm(regclass, mode text, fork text,
  *			  first_block int8, last_block int8)
@@ -183,18 +203,36 @@ pg_prewarm(PG_FUNCTION_ARGS)
 	}
 	else if (ptype == PREWARM_BUFFER)
 	{
+		struct pg_prewarm_streaming_read_private p;
+		PgStreamingRead *pgsr;
+
 		/*
 		 * In buffer mode, we actually pull the data into shared_buffers.
 		 */
+
+		/* Set up the private state for our streaming buffer read callback. */
+		p.blocknum = first_block;
+		p.last_block = last_block;
+
+		pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_FULL,
+											  &p,
+											  0,
+											  NULL,
+											  BMR_REL(rel),
+											  forkNumber,
+											  pg_prewarm_streaming_read_next);
+
 		for (block = first_block; block <= last_block; ++block)
 		{
 			Buffer		buf;
 
 			CHECK_FOR_INTERRUPTS();
-			buf = ReadBufferExtended(rel, forkNumber, block, RBM_NORMAL, NULL);
+			buf = pg_streaming_read_buffer_get_next(pgsr, NULL);
 			ReleaseBuffer(buf);
 			++blocks_done;
 		}
+		Assert(pg_streaming_read_buffer_get_next(pgsr, NULL) == InvalidBuffer);
+		pg_streaming_read_free(pgsr);
 	}
 
 	/* Close relation, release lock. */
diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca20..eec03f6f2b4 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 00000000000..bcab44c802f
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 00000000000..39aef2a84a2
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 00000000000..71f2c4a70b6
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,612 @@
+#include "postgres.h"
+
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		need_wait;
+	bool		advice_issued;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index;
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+	ReadBuffersOperation operation;
+} PgStreamingReadRange;
+
+/*
+ * Streaming read object.
+ */
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			pinned_buffers_trigger;
+	int			next_tail_buffer;
+	int			ramp_up_pin_limit;
+	int			ramp_up_pin_stall;
+	bool		finished;
+	bool		advice_enabled;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	/* Sometimes we need to buffer one block for flow control. */
+	BlockNumber unget_blocknum;
+	void	   *unget_per_buffer_data;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+static PgStreamingRead *
+pg_streaming_read_buffer_alloc_internal(int flags,
+										void *pgsr_private,
+										size_t per_buffer_data_size,
+										BufferAccessStrategy strategy)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = maintenance_io_concurrency;
+	else
+		max_ios = effective_io_concurrency;
+
+	/*
+	 * The desired level of I/O concurrency controls how far ahead we are
+	 * willing to look ahead.  We also clamp it to at least
+	 * MAX_BUFFER_PER_TRANFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/*
+	 * The *_io_concurrency GUCs might be set to 0, but we want to allow at
+	 * least one, to keep our gating logic simple.
+	 */
+	max_ios = Max(max_ios, 1);
+
+	/*
+	 * Don't allow this backend to pin too many buffers.  For now we'll apply
+	 * the limit for the shared buffer pool and the local buffer pool, without
+	 * worrying which it is.
+	 */
+	LimitAdditionalPins(&max_pinned_buffers);
+	LimitAdditionalLocalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+	pgsr->unget_blocknum = InvalidBlockNumber;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * We start off building small ranges, but double that quickly, for the
+	 * benefit of users that don't know how far ahead they'll read.  This can
+	 * be disabled by users that already know they'll read all the way.
+	 */
+	if (flags & PGSR_FLAG_FULL)
+		pgsr->ramp_up_pin_limit = INT_MAX;
+	else
+		pgsr->ramp_up_pin_limit = 1;
+
+	/*
+	 * We want to avoid creating ranges that are smaller than they could be
+	 * just because we hit max_pinned_buffers.  We only look ahead when the
+	 * number of pinned buffers falls below this trigger number, or put
+	 * another way, we stop looking ahead when we wouldn't be able to build a
+	 * "full sized" range.
+	 */
+	pgsr->pinned_buffers_trigger =
+		Max(1, (int) max_pinned_buffers - MAX_BUFFERS_PER_TRANSFER);
+
+	/* Space for the callback to store extra data along with each block. */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * max_pinned_buffers);
+
+	return pgsr;
+}
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *result;
+
+	result = pg_streaming_read_buffer_alloc_internal(flags,
+													 pgsr_private,
+													 per_buffer_data_size,
+													 strategy);
+	result->callback = next_block_cb;
+	result->bmr = bmr;
+	result->forknum = forknum;
+
+	return result;
+}
+
+/*
+ * Find the per-buffer data index for the Nth block of a range.
+ */
+static int
+get_per_buffer_data_index(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	int			result;
+
+	/*
+	 * Find slot in the circular buffer of per-buffer data, without using the
+	 * expensive % operator.
+	 */
+	result = range->per_buffer_data_index + n;
+	if (result >= pgsr->max_pinned_buffers)
+		result -= pgsr->max_pinned_buffers;
+	Assert(result == (range->per_buffer_data_index + n) % pgsr->max_pinned_buffers);
+
+	return result;
+}
+
+/*
+ * Return a pointer to the per-buffer data by index.
+ */
+static void *
+get_per_buffer_data_by_index(PgStreamingRead *pgsr, int per_buffer_data_index)
+{
+	return (char *) pgsr->per_buffer_data +
+		pgsr->per_buffer_data_size * per_buffer_data_index;
+}
+
+/*
+ * Return a pointer to the per-buffer data for the Nth block of a range.
+ */
+static void *
+get_per_buffer_data(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	return get_per_buffer_data_by_index(pgsr,
+										get_per_buffer_data_index(pgsr,
+																  range,
+																  n));
+}
+
+/*
+ * Start reading the head range, and create a new head range.  The new head
+ * range is returned.  It may not be empty, if StartReadBuffers() couldn't
+ * start the entire range; in that case the returned range contains the
+ * remaining portion of the range.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_start_head_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+	PgStreamingReadRange *new_head_range;
+	int			nblocks_pinned;
+	int			flags;
+
+	/* Caller should make sure we never exceed max_ios. */
+	Assert(pgsr->ios_in_progress < pgsr->max_ios);
+
+	/* Should only call if the head range has some blocks to read. */
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If advice hasn't been suppressed, and this system supports it, this
+	 * isn't a strictly sequential pattern, then we'll issue advice.
+	 */
+	if (pgsr->advice_enabled && head_range->blocknum != pgsr->seq_blocknum)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else
+		flags = 0;
+
+
+	/* Start reading as many blocks as we can from the head range. */
+	nblocks_pinned = head_range->nblocks;
+	head_range->need_wait =
+		StartReadBuffers(pgsr->bmr,
+						 head_range->buffers,
+						 pgsr->forknum,
+						 head_range->blocknum,
+						 &nblocks_pinned,
+						 pgsr->strategy,
+						 flags,
+						 &head_range->operation);
+
+	/* Did that start an I/O? */
+	if (head_range->need_wait && (flags & READ_BUFFERS_ISSUE_ADVICE))
+	{
+		head_range->advice_issued = true;
+		pgsr->ios_in_progress++;
+		Assert(pgsr->ios_in_progress <= pgsr->max_ios);
+	}
+
+	/*
+	 * StartReadBuffers() might have pinned fewer blocks than we asked it to,
+	 * but always at least one.
+	 */
+	Assert(nblocks_pinned <= head_range->nblocks);
+	Assert(nblocks_pinned >= 1);
+	pgsr->pinned_buffers += nblocks_pinned;
+
+	/*
+	 * Remember where the next block would be after that, so we can detect
+	 * sequential access next time.
+	 */
+	pgsr->seq_blocknum = head_range->blocknum + nblocks_pinned;
+
+	/*
+	 * Create a new head range.  There must be space, because we have enough
+	 * elements for every range to hold just one block, up to the pin limit.
+	 */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	new_head_range = &pgsr->ranges[pgsr->head];
+	new_head_range->nblocks = 0;
+	new_head_range->advice_issued = false;
+
+	/*
+	 * If we didn't manage to start the whole read above, we split the range,
+	 * moving the remainder into the new head range.
+	 */
+	if (nblocks_pinned < head_range->nblocks)
+	{
+		int			nblocks_remaining = head_range->nblocks - nblocks_pinned;
+
+		head_range->nblocks = nblocks_pinned;
+
+		new_head_range->blocknum = head_range->blocknum + nblocks_pinned;
+		new_head_range->nblocks = nblocks_remaining;
+	}
+
+	/* The new range has per-buffer data starting after the previous range. */
+	new_head_range->per_buffer_data_index =
+		get_per_buffer_data_index(pgsr, head_range, nblocks_pinned);
+
+	return new_head_range;
+}
+
+/*
+ * Ask the callback which block it would like us to read next, with a small
+ * buffer in front to allow pg_streaming_unget_block() to work.
+ */
+static BlockNumber
+pg_streaming_get_block(PgStreamingRead *pgsr, void *per_buffer_data)
+{
+	BlockNumber result;
+
+	if (unlikely(pgsr->unget_blocknum != InvalidBlockNumber))
+	{
+		/*
+		 * If we had to unget a block, now it is time to return that one
+		 * again.
+		 */
+		result = pgsr->unget_blocknum;
+		pgsr->unget_blocknum = InvalidBlockNumber;
+
+		/*
+		 * The same per_buffer_data element must have been used, and still
+		 * contains whatever data the callback wrote into it.  So we just
+		 * sanity-check that we were called with the value that
+		 * pg_streaming_unget_block() pushed back.
+		 */
+		Assert(per_buffer_data == pgsr->unget_per_buffer_data);
+	}
+	else
+	{
+		/* Use the installed callback directly. */
+		result = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+	}
+
+	return result;
+}
+
+/*
+ * In order to deal with short reads in StartReadBuffers(), we sometimes need
+ * to defer handling of a block until later.  This *must* be called with the
+ * last value returned by pg_streaming_get_block().
+ */
+static void
+pg_streaming_unget_block(PgStreamingRead *pgsr, BlockNumber blocknum, void *per_buffer_data)
+{
+	Assert(pgsr->unget_blocknum == InvalidBlockNumber);
+	pgsr->unget_blocknum = blocknum;
+	pgsr->unget_per_buffer_data = per_buffer_data;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *range;
+
+	/*
+	 * If we're still ramping up, we may have to stall to wait for buffers to
+	 * be consumed first before we do any more prefetching.
+	 */
+	if (pgsr->ramp_up_pin_stall > 0)
+	{
+		Assert(pgsr->pinned_buffers > 0);
+		return;
+	}
+
+	/*
+	 * If we're finished or can't start more I/O, then don't look ahead.
+	 */
+	if (pgsr->finished || pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/*
+	 * We'll also wait until the number of pinned buffers falls below our
+	 * trigger level, so that we have the chance to create a full range.
+	 */
+	if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger)
+		return;
+
+	do
+	{
+		BlockNumber blocknum;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		range = &pgsr->ranges[pgsr->head];
+		if (range->nblocks == lengthof(range->buffers))
+		{
+			/* Start as much of it as we can. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/* If we're now at the I/O limit, stop here. */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+				return;
+
+			/*
+			 * If we couldn't form a full range, then stop here to avoid
+			 * creating small I/O.
+			 */
+			if (pgsr->pinned_buffers >= pgsr->pinned_buffers_trigger)
+				return;
+
+			/*
+			 * That might have only been partially started, but always
+			 * processes at least one so that'll do for now.
+			 */
+			Assert(range->nblocks < lengthof(range->buffers));
+		}
+
+		/* Find per-buffer data slot for the next block. */
+		per_buffer_data = get_per_buffer_data(pgsr, range, range->nblocks);
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pg_streaming_get_block(pgsr, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			/* End of stream. */
+			pgsr->finished = true;
+			break;
+		}
+
+		/*
+		 * Is there a head range that we cannot extend, because the requested
+		 * block is not consecutive?
+		 */
+		if (range->nblocks > 0 &&
+			range->blocknum + range->nblocks != blocknum)
+		{
+			/* Yes.  Start it, so we can begin building a new one. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * It's possible that it was only partially started, and we have a
+			 * new range with the remainder.  Keep starting I/Os until we get
+			 * it all out of the way, or we hit the I/O limit.
+			 */
+			while (range->nblocks > 0 && pgsr->ios_in_progress < pgsr->max_ios)
+				range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * We have to 'unget' the block returned by the callback if we
+			 * don't have enough I/O capacity left to start something.
+			 */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+			{
+				pg_streaming_unget_block(pgsr, blocknum, per_buffer_data);
+				return;
+			}
+		}
+
+		/* If we have a new, empty range, initialize the start block. */
+		if (range->nblocks == 0)
+		{
+			range->blocknum = blocknum;
+		}
+
+		/* This block extends the range by one. */
+		Assert(range->blocknum + range->nblocks == blocknum);
+		range->nblocks++;
+
+	} while (pgsr->pinned_buffers + range->nblocks < pgsr->max_pinned_buffers &&
+			 pgsr->pinned_buffers + range->nblocks < pgsr->ramp_up_pin_limit);
+
+	/* If we've hit the ramp-up limit, insert a stall. */
+	if (pgsr->pinned_buffers + range->nblocks >= pgsr->ramp_up_pin_limit)
+	{
+		/* Can't get here if an earlier stall hasn't finished. */
+		Assert(pgsr->ramp_up_pin_stall == 0);
+		/* Don't do any more prefetching until these buffers are consumed. */
+		pgsr->ramp_up_pin_stall = pgsr->ramp_up_pin_limit;
+		/* Double it.  It will soon be out of the way. */
+		pgsr->ramp_up_pin_limit *= 2;
+	}
+
+	/* Start as much as we can. */
+	while (range->nblocks > 0)
+	{
+		range = pg_streaming_read_start_head_range(pgsr);
+		if (pgsr->ios_in_progress == pgsr->max_ios)
+			break;
+	}
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	pg_streaming_read_look_ahead(pgsr);
+
+	/* See if we have one buffer to return. */
+	while (pgsr->tail != pgsr->head)
+	{
+		PgStreamingReadRange *tail_range;
+
+		tail_range = &pgsr->ranges[pgsr->tail];
+
+		/*
+		 * Do we need to perform an I/O before returning the buffers from this
+		 * range?
+		 */
+		if (tail_range->need_wait)
+		{
+			WaitReadBuffers(&tail_range->operation);
+			tail_range->need_wait = false;
+
+			/*
+			 * We don't really know if the kernel generated a physical I/O
+			 * when we issued advice, let alone when it finished, but it has
+			 * certainly finished now because we've performed the read.
+			 */
+			if (tail_range->advice_issued)
+			{
+				Assert(pgsr->ios_in_progress > 0);
+				pgsr->ios_in_progress--;
+			}
+		}
+
+		/* Are there more buffers available in this range? */
+		if (pgsr->next_tail_buffer < tail_range->nblocks)
+		{
+			int			buffer_index;
+			Buffer		buffer;
+
+			buffer_index = pgsr->next_tail_buffer++;
+			buffer = tail_range->buffers[buffer_index];
+
+			Assert(BufferIsValid(buffer));
+
+			/* We are giving away ownership of this pinned buffer. */
+			Assert(pgsr->pinned_buffers > 0);
+			pgsr->pinned_buffers--;
+
+			if (pgsr->ramp_up_pin_stall > 0)
+				pgsr->ramp_up_pin_stall--;
+
+			if (per_buffer_data)
+				*per_buffer_data = get_per_buffer_data(pgsr, tail_range, buffer_index);
+
+			return buffer;
+		}
+
+		/* Advance tail to next range, if there is one. */
+		if (++pgsr->tail == pgsr->size)
+			pgsr->tail = 0;
+		pgsr->next_tail_buffer = 0;
+
+		/*
+		 * If tail crashed into head, and head is not empty, then it is time
+		 * to start that range.
+		 */
+		if (pgsr->tail == pgsr->head &&
+			pgsr->ranges[pgsr->head].nblocks > 0)
+			pg_streaming_read_start_head_range(pgsr);
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead. */
+	pgsr->finished = true;
+
+	/* Unpin anything that wasn't consumed. */
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	Assert(pgsr->pinned_buffers == 0);
+	Assert(pgsr->ios_in_progress == 0);
+
+	/* Release memory. */
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index bdf89bbc4dc..3b1b0ad99df 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -19,6 +19,11 @@
  *		and pin it so that no one can destroy it while this process
  *		is using it.
  *
+ * StartReadBuffers() -- as above, but for multiple contiguous blocks in
+ *		two steps.
+ *
+ * WaitReadBuffers() -- second step of StartReadBuffers().
+ *
  * ReleaseBuffer() -- unpin a buffer
  *
  * MarkBufferDirty() -- mark a pinned buffer's contents as "dirty".
@@ -472,10 +477,9 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
-								ReadBufferMode mode, BufferAccessStrategy strategy,
-								bool *hit);
+								ReadBufferMode mode, BufferAccessStrategy strategy);
 static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
 										   ForkNumber fork,
 										   BufferAccessStrategy strategy,
@@ -501,7 +505,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -782,7 +786,6 @@ Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
-	bool		hit;
 	Buffer		buf;
 
 	/*
@@ -795,15 +798,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
-							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+	buf = ReadBuffer_common(BMR_REL(reln),
+							forkNum, blockNum, mode, strategy);
+
 	return buf;
 }
 
@@ -823,13 +820,12 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 						  BlockNumber blockNum, ReadBufferMode mode,
 						  BufferAccessStrategy strategy, bool permanent)
 {
-	bool		hit;
-
 	SMgrRelation smgr = smgropen(rlocator, InvalidBackendId);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
-							 mode, strategy, &hit);
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
+							 mode, strategy);
 }
 
 /*
@@ -995,35 +991,68 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 	 */
 	if (buffer == InvalidBuffer)
 	{
-		bool		hit;
-
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
-								   fork, extend_to - 1, mode, strategy,
-								   &hit);
+		buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
 	}
 
 	return buffer;
 }
 
+/*
+ * Zero a buffer and lock it, as part of the implementation of
+ * RBM_ZERO_AND_LOCK or RBM_ZERO_AND_CLEANUP_LOCK.  The buffer must be already
+ * pinned.  It does not have to be valid, but it is valid and locked on
+ * return.
+ */
+static void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * ReadBuffer_common -- common logic for all ReadBuffer variants
  *
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
-				  BufferAccessStrategy strategy, bool *hit)
+				  BufferAccessStrategy strategy)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	ReadBuffersOperation operation;
+	Buffer		buffer;
+	int			nblocks;
+	int			flags;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1042,181 +1071,404 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	nblocks = 1;
+	if (mode == RBM_ZERO_ON_ERROR)
+		flags = READ_BUFFERS_ZERO_ON_ERROR;
+	else
+		flags = 0;
+	if (StartReadBuffers(bmr,
+						 &buffer,
+						 forkNum,
+						 blockNum,
+						 &nblocks,
+						 strategy,
+						 flags,
+						 &operation))
+		WaitReadBuffers(&operation);
+	Assert(nblocks == 1);		/* single block can't be short */
+
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+		ZeroBuffer(buffer, mode);
+
+	return buffer;
+}
+
+static Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
 
+	Assert(bmr.smgr);
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * WaitReadBuffers() (so, not for hits, and not for buffers that are
+		 * zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+/*
+ * Begin reading a range of blocks beginning at blockNum and extending for
+ * *nblocks.  On return, up to *nblocks pinned buffers holding those blocks
+ * are written into the buffers array, and *nblocks is updated to contain the
+ * actual number, which may be fewer than requested.
+ *
+ * If false is returned, no I/O is necessary and WaitReadBuffers() is not
+ * necessary.  If true is returned, one I/O has been started, and
+ * WaitReadBuffers() must be called with the same operation object before the
+ * buffers are accessed.  Along with the operation object, the caller-supplied
+ * array of buffers must remain valid until WaitReadBuffers() is called.
+ *
+ * Currently the I/O is only started with optional operating system advice,
+ * and the real I/O happens in WaitReadBuffers().  In future work, true I/O
+ * could be initiated here.
+ */
+bool
+StartReadBuffers(BufferManagerRelation bmr,
+				 Buffer *buffers,
+				 ForkNumber forkNum,
+				 BlockNumber blockNum,
+				 int *nblocks,
+				 BufferAccessStrategy strategy,
+				 int flags,
+				 ReadBuffersOperation *operation)
+{
+	int			actual_nblocks = *nblocks;
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
 	}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+	operation->bmr = bmr;
+	operation->forknum = forkNum;
+	operation->blocknum = blockNum;
+	operation->buffers = buffers;
+	operation->nblocks = actual_nblocks;
+	operation->strategy = strategy;
+	operation->flags = flags;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	operation->io_buffers_len = 0;
 
-	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
-	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
-	else
+	for (int i = 0; i < actual_nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		bool		found;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+		buffers[i] = PrepareReadBuffer(bmr,
+									   forkNum,
+									   blockNum + i,
+									   strategy,
+									   &found);
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		if (found)
+		{
+			/*
+			 * Terminate the read as soon as we get a hit.  It could be a
+			 * single buffer hit, or it could be a hit that follows a readable
+			 * range.  We don't want to create more than one readable range,
+			 * so we stop here.
+			 */
+			actual_nblocks = operation->nblocks = *nblocks = i + 1;
+		}
+		else
+		{
+			/* Extend the readable range to cover this block. */
+			operation->io_buffers_len++;
+		}
+	}
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+	if (operation->io_buffers_len > 0)
+	{
+		if (flags & READ_BUFFERS_ISSUE_ADVICE)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
-			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
-			}
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
+			/*
+			 * In theory we should only do this if PrepareReadBuffers() had to
+			 * allocate new buffers above.  That way, if two calls to
+			 * StartReadBuffers() were made for the same blocks before
+			 * WaitReadBuffers(), only the first would issue the advice.
+			 * That'd be a better simulation of true asynchronous I/O, which
+			 * would only start the I/O once, but isn't done here for
+			 * simplicity.  Note also that the following call might actually
+			 * issue two advice calls if we cross a segment boundary; in a
+			 * true asynchronous version we might choose to process only one
+			 * real I/O at a time in that case.
+			 */
+			smgrprefetch(bmr.smgr, forkNum, blockNum, operation->io_buffers_len);
 		}
+
+		/* Indicate that WaitReadBuffers() should be called. */
+		return true;
 	}
+	else
+	{
+		return false;
+	}
+}
 
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
+static inline bool
+WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
 	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
+
+void
+WaitReadBuffers(ReadBuffersOperation *operation)
+{
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	int			nblocks;
+	BlockNumber blocknum;
+	ForkNumber	forknum;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	/*
+	 * Currently operations are only allowed to include a read of some range,
+	 * with an optional extra buffer that is already pinned at the end.  So
+	 * nblocks can be at most one more than io_buffers_len.
+	 */
+	Assert((operation->nblocks == operation->io_buffers_len) ||
+		   (operation->nblocks == operation->io_buffers_len + 1));
 
+	/* Find the range of the physical read we need to perform. */
+	nblocks = operation->io_buffers_len;
+	if (nblocks == 0)
+		return;					/* nothing to do */
+
+	buffers = &operation->buffers[0];
+	blocknum = operation->blocknum;
+	forknum = operation->forknum;
+	bmr = operation->bmr;
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
-
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
 	}
 	else
 	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
+		io_context = IOContextForStrategy(operation->strategy);
+		io_object = IOOBJECT_RELATION;
 	}
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+	/*
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
+	 */
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
+	else
+		pgBufferUsage.shared_blks_read += nblocks;
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+	for (int i = 0; i < nblocks; ++i)
+	{
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!WaitReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
+
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   WaitReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
+		{
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
+			{
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
+			}
+			else
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
+
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
+
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
+
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
+
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
- * BufferAlloc -- subroutine for ReadBuffer.  Handles lookup of a shared
- *		buffer.  If no buffer exists already, selects a replacement
- *		victim and evicts the old page, but does NOT read in new page.
+ * BufferAlloc -- subroutine for StartReadBuffers.  Handles lookup of a shared
+ *		buffer.  If no buffer exists already, selects a replacement victim and
+ *		evicts the old page, but does NOT read in new page.
  *
  * "strategy" can be a buffer replacement strategy object, or NULL for
  * the default strategy.  The selected buffer's usage_count is advanced when
@@ -1224,11 +1476,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1287,19 +1535,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1364,19 +1603,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1408,15 +1638,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1770,7 +1994,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2035,7 +2259,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2058,7 +2282,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2373,7 +2597,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if StartReadBuffers() was called and
+		 * WaitReadBuffers() hasn't been called yet.  We'll check by loading
+		 * the flags without locking.  This is racy, but it's OK to return
+		 * false spuriously: when WaitReadBuffers() calls StartBufferIO(),
+		 * it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2382,7 +2611,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3450,7 +3679,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -5185,9 +5414,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5200,6 +5435,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 1f02fed250e..6956d4e5b49 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -109,10 +109,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -288,7 +287,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -298,9 +297,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca27..739d13293fb 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d3353..b57f71f97e3 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,42 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+
+#define READ_BUFFERS_ZERO_ON_ERROR 0x01
+#define READ_BUFFERS_ISSUE_ADVICE 0x02
+
+/*
+ * Private state used by StartReadBuffers() and WaitReadBuffers().  Declared
+ * in public header only to allow inclusion in other structs, but contents
+ * should not be accessed.
+ */
+struct ReadBuffersOperation
+{
+	/* Parameters passed in to StartReadBuffers(). */
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	ForkNumber	forknum;
+	BlockNumber blocknum;
+	int			nblocks;
+	BufferAccessStrategy strategy;
+	int			flags;
+
+	/* Range of buffers, if we need to perform a read. */
+	int			io_buffers_len;
+};
+
+typedef struct ReadBuffersOperation ReadBuffersOperation;
+
+extern bool StartReadBuffers(BufferManagerRelation bmr,
+							 Buffer *buffers,
+							 ForkNumber forknum,
+							 BlockNumber blocknum,
+							 int *nblocks,
+							 BufferAccessStrategy strategy,
+							 int flags,
+							 ReadBuffersOperation *operation);
+extern void WaitReadBuffers(ReadBuffersOperation *operation);
+
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -250,6 +292,9 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 00000000000..c4d3892bb26
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,52 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+/*
+ * We usually ramp up from smaller reads to larger ones, to support users who
+ * don't know if it's worth reading lots of buffers yet.  This flag disables
+ * that, declaring ahead of time that we'll be reading all available buffers.
+ */
+#define PGSR_FLAG_FULL 0x04
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index fc8b15d0cf2..cfb58cf4836 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2097,6 +2097,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
@@ -2267,6 +2269,7 @@ ReInitializeDSMForeignScan_function
 ReScanForeignScan_function
 ReadBufPtrType
 ReadBufferMode
+ReadBuffersOperation
 ReadBytePtrType
 ReadExtraTocPtrType
 ReadFunc
-- 
2.37.2

v5-0014-BitmapHeapScan-uses-streaming-read-API.patchtext/x-diff; charset=us-asciiDownload
From e2267faf0fed9006fb0b437406737f1644d582c2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:04:18 -0500
Subject: [PATCH v5 14/14] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
---
 src/backend/access/heap/heapam.c          |  68 +++++
 src/backend/access/heap/heapam_handler.c  |  88 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 336 +---------------------
 src/include/access/heapam.h               |   4 +
 src/include/access/tableam.h              |  22 +-
 src/include/nodes/execnodes.h             |  19 --
 6 files changed, 117 insertions(+), 420 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b93f243c282..c965048af60 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -115,6 +115,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -335,6 +337,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -955,6 +973,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
 
@@ -1093,6 +1112,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10250,3 +10272,49 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (hdesc->rs_base.shared_tbmiterator)
+			tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+		else
+			tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 022753e203a..9727613e87f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2111,79 +2111,65 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck, bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (scan->shared_tbmiterator)
-			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
-		else
-			tbm_iterate(scan->tbmiterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, and the bitmap entries don't need rechecking, and all tuples on
-	 * the page are visible to our transaction.
-	 */
-	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2204,7 +2190,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2213,9 +2199,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2265,7 +2251,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres.ntuples < 0;
+	*lossy = tbmres->ntuples < 0;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 74b92d4cbf4..c5a482cc175 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -54,11 +54,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -90,14 +85,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -113,15 +100,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
 		}
 		else
 		{
@@ -144,20 +122,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
 
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
@@ -165,14 +129,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -219,16 +175,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		node->initialized = true;
 
 		/* Get the first block. if none, end of scan */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy))
 			return ExecClearTuple(slot);
 
 		if (lossy)
 			node->lossy_pages++;
 		else
 			node->exact_pages++;
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	for (;;)
@@ -237,37 +190,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We prefetch before fetching the current pages. We expect that a
-			 * future streaming read API will do this, so do it this way now
-			 * for consistency. Also, this should happen only when we have
-			 * determined there is still something to do on the current page,
-			 * else we may uselessly prefetch the same page we are just about
-			 * to request for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -288,17 +210,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			return slot;
 		}
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy))
 			break;
 
 		if (lossy)
 			node->lossy_pages++;
 		else
 			node->exact_pages++;
-
-		BitmapAdjustPrefetchIterator(node, node->blockno);
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -322,215 +240,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult tbmpre;
-			tbm_iterate(prefetch_iterator, &tbmpre);
-
-			if (!BlockNumberIsValid(tbmpre.blockno) || tbmpre.blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
-		}
-		return;
-	}
-
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			TBMIterateResult tbmpre;
-
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -576,22 +285,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -630,16 +329,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -672,19 +365,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->worker_snapshot = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -724,13 +411,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -814,14 +494,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -853,11 +529,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3dfb19ec7d5..1cad9c04f01 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2adead958cb..1a7b9db8b40 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -792,23 +792,11 @@ typedef struct TableAmRoutine
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+	bool		(*scan_bitmap_next_block) (TableScanDesc scan, bool *recheck,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1984,8 +1972,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+table_scan_bitmap_next_block(TableScanDesc scan, bool *recheck, bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1995,8 +1982,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, lossy);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a59df51dd69..d41a3e134d8 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1682,11 +1682,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  *		phs_snapshot_data		snapshot data shared to workers
@@ -1695,10 +1692,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 	char		phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
@@ -1709,16 +1703,10 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		worker_snapshot	   snapshot for parallel worker
  *		recheck			   do current page's tuples need recheck
@@ -1729,20 +1717,13 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	Size		pscan_len;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	Snapshot	worker_snapshot;
 	bool		recheck;
-	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.37.2

#10Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#9)
3 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

I haven't looked at the code very closely yet, but I decided to do some
basic benchmarks to see if/how this refactoring affects behavior.

Attached is a simple .sh script that

1) creates a table with one of a couple basic data distributions
(uniform, linear, ...), with an index on top

2) runs a simple query with a where condition matching a known fraction
of the table (0 - 100%), and measures duration

3) the query is forced to use bitmapscan by disabling other options

4) there's a couple parameters the script varies (work_mem, parallel
workers, ...), the script drops caches etc.

5) I only have results for table with 1M rows, which is ~320MB, so not
huge. I'm running this for larger data set, but that will take time.

I did this on my two "usual" machines - i5 and xeon. Both have flash
storage, although i5 is SATA and xeon has NVMe. I won't share the raw
results, because the CSV is like 5MB - ping me off-list if you need the
file, ofc.

Attached is PDF summarizing the results as a pivot table, with results
for "master" and "patched" builds. The interesting bit is the last
column, which shows whether the patch makes it faster (green) or slower
(red).

The results seem pretty mixed, on both machines. If you focus on the
uncached results (pages 4 and 8-9), there's both runs that are much
faster (by a factor of 2-5x) and slower (similar factor).

Of course, these results are with forced bitmap scans, so the question
is if those regressions even matter - maybe we'd use a different scan
type, making these changes less severe. So I logged "optimal plan" for
each run, tracking the scan type the optimizer would really pick without
all the enable_* GUCs. And the -optimal.pdf shows only results for the
runs where the optimal plan uses the bitmap scan. And yes, while the
impact of the changes (in either direction) is reduced, it's still very
much there.

What's a bit surprising to me is that these regressions affect runs with
effective_io_concurrency=0 in particular, which traditionally meant to
not do any prefetching / async stuff. I've perceived the patch mostly as
refactoring, so have not really expected such massive impact on these cases.

So I wonder if the refactoring means that we're actually doing some sort
amount of prefetching even with e_i_c=0. I'm not sure that'd be great, I
assume people have valid reasons to disable prefetching ...

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

bitmapscan-results.pdfapplication/pdf; name=bitmapscan-results.pdfDownload
%PDF-1.4
% ����
3
0
obj
<<
/Type
/Catalog
/Names
<<
>>
/PageLabels
<<
/Nums
[
0
<<
/S
/D
/St
1
>>
]
>>
/Outlines
2
0
R
/Pages
1
0
R
>>
endobj
4
0
obj
<<
/Creator
(��Google Sheets)
/Title
(��bitmapscan streaming read API)
>>
endobj
5
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
6
0
R
/Resources
7
0
R
/Annots
9
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
6
0
obj
<<
/Filter
/FlateDecode
/Length
8
0
R
>>
stream
x������rF /�"���&��)�a��3��jD+J,KG�aKO1��r`#@�������WS�s��I8��o�X_���VOu�����>����?L���������}�~-��������5�!,���)����w�����������boE�o�ax�����q�����0t���5"��������R�������a
����wy��?�?��/�����*�{�>�B���AD����E<��e9��$���x]fU�m$���$�����M_������l���[IHt%Q+���<�
Mp����p������!�#a+���<��M0,�XI��v�n�������ys��&8Gh��$\i;i7�e��H�����9�mc�+4�@������2du$l`E{�����/8�]�XY��v�n+�c�7�����9�mc{h��$\n;k7�e��H�����9�mc�h��c�[��y��2du$l`E{�����	.#4��i�k�4@�����H�����9�mc\�yZ��9S�n�pjaE{�����/8��D
d�J�W�����$l`M{�����	��H-���*k7�e��H�����9�mc���Z8��U�n�pGjaE{�����	.�H-���*k7�e��H�����9�mc\��Z���U�n�pGjaE{�����/p��p��+�U�E]6��=o�c��8R�=���Mc�:6��=o�c��gp��=���Mc��H-�h����66����y���v�X����ys������#5��+m��W�/uI�����9�mc��Z���U�n�pGjaE{�����	p�{~����2du$l`E{�����	��H-{~����2���ZX��7��ml�����_e���Y	X��7��ml:[�������G������Gj`M{�����t.���n���v�X9GjaE{�����	N�H-��*k7�e��H�����9�mc\��Z8��U�n�pGjaE{�����	��H-\��*k7�e��#���=o�c��\zp��p��+����WE]6��=o�c��Gp��{~����2��ZX��7��ml�8R�=���Mc�:6��=o�c��p�N{~����2\��ZX��7��ml�+8R�=���Mc�:6��=o�c����Gj W���_���Azp�����ylK_o��Z���U�n+p��ZX��7��ml�38R��_e���Y	X��7��ml�����_e���#8R+���<��}��Gj W����_ (����5�ys��&8�#�������4��������9�mc�H-��*k7�e��ZX��7��ml�38R��_e���Y	X��7��ml�����_e���#8R+���<�����xR�Y�������|�f}�-qM?��������U7��s�Ba-xX�W(�U���n�_X7x�������s��Y7�B�z8�&���j��=�+���Y%�[\��V=�V^l�����
�j������B�z8�N����n0��z���\��$y�k����j�c�^X���d���<���
h��i5�	��6x�s�Ba[-x���W(�U����[m�������Y%�[\��V=�V^l�����
�j������B�z8������,_���`/Vt����-�Q@�N�	���7����La[-xD_��
h��i5������q�w3�m�������
�����pD_�����f
�j����-�P@�N�;���|�}7�����-�Q@�N�	��7����La[-x@_���e������@^��-*�5�G���W(�U�m�����Pq�y��V3���np�Z����q���������m5cV��W(�U�m�	�n�V[���^0�m5aQ����(�U�m�{aqWq�y��V3��np�Z����qX�������m5���v�+�������[mq�8��U�m�/�h7�B�zl[�x���/�����m5cV��W(�U�m�	O�����k�`
�j����-�Q@��V3G���}�Gq������G����
h�c�j���
w}�P�V3��Wop�Z�������z��]�-�����\��V=��f�����e�w�m5cV��W(�U�m�	�=�j�Y�����&,*I�����m5�}����[(l����7�B�zl[�xB_�����
�j���
�P@��V3���7x���Ba[��U���
h�c�j�K���b����)l�	�J���F�zl[�x@_�����
�j���
�P@��V3��7x���Ba[�8����
���m5�}��]�-���g��\��V=��f�Wo��������qD_��
h�c�j��C_m1��z�waQI��(�U�m���7����Ba[�x@_��
h�c�j�}���[(l���\��V=��f<��������������z�+������W��<��n���f�*Y��
���m5��G_m1��z����E%�[\��V=��f<����~�w�m5�}�W(�U�m�O��7x���Ba[�xB_��
h�c�j���
�v}�P�V3^�Wop�Z�������z��]�-���W��\��V=��Nx�z���|�+�n�HXU&y���������{aq���������`/,�P@��V3�"���q�w+�m5�)b�-�P@��V3^Vl�����V
�j������B�zl[M���Wo0��z����|��$y�k���������[���n���f�*Y��
���m5�0`�-���[����q��W(�U�m��#����������1����
���m5����Jg��zl[��imq�Z�����������VJ+o�c�j��������0uk|��5��NM�\�)�����*T�Z����hC��������Y�`����RI�h�_R�?gu�_S��s��1-sX������'�����m�����$x�i����z��3�o���uF�BE��C����@�r��!o<�1���&j1�L����������s��0��������
������/�$���:�q1�1�D\��q���=���h_�
2\I�������T.!�CN��$ID�����r�����ay��`��D�K��J���5��6fLi��*�[�$���&C�,��
�|��aB���u��L��������7��!��~��I��l��.x��AK�kI���,L�f�0�����s�AZ�@]�LFk|�W�j_�-4do;k��2-df�C��/I�@d����1_����*�hz&�B;����za{yPaK�"���D
D�1uC�c�^	VR���W�\�`�iO���0���YBZB3�[h�^��mx�����c>i	�����k_W�:�sFVl.6���q�B$����XCn�}'.�>�e���R��u�W`{
�mA� J�"�LX�m�����d6����� �m�M\	
C6�����2�5��1	x�����������#	X����L!���2�B6�l������HP8���gz���g�XOJ�����Q�8s��	��k8�R�$l`Ve��
Y�x�!' a
_�lV�� �-A6��B>�+&$��cgf aO
(� c�0%H��� ��0��xrXh��:�_�0�E��;��v�m
���(���G"�r���@43A.E�6�� Pf���Y������(�����N\�v6w�x���0��	@��
D��9d�b>2:�h�$l���3z�+��c�;eH��� ���0��xXxr��e������P���C*���p�9��20<+%�8|�1��c�������@S��r@D&�����dPy60��y%��I!5Y(+X����?�~=�*c�zIPj�'a������b5�0���D���7ZVM���>�����>+/x`_��@���0Aex	h	��
m������$l��;p"t������~
�R��^I��0Rv~�e�$l����.�.;X0�=���-4t�h���e�b�&0A}� �[xn��U���f0A%X�-<i���(�?��BCx�Xd���d��l�/��'���Y]���������
A6����`��%6��3S��3%A�H��N�4�[7��R�f=0	hw|Y���`��$l�9B�f!\a	�#au��Y�8`�$s���#�"	h(w}>��P.0��)�qt`�J.�/�$������	���=b{l�X;3�$l 2��[0S�(#���
4��Y�l��(n5C6�l����������
4��+�m�}���r$ak5�L��x6C6�l��z0�KN��=��@���o$�%N� K����R	X)��v��������$l`�����2�a�3%A� a
���e�������9	x����e���������
4�Vq6���k�I$(�)%aku�W�/^��9<6��i�B����>����	���>�yC��P�$l�)
nh7�"����6���s����t�I�@3�Gwv�����d6)ws����e\a@I�����5
$�W��w R�"��<����]I��!+�~�,E� �D^�Z���X^��L�|z��
4|��*y�CN�P&�/a�],fR	$z��$l�):^����t+h6����:�|�LP9�~
���<
����r>���q�B��o�lZ��1��	^���#a���o�d}(A6������iA��F�	X$,���eA��0�$l�a��l\����	2	Xd��n!�:�}(C6�:�B6=H��g��@$�n�� c�'H�%�qt��A�5����8���I���i�C��d`��!��"	h���� �C	#���
<�E60�F�B��
��w����=AVG�b���B�����
<9�lO����+L	x���L��
�>�c�hfm��C��C����8:�W�c�pg��I|��K�$l`���	+gF6k�0Q�$l 28�'�����+6�d'�t!�D	
E6��6�.����Y	h�����SJ�����
�=v`�x�C~��wVb�v2�y!C����/y�A/
[8f�u//r���7qI�@�^9����I����0�d
6��p'���+~��!	���+��l�����=��6����i�3��:X3�!	h�z3�x�C���0�$l����bBrk�b�3H��\����q�9$(OM��������	,#?K����K��1{8����
���)�� �E)#�,I�@��oaf'z!SL�X�1A�x	h:y����X� 	h�v��-�X�/A%x	h�7�y��t��Gf����&����u��(���_�J��[x��lZ�����a6���G�7������^��*'a�W���Vd��H����"	���2�#t��
D�Ci��G����@��
<�C2faL�.�	2	hz�s!��Y�f�`��$l�9B2f!\a	2	��{�W�C2uy�r�9$a�s���d����d6���^/ c�������^���!Y�|y![:��(C6	w�H��!�E�"t��
D��eS�|a$�7�{"��Fu��C.��%�w�G"]���|{W���!�E	���GTw56c&\a	����:p<�6�|l��K�k�@��cQ�2.0����8:�y{~����i���O�fo���h�s~
�8���D��@��
���!�G#���
D��5�f�<BHPK�D�C6/td����Z���}����S�,�Z/`r ���]�C6��0�$l��	�vm6d��a	j����gf���>��t��@3�;��1��(��
Nr��%l ���+|l��`�/a
�N��VIF��CI�@��-�M������c
@�6�����Cb�������-4|�N��������%l�%t��h�7�o�	LP����/�Q���0�l��Va������'1dP)���
D�����T�H��0dPM������$l`��ww�(O���!J�'a�n?�&#�*e��#6�0f��:���^��!�J)��������3�8�9' a�|��c��F�Z�`r`yL�7�4��A�p���H�ol#�Q)��J���F6.��������2	�=[_�D��(|l	���I�@�w�����@>���z"���rZ�����	j���H�3�2B��	M���
D��d^����$�+�I��"c!�c�yd��*�X{�y<x�D)�G�ZE`t R�n�l^�C����\�O�H������ �J	je���H�{�N�M���D�"�!�g:�wH�R�I�@���hC�)U�� ����w�����CB�2$a
�A��f���N����lol��N%��XC��sc��9UJ��$���H���-��T��J
I���Y~�F6tH�R�$l 2�U�"C��*���%6�H��-!dC��*eH�"���-C��&��!F�=R:K���!�J	�����`��W�/�R�!�<7|l���5�|�R�
�N8�-��)��E�"���)B
Y�b��fH������L�
d�?UXFh�v���h!�L	#t��,#4�;��l��?&|T�Y�@�[h�vO��f!�L	_p�"��,d��2a���Zb�B�x���P�0�TZ�2�uO�*�2$�	a����[hw\-[2��)����
�c�wh��s�OP
_�4$a;H���:��ikBHP�B,D�����r��/B�H�@��="as��5a$�5!z"���e$k���Y�B�4�;�)�3��	!A-	19�d��!mMW�F6���ac��5�#(k��#C�9YS�&��V�hzXwQ�H��%��/e"������5a�7 mM)����x� ����"t��
D�#?���Z��5���
D��w�1�0&��1F���$�x���x��5�H��C��p�9$(�*�����VB}!$KgB�Z�w����
��HP�e���*���d���������H�N�B�Sm�
r������Xh�P�8_���������%C�����
_����
r�������|M�	� �KH�@C����*��.e\`HI�@d��|��r�T���I���?�C��!�l���I�@d�g��2��.���#6��ViJr�x�I�@�<������AV���:F"�1+d>6;��R�$l����2lW���|+� 	xr��3cF�sH�R��w�a<��p�)$�BF��	�cH�JP�~�b/aY���W6d�����%l��<XT��z��
4���!���A����
4|G���Y-Z�c��StlW�f�t+�f6���=��p��A��2�����Y)����
���H����4���FG6��d��?A��M2��"	��;�L�IA���E�	h���Y#��4+!$�5Az"���J�#�4�E+��4|G����M��� 	h�P6��0��^GXxj@��!�K�j}���'m�
R��q�)$a��`1�e������jG6p<�d�v�9]d��v�"!���������"���
4��yZ����������|'#K��.�$�BF��U��9]�������g;��VBIP8���Hy�d�2A�U�j|���
�0��H����-@����D�3g3J�KP�z$a���e����UJ��
4�;�D�&�'�	j���e�J��0��A��R$a�u�m��p�9$a
���w���$����
,�y�����o�$�eDF�%ZwlT�{�����x6p�L���X^��{$���G�����Ce$+��#� a���7�������!	h���|+�!A)���
<�A^���$���G�@$<T<U��A�Z�ct`���=��$\!)Aq�Qjk�G��p�T��-\lk������s�#�/��	#=T�U5�-4�GK�+%Y$E-�1n��<����D;=O�E4�-<>]l8���\+L=@������@>�P���ZA�������!!'A5)1��
�!
���>z��jI����w0�^���D�"����B�F�8�?	h���JH&�8�@��Q6,H�F�Z�br��e��\�[aI����Vr��������������^y��������{?�tG��IP�^�L$a�3�1d��Gv�|����@�;V�X	��zD��� �.������$a�u�LW��a�Z�bt�!���C���d��HP[LD��O�*�
�HPJM����F���	��������x��d�B��D���
�Q�?CRN�b��\?	��G��hH�B�Z�bq ���m�r�2A�9��
<�G6j�%%���E�@C���UC*�2&�e.F�U6k�J�Z�br��<��
IPjO�����E�6�?���V��x�C��!'A15����,�u��2�������
���;��(���!�F9^��@Cyt�#-uH�Y�������GW>S�R��x	x��3��e����
���E�D��W��0n�q.�(�%��.Q��<��L��U��"�&e39	h(��%�H6�,%�HQ�F��
<;�iJ^��2�k������i#J���B������!q$A���0A6p�O�G> y�#�u"�������6���o&�l��7�I�@3��5�.9�KP� �<�CrL���#���
4�;����!sD	W�E6�l��!yD(	j-����*3��(��H�"����5@�H�j�R� 	����_JB������
D�C����-�9���
<�A�.&$��,�9g a
��sad����H��cEA�q�I$(�����x�3%�$�(��;�,%/wHIPmC��'ag�D�wQ��;��#A�"�8�P�8_�.����������H�!	h���RF�?� Y��������^'��� [D�%a�?G��r�9#(w����J��r =D��
�M����B�����R���`�Q���;���������=�d[fO���K�bCy���1��SI�b�x�T�lrS�4���%mqNZ����)���jO��.���MAv���8�I���]d��aK0���>=�le�����b������@#�L��Q��z�������2=lf���f�.����_\��{UP�� Q&c��5��YwJ���A���2������u5y���7��Q��Y�+���C"��2�������Vl��[Fc�r�>�.6{����v�Af���G�d1A��!���\�'y����_b��Rl�����_\���eh�
!�&���;�����oR�B���2������I�R6RH�Q��Iw��� ��(-c-0����<�pV�}������T�Hy]�SWV� 'cY{��z���.8�����bd��WAV �p�KHy��8@��V�F���)0+c-J��Y�����i#v��-.�������7� N4 	�[|��l�BK���������}E%�M�Ik����Hz��b����2��au�����3)o
L�X��.>�U6ra]pVk�����\�y*����G�r�9�[������C���2�*����h�/�q@V�RV��-F����l��������A�bd�y�FlRx2R�R���-6]=�3�l������������C&OF��������y!��Uv�'�����O�T���2����-F�Cw+�J ����n
I�b�?���m��2��;�[lH��*��mB�Q���-6��?q�� �(�M�����
���[�UlR�2�$o��!�c�'��������P1%�����d�=|��b}����.8�$o�e=���S
�������) y�{�e�I�b���+�������3���n�6H�_,o1����e���/6Mq`3����Hz�7���mB������H{�5��t�f,���bCz�V���mB�W���.>9�b|����.8�,o��oa}*�0���J���x������)+c-���Y>����i#v��-F�������Gq�IH�b���������7�S������/t!�-2�2��I�se]qRK]��������_q^eW���g�]|�������3�X�:�.>�]1|�#�m|���-��d8���J+;{3�BC�#���;�=��e����#���CJ*�$�e$$o�!=VR"��������-6�������kJ�Xk[L.6��
�*�$�)�[lV���cS�t2�j:�\MO���A���eJ�XB,.6����5�JXJC�����w�XLR������]��{��eIB
��2�
��
��%���d!kJYX�bdu�/j�,�a"��IWl����O~SQZ^=��$4$o��=t�YIy�]e�H��-6�G��3N^��=5h�����:*�r�����$y�mG<�8W�Q��A���������V�����I�HK8�T��_=l�f/@���T	g�F*"���=�������`6�r�����}a�~n��c2��F��[\$u����c6��2�z����X^���~��TB��#���)�+[&S)�[��������8���VBX]lH���X'�R)�����c�#fR%�Y�T0 y��)M��PX�>1�JYH�bd�9���4*%��5��H�.\�E�;�Wf��<*e!y��]����a���
������F������VQ�\���SZ1�-��i�q����-z�D��	s�����O��p��1'[	s2��9w�~^�B$��1���t��/*ae+���d!y��u�%Z�L��Ik����Hz�ny���3��au1�|�^i9eZ�B��.>5�d
)Y���R�������s�^#���|���-fy�����aU��-�)����7���Y#v��-6������0�Gh	+M����4P!%7&�	�Z|b��!�zXy HYe��eI��Y���X1GL�������az��.8�$o��5������:��S�B������1@��V�Z�bq1�;fR1L����t�~~&���5JJX�D�.F����l�^#���X��b�z�p�VS]���->Dk��hc�Z�at1��q(~���f�D��3���
$o���.&�%�fbg�L��~�����+������]	o�7b�X�b���L�:Nra�O���-6�u+�;_���
�kF�"1��tw7�pv����X+;,..����e�i�K��`��0��Y��=U,H1wH1C�D��s:v,���`�
�iu��e+[�Sm��! m�e+�#m�W�S���qF�8#G]l8kG�O��p�c�����s/�}��b\L����-F��g�q�q)�=.%�B2�.>3�c��h����c,o�1L��-������p���
�[��c���,0�e�uWg��9��s��/%��/���y�4�����0�!y�
�vR-g{KKY�wa���������F��*����	'��->�*�)����'��"��
k�H�U����7sXM"o1r�����`��4�Ry�
i��EuLg$�3����HZ��T�A���)c!���O
�l�D*���+�)�[��;��t�f�iA�	W�[����g#��E�mS���}��C���
�^F��T�W>��1�O������n�.��|J�[,oq�VV/����|��X���.F�lK��D��Ahy��t>�ay�������cs�����X��,.�P���(�W�����,o1^��Mb~&��[�sX'"o1��\��
�YC@��D�-6���=��g��3r������3%�����a��!G�\����?�C�[��1����f)��	�;%f|&�;k�GI�b�w>���������9�J��-����#�j�A�d��9�������n����J��#�[|���Yb���&���������E�NN1�pB	-n�x�8�l��/������pI�b���i$A����C���L����n��*[�D��L��-���!�
i�Z������_����qF�8#I=lH�m����A�IX9��a�Y��#�;B��R",$$o�R��x����IX9������}�����_$oq���o�m���Q6��0	��`$oq�)�������z����%�h�*����-FVUM������)k�5b�X��kv2F��2�&���0�\YH�bd=��C��^���V]��V�|�R�>��2��_��
���)�oq���jey��>��S����'����d�~LX�o���Y������S��6�Jy��v��O��Y��,at�a�;�LD*N�,8�,o���}rR�"D��IX��s�+~�Y�Y'\�,o��f�TqxO!���H�8��x��k����<X�TV�Z�nq1�����q@��}cy�3����g�;
B�Xk��.6��"9/v��(-;�� 4,oqqlw�	����_A�)�[��R�d��P7w�y0#!�[l���+F"f�`L*E���c)A��.�5�����N���lany��Xx���g�+��N�N�?����B�A�F��e4=l~�}$�m~R��-�0��"����}(
�[��{yh����e��9��8c����`x�C(k�����7X��KF�;���,o1��Nn�l[|�c��c����"��+��@:H����-6+f/��pXh�ig���[��;����D��3�2�iu������G��4��y����PHY���qF�0�����C!��Q��#N.>5����t����IX�bCZ=��D���$P�u�������N�N�3���d������=���Bq�0�E��3O�%�X��y-�2���W�	��i�s1-c�!y��6q5y}{Ki���{��g��P��#cB�Z��w����������r����l��*��l�+cZ�Zrq��ae�D���f�{\�,o�Y>��&�%��;����"o����ObB�aL�X���E;)��[��7��y��f�#�1	o��7��Fp�6�zb_����&N.6�;����u����YX������y��1/c��W��-;(a�d��w,oq�f��qXxs1aup�7M�����J/X��U���U�^fT�$o�eu>A��l��	k�5b�H�����m�Y�%F�#�����������k�=F�MXxH�b��;��	���O�	g��-�������O�	I�bK��P1�x�ak��->�'uLX-,o�]-�>[\��y��<a�pm,��l���`�Pe�<|�k�1�l���`�u����#� �_���p��J	Z�����m��*(�������k!�7Hf��F��[\d-���FI���J����-F���E�'���Q�%��oGg���$�����`�Iey��j~�>�����,o�!t�U��}T"cX2"oq}�����0$�XD��J�dKd�8#E�Qe]|t�t�$B���������>Q��.����->��u�%B��������+}�Y)�)&��[l��c�|�1�vS �l�Rj��-����B�xg':��9�$���W������3_�/bwX�����S�Nhe�� 6 
�[lh��)/o��KX��.F�c�F�T6~�'�S����if����L:"��"Xk	O.�.��Y����'����'�D!�EB�UN��
?xW��)�jy�+���qF�8��0��>A��aBq*	���J��i0��k�1�dy�O������x�����g������E��3O ��I���tQ�PA�x��,���b���"�{AW6z����{��#��a�l�xYhk�������9���d����JKX�v���H{�/0����,$,o�!�����/#��Z�{r1��}����Y�Yg���[lX}2RqxZI�����~����3��a!�����W6o��<��2�8�����v�w��t�9ey����4��~-����Y�������O!�$��k,oqqW*�o���p�n�b7�[�n�'Q�T��������-F���qxZi#���-6��;�
�U���V����Y?��������V�]\��Wr^q0x9z�"�����������{X�����������D��C�z+���Wm�7�W��gZ]|rv���em�
��E�b�=����qF�8#K]\��v~�0�x8�m�&N.>�����=qe]pI�����������x�+�������uV�^NW�	;��q@��vct�X����y�Y^�H���������8�9�]���$y�
m�Y-BL��r�'�q@���#y�s��7	q`|I����	H��-����0���PV�o���������)�����/�	g��-���^V�)���e,$o�%�����;^[f�,o�������]:�]`,Y�����9�a^���������O�W�1�������-�;�&�����Z���s���'/o�����z[�+�����7�U=�[�������%�^]V���by����I�axuYX�S��OvV61�����������T�0��,t����������������Y��\���I��
o-+�=y��=�P[((4
��rZ]l��~�N�#o��7��y��#Y"�8u�,$0�H'W�R�}���N�[|�O����`!d,��b������q�[�(�`����[L��5;��=�xe�����>2�����~��-�Y���{��g��Hj�u)|�9K(P?�[\�e���������������w7�S�a��m�#�	g��-F�c��T7n	q	���HZf@�g&�;$���"o1�����
�HeC_x#�dZ]���u����]3k�`�����������/8�,o1����=�H9(gR�L����qr�� ��K��-.o����y�K�	g���D�O�K������uh!d��-.��������/�q@���by��V,&�s����
i!e���.�n�"�����7�g}�ht1���C
B+{;��������E���������g}�gr1��n��
��/I+��y��u4���g|������2�iu1������7��V��W�-6&sl��8#i��$�.���u�>�e���`Z������&N.������B��Zb�$,o��W���������
���������N�7���lz��;qtr��%]_o����^���$o1�����wbB�fLHX	���9��_3�d��-����f5�I��1!a%H��n�D�����7a�!y�
���H����=������<����H��-���.�[lH����C�z����4vOL���I	+��z�����&�9�`���8�~���IX���qF�0z���=5(��i��1-a����
���OTvN���J",$o����.f����U����������S�T��4�"?Y��H��oz����R�*��<�w�Y���M����Y#���-.�z�p��������-�X��y�������x���{�D�0�U
�D�p.Y�b���j����*.E~���ey��v��L� ��!�}y��t��M�l���o�I���Hz(gV9C@��V�-6�y�(�Hg$�3������T���?�*I��bC�������0�����-F�����c+�\V��2�.>��yp�������v��-.m�BS����6������:�����?g�H���#���������`�)���F��[\�k�I
�?&�Wr���g����+&dw�����������G�B+�� M8�,o1���u-�*��;�+�zY�b�z�������U���TW�_��3��2 ���Y����G�8#i��$�#i�?Yy�NH������$qr�>i��8��[�t�Iey���=�����w����7u�T���tUS6w���N�N�;�������.@�w�_,	�[y$oq(]��/��� Z�/����>���8��~��
���`�8 ]�^���[��a��S��,	H�����^�SZv-LKX�]l�����
S���E��[\�Y����#��(�PY�b����=F<�����[��{���@��#�)�L���t���8
&
I�X��I�B{��#�qF�8#K]�������'"�%�R"�����t'�@��.���C����S�*��H�}�o\J,o����sb�iA�	���#�n�+�	o�'��2y���-��je���O���B�XC\\��~��=CvMx�^Y#v��-F��2R��W����>��������N������[������x4�K/$,o�)RqWx���f��I���aV�,x��YD�bd��0-��iC@��I�-6��S:��S�4�Hg$	�����l��;�f��2�W
'#���	������2�G���E���S�G�h����Q�K����[���=sa%�,I�����}�z���x�\�"v��-6���\![*�/V����-�m������������-.���^1�l�x�\xH�b;��/�B�29�����-��e��@���J��B;wH;C�X�b3�����l�x�\I�������J�X�,o�!�
[vn�G��qF�0z�dg#�&�����$N>�+��a]p1����yn/�/��`^��3�>�[�] �������-�����m����=��3�&/����]�g!���^#V�����bd��Wg���Y�5re��7���������*���+�[l��W:R�^&WZ��������~,(^
/�!cy��[\l��
qVx����`�����=.S��C��'��������V���^�fZ]��{�H]��! i�5+�#i^�K������gd�3����%��7^qVX0@XK�\lX��[����&��V�����I|��Z�B3�..uV�D='3����3'#/'�����+��5����2��c�o(k�5b�X��"���.^o�+c}��wqi��4:�xw_I	����3��'�/���E%�[l(�nL���g����-��������;�J:C/E������ qx�_X���Y��2�+�����V��[|`�����5��gd	����`�Ia�]/�+K�\l�z��q!�=/�	�[l�����[���� {��� �[L�G��x�&V��9v&�...���C����q@���cy����K��i�l���!y���NJ�����{:s��G���d�+=�\�pjY����pH���K��k��-��>$S��C�z&���+��{����H3�.��<��]IC@�+V�-6�{&���qF�8#K]�����#.'����������U3�
�.'�)L��rby�����O!�31&e,$��bCz����N�N�7���l
�J���8),f�p���A��x.����^qcX�@yH�b���J+>
+(i�����HZ�5�
'c}��wq�Y��%�	(a}�pt��q�������#�-.F��Oj����k�,,o1���g���w��������F��W������L�����k��4��y��t���x*,g��qF�0��\O#�%qdX�@I��b$��3�J������->���a`Y%����-.kV�r{�3�t�T�J��)/����I�b�?������[aZ�J��-�i����-���E��[l�y0�@X��0+aeI����-D��Bx��o��C�;�[��&��X�������UT�^f^q-Q~���%y����~���;����,o��=VZ@H��0)a%�V���B�X�,o�%�;�
#��Y��,a�����"��,����V�8y�l����.'��$�.'�����$������V�y��1��VoV�iA�	{G�[��H8./����U��~n���S�k��%ay4��-�;����*n�D��*#�n�v^�d��7������)�����K@��8���<��t������V9�xKW�pB(�*M8�,o�CX�������
.X��'�~�_�s�r��I��9fK�82��2 ���Y�~�t=�������[l��K3p�)m��6�HF#��:!?&?W"����f��}e��$n�i\M,o����p�~�h����������K;���]�E���(?X��(I�b��d78O�	���AX�\\��{���_0k�5b�X�������}��/��+����[���+��	��0!a}�rt�CX�.L(��M8�,o�3���_������\�,o1.
�^2�B����xf�;d���"oq����0�ZUg"?P$�V#��jJ�X�"o1�����qF�8#K]����U���8��'����&�]p51�6�
���&a�I��XX���f
z�RI�I'��[\�j��%��mJ�M���O����K��x*\6U�����"Vq`�3��>���Y�}~R�8 i�����H�[U@�����(iH�����[BvcLHX��]�����E�&�[l�?�+#
u]���)�[|t�+1��!�}y�KvQ��`�����#�L��
�^�r�#k�`������Sk.��g��3r���f8��I�{���g��-6�����U��2��+���g�W�sNrN�^Y�b�����%��$��yD��-^�g�k7�����2��+#���-�����F��[��;Y������2��+{��z��#������+G�a�XJ@H�c���b$������J=,`����������d�;d���"o��i�p����E~��1�..rz����`��4��y��t�wZ�4�Hg$	���t����"�HL�XH��bC�s��?w�u���X�*]\lXw��a�84�e�K��->�WqY�:-�:a�X���\}y]�\B��k�N}�[,�g��7��'�[���^<�.��3������j��.���7a�I�[�����V7z�g�4I�����[94P��K������X]@h�h����vo���o�i�J��-��;G����%%]p��������������e^lY��p!9R�8����v.�[�Y��y^�������g��4'�[��n�W�PV�z9�%��..6��J�e�q@��}cy����c$�M���2��@{g�G��2B�����>:��0�l�D(=��N'�[l��HB������NY�b�O~���L8wH8C�D���b)y�	)���Xx�����w�<E�k�`������w�F$�3��I��b$�9����������#N.6�qd3����gqNY�b����+��:-�:��ey��9�����p'#��'��y���-�~���.�.�++c}htqq�5;���uvp�?c��7�����ylqp�_i�k�����-D��%�B�KX]��Vw`�p�_	�����b����%����M{%`y��=t�z&��.���[�Sy��A��X@"o1��l��w���4�HF#��o���?S�����9����S��g��.���{����������R��.%���<�^UqPN c��k,o���������$���7I�b��]��R]�3�T|
G�������Hz��k�5b�X��#��IY�����,$oq�Z�W�|�J���>�9������9�8�	2������.�8"�(��>�E��;�����p��p�����AT�C���W��*���f5��H��! o��(�W�&��(d��|��cy��vM�a��}Z�pR���h���";1�N�N�:X�b��9[��.������,���,����V
W�3�$o�e���&�1���x#���-6���4*�l�po>cI�[��GdO���m�BC���w�e����JJXHH�bCz�d���N�����-6�;�!d�����=ey����MZ�����3�i���#�3��4�fy��Z:t�1c�3��Y���#+xs�����9	+G�<l9�G`��B8\J����->e�������V�y���u$Nn�g����-.�7fg'�����nV���������f��g�����y#���18�����`B�4L��F_��=\��_��=����Z�4����a�O��S�_a
�+��$��k��B6��c�)��l�������3/o�����z��5�~�"��.d�6�X�6�g�qF�8#O=lxw��"N$o���[��T9y��D�6,�. ����������M�)x�f
��E��z��N()���N�N���
v62��A6�t!Q~��',oC���C�Bb�<IH�+pNX�\\��r'�e��3]�.b�X�b���W���W|���yH�b���	�
s�%��y-���=��W)G[���N����p*Y�����U�V��1H�����-�v�~���s��3tS�-6���P�3��~@�����}���! a��)���:u<�gd�3������d�%#�I"��<qrqe��0������9�����TfQ^��O�g^]l&2{��k��c���/��Cy��#�[L��D���r�_��5a}rqqF[5�L$��/����{��}����@> �[\f�<&����`Z�������V�f�P����p:Y�b��|�\��Qp����ey��t�WF7wH7C�D���,�?�����1 �������o`�8#a�u#�������+���y��b�QoW������8,.>�5����p0/c��W�C�)!����v��-6���q8r���������X?ayN��-�KW�*�G*�x
�	�#���3��>'^�	������;��OvD'�B����I�b��\@8�c7�t��������S�������[|p8�
$:u��"ey��t�\%�;$��"oq���L��?2�iu�1��
<���
[bbY���t����b��d��6..>�5���W6����y���������v��-.vM?�eS����4a��y*1�[��'wlf�nKg,I�b�z�[����;����fd�g��U�k�0��$y�-���J��6\�V�����0���w��i%!y����
7�E	c!!y�-����2��C�z���C�+)��LJXI�����W�y!
I�_���HO�=��3��g���-��+�)�
�Kgq�����3���[|�������rV�y���U$�
�Jg�v��-�I���������������2������O�����������V�?f�'u?�6���7����C�?�������	�����g	dv6��% �Q�,����g	������?K@���kC����9x��W?i�_����3?����b��5Z���0�?%��+�?��_�����������������~���������~�5���<?�����?�������~��qzS������������������������>����}���|��?��O�����������y����?�������/>�o�������W����o����������vG_k�8�8�����>�C�s�C����n�e}�
���g�C}eu=}at�4��������BQ�_d�����dN��x����������U������o+���������������^�����Z������2/�b���������������Z���O����*������e)�|iP����k���/**������n
]
�?��A���dj�k���.5����?��gLP��{�t��:�uok����������a��<C��j����_c_���i��C���<�K�Z��QsY��������<6��=hZ���yU�<���X���v���S|����~��~�3����|m��9���<`�<9����u~�����w�6����/�n���Wv�F��Vg�����u�v�y�g�^�6�7t��si����
�����s���
�Xq���o����ws}���e���o_�����^n�����J��]�0=7�X�+���_�E���6�\�9���;�s���s:���������ri'����3;�5�w��������o���}e�~^��t���I�ke�wuJ���� 8��z����:���+��qN'5O���I�oUq:�s���J`]�I�o����9�c?���y�wK|�@��|�vIa:�vU����o!�����4��Mp.�����_��9.qIwX�NH��,|��<���et�\������~%�����W�C,t���?��7>w����O����
��y}{��0��=U_3����*��\��|�yI�:V[��irqI�1�T�x�����7����������?��z	$����Y�x><�_a�ciR�>��'�sc����(_����vy��K;t�,O�o�f@�]S���:�U�sWQ�t������*��?����~3������k9tc}]?R]^~C��Y���[�0���5����/������������e���B���g���]������e�Ku�.��su|/�]���~��7T���^������������]�+�����u�����j��_������\��m^�;W���}X���H���$�sT����TctW����W�Fw��^m��#F����\U��������0�]��$�+����Fw�q�#�+�����Z���XjXz�'�����E6(������9���]A�o��]A�������zF�]A�����n���������O�����������#o�|�7�w������?�4Z"<_w
�Z�|�)��v��1^i��^>.� ���Ey������~��k�W���%��8�nC�@�������Dz����n	�J��{C��^i�6Dd��F���(�^i�?��_�*.�^y6�_?p�x�l���t	�|�7���_>�����������s�w���>y�s�w�b��J�/������1����Z=��]��5�s�����\�*��_a$�^�B�������k��������kH�F���I�?G����g��������B�n��Z��|��]z�F����`I
�D5�+X��;���%]O�x��qK��V�%K�B������i(X��O�g��;B������
���w�XB��[,����%,(n��{��P����Pp���k�����;BAW�-'����-��
��o:	tu{9�kc���������P��m��
,�3���PC���oMaU�N�������?N�P�0"�]??�P�`Iw|�-Y�-�`��>]�I
X��t��
-�����B��%}�!t��
f��b-�cr(XP|��JB����L����P��K(x��I(x�PL\������i��'\����]���DJ�m�(�+��z�_x�������_����,�t;�������5rux�X�0������y_W������_������V��<��#�A��4�������h^�3
�3�u5�"��}5�������V�����kU���L����)���./K>l^W��g(��Z���MT/������m��t�K�[q�������;�^�m%,uU7�X�����:��HS�8t�S�?�Jo8���~�xB(�����z@�����}1�����p@���h7|�������6���n�k���+r<Y^5
�q(���5P,�Qk�xd��K6���	K�~G�X�/������
I��@q�5�����_M1�x��:�����.K����ttYR|�c3]�_>V���������f�xty�Pp�x{����������9>&oOi�]�w����[�CWs�[����S|���X�;���F����,���Xj|�����/��aq�\�����7�Q���E��}�%�+6u1z���0����v���0��.��U�?W� �����v��l��oG�C��!���9��~�
�=
_/���'��b��V,���c���%#i8/���!����.��;�BW�-Aaa$n94tui	��z�����X���%
]�?.�dA���
?���U�p�V����(
�vt��S��c�r��Aa��Z�.���amjPX���%s����ZYPx����TdAa���]���O�%�-g9,,�~{XXP�\��������-���n�q
;���7j���KNB��[������n�����#4t_?��BCW�M���;��k!V��������^�1
]�?������w:/,���u����f3�B��]
cm^[�(+v�z��fGW��J8X���Y
vt=�!���@?����i8XP����2����ErHXX3�#7�/|�6KPxw�%(�
%(�_������)=U:D���������]~�U7^~��^����fa .�e��_<��q���@Kr~w���6\������7�h���N�_.wj�y`^?�\I��/G�~���iZ��r��u�;�O���U�4����>h<Z�����5�j�i,�����Y<z������d���u�HBSw��9�tU�(r`Zl����t���CB�wP��Mb����'QB���,����)z�wx��Wz�Q�����U����F_�=_�KC}�W��h7�H������l�����;�X����j�!ab��Z������G����0
K6u��������4�-_����
��j�xd^?�q��Q��0�r,�@����_��B��K��W��������/��k.�}�b�r�_q����+V���|������U|Gz�������}����P�q��4�w�7��S`�ZH��}g*VWM����lFY`X���;/G���;/%��|=����bSW�H`X�;���l����������~�.���b�rhXR�T1�����7�7������K<XP���XR�|��v���8��kb�8���.��;�BW�-�����#���}SPX������0������T	�����N���U��z?4(,�Q�ia�����c��kPX���B95�j��6�Aa���'PgA�A��\�P���M]/��G��!j.�SR�\���sHxw��rio��\V��
����o���f��|�Hg���.���j�
]�����o

]�7��������0���'��Shx��MCCG�;���Us�u��u^�M#�a��Z�C�;�C�l�94��T�u�����v�U�-uI�����6�jhX���E�%4,��o�����+���n�&������zhHw_�����j	oW���9��s;Y�7���������������m����U�x��Wz�:�������cM�c�{�d���������������T�D�XW������XG����HG��#L?[5�-������f��f��]������8�`S�������k���qla�P���������1��Z�W�HJ�ZX'�~Yi�Zhx�w����7X8r����_/�;wa��}�M���s��b��}w��;w�a6�=������������A��������/
�����6<B�������sc��J3�p�U�?O�����Der�YZ5-u�4�+���k+����P��<"�1_���h�����[�;*����!��������!N��J6���\�c��:��V�1�
��7�|%��w]J��!�����KI���n8�+)��q�w{�9�������b���wx��W�{��k_�-1���s������[�+�b>W���o�Y�W��7|�.����=��[
g~�V���o�����8�+X}KZc�����Xc��������?�����aL4�+���;cC7���O
kP.;1���VF���si��F�����5������rK���V%�[����K4��__���wy��W����J�@W�_~K#q��E�����S[��NQ`kci���]��;2=������n5
,��/-7�5
t�������[�����%;�|=z�(����koi��X���w��f�zVI���k��|�GQ�#��&�1
,�P��~�-�5
,(n.ys�PHXhqs�����Y�sm��B���[,Q��c�E��������#
t��~��Q��������/-��XowK�}��z>Qf��
��n�,�r�f���K�E��jF�n�H�jn:�{,G���{,%�jX?v�[�6����aaV�G�YDXX���N9"<�h�������0B������z��a���?ZJDXP�w����n���X"���X"��[<=Z�����d���g[|���L|�w�����Geq���sC�,�tui)�=����!�+�3]��7$dq���g��C�3�^�a�}���i)����E3j�3,�Qk��#cG}��M�Qx����������6�qh�Y��O
wABuL�=��55��`E��<5�,n4��eAqs=����O�w���w�XB���n�gRR�|��~��6��S�7��l7�^[���l�w�������
��Ahx<Cc?WuKJ��~��{N3�����U��[�>G�w��=�+���S.��\�w|b.���/���;B��)5��'������X��t�q��0�����c��
�����������%�suo��\���/����NA����C��84Gzw�zw��8����0�f�������y:o8���zy���<O���P,��<�7Ey��{����y>�U���tF���j�p��#ra�|i�3�Q^�z�����\�6�y������'��o>�o�S0��Vkd����;";�Dv���|i���Ey������Dy���|����=��[/Gy���K���WH
z���6��r�8p���m4<�,����{����ZoHt�^�c�{�0��y���T������Ha���y��<u���V���.�����y�o	�J���������{��4$�i����������C
�|���rkx�5�������)����g����o~�0��z�_K�������z�K��6�-�m?��y����q���8x�1���Z��<�������z�[.�f������������S���k�mU���\���y���,R4�������t�����*r�|5�����.�e���V�����@�������l>]��"����������pAo���w�W">_����Ke�"(~����Z^ ��#��a�^��<��S����?���\MWC\��7C\�7|4v����h(�*n)��������������-Q�����v��W�=�����?s�������rO������#��j������a�%�,���#4
+]���)LgC�o	+z=?US+�SC��!��oxq���44.�m�h\������6�C��C�=|jxw{9��]o��oc��y��5Fy��]��Dy� ����U}O�W�=���l�54��T�|�����j����}��z��R2[�<O�-Q���{C����8���0��y�k�O�������q����p*���i��p�Ev%����N�����K���r�$�]il���qh��qw{%��y�$�������7T���	�9L������y����������������:��<��|
vU��)�U����m�mU{�w��#;�|i����]�zZ������]�L�����Ev������������|��z}uhd����PW/}0���'��J��S{%���\��8���6.�m�X����W��|����9��n����7T��=�o�g���|�Z�8����q��0wT�sU�t�����S�?���{X
�<�?[���z[�����oQe���^n
�<����:�P�d>�W>����@p�|Z�H	�|�i��P�7��/md��o>
A��z�����z���8����L5������U��|���3��|��/���^�����T����oAo{�w��P����x�/�z�Z�8�����y�?7�OY���������k���F}����<�?[^���o��;�k��[X/�Tu)Z��s8��J��z��8��(K�W6��z}��t�]���\o(���I�>�r�c�z ��rP&�����lH������k����tsq�l
�|��o��^�%��y|%���^���U���hsA���o���X��[������_����<�����>������.����[��|�k�;S�~�}����7�s���>v��T��]�_���z���X�0��/�j,����:Kl����������pa��y��9��j������gdL��
�����F���p�&�p�~����h�h@Ws4\�������x����8_�]�aW��W��~���u�����2������~�.���$�uu������z�$E����z��;o��T����/G�w������r�������n���W���'��yz�8����]6Gw��/
o�d����[C��,��G�[��m��������K�Ht�O���Gm5���k	h4�+����=��J�����z�i��|j�������u����S�����,����SC��Ew���v�,�+���k[�;OwK������9����zAD��n�+������JAo��w�����q����u���t��$��;�;��wDw���-	��y��4\t��;O�������5��G�!t��n��Fw����Ht�O�����4������Ew��O�����Jq8���'it���'{���S��?��Ew�X���m�������,�+Y���-������B&������LAo����+��������:o�gw���Q�Dw7�W��{�j������$��;B<O�-!^a��<�_R���S���7I
#�����x[���
!�?�_VL����5��u�c?Y�W2��+*��hOV,����,��
���k
���n�X�[�[F���@F����c}�mx�9��jFz9��^���JK��i�#��[/�}��������^��|���S��3����7T����o}��H\�w�}��[�>O���[5�y��4�:��<�7��#��z���}[����
n�IM	W�UK�WZ1
�b��k?Y�W2��K*j>��
����7��7�5��G��*������"V����-�,�+������[R�8���6�H�]/�{7��p�n�Ku�.�O���W�����w��������@�}t���@�;$������6_�p�^Oy�aN�(8z��(|��'k8�6�K�_
'����f��da�^�����M�yC:`���[�f}��T����B�kD_m�51�h\�����C�u������j�R���28�j}��`]?[R�+�uu���V�������������~�P�|��I���"PWs��uC���!�pg�.k���������u|�q��q��MW�u�����zM|=u���y�,L�Ti(�����0�Q�U�{K�������-EC�0����,����cq��
v�c=YL�O�
1�������PRIcB��8,��������S��!YYK#���LI��c&�P��	�bo��\����"��dk ��m�8�]/E�=|Y��|[����G�7�/�����:o�������)�<�R��-��Tix-/��a�#��U}S�����rD���V���$�J�����%�i�J��z��b>����i)�-!�?���e!�o>��8���z��,��7��������\�F ���|�������\vY�#�k�T�������� �B�6���!V�2��iI��YH���Y�N��~������_o������<��� 
n��Uy�8�*/{����|z��'��(��������a��z�2�T�R�������C�VJ=�^�P���Y���^,��zG*�z����Z>������R�/��������K=�|l���O��J����q��~a���okWz��Pz<���l�������_q+������]+����I������}�U���h(��G�{B����q#E��>�}��aNL�����{�1E���*���E���@����H��]=P���c}z�T���O/��;���,(����}z��E������z����z������7���s��c�(��W�J>��K�x$Z;_��,_8���SW\-���_������O2S�����nTkk	%�[K(3��DD��ZB���ZB/e�3��J������������E���9��)��Z�E{�)��Y�*���e����;xz������b3��Z�9XV�������;�/��n#��	����i���?{J@�)A@�)A)�)A���+�����s�'�Eh:�s���P�� ���r���r�A0��:d���P�!��	�W��Q��v�Z�o���Q"�c_L����+B~S�r�#!_J�%"��c�E����"d��D�^.������"�o�K�BR$����
�=�F&aSG��07��w��,�� ����
���a���cJ(3Q2nbW1;���d�P
��\��5 C��	@
��kc3���h6&���,����F�5�Z=v
���{�`���J��Il+q6�h���/��L|�������v�c����v��K�7�Wy<>���8w�������\{lu�z[���V����Uy�[w}�a|�m%8[t��JM�z��}<���Cgv�0���z��VB�k���^���Y�W����z^������c�zj��;���Z-������RO/�����q;�����A���|�]YP�������z<>v��������\�����zi��i�?�-%�'b�R����i7M���f���J86P�qp����L����}%*�FE��>�~3���>��l-alV�m�?��~j���-�^��u��u�V�u���u�
��jC�4d_�Q�#���u��>���YG��%*Dv��v��v����n`��O�����8����y����_�K�7_�d����6��7�.{���]K~?_�9���������re�u��������
�+c;}lX��������+��o�
*W���w+���-�m`����+W�(�1�P�2�k�r���S����H}�r�\�:2�)���������r�����+W�~�f+��~��s�1���9y2&xA����]����w.�Z�_��uZ�����+��O���N
��/�y�~c��s��p���������j>G�B��������9�X���hX�����]�'���e�Y���l%j�VS��=S�1�Q�@��"Rnb����#c1�|���Xg���}��|�}����������
�������q7�|���|ip��88P�qp��K�O��W���k�0��|l����V����ph��j>�x>FN�|��r�����b|�����Fc��|�N�"5�-��|�6��8�X�1�q4�|t�Gj>��j>�������c�g�;C����1j>~'��e��-<�OFI�t|�"��S��:V������<���\�,[�CQ���
����_q��t��4x?�q�}��Gx��o�'P2p���H�O[�*��S���3�S�m���)�;iL�*���vS&�jV�Q}P2z���uT��	U ����U _G�;��:z��?���"U c}�X�{�d��\������;����	T�<R���:�_q@r�=[gu�_q���	���8��]+��G�����j��#� %��A�^�@5H�����mL�w����wz5H��	����S�rN��� �G�A����4*"�w�^
�u��K�2�G��O��U`B
g|�����[x��,�8;�;���H{("�W�b��������o1^�U`:�
W�W��+>\~�6��x+�����Q8��WB��C
���cm���
c��%c;6
kK�`DvD���L����,wc��2��D<5�{��������Qy��yt_3��:��F�~�w���%���>�-���]^GX[�{�dT��e(���PP��S�g��bb�������"����������}�\~��%e���%e6�����:���Sd�z/�}4F��}���������u��������I�7��[���>����:�>F�8EF��A��OE$�g(���������SN���u�NB���d�D@����|2l(�}�^�9�}<,���~s�D"����/�^������W����W}�+nU�)�	�F�>��'�������>��.���
U��o���d}'4V}�l�WXmU���?5���8=��D�#�K��H�2�U_G�W�^��ud\7T}|�&q���a��S�x�:z6�s�TOM���
��������*@~���Cq���Z�����W���
0�`���
�����pl�d�LC!�D��/c���X2vh{�����e ����O�P��������2�?5+��>(=#���6e��H����#gPa/�:r��z�����ue���e��:Z9=P��&R��=Prp�Zke`��[���z����4�4�y�20�e`��8Pn?r
�&�@
���@H���r
�@�vJ()��)1{(n�q�W/��������
�2O������Q��d�{g/eD���e�XG�2P����T(�:z��^�;����������C���cr�?d��*B-�"�����U�\�b=W��W�\7����3��U��bW�q��11>�_{L�;z������.�vw����w�Pp��d��F5��&c��Xi2v��P���D������N�4o��j(�����w0Sz��ddcZ%T�*"���b'�@����NL�����8-*M~'#�L��|r4`���n���KJ���[vI����+���{I�c�w
�/�W�K����2nU����Ph�/2p���q�E�^����c�P�����9^P��;�eM��K*0�F<5+��A�������?��2"�=&b=%�S�����>~��r�?�*�>~/C{�%����>��HL�[���~��?�U_��{������=&q�~cw�����L(�~T}�cB��=&��]M���B��V}���>~'�3w���e?��:��8����S������7v���OE$���:Z��T}|E���uT���U�^G����W��u��|��
P=5�^����~��'c�`�y���/�@
��8�1��5`|�R���\-�9Pf��
��C�1���d��6I,y$��zX
2���_��3�JA~�����w2S
���v��>��8{��d�L)�]GX
���%]/�:���R��#cX��|(�d���{Y\���l��KA��<���t�C�Wm��T��.���@��ap��ap/���cb����!'�Pl������q���P!H��i��:�X����;�� e��A�fN����xjV���^Rz�����1[!(#R�
�
A���],������k��XG��o��l�<\O�[^F�r�\`��|x�G��zPF��2���`<W�����z�y����c���8x?�q5���+��vd�����_����_���%�����N��V�k����k����+a�r���<x�PSh��s/�����A�i1E/�_������f�\�+��GdCnm�����/���l�@���s=��aL[�o#��sj�����S�����vj����?%�������~L��W'�o�Q��(M�I�|����%{zPV���c����H��jm�l/�xLV�nw�g��w�����Y�x���0c?;
7���F��v?���v����?����O��|A9\j�a�}18�f��i�h��&�k�C��1���B0��E_��!������w����Q������d�>?�OF�]�y8������������\��.��\mf�}����������xQh�!���!���b(l����C��D�
�"�����[����N�G�^��C��X�M8�~3v�C`��wL�~�;���2��_��R���yPFE��&��d�!d�*:�pV����CPY�w*��Ae�*�;���O�!�x��<t��j��F���F�;8�[4kb)u��o�3D�?��	���*�U�~�p��/���?F���N�>��������t��+���JA�(e�0����l(@(pp����O��W�6](�����+���&�&�8!�B#B!�B!�Ca��#g��"�B���q� ��~� x42B�����B����C1A(0���B���*�WB��_�����p~B��&���������F
�\���B6��P�fU
*�?e�PPY��u��Z��x�P�����P�Y��Q�/eU����[4;�!���o���c�=?����������;�a|�?��?�����gU�wz��
U�����P��q�<
=
]�n��D���).���T�h+�0�+.�������`�!��<�Hb�Mx�4�y�4xZ��$����xI��%G(�������Z|�7��D<�}��(���Pdw�@�W�Pu�;�x�����;����t��O������xI���$��!�U�;Hr�E�<�s�;��Zl���A��r<�w�0��-eU�i���j�h����U���]6��q@H� �Ro1�����'c���� ����s��D�'�A��[�?�b]n�h!��A�}� �������^��!�j�uq�y|����8��9��b#!�!�Ca;�#g�"��?���J�8�H����s}s?8��:�b��!0�z�l:��s�8Nu�o�C��'ti�xMf�"�!�U�!d�*:�lVE�����TV�������a�~v��wKY��������h�����AeU�H��a���_��RP!26D���
w�;��*�����.���!}� ��1�l�Y! 88 8�oXH��lH�����]_��t����xO�~����y��3!94�0���0��i1��P`_a(�=���9��092��
�
�G�iU�
��W�y}�0x.�H�s��w���<��#���l~�Nv!���f*�i�xuF&;��+�E�"��e�������W����2#�_Qf��jo����u�����f�������as�n��#����7y�s�3c�u��`��x5lCk�PB�Q"�>����Xc����B���
������K�KY�|n��:z~zZ�����G=|�4x�-�J#n���������ap�a��
�;(���#i�Pd�u��3����� �a����2&��w`�W�Cz�~w����	�'�8^h����3lC6?�mH��k2c�ImC8��mPd�6��j���Y��
*��gQ�u� �j}(
��N��U�-:`{���nn��6���A=3��"Z��������O����@����fc��y]�,�G�p�OD�G��}pd|?��H�����4x��@SD|�<�C8�� \
��;8�B#!�!�Ca�
#g�"���3�8��F� 0v� 0�������C�/x���s8� p�5�B6?�AH��k2��"M�!�U� d�*�lVE���j�=7|6�^
����a`tV�O�Y�pL���Z?;h�/TV5�C���U�k��@��G94q������)<ox���X�b��8�c�B�	���	m������'(t}G�O�_u�
<���3�UH��U��U�>t`�W��B��a��W'O�;�bj!
nj!
�C��	���x(jA�m�@���J�4'�h��`P��r������{Se��D��j��
)���W_�7����������8���tV�j!�UA-��*��U����
ja�U�Qn��������Zl2���U���ja�Um�0����������������l�xqv@��w�� CU���y����kS��0x2]� ��_xz����_u�������n�������n�%"B�k��X1������k��k���P��A�}�������k�r�50r�5�hd\c;U1��~��$�����3�_�x?
��8��9��l~B��&��d�5(�=CR�������!�U�5�����lVE���j����0c�\����~)����TV��+F�0��E����p�uL�-�1�a��q�`�	�w�;�����A>K���m����q@7����<z����C<�]<���C��C:�_����5O�p��������gs�$E�%9��BC�m�O������BC������(I����b��UI<�z<@h0vh�$e�&JR��55�M����DI�f�������L�j#M�����pzE����6����������WT*��%����0���DI�_����ku~�qx�kK=�3�L�������K��ml��/�����kB��;��Ph���y�So���5��P�@�D��E����"~�]^�������H��_8N���4L���/���b(l����_��D�aB���	F��}��L�����~��W�����elg�2����P.�&x�S�38}�<�`��	�B�<^����4�[E�&��
*���#eV�������H������j���U`���H�U��`{mlI�p�[���(��)2Ja3������I�����>���8�]Fw�����,)W�;YR���	�d�4�������6"~���n^����6"�6"�f��-��,I��w�O���
�����3�A�}���������"����mM9�������n�������j�N�[�<�0d��4y�&3�!M��A�}����h�Y
����d�pVE����=YRdU����RV�L�Y����`K���ON��q)��$�?�K7����[vtS�~�O��������W��i����btF����F��.��r!{� ��.��&8�?�"}�].���.��.�`�p����,�����aH��aH���P��A�m� ��a�d�0Pr�0Pr�0�hDe_�v��VSv��K�~w���a����s�
������'0q�xMFC���$��!�U�0��*�pV���`Y��0��U�=Y���/e�W�?��aV-��ndV5��p�����������zoZ��Ox�����D������U������,���YB���@����D�<E;�����LC���4����p�KRl�4���4���b(l����i`��iPd�4�90^��#�%D4?���C�%(;��@��S2E�C�%}�\;��l~B��&��d�4(�=^R�}����h�YM����i�fU4
����AgU�4��j�2�j�bt�����=�Ae�w��M�-�v;F�4���%t���'8�#�iPB�����_�����jk]Y��A�������A��!��v����Uw���6�!��_��O����7���e�~��uxy�6GA��������ugVrh���������b(lK���`I��v������72F~�_3XF���W�%�+�8p,	c_kK���e�$���&��J�^����G���S��G��N�H��������Tt$��
�$KFG���#Q�����D���1G��a��O�S�X��9����1��o�8���(Q0$�^>�z1n��s%�!Q����_@�7�4)����2����W�8fcz�m�`f������C���s7�/���O���Q���v�4�<�y�7[ppy[�l.��6W��A#!�!�Ca���A��u4E�����W9c�>�
]z�WmO��������zUW�������0�N~�{f� �{����}�g8;�AH��+2cx���n��B��A�}�������7Z0jN�9�x��s�� �']P��3����|���K� ��T��f���B�_��4Ph�x�G��gP�=��tm���@�6��j�h�7M4m��x���6���6PY���ap��7mp���XW0hD��]���b(lm����E����������|�E6h��6_�A�X/��
��Q)�=�����h
����&���l~Bq�&��dFd�*�����
�A6_�8Pd�0J��ZvD�g�u������}7��/�[(��,(��;��a����Yj{����Mg��	����L������%���L��:�������8�|F7	\?[b;��@����I����+�it�>s%e��MB�MB�N�G�.�����	ip�	i��
W'PpD'H��$��	��	����"v� _��v�	�}�	��V��X�������wg�g�	"�O�tx�	��2�$�N�'�	q�xMFt�$���Y���pV� �v%����@��W���:4��w� �j=c�N��gl�	��fHq�	�������I��c�PU#�����c�/P�T���e�}8������N�\��*������.Jn�A���$f� �e��|���d�C�|C�|�L��o��eC�|C���R��R��.I��w�O���}�u�]���F��M���o`�u��|#�v=Pv�}A��>�}c;��7�x�N�t���
����!M���tII�}C8��o�fU�
�l�/�|m�/P�G�S=�����7��Zo8C��c]?}c�����4������/���2���+4��~|�=�������8��&��R?B�Y�X^���#�8�b|�����w���u�,C<�o��E|�<c�H�*��������7_�����}Y������������papwa��
�](�}2�$W;��`������.��(����`���5����x��Cp�:��_������3�^	�'��;t��rN~w��O�.������Jd�*��pVw����.�Y�#]�.�:O���lp<�>�qV}q�0����f��y^������l��:c
^�~�D�B����}]>��;	����hNB�H��M�.o�i^���%��	x	.�kt/�7/���O��K���{	��l/���%�W���i"���ap�a�����
���}$���.�>V��#�jR�G=� x4������P0v�XM�~w6+�q����nb��Y�{�r���:�f'Ti�xEf��"�� �SA(���9����������a|�u��a�PM�S_"�,��h�Cu��WuPlu�3����'�h��q~�P?�8PW]�o�@��#*�� ��������������5�V�,�A��Z�s��!�8���2�����������Y�7�5��&�A��A<-���7�`[PrDH��(�^��2�$�D4���2���^	����C�)������"����)���2���4�'�q�xMF�J��MHr���� �UA��*HJ~��~wi �j���K
�$��0c�F=��Z�Ei �j}-H�����^��RN5���
��A�)����;9(av�O����!��Z�Ms���!��Qt��kD",1hA�>��s�d�A���f����f���[����-B��a��y����;��b#*!�*!�Ca��U(*A�}���������Q��*���*�>l��_��-�;�uA���Y5�8}�����O�������H�=vA�}������YU#�{�P%��j7)�a��T������qV}�~%/nA�/eU�N�J`���/�}������m�#�������v�����'���y+������1�]3�?�l0��.����A��c�h�i��� W�-��;��'S
����t��h��Q4\�[I%��w���h��h���P��A�}�������h`��h`��h��0^�A40��9�Dc�:SA40vh����uFB����W�+��l~B��&��d�gA�}����h�fU
����Ae��5�hPY�
<F���U_�/��qV}16a�h�Yu�Y`��3���'A��������9,�K�����<;��p���Lz��y�=��+���qnE�(�G,H�?�Q.:[@pp����G?
p@@pp����4�<�y���0��$?�F?���[����K��?R�;��Cb#�b#�Ca�
���"��)92���#�)��
<��
��2�f��`�kEQP��`�w�����Ul_�Alp���� 6��	�F�<^���lRE��� 6�Y�F6���`����(6�:�o��bC���|�3����1��/���qV}s:?@l���L������&8Px}�{�� ���(����.)�<�7F(t�����������t��J������j��V���e-nc�d�����H��[	�Z�&�{�@\q��qwqO��������>��E�;"9����/E42S;tje_?�
������?�;iH ��^���bAd�j�4y�"3� �RQ�s*hE��A6��6`���������a�U����Y����bL�Am���3#��|�?��
��|26��@h�@��o��������7W��
\~��� �.
��h�e�`+��P��VipS<����W���]�y|�#������9��(4������i1�2�`[PrDH��(9���_sW"e@�+���e�:��+�~wb�{
D�����.
�*
��"��	�A�<^�iN� 
$��D�� 
�Y�%Gz
dV�{
D4�� ���}����{�ju��RV5�d����X�2������	B� hA������[$�~V���mu�����mC����"���f��!�����'���0[�8x�<C��h!}��"���1L��,>w�#�FTB�UB<-��V	
\,zA%��"��W	��Q	��Q	<������@�)����������(����p~B��&��dF%d�*��pV������YU#gT���v����1�T��o����� �j�	�^[GCv��rj}���	����.vt�����Z��4�_�r��YP����n�0�g'1jA���uw�M)��F��8���w���������`t�+�Y�qapwa��
�-(��9��w�A�Od�n��#�E4^��&�-0v�|J�N�������mge������W�P}K�<(��YH��+2c������`�9�B6��Y`d���������`x4��BhxN5v��9���A�fA���q��u���
?�	�Mz|�'=��/9��qX�w����y��g$C�
��M���dP��dH_�n�_���a�4�Z��f�`�����t����D������ �9 8��\6��*�x���������_���_�����������_�,�+�������l��T������l����k�e� ��X0/Z�
`^�V�yQ�Zm�E�k�
��_���(r���#�3�yad� E0/��1/<������������o��^4/���~�)��:T5|�Nu��E����������5i���(r1��^�Y�K6��{�fUt/����EeU��
���B�^xV�mt�,eU��_���!��i)��6�up�uHgyeS.��d�EW.����|1O���8�s.�.'�v��������������������������p�����.\88�����7����n������D�cW,0h�����XP`[,(p��@o\D,(r���#�r�a��vF�l�qv�Ct��������f�����>�������������b��_�O�(��B6��X��T���b!�UA,d�*��U}����/TV-^3�����	�U���[�����j}-�X���n�����b���b���?_���'�a��w���l}�K�<�~��&aw���h�+���S'8���c;��@����?�OE|?�^�i|�����4�<�y�Pt�������|n�O�g84`4�4l
6
S��A�d� p��hz��V8���f8ym4=�A�9a8��f1����1*�FL�AP�~v��f��y�l!�Q�A�d�5!�S�AH'�n�Y��tV�!�U�AHg�nD�Q�ma�U�m!*���[pvKY������Z?����s2i3��jl/����4/���G�;?:A�������u���sk��sk�F�w��RA�)fc���z��i�t�;A���������Y+�C1k���Ww���������[`��[P`�-(���v����	���F��F��F�W��x�����[`�gc�8����w�g��n��{�Mw�d*5�/�[�fTt����lNE��M��T���B6��[�fUt*�V7'���F�-����TY�g��U
�~)��7��[PY�����[�tg3Yg��������?�$4�����B��4�������A��/u�"����'�>_�y�I�

l�T��GH��G��������m6�./���������[��@"���V���N`_ p�pFpbo�����<��]�� �^��UT���E.A_����@c}��X� (��������H����s���$��@$��
g�M���i��H�U�y��/i�z�F�2��������6(hu���h}�/���3�L�H�F�G"�W���P��.�4� �C$��6�$�r3@w�lO@�d{�����g�����=z�r���P�=�@p�c,��^oWQ��t��������_��Vk�-�kk���n\�gApm� ���F��4,�;���S����4R�{��D�@cl��@��8w���%�;�QD�~��'c��
�6A�[ �)u���!�DQ7����M���iu�H�~B4��n��Q�
2�VO���2��2i�9��4�d�i��R�A�Q����q��)�}{��}����!M��A>-�{��{��{_3��4��B����}��ct�����I�[��i�(_���+n�`��r]S@��}7Yn7�k����=���8��@���6���)�1v�"vS@��ac�%.A�~�q�LA8�p<~���������g��5�7��5� �"��� �O�D*Z�hFEk�M�`
��"��3)������H����AJ��%�(��+Z�R����aJ}w��k@c��t@�5�����r8��2	���ZD@�6��B�W\�!1�F\{�b�z����[�X(��0�����h|APn}k�a�<�?����,�7%����}�d��Y|~n�qS0f�u@q]!���P\W0nD(�-8"8"��E����3��	�z5B��_�[U��Z�J3��cW�����-�	�_����mL�]�t
B@��6�lB!��� T��w-dS*�lJ!�M� �)��N��	���� R������Z�P8��R���������Q
5�:
8�� ?��<yn"Pd��"���o"P����D��Fo"H_s7�������Q�0������s�.�+_������n� {�0����Rw{���DF�(�������@pme@�Z��
������G7RpF�1����s2BW4���AP}�!�w0�������)�4+p�����gg�(�h:Ee ��2�&TT����@d>_DS**�R}eM���)���kb���q�����j��Sjy��������2��OW�m���M��IlBP@y*`���t@���?�\"���9bq�p��E���o���V���Q���r������W��pz��k[�dt��9t$2j�!���v�k;�����8�v@��@�����C�Q6�:�C �k�Aq�8��0���j=�MgF�����.����T�A4��J`_%D�*��hbE� �����T�����D�Y������*��8�h��vU�����Y���Jf�P
"��/�R���3F�)��8Y�76�@��q�+A�oZhJA��m])�qt��AI�5P��� ��~��d�<yZ���d�<���;��B8�_��������"����m���	���NX����
��}�������NXd���`{�"G&,2pd�"G&,����F��5}A�&,�H;0��Ekg4�	
wF������s��P����hE9�M� '�i�D4�����Q�"���t�g%��(�	�F�~iG�����Q��t!��:a"����C����>�`��A�����!}�]>��]>r]l��?�A��/���g# �.LZO!Gz����!�������4�r]=@��v�������Q.�v�"z@��v��3�q����3�/��h�3���|�=@��)
7���_T��>'��*��ST��1D����)T���@�T_�����R��tJ��h����-��z���XE�'�TaT�r����@\xy<_W�\W�`EFv+6Q �\n�h��W�F+rn���oz�r�hE���l<
�������C���;��w�7�b�{�����a	K�����/�Z��
endstream
endobj
8
0
obj
44607
endobj
9
0
obj
[
]
endobj
12
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
13
0
R
/Resources
14
0
R
/Annots
16
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
13
0
obj
<<
/Filter
/FlateDecode
/Length
15
0
R
>>
stream
x���[�������|C����?�z�E���_�Q	��@*�%(�N/T�����ZdG:�m/����m���e����y�O��=�}��_��������������<~����??���a��%���}�w�����c��u����x��7�w�#3�e����������L�3��/�/�e���������?~���������i5�]z$��l��V
{������li|b���P�H�{���Z����f����~�@�ZC�H�{���Z���������l��
 |��Q$���AH�^�ZC�Ek�u��k���(�^� �V�m���������k��Y��l��Bj����j+���;� ��E��������5��i����{���E��������5��k����{���E��������5�2h����f+����F���z!�zmk�����^�~�@�Zg�"���{��k[k�^c�F?���_kh	{�wR�������������_k�Qc�F� �V�m��g��=6c7��������AH�^�ZC/�7zn�n"|�������Z����z�4V{
��V,����Ef{��R�������������_kh	{�wR������������_k�Ic�F� �V�m����������_k���z�wR����YO��^�~�Ic7Y��l��Bj�����X���f�&����X��;��k[k�Ac�Fw��M��54����;��k[k�Ic�F��M��5���z�wR�����Ic�FO��M��5t�X��;��k[�����j�a��������Yd��z!�zmk
�k���G3v�k
�"a��Bj���z�X��}3v�k
�"a��Bj���z�X��c3v�k
=k��������5���z��f�&��z�X��;��k[���Sc����k������Yd��z!�zmk
�k���g3v�k
�k��������5���z��f�&��E��������5���z��f�&��z�X��;��k[k�Ec�F���M��5���z�wR����Y/O��^�~���n"�f����=�����5���z����M��54����;��k[k�Ic�F��M��54����;��k[k���z��f�&��:i������������Cb����kE��M�������]�����5t7h+�~�b�!|���A[��Bj���z��^w��m_k�a�Z{���Z�����&���C+v��E��������5t���^O��m_k�4k���AH�^�Zg�|H��h���"���$�����^�!�V�m���E[����
�k
�-�
�wR������Ck�u�������F���z!�zmk
=?��^���m_kh	{�wR�����K���zn�nC�ZC/���������u��Sc����k��i+��,2�{��(k����7�Y�R��5^s�O�{�����Z��Zg=j���X�V�M��G�����Z��Zg=k���X�V�M��Q$���AH�^A��^4
n�\�R������F���AH�^A�W�?5
z
��Vd��54���^�!�V���Y�7�Y�R������F���AH�^A���4
nt_�R������F���AH�^A��N7z�V��kSkj	{�wR�WP�U��^�~��k
�"���{��+�u���`7�Q�R�������`7z!�z��z�X��]3v�kM=h�������:�Ic�F��
��5���z�wR�WP���������_kj	{�wR�WP�U���^�~�Ic7�	4���^�!�V���Yw�7����@�ZS�H�{���Z��Zg=h���������4Vo�Bj�
j����z��f����z�X��;��+�u��������_kj	{�wR�WP�UOO��^�~���n�h����CH�^A���5Vo��������5Vo�Bj�
j����z��f����z�X��;��+�u�������_k�Yc�F� �V���Y/�7zn�n |��Q$���AH�^A�W=?5V{
��V,��O�Yd��z!�z����X���f����E�������:�Qc�F���
��5���z�wR�WP��������_k���z�wR�WP�U���j�a�������Ef{��R�WP��;���h�n |��;�����Z��Zg=h���������4Vo�Bj�
j����z��f����z�X��;��+�u�Ic�FO��
��5u�X��;��+������j�a�������Ef{��R�WP��;���h�n |��;�����Z��Zg=h���������F���z!�z��z�X��C3v�kM=i�������:�Ec�FO��
��5���z�wR�WP�/=<�����^+���'Y[�������+�u�}�������D�ZS���������:���Z{��b7���c���z!�z��z��^���M��5�<h���AH�^A��^F���s+v�kM��Zk�wR�WP�U?��7�{�XFm�"�����^�!�V���Y�����g+v�kM���
�wR�WP�������o�n"|��Q$���AH�^A������c+v�kM=/Zk�wR�WP�Uw��
��V���b��mEf{��R�WP��;���h�n"|��Q$���AH�^A��4Vot���@�ZS�7z!�z��z�X��C3v�kM=i�������:���z��f����:i�������z���P����kE�����	e���Z��Zg�'�m���gR�����zB�V��V���:k=�l�w=�Z�6�����z����V���Y�	e[�s������5��P��{G���z��ZO(���C��V�M������.���qJS�y\�_�4��q�������	�:d���Q���Y�s�|���i���+��?�}�/�fy���R�G�S������g�����g���G8�2�����1�`��R����?�8��%=���_�e���7����d{�����������M_�
\���Y���5sz�����I�K7m�1.49�����k�>���?���:��W�4)/k�����;l��on�����0���c*�r���������Jm�b������Y��C�����^jo�_���t����.KM�����*�����aP� =��^W�E�K��+6M�M�b�>����rse��I;U�i��&&��>��;�(V�T7k���^����I�� �M���Z�kl|�����g��Y"��aD�_���������>���2<?"�g�N��{%�������d{�[<�D�Oe�!5uJM�8�{��q8]�]�`V��5kb�����$
3M5�CT�c/���l�u����AjD�&�����9�[\#�d���<S��o�1����,J1=1I�h�u�{���(���?:(g\B��4��Q��(�^}]��0�|����^W]��?��g����`�u}���-=������_���$�^��8�c{|�Yq���}�C5k��`��R���#�������N�Y{��ij��g:���������g{�]3�qSQ6�,*�p��f������Ul�ER6��R�%���������@z��=�'��r���_�NN�B�{�Y:�I,���K�����PzQp���$]��^~�����B��P�:�g.t��k�"a��su�������_���	�}H������P������o|9�
��O4u����NE[-��{���x�e�dd{��IP�1�(�o4k�����V���p�g�Kr�F����j���*P�T��Y����8����Z�����,�z��;qy�N�N�T�{�P���[Dj�c�������K��������h�� v;H����5���4)5MJ�P+������������qA�&%��Vj���O0��4�
���	�{�����_DE�����#\hr�%���$x�]�e�OzR�Y����^;����7z������z����$�{�������JXF6|���0������Y�6u�M��l��o��d<�o�����{�����@�.�\�]���{���e��_��uq�����d����1��#Z�o������#����������q#�dPe`�w��S��D�A^�a�aP� ]�^+�@tz��I�iR��G��u���n�_|�[����O}�Y&���?bF�������t�����~�gW�����q�74nv������G+p����ML���a������:e&m��v���������Y����F�Wj�'4;ywn��Y���V�Q�O,��;����l�b�P|�L��,���K_��lB�/��V.������C��4��^��X�rp����&g\B�\s%��A:sR�A��tc�{�nk���M�r�����r�a��<�!��4��=e��,��y�b�Y�4(��Z��9]�����*4)����B����Q�{�G 2h���j�H����������q2������i�����l����|��"���j����m���N
B`��X�6�%�d{����I.F/`����w[f{��o6^�b�KV��n��C��������3�qB���^+��D���C�����^��2��Mtep���S����t����i��B�^liZ�\
�2���4)c�C���}�f��L����&#��n3��%C��v#h@`�����A+s�8u��{�7��X�-`�Y��6�^�g�[-t=��P���q;,��.nr��pQBW�2�a&�5)��kG��N����n����u��Z�6H-U�dE�@el�jPJ���Q�)V�C�m�f�����U�~���V��Zh��x�b�O�2�b�P��a��r����<C��C��4��^+��������m�BuJ�P���W����i��k�~\g�4M
M�B�>��C��2�M���8}JJIc�]wj��0`g�N�����#X��`���	�v'�{���@��8+w�������*b_��-�����q�H�w�����>9}����*cf4Y�����S�c��Sn�����:7�V"�e*c'R�R������Q\D9p��^���[m�i��&;[�x�{���d-�V��������\�{}�]n�uz(u�F��k�>?����"�����i�9u
�P+����aP� ���^���J�R���4)e�C���'���V�2�q�����P�\8}kk����3A{����I��-�=��3-�n���bG�4��������^��{��~>���XL)Vm���k�-�����;�M�b��.�{���q�@�$��Z�j��kY�#�v�QF@]5)��kGm.�a��#�51��k�����~�O�2�d�NY��f{�][�DF��P�$-�����`b��P��W:��K����O��R�����Q�3UF
`���4)f�#�nc�v&FNX�R�i������?a
n��d{�w�at����qV���l��w�������p)3t���7����%��m|�)�Xhb�����
�AC7�6i�`����Zy�^|�O4���^��x�h���w�8����� ����x$��d������o��{]�4�!��n�G9����k�����n�7�$����Jm�G��QtW�a�%��m��������:H����o�Z�+��iR����w���\�o�4�Z���,b��x����`�����<�X2��j����5_<�8�;��:j�`������M���Q[���W]�q�K��}u���Bsb�t3�a���v7� @�.|�%m��p��F�(�O 4�����mgO�C<�
�,�^����������I��^�V��CeH�u>�%5J����>�c��g��-���y��Z��V�����I��q	�B��{<�;�����k��O�z��I�iR���Z��;-:�@�N{4!iu���"K���Y;��v��Y�2���3"�Q���=������8+t������C�����(�U�l�6�l��X�\�N��4D'=�Xhb�����):�-M��������4BS���m���
m�JF���H�&%�{]���*4,����@��.�{�1P�1�A�x�{]m���)p-��i���k����*����`�IK{������^k� u
�P+���d���:H����
m.tz��I�iR����=��5iWbL�����P�\a%�t���@��/����:0N�xj_�&dZB���:*�!K�0��m���k����[,z+C�<�%!n��h���e{���Q����i��dML������`�0u
L�.�{]mg��p��g�'
J��^o��wn�������������8�1��F}�����Kd|Z��8C��
{��%�I
�:��F�H�J�����Z��_&�2�!�3�N1�j�6~�c�t:H��������lQ��I�iR������w7��� �	RRNC}�����;k���^��\��e �$I{��Vn+��8�8+u����k�66�2L�����6v� ��{
���F)=�������{���/�Uz��a�6.�{]b+�8�`���-�����c-�4b���b����r����b�&&�{���SVz�
�&$�{��x�Hn�H�J������?��?��`��\f\"�������A:1���m=�@�w�ta�'����?���t�z��Y�����w>L��'\t������~H�v�_)����6c:�''	��N�{�����
��NThR�����oM�K���6
�^;\����W�Ef{��-�|��_
 4��Z_\�_��
�23�N��J��{���<j������I�J{�{�$	r�P��&g\B}���Y��)�Y{��;m����$5MJM�R����4~�������
MJC��ci)B����^������&v�;j������������8?�W=a�O��zxx`���{�8�o|�f������%�vw�7u�M�,�{�����8���4���^W�YY��/rrK���{�m��9E2���|��	{����
y�7C������k}��~V1��P�$����
m-���Z��q��q	�B�Gd�aP� }��^������&��I!Cj�6�+CC�������1�o���@2��}	�{��A{�����!��N�����2 :�
�q������>��K���_�&�V��X�����������2x�K=kR���J=t��1S���-���UfeQ9T�2�e,41���vS���FE�5kP`�uA���18e�&B��O�{]m��-�ZD��D{/���r�]�@�J�����Z������yI��q	�B�����;�����k��.��&��I)Cj���9`�05��b�j�r�����������V�������v'�{�VS�g���4�{��ks;b��C�b�F_z��E�H�~��;u�T�4�TVm����:�r���Sl��e{����E[���������k�
�bHg�Q
�U����C�Mq^�������/6�{]R�f��Y+�b'L�{������f�Q��R'i$���o��#F��c4�T����%�;��|Z�s�9H����A���4`��&}��>SF��c���(i�i�t��/�6��]'����#���i1�S�2~qv�(�{����%2<�9���a����������3zqn�j�+���~�Q;�N&�����J�v���(������	��)6i�`����a~�	1 `qF4h���������g<�*����K�P�Sm�s�2��
S�Q�&���}����E+������k�yZ�T���������z�m�����yP��q	�kg���S����A:-���v��K���&��I9C��\�E��e�T()&��Vlk2����}	���vs�5�1�0>e(��B��`��B[�?2B�:�J�i������d#��2��"��f�l�uW?�1IO� �.��C��|c��$a��-�����\#��Yz��a���U��$��\z�!��z��1��D@��������c3���$�O��a��>���%��(	�N�L�{���	T��$	R�I�P��X�"=J����U�{���^�Az������u�O}tL�}���+9��~�=2���F�����k��.V���gF�	M���Z���]u�����2�{]us{g!MC�����i��q�*���g�+��2�
���Y|����UCHp��qS��������m� �H���T��J��^�>����8�(�����P�1e��T��K�{����#����J��a����B�C����^����-1������Njr�%��=x��Q�A���N�{��@m�l"��>�>�n��~�b��;�{����=��#�QBOf0���������z2�AGm������	�z4�����n���SmK��1��2Z�����^+�y:���`����������;D.���`�l�u�
r�Er�Af0`�v�n�}��G'2�h`�u���3sF=��P�{��f�������������m�;`E�T��K�����y<7����������d�4)0M
�P��������0 ������_�;k���^+�9����0|�9F��P+5<;�g���RGm��~��3>�I<K�v|������^�>X��wp��_��_�aV{��>�L���	�'PS������^{�}3���b��E��e���cP�j�u���("��&$�{]��^���0���e��g�����?b��+�0��J�8�����l�u�j����#F+P��R'i+��~s�X��XF3�N:��K�=���
c�2�����dng�Ar��4)/MZ��Gz��Y(H��EI�Oc�\%�3Re c
g'������S	�����rG�d{�������z �����s�������5��BOD �.��C]`wa`������Y��:�U�B������y�����?����"4k�����V2:��B�v��j,�b(���O�Q$��v���a,��;I�h���6�0���B�2.�V��E����Yi��;��B�iRh�2��v���8t���mW���V��
F��3A�%�s�4u;O"�1�3�L��������8+v����k�6C'#Q�nHf��8%Y5/���^w�z���[`B�%�s����hDl���i������3YIE���}�����Df�`dfm7���>�RB�E�7�>�P��_��2���4D;.��~�m2@�:=�:I#i�u�Z��E�!
\hr�%��m.PD�"v;H������E�z��I�iR����a��=�v)�5`����1�����i�BX#u�.{�����=L,����LK����T���rGm�����F����8)Z5����^��JC����Y�����J�v���#����FM�R��
�^;js7bV�2�q�4(&�{]ol�J��1��k�fm�����b���\��������^��e�;��8w�~{��� �[�tz(t������Y�1J�5�����E�K��]GWiK7���Y[{����
�����3^(���y�t�@��"F}E�����0kl^��^v�7��y�k��:���;�WI�W��s�v��j�?��@���8zMPS���m���������O���B�m��P���~K��^����>��7��^��^Xh���C]}����.��.v���vb�{]�;��uz(u��������+h�a�4��PW[���q�A���_�{�m����� ��<���Kg��o"f}w�v���w�%�B����+yt�i	������9/�VRs��h������^��M'*�:�Wm�������������S`�fe{������������bV{�=�������U����~���[g*�9��G}�����G.����{������8�{���5�
��P�$����ulB�qg,;>a�b�%�;*X�gn�aP� ��^���L������t�9��8F|�wI�Oc�\��w�{0G0k�����gE�Zd����#�������#��4�{��
��K��B��r�9�
m�Mel�����i������gq@� ��S}��5�y�5#��
`���Z�>��m���P�G�{Ns�5w{��+��r`����n~R7��P�$������v�@*C�`�q	�R��	�����i��k���	������P����E�f}���Ra��{/5��J�����2-�����wWzo�8������l�u�������[w��m����.x�H����������:�&m��V������u7=��v��3�Un�����z�fmw����rw~c&��^��{��@7�wP���F{R`�u�Z���+����������q��)��u�=����K�q����;��+���7���t�so�4)g�C���s<�e��
��Ic�a7�7v�^mw���v�c'y��I���LK�������;���u����1v��I���_u�x/h��z�m���2��O.��G:��q��i��)6i�`�u����Z���B�}��P��o��c�n�7l�v!i���
�V�b�1�Xh���C�}�{������Y<���>�0m���{��:I#i���>dQK7�M���Z������T�0(v��K{��vV�C��4)0M
�PW_���Jr�����1�����.3��	��%�C����3i�a�]�V�����u�w5�Yw����*��3�{=�������K�Xh�
tu��s?�;�pI[{��l%C�n�'��}������hTD��O
���R�~}!�D���{���^��B���j``��!lZ��������:����B�t`$�O���PW�����q���$}��^�f��R�v���u�����Poh��8���-����i���		�,rZB}�M�Y8�
�
����M�e�
�_DN���k?W{�a`�-�A2\�[|�X��.������aX6u�M��l�������Y2�Q�3�A)�����8e��������l����i�b���2�Q��Q_l��Z����X����n��^������v�l���~>��fw�g��r��A��B'i+��v���d�^Y`�PN:��K��R>��s�;����k���'�+Ay���2���<)f�#�;��c}�,C��������^��6.
g��TF��]_m���5��<������0��:�J�m��k��sF�������U�J�l��3U����\|�gmW����r��\`S��������m,,�@�M�4�(J��^5��r���^�$�"���]���Z���BI�2�`�2��������`����������
}~5�|����9jy�:=�:ISi��R��G<��p��E�!�N_7�f\B�������YF��u{�a��'�{�fk���X���n�4�Z��H�X�;�
;�����n����c�b��p'��i	������X���:j�`���Q G�~�o�h�sz�j^%����k�+��<�E��n0�C]`�V�!h�:�%m��v�ln��QXD`����g��,��O�� Cj�vyijml��#���!P�@�y��c�6��lX������Z��f;�
�����Z�����;�1X�o��&f\B����8�/��R������>�@Ej���&�}�][�kT�"�mW�������w N�:k��L�P��C��q��0N���*4)�jG�tS��� ;*b�Y��6�^+��L���v��2�]��k������f{�����x������k�Wdm����Vl� ~�/PS���������#"�����A1��k����g�/`����n1�C���h�~�o�����)��/�^�x��X5�WL�����m�E���e���C:���G��&f(u�:H�������7�JM�R�����;��I�2�p*���P+�t�E(�1CI���sZ�/�^;�}+���N�qV���{�</��m�Xs���$$�)>u���_�^����������G��.0_�^���?�6u�M����k��� N���t��Y������~�4�
�;_��\����
��:{@��1y���^;h�k������~P9�I�Fh]���P����f7E��������IZ����<��������W)�GtJ�@�����:J��f{��m+C�iRj��2���Pia���yDRL���������(������{����&�f;����{�qE�c��C�b	��W��0�����^��q��`�O����9�U��9Z5uJM�:�{���3O.2�����b�������PPa@�����C]m���f�2�`1�����ul8�c�[�d�%���{�{`���;=;Iki�����D2�A�3�N1�jmm���� (����A�1��V������}��LD2�����I)Cj�6�h��:�{��[5�P���\�0�{e���A�+��V�~
�B����Q�{��������9, �"����l�u���`#rX�A��Z�9�
=xDq�M�b��5���k���T�("����|��������"GX���Z���ag!C�
0,4o�|��~��!'�j``��`�|��;=;Iki���v�hC����q	�������+6M�M��h����`R�����P+��4�AC�(���Y�{�o���2pZ�S|5!�jm�h��!g�Q�{�9����\
��p�v#����O�p����u�����2�{]e�K�\e�~������C}[�TzW��o\h^��C]p1c
���[�m����(�^K;�?�������:I+i��>�"��UzU��oPhB�%��������N�0(v�L{��j+]���/�iR���Z��q��-�t�����^���P+�qm}�=�^^6��^+�������}�dZB������qV��m����8��S���u1���������E�r b���7,��V9�Z���C���_�=d�~AM�8�{]Pw�/��1�����l�u�������/�Y��}��os��b�2���|��������\L�;������km���
���(.��C�����^+��b�c���7&4�je��;����S����A�,��Vf�C�J6��4)d�C������/K���d�~�Ic����/��$1��o�{]�}{���Q���K���Q[�0J�9v����k��1Bm������ Q-�1Y[T{�����k����AJN	0j�FY������y)9,��&m[�����F)9&��Y`��z���'�0X�Aw��d{���w��c�2��I���^��qLe���X41��k�m��a���
�$�������)�e\��
��D����L���aP� �^��V�.9����I!Ci-�u���W`�����H;j8y�{{
��})kB���z�~�2��)eZ"������%G�Q��������/�\�_e�[u�x�e��:��:����l��dm7h��V���n6u�M�8�{��8)��+S�8g�����R�7��,��Y�%�}�4v�Hep�Lm�7{����>a�V��6������z[��n�����IK{��^�����o�Bu��P7Y`����B�A��tc�{��/��M��.�+��Q���4)e�C��b-�S^/P;B�8�J
Ic��7$?�WAt��m7i����tt��n�?i_�������mQ(����Q�{���/U������X�[-����m�����w2���	 �{]5��oAK�N(�I[{���|��%g'�n�|��=�`�!���+�^k��w40D�A	������9��m���%%�j@`��B��������IK{�������#�g�I�P����T�0(u�>K{������1B��&��I)Cj����DI;c�JI1i�{��A
�Y�4o��P�n�JB0H�����'hb�%�{l��Q�Y��6�^�%>�iX��2�
�&���f{��&���q	\�1p����9�w���I�N�I{��
�;���b�B����P;����F�q������>���.�hB�����j3�.c&�!m��H{/��l��]����:=:I[i����Xz�P�3@�	�P+�����T�0(v��K{����R���4)e�C����9��D0��4��1�,-1��=	�nJ�C��c��ThR�%�J=��4�8+u����������os�>�p����yuj��z~��;�1��S�����9�Ul����)4i�`����p�2�q�4(&�{�����X�"�������������R�2�a�6�������*�,�q����^K+��U�@�J�����Z������2�q��)d\B����6�����A:/��vM=���A���4)d�C����~I���II!i�B�-31��=	�.m�C�|C�n�I�#gI��`����p���RGm���Q����X�d�h�(}������^���e&�2�a��j���^{��e&FM�R��-�{�f[�2����A)���u���T4PWMJ�����2^e*��i���l���me�Z��8c�>���V�������������5�bje�#W�2�q��)f\"��G#����Az1��v�����4)4M
�H;���&�2�q�����Hz��7���Y{S���h;G�Q.�$����&�L��kO=�Q�����Q���v��y&�����8mZ5����^?u�u�
�^����)L�v��j�6~���j����u���Q[�z3|e,�gN�b����mnb��������.��C�������9-���y����Z���s���x��C��<C�fc?��b�I�Y{���.�A���,�<���rf{�{���8����SjR
��v���������
�+�(����~��
�_�����$�{�nkI�Hu�'��1�%����#���*4)�3�Jm�8��,F
�@'���k�6p�����"���+�������Q���N�g��#T7a&�{����K6M�B��
�^W��7^�������^+��%8�������<�C����3���dL�{��z�~���E0��~�s����	j����k�6��6�t?���a�+����s���]9t;�A�B`��B���Aw�m��=C����T8�����>��������>bh^�6,�v�Vx]�	��"�dM���R[����im�qz^��{
�C��/�@�=kY��v�����)4i��������R�l�z����(����������.���I��^;j�;�]2c����A1�3�o6��TPWMJ��Z���l �2pV]�w���~������,c�\h�gg�r[��`5uJM�:�{���Bs
����v��3��(s�&�fm����v�Vf��mlXz���v(�{�V[9�g;�B���a	�@g7�P�5��.�����^�����	���������;�P+�`��TvY]�N
��v�cNFE��u�����71�$��?��B�
c��{����.�b�y�F���5��D�P���QE�+��Vh�>/bg}�����k��J�G]4��b����l�����X�8`1VFz�A1��k��{q�����Bl�v�@j�6������*�]H0��5����;?�K��E_%��~�����,41���7[��O����{-��w���J\��������^�>?a"�A%���QV{�=�PZ���Sh��e{��h~�X�]�h���k�
��&�gTx]�HJ�����r�cQ�C�S��Y��v��a��E�l��d{���x/�J��x��5�{�������t���5!��k
������C�u���<;�{�x6�ed���u]�B���s����Yf�^v6i�`��b�����Xh;��j�6�0=�X=��B���}��a}�)e�V�{�����CTP��^�HZ�AW���=8��^w�v�qW�.!��l��B���h��"�M�8�{�n��F�"�u*�B���
m�br��cE�{���r$��	B�y����Z�WMC�x��]5�H��^}Zfb�!u���v0�jm�a�G]�a��m����=��H,{,m�v2�3��=8�#�]Vk�{����O�b
�.��a��{��>�E����,�P��^3����B{�{���a���.,���^O�E�)���R� ��k�6s��T��I�{��zx���3`����g��k,>�H�W`H��{�������%"�B���c�]ojyb{]#b�E�,��~�s��"R�IY��v�i�9q�����^a��B�e��Y]�K$F�/=�����k���9%�~A��f���c�~�:�&m[���A���"�NA�d���C��
���=	&�{]o�n��X�]c���k�=�1A��/6kR�����Xz�����fm���w_,��.�1��/6�{�����e8�.����^?tEL�wXz]�C(��u6��A~�6u�M�6�{��������Qmg�=C���a��'����72��;"�BC�����T�Q]D
�������n�Y�04 ����~��G�����?�.+�T��^w�R����F�.�!�r�C����z}����I{�]cw������~������vP�l#��h#O��4k;���B��<=]�C.���4��q����v����%��m��}�t���ba����~���eN������k�6�c���eN�.�����^�R���6���	^Q,k;g�B.4j����i��Z���m����Xh;�j����?��.�2h�vN�7��Q�K�����p�Pk[��9�um�a}���Z�m��������&gy�Z�rk�����2����^�7d�8�tq��?�>�����Ii��t`1F'�P���^���ctb{��z�t��AJj�v�Gj}�G���A
,���1��M,���Zh����v�V���ctb�W{���Qt���n����������l���U���xP�j�5�����"���AV{��u|	�3��Sl��e{��k+����"4k���^;���N(��.���d�>�z�KK������{����W��������l�����}���]�fm��i�b���������l����,6<!�F�.�Zu�%���^?e1L��;����Xhb����m^lh_u7i�`��r�9
B�tI�A���
=0k�����{��Vn�s��Z2R�I��^��Z~p}��<bXB-���Z���7�6�,�P;j�Eq��6���ja�u�EB�r6:��.^[u�'xD����6�} =�.\3@���Jt�>�8�u��1�6
�^+3x���r�c�����l�u����*��X��Y��}��Js��j9R�I��^;�~��C�E�+4���PW�QK9��D���
mg]<C����@���F�����k�����h����.�
���c/mm}�`���@R�I��^+��1��Bc�As��vM
�R��7*������>�J��g������������^;��XN��)w��{��z���4�Ph;c�j��
v�W�C6�>������CP����<e#�{=�k����CP�
mg{��Vj����*1uq�Q��
�^+�1SGP��A�$�{����o|]h��A�������\z]h�l��[���^�t��
{�z��AB�te�A�g��n��9�um�ag}���Z��3���\��������^����F����a���@R�6�j���6��8�uq�A�6-�{���7�������0��������:������>��z49*��.4�j��o��
r}�Y�������p�����g���Y������+��^t�����~o�p����UN���d{�����#�	�^��m����V��$�1S���m����l~�`���@R����g�����c���@�fm'���Vj�;�c^�
m���~���	���-��#o��K}�0���>`�{����~�:p��p��)�����}�.�A,(H��"�J��^���7������M��{���W�x��ydB����Vf3-�����H��ca�P;j�+����<�.�|a�u���t���,� �3�
��+���.�3��o�^+4�ul�M�G]���bx�h�l��(K|�On���OnR94uY�Q���Jmz@>]�g�������=�K �.�#��y�Z����3(��.���H�>����z&�y]�G&�3�Z����!�k���[���ov&z]�G,����b�ro�Y�*���Z�����K�VmN"�l���k����
.��Yg���q[��<�	M�B�6.�{��G��A�K5k���^;jc�`��]��NvLi��V�Xx`�6�j���X�sb}�Y������kw��c7k�,�H���� t�W�u��o�H;hsS��\u�(xM����k��{1G��$����C����
�:�&m��~�����Ph;��j��G,��4l�<�&�{��zhnN(���4H��Z��[�8�u�Q}����=��_��)�:@�,�P+�1����e������k7r���S�W]�	�����tE��u6�u ��v��j��\"��.�#���d{��z0�nTP]�G
��V���;����(��k���'�#EW�{�t�7q$��8���|a��@�n�O�.�[u1nx�N��z�7���T�Xh;�g�`o�!�#EW�%;v�j�=x����j,��;}��l-��.�"�G�d{�����-1*��.�JvMj���cA��5\�.:2����^O����1��R�p
mg���v���M���:�&m��V��s�I�`��cF��^;j�� �]:f���4�>��������c��^���9�t��Q}���Z������O�y��-��1�,�P�5r8�u��Ag}���Z����HI���|��3aV{�a��Z���H�S�EcFY��v������h��I����>���G���������{���s�m*����"$�{��z��LR9Lt!�Q�g��|������^�<�>������H�eT�.Fh��^?j�S�^(C,;�.i2L���a�Hl�l�B�	-�P+���2F�&�fmG���~��XE,���i2L���5�X�3��o�g�d{���`���1�K���<C�����5MF�����k�'��n�Lb�tU���1��R���]�8�����"�m����v�CW4u
M�6�{����X:]�d�l��b��jT8]���!-}�]cg�c���&B����1����n�5������K��j*G�.�"�Nhy�����a���;�k����=x4�2�Z�UN�G�d{��w�����N�B��,s�z�J�>,r��d{�][��>]Ze���x�>��z��b9>um�a����5��O�Vu�7{��l,G�.t"��gy�Z;����IW:��<<�$�{=�+'�GX`Q����R�P+���FM�R�6�^;���}I��uNF��^��V�A]�d�����>����CP�:�
m����V����A}��<�dXB�^S9u���vT�3������6��:�k���R�P��z(��$]��j:���#K������NX8`W]`�������i��N�I[��{��:��P8��:(���k=�$H�N��/m����7��1(|��. _�^��TrP1<A]�QV{�w��{R�ag}��6�j��f�4n����GY��G�d{��rj����
��)K�
L��Z��
/��Sl�����7[�(��mG�<C��c#��b���#���k��c6�r�������>��c��.�f�y�����������t
����,�P���9�e�Q������k��B�&��Q��:���<H$�{�?k��_QdT�YuTP����z����:�&m���7u�>I��1�Z����V���$(��,u2���B��n1�e��Q����1�G��[,��/���K�{��"��-����<C�fc9�e�U������k���m[���;��Ye�u�'xzI��z�UV���4(�bh�vd�j��;���N�I{������iP�Y�U@���
=����/0pO����J(b��j2�B��)c���L��.�R�yv����5�Xb��t����,�P��Z9�e[�����k��v��~-��E���l��������t	�~��d{�������)6i�`��b�OdXOYJV`���G���*���%3
��V���
����'�K��`T��S�����7��,&+���X�{����I���,k�O�K��{
��~CPV�4���]2G�A��
l��jb���{t��0�0��Y��v�ckN*#�$�l�����#_�6k���^�����E�l��d{��ov�QJ� ��
�������_V��Y_l�����1(���.�`2����+�Y�fTh;W�j��:CE��^��T�Y�fTh;�d�[M�@�%lt��
{����8d
�a��8�g��m�:����B��&}���U�!S��e]�X�-����e)N{���a3,�i2�Z��~a/��Sj����k�M�K� ��
L�����r��z2�B��&}��l,�,(+��>c�{����X�Y�U`�g�{��
Y��u1|x�F��z���lmT������9��z����:�&m��V��36���"K�
J��Z��]�
����fm}��h��u�HP9@eAYA��^y���/����GnK�]gj���{EP������v���UPg}��v�Gj�;���Y���9��'n��^��hj��^V�6k���^;l��Z�{Y�V`��.�{����;1�eA�Q�6�j����2��r���2�d{��z��A1��,)3L���a��8eE�A�6����o������/6����#�^���������1��/��u����1,�,��v��i�<����N�I�!�����������<d���C�(4�	B����>�H���<� t`�(�����>�H���@'v�G��>�%�o�X�tP�)@�� eyF�7�q�:���Y8
;c���:��is��Z�Un��}d{���@����J��K�����j�7q��R6�&m�������Pz]�f�l��B��;0�u%�a���M�P;l0r7A*��.d3J���QV�Z�t!������)&����ThR�g����9�c^�t��
{���us��G!��m����A*�����$&��q��*6r���9��m���A������u������%��[�el���^+���8�u�A��\�P����Q������\�P���8�u!�q}����=����_��
m��<C��������l������kml9�(�z�N<�IW����<R%�{=����������Ph;�e�B[�r��:6�&m��V�����K��K�����v����x��(}��
����{����|�c_��ML��Z��.�(���Xh�3,�V��J��+��<C�no����l������k�����A�k�VmN���1����?������l�fm���kG����/�M�r��.�{�[K��	@���N��{P�j������^W�u����G�Q�X�y]@Gh�Y��v����A_+����#&�{������-�
:�,�H��X�z]Ag�Y_l��Z�G7��+�V]8
Y���~��q*�l�������0��k�F����wf����i��Z����Q�����cr��~��r���9�fm����vm=v��a�t��a���GZ[L}���~��{�:���~
J�����<C���n����Xh;)��{O��~T/�1p��g�d{��r����t��Y�Y9s���/��M�b�6�^+�u/8F�.$���y����9d1�u��a��#z�P��j9�u� ��vH��w���f����[�{]����_�m��<C����!~]1h�Y�-��Vh��~]1���Y���l�� +��]`T�]0h�l��R���o�,��Sf����ke��Ya��bAB��T�g�����Bn��{
��V��[�K��k
���V���
�����K��l+�<V(��b��\�g��7��.����X�{��`������0r����!=�����u{��.�Ph;h�B�=�z]i��-���
m.P������B��@�P+�`~����2�����P;��K������B��@c��k*����4����^���9�uY$���,�P+t?�q���Hc��Na�u���������_}����u�������������?��_����k��uy����{����Y��*����+�v�������J����?�J�����]%�����:��@%����[V�/���e%����[V�/���e%������y��<�����cm��Y��k�k����c���e�D<�Q������os�E�z|�������������_���y~�j�?�n��������?�m��c|�m�������o��O��o������W�<�q<uq������T���l����r��Q����]Z���S�.�^}����:U��1<�v����v
����{vi�)����>W�Gl�)���}�#jLMK�����{�z�?������a��_��|�?>e�E�����/q������o>�����u��s��b������A�s�k�R_{�?>���3?�w����>��B�wG�y��L��9�Q����k�����3����v��U���}<����v��K=�(�yn���E� �r��F_�7\�/��I74\�g��~���/�=O���?O��n��n����{����1	��������U>�G�A�0�<����c�������3�k���%?[�����9[r��`�=u^���M�������r?��S�����[j������r�q��?N�������v��W�����#�t��xO�SJ���1|=<���E�"��zK�R��<B���y�J��fuE!|k�?z�<B���y���{�A�����??#/��3���7^�G���'pE!(���Z�| E!(����q��y�M�Q��
y�����J�\�#����<B���y�[j�G�|=�p�K-����2�p�K-����2�Pq�'��E!|�����y��]j�G]�o&�\���1��_��x������ej��Y�gh�qz��J�������+��5up�d&����9�s������t��	�����X6�R����	�����Z�n/�����+����_��������K^��t���oz�W������7��2�0u����~(�
A��d*�^�*T���U��{yuBP�=�*_�*��U
�'�|���2�>��?��Y��)�y�gY���5�p�Y���uu������(���
Y����Y��S�"�p�;-�
���gnu�eV�V�Zf*��zV�R��Ii�U���������?����Y��K=��,�
U�z��"�Pu�'��}���_�Uf�.�rV��Q%�����B���~>�5~���o������#����;,�O���d���O/+�C���?�)���l)��K.R�����F�8�p)����eA�W�"K���O����C���.�\��1����3�~�Aq���c�}t�����=��W#(�\�/�!Q�wdC*�^��T�=�aYdC*�^^c�����j�
���"
���+(��/�E6$(��[�j������E6$(����2>���]dC����y���������~����?���$�����B�������T
���|=R�v�3 ���2Rq�'��E��F���
�����"������n��K6v��/7e@���r�'��0�����1x��E����/�b)vgl
����oIr��&9*O�����o*y�1�
;�o�S�^���=�##,��s��n}o���{z�m�1B�}�9Xb���.;���;�c������v�����������&r��������"���#EP+�j��V���r�.�����mk)�Z��SQ��?��AT����"E���Ga)�p���"���i�D��/dy,E��W��f�"�����>}�i[� .|�K�|(�"���)�Z��S�:�"Ep�-R7�QK��F���n�H����AT�w���_.����y��/���u�k��d��������"�_��c��A�C_J��C�O�o'6l�;�Y���f�_���{���O����+=�������>�]c�
�F���@�$�/Nx���sb��r����!������.7����27p�{cn�cf�)�jn (���@�����J��s�r/��roY>ps�En (��w\�
�e�@T��wl��
^s'';En (��������9_8X��
E�~�`�"7>��W21En ,���_�N�b�������
T
��������[�h��x����[�h�����S�"7Pq��s7zr+B�G���N��<�:�/o��_�����p�W�e��j���k7>���nQ����|���=�6���m"������z,"�G���j%�>�����sa���W��Eq��H����"���k������(�����{;��y�(�{:c����������>o,
�.W�A��d*�^�T���-��{9[�����j_��r��Q���$
�e�Ae��/��E�+	NN��lA��/,)�A��J���:X� |������������+	nu�e��R��l��N����E�l������Zp�-����+	*n�z� (������p�@�-����������J�dh���/�c��j��W�'{�e6%�l��5�6[���+�����j�n����p~]�w�lK
*%���`y��C�^ay�JG��'��

����	n.�y����a��P��g��M;��B^����[�	>>��_4W�h�J�%OP)�r��R��<A�����o������	������'
��
�������e� (��+3�"O>�{�A��F��y��Y�������_������B�<A���y�[�]�'�|=Op�-����2OPq��WT���c��}�e���p�b�'���3���~���]7������<A/$�,O�)y���+z��`"����h�
Y�J���`>��?/������?��a�7$*=�r� t����d� ��
	����O'�����{;����7K�[�%n-w�?����,7������s�����{�h�������BT������{9Q)�r"(���"j�MX"(���zE"�k\d!����B�����E"|�vdY���_���Yd!����2�-���^w���kY���~�+��q=Q)�z�V'Zf!*_�B��F�,��n��B��F�,D���������G_�����������{!�]7��V8Y�a���~���2��+@2�)y{u��[,yJb���=
�xsyOC���4TJ�a���u����O_]iG �\���p�s.R��=XS��?	$Sa}O���DX�
� �[_KA�[�� n-����l���DAT��j�^M����(��{u[C���X�P+����Q���?+Q�N��DAT��
�(������"Q?�[H����=�E� *��+sLK��������y�%
���D��[$�u�E��^Z$
�u�E��^/Z$
j��r��^7Z$
jn������[��>���DA��o�C!~�.:�w��M�������DA���-Q�-�����@�+�����������E�����@����npI��5������y.I����%	q}��u�{����9�������|�a�}o�/L����$��r���90�?��^�e����{9P)�r>�R��|@P�=��J���/D��
>�![������S��g|a�E������2������|@����������rw��q�"�2p�-���//������[�h������J���7zvEB�{��E��pp�O4X>��F����|a�E����u���~�r�a�n����2��F�;����/_��-��8e�j
9;{-���O��u��/\��M#��e��%�O��{
�0}��C�rO���s������k	�{���AX��o��%�rO'���a|F?i^����5��{9kP)�r��R���A����T
��� (���n�5
�'k|���"k�[V�O����E� (��+G:Y���?��d��A���_�������r�c�5����Y�J����:�2kp�-����"kP)�������F��A����
����z?��w��Y��)_8��o���C�n�����Y�����a
E� ,��.�"kP)���E�`S���5����s{�TJ>������%s�A����B���V������SoK��^?� .��9�L����*�������Z� ,��^����.����|�|���[R�r/�
*���TE��R��TAP�=��J��SA��,0
�'U|a�~�*��=���)_8O�HE�z��2U�.08Y�"U>��Wv�����u����W�
nu�e��V_W�
*_O��E�T��n�H��F�T��n�LT���TA8��H�����4e� |������
7z�I
7z���2UPq��W������+����J���>���E����#EP�1�Ovd���N/�*%��"��|�@�Z���	0E~G^?� .����L������AX��+�"��9X� ,��q7�K�Z��'t?OD>f��������x&bT��3�2��<T���y��{y�B���g"F��r&b���g"F�r&bT�/�g�E�!(����E�!|����E�!|�������Z������:���+��"�~W��VZf*_�<��D��C�����{�h�y������[�h�y����G����3�g|��E�!|����u�p���o�v���W^�Qa,���*u�)���p&b��
g"����3����|�
J� *%_?�V�
)�J�7� n~�v&b\��w�����g0	��g"���a����Z��r����,	qk�H����{1Q�yG��V��DA�����Z�W�(����DA���K��o��|����[�D�����-Q?�[v3DE�z��KDE�qe��%
�g�����E� .���kb�D��.�H�
��(�����{�h�(���Z��V���|�W�[57z��mK����DA��o91~��$
��|>oY$
������q,��|��(�����������q.�T���Z�9����q�����@���3<��g�3cr�I�������t��=����#�8� ~��w�w�yow��.7������������������y
W�A���*�^�T�����{9�{���Z���A�����o�#!*����g���}����
�e> |��?	�|@��n������I��qe�J�������J����:�2p�-����"p�-�7z=|���xp�p&b����s�������=��|@P��W�������e�B��^XM�-���?J�[�E�[�o������^����^���-7~������=���{������+����O��a��oL�������oY����T�q����WSA���*��<}�R�r/�*�^N�o��%������o9� *����"E|O� r��&E� |���-�����	Xe� (���u�)��Y� ���)�����M����)�[}h�"����)�[�h�"�x��)�[�h�"����)����"��mE� |��\�?�?�������#b�u��_X�V�*n����.Ra���jP����\+P)�����
T�����u��@����j%�>�����E^ �t�~�A\�����f ,����
�����XV���kY���M���������
|DY_����Ro�
T���p�R���@���Y���{T
��
�'+|��2+|���3�g#A����/]f���rBc����J.����~���2+�fN���������
T
������Y�[�h����Y�[�h�����Y�����Y���O�Y��)����-�"DE��p��F/��(�a�W�.��=���A�a��w�"������/��d�T���|A�����J�p�a���/R�?W�����AX�
��������1��������:ps}?���_]���������������������x�������b��0~���xLq�����.n�j�7��<����I����
���O��������|�s����^�!����+|60t��S�z���	l7����|�>�n�)�����g�k������������������aZ��O�z��[�z\�������_9 �r*a��\Y�P�T*��r~�_�Tnu�eN�R��s'-�Rq�'3EN��a�l9���=�(>}���=���g��u�������^��9{DC����������K�������������=�P�7=��L{74=��U)E�e������cC7N]�+��sn�+��.����J�e���U���/�|����TJ>���\��u�\L�������4>����Tg��qw��C�o��_s�����d�x��a��W�XN&,���)$"��p�y�Q�w$"j�����DD�NGKKDD��|zVo����������A���Y$"��\xE""*��������DDT��_}��B�	_������C�����C��?���,���J���q��|=��������/�����|W$�u�E��^�Z$�u�E��^�Z$jn�d���C�(.L�-����X�!v�@��C�V>�������?]O>�y���<����55C��^�X�a�����G��W�`H\��{-�����-�i��0:;��B����R0�p{��!�J>�R�9�Z�r���;�������������j|~�
Vt�;F,{�{����;�O����A-�^���'������6�$����(����>P")R{cl����E����%Q�8��E9N���^4����
�:����lq����=n�#���g-�b���&��k��8�_�@�����w��]��^c�M]�e��$ |��jT�#!N��N�Mq��S��o���$��WuZ��:	I�������dX�I��(
y���N�X��C��4���8��[��$<����dl'!I��B0u�S��0���r��0�r��D�r�����l�/�pr�-)jC2r�K��r��Cx		��������F��<�L�~es���$ �>'���T��b�?��r�Lx	�1/�e�"��Vs���x{{!y�
@m1�m(`��T��_)�P���,���?@��aa(��n����V�����^:M
�D@���Z�&B7.���������Do�:���!q�DhM�j"��T5Z���IV-�k1�a7U������GT10��s��iZ-�������_
aB&���DH����*~|�a�F��3��7���e��3�
U�b��6����������Sq�.�x�����(t�&���w��^sT8d�z���)`��gZ2��nh�Dx
���0
�r�����SO��Joz���O!���p[<��\R�!~�S�@���z
|�tx
������6�o���M��
�pS�{��/$p�8�������������/��/ ��/�S-�4Xm3�Bk~U!I��P���dX��B�b�K
i��N�S���6'���_g�x�_��t�	���g��y
��<P1��gL|<>H�]�B7�r��0�kf~�������dg\�p�Op�����������h���������pr}~���5�oC�3n�N���d�++NN��A��d���Q�;(0��ch��/�������������������n�Hd6�mI��&���hI��Q]1�k���
�GxY_s��U��v��]�1Flzc|I���:�Ab��w:L
>!�r������$���b{W5���������EoZ�"��E�X���a�eV�������Yj-���]�1n���(�'��]�q6�nc����t`���h�,����7��Yj�w	�"�e�;�bTd��>�Y���?
�{������:@��������f�\�x��?cL+~F�`��[|�����`����W�o??\�3�G����\\��GF6ZG>8�e���r�%�0?�G��8
���4]�kQ���H���
�AC�v�� �������QRF��F.yk�T�E�q�w9S��[��S,
�D�U_,
@����/���_��+���_���	q��O�����K7�rF��S��]��hM��T��Wu*Z�:I�-�n�?������_���T��w*�[��0��7��q*p{�
��u�M�
<!���8I:5.��S��S�������Ro�x����[i��8���\�0�M���r<������qi"#C@g�E}4���D�y����#@{�D4�l���,���qY�y���r�_p:O�R�~0[���k��m�����P�����.~F�x������Z���Q� ~����R�7�ha ~���E�����~�`����Fi�x�_Eq[�(@�����5��Q��W�(H���!�����$����;����c\���(�(����Q���b@�(��(�Q�S�1��� ���iX��2��b���$���xI�}�������A}|������4��AB�GNd�r3�Qr�N����AB��:t�9�Nd���� �sRw&����K�A�]o8��� ����g����i�py{��(��-FB����B���#�=F����j$`�{.`��Wa�H�8����0}3�o�a$�&�C�H��i�!F�MFB��<���s������H�HhM�j$��U5���	If�v�#!I����#c\��FF��'!FB�Z}#!M������nA���������Z�Y���@H2k��3����|�l����<�>
sX	�~������z��������EfH����\n?�B3Y|����+$���0j���g�hy�0���,���[H���-4��z���7�$j���pmo�-�p[��o��-�^��F��[� �	�[�8�\R����-�n�q�^�@��!%�-L��uI���i�!�Br���o!Iv������B�X��If�/)$��c�������1��/����Q6V-��y]��,�B�Z����[��j|?>H���$�����m����Lf������dV�j"Z0�����������f��8�7�07���NlC���? ����w������a=$�zk�����`=$d��d;9�)$�z����,�9�f����?�I^W���|����I��'��_#���$���k�c�&q���� pK?I���� |
�c>_��\/'����Ir�0&S��A�[?�����'�'d���V�y�'9������c�5���������V������k�&V�5��j�6,��5��Z,�_�cl�>_��l��_�����kpjm����h��8�Z�y ����I��/�s��0�����:.JdQ�_g�_�������E��lL��_�x��zQ"��w/J�?zD>VFW�������gd���b�i��3���32��2#�~F;y��|���9|�N�����!��w)0�p;�R��N��-
8���Y�9`�[�48���k�x�v.����h4��{�%D�RL��tc�D�����tn�����[9r��U<�����Ck^U�!I�v�FofU�!I�����V�3d�Z����MG���� ��7���p�cd�s����9�	YII=�$�.�mA�sH���03<�$*�����[��fd+��������������(���� .����
�{&�+d3w�t`n���<{�����Qw��Qw��]!{��$8��]��-&A��M����m1	��2E��=&F�x/��\���&�yU�-&����j�&o�b���&�M�����i�)&�W�,P1	Z����yUM�$��&A�Y��	��UL���h��1�OvQ��l�[�I���j-�e.k��BV[7��e�g���� ������qf]�4s�2k�n��If5������$wr�&�(�x��FUB��P6&�>�o�B����&GE�1�5�b"4s���$���a#�����&�m�^n��;'��gn�uncH��x		��0

^p��W���\8p���z	ac��x	�m=�%`�W-E��y	����%�&��x	��;�=�K���y���9S�������%��U�Z��z	Ib������^B�Z�������%���n�Qni�q^����KHSk�\/S�1r����ZEy�f��q�K��$��/�k���x	�v��/��|z�����U	�)$Hyf�;$�������Y���o4��!�����GJ��SL�c
&C�b�G���+�a3��"��We
�QV���u���D��jH�����"��-����'��=VF�e�%y[��(V�������D�&�?�������a���j5�Q�	��K�X
_M�jH���'�7�����X�jH2�=�"K�E�X
n��16
�j�(m�j�8����S��'2O�����V������j�����,�!Q����'�'!2�D�J�G�L�;0J!0bN�F4_�g�!�7�'���y��?��L$�R�s�DBnp&���4]H�~�~�����F8>������p'��������p��M|���������}��C�~�����m)��`�d\�-%G����F!n�
6l�E���[�eG����ca�u��B���tK�Bo���0R�5���H���rg��;�!��u�����A�N�\/��,o/�oh
���e�
�7�����W�F��m�d��n������q��~vJ�~oj=L��1L1L�y����*���6a�p�',1U8��������pU�kN�iv������
:���8�J?���z����FF�O�������q��?c�������swu�h#��+��s�
��9��{�9�z|G�G3w\���^g��|F�G���6���4��F0[�������4�~��>q�?�j$` �1a$`,�"�@�gE�@�dh���	�~6>����}�����#S�D�Z�<�]F��w��i2Z��	�yU��$��FBkfU#�#��)�10����	�zp�H���T#3�S��:����u=5��o������n��������	���;�"�m(�#!!�;8��������r���m�G�l��Y�����K���z��*�a`�w^f���=���YD37����^\g��lB�Y��\��c�&T�,f�Y�pm�������{VW�b` VF;�00��Vjze�1V���2$�@?�?P�f��e������;�ib ���(f���W�1��	�������m��U5Z�����U��$��}"��,�����)�wAQ�#n���c^o��f��N�L1�T��Y�h��8�f������4��B��0�uDQ��ep��	� a�_��]������yr�o������ �0��W�%	��]y��0����vrn`|��C*z����
��~wI���I�a��^i����_$\��-�A��]�B���\1n��T]D�k��0�d�5t�k���z[]@w]1��a���k��}-���:\<�����8���$��n���W�5Hk�Z��If���5����I�5xxJ�gD]�x�k�1����zmT��k��q��5@�q5�8�f�\���mn�{����I�O���K��`����_��0�8]*Fs���LKs��+�2�L���]}�W����Wh�_�P��r�C*�3��Y��������
�m�z��+$j��>"=}%s[I��WH����_�S+�k�_Q/�T_c�TE�����0Z�W��()V_�7_��[����}C}@��/��+ z_�F��\/�/��+L�Wx����$���B.D�����
If�}���*���S��+`��o��+`����+zm�/s�i�gpc��q6�>;�i6�:]l�W�n�"_!��F���$���|v:I��8V@8��M��lC�c�EF._/{!9����Ok�����z[��C������pm�y��3�f�!a/ �n[\g���
{�U{�|��_�����r�����M5��]A�\�o#3}�"��}�����
�]��]��6��"�pG��$uQ��7���p,�H;����o��Z?����<���1�/`��������F������W_!r`4'�p-�3k�ij��E��inu.$?��k�� �?��"���^$0|�$����S$q6nm��[�Lx���[g���)��]�->��F!���y��$8M�NE��������!�o@�d��BJ����� Rr����1����8���������O���a����"���a�p����E��Y�p7,��w�"M��a�p���oC5W
[�#������b+$\�*���
��������l|[#�1U�+����
��)�@����(�n�q>�V�m���V� �V���n+��l�+�.!b+ �6���Z��
	������fHs����;�����|���&W�V�(�3��
��z[��5.����hc�b+`���7����c�������?H�#i���$���q����G����_�!Yq�{B�	�������,�+��6�84s�1�'��A!�68�����!�^n8���>$����pp��
��c��6'T�1f�c�pm��
������1�1?A�p}B�:��9��HD���L"��7�c@O�3�Q���s�B�	��'���c����)��W��uuZ�:��U�$���in��$����sY~��cl���c�Q��_�`�����zk���c�y��1���:pzy{���h�U�$���A� I��{�b$Q1���yr��~X�kVABn�
�1��A�������aO~H~��I��9&��W.��y��.@n�"�qf��vr�vL����]�p�x�X���09"��3H��g�Qh�e�����J���3�e�`��:}����+���`���4����V��q����`�-����Q����o��7������\h���$������{Ir-�X<|.���3��x�z!�z�\���zk���`�6:!�g��Q��z����d��E��b$�����}�dVk�w���h��\���&����p���4��B��_��X�&�����ua,$��0����0�kwrL��H�v�0z��r�-���fwrl��������_r�N�H�02�k,��X n��@����hc�#l�!a,p�����a,z�|�c�#]��c���/�Zm9������"��)�������s+[�����"a,d	�6z3�Yj����jYr��~.����� ��r=����q���c����P�2���1�7J��2B��[.#d��(�7!K��>%q![�!��?����!�|!#��>����BF.��
��y�����B�0�7����n t��n 0����\�fs}���)����^�/�G���|}~��5�����_"���������u�_|	��tk$��a�/���/����)��7��"�F�X����]x�vl_�qq��`�x���%���k�%�r�Y�/��X��H��/��V��Hr������#/�D�\��
�����F��E(���x�_���k�%P��#����]�X#m}��Xn���'�0���H2u�������|���MG���*�8uX8��Uq��?�0�W~H��?&Fzl�&������st<��� �����0<
��k�4�[n~�r��
O�[�`��@���1{���3�|h���u}`��	��A1hh�@������������d�5O|@75g�H?����5g��C�6.�u��0�S�E���������MS"z����U}�$��S"zs����U|�����C�\�B�r����S�q����+r�;�iJ����^
������m�p��$m�2'�,�e��g�z8�_9p�����s\rD{$FgG^��&\��~gG~�����+�$e������h^o��������C���a|h�	�5��b$\�<n�y���=������<�w��<tSgGBo��Uj`�{�)��v^^�<�m\8��bL�d���+�N�K1�rF|�y��X�<h��j��V5��Zm��A�\�K�\�_h�<�7�<�(o�/�b`�w]}��Xm��:���V����;��b�$o�
�y�Gai��Q� I�Vk���$*���1��������Q=���(H�����_�FTO4�Y��(��O\C�����-W9�Y�\��B��m��~_G�v�_���G���H�� ���F���p[�s��1p�u���HO@��woq�u��[c��:��9��1�m�M�,���c0��c�hp����M7q�4"K�~������A�Z}� ���c�$��#/�>��0���#u0�-}9��~��`r����c���=e���x,n����8�~'��c�Y{��$���!�y���������l�7����W���a�"��Gq�1���a,�r�6���>�b�c�����W�0p�
m��`, �����6��r���������D�02�k,��X n��@���n����c��p�����8Ni��+�B��bY1xF�41��ih�U�+�F0�v�zc��(���Bofc!K����,���B�\����\6�c����yc����(��������:���-}	�w�1�"dy��1F��,�FN�	Y:��5��������Y�
k�����?����oh�C�u���_W�O�{]�{��*���*p��� �]^��*�z}W��~����W��~�G�V������U<����������������������r��/'�G>�������������������%������r8�2����G.:�oYD�E�S�[���!���^�&�����������J�H���z:����������D������v�0����^)���/5�����W|��e��|�=�h@���f������7���q~���K����M
7������n�����5Go�x=�m���j=���'k����u��~M+~�?�����c[v
���r���� ����q�������u��'�+������W�{����]�f�[��~��o�����4��z��;�O���&����mR�K�u��t���2�P�}�����,z���{�Y�K�^�g��s�=���_,{�f_=D�!��(�R��}]6����b4@��le9�"��1��T�a@��^���Q���^Zz�8��sY�T!b���=`���D�5s��n�����^n�=���]f��Xo��^n���8���sV�8���0��^�>�cT�z����h��*<@o������X���*<����S*
�;�&�(�d3�����s�����K���������;�j<�L#���m
2������T�%�6
�D�a���$-�x3O�o����p������n��������������x��
������[������k��~%�z����r���M���������W�|���zE9)��[c��j>���1NR5_m��������}W/�L�W4�w��W�F�Q|xR����������P|��8�D�a@������d]>V���v:"��C���R>:��-���;rr���(>���z��P|��P|�mP|�\Q|���0�rq�P|S��(>Z�3�@��^ '���7��V|�~��t,���E���X�o^B�S�P|��G���c��*���-��O��C��V�(>B[}�C�q@�d���h;���s��w�j�S�q.,�o�*'/����� �;q
�0��W|�����{������;�[YQ���������z��i$���x�������n��9��O
2��d�S	���PEFzc��T�YM�UF&�6�q������|��Vd$���Y�2O����DF��: o��(+	��6.�����|�~;���N�����T���h/�I�""�qZ"��L�I}h��H`;CD"��P���!"�[��"���������!"�[�m"��{���;��xnkRo��J�j��J=Z��`������R�[�[TT�>���jU�a�wF�U}_~�{���}]:"GT��_{kW��G��f[Tne�����%C�a��/��s��S�-E�a�����o���J�����[>{�0|��e�(T_3w�>�v\dn�u��P}�q���=���/9^�����0�;1,�K�ze\�V���Q�,��a��pm�����\$��U�?��.��nM���u�'c��|2��4��������P��.���v�F������0�h/�6�������jHU_rNI��~�:>#�/������
����������|0�]o��f��W��W�K���P����A����U�*��2:�����(7��0��&��3�����;Bv}�����V�����
9j�9�-5�������?�LcV��?@�T��������4�F{a]�;�����Kk�������5��?`w��cn��k���\�>�����
�������l|�}��CS�M��������;s\�%�"��H�����@�������0_�=[��K�{��c����!�8�-����T��7�~�V��7N@B�z�Ts���X[�p�?���z����=�9�'��6�������?������c�/���!���C�5�a��n�i6�U��9�z�,9i������+!r�X$t@����"$]���B�N����5�R!����C��1�v=(�~�)�E="|o]D��'�����[�
�f���hM'E;��B�#�j����#�E;b�=e�o�+��cDihG`;�C;"�>rhG��"��
�������_!����������w��s�l��3�i����M	��W�xF��L7
F!~g�����G�Z�R���,�����Z�,��=R7�G��V�\$�e����H��}�z���z��1cN�^�T�?���K����0��;&�ts��k�������{������R��{����w��2>O��r7���dd~U}�^�T���n����������[-�D�|�}d���z�k�����qF��������7��oeK10���<dQ}��b`���y����^T�!|kx����sR-��~��B������1�����z���~���8����C��V��<~cV���+��_O�"��2�E����q�w=79�;g�lH?�/�-Q[���.��~�����#xKE0ofKQoe��G�&����!���^)D�q��O�~�S�0>_�W�lt�G�����}`��~�����!���C�5�aH�n��W�����shH��6}�etKF��t����������_r�{���j�F��d_�:��1|�\q�pcH��=���:�Jc��=@��S�F��Y#z/��qBD�a�����Siw���IG0��l�=�:���Cn��C�o�us/3����z�C��f�i&�u���8\.��g�;A���|=�u|9����j���9�������=�1�p�{�n��)]�n��+�E�qv��r����z�S]���K�*R�o��{�H�Sb��E�<A��C^u}��*����)���G\Q�������2��9#�E�&�X/�Q=���#E�"����G]����_�G��3`�"En�je(����"En���P��������H��W�0������6$40����y��~%d��!���mU�ze��Ra���=R����?%�.�F���;�{�C�!�qLT�%�MY�]��F������\E^��]�y�^:�D��#d�y����T�a���Zy_u�*�x�)�������iH<�6|d��3��,'$r������Cn�09$rLG�V���wm6�=�OF:V��h�0Y$��$����S�x��]���Jg��2O��������N��H����%�W���%i(!���S������5e���X��F���$����wqTI����M]9-E�!�i�#sV]�
����O����\�0s�%:!�����i�����oH<�V���#|;4N:��F���y��e�o����E#:����U�L�y���UD��I�q�o������v|��yv�����������7������b��K�����G���I4�o����a�q�F��<����%:���I��y���z��V^�c]�������@�Vs}���r|��c�����0D���q�H�<���yn��]���:��\c��U7}�%��p!U�%�h�B��C���.^vJ�*:/yl|�7�
�Q�����y�^��
�G�pE�zg}
���-��uq�=���!�U�!|��3���/[�!���uh>��g��������o�\��^�zC�!��o���[��������sv�����!z�C���w�>�5�;���b���jJX~S}�W�m ����-�USz��wM��^�VM�����U4%��N��h��	���	M��Gh��)��4� �!��4?B���)�z�D���tcl�jJ�����Q5e���+m��������<��� r��D��{�y��+�[�o�J��OD������l����6W$�0���C�M�����
U�N��?@��N���Uo��G���7|PU��c���C��]���N�4U�TV���j�GN(�$ 
7	}�!X�)	���M���*>@����P|3����U���Z��D�!|c�~sV��."r���P{���j��j�~�/?4�h�fn���������o���{�h�P{�lQ{�T�m�,����j�7�WC�����U����	b�W��yQ{����c��#�E�%OP�����6�-j/�v��J�=@/���M���]+�j�R��z�0���L��R�V{��k����=�;Z[�^��l��\������`���t��^n���8��k��f��0R���8RdH>�vH�)�W>J���H>B����"�}�|E�0$��$����<$_r�����|6.����������<B
�!Y���C����#��9�!��te���no��+�xS��>�oZ�s��*��?�����cn���]��!�?�vs/3��!���C����?�f�[7U�����jK90����m���� w\�#��h����{����l��iT4����#�/9%��$�/yl��'��&�_���E�����4>B�B�|��}�I��{����0��k�eD5�7��$�/�_��Cn]K����a����oh>���E�������������v��z�,��iS�h������-!f� �)��QU	�2.������5����>GU%��N:Q������=����U���51�0���lU�?x������$8
�"���K���G�K,�7�8��*ni��A���B��Y]�X�0{���y�'��9��]��,��7d�_(��r|CY"�^�q��o�������?"��-��'�>CD���x�U�����A�������.���^:U��~����?�?;U����'�����!T��D��������h���*>@��>�����0nz������~<���1�����9�/an]G�����:������z����
��\�,�y�B�!��b��������E�M�S��jP{��������5����O���wmm�=�uSCi�w}AFx��K������p�-�"Y��C�B�zi��P���M��R�G���Oj�a&|6nP���M]Yp���o��1Q{I���r��`>,��_�6|5��o��������6|5���o �f�[?rS����C��rS��[�� :��-���2�7��#tS�B��#t�z�eJ��!������t^vJZt^����x�-�^���B75������:t�o�q��S4�z
�qyS��]�y��>C�e9��y����2�������[o+s��7�v ?���8���^��U�w���!D�����_�C�o���~*�I�|����7U�����}���H>���(2T�����fW$���3"��'����n�	����#�uFD��vy���K���{�3�sO0o��plU�!|c{���,[�!�����7sC��������s�����L|���xx����y�4�_���������������������(�+��Cw���/����z���r8�1����������)�^����y�^ZU�ze��W�����}���_���c�TVb��h�T�[�un�����\�� S�&'�>������.�0��>��m����!1.@����+��z����X"��sG����Zs��/?��1�:����V�����O����#�������{�kXf�{��C�"�����z�ef�n���8��m��f��v��^�����#���T5��F�T����8P5���iv��0�+��T���^8����s���������.Ua��rZ1,o����?��5�T����>\�����=@ogY�d�8�������AZ:S�E��<��������0.������
#����z��O6i^o�=��+�m�9{�z�7��Z�{�{����&����������v�
����ze|����^8C�1|g�3z�7�fV�
����s�2���wwC���a��{c�[�=Bo�������,�6���~�y]��}��/�G�W����rJ���|R^K�o���l
W9��z��[��w����������}3�C�5s��c�_���^�����8�DDb��*��4JT����#��p*�p"��X��F���h/�{�*�������������S7+�o�����2}xn�����1�sE�z�%@�z�<��m&_�h�{"��AZ�N*����^���O��e�	���m!��[7���k����
�\C����]o�>\o��k��~%�*�N�MD��������KC����`�8}�~v����X�����pf���C���%�7s�������S�#�o���M�����Q�B�����<��O���������p~}�����;��DD���]U[����Cn��Cn�����}������rC�!�c���}������u�~�4y�6�^}�����!hS����'J�+g����l��x���~y?�o��eX��K��gg���K�������7x��^u��������G���.������k������h\�:iB�������Yl�t��I��\Wm�p�}�jK�?w=D[�n�5����um�����j����-W�����������l��~%�C^����$�q�F ��FcTU��^�G ���/����wW�)���`��>�@����Q+�w��QQ����r����C���V|��-#��N��~���-��gSE�z�T/���X�
kN�F{a��U��p�=V����a��9��[�$#���H\�Z�~�����w�!�z���w�!�z���Y���[�����&C�!����B�!zi�7!��2�E��C���%���I��-�"	�vE��9�l��fj/���3�c���q���������5���ll��C�3#���N�P{I�o��-N��0����K��zo�P{	����;����������}o�
�"�����5|B����^;�4_C��{���k�|�|����V���q]%�W���|��up*�0�KgN�H>��Z:�$[��>�����\�@U�!|�N�����X$����|��=�����iJ>@��+��s���3&E�a�ow{�~0�3j������E�=���~0	��5���!�z���-��w�!�z���w�!�Z�*�N��ND���)����*�0�c*���-���X�$_q��H>���[H"�p+����|����h�|�I1V.�o����G���:C�C�zc������XE%�zc"R���^�}T��<�n���|���I>`��|�mp���C��rC��E��rC�a�)���
������������}���=�R$��"}r*�EI"�nf����Pd�$��R%�Y8�EI"����"J���/��y���4�U%���z��*�	�7n�[���$k�3�����6����9��$1�kg��(I�v����5�,��Dx��@d��BI"�.i_�P���
%������=<�{��$�k��4�w��k���6���v�������0�j�[# �,�TRU*�pOwN�a~��[Cj���}]��I�k��\������qk;�B��5F����e���������/I��}[~��q�E�_�������C���1��[�7s��Cn�EA��\�]o�����C��k�{�!�Z��]����OA�M�����#���$$���+���?Bo�f�b�q�o�������C��V������7s��<�����.Q{S���=������;��j���{�#O�z�4������YB�q��V�����z����g����k��'C�1��!�������f�P{�mh'�����x���n�i&�-w_��1C$��H>@/��Y*��T	L������0=T�!|�Tn�����I>wPp����n��nUv����G�����GU�����D��K�zo�'y�;�mw9�Me!�3Z�T����J`b�H>��e!��!���a�us/3��a�5sC���[H�V�J��oLAl�D�t�K���(!�-o��c�4Z���C������[�q�iE���vl,�|��T�M��R	�[�����������H>@���_%��K�a�F��J>�o���*��3�H>`�H>�6�|�mh����/i^oH�^nH��8��Cn��k��>���r8|��t�/A���_�������"����/�@-��?��������
�I�Lm��0�S;�~�]���
���7���v�(M����U�"|�H#��:��/�G�MQ�_�������jw_V�!I18F�e�������$�G��Gz?���wN}�R��������k��WA�<���K�������������!H��5x��^��!���.i�C��}A�\���{����x���R�G�5��J<D��U�z�\<��z��_gc�7�I���X[C�D�!|k��!�������K����xp�7��xIp:�z�l�H<|��+"�pC��g�x���xI��F�xwnk����� �p#��!����9"�/�����[������Cn��Cnu<�]���������\"��d������X�G��q�R$�7��(���P��x�6�:��0|�����c���cB�e�M�o
������#t���G�E�an5:�|H��w���[���������M]�������$��|���Z�Rw�{���s��~�r��~���r��;�^s|���=gr����8_$4P���j>\������1@5�W�de�|���V����gW�d�hxX���H}v��2|g����#&C�M��MC�apZl=~:�:p�|��9E5�A����#���?�����O
��v�2H8��
�_���z���~��;���)K��~��[2�.)/3��"�z����W��~I����q�HH?��H??�FU�!���T�a�We�J?@o���*��w����K����!������~�9�ED��(y�7w����K�S���!c��H?@o���"�0.�7���[�m��pS�F'O�|�]D�a������m���p����C���74r�>��5Th��8��Cn���i6���{��	;\?��^�m��_wA�1#�u�?�Y�=Q!	�'���
IDEHze�������(�B7���/B2�F�@#�$�7=��n}�!���������#���d~�z�$>B�1�*$qC7�'���tk�*$qS��_�B2yV�B�{C�
!�\�� s�9#�-���m������'�1�^�|���}M��m�H�=`�T��b��+*�m��"��2��U�����r�{#�*�0���I�{�:��E�!����r/yl�b�)�w>��P�����G�h�(r�c���=��z�{�t�$�pS���W����3�$������!���h�=�6\�]o��f�ev��~��0���f��\?<�������;��Mr���y�"��tC����"�}�Ll�v!��Ws���:���I^��z�t�����s�+�����j!��rCp
����-2�{Yp�=~����!��qf������	��xK����r�7����o�w�=~�z�.��[w��r��m���]�1�/��!���7l^��{��r��[�{q5�xj/���z���m�����J`Bwi>@7]
$��q�D�a�W�VU��G������A������&������|Ip��#Tw�T���:l������$����>7i>���3D4�o_t]����Wws���|��i����8�������z���z�Ch>�V�l��{k�/��-� ���]��������B��g��h��l����!�/��z��|��#��~��R��z�{lZ��L�S��k�|Ip&��#����tV��y�(���pKwM�7um��P��<����������
��\��3s�`���u�����g��������#�{��o�����r��u�'z���VfA���b�����k�R��6'*%�r��qv�M��	�w~�EJ&�X�e�R�[�E�H�n\�)��������� ��"%�G��d��P�'c�P�_MH��[���&���6�R��r�����.��'�����O&����Dn�"�$r������6sCL�rCL��������������6'
endstream
endobj
15
0
obj
47439
endobj
16
0
obj
[
]
endobj
17
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
18
0
R
/Resources
19
0
R
/Annots
21
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
18
0
obj
<<
/Filter
/FlateDecode
/Length
20
0
R
>>
stream
x������L��W�33d��r_�=�#&����.@�#� T��`����$�Z;�f$��n���v�#��$#������������?�=��������-�k��#����z���)����
������������kM�w^���%?����p�����?X���k�rs����>��Vb���o�����/����-���`myq�9���>2��������k�?�\��	���#_)�����6�^���V�
(�Q��'Q�B!G��q^��#[�U+L���?���
9�������G���Za�x�d�I�G�P���O���r?�j��l���� �����/rT��Q�W������V@�����#_)�����oE[��/ZAE<j0�$�#_(�������G���ZE<j0�$�#_(�������G9�i+��G
��D}����|��}���l�W��"5x��=��B��}>j��.r��Q�
(�Q�OZ}�+���|����VD^/��?���������|���z��\V=���"X��z��\4hO|���z���6=���{��Q��G
��D}����|��u������V4�n*��'�>��B��}>j��Y}�e��T�����'�P�Q��G
N��'^��ME<j0�$�#_(��������ivS�\4�O|���z���4�O\��ME<jp��>��B��}>j��hVGF�U+�f7���V�J!G�>5x��>�2�n*�Q��'Q�B!G�>58kV�x�f7�������|���z��\5�O���ME<jp��>��B��}>j��Y}�:�n*�Q�w��_(�����6�_���Q��]��
c�I��|���z���iV��5�n*�Q�7��_(�����g��o���"5��/rT��Q��f���4���G
���'�P�Q��G
�5�O\��ME<j��Y}����|���%Y��W��5��8���Q�R!G�>58-����Yv�"5��/rT��Q��K�:r�e�+�Q��'Q�B!G�>5��z���,�]��V=��
9�����_�d��Q���j+�d��I��|���z���&mE�e����G
^��"��B��}>jp�z���Yv�"58e=��
9�������QGN��vE<j0�$�#_(�������G���������QG�P�Q��Gm�.��'~�Yv�"�1���G�R�Q��G
^5�O��������f��/rT��Q��f���ivS��?���
9�����U���y��T���O�>��B��}>j��Y}�:�n*�Q�w��_(�����6�^���Q��]��
c�I��|���z���iV��5�n*�Q�7��_(�����g��o���"58kV��B!G�>5�jV�8O���x�`�I�G�P�Q��G
�5�O\��ME<j��Y}����|����Y�W��5��0�����W
9������f��_���"5x��>��B��}>jp��>�6�n*�Q��'Q�B!G�>5�iV��L���x�`�I�G�P�Q��Gm������j����'�>��B��}>j��Y}�e��T�����'�P�Q��G
N��'^��ME<jp��>��B��}>jp��>q�f7���E���
9�����M���e��T���O�>��B��}>j��hVGF�U+��Gm�?i���rT��Q�W��/���"5x��>��B��}>jp��>�:�n*�Q��f��/rT��Q��f���4���G
��D}����|��]���u��T���O�>��B��}>j��������V@�����#_)�����o��'~M���x��M���
9�����Y����4���G
���'�P�Q��G
���'����"5�jV��B!G�>5x��>q�f7�������|���z�����4�#���P��6�����W
9������f��_���"5x��>��B��}>jp��>�6�n*�Q��f��/rT��Q��f���4���G
��D}����|����Y�W��"�1���G�R�Q��G
^5�O�L���x��U���
9�����I����4���G
N��'�P�Q��G
.��'N���"5�hV��B!G�>5�iV��L���x���Y}����|��e������V4�n*�?y�G�T�Q��G
^��"�2�nW���U[�B!G�>585=���,�]���u����|����QGN��vE<jp���#_(�������u�2�nW���O�>��B��}>j��K�����j����'�>��B��}>j��j+"�f���x��m�VD�P�Q��G
��u�m����G
��u����|�����#�Yv�"5�&=��
9�����{���\g���x��=�QG�P�Q��Gm��4�#���{�V�����V�J!G�>5x��>�k��T��o��'�P�Q��G
���'���ME<jp��>��B��}>jp��>q�f7���U���
9������E�:2��ZQ5��0�����W
9������f���ivS��?���
9�����I����4���G
N��'�P�Q��G
.��'N���"5�hV��J�����h��'.��U��+��Bn��'�P�Q�G}pZ4#�����G
�����W
9�����WM�/��U��}:j2�$�#_(�����6N��'^����t���)x���{p��ES���{��Q�OGM.��'�P�Q�Gm�4O\����t���)x���{p�g]G��i�����Y�Q;��B��=8jc]G���u���GM�u��<]W��'��Q�:jg���FE<j���v���j�?y��XW(;�t]5*�Q�u��3w����K��@��cIu����T���?��"�i���R�fH��V������=J�����/���������1m������]���?bN�Z?o�v���6��G���a�|t>�C������W���;�n5v�Q9X��4�|u�i�<��I����M���Q�����uO���6�1vM�Rc����t���[��vGr\:g�_'�Sc����O�^��}������^�o}������J�iq��������s �8�m��x����Rc���������-��:�g��6�V=���2�Q�Fc7�?��a�|?�L
i����2)�N����zB
���#�trZ�����*m�2�GV���-��Y���&��������Z�M�6*�U�(A}���i��>�����>�����]>a'����S�����'�CV��B�8�g�
�bP��B��V�G-������U�RX������!�;���_t�����j���e������.�}��0+�d�1-VY��k	~�am�Z��
���:����_t���W��X}d�Nb~�!�� �P]���������rV
+g���#�p,>]M�u�3��"�CV���	J900����>���������U�+�#���0��/$2S�`��P�[�K�����u�E?F@�1�iL��GV��+��U�M[���*����V9���t��rr��X}�GM�7R�L�"�GV����_w��X�'�)����Z�o;���T0�(�}�Az�E�����W�����>�J�a��;�U�*��6�m����Y�G�X>����`,������y�.]��_u��L��GV����_xH����mC}d��w��\��������i4���#�������nc��N�lR�=���?��}��:d��N�R�|���n�Kz0���CV������Jc�W�K6
�#��!����������n���C���Ak�g�'��v]����B������m6�v^'|�["X}�4X��	&@����/��{����C�mUm�Y}d�~>��}��r��tP�������;�D>�@�aH~��v�8�#������n��QF~�w�q�sGq��?�W���F?,����M��n7�<����Mk7b�A�����H[Q�a[�%K/�^��b�k�>���3 ����{�g$\^*MI�I:1�#��U9}��M������m���'�Z�o�u����io�0�a|m�iy���<�����A�����������[�k�����3���#~x^���&�<\����n�h�_�D�e�0�x�{0v�A}��b�d^NS
W����V��������*m�&�GV���,C��LyZ��X}d����!�P��[,�!�vr�t�H}���fQ)�#�t���0.�r�l�G�������4X��_^����P�[���w���_h�e�U�15VY��~si[U��m������2�W�\����<ok����(�7T��v���"m>��rw/���rE�������!kS���8���=A�����b��QY;�>�q��{��E�E����*�%:��f�� �`Z�>d���<tiJ*M��Y9|���I�Z���q�Gm+�mE5irh��
�{��zZ05-��G<�������	
�#?�O���W���i)������[sUk���>����|��}n�$;{��>r����N)����6\Sb����zY��
B����i�PY�x��]jj�Sc���v�{'SV�������#���u)��zJ���d�jg7_�Z��9S
��/������Q��mYT[�������p��2-���`j�>���etA��j��c�GV��;!nmE���%mC�����2+���`ZZ��3����j�C����>b��xi�R�!?l,�K^��Y���:.��1���\���������+�#��~�e#�t�4�`����>r���x��K����mB}��Tn� ���\��)���#�u��sV�������#�u����g����Z�����*���0r��z�q�����}�[��E�EZ���j����=�L�P��iUI���U:x��#��T���>r�|/�GxbA��J[QI��Z:�e��eZ���H�������1�\U����>�J}���B������8���)���#�ng����i�r���R\r�G�� ��\_Mqo��Y}����@�`�WS0�s:�Tr�GV���z]��^���}����A;�����d=���F�u�Q{���I}��lB;��G��{��(-�J�������-X9�s*��%�#~�T�����$]���%��mE���&m#����	����j���G���b~+3���z^�>����)m�������aD�n�yc�oWld���F���oS����R[x�6$�HX��X}d��N��U�M[�����|e�"�"e�i�1%VY���\Hj-e�^���>rh��'�hE���[iA}��S�@��y��^;1�#�O����K���"-e}d����=�D�}�Lh�2������U;���6%�&�������r���VT��j�6���m��4���iy���<�"h`����?c	���6���u0�&t�`����$�7�
6}C�������
 ���G)����R��)������mUi���>�H����t���g���z��i���j���}]�����>�
� t�Uv��
�����
��?�@�1�i��`�G�����k���"�e}d��}��Z
g�j�>���[�����$������1m+�mE5i��3�1-c�3���������h�v(04���������7Nh�C�>rh���0/HsUi���>�@7������lR�t�����������>�,ox
�Y�2�0�0���#�u������i�PY�7&w0�2�8�I�����;{r�-"ZchPY�����0�2�0��zjQY��G�gV�8Nj��>�Z'��	kY�Z��������-�s�U5yrhl7.����0XSRk�n������)O�T��j[QM����3f����>'��>����S��\����>rg�����~�o�(x�$>\}y82�o������qQ�[����:}0�C8�mUm��Y}���{�
��������>�����T��bx��`J�>r��}��Z���d=�V9ho�O���Jh'����z�+������C���Az�Gu����$}	���K/~Twi+*mE%i���6=��T@j���G����r�@k]�Z���>���b�)������>�i�T����5k��>�Zg7^�v��]��x/��#/���l|`|�����i���j������W����u��Z{�J�C��L��G���\���7��A}dm���x���)N+�G��N�Y`�����3dhP9h/�; ���K��������j�k���k�>d����O�����$����6���/mS�&mC��������]Z���>��O���V��r����]S�!�7v�.Gt}}��.��.}�U�@���2�t}��^0=VY���wo[���}����{�S�1�W�I%VY����1�����5���E;���u}�Z04�����!��
���d24�����!���//��;�>�\:�)MI�I��#����j9��b��&mC��=����E�Uz�#���{#�r����R�!�7����~<W}-��n0.U��)�v���c1�{��|�X}d���y��mUi���>�Ho,��U_��L��G��������/�S������}w���b>�`XP9Xg��U_���!C�����9SZ�i+�#�d���p����$�C���+�6%�&����������|�����
Y�wo�S�����]���U;}A~�������iA}���e��{����)������n�U�Y���!v����!��wcx�k�wa����C.��d7��zs�Vf�������V��+�"���|w6m�#����R����������,���������j�v��O+sM�����K�X���1���|���s�����r��,�-�X�GV��'��e��������U{�	b����$����~�/}5����&mC~���]�1�/����!�����1�o�S�������[sUk�����:V�^����[��q:������������Bd�	�1�S���>r/�sy���[���������:���1bV�'2I-G}�`�Na�#�"g�=���D��cc/c�)bN�fOYO��G���S������LF���G���i
�h���"�E}������1+c�S�U-yq�^?��!iJ*M��Q9J//�<B mE���$m#��L�b:��[Zq<����� �[�7�c���wr���eVg2���>��>���5W�fm��G~8H,]��.�����G^�����3�-]�V�o�U���{;R���*m�4�GV)�Qb��S�P�\b��;��	e\�Z.4�M��!k+�Q�������Vu�O��,]���>�!�J�'=�tA�i-�#�u<wC!#KW�LM������Z�&�k�tb�Gm?in����%���Z�6�`�n���C1�tM��<�;���n������>r�f��0��&�K;������x��[sUk���>���I�o�2�VN��^mVy��P'?]!� E�A
�
���U:���XYPQ�V�6m�#�t�x�
V$�`�!�5��yG6QaYF��o�
Y6�7�&Hd��}g�:� �L�Kfe���"ioE}�M=��eQi���>�J��e��1X���}����
5jSRm�����_�37����VT��!�����"� S���CK����b�Dm�����E{c����	-���9h'+�$ZsUk���>r���<��x:�3����`�-h����gzw�+��c���Y��hA@��Q�9K�#w����!�Bc�Xp�6s6�39��d�)�����j�?�2�g'+��P9x���������HkY�QW��0+��S�U-y�k72<�mE�M:�#���;Z9�s�������:���9�U�,��Q�CV��IG�&�0�9��X�G����d�!�U�Y[���*�_��|~����R�9i8�7Z}���t=����X�xc�/�Y����ri[U��m�������8����yDR��G����2T Q�0�]"�!k���������J������N"��z�p�����4�[;�U�Z�i*�#?i���I�'�5�*���U:�)���������>�Z�W���P��j[QM����gJ��)�yCSK�C~�X��U��w��C#����he�q���	��ub����4k�P�Q'��:^k�����;�k<�#����o)�2�0u8�%G}� �\�zJ��V�6m��G���_H)�2�8iI*9�#��w��N������tX}���}W=�L�T�L)�Y���A{}��S�^�f�q�����#��E�n���mYT[����|��bR��+�J�>���/W����4%�&����|���L����V���z�6���s�2�8Kjjiy���+C����������2�L�L�,I;��G~6{h���Z�6��#��+���������>��B���Z}��v����U(���u�*����K����-C}d���g�Z��.����,����%\�X�%(A}d�NV�`h�

�����R��H�����G���>r��|���eQm���>r�L�k~����@-���9hg#��Rk+jm��X��7g��T��x��\���U:[����(���yE}�g��'Px�ySS�!?;�L]���Y���a��m���e��{�Z}���O��2����(���u���F3�Z�[�6���:�i0>t�j����k����f�k0�^5����?rz��r
�����R�����]��
�#�S;$�!��E�EZ����������R&�����9����S�MI�I�1�#����>����VT��J�6d���Q�V��M������;�1�ti
�V�K������-,M������CV�xb��1xn�����8�GV��I;��-`�X��`�pj������E�_��C�������o�Z����Bq�.H����mC}d�N�eVF'1I-VY���j.Hl������Ez{oj�l�;e=������"���a�`�,F�0�#�'<�\��E�E���A;��,������U5yr���{r���Z��b�GV��]p.8[Qg+�H���s��X���\������!?��zna}���S0$�������{����Z�ZPY�:�9�]���.r����G��V�lC=$�.KA+�wu�C�������C��m�j�6��U{oe
J1�2�K�>�Jg�2Cte
�������z{�j�1�45������Sui
�2,������!�4�k�4�����N����)����!�����]���I�1�#�n|��+����V���!���u�5�O��d�:Z��y���R��>%���uL�~{v��]�����y�f��������y?:�HD�z\a����Yt_f���v\�V�6m�Q�$��6��y]���������!�@��]r�G>I�+�r$7/Gz�&����>r�N~��@^�����^��Q9J�>������H[�>r�N��9����</�W��}�'���!\��J�ta����������I�6��]�GTx�����s�G>u��7�`����;K�����0[�4W�fm�Q9H����{�����������G~�{���<C�j2�����j�h�=;�I����mC}d��n�x�`��/��j�>�~�77����h�}c�m�A;Y��!bV��YO,�#��4Y��c+'����A}�;�q�nt����HcY9t�����"X�`�^L�$�C�uN�u��T���>���N�)���Y4���m�j���c���	���YE}d�������Y2���}��	OY3��fm�#wZL5���ZZl���L��S������G���3<��"^����u���<�����*m�8�G�K��&KX�.��}[����z���Nk�B���j�
Y���LHX�.�����R����icZ�����vc�G~�3.�-�j�����������nE��
�%�C~��ed���z�td�GV���K$������m��>����[�k��}S�<�`�>��jB�Q[�?�>��n����-������EPQ��J��
��;�������||%��+���}U�>ry�j���Y�k�J�n�u�j�F�����i�PY����N�e�q�Tc�����N����o��
Y�w75r-�
���������8�z�q�����������,j-�V�G���I.�2�8�Y���!�����N��J�tb�G~�T�������m�j�/���71�8sj�iy�A{�6b�������l����eV��N��P�Qxp���Z��
���zo����r�����	��_�������{?Y����I��������n��;�'�mUo�fY}������[l�;%����u��*sV���b���Z/��s-s
S�����#����Q�z�q����#����A
7�����,j-�X�G~��=���h��iUO�G����{r���:��b�G��s�iSk+jmE-i��o��Y0��T=�V9Z����Z&'1zZ�>r��^��d�@��J��Y������_6
D�o�z�p.s07������i{��s���L)�}��:duNVf��2S
��VY���$��U�aZ��Tu�CM����U�a�2,�������Q����HSYY��{�TW��S��!���g��
-�]^�'��>����*�����X}�o��e�]k3j���<����&�r��E��Z�G���5�������G�yvy��U0�bn"k���'�pd��\
��k��E:���GVY|��6m�#�t�s�����>�`���5�y[���q9O)RFp	�#m�`G.Y|��`���!�t������>��B����z�&�[���"me}�g��SDp-����Ig��4%�&�����+��lmp���V���Z�6�G��#������mm��/��U;�7��CM��I�[k��������0c�\U��q����so��|t�.���x�_����#�'/�zn��n���u�b��s��U���?��#�d9�-Y���`���5d�N�Edr�����7�������.Y���`�!��!��n�%Y����#?k����z�i�4���5��K�=p+��������K=��Iz1�#��N�bf��?�V�o[�
��ye��
���yE}�g�e��
n�R�!?�M�Y���fm�#�u�:
tY
���<�������C�,�i���#�$w0��Z.���!�tz�����i�}�m���9��������G��u�(��^�p	�#����w�h.Kt�"me}�'m��\p)�������sY	��&������3�h.Kt�VT��!�t4�f:�2cd-������u23B`������l���j�r�2cd
�NS�!?:��Y���fm�#�t�^����y��?`����{���Q�u��,@�Zc����v�|cK���Mg���u�8.Y�����9�#�$][�A'=����L����\jL��G�����,?�����#�������,�-�X�G��i�f���l��@��������W���>�I�ta�G~�V&�,>�i[QM�F��?yr��n5vK�#������QZ�7Sb��ou���
V�g1���>���2�d��N��iV��^>>������;��8n�j����:���eV&f/��ul�Z�KW#��m�j�6��U{k�#�2�8eJ*���Az��l�"��5��c�!����n�e�a�����>�C-S��z�q����������>�,H���"me}�gg�3���4N�V��}�Oz�g�)�4I/f}�G0���1����>�����i9�s*�0�#?j+�qHsUi�����*�m���\�<8������G^��{?����^W<p��G���L�����k�6��U��=<��\�<�L��GV��_r\��^�<���U;�lp4�%hs�����G<�C��\�<��!C������\�^X`*����E�E���j�>+���h�k�%�C���\��J�tb�G~v^}<�������
��w�Sh9���iy�����Dr<��\����>�����0~��UP�����s�S��������
����-��[�C��\nm�Z�6���:1~���V�����Z�C"�ojm����w\�����pQ��R0�B]��U:�:���p�x������}���-�j�����Cko>�F-|h���}����[\�6;kJjM��Y����-�.A�}X�!?<��Dm�S�Q���h1�C���C�6��pP?^��A���s�P��\����c�Y9�����7'�C�tM.����U�M����j��P�M�A�W�I5VY?�����^x������oP�
Y[{�q.j9��*?��E}d����V�y������5�Guh���"�e}�g=�Gu�r������9����\.MI�I�1�#��Nn�sL�������
��'��xh5��������?1J������Ki���2JL����"M��F��b��%���5������;��������*h�2mp�}�{�������f�@�V�6m��G����/��i7��O�9�#����]����`J�>r��
h6�cd=�V�Y[�%��/�������>�E[Gwe%��E�E�����z{-G}^s'��}��>a�!mE�Mz�#���
h9��B����?��>�C[��Sc�������iq�Zc��}�O[�[W���������!�\�~�>����3������G~�+���z���A�+}c�<�Y�w�vm[U��m�����.j��2f8�H*���si7�d�@�������������2d0��zVQ9�t2�f��;�LN-��>���z�@Z�i*�#�<�B-K���Z05y��O����$=���}��.H[Qi+*I���|W=�L����}������Z��0)z����g������a�^��0�K������G�������h�8�Klc�M�Y���vm[U��q������u�i8���#=���j�>��v�:�rh1�Ck�jnC������R���Pd=�������yC��=/���>������p4��,j-�X�GV���S�x{}�^L�%�C��_���������>r��o����VT��j�6�'���s�b^)�7��C~��������	�[j�!?j+S����@
���C~��0i�5W�fm�#�H|�M��/�o	��o�o�Q��#gyS��K�����x�!�u�J�K��wi���>�J'�?�K�����x��Zz��}�"��=}jPY����\��>�`����!�O��������o�S����>cW�mE�M>c�G���.�8Q�!P_#wM�C���k��r���iA}�g��9}���Yz�#��t�Y��qY���K������G��&�dqx�C �x�}c�:d���q�i[U��e���������">��%r���N���������1V��������:�8�e�s���9ho��-/�+/���>����������HkY�����;����LK���<�~�vi+*m��X��'��\�$�LM�C���N/����y�.�u�����Q��2f�Mr��}�_{���KsUi���>������#�6���;��M��Q���nz5�:�{��������[���������z�I+j�5�:�k�����7�Mq-�F_(���#���R�a���SkL��G���q�3L��r�05V����0�w�][������W�%�F9��.���~��&�N�k��c�G~��8i����������G��W�)5vI�#~�Vf��T������#����<h�q�V�k�>���e��{����:���k����{����{w���������#[���,��N�2�0�0�=6��Uz�m��mUi���>�J���N)c�������R����s{j��T���7������n�>sff����	T���������5����P�TF{0�#��Nv�ef�Z�i-�#?���Y&e�q*��$�C��e��5��RmJ�M��Y��'<�e,m*mE���$mCm��
��4���ZZr$&�/0�`������f��.��2+��'�M��|���a`A��j�6���i=�������n�Vy��6g�0 ��
zJ���f�H��u ���y�6m�#���R��2��z�X}d���Q�
��.}�������6�p^'�b1��zZ���r�CV+�n'�n�V&��>�?B���U:��\���[�4����:����/���'�C��l���T��J�tb�G�i��M�T��j[QM���dp��2)�����������/h��'���Y����m������y�v'�G~6*zzA��j���������6)/�2�2'Ps�K������z�^��7h���f�ho�������i�PY�7���+���|
Y?����+Z-�h5�m6�!������6H���r�CV�l��2+�-s�]���:�`��J���"Me}d�N�EPA���LI�����^��=�`��rrh����U?_07�\����:���C7��a�R�!�u�
;GnZsUk���>���#��~����Q|8s���>2�����8nR����?�%G}d��x~#9�mUm��Y}���;���������>r��'c0rH1�Cz0%V9H'wL9���=&1YO��G���Y}��|B{��G~�T�!-�J�4�������bN��k�>�gm����T���>��!����K[Qi+*I���|o�)C�S����G��}CZ�V�K��X}�`���dh������v%����3���U�Yg��U[?A�K��S�]���x�S�������G^�M���h��`�U���#Z�,���h���jm�:�G���~.Cl�����DR��GV����]�`���7������z.�2�0��zZQY�7�V6N&��>�Z���Q��iYTZ�������=�,=�s
��eUK�����^�p���T���>r��~�`vA��j[QM��|G{���V��NM--Y���R)�^�V�P`�K�9t��)3���7���?�>�\�ubF���4k�PY��8�_��[�y=^��d���`n�i��Wy�v�:r���5�a�}#�:d�NFa��mUi���>�J���O)c�����Z�]IxW�.$[�"��5�}D�!m����2�0_�zVQY�7W?��c�S'����,����������H[Y��y����^&'O�z�>������K�)�5I/f}�G���������m����?1�8}jjiy����7yjAZ�;�}��:d�N�=���X��I;�#?;��-XsUk���>�~a�K 0���|&�Nc�I�GN����4(e�acL��G����\�V�6m�#���}KZ1���[�>rh��u��e�����>�h�? �� �xe����#dHPY��ldb���n-�T�G�Ox��D]�LK���m�w��]s��G�4^!���{[Q��G�sb{m����^�?pM�C~�s4��(s��9�7���6W�f������~]�n-����w�?7����%=i�����`�K�Y��o���V�6m�#��n���
�`�J�5d��[_���]��G��:.�A�� ����K�6v��%��^�g�pZ�����ubOh���"me}d�^��=H���"}�LI���:�Igy�4%�&�������_&iSm+�mE5ir�������
�`�I4�ac1Y��jo�V�u���yKR���l����Qobv��.��2�GV� ��d]��-��+��������'��K����5G}d��x2���[��i��>r�NDv�������������k[��`J�>�����k[PkL��G~�3�te�0%V9J��pfp��.-�R�G_��{�\����.�����u>�Y^�mE�Mz�#��V��!����.iy�Az��@Z9���X}�����[��\��pgV��G�����uu�����[{Z}�EW��9�S��^�p��GVm��>���#�..����C}d���)�H�KK���#�����\��^����U:}�#�.,A-�{.u������>�����>rh��N����,j-�X�G�>|�������`J�>d�NZY^jMI�I�0�#���P���������
Y���R��*�����������}	�#?��m�B+cM��pK��>�;1��\���e����������[rn�\�`naj����JW���:j��7�mS���9,��e^&/��xPY����� �"a 5�
L�!��~)��L�%�~������f��C����z�L��,��i�+�9F���CmYT[�����m����^��*���Uz�~���)�4If}� ����yU����!���:o8�CZ���}��:�G�/���0�`J�>�'-�!���xM07���i���uJ9�����w-�C�|a7���U�M��������4��yQ�Tb��Uz���b�����,���R6�g������r��<"�YE}d���*V�yA��������eQk���>r��/H�O�Q�q����j�>�������KSRi�������s�k[Qm+�I����X�`e�������!�9����U���+�CV��{(��R0%e�Jo>9��\���i����fL��E[�Z�U������#��K��}�(E�A
�
R��Ez��W��U�M�������_����-��G}
9hg��U�Z�Qk���nC~�EXA�p���J�:d�NYeRf[�\B{1�#k/�����[������HSY9|w��D+�
V0-y�Z���,/����$�����4����k[Qm+�I��U{����=
�/��f�C~vnW�V�Q`���9������"�`�R�!��n����Z��
���:{o��u�r�����+�G=�#�����H0�2�0�9�5G}���^E�����i��>r��|P�V��PI-G}�`��w�"��=������$���L7L���W���7�������(��V�a/���,�-�Z�GV������i�����8X��-//����$���oi��;Z[Qk+jI���u:�l��o�G5��<���e|�Z�?�b��������2�8���d���t���\U��eV9���-��:���l�4�`n
k��_^���2)�
�c���Y�7��si[U��e������pP�d�*���#���>�E�Ak��nC��{WL.�2�0o�z^QY����\����S(���������N'=�`-�Z�������3� fn��������9X���`jA��J�ta�G~�T�������m�j��v��/1�8yj*iy�Az�3�V�J`��������2+3�s'�J����?�1� �U�Y����*��}��E��v�q�������
��#o��o'��;/�@+c
�c���9X���a�. �`m�Z��
����5��>�`e�q���b��;���B���Z�,h�����6�[,��8 �L4����R�G>7����C�a����\�G�f��=]o��}��Z�i&�#��n���0�liUK��������7%�&�������k��������
9hG�[�������RSK�C��U�\[�G����Z�|G�7#�Yfe�q��=
���uv��m����8�G_Z���1��-BK�w8�9n�k������[���`�V�Y����Z���K�6��;�����#
F�HI���G�vu�uv�l�\'�J��p��o"�
9h=E�!��)cR��I��Y��������@����/��dHPY���j_U�eQi���>�J'��0����"��LI��,��;��4%�&�����77�wm+�mE5i�����)e�q��T���Uzw�D�V�L`�������K=��1N��7�>�ZgK~1�`�U�Y��������{��p��]�q�`��\�%��@����+����u�A;��T�r�k����;�`�������VP�
�_C��B$�.XA�#�;)���V����K�z��)�G�.XA	�#���"�.-�J�����E:��gh��������U;��E:����5�����C?�U?d���[��Zw�*���E?c����[�>��������k��)�co�v�G}d����9n��	T��<�#G��q�#�.����m�������#��^��n9�#G�tz��S�Lp���X}���c�����.�@�15V9hg/s��5�W��X}�`�-#��SMpk���>r�����Z��l�k�>b��n�MI�I:2�#���]��j[QM�F��k���EN`e��j
niy��;��fR@Z�?Sb��cS�G���r
/�N�n)����W�
��U�Yg������_I�S�J��]�q�Z�����v���{t�"��}��:d��\$��mUk���>rh��e�.A-���}
��G���u"�j���nC��G��e�K�����k�:d�.w)�K��!C���*�.�����D��HcYY��]�Z�n�N�[�>d�������T���>�Jg
yv��
��}��m�A{sF���'���!�vv[�9��'�
���C�6<���s���o	���������G��A��g|~��Z����7��d��U;�i�#:�mUk���>����D��nV��Y$�X}���n�l��^���V���;���c��8�c&����>�@7~���x�-�����v]�G�nN�C6eQE�6�>�����-���!�3�U-y�Z�-x���T����>�H���8dC��j[QM������1?��I��CSM�C�ts�U�����	��U{o�SJ1��LI����;azBi�*��2�G�:�]�H����%�2�s�Z�������*D�',���E��o�[��i�<`4A�V6m�#�vNf�&�	����!���#��/9�/�1�`Ep�j�;�nCm��(�0LV��S�GV�|Aq���xI&������<|����,*-�X�G�t�j&�gX��i����:������B��Ib}�`��Wb�����}��<�gme���n�z^QY���3D���LM�����,���B�4k�PY�8�gw�x7�S9S���-c�������Hx��s�G����f3�?�����k�,��<��&
�,���?�#G]�{R�
K*������N\���x#��c��������2C*'*�K�>r�N'2������HSQY�����
�"E�5vM�G�����0���
�)�5I�E}�h���}��M������m�O���;!�`5vK�#���A�A���������F,���Z�Z�>r���\�{_��`=G8c8��Z}�E^��6���^��0-cW���/lr���������B}���o�u�B'������<h���^.D�@h���nC�FN~ap�����I�S���*��������,�(h�E}d�N�����E�E����b�;}���������Y��
����$��������*��������m���s2s��6�NL�O�ZZrh���qm����`����Y����d�%K���u,����x���Y9S8��Z}�����Q���`t����kxc���Y�7rk[���u���Y'��0!�����������~3���x��/��G��!C���^��T�G�vR�L��"��S�3	����������,�-�\�GV��w�i4�K�����E{;xhMI�Iz2�#�u��G��������
Y�7g8�2g8�hjiy��z7w������v�C'��#o�b+����Yw�<��\���m���=w|5���v{:^J�t��`nk���������n�!��in�R�.�u�A;|�:�������i�P���K�3�����t&���#w��G�]"� 4�
h�!?�t]&e�a�����>���>��ded:�4Na���>��q��'�eQm�V�>�jo��@+�s�U-y�Z�=���T����>�Ho<��6����VT��!��N�#d`����LSK�C�[�g��W�V�M`�y�9|��e�v'�i���}����s�+HsUi���>��Q�Qe��3�8a:���Z}��dV @�a�b�[��!w�[O>���*l�*�G�V�_�dHaA��KI=V9|����T�"� 5��f�!?:�*�2�0G�zJQY��|����%������{>��,*-�X�G�����e�q���&�CV��i�������T���>�
i��E����Z[QK����z����3N��JZ�J�>:����	����!���-�e�q���	��U��7Zk��k�j��8�G�������%k�,EP�q������s7&�.E�����>�h��Z��� 9t%�����>rl��w\�l��\s�G~�ez�r����>r��{gR�Y��%G}�(��<�[���"M����:��6K��h��:K�������ZSRk�Nl���uz����P{p�I��O����oy)��Q�d�y��\������/���g�����~�+����-X�>�r^��j	r�������Z�|^<��������A}�Nw�7�X��<���j�>�����I������o.�
����a�t�1i�zQY?�[�Q��:/����>�J����Y���"Me}d��|���y���%�CV����:kJjM�iYY��_g���V���Z�6�`��K��tL"\���!����#���jw�n�u��N,#
���;�i)���zs�N��j�6�����������]|q�Z���~[}��U���	�$������!w�;!F][U��U��|�}�/�8�u\��r_C����Xd,�B�������<h���i.dp�.@}dm���
�\���KPY�w������HSYY���V��p�Y�>d����t�������>�Z�=��Y[Qk+jI���z���2�d]������'<K�U{sK�Up�#?;��%,�������CV���6W�fm�#���[j�w��5�=��o����������#[����T&e�abb���!��[����?md�Y����MC}�����@��ik�%�X}�o��~��~����������
��^��dj�����X�s���w}�����9�v\�G��qO�x\�Yui#�#u��C��2+��3�U-y���2��LI�I:-�#�s��P�T��J[QI�����F�M���������Zzg��NZ�#�}G�:d�N�]dT��Q����$�GV���:i�*��6�G~�0�)Y����5nMk�����;{9%�:����!���2u���jm�6�GV�����2�di�Nc��E;}2�sJ�v����#�6����d/�Lwp�#���m��,���C������K�w��E�����W�6P���=�d}����!w�p7��
��T����>��~�am+�mE5i�j�7����b�v������������*L+X�v�o�[���fZa5���05er�����������C}�������,����1�q���7�=�#����N"� 4v�Q����mUk�fY}�`��$D8A�0���5G}����L�p������������:�E�2:c�y��u��s��)W�S"��V������eQo���>�E��5P ��0�?��k��g ~hMI�Iz&�#�l�����������8JG����V���niy��:��n������j�����:���H+h�]S��jl�HjsUm��Y}����n�����F�{�V��}f�>���[��E�cTa*b����!w�[!�,����m�*�G�r�2�t�(�|��y������yg�~����oh�
����������<+��D}��]�ydo�370�(�C}���u�u�&d�p�!�����,�x�hy�6%�&�<�������/C|�T��j[QM��Z;���AaV	' M--Y�)��`�	H��$�o([��zsVD-s���O����fL���Z�6���~m<!^�%Q6�>���V�����+a (�� �4�����C��J�L
x�����C}��/���`zp���OZ}dm�_��]�t�����%�
94�{�a<����)N�3������C�	����vT�G>G��y
ueQ]���>�e��7��c\q�����������e���Z�tV�G��>��V���Z�6��u^�2�8�hjiy���m��82-s�=������2`�U�Y-���}������E\��F�V9�^��~^�B�.��}��:�N�-�F1Bm[U��]����gN�e�pJ�Tc�����s��C�@g���nC�.�[��	�	H�s���_��p�D��a�����]���Z���{^�[�i-�#o��1�,��3�s�Uy���a]J�K�]YY��=����z�������m��}u�g\<A+����������{�CP�0�t@�(�#���&�
HsUiV	�#F����^�^�g�p6p0�����U^W����LB|��N&	.��}_�:du��cT��V�6m�#w��eH��!��AR��G
������i��oW�
Y���n<4��P��$�iE}�']��aoo3R8U�������^Z������HCY�k���8�'�-������}�K�21 LI�I�.�#�>�/_<m��VT��J�6d�N��aZ��i�YBSI�CV���7^�{\`����P�oN[��v�����m����A}d��}2������N>�r���>2�o?@!3EWYp�Q9
�n�AVT�M�`������ K*���G}��61	d��Nq0���G��=���p-�B�O���#���j!����(�����������������,�-�V�G��\��@�Op��[�>�`��{�P��:k�����:].mjmE���%m#���X�4��<�`�#�V�M���6[G��Y
~��Y�+E���#�����H���Y[f��/�7��D��?��s������G~���7WZu-�
3c���9h'��2�`m�Z�6���:}�1eV�g#I-V�k[��)�^d�����6����9e
��<YO#�#k��.BG�g�.�@�#��>���he�pJ �����z9���3%u&�<������!m*mE���$mCV���oMO+#�s�����<o�y��V�K`�u�Y��� +(��+�))���'�����qi�*��2�G��������?F�r8����j���;K9���p/3E�rp��G���[���o�k��������w�V�������>������4�%�A}���{�2��]���G�l�YF�.��?C���E�|(�0Wr�&Qn-�Z�4����������X���`j�>d��V�cf��nM��YY���qo+�mE=ir��nQ1�taj���mr��'��3�ta�V�Q���������;�
���C~�V������mC}�o#q��n��V�-9�9g9���Z}d����R��L5��}��:d�N�:`xA�V�6m�#o����_�e�q���c���w���Z������6�����0s2�0y�zfQ�s^=C��:tl������>�4��WK���������H#Y����g�)d�q��� �C�nV��EJ�H�GYY;�x��������m�����c:�����QSK�C�ix3����q���m�z�'�L's2�8A����������KsUi���>��~���^�gxqr���;���Q�-
�[�����>r/��O%8���������9�R0���2�S����>r�l�s������V9~���8�@feBa
��Z}�`�;�b���tV0=V9xG�����.-�J�4���tz[�	�,�i������{���1�`MI�I�,�#����\��J[QI�F���C���\������OrOp����j�����:���hwb�q.����#��xr����5W�fm��G��.H�I���-3m�T�8��S�2-0�o��h��/�����#���),�(l�
�6��{C��Z*A�T���{��F<h���������w��F�xk�v�"� E�q#���8Ho��4-�m�$H;.�-p�^_�"��,�:�4��8����L'h�n�"������7�{k��#�)�4I�e����=�'j[Qm+�I������
V��b���{��c��L��t����n���Vy��r*�E]
���l�@x9����*l�"�G>�=��t��B�o$�r'���F!�0���"�
y����r���C��������<���"�-�
�GVk��Wa�������HcY��	��Q��1����z�>����C�>�B��j��_�GV�l����������
Y�7���X���l�Zo�$so���d���{��J1��LI������#���z�6����������o	���������G��{�"yZ��i��ic�U����y��}mU_�V�>��w�,8�3^�'X}����Cs�E��k��nC���.�2�0s�zBQY��	1s��z��^�.�#)�&��6��S�����HKY��'<���S��L5^�������4v8a���4%�&���������iSi+*mE%i�J�>�@-C��`�R6Y���bui���-e��U:�UW�/1��
���C�[�O5�4W�fm�#�4��&i�|�V�v=�8M:��>r������qeV��.��X}d��X$�m[U��q�����s#�.�2�8eJj���j��gy'E�Aj���nC�������-��hG�F�y����oC-�9m��S0w�M���;����W�����S0-�k�j��e���zV���>�h��������Q��o:D4^k~8q���>2�o�����t����%G}d��v��/<�mUk��Y}d���;��[��X9 ��3������cK��x?����#��b����2G�z|a����>���@/^�jw������������K'���������#���]�G�ol�����r\������#�n<ZY�~�!�zf�)�����G���Wi�����:�-$�y�������H�oQ����_}�8����!�����U1_���<���E�3����[�"�zDl��:����T1�m�������>0�q��V���u�3���VY����?[���sjK���UH���L���j��������b�v��qk���������|>d�����Cxp��}_�������y����i���mCg���.��MvI�Q�.����T�Ci>����[�[�I:1���hW��>�z��W������C�.��V�*�#��c�|�/J7$�GBZ���!A}d�J� ����f/2�II_P:����u�k����,�7����$���I��E[���c�J,��=���/)��b�1������Z>C��{�cpXd��Z�V�u���,����o��Z���h�M����>�:gW����V=�`XPY��A>��#����T�Q|Li�}'����#yw���,�bN+����CVk��O'}X�Yhm�Z��
���u�l������IR��G���=�����Q�qR����j�/���}�q^�oB������KI�,G���Y�G~�����:N���X�GVk�s��m��C[����A}d�����>5���{n��Q�p�����>:���>�Z�J|�=������k�6��#���~3�����	�a�V����[���j�{3���yzZ�>�ZS��tr3�^��E;��G�������zj�����A�k��^H����g��[���G�x�k��a�zf�i����+{�f��#_����W)Mc^���W���w_Z�UYf���!�������n��o��M����8��,��wBh��V��q��,����~:g�Jw=�`�s`��E��/U�q�c=�G.����da��iE}d��q\A�~"�}q\[����A}d���1��������7}�����j��!o�@�$`�'��G��b����z�N���|Y����#������f��}���*�GV�1m�|_?��+��[���������W�GV������K�a�z>���������@��wJ7���n�G����/��r~����F}�����j�6d�~�r�}�����������,����������)z+�:�Q�Gi����v��v���NO,�#�ux���1���V=�`HP����O������������s�����w�������������g?�+mv�t������z �����?=��4-[�O�?�K������e��?=����������������c�?�An�1��� ����Oy�[������9Y>�ogc9���>��_?y�,R��I`9���f6��8��>�?������_~������O�����O�_�������O/���|�W����s]�������������_�����O}�k�~����������/��w��������'?������O����N��O�������n��O����������vy��������������g�O��?���?�Zj��J��}���9�����^?�}����/����P^!��������}'�U������H��~�m��������w�qmi�����+U<�6x�*������2,@�Z��f�����������n`_���3f�����S~����/�=@�������gN������^1��e�����u�����:�����-���x9_���M�J����8^������4~V���M��C�������������~��6���p����q�}�rO��������.�&��5�o{��� ��k��r?��\���N����3U����B��=��{����{��l�=�����5��{�^�^(�=B��z{u�]��{��0�y�����Q��{_K�����Y�w4i��~����{E��qO�=@��{����{�^��ys�i��yp�������S��a��{8�������+��v��v��~
�v�b{��=�x��r��v�;���y��=������+���v�:�������������EiZ�����p��=���wy��z.�����.����knn�����m_��=/ia�=��������g��~���
{�"8���=�����|�v)>����ZI{��S���]����.c��|_
�6��0��f���K}����:��|�
{>o|c����������!�|�5(>k|������/�����=�]{>Do���=���}���Rf��z{�6���X�?��|_)����C��6����n��|�Z{�=�����{��a�W���k���z�'����������a��w�i��rJ�&������s��!��&<�|���?�N{>��}���3�w��!���b��o����i�7�|��������?���Q�������C/������o����?�������N�����������_��n����M_/�O�o������lo����ns��yx�m�x/�����~���.�~��Y��}
a
^�%�����������pz�Y0���N�x���������}/�lN�w����`@�um����k��l��������J����c�_7n��"L_B�D�?}|��L�?
���O/��a�A�����sz�L�1�|\^$���;\��d�[n����5����msG�t�����M&�~1��x�������Mv|�Lg�?9|����w�j��s4��u�)�������[[\��w�>�UT���%d����0�m�~ ��kM|	#���m��D|/�����U��;��]g��i��~?X
�s�6�uv�_������y��8^��~����!��<�IQS�p����;	���
�����	!�s&�B5	��!��2� ��?�
�k,�����!��r��VJHBp���5����������������%�[(���s��=��7�%9��M������,��*��%9@���Kr��#9��_��Kr��+���"�����ab}����9��z!�w&9���&lt�Gr�5����t�h�	?g?����%�9���$��s���'9���$��@�qR�s��!��y�������}�n�e0o�v�D���e�$��Ix�;����y��r�9���(��(���G�#������	����&9@O�m���$9��ny+�hNc���R����6m��'!����C�)d��&�,
ps����G`]�TE2m~'!���o��{����"|�<B�.!��	2�@�F(��BW�Bx�g!���&�LBw
Bw���h����C����y�$���B�m1B�]�����{��{?X!`�^�&pC���?3o!��tv��7��U+T��r�
\�
\�
��9��=V�B�d,t�MVC��O���J@��Ew/�oNc���r�$Y��:�4���@���A����0�����
`�
�T�E2���d��
�Q���w�����	�������`�Ox�Lg�(�&������
��^(#OV'�����e?g8*o�J�iw�	+\G�L�x�
x�V��.��@n�=�r
e���?7�(6����!�r��a��������y�V�t�w�j�j����HV���V���V�+`���V�[��X���{��^(����F�:��.���s�h0�s��=YLr�BO�l�����&�l����(�cIV��V�H��(��^+���Q+`��{jx��pHV�Jg�l0 3���a2}�De���B'�lp2E+������~�s����9�n1p��x���U6s�
 �P+�\C�@�	��r
�����z��
 �_����
x�V�:������7��(��d�����%Wmb�L�j�rC5\Y5\��!q-M	lib��������� �j���I5z.u���mO�HR
����Q5 |{�c6��T���r�_R
8����Y5	Dnb���Y5`���K�j(����d���"��}
�9��1^Z
0�}��U������>~���������s����x�W����u���n��{�`7���j����u�V�f�8���V��T��#6X��;�O��e�[�&����w�?V�����{��~�G�f��p=�������/�u0s��yks�:X��p����|&�b:���;���������!��9�l)C �������m��!���JG�p�^�����,����x�����`�t�j�����0,�o�Kn�
>�7P�e7P%S�
T�T>�@`Kg��[�?��K�����Y=��g2����|���pr;C^�3O;C��o��[�������<�N�o��^�����WW�P�!
���$
���6dn����(`�^��o�N�z+�x'Q��^��he������M������!
���U�t��XqeQPpeQPpeQ\�(�G�#
l�b�1�8�z�\��D���@�b�Y(U�I��{�����J��,
p2���$
�	/�3x�<zDA�EA�LuQP$S]�#
0{�+p��*�$
����-��_Z���C<�����S"��J�Y��)=�(@�Z8w��:��u����o�O3a�G�+p����+��>w���e^n��&a�o|-�]x��s����]�qa���0��!u9������j
�j)/(�j���+[��+[�5�5���c
��c�H���[���J��^?�XEk�Y������������{��v���{�a2���� ��3�A��]���A�&�l����i�xP�u�P$V� �U7��$�R��� �����"|���%�����am0��S��dp���9vO
�F#�
�OKD�����oM����?81��
U!����Y���,�r�,@�A Wo~`o��x/�y3�3��g�-d��
-��/�������Y���,(��,(��,�G�#������G�C'�@H��k�.>����@�S��])�H����� ��\
'�� �&�,
�|}�7�fAP�uAP$S]�T�S@`� ���(1�{>�����6������� 0�+��C��g�%������wA��I�!0*o���N�p7:�[&E\GD�xC�x�J#r��1$E�\�.E�r
��<��p����=��yE����s��y>~�G��
����kpy}6��DV;$"�a
�\���^^�A��H\K�D[:$��!�������`!��M9OX:$r@��)��op�<���C4G��N�t�g2�D���<|=���4��"����H�ziB�L����&`��7�d��Q���lm:��D�.+�y������$���7uHd�Z�{��F�q[#�-�	��okdn�����8�w��^���w@��!����������mw��`�e8omnxo�;x�����8]��<)�b:���;����V%T\�
��9�l�J ��*����c�'~�B��d7@hS��B�=�q��NG����'��V��'��]]��'���|��7�&O�M��x�j�Ub�=A�X�
[<gC���R�����	��
���@��6��'�>��$OP%m����&b���%`n���a	x���U~�<^�="s����m��,s��O�����0�_E����F7��g�m������;Y/w��O�'�j	�i�^nX��+[����] ���c	�����%�otX@�����%���B��bX��="/������j2�(�	��d��.T	D7�L���5�f3P�u3P$S��T�  ��������`�=f�?�=
�����x"�x7��Jh���.��R����J���:����nF�_��0�w28�vE�o�>�r��a��oAp�Wom�\��y�a�k0^n��E���f��M�
N_{z}�z�=���(��(���Ys�{��=z���c��	�v�@�����0 ��4�\x������!��7�|�8����U���5�f=P��X�E2��@�L��{�fG���r���?O������d����N��Nz�L�>I �^����=�����e���Oz�z�C�
��@�A ������k��5��xC��{��A�{�}�$��w��p�=p>��U�|HT���W�W�W����{��������cO�>t�i������z��Mc������{W_�������I�d.�=r������<|=�X�E2��@�Lu=P$S]`�0��/�_zI���_�Y�s5�3�]���_)$=�������-��|^w�����w��6\��{�	"s
��k(&�p�"lr�v#lr��M��[�\�-@����7a��
[`����f������kz8�v���|��>m<Z������~��b������x� ��V���3w�W�Wm�@\��~h
\��o��^��Bk��yi���}��}���w&�A��	?�%���D�#����5z%��N�����-��o��+",�W��M}Ip���'�R����IpTi���BpT��.�Q��f�B�*�6�VCpT���x��.��Q��i��������Q:N~|�h��/����e�In��.����\�Z�Bs�����W$�Vh��0��������s�k��0���+V��j4x�z�s���~��q0o
�<����F��&Gp�x�g�#��x��
��
�Z�@\a3��=��G�u�;J���m�����)�O�������b������7�Ax�_(��� |�����.{3x�4Z
8������7�&/P�������=^�+�:!�@�x���i��7���@�v�8L�+a=g/��Pw�*�7b���,�,��i�Z�O�GqG�daR�m��>�e$f�9]�?����r���]��>WCC�8�v|C ��y:��=�M�m���t���3U����/7t@��u@��up=%^_���?'�u�=:��B�����2�����HKw-L{A���"��@�B��t�7���I�Cn����YXi�X/����
�^&P�h]����������p�s�������V)nH:�x#
M)�@��o&�"pL���@�A ���}��V���}����nK�P�j�U���T��{��
����0��o����`�,��m+�PVn��p����W������W�W����{|�=�^�K���'�������|C%7��D��16��^+��&7���Q�*��/�~��
 |�4Mn����0��O��A��@�V�������(��������7P<�7����{�a�������a*���nc�p�v�
`�g�s����B)Z*(��~�"G�`���T��
;��p���� �P(�\C��u��0s';`�^�f97�����@n�\F��v��d;p}B�BN�@��/7�@���@��������=v�;`O��]���)�'#�+��C�F#���#��~S:k&#�����_6_+wd$#`Mw������S-P�u#�M��`��@�����<��T-p���}��o���I�����Y�\�}|�t����B��,��� 5�@�JH$�c�����tL|t(^hz�D���1������\A	C%F�p����
��M��;�p�m��+����|��Mp�
��
W�\C��z�<]��yw�^vg�w|�l��+=�+W�p�L��0s'QqUQq���}�@�� ����b^��!�O���<Q���m�������A����1d�WR��m&���n.�P���^BE0|%��J*�����p�����8��S�����|�C�T��,G#^�k�CETI�{	�T��1���?0z���H���/i�X��H�^��8����E>����M8������I� ��4������?h��
f�����I6W��a�
��7<�C��u�
��es�W?|���0���d�9��l0�w�
��xR�e���U%L��rC	\Y	\�&����NJ���	,Tr'%`�.�I	<������p*�� )@�N,z�|�E}�MHI
 |!�)�R�k��=Ik��R�>�)P�u)P�U]
iU��H|�
�:V�w��=I�����FY�^��m�0L�+�0D��n��LRc=SL�_*�7!0&������o9 �P+R���
�@n�R �r��
^n����md������0s/��X�������p�[;!��I
|�����E
x�!
�,
�,����He�I
����%)��3R�R�S0I@���$�VNq$)�yn��R�w) Z`�Z�)���5�e)`�L���
�K�"��R�H����$����
�Q�=R�x���!B
�_�8�a��Mm}��ILR�[�Q`���p�0K��O*4�����M~�&T��O���y����S[��@�Ax��������-P<����7��Woq�]�I �];Z�;���v�@41�\W�a�
����pWvWv8k7`���
x�'7�~v+����	��=~��n�������&��f7���On��"�k��n�>�������"��n�H��(����o�%7P<��
����p��RKB��ILn�.7��v�"@�R0��
`L��'7P��~)��p�c(�H��C��x�
 �}�#�r�������n���0s/�'�P2`]��
 W�	��~�����68$��
x��
��
����q��{��=uO�?r�O��0>��~v�^+K0����[�n��&�����g7`M}�
����O��n��n�H��(�������|���~��NV}���L��Y`V�����z�z�@o�ZY`�gJk��	�R�$�&���$�(�^�3���5s�mD����M�����5��Z�CX�*
�k���&kP<��5@�������:�����f�>���5�r�w�������w���w�����b�Cf��M��(���(���(���@���!���hv�`G�C���!#��z�M2�s�z��"m�sQ�Mqb��(��[���$#
����9���0���%X-T(���(��*#���v6(�����L��]�����;,���E*��G}|�J�j���@�V��r2E�g���D_J'$~D����?�
������B�rE��\Co�x��������
�8�
����C������d�P���&���>�C���������T-LC�B��mV�(��(���93�( �kS�^�uNZ���7B�O�?q~���m��"i@��@�#5i@����Y`@��b��~�Q���=5
e*���5Wg-`M�Y`]iU�EZ���=Zp������������P�R�-��4<D�Vi���z��;i�"K���I�~��{���a��oA(�����k��m�M�@n[����[��8$)���A
X�Y��u����R�+�!��R���&)p��'�*�i�W�W�W��)`��{�-_�x�����Tn�/����nLR�k�\%I���r<K�/���$�V��LR��R�0��O�G
X�j�EZ��@�V��v\(pG�@�x�M
���=�$0�����T�R�%$)��P����z&�^���� �kv?����Y�NDnjP�b�~�Ix��0r���k��5hk�@���������n�������� ����^��������G
���n�7���(��(�r����
���hj��m��zrO�g707��J��\h���=
���	��f7���r�>������
XS_vf���������"��n�H��(����w����v����kw�KnS���8L�w7�-�7��F�R%������~���s�N7P�^d7d��Y4�o���p�m��7�\��r�0sO�����1��u�%7`�e0o�s8o}�p�3�n��w��F����jq^n���+���+��z��=n����^rJ��x����JO�|��F�
z-|�d7��4<,��_Yv�<���n����0��O���a	��@�Vu7P�U�
����77P<��;�
��~B�J���@��v�7�������
`�gJ��@�R(�:|~������&t#�Z�o1Y�����*��tr
������
�-��
��!�3�s��.����T��{���
U`}�������������_����~���������_������_���G>�9�t��������_��n������gO~\����G��|qB��o!N*n/�!N��/qRq�� �	����I�X���p����g��o�r^!�)u�1
B�p�����������	��ImK�F�oo��f�C������N���V�<��_Sk�<��ra�7c'y�M�I�T�������+��|��2{h}'}�h�&��'<�K�>�H���\_��tz]�2L���]z{*C����SR(<�o��$�1[j�xqucB\G?3w2&f�dL��7idn�o�a8�~���p=��o��C��{2&n�����dL��������0��w&=p
���C��l�$=�~���;�k��(��p����s�^�Mz����4m4q�)���p���a��	~�OJ#���;+��J8'��@��9+|�]�@�FvI	���N�(r��
�\OQ�u%P����KJ�����J�����/�HJ�%��Q�~����W�F8o1L����(C�F~�BuSV8�o�>$)|9�r����@�~����U������?o����_�0\�y��%%`���0�z/���������P��0)���3UU��_P��p�?@%%��]MI	\Y	����J����Y	�*�(\j�r��p�	���	�(�t����0�J?��0�s��wV� �������
<)�"��UE.mj���I:+��,gJJ�H������������ $+D{�N��
��F���W���>L��?I�{!��h���������h��J@��3���G���������%���@�~���J���Z(�x�����)�����*�s�����rC	X�����
%`�����a��z��p-^�/Ppe/\O��=�*����&��'/��M�	O^'PP�z�X��8YH�*�F�-]���>���L^��B��/��W�T�E.�K�I:{��{�"M�^��������)���)@��_��N��`�W�Q_�S���"�����������p2������/]� ������m�P/��GC�����0\/�ox�zH^�:o�x����/A8����X����aw��D/@T� ��pt/Pq{/�������R/@`K�/5K��6��@A���H+�a��r�WJwx���F��?����{x�o�;
�T�����T�T�X>BP�e/P�i�TyZ��x^n/�h��{x�@��"�Gz���E:5!���O�����TzU���|ruxbo���&/�/�>�����~�����#�`�~�����q�<^����������^���M^��=��Q/��~���������q����w��pq�v��t�3$���a�m�W�����;�����v'�`����
^�^�v����v�k��!���}8�BM~u���$��%�Y<�~�N��k�=�<����t&�`M�Y<�OX.H��r��*�����m8�@`�A^n��h��<�������#�W������#�����~�5z�|3�w����� �����d�����6.��V�~q$��1Y�����B������m��o��r����7Yk|����7,�y������a!�q�oX+wr��S�T]1�	�u�6����}r��&�S�`Oa�-x�Y,������	~�N~#��n+���B�%-����c�@��k �|����k�E*��@��t?P���k��~�H�zaB��u?`��G1��G�����+ ��>�j�d0��������v`{�O���K��H���6� |#���*p����'7\GG��7E2W?��\���n���8$7��m��n��n�n��p������n��=�M?�����
\7�OT�
�q�q-��k9�Ppe7\���
x��vJn���-���6�g��p�����H���P�
`���O��
`��-���U�&Hn�����!��"��n����(��(�z�@��u7P�i���=�p�yj�	d;�(�|��FZ)K�������v�|�g;��\�>�v�H����a�m���vT �p~�����8^�@����u��X����w�a�k8�`����[������7�����������;d��|����ZA��A�m���"�G�����G�jSn]E��R�������P���6�"�h�
��"@�VY�I��x������{�JuEP�R]`]`�|�H��"�����Q��<��E��?!�F��������?��a:}�y4����'���~��wjT��6�]�^�������_�H�m?�p�/��%C_�x���[������7��7��q/�ox+7y�����<��Q:@\G�@�U�pt�{�k) ���R:�K�r��W��&/�(|H��H��G8�p���q�� T�*��0|{K3���)_)�$��7�&/P�<�~�
,{o�N^�J�����������f���}9��@��>��L-�������#2|}�wW:|�F>��0)�&`��t�)>�����������Cxx��}������8y��^��
/�����A��i���C�7\���{7��g�m�^��~������:rx�-o-m���DV;���������n(�j�C�::V��gY�
^�w�I7���:u<|?w<\�y�%�I=�dZ:r�;��>�s�g���h�f$����R��N�\)J���V�z(��\�P����X>�P�V��a�Z���50t<��&T�'����q��p��z�H;:�~����PO-T�jX����r~[���@�F�'a!������������@������~�fnX/7,r�������7Y��m�~��q��CX/7,��{�[��j���u/���PM1
��8�Pq��+7��z
�)L��0���"F�=��z�8�Bk�d0�Bo�d0��LA�a�h{
�U,X���,���a�J��!�@�����������@�(��nl9����r`�����<�����F����x"�}�(��n$;��\�T8��o�v����5�( W?�@�����W�i����!��P�`o�^n�o�X�C��8���7��w�a��6�������`Z�-�b��hgPq�c����/U�v�B�dp�y�-�j���@����pKe�k���"��k�����|h����~l�{�`�*���E.�k
�~l��v�H����"O�v�;���c���	���t�%��-����8Y	���3�'q.���n*��_VJ�6��O�P��"LJ7	%�o(�xC	�x�6�n�i�����?����7���{��E	X���\���P�2���k���x��+{�����������<^W��&�@K�C��J@�Fc��re/PD[8�����JuI������3��T�E.��
��
����H��(�����/�������	����^#�tJx�N�^��k�0�>��|9"?��6���'/P������{+���r��a�����r������^��.A/`�&/`����R*��5�
���?3o���
/�ox�x������^��/@\��(�^�����R/@`� ��4/5�i^m��Sx�@�
��M?��8�^������U����S����R���\*{�
,{�
,{�*M�^���� ���!/7K�CF[�x�}�^�#��$/P���uF�T���9�'q���^���6���/@��P����u!`�~-"s�������y��`n�:��x�^������p=��"��0ys&/`�������w���p:�v�����y���~�w���C�_x�W���Q���<��6	�:'V\�q"q��l�������I�����I`x��\:�������/p
������&��O�W���5�q���]��9�o����M���H�� ��������(��./�|'v����(��a�*���*p�k=��"G7?���x�JuuQl\���q����\V�J�B#�a*U����p����&Y[��������������_��}�z���I\`��'q�\��q��U'���0B\ �+�����[^n�\����^�&�7�r�"C\x����I|~<�IU��qK*��+���%$�����q n�QqV�tF���3���M��4�\�����p�'�
���(�@�o����*c�&l��
@�B��K*���%P�Q]yTW��U@�U@�J�:k��*�H��
�\P�{n��|����0Y|Z<V�����8��+��%Y@o���
`�gJ�H�E��7�M��]�7)��r��0LN���x''��m��p��N���cN���&'�����p��V��p=�o5�����%'���0s��y��JN��ON���LU�0-N�'\����+�o���CNN�'`Oy-���Mr������p�8�	�������������0�w'���1����Gpr�(�7�(����<��m(�zy@��@�Ju'P���o��	`�	����'��}v���e���HN���J|1.����U�Jr���{#9�A�V"�v����o�09���Y�"���"2�P'����HN���p=������`qf�e��r
u�m��pVnn|p���WU �����������+��z��=�����5�97���&�\1�������}�����t�9z��x��'u��I ���L�EJ�%A�S����K��K�"�����g�|�K�"���">$��'��@dI�KD���$���/��0���
�$	��jB`f���L3$I |)$�$	0&���I�R8�\�;"?�I��m�7$�w�B � 	��M��C����`=(E����`�^nHo|C W�5�;�$	�7���<�;"Q���I�Q�%A���7$q-�������_�!	l�����'I^�B����2����i���N<$�3���?���$�I](�J�$`��s��J��($A�S�J�
,K�
,wI��j3!	*�,	�|�lQ��J�j%��'�U�ys�.�wz�]�$�$���!	�U�Bpf�)�a�$`�R���$�p���u�Jd��*���~����>0I��*���$`n��i������$���;\���8���)�I0�-5&I��~���������M�m~	=�-WmkHLG[C��w��<\��!q-��������I6��������{@���F^p���{���qt3�I\��1N.T��vt3`�B�M1���o�����H�rQB�����
���,%T�T.J�7v�R��h��m��Q���a�ox�>���W������r�0J�����aVU.{���[�n ���\j�7 |%�n����F�����_���~���8����8dn���q��7��u��8�v��E���_���~��`^�8x���;�0���.x�;y���s�T�1
��k�H��"�����k������mRE��^��
���8�e�/��VWF��l�V��|��/g"�����-�����$
�Q�'M�����{!C�UXn{X�uQPdm��*m������((�v���o���%Q����/�@���OY���#
���P��D�W��Q��k\�������������^0sC`�	��4���	����M��B?�`�Ch/74��{���*o���C�w�TU���W���h�Z4A��5p=��7�L������������g;K\��R\��'Z�8�o�	�������l�1��S�&����'u���I��[��D���mA�au[P�������"y�eE��m�����$;�~o��������]M�/(�~���(}���\�/����������g^�/�X�����/@�twD���� ������k8���v�/���-y���'|�5�X�C������`=(]>�������f�y�2X�-u;���)	����z��:�q�'V\��D�
���4 ��������!
���]g����b)I^���y�(G�
-O��������|����'u��i������4�&�$
�+K�
,K�
,�>���,
����8�Fl9�@`��R�����2��e��Be��d�8����q��|
��2�^��eP�V��
�2�b�*��O<�q�(���2�
�^b`����P��{0W�E����
����p/����N&e`����Ip�7+&ep8�+Om�HT�2�Ex��Qu�����l�3x?�:�
�W������������!)�P��DR/�����pRJO������2(�\gPeB�]b��A��A��uePdo]��,���2���mh��K�r�/��`#�v�������p�x�fi��{P������WB�N�W�����}ipM����,�+&md�6�rC W�|���������b���4�^��
|��r��2|�
����
�qm`�~o����-�>��jZ��jM��6M$���q�W�%Qp��.�88�&V��<��� e`�i�d#������F��~�N6���?�\'B;�d#pB���h���~�g���
��?�@ |-4����T��(��^�P����|�
D�XuQ$V��o����@��@�wvWg�OK�mN6�H�]b�����w��E��*Wp$����K=w���J�G%��11- ��oa*Z�g��d����m�������	�`o��Y�ou�u�������/s���fn�����y8o���}�r'C�����UC@LG�p-�
��a�p-�
���+�S�`�}b�'��J6\��������+�:y�V&C������
/�t��$[���Tn�L���#�����+wQ�2�n
�n
�n�����"{7�M������}~'}�(� �\$_��D�q�cWR�����*(���\��1|�W���`L�u�/����G��z_~��}x��j�����0zE��<z�o��8�/�r�x�������d_p��=�V��t\�@\�/���b��}p=��_@�L���������%�.cO\�&���s�3�� �;[$C���TZK&C����'"�"���EN�
A�
A�
A��uCP�k������~u���H�r=��'����~)U��H�
d��J��"�����2���\jm~�k�$F�������r
~��=�m{��^n�/7�np��!�|��u
��z0���}������8�3�<����?�����	����A�����zQq�����uH���J�Z$�-���R������Z�4����	x!����	xm���x�&�I�7	K����z%���5�������Bh�*�������&��r��
,k�*a�����r�_��	�����I�h~Z,�x�Xz%�l
'���A�����$
>s%QP�Qo�*
x�����*=>Ds�B~���<^]0Wo{�\�[�w=�(`�.
�����s��B~�����N�����=��v�T�������-���j�:�	8
QPpeQ\�(�GX:}0�\j���%��m�D.d�-]�6�=	}M���?�u�������i��pn��jg� |#��g_P�V��U�X�Xn�X�����/(��li�H`GY��'�W��L��D�7�f_��D�3�8L��F��>���� |��
�|���Y�W�~���=zas����0��7� ��p����_�\�/���?���G�D7�2|�������!�o�x����B?�O����o�����������_�O�q�=��nw���.�����������s�3��&kL��bX��w������|�����\������;��
�`;v�G�&��M�����Do��*��
>)K�U����g������e�_�s������<�+�i�_������k_�F���AA��`F�L2(E�m>�����[#���M�����&���<���P�������*���G��H��a�^�18F�{v������8wK��[�!\9�u8����n��c�^g��
G�E����R��E�������S�1��S>������w���o����:�����1�]�r��z�����B1Tey+���� �`Y���lY��?2Y/7,r�+-Y/7,r������5O����iQ��t%�����|��>�)�B
I�	��P�>��/-�'z�\v�|�z%t��>��T�m�O�e=.X�>���y�����p��F�	_)^$�����[m�	\�M>�H�r+Hov�>�H��F�Q6��qI>����0�@/�*������0����O�h��:������O@��' |+`e�P���#�'���'��P���|�?�������J
�����*5����rr	���9j5p�mG��m����@n��.,r�We�+Bi�8Y���J0������E��7,p�f�a���"\v�QP-0��d���M��
c�V~6�c,\��,���k�E�Vi!�,�z�j$���^*
&���z�T�'�����m.��1����m���%�P��>Er����5[�"�6�d���[�2���v^��f�~��^g:,�z���E�h�+]�E@�J(����[l��8L��o�ns�az�E(�}w�-BjX��>A�M����:L���J�I�����=� ��a�(A(�z��j�*��"_���>���#�r����:@n_I\�fQ�8�:�p�(�r
m!�����K�D�<N����*��7�q����|�a�p�p��+��TN��J �V��*�X���P���R�q<T���pIwR	_*�JB%0|���*���g�J�����J`�Fiw*��g�J�&���L+p�G^��bR	uz�U�W�J��*���J�X/���J�h��<�T�M*��w����=�����O.H����j�J��n�bxLmp�e��t�<���>��=$�;F<�BEn���8S���T��\�����2����2������L`�^��\�������Lps��ys�o|�L8 �=&��8�@�E�U�dp-�V��� `��
��A�R��/@o�_n�A�X��Vk� `�W�o�� �Cx��Kn�����u2��\����JuI2\����7��d��*i����d�����d���E�A(�k3� `z��K�k_\e���^*d&����	
}�A@�Z	K2�:.�8��� 4G�1L�����7d~�y�x/�.\5G���v��~P��	�L���M8��h?�#���0G"Tr
*��M*�z�I�:��kP	�5�/7T��{���H���y������{���=�}k����9,A\��#1-~��n�������������b�padRq�g��*}?�����s�������������q;b��Ch���2�I[ |��<i�o��I[��|xem���zi�l$m�������(r��-��+����n�
��(��
0�B���(^����-0�Jg(����w3��}�E���R��F�����(�L�Z&���N<3�C���)�V�H2�P��C��k~������;����B����
���Jjy�_��L28[�&��]3����}Eqx1f����;'B~W����r��f��m�\��xC~ �-�B~X���������*
`Z�c�r���e����+�h���?y&/��R���������&c=W*����h�	? f�����"�U*b����]�,1����#;�E |q�P�����E{�E��9��E�U�e�J�r?�:���8�BuFr�^��5�E`z�?�����u�)g�p��(r��F�N�|�^�[�0L������BL��[Xta�E?b;�9��S�>9Bw��������j&��_��\C�rq0�AW�\mPl�em`�^�&pC�������Ch�v5��
���U��t��$��
$q���Y�u�c,�O���S0i@���I`������
0�o�/�I |�\��������
���	?�fm�p�+k��x�_{�@V�U��`��Y�U��P��.:��;�&mP���!��
0��]r�E��&%k���t����y�K�u�� ���	u��  |!�`��+�lJ2��M��4����P�Av���d�k0�)m'�nr� �vC���(�E@���r�W]N�����!�";y�" ���e0o7,��{���
�����HM.������v�$�����
�Z����Z�������PZ��J �Z�#T����{)9���XI%0|���*������YV	�	M��J`�Bh��T��BO���V�DC%T�U�@������J�M�*�z��c��Q��
��q>�C%pz*�C%T����.I%0|���<�J������V�1L� W To�^%���ml�{).]�1�bK���P�Wx�>BE��@V�~��A��������u^n��m ���C�7L���d��7���	�� T2�A0�w2^n6�}�����5���f��w�J�l0����� z������B�g6���A�F�M�w������'������N�"}�g��pi!&�����������5�A(�k��PI��g�~�MLm 9��u�� `������ `����l�X/g�Z�d��S�.����X'o����0�~'�����WJ�J2�+��+���Iwo�x\$�+Q8�� �;4N-���]0WZ$|��������+!�,������^��� ��h�/�P(^d�P(�?d�`�����W�;o�����w3�������E��v�DV�A������c�]��3��d�UVV�~���,0�[�2!���r:+@�������_q�=�T.�CEe�p)�IY |�������R����gJO��,.5�H����z�C�h��U���.T��CY`������i��,�V��M- _��6�<����9]+ ����)8�d/>S�8_d��p�Q��;BhK����;���@�V9��W�[���Y?CQ��U��(�m��� ��E�����8V�~��$-���,IZ �[e��p�&�!-������r����y�Y����7��u�&�p�<?�X���}_��p-�0��P�B�m�X�q8�s��&Zi��m�z�4�O6���T�'����p�x�	�*���&|���b�����"\��5��/��& \i��mB�\�%x����lB�^u�P�W�E�^�{09�Z.����_�&<��B���I�&����;j�M(����c�d���f��Mh��c�i���_+aI6�x�	#��+Q9����@�������;:N.� ��&L=9mc��G�r�����{:����_5zOG7�2�7GOG��~���bO���n�L�,2
��c�u\�`�E(b,t�,�B����^+��E(b=W�h'�PD�M��s���3�Z�P��J��"��4F������/oaij��"��"�&�`N�a��5,B����(���T&�PDY���E������E("���X��_����K#��A1������:(��p^�8L��F�:(�+����W��?��:(_i�jy��b%*m
~
��G��~���<(�m���H�7<�����Wn�Pp�V��Y����
#���+�rts���=��pn������m)Bl��T�A�� �Q�P��q+Dc�Dv2������}�I���!�z��f$���~W�f�A@���c�*�#| g�����"|���H�K�0o6�O�z���\�A(��z+D�^�V�����j(��h�X�W����h�ka�A(b�h�X�����l������ �a�S�8L����b��x���x6����|�I���l�2��?���L�� �/���H,��#~c��� `,���a�+�rD�� �F��P~���
��\�JIw|� �z��5d�p���'�j�j�W�m���0���.�
����A�;N2 �s��w���+Y��s�d�7�#?��g�>3o���� p�����e��E�\��0�/���l~/*�^���3�5|��� ����2���JQ�D$�P�W�$C�^�W�d�P�Z�����k,�A��TD~6�:���l~o�����az���n��
�F���  |�t�\�����o�09��,_(Y���#,BAn�,�����@��! �`�k���1�! W��X~t���������E������_��n����:>�hZ������~��b��K��k��\U�����r���w�O����Nk�	����orG�ba?�%��3)t�K�'��r8���b����n:����Mq�����-��}��Z����Q8?�H���6��k(����W��d@�|�v�,�~
�R�$�QN�Xz/�b�_���)T��Q����v�5F|�\Mp��G|�����r!E:�����������/�L�>���U��{��D�P�|~��WE��"�_1	�r�w]������(�������pYG��rK&��������1�����cL��5�^,����
��#-�P�eP(8^�D1^C!r��6I����zP�0���$%�k�&�\O
���,�D��D��	�#�@�%t�@/�����F�4���7�q��(��pIb��}��}@���G������C�\
W�$�P$V�>��P���}8���	�,|�]��LD�V�P2�4�MD�fuQ��f�A2�f�Oe2/�O��l"�t.���x�G���D��~qS6�k��)�&�xm,�1Ug�S+6�Dr��@��(F�o[9����]����r]F�v3����F"���Se��_A1��b�}��GVE�m_�b�����8�X@nW�=��~��L�1�!��hA�~	yT;<s}���h���I��g��x2��+�1Z:���>������{�E�8&���e�X��
���70|�\�������7�o�M���p�o�2n�1�~�U�:����gp<�Jc��h������4�m�pe��p���pe����Z�W��p&(������jI+TO����z;��'JB+Th���h�����p�h��L�0������Q�P�Xo:Y=��V�K�f�={!*r_,<j�����_�0��p]����s��j�O�p�$��M�#��>LU��~K�d������p-�#8���+-��'���'\������q����������.�����Mc�r�������=+��������.tyHJ���U4)��[H�J�H��R���D�f�u��������p=J�L��&��X/���0�
T&�h��@R
�B����^��Y)��R(����&�P��e�Q�PM����"��(��(k����H��HT��]Ub���h$�`snr�L������w���X(�d��\�b���5����	v jOJ�Z�p�zOJ�z��M=)-|$�����e!��A���$}��}��i��(W�%������qf�R~,Nb�s���$��.(�$�T
Q�X@��v�f�E�$���=b��$&�`N�Y,Sh��N����f����X�4���Y,`�����b�[�!�bW�],��
/�S���� ����)�����pB'�B1����I,�~U�$
�~IfEn�G����|kh�`���fr�v����b��������EL���
���CX/7,���y������{}�=o(�SRo<����_�����Z�p�%���'.���b`��-'.0���W����u/���{q�n1�QZ&��r������b���h�,2H��i�l1~�r���d�Z��6Y�on�K�������(�~������(��N\`��G�������
/Y�����Q���'{������_�u�])e��~���:�t�F���z-+�"���:��(��`���@�J�O�%_O���$�	����,��8��MTQ�~���~� �z�s�Y���������1���-z����p ��d8�w�l8��0����<����TLGKI�Z�f���r.���zZJr�-�zz!�9�|�Z(W����j���G��|xB��dK�|(���4!��/�����7e��P |�\������SMx�E���C�e�#�P�����QVy�w�e�mVg$��i��_S���B�\=�D/,��Un���2�n<�����~z���X��~�����{�bM
��C����Q�|(�y���z
dK��\�zK�j��c�XD��E����1�
��W��b8^���j�b����X�X:?��^�����u�fn��������~�<ZQ,�q6����������X ���Mb�c<���X �r�}�^�z�X`�V����>#���g4U5�t�P-EKI���Lb���Gy�&�V�E����mQ6��$��B�e�y%��7�&�P�����`O�!8��oNb�s��l��B�$8��/'>����I�PL�3*x�X/)�jmWx|�H���H(��[�6'4B����1��G���GV���>��*r�����c�j�c�$�_[NL��z}B����G|�X�{��Q,����V[�����w�*8�m�2I��%Bty��i����ZLpG%�k����k���1��H&�.���I������-0�oR3�p	�(��%����C
$��(�J�\�ME
E����.�����% |�\x�\B�f��"\&C��*��.�L��K(��@�N�����0�
�$�O����q5��oi�mB1n�g��6�u���|�gg�1�b�H���.����3j�u#������0��r3�^x�h[��X(��z��N��������?�*�X���$p���e0s�8fN�z��B�Z��rb��q������$���� �k9�@`e�����#�4z�b�k��a�7�F���e�������.���������.^Y, |�4�Hb��t>��.�8Ib�H�]p��"��E
E��O?����>�X(�.�D��L��"�2���}�
z�B�zNm�Vx��
)e�P,s����E��.�LZa����v������-���Y��P�^d�P.|�1���w����?��q��"���=�S��:��D�'�0E�
n����f�b0�5'���C�x�w��������v|�m��b�H"��#���T��p��1$q\G��g�s��7�y$������F\8��.i��<9@�/h2tp �������S�#;�\�L����79�/�u������a |�\:�F�q��E���G���p������a`��D�a�~��+��Q��3�Q������a`�]�����g�l�/����~?��3�/\E��"�J�M��@�J2���W��I:�7��3����(]*?>��Q��tN'D(�r����(!;
r����K�"7r>>������;��o���X�N�!<�5b�5�xCxW(�	��\�������T)LK5p-
��� �j

������I���c�^+7�%��~N�f�{��|�3����j�b1�7��D |����L�WBax6��j
�d"�Q��DiV?�a���D��{������_>D�]0�J��n��t�;����+|�%+���8[	D�tTV�P�v���J�k��(������"�t��{�*�K�,���]!���"^N��QYQ�d��!>�&�L�*��>�����)D����
k��h@�������Y�����c�w��6��h��7D�W����]��
��{������~�u��ZD��j�$8��/�!�P
�C4z�4
�����:4>#��$4�������n�R���&����rIh������k�U^��G��f��l��b��,�4C�f��(x��l��bR����I-p������?�I-�\.x �V"�x��=�zja���r����t�A1�3W<���l�Pn}�0J�M9���+����l�����Z�������o+E���z��,\�y�_��L^��
��\�#D�������dx��� ���9����U0s'��������cU-���ZR����z����0��1���P���Z�Z�Hj���sR�6��xFS�2�Z(����������iY-p�RN%����r
$��oo+��]a�*��g)�,+�������4�\�I-`���8'��i���s����BW���t���+�M�~I-�J��M-�l���3�csVE*�����TF��B�����Z(V���u��bsR��
r�"�BAnK��|�=�!pe�7YT�A/���Ozc���^����p��z���;����p�;�����y+�6�$��rGk�������X(/Hz����I/��3qs����7�U�Y/ Z�57��'4U.t�{d�P,�u��.����V�H0�~@B���k�,%��+��e�P$Y��?��#��4+�cQ����Kz�L�z�B�f����^�4��^�V�1 �D?�'��+�M��<������B��[��r���x�mB�z�K����T.�L�YT������\��`(���`(��E�Y?Q�-Y/ ���z�x���������Mr,�`���6����#�3w��5��v��~����:^�����_����~������_����l�N����n����=[�����T���_��^����/�������:�v��{�<��:�w��*"���o:�b��x�H�P�{g�?{���p�g��x�7B���i���z�;�������.\Sx9
c>��y���8M�������1���j�#����B������d���S���~�
�=���9M�L8������?%��K�(������8��/���P�w\�c�R9S������j���?�p������K���k����3�����Y������p�[�����?=����a{^�_��������q�^�����+�����_yGH����a��#�L�!yG�������i�����������p�eV�w\��!���!����<��n]_�W���+~w�i�	���]����k���="���t~6���~��;�qfJ[��G���t���GD�R���9��7����G��/������G���G,b���Wa
_c��������}O�������|tB"��?������j��`���f�_���+{������s���/���;6�0�M;��
��a�L���>��)�.�o8_=@+%=i3H���L���f��3I�$=���	
=���/����g���Z]���m��g�YM����������W���60_�G���@��#za��!/�7�dNl
	>�.f��!�Bw��5d�V�7��a5r������Ke�[�
.����
�t���h�e�nhj����?�c��<
C8y��b�H���}l���M[D^s��M��Z�&dn{W'>>��>�����+?���!�WB'��5�`(w,��!�gR7��5��gS�{o��!F|#\<�~9&�V;����������cs��b�l��5�r���J��
��7��J[AL�_��-�C������[�"�	E�i+����H��`��9��D�]A6� ��`1��i+X�_�2���Ol��~������7�B�T����V_q�{��� ��~��i+��v|c+X�6}+��|�y��i�
"�������^*�����:����V�[�s:o1��"���_i+�W�O�� ��?��y�-�	���Z�����+V�V9��6E`�������W�Q����R|�����m���?�������+�P��l��aZ���_�������I�?`�nQ�7���U/N��?�����bu"��@�����B��w�����/����Kkr?O��z�}s�t3��������3p��)}��^M��_����D�J����J�+{����v
#�+>W�����+�CH�W"|���������,iW	���aM�����Zv��we'�v�_
M����x�f��C�/�����K��F�U#ZK�]%�����}B���**j�!q�~���g���(�S�K��-��[�������(<ba��K��.z�Hl/�+����~��>Fu��kh�?�M �gR���	$�����f���0,�����!��<
�|�S�����y�on=��%����.Z�4�K���K����
Vk���[�
|-�Y��������:��_��P.r��`5��}�d�\��M[A�+u�i+8y��V��3�b�i+Hl��*[���n��-�3(�]
��;�j�T�X�s�}s
gP���3(�8���6��%���2A�J7��u�+�����o�y�����{ y8������*���U��_��3(���?8�Gs#�J5�e��63~��ckZ���O���q�o�27�Q^���(���[�E�W��!"\��#���t�a�\q�i����p�&����[��"�g��M�4/�w����'h&+���O����?�N��s���i���6��q��P�!��k���kB�?��0���v���?s�"�W
:�1��(r�!��'�GQ��F�w���`N����J����(���o?���E���}���B�o���y+�#��X�V��v��a_*��V����D�\9D���EX�{��D�B��>o>Sni�� �_��Al��6l�V���(�{��,���W�~�z��� �����������2�{����U^�y+��p=j�
�~�E�D�� ����Vs�v�\�����_����|�S��=-2�|��Sn�Yvl���"m����q
�����A^�oJ����C�R�M�?�����?��7rG�*,��Ey�W�������?Bo��������o���������w���>���u:�R%B�(
�GQx�E�^�������������L
endstream
endobj
20
0
obj
54870
endobj
21
0
obj
[
]
endobj
22
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
23
0
R
/Resources
24
0
R
/Annots
26
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
23
0
obj
<<
/Filter
/FlateDecode
/Length
25
0
R
>>
stream
x�����$9���K!w�*+�����"��� 	@�-��@�at�z�p;���[8##R]ht�N+>d8I���������������a�����?n_�����u�����_��4�����a��>�w���rY�/�4}�/�v�&�e^���o������q�2�ss���m�������h����_����������.V�xm���W��d���6�����< �u���:��_�F����!�����r���Y�������f�f��Bju+jmz\�Y��I+����F����!���6}'�Zgm�g�0D�55��}�'�������i��6��V"��E�>����V����i��6��V"��E�>����V�z��p�Zg
��V"��E�}�g������������OZD�55��}�'������e�Zg=]���������@����!���6�F�u�f�
C�ZS�H�g}��Z��Z��]�Wg
��V4���W�Y��g}��Z��Z��W���������W�	Bju+jmzR_}�C�w�kM�"a��	Bju+jmzQ_}�S�w�kM���>����V��tS_}�K�w�kM�"a��	Bju+j�����:k���������"�>�3���V�������/]�
D�5�����OR�[Qk��������\kj	��OR�[Qk���������\k�U}�A� �V����7���v}7�������>AH�nE��z�\�WgM��Vl������"w��OR�[Qk���������D�ZS���"����V����h��{���\kj	��OR�[Qk�����z��n"r���Uk��	Bju+jmzkZ�����&"��E�>����V�z��������Y+�����w{�f��Bju+jmz�h+���|7����E[��	Bju+jmz�j���z���\kj	��OR�[Qk�m�Zg��|7���m�Zg}��Z��Z�z���>h����
��&���4���R�[Qk�������|7�������>AH�nE�MO��z��n r��'��}��Z��Z�^�W����@�ZS�H�g}��Z��Z�n��z��n r������>AH�nE�w=^�Wg
��V4���W�Y��g}��Z��Z��W���������W�	Bju+jmzV_}�C�w�kM=��>����V����������"��E�>����V��������!�q+�;���zS_}�'�����������a��M}7�hi�Y�!�V����G��}��n r��G��}��Z��Z���W����@�ZS����!���6���>��������F����!���6���>����������W�	Bju+j�����:k���bS���E�}�g������Q}�A_���\k�Q}�A� �V������=v}7�������>AH�nE�M7���t}7���(�Y� �V����^.�����Y+��n�+�,���>CH�nE�M������@�ZS����.�_�=��d^�Y'�5��������	Bju;�z���YO'�5��v�5�����OR�����m�Zg��8�X�����(�Y� �V�c�M��Uj�5��ZD��ii�Y�!�V�c�������r�Xc�n�ZC�h�!��k
=mZ����ku;�zRG{�'���Xk�����z:q��V�c��Wu�}��Z������Z����ku;�E�>����v���v��Y���@�Z�f�f��Bju;�z�Y_O^�c�n�ZC���|�'���Xk�Y}�A�]�MD�5�����OR��������������\k�U}�A� �V�c��7���v}7���(�Y� �V�c�MoW��Y���@�Z�f�f��Bju;�zT_}����&"�zT_}�'���Xk�Y}�A�]�MD�5�����OR�����M}�A�]�MD�54��}�'���X�]��E|u��?k����"w��OR�����������������mE�'���Xk�i�Zg=�|�#r���Qk��	Bju;�z���YO=���\k�e�Zg}��Z����n��:�����k
�f�u�'���Xk��������Y+���h���H���!��k
=����/=���\k�a�Vd}��Z�������:�����k
=5�u�'���Xk�e�Zg=�|�#r���Mk��	Bju;�z�h��^z�����(�Y� �V�c�MW��Y���@�Z�f�f��Bju;�zT_}����&"�zT_}�'���Xk�Y}�A�]�MD�5�����OR��������������\k�U}�A� �V�c��7���v}7�������>AH�n�Z�������Y+6��D�f�f��Bju;�zT_}����&"�zT_}�'���Xk�Y}�A�]�MD�5�����OR��������������\k�U}�A� �V�c�MO��Y�����n"L�H���!��k
=��>�K�w�k
�"a��	Bju;�zR_}�C�w�k
=��>����v�5��������&"�zQ_}�'���Xk��������&"����>����v������:k������&�4�4���R����������t}7���(�Y� �V�c��'��=t}7�������>AH�n�ZC/��z��n"r����}��Z����n��z��n"r������>AH�n�Z�^������Y+��n"L�H���!��k
=��>�k�w�k
�"a��	Bju;�zV_}�c�w�k
=��>����v�5��������&"�Z���	Bju;�zS_}�gI�b�n�ZCk��>AH�n�Z�^����^����Z���6�j��>CH�n�ZC#C��>Kzku;�Z���	Bju;�zV_}�gI�b�n�ZCk�������},�g����2��y���:���	�'Y\fK�����W��mU��h�z��g��1��Y�n�����mi�8����ek�q��O8O�2����4�7�����^���~V`����v�n���V�.�����&���Vl���x�^�m���yiw�r���6(�i�`�u�~�����'^?+0��t�[������x�c��1������������S��:�J]���n�Y+����l������,�}�;��\j���#16���D0��m�>Yh��i+�B?��uHmE�c7}���O���Z�4x��s��g���{��F}��<��>[�g-�;���y�{�����9��Yf
d���0�L���f������ ��f�8O�ya�y�!�}�
m�����~N�#v\d� �
�m�6��Z��O��j������P��Cv��:�7v���9��� �S��}�
�f��u:����=�(��&�M��v�n�u�~N�g"������������M�iOa;m�N��A2�'��9L��X���`M;d�V:ub�|���'	RW}��=��8V:�Ws��&?�L����J_�k$t�}�!�Q�|���K*G
}���.�}�Bm{gZt=��u��b��K�s`��p_O|�a������e�#�P������Z��M���:3��0n��s���������������m���G�)td�`a��b�{��ON�����t���U+4_3�������p���u��i��k9��o/��:��zf�N	,:��;�Yv�o}����O*{�����g-���(��|B�����r�����z��m���������N$���S�>Y�g�X{���~�|�`w�w�@[���>k�G6}��w'���.}����h��9�M2��>��kM�m�#��HvFP�Ye+�)��Z��x��}6���a�;/S�����F��}�B����0U������X�V�v�La��`g�q<�!`g�&�����Zj�����#�>);;��s�}�
�'�}7�^v��?���}D�
r�A#�;�����x��7@�F(4!f��@��n\��>n�����6(�i�`��INA�U'��~c�"�>ki���������	�TL����g�TN~K�Fq*`����h�o�Y+��������QZh^80m�NP{���_d8��+c�����>��H�<��/RqX"9%�!�v��	�>�%d�L�,���W��X�����NX�{��=�8.	m�B�����NP>�P���#u�����g�����Ve����S>z;���^R>P�!��w���q����>��F�IV���O>���i��+5���	��t�yb�ev���r:�s��i�Y'�����;��8;��5�w��c��pr�u��K�Vd}�tp���5n��}�!%kX�?|��p�����}���t�/a-L�m�b���Y������N�%R� ��p���b�Y+�_��"{_�	��6!j�g�����n�b�3��E{4)f��>V�|b7}����f�J�X�]���}2��R110�����Y'*w7�a�%�N]��B���q,��&�#�*8����Y��z��Q�Y����M�{���/�Q�YXhb�>k�b5���`���
m�6�g-��>2���{s�Y����1�_O
1����A(���r��������!/�W�&���h����M�)4o���R+�>����}�=�Y#N�rB����
��SS���Z��.�g���3�}�����p��ww����������w���`�u�&���F��N�Bc�Y+v�JJ��_.8��m�b���Y����U'��>{R��g-�g'	B1)�e/�}����~x�X������?p�>k���5tinX����M-4o]��Rv�7l�1�!.�W�'xa����Y+�3%r���s��
u�X�����z��o{<�|�\q)g
���pf��2�?�MH(�
�r�n��B�}��>)]���q���mPn���}��}"��#_���5���>����������.~�����)�����:a;�y�2E�i���Y���^c�5��N[�����~G������q	!���DH�����	���!D�Bb�Y+�����!D�m�6�g��j�p�y
��L� r��g�n���Ora�8�C���}��H�"���aH(���9���N����B�y4B�y���:�"���6���y(����B���q,�@W���M���Jz�]��M�g.A���r�!n���iB�>k��v"8�4Z��M������G�L\��Q
*G�F+9���V�>*����z��T���>k���U�q?�XN�Vr��g��X?�Wr��O�Y����~��4\�)������d���x%���ha��v(F��-�=B N�������q�-���=�=�q?�<*4)f��R��uwl��q��Z��{+"��D*'
s��g�����yA���}��wc[8�5���]c�Y���9|�s��O�Y+��}5R91h@�S�k��C�K*���5��,\]=���G
�(������D��u��D�>�E��=aD,gxQ���}���o#r���6m��l��q�k�����}��]=(x�����dA,&
�#�Ykk�o�������4��1f��b���q�5����9u�G�����������Z�arj\k��w�+��>����?t��xO�T���g�X��t5�85��M[g�Y�tC�����jxG�i/~��Z[����+��pr�iT�SwM��g���mk�Q��q����1(���5��!f�u�}��84Bm�a���v��	c���4B�	1���^��aB���4�6m�������E&����9���Vf��
��`�s1H4B��g������t����@�H�&���V�s��P[

��V�����\�:v�_�g-��b	�
w�bx�$��5B���E����h�W=�d%�PhB�>k��{�.��A�M�����V�`D,���Ct�?�c�Y+����h8�a�T����Y�O��������N���}�����`�������Y�O�����3aX�����w���ha��r{������h�A�}���k�������Yc�v�	��1�z��-~y<�'�3���9���V���
�Sx�����1�6m��jcw����qJ�x1/���V�s�[����b���K�?-���V8�����b�B{f���
�p�;[����B3G���Z�{?��&���8A��	Ac���]K��}-��?x�8C������c��?���p�k����k��I2�>�p�����#T����1R�=5�Z�De�������6(�i�`��P�{��1d�T�2���Z����2�P���c,�6���sR91h��S�>k���t�=��s���I2����� '�M�,'
s�v-�b{	�8�5j���>Z�g�?r�K3����m}��^/H1��gM��^�9�5f��]��>���U>7�m<�z
sh����Y��K�8�-����p1Rw(w��35l��as*��s�n��P?����9����g�R�=Jm5�c�@/��q��:s�_m8��6�s�u�l�Bg����1<qR v�i�]<��X�������i��8�%�t����Y_ D�c\���	M��g-L~Fx�	�c\b��i�`��@{.��PhB�>k��yr�2�C\"���'uK-�i�
~Nt�>M8�������g���}YH������B3����Z�W~8��Bl��D�9���\K�������o�`�(�]���>k��D=�HLU��.ax�������z�A=��]���PhB�>�������K�����6(�i�`��R=����(N�r:�(�1�����M����$
�)��Z�1���+q�K�C�=i�\j�v2�p�K^�n�Pa��@���X��0�����w��2���9�%/PW}���Z{pH~T.�9�%�t�"������%���S��
 f��B�|�0V@98%�!��Z����{	��=��Xj�v�a9�$�����f.�P���M�+4��}���g��,s�y�;�?��s,41�����mg���$A~��>Y�g�����a�e>D�#�p��xeb��z�H�'�+��� f��BC[=�g��
 ����9�Y+0�������>P18%�)��Z���	{��Ph�i3�Z�����M)4���}������v�����#�>L�+��V�>������z��>W�g�����Bz�������3���3�}��?��x������Xn�k�9�}������z����oR�����3��S�mU�&`�K �SM;e��:S}7+����;�{���]_=��X��E��Y>|rN�(������d��*����v��j���:a;!i�����v�v�t�>�?pW}�����f��rC�j� �3F|�"Q��,�3f��U����z9�%������f-�`�Hv�a/����y��Z��h�{��s,�'���Z��������=��Xj��}�����#�������g��'������f����������N�� a���]K�]�#M�`���6�v��>[�g�`���e��l1J���0[0���g=��'��bn�����NP���[Mk�q��Nj���i��Z�O���X�#]����Z��O����@�i�p3�Z��n�!8.��a>�������{y���B3����Z��w������tv������Zj�>��?PW}����f,�v�NJv�44&��1�������(��D���g��0
�+�������?�B{��k���Y�r�I�_����2c���V���(f��P���s����e�>k�2W��-����������V��-���#�f>�q,u�G�j��
��"=��3�Cu`N��>k���P�CSB�d��:A=�9]�|8S�P�L��s��g���F�B	
{{��<��Xi�>��G(�����n��B���s����41f��b���u.�����v�t�>u�C���`M�Rg�tz���(�zg:X��1��/RT����y��Z�\h����Z��m�qSj���u��:Q}���G60�%�����Y�Z�G���<�bn�<b`�u�b7�qy�qV�`</���N����:�G�������Y+6�i�n]���H<�B{F�k���x���^y���U�'��h�
;/G����:�Lmc�Yu��l���N�|��xN1���*	*�MK�w
�sj���>k��36p�k0���P�Zj��.��h�X<���|:c����������x�1������c7}��Lm3m�V��{x�r^��<�l�Rk7~�r�@]��B{B������4
����0Q0���g=��G(���s��g������4���8O���6m��V�s1y�rV��<��}��	��
Z�Q�!y5��t�R4g�9�����@���|��ZxO��9t��	�\6�Vj�>��G*�
�s�v-�R�I�>_��L���9u�
�����R����x�S���}���x�rPj,�C�>k�>��G*G��
�A�Zj���Kv��T��Hg,�P{g8�4�Ph��3�Z�����-����c�f"��Z�{����QN���H<�l�R+����g�{�8%p�'
��=�X���xA ��r����������=�}����q
(����9d��:A�^�o4-aS�O#��5M��g��1q����#�F�9u���}�J}p%�a�T�L
�s�n��R�L���9u�k���Z���������x����N�r
�%�?
�s�����N?qy�����x�X�]���=f��%������R9�@��#�S��j�p"'�Ek���6(�i�`�u�b?�q2:�qB�</����V��(���gz�w��s�i�4�Z�O��s(���s��g�CP�v
�#�){���	�ie�����U`h��3�Z�|����b�i4���8e���z�X��h����a
(����9���h�\��9�i�`��B���x�CO����t=�R+��������� ��s���Vh'���F�
�9{�R+4~��_PS��F�9v��
��<�� 9j�#'�S�F�9e��:���s
��������S���*oG�}�'
��u�"�<����$V�YW*�P�=e�Zj�>�x/P����m�}�B}�/�p.����sR��g���.�T�H5�I{�R�o������,����K�m���I-fR7}���Z������bb�s�\K�~�^nC�tbW}����g,�b��<`�k8���D��9f�����:��_��9�s���j�������m�}�����?���Q�Ax�B{��k��g�r�?�w��s�iO�3�Z�nJq�w
�#�����ly}i��>���l��wd�>ke>w��S9h��S�k��-��/���s��������5����h���}n��Dg���F�2)��=o�u�a.����Sv����-�c]�����mf��R��n�?����@����g���)!&�=��XL	�7y������O����A�����g���=-�y
�s������Vj��s(p�k����]+���o����U��g��Sr�k����,�l:f��5-���k�iAc�c�Y����g=�:�
�k�,�g-<����b8=��F��	|��V����,~����X?���>c����!��4��!f��A9�5
�Ph����R+���;~�F
��u3L/c�Y��6yN]+�#���Z���J���sj���>�D�U�P�@8r�=���������14���=��Xjmh8��OE�%��@C�H��\:s�����m�/���Y'(7Zf��)\�������f,�`{�|���0X�[����%j��[Z����h1������#O#���e��Z�O^a�XL�Es��g��2~1ZI���`4R`��>�z#�x��s9>5(�9f��r�7�rjX�c7}���:u�j���p*�
Ks�v-ujl'4����9u�G����r�kd���L��6f��:~�r�#2
3��i����Z����9�
Jm�4�g�M�}��mx�����4�)f�u�>���T�G
���_��{Z��A#�c�Y��3�����B3����Z�1�U�����!q�B{R�k��d�+���d�=��Xj���������]�413��n�5��]��Q�iNt����Vh�"�#�9�5��M�f�Y+�����^��H5���>k�>���X��7{>���������q2N�rZ�p<���Y'jw���^�����5��3���������9g�VZ��kZ9�5���>X��������y���}��n@����PN����Z�������|��sl���>k�>��=d�'�3���9���V*?	��z�:�#_�k�����V�sl�rb��<��}�?���9B���f�J��p�E��04@n�a�0���g=J��q��-����8�9��}�
}b�Ac����q��:q{��p$h������Zj�����;\�(&7{����J��R~b��J�8t��P�@9��}�:�'Q���94L���>X�g������c�;�����>�
{x��6���s��7c���D�a>k����4�|3f���7���`�@����f-�`���sh��m��Z��V�����zb���Ia���b�Y+���u���@�i��3�Z���!r�bR������A,�9��>Yh&���R�^\E.�N�q*�P�=����J�DPmw�s�g�8'v�G��u�R+6dF
�aI���Ar���ba���>k�?���q�Ar��v�n�u����1�5H��M�f�Y+�{��_��H5���>�L=����P9��z��:c�������4T�1�}��}~_���>Y���}���#���r�r�j��S�k���l��r���]���3f��E��8r<_��r�j��c�>��eV����DA�]sj���>k����15x�ThOws-�PW�X��[�
�����F����>��F*���9���Vj�*�j95z���>Y�g-�^T����<9�����Z��<��7���U�*���K-����|�&��Ac�v�	f�1��	"���r�k�����f-�R��S:P����m�}�B
�����0�5|�Ph�us-�B�.�y(�s1+h���n�R+���.�`�������V��'������u���r�NL�IY�R+5��*i�G��R��Ri+��V��G��2K������[�Zn�����^�:MJ���>k���B�(tTh[��Lc��hj�6�J��]	��6�Zg�:��6?���}iX�/A�������E��x��M�����~���]i�W���2�g����uGp\p�����C�����`z��c6b��4��1f��`cdW��C����m�6�g�P���������i��S�>k���N�����3����R/^"X&&��B�����6��Vj�mf�c�I�k��G����tFs��:� �*���,`��bi,��V��I�br�{�r�����y+�r�0��iR�$}��Y+�s��{,P����(eK����rh��2(=�A�	is������U{4(�����J�eP:4�B�l��](o�v���*t���>ku4���b�vY4D{���1���g����pJ��������h
����R+�����J�����q��Z��*$x�p���J��I��Dk�R���G��A�N5�y��R���N��X�Y�,�g<[K����6���n��L��a��`ChS�/�n����EZK����^����i�N�/M�R���J��$�s���6�O��Z��%=�f��
�CJ�����6�:A�/Jw����g������>V��x��e�J��S/�2�s
�����+3���Y����Fcva�8���^���g��O�:��6(�i��>�GM�HDi+gs
�'��Sv���*�}�4|<�t�������Y��J+��=��9"�g}��WOi�V:a�I2��'z�Hh�5����M�����'r`��bi&��Vl?��O�������3o�N���+_Hm�R��%�g�������|27,'{.��b�\��=�0�����0��I1���,�\���������0��}�9��0p#�9���r�=?�Zj�rJ�q�,bZ��
�l�6�g��������r��s
1���N4?�����hp�iO�8�ZZ������8��l������l/���"�0
���}s��?4��*��E��4��Y+�{��gU����\hr�����%)������I�0��V*�|Qo����(�-J��R+��)��r���������J��i��S�U����g�hf������������f���q���w��zZ�\hO|��Z�\z�y1|���\�8�i�`�u�b".?�r"�c*�A{��k�����5L�z<�q�=��Xj�Q{��]�Ir���z�'	��Z��
�8���e����~����s�+6�(�,�rQ�"��}�i�t��$nXN�Xm^��[���j�9�iR�$���Y�����8�mQn[�3��V�5���b=���j�,�B���R?�dz�}R�[V���`a�������yU����Y?1f=U6]����up5Laj�YO��H����
=�E(��M]K-���1|U>��rj���i��Z�l`HY}�"��Ev9���f/c=���r�i��:�Z��{x.�P�b�1�C�}�B}�E������c�������,�}��E��4��Y+�wY�����pI?(f�J�X_r�)�y_O�Gm�N�b'����Z��/��!F�����Lc�������>�r���^d�g��bu7$|B��I�W��J�}�B}�f�u��{�.��j�>�%�����*�z����(���]K��������m�b��
�Y+6���!0���YTh��{-�P��e�[F0�k�>��=C�Xj��H
�T��+�qP1��
��j�R�/����!Z��Q9�/\�k'�}�B�8Z���.�.�T�g�P�x�`s8�����&f�J���7�q�&p�8I��}���������(�-J��R+���o����
MJ�K��Cd��b�1@�\*4(��Z����?���\�b��g�����}���7�����8���I^az��}���y=
<�#���0���Uf�uneyV��q�C���v�n��R�������0��<+��\1=8��9�!g}����^+���OCV�V��/�e������k�Y+�{���p`��bi*��V�y�$����	���A�V����}su��:I�}����n���m�b���i�t�z�@xyeg�Y������o
is����r7 ^)4M��g��� ������i���YK7��O�t�EJ�v�s�t'\������>���C/Xk�[��3p~>ki��|-�BY��B4���A�M�����CQ.1# �����p?)���Vl'7]�p)�����c���1��wg}����{-�@��;��t;�]
����a��@��W��v�(v���>k�v.�p�aT:.���[������n�iR�$}��Y+��I���mQj[�2��V��&[�K����g��_�:�)���NX?���Z��Z�5���\1����}�
-o]v(]����Y!���gD���L���B�����>�Q�v����n�y���~-�r=��>M�~�6(�i�`��bC�,]AL�/bPz�CL
1��A���t#����j����Vj?(�����4xw����>��Z~���MC�}�n���{�vd�g����	��E��4��Y+�{~�~�����R����zz!�{@�I���c�g�zT'���`����(fK���}�q��9��������N�����)�P��Y���}�?�X�p�U��v[�g������rL��f;�Kw���]���z�{a��CK�MpJ��|�~w�Zj���xRM�Egj���q��Z�O^[@*�
_/&��}�B����3�P�~w�Xj�vo���c���K����Y��O�������vb�g���?�;w�(w���>k��������t`j���
|�c�c�I���`�g���������(�-
��R+4|��-�^���L�����Oq���j_��Y'l?t`�.E����R��Z�e���3�{/P�U����Y��).K���UO��:x9��a�Y�r.1�Kg�\��ZzF�Xh��c-u�"p���X��AqM[����q	�gyLN*��
w��g-��-*�Wz4��������B�������B��k������1�(�;3=��:������I
�*=��E�J����=/G������&f�J��~���I���^�g-�g#����E)�Xj�>)@*=��DwJ�K��'#��jO��Y'jgM�~
G������Y�R�Xc����Sgm���)�{3&���������W���Y���N�N�o�'�	5���>�
���[�����6m��g����,\j���jz�1�}�����s��G��kb�>k������������M��c�Y+���]���G1���}�	{�_�s�9x�.�V�g������K����A9�V�����\;M���#�>����H����Nm�R��������	B�����C�\���H��^��`�Y����K|'�3�a���z�~�a���Gf�����|b6�c��B��Kk��Z��1fs=x���m�}��>���O�>���{R����k�������gb�������4�Z��9�x��E�*'z={���Gk����`s"���(��/�K�����}"���]����Z���<�F-��i^�;e�J-�N8�p=v��I�/��Vf��4*�-Jm�R���J}6b�X��|�h�is����B���Ph@`��B��Xp��*tV��N�a�
0���w�7#����EZf���?�]����0Xb����R+�;Fh��q��Z�O�b�J�e����Z��N��vXG��
�i��k,�@}#��	vbTz�J��Ta��6�����Nu�E��a�g����8��]��E��4��Y���y5,�`lB�a��2o�N���j��Ic:`�I���a�g��+�B�&�4�����E9�X��=�8���A�d��o
is��k��?��$��v'�Js���	�Y�PSmc�Pz�B�l�~8t��&��z�����R6��zn�\���s��B�Upk���M��p�6.D��;�i�`��B;�6�A��?��~����b4���*z=��P�~�Xjmi'F�D��
������gJ����Q���6�Z^�
�[��}���.�T�g�����}q
Qj�z��ThR���J�S\�����z�����_�g����d�{
�����h��X����e��`�Xhb�\j���"��,n~��u�~
��~D����s ��U;41�V��4$��G��"b�U����Y+�g@����������|m�������Y�>o��I��l������@��g��|���m�3��6m�n�u�����V�&`����u������n�;������k���Y'������?v�����N�n�|8(����|s�^��g}����S�"t�(t���}�.~�%�U��ph��:`������.�����C�:MJ���}�����=��]:*b����(f�{q'f�~
T�5Pw(m.t��_E7(���v�n��a����JwA��*uV�n�u~����%�v��Q���������y��g}����M�g~u��X��G��;8�R+�����6(�i�`��Cl������t4|��b�Y+���/�\�~�Xj�>5�Xz�9��la��b{���s������:��Q9��}��\��H�h�u�Y8g}J���X��2(`�J-
�NHt�N�R'����Z�~��/�t��E�mQ�4�Z���M{�
_\�R�\j��[c���~�U������Z������S������	�Y�_��.���[�:�J��m��Z��p&�%dT���O��+����y���g=�I��>��B7eH�1�B��7�R+2L��t�,P����
�}�J
��''��K?�7�I9f��r���jnX�~��Xj�����K��?�5p����4���}����^��KND�{3��h/�}�B����c������E��4��Y��<�{.�����eP���Z�lz��u��:I?�}�B��Q|7�o�������E)�Xj�����^�]�Q��������R+��B����	�/�\K-�^�Cz.�����I;��V��*��~�yU��
�}������=�~h�=��v��0�>���+��2.�^\L�
�k����hO�j���u��Z��}w^F�s������Z�Q_��X87`M�
�c��'��2*]^�f}���:u������v��6�8i7�}�J}6uD�.�.�Z�g�\_��!'~k��X:7�@
���R+��%����v�;IG�}�	�	����<����?)��~�h�B�>Ju^\���5o�4����l��{a8��:+�
��R��j?�f9P����m�}�B��~���q*gA��'��}�B}.�A�b���K9�Z���>��:)�"/k���6���Q����l����Z�~���D��H�rQ�"M�}�:p���\3��'8��H�&e�J�T>�%v�8�7M�����>k��<���^����@m�R���i,�RC���C������K���u������'v�~��`��~��4�n�|@�	Y�R?��k��;����Y[���S�r�;d8?��J��v�v����}���;\��>n
���tN5���>�D��������qf�u��K�t�C��$�A���Y+��%=��5�]c�Y+��+�'�KRwY������1���������7�.K2�hB�>k��2S_We.e.�P�g�:���os9$��th�� P�����/Ge2>�X�� '����:5��?�=��5��(e+�z�y<�{,�j�P�is���@�%Y
u�~d�Yg��	N	"�G�h�� P���i�z�_�4g����#u^�:k��>���.��[I6����vQ���"�h{�]I>�B���k�����G���������y��Z�O�Du(���3��Z�O��,���3p����7�8��L�8�Y��t��?�t��}��=w���$�A�.�V�g-�z�=d���?�\2o�N�����PG�Z�� `'����Z`�u,^�o4�F��E�mQ�4�:=WOSQ]�~K�8��7�K��|������&h^o:��~e��H]�;����I���Vj�x|sv���Bgm��N�����'���� �L_��M�>��N-�{K23�uI��B���k����q!��#�
�m�8�g��ph�
���.I��Xh�W�Z��Znj������
�&	������O��K288���^�R6�
x�_����,��g-�n�}�dp�E�J������ew_�������[���vB�{I�@���>k����Q�	�������E9�Xj��\�)J����to��!P�\j�>q�=���)h��u-�r{���$��S�IY�R�)��K��d�.�g���y���gm�����?x�����������Z�a�����7�
�m�:�g�Z���G����+����Z��COt'���k��tK�XC9�r� ����Ej�'����r���dg����vb�g�~�pC.7���?}	��E��4��Y+��)Aw!���������[�����3��D�C�4)v��K���\����������}�
��M��&G�M�I�W��}��??q�S�����g���.��0r����~����B��>���	F��i�ot,�R;�}����N����f��P����X�����c`��6���S���E�J���}���F��;��y+�b��6�[�u��:I'�}�J}rf�P@������

�����d�kRbW}��~��Zj����H�6?���]P�IY�R��/�]B�U��6
�Y+���8{7;4��o�������g
��u�d��9,dA����Sv���{���mPl���}�[V�7Pz
P�e@5���>k�>�a&@���kB�>k�v�y��.L�d�}�������0(L�rS;��g���p����� u�(u���>����`$�p1��v��U:q;��e�:MJ���>��`�G�}�-�R����(e+��
���6�_B��`���5��6W:����|��v)���}��G��$�W�
��i�,[�h��W:�
��if��#���$o3<�~ �=�cL��Q���z)��s��q��
o������
�}����
m�2�g�Z���R���3)�����PwY��h�/;K-����[�����W������Y�7N�m�qb�5��h��}�J�������E��4��Y�������2*�_a��[������G���;-@�I���_�g��:�1����(�-J��R�,�`�u�<z3�15-���^��!��w>�Y�j?��
��Zj�>y��T��3���l�������c��6����V���k�3j�Y�r2\��9)���m�n���r���
�^��j���i��:55���~p�4�����eR��g�\�Y�����Px@M���c������7������i��
���
/r�agz�\���}�Y+�<��@��Bi+����x�����-|w3o���z8^y}����Iz0��(oh�f�!m��mQl[3��Vl�(<]�Q�b������R�����U���n��Z�Z^������O�B��l���v��zD��*t���>k���+�o��iN�\���7�N���|kws�a9�sQ?	�Y,�2��9��y@�~��X�#0|��u>gp�q����i��i�Y������o;������&�g���w8���\��HSi��RC�Ey��'�A�^`��1��b�������E�Mz��N���>�:��
��o��N��%�s��D��>XNz�N�~��Zj��B�}Zv^;+�Y�b�y��Hc}�ri�k�Hi�Y�������+v`���/�\K-�����#=9���A�M����7{���K�4����)�+�I)f��P����`9���X�~�Xj��~�g�,6��t�����Y+�KB��b�����k����:��~Z9��l8��\�Hsi��bGf��:K8M�)�/������R+v��;��r(�y���Iz0��V���}����Cp}�g
�`��NTL�'�D��&t�'
����&������W�'��h��,�t��*v���>k������o6=�k�7#/�����}�V+�m�}�	xRM;e��Z��3�������k�*��:���#��E��;e��:Q�oct��'��kB�>k��G[��o��wBMb�Y'ho���|G1���}��}"��~C�;w���>�����^z
=�N�i��[��{�����iR�$}�Y+��Zr��'���Lc�36�
}�t |A�.M��;���N�^��;-=N���o�,u��;�����t������(�>����{�&0�r����N1����=/�	]��;�i�`��`��g9���pR���k��������G�j���K�������G�I��u����B}�36�>���pR`��R�����l�ci,���oP>Hw�	]��
M���Z�e,4O��|�G�:I�}�
�o7u�8���h�c���i,u���]����^��;���V�/KK���\��;t�����|1a�(��+
���,[��	3����G�|Tp��*p�V�>k���p)�-�.K��:�8^~i�Y������	'�/�\K��������@�C�6�Y4�������<8��~����J��������5�Wn��l7=(��'��_^�R�W<<�Zu���Q50��Z��XY:,=��EK����?"M�����&g�J�����U����I�1��j��cnz,=
���(dK����KO��
��o��Vj7pj��D��g�I�}���%�1Ll��D����W�N��Z���p����Sgm��V��������f�7���a�}�f��C��16�P }�A����b���\K��xd�@�C�l��m��:`�
������tl|e�`�Y?ngu4��pl����7�R'l/���.����]m��
��r�=az�����/M��a��R{gQ��@].J]�������}�2�>����M�r���i��_K���iR�$��Y+���x�����m�B���i,�B;M���J������6�Z�u��1X����'h��s-��5����t1x{�e�J-���t"v(�N��2w=�.��>k��s��{����k�����g����p�!��A�M�f�Y+��!��g��h�*3)e��:5�|o���p3�����:75|��-�xv�n��t3x�����}�����x9��H�����U�04)f�u���0s�{@��Bi*��N��E�-��Dp��"��1�V�����*��k�:�N�b'����:c��Wpj[���Lc���]���=�O�i����J�-�:%_H�W����>k�vc9o��K���������6�'
{l��8	���PL��b��[*�J'h��
�����8�mPl���$��n^����(����Zi�>�t�y-1��k.�\s~Q�X������
(�@1�����Z��e��nX:��+|��pI+�����*t�(t���$���%�1��,]��?���	��J'h�K&oB�I��taN�I+�A�d��F��E�mQ�4V:q������%P�is�3�7C��o�;��9�����k����A��*vV�N���_�G'b��d���5�n4��9�����^���2Xi��#�R'*��C���;P����m�}�B������c�4�t2\�O
1��v�����B@����_9�Z��d���1x�����>k�������>�N��p}�}�Y+���4j���E�����Y�{p�N��t2\�J��R+���O?�4)w�^L����l��c����(fK��������`�o
is�����jw��Y+�$��6��[�K��$�g�Z�)0�����W��� �g�S~7�-��~����_v�;8�>�I�_�w����K��w	�~��Zj���
���
m�8�g-�nR&wY��K������Z���!���B�*\����������N�n����i�G
����!�7�Hb�{3��h�}�����Dw�rQ�"��}�J���������eP���Z�O���_�;M����>k�zb������(�-J��R+��E����t-x�Y���>�D��
k���Ht8����F-��N���tz@�U��v[�g���s��2|�����4��4��9b��bKObb.�
m
�}�
}6�<����"1)���N�2Y�or.s=���^���J�!|�d8��>^_f}���:Q������|��&�g������;w�(w���>��d{�tc���"1(e�J��jg��!�����I:1��N�^��4*�-Jm�R������M{^f���1�R'�iz&���jW���1�R+�=�h_���+��%�g��:z��,�����Y[����{����x�i|�����U��Y���8^���J��������g���Z���mPl���}�	{���]r����bR�n�u�>~Ew� ���&���V`���-����=f�gj�Ygl>qT�M��5�Ph�5��u���!t�"���#v�(v���>��}6��tk|�3o�N�n��M��&����:�:����n`�Gj�!�X����yh�RM�b�Y+�c��'�p{�O��n���R�>k���`
�l�S>om4��/r�5f*��O��o�\h�-r-�r=[r8t����I��q��Z�����>a�'�s�&p��g-���
��5���L�%�c��w���'p�7@(4/k�������������P
5(��Z���c9}k��.�T�g���
8�t]��5��C���
�����:I��}����$�����Lc���\���,�j�!m.u�>)@*=��\a��R��p��*vV����7����?.�{h��]o�k�>�A��������k@�o�N1����t|�c������}��
�������h���}�J���P��>�T�Mq0���c��>�xj>�zC��������%���(��g�P���yg�D4��ci+����������!���Lh2�����~Z�\�:MJ���>k���KK��!��4*�-Jm�R���J}2���1���)m.�R�p��]	�g���R�� ��M�8e�J��~~��gm��V_S^<c���4������-���z���}�
��9��&���V,�i�9�Ks8�i�`��@�	��ci�b����k���P���$�5�w���l?,��f9 ��~^�R+�<U�;-�q�B��}�}��{�.�.�T�g��g���[����R��G��)�:I/�}�J}"
o����E9�Xj��|'����i�����
�����c4�1��:a�
p��*tV������p�yY����`Uo��~�}�f���-q[$N���AyM��}���}<�LnT��|���b�Y+�5�[�8&����L�i��s,�b�
U���-N�F�D���Y)��N��#%ls���r*_�����E�	�Y+���8�i\W�.�.�V�g�������W�	�&d�J��lSU�����������Z���V����?0�������~`,��t����e+u�b�?,���&���yU��M�}�B=���\�g�w�K���P��Y���.��������g���'VN�z���Mg�Y'j7W?gr=vO�i���Y+��N����w��I1�������3��'�41f��b�
s�Bf������C�x��:�<�.� /���.�.�J�g��O���bm�i��[�s[;�\�;M�����>�����V���m�b���i��Ik���l������nJis�3��J\wX����L/~
�Z��c�m.�V&�MS8d�*���~D��%���4��Cgm��g��Bv�G��g]�$8|���y	��g}�'K�+j��5�1�*\��~��Zj��7��g��6m���zd�{kpq����
��o^K-�np\���H5�Wo����b����O����,4�������������eX���#��>k�>{��c��bi-�����<���n�B�3o�N]�s�3�����I:2����gK�,���~�X�'~dq9\��B�5�k����D��!����
M���:������"���bgm���z���������t/�W�]��D�g=�y��H:����U�4!f��@%�2lH�Lj���i��Z������7�����eR��g-P���O3��t!����j�o�K���5~� F���K����Y+�s���X��;�v`�g-Pn���
��E��4��Y+u���I������t.|��2o�j7g����iR�$=��Y+�y�dO���-Jm�R���J}��%�th|�iJis���k����%h�qt-u���?�g�>��0��`�����tY���Rgm���)��e�>k?]�>��0��u�f��,�Kc�w�A�n��tkx�0�����V���x80��L�l��y��Z�O�K����I1f��b ��p,\����������I�u��
/O�>Z�g�T������`�g�+�vc�g��s�������EJ������t���I�c�����y+�R9%=�����iR�$]��Y��0�Jm�R���i,�R���Tz����`a��R�h�����c����>V�g�g�-]����Y;,���I��X�e����bUo���}��iE���d���>���6��>k�vn��i�����*1)���V�����YT�~��X�g���,�y����\a����8�8�C��=_&�P`��R�k.bR/���.�.�V�g���>����� �Vj���b�9��T��}������>k�#��S��rV�S�N���V�����=��z*��Mg�Y'��Y�I��������g������z6���&������r���lRM�b�Y��������(���Z��M�������E������tf�n�5!���3o��\,����6�����I�1��NT{���9��X�����E)�X��TjE���F���vL�+���[C��������v)���}���\(�X�j�!�V�������%�KR�U��6���N������aIA�g�w/�4���r8��mB���@�C�>k�v�p�}��t�6m����9�	�w��1��������c�N5�wU��V���D�J����I�}�B�;�t2����M�������D
B�/=���EZK������oync�N��M��;e�J��z�������Iz1��N��x	w^z4��mQ�4�Z��gN�u��tB������
�~���v���WU��N���|�.=O,41�Vj�(��W������m��Z}N���A8d�t��`�g�K��yg��g=>8�X��s����pmx�1�7U��j�/�&���
m�4�g�P])����G����I�7���3�"
Qm�i�
��i��r,�R������I���Y'��Vf'�=��_��R����z��J].J]����Z�_b���P�S�T�E:-5���R��'L?�4)s��K������~
��(�-J��R+��O�����Qt������dab�Q�,:1��:�����=���Y;+��������r��o?�����#|��/���_����_�������w5����w�K�}&��.C7����;]������~f�	�K��r����������r���eC)��K�q]fm�������:�a}<������������������\�\?;�?��������e�<�s����������y���?���������?_������������+{��T���K%�>u�K]�o�|�������
�X%���?��(���
oc;/����Q�k?K[;?�_����K�o�i���/���?~{����7����//�������(}|T�?������
�~�����Q�_/����}��e[>�V���?���!�Q��I����u���(�~t�����B�
�v��/��6�?���?�k���������gy���f�����k>\������o��.�y�{�����[{�5?����r?�����G�_-w�p���U����?F���J���������/���/`>�������]��
�\D��0�\�z9��/���-����j���z����/�;���}��Z�X~������"�,������IXV��f��k���
����\���
�\_���"��}?'��'��>o��?~qx9-����{���ei'��v�����?k'����O�����`]�_���>��U���������������jwK�G��o�?P_
�����/>N_
>����8})���������`]��7^��R������a)X�������������U�o����������s��9����{��^^��<�___Qr�W��r�.����V���//���;�������p(��u��;��.t��^�.��}R�_�������,���\�kt\�����_�Q�.`�{�;;���a������QwY>��e�V�������z_7�4|�R���������uYN����:yi�dY�/���b��r����������r�(�����g,��������,���uO\�����7��r�,��K��|P��_���r�Aoy}��c9hJu7��������os�����y�_����`=���z�}YX������/�r}y�������<�v`����|�'^\	��}�.��������K���r�(��;_n�r�(z�n��"6.���76��r�(��������E�������a9X���'�=��
��>���B�6�5������N���kM_>�;���<��?�/o��|)X���7���R������.�|)X��v�������)���L_
�����������������q)X�o����\�k���������=<.���|}����e���X�r)X�o/aK�r�z�W��`Q�;��|0��^
��������e��.��Rp����R�,������R�(z�};>�*�s�����;��`Y����_�Q�R�����P���/���q��E+,��?g����,������m	��;���������N�/����=���+k�Nl\�=��g�����o?i�,��{���|0B_�[����gyq	j���q\���������+���>)���+k����,��N�!��������Yd��������F}-X4����-X�����m_������\>�`_+w����z�|z��?~��
����x�\����-�����9�(���-U�����c�����~�e�������,��7����kQ�W���s����?���������-u�����1��A��^xX�����_����r*����y�q�ekY�����jL�/[����eQ���^���ga�Z�y���8��joP���D^��S���_{�q�Z��_������C�������)���������E��G���o�p='%��NT����7v��<=.���~��%o'���w~�m<���~�T�g��C��n[V������c�3~~�<�|��O/�$��`��Xl�����������pZ�o������
��~�'|�����-/_
�?��w�
})X�����R�*��7���R�������K�������R�B��uy>���H�������D2V�~y}�
�G�����a!X�wz�/����E
���{��5�u}_�`��-?�\~���}#�����������K����%�����"�.���K�"��1z�������������������J\�E�jR�_����0����������+�o�t�u_���[�x������/��z?��Q�����1a�����T�������f]�I���h������q��,����:k������v`;+�w�Q�4K�8y#�P\>�e~}y�+��Wy�����7B�|X��z�%W��o�z�!W�e}_�*��<�o������'���\����N�W��C��:/��������3��GM���(��}��)�
��������T���bX	M���D�a%X����.,����w"��J�(����K�,
��j������o�����_9D_��+������z5�������m���?;N�}��%}X����w�!�U`Y������.��7�q�����04����IAV�e�|��p]����r����U��Y��U����*���Om��U��
|��y{�S�W���$���*�(��7�F�*�(z�_|1T��7>)��w�I��_Q4���>�R�����+����;=,�������B$,�����sT/~�����������������r���~E�����c������Cq��`d~{}�z���������{0���0�R��'��u z=��W_����+{��GK��+��K��+�����K���76�|�W���ze�?a���_/��K���K���W���y�}��&�3���;|,|��������T��vm~�9�%���W��\�N�L\E��3�����p�%y5=��o��F�>������aY��o%��UdY��w���UdQ�;��@X�����S��;�u��������uXK���W7?�����=�������8~<����o 1��|�Hp�~8a�3��F����|0���,}�O�F,���J
��oI�����?^��=����o$���^����C
���C
�:�����+������X���p�\�����B��U���w������U�+z{s�*��{)�}YX�������}YX���w��|YX����<_V�����_V������,�{�/o\k��u�������z�������GC������#�e��_���ea~���(��e�z��lI��������'���s�\"Ve�q"�K����okb�X����T~r�\ >�b^?��b]�\ V%�������72�s�X��oxs�8��p�JU���b�A��\��;���&,���2�����*���iX������-aMX��{��aMX��}yz5�gN���gN^ua���>�������^,{�;;}�]�G!�}���E�w��V,��;�k��b�k�wU������wV��9���|+[�x���a'���]��!a=X��3"�_���u}_���z���������o\�|�������������#n����H����R�(����q)X��g>�q[��*:�sy~y?2,��� ��Y	�g�������(��=��O8�R����~�K2���{�/�o?�j�G���$9,��VB������%���z;�]G����R����
��^h��
4 ���y����qKfq���$��7Ow�{z�8X�b�o������(��;|�RB_;���"�����0����)a��TJ�������_���~Ir�mJ���X7���RB�k�8X)a��mJ�7R���tS!��h)!@/���P�B��v'�6��WiD?^D�����Uu������^��1GQ}�����5z�F�����^���hE�@o�{`(F�����89�N�����1\��3�X�G��1en�=G��_�I P=����V�nA�����2����U��l�-��nF�]�z�����u
yn���{�^~�/_�(_�\���Z����]�B�����.Ga���N,�13��kB�}3-��c�����[Dd���A	<��7��<2���Yyd6�]:���yx�y�=�Y�V9%���7S2����3>��/��\Y���&	|7���(���������Q�u������B/���fn[�-����p���'��D@�T��E��yJ@dd�I�$ ���0�,	�Y�����y^�������"�,�x���'�5

j��'2u>Q_�"S�yu
�5t`���J1"S��3g.�zL���y���7�r|(�+T|����#�[�CS�]>3J#SD��3)�)��;��S���q��18No�Z��}|�X��B�2/����;����������W������"�_��y��&aE�o,���g�J
yp*i*)D���������]��%x~�(����3�;��x��<�����1�@�:��������i��q����|g���C^��H3E���f�N�T���c�����L�C���[t�'�@���S5x ���y`2��+Jx����q~���t	����C�?�e�������oA���[9 ��n2S8 ���D�"����z����n:��6���Da\��q�x5��q��N(�����tB�D��3����O�';�	��;���	������&��Q���	|7J�2,h�s�}*�y��;'rB�62@'�}c4���(��������d3��U?Z�s���{|g��!?1���9!�;-U'l�UN�=���u���ns��CmsB�_�������(��9!��O����/
��8rB�~{R�U.���wN7�@z>6g�mjx��E4>
���:��z��D�@|;*Hv)
�����@�p�f�����72������JQx��.���BN�(>����r>���[� R=�'on������rTCJ��@���?��[�n��(<�z����n=�h���A��=,�[�zI��pO��3��?m������������}�����/�������_���������#���/����a��2��d�y�8�ZB�����M|i/%4	��[��x�-�F���f�Zw#��j�W�o2���E���	�E>
�M�efTU����/x�����[��552��k|J�LtpD��$�����o������A\��������tZ�F���5-��ZI����G�4^�
Fl�Yy�����,>y��p��ge�?���'����Y�?3��d����$2����d��t9�d������''�r�����u	�@��j�n���MQ"'������sA��H���+��;[��������<�-��������?�TQ��eJ�D�w[2}�Df�{fp�W3���
f���A�3�Y��y�"��q���wN�|`��t�f��k�J�a2�����i��3��k'H"n�"�d�v�d�l_�4��
i����kc~��;�~��;�I�e�]i ~+o�B/��� ��K��v��"���c�:� �D�\g_��C"x�i����*^�C������`��J%����1�Wm3U���gp���Cyc�������\����b�6���J�q��d���]6�A�cu� ��,�SkZ&2�VL'�K�
�I'A)9�<�����z>��l�U��N�<�U3�l8NVR�{C~���q���E�]a�u'�~��m���-���Hzc4��d'���	d��/,�A��7
�XN$��~$����|7�A���
��^��S0+�K���a�������N�W��|����Wb_:�1�?�R1+�KFn����+��'��\��D��������0=�~��|u-\����s�03�����;��v
e;<
����2��uxF\�;'p��O4nI`�^l�����(����Q�h����z.��Z�S��D|5���ZI��������9[��������E�����v�if��x�PD��K��d���1��av���]�'&���]("�/����"&�by���ee5��}7r]�
!P���1G^��������=V�{6&o�4v��;$����hXya��m^��M��r{��}��=�4��f�xA\�@�@��pUT5k2"�;�h�����.��	���!96G���v�I��1��m���
�
T2p#���!�Fn�!�|T�������W��w}�W2��|Xy%���}^ye6�.*�V�-��������d��H��i���6
��4D��z`)P��T<:����
�gIw�
T82�t~\�&�X/���&���
����>�'<uk�8!�Z�T��0�kH'���-��N$��h2�>HO*<���N��'������D�.*��+�r(<J��5��/Pe��TEf�3��D���y_�����Y���#3D��c��!���B��|a�yDf��+cZ"3LF����|p��+3��k[� �N�=+*<^�]r*P����x*�KN��3r��s�C��'p��V�t�^�7rA���
��	zg��F
�s��!R@�<�����W����@w��[#W(O*���&
+�}��A\����X��~�����g��]�d����d����.Pa��e5S� �;6V�"���>��dZ��x�&#7
�D���t�������3��3 �|z~�1�/��������B@v��)�e��D�s~�
�
�@�q;�n?��a�F�A$��1����d,���H|���^.�|F~P$�>���*�{}s��~S&�'��Ls;5�u3y���4��� ��a�� n��SN� �O/�>D��cH� �o�:PA�*���	����`2r�E��=��iS�`����B�)��S�h.
[�Bq6b\� �� ���O����Sx�l��4\�T���\X]��T���cY�O�D���^��>���^���_vi����1EN�>V����{��A�:���]*�w#ic����7�������E��{�@_Y�.�&����!�/����i��<��d�]���O�1-��]9~����7���h:c.<g�x//)Y ���%_�"�p{T�d�a�	"���/������"�x�4�^��JfM
!�5):��,�w+�2�j*O��F_f�Y2���		����ty]����������
����������t.��>%{[a��~B��i�;�2�l��
�K{AwN�e��!��0f�b<�Vf��|m���#���y�}7]^�g�h�Qx%#��+3d]��EB�Q{��������N5�d\�9��1�z]}�~�h�B��h'����q`����cO;������tUq�=�uo���N�=a���)~rk�	/�$[��_I7$�71���"��!i�����:���y7�Lg�������jd�����|���"x'C�l����G>}l�������=����2S�	��x[�N��(f_��!n���O���'4x�����?Q�7f]
��3A;���t�������cs��1iO�m�������	��������,���^���l��0�TF��A��Y��*�����E:��� �������:����1�����&5���i�t��n���9;�$A<@�O�<�]�CF����{T�n���s~�	�
���q�������G����h
� @o�l�@q2FIf��>�G��	|��Q�%�Z���W��gH�;��,@\���g��&�kGU���<�F��@�p3.
��H�|1
�j	o��t���C���L���R���������C��FK�@�����%������G�����g��*�q���g��3���M�p����U/����?��a�{n����YH�o�8�D����_qB������w^�$���ITa�0A�*NT���	�-�mu+������y����	�f|������Y+L��WA�L��7���2A_8�	��]{��\��&�|�7�����;tA�v��X}���c{b�<�w�9���9�R ���9����W������v���>2G�r!�^�����~e��)���M�v�c<��
��9�]���k�{}d��3�'����������+�?I`��e1�*�l�F������w��G�;�L�����������E��1kk%V���?w<�k���peg3��uq��Z|;�x����t6�a���?�z�]V��l��S>#���r�g�M���dK���c���x����j�~9��
vy4�yx�D������w�)\��Ut�j��Q���p���al"�[sZ/3g�����jl4c�i�z�_���/������y���.�V+��K������i,g��3�x�f}��y9=I�����	�x�
�/�+za��nyg
��Txb�=3�?��:N9����
��u��"�z�^s<�\�x�Z���������W�T"�;{cP�B� �7"�����D�?�S�@��_�i���`$�=���"	���G�����/Gw�m<�@_��zv"#/��)������1�U}~d�59����T���k��_�p*�n�[�0����
��kS�� .����������2B���S�!��c@��|��":�7s�qR�L"�Mq�;��8���{��}���Ao��k���T}�F\��d��_�j�>^woLd��H�]:B]��~E �($2~ v �;���)�Q�y� �����Zd��%�����c���AX�@���*��r ���k�$F�-����{�qN����������r���rS/�R_9��Cp�'2?�)��V��/
���0buxF����x�������x
!��n�����d\����}���y�#MSV����WFud��{�t��������]��$�������/���d�B�|�U�V�G���8�t���tO��5��N��J���������9��d�u2��Gk���]�����>��,��W�@�|nT9V���PE��x�z"{<^w"{����9d����=�_��O��7����>7�W��<?X��W_����^���(�k���t��k!�/����"|c8F����Kd�>%(�]Q�=-b�~`�
p�E"��@���������"|k�1�$��TO"?y�|B��cf�J�����?Y��W�jl�iWA��Z��_���0�s>#�Z�\2
~����L���r����
��D��]k
�\#��T�d;D��*Jy��d�s����V�0��Z	9@9����<F�������=@w��,rA�h[hwI!�al+>T.������'!�)^$��������q���H��>3�}����n���qO����O�;!�A)|X����E	�T���
�0��]Z��
�����|��I��.r�����@���2hy���-y?b�v����'��gz�y�EzL��Mqk8���&�N���"����CD6�jWr�DX������S�1����4^�/�,��{����Te�SC_���	|=�a>5���F�����p�v���U�D�B��fdW �&�:*���o=�A�;�U5����{����l/�4O��^��L�x�5���
�����T�;��Q���mxg?r��&��[� .��4����2�_l��F/�����T�ss~�������4M!����8�@�^_��q2�%:�@^u�j�	|zr�S|5��M�+��h"g��n|C�+�?��af�oW�Jc�;��$��d�������������y*�������!��(�������H�p�8{%�?����S&����31�vHA�<�B�W��*�K�6�C!�o%I����v ����@�.�i�����3�?�^�q�����:������@�x����G������	|�����Y!�������R?�#��iS�/�QR���S�Q�^v6gF����s�5���l)�8M3�S+�^����^���T�����%����7�=��3�}+]��A��8���Y{�����8a\�����J#/��������r"o�w�WsB�v�	�z�z!����.��I"�����I"��O�=_���dDw4��$p#�?0I����$|����$|g�L���O��aB����f��?�Z*�����WaH�C���aUH,5'<����5'�o~�3��55�q��I��m|�+�D\�%����b����wJ+dd��zJ+���~����w1���`^�c������� �����AF6������0~��[sZ��j��2��F6h�2��0��l��Ng��|�t�l��c"�]uB��
l��g������y��3�q�;E�
������
�����l0	�N�'�)��;���J�f���i����������q�~5r�el�q�g���]��"���+/D�.�i��������np8���45!P�A||k��ON��D8�.�>��)�����{������ �njB���uGO4<L����]G6}�Lx��������\jn
��������o|���S�	�����
�������������O�i�<�}u07�t*L�m������3�H����x�TC���L:���g��U�����ZVC���G���;z������Wg255�D��&j�@d��'�R�3A_�����&�_p��C���{j�aio�}6v9V�+�K��F�dd�c,����^8�����Q]����|N�B`�l�).��!������!��0'��w�c�_�����F�FC�p�q;d�y�����5��/4�B����C�aW�����il�����?�������B;=���� ���|��
�@�x�g�ZQ)��G�h�A���c������w�t������=�^:�/���|�Y	��egsn�q��RNO����K�X����[���G'�;�������t��7��y�b�������Nt���a=�X��&Y�s��a���/�i�bg���������_�������_�W�>?w����^o�������_����Q�����Po�O���%�\'��CWo-u�����y�����x
g��y��d�����z+�Bh]�9��������n����r|>^�V���6����c�x9\��8)���UV��/�t��r87�������.��������n��7�jn���3q��E������GX�����ULk8�����y?[��m!�r�t�m5?[�z�J��	��)
]?P�+����������[#_��Lr��F�Sn�*�1��i�q���8�gB�l�I�Yt���96���[������?6���g���5����:N���o������>2������Ss��g����?2�����[.�sUq0�l� ������7���.��Ky�Es�/|dB�v�'?*8�z�����h�x8�Q���87����������po��-���I���_�b{�<yV��4:\.�&�j��S;�V�w�0�0�jA����XqU`5)��ltjA�V�V��|�9���W�q��M��p�C�*���H�u�A8���w9��~��		���5� �l�
�����Q8H>���~xH�]��I>����)�r�����S�� ��7���n:U2Hb�-$���0d����AB�d���?_����'��u:<�?�#��w���������d��If�wk�Xe���"��/n�W��Af\=�!� �q�N�Q$4�c=;j�~~�5�[z�T�����7�
��w��8�!���������U��.��/����k���"65i`�
'}��X����B���<���`q*����m4d#��3�
�������3�Kn��������g�GQ!����#�
8�s'�"�
�5�x������!����e��c��L���-������R��;���A�z�	J!9�*
���k-JF���*
��u��4�iT���4$�NN@\]y4�m��?jrBg�{s���T����b�����H�*��� ����t@�FF��5���J�kt����_�\�|����vUF�u4����Sn\j��@��~��<!�����������K���nY�#(��g|k\����s>
H���"#0�0>_���}+�%UF����y�UF `�Z����v�����+b��=�C��1�H��2���Ye^B�^��Yp���N��:y���,�fP��G^e��eAF������(#���n�UF������}b��Cc.��y��r��X/����7�r���W���7�I9`\#G������p ���d�U�/k����c���U9T�j:(	�h�P�����g�7> \#������W�W�x�
Zo�.Z��1��m?�
BS��������I7����u_��
Y�|;�)���w������A����$��j�B����u���$!V\��p���l��P
zm\����=�#Q5H��|��.��J|j���XhW4�l;�� �����F��Q�T�d{���l��V����QP
�1����B�t3���y����n�_��Yu���8����������U7@\?��q�y��Ag�{c���$w#
�r{��}��{���_W�1S��.��i�T1puz���5Z�5S?�A��>b�e���S~�G|�G����0���`�	�<a���~����
����H�B���T���=�(D ����K��CA������U�H���,��2D[���$��2�)-�c�ob��jFE���iFEw�����n�]AT$p=u��H�\/�l�s3��_Uf��E�rm~FE���'�!�r=�`rY�o�������cQ#p&f�3d����u���F n�,���
��{������E��<�Gc��3������Y��Fto����s�j�����p{�3nsF�5��UsF\��T���q��JO6Y8�F{z;��������z��|B����SPr|2g�;�9c�G������6g�]��}��ugtu��A]U�*t
�Q8H��8�A8���p�]��O�x9�x`��/ t��rFk������(�Z�����D� 	�F�HP����<!���� ���������V��DoQ�����:22���j��ch����y�:����U'���7��5���G���Y�����#cc���QE�����"��U4� $�9�D�'��@uE��R����~	���j�p����h�F�vPp��-����o�f�V��t�i��s�~�|Q�z�/����y�-K��b��y���V��o��E�v@�����v���Z��i}G��$��j�%A-`�'mTp��!�����<pg��A-���[2G������AuR���:��]%/����y�A-H>d����$����pl!/
����QW8���'��7����"��eHI|�E�%r��* ����)n��a��W!9�v�A��
�7Z�n1�f��j]q�]���!v�����A��
�;����<�^�U8 \���V(p�^�.�<�+�Qe�g=_$�<!�u����WN��*����n1d��OVjeB�
x�g

��cu��2R�����x2�l�����CC,��*���/V�:���3nPxk�uAA�M��Y�WS������i<����u>�yQ/���:)v�/��("
�|R2v�;N
#����x����o��~)W�v�\TP4B��!d����w��!p��q'
��\\Q4�� �G]�x4���0,B�\
�3n���F
�y_�
�j����c��Z.�^<4�]��#����x7
����2h8�s���j��4�b��	����6�k��{�a�QO����g�!�._.[������@$NKPp��^T�����+�d!VG\��$�%�;$!����u@�����b��(!���.Y�-g<-	����%\D�y J8���Dk�{���9�$_r~���:VUBH���\d��#!�[���(�	r������j���QU$ �1��1�U� 	x�j�gOW#.���4�x4�M�+	�Ag�{c��� �{�����e�x?����a�r��]�E�������	
���r1���� Fn�E�YP�\��g�	����0�{���(���tR��"/�Q����U�z�m�+}"����v�,�	|��N�O�!���T�kd�2Dm�E>4r6P�!��j�Bp�~�|g��>��j�!p�9A�����g�Q'Q���^8���f@����K�v�O��dp�w�!pV��w�!�3��S-�����{�fdHTE���M�"����)��i��
4	qM�3���#z�.��A��;��I ��<��x�np}|�_W7L�c�
W����]$\��4�.���+�(��Vz!��yc@W���N��j��s�1�Ob=�����m�H������D�]����$yT�E����+���&w�z|�T��x���u�&�It���$��G(���m#���;�	�8� `�2*"����H���OBpg��zp	��f��n��� 	�+]�	�����t	�ARug�}k��#��62;9���t��]�����d�H�z������M%�V��'[+���/�N���7^d��������cm��q��E���q��������
��Q��A_�*����h�C���k���'���"��]5�f��4$��p�<A1��^;7���Tm�W<��[trP���G)���$�{�4`5�K*�6��V8q�)T� �p�H6H"�j�P��X6�^�}�
p�����g[1�W�C�9P�^��h\�O��:�&�O��fP�[	VQ/��\�?Q/h|��d�t��dD^���!9�z�DM7����.7��n�G���@���Q%�&��$��$<�~���������N6H��j��
 ��V��+n�Mx<��@L��Qe+�"d���c�W��U: \=-�J�k��U��'��"P�����x�
�_��^;)�U:�	YX�E:��6�u�t��o�t����o^6X���t����iyR��F�C�H���I��7p��h�%��0H�-��� �1���K�o9���J��]yu� d����T�T�����$��R�� �Aw�t�Q_:`��a�P?����o:8.�_27��������KY�&;��"G)]���>0�U|�W������������b�\��3n���F��t���J���k��fAA:Hp5���]u�t�]LX/����#S"8�:)�����[?��d#9ryoF]n|��[�CD����J^�jt�;}���#���K�`u��+�Clgd�v�o��
�/!�^�%�d��������K�3t(J��z1R�p�X�\/W�s3�N�����k�!$JLT
+� !��O�UBHSv��b�CB�?���"!�zH�aW_����l����So(Y$�~�U�Hx�������_��{o��n�$������v������k��F�@/����a��2��/�&x���:fC��5t$\=�!h]q���k�����������Q������3����Y���-��j�H����u�����$�8��3��s ���M�'���qW�*G����r$����5dG�M�#	���FP9�h;T<�zr[T9p�����r��u� �8�F�'unF���O'���dw����Y�//���^��,�D���T���0i�2���L
����E��-&����T�)����gB�K���h1ql����)�����0j�7w���j8�s����<<�-d�����z�����X�����-���G������\�*`�_��"n{G��a�H�:�	*�e���6�cr&����n7#�?h��t��������Y8�3�����*��{p��z��|���"xP|��pA=H��<�����z���A��T����R4��W@��8|I�������'	x�u�4
	��FO� $��IAH�	Y9�QH�s�3�N����%	�={t���}k���-Q�Wj����b���&���l��������w$��~����C������#ptE�����F�A�
�Xg���;�	�QhqlG
����\A������������\�0�g�����Pu�W��A7\�Kt�5���n�g��������B��A7@h��}�
zm0���2.��
A7�M�v\B�n���u��A7�P��E�	�u�}���k>����-'I-�&�I��s:W!V����DX��$oDy*����n��cQ��� n�Zv�#sPp-��AE�I7���"��,_���'����h��26c�b�(�&�������s�T�T�s���dF�����s:L^[#��7��$��XqURe+	���L�cc��<%WNor:�'��?4z�N�������R�yj,��+��������^t������~a`�y�B�*WL�B�+j�������{�������]x�=&}!YG��@���4R���@�E_@���R��d�W�x1q^_�j����&�|�%/!���c���u�����C����4e����)�����F���!��~�CuEu���7������Q���=����z�P��x�W#[!|��r��Q�m#h:��l��X5t��W�!�0�'��I0Y���)Y���G�!E�E���D�l�6N2C����{�0&�!	��'$���Ih��{m�
#Q~�tHF��P��I��`<+���]!�C������&�����
%����&���C�B�k:% nW�dvm��5n�UH&�(OZB���L�O���Z��a]��������s�t>�����.�u� |9�*��Y���l�4�R���������l�5@E� vR`�v_e�!~�4���.�x������U�**i�vR&�D��� �6�AG�SQA��^8�}n���4�m��t)
�� �Wx��lT� ��vnB��r~�
�f;$46�����F��*$��
W~���~fl�d��[c�p�z����V���h��R�����.�Il���* ��.�����_�_�� �p'~C��	�5��cc�k����!"���t�]�o������������yi;6������H������H���9sulD�w���@����������P���;'&�x�WN�J�#�(�bA�H��j�4�ixhz�1$���#������ix{���P��;Co�E�z�Kz)�H���T�2D2%�3��R�v�����G� �3E���F���3���Gm- �n!x���d���h�we�#p���S����R�\F��896�OW:J"/���y!A�{���$����y!E6���
V�����o�k:/�c6��'c�����F�AUW��AE\��,����op���nxN�h.p�S�����lx�����U�p��� ��GT��wN�K�p���� �l;w�(�|�
?�����&����n[���U>H����i�wG�`��1��w�*�g��*�B��3Q>�y6�,�?F��pB��fH]��f�|���5\y�|=~�����wcKN[>H��Q�0�gq��E>�u�q>N-\y�U/�Mm�+$_Y��z���;E�I���4{�=�t�_�@(�A���M�.�"��V�t��F� !�j�����~��L��0{B��"]����W�5�p��IA7��3��n�s���(�O���t�6�f�n@��W�B�2������������Lv����'�f�r@�;/�����>��9^up�C��Jz5v�}A;�}�_��v�EU����t���Q��d]N���C����,�tH=����2A;�	Yv����B�C�T/����������%F�x=��	SD�)�o�SD��q+ �H�+|$�
�x�?c�y���S�W@0���<�;���� F�
���o��{M7z�7���!c�+�w��	������ ��j����������A/\#�2~��}CF^�]���r�5�j��� �Q*�>�V�Jsq�'}$h8)��U��\�|�������u���h�����[!�KBo��#$�n��4���UG�.9l�!�tzu�������#��X��A�%42���/��Fpj�W�'�8�s��tT�*	*B��wL���S�?�!A�}��n�/NE��m�"�:�|H���X%����J
I��%<0z�����_�|���Fs�*' �����X7C
�rB�l9!��������+'���X����UN\��8�	8�*;
r�.{��^�\9��`p��A@�y6�&���k��28�[���2\���ao_��YmGY�|3&��#�e�m�|� 	O��B�`�yCg� $��O=H�E-"H�����*�1�#H�Z��d�;�K�^B=�&J��zb�p���B��uxy��Y
����WH�`������l�L�^^$�t1m����K�A2f9A��d}��������*��W��* E��7d,�
�wb���;1f��
Wo
0$�M!�9]q�������x��PD��</FBv�	��c�k�6�����WtQ8����o=A�`�d�b��/F��y���=CM	�.��XW�xAu�U	���c�T	���Q��*��;';(�x�W�
DP%�h���"�(BU"�����@�����D$��W%�$��BT%�0�.��0���#�^�<!�>-!���D����!u568�u	���m��K ��5-�.q����2��~_�>#����atX�8�>��^���(�(&���w�$d�60H]qO���o��n�P�3���v"
�v����1��n�����b��!�F��
�:T�2�-�PL����3\�0�4��1������:�	�vqj�Es�{p\��3�B�N�����^�#Q\�	�i_z������!3��9��1���������A^��u�Cy��n*�0��$���B,F� /$�j��*/$��OzH�����C���1�5� /����A^�S���Ey����A��	1�
N���x�v�j���`8Ey��c{<?S�Y��WF���r���������7n�p�n��W#��#�,"�����D���qe�������wv��z��� ���Q��$�^��~CzA�wu%��\A�����^V�y���������=#���g�p]����GkN��U,��3r��X�s��^x��V�U, ���
]�^�U�
�l���kA,�)Y8����mtA����{b��*�_1Y5�:�u�}���?�s����wT!]����#3`;K!��v����[ `#�����d)0���&�y�U�n�8���2�_!�o���8�AQ�s�vt��(��mi��@�+�A��5��+e�/�������-��a*�����
9%&d�z!��+p������EW��b��l�wa�N�Lvd�R9�������V*'����r����-0��������7�-����U�2AN�.rB��v{ �%�k<�9���rB�� '�45AN��������+��=�	�2�{��lo�,����T��o�V���.���o�t��B�/t�}Q6H���G�l�D?5���x"����n���Q�h�����[�z02��h�;C����/����:�u'�F��w����pi�|x��
�W��
Ru�r��z�	d�pa��	��I������T3d_H���x8}�� ��8N���*�x��"���	E6@\������l��$[6@\����]q�lp����H�]���l�������4�l�zifpF ����PE�k��8�z��( ���/��u�h�s��*�M�D<������l ��s|3j�/��/$���)J	������l�e� 	����4�c�'���^�Q4����GD�F?� �"���f@��rC���9)�A4@�M'���i����;d��,T���_�|
�?@�@(�H-e5�Jx4���*�Q�_%�������~/���o�����:h��R����$����X�e���������3P|���������������_�������_�%���yq����#���/����a��2�+�KSQ�2�nC

`ne6���U@Ip�<�Gk�G�`��[a��}B�E��d="�(m(?AE�����*
@/,�(�r����$o=�{/h(����4\��c4�d)�xJ����?\��b���N�����n��J����6�b����������|\}=��d�����(�������f�<��g=�)������$�HCb:\�!#�)�R��}�S0r������ �`>=%���9�X'[�J����y	��q?4�ynX���x���B�7c�������C�Fg�"� U��h)��x��������UJA\U�-�����5��|-�Z}?��W����4����KzeX���	Y�<j����P�z�T>
����}�z�d��J}���������q}4�����e����h/���O�
C^��(���
����i�v^.�&�zd�j!G����Ce�p�zY{���'�5O��d��S��O���7+�u#h�����-����$C���W������&�E�3h��4<����.�+xW���s5�����Q[@��!9Gm���j�9KfL�5�d\�ld2�����;Kf�;-�/nM����!-q�g�cc�z���%�x���Cc?�������{~�}���s�����W2�������?R�����V��p:�?Q����M����H.?q?��V���C���b��C0�^vt�~?��6����C��OEA��:��C�2�^<J��,:�o����C�|[zU�h ����L�	�
����H]
*�/^���Hyk�����6����RUw��+�6�<�b���G?�����H6G�D>���x� �x�&��
m8*T
�����F� �T��o� �et\
"[H���j�3R#��}�����Ap����KvC�asUf@~{���[0�<E�`\����:t����B/�(*=�8$��nF��-�f�<%��q���{s�d��(��
~�����++�F�j�������6\%����z�`�Z�p����S����gG-��V��RA����+	��'s<(	�l/��J���|�Joq��F���#$�d������z'��B�!�T��X|��5O�Uet�Z-��:����0��#�_`t]:B��Q%�[;�w�� h�%(�����AGH�\mpj���Gr0lc���|)+��OV�)���<�o�����0�6�������[T@v/_�����RA����~�L��M*����
�Q�E�$T��B7lQqeq��
�����<�**to.G��I%��,�z,����9�QQ@h�B�6�DAQh'�5*
m�[������N�5��N�xPp+}�*
8�N��(�r�p|E!�q��-p$q��_$�p��T4��q������89Ub��<�����KZ�	�Qb�ni;�*$A�K�B�Ab�P����n�<J�t�;Jd����y'+���y�J4H�R����_�j��9�kEQyg��,�Bg��*�GA7a(�����1�]T��;:VU�3���_�Cc?�$����f[U��[U��S ��u���"�������_��/���G�a'~�JY��v����@���V���X!;���b*4����6t`h��"Jm8�����x�	R@;�����W�2VSH��N��J�q�F^o�)p!��E�)p)�Z�j�������6��i12pB�.��Q�'���&��?�|���;D�$:���I$�Sw����}p��&��]�!�@~�A��0���&��K#���M��9�.�&����#hf�5L�$p�������(�}�4>����Y�5zu>���o#��sR��&v������G����;A�@\Yo����%U�H���_ �nJyo�[����Eex�?���2��ha-�!1-�u������Qk@������^;��Ak����w|���������+j�m@pk�Cj���
v8?������������:���S���)Z�lt��8���^��/~=�cU(�*.����T�!����F�~��������oBw���bL�H�6\����K���<4zK��=�tB�ql���ce��d���h�B����CG�]�!p��w����ur!�f�dC$���H���
��w��6��
���R�!�Sb�	x�;7�x��������0�G2_�l��?Ru����:C_��3�wK=���p>\>Q5��^���Dv�����+�����7["Awr�dh��^za�N�KA[�kB�j�=Jx�l�F���g{aP���@���8Z�;(��g|e0� (d�dk����������J-0l��Sk�[:o��i]�����Z�'UP���[�^��p`h�6W�0m����]��-���"(�YtZ]4��$(����:X��AP`���H�

�'��p/���F��G��G��z��IP���+(0�z1��p�E8\A����������h7=�q}'��3��'���7���d_�`�p>]�b���vq����� Q;@h=�.j��Q;@�.�-	zp���v��]� 	���Q;�]�5d���2.�����l[o�A;��X� �� ���^��$�,�8Af�d�4r��;%����
������U\�	��S1��'B�-AEH��T�4��^
����=�8��9lQEH?j�����F�PT0`��f��{��f�<���"$��e;����?AE�PhD<Z�������w��o��O�O������7i���" �o��gC��ph���q��4�C��,�*Bg�{c�K��"t��*�3�n���Pu���)�~��[�AB@����B�%�6nAB�w:��*Y%�^:��AB��K���I�\�����hL%�����$�d��B�����dgx�E!�&N+�( ������5�G6�<�d��m����[h��� �$�.
m���#�Snpl��N��Y��������|j��7�s3�N��������tv%����w��(d_a�E!�$~5���A��m��\�e�
��pQe�����#�J���=���uH>@��|��e������I#U6�������/o����E�����sw$d�����iX%V5p��\�v��+6�x��A�y�:w�udh��$�m����V]H�!�)�
����������4\����4\�N����N�����g��Q!��je�����oP,�����g�~�O��s9C��<����V%A���Z�U�HNk���tS���B�)���3!A�����0"9JzUe�'p����'|c$�F}����z�D�)2:Os���-���9��sYE�3^�;.C�����1t<����L����Q��x��������R ��y��[������e ����_y?T-q]�����y.4���<�����(z���98j��>�@ ������f��^;���=��1��>����������',�eE��H6�a"� p��EH�v�9�R�����������������O��A��e�9.�A�H���C2-�C)�������
A�*�?��U�}c�����D���aP"Z��E%w���'*��fD%��zg��Dt��E%�����JD��F�LP"��4*7��Aw1yM��n$�m$���
���J��E�,	��P\�C���Y�n��$��e������[YHX�����w�����������{sy}H��
 /O���j&< �.T������TP��L������&�m5p��C���@���v�| h��f>��xq
���Q((<�'��f?������<�o1qW�!�%[��/�`d�dkP�P���X���[�
�mT���>��t8-3��������D������n���`X�Wm���7����
��D�15h���_�2��������G����B�A3d��-p ��&m�w��YL���FE[`���`\���q����-p�Pq���{X���5����S���@�Y��W`0�_����X7��Y���.�QW9T��+*8\��6*���r��]�����s�r���]��������yn
�@[����2:=L�r���5����W#�WS
*��8�u�k�r�����RP��$�lw��$!V���Z�|�����g���9��:b�����LX��Y����?����D��# �N�z?F�F����8��f���#$���E!��+���;0r�|�,�Y
��B.Z�@����0�d\9_�j	��AK���W*�u4�[c?E��������%$�[KH���% �o�7j	�#mWKT����.����vXnZ��BB��HQHh�#F!�������K��}�]� ^�����8Xm"�����+�{e�z��g|�t�Iv�y��hb�,
2N���PL ��������eB��S$��O	a�ABH��^�W� !����$��������J7���!�����,^��� ;X�'JnU	���Ru�|������W�W=!�^���r�h�P�����z~*����t�W~��zF>�����pi�����u��Wwj�7���;d_��3<�n���w�~��h����}:��W}=�i��T~���$aE>W�D�o2���h��N���D�?p;VO�7�B�2���]�(zp��������ZOb�06a��$��q�����2nWQ���,��|$K���,���E�U��bMJH�@h#���<�s��+���kf>j�k&C�JjT<p7]�&pg9A�H���4q�}z���s���z�}��fX\[V��;��evg^_�yEB��N��d��F����m�B.E�����c�<X,&��,������?�B���A��n��������6�����P_M&YOa9���1;����Q���,�������sco������Z�����k#���\��Q����5���S.F���?�j�C5�$P���o��`T!���
��������c7��tn�Uu h/1��m��W���
A����s}�Uu ���(Q3.x�,,I�p�l�����;pY:�2Uw���^u_�.���$��Q�Su�6�Zo�s��FZ��2���C���m��W���QO�
�Cm�>��QKj�A��(H�2�v�Ab����6������W�Z���3�lKI��������Fk�G�������,d�����M����K5xO��=4�OF���(�|B�)�,t�"+dDw��d���I�2d#���������_���)yk,����C���Ec8^>��fba���Q`�N�����(0 �V��(0��`/m�����|z�T���NJw�!K���J��#�9J8�V�G�|3���Cq��9�����d�f��E-�����EJY�r=k����������������,��#�� =t�E��u��(=`��U�(=��q��C�U���w1�(�95�����|x���?�Rz�.�Q��o��
��qG���
��Fe�A������,*��<���QU�dc�*D�'��������<^�0�q�l�Ks?�-3;�����[
<:��x��
�����9\yP�$�R7A��U�p�Dm�����- �����+��- �q
�@/����-��6&$h���?h8�K��A�p�7�g{�|=>���8k��o=��,����t(�r�]tU�YVe'�C��lBtk�C+�8�y�2��S�P/YQMH?��CU���EM���'sE5���Nr�r�e�y�4\FG4�i�B.����d��1��T'���LS��X���
����>[@�o����?��E�
�+�]Tp��s0 ��U@@\�i�
x�:�Y���   ���y�U@���g�`W@T��6��������'n?w��3�����_��L��y
�@F��(+ �1� +��
;������q�����j��Kk��E�#1$so4��O�%���*1`��d�P!�����^��oE_#g?8j��������U�6���/K
�F��3�����jvykGs��>���(/����������\����yn�����%#A^@���SM!��F��9[^�����'^��a�P@�&E`�;U`�P�[P2a�-(�C�R�=&��
�������[[>�f"U`��{o�����
]q/�����_��;�����&]LU�+�E�u*i�p�;=��8F���W#���9��o�A�@h��2��2�)�8�o��v���BM�ak�e2�D��6�� F�2�����m'C;��x��v
�~q|Q�
v
8-z�p�k@h����<��l"�(���}���T�!�O���>5�6����'5�| �)���J�X@��gf���N��P��*��1��Oz�����zJP%��6s,-�=d����.���/�d���I��_[�3�����c���'t�O�������<�]37��`��0������Cr:u���<�3��xEfK���5W�H��>�<�>���s7���v��$h�82�[����-x�z�g�Z�	�O�q9��Ao&�I�v�fUz��v�_����i#�E�_)����DF��'l����X��_��� Jd�l����Dcf���h���)4��C;
AK�N����?m�*V%	��"I0��G�C��<A������"��vfAo�R�'�������j�
���Nf�<�K�.:|�gNP$xe7�iL09�����k�{?I���_���r�HI��<��$�����d"��<^�����F���d�l��.&�!C���If`������X����,2C6fuo��IB>��&3�r������N���1 ���5���������m=h��t��Q���F��Ac���(4����e�t�et:��z^�Nv�<���bP|�������E����YW+.��C��{a�]�Uk.N��4���4b�
E��G&(
�"�+���[$n��4 ���8*
�'�D���n���^:�Ai���.�|�,��F�Q^��^v7�0��F��ceu����S�
1g��>dq�(������������e�p	��^=y����5Z`�r\���j
��}�H������t�Kc?��� ���Heh�3�I��\7]_�
2�Pl;><�%1WbT�p�Nn�H��.���'>F}��XF�0�C��B��/Q_����]>�[��/�.���RD}g��e$�������3>sz��l�$<�������mI�����Yx��]f"���!��v�����g+$G^7[8�G���lACH?
"t�:���)#[�����Y4C���%;TL�l��A����~��b4��}c��'x��AC�(��
��zD�����!�Zw���v�W���i�5<*���j��5���! �����\79�j����?���,��
endstream
endobj
25
0
obj
53067
endobj
26
0
obj
[
]
endobj
27
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
28
0
R
/Resources
29
0
R
/Annots
31
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
28
0
obj
<<
/Filter
/FlateDecode
/Length
30
0
R
>>
stream
x���M���������{�����]���n�8���s�p�Fbw8� ?s����X5�yr7���R"�H�"�_?���O������y����x|������������~�4��,"�-������!��n]>
��{����$o�������������Ex|�9��O"��6
O�3���?}�����!��o���a]�=��D�K*���k�eI����?}�?D�;Bl+=Y���^>@P�e�E�6.��s��Z��Zd�R�{�A�z���r:*��%�Q-�K�ed��{�A�z��y��^��j�/��������J�(K-�2p�����B��"K����*��,��i�R{9�?�� |�E�,%��T�GY�,o�D����?�� |���,sz/!�T���"3���9�A-���Y���^>@P�e�E�.����YA�R�,YJz/ �T���"/+���9�Q-�K-�d)��|��R=�R���W����@�R���W��J�(K��[����2��"��b�5�=��T�GYj���k������K-�d)��|��R=�R�<�\j/�-��_j�%KI����Q�Z�u�R{yn�nE�R��\j/ �T���"o#���k�w+��Z�m�R{�A�z���r���.dIT�m�Zl��5����G*��,������r������y��^>@P�e�E�.�����V�/��������J�(K-��r��<�|�"|�E^W.��T�GYj������������yK\j/ �T���Yz��^��G���bc��,sz/!�T���"O���o�n |�E�,%��T�GYj����<5}7��"K����*��,���}u!/M�
�/���}u! �T���Y;��^��G�H����2����|��R=�R�<��.�������y`_]�*��,����B��_j�'���|��R=�R����.�������Y���^>@P�e�EN��yi�n |�EN���A�z����������?�Eb�
D��eN��#��Q�Z��}u!wM�
�/����B>@P�e�E��W����@�R�,YJz/ �T���"���yn�n |�E�,%��T�GYj�7����6}7��"o���A�z����������?�����,#�����[�G5�yd/X�}��R)��N���#{�B>@P�A��<�,���X�T����g���|��R=�Rgye/X�s��R�E�!K����*�#(u�7�����+��Q���^��T�GP�]^z��^��G��_j��eN��#���:�#{�B����J�(J
yd/X�*�#(u����<�+��Q���^��T�GP�,'�����+��Q��d)��|��R=�R�������?�EF�R��,sz/!�T���Yx[�]��R�E�!<�-����:���B��[���'���|��R=�Rgya_]�S�w�������T�GP�,'����4}� |�!K����*�#(�.��}��%�Q-�nyDdd��{�A�z�����������/5d�R�{�A�z�����������/5��}u! �T���Y^�W�����������.����:���B^��[���%KI�����z���}��%�Q-6������2����J�J���}u!�M�-_j�#��B>@P�A��<��.�����K
yf_]�*�#(u�W���<7}� |�!����A�z�����������/5d�R�{�A�z�~�}�����8����[���s�PB�`������K��[N\9E�U!���Bq���=���b�\���r��)���ys�/.�#*�(R��_(��cWNQ|U���Pp�p���Y���P�#��I��O��>�V)G.�#*�(����Pt-g�����W�Bq���=���b]���r��)���it�/.�#*�(���PL��r���b�\������/�4����5PNQ|U���Pp�p���Y1t�P�#��I��O��>�V)G.�#*�(76(]kp��������Tp�p������p�T���p���B��#�����{D�����bj��S_����_����=>NQ|Uln8P*8\�GT��{7(��a}67>���@��H�8�p�Q�E1��@������W��������{D�����bl��S_����_����=>NQ|U�n8P*8\�GT|Qln8P*���@8E�U���@�8�p�Q��b��p�P�#�����@���#�����{D������o��S_����_����=>NQ|UH�x�Pp�p����X�p�T����p���bu��Rq���=��g����@��G�����<��G
�����/��
JE��(�*$[<R(8\�GT|QLn8P*���@8E�U1��@�8�p�Q�E���@������W��������{D�Er��R����)����������{D����s��B!��'���<��G
�����/��
JE��(�*$[<R(8\�GT|QLn8P*���@8E�U1��@�8�p�Q�E���@������W�d�G
�����/����bi��S_�
J������k���B9�Or�y
d+��#�_����=>NQ|UH�x�Pp�p������p�T����p���bv��Rq���=���bu��R1���)����
J�g�Y =�J���H��6�N���s������{�E�g.~��G�#����@��H�8�p�A��W�B��6�NQ|($[<R(8\�GP|(�,7<R(��M�{��bv��Tp�p���P��v���4:.�#(>�s������{���������(>�s���y��<��/�����y����68G^(�8\�GP|(���H�<�p��C�'�E
��~o����������H������<m����i��d����,�S�L�D$��>)D�o��>�e�pO�e"��}��:��s��uyVmD��}~n��s#5���%��u��4�������'u[��<OHP�����^���@���}_������k'��L�����z����{k;)
�NM�n����]�"���{��Bx��s����������7+��06�0�9��;���M����1(���)Td��k(t�?�;����7�����9�K���:v=�b�j��P&�����Z��o}/���t�;u�c�u���P]���L}���YW|��$��cgj�c�Q#����2c����<�������O�N��u��:Q#Fz/��������V���>�����F����ia�4����7�g�}oK�;S�����(s�1�F�C�������]�f��g�+u��$�P$���TT�@nJc�MId@�-�
�5]�fi�������+Sg����2[�\���!v�::9
.&QE�!����9��>������1��r h�"���P����g�n�`�`d��e`rz/;����X�I��+��F�������Z���i}��������5��\3*4N$�����b�a$����u�O�8=�7y`�����������>$C�cV��C�-�]�����v��i��wO0��u��:Q;Fz/�TU�Z�V���Lc(��`2����y�c�d�-��eG~��^^��o'�HVP�����=��;-�5� �����F�������k��{��3��w��E�[bs��wYs��{�����-�
�&P1~��b���{��Y���I�_�5�8�p���es8����S
K}��x���j�0�����{�au�j_�^��l!�K����+����l�G?��_��%�����b�-��X~L�Wusj��:ML��Kz/;�IkhZ��Lc$;�����4,v`��B�!�P���4G����]`��<��#p@WnLY$���k�WF���@���e��z�\g��<v^;s�rz/W[�&�s3X4n.������\P�e�N�{����`]n2D�ZB�&T�A���L����ZV�ax�Z�����+'��LXz'k���5�Xqo8�6����^&�����q_�f��'��[Orz/s]e�@o{5����p���_Vd��d
e�����UW%��2����[���2W�i�u������tL]��H�e���\����i_�1�T�mB�yenM�����qu
�&�N������������ei������1���^�����5�s����9���x����	]���v��$�`$��_�Np`�'X��Y�Pf,ZQe�V������+'���~G�
�17k����T�n�=���$��l��~Q<WM��{�@�����	�M�3Y&��2a��@<��B^�uw�����k'��L�Ue0~'�z;���a51%��2Su�*��d�����wYs?VN�e�fk�>�x���Xo�#�g��"�uWk(T��I����d�]��w�$�[���2S[�]��`���U��L�y�2����8b�6��	�
���)��Lm,��}	4-M������K��J3W7��p3��$��9���WG����`W��"F�{�ae� a%��Vx�g��Jz/����D:���j���l������:u"�or:r���r�����9������r9���9E�����P�~����Q.D�i`l��Iz/V�Jk�:q!�
��������g*���z�����s�aN�e������4<H���P���p
e���:�B�#v�G]��U���aI�e��S3����1u��"����_�k�����z�e��[(3UGh�����D�mE�����1�{��v�yW� ����!��=�s>��k��$f�9�����nK�+�%��"����s?�
#���A�-������'9r1�fO�r��^N�b����$�o�p �
K�a���������DX�L����~"JN�eGmN�`�+�^��JH\��������D����v�f����F���q�L���0a��6�����2����Z7�NS'��������F�hR�;��P����0e#�Q	5pD�fY)i���Z8�4����209��k��Pe(c����+Sg���^�]g��'6��q#��M�yY����^v�<�C``�20�����������B�������^f�1K&����Q�+209��_�+L�@��
4���:��2C5$;t70��?Z�"�e�k(3��n`R�v�<��l ��s(�1����B������LP�x�gpX��Kf�
*�F�S�-��:���9��8f6K��B�&�N�����D��2Z����QjZ���Lc(�gU�C��R7&xtS��L���x���qC�+�&��"����������|��3�ss��^>QY������2t��Iz/��0A�GqYy�!\��,��Kz/�;�f.+��dl�erz/ 
7pr������%���3v�pWw��������\��$�J���h�B$����^0���	oF[j�!���L�R��'���e���<�Y ����v�
_%��c�B5Ez/3+,���DY�&X83LZ��[(v�L����H��un�NS'j�H�e�����#��:7P����0eC��f���j��U���a�����PvuEo�T���Q�����^��c7�I�	b�6�/s�]N�5���}�g����L����|��UJ��2S[u�j��e�Hz/3��
��<Sa�1�����{����4�r����#�"���T}�G�����UE���235.�����K�Uk�ID"���2aS���Lk/fO��s�.S�,�{���������k�
c�9���ye��{�|�|�� ��+��`���5a��2c�/������%4���yi���1�k<��E����g(�<f�!i�������
Hd�_�{���VR�"�S�i�� ��5so:k_n
��>k�w��^%������l�v� TW�b�yc8(���L
F����pa�yk�rrz/�j/O����p�fY(���LU�V,{[����g��"D�{��:�
7`����p��@$��	���V�;��P]������������(,<�W���2A�;��������Z0�{���0"�q����0fC�a��F��0��5\)ie�6��`�yg�BWnL����U��7i�*2(�����=�
��u�����E�0�]��N6�<�{�'���E�$2z~�&�gz/�l�]?���S5
LM\�=��=���g���E�'2~c��)��^��f<�`��v�+�=����H�4ksp"�����������~���U�`������Q�gfmN-����}�������_����iajZ�2����:��V��^�l_����@.���!
j/�v]���^�����r�����`w�`�-����)p�G����2w�����������j���ec�G���{����-��M;��*2(9��
��_�g�K�WJ�{�U���M[�+209��{��p�N[�"�����2�7mmW��B��^&��*�|���v�#�B��^f��#C]:�.TW��2Q[�h�	�R��h[���[(u���G?��41u�&��^����h$�+��n�ia�4�r�5�Vh{�V��F��
%���RV�E�
u��$���������p�����vCY�PnSm]��hc���\7I���MvQC��,.m��a�g����{y�������I	W��pE'���������7
�M\?I�e�=�����	Pdrz/;���W"{1 �,YJz/��<���*^L�"E�{��f�o&���pc9����^&�nZ$�g�1�/�t�]��H�e�����-+	W�x2�����2q�|�%�O#�	�ib�D�������J�M����ia�4���=�$T�*B�4�2S�-�t���P��Ud�Hz/3����x	P���3�[I�e���=v�4��_8�Xvy��9��g�Nx&�X��&2y�29��
��4f���&����rYM��dB��*2����������l�E�!\�/���p$���{�gwe���i�/*���L��rP������`���V�{��'�����K������^&l�`u������ye�>��?��?�?#�gr5�Nc'j�H�e�Vb����F����ia�4���6~���\�8	Wdp��������<��[����^v���B�T�O��
7$I�eG{6�0�NJ������#��\3���k�����=���0E��M����^^��Z�$/�*S��d��ePrz/;����hd��h��j������������g��LL��������pVg&�,D�{�%(�U����\i��*��L���������sn����L=>f_��@���U��L�s!e
�+�te`���2A���X�3��gu��:Q�Ez/3u��{ �F?�0#uT�
�"��!1eC�Q�-+n.C�+W�#���X
R��Q��+x��g�l�����2C��,a��P���3WM�{�M����o��-��.��<������,��a��+���.k�{z/[D��)W!�404q=rz/{�qD<E���`�21dO�em��UW!Tq%B�ePrz/;������3�����5��r��G�������?kN�e����
�41u��*������P��BMS���i�dG=2` P�u�C����v[�k���Z�����6v��pg*;F�S�-�_�-L�p���3�.�����]-dF�v�8
����.�����{��,b�����t������X��W�\�i`n��Iz/���"���g*�=��Srz/���]8S�|�fY8�����������0�2{���Jz/6��d�&=����	��`$�����B�J]:�.TY��2Q��-�B��	������yeb���o�����Z1�{�[S�4x/����ia�4��k�I�W���a����Pfl�Gyx/�����Y(���/VnD�����1����i��0����g����q���7�~��Ra�i�����^�R��6�6�+G�{�����*�6�+D�{����`�i��rE�]����m���N;��d�Hz/�y�:mY7�����^f*�����>�t���X�����L���������:ML��#�����SN[�
--��4�2�*Q��y@a�i����9���H-��T��{��w+�����
����A�`g�Hz/sOm�����,�/�Iz/��W�u���r���T�A�����������W]�"�U�}(3�9��-����e��pe�������vu����5���8P-9�VG.��"��L�3�R����c�B�Ez/�1��8���r���X�����L��.g�r��n�5c��2C�����
�6�hZ2��L�i�9��_�����}����P����+l:�^7���������l<���$���������3WG�{�Y���$3���7S��`<���>2�����n8���P����5���gUV��Mc�M�{�aO�m��F{�
'��r����-p����|�Hz/3�5������J7Ivk(35

3Cx,���L D�{��gw�(u���PU���D=��9��f�;�@�-�	�����L�&�N�����Lm��idhZ��Lc(3���}��gF{�
%������;x+��o�+7&I�e����P85�_�1Iz/��t<j���t��Iz/h�[�;�O�a\��i�Spu�������~��L�O�i�.+eO�eK� ��i����&�VN�e_��b�U���a�41gO�e�m��_%T�eB�ePrz/;jcI�*C��dv6�7�����+������0O���{�q[7��TY5�����^vP�����e2��Z_���bOu��^~����];���a%��To��g��}����b<?0d�"��K���mh0�B�W��\�����j#AtTX���O"+���
�J����=��l�����nz��2���^���2S��h�i`j��Iz/3��~`ay1����{�����&�U�bx�e�Fqe��p0���."���n
��G���`Fe�|OM�p$��]��@5�\:.TQ��2W�uGz���'�����2S[��w=C���D����P5y+���~;{.�b�Mx��b���
�������e��bW��"���k(���nb2�|����������r�9��#4,�_:���j���e��w��_��g�##����[sz/���2����R�����W%�����R�x@����5��^f��[R+^D�"�U�}(�qo7�����e�)qe�R��j7���8���K�5�����~"c�WF���	Kz/3�yI�x`�������XsK�����B��s����[(;(�������������0�{����u�����05-L��P�6��H�=4��*M�"�E�s(sU�g
��Y.��@]�)��W%���TY�j�����84�����2�a=U�iI����W��\-I�e�k��XT2��Xy�5<�(��{sz//��2���N�ph2U������r���c	5
LM\3I�e��v����P�3LP&���^&�v{��\m=����e�re�V���=��X�
�&S������2Q����������0o�,���Tc��N�*�a	v��Pe�����ZN��[M�(V���a�20d�B����,�������1�{�����o��%1dC���_,��p-]��Jz/;�^G`��K<G���`��_U�{����}t^:s�$���F�l�2?\����S�{���)���rO�eI_�c�db���d,<�L#vY1{z/{,f7a��@����u�������A� �
�����=�����\*�E��HN�e��k^�^$��#S�_d�4�W����T��P��Y�P�c��`��m8��2c��*;~��B���tL]���������$c�a0{3o��X�!gX�+��A�:ML��Kz/;j�{x����ia�4F���;�_��k��$��9��U
�+�����)����^v��u�7&86La�1��^>hL�u�p\�W��\�������;ks������0��e\D��{��M�'�@�_��D����5���0��[MCWM�{����2�ke&�&03rz/3���+~M�Y�[0�P6���Q@���$i�O(���jvj�@�O�`of���2C;������]6}W���^h�[+&U�<�~Td�/p
e��\|Pj���j����z�k�6x����zU`�\����h���Y�Y���Pf���E�=��Hz/���g�b�7��g`$����������1�v��Pm������e���$Uv����`Ef�B���~�T�%Y��C�A�HD0?��qPeX"T�q������K�S
FGvq]���+Sg�������8�L�x������$������
 ,���,��{������
��H\I�e�8�����Y/��C���[�a=y��b���������[�����-��Hz/3��c��}�-��Hz/U�+k�j?y��b�,�{�����g�+��O�����c��[(3u�>�z; ��aAy��r'j�H�e�bI�.n�*)4-MC�1�����O��L���If�BY/��C����a~6�{�5V���Id��o
e�����9���nNpa��Y)��Dm����ye�����^fa21-����l�e��p]_N���w�j���C�SZA���t����5��zvFj���n������NS���S+%��2S���7T+7�zs���{��P��xC5(���Lm\��~�7TK.��"��LT�%w�������c�B�Ez/6�A3��d��P��x;�R�-��z� r�Nc'j�H�e��?��[����iahZ2��������[���VH�C�A[7��m�vj����$���X����]������2C[k��]��Z�3WM�{�Yb��&�!S��.�[����&�_�����m���m��Z){z/;j�lF�^��Z��k��{�r�d5��n�7U�e�~O�eWM�R����E�k��j��209���7=\I����`f������:>��TK."���{�����bp�����-�J]������z�7T`��xS�b�-�;cThL�Q��[��9Q��^v�s��*4-MC�1�T��������	��w7+'����8���)���`�^x309��]s�G,�0������mN�eo��#6�y�����e�lp�`N������	��"��,��k(;����
5
LM\9I�e����.��0srz/3�q�\�@��4�z���=��P��7��]%��z�7N�j?�a��I��Z6���\���������~����C����tg��GxS����{��h	��^i�����+%���*IK���y�)"�l}(�T/�v���,�-lc(3�q�Z;�HTd\����L���#�����"����(�O�3fD���c�BuEz/�6[&����__	T�_�ye���)PTd���e��[���k�_�����_����k���;��5ml�&��]��Y9��'��2�q��f�%P�sYo�ZC���xf1\������&��\��1�d��7�%O����\eV~�cn6~�fY��C��'�U��PE��Y��L=�[�Pa�r.��"��L��K�+c���U��L���5�*�O�"�2o�����M*t�:Q+Fz/3��;��8AMS���ie��b�e�)���
����9��5�r�T����D����Pfhc��Lq*^M�"�l�����K�������&��l�� �f����V7�4��w7v��^^�x< ��o��W���l��"[�a	7
�M\1I�eW�hd/�/�'�2��2W�y���`�}	6�zO���mD��;e(����g�����E@��E�8�R���0���*��LP�jW�`t�/u���PU���D���G�����?o�L������J�NS'j�H�e��v�-	5-LMS�1����Q~)c��2Vd�me�/d�-	s�f$�������U�c�X8.���5Iz/3V'�f��Y��_��2u��Iz/;SKdF�:	W����Q����S�q/����������BP��d���J��{�R�'�����&�VN��z5����2����1{z/�l86��	p������i�w���&����f��9���_��;��2T�fC�nsz/3T���~�8�R�K���j*�����7Dsp%�U���a640e�"���92�����:ML���Jz/;������!����q��-��a6����H>�F�*�%�2����rz/;���������!nM9��}e?^l�T��2s����^�f�N$����9�-��v����^�k����f��s�%�z����[���	"
�H\I�e���������hbLN�e�F�^.�\qY���^�6�2sO��.3qS�-Hd��me�6~dJ�����M[(��So�i�����UE`�C��O���m�o���ME���2S��%����t��E��W9����f��E.�'o�TNN�e�������<����2W��9
�~��;��^fh{��t3����gY���C�����C���Od����{��i6�������/�*2([���6�-z�pW��"G�{��'7k�3�?�e�7qYPN�������)V��`E�;��P6���$��400q�$���������yK"�"��D}(3�������{���^fn�.I��
��%��r�9��������(�M����^>����'�3<$RI�e�IO�pW��"G�{�����W�����<�������Lo����E,����sz/$?|"
�H\xI�e�h��������{�+�A�T�:o�D�{��'��@���)v�N$���X���s�������^.?ge�=y��������^~���t��)�@$��zb�,=�w������{���,��&a��w�����,+eO�eK�Y ��������\�bp�~��D���{��������dCI��/����^������c����f�����:mm�����ML��H���o
�j�]��f����G���C�w��B\���{�%0���Y�_XC�@��B��8�_��k%��\��$p�
'��������e��@������2���
=Z��;n:"�}s(�Z����+������\a�B���
��������e��v���
u��(�P$���W<�t���oa�M��A�9���r��������qA9��
��'E����M\1I�e��]Z]��3(&��2c[�.����A�Y����P�����~tp���q[Y���C���]�����������-�]m�#X���Vb���o+��\���)��u�o+�P$������B��������w|��^�9=�����X������l����"����U��^vU3f���{�p����srz/3��c�g��-�Y�s��P>S�`� X1�YO�C�}���9�W��_U�{�����"Z�b*2 [��Uz/+?�%KI�e���1B�(�]������=��%�k3uP��9Z){z/[��I�i``�j��^v�<}� �����=���W}�C�����^v5���S��j�KKLt��(�J��{�Q��������>������^�o7��@��>��,sz/!��z���l� �T����qXMm���S�Nd=�y
e����������&������J���
�Yo�C��������z�"�)�s(�[m������[�(O[(��f�b���M��P�j�����f�W	v��)�`$���o�x{8m�M����9�������8
\����5�
�24VD��*����(�o�����{�Q+P�<G� ���>^c9���@Y��C���ZD�t������8�w�B�Z��_��E��84�l}(���A�RW��"E�{����l�ks�.S��Jsz/OOt�s,���I�7�e=u
e����9�M��+&��������
k��pJ�����'��V����F�{�}�F��<��*��:�����}�W��D�{�U6��W7��0���e����[�+U�"���Sk=]���v������{y�p�VF��p8`E�c%�Pf��Uw������'����g����4pX�rrz/�Z_�}�Sn����1��{.6P��SHN�e��N'@�����&�-���6^ID���8`Ef�C��e�a�s,��sp�bW������6d����e�	G����,�_�����������Z|�#������y��q�J�`�������+jgQ�n�D�5�=��]���N�:�9t
�����fS����q�YV����g�Z��]�f����z��)�j����k�������,����+�=����O���8�M��+&��\����C����8�������>�t
���A8��6�y���,sz/s[i��M����9XI���o�������x����?����^~�J_���]6}g���^l��9�*<FQ{2���*�����2Su���5���F���9�&����2s�j"�]5�1:6��+�����2c�/��VoR����tJ����7���,���i�G��h:`E�c��Pv�V���T�i��9�N�ZI��3�"�T���S������x*:?��)u�/+��������b���V�P�����
��#��K���9�P��$�5���;��d���U��^vT�i*��C�Y�2�C����p�u��@�s���W��#������mi�� ;PE����P~��n�!vJ���Jz/3����_���l}(�VU�z��S���U�{��0.wi���v�	���{y�q=M;,�\�b�*���2Su�dzN�W�J���&����2SOZ	��UX��'���^v���	P�M5�zJ��/UU��@�$Td=)je�Uq��	��{5��v��*2���Pfl�I��������>�y��K�p��)�$����	Z�:������
�����,��~N�u��6����{�a5��@���}������r9���9n���!x�fY){z/���o�V��������3F2c��\��s(�YV������89�~[�f��]��,���{��v�n���fY1[�{�L��W�������������s��.3�Cqrz/�6����:I7��I��HAPE��x�P&��&�~����M\;I�e���QF���A1��Crz/3�5mE��8E�fY�C��-C�>������g����r���B�V�qB����	��,�<�,+������]�c������^&n;&]�Cw��
����{y��Q'2��9bX��h�5��\YC��(F�&����2c����c�Y�C����������4����E���F`E����PflkA��C������^fj� ��s@#�"�	A}(�VW�}hT��V�{�����r_�>�4��18�'���<R]�����KPa8�Q)9������������u��^v��<:>�5+��"��2c[�q�{�jTj��(�1��znePXjTHN�e������9�Q�WI���^0z=G5�*��&����6P������?���2S[?6H����]6FG���^^'�jc��N�1����
������"z=�4*6q�$��{n�P��gTHN�e���E��xF�f�
��^v�m��J���FPE�#��P~���s<�B7�������b�{hWd=����+���=�3*t��*�����A������0}������Od��M������9��]������[�#����.��@�����d���h@������=�b-��@�(j�
(��M��R�������4�#�<����|�Pxr�Z�Cr��bW���
����fx���Ea�1��G
Eo���#*���h�P��EkE�����e�����%)���I$��V�A��$�
F�5$�=�B
�
�������7����������P
c4d(�����x�[k/��F���24V�n����BEa�5��G
�HR��.�K)����������-����b-:�Z��B�b���R��aC����O.Z����H4V�n-���Z-�:Z�<R(^C���pG�����#������`V��h�P�E}E���WA������G
��f��1,=N3��
y����	��4h(�,���`tk�AA����G
��tk=Q�)&Z�(�����x���M)8����������'��[��)�n��*2h��{�x�P0����o���'
���/�G
�<r�i�$�<�G	tr�X)�>�f��K+<��@��B�����`�-@��rV$�����n!d�$!�BA��B���1)z�����I)���@�L6����W8%����B��/�L�W��E���Fc��������B�Da]&N�G
EGaD�a�Z
�3h(�����`tlF�9��������������"

=���(}~��p
4,<R(��n�6�B

=i�(}rz�ve
�3 <R(^lh�O)D��W���H�`��%��l(JO�g�� y�P�t�gZ;2��Y�<R(}v�������&)?�����+S��E�#����kG��=�c4V�:��Q)��������������B�����gM[E��;�@�jI(������p����j����
�n4VD>}T�{N�'
k[p��<R(&�z/F�8)�P��PX���#�"��'��6PL��&W3<R(��Z*d�j7(��B��Ba����Z
��pQ�!GcE������
�g�P�9GsE���N{5�g����x�P��~�W�A�~���E����/� P��e��C��B�>t���
��5!8�H)�����f���
=�h�(�8@KmE�Yrr��#��������x5�g�P�$���*���"-Yz�XQ����>P$��C�'1���p5	h����x�Pp�O��}i5hY[_QU�OdQ�@������G
W��6�2PX�(�1pdR~�P�#��;2&W�A����)���j(D�����<R(�����[��
ZT~�P8��t(����-:+=�i�}���,P����B!��B���V�@1����-�
�������C{"p59hY[+�tt��Z
���}iy�P���a#(�P���4&y�Pt|�]���BP �AC�A��A�p�
BM��&W?<R(\�[���m�F��B��+
f���(���1z$�XQ��77UA��
��5W����F�O�C��pa�`��B���?k9�QC��5���(���:t��W�E�������5'����Efcpq����
�$���"��OmW;�"�%�
�7.nSK����\-�H�x��j
$r��wq,y�PT�W,��W�8�yMsEq��G����r(p|��U�Z��z������c�����(�xV�=��,*uu_���T��.^qW���3���B1����G��v_��,y�P����ip��j�G
W�=�A�t��`C��8������F��*z��XQ0��%�F��**I)���Z**8[i�*
�0By����Uk�tq�J^���#�������.NpW������B�$z�v��������V�sjAY��������	�
o������$�
����W�nB�;��D%�BO\+�j��������$*G)�M����n�#C����������m�������A*j�+
~�:���qQK�� ����G
�C�<�����9���ow����#�ByuU@���	����#���_b}8��M��G
��wkL�.	��b��b���X���#��'��n,dQ((?R(<���+tK�7��E�<R(,���n�G��'�\����BQo`��DoxuX���4��W;:����?��"y�P���]�d�2 
=1i�(�}�C��������')��g<[m���T�<R(���4����T�(�����x���ep1��C��(�����uIJ-��h����x�P0������
q����������6(su�
=Ki�(^��j\������#�b�����5.�R��G
����q����48frU�#��d]�h�j\\�2��B@�P*,������0�V�V��*�$����./��}[(p���U\amKy�de�"�j����#�����7����W�������"�F�����.�rWX�����B1s�Wh"����Lj��H�0�S���.tR��U	�
W�#��ip��
�G
������
�"'G=Ni�(�}�bZ
���T�<R(\�h�.nR����x�P0������N��Iem}E�xc�X���T���6)�nLJ����]a�N<�G
�ZxUn�V���&A�B�YZ+
C=�����M*;�
��B��V�&���
���BQ����T29�OcE|��'�=p��`B��;���������j1\�$Hx�P0�=\W{��%�By�+
���O��W����C�����!tj\���0&d�iK��B!����2���H����>��K*5��#��W��sl���\�����UV��%�����4�
W���K5.V`Q('?R(��+X�Q��%���,����Y����U
��XQ�n%<SM���T��>�<R(�G>7�z �+���N�H��_��S��B$�B��Z+
?gD@�n���#�"��k���.>q�����_���
Y��OT�<R(�����.:Q��kEx�PT�����#���,*I)����[����']���W���H�p�n�'��.fqW�������B1�U�o��]�"�P��MkEQ2[�48jr�#����P�J��N"����0��J���I�+
C=���V��E�
�5W�n���5pq����7�#���m���]�EA��������?m(tu
=�j�(���GJD�~v����Z	9����w;u��!�ipa�
�G
�O��b�ip��*�G
�[���
p��@C�Ga��������D�����������*L��k��u��
���L�����H%m}Eq��A)=�ENz,�XQ����M]H��0={��P��B!��|��O]�$��PR~�P8t�(?��.HR���R)����ve$���H�x���S]����b�S��X�����W���Z���TR~�P8�uW_���J*usZ)L=w��!��pa�
��X��go}���}gQ�z�+��>w���c������@*�(^!�����M8l�����
?w��E�����&L�W8���e
e�C�I,�W8�y��X����YXc��o�q���aQ
��'a���W�a�`�����Y�iT�+���;�
vE��+zV+^�5,�����*z�+�y�L������(*y�P��"����j����VLn5p�.PS����
F�8O�Ej����W�������aB\�&Hx�P�x���2��6��j*J)�}�\��#�xI��H�x���O]���W���H�`v�w��*��M�
��qB�<R(&v��v��'�8J%�#����g �N�c'WK<R(������EU
�N�W�n^���EV*Yz6�XQ�������V*K)��v9^P���68'j�*
�>9^Z����T��W/6r5.�R����x�P���TM��������(y�P,6F�����F��^*I)�:c��@
���G
�k��~�B -
=&j�(^���R	4zL�\Q0:>�W�����HEo�U��Bq���^j�Q�2zRT_Q0�,��
iu��^���#�����z�����c/8�)?R(����]���#�@HE�G
�c�?�Z�ip���)�
o�g/h�".RI��B�r��J��H�g��F���D��1@V3��"�)/W[����T��>�<R(�9���VK��"�����������	���}ly�P0Z���_���[��t.0rWX������B�M��O����$y�P0��%RJN�#'WG<R(����j!\`$�P�9R}E������aC\|$Xx�P��}��Z�V#�"$�$��W��&�EI*|s���3�<0+`�q���������6�EJ*zu��
F����c'���J�
kWp��<R(����!��!q����G
��Z�������
&��"j&\�&�P��V}E���|@����T�(�P���p�y)����
=�j�(^��j"\#�P�P�i�(��>�iOq����v.�$��ii�9�Z������$�
F��QV�ip��*�G
���L{�h
=o��(����$E�/���E��+
�����'.�d(�����p���2�=��4*{s�
��O�s8\����6)�5r�[�W����s�����gC���;�
kUp��<R(�:{Q5�jE\�����B����� �Q�ip��j�G
��K+j#\�#�P��W}E�l����j"�#��0�
G>yM5�jE\�����B�b;S�"-�����G
�k�V�"-��B���+
�n����p���^���#���&�&��Z�
cUV@�)��k! �	q��
��
G>��48tru�G
�C�a\m���TV~�P8x3x\m���TvV�z��+�;?���j���H���V����Zo	�<R(^��	q	�(�����j��p���^���G
��-
F�s����C%���xx�n	2������������.(9
��\�H�`�y�8�H����X�H�p�F�
L�bD����5V}�_�aC
��5W�n�0L�k������G
��_&B�0"�BO��+���,����P�aYcE���O�j!\����FW�#�b|1�P���
=5k�(~v���48tr��#���z��p!��C�'i��[?u�H��G��������U�aW���#*��7�G
�t����]�E\*j�+
��O�m���]����Y����R�����k�T)y�P�/Ej/u�@C�Z���[;��Trru�#���v��&�]��[
��i�W�>�C��e|�(�X���x�c��ZM���T�<R(\��$5.�R����x�P�Vk�.�h(����� ��%PC���.�qW�~�����B�����!��I]�#�P�)SkE�h�^kM����
;
��\-�H�`�L���Q$5���]�����BAlY�rqp&^E���T�(�����0���t�Z:����
3�������d�.�]g��]�
[z��\Q�/�8�-��������>R(���$�y|������*�����u��KoY�>M>q��G
��Z#Z�-������iq�i�(�������
z\3��4W�f6�q�z��W���)�n�:��*����X�VQT�yp���_�`������%)���u�N�`1~�\��0�2�H��H��GN�p��\1��PP~�P8���T���N���H�p��T��@U��7�(be�G
�����M�p�.�8�inc����uHr�>�zH���s�#�����^pg?9�&�����9V8vcDh�������6)������VG���P�����>�q���&������B�k}x\�q�BN�#����1V�{vm��\;SG���PV�c�k�V'(��53Q$�
G~�o
\�d��BY�+^�^�=�=�j�#����m�����w�Ay�P���!G4m��u�@��t��J�G
��ds�(:F�ip��*�G
E�����k|��Xy�������U[O���q������+[z��XQ��y&��#e9���G
E�]�.����IbB��7)oL~�
y�y�j�#������x�=s�6>�������po��tS����7o}�P��������iq��8�4V�u����G="�o�e�������2�����f���H��Y������h�����f�G
�9�a�0��1gW;<R(�����W��O������:F��)�����7?W��y���V6n�����*;
��\�H��V���EA�t=�$�
W�������FE�BO�+
W���R_';=f����3;�����\����i� �k�m��B�>����8!/�#/\[}�P������pu���
�5o�{����q��q&n��H�x�����O�cMcEq
n�>��e�:BL��c�����]���6^N��kYP	�
g?��r�~�3���H�8hW���3��3���BQ��v��6g�
�q��<R(f��CM��.e��Q���f��s�VL��	��:�LTt:�:��Ba�G�Y����&z�m_Qpu[�&�Ss{�-
=�v�(����y�i�3jv_
=bv�(��6}����c<&]���BQ�c����/��/\I}�PT��E���e��:�������\[6^M�����e}�P����o��2U}&@�A����7%�>����	�d�G
M��C�S4\��T�I���x�PT&'v�T=�����gWI<R(���d�$��Q_�	OV�\by�P�k����D]IF���I�(�H���`�B�D?���;
��\-�H�`�i��|��d�:Lx&G�G
�A{s��C8�0��<V�/���/�F�U���x�P8t���);�x�r\��#���i���zA/�C/\o}�P8t�N�Q2[�?��C�[EQ�����iq��mM)�Mx����:�:�����p���>�k����p�H�x�����h�F����l��U���4%��#���x�P��I8�U�����
��6�s�)�H T�nr��8��)�M�J��
�>��������L�v�H����@`�D��	Y}��
���H�p��'�{�FP%g��k���Nn�
\��L�f����B���H�p��01q�[)��EA ���K��W��3�h�$hL�-
%�[�p������ir���9)/u0����GN�Mc�p�����8��V��9Sr�4�
W���'J^]3@�H�pd��GN[>yLa������3y�P�����	y^yv��G
�����������H��������H��uK����o�^J�P���kEa�U��^NH�pS��B���+
W�hR�qJ��B�+�z��u8��K4zP�ZQT�%s��������G
���	��`K�����t�p��B�����@��
���Bq���S5-���9�#������]������4W�>��_-;����P��zCV+.�y�@�l����Oa��W�]}�H�p�?u���������y��������Hu�7������������]��>�>zk1������o���u����_w����u������_wE!GSfcS���)��|���.��Q��[�������g�t4�?��G_�{���M��=������,����nb��.*�_f���������l�������{���o���������������z��Y���U��{C��#�����������O���/|������?�{-�uoC�\������q)���]���x����|�� �����f���}�f�����|���6��Y�\���g����e}�a���d����oY���������oY�����:���[��~�7������@��?����i}����w����?��_����s������������~Z�����������/�{k�������/�A�?�:����e����=�~�Q��������ijX��r}Hg��Z�iX2�u�����,�z���\����?2�_���C?v�Y��N�~=��^������(����mJqd��>_��kY��#���|!���0����{:4����e8���~�����a��J�����.w�a~��k?�s���]����6�Y������W�����
,��p9Ur�����|�������~1��mL[����\�7�������Z���[����6�=(���6q5���=|�����?h_������������������|����}��~���%�w�w��}H���=�7CQL�������`�����|����� �_�]�Y���yyD�&���uc���������q�Qt�o9��|um�-����<�,[�Y_E�e� �}}1k�ld����f�.Y��f�O�|���;/�,ST>����P�L~������5]�?����}��f�"���2����[+~�x���Y��e!�TQ����Z��X�����!�'���X����km�.V�Y���`+��r�����p������,V����b�[C<��?�o���y<4����-��A��c��K�v�"|������b�]�2_	�>������~y��+���>s4+�������w�%u�D��Bc//��o����m���K����������s�����Acy_��<������������_����2��A����_^�8������2���|k!c=��?���wov��_�{�,8��}R��k��L�<��5����(��O�~�w�e�(�ow��������M�D����?��rC���?���(��w~L���(�_�������]�u}:��
Q�?�Y_���rC�B~}�rC������r������|��Rt��f�~\��rC�O��O��
�;�*��
q�7����7���#
]^(3.��_]HKw�j����k���j`��|���Y��7^�Yz��������]���S����P�J���Y|����w��thv�=c.���C����p�f�!�����2/�'��^��K��������q�������"4��������F������8��s^�-�����������F���P{���p��������-��������~�����Z��|wm��s��f0C���`��d����%��f���<�.,�Y_9�A��e0zsa!����y�YX�������B����E�������j��a�z�Gd�r�����[�(7|�_�o��|�,.���S���s�=��w�g�^
8����??_�����v7��S�uL2�-2.'�_�N���~�[���]�a�������Y��o�,/�x��>`y!�����]��Z�SF��d�����l���_��7��~}M�..�o{�/v�'����~��A��Y\���uvq!���[�������X\��:�7�����������0���qk���"���w��z��z��}�����w>l�,�����z��]|l��}\^�������bsx?8X]����������)�������B���	V��v�C�5���]���5� �}�����)Y�b����>���]S[��Y��B��]"�5��C~��b�*�����vM!|��Y�2A��rT���]Q��_w�����������o�������f�R���.�7���WtoD��\=mAW�~����� �6����� �Y_o�v���� � ��~���xhb��k�W�M��kr?8��)o|L�~"��i��~Z���q�����|����������~��c���~����0����~��N
������}�����A{�����T�����0��������	vH���r��~�������� ���A��w0�Q�r�B���s���A����g}}]�.�Y����,Y��a�����)�.Y���2���qKQ����r,d����K�YO�|�;{t���_�"���st� ����yu+Awdn�����	�+�����u\?�?2.�!���B#���b�3k����0���Yv
!�#�8a82��o�z���;G �B8<�q:�xhV���0n�*��G��g����Av
!�~����A6����� e*���KXR��w����K
[^]R�{9�D�B�{}_�pP�?���B���^R��<E�%��k�?
2��j3K
a������|uI!��������[*2�w�o���O��?��?��K�Oo�g]�n�������c�uK��{��5���VT{�D������ ��7vN��9��/�������e���os�����_�/�
���������2�������� s��X�q�3����s���2��g�37++a����W���J�����ve%����;1��J%�7"5te��������a����d������u�z�;e�x������|~F�\�|2�����U�����qTWC�:P
���[{V������������m�����3\����%�>���	�f�G���!����*74�\w�������R)��{2�������n���z�Z*���B�����0���:���WZ���?��n��\Y�6��������r���6��R���^n	�����-���r�����-a�W���1�_'[�:��1D�~����Yc���yc��Yc_E�^:�5�(������V�%��C"��1�g�����������������|�4\��t����qE7�X�����>���#,�����;�
�A���7p��V��������#9��������Z�7b�t�������Yo�M�����
u�{u7�j������P3�7������}�y��]o�2�u/�A��w�-/|]<�O�����yn���3�#���9B�s�(�b�����
��g��F,�Yo�e��#���e~���zC���;�@��p���K?��}������>������O��������b�fo�Fz����"�pP���)��������������q�������x���C����'>8_,<|l�Xx��2�k�5������Yu2��s��8e}�$.�q$������f�H��o�4�!~��n,����(�/���c���S8/f>�x����e�e,��;Q��C���qH�]u�����/_��f�-��\l�s�5K��=����_w���JQ���l
���f���P5�W������0	���n�/�s�M��Af�!|�?o��4��xh���	���#����ky�G����*��C�Z��9���8T2�~��]q�d~�^��f���*�Yq�d~�DQ��P����Xqh�>��C���?�26^�W�r\��k$����~�C���[:t�!���A������-��xYs��W�|/�]u��|u����M��F�������+�7#��.=�^����Q�����u��5\���u� �;��v�!|��!����|c��]w2��'�W7j��C���{Q���"��g>u����(�E�~�C��Y�U����v��]u�d��N@�Yu�6�-��:TKc��Yu�f��=�"���Y������m�f��j~�[�k���s3��9������Ys����G(�5���|���o����Xc��7��F|�]s���A��C�����v������ f���Z�Om����C+�V�o� ��E_3�7�U����|���1M�
 �!�_���k���9���?��6V���:���d���Xs�x��k�Y��5�0��'Z|pyu��c��k��]sHC`����z}:`��|��:c�����di������n�����Y�C2���#��C�B�\�nW��|��G��d������!pzC�������5��}���X_>��kd���b�Yc�f������1T���j�C%�w6m�5��Q~�C���o�5�0���(�5�����!�C��n�ZO�����f�!|��qW3_�l���>��Xa���[�B�G���s����3�r�DU��P���V]a3������<�����]��7�Tt���!��0Y��owV���_70r�������6�>[�;Yt�!�}�>�0���tD�^����?����G<������|? �!��_��|��w����?|h����M]�i���`��������#����a��nL�tG���;a8<"���<n����G���o��7�����n��FPE�����
!Ka���oc���2��3�|Hw���<U�{@e%����|zs�chJ�q����v9^C���Z|��k@*��s&��d����Q����Ey)s��Q17NM�2���^=<�jz��w������qc���GT���w�AF@E���{�8<�����y�GT����+��F9<�����Q�.zTM��Kdt��:�q���0��BY�~}wg=����K�T*����F��Q���-�?*���'A����/��F����|���TT���$!?t����������J��1���++C��.���������}�����^��F��]�(�7*����Q��77*=����,n|p�X���=�^�2�vcTf� ����Jd� �Wq+��.A�������m� �����q�f	"��W^��{ze���|.�_�~����<]���8�2����7��-8G�R���6����J�_olj��a��nlj��a�?�,����0�_765������y�"]~����L��Chv������{cm�,?T����q��C��������,?�o��1>v�!|����������9L��e��U��\h�n��Ch>��@7�����q�]~����w��C���k����oj������S�,?����i�LU�!��E�i:.���3*%��L��a��O���{c�a��{�D������v=�!�\Yy���\o����{y�D�>8�t��n�2]r��|��0�e���d+G��e�n����c�..e`7G������n�0�}ttm���9������4����
�l�������3/�d�#_q��J�2������p���J�_n�����J���'>^~���q����uOG5��w�=�tT��u����qP�we`OG��^�H���J��qSF:�����`�����^
t�=F�b2����y�h�a<4�_o���]a�r3��5������A`wo�����n8h����_w�/������BW����_��V����hv�����/��b�������0���u
n��|���]]?�rH�9_����]|�
Ch�.
�
C�������M|�9�U�~{��2)�������C�> ��c��5�0���Tn��/��9�a��7����0��;H�*C�.���*C���� �U� �[���*C�Bv���L]e_��;%7��K�|�c�-A�?�	��/8�2��o��S�In�SY�����0�
��s��]o�f'�A�*���q��]o�d��N�2�
�{q���7����3$*Y�a�_������������)���,��=���������C�������=�o���Nd��������=TF������J{�~x��(Q���?l���;��A��C����<u�!�^�f�)*��U��__"��C���}�����7vTlG����:P����{g/�z�"����[w{������Z�$]�����]���5%����@3�����f�r�N��P��I3��V��!;�����-8 nAQ����	��Mp>�|��+C��w@��G7������*8����T��l��&�A��nv�0���]�<�k�BE�_z�H���7�Dw�f��Ie�qb�~������oJat���������#����H�����$b�|q���6<Ej���("5���L�hR@���O����5��E\bm|t����^;O�".`��F�����ah�*.`X6�E�����1`G�� ,��P�v�b��5 ��Q��!�q�;c+�������+���Y9�����g'�&J��TAD-n%��/����>dU��U�O�-J��6Q"���E��g�%�_��s�������\����p���;9����A��w%�.o6i� h�R�qA<z�����8���'1��x�o�VhA���@P�����`=�|���E� ���y���0��F�����@��1��_8U�0�����f��w��d�I3��sn�d����[C:w����-��|�����_eV�#�x��U�u����aD���\�����^b�U2��Q��,�o�Gtu�M�����_QQ=x���th�x��t:������-�D{��n<�+8c�i��
N�
����q�""���V��P�b�1x���������=1xU2�7�I^���
����2:��q��_c�����C����M�$��Q�;H���y�%]5�*9�����(_��>L�����q����&9�H�y|wdM�J���Qji{U��Va�1d����4����"����m��U���G>�k4��G����Q%"= ��qa�!�R#�Dz�k�hr��]�^����5�:Dz�kw�U�!�v�������O����131�"�����^�F��H��.��=��{�������r�����H/�$=|H�G8%�*={k8�^��TF;��%Q0���~���P��&> �������D����P���}�P�2?�c���8����^����$�MK$Mr��m�Ci���}E�ICGa���To���H�:�Q������F#�4up�����4`�7�HQ-n����0I����W��m���~�>/��Gq�h�1�R����[M�����{�����
J�N��v����d�5c�����V�����O�[��������w'uJ"F��������wr^^�~��;Y�=8�F���k�aM:>�N�E~��A�O��N�#>q�0D������m'�'|m�*@��������e��g-&�����S
��<`�O��Mu(G~JD��"��;`�����_���"�����~�����;����AS�q��}�p�������My@������������l��k��=`�dT���dT��vZBT{��L
�
�0$KCFR��2u�8���������+�k��q�ZL�>W�0���Y�����!"C�v:����5������k�W��
'Hz��Z\;�S��GD�g�X7������Tp�����{|�8���D��Pdp����
���
���a���C�C���
>3t]��4?�b��xL+<%~��
 0JiY�	�[ D ��l�����������D��`�9S�1��9y�"p�%��;[�6!"�t������W��!p7y	"��*B@O�l"z�|�5gK����/2�zm�+�����`h2�����y��o�J��%�|��P��7�+G�!�_;f�"=���������+<OHIW������������y�M����8[��=�3�x�
��%G:��*;`��i�*;`�W�T�}�V��z9���";�O���������������Dv@��:���/��>3�xEv~���
�M�$�*�����r��0�x���3Q16�p+*�%�?���$�-.?-�����Cet���Bp���Bp��p�����y���2�����������}�m��z{(�I!�nB�=/��7j��!�����Io�f@���Zb@A�O>������|z��K�����M��vn��/
�=��W�r�#�&B��GIC|�D���K+�����@�|j����Dn�f<��3g6L3���7��7�	>������[�*����g�Q�O��x��I�f<��3�`�u|�Iq~�D	!���s9�'4�	����l'+W��h����<t�=������&����6�YU6����}H�5�c�
^>~S�Aj�H������#�rkJ��=���������0�#��������W�*��>*G���Q92�%��t�� ��nds������sDfN�����yn�yw�����!�vS�����;8�=�s7�Wy�o}��l�9�p|���u,U���Q��r��a��9���zV���7�w��>{�<I�E���g���0yC'�LO67�~��|IC����I3tz;1����.��-(�Dn8J�$�1�:�&"I��G��[$�`��^���f�$0��_�$�+���h������$�+wc�D�{+_<�'��M��Dk|�Ho�I����l��n�f�SgB��{�.��i7�����J�T�V����W~���N�w����U�N�� C��x�!p�����H�~��B���H#7��4�<�X���f��U���9E����Fy����sC8twpV�<�yS�Ay@�|���<�N�y�S�v�L32����t�������B�s�4\:Bz�������^<G}��F����/���<�Kc��8`r�'�G��c����
���q�S�3�KfN�E��.���V�������<��\�Z���j�lys�E(hF��H�����/������E�Z^����0�qE�~��F�$p�����/��1���_����Mo���!�"�|�4�MEn������G�)W>q�����s�c�"��=c����#��@�w!�;H��O�����/��%��w��w��O���W�~����y0�������_�����0nV,3�����~W}�����(�(����w�P��g�#�J=w&����I>�<�Uz����T�|�����to���R���k��M����L�@���S*�I
�7�����`��%�6��6Y_"�B���a��N>�DR���0�Ior��F$���Z��B������!���|���{
�h4�*[-�����Ru�W��Q��,�.���8%&�.�%oC���O]D����������g~�-�w��� k����)F����
����^4�!�tm�pFm�������9�
���hmbC�Sl�
��d�
�mj�
�����U�S�����i��]�P�yMl�����
�at��������
�yF�qs�$h��\�� �y��R������������<�s�-Z�_�l�*\|�0`�

��"�����-AX��oSi��?�����6;�s���x���_:���U�"�'F����&y��Co����X�m�O��~��{���aW�\�h
�)1".����G��M��wR�M�����{8�FeN�X�c�o�����d��+t�4���e�_[i��* ��-/�$�0�/C�+��
�;/�}������B-nS�`�
��m�B)�����^�_����R�6�O�gW�����0��1����)	��Q��o~>}4�������v��[��oO��O�&\���&h�gp�X�M� ���c,�a���;��M�`������6�"Z�QH����hCj��[G�	�c41xAp�;�G���n�}p�����Q��_�+K� �^q���"�n���~��@�"��'na��D��3g�ds�`��C-N��A0��1(89���AD����`p�Z6�������D����
�#4x�'�����n;� 7oI�l��v���`�t���]��0���\��h�^�1����� �@�
P�#������N�Q/Fvt�kw��9�����&����
^����Au8\_3�Vtn��W���SU��B�������:���^j�P�����,:���������7���������H��8��(~�������83 D{�4Z850�=��Q`�P��gN7�h�Q#�Cpu���=���E{�K�F{�Snt�����i���!�t
�J��������7����`���O�"����>{���A�����T6���|�&c/�C���-��x��Cv ��=p���zk�<~K�������[�V�_*A\�r����!�{2�����������G�FW�[?QC�~�q}'�����el;gb��*4�	��0��vrz��<M}@dgx����y]Q���7���q�����,����=1K�v���C���Y��A�s�_E:4z�|@J��z���K���%��o%)u���H���l/�������
�Z`��NZE�vO&��;��g?w���|�������?�yV\$���6"
������~��M��#��m���Z����:��e����e����eCYc�v*��q_�sc��tvp���G�tvD?(�C(�����i������l�E#|m��h!��	K��`��F#R2��3-�I�����ggG�ltv���O�&FT#71��������R�b���1:��[e�f��|?J�M����8��}3|D�f����m�(����#��m�����A�r5@���fA��ZW 0y:�@Oo���^��U���L�T 0$Kg8���|�U���=��)Z����a'��n��aG���o�W���H����K�F~m�����W�W]�Qc����!}zDd�_`�9������U�o�e��|��{<��yY��
��c8(������}���Sf��s���zR�AX���"8 ���,[���1����,�r���d�S2�����:/�����yx�=�������=��oN��������< n���)��o�����������m+����^;�f�^6������Y��\���p�����T5�~�����$Q��h�������!�A[�����#���8�����|��N���X�������A�C�o��3���Y0��i�i}>7:�Eq`�{O�mNI��G�xV
��nX�k��S������io���0��x;
_��Io3������!�9����)0��2]��������`�&�[}	MS`��a+���}X-�+vv�O,�|f.l�+�eF������(x�Sp���4��N�&	��������� $�x8���Cg����MH��/��2����|��BBtS�BB5���o�t�A�<d��o&}9}�Q��	a�6��#%!���:w����A�kg�f�� ���h���yC���2�C-��x�@'9z�� ��-��BS+�`��ODQ+���2iQ+|vs�,��`��YW�
�9c5E�@���� j�/��%�V ���2�"8-��:q���7�h[M_�F�����OW��X�]�^yv�d�"W���i�j�qGW�(���cs�`��C-�-�?{�a���Qp��s��BD���r����u�����RE�e�)�F>���`��a�%���Sf0(����0(A����M�/e|5�
��t}��O�?BF+��OQ�|S��!"���CD�Q���"��
z���}�����������)Q�CDt��k4������5��Z�A����V
�B��N���A���2�?T�����:;��i�y�'�f����c�����E��uW*h:����g��nO�����%�%�!p�C�TW������K��R���}�d���":^�����CWn�d��+Wu���q����ZEu����*ge��w7���:�?G�$��!~��d�SF�}�������a�S��'�:;x��_��6D{���F+�N�{tR�����,�N��?D���� E,�.�V��C������h�/�!Et��M*BDp��?���31w�����\hB��}�	��I������!����e�<����	�Y07��U!��Q!�_��_��UK�@��o���H���?`��/�������������
�����|�?|<c>y|�g��+������l������t��|��[X:~������������fO�q|��<�U��+�:�*^��!}x/������W�!z�.��^;O����W��p2�����7|����<��{�9�&;J�uv���#b������q��b�c�[?MZ-��wT-�?ep��r���(�}�CD<�@|�����#@N�M~�(tv�o�oN�����8�������Q��kg��:�����ii�uv n�����oW-"�n��Tv�)	5���"p�-�*9p�j�H=5JFUr���L��dj�$4�C�4�LTr����VS$�S���~|�d;#���:y�������y��L��eM�$�pv����0��H�����qDp���0����U�!�x��M`��7�R/����C3r�)9<V���
>{��'?|El���
�����bC��(Zp������g��d���
��n����8��"���Yr�� ��0��[���I n���L�w������1�
�#y��An�$[n@\���q}GJ��7[\����o�����N�L�u���@��`�An ��s��
�QS�@�S�.C���?Ne;,GJ���������������e��>�N����so����u��~i�2(;����+6����i}|n�N|���>���9�Y0���)��������kx�yYd�
(������DNc�ps�����DV�X/��8�3cf��
>u�`6Y��W�f�d��Sf�i|^�(�������C@
-�S�wb�88��C�����Vp��������_�3��Y|9L����!��a<�"���3��{����������.����m,#r���M����/J8t��B}`\���x�����l���~�������O�c�����������J�j]~���������?�������~��?~���Ma�_?(��v����.����v�Ed��
6��-U4)��w�&��*r��0�y
��@O�5������^�=h�S�����?:��O����_8�����r
1DY(�U����#��F��0i��q�$������)�N�~����t?iV�W�������J���#��W������>CV�:��������8��=�����]7op����v=\����������.��<�f���o�2;
�a������@��?��Lev�q����a���o�av�r&�	���%�.���3�0� i�����Qf&M2��0i�Y	��0i�������1��6rV����1�"�NFx^*����50�r�A��Fn�����<ww/��Nob�~��n��q���{�����}��]f�%�p
K]av��Q+�����{��za��(��HR�0;����tf��+��G�]�tm�����Q��K���I��_�������.L_������(��XO�av��6�2���N����0�i��;�-P�0N�������v��h#Xq�/�f��f���"�A������JO�6	\wtA��PK����;C��Wr�Nk��;�^�DJ�0�F��;�����rl���-���Ny��� g|��4i���I��F!w=s�E�h����;�����I��o�r���E%w��p��]p[��5WtG��]��.?�v�t,�C�z����������+�����N�7���?a�#�zG�E�������;�^J��|~����Xq��1��q�i/�J�W�<_�!B�j�F�T��ic��q�/���q���qw�k��M��)�xQ������1���w�(�o��o��:�S�c�����EG$O�/B��z�sw��f2O�W�{}������g�|����^������==!wk<_}	������������9���������k�Y)A/�N	zc�Zy#���}�7"��*l����������Q����W_���
o��YW�q�$#��ANc^��� i�F����1J��5"�S*�:5�����[�Oxc��� ����7V���F�rZ�*��W<T�����)�4��������s�`�p;���+�� q;�v
����e��a���v��.���}�QN��9����]�4Y�q�0i�.\N�N�&���$��7N��p;���H��0�n���]"� ����5;�9�::"nE��=��k�i<
�^����8����`p@�M�m�w��rL�gj4�����U���g��<���-J���AW���b�y��3'Ih���!4�7Na��� g��� i�����0i��
N�0	���1�G�y�4��$�15Ch�/�>v�y�I#4/�-�!�����(��4�mDc�'��m�^u�������V�gY�V�]b�$�V4on
��0�<��_�J�za|}+��H�*:s9��7=_;�0������� g���(i����0i|�&M��	���q�����7�}���7��C�����X�xA���2�����]{�o��)�xr��vx��^��y/���3�<����6��b��\��y�����n��-���������3��=�.rb�X�,���1������N�1�������%M��y�{�k���8il��I��6_��ob
}���������(m�����x3�aq�����o�r��ax������O�W�����#���_�K�^���(���z�>��+���w�����/��������yyS�ff�!�
�YQH�5d���	zj0'%����+���#�	��XO�:�F&|�8�	�D��Qe�d�4g�LIc;�D����hd��D<��1dZ!��;k��_����_Y�L"���L"�����F&����!���q�b_>���/�����#�7���������Q4���q>��� ��pK�_0�K�2<�.z&����-�/���{������`��+�M9^^��e��������a�Y8^�6Y����0m���*��*q��XO��������s�KG�������q�6��?g?�<�o�`���64�2n�^�����m7�i�th�e������]��qf���������J���	�UN���.y�y��g���8��iW���q��yR��L�(���.����6���1�����i�}�m��-7#�tA��
���!��h�RN���e�q:x��4Nl����o�-�m���������<4�.�=4������	�����}������'&tj��G�%���P��zj���G�g�G{�%h�w��=���Qh���c{�����r���jsF�^�4vo�4���IS���IS2~-N��9J�������\��x0�3����2v�+m���+m�b���y`}������vo�}��|���(�{�+�k�^�����b`���=���+����=��������=�^w��=��83Z��a��sl��O��m����%�[����~����g{�4�9a{�4K�Y��=Lc���� i6��������"e{���RE��%
���7��:p=�3lw�z���Q�����<�;��s^?���s~�����|�~�z�}/��?z�lv��'���[������������_����I�o�F��+7�@�(�Mzj��(7h�0J�)@�[#�#��������p���*O�M���OE�y�+t�MY�x*��
�b]`=�	4�&	Oh�Bx*@/������=��zb��G��_��o,>��4��g�w����?s?��7_�|�f�|)� L"�!Lv�mU�]��������[bx���B�y�CH��+�[�>
�3bNH@���|A��L�y?-��������������.n��n'a������c�F�����a8jH@O?s!}����
���a���s�#}����6N�Yv���?\/���K}��?S�������C\�����?��[�;�������Z�F�7�1��_�z�w���������m
�,���P��U�����~-
B��n��X�&��w?�l���7��'^C��F��p5B�z�����s�mV�@/��%���%���P�)~o������� <6������q����C��W�{�����H���D�����R\�<�nb����v� ��i�T6���%�}�{�
�Cw��/H6_��^],B�^�������{���j�r�v����^
�q��E������d�#����.t����o�����&���6N�F������vot�����x�=�5h�@�7_���{������t�3���x�y��m7�yy������b��V}��?"�����>��G����^��2?�OCl��vKW5Bo���n���K�������������0�5a~]$������[h$
������+��m�<�.<��6�g%�����p�R������N3��|���7]������������;������/���=O�z�i�o7���p�N��}
�|�}���H�$,�Nk��"=�U%+��U[��B'q?��"�|��+�b\�$n��2�it�V���M%�"\�n�����Q:	�S��H�$���s��I�^:�B'q�M(_t����9u�v[o3���qb�O����63n��|�=?y����m|����7��������v�k�[����X�g���t���������z��>
���
���qG+���1�UY@�g@%�w
��n���+����"���+��P��/���0=����,�
!L���Haz=w��0=�B����1-L���0��������'L�����}!�[��7]������;�VQ"���R�m7�����*�����AL�	�Q�0���!�1�N�@���3�w]dDM��nJ�]���#��;_>eLz���B�|��JB��|�+1�<��;��Zs���*!�0?D���!���p���<_�tx��H(`;�k�t��/�(]1�@��������JW��(��>/�����p���~`��s@������ ��c���r����_����hD��7F
cczQ�����E��g�����2��c�
1/�O��E��2���2>��;�_���~�F���4��A���wm�h5���#��0�E�S����r��2p���np^1<�6��(�<�O"X�'����uD?0{�a�f���@�0��F�������q��q�F�c���Q�|���`/
ID��;��#���+�����W�}�~�u{QD*
�{ji����������p�
�#��;i��4���M���/������g�v�c`�O��"`9��?��������O�����;}�~_N���\��)VkC��!Z�B��c�swD1�(�{f�(&`/�9c#���jk
"�����hg��[��MD�&(+��
w�8a�DV�&F��\����$@���]F7�:_�03��n�Mg����?X�&������t{�M��M��E�����F7kW,t�������3��n��D��q����I�#<��aP��Yh	-�JiD���B��=��\�wE���v��4P�1��E��(�C����������~�^� ����2�~��F�`O
�3�~�]S[��Kc���������#����3}�����U��!�P1?����!�=Y�X�W(��+�����t=���t��@���F�4�Q1��'���C�G,��X `/����{c�d���1l����-e��^�\��E,����"R�>ef����e�����qW�;��2b�oo���Y`p����/R���`�x`�C��W�@N�XX`���"��BX�ba���Zo������5��|�*�q��%J	��
vU�	aWQA���g ;�QAF�����r�2�
zM�	��o$E��k�
�����T���ZOxWyz,T�w��
��qWEo����!*H�MiT��m/���-�8�
2p� X�� �V�1��B�~`	�VL�c�c����!vM�I�<G;��}��:��#�G�/�Kc��?D_X���}i��n��S�z��Y� �)��=u����v��0���c��w����Z���/�����3T�zL�5����W,��+�_m(����X�_1���,�;l?o?����1�����?������������������_���g�_g�|�n��?�SIN����n��Po&��;y�b�h��\v��!Y*���_$Gt�g����c�k�d8�����a����;�M��V�p���Gt8H��h)t8���{���0{���8{\��^�����h;R����v�J��b�|g��os3���E�����]>q&���@��1ef:O��~}~h�����b-ts'-�
�������9���]!�;�Ua��u�����]#�Gq0��F���Bhr������1�o��0������m	\���jIU��#2��J�g��J�g����)B��q|F����&2���T����=5����!��B?�Y�������"b�
������J�P\s��"�9_@kW|>o*����
tAW�#O'��l�W�m���+Z��8������?�fe}�=3n9e}��3��>��Q�'�����*�ctkf��>F_;lAX_�<Y>�X_�=>���'�U��q���}k�'_XG�0c�e�$_8(�/���m���=Z��EA����W<p��P4����������0d����r�|�f{tr���>��?2~�`
�'����|����!v�����Q��g��{c�D���{���)�v�p�V���e��4F����1�H��gO�eG�_q���F��nR����w����3+y�����X������+o��V���k�<o����x�����h��j�����!�/�D
���G&�l��2�������?�G���_�3Yn��{cT����{n�n����n1������T�m��O���p�Hq���_��J�����0�J?����Tsys�g�����'<VF�/@���A<
y��o]�����|������q�/XsZK��6���5�_�7�:�N}��%�^nSW��4�;Y��+l��hI��������1���=5:�G�C=M_���������d�4a(�D��#�)�Dt��F�%�oc��,M����5�U����<��'KY�Vb�
�%��x[9%��7�{f�=�he�=����D���Pr������wy4a�3�����`��"�9�����������6��#�s/*#�����]8f5���x�gyq����B���Oi �;�F4��`�D�@�v��G4C��w(����6~��b����	D��m?H �o��9G�S@K�gD��)x[l�&wD1�Q�\����m�Y[����:������/��pD}e|��2rc���-�Y�-���zh��5xk�Y��`�ym�1���_��
;w�}g������)+Z��8[(�#d��KyaW�������I��6��-������\���0��yE���?Y%���qD��a~q��]����*mc'��E�S�OeOM?	�o���>z�<�W��x`}��m�>^�������j���(�����AW��?2U�`k��g���G�D�#��A�F�C=��~��#�)�C��m?}���WN3�R?D�7d�r�o��o(���������v"���N�R?���}}s��Q���S�!kD�����C�����(�U���������j������8��$Zs��Ly8�b8
,d��B&
F�BF���G&�l
��"����?��z��P�i���aL&����?D�;�����~0���2���CU�W�>#��O�5Y�_�?Y�&�o���5���~��A����3K����!�3BsD�:�>���t�D�a��5�@�G�5�/�N�RB��=�����~�k��FO��]��_�������Qr�|��^��^fnO	A�=%���Tj	�����������L�NM��Zb��������7���K���y�Tb��+g���(pSb$�_LX�=#bfO���1�P%�k�&S�%F�����2���RBF_v�#b����\:J�!i�Z��2��?�7j@��e{X������.0*d���*�"������\���H����h���E�"���F$���Eu~���b��a�J1�Un���*���k�2jD��) �A��>�q�d�b�eJ����C_�������4���;�S�/v�m�j>��
2!��~��Z�-.Z�q��/�M[�ah��7�$���@m1Xs�_a�yx�q��I���p��Py!;�\��{j��)��P����]�c2q�8��1���]�����_V��+�wV�_�>>���e~q����q���/����&�q���&�}Q���m�}Q��
�����e����^�����@����&8������������-l���������^�#������G&�l
�"���!��]F1�5����CF�"����@D_9n�Jtc�J���z
,�����+!�{aa2�J1����HQ�|e��7��"�jF��4����75��

�g����[-$0��?-���X`'��@����������W�y�X��G��l
#����#��V�.c�����O���1j$G|�=7��G|�W�w������K�g�q?K�`�=|��">��v�\���*sAF���#>��|��"����A��A<��&�~�K
���������������|/)������>^�����]�g�^�B=]�����3@��T��1�`���;^�_����C�?Y����X���b�k��vU#a/n�]R�T��������]�����l�h���
�Y���a�1���S%��fW��oDg��o�#b��Jg1�fU:Kw��������������^���[L|�D���1#s��=0�k���@�&m�
�3�=��3O���FNKz����y�����x��n"p�qb1p�oa���N+l�]q����B��@;����5���� b��Gd�g�@�C�USR{m�w�"����;���'�Q?��@��E�#7�/AVY �;����,�"���K�[����f���@�^Z�-�.����3b�����{�}<>�]��
6��dh��.p^�ll�+JkW,l�v��k��
"p�e����x�>�b�L���
�v?08A�o��	��W�l��
+l��g�"�l��F���A�I��T��+��l���n�A���a��l����6H�+����AB�������A�����A��O��	{��[� gi��J� ����x�6�yj����G�\�2�o�`CVj,��&)3p�=.`���h,�x��2pA�s�����t��A*k�;Q*�����
"v�0H�3���� `[M��~���G�R�l��Y5`Dqg����RAD_XN��n.�E���7���]��L�S[� `��zD����t��RA��|u��
�^N����o��G�l*�YdLT�v��o��
"p��
�
�P��P�*X|���b����#CU��j�C9�K;�U1���<];��}��� ��E�f�h/'��P���x��������?@��$���@�H��S�VmD�{n�'����@���-����^N����������?�P�u��?L�|_�\����������������+>�c�>}��m/��*���_�wI���B�vC
��J@.{jF�u��*�����5"��}'�I�K?�kG�RR����(�D���w��2@wJ���ql��Tr���1��T�]S,x^��u��8PR	�K��(����`~������`���V��'�����PV\^>���,�9a�����*k��U��BX%�O�����J<�Y�������h�2mD�h�Uz"bU���1Q?����%�Y.�xo�L�_��5sT}Qd���K��Z��='�~�g�(������G������~�=w����af�-
F�w2��{�&�/���/��S�����P���Q?��~��a��W��_-�P?�?T�{�g�X�_����!p�{r�������9*Z��rUU!c�P?��9�0����fW�~������~�^$G��/�&L�~��2N�R?Bw���LGD�G�����qs�G�s��V�gf�AV�������+6T�~����.���?�k�������V�{�WRJX��F��OE�~��ZJ�y��1*k�9V����o��C�����<j��{a�@�����:��/�K��(�C������������k,f���_}9"����?�v8������%y��?�^:���?�Ig����l��
����8�^�4��Y�U���������!p�
U�_m�����X�_1���,���}����-��|�I�����?t�&q�����%g�\���x����{i��(�Ct��W����,	���7�L���#R���������f��}��/�L���������w�,�w��4���5�������C�
����������~�Z��C!��4�������K���p?-nF�f7	A��$jLQV^	���J�6���W������&��Q�3�����`�[�+�O���F�������"�1���1�w�3`O�w`���]�Y�wxMy!���Fc|����cw�a�(/��B�Oln�`�	�8o0�8&�8��r�m���
���<���+�Y����?0��@k�E\nQy!c��vUy!a/�u+
��4|<D^����OB�}������n���<�W�e�?��#RcTH�w��O0!��A����������.���8k%���+������kS����=q�#����y���
�@^d��Av��h����U��~�:KjW����F��Q������1v~����v�����2�~��E�/�������!�Sq9�~��,aL�E��43G�#b�gJ�������gB�03���~��5��������T�����
R��i����C���.�,d�
�Wc�~�+���.���'����ie���#�J6_/6���i�[*�C������,$���B��Y^�R��e�	q��}a����������z�Iu��~g1Gdnp4��}�~g	a�n��33_3������S��(3'F���MfN��p�|�<�6��9Y!�!p������6��j���!p��
����p>.�|�?2��`�4?@��&f��c���a����#��Un2��E�/�KCoQ������|��2�8G���4� 3�n�H��4a;>�#��Un2��k������{��J��/��R��Q��4Wh~������B�t��B�W����+>l?�?��Wg����_����~������>~��y�������e����n?�[����]�X����z��~���t���
E� ��v�Y�����l�����r��{9����p����l<^����h���8�O=���}<{��U�i�9�"����$��n"��[B����G_9��O���o�iT���Jc��e��I����o��G�����n����u������
G�hx��g#?�l�E��^���;{�����������{5?����G��������Q�������<�7����}}>E����,�W�����<9��J���M8���_]}��&�����6���]8��������_�S�l8k������s���������g��_�x{.�e�#��DB(nBlK�-!D�I�+���/B��K�l4���@�F��H
��U$���HWr�"!��q�=���7�W�?�p��r�*"'p��74���5D�j�A����Z#'�^�*'��"'���*'���*'����9�����*'p4���UN�x�������c��"'pL&OSN`��oOR9����{�����}��.��s����4u�)E��7��D�Btd��_��i>���8���g%_�?t�8�_���$�]��~$�"20pV��!:�ia���kn"�E�o&��I��H�5C-�H������%��@b�"��
y��Hbdc��J��K�Hbl���$����J�c2q��TV@������B���E��
�7�HV(F�ge��Pz��d�9k� �B��:�J������HE�C�Y!�W�o�*+`<��%#Y������x�n������������O.)��1�+)X�_��������~��!]������4��w9?<L4��8�����'�?srTe@�������f��;(������t�`�Y����/���r��p�r��D�����Gf
l��'KDp���
�/8����!@.�i�"���ix*8`4��=T����C��L��|NTp��L��Z}���������`$8���#����	��*8��n��;����^	�\$8�jY��^�"��P|����^M�����j�����M�Cz��
�;K'�Hp�\��hJ>������#�Q�7_4����SU�������y���1���'�
Ql�������1�C5� C����\O��#��q�o`��P��#���#��	�Fa��!���W����@.*i��B�1^�8�0`b_��0�5?S�&^�i�Q�
�������Tm���cS����
���Hm�EV�����
�w��
�w�Hm(�cGjC�;R9_66R�;�7a�;�x�?��c�N��6��bWU�
���B#������:>�yo��6���F�DS���CS�(8�/o����R�@����@�����w��C�OH��Ee�:���;�;!y���mLC��@��$����SX����9������}}��=��D�~	ZO���Z"`����F�p���5��rA��G�������
����H�����40{i�H`L&�� -}f���D�`?�-�#���������t��}�&)*���WU�(�WG�E���oP�������^--�{5����Ex�fm$��������{�8�T�j�m�T ��)e����&LEeD��A�V<_tq9�/�
\�|���������K�@�t_ p��[*#�������d�K.����,����D��=������������U�DQ�����b���P��B�+
x$J��W�FQ d�lA��*�$/�a��Q8"�$���p� �lFx������	G������#���������D�����iUd(�jEd��jUd��}����
?���M�������W�����0���v�xU���1�8.�"20�3IE�h?�VC"2���T�	������`�7Ao��MS��\0�"�N��i
�M����MS(n��5������I������C���^q��	�1nz�����zm=@k��Z`�`_O�}=!.��HO��B.�(A�M��'`��%�#=�������
�dLDOx���	�
=7a�|�������q�'���#=����EzB�M;�j�Z��������jGzBp���<���6�,zBx�&�UO���(�?��j��f�0&��l�'��G]�D_����Q����������EQ(�,"�t@DS�^�h
tA�E]�`A��$h����|���[�B=���&�E��.`����O%���f���������K�
endstream
endobj
30
0
obj
49834
endobj
31
0
obj
[
]
endobj
32
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
33
0
R
/Resources
34
0
R
/Annots
36
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
33
0
obj
<<
/Filter
/FlateDecode
/Length
35
0
R
>>
stream
x���������y��K/SJ�����YO_t�Y��_LU%�Nx�P��cgm����pB��������������+���������o�w���/��G���WJ�������������������mg�oO�_������/x���������������G����!���	�������������?����������|�[��{�j'��N(�G@HZ����N���\��`!A�������Pi~Z�m����,B�p���{�����%��  ��?�	�o�l	�-�7�=h>�=K��Bn�CNh>��	�
�7�=h>�T��Ah!��1Nh>��	�
�7�=h>�rJ���Bn�c��|�g��o�{�|�J���Bn�c��|�g��o�{�|~�C�� X�m��o�������4��I��]������,B�p���{�!���Ah!��1Nh>��	�
�7�=h>�s��!/����C8wi~n8�q�A�!\�4?�r}@Nh>��������4���%�� X�m�C�s���B�p���{����@^��8��YD����4B��@�����|�g��o�{�|�,����pB�!����
�7�=h>�K�Q8��pB�!\���
�7�=h�	�K�A����\�>��Y	��7�=h>�$��(���pB�!��EHn8�q�A�!YD!�����C�?�� �p|����C���BY��	��Pe9��o�{�|�&�� X�m���1�B�p���{�a��@�����|�,�p���{�!�r 
�z}Nh>�$��(�p|����C(��BZ��	��`!A�������Pe9��^����r 
7�����&�M�A����TY�c�������4�.��(l��8��vYD����4B��@�����|�g��o�{�|�,����pB�!��EHn8�q�A�!\����^�����@n8�q�A�M(/Y�Bn�s���g-$w�����YD��^�����@n8�q�A�!dYD�X��	���e9��o�{�|�,����pB�!��EHn8�q�A�!\����^�����@n8�q�A�M8_��������8&��ZH�8�q�A�!���k�>'4�!��(�p|����C(����^����,B�p���{���r 
e�>'4��Y�����4����r r������?k!A���������r 
�z}Nh>�]�Q��������d9�}�>'4B��@n8�q�A�!YD!�����C(���
�7�=h>�*��(�����|�g��o�{�|�M�A����'4��Y	��7�=h>�]�Q���pB�!����
�7�=h>�$��(���8���,�p���{����@�z}Nh>��	�
�7�=h>�K�Q8��pB�!��EHn8�q�A���o/�Bn�c���&���� �r|����C8�O^��9���C���o�{�|9I��p,����C�I���o�{�|g��!/����C8�4?7������"���\����,B�p���{�o��:�7?r������?k!A�������pT�O^��9���*�	�
�7�=h>�|I��p,����C��4?7������&�B^��	��`!A������7�g��������8��&��ZH�8�q�A�!��>���\��a��An8�q�A�!$YDa_��	���d9��o�{�|E�QH��8���,�p���{���r 
e�>'4B��@n8�q�A�M86Y�Bn�Se}�	���;�o�{�|�,�������C�e9��o�{�|I�Q���pB�!$YD����4B��@�z}Nh>�"��(�p|����C�d9��^����,B�p���{�oBz�r r������?k!A�������p�r 
�����|�,�p���{�!�r 
�z}Nh>�,��(�p|����C8e9��^�����@n8�q�A�!\����^�����@n8�q�A�M�/Y�Bn�s���g-$w�����YD��^�����@n8�q�A�!dYD�X��	���e9��o�{�|�,����pB�!����
�7�=h�	e��@,��?���1�B�p���{�a��@�����|�g��o�{�|I�Q���pB�!$YD����4B��@�z}Nh>�"��(�q\k�w���F��}��������(T1�(�p|����7���`�`!��i��|���;�o�{�|v1�(ls���{��S�?�� �p|�������`���}�7��O!��F����5��"�4�m��wl>�"��o�{�|�l���}�����ln8�q�Q��P_b�A�����K�S/��Y	��7�=j�	�l^s���{��S�?�� �p|�������`�p�}�7��O!��F����5��S�(��o���c�)���G����5��K�Q8�����S�d9��o�{��&\/Y�Bn�s���� ��ZH�8�q�Q�M8d9��z}`��|
�g��o�{�|�,�p���	���e9��o�{�|NYD!���	��`!A�����G�7���@����8��.YD����5�#���A@�m.YX�	��-$������&H���/����S������5�)@8n����c�)H��pW��5�=j�	R�p ��5��{��S����N�k�{��&��a�����q��|/)@�;�o�{�|��@��k����� B���]����Q�w����_��:���_�_����������n�����_������g�����pc�f���� ?=��v�t�u����^��v!�����&���� x���m�j�u?r��������������?:4�,$���������]uK���������5[������!A���?�_v����wL��K�Jt��i?�*qth YH������.�����v)�6ut-$Sv�,�����m������!����0����&��������})O����/���>�_��_>�]6a�o�A��_���ut��cf?�f;?�)�����������'��K�)	8���� ��v7���GM�Pkj-I�D���st���t3�����wX�y"|�@��eX�)�������u{/2����/ �k"xt����(��aa��;t�N"$�(c@�����N��i���������l�� t��z���r�mC���^�(�K_l\�XH<���g�����"�Y|���J����s��u`*�L��i�

$	�\m{���rdO�*��$��Ec���������U��|�F4�6�D��;�l�t>���-����<f#����O��`�M��w�!A�����qh��6_a:�{��:I�3xJO~P3$��j:�Z�PkH:&��:��4�F�5*@j��Bw�U7���ng7�j�%w����]�Y�u�s(��)�,�!A����rd�sJ�PV������O��-$��k7Iw����z��K��dY�G�P�� 8��s�u[8������p������6��A�~�T)	��;���M�L����A�
?���y��'$�~���i������s(,n4���e��9z��+E�-$�_>H]*��o�������f!Aw=�3Gfq��
����`�p�c"5���E��+Cax�Gi+���D�d�&t����M����	�}�kQ-$7l��/�U��5!a�!�B���q6�_�<��w������'ZO{
NsB��{{�� t�y�ug<�Lk����,$�����������G������w��42�	)K��A�!����u
_�;���,$���7o����Y���_!������`������KK��g(�w�<���5z���\6�e�A.�2��~dw���eT�&�������xJO~p3$�R������"6a���K7Z]C�-a���j����(~|��zw����+�BH���;���0_2� T�� ����3��|��z���t!A���h��[�%���	v$B��Ux�9E�5�{��L���@�VL�B�0ew�T���g���J7��gL:�K"�r
ND���e!A�����'S�^^8{n(u
y0��a���B�V��'O�;'�&05����O�4BK�^2��H��:�Y6a�S�A.���_7k���&�mV�&��g�n��:%A'?��hN��<#�"�Z���0���@�!F[D�V�U�D��q�<����4FBH<����'�:��lo�K���5�>����95K��'�v7����.^Z#R�&�q�	Bwz����s��7Z�dXn�`�]�U��� �/�??v�Cg���3"YKB�� L��x�����F��zw���a������o'Op='��6M�k{�����d�#$��6yI4v��]|��i������>�|mV�&���g��	9%!'?��i����v�Z^���1�L��iTZ$��*��'B��et>c�2� !Ax�P�-	����x���P�&��5y%��j��!$2�
x~���}v�
�{�:#�&�I�	B)�Km�t�������EK�L�B�����+�w�`�]�Uz�� t�������DdlI ��bo)���pDC��s�-$r��u�w�$�!�P�s"������b�u.��MF4B�0����u
�l/��	�>����\��������D�?��i�&g������fH�8�c���"6A��O�U�m�YR�!��7���&��1OM	�����?�Zc�����`BH�}��n�����!A�M����ho�?��v��	��}�f!A���
�������g	Rj!A�2{�������G	���^�kl� r�$�a/GZgr�
�	`YH�����\��-5�r�-$_��K���;ODv&��B� d�q�_�u{�iwF.����3B������]��.��n�nsTgw
NCDv�+_cA���������N��`�$���9B�������w��:lhZ��*�t�A���+�eggGF>�n������M?jp:�&�����M32r>�������������>Bo_� �'�V{��w����~e��	@YH<��E�_�u���J'GN���__������l�l��$(	����t^dl���M0B����������|��!	!A�b���Z5�r(�	�C����vy�_d�M��w�!A����8�
Y�.�|M??�6��3��K�FOI���s�����������S�7B��m�i
N�@�!�!A��mn������y��v�q�� ��k�f��;=�a��C�/�� t�����������
�06�,$7'�c������%�A�8����5��8��p,$��u�C���&!A���	�<N��rO!!A���y��i;r	�	�'?�sH.����3C�����_�������)H���^Zfx�Sx���!A�0����v-��EP����\�-�-rx�42*CC�����w��� ��z� CH��HIg����
+46��5<����T�=��������!A�Ou��7v����Yc�|d�9!�&��a��!���~�2}���� ��1�",|��U�\w!W�"B���o?��5(]yK���w�~��|��pF#�` �a|����:�kd��%LYn1B���O}��;[D�"�!Apd{n}F��{�l��ev��fH<���~���:�kl:#2�]P����9�x��;%a'?��){�V�t-��EH����VY������P�0�r���zM�ih�%��	�G/�����Oag�	B�Co?x����N$JM���:	B����	�ip��%1&�e!A����;������!Ap��Yn��a'�Q�������R����,$����wud`���M0B����
��54]���,�!A�h��}�����r(�	�CsM�[y���d��	��^3$M�\���iR��v!�k"x4��]��-��@�NI���o����dM~T��A�"�tL�)�����\���y"��^�3�Of�� x�0���E��I�3���n����Oag�%B���>X������sI�QaI�� X��mT�62-�2�&�B� ����~:4x�^���K�q*
��i�H���ZH�L�����~���H#7 	BO��m����Qi���e���������}��A"���m!A��}[��g��	��^#$�w����a�~�MD"�*_cA����t?C�$��7B������t���"�t����z����i��^U�X�����,�x�i��>e����A���x����2�L�D'�B�p���H��;����I	�N+��n�E���VP��\�	��g���W �1�)@�L�i��N�������������ut�>"$�����
N�D6��e!A���[J:����F6�@	���_���>iid�{�� ��^���	���I$s2��f!�E�It�]|���>
�s��b�l���l~�S*_�w[���VRSj���!A����F��E��)���u�AF�D*W�U�D�~/���
}� �`$���W�=������d�!$�~�O��|
9K��T�%C����?���z��R�%
����Q�������@�� x�c������I�A��OX��'�\@���az���hR��l�� �.�"��)�\�BH<{�^���E��.��(
!A��e]*:��v!��~3$����O�=�Ja�!�������w��K�)	:�Q�� �~*�	Ja�kP:&�'S����*��&)e]H�y"z���.��6)�]�BH���D��.`C�\��W����w!:K/�h�t {����gn7��H��p������^,��.h�U���Q���a��v������J'�m��J+����
i\��az�o��
�4�	FBH<zY�����CZ��6#$_���Ze������ x�+�}����_���&����� 8t
e{&�id$��]@����|mF���*dW?���b�@��*@C������O�ARb��S�5B�����=C�)��	I��2�<;����s��O)9�_R�$
��~@�4���n6��#DW!!$������K�����-eGH�� �z=>v����!�#!$���8'K��!
!A�_�a!6N�R���C!$�m�0��*��fd�@Br��fH<���i�s��
$d�k"x�r_��tJ�N~�3$�4��!�"�tL�5y�����)JBR����M?�
!�C0B���G�r>���� Lg���3����g��x��r-$2�S9*5�����*[l7��A/�"���]waW���A�O���4+,���ZH�W���$�p+c7(	���`�D�L��#���� h��� 
����2�-$_|U�y���&����� x�����Ya��*_cA�<�x�o�Vd���� GH���f��X����1����Q���1N����[H��/����OAgW������
�xI=���O��'��W�Xu��/�8���#������[���_�q\��	�/s��/�8����_���� � �8BH<y����T�������^�2�F��A�q�� 8r����u�}}�S�ev��fH<�y�8�A�q������,43�
��_Jq�� gH|�&; [�2��}LO^~�����-I%�A�6G���%�BR�&�w���H��t!A�YeQ��s|>��SH'��c�-$���z�	|���*cC���D�l������&8�ut�^"$������Pm3C��
��l�&�G/NO��mf�	<e������cd8��!������~>,�Q�R��	��/?Z[��"�l�.��	�cw���,od�8��IP������)	:���� x������"�Z���� �����EO�����_$���'o��D��_y��CH����3���t�N"$2������>�yw���	8w�B�P�z|h*���������3�����O�]wAW�%B��e�i��M�DR�e!A��UB��a��6��C�s�oO��h�\���� �S����G$R2�w��_Z�<��&��;�� x�rw�������vA�k"x�r'��tJ�N~`3$��]^��kV:&����������,�
�����K��e��
}�HCH��/���54�Y�4�Az���4��)�,}DH�7���������wg�H�>B���-$W�{�n���_c�-�jQ-$�^la����B��I	������������ZH�����9HW9�s>C�
��,$z�9�����B�kh���Y����G�m���}��="���m!A��.R���]6A�]��������nT����W�*h~�NI���m�A�����g�Z]���1���1��Q�G�r�-$_�E�52-
i��l	��|oZ@�S�Y���Ag���������(dQM�����g��>�4(KdL����D��w����uf��!$��E2M�ihz��$$	�mw��
W2�	<�����B�q��dI[���� x�p{OW(���Aw���IF4B� ���Z4C�M����!A���	�����?����D�lv���jJBM~X3$���&�!�"�tL�A�'A�l��7P!��<�{|��%cd�2� ��s"<�1;�kL� �%U	�0��%��'�������q��Y��@�C^��m!A�'uX�_�t�fE7`y�����������G_�B�46c�]�U��� tlM��x�4���CZ�b!A�=^��Y��a~�6��|����/4��R�,7!A��C���P��Y������� ���$�M��w�!A����K��I��!������eK��^*^��\�� ���\7�K��O��	�'����/%/�V�&�Ww� %/H��K�aL��e���6�����m��i	B�7�6}k c��Z`B����D������R���*�CH<y��� �.���_�����/U.�4��]�w���1�})q0�8��A���>�s)pB���O7�]6A�i�A���������|M^�i8)	'�a�� �a<KX�!�Z�Z�@�1�O�,;�2��R����'�����I�
rN?	���hy�_�;#�� C�\A�����F&E+H��E���>w>&E+>Bo}8e�B�Pf�<�Rb��1�LjV���[�aF��Bt�]��	���*
6�NjWe!A���vt5)^A�	<����~/�=�M���@!$[�����L�Q�?�� �����!�et�]dH����M�^R�L@�k"D�����PSj���!A��"���*��)ap�G/��cRL@�<��]gd��*���!A����
:{��/]�*�D����r>����	����[��@�C��2�m!A����M`mRl2��>��������M�B��m��mRl�j!A�~/����I	����a��~.�QM��
  YH�xCN����g d!A�wz���N��M��w!A���?k�����&���0�.,������FH��2�t���"6ca~C��@��*`�@T�cA'��2�g�S��	 YH�%��T�B�5�����47�,Br��YHt���@��+mw>s�s��zk�)��Dh!������3��!FH<�|��m��iDH���,$�v����� ���S������������X���#$_�`�����2"Ys!$S��Gx����&��;�� ����h�I��p���g�5}S�������	�M��#��E8���M�D�{�����w|�8�IOV�a����`ub�S��}N�gOgg �I�A�#�!A�W�aFr>���s	�`E��J��|�>����}V����<�46�KB�����sFx�^��	����C[��Iq�,$��O���$D��������}�&eI@��#��s"��^|�N���$�w(	!A����/����7C�������&UI@�P�&���w���(	��n��������?�����"�tL��.8�����2� �p�<����<#�2� �l���_���gEI^2� T�����)iX���g�|
9K��z����M��-3!�j��� $�]��M���pHCC����D���y8}���J��i���� /46���x��k"{���F�y#�&�X�c"��}��hL8V{;'�����C�\#��/�	�'�o���\6�e�a:��+�/X��r�G{X�II8�d���@le!���"�tL������p@�B���y"�'J�eP���S���}N���F��hh��H��_�
�|
:K'���0W�g����x��@djM�����}<�>����4AK�L����D����t9�]�U:�� L{}_�l� ��$(	B������hn�����}L��r/+]�����!f��	���w_o�s@dg2��a��u[��'�lB.��	��R�<���&�HIX������5�!�Z^� cH�i^L�t���?!O�B�y"x�*���v���|��FH��^��*�	9�.�rM��9�/Xi8���0�t!A�k<������y��&u!7��U�� X����1�����#Y���ZH��P����]waW���A�\�����iI����ZHnz=Li<��5�	@YHz�}�L�iTz��fY���a@�7���<	��k	�2��j�S8eN�}CH_��X��QM $_caD��OBjJBM~�"$��8��b��E��"c��9������!���y,<���0��2�L�B� =^}7Ckh:!V���8^d����O!g������D#�|%�Y2�&��i	��}%>���Vgy�	<����^�p�9���.�*�DH<|�i������!JB�� L/���%�p;�������0����g�X�;�� |���zt?�E2��)|���vg��	��~3$_��s��/Zj�����D���w|�K�)	5�A�� ��������]��kT:&B������.�"��*��'��������}�������������56�9�.�����}F����t!A�M���s`�R��#���3�-$��4���J:��7��>'��=��C���&DW�%B����B=�J��!����Dpl�*7)����9!�|}L��E����8���������P|�M��*'�w(	!A��E������	����!A���ls�tF�n���5���1OI��q���a����kr-J�Dxp�{t�aF�DW�T�Dx�\l�S��}N���7���T��e�k"L�7G���w>$5V>Bo]v
2B��g��iBRh`�XH<x�u\HJ��]��	B��}�����X��~M�H���B&�Ij��� ������3��4����An�b��9��Y�?D�P	�g��w@��pF��:+D�m�a�@�R;�����
Y�����0*PSj��!Ax6�;���+d�"�tLa��8UF�G�����<��d�
^V���y�\!����� x�h�5x�	2R6#C�\�~u�x�{��O�f�B�058�h�f9[z2�&��n	����G�3TB�����gI�	</������OG3t�]��	�G?<Tdz�eG&����D��wFHkiL���EY.4B� z�z��"�G��P0B�����r��
$aH����H��/HAH��:��Hj-B�E ���w�U�.�@��U�D������n��$D�~`1$��i��� @����c�{}7�K	��t!A�l\��d� ?��|�C�:�8qTw	��<����/eH�6���tW��?!���!!�J7-$s�mE��!��ZH���Y��$)C��a�^�.fp��"�B���eu����� ��������r��\|!O��X�l:�T!*_c��[��� !<�!�� �����t���"�t��{��'0��	�	5�������E�)��,$��o��>(�H)�Xx~w�oR���,]�� �c;9I�+����?Bo�8�B��B��F;BhR]����@KL����D����|]wAW�$B�0E�>X������

����&�G/~|��hdx��1<yQ
����t?K���i�A������9�eI/�	�cw�.2%�l�.��	�g�������)at���'"O�����������;�
G�u�g�����gH������!�Z]���1<zyv,���i�����j�����p4��Q!i���� x���DI�������|�k]H��|��=p�������@J�]��� th]�s���!�@���������+��_���m��>&��q��L��!A����>�e}�6�s�T�?D�P	�ca`�M����!A���t�)_��
�|M�>?��mv]�K�n���!d'?����9����x��(���{���s�`T��!���pK���s��!����� x�d�Z��$UC�*�D���jw��#�C��O�a6y��������L�2��&��k	B������ ����m���GuZ���4�ur�."$�|���<���4�32L��x��k"tduc�8f��������p����g8�z;'��������p����e�#2r�����w�����.����6C�����0����|Mg%������tJ�N~�2$��&x-�EX��_%jU����x�v�r���X�of��3�Ojp��~N�~x�6�0@#C�\���n3;����I�a�J�JZg�|���bM�8S���Bn?J��4\c�-GjQ-$�~|�(�uv�nZH���W�����"=KBj!A���l8�����A���:/ll����Yn��A��j��J$i2�-$B^����l�.��	�g/
�F���J$i���5�J����Sr�C!A�N/,�.h�Z]���1���]�~�*]��������j�]o���Od&d!A������y���6��4J$k2�,$�~��`�S�Y�i!A��_2������3:����s���;'���� ������6*-�2&x�9:�����F\wW�B� ��y=����A"}K��� x�j�=����GC��3��������t���?Z6��^#$���0����3Hdt2���a��;W{�{�$�l�.��	�G����5*���.�|MO�m��M������fH<z��������c"x�2��2�h�����j�_u��g�S�|~N��:M�kh:#�8d	��G6=pJ��)�,�DH�����m���xg�������-$�>a/*SN�\��}~N�5�uv�~"$��{���50�I\�����FH�3&���&���c"L;���	8��2�,w!A����#Cw���MF7B������;�3v��]|���y�/���U�1�M�D�*_������Z8�9%!'?���>�K��kt-BJ�D4#�Vg<>�����A"��B�y"x46 �[�2���q�g����n���N�B� h��$�g4@C�S�Y:�� Lg��!7���Z9
:$��&��r	B��Gn���Y����R&���s"L��
��?��]�U��� |Y��h�G`�����,$�2��}�
�4�	</�����|�64=���,w!A�������Hdp2�O~�B���	��^3$���P�V�c���H���|MG4vJ�N~p3$��|MG4v-��EP�����p�4z$R�*��'�\���e}�8��C����U���L��L.+�\!�c��?�G��|���p������OG�%O��� x6m��Eaw�;��z'DW�%B����R�e�LG��
����&������&��G��m�3?&B����:P�KR���wx����#�N��P0B���O�s]6A�k�����w8�I������ ����zBv���!A���C�v��	��)�����[�o��3I=�j����(��4<����4:��DX���n�h�f@�S�Y��� �g�N��Ia�����egR[H,$�������F��ZH���O���($W���a����@���D��B�0��0��&i�&�d!A��w2`c�"-u�r�-$�K=��Llu$h���dl[H<����@�M���!A4���o���J����@R�����GvJ�N~l#$�~�U��Z^���1�t�
��HdPUH5���b�,����4@�� �H[��
M�lhH*�X�r����OAg���Af��B�1�z��6)�z��������`j�O��O��
�G��A��8�O�/�:��1DW�$B����:&�aa|RT<��5|��+���	D��:H	�=,LC���0@C����9���$��>�c��A����7�]6a�c����nN��(�bH��D����SINI��n����~Ot-��EH��=��^	6�Qj�U�D���4>�C�)�!A��eB�.2�h�R6��rM����t>)Cv�^"$~*�������+w�oM����2�"�.�8�A��L����D�8�����]wAW�B� ]\�D*}yZ��A:�<H�>gp8��M����D����a���Vh�b�;�� .����vN�\M�1B��;<.6�:�3v��]|��^ny��54��RR�&����$�AW?���zM�ihz��,�\p���q ���i	HY�T�� |w�9�:���2�?�����������Kp~��!����B��M�����]~N��r���y���.�*�DH<�?N���Y���H[��,$9�TO'aLxd�1�7y������!,Y�r��?>����S o���� 8������"_���&����� x�r�m���l~tS*_����j��b{	:%A'?��~�
��Z^���1��&�U�MJ��T�D���_M��". !$r�	=HJ��eH#$2�/^��s��cy�TAB�)n!A(_~,o�cl���!�8�s"x��8�y�ut�^"$�n/N�Fel<��5���p����6��A���=�h����C��
'�o�D���"�4�F�Wd2�O��J��lB.��	�#?�z
�24��5<z���tJ�N~�3$�.M�a�"�Z��� W���g@���!���<��6^��}�@�����������6ih �k"<A����Oag�%B� s
7(Z�[��xg��O�;�DF�'��#��!�7�U���
M����#t�OH�:��3Ac�]�Uz�B�����������*	��p�WeVh��A�#�B����
`��"-��r�[H���_<��Z�"R(�-$�����]6a�G	���hfhZ"R�]H�
�~���)	9�m!AP��k���sgJ���U@�
J^n���N��}��n!A��r�p����Int	���v@�S�Y��B�p3Lv��q>_�w����	8��B���}�>.2B�il���0&���s"x6�}���7�������K�A����4&dOIH�9z���c���m�?&��=��J�id��%nY�5B���'6N�JH�d<#$����vt��	��>2$������K��va�k"8��� �
����:%A'?�����\��E��*�����UjtE�KUH5O�oo7]����5<l��_^s�^c��0�PCH���L��g�|
:K/�F���<:������,5'�[H�Yz��!���+�����hI�	<������SN�3t�]��	�����\�~��tD�KIHA?�H����6�G�a�T���50
���,�!A���L��;�D�$�!A���P������l�,��	����=2�h#��]H����}d^OI��m�A���q��rOu�{��E��)��$�������
��� �^���:�)c>?'��I�?5�pz!R5]	����a��:c�S�Y��� ���>����-�Zp��!��>��hx�LK�t��~N���x��3j��Z�{	���i��������,$��>����gp����wrY8�����?���V�A��7���V���<M3B������c�^���&����� ��<>�6���9 ��]���������;{3vJ�N~,3$��O���G���\��kN:&���>��[#����U�<��������|������������50MY�0���������O!g�!B�0��n�>��;�BKzK����s����%#
�,!|?'�=I�i�dI7�G����6�w���,!����0`����3_�����9���,�0��'C��o�b������� 	B����oL��2IGM~ 3$�1gy_��c�"�tL��s;z�����&	�x�y�����9���$����� H�2����$!P��S�$e�|���t�,�DH��,9�����&��S�[H,��Z���Y��M ��A��� ���]waW����g�<��w�ID���B�0b�|
�1a|�le�y��qhv�	e���G�O����x�1�B�0���M����lB-��	���O�;#����H��Xx8^;3fJ�L~�"$�kgc��E��"catc'_e8���sT��<����e�S�	@XHCx�r��t5�2�,$��/����j��YH���l���.���^��Hzo�S�������ewgU���@�� x���X�� ����!A�n�c;�A�k��UDH����_Az�(�A��UD:�	<���S�dE3�uD�����s"|�o�/&��C�H	B���Hhl��HG-��	�tx�������|!������<,��y��!�A��	���������t�Z��� ��q����!�@���y"�'���7����!���� x���*-�W!H����w��W�s�`H���I�a��4�����;H����a-$-$~h5,�L�kh��e:&���s"z�P0:#�]�&��t	�'?�GI6�r-xP�k"H�Gg�w���6
M?��+�GH���2K���;CBVT=
!A�l.��W���M]6A�m�A�}��pg8�LKBn�(_aJ&��C�"���C�0G^�wn����,UH5O��o��m4C�r�!�P�s"t����>��t
$.r�����:;'0x>���	��������	_��	�������'�<�?�s&��<:t�BHzUf���}-�!�8��D�����|��Y�A����o���|�p~�vN��>rv��:D��,B� ���,N��FG�,�o	����'	N��F����D�����K������� x�p_E�1�u+���M��c��D��8F���}���}��FHt�����}��!U�����q���v�n"$����'���������;�X���e�� X��~�#h�F
�1�	d�� �P�_/����]wAW���A���4]��0#�@P	�vzU����M�B�0����kF�
�@,$#���L���N$2�-$��5� �:]6A�_�a~�G[�h3��3���5}��]�����FH���x3fh��M )cA��x�7�4���}��6(	�^�U�6����L7��r���8��a3`�S�Y�i!A�w�~���}�w��	�Ip\��a��;����eY�	<*���n���uf��!$������46�	�J��az����vp���M�)��D�Njp���JY�4B���W�t��E?�
���p�!��Y��:�Z6��c�a����B���������D��e�G'2vJ�N~�3$���n� ���A�c"��>�=2��SP�av������}���3��� �����E���0�a��������OAg�$B���x���d�7���������	8��B��B4�����������������}4>C�]�Uz�� L�=>������F�NIP���S���a��6�'c��G����Q$�-u�r��G��E����w��<J9B����m� �lB-��	�ty��M��i�H�va�k"��pHPSj�C�!A�
�I�A�3v-��EP�����)�LcD�VT�D��F��~�(������ 7Z���G��
����BH|_�k�vVg�|
9K�[���t����'"Wk��� $������d�-o2�r�A�]�Yz&�&��uv�n"$��N��y
NWD���e!A��&	=��pEC������0Gwu����h�b���� L���+4���E�m2��^��9���&����� t������5(=��.�|M�/�wg|OI���o����q�=���A�c"|��*������
���0���v^4Ec�2�����n��c���MB����2Ztw�g�|
:K'���xg�R��#�����-$��o�;�R`C����D������O�u]��	��W�f�~REh<��5:����3��*�O���1��#�3�OP0B��/��i?��H����/C������N�d�k"H�s	�G�gm��~M��&�I����� �aYH��w��F��"$�<��^m��I
�Ok	�W�IgARIh �k"x��J$�S�Y��� �	e��.�GJh|����I�B�`!w/}��� ��,�iA-$B^���������I	���3�x�p�&��B� �q��Xy�h���
�B���o�����n�&�a!A�_��o�4>�bP�Q�'/ _�P�&��{�� (���Y�q��R/�6_cA������rJBN~#$B^��L��kt-BJ�Xx4���;
N��!d�<���l/�.��(�C��� �;���pZ�T!�\c�f�����oR9��,��� ���������#����-$���{�	m��w�-Y1�g_�������
��]waW�$B� ��g��9+�'�b&�@��D��{T��>gh8��M����D�M�kh��%�Y�6B���fg?^~�S0B�0����_�x�.����5C� OW7y��b�6�lmR�&B�V��'%�$?����?�C����c"x���*��U��eDA���y"L��Kc���OQp��~N��bQB���/Q@*�D���t;C�S�Y:�� L�O���N��|�� q���a�U
��*|N���	�g~��c>Y�uF'eG��?�A�O���M+��#DYH<{��3:)<B�	<�����
�N'uG�����s"L���Scwf(�G�BH�{�3=N���Y|�[���@@�Rn��|M�]�'5%�&?�k��#����c"x�}u`Z����a:�,H�OZp��~N�ozM���#C�\��3<�G��)�,�DHf�W��2������� ��&��o	B$?���5&��2$x��9:������]waW�B����n���C�gIX�6x^�wfgd���M����D�d�?�������Zf��n#$�w����7t���Bdg2�ON�������g:���&��{�� 8��g���9��,
NoD��+_��?������,�����gH<��W;�;$�y&���!�c"�oh�=�����r�y`c�%��UA�<�����i~�i��>e�A�	��D��|u2.M��i�H�d�!$�p��J4r>����	�t�>��L���������H�oM�!���*��S���������SZe�?'B���9_��@�t!Ap�}�kh$��$$	���4�q�������6������0���,��u�_#� -]�r�O���^�8�,V����6#!$�<@��g��	��^3$�=J����G���`�������D��p�5gUg� �$��8C�������Xw��C���!�c"xts.��e�sKC���U!�<<s���w�{>e�A�1��D���������F$q2�as��=\��I�3t>���	����-�0���1@o�H�>B�a�-$��
�1a��4����9M�F	&�uv��YH��<�Ngl���M ��A��xT��F�y#�M�B������t��9��,$}�]�D��%���i�)��m	���o���tJ��l�.��	�t�����_�hp���X��%{^&�)	:�1�� �o�B���/A�E��(cA��-{���?�.�w4�	�<��4;�Of&�d!A�0���Qd�GC�@R���<]7�N`s��S�Y�g!A�{��w���>:��T�9n!Ax�
wei���0� ����wv�z����)	�B���|��_*G5���=��6~L������r���M��-�mFH<{����"4(�P���^�$tC�M��w�!A����I�id�2�]@�������%�����gH������c�Z�]���1<��P�G�E�id�R�*��'�'/���|�}�(��c�����L5�9����N��d�!$������)�,}DH�$��w���KFz�s��G��;n!Ah!�}�2��Rx��9�|_��s@C�]�U��� x�c�44=iT������J���g
�4�	<����8��i\�{�� 8�����?��"�G�GH���(�et��fH<��A��I�ag?�;�D�+_���I��7�NI���r�����&���A�c"x���Iz`�%�HU��<�fsm6���@c�2� �t�s"|7�i�
M�D:%�!A���c���O!g�#B� ���;������&-�3��[H�����Dr�`C�'-�2�G��A�f���*�C������t!A��zRS.���I�sIH�^Vn�
Filx2�1�l��9�}4��R�,7!A�]�����!w.�lNF8B����}?��lB.��	�'�v��$���(�4I$t���5<\�(����%�����fHn���2��Qkj-I�D��:�����4�
�������h�|�>e|A�y��D����2Z_c�����BH<_Pt�s�	�[��O!g�$B�����N��Z��"2�&��t	�9+�1�KI��b1�EK�L�)��D��M0M��ut�n"$�������5*�[��a@�fI�3(���&���c"�wu�A#�tAK��[�azo'p�\��A#D�&�!Ap��~=����&����� x����oVf�������
�.g�����fH<z���Vg�Z]���1���4���"W�B�y"z�7���e���}�CH<{�(��58����4�A:�^����OAg�&B��g��O�:���8�3���[H,�q��9`�@T	�������"�D�]�Uzi!A��q=2��P:�T�!��A���[?����!�	@YH���z��'r�6$	��Z/����E)����wx�4���>��w!A�zgO��sG��CT���g�=k{	�AW?�A/�����EI��j�^q���!���m!Av�ir���*�t�#Uk�6��r�A�sI�i?R���,��� ����nM~�z"t($NM�1�������e����P����#������7��C�]�Uz�� x�����50]
)T�����M26\��&�v	����2u���(����h�a��
��4*$Q2��^}E2r��\|�G^�Fjl�R�]P�������NI��p�A����1��E��*�����:�64=�TR�A���;v�_#������FH<�o���2���OAg!!$2���,�t�W�BRO�#��e�u#$��T������Q�4mJ���d!A�����4!)*Ct�N"$3���}�����M�^�vF��2D������0E�]�N$Ee���s��s"t��w�� �&c��1������?RO������ �R�$�5I=2�5t��t�*Cv�C�!A������;�t�a�"�tL�����#Ee@�H��S'�]����S�L���������(ue�*�D���O�4=)+Cv�~"$_��4�������	8��B��B��'��56}�R��� ����I4]��ut�^"$�~z�/��EdQIP�~zp!��EC��#�-$k�����EK���l���+N���;wD&%�!Ap������e�.����6C������
64���.�|MA/���
�����	�G/m�.h�Z�]���1<{�j�	�^�D�
�������&��3z��Og	���R'�64�I��3���G�7��R��F�����!A����v��Z�:$���P��r	�����
_R�L��	�� �����������B����/6��Q��H��@ZHn�|W��hx�����A;l����84B���U	�vqU���9+����X���	��n#$B~����"k��������������	������!�Z�]���1��.uG���.�4��y,��^�>�e��

}�H�� �����k��F+D�&#�B���~����|
:K'-$w����|�O;����kg��U���St���5�e��~���
=�v��W�&��B��?�
����c��v���
�^WE��n����`�*<�w�)`p��I&i(��
z���/k���lLF3�P���+�NA�M��w�����oe�hl8"P�����NI��i:�
�~�� ���A�c,|{�af��!�T�c�{���S��PpD�=�G���Qd��

G�\cA���#����3��)�,��%�0���.r��������5��&GHv��?�Z��]�S�]#�-52 	�'���������C�a�;h"r�$$	�=6)������6�P	�7��V��4CK��h������G�h2�G~�����	��N3$=Kg�����?"K�����������E���3��_t�����*��&�L�
��� ���d�r�!�8������DS�n���)��FH<y��4 C�S�Y��� �G{y`m���;WB���Fo!Ah!_:��iT��������'���]waW�$B�����iD�L�B��d!A�^��j��$Neh��� t��m,���KY���.#$��<�2D��;�B*%C!Ap��J2t�]|�A?����K!��������w�������	�g?��t���"�tL��pz$��*��'���v��2�h�?e�!$_%\4���M"����� |�q����)�,�DH��2>}P!���7��Q"�j��\�� ����n{��!�`#�(-�1 	�'�'W���\��ut�>"$����$��4lh%��$$	�\o��x�y�"]���I#�` ����u�J���� �������b�aQ�����f�Kn6c!$T��/���!wP�k"�@[�_�3}���`$�An��fw��2���R*�����-$b���8�+r���M ��A��j���\w!W������������	��$�E���	���1��	@YH��*~��t0A2���ZH�I�/����8?���mP�'�����l���?�f[H��a�9;��{mH�/����G�g�l!A��w�]%�����A�
��?���G�9������J'�^>\� �(�x�k"zXH������$ ��}LA��kNV�`�q��@�����T���7Nr�9�`! w!A����8���g�!u�&�g������n�0�)w���x�+C>����S�|2��Y'�ZHv����SN��8�xh�9��6��d��*�DH{}H'	�jl<<�5|��:e2�r�����6�g���~s���7jxzn���:t����/��pzn�&�t{�N��vs��@n7B���%�4a�Sn7C!$~�-��%�����?�8��B���gR����|VKrB���_<����,��e!A������w�d��S>�� ��y�|��M�)�y"|y������
�|�k"�@[M�|P�<�	�,�!A����95�)w�������|L��aX!�rp����/HV�8����C�M�1��Dp���C�F�����!A������L)��d!A����3N��?.��� ��#nB12���M�B������`�Kn4���� 7z� ��p�#mh ]�����l�T����3]�4-	�����V�X>�"��A��h��.�*=�� y�>�O�|(�	d�� x������R@YH��<���}<��03���/�|H
}��6$	���G�]r��*�pb������<�S��	@YH�����c��.?�|�~N��V��}���!3��1���:'�'/��v��]��	�g/���"��Id�'AYH���+�m���uL�z�blL"���#��D���c����
gj�k"8�zF��nc14���D���/,I>�fC0B��~�?��Cv��~N��?�c[�Gs��9���|�,$��Z�s~���DW�#B����W)�d�<�x��k"8���>��K~�[
����� �^�(|D�}����~�5��O�jC�Q27>��#$����Yv����A!��6�-W�|Xd/�xH�9{�]���h<'�5|��b�<CsL���GH�����K�8��a!A��ns�66�*���#$����@��dd�� �+�H8���.���?]8a�B�p>��j^eh<����^��f=��]�U��� |�o>���h<��5<z������|�e�@	�tz������r�)��~!$�����GTv�
��5|�G[J�H>�FC0B���7��K6�}����P����B�}�
��Xv���B����?��]waW�����}��p��OL�j!A���Rs[�1��n?�,$�~�5l�!����a/\�3�l�#���m!A����"d��&u�������G�)7�B����,���������������Z�`���~ C`y�s"x����u�	��m!Ap��H�$![����
������
�|Zd���t!A���o`�y��oD]������Wl��<��7��o��l@��8gy�s"nw����H����g!$���%1�����e!Apl�t������I�y%�&���1<����(��3�,$������3�/��	�G/��Kn6�d�|F���z���Sn5!$~�?x�a�ms���T�� ����{,�9���7�,$����!;����K�A��^��9D��d!A��z�1A��7�M`�c"x�bQ��Av���5H�D�v����/��P�4]������3��y#�zM���7���F�)w!A�����/�
���#��	�(ZHN�'hu)���2�o<'�'w��FG�a^��nW�!B����W(���!;���� x��G>N���dX���kr7�rb�
o C`��<����d����k���W��.���:��;�� |�kN
����S�5B�������l����v������'$i�uiN���&t�OH�4���B����@��e��A������		��|��	B�����j!AP�����9���v�%��)$��|���7�ZHn��W�|Le���\�f�S���a��nB�h�,����v�,7��Sjh<�����`�Dp����t���J���H��jl<�/8r��A��~����$mK�A��������ll�	�'�g������Kn6K�D����~�H����,bl@]�� �~�|t�S�5!$��Z�<�����5��QP��B���f��(���w��
�������O����ut�^"$��������d!A�+��mF���w���� x�����?�~�d!A�������}����zE��z���	K��	�W�������O��	���X����	����E���A��q���~�B��M`��s"x���;x�^��	��?�y�l�"~�a��� x����adL"X
BH��6^�9����B������/��P�(]a�����lN#~�c��^����I��p����l��#����-�/4~���`����~�ZQ	��<}�����/��UP����;9'�O�m-��Ni!AQ�%x�P����	/�(:�����y�{I5��������4�����[k!A���;�E���d�^cA4x�S���|^�fF�,$���;`|(�n�&t���YH6��	�����Wd�2'���YH<��Bv��]��	���~�qJ�;I���D��������'���F�m����u0;�}�DC`Y�<�Csz�;�%�!A���������W�d����(�@��?�������*�Rq�xB}�Z-���X{�
��}�1��>���Y|���|����Mk���bl��ZO�]��?<�c��������O�����/\�������������c��������t�t�������������z����[�������������������_��_����O�������������_�������������������zx�����������zx�����������eh���������_}�
;p?������n����������y���gC7���\��z�����������������w�������r�������|��~:n�7��y:�������>����������������������^N����u_`'?������v�>���3
|���G�X����
 ���j���<F����i�<���p������?����o�����x��cD��q������[h������|=�c2���o�{�z�/�.����8L�<��
�l�)��.������e��4���`$����z�|S\���O\��C�yz'OD�up��:��:7W���_.�qu�����={D'qD�qu�������M��1(����������z4���?�V�C��w0.]�����a����H?o��v��������w�!��@�K���|ena���:��w���2U�e���;]��L'�O���gcrT�?�v[C+}��??�zc����k�����]�B�#��SF�.���.�����M�����M��:>yC����N>����R-�E�@����|(��|(��|(�� �B�s�N>��| d=I��!�Ir'�h��J�����c�������D��������/��Ts��|N���������h���C���!V;�P��D�PD��| ��|���N>D�j'���
��`�~�m�u����������j�8J��Hg(}���*��{��������1���~�?b�����������._�;S��\�����>�2T���@}IC�Pf.�v ��,�P;�<	hz��{6h���
�06�	�G_w#��W�a����������z�>~��J����O>��=6^
����`������n`�n`�n��� ���(��A�3���!���J�t4�,��t<fz	�
���>�C��#���
:�3�'��(f�(�A�
|�����������m�@aE�n#U;�QDU��n��W���<���(�j��������stL&�������c��m���G����	��q��S�D�u��z?-fVG�
������/
��z�_�(�(�r	�v?v��4�����3*2�_P��V
������m
�_hy��p�@�%*P8A'Q.��ev�P����
��
i��*�`�*�`�*�`{�_	�P�m�@�z�V��#6��Xu
/�P��1"�*P�3����YX����,�a/�<C1��j���������C8�c������c�Xp��C8��c(��w���+V�7�P�X��4�����1e��U
����c�h�98��><�=��k_=f���Q��F��
���5�P^����?����K���
��M�|�^��{�� ��:��o������o�����������p����!������^q�	������e�fdB2��2��2�d!�dBA�B�v�dd�H�B1s}��^:�O���1�<���� (}�X�"���{B4�u!�:��%�@���N d�*
�"��E
���A��
���	:�Kc��~0f?�(kcqU�z��?4s���C1��=*�BG�P���S��z�(�=�����@OE
%Z~�)�"_uk����4z(��Z^��[�_�����;��R����������p��X���#T������
=v�����V�QY0(��+��+�PtQN���r �H�IJ6�B�r��a��@�@�O� �Z�r �����N���������Y�e��1�IxZq�ZJ�8-D4v"L�QC"i;Q��6e@?#�� ���(Bm�B�V-�A�y�����(C���+��,�X��lu�[�"�nt	����~��T����_x�A�k����.5�h�M$���W��*0�������t	�"����.'�ey�r�X
z�z;�f)��A�!7�x��(��������*��H''�{�`uRRlFNd� '
�/'
�/'
p@Nr��������iHI�k�r���������6��@9A���Y�-��c��\,�&4��x��X'�&����;Pg"���3a��]2������0E\
�CD�jg"�q�3E\�R�9
#W;A�������z+�N?P��� �����F�����E����AI������`}qDO��G�0::F�Lp
�����PQ��]`���]h�����@]A�P�7����V
A�Y�m����*|�l���sa��	�z����u�=��IC���(��n/KM��0���
l��
l���"b�"��� FYO�P�0�J����fW�]��%eO��RP#����`�g7K�����%e?���i#�\�C F8}�x���H6��I�������U#��
b�"�%U\�Z��wz��eq�':MT�aB����k[#|}�~���[�ey���#��5��%�����z���t�|9��A�
�*��`�������q�p�J���cl�h�������`h�,hEQ�*v
�V��O�����xU`p�~|����u�s�<c(Z
��\�
	_qkB�������[�v�qY0����6���4���P;�P��wRt����ad�4pt�w]t�=�L�\�@�3�4Mt��4>�un��7Ft��\���t��T>wn!�:�&��!�P�n��~�h�[��;�P�U�����#n����@���[����x��s��wn���s��y��7Fctoh�~�B�|�@��{����
�jd���\q9��B������p�U���N��1�2�*��Zp4���,NC�b����������3��A�������mw@�w��;(��;(�~]9.���p�r������B~���Np�=u�������������x��
>�����@{P��&�<���N���h���A4�u� KF{
��=(��x�h
������=("���\�M����@{@c�1"�����k
T&�y���L�39�T&���l~
������z���+��
�?�hV��HT?!��2>:P���j�
t]�m^���
N$��_�������I
�K(nC���'�'�B��A*���|f��m6c�`0�7�7<����,��Y ���Bv�I��{�����w����a"Z�����
Z��9;B�2��J��P ��s0	:����?&���[�oP�
��c�����c����1�0P�P��������NO����s�^���@�@#v�1�����A��Qu�T�c�3i4�0� 6��%F����`��U��M��g��0���hEt8(Xv"�(8�h6�������h~�������&oeti8M��O����������{����n5�����_(��_ ���6,���,���_ �P�!�*�N��gt
�=u������	�/a/�w��)��i�N���,t�&�/����S����)Dc_�
�����$!�PD�@�BA�[MVqU%_�y����S���lX�)�ad������Q5���Q�c:�@g�X����~��=:v�]3�c7+�q�E��0:>N�����S|�@���o����S�`�������I�BS|�@�z1�mh�2N����1�����Y�^��r����x�����G��r���{?Rh�T���TT`�TT`������3�bTd�T0����*!�������h-��l"�{���	����F=3Z��<�[\�`-�xO����S��0��"M�C3�����"�ddc,Z�l�EkQ�X����d��p��F�T%c/��@h-�<;"�x>�����U��@���'����2��� _=�}������`�g�k���nA���q6�6lG�z��KX��tn`��QR�Z��������&>��
��h�����W���}=�� �U ��U���*`�*`�*`�D	�$�o�h
r�*�s f���<��?0�sO��c���4	���l�%����
|�'���b6�]>�(����.!�:�&��!�
��K(��
B�P���K�F��%�~p���������l�T��%�����`��qzQ�h�6v��K(b�C:�@�Sc7)>T���e|������?�*{x'�o5	�=�`4>he,�xhe,y+{���"�E({�q;���J�|�@�����p���V���E���E8m�W�m4c�`�����8`9d�8�-[���
Z:����"���tf`��s�Z�^9o�h�xOB'Sr��x/�,�/���h����a��}�Y�+�"d#+Z�hd�,BAXz�'�?2�F�G�@G�9�a?���@�E ����,�GcGZ���-�1�D�Z��E(�����A�$���I����;���P�P�\Vb�F����<����X�`}�F4�Spp�d|�<���04y�i����J���
�
���#��m6c�`�����8`�������Q �L�~��A�@���%�Y� ��]��=1�(�]��=q��J�9Uhx85�Ywv!�:��~�]���.Dkg���B4�vv�F���:8�z���.rh�g���t�����p\]<��?��������1[q���8k�B�;(�C%��I��[����c5������B�	�h�1Z7/#]��l ���@6����
E��eC�dCv(@6PpB6Pp��!
�d�mO�H�����
Y0���������
��
9 9T�@�y����l ����e��C����
�Q�|�'��N6P��Qe�/���:�
~�l�����l(��R��h����l��$q�#g��`�����2�3�L���2��86��
4f�e�@���B�<�����
o�������G��@�l����dC�'�l�	F�h�P,T�dtC1:rW@�
4���M7���72h������(8Q���n��1��,tCt(>�����+�p�_xO%�j=�[$C��")4�1���1*��1*��1*��-��3�"+�n&#�B�����9����T5c[�@c�x�4�Z����<�|���Z�"9}���
#�Pb���weFbd�*J���WLd�*J��������_1��s�_�e$bg$cO�'
J�^8��8U�]|���{b�?�����;�b��tc?��b����7��!^"�}���xY�j�ukq��~�n�[���F)P*��Hn���E�~����C9/C��<��E�r���x��0���4�:<yr�Hs�+nz�p|�Al�@����^(��^(��^(�~�]�P��*	F^M@/�k��N��d�T�c[m
�J��w�����$8�j���!�:�&��!�&�`�FV���	��,��` ��` d���t4���;�@c�^��	�~
K����LC�C��x�[2�KW�Aw��������G�����<�
���Wh����2�c���q�"��=PQ%�E("�o�`�h�E���E�O��*�-�f,B��!
F�P���C� ,!g��|'�i9i�~Aj�c���(h����h�z�8�����[�5�(Dag��3
Y2��(Y(��AU,��]d�lg9s#o��@�@G#T�@c�n�;�@������}��Q(b�O��;�Dx��a����~���8|��m��X�����7�h�$���9|�r+����Z����2k��{[Kx���vp4�v]pp�9Pp��d���9d�����M>^|����$�f�C�������X|�C�@ED<������9����q�(�x�Q6���
��,_��<��~n��J�_�Q6�p�����!�:�&��!�
��l(����hd�dC4�v�����@��s:�:��^�
t�C���V���^;�:�0��%�#O��Eo���%���n}������C"�@)��_��P\���F�R�	l���������T��V�Sx���FrpB)d'�B��;�p����o$�f�BJ��J��J�j9�
r����W��2���k��Z�b��67j=P/��7��]/�TU�Y��ni���e��N/D#a��d���!Y���U,�2�H�����"�^ �P-��^�#�I���N��cv��d��}~�^��gI�o'�2�>����k(~����
�Q�pD_��	��������95�S�6��h�@cc�6a��
��
�+n����������������	
����#��w�7���w?������o~��������~���_��r��p_.����K�c�t�����\P?B������$w��_(T�M�T`-��R��4�K��
�_r�=���,��/�<5�������V��q�l�.�p���������gNP.��4^�v��=y?<d�;��K���@������Q�p���j��vTAE��y\���������R����������R���� _�+��|�b�_�Q�X����:��'z����9u�0cu1�?>c��B���Fho�`b�����/�
��������R�4�#��LL��%O�H2>:F/��e�� ����>*���5���L?���a�����`����<2�������l����5������8�/�u�����Zm{���}X���y P=3F�P�}�P�}�P�����8=+F�P��w4�<�wN�y ���a`/	
��5���s��=vj/	c��=0P�����a�����N�
�|�*��Q��
Yu$���AF�
��o(��K�7d�
�Yw��o ��o d��v����~�����^�v���#m<��]�m��\�;���w����9�t~�;��i��z�-n�[
4�dh�oe+�� ����'��l���
��Q�@���$����U���^�4�4�*t�mx�-1��
�Bq�����wdG�����=�>�@3>��>��>��>��C>� |!O#IY/�|��O��1�la��O ����j���C�&Q�@gv�Hx�s<9}�x�	��h ��BA��h���B4�vn!e�-d��Y���[ d�-|l���(���p���Be�J��(k�7�j�� �z.r�*����wV���~�����g���A�Se��A�V�W(�Y�
�b�@�����,Pp��
����z�b�������VV,����\�6�uxe�~����;�[��~�$��%�.$C��%C|
����d(��@���BI:!�@�#${����d �gL�E%H�76���d�3�x��e%���r�N2a%P�P����2|��$C���%CA�}��(�I�h��$!��2�e�KP2�QV�������-]�d ���w$����$!x���~��*�:���7Z4�����vN�8}��Xm2/_�;�1���/�c��	:��)����"�%��5�[)���k�_�����[�Cv8@M��(}�.;,}H_3�	z�	5q�����n������
l�?T`������Q�W��Q��Q|42j���D�#5�om���	�^:���;�}mFM��]:���&8}�X��k���",�����?Td��5QE,_MTd_MTdU �9�&�Q�De}5QGY_M�Q��]��+�F���� ������������������jM��AN�O�����y�^��w�/&$����V0QM�����x���i����������5��1^f�B��^f�B�f�8�>����wEp|}�g�\�m������q�.�z�>����q,���{��``�w%���84�7�7�7��]Y�����<����x��C�0�zW2�Q�������$�w��W�����lx����}����}��m|��P���~�L2j�"��GAh�h���GAV�
h�" ��>����E��[JT�Vm4y\z+�Nz��V�e�
H�^J��X�����B����Gb�j�&=��;;3^�>8z*��@����u���m�E���Q\���cx��Il�����
>���yp�5�6�9�������H8�-��h[?*��G.c�(�"�t��/�pPoWl��W`_5`_5`_5���W�@q!��+�)��@�F;IT
t����:�@�N=r�{��hU���:���/�5�^����W��%����+��W�F��+D�j���'�3z�h\��BW^��������+��+�q����+���7���a/�^�
���<���?�I�z�B1�FUx
�_��+h����L��GzH�
,�~��������Pz�g%���&���%88p")zV2����1<y�P@qDv(ZG���T�c�K�{������f�B��IT`m(P*`_*pH*��T �L�JF^�*@*r��M>�!�@�O� ^7J�^9��(��L�n�((}�(�
��2:�wR!S;�
��T�F�N*1*�G#WQ*���"��BW�=����9o3W;�P��@�����������Jv!�'4	��vZv�!�����������Y�u��RY�����~���\Bq�	�@�Y��\�_��%DGK�Q��	N��2�P!|�`�B�FA�@�C�S5�!�kq!$����f�B��B��B�����X(��@��jB^���b��Cb��sH,���d���^9��b�����2#�B�X�t���tuO�#^Q,��?�"T;�P��
E�
���h�P�b����K�B��h\��B8�vb���LWJW����x\5z&�X(��ql,��"�:+Z����q&����HW�n
�(4�@c��(\G��9���q������]A��/�������f�7�&P�|d	�&P�^�p�@�qCs	Z]v���y4�m%6�*�����;*��8�*��9��x����|4��O�	���gl��3{{elk����l�VR���f����=��;�,Ts�lG��o���BE�K���BE��BE��Be}�PEY�m�J�QVe_F"�~>�e3�j�(���n�������n��N/p��6\"��j`�=
�:�
-�Blu
���_��/p���Sx�����!+�\���B��K
��u�`��f*t�=d}�F���al��nm����@p��\>������|�����.%lf�H��DRh�]`�]`�]`�]p�]��� ��� d��z��`d�\J4t�3
";���G#c�A�1y~���VP��Q,��V��=1��:[����(�~D6�v�"V;[���h+�q��E\U���q�tm����U�q5�*h\]F� �����
:&��\�=!�UP��e�s�|��]E��I���.	���	�]h��M*������+��P?����QZh�s=H��U���;P����d�66��W8���\���_�����E��=zr[1hF1`_1`_1�����P1��b(��@������!g�Z�q^�;����W���N1�1�Z'z�b�t��*�b>W���hL�C4�v�!U;�P����~�}��!W;�P���b ��NF�P���b(��Z�����'x\�d�!��L�QA�@�Ou+�'*�"js���;���@�j�
M1h���)z��;/�b �������
^�l[Z�6j"��X��x�o��@/���@��<�o���u�!{�����.����=�f<B�[6������K8�
�ZP��g�'n�����Xp�
=��Le��$���?�u&��WN�	�:&����(�j8�&��?����o���I�F��$��I(����!Y�$��I�+/�����~�F�4m����iM����
<���f���:qZY�I����%�3	E\u<E+V(8�~���
 O/���N��l�,�� wV�]i4�Z�a�@���9��f���J�QN�*����Z���
��@'1��/;}w���C��z8�v��`������)`�H��r�N]D.�@�!��9����FH.P�Q��r��gN����j�F����~/&{��~�)���E���~�(���
9 
r��C��� z8D�l'�(�v����#��Ce�_T
e�
-�Q6�h����N5�1�;�:�@���Z��C��=�a��E�����|�fz�>z�o�	�;����!���ZnL	����]#h��f��Htv(������
O�q����7�4�I���j4D1��Q��!.����)j��d��������v�C�5D�5g4DE�k9�!��+�4����l��h~kgZI2��-k��L���P=p��Y�������z�?T�����"����R�z���z�FVT�n���*��z�0�69��������`�~��������x\5*a@<TqUot����
��[�����^

���w���x_����+�b@@T9Q���
:���B�;^
�GI�������e��Dz�A@T�@k�8��>������,���Y��p�����v�x�ol����w�}�m����Z�$��@��WI�AR�E��$���/H�*���� )���AB�K�	!�)P���nf�$�=u�'� !��&�c%����	dbo�U�z���}�Q�P���wP����R����lT��H4�vz��~=R�����Gy���zs�N�����C=�tz�Fl����pT]y��8U��u*�<x�����j��Y��J}�KR<�����;zm��j"���i"�H���x�������6��|����`�L��>��.�om$88����m$�`��1n�apk#���^�fN��Xa�����~�E�
B�
g<�A(���@�@��;-B6j�� ��y�G�@��.�~	��9m� ��8�+���������!����w���NCt���9�hX�B4�v!X;��������!�5PbA�u��vwTwzbwGu'F,�����"�����"�����%Z��5,X�7�wY���c����O�:�z}H��5�	`�5�i@Eq��mm��@���}��~����G��@;J~�F����[%G������k'�G�N^����*�=�f<B�;FT`m(�#��%=_��#d��yi�������/���]�#��A��=��Q@�K�Q/��<���<B1��!�G���G���#��G(�����G��?�9P�@��ZBy��N�;P\F���x���D��>�����p�(A�@g������7N�
x�7��=�/��z�W�����l��
��w�a�9Q�������l�4�� �0i4:��J
�O����L��)�a_�mh�2�
,;0Y0
V�E��vfy��6�
�_�P��r���+���v�� �Y?y���l|�G�@o��5aO��#P3���6�0a������xO�-&�(������S��q��Q�����i�,5C4�v�������f ��f�����4Cq�G��;1���G��>������Th:��6�N3������
�4�,�F��������0�w"��n�s�w�l
�
��V�P�'[D�!:�(hj��I\�����l�`���4�*2�,w����b�
���@�	�p�]���~�a#����*�]�P�m�������,���l`�LwF��40�O��dcO�}�(��m�	��^9_�A6���8G��l�fs�_;�N_:���l�B�_��
�(�qe�D��*��5 �1eCY���^O�W`d]��j����j�1;s�c/�c*A5�y��F��gR�����g����;#������mgD�H�w��Z�
q;��DF�>�D�_���h;y���/pp��$�f�}������h����P4����f��+n~!|��/d�����^���J���6��3�����������Q������P����3�fTd�-�� �i�Z��0`-�hW�����O��a��z��Zv��>����<�dP��>w�7ZJ�N5Ek��������Zd'F6�v�"Y�ZD#kg-�����^����D���%�����#�~�t�������-�3R�qw���-����<���#����x�E�"
s�z�!h�q>��9>���:�����B�}��
���g4pR'�O088�,�3B?�9
�OgA��9����x_18���5�p���y�X ��X(��X(����
��6q�P��F ��\�b���zq�:�H�>����|���`������{|��Q6�Q�b��I:�sg
JJ_;��P2D#l'�!����I�h��$C6��d(�����d��}�dNF������b�#m�q��c�X���R6�Y����W�7����U���U��T�;:�"��W2�"��~����F
�Y]��M�!�5�`p�������~�u�Z���Z��&�)[8M^d�E���-D��-\����v�q�w�/Z(��[ `���BA�B�O���[���?�:��?�:FA���;���{��F@���f]�����-��]8w�J_����F��-D#a�
r`�E4�vn�������[(�l�-��^7���rt�W�6t�=sf�0cN�t�i97:<���������)f��)8
���xu���Qe��	S�'��btdw���j����w�)H�gTp����I�$��&(X�"���3*#@2Ppb�E�!
�����)~�40l�4T`��d��*�m��%�*�o9cY���4��0�L�LS��?�[\!`{et���v�__���C_����'x�X>�n��v�c�p�Z�H��!jQ8T����P�����`�����6�(����]q\FQ�"�1z1����9I�0j�0�C3"F���QO�p���J����~����1qA�;�c�HsZ.i��B���vt|�����r����i�)��/����>U�i+���`�4��7M^SYp��{����H2lF9`_9`_9`_9pH9��r ��r �Lq���^����Gf�c��cY;�@�+�#((�7��rPOD�����s3�r����~P9��o-����r(�~�C��� �CA_�P9D�m����iy\]��r��l�C@�@�(=~t���S5��i46�0�?�}��C�|6�(��w�l5�C�tjN_�;�D�>T���
m�a�A�v�v^;��@�@o\�����s,88p�E������%�+�@���������zz���o�������i���N�*?.�k`{�F�7mT`�k����^� ��&9�����{�AG#�����B�^��S�&{��$t���=��M���t��������
��%���hX�$FA�MDk'1���o������"��z�:8���19T7A�9s>�����$a/�*��	�*�oM ���Q���:�3��������Sh���M?���,X{A��(~��z�_��~�_���(�	A�Y��e�4��m�_���_Pp`�F���_���o�<�QpS���
b+��N`_1`�t����M\�t� J'YO�;�@�}4P1��0�lD�@��(&A�@���	�N��xgW�I>���u��
����h �tCA�L�@�D��!eQ7D�l��Q��
���l�(�����s�f��c���N#E�
��6���u�{�h��-Oc��d��}�l���&�!
�����2~���$�_��'@3cclq�fywH����#@2�;5���r}/�nhe8gf6�@��M���<M^��$��{W2����UlK�H��K��K��KI��������qf�PK:����=w�!�d �������7��7�U�5�	^8o��(����\C4�v�� \C4�v�!k;�P�����"$���5��k���������y��t@�@���h{f�
�la/������'����@���DQ���Q�������lo��_�@K�����h���#g^T�,�@}C��N����|��'������"_��C|�������x�����(�C���N��i(6aJ���k�Z���YI�%XL��}(�j!��>Pr�������R��hDJ���t�������}���}�'^�����X6��/9������?So�>�a��tGZ��P�!k�>�d���$���`�������>�11:O\Fy�%%e���1��~�����>�M=�5�0�?���}(��k}j_[*J����S8|a��^�M8�7�~4����-wz�~�XR��iq���`�^`?t�k�d|
�"��� 
�����)���p(����O�<�/�P���p�zP��()6#
�/
�[�P��r
��;�d����#���7�����Y��x�m({�()��2�9`Oa�DUmd��:����	�J_;�L�4a%`���3
9`��0
��s(�v�p��L��-��m��,�9���H�"G_P����;�@��
,qL�3|)|o��x0��������u{����_dT;�i�^�t���� !(�����<�U�P���%��rQ��~_�"��Gqa���P\�_�P�"";� "�C""���������F�o?������?������I����r�n��_�r����>���sA���Z��%x�hdT�'F����]���O���vx�q�K�����CK�([�����"���:��\����'-�^c�{��76�5�-����k��_X:ew��e����2L_9
�u�,������v���r��J%T4���)��,�Q�h��+�qT4E�G�z�GFc<>$� ����u��m��`D_Z�/��������U�������m�w����������?�_k*���W�f�����]�7��
�D��)�:��cD��w�r��k���������)�	]F�����2�h�>�
���x�����AC��sel6����8���!8��Bi�����v��� ���(���`� ?��Z��?w��^����e���;kA�s�
�a[o�h-����g��t����T����W�G�����/�9@kA��O������o
4�k_d�E4�v�� �E4�v�"u;kQF���(���]�a?���:�����N�����Y�0t�)[An���
J_:o�����t��q,��AW���t�v/���t
}�����tN���^X��#�4C=I��w���hPt��Fy��$���^��[��C#�J
���yle�{Ov�+���Q���������]��/QK�
���{�C���Q�� ���(�b���S��s���<�d��=e��A�!{f��<a/�a�U:&��DX��{���S�������q$�tc��{������s����kG�P\��4�s�0���h���ChUC�����PFZ��A�@�Z����i�����`_:/���;igzcE�5N�D�P�����~��k���E�2J;P8�B���v����N�px�'{k6�P��EZ?��UD���C��w�h�0����""�n��������t������M����i}��e�&��(-�Y>�zj�������:��8~�j���������l4����Z���+:�^Z���B���O�w������������}DE�DQ��v�G���#*�q�+��l�EQ��kn>�
�b����#����~�FK�u�Uw�\#��i3	>����9�|D��8��������a;�"��8�
}�]4�#����/�����Ym�5�`l��|7ah��(����B�G���M@Th�����a���j}��
"=�� ��"(�
-���#> MB�W����{����yON������.�`��� �L)�d�C���)��k��������r�--e�c2u��J_8/��(}���������[T\�P�����z(V�O}�Q=P�sE��2��aV���� �Ch�����9���hR�����{�|6G�@#����Ci�����������a Z�b�k���Q�B�x��@,T���O	}+ �
��0[��wvn���|<��;�������J�;�*��,�pZN�*�W���@�'�R�������H��(��U��&Q���?�QA��7��&�E16je��r����}:���cF����+��������R�������S����8V����H���l�
� t�W��
�t���S�t�G�x�GB�{��&J�?�O��
�?�#�F��1���]�#�t������0 E|
�"���v�IaE�'�0�~&Sg?�8g��� ���e�Se���9�9�v����?���=�h�q�����l�c��j$�����)�F�� �T������S�1D��9�.
�e~��c�������c���c~���� ?��$��C�F1�q'��Z;�?���w��+�S��"�5��%`<
������_������(���`���B-A�z�NK�����t��}��� l� �NK��Q�%�h���������76�����T���M�:EA���!��AEA�k#k�
��+*�h��EA��Udcm�(�`�v�E����(�h+������!4��c�)
�^X�N.��|�y��(v�N%
���$�����p���Aw�/ T]����
JZg�u���������*
���|z}�%h�dk�Y�R��(C��i�1�`�
=��"<�h
t��������h����c��`(X��������f����xa�B`�8p�8��y���w
4lI��h�(���:�@�3��4��p>��q�����h���&����������������N�J�8'��q�`b��u����
��q(bm�(��rG����P�����3?�8�q^��hh�����H�����H�Iu����,;SK.�#�ay�c��4���"���9E�PD�����3��3�9����b�D�"F���	M=�{K�0����?��N
�@�9Hl	���>��	 ��b��#XQ�MBLd��Db�x@�b���3�`�X��?��C������v�
>���'`'�(";��;Q,7����	��y��^��K�{9�	>���o���??^~�����f�8�DE7V%�	Nn���!8}��-��H�v"j�Ndc-��*��U`'�h+���
��o�`'�u�o�F��SWv�G[�{-�	m��&l����}�u|b��DQQ,������4�S��<H�,x,���9����F';����.��8�:_M5+�\���~�O9J����)� i�"�n��B���[	E��P�����UB������h��_�QD��Q4�P�����������:|<#��wt�������k�b�`#e�)�``��q�������������eg
/��lG�� ��sD
�
�v��;���~���X3��(f6������A����7�����vPmtc���"$��8+������~�Enj�F�D�#o�k��Fq�$zq��V���j���FM�6h�]��
jc4��:��Wtb�����`�1����
������no���������c�'�JZ-��buZ��ZTT�����1��U���%��g��F16z�DS:pxH���fn���^|����A�!5��P���"�:Z�_�G�~==:p�OW�,����=8���I�R���'�q ����s���;9����r�'c��7+4 ��pN�@B�����2��='n�~Gm�V;�u"�N����"���
!��r�0P��801Nw�DH59P�Q���)b����
�~[�*��o�(B��F?��2�g�9�(Bh��NC�O����������EH�4��[v"����'��k��R�oF����4K!>��M2�x��z(�(~��S�9�6� �y����;��k:�����^���R!/}C��)����"$�����@����&1!C
�,p��c���;E��u(����L�mdlyA���)�/�`���B���(���B���4�:�F��=3����a?�7��|�W�����76������gva��w��������Z�[tb����EA����E4�v�� �}3�X�v�kQ���(�������kQF[�}�����>��(��jD.��|��V��|�'�s�S�>sz��#��{UEg����(�=r�j=���x�Y��g�3F���+	4��?@?=�p�0l0)f3Q�F������^B���%�+�:
��I���^qk��]��#�@���|���v���uM����`*�]&���2	�la`��=��$"���r�40�3���*e����Lm�L���w6�(�
�>��	�N_;+L�o�>$`*���LC6��i��~}Dk�U��;t2r�40r��R>��iChx��7n�i����_�2��Fa���N�!�U��[9���^���a(����01B9H~�N��V1�x�
�VQ�����#*��M����7�P]s�%g
�@������;D6��'Qn�����|�6�����{��	l���oplY�q�y1�=�F�kT`�C��T<0p�Cp�lRF���,�[�ac?=��
�C��b�����o+�<��yuu�!��5o����Uh��E'��<\Q����E@�+*�������>�*��
+�h���dd�9z:��^�<����!h�u��\#��hM�b4�.��y:�G�������9x�^���CP�O�x:0�}��G�����}g6��	�����z�@��I@O������XC���L�?�t����Q��.A��_��P����0m�F5��������6S���T��|���&�F�fT`{o��3�
��
�3��T�^-��
:�!S��r��k��fg*�h[��\_���Sc�v��M����NP��N�o�h'�m��ix�v�^���Z���"�$
r�ND�kg'��E���i�������e������� l�gL�'�+�;?��Nn�����s��q,�.?U��'��hl,A?AC�$�'�g��Ps?���1=���cFZiD���e���6�X^w�-~�65v���(�&pH���"@�Dx��}(�rG�t�$���6��$�{�^1��b�T�p��_.����|>�������w_s�sA���3�m,!X��&�F4I�:��&6�����D�H���%�yp	g��;WB�3�+4�v�9�(�J{����+!�������b�-U��W�������>Z�z�*�������(�M(}�8�&ETx�h���Ip�������&�.���I�>�WT�&t<���5z�W:�	a/�n�M{�����A����p��� c��q?���\��<x���
J���f�!=�w������sTG3&���7������>)���'t���B��"|����v��W����+^��i��hg���%E�=	'<Iv(���&v;V�R���{����f�Y������:`	�3����|�{��Y���c�
��9/�( {�lk@A�kg����j���{b�w
������r
J���;�0@hJ��k�(}���E�U�e�v(������i�"���3Y���i�b�E��������Fp��l�h7��v ��w��y�m�8����W��A�@�j+}LP;�;�8z�C��4��N��p�|��6�����.���_�2�,:e��g4����+@+���w<�V(���(X���
��ed�}��!A+P�q@�����3�(X��(X��V8nO����4R�P��=)f`��Vx�V�#���50����������
�����V��=q*I@+p�������3��D�
�8������Z�����
�x�Z!pQ+T��
���Z����r�
���_�@+���h�W:���z-
j�vz��V`l��j���{A�V���8�6}TO5=J�X�����P�0�i9�[���a�3G�r�f��	�����6�4��S��fxL1�{_�,�i�W0
0
����\��'/pGxU4�����8�rS'[L��=��06�
���@��h1��
����P7��1^D�@�3�P�N7��y5E�@�k�X��x;}��=����;�;�@��)�G�P��V(�(}��pA�@��^v�k���bo�
���"};�P�_�#�_�;�P�����|<����h4���v��z ��s���^9�^�z�O!]�u���n=vcEgo5�y.8��M�p��D�\C��5�k�D�N���e?���u
�V���~����7w�
���l'l�~�64yN��ax��}���K��(��
�I�����
��
�)n ��mx���P�
td2
.���W��m ����ma;��:�@���g"P�@����)J�9[��0��a���Q3�J_�������"Cq�V
U��
�v8��(;�P����	>"�f
<�
4�1�nl�G�@�1�@�+kG8���
�����U:qy6L�,��}��C,o��Ny����:�������dD1)r��z$d�u�4��{!�CW�d�����MFPpBFPpBF_Fd�dDvU���`�9]����}���7���(W{h��l7��P9}E�Q��f��Q<��(8����E��`����������P��XD�@0���dEb�>���y�����'����;y��
:�3gnQn��(@�A��Gz����t���Nn1P>Q�;7�X�E�
��(��H��E�h(�(��.M.��|f���`$_X'�\#��NW�V�#����x`���qG�����sG���]j���9��p
w����FC�����<=st��g����Y���jJ�3S�o�_�	F�v�hus��F����G�9
�)���}1��`�V'H�Hv(@�P�\6
��}&8X�_�����oD�Sh�����
C�Sp�lQ62g��l�L�����sx
:�L_	�^Y<ao���XxA�{jt|�����r��Mk�������s��������D4�vn� �D_[;��sE���J��"l�M�#l�&��&�v�����t��a/O��	:��)����:1V7��78;u�p�g���!�&
��3wz3���h;=
��n
��@��HZqE���M�l(W�/�W����>�<���e�_�`�m��h�v��/P�^��Bv��/�������m~����1N����������~��3~�.��_������~����.�/0��/���m��c2q�,�0p��������Q�P������k�����7����
CE�
Ca���*�������h�a`d}m�a����5c?
�������0��2�ii�
�:�*������;������/�93���#H�	gc���w*���������U����9��Jf��9_��B�-�#hY�4�P�uM��<)��4������<�������P0�I��1n�����h������M�;����`3���D��%�}QBpHBrHB��f�AB��0J�^9c�����S�Z���Se�>w>��(V���$�������	��Y�A��DEH�"��%@B!��`Y�X���m�����I�b]'zK0v�����B���t�n���OK��a,�N�MC�����;
A��xu�x�����z~�[^e��e�9������u��br�0���P����F�q�h�8��7ap3ap3t���0,o����q�`uw������B�.6c
�����3���3e2���?��q���wC���m�~��������3�3�>w�D�@�����,{���o�R��8a0`
�������P�X1^�q d��	B�����8�1Ve_���j�����S4����i��l����:q�m�qx���J����3f�T��C����|�D�Occ�����l2%����������=���w&��5Q�|F���U�)���H����Dj������D1Dv(@MPp����1�7#���==���.?Z_�O�����x��v�K
�(��+��� ��F�A����Nyr��%e��
Tt<����<{���${��@��w�{O%���tf�/�WO���	���t�#l'?(}:04i;�
���(b��U�
�~��*��-��)�(�u��c�,A���k?�e$��wL'?�ss�_�a,�N�+�1��X��JT�������s�	��1>J�f�V{Q�t�0�
�o]�1::��@����������A���74!4��[��Pp�R��J��Pp���k)��'K!0!8��?
�1n��v|`�� ���(���`��i{����B��8�Gy�_5�
:�!�m�n�� �T�K>�S�^��>w�AAQ���>

J_�������������	�hx�E_�"`;AQD����F�NP�6P�A�OA!�QPv��Q�^:c���>���������x�3A����	
�3fF�W'(������3��[1��(���p:��2> �	�@'�N�7�}�h���u4�$��Pp��
��:
���
M�qJ'�:������]n/�p����.0h�.T`�.0pd��_��.0����]�~|�W��|<���`{e����|L&�(�x��M���n����;��5p��)��P���n�5p����k��Zt
��	������]Co����)�����v
���S�'��{B��
����eO��(�����Y='�*���K�1������s~
���!d�|m�����������'}V?AnJ�zO�(&�������C�����:[<�l4p�����n�U0��Cx(�xH�����vY����'��3K�m�@��P��n�| ��h8c����>r�>��f�M�}��at@�@�+��:&��R|7��NO���s#���C�Zf�zA�@�k�+J�8]�8D�kg
r�8D#lg��w�d�L�	F����Y������cg�X�2�q �����3�i�9��z6�����U7$�]��1st��!��D�P��]�P=��
�U��WuC
��@'4C����4��7�x(��@�	�7�@�8�(8P�����V����g�{�`��d��f(��f ��f ��
iB���u���r�P
>F�L���jq���Y(+���f����5�[r5C�Z~����(}e|��4�o�k�E�[\V��f("����
���������4���vb�@�9����!�@�z��F�@����Nuy��
z�����9���[
Q�-O���w���;=����b�p�<:t�'D�m���l��{�Y���
-o��������T���y�,�D�}/A�	/A��}|�Gopp��e|}�����t����s�?�������~�����O�����X���k������y�7���~�������	~�~�\��}��K>]��v������I��4����yW=������8��~��V��� {���������|[���������v���������������^���������q��������,�[{})fU���{��7���+�\�[��������z����b�*,n�+�C;k�v�Ou#��082�_2Q|��^F���Q�ua|���q�A�
��o��� X�d�j��W|9�����eh���;��<4�k�Ma���>��������=*���;O�������	�?�vN��?�v����?:�s�������v���~iqq.�tF'�����b��'+w��U]�v�����9	�?:���v��{�t�������q��(}cD�.����4���?:�3�B�?J_go`�G�k��r���Hz �_q��(XN�!��/����6���XC���X����~����?F}���?��>�DEG�c?�r5����G���?>�s��#�|�����1��)Fy�|F��50��������|V�}b���9��|F3����N��|��Vvy\���{}���s��@��gt��Q�����Vs�W�����9���q�\���?���P������-�o����q�^N�c9n�_��q����c��~H��I|]H�S'Q�$������K	��)^t]H�{n�!��@:�3�hH	�3	�������$��g�j��@:�z�.	,�To�I �Q'Q�$���NJ�I ����1	����8�K�|��C�0	�3:7>�wI`�^�������$����}����%���j-	�`9m�$0{��R���m��8 �C�%���������n�K0c;o�]H��	D]H�+c�Q����'�tI ��q�]������W�����$�X/�)G��Y��5�]H����I �Q�u�K	�i�o�����4��$����9=
�@J_U,]Hg�y���8�@Jwf�@�$�apK)8�%��I ���2<y	�
H)Xo�sc5m�8�u{�>����`�OH�I�>2����Q��t�%aO�������Gf�^�rt�%o�3p�Z����N����7F��.�$�����@����7F�.�,f5����S=m���s�]bjI�K�tcjI�{�$��ZRzj�I���Z��Z[X.#���i 
�%�;{AZjI������^�^��R�,RK
���O���2;�Z�U�d�������-*�������1���?����0�cl�@0���x;�c0��#>u�� �c�����������8
��O��x�����:��jN�
,-��3�����1vJ-V�m�?��8}R�|>�F?D����N��� ����!�!�cp'M{��d������������j1<y-��[�����h�������i������_l��aO���]�G�s��t�a���1]�G�{n4���?:�������?�?����8��?J��6��Y�l2�sjxK������B��������o�v�����O����/�h~�>�3�}���(}axW���.��8X���?
�[�G�z`��(8��$��/;��Qp`�	'6�\��C31	�\��.	$�����@��j�$��WFb�%�t�����$���s>{��g����3jUuaH�S�<ML��f�����@:�zC�.	$���:�I o���K)}��WL�|��N]Hgt�/���1	$�H��4�%�l|��$0{�������|��@}!'��(�K��#�0	$�XH��J@��;���1Y��.	��=7��.	�#�x�.	�k�����@:��yaH�OG*����Y�����@:��q���
}	&��	T7��g��PM_o�+�����|����\�wI ����K�K)}a�tL	<�������ZH�z���f��@
��!	���	�N$����g;^O�M&�+k��x�xs�	C��L�I������9)�\���]rI�N��.���=3>�w�%������7��]rI����%����7��]rY�jb�I5��m&|T���.��������%��s�
&��n���%����
�K:�N��.�,����Kw��ZrI��66hc�bH.���7M$�Y0$�t(tuy��Y&��w�eB��6�����{n�R����Se�|��������9���>���U[������|��tD�|V3��S���?>��H�Nm3��m�
���1��0������Gf�+���r��(����������������������98��&|�-���@������g�0�O�P������oc���m���2��t����~��������/0�#���MI~CN���X��2
m3���ic��4������j�?�^Z=O������W~\�?��F�?:��yp���}6���0�/1�c8#Mk�G���W���(8p�I|��D�G��m�i�qx������e���6�����b�"&��=7����@�^���$�o]_vI �����0�g�o3�3:q�&��>s>�aHg����I �S� fL���1	$�T�!o���@J�8��`H�s����$����5Pm�}����>�vk�$�apK	8�k�_q`�1�M/���0�!	���c,h�I��{�2a���`��:��@��%���2�H����;��@:�3#���@�c&�������$��g��.	��2�tN���@:��������O�����DM1o�+1��������]Hgtf�w������I �g�@
l3�����a0$��f���������q"	����(.���Ro��
�z�n?���sA}�j~�&Xu���ax>�(�����}\��������[/u�c����|��RW�v�����4��������)�����M�a&���J�0R��)�����D�������{�p����{�9���b/��o��{��	&��3"������:�������c�J]�-[�J��9�������
r�`HZ�CI+�<}_�qx��+�L�]����$�@�������wZ��$��I e?�@-��$��W���]n������y�fx%�0$��;��+1,�k��^K�������n�}l���}e�R�Wz�H������J){����C�~&�b"��b.���!1,�V�����Q7��b�������]��O���sC
N��.���L�_�a|cw_�a{����7�{b8K$����S�01$lg�B��31?l��{el;X���q��,gSo��%��n}L�$����s�&����g�@H��}�c.��$��C���.	$���������b.���.	,�Oc�1&���4*�1	dO�@���K��R����$���/�-	�/�����R������c���8C��=%�Pi���=�&2Az�s�3A�}'����d�2A�^���������:I��bb
#�I!���:�.)�g����|���3� �M��Q��y.��A�����2�)!a?SB5m�����DL	��t����
�L	�*���djL		<q�J���_�X�)a|�����!%���cI	/�UZJ�����Az�?3�o(������t��'{���x�cJ8:���C�O	��:'�t)!��RB�p&FV�������RB:*�!~�R�q�����8�SB�^�K	�L��1%���!,����aJH���������R�����������)�~�4R�,R�0��=c|�?����|c�~||��NW�`�tJ}�!J���%e�E�]vI�����g����K��j��s1�F��)e1����������L))}��<����=���%���H0���t+�����O��`��)�e����J���9=�K1)}e��]�Y�O��<���r����.;��v�m��f�SCy
_�^������Tsl���d����j'=��lR��
��w��y+���;�{�#�x��#$�������!c;A�C�^A������,��jb��EN���=O<���O����+��1�s"��[�>�����RH�����|�f���m��j.�N��'r��?�DN_[�1O�[�,��H�$
9X����98P�7�����P�ap�9�?��C�����������
endstream
endobj
35
0
obj
55654
endobj
36
0
obj
[
]
endobj
37
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
38
0
R
/Resources
39
0
R
/Annots
41
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
38
0
obj
<<
/Filter
/FlateDecode
/Length
40
0
R
>>
stream
x���_�������F?y�]U�u��>��R�W��������=L�1����S�c)2Sy��O�Z��?R�A�
��_o?�_��?,���������u��-�����c��y������_��~�w��q���q�,��n�W~���x@�q����?O���:MK���a�n���0�?����_��_��'���/���c����2�e����	�zf�����������Q��Q�ba�����T}�M�����='T��� �p|�������T?��i{N�>+&A8����K�?�q�}��`&��98��P�����+w/U��i���09k�qB�)X�0	�	�W�^��	�M�����='T��� �p|�������R� &��98���X����+w/U��}���09m��	��`��$'_�{����1M���LN��O��}��A�f�3����T}�E�����=�	��`��$'_�{��&,Daj��	��`��$'_�{��&lDai��	���I8�����T}v	�������S�ba�����T�C�o�LN��K|`FP�����+w/U��Y��(����qB�)�D���+w/U��U��(����8���X����+w/U��$�@�v|`�P}
I��(�p|�����2H839mO���� �X3	��W�^��	��Q���qB�)�D���+w/U��Y��(����8��f	�p������o�*�@�v|`�P}
V,L�p������oB�p 
k;>0N�>�$�@N8�r�R�a$����'I|`FP�����+w/U��Q��(���8��F	�p������o�"�@�v|`�P}
��Q8����K�7a�p 
K;>0N�>+&A8����K�7a�p 
[;>0N�>�]��(�p|�����v�p fr��]�3��b�$g_�{��&LD�����Oa�p 
'_�{��&,Daj��	���H8�����T}6	�������S�ba�����T}v	�������S�%��	�W�^��!���A0�����k&A8����K�7a�p 
�v|`�P}
��Q8����K�7a�p 
S;>0N�>�U��(�p|������$������O���IN8�r�R�a$����'I|`FP�����+w/U��Q��(���8��F	�p�����~V��p�0	�x���U���vG�����P}�"��|��]����CX��G���+w/TBZ��AXO�����P}V,L�p������0l��A��i{��,�0	�)�W�^�>�1I{�0��mW�{���$�	�	�W�^�>�y��a<���r�B�!��T?'_�{���A����o������
R� �p|����C�oR� l'~�U�^�>+&A8�����7�v}��`&��1N��	(�L�p�����a��=A����]����C�&iON8�r�B�!,�T?S3> 'T�2K��p�����a[��AX��9���E������P}�*�����	��`��$'_�{��&�7��`&��1N��	(�L�p�����a�p 
�v|N�>�I��(�p|����CX$�����	���H8�����P}I��(,���P}V,L�p�����o�4H839m�qB�M@�f�3����P}��Q��8��F	�p�����a�p 
c;>'T�,�@N8�r�B�!�Dan����CX%��	�W�^�>�$�@�v|N�>�$�@N8�r�B�M�	�`&��I�c�5� �q|����C%�����	��0J8�����P}��Q��8��f	�p�����a�p 
s;>'T�*�@N8�r�B�!�Dam����C�ba�����P}���A0���'T�k&A8������0I8�[;>'T�$�@N8�r�B�!,Daj����CX$��	�W�^�>�M��(,���P}��Q8�������K8����a�p 
'_�{��&�7	�`&���%>�k&A8������0I8�[;>'T�$�@N8�r�B�!,Daj����CX$��	�W�^�>�M��(,���P}��Q8�����7a$����g��P�����+w/T�(�@�v|N�>+&A8������0K8����a�p 
'_�{��V	�0��pB�!�D���+w/TB�p 
k;>'TB�p 
'_�{��&�A�� ��i{�����b�$g_�{��F	�0��pB�!X�0	�	�W�^�>�Y��(����P}��Q8�������J8����a�p 
'_�{����QX��8����Q8�����7a�I839mO��P�����+w/T�$�@n���P}V,L�p�����a�p 
S;>'T�"�@N8�r�B�!lDai����C�$��	�W�^�>�]��(l���P}��Q8�����?�e��p 09m�.�8��b� �r|����C�ViOn����P}V,L�p�����a���A���9���M������P}[��ai����C��T?'_�{���]�����a���A8�����7�6�p 
fr��}���>>`�f�3����P}�M��������IN8�r�B�!��T?s3> 'T�:J��p�����!MR� �����P}i�����+w/T��q��@���=i��$�X3	��W�^�>�Q��(����P}��� �p|����C��0	�Y^CW�{��$�aA8�������J8�����r�B�!H���p�����!I8�����r�B�!H���p�����o�4H8��,�����P}&It��3���5���$�?�u��e���6.�����z�g���}�
[���h���������m��U��N���yX���������-�G@4O?����������sM�;&Ap���r���s��6���������o�~&D��@2� x�������yn���������~~	���(�$m�I�r��$������N~ ���Hf��O��_���sXO�{t����6.�L�����>�L������|�� �l�>Z{2��,}�v�kp%�^�����F�;~V��m�.��O����o�����g��'�m���Mz&A�c��Y7Q�����d�)��L���D��$���v7���"3
@fO^9�}^��;����FA'i#L���6�|-�^ws��9�XhjPf�.���9hL!�U/H0	�G��)��pI��p������	���t6�s�^�j5���'�j��� �y���dN���M��1��4U?�9�>'���u7����(+��C�0&AX���s�����a�)��@2� x��(7����W�R�N���4&Ap�dq]�k��csA$0�L� ����alL!~eJL����s��9��Uf2� <E��`�]�T�^�|~_sz��$=
��V<��q������IO�$�gm>P���t�������! Y������9}t��	���lbhN�����$�����r�	�iv�V�I��G�yp��a��$!��t�A��C�e���`dL�� 3	���S��C�	D&Ax������Lr�M���^�������?�O��)or��$�u5���o�����vfL�0�GCXkd����d���
M�L����s�0��=���D�Q�I�� xtc��4�{d�I��N�f����h����(I0	�G�&p���9'�@2� <u�y{y����#Q��"x2���m�`�p���0	�s��3����7�h�����g��~B��a*���=F8�C�#[`�,3mG������>
$3	�C��oL`�Q�IZ	� �f�s��c�)���AF��YPf������6��m��`�*�cB@��A���$���� y����s���"����6?�F�y���F��z���Id���������!�T�i�~�w?��A&���!��I0	�2����BN��,��������8I9�BN�H�A������ ���h`�����0E���DDL�����=�!�� �!�d&A����=N����!�t�y�O]oN�=i����~�����do��p��4U?�[1���L)��C���`�,K�3���9��G6$3	�G��r~0t���0	�s���p�eC,0�L����oq���P`�$�����:0�8�����[O)g�k� ��a!wN)F��@@�&Ax�zs~0�&}
�NSEx����0���#x8A�L�0f%�W���)��b���:L� ��LZz�r����f!OX��>M10���p� 8_ve]���8?3��JK���~����If�-�d:L� ��������w�kxF���mu��'��;Io�@�~+O�6g�E8�o��f�w?T��XN"�����I��J�Y���I�<�	@�I����FA'i%L����:�E.��G�B2� ����$alL#~K;Q0	�\����y��P'Xf��b�PX��KwC�i��^��7�CN�_~����~�������=��$���g�Mz&A���\�`��M���p��8]�!;5�����f��
2��$��Mh����a%9IaOn=��� [XA����������D��� H�[�����bPf���6;N����]:&A������?d+A��"�]Z��I_C�Q��T���d�� 8;�&A�N�zb>12���J��A�����d+�I�� xr���9��U��$�c�d�*�&	&A����f s�����I<��qn���d���0	�����p�
�d��� �n�F�d�����i������M6�>�|B���a��o`�^��3��`%�L�����]0A�V���&Ap���`s��D�I�����IDv�� �.y��IB���
(3	���w����.�
�H0	����YB���
��V<�1�s��M�$o��0	����������;%����d�o�q5f���7�y#�fR�� ��)�%����%�L� �F��[T���|�I����y��^R�M �0	��l������M�L�Pg�������e+A��,(�������c%z��6� �s�1�Q���e�<���(dG�zr��=����d�I<��a�ir�&�$����!`s����D�I�?P 3��d
&A�������d���d��$���d���� �������M�7#�$O�5�I;27��a���Q��2v�9����r��� xr�������4�#�B2� 8t����^�C�$���|4�%=��$3	������.�
�P0	�g7S�����q��$�
� xtgN�&}
�@0	���'�w�����%>�e��VA����p�F��!�9�${7����/4�N��M0L� ���=N��p`�I<��������$�#�$�1�a��
�`C�L��������7���	L����s��9���N��[E�K�x��Bvt�Io�$2���a�����!d�6���$f��/�7�l�$;��e&AP���a����d:L� ����7�l�$�2� (���"���eS%Q�I<���"��t�	 �I���g�����66oc�WI�~+�.�X$z��6$3	������t����!���~�a��*O���� ;*���_[E���MN
����$-�I<�;/��>dS%Qf�*��Q!��>dG%@0	�����R	4��Z*�G��#�
����]�&A�Q��8v����!*	�o�����A�S�IW�$�]o�
���!��	2o�IF����f���l��~m��[Af�KIr�6�$���Nl����(3	��KO���1�V��9������_}��	DvRe&A�V73�����Ad+%P0	�gw�
6��KI�~�r�;�S�IwC`���"�o���2�V����)��e&A�������3�l��~m���o0G�vJ��4&Av��=��P	6f��U��A6��P	L����o ��4"�)I2� H�{���KwC@�y��]���4��w��j$h�U�����w��k|���TXf��o��{V	2�d��H��A���6�iv�F�$����4od��H����������,[f��*�g7>��]*[A��,\KE���t�d�����k�+�\��o/�Fx��%Kg�$��MhA�&�
�	���P���K���!�UVd�:L�`&��
����	&Ar��v����f�~bbl�"�����$�����)B�6} �I���/U��,";I:L� ��i�]z���$O6�s��l���[Yt�KU�7�k2� �������:�6���O ��e&A|�D�^���K���62b�0�k�~m��[�79�J���&A�AgI�8�.J�!0���"xvc3
g�EI�	��5UO�~�6'�EI�������9�6J�w�n�A~|s:�m� C`��[E��K��8�.J�7�l����9B6R>�|ZA�-3	��6�>��!;)����_[E����-$�Q�I�� xr�g\@s
���$�I}r��m�$���_SEp�����hL��TA�>%{�����[�^<���7���	4���U�n�9�!�8����a��K���t0�2������$��f��n���1�s~m���C��it�6�$�����`c
���2� T�}�h�h�C�6�I������l�6#���!0��R�k6&�w�mH�5���;����)�����V��z����M:�~M�����}����[f���f�{z2g�?J����KOJY��N����&Ap����d�(����V���%�lL!�(����'5a~���@C`���"xt��Q�w�n��5���>�T�9D�����*�G�*`o����k���M���7�UvaC���$f����,!�W7���$��2Lr����fO�(6���J�ae��*@c����~MeA�
��)B6��lA�I�����t�	�I��y/s�.����bhN!�u���V�?���IW��1��T��jq�	Bv�>�|NA�-3	��;���`��eL��U����8�w�l�l�*�g���c~��Vv��� <�p���ml���T�>���R6��Ko�$��a�{R6���Y�n����M)�F	���a�g��-e��C�4^�I&���y��[��(�$$���+�b�����}l�yu�����7.�Se'�&0��T�z��;Uvp�
�i����l�y��N�w�q���{���Zvp���*�G7�������Mz&A���
��"8B���{�L��<��^���Fd'Qf��>,��4
:I+a�'��IB�o�
�y�nA���?��Dd�&H0	�Gw���S���$�L��\�9=��M�w�k����Av�k� ����0	�s��!;G����aw��Rb��}�!�S�x�L����em��B���Y�������+�FA'i&L����Y��),��Ad�(AfG��R��"�FA�I<�wG8��Bd�(If��|�@�.=
I���"t�K3��9���Q��[Ex�zsz�]�Do��0	���o=�]��>�lFI�zu��L�z�s������ xro�l�y�����W�� mn��;T�N�mBb���,<w�y���I�w��f%��l2�l_$h�����S�����lf|����40	�ms��S2p����I2N{mc��4
9I�`!����Av-����n��������M`n��"xx�Q�`�n���D�I<;��G��e�"���7L� #������lZ�Z�*�orc��y4�7�hLk5UOn'k�T {B>{ ���ar{�yU99��E�!0��V<�����lZ$;I#a���s&'�����U���38��G�l��j�O^_��Il�c�TU]�	��c! ���W�}�4���H�~��z��@6(�IW�$��e2-�C�!��%��I����6G��ohL������{����x���0	�����?��E��YPfa�����M"@��ZSE����`c16f�Z*��lL
`�����j�+����Y���H�
�i�n��;?�"y����$ZSE�wX�)�>���M,;�Y&A0��o9K�FE�M �0	�Gw���$d�"�IZi&Ax���#d�"�&�t��]�v�h�"�Oqg*��,�o=�!��6���$���U����M�L���@�!�6���V������Mz����������x���~Zy����Vf����j���$!�����Z[Ep�����N���4&A����W��<";�2� �7+��Hd�"P0	��w�h�9��^E��$��9K��=�! ���W?��O�.�m�!�wR<�IF����0;�y;�{2����������4�-�iv�F�$��z<�[E�����n��[�i�F���$���RSE�����4HW�E��;m��.=���������7fXZ*�\��go�^A���4	��O�QN����t�����W��O�>J�	{��=�N� <3�|�;	9�BN����"<���$�le�A)-�����\d�&���`����H�q�Q6�d�Ai�+�G���(W���lB^��0	��'�������{t���9��$������l�G��K��!c���pt���$M�I|;_��L�$�`	2� 8r��$��mC]��B`���"�F7���<��C�~x�l]KE��mDoc�u��M� xr)v6u��d����e�2�k������&
&A����]�m��V!�U@f��U]�n6���TZ*�g��d�`�/L6Ko�$O������M���`�5�����e��C�����IV����J��d�5Yfom���]�$'i%L����sI�d�5����Vz�1���R��zg��"Ho7N�����l��HW�$��3:�<sSX�� �I����2�:z���I���*�C��
��QP�^|��]��,��r�����u��V!�U@�T�����2/t����|IJKEx�z�{�q�P0	�\��/��.22=$�/2�`��;�3�g�e�"m�I2��13�Qp�I>!xt������ ��y�ip�G�	A�z�A���st���Iz�A���������&APtk�
��|E@�C �0	B������t7}�-����$�ndZ��{�3������$J>��/�~F^!���f�@n�����=b15
i�������3�<y���L�:����I�ivZ5OEA������@�?b-�����p2��o2�g�MF�!t���N�w�����av�!\�VHH�g�e�"�<L�H����x�B�~�+s��DbS3	���X���2^�>�����	���U�no������M�$���8#�W�����`O�u^d�W�zn�K� 8v�)]��9+,�d��$�������^}�iA7��GY��������[o����<�B����Id�5^��:��N����"� �s^D�Wa=������[�������2��I�e�D��
*e0	�Swu���l�^��0	�otv�y�wi���OaQuH�k&A��j�~���S������*��7?��2v����0	�g�m>!�.��Y@fOn|?Dhd�H#����SE���f::��Mi��E�&A���w{@g.�*�0	�G��8e��� ��7�&Av���h:I��F!-{E�7��8'���g��~��$��%#�U�i�<UO���B4�$VIHi�r�[;~����@�`(����F/x��'����� H_��)�9A#/��i#L���(�����r���f�������W�DC`z��"�|�E����I�� xr�A�d�U�o33�����gfr���l1���Iz��������J�L����P����� ����&A�vw.��LO�E�(�e�����"�B�����j�$������e��
9�2� �<w��4��TIHi��n�be��Ky�1� T{����:��RXR� �I<���A���l�^��0	B��x�7��a"����! ���au&v?�44��!0��V<�3=X�N���4&A���D($cUgdL|~���~��U��7����� �FZ{x:C�9��o��['���;�tO�-gV!�$Bn����3:(cC8P4	�g�����=����@�I���p���n��@��� ���B��`o��� xvk���oh8
CCi�+��Dr�{���H+ah���
�����9���&A0��O���5��y9�&u�A����3o�?.��Ii&Ar��58�y9�&�u�A��wj�^
�eh8�y9IfA���7�/��k2� h_7|��������q3	��O2�Ny���F�$��t��4=�3����,xt{6�#2�<{�&APvc�#2tZ�V!�SYtk��d��Q��b��6� ��5W�lz*�+���$O^p�!C/���f�=����������8K�� ��G������ �AYpo@fO�|JGr����0	�'�g��9����0�I�*�7��r�?����X�b�$��v����iXIx��R<������� ��7�&A���������I`M1
j�+�S��02\���$���dF`��
;��2� �sS���Hi���]k���@�`(����S�4�V32�`��uXD/��i$L���x���c��~�6=>����3��3C�$?�>�e��!x��JO���B�$�#��'8�X�O�U���IH2���M�Y!SE�����,�� ��^��1&����"xr��,=���(�&d|�$2��_���Y����4	�tk+�����C��a��As����Y���4	�������1tZ�V!�SE����f'V�I�x���R���t9�d�A0L�������M�����5�A����9�^6a/�J���[,s9>�!�^
���I������XN��*�G�g���4
8Ian��g�9�-5�	<��V<�3�d��O�YAH�I���>��!���*�g�O7��,W8=�Q�y,KE��f�MG�3�d����&A������	}n�!��A��\d
7a���g?�ia�Y���yrZ��V�SE���r~�A��l@��"<usg^���4F�I��t�>-	��Z�������t�>)IF^��0	�����3�3�B�6q���a�w�k�^�J��3�d3	Bu����3��OI���4&At!������ $C��R�����MtB>1�x��V<����N��AAx��R�lx��|v�!�>HA���'���O���M0L����/���|�sdd$3	��[��8�{�C�&Ax����}�
�!����wv���p��G9���;"��0�`��$f��
gFK�����C �0	�'w����iv�F�I���7K�-a�-7�lA�I��x�������|�I�k3g�E&q#���A���R��-]���n�I����"#���W�f���~����t�G-{Yro^��=������I���~�vZ��VA�SYxr>����tS�����R����0co2�L�L�PgW|�*c

c�@���a�+p���	{�f�Id�3�.�m�����_����C��&�3� �������%S�x��V<��e	��it�&�$���.Prd�
�G��*BO���vnR�d�<^o���5}������*��J�	J�+��z[*�G�/}_����4	��w�A��R�d��A��p>c���g?�iiwc;�<	9�BN����"8r��N2��)%QQi��}~pr�%M���3���V�J��!���������l�^��0	�g���q�~x�9aEw8��L�p�<���~�VU&���"ddyY��<��Q8I� �62S��d�D��f�I�������32��M�I�SE����A��N�hK�E:&A����~��:s�X��h�I�����	y���F�$���/�����C��F-{Ep�����&�y���7M� ���n���Va�UP�T��n|�@_w��
�vKJKE����#6}�O��0	�\��T�{���
&A���H��#�)B��p*��a����FC�	�'�n!c?V{Q�>;|�9�����'�|�=&Ap����~@RR�mO�*�g7O����OHJ��Grn��Ob�$!�C�'S.��;w���B^}�i���/03/ �(�������������Y���4	�Gw�� 9�BN����"9�G�= �	)�����D��"�sa�&���`�z�O��M%	)HZ���TW��H>
�i#L��o��)��5��/�i���!L8n�0	���}V�%�(C�@�aA���a�t���fA�����&�t�A��M��v@���@2� ��5���F6 3	��{�A���lI�
�L��=}����pRF6�@0	�'���#{��=�A� �w�itZ�4OeA�������0�	D��,���V�l��F6 3	B���{�|�,�����!��q���ap����pB�8���U��-Dt���0	�G76r>�2�|�Yr�5�g������� ��|����'l�!���a���C�M�������r(	&Ap��=�`s�F0��M� ��9��y��GM������D�U�i�<U���9lN�To���R���=`[�6�$��A�7Yz�B��	z��� ���:9������6���'��IF�am��ds�Fl�(3	�c����IL��Z���[<Z�l��ng��I|�[KN����mhp������7X6/�d*76��;l�7�{�����"��5������o���A��o6M� ��{�2}B�Q@fO�MFG�<z�C�&A��9��FN���*�y�~���f�N
�g/�������d�A��[E���C#:��Lq�!���wuwz�i~|��9�����~�$������S���04�3�UA�Z6�����`�.�&�� ����&����"xt����.,�_���$}��/=��e5}Bme0	�7��/0�:|���I<�3�6����G-{Ex����g��~��$��F���;��N����"�?}<����L�aQ����� ���G4s��d�A�a�[E���n�������!�������X��l�^��0	�G7cRz"���r���w�$�� p�Z��Hr��G�n��{�X��JR� xr�z�I��M���SEv�5���.��������4�D�����`$���+�9"�\@���M� �f�?��$l�?��+��`C�L� ����j�	{��=�QN� �k�{\ �itZ�4O��;�v��Fo%��JKE����3O$�H�d��$����\e��[I����"x����'��/�F���q���
�z��W��!s^3��=L�`&]]�y"I`�	&A� ��M���N�����L� ���zA�`?�U�,��$�>?N�>Pr'�|�I�#�J��M�L� �����yII�������y@#���W�j����I6�%a�&���eA��*��y��G8L� ���*@tZ�V!�SY���K�M)�"HJKY�V����n
+�m3	�^���w�^6a/�2� <;�2Gt|�OW���!��[3	�����#:�tU��1���n��[����FA'i#L�������M_�u�,(3	�g7���DF��2�	<uw�O���2}�-��j���{�|5t������
� x�y@J?d�u���L� H�;O���
�QH�^�xf7��<�B����I��M2d��
9����������M7��TTZ*��{���M?�U��5L�����I^6!/�Id�n|�	$�B��p���a�}�Z��$����Co������l�@����$��I<:�)q�)*�tQ���$3	�G��,���$Y@0	�'��b�>J�5�� xt;,���
Vc�$�����$]��o7M����(�^H�5
�e���M�it��&At��06���L *-��f�H��7�l�����V	���$cA�^�|�-�^H�%��Ha���S����d���Nk�b�p����0���!s@�.��&����"xr����(�$��I2�����98tHX��R�����������l��*�'����Ldk�E�&A���B�������.2�a��\V�^}�i�z��3�Nw���(�e�����y���8M��\wsevZ��VA�SE��>�=3Ow���l��I��$uta�p�o4=�/��0	��Os�d����&�E5L����)}����9X$o��5� ������/HN�I<��2�@R&
�G��*�G���3��	D��n�����8(s�0d8e�L������/��	V#�$��9�� ��7�&Ax���3��	@Ci�+����/��	d�~��$rw5
����*��
h�*�S7W�	$g�x��R<���%�7hp���U��D2��dM h�+B���7�l�^��0	��W�~'_�cI���y��=L�`&���4��p��4���$9����9;��(�$�3� ��v��!
nY�I�\}���m.�C�L����O��
ih@2� ����`�I&�ldx�I���&R8<��A��o6L� ���� �E����,��}&�<z�C&A�f�]D�U�i�<��'����#�mQi)O6��M��	 �I�m6���#�mQ�^���[@�^6a/�L3	��^�s���G���*@i�9p�����>z�<��l�J[U��3~�����<�t��N���4&A���M `�WbI7�L����/�H��4�	<dx���Z��hzJ[M.��0	�\���}�<������N9L�����;t��^a���4	�oww�s��,��������������,��q���{�'�itZ�4O��.%���+�$��T�'�=��7gx��V���I;����E���u��D����C���\g�
��C�	�f��s�zV
_t���l�c��*B]9�����ix�f�$���_t�������d&A����D�]�<U��ZMgt���la�Ho�$�>�HW� g�
k+�0	BF�����1�:g�-�I|��e��l:&,�FA-{Ep���n��gA�~8�$�}��ivZ5OA��=�����J�JKE�����Q=��7h0	��W�~�`cYgl@�{Ex��X���lB^��0	����+-������S�:�p���aqw�S��h�%,e�d&A���c��]
h�%�efO�I<��!%�pL�6��I<����~�`�3�B���;lA��Z���<��o�bFFL�P���gM�_}�i�L02�V3���$r�����+2�<x�c�&A��5�%��&9�BN����"��iw�AFO��LRZ*�s<�D��d�A�)�[E����z �S��d��$����&�y���HaOn���BG��)��'�I6�aw������j��x��V<���+3��(�$��I��9��r��Gb5�L����C@3hl�Hc����������U<i ����n�t6L� ��m���;r�AbQ%C&Ax��3�g�u��[M� xt����e�����WA�n�!{��=�!N� <w��%/�x��T���G�Do��x��V��l�!K�q�����W�����{���H+a���������!d>d�Q��I����g�@2t��d&A�����?�@�@�aE�UNo :H>��$r�[~��@RtmHf�'�7��d��r �d&A4?k��26�mI�a(�AGxozv��Y��g0	�����,�2�N����,H�[�P%�mz��APZ��^������ao~��$��6=�$�����,how;��M��4�L� ��+�����Mrt<�l	���]3	��}i����W���,3	��w;0��(�$��I|�;����J�td&A�+~��3�F���hx�T<����W��$���{��3%i:@�I<�7'=�tW�-�H4	�G7
7A���g?�hA��OrZ��V�SE�������V�.���Ta��� {���!N� <�n�"I�6���"<7���$W���&A��l+&NO$�:B��p��ar�z��MO%�:H2� 8ts�e�H�u����0	�g�N
�\����"�U�[)�I��M�a�SE�K����$_�p ��U������9+��L���@�|��� {���I��[���7��)%_Q�^��}���y���8M��Tog�PR��V!�SE���>�l�JIBTZ*�\������4<�x�O�r:B��6���"��nno���l���p:���0���Nwt���l�aO�*�g�~\Ft���0	�G���4�8���$������pW�6�'OA:����;:�tX��Z��a��de�;(cgk�0	��
����A��o8M������M��e�,�e����n��ix���&A���N���O8��X�$���"xp�KB�Co��p>��U�����G8�XoH�^��;������&�E�� �d�{���i����y�&>L�`&}��YB8+[eA�I<������it�6�I���������g�aE��B6���(3	��l���Mge��Ez�L� ��c3Gd=n~�C�L� ���B7d�u��
� �{�<�Xl����,�������y��9L������yvZ��VA�SYxr�g^�rz�2�L *-e�cJ+�� z��fHf����6��%���H3��u/z���S�y���H�$B.&�/<���d�m�XX=���m�`&�S)����8�
���������kmz=��(�$���TA��G������p�<��V�m5���8�6��s�������F���44�&���� ���G���L��cQ%C~S��??
��u��M�������?��6

�	���A�r�7!���g?��4Ux�z���VA�UH�Td����36�pcc���KY�f�����<�9�!�s8�H6� �C��WfN����������� ��<����ir�F�$�����y��8��2� 8xs"��lhL��6�GCO�����|<�)d8�y�*B�\�7a�l���BF8L�P��y��^A���4	B}���x�'�YP�^���%�<	;��N~��$2�[i8/l�6�
��3/���_���IC��[Ev��q���04���"<5�p5��	z�F�$O�`�+z|.�9+����C��$��\���p��0=���&�t��"xp��tD�N���4&A����N@�Q!���d&A����D�Q�
=U�nDHtC�����t5L�����:����B�/�&At�w���_ ���M� <5�3gp�9��xB�T��9�m����&A�����lF��$nl@�{Ex������l�^��0	�tw����:�4�"�?l&AX����Z��z�r�� ��Q�U��~n����ir���$������x�i��xF��"xtk�6'�Q�QCC�y��V���7������YA�/���[i&�)��� ����&A���W����g6F���WO�?��p�
���g�$�-���9�BN���$r���`c�`dN��r���$��z������&�EL��1�����$x���p\�a3�����$��� ��4���� 9I�$J��nh��	a�,��$�>��m�wxZ��_�
g!��2� <�l��=�	 �I�����3��V��$����L�:{���I����7��@�@���A��n��ga�~��$���<A�'a�U�i�<�e�2$iX����R��E�%���3O���BG�K�Q�����$�{Yx�z�	J��i��A�x3���-<�$V��3{�$��\���3���qh<.x���S��4
;I+a�����Pr.�
��*�ow����$] �<Uiv�P:B��6��;l�I6��]��(
&A�K��6w���B^}�iO�?p�J��@��Wo�4�=���� �I����|D�UH�T���}I����{ (-��!��A��@�&
&Av�[���$�I�^�f�/:�������pz��a��7�,�Y�8+[���s�������HN���4&A���e��TXX�B2� H�����
Oehx��T<��Y�����U��n���I�����tD�'�tUXY��I��O�/d���� ����&Ax��37di?�)�������!c�U���4����+���`�����|�������IgC�y��V<�w�4VZ����Wiu�'��M���&A�����D���s^�d\x����^a��}+�G�����D�pd�I<��B��$��I�� xt��e���$�AfGn�KG$�H6��O����M�!��6�&<lA��DtC�m���`$�A��s�2�� ����&Ax����\@Ci�+��F���&�y��8M���w���yxZ�Va�SExn�g>P�-�
�'/�����\Do2�`�n����@���T7h0	�s���,D/�H�A<W����n?��\��:�%l&A8L��Jd:*,md&A���OU�����f�$������"��Y��(<Ui����#:�tU��2��[Er���`g�
Kg0	�g�?Y����A��o5M�P�����`�Wae3
�L�����y"#���g?�iG�H�3O�N���*�y�r�[�l�*�����R���'2�&#
O�*�g7���d�*,�d��$�������y���Ha!�bq:���{�*,���#}� �I�4N_d�l�gp�:L����s�^:��N�L3	B�+/zA��?�u�,��$r�;��%N�����A���(��\�A�����"m&A�����K�e��8��$���g� ���W�h�A;���{��!����eA��T��ga�~x�$�N(�4xZ�Va�SY�q��Ch�H�����R}l4~TN��<��7i&�<Jx+�����$7j&���e��y4s�F^6!/�F3	B}6C4�Og�����=|��E�!�a3	��?��K4���!���"8t�>/��CDD������x���"�vw�.��S�l��*B�/�i���p���U�n�M8��LW5`Q%�&A������M�� ����&A���%�pW����Az�/���,���p���+OvZ��VA�SE��vwnX��0�
�g/��>w!`�cN�]���d���^6a/2�a���'of������C�!�f��}�LJp���24���U�������N�?_0��zd�Q�IZ	� 8vjs������e&A�����hz"�W�-<U��Ddz*[U-��0	�'7������Sai#�&A��vr��&�u��[M� �A�|yO?t���������+��!#���g?�i!wf":��N����"���m`c�el<Yx����o�Fg����d��$�n9.z��M����3�A&��u��&�E	� d�O���y����u���9;#&AX*��70�M�h�x��Vj��,D�Q�&�4_3	�C�6"�P���$��������
�hlx��T����p�E[�-��0	��7�tzr���J� Hw7}���:sXN���I|�[��yrZ��|g�$���Kc�?�bbL�JKE�+��3��m���M����)4���:f��W�����l�^��0	�g���0-�2�o���a&A�����)����1sc9!&A���JN�������}oA��y����
m��*�G������Qfq#C����Vz�yN����V��$���y��^A���4	�G7��p�bh,n
�e��q�p�<|�c�&Axf�e���irZ4O��o2Wt�����HBJKE���6��z�q�g	oAZ]���l���Mg�%�4�A���q��'2��	y�F�$O���rF2�<�����>L���}!p��B�C�P� (��3�.PR������IB�[��J�!C=L�Z}�+��H�x�|&Ar��Bcg���� �0	����4n���A��o��A�M���q��*��##-{QPtsn����I<H:L���V���I��*��I�@k$�J2���|������Vx�9"��A�&��0	B������$�������(<;���$�����0	B�����O�q���Y�f��������T>�GF2� xt+�������4&A���/�H>�w$C�!��� ��`����<k>�g� 	&A��V��@���h8�w�*�G7G8]�O���(
&Axj�e.�g����o6M� W��kM'��wd�e��]���{�c�&Ap�����I�ivZ5O��;wM7�Sxd��T�6�pnT��d�A��[Ex���Z
���4@�{Ev�'�{���H3a����0�<;�Qb]u8D�L�0�����&#�~��6&����"8rs�6����(�$m�I���#����x����o�_����42��M���SE�Vw~�M6=�-'�l��I6��e���!N�P0	����K3�:z���I<���E��*����AZ+�p�<z�c�&A���W}9�BN����"<��$��~K�$��T��!R_e�M����U��ZM'x��&���Q� ���M'h�e�"��I�w������C!�]8��L����>$C�Q�IH0	�C��*���C�����o����)��|��m/�*�sW���'!�6� xt��R�3W�3�� <����"z���I|o��k$�����P�^����.��Y���4	����+�)D2vZ5OA���"tE>��xv�R��>��GO��d�M�L��\���|�!����=��M�tD>�H�^��0	�G�	Z���~t�k�~�5��u�!�a3	�a���RC�O���^�U��~Z
t���0	�Gw�E4�$�U���$�8s�>����F6�GOA�zdI'x��&mE�H_�$2�����>��t�%���� xt����&�u��M� �o�Q�<���XU��Z�����<wsg'���s��9��M� <5�d���itZ�4O���2�w����JBJKE���S�2�g�M�$B>������L�����.����9s}�^6A/�F���md����|��C���
g5&A0������|��M �0	������|�����fAw;KC�7��%�0	������)K2�!�d&At�fR��}���$����|� 3	�'7_5����%z���I�>�g�<��>iI�Z�� �������,����0	�����'A�U�i�<���n�����%D�@RZ�B������� o2�L�L����|'�*��.�',�P�^:�G�m��g,�����L����w{|�Ny��p@�����so=�5�gdxH#C���[Ep����D�Q�I�� �F�����32��!�l�[E���J�?��C�m��*�g7���46|��!���a�O
3x��Ly�N8L������u���L� ���}�6\��!������{��=�1N� ����Xlx*cC���SE�������7|���7L� �n�U\����
�u����o�2��	z�F�$��_�z|o�y*���b�If�\��u���V5&�8��"8r��:��N�F���[��2Ot������e&A������D���2�	8��L� ������������"�
� �q��7@Wt�T����J�8L� ��D_{���v�$�v����hz+��F!-{E����|z"#���g?�i�'/8=���*��
j�*�S�
�o�����*	)-An����Do2� 	&A��*�������J�L��nv�o�l�^��0	�h���||v��I��'��IV�m��c6z��L?i�x�V����N��ir�&�$��|��y�N?�u�,,3	��wE���&
mOC�*�G�/��M?iK�Ez&A�f���1v�'���1� �H;����@���W�h����E�ih:I,�F!-{E��u{�5��=�����I<��H���Va�UP�T�g�<���X�%A��"�5??�N���4<
}�B��l�I,�d��$���~�e�"��I2������=>���#Vsa�I��I�$�����ct��VT�@�aAgo�y�c���FA'i��!G����cn:��;�t�X���8L����
��	q�
���F>��$u2�1'�t��|\���$z��_�N��\�al&A�&6vB��y����$B��DC4} �k����,��
o�	z�=��� �/MFN���*�y*B�8k!�0��r-	+-e���O���4Fs��ixk6��������u/��� �\����Bw�E�!��q3	��������7~�������p�U��*s���c"8�N�:��������dz#��f�I<������pG�6���OA��]����@��*m���I<:���G(��*���X��
� xv��vy���V�$����l�(��FA-{E��f���&�y���8M�����XtA�N���*�y�=��'�`�Ga������������4�(co2�`a���J�������W�6�p�B�^6A/�H�A��1��G��(IhB�0q���at�*���ePr����o��[��2'(Ih�N�H�!c��s6���I�@!�P�[E�����Q2��� <��t|�xd8�|�*�'��3��I�+���`�wY�����/��I���#��,���1������p���V!�U@�T|�{��M%�_HJKE��n��>������3����<d�|$��Z���&gi��{$���4&A8�<�s�q>Rq�+a�t8P�L�0����G���h�%[�����������}���(�$��I<��U��NXD��2� d���4��Q���jQ�*�\�V"t���Mek�Ez&Ax�M�cIWn~�S0L�����lqa�:x���I<�����Gw��z����{��'z�=��M� 8t��L���$�
Q�T<�w�	���5c�UA�n0��Ir�����KN�#9W�^��0	B�TFt�������p���au_���
�����$��x��V����|�$�^O�L�!�[|P���H�P!���[E�Mn�"��4/D���������$
M%i^@�I�k5��dy�r(	&A�����I^!���4	�'���J6}�$y!j�+�cw��n��ga�~��$�������
;����� ���L2���$�
Qi�O^s� ��6$�����g��I���0	����{4��C�����y%�i���� �Ia��������lYq$&A8Asz+�[!;��N�J3	B�]z�_t�������s�!�;M�!��Q�1� �4��L
�
MGeK�Ez�L� ����z�3oa��U�f!�����A������.�A�����=�����I<��|n��VA�UH�T���_�t5�VF6�����g/8J`o2�L�L� ���:��L���33	��[[?��l�^��f����_�_�����������?��O�<������������c�����������u?�p�����
6�����ar�?���/��~��_�����3~����u���G+?���r����E.�!x��.�!d5y�>��������_~�o�����������_���\>���?X���G��Q��w�X%�����/���~�o~��?���������������N�b���Q�����w>���O���_���_�������1w��u����\������//5!��i�_~��Q�_���1k������>���R��t^�����_�|��-����n�y��������M�k�N:����q�y�����g��Z�6�����s�������c�T��s���Z����������}�����zL���n�Y�_?���e��'e��yM^�UoA�Y�]�Uo{j��/������a:��\�o/_�q�u���6~��e�>��I���}�_�V����
��r�����//�O���j������v�y/_���_��k������������bM��2�g�qU
7���0��?�����������|z�7���A����t^��<d6����)\
+���n�������_�n?]��U�"���W�R �����(�e��&rb��������P����}1���B�^�w ���s��~=@,����i��I��era:sb����\�b�X(�=b�7{C�X,��8.����7���� ~G������������w�i,L��=���Pl_�#\�X�������A\ �~<5�v=@,��_{`��B��-r� 6������.@,v��B�,@,��x^�Z�������g�_$���X����
�e}�igV��[�g���`���P������$
e?��Ga���V�
+���^h]PX,����3
����{
_����X��������X�������X�;�������_������5^��GZ�����)k��~>������W���_s�Y������c�`�T��/<y���R�_.x�<�,����}��`�T���q���?���V��oj�G�������5�0����B�G�������/���O�O_^���h�~?]�6����eg�f�~����&�6�s�_���1��gD�b��x����\�<�,��������sk���_^�����m����������8KE�u!0D�Y.����8��"�|s�q��`F�o.����������n3� ���P���+�b�?'��<(,����A���vAa��o6C���P��Oe�m�1}����������Z_��������������m��(v�co	�������Q2e��y4e�ye�������
�.P,�~eA��b����v�b���^����d��+A��b���Tf�X,�
����~=���4.���ga�{/E&~�v���
������r�
�.��;��B��&���Y�k�z&��va�e�pM���n������}�5�����u��P�o���/��u���r����X�*����a����C����R���/F����R���(y<X��/�^%O�c��cW�����k��"�(9�a��b��xlX,���"��[�,,�r�����_�e�����q~���r�/?6�v/�L�R��/����������a�
e���a��o�W��9�����n�{1����f������������yPX,��o�\PX8�����?yPX���]�yPX,�MAa���>�]PX(��������A��Ax����U����mr�o\H����b�o���|���{�T�[v/�~���b�o���\�;��b�/�����b�o�����"
�Z�
�V�N/��}��.����Y�����\�'���B��l�����P�����O
�����[�<(,v��I��[���X�_W�-�Aaq�<�b������X��.�����b��.$�����U��=������� ���D�������<�����ra��
+�����\PX,����yPX��/?����B��yRX,��h�A�{k����_�Vf;���<),������#(|��������4�P����������_~��>��������������0�����a+��f�%
?��0��R?��k/��W�mfX����?��b�R�_.���c�R�Wv���q�����~������L�z��/E��i�_���_r�m��;��O�a���f�q�_?g���,<.��Gx|��i��/<g���r�����������w2�Ke�y������������_����o�w��T@���O"���o���!r��+:��T���!r���l�,������_���|�_������Pc��o�1C�7wC��������9�z,X*�s�����<,��x��X�P����_�&.,�����\,X��\J������x(��G���J�z������=�����y�W,��O�z��r�^�������>����U���&��
e_�Nz9������y���x����N�K�~!���������\�W,�����Ow���8��a3e��7�7w�������r�oxDZ.�
���������"�����
�����c�X�P��>#t�_��/f"���v�9c:�&��#�������W�.�+^�+�����P��#yqo`�{���C\�W,���}�y�W��)�������'�+^��|Z]*����&.�+^��{�Wwd��#�bv�<�+���BjY���o>r�_��?/lZ��������l�����{g�W,��������
�&��!���k������o�����o�q�or��yVL��}�C�B�_�������]x`���B����/n��������B �����v!���=^7_������]�������]8������=A`�O/�5����Uy�C�B��/��������]X���]�\X,����l\X�G��dpA`������_T���7d�)�� �X�;����x�>��k�~C��r��?����1���.��yL�������<,���7.,����d���B������������W.,���H���7����z��K{��)'yX,���{�MA`�O_�����U�p�r��~��t����.,^�����A`���]�.,���.<�tA`��?/�4�������7�����&��5fX,�
���~��������Y�����k���/>lH�������������/���pR*��9����T����yhY��_����T��z��e�z���)-�W�R���������e�e����u��|�\�_W��B�r��'�,_����.�E��f�e�.�rd�r����^}=���D;��zr�������2g�ey���
0-���qan�B�R�oI�S.�
���`��������\�������{�`����/�Z���-�[c���z�b�R�oz�X*��'	.�+����Ke��9������J�]�W��_�x�<�+���8����Y�W���.|����b�W������W6f�_�O�x����UyO��R�^�2�������^�������?�H���r^�5����=z�������?�^_~�\*�-���]0��B�oy�\��6�~���r�o��S.�
�������������\�X�P��Wb�<�+������<�+����.=��~[�W��WvF���x��^8f�������d\�������K�z���������$3�>����_�������]���L����������X�_W����_�?�������{�����K����<�+9���0�{s���
_yb���X��ze�_��7|d\.���{k����q�~Gr�y{��-Y�S,�=_��~�/�����B��.$mvA`���_� �x��]�i���+��J��<,���(�
�=����c.,���J��<,���y	\����� ����\vK����
`�~C�A������h�B��b��q���l�@5��a�n4_����YH�^�������G���^�@�����w��<�����q&�OA 
:��p��$-|�����4�f�D5�~&'�H��1��v���6~v� �_
"5�h��Q=�h���
K�@>�Nck
qG���!D����Y�@�����5�=5Z�h�V1*j5���5�A �;Ui��;c���~�8���xGW#�@T������vA ;l� W�o�3�YSH���O������a�@���W��+>}����nE&�7j����x�����2R�i$�kpI�K'������T\
.I{k��hp��^|A�K��O'�^�KV�$5�$���y��,V����Hp���!�l��g��*���]�Q�$�%�{�L������i�>a��b��!���x�ip��#YC�K��!�\�p�33���|�$���+���W<�,�e6�\fM1����e���/�����?�^;���y����?����t��?��=��������~��3��O#�~��P��]�?��P��{��
�':����u����K'iT�?T�9`T�?�O�{������&������e�T���n��5��Y��C���l�������p;x���������)����;f���O#�j��@{��h�����F�?���1C���^%�C��_9]5����/�c�������G����aj�k{j���xvV��
�q�3%'��Fq���h�~y����5y�4����V�97JcA�����n>�q�2>47i�����1J�4����f��S,����3,h9�>�o^"D�@�	����m��k'������5a]�6XB�vP
!h���WC@�[�S���S%'l�����!���6l$���fj��V�
�vf�@�S������� �_�V�������!,|�qV4��|1��C�;�2�qA �o��A �q��((9a�D��� 0,|���vH%A 
������(�(9���\�M}&�����A i��@�	i����l�;l~s� �-�rf�JX����?��wt�T{JX���� �w��PR��jO�6� �w�����@�~q2H%d{������Y}��A� ������� �wtext
Y���^.A ��@��,Y8�U8��)�x
Y8Pr^��p7l}���y�����
h��.���o��G�z����b�l����c�q�t�(��{r�|8�4?�+��hk��+h/C�����������	C���^8j5pEuk�����uX�����tq�����O/������'�|��'��x��0�c?��r�x3@����i��gW��Y��c����bL�?���w>�e�;�~����~F��p�bXXBXnSA	aA8R5����),���5����T��~k��d
q h/�N�C�+#�h�A�)��<�u���	�������hl�;�|�bCT�9�v�	Z�l���3�����n!?6Dez����>C�3:�kl�/�Wh�
A{��klX�����!6,N���Zc����o��MwZN�!�f;���%�l�@SE�7�9�o^n�p����i�,����"�����B����/ya��|�!2���"C��G��������u"����p��q��F��!2D���42��p~��s7��hW�� j]-5,�������O��h�7N��A;������!,<�����'k1N�F��s�����h��������%D�>�<�o^;��h0kc�Q8
�p;�|����Ya�~��!$D��P�!$m��!!h����!$���a��k����Q��|j�|��H7vmD�C$��;gb�F�xpN��F������ j�Y�	V�D������ ho���C$�;�%k$X��~C�!,o?�`�����b%q'`�"AN$=�p?v�"���D�(h�����g[I���8	���3l�tSp���}�5$������ i���E�I��'8��=����wxm|b����Sp�O�"4�������TVO��c����}X&$$��1�SCB��9���������5$d����V���X !!�G>�p�#�#�p�&-|���@14���w����>o�nHx��~�/��+�MY\�l^!a�
��4���@�3�����C�Yla�N���������F��T���(��JT������;#ka*�;�r4���!���!����5��k\���s�pz&iXY��L����C�!���C6i$��C��^�����{�6�)�Ds��\��i�\f�,�%
������]V�b���������&��C1 h;#)������!��m���������?;�Nv�c���(c
Q}��j8�g����p��N�p0|��p�
�:�U�A�N����'�p�<K4Dug8����X�7�_��� �;�S8X�g`�3�9����%),���(���P���}��v����SXH����`Q����� h;-��@�����H�[5h � M�`�F�7v�%�����A<8V�&5��� S��62>�jPXX�\IP�+������bt�><������!!���ib�!a��C�Q}kt����~��XX80����_���0�b	Q8�p�*%�b	Q8��;+<�"~~�(�
�A���2$����?D��}�
{�CT�[�I�F���H~���Qa������F���3�Q!�;�iF�>��PT�6�7��B�P��Q!h���}CT�/N�M�
A{�L~���retj�B��0z#Q!�o�7�F�h�@O�j7����-q����3ST���������a��y'������f!���v�
Y��nY�B�vf3hTH�k��P�B��_[%*|��{D�
E����_�D���3�FjT�g��YKT�|2Q!�(S�\Y(�3(�D����ITH�;���F�����4*���2R������6+$�H�2�����BD�,�`6�������u�Y�������V�r9Rw���[�Y�B��d�G��_���dZ|�o"i�:j����y7���5f+k�
�{���h�Y�f�7f�6Q��H��M<-f���E^{��}�0�;�0�*�E��W�t�tK�����~.)���{�!�D��a�!�,���D�1��
����R���}%)V��$E�v�l�8�q&
�cx�g�p������E"��5���W0x���*�JSd�Ls�^uC�k#�"@�N������PO�����N�AT���i�������{��zC>�#iT��b7����G.
A"^�>��D�fF�k
���j����:V5��
Ab���Y� �wF7�H$-�������'��H���H���1$D�n��H|�fSt�Y����UH5����C��A;�=���F�<���X|�����D���-��'���5�LD����v�����LOm��4P��eO
A{�O
A;�m�w������4��!a�����CH��[������������BB���p��bZ�<�y��EN|���B���������������CT�k���!mgh����H��B����>HST���B��T�V��r�����u�=]eB�O��@���2u,l�Lu3i��D�!*mg���v����r���\8�(D���2��=�d,�p"*D�����)$*��B�BNd,�p��Mx�$*�
kT���=�VH�������G��v*����F��F���5R�$*|���7�����)V��;#A�B>8g�>���H�B��IT��[a7��
I;U�L�;�a�D�����cuk�D���7H��x��p������,`�aOQ!XaXx�
����6�
����W���������?~����������|���~��.���o��G���	�s_�s�=����p)-������L�G�.��3�fb���)~���}�����,���)������1�l��9H�U��vs<��������1���������p��~u����+|A{o�'����>���������"���U�����>����M��Vs�M������L��/�g����a������It~��}�>�����3y�]���|\�(��6�����0����7��5��w��?f���������g�vc�D��9��m�M���f����RN����~���A$n�������4���mx���*aS��e����������������\��?��
C��m�Tt+�o��9�����k��p���v���+�-#8�������N,��2&,D�q���B�g	�������k��+6F(Ke����P����,�l$�+K@K�?�%���i��,�wF���%����k_B�������,���vZ��V�%���75���gXB��,!�[�P8�K(�,�����qv��4e	������1���Z]��%��Z?�v`	x7���%���F!��P}�e	x��o����N�%�p���kB5���j��di���&�p���2w.��Fi
w�wJ����o�s*�&�p�|�o^7�Di
�s�&d��&DM1��KlT���d&�>M(�}����!����P�4��j�	hi#�Biho���J@��n����4���4oU�PX���P������*h�����3�&D=�@
�@fB��4�p��n_�g��Px�Me'3��9�]�Q���OBEx��9�@��������8�q��y��1*e@���Z�����4
f�[M���xZ�aJH�����	!���������m�"!�bEa������E(�@(�@(��4����P��������
7��(���p��G(�]�PX��p@�G@ec���P9�
3��'�PX��	G@����M8j[�'�P������8Biq�:c����85+G(vteD����U8B�lg%�}�p��s�P*w���8B�]�
Tv��8Ba�G(�z$���������~uF��y���+D8Biq��L�8����~v����M�|q���	�P��#?�}�?��\�P��:�}���8B!��8���OE(�����#�W��
�>����<?!m�/��6�G(��ti��#�l#&d3�v�Ja�#�p"�#��C��l4�R��f6V�-m-W�������E9h��f�����N�r���Y�r<�w�`�#;z���}�����!�Z���G(�k�#��Px�G�H>Ba�>�8�u#CC9Bq#����M����n��?��+c����|/nl�;.d?�����B8�}a�q�8���L����ia�(��x#��	����P���o������4w*���P8�P��GHo�p��9>������	�?��^�|~�-��Z��>�,���O'
a�N�p&��n��J'@9R-��F���	�����t���o�x���z��m��h�#~�Daqcz��	<�����[\����+�(���{!�Z:����:��N�v�D�]��|��wm~u������^����w�)��N|�LUP�[���g�vc�v�-�5�����XFA����O*���@��v�&P��~�D!��^(��6P�������'����S�<���N��Iq�?~'�B���X��[��n�����'�����6m���N���O
a�&�}#� �ue��@i(�g�
4���XXzc�QM����{�	�m
V���~uF�)M@��8�Ei���S��4w��3sBiB���Q�:���ohB�\���r�&�������N� �H6	�������4�e��4���9��M��A��9��N��	��j8�g���]p�e_���o�X
�s�_{�%���B ,W��� ,W�N,�V�������P8�����a	(�7a(���BXBX�2�ymK@����X�5�{��Y�fXB!���B�g	 ��L�K�Ke#�\Y�9����t����@{���(K����R����:��
�=(�%������;�4�XB��,!�Z���K�:��%��Px�K���I~d	�	����h:�,�e?i`	���);�<�k������y���=�f���}����HNr�f&������r�����b�	(�Ny�@��@K�B8QB���V(��	Ya�	��S���}L�9�y��
�����f\�7��
Qw}��bx�z�G�i�t$�R��m�P	�H�-HO���bR��b �L�[�(��@�K�� ��a�M��}��_���~u�����/F�H����D�	�)�����dE
������U�B��*R�|��*e)T��G
�w����)���L�(��Q2 H������3G�6&�*R`���B�R`�W��D�_��-�����>H��t��?��4�	(��?f��d`�v
���7n��O@!�y�6����g��N�����Bx�PH_�6/��������G�l�v$�P(�}�P�@�3@�<��	�l�lT����tO �T��^;_�(���+$�E{o��T���8�3(����{���5?��g�B��@!�[�P��P(�@����PxW;G�Q�(�@�}��P@�g�'���F?@���"x�h���(�����
��w�`��`�GrH�ir0!T<�p)�p�{�Y� ��))`����q�R@���������yL_�7/�P��+~������������1������F�(���STQ����QG�)*�f0���W�G��
<��1l
c���
�v�
������*@���IEh�'#DQZ|��8Ex����?���w��UD=��*��u@Q�:�����*���U�5�*
������k���0���F���'�����p����
����;����+#��4���-���$�g���O����	4��(u��H��=\=�wIO�#�@W���`�6UF��FW��:J)�VVJ=J)p�����@���J�]�P���>>��
@4
�f2���B�	d�H�L_RQ����|S��fQ�������k#@h��o�
���}������X6�<�V7	��K�XHAB�� !�Z�P(71�����@B�	�w�'F����_r�s~&r��oDe
h�S���������u�

L-�4.��P}��T�P��W�)|=<�����`�x@�@W�O��h��&�p"����'4������'f��NEd^Dx��P8����]����5�����X���Q�f	 ���(����B�g	 ����K�L�GR���`3��%������^;��@{����%���F�����������%���p��;�t*K�%~*���u`	Q�:�����'
���V�Px�@R(G�O>
SC��!��f����%��Zf^��������9Zg���P}���P�P�q#�BX�v��L�	����ws�	��D�
���B��B�U�����V����{=��NE�~"k
�	(�h��������M�
kK���������$A
���*��/� �p)�p)�r&=��3H����.)��3=I��/�H��w�'gA
l��7���N�[��i� H�������xG����B�B��*R��VE
����P9W)T�~K���6�dR �L�[�_E���z��r��������J��3������i>V����V��~v��|���_ul�����++���I��	S8�8�X8��1���#T���x�}�6��+p�a�^�,�a��#�p��x�l�v$�H�C%�s�B�NM �G�G�C�HM �G@3gZ;������@{�|$W���������:
/�#��8�����\9����N�
?�Q�:p��o8B�\�P�S*����Or���G����m 5�����'(R�k�3��g�?Wy@
x��D��g����Y��3������i�)H��L�v$i��_�
RX80~2�bA
(��A�P������Z��y�TD�O�)�tE�Bx��s���#�7��m)dW,H������*�����cx:>���TO��������q�f���-E#����G!����@������P�[����=����q|C��}������_U�w���l)$�|�����j�������)������Qa>0�bg
��L�w���Y;0�B�o�����������ige"Q������3��@;/�����v�� �����Y�r�(����OT)���C�A��4�?������T0Ha�DfH;�_�#�5�f������m�" ��#Y����0��@�H���(��N����4w*"��mt# W�F7B��BP�{�'�p��zpB6X�LyF!���B� ��a,���*X(���,�r������K,�uq���<*F�A��v�(X�]5�Vh������0�_�b$�	��sf�*L(<V&D���^v�	h�L(�aSYaB��}�g�l��+L@;�`j�o���.�b����^9������� L(����9�T_96W�0���'qj��?h��S�������	&��'���C�}$	g`
'
5P8���	��~����S��	(���9�0�YYa�	QO0��dm���P�0��agj4@��0�P�z����hL0�A9�-}�	��FM���^��>��7�B^���P
��&�5���=`���`�L(<V&D��
�@����`B�
��]aB��0����	h��x�&�v����..�Y
@{�Q�}����L(�����0�W�s�d��Le�	��fL����t|(~�}������l���$�p$�p$���s����x�?�9,��������sZR^��t$D�������N��	$�y��m�P	�4�-�	$lD�BH��o 4��_�/7�	���4a�	����
BH{���@���u�	��F2����5
DhB������&�~.�W����c���NViB��*M���O�~VhB���~ ��9\�1�lLt��;�OR��7�'*,���)��ukM�|�Y�k_XB���k�d�/N����_���������'Z���������_h���������UTg�-=�^s�O�8�	����).�p?��m�\D�BZ�s~�c)���������x�������n'I��T�J����@��-@�g�H9@��:���G��J���p�;QS��LC�N5T�]5jA.������.�i4&Q����0��
p!�c�u�\�z�.�NF�B�g���J�;��8��~�^MU`;g�X���4���FA��������o����s�B���hQ���r��(^����x��0�d��%QOD#�v9����+n�mO�x$����	����1�,h��������S���s~��)X8���XyBT�t�����&|���X���=T��������(I�(�}JQ���#m+���M)(��oN��lt��l
c��	��	�^Z�	B&�g8=����� �3�{����L�i�T2����C�\2����:��LD=�@&��u Y��d���~{�����k��Q�v?i x�1�J&��}
���u�t{x���E������+8@�bc�����zCq�C)��8�	H�F�@
n7:H�H��	H��	H���������h��% ��_�p�;�����@EE�)P8PQ�]�D�����I�f�
a�$�>I �FH��$���wJ@�(�|���i���i�$(U���y$��Xw��#i���@1�{i�w�B���]�*�~.nk�iV+@�Nv�
�����r��-�
�r�*U(�l���8��~��PL���}e
hg##A���Lc��N�g�������wcP�)��n����������h�~+��(?�>QOD/~��b"
YQ@��M�?��+4{d�@���)�(�p;D���D�
�Q�en�T!D!j�/����?n�KH4��P	�D���	G�3���CQ ��00%
����U����=���� D�w�h� D���N�M!
�B�W����Y��j7�7���EhrD���
���U����J*7��)T��5Q���OH���U���s�L�����
a
|��a
�[�����o�:���|���R�P����R@B�����SrB��@	$��N�B	,�nC0��uo�bB	a�	%��'�����J��
A	��@G��)&����v�,��,�PPBXxB	Ya���~x�Ot6O�H�B%���B��	h�O�O�L�)�x���#OX$xngf%���ZNyh�&Q������	h��3&Ey�o�<��'�~�yB��(O(<������O�z��'n6�
e?C�����R��=�5�7�����=�]����:��'�/����[��	�n��&�Pxn��dJL�~�|�����v�RL4��	aa�	Ya�	(���W(u`�v�����)�&D/��N��g<\�6�����p}�>4vG��d'�>M(�}����!���"B@9D��gxog?�r�	�������6��
4�_�:�	ho�
DiB���L��&�~.�Z
�	Q;����hB��4!�f�P(hB�g�������������%��3��&.�>�Y�}����9�Y�_y�YN���b7����T�Y�D�G��L8�Iz(,h��k�O4��EBP8AP8�8���~����#�"X����;�2N�&dm,4!k
�	�����]��+���n��?�ul������$m�wD�H�C!�S�B�� �/VJQ��I9����q��#[#�����>�J&@{i�"�����R�h�:�J&��K��)�(v��M�d�w�iQ2���+�(��NY�:��B9@&
�������!�����\���m�(�@�j��P6��5�����`*S/�G�����0���������@u�k	Eq���S�Hos�(����|<1F"���������T��LQ��i����X@Ex��s�g��P��_�v��O,����+l���P�,��Y���QAY�2@y���@�������vUW���M����)Q�h�2@�^?�|{)W@{��1t��p�b7�_�����pvT�B��\!�d���W(�l�+��~���vM8�����p��s(������7��.Q������h�
�{��J��`�����*��n�FJP}w����,���������������n�|�PD>U@����*�p���PNP����*dW,T�[?a�s~���B�
��b�*Do�R��F���GC�T�D#T���B%lS�P�PR��Q����V2����P!	����
�$�.:S"'�@�w��O�D����I`{�j'X��y�I��L�����_;�u�J��UIB�Z}�P)�
�o�I)o�O+!	����a`;�}!	|�F}�a�k��r���[���3�z����D1���w�?}W��o��L����3��xPY<����e�p��(� l�	�p�m$���#"��x����6���'� ��	�W<����'x���N���i� �l�C%��B�'h�A�A���R6����������M�hn����S��;jt4P��kK[b^�~�������O��'O��Y�����1�~�	�����Nv�	Q/;����hB��	��m���&~��K ���I��Q��4ob���AX���uk���&��N]���b7��u�	�~�	�a���>.��?�%$���n��T��W*������jA���p�����6��5�"�g`�v�� ������� ��� ���	b@�@{��������h7{$�L�B!�#�B�G �A���F�E��)[�a
P���E�j�+�v,I��NsM�
����[��{�j(V@�{�Bs?+�~�t�Q(V���+D����u�
�`�B9�
��
�o�*Omj��<��Q8�`�b,�o���$�X�B�����,����;X@us���s��v�S�Ba�~6��k�K��2L��N�������E�
��g'��*���Y�|G@��s�4w.�W�pN�*�p`e���+�z�_�����A����������?�����?���������+�W�t>��������:]�����B�V]��+_���*X�~@�`�W��@�J!�{�+X�u;nT���l������8L!:�a���h�
�(Z���o�5�< �������9O���)�F{o�{>���������}��!�+���Y������v����B�[�"p����R���Q�R������r/p�{���po��W���.W�|l���Y��j|59�y��3����w�w�	�����Mu�+�~��Y�^������i�	��p��M�W�N���+N$h���s�"��=
V�P�+YX��X�

HdW<!����o��@�_����-!�p��"�w�V����!���\V�@����
dg������s?�y@x@�G�"��Y�.%�E{�Z������� t#��5 �%+'�CB�[�pBB�@����\T~�yw!������(�[�o�3&�0���gBq������i�p|�]c-�t��"���x@��u�V!�f`����N��
�
��G!�p�����>B@a#;c~������S������B��BBVXBX��M�'!�+�����Q�E$A$�/2�@�����H��1KB%��w�r��+B ���WqA��b<�'����xp
B�}���(B ��5�b
r�����������P�v#/N�� �%k�Q)B�|���P)��r�>B������u��H�)�8��������=���eBu��MA:9#�������������-W��������]������zAh��W������v���&�p�&�p;o`�	�O4���yM`�@S��)�&�p�cDXx�	i����TzT��	��'4!l��&�p�&H������l�������P��E
 �O��(;H����:�Q��u���:R��H�>�������^���&�}U���~u�`���^	��t)/��f�x��������\T��y/��P��������6��x����R������o�x��g��<���Q���M��i�Z�8�y������y���5C�o���-���:�b�)?�>S@���b
�!����]=!L��+�����l�S@�@�CXX�
'�
��2>�7/�="l
a
�S��x`
�W��S��P�l?�U���m�
a
 �a
 �G�)�p�q`
�����4M��^��P�����1�P9�~���@{��!�h�W������l���r��'G^9��;Gh�]9B�[�J���8B��Q�=p���8B���/8�x�#i
x���f�x��W�r<�hH�����"�y��sN��y���ES9B�k����rT��&4��p����xV�	(h������(����P�G�#�p��+!�y���M9
*�6�=�����=�������^�7���}������K8Q�����D#�I8������uJ'@8���n��+�e��/32H�hp�l�:})�M�i�4r�sgT�+��W��v`h����:�	����o`�DV������b������������(��z��Sn6�)
���TNQx�@9E�i�vVN��v��(<m����o~?�i������<�z����R9zZc�����u���-�4B��S�m_8��)P}�����h�������S�p�#����M^q���@�vN��e�{�_�E�M*�"�f%���",|�?}�9��M�T��O*p����YSL8������8D3 ���P���O9�@8�������P~�?����A���b�(��Cj��g�x�+\��b�T��;���������4�������p]���H<$>�_Y97

?
���v~�P(7A�����B����

/�O����G��;E�Y��4��@����
����<�Baoc��3��4��@o���/�P}�$�P�-M���9�P�'
(P�M*(d�(d�%����0��T�{G��OE���(��	�S�8!z�'dM!8!j�/�p~;=��8�D#�$�OV�@��@��HTp	�����HDp���#Nh��@�O��Cp�m#�Bp�E��%8��w�����~uj'����t�	�R6N>���+w���S�	���qB�h}�P)��	�����pB���:���w�&g���kR�����k 8�O�1�Pp��>�T������GqBe�L�G�xj�$��;N��t���}����������(�����p�(X�m�	'�W<��Q�p�����BppB�TN�b�	,����|����]��c8?�[��@6��@����xT�g�C�)�r?�����71<�F=�2<��)�|X~��)����	Q����94D�Z|��Q��.���Yt����s^�)~6�
G`
��mze
�r7�A�B��L�������4^[JP����T�t�*�	�tg�_�~�3P���Fu��3��4�
T=����R��{I-B�'30���J��?Q�s��*�p`r�<�M!T!*�T!z*�*D7O�BX�4*T���>U@�U�
U����*\���S��<��������MP�d*�p��#	�{@
T�CT�A��*�T��{�B���T����U���e)| ���=^������T���bBp?��Q��~e��xQ�P��U(mw&�P�B9��P��@�B����C�(���T�����T�������^:�E���>Y��j���T�����?��K��r�
���q�*���}E�ni��?Q�-nwP�^�DP8�K����B��80;"k
�
a����HP����*D��R���PNPn��U���WD}9�z>�������6���H�v�G]��)��H�G��PZ������?����>�2���S3)X���
<����|��&J(@{���+�@{o�o[�@��kL��J(��8��B�;������Bu��(�k ��P�=�5����������E�_����P�=B(��8(�����8>�������]:�L	z����R����7����-5�[~7��f?�bb�3��|@��|���0
N�S���(�������@�Q�I0
�j|�o^��cZ�2�y	F��]'4a���G�fc��g�H�G��R�p���C��JzxP~Lz�%��P���%��~�)�a1�(R��m��(����0E
h��S�H]�����H���I�P�P��R(m)��	�)D}��
�@�(o�r����3���;#��{��%(P(�b��#�f.�t�g�����i��g�u��
(P(~-��i�P�n����@P��N�<�	����B
t���	�N@�v_?�	(�(���BqBv��
g�����	N@�N��XpBT�'\�GY'�hd%	Gp	��'�p�����:{�	x$"8�Q�'�p�?��Ap��~5�	|X����H{g�=+N��m�\p[|�����	�R��d�	�W�F������U�P9Z'T���,8!��'TN��FYy�v�����tf`���>���|B�uP�_�>
V�P��T(����4
�I�T�Pyo�M@�2�Y80�2-��t���P`ac���0��'������{d�@g�������+��B��M@!+��.�o�se�{$�H�	g�g�G�H8��@����P�����tf�c����G���W���%��@�;'�@������2P�&^U�P���[�R�++�,*U(�l�*�6@
e�3C���$���7o�R����I
|���B���L���L����	�h�fHA��F50�xj�D�k��*�B�����)��FR��$)���iS��B�Bv��P��IB�Bt��P8��+�>}��P�=��P8����I
�L��N���H�����p���
a
 �a
 �a
 ���)S��\�G�o�T���j���)�����2<,F��2��9�A�)�^�_��@�S0�+S������<e
�W�/��[���Q�B�hL���~/�J���)N��KYy�v/��5g
��gz=���)��0:@(S��Lg:�3��q,����:����~d���2Twh�������������P��T�a��LT��)Y8P�P�H�*�p"S��)�+����
������V|�o^��c��BP8A�+~����y���^��?�-��e���m��(T���O�T��vI�t~ ��=���b�~-+��������5AH�^�=P{�)�@m
)���b�~(�����?
���s����y��#�������^��3F�
�����4���6wS�G��m�(�����]T��/����ow[<g�l|^~���5
����N�~��1�(��ch�
����8��(~�������A��F�GqV�%� i�����~J>���@��6��n�=�@�����)�|���9��\q��C��)���>�W,�#{*�|D���n�S�!	���G�����$���L���$��!	$l�V�$����a"	x���!	�m������v!	|W���I���0(���)1F�I`{���w�d�g��������@HB�Y}�P��&+�P)�����<����&$!���$T~�&	���$a 	�����8������p�u�k���w�[�c��37�02��$T?�F�
!	�Y1N�D�&&f�p?���$�p����$��'�@���H��3&����PT��M����� B�DH�G�pQ\��JI�
O$���x��I�F=�p�$�p�(��#�#I8��P)w_���9�~���@���F�������d2�L�e�����tG@{/��+G@u����p?Nq�r���8B�X�Pp���pP~�aT����r�!�p��\w��#��tj=��.|��n�-��?��������8B�����G�q��|��#�o[�)*�h�#��'���/�5��|��5�p���P��+�bdM����'Os�"����!,|���G��X;<|��S�a�f`G
H8@8@�_<�Pv�FJZ�L�k"�	��)p����G,��T;�B�\�~u�h(N@{�p�o�8�s*p�<����r�~O�J���Py��5'�5�
��|y*N���	��8a��	x1��\����he�	xC8��������.�#�P}md!8�#�N�]��'p���TKv*m�"8M��	(�N����8�p�����v`�N@������N�����n�%(N�z��H�nI��&>�p����OT����!��F�|�M�]�����\7@`j;�2&�M���q
�Lo
P!Q.h����M(�����0��0�i�	��� �&D��
��wK���	���8��	&D���F�_n� �o���j%��o(4�-�_�� ����H���~�3�b/
���W���� ����� �!+��[Lof�fbba��!d��!a��P8���!k;�]��_3q�?	�>���>�����LJB��P��#!j����o/�������_�ezx��j��N�$���J&@��5N��7����=��L��&C&@��L���������M�j6Q6�w�HP6���`A�&@����Q6�����*�(v�g��(�����bQ�:�����&
��(��������DP~��h�M�r?�I���D��F�E�xq�+��c���0��mS?��0b��n}"S�~.2S,�8%Q9�����0a
�rd�D�CA��"�b��+��z9�p?q�m�T$0Et�S�p`6&z9f}�b�����N���{p�&K@�D�
'�&P��N,�Y(l�-�X*Gz9�a���_,��6�'�Ph�Qa	�]qr�XBq��^K@����TXBa����yb	������K(�s�t��XB�Ym�P*7-2���iw�U~���k�y����B�~���P��>K8���PhU@����j����^;��������x�[�F���r7����b?���R��>�v��A��~�C!��A!�.��i�/|P��~�D!�~�~���9��A!���p�;�~2�>(l�~���B�
���Az�_� |*&|p�?��� �*����e�@x���5���[���Xq3(W|�NG�����4J��k�]�����(��9�0����L�D�����P����29����v�D]��
e{�d���������6W��F����"��c*��OE(.��AI^��aH�����$�q1� ��]�����k'�D�n���	�P�s�W��R�����~��>�*�S��Eq�����������CaY�c@��)
�+c@�c��ehc�C!�WR��/s�g�B
��MN�N��{��
@6@8Q����<��)�p(O��<��-`}C�\�:@<�F��B�2F��xo�N
��S:���v1�����W�K�U����Nu�B����D����9T�P����@���7s[:D=��.|��������0A��������i(�w���a?�r���5��:<����?>t(6�?�w��?��Q���Q"�ok�fL�W��R9A���d2�p�fe@�v��P���R<~!D��6��5�P���P��]�P���e~��!*<P���>��#�f�!p��jNtV@�ea#[\)(��J�s���A��B�m�{(e�{c|�W����t���wF�8P������e�PuR�2�~�t�U�2^��,��p�v�R9��Px�e(\x�J
�x#��$�2oL�dy��Q������8�<{K[����3D�������i>Z���nv@����I~�����@81��n�Z@��)-dM!h�E�+Z@a�d!�@��o^�c�q~��\H�B��)Z���_�����	_��ch����2�A���E� Q8S���'�"��QdQ7��,@��}J�T�����U!(� j�KuH�7�_�=@
<�F�F����6��@{��f
)P}�<�R�~:��HQ���(kR�v+��g�7�5�
����1�o�6��R!�9��D*^�~���+���9��+�L�8�f���������)�����4l���p�FO�x��O�	R��'H����<�~�)p��N(��1H���o�)�+VH����z�n�R���0Z.���E�I����%�,��B0
���`����H��5
~8.I �H�	GJ,H8BH8B*a�$�r&��Q�{J,�PE�k�������������_ \��wNU�p�j/7��VO����\:�'�*/����������\���>W�<��*O������R�~�D��_��	�">���!|3="I����x�h�����/�M������6�������_d���%_d!-�E���Bx�Y`a�DXX��8������)���'\!{��+�W<q���'��=�W�^����\D3\�#E$)� �H�H�g\��D�;�r�����[:p�R�X���|�
xo��������\�wN#�
h����k��+W(v�hi�\�s��Z(W(�l�+n��W���q���**���$ec�r<���Q��?p�/	��B&c���3`�0���F�����g��L��5�����L���:@J���������
^q�y�;FN���_f1d7OCt�1�p�yC������S��b@�@��7�p�h��k�MT�� �� �� ���������r���$�L��G�o�_�c�_@�P����(g����KA�;g2�r�b/
�����u������5=b���8C�f��P��7T��KQ����T�P�p�y��@]�?q���|1C�xq�?�e�c���(h��h;{��2<�����<P�bcW����I(^�D"
'(�r�	ne@�D"
ZDf��2�p�A�y�T$P����4*�����	��yJ�D)Ct�e���>}v�H��P\oe�L6GZD���@)(��2<(S6�?�de@�m�=������rT�����P��w���7���^9@�2�zj�%����_�2^��'!��P�N��P8�@�D�h�����Pn�����/������(�?p����x,*e�����e�@�_5P�~�S�bR����;h�)n��1J
��1J�R���e��M�K���.&�P����M��e@�D.Ct�J���$�����P����OE�\"�yB�����<�Y_}�-���<��������?������?������������/�~O�(����������c*�-Vq��?
*n�~���7�\���{�o����x��^9����+�CS�C��k0��M7�w[_\Lf�_�'����S_�~�w�����������#�.������yN}}��QX����P�R��
�]
��@���ozY��@s
P6|���z�o�qh��d?��r�����3�/�?������(&9?��N���b��/�I��9�z����6�����yD���vu�L=*���5�7���6@�b�F���������/����������^7�c^����Y����S��x.O��Y����va�����I��/j���gP��P1���d�����+��|S�
'�Lv�g��_8�p��|� .� �� �~����k�#����G�lg#<A�/N>��Wx|�e�<j'�5)�`����� ���;p�J�&xwwV_�	M����X�_�2���zfh(������&*uc$��	V_[�!������sB��mZD�D�{�!���o��	�`K�w�&��'���?�?w��e�P������ ��]����R�����?���1�#(���� �}�������)��R�'�*��,�nu8}��y�?�YJ��y,��Z�"W?/�~�O�"���/X�=�d�	O�",�a�@��t�`�>�8��
'��sn��	H�p��f�f�' ������S:H����c�@���� �?��ih�u?�W �/�D���������@��s��(�@�[�H�������pP���*~���W�@V��SH���iU�@bF�o�Yy^�D�r� Q��n�M����a�@Ko��V ���?�Us%�&�E��_�|��������B)���^g����t=���?��;�s���Z�k��(��Y{�2J!
�~���JT�)0+��b�
|���p�_��1�E*_��t�F��P���[�
�z�[0P8P����.�s����8�m�S�r���vR�����6�8|����[n��1�S�����>�p?����Fq�h���L�h�8
�><hS��}@����B���������J@�O:D��(}(���p���rF9(}@��S����X{�k�@
�����V�}(|o��B����BJ��<�J����o��_���?q�C[���D��b �����$�D|�����w�=��ou�<���?����y�4SH��(
Q Q�#RH�q��7�^.�(�9$P�$�,gTVN����GD�G�p�s���E����v�&���	 aa�(�������YS8�r�l��d�v�K� �������G��O#�p�9T��/Ni���mJ�0�tN�*����
M)�@��L�P��|�;yTp�/���#P}�<�G����_pD�nL�QQX���]qD�y��������.{H#�E�j	?
$��F��}��EH<s��h�cT Q����$��o�&R��M^9�z��b4��De>��Nx���E7���d��:�B�_V�@��g����4�����J3
�>F��$��R��q��1�sV8Q�����n�� l4(���n,�(�@��_�7/Q�����v:_��e�K�x�f���k�"~�}����D��dA$��5/���3}1I���	AQ�������6����9�����p���q�n����ws������k>Vn����B�F���
7X�5T���;���
��K'OD��=��r��5O�|��������������UP���6�n�g������U$������Q({[g��RV�Z�oO|����g���q��b����t�OO��1�C)�`u���>�����p�����|����/�QI�9��F%�2S�E%��&S;�J:P�8�7��_x�����'���~m��`���L*	�b����7x���������eO
endstream
endobj
40
0
obj
51311
endobj
41
0
obj
[
]
endobj
42
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
43
0
R
/Resources
44
0
R
/Annots
46
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
43
0
obj
<<
/Filter
/FlateDecode
/Length
45
0
R
>>
stream
x���K�$���w�B��������O��QM�h@p$B"��H�����ak�-s���\��U��s������������������m�����������:���!���iZ���)���`����a(����4L����V��?�����������?��~����q����:m���4�����~�?~�/������4������O�Pn�	�����`����?��%N�o������5�$pb���C����$�&��1N�>k&I8���=*�����$�&��1N�>k&I8���=*������$�&��1N�>k&I8���=*�7a�O��I0���'u�4k&I8���=*��0�2�$�&G�'u�5�$pb���C��~v���'u�5�$pb���CXW�~v���'u�5�$pb���C��t?	���qR�!X�0I�'v�Q��	�}��O����8��&�Y3I�'v�Q�>�I�Y������C�fa��N����}�,�0�����C�fa��N����}E�YX��pR�!Yd��;��t���&��$���x���1��I�8�s�J�!�����>'u� ��,pb���C�d9����>'u�$��,pb���CXd9����>'u�5�$pb���C(����_�����r ���G��&�7Y$�L�Sd}�	h�L�p���{T�a��@n��8��Yd��;��t�,��,��8���Y�$��;��t�*��,���8���Y�$��;��t�&��,���8��6Yd��;��t��r��@��p<���1��I9����V�(6�������&����(6���G��&��`�0��v��#w��,6���G��&��`�0��v��#w��5�$pb�������������s��}
�8�,pb�����v�39���x�5���I�8�s�Z�M��f�����s��}
�8�,pb�������������s��}
�8�,pb����P��fai����G�>k&I8���=j�
��l`r8����o��M�p���{��o�0�x�pk����G�>�a��$��;��u��i��'a���I��0M��$pb��������$L��8���Y���N����}�"�O��]���O���I8�s�Z�w�~���,���x�"�)q}�f�$	G���G��&E���[w}N�>k&I8���=j�7a���I��pR�)L�t?	���G��&�7�~�����}
�M���N����}��t?	kw}N�>k&I8���=j����.��$���x���g���5�$qb����0�r ����8��FYd��;��u��Y�Y�����S�e9��N����}VYda�����Oa��@8�s�Z�M�d9����>0N�>k&I8���=j����.��$���x6Y�4k&I8���=j�7a��@����qR�)X�0I�'v�Q��	�,�0���I��0�r ���G��&Yda�����O��r ���G���0�d9�39O���A@�f��#N����}Yd��_'u�� ��,pb����0�r C}`��}
�,�p���{��o�"��,L���qR�),���'v�Q��	E�YX�����S(���'v�Q��.�7Y$�L�Sd}`F���$��;��u��A�Y����I��0�r ���G��&L����_'u��5�$pb������r S}`��}
�,�p���{��o�&��,,���qR�)l���'v�Q��.,wY$�L������ �Y3I�'v�Q��	�,�p�����Oa��@8�s�Z�M�e9����>0N�>�Y�Y8���=j�7a��@����8��VYd��;��u��M�YX�����S�d9��N�����]X��H���g���A@�f��#N����}FYd��_'u��(��,pb����0�r c}`��}
�,L�p���{��o�*��,����qR�)����'v�Q��.��,�`&��Ye}`F���$��;��u��A�Y����I��`��$	���G��&L����_'u��$��,pb������r S}`��}
�,�p���{��oB��@����8���,�p���{����M�I0���Y�4k&I8���=j�7a��@n���qR�)X�0I�'v�Q��	�,�0���I��0�r ���G��&,����_'u��5�$pb����Pd9����>0N�>�"��,pb���?��v���$��p<E�fd��M�p���{��o�x��$��]���O���I8�s�Z�M��~�����}
� �O�'v�Q��	�(�O��]���Oa��I8���R�F���n�s���v�o$���-:��p���{T�o��?g�����8��&�Y3I�'v�Q�>�q��$�������}�,L�p���{T�a^��I�v����}�*�O�'v�Q�>��H��0����G���"�O�'v�Q�>�m��'a=���s�J�!l���p���{T�o�0�b��`&��1N��	h�L�p���{T�a��x�0����G���Y�$��;��t�2H��0����G��q�Y8���=*��PF�~�������C(�t?	���G��&�7Y$�L�Sd}�	h�L�p���{T�a��@n��8��Yd��;��t�$��,��8���Y�$��;��t�"��,L��8��Yd��;��tB��@�����}E�Y8���=*�7a��r 	fr8�"�pL@�f��#N����}R.�"��'���A�%V�~����Q�>)�X���I�� �+B�~�n��t��K�������C�r��_?q7zT�A�%V�~�DrR�!H����8���y)?R��q�������:�����Yz�G���{�~~e��; ����������d/>�c�1m�����6����|�q��e������ ���km��0I��P��?����g91G���$!�qW|)�8?������~VbrhF�I�j�����a���L�f��_<�~����\��E '��!D���3�������~s`��{|�(p��Bd?o�(����G����W�/7�/q�4IB�\�a�9c���e~������[|O(4o
!���9�O�v�o�����v�4	y��8M������/��o���<��(���,�������yr��C|>iOt��l�9�R���?���D�<e�*O#�$	��z>���?��<f�]3 -[C���s��8��^��]y��~���&IhN�|��1�c������[��$	���Lg�%��|����
$3IBD�Q�O�4	��2��(a��8��K�G&�#j����$���5vL�80�-j�9H7�$�k�[���x�,�W�kC���l8��M��7D�+��!D�[��n������ag�$	ne���i�6D�4	z��M��?�������(���,��� ���h�����w26���"{�������{�	{�O9M��5u��I_ch�'CC�L� ���������y^�<�a�y���o��s5���'lgv���0I�|�h�*����~v8�mhL�L����kT�Y`�A�E��$���jv��K�4k&Ixqlt5��3��3w���$!�L��u����r/!0��6y�������y��;�NI�b�$!��<��,���z�	z���I"������t��*
����e���'����	��i��n�$!��F~���y+�1�\!�E@��d���k���^�"�27�H��r
��o�)�4�*OL���������^I�3�$!>��(	����U���&IhMi�|������t��,���pa�)���^���L�?�����$�13n�����\!L����s|;��{�IXf����>��`�5�_f�QJf��8`>N�~�L�g?��r�!�\��!Dt/F@��D;����<�0IBD�3�Oc�=a�1�$!���
:cO������$	�]��SN�9sN��"�il����sX5��z�4�$A���M�
��l�$!������*�YF	�$�8�p���s�F�)��.3I�xP�����C�M�.���$	��n��,�0��L�Pa����Pp������L�M������w��o� ������M� h^�y���)����������[�����s��O/�-�<�f��������Yn�Y��`����@�#��)v��AP�V��[�?8�<���I�S|�a�!w�.}���"��j��G]���������u������*�	��I^���8���tr���3f&IP���[[��3��
y�1�I�����#��I���'�;�&Ip�e��w�w����30,3IB�����C��3t]d�0IBDw�&��v2]!�&���$	�����@`�ts�#��R��S3I�������������cJ����e�$���AlH���I"�3{��y�	y���I"y���"� ���h�E��!�[Ch���}�_��${��=��&I��o0n�B�g���,B����������g�.���
���m�^�9�`$�$A����"�#va���$	r��?�������*�Y�	�$�DG��@W���.�Y�0I�;z��JEq?����h:B����$AN}:�����B-2>�$!�U�hd�@��&�I"����4]����W9��l3IB$�c��X��`<�zm�rN���+�NM�l�$A.w%�Z�����&�%��&I�d�������S5o
!�_��$y��<���&I��r����"�il����i�{Mwd�U�5L� �������4w��@Z����������8�=�(a����������?�'��v���I�����9tF�A1��I���I����,2�$�1_)���h�"l�&!�I�nh�S�0\Q����$!�]NH}-@_�-�
�P0IBds�S��t4{&�"���!�I"���q_������!�$	���+�hv6]�F����!Dvw-OWc�i��o�$���O�t6�.���"�il��a���y��	�9*B*sC�q�(���Wy� &I�������t�����$4_/����~��U��&Ih��|�bunn������]��u�������A���d�F�����$!����~.����&Ip��,��@�����c��d&I�����30�c����$!�_M���1~�OL�������{�����I�n�$��[����{�	{���I"���2�G��Hl�A�[C��owaO������$	�������,��� �n.N�'�.�"�27���}���Mh�U4F�I�fw��t�;�.�5y�`�����j�I��U��&I�����I;p�[��0�����$	�7y��
�s���.���$�C��}��ev���I^0���g�n�n�p'�J�gd�F#�@f����-��v4]��g��f��6�������������L�P����e��3�r��$����/��v&}!�l� ��.T�����qF�&�N�y�I���8��]A�EH�X]7��>�<U����!��.D��?���eHf�u/�N'����l�6+j����n�s5{�	:#l�va����$	���x/�gG�%�����$	��os��A�E��$��-�U�������H�2M2�$D�q@��#�#��$	�J�4���vi��]�$�rw�?�3��B�#���$�k��1#v����M�K1M���O����tI�"
B��� �����9�&O���I��p�4
�,�.����!D67m�Ja'���tK�!!��!Dt��Czc���A0L���/�y�l�6���!���C���"y^�<� a���),�0��O��
Gl�va�?Z�I�-0k?��gh�L� �[�g@2� �"C�I�Z�AM���� 3IB$��g�J�
����6�P0IBdwsE���
�gl��I�t���v2}��=�<�0I�������<�WA/7A/q�4I�WMwfdx@#Ch�B �SowAO������$	�bHd�!#ChB$����^�VC0L� ����Q�'dd-[C������)`���g$L�������]�sG��B���$	�)�(}��QL�L������s?.���&I��nYJ��M���$$3IBD���B0���M0L� w��@�hv]�m�f��0IB`�������vE��$	~���s5;�.{��H�$	��/�x�z�=�G�&I4&�:y�\!�E@��"�����h:#�K����"�u��z��p�$A��9�t5;���y�`���C�/8=���U���&I8t�|<�����
�*Oa���q�I�$���������a��M��������oc�2��@�$	~�����tE��L�M� C����16���w(3I��������tP�W��N�I��q�v�	;y��$	�~=��r��
�$T������S�fe����8�
����&aO���I���L������[)B�����~�$���f�2�$|�����l�'�W�v�I��Cw��
y�A�Ijh�!z��W��?a���)��-|5�?�N�2����{�m�	@�I"�Wd����et�Q�$	�a��H��v6]6-���$	�~i?E0���M0L��t�S���pz(�B�r�a���������,�@�$	�i���*��&�%��&Ih����u�f��a�4k�Bp�J?c����g�&Ix�Y��!E�1}6+EXen2qC��1�*���`���>���^f�a�"�&I���/�e�<�B�e�0I��0��f/�@W���.LRD$C��Gg38}��L�L� �nYd���A�E
�$8�k�)P���]�b&I�P�+���	���$	�B��y��A�K��&�$	�]����4#;����<�0I���3���z�	z���I"�q��c�<v+����!|�V;�c�i�n�$�K������,��� ����tzV�c��@enB�����z����`���������wy� �l
!��S���3��
y�!�$	y�<8.�Ty
�G.RL$�+�r�b����Qf����~L
o'5F�.2J�$��_t�F�?��"��I2�0��LxC�,L���������Ju�`���T�����"��$	�����9;).B�M�$�+�s�s|��?��"$�[C�Qw\��.�i�m�$!���bN9gg���,B�����f�M(uMH*sC��K3�M�$�E��I"���Wd���gA�$	2��`]�^���[�](���%a�B����Od�1�$������� �"C�I��z
x+����$(3I�c�}��1|�qL�fa��8�����0;�>��d��[�$!�_uJ���������`��/���/7�/q�4IB��:�b�4n����f��!�A�Oz�O1�4	|�0M������T�]a�EP������@��`/T�T������y��/z��
&I�����24vC���$	2�WO {^�=�(a����\�����2"O�y���lu�LC��#B���B"D�&I����G�{�"d��$�=�����nRChH�M�Pn�,mR�
�� f�pwSNW'D�6(3I���3T���|��3I��;���U��M�K2L����s��s}R<l���� �j���/p O����h�$	��rr�etY�4�uA�/���Qj�U�� �^�� ����L� ��fq����Qj��luA���J��U���L������4������|
�U�tm3I�nRIO�5wu��������U2�'{�
A�=��g�2��(a��6��Z�j@�Ab�6	�L����.!�]rzA��O���=6�������w4���g��0IB�ng�i`�&�k�G&Ip���A%����&�%��&Ih����8]$�p����!���Fnw�N�P��`�$	��\K��3fY�YALcC����,K�����m+�*sC8�����A,�D���`�$	_}���v8�"�l�`�$	�=\�.���*�Y�	�$|q���YYx&����C��$	C.7q\L��2�&Ip����y+�����$ 3IB$��5�pI�6��|�
!�;�G���L�d�Y�2L����
�p��\�O%�`��H�P��3�C/7A/q�4IB���`���R���yk��w~����D����$	�B������d��!�wi���n���L��z�����;W �=����5���^�Hy�g#L� S�q�>L���nn�&�`vg^�I&~�}���=�1���	��l�
�1c�����.���&I����^��x���!T�t=���Q�!�
'O��� ����a�M1a!�L���qL��/7�/q�4IB��Xzdlf��yk�\_�r��hsO@����
!�_/�OvY�]A�I��_�����@*sC��~�?��<ex������*6.���9H���z�~)��{^�=�(a����r����V���cL���f��5�K8���`:)�P���������t��v6v7������$	��J� .�8&���!p�bv��mSf��0IB���u��0{Q� l���I"��r �
���T�$A�Zn��$�)>>4IB �^�����,����������i:�����d�/V�%z�	z��7M�������M7���<f0I�o6'yc���g&L� s�q�57����~a���)I��$�L^�a���t�r��v�$x�a@�M�F-�P���L��C���~��V���@;��v�$���.	x ���5�$� �q�tv8����f��f����n��<���l�GXm&I��i�L��ez��0IB$���������Z�o1L� l�W�����W��&���A�6�\pN�X+Z�� �^g_C���g��$A�;�����N����}��S�6�I6�$��W�e�����VxlN��Z6�g4�
!�_�'��.2J�$!���4s��
8�|o��1!$c�6�	<�yl/�}��e��r�
�j�����_��$��lr�!���ik2��/E���m�
���"���F���*w��`���^����?�?:�rw���x
~F�A�f�����`2{�~X>�?��'Cs��b$�Iz������'y�D?��b)�� �"��I"����e��K�;�0����� �L���~�@����8����C��$���b��i���^��d����9w`�'�L� p�9��7k�d���c�M�W��{�\m�$!�����r��c�)W&I�d�&<��5���)_7?�J�N3I���4�����-�|���f��$	B��XE��5�{9��f��&I�dW�_��H�{=�g�!���{Ch��Y����3�&����!Dv����>t����g��
!��V����^RCor�!��ik�9T���@���n�$	��M*v��W���$�7���RY%��I�S�S
N(4�$������Oo���^���)��"��d&I�h�f�km�r�\d�0IB$����$�h��I*�x@��!Dt�c'���*�&����!8v
Ra*�/Ro�LA���sC�c���������Z8q��<���k�[��^_n-L�����S��W���$��t�b{�V��+�|��������$	f����{��T�Cs��o�H�M� h����9���Lf�� �"�4�$�['���|��	D�&I�l{�%J�)@��#n���$A��YhsR�o�n�l�@�n�%�g8%y��k@f�!�f���r�����k&I��I�C	9)y�[m@f��H^y��P/�&���v_�4��4����$	w�.���[�[��O#@s�0kO�ZB@����`�2�� a����'Q`JX�,6vo��{�1;���A0I��;aW�k�P@��#����%2g#or�!��ikr�;H�
k|����vo��=~>���O���c��y���Od&I}
o=�h+��B���|�A��$!�g��^���2��0a���~.����I�3!~6_`�
�(3IBd�$/�|�L��_�?����M3�$A�/����NC��I��"�y�����,�&I��,g�*���`��Hv�O�[VB��,��O�O(8Z�L�0�f.�m���������!�T��!��O���WZ��� �"��I"��@��<f��IHf����$���M��6cC���c��c
18l37�5�I�&���������1!s��!���B@w��8%�����`(�$!���6~*�!��O���r��O�$�D��+�4��i�9���iz�$!��!��G/�S ��.2��$	��;�b���]�#$w�]p��I�������#$����@�n��4��"�3��x��A�Gz�$!�;���!�����v�$(�����L)k���I��x��Q�5���r�w�$|���Sow��)8��L�p���96�&�9���[G2�$D�k��8r�\d�0IB$�����]�%7;��[�!���{Cpd�������9b.!0I������`i�7y� ����!��2��`�M�31m
!�{�k��a:!H��!D�kaQG^�fC0L��������G;1-t�d��f��!��"zr%��GLu(3IB`�u�2��(a����=f�bR(�X[��"��fc��i��m+��
��aW�#s
�Y�d&I�����Bz�{
�$|��s����dCj�7����&�9"��:�*w&I�'����N�
�?��2��$a����y�J4'���Hf����Gg�e��"bj�C$L�������9$��:��$!��6~�Gf�G�%&I��#��s�����e&I8.���:6�cor�!�D��5a�����h�1+���{C��Ry��
�@0IB$wV��bV�.����$	K#S��}��!��
������.4{�|�?���Xe:�/2L�$!�]p���g���J6��7�����Y"��:�	,+=6����!����J4���BD��u�Mn7�������#a�6�sDLM%P��!v� ��$bf�C�r�a��8ln;l
���ab)17u��rG���$	f�n��9-���i"&��mQ�I��~o�|�W7��y�2��(�$	���Y�����y���Fbz�C�&Iv��qmV�H�N%�L��W���4�1_�d�M� ��7?@or�M�L����|z�	"��mI��.k��	Wn~�������6�$���R�1]u��bE$a���RGs}��\�b�*�2�$Dr���<��\!"L�����85�LU�!�D��!Dr�Xy�
1m��M`���!��B��3W	��*�sC��}x�'�������k�$!���usC�Z%@��!D��9�nn�Y������I�����99���]��	*H�I��������!��
��+���/��8t]d�0IBD�������b�*�X���_�����pv�i��lJX�Iy�e�7��b�*�X=snmy��w�aJ|��
E4��!�{���[�I���C���
�$D6���,���Y�Un7#�$	����;��gw��*(�g&I�J�]O���g���
�kC��+�f��Z0E��Y�.2H�$!�;g��)"��
$3IB@��qN1���M`y��!D�s���]��]�	�Y"���
�%��������|��sD��u�M�6L����K���N1��p`m������sd���j/1�u���Jmf����������5���44�dCC`���!D�EN�S^�!��.2J�$A��/���./p����$	r�;N�%��*m���
����{il������qsC�����il���Q.9L���q�����5�`(�$!����O��g��ro1�t��=���n�3yq��75��mI�I��2�����2����$	������<R�M i7I���Ow�e�o�ds�$6��?������c�'1���7��f�a/���?�8���IJ%A��.Dr�G�%�S�����Vf���=�{�9��HR%�XXkm��_����R��HR%�E	�$D2����!_I��j�B`��\�s�f�/��"dXWkl�����@�O�w��%��Jr�$	��.ps��C@i�ik��	�G�����U.8��B@�p�2�R�o|
��F�+3I�84��dG��d����H��$!�}E�g�,^p����Ht�1�$	]-�����[,��$�I^�����C�5������������F�|Xx�
�Y�I2�$Dt��{K%���Mn6L�������3�$7��B ���n
�s����*�kk�
���7X�$��)���$	s+�Z���d6������ �j>P�l$��.2F�$!����� ��C`i�{C��ynn��F�M`e��!D2~����>K���$7�
�������:��$���M�4L��~��e���$�d,�uo�6{���"������R[cC��rlm�p89Hv�S��	*^�IV���epz��F�!����"��N���2��(a�����8AH��Xl������")~$o2h�$A�{���H��X��������]�?�M`��!���o��DA��zm�����5��n�3�����I�*������mQ�I�����r�U�?���L� d���i���@���'�&I����"�<4��0��X��X�]�����9�H�I�I��I9CH����k3I��m&q�B_�����mI��.4G]Gs��?�W��f����o�8AH��S�s
�Q�I�!!�w�� $�l���6������0CH��EF	�$D�l��_Eo
*���#�L��}���Ar��6�%������
��!�}��I"��3��S�$����M�I�\
Rz�&����$���B|�:�M���,���_hT�2�$��,����|;%�l�D�6��N����7_N��#�� a��9���N���$�d&I�d�@E�{%JH4�`��Y�jl�����J��X�jnr��?��+*9v$or�a��@����WTr����*T����0!���y�{
�E��� ��K�/��l�G;�a����JPf����aW��qv�;�!�����Y�S}�Y���^d�0IB�wgRN�d6���7���~6�)Br��6�e����/��4�I�#�L�������"���m�5m
!���Zcm�9�R�F��X���{���X���~�X�^�vC`)��!Dvo��Ia�����&�	��v�$������<bhH�M���^����� �"�4�$����9���FV,&a�&I�q��v������&L,G5�������Cor�M�L��������x�W�e��f��/��%��&��B�u!�_��4�$��)�����$	��b����]�<;���`��@�^o�)�g4�f�7���f��M����fBd�"g�q��k,~$�I"���K�&
���!��_������HcChn�.����4H��S��5��$	C�B�|�'hd����G��$!��G��5�?��&I��bv����>B�$	�������e��WX��&�FBDw&Q����2�G�B$�vx�{����!���;�M�4�I+$j�7aws97Hb!���k�$A�N��+|
~6A�"3I�3��ws�$
�������"~�$���"c�I�|��� �} C`m�{C��kw���XR�&'���{4&��|�%�$�$�K7���d������
!�_<���W��X�hl=��w�����������_i�2�$,!	�w�6^OI��
!��'&~��x=%���"C�I"�
V�����JK�nx��$!���Nl���7�,����)���AR�����DsC����.����7��Ph������#Nz�{��CR�H��
!���89Hj���j�$A���f���z4��{
nB�Qh7I�����TK�%��	D�H�M� h�S�[�rr��>r���L� ��{~Y��a����&���$���Tk'��KD�I�]������ ��@�@�n�A��eU�
��H�&��L� `�xx���>$����^"����� ��D�r��$	���^�����2>?��8��$����r�f,�*'�d��
!���n�	-�@�&I�������C�	2�$8�%z*w�&I^$�V"�������!��D�IZW������&C@9�ik��I��s���E��{C��^EN
��H�*�&I�K�j��y�����'�2�$!���� O�+�����7$}�$3IBDca��,!d��A��.2H�$!���3�>��� )� C`%�{Cp�<������!��3K�
A���a�0g
�Td�f��xU}|C��G����B@��ik�wV]�,Sq�;
����
!���\S9	H�$���W�$!�_�����I>?o����$a
�T��P�iv$s��$I��$	��O3_xIL�
�I�{�����@�!������Zn �� �Mn"L���1����@�!d&I�����/���mK
�
!����+�W��0�F��>�����$a)]q:2�	I

�
!���b,(8~�&�Ht�1�$	�Y}�q�s����Kb Qf���v���H#��u�6�u����/G��"��$�I"����f�=��<�`����	�WT�^�r�$	�+�7�Hb�Spo���B�I�$m�y�Q|������&��$A�\M#�����W�2����$	Bv�i���j��xy��$��$	�n��U9D�p{}���u������
7�W��x{�lA�I����=���z�M���$A����p�F��ad��u!���-`{�;m��
Jc]�Q�J��qG�a^�2O�O%�bd&I��4)����\�
��� ��������-"��.2F�$!�_>�l� ��H��$!�_=4��1�H��JcC���d��� d&Ih������M�6�1�����o58CH�#�XA��"���H^�VC`��!|���� ��O�O)(cd&IC��?����?�����9�H�#Qf������K_p�3��?]d�0IBD��{$��B$�$3IBDw���!I�d��2JcCp�=��9�TN�I��$�q��3�H��6C@�ik�����@s��H��{C�h�y����.9;H$���g�$!�_.�d@>?�����$a��j��$h���6������Ar �.2J�$A����8=X$&�&!�IMOy�$���_��$4��?N��YD20�2�$D���
���k��4m
!�_����ID0	��
����3�d`�����I�����J
�S�s
�7�I����"����9AH&�X8jm�o$�R0	.���&I��z
f%0
6'��$�L���F��")�G�
!�_���CR0I2�$D��)�$or�!�v��5�H^1��`�	DR0I��
!�;'�qn�L�W��0IBW��0�S��_>7������$�Lr�%��j&��=$���$	�~��4�� �"�4�$���eb19H&�&���$A���M8&I�\Y9j��K~����@$	���$	��EH'��|�% 3IB$�!%{�nPf��;����|S%�)��5��$	�V2$>�Yc|Q%h,�6����6�)��7���Ix�a�$	^�|]	i���Y�"�2�$Dv�>���|S%;�hXBjlMt'�8�fI�$�L� ����H�7��P�i�B�v7���m�$�I�vo����8KHn$���l�$!�;��8EHf�S��
�8�I��RV
���cs��H��$	���7��A�E��$D������C#I2�$D������	D$W���c�#�3��Kb&I�#������'���:$_(�$�v��hN�/I�vo��Y�$�r�!�n���m�Fo8%H��S���6�I�f�9w,�{�9'H�$�X1jm����3O0��`�2��0a���~��$��7$o� 3IB s7]/��9���5����I��#&IHf�AwJ�q^��Q�7��0IB��t��8@N	�/
*���7p�'�%{���$�k����*	�O��'����I�$���������d����$���Wj�� �D��$���A�?��� ����@�n��8�~ICN�,J�.�����S���0��S�$����$!�{�8/y��l@f�%�������!i�$m�� h&j:23�85H�*���i3I��{g�`"�$O�)����l2Q�Lvt��"��c:18�V�Z���{�0]A&��;S��1�lXL��IE����6�lc��fq��.|�~��|��������.����nr��vo��r��v�����wl{�����u����k��v_<����<����RUf��!T��:�7U�GA��"YkC���7M�r]A#L����!�TI�d�BdwO���*��D��:Yf���~��%��E$y�$3I���sL�$��S����$�p�sdN �9J�vo_3'�%y�
�$��Gc�I2G���OP'�L�0�37y��������d��
�5�����y�����1AH�(�E�	�$D���4Jg���C�F	1�$j��!��%���BD�k9rr��Q�!�F��"�~>�;xr���C�GA�Id�����3�����Bd��HwP���� $y��Un7L��!AA�J%������H�hA�,3I��H�l���ArG���*]kC��W���.���&I4�Q0���W��9
2���7���'>��_n��$"�����������9CH�(�X�kn���7�)BR8����Y����e>$���wD�r�!�^����W�����������h�n�3��G�"+|K%�d�M� d��C:�#��@�A�E�h&Ih������7YR8��M� �Ws2���,)��f�u!��U�����|�%����$	����>���5�-�$N�7��f�ew����74�I�$i�����m}8?H'���k3IB$��	�i�������Vf���O4����)B�8����YkC���a	���� �"c�I"���!y�`C`��{C��[��	�� $��dX;klr�k�iz4&I�Kh�
�t��T�7��P�j���5'� �j�B{�Gg�������ZcC���E�n�s"8AH��S�s
�[�I�c����)B2H���ZkC��'�B.2J�$!��w�3�d�
$3IBDw�R��<J�	,�56!�~��!��`C�L��E6�I%{��
�$������$"��$m�������}8EH�(���m�$!����;dh�$�)�Y���$	��ssE�]b�������
�e�����(�C���/�� �"��I����!�@C`��{C��WO"��$�n,366A�"��!$�h,367����H���Dor�!����5��~9X
6��"%j�7v'F�B�H�^�f�$	��Hs���H�S��	J��I�F����@s��$R��$	���['�yD�A�E	�$��{���$�h�rvo�\��lL�G�����"���V����A�H���"gsC�hW��V��3��������I�2gI&���B`�kgpj�dR�W��0IB��/$�c��l���i�c��G����C+1Z�9��lRGz�$!�_�&%��.2��$	/���U,��EbJ�#=M�������"$����@�n�A�1�+���#$��]p��I�������m�#1����$	:n[}�u�m��bhN#1����{U�aW�x��!I�$�r�w�$(��o����p�����gT3�$�B����Y�1y���
!��R��.����&I���17��
��IHf�AwB8����hX�ll����ns��1{���
�=����Cor�!����5�W��>�%���!����!t/���U�5V:B$w�o�1�u���bcf���D+��Bb��I�/y����et�1�$	���bh��1����$	�[=������<R�!����"��<RG��zC@��ik��bt�h�J1����{Ch�����t�=�����_-��2�$�!�������9���z_kC�l|e����YH|Sb2�C%L������JL�$K~�Bd�����x�cJ'I0IBD�#f�I����N�!�����Z��h�M1��$�$!����S�G/�\k�k��r���$am$^5
S�M���dC`���!�W�oJLlt�"��I"�_���J�/$�_����S��}G��S�Xjm�=�v�z����F������|�jw���U��M�K5M��������[|�(�4o
!���~4}�4	�c�$	��Z����1��An7��$	��;�����a��
�@0I����qX�n�w��@Z����>��f��*�YF	�$v��Yz��B����Q�l7I���Re_��7^�1��l��M����5�b�c��$A��O��b-�&��$!�g����}*)��_Sh	2�$�o�Y_|*�M�4]���f��f��H��(��_�����w�j4!���$A��
����<������8l�$A���b9O���.F��'!�[]t
� >zSt@�E�%>f0IB��e���
������&�T����
��`g�_�6E�&I�l���?�30��
z���L���~���N����?P��L�p�Y��n�b�4�XPomMv��2���/��EF	�$D�q�c���,M0��7����C�[�li�`�����R�,ey�;
�������,;�����>�!
,�67����~r_����a�$	� e�zO=�l���
�ykMv%����I�S|�i������Vd��!C�E�e�46���k��m{,�!�T�����;&�Wy� 	&I����\������F3�$!��C��s��y^�<� a���Lzx>�G;�s�]�N5�$	�OYg��|_��il���5�C�I"�mn�b�,z��9�C%L��F�f������dC`��{Cp�=��&����8�	,96�8�~���h�H�Q�r�a�������$;�M�<�0I���pr����M�K4M������og�A���6j�B�?��ug�x;h�i�o�$A.9������evY5�
!���#pp'�E��j(*sCh_��qh�|�G
��`��/
�p'�Q�fnV��5�H�W��_�~4�9���P.�L�0/����pC���!�R��"���N7�9q�"��I"���;�P���h�Tzo2�z\:g`�
o?:!
&I���q�tF���,����
!������?�����U���$	M�[��6}`/7a/q�4IBd���36=6V����!|��;d�i�t�$���sH;���"�il~�Xr>����n�Id����Q?��GM�a��YI����q�p��I���cP(�L���o�����kQCC�k�:���]B��x-lv�]d�0I�c>����a��*&i�L���K��04\��M`9��!�w�$���Ma�Yn-L�����8��G��b[!4L�������������a�$	���	��G�?`W1i�BDZ��~#O������$	��b��}���
^��EX�����s�blz&�*������n;�c�U4F�I�8lz������!�l
�k�F��y�,��I"����?���'\�M�`&�� �xZ�;�./~<G�	��&Ip�b	}^�|����L����y���sD�@�n�A?]���.=cOT	�lxJ�~n`���.�y��R�<��4�Ji��Y���$!R���ap�%�����L� �s3H^nB^��a�%���4}$�1����.���q�z�=��&IPt�L�J^�evY5�uA���������l#���6�$�/yM/��������f����-����<�B���6�$���a^���?u�jP��L�p��z�_�C���24_BDw?�6/t]d�0I�C��L���
eT,&~oq����t? ���B$�����������
�E�����S���d��;vS�l�$	�����������Q�$	��+�O'dl�)cCj���k��W��DO������$	�����&rY�\McC�����tA�����*sC��x�W=�������P0I�����?C�AH���x����Wa�2J�$!^r����H�WN��S����$	S�@�^0��K�'� �
����� �Nq|z>���"��IZ��!���
2<$6R���$	���	�p��4�&�b��"�����6����f��0I���?��>��ObG%:L���_Y�������a�$	_�s�;�n[�AX��"�� q�y��<���&I2x�����F.���"�il��)�k��.���I�vj(B*sC����l����C�80I�<d���s�;�.;9y�`��/=ctF�W!�2H�$!��������O��'���a&IX����;Nc�O���F�6��$�����Z� L�G������}����$(3I��#��3*|�QM�cC�#�z����Jv���3��q�;�$D������"�p�\�$	��]���{�	{���I"���@�������4o
A����]��$�)>�4I�\���	����"��hB 7rV+LC�3bW�T�� W����8�cF�h�U3�$A^����~oG�3b'�L���E����U���&I�;Z~��������=����&I0�W��{;����R�@�n�a�Z,��2��(�$	�>�;���������$A����?C�CzF��2�AwS#���t��}��f�I�f����l�&�����L����Z�����g�	g�c�I^y�\�:�M���� �y�zyk�XB���.�i�i�$��>��!�,�.����.�3��8�����m+�*s]���ZA�Wy�L�L�����9��M��m�<jf����9���y�,�4�$Dv7	����X=#�m���{�$	7�5�����y&xG	2����L��AkC���-t{�.���&I����$��(@�3b7	�L������
�hlxp��"���P�m�8���IubJY5��9<�Ir�O7�`37������WA/7A/q�4IBDw�O��(��1
@�[Cv7�d�������KN�$�[�d�kNa�U�9L���q�XY�{�R(�l
!���$:C���g%L��@��c`']�Dy
�{��&3I�>+��Ag Q��������� ��TD!��0a�a����HM�!���{C������@���m��Bd����#HQ�!����!t�z��&��C�'�
!���/��^n�^��i���_x�����!5o
A��\��]��$�)>�4I�w;E!�,B.����!|�fceh:J)�BR��o6��TE!{�
&I������(`Cj���M?(uQ��e�0IB���g�m@�?���Ey
�q�D23I���� ��Rl<
mm��~H<<���� �"��Id��O!S-1��&�&
Af��Hv���"f��R�`x��"��~���`�����(#$[��+��U����H)�2�`��!����
{�	{���I"���:��9I��B��5�x�{�(�JY�����$	]���%�L���"��gB�j����D@en�!���y��� 
@0I���~5�E2:Hl��!�I�����I9�g&L���k�@����Tcy
�g��=3I�������I�'�X������� ���~tR���"��I���o����x���!Dv�[�J1�M�IcC�����tR�`<kom�z������J,#���B���2J�r��M�$Dr}�������@��� ��5��~R���)>�4IB$�~����M��vnJ*�4�
!�{����tSR� �$�?�Z*
�tR�I���I�7�=b�@R���Y��$4�o����ZY��N�`+�&����$�L\a�tk���I�d�] b7I�g�&�|��er���I�\����j��k�&j�n��W�]��L����H�uA����s<;����n��g3IB$W�s�z�'��%����6�$�_���
{�	{���I"��J��:;�~	��A8�V�����[�1��U�=M����
�$�U�Y�������"��i�BD�O�������B!��.(�s(��z�^�13(3I������3p�����O�����luA�/��t��oz�M��<��pd��$����
��3r���BR�h<�tm��9d�A�EF	�$��tS����)�z?D��.����If���.q����[��MI@`��x�{��sCR�l<�tm��O��l�����`�x`���#�#��	s^H����A�$	��H����@�������'3:")�B�o�$!����u~H���\McC�dK;��U>��-~�6]�QEPen���<���y0�Z)�I�*OC�$	��|�W?s�K���vu�Ck�����{?v�����WA�2L�$!�����*1x���)=����.�4`3I�>�?�D��>��x��"�7h�;�� �"c�I"��75x;�A!�7�n$�W>�#��$�&���!Dx�S9�<#�KO^B 3O��(����'l���I"{/{W���/x=�����8n�$!�_��7i`��[C���!����4	z��8M�����tz��E�e�46�y�4���!�T�� ���/W������$D4���E���*�YP0IB�T��B�i������'��QaK�8j�L�0�>i�f���hz*����S�����N�7��^�&L���7>�7���W�ZM�2�$�G�WJ�����V�6�|�I"����`�_��n��$��Y��v�
{+y�a������EWd��&�%�&I���e�V��	6�vV����!D6����%��$�)>�4IBd��^��EX��|I���Ffhl�
�27����w�]�M�����Fn7L� ���6����U��<�0IB�U�1=6���>���������fp���$a
��������x<�h�+�d�������/Gt]d�0IB@��jM*��l�*lo&A�I��{_�����&����!t�lTz��M_e{�Y�6L��������Iv�
�y�a��H�U��UJ�������8f�$!^������tT���������n?~��4	z��7M������sAF.���"�il��|��W�>D@Y�����}��!�h��!Dvo��M��<ep���6�������c��������T�S�$����#�����*�Y��$8��?�?�~�w������n��O��?�~��������|�������<��R�{�����g������}�x�����������n�>�����w���6���������?�<�w��w���}�;���}��������gG����~t�n�����m����]���>�(�2����r�w!������g>�����������o��������?��������?,���&����B`��V�����������������������5�����*C��o����l�c:8j���
��Q�}4����?|����4.�?����_�������o����r���g��K��b�~��a��������m�cz��2\��w�>����h�����<���w:h��?}�l������u�a�|�������������'��s������o���33/�q��~^��wu�O��������������2��L���c�y�����u��,�\�Y�r;j�9������?�m��?N�=���~�����v��u8�m������0�s������u��O9l�9~;��x���?>/���a<�m�}\�?�_��x�����?O���u���O1��N����.��}+�����?�w�^>�3��j���g���M���>�y���
��J��P:���M�pG}��l�[9~2~?���F�������m=z.�<})���������<������O��\}t��8�Z��xt��8�>��K��l���6|�9f�a�s����F�����0C���N�
|��vN�B������o3T���s�w���0C�R?�8
a�J�}.��]�fh\��f�^��>�����3T��o����m�3T[�������3T[���f��*����s��f�����������va�����dh�������3T������������r�	�a������l���k�������W������������a��l��Rc���~`N���O�o���co����>�~�0C�����f�����|"}�����8�����6����������I�-=����y����
�����nw|���M�PC�J��.����}�����7����5T�S��!�Pm��7��
��.�Pm�tp���
�#���K����<�n��e�m�.�*��_;�xC����po�4���|	o�_����o�^�7�5T/��1o�^��oh\��w3�*��Hk�v~���
����J$�������,����xC����?�����xC��_�$|�xC��oWR2|������
���
i
���l�]��1��|N|����m�74g�����74g���;o�^���o�^�K?Q�xCu�}��!������h�74�����o����2g#������}���j���~2�������;�`ZC�U:�vi
������|oh4}v���
��O��xC��w��7�tn��7��ao�6|z���
�������
�����Pi�B��7T{|��x��.�7�t����
����x���Rq[��
�f���Pi����*
�u>���
����[C������|}��z��'R�xC�j�u!w���������
�+��7��3��{����!������n\i�����-�QT[��R4��������7T[�
�!���k����
�������
����E������������5�����~S��:�~?�����������6!�P�m�]xsB�������!��xZ�GwC���p���W�7T[������6>�Pm�����xC��g����(����T[��?������l��g�s#�~����~��Vv�����lp>��_U4�������80q��j�O��B��O���BU�y>��=v��j��?~`�������vt�.4�B���z�6��T�j�g_�K�2�~4���6�������&>��5}.��B�F���5������S����R(jm�z%��B�K}�C��_�+m3�Q���]X���F�����C����+?���F��g���\d�[��J-����L�8�v!�Z�V���'���2�!��\{=�����i�f��W��4�o�{>��_���?�.�Q��j��F�j_����Fk���q!��l���:<>������o��4ZO���/�h���^:�f�+I_>�����$���������d���_	5 ��j�t:�(ZM�!���M3��j�t����{d*����o�#S[�=.������7��������z�o���5|%����{����.G7���`p��g�X2��!�9��4��O8j
����*
�������������}��?T/���?2��C�j��2e�z�~�C����^���'������M!�Pm��+|�������iO'���C��_�����j�����1+h���Bz��;��-���������������7D ���"�k}��9��^�	�>Q�o��p���~�U�~f1���^�"���D5C����z��H�@4|�yO"���h"���$&�D��+��G�W�|�%#�
_��c�f;���4�T�p���:��
�MO~����n�t4�)��.��������:T~�����P=����z��������on����a.ux��c�a��f/G*��'�Pi�=Y����!G��w}�Q��>��Q���>��P�:T��_�vQ���>_;D*���'�>�P���}��7d=T[��������u��������:T[�v����C����|^�������������Y����������+�1>�P}�/��1���>�K�9T�����}��z���1b�+�����������94����Y��C��������!G��/:b
?t����94Z�r�������f=4�>_�Y���g=0���[���
��lD����h�6��2����P6���{K�����j���S���on����|��r|�Ns\���7����q(leqv9�Pi�-�o�>����J�o�q�_��D*m?��o�q�^���Q��WJR�hC�z�q����6T���W~�����{��J�}m������!�Pi��~�������U�����+o��6T[��A�
�������lC��1��!�P}��<����
�+���Lm�^����Y����`B��z��0�hCu���B0D���y�X���)�z��������?o���������~��xh����<T[��R��[��]����'�������C���Gq2��h��G"������o"�����.��X�^>T~C��Z�b.�Pm�
gd�>������pFF��w|[�����{v��j�g��!��
5�u9�Pm���J��}/���WZ���������E�R������p,����������#���R��G *��zi�"�;����e!Qm��+�|�������[�<T[�v���@4Z��u��@T[�����#�	�
���l��E *-�)�x�O�G��^���Y��6�>Q���N�)!�������l��R
��3��y!^�O��:�!�P_�}^��s����������J��C��7��Z���e��,�o���*U�>��s�
�.��r�
�#�Pm����{=���k��
���R�����8�|�T�'�����'g�G7�JE9�yo�SYo�lc��*��v���?�i|���������h��Gc��>�5{��e���DFj
��#�Z���i��"�����e������S�������
\ZF�
�r�g��������������\@��~���z��/����H��*r�z��_I�p�z�\�2. Ro����> ��g��-iM�g�=��C�� i='��f@�>��/��"�������L{a�x_��W�6�pH�^��������1���������G}�^r��'~>Bs��V��griy�+��"�z ����j�
'���>`��{��Hk�u����/�\��>�����������)�����OA���7�G�
�N�ax���jN�>��1<���n��T\7T=���7T>�s���J������\z���pC����0��0�������}������)!�Pi���@�����t"�8T[W��z�����:����!��W����q!�7o��o|�����
+>���i���lM��30Zs����O�[��/�Ep�����PC��:���?!�P�k�ph����c
�j��^������/UB���'�g���C���W����C���V0�_8��5.k��������|��O>Z��jM��|���5T����jh\�e-o���������3��Qo�|����������q>0����/����O�(G7�B�.�Pm�t�	>nbj�r����{r*
���D����Yk����� C��_�����{���4jm��A�J�\)?���{����>�Pm���Bk!�Pm��+��� C��K%8|����?7���y%�������:�A��L{���{��dh��'�dh<��.�P�k�����x�S�����/\�d����'���k/|���9�Xo<�����B����������v�]��L�i����x|����.�H��
��/<�.���l��T�V�o8����f��:����`������W�>�����^qxk�}���=v����E&Z�����6�"�K���C���.qxk�}��y]j���a�J�o9O���{��������K|�T�v���\
��S��=�Tab;j��+'2��C��?/$���C�^�|���v��~%�5����v��v�O$WB&>��x�.�|�������_�.Qo��g���Cc�}C��1��|V|��1���Ay?�W�u�F}��pJ�;4���'x���~%���*m�q��vh���tpa����~~W��:�+�;��C��oo*3�~��
���4�ww��
�9Tg��'_0��|�/�����
e&�
�����C�b�#�������:��:��C��7��xs�.�Pu�c:T>qA��������%3���{O����">.w^�\�lYo�A�J���D��C����Yk��[�t������~t������>�Pi����;}����W�}��z/���	A�j��������v��:T[����>��x�.l�}�����W*g��C��+��C��1�^/i���6s�����p^�����A��\{��!t����}��:����Cu�}S��1����4|lh��Rm\���������J���7����j��Z�'P|h�~�7�|h���_Y����3����F���yh4}z3��:4�>�u�����5. ���]������!���ox�=����4}��~�h��� ���@��R��{{�omx^?�r�����?���E�������������F��	G�2�>��a����3�q$[�l,{����78:�}�u5��B-(�^��o�;i��
5T���E.��dbru �:�!��?�.#jk�^��O� ���_[����P��hk{��[��r�d������J�m�h�u��L_:kQl
��-�hk�.�9�F��`��= �Ft�����+�D���(L���������-d�5������������^��5��6���:�Yk��x�Y�������h�y|���"������]��=2������I���T������q��y�� �����)��/��;]����U��<
�h�
z�F�����3��%�gN��U,c�j��O=V��������������G�������O����P���`p�����������	���]8_�]�	�����4�Fr|�O�sj��?�Cm4P��`���^~P�O�\��/ �'��;��O }�<��H_U�H�V����>�>��O �7��"8i������'p��GC�����;��H�`�����;��?����OP��|V�Ogm�n����5�k�������Yk�9�;k��;�?1q�g[[l'���}}D��"�����Ip�@�3�"�B���n�����n�i�G����.H��}bI��$�_Q��c|E�_fc��P�LO^�!��NW�x�_2����6���j2��d�a�'����� g�0��8��������m���8�d����1p.gN�<5�>72l�!X��U��H_;5U�d@����jL�?�
� ���x�!8i����Q�5F�d���T�M�+w�![�BL���M�o5p�����G;9��x���Y;�������1v�d��U���In����Y�t
y��0��(0����#���49�_#�G�*F�!x���1���f�i�p�����$���9��u$"���W�m�H+�#��
��i7@l�Z���C�u$>�^,�������&���|ns�5���o��k�q6B��k���.�OM�c2s���m��)��nC���R����t'a�qx�;�=�m���OD��w��I~�����{�����������-�����q��� �"8m���i�
��!<mR.��6�q�|n'�q��6�M�nCp����4n�{���
�h�zxw�����q��D>0�q&�Y?`���7N�qB���
�G�������g���T���`��&�X��|�k(��(~f���F����Q��������7 8��"~C1�2��
��
�N��
��$�]���\�@��fDv������l|����C��?Q���dv��N>��
D��n��<_D�����'�7D+�q3F
�t�M��
L�8>��
D��$��^�7Dg�_�2:l����i�Ms�^'F����69"�7�Xw�o0�x���z����KJ<Dgm����
L�9],voN����zxw��
)�~C�������|���
�{����xA�e*#t>�����1���]�:���o��0=������4�����/�����{�~���$�SM�05y%}2\����:������L�yx/o�z�P%��B��k2�1�V�5�7��$'7>����>��E-9�^�7�+'�^]���qO��H��2��b }�LT#X��m��H�:d������Uu1���|�����B�Q���������.��|
{�b�Hw���.�����v�Yi�b�YkD{����F�Fu1��6���q1��p������^0��������ADgm�s{�bL��}DG#X��:R����#�)�o~JA�x��;pl����e���x�������S����w���Ne�.�S�����}��5�ex7�y���c�(�G 5�2�����m��%e$�����B-h�oW�an,
g�r[-
j�j[-
���4�WNUC�(p.�jU2�w�\-
�/�J�"����6�7N�C�(��
6bA��;C�7E�I�X�Q[`Qg��"4Z��4x��=jQ�X��Z�G;���Xx���jQgmM���5�%�E�������U�4"���O���H��;"z>R-�`A��C�nD����x&w����"�0����c�3�ep�3X�,��:�Y��%��<�Y�N�Z
N�:fQ�LO^AZG�:m�/��r)m��G��������F���i@v��qp�����G���N�7F�m�4{�\������C���������j�N���H_u��V|�g]�:������t��K�: ����:�_N":y\<	J\\�Fj��8�E�8�y��qp���u��5
��������: �7��u�����u@��I�9N����������'f�gW���;-2x#U$w+=���,'�.�q�����3`	s��q(eu��f�!x)����_��8�gkIp�
W?�8�p�uu�B_��R�m�����np>(��p��<�������U�9�h�
?C<`����n���9�&�g@���`���[�Hn|�`���>�>C���g@��q�4>�{#������g��nB}�����z�M�+e	8�]~D�g�Z�l%��#�>���}���Y;�3�����)p�>C@/J���/u�>ke+���>C�C��^��'NH|�H>C���VV?��3��%�!������l%GA��j�yzet�dpA����4 8��p�������(!Q
V���=�|r���� p^�j��?�N�j60;�rU�!���%��
�^8Y�b6�n6$���
�^9u�%���M��^5�S=A����W&W�L�8���7E���H���s2���b<D��V�gA�Z��n�p,*���R��3>y���X<�N�a��7�= ����U�X�:1>��z�N���
�wF��ZL�;](��N�*�!�FF���oU�||�D�����|�gRE�����c���~��|��i�`L���.r�]b=T������j��z �Qdr���������
X��%���&�/_{�O����_���/_���_���%_,����vw�����In������?������o���������v��@������a��~���%/(�Y2u{>�m�{���%�]Zi��2Z"6V�7F)����#�������}7I�����|���7��/Mz?��>>��d��q���m����;��}�D�|^?�e8�Fu���<�^XQb{m�����F�q���ir>���<k<\'�b�e�]/�����������|t�~{�|���f����^���?���~�3����="���z�xv�/��S�g��_>h����1�g���8�9j����D�5 P�F���*z����x~��.��n0���U}~��K����}u��L������p?�q���|����2�_
7�����Z��wf��F1����'�@����*��
��b��sK����W��f{���n���
�1���q�5bW�����b��STI� ��FZ��A����v_�T28="qi��a��&����"�w�/����1���Q~���<�}1��x/6� �{Ch6� ��F"���}�#��)i�Gj4!���Jm�A����z�@���������#9�t��F#�q��*��</5E��T�U9����m6c�49�fu��H/���!��|h� ��{C��`S9�� ������E��sxm��x&����Wt6eto�/���y~tD0�Opl�Q0"�B0"8��E0"8�#���P4���������S�l�,R���p�*�}�c23
�5R�k#6���@���F*}>x�I�JE���I�V������m�"�u��T�">���T��(��%�����/�����������R���eTe#���Q^����c��.+J����p��ci���gh�Q)"za���J�s'�xT�o7��������/��S'UzT����S�����"��C�j��{m���\�H��(i�j��9�j��N�KU��~���"��o�d1.Q�<���U�H��@��"����fS������D-�>r�[�j1�
�H��SM��+����p�m��hO�����5,LQ��c�F���E��kc��Z��F�Q-�����O����q��T��S��_*`���vCU��Uc�LK��a$tI|"������������fdp6������^�7�������{m<o�	������(Q`��2k��]��a����\������_��>9E���F�����~����������;�%JT���������ml*��SKS*�KM�b��~z����sn�U��A�[�L�8�*Jq��sn���h���y+*J�~���v�xB|YQ�_Qy�����S>�����..�,~bQ��`Q�N/7Q���Q��%�/
��6�_iV>�`S&��d����+ye����[hoEv4�WC��d!�1+���J�'oo%+��+/�M�bxb>nR���#+&��^� �{#4������_����HyW1���b���H`k� ���T�D���xh� b#������"^�����,h����S8�A�8b�A��;��.��&p^��b�\�LZ� P;�:_��7��6>!��NC*��~����y�gF����1�0"��k���r07�@_���
���Q���8����j@|��zi4 �*N��j@�G�U��}T�
����R���W�h@�;1��D��@H7~}������r�T����tD�xe��������S�
C?�$��*��0|>��BT"�+�r\��
@U*"�&���T��U�l��6� �����8��m]#����*�8����E��{=�lF�E�wN^�
E��s"�=7:�7B��^��z�ch����_��aF[���r:J^&��`���v�F:b#z��IC��W�������:1@���<��3�3�1������8���8��8DpEc)X���vW��m�����G��3��zD"�~���/�c�,���2:E�i	�a0��SB�a0��1����Q#c��Q��R�������!�My/�0�SFe�Q{jmtqq�)���(�>�>EE��Q������Hq���8�Y��������0��rO��X]���n�C)`�wN��|�~_N���Z�{y�����D�/Hu�
��z�(P`e� ���j4(���%�����P�2i���|����kqVS�'x���������T
����E�{���x������<M��#"$+y�\��hF�&;�o�\�Fw+=�6��k'���?����]���/"?�%���I����,�v(D`�>�Lg%��O?���N�Im�'��>%���U����@��j:��a�ss:�������g JjK�_
�R6���L��`�%�_� ��-�$�{�o� >y>���x+F�`�"���1���JUR1��i��*��1�F�!����D��WW1���,�b��Om	�~jK�q����-`?��|�c������
_��h�!��h����^:f�
A`���#>�)������ ��C�A�!�o�+4�h@����C0��Ki|rC���S�f6��-�>���p�������G�����t#o4 �������H�7�]^���-��t
=��������r+�vt%���0�qp���6�S����[������C�������y	��|a��v^�*��0�r4~���k�JE��Q�E�"�����"R��s/�T�"��u�-R����,��������*����2$��/���|�
��v�bt��#E6�Q�;��%��W�U�Zd#���12*��1�v%~�'u����O��-z�$AN�+�[tErK�.M�QF/i[?�(	����Qq����.��0�q����gT�j�r�'���8�k#Y��@�LJ �@��-���8���#*�>w��U�^�#����3���+#t��/l��-�fD9�8��u��5���uM��`�������'�$����ny��S4���
e����?aVP#'|��J�yA7*E��p���x=�>�����~���)����}�m����]�����!0��F�{i�YiD-�WFEd��&0_����@�������Eq��`���ZfFlm#k����K5��NQ�F���(9.*kq����njT>�P�tI��4}���R1�t�I��Y�;q����S`a��4b�Nw�F�"�	�� I��G�l����vF)�h����$�3n�����
M�o��x^������]�w��]K������0Huz�6Z�V����^�F�i��7��3C�����hA��C �]�1��C�6Z��!T�n�WF�}�q�S-�O>w�evS��1d ���L���������P-���F�ZO���M-�����-����`S�%_��x�,y���cT��l��-�3�����+�Q%�1_P��O���pW����W��U��z� ���'��7.���s�~����[5�C�^�5x0�y����8���t�?�u�t�[]�T#��:�\D#";���\��zq���u�}���:���)������`.��9�����o������F"}�����|�3���L�fp�����j��������j���j�B�_1��3c��������	��@y�������J@b��xB���^��*y�;�~P	���SxN$ �����	H��Z/*�>/����V��;���3J@�QCt��7��E�5Z����vj�dzoD����J�4�J@�;V�H����% �*�xa�A?% ���u��.0���dp�d% ��
`1�������B�C�4�����H@���ezL�HS	��]�/:�/�\f���|.�rD% ���=�H@�o��*q��$ �
)�G��.�w��E% ��N;J���5z��Dzo��60��5��L_��J@���$�Q�G	�UEQE���m���<5y�
��.`5�8=��._o�����e����1�f�	)��������(�K`;���H���EJE�F�wC����B����o�%���)d����a��t��H��t�F�H�Qi���&�����m� D�������;�s��������������������7�>w������4.��?�~�2��H�+�0Zr��.���^Ud��
��������38�����������!P�2T��0<�F{m�Pl�!��p���@��(�d�G�@��LB��7�hWT��������a��K'�A�!�#�����`\������<<��|q���#lU�N�Y�%���������q
4�����Nj�!�NoB�Py�Wf��*���Q����U��gi��gZs��+���]��9�F�*V\!�(�_���xQ �?���U	+���O�������ezL�"��d��p�V���q����s�4UV�����HF�[��*qV�Q���������K>}����7�����B#����\Q�*���RJ�����Q6b18]�7-zU�z�U5��y%�Uu1x���m��+��'����������'�h���g��07_A% �;��H@b���1��1Y������7B% ���e"����qH����R	�t��J�hV�O.���t	�3jt	�;��\	H���y�������
@����A*�w��������T"yB��O��|���$��H�y
@��ap�dp�L ��?���x���-��pz��vgd�5�#�����^%���=3�������D ��}F��5L_;�U"}��RV���/D�@d�K<@#�G �-GW �WNN�x��5��J@�;���DzUy�h%�O��7�D"8��y�����Q"���5�
�-� �+$`1�8=�Y�����r���NT�{q��f�
�����V����^������H��Db?:��	+D��	+D��g�/�y�tN�?��^��{��K��N<�Hw�����C��B)1���g�8�$2}�t���D�IsGv��D����w����n$&�F�@#1��qb�%a%Z�	+���J�������:l��>�%_��K.�\�Qy�O0��(O�4��'.�}����=<���
Q��wj#��0r�q�����C���Z�<�Qo������W�8�����C�/�O�l:��C�/�kV���!���<�1��C\�3g�U"�)9��C�IN��F"}���Tq���3"�q���}��C|v��VV^�
�YI�����$����@�t���DbWJ@oJ.�lx����,h�����N^�N�~W��l�����Tkt"����{a+��4�7���Q���������`6��}U�8�N��F%}>��T"��U�8�F���Dd;M��~����P��q��)��tZ�����DX������F�|��*o�ap����~�|���~�MU�W�?���r�.h�\�W�W;y��J�XC��O��dn^2�$�]^&��E�)����+#�Z% �wgXy*��\���H@��{hXR��$z?o����p7����������+C^��g�&D�G���	H��g�/y����0�7�7���|U	�����'��4_��)��O	���4e;J�)\�T���
\�T�|���,���L��/��a|56�����M�J@��A�H@`/���{f4&i$ ��FY�F�iTxV	���#_U"}c����q��Ra�1**qT)%�s�sA% ��FY#�j�A�Dzo<{#������V��F$ �������% �W}�\�������5���18o�m����\>N�q|�~�^5������_��������}��������������9~���y��*wb�.����v�Po��w5^���(��04��+����b`o�UB(y��J�wV��F�|�������_������9��b|��sY���5�{x�:l�����5�5�2:���@��hf��\'�b_��"}c�Y<�]�F��Jc���������^P�����>��*�1���#"�������T��.�4��<������<__O��<��!���a�S�|=��/Er9\&��`a���D��s��Q�@_{�:�����~L���CvD����e��~V��S�{?6��Y� N��'*��/-��A`/�Z�"��qj3�V���r���o9�4\X��@���8*��1Z�4r0X���X�D���hV9�SqY�O��E����Q��N��9���xI���^
�,��8/��r����
�$j���K��s'�E,Ab��sd�9n���L�����T���]
������Z��MF�k82�}1�e��7���d9����_� /{CT���j�2�Ab����>2�S����9��"��u�;L��|H��k�Dt#9g��-C�'�s#7��D������E�19r��~B��������b��\P�gmV.k@�i��P_(�)��E`��P���^��:�<�3�c�Q�H���u�c>3�z4����T�qN�����>��~�"}��G�(K�����Pu��e�}�������Pr*�jk�b���=���g��I�W��+gm��h�"��^6��<�������qR������0jv�J���F���
e��>���~�������Z��N�[��.���'o�zY��q'��|C��x;7Z���_V����"4Z����n��Z�#)���8��G�hE�{���������A(Z����jEw���jE|r��hE`���r���+�^���I���=Q�a���W��>��q]�+�w��6���rD7��H��W����Q��)q�8�yF����p,E,��U�X_�i��}�.(�H����.H�!p>/�����^n�dN�|Oo�f2��]��4�F�{e������jD(�?�
�~�#��.I��"��p��V�����$��#*-�T���o���0�&���h��A#B�}�����G~t#�����"���h(����%�����`����W#B��6>%����aQ^'�N��9q��j�^���k����"1\!1k�X$f)x��������@IxA��h�;�4����r�&���A�1��������'�zh����c��Cf������0[rLx��}4�(���_R�@���W�k$!�����HB`o�,_�������<M�g7x���u	/�Zz#	�^&	�nF8>{��w����g��^x}$�0��4�^�W�/����1�gl?����'����CW[�����0�.JxyES��GA���(��!��!x�/�����W�}1dK�U"��rJ���q7�E� ?�Q$H� 07v�P�~j�r�������q"r��s�I�d��H4R9����jW9�����J#/�����7��j,p	#��>o��������F���1��S#2���4�4"�^���h"����&2�����F(�*���������4bi�!�����Vm�#n�xSm��PT)y���g�^q�@"�w*��6�q��v5��|Y�
���5�Wzgt�k�!��R\�T�8��jC\-��jC������p���m��j��m��W��6D�c>o��=����Td��"���w�.�CfpAWAg�s#�?�R�������9�����^8��\!�����HB�;���$��\;5�U}>X�~}�S��N#	�>w�I�$��Y#	���{edW4�Wz�d��$D��i�����S�����Z6Nf�JB��k#���=�i��'�W�$D���.�:_�G��ve}�Q�<#�pzNg5r]RV��Q�^�m������tKd�������7���Bh?����������"���G�(O`X�
�	�G*K���*O��C:��OM��/���*O�/�p�Fy��o��gU�H��[�=jh U����32�G��/���}4s�Ty�>�9Q��<�~7R�|�h��O�Fy"}m����K��o������(��[dp�)��\��R���
�Y��"0K����D��W�9��i,L_1���B��&�+��}><��������>�p�i,<���w��Y�X������Xxb���-���"S_��u���M����*
q�y�L�!��N�h���v�>5�0\�%���v�������I�]�!�7F�q#
q-:5 i��*i�/
�w
Gi��|}�Q��.Hi����4Ns_"�"\�Et�X�SZ�����B����{��s������^6����}���'d�q�(�UAn����R�2$�#���y�{K%��!������wb2}�<��B�|`��B~���<in��Ou&���K���ir>����<�V���B�o�
2�y�VY�L�_V'+������)��f����yY���f.o_PVn�����Si�)	]����$��\�?�"���-����s!nw;I�����k�F3{a4WS#��zf\�5������C����'�&T��n��#}��X�q�|�s����
��Wy
���+��]����_�O��	4Z����R��)�>�j�`O�W}�qO��b�V����Z'u^�]����H���vC�K�b��K��c`c�.��M���.��Q-"8m.�Z<�LC�vN���E|�|E�F-{aT�h�"�?��f~C�;���Z���8�T-���6�i��/V��t']�Q���W�����E`����M��^�
������:����lh>7FC�F!�.]U(�8A�[CGK�B!"�F!"�r?�H��Ea��3�����$���N��(
���(p����z��5����}���)����}�m�������!��@C�EQCBb/��z�~����������4�����R�_����@���R��~��W\������5��(�_�^S�����b[�qT��>Z8��_�>w5�~E��*o�+��u_}��nH+p8��6R�T�����D��|���_�F�~
����g�$��j��YX-��vEp�H�qj���������Q-���hA`/��%���]k� �����"����0.~_@�?\��7�j�oN��eQ�e"}U���G�H������njT>������Nr*s�&g����&g���������d�F
gL��5���q����_�����w:��|�����uxD49_r�����F<4*������DpA�M-�)/���C�����M�D4�~�d�h$��1'/�c�\}�d$��`�&�HF���QX%#�����H��r(���#�A%#�j>V%#���?bV��/�x�b��6����v�������:|����#��2�I�<��Q=U�"�����=�@/�������L�fpZ@�	�.h!����7���1�_1xT�������@^?�������������5�w1��;/�c�2���y��n3*��dj6�sitj$ ���c�_���������<��f��D����g�q��8�N��H@`/����v7��8����7�����7}#�u��#T���W3
@/*�FW�G�������i�;�K>=�"����1��x���/��0�l+[ �G�ui ����@o��`#�~��N��U�i$5�D����6f���! ��!�U"{]#qT�Dc���[�E{����S��8��������{���5�k't�:	��� �WF��(\����+����-K ����X` ��]��_������L���+e��]����~���SY	�eQsb��K�G$������a	�nh��W�!z?xE~<"/n'_���{�i�e@7�X��D�QG]�%����G�?��������Y�r��D�UN�c�M�]������+�\R���WF�v#6q�.�F2�7��4>M$S�����N��/|������?��8�9��B��v���kL���4���B��H]��*R��|J�kY��@������^e2�����o�"�����s*��
GwN5R��52�T����HE�/��w*zMQo#�B�"�WN2�J��k��m��Rw�=�*�w�&g��V���ure�C�~�TD����n�"��K�(C#��{#O�X��N'�Ct����*���:#�r��:_hq����j8>�K@���F<2������j�H�m}����'���sJf�j$��n9��H����������M�j�H������y6�-�h�h>���jF���/��7��F�'��<����hFf�]��:�������5��Q<F��y���(Do��]"�7V����*�,�^bt�I���ut��7��_�?o�\��R����5���G�W�_������^�����B���b�N�B����;a���1Y���_����/���9s��J@���;`���Z�s�i*�~o��*�Y���	�l�&�J@�������M(�K�?�J@�����H�`������J>~���H_��T��u��`G[���+.�^a�qq<5yFZ�H�Z�H���	��l^t#?��q?�:�vgD;7��h&x������H@��q��H@�/��*q>�7�~��
�����^f�����u��������1��^!���P	����H�`��?	���h>�H��4�'�70X�F���7B�D�Z)H`fp�x����I?�H@W��.�dp�p5�8=�Y�z�<���n�+�U,_���f@�,D]�6����(���vJ�iX"��2X���`��z���@��B�*���h\��D����%�k*j�Z7�.	K|e���	K�]��:�&g�.��N�urevC��_0����<m�&����������	H/���3���_VD"�O�W4^�^S������G��I
?aSQT����|*I�,��GI�b���r�n�R��=&����;id�S6��G��#=���[i�wC��]Q������jD�#w8�n�T��zY��	�K�vT�����D5"{e�u�����w/���;�(�`'����Q)�u�1�Sg��RV��Q�^�b��K�^����w�J��9+���;V�����C�>}��]��������g�/�'N'�?Ec�c�c<����aA����F`�N���F`�� ����HF`?�&�JF���s������n�� }��{�dDzQ c8�������;X/�2�r��P���x���|�F,�x[��U,���C�X����$�����eqo���b���N��\�r���3`Q��0V�E�!��e�~bQ�O,�����G�� �3BS	���
M#�=7��	�{9h;�9������0����7�E�,H�o�n���"��p^�*qVK����\�`F���*q�:��"q�:��:���+��U�?_.����Z���5�k��	p��	��N,��Q"�B��S�g�5	X	�C�2�	��#�X�[���������8���F������C|��Bq6��Q�8���9vfs0����j�����Nk	��=�%��T
��	9���6���As����A`����F
�L
�x��`r�U
"�7�|7j08���X���XQ�����6�Z���Q
"8����WQ��E
"��D���\
5��}5X
>l?oG���Zf��������������M��_�|�n�?w��.����v�PoI��x���O_�a	G �,w�)p�I���NZ�����_�]��O�OE�m��)���c��"U��"�p�����y�m����S����t�]��������)z7d,'����s��[�6w�Y��o9����sw��[�5��������;����X���gN�������_�E�:_�����5���u��;_����|}�&�������������5�������5o�|�*'������8}�~����������=[�k;����(X���x����G��g@oJ�R���
Wx����7@=��-��|����#��v?���	<l��+#k�v��$8�~v�������C��?LO^z��������j���xZ	�mY���J@h>�q����-V��+���P��yb%��X������g����S���;��K'(���>������y��?��c.�/���RL,^�����G��y��G����9�.���gC���I��Xl����m����
9[}e���C:�������
D�G���@�|\��
��L?��
<�y�Ym>�U��V�1�W��������L���
<�'>Sl�;gd�V���6No���-d���N�������K<_��y#�����7��<��wvSc�U
NE����C!�B1x4����U�o].����X�j�ez��C1
^�+�?
�CYJ1�\TC!��	��M p��=N>q���"E)�N�Q6�N@��%S�x�y�F���4��7V���3vr����K{�@KtB4�y!��	D���I�Hm�Agd�F��! g�D���l��������F�����U�^��C�p������F���Ouhl��}�?_Gef���F@��i*�6��������{�:{�W�T�����x�d?��Ct���@;�Fg�,������������P���, 8��+����X�Y�'��@\�'/=��,�/���^n�, �����yZ��X����>����
�^����|���.��l��J����]s�o��*����������\5pL�]��V��������Sx�{��k��������G5p�8��s!8�
���\`.�ln�~�D1���������Jb��7Xsg�&���0_��1p/�&j.�����w�k���y�qjc.���8������E�>���N;��$�h�#e�_���*����;3���31"�Z�tzqP�V�
x�$F08[/n����6 8�/nC�P�����"��8m���P���6����L������mlM0CN6:�!'�9��C��U��.�GJ� �#%�`e#J_�duf�o�����h�`/�����Y�����6X��N���z���u��9��q�����z@������w������Cpne��=����������{N���\}%�
@.�p��#p�<�����~W�!x��K�4���=�-[a�|�n��%�
�w6��l��?k'�C����(b0z��e����}����C����%��F�1�P�����s��O\�4������'��t��l������*N�b6��O���{��������[���+f���]+��y�_-���c��<P�5�6b���r>��	��Q"A
�?���8�F��8����&`����kL��q������:l�i��F���H�������lL��\`Z�������1-��� `"8_���l�\T�g����94j\�i�c����"8_�������D���k�i�{g����i�����Rh�1^�?��,�|`�������i���bZ���@pE�W����@pE�D��i��|��uz�
JG��c5-j�XL��'~:�/E�rV��B����@���g������,8�#��7�/i)��g�L�������^:�sR:���w�TH�H^��&����}1�&���a�u�q:iH�H��p�����t$�7Cck?-#{��W\�����G�!"g���e��~hD�r�k>Do?4��Fq�\���g�&-���������A\��3*��3�����L��;���{gc� ux���d,�[���#+�|J��t$/��f�<�����P`pA����P���JG2� 
�<
�Wx<M������Ij
������\�p�{Q������i
5�"�P�v�B�k;�$���5�
D6.q%T���G��	8��i��#����Pb/��j$��tV ��\\��#�U��<Q��
D���}~N�D�����O~�BtR��"����c�&Bp���
����*D����/�|���8�5�#yk�Z�X�D�1q���D�Q��Wd�/L���Q`"���X"���>�E�'����� ��	:B0�W��$�"�	���,�6L�, 8�FC�<m�90��Y@p�;}tj�X���'�NO^�g��N���P:Z���\���.I���������]����K4�l����d#�\� o�2b/��Y�
�)v������cm�,�R��?%���l�r�E�9e:�j��0a�j�|(�\;j5����G����*�W(=�! �+Gmr�j�=k�j��WQ���5�x��j5�-:�j�����C�j�1�gE$�����uf���j@��Y-j5������=*x�l�"b5����@l����m���x�W��|�w��2���J�<���^qJ��< 8oi��C�����?_2bt\�<���y@p:E���1���8_�����]F��5�
�w�������yr�����<����:8����:�^��q^�*�a||�y�8?�<����_�<}>dJ$��y��T��":��z�dqJO��y��� ���V����-rr���3X�<�eJ{�$S��,�G���$���n�
�<���
��O��^��NjW��"B��qm�I�����V����_@����������`p��P�����y�0��*r&�vD�_(k���V9�k�������5kG��I��"'���v�H���$pM�M"7��[�H�P���p[���)���c��3m2pL����U������*pu�nj�oxA��Pw!9��U �	vn����*��(&�WQz�6^Ep�&'�*��5y
�W�����ft���#������9\������5F5^Ep�����W1q�DI�4�3S�������W��gm��������8)��[5�1y�Q�Q�< 8�M"��0,\Q:���igGJ��W,��g��t��eQ:}_���FYL|��t�����t�����{�e�]_�����W p^F��@��\|���W ��/�#y�j*G�8�#�[ ��rd��H*G���N����z�������������j�9V��q��K6b���o}]�1Dco���!:g}�!"����j_�1Do�c rM&�����=�~j�xW��Q�x/:.�n�����N���0z<��L�?���SU<�?k�F�X9��P:`4X��o�GS!z����sA+
^�������w��O?qA}�w���V�Q.q��(��B�P��B���w�r���}=4mC�%�
�nE���T�$pM�H"�=��N�Q6�9�������Pk�J^B��tBN�J�1�����J��}O��6���c����,}U �w��|�oc#�Z9�F�F(=! �"r���~ZEt���	���?L>�q��6��QPm��u���cm�YP!x�9�w��N��H�J.���{gc4�jl<��&��V�4����#
��]�A��c��|�3�"B,���~f��O�Wo���+�2,\���x(�[(_�'� ��|����P��P��Z����������t�H1����=/��CQR���E�kZS��5�_����p���`/�&R����S�#y��??�6<���5���>��
x/�
�X
��U`5��������D����-�X��$Y�����+8���V�g��j�94n��j������1)���5��>_���;wz6oa;��s+^N���-����yVb5�O��fT�!X��w�P'��Y�<�i"b5 �����_�b5 ��&��9��((���P��P��b5���X
���j��I��V`kb����68�n�j��KZ����b�D6R��j�a�iSl����^{��^���!����Wt��S`5���F���j�w�H���Z
���NR�Z
�����&����p�X
�Y[`5gm�L�a��k�E����9�)�c]���df���j�Q������S�C��;���v��m*���X
8��Q�@���/g��������Y���x�w�6�cM�h���
�!P�VD<�I��J 6�zV?���O,6N^�8�NM^�
�����.�)Y;y��o��y��~3����S<E=]�����3�����m��� �]���5C1:&8C1:&87����$������8&D�G�j�G�����g�md��gB����{&�6�?���+����3�����J�Lx�;��O=<�o���D_���Q{ �gRM=���{&�a�g��.M;v��D�x�h�v���gO�k��|Y uMx�����Ib|�����(@z��|��u���&�Ez�>j����T�Oxj{#Q������Z���8����F�k�M���8�������Q���A��t��� a���b
T��$�m�0����*�����-�C1$Ngn�	����h���G�a|=+l����7���V��������V���M�#F�W��9��X�6�@�����0a�r���O�m,`��K|)8���yCl�`����}�>������s��j3}9�H������\�j3��������K���YL�m�p�����f�q6���fOo?8�g1���Oo����8���Q
�����rA������e�x8���3o�k�^������u+�<I�T+_fy��Y�2�=���c���#�8=yb$ � ��v��H@p��P��b$���0\P[��y��25y�#�<	���f	-����v�G�s=\�`����g�F.����p�
��6����j#�7"m�'*��?M���a������20D���Y;�;�D��\9��@�~ikQM���*�U�Y{BL��������!8_����@6�J~��|[�����h"�Bp�������;o�6��y���pLf�g�q�t����4���q�6���u��	/�?�6�5y����1��g�h0�(�(I�`@U�.�)����'^��j�0��_q�Z�|O1�������`1�]ZQ���	��x%c�WF`�xe��c�&?��U��@6�@����>���/�?_�F��:8����q�	u��8�-��+�r~�8�m�0���������c�,��F��������@�=GI����YFd�gFD.pJ���}���L	���7�\�>�_��>�81r0�oN�|h[�>��x�r��17y�/���=�x���e0}nD�6��WF�-�,�p�)�dC�'_\�Y�2��|���c��$��,Q���2�3W�(��o2��e�WX��}7�.j�!\�2 8_^�05y�25y����2�k��n��k���o���q��2`?�G�")�Ff��@���jbp�����, {^���Q��up���:�F��������9�Z5����|f��&�|��:p2}S�&'U��Pz6nB@.H���.����ID������0������n/q����M��a�
Q7�s�-P�&{u��t2��Q��]Y��1�W�1Dj, �n��k.<���N���$���j$����J"��G2|)��?@,��5*��l(��E��M-����s�p���j^�&�����5*	lT���XV�|����I?�
endstream
endobj
45
0
obj
50269
endobj
46
0
obj
[
]
endobj
47
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
48
0
R
/Resources
49
0
R
/Annots
51
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
48
0
obj
<<
/Filter
/FlateDecode
/Length
50
0
R
>>
stream
x���[��:����|r#w�v�p?�t�DR�W���
�v6pp�������������9��b,R�U(T��{�%��8EM��O���O������-����z���?]~o��W��]��^n)m[��R�x�����_��{�\��iI�w�\���+��-��'��������_�}Z�\��������0����|�?>�������O�V��o��R/U��B�>�E�(��|�������6�R��8�������f�'�!G��>j!N8���{B.�������8��!P�q�G�[p���������>j!N8���{����w�r�����@�"�	}po���P�7}�N�����>	h�B�p���>�t1�q�r�p��C�f���>����!��9|'�!��!�;|�,B�p���>����wB���Cw��Y�8����-8|����	r����'�R��8���������/\���������/p����!��/,��p��CH�q�}po��C(�q���|�;|�,B�p���>�j�P������P���8�����'������@!������,�8����-8|�y����|�;|�y��G�[p��y���>�>j!N8���{�f��������@�"�	}po��C���/l��p��C���/p����O��j�@!�����pH@���#�>����!��q����8��!��q�}po��C��q�k��w��y��G�[p�6�8���>�>j!N8���{��<xa�?����<x����-8�]���~pB�s3���7��8����-8|����	���s��CXo�?N8���{B���w��}>`�;|�,B�p���>�z5����}>`�;|�,B�p���>	��~����8��I@���#�>����!,���.���������?N8���{BJ����t���BJ���p���>����;!u���B����p���>�Z��;�t���5�'p����O�r��^�����>	h�B�p���>��<x��}>`�;|�y>��G�[p��y���>�>�d�p���>��<x!���q���E�8������p3�^�������@�"�	}po����^����I?�q����f)�	G}po��CX������p��CX���8�������������8��!d�8���>����!l�q���|�;|�y��G�[p�n�q�[��w��Y�8����-8|��<8�B�Cw�$�Y
q�G�[p�V�8��k��w�V�8���>����!d�8����|�;|�<x����-8|�<x!���q���E�8�����'!_���(��?�q�O��'q����a1�^����q�a1�^8���{B2�^X����������8������P���R��w��y��G�[p��y�B�?��B5�^8���{��r1�N����T�|	h�B�p���>��<x��>�>��<x����-8|�<xa�?��B2�^8���{B1�^H��p��C(�q�}po��C���/���8��!P�q�G�[p�$lW�8�
9�q����f)�	G}po��CX������p��CX���8�������������8��!d�8���>����!l�q���|�;|�y��G�[p�n�q�[��w�n�q�}po���P��q�	r���y>�4K!N8���{�j�p�?���j�p���>�l�����q�!��/p����a3�^���p��C����8�����'�v1�N����l���,�8����-8|�y����|�;|�,B�p���>�d�����q�!��/p�������/���8��!�8�������>���,i������%��;��i��7�O��xWI������<�u������m���g6�cH@�{��g���V.[M��[�LY���������(��|�H!N0���L��?����q������|�4���� ���=�	������>.�rK���O�v���]��$�.]M)�	����N|P�F��
A%�!{�L���o-�b�.N����]�a����8�^���D_��p?�����/��$��m�X���x�����f��� ��������q�x'�t�[���������f��b�E�!N���q�������5?��Dg=���R+�&�I��S}���?��I���r5��8���'���^�;���tM����i�':�]�A�bHi���o�����x��d���L�j�K��;2��u������([3���$|3��B�`F��\�����o����;��q�|e/�$0��b��������w��_Z-��y���j���7������~�va�?]�^�e�o
��'�<B� �)x����v6����8A�zM���{��.�rLF�����%B����#;=F�����3�=�\U�	4�$=;��8A�3���Wu?��U�*�d4L�|V�u (�	���wf~���2L@��76����4�mw�;�ifIy&��E���gr����9�'O���2].]t�9�	���v4;���R�5�&�������L&�d�Inq�&��X����OL{&�k1�Z)�
A��6�0M�n��j�����T�
A����������}J'-d6��|�\j�8A�����f����E��l�t�L�>c��Dj��	B� >�9�|�=.�Z�g�-��4$�D!N0h�5�Z��Y@�����$B�`>�������Y��	��d���W�x��9�*L��C!NPl��)3%�iW��O ����f��4��<�����������q�F����^.^t�9�	
�q�~O�G�8������bH��4�g��{�S2���9�8A�{�	�A����k1��6�~>�'y��<����6��T5����GS��T_���h�'����mr1��
3)3��������y3�l��'�����>����G$p�����!1��*��'�o�e^���C��Df���	Q�4��k�?b�����$B�`��V2O��C�"1�J�A!N8�fG��-���q�}b9U \��:����l�).�5��gM���[)���1k2#!N�lLi�pO���].�]t�9�	�����H�>B�#��1mZ(��&���`�d�Ihq�b���^�-��?���������4�7�f���l���3�'htgN�7}"����Tq��a�[3�0(/�����.�0}��R�'���[����$�D!N�h���o�]����q�+h�i����f{�,&�8����;�������H���'h������7[��Gy��ds�!p���!h2O0D��p���la���A�'h��_��'x���r1����!NP����x��� ��9�bH��4z����~GWtJ���'(��|By�V�������k1�Z*�
A�yt��CLi�v2fSD�P�
A���^]bf�f� �	�|*+��������&1�1�!N0���Ad$x�<�~"�	���$,f���V�I���(1�y
��K!N����N��u/�D�w8[%M)v�Y{�\<����Xt�VH��x5�'�pO�`���������$��C����:���c�kZE�=�	���T(�a��h�j6W�Q�y���CY�f�{��3bBcF5�8A�+=�6<�m���b�Ew!N�d�����lvFLh���X0l���:arJ���pF��y}��E"q!\���t-���X0hzQ������h6�M�j�{����x3��p(�	�3���f_�$��1
q�A�<V'�i=�2J��f��t�B�`~�����n�}��]�B�q��[�J����p�E�K��8A���Z�%��S�����aW�O�8A�y������1�K�D!NP����U>���N
��O��(�	�_u(���Bn�5M���t�<N�6L"����n�8A����
v?"��!�gq�"W,jj,`c���l���-��o
A�ld�d���g����)t�#�C����3e��o`�	���G�Z�CJkC������f��=b�V
��������G���2DB�>4���v2�#�nf�!�	��t�xw�����K�dv�;�N"�	�-���;
V�*�
w���h�8A�EU��8%L*A�5@�M�91�Q�������W�K�8����
���
sD}^��'4���,��Mq`f!�	�bJdx�)���i������I�+����v4������q�F�S	/�y�<������5�8A�7����#4\��@������u'��A�d�Iqq�F���$�^���bXim�������$4�jn
�}�	�z3
����,���NIh �[C0�����l��y3�lz�'����n�d>��N���.��Qq����W����:��NI�)�'������l���aV�9�8A����d���l���%��'4�t�k�>"����b�4
q�&�U��z�.QG>�k�7>��&w����I��y��q�"��_�Hv0Wn	t�t���'(��'Y��9+�����y�bH��4:��=P�[��A'=�9�	
�\���~	�k1�Z)�
A�_��l6(�Om�b#�	��f=�U��b�6;�S�j#�	������:o���F���4��A<��\k��MH�����"6YP��?�p�Gh�(�����'4�q�/:��]��������RN��W���Ga�dqBD���@�?ux7�=�	�S�yv*{������sq�o��|�paO�@�AM!N�}�"\���b�Ew!N�O�bZ���PFEh�%��C��X���=��:%�NzH#�	-�g/�av-�]�A�5���~5��]��.�����g����b�5��.�ZS��aW=�������f3�)�	���O������������F���!a����+B� ������W+Y<p���d�#�B��8A�q���@��a�!r]��."�	��}"`���lJ��$��'hvwm*�aM�&;S��I���;;���fM�\f�8Aw��d2e���<���0s1#!N����B���\���r�tw����tv2��,��[C0#���X��S2���5�8�t����0"�b��PZ��1�����)�4�jn���8d�fF!�	�����0�������gq��N8���f���!NP�n�$�z{��E��v�6G��~l��I����	���-$�D!NP���%� �����b��t!N�h�+F�Z���G�M`��7%C�'4��]�*L���E"�@ �8�Cdv����H��l�4B������^>���\�#fPf�#�	~��F8�)q2�d��xA�7�S����\��?f`v-�]���'��Zt5'�o�4��.�TsC0h�f
3�"��|K6�F��@(�8A�e�@<�q�o�������q�B�/��������[�)5����[���j�s������42�(�	��0.�y��M�FW�G�8A�;5�vl��� 
q�&���m�O�1wlSn$�8A�����^n�7dSmhDB�4K�:_�Z��M�����:�cSk��E��C����X���B�Y�Z#L����{�+-#���av�C�C�`����<k��������^�5�6��)�4�jnf�!;&�"�"l������>��B�����q�������L�����P���������vL�p �Y
q������k����b��t	!N0l<� ��>Wg�1u>���8A�_\��d8���B����/��yL������,�8A����a�1�?���'ht���S���E��C������=���@������O������Nz�s�4�x��pS����PZ�&�G�����2+B#+Gh ��>v��cz3�����y[���Q�rk�u��<o�M/�sK�T�g�3O6����������m������2��)y6	��C��dw&y@�����%�8��Eg�V���M��I`����&lz��	sv�R�,��$*��)l�8�^�^�L�;S����8��E�B���;ng*�0��~#�	��`����N��)l2	��X0d���EI��\
9%CNz$#�	�|�l���fg���M���|w���8���7s�)�	�{ a�1�E�&�Q���e�Bkf�1�E��M')�	�C+Q� 
��/�IK�j�(�B���|l��lH4�! 
q�&�V|�����^���q��7������l�$L��AQ�4[,������.Dl��I B� �~!BPdP�)��es���f��5.lBO��)L���F�L���0�����GqBs@5V<���pv%L�����`Npo���j�)t���C�`����l:����k1��6���j���I�l��+U���!|����z3C
����-�(f��!b�d�B���N��:o�M���/�g��<i��>��',���W�[��h��0�B���Xz�V�l��+�Tav5�D�;?����u����'h��k-�/4�DB���������!NP��*�`�<��E��@!�	��[d����d�z�C���//�`vJ�����'vo�E�Lx�)����6�v�-�T�`��/6�8�����@�K��L*������[����y3�l��'hr�,n���u2{D��e���'$�u�|/=���0	bC�B���/Lo��v]��n"�	����aD��8A��H"���>�d`�@(�8A�E�
�]�4��D�a��C~q���/�*�A#�	f���xd=��0
a�����!4]�[���N���g��~y��k1�Z*�
���L���p+bC������
�z3#
���v�Cl��!Un
����-L����7C���q��i�*I��*lD����UaN�����6��ro����f���{x���!h�(J�����G�\@�����$B� ��_���lR�S$�'��W��.Epx���!|�B�	�h�)��ds����-�d�?�Gp����o�8A��o���\��ns�4�����o'�CbZ�P�53�����#tJ���'�Nw��%=��EaRS
(�
��N��K8�7s�!��[C0?��}���h�(Lk��F�Z��v�0 "�����#B�������������0�y
7�A��8�B�o��}v*��)v�!{�$U�\�9��b��t�B���x2@��0�I���8�����CT�Qw
q�9��OBl9;�M��N�\]
q����y8��<���hs5��B�`��u���������5B����{��fW��i1�|����\09%CNzh#�	���:�"�b��PZc����gu�fC���T��`z���-�����QF��w��b��+�OBlu;���&3�(�	�I��#t�:�.R�Zg��6Y8V��`Y�!�M����)�	W��42T����W���hvD�����lo
A�y���F;�0�.]M'���[��������S2$
qB�?1�d�#2���$�n�kCdz0��*���TvF��es���_�t��S<��=��1e2c!N0h~�������G�r1����!Nh�;+?go��i1�|k�s�)����<��!N0��U��k1�Z*�
A�{E>�kl���U��!�t������nAs�l�B������pSu�)H�����UU�+��f�0U'�D!NP��~a�&x�����b���!NP��o�"�g����@��~a�N0�B�������L�	f���O�
A���L�Sq�8�0��L-�������fX B����M���M0�\��Ns�4��E �U�J������%|��M,��C�m��
��{�s�1�z3'!Nx-as�1� 6���!(��t��`�����&B���/�"	#0�.����M!N�����B8��w6��zk�-���3j�X��w��jz�'h�q��}����C}m�K[�
�r�&���^�B�J70�.�����/[C��(c?0�.�!�'�n�Z����b�Ew�C�`��b���2L�&�[C0��z�N������
4�9]�A�bHim�]R�@c��~5���O9�������4�8�c��}���H������l������$B��_��0ASi�)H��^������r�b��'M�
fQ�4��5������j��'�~�/�|U\��)M�
&Q�4����0BS��$��kC�������!N����.�M�
j�!�	������r�r�}�'h���7�f�4�7��o
A���u�tJ����'|l|4�7�]�A��!|d�	4�7@��{R��`~Y�������73���>������@*������b�t��t6�D�4Z|���������k������}��!N@�7���9����.�3�	�z�~�S�	t]��^�!Np�~�3	���n�3�	�[���gJq0�)0iq�Ew�e���r ���'ro�'�T��vH`�������n�].�]t�)�	���#�h�q���o��F�q�6@S���I�o
q�%���`�b��TZC��{��h
���Ts(|��l���73��'|x���J `��@�[(�~�\���y3�l���8�}��V��ZD8g}�>��Qb>��"�B�����x�O,?hj��l6J�U���So
A��
���ZD� �����$B����ZYp��>��\2$
q�AQ/\���IB��{S�
A�;YCa�;������\j�8A�{;h	|��QbFgF8B����:�	^.^t�9�	
��C��pg�WbR�T�5�&[1��.W�N������~������n�i5�Z��JkCP�����56K���!��t�{{Q�z3
oN�5���.�~�^��dvJL��0C����,wxL97����7����q��m�n�����_�������M�M!NXU�v���%,P�a2��zk�,viw����
��A��N"�	������k�0�P}m�|w6����4	�A��4���4���	�b!�����/[C�l<"�}K�m�T*��8B�4���5�`d$r�r�}�'�r��7��f���n1�|k����xk{�?B�d�Ipq�Fc ��������������4�����v�?f���f����T�
A���y��E���p@bof�A�&���L������f��l������'|��l����ag�K�8A��������w����.`�j
qBV��$����FIl�A��4��f�]��v5�D��b=��X�k@�Gh8%�!����������N^	8	�Q��t����a|��W6��l
A�����v6�e����s�8A�i���X�E����r1����!NP�ML��-�a~��_P��4[�����} �d�I�rq�&���y����Z�JkCP��'���_����Fw�^pb���
[g�[C0��<+�|���Ag3��}G{�J��������0�z
Wl`��8�B����[��f����.0jq�ew��D���AW�K
q�Aw����d�*����!N�d�����iR0�P�� (�	���}��}v2�������C>~�%�g��������M���W!�?S�C�r1��{�'h��i�����U~El�'�����X0l~�"�T��*PS2��G5B�`��<!;�k1�Z)�����j.��b������I`R��`��7T�����gz`of���8���&&�~A��1�2#�B���^��;o��M')�	�~"���;e�$�>���tFL�v[XS�.���B��iBC���5�&<�8;��b���!N0l�t��~U��1�JE!Nx�����l��M��C{m�+�.lpg�Q�D.��'��T���>Ia��9�Q�'�>�X�E������"�8A��3I�� ���l��9-��o
A��Ol|�N�������Ub�G�Z�CJkC��N
�}o'�3��i�TsC����}���g�Q��5���=�g���l����q�'h4z���G��r6}D������`J-_l��=����I�.`�p
q��������2�=�fN$��[C�d�����b�e�`�����$B� �4��Bf�z��ng�b���B����[-�>Gh8!�I������D�B)�3F���1���'g:�����
[����j�8Au�{�f�#t�t��'�6����L�CL�������K�d[��:%�NzTs�����%&��Ge� �b��PZ��t���|��v6�!fk��jn��n��{��W���/��|��F��^���
1Y3�!N��������7C���q�����Wlv��.H�V����k�����
:aw�
�!�6�[CP��KZaw��`W�M�8A�_]j2��.B#@�M~>����ulz��@����
A�{5h��~�k�0!NP���~�
��R>�t����=����[d��r1��{�!N�`~	m��O�a2���!(rc+����;%�Nzhs�t�_M�2�������4��~��1����Z5���&w��	�#�fF�
}k�4�Nfk�t��2�8��V�� �����"B����U�l|���.H��~���2Ts��l����@Q�4���5���aW�M�8A�_����l����Q�4�R�3�����#�$�V�kC���=�����;L��m�/[CP���Z��t�4����>^�-�O����{�!NPd,l�R��t�FC)��F�Rrl���@'=�9�	���&�b��PZ�!cv���V3��u����!hh�>8��p�(]��Yq�������r6 �8�GwU&h�C��)�SX�A��
�_�{f��lQ4��&�!N0hQ'��s?�����AW�I
q�D�Y��{Q�������S2�=�	�����{
w"�.�D!N0�^}:6���D��l.3�8A�����{���N�D��M!N0��w��|].]t����������0�Z)�b������k\���A'=�������^���bXi�
�/�d��lT�HU��9;\g"W��{3C��(�	���3]:�Y��$1�2��B�����&H��v6��'�~g���nvA:&v+�'\����O��t�fB���� ����U����t5�C��������0o�~m�Y������2	�I��4�U����T�	!N0�n�`v?]�-�@,�8A�{��]7C.C.���E�[u�#\��)s��|k-^F�����27����'(r����>]�F�k1��6��������M����4���5���(��;�o
�#�f��n�rk��"}��MOW��l:�'�_���k��Lz��	�.`�v
q�����r�����4�"�����Fs<��| �G��t5�D�4:\�Y&��!1�K�D!N���=�|��7��~m����l};������\e�8��������
W���k�8A���A��fJb(��\��s�����o�zX[��m1�|k��_�J��u�{O�����
�o�"��G�Z��JkC������W�����[5���F�Z|\�73� �~�[C��\V��]������v8�#fnf�!�	�����l~���ag�O�8���i��y��K��Ab���B��T����L�g���	�/����m��.�\M/�E�-;�>1�-S�dP�����F�)	MoN�6��+n#<k�$*{$M ���q��������%�a&*/s���B!�	z|w��\7�.�.����_^�BtYo����-��o
A�_,?.�)t���C��O��_p0�������>v�����b��jn�-��&H���3��~��fw���d�HL��0C�4�������y3�lz�'���+.	�+�J��3�]�����"+�PJ�|���FbC�B������av]��n"�	���)�#8�����'hx�����C��A&��S�4�W�vGh8$�!`�������Df,���1�'�1�/T�a5����].�]t�9�	��x���eIl@�[C��W�b2:%�Nz�s�4�`�KZ
���0��4��W��2�#�!�UsC0p�����a�flS�l
��n�m-f��	
�rk/���&�����#B���'b{�����*��H�����}��'P�����{�~;���&Q���=�	,�a���\��G��t5]�'t�@������[2�=�	��#��l}D�9y�'���<�|;���f��\i
q�!Gf)>�a��Kn�7bg7�8A��'���sX,����b�Ew!N�������	�bH��y�w�pJ���F�4X�^�n��}����k1����A�����pvG���a��+���G��3@�'X4�g�m^x.�oG�9bg��8���f�#t�:�NR��
�7�b�{'��i�.���q�U'hT���~�f���	@Q�4��I&��b��t!N0����������%C�'h4'�:%S�
�$6	�B�4��;@f��d6!N����D.�Y��q�&���a$x�x���'(��	&�x�p��>�i�bH��4��b�r5��:�!�!NP��w�l�D���k1��6M�=��	�h�IL��!��4���f1c�M���cq�����=�83�����mv@B�����#B�`�d�Soel����"1���)!NXe��n����I�)@�'t�� ��b��t!N������Ib:��B���������$2	B�4�S��
p'�E�D2���'hr��[��-L�93��s��n&^t�{�3�.�.����>.[%�o'�CbB�P�5�V�E�y���S2���7�8�yO���	^���bXimg�w6�$&t��jn����$�fB!�	/���:���f����5�8A��w�6H��r6�D�ZW;���mp���F���.�F�qBV�:���d�I�R��8A�������.�YM����nEw������i\2(
q�f�^�iJ6?B�	M���>�����`vG�@fs��
�m0+�o�����Y��q�b�|�ZV���0?b��a�oq�b��-Y/�!.�������!(t�9Wl��
�#tJ���'(t�0��`�)e�`�b��TZ�b����;jU3�� 1���UsC07�c�`�#�f!�	�}���l����q�'�{����-��}���Ag�G�8!p�h�6=Sl�)�L�Jyq��������4��!N0��at]�"!�	�}�g��,
q�������b;L&�@q�&���d4�v�@,�8A���AzR����C��@ �8A�{9B6?Sm��E��C���>�3�v@�P�5���Z\t�c�0?Sm��Ipq��u���0?So���TZ�f��n��f��9��;L��!�nw'��z3�����~�R�Hc4�~Un
�c�f�3�M/�s�n�^��ca��Y�.�Q�!N���[�	6���1g
q�d^�kQ��v2{&R���'r��F�&��
�"�.�D!N0�gyf��9\6W�B�`���
���70(���S�8A����x�G�?�.�.��q��t7�.,�J�\�����|�Gg�P�*~�rJ����F�l��W����!t-]�!�5�0���D5o3�H`T��`��7�lA��P#,
q����U��f��L��4
q���9���f����B�`��k=��c���;OAN�hkv�8����D�Iv=StL@P���Q2�.�YM������@eO4�vB!N��gvL�%�B;!�	��a��gJ��Xq���j���B;�DB�4�S�X�������{�!N���+6=Sjl@�[C�lQ.�A�2(�{�������<�����b;������4�xi�p=Smd���?�e�3�v�����'�^�`��5�ESq�Y��<,�%�lz�����'B�����lx�o��+�m����)�	{Q����6H&h�w�8Ap^���#v]�B!�	���9���pvEL��aQ�4���-L���EB�@$�8A�;�����d�D�*fs��M���f�{��%b�V5!N0}&{�n2y��\��Ns�4���5 �!b��P�5M�?��jcwv;b�d�I�oq�G.�0;"�b��PZ����RE�v;��S�jH57�u�����d�'r�-e1����43��s��fb�#v�;�N"�	����7OAZ�B�����/�p!S����x1B���0.��O�
7��'�n�Xx���)S�$�8A��R�c�"4�)sB�����X��L�j�B!�	�-���L(������7�8A�_�h6+S��I��:���T���XS�rJ����'(��k]�]�a�bPimz�us���36+S��I57�>|� ���a�fB���;�p"Sod�[C0w�p�w�H��G���}�Rm��<�L[�S�(�������*b���=�	�m�w�p�b8�t�B�`����c�["2	�C�`�/O��&[z@�'�xg}��!2\��$D!N��n�$8��fS�0�1��B����e���������5B�`z�7��8��I`T����W�`�:%�Nz�#�	����^���C�������&@��M�j����m����aFH���W���I�I`T����8&H@�����%�8���W?�������1���!N��O�E�>
�F��n��#�4��(�	Mx�����u1�jz�'�B�3����$1�J�D!N��w��~D�?�� �	����gl;�
��m�\e�8A��+������`�����n�8A��B�,���b���\��ns����3�zt���i1�|k��{;��d�I�oq����W�qj1�ZL�im���v4"�J��jn}�JM���fS����'�q�FX��f������Uc����.�`�����B���o��K�?)�"4[MaH�B��Dc�����.]M'���~-�����h�DP��>~'������@S�lN6B��{�������o��/f�!�	��-"/n��.�.������J�����0{Y(�B�|sP���L��-I#���\cq�'r-�\�Q�4��]��w2�f-��jn�
w��|�'�f��~k}\��gGDfg���.�8�����
�!t�:�>"�	����<�E��	�.`�y
qBR��w�z���d�%�5���o
A�;}f�!r]��."�	�������'bC����
A�_\�d"�I�����`�t�S����H��l.5B����O���Zl������'�^�V#\�5;�].�]t�9�	���2��1cY(������3l�GnLN�����s�{�?���]�a�bPim���Y`R�(c{��P�
�#�j�}D������o
�����og�?b�dFB�����p?B�����%B�����P�~{��G��v[�S��>��G�L��4�! 
q�&�S�l����W�K�8A�{)_�?S�h Q�4��T ���LA����m	�.d��P;,	!NP��7���������4�8A�_^�4���f��|k
�|9�Lz"�)?>b2�LM�sm
�P~�!�Wx��aB��	�k1$
q�>����lB��	�x���������L�� ��[�o
���h��h�
SO�I��>ze/0�E��������'PH��YP{P6
SR�{�,4Z����N5}�'HNw8��)2	�C�`���?2�C��'x��h6S<d�'hr��ha6�z�$
q�F���q�F��A�k�8��Zn���w�9]�C\�) ��|�s�_. ���;�A�'�~�8�x$���r(�k1�Z(��`��m�Xlp
V����d��0��X���w0z3��(�	�y,���&�[,Xt��:L����ag�K
qB{�sA?���n�-�n��.`�w
q�%����}��iAo/�5�n�$s�b8�t	!N�}�W�s)���h	����!h���G&��L�%�6M~u�>�l�4G���"�	
��o
���!W=�Y B���z�6�f�#j�j���'hjwU�U�����P�����^w������A'=�9�	���+�]�A�bHim���:��1K�TsC0?��v0z3��&�5��~�^G�B�f�A���+l�VG��t6�D�Zu\��,�L�S�����)�	��~��L�P!�&�[C�K�!��)W��j��'h�����fc4EKE!N��~�v>S���$�&�kCx��^Id�FS� �8��;6��g��P;,	!NP���>��)Z���{�!N��>~� ���,@��4Y,}�S~��E�%�)t�#�C���/~���Z�JkC�������
�"�����0 S2h�����d�	�?�`���q����wV����v���.`Ou
q�r��U�Zl�)������o
A�{5���]����q�F�fd��lR�C%��'h��yP���N���6
����.����h
���F��[��}�	N����q�j�f�"5�>D�r1����!N�hL
�U����.B�Ua:�R�5���oa"rJ���0�'(roK��p-\����!(p�[Y~?�k�A����xG��4��Ma��!��s��F�#Jc/\v������cq�fcPW��V�&�y3�lz�'����*����`��|j��:�8��/��s�@S�p����4��M����	���(B�`��������	�xc�kC����"�AS���$���kCdz+�e�3�K���}�/[Ch^�8
��g��PC,
!Nh^fN`�U�l~�|	���6�8A�9A��aU�����/H��4�Wq����/at�C�C����������y��_��Z*�
A�1�������G��3�HS��A57����W�	�f���}k�_o�����:�j�$4;$�rf�!�	��eo�M�H*�<o�M7�=��������g�������ao�=�	������	s$&	��C�0{6	j]���Q�$��,���DB���=�	-�}`�������M��.E!N0l^h���I��	J�
-x����v2�b����g
q�+����'~�.�.��q�Ac|I�������
W$6	���X���a�kp|�����<���'|��������k1�����{�a�D&�A5��!?M�����S��aN�&(
q�e�&�0��f���(�	�a��1a9����)a�����B�p�8��K���D�x��!f?	�!p]���!�	���r��3a���B����
��;��3��>}m���\M��Nf{�Y[6�!N�d��M�$��J�"�p(����F��<�s��������������7�8�������z����i1�|k
�y�n���L��S2��G8�8A��Y/�`n�V����k1��6�F"�K�m�� �9a�T
������;��:��_��CvBof�A���������"������y�dq�f��L���7����q��������(^�"&N����)�	��R[%8�{;�
��'xj������yK��8AP?�����&���{��
A�_�2h�&�:��-�/[CPh^� ��zMeU;Z8&0fx!�	
�_Fw�S2�\��^s�4��%�G�����fg��e1$
q�F��uk�.���)v���C����i{�k1�Z*�
A����A5#��	�jP57}����A�B�A73� ���[C0�V�D�eK�t��.�8ACE�YQ�[�qc�!v�;��!�	��������]&O����)�	Y}�������pL���.����K�����x5E��q��)$�!&K�4K!N����?;$8	�U��4��O�f;��Z6!N���&6�'Z�!fKfP#�	-��
(X���r1����!Nh��V�����0D��������/�jarJ��� �'h2Wma�V��t-]�!��!�~\���n'�b�T
�������[�w���(��[�o
A�aL�"���Q����K����!�������T0y
��hCg�8a����N���J�z	C(�	�z��)3�b��t!N�K���p*Z��)�8A�����K;F��L����~q37���h���5F�4��-q�-�	3&3����KJp3K���.�.�����8��y�[����0'��C������b�����C��9��!N0#��;(a=����k1��6����Z�W�YPx�-Y�0�����������l>���0����o
A���t9�^���p���rk��]�_���T0)9o��M/����:���)���KV���8�B^��T��)�4	L�C�`���pft]��NR��W�����p�&�!N�'��%��)���]�B�`��������-@��8A��[����0?S�����8A�{+���L�&�i�8��_^[6��)���|����\��g��04���'(����@�b��RZc����+��L��I`T��`���l{�p�73�(�	�}����W6IdvES��A�Mr��]������l:I!N�7�����o/������.`�p
q��#����h6G�G���o
A�{�!��]����q�@�9���LvE���AP�tw{��Gh�"�I�������%���4o��"#�	
��QZ�"�nfh#�	
�s��G�r1����!N0���Ol{;��������!h4V�s�9L@�_2:%�Nz�s�4:\;/�����������4��*��t��K�Z.`�I�j3W!N�l~N���E��\l6)L���F�4Y<&�8�`2:o���F��ME���K��;���z*OA����'�����CqCc2EU���8��{���LUFW�I�8��������*`C����
A������LQf�����
������TU6�l
A��e��LYj�B!�	��5bf��s�������	�8�	��C[,6�E�/W�N���i��~a��V����k1��6����eC��&���x�����/�����.fo���(�'hvw���)�6���!h6�%��Lq&g�I�8�y'o-��m���eLmv;�S�����!�p�,�h����o
�%x�	��b��t!N���7��M��dP��~u#qF��Moj�6�~u�&��Y4���r#�	/��`-
��ea�c�9B��B�����
������5�8�q���EJ��)��,1�Y)��F����)r��C�������j��r-�������EbgxP�IhvJ��,��jn���{1������eq�f�\SX�nd�9	�F���eq�F�7�r
6e/�y�7���q�����lz{��EL���
���!N���!����	���2���=�	U|_(��09b��0���8A2_YY�&GeL`��?%��C�`�/V�f2\����8��{�����i���E�'���^�-l�'3�)�	��I`�#t�t��F�Z�����'���1q[)�b��{��.G��:��'�_W�A�m���t-���X������2�A�������HG��73�H��V�[,4���n�)_$4� fmf�Q�4����=��y3�lzI!N���3��=?�g��a��_glcN&i
y��
�#2���0J�@}�C�z&��.�]M'a�V0���C�:B�/	
�����`����h2L��0��:�������0LB�0���e��~�]��f��a�fF8��
�+���\��N�]Z��_^�6����K��-�W^tJ��g���A������t-���X0���S���Z��k�N�94z���x�	�0-"����z���%G���+P�f���e��$�hm?;���t�M�9�v2�',�sx��n`�w@�9�$��D}k-���"`q�d�!v]��^"�	�no6��P��(�	��������0'"�����
A�_��d�&��es��E�{���AD�����q�"��~\u��?`��8A�����nu����)v���C������|�'t-]�!��!ht����w4fT���{���������0��]{�C�C���T-�]Z�����'Lc�HC�4;.	-=ax�<�~"�	�X��cuaV�����'�k-�`�;;�Nf��	���������Y���sq��moCA6���YL2$
q��nc&��CT�QI����V�oe�~v6M����q�fw\���I���q�"����D.�`�!v�v���'h��%U�fs�f1�|k�����������)v���C����]��]�A�bHim���:s��v8�#�b�jX57
����������7Q��F���/��^�%��1�2#
!N0���a��;��@�����$B�`������������~z���>��?]>�k�����w��?]�OM�O���[�}����Y�����?���eU��3�>_��������{�����������������je�g�r-���]���D��8�'�~]������o�����������~��������x�C~�f�^���K�����oo�������_��������������������.�|��4�<��{-��R�F���/��2�p���N����K����[o�������C
�?�4�u�_/�r���{���|�����[�k�������~��mk��%Gm}\��aw�����������cm���w�����������O�:&t~�����5@*��T���_�fl�_���������c2�|�������rMG���}�
o��}v��o�'�N��������iy�l����2~��?Co�{������Q���-�jy��Zz���+�\�������>�������������l����a�\�������Wr=���y?�_�w�%�]���O����|x����o�W4_:������=��g]��p[���O��?�������������{��t������~�9�r�w����]����97�z|�����n������#�k�T���z����16|��G
n8������z;�x?�7�������������|8*��6�nbG
�1g����+�3Q���u�a�2�������.(3A����[f����z/�������V_��Q�_�ccCe���m|�"�A�������2m�5��~M��g��Z~�����Bx���~8�%3�9�eF[�����ubV�2A������U��������B������,4Z����B�N�,4\���B8�G�*��<1������dx6'3�5�<>�����*�?n�Yh��g�����2�W3�]�����_��,4�������u�����hx�,�
�Xo8_�>��m=h��)i��'9:�i����O#4.�������4���B�Nn8���������~J!��_<�F8�a�FLGO����4��A�?~�4B��1��i�F��+ n��b<�!�A�_���B�����	�B���_�Z�B����J!�gz�5�L!�������)���|~�����L!4������L!�?���>xfd
!���,l�)���o�{�D�L�N��B���c)�F�'�N���B��:��L!����Bd����+8��Y�������L!�W���4�����8�q��C�B���G���B��|�`�2��>u��\����n_���x������k�#.t9�OY������q��X��,G2�6<<����W�"�4�c�a�q>#�����g���WD��C���9�s�S.����rI�-�G��]�=g��C��i�si�F���G
��v�x�&�A�+�����,OL�e�!���x/���7�2���m�����|������2����3�/�v������L;����9�2��2�o�N�&�q����C����h�|�7���	+��������2��������Cx��O�e�!l��sV.��c|u�J;�|�^��\����f�oI������i;��4�����?4,b��U��1l��Y.�,�K�l��%q�&������YpI�?mW8�x���v�U7���$D�����"	���s���>2	4����|"l��$D���i�����X�!�'7\�.�D�"	��h�G%!nK��5��2	4���c�LB4�_��hx~�C���a�I������!hy|Q�JB�gybY�LB�mO$Od"���Xe"��?'>�I�����O�|"<�_f�\&!��>?�++D"���f�x2	^������e�q�M�$���@��h�|�������$���W��h�_OHB-������G�*	�=�(�I�p|�5�>a9�s�H{�$Dx%�d�5�_����hX����'2	�����J�BCc��J����8i�C�3U�a�O��������_�
�D�3>�~C��p�@d ���:%6<�
��@����,D"lx��E"lx���zt�&�Xd ��GS�O�5?�O�����y|�<����:����OF��R~���t��V�c��"�5|J����s�WD-O�*_uD-����p^#>����y��LO�SE^#�eO\G�UG<��L�G�����O�������"�����]��+��������;�|f�����"��h�<����l�n��_u�|��x��Qr�u|�,2�/�"3�5�:Qtb���g��X����X���>>h��m�]���F�o��3��X�(���R$4Z�9����L��}=)JCD
��X���q��G�9��,�����ytb.r�6,r�]d���v4.N�1�zf��Q�N�Y�����X0�9��O�(N>b�Q�
���8��&���N#D��� �A���*�A��kre!h���Q��������n�D">�Ue*!��KT*!<���L%m�5��J%���Ys�@D|�L|��R	�9����P�J��f�[�TB������/�h�_�D�Z��R����"��)�/�h��	�����R	A����T*�q/9�K�����TBx�O;e*!<�u7�����{:r�������SwW�J���������[�Y�(jL��tt��L$4<a>�Z�x��	�]����<��d��d>�6|B�����P�!~�~
/��"��d�����;�c��O�H#�;*D!�I��'8�p����9�F=��C����,Z
O{�>�;���s6��Z�>>u�������Bx�f��"���s��������)���|~���o8�Cn����R�*��l~N�u)����5���)���o{
ap�����@�B8��R��,S���	)�s��2�����g����k�B��D�F�B8���R�U��V���8Q�b��]?�\�t|w�s��V#�����FU
!l��Nc��
�����Zc�j;����~�����Z��e�e#�g���"�>./��������o��Sw�l�k"��������l����!���8e_�����C�|�!lxxT�dC���-DVv(����=M����=��C����1[
�g��O)/5|Ne�����"��<^�Ze��wN]��Ndd�!h����\�!j������74��L�G�D��/3�q�|C�����e�!�]��Y*"�
���	��S��*��h��%��\U��qw=!�����f��c>����
N����������e�!'-Yh����K�Wrb�P������<N�t]���>K_n�"a�?g>��A4����
�kh4=QG26�������g"�6|��q�'�������_g��5<�`F&���X�z�x����;e����Gobi�H*���J*�Ow���N*��ST���ER���t����s�
��;%��<�F\&��'^��Bx������Bx	��UR!���;���B����
2���/3���B��Ye�����J]�T���Y���B�>uBI�S��*��hy~��so�*�p��U&N����B���.2������*�t����B8>�����B�����2�^����L*���+~��T/�T]�ThX�x%���{��Y��p����(���v���0�I&�^h4=���>S;>�M��C���
,�c>c-C��)5"���X�>��P#2nx�L�Nn�]���("�>��������p�V��������������������������?��OC�t�yo���4Hc�����z�\J���={,C���w�"5����Q���NE&jx���������N���$\�"i3�kpU����OD.&j�Y�r~�G����E"��c���r�m�j�t{���+=��i]�s4�e���-E�����PD�&j����z�B��� ��>x����?������WF�3966.E��u�����\������7����������"m����m�;�LJh;����F�������Z�O�����DZ(����O��$��~�XO*�5q����/�"����W)�����!�"��Q���-<������v�|�3�U�kZ����8���mcbO��1���|M|����K��	E�c>�����*f�|�9cs�s����97q?%nT��&��A9�Z�XP/����+���DR���c��F=>'_&�	����g��T�"h���u����>�+�LUm��x����)?=������ktQJ���e��}�{����?'�����������{������v����~Z�{r�z�����|)�����Hf(�r�L��P4�]Fr�[�J���D��_�G-��f����?�%5/�m_8!���k<�����}���D���0��D�Z�q���3>>�UV"<�S��[�5�����s��	e5���x�
����Iv��f|��W�����3��G)�����RNnX����7�X����l��
�������xT�7|;�x'��<��z|�N�(%~���q��}�`�M���(�A
�4)�A
���\���g�"h���:��W��e�j����I�hz0�J[&���Lm�)�Dm��d�5�8��t�$Cx������_�Co���W�W �s�cf��"h��c���I������-E�*���o'�_��n��i�B�uS<2���������1�,db!�]���Ub!l{�;=�X��-��}��eb!�=��U�����I[����gJ���=��X8a�Cx��<���������B����B$�g�������u�k�3�8#�6<|�E�!��'�7<��]���O�
%nxx%��3�
����G�b��o�o��E����'��6,����d���~�����dC��x�)�l/.�
A��n��b|�!�
A���������X a�����C������d�!h�����	�p�M��	��|O}�"��2��K%�s�mb+<�`�Q?gv��	��F�}�.����h@$N���C�F8��G�NxB����		��=v��������"�������@d���{?��f<�OJ04��D5��w��[[���~����}�����c��)F��C�������5Ec���5E���K:��)\�6{���m;��>����v�E�!<�v	��gx��H3���H3�
������	���
�����s,�a��kQD���#�i�z��y����7;����Q����E�!j��4C��)i������H3D-��f��_+�Q��kFS�f�G�9���71Ui��|��,O�Zg|b-�H3������2���m_%1�]h|��1���L3��~F����L3�n��-�4C�����f8�+��{��6�f��>'����I3�����i��;�A�H3���L�w��<S�#����g�;"���>Ol�#�q��&��e6}�'V�e
Q'&�����Y��"���?��E6[M�8��j��"��/M�
�����:�
��l@�!>'|Dq������
s�!n���B���3;�u8wT�������e
]���]�gD
O���/T'sA���2�4<�r���F�cG,s�S187������ra�_��2��=SM�2��g>DV�����s��l,�?g�k|��4���t�������<��e^#<����e^#��Ne|d^#h��������C���X�$�?��������_��n4n�'d7�vBv�y>?�����u�Q����w]��8������r���T����4�qz���k��;�NP%:���yb��Jt4i�?T����_3��p}���4���XQ7}J}��]`�>e9lz*�����_��3JR��0|M�3����}��Be��;����3SH����������
s����E����9�6<��	�S������ncY	Q�2l�a���#D�����*T�m��v!+T�m�>nY�2j����Nd�"h���6�2I��}f�LRm��I��
����>�
��P������E�9�y�)+T�g����Be����"����Be|�?��\�or��/�oT��qvNIQ4��D�J��������������f���tE�5<�����x9!]������tE�w�_I�tE�����r�73�s5�����h\���%2m^�?gVP��E��cb�L[��y�6/>��3��^�4|J��d�~� 
K�#����g���'�X{6|B����F�),[���T��
��/�	_|��p=�x'lo5|B�Z���^ 4:^�P.�_1,H4���O����@���p�,}�~^0�vG�!�L�Xe"h���Gj�D����!r�D8'�>2������Xb;j�������Q�_�gf�����9STQf������������s����]|�e��G��5_������"�p��\����9�%Z��3���������'��\C��8^�s
=�<e��e-��b��/'�����!���9��FB�N�f;e�����X��_���&���c�D��)�-����&"��6�8w\���
s"lx�N��A��p>���>�����B� �=b��8�aUu���>4]�2jv�u�LD
����������,n��b<�!A���D�k�'"F�8T""|'%"���L-Y�����3�Ve""�;#�DDx���)�ClG�yT��`�DDx�����Fx��vV����m�h��{�=�E�f{B������Gk[�DD���B���r��8�����) �/~�m�LD4~��T����[|�������/vO>>�[��v�fF)��Cx�z���0.���}�z1�-(g����������:4����F�6|�"�p�yy�s���;�V1^�r9:�s���8�3���3�a�g�}8�a�w8�T����
����?�w�]�����]���P!"j��"��'����S�Q��,��-����:Q�w�z���<U����L���y���oS�(8�����D�!>��<G?�������HJ��;������;�W���n�"���~NT��y�����;�n����p��uS�"���+���y����<��;���sjC�m���c;��U��{~.��=v�#^���S������"<�.�n�����9Q:G&�[�L�(�t�o_��Z�b�����b�����0�O���O(�jz8Y�0O?!��������y�����T.GG|��q�'l�������x�b���������S�y����$�!�S1��z���Q����8���'��0���+`F������F�����,1q;<��U��h4<_\"j��
�q����*��=^�L�4����,��9������UT��m���/3����F��/s����Fx���������osk|d~#h���1�h��v8z���(/�=�P�0��'���,G�n>�A��r4Z�/)����~�!��1rB�#�����T��y���l�c{������u-�����F��_-�K*b��K*FK&��F��;�
��h�t?O��
����1�u��F�!f��'4w�����S���1Q�R��|�y��r���D��x�|����w�g$<���7�Y���9��5������G������8�,����
����
sV"����J�
�a��
e��������f���f����<+`�7����mpB.�A��f&�2I�=��JRm���� *`����LzET��G����b�Ex��L<��
����<������/�4�k��sR�DQ
3����mU��q%��O�e��1F�k]�tE���$�a6�������U�"���''"u�<��D�.��Sh�m�h�R�_����}*u�����a~z5��"<�	g3�Q�_�L�h��L�5������$����������>��1�n@a���o|a�R����?i���E���������%bQFc�4��>�0��Of(Nn�v|�N�8�e���s�Xd(�	���3���4��M���(��&��[�\74<���\7����\74<����q-�)��3�	z����n�!�A�_fR6r
E����Bvj
E8OJM�������r�D��O����&���>����n"���&6�S���n�k����.$<��T��.�q�/���w
�
�v8�>���������;gcp^'��_�e1�������L:���svm���7W�����2k�f;��J6��naF><�oSl�a/�gZ�1�a����0�
������`|�#s�mk���1�'c8y!ra�g|�q���9���3ra�g|�q�9�9���_��S!r'7\�/�	�/�mX��]��f��������d�!h��A�������������d����
���U�!|=�DC��s����@&�����`*
�p9)����UD*��8�	�h������|���~�m�P�L4�7��OWd��q�=���7[�hZ��'C$-�P����|���wyN�����R
�/��8���9�/�q=�R
]��O�|��q�'�i���v�4�L5�������TCxy?OX�L5�O]�E)9�6<��g����;&L���������	�yo�gd���"�6<��Yd�S1�qg���?�����J_�;*d����'2'7\�.��8�������
�y���8�l������~9�6<�>�3a�?������l�<�
��q�Wa�3��lC����64F��,��
��7�a��64���p�64����#�mh����
�����3�����9Q^Od����Wu�u�64o��9d�=^f�������64o��_S�|����{�t!�F��d����@8�������gc\�/2��)�����.����5jC4�ckC�.q	����R��q�?�|r�������}"��������TQMd$^��uBF�y���H4n��+N��h<[�o�8��%���������X6��yXCBC($-����*��j���Mv������l�O�}�p���f������_D"��-��q�i�*��!���3��/"Q}�/"Q�*^D�����9.�����E�s}{)�TO�����n���\�s������&�n��7�' �?K)<	�����a(��-���Gq�W������O��P
jE)�=s��R@{nl�;��+g���� ��@Q
F��K�(c^4��s��,$y��R@}����\���"���d��p�9k����O$������������	y�:�O�Nz����0�'��+j	�{�>�����`6X�����s��6�+uTe���%@_�<}�?���>�=<S����XFQJ�$
�rJ�@�u$��������?H^s�f��<gT�|}��.��~�i \AOp?����]���n+/|��������F����[��N�2}����{N�������FK��i���p2?�@{��R%~��=7j��Os��QJqj;�@p��p^T��2��{���]�����1������/Yk�8c>u*�G���Q7b;g���+=�������jT����Y�#P�G�S��j�o��� ;������!��
E���A����j�/��E��6Pg� �u�Cw"��F��"���(��G�^��N���Q~wWxc<o�q=�gy#�C�v�������
(���/��}���+m���=�czG ��V���6�^����+n��|z���� �wU��^���Z������~Zk���7����6��:��6�v�t��g����
�=w�`
���O��`�{��P���[���������6��Xs?6�����XM�HP=�a)m$���?A�F��l��`�����{7�V���-�������0��c9�-�otG(Z3xZ�85�T>���QN��T_��Cx?'Fe�P}a�`4����-�pEeC�P�����+����6��
\�(��A(����+^��� 9�p����������+J��/��g����5���66a�<�V����wJ@�(c�CQa������f�	���B�.�y
_��3�Q�jS&�/�7�����e��t���95*]����*��>�|��;'��.�6��.�6KD�.���.�6]�p��m�G�>9�'��?�J/�a"O{(f����8�SM�aL+y��a|0�b���k����/c��Kfn��t�!X4y+��7��bG��X���(e(n����8�?���i1��7�5��$�7�sY������<����i���|���N7"o@a�
3����_1i�"�����7�^4��a�
�e���7�p�mYx	����H8_O.����!�Rvl��1��Q2-�������H���h�����H/?�^
c���a�(���75�=����1����d+���K���1�(��Q����"�$	�e�d��g���B�_�3�����y.�`���W�B�<��w��K�i���������`a���X��������X��p��yP/��?���+o��
�q�I�����2Jp���1j���L�z�}�?�#Hys�����?
4�WT�F�"�# �������3�K�`�4�h ������?�z����x�������_
$l�U�h�Y%	���o����0�+V���������
����o���9D)���s�V��+��QZ48�3c�N80���������3��t�/� ���Q����j��L� b�����Z�%��U+�2mr��!��r�4�y`���a:�����t�#��������|�LHU��kq�/8�s��fLP�����[68�O����t������)9���1���O��[�F�X���`��tE+����p�������S�@:]� w�����{�>�7Q9��|�F���p�x�����2:9��m/������r�A�(Q�h-P/J����'��xQ�v�%k�c�^��=w� �=���*��K������q�T��11>�+{���������Q���\�����:4
��=�J����P��-8�!����Z��J7���u�~�.2�~��<)���r��Q�����o��=�o~��#~��}�����:�����m9�s�������_:H�=�z��({����)+j�����:�r
|S�gl��7�p���F
�(���_5����
��
�*�����(i��$_�q������
���qA�F�k(]n�5\v��A��D�=�Z��y�+-l��g1-l�����Z�\qr->���G�Y�O�������g��
�=w��4��c_4`�'��������mQ���[�N�
xG�����P_<���,w�c\�vqY<0��#H��u�X!������O��,�Q�<��c�b�6&*V@m�
A�>�y��+��;�
�A������g������
9�i1N��G�]�v���E13&;u��WyU��9�� �����U6���"����!e�k�k�U���k.��Y�2�2�-�/e2�OP�����#�.���2�pEEC��P��c��8���RqQ�.�N
5�p��NP	�*P	�;�5�p�JSQ���;jX��`���4��q0�@�����~r�~�f�+�����K�^B@G|��4���VH������kc&��V��R4��p4D)1�N4D9��_����O@?9F-�����_`���8{��.8��4��;���"x.����E|~�o�W�b��K�QC0�o�� 
3p�0	���N����?��~Q�S�*86i��������cj3~k�A������k�i���(�l`��.
.p�`�40j��6s8���f([0h������9�p�����K�`���\�����3�~�U����
�}e�=s�(sm�S�c��=Hs�x���X}{[�I*��������B��)s��R1#J��k��D��2R��H9���mk�n�]S������2����9���/���>��,�1\�yOn�g�x����
�w�1�UAC�n��hqk���q��5D�%���na��W�oA���p���35�pj(V��1Nj�we��G���?��g����@
(\�j�XP
g��&�r�O�� ��q�z��m�I��a�p��J�I�"�@����B��?������js[���(���h��C�b|��E;������s���{�����/nG��]��/����$��C=y�b��w5�Q��X;�M������h���CA��\
��n��Cl(���tX#���
%k�XAp6��6uXsA��K�5p-f��q��>&'�V��7E�|?�!�
6��N�������3^�����1�e�~?�2^��V4�Q��x|q��	w��<��2�	s5�eT�7P8���b�0
�@�|�I���+��8]�"xC��i�70������z@rB�(Q�H��GI�3���%k��e�qLf��G�(I{�L8P ���I����u@cb4�+�����
$@{c�� �����R��W�
7��+����H�J\9Go��zL���P\�+���<W���)@�M�����.�	|���$@��������n!P�B�v>�����_�����,��u�u'�S�aT_;�b��Yw��3"��3�b7����3�M�5r�i��Wb�/��H�/��p�F��	RLl(�b�`��S��OpUT�v�T�G�bSRL��(��Yc�
�1��
x�}x�Y�h����&�z�{�i��m��!N��C��{i�]��|��<`(^@��QK!x�gN;����/���y�r����B��!]���(����|�4�(^@��S�x��F�k�@����4j�f��Q#H��A��](�k��[D�e��A`j��uP���0!��
a�.�h�����B�.�^{[��e�b6�9�*�����:���+�L�f���c�
�\�_���!�-.���L_�p.���(�C!\��5�p�L��<�/6��VE�
W4i�p�*�8�y%����P�������������)�@�%�$lL��CQ�LA�5�����/�e�X ����	
�=sb/����@#~�bj<(�Dbx�)f�����(�H}~����`V_;F0��a@�Q��V04����:�)'�!�!��~�?9F9�`����f`m�B0C�����������;����W�1��k�_��wS�B��7<8�,���qTid�����u(l�L�� >�����Q�*���Iw�4���i��@?���_hy�h��NA0�~$?��:�y��c
,\�Q|�
4�^q~�O�o]�x�e��
@8�cW��5��k@[U
4�)���Ih�_Pe<��������� dM-4������\��h
o�F��U����9�*h�\x������0��OF��J	
AJ�����\T�P����vM=C�T���0{gk����p���k�'I{�@#
��Y�
���R4����
�~N,[��?C�p1��-}NoE���s�~R��[�U�bj���-95�p�\M~:+P
����p�����(�F�beK\G7��.�P8o�p���^��P����}������������_���������?)���S��������O�.������;P�}/��+�����U�
R����SA�K�ou��8�����|���16�?'����+r�8�;��
��v�_�����c�~����q�y��~����~v���;���u��|l���R_x�/���qUQ�o��(&P��������h���f$q�����.T�����&��(�����|]��8R���������h���[��0���c�g��|����KKvz���4�_<���� ���~�]f1�~���3J�!�s���xXD��Q�����$�ju�������w�xiF��|U���"J�v�	t��p�A�tI��� ����x]�w�_�����e���U/��u����M'����D!4(�����+BSz��I�~�n��$@un|���h/���I�[��VG$(����I�#��G�l�	P_�������m�������M��Gy����ws�9����4f4�w���2������o9~F�e�*2�N�����G�K���{7�OU������"�L(����T����Y��b��g�G��gch�2� 3�O������kQ����3AR�E��@��Y`��Z�-�����G'H��C���;�$qQf�y��,�DD�E�>��c	����c��Q.��"P78��{�������]!���<i�&��;���F�l|�����q����0P8��y]���'��K�=T0��_�},��M�B�E�@|t���]�fE��
]\w��8�.��D�\[X@8�;h�N��� ���r"�,���v��w�c����g��g�
-���cJv4�P��!P����i��E
(P}elW��@����0"��q�
#�k_�P�>��k/K�r�v�����5�sn�x�:�v�����i�+���G�����{�&��,���Fk�����!�;�B?���}iYu���}�(���v����Yb�v���'��g�F��U����A��Y��0M���?`��7���b���#�J!��9��#���A��$l�����j�x�kP_ny�x/+l5P�`
i��et/����#J��V����}W�2	�5�/� ��iG�G"�T&A�3�O��zk0�6%���6|/�V�1�L�G|c���Hp�'��h!��|�dM<�`����[��/�k"]���[�D�n���H����}�D��+�5H��"g��T�F$��7&�������
����;e����q���5"\����N�|�z�-�"zC�@�A���(1R��kc�+����oe�~_3�"�� �a*a$��Z�j ���U��\� X8�m�lp
O�n����C���|�pDo�|��i�.�����5����H��v�]v8���� [�@8��(;�gvm����j��Y�ho��R�0�������_9�k���l�~�;�u��;��O�
�I����M�P}iT�w���V��`�Ad�����K�C�q�f�G�C�q��������a�v~"Q��xO�N��0�����a��k#�w��W��z�O�����e9vVc�S���z�����z~JV�u��G�>L����="������_��t�z���.h�`���X�����=���/v�uQ�������z�>��U�C�������A������^v7��?�n�o�Wo	�V��:7��������u�b
����jKA���6Gz���#�4j:����W��pAMF��p�7:Q�Dfn�����>u�Fn`RY����q�8+�@�{��o9�q������1=G,'88��r�:�v�����1�0O���S*���.o�����1�����Q�����qN�K�XND��o�:@mU�t�s��o�@��a������at�(���a ��c���.^���OA�t�^��yD[0��"�Q��#H\>�@������l�L^���f�I���Q^��p�<��F�@�<�8�]�|���<��:P8���8��
�G��c���vFHt<����{�#(�������3$Ay��w4=��e����n���a�dFwa�X��y�?���D��d�'y��1���;eJ)@�x��a�&NI�R
T�:�k�R�����R
����P
�rc��R
�����R� 8D(E���I�a-Z��R`��NQ�R
���6�2��[)E��1�\G)@���qB)0C:����~�I��5���^
�j�����v�"���|��R���(��(��j��1
��l6FQ{��(����(P��Q�pM������hU5�&�/+�D����D�7��D����D�#�t�T�����y{<rtB�?@��	����l�e��N���s��w���*&�1�9�%Z#���cF�4�5���\<�F��q���@����	T��G�>"����W���xS���NxG�I�:�L��\�	3���a���09��8aF�$�;q<�}�^P�P+��&��o�����u�`��:���I~nXw"x��$
!��W�e�q���]!�7��������V�v����l��-�x���Kx>W����#0#�KZ{Hp��r�F$j�Y�
WTM��(�B$@���8�������-����������{�G*���4�P�p�7f��(�b5��=�>��$���JA��J������=3\ �R����_ &��qv��(8�K��4F�_M� ���[!��X���c: ������V?��'����N��0
V_8� �Q����^�(��V0�(���q�Mj������l��c�S�IG�
Gp������C>�:3.Gp�u��G����:Ve��;��9�#YW�5�����Zv�>�-��
G���Hs�����B��pYl-�HM*F�F���~�U�K���V�|���!	�C��
I���`\(_q~��n�2���O+#_�q?��,����C7���J��C��~�9���!@��,���F�c�!@{f��:�����f*��h���w"���"#n�[P�O�uQ�wt�t�+����,��g���r�@��P��k��T9�o����h����r�0��3:����������U�w�?+��x;��:��[�^9f�{e���A�^S�!p��{8���H��^�5��ue��u��p�7q��<��?���_����X���1��a�@��o������J�X���o���
���D���N��J�gC�P"x��K0N��Q06���Q$QeA�.
�%X8�����/�����t�w��>-/�;��!$��h�����!��}��"_�������.=�D�+X}c���c�0�:�I���������o�L�H���F��	��Sf��W��*�����2��qB|���p�����7��ri����(�;<s��������z��"����U��(��(���jW���f=����o����Q��������4W��N4��Hi	uH���E~������)���}����E�D�>]�1���]E�H=F�@��!,���2����=P8MSz�G����<P�h
ya��K���e�I��m��^��bli��P�Q��{�^�`�Za���������������
���L����;�J1@{k�:.A�~�����%����H:.���wR��o;V�����'[��L4Y�0��X��#��k`���0�����|b?��=:��&��+������Xp>���]i�O���J%P}f�������K�^�AA�J`6ZP�J`.����J`�g�����Q&�Q	�z��&�}nQ��J�+#�tTs���a�������8��O����`��1��������D���k*�T�`+T"��~1F��(��k��A���
W���p���b`�J���R���hF�K�H����7$8	�D��Q"Q+,D�T�E$�w���#G$Z[��O�B��S��R�:�B�s�BB�B8�F��p���V!��>{|kM^��G����l�F�� ����S����GD��)X�#"�IIcH��o�W������OX�!�J�I�8�PC�����1$����H�C�s������i����h����f��.�o�h�M�:�-�I�y��[$J��T��HY�F _���[���x�7�d�;�!�o���B~x���Gs����9���B"��)�DD�����(xn��	i ���3I��;��T�w&_�Q����������{����t,.���W������,�%��Y�������
'@��������:8����� ��1C����/�zV���9L)��x/����	����qwh���3�����3Y}k�����/oEA��+�@ugVN�&P}��,E��v<M�z�,B�D�q��,h"�����h�cN��	|��"���h����B`�g�iX)�o���R��w��
�O��@��'���y�;
�-j4X����:s�>\�����(D�.�8�eT�����j�U�+�#���
H��j�P6��H:�������g��l*x�>��WE�M_q�6b7^�<F
�������l*X��9�o_�fF(D�pG!~6@�v�)����*��|QfG!@yj�t�g�UBG!0��^^)F�p�S
�;���Q��������O��)+W
�wti��
��[�QG!@}i���B���Z������W��~7L�E"����5<����IJ!�	��m:
�+�IP)D�I��])�o
��Q�����R���i�Q
�����qg�'�N2��q�}:g&+\�B�"c��R��S���o�R�Y�]&?V��c�� i����E�p�Y&�kD�A�p�(V���tax�yc�� �
���"_�q�>�D/�X�2�}�'��8��'Y����m��}|�TO���?+n����W���:J@�w�$������������or�'��L].X�)�P�V_Q��K@}f��v����������P_=�`�	�G�'_�	����+<A��shUx��N)TOu��D�I��,�����"������o�aH�-��5e��u��������)�oV�;����"�����b� ���i�Q@}��L�y�0���[���m~����������m�s:�|3��w�pR��-�5�����T_[���n�~i��$��~��6���sN�
�& �w�Pn�W����^^�F��"MN�/r���'�[��3��&��U	J�2_��(%���(_�(%�y�(%�t�(��1nh�����|4�s��C�h[�A����3�|�M������	T_:&�
&@}f�L�j���:0�����cAH}���^��o���.�@��e�![cT�5��@��cx�`�~�(���	|�jL79�
&�so&0;�s�>7�:0��wet�u`���l�y��ie��`W���vxW'�r2�
&�9����;�V;0��<������Z�L�y�`�d�5��	�p��y��E��}4���V�6�4
�a��� mL@mp�M���H���!�����R'�
�����Y_���78��p�T�'���;�����fB�%N�$�w�V,A�Sg���������8��{q�IH�	G{��� ��^;��$8�g^�	���(�U ���P�����$��a2"@����4���:)@"����\i3!u�-I�L���Un0"����_�L�����$����"m&|�o���8���Q�������S�����8���� ��B��l>{���q��=*/���|;{���M&����W�;�N_���Q�<�Z4�
BD�yw���p��4��sD������h;n���x[���z�G�bn�F��E�
���6�p~��et�JJ!X8]
!�����>9��"o@!��k�59��_�@{fhw���F_k�@{u�g�s�~�;���^_�w���Fb�������CF?����?���
?���7h��>wF�(~��5��!P7@��P7�Y?��������3"T�C�}}�M���T��/Q�{������u��o��%��-B��_I.��s�W,I�0TID��0,#���;}�n�� ��U���@��J"x��C<?y��3����@������J�F"P����C��"B"0-�[@�D�;9�� $��f�B"j��D�+3oCq����Hr��E>B"P�`)�i��\Y(����3�l�5$�k<6I�q|�Hh����F?����F���pi�����������=�z�I����T_:ck�=��5+C����z1"uc�({@��C6�=�6[T!����C����>��6�5�=�v���cx�Fy�qx�Ng�a�{kM�8|�����c��T_9sL7k<�W��Tw�^;���K'2����p�P}�x�
n@q�	4�H�_�K�{D���
A�X
L5Y8}��p[�'�������P8���
W?���`�(W N�B�C�� �y��t�����&�}�=����2G3^] ��_�j��%i/����m�oA-&H�i1�SW�	����!��z4Qtt`�W��b���
F��>u��(���>s\Ak���1RP�\{�����>w>�+���::P}��G���L`����_�Mm`�X�b�>���Dq�"G,&8��$L-&8��H����~D&����}i���������=_�����\%����wa��s����7R��������}����\��&�9���w�h5���G��,�#H[>�@���!���7�xW���+|7�cs3� ����:+�u^������YW��ysW���I_�p�R�'.�����	Pu��;8�K�[S�hom���%�����	���iaW8�+������9���o�f�����w�/Y9��*@}m5�w��}m��t�����E�>s��U������
T��.@��q�\EA^H�U`&6F)��Ll�QT�������#>3J�;T�1��
(�����P���U`vt�m:T\��������3�PT�Y`k��u��T>�t���c���
�vkt������*�$���`5��"Z=F ]0������TQgA(\Q�����U���t��e237�@ig����Gg���p���s\7�������r������w���q��B�%��$���UbA�S��A�CH�Nr;��PB+8&����R��s�Y����(�F��	R_<�KV��	V_:�O���1%>���">E�����������q�Z�C$J��>��!�\�Mp~Y���t����Q��^�������������e����0
��S���"z���SD���a�3���.���{N��
V_s{�PD�l�<	�`�U��V�N�e>{Fx�X=#��
���HEt�i��_s���
.(��s�3L�<^W�e�~��_$���",���<�V�1���.��`�|#�et���'�?�p6W�E����m�
!@6�eJ!�?u#a�{(���Qc�A�^8Gm���h��� x�9F�� 0�S��"T�:�� @}~��~A�>7��v"P7�A����/R��ts���1|Q�Y�������@��`L�Qf��W��6���Tp�������gS���|'v�-����a�)*��>6!8�����!;�s�|��3�_!���&������i$nUH\��y��j�`�|u�����l^}�kNc
�������+���
2���>�+�`0h�.��
�M%����_�7�����+Fu\N*3����B@8���(O
s��>���p�����i������d��Coc��T_8V�J�~N���T�$�|JP���T����n�,�
0�o�������M���e3r����\�������f8I��D�z��R6�(��o��*��Uc�H%a�Mf%�}'%-��c�(��������W��!X)��|@�������[����-p�5��O��E���1�w�!x_OK���'�/��U�����2|��~Bt4Q��e���#P�``�?��a��RxD���.p���O���g�p�����G�p6��/��{��|���{M�L���3Iun|�R�
�v�;��[��^-*H{j���EG|�|���\�OQ��Q_9
��<�������y�j����@�����c�>qN��<�k�O���;�]��/gQ�A3����:��)E�
��(�c�a��&���E3���[>bJ�1�m��������I�q_?��?$$Z1N;I3��53y8�&Jno�#����3B	V����#ggz���1�4k�y�p����������
@���w�l����d��_�����@�tY��.p��
��SpJ����p����2�^�$=3���H���df)Io���@P��!���5(��`�Q������)������R��c��Q
������H?��sQ�(F|�|uTJ����Fvti3�|W������4��XDD���]����k_;��Y���R��2�;C{;f�����Q��������+��"�"����������Y`&6�0�Y`&^���Y`��O#	�Y`�7�IP�,0�������c��1��������53yT�d�.��W���"�Ks'��5��c���&�*��'}�Y�a���[_�\5#��F���\5�qM����n���P��W������Lf@X�A"�U�st�#oo����i�@��:L�Y:�����=�9��ZJH��U����m_���h���v����p��������h@)���h���������*�JX���X��g(��
V�bVD����.����F���
Vw����$J���f�s��/
T�9�����?_@��$��8*���������sXp��\5Y}i�~������D9�X��c��%���;W���;{`�dd���wv���h,a��U���p�k��O/�Q<�*������j��`�WN���	<Ut��p���&
<5�M��E�����:.p�`��.��u^F7��S����B]-~�>�	���xj��:�M�C�W�v�:���Q\-H{��u*�����+(���;�;��[�9R���Md P}n

�
pp���
������[�@��SE�� �f1������U��P�N*���k�x'~�������7������|'r2+�����t�A�>��F��>K��>���_��8���Z���h�(�o
�����Z�W�D$���������<�����3^��OI��0���S(�.O0�/��wj���f40Q+,`"8��`�+�
��^L�p����4�0���w`���_�m0�y�`��^�������h�����P��
&0�����	��S�����n�

&�~N��(�@��5T������qLTL��c��	��S�L@�gZ�k��	P���L�r~�R&���n����g�'(y�
&0��G7u`3n�����QA����5m:�+����"P}�LQ\{~�p�"P}i|��X���T�8EYD��6���t4HL���)�g�����`r������O�(��V0���������F!P��d����B����a��+(
WP�qAsX�����-H@=
endstream
endobj
50
0
obj
44635
endobj
51
0
obj
[
]
endobj
7
0
obj
<<
/Font
<<
/Font0
10
0
R
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
14
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
19
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
24
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
29
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
34
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
39
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
44
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
49
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
10
0
obj
<<
/Type
/Font
/Subtype
/Type0
/BaseFont
/MUFUZY+Arial-ItalicMT
/Encoding
/Identity-H
/DescendantFonts
[
52
0
R
]
/ToUnicode
53
0
R
>>
endobj
11
0
obj
<<
/Type
/Font
/Subtype
/Type0
/BaseFont
/MUFUZY+ArialMT
/Encoding
/Identity-H
/DescendantFonts
[
56
0
R
]
/ToUnicode
57
0
R
>>
endobj
53
0
obj
<<
/Filter
/FlateDecode
/Length
60
0
R
>>
stream
x�}��j�0�����.�1���F���}0�����bz��/��]�������l�<4����Q�ho��0���v�7���j����[
��,��`hl?����[4N��tu��nH��5xc�t��k#���`(#BP
}L�$���f)l��h7a^�������s�F
��
��{ 5�G��1A��+;���G����dQ���<���1��B�HT�H�H%�D�m�D%G�C�&*8R/�t��������tmsq)4�Z�u�I���%����V'A�Q,�S��+��hU]VZ~���	���qxia���y��r�[���
2��
endstream
endobj
55
0
obj
<<
/Filter
/FlateDecode
/Length
61
0
R
>>
stream
x��}y`SU��s����I��M��&i�R�B��Pi���eGj�T�"�#�"�
� ��6�* �K� Q�Q��q\G�e�]tt�����$��m��{���h��>g������<���%FDfZA9&-Z�;�����I�4L�3m���f�B�G�/�.[2�}��(�������L�����QD��=����v~�$�QO9�g-X<�����?M����fO��
B��FG���	��$�H!Z��}s�M�3h�}������1����<r����)�"������1D�!ZO���]�`2M�%t=>O�g������OKi+�����.�h���2I?N�U,�TJ�c�"����F�BV��@�G���������]N�2��F�������y�[��w&�}�^�C0�$J�L�h�t������������F�K����c���o��*c�?��O2QU���OW�0�S��R���C�-��:���3�H=�?U�B��iz����;6�M�A~�4GV�iz��c���t>Ci5��t58v���J�#OG�M2!Qg����`�c����,�yX.����l��~�/�+�V�oI����%�+���!�+}%���V=_��������!�}��K�4�G����
ZI�i-V�N|������&�O�o�.�O_����ug}Y��.c���l/��^b/�z>���_��X��U&�B!��_�P�wd}dW�/�M�������M/x��v�Z����������0>�-z�>���8���X��:�"���`#�X6�-`K�*v���`w�0k�h�`����O�i�586s+�s/����3����i|
���{�A|��W��-�!��/%IN|��<i�t�4N�--��H�������{������r�|��M~D~I�\�^�*7(7+�+*��:����t��I}S����Tm�v��J{�D���A����3m������7����KN������[�Mr�L����J5����0����El�J��3t��2����:�������e;�H�_nf��e�����K�����Co���,��i4�����<��U�KO��T3��u�Hy|�d����S�9vG+�K�O����~7[*}���5�wY_eMU��5�a���v�A�K5��K�Dj���=�#>����t�<My����0e:�������T����?����i�t������_�A�g�]���S�����I�1��\f���Fi�l��G�CO��k,H������f�����Q��K��^r����l;��_Q���4&2��){�/����Yi'��c;����~���
�f�.���B����cV�K�X>
��4���|��H�H�b'_N�����B�/��;��o���%={w����K��`A���y�9�l�����!#��v��:S��v[b��b6i��UeTX�j����r^`���"���	�
�>U��&�k0���mB��mZ��-C--��WFe�}�_�������Y����@�/|�H5�r��ID����J��
_�5�*�U����l���vY-�X:�.�I+RaW`�.����wU������Q���aO�B!,�VN�1���"����\f'&�)0 lMh��MX��n|3�t�z������79hbC0ar`��q�aiB��#)�~+���'�g�xx���5�k3�u��>�]�n�/�edm�Z��������V5��B���E���JtRS����R_�����,H��0�Z�������G���u�����@������n��FO��9��s�.GR���l�X"!�ubJK��2��T��v21��`�A�7����0���2�7�����S�pWx2�aF�<�a���(���\G�����N~qn��X�����DRG���>����!�@,$������\����
�q�@�>Q������~�X���B4��������&f��PQ�.�D��xM�Q�"^�r{C������6����;�R*��	��_�����9��W��!�����E�{���R����R��x�d�B��4�������!���4D�(a����aP�Zg���������.���-6�p��������^�:	��x��c����SW��n]U�W��a��&}����X��o�����l��h�~���p��:Lb:�i�4`W���+���[��'v����9����A]�~Q�(�-�"�9�f����dTe��0je���Ojbd���e�&5�h��(�Oga���+��Zit�.�c]��j�d7)r��G"�&{yL�"�9Il`���'�A��e�e�g��6�Q9��q�����O����L?���?���|�a����y
��F6��2�*WM&M1[d�dKH�T�]1;nK`��!fi	NMK�	��%q�C��aN$G�`���W�&�X��i�,IdJ���z�;�q�!wy�C|�`\�e'Y��4��tM�����^�����t0)����8lO+O?���j��5���u
�������_���j�����~���G>g���R��{�r�?Ul{d,?��y��������]��������><�M��E������)1A6�����2U�c�I�?�����V2iO���&>~���f�)��e�e�h^Ff��v*�bPU<NrU�t��2\:�q������������E����3�'�^�f*�^�K���ek�.�#���V_���_�b+��?�� 
��t����r��H��"a�#���_��������J�%�8���
@S}����O�I=:4��?Vg����oj�C!��.y)3����V���R�|���O~������&evV�)���R�re�t��"����C�$�-=F�b�����0v�~����oE�v��O�����e�8�O� J\J���� �Y�_R���c^�#9��{Z�K��d�<��V��$E:?�W]�$�������S6��;��&����wl�|�����=����sH���2b&�������z��E�}��\��bg �"�u���r�Th���H���KH�q��%�lVGr�=����p���onJZ����d�=�fu�U��*�����d������?--5�9�x���v��L99f�+.G�d{s�����q`������4��-8\����P����6Sk1:��0��d��j6��el6J��x����B��:U%����������~�gd�
��O{����"?��4����f��>}����3����7�s��H�r��+��-]�.�K��e�E���:��!���BN#�,l�����T�
~!�����(\�L&�I�
*d��-�br*������sE�Ck�b��������t�����B	��-�{������'h�tG��L�I�����nP�+���Kc[.��C�l�C���z��b������6�/�>�����o�����K��SEL_�!w�|=�J`���+��?}��8��������U��O]%���j�����'r/�u���dh���Y�%�H�-��.`j���t��_�QX`����%;�f��RJ��{z~0XhItZ,�i9^s�J��ky��^�������&��PV�O��e�eQ�#0'�zV()�e9�fgIY�b�y���~T�m�I�IX���H�]Z~����[T�H���b��OT_�������=z�*��S��g�������W���"�$5��
����f�n�^�$�%O�y���&���\���|����z�k�3�k=};�����w��?�0c���
���~hM��F''�2/�V��}J��O;.��3fN�����_��}dw�m�KJ�L���qx<r�B�145]h�,q���s��K�?i��)�(�<��������R?�����)d��!GR�)�9#�@�r�^UK�'��k��}��u(�P�ax�S����P�9O��&sJJ�������4���*SM�a5j����`2������Ezi�n.���9XI��.�C�;��O���X,���aE�O��T����],���J�$,TG-E3� [[,�Z����U�~�-GF,Z~�y3�t.��VM�y�����tR4����W6|�y|��y�����7\���������{z>x�y���!K�4�9-�6Uv;3���r}�1�q�y����:����Y-�5���h+��
�	���d�U�x���XW��i[�O��`�%���m������~[?�����3�-F��t�KL�w�$�0���Pc(��V������1�m���l�%��\����n�:����{��x���	S���|�j��� Q�a�� Qv����������%�Y��\�%�&gz�	M����4�3��H=�v�Mu�X�[
Sk,S-J��R�Z�X.HU�v{���4'P����m��[_��&�������o���&�����S�|y�Y��e����	'�O�����"(�����gs����8 �bJ10g�0������������|j��S�����H��K/X6��k&��9c�v���S���C�/<��g�����,������v)�����l:������
��&�R+���g_���#�=��s��z��HyR����5�2����NR2K�gR�'�`#���h9#�0iS��d��,��	�����o
e8}��@��r�z��a�c�����/*��|D�c�������0|��cA!*��
_�"�S-����jTR�?�,U���z|�3��ft��~�Z����=����3b3�W1�����7���Q^�-w-eK;$��qvI=�������������N�R���w����%�J�d�9UJNMKKB��k�d5�������P����gfN^(��#���A�,pJ0��RS�ii�d���(�Ew�q��_m���8���8�}S6	�������+K\�'�:�i����y���\h~��%�p Z��I�b- �?yO�=^w��I������,q���|�I��o�;����='�[��T!A=#��@����e������������������R���)y+z*���=ynrnj9�ye�.�.����O�w{<����r�����*N,�:5w�K��&ZTo���6{<��0\���u��y]E���\�x#��&��������K�������8��-�����rX\������4\����#�����_�����<P�15~� �Q�)B|t2���G
m����x�U��.�\*�3�qKJZ���b���b��t����6�g���6l�����
��~s�W�un������v���?N��]Q�u��W�,iH��/)mL����'�ld�w<�����Op�(=�d����z��?��s������M�f����,Oc�o"7�\�`Ve�HZc�K�6M[jZ
;����$U��6����%��s�;���		�D�31���*�l"$�VBBm�y��9������_J����'�N���U���0�f��������z��������~���t������s#�����8��.��c��;#�Zk�����<�����jR %�>TM�v����]s�o��5��*&��R0����c������
|����5������M�>K�����>�Y�c�I67��CC�z�n^a>n���"�f�#�Cf���"�L+�I�\�2s��I����j��\���e�����x�\!����{�MpS��bL�
��E����]�����y�r�_��k�������Q���%9�������kjv�����n��<����'kST�z2���M�)��Sp.+)�XJ��*�{���w��#�|��R���.d�
2|�8)`���E?�du��)!�b�R�z�v��f��]
Hw[>�|cQf���nS_��]*xam(��@�h1K&Y�e�DS"i�V	�r��~%&{��!����?��	��l0#4�a6�,E�d+�UE�M�j��I��\�X�F�c�����4U���$&`o��Ud��o��y�XS(h�')LY_n�)Q�g��qv��$`�5�EF�y���
m62���B�R^V����K��+"tjI��AK5V�Tf*�*l.t���"�bI��X��'��T�/K~���/@D5�}Y�<�����%Vg ���lp���$V2[zl.|,p��%����\��uG�����)|��V�jLcl%O�]]��Y�)���Tl�2��B��':zH�
8/(<e>G)�#����
x}N�(�1��gON�8�NQ�d))�\���&$�I-�f	�����Jt����N�8R8����Do�#�&���r�(�w���� 8�sx�����:'�(����&[��f�B�'n���������<���B1a��5C-�~V9�N|go������M�8��k]���2�l����e{ou��1��K�g�y����q��I��u��|!�&�G����������=B�'b�Y�R���N�F�h=5�9�^��T�/J����'=�tF���$�������e�U�Q:�X���p�`�������"�$�����JL�m
`���ZH���5�����rv`���5���Vk�>k(�b�d.�a7��,X^F�	�abv �q�����,���5��;[;�<0a���k�nH\y��������&�_��������z8��H2l�dx���=�h�~J�O4>Q�e;�YC��l�*��,��96�&��;;���T��"����Y{$��W�XY�>
u.�Ay~��4�6G����ySZET��
�9�u��`f)���4��$���o�"&�������>r��+���w��>�&V�zo�|���=������_�yf��O�x����?��M�G���8��<2C��%��������������+}R{z+�����J���L-�����	�z$&�Ap����-q���F��U�;/�7��9��U��%'q)����b����eF}���Y���f��S��t����������N�5�C��C���/v��<�������\�O]�E������`=	���X}�q�fxw������E��Q�9tq.�����y��G/���������<���<���r�������P���l���>���C��+�����[s��_��B�b��NgB���u��M7�e51-q������I���ro��bK���f�s�������`�c�Z��#(�=���d(6�*Bx��
4���i�������a�z<���Q��p|]o8[��Q�'�OW����*�Pb��k��2������>n��wV�
(�eq|+F#	[pK�Qw��5�����������\�����W"'#5�
�����B�z������I�Ta��[����--��zn��� [�@�D���*��V�����=Q���X�Z���v�w��K�J��T�2s���J��:�{S4�������]�
E�kf�>��2������i��r�<�t��XRN���H�����'��<��s�C��7��Gr�I���-g%��$�{=��h�aSJ�c�,/��/�=AI�`�O����1{���Y�8'7�~����{��U�%�Xx���YW�U3�����+�L�����,�t�=h����%4����=/�����~��_l�%}�oRvP:�
\`�j_d_c��vG�}�p��>I�Iay��l-LJ�u����I�������Fg�9��g�N\`=�3 �d��9�V�y�Y27����������g�q��� N2�^!=��1��=JD��R"�07z:�>���e���+7fn,yi���]�\�e7�>�g~e`9���)WE��o�;'������\-��`�"����|��Q�Q����5xw�k�s���b�)���:ZJ���E�	�j!+r�&
N�S=n�4�3
��j,w�GG��4u�q41qfn���M�x�^n��-Jz~���8\�i��������������DS����bvH�uU�q�=��")�
W<.���[z?S���z��8|�b�G�D�'���,+��8a ���>hx�6G�`�>v2U=v���-r�s�����W��!y��Cn��O�l���}���0u��|Js�����,�)Y���3�h3���4����>�0{�w;�N��=W�\'��^��*�Z������:?6b�$���H��]���@x������`��R�\.������j_��JN'[�����d��&Y,��H�Mr:��I�dI9�'��O�����JO�M:����On<la�&����2������O{2d���x26�7���������G<���=�*�T|����K0�$x{2����q:�@��8����x����s�c��s��/������[
qh�Ue�6���)\�*���L����=������2��;���	D�d]<u�^�|r�s�}�������>;f^�|+�bP����?s�����d|
��yO��}�����i�w������
p��E��@�?��?�,���Z�/r��ScMyi���Y�<��3�L:����l
���@�Y��/��$K����.����h�<��.���
�N�;�`�/��g�`>�M^�������:�.Fz���������D(���>@cQ>�����q�����t��E:�m@�V�B����9����Z�I���/��<s,P�>��^\�vb=E9;B��#�	�UH�B����i2����x"�&x��
���86��7#-M���4�;� P����7 ��9��	����������@�W�����+���T��@���~�E�%��}@(�h17�4s<)O�+M�?�q>���}��`>U�wR�t�z�n�z+}�r���o�>�mTs�1��Ex���x�"C&�������)���w^�O�7�[�
�|�Q����;�L������XwV��	�3m&~��60J���c]��|��g�����������bqr����E�0px<���P ��7�o7�(��W���MC> B��Z2�C�!c��a
�w�9����2`'p?�|"���Y1����l	��SC�g�^<������*����=��S�����C�[P��z	����/�����h�g��c|}�f�d}E��y�B7�E�w�����h�t
U���<Ba�7�r��\��NW��������
�]@{�]��/
~�Jw���_������;�Ob���|���	mv8Z'�@���i��
�k�N���g������$���9�
�����@�)�n7�dM�r�DgT�B�G	Q�/CN� �E��Z(m����4���-x��j����G��_�����sZ��92�V��4.�m���1�2��g��J���o�A�g�>@G0�U��E>��D��q�<WN�#���<��V.�R��@��������(t���B��R�o�����c��a��illo�����<��=��eB���W��4I}��Kh�:�}A
j1e`�_���K�/b��{��
>����U����g/�E��y�:vc�S�F�ji�{O�}h���T)�A�J��7��b����(�/�UFQ�tZQ��6Q���A��[��	����}��2�����-�m@E���},c��������b�Mk����1�'�Cy�d���sb.�AOcNu����W�gi5�>�S���G`�s��y�5�ya������3l�!����Doi�t�6����5�D_��]@���z�[g�,}
�����K���3Ry�vX:�}�ZC�t �nP�}����o��g���6>�nS���%Z"GK���'�K���d���Obz�RRQ�o� �;��D�m����������S��U�i����r���� +��AT��7�DA�@�Cs�0���]P?Zr�WH_��i�����5�%��L�F�H��H���+���i�d�F�9��&���r
�/�I��P�(��{�;��~Z�v�L�������S����^�����}�
��r������A������^G���?�v�<�% ��7�kc�q�3����T*����s�����s-�$1������\�'�����m 7J##[���o��>A��[�]P�C���W�%�V��g���������E���F��2�s��LE9��O��B��^���e(��M(�:7E�3��O�(���7W7UE����G�ex�����#_�����)q�����wP_T#��.d�'~��:�y{���Vv�7��'mm�M���������o�V>h�C|�l����8�#��ts?��2���n���G1j�Q����!�k��],�!t����+A�|�'A���=v���������^�k#�GhK+��b��h����������*�_E��~�����x11����y������q�X�v�"��
1�s����*�s�����G������b���;�����q����[�c]��b������"�N���J��l�x��'�a���<�<t��2a>&G���B�d��K#n\__�����>�������V6������3����g���~Er��{,f�{��U?����7������y����\���k��^1�q�����2���=�#H���g	r�l�p���*��"�G��I 1M�.b���a,���������� _^�S���K�i�5yu��0+����q��Q�B�}�g�%��p<K|�U����c�^����|.0���Q�����������
�r�b������s���r��d�e�������?�c�3�N�����t��8B�)��_a�����8�+��Ga����M)�
�#@���aOR ����>��������3��Yj�� �w3���!����VgT	�����+���-��%�?�s���B�������=�M_�'��_~(��tk[���(�#�s���K����
Z�(4�-b��m�rA����8~��/�������y��������__u[���0�_�sN[�<�W�1�-P>��8��G�����c������/�G~	�mc���HI@%�.�~�}�?��hs��+"|�O����r?(|�������|��I��N�v3�<`r�����?R���������c#c����� �.Dz������0�����}4o@���XD}�l����|7 ����P��E���g)������� <��O�O�����T��S������B������V5t�T/���u�ie��i�|}�>��P@,2����4({���W0����=Ck��y�#�E�����C�}�vW�'�A�J2�3�~��	WX.��O��	��/Uh�41I�R�o�~\Si�2��wS�����!�������fuKG��L��sRq�=qjz���P��F����@��y.�w�3�R�sl4!�u�/�5�qHl�+
�m�<T����a�g�a?���W�����h~�Q���>�>���}���y��[�Fj]�c��E<o��/RHq�7N���K}�S�8+0��#�OC>���<C�# �g�m������0|��7>Pa?[��?�76�X���	�7oKcc2�'>0�7X��]4X�	z53�`�>e&������>��aJ�<n�r�_��V�&�����X��X�%x4b2�;t����������t�Gv�,���#����w/#�����Fu������-��#���F�!Fe�����\Y �Z�juQ�
m���������k��XN�a�����.�R�r���g�z%;�&������T��c~��fGiD��X!�mi�s�_:��?�6���Z��
-my��4��������������6~�U�K�@��wl1��s�Xl�Bc~y��q=g�}gg��c����������*j^nE?0�����E������
8�����@���6�N����Z��g��~�U�N�F�jE����������]��3�����x��>���
�1�C�dc�[��XJ3L�c�=���v��-�{��q����2�x�������<:�W�[���5�_{k�/�&|�=l��=g��o�*�+p��/��g���>�%9���KS����h�r�Dn�O�������_�}c���N1���GC?��+���W�}D4&�����F��c�o��B
�*2��t/���"N����1o lV,��MrP��8�Q�2>V�*&����e-���bCW�A���`x�c�.
��1G�	� ��B��.@���#OE}U�c����h�����t�e���'��93�����U��g�B��k�J5���B����p�]�8{�O]1����si�Qv�Q?H���-"����c�_|�-��@�~���E_�E�[�w����Sq6�g�|E�E�����A�����q��>�{��h)LK����pZ*�=<|�6vZ'�D�>����6����>��{9p+:�q���S���<Q���� e�j����:����/�G����>���"'�����(���I�������.��R>?M�0��t��?G�����a�O@��RW}�\"��O�&m�+�_>��V�a��&
�zX���+�������4
>��b���� #_�W�S��"�;����3��G�wu�P�3�M��Q���3m(�����%����J����p�y���xn�'o#�g����:<�*d{tc�TP��L�q�'���7��L9"��E]�}�
���t��o�~F?���)��5^@����W^���T��J��z�je����������9�+��1Lr���s��wk����\�������}Q���<��k�<N?!�i�;�L�:�v!/l�����	�����N501�j�>�E�~����Y�������l�V)�2
2���S	���� ���J�#�|`.��|���8
� � �� ��o,�j��l��2�
��
9�"0�}�k����$��m�-���l�o����2����,����z@�b��U��S�@}�[�����D��������Oh���3w����W����O=�@�#f�������$2R���5�������aL_��V$��V�������?(���S��1So�}�i������\�x�t��x�~�B���9H#p�������7�g�����{k�/->�D�����:N[LC��.��]�
z������w����(D�q�����x�C�/�-����\`��n��!w.���~�Bk�V����Z`w�_%��6��:-iE)YQ8?#J�'rA��D��B���w��(�����hG;���v���hG;���v���hG;���v���hG;���v���hG;��_����G_S�%�89�����|(�$����c��
��K�CM|G�#����5���1!������vz8�d���p`< ����7���w�7H����W:dhw#���(5�����������"���{�h��[4����|+�x���q-����omL���fv���mL��n?��E�{q����
YP�<\��S�K���7W����x�Zn\���=V�����2���"�Zn\�����h�N��>����,�L����Q�^*d!/���������&f
���v�
�v�}�{A����A������[�H�U#��D.%'�BM��}�5��k����w��7�>t@������y���>#K��;w{���jv{��m2�����M��R��yOx��}����������h����&o��V[
�����{�ww���{��r�Qu�$d�N�Mc�zk}M��a>����x���JTV41��7������qkwq���n�y�.^���hw��c��QoGt�m�R��hN4�lz[��C��]��\��_��W��K��S��U�T�m
j�r�M����lr�l���d2�&��Mdr�_�
��:Qeq��������z��"M�.�p�T��G`�����z�/���@��VX8���/��V7i��pI�:����vc7��4��61����yD���o����z���!�~���:J[T�.O��TZU�3�����ip��'��#���*�6j��4dG#�Id7��;3|k�����u��"�g�U�o�W��=�������v�T��%������j,��b��h�� hgz��E;*7�f��Y�]�h���K�Q�hH���.�=$��v��(�h��z�U�]�����mD�.3�x�h��M�U�F/�F���M:��tii���Ibg�x�m}�6�����3e@0X9C����]&P7p\��9��3�=��o[�zY|=X����T^�6���VQ��u_�{y����u�cU��w�/� ���&��r�����?���r�8	}����C��-���~�������[�K�*����:�u��Y��M��ha��BIji�Rf6���/d���C���P�Qk.�o\�A���`1
endstream
endobj
52
0
obj
<<
/Type
/Font
/Subtype
/CIDFontType2
/BaseFont
/MUFUZY+Arial-ItalicMT
/CIDSystemInfo
<<
/Registry
(Adobe)
/Ordering
(UCS)
/Supplement
0
>>
/FontDescriptor
54
0
R
/CIDToGIDMap
/Identity
/DW
556
/W
[
0
[
750
0
0
277
]
4
35
0
36
[
666
]
37
39
0
40
[
666
0
777
]
43
52
0
53
[
722
]
54
56
0
57
[
666
]
58
65
0
66
[
556
0
556
556
500
556
556
277
556
556
222
0
500
0
833
]
81
83
556
84
[
0
333
500
277
556
0
722
]
]
>>
endobj
54
0
obj
<<
/Type
/FontDescriptor
/FontName
/MUFUZY+Arial-ItalicMT
/Flags
68
/FontBBox
[
-517
-324
1358
997
]
/Ascent
728
/Descent
-207
/ItalicAngle
-12.0
/CapHeight
715
/StemV
80
/FontFile2
55
0
R
>>
endobj
57
0
obj
<<
/Filter
/FlateDecode
/Length
62
0
R
>>
stream
x�}R�N�0��)z\ZpMH����?}hl"�)���������M
��33e������'�a�5������c��[��c2����+����h��i��r����'/�������[�b�S0�����P��>z����7��D�l�	�������m�|+^<�XR3z40�FCh\�q)^���8���j;
���)O�~o���<B��"���?�R�LJR���@���P�V�2��g��O��@YvC�V�Z�R�'��(�.
�`�H��N	${n�_4���u����cq,xp�$���m��_]�?�D�
endstream
endobj
59
0
obj
<<
/Filter
/FlateDecode
/Length
63
0
R
>>
stream
x���|UE�?���s�����K���!��h.U�4)$�HUQQ@����kC�(6�%@����.�Zvw��`]���UH��y��Bl������������3sf�����	+,	����_������!e��Y�g�~M�jLG\1��k&MV��p���s��	�����0d��2���l�����)3��W~z�P���^>��	����,��������;�z+�g��8+��A�1������"���	���H}�������/�9��+l���Ix�M�ga7���c�M�������]�w��%����k����H��a=��z��u/�`Y8�%,�%���j	8!z�������+a,|$�]��f�E����Sw�6�c�S�s�����w���S�Clq<���� ��,���X-��,59�#� ��1�0��=<�o���0[ ���<��K��Z�PS`5�b��|�e���A�c>��������2��xjC�8D�=�����7���qqS��	g�T����Gx���ir�JLI������a$��	l��'�J�������y��f^��Y��!lo�g�5��`������|��o��%�v���G���SJF���W$�����/����F�6���������w�S�_���/�p<
�d^��
c�)l[��d��� ����#�t��4E�-�A�������M���[�/�F7�m�K�?S%��0�a1��X�_��;��|�L��\�gYl$�o`��G���)V��d��/�w�{v��*<�g�l���s���w�!~�����-%�r�R��f���I��w�����)�������'MO�^4W�-`y����E�6A���{��4��>��ag!�8�	�;
��^��M�&s��EY;�]�33�Mc��|����j������8Kc����<]��#/�=����O���*~��o�%�d��R@*���j���<��^�Nz]�@�D:)����l�cr��/'���q����s�s�X�k���M��,U��2w1�gjf�1�a�n~�2��O�
v@�vXZ,������T��7�H���V��R��l9����\�|�~��|��}|-?�����l8L����)~y#F������<~���������U��Gi�^�:�	�5xW�������lc!v�?!
E*��|�i4dI�����z����NYV"fQ.�`%�_R
$>����)�������r������v(e�sx����
�H	�W�Ty��z��S�u,�I&?��j�������6�PzG��^$7]�� \Kavj1\c-��M���<�0J�R����B�*cQ�mG���r��4K�H9 ]�D	��G9!#ME���P���
0��b(u���.�1�����d�"ut@y�,���$�;�I���:���9�L}�S�T������{�^_��<������9�������*�2u��%�p)�#���`��=P�4�oN��f��~�RO�b�SR��x3�`�9�k\����{L���I���<���������-�^#G�HV�wn�9�+�u-/+-����c����v��y�9�Y�XfFzZ4~����]N��f���,q������_'�������9�`B���uq,�{v���xQ-~v�$����fR��l���x%Tvh�����;'������z�T����� �^%�NLgea�x�����:6>����USV��_��n���k��C{�l�c����P���,t	��}3�U����.���FP'���P[7t��>�����;��c�.���rz���
���)������T��5����+T�t|�Q�S;a��:iB5��I`���B�	������F/k�4MZ�'<5N�+����
��i����l����_��^��8px{�K�G��%�e����J���9}�d��x�5�g������DW����dm�F�;S�!�'�b���������	��7�a���l�$����th�Y�h����g����g"%�Sj���3�hD9�� ����q$�s���Q0����V��j���jqE��Y{�_�v�rj_g�Ss�+����c�8�d�^����%�N�I
���D����H����x���whU�����1����8�����ge�����K1S�h�h-�K��@�8Q]����=���Hz��x��||Rr=�����7��V��>S�����<��=8<g��1��}V���v���r��n���T���h)��)�&��H�c�+Sf��N���A��
fR�(a��u��~ZXm���75��S+�i���{���9g���c��FU9p��+lg=CR�:��GH�0btV�W�D����R{�����8e����V�g����������C��(�V�����b��	
�E�����;�������7�!������+�q�����zn�a��mN��������^a���[8���������F��$E)�R*�L�20��Gn�Q?mg`�x*������(�e.k�Z�j�q,����(��1�F�nI=�%�; 5r&l��n��dy�0`�tO��=��&8qyU�:�����&�B�h1���U�UQ>�MKk����p�G�iw$�9�}��+*j_��K�HDbi�p^!����#_�%���<_
	Ig�zk�3�
��w�+�q��+�.N�'k��8�����5S+��*��i��VT�uL\����)�������]f"���1�!S���rrwBr �<6L�,�*�(���,�t�A�\�cA���H�?�H,f5��.�%�����|������.�e�+e��]����v,]��U����7B�����������2|��
�T���<��K�w����4�����[}���*���n_�=x������y�'�k���\����,>K��� �Y��iV���n'�Gj���x����`6~DyV�o��mC3m2`�p�'A^2�+��+��l!��:|�N^�X�Z���J�K�����4#S���P!���N����9����{�TR_$=�7�)oV)L�R;��Z�?�:�=G�+��U
7s"��-�)���Ng�����n>�����)8���*�b\��������6+?}�	|�Bo�����o��]�W�T��A!�5���;��xDMG���m�#�� ��p�'��2�������d5��������H������������/�]��v
�Z��~�{�r��^�����m�m�{�h�pi�4������
�J�i�Bs�����NVV����Q
1E�T��*���q���
=s�b2�M�@�D��QVe�|+�;~tM�����-��$������F?Q]m�J���z�!�����'
�}*q�G���6+#�����-�zN{s�[������z��j��Lf�>3nkS�����?={��p�}�����o�.%��I�R�
�M��i#�M|!���}����S6]^���X�gdf��%��98{�&��F���PC�p��"!5��Jzy��r	��5OF�x
�u���L�.��������"�]��-�gk�(~0S9����B�SA�	5�����(���K����T}�7G��I�<����~���p���'2�,d��N0#g�X�0����W(!JS!il|�q���:�>�2�I4����7I��b*�o�$

Q��Lz����'�����\��m�P<�z8��P"�����PL$���po	�o����r�a���p���I���Gf�����_�}'Z�GR����FI�Qo��d�sL�(��v+��_���n���v�pMw����^������h�h���c�}�����j���*L�Y<�����L�jQ�W������%=*1n��K�L��o�:��<
,���h�[w�F��j#F��67�&/1+{�/�8��[���V����|!�x.*�;6��!��TOh�V�X������K���2W�� �C��v�V3G���@V~W��.��r�sA]G)f�O6���Cy��������!������y��/>26��g{T^����G'M�����|�����oX>�3q���gri/���Ka!�t
�����	'i�����7��v96��L��] 3]�l�nj��q:���J�7��wb��b�����UU�1�.��}�>o��7QB��/49��>��N���"�Ui�����i�����k�K�+���=����� :������e��dk=���d��19��o�����(M8L��Xb����fY��;.>3��ab��"�Q�lT57W5��b;�A����KO��V��:�X�-�7�.�
'��,�W�o`w����!�O$j��r���c� �VP� u�pa��I���u�Eq���AD f
M�Q��{�/���������
K�M]�������_�>���UM_��B��~`Y��������_v��7���<yK���:f���=M�F�B%�j��r��v�G���34?NE�����8�I�sE�VM���lO�f��,��&�"B�ZE���h��j�S�W�����%/�78�l��%3���UI�K�,9�;��Yz�?���%m �X^��
|���������a��
��F���5�4'�s����������������q.qjLm0qd;���\
l�X��&�q���R�LjC=Qy��SQ�t{XFy�v�q�qC����x+P�����VH�*$9#��^Q���u�~G�^�X4�����pd�c��B���f���$p�P�J=����a������w��W�T��=&m?=����(��i�Nr���,����N'}>��^���F��Rg�H2D)���"���A#�H�D)�0�"���zS%��gK���p��4�,�e������nY�Lw������q)Bb�r!�C\�,���	�v^��"�&cE���'|r��x/�b��]EQ���������F��^��U�����]n'�����t�sq���0}P;�2{�D��������T�w���B%,�J�AX
��!T�����Y9��=�y������p��-\�/5� ����%��e��	�$��]����lZ�2��@���~3��F�!���7�?�����O���i�1��;�0���N���-RW�����[�T�=�t����y��-�I�B�
���".�D����O����e1�4�Q��?�K��-$Y*6mK�8��bnc��q3�N�t��f���;m��Tj%�'jfH%�
	���������~�%��j��{k��:L����d�w�w|�wD|�Tk��L����Y�L_bY���������-�d�B���RY����s�Y��C���8�4�&��
���13R8�-���<����)+o�*(Ke����<��l_uU{�l���L���B0g
���*��U�q����!9$�!1�� �
i����5�����XK�;�)5��p�t:s�a-��9�9�@l/3i2/Y:9��Q��^c�d(��n���#/�=��\�x���?n:��-_<�Ac�!��������(wM�4��y������u���@��=���/���fcu���7m����-hz�0+���d2��-��	�N��V�s�$q��!���x�m�k�� 1��RF3�B�E\:3VO���t��`�$�T��+<���G�y$������:A������.�����}����+�i�6�jx�Y�{�!��G�� �� :I}wB��U�
1l����f�|�;v^�f������gNJo�GE���x�{)U,��PkN��-$yzs>*���.���X<����H��H��-|d����L�T��uf�E!'��A�M2�x�ml4(!��=$M.��f��r�o�����|�����f�1���
���E�
���Oe�8���B��Z��	�/=�}Fg�+�`��J�� k�������N&k'v=\���,��sW:�
�
+�Jy�e��f�R�m��=�|�l[��Q���b�:��I�D���c]G�b�
1�i��L#B�f��me�]|2$�J	�R�Y�$���q�5nn���
��d�$,LX��0��u���d W<�s����c#$<�����n
M84N4��f��[Q#&�,*]��V3g6���Y�Hw���@�x,��[����M�u�g��|5}����N��N��;/]:}��[&M^�������|���OHi��������M��]����Oc{�x���r�M�.[v����UC_t��'
qv&��u;����C�k���"��8]L\V3+Ua�S>�R��"����0����;����3����+�/Z8v�ch��y�49)�;�iZ�8�,${�{�s���O�3���k�Kr��0�1��t�e$#�(����x{5%BK���C�'nTI�~�R�#�� �X|�"a�yS�B�g������%��G/&s.^�3I�<8#:9�����+��f�>}>�U�����������A�{�Z��������+���!�qd�S��������A���3�<�]���c;M3=�����=g�������	 �!O�Q�ES��f>�$=��*q���yH��f#���P3��T��$l�
���e��1d�G���`��>����	����uyn�������c�]�_�<�.��y��<����l�z�,��,Gx�tf��GL]��i�wM�7m��n����{Z���d@�9]>
�+2����E���v���
g�@���E��j�5E��S��wZ�\�nu���S�@�F����Bs?�X�=�\������>(��2���:��^/�&!��In�T,'��U��������T'&Y�&�r,�����e.&���e��,x\���x��bW���ZW�eZ����I�7�v�r%RvM��r�������R��\���.��HYZ_��p{!U������y����V�.��MP'�AH@�$���\����h^VnC��oJ���L��K�Tf���V(�~�N������z�4��_�t$�+����)�T�X�r���w�6�<Q�w�� ��bO_W�*�Y��N�	�@(/�],h�XPw����������*�+~!����@@��"T��OP���P��4���OJ�n��\����e��p�;a<�l���QG�*�#����l��4��6P#m�`v���.]�/r���:���& ��r��tq�m��TY�s�������|���Yi�����_q������P����K��[2c��G�3n���%������<�����}�����?���n���t�pPq��9�j��M}!Cn����	!����w#&�*B�UzD����\��mgI
��0���vs8]�3W�l��6�50�L'H�	���>!�q�TB �{���b��|�B�}�C�}�C����
�����������4���Y�E�����m���c��S.����g��%7#���4��8�U��q���m�3cL��r�%��X+�e���&NN��Mr�`�\{"�jq�t%z�dI";��Z��`I"2�$f���X�����r�Y�\e�f53���YH�v�&j�;���5�X:��!��9�����t���sN�D�c����Wk��D�(�g�i;�2q�2����R���o�n�?�|y����6E�Y�q���ngKB;�f{������M��Oo����(��"-}d��`��l\v�9�����ry�E|��B������4�z�|���[�C�"G}G������8K���X"Z��������;�\g�`w^���8����_d���<�|���p�, ����pi=`���;��YJ�����y�Q�l"(D���=LE�9���#��D�1��xIDz��%)�Q��=a���`�u��h=�>f����H��4���25���o�Yp���n��G��Y&�b�����<3gj|%hF(sT�L$�l��vB)�D���Bq��T���<����O�vQ�"fg���B��Q����Z���&�]x��io�4������g����'���~����]���zp��}���W_����{IoD����&���&�Az�c5��H�Di�i�u�� e�O������H��;��'�rgo�H���A����c#�O���NH�����'�*��


��
J�t�*u��UUNK��a�H\"4�0D�R�����P,���Y��B]��N�{���4�NR�4�Nz��������Q���l��/�x���I���u�&LU����5���-*3�Z�zM�[�{�XwMV��nZ��-�����h��`����T6������W�8�RX�^���4�C,�h���o��%�3�t��������[��s��_��,�le��|����[<�F��g1&1+l���5�i�v��^S'��CrXdzB�]2�oe�Hq�S$�y����)�%�,t�E�D�Mk2+��8%�;��<������~�O����rH$Bb2C�t�A�w1��=[;w+���X�*`�$qo$�D��8..G�����^?*��6VTC\#��3��L�0���������ld�If�p"q�%����D�Z)��X�X
y�*��`��&������X��Q��4�(�4�`����Y�qN�'�����+9�PN��������MW]06�[����V��=���E��m}�_���$��e�������8�P�8B�P�\.��v9eQE�B����L��O7��v�����+$�h�y�di����������$M��P�~�P+����6�5J����&0�~�W+�G�����'��� �]��.eu��A>+�.XL� ��������O�8��t�/��i���?&Cb��`����5�1k���rq=`p�����*w�fV��x"�r��+$S=���j+�R\�<��HcN�-�M�����(]��;O�G�W%�YV���~?����Co�4�j����
5����]7����C���	��0�D2�m��E���"dd����i�FK�$�2(���*"4�7FP�qD�%�q��h@EO�4D���,B���e	��=w�=]h��XWY�Y��{�Y�[�`�YgYY��E��)�-fE��,s��H��D�70PL�lS�y&�����:y�|XV���er\>�9Y&�����_�/��Y��l�8&�����)��-��`N�8���N4_l#9:g��l��msyi@��^^__/}������]��7a��V�
J:[��Y���^[��Y+��|[��Yk�9wLb�����������e�Z���g�iwa�PT�M1�Z�G&y�MR�4����2��[6.i�Fol@)����yK�����h�{b�u�j���6��H	�
�K��������f�
�B����8q�M��]?�M*�h���Ov�O�fj��Z�c$2��K7iF"j$2���^�iF"j$�Y���H����H��Sa	���	�!�U#�5#�4�r#�����AvgY�|D>b�8t4n:d:�!K<�N�[%)'3]	��B�������ylU��<�
E]y�<�#�7,_�%��_8��9Lqa;�	,����aV��[Zx����V��4�AZsi��4��y��4!���^	K�4������WD�P�4G�>G���&r��A`�1�1��!(?�-U�B���}DA�A]/�6t���_(�$��Hn^��5��31�DK���,1�E�v��L�qp���?���54P��2qU��P�/����1�3`��b�%aC'��NHH���v�CK=����iW����5���=o���G�^������q����i{c��q����x�2���w6��[�!'����$)>����~*}�;.��)2������Q������p*,�-~�?�E��)A���r��u'|_1�!�aaI��Ua��]��f{�.��=[������{�?h�a�9T�bsm&�����a[����Y�u������xi (�&(h((�'(���z�G�f?oR�Z��&��K�=IokepHxd�4#��03�z��\�hT��Qu���T<V��f�I�����4��yu�)ZLw>�(a���T���+?�~�j�/��o�r�}���Tr}�\���=�z��y�����\��"l����0��N��9������^�-�8_�g�T[&+S-�2���{�<�G��kk�P���/�0����3�3����Y����K#L#l;.�&�&�.w�B������oP��������	�07M����������N]�E�^Ol�(��kwfm(�E��+�df`V�q����U��#�VTcm�0���rhZA���p���+�p�A��������� N�!���`� 6���^qr�������������L���M�M_����!�p�p���K�2��w�}�p�����]�7���{,x���~�tl��eK�l]�l�����j��q��7�L�|������k��`�5M���*����M�s��s���\���X��#'�$P��3cV|U��=�=m@h@Z��b�����i���������=�7��?���y�$�p<��	5(���}�������&��q��>��U0�eW� ��A"��b$������m�m�M���'�[^�%�D���'m�_��5���mD���H�y�W�Ku'����\9y{[���:v��1V���NX�$ ��0Lh&��	?#�"��TUlA�8x@�O��H���a�r��)�D��#j��Rm�q�I.�>��}�>�����#�X�e��5e��iW~t��;:z�j��O����i��+�
[�����S�^�����a���������Z�"a��>L*�1Uf9r��K.O�����c�Z�N������b��f-\ea�����x�Y��������k�$������`������SWY������?��;����s'�������+�\���	��jm�m��(/�<r����/9�g�s.�g���g���D��U��4��c�J}!m���$�����aa�[MZ"��%-�k$r�D���2tM*�P���������sGeO�^`��zs������(9��h8�i`��C�4>�s����c-c�cmc�cc��,���l��������������v]r���������r��.������������i��)��
����,4,�l#�c$r������	��Q���
��&��c,y���d{��(y��#��#6R�9Q��Xdf�������? ���/���*K2����S'��V�L��T�����c3.������p�=�g�>�����HN�h�EY47����J�y��!����:"��%���8���s�����S\�]�b0���.6��E��m��X�I���?�)�n�(��JLa���[��bYEe�K�����E%������LXA�qm��v���%�%Fc�*����r�����

�,��z�����J��E_w�G��j���{kf:�B���N�3�8DK$f�����{�N&t��8B�}J0i�h��3���9&�|��U}��d;�i`-4�1S2���r��Av��aigKc�V���� �f�����@�a*%/^��b	:������K��yyY����l>#	������������������������~��x�s�.������QS�]�vn��9{���+��x��������p��]s�3|�����Y{�3$[sS��"�b1�q�d�h2�E6�I��b$lD�9�eV����Xa�N� �Zn�L��V�!�9�Rc6M�9X�l�c�3�<�����,?��u�=��f�L����Y��\��*�4�^O��f&kf�ZL)�u���]|�Y���Z��Q��=mGNT����JRj��R����U�B�y�I=]�
gq]���*/����7o����(�\�V=o�#����|y�m+��>J�������a7��(9��2����/�������Z|A����<8P4�/A��6�_�y�m4�b�����(�|��+��s	��K�����\�4e��b��QZ���D�G����h]4������b)�A��H��������V�j(Rk�"�}�6�������]�U8B��#g9`to�O�'�R������/;"3Ge��t;�b�(��(�#
�O���h1�*�R?}*��,� �+v��T���%�Q��v����~N�C��f)���j�z[���
�c9�8�.������+�rF����.Zh�.Vr�k.6��O�nfWdnU�����-D������*	��n/sgG*RTC#c����Zp�v�1�Q��_s[��`ET�Y��Z�������b�Er���>�u��v�}op�����u�]���/����6�W��.��w��� ns�(�V�;�f�
m�*�>Ihn���$E����)��$K��n�h's�����;��C�)n����`���y`�X%���d�<��w8$��*I\A��p�m��y�;opd���
I[K��T�*�Ii�����t������`��wO�HcMc4|L=��8�Y
�?����r��c�f��{�u'j���n�2��e.u�bdv�����j�O!�]��
;��=��������U��?�T���
k2����j���[���R)c�(��t��������M|�h���y[��t'���w�7}�Y��w�Yz����P�TCR8�i��
RR�OG����|��"t��3�D�X�
W�Z
m[(B��������%1f��n�.�G�^����^w��t�u��'�D����"a�
�����NW>L�H�(��ro�IIgW>^��L����z�����^�(pvqtq�������~�jo��:0�;�75p�r�����kK�+<+�+}����=i^}������s���F�*=� �����&�{�ovK�H��5��[Q�lW���z�^H������1�v�=�<�

7��._�z����8}w:Oo�U��8I��Wy�^>�����
��v7��>i6z$f+wtrqHC)w`���t��W�������k���R+&���G"�W���a��HA�T�A�$Y���O��v�	B�;��5|`]x���������/�A���<�����V���V����*<��
�L�vP�A�g~ �+�n�/+���J��_N�B�9�+��<�&{��?Hd���7]�#���QeM��Rs���3����\��*>���7��N�\�R�-�e{a;�V�~S���_�p/+����������,�����v��Z�V�
[������Q��|�e�u�z9��_�����<�u�[��-��	����v�������o�L\�C
����
+��SZ|����-6[�~����eQ�S��6�	����jr&\6�������<��4�A��=���v�s1p%]�]�\�]&�N��G�y`���M���LH�a�����yY$��qK���c������8�U�Z�T���qT�� Z@)���/�H_��#.��v,�B�m�,4��{q�"M��H�W#H��b�M��G_�H��Z�i�Z���CB;������8|Oi9Sr������4+P�7��4D�m|a�5���wI���/�����'���������g�8w���4���������������M��U�8����D��|^�`�����~�V����Y��E��`����K��@�7g���Q0�-�1�7[@�2 )?s��F���x���#!*�Q�lbb8���Nj���E��\c��L��T#�w��e��X��G�O�I�f`~��-t�:��^e#�������l
��1��c�]'=m5��
������o��t���>�o��w@,�>�b�1��0��X�^�����#�c�	�_F���z����Wa�\����(�C����B�g	�����"��/����o���c�)�1l	���^�:�����Z��V�/��"��#���~�!_���Q�Hy4O"��ka0��s��VS1H`n�Q~�I'�>�V�����3�$�@%"}���/F��w~!��F`�1.��
Z�X�}}k��
���^�}�&�������,B\N����i�i����
�{��%`yH��h��P{|W�N������s��a�eD��`@��|��A(�DG�Q�#�������B��_I�+�����
��8�86A��7�����z�]�O��L��E�$~!���l6�M<E4c���������h�9F�����i�������L�p/	�1^�t|�,���i^���� O�qe�o�$xc	 G��������x
l�w�W.E�������t'\*��R;�h��e�=X��
Z�@)���?�*��`>�����w>��y�9�-���!f2=���������I�l���bB�g�i���m��(3�N}e:�J���E<a��uB���� !�,	v�e:k0�U8��)'��)	]�=�>���X>��1��n�[�C�w�"X��Rs&�{Q�a_�m��@��xV::��Z����:&���Tc��
Gt�D|�t4i2B�����(�K5zM��L���c�j�g+:���>���u,t�w�Oq��O��d�H�s$g�����W��H�$������u�1~��>�a\��R)�o�	�>���M=��`��S�	����:ut�I���]�������R����
B�|�zt��U�M�p�Q����y��=]�s�V�wD�e��X�Ks"� Lz�t�t�3����&�=��m)x�����p���2��S��"xD�J��(k�@-�}����r%8-������	�
��s��']P��hR�\�/3��`�C�[/�$����1�=�"D�4�N%
{�kXk	!�7/��h���������H��
}}\���e�r�9 �L���4~�|��i���6-�9�.������e�?�F�'Q�A9L��=�BN@e:��e��PNb��b������wo��1]n�}�S�*�e�F ~1'��,v�1����K_�zi,G:�a��a	t@�&�1�Y����c�Q�j1��T���y)�{��H����Ty�H��w=�A�������q�����+)/��P����G����P*����0F�����
y��6#��6y�5�3��t�������`��i��RL��z���>�S�~�A�k1V����W
�5��R����X��i��g�'�������� �[C��yZ�4��O#��w��4�aO�v���m�~-�r9[��(���bL�����MZm�rx����[i_@�=��X�q?�5�YKP??W��������P� ���.B��8�]��.���]��e!��W�_*��Ll�*oJC~�����[c�5�O���l���z`�7�~�8N����c���w!�F��7�h\�����bo�*]�4��|����4�	�����ih�[����^�����0�%:h����<�\�����W�<��>{��y����(�V���~�W�@���X��y��?�2AuE{'�O �%�z��!���CB�y�B�*����c�K����%�7�?��W`<�F��g[�m�2C��\�V�������' ���x����� �"T��>�!UhGB��b�q����t1�q�C#0����nj�pb��e�1~��������4����t�2�e����}�������	�&�����i��/��S`���c�������=o����c�k�_���U0n��!���^�#?�����?���wc�Y.�q�������{�;6��7��{
c�+n�3hk��{�O���k����=��z6��<2��6���h�e�~������c�_���L�+��d�b�^�Lb<#i�/���������5������� ��7����7�@��1JC��.7���(w��x?�30���i�l����
�����Ou��@����
�Tn��������?�o����.��RO���
=o�z����.Bk��'v�o����O�����8��.1������i��g�mF+��OA{y���Ck>n�7=�s��%P�:��h��2��Rwa�
��PbyJ0�
�z��������6�o�1#�Uy��;ZG�o�sk�%�\��8gB���C1���1�Xk�Cb��p����������@��3.���g1���e�_���N�������
���3>�T�r��3@���A?��W������+|zM�6;�9�M�Cc����
���/I5�����w�/B}h%����gB�e��~����[�!�
_2��H_)A~��~�O��<z#�d��j$�_����f������~�Ug�k�/�K-��,�M�J�MX���vxHI�����^%��3�?�eF�}��7��	������i�����u�w���1��A�Q��W�N���3����������u~k?�X&���>�'�8�o�%�R�>���b�����K��a�`�"����{��kq�W���b��������nZ��NY;��)���"����(���7������� �^���4(�-��n��uS��v�k�f�pD�k��HgG`����#a��������N������[?��+a��i�9���o](�@��#��|��v=s��vn���7�o�#>�H��>R��y�5'�^����r��h��AY��k7��
7I�@��
.�<PK`}So��1FK�����w0�S�+�c�L�8W���pJ�U��Y.a"�odY�9a�����XV��wl��[��>A�����{B-o�>��X�IE�kls��B��������F������S��zy�5�������=f�T����K�����������������������K���X��+��X>��8P>�>�i�M��������0F�k��i�_�&������C��7�����:P��h�� p_�vM�`����0�I��(B�����M�i}�}6m��7>���[������D�${wa��X��r��:m�Mw�����}�hWw)	q!��a<���iH�	��#�/��>.Jg��A����uF.���j��PW���X�.2��Y�j������B��P�UB��D;�a�Iv�p�DQ�VS-�&@�d�8��.��DLGa�|����]|>�[�C����In��!����R�	���|Xf����u���8�`7����F����#�W�^_�M�����[9�c=�P_��qPa��{[eXM���r?\fn��!.��eh���yfSW����{3���q��"�q:��@���v��{k�qo�T�sR+�3X�9=2����-���Ph���U��aX����P�NM�s�I��w��'�d�lZ���]9��<lFL�q�?m���a/z����h��w�y�"XIw%Z�5��lS�>�f���=��l�~=naoh>�=h� A�x�'�:��$��� -���y70K?���0�4������|�}f6�n�h�h��|\�^:�_� ^:_��yX�7�3?Q��M,k\��OC,@L�����B-����~�l�V��0Egp����#
boi��w���$>svO���7���F<Lw�~���u|7�S�<�y!���m����[��v?�-�!�����Dkd���[�_���,�b�j|f�g�{1�K�8��^�o�-����S)=��w}w��-j�?s�@��������Z�bM@��X���s~���+h��u#���E��?5	�|�����_�r�CXb���o�y����:���Ab��F�w�F��~�~]o�a�a�����a��
p��l��X!]��@+�`�V��R)�1��<����~���1����?]���u����_{K�w�����)?;n\��� ��l���9���Wu�M@^��]%i"��Dq_���O��6����~�FQ��3�5>��?�����<Q�?s�6O���f{��p�wl'��/�:���dc$[P��w�_�Ig�|���~:��I����A_�Z�Q��(���lZ����Y�+:�i�_j�~R��7�S-�{�L����"��m�c�hh�\+?3.C�J���8q�4)��C�����
�k|���7I����Vt�f�~_�|b����2Tz����W�wrh������D{c_(�K�Q��1q���;=���Dv��;
���aXwX�/�����/�8�Q0���I�>��N�g#fb:��Q�xqt���N~��I����poo��t��@��~{;��M\����m4(P�^}�J=�}X��NIB�B
�i�/�v���;���xf����c:}m����C���e������JyxpM��r\�7���Q8[�5����`�����Y�j::��>x��0T�N���*(T��{���A��n�'w���0|���������0b�4����#�>����d�=�Yd����k��5������"����'i�ch�"���=�B�1���8�C5�l����lh��RLw���t[�����}m�+�U��t_K��X����_�;�,jq�t/����-������~�n�o���I�?<Si}w���r�f����o��!������nec��w �D��� C*%����v�dG���{�����D�O���+S^)|�K���eSO�7�:�������o��R),�"��]����7���-��$kI�
�Aw�q�����dJ�iM�C@�H�%{�{�X�y�.Sz�������Ar�^2���,	�}
$�P�j�*C�j����� �!�1p����~Z���>�SB7���I!��i��(���M<H�[��n[>�*~���.��<���i}��u�O������m�w�������J?|N6�;����u�5���Y�}����{z�o��V�x���i?G���z���8q�37uB'�O"H��6�������8G^��hu�;IB�?�b�� �������c�~��O�B���8�����������!�����Z�?����>��>�Z.���K�W�E0��������)��H��%���)�u���:8�3�A~5
~�lh�:��p�=�xm�#���H�!�8�"@��������A;\����W�9���j
��]OT�G�(9�s$�M��mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC�/���|��0���
��������&�;a�T�5?;���#��nK"#�S*�2��K6H9[��w�R�V,�8�3��2��2�\�p!bbb7� B����3k����!�o���R�Fp�n)�"R	b#� �!�@�E(���D,D�FO�Rh�]�8���[E�u��%";A�����Uk��aZ���V��V�s�V�����bo^�"�m��==�R?2���!�{���`��:��$)y������-��$.1��Xj���8=%=l<��/��7����������1����?��B~���*�Z�n���������C�!��P��B�C�E�F|�0�0T��D-"�t���1T�{�Y�a���b�]�.��-]+Jv�D�XO���D(MOx�%
��[~h���+����
�A���%�s�A
o��k��n�'b�zt�oA��H�����8b(b<bB����z!V!�!�He��8�:�m��H"�",��������3�#���/Cg|?���_��D�I��`����|������s�6*�*�����_�����zx�n�����*��8�����[jc^|�s�����R���#HN�%�{!�)��~.�0X_�����>�Y
�o�S���S�_�S�_~�(����)
�����CF`
��fGnA����,�����Y�g�j���A�W�/� ���RT�3�:�hW[���i�b�8�:M�u��)q�����j�$T���)^���h��! KT=����J'��*�R������Q�������S�������C{���iN�����J���?����gg���X�!�I��-]z�0�Y�Ph�	tp*(�5��]���:@S@�@����6])^{�M�
B���/��G����8�q\�q|&|���(
�2��<���]�=Y�}n����E���x��W�&�Au\FuR�!,�(WPvP�P(�Hw���D��%�r�S�=�f1�=�\����X�?�q���xv���f4�������
���1)M::!�mJ��O[�~�J��A���F�x#���Z�YTs��Zj[}�"�&\u0HR�D=@�>OT��~�J�P�����-TK�������=S��P]	�����/��5�g����~RW�z]-S.�����h�wzwj�2W�'����*e�1�`�i���"������`�
-��j�u������!^���*�&b"��i�3�m�(��o�}�9.krT��O*�JX9�W�)���4)�B��n��i�O6���_��4�zX���m	)�"��{9`I�T,��@�y��5�p����R"��"�t�
�+7&Y���<�A�
p�F+�>s�L]hp�J'k�P�$m+7;�~m��m�H��l$�>�6�N��b�/_�>5r�e���"�6j�>^iDm�}9������,�7�1Wvq30O
�������e�#�+����a��������$�G��+��A�\2\p��t���n����#���"��D&�L%������a#QUDb�@�4Q��i�\~������*2�9�zL��}��2��=�9�����P*���D��2�>��at^��6w�,���_X��j���r�-$�z5S:�]��L"_%��t�Z2��Z��W����D�P���\�G����y����4w��\i�+�s��c"k|�XUH��P����r��\g��u�?�7�,wn���]�b��x"�ZQ�����Q���w�@s�wE�3��-����hnK��QYr�H��a��8x����'�+
����y5�T�X�����f�UYF��$6�oki)���x�C���6�m�����/�ZlkK��u0cP!�`1kZ�G��^ki����R�����0�����o�)~��RY�k�\T|���.���|����`@���
=
endstream
endobj
56
0
obj
<<
/Type
/Font
/Subtype
/CIDFontType2
/BaseFont
/MUFUZY+ArialMT
/CIDSystemInfo
<<
/Registry
(Adobe)
/Ordering
(UCS)
/Supplement
0
>>
/FontDescriptor
58
0
R
/CIDToGIDMap
/Identity
/DW
556
/W
[
0
[
750
]
1
7
0
8
[
889
]
9
15
0
16
[
333
277
0
]
19
28
556
29
67
0
68
[
556
0
500
556
556
277
0
556
222
0
0
222
833
]
81
83
556
84
[
0
333
500
277
556
0
0
]
91
93
500
]
>>
endobj
58
0
obj
<<
/Type
/FontDescriptor
/FontName
/MUFUZY+ArialMT
/Flags
4
/FontBBox
[
-664
-324
2000
1005
]
/Ascent
728
/Descent
-210
/ItalicAngle
0
/CapHeight
716
/StemV
80
/FontFile2
59
0
R
>>
endobj
60
0
obj
318
endobj
61
0
obj
14395
endobj
62
0
obj
311
endobj
63
0
obj
21099
endobj
1
0
obj
<<
/Type
/Pages
/Kids
[
5
0
R
12
0
R
17
0
R
22
0
R
27
0
R
32
0
R
37
0
R
42
0
R
47
0
R
]
/Count
9
>>
endobj
xref
0 64
0000000002 65535 f 
0000493855 00000 n 
0000000000 00000 f 
0000000016 00000 n 
0000000142 00000 n 
0000000273 00000 n 
0000000438 00000 n 
0000454534 00000 n 
0000045119 00000 n 
0000045140 00000 n 
0000455834 00000 n 
0000455985 00000 n 
0000045159 00000 n 
0000045328 00000 n 
0000454690 00000 n 
0000092843 00000 n 
0000092865 00000 n 
0000092885 00000 n 
0000093054 00000 n 
0000454833 00000 n 
0000148000 00000 n 
0000148022 00000 n 
0000148042 00000 n 
0000148211 00000 n 
0000454976 00000 n 
0000201354 00000 n 
0000201376 00000 n 
0000201396 00000 n 
0000201565 00000 n 
0000455119 00000 n 
0000251475 00000 n 
0000251497 00000 n 
0000251517 00000 n 
0000251686 00000 n 
0000455262 00000 n 
0000307416 00000 n 
0000307438 00000 n 
0000307458 00000 n 
0000307627 00000 n 
0000455405 00000 n 
0000359014 00000 n 
0000359036 00000 n 
0000359056 00000 n 
0000359225 00000 n 
0000455548 00000 n 
0000409570 00000 n 
0000409592 00000 n 
0000409612 00000 n 
0000409781 00000 n 
0000455691 00000 n 
0000454492 00000 n 
0000454514 00000 n 
0000470994 00000 n 
0000456129 00000 n 
0000471423 00000 n 
0000456523 00000 n 
0000493193 00000 n 
0000471631 00000 n 
0000493574 00000 n 
0000472018 00000 n 
0000493771 00000 n 
0000493791 00000 n 
0000493813 00000 n 
0000493833 00000 n 
trailer
<<
/Size
64
/Root
3
0
R
/Info
4
0
R
>>
startxref
493970
%%EOF
bitmapscan-results-optimal.pdfapplication/pdf; name=bitmapscan-results-optimal.pdfDownload
bitmapscan-test.shapplication/x-shellscript; name=bitmapscan-test.shDownload
#11Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#10)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Feb 28, 2024 at 8:22 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Hi,

I haven't looked at the code very closely yet, but I decided to do some
basic benchmarks to see if/how this refactoring affects behavior.

Attached is a simple .sh script that

1) creates a table with one of a couple basic data distributions
(uniform, linear, ...), with an index on top

2) runs a simple query with a where condition matching a known fraction
of the table (0 - 100%), and measures duration

3) the query is forced to use bitmapscan by disabling other options

4) there's a couple parameters the script varies (work_mem, parallel
workers, ...), the script drops caches etc.

5) I only have results for table with 1M rows, which is ~320MB, so not
huge. I'm running this for larger data set, but that will take time.

I did this on my two "usual" machines - i5 and xeon. Both have flash
storage, although i5 is SATA and xeon has NVMe. I won't share the raw
results, because the CSV is like 5MB - ping me off-list if you need the
file, ofc.

I haven't looked at your results in detail yet. I plan to dig into
this more later today. But, I was wondering if it was easy for you to
run the shorter tests on just the commits before the last
https://github.com/melanieplageman/postgres/tree/bhs_pgsr
i.e. patches 0001-0013. Patch 0014 implements the streaming read user
and removes all of the existing prefetch code. I would be interested
to know if the behavior with just the preliminary refactoring differs
at all.

- Melanie

#12Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#11)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/28/24 15:38, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 8:22 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Hi,

I haven't looked at the code very closely yet, but I decided to do some
basic benchmarks to see if/how this refactoring affects behavior.

Attached is a simple .sh script that

1) creates a table with one of a couple basic data distributions
(uniform, linear, ...), with an index on top

2) runs a simple query with a where condition matching a known fraction
of the table (0 - 100%), and measures duration

3) the query is forced to use bitmapscan by disabling other options

4) there's a couple parameters the script varies (work_mem, parallel
workers, ...), the script drops caches etc.

5) I only have results for table with 1M rows, which is ~320MB, so not
huge. I'm running this for larger data set, but that will take time.

I did this on my two "usual" machines - i5 and xeon. Both have flash
storage, although i5 is SATA and xeon has NVMe. I won't share the raw
results, because the CSV is like 5MB - ping me off-list if you need the
file, ofc.

I haven't looked at your results in detail yet. I plan to dig into
this more later today. But, I was wondering if it was easy for you to
run the shorter tests on just the commits before the last
https://github.com/melanieplageman/postgres/tree/bhs_pgsr
i.e. patches 0001-0013. Patch 0014 implements the streaming read user
and removes all of the existing prefetch code. I would be interested
to know if the behavior with just the preliminary refactoring differs
at all.

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#13Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Tomas Vondra (#12)
2 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

FWIW I'm not implying the patch must 100% maintain the current behavior,
or anything like that. At this point I'm more motivated to understand if
this change in behavior is expected and/or what this means for users.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

bitmapscan-refactoring-results-optimal.pdfapplication/pdf; name=bitmapscan-refactoring-results-optimal.pdfDownload
%PDF-1.4
% ����
3
0
obj
<<
/Type
/Catalog
/Names
<<
>>
/PageLabels
<<
/Nums
[
0
<<
/S
/D
/St
1
>>
]
>>
/Outlines
2
0
R
/Pages
1
0
R
>>
endobj
4
0
obj
<<
/Creator
(��Google Sheets)
/Title
(��bitmapscan streaming read API)
>>
endobj
5
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
6
0
R
/Resources
7
0
R
/Annots
9
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
6
0
obj
<<
/Filter
/FlateDecode
/Length
8
0
R
>>
stream
x��}��d�����������>��`:���u�c���cfm���,�`���.��OUI�HRUWd�`���V��C���D���s��{���]���������}����������}�~��1�
E������k�m��y~����:��&��_}7��|���y��	�?��q����(����|��$7������~_���+�x��?����������?
�k����h)G��B<tK�O�*�mJ(��(�����O�*���)����M���l#07��_p:�e8��N����~���@���1:sc�}v���@�����W��?8��(;J' 4���N�����W�G���3�F'�h�E��]������[�+{I����p�_T����.���)����fO?8�2�.`o����]�����w��V���@���_��X��~W���~p:�e���+7p��U����.�i�(����fO?8�2�z�.�`����]�����nE�����.�mdt.���O3��t�Kp�����m�����.�af�v��Jp:�e8-�N��~W�N����	8U�U����.�mct.��Jp:��YS�S:����~p:����c�v��Jp:�e8��N��~W�N����	8��*���@��>2:W�]�s��O~w���=��
�m�����.���y%�o���N�g6��p�5N?8�2\��W���8��t��pg�^	�[s�����.'"=��
�m������6����5N?8�2\zF'�tk�~p:�e��I�������t	���
�m�����.��Mz%�n���N�'6��p�5N?8�2\��W���8��t��pc�^	�]�?8� ��6�'14���OY���f�G���
������~�qJ��[��������sJ��[�������>pJ�W�
f?9)3�{6>`ho���������G���#��������SJ<��(��������SJ<��-��������SJ���2���������i�C���������s��&��'�#%��u�R���:��t����R���4:��t��x������}ED���H	x����ow��Y�8s
��x����jmE��5`���WD�^����p�q���@X�N�^Jh/qE����k��I��>���t�5`���WD�^����x�������b��E�=P���D�^���<p�z���iY�N�^Jh/qEDZ��?9�d)O��s{���3�?9)���x�8s������sJ���3�?9)3���QJ�+"�ONGJ���EH�W�9���H	x�8��c����������SJ<W� ���H	x_8��k�G����������Rbh_�~r:R7.B������m��n�.���Lq>�q�i�������w���F�w�"����?�?��WJ�HX��'�$�w�������A�m��=�.2�u9����t �����(2��}���2�����-�z}���y��i�<>J�W�����p\�qd�(�>
���uF���
(���=�e����1��E��]W�pW�OkK v< "���m���$�Ei���T�:�GaKO��B�kK�lmA�F��{sE�;��
H6_tUq�A�F� |���5\�
(�my���"��t)vH�$;@���a��-Z��RsQ4�l������/�v��g�y��3���Plm��\��r�7���^�3N{�\�$�S��Eb~*^�������vvqe����yr14Pl��z���u^U"��������5#{���D��X��F�;�����4��{�(#7�n����d�@��H�X�����>k@��X�{��hcf{�	B�Nn,`O�H�s�y�7f���Q�������/�3��V�24$O���x�81�<�l�V�������Tk�L�����I��'`�4@"�����kc�;\0��������+�uP�X@��}�)Y��PV�P��Hd��Qd6?,He��
��B3��LV�+PFn,`�r`b��
�=A�K�|�����l� RT����"15(3v�����>�'6�Y�p�.�|���9���H���c�A�ll��rc���Ude�`k1�<5����!g�7(R�m��r�d�V�P�^
]���Jh,`��L�g���o��37��������y�������"oNua�rJ�����B��,��+�c�^X��#00�a=S�;�U%$���� ��K�AFn,��@��/;Z�B�ln,� J�n�d���+�JE�=�����y�g?��`WX��������(2����e���������ljl9��_���	"JKc��E��������;����=��.$����A��l�E���|���	�8���qd+'P"��Y�8�dEdz�x]!����*u��L���kD�kj,�x�;s�"2�\(2A��X�w�/�g�c��.5�=�������D�h?����73\�����~�=�"���6J9��N��q��5bj�;[��������i���q�����0�BW9����en�bg�����h�8����GQ��
%ao�����n���kc���9NP4�;���9��=���h�����K�Gy�<Jj,�(��e�����t���������pU��H�����,,9��(�:���T�e=pP(J�����?y,���g�U�p6QV>rx������R8&�8U
���lk��_!��I����=�k,EY��������T�e���9�|��V�|�,�"�r���X���P�,�;�+�;;�X@R����O�+�����d.�\�+5��o�� {�eS�S�`��(��!E�8�x�Tu3T����_����l}���<(l�s�Xb �����:�,"������e�w1������u���\��A}oA1,+�'��K$��	{M�p�vX��3\XJ �8�pk�Yde�����$L�4��g8sf�����4pa��b��2����e��_�c��x17P�0'�y0X���2,�z�I��%���J�f������*���Ta�X��(���Ch\}d^�b�����@@*�.��`��y!�6P>��u�<l���'`����w�,p&���=p((�Y�AT=K|��|�	�t$$����"a|��u��X}��8Yy`��u9K�������k����/4p8d]z&������/J
��J�>�HJ
CI��tj,�}l��r���%��dQBrb���T����e�K�+���K �\t����6;Qb�("5���Y0�G����
��X@.�FJ���2��%���XBr$���U�//�$�Rvp6�Q�d-%
lv���&N�@[\Y��9f���C��������lf��0Zl)N���.���]��0"�����,�\���+��,�^��f�#��%$G+o/QbY����Z��X@q��V�YG�{�#�=��h,��wp�,�-"���;!f�oJ(D��[�p��m���X�y��)6YD��b�a��!5p>dk�����ue�\��\y�T�N�@W�9��v��X���e�ng��ug�~����9\+�i�7E��	W~�o�H��������Ud]'�E�"yj,�
Y���wp�"�B~m, �u;�F���b�q��pb�������lBEV��_le�`S�"�����QV�e��S �uW4K���F����x�*��@V6B�� ���������6j�(P\���N}�!�S��Y�7�HX9�GNX�V�,�<�	�}��dW 2!��O�l�t
t�QV�>~����Vo�({~`�����[yyX��-���d�����;@�,7C�7��IH���.@$(��onK�$�"G��t��y��VxXr���n�@�,5B�����X@������P����X��e��0=�Bwm,�d������^{�R/�T	�5�^E���)"X�%����V,FY`lk���������`���"0���5(Py8c�vugEV6;V[�Sck��d�b��.����<>�Z{�v���}�w�
'�KH.yG�UDf�c	3�
�(�.�|QX��.�����{R�{v�+����Ky�TE�-��4PFj,�y��l����>�E�@
X���m#{�[P�pz����(2�����.��@�@�2=��EI����X@�pw�U��x�/l�����Vn��`������F$\�Y�9l���"���^��.��k�(6��-�,{|�kW��f��..&��T��jp��;?�
w��S��y��F�m��;��=���s�"4�=�//B��S�k#��1A~y�c>u*�x�;OW�Y�A����&����qw\l��/��H~\��/��K�����`�O8l�	��?�������D<����2n*>��|<vnl���v�xyK�KLnl��F�\��}���(����S�}�M������
�F�su�9��?����1�u�D(<U���lXm*wU�K��
����x�&���#�V�g4����=J+�M�%�����w��[�������P���(&�E`�(p���T���{�p_*��}������`E),i��(qfy��{��7�`$Ej6
���<s�I,n#�����9�o����^b�1����'��y��]�-F<[3��C-bA��f�~]�>%�bo����X�m���u*��$Hs�`�(���]����^�������%�1���I\�������,9���)v	�����g����J�(c�2!r�qn/q�����Y�q3���K���,_���A��B��&��U�i�7	Z:�!aiL�q�O�%�����
��e2D��h:��X>�����C��
���K�.L��| 
��s�a���s�����8n�����%�yNs\�#"`�X���;�����i�,fy3�hz=/l/�x�b*o�C���sB��KL���M(rA�Wk��T||�z$f��%L����g<�gU��a�y�V�e\v�6qwl��h�T��q�Rr{����k���<h(N^��K�����3OH.#	��C{�����5�0�<#�K�s{�����S!�W]�f\���W�h����H�jb"V����KL���z���&�:����;+��VE*"O���/����Z9"V���k1r)����T}�����X����^b!��F���=$L�v�k
<�]�;�R-Ra(��w�����K���[���{�X�(&�����w������������Dn��������Kdq��O����$.�j9�Pl�/�$Lli�K.<�����
�����X�e�mS�{Wa�
c�b��7r{��T9��q�8����7r{��������0�������X&2�,2�X�B�����^�c����WzP.������]�$�����:�'����q]G_#D;������Or{��.�-�%Z+s��/&%\����%��wo��`!|ii��R���@�(��<_YBy��^b*�n������e��^�����0s���������������V��v��u�]�",��kMeOtSqw\����qh0|]����+�T�ES��YE���On/���
�E{X�����~r{���2�$���� ��Z���&�?�[��u��_X+R3.������{�N�v������^b!��Yl�������r{���v�� "��L�����%"�g>����p�������rX��=C�(g�T|���=<|
A��5�%��x]�."���0R����L������h/1�t1�T"{�����3	W��%�����}K�E(x��<���M�B��c��7��3
\�>:���u�|��������K���5��C@,�+?���K���.�DW�q�r�/�m*>�W�}����q��~�T,���CGrw�^� �K,Ss< ��R����It#w; 0�C{��&���,|�$a�vv�#r���vH�8��!�J
��b"�~�B��,8����^b��:��/P\�/(.c��bn/�Q�����@y���<�I��^b��;�Kp,�%�XB{��s�7��g�������������|�h/��o�&(n�#��I�����=O���^���\��r�h/1�{���3	�:L��8�8(������P�4�g8�*�M�T�]�����!����I�%�����P85�WX>���K,����<D.87�+?.��K�n���:��@n�������z5g"������`n/��
����Pf�rr{�k��D�|�2.���a�h7������i��~�ENj/�|o�M#7t�8S����K���7�*D?�f\l���s�oY-~���'L���w��g[���;��"�)���K���b"V�+�F�W�"�j�N���n�R�C���"4c����%�u3A-�u�@���^��@u�=b��j|������U��P �O���Q��W]!����Jh/������|���yRqu���;��,�%�������Wm���#�t�8��6�%�/���R���2��r�N��\��8D^#�0q�3��9��*��*B�]��(=����u!78H^ �B�������]#��)�2.�.�g���A�Xp� 6�r�bR��{W�P.zR��!���kD��P�����N�B��YQ���0PB{��w���E�;C�(g�T������@t5w=( ��X������KxMU������������D?���������D�]/�^��r��C����{w5�\�9��k.���L�P x�q9B4������W��\� �K|��*/����r���w[0L.@ ��#SA���T���Ty�x�\��5�y����]a�/��+�2.��6�����@|y�\��KL�IAuG�H�w�W���d��b.���/���\x%An��d��b�^��4����b��#�%��` ��8�� 0�����&o��=A����� ����I�� ����R����cAI3���%V��z��sM�����S1������r&\�����M����j�P�a��s)g%7
�����S��N�q��K,��:�����u�	/����a*��E$.&\��k��D����gn/�"�p����p���q�v����C�3��QNn/��C�l�f\����@�S�s���^�H��K�n]�����9[�a����i�y�q�������������7A�����"5c<\��K,��)��6kq`��.g�;��|�[���""�r�yP��d�M�"����r9������I��]N��B{��c��AF��=@�(f�T|�S��q3L�@�%~�`�����E���Kl���|��;�Y������[�W����`�%~����\��E��Q���X<��{��}��z�/���������������|�}���K+�	���������2������w	�=��0�������=����������^��mB���=+���'�X��{3�����w)���u�����K��r��.���#��������w	��-�\�.���2���K]cw����S�5���r�#����o��������������/������^/�����+G�)|�����N���������������K��i��O����y�O�?����?����?>��������������~����'}�;C�O�~����9s��������z?�����=3�����������LF_���X2��,����q�E��<�/�J�����S������0_���&���-j�����M�C7��?������O#�Z:�/���X�������������~�$'�,���������~�����������<��?���?}^T���������>����=��u5��8��s,5�?y����$��!>O���&������}��*�G���s�Zc��b?��sL��_]��w��m�M�����?O�l���^<c���d�����>g?�u�n~r~������-��,��O���C��O~	��=����9Kx�����]����~S}��������s.���N�������9y��Z����k��z���U?�{m�b��z�}�>��^��:�����V��;9��������6g���C�R*'�R�d]6��c�N�s~k�~nf����u��m����^_Z�kv����w�����<��x�w�l���y'�������������\���]YF����m&�U�Z�b��z���'��2t�O�2�kF����������_4qO�%3��A�o���]�]�Xi}��s�x���]]���>l��z����[�Wx��y�4�O�~������z��4.Un�`<�������7����yg0�=}m��Vv�i*��Y��y����V��~uXYp���E��L���uZ���v��ee��i����N`gFo-�����������N�0�m�k��9��:�6.��FX�Jbq�]&�2_Bh��u?��,T�v�(�f���2(���m�7��2x���uX���e���}n��{S�#�� n�������mT���3y���8�;�����C'~m�@��|[�Q������Zw	%W!��K�v�o�d<��7<�>�U�OW����oS������	��@Lsi{g�i��c/�����C����-������?A�[��n�q����*�/���Q/�
��Iu��x�e��1
��[������n�_��I������#�Cg���ic:����m9��1K��'�%�Y����N1�E�H	c�6rcI!���,����b���Hc���b�$ �<�:���^�k/�>k���[���2����:iDhQ�_��hHhQ��B���BK��#��P����UB���/Kz�&BB�i#��n#$�Tl�q7�����4�mbVdi���,a�P�g���I�[�������S;��0h=�����,X���
�6"z����>��&^�W�K�R��#C��W�H�2����(�+�DH�2m��*6���`�
��*6�f�$zUl���l�;"z������!���b ��WF/�����=D$v-�#6[u���V�8dQOe��T���e��c��W�]����&��e��;v��]�6BbW����U������m;~��@��@�2��!������j�]�����\�qV�6wg�M+�}=O>>�
�U��S;K7t���
K��
������nXZ�����^`����o��m.������_�Q�w���K��K�44��TB�N�������K��=e�`�j��
�e�p����gSt��J�8b���c���1�;����]�����JK�g��M��1�F�Y^����U�o���Hs&������UD�����^��N��u@��N�
,�N����E%�X>��c�u��4���$�����oXm���$��	,�6BK����n#$�Tl�X�D�PC`������Z��1������q~��S�6"���!���DH|Q������Y�n�'&���v�Y�h!�%�FH|��Hc�B�/�����s]�RI��{���;����{U����O��E��.�CN����E%�.*sPtQ�c�,U;f�%#���H"@�8�PGw�QGoq��m�

]uGd/&�Y,��_@
�%���d7��y�����Ngu�e��:�t����c�J���^��e���>7�����a�Q��_|��S��#�:�k��Nalv��7i�}v^�d�^ah2l�l���?ecpT'm�bl*��Kc�216�����<�Nr���n=fP2�i~��-�6��T��3���7����}[�as&uk9���!G.t��S�C���e���}v�'��!uv6�'�w��5��������Na�*������~�3p����3�;�������rG�P��.k\5]��D�����+2�t\�����������PY�x��s�j�"�U�3����s���t%8^���T��a�����\\�J��q�<QE���@Gd�9��G��KP�=��������CMf�B�y��X��i�^H�m��/�y!�:�Yj��$�M��U���-�^H�s��;�I������B�=F/d1�����^�v.o���H�}k���jh�/��"���uP]��f�+��C\��g�����zn\�BW�w:����~;�"����}�Y��S-����H�^�TYvU��kO�+��?8
]�+��_<���b�L\�F�X�-���s�9;tE��?�w��N����ok?o�<��KMG��g��u*S<S43�#�t�f�������q�3�NG��px*������T��g�1J%vl������[�_���������4��}�=���>���a��E.��$�rd�*o�R���/�Q�x^���b�L���g����g��xE��M}��U�&s��7��������4�/���^H�k��(^H#�,�/�Q�x��/^�R�7�3���c�B��#��=j�s��;P��f�Y��Eq���(�,��U���(�7b�PCD��J4%�U3qFq��xE��~�8#]��	�����(n��{��qk�dqEss�RqE���Eq����e�+�x�����1�*�+k(��R��i��"tE������z��/�4���0`V�+������bn�3�"��uOq������#�/���������7����_=����Om�RN�������UI��l���Y������3���������Y����1L\[XQ6��7(�C|����>-,v��z�
��b;L����s�V��2Z����X�_��rFX���+��0�2���5!�7$
S�#�(���(9TY?5����4�S�:�65��^S��-��i�!��?��Lem_�-�������a��Y=��N���T���1�_��h�^��8?��:s���{�`�*o��s*q���[!�R�8�C+W�j����V�554�y��WG�*���5�p�(kV�h-���*�����a������v ����Lf�]v�}�����?h!N��5d*g����4�/���d�8�Q{*,I�����B��F�����8e�wNkZG�u��l��8��t=;���8�[����3(��� h�#�,fw�����5^��X��������*g�������H���=N��,���q���,]�����Q�|1"�8H��������,�:�!+�:H����y��Pu@���!J�3c�����U|���`Y���G����J�
	V�B��F�)H%�JWsH���_w$X�	V��A��m�2�p� ����:�m�k�
UG�xfV�����>c��g��Jc��r��G,���J�
	U���pH���=w��P���}���*���u~C�e�GI0T�Z	U�u���h� �J�sH^nP�2�lX�C���1P�3�KM����!���1^���J�n��.*��dC�(7��^�qv��jW��_e4���P�v��]������^B�����
�N����RB�J�Ba�z+���uxC��g�W1��������0����dv���2;n���-^���k�?_�r����	�����M�~q��'QJWs���U�WOuo�R�q��`����5�(e[�7a�X�wm�b��E�:�x���tU�~���c7{�^Y4��+�`�+��Z����NS9U����(�:(F�jn�k��(�:y!o}a�q�k$F����Q�u�cT�u��[G��L
U�=��T83F�xf�R������v1��b
�5"Xi�!�JWCH���c�55G���)Xy/�6�b��+�:������EV����I����Qw
;`*�'��P�aD�
g�E�`]`��z��L	��b�p���G��iB�N�t��`�s�D+K�����p�s���0^�&�]�����m���x)1�f#��U�����������*���@
Y�#�s�z��!|���\�_�h�mu!xW����,P�u����������rB\��eo�����[��"v��-SsK������:�����8���.�f����>7�`J�S�.&�Y�ns[�����!�M#~X�����<�0���/C����M��I�bp���A�m�8���89�8��Y]�[�����k�lj�5�6u����.��,���V��X��ewh5���,��cl��n�Z���~PkM�W����D%
���N����@�Tf��W��������y-U�.u�7�����5]7��e��k���V�#&�����xj\�2����eM*<sUIC��F��!��T=�|�T�~q�,N)V��)Y�ne.NI�u��k�v^�iu;�
��n�B�dQ��6��F���W����h��4�������s�8%�;j��j��,]{���t�=g��s�j����dQ�/��o%[��~]���������:m�dI#n_2�~I�D{VA�������d����buM��������k�������������x&��u��x��Ha�J��T�����T� ��r�|��V��3��n�3z&C��B���]G�qF�#V�Mj���m��]C�L&u�Z:\����i��/:�w5���\%n_L�OcZMW�_<�������z<K����p]S������n|I�������s�w�����T���!�0���}���$UA�0����
�d��?	�t�^K7t��[ .I�uDzht;b���n���S��&auszNi}@��J��4���1����Ak����N��u+sqJ���k����k���feR�}�Z�1�����>���!��*��~���4���C�G��_����7K�~�d����t];.�$~I��g��'�<����E%�J�>~��Y��g��/E�����H��J1_R�CjT���(�;h%=X��/��v'q�����/��XI7�1_2��Q&u��C����[.G���OO�{�����~����o����^UB����UY�G{;K\�J��-�F7:5����{U����Edg�1u�Q�R�;���Wm�}�y��c�}������Z�����f�Ma�����P�[�c�t����y=���g	T��l7n�����=����xi_�'~Yc~�r��r�R�;��/�!���c�NKm?{��u����uj�����x9�.����Wr�����q�x��5T��o�=�F��5���1�=9>�C<~�R�;����!���cH��>��[��W��f�:q���e}��(sq�:`.nQ7�+k�S���**m�{6����P��D%q�*������������$��B�{�����1t�6�{6����n�9�x��nw�0q6���8������!�vT��l���F1{V���$�Yc~�}!�9v�{�A��c���gk��YC����=[���=����8g}#n�0���1.�C�Q��\�w ��L%�n]��.�"v�|��C{��^UE���>U{�(�������}����p�������__B��U��[{t�����Sj3�[�����i������xg��#������97=�{�<���������-��u��jw�$;V��2��}H��m�t���r�c��8��}�������E������2@��#
�Mj��C��/�a������$�����A�.�?�����)����^o�����<-88�����HVd��"U
aq��'Y�F�8�H�"���-4��Zvd$+���>3 Y��k��IV�q�z�IV�q���qFC�"�����>xk����(������ ���r!�+�k�99�
��H���|k����!d�����>�Q�$+
�!$+
�!$+�}H��^����kw��c�P�h:TwN��1�
�y���ySd��ZnNK>���Y��Z�x���Sc>O��F�A�����Z�4d��"v�CqH>��OfH>���C�I��C����$��8�M�!]��(�i�i.��k�|H��r��6��I>�q�9.��P����P���P���P�����C�I>�[^D>d���1$�P�!���kGG�!��8vrH>���W�N�X�wP>�S����q������(��e���n�t�%���7�0+����r�[������dE�
)YQ<�vk���-5�s��k�T����$��F�"���J�U���F*�cZSR#C����Kjd(��}�TR#C��K�Kj�r�iMc�XR#c$��s��H�~�r�/��$5
v $5
� $52]�;5��!%5��!%5��!%5���V��k�w�JjT�!���#��]'%52|��nRL�j�Mz��E�F�K��F�}������=�R�x�q��������Q|�����4��oB�����9�
��V����3��I�F�i��E*qLR�1i�8��H�rH�������I�t];N��H�~��t!I�>��	
I�4�7�I+�Y��?)�u 4)�� 4)�\Hke�ZuN!�E*�WGe�^������q�}j���m��>�a#$)�}��n@��>�{���n?��s����a{> ��}n����������nN�JJ�i�-2���E�����x]�nQ����(Z�������s��Y��{��N�e{o�W�#.VS�#�qP�k�$���G�I��k�q�.I�tE;v�H��q�#���K������$\�H:��H��q�yV�I��?h��@h��Ah��Bh���u�C.���.����q���5�z��$\��Q�W�!�����N>���p�L<�]�}�xj����L\���>��C��%���(Z2����Le�-��	W8uI�,jy���[����a^���4$'����P�"6�4���<����Ir"�9�2O�rLe�����<]�m��H�vU���H����~$'���<�&9Q���9Q��9Q��9Q��9Q�!9Q�!9��C��P��W��>�u���D�q\aIr"}$_����D��Q��S�����n���bF������g��v��(�P��>���h��D�}.9Q8u��VG�����dD�����:�J�Y���H#�%��C��4���<�9&#�������tE�:�����v����H�N������#��	��4�7�9(�����:��z�Y.��Y>�q�dD�>�dD���U�}�?#�}�?#�}H�Y%}$��[	��t��9+�D�������D���c���4�������s��sJNdQ���6�����i%���9����}�x��a�X��hjrbi��eR�6"52������f�J�Y���F*sHjdh�1+������"C�!�E*w�f�1�������)5j�����;�{��.�}���C��E*�����U|�;5��wjd�:��;����X���5��
�E��������hb�*2�G��E&����I�O�L�����t��,��5&F��n
����pj���&�J�Y���H#I�4��=#�8��Ne����rH���WG�U#]�!�BR�Sb����HIG�K#�;���`�A�XB#��4ZI�b]M�,���Ne�I�l�z=wI�tM;ND����!����!��H�!��e���uGfI�,���12���;F&���;����NEk��FV��/s�*:��������CK���\��p�(i�E��/����;���ZX
endstream
endobj
8
0
obj
15754
endobj
9
0
obj
[
]
endobj
12
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
13
0
R
/Resources
14
0
R
/Annots
16
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
13
0
obj
<<
/Filter
/FlateDecode
/Length
15
0
R
>>
stream
x��}]�m=rV_��
:��{>���9���[�/)3WDE��!�������Uk�vU3��yh����r��.�������������>_��^��������?�?�����q��y�_8������_������s��?�q�6]�M�2n���o?Z���?��a&�<�z���a�x���t�������������v������������?<��J���B�<�B`����������u����g_"t�%���D�����u�k��Zk���D�Z�����g"D�.u���
�K���@�����k|"B��R��4�Zk\��}����P^���~���.(/S�u)�q)o���^����P^��V�����Y�Z�R��+@��5`���������.x�Qk����W�]�������L�����5�a�_�q���
�k
(���'"D�.u�O�������W�]k�@	�5>!ju�k
x�e�5�|�*ju�k
(���'"D�.u��������XE�.u�%���D�����u�{��Zk���b��E�����g"D�.u����
�{���Z]�ZJ(���Q�K]k��(k���;VQ�K]k�@	�5>�-�'���Z\��x���������R���z�'����C�/�Rc,��(?�����U����������<o�R��7��R��\jJ��0�5�}K+~r�)�;a�*�OD?�����^����m�����<
�R��7 �'���2JJ�'t��\jJ��$)5^��-~r�)��������8~r�)��q��n��KM	xZ%�����`�������_�'tp��RS��P��/��?����}'(5��'"��\jJ�c/Eh���[��RS�I����n��KM	x%���I�}���O.5%���R^��$(�?���O�,(5��'"��\jJ��	�5�O�I��KM	x^%������?�����MRj<�b�'����KJ��{+��'����y+���'"��\jJ�S/Eh<�[,?�����ARj<��[��RS�FI��rof^~r�)^:1�0�?q��RSf)B�������RS�����������KM	x�3�
Owg��O.5%�M��+����?�������k�OD?����G9�pwwf~��RS�{I��xwf~��RS^�L���?��O.5%�]��+����?���o���k�OD?����G9�pwf~��RS��L��������KM	x�3�
���?�����MRj����?�������k�OD?����'9�pwf~��RS^zI��twf~��RS��L���?��O.5����3q���?=(?����1�qwof^~r�)O���x�73/?�����ERj<�����\jJ��*)5^����O.5e�}'f���'"��\jJ��.Eh������\jJ�s')5����O.5%������f��'���>HJ�Wt��\j���^��+�OD?������(Gs�{t��$B�0PBy�OD�Z]�Z������Q�K]k�@	�5>!ju�k
x�6���o�D�.u�%�����~���-�[r��}��n����^���M�-%�_�N����T 
�������v��������`�;�+(�����n�����[7�C�������7�W����,i��%,��;�o�xkC�4�������Rl��^�5V�)E�?��E'���7bP�kl�/�����@���e��������F�B�1�H.`���L\��]<����<Iq�*��l�R^�����&�w�
.�jX^c�]�P���\�S��@	uP^c�Mw_oA �)L��Q
(�5��l�{��~\���X�V1�b����n���?��������r";��kko/?���,�~0��L��G�r������+����D(����a��q���T4�M]E KI�������=*E�@ h��n������?DA�PnQ�U��Y��Q^c�C�
�H�q�� �`���Y����G�����L)��`a�YM}S�7s;�����20P�N>�k�N�%���XY;4�.9�X^c�O�3Orap�%�����r�Y�N�����O���
2���Ky������wbt�8��W���T
FTv7������`b���������A&���R^cW���}�T
h�\r����,���*;��� )�k,���a���z/���V{�BJy�����	���!�VX�)��J7�7^@����3���������f�u���A?��mU�U�����L S�s(�5�2��d��z�@N�
��.�X^c����Y���!V�����X��
||��XR�A�	��(����6wN�J�`P�3=x�������4k?MR T���$���X��m���do�) u*�N�l&v{�<�G�h�m�����$$����B�@	�5V���Z��pt��]�$`�3O&>��}"�Q}�HY�k|�����Q�	�q�9�tj�L,���A����[�������d��q`����7��3����<���-�cG)���X�=���D�L0ab7�2+�5�2��4T ��g�Jy����h�Fi�0�y�]�5V�{o*��
6lz���Q��������Kl1���](���`AC"v����r�L�D�+�h�Fi�@ `P�k����������������!�AWL�k��n���
�)@(������/	�@0v��
S,�5����<��h�p�4J)Gy���d3�j�������P�Q^c�Um�E�����$�(������6W{�������@k*�"f��#e)���gf7�&D�"v��<YX)��l�$m
�,�d�5�e�u����nrV'����'�j�Sd;f1���p�v4�:�������Gq��(1����{���X�0�EZ;�]�k,����C*� <H��Ky���ufX8���2�A���,�fb��w�2UA�hhpJ!{�k��h�a:�S��b�����S�(������@��v����~�L�����
�e��F1����1h]@�&U���`�L��C��d��Lg������{,�1;'#g#��gP,=yR�����xw�>�f��P�k,���|Jv
��Rs�e���������lW�?0�Xe�By����h_i�������+5����WE\���}���� �X0@8��(��������3#})��j�{�
�"
����]�)�5v����h_@�&U��cd�L,�>�����Y�?2�n������)0�BFr�[>���R��JE+$��HJ)���z���&F������f�R^cuB�nXF���@}�L)����G��P.?��>����F;	k��@�H�v&������&1�n��E�=�:�R���� 2��Gw��P^���D��Js"�e@P^c�$4`���������G�"S���,��q��^�!I`Qd����5f�:�_���r�f��?�����/��M�2����7.���\N��D���R�R^c���bK���& 0]����n�;s*��Df/���3�IK�a��,�@	�5>��z���F�db�u�NeP�&����k�L,�N�9�Ja$Z�B,	��q`�{
�k��+4��T(�y�]�U�k�Ja��
��s�R��l8[������g��W�	�;0]�v��X}��xL�-&�������S�Av��
�
��Jy�u�=��r��l8Y�X�k|�i`&P�,;�`�,�5�?�Y�k�rw�k��y��/��n-3�
6
�LR���H=�q(u��S]�7n�����n�A�&sj�n:,���->`�d��.�������J���"�&L&���R^c&�o�j����)���t?b)�����F
���B�R^c��,^�C����Ev(��X�}���\�l2}������\����~�����cd������[�(�q��NJ�,{��L&�y2�����D��]�(�5ve�����MjRu������>d�zi}�5dx3&����C�1; 	�N]3��XI:�`@@ ���B����z44 L
��������@��Kk"%����x�Z�q��1��Q���X�}Q��4����8��Yv`��5�RJ�&���C�(c�L\��}�lC/m	�������'��~h@�&���tw�L���#C!s�w�|��]�TV���@����U2_�n�-�5f"r��#S;wy�!�������Xx��H&q�;~���yKy����I\$>K$q���o�5i^���?�`��t�4q/v��zkc�*/�V�P}r)��#�s��5.���M~����qzp/���/Q�H�i���������H�w��;�]~��'�HbW�M(�`:&��x�w�b&xLVH `: ����b��t��8.W����	L<��m�� L�qC/�-��O&~�-�m�6nL���R^c�-I���G���pu6���c��>����M&��=��,���M��%D=�L�Q^c����crA9�6�)�5�Z����C�
�(���Oo���v��:����Dif���m�2H�����[]h�g�5��tfG�q�L9����p�n���3 �N�������Z��A����(�t!��,�%���/g�>��� W��}��������[���8�<����[���/`BP&��X>DX^����Q�B�L�4;����z������(��j�{�C�K"�k��/b	��'/c'�U&�`:���X��;�Q ������R^c&�=~������F9P^��K�')�Q��0�R^c�iwS�A�`Yf�J������=h�
���h�`���8�]cuS���	��5=��5>��"Pq���������YerAq�r���R��{�L,�%��U�)�5~�Q��� P?��56���{p�;j#����K��������v�@�F�Co���k��v��F�L��<�k�E<B���\�F4W��S�kl���^�@�C�T�p��X~���l������s����I���Y�L-�bVa�0�]�$���r�l��Y�O_"��TCq��Q��3�q�$�Pv$9P^����LvdF����CVK�j8I�������vH��Z�0��Nx.	�k|��(�\�����o&V"��
)�8�G�S�yg�Z��D���P	��3��Q�����w)���X�}<����>���_ay�O�	���2q�����+��c������L�c3�b#P.��8�����?$��Cx�F9��R�&W�+�by����"���%�R^cW����+�\��Y��KgP^���	��6V^���5z��(������c�Gx�����W�r����Y�GI��(�|��������p��k��\m�e����R^���q�'rmd��q�'�Jy���8��#<��&Clx�k�za�y�X�<h�����x��`[��Ib�MG��i��3��p4z�h�������+�5V������"�F���{P^��=Q��<�(KB�e|:���f��x�^�CI�o2L%��������N��'�TzB�(������8�2��z[���X^��lb^McQ�����Q�U��8��^	&�Q�Y�ld)���WVNke�1�2�������������(�(Z�,�
��F�72$A��g�T��,�@���A�@�2g)��l�/�����	��P��s=o?M-!��s2�h�}3q-�����&��/�56�����@�7��������}���U��.)����7����w9���*"��sq�	�>�b��wg��/����3$B�#[�k������+��m�5����W(���^�����N��
	-o�2��xR���Y�Aq�Y2������o���$SLH�~��(����'�o�e�6�2~��t���}H��$���z,q�m�������M��=�M���8��R^��;M��^Aq��P�~���X}����y�����t1��X=�(?����<�=��a����{h	�r3:Qo��o����1K�]��V����My6��L�)��or�������BW���v373��L��'z�sj�(����y:+%��o P��]�k�h�R���_9=0<�
�5����q���=rAeVo���Gy�}����K�����8���=���5]��'����R^c�H���'[����*<D��5dd�hn-�����z)���T,UU���$�ax�k<����>�dDLr^d\aW�u��j/��e��"����5^���A��Q#�-��6?$�P�M�W�&�+x�k������H��W�"�,�[u(�8
Q0Q�5�"�v_@r�Ar�rJy���e����*
���Q�Q^c����$<�X_�te�����*x��\�O�D�N���(wXJy��w�Q��FrQSdTGrJy�]��k*$4E�u(�k���DUA@���KF����C�_wp���XT�M*,�)�5�U�^�m�~x�1M��k��qW$��(�-w�Jy���������������g���BE9PD�@	�5V"N�C�fj��R^��bg�@u�q\�\I����}���:C�(�*�
+��z*�[��|R��@y��{�w=	���%H@)������d�������-��u�t>��������>�.C�
����3c$���2B_iOw3������\�Q���R^c&��
�)C��vw���QA.�(Z�U�)�5~�CA#{�� 0
(�5��h���rE����[/W 4���[[�*#�^.>h���U�\�T��Ar��+��������$��v����TO� &�����w!��<F�&Gy�-��B�^�$�)�(W�*���#*� ��r�h�"Q������Qd�	(�5f�6��A.h��U���K�wvIF�2(0J)�5~�yI�������r
�����P��F"
��r[����*QEd*	(�5>�&�my��DL�����o2s������Ky����,|m�\�<0��].�Ux~4��^�g���W�~YaC����@po 0�9t&f�7��rA'e��Fy��nY�@y��LY��nY�Ay�F������B�\$>0S!J��L��=��"PId:Q��3�Y#��$2�h�������:{?�T@r qS^�d����N_����HY�k\�i�������A�{�r�1����\�'�)P^c%���e������Nr���}�`zj�I |�\��)�b3�����\�<0������5�u�����AqS��f���Qme&����mrU���#_u�Ir���B�N����w��*����6v�X������C��
I�ad.�5�$���+�X)(�}���O���DO���>��L*|� ?���7w~�|x-qx9���;w���]1�7������%������+�pf
I;�����GV��K��F�� 0m�w&�bL�db�IG���,�TcOl9����=���I6�4�&^��O�		��yl�I��4�^������7g2�9'���"�S���|[h�Y6�2���V��/��������f���,[v[eKj�T���KL4�,u[e#j��������R0���qn������L ��ZP���t��4�DCB&!Gy�}�g'��X�/���R^������$1�/�u� ��5��,���wrh�������5�b�y1�*��CB��{g���sN#T&�Rd��(�1���l�D�S0��Y�45���lv@���D���X^�Sq�eEq�m"�����3q��`��T&�`��Ll|����D W0��Un5��d��P�	,7�P`y����b��# zp�0J9���J���-��[z�L����>�X����`���Vk�z�"�$�I��Lj��m����j��@'��
��n;3�EF$zO���(��hL��]D�S�
���5���H�;D���x�
����P�W}����B������'�j�*v
H�N�F)���J��j�&�:q`�����q/b����b�'�:AR�jD���{���Mr���E����ay<�A�@H `�5V����W�`q`���g��x<������(0��u&f"r���(:L�N�Y7�����F�e 0PBy���1wL]V����s/���U���x+<x=/�]Hn��\g����jh�\pAq�W��Ra��f1��$r�eX�K���t�Ub�*�(�����������?>��������������/��n����e<��[9���_����������Z �u�&����K7���J���\��_��J����W������J����W�������g}���Sz��4��}����������r@��,�\����fU<�q������������O����~-z|��o��1���u����x��a���_/����������y�������c����5|��&������M��>_���~j�\�T��y-���_?}m"�����6��&��i#�O�����sq�m��e?a~�~i�����������M7����'�_�~in�~���Q��s��1�
�k���������Rto������X�uZ>L����;��������^	�n�t%�WM���6�9��f�e�C����m����s+�u>~��S+����u;��P[�_'�8��-���YR���fhv���[�o��mR�}�������-����h����[�_��5������[���j�����}��{��������,�p[�^�u��p[�~��=����q���=�f�B>��n������(��u.��^��{p��%������_��"n�J��[�)�#{p�8%
���
��6�K�����_"��yp�������y�\��<W���T/���u�yp_���yp[�^��a��������8,��5���)�k�{���)������=�v'���u����G���_�n��n��w�X�m
MN���p�.q��;
w�&q "'�0�8q��p�������}8����x��1'��y����v���GN�D��R��;���F'��^���I���;������K���k�n��n^:@7�R��p��u]���q��L��bn��Mq�q��[���&q���SV�����07nqn��%��U<��s5��qO��;�������{q7n�^��u���5���tcdG�q�:�.���)qk|H+�q���\����H����g��������Q���~w�~m���HoGS�l����G�X�)��E����O�5~i�p���1O������$a7��������4r�]Zt��=�&���q���Ik���r�8���r>�Fy|)%w��o��c��2���y8�2��y�?�{���q��}�l�t�7f\�9��q��h�����{r��{O��f��h�Q7����>�n^����n^��Y�W�x��K���8.��(�����4~Ps�����lM����G������.h�g����E�K`�N���G�r#�����5e)�n����!��[��i��[��#�4l�o����%��1������O�sG9��{���y=5 �cel�ok^{`A���	�Y�������h�����%i6��[��]G�����g&u`��v�mI��N��o�9����rJ������l�m8%n����z��}:5M�=����&�u�����:�n'�&i�I'�������I�1�7��gv4�7��������'_4�wZ9e��4t����>N�7N�h�����@`��{p��,�k��PO��9��'�r6�w�yx����������<<�?��[N�y�:M��q��]�i������������v'�u����#��]�uq��<-�����y#���R���������O�!�K��C��y�	C�:���6�w���I��	����!��8%��S6L�����v+��,�:p����4�X`������,��<��q�rx����Y�
�x����&��	9@'�<|��i���qg�kom���k{{�8��~�ivs�+3n��j�p��'���7�nlO���t{�[N����~����f2���������������?>��W�� ]U((���#R

����9��u=1h��q8(��S���}����8'(��S2��V�	
���	
,���I
,�cs�����'��OrXP�;�yP�;�yP�;�yP�;�yP���xP�����N'�<|��sY�C���[`��{���kD�is��n���������
���:7��)H&�p�k��)/��u�m��_{`��x��Ycx����ce��o�q���[6�K���I=rl�fDq8���3���G�M��#�&s`6�"��_��Yda�G`F�"�;k��n�/)iG��H��"��1�#��A�#��Q�#o�7�3�,��9�,��9�,��9�,����,�qI
���n�@������QEu��F6q��cL:J�1����rd���#�:~�_>�8�������"�������nh)��ni��o���I�2������2�,��m�8�������`�r`�&�vC��9��C�����Y&e��'���?w���� ����Q�'����O���9�����q����m��q�&��8�+�&�vk��e�{���� ����)���|P���2)G,��!aL;���p��n���	d�9���w!�4�7����x �z�7\�s�J<�w�H�I����x�$��L���&qJ<`�DF<��r�d��S���k�n�L�#�����'S�cK�,H�,pGy���;����;�[O`<�=�)p�9�NH�@�8�x���
��q�����5p�m8����8:X�����0��a>��0���@�����cn��$C��S�x��[�x4�R7o�`4����NL8y����I�x����n����"��"0�sB�9'$�[9���B��G	YH`q�<��B��	Z�<���������c�����������0o�<ZO
H���y	['�<�E`r'5���8�L�)$�[�k{{����~��	�6u�;Y�:������#���'�_g�p�8��s�I��K��n���`�Q'D��<
�>��R�6%
���Q�E�X�)Q�E�X�)�9���1`7t��������rJ������{��Q@� �Q@�(�Q@�0�Q�7����:���1`�s��NK�yX`���c�,
��y I�E�k��������Sc�Q����O��@z��~@>5�����B�p�S�F�|��v<�����.lm����6�����>����������O������X����w��H9���I��-'���?\����~���&��j`���G@[����r��nq�K���d����W�[��7I�f�mN����u���%p�������_��������*�G��g����Q����<p�XK�\	-�/�[��`����Z�x��&�����xu����y/������k��x6w������62P��z7r�>�M��<��{��C7f���t��m7\�,�P2����=���"����	Q�)y����o�{�����5}�zm��5��D2v��%����[���@��JG\-j����!��J�m��:V��\k�����
F2�G2f�?n������%r����Q
�
���sk�����������mX��?�T�P0�|Hy�d����6�P�����|B�����]�������{S����@
�u�;!�r��K��u����:CZ���&t���C/�O5ox�f�n.�����0�����A(���o�M�V����q��}?��3��5��p~�jI��!���}#�|��%�G���%kI?�;��-	��;%d0�#���c��19������|�ks�z�9����s�^��H��l���N�[��_�r��X��n
��/������)K����?"�.�V|-i]�A�bQ64�Z�h����Z�Z������E.
�<-	�F�esG�C8��^�c�{�|f�Z��{������l
������6�y��?�S��2�_g'��2����i��f�6�9�}v��"4_�~,Ya�s���AM~,Ya�s�����c�#���
���i&wB���~�3���������3�O3�s|��~���E��`S�dfc���p�fP�2�i�e��'�4������
^��&���+L���
�iiL�O3[>�"f`Y��@�hf�36�<��(-���������kM�����~��q��v��M��9���/�����SK�3
���)e�3
��7������������L��#�������������y�����<��[y�[�4���k���I>�������@������k:���S�����9��V��95=�[����'z��I��&uNhP'%zX��|�mT3gV1k7�#���������@Wa��N��0�*L���\�i�&�����Y	��;#�0�}L63��9�c0.sj����|X����+{~��E��al��]�a,�����[��g�05��`��2c7|h�<��0a�+Lk.$z_a�Y����>#��k���'z�;���3��Ig��?�9���^g�1s�����a�?"?���q4&uJ(cQ���������g`r����v�{��Co��wq�$�\�kIx���������Z�p\�]����G���������;Ks�[ �]�x�_:3y�9��,r���M������=�w1����V�i�����8m�)%�H�H��;�;�#[O�0;�%���5��~�g0x-�V�4&wFV^>3z�lf�4s������}
������_�-}��3I�������p�����=�����v�[ok�6ok�]�n�[Wl�.����c��U���'[�����]�qr�@��=/�������6�w���:G��I��c�s�-��jC�SR5�3E����-��N���D�:7?�	�f2G2TP����qJ<F�f����Y�}s��7����H�L���(��u�k��xf�4�`
d�2�3�c+��qu�>*�8�������s�[#(�Ho�������,�hTbq�O�)*�y�Y}��[X���9p[[X���d���;���b�GZ��f;\�[���4[�[�9��D�s$��R2/����)�kGs43�M��cV�3�f�>��y��>�M���}��_"Q���Fg��9��I~K�W����f���X����'�=�xnNvk�]��)�.�)��8t�#3F&u�����g��1�z/#h�[�5'cdR��8�e�t�V23Ff�3���9��T����a� 1���wd���dV7���,�I�>N�E2�_B��,�A�H�������f
n��V_���z�0�]���n����A�MN�&Js�b��&�m�m2X�(PW��
n���gEqf{���)��[��h�d6G� 3MnK�'NnK7�Q��%�9#��n��0=��i������7��e��q7�X��uu�3e�����gT?+T4�C+����9�Z��(f��V^�[=�CgW:c��cn_[�b�
��s�d��kj����,���	����if�l��dQ'��uh9�RM�!����)�2��?���8)��#/�B�h��;��������
v��S��$��Y�g������I�U��0����NVGfL�i���t�Nf�N�0�d�z 8�I�]��I��Xk_~���=���yNS��*�i���<D����H���x��n��F	<z���A��+���lq�n��]A��������G��Jg�(x��;l�Y��k��495Nxl~^?"I�b�����,�:ge7rF2����d~���Oe�-���n��b;�#��Nx��,�����EJn��[���������p���~�������/�����Ol��[���9;l���U��gaW�%�>��Kdm�.o�k�:�#{��:z.��t���s�Z����E�&i�yD�o���V6��_�����W -��ma�1������Z��#o1}3���kN�G}sk�JM���::3�+�a�,������!W�����+�A�%�,S:��q���5)�Y���a�9�n�e����,���;$���Y���u��d�vn��g�J
dm��3��m
^;����C�o8*�H#�{���q�\x���~	�[9����j�x��U��}�g�Z-����f������v�k��f�&������5��W�|�	g8���ze,^�wWs`�%z���1��4��,��(��s�j���~�dj$�^����R63z�!-��y5�4�I���A�����W���������E��F�f����^[�/�qf�'��d���a���/����{���s��q��n&��$pW�Z&y����������~m��!'f~B�s��[Rs�������u-�������"���A���eQ�9�kQ��"��A_��0O��8�3�:���3�_o�/��\-�;1WK�		������$��-	�%����%_�T��k�s��������^c�Z����[!_��LY��L�v����A����Y�G`�a��$�����8����I�;���+YK��2�$����%�5DSK[4�y9ZHf�����r09/�;#/�cN���L+�s��av[��Jf��kK��f���=�R��uV�e6���Zo�
��|h����=g�y���9Y6�K��_K�������P��|�z!��hI {�9/GK�&N��$N�x3�"��"�+�9��Ur[��J�1�p�uuq�
7s8I�"�I� hS�?����E��$bQ
�D��kfk���;s�v��,��k�&|J��>rC��������k��G`�sC���;��Mz�zD7iqg���u�Dx�<�\c��l��� ��Z"�8������8c�������ud���2�����?���������_"O3�e������r�$|
���pn��%�������W��iIxS�&��`�����q>�c��K�3cx�����ax.�u�����/?�"MJ�����,��6?�[���-�[f[	����I~X�����%��4_K��������%����o9Z��$i������2�3�A���oe3��JgF������������C����)�X���/��2���.�:)�n�H$���I�#�R;�/WK�a��%)�����������v�����%��s_&��mT6�L
�v�;e���s�s�#����� �����������C��[�I��ud���.�1R��-��d���2m���T��.WK�������r�$|/`��p��hI��5w]������epg<L�����l����a�'�{�	�+���n��7�i�1��-����k�	%��}o�9X�	^���6�v�3����36,<��7�Q����p,��1��Y�
]�B���9������}�����5��	�6��rbrfq$!���S�����jn��7���)v-��E���/TX�9���n(�~�S��G�P��:77�8�9��b�9��}��g,�}3�1�1�o�u�������7�9c�.��A��NL���
 &gFb\zC+|u�k>&�K��>���a��G�NZ:��p��A�T:2)*.�d~�o��5�6����1-C�L����Q���7E�q&#�OnR��d0S��tt�y���V�L�Ix���"��3.2Ef�SL��8,�;���}�7�@��-i	�d�,�3d�Vr3dR�'Vr3dPG�r3��tt��i���2C�a����NKN%�2�#�L4wD����;"q��|@�U�4AJf�u���
�<�9���n�,��~MH�7�C��3���t�<���.!�dR�v�<�-���3Of�V�]���J�'��h�=J�1�G}��%���bM�Gq$�`���n�����b�r[��#��[wY����3�d���d�=�+�p���>&�2��!�E��[o���`�~��
I��d���[����������
�I�>����~	D���9-7tnKG�IOZ:z��IK��t*y���,����e0��y��A#��D�����|���gFn�]�$CdR�6�QqCdP��$��-���/P�-���i��]~�������+���Vn1����%=���L	��,SdR�,FY���$f��v��M����u&S��tx��n�����)2+��)r�����L�?��|1j��$P�5�����G&u����/����=rZ:>52�#��H���~M8�~���l&��		�.s{��S#�9a1�a����Ws���k�E��C}�E����6�HN#'$�'�4�Hvs�l�Y�_On3�d�t�E��#cy�cn�h�<������jE�ny��a�7���o�~���O��oO�������ft��$
�M�*��g����?�m?+���	o�����\���xu���`������q�������������<������[�������\���/���n�iw�iu8>krG�`K��mw-|����V�y�y/����#��$��d���6x��bf�
���<���j�Hb=3�f�]������X�L�AyUx?S��k�N���1�q?����Z�/js[ov����#d�
�[o�&�fC'�g���y	���S���������8S����b�
�ko����7��kd�Y{�[�I���9����p����q�l�����jf�
���D�l�����A6�9��O��qs�d�������?�DJ�
endstream
endobj
15
0
obj
16861
endobj
16
0
obj
[
]
endobj
17
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
18
0
R
/Resources
19
0
R
/Annots
21
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
18
0
obj
<<
/Filter
/FlateDecode
/Length
20
0
R
>>
stream
x��}[�%�q�<�)����`?h���c�DN�6 �!���;����j�������
D��O���,Yd�����������?��x���_����9����?\���g������o4��5�������am���]��s�.K\�*���i������+���<tc7�#�am�;��������o�i�C�����C��Vh��������1������������ L�T>�;"L�.i�����:�T~�+HD\���2�����vQ?�����P��P�P>������O.)%����1��D�rI)	/���q(�'���KJ��t�2�T~G���KJI���JD�C�=��\RJ��`)c���+�(O����0�����R^&K�P~O�2YD����2�T~G���KJI�[��7;�{�1�On"��Ph4��1���;�l� L�T>�;"L�.i�	���u���1����&L�T>�;"L�.i�	���u����2����&L�T>�;"L�.i�����:�T~�+HD\���2����S�KZk�}o�"�m���Z]�Z&J*��l?��Gk�������FD\k�DI�c�#�������l�����������0QR���0����&��)(�s~J2����&L�T>�;"L�.i��[;�����}�jW�,"`��c�'������po'����������0QR���0����&<��x����jjuIkM�(�|�wD�Z]�Z^�b?�c~b5����&L�T>�;"L�.i�^���:�T~�+;w����2����S�KZk��uY��'VS�KZk�DI�c�#�������`��w��������0QR���h&��KJIx
S�����X�O.)%�e��1������%�xm&Cc*�#b��%�$��VD���|a~rI)	���q�7�A)��\RJ��5�	������R^��J��7��'��r�C��c.�~rI)	���6o@�O.)%����1�������R�K�1?��O.)%�u��1�������R��fu�`*�#b��%�$��VD����`��%�$<��_�����@��%�$<��H�c<�G���%��kCc*�#b��%�$��VD����6?������R����n��KJIx�-e��������\RJ����|���X���R�7���1������R�&+"���;�rI)	���qwt
~rI)	O����p��~rI)	/����t��~rI)Z���`*�#b��%�$��VD�������KJIx�,e����6?������R�x<Z���\RJ��Y��x>Z���\R������L�wDl?��������q{�2?������R��?Z���\RJ��b)c<���O.)%����S<���O.)e�SgV�	��;"��\RJ�CkE��;\�o?����'�O����'����bW�	�W��O.)e�scW�1��;"��\RJ��]�'�9\�o?�����Opw�2�~rI)	Ov%��!?��O.)%�e��1�W��O.)e�KcW�1��;"��\RJ��]�'�9\�o?������R��?\�o?����g�O����'����jW�	�W��O.)e�kkW�1��7��u����E^�\�������cgXoB��Z}Ne�f��Y���E\|�|��b�v�����o+A���:5�2��?^�^Y{-�k�U�0QE\>��w]�,K�����]-��C"�m��S��������\=���u��#�m�Y�Sf(s��x�0�#�c���$�,����>Lzc��G�kS���q���nC�[����j���I
��,u�����P>����^s����6�����8�05������\������|�c��yz��W��eu�(�8�o+��I�
��E����-��
�0<.cu�y�����h���eM ��)v����|������U��^�F�X a���~�|S�3Y+H*i���Pq��|�w?S��a��(N���(c ������B�	K���m�#3���3���T�,en >�=}k���|�h�~��1��y8)��&���O�,g �	8���BD�5��2���g?m�����S��X���1��b��.Vw�i�%�r�b+���g�%�����R�[U�7"��|�U���9����&�%�j�09`���8{0:�t.��r�M�[)�|���;�m�6���M�"�9�<�����cf�Ir���x"�����}����X��@��n����\��%��Y��@���J����6�W:�_�|����[��%�����(6��5� ���2��1�1�,i�jB���|�O��I��	������j���������R�p����c����".�P0]��1V�NY�`I,�P�kz+&�����$����
eq�M�P>�{�u����`.�@F��cl���������v a���@�=�.��\2�$�0���?�8dY�h{�0���1��I�{,b�=I�)��T7s�:XAH�,
P�|��M�'B�PQ�)�%Lb�|�Oil�3�S�([4^��1����1������L�#�f����Z(c-/�%�gm�H*[4^��V�V>����Ne�Eb���[Dr�o+c����FHv��>���|���<a:��l��E$u�pA����k��#����A8h,Ok;����l���1>��twN�����p�y�ka�`A.�9�}�"g+�O+
�Y�b�&`����|�����,0`�4G�.��f�@��l��A�\���1���7#Y �6^>�V@(c%���+�.K���T�C�c�s���@�m$0�����t���j��c��I����E6S�1,�0S�
��7�
z���,�0�S�yh��#��-�	=���i���?DwGD��@l��:����5�ER8��E/b6��s�����hLO�D,�s�.���|�����#�e�����	�c]m��d:H �{!X2��1����x��I%�eg`)�|�#��$V��+f��%����e��R�fsq��g��D�h{�0���1����9��F��9����/��lv��/���1�����[34��b��~�G�r{�lNH�l#)5�|���3.���������VN(��{olAH�u'	�c�#��mo�9� ,	I�O�^��ryx������1��4�$�F2��(�|�?�i<RI�j{�0�	�c��iaD"h���6��R��1�>���$r�-�I������2�o"�0S.
������+��p�~��c����jI�B$�����Yz�|��r31@l�k�&^��VN(�H���`�Dr�b�����B��{i��r�dFi�XN(��~/�I�2��%,Y���+�9��c���W)�[�|�?��l3I�h��0���1���a�IrW���Y�8@�6��ndKk�~�B������*�V^�Y��1����������L�4����c�����l`mL.���1���;Sd9I YVsI����1���d#iYD�B���1��}W����1���m+��obCH"�P��8M�V>����-`��W|��B������������P>�Z�	o��Im��RB��u�:�-"V�q�|���������jo��[��Mx������.VQf1�|�#�'���6������4��{rWo��!l m<���1�����"�������T>�J�mR>���DeAY*[L/RB�GR�.KE.N/�*C�[�'��D*�R�BM���1N�t���@������J�c���d�Iq���T�����x'�
�G1��#L�T>���&]����`����8;J��DX.�:�O���1�:���.�'����E,��������W8F���`�l$X%2�X!��&������K�I���x'y�-{c�Ef�P>����_/�\2k���d�
�c}Zf�/��e`q�%�mq*.7,Z�}<��]I��v�]yX��"7N��8�{6@t�$\<x�pH��c��p}f�J����i��r�|���_���,�������~��*K��'�����1�����ky���t�h�����w�e,��t:�o��1����P���"6�K��8�G���������`o8�W��1���n5��0X`�������$����v��B�+�g���,6'��c|�;I�I 
�����N*������,b��D�3����)�O!,7�=��3���1�r�m�����G��;���T>��Jx�`u'�4�X�Z
���%]�z������J��|����U�a@��[���jn�QY`�*|�p,
1�o
XR������������8G�V>�;�$����Z6����|�Uf��Gm;O�|�oCi�H%mg[�j)\>�V�Q(�tk�%�BB�[�g�O"�4������1�r��lp��;Y��:����1w=8�/$�� ��;�]Y�Ii>���Y�c|��D�m�������h����~���4l!?r@�c��=\6�@6tP��1����m�ED���E(��o�Cn�@z��	��P>�����	�X~o��	�70�AS���%�����<7�tR("F�iT>����,	\m�f���7m;~,"���L��8���Xk�X}H�U���J�*Y��=+1D6�py���d��!�IR�6�F���%���qfx���A�,�0�	�c�=;�X�V$6`�l�A���lll����	�c��X���"��^�Y ��w|8����6�\�,gn ��4�<6�QD����|�?�il�ll��]m�Q�����/������m:c�H*�,�(RB�g�V��I�1M6�Q��o+��Q7��(>�-�Hq�G����1�(�(��|k�J���e�Y(aI��@l��>�d�l���b��8m��	%{eE`�lV(��W
l����w���������F����~��������6����tr�`X��`X�b�E�Y�@|n� ��p���;����|�'�4�����g�4�mP���x��8v�H �s"'��1��}�8�6@N�{���8n����G�����3s[��oW�6j��^�[��������f����P>�V�r�:��xO9v����}�Ss_&�eKm�<K��a�Eh�d�eC�D�j{3��q^�T>^��`f��Xl�"f+�|���D?��Qu"4~��_>��b�l\����b���cK�z0���H%Cg����@*c+���3��r	K���k�#��A�Jf����{��|�OHkKV�����P>��-$l�X�;����\ ���5��m,��$�k 6b�-���,w����t;U�I�Hmo�,v�Q�X?��^$,���w^�b�E�l���%]�1�"|����������q4���;���.6n6��^���1VOw����v��6���[ ���Kz�R���7���8�*��Sy�b�e��Df��Z����<>L����a#��K��|�#������,�9^]����1�rO���T�r6�O��
�VjOG����s�����`&2G���%�\��ypj��������v+����C{l�fk�HaI87A��OYl�H�bU&y�_ ��*��;fgzO��b�'��L�a6BQ,�����C���)�L��l��8�H����'���%�\��6e�E�������P>��MO��w�/���*��%����c�l�l�%� ,��?�il�l���mR�Gr�uh57���A�"v�=I�c�/���Z��#��%��qV����\"u���<��/����=eJ��_C�0�N�c<GO��x��:��`�����Hy(c-�xg��	%s6����B��1F_�{�(�Ac��7���1��2s��������X�h<��q��`��E�#�w������[�r����`�-���|��`��m��Y@(�E�34$�I
X�l�c|�3�F����g��$�[>m������G����	V/g�
�NR���������[ �}Q�1"���p]��cl?���a�acvEj��U��8���"���
X��
Gr���X.[^�����1��H66*�E�Tr
���2�c��5+*�:��$,��:��;�q��?��Fn���#�mUcl$�B�gZT6X$u��B�������b�Zk��}����`����]]6Z$��/dZ-���8z���P�����Lo��1�yD��� �B"��u��)O�P�\�+���mI�cl��M���������v
������K�����f]��a�dkx531T>�����Y��^%,����@t���������w�Y%�9���� ���n��
=J(-���oX����'x8G��K�X�56��p�+��KW�����������&x��|��_E*}�
�%)\>����cP��
���|���@�S����"�>�����Te+�X`4��O[>�a�i�
JpcbN>�*R�{l��*����C7Djoc6��v�1	��q���)b��l��*������rW_���nX}�dO<d���6U����������?���7,����n �C����"p��D`�r_��8�������VY"7`�0=@����=�������2��q^���=���R���$x2��G1+�W�G�,w����S�p�Ja�SD@(�H��,�_{�""�����%����a�����j!��t���VL(���yo�bw�7�j34���1������fIA5X�3s(�D����@2X���
���1���aA�X��V>�F���4���d�w�����8{�R#���$w�J��|��w�h��A
XigovLS���Q��PbI5�*���1����X���c�7��P>�V���*i���TR����J*��D+
���2��q$���]o��Vz3�=���>1bE0�RJn�r�q���=��H
���H%,��#���(���leF#���8+vW[Y*i��#SRB�������\VY�#�V+'��q$��&�j�-���*���O�x�J0k���P���VF���S�):I7�Sm�r���8���;fJ i+[����1��I%�T���l)C��-Y�:��$���n� m���r%�m��<��Nr����l[R��������1�D�X7�H���y�B�+����}�[����x�;�}Y�v[�b_��l�%���W,
�p���������g��*��|��7�H�h.���P>�Z���+�����nX�l�cl��WR�J9%1[��sE���i�JW{�_����EH�=�u�,7�S���:�%�XQ��K���X�;�G������\� ����zSrI_�
L%'����{ZY,�+���V+&���'?W������w4;�)����}�e���f/�p�G��e�������c�~��]a%�4�\�z*��/b%3����%�{���I'�����R��� ���>;P
HJ`�X���x�p�incn�-���{3����������lG'�����
��f�����������|+��o3��,���8+�;\wVU����cW���uvS5�T>������oMue��[Yj�V	�Y��DnK������vK.�].6N_�N24*��uv���P��H.<v��W]Y������Nv#)���v��vcI�,����W!�<v�a��{��~_���n9W���@�
�@<���^������D�{�&vKow1QC����S� �vo�+���6+aK
��R7�KP��p$�7#���������r?�-����q$U����m�7�~e���v�����1��������:�o�O�a������dR��YG:�:�"5��:�	�����vmL�/�(�k�T������V<�q?Y�[��Y;�Vj�`(�"y����U���Lp��$#�U����L����q"C�}h�P��c���#����uAEf��u9�m��=�~�>��U�N�K��K2 �Y!K����:f"5`��X �yM�A�kbq�%l��8��n�'��lX��b��O����v����
x��L�#���`&XJ��`�b+��\PzK�hB�D���T����u�6,};��u�1��e���G��}�2,����rCk]�Gbe�rOg���-�
�~%������[![���JK4�R��)d���&�I���1�������!(��Cc��
�n�����&���Z�M�WEj�E�po��[�j�H��>�%+R�����8�V�����M��RC?�������8���h�(��oXu�h=��� t��;���"5`9�^ �K���;��rG�����P>�Y�hW@:�������0���L��:���
�~���C������/"�:�nE�.c%���������@�, ��1�{�'��l`� ����a�Eb^Y�V��Uw�vk%����8H�B}c�=Df���]Ip$e�"�Ro���a�����1��{�����J(}����$qAX=�[��a���u���������co��+�����:�V"F�|&�?��J�Xm��%g��%x4��S<Tg�������b�x����o����a%n��Q��O������R	�B���9K����x�%���I?0����p��r	��P>��U�Ra1��q����EU��zB1���ciD ����&9�Y���X\�yY\�B���1����X����
��P>�Z���g]X�����E�V>��������������Jp��E��,b������lk�X�=���H[Ha9�j �>��U�	�Y50���1����
%6�*�
����1�bO��m$���$�0�	�cl��.#E!���a����(<���#�%��:���&�L&8hf.R{+BD<Y.�C�����X.���*!rB��rL������u&7��p��c���^u�u#E`�r�@��2z���X��L��P>�V���B�aJ��v��������<�g+ �������$X.+kk�����1�v�^z�+�u�7,�;7�U�1����X�Y�nxn���H�q+�N�	���������4HB���� �Y�~;�c�g�DE.i��G!r��1�t;�v�{,7`����q�{a�O�N�A�a����Ipc�*�/"HS�v�����+�v'Hm�%,��
�;��Jg#>DD�r��A��Oc�#���l�f+'����{����
e��YH(�O~�������R���$����H
j����nc%X	���e���6�E���1�r����XRZ��b�|�#�'}K:k����P>��meVK{���f9�|��:���`�07��i���	L����6���c�jf	Vh ��)�~,�z�^��%.��8��C�:�^�`��YL(c+�tx�<���
+;����O6����XJ*i���% b�8�z�������`��% ��X����c��1C".`	�� �_y�#�rIe�����8�{��f�����a���8+7
z}�aR�]��c*��Q��,�4��3,�� ��5g������oX}dow���M\�F��:{k���7�9���mvo|�0�b+�d�����
����m��\�^��H
��R���b+���.��������n�%x,	+��e6�d�S�b%��Ra������g�v#,�sfKCGU�~���n������|�8'v?vY�N���k�������nB��qv#e����H�iw���)��,r��1�ro����_^��?�y�����o������_\���9>�����T�K��H�_�V����������o�f� �����o���J������n���+��:��r%{Ug�[�d������U��o��^�4�Bo������c�����	���AQ�~4���7���������7���_�������O�pO���`������������:�������3�o.����?<����^���7������s���_m��a��o���s���;��W��e�c���z�-k�����������}*�����?o���6~���J�RF~��������{�q���2���}���[c��Q���]�������ufl1����?)����9������=3O�>�S)s{��;m�^����~��2+�|KS?}{t�e�Z�.#�v���<e��6���X�e���].4�b��v���X��m���\��r��v������z�]F�[���o��d������um3�3?��i�k���o���/�������~e.[(N���g�[f*�����-e��S�RYL=�}-���2�����ooz�g�d�z_k]
��~������#O(����l�+a0t������m�n���^���i�����yv�'j������XL�u���u�?������=��;y�����]��;y�
A��RXk���X�R'v�3U7��T���>aS�
mJ;N����lJ�N�rhS
����6�{�
��z`S+`������rU\������������)��r{{�g��<����F+@�������u��_
gj\���{��o����E5��~��G1�u]����5��Em!�q�n����b�kz��y�����`i��z}$��Xl���x�l�����������lc�	�r�`3?�OL�1�o����u�r�`[?�;�}(�[���1*��R�$�����#H���s�c��n�������)%���x����)lg�'��#�{�������X��v�Qk�A;��i�e��c�B9C��x�Z9C;v���g��w��;�3��#�*���|9&��-?��=��E�@���+�a.n��:�K����[�r�����|$��q�S(�P��W�z����+efg�� 1o��Q�������e������v��GShg��c���!@���R�3��E���m�t����l���@���r� ��})P��P�3�J��!H�to��0<q��Z�e�H��K9C;�P���Rjq��v����3��#��Q9CY;R8�3��#/��J������n�����r�`��6X�c��)��Z�#H�xwFK��1�5"Y��x"Y�5�[cq�25��e���r�5���ej\��kT����ncq��3c��y�#��:rz�@��7Zk��i�[��Q��-_Tk�6�c�����`{�s�;��U���`K����;�m��Y���KX�$�hU�Q��Q��������)������<%H���K��RU��=��I�����S�����P�R���=%hS<'R�)A���nU�R�����Yul[��}�n-(�(cGu�;����U�$����G�#�]�;�zR�;�5.�����-!�Q�%�}�������;�]g���]g��jk��|���v[��Q��S��p�I��q�G�����m�)�G��J("���(�������#D��G����?B�[(]a���G���|��?J������n}sD�*�����+A�eLI���EQ�Q���O�r6���(oS
G��Gy�R���Q������M)�D���lJ���S6�������s�P|%<�~x���r6��B����Jb�y����.��mT���+�j������J9�r��|����A;�{t��c.����R��������Z7^�2�2>�����?O������q�Gl+'�����	��[\_���������1��?��N��-��P��g+P��������?<ak��]��"��ynj(�x.+,cP�9r��n��IQ9���������6����?�����1hS~8���������*L���q�W����}��elJl���}0���s��U�+�;���
�����q��t5#{5.����|��N<��-��|����=T��+��~���w�5^��8*�GWW7���G���!��q�	��9�B�['�n�:�T��R�~��9*���3�R%�hC���!��7O62� A�J������w���Eq��L�;���M��T�m�v��6��/oS
=�A��V���)��)�'`����r���-�e�H� �=;R���)�#���s&N��������.NQ��S��qy�i>���,GSf"���,S�k,�Q��cT���X�:3�F�[�]��Ix��g��M��J��}-��r�q�������C����r�u�Tx������p�k��#��4��v�`�n�;��Mx�|�d�W�$�d�P�Q��������el��~S����7�m�;-^��*�r��M�r�)gS^<���)�R������Mq\+UnR����k�r�vlJi�=���������a.O��1|��x*���5�;U���������9?�[c����o�(e��� r������������|������A���-!�*I�y�xK��=W��[B�����-!�7��'�n�'���D�����I�+&�d�	�����;��0��g�$R�����~��t��}�r�)oGJs�����#��:����S�!a;��3-R��<;N��CJ�������r6��w$R��8nM����)r:HB�5�����x�9��_4�\_GR�:�QR�vf)�������_����#�g�(;��(���=��+^G�5��pm���o���q-	����G<$@�zEyH�z[�F�(	��+���`k���6*	��y������#��M<c><��C�X��J93�>C��]��A<��q�!��H�A�xH��8r)(	��#����v������y�^��#�|������`���?��P�"�]�+�z�9�b�(�����������a��;G�A�{D\W��\��qy��i����u�k�gF�����+m�a�Vxn���2�����qi~�m�L��f���
D����F	�[�tV��-�?&9$R�����7����m�v������^�9O��Z�������%F�)�j�J9pF�_�Qi�0�+0�0���cI7���
�p�0Q�����n^/f����r�v�k3��t��|G�=���zb��m?N���G�UBTo���o����iPM����s��&o@�ro�B��&o@��97U�wU���7l��u��G4d�������&l�v������ [BRoJ�\��$��A�9���i�����Yy������2/O�Uyy�^����8����*�����I) �������#$NM����qQO�H��q����L�U�NO�U�NO��s�����;D^�JO�d���]iR�u�A6�+=�a�6�c���:�\!>�v�e��5n�T������9�+�\!�ij��=P�Z��F�5fm��Z��Y7o������YQ���������6���9�s��9�s?��S;�{�W;w�}^���v^�J���y��lb�1{�'���[|��36V
�+���c.O�3��?g���oP�������x�����o�-q�[n+��
�k����s�����c��l@]k��(�{K�t���������9;�v�-q�u�l�v��^5gg��{�����u��6`�px��P���1oy\"���.�q�;����kk�8_����N�-�;�o9C}�$!^o��,OS����Fp��IuGn)�����������R�-��$��1��?�d�?<��j��=i������%��+L�����7���3(�q�j��������_��2��PW$�������Q~�~�\.�m�H�������H�ZO��j=	��Gy�,�rz��x�E.���#UV�����S��*R����U���!�\~g�2������z+�j�v+�j�v��>P}��`��j�	S���g�#>�[e���g�����q��0�m�H�����jq`K;��J
���]I��=����{�P��������@O��}�=�y����c^���JXT~��>�*.Av��F\�K���-f8��g��o 7�o�*�z��!�r:��O�#��=��Hp\��n@�#����5.^���8�-��vKpB�������v��G�W���t?�v\�L��l�E���2
��O7���A�U��[#��-����@�9���l�*� �-�������#.A����]���@��3w+o ���GPq�7�����~�&7��Uy�1��$����[V�����%�xp�;��������97�70�7��z���_�c��9� d������d���IA���$'bv85rN��q�s�s�9A��"uk���	��,'��yh�=�+v�3�<JTl��~��0��Fl1��� �*���y��
�{����p�Q�V
� �7��������K����A�[o��-���������;�+`y��=�x�S\��@w?�����=����� ?��Z\�/0����H�.QC)u���	_ g	�~�/�k|����n�F
���QC�[�3#f�}������@�����8xL�=����1C9�������J=[��_��	b����5��o_W
�m����|��j���D(}�D|���7�/��=�rT�R�{�r������������1��
zw�P~�������PI~�6����w\ ���"��^�v,���K���Mt�t)^����
[�\#/F�����DT�������v�q�qyQ������Z��?P[���0?��b��e��b�-��V~�����cF��{����K���=f���{�)oz����7���MI�q�w�'P�~�&)r
�3�v�(P���(�P[j����Q*�����Ff��:2��U��J������9?�������&��wG$��I@�v��*���r����C}	#��}d�{����'�=����b�&a^v�����n���u�s-b�ma�k�����i���uB<��m,�G��{{y�����8�x��J@��r{6n��
����W@��n/���\)�C������)���=k�$���B���r
`m����&sC�����
����[Bd}���8�A������f�r��w,E�#��w]9���>\���s:�H4�����Ss9z�4x�3���a.F�����	���#����m�I�p[�����B8R���C���[��	�=F�	��;���[qV�D�5R!�*��"�Z�`��D���X('P������R
#8J<9���L��j���<����:�����8��~���qG?\���?le��\����\T�-�H	��;��
"��d`U'	u���w��'�A��C�	�4~y�!v2���M��a��d���r��<�h��N`��i���X����'n@���P���V��~������/�xk�X�x��3��������e�u�D��z��}��O�$~� ��VB�/@)5JgZ��\���2Vy�97��X+��A������[	�A_�xg��s�<�=����y��J�_�����E�
������
r6���;��F��s�V-{9f���\#�i������h��^����~� Wc������>A�����>A�/�"���'�5�o��D\�'�m��P>lfG"u���f��|��+^@���/�+&�$�����O�Q�:>Af��}h�*	��;�i~��3����@~��^��P�y�e��������W}�F����m�\�x�q{n�m����df���?�i�:�IA�:�I����
>)�����x�����������JO���fz�eL�R��o��������������_~�k�X��y��"}3����o�������_}�u��^}n���Ux��.��i�\�<�[)��^U���e��&����������uY���_#L�������i����J�����q�I�Y�[:������LTZ�H����hF�u���w?�=G�u���9�U����?S��o�V���z��z�6�^�x��x��������q��vYp���o��<�{o1{V�t��x+ET�]���J���#��V:@�z�*��Jk��A-Jk���d#�{�F�-��Q���u��\T)�-O���PoF��-%V:XkG�t�����t��w��J��m�8_�����j�����v_�*���P�c�k[��j���������{�o#z[j���SR����n��O��u�m�'_���s��H�)�sL����2��.��-��G��K��y�l���p��p�0]Wy{�����b���'�Uj��<G�z�����i�;�\��N��������W�<�-�2��y�^��c�(�� ���0
5��[���X==�������Y�K��n;`�?���e+�unv�?�������/�~��dP_�=&[�d}y�2�A}���8�o�������������^;o��������g�^��<�jm���:.���_~�]+�w����C7v��?�v��{i�������n��/��k�3����/�G�C����s��Q����V�_rk�����=���g�5N�s5��v�g�����|m��]�av��C�TK���0�����>��'������^��Vf|H�x���{���f����T<�L��|�����K�{_�z?;���\���5}��3���@�5;2�m��f5������@�
'+���p��>3�]_�|���L>k����%\MI��j
�O�8l=��W���=3����M����z6��|��=A=���`�
�c5����d�S�T�.��f������rZk�Voa�x��2Z�x�U�lPk�{����mGk
�d��2����,sq+�,�����p+�:/�k�����i���P�V�����p=�j�Z^�f�z;m.��U�$�v�
�K���?��J=���<�&�����v�d��=���k��G�75�e4�s/J&0�)O�}u5�e4�B(�N�;�!��)�� o�t��W����U���������fJ���<���6��1$�(�rH�!r�+�y��z.~���N�>��" ���������Sg9�����SD:����^�UscF[����1�-�=Q�3��8\UscF[�27�*�(���|���3���e���#�/`^���x[�_0��!x�{�
�?�2n�y�?�C�K�>�<�o�7��8�&����gk8�&���
m���v��{�+�/�;c2�e���)3��-K�5��!!Xfhc�	���W�#����-�&;>�m��_rk�������������,k3���a�0��f�p�������OH��y�P�ta}���=�#�!�=�#��pK����vk���:����rm���n^S�{��z�Ck���V�)j����������~+n���sr�`p��87�1�'��u�	�>3m�"fO�Q�^o�s����������vO�1��� �0)s��Q'}�c�po�"��o�'��t��q��������a�JS:��tG��'�FM7Myq�O�t�������q{��x���]#3�\|E���*��2���@����y2��!zz��/��@���+���fH��X�������Fd�$��Lw��3��w;��sd:��F �^g�f���2��[&���2�aw�&��f���Z�������u���C;�+e�$�V���JBVw	��G�8DN�
��a��.+�'A����X�6A`�;��X�s��`�[��YP&@X}R��r@�\�AP�����������`J!�K�}8�*�,�C�~��_D��9)�5;�~�������r+�S���)N�����qA��=�?)�W�N�y+������|�v���v"����5������R)$�~�<��&���
�ss��^�V��K.� ��������=;�J�`����]����s���o�. fG`<���9
'������DJN�7e�|�d/�Z��8L��Y�������U0"��|��^����q]�7�rm^>��
�\�;�y�	q��v�]Yc��:3l�m�Nk�`g5�ROzqySftj�Tzj��j�`I
m�2S��)xd���\��,���d�Js����/�Cie� ��L�b'�*����,�TeC��j*8���
���� :�>;��C��=)��mB�?\��*�����+�+�����u��G�.��~��P�]���J��v)�(�8w�J�knsM�i1��b�����b^k�������!�'O�
e���c�A��Rf�,q��?����H������%��+e�:n�����U
}��7������W�e��c.�;i��c.���s�~��Z���!�GOve������0�Q8RtjC�o�8��\1T���>��im�2�P�6��i�����`��V���m+^u%�����Yu���MS�Je�Ko�HZ�~ICB���A���{D�x�&,�����`�HZL��I�=�6�S�V�����\�{����X���k\����c�PBH��9��5����!d��~�2/o�a^o���|A�"�n��-��+���L�|��v[&D���-�\�=���2!r�L��1L����$�	�x�l�0�S��T����W2�5����/�E�����XFD��HM��FD���6�m�?B��;�"����T���=1�8B����=Q����T��.��~��*��)y�����=�Qc��X�c����l4�6_
�h�����F�/w�������#��6i�����Mlo�K�b��+�W6�S�T��<���1�����W���:3/�2��9�i;,�\a�~��$��>:�"kS��s���G���}�T�
P�6��M�6T����SkC[�m��������h�[���JL��b�2�<��?)`������������A������]�����������������������HR��T����s���D��ZV�}<H���3V�a�|;�p�6���7���q{�A��n�[�HZ76�"���FM9��E�UjyP�R@T���K�V@L��3��b�7��Q@�]�(�����=8�_��H��)�/��?\|����v������c5�&�\�p�����q��LD�R''�~s�u��.[k���Z;N�D�`����c���m��$������)����	P���qCS��v�����|�b��Gq�\gW����uf��vV)e�,&j��_h�������q��&�pl�������~Q�������'R��a���R�sH��I.(��9���n��&w�s����8�PH�BL����#�p��BV����s�70k�R��\K����1{����j�s2�A����{C��o�>�E����:����C�9���/����L���f�S�;�w���l5����J@2���:������%�JEot���S���ay�kj	�Sy�_���j��e��:������f��z+�����6�����_rk~vEai����!-K*��5^��1��4������g���s��/��/��E�����lr!����^P�!��;E"���KT�5	o����j[jHHDV�\��"��k����5�u��RPS\1�j)5���G��r���|�U���<{V��%��������\������<��l��|��g��-��h��Kb���#������'SM_�1=wa���}�%�����M=}��~���5w�;5}AM�"��5���A��h��G����v4��\M_PS������L ��p�D������U�Y��s�+�\�~�i�f����%Q���<�HOb���a�%�X�������Ox���(���|����;�o>j�c�z>���Hf$�YVi���[��rBiL k�i�S��[�[v2��.xq�r�S\Fy3�Lq�����Slm�GG���F��[��N��LKT�[�����:�a��?�bv�4!���?��n}�_=i���!/'������OO���ZH&�Di��`�,?<0�(��x��f���QpF[��jv�hKyN=;f����YX�]��������+sce^������9�s[�&��_�4����!r
f*�2!�"��S �������o
f�MN�e�N��r��P.3���ur�����F0SN_�|d����n�_r�#���H�K�`��#<b�����`�������[sF���K�����V�=��3��|G��_3�
X����	i!����:3o��g�3`��Y��*
�z�#�n�W�^B����s��+E/!�a{�p�_����=�d��%D��z�C�@
	����)x�<�)��XS����SFS�E��SFS<�.���5���[��)��].5{�&��1<{e����X�;��<��g���<sUmu�;O_���>;G����<�p���s���/@��m{E���������/@��L�+���������������j���EB5}�hJ��52}e4��|�]M_PS"��t��M^#�G}f���g:`�+S�r�������La�-��/5�-_�$�:^0TS�~u�m'�K)s��e��%�	�8�6�M��8�� 	��;5R^i�����g6[NkMx������2D��G$3[Fk�\+����y���e�����e1o�q/�juyeV�6�sY����-������*
���4Le�P������"Vw"����mu���]A�r����nd��f���������Q�a�s�k^��X i����<H��9�V����������8���l���������H@�CD����W.�v%��5/�vm���Q����\��"���������x`h���*�}����P{B��B�Z�?��P�9R�+{�FlA���
Q�v��\��U��K�{����\�v���'J��sW�M_B���b�'�joqB�`���E�n��>�����ZZb�'G��:����#���Y><��,�1��E������|/W2���q�%[q{m^��:lh!�Z����U�����x���������-u
endstream
endobj
20
0
obj
20899
endobj
21
0
obj
[
]
endobj
23
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
24
0
R
/Resources
25
0
R
/Annots
27
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
24
0
obj
<<
/Filter
/FlateDecode
/Length
26
0
R
>>
stream
x��}]�,�q�y�S�}f���A���=�	9v8rn`���qb'@�~f�Y_�b�lwp%A�]��Ul�Xd�U�?=�?�������x���w��zh~���'���������2.}��F�?�����1��q|h������%.r;��a������Wx���C7v���	O���x-m�����<��V����������@z�?��
S���x��Y�O.)%�q��1��D�?������R�8������R>/�2������'��r�c��5e��|^D��%�$<4VD�C�=�O.)%����1��D�?������R�8���tV��m��S��O�"��R�+"��<��g#"�5a���1�ajuIkMxm�c��
���%�5a���1�ajuIkMx�l�c<�m���%�5a���1�ajuIkMx�m�c<�����%�5a���1�ajuIkp���`*���l�b1�\(C�����~r�ugCA�#�����1��'�����X�w;�\���R�[K�q����\RJ���R�x�1��'��2���
e������'���p?X1nw,���%�$<��2����?������R�x��Q�'����y��1�w���%�xhCc*�c����D��'�{�TKp������`�Xa���1�ajuIkMx����ybjuIkM�(�|�wD�Z]�Z^�3�S�F�Z]�Z&J*��V�����]�����}��k0S��1�ajuIkM����7yKkjuIkM�(�|�wD��DS��Np�7�[#���������xG���%�5���	�����%�5a���1�ajuIkMx�SP����djuIkM�(�|�wD�Z]�Z<5v��1�������YD�L��xO���%�5��N�	n����%�5a���1�ajuIkMx�+�w��������0QR���0����&<��~����jjuIkM�(�|�wD�Z]�Z>���1�����%�5a���1�ajuIk��Z�%�T~�+HD\���2����S�KZk������'VS�KZk�DI�c����A~r�mU
E�K�
-*c*��b�7q�	�a��1�C�h'V� <��2�c~b5?�������������O.)e�K;�S��O.)%���\>�m~�z����R��Mp�7��'����b�b����5?����k�bL�wDl?����;kP��m���%�$<��z����2?����'��N����'����b��	�������Rnxj��1���?��������q���'�����X�w������KJIx
C���x��n��KJI��X�O��m~rI)n��P������~rI)	���6?��O.)%����1����O.)%����x<:?���������|t\~rI)�Zs<�`*�#b��%�$��VD�������KJIx\,e���}���KJIx>[��G���'��2��1��	��;"��\RJ�]kE��9�~?������R����n��KJIx�-e�����	/�����
-.��he."�Z^�b?�;"������R<4f9�`*�#b��%�$���A�������KJIx���w����'����d�	���'����r��1����'��2��5��S��O.)%���"b�-��O.)%����1���4?���\-�x��i���|�����M��7��������s�,`-k�3��R���A�����4��z7���o_0v�����?���`�z-3X+fa��|����<��<_�qZ���
,K���f��B%uj���)\����J�o�u��e�5��������ga"v�1��YL(c#vY�u#���K�m�P�Y��h&����~mhN��J���`{���	��C.cuto�r������kI,��`���$�|��b����6f����mc��cl���f^�^��&��C����m����c�bnR�[�����'��,5��0��R�GR���@:��
�OR�#YK{+%��qV��P]���u��\�I�����P>�V�(��5��Z���d=����p{�U���ZKVC�-���4;��K�c��D��Qw+	���"�Y@(�{JC��a��nX�
�c���@�S0��8j@�����[�qf�(�C���iTJc����
Y��8�F���f�O�V��k�����3��H�imPS�t���/`�}!����X�]����n����n��v�XT7*��mvO�#��|��X19�v���.W�~]6����q���VL(c#���K�i�M%D>����Ze|�=�l�k(n����������c���dX��	7Y�Z���e��#Yh�gO�c������Sc���R7r�\�[!�|�#��-R����Q���%��1�b���&wl(��;���C����
%�-S���M��T�I��,�
T>�Y��0m���oI,�%����	�c��Y�j� �D����	�c}'\�zL:������X1�QP�S�D��$�:�^e���<4Z-���8��V|��O�SI*w"���J���8/��t���4��*g+�X�����R�!�%�
w���C��
�7�*$k%%����H����Jj��}���e��YJ(c+��43�]+R�+ml�d>��1�B:�f�_�"D �9�HW��4@��>�0<+U��N�U�g^�Z�j�%6��=��H,�dF�I5��H%�RB�[���(���Qr��P>�V.o9�q�
�[����U>�q>�W���!��g2{F)��JX��AJ��VK�b��8���8
�=r�E ����RB���S��
*%"���c<�6�2���N���Q����
[���)z`��Vz��}�O���=0cJl���K��W���6VW��3&b	/f',�Q,����H�c��T�e(��;��%���C%N��cu��\"�a��m��E*�v1[q�s	)���SR7����|�#�=����G�A�q��:a���q$�P�YA�&���n�c��[�H.+��?���|��%�|��M�k��c�J�:�������)��W~�fR�
��}��(�`G i��~��Y@(��;+���TR�l�P>��g���Vp�<�^��+����C�]g{1���8��	�@lUvN�T�o7����uE*a�27[��c+������#9�����H*c+�`���6	=��$�B��]�Q���n�%{�8�L���~c��WCs������X-��1���a�
���`u�4�����p�C����q��=H��E�g�D,�=%��UT>�V���K����X�,&��q��pO,q:E*�W{H W/��1�l#�%�dgm���	�c%���%�����*a� b���Uc�m�bm/�%�r��l��VE��X�����K�c�60��������O�L?�����\U��}�q]}ZLR��.���P>�F�z�� �����`/�[�&~*��4�����X>K��,
�V����s�;J�$�;��r��=�K�J���"��d��������*c+U\YB�G,��-��6���8�����,.XY0�F����]���`]��`��c���Y��v"YWN��m'R�gU'g�g��d]I.a�37�d��ad��;�DI�c��O#�r��	��q��N%�H���r�w���|��g��_8�o1���-Va=���nV��
��QV�P.
�Q��{�Q7�M{pN�4q��<�O�c�X���������1�b��|6��������"%�����\��+A�b!����
�/�
�c%��<?6�$�(����
�c����[��ZU�t`�]J�c�~��9%�l>y�h{���x�
6�$b�G�(�|���&��$�l��0����la�����gK���h���k�U'$4�C��e����$���8ki����E,�0�Y���;�:�X���
]�%��G��.�����>�����^���<#��y�!+,4`���q$��ke�hcVD������|����� ���!mUY*YQ�_o���qV*�q+���5���P>�H���l��m(�m���1��!��"��f�P>���/Q�������4������x���d���vV�L��t���gt
X,
�Q[��c����[=]7C���Z	V���a��7���I��[�d�,�\����i��L��8�]2�a�Z"/`�,� �-y��������"��-��|��g�no�@6Z��]G�cl��H��&�Fm�f!sq����e���f��1=���'���Tg��%�bB�G���������a��I����:$V�F���
TtI.������e3b��Dn���@l�;�dZl��%,q
��mX��*H�������|�w��b;B"�����j�P>���B6'�5?$�����@����g�i�D	����8�MOk��-�m�Q��t[+�)"����|��]��j�F2���j�le��1�2C�������$N��	]��&!T>�w�
-��k�X a�4g[�c�u�a�=_��l�\�n�;�O��6�Ud,������u#YF��b	K�i�{g��H%�i�a���P>���fna6�$�*	�/��c�oxlYI [R^C�.��1��P�m#E���!	3��@u��������mJ*c#vY�O�j(GE��96a�5y$�0K	�cl���\������&��.�	�*���<�|�m�,�0�Y������_yl�v��||���	VWt6�g�d�l�v]-��)P�GB%?PIM��Y*�:�-RB�G��Z��m�@2s6n[���cl?����d$�,�����cl�Z	�g��$�����@��o��e��II�G�����yw\i��rG���I���g����
��g��T>�;���	��%��2����4��QI��:dJR�8�I
���g�m�hmnt=��Y�s������
=_z�azT����W7�O�X#6�6�A�n�	�c���V�dBm~�Xdl�c��3�A�����
��V>�����f��$��,	�����8���h]��Vt�V��K>���|��R'��Hb������=��X�M�=��,p�}0�c���[x��=~D�cD�6���E,�[��Uf�p������z���8�������%�	1Ct� �,����;Y ��#B�����&�f����5�P>�J��4�"��R	��Z
�wv�!�"�F��T>��#�^��\j69D���1�����b�_�p�����8�q�p�\���T�j\>��@�
�*��!���[�P>�J�}��9��q���h�P��v������g�����b�����uo`�
�yb3��H�g�7��b#u�}����s��6r_�����1*F?�8�ACbd���p�	��q�bD�+I�Y`,0`��f�X	���(���1�����P>�Y�C�����r�GC�[���3���\��$����6�~-��q$U��d����xa���V���a�A�����
W���R�a����|����"Bz���
"���|��
�]����"bi�� b~�0��q$��#a
6���,r��1���F,ri��0by�r+��{�\K6����^�l�73����`CoE�h?6��q�c��n<l��H�����8��<�4YFCkF�����p�����8z��p[D�8a��j\>�J`�V����I�5,�����@l�e�� �4FHj�Tj(c+��%[,���v��T>�ww)k?	�g������g�1J�ORit�����P>��g�����
=;��l�a��CU�Y|6�P�,�F-GdN1,���D�|����g����D���A���
�"�����"'�����m��P�F ��w�m\�z�w�8��`��:�	��g	���������FC����,��q��{�"�l;�0���;/���@jXa�l�8"G7H���X�I�������$�����q�)y���vLp�|��c*�����Q�;[ V������GJXn;k �B��z,���
}�'�C����$�e!E`�fx(c��w\���Ne�f!�+���l_6a6��f1s�����ec"E�h����������6k���f��I��q��HUo��d3u�7[6(�R	�%v�V�\��c����HI��J�/g�z�b�l��8�Rk���TL�z��p�f�f#Ef�r]�q��hn�d�f#Ya����8����s"���
����H��� �E�r	�*���[g��lrxyc�����Xk���������,����JU[�������b�g���YJ(�H���HlUl�"�%,7N�>���Q���"t��C�c��V���M/��`�96�pjl�`�G�p�m�e��X2;6���P��;��)��,"`����8qlsX`Xk��
��P>�QS�+M�'J��F���|���w`�H.6.�rB��u .!�"��A8���4��v#[6 8����q��c�����"�l;2��1P��������,/`����8�8��=6[6\P�.VqB�g{��	QWfn����������az	��"?t:E 4�G�|���F����$`�����{"$������l�lp��XnS� ��u��BV�F�����6�b+������
�c���r�n���n�dg�D��@l?� �UL������T*c+U/�!"�l�����8@�=
�dS6��b	������E'l�H�bu�����@��b�ld����l$`�;���;��������2�b+�`������P�r�aq���Y�l�l��
X�2� VB�d�H Y9��f8@l�����e+�+��T>����X��v*�:)b��H�n�nm����A��\l�A���� I�{�}KXn; ��	�*�6k��:[�P>��U6\$w��CXn8\ ����b�lD�����mh��{#����P��>�@���� 6d60��������^�0*��k;�A���'�@�q$0`�op�8h�����3^C����1�=w�������,���2�@i�=g"s��GX.� 62'q�n�0�d����X�PW�z��H�cl�T�q(����:����Og+$�������(+6^$u��DX�$\ �*��S��4���
+kw���	�����#"79���
�@������H%#7����RB�+�w����`�X`�r;`����2�Dh�t,4`�p�8�Jd�HY��3�!�|����K@q�mF�r#_�mFtf`�G��dlX���#��q$��rC�$��
I%,WNG#�h�L���.v@���s�����sb��7,�gnmPt�����-Hv��G�*c-��'�{�{�P6366Z�l�c	=�&`[b#�E��YJ(������������!�)[���z�y)������<�cC���I��"�l�l����=�Id�fc�E�h�5��q��q�;7.b��_C���0>� ��XkHb1[�����Z��.V�f)�|�#�+@1n�1�V���1�	n����[����T����i�.c%���L�=Y��XCHX.l �~��ZL����e�h�P�[����l�H,@��)8@|���qm,�
 -�f��T>�V����l�ZcY*a�f��8���u=�8�:��%,w
v���H���,�@^�����1�J�W.��k�Id����	�{���[8�Xm",�.�Vb�6�6�`��,��|��
C?6�cc|7����X�c�i�}�x�m8���\�f�xN��>�lg6,�bA�����A� {�J���/�����[.���emX��e�gW	���\U{t%"�����lT��T�r���r	K�t1�4<y��m�IK�t���;&�m���l)r�d��H��������"�0	�c��Q2{��a���=UH���F$�����'/+���5R9{��r	K~r��{�F�gDh����Al�],��G���S���<@|o���v�v��D��n�����BC��R����
�%UwAXKM�i�tAJ2�5�-�V>���C�@��7|�����%���� ��$4`���1���	���k�������%�1N��C��o7�Dj����@l��y��RYa���H	�c��oe��;n"5`IX� �R�����v�M���1�rU� �q�L�,���7�VH(��c����Z��qgwI���Ipg���0!�J�g�B	K����<V�=!"���b�]��Xm�H���H
X�����;T���v':���%�o���rE��$mas���&�'x�/����z�".��z�	V���b��"���liz+'��q$��l)�KJ��f4r�|��r��+%I%�eS3[)�|����[4H%;��$��d�MG��:_���'AJ��e��MlN�����v�E���M��b7=�z	,����[o��1V?��,�����h�P�����z$�T���l��1�~��Nu���n�f���	�c�~'����f����d������_��h��D��YN(c#7�����&��\��8q�3,�t������|����k����P�iw�B��1�����&�0`�6�ILq�K��U%���l��.�H���#"w�s"����7+�{���\)q��&�P��|�#qfK�g����%�}����
���s�~�E�Y�!,��iC�.$�&,`��!������K�����b�Mt��c��b�&"X)Lb���cl����vR����,��V���Nz@yY��F�5<Al��o��.�����L�"��M:9�!U0�Jj���@l�.��OIF��/�[��~�������1�\��~-�
X"����������l?v1�S��
�S�{�J`�*����9��1�m��N�mk�V��w�;c�����6��T���~,��1���qK�[��}k?v���������J���o�c�P>�V���#W��~������q1�+}o�������_����|�G�J�i���,�GX��Sy�~����"0`@�c5���t6��<����9oG�p���%6`5�c���A��} 	KlCq�;��G�Ef�@���K��H����W�Y,}�����1��7����8�J��;�����8{���"�{�Fo�l�c���Z�%��+yf�P>��g���~���
�.�����v�����p�mh�����m�[���K�Me�Opo��Gb�����X7m��iG��%�O�]��,�V�?yK��qo����3h=I�4�u()�|����\��#���%���8��;�b�h�
�������q���7pRY�I�<[G)�V�]�~�P�B�����1VB��q��&�K��|��7����f�nXz�o�;c*g�.��uE����:�1�Rw���wL�Xl�c����\�:��A)��%*�C}��������a����vcL���i�����mU	
Xw�����BsJP@�p,.
���:�VM8XG:�]6�%������c��!���z�q���2�9J@(��3������,���������Jc76�:u�	r�<�u�N�;"5`9D^ �J�'��U�mcKX�����~U������%����A���Nva��k�c��i/�#1u�b�
K��u�cL�?�M"R���_=�i��p$��S*�K���,r��1���Z���b����
rX�!��fN�D�v� "6,�[������L�,52���E�V>���e�=Q>�c�a����!Hp�I��������;�C�`+���'���i�DN(�&�2�w�D ���3`T>��@��"����e(c��w��E�g�D.a9�� ��h��������nv$��\�Hzh����nw$8�PY���a�P>�JDs|��ze7XDj���PI��zo���K�h��EN(��\�heU�'�,�0K	�c�����?v#i�JM'�q��!�b�WSHjiw�9H] �"5%��v�H(C���M�qv�HL�|���{��Y�lh��
����1�b���bu��,�0��cle���2Lv�l�JO�%��)���7wY����
XN���d�j�������1�����������I�����!�Qx��&�Q	
����1�B���I.k���TrB������vp���ck��bL���#���a,"�Q������'��K}�#}6rB��r���'��C������x�I����a�k���KpsW������X"3�Sq��/$ixx�V@(�H X����
,"`���1V"���X&i�$�2B�[��!��co777��e���	�?�#Z`w7El����L�{t:����d��G���`%���iG�i�6��ne&8�o�D ���9TB��V�7qL�����C%'��q�����y������j����o�<����g��5?����n7Tw��������V� �u���������V� �ujF��
�_����Z��_7��J�:�_�����W���3��+����/{}�������n���oU�^�
����ZJ�������s�����oX�p��U%��O�����������O�����0|��^k9���|��jgw]c�tY����?��o����O������9��?��:��!�������|�(#?���O����/E��]v�O��\�_����fy����������xe��5�~%.#�i�������L[�a�w�_��_�Oe�c����Z�-�yi�c����k��"������k��2O�������m;\���{q[�}���������t&}Y�S��N%;�o�*?�m���S���	��V�T>�����U0��j�
��0�;�W�Wn��.������m�`{oF�l��������"��6������X���~��#5�-��!f���Z.�m���6-��qh����[�UevG�4@���j�iP&
P��h!�m���-bN{�O��6��n�N���x��l�������~[���@m�������I�u��w�U���cm�������a~)^u5�>s��KY�s���[[*H�\����
P��]Vk���[�sm� ��j�Jm��'����]m�`{�VY|e����S�io��k	n��p�6N�)v��8e����Se��Z�el���z�&yYW�ejN�\���
1HzZ��RWB6�2�O����i�2�o{=�6�������7��m���hiC,��5l_��u�k
���e��{����r�,	Y�,���y�V{
�?�
��}�?�6����o�c�����>Ar����O����<�7� 9m���������K�>A�m�W��&�	���O���q����
��������Y�����
{�����q��aI�aX6R�g��o��>e����}/?
P�	���i�wK������z���?V��=H�����C�%����%�l��x#�Ta��1o6���^a��156��f��`��zv��I����V���i�����a?��0
�e��M_��.�
P��6�t�M��������V�
��w�6���`��=!m����c�����w�Q�m�o�R_W���WVK?C[~N�m�~�����P�O��d��A���Q��3���p����~w��b�2��V�m����71`��;����%��{��q�*�rUn�~��{l�������|��o������o���|8_���i:,�L������M3a�5���P������t�l*<1��������b�~ql�+���oO���v��f��S8�-=/�� ��nowf�]�\g�@�t��������?�M����v|�=�}��[~xL�'��|b��I�[����m��Z�X\�����Q(+
H�RhJ������4�O�4j�+�k�
H~Z#����t���u`��u7���9 vv���G�4��S�e{�;��Ng������n����u�E4_��=my
�T��2v�����l����=�~����:�wj\:��D0UKX��n����"�Yo{�����G}r��-��G���m����6�S�������|��lp��N�s�T�	�2�P�<�c7�P�:u^�Otj�<+�T�)�M���f�
������;��~[��2�� o���9b��k�.s�����Xh�
����Zo@}�$��M@}�by����t�el:�t[H�5��7G0�k@�	8��+�Nt�n��6uy�g��0�I�W<�K
�q�!�:�\�RwM��$���������g�(K��+YjD}r�[�R#�[�Jy�����>,]X���ub����wbyx����?�'.���N|�����=�d�1��:���W��Nc,����
�����ui���E�K�B��SQD����;�Q�;�9�~;����>E��u�T:
\m��KH$(�cn���[��q	�u�4�������n�!�Zm5���$]h����%�������]������p��S����;2�d�ky�9�:����*�9��H�������������&��6��{j��7KH������� @��D�v��T�)4Ka���}��Y�v�5����n3���D^&Cw_5��qq/��T�q;������������{mQ�0�w�m\|�
�b�bgoh�GqK�[�o�
���(u$�[�%�+o	�VJ�D��j�-���R�o�ho	��\Wjo	����_8�(o	��'��3l3-!R��{8:.\\}������g���Qa��yu�{��G���]��k�C�����&��o���4�M�&�0��*�5�F�������/��+�5A���Y�*�)c_�%��o~�_�o��?����<�������/�����������*���:��wy��������2��3�i���K�����<����Z_f��/W<+����p�qwV��k�ih6J|���=��%��'�{�����[������\F.A�����Wyo�-W�j�������>(W�o���r�n��=�I�8���{�����vd!o��<��@^>]�n�3������������uk��m�L�1��C�3>^��3>��[b8��]�v��S���$�p~T�a�wOR�
���0\����Z�~���z��8N�W����:����W8���>@�NJ�l�~��?�;m���,-�V�,����S�:[I�H��/Z�j��}��~�K��*><��O,����(��0%hv�*L	��e���C��	�UG���!����S�E����(����	o��
V�Ve����m_w�l>��7��n�������ve�?�	w����=�s�^����&;������n�r3��{�(nQ��������=�~n����|`�a�p`�a.�t�q���#m����[�Y�mk��mq����8j^��u��R��Iq{k��E%:�*)i��/&�>/�~������~�l�+�6���h)���B�F������QNk��SK�{8�,�y�N�&���������Zsf�w���V�m����&�������JN����%q�8���s��^9����������+�6c_<����f���2�8��})�3��������._+t�����#8��	�K���Cm�v���=�0�=mv�c�Kn�O~7{�P������e�^�������f�f9|����W���_6S�b/Y|�s_�v�����<���[y0���V����M�����E��w��x����"b�=���E�'��[���������t`�[�qM�x����=m��b}~��T������3(Y�����N�����C�t��i����=w�����������Ii��o�
�8���5���z��-T�iXv�]���������l��8R��k��'�*(��9{���r���o6U���[���1�g��"���;����S������G�����7��O���Z8b�5pyN._v���������������;�:���n1���������$[�rs�~/�:3{������T�����m��K���6=bv_z�H+=����*�Qk��]��\��Ti����=A�r(��?�av��.�4 [���s[q��3�V����)$��z��NC��zN[��s�n��qO���b�'�+M��X��;��9���%S����+/�����b��z]D�wq{���0��g��~�S������r��]yv���^��.S�pD�{����;T�s����%S4gW����O�&������Z��(���b?�\~�e�Vne�����-�k\~9]zT����LK�G�6_3B�����/V�����eC�/��������E�/��p]���%@~
x�
X�K��]�k�/���#_{�����'�!�����x��BJ�\2���~�7k}������|��|(�P��7i��_=��**��^�����9[���L�P[S�7�}�L{����}���q<�%���l���bg�uk�)$������
�k�����Kz(�
���Q�rD	��)l^����Y���+dq��q���������+�T����s��Y����|�U�5�|+�\~r6��?�3�\m9����''X|����>�\�}S�Y�������8N@}�����8��&�	�?<kU�J�����/��'@���u�#"�7�3���J����G�-���=��;uQ�����8�";3����K�	5��#�i�
�`��3Y�vB�y�Wb;aK;.3V.T��8�1�1�l�y���y3����[%���GrgKo�i�E]U�~U�������U��L�~�1��9�?tD��UD�L��8��D�f��vp��������n�}��;�Z���s�M?|��a�g0b��@%W�b�I����>���>�����
���b�4�f�'T���8L������_<������4�r}au�/���/n����v}���9	�����\_� ��6�{����t�@�Z]���Q��^Fg�% _#���.�*��<�*��sU�r|3����+G9��WO~�r|3��XR�G���r{a�x"0�����������E��Y
���f��#�ZE_�F9y�T�e��8��s{�}q��*�g�z�/��t�a��+w�L��8������b�X�%��'��c�������!�r�[�Wr3_�e<9����a���gaG6S��V����5�C��m,�������{�q�[�������8�Y�Z���\��x�S��'��+]���O�+�'����|M/�� �w�c$����v�o!~,��7�����"��p�Y����A��/�[^�s�m�����m�\s���W:�s�����8�\s��4^�=W� �Wh�s����G�����=I�rni��1�������������c6S~+�'�.����'9G���y����]��9�0����WZ��T����Z���[�Kn�O~7��9��=x������q��x��6K��&�N#6�����N�����\���������9�r�����?9���c�>�r������Z��in���%k�"�q����i&L����"����D��y]TN��g���Pq�8xU*"?��f��7������]����^�2�wb��+ 
���u�$(b5t4���b5|s0r�bN
����:���������+���'�[;=5|,����$��}�r��c� ����N���|�n��AY�ej���1{��F���{F�/��K���z��.[��5E���������)��Aft����{%�n�,��s_�n��'G��>�����2�C�|*_�����C���Q���Mo5����p,���=Vj����,�P����'��a.���9>�\��-��#�����r���z�:WZ_����5Wo�3�����=���q@}����8��=(#;�����*W���\G��Cy�k����,��U�����SaW>;=�<5�����2����&v?��_�M����|�������2�g�+��d�+8�f�b�2���<O�IUB���'U���-��X���;������)x����<l���F�$�+�E��O���O���9�X��nXA<��z��h_�U2�Q��m~�����~w��#�KM�����PS<T�7���K�����P�������S
Bm^����9vdr�5.�\�fz*%�,"[���)�����?@M�c���"���UerG���UM����#�ZM����������u��;�����e����z�P��I1y��Tp{;Nfez����K��+��`��q�_<y�2�c|�$p���u������;�R����������r��#f��w��6����(n�f��m���9����x5��r{Ho���=��R�3z����H_!�j�Q�;\
u|�������="��_���������%T� ��p���UzD�S��3��fQ�@�?J��D8L�����' r���	�����#Q+���/
�����w��(!x��j.�4��~���&w���Xk^��j]	��k��<��\��.{�|�Dr�r���6mu�
&?Uy>�!����3��/���c.=�U1�5��f�{7�����k\a����9��5�U|���������
��~{�<�H_�I�;���+��w���Wo�r
�-���l������i)7�c�*}��������K$4��s��uo"�_���9����?���������pl�+���J��2�q����x��L����v�o��0���4+����p�q(_��?]�IM��=���_rk~���Y��-~�DU��zxP�j�-&��{
�f!�r� ��0��8mrG|�c���n~v�2��U"�qq��8l�����] ���5�������A��C�{���8<�o�G�o�W��~+E�]���[t��|g^�i�������O�u������%������#�D�o`[x�%��
 �w�
k��o�k8�+=����_R��6_�����������E�����W�I�������DJ�n��u�5�7g�=�y�P�U+�:���6�T'ci[�T����������g�-�nc���__�n#�
 W,�UC��=�8�V��L�AO��<����1��M��P�Y<h\��V�k,![�bOU���U��\�o���b�b�0�-��FH��|�`���<y�C�o�v�r62�P^eq6��q���
��������u(!�n�WG~�r69��U�?(�"[���f9����Y=����C�=��0~�0���P��]N�E�A����/\��C����&���w����@v(p�|wh�������9��N�J4�����Nh1��������Go
�;�c._��;�c.�H�K��4Q��fg"7�x���-����GH7V]�8n,�\�D�p0FJ����}��J���M�#^GZ���w����G���0���][�������!�������C����YC)����Z4�!@�~t����b�|���4W�@�x�G���
��4��
Vy���p�����a~�����H�d���:�����:���wOL�D#a��^��$9G#��|��
����<U��3��G�5�������`G�`�"U����e�o�
���?�$W��gP���xaH�s�^�W_yo�����yYwW}�������H_7q��'D����V�S5%��Kz
"�g<��)���<	�<��Cq��������
@������o���d�m@�'O|��62���h$�	����u����IL�
}�[S��w��Kb
n�w����Tbg��/EB�oAW��p�?y<j�yd�~y���<vFg�����-�<���i]��'���k�jX��~��_�T����k��<zu�z����a��B�V.?��\�[�4���-���z�}����B�����o��KI����UaR��
�)\�[�����R��6�����1<Tz������-���S�q�?�����#��GK+H�����3zGR���w<��.S�$u�������p���1x*o�-@�|���)o*��']y��������H��oX����p�q(�Hc����?����ws;�t��"�����m8f��e,��
��A��JG���9��-���ne�+f���G����a���Ugf�vk������}���(����^������-������#�w��=����'�JPG��g�>�������l��MI�D�?�#:�c��u�������7�!�����i����7�t�cQ|�@i:�y�8��V�[es����9����7�����[��)O�8��)O�8�D��@s�F��M�dv�,����9z�}�O���
�}�K�}z3�6��^�Y����wI7������a��n����C\�L�+���f����htg���������c1������-v&$en���S��xM<
\���v�G���3�G��O��"�Q������d�w�){�I������x��%��3R��/�@N}9���&�s�zn�<�RG�o�
S�o�zw�:��,��o@�O�Z������i/~Cn�;.c�!7����
������9e���Q�^CN��<95����u� �O��
G�e[��~,�����\{����-_��;��a�;Q���������D���s\c��Cs�R;�x�H�\��'���W_������9e�Z��%y���<�U������X����H��#���Ib�kG���s�E��v]�����[D�;��S^{���xP�]������|��*6K��v\�
y�X������wU�������K^;ni�BY����]G�?��������z��>����p��.*�I�;]p�+�����x�x�sr�!t����QD�&����`o��S�+�������� t������)�=��Oq��m|�P�5n��8�������������������������
[b����v���i�wY�\�l�����������"��|���i:�_V��m�}�4S�EN��k
c�WU���wG���3�e�Oj+�l�{!��S��IU�N�_�q3�e� 1��~9�k�&��p�i�qi���^Wj��!�Z��q��0bu�.J#�-���aT��n�T-X��0 ������3���w�]������[���R�[x�o����P�:��[��*"��y�Z6W�v�Yx�O�[�O&�2�Qx�#�������tU�P{qX;<I������VX;W�L
m��y\�
w>9\4���-��L��x������n���pQ\�����A����<K�����Y
p����Y
�:���,��s������"���~u�������}�A=/��y��z�y��~�y��~�y
��cvU�����Jv��3O��9h�Y*�yf�s���s��u�s����c�,y�cz����<G����"��b���(T�a*�x�A��j���������#�V{R�����f��r�wG2�Q:���������j��jG�'5�P���e��M��Gh<�����v�����Lwt�g�9
�r�%;���+R�k��
�Vq�p3��p��
Q�g/j�B�/�<5Q!��n;OT9�pOT9�p'�`�(Wh5Qa��2Q�������pK��w"OT����<Qa�.���>�[�NnT���$�k�r��&)��5��T�A����$x�LR���#2_OR�����~q�[�?� ����4UU=�4����P��`sT����~�i
��c�VN�����]2v��s�OS���z�����7�kc�SY�kL�R�k,�-��4���cK����8k�e �r���?@���&�����q-����vSu!�r���g�f����g��v�w�v�q����~�k��:����v}�����yW���u��Jy����B�s�k��l�R����VD���g
�V9���P�G�'���z��/��o5Gj�m�j���z��hG��'sTV;�'^��C�QP;\����y���(�T�����g�l���^��,�T���<U����,�R�f����J���
rV��u-��x���u�!u�#/H����7�?\H4Se��;Se��=�������!3UF;O7�L�i�-���Oe��c�i71���K��5v�SYf�<�u>��?>cj�z��j��U&+�[��+�5�3 ���%�'+@�:�R���H�U��_e���Ue�����:�UV;
woy�/��o��7{e��=QA�
T
�t�U��8RE&��u>���?�~j�z	�j��v� o�i
��w���|*@��w��L�<zn`WUU��UF?�gT;������z������D�?<7��O��<w�{�����v�e��0;b4��������2o�&/
����f��E��mV��}�du��@�rC'O�d���{�=;�JO}��cUv�|'hP}G��X%�[:DX��������t#�_�������BX�G&8�@���w���>l�W��	�(��$%l������|;��0�M���������P��S��D���b�"�:W�Mm��r��������a��{�:�u/!������U�Wk���/����$�y����e�\��,�������<P}��c����K?�dpj'��d�z=��:��<����T����=���!�v�D��c�F����V/����p�;,�l��Vw���[����k�#���U�����2�n���Z��2CN�R�-T�[o�h����bP
P?�+�A�����������r�*AjO��X%����Kem��xt�1Ib�2����U�\g�JW	��A g�y���x ����)��5���f�J}6E��v��)qE�Y�R���@�nu���l�s�,�o�R)d���/�$�y��Y������PD�����j)���?�Ml�(��h��i�2�^���n�*�%L�Q���-]c���=���Z����=�VK���4e�+��v�WD�!���[�d��Csm� u����G��k�/�Z�x���Q���O�����[�qS�)�J{�,�H���^*f�L�Q���~!_3us�Q�z���QG�5v�S�/��B���qm����v���#�U��;Z�T�I���y@�lu��WVc����\m^�|uy����+_��u:�"C�5�wR�/9��M�����	P?�9���z=���z,���k�2-��6��=�V����x8Z�����/���M���Q���|�[\CD\�5��UL��t��ki�k�oi�VU����!n��!��gK��Q����Q}f6F�[CmV��W�"V����R�zs�8�F�����+��mtm�`s<9�j�8AjO��'���K��8�J���B�����)l�j�X�s�;I��+��g���*���?T���S����]��Q;���T�9�L�R������T��]���u���DYYS�f�.�c�o;�f���f��9�
�������_��/���/��������o�/��������M%#RG�����y�;d�(6~]�_����i\wjCFW��S�� q��Z���:�y�T�+�,��O����7�sq��e]����\�xF9JgY�%������Q���Pos�,|J^;
���fI� ���dr�����-���H��������A�,��^I^4&�����x�HS����P���8�`���x;�2e�FX���^��O��+5e�f.�X]����c�e��������~�w�����9�6iy/����[y���.����`��r����p��OUi����SV�%�3�h��1�������a���9
p:|��o�
�s �� =G�'�����`3;^V�
j����3TF9�3TF;�����C�P���ig5Ce����T3l�
��e����gYf��x�:�;��v.�,<���?�S��;�S������������gx�xV���Z������l���@�Z��Q@j��(���hG����ZY�(u~d����*���{�z��-�:��Y6u�@�s�Y�6��V��y��=X��������=,(����X���Dx�LT����9=Q�Zl����� l�G��"SUU��SUF?J����
6G��
��G��?2U�v��[������
V���Y���P��|��m��wOVP7J'+I��4�N
-b�Fn N�S�<"^GL�������5����Us n����Kq�u����r����XW;�X[;�����5��C��X;.&����=/L��c.�[i���3`}f��3��u�t��g��yg)�Y� �V��`#8�+�������,��|#Tyj�A*yju�C�S�p�|��������a����"ni�W,�TF���Z���Y����X������,��
or�8�H�<8��S���pC�S��c��<�O�C$=O�fv�S���-���C�R��{SH�k�'b�xql��,����[�d��jG�BC�RY������O�`^�O���&V��9fG@a���f��\���C:�
endstream
endobj
26
0
obj
22442
endobj
27
0
obj
[
]
endobj
28
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
29
0
R
/Resources
30
0
R
/Annots
32
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
29
0
obj
<<
/Filter
/FlateDecode
/Length
31
0
R
>>
stream
x��}[�e=vU=�z
�:u�������W�BB���DQ�����>{y^=��.O����F�1�|���������}|��o���|������?v����O�����:��6oc��F�?�������i���c������m>�]v���P���������n�y�������?R[�i�������<������q��H4��(������������?�����'����>YJ�Sz$�-����S&����Sz�)�����[NIx\���)����'�����ZJ�S�3��On9%�u����g���rJ��n)=N��D?���[N��:�^��{L�O$���rJ�So%<�K��On9%�e����g���LAx-��K�w���r���n2�S���'����0[	��r�6?������Rz<�{���-�$���������On9%�m��/��m~r�)���PzL�O$���%��Rmo�pW����	�k�DI�=>�0�����gk02<^��'����j
F��Kr���S�����zi@���r��]o���Jl���F3
� <��H�=�O���-�$</���������rJ��j)=�O���-�$�o���������r���~7�S���'�����Y	�����r�)	/���x:���'����6XJ�����r�)��PzL�O$���rJ��d%<����'o�E?
����x(�����D�I,A�()��'&W�<��������l@L�ny�	%���D���������\{��m���-�5a����H�\��\'<vf��aJ�$�s�0S���I�\��\v�weKkru�sM�()��'�?��gk�3<�����F���0QRz�O$L�ny�	�v|��\/L�ny�	%���D�������n����!������0QRz�O$L�ny��z;�yL���b�W�f�,�)��g&W�<��G;�f�/�&W�<�����{|"aru�sMx�3����������0QRz�O$L�ny�	�v����<��\��\&JJ������-�5���^����-�5a����H�\��\'<��e����}I�\'��)��g&W�<��G�e�/�&W�<�����{\���e���%���:�e:������W�E�����FAJ���X����[J����j~r�)^��PzL�O$���rJ��h%<��C���-�$����{<��������rJ�����������S��Y��R���'��2���6�cJ"q���S�A�pW�Q�'����dg��6����S^�4:�S�w���rJ�iO��{��{���-�Lx���cJ"q���S��0���6n��-�$<��[��r�N���-�$��m��W���'�����XJ���m���[N����m�S���'�����Y	���m���[NIx�-����FO��-�$�����W�0�'����[����cN_�H?������Jx��{���-�$<�����j&���S^&K��t�N�~r�)	o���x�ZDM?���	��Y4�0�?�8~r�)	�����Z~L?������Rz<\�
���rJ��n)=��&��'<�
����8�����\$|�	�f��c%�����y�����=k7�o�Z�y��D!a���\��Q�L�~�g����Ym��S	�/|	�4��|�C��=�.��M��o�z�j��a���8�����`�����\z+�0��Qz�O�����%i�xv��B��{�I����p���j^�"O����Q�<�	L��h<39U2)������l���;��#�.��y�`���G�=V����;�`u���h	���;��#��rS ]j*f�\���u�7+�#&
���������[�m�9�V`k(��w�� IJ���b=��>�����u�i6-�U)��,m�h�#����0y��n�����>s�x���~f
����x�b��R�)��Y��L�HM�=��j4T_��Wr?��g��)f��{�B_l�����?��eY��{�"n�6^�������)p��{��ol���_��dU�,W��)������j?l]���pYN����y�HNW�e�j���Sz���<�S?��z����R��f>�w)����?zjx��o�kY��`��{�t�7��3���������e�#����J�M���R���4���#�����|�g�2�r]���HX�����~/��
/��j�U��nJ��U/)�W�z�0�n�")��.�MD����z�Y������c��6:[{��o��������SLC���=V��2>���Sz����XM�������Y%���,~�j�$����>N��{�$.'�+,r�Y��OPz�U�����D�����V$����^�U.,�`��?H��{��3/��+�jrg�n�q����OM���H���l<�Q���c'K��X�;H�+����r��xuq��
e���Q�Y�O���=r��H�X7h��'x�nO�]Plyy���z@"��`=�+�R�TcW�h��U	�JJ��U�s:�U�=��N��[U8�L���L����m�u�����x(�|4�'�k�:|���d�;��/�Z�l�r�v7Z��������k�T���2>���{\���*�~�6Y?�NGqz����TS*5rQmX�U�^���a ��W�l�����������e��Q���u�-��X�I3�r������b]t:}��=v��WU�X�\���q�����<�KR�,�.�,@7Z���c�{�]I�*U�;��	Sz��_+�;����'S��]��6�:Ag�(���nP����80L�=�OM��ZV[�|�����c�e����2;�������'���B��q�?�hV2����B��R���>�I�=v��������*aVI�=v'!.�R��������M�=69N}r��?���?oS����K�#�Fd��9��������{p��aj&�������/l@����S�`��e?t�X	��g]j!|���NJ�����oJU�����c?� rJ���-���LU*�.��3����$N��:�bz��P���l$D�j�.�����AlUO�Tj�.��&a�H�=��ZTZq>=Y�Dw&^6Q���*?��ZT��l���r�8�nW�2��\��"H5h��v�O� V�Ox�\Gv��U	�~b�U�����������)��N��%��N.q�u&>
��{���!��3TKv�I4�P��7�J�l�GUbW�X���������P���"KufV��]��g_v��t'0+K	���JR����'�`�>���MX6�7��(��}�H(�\�fuI�����N��0KIJ"a�'"����a�H�GD����'H�_O��{���,8���V a��b��}��YV[��<2�f�����^M�����q��R�m�Rz�]��9l�y��m�f�y������ �i���0��������q�l�m)���%J��U���jv�lc�[c�,a��:����V];�"��,�&���lys<��P���F-��5�J7��,���i-.s��4+�"Gx6+�9K+��3e1O��Y�U�	�f�7�O~%[Q�#+kL}J���9a����� ,7�l��<�\��"���"a���+��f�	#��'a��'����[�Vl�V�����I�=��0JK��#��vI�$C�=~�s���l�d;g�L���Alu����>��;fvJVvo5;#9V�����E�)Y2sf�Dn���[�'�iE����9Q2)������
�$Cg�N��^)��� ��!CFrd�H��#��{����Y���y�e��{����E#��'a���?�}l�Hp�J��	b�=�M.����>��b��NJ��i����M�m�;&zJ������M1`�5x�"Q�:����fvV&o7;�9v7W�+����[T�	K�����S�t��E%,A���+�f�t�=E%������|��fY2q�6F	W� ���=�-]���J%,�!n?�2y�$����&2k����M(	��Z	����5�w���f�^_'"��O�%�����|���[���c+{��.��T7���
������m�)��Y�0kl��^�l|L�����',��n���w���z�/�t���c�|�hJ���}f�H4�����q���s7]�_${kb���Gz���{z�M����wI�������e�J�C��RVW�n{�K��-�j-0�&,:k��oLq�lVIu���0���?��`������Eg�v�O.w�(�]�n�V�H��O7)�����&�0���;��Yp��~P����+@X6a��:����t�U�>���������5�LO���a���bZMH�MXN�l;��E��&�GD	�A�bw?����l���Q�	��b�����m+���%]=vJ���=_�d��;����>�
���V�����J%�:k��}n�ITg[��I��{lU����n��0���V��d����a�%�2)��Fv;t�]P6RYa��l�"L2������������,G����b;����t��{w�"]���=VW�Z���l<Y6[�M��y���e���?%���'����.�����[�'v)�dtY6a9_6@���r�+�P�M6���)2)��E���0���%]����q�s�=$+J�duI�0���V����f����lk��{�n
�
��d>Yn�5J���	b��q�x�([��u��HJ���4�d;Yu���0�Pz�����lD����K�u�b��\�j�����&�5ae�7��cu�u��U5��J4a9�AlD7�E��b�X����fU*)��'W��5��J"a9�9@�$N�<�t� �V������o*WRbc��I[g��c�P�^l`]6�<���F�=v�WcL��mM&J��Ica#I��;�L9O�/SC�}5Ve+�s�����[�gC
Dv���0�Pz���GYX����L�lE�,a��:���U�XIK��XUz��{��+����|g�R%3j������c�����eCjB�����c�{1���4�J4=[#�����[��X�S��/H�=.���<�t������cJ������a��[CK��n���N�b1��&���f���c_�W�,������~�r�Q,���g��8�{���|gk���M+�m�I�=>�l&{kV��B�u�����#^^Y��n�g+j�s��d��cu���"�N��d%�����\��AlU�W*�H��"�z��;���Wd�H�l��'�Rz����6�u���4��2�����u����(�8���Vd� �����Q�<Q�m��'���
���?��ec�3;[���c�hFy���l0��	�@J�q����6�g$���D�d(��EYx�����DV��,Rz�][z���;�hM"?t��d�DeX�R���.�dy>�kN����(l��M!I���/�Al���{s�.YY���F��{|�i��G��I����9@l?����L���y��Z���c+��o�.��Fo�@��n��T	=`��=Vo�t�n�����P^teYj��P� w�l���]j��h	��U:������"Km�-��USz���s�,�����Po���]�-��	��kJ�����0���������
���z1��	�@{@t��b6��KM]aE���=�r����b�����"J-���tSz��e�����:7>4����I��'���
�9��oJ�q�3O�U�����ac����@-��xp/q��n�6�[<�-9�Z�����h#�Y7a�9�{�u���.�W�-O'�=\���hC�Y0a�
��p���E|�m��h��������f�;���;�ol$l��o�,s����"�����A���3g~�������X�O�=���cbE������w�Sz����LX��
��7��bW����
�]�VwJ���}rAj�G����Az���{�
|[�z�f�{F���j�G��h���������Nm������<��-�F�D�r������=�W�*��n�E%�����G[ai)�%������.�r��)�M�Y,K�e��b;9�Dw��H�t(���s/�6�C�AQ�m=Rz��_{����iM�u	�NJ��k?e��:%��mM�I��{l?����&�O������.%�6�(x�t=��X=]��J�*�M��e�+�6����'NX2S$Hfm��p�)��� ��!�,�K&������m�^u2Y��L�&,wsM�wh��>+���GsW[������l	���xza���{��l��r��?�DO�=�w��'���:�,0O?�>�8�3�#��)����_!d�Xw���0�Pz�]�x�X�H�'�U��p�nc�2�^O6-G��ovT�d�l4�(��m;���U6m6NTRz��S���������`�r����`'�d�ll����r���d+f#�X�0�Pz�����m�
�c9�L�v9����jdg����{��tb�z��E��?O���]Kd#g�D �����d�e�Dn����{l[���#�����^qOx�m@���z��gV[X�L��z-C�=��W��l�zk�H6a�9�{�d�����*8�G�F%��X�^���#A2p$x`8�{\���Y�
��l���?��l�zk�H0aX;�������e���d����{��N��Dn���������'���� LX������|k�m<���m�V���	Y���%�c�&��0����>��GV�B�:�}�r�a�����6+6�Ld���l�tG����D�r���+��9�#6f�e	����({����lnl�����O��'oEw�5IXn` .6\�����F���n���{����m�
c]�r��k��Yt�F��f�a�yq��\�'��h���,�l��2<����kY����-�LX�?� v����l�l<���;����;��K���s�����>{%���$����	��>7_pc]��<��uK�=��bfG�e��^���v+���6m6�Ng[���c x��&���Q�r���_H�l���	�=�����*r�m9����
b�r����[/T-}�=���V�o����M�����l�lt��&,�!n[���#dQ6y6:PDRz��(
IT��d�lh�h&,W"[��QM����#���^�	b����#]�v<���J�=.~�������y��YJ����3l�_6R$v[���c�i�A�dT&k�H���J�@����L��/���B�r���}���y`e�v����D�]�h�f��|�j�r9��U}v5�e����O�I�=V��RdUl��&,���zr��
���!���v�	b�z��Fe�Fh����TJ�q^�p�f[bC[Y���	�A\lC�����nK����7A��g�a��!Zy��[�����g��l]Hu�uIXn�� .w��;B����X�����]�)�SA�lZl$�h�4(��^��C�,���������������@^�=0���k���K��!����c/q=�!A�u�<�e��{�bDn�E�0�����{2�KTw[�	��<!|Vql:��,��P�=Fwv���m��%��)��� ���b�m�����m|u��R���9�%�b�I��{�t���
u�����b��uw�6�Z$����g=��$�dUH6a��m��X��y:���f5�K��^6�]���Y���dc�'tl
Rz�A
��%Q�mE�����/;�I� ��D�V`� ��W���f������A\l3��:�f;��c�����
��F�>mpfDz`�+w�l�&���#��fc�,��\]�!L��c����8���c��]�c|Z��`�P�����P�T�f�����e�Z�����W������$�1,�;�L��#�����3�J��D.a9:@|^���$��`$�	���	b%��o�?����0��C�uRz�RWZ�]�>�j��]�������uz���iW�9��A����'*5C������h����Vj�v1[t�S��V�b����]�����1�S<���H���mD�Y ��8��TZ�]�<�����k�Sz�����(������
a'z�v�M��H�=�*�1��n��	j!v�Q(��{���Uj��8�
LX��#�S;w�_�b�Z�`�2���p�o�%	�I�
��8��������z����[��M��R3��Q�C�=v���� ��6�"������$����N� ,.�����R��U{���E��g]6nmv
C��q����.w����e�%,��:����FSt�5���UN�
[�����]����������
��4���1�b x���N�S3ev�����d���n����W�xg��^�;��q��wb6Z���c��O7^��j�eoS���c��������V����9������>X0�&,g;6���S���R
.��G���{�>���D�4,��� ~�,�j�`�2,����� ���$�A��*I���X .���3{����.���f���?{���]��
��X�^������FLX����|2�^d�e���,��{�d�p�h9���E�H���=�N��G���#��u���[O���T��8rz�{��	��viWP7��N�=VO�S��M[eQ���A�����d�
��I6^�����o����H��$������[�'F~jv�i��KX�����=��m�=�t`�Lg{~)���,��h�E7a��� V�g���
�9&�#,���N��"A-��YbJJ�1�"���M�`��%nv�������&G'��bK������;�vgwV���jwR2<����������QMXb.7���E�����X}�n��3��T�7e����h���A�D��9����X�r��������P~m���x�X�
a/���KF�R�����vi1��O�q�����&���)���]����}�KJV��]���h�XNO�	�]�8�*��.8dx6.������������Sz���S��,��'$,{�����>�����%��G2@l����ru�v���\�[����9��1�T����U�URz���e�5U
�R%�����#��'[��K����2Y��E�H���=��Z2n{��V����+9x��J�K�hw���w��w�ME�k�8�J ����*A�:��������.H�/6aU���Zs<X?F�����To��eN��R}fF���S�Rz����%H�f�Z���r���F��x{	��\�w�����\/��Sr	/���1���T+��9��q�r���q��O�%�/�J�+'�b\��U%n����b]��;��v�3�t����c������r5r_�NJ����XP��"A�H^������~��F���q��z�;��e������t����:��c��L/%9�>���������:�J2�XJ����M{�����/7aU���js��^���9�;��2=��X����U"�uhB��LJ�������k��Ld��MX�
���=]-��>aU��q�s<<w^�k�x�J.a�}� J+	�k�E����)���c���R���z2�CBI�=��u��Ke����U�-fy"��OF�P��U%����o[�����boD����w;��k��L��RMX�������^{���\�G
���9�t�N��2^6[��o�A����������������[����o��}�;����O��g��2��\����H��z@��x�^���_�{����:w���������������U�uy�������U�����]������U�����]����_���{�'�Fw|�����������-&O�Y�g�����o6@���*�G>�m�������O��o��������Y��%s��o���l�LM]7�������~w{��w��_}������w�������h���>lf���_V���*�y�y_�x�Fa���\���rF����;��*�}<���G��
�>��Q����N��������q���E��RI�J�}���a>�>Z��J�e9����[u�������m,��H��'4�IM_���E�����:x�����y���?�2���^��~��R������+��`u�g�Y���k�=R���Q���`�sTI�+X�m+X�o��QG��o�hXJ�)bF�p��y����>*
����#>\��G�����b���
��kd�"sWl{����`�j���S�a���e�j]�2\�F����o��{�^�6�S�V���m0�=��~����N���&�b�:�/�*���&�"�����/���,�i�u�y�R?@�|g9>_�9~��W�����]�mj����tSC�}T[�(-M����6,M�������:����k���k�07���x�Ja�x��H?&���A�/$�
P����I�7����<�i�Y�om�
l��.��������t{��}�����V�s���jo�<W�db� s`Q����aa�ho��f�%��������6io�<������y�4��� s�w���vR8���v�������\�{~T����7� ����M�#��U�o���t=Y�C�_���p�+�tx*[.��<�"��^?K�E2\����O�sdBD����������[x�	�V�d����g�8�!��FFP�<�o������K�K7���|�t$�b�`I��o���~m0K�����[�_Vb�]rR�6�zCD������)��V�b�g xF�"@Y���R��������fm����6E�8��2E�:��'���kd��L�t���s���6�J��K��5.
�����&�X����E���_��	P���/��Te�
%^�-�t��,,�O��.e�`I�u�"���l��Ej���#�8xiMy�5��#�6��F���_m���G�q��Bn2?*�tx��\��T��l�*kK�K��K��td��W�`6X1��
�F���������m~[��<N��{���k0�(��������z">&���:0Q#���D���!�&�D����39L����K�s����S�s�~0�9�8�S.�]���![��~�
�l`�H"H�#*C�C��
��`����A�@T�2E�:�gkS��5b��_�~���}�q=�Q����������]*�h�:���s|��J
���f�~b�g��RD�hS���iC�C���1J���������-D�/���b�`I�F�h�������\�@��%���l��Y-Tm�{D�"�&�y8�M�u��h������H�:�
)�T,������)�K�k�Ho������0"��=8����nl�
9n�l�w�+�X�b�qdkIY#D}X���A�F���D8!���X��%��Q���N��Ca��������b�D/�q�-%n�J9�����[�}��9���_}�����?�����\��EuC�:��H�'q�eU�h�����o������;	�Y9��P��:�p�?�����7�=uE������]|���g
#P����/Y��#����r\���l|��������c��\N�c�g��E��o�\�2��������h���@\;������Ek[�b�`�[D����cJx�
���Z����}�>�l2U+��m��\o+��rhrV�mk�S ����E�mO��+�����q������(�*?Z�w��\J2�2������l�`��!o��6Y�J���k�W�
�>X

�]����kZ�������ik�W(��	m��#���.X-B�p�~�F�3#n��*�h��w8Y��"o���"���A�[��XlQ�8�������8�29��V� s`�B�Z��_��c9���|!��
�����8�7�
�9��ZE��M�
� o�*�>����~��M�	q�~�nK����n���	�����JC�o�	�qSteI�=_���b���#*������q�N�_���ll7�P] ���]2il:��q�]l�2����x_/mGea�
��R����|j;^�s�M�	���D������2�+�r��T��
�������1~4-���c����i*>
�D�i��}���rV0�;*�8�S����,���cQ���d\N��z�g��wi�o�~�%Q]��~Zw�a��	��B�&�;��'�������_iV��
\Q� ���<!X��4��u������/Y{B����#��f3�U�/W7�Q^���M��.���WT �{EM����
f����WT�#�/B�W���(��hG*CyE������������+���k�Q^��IcN�+*�����G��{8��P��Pq�
���b�����Y�s����^�su�����Uo���E)W���B0��m�1��y8BM������r���*�Cn oG�6q�o�n������%x�S9B��'��#��F�T�,��)p�e�hY���#+�����o5�!�*G���V�vg<����=��He�)G�`G*{�r�`��#��D\d��_O�iG�hG��C�v$��v�`��F�9q����y�B���9Y�q��J1���A��8B��,�Pkf�j]�
��������N�tQ���!��'����n��� k��������'�M|"��fs�2�'�%��(�P��*)�P�u�OK�[��\�D���|��e�O��G�������55"�'*X��O���h���Q>Q[;�|�B��w\�'*���O��F.�T>,��n�v���A�6#�������-�A����6v�`�<)S�quP��F�����r0�
B�
9��!�N��A�\�V!�rm�����;�j���!���s��}b	F��YH����P�7�I�x�Iy[8D���C���8D���8D�	n�I��9D���f����!����W�/����+��!*���CT";D%+��kkF�C����C����CTjr���a;hr�a;���t�N[�$��#��y������7���7�n��x�9|�d\O��P)���m���}������.�j���0o���P���/�y�},��Z�w?������2���_6��YF���r�p�
��='���j���j���jD��~�\�X���\���������:|5.��#N����Q�L�A�b�J}}t����R_��X������}:k<��M�i(��J�P�X�8���\������������lG�O�X������U���j_$��`9�m�s'O��_����$\:��&�[e�W��[\��s\��4��p�������w�J%���8����w>����57m�y	G/e����.@�qw%��6*�qw�������o��H�8p>F�@����EB�_"O��G�L�^��@��'���Q�9��F>P�R_Z�EjkC�T �o3�H�����,
��H�R��vD�@����8���H��g����.��%�9�^�6��	]��<"X�_#vD�� w��	����yZr�7����r�c�
vt�2*���X6�
�P�,Q���
��,[QmK�O+�r\��(��q}�K�7~q����egim�N�l�,x�F��s�S��%��$&�\+g	5�@��8K���4�Y��n�C�_#k��Y�%�g)�F7OU��(g	V�k��T�RS����FD;K+��kjF�����(g�`G��R���)a;�%�'���%��)g	�t��7�,]�������B�~�o�j���+���>�yY���`�����Ey����s�|]��s�^o\{
��
9���/J9p��vV���|�C��"�D*�D��v����IB�&�Q�7��Rh��x����sx�X�m,���������/�w�u���r�`IG.����pY�Dn�R6��L���B�_���ph�����Q�t����C9Dmm�r�`�|�CmG����!��w["@�#t�I��vl�{T�#��V|].�j�B�(�<Gv���9������ o�5�J��O/�����e!�B������������;����x@�,������U(h����j���<Q�7�!���o��D��I,"n�����Th��#�x@��Q,.�o��:��pY���[B��
{@���*���,G8~�d:��s%��*���"\��An��R�Q���T���9\�M������L�z@�R��db[B�_��`K�T
�oQ��e��D�u����	d��4*UO��i*1��&�y���&����nu��K�~�h��9�:{R��-��>�_��{3�#xB��t��?���L���]7�RD b�^!9lz�x���p�6p��K�|B�9�}E������"�B5�/T_xO�m��3��
C����5�-���G?e[��z?�W�sd��'e��>N����"r�V�q���)�WO�d�s\;��Qii��:�l2*x��������>��Y9V�������Q���Q�P}�Q�@�

#��^j��Yp����F�b������G� o��b�s�x���I�7~��5/���Q?:�����q6�
���1��"<�,��������P{�������Y�1�i��cR�����B��{J�enVcl_��0>
��9c.�`x�+r\50�K0��Q,�+�.c�
�
���x���J���	�B|xB�M\&D�5���O��{�NK��65<�mjx*5���|��!�n�G�yx�-#�;O��#7�S�i��z���\Jbn�����y�j]z���=(��d�*�Fw�o��&���B�_#wl�
P�#2@5mz�*��B��O�[��`��%0��[Fh�S�AN�!2j�Z�1P�V�9~X��\=����:�2n�k����n{{�c��-�o5{��F�. g�H�ox0�M�5��"���j-���8/������A���daQ��^,����G��z��)�n�8����c|rS �}d?3 m&7M{�
�/u�p`|��.��������K��x����_������z*�9v��x�:n����6��!a���������7�3G����`�����u&
�9���b����4]�^4�`\��^�8��������x[\��x�\�����^�K������`a��S~���+?P��\�$'nqY��yX��k�����fa�i��s�B��-u���@��>[���w���F�5���;p[�6��}�S�"�m[.:x�
�w`��������s�B
�������\��Mo��A�zV*3��e�<4g���R���b���[�Yf���s���9��dK�����Mf������6�qn�P�X��4	�����?��Yu��FpX ��.>���/��[z���s��������i������[��<����}�����N�e���>ZF���2��<�����x�M��<�g��P��o���-w��~�Z��E�^�o��/`��������������Rn0�/�����93���������xj�����x�������b��x�L�q��6�,p �'��0WV��Q��������.2���/���L��vn5�/���vo5�/��Z���p4���:xx���8rH�'��0;d2��<P 2�/u��M�2�/u���eiS�x}�8���g�5�s��bnqY)�����l��>jh�(�x4~�9~���	����������z�?�������l��]�G�Mf����l�����&�.�L�l��A>��[$LW��a���$�?'G�c������z���������g�M�������j��/���?,�&K���^{�@f����:�����O���?$�]P���q�_���������y�ta�����F}��H�*�c@��|�o\�|�^k������}���uU����\���wy��OS~?�/��/��#��b����@�7�U��i �G�o�#����b\�_[����*�P����D�#��|����'�=��OQ��q��@���mG�>E���}�BW�$V>E���|�bW_����&>��_�>|����k�>B|���u��G�i�������p�*�y���y��:5��Wv�n��?-\ji��K�����y���\=D��������VB�7<�GeP���g��R�
�&������8���&���������<�+�~@���.�cu�r�XM�3���Jh�����@���z|+����[	��^�#����]M���=|z��������v�/[	����I$?��_���D���<�����x�y�A��a�R����L�a���rx���y�(��Iyw�?"O��d�������q0����>�l2�/��'����d�����>�m3�����d�p���pa|��Z��>���V�}X ��_���/r5�o����i���B����g<��m&��^��	>��b���2nsJ��&���;���:x�b���:x �2��c@u��L�!o����(tu�.Wa�z~GQ=u�������Ff��Ff�������^�o�g���k;�:00����bm1�/�F��R�@�-&���������*���8�#��(D�-2���?.�O��pd���_"�2�o�����D����w�E�R������������r���dew����2��.�R$�0�R�7�������&�9u��4{���.�����%������y�_b����k���k���'�%�����=��D�M&����?�m��x�'j�x��F�m&����2j��{�Z&��:���&��@����?&ot7P���'�M{����w8��m����B�=�+�@������?,�&���^���v�oM&��ymL&���"�7���Z����{�J]?#��~����/��o\2�/�8~hsf��G��Bsf��7g�.j�v���=��s���o?����������~�����Uf}�u��~�"GI�����������������*��>U_��0]����q��n)��K�����eu���g��{�<�����(�����rR���.Tq	�����%H_"GyU	��*O����~����[�D������Y)_H]���0�%����ow��*dD�9�+����O����e��r�elw��.f@
�Q��#���0GfEo�p��]k���@�����KMo��&�]�0�����n�:��m�|F���6Pg�����o�5�}����a)����%�����r9��>�[o)�O-��n0��L���M'�����y�O�C���w�c���`W�,w��gZ�k�����	1��j���iJ��!��LSb����d��F��S
���5;��4D�����_q.z@��t�Qp@��3U=���~�b_�3��4��4~jk�J�(��5��$�X���G1�J���`Y�F�k��;!�3����f���U`��F���|x�j]���s\��~Q{���k�����Z�4r���u�QQ�n�U���x�U�Z��_��Q��K��'�����6�p���^��b�e������u�Jj�>�Q�T��@�p�#^-�"��f7���.0o�XH�V��������O�C��Sj���M�-DY����L����#O�����k�H��K�%r�����$>p5n%z����s`t����Jj���Uh%�ve�:i%��f<2p��Ub�w�x��-���9fw�u�����^$TC��0�_
]������T����.@}�\���vZ G�i|�*�u}���`i�r�����D]�VR��)Cl%�K<��Ul%��yj��e�	;RC,�/���d��o�RXb�y���G��������1o���_�]u �o�.y�_��ms8�;��5H@}�.U�[j<��� ���Y;=����W����C\�xXl%qW�;p�H�������a+	\����B+	,�����J����0���	���5��@������x��w����G��U���i`YI�X�������z;-��5�z��e�!W#,����e5b[I8<��Jjs-#V����Y2b[Im��X�V��GF��VR�s�`��,>���B�R,1�/��csf�;k]��5�3�\[�����i��GD92�F.D��W#�>���{������F.\���cx�*�������$J��H@<�\��bkd�*����2r����X��g<��H��9r�2�[��G����s��Z��u����mhw�R\������{ ��H�vZ �k�����5p���`i�D��RW���O7�[I|�������[I jB
\�VX�SW���@��f������	s�Y.r�J9�?�C�q�6-b��eB5pM�����6��G��.@}��+����@���n�q���	nPW����=���6�R.�J��@��Ul%��$2p�:p���
��S}t�\0�-v�J����\������y���s�^�^��~�Rsm�g�.�D.�B����km������)�s�k��K��z��1�2@����2@��AUj��90+� �[}5����nxg��>7hx(���u�� �K�MK����8S	!���E���s���������]jz9���<�������n��/��F�!�����f��[�$��\���-�qk�X�����5���������/���5��o�����s����n����F���|p��/ha�_
���MZccf�Aq_QLw�E�uyr��i� �����5FD
��5FD}�z����@a��3��v�W��e>R\.����^"���k��c�x|A�i�o�k���io��)�|����	j��#��k��_C�<b�`��o�h�T,��\�a�e]�X&X�/
�py^S��M����G�AF��c�l�
9^wv���M�	p��T�i�Y�L��4A����l� �k���83O�{��n^�b�
��I���I�WN(�L�#rf-��"sx����C�k�FY����e�#[���=��
��_���
P�v�����D*�W(��u$>Q,T��kovU,����X(X
"������*0�G���j��-��2��-T��[�O
,���@���P���|
P�F�������BA��N�X(X�m,,�&s(X��f�P�����B�f�������5�hrg
d��YI#�:��A�@���v��%������8��	�yYkk�&IY��e��,�Wa�:|�2GLf[�:�b�
��5�������|"V��2M0�M��!u��@H}�GcF�*����-\���1S����b�p��\�qlB��+�4%��Y�'3Ub������������<`p���Yo����#��R�v���z��k7d��*�{t��P��Te�u��)�y���,�~c������J��1je���!�������o����[�*@�h���ro�SXh4-V�p�m�SX.�������:|����*0�������R`��ww��z��V ��;X������~����������+�{x�
�{��/e�`�
��`��o�Uk^�T���g?�R�k��[�:O������������_~��������o>����T��2T�'��2$
�[V�G/�����Fu����_��d/��4������)ef�
endstream
endobj
31
0
obj
19662
endobj
32
0
obj
[
]
endobj
33
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
34
0
R
/Resources
35
0
R
/Annots
37
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
34
0
obj
<<
/Filter
/FlateDecode
/Length
36
0
R
>>
stream
x��}[�$M�U?�z[uWUwu�x�&2.� X���A -< ����.H�}�2��q,2��K��4;���<�ana��nn��O�����?����N�������~�~���O�/����=��eZ����&���>�����M��i~���,��U�rZ�M�����^N�r���S?���?^�~��[k���_>������P��7����om����A�����K{���_>��H��������[��G"n?��)	O�����?q��eOIx-�������O.{J�7kT���G"n?��)NgC�1�?�����$<�V�������O.{J��b)=.��DL�1-V��ZJ������O.{����3�S{$�;��'�=%�������.~��O.{J�co)=��������$|,��c�v��\�����Rz|��n������������8������$��W��{��o���eOIx�-��}�v��\�������x��n�������ZJ����m~r�S|>u��cj b��eOIx8Y��������$<����!~��O.{J��`)=��������$�����9~��O.{����d(=��"��\E�� <��y�O��=���{M�(���"L�.{J��u;<�u �O.{J��u;<�u �O.{J��u;<�u �O.{����:��=�����(���H����?p �'�=%�so)=���eOIx,����r�S�v�������~r�S�'+�������\��������?x��O.{J���Rz<���'�=%a
�������[�������u������"�O.{J�CgEx��[������P��r`���������|�� L�����W�}�	�����S�@L�.�^&Jj��������������9�Q�W�}�	%���@���e���O'�n�aj�$���`�,�=>azu����0����{Z���������{| �8��'�@���d���3���{M�(���"L�.�^�g�k��x�0���{M�(���"L�.�^^�k��xJ2���{M�(���"L�.�^�����1�?z�u�O��e�P���0���{Mx����������5a����0���{M�|���x�'V���������{| �����5������O��W�}�	%���@���e������;L���b�s7�(�)K{��D�^]��&���)<��������5a����0���{Mx�l�=��������5a����"N�y��\Et'����i{�����>�m����e��? �l'V� �����s<���\����b(=��"��\�����*�����$�����p^n�q�����\���g�ywx�w�[~r�S^�[��9���'�=e����,������'�=%��:�>�>�����$<�����q�O.{J��]F��t������$��5����q�O.{���'������~r�S��p�O��q�O.{J�g�t����1n��eOIx)�"���|������,x����S��O.{J��`Ex��;�-?��)	�������n������y����z�O.{J��9�����S��������3�.;L�Dl?��)	���q'ow�{�������}]�������O��.��������|�i�,���Z�M����Ys�5��0e)��j�k��q8
���]���'���K?L�fk7�#2O����,�3�J{��SYy���1�z+p;C:�soP�{|��+�hE,��a���{�4�����������H�G��M�<�b�����������}��i|Y�,�v2�����Z������A����b�%���{�$��I�R��-�3��B	S����
�V(�V����CN�C�=~H�~���%�4�DJNi��Qj�b�E,��
ei�q,B��dMe`�������=v����a'�[��,��&���J�x�x����F��5�[����c+�d`�,���}�d�P{��������5�������c0���������@�OK�=���� {kO�Yur�+��� 7�m����L����+�l,�l�fN�j���[\�yi�C���B�Pl��)�=v��o8$�
��v�����jWa��ofG������=v_�=$�4��$ZS{����\��`�������)�=>Jm#�#d$f[(������Y*����>���{��b(��-���
SZ:���w	|fAEKSm0,��fs�|i�������0Z��\�n�r��;�w�h6
KFc3�XLi��W/ZP�6�A%�[{��F��J�dK1��|���{��&�0yU8�s �d.f�A�DP{�C���������>X9���V��\��w����ns���gY���
�o��l'b�Fm���)�=v��wgK�k�D@i������tv2.WL���*���:#�%c5�Or���{l���Q���r9=�`R�{l�>$�\2V���r���N��&Y#�%k���"����(����f{����{����9��|&�1'm���c����F�"fkA���
VNi���+�o:,�L����j��a"�hE�U��\�,�=v���V�)�,^����Q{��Gg�X�6��a��F�=\���@���h�}W�{��h�E����,���c�L��6H&g�J�����;��b�d�6}[l�=>R"��M�f��ei�����b{�d�+��Ml�	�����.tD��e"�,&�2���b�;��Qw���t�{%�dv��.dr{���������<���wOK{�?(W�o�Y��d��l�UwX]ry8��pv�Un�����5������S��)�����>x���^��s��|���8{�q��?��B������Q�����X�����$������=���v�c�������w�����M�Ge7?�V1�����&D��Xl�-Y,aS�{������-s���k��z�\�.�=��6&��nLL���������~N.�D 
����������@e���hx�^�#�������!�����������[��q+�c��i��b��R:����n�
�ED�tO��{<>���P��\�,����=Z���#bcr��K
��y`�AF�V)��
/v[e����Q=����Q����+XRW��QL���Z������ef����L��a����eJ{���{���
,����>�l ��tp=�����"b���
=�"��w�E�Ry�lt)R������</\JM�����)�������[��_�
6��aw��n`"�����%1c�X	��n=������`����=L �eY�/AR�{�-HF�F���F�T��{<D_4a��HS�<��r��\Q�8uW���_O��<��$�<~6
K���������f9NfPY*
�M���/�����whE2J6�>O�:lx�����w�KG�g#��$,+qn��(���G��x:�m��C�A�=�3E(
	��uJ{��P���w�d|���y��a���)�au5�)�7���e�4�v������>��#b��Xa9�� v"�M�"��&
I����c��G<g����e�B������.��q
��q���}A�v#hTl
�+X���#y���a#��8���c/~�'��2���Q�������O%�O�u���*Y,�������Q���n#���y�9��"5�J{��c�w\��:��{�I���4�\��T�Pu�J{�O��^v�(��y`���dwpv�Ud��p�d6vG�KkQ{����p��e��[;"�����U��p�*b�|���#+�=�b7��J�$��3Ov_�j�q{��h��hv�4�v�g����P�Z|��|'���R	��iq���<J��n��T_���x�m�/`����������l���y��s��@���~�����x��/��V������]i����)��[/��Vy�T���{<�f�`y��H����1��o.��l���$�<|v#Fl�=��yg�Y�����X_bpk��N�.Y�v

�N!<���>}t'�	�-C�r�#����;!4$$�����t�P�{fj��2X,�`.�X�{l5{/3s�������	����?�������v	K}�b��w��~������Y��A|P�g8��+�\E�d���{|l0��(�P���#��b��{���z6b��z�,����y��K�q����iQrk9����Mu\��P�V[&J	X:��~��*q�vGty.�������*�d�=����,r�vGT�,�"�V��;�M�#�b	K�H�Q+r�v�SD�%kK{������R]�VK����f+���8lm�������c�Hj���h��bWY��+������� �J1�$L�����6O7�d�JbW;����p#�N�����
��S�{l��Y	��$��5�$��{�������fg���b��,�V�c�BE�����	*���=VE��),bY.�T{P�H����{7�!�i�)X*a�P� >*�G.�D�o#�dwi��C
�I.P8[��:��V.�Y>�av���f!s�G����%���������q���$��x�c�K�=v���rA�*�
?Y�`+B�j��S�����pd`���>;��x9(����=�^%ksAX�x@��:�3.�Z�H��{�����K/�=����[{�����YJ^�����[{��Zyj����dg�;����@\��f;��hx�cG�����D�g����[�LY�{����%�d���V,w�CW�{��W�J$�V\\vX�����G
�e�X�������V({�"��f�[��Y:���R0��������{{����c��SeQ�dG/+��g��T���lY������7E�I{�,_
)�=�y/��� 	%?IB��JJ{���x�	��S�
�%����Z���y1d���{lyo�����Nv��j�1������:�,`!>4O�|��8v���VK_�{|T�z�����w�6�����NSe���_����H%�R�b'U���WhN����Z��&������X����6c�hSKDh�r/a��
\R��t�~������%"����CO���f������B�Z�O���XJ��VJ!���V��
\v�T>e��JX>��@l�>z��b�����,����}`�x�c���W�vl�����B�b�i�D�j��{���%G:Z�������)�=vr=t��5*�$��{��|ge�:ZolK�+)K�+�o�j������fa����wP���YY��/Z V���/�o���a��rmN�H)�=�?�an��#ok����q���@Z��%q�gI��T]i��U��-v��u�$��|�n��
��^g:Y�KB	����8���������'aC�=>�$�K��1$������*oN^r�^�?2������)�a��rk5�I��������g�v�nt�n��,�����Pq�6?r�O���|�>��9H������ ���JDw�R��G�
�2	���b+����N��B�����_�����i������_�,�=��\v�T�j�#KX>��@���`ob�������vX���nX��5����3���Wj����]W����v\	��i�8Wx#���:^�J����?<��AI�b��0	��pT�������XRb�����'���%v���:u�����4;S���5���u����^�c��d��5)�J����2��/�S�0-B�R��n������y�����{�w���)Uy���nX�x��}���@���������x'q������rk�1z&�e:��c��k���O#�P����`��]����m�=~���e����O�	���{#�p�17	
V�n07�X}���N�%�f��'����N�<������X�n�F�S�{l����F���^�]�+w���{3
�W�K{���-IYo���SR���T�-���c�I����i-���8�DO�=��8_��o�%�Rj�qh���3�:�!%,_��!>�^"�0���s_������V�"�]+/�V+����
�=`�I�k7����{�^�{��@�pE,a�t[�eL^����S��������}3^��d�����vvRRb�X	����'IB����z����c+���
�I�[�*�-X
K����@z�{^tX���c�����(�����YNi����`��+Mg��?�Z�l�P������P�-������|�B�����0&�l�<VFi���)g���S]t k$�d�<OF���
����Qv��'�F�\j���{�$�$�%��Yd�bJ{��O���������6\�Gp{���z?��e�d���NZ���}"�N���*����~m������9�|
�����y����zH1xH���8�JviV��8K��#�#�d�$�`�R�{�AK4Y����N&kz�;�h+f����j%u�'.����8�
71�Mb�H-X�l�=����6��MR����k�F��D��I��������d+�[{��@�j��������&Iu�������P���$�*�KQ���O�����UAX��t�'��I�g�W����
L�{���X�i�-E���a	[���Tf���V���vw7��b�V�:���=V_�w��#�3��Jn�R�f�X��,�D�e��@EY�{>���Lb��Z����!��B����]f+�`)l3Bl���d]v�Xl��b��I����},5P��
-K������/��T"&;����P�G��J�j��0��F���{����K-�Y,�0K)�=����}*�X�!Lb���V���9��LR^����&	o��}R����$�f��X��X	���;39y"���� �B��J��$��j�����k�Pru&=O	)�=>���>�cg2����{���df2�D(a2w[��&C+��Q�$��{��>�=���vP	��i����K��$��\�,��������<X�b�g��D
���I�3{�g3�s+O��|�=������KJ��d��n��-�H�:�@�(K{��s���F����)�K��b�\v�k��Xy9�6��K{��3��B�;vu&gN�P{��39=�N�d�)���x/���c��C�$��{��~��&{7�+��L#��?(�-��&	����c ����&�`q5����yL�<�g�a����
�j���z�����1Z���{��>��b��ml�)�=�B�Web2���
����X����"���Mc9���G����dn����r��"���,p��,���#�����&YL,������?@���+������`�\������r6������Idx���J���o�n��z������[,����� �B�U�`�a��Dj�Rj���J�_������K��b'V.�I�������fq�X�\�_ vb���blK%,��:����>�;��%,E�z���G>����%,��F�?����lj�%,���+����]�M���5'j��G�{��fYmXy����������{c�����Yl�Ro����`�FB�������c'�A��R�d�Km�b��{���Kc�����YJi���zl���H 9��WBvD����1���3#���H*a���A���wJ';���X�d��{����|�]����|#��%�d$�<I%�RJ{���D�b-�0�������?���
+���L�>w��|/@I%hS�H
��XI=4����=HX*v��])�j6cO�,%{��V>����Hn�R%p��=��{;t�sx�c5I�=v�P�'%u�
%,��z�C3=^�������T�!vb�f@�K��"���x���|o6)��}-	K��b�Z:���!���������]zL�)����t^�.�M������IK��;�wm�]���d������Z����
	$�����(�=��(q�kH���~k��S��Mcv0E.-�Hn�,����q��*����e��ki���Gs�E�j\0�)�=��&N�H�^k��yk�1�D����Q+�)K{��q|��{�7�a�jz�'��]��z�\%�����%9���P.�v��9�R	KE�b+��{�?+b��t=�J,
*�.�H>�,��F������,�]�mf;���c�����XjYa�T�R���<$�4P�J"o��HX
�����|����"a�<7Bnv�@�g��Y������'��5����
a)6�@l�f>�O
_9l�����m����f����Y�"�`)��@�~`Y�b���LlS�{l�>P0�|�M��K��b'��^�0�K.��,E�F������0J�>Y���l���<��s�jegc����{���d�2X�@r	K-�b���Z"p��a)��@��^�m���Vo��[ ����������(�s���t���u�b�6,G�_� L��.�����M����*���;s�{�B(��3�
+�r�v�����:G{��a%p��$;<�����#��gy���d�^]7_,�6�-�
�k�=�N��w�����%���l�>0M��Y��7���YNi���{o�^�n+oXV�j��wx>����Hiw�G�'�@<������'b�0����)�=v�i,����%����Vd�}��"�,��%����c'�a�%�l��G�Z9�������jw!7,�:���������R6@�)R7<������N�W���6$�-X�l�=vr���Q��H��a�R�{����� ����9[{���;��d���[c*Xl�=����Q���
+#�~����c�+b�j����K{�����V,�nn�L�r�����|,�T������I�U�[�xC2H��%r���#�J�n�!�]���a�Cy�8|4�y'&hw(6�Lv�;;<�����=	Q�d� vX��W?��+�e��{"�����}���T2I�#�R���V�����fw#Df���}�a+���:��`m����og�C�w��Da4�(��
��b�O��[�A����g�����r�Lp�&;������c+����m��������j�����V����O�����c7�a�I�7Zs%q�������?^�f{�w��XW{�w�g���u��<"���������U,�e���zENi��{�����0��^@�=v��V��a�[�"���<�a���4y?w�J{�c�;��-7,vy��'����[�,���^�<��V��H����@�{	���k���K�aoC������k�G�nB�v([{�?<����o��8�n��iwco�o~�����KlB_�{�wl9"�,�^`c�����
�^fqK����6��K��.�	�X�����G�*.�v�������������;�bwv�^,y��N��{��k�;��R��+�����H.�$;�����?�K6:HF�Nd�J{�t��X�$�%���u�v5�)Vv������+�v�����%s�X	4+Q�$������;���1�������H����$��{�����[!������u���'oX=ko��w����w��O��������������$�,[�Z�R0v_�z��������v�q�� '���7����y3�"���;�n���z����v�j��Y�v�j��(�C�|:�*��Tz6��5��zi����������c��&���M�>����v��(����]�}|P����	K�@��D��	��mr�/����������
�7,C�t6�����R� R7�pr���c'�����zh��R)[{������[nBy`I�z`�! R7�RJ{��T�����T��t6t�������=�l��r����wY��$s��zXE(
���Y8�����
U����tF�dcvJXr^:�C��Y�TJ�h�vB�=�l8����z��:�w�_<������q���]��������-�6�2�N���������n��:^u���A����������I�u��W�����F^��@�+wr�}��r''�g�+wr�}��r''�g���9���O�n{������������j���g�d�\�}��7�����j�������<��?���OO�s�?���������4_���;=-��Q��}��r������������__~���?������1����uJ��_�����|}��~����O�|��^�Vp@������g����_����W�r���+��|y��^��4��������J�y>"���+����4^���V�[�i�.�c��J�Tr���z�����4������������u$�c+������Gc���?����|]N��)�{��~����U��������}�Y�;���{��+5�\�<�����zg�^+�y���{����H�Wk�z���7���[�Z���F]�=k���-�:h=kA]�&��g-�����jg�f��Jj���`���������d�����������+�_��Y+�����R�Z��_��I�Z���u ��V[���������[���~����5�;�:�3 ���V����A�������V�z���f,����
Z�XP���U������J��ZIm�e��V�Z�+�����X��zm�+��&3�x&���c���E�,���8�j����x�3z��������{w��P����� �������s&"RS�n5u��)�����'�6����M]�-��J�S�wb?LM]��DO]�J�_=uA]�ffs5uV�ZO.S�x���9�y�$f	�s�������@-��e�Q�T��������u��PoN��Ln9T�6u�yi=uA]o��u�u=uAm�����B+��n�V���B+���TSWh%��VSW`%���\5uV�-s���
��Z&.��L��W�\?qq�������3���W;)NW%/�{��p�v�?��������=s:��~�L[2#"�������k��Z����-�F���u�r�u��3��o���O�b+I����?!(���J�����J^���#+�'��YI����9������sm.��C"�L�E�\k^
�Z���4v<g
������������9Po��������:]�9�����V��9j{su��9j�jl%z����U�=g�VRI��,@�m@��8����������3���"s�x�
���>�����}�Y0�������m0k�H�ZS�>��~K���YP?g�����3Y\z������3�H�ZP�/7T�e�f��J��Vh%�YZI����Jj'D��+��d��V`%���Df-��9��9���q��?���me�j������[�
������0DO[��Q���Re��*dsHu!�����3��z���~is!,��Zj��`�����B+����iP��-*�q5mV�����u`%�
B��&�s�
B��"Q��.���=�zg�ZL^����6s�GO^���N!�n�����������_�����SIhj�jl%z����P����J����I�Gd%�����+��"��o�S0�3>��Y��������y�3����z����/�x��I���p��3&}��P���&bMg�D]mp�S'�����{�Z�^g�f�,ui�1��#e{>��?$��\zSS79���/-�h��Z�
2MT��y/b�'���O���H�e*)���m<\�^k�������8��b�1W�8	`��S��a���.A����]��Z����o-&V��bw*b�.���n��{2�v��*w���A���=1����f�:{{3�������.�������|=C���Lif��,S��zdQ?'��� ��E���k� ���������u��(���hX��2^��^A��L-����[T|�=�gZc����E�'�-C�������?Zd�!����}�~�M�������/
u����u���[s]�
��E�1�w�#����xkm�G:BN*"m����?����H�z�H����z����X!M�����	���}���L(O�#���6����H�\��/��1��|��O�8���-�6��(���7�Th.�
��Rz�.�u�,�u~�u���S��~ip����Xr�[j��n)`�/.�n�1�rK��Sr�mf�Vn	S���Wn	Q?�I�F������b]�o���N�%��D���%���uls�:6X����$���%!���v�$5a��>��MM���3G����0u�)O�3���t�:u�Xy�P��=�X�yO�:�{��z��<`n����3�����X<]���}5�F�'�zA�F�.H]��ho���^���D|��THb�����?�����I8�u���-�G&���Qs�����t������?=i��]�|��?����Aj�9�M�?!A�6J4�������~N|�P�)@����ES��tZc��t9:���zL�)��TxHn
�#s�n*`N�������
{�������)	���Ii�������f:�N��(����,��%H�)�)n����[��N$dJ,�3�Rc���5qv�N)`�����������#�F�)0u}yS��u�
&D��g��R���	_��tRf���S�u�M�D�-6���[��E��&&�1�n�
������}������_�����_��_�U��������&/"���m��y~��<~}F�r:�&J�N�o�s.�#�!Kk�y(U
�{M��^��m��<�S�)#x�#�����v�pYqc������������:���w
��y��.�:��	8�7_������a�k��WN{M��L=M����y�ck�d��-�~�V�r�
�86���P"b��b5�/a����~�fi��~g��Q��m�h��/�v?�8y�}�����q?��kC��h�~��������e��1����v�D�P
�lP�)�d��������������&+,��d�x�Kk���s�8��
�\��G���R(.j9��
2�8Om��~(`�/�w��-�dO�>�D9����j;'�Z},��	�&Re�9!�&�	'k��wt\W�s���vN����)�rv_3���VF~������W���,�o�V�A�����8��x�m����-
U �L�:LG��/Tw��b5���?uK@�+S����%����]K�g/������#����_n��z���!y���C�����\M�����T[7��nh�
.��~��;Y��u��d�q9�#����:����8�?�xad�*�#����0��_3G��s��I�)��q��2Tdq
��E}��9�1��k�3����+Y�;�w�\����>�qu��p���j����ly��#]T���&���]>�
�phjvQ�!�Y�A��!����(�������RnbB�CP�����*�jN�,*����:�����[\[9_�p�����Z���!8�/�e�
� ��Lt��!H�+wKd��E�;��I'�D~��K�5�#:
����*�zN���pj:�4���?Riz*�~�{��p(�D�fA�����p�o{���=�T�w�y���?��v:�v��WE_"���	��j-��t�\dI0�Z����)�1v�O��C���!�C������Y�	�g���
�o��!�[��u0�3{�:����zA5������*�T��L�c�N�GU8��=k�p�0/�:5*��o��I��R����z���k�:�$]l��'��P�I*W�*
=I�BT85������@����������6�
�?�8�T�P�G��j��!H�+S7P�!h*��ha��;�A���M��`�m��g�����X�� o���~�����Pk
K(��y>�y=�����a�%��k�
��I0�ms8���$�:N|A�CP���#��!����rU4�M9����!@N���t6���P~�-4��r�������$��YL�h(�"�;8�����#����sd��%�$�Zn�+���9S��t"�T�P���V���?��I4�2�����?R{�?��61d���lq�?b�����]��/r�o:O�6��4\�'��C��N���C��K���=��ZkB����P��zjX���!����x��������[�#*$��o�S�
������>�5�R����Q��\��(�u����D���2���K&�����e��$$B����/E�$�/y�t�l�
J��~�6�C"��o�kQ	�����DX���Z	������2��(�#�-���P�f��$$��?3������L0�!Q4��?�1��tM��C����C���:���(b��E����"��=(�z�?(jn���rg��k5�w�q_��ws�Z�lQ�����C�M�"�o�n�m~Jg�a5'>5��-��LD$����Dp��-h����9	���L��p�o=�\��p��e0T��[�[�IG��4.n���
[v"�K�[P��CrnA?�8�Q�V��D��
���_nVR�\��J>p���'Q��n�pU�:z>���i&����:�*XE�?�){�J�������Wk�_>������x����K��~��8����O�;�����AW���RcM�����J_�����8[d�!�u�o}�����r�uu�u�X%�	�9�3�b$��6GRP�?2��U����,%��U���%���b$H�����b$@NW���?���"�,��nD}O�����"��BOR��������T�5���x^�Lo�C�e$N
���oQq�%��vu�4���KQ�$O�XA�_��y|,K�X*`�������iZ�������qrJ<@u�!�T��.�\E�'�U���s5N�k�e9�jm�!�?����5����GHK��I!�&y{�7q�I�����FI��>�FIP���5*H��n���eKT�u�#s�DI�����T�\Ip(_2�k*H��o���
����3P
��9�|������$h�-��B?�.����bt"�~�6%p=2�mi�"s/�$�m""AO�#3�*D���=s��B���$
�)�$�`	�c�?��)`n��]I�2��/�QkMH�^sf����Zw�������x(�D�:SsKD�Tr�i��O�%dmA��	�5�/x%,
���)$,
����C��D6�E��W������o���A�����
���|��`�R�����g��0�E�Vx,�5���d��BO�
�������(��a����d�E~�6uo=2�m�T�PXz��PrXz�LQ:
�BO�H���(|�[d�A����}"�n[��������&��������7}P�^tP.�AQ{�������z�tG���9�g�#��]gj�g�������Ahx�(�������;�����[�EP���"�($��Q�Q���~������|)xa^S�A��[jS��$-�M����~DGFM���OR��&���D��"#<�S���9Qs�o��������-Sw]�E�I����K����� ����KA�_�z#T	<4�tTNf������j�����}��k"S��a��^%�z�O�[�O�������q���%fj�<~���aR0~���z���u�����<m�*jZ���������uZ��|%�&KJ@��� o��
�o����%����-m�[�cIWK��S��T�u@�)�&���4j�����Z|�'���a�<�m#���y=�u*�S`��~��0����7oK�����mi�[�Y���@
�b��������s�����xwyUJRB��H���U������U�l�B��j�jjz�
�#?C�����3We��o�;}j�$�����)�QP���Cw���zrk^�� ou@F��yKe���4�vK���B�z��f'���T��go��	�
���e���{�jjjjzjjjzj
�#[= �s�L����u$�yY��_���w>o����%9>�6��3�nv��`��F����~��p*`��p}��/Nr�B�-b*�[_�Qf-�[_�A�ZX��������r"x���n4k��
5kE�Q��LUoBuT�=2o��Q{f����D!F	�"�d��\q������sU�\}q������om����4[������O��T��`��
*�C��� qj�f+@�3S�O�V��_3E��l�F:���#�%��:*�����3_���
ZG����v��uA�q������Vd��B\!suz�L_s��+�W�>��0���"���q�:�n����}}���d�+ �7���8�+��9���{�2'��������%�T6>�~���2�B�����_K�����L=�H�o��b�H���5�o����/}K&>&���T�h�
�o�68��^��AT�����#$Y;�D�0I��z���s�<~�3���H!�]�M/�s��(������u�T��EO#��j<����(
�]��������4`��?L�|�k������^Fs�:���X�����_rz���{k
S)����%���������Z��������^�#�&�������~NUK~��D��\��
��,�U�E? �l��E�����Z�C�����,�!����M��^���f�7]/��W�����?|���~����d����> T�~�����Z��/z�~l��'n��E�����z��'beY����^���?�v�E�s���?���G���g���\���o�cY�=n���=NW;m�cY�>4��_��r�oZ�%?�M|�A�����j�^��o�R�z�u�(Q���P��yI��CM'>�����-����p�f��j��U"���3�	����k���{^I�G��&�����,���rkX-���_���CM'^���/z���,�����W/��=QVF-���&�EY����O��h���:����`�?`n��0�?�h�>���h��^������px�x����u��*Mkf����>�S����B��"��6)���[�P����FY�c5�_�Qk��������v�;�q�`S�Vd���_2�_d���;����\������Fd����r������=����=���5��S-k��EO���=qH!kL�z;��=I��?&����T��D���e�S7,���@����h>��Q��_;����������3�������/
�`��>P�����1k�
�m��fH���M�������t<��H�Q��t�\��u�j���[fO���$RhT<����t�?&��9"Q�@�����W��x=�!M����$�`-':�����L��H!o�wQ�����cT<p����H�
f��^�V�3��4 ��l���_���������X�t%���x�%Q9Tw�fndx�L�h��Z��"�����`y������������K�61b��&F�-���x[��B�m�q����-�s����-������*���NdG��P��.*Kl��k������%qG������7mUlM��m��=O�&F�?��5z����j93���9quV��EoR�,~�+�C����(\�b��EOx?[@��Lf���lY6��, o��(�mY@����|�Xs��>V��/��:�����P����{���N����s�j �&g	�7�A
Y��&�_�rS�^�C�_���>Ts�3�j�5�V�+���z��f>��v���E��_2��b��|�E-���<����=O_*�^�J�S���E�/������b?|�k�(d�����?��B�%��b?x�*Q���E�\Q��~��'+e��ez�y��,�Q���Ksu"�d���^��
2�Z3����e����K5��,������k��!�&K~�[�c������=bD����^���Lb�Z�C5'�\j�5��1�~K}J��pS)�j���%�pPd�����^��]��=��/z~����%?�r��P���+�����ND�j�_��1�Z�/z�B�Z�C��6�B#|�?<���@+�w	x����8>��C����,�[kB��s�qc]����.$e�93/���BR����G��������3���X[�� ���o�����pE����KY�c5���JI�P��������G��/F��?�w��?&�|UV��	&�*d�����Eoz��}�@V+C������?�s�:BX������n5q�U����g��S�����_m�b�g�$�������X ��3�D�P}�*#����"��C��On���
&����As��y@�\v�}��d�����{�s�����K�Z�Y��g|\���!��@��>�^��8S}D�P�MJ�b5��8�����Hp�[p�fv�Up�����35�Tp���l��=OS z���A����X��j���b��D��

��'�*4�?3�4�h��E�]�K8p��W�\��&�8�e��������/{4���x)��7������Gt4��YV�s}�R^��?Y�7g��`m\q���J���F�����_���?����}��_�Qe������F,b�I��J�������������_~��_���{\�J�����u����p��s����h����uu�F�/�[fw�����_�C5�W��X�K�O����@Hs�q��@@^5Wir'�#������N�#���'��1u�7�E���Qa��oWXZ��nwj��D����#�J�P_[���v%���!m"�K���:8� �\�4���uy��2���#_o�Z�
����2�V "�\��F��Ia��"���pq�������������rD�\��+�^����%E~zw��5�v�R������Nj���#���K�����d���d
�M�z@�\6|j��������-���)�&�J��I&���tD1�'V��L����1����eW
�2��>���r��������
�`K�De6���?��������k�y����/@�3�[�kh<��T��-L�v�j�������62�LF�<�?�����]2�����W�4���p�Z����������?������O���.�!�:����S�{X���<�i?���/����/W��*���N�ty��~�G�WcXo���"n��O������������tc<���(x-��{\�o�T���(���|
��em~tEA�|o��|�zj4���S����#YM=������K����1�&����aYM ��DR���ufGNE���G�����|�=3�G�V�`�X�_�4TP�U�-��"YS�����q��%(�M�v�����;���8��D1R	����3�GZ��jh1g�RH��~��:�����#Ma�7?�E�h��:�
���y�nv�>|E�/��b5����"�*�Q�JT5�S��	���.8��2_��{�H�SSWh%���L]�J[��*��$�I5qV�����+���Q�xb��+x'��W4��i�����\�2q�
������5q���w����{\���������*�W�������K�O@����
�j����&j�
��v�X&.h%��ez��V����&.h%o�e5q����Ij��v��M��9�m�����1/G\��~�]?i��CE��O�l��"��N�A��b���P����-�d��!�����hQ+��G���Rs*����_��Um�%3bh'�T��NjP���L���I���;�Q?��9���&���V2�����yN���A8y�wyNl�����D"���f��H%��*-����� -�?����_��Ne����g�L[��"i9X����j�������Km�9-'2��a������f�3�&0h,��0����$�V3���:-g����5�4�.�i9��^J�������j��������	�����%�L�53'�D��	����Zn��z\�9\��S��rj=�H�� T��_!�����L�.k	D�����X�_i�*�������,%b;����qpl'�	����d����� f���R�nk�������L'�Jh�N���C������s��Jsf��"��t��[Lg�u��:�C�{�zN���:�Kb�N�i�:S�Y�u"�_�cT=��!|���jF��!�3Zc+�3���}N����$�G��[I��rj��V��r��:�@�J|�IM^��M&�����0��'��9����}^��`�%=}M��=���~�|�LM_���s������R[O_�:�m1=}A]�L�j=}r�1M_���j��B+IL�VR�*���&9���$>]����J���\�/��L�E����W����-�>B����.d�j��j��gPH�.Hj�!�|�;��N���(D�gY@�#S�Uy���y�{��������Gg���F��	�4�k��3D��	���^'�������+k�x�����;�����N
r�7�>�6"}N�V����RM�=��&��k�x�������������0`:���O�<�i�k�k���2.�!u��|��K��./����}���F������j��68}�=(D�-���mP?�� �
�^�h�a�����Q��\$������j1Rxt^�Y�-
�"�tp�;���
�����&[���-�	��:5e���2�����z;Cm�o�am'�`J���������E��9�1��`��3y���k#�����x%D�=�qY����Dz��JP�%9�f��~KP�WB�?��@�o�
.�JX���J�����7�r�Z����2N;�G7�"��n�c������O��E��m�D�(�QOln��XD���n�u����X��5S�Ey,@�#q\�=���+��<���{�
v��#�4XTE��4��Y-������7�f�
endstream
endobj
36
0
obj
20732
endobj
37
0
obj
[
]
endobj
38
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
39
0
R
/Resources
40
0
R
/Annots
42
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
39
0
obj
<<
/Filter
/FlateDecode
/Length
41
0
R
>>
stream
x��}��,;r�~4��BwW_?�z���Ve>��eH�aK>���!��dK6��wUe�������H�����2�`���������[�����w~�����i���q7?�����_�E?]�������������C;�?O�<M�'�y����w��/���������7zn�v�n����#�����K-����x��a\~4E/����0/��{��������9���|jRH���~��V��C������y�����9�\���K �3�~�b)r�!���S
���~��V��C��8���y�����9�����B����������P4��@���h>��>��Go�������WH��}���:U�s�<�M���R p	����*���d���&O?�~2<�l`3A������`jl&}��:X\���f*���:Xt����o[�Bg���7����
LZ�`Ypl&|+�:XL���G���BgK��'��f*��*t�,����d���i�3�e�0�L��� -t�,8�6�=H�,���f��o�BgK��mS�L@E���
�,�df���\�
�,���f�~o�A������f�qo�A����h`3���i�3�%��S�L@E�x�Bg���dx2A�������`�l&�}{�:X�f�	�=g�
�,	��Ia3��Y
�,���d�f�,�.<�hPX0��?t�=��S��U��E2�OZ�3�e����\0�������`2f&���R�`Ipl���Td�g)t�,��������N��Y&/���������I
�,�������I
�,���f����I
�,	Nm��f*���:X�������I
�,���f�~�$������f�q�$����``3�i�$���S;�����l�,������d�v���?m���`4��\������!s�<, X.�	6x���A�Yp2��\0�v'��T��E2�OZ�3�>f3��'����;����`�H&��I+w�'����Z&�"��C<Y�I��T$l���;���`0��\���:��T��E2������;����r������<Y�Y@�\$l���;���`2�M.8��OZ�3�>��d�
��rgP�U�6M:�e.��>��U�Z$l���;������d��O���A�Y@�\$l���;���`8��g������A�Y@�\$l���;����x2���?n��;����`�H&��I+w�g�4��g��?n��;����`�H&��I+w�'��;L��	����L�y�)�,�[<i����,��>������rgP},�<i����,[S�L���vZ�3�>��d������t���?��'�����S7���D1O�v��9��o��P�������N��F��]*�>��{��0\�>M]?�����=oo��]@{MJ��o���k���>��2<]�j�k��?�yj��[6 �)e=�)��LQ�{�lX����u�����u}�n�}�&�m�����4����KKd�?O�x�,�E���f���*e��}Ni�cs��s���L�,�YqO�������������J^���������N�������"L�w���_��I�+�!�_M������.��u���}B��O���0q�U���{�����=�FH�������xq}^Cr���Ym^-�Uu�����R&]�0����!��}NI��+��N!^��#}����>�=P�u�;�p�>&�1V���s��{Z$�������k��E������a�2\G�Ag�[���1�C�X��������������.%N�B� ��c��}6�2������;�h�#�x<�l[~o�m���|3�Vu�L����a,�k���>�M��7������nC���UX���h5��>�������������V��n��O)���g�E�[����up;�~^�G�������s���uU�k��&I�R�w#�������*� 1���v5��_������V�������I�m��um�)�Y"���/�OI������� ]�:�:q7)u�	D�����9%�s�4SXw#�������*��	0��^"V�E�4Z�����)��j{�����J����a�)��{�lXE���Mi��X���L��U���{�����v�JtZ���uG���fC���!mc�t]o�� �|��a�QSH��Z p	cv��L���~ Z�7��iR��@&��`Ff&g��|������DK�L�0������	%�
��Aa���R5���t���Q���k|��*b)�����{M�
��c�hd.�	RjyUg,:r�}��Y�TT$�@���U���&L�I�H&0o,��ze�pT�% $�=&KH�2&]�,yh���M��wVxt��^��u����"� �v\������`c#����d��[�4k9�o�\���H&�
duL��';�E2�]-��^�H�J	�
O���h�;>������&5�"��DB�-(V��d�G�P�L�������f����I@D\$�����E3��u���	�)�_��	=c��d
�yG�H�l3�����".:,�E2A��_>��<��N25�1S�>�BE2Ac"o�9�h$q�s�p���H&�����N27���Wf**�	��&����yHe�g�Z$�vj$jG�����v�"�p��Uib��G��]���&��� V�daOs�������;��YEM��=MBE2�V�8+\���yH��E��~;Q?be5��BBE2������XX����q�L�x���)�K�+I��uHV(�@��5��
&����t���dC~�N�"]MV05�)������,bjn�w�8�M9�q����H&�j����F��<;��E2�9��?Qn���(u�~+�(�H&P�5���Yc�5\�M�c�j�GED9�T���c�P���#���;&L�I�H&�f�*�*a��5;��E2��������d��Z��d�	����l+F�r��I@�z�H&0�����%Y@V�,`.*�	�Y��5G��Z�, +.�	�W����cE%jVe�D'�DE2���+V��h3�dg��H&��a�V�
9�-[�E@��H&h�������i�3Qc�f�MV���q*�	���f�~��X>��v-�	,������D�P�L`vw��#n�P-Tk�L`;u�:�R�CCL���"����J7i7���
�*����l�,ELv}4O����d���.xR�5[]w4�8���\�5~��j~I�5!��H&H��7���e�n8��>�U�\0$��#<�6�u8-
1�/����f�^r=P�L�R��^^���E�\q��nw��[�f!7�����$�N���k37��Y���T$��x���oM��6?������))��:~�P�-yMH5fjzI��a�E2AgN��[��5+}kV6(;��m�_x3�
d\��oMc�����l�cNl��&��ebH��Rb�[Y�Ot{���&L�	�hAJ�4E���.�������$T$��*�C�z�I:z4�o?��R�H�L0&���P
�rl�ps���3�p�L`�%Tl��K��5QK�&�L���d���5�-������7.�Y~*�	F�CU1�`��������P)s�����kS�~��3��P�`6�h.H�U���n�}���t61K��T��H&��W��_�������{�x�����d��z'�L�������p�<��d�~�f�( R�����z�q�2A?g��w����xt�J!Y�d��jn�(t���45��q�$C�Z$��
FZ���qj(i��&=���!�d�$Ao��\�&��kLL.m:�F�����;���7�����7I�L���� �K����w5H`��R�{'DL����hz�DE2AJ�&#{�"4��`j�Z�rL�;:G�;>%�Ug��a4N%%��"�`��J����Jif�Y�S'�B���C�s�����&L��H&��;�����&L�Q�L����J�����3=���Y����d�A%�H
��So�w���U06�u��Z���t��!�n���5�RB��>�t�Z�������KI���H&0��E�_��f	a���w����a�=j�W���YBj�l�\���R�.�PG7w6��izCE�m�{g�F:����mfIH�m�ZzL��3�6c���*�bI.P�b�Yi��37�M�c�A���xg����&�F��H&0ir66���b�hSI�F*�	�W�?���C�-YW�<�#�~b �fQl�]G��T�O�@�P��e1N��E2�K�(���?f]L��H&H��=V��Y�������"� %WN����]q���x�otLf%,�|F���;�2&�$��BX.p��nw�YcjLf!,�S���t�Y�,{)�)��q#ez��5�b�W��d��dz�s���{�,�e�r��iL��'M���fEL��"�����I39��Y���k�LZ{g7�����cc��(���M�:�=Q�fV����Y��)���~�5�&��,��X.p�w:Z��_������"���V�6Sb\!������ff,t�2���K�5�:&�$�bX.H����[���**�	L24��Ig�9�$�M�"�`+�t"<�}�.X*�	6x���_w2����<9����?��d:��f29���8����[�i47��4&�_}�~>��Co�M0��|7i�M�RrF!�L�r�L�������-_yX��S������q0���,TS�o)�	g�t�Ej6vf��(q*�#H���gr�vf�Z��H&���qn0��BN��NE2�I����&���>�$����d���sgRe3'$����~S�?�:��e�p�Lp�f����|6���Gp�+��;C��K���P�L��s�7*&�x&��r�Lp����;i2�*��q_�R�������g`�`2�9�@%%5����e�M������%�mr&��R$[9����,�X�������7��#�$��'�H&��M���S�G��W�P�LX�i[gz����L�dz��d�O����{D.��gj�s�H&p�y�*3�hz���E2�Fz_���3�~e���#�[�����boy*8*�	��&���:mb�p�L�Um���^�Y�\S�6�cJ�,�����U.\$UR��|f6�fV�W�<CE2���	#�&
S�6��������U&gslv`����H&0�;Kabp��M21g7�E2�}�]A��dL5�	?���"���w{=��-�9��b*�	]��3�hz�KE2�}m�f�L>�%�p����cvL�b�yN:��H&@�xHKK���0	�_V^���1�&����,���=�Rbi)C<���'���7��@e�7+�[;`BM���I '&G`���ar6�|_@�.*�	Lf��	,�Xf%+��$�	�#p_y��l$G�6��Mv������H&p{��X`+��L_�@nf�A���GaSK�l���LqjA��;����2�h��D�E2����V�Yg��,`�qp_����9�g���
����'��:�b�p�L������m��[C�Y�TS��oy#���D>���&�)��`�,��`�S��H����/���UbmM���@�5� }�;S�	3�d�$wDR�L�2�q��M.��Q&���J*�	R��\`bqc�����Z.�	�^<�X^
�jMw���N�#0�~�:�����Y@\\$����l�J�Q��k���9��]1�<y4��E2�W[X,_c����GqM�#0/��:����:��<\'���4����2�f����6a�"� ��7����P��7LT$(��]#1���&���cJ�E2�������?�fI��U�T$���������F�:���"�`��h�Tl"�M�r�L`Zywd�G���b�@��^q��oY�����[���F�����"���fF�J"��KI\\$���ET����.m/g��N�mnh9���8X�$�j����ku���	�en�������A��	�j�����M����#R��D��NE2�_��w��.����/�i��|2,���m���H&0���*�|6����"���v�:��g���"���a�H&�T%�T*���W	����	$����Yd��q_�Ie�L��"Pv�.��"�����^��3����
&9>a�f��e$n1�&z\��"��r�k��
��g&*�	��fl���
"���Z�d�������XJ�&SQ�L`_��8&��s7��T$�3��:��&�P�L`Y9�n�HS�~6����i�nu�G���U0��v�,�|�1��I��,0�����9��������\���rQ��9~!�$�d�#P���������L�I��8��x��S�y���P�@R9t��}g|�XLq�Q$nH.�����^��7�F��Y@L\$����+��
��dj0��q�nc�5�,��8G��\$����l:��4�`�u���:
eN1�<e�
��w�=����f�@��"� %�$&�Zb�c��ijAJ�2�������T�@���������|mT8�:�CT��c�A��&��b���)!�"������XYsdJxH yW:G�x��Lh
����r.�	6^R�ts�HxH��T$�����Fsfh�]��H�L0&���@F9e(�p���#0�d��A�}�
����#0�EE2�!�;�P�Y���I�t� %���5�C��D�E2A�=-�#��������t�p����H&P��SZ����"�:>�3���&k�`��3B��l�0L�Qgr�xg�jj�00+$�N�����
,�f=6g&I��9���o�n��n������&f�b_�D\$�N�����'4�cf�aq/DT$f@}����/��sg��3�w�A8Y�M�,��&,��wx,��&��I Lk�L�^w+�E8Y�M��,�:,0�+�������&jQa��LT$XjI;v��j��N���Y�M��P�E2����o �[I��Z�Ij�H&h���Eba%=fVH��(���QRbf5n�(����d��h>-<���CIV�9��
wcfY3��u�e#h��H&H�����b25�.S����H&H�w�Q��&�phM>�`�\0|1RH���
9	$G��R��KmY?M�!s�@�45�@qo;���&�PXI ��:GX�/A�o�:�+	$9����|i��yh}�yX@�\$|U�h���i���Y�\��l��|��3��d�r�L`^r?0g]�brZ�br0��K�o�5f���*�L�\.8�@;�����H��H�L�X�d�[>XzCEE2A�}��-�l�����s����qZ��7	$������9���bZc*���d�/��|�i���fS�G�E5S@���i�	��V���'�L����&G�2/���v����^*���6���d�{uLY$�����M�F�e.���C�f����1�	�����6�Y
v)�	2���c���s�Z$�v�_�c���|(��H&�lX�6&��yV���E2j��I��%J��������n����j��0�h:u�Z$X��������9��M��E2AF�{{���\�`Q���"���[�7&��3qu�=[�d�{�����Qn�@��.
j�����������nL$E2�b��Y��Kc������q���,���KC�3	$�c�R��,�b��7EM��88��!��)V2
l
.�	r��e�*V2�hS$��x���}�{F��`��i\�Pq�L`��"(��Oj�!f��g��,`�qpF�w���i��0�@QA����!0
�S���0.�	\���2�]��
���7 ���
5s����dj6�i�3I�L�R�l�L������q���,Z��!L��5	$/d�R���d6�i���&�d�AJ}G�ng�Zlf�&\\$���3�,��oB�f:5��}��x�=��f��������6��l����rp�����YL��������Rjh�omJM)SOF�X y*'G`��������)�`����8 ���{/tQ�l:�����4��#H�w�
�eL����F�q���]��f3
S.�	k�}��x�F	$u��6x����>8mc79����>=!�by6g���d��{a���G��i��0q�L���b���?�3�~�"������m4���Y �"��| ��e�d��/rrF����fY4�������"���g~�a�lT��B�d�$Ol�����
MH(�\$(w����l[�����@2%��%���r�
<U1-�E2AJ~��`��4:$wa�j�t�I�������X�4�RQ��#H�%��	�d;@���R�\e6LT$���Q��=�o���pr����jV�F��5�j�4X4P���J�G�* ".�	�V��QE*�$��H&0��[�l��(R��
���d�/���("g#F��@��"�@���_+�<�"V0	��5���L����	��V*�	L�r�.�@�X����Y�c���*	ZI*�a��!���Ss����L�8`����v�t�������L!Z�d�m��;������L�������1��@�>
9����Kb��Xd�M��79�}�iU!k�F"+*�	\�#��Ll]���I ��:G��4�\CG�l
����op�yk7\���ZF�d���&G����~���u����f.�	R����������z4��E2����sZL`���g��\$��j�����]28�f��Y�LT$���`_���[��sm=�z2���&89�����S��K��W�6�k*)�	�6��-|��&S�@�M� ��7&P��fv<��
�)��[BM&��I ��:G`Z|g���3��dfH���(�|�l3)�L"e���&G����8�����^1$�_������|Tb��z4]�I��9���������M'�@2�
��p���%@01������Y y��������>�n����2�d�������Q����<�������-?�|������'��_����5?���2#�U`yL,����Q���|����G���b��?/���c3�^������^�����[6��^��b�5����~L�}}6��������p]����r��_���O�����in��/�����w�?�w#�Cs��_��gw�~9������7?�~����/������5��p�y��a���?*��x[��?���/#��������z�l��tY�����Wl�A/���@�p��k!�4l@��j�T=v���M�^���Q��v���W�����_~x������~�������n�K��9�?Oc�}���+��eju�F>"k�u�J�}��`���B��`�k#���C�`��x)��6���v�
�
l���Zk�����,��W��6X��2<���2a[>D�����O���m��b����_m�����]}���/6v�k;M#�����C�q���F~�A�r�6?�v��S���� �~���i�9�����C�K�tBYB���U�nz����l�@��v�6w���[��[���;Mu�����=u[����Y�� �4_�7j��K`HW	A�tMY$�� e
�,l��H��I��W�Q6�(����n_�e����o�[$���E*�S�;���)�K��\�j�"�@2P���]j������4y�<u�5l��s�An�c�
Q�	@����y�f�|����8��~/��6N��� q���n���q���V��x�ti�����1N�LU0R�U��-sUG�y���_����;��1�G�@���~�x��Z���,��hk��C��V�A�4�VzY�/\0R�
��gy�e�AG��z"�A���c�u�}������n���Y/h��X�����vY�/�)���#[�z��8O�����!oM�l�����l�C`�K�l��rs���^����0��:�H�+���_)k������>M���7�����zf}��?��o/��?�������?���������u�0_�����0S�W;N���m�#��q���-:s �����}T]�_�����-������S�^C����/6&������9u�Z�;��w���1R8�����?oC}a�y�c?�������=��_����R����J����kn_{�z
�[�S�����8��M<�y�����8�����|Ms�
5�=6��{��]0��k��b��KD��.d{jS���N�7���o���:�ti_F����E�+��Po�r��:���%t�p4��M���Y`����2/�q������v�?V����O�Y[�X)���P�\{
�'{�����M}�������7y���#�2����N�n�
�X��������n�s����������������O���+s?]�]� ���%������n����t1?w�<]����?oG	�[~���7z��/yC�����?<���?^^g�s��kt�������_\$�'��f��7�ta�_v��>���4���|0�g�j��{@���.z}���M��^���#8���!���k����M/�]����1M��d����[*�����u�<~+��a�.�w�����!z���-����o)N������k�!�9�����$���9O���y����H������o
�\�*�[e`��k7��*C������9��Lv<:��C`%*��k� \��t2�A���������������-�bO[�#�����h���(������]�d4st�<4B�fN��}5\>L����g�y�^g���m�K�}p2���	�x����&#��[�
`/+|�#����:.sc���N�$#������� z�w2�Am)��NF2�-�[��hK��y2�mhK�����8�V����f:���F3�����2��:��f��9u���U�B>�6m��U8����C�����z�D��7=	��?o�A�15R"���HV��C���&v�f�i������82Rbm)����kK�	;=Rbmy*���H��-��H-���h��
�B[�<��5R���M�|@�q�z�%^�>4������n,^����G�
7�v2P��X����!X�5t�0xZ�!�k���]�v�e
L�0����K)����!�����U�T_��+��M�R��%O	�(�U�@�@���I�*z
�������a?m�\u��B�@���*�"���~FC���&����n��NEh5�|d1Z&"�U�l�V������y1�6��=�'�Z�{�u��i�0�K��K�k�])p(�F�Co�p��
B��[���[9�����
�����8U��Ws�9��9������}�	W�6�9��<���,O{u._�7�:����[Z��tq�>��������Pp#�3��`�
B���T9���m�8���o�#���o�?�����X_[��CX[^AOj|s�%~����C��B�i���&�c��-�5�����##.weDs�����@�;����(�����rs���kPj�x�],T4	�W��
9�0�k`=T�g{��K�}���m�Za������]^��3�������������a=m	�V����g�b�������Ag8�1�����V�AdLC��#��&p��AF]�;�z�,0�3Fa�@�(Z7E���$��z��cl����BYi�0��V��[��i3]eK+]�x�n��_D�@�d�O�`�������2J�`�*��\v�k�X��E���w�6G���5�Dv,]i!��^h-�/�Pw��v�4�J�+\7�K���	���D(�]N8WPE��lqUPEX���C������qXT1��y!��"T���i�V����#]wIeMi���+�L�zG.XU���qe
��zg�p?O�@�s�;t�Q�|�8�!�H"�D������������G���^w�p��Y��[<����C#�
�������
��������U����
VZL�P/�^�(��X�OL�~�dJL��ur��zg_���D�Z�K������?T[���$������^�����s�0��
i,��(j�����P�%��)W��,��O�"�����)��?��w��I�G��
`��K��#�@m����*_J��k^Y%�
���F�]�yU����#��z��=���9pc]b� v�K�&`��q����=��R�,�&�����Un�����C�*�����e�+����9��Y������^t����^C�=�s�)�@V[/��\)�n���p��B�o�3=b�p{����k�H�X/������^����������\��D.<e����1b���_��|�_2/
=
���y	A����k��Pm"ac�}�&`/��K��i����g�������c$�/�X+^�V����`�HjvD�C�1t�+���5~G<B]�Z���;t��6Q�3�}�Mj��)�IL@����[<��*�?"~�D�?T�Cs�o�A�/�X�^!����q�	��:}G�$B}�����ptm��kd�`�n���ut�R�6���)K�_"�iK�Ci&����R�Re����_�P�Quh5�r�K�k�H6Ot-�}D�&&b�/~$&`G�$&`��&)�d�6)|KL�>D���������Z$���#������c�\���e�5�;�`�W����A���2����p���6X;�D,��y���B���~�T9n��UE�`����%�w���6X��m"7�c�k�<�
q����}�]o��o���c���������?���_���?�s�[������������z�M,7@�LO�
�#��
�?���J����������� B]K���?�Sv'#��@���D���1�}R��^����<V���;�B��x|dp������B��z�\�A��G��;�@ ������������{��V8��V�t��v�m���[<Ro5#�-^��+�zN��_���<��\�l�r��"�<��X���!��T�������E�h�b���$L��	 ?E�v�v0����"��G0���B��c�`[�*����<�m{��������IT�
��pkG�d��@W�U�
�,R�N(�`�5����U�L��,}j��c�)��s��t�VY=��+,M����V�m���c�K:2W��#G'�0X�
����6��U<!6	����*������MB��[D�MB���D���M�mB�����:���l������U�A���6�+yu.Or�s%��9T����[#y�o6 ���_/�!�����y���]Xo�,�����2_N�N�-�%����/�D�o�+����4n��G���n�B�X�����&n��������_���{�;�[�� �����k��#����}S:��20n�H�H5�C]�&�Y��������,L`�r���0����yS?���B]<��-��U�]��)��������)?��^'��6�-x���f�_�m�b����c
�o��-��
��0p�m�1���=��������O�t��X���u9������C3}�����o�����:~�IL�z�tXa�V�]aGn�K\*��k������K��x �^�T�-v�lsMr���K�O ����l���1��n���������:V�XV��70�����s�|s�\������d�����l�\A[S����&��k���5��U;W��)|H�+hk�#���=[���B�9����y�,��.�[�	W��y����9��7k�&�������!q�����P.�;���S����oy|�8\�B����YX�-�c��n9��N�r���L���� ���=�84�w��:>����������v�$-_��;�8p��v��S�@_�c���
��v�_#����$t������������_&����VOn�J��A�b��$Nv� �!���w� �K�@�v� �[dm_��8F�B��ceJ8�d�/*p���U���U6��v��M�`9V&��w���9�������de�N�c���W�d9v�%�>m�#��"i���n���+��[MA��Q����f��@��������\��V��]��M��~�)��r�\c'�6�r�jw�r�jw�0O'���SS1���W��)
\����+������B�������M�}��y9�v�L���p{���Pq����"y��G�����Q�
�o�<*��H��=*��z3��������\���+�m+����A�GU��h�
�I�����#��j��+��k*��+��8�����y�Cyv%�i*
��G�S��������Db��
���o�����{�Q�<n�����L����ek�k�������Y��*7�xO��C�����xOu�#�����8��`��'E��g�	 ?f"����q������|���l������`{GZ%��`�?����Ws���h�	�h��1�=A��HFe�=���w�xO�Y)������o_N�'����)���+�'��D{O���8���cW����F��y���g��Q���D��iO��1�A�I96&pW{R��<F�Q�'�'�%�Qty��R���*����Q���n��R��#ek�z�*��v��������"[S��,��*k�r��:W���[gu���pT�Q��OO��P#��	.��XXK7����I��B��+�p�K���-��P�b�m�)�
��K���v���zN<)n����]�}���	o��@���xR��L���	����HR9��[=��K�p����F��=t�����,L�Ra��;z��M9���$��f�|����v��|���ca"�l����0�ys,L 5�<]������q)�sQ~����A�p!�
�-,>�����.���[���Y���#O��X��S;cu[Y9o���y���y�Zg����qB�u���%����$��j�5�&�t�k���w���o��~)�d��-���u����&�*����zj=���2d ���bj�������5.T{Z�e��4~���HRu�iA[���=-hk���������rZ<�:Q{Z��<GB�U���D2���y������9�7]f����i��J��$+�g��#����m�G]6��)�0�
Z�
��yu�|�@WHE�O	���<���a�����G���=����k7�r��C��U�������V1Z>���C\��7q��S �m{����$�`�E2hk�
���T��@�m���+���NG*DB��
�B�cj�
��D&R����o�3�:�j{��[�e��������[G�o(��NG��lhg��,�MN�m�X�����m-���\������U����o?�2z�
��Rwj��,�m���s$\�^1N B��r��`2
b�bPySNcTH�Qz��vV[VN�+$����)��q���(�k�Z���o�����PN�s����<��r��s�A�S��:�v�t!��J.n��HX�r�p��U�&�S:��l��R�}�\d�\*��z3T5\*��,N�]��fE�T�]�_�����K����+�����Jq$��mW���2�C������r�p��Gv��C�eW
u\9T�]�$,�
��G�A�Pa�r����=)�2���Pt�v�P�����}(��\c	��
<}S����Ey�
���k��O����.,�����s�*F�=��r�:���LN>i�	 Gb��	`?���	6�c`KJyO�������9���'��O��\{O��YV�F�)�	��s(�PyO�#r��ZJ�����OI��Ci��I9&&�����I<)����|R����o�=)��������H��=)��+yR�U/_qK<)��|L�I9=X���D�����c���Irv9�$~���|Y��<�����v��A����|�N6��W(��ds��.�S	�����V�{�@�G��*���-��+���Q��\�:���@?\���E�NMs�Fpz�85?��i���,�90��3l �C�T'��r��{M|A���R�O��������o�Q�|OJ�=���H��c9����<�>��k���V�,kJ5�%x�~�sX�.����Y��u�4DIfj�#-O-35�?���d��@W�F��._��c��+;���`��tW[��3�Z�@3�~��������������T��������
�D_Z�4Y
gP[�}z8��X��TP["�j0s�%p?��`�|F��`��#9j0��^~�)��`+�Xm��V��c�5�(���Al��k�h���3��������#v��!��/��������=��n�5IvW=�0p�z��v�a���Ho5l���i����+~��#��2pA=)�:�v����\c5��P���]�������*l��'5�!�:���%���1a?VB�������w2�����|TcB�k��I<B���x���'���2�a��J�B?������z!�*;��/��#z���T�u��fr�m7���7�eH���\���i����`�L"����dH�O�
8=��Z7ey�����4����Wi��T�=)���[$��@i���3�z�R��!
�<���!
�GVeH�mR�0�s���s�����b������Z�3^�W3��p�G����l#x���� �e?�ptS�q;�[c�%M/�������9�����m��ni+��*B[��W� ��u�7~������a=���K�M����`��H��`���qp���52�.j���H�EP����>�g"�%�/n���W��Uy6 p��:�[�92?�sFX�����z�����5(r$��J�3�HF�a��]�����j������������N��c�8J�:�D�{���2�_�e_�z��"V�Z��'X����9J�.�x�����"�|h�`�F�d�
`�������0����/�H|�NW�&{��Ip�<���h�a���tO��vB����{�u�#j�~K��M1�=T���k�nF{�
���P�
$�����$>�{������!��e����c}����X��� zh_E�=t��1y�Z!}�]c����=���!	�p����{�\�?L��\! �rJ@2��q�}m`� p�/���
�m �*!���N�@^���av��6pSf~�_�mZ��{
���W� �g$%��`���,��@��V�k��/�Ku�E�O?��p��
����$�j�S`C���~�=��o��U�������`��G�G���_��l��C���E�Xc�"����U��Q���u�\>���.��O|�5|��]��jC�=�V��	��������.�4lw��8��
�m��;n��������2@����28-Q~|]��9p�D��%���B�P�q��~
M��apZ<� ��:�/D?D���5c)@�u��&K?�K�,Sb������|M�<8Z�f��i��
!�����mFq\+�"��m��U}�:8��!�����f�������~��F�#H��p����hN 	(�.t���v��<���8�N�m������������9A �;k,���<
��Y���������[�~:\�Y9�(������{Y���Q��,(k�`�G�)����}��Q8�U��s�?#���G��Yp�-W.����	����X�!Uy��T�"�����|��l�����8������\����Frk/��b��Wr;�7��v������e�i�H$m@@�H�%
Qr���%��7�r�a�n��
o�k�_����9Ad�3(���)�}����	�!=NV�#�@��(�����}D��_o+����:|:��d�|�~
L���l���l;*r��A_6��\��p��%��W"�|�M�'��]�����
�i;u��4iw��G���!y����R+��������~����.��@�V9_���@��|�k��'�9�|G����[�9�P;.P_>#�j�qql�{��zd�<q\ �c�U[�S��m����g��m�[c��r����.t��Vmy8����������j��v;����uVnI��a��{V �!0SK<��I��78�2�*�<�~j��J��Q=�`��.�~@[/���vZ��v���Y��O�J{��v��x\����K�T�� �r�<|2����Us�s�V rFDy�
D�N+�����o��[�%��x�D����
+�0�}G�_��>����=�a�}g�����@	]��}gH��K9�R~�[�����	�j�Z�t�.��j�Z�L��VT�r�x���DHm},��Pu|:�.N�N�C����
������(\>�k�!?����(�����(�����>n�J��!:��.���0�g$@By�G?"�������P�F�<=0U�QX�s�Jh������o?�5�1��!�Q��W^+O���sm���
���p����S~����B�R�	�#��+?���@��Ga���~�]����.���Z�}��+�1x�����k�g�]K����q6��.v�d����q��:�Ce�a��{�����\���D�"z�0������a�M�p�$�^N �n`(w��k$�G���k������q�dJ�=|6��C��.8~�2-G+�q�����99�H+�����+�$n�H�(�,8_~�"
�,��L���zB�v��{44���D?D\@�,�N��r��1�9v��d��{������A��?��P���p���/8F	AGb��P������i����@��)U9��
u�Ia�+1|�-������<�K�J�Zi�v�hf�J��P*&�J������k���������H��v% �g$��v%���Dn���D�Y�]	������p����l��/�`iW�v����������i��/���+�|�uec�E���I^��q% �Gd�N�P_���}
�@����e�G�d��.��u���dc��Q�g��L�TNt������[.����%r����3�3l�v���������
endstream
endobj
41
0
obj
19244
endobj
42
0
obj
[
]
endobj
7
0
obj
<<
/Font
<<
/Font0
10
0
R
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
14
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
22
0
obj
<<
/CA
1.0
/ca
1.0
>>
endobj
19
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
25
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
30
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
35
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
40
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
10
0
obj
<<
/Type
/Font
/Subtype
/Type0
/BaseFont
/MUFUZY+Arial-ItalicMT
/Encoding
/Identity-H
/DescendantFonts
[
43
0
R
]
/ToUnicode
44
0
R
>>
endobj
11
0
obj
<<
/Type
/Font
/Subtype
/Type0
/BaseFont
/MUFUZY+ArialMT
/Encoding
/Identity-H
/DescendantFonts
[
47
0
R
]
/ToUnicode
48
0
R
>>
endobj
44
0
obj
<<
/Filter
/FlateDecode
/Length
51
0
R
>>
stream
x�}��j�0�����.�1���F���}0�����bz��/��]�������l�<4����Q�ho��0���v�7���j����[
��,��`hl?����[4N��tu��nH��5xc�t��k#���`(#BP
}L�$���f)l��h7a^�������s�F
��
��{ 5�G��1A��+;���G����dQ���<���1��B�HT�H�H%�D�m�D%G�C�&*8R/�t��������tmsq)4�Z�u�I���%����V'A�Q,�S��+��hU]VZ~���	���qxia���y��r�[���
2��
endstream
endobj
46
0
obj
<<
/Filter
/FlateDecode
/Length
52
0
R
>>
stream
x��}y`SU��s����I��M��&i�R�B��Pi���eGj�T�"�#�"�
� ��6�* �K� Q�Q��q\G�e�]tt�����$��m��{���h��>g������<���%FDfZA9&-Z�;�����I�4L�3m���f�B�G�/�.[2�}��(�������L�����QD��=����v~�$�QO9�g-X<�����?M����fO��
B��FG���	��$�H!Z��}s�M�3h�}������1����<r����)�"������1D�!ZO���]�`2M�%t=>O�g������OKi+�����.�h���2I?N�U,�TJ�c�"����F�BV��@�G���������]N�2��F�������y�[��w&�}�^�C0�$J�L�h�t������������F�K����c���o��*c�?��O2QU���OW�0�S��R���C�-��:���3�H=�?U�B��iz����;6�M�A~�4GV�iz��c���t>Ci5��t58v���J�#OG�M2!Qg����`�c����,�yX.����l��~�/�+�V�oI����%�+���!�+}%���V=_��������!�}��K�4�G����
ZI�i-V�N|������&�O�o�.�O_����ug}Y��.c���l/��^b/�z>���_��X��U&�B!��_�P�wd}dW�/�M�������M/x��v�Z����������0>�-z�>���8���X��:�"���`#�X6�-`K�*v���`w�0k�h�`����O�i�586s+�s/����3����i|
���{�A|��W��-�!��/%IN|��<i�t�4N�--��H�������{������r�|��M~D~I�\�^�*7(7+�+*��:����t��I}S����Tm�v��J{�D���A����3m������7����KN������[�Mr�L����J5����0����El�J��3t��2����:�������e;�H�_nf��e�����K�����Co���,��i4�����<��U�KO��T3��u�Hy|�d����S�9vG+�K�O����~7[*}���5�wY_eMU��5�a���v�A�K5��K�Dj���=�#>����t�<My����0e:�������T����?����i�t������_�A�g�]���S�����I�1��\f���Fi�l��G�CO��k,H������f�����Q��K��^r����l;��_Q���4&2��){�/����Yi'��c;����~���
�f�.���B����cV�K�X>
��4���|��H�H�b'_N�����B�/��;��o���%={w����K��`A���y�9�l�����!#��v��:S��v[b��b6i��UeTX�j����r^`���"���	�
�>U��&�k0���mB��mZ��-C--��WFe�}�_�������Y����@�/|�H5�r��ID����J��
_�5�*�U����l���vY-�X:�.�I+RaW`�.����wU������Q���aO�B!,�VN�1���"����\f'&�)0 lMh��MX��n|3�t�z������79hbC0ar`��q�aiB��#)�~+���'�g�xx���5�k3�u��>�]�n�/�edm�Z��������V5��B���E���JtRS����R_�����,H��0�Z�������G���u�����@������n��FO��9��s�.GR���l�X"!�ubJK��2��T��v21��`�A�7����0���2�7�����S�pWx2�aF�<�a���(���\G�����N~qn��X�����DRG���>����!�@,$������\����
�q�@�>Q������~�X���B4��������&f��PQ�.�D��xM�Q�"^�r{C������6����;�R*��	��_�����9��W��!�����E�{���R����R��x�d�B��4�������!���4D�(a����aP�Zg���������.���-6�p��������^�:	��x��c����SW��n]U�W��a��&}����X��o�����l��h�~���p��:Lb:�i�4`W���+���[��'v����9����A]�~Q�(�-�"�9�f����dTe��0je���Ojbd���e�&5�h��(�Oga���+��Zit�.�c]��j�d7)r��G"�&{yL�"�9Il`���'�A��e�e�g��6�Q9��q�����O����L?���?���|�a����y
��F6��2�*WM&M1[d�dKH�T�]1;nK`��!fi	NMK�	��%q�C��aN$G�`���W�&�X��i�,IdJ���z�;�q�!wy�C|�`\�e'Y��4��tM�����^�����t0)����8lO+O?���j��5���u
�������_���j�����~���G>g���R��{�r�?Ul{d,?��y��������]��������><�M��E������)1A6�����2U�c�I�?�����V2iO���&>~���f�)��e�e�h^Ff��v*�bPU<NrU�t��2\:�q������������E����3�'�^�f*�^�K���ek�.�#���V_���_�b+��?�� 
��t����r��H��"a�#���_��������J�%�8���
@S}����O�I=:4��?Vg����oj�C!��.y)3����V���R�|���O~������&evV�)���R�re�t��"����C�$�-=F�b�����0v�~����oE�v��O�����e�8�O� J\J���� �Y�_R���c^�#9��{Z�K��d�<��V��$E:?�W]�$�������S6��;��&����wl�|�����=����sH���2b&�������z��E�}��\��bg �"�u���r�Th���H���KH�q��%�lVGr�=����p���onJZ����d�=�fu�U��*�����d������?--5�9�x���v��L99f�+.G�d{s�����q`������4��-8\����P����6Sk1:��0��d��j6��el6J��x����B��:U%����������~�gd�
��O{����"?��4����f��>}����3����7�s��H�r��+��-]�.�K��e�E���:��!���BN#�,l�����T�
~!�����(\�L&�I�
*d��-�br*������sE�Ck�b��������t�����B	��-�{������'h�tG��L�I�����nP�+���Kc[.��C�l�C���z��b������6�/�>�����o�����K��SEL_�!w�|=�J`���+��?}��8��������U��O]%���j�����'r/�u���dh���Y�%�H�-��.`j���t��_�QX`����%;�f��RJ��{z~0XhItZ,�i9^s�J��ky��^�������&��PV�O��e�eQ�#0'�zV()�e9�fgIY�b�y���~T�m�I�IX���H�]Z~����[T�H���b��OT_�������=z�*��S��g�������W���"�$5��
����f�n�^�$�%O�y���&���\���|����z�k�3�k=};�����w��?�0c���
���~hM��F''�2/�V��}J��O;.��3fN�����_��}dw�m�KJ�L���qx<r�B�145]h�,q���s��K�?i��)�(�<��������R?�����)d��!GR�)�9#�@�r�^UK�'��k��}��u(�P�ax�S����P�9O��&sJJ�������4���*SM�a5j����`2������Ezi�n.���9XI��.�C�;��O���X,���aE�O��T����],���J�$,TG-E3� [[,�Z����U�~�-GF,Z~�y3�t.��VM�y�����tR4����W6|�y|��y�����7\���������{z>x�y���!K�4�9-�6Uv;3���r}�1�q�y����:����Y-�5���h+��
�	���d�U�x���XW��i[�O��`�%���m������~[?�����3�-F��t�KL�w�$�0���Pc(��V������1�m���l�%��\����n�:����{��x���	S���|�j��� Q�a�� Qv����������%�Y��\�%�&gz�	M����4�3��H=�v�Mu�X�[
Sk,S-J��R�Z�X.HU�v{���4'P����m��[_��&�������o���&�����S�|y�Y��e����	'�O�����"(�����gs����8 �bJ10g�0������������|j��S�����H��K/X6��k&��9c�v���S���C�/<��g�����,������v)�����l:������
��&�R+���g_���#�=��s��z��HyR����5�2����NR2K�gR�'�`#���h9#�0iS��d��,��	�����o
e8}��@��r�z��a�c�����/*��|D�c�������0|��cA!*��
_�"�S-����jTR�?�,U���z|�3��ft��~�Z����=����3b3�W1�����7���Q^�-w-eK;$��qvI=�������������N�R���w����%�J�d�9UJNMKKB��k�d5�������P����gfN^(��#���A�,pJ0��RS�ii�d���(�Ew�q��_m���8���8�}S6	�������+K\�'�:�i����y���\h~��%�p Z��I�b- �?yO�=^w��I������,q���|�I��o�;����='�[��T!A=#��@����e������������������R���)y+z*���=ynrnj9�ye�.�.����O�w{<����r�����*N,�:5w�K��&ZTo���6{<��0\���u��y]E���\�x#��&��������K�������8��-�����rX\������4\����#�����_�����<P�15~� �Q�)B|t2���G
m����x�U��.�\*�3�qKJZ���b���b��t����6�g���6l�����
��~s�W�un������v���?N��]Q�u��W�,iH��/)mL����'�ld�w<�����Op�(=�d����z��?��s������M�f����,Oc�o"7�\�`Ve�HZc�K�6M[jZ
;����$U��6����%��s�;���		�D�31���*�l"$�VBBm�y��9������_J����'�N���U���0�f��������z��������~���t������s#�����8��.��c��;#�Zk�����<�����jR %�>TM�v����]s�o��5��*&��R0����c������
|����5������M�>K�����>�Y�c�I67��CC�z�n^a>n���"�f�#�Cf���"�L+�I�\�2s��I����j��\���e�����x�\!����{�MpS��bL�
��E����]�����y�r�_��k�������Q���%9�������kjv�����n��<����'kST�z2���M�)��Sp.+)�XJ��*�{���w��#�|��R���.d�
2|�8)`���E?�du��)!�b�R�z�v��f��]
Hw[>�|cQf���nS_��]*xam(��@�h1K&Y�e�DS"i�V	�r��~%&{��!����?��	��l0#4�a6�,E�d+�UE�M�j��I��\�X�F�c�����4U���$&`o��Ud��o��y�XS(h�')LY_n�)Q�g��qv��$`�5�EF�y���
m62���B�R^V����K��+"tjI��AK5V�Tf*�*l.t���"�bI��X��'��T�/K~���/@D5�}Y�<�����%Vg ���lp���$V2[zl.|,p��%����\��uG�����)|��V�jLcl%O�]]��Y�)���Tl�2��B��':zH�
8/(<e>G)�#����
x}N�(�1��gON�8�NQ�d))�\���&$�I-�f	�����Jt����N�8R8����Do�#�&���r�(�w���� 8�sx�����:'�(����&[��f�B�'n���������<���B1a��5C-�~V9�N|go������M�8��k]���2�l����e{ou��1��K�g�y����q��I��u��|!�&�G����������=B�'b�Y�R���N�F�h=5�9�^��T�/J����'=�tF���$�������e�U�Q:�X���p�`�������"�$�����JL�m
`���ZH���5�����rv`���5���Vk�>k(�b�d.�a7��,X^F�	�abv �q�����,���5��;[;�<0a���k�nH\y��������&�_��������z8��H2l�dx���=�h�~J�O4>Q�e;�YC��l�*��,��96�&��;;���T��"����Y{$��W�XY�>
u.�Ay~��4�6G����ySZET��
�9�u��`f)���4��$���o�"&�������>r��+���w��>�&V�zo�|���=������_�yf��O�x����?��M�G���8��<2C��%��������������+}R{z+�����J���L-�����	�z$&�Ap����-q���F��U�;/�7��9��U��%'q)����b����eF}���Y���f��S��t����������N�5�C��C���/v��<�������\�O]�E������`=	���X}�q�fxw������E��Q�9tq.�����y��G/���������<���<���r�������P���l���>���C��+�����[s��_��B�b��NgB���u��M7�e51-q������I���ro��bK���f�s�������`�c�Z��#(�=���d(6�*Bx��
4���i�������a�z<���Q��p|]o8[��Q�'�OW����*�Pb��k��2������>n��wV�
(�eq|+F#	[pK�Qw��5�����������\�����W"'#5�
�����B�z������I�Ta��[����--��zn��� [�@�D���*��V�����=Q���X�Z���v�w��K�J��T�2s���J��:�{S4�������]�
E�kf�>��2������i��r�<�t��XRN���H�����'��<��s�C��7��Gr�I���-g%��$�{=��h�aSJ�c�,/��/�=AI�`�O����1{���Y�8'7�~����{��U�%�Xx���YW�U3�����+�L�����,�t�=h����%4����=/�����~��_l�%}�oRvP:�
\`�j_d_c��vG�}�p��>I�Iay��l-LJ�u����I�������Fg�9��g�N\`=�3 �d��9�V�y�Y27����������g�q��� N2�^!=��1��=JD��R"�07z:�>���e���+7fn,yi���]�\�e7�>�g~e`9���)WE��o�;'������\-��`�"����|��Q�Q����5xw�k�s���b�)���:ZJ���E�	�j!+r�&
N�S=n�4�3
��j,w�GG��4u�q41qfn���M�x�^n��-Jz~���8\�i��������������DS����bvH�uU�q�=��")�
W<.���[z?S���z��8|�b�G�D�'���,+��8a ���>hx�6G�`�>v2U=v���-r�s�����W��!y��Cn��O�l���}���0u��|Js�����,�)Y���3�h3���4����>�0{�w;�N��=W�\'��^��*�Z������:?6b�$���H��]���@x������`��R�\.������j_��JN'[�����d��&Y,��H�Mr:��I�dI9�'��O�����JO�M:����On<la�&����2������O{2d���x26�7���������G<���=�*�T|����K0�$x{2����q:�@��8����x����s�c��s��/������[
qh�Ue�6���)\�*���L����=������2��;���	D�d]<u�^�|r�s�}�������>;f^�|+�bP����?s�����d|
��yO��}�����i�w������
p��E��@�?��?�,���Z�/r��ScMyi���Y�<��3�L:����l
���@�Y��/��$K����.����h�<��.���
�N�;�`�/��g�`>�M^�������:�.Fz���������D(���>@cQ>�����q�����t��E:�m@�V�B����9����Z�I���/��<s,P�>��^\�vb=E9;B��#�	�UH�B����i2����x"�&x��
���86��7#-M���4�;� P����7 ��9��	����������@�W�����+���T��@���~�E�%��}@(�h17�4s<)O�+M�?�q>���}��`>U�wR�t�z�n�z+}�r���o�>�mTs�1��Ex���x�"C&�������)���w^�O�7�[�
�|�Q����;�L������XwV��	�3m&~��60J���c]��|��g�����������bqr����E�0px<���P ��7�o7�(��W���MC> B��Z2�C�!c��a
�w�9����2`'p?�|"���Y1����l	��SC�g�^<������*����=��S�����C�[P��z	����/�����h�g��c|}�f�d}E��y�B7�E�w�����h�t
U���<Ba�7�r��\��NW��������
�]@{�]��/
~�Jw���_������;�Ob���|���	mv8Z'�@���i��
�k�N���g������$���9�
�����@�)�n7�dM�r�DgT�B�G	Q�/CN� �E��Z(m����4���-x��j����G��_�����sZ��92�V��4.�m���1�2��g��J���o�A�g�>@G0�U��E>��D��q�<WN�#���<��V.�R��@��������(t���B��R�o�����c��a��illo�����<��=��eB���W��4I}��Kh�:�}A
j1e`�_���K�/b��{��
>����U����g/�E��y�:vc�S�F�ji�{O�}h���T)�A�J��7��b����(�/�UFQ�tZQ��6Q���A��[��	����}��2�����-�m@E���},c��������b�Mk����1�'�Cy�d���sb.�AOcNu����W�gi5�>�S���G`�s��y�5�ya������3l�!����Doi�t�6����5�D_��]@���z�[g�,}
�����K���3Ry�vX:�}�ZC�t �nP�}����o��g���6>�nS���%Z"GK���'�K���d���Obz�RRQ�o� �;��D�m����������S��U�i����r���� +��AT��7�DA�@�Cs�0���]P?Zr�WH_��i�����5�%��L�F�H��H���+���i�d�F�9��&���r
�/�I��P�(��{�;��~Z�v�L�������S����^�����}�
��r������A������^G���?�v�<�% ��7�kc�q�3����T*����s�����s-�$1������\�'�����m 7J##[���o��>A��[�]P�C���W�%�V��g���������E���F��2�s��LE9��O��B��^���e(��M(�:7E�3��O�(���7W7UE����G�ex�����#_�����)q�����wP_T#��.d�'~��:�y{���Vv�7��'mm�M���������o�V>h�C|�l����8�#��ts?��2���n���G1j�Q����!�k��],�!t����+A�|�'A���=v���������^�k#�GhK+��b��h����������*�_E��~�����x11����y������q�X�v�"��
1�s����*�s�����G������b���;�����q����[�c]��b������"�N���J��l�x��'�a���<�<t��2a>&G���B�d��K#n\__�����>�������V6������3����g���~Er��{,f�{��U?����7������y����\���k��^1�q�����2���=�#H���g	r�l�p���*��"�G��I 1M�.b���a,���������� _^�S���K�i�5yu��0+����q��Q�B�}�g�%��p<K|�U����c�^����|.0���Q�����������
�r�b������s���r��d�e�������?�c�3�N�����t��8B�)��_a�����8�+��Ga����M)�
�#@���aOR ����>��������3��Yj�� �w3���!����VgT	�����+���-��%�?�s���B�������=�M_�'��_~(��tk[���(�#�s���K����
Z�(4�-b��m�rA����8~��/�������y��������__u[���0�_�sN[�<�W�1�-P>��8��G�����c������/�G~	�mc���HI@%�.�~�}�?��hs��+"|�O����r?(|�������|��I��N�v3�<`r�����?R���������c#c����� �.Dz������0�����}4o@���XD}�l����|7 ����P��E���g)������� <��O�O�����T��S������B������V5t�T/���u�ie��i�|}�>��P@,2����4({���W0����=Ck��y�#�E�����C�}�vW�'�A�J2�3�~��	WX.��O��	��/Uh�41I�R�o�~\Si�2��wS�����!�������fuKG��L��sRq�=qjz���P��F����@��y.�w�3�R�sl4!�u�/�5�qHl�+
�m�<T����a�g�a?���W�����h~�Q���>�>���}���y��[�Fj]�c��E<o��/RHq�7N���K}�S�8+0��#�OC>���<C�# �g�m������0|��7>Pa?[��?�76�X���	�7oKcc2�'>0�7X��]4X�	z53�`�>e&������>��aJ�<n�r�_��V�&�����X��X�%x4b2�;t����������t�Gv�,���#����w/#�����Fu������-��#���F�!Fe�����\Y �Z�juQ�
m���������k��XN�a�����.�R�r���g�z%;�&������T��c~��fGiD��X!�mi�s�_:��?�6���Z��
-my��4��������������6~�U�K�@��wl1��s�Xl�Bc~y��q=g�}gg��c����������*j^nE?0�����E������
8�����@���6�N����Z��g��~�U�N�F�jE����������]��3�����x��>���
�1�C�dc�[��XJ3L�c�=���v��-�{��q����2�x�������<:�W�[���5�_{k�/�&|�=l��=g��o�*�+p��/��g���>�%9���KS����h�r�Dn�O�������_�}c���N1���GC?��+���W�}D4&�����F��c�o��B
�*2��t/���"N����1o lV,��MrP��8�Q�2>V�*&����e-���bCW�A���`x�c�.
��1G�	� ��B��.@���#OE}U�c����h�����t�e���'��93�����U��g�B��k�J5���B����p�]�8{�O]1����si�Qv�Q?H���-"����c�_|�-��@�~���E_�E�[�w����Sq6�g�|E�E�����A�����q��>�{��h)LK����pZ*�=<|�6vZ'�D�>����6����>��{9p+:�q���S���<Q���� e�j����:����/�G����>���"'�����(���I�������.��R>?M�0��t��?G�����a�O@��RW}�\"��O�&m�+�_>��V�a��&
�zX���+�������4
>��b���� #_�W�S��"�;����3��G�wu�P�3�M��Q���3m(�����%����J����p�y���xn�'o#�g����:<�*d{tc�TP��L�q�'���7��L9"��E]�}�
���t��o�~F?���)��5^@����W^���T��J��z�je����������9�+��1Lr���s��wk����\�������}Q���<��k�<N?!�i�;�L�:�v!/l�����	�����N501�j�>�E�~����Y�������l�V)�2
2���S	���� ���J�#�|`.��|���8
� � �� ��o,�j��l��2�
��
9�"0�}�k����$��m�-���l�o����2����,����z@�b��U��S�@}�[�����D��������Oh���3w����W����O=�@�#f�������$2R���5�������aL_��V$��V�������?(���S��1So�}�i������\�x�t��x�~�B���9H#p�������7�g�����{k�/->�D�����:N[LC��.��]�
z������w����(D�q�����x�C�/�-����\`��n��!w.���~�Bk�V����Z`w�_%��6��:-iE)YQ8?#J�'rA��D��B���w��(�����hG;���v���hG;���v���hG;���v���hG;���v���hG;��_����G_S�%�89�����|(�$����c��
��K�CM|G�#����5���1!������vz8�d���p`< ����7���w�7H����W:dhw#���(5�����������"���{�h��[4����|+�x���q-����omL���fv���mL��n?��E�{q����
YP�<\��S�K���7W����x�Zn\���=V�����2���"�Zn\�����h�N��>����,�L����Q�^*d!/���������&f
���v�
�v�}�{A����A������[�H�U#��D.%'�BM��}�5��k����w��7�>t@������y���>#K��;w{���jv{��m2�����M��R��yOx��}����������h����&o��V[
�����{�ww���{��r�Qu�$d�N�Mc�zk}M��a>����x���JTV41��7������qkwq���n�y�.^���hw��c��QoGt�m�R��hN4�lz[��C��]��\��_��W��K��S��U�T�m
j�r�M����lr�l���d2�&��Mdr�_�
��:Qeq��������z��"M�.�p�T��G`�����z�/���@��VX8���/��V7i��pI�:����vc7��4��61����yD���o����z���!�~���:J[T�.O��TZU�3�����ip��'��#���*�6j��4dG#�Id7��;3|k�����u��"�g�U�o�W��=�������v�T��%������j,��b��h�� hgz��E;*7�f��Y�]�h���K�Q�hH���.�=$��v��(�h��z�U�]�����mD�.3�x�h��M�U�F/�F���M:��tii���Ibg�x�m}�6�����3e@0X9C����]&P7p\��9��3�=��o[�zY|=X����T^�6���VQ��u_�{y����u�cU��w�/� ���&��r�����?���r�8	}����C��-���~�������[�K�*����:�u��Y��M��ha��BIji�Rf6���/d���C���P�Qk.�o\�A���`1
endstream
endobj
43
0
obj
<<
/Type
/Font
/Subtype
/CIDFontType2
/BaseFont
/MUFUZY+Arial-ItalicMT
/CIDSystemInfo
<<
/Registry
(Adobe)
/Ordering
(UCS)
/Supplement
0
>>
/FontDescriptor
45
0
R
/CIDToGIDMap
/Identity
/DW
556
/W
[
0
[
750
0
0
277
]
4
35
0
36
[
666
]
37
39
0
40
[
666
0
777
]
43
52
0
53
[
722
]
54
56
0
57
[
666
]
58
65
0
66
[
556
0
556
556
500
556
556
277
556
556
222
0
500
0
833
]
81
83
556
84
[
0
333
500
277
556
0
722
]
]
>>
endobj
45
0
obj
<<
/Type
/FontDescriptor
/FontName
/MUFUZY+Arial-ItalicMT
/Flags
68
/FontBBox
[
-517
-324
1358
997
]
/Ascent
728
/Descent
-207
/ItalicAngle
-12.0
/CapHeight
715
/StemV
80
/FontFile2
46
0
R
>>
endobj
48
0
obj
<<
/Filter
/FlateDecode
/Length
53
0
R
>>
stream
x�}R�N�0��)z\ZpMH����?}hl"�)���������M
��33e������'�a�5������c��[��c2����+����h��i��r����'/�������[�b�S0�����P��>z����7��D�l�	�������m�|+^<�XR3z40�FCh\�q)^���8���j;
���)O�~o���<B��"���?�R�LJR���@���P�V�2��g��O��@YvC�V�Z�R�'��(�.
�`�H��N	${n�_4���u����cq,xp�$���m��_]�?�D�
endstream
endobj
50
0
obj
<<
/Filter
/FlateDecode
/Length
54
0
R
>>
stream
x���|UE�?���s�����K���!��h.U�4)$�HUQQ@����kC�(6�%@����.�Zvw��`]���UH��y��Bl������������3sf�����	+,	����_������!e��Y�g�~M�jLG\1��k&MV��p���s��	�����0d��2���l�����)3��W~z�P���^>��	����,��������;�z+�g��8+��A�1������"���	���H}�������/�9��+l���Ix�M�ga7���c�M�������]�w��%����k����H��a=��z��u/�`Y8�%,�%���j	8!z�������+a,|$�]��f�E����Sw�6�c�S�s�����w���S�Clq<���� ��,���X-��,59�#� ��1�0��=<�o���0[ ���<��K��Z�PS`5�b��|�e���A�c>��������2��xjC�8D�=�����7���qqS��	g�T����Gx���ir�JLI������a$��	l��'�J�������y��f^��Y��!lo�g�5��`������|��o��%�v���G���SJF���W$�����/����F�6���������w�S�_���/�p<
�d^��
c�)l[��d��� ����#�t��4E�-�A�������M���[�/�F7�m�K�?S%��0�a1��X�_��;��|�L��\�gYl$�o`��G���)V��d��/�w�{v��*<�g�l���s���w�!~�����-%�r�R��f���I��w�����)�������'MO�^4W�-`y����E�6A���{��4��>��ag!�8�	�;
��^��M�&s��EY;�]�33�Mc��|����j������8Kc����<]��#/�=����O���*~��o�%�d��R@*���j���<��^�Nz]�@�D:)����l�cr��/'���q����s�s�X�k���M��,U��2w1�gjf�1�a�n~�2��O�
v@�vXZ,������T��7�H���V��R��l9����\�|�~��|��}|-?�����l8L����)~y#F������<~���������U��Gi�^�:�	�5xW�������lc!v�?!
E*��|�i4dI�����z����NYV"fQ.�`%�_R
$>����)�������r������v(e�sx����
�H	�W�Ty��z��S�u,�I&?��j�������6�PzG��^$7]�� \Kavj1\c-��M���<�0J�R����B�*cQ�mG���r��4K�H9 ]�D	��G9!#ME���P���
0��b(u���.�1�����d�"ut@y�,���$�;�I���:���9�L}�S�T������{�^_��<������9�������*�2u��%�p)�#���`��=P�4�oN��f��~�RO�b�SR��x3�`�9�k\����{L���I���<���������-�^#G�HV�wn�9�+�u-/+-����c����v��y�9�Y�XfFzZ4~����]N��f���,q������_'�������9�`B���uq,�{v���xQ-~v�$����fR��l���x%Tvh�����;'������z�T����� �^%�NLgea�x�����:6>����USV��_��n���k��C{�l�c����P���,t	��}3�U����.���FP'���P[7t��>�����;��c�.���rz���
���)������T��5����+T�t|�Q�S;a��:iB5��I`���B�	������F/k�4MZ�'<5N�+����
��i����l����_��^��8px{�K�G��%�e����J���9}�d��x�5�g������DW����dm�F�;S�!�'�b���������	��7�a���l�$����th�Y�h����g����g"%�Sj���3�hD9�� ����q$�s���Q0����V��j���jqE��Y{�_�v�rj_g�Ss�+����c�8�d�^����%�N�I
���D����H����x���whU�����1����8�����ge�����K1S�h�h-�K��@�8Q]����=���Hz��x��||Rr=�����7��V��>S�����<��=8<g��1��}V���v���r��n���T���h)��)�&��H�c�+Sf��N���A��
fR�(a��u��~ZXm���75��S+�i���{���9g���c��FU9p��+lg=CR�:��GH�0btV�W�D����R{�����8e����V�g����������C��(�V�����b��	
�E�����;�������7�!������+�q�����zn�a��mN��������^a���[8���������F��$E)�R*�L�20��Gn�Q?mg`�x*������(�e.k�Z�j�q,����(��1�F�nI=�%�; 5r&l��n��dy�0`�tO��=��&8qyU�:�����&�B�h1���U�UQ>�MKk����p�G�iw$�9�}��+*j_��K�HDbi�p^!����#_�%���<_
	Ig�zk�3�
��w�+�q��+�.N�'k��8�����5S+��*��i��VT�uL\����)�������]f"���1�!S���rrwBr �<6L�,�*�(���,�t�A�\�cA���H�?�H,f5��.�%�����|������.�e�+e��]����v,]��U����7B�����������2|��
�T���<��K�w����4�����[}���*���n_�=x������y�'�k���\����,>K��� �Y��iV���n'�Gj���x����`6~DyV�o��mC3m2`�p�'A^2�+��+��l!��:|�N^�X�Z���J�K�����4#S���P!���N����9����{�TR_$=�7�)oV)L�R;��Z�?�:�=G�+��U
7s"��-�)���Ng�����n>�����)8���*�b\��������6+?}�	|�Bo�����o��]�W�T��A!�5���;��xDMG���m�#�� ��p�'��2�������d5��������H������������/�]��v
�Z��~�{�r��^�����m�m�{�h�pi�4������
�J�i�Bs�����NVV����Q
1E�T��*���q���
=s�b2�M�@�D��QVe�|+�;~tM�����-��$������F?Q]m�J���z�!�����'
�}*q�G���6+#�����-�zN{s�[������z��j��Lf�>3nkS�����?={��p�}�����o�.%��I�R�
�M��i#�M|!���}����S6]^���X�gdf��%��98{�&��F���PC�p��"!5��Jzy��r	��5OF�x
�u���L�.��������"�]��-�gk�(~0S9����B�SA�	5�����(���K����T}�7G��I�<����~���p���'2�,d��N0#g�X�0����W(!JS!il|�q���:�>�2�I4����7I��b*�o�$

Q��Lz����'�����\��m�P<�z8��P"�����PL$���po	�o����r�a���p���I���Gf�����_�}'Z�GR����FI�Qo��d�sL�(��v+��_���n���v�pMw����^������h�h���c�}�����j���*L�Y<�����L�jQ�W������%=*1n��K�L��o�:��<
,���h�[w�F��j#F��67�&/1+{�/�8��[���V����|!�x.*�;6��!��TOh�V�X������K���2W�� �C��v�V3G���@V~W��.��r�sA]G)f�O6���Cy��������!������y��/>26��g{T^����G'M�����|�����oX>�3q���gri/���Ka!�t
�����	'i�����7��v96��L��] 3]�l�nj��q:���J�7��wb��b�����UU�1�.��}�>o��7QB��/49��>��N���"�Ui�����i�����k�K�+���=����� :������e��dk=���d��19��o�����(M8L��Xb����fY��;.>3��ab��"�Q�lT57W5��b;�A����KO��V��:�X�-�7�.�
'��,�W�o`w����!�O$j��r���c� �VP� u�pa��I���u�Eq���AD f
M�Q��{�/���������
K�M]�������_�>���UM_��B��~`Y��������_v��7���<yK���:f���=M�F�B%�j��r��v�G���34?NE�����8�I�sE�VM���lO�f��,��&�"B�ZE���h��j�S�W�����%/�78�l��%3���UI�K�,9�;��Yz�?���%m �X^��
|���������a��
��F���5�4'�s����������������q.qjLm0qd;���\
l�X��&�q���R�LjC=Qy��SQ�t{XFy�v�q�qC����x+P�����VH�*$9#��^Q���u�~G�^�X4�����pd�c��B���f���$p�P�J=����a������w��W�T��=&m?=����(��i�Nr���,����N'}>��^���F��Rg�H2D)���"���A#�H�D)�0�"���zS%��gK���p��4�,�e������nY�Lw������q)Bb�r!�C\�,���	�v^��"�&cE���'|r��x/�b��]EQ���������F��^��U�����]n'�����t�sq���0}P;�2{�D��������T�w���B%,�J�AX
��!T�����Y9��=�y������p��-\�/5� ����%��e��	�$��]����lZ�2��@���~3��F�!���7�?�����O���i�1��;�0���N���-RW�����[�T�=�t����y��-�I�B�
���".�D����O����e1�4�Q��?�K��-$Y*6mK�8��bnc��q3�N�t��f���;m��Tj%�'jfH%�
	���������~�%��j��{k��:L����d�w�w|�wD|�Tk��L����Y�L_bY���������-�d�B���RY����s�Y��C���8�4�&��
���13R8�-���<����)+o�*(Ke����<��l_uU{�l���L���B0g
���*��U�q����!9$�!1�� �
i����5�����XK�;�)5��p�t:s�a-��9�9�@l/3i2/Y:9��Q��^c�d(��n���#/�=��\�x���?n:��-_<�Ac�!��������(wM�4��y������u���@��=���/���fcu���7m����-hz�0+���d2��-��	�N��V�s�$q��!���x�m�k�� 1��RF3�B�E\:3VO���t��`�$�T��+<���G�y$������:A������.�����}����+�i�6�jx�Y�{�!��G�� �� :I}wB��U�
1l����f�|�;v^�f������gNJo�GE���x�{)U,��PkN��-$yzs>*���.���X<����H��H��-|d����L�T��uf�E!'��A�M2�x�ml4(!��=$M.��f��r�o�����|�����f�1���
���E�
���Oe�8���B��Z��	�/=�}Fg�+�`��J�� k�������N&k'v=\���,��sW:�
�
+�Jy�e��f�R�m��=�|�l[��Q���b�:��I�D���c]G�b�
1�i��L#B�f��me�]|2$�J	�R�Y�$���q�5nn���
��d�$,LX��0��u���d W<�s����c#$<�����n
M84N4��f��[Q#&�,*]��V3g6���Y�Hw���@�x,��[����M�u�g��|5}����N��N��;/]:}��[&M^�������|���OHi��������M��]����Oc{�x���r�M�.[v����UC_t��'
qv&��u;����C�k���"��8]L\V3+Ua�S>�R��"����0����;����3����+�/Z8v�ch��y�49)�;�iZ�8�,${�{�s���O�3���k�Kr��0�1��t�e$#�(����x{5%BK���C�'nTI�~�R�#�� �X|�"a�yS�B�g������%��G/&s.^�3I�<8#:9�����+��f�>}>�U�����������A�{�Z��������+���!�qd�S��������A���3�<�]���c;M3=�����=g�������	 �!O�Q�ES��f>�$=��*q���yH��f#���P3��T��$l�
���e��1d�G���`��>����	����uyn�������c�]�_�<�.��y��<����l�z�,��,Gx�tf��GL]��i�wM�7m��n����{Z���d@�9]>
�+2����E���v���
g�@���E��j�5E��S��wZ�\�nu���S�@�F����Bs?�X�=�\������>(��2���:��^/�&!��In�T,'��U��������T'&Y�&�r,�����e.&���e��,x\���x��bW���ZW�eZ����I�7�v�r%RvM��r�������R��\���.��HYZ_��p{!U������y����V�.��MP'�AH@�$���\����h^VnC��oJ���L��K�Tf���V(�~�N������z�4��_�t$�+����)�T�X�r���w�6�<Q�w�� ��bO_W�*�Y��N�	�@(/�],h�XPw����������*�+~!����@@��"T��OP���P��4���OJ�n��\����e��p�;a<�l���QG�*�#����l��4��6P#m�`v���.]�/r���:���& ��r��tq�m��TY�s�������|���Yi�����_q������P����K��[2c��G�3n���%������<�����}�����?���n���t�pPq��9�j��M}!Cn����	!����w#&�*B�UzD����\��mgI
��0���vs8]�3W�l��6�50�L'H�	���>!�q�TB �{���b��|�B�}�C�}�C����
�����������4���Y�E�����m���c��S.����g��%7#���4��8�U��q���m�3cL��r�%��X+�e���&NN��Mr�`�\{"�jq�t%z�dI";��Z��`I"2�$f���X�����r�Y�\e�f53���YH�v�&j�;���5�X:��!��9�����t���sN�D�c����Wk��D�(�g�i;�2q�2����R���o�n�?�|y����6E�Y�q���ngKB;�f{������M��Oo����(��"-}d��`��l\v�9�����ry�E|��B������4�z�|���[�C�"G}G������8K���X"Z��������;�\g�`w^���8����_d���<�|���p�, ����pi=`���;��YJ�����y�Q�l"(D���=LE�9���#��D�1��xIDz��%)�Q��=a���`�u��h=�>f����H��4���25���o�Yp���n��G��Y&�b�����<3gj|%hF(sT�L$�l��vB)�D���Bq��T���<����O�vQ�"fg���B��Q����Z���&�]x��io�4������g����'���~����]���zp��}���W_����{IoD����&���&�Az�c5��H�Di�i�u�� e�O������H��;��'�rgo�H���A����c#�O���NH�����'�*��


��
J�t�*u��UUNK��a�H\"4�0D�R�����P,���Y��B]��N�{���4�NR�4�Nz��������Q���l��/�x���I���u�&LU����5���-*3�Z�zM�[�{�XwMV��nZ��-�����h��`����T6������W�8�RX�^���4�C,�h���o��%�3�t��������[��s��_��,�le��|����[<�F��g1&1+l���5�i�v��^S'��CrXdzB�]2�oe�Hq�S$�y����)�%�,t�E�D�Mk2+��8%�;��<������~�O����rH$Bb2C�t�A�w1��=[;w+���X�*`�$qo$�D��8..G�����^?*��6VTC\#��3��L�0���������ld�If�p"q�%����D�Z)��X�X
y�*��`��&������X��Q��4�(�4�`����Y�qN�'�����+9�PN��������MW]06�[����V��=���E��m}�_���$��e�������8�P�8B�P�\.��v9eQE�B����L��O7��v�����+$�h�y�di����������$M��P�~�P+����6�5J����&0�~�W+�G�����'��� �]��.eu��A>+�.XL� ��������O�8��t�/��i���?&Cb��`����5�1k���rq=`p�����*w�fV��x"�r��+$S=���j+�R\�<��HcN�-�M�����(]��;O�G�W%�YV���~?����Co�4�j����
5����]7����C���	��0�D2�m��E���"dd����i�FK�$�2(���*"4�7FP�qD�%�q��h@EO�4D���,B���e	��=w�=]h��XWY�Y��{�Y�[�`�YgYY��E��)�-fE��,s��H��D�70PL�lS�y&�����:y�|XV���er\>�9Y&�����_�/��Y��l�8&�����)��-��`N�8���N4_l#9:g��l��msyi@��^^__/}������]��7a��V�
J:[��Y���^[��Y+��|[��Yk�9wLb�����������e�Z���g�iwa�PT�M1�Z�G&y�MR�4����2��[6.i�Fol@)����yK�����h�{b�u�j���6��H	�
�K��������f�
�B����8q�M��]?�M*�h���Ov�O�fj��Z�c$2��K7iF"j$2���^�iF"j$�Y���H����H��Sa	���	�!�U#�5#�4�r#�����AvgY�|D>b�8t4n:d:�!K<�N�[%)'3]	��B�������ylU��<�
E]y�<�#�7,_�%��_8��9Lqa;�	,����aV��[Zx����V��4�AZsi��4��y��4!���^	K�4������WD�P�4G�>G���&r��A`�1�1��!(?�-U�B���}DA�A]/�6t���_(�$��Hn^��5��31�DK���,1�E�v��L�qp���?���54P��2qU��P�/����1�3`��b�%aC'��NHH���v�CK=����iW����5���=o���G�^������q����i{c��q����x�2���w6��[�!'����$)>����~*}�;.��)2������Q������p*,�-~�?�E��)A���r��u'|_1�!�aaI��Ua��]��f{�.��=[������{�?h�a�9T�bsm&�����a[����Y�u������xi (�&(h((�'(���z�G�f?oR�Z��&��K�=IokepHxd�4#��03�z��\�hT��Qu���T<V��f�I�����4��yu�)ZLw>�(a���T���+?�~�j�/��o�r�}���Tr}�\���=�z��y�����\��"l����0��N��9������^�-�8_�g�T[&+S-�2���{�<�G��kk�P���/�0����3�3����Y����K#L#l;.�&�&�.w�B������oP��������	�07M����������N]�E�^Ol�(��kwfm(�E��+�df`V�q����U��#�VTcm�0���rhZA���p���+�p�A��������� N�!���`� 6���^qr�������������L���M�M_����!�p�p���K�2��w�}�p�����]�7���{,x���~�tl��eK�l]�l�����j��q��7�L�|������k��`�5M���*����M�s��s���\���X��#'�$P��3cV|U��=�=m@h@Z��b�����i���������=�7��?���y�$�p<��	5(���}�������&��q��>��U0�eW� ��A"��b$������m�m�M���'�[^�%�D���'m�_��5���mD���H�y�W�Ku'����\9y{[���:v��1V���NX�$ ��0Lh&��	?#�"��TUlA�8x@�O��H���a�r��)�D��#j��Rm�q�I.�>��}�>�����#�X�e��5e��iW~t��;:z�j��O����i��+�
[�����S�^�����a���������Z�"a��>L*�1Uf9r��K.O�����c�Z�N������b��f-\ea�����x�Y��������k�$������`������SWY������?��;����s'�������+�\���	��jm�m��(/�<r����/9�g�s.�g���g���D��U��4��c�J}!m���$�����aa�[MZ"��%-�k$r�D���2tM*�P���������sGeO�^`��zs������(9��h8�i`��C�4>�s����c-c�cmc�cc��,���l��������������v]r���������r��.������������i��)��
����,4,�l#�c$r������	��Q���
��&��c,y���d{��(y��#��#6R�9Q��Xdf�������? ���/���*K2����S'��V�L��T�����c3.������p�=�g�>�����HN�h�EY47����J�y��!����:"��%���8���s�����S\�]�b0���.6��E��m��X�I���?�)�n�(��JLa���[��bYEe�K�����E%������LXA�qm��v���%�%Fc�*����r�����

�,��z�����J��E_w�G��j���{kf:�B���N�3�8DK$f�����{�N&t��8B�}J0i�h��3���9&�|��U}��d;�i`-4�1S2���r��Av��aigKc�V���� �f�����@�a*%/^��b	:������K��yyY����l>#	������������������������~��x�s�.������QS�]�vn��9{���+��x��������p��]s�3|�����Y{�3$[sS��"�b1�q�d�h2�E6�I��b$lD�9�eV����Xa�N� �Zn�L��V�!�9�Rc6M�9X�l�c�3�<�����,?��u�=��f�L����Y��\��*�4�^O��f&kf�ZL)�u���]|�Y���Z��Q��=mGNT����JRj��R����U�B�y�I=]�
gq]���*/����7o����(�\�V=o�#����|y�m+��>J�������a7��(9��2����/�������Z|A����<8P4�/A��6�_�y�m4�b�����(�|��+��s	��K�����\�4e��b��QZ���D�G����h]4������b)�A��H��������V�j(Rk�"�}�6�������]�U8B��#g9`to�O�'�R������/;"3Ge��t;�b�(��(�#
�O���h1�*�R?}*��,� �+v��T���%�Q��v����~N�C��f)���j�z[���
�c9�8�.������+�rF����.Zh�.Vr�k.6��O�nfWdnU�����-D������*	��n/sgG*RTC#c����Zp�v�1�Q��_s[��`ET�Y��Z�������b�Er���>�u��v�}op�����u�]���/����6�W��.��w��� ns�(�V�;�f�
m�*�>Ihn���$E����)��$K��n�h's�����;��C�)n����`���y`�X%���d�<��w8$��*I\A��p�m��y�;opd���
I[K��T�*�Ii�����t������`��wO�HcMc4|L=��8�Y
�?����r��c�f��{�u'j���n�2��e.u�bdv�����j�O!�]��
;��=��������U��?�T���
k2����j���[���R)c�(��t��������M|�h���y[��t'���w�7}�Y��w�Yz����P�TCR8�i��
RR�OG����|��"t��3�D�X�
W�Z
m[(B��������%1f��n�.�G�^����^w��t�u��'�D����"a�
�����NW>L�H�(��ro�IIgW>^��L����z�����^�(pvqtq�������~�jo��:0�;�75p�r�����kK�+<+�+}����=i^}������s���F�*=� �����&�{�ovK�H��5��[Q�lW���z�^H������1�v�=�<�

7��._�z����8}w:Oo�U��8I��Wy�^>�����
��v7��>i6z$f+wtrqHC)w`���t��W�������k���R+&���G"�W���a��HA�T�A�$Y���O��v�	B�;��5|`]x���������/�A���<�����V���V����*<��
�L�vP�A�g~ �+�n�/+���J��_N�B�9�+��<�&{��?Hd���7]�#���QeM��Rs���3����\��*>���7��N�\�R�-�e{a;�V�~S���_�p/+����������,�����v��Z�V�
[������Q��|�e�u�z9��_�����<�u�[��-��	����v�������o�L\�C
����
+��SZ|����-6[�~����eQ�S��6�	����jr&\6�������<��4�A��=���v�s1p%]�]�\�]&�N��G�y`���M���LH�a�����yY$��qK���c������8�U�Z�T���qT�� Z@)���/�H_��#.��v,�B�m�,4��{q�"M��H�W#H��b�M��G_�H��Z�i�Z���CB;������8|Oi9Sr������4+P�7��4D�m|a�5���wI���/�����'���������g�8w���4���������������M��U�8����D��|^�`�����~�V����Y��E��`����K��@�7g���Q0�-�1�7[@�2 )?s��F���x���#!*�Q�lbb8���Nj���E��\c��L��T#�w��e��X��G�O�I�f`~��-t�:��^e#�������l
��1��c�]'=m5��
������o��t���>�o��w@,�>�b�1��0��X�^�����#�c�	�_F���z����Wa�\����(�C����B�g	�����"��/����o���c�)�1l	���^�:�����Z��V�/��"��#���~�!_���Q�Hy4O"��ka0��s��VS1H`n�Q~�I'�>�V�����3�$�@%"}���/F��w~!��F`�1.��
Z�X�}}k��
���^�}�&�������,B\N����i�i����
�{��%`yH��h��P{|W�N������s��a�eD��`@��|��A(�DG�Q�#�������B��_I�+�����
��8�86A��7�����z�]�O��L��E�$~!���l6�M<E4c���������h�9F�����i�������L�p/	�1^�t|�,���i^���� O�qe�o�$xc	 G��������x
l�w�W.E�������t'\*��R;�h��e�=X��
Z�@)���?�*��`>�����w>��y�9�-���!f2=���������I�l���bB�g�i���m��(3�N}e:�J���E<a��uB���� !�,	v�e:k0�U8��)'��)	]�=�>���X>��1��n�[�C�w�"X��Rs&�{Q�a_�m��@��xV::��Z����:&���Tc��
Gt�D|�t4i2B�����(�K5zM��L���c�j�g+:���>���u,t�w�Oq��O��d�H�s$g�����W��H�$������u�1~��>�a\��R)�o�	�>���M=��`��S�	����:ut�I���]�������R����
B�|�zt��U�M�p�Q����y��=]�s�V�wD�e��X�Ks"� Lz�t�t�3����&�=��m)x�����p���2��S��"xD�J��(k�@-�}����r%8-������	�
��s��']P��hR�\�/3��`�C�[/�$����1�=�"D�4�N%
{�kXk	!�7/��h���������H��
}}\���e�r�9 �L���4~�|��i���6-�9�.������e�?�F�'Q�A9L��=�BN@e:��e��PNb��b������wo��1]n�}�S�*�e�F ~1'��,v�1����K_�zi,G:�a��a	t@�&�1�Y����c�Q�j1��T���y)�{��H����Ty�H��w=�A�������q�����+)/��P����G����P*����0F�����
y��6#��6y�5�3��t�������`��i��RL��z���>�S�~�A�k1V����W
�5��R����X��i��g�'�������� �[C��yZ�4��O#��w��4�aO�v���m�~-�r9[��(���bL�����MZm�rx����[i_@�=��X�q?�5�YKP??W��������P� ���.B��8�]��.���]��e!��W�_*��Ll�*oJC~�����[c�5�O���l���z`�7�~�8N����c���w!�F��7�h\�����bo�*]�4��|����4�	�����ih�[����^�����0�%:h����<�\�����W�<��>{��y����(�V���~�W�@���X��y��?�2AuE{'�O �%�z��!���CB�y�B�*����c�K����%�7�?��W`<�F��g[�m�2C��\�V�������' ���x����� �"T��>�!UhGB��b�q����t1�q�C#0����nj�pb��e�1~��������4����t�2�e����}�������	�&�����i��/��S`���c�������=o����c�k�_���U0n��!���^�#?�����?���wc�Y.�q�������{�;6��7��{
c�+n�3hk��{�O���k����=��z6��<2��6���h�e�~������c�_���L�+��d�b�^�Lb<#i�/���������5������� ��7����7�@��1JC��.7���(w��x?�30���i�l����
�����Ou��@����
�Tn��������?�o����.��RO���
=o�z����.Bk��'v�o����O�����8��.1������i��g�mF+��OA{y���Ck>n�7=�s��%P�:��h��2��Rwa�
��PbyJ0�
�z��������6�o�1#�Uy��;ZG�o�sk�%�\��8gB���C1���1�Xk�Cb��p����������@��3.���g1���e�_���N�������
���3>�T�r��3@���A?��W������+|zM�6;�9�M�Cc����
���/I5�����w�/B}h%����gB�e��~����[�!�
_2��H_)A~��~�O��<z#�d��j$�_����f������~�Ug�k�/�K-��,�M�J�MX���vxHI�����^%��3�?�eF�}��7��	������i�����u�w���1��A�Q��W�N���3����������u~k?�X&���>�'�8�o�%�R�>���b�����K��a�`�"����{��kq�W���b��������nZ��NY;��)���"����(���7������� �^���4(�-��n��uS��v�k�f�pD�k��HgG`����#a��������N������[?��+a��i�9���o](�@��#��|��v=s��vn���7�o�#>�H��>R��y�5'�^����r��h��AY��k7��
7I�@��
.�<PK`}So��1FK�����w0�S�+�c�L�8W���pJ�U��Y.a"�odY�9a�����XV��wl��[��>A�����{B-o�>��X�IE�kls��B��������F������S��zy�5�������=f�T����K�����������������������K���X��+��X>��8P>�>�i�M��������0F�k��i�_�&������C��7�����:P��h�� p_�vM�`����0�I��(B�����M�i}�}6m��7>���[������D�${wa��X��r��:m�Mw�����}�hWw)	q!��a<���iH�	��#�/��>.Jg��A����uF.���j��PW���X�.2��Y�j������B��P�UB��D;�a�Iv�p�DQ�VS-�&@�d�8��.��DLGa�|����]|>�[�C����In��!����R�	���|Xf����u���8�`7����F����#�W�^_�M�����[9�c=�P_��qPa��{[eXM���r?\fn��!.��eh���yfSW����{3���q��"�q:��@���v��{k�qo�T�sR+�3X�9=2����-���Ph���U��aX����P�NM�s�I��w��'�d�lZ���]9��<lFL�q�?m���a/z����h��w�y�"XIw%Z�5��lS�>�f���=��l�~=naoh>�=h� A�x�'�:��$��� -���y70K?���0�4������|�}f6�n�h�h��|\�^:�_� ^:_��yX�7�3?Q��M,k\��OC,@L�����B-����~�l�V��0Egp����#
boi��w���$>svO���7���F<Lw�~���u|7�S�<�y!���m����[��v?�-�!�����Dkd���[�_���,�b�j|f�g�{1�K�8��^�o�-����S)=��w}w��-j�?s�@��������Z�bM@��X���s~���+h��u#���E��?5	�|�����_�r�CXb���o�y����:���Ab��F�w�F��~�~]o�a�a�����a��
p��l��X!]��@+�`�V��R)�1��<����~���1����?]���u����_{K�w�����)?;n\��� ��l���9���Wu�M@^��]%i"��Dq_���O��6����~�FQ��3�5>��?�����<Q�?s�6O���f{��p�wl'��/�:���dc$[P��w�_�Ig�|���~:��I����A_�Z�Q��(���lZ����Y�+:�i�_j�~R��7�S-�{�L����"��m�c�hh�\+?3.C�J���8q�4)��C�����
�k|���7I����Vt�f�~_�|b����2Tz����W�wrh������D{c_(�K�Q��1q���;=���Dv��;
���aXwX�/�����/�8�Q0���I�>��N�g#fb:��Q�xqt���N~��I����poo��t��@��~{;��M\����m4(P�^}�J=�}X��NIB�B
�i�/�v���;���xf����c:}m����C���e������JyxpM��r\�7���Q8[�5����`�����Y�j::��>x��0T�N���*(T��{���A��n�'w���0|���������0b�4����#�>����d�=�Yd����k��5������"����'i�ch�"���=�B�1���8�C5�l����lh��RLw���t[�����}m�+�U��t_K��X����_�;�,jq�t/����-������~�n�o���I�?<Si}w���r�f����o��!������nec��w �D��� C*%����v�dG���{�����D�O���+S^)|�K���eSO�7�:�������o��R),�"��]����7���-��$kI�
�Aw�q�����dJ�iM�C@�H�%{�{�X�y�.Sz�������Ar�^2���,	�}
$�P�j�*C�j����� �!�1p����~Z���>�SB7���I!��i��(���M<H�[��n[>�*~���.��<���i}��u�O������m�w�������J?|N6�;����u�5���Y�}����{z�o��V�x���i?G���z���8q�37uB'�O"H��6�������8G^��hu�;IB�?�b�� �������c�~��O�B���8�����������!�����Z�?����>��>�Z.���K�W�E0��������)��H��%���)�u���:8�3�A~5
~�lh�:��p�=�xm�#���H�!�8�"@��������A;\����W�9���j
��]OT�G�(9�s$�M��mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC�/���|��0���
��������&�;a�T�5?;���#��nK"#�S*�2��K6H9[��w�R�V,�8�3��2��2�\�p!bbb7� B����3k����!�o���R�Fp�n)�"R	b#� �!�@�E(���D,D�FO�Rh�]�8���[E�u��%";A�����Uk��aZ���V��V�s�V�����bo^�"�m��==�R?2���!�{���`��:��$)y������-��$.1��Xj���8=%=l<��/��7����������1����?��B~���*�Z�n���������C�!��P��B�C�E�F|�0�0T��D-"�t���1T�{�Y�a���b�]�.��-]+Jv�D�XO���D(MOx�%
��[~h���+����
�A���%�s�A
o��k��n�'b�zt�oA��H�����8b(b<bB����z!V!�!�He��8�:�m��H"�",��������3�#���/Cg|?���_��D�I��`����|������s�6*�*�����_�����zx�n�����*��8�����[jc^|�s�����R���#HN�%�{!�)��~.�0X_�����>�Y
�o�S���S�_�S�_~�(����)
�����CF`
��fGnA����,�����Y�g�j���A�W�/� ���RT�3�:�hW[���i�b�8�:M�u��)q�����j�$T���)^���h��! KT=����J'��*�R������Q�������S�������C{���iN�����J���?����gg���X�!�I��-]z�0�Y�Ph�	tp*(�5��]���:@S@�@����6])^{�M�
B���/��G����8�q\�q|&|���(
�2��<���]�=Y�}n����E���x��W�&�Au\FuR�!,�(WPvP�P(�Hw���D��%�r�S�=�f1�=�\����X�?�q���xv���f4�������
���1)M::!�mJ��O[�~�J��A���F�x#���Z�YTs��Zj[}�"�&\u0HR�D=@�>OT��~�J�P�����-TK�������=S��P]	�����/��5�g����~RW�z]-S.�����h�wzwj�2W�'����*e�1�`�i���"������`�
-��j�u������!^���*�&b"��i�3�m�(��o�}�9.krT��O*�JX9�W�)���4)�B��n��i�O6���_��4�zX���m	)�"��{9`I�T,��@�y��5�p����R"��"�t�
�+7&Y���<�A�
p�F+�>s�L]hp�J'k�P�$m+7;�~m��m�H��l$�>�6�N��b�/_�>5r�e���"�6j�>^iDm�}9������,�7�1Wvq30O
�������e�#�+����a��������$�G��+��A�\2\p��t���n����#���"��D&�L%������a#QUDb�@�4Q��i�\~������*2�9�zL��}��2��=�9�����P*���D��2�>��at^��6w�,���_X��j���r�-$�z5S:�]��L"_%��t�Z2��Z��W����D�P���\�G����y����4w��\i�+�s��c"k|�XUH��P����r��\g��u�?�7�,wn���]�b��x"�ZQ�����Q���w�@s�wE�3��-����hnK��QYr�H��a��8x����'�+
����y5�T�X�����f�UYF��$6�oki)���x�C���6�m�����/�ZlkK��u0cP!�`1kZ�G��^ki����R�����0�����o�)~��RY�k�\T|���.���|����`@���
=
endstream
endobj
47
0
obj
<<
/Type
/Font
/Subtype
/CIDFontType2
/BaseFont
/MUFUZY+ArialMT
/CIDSystemInfo
<<
/Registry
(Adobe)
/Ordering
(UCS)
/Supplement
0
>>
/FontDescriptor
49
0
R
/CIDToGIDMap
/Identity
/DW
556
/W
[
0
[
750
]
1
7
0
8
[
889
]
9
15
0
16
[
333
277
0
]
19
28
556
29
67
0
68
[
556
0
500
556
556
277
0
556
222
0
0
222
833
]
81
83
556
84
[
0
333
500
277
556
0
0
]
91
93
500
]
>>
endobj
49
0
obj
<<
/Type
/FontDescriptor
/FontName
/MUFUZY+ArialMT
/Flags
4
/FontBBox
[
-664
-324
2000
1005
]
/Ascent
728
/Descent
-210
/ItalicAngle
0
/CapHeight
716
/StemV
80
/FontFile2
50
0
R
>>
endobj
51
0
obj
318
endobj
52
0
obj
14395
endobj
53
0
obj
311
endobj
54
0
obj
21099
endobj
1
0
obj
<<
/Type
/Pages
/Kids
[
5
0
R
12
0
R
17
0
R
23
0
R
28
0
R
33
0
R
38
0
R
]
/Count
7
>>
endobj
xref
0 55
0000000002 65535 f 
0000177001 00000 n 
0000000000 00000 f 
0000000016 00000 n 
0000000142 00000 n 
0000000273 00000 n 
0000000438 00000 n 
0000137868 00000 n 
0000016266 00000 n 
0000016287 00000 n 
0000138980 00000 n 
0000139131 00000 n 
0000016306 00000 n 
0000016475 00000 n 
0000138024 00000 n 
0000033412 00000 n 
0000033434 00000 n 
0000033454 00000 n 
0000033623 00000 n 
0000138205 00000 n 
0000054598 00000 n 
0000054620 00000 n 
0000138167 00000 n 
0000054640 00000 n 
0000054809 00000 n 
0000138363 00000 n 
0000077327 00000 n 
0000077349 00000 n 
0000077369 00000 n 
0000077538 00000 n 
0000138521 00000 n 
0000097276 00000 n 
0000097298 00000 n 
0000097318 00000 n 
0000097487 00000 n 
0000138664 00000 n 
0000118295 00000 n 
0000118317 00000 n 
0000118337 00000 n 
0000118506 00000 n 
0000138822 00000 n 
0000137826 00000 n 
0000137848 00000 n 
0000154140 00000 n 
0000139275 00000 n 
0000154569 00000 n 
0000139669 00000 n 
0000176339 00000 n 
0000154777 00000 n 
0000176720 00000 n 
0000155164 00000 n 
0000176917 00000 n 
0000176937 00000 n 
0000176959 00000 n 
0000176979 00000 n 
trailer
<<
/Size
55
/Root
3
0
R
/Info
4
0
R
>>
startxref
177102
%%EOF
bitmapscan-refactoring-results.pdfapplication/pdf; name=bitmapscan-refactoring-results.pdfDownload
%PDF-1.4
% ����
3
0
obj
<<
/Type
/Catalog
/Names
<<
>>
/PageLabels
<<
/Nums
[
0
<<
/S
/D
/St
1
>>
]
>>
/Outlines
2
0
R
/Pages
1
0
R
>>
endobj
4
0
obj
<<
/Creator
(��Google Sheets)
/Title
(��bitmapscan streaming read API)
>>
endobj
5
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
6
0
R
/Resources
7
0
R
/Annots
9
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
6
0
obj
<<
/Filter
/FlateDecode
/Length
8
0
R
>>
stream
x���K�%;rZ��5���}�9�@2��|'sjX��,���mvkt�kC��a�����^��� 3W�����N����`D��~�v���M�a������������\��_������iZ���
�]����9���u��q���s�����o�f�������8���?2�ny��FD�����}�������_?�4>hz�����?��IQ���g�=doF�eL� "IOq����h��_�(L���H�S���*�2bUQQAqR�����wsZHI6_fR��$$�����iQn��F8,PnI8_p�n��������iqn��F8�PXI�Pv�n
�������iqn��F�(��$\(;i7�e��H�����8�}a#�@.�����2du$l`A{Z����8�]ZXY�Pv�n
+�c������8�}a#{(��$�/;k7�e��H�����8�}a#�(��c�[�����2du$l`A{Z�����#��y8*�<@�����H�����8�}a#��yZ�9S�n
�pjaA{Z����8��D
d�B�7���E]6��=-�m_�Gp��G~����2du$l`A{Z������H-��*k7�e8�#���=-�m_�Wp��G~����2du$l`A{Z����n�H-\��*k7�e��#���=-�m_��p��p���U���.
X����/l�8R�#���Ma�:6��=-�m_�p�NG~����2\��ZX����/l�����_e���8R������}��Gj ����/uQ�����8�}a#��Z��U�n
�pGjaA{Z����N�H-��*k7�e��H�����8�}a#\��Z8�U�n
�pGjaA{Z����p�.G~����2du$l`A{Z����qm�Gj ����/�S������8�}ai]����_e����8������8�}a#���Z8�U�n
�������iqn��F��#�p>������
������8�}a#���Z��U�n
�pGjaA{Z�������H
d�B�7\������(l`I{Z������H-���*k7�e8�#���=-�m_�gp��G~����2du$l`A{Z������H-���*k7�e��#���=-�m_�7p��G~����2du$l`A{Z����q�Gj ���_�_�M���%�iqn����
8R�#���Mae���iqn��F��#�p:�����!�#a�������0�#�p9�����aGjaA{Z�����u�H
d�B��U���.
X����/l�8R�#���Ma�H-,hO�s�6�	����_e���'p��������������vSX����
,hO�s�6��������vSX����iqn���6w��b/�>�g�_��n��{��K��D7����W�����
�-��a�JX\��R��R�q�a���p��)l���n��p�JusJMx����GNW(l��J���@��9�&�
Xj��#�+����Kmq�JusJq����a�/�b��bUI��(�T7����	kaq�����Z�8a-,.P@�nN�	�x�i��#�,����Kmq�JusJMx]���������Z0�dy�P��Sj�����x=r�BaK-x[��(�T7��t��G�m1��j��X�
]��$y�KP��Sj�#���}7S�R�W�p�JusJ����W��x�����Z�����������p@_�����f
[j����-.P@�nN�#;���|�}7�
cQI��(�T7�����;��n���<������$�r��r"/����6�-_�	�(�T�}�/3�����X�R���f��������/5��`�-^
�5-�m_j����-.P@�n�R��Jm1��j����E%�G6�D���K�xX���cMKu������v�P������
Km�Pp�i�n�R3����p�Ju�����a�-�
�5-�m_j�+:�.P@�n�R3�z,��k������K��U���
(�m_j�s?@�-f�R-������$y�KP������kaq_�(NKu������;\��R���f<������w�-5�}�(�T�}����wx>��BaK�xE_��
(�m_j���^}�P�R3f�,oq�Ju����������K�`
[j����-.Q@�n�R3�W�p���������z�P�����g��;<�n���f<�������/5���z��C�-���Y%�[\��R���&�v��-f�R-������$y�KP�������;��n���f<�������/5�	}���[(l�O��w�@���K�xA_�����
[j���.P@�n�R3��wx9��BaK�8�������/5�������K�������$y�KP�������;��n���f<�������/5�	}���[(l�O��w�@���K�xA_�����
[j���.P@�n�R3��W��r������1�dy�P������}��,_�S�R�$oq�Ju������z��C�-���G��;\��R���f<������w�-5�}�(�T�}����wx>��BaK�xE_��
(�m_j���^}�P�R3��W�p�Ju��:����W[,��Zl���"bU�-.R@�n�R3W������V
[j������@���K�xXj��#����������@���K�x����G�[)l��������/5��_��,_���a-V�����-.Q@�n�R3���X����w+�-5cV��(�T�}�O����Si�n�R3�,��
(�m_j�����x:��JaK��������/5�0a�-.]�����/5c�Nk�P������|������R���&<��Z;�Rt?�:�������S���m����Y����p�U�74�����L�M�,�`�>vO�J���R����������{���eZ���&=�ow��[�����5!�Q�l��a}���g��Z�+#U�K��CR��X@���LCZx����������{y����iL|c��P����$D��-J"Jh�zC�92�{��?>��5![Y=L����2d�xW��{��q}�-�C\B��,�u�������Q0���
&�H�?$!����k��y�1�Z����d�|H"2\�Q��z2Y���e:)�;�U����S��!3���P�b
�c:��Z�����(j`r��oF�����A�|�m�Q�@��mFylA������D}5��y�<e��wL�9�E����#���tql�:������H����[��M�\���E2.��m�sl4��mK;."�4s�����kK�m�~�H�o���&tI��1�62^����������7���[���62�b#��Vv��7[��|df2��$B�"�V+*_�%M��	A��
4�;������
W����
4�;exB����`��
|�����o��#(��N��jP6)�G�@�B��4
*Q���lT����9�����@����.���%������������stW~�P�G��KP��gB6r�6
C6	���������
D�C�N�<����&`��>UA6d�#3��f& a������[9�	fn����S�6�A�r_��9��eC�%�:��l��
�w�J�B�AT�s����%K^��'��tD��������������n��"
hO�J P'6	���my����N��
D�s��JH���3�@��3�����,J�
4]�Gh�53�}HP��6>UC�f���	
��;��.dk���/����������pW��E�)m��Yh.�;�z.6hvlS��������>Y{@{�������S�l�+��"�s�(l���c�d.2]s��7�����V�����5G�d_nv��_��M�I6�6�r���9�t��=��)�z��
<�Cl{���9���w�����D���������(l`��#yn���0e�2G6�7WW�c����1M�<�{h�`{�������69����doCr�(
nv����������H�r���P���=����ll2��>BGE���~K�Fb���6�<�1�{��('[�+T�:�B��9������#(\d��E�_� a�'�X)��2	h(�#�'S��v��&�����%��t���:6��
���-����
|���J�r�n#(��L���%+S�)�]�#t	X�Kx�n��-x�E�Gf�Pj]ge�����va�b�Q�����S��l=LI�%^
�6�p�0JV5���@]6�h?
=���
�2�r6�P�<���R��(l�����$�t
Ay�g��4^�C
�x)�(6�������+��[_4G"e�rSZ+�lv�����"aWT�=�0�Y;AQ�
L�����Q��4�e_R6�P�u+r�xmHP8����k�i�0&��s}�)
h����������t���2	X���;�H�v��.
h���\��AM�r6�t}953���s�\���`�
<]�k�Z���k[Q��R�P'�A�a|��&T6p0W�F��E���"�������k������P�EaS���LI��&��a�7�M�E��.Dy6��xlx�_Pua�����=W������a�&lp�a��	���q���v��?�2q,`Q�@s;�5s3���� �r6�y	��%� ���I���s[�j���=vU�
L�?B)�
=DP���>K��"l����\�o�������fZ��.��#
����.9(I�$@EH�@S����BIS�(��Q���4-��tAVG�>[!6��V�
���
,=��As����eU��,h��
��#?�A��-$a�'1����	u�YmI9H�@�
�Q�(\����)�I���\�����\�	Xz]d�V�yU^V�P�m�O���H�Z���c�Q��g-��W�����$a��Mr�zF�&H�����
A6�yN��\�$@�$l�!9�*��it��m�Q�@l��!4[
#.�y
	Xx����7G|�G�EaK��L�3l����O�N����.�
%[,lv*��;�D%g/�0a�s����Y�qt�!<8��f����'M�p4����&Ld���*L�����S.���vV�+@5���)�3�)�xa�U9�z��|��a�v�r=�(��p����2���P�?�
<��F����A�Ea��![+��
W��|����pdC�]W�Z������kN���l/���Ib60y��������2A!��f���~����R�(���
<SE{�P�|{��0Da�bG��\�|�+BVN���v�,\d��*�*����"�
:��<�=mt�J{B�E�+����_$l`�=�z�_��G�����[�
�3q�|�>�&�4����0�������&L'�6L��U�u!a�U+�,l���(l`���_y��#�������-�Te��	J���9��U)�.6!�eU�[�@�B��UI��`_U_�G��&����>$(��Q�@�8!vSr�����b*��U�:pOUu�+��$l��U�q���H|�����Nzs�	3E'(Lj.����K������AM���h?N�-2��DP�Y����;�m���'BU��;+w4�������S��������,����l<<W?��{h���p��=
�rug�W��-H��aKM�v����g����|������pE����j�&��7��E]6�t�a2=�$��b���k;��<�p��O��;�a�����$����y@�=��&��v��<l�p�@�j�����c�lup�@�(>	h��V�����0�����{&e��3J�&��t*�E�lyp�`�W�Uu6C2����>e���J^��90��Y-`s��BIPSY{f)e��z[$�l��m�Y3YG�>���-f�^�w(�fQ��������|l���"�����u�#��\a�%�4
��r����O��-���@u6���KU*�e8�2k���@���Xd���)BGP�Ug������q�Ia a�Zc�������D���!xL����'�����'���%��U
<��p�0i6��)~�='\<��T�*��f+�
N�LG�_����'a�miJ�A^���J�!
x\?�<ty7!���H��|
g����3���{�.$a��O�d��+t"AM�%,.��m`/'n�9���
\�h��:�c����#JWF����=@���
L�A&0�Q�u!a���c&�68��������G����x������|���	��(�mI��l���{������,v����Z��j����=U1�dp�'B1�E�7���Y������z�����t�uS�S!�p������Dh+w��F�'n�����t�~��Y��J658��hB����E�k1�}�6�P��}���*�e
��Q�[�����
�Q�:*
Xj5�8g��'����]���n_O���������&T�9�
��Q��!a��s.�e.�=��jRh�@S��%�
������������gz�8�T4$	������Ak�I�1e�zf	���M�(c���9:�+��q��J�j
�T�
v�����'T�)�j6��d9a����h����:L�������d��Y���3���B��)�HP�Fgf�J�A����is��*��'��llWH���@��Z�	J��8:�P9>m��*�O�$�(l�HN-F
�/XQ�(l ���l�pbET��
�2��0l�pnE	
C60O���Z��@	#�T�(l�B�@)|l�pXF	���Y>���m��(�]H��	K2��
'g�b�xf�:v.�+�"AM���G�l�=����3B�V���}�U�eQ6�l�		jz���,��q���ta�"a�t��B��.�t�(l`BX�T����L\����&a�iI����j����c��2�n�u%�z����d������0l���~�&��+�!A���-�-�e��=������
d���d�p�G(#T���������a8�����
4�gAaF6q8��a
������N	A6����A
�f8$�*�C�@�x�W�����o�>��Z��;������F�[��gG/�+tb�����{�2����Q���%>
������3�]8�#�5au �]�J�38��j.}�@S�$$�_��dhp�g�L���Hxt5=�>�B�
D�SV�|�!AI����##`K�7�HPS�{&�gV���D�&�Y�$l���N>�"������pDa
�q�bthB�P-6)��
N�!A���w�!<g�BHf�p���
D�S����Q�(l ���	���N�
t!	�T��� ����z>;J���>�����(l�|�>�d���?��
D�C� ���?J�R$l t#�>�z�A�@S�s��)#��Z��������!����! %��"�����p�.$(�L���%[dF
<���^��;��AC�����������f��!c�@����Q��O=���G����^��:0a,���� e
P6�T���0������"
����<��L�		�|)1�<>�z[���'[���)�}H���1t!��R��w�~x���t"Sr�@|!�:D;�>���T����j�����.z�R���=,������
���Dx�&��pXE��IM���0�:=���D(3p�,uz�az�>���\<���*���:\�a��
P~�a�u�c+>���<���r��O7%b����
�gU,4�;�|��]���
N�(=����ec�S3J�A'���O�(_.~{N�X�l��e�
lo�3�(��Q�����O�(��NP��W&��XnP�0e����
4:�6��W����*���_N��*���&��|���Ac8���4	X��`'FD;AM\��l�xL���uj:���e�����u$l`���	�)y����>K������KO��r4[���GP:�SR���eJ�$��!l �$�������!l`���>cJ��L��i���*D~����M�M�}�=�:t����
���a6�T!2u�No���U���������r��p�$�qm��<�=N�w�:�%�6
�]���8�	%AM�]�P�	z�+��>$l V��r�F�+�5��w�S�L�9��E������
4\{K�l�����������&u�b���eQN�j�&[��}�v"a�5�������r�jN�BH�g�y����l?<cG(Q���� �$�]l�
P6�pAC��������4�w2�H(yT���y����
��}��"aOw
���Q
[��|��l�����u�K�j6p�����h��s��kuQ��D���'E��[��A��
�<������<
�l�x����Rn�A$l�����M�z��f��|�z4U�
�GP�VG����5��F� �Q���0p,��������������S�'M�L�V���f��4��fl@�=�\J�h6��xl2�*�	jr��@�&E��
:����Fa5a��=O�NP�R{�ap���r��!����O7��xF(6�w�?�6��V���l`�1���78���G������������*����^�}����V����
��������	�?�7hB�2ac�������-l,���^���'�
6�:���]�9@8�����wgS�e8���2��xO�������0H�F,oqBx��	����2�<�����d���.����������w^1y��MxH�b�=�b�����n��,o�3�K�������~ey��m_�w�wNxW�W���\���+�}g��� I�$o�P���Q>�	`�9�O�'|X��	Bx���������g������1�L����f�G�	!O��,o�CX�	�P,�����t
��ycx�&e,������5�����p�&ey�O��	v�	'�(9�$o������������M���l�L�XSOW'���J{/����[��+f�)![�$�pB�����b�����5�tt�S�R`��<�'�X'���wM����Z2�%�������t��.@ ����J����3	�2�a�\Ik�������)x���yB�N,o���/p+��U��U����O��+v�����&#nH(6l=��x�Y�F%S����wqvH�MOhW�B��9����C���6������(o1�����R������&�[liO�����yV��-Ny>W�����V�(oq�}>�W,�C��J�{���X�m���E=�[���b�
�U�Q<�+�[���L$�l�L�������&&��pd�pb��9I��g7�����2�T���a1RB18��,o��0c�2��$CBHX�&G'���0�5���C	�[|�+���p��d,��$o������J�X�'{�����HW�J�����>� ���K���cn����F�
�Y(+cM�\]��X!�6&�0�[|�������-a(	�[�%-]���bxp#�!y������m@�
�[�e�Lwbd|Vc��e��������X�IXW�Z��8�Z^��g8&B81W�q$y����|q9Eh�>�I�����H{�M)V��a@���cy�Mm�V��Iej��2		�[����I1z8'���<���g�hs�U�82�����Y��wv�L
plFiX��|es�+�Lp|&��z?YU�x8A�����,o�~L
+��!�L
�����Ggh�B�.6HT����"_'1h8����[�'��q������1�$oqBw���M���������.���f��c=	�[|�U�q����=J���I�3s������c�]�\��A����u�Ney����_W�78�CX'�A�o���,�i���@��#V�(oq�yb�E���t�D���X^�^����Dy��j�oJ�����.���->��b�pJ���(o�SG��A%��$�[|�s����
�A%e�z��u>��O%E�X!'����=��8��F�
O&	)cM�]]��'N��}�%�%,9�$oq����
15<��*I�b����1)<����5#xt���������$% y�M�L�Kx7�B��)<m..t�X�
������i��i�a��8'� &G���#��t<����gy��g����%�i�!y�OVSF8��Q:����-�V��
���Q����uNJ�a�2���isq��t��R\*���f�]�\S���+�+c�
G��Q�C�nf?�C�x$h��p��x>w6���������f��.N����t��a@���by��J�_wQ:��Y����I���m��,td�BGX�I�bl��+�B�����5�~v�)����	����X�����Y��G�p�2'cM��]���h�k��I�m����-f����brx8IX	+K�����j���!%�
X9���PYw����%�Mq��Dy������Z�Q</5jz���gk+6�������Dy�����K���c	�[\����
�U3)��{8%=�G��[�8�UI�'y�������[a�dOBX��WgY�['�a@��ucy��������z��e�I��������V^1��;�Z��8���'P�
����O���YwV#��
'c���]�� ��UYW�W���O�#��"
��u�8�W��'y�8��^jj�g�S��}	a�g`uq�y�SX���t�������H���� �kB����1]�`_(l�x�j�Fc��z	�^����E��5��9��(k���b�������0R����"�xD�b�-�(|W�#�4!�#E�-6�E��+�4,H$�F?W���:0��0��b���.�"����1����OUuXp$�3(,$���������E���r�[<�	�i����pX����U�o<8�,$o1��}�L���X3��9��������2�<zgY�{���S;�������w��2�s�3c�����������yu����*f#����N��*���3-�)����(�	�i�	i'T"o��=��:�3mX�6,H3�.F��.�Ie�y�
Hf��*�@HWM����->���ceN'�����Xh�������s�Zq4��a�+���*�����~[zp<�8q<r��[��y���[���P!e�7��.NHO��R�0 a�Z���X�t����:f'�g?���-F�S�\$��a�����.F���':�Rq0��0c�����K����.�P����.6�x�q����t��@�D�b��g�I�81�|�f�\��H�����u��u�1+��1{��FH���aA�it�3���H����C@�0��DM�����0f]q0����z�GJ������,�����8(f�Wd��j,o�s����[�X��$�:Ey�Y�t
����S�J�-N	�'y�Ox�YI���-6��������	�3'a�������/�d����eV�����->�����D���Ix���V[B����-��q��������	�	��[lz���H������i����h�Lh�	i'�,oq�����5,�d�F[�<xtO�����/��4a�p���]&�+(��B��9�$�S"RqZ������->���W���+��X5������S���'NL. #y������avJx�^��g���S�T�������[lx�{������p2�[�z#��QqLx_Y	��g���5-�3����]3�,�[�,�8���>��N�ey��Q�D�W��|���y��������4,H�sE�b3�J�����)3�|(���OTt����+v+cfay�
��=!��^>�OY���,Vgrf�Wd��j,o1�n��TN��e�������;��x������9g^�|��;a�gouq�j�^���"H�",o1V��T��2�����$oq��|���������~����{|l��(s;����,o��E3��7���	��e��,o�CX��Q��C�j(�?���%�W��|3�3o.������&��`������K7�����|aA�����}'��A�GA@�0����T���+�L������"�$�8JX���5������3���->m��m(�C��|D,�O���fw�~B\�[	c��ruqB�=��o�YW��",o1�������+!e��\�.F����	WH����L�RR�r�%�[���}��/������-6#����q���Pey�B���0��!�5y����71��"���g�\|�e��0�4!��V�-�O�lNlL�XTN��K�ME��S�"!m�r�'�[�@F��;���H8y.cN�z���b�<XL��IH���+��#�������<�1-c�?�wqB�g��G���&2!$����.�z���3��L����������D�D(3�"A.�\���T�x��W�]:�]��"o��
,�������g�\�4py��iB�	���[�l����3/c��F���+��B�b2f�,o������	9fB�B�l..���X��W���,o�3����0�1bu�\:�-f���p�����lFU�-N��Z��0 o�j�����\������dF%���wO�
f��6�S�!��)0�QXH�b�z��-~��
g�X��B���=�2O�:ms<� /�[l�oj�2�%0aV��?[5Y"`^�\:�l���-��f�da�yE�:��->g��������d��1b�p��-&���P���a��wu����32s0a�0`X����K�$��>oZXej�ppB��Y�Ghd�`N�X����#<���{2K�0�c��wu1V�0�L&��g���z����|�8|T��C�j&�c�N_/E��Xx�����(sJ�
0VD�bS��
T����N�e,<avq�')�
��% �y���I���w^�wF��y���4�[�fy
��K��%@�X.]&y�G��<��X�e��i�C%�z���b�=�Y��a@���cy��uz��v����9{!��[��	IH�b��'/uSZ�����^�<�8����L!�7��3v"�[l(�C&�okV X��]�f���G�iB�	�N�-�������y��<���|���H�m-�Ee�]|���[Ye��:O�-.�I�D��W��a����]�$2#brl��*wS����S)�2!br��2��W#+���R�1=VY���-NX�/�!f�
!c�$�w1V��q8e���b���-�viy�Vxe��X�ay�O7�L�������8�.~���2�L���<"o��(�o���0;ST����VM�-L�^�����&��b*�����c���d��d����N��&y��'��t��dL!e��.NH������.H�N,o1����e��dL�e���.F���:qa:�����G����@xeb�|�Yo�^]�l3���I��G���=�x?�&:!\:$\��"o�!t�3��cR�`,*�������Q�7,�`������t�������������;����p��c�,o���T]&D
/c�Y6���8��T�+���G�:LD�X��E�������t+��1Qi��������^���S�#�[�lUen�dD��XhH�b[��'�W�n�I��8���G�aL�_a,*I��|/,�2/���K�yX�b[���!�&$�`����ay�� aX�`=\�<��1	P(��0{��N���J��h!,$o��F��s����,����P�_L�S�kD�?5����Yk���U�,oq�������V���9���-v�
�9*]�.`mX���.�����U<&�)�[�g��)�������>�0�����4,�0�o��
V��~X����}=�R�z������)�J�tH�@EE��|[�W��A�`,*�����$^�	�		'�"oq�N�G0?P(��it��:�$���J�b?������7�L����<��b��9�?��0��"�\=�?a�9�&,�P���$z���`��9�[�����b�MO-d����y������gy��7��d-���,$oq�ZufB�������1��D���	�������,o����3�N�F�8\Y��l�����t��@�D�b�����V��%��e�\�7^ ��3�M�M0LE����T�j&�	�����&70��	��������H�x
�����G
�[��M����A:����q2��k&$o�|��&2c���$y���B�n
^i���k��Z1=p�q:gV��1�MYH��B{����mJAXG]l(�f�P�jLk[�}����:�\��l�+��e���N���lB(�%&�1��[���N��B����l?���aA�� �4��t#��G��2!c!��O���X&�%&d�,oq�������W��qT���g[T�����x�]%�}�U������%�_���c�$�Q������L$<�
S�)`mH�bS��#�]��4�2��tFfR������Dy�
�Q�O��J���F,,$o�m��I�	yRfB�B@��'�)�%�]9�\���-�3S��G�h&$�,o����+jy�iB�	��[|�aefB�E���L���s�����<�2/a�!y��y�]"��B1�H1��dy�m�� W���5���d���IU^"y��\��a������&���1�����h=��LLiS���cy���������Ym��X�5�]��f_��9S�D%�[l(�T!�9�����-.�IfENT�al
f�,o��:q���K���I�-~r|�l��r�K��3o.�Z�>����9�	9'�"o������	���aA�itq���E��E
�e�(�.�W4������|+"��v��b�a3�-8z�I�����->���y�p^�p��������A�fO-�����W5H��<�D��|a9F(�
q�KX_eZ]l(��4�a�0H�,o�CX<)��z$�����-N�N��3J���i	�sL�����qo���������n_�A�P}�=R������+b��C�**�gy�}n�DD+�J�i���YZ�!UuFL;MH;�(y��v��+O���|aA�������n�(�-��Pe�]�P�o���8$fZq������+]�-t������[|���0��"���ay�qL������Q����%byW��-�ryl������V<:���V#��C�J�
X;��8K��d���X�Y�G��,$o�i�����������w�Fg���{1�x+����sY��gy�)E^uZ���c��-F^�$_�\c�N���o��o�z�����n�Xh�Y�'��4���'�W��N�N0�E��������	����bC��/�w%_5U�����.I���+�������B����+���Q����-�GL8�H8cX���,W|�v]0�6����CJ$o�r63R\��
!c}�iuqBxb�A<��*k�j�����)N�k���>���xO�������JGX_m]��z�W1��&L����T�[\0��E0�dy��v��&\:$\�N"oq�N�S0MW(��ysq����6q)L;MH;��y����9B�,��
�L����z�/$�2�����j:��b�s�A�X_hZ]��Q���:�*^I>jp�����J�VU<��+��X5�����G�����,���Sy-)�[��g�����<i�%�4Q�bK{�A'����5`�H��<��������e�����v>�)�BAXT����~<��	���z�[lx��E��W���DX�Y�-�[l4��"��s�;7�U��y�L�;�t�@0EZ������L�~3��.,�>�[�:�t�,;8�>0=ZY����s�:�UV��B�?YW��1aYYgd!y�
��M��Q�����G,N���f��L��S����>���Y�O.Y=L�*S5fN++ay!��-NX�+�2&Jc}��w����%<(;	L��,oq��2�h�0?Zh�;H���BC���h�����-6#�l~��������#����S1fD+�cD�-�V-��3�H�
�L�����>��e��iUfgk��2c����0jD��,i��.c�Q#.���g�\���?%.CY�Yg��[����d�y�'���Q��xx.�Wfc�gV�����-F�s7]
������$$o1��7��w��D����KX_.]���y*2Qc���2�G������-!0�|��,<,oq���_vR.�p��p�����a��0�L�������SF��L2�3oX�7�@y����v���������l5��Y�q��V�{��-��:�Nv�L�����bc�8k�N1t�O�O�'	�#�G�H�b���[g�gB��9`%��8�.6�3�D�a@��u`y�
X���/�T&r��'$!y��
Y����o�#��5�.�:���Hxe�H|��cy��'sq����#��$�[�U�V����f�t��C�*&�;�P��B�`B�B0o.vLa}G��	�&�"o�0�{����aA�� �4�8?`t�'
��9^��X�b3`�I�:�+����XfZ6�����F�;��;��dy���J�ae�(���8q���[�@���2�cz��2���V#��ua
���[l�z�p�x��V��~S����8�O�\k%$�o7�.�j���G��kae,�(u��M5=�`�5��`V���mIuL�tH�@�D�b�����%`���2�ys�����l������S��8�Z^nbZ������L��Ow*�B�b�2f��8������}*n���e�\�\����\pe��n,o�sS��3&����x������,�����`B�J�-�����P�)���->_'�����V�(oqJx�.*S���������-6���	��}�����<���� q>�I����L,���k�^�':p ��t��@�X�b�z�����`Z�J3o����)��G�iB�	�,�[����3�H���F?_��c�]�V�0{��f)sQ�VE�E?�[|j*�{,fe_����e�<��,�n �/����?by���-��	��kV�N�����9���	��+n�I������#i�qs��)�C��	9H��}��?@����g�F;���+!��3v%�[|�P�e������*�[��>4�����������L���.�.PK�����Y��+�C�y����]��NN0`E��3���Q�� kX�e]|����
��Hf���=��+�!���������@���#���e�\�e�?-��Ei�ig��[��;�������F���X�H#y�I��c:�Z�@X�d[]���Y�U���a@���by��j����O":�Y��1�z��8[Mo��cbVv\�JX�d]���I����V�����,o��m������,o�����#e]:d]��"oqq%���%��%_��7g�P1'^i�	i'�"o����[h�0,H$�F�3MuKD'nK�>����4��U��+������8?%d7��Sq2�es�1��������3���-6��%��b��:.���X��#y��}~e���������������2	���6H�^,o1��;V ����hB���4n��%��)�Y1a}got1���9qFD+����f�E������
��(7W<�|��`ey��VuFL�tH�@5E��l�|�1�8-���g�\l����v�I�:M�:�py�������%&
��I������xA�����O��4av��k�%euNL��pb���.6�P��_uO�*�K>�p0���yV�����v^�v�����~���h�����;[)Z��|E�o����+�Dm���"V�a�]BXXH����`����	V��-�j��d������ShB������Fy��1/a}�pt����E����l��ey���0X�E������G1�[l�S7��b��C�j&�?W3uT�����,4���,m��A��&��`����H{��	iX�4,H2�.>Q�}����#���,av�a=��W��+�'��(���';V|��/��"O,o1����Yr�yE�+��?;
��������
�<Y���X���:2��1H�O�?�-��V�7��ZQ�b��n�	���G��y�mE���I��x)L�W�V�(o����)�B�Dy�w��4�`&��oV�Q�b�j�/5!\:$\�j$o�[5q�3K�U�����7�F���*����6�(!y�-��r��S�>q�j�p������_�K`��0b%���*z0��G��~a�8aY6�X�o2�����3�-�[�c���}��7�<m���<�H��� z��!^����k�7a}�quqBk��0E�"`MX�b�Y�c^�g����o�	IH�b���^oIX�G0+a}�qt�i�\ ���C������c%��E��7q��,�B�>p�����1��)�)���[��Y�Hy�k����<��b3l����N�N0ZE������a�� mX�f]l,���+��o%�I��b$=\fp@�������u�y-�4�h�$.1x��j"�[<>��-�4��+/c}�qu��=���n��Ox���-F���y����e�O8�.~��e�������>�8�8�=����2�C�������u�� �:�C����������/K�TM�-6C�`=F�oN��`�
�ys��k��iB�	��[lh�v�&�:�B��2�.F�S�*	����X�~V#����|0+'0+caY6?UU��yE����#��k��j���df	�#�� I�b�?����8��p�LX��\]��'��Oh�������h�4px�}?�{aVq'�O�B�'��A���=S��'G�cO���9��`�dy�����Aq�N���8FY�b�8���$�Z��.�.PK���l�� B��%b��`�\�*:+�L���X'��8�����I�2��<{������������3v�[UcK���2z;�N��}OX��^^}����S�'s�t	��	G��8��/��.vO���|�D��:���V^�)!�>���{�,G�B��&��+�[|�P�EH�WB�B@���I�!�^~���'y�-��3��LA�U����*y�B8MH8�(ay���:32oX�7,�3���G_S����w3/a�	����/����v���Xey�KcG&}HvW
��r�<l�vx��[���9|�p3��<�Hs��,��",����<�3+��������|:��a!�O��j�
B�0��$��<�������W�'a!�I\i�wG;��Ut��)��x
�w����U�/��L���8hy*7�Vs��+3�0-2-PC��
��p�U)�i0;
Q9o~�e��iB�	������<�� oX�g=��)�����9��=���8{���<���c������z�6������	�%�<���R���@(�)f�
�[l�V��PW �I(���H����Q���k}���U\�������z�����9���k��'���
�#�`~B���:�2J���)�+����N�B�
!��U,o1v��S�B��F�x�,o1�����]:�]��"o��=t�p�W�|D�3o.vFg�3)�4!��S�-~�_��0mX�6,H3�.>_��I|�|5$���&�>�)V3��A�����$����!c!X6?k�q�w^�w�����f���+����	.j������C������@�s�V|7�GW#��� v:L$
X7��I��}�=�+�I�Y&�!y��S+aJ���		�S���MEO&e(��/�Z��WY��gX�S�U�%�08�Y�b�����R,R,P5���l�"B�Q��2 ����P'�:D!�����l"o��:����+6"c}�pu���R�h��)\�{lK��8;��k�2C3��"���cy��]��qL���Zb���	@��x�T�����W�k�	��������D�N��d
X;��8a�
*s/Q��,A��*I�b��wgMz�L���4��GI��g�Q&`��	��/f�F���Y^��#�N����ey�
��e�:)3��!��y����U���'J(���������L(S�D���"oq�BtRf���>����t�d6&B��%��Fdy�u���)�)f��[����]&:CB4a��y�/�[����W�d^,��2�����Dy�
my�[�aH�N8V��-N9s�6S�<
����(o��8�����hH|V���<�����������-6w~���,z�[\�<�� 	X)�J���V��B���y�!�[|�e��	e:��� �.��L����P��],o��:�t��JHX	����:�tY�	��u y�-����}������������?�}���������a7�|�S������Q�G32�]�����#P��z����<��E 7u��]�ws7��E ������@��oKM�=��7�o����QOj���{�,�??q"�����$�L��PR�H~��������_��o�����~y���iX��y(x���?�i���{���������O?��?�8�+����?�����?�����>���u���}��}���������?��/?����c_������?�����������}��?<��q�����w������>��n�8�R��%���,����
�{�OY��M���F������������L��k~=���������&�����hN��?����q�\�<���������#��?���|���|���x���������?|���#�b-�.j��>������������k��}��]�5��L?�5C�V�8C^���w_�U��F���d��n�����k���>����Z���������~�f�1AN������m���VW��
����������x���Ou��q�9�Y�oUc����Y�o��R3��{������e��vB�o�_�5���}�*0��>�����%�����fn��k����<��z��[�����k�"���/����~������gn��1�<`�c>�����[_��+���e�/�~C��]����{����������:���
�8���=s^���a,��Z�7�7�����{����z�7���2�7L��2�7LK���.o��B���qx�eVw(���k:�!�prO�\���9�����	����i=�����S��9�a,���W�*��>��������qY��!�tZO*�
S>�����]�
��zR���tQ������h������n�I�����tH�i�/�:��������	=�y��W������������/���oW%/~_����q���W���h�K�����_���.���{��WH�_��k�Cw�2�n����In�_�
�����m����'����������Z�i��la��_���G|�o�i�O.:�m,��������~SI����o����������}����}|�U�������nv}x�~NKs����_�E��J��<�_3�����R��t`@;u�+|0%�6��o����EK}X�����8��m�w�UP��nB�G��q���/3����q��C���{��#�|����������[���r�k��~n!����+���
�~���~�������������~��7,����w���{]�Tl��z)��6�.��;W�����w�������w~#<�|�=i|��~{L��ZC�;W���S�� �eZ��]��������w���w�N�v��h|�Q����.~6K|��~4�kl@��ZP��]���^��$�����](�]��kT���q'�'��G�~��4������8XC�����:$���~_��\�?��T�|��CI
�Z���/��:�����2z���|���!_c���_'�LNu1���A��)m�������IZ�>_�[E�5��u�XM��/�����yH�������X���/����G����y8��1Z�"C����%i�W����/gI���9K��D�`���Y��!�	C��ku����M�A`��*�s�S� �U7�s����r�/G@	�_�8l��c��m��`�s4����(9��:�F�y|�	]�-bBWq��0�MbBW�[��L���,�Z�b�QcBG�^uaIL����-b���/�W�O�R���U,bJLX����Fc��%�n��,���`��~��79&<6$�	�~d%1a����v�1a��>]���
*\�5�G���VG���aFq��`�KD�Q\�V,a�����q���p�WO�kD���|�kD�*�~=������fs���VQ�$"tu����n�3�}�M�������0�����C#���/5��F�YC����tq%O#��%UG�K�~r,�3���z?jD�i�O��d�yKzk�<����m���YKz��$�h�U�"�(�>�^1������8�(�[�XB��%�P�u�%l�x��<���=O�����mhWqejI����%����Pa��������$���$�t+�V������V����X3��5��a ����^����}O��[��{�9�g�M�1i������3k^O�_���}]����`_Ws\$-�Wm&J���9o[Qw�������O���Q���n->Q�^LM���������e���ZV}}S�����^���xM���Q7^.u����r�������W�5��C7y���F_i��j_��U	]����c��Xh�}�o��+�����++�Z�b_PbE_��� �x�KbEO���v=V������R�u/2#�[���J��#�	svt�T���%;��	s�]�
,1a�������g��G�CeLX���#�9�
b�W���0��:&|A�9&|���e����9#��j�a��o�a����0{_�����ED�*����D���F��;F��<pf���1�$"��v��F���5�2:��'�^���av�|m66�$"��QuD������`GO�jDX���'fZ�"
[#��]M-����}k�JX���U����$��@u}D��R�^un�\�$l_f��n^f^!|A�y��y�%l^f=�8L���2��W�"$t��-Kh�i���'.5$tu7Z$�4���C�$$����4�$$tu��HJBBG�������0;j*R5$llFIH������`G�G��Q����b���,��b(�!�	;�Qq�&		�vt��D		3�[��Y������b�c���%���!!aVu�a�RKP���Q[�/6/u.���:��W� ��W�d����h����(,�4����0jX�i�
w�a���G�+
�-����0;j�U�!��QuX�������%aas;J�����{�k���r
3vt}�M���vt�F���$�%�D�,fJ]o�:�TsX�^���/P���%(l_f	
�������y���C�n��z��y����o�UW���J����:��S����m�[r����rd��[�����W\����'��NT���a�Q�I�1h��j_V��Wm~�9���o)�Wu<Z���Y����b�5uu�x��S�Ly�_ms�������}W��
WFy�Z�D�Y��iV��Mq�H�����}��Be�RKL���Q[����KMa����E_i��k_q����v��r�X���V�8�����n�u�k�[����05V�t�}���(���"OG���f��a��j�(�����%;��	KvT�FY������]��������R�1a~�\Jb���[�y���_Qj:��3��_���98"|A�9"|�j��7G���k����]�-v�}�mv�}�oo\%a��[���k���A#BWw�n[:�=OV���5�a%ac3J"��v�D���(���Q��:"��v��0cGM"��vt��o����k}�sNy����9"|�jZ%|�j�	_�z=���U�W��^��6W����%���j[���&�a�%������j��sM}�
�$0��v��BWw�I`���Z}�K~��l�v/2�$0llGI`X�����;���dGW�x%0��v�,��v��'��������
������Z��II�e��<~AsHX����:Q����^��6W����K^n���]�M�BWs�����&�%��-�w��vE������{<�������;��Q��z�aac3J���v�����(	vT�^X�����\k7	3v��EXx��������������-����w�_Pj��������n�_/|���em-�a�RO������}Z��G.i�C�s��n�h}7�k�L�����L���~�jJ�*�q=\c�L�^��-�a]�o5��c���k�M5�uu}t����a]��/��z=��z+��P6k����P��5%�l��j� ,���g%�-�S�a��9}����P�`N�[�s�6
$���=q��P���y��{E��F����b�3cR�����6[�������E�\s\�z}YJD�^5���k���<N�ig���o��J�^O7���W�":��C�;����]��4:�u����uc��s=�K�O���u�
gn��U�H��0oF�o�����2�Z�b]V���v�aa��j7�s��b�3����J����}��#;�r=�����5��W�i}3W�_���2�����M�`^u��f^uu��Ts4�
��Q[W���!�/x�Wz��iD�*����D���6�����
�ID��ns2�����z��V����}��dID�51k��r^�"3J"��UG����5F#��U��F�;�����0������F����~#C����M���vt}oBVs��
�W}��o�	���V���K-1a������j�	_�z;j��+���ZCN�K^����]�M�LKT�S������&x��ns2��-����dE.���n������FM�5 I`�5����vtuyS��]g50��QE^��;�(���~�^tnE��0d��;��$G&oG
�)ofU__���`r{}�����e������N��Z�����+��z6W����K^����]�Mv�]�5�,	]�o�������k�2	3����r�'���a
����u�$,�����M���U��Y;����aa��jS�KvtuwZ���5Y/,�Q��������F��vDwG���Y;�R�NNy�����?W����fUW���W}9���0���Da^��T	�����U�w�����z��!��}f���vW���J[������W��p������Yn���*C&�ff`�xx0����5�tu��(wn:�_���5o��L]��jo������p�`GWo��p3cGm��f��.����;�X��p�`G���'��sMz���Y;�~�A,f����b��
.p���l��������-�f���P�}sH�������k���Mhf�\�������Qo]0��l�z[lH��P��4tU��kvU���i����+f:������{����bf�T� (1`c���U\�&`�|.�f���rc�|j��3]�b�1c>���=�;�O�I��U�������������%�NT�j���G�^Vs�~s�2s���|ym���/�
����.�r�7u��_�y:[Dz��{���F����Q����\�������;������r��Ho��;txuW,����R�2��^�zj��}S�XE�H/o>WoH�H�7�&��o>��5�H������Fz��\��3��r�����L"�������H��]��L�^��k#��%�H/��>��i�5I���|��%��i��>n�Y"����T������\Wk�p����zL�����O�%�����||�y�?��������-�w3��"��Q�&���03^�j�V
�r�S�y���{~s��/)���3����s���$��T{�������$�^nT_?���{�)�b�P�=_w�p�o���l��_n��^Ns���������A�]���p�y�%�k�Y���c#	���W]�C�jmp	�����
I��)�T��B�y������\7���&�{����W��U{���S�3�%y���ZO��-�`7o>���d��s���{��\�8	�<���M����N�Zs��hT�r}�U���������{���}�������������j��/W���r��\�D�5��Y���^�v����_N��E�y����?�rwM����RE\���"�����z[���O�CkP��nT��kn���23�Z���T^\����Q��5��xis�u���fZ�������&#��������"g������N�~�V3CN����+
0��s��'	03�d!g5_O9���e����h���?h�\���D/G���~�9��:������o�����������I��6BE��D|���
��D|��F����k����.�b0��^����k}������W�5�kk=I��3��e���������������e��]x�<s���Sqe�F|����I*pv��ry�h���n�6sVs�m��>���b��bV��������~����������e��/���2E}���������"�s�z=4���S\s�=��<�m+qU�I����[b���S�&5�Q���J2��f�6��r�S�y�5����������`�|>Wd�H�����w��������Q�o>-RC����m&�^N���%��u7�x��ym/��:9$��z�8��:9$����I��r���C���������\��S]��jmpZ���"8�-��sU7Z��T��L%���_�;C
��N���j��U{_}.pf���x'_[�I>Oq�����\�%5������;	�|��xBF>O�����$�������Z
�r��E.pV��v
�|�U_L��vu.p���o��p/������������%��i�Hn�\}�_����{a���Nq�^��p��{���$������U]�-��{���Aj��=����:���^��������p�/������:��[��v��{~s���"��o>-� ����W�d����/�N�� 9$;����H���[�L���6�����_���]�r��_�j�~l8��:�}kH��^�v����^�2����ua�������������������>�����/�L�������3]�1s�~�}�-����b��v��J�����U$�u�^���7����=4�uU�U�\�����K��:�~3-]���KQ��=��W$���N�\�>������ 9:k?W�Q9�ml@��6�-P�]8��z�%�uU{��W��Cy\��h��/-��������W��GY�7���V��^�j�~J��2��k�2R�JF��l�]����	g-��� ����I�����w����/GxC�GL\��w�4����8��7B��Fx���S;I����R�*�Dx~KW\��^��
y=�D"<�S?W�%���K��o�O���j�(^�9�7�t�p�Dx�U|�h���t����}J�p�~K�~�S����SED����y
�|�
�6q5����!_k���z���3z/�f�5�+!���>�����|m�r�7�����"�s��"��������S�V�`l�y��49��i���CC����|~����zQ�W��*�{��$!_��j�.�6���g	��T����A�r��kT����U�Hb���������{����ht5�,��w����S����/��z��=_��-h����h��������=9����x������/�����$��4C�U>O���#��EWu���o���4�����{�}\�S?�����W��b�>	�r�S���:��5G�U>����|�5Y��[��)k
��
����^�������|�s=*�����by��\������~y��{}��>_o}��X�|�������+_[�I����MW��G�4���6	�<�5�����S�V��|��F��~K7�������>�|~�~�9��_n��l�vG�S���z[7o@���d�b�V>��*�5��[��� I�wl@5��I��3�Y��S�Y�����%�MT�	G^*�Y���������X�?_o��>_���e�������A���z���B��#+��_�u�l�z+�A2e�|5������i
*]��*
���U]s���f���������8�\hW�������%���j/����Rf�K��&R6�
)]���B77
)�S�R0��5���|����]0���"O���.Z��2;^� ft7����)��j���I�������/����93�};sft�2sfts����_6qu6XLt�^OL�>�*�eI�>Ou�c\I��7s��M\�_kN�i����Qs���}{��������/7^*�^5��YO�Rb�|.��i��7��������}~;_�����7��P����S{�a�+�0�X/������xx���)����"��i���:��r�#�_���%�����-!6���q}��Z3}s��M\�
�D\���V�y�k�V�y��x��.�������%	�<�_+n�M�>Ou�{\I��W����`�/7^����}m�'	���O��6�$���Ou���|��/o>�������&�S�s�,��%��|	"-��<g������1_Ns�b_�2�b_s����^�v���5K��Z��+9q���<�M�?����6��d��I����Zq�x�y���L��o����J���x�p�����$�kk>I��7��l����y����mn>���s=/	����f�<	�r����s����[�5s���|})����e������U=(�_s�|n0c����`c�I�����Wk�����$��K�]]����y-	��f��W�~���5O�i����Q�S*�"�n���W����&�^�b�*�`���$�^�d�W�Z�L����d����h���LU�w4���L�����1�O�d��� �_��]{��5��	!�V�~� w�K,���K,�z�K,�]����3�]�q�����>n���.-��\���l�HH������et[�~%_�F���-�+�
3-~=)P��L�_wX>�����u�]�&C��q���Rm�HcK�P2��CB�������v�����dv���`>��Q�
O�
��u���\��ft7��j�,����<��h�~� ��oe,��2��/3���5��qs����qu~��'�������M
]�5��&Q�������<�_k�%���S�f��Q��_��Z���x�~b+��r�s��j��r�s������v�`>������-.����r+�n����_.O�I��S���x`F�/����M0���HgK\�?��\�?���A��Gz�5o�\���������Wg��aWo�H�S�(��T7���f�|9fJ"=O����{5��T���H"��j�`���H/7^j6^��XO��5�$���Ou��7��H���$��o>�k��7����x4�[dg�__`�H����,�4s��^3�z�5K��^�z������/��z��,�^�2�y������2���"���6	��fh�y��$�d����/����+4��T���h4��������~������5�kk=I���|��/o>�_�|��K������)	�|�i��1��7v'_��,��L�r�G<�i��p��en����[���B��\�/o:K���\�����^���`��f
���{��!������E��kn����D|���|}�PB>_w�E>_w�����I ����N��^^{�]�����n���
����F{�mG������{%��=�������>O���t�����J���S��_^uu�
��������9|A�9|A�98g�����W���{;�I�������"�?0��xf��� �H`�A��o02��TpS���">��^��Vw�T?��v�F�{��T�l�}�z�l�:\�)��g&���9�<�����h7�a�������je�����U+}����X�����X��'��.��J�f������
VmJ���`�6rO2�}���U��}����G���*��>�
V�#�7j�~7.O�
vy���|��?��~����.3�{o�L��;�FF)�������N8��Uk6~�^��;����B0�������5�������C_��[��)
i�
E!coe�E!c?;��P��hc���?I��Y(
���������5�B���ju��*
�>�
�*
yD��:P�}dg������
&�9&���'�W�X.��W�d?jM���}��59<�5:P*t�Z3������j���f|�U��%6�5�g�J��B���
5!#�jB�����&d���3?o�'���k�����Z�������~~��Pm�nMx8�E�����U!gW�AU�wRWCVU�wR���B�������~sV��;�-T����o���P��O~U���Y�5V=�B�T�
��[�?v�W]Ua]U�Bw�������'�����<}��!co��KC���z�cb��z���;(
���H�����wM(
�6�KC�ncz$��z'u/���0���4�;)q�yn'�7���$�4\�Io�N��P���v���z��Vo��
����
(
:��G����������i���F
C�����pl�0��HaH���������H�0��Pa(cb��z���C+�0$l���xk6�!��Pn#�wd�����s���[�(g�Qs�U��#w���>���x��{��,��}����UY(��uu���P�e�D��=��u��"�Ea~��(�h{$�
�Q���Q���,��O��j��������<�u�
�'Y(����&�����d�_�,6{���>��;Ul��h���b�?I��@(6�����_Vo�sJ	�M���?"W���Q�@�bS��nAX���G�I��^�l(6�s4fWA���d��b����>��,��}��H�b��M�+��r�(7��yZ����y�1��x����������GMx�_������I�X�8��&d�P�"egnXQ��%���x��_�	�����eX��fc\q�5avaM��Q�\5!����.��z��K�}d��P2��3!
jB�$�V�1�q���@E���:��S�5��-Z���t��qt����T��o~�GOK�n�U�W=��s�����u g� #�r���:��Sn�����G��c����:�?�M��A���~����u k6��Xf���j�?D�}�^������Xu �G/���Vv��,�����:P����Pr��C��l�9<R*t�7���3�����
Tk��j�
T�veU��UW���*P�_�*0�j�I�����c#J�����X
�H���R��S=���l���� ��hg(��4f�@)�������zkB�U�6�K��>�R�G$��>�O1�}��#KA�����a��,���+h�����_�������4���iX��1�+�z�
�D���K�1P���R���*�h(��U�l��D1H��o`()9TR���J�0���5}�1&��SOr�gW1H��vGq@1(��P1(��]�}dO�1�A�bP�����bk�������I����bP��/(3n��V1(��C)��>��h���D��`~����G1�����G1G�>O]N_�R�:�����'�`
E�S�z���9M���)��q����l� �E&���?�Pd�'i��E�O6;�8�"���s}��m�E��G����>�"3�������8a
E&��Tz(2��|�[�:������?�2����8n�=�~-�o��Y�f~��������l8�W���a����f��������J�4zT���V���rd����g�iB���C�Q�s'V��1�!C5�����P�j�'�)������I)G��|����}$ED�8~� �G����>z1~#�j��S��?��LT����7c�����<��(��}*P�
P��UW�����+���X�cz��<�p�
�F�@����:�B��#)������������@�$��n���fu�G��o����@���:P��.��@���#)bE���(2�����p��O�?������K�:P��G����D�D������0�*0�������C�&Kt���8���4��U�O��~w7���R#"��"
KA�N�@��)%����� ��#)�����[o��)}�T��/�>�KA���X
�}dh;(�>z�?G(�V
����'��.���z�����T�T�Z
��jC���(8
A�j�<)!���h����ThFM~�U
*t���J�4J��n�S(6a)82���C);t ������12�F<���$����xk���P
����r����8��G)(�Q�@��G/}v������i]��x���.��o����y��2�>��a<a%�X(��:�^�W=�A��O'����h���z�q�a���P2�?���������b��_�G��~��������n?��jv����b�&���Y������~%����������?b�s�_�"o�\"7T�f�9�1A�p8���Qv�����������9��3#�x>��_�1.���0�v.��}�B�]��������8O1�y���l~���4y~O��~6�
��/��JV������rM$�d��5�d���0�nc��e�|V�������}�6���;,eU��8�U���������������
�����5�l�}6~0��S�����������y8�����u�5���Zs��n>��_���va�����v�_)��y�J8�����	�����<�����^�����>\_�uV��l
�p�.���C��!���b(l����C��D�!(�����#����G������at��C`���p��Cp������������_�B�+eTti����8�lRE����#��YB6��C�fUt���_38�U�=��x<�G��!��j��KY�p��y)�G�Ap�s��@wz�:������ ��U0��3�:P������8��Zs@������{\�����:H�x����u�q��l(�:��pw$�F�A\� �Ca��v��:`��:Pd_0rF�
Q<��&���:`�W�@���p�pu����~����:���o��~��O����=�Q���B��D���Y�A6��:�fUT��Q:�6#
�����2���U��x\����(u���1�������d������"������9q��D�����"����|��m#�T0u0��vk@��0��A6� ��!�/����K��������v���)6a��a��i1�=�`���"`$������j�%D<�������Wg�^���p��({ ���������\�X� ������{2b�I��$�� �U���*��U���e(9bf���x ��1�KY�8;\���x��U����=�Y�8�3N,���g����O�{��Xsh����������{0.���<��D�m�U�=���dU���8x����=��/��o;���~���)6b���a��
�(�o9c��u����	{��{����<�����h{���T.�<�7{`�>�cZ!��l~B{�&����=Pd��@�}{���h�Y�A6��=`��gC{��jw<�~6c?9�������KY�1eTV5�`TV���Q�����wp�B�����fx�\s���|�F��R�����F�?�������[�A<�o��
�}�����TQ��������������z_0��d������J���b(l+���0J�X	En~q��`��@FJ~�����sj��c��v���E�9�������w:����a'�������$��	�D�<�#3N"�R�I�s*8	E��1���w4ds*:�lNE'����$xNu�Z���c����9��K���u�r�=HA����_0|��i���_g%�a|���Phc~��4���?HA���v��P�~G��Z��a�]z?������v�w��cl����`�U��K����kDVZ���w�'���apI�0xZ�-�om��DD"(�0��3�
�l���G�X5H��8�$c;?6�D`���u�#x�3�:�u'/h�l~B��&����F�&U���k�lVE���~k������lVE����}��LV��*�dU{��LV��*�f����%��j[$��2��
��_@��$��)���6z����"��"!�A$�_;	
	���H������H��<���c,��F�p��~����	ap��0xZE�'	
�w#0rF$(�/9#9#x4�s%�)yQ$0��s�$��N��Gg� 8��7 ��	EB�<�'3"!�TQ$(�}�C8��H�fU	���"!�UQ$�����U��>��UQ$�������j_��HPY���C$����)��0�Hpp@"pp����T����k.��K[#�_:8!�
H���D���$B]!��qtI�4�-|�l�vg5Rl�$���$���b(��	�[�K0	�l�J��J���HKe;5/����~s�)�I�~t�M�A�����S&!���$���{2b�IL�$�-	��
&!�U�$��*��pV�0�Um�0�U���xV� ��a@�$�f��]�$���?�V&af�nK�
��K�hg���%�?m����+&A��}3�0	����V@����V@�]�
�i��8f.�wa�����I���I��Y���m���I��$���b(l����I`��IPd{n�x�&��3&�G�_��I`lkB!��~1n C���o��v4	<�N��&���;%�$d���4y~OfLB6��IPd�$d�*�E�M������pVE���j��I�Y�?iM������$�6�]�I������2�����@��7��*&�f������&����>�$pp[Q����8O��w�}�B�����$��cncx����t������G?B>�e���i�W]}9}Mo</�o�������F�v�7rh�N��e'��i1��P`��%g��"�}���(�^� ��������v����h';4����P�)�6k���R>K����f'ti������lJE7���&�9�D6�����Tt*���E4��}p���n��o�}7�s�=�Q�����P9��Af�/���?�J�?�Q�#1rA��-<�K����*�}�]X���v�5����X=��=��������=��i�P��
�A#
!.�O�����
���(E�#g9�����9*���Oq�����c;?�a��w����>1��)��	%B�<�'3!�TQ"(�/�Y%B6��D�fU����AgU������������<�O��=ta6��G%����������jpP1���A	���	��5r��A%��
j����a��f�����4B:���(��GOK������c,����������)4����a��
[#(���������F`��F`��F�����`l��?h�]A�o����x�oo�4�;7��F��'�i����h�lRE�����Y5B6��F�fU����Ag�n��~6c�4����g�xV���C���j��5���o�n7�W7�t��n�����!8�mTj�Bx��T��:��_uI�����D�!�B���B}^�!�BH��-|^��	���H�	����O��p=�����xI�=%_��(9�D4"���L������(����	<���������qQ!���#���{2��I<�$�!�U�#��*x�pV����f���DV��Y�3Y�nGY5�dV��[�Y��hv�On�K7���/��[ (�����fvcz��%����\B��+��G�0S=�
	�X��G������s
q4��khH��No���M��&���b(l���vW%gl�"�����J���M����(I��$A�	��\��6���6\�	<���gh8���mB6?�MH���d�&d�*�E�o�gU�	����lVE����htV�7��*��U#�EV}Kn�Y��h�&��jL�,�����|.����v&���}�B�5���m��X�����H��9��Zk�G�Q���K��?)!�.����^����+��x��=����?3��Or�O�������m?��*����}�b����ap��0xZ�->���Y�C���� >��0�J}d1�K� >��������CN��`�������������6��Gm
�O�_��>w��������������r
����~�>E��/��,��T�@�����Q ���
De�&H��
$�_Q����\3(F~�(�_}���=$r&�v/�X��������u|+�&��=��?J��Fz��>w�w���K����g����Z��������E:�E�����"�j�Pk4Z(t����[% E���>�H��)���"SD�o�e��H<�5s����4���Ra��
[10pF1(r������������8�b�[���c�J�f�(�~O1*�N)�$?�1��
�,7�����N������
���3h�pN�����F�
���ZA�T��B������9�����s<��r\�����"��F?vV�����?}^�\�����M�`X��w��}x���������e1F�F�^lJ1�cS�
mt^lWB�dP��Wu�^�����4C<������<����9������������0�dC<-��WC�l`��lPd_6(����3���?��������+J60�S�l��v.��������3p�����9����7�~���n��'�
i������DC8��nPd_70rF7�����U���
:��]:��9tV��K���9�1�U�Q������� �Zz���0
���bt,���<G��L�
��!%��(��F�L��?����L�fb�P	�p�J��K%���g!�	�5�X������!���	i��	i��
�u����e$��	�i]��~�6��#6Al�����.�X�^��~sK��Gg�I�A5/����8y~OFlB8��MHg��	��
6!�U�&��*��U���eTI����l��������j��Y��0�&���1���M�Y��h�(��������p�����w��A>����Ub��-��iA��oZ��{�z����3�W]'#��Z�����<C>�3����=�T-3��5
�X�i��+��qPRl�4��e��i1�i���]m�i��40r�40r�40rd%�LC�
����s�hx�����i`�P����������7��
�!���4���{2c�IM��}v�B8��i�fU4
*�v3f�����)��U�WW�g3��44��a)�fL�����`TV��4
*�3@������|]2&���a��kq�Z��zt-�������n��t8��4��\�����i�	
��x.��~��&���	���l����MH��t������tau���,����}����Y��pap9�0xZ��(��$��#�dH�}�&%�C��`�����Q�h��v��`�������o����`�7�6����~tFP�����s�E6?��H���d�Qd�*:�pVG����(�Y�:�dp*�v/�,G����(xV�\�1�U�Q"�>����Q�eU���U�
2��MG�b��x�� ��w��Opp���PQ��4�8��0��w���G�	�t;��cd:�e'��.;��P���]�����B���P�
A�}�@_��BPd_!0r��E����Y�"��c�����C� )�)vQ!�x?:��8}��f�A!d�*�4y~OfB6��BgUP���
A��
��TV�^q�}7���P!�h?��B�Y����RV}2F(,e��H����F(�U��7c<�\z��A���C"��c~�\k�ulB���$D8���4�.l���44:��%�N�E�B�{(����n�F�n�#)��u����.|W	����,`�
M��4x��4xZ��$�V	�Q	�l�J~6�5�@��h�J�0H�������@%P�M%4?K%P�M%4�JJ%�x?�WA%�����O����=�|��g�HD%��j��pV����(��=X*AfU{6��F�
��U����j�~�����)�J�Y�5�dV5���n��"A���4p<���@��y���tlFsB<�f�����:/J��__�O�ad0��H���D��7���
����~@�Q����Q���Q�1\�;�vG>RlD+�����i1�VP`_+��"���
��o�D����A"����oi�;t�����a�x�C�}������	�B�<�'#
���ZA��2�B6��V�fU�
���ZAe�f4@+��*j�U
rX����U��
�
*���J+p��C���
n
b��x$��%����g���wa�/��� ��� �wA��v+��]���zV@�G�iP�~[�q��h��2
��.�W]�A�[�4(tw��i�~��_(���1
ap��0xZ�{U�����3�A�}������� �a�X���o��;N�jb�����������p���?����<�g\ x�lvB��&����gPd�3�s*x�lNE�����TN�OB���%�g�9���R�Tc�����<X�������h�d,���j?g�g�����i�?�p�(��SknU�~x�p��#�(<�B��/�������#(t�V�i�1<�Nz�G���#��_��]N_�/�����+���{�)����	?�����P��
��	F��	E��#gX0r�������~��o~�;J�ji��������';4�Q�������o�������"M���C�M�h(�Y�"w'*f��1*�v/�8���q�3Y�7:�6��$��,tVm������i
e(TV}���.�$��7<;�_��gt�le��}�2�C��f��A���_�?�!���������[C�O��#�>�Vy��/�;�E}����=g��o�qz�r$�p��F�B\z!�Ca�?(p��}%"zA�}��������<�Q�����;u��������x�C� }����^��'�i�����oH�K/��*��lVE�����TV�Z���� �x42�xV5��a)����P/���f���*��onF����G�c�\z�Sa�@���QE���IN��r����C����O�ktD�����H��.���/��k�7-��&d]>!��B�W�"��Na���o�S���SH��SH���P�-l�,Pr�)H��(�?��%GfB�hDn���P�e��Bw���~)����b8��Sh�����K
�B8?�S����d�e!�T�)��j9�pV����(9�x��_s9
�������{)��>.eU�0H9�U_�������#u�B�i7���o�Ga���{�D~�C$��$�HH?�!���.����0��V!��
26�O�����o����oV@��v�o�h��0]�j�;�b#j!.�O��p�$�W��H�E��#G�5Pr�(C������E���7��|��;4�����'Y�(�6��o�Y:]�(��	�B�<�#3bA�}��� �9�B6��X`��e2��b�G#�� r�{.�a)��53��S�)� x��9 TVM�[)����jA��v�����>:����XPk6:�"�^u��4�n�;�=G�\�*ql������o4�����%(��D> ��ht	�3+���q	ap��0xZ������K`��KPd�%�9�����K��%�hD&?R��%4�
.��CWWR���-�m
<��;&=tue8?�MH���d�&d�*��pV����h�Ym#g�9r���F�M�g��M�Y�)1YAd�w�XE��U��
`8�v�D�`�hS�/a��\��I=\��#f�)(t���M�/����b{f����0�N�)|.�,}�]zYr!�{@.�_q����\H��
m���]�|^~r���?���o�����������?���W�����y����WE��[���o?�����-�Br��B����`[�W�mQ��w���������y�-��t`[���l#GMPr���8;� ��0��w�n��I�����-���]���&t��N�^�o[�mK6��m��T�-����`[�Yl�"7����j�KlK6��mQY��c9�U�&l�������RV������g�_�x�mQY�?xm�?gz78����s��������y�0�k��o��ZT0���r���y�����y0����<����1p"��@;G��9�v�/L���}xe:��i���W�?L��~�e���=�}pex��'\&��>�A����OP���E�	
l��}}p�/#�	���h�������H�	��2�����}c?9'*�'0��� �$���o�'�x?�}��|�+��J�F|����O��T�	���>!�U�'d�*��lVE�����9rs�LV���Y����>�g��IE������*�'�x[���OPY�x��'�?�Y����x�{���9�2�7���?n��h;����Kd� �Qq^s��4�4�^���#mq^q����K��o���v�%�=q���F
64�l�6gq���8�d�"�!89!�	��PqN��~�&_�K\�~u(�8���8�N����'���@�_��{��tF-q�N�%�9��A:��8�������� �UK��j����csY���9����	q��j����v_#�8P��D�S*����;�����
A�:���_�om��l���n�;xq�}��
��g@��a�/�8���mIqw	�P3]B<����O�w����KP�vw��%��5Gb�=�h�
������BA�m��������P`�M���#g�#':T�3B����y�U�2��3����17������BA�R������(�)�B6��P�&U
��
BA�}����/�Y�#':��j��?������(xV}�K��RV}�����������Xt���b�!(p{���A���"1f����]
������
F[�\7���c�L�TP�S�����
������_�=!.���}Wq�x����nG�p������'��LI�� ��O\['�m7#�w	��M ��I ��H�1�x��3}	};���4Xi�$����np�j�G�M�h�9B4��?�fQ��4
� �FQD�(��hEu@�s ����@���,pXH�N��B5����Xo"�'�t�_�)��bt!r��~4!��h�B����OB�G��� �5bf �H��@�;�@�;�>9��������}RJ ������^�_�������K��(��#93����kk�(4�&�1Jpw�Ai6~/�@���5��X�4���@�����	���*4��1y4����f��>P�����]'��f��P��d��A�����4
�A�}� ��;,AT��E�F���3i��k9h�pE� �h��`�4��a&�v�"�fi�W��a�;G&�u:�b��~��8�@c������F@2r�X� �/��/���\���WY�@>��n��,�k��c�_���<�~�E<C
L��\W
fD
�9[Qrm5 �v{f��;8��@��~3�C��~)���`kT��@ ���r���V������1���n�&�-����y�`�Ym��� �W�D+��lf[��h��mA4��-�fV�4��{u�����ps!��Dl��g6���3��@��&[ �#��g�P����8� �?�K!����q��3(�4�B:��k�fv��iR�
a�y��W� �K��`�;����>`��>P\��@q]}���>`��>P`[0pD0pD0pD�����>�Q����>`������@������?�sE�������h>����
� �VAd�*��lb}�����������������c����Y�}���8�2k�N���Y��`.����m����f��l��(�NR�b3l�c�g��.!�����q����?��V�����^�[v���?!��V�����"�oC��{GbX���a������NWd��J\�Aqm� ��J�O-��W	�Q	�Q	l���J�1�t"�(���%�[��t+�����T��/��l���,@%D�*��0xvsfTB4��J�fVP	���*!�YQ%D3+��Y�Ncc>!�ec��a!��3��Y������@��?�7���
a&�v�G�@����{��)	|���"���w9A��0���h�� ����^��=P+�����+�^����A�|�>�����8����?C�Q#�@pmo ��7\�n�p��o@�o@�o@����7�Q����7 ��	�~w�����Wu�chV��.����L�aM�(���A4��0�fT��
�@�}aM�(�)��H�~��qF���=�)�4��G�0�����9���A��s0�q���0����	�b�]o�����
�D�dA��@D�?���1��8���^�����h�0H�yX���_��.����
�������9b��������k�\�Bn��(X���XT`{�"�g��� ���E~3�FY�gc�AY���E�~q"
�F��d#y�o�����
��v���!�C�<pSi�y�fQ4"�5���y��Q4"�6?[�<pd��J���E�F��<���@������Q��G�F��
"�Z#�'b��N�!9"(�/F�B:��G�b>B|�c>B��A��������A��!N��`�K!N>/<�@�B�<��4���j�0#j@p�������
��E�?�@���4(p�A��8��@��9�@�/�-�:3b�'y�`�&��@��m�b��y�����@�}[��h��mA6��-�fV����� �Y�D3+��pfE[ 3�=b�gV�q�����SX��wce�)����7m%(���.���A���m�@D����u�&�:G�A�<�A�\� N���8�~3@�cQ� ����\��?�+��
endstream
endobj
8
0
obj
43500
endobj
9
0
obj
[
]
endobj
12
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
13
0
R
/Resources
14
0
R
/Annots
16
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
13
0
obj
<<
/Filter
/FlateDecode
/Length
15
0
R
>>
stream
x�����%I�6�D�	=]]}������{�
 Q#H�'A�E������f���+#��l��-n����#�?��������i�������~��?=������>���_�:�<��~@��w��W�x��O�0�5>���|w�#q�S������~��q1���C�>����"��������������?u�4mB�A�<��l��6y�������Q,�C(�Y�	1TB��
����o5�0k�=N��^���*!�q�BZ���xZ��'�Z/@�[
����B!�z�[
���j��|�����J�{\��V���N�>��C��P�V'L�I������o5p��^x��+� �o50TB��
����o5��i�=N��^���*!�q�BZ���x���'�Z/@�[
����B!�z�[
��j��������J�{\��V���Nxx��j�!_�(|���$�q�BZ�����X�����M
�j`����
i�k�j�Qc������������PH�^�V��wx<������5V�p�BZ���x�X���a�&�o5���z�+�����	���j�!_�����	Se���F!�z�[
<h����0v���*!�q�BZ���x�X���a�&�o5���z�+����������c7)|����;\��V���Nxzh����^,�I�0U&y�k���������~�nR�Vw�w�B!�z�[
<h����0v���*!�q�BZ���x�X���a�&�o5���z�+����������c7)|����;\��V���Nx~h����^,�I�0U&y�k���������~�nR�VC%�=�PH�^�V��w�?������J�{\��V����5V��x�I�[
<k���
����o5���z����M
�j�Uc�W(�U�}�^��=�|���nR$L�I������o5p��z������������PH�^�V��w�?������J�{\��V����5V��x�I�[
<k���
����o5���z����M
�j�Uc�W(�U�}�^��=�|���nR$L�I������o5���z��������P	y�+���������c7)|����W(�U�}����;<�nR�V/�w�B!�z�[�����X�1�k�X4v�b��r���J!�z�[
�
��G��(|���A{�q�BZ���x��wG��(|���Q[�q�BZ���x���G��(|����W(�U�}���Y[��t����x���W(�U�}�~>$V�0�k�Xf��"��T&y�k�����������q�����[�W(�U�}��������(v�o50TB��
����o5���V{<�n����J�{\��V���^;m���Q�6
�j���V{\��V���N�{j����^���b��M�I��*E��WQE�k��g9�J+�j�����w�B!�z�Nx�(��}9�J�^�V�w�B!�z�Nx�(��c9�J�^�VC%�=�PH�^A�^5
��\��������F��PH�^A�7�?5
z�Z/�o50U&y�k��W���{��;�,Vi�k�j�^��W(�U���	Ow�/Vi�k�j�I��W(�U���	/wx*Vi�k�jb����
i�+h����FA�!_�E�����$�q�BZ�
Z�p�;�~�����k5q�;��PH�^A�4V�pw�A�[M<h���
����:�Ic����������PH�^A�^4V��t�A�[M����B!�z�����X�1�k�X4v��Se���F!�z�N��X�����
�jb����
i�+hu�����c7(|����;\��V��V'<k����0v����x�X��
i�+hu�����c7(|����W(�U������=�|���n�`�L��(�U���	��w�y�A�[M�k���
����:�Qc�����������PH�^A��5V��x�A�[M<k���
����:�Uc�������P	y�+��W��
�O��C���Uc7�	0U&y�k��W���{��;�<�����&�J�{\��V��V'<j����0v����x�X��
i�+hu����c7(|����;\��V��Voxyh����^,��O��2�{\��V��V'�i����a��o5q��z�+��W�����;��nP�V�w�B!�z�Nx�X���a��o5���z�+��W�����;<�nP�V/�w�B!�z�����X�1�k�X4v��Se���F!�z�N��X�����
�j�Nc�W(�U���	�w�;�����&�J�{\��V��V'<i����0v����x�X��
i�+hu�����c7(|��W��;\��V��V����X�1�k�X5v��$l*7y����W����N{���(v�������W(�U���	������(v����x���W(�U���	������(v����x��W(�U���	������(v����x��W(�U���~>%V�0�k�XG��*��T&y�k��W����Y{���(v�������W(�U���	������(v����*!�q�BZ�
Z���j�=�b7)|���U[�q�BZ�
Z���!�z�!_���j/f���2�{\��V��V'�i����Q�&�o51TB��
����:�Ac�w���������PH�^A��4V��p�A�[M<i���
����:�Ec�O���������PH�^A�7��
e;�Z/���'���P��5
i�+hu�zC�W.=�V�v�&����vu[��W������=�\z&�z�ZM�7��q����U���	�
e{\��LZ����Xo(����my�^A�����r�����k5��P�����u�����.��u���~�i��a�$��d���U���	�s�$��UD��?�W.��?��_$L}���������|`}�i���=������!�N9���e�	�� �������_��,����0#&A�������<��){����X��B��u��u�nA�ce]����\���"������/0y�����9�^)�I)�
�I��`�>e3�<t7C6B`
s��Xf�%����R����,Ub�c��c��bV����t����� &�>dAS��������������,H�{|v�|(��p��p��`�C\������taS�2�����I�{�u�X�Y0h �q�g�����*��i
�����*�i�;jW ���nc�E�b��;��.{�h�+�}�W(0�� �qv�����=��	yP/�P�&O���]=T��/ \:%\�c��X;z>���A/�0�$�q����%��^X��<���������A�^����r����bz(�$]���g��y�DH���I0�!~s,�	'^z��K���W���Pv�F����mS������~.`lS �qv?��k��<��g�������4I�c�����o�v��v��A�c�=�g���\^�0y����[��w+)��@�0oO�k���n,_���_�7�w�
r��#�����9�tV�:����j!����h,������qC���<���l0TB�cGQ�>�@��(������/��">��;��;��A���n9����M~�o�t�0r"��8�����33�/R������n��H�$I�c%=bs_�]:�]�s���o���K�6��#O��Xy�]h��@�0�*H���]:5IP/������!�����;~X�"�������y���N�Q�{\�h�#��B�W|X=:%����4�	�aP�A�*�=~�6�MH�eR�eR��������Fn�A�OW��fC\Q|��b�U������1.I�h�I3�!V���5s�����2��K��A�$�q�]�z��"-C�7l4�������,Bx�Ny�^�����2B$ZF~�J��{��{A"���
��1���o3C��Zd�	g/����U������[u'y�=]�, ��P�Izy��I	��!������k���=��0�aP�A,�=&���Y������-J0����N'�n��Nh����Dm@�����S�1aS?��-Q�(H1�J1j���n��
R<�u����OA���:�i�R8+�X����=V�;���t��h� ���Z&}���g�i�uxvy� +��NO�,I��������"w=�=���=���\
����G�F`{jk�����e�2><�����+��X�Yh��@����������9������&��������a|��|��U�{�U��F�LJ�LJ0�!~�`'A^(��gC�����l~H7���z�{\��`?BBD�`ZC|��"C�He��'�����=��8�bC�e���w��I�+/�wqc`��)������Jz:�O^�~����=.�Z����`R�&������lb��'R����8��=RQ�n1N��g�nt	C��:�>�e��C	'�!�=�F{���;U?�!��633���aP�A�+�=4�^C�|��|����>�'��1!�1fp����e���1(�o������M�c�!�b�^`�Lk��q����t��t��A�cO���J8AXz�%ao��=Q�{\yS�(Q0B�{?a�L�g�}[�x��!��)������z��d�I��O�wJ��=V��}	X���0�M���z�2ak3�B�cGQ��b��-q����	�P���nz(�$����:q���/��<B�����Ni�5�E�����H�AIY���8X.����I��I5}������Ew��,c���V�< �u�����vWYq#R���i
��2��p��p�A���B���x*���{�
��h�{�=VJ|�&-�$R�'�)&I��XI�|8�Obe���b�{�^E+�6@� ���y������CG�AB
���!�P������1�
���n�"P}������z�.H;=�v��Q�c�=��
y����g\C�_%�����0(� �������
	���I�(����4������'0h ����I��x���Q��	y��b����v��\2����Z�h~�a<ry�{�0b!�h�7��;��z��~��8�;�#��)��}J�+��ubl��5��f�����|sV�~����{�l}[A>D�m�����u��l	�H�$y��\}�[LH��3�m�+6�{�h����d?�YD��P�I�
y��}�Ji�O*��������k�#����H8J8������&Ux�^y�Iy�Iy�>�u?�9��H�O�E�/c��\��@;�:J�4I������w<u%l<��2/��6�M�g��oI�c�i��6��&h��e�C�C���w���[�2g��C�$&A��8#<�
dAJO)������'h�}���Q&+0Y����z�c��\��������l�y���2y �q��jg7�g�L�-S?�=~����0��N�O�{\��2[�|Y��`���k���{�������s�Ly��3�3�J�LJ�L�~�C|f`����"3=�l$��"i)�t�����3y ���<�N�������Lk��YFVz��8G��=V��G<��p����q�K��������GtH���G��$�{�����+�,^��g�\�c����J<�8#xqG4��$��v�8�08��j�M<�����k38�ik������ �����<����f�����|O��4�Ne��������,���C�(1U�k����{�����j)���W���"��I��I�}������[�?�a�e��c�F��!>3���Y:�'����E�8�1:�w���;����t���P���:�{<���Wgd������(�+����
z��H	�=�Hk9N�	=�N:`�O�k���"��!w�@�c���'"R0b��v����������B��e'�=�!N%�������V�Of�=4O>`��KeD�aP�A(�=.sF��q������,C�"k=���q�{�Ei�1��u�qA�
 +0X �q����#�^`��@�c������<�%�|�'r��I��$�����
�s�T��XY����n�_���$y�3R�^��A�
����;����?'B�o|��:}���4!����������y���?'��P�IzHy����A
��DG����N��k��Y���A:J:�����Jz��J
�eR�eR������kN�t���^�`C|v��W������t��!���u�@����1��qV�Q�y�
�=�������/�Gp6y�!�L��=�O���f�����>�i�K���v/�{�y��!/����7�M����T)�"*��$y���(���'o��I���t��������,I�c�j%k�@���0��$}����� �0�m$M�H�5��Z��#��xY�������5��L��L�3�,�Zs@>�+~�/�#�v?��;�bJ�<I�����2bP�MO]F	��i�p��QV�a
������)�{���6��L�/3Ye)c�s;������f���/�q?�|p~�N����-`&K��XYO��OV���g�����B��Ay�a��"b(������C"d�xr�������/�L���O_��K<1����������Y���t�T��=��P��x*�0(� k����"���AL�Cb����cF;�,��i�d!�38���	L�i
��]�&�8+��]���e�Z�Md�c����9���#-I����ks���� �{����dZ:eZ�+��8c:�/BH�����=z��fF���������>}F^F�8F�<�{\�����Wi����j!����F!�qy@���bz(�$���{3����[�C{P��b7��O<C��20���L�������A'��I�(���E	�1�'G��t�N"0�C����r������i
qy�yz~������-�{����?��@1�{���$y��|b��B{����'Z�|c'L�$����Nn��)��������lr�����'�{����s���	��kG��L�����Q���n_�~���������J1Ig(������bBb���d��])�2�p�p��Iy��&Q�Z�2)�2)���x���-2�c���bQ���w��h�YW0x �q�7�"1&%R�,�*tA��2ipn�"X�YYG��=>���w���v��b�_x�7�Ct�h�3k�]�+C��7l,������.�H�]:�]�sI�cG{>����{�Ay6y�s���Z<��6L�I�cO��@���]����=�z��1mt����U��=��%�:�f�uz(�$����'���Q�c�����S�����Y��0(� ��{�+6�eR�eR�C���W��'-�75��,c��5s?��u�$L�$����eJ�P����I�;�sw��8+��}K�;��g_�G:p�������`������&�-#��&�{�h�j�p�q��AX �q�ZM�[$!"��I��=a����4	�)��b��x���N%3|p����;��'M �;=�w��R�c7���BP���,Tb�L���5F
����T)�q�T[��W�eR�eR���v���n���H�
��$�����
���n����9�'���/���#�r�R����z���E
������9�{��
�H��l8�,|�1�{��i�SGa��}8����9��y������K����
�g�~��X����^�|��Q�."V���=)��X��d���Yz9Y ����_�Z�XzGi ��~t�g���M��������dZX��$&���8�_e�bt��t���{��x2����CO��2���k�A����S	y����W+Yl���d&����
��=�������5�{����3���i�������L��������z0����{����b��7�E;y�3�7�B`e��s����=VV�SfsiiJ�=�o�	���}��-���'0��|�!�Nfja%�.��A��C
1h �q�d�r�pz(�$����gm����'!0	�5�n`3B���w�w�UKy��Z��
��.��.��}�����+�!L��2�����w����	����C����!
������I2�!V��M��@:�J:j� ��#�oR����
g�z&y�'=Vz�X1��^@Z`{GtqF[��0�������]F�����������oCF����+��-�SzeI��x�c�~l�����"�^@�{�sV����������<��g����d&�������}����z��4������i�qz��{�s������}��z���+��W'����v�����&�1��;OBV�W|@o�X6y�k^Bg���/O���v��v��%y�=�����Kw�O�Ay6y�s^���\+(6L�I�cOQ����n�	� �{��X�{��m~���M����y�D��w&�{\�<~y�b��b�������D'���
���`#\��8AA���C�$������"x�YyG��$������m^QO�o8��|�1�{�x���9E=wNR`{qr�#�]�%��s#]�g��8#���S1�������?�{��<�f��Q��m���db�=}�����z��<��x?��>��Q����C=�=v�<4R�H=�M^`{ir��f�S�b��b�����F�<��&�=�8�8��j�	�O���l�/�!�!]�q6�QUB�c]�>H�.�������a>@��=�N���&�����9��y'J��S�E�y��>����A�	:`{���=]�������%��W��������p������9����g6^�����������5:<�N���k����U`�N:�c�S���8X1���.�.�d(����
�^�i����c���
$����u>��E�9���_��E�/0y�5�e��'�8+��]���������p�c:�(�o�
�e�$��x���E�D�(�����!�9���,5�h�Ni��=zY��c��G��������c?�x^��&lo�!~��� �2^��z�Y���nx���(,^��V�)�=~�k�;=�w��Q��r�,$
�~Pw�r\C��v��x�AyY������Q�d���h�Ii�Ii�>�{[<U dh��������C���f����9��5���(~���5y��5��������{��G�"�<��5s+�a����=N�g�c�I��M��O�`�C��z��8��S�E{y��gG�(D�D�h�]��$I�c����	�@������xO��]�v+���=�W����b��>!�qy�XX��P�I�Dy�����L"d���S�q
qu��,���t��t��I�{\]��RR�[&�[&�?�!V�;�m/�4��uX!��Y�3�qV�Q
�=.v4�T�<�v��<4?������6y�!_e�e�$��W���d�����&zd�.��.��$�qNZ�?�':�j~��~�����l=���c�v��I���<��/]76�Ni��8���� 4���y]�I�cO�rRL���O���l�������g\#�e=5B|��0a$y��GlIHg��O�a���|�,A8�J8��%y��5>�o��k7�yW�4��=~�<�g��j�I�E��=m7�8#<e�t�z��x��=v�g�N�K��'z�'�{\�������^@��w;J�G{��w�s���������C�{|jA�]����2�������;��tAz:��>�o�y=�i��L$�=.���57�G37��%�Z��=�O�3'��2Il���!���.���4�E�y�3B����q���GOhK��XY�����AM�M��J�C��7�~����LR�������NDOc��C=�=v#y�t�G�����t���G��j������r\CP��I�Y��8������)[KB`{�lqe�R��(f� `{�lq����)���@�[�����Ig�'.�w��A�c�=}+�2���
goZA����@����%I�I��=V��3����4�E�y���(�B���/�
l��=C���J�!����$�=�2F��K@��=a!2
��K( �=.N�A� ��P�I:Jy��N��=IB`�k�a�h���Q,�Z(���c����l���!�t�1A7���y���c��o$/0y�5������iF��+���y�������@���h�G���������0����<#Y��i�9����p7���k4�E;y�3��o���z����
�3�����R�!A�2����������#����c�v����n_�2B
1h ���^�����F7I/)����iNg�N��3�!.�A�������,^�{����
	�I	�I	�>�owt�u����6�gC|jb�5+�;��������=J
`�����C"=j�����0����h�K���^���&�1���F�D�H�o�
�&�qN{.F��S�E���=��iy2bq31(�&����=�X���a�$y�����Q)�2ja3�d&y��]=H�'^�#����7�{�i�FYB>����%y�O/!� %d	A�cOmrH�LJ�L�r�#�����r��c��cQ�e�p��v��Xg]/	�%�{\O��D�0�����$����`������v%�{��G4�����9K�?�;Yh�@����W�C���
F�tJ�h� ��v�81����bIl��=C�����"^��X@��=aX!�H�aI���s�����'/6<�C�{t��"#���z�{\�f���H�AIY;���:��d�G�gcM�����V���HH��gcIy��M�.�N=/k���@�c���l����_�����0�	K���;]��-�*h��u�9���Gsr�$\:%\�_��X�y��������w��!v�{�k9�%Y�s%k��*Y�`xk��|�|�1�x�n�$�j����.Z�{��^�|�C�&��=..���%|�����d���%�2��A�Y�����������L��L�2�!>��E�����u�1���*C�f]:��:�����g?���L����$^?C�!�8+����������t�������aI�������G���
��	��ds�����G�v��v��A������)��>��$���(o�{@�������>���j�'���G�>�{��d��
t�����W�v���P�IzGy���3{��<9�O�e|�g�4��S�Y�d�0(� +���ykq�������,C��vb�(2r`�1��B������:	:�������egcQ����L�{\���O���������'�|��K�c����0$Z	|����K�cO{�� #]:%]�o����������b���������������F��{,���C�c���f�)��=>���Dg��
]����g{g�t�C�&�]����v����B�d��.�S�q
p����"�0(� �5�{\!-���W�eR�eR��p�7�-�<��pF�����AB���.�
�&�q�n����#7��6y�wtQ�"�8+��=��=�3wx�1�v����3`I��G��]-[g�T��O�^�C��G�83�u��u��A�����u������T��x�W�U!b�W����<��bJ��Q���:����8����k���]�����on�@��J1I�(�����z0�e���S�q
q�k9��duR������~e������C�7�������m��sy���SW��������<�{�����������4!���l��t�Y���_I��N~��#�~9$m��������~�_Ig��v�+o��3F9 m�����3��yr���"N�1i�����1��6^`���C��{�mfH�x'���Ey�����N�������l,��QS����QT�H����b)�qq,��W�eR�eR������=���
x����1�E�05��Yg]8�����"k�mfPJ�Z�o�J���e����X�YYG��=>��3�Kr�>�,����$��p���)9do��������Q(~���2��S�E�y���K�������#c��Z��'#D����Fy�OO#���7B`>���C|���H��S1 ��#��<��J1I�(�q�H���(k�"�����%�}����8Y�����Y��e������<Cb�{���!9�o���p��"�0>>����1[��u%��is����o�������fZC���b�����]���e��u�Z�~�Y��iI��ih��HdF�tJ��z�{������� ����M{�Xi�U�e��r�X ��~l�0�9�o��|�,�{�F��)C���b�@�c7�\@vQ~��z�,Q���CY'�-�=�n���cT�6�S������+8@;J;������Y��
�.��.��}�O�6�o�.%�C�Y��p��w��W@;�Z������?�a�+�������E�J�!�8+��=�����B�
�1 a�=���&�1�kG���@�h&Wd4���9m����J.��W������u�Xr��x6�M������c`����>�{�v78�(?��'�{��=�������O����Q"
i���N�]�{|rt-r�I~�K���k������SiY� ��$y���a���CN�g���,���e��@^9���,c��K8��t��!g�3�YWR����Z�����E��g4��SS��4$g%�oI�cGz����a^Yd��%a����=N��]CG�eh�"a{�o���L���)���������+F�vO$����!�HO%����	��}�����q��k�/�:����u4�i�j���M�.W�{,][,������s�$���P�I:Fy������D��]J����HZ8�2)�"�����H,0$^n
�Y��K��:y����b�������D�����N!�=~w|�;��;j� �q��H)|�����cyvr�?�,��5�$�q�|��!�`b������$�q��8s�'c����x��=v=,���t�����
gJ�/��3�����>�:�G{[z}9�o��|r�1�x?��]-F�y~#�����4������������V#!6 &���X�����X�IYY0��80��AO�cl�[2����z��Y'�^��C\d�%���� d,��3}�{#g%�k��XIO=����s�
?�7�G������<m=�EBD�+|s�3���5u=�d]:e]�[��x��j�����A�g����)C����A���I�>���y���(��*�c�������e��U�����F�O����t���V������	��g\C\�
oC��������,Q�{\f�-�.��.��}��c��{@�XZ`{�oq��T�1�YW0h �q��V.�^`E�+0Y�5�gfv�H:�J:j� ���x'+���v������I���x��P�`���}���bGQvu�= \:%\���8#,��\���Q�`J��=>�OF":�0a{������������=��
y����x-dq��k�+/�q�$z_z�62HT#��P�IzKy���o����N��k���[.h3�aP�A�.�=.r���w��w��g�C�V_]E]��,���!.���H;�2�+����A(+C�<�� �q�5
��M`ge�o���T��IPY��p��7y�!_��1:�i��iQ�I�c�T	_���q���A	6y����\))@���V�#\���O
���:AI����L���h-&p��M����~:�G�������uz(�$�������������E���`]V^���A�Y������B��+�2)�2)��G�����O���U,�����q�u"�;�*J�<I������&]G	�X�:J�WF�rP�X�YYG�[����We���bc�a��t|�,�{��S��F��A��O���C�Q�����K��	�9�$����v/�w��$y�O��st��X���!�>�n���N��.]?����w��:������9�5��u��:�k�3	L��3������y\g�G`�@�c7���HZ���pf�����^&�|4;��]�yp�@�����w$	i�z�����0��4
����J�{�cy��G���o����C�cG{�S��H���y�+�I���AL��3���so���u�Ay��OFX=4��,"�a�$�����Y�����$y�3��,��K���v�+��|$ii�z|�h�������'c��3�d����2mGi����y�1�n5�u:�4x�A�G�{�n�h��z���P'��7�4r��:��`�������f>�[�7�g������Q��O\8S���$����+��G%-]OD��}���J{<�4u=�H^`{2�b���8C����N-�=�5��u���A�������y�3�R�m�!rP��3��v�V�Yg<����5����d���6y�!���-������l�;�����K���v/�{|�����"8����l���[�[�����y�������5hi�Y]SI������G�����0	���~|�O�:��GD�Y�7�{|����Y�u����=�$���|l��6�e�����C�(*�
&��S�E�y�+}�=�b���y�!�(N��xaoy��@��J�h;��)��-�1��v�&�Ug
�o�k�+]���b]������b�}�Q�
g��>����V�v� /�=,2�8�=gd$\:%\�c���u���(yiiz4�x�����A��(`Tz4�*!���]�%�p�C���,2�8�Z�������=�a
���BKJ������$X�!��Z�45�Yg
*!�q���g2�Q+�7��_eH�����!��H�>�=v����
&SZ�dJ�C�C�1���!/V<x��5�1��x{ ��)��Sy����������&�{L��
R�:��P	y����M����n������7y�!��x�0p��r�86y�s��wLJk(I�0U&y���:
��!�?>t8����k�A��S�U�+�{|@��0��g�$������XxOY��*��N�'���\���	�-�s��a�0��S�E�y�3�w����y��N�g�+c�"�Q��&Q	y���
�)H^`��z��9�A�p�9������X���br�����}���~VZ���l8�4����=�:OW���v�6F��=v�A<0��S�E�y�3�sYGX�V�����}�Xy�x3ZX����WF����3��Kv�#��s��u�5���#�GgHL�������5��u�������Wk�6��$!��p�>����8$&A���F�L��S�E�y�3�S�Z�����n>}�8���v��8$������]j�
)����1��>���
:u4^���z�{|z9�8�����$X�!~w��b���xg�:�{\�:��V�l83m^���=����!!MY+m� �{�#�&��)��}����[����)kU��$y�O�%MUj�0a����=��'�i�ZGC:`�\r����p���W�H�{\Y+4U-�!0U����Vh�ZBc��N�=>9u4[���������6y�!_������u2�r���S�v4Z��1�E{��=���4.-�1�M������(xieZC�$�qm�h7Zc��e��������2��	���p4����HKb�p�9L���Q���l8�
^"��=~�O�A�3��S�EUB�cGqh$L����vm�3����
�^yawZ�B�{t��
����mbc�]G��HN^ZC�0�=>=�\�Z�b���,�=>5��utZ���,8���$�q�f"xi�Z�b<I�c���'���oC%��)������k}����~���v_�3�nxO*ya�Z�B�{�:l<IAS��S��=>=��1-\1�U'��X���f��U'�����y������3���#�u� �q� kO�����l8s�&�{<H)��YZ�V������C��'v��k-�1�E�y�]w����������v!�3�o2m[�l�6a�����
�]klH
l���!V����i�Zoc���+�=v��C
4y-�!)0I�g�3���qZ�T'F�/<��X���gk(`j��i�I@������t���j�����?qE�R$l|�!zT���:`��cqq�j�#�u��5a��1�!V��>iQ�qrb������'zl2�v�9
�=>9�\�Z	�a3��n3�#����)4�b�T��=�)t�
�!6���1*���{\�
J�|�b��]]�G���zV���<-�1�M���yi[(��uH&O���i��rmk����:�I���r=?e�o8[��=I��$_�Xe�W8Ha ]4�A��"i=�B^Z���<I�����OF{`D�����l	ip���������tF��T�,����?2��FF���y�u�|���@:���}��=���z-��p�m���I���T�R�6$-�^��&�{��G���akQ��.�;�{���J�����@F��=��_��g�2�����>�A�j���Gs�� ���=��E�O�U'�'��5��uS��%/}����3�s'��u���������d��h��S�I�$���x� M�*"���s�3Rx�8�cLK�L�v��w��K��b"�I�+��"��kE��&�+���n\��	@H'��EF��=�_�F��|���a
������uk�	��Z�g���&a�k�,2�Y���Q���l8�E���=�k�����-��-��gt���=q�����h������O-��B����C���!-PK�� �{�-���N(0�k���S�H��0��g��+(���,M��w�����UC�er�U�6l�y���������P$+Hi�Z*d$���9��G3�[���p�^%y�#��o�$��3J��{�+-Z���p��]Z�G8"�$�IG{��$S��{|����JF���%y�#�(kE[��$�%l��g��QD#�'��S�0Y�����x����l8��� �{�<[OCk�b(�5
s����{Q�e-�2�E�y���U?�IH[��(#H�W���i��`�Z5��	}���6h�Z
E:`�@a����%�n���m����\�|�I��k�������&mYK��n�I���'�h�Zq����qr����Q`�Z\E
`�L�g�
7[�z���h�	�=������T���$���8��7BX�R�v7D�J�h�ZHE
`�b��OU�&����;�5��� �h��v��3��,U�5�Yg	�.|�C����r�Q��6�Y2�bH��Rmr��%lUK�H
l@�!�Hk!�6��RF�h� �����N���J��4I��}/���!�Z��Hy�]?��y0e��"+�]{1��t7i�Z e��N'�=v��������P�r}�8X��p:k9����3��{����H�a�F��{���00����+��F�tJ�h����A?c�O:���6��M�c�����dG�MvG�
/v�E�������M�&������w��L�<I�c���A����M���pD�:��I�Y�,ajN��=�4e��h������$���VO�O������^�?�{����0����x��=v���IA��j/S��=�e�g,��Yk��b�l�!vCy����j�Y����1�A/�fn���0���+4��_ui�Z`f��g���|w���l7o�!>�?�S
�ch�0��H�'������pD���2�9�����`��]:�]�_��8�g5eNB�;���I�cG(�\X0(`����������D�}������C|z��xA������a
�[,g�Y�K+gx����������b���K9��7<X��m8�t^���=J�l����uld�:�g��@S��5�X�#��X;v�"+����t�x���n@�U�+�\+��������+��K[�J6�I���[�����Whk��[��5-+3�Y��Y�?]-�V�m8�P�r��=��,���iay��v�9�o�FI�tJ�hW ���8����4-�2�$�q�O\�Z�E
`�Qc����5��U��u�b�=Yji��(�]v���>��5,�Z�����W�O�C�|�7V��v�7a���=>�lI��t��h����9oiK

D���aP�����kgO�-lO��V�j����#J���.�&l<��������w��L�<I������N��$���x�g�k+�F��U���w]$y���8#�+��s�����02-|"/0o�H�g��]�Q���i��-�;��/9�������:��7�:��-z"
�=~w�p�k�y����g�����Kc�uV����>���A�i�d>�<��g��O���wP$y�;-/93�Ks�(�I�g���1�L���o�~A�c���Qh�C��R�X�h���nx��]�����aXC��{�i	Z4DZ`�
��w�K[��!�M��A$y�O����:h��3���I���l%�@��Hl�P�!v����(�N)��=�(�I���r`��'�{\����F��&	��.�W��4w�*2�I��
-W+��b�����:]g_s!--[���f}���3�����y�K=��q��}���_��\'�'�pf�8�y��rq�R��HL�I������F��t��hW �q���Y!/-Y���'�{�������j�&l�h�!���}����n-$2�$�qe��zQ���P��a
q}(��J�Y�����C\3�d1�m�7<x~�K�c���C/���/`��x�{z�H��S���M�c�-�mH���
g*��=~H����j�6l<�����o�@���
g�3�orH�I������?�����@�O2�E��;��_e���j����!�x�|�!�����=~w���l�x�y-����u�u�\j��5*���k�
����y�"��3��	g~�W$y��3?�&^��M�v�b�{�d��t��h� �q�{�$#�m<�V�R�g��`�x�Iy�K������b��Ix���$�{��:����	�5��>�64FH{���
�W�DC���lw�!��q�G�5R��pf�8`
y�G-�86x����##H�g�o|Xe�K���v�+���+��Tu-�]����}�?��EK	��������+�Fl�+�!vCy.����:����`XC\J��Tj����q0����?H�F������$��\�+�I9�Q��s������K�e�{��
�\�R���&l��!v�'6^.)��x����9�R��)�����;�\�Rb��v��3����	g�C`�k��iB���$l��y�M�c��48��Tn�{�c!
N�2� �{\�mGj02�
?�T��O�Za#�QI�EF��{����#��)��+ �{|~�h4���u�6�M�������2�Y�0����#�yO�.��G�>�L��t��������������|����j�F�tJ�0��'y�3�s���Sxi�R^��$y�O�,�Zj?����!>=�46���WY�{|��46)�0B`;��������##L�N��!>�v#���"��H����^k.$��e.e���y�3�7~b2^����<I�c�5���J�3�I�����C\ID7P���r$S��=�����H���������M��D���I�H��>C\K���d�N�=��r'������������I��QK(l����`�Rb��v(��\�M�j��t��A��bW�4p��x���/><��Z��.a;����u������z) �x���������$�]uZ!��~x�0i�RO�����Q���d��N,�=V��9��,U&	���x�~����?�AHg 5'�&�qN����5M�����K�I��h������d����H�IF��{�hO'��~A*O�'�{��{�c�W����e��������w��M�<I�c���t-)���%S�>#J�!�p�L����}����d����$����O��a�}���AG:8;�?G8�������h�Ni��������H6
���X8��d�Y�:��������c��H����hWIO�k��nV�W$�E�aG��>�@���B��3{�)�$�qw��e��%yiZ�c<I�����M.p-�1�E�y�]7�~8���c�'�{|��p���3��k7OD�����X�������5F��������X;vpo8MK��H
L���w
�yg�E`;d���2�4�������amO�'�J����TC���C����tK�t�v�gt�.���vZ`;O�q���l�0pF�Ix ������>��Al�����J�A��v�h��	y�u\O�=Hi�O�{���'3L(���:�T�5}�O�-mZ+�6l>����M�c��n�R������\��k�g����Q,�R$���I�cGq��%!�]k�� �{�#y|�����J����������k�xi�Z�d<I�c�=��o����������rh�Z�D
`�)�b��AR�+\��6l���9��G��:<���'�h5���*�:�I�;���-mC���f���L[�a�haZ����}�s�3�t�-a2�������B���SJ���&�$y���?�hUy6���`p�i##�u6���>��E�i:�����}�%Zv���N�0��G��$���fV�%cG',����5{n6��N�����g���{�q��`�Z�D������o@6:��>��$�����c��:���/`XC�/
(4/�"�]O�qq�>GheZ�d��N#�=>9��/�B�pf�v=��N����w;L��j-i �qF[���������!���IHk�����!>�?�u-@2�U��t��������G�~}��d�������f�=�{���TN?�rn�v6�#�I���l�
�H�Hlg��g�����$X��:������E�j^���|#��4I�����PFB���:�v����0~���uO����c�����p���4����8�^�]M#�}k�������n3�Y����C|f��E��j-��p�x�?�{<IeE�s�=�i��}��2�$������2��S�E�y�����9���k��$y�������P�������Z�G'�eP�?�{|���d���:����`XC��$xHA���'S�>C�];<�H+��'��u!��������������������O���=~�������������K����g�i=���n��?��o7��}������s����N{��o7��e#���6hd����F�Y���ld����F�Y���ld�����������4����g���Z��������I��F��
��gs�Y�v|�����������������>���?�c���?}���m�y�P�=��>��?^_������?��O���?�w�xO�<�����:����_/�]���������]��������C������%����8P|m �]?U���x+��P�����#F������m|���i-����?_S=|l �����[=�CE����v}��.e�|M��?Bi�.���9�����#������~���~�oz
���������������x��<���u���������k����N�;����`~�g]?�Z���
E�y��Gx��c,~�g�>v ?��v�<� ��}f�k����������p8���\�a\�x��=k7~|"�=�o�m�3L��3����@��kz��M�<����O�rY����������k�>}~���������>0?_��<���W5�Ku�\����A���E���3���L������j2�s}���������n>������~@��e�k��C���|-�e��@�-������~K'�^�SY:���9��������tB���tB���tB���tB8��^�e��p����2�tB�z���8�Y:!P�G�������F��W����6��I��o�#��N�<BAq{�V���n��y�^���nu�y�V���nu�y��R�M^�G���<��.5�#]��V.���V[���J����z�Oey�p��kY��m��E�#�����Lu��7��:�[�����.��9K��y�Ak#K��y�Ak���n����w=)1�����s�1������T�c��A����AAos����9}P���>���>((nO��I��I������p���FG�����}��[~3�����[���;K�T���/��7��I���b�����4O��nu�y��V����u�Y����������K��������<}Pp��eE�z�����p��lP}��^�8�R/.�a\>]������+O<�o�;ai�@��k�9m��_���Yk������ �{C�A8wM)����^k���DR�.�y$�t���-]p���`]\OD����6[��v���^
�6����w1���g\Y����%�����c�=�X�����(�S��k�,���#�Q��|����9�Q�{m���F�����|��((������A4(�T��{C�����?�o���Fh��7�.X^#P�}�_��fy�p��]�,���������i��q8�?7a��(��o�WI��������[}h��������[�h��(x��\��n4�e�h{.��F��������R���z���y��J!�n��"t���J7L�V������'����o���)x���`K`�r=��Fa�����?����r]��/�m��;V����%0�_�	�������{4�cu]\�J�j�[�[���{�>��i��.n��d��%x�qhLD:6�L���9���&Jz[�"��$J�����[����e�Y2 R��g$B���hk.r�To_�������M�"�+6R��Wi��+�����c�d@������%J��9p����:�,p���%o�����f���m>q������,[_�M�(���)����6��N����+�n�z�=K��F��!^}���X���H�z��7����������~���E��(i��h@:������������j�R��oN�]3���n_s<�p��`R�cK��%jM
:��(�mN
�6'
z����{���I�@������@���8��%�+P����X���B�
���@����dF�To���W'D��ju{Z�0�����,-*��e*����N4O7���F��@8��[Z�^G��nU��nu�yZ��H����{�����]����������^�7'OD�r-�tdi��m����7����[Z \}��gZ �{=���@��zZ7#�c���;!y���4��9�cq9�a���[�?�j��_�;WW������*Z6����h8�P���;J-��u�����lI��5gw"|�lRZ3��[2��������@Aosf ���;W�((n�����o9;)���Q��M���@���r�p���=�����[N<dy�p�n8x��B�����.��c\h�((n���D����^4��]{^�V7��
n��\ P����6����k�U7���e�	�'3:����<3��2WU[f��H�3��-3p���
��Js������^�907P��[K������@8�gJ-n?Cp�f
4_��Z~����Z��7[_V6p�hX���6[��f�����<?������w&FZo9Np�^��6�
z�����Q9p��,?(�'?(�'?(n�ig��@�MwD�i�!������B�,?��+?���-��,?*����Y(������>4���D����^4��]�q�[�h�(����@������m�[ ��?�'��@���'��=��@�
��g
n��J#�����dY�@����}��Kry�m������<P��\Aa
B�
��p�S������?�
�6�s��w��
4_�v����3���
�
��6,7pw��z��6�����<>5/K����g��Z������:�(I(�mN9�6�
z[�3�����F'K9_�X�!P|�N�<����[-�(�'���o���Q����H���DI�rT��)��������F�r�kiy�r����)�[}h�r����)�[�h�r���f)�[�h�r����)���ox��^7���n��)�,�Pt���r�r���[R����rK9T���K,�Pp����YAB��7�a���?�[�!�{�n���k������CA�
����|���H���q�
�,qw,Q�|CuBA�
�	wk����_�=q�����}�y] G0|x����A���AIok����5GP��Z����J���r���#�7V�A������#������Y� �[��q��)�H�-7�Y� ��
b�A��[�%Z��^��J��o9���f9��3Gp��AI��-��Jn��,!R�p��r%7�\��q�C�#�Tk���?p�\_��m�i������A�?��o,y�?G ]P

8vu����0���z�	�H��7<�X��UL���	�����n�^��_]�!�},�!�_�����5
�k�f��F����,A����,A���,AAos����9KP���%���%((n�����Y�@����<K(�'K�q���,K��-�F����?dY���\k�e	�����dD�%�k9��e	nu�y��V�g	nu�y��V/�g	�u�Y��V7�g	nu�y���F�F,�����,K��o
?�w5��a-�Y���6<18���g�%�i�Y�_7���%�����!;�/��?x[��b�kf� lq{Q��zy�!���0Bi��K
J���1���,GP�|��s����4_��a=����a9���rwk���3��r0|x� ��&
�w�rP��zbIos����9Q��������Y� P|O� P�k�~���{���(G����,Q����<e�(T��(�z+'�8$Y� T����K�((���D��>4O��D�D��^4O��F�D��n4O��F�DAh����7�|����r���H����<Q�s�s����P��D�Ns�(���DA8����%
���PL���^��i�����K!�rb��	
��J����2����\�mi�p$~����4�����	
���;(in?lP�|��K�=�&�[��	
����<M0wADl�1�zK����9MP���&(�mNz�I��	���	����~����7<���	Bk����	"��>B�4A�zK4?��u���<M*���������&��7�i�[�h�&����i�{�h�&����i�[�h�&����i��m?u��-O%�n�� �?p���J�&��-�;�Q������P�bi�p!�_Q�m�� �{=��4A!$^>#ai����4A��4[EAA�
���&�4���X�|CEAA��$�z0�7�
�n��
��l��������2~��8|�j�������F�4������DCAo������DAo�����[�F,)n�1R���
U��_��<�@��)T�����Q��n�H������D�����<��]'B��*����.4�@��C���N4�@��E���n4�@��h(����Kn������*��>Y��F��c�T�U�Pt����n��;
v�}"�cs��Q�_�U�@���D����f n�������20�P�7�
�o���f�Y������CA�����2��C��7�yp�([����a����l���-����w��1C��#CP��Z�P���!(�m�Q��������H�-5
�����@�����w�#�U��~B<�
b�D���,�A����m9��46���A��[KR�r�:�,GPR��#���f9�{�h�#���Z����9Gp�#�r%G�|�A���[�n�9G���r��?p���z���=�#�k�_
�e5�9��G��z�	�F,���{R� ^���b��K�Y�P���y�	ncg�y,x�!�{��|{H���\Ha�.���z��nK�H{��v�L���������J���A0]��w1�5]��%]P���.(�mN�6����
���H����B���]+(�7<I�%�1����'�Q���]�,To��<OD����,Y��M)���+�����<YPP��,������[�h�,���f��[�h�,(���dA����&]��}�y��Y�<]Pt�.�����.I��u���BG����t�Nst�����z���J
���~�����K��PC����Xo���%Sow�v�,)�[����ix�%�6_/)������wk���������GJ�/�,�����~0�Sn[S��;n?�Y��

z�S����p��H�W��^��
����)�~�W�*�M�z�B�*G����q���3K��h�;��8��%���p�o���\������~kY�Y���M�����<{p�_���:�<{p�g�������gm���Y�R��gm/5(z��g����*���a����gc��0��;8��w=����
�e��p!6G�#lsK	�0�(���c��c���7'����(	8\�?7�t�������R	�k���	�
�oH%�=�J�[��
�oxoa�����z�b�������������TBAos*!�{O*���=�(���B�����@�=U��r�b<��\c����Z�JT7�Xu��Vupq�dy�P��7�����qu{?���=y�[�h�7����y�{�h�7((n���F��A��6_�Xr�Wr��A����
����0y� t����n��t��;�?����Q��'�{q}��� ������JB���+0�p�^K!"�
��_.����[�e
n�<WW���3����3(h���BA���}07R(hn�Q������/w�.;������������o����������y~<���Z�?�cE?�X�g��-�k���,s������b��2'��^���2'��_.��g��@oC	����W8
g	�n����r�_7/��-�/yG���b�����3R���~i�}����q�Z������)�����s:����fY�P��-��,�RP�P�eUnu�yV�V��gUnu�yV�V�gU
.��P|���b�g�������v������\����T��v���v�����^X��J�{��K	�C����){9�r��?!���7���:#\���L��z/?�`i����k �1������cag;�n��Vnns�����r��c��bK�4��Z)hnx��j���L]_���7a|,����_*z/�a�<��
w���G�t��G(��N-������"����-���������@4l�,���>���(�G�To?k]}w�y�H��-O`�>>�����B8���_��,��������A����a��AI����Y�;()o8d��{]j�;���f��{�j�;���f�������n����re�zqh���[m�
"��Vw�����k���Y���Z���n�����p�V�5�0()����%��?,a�����Z� �{}c����zQ��m�
"���7 �.(i���`�����)����
K�Z|}S������"�o�Z���w-��1Y��~���e�`x�7����@�-�����dA���dA���dA4g�?��dA8�_��d��@�����-`�,ToOy]������?���f��U������� ���c��*�>��^i_���6T4X�����i�,q*�������'n��y��V�'n��y� 4���.K]ls�A�b����'B{=A�'���v��Y����Z���A��[������~k��������^�'
��[e�8���{ �u�^i�����-�X\/"�Z����Z�����Au��q�=�v����z
�t�2��n�8X��H�>�>W�
��[W\�>�^?���A���+������C���C(�m�!���~p!�{K!����X�C���-9�@����$,���r��r�H_</8������y� T��y��Y�����E�,o*o�L�����������_���.��c\j�7����y��Sm���U��A���<X�7����[�,o��{��[m(����[���*��	�z�������A�	��[�Zp�V��Y������a�����3oP���G�mn�+[����z��E�X\/:��������=�7(hnx�����/���
y�������2��3��w���7��F��A��r������oSfy���~n�Zo��6�
���z�bdy�@o�/�Y� ��x�7�W����,o�n�a,��#���U����o�='u�\��B����d9������!�7��d9�P�]9�[�k�C����9�[l�C(x��B����d9�p(~��+~�C(���������km��B��>/<8���7Tw������'�P�S
�#�C�p�#K'�_�y:���b���	���\����5�dB8-i
�!4_K'�cqu��!�z/?%b���H��$y���M��������z�����w��s�Uw�]~��Y�V�6��������i��~��?/(�����^���!7Q����������r��;.c��~k�D��XD��j���G�z�k�����
�8��.f��{����E<��?e��,"�6�J���W��_?]5_�+����Kk�!�cy�{]i��()n�x��L�/^���fy����=gQr���ewzU�\���4G��(����0����j{�"���>/{�"v�
����6���C��6�%j����Ci�[�����Z��4���,�4��}�]3�J�/?�����m����m�*��5�������������e�|��~���^g>bq�f&�a��5Y�lx�������hn(d���Q�����������Wl���p���Y� ����dA8�
#�%����j�%���<��%�~��8 �sNu{��C�_����R��hO����\q�%
��=qp�_����8(x����k�|��ZQ������{n�8�����������mdi����4�H��0�DQ$���
���_��k��������A�Y|�)fUfGE����Q�����V���Z����-�c9����9�Dd�:B
AD�~�'h���A�CC������xQ}�m���H�i|��������V���@ �u����K=�#� �|Y�A�B�i�R�v��������3�j pm���F���h��p3�;��Z�x����h������P��v��Q= �/�HP������4��P�Q\��P=���o}P�a��h\E� XQ=�FVTDhm�z@�2�����,�z��P;��4�:��sQ������V#�O"���D��(�Rf"���@m�wQ�k6�
�~@W��+����QP���G���>��BxACH[�4�8�ea�N
*^�
Bz�� ��������@�]jDF���@��n$	��fd���(#P?�%#P#�*AF�v���F�@��n��A�t_
���z�����p�d�U@F�G1%#�s���
�(#D�*����2������
� #DC+����2��~��Q
2��Mh��&�{���@Ck��-���u{��-#����	��0Y�CF��o'���@�������+.A 
��%#��k��v[DH�xtP�xtPH�^�.P� ��	*%!�w�$�02J�������F��-!���@p#�7#!���]$j�L5���?��Q
��:U� !�M4f��@�wN����It77&jK�(Z�1AB����������(!D+J"�v$JB���D ����H2���2�v�
�����3�$Z����sQ��;rtgK�Ehm7@�$�����D�����%!�c���}�g��c���:�����������% ��r[�(!le�C��<���+!lg�C�
��v.!�|Z�������>�2��g���\������m�H1	
�w�*u��&�L2�DKF��u��{��:�-�6J0�:���d!u�A��:mu�Ao�9�N�MtJ0�f�;��Z2���}j^
K���+�Oe)�l*V)�P
�D6��"�
��Hd�)(�����	NmEB�S�%��vKFN�:J)<�n�:�v�6�E8m��c1�J�P��?�	du�7N&��uEY�"��<�2�C���r����SK�b��[*(K�-�/C������r�<�ea�l�<�ia��
i�!\�sw��T@0#R��u�
�7Q�p��6�
p��[8R�����v6,
R�vvQ*������A* �;����p�2j!�Q�R_@6��N�z�
�ae�h\E� XQ6�FV�
��d�hhE�@�V;�A�V�B������\��:�� �M���(����\����gR����"k?������0%2p��+�~@��$������V�u��b�2��|9���~����V
By�B�mQ�A�\�~�F.� �|Z���~>C?8��4]��`F��k�7�j@p�7R��3���s���5r�;���FR��Fr����n�a���i�����Z2���T��~ ��q�� VQ?��U����Y}�@��f�������v/Z}�@�V_?��5�K�o��|X�FF���us�$�~ "k�K
�����H�@��OF��� �~���"�<C���� �?�
�@��B*�v�������V��9q��������!��QB�����3���7�d�%#C�����i7��@p32����?�9��@��IC ��4���-��MFh�����U�(#���T��� �y�%c6�����(#D+�"��-Uh��ph�2��2����@����Ck����vKFZ��%#,F���2������(#�D�.�HC��o_oG?����L��$jc���$���SP�	A w��!�@B�� "��?��?2�\"B����~?�42���;h�-#C����nDF ��l���f �������jj�m_����l@F �7�y)�n����@�C"����dzWN?��9�3��
�(#D�*�"�6=d�hdEA�V{���2�6��AF�V6Z7�� C�/#����4�w��Bh5n�%#,F�g#���@O���3|�dq��N6�$#�����@��d9�\���vP��z��!k���������kc�����No��1��S"�@d"��<�C��\Bz�%!���q���N����u�����-��y��z����[��	?��m�H1Z��u�<r���7�����'r�����
�������ma�OJ�`��oJn�`������o����	mH�v�����s�og�5��������������������JSZG6�����m�#XA��FV�:Thm�����Z�}���C���1ZA���u��hJ����+I��GmcN�a!��9�uc�c�c.���-~T�����n>Uy���v(��&1�
�_y1�
���0'�v�wp�&���9�'�O�H��R<�'���5�.�����%�'���
�#n��w�m<���=�� ��� p�l	j�@����R��fj��QQ
�EdP�^�PA �#���}��1��|wBP����B����� �s���@���<����� ���������� D+*"���*���.�Ck�Ec)�F�(4�fPhh��PA��u�W���u"_��?����Bh����� Bk?n���Y��6
��
�� ���� d�w?,��x���|	���T�~�Ez�� ��KA�]���G�Dy^(d�dytoPSC8�?���@0#���5��B ���
t��w-��!�I��!P[��}���U@C �g�!h����
��c� hz���
�B;	�!�s��T��p�jEY���B4��� ��!D#+j"������'h2��$xh��_�AC����>�E�[\����z!�:�<��_?q��v�s���"�A �7����cVVa�T{����F����k:�� 6�?�b�"d��������� ��$d����������V����^s)	���JBz��$��F)	�5W>BZ8\���{h�$C�
����M�p`���j���@m���QX@P �gv!
����A�����	A�@��W�
z�_5
�\�^���6 (��'��PP��U�qX}A!YQP���)���dh�j�����WEA��V�4�_&/4z>6}���Z����D����� �
m��c��/cF		��c'%H��R����RBz��� �i	��,�����AL���������F_��X81!��%&��O;(n#��p9����d�1A��b��T8���@p3�	��>4�	��
z���f���YQb�~qnD &����H|(�K�wN���/=|ON?�	�����;pFy��5AN�V����Z�.	���r����������P���/'����hp5��AN��u��9��G�X�Fe��bp���A*?a)���&�a1�:%eP� lHV����������������JT���� v.P�Fm!�<���9m!�<���W-.;HT�1���k.mA����t�������������5��w������M9�/XH\S������h�Hq���XP��@���p"�A��e��

}�+���\!,md���������%���I#,x��?��+V�+�a!���n�C��,���Z���pl-�"\�\���C����+f�k�
=�
\�^�C��	��t�!W���������Y�![�!�,�KG!��7��;PH!p�B���bf?H��\�)�A"��Vng�L��\���Q"�o������D��:����N��<�@>-xv_��i���� .��u�Q�� 0�)7����&F`R`�Qj���tT��wF��R�CrQA �/NM9(t�)�� �m|�>|�L�F���#��@���A@A��kG�!XQA�FVT��[��\�!�����a����\�������U
��1,\�R��bp5�#����.����y�~>��t�G%l'E`?]/�V�e@�Ik���?i
�Hk�<w�{)p�i�%�wn�4��K4��	C4�L�
��%���(�@ �SG���8��
>���AW6 ��|g�
�-��l@p})��lA6 �F�;�
��3�5rF6 ��Y��WH�
���b��
�G��(�m|��.�lp�O�`m<��l@���8�'C|�����������/D#+���������l �k���e!������4����|�������l@-��$�[�����y��
X?y5���Rf�_S�A�?k�����
��n�=
B~2���os+��[����v�A%H�`�F��\�ad�r@G� ��.���vi�D6&J~��<���Y����f�qA�������^����@��)j$1A��
�B@a ����fp���@-l��Aa�Fv�9��@�o
C�cd)���f��0�W����OyG���M\x	(�W�
�v�{@a�VT��Z��[}�AW?1��e��AWwR��r�����Php��m
����������c�
�N����b��+(���S���O��1��G��@nk�2��\y
���9r����������������x��_���%7�	�
���q�
��r�@n�� ����R���,�����5�����HQ���u���Pn��#��(8R��-Q��#������b��e�o��QM1���OFz5(��R��XWP8x��!XAY�FVP����lleAW[YP���`0�\�������,���5�"Nsq;�,0��q����^��������aPa���RT��sSJaP��'*��o���py��.�Or?7b���+�[;�q���,a�v�=��0���1��s�T�r�������}9A!�r�B��E�v���v�"���Wc��������qm�vd�nkG��P)��R�DkG��h��p#��q���Z���	U
j��*��?pK����@�����t������>�JA����*�8�F�	����*E4��J
��R���<��Rd�+����*E8��JA�l����W�T
ji� �R���@\���rl���q[;�����Dub&��=����2��o�8�W��;��,���P����P��^��"�|�������
�����A�����'��W����+u"m��q~D�m"l��\9�����~ pm��� ��@p#Y7���g�����8����
��=���~qz��~@7�hG	���'g#A?�gY����W����(��I�� XQ?�FV�����hlE� \A?�.�����������j\�A?����MF��W����\#�U��;9�"��EA4����q�|�Ia_��<�S���B�����!�G��Z���A!�o���#��?"�{�����5��G�X8�,I[m!���r�_[I�y(	W�}�it��Q��$���@p�nFI`�!�$PGz=r#g��1����@�o�MhP�&7YP�6>9
(	w������b�L�%��;�e�$D+*	���J��v'[}%A���%!\QI�66��AIWThp5R3@I������$�����:1,��'CHEQa&�u3��_����8��^�|c����"�Of�R�8� qb�2����
�p���o��Vl4~�=$��	���� ��-����<$��r�[�aa�>
����$�����5z�C�jDW���@��n$C��ft�������+P#�;J��@�o�����@�t��9�
t#�6>9��+��������@���u
��P�V���u�hhE]A��n�D�
��
�u�D���~����a�zx���������t�srX��\KD�38�� b^���q��v%&����ab���~J�h�G�
Y[TJBz���@Wl�����(l�=��Sy�b���C?�� �|Y��@��������o�~��?1~`�5�(\W?`�	���&���pdB�p$/�9����C��t�C���%��6���{p���������P^_;nT�A6��~����dC+���
��
��J����nc#���ne��}.n�*l���~��������\wF���b^3���"�t���L�N�
ByRr_A�2��CC�[c� ��G���k�h��?�����s�g h��*
�?c��������}!n�� (�n���������_~����������?�������������.�����<��O�o�/����������ia\N������|<��\]r��,�j���@%������}~_��0�y�������z�8�<"�I�������S>�?����W�K��2�(���	�����N��;�A��4������������������t��:������Hme�t'�H]��d:a�~���ezk����s�:�7���e�8��y��f+�����x0������1l^���y/�|k%�����	2��<�_y�bg��������}�����Cp������^>t".����A?.��m�"9��p����WX+�>}K�)N�����u�����zm�"��6:g�����X����Hd}|�<�|^��,����ZL/�<�����L�:����s����?��]y�;��i���t�w^|���8���(���@L��g��	���?�Av�)a?m����(�Gm�Ng,�Gq�����"���x������f{���]�l�@���^�����;�7{�����I*�<������;8�=
��P`{t3�F�~d{|����'��	
lO:O����w�������D�8���+�lO8O���lO8��IlOl���l���U�U��������$������P�(n�d�zY����|�x��]�����|<����y#�h6	�Ga���=�|���h�k�=�5#���^.H������d����������d����&e@����dOlg��	{'�=�<�����FNd���dOX����dO8��������4��;�-�=��V����I�w�,9 {7 ��-Q�^y>j������',x������~Rw����
��2��,��qcl����{��!���������_�)HE��f��E�8�����v |�y�#������~��;�����r�'���2w'u�&|�y��E��f���)�y
�i����rCN��M�N����p��^� {a����O��{
���{8?�x�p���/������o���7b�����c>�$�-��1�	%�^;�$J�1Z?^�/?�������2<rKj��|����%_}�6�nI���(�FnI�WNDU���O�C�>�<S�T��<S�T[X��w9�S���9�SEDF�T���.-<���'��rN�T���9����
�o
�_�$4��\�� [�sa��-�V�#_����#�x$��l�����H	����AZH�C��z�$���(l��*�\��[�pA��[#�� ��[[�.�,.H�7!�Q:O�����oV�O:����v�g�����o�y��`�<F�,�|t3�FwC�|3�c������ ;z�`|��'����<�ia��/m��|i��|ak�w�M2�G@So�z�/��G��F+^�|�Fnzwr�|����;�|���D����~���I�|t3�NQ,p>
��f�����dO�������'������Q�1J��vf�\��������	�1������2�l���8������:t�8�`}9����������� '���qG�H��`�6����Kp�$�>
�!}�_����@��*6$}zk�������OU���/5��a#����7�)QL�����G�7Fb���!�����#���������H��7�Gjro�������p$��<pA
��������r��dp���L#�#����
���F.F(��7`�o��a�l���CGd@n���0B���#�Gf��*�G^����Y��
��u�|��r�M����#�X���
���f���lF�w�`�s�d3B�H[��50�9G���#��{V_����N|�oe"P!��`|����'>G|0n���k|0�������W������|�������c��������� Hd�zm<�"�$�7>��!]�s��O���0��.���O��v
��'�v1N
�2��A
���TW^F�I����)}��A�>e����hn�'�8��q����I��h���S8R?��p�M�C�T����S �����q����!'f�p\������f���7���7������I%4���3�#�U�0��qe"x��O��j�M"����#$��bb-���2� ������(��Z���I���I?�6�)�'��Z�lm�C���O�D�'��������\[Z�i�3�
�
���<Qt�G�/�<�Av��������E�r��	�����_z�F���
�w~���"��A���@��O��x@�w������+�?j�[/5������s������l$|�LQ�'��'���|���#��X����P�:��PY��9����\H����NT�(�1�3��&���8� q���,����5��}�v|������\�_����L4����# �^M]�2h�e!+[��^@���#E(<F��f:]m����JQ?�<v�v;�P�������c4|,��l�O�������O9O��
P?�<}]��:)�^���<Q����DC������B����������<�e��>�K�g�~��m�`C�'��j���������@{��E�����?H�(�������<��o���cG�G�7��"�;R��� ������+�G��x8�j�{h&�o�jeyc[��8Rs<�@�HNs����n���@����y�A���
�>Y���r���Zq��	L[�H`�H`x�>.�?WS����x�=��o��'����>��s5Cm��\��W%~�K��������{������k��6�b��h�.�r�]���<���@�1�8���J���b�|k���/yP�)���B�]������]�ukU��FC��S7�p�6��,������R��~�_�mS����2�����k����C�v<��o~��om?��]8hk��E[��������m1�(r[���U����Z<~��
$�}>��%[��,��6�2�#�k�U�av�[���<k������������o�V���(��qN��	������te��{�m��d�6�v������D�{�m�Q����6�G"�n������1���I��t0�f���l�K�+�3��0�����������9n�D��~����;��96����P;��P���Q��>4P;�6��H��-��.R;��4���v�>��Q��}��8%������n����KG��Q�]�������X����1*�uC�j'���Q|�?�����I����y:P;�m�����J�]~�C�K#W��@���\��_������"x��B���>8e�<�ay|������u���35X�vz��c�;'i�X�����(�'�t��q����)��Y��w`�]�m��q�1n����4���i��[Y�m�?`��s[�����,�����?�N!���
���W</��������6�|Y���^�>������M��T#�
�v*/��Q��s�0r���A�>[v���9}���Q[�-����e��lO��~N*�=�jP�b{�m��v���lO�MwFJ�=�6vzw�~�dd{�m2lO������p�SM�=�a{�o&���O���-?~~'��-��	d��$���z���&]��_��x�p��_cK>?�T?7����0\���a���*�����X��"�$��m�� �$�k�-
�$����$�~��n~�IR[����=&��;O��$�)1N��z}��=�E�8F:�J�B�K1w!�o#�J������)_�,�*)��i!
�R�P����>������cp���x��`�~(��5
��=8�@p�4�x)��b���R<����`��}��
���}H�/5���
��@���	�-���}z�t�Gm�r:����[c��>
n���z*���	Q��]�����zz�?�z�m"�H�����8��v�
�x�.�b'��(���7��@��Q��1�>���G���^��� 
���|���������#���b���H�(t���v"#�#�������o��f��<j�TZ �:�0���SbpH�y�#��m��E�(t�����Q}4���1=hu�h�p���u��M����S�M�<���:�G4O ��
��8h=�~����K�_������	���xz�\��F�_�1��������1h�p=��C�c��6Q\���z�+�'��C��q�g�Fq=nq��)��^��r�5E��i��s]��](� �\�9!�)��o�S��_%S��c'�~�Vv������}qO!�[�M��
��'O��������;���S�	�w)�GP��z����}�����^u����R@}K\��j��zgT� ���Q@�U��;�/����J��/yP�[����x��'������t���Q�1�O�}�m��y�d��FCH�f���d�O����W7�����9Q��}�O!�9|�5�K#��#_����O�����|���bj�1o�=,��
a�nm�L���>�M�������!�$�c��&	���Gl��z��Y��o���V�_`�����Ej����.���]�����P���%��-��Y
r�7���3�R��YN��b'*�r?������~���,�+.f)��R�ia��) ��Q�2��b�a;�w��a��6�t�F�R>
��|:��L�7�V���@���$�|��kC�D�G����P>qJ"�e�U2(��c���q2b"u!c�P>��fB�G]�y�>������O��6Q"�\�5P�
�/�/��O$��Hm�P���_��`F��h0���+��^q��4r�=������]��AfD���}��G��z8&�)�G���w�}zg4/C�Gm}{��)��
yq�!�}�+#R�_�P`�/7N��>�BF��>�B�#2u!C��7�B>��q!�fDZc�\I};"�	d�fd�����O���q��~_�������mZ\T0}L�
��!�����"��&>x��{�>��i0��Cu����|�A���������DBq���t��Sb����Y�DB��H��v��W����q��$r�1Hqq@�6�����m�)���)��S����0
�]31�{�!q�{���DB��?�*�v��P���/n�A���H��&�P#o�8�#�CG�?a�v�C�G������
�����8p=
�bh��xD�Snc���nc���n�-�-�G�&R4����
\�����~�<�C=b8��������)��(�S�1��@�{�(�>�l/m�b{ik�K���^z���3w�~������7��������������������������������������W>.�?�������M?��o��'�nxo����z�(�G��n:d�ze$>!�%���{�=8�A��������_���c���w9���oOwv����� �n���E0��T6����s"O�y�=��K���v,v���y�}�s��<����e���fQ��oh�<�n��2�K�O��yK�n��&�z%�d<2d'�r�`���J;e<��3�>�aK�|��z�wx��~�����y����y�;�ug�}�A��D'�y��[��1���y����w�~�?��w����2�q@������@�������m���N'�|��|��#�|���'n�GF2P>�GFP>jmg�;R>
���x���_%����;/U����r�9q���|�o�G.�3�<������eOF=r�W\�����~�}lJQ?���@����e53h����A�8(E����F�H|��7��Nh���N���{|�{]29���7���{�y�#����cO���������ctt,����P=���z�8�����S��T�O9R`8p?�H}�����������&�>����)�1�;1��%���W���3���%�s��D��M�_x���eq!���������
�~����_wt��hg~(R?jkO�;���jP?
�3��������=��������I���_�y��I���k��f8�6rJ������#��<���{��y#�'����}���W#������������!|��nw}qK�/�{C��b}q[��+n}@�>��P��X�� P>�R��1"c�t��Q[���x=��c3������w���#�����H:��(�����������'L ��~������I�l��g�"�~d�����~r���ct�G7�V��������+�{��������f(�'8�mz����)wT�����7��0�P�����	�?���:
]�+>^�b���t���}w�������p�r�d�#�$�+#!�$�k�����@����v�r��9\N�#��G�����NQd����������l|��f�
��0A��|�M �|B�P�:�������Pv�l�P�����J��PSC���
(��#�-t�#�PN��OF�R�Grsv"��oe��Z!��$a[����E	�i�b�i+��Z��fx���c�R�2P��� ��U@�b�A�6JB���{��[(l�����Q�������[���@�o���9r?
���t�Gm�y`�����R����hU�O:�]K����|��pg�y|�c��P|O8��}���0������?����'�Gw6B���SG!����(�� GR����4r�����~��2 �dR����� ��=���B��u�3SP����E��p2������f@����C��Y�o�d��q	����=g���3�<.��c��A��$�(�:��a(�g�������G����C�lgR�@II~��{�ia������=��`g{TJ��?���Q)@�(l�����@g�?
��v����������)Y�G�w�(	 ~t+3���L�??
�q���������Q��O:���+�����'����r�;��s�?�<��#���O=@�'�'PI,L�"�m��k�y�������-��������\�/�\�/l
$~�a)@��o��	?�R��1�i-H�t��W�ze|^��Q��S�
��n������n��������o��H����A2@�����O:O�@��������O8O��X:ObR�t���0���|�y����#��b�}��H(n��D��
�O �-d��(��^q��������\�/���������B�d
�7�IV9	Ev�I(����$��EDD�)'���{���rK~'�,����"�1���V�/:�$�����d�@,ZI�W�|�R��;�OX��'�R�Q����~����*��t��8w�����S8R���S8����4��+�K�b�@��JGYO��]���{	]QX"�������&m�"�i[�#x��&���P�$�@;YPH	���1�$�@;-^QP��^9����Q����������t�����\;����(�����O!����#�q�~x�y|A�:�q�Aq�y�B�<F�=�<�wd{3��?�{��hh/����Q�9��G�b�8�@68���	r�l$���|i��|���8��[~&	
��0�P� �v2���1��36�8���h�����}���Vn#3��f�� ����H��������u�3�cs>�<��[�|�y"���y"���y}b��8CNN����\��&O����'��G�8_yp�<�ia��}������#����J_��1�D�&&S�����IB�Cr��p[;
(R?
n5��G�2�?�7s���~|���~�yl��[<R1���IX��Q�y�o$P?�<��G�wNE�~�y^�������%��N
R?�<F?�������|+q?��'~��n�E���(��F.���r��������������$6T/���W�}��F1:T6�m���;�f#��[�d�#���i���G�7�i�t��I��i�t�����}a�A�'�����O8�!:��c�W�G73�����_���`[����A����}�o���/���}i;O���'�H_��������xz"CHZ������m����_����{4Am�\c��5����r"5&�G�	�~�RS�62�.��U������Y[�hiS�Z*���@K)�3�i�������Kn��R�j���H�t�{a�m����h+��������
��o$Rq����HH����4�N�*��]f�I��(�Xq��
���t�m�O:����_f?o�l��������#�}���-�h���@�*/��5zmDN$x��e����Y[��I$xb7��p<
�u&������e x�m�<C�6]�"x�HJ�'�����I����n���l x��+c�2��qg�H��f�L�<��L���A�Dd���)n.� w�~EIx�E��.r��D����'y��!��b&����������wzm�M�wz�<,�gmm�P(z��11|X�o��)E�8��5!x��6]ap�;�6���wz�z.z����^=��v�n��A���D���m\}�.;��lo��i~��Fx�w;�����Ge�lO���~	�B�[���<hwF_��[y��42d���G���������h!����>4p=�6�$�����S�l�<k���6�-�6��S�z��QS��	p�F��p�n]oq=�6����WNi9p=�6�61�����E���������m�_����/������6}���6^G� �J?}P���!���[m��C�S�7y0n��<�\��y�#�;��#��G�G�V����Q_�<��?�y��|	y��9����6�z<���dr����
</�6������a���O��m���y�m|M�����x�p��P9��_D�G�_��9��(v�-Ly0=�`z����M/m��zi��z��m�'V��=^?]���|���}c����9]���E3R���T	$�6���@����	$���FI���% �b�9�f�@R��7�~�m������:�6���t�@��P�� �@J��{I�m�[	�p�]��x�m���&�A��G�I([i�G�b��8n����OL�PH��up��yY�����F��R�`f4B�X�v �#���R<��B�G��G-�xz�p�xt�>H�(��F�n'��_�.��%������t�cQ<
md��n�@�'�����(u#](�p�~�"R<�6���H����	��Q���[�����:8n��T��q������_.rz����+�+x��X�����[�qx�
	��b&��m��r��#�~��:��A;�G��1��������c w|��(r��_6S�N��]���xf�N�;�;�6�" w�m���"w�m���E��6n���t���$��q�W#�����;�9���~`�h��.9O��6r^y�y
������Q8^���-:�����v����GpHHQ?���~t�]�C��!�#�kcTR?}�~��-��k��^[eE���v�P?
�jX��p��	{F+��x��n�����n�OA�G����'��_@��O�M����O���H8����U����I�������K���^����+��^sq�4rq�02r���d��z5�����\�B�?�����3\�@�d>���mm�`���N�W�z�����\/�6�������z����8s���I���y�����p�M�w�:��f	��Dp�'m���F�Tq=���y(�~W����_��F�=�P�r�G^e�b{a�������U�q8���_cL�f�Cvk=f?�I$
���}�I$�^/�H"	���4H"�&�S��D�m|I$rp�"���/�:�H�6>��ncO��nc��nc�w�nc�`�;+��<�W�PC$��m�7t$��m����DRl���������;�B����P����N��|����������yL�x��X<�����3N�
endstream
endobj
15
0
obj
46137
endobj
16
0
obj
[
]
endobj
17
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
18
0
R
/Resources
19
0
R
/Annots
21
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
18
0
obj
<<
/Filter
/FlateDecode
/Length
20
0
R
>>
stream
x���M��:���C����UY�?�tXG�����`�0l�����v�Q��n��w�+�����(����D"cU���-R\��(���^?��~��_�{����������������~�����R�%�g������~��R�okJ?�����	N[���^��OY����m���?A�\����V���������������mmK/p��-/���:����x��o��N������u�'�,��{=CH��A���^���=~����(�^OR�wP�����������_kj�x�'��;�u�u�Z{��gYt��55�D��D-�?y_�r?n5�{���5^��u-Q$��� �V�s����,����,�����E�x�g���\k��h^��ID�ZC�H�{=AH���ZC����������E"��	Bj�>��6�����f��54�D�����}�5��k�����,������hOz��Z���������k������k����!�V�s���K��z��X�����(�^OR�����e�Z{�&�:��}�5tQ�=�	Bj�>��mZk����J���ZC�H�{=AH���Zw]�j�?���w�5���^�R������z�I/��M��5��^}����}�5tR�>��������F���z��Z����.��'�n��_k��^}����}�5tS�>�r��D�ZC7���� �V�s��n�z����e������E�x�g���\k�M����[�&��E"��	Bj�>�:�W��v��D�ZC�H�{=AH���ZCW������M��5tU�>�	Bj�>�zW�>�z��D�ZC���'=AH���Zw�����F�,�]����Yd��z��Z�������O�u��D�ZCo��'=AH���ZCg����n��_kh�x�'���\k��^}�����������'=AH���ZC���']o��_k�]���'���\�C��%^�5�gY���D��<���"�V�s����Yx���nC�ZC�H�{=AH���ZC�����t������F���z��Z����n����r������n����	Bj�>����"^}���e�V���w[�=��Bj�>�zM�����w��zM������}�5t�Zk��;�6��5t�Zk�'���\k�R��^�;�6��54�D�����}�5t�Zk���w���U������}�u��"^}��v�������E�x�g���\k�U����;�6��5���}����}�5tV�>��������F���z��Z�������'�o��_kh�x�'���\k�]�����w�k
��W��!�z�k���R����,v�n"�f�=��Bj�>�zS�>���w�k
��W��!�z�k
���Oz��n"|���z�IOR�����U�����w�k
�"��!�z�k
��W�t��n"|��w���� �V�s��N/�j�?�bW�&�k����!�V�s��7���~�z7����z�IOR�����E����[�&��E"��	Bj�>���W�t��n"|��Q$��� �V�s����z����e��u�,��{=CH���ZC���'��z7����z�IOR�����I����[�&��:�W��!�z�k
]��O:�z7���E���'���\k��^}��������F���z��Z�����,��^#~���]����!�z�k
��W��r��D�ZC���'=AH���ZC'���^o��_k��^}����}�5tU�>�t��D�ZC�H�{=AH���ZC���']o��_kh�x�'���\���K��k������k����!�V�s��7���~�z7����z�IOR�����Y����[�&��:�W��!�z�k
]��O:�z7���U���'���\k�]�����w�k
�"��!�z�k�u{�W{��Y@�Zw�"{��3���}�5��^}��[�&��zS�>�	Bj�>�:�W��v��D�ZCg���� �V�s���z�I�[�&��E"��	Bj�>���}Q����,�����E�x�g���\k�U����[�&��zU�>�	Bj�>�:�W��z��D�ZC'���� �V�s���z�I�[�&����W��!�z�k
���O��z7���M���'���\�C�e�����,�z7��"�x�����\k��j^/w�m_k��j^OR������i��^�������i��� �V�s������:�y�!|������z��Z�����������
�k
�"��!�z�k���%^}���e��u�,��{=CH���ZCo�f�����
�k
��������}�5t���^ow�m_k��i��� �V�s��k�Z{�������5i��� �V�s��������y�!|������z��Z����z}�w{��Y{�,v�n����!�V�s��7���~�z7����z�IOR�����Y����[�&��:�W��!�z�k
]��O:�z7���U���'���\���E��k������Dt�"{��3���}�5��^}���w�k
�"��!�z�k
���Oz��n"|���z�IOR�����E�����w�k
]��Oz�k��.���t�6V�%�0�B��Oz��Z��Z:-��^#~�EG�ZC����!�z��zU<���X�V�S��Q$��� �V���]'u��^��Uj�>��:���!�z�����t�6V���Tk��.x��������.x���X�V�S�����IOR�wP�Cg���I�����k
��;j'=CH��A��������w�����������w��?y��Z��v���U#���Z��v���U�����k�B�Y�~W�_kj�B�Y����K�9A���XR]���Ou�i����b����RM�S�|��bh�O�zF����_t���p'O������~�4�����iU���wh~���{[[��}�)m����
�|��4\�V���w���|��:�������x�G���e�?��W�4� k���f���s�{���WO,�����BKQ��	��^?K�����g���q�6�����X[�vl��c�����G��m�vm�}����+��Z��R��]�M[��j���^Gw���D������������
4L�^���L��~?��@hz���Q��Mn[��41�{�������������tMN����{uO�{��~���	��x��{�qg��%�} ��x�����������]�S���:�Ef�{��&��-�Y��
��m���})�O"�G{�-��My�/:*l4�Cc�x���)��G��Z��d�,C�
��]�������>�������*�in���}��z�����oduM@���2�a$��
,y�j�{}�3�Wxg��S�A�����Y�v�����#���}�k���]O��C��O2��w�<.�U�^OR�}��������	�^�����������=����x�/��'�������*�in���:�h�����������������u��m ns:n���O�Z��2�\,������^����+������|���P����@��t\mF�{4c4��V�j#B�����Z�R������O�=4>��x���iG�'���W��&��{���7������
l����<�Ips�:��]�����}��3������������6��D������ss]M�k����nIm�������g���Z�GP�"���a���r_�mE�M���^�;n�j�Y�^��JR��r��c�E�k��n�^z���A���%�����
yZl�{��vj��O�89���<���{�&��� �$1q8�y�{="�
���#!�mUj�Dz���:�����i�)9kI�9������9.�qS^1� 9����S�E�����-0�&R#}}eo����t��u8b$G:H4����	\YW$M�{���h�,��
����G��.w��RjJJM�m��d�Y���V����H|A�	����o�6N����f���X�?�*`������������K�O��){�?�?�"y�g�f���{�l�=~��+����+N��{�������=�TH,-������^�oE_=L�7�V�5�
�^O>MM�����=����}�D�����c�j�'�p���i�8�^�x���{����E�Erb���
{��N�W��=�����,s�k`������i����V���vW�n�a����1��������{3�r\���/m[hP���E���F�U�Y{.��Vj^��Z]�
�q|���6����e���}��z���9`c�5=���g�9�VE4��^?��Crb��3�&��{�?�!�a��z����9m4:��;�WC=i4:A5�N�I�vD�{= �<o3C�,�-���v�������4N�W��=���� ZQD�^�x�]����\L���&��P+�����-Is�jK"��O������_�����=����3���.����������y?�Ap�}h�x��!w���?`��5���^��y\�#��*�iR��Z�w/��:�������x���6x�e@��]������<�E��N!���Jk��J���B{�{h��k7E�������eQ`�D��G]�\�S����J�{��v=����b��T�{�Y�XE���R[QJ�B�a_2�\���kSN��v��)
��]
�{}����������}
��������=���R�&�x�//��O0�D����84�F���1Q���6R�`X
tMJ����:���mUn����r������iR�J�R$)��{����_�k�����/�h����������]��Q�<����q)���^?���Q�E�E�d������#hX\��Zd�C�8'Z�))0Id�����;@���V���������]�����i�i9���h1A/��B��^?n.������{}y-S^~�a����W-Y�G��	t�]��^gw���c1i��G��#�z57�h�A^�B�ib=�k�}���&�;��r�{]��)�]P�x��������[��6k���x�}�����0��B�j�������c}�r��_:��~��6�����{=��6��"Z�"�����f�.jN��rZ���k�a��(�J�D��'����N����x��'J;0WfM��{�]�������2�G���0�x
�^?�<�N<}�d�[��`����^+6��kwT(~@h[�47�{}�k�;v(��g�vMH��zv�l7"�A��{Y$����n���yo�6��^��n��H�xq
�}�^������U�[�I��^_����.�����&'���_���2���$}��^?mQ��0�	H[�?���r��(48��:Ht���@����=���,���\�5#�{�X[�#�i�e���t�wY
6`�x������uz�n�$����B���b��*�if��Z���t�%����x�gg{�t��!�F���zvB��MF��R"k�!��	����0s��^�"�����l��,�-����N�����p��j�y�K������������1�k���=��[Q@�B=��X�����j����:�i����rU^���x������+��C������n�=�?��A�]Ld�f�=����W��
n[��4�{���O�H���9uRJ���e�����`n�� �k���@��������x�`�t������i�����Q?
f���E�Ee�����
������U��{�?�46���r�tV�{=I�C/�(�-2m��8���+p��i9���0�'�j��F�����-��>�� ���� ��O�%��\��51�{}y�M�8������_�.�+�k��eb����6���mriP�*�8G���{�8�h[�4������?��ciO��'��^�\����������^����4$��6c����o�Fu�
���jK�x�}j��8�))0I"��O���V���r��(��a	����b@m
h9��Ncc��C]�������c�&c����n���'�\m����C*G6LF�&��{����9r���
m����Lu���\m�'��x�n���w�0b�
��Q<��>��r9�a���1���N�����E"�� ���8�E�Erb���9a�LGK��lE�=�O���A��l�&��^����
Pr9Z�Ff������h���
Q������=���'��B�S�P?n�>�5`�
�����D�s;��$V��\�nO>��j��U�?ZMT���V6J��z����u�����x�]���{�\"�{la�p���������g���/��ir��r��HK,�A�Q�x��*�@wU�j�u�>p7`YX$C�{���5�M��B��P?��ySR`���x�?���K�����('m�v����Eq�����C=����n�j��F����q���t�6���=�s�y��sU`����v��?}H�gz���_=G���bs������I|T��n�6J��z��'��!��m��i!�kM3���'8���t��Qz�������mv
�����\�!iM�q��{�8CZ�n�F� �k�U��*�,�(������J���m%�=��d�(�G�Mz��~�@6��ne�	h9�s`0l���6���[{|~<���l7�nS>�0n�*k��l'�C_���a�aP�*
m���P��c��K�pMsB��g��E9>�e�x�p|L�O�$�k;3e���8��e����j�(�u�k�nP�v�Gup-/&�$�EIE2d��.��/kd��6Z��d��=����FC��l�$��^�x����r[QN�B����(�[�	�&��P���+W�4��X�� ��G���R'�t�l�����;��y~e���C��qB����9��F���=���=`zyh��^;�����	�0������x����=��(8�MJ9����y/m@���nv���8�i�Hgm���F� t�9���G{��AN������3O�)�����z�
�6��LI�I�	���\E��hE�h�i���n�[ir�r��/�bZ���;�d���*�^�.%�������{vE�=��R�����W��z�y.Q��z�h�*�^��K*���TC=P����V���i"��Z{��;��u3�qz��.������u3n����P�(�\��K.�GTC�)����E9�vhO���w��,�-�.����F���T���6J�C���M2f�9��I�0��vM{��p����r[QN�B��{~��\���6N����RSS1l�.
����'�8t�0����=���������*5kr��Z��h8��?�jk�
7[9�?4O���^��Mm�#$�p�1�������<��e��*�iN��Z��~t_��?%���Qct9@�j�B�Q_�P+����W��������-����19ajB��[5�,D�����kE��z)����������Z�I��^W���,��� 4y�x����RR^��x��[�>mo�!���V������P?��4aRB�r�� ����]�{������X�����=��� ���\�5�{�������;L�E\��G��x�����}������$�?���j�������*�i&��Z3�����t��q�����V������k;qn��\:M����������z��t���N�%��P�{����3f4��E�E�b����3��bf��4#.hV��=��������2�k���i0���V��P��!H�r�)��P����~���vh���P?�����4�P�� ��9��[�sU`�����C���C��r�rh�������O�U��t&m���<���9������V�5�	�^k���h��7�����+q�����V��Wc�9���@�����B}����^r�IXemT�{���}�4��kF���v`�{�:�8��v:������{=����Kq)).I�a��.���^�q�9�oZ|�B=������"��
�{�0#����Sxm/�{�n���+6"���R�&�x��z�"&������5��_z��rG����l��1�>�Q�x�=��]���U�M���^?H���<29jsN��q�{}��Yk��q�C�����~��!�#8Dc���{����!����i�����r����
EG��_��Z���^�lo�c�,��s�U1y��������LI�I�,�����_�MI�(�-9m���R.��qn����#������Q�&��{}=���9��Mq��=��{%:�Oh�\�5�����yz��t�����1z=����F���z��t�9��vz_
�bo�����s�6M�^;��Y��A���Xh;��jw��z�q�Q����{��E�-�tR�y��RC=P����nHG� �k��(�"���x�����H��
��{�����q���t�6�/���r,��@.-D7���P?�����n����x��vQ���N 4e��#�Y�nQ7n����r�s�-���~��Rx�^��z�������o{���K�-����^+6�1�����mUj����@�<�0k�
��A��~�P;����^tCtm��m�� 8���s"�y��RC}�T��������{���d�#��07�M��-�.������w�,}�k��Y~�C}��w�0%&������=��|t��1[QF�B�<��������
�r�/�_����G���j�A��A�s������
P�P_��f3��Ys@���
����������x��������='�������_j���t�6M�^�s	7���t�������������@7n�v<��O��"��N.4��[j���7Z�d����@��&j.����[$Q�{��w��H��ML�C����������_�{}�M�X����V�����i�1�@��2M-���o��Y��@�y~5��5�~��ac�K�4�/{�?�ChK�����i!�k��~���8��f<���{]eci����%Ri^�E��x��z�+�I?`���!�k��}�� �N|�z�^����Y��X$������F.�J�@��v�����k��� �^�Kz1�3+��H�������o}/p�U����=���h�����2��V�{�i�4&�r�q[QN�B=m���S�h[��+��P�q7�	�����h��oQ3'|7��}������>Dc�o3kn��z2����q����_:/<Z�+�k��o�u 
��/=����p��nD[�4�#�kA��6_qK?��&)�+�k�}�s�0)p��q�x�O��+.piRXQem�#��iK�o���2�;�x�}j����u-�B�������c���<�S�I\��J�{�?�=�;����$���{��7�c�����R[QJ��|�1��@��6M-:N_�0`�^th�^������/qq�������h��En�������$����1������<���{��-�����a3*=+����j���2|p����mUj�����>�5�����I���^�x�5 �X@tm�%n����.��K���*k;"�k���3C�������x�?L�,
��(�H���:Ht����^\��
�{�/�Z�,/����$���^?mQ3&[Q`+
H[�������s`eQ�������?�3,���mB�{}����B�p�*.k�D��.������;���/6�6�#{���ls����,Xh;����ao����m�b�f�x�,�4�9����}|�����4�s��������/I&4�Z\j�'�A[����^�x��{�}��<�eQj����e���{�
g����Z��_|�@OlJ�M�3���;�����(���-��-n�j�����N|�����\�_�w�����r1������6��^L����S�����{��e���5�p������k�����)Gz����� �� ��3H'��>)��{=?xX6pa�vmg,n�~���;���D��D���EG�9p��]�^���C�������(~�WZ����^����!K?5w��}UN�C}}=m�"%E$�������`C<��(��-���������M�l9��^��C0���h;��:�f�H���@���~:^�����f�x������C��q=��_<�������l���ai;���0G����h#)���*�ij=�k���mEw�P��I!G��>��/�
\���&��{=r��+@�q����=�k������?\&h_��^�k9��`�hYZ$K�{e97"i<\�
�{�'w�pP��6E�6%�&���������Y��(���-�����Z��=q�����#}����
`���5=���7�P���F������t�17W�fM��{=O�l\������C�����r��;[7G����k;������XN�}l����x�����?K�*%)��{��}�V�����-����d�O���� ������]�������j���vS�{��}���q���"�2���v4���+���P_��������r�tQ�{���a�l+�mE1i����m:�n��K�"[��+zz�`�V�,�vg
���Z��,e���=���,��Z�_�f��s��U�.�u��yFe��z�pc>��si��wmgc�P+��mz�mUj����@Ew�n��`\N$-��{��u�7���k;s���z
BW�@�5Y�^�D�OM����q����|��(�H���:�B�G��ope�j�yu��s!0%&������kIG�GVmChr�j�><�`�VmBh`����r��\�<��&���v�>:�`������!���l���'�]��3<{����~h����1����je����E���V�6��^�O�"_>J��^_��7�~���5]VqR� �1� �� ?���z�|��D�����>�'��X58����vo�E�Ee������@�|`h��P_�x7Bn+�m�M��G7'���1����P�s�����3=k�/��>S2l����A����7�r�Y��}�7�n���6{���j���\���#wm{�P+��-\���U�M�C����XM�r0��<)��{=P���8N�q���\�-����;��:VY��^�n4<�����=�/���� �k�������(�Hb������1;�����=��P�AMI�Iz(���p�,\���}��-�����/������v�g
��>},�Dv��������Q�>���59�{}����N����ks�����^#������o���r�{���� �d��m�\���a���!�����q�x�G�3G!"[�
���~�C�^~vM@���9�� ��Y4=����������E�D���v �
��o�����H��+���"ZQD�.�x�?N
�~p�!��~�����`�����-�51=���-B���k��=��"?����*7kv=�k�����fQ��r��\xg�����?�Ot }S������30����\[�4�{=����w���V}�gn����@RJ��Z���0.L�����-�������D���#k3"����L�@s���"�kwIo��0{�,�-�'����%�:���������:hIg'�HII:)��~z�cma�V����O�%��siXTmC�{=��t���Kp����x�?M�.n������p���(Z��l��G\�;����i���}���=����s��q���n��x���gLp��n��I!�kG�;7�V������:_�v�6x��p���"�����tW;��<s��V���6s���r��A�������-�r���x��w��gH�����{����y��c7D���x����k+m�mE��('m�~�=}
��X��m'u�PO.)�-DT�&�v6g
�������/�-���=����6@����� ����.f���>��v84O���^'��K�X����?�����;
7������~����VE4��^k^�?��K����m'q�B=I
^BD�"��S7�PO�
 �3@@������!��*H�I\h7D���9��(�"���x���Do^ 4y�v��������$���^O.$���V����P�!���|X�����jwG������U�
��~4�f.�\hr����N7B0WfM�^O����������C�,��u��_?��/�9��u)[��U�T���]�	�5�B�=���j[��47�{=P��	i%H��$)��{������k;*t�A+�Z
�4Y�^kc=~�\s.-�k"�����Q�(�"���x�]j���K��
cUN�C���%��R`J
L������i�mE��('m��'<&�c2g�ze����r�7W�f�9��Z����_?d��9/��O�<��F����#qr��l��8����f��;�C'��I8=�k�h4����C�������#8tb�����x�g���2j��4k���^�z�����(�Hj��:�����cbr���yU@�#�q��MI�Iz"�������@���V���E��]m�`b�`�h9��Sp����	��^�x����a3��8e�t�hx���c{�
�����D�x�_�&m����CvmQ�P��5�����U�M�@��.���1�Kx�9�MZ~��Z��{�<�0P��s(�P+��p���KW��:k�"�k�}�9\�
�v��"��K���i��E�E�e����~?�>�q�	NuW->����'m�"%E$����zz{?J������z�S��AK�h;�2�����F���xr��D��Ij}�m�\��H�{���l��-��l�g5�x���m�&���[��������8��~kC4M�^�G|�}M.���
�$5����]�!�[�������	@����8���j�j�x���.f�/��F[����~zml���L�1��v����������V��P_�������h;e1���������	��Sk������R������{����8��v�Cc4O ��^��}�����y�F��������V�}o4����h_L� ����47�{�r}<h��AZ�7��{=p�m"0H�^f�x�?M�c�np&��.5��r9@�g�C
��v��~@'�,
,�(����g��1t�����NcDJ�H�/������_�R��-�AN���h�}�Jn9��/o�1�
���K��d��I��Q
t#��mE�=������qsUn�T����}��v�;�=����^��M��-�+�h;���z@|�
��t_49��Z��?�p�������N�B������#�n�&�'�-5���������Q58�����X������k��~�O`J
L�u��$'�@���V������nb���&�����������*���^����)0,�nhb����^?����n�6`����h�\F#��;�m#w�){G�����-�XC���x�G���
�r������x��q�o��K��]��9���8ZUo�}�,��{����s�����L�u�3�]�����%9��&h�MN���s���l��(�H����qo��p�*]J7A%���n�����R`J
L�a����<I�`��-����l"�^�{����#=�#�}t��!�v����F���k�6@�#����;�t�am��y�x�g�
��
���A���u�lP�8�w����d�A.��3�$�{����)�\��]�A~[����#G��h����-5�����8����z�:���i����(�H������cc~����X�����z�SR`���x�_Y�����V��P_wR�;�6�D�"[�9�p�mc>xU;���WC��e��y>������-p���^9��m�.W�eM	�^?�1����4.���z���n�}�]'R���N��V���Kr�����!���{�&�4,���_��45:@��!�v�zI��ro~d�����/�=�� ���5�,�-�,������	`��"�������e�����+8�O�A�����{��(��x�?N�iw��p����r�]�>���a��&h;��Z�7'�S`_�K{4)e��Xd�D�������w�s��
��������x��iO��+��(�����j�N�>��VE4��^�z���E^��*�.�B�I�P;��m`-Bn�'r�����PO.(�8�<to������H��e��k"��i��K}U��EqE�d��g��@����=��n=�q)).Ie���=���{ ��@�-�AF�Iz����b�v�^
���#7����&���~�p���UqY�B�����}�uJ#��Kgvw�{���/}a��a�&��6����>_W��V�6M��{���?��:�.��]�����|���%�=49=���{�@�%�^���=���/)]�o�Kp�����{}}I/���[���^_s��&����]��B%���
y�������"���V��j��{�������#���]�����g�t�N�kp��M�����0%<d��l����P���amN<���`'�����}pbh���������:D��A0���N���~�=��6n[��4?�{=p'S!3���qp��������:=x]�y{[�D�(�$ZY��^����g�#8����x�����jC�,�-�'���H4�r��8z'����P�[���h����$=��^_�L��hE�h�i�����RGK���j�!����8���M��8���C���]1}����*0kwD���y����������C�`���*;��<�/`�����WC���>An[��49�{=p��j#�8�O
��^k��Gr�
��[���������8��M`E��	��k��[>�5���^�+��V�}&��v��y�eQh�d����L�8z�����Px{����r��V�{��� lE��( m�~x]�
��p�v�_��}��r�vh;�����v4����e���+I�.W�e��^;�������=X����^'�����wR�M���(=���z�0�Tn��i!�kI��r�J��A�O��=��B�1��Py�����07`�vB�����;�	���}K
���qJ~>����[�Q5����Y��U�����U�Z����^?���@���@h���nM���n�$]��^���=3\+�kE�O[��W���Y�O���-��u��O���}�O�V�>���%��'.g�� ��OS����r���x��r4!�Y���x4`���<��y>��\����7N��z��%�G7���{��q�C������{=��c��d'�G�-5�AN��aE���j������|��n�"�2�k�
�px0m��ng'�����|y��`9���v�%����z���E��Z7�[�i�4��o������v�_
�e#^D�f�h����S�P_w���&�b�{n���!�k�>\t4�z~h�O�;��F|�V�^l=��������#�k�����0�;�
�4����{��p9Z��s��^;���0����������^��c�n.�?�f�=�k��m_?����l�=�NlY[$3�{����X��������{�'��_��n�C���u�Q4|r�����kE�?�����a��1)���[�
�r�A��3V�+t��NJ��:��7 -Aw�����7����uc���&����]�������C��s�z���d�"�{�YN��WC= >����yr��t�W�������t�91����t9��vsr�y��RC�Z�v�����3'�^_w�uK�!���x��Z��q_w�
MH��:���LI�I:*��>/iS^+�kE�O[��'����"tG�Zu�`d��uw�����{=���"�h�3��r+������g�	�����I!�k7�={��|]��.VN����z��=���������\h;v���q�~��mUn�����==���t��#����W���(�1`���Z"���@�����x�4��Z/�����WUjY�Z$M�{�9=��@�'����i?zn�I~��~tk��6n+�mE9=����=��MM�3�����3oj"�U�>�v|^
���Is�X������������*7kz��Z��[j���f������t��u��ntRi��(=�kG��`!�A7��ir��Z��WA�b�.���
��}����_vm��m��4Q�T�����������S.�
��_����A����9���
��(�H��������^�=���^j��P�����.����$���^�4��]��j>���������xp����U�{4`hgE�>�������zr!i	���Y3@��z!��OR���������y�^����vW��D�]mg��P�'w�r�����!�k��>��,�Xhbz��.��Q.@nw
r���P?nW��.���K
u�?>�@�D��C{.���+����7�Z]~$��7H-�R���x�]7z�-Ra�B���P?�i�'k����$���^?mT���(��-�O�-W5�����s�����������"��~�|@����=����t��asUl����b�bR�c��yW_��<�#�k��my��B�3W����{�L
���.�pz���{�dt`� �����O���\	��&��{}������_�$��ukv��v��u���/d�,
,�'������Wt.��K�U9G���;�U�(MI�I�0�����������Z�����W����D��hZ|��~�M��=�k��������H�JD�L������{2i�����y�x����E����zpg�����X�^�O�(��C���Ph;C��Z��vm�r�����!�k����O��XZW#I1=���&���k;Bq���O<!�v�uO��D��.���i�Qq���^?J��_�-�r�$�x����]BiV\��
�{���;�qb������2����iN`+
lEi�4�`�	��*�@�Z��#���U����XC}N4����:����v�{����\�5�{���aNtl�4����<E��{��&��/u�u*�
����h�j���*E#�T:WI(��z�N����?��Nw�B�i>�p�X�d�����%:Z%�o��cp���H�{�aj���E�ERc��AN�8 �n�U�����z�i�������R�{}�xf@���V�����Q��.}������C��Z���[����j���Q�4t
�2�� �k7��}���l������v���eH�����r;���:_n��Xw���)!����S4ri���8=�k�������n�����-�q�u�;q�<vq������
t�;���^_w�u�9�v�c
��J�����&M�x�]�`D�#���6N����
m�������w����r�����B�S�P+��+T����CSdW������p8����(uw6��vLb
���,?l����k����4����1S7�mg$�B�����qT���H�{�2{���X���M��{=��C�n�?�F�����E����,�+���x����{�
��Pk��O�8>��p�&����z���Gm���V��P_�������.t+�QZ�����������C��~�m��b,41e�g��������!��;��nK?�W�1�G�����O�t�8q][�G��#��C���'�kRz�����'gr9���qrz�������#�n�?�f�=�kq���0jY�Z$I�{����:Fl�1ND�V��upo�v1���qz���v�u#�q[Q����>=�\�����8-Gz���u��!�v�������\����8e���)�^+�����
�5����Gg�E~�a4�9�=���lF�?���l������N7���Ow�VE4M�^kb���Ot��N.�e�
�%w���q�P�y��{�)���������K
�k��K������(�^�y���WU\YW$=�{�.��o�Y���ne7N�C}}����uC$����:h��W��������.j�������cs���y=b��}��M���4_�nk'����Z�wo���t[�Q�f�x��7��7����\'���	�=������
+�XZf�]���5�v�S��mU`������%����N���_���y���x�+���s�P��oH��J*k;"�k��w�-��A5���F;-��~�{��,����x�5�����K��zgUN�C���������2��OS�-���r[QN�B��O�\�����i�i9���K[�j���k�'MI�z�6�Y�Pkj���|_��LF�}�1
���C�$��u���w�i�N���k;����a���d��*�ir��z�N��`+9�������x�5��� ra�vm/n���MiK��"'k�"�����oA�|�������]�����,�-�(������
.BV�=��))"I_e����9HjEI�h�i���G�V�U�	4-�����,�����w����-�#���E�=����e
��*7k*����;�nS�}�t��u���y���5���B\	����#���d ���V�6���{�4K�p�%�����x�=.xM����84���^�y�_`)�����������:0��s�D�
��=��;����(�H���z��� `=@tmE�=�A����d�V��� ���K9��A,L��
�r��f[&F|B��_���x�g��8][�e���wG|rsUn�Tz���F����rlZ4��B��<���{��7g�>�E-s���|���w�@nxQ�j[��5Z��^+���U��Sp!����.�tec@��]���[�5�����K���%k�"������^[�M���e$UE�EErb�������H��bU@�C���G����r��R�{�a��B���(���-��/0=��Q\P4��3p�V������x��I��t����2����.C�7W�fM�^+�n� ���C�c�<�k;o����?�Q��p	N��������Wb���'��x��<��A \�����-��/,���=`Y��%���+*��2����j�!��sN��6(�����4��x�/�������-�O����/����s��^x�35��8��vd���+*�rU\���x�5����U��l��Y��y*_��:]m?�e#d�r���k;��Z�O�����m������#dr��7)��{����5��$�FA���#�B��w}�����+��<2p��~|u9t����{'N���"�k�y���`��(�H���������@.�ZN�r�jw��yG����h��r���!��V���vP`
�$'�����s�U�,{�����\�5�{�������m���i��yB_������F?�rL�=��A���5����#��1��M�B��.�q�aX7%m'�B=Ap����D@�4������;�4������{}��
w@�EERc���f��n�&����z�&�D��5]���P��?� �������,���#����"[���q@�]����[��$5����hY�P?1����Cs.����������a�����z�|�{=�^�)������4�#������uu5��8_�^�/����
dk�q�x�?���{��=�q�x��;Y������������x�?N��@�[�H�=���o��vM��N�]�������$���{�7`+
lEi�	�t
�\=�r�v��E���im�#���;
�BwW�{��S�@O/)VD������^��}2�g!������x>_��z9�P�������f�)u�v `
����#{�D��u�����iH������
�$'z� ���=����DS�@��%Y�	�^��"�L�k����z��?@3K�,J-�$���n8s��^�3R����:@����RRJJJ�����w�<�<�mE��(&m�V���t���p����r���
��}���������{���}�/�G��z�Ui(@����� �k����&~#{��,����x��G[i�Pd����������?2������>���4)�{���N���>�����V��&*�Iv��^������;��o �����	�&p�B
��vi���
��(�Hb���Q�9-��K����'����K�/��V����0�k���&��%i�7{������Y����U�^O�m@6a�E�=���z�����UqY3@���o|�A�!���\84����^���h>|3���tL���#k������*�i���2�����.#�rz���km���sF����QC%�_�k;4p���r��:�+Y
�^;����C��3+��A�%��>���WU`YX$?�{�a����si\U���{��D/n-/���$]��^_�.I�hE�h�i��]p�B��u�th�i9���h!@T�&�v�_
��6����v�%���{��������r���x�?����f��;��|=�����cZ���6.��XC=poy�pd#�l����D�w0,�A6V���bo���
d[�A�y �RC�r�[�ds5���^�������Ere����j� ��
ML�C�Q�t�q=@���_�~���v����V���v����B�`�N����
�=d������B�30;7����&���v��w��AdC������v#�8��9�c��q]��_<�������.`�8����sW!��
l�Q��z>X����*��
s�{��}}#w	>�?.zH��E��I��^;���t��}��59=����
#�@W��C�m�����dD�EErB���^K���p�6N�#=�%� ��5�3���q�q�6`�h9����O^������x��t}������G��~����\��5����>����:���_pph����~������4�N�i`J���WC=Pg?���k���&�x����#3iM@�����
g�k;�oup	'��hX�dm1�{��r���=i\Th�D�����| ���"91���9�H��}C 4y�x~.f����2��8{�l���V��P�pr��-�siA\44������c:�����6%��v���/��\��x�'G��q���C��4�{��N|9�w*���I��^+�fo7�y@�����!�k�>}`E,��������������^�a�%�@��vmG�m����"��X2dmQ�{�H8����k�E��p������"2�k���Cm���=i�y���h2��(�I7a��g`���i�q����i�-�z�;={2\����k�/o����B����������q���`�
����~
48v=�Ip�~h!�������5�\�&�]���5����(�U�MC��80����p������<�a��P ������-��x�����%C��C�����XKt�9'��;��u���DYQ$�{��#�H��X;M@�C=�	�"RRD���x��9M�.2�ZQ\+Z|�B���L:�f�9zS@��v���^F��S��H�� ��[��m�&���x���|�&�����r�&�x��{w87�E��w=���^�������nh;u��z@<.�$��}�6��^;���
�t��bz���J?���k�p���� �����<�p����w��:���g9�� �����Id���(����053�qo\hr�����~=3������U<������;2���l�|8;���F���V���P;��F)����5�F6���S��v}G��V�hd3�������u���f�k�;����������K������!�����Y ��]����Vnx�{���Z��'����#��w��t��m�S���A��L.-I�`�#����^x"
H>0M@���#�����Yd��z����^{�h���~|��d����^��q����RjJJM�;�ut��V1�q��M�V|�"}}V�[��b�?P��%������a��}7`�({��w���~f���{�x����:s|�$��<���{����z��0l��a���� �����q�����i!��3pr���82s&���������p��b��k;Bp������9\c=��!��e���7����P��x���~���FL�+��5�K��E�E�e��A/
���i�78�_��������I�X^�MI�I:/���l�p�6����V��POo�������n�9~��[���}�����������31iW��kB����=3#�rU\�|�����v���=���^o�}��6zR���j�>X��t#�q�f�x�]������@�y�6z��x�P���a�]����{=`/~6�)�z��y��RC�a��$�A�b��A����������ea�_��RJ�M.F-�R�$�x��e��0��Y�����{��Vt?�"%E$����:�(^�{t��[Q@�B}y��KZ�n�'�N2������V�,�'��O��.m��B��Bw�
�V|�C}���0Wf��^�kz;O�
�b[���C�d��u���\�C�RXttm��P;����j[��45�{�����6(s���Cq������V��XZ��(p���
�P;��]-����������Z�w� ��A5��jG;1��V��a�?�����j�E����(�H���Z���'��:��������z�^y))"I�e��q�0�'��[Q@�B=��i��Aq1����C�Q�4�Tz��X��z�]�\��H�{}y��_������.*�����x�����?���0�?��x�G�������*�iR=�� �p����1p
���#�����#>�pM@���]��	G���#`	��-{��>��g l���A�g�����l��,�-��������*`��s��N�Ez*�a��kl4��jJJM�a��5����diSj+JmE)i��$����]pm��r�?mW��U�S���x�'w
�)@����������F��2��\�5����������N������Z8���4�<��� �	@������}��Bh[�4+���Q�����A��C_�vY�}��6Cl�)b�M���[�}���D����#����F���n~9�\����zQ.l���M��@�0
��pz�QgFAjJJM�qhN?Oc<��(��-�����G
���s����b�'�j�E����FzB��������m� �����
c�'4W�f�
����:����i��U��yxc��z].��8������L���C#k����@�UMSA�����cZB��2��HJ��^_^�����g������q�.u���`)��!���!�	}w2�6+��G���v����le�c��(�Hb���%v��
q�).%V->��p?�,/���$��^_v��(���V���R��Kj��j��hT\E4����mI�j���0k���^w..-�siQ\XhB�����������x�?`�@��X�+�C����u���1
�ciP��wm'c�P��3��l����x�P����+��c0_��K��r�Xld����Z��'��)m���m`�����x�]����E]�/G�_�!�,�-�,��>w�������t�5V�=�0|3yy)���F����e'���f�V��Bz��A��HG?�8��M�o9��9F^I[�j����4k�?�����gp����^?��c@Z��*5kj��Z�w_�4o8���wp�qh����.�U��y��c�Xtm�{�P���mUD�L�����!:�`���W��|�n[�!���-��{�
BKz������i�=��.����]/���e�&f��a�>^�oz������{���d���m���qR���<��F�g�������C����Q�;�Ap������x�?��� �I��6�C�����ly��'��������|���,P��Yj���^�,�{pwm�����^{��L{�����9�������8_���Vm�����^��|��4o�
{�a��qo=�����M����@h;_���#7D[�4�{= ��W������B��r�P���q�a_��-m���Pk���z�f��zq�y�[�C��7#.o�$7�����P�&~��V�nx����V=��U��������M@�r�nH*��UC��[C��=�Fm���V��F�����B�yZ�P��r�6HnE�s�������?Q�����E{���C��G:�\oZ�	z!��k����7������zE��%��'0�l�������}z��I��<\|��QwS��{=`=�4`[�4/�{�y�L�x��.*B���W��xVk\������{����F�n�E{�[�C�z���%mS%���)��v��(�X��EoUb�W���;�P���h�S����x������[O������B�Y,5��jRID[�4�{��&	 o?�RR@����B�������h"��y���+������W�^�({z��,MJ/0���t�����E"��	����th��2��8��F��e#n }�����r�{=R�9"����<=�k�$;���n�C������n�n'����h�x�=�����rw�)=���|��
�.jz����Q�x�?��������]��������_���/z�;�I���r~M��[��@�����jG��#
�V6M�^�����M��j����Oq��&����vm�l��d�{��@@��9�AkM�p�����i�����@��B��B�8C��Vm5h���y��{���m~y��{�=ye����X����az������\�|��&9��Z�w(�-}G��]�'��P�-o8���h�B���s���Y��U����{�i����O7��6+��~�(�;��(4��:N-8��6�4�C���=���og�N�x���>���]C����t��V�6��^;��3:��`@KL���^_b�����E(���5���\��E���~���1\���0����z�^�X
Q��B�H�{���o�o������������o������o��?�7?�n��K[�����X^����-�������e��������o��-K����[Vr����Jnc�����6��Jnc�����6��Jnc������M�����X�D���������R��rH"^?'R����aul�CU<���O������?���������_��~�c���_�{�Q�o��|��)�?������o�������?��������������������_�Un�YZ�}�1�������Ny^�_�7�+��Y������?��}���/?������Z��O�����V��������Z��w4����.g����z��7�y��
���~��+����m��Z��~������7��mZ����w�+���I��=�ne��w_��f����u���|�����g��K�.��g��g���W�,��k��?��w/��6f�������U�O�Wr�9�����o���?W����H�(��?���r�O������.�����|s����%������4�����r9�[��U~�/*����8�
��&xa��7�q�}�����/(���}oP'xA����7�'x��������;L������?��=�/,�~��t���W��+�q�wy�|w�h������d������~�o�������&xa#���k=L�.n��/��	^X��������or�|s�h�����yU~�����O���[y�I�=�)��3]���y���0�/����S��{znS�?�_��?�U.���iY~�y*�-���^P�3��������G���^P�1>����^P�aY�� �L/(�x���g�L/�����7fza��e��Gy�����]
3�����?������W3����~�;��.o��m3��������^x����0��h�����a�w�����;�8��\���B�L/,�o~��w��.J����wQ������E�����\�����"�M~��6���������^g��?�:���R�GN�w�����������7�f{a��@1������Z�����?��������)�0������?�������h���;�����_�~�s�?��g{���?6�l/(�_���A�l/�m���^x���_Wm��6�����E3��w����{�_�j���f��]�6�_��������f{%N���E��~�e�����=C���E��l������.J����f{%��������������)_������O�����?���_�Ut��?[qY����,+����Z��k����'����;�I��8���+U�� -���c)��j"0�B�B\	���232�[W�G�u�Z�D.���s�����-n�L��Mx�y��a;�[#V��X����z����z��������\xZGwWO�w�vK�1��v����D����>����}��&q�����dzIq������?�>���/�7���#q������
_o\�p��i�y�[���r���^�~N�1����3�^
�%f��u\~��no��_c���uy�L�/����OwfZ� ]��t^��3�P���C+�����rX�|r�x�+�����������b}������bzD����LW\Ogn�����������/���r��x���h��7���QV�l^r2v���5���g�������<���A~In?U/Xo�n=(������
�u�tU4��s��C���R54�����@LX�:h�	/��x(���@Lz��`�K���?t���b~�����\�

0����Y]<�_�o�����k���[x�y����0�i���L�og��f���.��q�r�]8�@n������N�g�@n�E������b��v*%�@f���8����!I2;�����g�L��A�/�����y�b��y�\Od��D��nx9��������6��i�d�_�{<�=q��~�\��F��h���V+�����w� ���U@@4-� ���Z Hte@������z�"�DxU�T������TI@��f�V=t������O5">y|K+���X���IX���Kx�Ab�: ��)
 H�T�N=���i�<# H����Ab��:���?�;����O��o�[����������Pg]�m[M��N��J�/$�~`-� [q��Zc�r��Ecn�`������$��4��
��3��Y�T�z)��^^s����iL��.����q���*0 �`��
`���� ����50 �`@�=��{�
�������H/%���r�P��0���*��x�QP*��?6��0������V/E`�5S�����j�Pl�5S�f3E\`6S�������)���hwM���=.x�f�`n��W�B#��;��������*}6.H��)
��� Q���o^���8������+������7���QW���Cr�7��\`�m������:��iKlY���T-� ��3]$�20 �`@�=��{��
!���v"�T:�0��n��N���eT�P��P�c0��+e��F������V������f
� 1SX�3h(<4�j�������$v���/�G��>�c%��
�8_


!� 9�����$��D~��'B�
�n��!(�;A	e�C�i(�w������
��SQ/��
�;�{����\���o$�Xu��������0�������
����j:��W7�C�+c�DWm��t-M���)"?����LxU��
�����l���(���K���L2Q��v��+%������~�`����1@^�C�`|=������f
��j��3����P�-Ms3�J��|Z���@��>p�Cb��!��J4C+�|L��N�\��f���I	�@�b�{�(���2�zzB��Q��co�!Y�!9��������+��������#9��|y��|pGy{z��]���(���v�}�1�t`�n����	2]5;���#;�	�?�&`�JvB�V�C�^�P��W�w�Lz"v(`�eL@����h0@?z]��j{�
��RH�P�7s��^�P�n��k�
�n
��l�
�v
��k�
����!7S��O�r� 7�����[fZ\�~�L��C+��Tn����0�p��8���������Wb@M�_T+2=��&zqC��'-��_OZ�V,������� ZaC�b�����HY0�6r��� ~���v����;������;����Tv@4-� �U+2]�$�2; �v@�=���X!;���'Y";��v@��RUdD��h@��F;�G�C�A���/=I|3�.hr���J�X����L�X����N�$vZ|�v��������f*O^��_}�	���L�mG���-����V'7�V���b���J�����w�s}���^1��5������-$�H@ca��$��8��	�X&�+_^��	�qL�(��h&0G� G"��Md�V���� ��YA�+��kV@�-]����tA�1�_n�i���"�"4 S���z��Qr.��\����y�&z�I�Yx�y����")��)���")��)���L��
���I}�u����i��")0�����2���ah���V'%��V>yt�)�@�I=�����`�n�T��J�8=z��
v�V�`WR`V�b�rcn�����z��~�dH�;A
���W�_��D��FH
�������Kd�R���� ��IA�+���!D�C
���a)�1^����>t���"�P��)��
#�����}+H�.���)����JGR`5R$V'ER`�R$V/ER�5S ������3��$f����")0�)�j�������$fZ(���������� 3��S)��[���Q��T�4V@W\��eT�Pv��D��DY��)��$����'0Gr
�����a �5)�+�Fv�� �5������o���Iy~u�[���9�)����@$�2�Hte�����Z:'2aK�D&l������� h���� ���s"�	�
��^ Ox������Tw���	�n�������"�0>�����f
�j� 3�;'z�Dj�zC��L�q��i�M{7j�����f��-�V���^�������
��_������To�@7Wi��]q���v�!�2G	*�D���`V*a��C���H"a�sp�8�D�\fJ�$�k&�V&aV�����/x���tp�n����
2]��=s$.0aK��$.0aK������I�J���~��=��L��.p~�>��`�\\��n�7s*\u�x
��[x�y�p��7������^3n�5S��CQo	
��m�@�v
�����hv�v�t,��z�^ Cv*z���U�U������"d����>y��o���B��[�B���z�������Bw4"����������O]���>u����
�Qn�����
���_u���L��
���
]$�2* �T@�-����91^M�p=-Q�q�,Q��(��
�t�
��q��Q���
���P8�*����8�������xDV�CT��5^+ET`�RD^3T����
3��!df*�M��T������L��CfZ��Q3�"(H���
!3�y���~��]�&}��L�K�Bw�/�,����(35H��6���P�p�L���;���z��>�� �10��H/�+3p��`�830��#��"��Qd�p��
p���� ����58 �p@�-�y(,#��'��H�F.0iS{���� n���}(��W��#:��9��E���<D����f�������v
��j���v�Yf;Ex���� �?�������Ab������cP��A�;NJ���|�x�$�|:�A�t�?���s`�W	�r�<0��A��wV��9��]y?r6�����v���v0��Y��yK�Z���T��w$�2>Hte|������z���"�)Q ��cKoE���o���Bh����DO����id�*�TF*<��9��X
��Yx�y����"<��)���"<��)�X��Aj�z�Aj������Z�5ff:��G�Th�� 1�z���L'J����w���-
�3To<��=1�����r�?�A��7[���r>
�_����E+�����W��|.��� Q���_�������o���z}�]<_��_�k����������\��������������!9����F����LW�LwR�A7�� D�LXx�����
��^���
�z��KJw! l��Jx�~J����s���m8w��{H�o��9��D9��9��\�?�9����-<�d
��9��
�#���pp��V��vC+�����!E"���{<4����~��s�VZ�3�A+����<A"�RD��R�rYiU�o��E�>��LYI���0p]=#���$��-�����)�-��P��p�9fM��Q�:X�����������eC�O\��p+7T��?����hZP�W7PA�+��DWFD�^�����
��������M!�>�;mu|D�"�y�����'CiwZ�z-�4��Jn�*>}������R�V�C<`|-i^'E<�Xi���Z)���J����{�@j�U���K
D
�=B�n�J���x ���#	��O�����~(���`e�u��=d+��������e"p�9�Y9�9����s��8�T�����!��Ww�{�����|�z��T���L�����]$�2 ���.�D������ea ���;`"��4�,@O���1��4���D�4��]V�����J�	`*����YV�C,����F�X���0�1�R$V�c��"H���� �@j��Y��R+�?��!�O��X��S���e=$�+�~X����i+s��
Y���[�]qc4(�<0�&���G��2 	$����5�(�����0��(��+���D���p�A�����9)���0�f��p>YB�J	���$���-P�DW���L	��'y�{(�P",���:�'��:�������������������{	�#)_��Pq�x�_(�@�������H�������H��
��j�H[-~�b��jq�@�CR��Bb`�R$���v��R�� �R�[?��J�b�X������V��4�[�^hi�.��Z�]q�pD�{�A��A���D@�\�=��WO2�w,�$�uq�?/H��u"Qi�^s�2�����}���$�21Hteb������Z�3)"�!DxV�|��{�
��+��H*/=@	��XZ��H+
�jKc�.�CJ@��o�h�T\�F���j�H	���O��X�)Ab�z7��"%H�T�+H�T������Z�'���O^��0Hr?j�K%H�tZ�J@����(7H�R�n��(+�$+�+�������4��m�#��;�^�w�U�D��b�8r*���r��8(�]�2�T���w#;Xy�����$�U6u8]�����|Y��U�F�k?W}I�U�"RMz0�6�����!���pz`�B�v�&\O=��Oo����	��v-Y�Y�%�
|+���!��D)����UYR`���s#�7p����\|��k��>�n��'��!2aC�m50��VCxm0�Fm����V����j�� |'�����aO�Q
�AW]��D��B1B��U�x�����e�[�������%�v]�'�r='�'�5����]�]�+7*�O�0����.���}��^�����C�G���q��3<"�P���|��pG�1��q~�U���0�n0�DWf����@������[�D2a��H&,��3x~��.
��n���
��Hk�(�vK���m��H��������������\|���f`�>d��\��5UdVWEf��U`��?N3��*2��3���V�� 3H]Ug�U�=U�PW�:���Zo��� q���h�^�B�b��hK���<�����1�_�L��L��z�����!9�D��d���![q�u��6�c�
�����W�;)��+�h����Iqd��e���+��	��@�a�|ePA����DW�{�te���� ��z@��"�	Dxe	O��I>���@��(E!�tw��{+���]y��\���P|��@����k	VKE�`|2= �����
 �j���� !����r�@�[&2�V*Od�Vj������)�����~���]�
C����'� qU��H���>��/����"��z��6��>���D��Y�A�\�r�$�z���n���8m��=�U�!��;�GJ"�GJ=��2��z{�$$��`�tQ��6,�V�	D�B��A]�&$�2M����	D�C����~4��oyH��}��&���@��+-�H/���	�l���H��T���@���4�j}H���O��&X]i��V�&$���%$�����"M�1�sH�	�����zh�����EH����������:�+���FG�,*��
��!Q�G8�;)cw4ZOn!�G��W7�9P�`]10�d�z�E{,�$�zO���$��������:��{��\���P���T-���� ���A�+��!D�~�Eb@�oW�jC�x/!��B�'�����\	
��g[c��H/���Hh@\�T|*�Cb@�Jr��!10>�b`uU$^[b`�U$���� �U�#��'��FYx�b@��2��[�0�s?j���B�+�{0r���lW3�����/��P]�r�_Aj�x���V�@�_Nt�t��L�eC'���������D���(�!���XB���gt�f`	������������������W�����F*�"	�,vh���+N���)R]R��"���HA����C#��HA�}��R$[����)�t)�3(��ubG+!�a��^)-�Hb���P�3&�J��@f�Da|.�".&�4D������l��(����
�}#EcGR��HQ$F:��z7h���3E��>OB�VZDo
Q$�]����#�!��0&b;�\��x$5�`�������+�������`����������8r*��	 ��{��B�rz@�!���c�T��,qz�S�R��H���zUP@4
�n���
]�=��"��f���n
T��M�?�����\	o�
��D����H{&J&yWJP���Z���/����
�����,<�dzP��UxmP��VXmQ��V[[�o�j��-RpGb�����W�.Fj0��j)D�����A����@
�����������e��d�eH�/�2���:��!$�rKF��"$�rK�T��s�9�����0�{���'��2�+�������*F ����
����!��1��`"�h�@�m���q0���+�"��;�2R���[|E�@��o�n!.��l���#Pq%�1_(L0���#$��t��"F��*b��F��*b��Vu�����F!���T�Pi�H��J�v@�tj�8�����Xi�Y�zx�K���N�����:X��7��C��$$�Z/�8_�� Q�+!Re=0+C=�r%D��z�f7��rUH���r�(�u�s	n�`�r��EW����&Cr�T�@T-!��:��2@Hte�@w���'�{�����~�x�d+�Hw�*�^"�}p�V����]�M��w�!����x7�L��h�TVOE�`5UVWE���U����j����2hK���D����'
M�!�@���,��W�������)c���zP�&P�nZ�L��4 ��H�]��!Q���l!Q6�D��~��F��!��*��O���\�_���z�~�d�{����6 �D��0��� B���������Z�W7B�+#�DWFD����!aO�� <	�!��� �l/�oq���B��@���NB��SEW��#B�Z"�DXGVSE�`uUD^[�`�UD���9����y����KH
h�?,]��T8�H
��:F9�V��DP*>���P��~A��F��v��Ao�$����V�@�2C�9$�� ���ey�C�z7����0,��0�3���\3p�9����E���w=s��{�l�O����o|����z�����7o���Oo�T�����t:��[�/�����z��G.z�z���}
�o��O�J����'L�^)�$����?a����<�	�����d�2?a����������BH�8
H
�
�	��0"�	��2)��_�y�gB�7�&Y��_�����]I	n���J���&^+n��R�&^3n��i!71�ip&�������R/�v
�$�S�_$�@a(c�i��n�N'���,����ah�����2;��tb���Cn�����d��^�=;a��h��������yM�V�|���[�z�~�E���~K�p(��]��qxK��t�^Fu!��������P�W�q�k8���r�i��`���p�[��n���.��
��0���	���
��Pa�����gX�����h��
��"7���	��Kc=W�p�$������S�n@�Wo��Ab��f�
�^�� 1��������
�v
� �S9��	�k�������N��v*w}��������Zr.�h8*5��T�T|) B�4�7���<�C�:A�����R#[q�G7p��e]d�B��i(���K{,��[���dD������_@���U����X�W}�T1���>& �����k����	���`"����	������	_���^[��L@#=�8L@c=Wf�&���*�����~��*�Rj>$V�c��KuL`5S�V7EL@�F&H�T���s�vZ|�L`�S���Vs�CN��1Ab����;�Q_�$v:��0Ab�u�
�����E0A�\/�h��(+--&HV,`���Y������i��0�_ �
���W� Q60�rK,�F9����b�]o�xu�Xu�����r���B�Z��4 ����k��n�����zr�p�����/U
�Q�e4���
�
/�
��R������T6�\�����[@�O���_)P�Ab�zM��KX��A"�C��4��)B���A���A���s��
x@��N����N�^�� ��Z�W��>�
�h���2����w�����n�%��(+���#xu#� ��>B��|�C9��}3?�	 sh��zL ����Ep+4��(O�h��q@�.@�����mZ�L��i�t��GA����i�t-��	[2
��%��5�%%�?mB�s@���+l@������\)Sh�E[�vh� �9�&&�_)�3dV*gd^Z��h��k�
�n
� �S�df�24�������7K�?p�L��N��h��i��x�-;���S�ye@��N��h��i��Od��KM oLYy�����c�>� �Ds4l�)������@���	��\'p�_����#'C'v�F
���H�Y���_N������nw�'�6��f�}��U�(2M~ ��B�L��cq�C}��z�7|�DX�8��K}/�q����">��"E����"� ��S�u�%P}�����=��n�e�s���%�P��n;�i�1[�����("�{*�8z*f�*�T�Z+���"�����S�m��"R;�V&l��z��������B����{X�H�TH���������`��/��ttT��������Q/+�H���F��
0��i��0`�lp�]y?r6�SG���fR��O#;���t�����1=����i���%s��Z2]]O���;0�z�/�\�G��g��&��.�(��\@#]�:#.���)�#$��KP���"��|&$�".H���������f�� �3�v
� ���[�nh�����".H��*}rj�N�v*�R���>@qA�:C\����G����W�����!�o��R�2������� ���
./Yq��d�S�c� Q��W���Z"���["�u�#������� ��&�t�P!��@�[�����Z A�+C���D�S��N����5�&@z�>��H@7PH[H@��[mu�C�ji�g��]�I�=�
�A|Wn$��]���S`�R������j�	a$v��7X�!��N��f����iu��i���o�Ej� ��j��Q;�����S��!��w$H�T��h��9��G]����D�e�y`�$�z��F
��ch�}��`�(���
��n�^s���OF�C(��W��]��J�U���������3��H��v�\�P�@t��r��n}2��DW��@t=��{���z�,��iS�;:�(t@��{����zf���D[����w���@�)_i���V�� �2�@���� .����NX����N���Aj�z~Aj�r;En�t��i��$��[�}�X�������@4���w��@�II���[���I$�+V��q��DY����]p�H�[92�QV`_�e��.�9h�]�4���R���z����'b�jE���L�Ax�D�LWM4`�����L�R���-��5K�?m�j���D&�]o���z�c=-��m����w!K	h_wg�^+Z��R�^3Z�uS�f;
Z��S�^;Z��S����������N����Q;U
F�T(Z���PG�����j�V�����V
������(�yf��
�H������
��������r�	��%'#X�=�����{�[f�9��xuo7����G���'����[���I�)���f�E�����Htk�� �n=-��}� ��N�L��I�Y�%��	�_�F�C��&��Q
���+��#�h/��T|��6�t3'J^���Vua�U��p���H��x�F$���0�j�#���0�7K'��N�����0�F�~:F�i5��[vZ<~#;f]�H�t��F�_[h����ae}$S�'�G�B��z�����X��8�����c��.d+��(�Or�.��8�|�G��8��|�A�A�[�a����IW�L�� ��:�(2�zf'`�DW�r`��*&l�r`���=�[�GM)ET@O�'o�n�0�P���P@w[����QAm�Ec�*�r~��|.�X��JX�QAbzz���Mx�PAb�z�Bb�z�=n�*��N����N�_��.
L�����'o!��RBqZ�������@���@4�R����r�=��
��#{��� Q��"����|�������r�np�{��c����4��J�����M, ��i��nB\��`�D�������2,�G�S�@O��
��\`���Gy���L!�h��+X@�W��W��>�s%�`Ab�z^A�y�&��a��Mx�`Ab�rK��",����}R;-��������������9��v*p����K�$vZ/;�"��4h�����:�z)f�}������1����`�3H�
� Q�'0��I�h5pGc�{��f��r0���;�eC���R��p@t-YD��e������z�#a8 ��rG��Yz)��&�\8�h����Br.������A�zG4�A|WH8��s!��Ab�:8�z)���"8��)���Nup`�S���Yf;Ep����K1�S�v�$$vj��E{f�2��]�A1,�c�U;Tg<4p@�����c@���c�(��.���� �F�L7�P]��
C9�9�@
��A
��
H�}����_d$+6�F��8J�+R��l�-�}����"�u�}�B����kI1`��z&l���������d/4R�7���N�0��������D
�h[6r��A������1� �R����@
2��S�n
��l�A
2a�x�H?n�>���3.��v*O]��T�������3�`�N��$H��|� \|�t�l�<������ S�;)2eG'E�n�*�"�gp�+�]#�H)pGb�>
���D��	�����GN�0�q������^�-�����S�=��Y�N����p�{��-����#�>r�{�T�k<�&��������4���3c�[L�����?�;^�/��4���~��A����("�p4X�gXa%4�q��� ��'��Qj���p.�����~�w!���S��p_�gXmq��GgX�q��Igx�p��Jg$VZ��8�xa������1�R9�!��*��R�6e?j��F@�o��.(#�R���H�"��+�QF���Wn0�(+0�Oz0���
�H��+.����G���$�H�
8����h�H��j�?s39�![q�?g����
���:��Zr��cvd�+�<]�e
��<a�",$S �g��	���cA=q��;"��R6����6�Y��(�~Vj8�M�*X@��l$�Z|�X=a��T$��I��,��*���V��<c!�`=�X��ju��v����
U�o��h����+�j,��]+audC������&O����
$+��0��#���������_�;`���!��z�b~$���G�����0��uR0G80�5`�Yk��tx����hZ0��`�k����	��a& ���,bv|-���a��0=������d|���H/����	��&X0�T��b*�T��&�Z*b��S�`c���`����]$��&��*b��V��]$�Zl� �U�@��d�`��V���}�V�����W�v�ZO@ tO�J���U��� T��^�(��G6f`_��-�k!����r���@�r�l)�0�7H�����5D0������hH���	���.G"��d���@t�7_�	D�B��� ����	D�C���&a���z�=m�1���"M�'C���@��ko1�@���^c>�{/���S�7;�*���t�Z*���S����"MH���^[�`�U�	���4!��b6�z�=4��dO�=�d�[��_��&���#�A�	tOgJR�*��*!��L[�h�T�>2���$�B�bC�����Xc� Yq9�=�A�\��� Q6�*��:H��/�����t8��`}d��r���.��1�K#S���<`��Td�j*���<`�x����\�LX���aK�?������d�;�<`�J�m���,a����]{���<��JK7����������
� �+����k�2[�+2[�+r[��A��\?��
��������������z�x��/����L{%������+�
��}����8��A����LY�s�V�l���\<p�_��L��%�/:��h��~2<�����sr8]������;��U���/�`�j�E��h��t����H$�E�r����"?�/�@$�p��	"������~�����$���uL�8�
�D��
qy��(1�v�L����
9�*�4�!��BhO��j��!���,f�r�E��"���)p��"�H��
8�C1^Y8=������KwVZ�ri��[8��������V*�Y��K��uYT�:��5�>4������?$�(���&��|p�]��2����14����6�W���d�z��]9���\zp+z0G����YWL�P��t�L�~{@����L�2X�	{R���)DXh�x��a�����Rx��O��B�c�as�������ok����D����D��Rx�Bb�8�Nk�3�3�WQD��]��b���<g2s��G����|<������P}� ����8�zH�#_�c�L��Z��$�Fw����0`�����b�3i�B1�9��;0�X8�5�SX�D�1$+���Ip�"HB�\�����=+��Y�g�sh,X6��d�ur�L����C^o�x��:V�QzW�����y�c*T ��@t-uD�R���uD���*�SV������)�O����i�5=�B�:@�P��1�s�.tk�{/����Ra|K?�M�@7uv�[�y�-P����l�j����l�j����l!1Y�-$&����d�-z��
��)![���^y�l�kK�F~L����U�46�0���a�2[H,V���@�WBE!d)Pm��7�QV�	]HV��w���y
�/���/���/�Od*XO�d�U>e�r�/D w�)��#W!Q�`�^�lC�B�\�e�c���i�A#W�{,0][`�����l��
��`L�~����%��_H�Q���'piK�?���~6����'0���&<�Y�E<�o��~��\.�T�XO�LU�	^W���_� O��*���O��U���5V�n`��L0@n����j5�`;��S�-v7h�R���]u�A��Z_	��	���	���f�E�G�r�3D���c�7i������d�
�W��_��i��SQ���=
�Or��L��������[4f�U��`�%1�E#Su�&0]>�Q0��DW�w`�|@�=��C#5�Y�%�	�D�V%�Cm�~���R���JN?���-�y������J��K%�P��`%XQ��b%$�:JHL��%XMQBb�jj�+=�=��:p��c���C�=Uj�w��z�W�QSjBf�3W��+�)�@�����]�R���B���&��[e����%���Hi	#��N,N��X�i	��\!Q�'<\F�O�i?��2e	��(WY��f}>��7��'����'b�F���od���B�D�~�\����e(��o)�
�k����gU\A��� �v�GM(DA��@��y����OCDA7Q�d��1��e������<���wX����~��"��:)b	��"�H�T��h6S�V3E,��i5u��~G��:+r;��u�,"5������OO�I��3�+9�n7��C�n�%0�$��vsz������G�� �&�<Gur�7u�+��:f+��%��h��5�0+C����A�C��z��f��o�W�d �H�H����������g�1���{�U��tTH]K����8$�r���t_`��",�8��(=j�������A�0z6>������������$����P�M����D~@��J	���T����U�n� ���A~`�U�������Vc������x9���:WG��z�<"�X=�!���Q������Bb���_Bb�BUP ��*��~\��&@���i�T��J%��9z9f��T�2���z��l��T�����d��d��������$4���������t�U�@4-��Z���DW�� ��@�-��)SZ,��'a_�r�	�D{j$��:9L�����F0�Hw���F�t"$�"L��:S��L����2�}cf�:L�:,���"LH�u��5Y�	���5���a��{��$�9�L��mU��OF��
�j�Bk�����Hx��A��������J�����^��!��Y)�h�������-� I$	�AH��n��Y���OE=M`3x*�����S	������� �r�z@��������N�\Uo��t��:0B���!0]K�&l�C`��T�-���S��3,�a8�������}�[(����_����o�M�)�,�_*�1x-�A���v�O��O��Ud�*���V�,&,5W����� ����i����5��Z�mu)�������d�Z/Np��WB�����?�����Y����S�+������|�wS0��n
f���c���c3F=nG�H�"G�H���f�����7��>�����#��O#��s�L����t}oz���-���#���8���#$�j:���#0aK:��l|~I�F~�'��U������T����&m��0����Kd�@7u���U��+��U�,R��a�t��"UH�u��5Y�
V�E�������;k�&�{�<
�k� ��c�6	�c�$�g�����b�����+��7�]og�
LY��h�!Yq��BCt�z}C�ba��`�����Gn�w����u���Y$�9��
�
�5U0?{@e�a�]�z4�W��>~����?�����������O%����N��z����m���D��\��y��3��z��
l�h������:��Bt��������}��V��\v��>�����������JE����R)�^O�.����V���z@�6�}!�o/�������x�;6$>QN��xW��A��L�~�F�B�;�"��������l�Kd ��h����i����]��-�9_��r����
�1��!�](5 C�^�s.�-)�#V[x�����>�M���4��7�]	%�a�(%	�Q��(!cV����W>Srt����D[��y���������S4���
�Bm��Y��
���b�,�C�F�b}��=Z�z��e��.G90�;�Y���} xA,Y���<�W%DS���@t�M��,����|>�w~\!�h��Q�	Dz&��B�@�W�����=$�������gD#N �����#'P��@�'Pq)����B)������r#NH���r�s�&VN�����NH��:�b3�&�8D4�K%kc;h�B�@�^g��6@��J�$���l�w!$�:�C@��*�-F�uZ��Q{���A����B".tb	��\Pd��<�r�},�
"�r5���(���������oGV\�qy9�W���'0�]����k�(���(�n �nC����!MB ��@t=�+��!�_�!i����H���_�h��B�)"����"������@T�[���x��\|����/�1�@��������z�\�s'!�U;Bb��8BH�����FY�����k�Bc7�j)Bb���@4�s�4Bb��' *>��"BHP�M�Q{�g� BH���D?�<L��=�n��eC���t��+.w�������@Wl�C0�B�lh#�^s �D�'�/:���(���`=q���
�`]/4�����������0�q���L���8o�3pc���I�R�t����N!9�����<�sa�<p&>��x�;=4����Bqp.�P��G��V��/�Y|��x�<B�^s���ku�g�������RU�#�(/����G��*��G��uV	p��^��G�O�Tx�#d�Z�V!s@�&`?j�B�Kp�!q�#d��^' �#�'�>"��M��3y#	��N27Q{S�u[*B	},�;�Q���Epw,�#d�z*����<�Q�`_q#	�7��u
#-���<������ZH����k�H`���'$	4�B{G 	DZ�:D�@�;� �H���+�@h��B(��N�)%@��\xn�$Pq�4H��x�b"H_*��$$��lH���$�����!HBb�:IH�U'	���	n{E�@���j$	4����Hh�g�l 	������@{��E�P2�����%�����I��C��B#	��f$p]}�,�����r9���$��,��,!Qd���N)�6����GY�GN��%��/#�W��
>�zV�Y7X�����{^�t����/���C5���L0]��#��,��� ����(�n=s0�9>�>7�NDVA��aa4�B�:�
"�PfD� ��%1!XW��!��[9����#_E��*��J�,�*�1|Wb���
Y��*��4XE��r?��h�~������c��~����N���_t�[P��:�H�V�C�"�Z�L�4����^��n�Xm����"��z�r����Eb�qn�X�p��~��� DYi���E��znE���+�k)�+n�(��4Z;�z��vd�u��]��Z$+�+)�����3d@�W�z:�Or��p+7�p]�������%��$@��:L�`�5%@��*�0I���B��P�����%�d��~RC*P��2�'@P����*��=������w�9������P��K�8s�[2�U�q@��^��27Cn�J��Q���@�W!=@����� !��:�D�@��t�@�0`�z}h�~� !�Wev���

<$$�*LV���k�*	D{%�4�@u�%�`�[O�h��q
4#$�B��kb��������
)��
���������G84���F��r$@X�\����UU���4-��:�N2�z"$b"l�c,�yF �S�3%`"��su�@c=>� F����@#P��2y0}f����T|"4uG�@���\8�T�+��;2Pq�#%b��"FH�U�����^G��kU:0Bj��8FH�U��H���420Bb�����~�wT�O��Z�L�(�]U�-��i�z���r���F�v���QH�V��Da�i��	=Q ����IRS0��1�d���(�m������>�a��S0���]y��s�	4�z�G�[M���>o��`V����O�������:�30���7�����V�����1R+0i��X�G�^W	X��Z�����>��n���������Wb�����b�����:1���1p��R,���������Bj��~��b��V�T`��N8�r���O�V+#n��$@�j�6~�2�����L�����#2{rC�+d�*|��������r���?�
\|.�W��U�i\�i;�|\���^J�<�#��B	�*��Xo��^s�<��d�}�v��KNFp{,Z��}�Z�B�\n����}�-W��Hv'�:����HX��-'Y ���&�$�"Y�1��@��T�d�Hwu�>
Ah�'
��$�����,�m]H}�,���]�0W_n%&�@��
p�@��}��,PqY�-���i����j������d!������Z�NR���RYm���#y�{N;����.�.3���!��"dH�V��u���e�N+�Cp�nC��+ �� �eHW����PGW��2$+6@w,2$�B����
�����2�j���r��=0���f�+�^��-�����|�u�����7�W�i}!����i�K0�_���	��ny��/����Y�n��P��J(��A��fe�2�t������\|���[9S�_P���t2.�T|�����C����*s<_P��*��E��r_��h�^��������K/���j�1�Ac^�EC�A�V9(#����&IP�����������_$V��V����j�� ������ ���S�g��-�B�$	z����$AW�_d+.s�6��X��yy���0G"J/�{=!��A.�H���a�L�W|�;a���m��5�0������YWeD��At���'7�������A�]UDz!|�A�@c-��l�O������A�u!��"\����������������)].Pqi()���h����i����bn��j(�V+�������Zu�QM��0`����!���_n($������j����~*�C���:��
���on{�K
D�RuA�7B��PHV\�a���r�D$���	o�!!��b�
�T0��C��VpG9��{�������x`��z�~�{DRMC3�k(�����zV����I��&��B�+Pi���$��d���8�
�����m](sVH���7a�i�
��2�,�B">U�HVH���z�
����X!5Z������R�U�9X���a�j��V[����Bb��f������\|�i�7C����BAR�����w�r�����N+.4��:����C����GY&'^!��*��[<�.R����G�U6�v���O[p��O[�����`^q+�����Re�cd�\�Eq�?!u�5����{�`W��W��i�g$U5d/P]f ����$��@c,�_�@��Ff���B�!f������"�����
�_]�-�g�]��@�?��4�*�usP�!����-P��T��3W5c!y��9�{U�9�kuXf���^��$���\@�^���{>pZx�fhai@���Q4���i�}s-$N+��G���$!Z��3�����i��(}��6TC$O��u���D��,��a�z=DC�5���8\H�
p����������`W~TE$���"�'��w������H X�^w���
��%��VFAu��,aX�1�,ie�;�"�P��X��V��!X���P�P,P��R�`�>3�
u�efJB
�*>UN�*.U+X���D��C`!qW=g�>��^��!7q�,��Z\5�j�B�E4��+��{-������V����
�-�&�k�s�n�^������:z+�k�Za=���2�3h�����(	�&$���$�4��aHW��0c�$�����vd������+�8�{���`W��^�}�q���w$�$�����*N���v�8��o5%��y��z��G.z��^�[�Q�LRMC�I�[��At���[�I��k}����w �����
������t��)�X�v4 �TV
��n�����������Uw�k5'@A��b��U
��t��D|&|-F
B���af�E
���m����m�[�[m��D$��r����-��N���i��g���v;��K��G�X�P�p��;���z�$�+����:n�^�$��2!��+�+	"Q����z:DC#��<8#U6$Z��O7�:���������>J�L����H�����5��#������&��j��E�<����&����4��q���y�*� ����[�V
��zj:Xp�_B�T��i��>�+,�"=Q�E| ���6VgP| �K�'�i���'����O�RS0��(��|��]�~�mDr��=�>P���%��F���V�E�@�QG
Fb�zmGj�z
Fj�z
Fj�z���ud������I������"��F��%�_$�O(���Z��,r�Z=}"��L�P��]||"��h:Q����%"Q.�\D��7�~Au����0�b�LTu����� �Ww�<u��K��n�]x��Tw���[��=<�����"<`���
��h�t-uL�T���g���}x�wPH�x��gB�P����Wk6<x��
fx�E�-d�.>Q�d<��S�L4x���J���\|!$<��,���<�lVe1`���
d����m�r������b=~-�6[��M�P�=�}/'4����U}Ww#.;X$p��>!T
���l��2p�!�-����������$d�z[��{���$�������H�I	�GR�_�8r.���~�>-���D[{�[b�}�-1���
:�;�!6�#�~1UG~�� �[���������-�	|��=81�>�b ����^*�	1<I��N��n@�Q������1$�B�R@T|����@��9%���C���A����r��N����l1���
���R��Cj����C��&e��a�e]������m(F\v��+����L��y^�\)v����@^Z���:E\�t���/�X((�b�LY�:�)�]'���`� s41���!Q�+����'[�|��8�[�%/x]���D�!j�I�j�` ����[�0!^ �.�@���v���y2�yS�E�"=(�"��O�/�x!9��i���4N��
�����\i�
x��/��S������5�^�l�:b3�*�������x�n��vC�v�j��F��R�-�[�����>rRd������";�������D}����e�������2��R��Q���!]�
%�-��^���<�@���-���eC���Z�+7���sd/��.$����.�?'�X��;����y}S>���������������#�f}�[�K� ��d�h����b���������F�>�
�
z=9��^I5/��R�-x1zZ�exA��W;�T|��xA�����_(�^P���]^X����p^$�[|>�q�w,���AFj�:��1_�_yd����@��rdP�@����2����q����Q��_�Gw&��W�Z%#�H�>�	@���b$�zS��[��{��+�(@�F����/:�3�Q��^s����E'p�{���C�)gJ�c�t�j������^9MK
��$I�z�;&I����<��G�h�i�4��$R��c��|��@��J�B 
O�_����4	��2yHw�*���
��/�Wk 
T|������<����H����Cj�z���h�����i�h�!1�33�e}����*������Hu!TH�O�:b�3���~�\�����Ra-s�F����j��<<u���#����"-;����#NpG"�#�2\i�"y,�_�'�c�"�+��O?N���;��iyz��$0��@#�r�c$J$�S�-$��(`�c����f��c.���`L���l����[`�Jf0����*�&=U[��^����-�X+3��-��D�l�Y��`,u����K��Hr��2�0��)�&�_m��-p����q=f�Uh��B��rI&l���6Z`�����
�F�r�-���������n�R������
��)����pC���p������F���+���x7��Z/�^�J��i9���s2�zW�80e������LY/���_�apG#��{�����s���g�>Jb?r2��
�3��g����4�e��J2�'�=\�����������k����[������Xx)�@��[0�"�PR7�XO��l�
D\�
����������(D��<���;��>]�9 *�R�1P����/�Cb�r����W��>�e/���k��D ��\��Cj�r�Bn�Uz��nR������(�xV��r�BA����gV��n�gg��^�����.��4DT|)\-$>[�`h!9�u��B�$����^a�F����������(h���b������L��h��B�\~M���F��D�>�4����
w4-\_��_��V�L���n��h��z�6UI���&-�0���tw��`Z������"Z �KI:2��Y?C�Dv�^���T�����wUE����/�,a�T|�$xfHlV����U���U���U���`��h����UwU����������� �v��wYe�0B��g�n���2$FX7����/�q2��k2Pm)��$��i����}��y����{��%���r��317�^�"a���x!Q.���(�~���v0���)�]���[3��NN��^����d�j;I�Y�A� ��v�<�z;�g���fs��$�P��F\���H/�,Lh'���d�D�4c�����;�|��*
���+���/��\y=|A���f:���K%]���o_$�[]q���q��/�I~�r�se��+���-W�����^��1A�����0��n�?
�����0Ef$���������;J#�H��9u3���h���
Y*�����������V�Au�������7@=�	�AW\.;����SW>��L�0�@F��7����&��s�&b�ub�#�@�e�����i
D�RyAt-M$ipM�h�=�����$�����4�Jo3�D|�|���$�=T?�!_���UTK<��K��J�=�*nW���O������>b�Bb�zzD��z�"<�?���m5�"�Bj�z�j�������
������Vd
D|%�[A����$$�'�|7b�3��G�u)P����R��zx�+%�(�"�C^5o��r��A����:$+�^���X��<eP���
��CfD��z��z�\�Q�~�\��($���w�#3�}�*$�*T�m��K"T`������L�t�/�����������Y`P�I+�x�M�)�S"L��v����+$p���!@��3;5���g�]@7M���H�;Fz�@��[$�G�������
@����x�-#y���z$�ku$e	L|���l�	��_���#
jrB��u�L!���=�Bf�J�����l?�)���]H�����z�B�2�z
G_k�)�T!S.���$����i�$���$�b}8�{�A��T!S������'[�
��>������;��a�;2X���jAD��
���FC�@�ki��c,TZ ��|&�|�@�@c=��!Z �]�e-�|�gi6��:�1Cr��f����79_!q)�Hf���af��KaBb��f�|n�����!7Z��Cn��pf�q��+p���F�z)�!d���4�F]�De������"d��3��B��e�n�PG��WBI@��G�)W?pdH���L�1������W�'.��E$.�IbHV��tp�d@�r^\F����q7�\�{Q�Fv�>��!��1\�_����L��$��d/]O�v!c!S
�0I������4�J�."������I���������AT|�|��@��J1 *���1P��s@������*J"2��g_�F+���Vn��m���nh��i�L��m��h�)�}��f!�O�u#d���L��
�����3�2P���&��Y`�Jg����[���"��������5G�{���@����y�oY�5 C�:"S��������R���!Q.����hd0+o������t~����?�������������X�?v��f�����O���������������}�CI{��8���-��-�p^��>��c����R�s�-�������R?���[��r��_9��9v�a��mT1��4���4W����a�����r���Q/Q�G�S{W���P�b�f������6���x���x�����>u���g���S@��!�T����+%�|���c�h���e�(N��.����\�7v<�i=�}{B��R��G���t�-�����[������T��������"q>n^���z0������%n����9�����>����p�#���^��ozp�#��G��~�#��{�~��/�������4����������T��>��?�]��lxs��
�O���^������o��T���?�i_�'��h�WJ�9������������������m����?�����������|8o��
���kl~�����c�?~�����_n�����|����m�;�����|<�?4�����S�g���������-���?�;�������������������;����}��iL.��U�xY���n�S��]���8^vyW����������`��i�oI��U��q�����
j��Bf$������j�DYy���mq�z�����]o�mx�{:��t�������|9������K"��m����������1��R�x���V>j����G*�u�i0���D�����=��a��)�~���(�o�x��_�DV}
P-/�9���(s�6������V|18^��D�������4 �TJE��#���7�Gj!u�m�9���s:x3��\�u���o>R�>m��z7�l{�N1�5o�������pW�n6��?����?����??�����*��$yW?�_3���o�>������H��T���'�L����_�y,�C������G�]����}p��#\��J��~������N���x3'�J�o���`|
�o�D�����eC���Oc��fN#�R�5D�_=z��w�dC���p���G��������M�O���8�R����I����pO"��e��i�'B�<��'�%$PE�G���r]o�����$�����<�j�~�d���?���������������rO���gS�5�����
������������q�[wh�p�[��}�E�z;������a��3�y�\���(W��6~��A�6Ne��<x'�w+V��m�Hw���p��+!�o�4�s%�n�4���9�����Qm_E�qO6�]i��9�\�����_�N���.�t���"\��.��pAO��^T�t*������{&���:����.�D|�K�CY$g3��������������W����+��?����J>���
�_�5�����z��B�5Z�������g+6�r���u7@y���������P��D�r���f
��M��<��+�������+W_2�����d�s��Pf�w~*��'���x���x">������*����O��J
cT_r��{M�&��\|!dRA�}�	3�#�����y��<D�;x\���H��
��!�'��?y��l����L��~�	}�"z�!*W_���-�Co���3}��2Q�W`�}v2��--��D�r�t�"��;~�k�kV����5�`����T�w@&���SE4w@&>y�9�������V��C�y�L���[%&W_����E-*1������Zc�\~�h�P���M0;3B=c���rV�z@�����y��`���&����"~MD�*+��Q���9*1���{����*1s������q|TV�q�+/�8>�q��?Kq�*1s{��{�����7�J��wx�T3F�=���G#�3s�zO�x���A�S���L�A����=��-�����aWnD���^���X���]q{��>O��+2��L���iB�+4��7"����3�|�O)vg��|�`Zr�	���P�������B��{$�;Wr�#�����Ne�I&|����H2�<ud�g1G��}���D��3^%�Ag��R��*2��6�S�������#��m�O9�sK"���s$�v�?����??�y!�$��/][�8���q��dgGE&��r�nWs�r�����'s��b�^q�$�)�?������I��f�?��c���Nd'B�
����pS9��f��i=+�e[
�xY'��G7B9-��O7�}
�\I��&�z�F��?
�k�76w�$l�U�>S}�x�`�?[R��i@z.
�
~����P:���=y��\ �����]u�����g�A��>=���y�>~~��5/�q	��|i��.�������~����=q����C�f��8x:�;;Frg�en��7����64�����
W��K�v���{���������q�2\�����/�DZA�������-�\���WB:4���6*��N#>W.�pK'��m.$r3��#�:BONK�>/75��������.u^G�IP�B_��'��2[7����HE�����?Br#���O��4n�})�5o�q���|���n�������~����;y,V?����q�}��}�V g�$�.����.�������w�����3��x#�*3�����Dn������e�
endstream
endobj
20
0
obj
54666
endobj
21
0
obj
[
]
endobj
23
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
24
0
R
/Resources
25
0
R
/Annots
27
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
24
0
obj
<<
/Filter
/FlateDecode
/Length
26
0
R
>>
stream
x���M�����w�F�
y�;�=��I���
����z����
w�q��j��w�!�����(E��������*w�!��M26��p�u����\���t����/.����+��������a����y7@zo��u�Ww�L��n~��%_��<��_������.������S6�w�<=�����*���������?��]������b������b�u�����
1Oc���y��	5����
����z��5I���}��s
�$���-������~�Rx]�����I���Brur]��T���b�*EA�\S#I�{�@H�nA�������b�*EA�\S#I�{�@H�nA���g�����U�����F������\��\/z�.�k�a�*EA�\C3�b�u!���.z�j)�.��R�sM�$a�u!���.z�4�^��RW-�p�R I�{�@H�nA�������b�*EA�\S#I�{�@H�nA��/����}�Y}7�	4�,�^���[���;��+}���@�\Sw��W���\��\=��^�n�w�sM�$a�u!���.zT_��������zT_��
��������z��]�
��55����
����z��E}���o�"���?�f����Brur]t��z�/���k�^}�J7��[��������w}7>��H�^7��[���'��+�v}7>������n $W� �E���Wz���@�\S���W���\��\?�t�������R����O��${����-�u�}�Rx}���D�\S�IK�u!���.:��k��=�M��55����
������i�\{��|7>���������\��\=g������&���I���Brur���U|�J��U�9k)f���d�����\��\=\�^_�|7>���EK�u!���.z�j���|7>��H�^7��[���s���z���D�\S�Ns�u!���^tw_���o�"wZ�,���,�^���[���;��+}���D�\Sw��W���\��\=��^�n�w�sM=��^�Brur]���z��]�
��55����
��������z��]�
��5uV_��
����z��E}���o�"���?�f����Brur]t��z�/���k�N}�J7��[��������v}7>��I}�J7��[���'��+�v}7>��H�^7��[���g��+�r�Ka�K��g��+�@H�nA�=\�W{
�V)f���'�L��{�BH�nA����W��u�w�sM���^�Brur]tR_��������:��^�Brur]���z�������I���Brur]���z��]�
��5���z���-����U}���o�bV���$���-������^}�J_w}7>������n $W� �E���W����@�\S���W���\��\��W���������F������\��\/z������Rd���'�L��{�BH�nA����W��e�w�sM���^�b�r���P� ��������\�hW���\����������X�\�������t!���s
�G���c������s
�$a�u!���s]�t�$�^��U
 |��f����Bru[���Z
�/
�Z����5t��v���m�k�a�\{�5k���:���:��n $W�u���������X�\��������t!���s
=_5�^O
�Z����54����
�����u���I���}�@�\�$���-�����5t�k)��6�u�n�\C��H^�Bru[�:��^�~�w�s
��W�t!���s
=��^����������W�t!���s
=��^�i�w�s
�$a�u!���s]�|U_�5�[����h&Y��n!$W�u��{��+}���D�\C���W���\����N��W����D�\C'��+�@H�n�\Cg��+�v}7>��H�^7���:������j�i�*>���${����m�k���Rx}��������:-��
�����5��k����|�!|���^s�u!���s
=�k��=�m�k�q�\{�@H�n�\C����z��������Is�u!���s]��"�z�a�*ENZ�,���,�^����:����������
�s
�MZ
���m�k�!k����|�!|���������\����g������6��5�8k��n $W�u�������q�w��I���Bru[�������k��J��u�L��{�BH�n�\C���W����������W�t!���s
��W�t�������N��W���\������W�t���D�\CO��W���\������W�����������W�t!���s]tU_�5�[���wQ4�,�^����:���������n"|��{��+�@H�n�\C'��+���n"|������n $W�u��'��+�v}7>������n $W�u��.����}���n"�f����Bru[��S_���]�M��54����
�����5���z��]�M��5���z���m�k�Q}�J����k�Q}�J7���:��Y}�J�����k���z���m����E}���o�"��&�h&Y��n!$W�u��;��+}���D�\C#I�{�@H�n�\C��W����D�\C��W���\�����W����������W�t!���s
��W������������W���\���.z������Rd��D�$���-�����5t��z������kh$	{���m�k���z��]�M��5tR_��
�����5���z����&��Z/A[�Bru[�zV_���K��\�����K�����\���.z����zl]zV����u��^���-�����54n(����K��\�����K�����\����N��W�u�Y���:��z	�ZW�����>�����_�8L�4��i��0�A�,��\�����"	x���iP���w������E3���II���y�Ly�7�����)�q���.���{�}�����>����y��8Dl8h�'�{�l1�G�w���r��^�����R��q*���{��rL]��qTD������~���j��+��C
u���A�k���Asd�P����o��p�o	{�`w}R�?�7���� ��-�^��u'lR�6A �f���k�p�*�h�2�1@���>� g���h�,�^��%�VW�v��b��v�^g���;k��c��k{����l�2Y����d��z�������y�v8�/��^�{sv����M@���qQO����"���^ej���9�
(�^W@��������:0��n|KvY���&�)���V}R�cpg�ChNk�9����������*�����>���eaS'�C�{�l�aGN��{��Ec�{��US��9i���b��x'\����K/�(�y�S^�����w���s'z:�A9��k��w����|5.4z�����a�~RvBz=���������a���'�&g���p[e'�uz,�7��}��-(;���2��-s��kws�~�����h�����������"���^��.t��F�~�>o��������Q�,E#I�{}���Dyg�E�4�����z��[���TW�s����
}�`�h��{���z�
@6l��EP������Z3��Sn������-�l��6G ��d��Z�fN�*dU�lc���Q�A�����p�~Gh^�?���B�F��[�t`����������i{.H��5	�G���Z����6��O��C���J�tE\B���!���A��z�n�|����{+������?>�W����b^�a{�vz��7j.�����y��tGRs����+�^o����
�E�����,�^+v���z}�����Ga���O n�P����A���zyT���z���������������
�h�,�^;��d����[)|�`���Y��h{Hc�#��V��F����(��t�k�{��F�����GI��n/��W�I+��{����K�
�'&\��q�J�h<�{��;X�ze�E�a�T�B�R��vT~`������KWF��R��
�^�>Z�T�bX��b���'Fk��E�'���
��~�����6���	��b��s�E�'u����C5�����F����_�,�x�r�{��++�=��V,4����P+��;��i���p�2�:�E��{]�r�3���b��)���Z49��k�
Kk?����;�f-����bK��n��_t����{�7��4����*H�� aZF������b��K���	(�^oWj������Q�n[k�^o�aL����Lf�aXt�Z���:���E������6��bV��z�
���?���(�x@��h<O{���������_u|��b���������U��H�9�^o��3��e�}�~s��^�3�gg��j���������w�W��l��gm0��z��6&����R��^�������;i}B�E�������~�JS��|h>�V����
��@��L�����5P�f��k�e���!b���{��[��_j9��k����v�����.Z�Ed���Xa�?�w��-�^�[���u��G�.��E�m��iG=������	���������d�g���iY&������H�&��{�T���Cw�������n5wJ�Z6�{����i���j��a�����lW��`�>� �_���j�1��Z�K���6��Ye}���{����0��b�6J�5�����,��*�U���vj��o�;,����
M�|
�RQ.�l�}���X{X�NZ��|���C����9XV��8��U8.h�������'Gv���5��ThR����zl?���Sj��������{����E*4)�����Zf�a�X�E�����M4�����E*4)����i��(A���
��a�9��E�nZ����5F�ThR�k����6LT����e�I��^+vc�Qq��5R+t��������zXh{C��qu2R��A��S��v�mmF��k�����
�^�RZ�/;��j�	MF��z�n�����@NC�^7?�z�OG
�������O�!����b���Fa������#�����e��Z��_�u�j'���V)4_���Po~�vg5^l������a��8np�x�6sz��22���@���R������.�t
�"���kW��^�^�1W�B�{�����g���bg�A�{����p�����A�5h����5.^���k���&�K�{���X���Gh�/�^��%�gv��e��x3�,�^{��x3��N�Y�W��v�jk2�WxB`�93}������c�]=c����S��������5�-���U����O�${�F�w��,�^�����nDmI��How�� N���5�-��)�^;��M���An����^��V�"!3��Lt�i�B�����k��a�����]��mi��D�b���5���Y�{�]Yb`��_M�	e��7�{�zxK�����F��V,����)?��5�C�4��(��k�fmQ��i�$����V)4��Z�(��v�4��0�5��=�g�I��{��w/D=/�bD����4�m��gJu����uY��A��*4)��k������YK'5wJ�Z6�{����m�.*����xPJ��z�WAP��Nh-�{}Z����gu/���I)�^o6&��J�����Q��Y��^oVk����$@���W�{�V�{�Y�h�}��I��{�������^c�]
vuH�t �l�� ���F���{�M��	Rs���e�����0:��^��H���C��������5���E�"}���K�>��m�B��")���o'��kl�qg�W�{��*�b#jg������m�������0!vy�n3���
{������G�9"ht��`�u�����A�+�4��0��k�����eo0w
�Z.�{�w,��@��P��v�`4�a1h4�lw������6I�X�1uF)�^oR��=]��:k����Mj�x7�
4��8�5���
�b���:�NZ����awb���5�n�%�n��������AFk��AF�vD�a4��|�����Z�;��]c�\�{�}!I%��D�����{���z�A�v#Qf�Y��^�h�h*[��]�"��Q���j�W�W.6�13(�]!2�Z��4%�Yd�� �
��l���������0��Zm7�\C���m�OQQ�G$��(��Z��P�$�����{��jJ�^VAg�S�{���n��u��B�U&�P?�u'Qq'�Uh���u�����	HXY����������'��K`�q��*�)��
�z���.�e�h^6R��V���]M
�C_��XfTh��������	�[��*D�v�IjW��?��wK�q����jW�=�Yg�Ah�u2��>T�`@���U���g�	;�D�U�I+�^7���Dn]uE�le
u�h����}W�E��.���k��q��[�dTh�p������t���iHH�%	{�bo���MH8�`�����8jO �DEW���{�'�x�9���'�D���H�PWP��l�E�0w
�Z*�{�����lw�b*>b��=(��{���U��8�-��"�C�T���N(�S��{���+�
;k�B�J�a�kL��	C��K�T��|
�f���Hb'�Eh�w�u�M����D/m����?{�at(GW� "�MJ����nM��@��x!K��{�
v|Z.;�U����V���%��E3�b���EcS�x��;�'-�^o���YU�:��I@O�����u��{}� ��O.��@v	�����5�_�r�������A����@�������
�=i�{v�eG�P���k������K8M������Mh��a�#%�����Pob�=���V-�]3���p[B��%����s���b�u���
_�����B�MS�+������������^�b���JOn���S������WHl�-����C�����\��B��)��V�i�Y+�7Ls��
��������+-��~�
�����
��J�>�����	}[Bf���^+Q������^-q+��{,�P;`�^��$t��vs�5�
��DiT�YK{�+�!_��&Q������������������J2����x��b�5����,����5�����Ol���\��k��Y���!��8@�6�b�u�q[�2*`q
.����H�Rw��b��h+*�^����;k�MN����`���C��~�b��v{��&�g�Pt�/yiA������zs&G,{�,��{�����n����x���w��3����0�S��v����O"&�m7&����h����e�%�7����kG�ud�)��vU�5��E+�"#�+j�S�����G���i�����k���]�*��!�v;
��$�����^9��F|7kQ`�u�h�A�A�]?p
��Ec�(�mW��V���(��_k��Q�������X�<�;kE��kW��_f�V�r
�0�|
ul��p������P?�e��5�c�U��M����������A �]=0��>�����r��^+���f�r<��{���&�a1h�1���}��a	^�>���;R�7'�t
�0���
{�0�2������|
uP�v�5�b�U�������4x
�0jV
����[�����$�����7��L�<?���/y8(�\����������j>�T4L
���X~�C�
�k���E��yH~���G��#��B#>���{���:���}6k����5v���j��8����z��{�])�^�Qq�� w��{�=���C�F|g���Xy?B���Z49��k_������|X��5�A���S8iM@��z��3���rON��X��������*dk ��^#L,�b�u���F��O��84k�`��B�~�����-�)�^or����5���E���>��
o�b������}
����Z�^���!�auP��7*��_�N����b������,���<�^���$p��j�{���r����!�}RC^S��V��'�*j����p��Z���1�TuE-��_�'��{�{��4t;��1n�v��p���o�7//�}�g���
*{�����{�������Yz)y�V*4�s����N1�
4�� �5����h�{x��"�AB'�Oh;���Z;���k�~���EW#��{�
(8t��Q1 �
m���P;�������N�Y{�������a��S�������k*h-��������G��A�p*���O�>@�o��^�?�N����Z�;?���:�����}�zl�=iL�����3������kd���)��T�b��&5�a]O�q���d��z��6��'����b�u�]O
���ur�L�+�������5���Q��,�b��A���"n�J���M����p��rSL��|
�������5����V!��^�����Wf:��x����G�{�UG`�6�b����k���&5wJ�Z�b�u��u��1���e,�^o3��,D����qN��z���2���/���������7����������
*�T_w��������N�����;[aI��
������}�����P�6�Ie�`(�{��z8
�\�
J"�^W\������(I��k�A���m_�������)��dn�z�Km��S��
�^7>e�zD��i��%Y��>\&�)
{2��u{������=��)Vw�^��]uA������[�R~��3]Tv9
�2J��Z���~�;��Hl���p��Z�����eG��(�{�;=�q�f]��3tm
Q"�{�����z���������y��0�Z�p����^;��"��S��3_C���)H�t��~�����j��`����V��0{�F*-����f��{�6"i66��5n�Xh��`
�&�*l����qC�B�u�P;lp�t}.;��
�h�l�����'���.�ACF)�^���.�Qg�Xh�/�^o}����Y��=��L��^+���;|�]Pc�;i���k�
�Mc�d��]v�;[4�x���i+ �.XZ=8fT8UP�I)�^;����Qs���e������{H�������b��vi�.:���;
�^��E���1B��
��M��a�A������{��kM��@F*4)�5�J
��{�F��^��*�>�J=��5~l�6L$����{
��0/���5����
��{]c�;u���E`�{�`���^�!\�[4�/�^��z���^��[Y�������u�e�Y�L���PY��T�J��2�b��6u�����:i���:�>���-���t-�������{}=�~�!]�A�-S�+����
�2h���L����1�~&��]��,�b���3���2 :�Fn{����tf��"��zH�~��������y	�0�Z��q���/F,���p
���6��U
m@��V�-��d�
]Z#�]
����{�oE�-��=�Xm��kk���v	�j�V?�U�E%�����b���^��~�4t�0��k�N��U���Qj�3(�#�^+to�_���&��{���0�Ak����{���c�5Xm���k���v#�5���lK���w��5|���V+����S�3D���'
[t5L�:�b�uz&�	�P
�B� S�����Q����N�YK{���� �]���b��&6|q
}��2&�Z�]����/�>(�@��2��'�0z9��V,4���Po6�0P�T
�B�M �P+ucsc��o�Ik����}�7�;K���k���b�� ����o��7*G�\3�b��65�|e���5�f-\����������F`�X����<tN��4vm��H�H7���������e��z����k$�Qg��b�����wx"8h��%9_#�]�x#�\��;i-{����k�������{�//��@��S��V�^�a�� 6�f-����6�Y��(�ql�)�^WXl���Y��@���>���,fc��P�
_3H����o���U
�K�9��
)��f���9b����k�]�9�	a�I+�.K�C-T��p���z|m��o�4jn����K����
U���������5G*�]�2����8o�vs�������Z�z��>�7bg� =R����k��ZEX�X\��bL�����K�C��j������8_�Js�*��KK�P���s>dJ5��\��R��")��v�����7^7Ji���q�����������^jr�����e|O���aP� ���^;lt��
��T{��Q�yT����}�����j[�:mK�����J�u����V-4(���Q������l�&�&���k���F������|
�V������<YE*}�����{����v��*r���Sj�������J����B��C�PW����t��p�7
�^os�b��V*��`I+�^+�~�_��>�����6`�{|�p�b����Q�I{�]1wF��B�{�1�wJIs���'c��aP� m��^�~j�u}���0���<*c�C�d�5�Q��-=F����B���>���I�48���=>T
��)�� 4��C��tX��I�I{��[��V�p�8j<��+�[�����������e!�.
������)���r���)0k�`�����Mi�6q�v]�5�W��1i��!��+��Pk�U?I������_�����,JZu��Z���0\AU[��K���)�Ja��B��K[����&@��BG))��V��<�|S���p�0(%��v�C^L���������Awl�N�i����Z��Q��u�r4�2�S�8��pA9L�&&-������R�AZ#�m�����{�a��<�sOn��Y�����_�4n����|��k�e�L��fR9�k��Q{�u�f��uo�EOv\i����L��&�E���<(I���{����]�O8��_2�g.�){�k������q�Eq���^�R�zU�+p�6N�#�l����aP� m�^os��k���G��Q)C��Rw�/��q���S�]1�{�����-MH��z���w���kmD�������
�4)0i����~��i�rb�J�,��n����{}�x���p�P�*=&B(�]�8�Z���3�*ps����������@�U�R���k��jq{�X��S�I�mw(��vE�{��
�F��,�]f8������j��#��A[1������1�����QJK{��sX��U���aq����P+ugQs�*s�9H������I/`�G}�7?m���K��E��U
{�]A���AO�e����~�ht��I�I['����$�9p�x
�)��u����nub�u��8�����7�PW8���G����N�YK{�����P��+��dPL���}�`k�p@mWm�����#��K��	{����5,\s\�h{��������gu�(u�����f/�VfI����D:M>��^�����U�yT`�VD{����Y�\�M��&'�Pow�4��0�yy�����Z��x��zxl����kK���C��+�u�yF����_���x��L&���a��^��:�zZ�8h�"�j-�^�GL=.f�����>�J��8�x��[Ik�..�B���WA8^f_��������J��Y)�/������X��2��
4�Os�vL(��
�di��Vc�|0'���Q�yT�����kcs�b�*4)9�:���	3�iR`��{��>�G=���jL�-����q����9�24��Xh��v
�b�>�d��)6k�`��bw�&h@1�
mw�^C}���+���2�[�]��z�f��4.Z��A��kh�P���E����P9����j+����P����G)&������Fjp1��MN�C�
ZO-181������g�����<*7���P;���:����MNN�n|R������@#I�{4��_�Gm&�RB0��n�	~��4)"i`��VW;����7]�y���{�a�t�8nJ*��75�b��������iS�f-[���Q�c��>��9%�h�,�^;��>:=tj�ES��v�c�G�o�j#i�{�kh��=s;�����|����
i}��y0��2G)$������:������{�$�����
���,��^o?�p�/\���-�89E��-9�1iu�$����Md�c�K�eE��q�t�h�@�II�R���C��<�>������|o/�^�h��~A�!`_�]J>��B���p���)6kI`��b��*_�:�A*=�
�R���������@m��������h5r���$i5��kW���.����)��T�{��=m�-��J ���4��!vw�
�Gf�@�{�(���XD@3��B�\��A	�4)6I�������������s��h��^����
����:�������P+v���)Ps�������;`�����������{������q���E�M�}��{���0�MZ�������p��������v�y
u��z7�xQ�(����k^{K�@���]:�9�A��~��
��i�����dh�er�	4��P���L���3?�����Q&��@�II���~��q$����Fn^�_��NO�@�G�I����P+�@?�F=L.�]�
�&�}&��;�L09���qwW���g�������P?[^�z*�P���)�O��K=l�Q�K{�+���@�z.���k��
1�������e�p�'�
�G}��l4����a\O�'�P?�h8Z��\r������?0�n=�k����^kA���I��.���B��z�8'�3ESr`��
�)�����SlRs�������J�����NB�L�H�A���
�����B��h{��uE��x��J��s�=�0����z=��Bm�P��G�\�D6fsF*���^o6��Mr���,UG{���k�b;@hr
�+�����@�gq�����M��d=K4��Po�nvv������`mc��,{�a0��8��z���_���q�8
w�3�As���e*�^;��O���+�Ee���A��������G_
�hb������i��9B��WB�&��{��G�ug=��T�I)�^o5<�lc��~5�(e������3O�c��~5N�#�{j4O'b1H�����`�>
d�<*0�
�H7�����C��VK2�HGej^�`�I�G�{�[e���GJ�(���H�&����~=P���Q���b���>e��5.�6��.��_�
mo�L����}j�z��pY�{��������_�mo�\C����k�������3�Q���T�C������a]s���$)�������o������%����j���n���I
:Jai��+��&R��l�A��'��V���E
;��!���C�]o�7����r�>���{?T�U�Li�M
���B�dS6��gY�;i����nT<e�h&9��~�he_��iRn������?;Ag5���s��h>�S��.�G�����?��h{h
�r���7w��Z>�{���a-���q�1(��{��;7�m�
�j��.Pj��F�o,��<I��^;�^(���5�����d�{�Z�����E�����^ob�=Rs[�J���H��4�z�j�HZs[��bi�����Z&0�
���>�k`4
6?Up�c\�dM>�PoV��_#w�F
��~��u*][�B�2��V����~�4)4i�`����������t��+7�������u�1���@�3=^l�b�u<��Io������X��Z�;w�Y�cB��%�k����}��ez�x����Pt��]�A�ex���K_�g�g{Yj
�b�8���G��+�5_�G�g{�)�Z�6<������U�l����RV�{����%L������1����9�B�����b>J�p��K{����]`�JO6���P��}A�Z�n��J��@�C�)+%�P��-��^���RN��H��%A�{����S�����sWz��ThR�9���_�+=bm��e������8U^�eE�4-����&.��t�����������;��E�
���+���kO��>��"5wJ�Z���kO=z/�pj�.��<��n|b%j�
7Elqk�>�a{����4�)`���]�a{�W��C��R�J�6q���x������-�)b��bG)l���c�R��j-G,���0i�
�A)�u��.,�����A�q��z��{ouK%}�yTh2���PN�m�4�C�tU�����
�S���:�U�N��m�������z+�s��X87`]a�9��]G3�B^��4).i�{�D�l#��r����L��[������7=���m*��/E��S����o]��*j����l��Z�{��k*�WM�R������#�p�f�m����B��:�B�3�-i����u!�?�hK�Q���Z�i%.�|P������G��E���n�j|�6�;�+�0(u�6D{�7+5����5�J��R�>��������)\�d��������Zo�u�b'mP�������3�Q�t)\�hs�����;3os��I�I{��yR�<_����K\M������_����?��Q�t.XFmON�Vn��3���N�Y{�]a��n��(X:�]�{�{�ld����h{d��fq�Od�~���u{��{�w1b����|��{�����k$B��BG)+��h�>��w��CV�tp\�tJIs���p|U�y0`�A��4d�{���������G��Q)C�CE�"H��D��KVJN���_Y�����=A���S�7�l�x�q�����{�]�i��d.�4)5i�`�����a�����8�c�������b=�n�A����(���B���W5V��)6k�`��b<�V�tq\��)�^+�XHE���h{~��R�^`\:8,��V.��v���"z��k����d�{�\�]y���������Q�K{�7?s=4��2.�T�r�j����u�*v;H[�����
���@��R�����s��������*+&�P+vw��i���u�{���s2]X���q=��	�^W��N�zyG\���L��z�k^�pO@.M(��s|
��{=n^����K����)��`�B]Q�������G���Z���5��+��m� ��V��{�trS�Q���e
�R��F�(��P{��'�Y7���{*�(����O5`�rY�Q�IIs����Q�A��4`�{�@.��{�����yTj�2��V*w��U<l�_��?��%+&�Pk���I���M	�B�B��{S���p��M�8�Z?���=�iRj���������O�!w7m�����{�alK��Cnn0h�W{q�����P�A�����h2���5s�����tirgCX��v��F�������
F)�^������J.m0`�{�}1��-��\��d��)�^G�N����/�����Z���k���a�����Hou�l�p�gu+�0(t��{���u��vg$�QIy���>��m'��{��*[�ar���W���o��������	ML������=�������
3��vXb���'�koFh���l�������atr�E��c���P_���Cq��D��0
��V�N�	��\caPh{�j�����=B�����m/"��V���	�K�"7Y�^W�Ca�C�K,{���|�!��"F)���o9.G�{�sN}u-~��jND.��0i���Z�@\�J��^i��&5�i�.Cn���yT���z��6}��C�"�[T��B���A�Ux_E��EA�s�S��{�%���0���pi�
�^��fx���4).i�`��� ����G.�(�Z)�I�b�u'G��^}����6
m�PN���n2o$�kT������Z.�5)�����Fr��A����k��K+����Qq��(�Por�?6�Kw%�k�^o|�x�M�$Wk0j@`��Bm�&�>����5*�(E���B��J}!�c+g�*����QQ�j�2��n1<�N��aP� ���^�1�Xl�Q���<*e�C���c��5����%�P+�
_y���W,]�\�Qa'mN��Z�;�x�E�=F�&e�C���=�F\���P�������{�/�g�B��s����b�ZVa$%�vh���aYR�=�9��Q�~��6w��Z8�{��(��_/��S�ZhPH��Z�a����*(<�E��}�+h�RsTGG�uW������>�n���Z����4��{�������:)p�(p�r��k-����K?�eQ��4��@��^
�aP� ���^+s��:)@���<*d�C�\C2/U��b\e����Q0�M��u��mqN�v���\�G*z,��������=�>	�4)0i`������DI�)�^l,W�kq�h>�Y���@���TpK��n����u�)����L3���Sj����k�z����Z\
)�^o�u����o[��������c��oa��Ba���rg0��K,��z�A���J=t�a/
����Z�O���k�N1i�`w/<�ou�:H����Z����|�yTh2��(���;fK���,:mN��Xh
�rw�C�����AA�[�S�]q��^d��U`)���j{�&e�C�T��K;L��iRj����k�yvbR���r��n-sY��_�\������N
P85@�6�b����?-7En����p������m_��E�`�X�����G�*`qf.��b����{���Q����Z4)��k_���%�&c�2*��{��q�{u�a�VD�j����k�����.W��RiJ��Z�6����z��Q�yT��Gz�f�p������
�j�F�)��Z� ��F���I[S��{����U�[�
�j�F�Ho��������4)5i����
jx���c9�l����E�
�b��U5��e�
r�����J�h{�u
�bw���5wJ�Z8�{���/3���J�����b�u����g�D���kjW����:P�X:,��V"��v��1��B
T,��
5(���}���~}Yn�(n�B�������CU�ta\�t�Is�;-�������V�4��Ri���Z�n�����AR����G��Q)C��n�<IE*]�*Y)9�z�_�?b���'g�)�AS�N0�$�f`����4`���<�������)�����i�\�,���{��=~^b7�5�	,��E���S�[G����f|�����b���^+v'�N�0���*�Q��V��l�%@��-����C���e��6R���JZ���Z�q��}`z��j^K��6a�{]Q�_�K��RL�{�������R��mq
�)%��vm�~�����bsL��ri����U�]���4]j��H��R�����R�����
�N��I+�^o�J7��y,�z�G���{�c�u��0����2�������\,���{����n�Z�@^��1E/�^��B�I�y�@l���p���aw�+���`�����b��r�~ �h*F{P���p�PoWm��Y�r��"%i���k���s<�~����l��{���[�;����Wr�P?U�6��:J�E�����m�JUq���<*g�C}��5 k	p�������2��b�*���;����bOn����{��k�uZ������"�'��',��|G��{=�����0���	�B���S�z�����;�f-����~��8�L�0����I{��h��]���8l��hoj���6���<f�I��^uw��Q7&\��R�{�]-����RL�{4OJ�@��pF�i�i����+b�'��di���{V{���5��Qyy���>�ZHV����������TzL�����B}���1��B��S�]�<x��a�����{���/���{m~��3�����?:��g���-�0���5��9hA/E0\�R{�])���4'�W#[�a{��?n=G�W#u��{�u�qE�����I)�^�O�HkND�G ��{��<�f�B/I0�(e���Q�
�I�z�����|�#��=���������A�.���mww�F��w%7���H�]�	�m�����Iw��#p��S��~��b�	\�1��8�i�����I��MZ�b��B��D�G�3��a\�,���{��rp�X��`X mO�N�V����qs��������%>ZJ'U�tb\�
(�^kA�.���N���-�>�J�9hN�P���JZ���Z���^��	}�K�J���^+u�( ���E�����^o~��&Q�*�[p��KMJ�C����-��V��bi���z�k�6��^�yT`0��v��w�&\��i���W{S�]����i��'��D��^7�F�D��4I�{��6�K}�3�]��<	�-�^���5���!�
m��N�V�qWBn����t��Z��qi�zE���z�5�u#D�pz����Z�����*B��h�e
���G����q[�% �^+wo�����K@*4��Ms�u�X����aP� ���^o7��C�Q��P?[�����[�!0LN�v%���2������B����r�.�
��s�UHw��"iQ`��m/���`�%�#q��h�[��.����
�����]�)�������@9js�=�^W��:z����0��W�������������~�/{�7����B��?q����^�vt��k����RX�{��m�@.=���r��fK�|����A�.����-.�Q�yT�������1����`���c�
�����q�<�{�(g ������^K��O��Y��/�����.�^������f=~Oj�FY����~&1\���P��kW���z�c��7�b�����t��Y��[41�����F��rX�3����L��{����P�����E����^����M��l����Hs���u�������,��^�w�n��1�:�E&�HoW��4��I����?�"�?o=�rP��DmI�s��&�<Ja�4)0i���~�����<�c��g����k�eHw�G�aLc:�����)�56�J�pLR����@��v��m�1���[�a�p�����l`:Ofq!db����v���>���.���^�H;���.�#�9��vG��o@��:)p�(p�R��8��d������-�4G�}���O�����na���x_�G�Cl�G�}��{���p`����K�)�����t�:i[����L�H��^���.|9��h��"����E�s���cn�D���`�|A��{�����v�����^�P��0'/��-�B-���:(@s���E����9��k*@����K���R�o��=��n��bij�]K��O�J���������D�0��v�ZwN�$ ��"F)��vE;��E.���N9iu�d76�.W�i�����:4�n��G�}�}������mq����S�m�>�I��=C:���OJT��Q\�h��������&E$-
��~�[����5p��h>Z��.��i��gn�p����(��!�B-���9��;�f-��V��S�d�Wq�3(��{�Y�0b��Tx*P��P�P+���R����JZ�����u��-\sT\�h3������}����E�����^*�:Z�\z/.�:��9���o3��i��kN�[v�7��G��Q)C�g?/}S��wq����S�7K��2���	��A�B�lq��
���"mM���pk��0M
LZ0�{�Y���a\�����*�h�EZ���������ShV��V���3t#�K7�����b��r�Bf�F@���h{���uc��)X�,���,����n�f.cA�K��$K���z��+�0@/J�`���L\���q�#\�t�|�C�
��v�*w�;Hc����b���������������I�D���)����_��;i;��'I�Pow�
A��%���{}��L����^���TC.���6�\�<t����k���N�%p�NX,��_���qf�t?��N�YU��v�����K��������k_��M[�`���]41��k���=���P���JZ����mj{��q�*
��b���l�����QJ	{��,��$=�Ol��Is��m��"�X�q�4%�{�\5���I-�(9E:��OB���Z4����qPs����b�S�8G�����7M�MZ�b�������+]�>Z����������;����G�P+�.������1h���p��z��p#�^E/0J����6{�����E�;�}���{���z��|
�2�z�%���P�r`����3�xQ�(������=���cmD*4)i�fa�?,w�;H����
�Sy�&=�N�=;���P�Y��M�r�V��v���_�S���]
�|���{�9�h?Fp����B��S�+��������
��$��ZK���5�M=�N,���y
�bw���S���h{��f5�s��H&GV=�N�����������H��{��tl��c���d���!�;?�G=�M 4iu�L����*��d
�k!G7�����'������uC���a�V��V,_��{�@��Q�j/�L�`b��z�3~{3��zT�Th{�q
uEm�q��#���Z*�{�J��S�I=�M(�=�x
�B��W6N��m�m4����^���U�6s��S��B����j-��g=@�q�3Em����5�5�xQ�(�������p���r�4�Ls��$��i��G�ei3��z����%��B���)��8��1��UmO"N��n���D����-�qu�����lC$�<���Z����`�%c�4w�|z��{]�qd��Vo��|���3�����)�
��5����Sj����kG����#(\:
�|�{�+��m�",�<�C���%������	{����]����s�X.���lC�/�6��;^�;Jii��+�a�'��
��3�aPF�C��Q�����)�G�fiE��Z�w�I���d��J�)�G��*,���*�=v8�Z�;��G(}W�B�9��}a�
P����E�������
��G�mf�k�����?��&}�'�h�,�^���tzl��YV���@�P�g�qx��Mr��Z���<�<��rY\�Q&����tb���������hu%��L'�hR���J�=�C7����
4)��kWV��|/�/1�xQ�(E������/y�M���EZ,�a�iW�G��]Y�L�������A1��v��?�>H#�]O�f�#�����9b�rB�&��{�����1�l.���!��4)6i�)�^Gc��`[��r������E�u�b��E��v"C:���&�j���1j����l�����8�2��Q@h{��50��c�&����m������{^�7������|�)�Ob1~,�����ba��b�W��&�/�h���|i�k�;�Hr$%v;HC����X�|��y
�G��Q1CjW��_�� �,���g�R��|a�_c`�I4����P?Y�����M�8�zk���R���i��&�&-��n�����_��O��}�|��{��!���k.�
&�E���S�+nk�DwQp�9�$y�{��l���!L�`m����V��s�r��>��������9��������Lk;������qd����QJK{�7�a������o�t�SL�C4�����i������K�n��G�}���:���!��`��e��#]oUv�vm
N�>\�tHw���� �{�d���6M�MZ.�{�X��3c����/��fX4_,�^�C[��2
�.3���Y�)���^��0w
�Z*�{}���$6�td\7�(�^+s?,��
\83p��7�Por��`���^IZ���z]����^j��������^?�u�K�;^�;J1i�����CuM�T���q��)'����F���W�:J�
���Mj<��U�G��Q1C���
O���*X:4.W�br
�����v�&moN�~����*X�5�W�E���c��piR\�R����>�������3�V������������-��
�
������)�J�I��5wJ�Z6�{����K������b��bw��q��n���bj��\�H�U�tkX�%�Y�{����:�r����K%m����}��5���@/J����z���T;:P���\����P+5|��zn�rU�0(t�&L{�+��Zj��G�QC��o��#�������B���6�����A���S����w��������%mG��z�G&z-P����e���JmF���*�{���Zz��!.�^����_�V8�
o����
��{]��+`s����*�^+vz|����������&qo���q�4(f�������~�EP���M�=fIk��{�j����?��.m�q��4ZhR����T�M<��$t�(t����k���`�*�
G�/�n����H+5/�����-������na����}����*���l��Q�yT��G�aw�X�W*}�HY)9E�Qwo4_��-���^c�"�di��
���k%mQ���g���
�4)6i����O8x*=������a�b����C�����8��� ���{(��@�zp��{�=z�/����61���p99���m$@
����PN{e��:)u�(u�b��k�u���1*W�>�����Q���[u�}p�*���&�^ob�H����Q�yTJ��z��
	����8�s����S�7�Ss�����'h{�q
�+l��|;���A�T�zL�(��M*w�jW�1\�5i�`��R�~�8�G�]��|S��{��NW[���:�����p�B��5W2�������^W��v�$Kp��)�^�r������\z,�I����S���>I����/S���]�����F�����6W�Zn�(n����km*��FsE8��IMH�C��>[?6u�:H����J=��H��R��������*8�(.�&�S�����@�N����Pd7��h�4�S�tN\
h����.w^�2�l���\�������p������O������.���}���|�����aLe�o��������EV]���v�������H���4��.�;^R���������]�������4�4�c��/Z�q]�EWyX@�
��v�������������~��u����v��?��!���0���`���{��������������z���?��w���>��{.�qN��#D����R���z���1N���������k�����?��������}n'�������k�O;�����|)��k����|�'�Z���7������bk�^���{��V�_���r���������G�/��:�������������H���v~������G�������k3��������m%����_O<�+��#�/V��7����/&~�o5��H��v�]��gY:�k9�.S;���������,������=?������x��4S��r��z��m�����W�����9��������M)O���r~S�����_�������9��A�U�g��a��n�6 �<;�s_�'^���?�;��o�zv%���Y�����:�W�����'��}|������J���e�:�^��H����};3�����~��_^w�6�j3'�n3�VWz1�6��J�O$����g���4�f�qW�q�4���_��������>��������_jyo��%��������E�p����f�\��������u�[�-��������X�?v+E���o>����������
��+�w��
=��K�O~��y��Q��cE��/�!��|�����,�>��S��3����qo�2��E?�sE~�h�����Z'�.���?�q�5�Y->Z����G��c�������a�])c���������<������S�w��������3�������1
��q��'����)_�V������#H�m����,=��?=fL/�w�������{�����g�Y/��1_�k���]�����`��?�.������S����]|��k�ql&���:��8/}���^\�M��H��c���N�-A6���]�^��]����mF�����1�6�T��[_������S~�K}\*��.U�7G��u�E'���hY�������7��{}M�^����XV/�����\�m�������)������)�{��]��M#J��o6A����[r<_���.'��������ry���k��k3�z�$�Y���J���I;���o?k���J�{����_�'�A>=v}�!V$J��c����t=Y?��3�+%�����/G������V�����z��>=~
z���f�z�w�z����^]�T}����q���F���z�������E�M�7:���������8s��OOt���-:�_t~i�Q'�8��F��{����N�7z���*V<���)�e�6���b8M?���4��)y9���-����7r����M��;e�G���}����M��9��T}��_�NO��d?����z���~��L�~���_����<L�����z~~��g��r^���/������������� �rG��,�����Fk��N���]���m5#��B/�W3�F:�y������y�����_|�����<�B���5�*�{����/:u�9��sp����pm�u�?3�,d9�������m��|�c��|#��#p�U�90����w�m����f���g���w�6��������/o����n�K��|��_/�1N���?{�z��g����s�3J��#������N������%C����N�d�\ND���	�vf�Z-�����LUK���}}v\�o|����*�?l-�-.��?=f����7:���R-6:��wY4lT��W�hh��s^-6���/w�z���Y^���#�����-�#tD'fi6g�H��9+�F)����w���X7R>1c�Z������{��s���lu#�/�w����me�t�nG��cY�%=�~�N����m�^���`�]m�&�Q�����/�_t��=w��&�Q�����~��8�g6���`��������<�^M��?�=�����������`���S�D0N���s�D0��gVS�D0N���}o���=q���n%�zS�&�[�����9�j���|�����8�O��bA���������Q�S+����������I`���������^ni���o�NO�D��9#gQ��N�(P��������Y����?=B�a�/��O�W�Y_���>���#��w�v��N����^������=@���N�Q�����_���
)�+�D�u5)��26�^M
�>��}�������/^M
�����,vGC��?��r���8��el��G�",`��c�%�`�V0
E������dX������E?�sEN�Y�tMG��e���I��>);��~s���|9���a���1S7���hoN��@ir:^7'J���u��u������*�xJc0(�>�%��1�;S%�����[���������
!L|�-���R�����DhC�B���'"s�B���2�z1����Q6�_�|�1�[����
�jV����m$�\����p��pVI�G�G���>�A>��z��_����i�^�_���������/[������>��r������&�W]W]�W��{=�>+�B`��|��?8�\�m�~c�|}[���c��
���������_�Rf��V���0����yf����<�_c�L�]�O��w>��a(���m�g��N���t����� �/'N��������3���=H��27=?e�������=��?�L�){���r/����6e���)��r���<�0�'�a��x�	�f�y���H�'�N���������z���O=C3����{{�#�q�y�#�q�q&��
����39�9a�X>�]�v����z��w�n���Um����7R~}�9���;�7R~9�����R>��{���r�o����F�?O>�{��X�(�����T��?��G�&��L����Y�c.��j�G�����0��'����r#��V��0�ogf���2L���o^��#Z����,Dx�}{}�]E�lt���jv����$���l���h-'�P�f����k���F�_o���r����:��n����}�=n7x�� ������9��Yw� �����0����-@�]���/_��y@�I��q���[�]��������9���K�F����6��&�Q�xi����Q������'�q��������f��*mG.+}��`T�/%��MFN�����m2%�����6��z��[�����dp���8�o��8�og�l2'����j}��|;3_��`�������������;_��
��8���0�}���b[���t0N����0��=?���~�������O���\[���N������b�m��3� ����w�a6J��^��k��K�>��yT=��>����f�Q�+{]�F����:���?�����������~�T?;�����U6;��3WT���s-_�������>�AD�/�1_�,vP,�������bq�����%>4w�X��->�-���]���cm�}C\�_�C>Wd��ox��)�l��`|����c��l�/�g��x�w8�[?��
��M������������OL����I�>%����� H����;{
n��:L�]^��?��^�^��������������\�Z���;���D����<�8O�����z����6�������I�y[�:�����Y{U�����8�\����o��}�N����L0F�$�7�_���Z�����������������������p����)�+��\�m��Y����#��
���_�}��[)�	�����_�we��V��������_������������[^����t�w�zz$�������(�3'W�y�������������MS��<���O�%�y���r���;|���V����W���Sw��||���4a���:O�c�F�����x�}~��8���s����(�V#����~}�=��^�q|u��o��o'���h�0������347n�'Bs���J�/8?�����$l��2�H�����w�m��������w>q/��w~���~�;�Z�iL�rz;�]���_��;�|�X���G0���FL��?��A�
�_��=}%X���r��g��������q�����e��8��g.��i�V�O���4s����@����Nt�����D'�v�`��Nt�y�l���<q�H5����3�#������}�6��j��/a��f����j�����W��Nc���SU�e J��4/��w����}9�a���_�,�j�|��;����w�1��[)��C��_����q�Lw=���[�h_,�f~a�?O���g~A�8Rr�X���r���x���������O��/���'����o#�w�Y*J�K9�s�������"����c�w:�7N����'�������P@z5�xn5E��N��J��;^}���	�g~���b�6���wx-6��?����8��8�;����/��}�c��s4���t����]�������,���=�����5����~A������������I��pY/o&V�� �O�����>��������fb5����cF��/j~�3��z^����u��w��y��g�������O_3������F������/�D0�(�y�����~�����j"���_�W�D0H��c=�� �{���c��xu�������
�
UD�����`����9�C`+��~l�o|�)�_�C>Wd{lwd>sV���1?����>��{�����c��a���a���8����|�:N������1��^��K����%�m�_��^N3�x��?�fv~!&����?�B ���N����q�7�j!$��z�w������
�t&6���o$����a5�����_�Y��;��N:z
��;��@P�O�������o�^+�������
������L=��h��f�_t�j������U���_�����d����M���E?�sE���M�zz?��S�~�F����#�w+��g�������N�f������)��������F�����[����t��zV$���f\u�+J�����9y�4�:�~�3��s��{�8q�\='�V"}_����� �e�����B2�����S��|<���2��������31*�<�>��o������V]Y�c�'4t�7LZ���9�`0~0������.]�����1"R��������TVtd�p�x��=>{7�fz��b���q�8_�[�3��(��D/���f�4�Y!7NJ! '3d�5�
�Y�!�������2_b^F��K?�D�V���n�"����������������\������_������N���e���8��%��9����m�1�}��"[I\���A���W�`9_+�p+c�'��N�����e���o�|>t6��q�r���q���Xu�E1@+�q�%U�E�l��P��`9_)R��S	���>_����������C��N���F��Lir�5rx�x�����2,�j�0��������4������>~�F��#���
���<�"^��-$i:�P'��*��`��D�����T�)Q���� ���qzA���8-u�_
��9���oo�#��<�|��V[��aZ�^p<7��w���B�����W��e!�33e��+ah&
G��B������e��%��ip����C��n���-�u��q{>���g�w���=�N�Z��w� k,���?6���)�a��|�����J /�8���,�S��0�|�����e�������#HP�Hyw���-��> .���-\�L��=��P�v���y3�S���m��O���a�����H���!Z]
#;M��7��/�T#��.��<u�4_"IR���g��M2�����2�_{[�"������.���e���&�Rkl�j��H-z&�,H*��#�4������Y����bo��g�t�:#/�����p�U`p����ZZ�����iF�������i&����:#��0�@��+�L�����,&���|)~��py��� ;�V��F�Hd����f���������J���;��A�����W�zu/T+� 3A>�+r>T,��\�|�����"���x^�7�+_��:����p5x�����^��G�a`�?����h�lEW��C4�����~�����C�����]>}�\����*��Iu�gW���&��~>�����������g_�*p���
�o#���k
�O�����������
<{O��l5x���+���;f�E��O����R%���u�9��q��CQ���0��{
�N���A�IV���V����&	�8���@2��4���/���_��>�5�&��"�8\��G4	/��ezp�2�E���CW����������zrb�������s�~�������,������2=�����C���\���g9c�Alv����gF�jZ�W�Og�5{2n��s#l���j�<9��49��[r8wW���u���^ZHs!����@��2y�0->_N\����+��r�?���}s���hYv�����3����x�P��9�+.�N���W
wk*|�[��IN�������������	��1�Z?���Y��C�K{+N�nO��[�H�#�s����DG�_�k��#lm�s�������&�RS&�V-F	]��W�k1�N��7���������.m�����}\BF��K��j&
����P�%���k�Q:1q���4������!K4����t1�2�z���"���n�-��!�F��f"x��08J����4M��Q�z�(UV:)o��|'���ub^��w^�|����e�������IY9t^�@��5p�Y	��r������g_�4�8,E��j'���:L�v4�6}�(��+x�����m��f;B�o7�93B��a���= g(R��-�v	�i5QU�D��*��D��-!�R��M���7��o!�k�q�f3��K?�l��K��,�;d`�h7����
���9-�������A�v�F��;
>R�Ty���#%�p�iz����#�R#)���1��H�������#U9^�r�bp�{��'3�v�4�r�l*���i�����:�2L�g���g_�^�/����3��Y��`����X8��b��[i��'�4�F�W�1vR���'!�\����s�R����c���w�9�c���6A�g
��s���������A���8��Ny��:�����p��R��X`�]m�W���<�������&r���q�Xp�����	��|����j�|�>���J{�\�����y�\��������2R�����C���\
�6���J��`�����8��������C��V��#_F��K�wo����/�>���C�B�K��f�W�?~�j3'�
�,�C�y��o��D�X�����g� ����F���<��AtB-��s|HyhW�������U��r��izj��_���>���s;|���0:U��q;<U��0��n������Vs��5�������SM������=���|���:^j� �|%]��n��s��p��y�aKn$j�f6n���H$���1>���[�f�}�����+���M�,�n"���E�qL�����IG�G���vW�c�G�W�#���M�x�@J6����e���|)���l?�}��l��/�����1�������M�����	�!+��C��
��V�*wZ+��C��y�������M�z�h�x�+v�,M��[hg���2�V�7��MG��o���2��ke��\��]�<MW�!P���W��n������!Cs��W|5�ry�Z7q�K;V�k�o�
=������fRi�h^���o����ahnt��v�_)n���oS�k��(=9�~(CVZ/��y�����n�����/�{y�f�5	9@i���Z5k ��������J ��8���V���@��+[�f��WTy|R��������hY��x?=y����y��":�G.��t�*G�N�W��L��]=d~2P�z������q�Ti,sZ�������?R#��|z�H��D��w�����h���������Ws��j��;�y�~S'~1�����	N�#�Z�U�	>R+~����/�������
��T1�q4<R� ��j���J��jFGj�</�C���?��||vj���(���{y�f�<���
�������K+�n-�d]o�se���������yn�4�~rV�g�6+�����?�e�&��+0]}�W��[_��`(�[_���`[(wk�xO�����|9X��p�n�p�Z����V*��nM�w��\���X�c�9<P|������l��������mFj*H[�:o(�	D���y�uk��z���tk��������6??�|�|��nF�d���?4�?��V��/�1t3����h�*�J�+���������v��lz��/�����;E�R���:�uo��a�r�U�z)��Y��+2������B)�B�~!(�]���?LVDV�#���e����z�o�����Z��:������<>Mri�(���
�?N�_�U+��w�]L�w"V�G�)��G�L��2����s�y��'	�q+��m>>[i���k����{�4?%�����w~����>J������t)��qK��(�^����z�����W=}��@���+����}
tw�����M
�p�~��]w��w2QR� T��_�rsM\"��������D�� �&	��������/�kw�h�������[@��a1�?��_�c��	�0��cpel��:�������+$��:@��pB�����Y��������Q�����P���ar{!�#d]���m�V���r�L+��^��r%���ak6�U�2;S����7�����0d��|&���S�����V}�U�o�|y�D��O��/m��XB����i5 _e;-�j@>���	-�x+N�>%_B���v5 _*<��!����k@xB����?����lx���9����K_6����^�Bh`w5`x���
���0�TXs��"�uc	s,o]W$��^�����n�5�����*'@�+:��;�af"U��$��go��A��@�!d�����t'g�����%6_�����&��t,��_��v��>[/�.<�p'��@�R�X��{���7a�(^X�� 'v��)��A��/~�����R:h}5�f&m�`��psh���B��rl�7�O�Vy��yb������'$�|>������<����	����,�Y��o����g���w��2��|�������_��gV��9}�|��<�����F�3v%������+��o���`�����h����/���b|����+�7]a���*y�pW���^��|}������p�O�G]�7Z��.�4-y�=w���F���q���u�|������%�6uq�x�]n���/e�����qzt#�q�8=x�����`@�+���Jp�>_��,���J0��3/!�'��>�I2g �j������*7d�����t���LPn��
�)7��M���%�u���n��)fzz!�B�����3=��Sv:��DP��
���F�#���@�t���_��1�Dy[}����Y}����������������jr�/��jr�/��h59>@��)'��{|%���6�F���0N�t	X��W�D��������t�ZF�z=!���Z�#_F���9v#qf��{��6,p����?��%�����hQ�r�6N#��g�$_hB���fw	����M>��
��KE��
��+�������
�\
^5�x�L�9���o�����	6s��l"��~�?5v�����@,6�5�m���`��z_l6N�:*ag8`\�� {����9=b����<;�+��������2y�����aT �xs?\����3e����x���E#��1~��|���?�^����������W�K2��������������3Ie`�_*c%]��7Jo����	�+�����+aR��� �R����/X9?��_�}��+6<�U�6c���?P�E�<j��!��3:�p����%��1�k�w�!��0�m��/��j�wz��6�Hz��W��$_��2	�K������$������I��,���n?����{�ip��
�*�����,�;�����H��f���E��>�K�U�0(�g����ZJVNV��:Q}S�Jh�r]a8���%t��l�#����V,���y6���I@���Yl/��l�(��=��C�~����;9�l��(
g�l���t��5h�	6�g��9�{���N��>�{�������s��?����������[�!X�U����Y��+���37j��
��o7[@��
��.?���(�[������ �7�D���|#������o>[B���!�Uq�o0���A�?w7��@�p��@i��!�5S^�8���s���*�7��'�����j��Yq����py�
���$���������C���l�}��uk���WT�>�9����"�g�gG��r�$8{�F��7���-��0,����u��7������r:_���B���=��BG��aY�X����q0��U�|=�L�)7�f�r���
����J���U�j#:@)�=����_my��u�U��m�s���h%��v�
|���5�iv1�����h��2��V��t�Z�E�tO|-���b����y���H���o7g�#�x�}>�:������'�L�	C�rO�F�:U0�	�:_[B��R��a�
�4�����f_[Bp�����|�3�8�
|m�|��#�
����T��!��/!�tYp�ep�x{__������	�W_�|#��/�_6 ��3�Rl#�
�6�>;!g��V��������l��N�rUc\}vD.n��o�A�M����+�,�����^��������_6������@�������������s���U|~'.��sW���8Q�VW�A��0d�W<�����J�U��>��d�)�T��������G_�����WA�7������)�"D^	ue�!����jOB��	��B�wj���]k�q�
�k�W�5�7����������at!����Z���>]���
g������LV|"������>����B���������J2��njO�;�AjG����2|�+�{�<�W�?��*@x����_��N��`
[�L��c>�E�L���|6�����C��E�y������t����d���GyRX�����C���l=a���	=a�F�@e=a�FBV{���LJO�����'��A�����z����LP&u]Qzy�|0�����^J�oi�zE~�3��Bm�B_�x���]�2�5���A�F�������sWm��}b]Y|m��;u�����-�G�.�1Y����e���%���<P_�5�]���(.^�2��L�%;:����W��@=y~|hk����*p�>]�������s���U`4u,���������?�$��u7�o�e�&pz�G�LB��Sp�'OVp��4���3�[�L! �
b���
��}�
���-3�0,���
z�PXw������%������kEi�7W>���\��o�Z��<W�#��`?!��!���zC�b&�@����?P���U��	rR���$<L��1�F��Y��A���U�Q�J��"��s�j����D�~�D8��cEb�c�R$�B�c�X|�TEozhj=��|y�z�X��k=!��^|pX�]w�!9w�$������_���_�7��\����cx.��^���]w��w+lI��������Z�_�o�8o�
\�.������3_��@V���z�Y��k���]��x�Q���������\�=xD���]j@O�}w:6���F?�����F���O��	b�o��a{l�O�d�Q�:�c��d��=n�
��8��k%�c`{��_m`�����������������B,\�.�K����ow�[r�^ne_����e4�����o���`!�_k�fn��i���������n4�N���Gr�������Ck���a�?t���%��lV�F�[
JDT���q0��^[/���y3���L�E���n��������v]������Z;�+�+�n���b�R4����'����|vlc���5����&~����
��78���4�`N�w]�\����w�[�\Zq��*\v��:=4E	t#��j>;����Kz�4�8�@o�]_�q����y��/
����B����s|5xM�����Q�����]�������pn���Z����p�+W!O���f7� H�,��A~��� �������i����}O��������;U��+����v$��'��O��-�a�V�
��������h�]B�~?�`�4���0�+��Jo��������~�?�|,�����m���x��<\c7��}eG��p|��(� ��<Q�:�����c�Wl���v��I���	$�2M\���%�v���/xJ�R8�'�Q8�5J�p n���{��iG����J����^�0y�QG�\���#q\R�ri����:��d���N�c�u�cp��L'_�;�:����o`����i����'��>�R��p��\Q������4~{�NM�� �f{D����*���	�Y���7����7����6&��M���	S+9�q70�����n`������uJg?���X��h;�������S����$��#�uY�P~4�`,�0���4�<���\>��#?���6����Y������W�\F~������m`2��u�W����F#Ex �������W��e���X���w��������l��U�l�q+g���g���������	o��i6�V-�e���������5U�n0*m[����X*u�p����+4��[�]��f�np�'�-��u��,�BF� ��2/����"_1����2������+�np���Y^�R7���*M*F�`����\�D���$��Mn^u�Mnbu�M�YYEO�n�`�f�M�ZI)�Q7z�!��q�w��np����(�
�Q7xO+�@G�D�u�_��#�u�������Q1��O����Q7��|>�����Mt�g��$�~�J�D�m���V��':#WN��x���D��uJ�%��7	LN�@&g$��,����`8�MLM��t����'M��{��n�on�\������yB��sp��WyN��+�������ub:mZhT@�P�D�2�p��@�����[����*F���+�PF��''���AN��,��qD�Tj�2����VD�� ��p�c;��6����k����,xw/�G��:q�n�n,����yRs��y��J���<AV���N#i�����%J�����<aZ%IG��i�eb�V�^
=�}�M��C�j(y�(����=A���!z���ae��B��j-x�k�2F6v�,3�|�� t����D�qKw5?Y�N�?C�8����U0����=7�o�7�K��SK|XT�^q���no1.!@��>U6��|y~4rm���q��(�sw��������~K�U=d���j���
A��{i�!������'(0os�	
���WA��
GP�}�4U�X|������"���d��	�����	�G�On@GN��8Q�������A��X2e�X5d'v�FM��8<�&������%T�*X}c_q�<�=K�;���,���������U������5���|���%`�g����%����{�t$���x����u:�|�J�I�<uOxT�Cn,L��B0��VL�4�����
����7��{BPL��!��96"��|z�����N�"��M����\����L��8�����X����9�X������>;E~`�s�,��(/g�?�z��I8m���dQ�m���K��0��h~)��m7�����}#���r�+rM-p���dS��G�����X���d�T�
A�eMC�P�-��K�t�[�5���V�#��-�W�Zy|�\��K�Z�c�m-A��d8� ���53���H��it�y��m8��>��/�*��o�����Z[�������������
�����u�_8!��s
�oRix�Z��M�0Z�z����&0����J�@\~���'x!H?�'x���:r���+��G�3ti>=~l��-��\I�q��	��L�\K����:���w�����E�3�����_����d���'�*ul|v
��90���������\@�c�TF�8.��/AE�� p�=
�aqR���R�n������N���:{��V={�Uv����Ugo`��9��Vr���	S+�b�
||����n`j�;-�
�V^#���Fj��E��o^�J��f��b?�ZW!C���!?�6��������y��
k����:�C���l=B�o�R�����������SHen�q�%DU�qi�x�+4�D�f���I��cn���*s ��cn��� '��|~	��`����i��%X�$G�Y���{�;"��QuW�W�A����W���p��n������U �duF���(�������:z)L�v��L�b������o�/%�F� ���s��c>�dEF�`���+;�F�P�B����IN��(��+6Bx�z�o�?���:qj�	�Z�F#t���vUB'?�:B'J��~�:8�N��~4�>5(a�����*�o��'p��\��@��?"O���~�J���m���B�.��W��Y��,��*B��EB!��N��a(3^��xC�����R������E�#����S���5W~'B����5_��\�w�cQ��t���d#{~�z{}��T+Y����\�����\�����;W00��O�����M�1:0��`ct`�F�v�����hdzHsi���{{�h%�����2������h��[���j�7Z�w�dh��?��W����W������v�KfB����X�n�R�<;(N�l���������X������g��U�j+eX~�x�'��B�����]�����a���d��@�;��Q��^�`���,^1�\T~���>��%=U2!���M6�
A$t�H��s�B:r��M��Q
���w=��'��/ne��p��=_$�EY\�4GY��:�"�GY�+4�O��<��h&B���x
��f���"�!py~�Lh��q`�_�G��,���s���Dx�m����*���a�%�q0�3�_�8
x�'
�`f0|��q9�"H���lnf�E,�7�r+;Q�� ���or����~'��uwY|��GV��������m��.��[=;�����h�����Anb�
	_	�����EFy�q����L@\��o=���6�����L+N�;$���d��$BN�;dG����'���ldc'��O�z�&xHF������r3�a��N�C�<%�8��_h��,|hJ�o�$��)�<�0+So�<�eL�9��X���q�����rw2��TXv��F[p�����!����
��QX#�_
o(�����X7���#R��'��*��F���1"����*'X��$N�����;�	��)N�������,���U��ke	,�K��&�� <r���\��
;Jf4�����>��/�)��o������YN��������L�{?4�?����	~��Ou'�;_ ��	�D��I���N	�M��bZc�+��F�$�	'5I]�#s�'�9��02'}��w=��,�����l2�9�1�D�5�/��J��gY���uDN�K��������sb��f��$/��1%��L2�C.@;9:)wh2����f)Q.���[��2p�/Q�.	�i���r`���	�W �M>�@���7�������	�IU�cs�,�����M����� ��i���:�i��:0���)C`�l>��H�:��Y����C�V�?����~$���]�>��0�������v���|>����W��e����q6���S��������@\^�S�I`4��k
���@\ZTd� t��q:�������G��>+(=uV�4�a�N�b�v�<�<�syz	~$��������bG�v0����pI
�R;7���f�� \A[`����S���������p$A�K�������A1:���o�s��{X��.$|uW��\Q�s��=WG�`�R��R�n,��tNn^utN�X�.����t>����������'�2���������+��bN�XS���B���(��#�����?�w0B������6��-��s�����<���Y	���m%�Y����O_�������i����U�N���L��D+�5/�&��tp,F�����`0.����{�gF��=�+t����9�����i}~P:r�s��=�s�x���95�_��o������pt��AW�s�o'�w�`M��dEAcl�������+���R�[����I��|>H�tf�/������w��
aq����A�%���+��:^'�x� ����Q�e�?����M�X�����09(N���,�������B�4���g�a��/eX��{�����\������9�DVp�q�B�aW��_�~"t��!��Q�E"��G��BiU$�7}�7B�
m?�Wi�����2�P�]�v�k�����!������UaH6�i�,'	2K�X����n�������z8w�w��;b����6��$��:�"L^����������5�V�z�1WiN2�ox`s�}���{�����pO���T��r#4�Z�S���v�X��gn���0�_
����RVn3��/��� ���N�u�J�����=������K�qAr��e�������T��;O?z�nk����jqn]�[�9����N���X/�i���J��|����M��W������}<w����%�)�u	&~N�R@\�����`\~�N�= �`_����q��~���'�'��/&B�go�S����c���"�	�������"@�}l�g����6��U~������������p�*�����;~���e�b�2&�5�@haX��U�m1F,@�e��	�t���#�B��p��^+3��<F�������=J^����0���V�n,���v�BjJ��B�Se��(��#p�p��6���o-��w�� 4i�'�����|�v���oek���|����GX��HJ�z���!���c�Vf
9>&'i ���x��r4����>���?|���;G,��H7�q�w��y�q��������D�������a����
\����S�8$�)`���s����8{�z.*{p��/OMe&��u�A�K��1��N��^Zq�g�k\���`aR��`�'��u����Q�	
���:�#V8`=�1N�q��<�����8����
�m�0������%�#8:Se&�����{k�O��������6w}��0A�o�U�����2=}����z��^���5�X+�z��T�!���uq7��h���u��=�PS���e����]����k���|>����+��/���;��@��+[�K����H�b����	��B��g�vT=H��+mqiwWs��0�\�R#d}N|�h�f_DIc�$A��8XbB�c+@<��!�'o��:���H�q���6$��	�2��Y���n��k�
-���2���&���VI����������_���_���D%|�����A%|���N'F���P�U��<F%�j�B��{���+��o��?�Q>|q�tx>�P>|-u��>���p����,+E)�O�	U�'&W\)�`�v�a��[Q�f��%�F�4�:�8�~���V���
�b$x��T��`G	o���	�����1�'�c>3��rh�|=h�XAJa��:��T��]��QX����F��gZc����(D������L{��Q��m)o@�R���6
�0��\C����,�������%OII�|YR�O9�N��}>!j
������0�%�n�p�1%���GG2�''�����	rrG2���`eI��*��E]�(��=����`K	v��b�A�*^��b���1��F�����L��#�����$�SO0	U��3��)	S��)	b����C�T�n�S+_+t�'�#�g({�>D^��	����F��D8��`�IU�8�!H�B;MmJ	�Z��1�^����w~��a���[���S��'���.�`���q	A�e�����>���W5�q��P�c+������DXp�x��+z�p�������uF����������m����v���`�r���'��_�96�&xd��2�[96�
/V������g*+����R�!3������	�M����*B���K�X��������~�JQ'���F�y	�K��/$V���x�X�%RS��%�����+�V���Z=8��[g�gp��!�����O�>���\�3���yf��
s�"��%���pz<=��� GO�3/��5z`�/��f������[JsE������F��&(�Q�c#���)#��p�� |?���'x��jVL����1�����#alD�zK�Da�w�����We
�0��X�;�q�5�s�������r1������N���{z{�B�']��D�t�^*^
�.�%��.��o���]����������r�tt��K������!H���f�S�>����=����R�$'dv5��wBg���	Bh]����U+�����WJ@v#IU!=O��%�|{�f�����{�3J�%C���S|yb���k'D6�uB���{�ll��UG��'qR���8�&?�R3��G�B��b���v���7��!���h�m���V�
&��m�p�A��6�pI�K+b����U��'��4��XPpg��,���3@��g�p�'�3��?�h/)��8(_�c��xoO���� ��`�I
;�a!:<�t3� J���B,
��J�nc��Jn> `� 4� N������(�;��8�����z&L"6S� ��vt����������XWBs��`���]��zA��$��[�����L5�]�|�����M5�����(�
��r������\nNS^:Q��������m9
}EB�o"d�f�r��nk�F����,"d����6�~��&����%H>�����r����WZ;S�������/����`�sZ��3��b�o�~Te �.�pIq��?7�k���{���%����?0���6��@�
�r�3/����� 2p�O��(�� �.)|>(���8�F�KD���R���	�Jx���� ����Xg��*�F����z5����=�&Vu"k#�����V��)H���0g��?A�G���u+��g`b���<��>�]��Z�fx��,��mo�g�W�C{�VelD��6�o#�6
��9������G�EA�k>0U[��f5�o25��\�	�`�.�&�w��&��J��"�D��������~���DkN����VA�U�j��P��2�1��I���YD�������qmv8�\�A����Iw�a�se���� ��daa��������/��0�������B�YW
>8S��s�B�NumI2���	��p���c��J����EnJ��B�RekM����0�-��Zv�@�K���10�s�{�30$�����7B��g`J��c�'���R����\�_����/�y�7��������J!@��@!T�C�f�^�e�\����W�@0�F�@��Z��5�#%��d� �i|�H%��������K�:b���[9}>��5������Rj�Y5�D���:���u�c$���9F��m����B��l����Mt�M��/�m�c'��������Dh�0��@�w�����V��=7���M@�����:n�),���l�e@2���un"5g{n"H��d��Hre[S���'q"��M�	U�&���s0�
�s�@����%�F*O�yf"H��-�g&�������<��$��j"l�u�N�w�����.���(&�8S��&l�
�u]	���4V�X0�Yq��!w��K�>;�K@\�����'W�20��V���0V"�2��+��L~��c.O�;����l�\���L6�CS���e>;a��4�0+Z	�`��qe�2���*jG��2�Qz��Ov������_)3Pe7�D�8��K�-�22*l�A�Ru�z+GI����G�K�
�����r�V=�?�6�����<m�tb�Z�z.8�x�@�!���To/�y���0�S�_��0�HSNm�g
�f]A��M����4W�@�7W�V��?'�JT>��~�T�9H6�}�~��(�X.�n��f.���m���p��|\��$�xn+E��xn��������V�M��:o���5
"��03�"��n�\B��r	�w�3����9"?8�3��ca��	8�����=S����n��W�?��v���'�#��7��c���q���4�P#�����<�Ct��������*����)�QQ�e9��F��,�F�
�����#�X�J2����=G2�	W����D!����Y<p�'���]3�.���:'`x��w��C�$���y�~{G��gs�����~.�^p��v�c�������\9�������g������^�?�|WIQ�D%����-��<N�L���nA��WL���2$���z�
��;K
������������wnS��g��D_@��}��|�3����3����DM |�0���\�K+��#|�0��>��	�G�@�55s��0��>z.���rA��������*�#���!��w�l�����d���x��>���	��J�fqO�Re�H�����(�X�eU�j39��v$:�	-'Z�8t��3��ii���#8=	�#���;z&�����`��I� �
��#8�.)�c�����>oh�#`�6��������M9�!x�4SE$Q��i�*"A�����b��f��md�1'~����/��cR���W
3�w�c��EmN����G2�O���J2Ta���W�|1�!�%�*�V��l�d��5�#���! t��&� =p$�V�#�2�o�z��a��Dx��d�;{��68�!�8?b�5� ����g�'��$TO1��4�(��)�QAN%����e�X�a|x�)�#`��x�#`�y!�'`��k�#`����f7�RW���~$�ny�'�������=?��2;���D�/-���!��2�Qx���?O�C�A�vDgSV/��}qi_E����O��AP���"e`F�	:�J @��B �p�s3���#>���?�=Dv��K�������_���_�������������
�M,x:u]���k8w��{�;b��Q��,�������bV��*�k��7<��-�weplK�^�Tp~ 8��K�n�/
��<��'_�7�L8�@O��	G���������m�
���������z��>��`����(����q{(�Y���8F�/�]�����v����p���	�-+�0*&H�4��+�N��������j^���0��*G��I�4�ptL����y�����{{2&H�B�~$�.$��Ck��;���%]k���m���R�G�J�b�M-�#���8x��n)$������F�@\�$=�F��3�l4Z1�RRi�ldSu�>=�T�����#���$����$�V{��8Tv�|y�g2�@�BMs��8��s�*s�Z�Ayq>72��{��Z�~9]�^*��������m�����A�A�]|:�>e]M�����;��8u_I~s�b�������*�a�'���W���_��Fb
x�g��G-�#����-��d�_����r{��Z�Z�����jG/�D���xzB�,t�=�#�V0���V��3yYwN!��<������v.�u���&�������o�����v��3��&}q�����-�����\���<�{�-r��@�
����c{`�}����n���`�#e�E/�Iu���C����H"$#v��i���6Ay(�:0�&8��g�TZ'�hc���jm��ss/#'����&;�����l�N�)��n����9z��� �
��b��RZj�����P�q;���;n'�&o��� ����A�3���d#z����l�j��k���D,l���"g���J��tG\���:���+vm5�����$�:�w�t�N�y:%j�x|���#�u��I��u0����x�8���kN�X/�G��DG>����Or�0N'J�Bk�n$�nS\ct�L�����C�ch����gctv���?�/0:��S�����W����R�u8����z�"���� ����u�'���J�k����
�2��r?8���~0�>����O�1�'7���D+�%H��I�Ee~"d:��I�Fe~������M�n�E�[�*_z�.��{�B�3L<������?Z����=\q<���K���\�k�������?�����`���3,_��:�#��4CF��d)�?l���������\���Vl�����o"����������r����/�m4PM�G�3���x@�����`�]	�+}k�(�J���q�\W
�Zh.�4P�l��l�A��-����:���z|v$��|>����WH��ge�������l$PP=+,��q�d�3'E����!@7��	��*��+�N�_+Z1-����pS��Jq-r\��b\O���r=���q=��y�r=2o��k>=�1��<�4n5��"�`��;��T
y*i5���88�����(��y�(����R�9�B���"�������V�=�=����)�c|�c�*�I���h�b�1>0���1>0���q�|��{�|�hf�h�K��	�.�ue|O�uY���}���6g��,������Z�����	��{�T�RI�V���c�|Op�yE��=A�������K��cp��9C���^7��Z>�����A���s���Q�-}�0B�p�z��4A`�C	�*����u_��wdW�]E�����H` .o����������$y;�!w��6$��p���swC���P���M�U�����P/��������+�-
���fx�F�:��-��/ ����-�q�������3�B���"��rM7�[���������~�3H��q��
%W����Q��~�
��������N��m���*��T�m#`����~����Y�qbe;�v�U�i[��b@��r�4���mqby��'V>=y���X�u�G��x"W����Q
f9�v%V�)�D0G��[k�	�/��-0y*����F6v"���b�|~4�d]/��������E�<��
�|�P��[D�/�G�o�R��G������!W�`*]��\I����$L@g���o��sa:�o���S��D�U����R���P�Q
z)�|{J@����������5[>����mtl���N�WC�=���.����-�<�`M�0�i|�o���+�����N�.!G0kOp��3;y�h?�j�<�#�]��<��H�jy
��0��;�9��c��w�Q��2�,���B�8YL�sA$���LbXY�h�]>o����F����S#���k�����y��J#L����z�
����c|�_:�
�c|��Ef|`�����	��V�2���/�arq����5-Jr��%@�'UGvO�T�'��<��0=J��vO���'@�n+���\(����ZrOm}A���G�� �/����;��18~C�x�"��rU2~A������`h���$#z!�F:���)&'��]������p��n�,�R�n���y��up�g�@��u��m�O6����H����/��.��GN����p��7|����)V �������0^z����#8���I���~��cu0�R�%����V������\�B��$������R���w�o��<>������<�{���������_�����r|���:Q���:�������D	�G.:�YH%���7K����+�Y=���"L3$��IG�=F8<�rh�	~�����q������� Q��ld�g��Q���:u���8R.�'<������H<���FG��$-tx8R@�o
G��]-\��\���Im�E��:|1��Y���0�ke��#u�\2D���	���
�N�)���n����)�0���N�`e����(�0������	���,�,������0�(J����m+{�+-�	v*�-=�D��F��<�4D#p��~���������	~Jf�G�C���l�N��W�t4#t:�4���yk�b���[�T2'�[t�Tm����5�s`,t�N�����|j��+Z1�/���p�Nn,�H'}�F�d#����<�s8�L�I-B�����08����:��Y��jY�����[�� }	yO�@h��Q=��{�@O��S=Zig�T�^*�#G��XO�!G��h��gO��x/��Q=A�yw'g���o^8����@o����� ��{�=0(�M���v���:�'8H:�0��&0��=��":�b=���ZY|)t4{�'�!���'}�T;$B��V�����Z�y4#�(�
�,�8�VjZ3�����8��`�R$A4x����H�60��$p����=aq�q+���klC��xYJ���>9�5�F��#����<9������>n����M��wdq�h��4�5�`���fI�p��jI��������o�m���9�J��:e���*M:����[c~�Z��0?Z���U;b>���H��	m����	>���f��%������>���2	+m�~�QJ��'a0h����)/��d��%S-&Yyrr�di��V�-��]���������'Y�O�y����oDOIIVx��I�3�s�D�d��9�`��K�n���T�;X�q�]`=C��M^��sU0�j�`"H��x�k���nO���\�e���<��'��$�'d������� ���Qv��`�����-+6F#�4����1����i�������m�o���\;��B���H�U�R����p8@/�w&���k���<l��^��lA��E��__����I�c��5�����FJ�9)�8����m����8��a3�Z	k���+M��H	x�'�=#{�����k^'p��|)�&-�hv��,����H��=�F��[�jy��y�F�V�_������#�>�@+���$A���_�I&Y��'�Y��w��=ghe��_���/�.����^��g��9t��~.�^��	~_V��>4�?���&j���T��w��!b�'2o<[�����T�'X1��b�'p�t?��=��0�
��+o�N���bcz�q+�������'\�L�b�&�r=�9�q=�Q.\��z�}�E�	�|OJ��+��K��"S����������SF!#��b>k��b��A�I����k+3>�1N~�3;���W���1>8�3�{�	P�2�3�o�6�=���2�zc0�bpu`
h��|�JP*�gB�;�u:����D�&����,�jc{04�Q9�z�
��'8��?�Nz�������!$F�D)V�����X�4w?�b�J�e$��9�������v����?�^�v����K��_�6%E�qK%�Ur'��tr'B���7��Nf���D�K	�Z~xQ�R��\�������`\���"��k��WL��>�h�<'�������k�|O>r�{��o�7�e��r�o��U�|*�hmEWhWr$��$����=���G���r�v$��)2
G����!I8X��B���x�c|����vG��������C�;���A��A)���1�����m�O��O�xa�;�'K���8��O�b�H;��>���Q<�d
-���)�7��L����Q<������x������	R�*�����`��)� �O��e&��9�~�x����/������'�����
���Q<AB�D��w����m���JH!�*�t`,�����1��#1������+N�t����jE�<CRY�t����#WV'�X��'X=h���q:���s:�T��-B�Kl���5]9���+n�G��w���e��w �pqw���
���S����;:��A/���;��./F��h��+��w`���!�{��/�q�f!���ZQ���@'�q�#w��n����Y��z�~'�Nuo�8��4����yBhR��h�0���G���V�y�T+4j�Z]��Za&��[�V6��".t���N������8�f�U{������"d���rA<x�K�rWl��`�����F����(�1�H�}&��6�8�'xuGe��!y;�!;�0dG�t#���O(;7N�t�����y���E�������������DJW@U�s����py��9�F��sn����7/��w�n��������"p_�G���"3p�������p���.�������1
>-������:B���?�����`��"�ptHj��t���Q7J������E#/s��N������{�tg���y2$8��
��!�o�t��8�.y�9����+�<�X���!0�S�_��Z�t��
/]k��A#J��Z�|E_����;Ah�A��D�4!d4H�,���mdZ�aD�|�K?�b�r
4p�4n5KI�D���{i>9�*%�������J6�Ej$
�ps�G(�%.�	���%.�V�"\���g�8i��g�:i�V�'������"`h�)��Z��0�k�y��z��LX��0���S�\��b�k<�H��G�gr�Xu���C�����^�)d�u�����G�<�e���	qzeG�T6�:�U56����<Zx�ol���O�&�Y����oD2��& ������ke�c��c������Q*�]k���l#�wU��+���u#B�,
�!����(D����6oD�[�U �%��&�Z����������%����*
������a��l4�����xn
������kL�e�Ze���.�	�W&{+-��F��|1�i� �4����y���z&�5=���w7�F�K��ox��;NG$��RG$�xOG$��P���8��a#��W��~}�J8Sn�&P�M��V�-�<�_��+G+@hE�P�4�Q��9*!8�	�up�^9;*a���������w�Rg��4p���dPv#�v��B�f�-��C=$��L���~{3��g3�8����<�{��c<�������������|�f����w�n]/�S��(cu0�>V'��U�H\�j�Y���lz�|��:�AB��ip��N����������B�3��gK+U��=���t�G���(����
�g���qD��T����Fp��,O�A��V�#?��)��z*��y�@���B�7�se�������
Z<o�L��x#� �J����`�W����F|y�L��'@�qsu���\��S$X��������s��y�(L���g�� �ppO�W�rc�Z�T�7�<<�<��y"����������Nz�F{!H=O�[�'�fz]
;���r��I�����������������9�"������U�8���D	V��g*[��llE���E�Q��SW������U.��}AwHT���5W��|�����u�����|�#W��������O���O�E�K�h��W���V���o�E��t�p�����Z��=U�R;�nl������_�!��"�}o#N[G>��O����|��_��h �����N�1���%	K>X��^m��~(�QA����\~�t�tSQ����h�0����! � �w4<�<��i�0��^�V>W������%�����qwU�H��KV��f���(l�J3�.�_�_'�����a�f~��0��	��6�K��l�s�"�(���+��K�&�"� ���]��`Rc���`��3�#d����@<\x�����w��-�F6b��������=w7��������<�����"L���Q�/��4�%U�Vx��g4��)�������h���p=U��8FB�S��<�{d>��NS�;�c\������V��<��7�K�r�`���Xh�pF�Qu�D�zwT�d�����T��0��Qv����7D�X���p�q�3��3z�WL�B�����{Z��n$�.�'R�AN��S��#���)
�OV�H�G���1T��~�J�����'U*Eq��W�(�zeLqiWSF;��/A �js����G�Tz"X�>�$B�4��M���=w��H�D�
N����q���@g��k�@�s����^ ������x�����$o����
�xke^k�
����\��8�|��x�j�a{wY�B���o)��/�����_^�QF����D�Ml,B��x��s������:������3�0_$�M���`��	��66�'��	z�\��M@��.��	�c������2���	8���sl,�$j��	8�sh�����Y�|�cp�[
/NL�����%wG�(aBa��yg��&D5��i��*y���)"]y��m!���������(�|��A�+�7��8��gke0.�R��MXo����o��5��nu��y����U��j =���( =���FU�)���*�s
�_���,g&)�^(2�)����Q���+rv�����������T�z���r�$�|��88������S'Dy�f������0��n�V��R�c���sz�!L���C�x��"8�.�w�0����fAam8��H�;��!�p.�8��7d�����-�>����o�����{�>>�7�����}�<�{�t<�nJ��?�7hT����T�'����Q� 3@���m#���
��\5%84fP�� ���F~'U����&t��(���&t��(n���?���������Q����SazL��D��pW|��T�$���H�����1�=������G�g4<{����=��R�����Ib�����V��#�t��=���a���{�T�v={��VL��<2���=��a���C	���,Qze�w�.������K��8"-��:�(;�:�(L�rOK�^u�w~�y����-pQ��g����AOH���F��F��I�s�i��Z�f�+�X��
9���]aZ���.��-6��aF���Vw���y��k6^"@�'��6%@�Y%c&������7������9�����8*�0z�%�a�a�!7�!;4F8$omG8wa��_�����M�
endstream
endobj
26
0
obj
53548
endobj
27
0
obj
[
]
endobj
28
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
29
0
R
/Resources
30
0
R
/Annots
32
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
29
0
obj
<<
/Filter
/FlateDecode
/Length
31
0
R
>>
stream
x���]�-���/��C{���� �J���	H$�((y�H@���<�=F��ew����g�h�Q�����=������k�������-����<>��O���������_��,1���o
������~M��O���
��F��F�b�;�?Lo�}��Ex|����x�ez
��R�?��O��I�����i���+�'���$���c�1�-������(R�Ubd	}�;�T������Kmq��������w(T�u�3N��Jm1�{��-u��2�[��P�z��^F]��~����F����C�J��K
�N��g�^-@aK
�,�oq�B��Q�8���g�^-@aK
�,�oq�B��Q�:�mXT�-�~������Yf}�{�T����S���8�wjA
[j`d	}�;�T������Km�k
[j`d	}�;�T����k���8��j
[j`d	}�;�T����I��
�������I��
w(T�u�w�
���S�W��m7)v,Y��w)T�u���A�����v�-50����
U�G]j�0�R[<�n���F����C�J��K
']j����
[j�8�R[��P�z���f]j����
[j�m����C�J��K��8*[]a��j�������e���G�J��K
<]��#�-���s����C�J��K
V]j��#�-�����w(T�u��c���8�n����Q����*��.5��t�-�G�[(l����Kmq�B��Q�:�i���b��j�%]�M�nf��-�Q�R=�R/�VWx<�����F����C�J��K
�j[]���v���YB���*��.5p�������&�-5p����
U�G]���A�j����E���3��oq�B��Q�x�������&�-5��mu�;�T��������m7)l��m�+��P�z��^����rh�IaK
�,�oq�B��Q�8i[]���v���8i[]��*��.u���m�����"i�M���e���G�J��K
<i[]���v���x����
U�G]j��mu��C�M
[j`d	}�;�T����Q��
�C�M
[j`d	}�;�T������������������P�R=�RgFm�-�~�������Yf}��e)�,���`���aU�|�:�$�����P�R=�Rg����6��T����A[�
w(T�N�3��
V8�
�*��*51����
U��S��7m+��U��Q��x�V��
U��S�����C�W�LaK
�,���=
U��S��gm+<�
�*��*5���`�;�T����
VxnVU�GUj�U[�
w(T�N�3N�
VxmVU�GUjbd	}�;�T��;����C�W�LaK
�,���=
U��S��'}����6��T�����>�V�C�J�pJ���mu��C�
[j�E��
w(T�N�3^����rh�AaKM�j[]��*��)u�I��
��������w(T�N�w�m�-�~�I�n$f�Y���*��)u����m7(l���%�-�P�R=�Rg�h[]���v����x����
U��S�����^m7(l������P�R=�Rg�i[]�xh�AaKM�,�oq�B����z���m�����b��I��e���G�J�pJ���mu��C�
[j�Y��
w(T�N�3�VWx>�����&�VW�C�J�pJ�q������v����8j[]��*��)u������������w(T�N��x�Q�J��zl�z#I�E�{�J�%�{xE�`N�.�`<2��S�^��I*A�G������W����OU|���txt�^�!H�)~%G�]x��� 
����������ot�+�t��S�4��0[$�=]��W|����G�^x���`�L}*A�G���e6��������"XfS�J����{x��`]L�+�r����"XS�J����{x�� S�J�m��*�R0��]��W�,��U� I�>)������l���xt�^�!����G����/��ljA�G����lj�t�?OU| [&�]��W|V�����<U�E���@-����=��C���@-X�����/��ljA�G��?��l*�t����Q�l���xt�^�!��v�����T��l��������A0��Z0��S_�ljA�G���h�� ��S_�ljA�G����ljA<���*�6��]��W�,XF��H���f�HD�E�J����{x��`6��Z0��S_�����.��+>�lj�|�?OU| [&�]��W|����p�?OU|D��]��W�,��T$��'��Q�l���xt�^�!��v����T��e�J����{x��`1��Z0��S_�����.��+>�����x���"X�v�txt�^�!Hf;P���x��� ��@-����=��g�:��@%@�n}�� �I*A�G����lj�p�?OU| [&�]��W|�����<U�E���@-����=��C���@-X�����/d�$�������A2��Z���S_�ljA�G��?�h��I��If�D0[$�=]��W|f�����<U�E�l��txt�^�!f;P���x��� ��@-����=��C�v����x��� ��@-���/���+����y�x�(��i�v3��txt�N�!Hc���H��x��C�l���xt�N�)�WS�J0=�+x��S�l��txt�N�)@,7&�s�n��=��S�!�]��S|
tx;O��F��p�OA4��txt�N�)���<�a����*>�1���0�=��C���w� �+x��C�M��W��.��)>:��'8�W�T��@G����kkZ��`����������),�;�3Df�9LF|:�f�����l ��j��/����s.Sd,��+���o��^'S7���5�z���Q�f��}�
�:����!����[T��3F���%�[�du�����l)x��y���-��o��s4���4������������%�[�Y���0=��;�g����m���4k�u��s���k�0���'k�����g��{v�i�
,kvt��)���iwWB�����/�,�������B�!��}c�w7��u4��*I}�5�{�
������������A
^b�����I��t��7�M��h�E
]�[���}�<��Y��U��Ug��.nV��e��~'�;Mz�'���#*���u��(X�F�`����t��! ���09���M;����i��_�1�O33�?|�!j���}���#�RyKJ+�w���A��"�)�B;�yi�2/0y���M�b��@3�4i���}�5m��2|Kc
3�Yi�p��,Y�b�*�Y�q_�]#-��:�����������N��Va��{t�	/���L;��\i���+�l����@:��4T�]M��ZR����-�*�ki��KS�y��6k^�zJ�/mH�E�.j�R�b�K����*��U��Ug��.���n-&��LH#�	�I���_[��J�6�1�[�i�-�lh����0I�����:��6J�.Rp]1�[l*
"w�)�*_N���d����-�&@��I!M';�]�b��]�h�@�&M�t}������@���S<�,:�]�b�	��(��P�������oqI���b���;.��K���G
mP�]�6��=4�������F�����P�W8�S���X$]M��ZB�bM�r��I��6�����W`�}��g�,a�����)��q�{��������,i�E�.j�B�bC�G�s��X}��4:*�E��j��j�e��a���[�vi�@Ks��O�4)x��>�V3��g��e������<Y�b�+u,���y� �G�Q����e�<�b��$�5D�t����/�L�I����������&<l���"�t��>�[\�5�{�$�I&]�[\��y��+��gL��o�SM���"a6c:�q����o��f�G+���Aw&�|�&�X���a�2/���������������)VU5�[��&�(��Ka�H�Z`������8��_��,�uQ����*������-��j��j�evq���w������+0YRpq�g�S@��0L`�	+0X�o�aeo>-i�f&��!j��Y�o���{?�6���c��1>�}�M����k�I&M}��3�^\�3-Ws�M��-6���K6X��������e}���u;����0:`��Wt��d�#(mh�C���o���G��X�o�3���.� \M��jR�bS��_�ngV��<L�%l.v�Rv]�o*����E�-j�R��f-[��,��M��M��Yf���\�3+�t�
�fI��/�OY���H�->��8u��&��=��oq�������������4DMt��o�&=�g�N����M�'��oq���+�F!�I�I�4^��gL��o�&=tO��k�4k�U�������e�t�\<,:��o��d��v7^�.�f��Af}�5��>WLTf�	�y$�.���'��i���3������;�e$\M���Q�b�~�
D���h�x.�t�as�=��n� �tY4���,�-nY�9KLx��y��y���������6eZ�.��I��/�1MH�H� ���f��3oT����j�����=��oqw���T�M�Q�]+�[|j�+��y�oh�p�1����-N��s��i���@eZ0�Jv,4������=KX��Y��\�������S��v�g�E���'�����7���0*���-�}z�g%����G&��~��-���;U������g"=�����6_����+���&]U]�o���
k��k�3��	����cH,�E.j�B�b�����b���V��V���~��I��0���&H�������EE��%cf��-n�w_+)��b����L����	)�	�!j��k��-~���0��Z4\<�������'����oH�����$c�d}�
������I�&]9�[�YO���4e^�.����-6��kl��0��t���Y����aLh�T�!���G���4I9M�Bz�B�b����Gs�u����&�-���;(�I��4Y<M�$l.~�m�.�uY4��F,�-���.��(��[Ka��4��4��d�]l���f^lS����Q(i�\|���4�O4h��z<A���#�X����"=��o���L��5o�������u�<���4_<�x�3�����4������R�3��|�,�1i��������4i���}�;���4R<�,:��o�n���D}��KNX*��\8�o��<:���@3�
�[�Y�@�G9��O;z�B�bS�s2FM��tUu�����x��Y��4[<�L�'l.6m|���uY4���0�-6�=\�i���V��V���.~��I(��L��[�[lXO�H�e\�O�[��8��;1�������K-��>QWY�3-v��3&M��X���H����}��
�4i��k}�����*�����gB.�<",� �[��9��A�Z���X�U�����/v)Ws�Kh�A}�;����#rqe��@V�[ljv�p��:h�UU����zz�/�v�
&�6�V[.�`]���K}��3�`�'oZ5oZ5�2���Q+kw�����I���v.���zP���g���LA��c@0Y���M�^I�B��
��=��^e}��O���������
L��o�f��"H��� �IW
�k�c+#��6��4Y�b��GK;�7m�������}&1:pY��}���}�j��m��}�^;Ai(t��XU��o��UC�6��<as�?�K�0j�e�������9[���oZ5oZ5�2�����
:N)��e
.~�j�
:R��F=��oq�j�
:B)������P���i
�/e=7��x��y�[L��?��dZ������y�[�h�W�4 L�&L�^���U=�E�!+-���fy�[�U���>��=����[��u��IG��#F����[l���W��U,��z���[V7H��h
���sU5��[�������v�[�I�������3��nY4��k������I��i��i�<��`w-��nBZ���&H���!-���6;��w}�]&k/@�A@��"�usp�k����A�5o�U��-��Z������������-�;�ns0?�F��~����k���h��i���-6�u���_���F���E�d}�_md#��X�7c�@�����c�Q&���Q&�^����*Z���W�zC��f�v�
�u����/�-����9B��A�^bf6�j�gC>�,���<��V�`]����K}�k�����g_.��*�������_f������6	�	&=��I����N1M �z����:hi��`���<������a��0��A�b]��k����6L�{Y���'����2eO[�}���	�0d`&K��X��5Z�N[D(�f��i��IW
���S
��`�@�����]�V�e�E���?�-����	!��A}��C�{eG^����=d�o��h}eWP���XU��o��U��/lx��6��4:�[M��!J}�u59��DR6�ti�ti��/��;�
�P3�\�L� b�!��A}�;u��N�5E�����x���[>��W1<]�8�O��8����|������I��-��ce�2��,�`M�fM�r��X���K%	=)�~��U��b�<Y����w��Et0
���C�b����+-N4Aw)�-�+y`"2��)�������3�XM��:Q���u��>��1i����S'���XM���H}���8��=x��y��y�������-/�&M
.��(���Z�]{������?�	�,~�\��_j���>�x����oq�?�zr	�|\������g}�>�U���#4�+6I��I���-����(\�3/Wh�����-6�ub8��e!+j�f�[�b-�s���,���5��Aw,�-vR�s
��e��j=n�o����mPp���V��[lF����a����y5j�oq�j\A�VM�V��2�����B��{�)i�\�j[r�o4oT���;m��v�`f����Sk�sD�5o�5�����T���L�'�b%��~�qT��+���RW��
�A����w�B��[\���!K?(��)��I���R4��\�3Mw��������I���6�;&M����f���`�t�e}�M=�q�e��/�����]5i�������4�������W��[�b_���e���B���N��/���k87�I�,��;�Q��L�Et���[4�[�r��H�7D�4O���������r��w��z^�����\!3/WP�@3&O��X�����	�4i���}�Z�}��8	��r��h��o�!,-�HP`	E������\)3/WRl���B�[�o�����j#b@����_U����A���~����u��y���#1����]��^Y��,�sQ#��kN~�m��y���,� M�&M�&Yf�+���0��IL�\�t���&M����o���q�a��0�q}�����9�z��qa(�k�����+�z�����`'�|�3��p�������m�U������C���2���K�����uH9��uvA��|�svqAzj;NB	�0[�o�!,�!�}��I��%�-6�w���k�z-���f�\�h�%����-#�suV���E��[�Y�(��Y��.H��I����yy���}���0��_�Yl�I���OaF���<���f������?�%�
Q�]�[|�'�Pa�[��k��Qf}��zx�\C��^z)�|3���}�A=�.X���-.X�k�=�B��� ���j�h�c��7c����b�{���������B}������"OA�����o�i���8N�w4���I}�_�V�S�����'l.6��~FM�,�bQ#�����SjS<_��UR����j�ev��
J���y/�|�2���y"VI=�.h�?������Jx�=���,����T��/��	���-n�����zV�qa�����oql=�m,��G�a����.�������H�+/8���-6����-m�zW^�d}�5���K4H�UyA��|svq��es	�B����-0�J9D�N�o���^�
�-.hk��0��&\U=�o�C��\ ��R������z�\D��g�����L��u���)�usq�N\$�3��"�~����ip�S�s�*�����'��
�]�b�9rpu�t\=�
��d��[��5����i��I�'�[l	���X3�In����oqI��������`�:	��%�[lX��\3/J������o�����d�u��l=L���'�����[M��JB�b�������b�=��y����h����)5Z�o��U����i��i�<���n��$���F�kY�boq��r�����FW�V���9�}V��`
Q�=�������~����(��w��x<�����~�LB`d}�kB�����~�,tI��t�.k�������o6�.v������6A�`f����Y��aqT����1���O����t0�P��~�L�[����K�{%�/m�
������f]U5�o�b
��AI�Bd����I
L���X�F�Q��\~V�6@�a�E�[�[�H�I��7�����~���j��j�ev��e��A�k���8��B��O6�z��	�V.�����#����|�1�����R���Ki��Jc��1�����&�5����6��A�bg�o�w����-���������o�|��-a�@,�k�..5Y��s�M��M�^���I{`��^`�f���&o�CO�(������6c�v��bM[�+�K��a	�Xa��
�o(����E�������)����<k�!}�O�5?�)�Y�A��������Z|Q��H7�Xa��
L�����}j�����i5��o�Z����5��5��e�]�lbY��A�lXa��
,�r.n�UO1�`���p�O9F���B/lXa��
L�us�k�1miC��AW�k�s�4�5?��e�i���b��x�O%�}�Jhi�pd�X>�]�iO�`���&��t��o��=�,��4p<2-�'�[l�{�s
ha�@��|�qvq���E�,�����t�B��ii���X�8���X����A�9[�	�:h�UU������d����+M�N�f	��5�A$G0�.�&]�(���f�8���kZ5kZ5�2�����uD�s��p���*i�\�y�����4`��z0�w�����5-W��e��I�"�[|�iy�#��!j��k}�_hY1\�/e�OPO<�������?v�����4i8��Xv}�K�����n����i��IW+�[lX�b��\eV�3����[lX�~���+�XwL��o�a���mdya�1�q-�~����J[���-��I��o���+f
���	WUM�[���oL��b�xd�4K�<|�U�#�)�.�f]�����/��v
�i��i�,�����[i��J+�#S�,)x�9U�&�8=�L�4���1I������_1W����'&=������
'�r�@k�5k����;S�uyS�?DS�������o���X�X��
��������o��>+�I&]1�[�+z��*������h��o���K{^�3�f,���]�y}[^�Ui�2-
NgAw+�-nV�q]���9������0�-~��b�@��vUU������&��G��>l.6t�a��bY4���*�-6S��;�b�@�VM�VM��.~q��u���^<%����
��/��Q`~�q�.����7�:eNZ/��������6vw)�N`
Q�]3�[�Y��	K������p�c~o2�[<�u�?����'��������}��'��I�&]+�[�IO�3��~�\�h��o���>!
a�@��|�rv���i�C��r�(t�B�����	�F5x�A}�5m����	���9WUU�[�8��(�E��X�������Y��b�J���GX�>C��e������X��MU���2k��j��j�ev���"���HVf�A��(i�\���'����g7!�z0��.��5���bya��x�^eV�3���`������C�W`
Q�]7�[�\���*h�t�������/��h 'm�� Y������k�C3]�U����*��K�K���$O����:��z�p	��'(��b����^,�%�j�#K�[|<j�SY�A���b��X�y�V�
d&K�\lX]��r�FMc��4���*���[��4iZ5I�����&=�hLt��I���1:6��E=��oq{��QS�J�h
$&������W�4:X��]7�[��Q��):T�D~_O+�S���Y��o��z&���PdZ2��qF�v��qE�4E�5���������"��7G�����{q�!)LH3�o�.n����/MBAw �-�t MB"�jh#K�[��v������iWU3�[lZ������
5\�I6���x�R�ZG+�e�|�����9p���7��7��g�]�b��!>���|{3��i���"]��X��]�k�{�����T<y�1}��}��g��3��A��Vb�'��J��t����Z�}�]�b����!
��� ���%�P:'�Ux!M�&M�VY�b[Ke%a�t(Rd,Y���z���VX)��,Y�b�z�TI+��1�7c�d}��a��I�$�� �[l*z�DL��� ���&�-6���o�I:$y3��y����i�@�,�vQc�w��q���j��j�e�p���H?�LJ1�!�������� �H�����O������aKs��_�6c�Y7�[�}�#IG���k��-���4?�Wi�v\�+~�2�[����/�eNZ(72��lFk���-H��I���-6����M���Y<�,�$�[\��Wu�#�\�0c����b]���.��\�Pt�B�b�{�&�Fi������������8mH�A�������Y�~d��f��3i����&��B(�ES,j�R����X ��U��U�,��5�ah:�LK��N�4)�����/bNz��\�0��}���b�2!
�8z�@��f��1���6DMt��oq���)M��c.�t���c~�3�[<���@��	i�p�X>
]\����ak�4k�����u5���I��6�'�E���-v���a!��Y �X>:������LA���T�=}�u�GR���O�i�x��C��s��B8�As�����Xq�r�������2V`�q��f�,as�����.����%���I5T�o�&��'��Y<_�1kZ5kZ5�2�X��p$=�h�x�I�%k����4H`�z0�gB��_kaZ��J��s�L��X����[|z�V	�!j��+}�����5���?���Zx��1?X��-^�k����^���F7y��@�FdM�fM�v���`=�[	a�@,�J]��y.���fF���;���M-=�
�0P���Ctq��'S�Z-<���	}����E �u�t���-�=u0��0T`&K�\lX�a�f]���QI}���;��\fM�VM�VM��.n���(����
���u��b��E����Q��6�,�h�.6S?/���gZ�a���0V`&����YY�g(����Y���-n
�b'V|��h-��'����Y��X=�>8���F
����;����Pz��.��4%�i��I�
�k��[}1D������E�d}��U�	+�JKVX*�f,�o�]l�z���4_8�������H�����i�x�C�����'V���yWUQ�[�l`�gW�V��Y�Qh�4asq{�+�0j�e�������Lm�Y��Y��Y������_t��v����yRpq��u����Ui�
�k�#�~Z��J����O���������
t!j��+}�u%��b��_��m<=q�Glw}����^��s�sXi�p"�������h����`�@�&M�t�����j��K��S��yv}�
��{O1Y��I��I��->W��Eyi�p"�_������5"���*v��&=�������c�X-���f]U]�oq��u�j �Q��i�,a�p�����F���i5��o��&���.�&M�&M�&Yf�G���+������4K
��&����U��ze������J���LKc���GY��v�vCK	m��6��e}�m��W:�P��h�`<��_�����/��	i�pJ�X>�]l�:��"M�"�:@�����zNs�yi�xZ4O���i�����P�0c�����>a���a�h�����=XO���M��P`~�w�\�i�6{i�����;����.��n�@u�u�nQw*0h�oq����n���^fnw�O�f}��3��������\��i��b�{"|)�;x��y���-~���������E�d}�^��q��(2�/��.�U;t��,���V`�kp��-����HNH�Tg��������\���A��%�-�Pp:���;.�?���-���~�)!L�&L���g.Cd<�����/<�.6�����
O�1�Ng,_[.n����r��w����-.�����-9�iM��.�	����u�E�����7�����~���X��}Y���~��
N@�T�������~*�IW������C�Fa�<Y��N����S]?e����Ptv���x:�a,_
.�my��u�`�n�����es�f=�1r=�#���@�[�����o��
�[\�j�;6a��v,S��v}����_y9���:���-6����0��;�M�zY�bC{�s[��#i�B��[lH���Z��8���;a�1Y���%k�a��y��O����oq�Ss����&Wwb�����������Km����oq���c���Qwd����)������bi�'����c�e����VR�W����WN���&��tU�o�S5@&�u�E���-�5<��p6����xU<���������Q�$��i7I�]����to�sZ��bM{G�wT�i�I��.nv���2No�F��������i����|�����P��x�>N�w$���o>� �[\���c^�W��t��o��=z3�)��~�X�84�X�m�9���a�X�74�X�������A$`��Pp�	R.B����t��SC��b3x��������iquB�b]��{yRCg��5��->?+�4�^�������oqh�
����`��+�|�%��`m��%i�IW����b��Ud}�uK��| �d)�|%�X��'��n�q��5�es����<0�@�h�M��.6C���JBu������)�5iG��������o1�O��p�io`�f,,�������LaM�fM�nY������������������+y� h�`�d}�
���3���O��oq����td��u�=�1Y����u6�����}��C�m����-.9�j	E�]�1�����<���|T����E�������X��a9�G5;I
,������Hcj�j*�XB��.��:yk&��x4��b�������'��&"Y�%~p�a�������;�����������M�*'-��U�[l���9M���N`d}���y0)'���bR2�w��x��M�[|L/��E:`�]\�����%o�4o���������k��Z����'�[���g)�����F<�[�Y���������
,�����u���s�k�0��t�B�b3|�34)8��#�d��.nV��+���`BuB�b�f�%`�`;.�F^��/���}����_$�P���a��L��	���-._����l�>_���->]QNd�&�K������6�]8��y�%�sp�������C�l�[�����T��y��q�r�k'3a�Fk������9���i�oq=p�^�o6D�+����6�[��������������'�[\�6��H�IGc��,�o��8��$����n$����-O��ER�8��&$Y�����v��K{�	����-n��S3�^���������:L9�����F����X�^0c�io���L���[��'%x9	�����[��?r	o�4o���������+��h�7�~�����k���|�3��o�i��I�m��F���e���i����n��2&A���T�D��M� ��v}�m����r^k�7!��?���a�x�����b	`���o����g�vz#-��V�..hf��m���YB�b]�C�����6c	o8�X���s�i�3�K���b�zb�,��9!�#y�oq�9����PD����XW��Cs����bZ0hZ��xR-G�*G�v#+��j�.���Wi�4i�U�����h�[V�F�
&,Y����aI�9�}��%�-6����[{_	��[���<�������N�_	�6�����T��J(2F����5H
�����*�}��b2�S��xi9C���W�	���v*�����}�)�}%�IW�����N�����rjtq�e�#$&�v���%���b����6
t����J�����E�g�o%���E�[��'>9����l��_�����Jx��H�[�y�`2��k��b�`9Y���vU��"�����'�� |��*�i��IW�;��"���!\4A���Y��b@�<�I����]|���� ��!���	.>=~0�I��~f<�es�����X�L�mtq]Qw��d&]�	���o���aT%No��cY6F��-��k.�d��=��e�����~B��@�4i�����-.Y{w������tK����]'x��a�k��M���v�Vr�kg/!��-��O���v�"]��>�[lG��we��j���� ����-���9o(�r>�Td,�?��5����B�&M�t��oqA{�a���!!��]��y�;Rx17h�V�}���v�
	97`,=��o����������?���]�rvn�'9a��nQ�[�jOr�i�����o���>N�/�r>j�(a����%�/��/M�/�ZA������%!'�����o�n�������#�<���tE9��3	�%�Ip�C���$�tW3�������L�[����dt��'�!�6���@'��
����[�����G�����/M}�LZNy�%4Y��������I&]/�[������i���	,�OF�����0��[��e,1Of�����&+��v���o����n!�tO3 ����T� <�Ls�#EZ`��2��L�rq�k)!��K�oq������v\�
K��-���p1�,�~R��h(��������i��I���������"�DA]��51����f,Pf�v=��ER.�WKH����V�|�H������=�->���k�[J�nT�[���O�o3ZO�M9K���� ���)���SL{+�p�e���@�Yo9��S�w\��	*AE�5������;.H�����YQ�F�[$��i�=A%p���o�
�	���J�m���v}��8���q��'����D�{�EyAPN�@�J0�U+�K���cT�R �<bCP��8e�V��N��N�zLR	��v��
����HT��!pX{������x*H��8}�{P����<�J$��s���@y=�0���5��l�����43{cn�h>w������������$�`�
n�G_�H�UPS �8bC���B�qB*���9�:2I%(�{�H���+���@t�
�i�� �������u]5�T����K��Uf�r�*I��Vu�����Q'�f:�I*�n������:(��k�N%e�+'��'�.d�J�j%e�+_-�5�1:����W��A[Nx��UPS �AbCPP�-�Lv��U�&S?&��
�����W�[5#dl���mI�uA�q\LR	�;��
bY�CW��$���fw)����*I7��LR	���qz3�+����*)��!x�{eEP�]%y4��$���p���M?*�.��cd(��� �����`�|�4��$'�k����5��.�I*A�i�~�	��9[@
�(qEf_�5���*�>I7���I*A������44�L��3
�$��qi�8�I�	C�,%���lC��^�������5���$�`h���|1����%5�#6��O��fX�dX���TS���d*������16u�}�#�OyF��H���!hV�cjI,K�r�*y����_��*V����e�J�������~�eA��*)��!8��2��GXIM�2I%h�\�y�,�Y5&��,`x$�S������0�U�Hd��4���OYF3'��ES1I%hW��J�� ��1�cn
��R��h�/8)���!8�)3~T�i`
Pc������
PG��HT��!hR�{�E�qAP�'��@�J�����y���
V
$�Fl
����:M�:��1I%0.�7����	�\��l���*]x�T�\%7�cn4��_nf�����$B�J��e'���L���~��18��!��������YV
��UmcCPO!��)���*9��a&�������W�_�Kq I%X�{�I7��[�	��UR!I%��g6�2��[V��$�����T�h��H|��!(���LN��U�R !;BC�j{��T�Z%�f��TM~��]&���*�)�cC��^ �4U�[%s4��$����F<NP��A1�'F��I*����p�*/����I*�!?�M
j�����`B�J`��Y&���*��`���/0���d��=F&�r�*�!������s*�%87���I*���Kf�r�*�!�m���yH�C~��T�^%u4��$��]���4'��������$�`h�`�i��6�_��$�� ?�b����g/M��I���*�|BQ�s��I���
A]��g�r;+H) �T��{o)J���.�$�@����Mf�r>+�)��%cC���c�LM�VrG��LR	N�(�DO�qB��tf|$��Y�(�����HT���/m��<M�<�2I%��������b/4�@�J�j�e=0�hB�D:���}g4���a���I*����o��t-?�l
�nf���g��fY/���mcC������b`���:��e�J������b��vA�l0	�T��%�,Y���)� (�!��/�$O�!O��LR	����z.���HP��!(����}��&<H,��!0}��4?���z?M�^3@-K��|&$�Mj�_P�t�z3=KC�,[C���F�,�e�0�p���
�&?:��R`���:��f�J`FUk��������r�`�$����9c�������	�T�}�������	y2�d�JP�����
�8�R �S�����y�N'�I���
�n��)$��q�#9B%4����K���*��l
��>{�HjY'�W�0mcC`��"��N���#N���k&��1�i���.(���!\r�J�$/�O��5�INR	,��9s�<i2<�TI*A���%��$���0�$��P��p����`��1�/h��^Z�����j�)'����oB�����\HR	���?�in���@����+�8{p��8����<HR	�)�=���q�����2HR	���Z�@�R mbC`X�eCx�dx���T�����o���J����U���C���`��f�i37��o�d��?S AmBC���>�%3�x�	�fz�I*��>|�������8
�66M�����
y4}M�����&����<�f��i���i����m��"X���,��@������>8pek�k2d�J��,&`����}1$HR	L;8q]3W��U1I%���O)$��&v0��I*���Kpo��)`��ek�����!���������\��5�.�@���
���$��qz�����5HR	B�P���$'6�K�%9'�q�%z���co%N�Hr
$�Lh:-,��x�	�f:�I*���8���Y) 	�T�����BM�R �k���7p9����.('�� I%��R��<9iB�I����
A�y�3YeF�>�0I%0�����p��=f�$���9�-�L<��'<HR	4�����1Ro�����a�J���/.d�>�S �r�����	g��8��f�J���+���7�]P����kr�J�$g��e2����^|Y T9I%0�G^V2#��P'SK$�%u�\�~��u�x
ENR	�#�NV��kp��9�/0�|bG�u�8���I*���k��������"I%0���`�#m^j��,�UP�����������o!X$N��,�i��e4����\94I*�x�_Ox	r��m�@B�����z�p���i��-�T�v
�y�<�(�H|��!(X�`r��2��_ �)�9�!�����V��^/��e��@1I%h�����\���.$�Mr��V&���h��I*Ag0��3�������]�$�`~���4�3��%A�JP��Z�h9A.��8�-�fl�����s���E���
A������2g�c�!I%��g���z3�M#� I%x��eJ=�S al�����&s�8�	y4��$�@���p�g�]PNm��A�JZNk�(T���5�&6M�Ft
�Vr��p'SK&�M�"�L��GjYH���0!I%(��m���+�q�[$����
�e�0�{���THR	L��]<yd�O9f�$��t��T4Nr�M�2I%�Y[��$4nr������mr�J�$'�Ih��H
�0�$��M}0o��&��L-�����>���yj\��*'�%w�7���mN8� HX��8���9���I!���x��be"?9��L�"I%�WT�*�L��a\��d}�����o���4�>E�J`���������������6X7�I^�
��\8���CB�D_Prw/�0���&��L��`X����`���b�%]
+�s:�{I�IRNZ	�3�K�Y�l�A9Q;g�|�S���
VN��&�4)'��:�c��<%'��D��}����l3�i�������$�`��T�F�y=Cj���EM������<M�;M�;�Z2I%(��\��S��qZ
$����%Nx`���D���n��V���o|��I*����yn���s3}�$���<X�*+��G�ml���� ��t)�gn:CG��hV��1
I*�"�*��8�G���	����9NyY�dX�� �T�����2#a! 	�T������h�(8)��;�!p8����t3�KC�,[Cp��2�F3C�I��������hz�	�37z��d�4�^�����u�$�`}�J��df-�)�@;�!���?��Dw�w2�d�Jp��1����7�glN5�s�&�\-��[�(?sC`*~�L��`��M���	
����4g8��L�3I%(��7��hY<�+�PlcCPs��	k4=L����3�����<$����de���� ��W�����x�	SNR	����s�s2uD�JP2wm�,�5��GNR	:-�~�������,X%���N�W���GR�#'�������W=��L#I%�W�Y:�)s�8�	�6�������8���r�2$�T���W#���B����#5�'6��`��3>qB
�� I%(�m���3~p��@���
�������f���	�375k��T���$�gzSB�.�3e6�81I%h2w��X�������36N[�n��3���@���
�3��>.�d��vA9]%xNl&�=t��
3''-�Y���h��s��q�#7:gl4��/�2)���pC �s������D�e��8�A�JP�:��fz���Y���Y����L/��5�qB��
A��{��:�N�@���
��������������3�
�T��E?�
p��������
��>��e���	u2�d�JPP���'�,�=O(��8������+�q�[%x���6>^���<rS uBCp��]E@.�x���I*���yi���;�Fg�JP���S�u5nq�����5�$�`�]��� ��Y�'$HR	
��n��8�P��P'S?&��Z&S����2u�C�0!I%���w��6nq�����n?;�$��k���I*�!�~�'��R��l��8����	k4MJ��������xK#S�8���b�F�z�I*�����,4.q$�@xr�J`��,��x�	u2UD�J��s�����yj��)'�%u��s���4NpQ���������L9�GV�$'��>��c��t*�B�Jp�S�O��Y��'D�����R�h:�(�ff_�P���q���:��.HR	�sNa�����N
$�Ll����p��p&S-&�]��lON���b(����'g;9��� 37��t��r9)<&4'+�IN��t(���l
A�yf��in.��@b��
��F��&i4=K���]��'�2��#�.(	�pA�J0����o<��I����
A�i�}�!O�!O�~LR	��O��O<RS@&$�u[\��U&����=gn�>8S�fZ��Y���^��u���5�rB��
��A-���	'�fn������F3�mj0��T��]�����p4<H<��<g��d�;M�;�*1I%0u<�#��O���P I%p8{oa�F��H$��!�rzV��$��
f1I%8K*���Q
�f�=����FrYhPM�2I%h�{g��`���)��:sC`��"���7>{��\(�I*Al��x��u�8���	��,S���P|RA���'����I*A��QI.+�q�.$���D�E.�aO�!��:sC`����4�O�t8�&6���_�cP��0�a.	����}�8�u0����$��1����R����"`�akO���8�e1�����8��J=���.Y�jX�jH��!�������g���������A#����y��Y����DLR	4s�=b��_R0��E�h��W�ym^��h���%�TM����v���6��!L����T$9�2�]3����@�r�J��S|�Q����A[B2��0'SI$���G1���SRC L9I%�
��������
s$	Z5��|�)Z�gp���!H<*���,��R�p1h;ya���(HF)�K.�,7�[a����{�g�JPrw�+�[f�Y!������0�e1<��LR	�C���),��j��j������la�2��L�p�������Pa�@����LHR	���~�+^����!�u�/7�<��h���&�T�6y���D���w���D2>�T������<��Mr
$8[l����b����p'SO&������6�x}��	76�]~
�g|���77�;=M�X\F��X=�a��H����.4w;kay3�I*���=
�:�UWU�T����Ha�2�XC��&C����a]�?p/��^���$��9�[fk�
yZ
yZ
�27���I���ef��<�%C�BC�������hF�a�J`��~�����byf3��I*As;0�B�!��LR	4���L���S�����-��G�,`�A$�s�
��}��8����$���|LN,�y`!��T�I*A���E�y_Aj
$���h�����z�q�C ���@�ELW�e��1��f�J����-�og.�#�lf�3I%(�u��oa�x���K�T���r~�(���0/zxI�J`z��Y���j��j���!p��q�L���8��I

����e������G=�%I%0����u�+Xa�x�2#�I*As�5.����<DCL-����T��1OxvAi�gI*Ah<����c^���	�M}��P��P'SI&��z�VL���T�Z,�y�#LHR	
�3��I�d��$��97���:���3�`:�����������Q���m&�����oc4<�`xV]EIR	t}��r��<,M�+l
A=�Z�a
���EbIR	^�����:��:��i�����:�&3��
���U

Aw�vAlH�^��I*�km-�-S���	�.&�N}!YC4����I*��O��@b��c1<e��"I%��1��X�4o�\ )H���h���7b�@�&C�L5���=�$v-s����h1HR	Lu��������H��!h7���d0�,��`:�I*���n������|<�Q�$��LmeO-���`�W]]IR	���HV�G<-�$l
�+�[0��0'=�$I%��G�mbk2�N�ij&�����	�bx2���$����^UV~0�h��MLR	N�[���W����C�$�Iz��:�I-������j��S��KaN�aN��HR	���[��yw)T9I%0��].���1"��
�%�&!�g_P2��i�z�����2�7�����G��e��4��bF7�T���{d]���*3I%�U�G+�L��!����������bX=����
���-j&�s�����e����%yx8�m
����5G�O^$�f,A@$�����!��j�Z�O&f,!I%����0��hx���T��wg4ec~�Hc7����$�`T/"x������H������)4b$M�!M�vLR	tu��X,�i�@L�
��u�a��#3�$�@3��0�`:���H���8��
,���)�f�Y`5�LR	t�g<cPFbH�LSf
2�$��L&1&d^����%I*A����V��VC��
�Z���t3��) W

�&�{#O2���&	w4C�P1I%xqN��9��) ��5f)98����:DCL5���a�>������O�X������O�V��������+|J1�&�pc~z�6���!�u~�|������s��;���a)�u������������B�E������B�+�T����Y��(��3:��fI������S�g����>��w�gm�������m��m�C���{t�f{Qv���B�%y���_���������7�����O�Z�%�bo�}���aX������m���������O��o_~��O>�������Z�1�o��4��~��?����|��ti����|��k���h�?~��-���~[��Yy���KYo�A�������a��y�Y~6���1N�������c�d���I�v��f�:Yf}���8�����������|����������������1�Z�4�:`��_����N�_�����z-�0����������3_C'�?����>|�q�d����_��<�������o��v�?nd���w��1�������}=���R/�/�
�����^����4��R����ROc����S}z?�������k���Yc����T4��sK���:;�o#������>��:���b-�u�{.�5#=������o�2C��?�����:;�����^�~���]�y};�ts��r��m��9�|�s5�m��{�%���������}7��~������������_�;#����z1��m�u[������7j�q;���Ws���}���7����y��_k�k'����}|�o�0�W�m-�����?_.Z�u�b�s�v�)�4�<\6���������U
�Ay��g8�q�x����/���7���K]�g�Y�~�(�3��~�}������r�>c�d����q\�������]yq�����u��&)..���|gN�_������n�_�k��AX\\4�����1�N�7Fv����/����������h.��&Lyi��������z������Ec&^�����[��>oq.^�So�����b��������/���gW^�_)n)�����)n)�q���D])rK������rK�����9/K?�������]V?���p���{
7���*rO���b���*��?5��z0T�_3���r�b����r}�����.�/>xB�o#�������o��&�w	��R�|��%,<C{�~���L�^�_o��^8I�Y����Cq��.��]Bq��.��=�\*xY���,.�����k|����|�#��/��������{�������L���K��
�em���<.�^p?����;cF.�U��;_�d�3�������%�?j�|���o�q��y��z�0�G��R����������(��h��j��l�K����-�
�������+�~�x��"������r����?>���5/�Z.���>e��q��l������s���8J����r�q}t�eCk����Lxk��n��W��r��w���	��UC+���#i��9N����k^7��w�����B�"����~.�[�o^���q����r;�!���|�����q��o��n�]w�H�~�����
���}y��v.�Z��g����[�4�����������6�����Up�����yy��f��#\��?�q`.n��o��Z�*8Y��N�oR'�o7��w
��������E�!_��-�,Z��z�7	n{������u2�3������in�������w9���~������Bk��x�X�%4�}�Ibwn�K�U������N�W="�.��>����]Bs��x *��K�E���.��������wT���#K��Wy�����uU�]b��7[;s�.�?��	��������������??��O�����iRH�1��o
�����b�{��������S������5��X��R�?��O����b~����E�e+�_/����P��b[>_C����N��V���Y_l�m��������� �<�P������}������	�I���|y$W<�_�<�+���_�O����
��`\\�<Z�N�cHg���}T���m�a����r�������v�=K��M<��7h�7v����4E�������v|/���\������-^�7F�[#��\ws)n�����M�[#7�?��K�[#'��7\a�[#7�����������Oyk��/7v��Qc��x�S�������~qk����7^���FN����w?�����|�q�]������s�Q�5���."|��Z\/�-���������}������.��|���9�9y=^Ny_�f}�F��E�����Kq_���h�}Qc�]�X��������]\���G�Cr����7nqK�w%���~j
��k��#V����{���+|���;�~^U4r��5���F��=]xU�0jw����^�J�A_�����lv8��4e�U@��r�����e�>{�����i~���N*:�%f���Eq�p8�|��C��-w��z�~�|�.��|��vX�S�[��\}%P�@8������p������p��q�+n ��?��X/n ����C�V��}��WB���q�*/%���y�t������ssu����R����g��a��K	'�?���Gfq)�d������w5����,���R�m���B�O����?����������\{/�1n��=�
w���TP\P�k���'����~��+�������;�����m��7^S�w��{+��]s���x;0����3�;c�����}���!q�h�}�nb��{=(B���^w��;w��q�"7n������z�,\(>�%���F�p�����~8�#p�r�|�����n
F����("-������{w��R�����?��������_��?��?^���]1�a�|�k�6�����=�~�����l
_}XQ��$N��n�X.c�8Y��q�����tj6�����^������~������{>Z_�P2q?�d�3��������3�3?���)������F���4t2����_����q3�����(��g�EL#�>�E����;�r���F�7�!��w(���Et��r{����(r�������;;�����x���;`;���P\tKa�d�=����h�
��������8�J�~2����i��6��_�\��-_r��_s����LT��42��O��V��.�����(���7���;�F�7<]�����?��;7��w%��q��~gD�7��q[��k>�������&#��S�0��_-|9g����+�_9_~*$�/]f���2K���q��Cg���Q\���;/�o7N�����/��;�)�G�E��c�2��C ��c����;�������l���g�!�l����,p�����b�����k���7(o�v�_I��7\���=.��~��w
~�~�s��������P�5�����]�5�2��z��������)�kh-����5����a(w
�e��W������	�������s��m0�q��6j�g���W�����!��[�3w���zF��6�K����u�o�������g\���TW	�=����mW�p��q����z;3����{��;����e���;����q�������}�����[;^����qL�^��������Nk5��2���V��]{�8�����A�Q!.8m�u7T�_�����������n\,m���|��w@�/�}������-1/����_����7����������wX�h#^��o8�o}�����(��xY�������q��{�+����/�
�/�?�]j��;��S�:�:pRvI��N���i��wby,�����3�
O������^�b?�a;���;OQ$�m�q��s�!l��s�C*���c���-��W\���_
�?�~��FH_�4������������_<W���������y�������^{�S\?4��w�}��5���C�|��^VW_,��r������)����=O�����������Fx�=�m�)����M�b���!�����*������y����.F�*��@1������,�^��Kg�����]���+�@~��ol���=W��%�~�#�����}ly�&��������}h�E�m�C��� '�����z$��&�m��{��&�����R�7An3���)n���|��Uy�6��;q9�� '�o����#/����
����~��2�p�O�FU�5������=P#�ow"��@������{�n�W��=P3�_�*��k��wG�Z|�~nYn��������z���U/ �r�����[�����!�j,�?���[ �Q>�q��F�����{�.�'��X]�F���/w�i>\|���QV�5�/������B�t�_����;�8�8���j�s������|�����J��\;u���[/�7@�q��\c[\��~��Lr�6���a�����j��_��K|���B������X.�>���������>���9��sf(�����J��B|�Z�������r��~�,����?�Z������r����g����������?��0�B�x�q��V\
9��qW}�v�o�;��(���6�=����jf':��D���Q����8W��5P�����j��W������^���\�
r��fq
�.�?�wcq
�d��N�H�_�_�%Pc���GW^5��\�K��b{��Ag��r�Mby��\O��<�k�f��c ��>��J�������k��K]�<qq��������k�fS�0��M�b���!���/C�>�������~ ?�n?�IU�x�$�>���"�����j���/�%���l^�|t�r���m!�>�/�Z�F@�����7a�wr���m��4
��mx;=�{�����~�����|�4v3�v�)�<9s��q#v�r��#��n@c7����>.�*M����,\�
w�F���Sn����g�����;�����x�������{��y�����;/	d����;�f��F�_�|�A��m~�"�A���y'n�52�qg�3�Pc��q�����zl7	2�\n?"�qs����0d��F{��B�`�f������l���	��������r���@_o�a�������������������/^[-���u_��1m���G��i.�7�j�Sc����������~���15K|�#�9��G�Qm>��q���m�;�F[���TwT\�(b�4����
A��-|�%p��(���f�o�4�����;���7
�R�{������y��ip��q'����k�[?M�7
N������a-o���_\����48����1�5n���������y>�z��a�;�}^f�����6����^���qp���;��7n��y+��������oY72�y��}y��v��w�Kq��f~#�Pq����/7�n�����^�R�8����;�}��Cc������9,���b�U�5����'���Y�zX����~Z���)_���5nZ����q0�q��}�AN�7��o�������g\�<O,7��]\������������-/����
���/������;b��q�Oo��6��w��|�?b
c/���7	��Zz9g8�|tK��O����N.>��t`����,����j��m���KsG{��R��y����G[q����B.>����YB���v��'Kn��_��7?N����/�����D��WKn�_o��,��-��lm������.q2�WP�~�JN�N��j�^�����&/o�'�b<.7�7:�����.���1�k��X�����M��|�G�������A|�������(|�����b�i����#Jcx���U�d��Ne>nj��7bi�qScM�M�pAi���3/]P:k��H��5����i��5��^�������G�zj.5�>$�qg���(Y^=uJ�Y�����i��
���x���_������S�(|��w��f�������'j�����p�tK���wO�_����5J|9gqj���B��o�
�����Le������Y��>xl�#X�c�u��o��rg��9���|�'wF<S$��6���@��8rr���e�7����h��n������;�Bs���n��X��
���UEqk�d�9?���uu�5r����.��$'����B ;��Q8���7C 7����/�D������� j��#B wJ�!�;S��CUqA�X{��<!�Ms���� w�V%�C�Ou��"I�$��zT�=C����2Z��e�����geef��4��v��c��z�Ny?aa����4��$��A�P���m! %�o=�(%����J��+�77�o����E���D�	�m�	�{G(�9������us���iB��A:w?����hB�{����
�o����-����������!3nS���VW�Z�Xr��z}z�8���#jP�b��x7�lP��k5��������F�C�}J�;���E(AfdT�.g�S���uQ�h%�����Q	"���s*Az"|��D�g��A�'���Dc�R�@��y�U��:����i��i|S.j�������j}�)�`e
�O�������
[m��\�o��Ws�g3cM���%BU�@��[�V��^P�@��*���?�~�9 '�����X�J���W�9
h��-~:�KMr��_X��-K�2	u��d���q�~��t���gO�9?������#������o�g�s��c�����m'�E�;���o�x"�jeB�Q�)��b}�X
@���7LY#�~{����/�����fV�5�%�Y0�@������U���#O�`?�^shH�5w���Y�e�q9~(o��s^���~o�Y(3d�B�����%hoc�+����������06b���dR{�`l���R*�\����eVUc�&S1���S��A�d*��5���O�>2�����8��~\����(�e����O%�j;���z�F|��%�������Oa�����[���<�����YT�����58�xK�`Q������{�8�y�$��8�����|�8���Zh�;�������%I�0om?z�
������J:�q[os���V���	*��z~���P���,�3da&�i�lH�\t�Qn�Q�X4����qg���=���z��v��g*F�b]��#7��|y~z%��i
�-��+k
t.|���@�W���X($R�����j_��5�xK���5��X�L�y�WZ�B�(3�i�;(*%�mWD�
�������P�n:�/���E�J�h�%U��2_(�y@�����Q-�	��������#}8dW�CH����M��\v�����ipS�`
�!9��r/�I�guq��������ov���s���Sh���/����/O��sJT��(s8��Y�T,��"��S��|���~��A�.�JDr��0w��
|O�o��;{U�Hos���U>���~��9n�&I�#��s2��g�n�V`��FXd����&L���
,2�z#�a`oL�$�&��i��|~�i��������g�����C1-���:�+�����'�y��0h�Zt�Z��E��z-�x��>}z��f-|�Y����Z�,����f�
w4�p����j�3��R?M;�/���	��v���+�����/��Y��`3t�?�P�H���������h����h���������
7�C�x-X��n����G���/�~U���]���Y��ICUO��c��C��������_5�����j��~T�T�(F��_��?�e������]?�������������������G=>����7����k����Ef!EMK�\�n5-	�����e�X�l�U���Yw���u�_?r7�?������X����j�[x�����_��{�hC=��]��]G�`T�����P9������r�#Q��@��@OGOT��\�H��d��rD�;#���(G4(�n0HI9�����}3�����i�9�X����\���(�_(�C���sY�����B�F)��l�Qr�V�x��^���@5��:i��S�U#���Q�>�(9|��h���A�H%&���}%�S�8���W�����&��sx�U���u�:���e�����0B�9���A��A:w?�����A�{��n����7����R$whp�����r�r�PT�q[%Q����f�B%�`���.��d��<��d]1T�cUDv�&���������O/��d��
"32�A�+?V� �Zg6��n^�J6��2���!�J
�P�6�z�����Z1�D���e7�Z����YuS��������P~h�?�����*P~���O�.�Q�I���G*?)��^3�Or�V�C�I���
H�;�z��uT~�L�
k_��@t�}h��Bu�>��])��@������7;l�up�ZJO���5z�.���H��k�?V������������|�??������������.��a��7�Na�F�����d����rAP����a�^jt9?�p���n8���oR�$�B��	�A	r]n:�lCsY�������#O��{��sHCn�����_/��y�����W]����z�e�m�mN�~�Q���pUvf�s��AM�Vh3������#p�a��g�Zmk�K�)�)Q�D7�i�p(Z|q������h���=��>?�dG`>�z�.������p���ROS8�p��"��#�P���J8�d+��#?n���7~�.�*�������<�q���5G�T�����W���3��7_�[|���vd�����������u�(�����1P����<����k���0E8;�|*��w�|&�w�	���g��S�l�v�p�!���v������~��0�������9ny�r�M����<�^M�G��i�O/D���h�G>�<����Fy�r!�����"���(B��=]��E��O�.B���@�
���N"��Kec�SV��q���tc���_��5O��E�$��%%�L3,Q��+��(JPp��E�\��Q�>���D����V��(A���`"����p��(���z���S�iQ��2�%��Y+� J$������}C-�E	
>�Jww%{O���P%,F��O�?B��t<����A�H�W���>A�'���y���CV(������^��y�0diJ�ex�e��Usd��:�V��^s��d����������p�#K$�R��8��lj��{�z�b�m��k�q{|/��&E����0xa����z�D�8���A��h�a�Jq/*4�3����@{������V(��{{������+��+�s��j�����N�O�h���/���m>��W�������08.�L����%���h������Lh�Q,7����~}	M?�Q\<u���GZ�������
�>��H
_<�=?$c`Qv�|*�P1�(��B9��d�+�~a?rk������_f���=*�g���O���?����gw�~>����^h��C����cC���uxu��U���p��|2dC�JJ�d%� +J�����l���/L	8�P���
cF����kB+J��z��������7������k�����L�5�����\���5������%[`w�����T�>��ofw>h�|��.����7�p�e��)�z�5
Sz*|��0E���)�a�	
S|�d��0E�2S�C@��[��R��W�L�����Cmy�G�%���
�1��x��Tj��(����q������3+
Q	�2�������j�3��[m
*=x��1�����2=c��~�(��i�(@�X�
�D�BI�h�L������9�E1t����;u��Q01*=������q���|%�����u���K���������������G�����6���D��h�0��{p�(�&�,J�������r�O�x
���_�k��*��r?��_�D%�u�C%S��#�V��A����J�X���^�������P8��Y��*��C8"��������������(��'�r�Q1�B5�F4�Z�T�F4$��+�F|~�l0*f��g�MQ��*
.���PD�����T��J��D�AEW>UvtPQ���V�n����J4;��(Q���V��3�-&D������j�|oO�&d!��0�e!���N����K��d!���{��eD��|���X������Y�P<dU������Yl���R�US���E1�[G��e�[Vh$��A�����Kx�5*�py�v����Aa0�
plI������������#O�,Y@����(�<�8�v6�3$���x�����
y�y�H�Zs��uYWv�e�s�����J��s������a��9��0���^)��Q���O�W�b)��/���r�����2����U��mR�
� ed�R+�y\����_1W�o�����l��2��c�������bF~��}���gH�&���se��<�`x��B&�_�����5�q+��	Q��S�TD�,;��G jd��E����q��[��,jd�V��D
>S�zC���+�x����sK���d��^���Ud�u?�N���Pw}��������&ld+����8d�l�e�&k��^TK�X���}��Z��!���q���iY$����p���4�����J�~�A�S�Ai`���
J�lh�Y8<��;�,~�l�]e-���O��mw�� �J�
+Z���TE��a��f�t��w+�'�p���W{Q����w�������Ez_*�z����U�z]���z=t��#�h�?>8t�!9t���7��9��{�c���7F����w���?��������??�}���q�C$/���[�����w��96���
Mq��i��:i�/Uk��P�N��U�<�Z�>S-9��V;������7��c���V���|Yo����?:��ai�,����C����KuI��g�+���4���d��@�}�+n���� �P�z-�y`GL�v����X
���Ca]��>7�������r�o����2�E��5�����(�����0�u���Oe�r��0����m1z&|p@[�����$4�k���I��^�Z^9T�����ePwX�<;���*�����?r&Y�4w��_5�J���*�o��EWR�U���7��)3U�Z��J?S���k%���@
��J�K�A��\un�4��,�����J����u'��\?���$9��J�;��ZP
��7���#>l��\
U�`��%�b�N+�L��<z�����+���N)���sVy�N+�S����|pN+���eN�������[h�l�.��v��aVe�����3���uA	r����W�!��wB"r#�DD���D�y����)C.�a�2���V�0���7�������3�����i��sN�:��O�*J��BS8��/[�Z�2���D8�0���9JM<�%��D��*��h�?���h@����hH��JM|��G/�*��D��OC�������[��H��q�(�.�~nO��x
�E]i�����;�?���
�)��ZI�����\	Z���[���6%!�C��d>�QmJ�f���CB�Mg�l������.�M4(�J%
�����V�Q@kJ�����XIZSz�H�.�����;��Q<�������%�#�~�t����;]�������Wt�t��Z���P�����i��T~�7����;4�4�d
*A�w�5
*A.5�Ns��`�@%�YV����2%��r?V������%��������+y�JRz<��Jt��H���~�:��v��^R�N��n):�lpBGb���e*�H����8��UK���������P�x��!�����*��3�6T$��?�+��8�J�>�v4�T�N��o�OeY��q��T#�������`����#����� ������G,�A��,���7�����&eG���n��+9������� 
}O�A5u�=��9�
�=��/��0z�
N@�����*��{��+�xk�C���8���)�������^���
�TE�[�Jn�B	]T���**d+.��4Q!C��?u�B�,:E�nL�������]�o{�>F��B�G��������p�'��u~����|����@�Bs�^1���	.;���-����HSU�e��{���DY_?+�uA�n��d���=7��������MU�$
>UZ�@�H���'P���s��	
.}S���<P�V���U	U<����q���0A�<����YQ�
~�J�������R�oG���q[�vC+_>��\�����b��F�@u=7N���7��nAq#9����q�d(�|)��������&n�sK�?��$���w�4i���C���m;Y�S����]�	�n���\��8�����
��i���@���"��d�z��=��b"C�
�Mi8^qe���>�%�M,�4���a�J���}^@i ����Y��f7�����H�����������I������ke����}v��
(nx�U!�
���]��O
h���j��@{����z|(�;�=P���5A{����A��_)=V�=��>��zO����3�H�z���h��j����Eo�����{8t?����/x��/��_"���G��/��5W{�����k��J����G��e 
>3��P��27y?���������|�M�<���/�1(%+��CJ���\�j\dC�AV�V����\3RP�l����!��R}~��oF�U�_�^}�g�u���@	�T=~�����&��y�2�e�e���H����	@�-�0�����OE���=�k�a�@��;2l�!�k�O*Lh���0�0!��g�P�|%�#	��~\^9T����T.������}�Cp�
���_��U���_��8�����>+�T/�O��:k�y�$��L�k�/~����56�����������0�
*T���^?�*�q-�%@�
=���AWR��o���hs�	��X8����,��o�W�^�K�����/��>���u����,�����p�~>����^p`�B��;[�����?�:�����y����p�h��e�f�����%���
�E��+��d���!3rX���#��w���V���f�X�^��$�I#����eE����(��~R_s�%���G#����
��2��� JKt��((-Q�z�JKz"t���D#m����c(-��<����, -����Awc!�K��
�x��[�O�,y>�C|�$�E/���O�r�F�_�>�`HT�\��PD7�C(J_���C+jNEz���"z�V� %��0�����:_@("�3�[kXx�VU-�	�(��K�5d�����������q�;��w�/Yt��_���p�����3�G���#�����(yj�~������C>J�n����������0T�)'WQNXV|BKJ�;YK��8�uv,+I�gUGt��������2t��-R7�iS���\G�l�g?�������|��B�w9�H��o��]QEb������e���\����P
���?ABb�3e�r��2���x���G! ���pL��oxg�[�M���4�+:����P:���\��h\�h|����c>QL�B*�[�`��Wm���i/+�P����	�����v���0�D<�+��'d"~�>����N|_?���V'��R5N�:���x�C�_
������2��]�:����>�hu��+E+;��m�[�\��~?����4T����BwR3��A/�i��T��z���
�X�t5,��+G6g�Yw�u���T�G#�P�'� d4���V��!�e+rys}�w���������V��~������
��_����f{�����jN�k��?o��?���o%��k��y��q�������[�oNYD&�o��O��T��f�Qd(��*�(C����<e(=�#�Pz.j�^C���������i��
�vw\G��y?�|#��`����N6
a��4(,�IS�,BXH������@?��������IS/C�}i�C�s�cs�H�;��s�9����!�����a�\��n��t���;W��o$�M���H��se6Q���������������z�*�;�[����A�aDvG����1��U���dw4�����;��B��%Rh4vG�W���]�3U��`wI����<��(��4i��bw� ������K�F(v�$�G����@����[Q��.V�(�W]�!�5(����K"\�x>��~�p�p�}m����Mn��F�_X���f����zx�T����h�#���oEh�u4��m�:k���������+�:k� ��&
��4i�J#��4it^�&M1 ��h������z&4#�K�P������������T�Y�)��9�:���������%�(���u$�e57�]�\��������J���j���u$y<��@O&$yz.�� ���J����X��N y|������J;$��$g�7�A��I�$/M]�K�F'yi��W�4��� y4�a�+��$i�q�@���XP$�b;d�u����d�����������W��=
F�N�����e�g�1P���!��Y�6�2T��,���x�T}�#�QV���1��`t=����< �$ y���^|�����;Y���+Ip��e���y�H^�6�U8�~0��H�HO���r�|J�g��,m���y|!�����1��8����<�*���u���N��[Z��{�p���s�x�7��W\�b�����Y$����+ks�|!�_�[��������e�j�_�.
2�e��o$�������@O�K����������c�B��
���z��?kL��r`�|!��#k���Fk� k��P�kL�Fg�4i���o���Y#�
�1�F
�0'�^/��W�>�5�!�Y���Fz��k�:q0[�>���X��yzei��g����n��+��k���z��S�
�e�����_�8��L~U9 ��h�W��	�A��FH��&D��z!�d���H"�@
>S����+�Z
Y _��Ck� ��
�@s� �i#pW`�z��.�1��Z���XO�4��I�L�4
8 _
�'��s���z�^W�_s����k|�R��ek���u��C3nWhr�o��U��q��z9�t�w����0����KJ��`��T���@������hS���T�~fG�J0;
�R�G��%9#��eIS-Vf�&���h���]�4E
��&�0���L(AfG������.I��W0;�����o7;�d^g_qS��������������:q��/��KT�C��Y�!�^�1Z��Zx��hz4��@�}z"�c!�#�s��y��e��������X+�b��(������9x_�3:�K�F���!����h�xx_�4Eh�}4i�V&�}I���+�����}��_K�4��%�}[��x}��[���������y��/�����W\�	�F7Yq9Q���\���09��}��/���w�B���0���6]�2��Pm��A���?A�x���c^�w\�������"��{r�]�4r��p����4@�x��Q�����
��E�~���/<W���w�
��$!;�Tz�q������q;Q/�z�e�y��d/[�^��!��|<u��#x����)_S
/��f�����yq'	S���!������p��@�����&3�	����F5�7���1���@�G>��4�SO�_���,r���fI�����I����<Y0O�*t�F�4u;d�y���l`�I�'�����eA�JoC���B��>��1Gz��N0�X4i0C.��&
�X�E�`����l�������������1��\K�
�I$����s�\�\X5�;�V0�w4�3���K�`������;e�w��A~�$M�8�K�F.�s'
�;�4��/��4 ��tdxI�xtA
�TH0�$m��)�����ad}����%���^s��	r�z���8�K��Ql����b;_�#;��]����
�#��v]m*�c������G��JEp<��R��?�y�._)�v�����9^�4r�n�4���9i������C"����1��%iS�?F�7���#���������������	X���KVl`x	�����/A6���(���B�j�����������y����|�R���`i�`���8�6��1hS/��T������$���2�:�����|o�M�|����������)>����I#��`|Y��%e`||)��='#�����/;�T��qu��c��3w|/C.3����kn��<�:��V����+._�;[������1���:.n���`�O�6�zZ�i	>��>!�tp������+��
(�*��Y�)^�6ri^�6���;m����pG��@��H�h�]��/�&+�xI�8|��sJwj��L��+n$/AD��S�z�6�X��h���t�%����������������y>o6_�����@�����v�9q���
����mf�j����	/����sh�.�)�6��c��g]|��^������C�G������x#3M��u��L	���|;�N�����^����^A�J��:O%���\��i
����*K�����~<�S#�Y�C�zf�d�T�Y�`+�-��R\�	���y�p��<�dr��#�3�z)`%��ARi���s�7�w��a�
�;v�������x�!d!11@���!$�s�� }�����|�^_��t�p`���>������pA�6H��|��;VBW]7A����i
	�HSH��
HS��D�=���w��dg�'��Q���d)O�v���"��j�&�OP��p� �;Y�p�^sP�Y�)�#�]��8�~�Y�t?�F/�!"�������������*��@	���#��\(`C2H����e}��+k������H)���M�eS���4��t��HH����0M'�]�������@����<F��z"�)Fb8�B:1LR��r 
x��1A�fG�q�l�SL��a#��	��L���	��`0�����V��y�l�*������G�9�Ed����F��z.L��0?-8�+4?u���{�7%��;�<j$K!�����yp�;��y:��3��tz���*�i�N���p�,�������d��N7n�y,���f�z���c����kn�������Gj�� v1@
]��AH��Y�����![��`�W
���A���)�B�'��PU^8�;� 
��z8O'Yt�2@�@��>��S���N���T�����?����e0@�-���!\�(�����<����/A��3d�sG#��9���x{�m._�I�6���:_�M�p�N�)�i����o)9d�W*��_���X���z.��G~I�g�C���#]	�%}�3E�~I�M%��lB~��t24���Xn�y:	��/i:	e��/����!����'����������{�h������ad�����^��8f�\�e����X�Yq0L���a&����q�����O�	&S�\n,����B�B�h��	��j^�5d�s��FH���%j��XOk`~|�K��Q������%T�[��M�x&sheq�=�6��@l�@?lq����h��/N��%����"���KA�E����XBM��k
���*�`{	��]b_s(�	��F����{	�>�$C.	��h�Fc|W�<�Y�h�L&���U��G�G���	i��
�>H��\��B�G��B$���1.�hT��_.��yI��%�/��)!LS����������#��u(M!��(����2en?��-�M8�Rp��G^��m����{����F�h���~�F�d�K�
�n��{�8G�v���a�	��k+M�c��h*��"�	�r��P��c��2H`�P�����xO�7`����?.��v�4��r�F�T��v�_s]������,��^(.��r��0�)(`�-�������wx��})�,�fA��_�j�}�I��~��Zv|����2|�u,��!v]U�{�p��(���B G�xMg�uw���6�qlE���@��bz<0y��bx EW�q�R�����<0��rKI��4�x`�?����T���OU�H�G�l�<��{*���Gv�C���L�GR����Mm0��^�����R�&k��Jrhy��"
<�}���&��/�����r�����~�������^����jh0a���-���rW�T�`{zL8���${�����e����1������9C�.��vt�G�]D/��M�HAi|�N���K�=
J��1y9��z�n�;�n^�O��J�8�+��������AE��AEi����g�I�f� ��Y�?y�u,����:���>���,��;����X�n8�" ��"�V�.z\�`KF�(K�xO��?��s��!E_H���M���%��[d�4�&4�	i�L=��`{zR���K{=Y��[�Q���d�;�5g�Y�<���@t�J���t���M\O'�r#r-���a����6�^5��Z.X��:���>�$�����4A��LSl$��fd�=$��ORh�E
�<K�) E�� R��r��0���t�?�
�47�4L7�{��) ��Q@��@^{0��C�J���o�)�R�$0�.kI@��A��@�eL �nh �	��I�C�?����Fq�}���4+7]��g����������=��{.��")d�]�HP��xO�j �}��k��0�!�Gp��TBR��]ot@R���)�@
y��Gq )d��H!�G�r�?��$���Z�9���D�rE���[j��.�e4/7���C��
2am�	3�2�
�h�u0�� �c�c��7�F���V��=���P&;�"�����a��u�"����d��(2D�>�z���"���a1�y�>"��5a=�H���l���]V�!�'9�4��g�������p�n"E_
��7��m4n���!���!�?�`q�C�
����2���@��i�c�6\$���!�7�~s���o�������������o�������������9\o[��f�����������n6��N+��u�b�3����e�.��%���/c{,�`O�:�K�����=�L�-�# K��V,�z,9y�BS9�d��R8!�dk�l����H�82�������==�Lc�]G���}�������1�%�
�yd�+O�wva��n����zmxj�����^�f��z��zu�i8���_����'�(�n��l���A�i������{���A�8�c~�3I:u�����h���w���xO�a)��(������6�c~}! �K�����/��"_E��f�:�o({t�GmA�G�g���K�f�������������e��g�����
*i�v�r]���FI!�A��@�=���d��R���"
t���L`��p���#���}��A\��E2��?��\$���f�C����E[��2��������Rw�A��R �Y�T)[�Ao� tg�A�=uA
� ����d�G�C1���S���`�=�x> �z�/D@.S�F����1??���#|�/��s������,�����p��$8X.K�P5���e����`�5_p�����(v�D��?��3�k����c{��G��h���Q������/A_Z��,���������4{�/���3�?s��%pvZ)�e.#�3�r�����i�}-<S�I���N���C�
�
�T�,u{�V�A����#48g��k`�������=xx��[W0P�#���`��)��@�OK75��^a��F����#�4�S���G)���X����'�H�ML��@���#����T���GiLl�����L��gy��`�^��e1;�t�/y����p���B��W
0�vP@74P@����2D@
\�88��d��}����j����V��0`�����
��V���W�V�O�*i%�V<
{����nw����5S��{�h:H+)��N���@+)�Z��DZ�$O�he�=U�
�2����a��K���j���=����#���3Sv�<�&�=ZI�W
i]1
��+�����"v��I0��0Q�u��b��E?���^�����t	�&}�ut�W����7�wa���c�i8�q>~{��`O��'��^������{wJc�����R�����������%�
)�Z�dDV�����0���1����aO����
i����5���� '���V�=NH���Yf�&�9�p���rpB�<w�f���I0S�3h���Q�O�qv�3S`C�7���7o��@-�%���B������>�=�
�>������
eR	p>��r�	�/{�
����WJ�4p�,yt��e�>���=���D������)����x��x���z��/��|}-\�������p��_u�/�������K�������F}.n��A���p��
3h�(���-�\�Ed�
0���
��P&�c�4�K�1��`S�l��[y���`�4��C=6H�WJ�$��$yl0�����l0���Jl�`�@ke��Am�P� ��D����A���6�G:s����
Rp�<�����M�C�\0<4�,%u��D���K�-����9-��m��M�� 
��=�G�m���zV/9�+`��� ��3�}�G)�B�
���%������G����M�x[ =��}����s��m����nb�#���m��f�c���-��@��&�u;� �	���8A���������&��i�C<��?/�{����jj��O��-��0P���%�7#�$�J�|�\��pC�#�4���-6j���s��=�ez���/M����
�2I}��7{z���==j�f�nk������#h�H-��Q���G��J"����/�[r��\!iA-h���:����:�%���E-P�d��9�v��2���{K��7�4a��*ClY��H����V������\=a���&,R�����c}���"���+��hM��K���+����c���;���1�,�hB.�?���4���K�W���t�0���r�	t��:�_��YvC�s����8;\'h��$�v��Q`����}��ja~��� �c�������y��x����v�*y��T�W���W&�����+�}Y����u��2��\��
��gOq�����������G�(���eg����/���N�/�A�����b\�Z�:�9p�L6���l�(������t���)~v�`}�d5��dk�n<�'<��2���Z�	����Hx��v�~<��vm���������/�b~$�q��d���~Y�T����==��f�~��c��]����IR���O��������^��O��������y�I2h���(`]g�A�z�_����0t�#
0�.KH�o`�`=����2dWG1����P�2p��c���~�R��i�	G_*w�H)�����Z��G���{���1�@���r�H`�?��t�?J��e}*x��H`�?���	L�����o~l�40�v�@;t���Y_��	��4��4wtH�a�bl�s��z���q��~����������n6��ny*�UX�C��
�.gQ(w� ]��B�U�=�h��*���z�%�^�������a��R�_=�>����U���'��F���k�.��!qMr�j��?7�F�]�7=�J�z	�����sy��R����5����
}���^��J�T��S3�C.;�R�CG���(h��r�t�u�d�	t����09%�6�d��X�3�c�6��d�A������7LHa���5�C�\����	���(*?$��wZm�=~H���$���{��"?|�����_��t�<�D��}q�����$�����\�[�y.	���i.��z���� �"?��$���I��D��=2����<;����<
�\!VA���t�����	��&�������X�:B�^5B�����!<nm�S��������cO���	�Dh�DN����7���U�Hw�0�/���|���f�9���*z�@��P�<��+
����������S�*��GJ<������OR����O�TA����~<0���'DAt�iv�f3x&f��F��L0����C��
�`m`�nh�s<��29����c=H<)��=H�'��b����i�x �~����c���_��6�4h�|�(>�=N��HQ�&�Te��	�\�T'LsI/{��T��z���K=NH����T}���7U�&�S�c{�0��6:A�%�����?�:'l��n�`�I0��]0��P�h_50B��F��Fh��1��[��0X#$���B�c�{"��=F�]W����v�3��b��� }���c���te2�f4�L
X`�?��a�?�*?`�4��Gd�4L� }�BL�&�S�w���d��M,z,��/��U�)����X }��J�P�5��������c�p?�A�E��X��}5��XWW}���6��<����O��0x�NSa�r�
����%A�XZ�]Rl�#�$��{g�=*yz��>I�]�e�,���=vI������2AW8�f4���<��b_"�.i����.i�x������M��v��=���vO�5G_��xM��;�� p�g��H�������e��lE4������
���e�L��v���
CU�����( ��t�}*$�S�a�G	�\��=
H��BM�&��3S��/$�	��/q) ������[i�
H�G�7R@�?�NA
H��B��')�G�1y����G���1�&�S��D���P|�@�;�����R_s�����	�0�y�!:J��(`���f�FO�7LWa��6P@��r��������E�����=R@�$�{Z������Y@
����n���%o����A
����c����?3�3��I&( ����������3��Y�,��)`�?����=pp��bm�e���
���$0�6�2g�h�u�@����c�����[F�0���F�	�{�O�Kd�S����	�R��c��I
w���g��sd�}.
�&�Gp��1�$�>�<t?�?� d`�4��[=&H�J�:2A�$�td��Y>����2A��z�zL0A_:zN8�bYL���@�U��f``�I0R�X`m�5����hH���2m��z�����c�[����@h�H��W���2��XT���g9�+�H���>�,��/�d�I��='y��n4[`��i��+�@�?�F�,�>�zgE�&���/�c�}q�������Y����Rp�������P�m]L�a�8��X�X��:k�h�>��?/�{��-#��7�;��='Z�9a���C��)���%��Qd�{*����%�~���7�I
oGd���F"���3e5�K��P�����{f������pl�3�%��E�%����%��#
��@��^�Y�����L��������{4���x��&�Cc���^�`�I0��g`�	�a��}��4C7x��a
��#H�r��I$�[�E�2l��!�^(
���x?�����F�gY0�rt�� G_�9������.�n����x[)�@
�3H(�
�gP�*8( ����b�������F
����P�xY�cZtq�����y{�P��������|0KTa$��_�'4�1��7�� f���� ?f���{���:�; Aw��(@	�gBCv�$s��R�#�[�?�D���G�OR�lC��<��T� R�������?���~�,��!]����aKz/�C�?3�+
�OK2����=L����:���E!���2��[��ns��Q2h���}�@���@;H�; @h	4+����t�� ���_�{*��&�1A��r�f����� }�B2A�,'BMz�	��m�'��.s�.��"L�G�+���82A�?���L����` L��O�A���g�1���gQ��E&���dN���e������n����%���5�Q2htCL�
��vh`����c����@a����@��tU�X ��l��i�=�{!��$�k��Y`�,��8d�}!L9���]�dFH�na������4t�B�?�?�GH�����?K�����.(v�)�����/���.�������)L�lhO����c���!
���c�v����:�7�����j��?���?�����J������Qnv	~�49^6?�������o��r�b�3�z��v�&���M���Pi�at�U'��fY(���Oc�E�v�
!��1���ayU���%�4�>|����������C9+�����8���R)���8�>S��N��0�J�����L���;\A�J��i7x�(�_��0r���p}����%c����[8���"�n?�7����F������~7xfO�IF�����;����*|G���s�>^aw���}�C�������~��@�
����������:����m��^_��� p�4�r��X�7����O�7=�������j,���2]���u,�����bY��m������������
��EQ0����9���(vNFW\m�E�n��(
Y.�Cj�AQ`�B&(
<���(
{���E�a+U������9}���)=�aJ\	���2����*s76o:_Q]p#g������Eu!C������=cQ]���ur�.dglq��.0��������Eu����zJT�3��

������+���������B�<�:�����zA[�+�;�R����e�<}��������S�O�ZH�
�(�����Cn���t�,��Ot��.Y����P�kU���,���c��,X����p�����I�Q���,$���`Fe!�kr�^��,$�z�C��n�)Y��Fe�Fce�U`�6e�`/�ofT^��������LQvPY��k����,X����`F�PO������Br���S�3��,0b�[���jm�n���
��=e�`/���a{���^�s��a{/d�}�������7=�a���GTpp�,J2h�4���U��@�PY}�.�l�e�Tz����/c����������g���|��m��n��7Pe0_���u)`?���uP���
C���
�_�ob�`=2�d�X�`��!6�tSX
���� �d�l�h���(3�����2�~��[`Qfx��UfX�d��2`e��RlnPf��=���<��&��z��d��2������[m����$3$gld�$������cg��������C�
j
}��5��f`_	u�($��
Ds��S(���|���<�
��,�@��"���D��[D�����/4��2�d����;@b���!	����r���e���z$/0H	�.1$����$�l�r���$�,�U��@��h�M=4�?T��B������e�>W�tPV��K���'+X����`F�J��`FY�{����������\��
�s�'+$���/"=W��(+�su��^����z�z�z������fB�^OiH����@�B���� 0� $������U�{�B\��B�$���!�4�`��J����2��zQ@����6�3x���`�^#�p�2x�:�y�����l��������M�UE�=#)�E���z��������^d�gd�\,@�� {<#��0�zA��1�zA�1��.�^��2
$^�ewSW���L��)}��*�c��d���3��d$��	��J����)	���r�������\T2�3�P A�X��`?v��'}�
$hL>���-(�T��D�"y�K��#d�$0��z�x �B�\$k�wsDMDm���A��.��t}��el�{#v�Z5VF$���;�al���.B���Xww�'��6��������p������
�"*��CT��eQ!�K"2�������
�n���=%�3��G�>E�=U�
��^(v��vu�
=tu�a��C�+��G4_������7�p�z��I��B��k����Q�����Em�!��-��-�G����Z�r~�����e�h}!�;nF���!�����-�^�\h5������,�I����3+��a7��� ��2���`�
���"�6TB�W��=
���_s]W8�=BC-�;�-�R�%�em��z���(������B�`�`�!�����-d��C����@�a��40���Gm�zH[�9��fJmj}����lO[0#'�I[���=m�{���`=j{�A�t`dG�A[`\��-����0������vw������a��^K35AYHN�O�x���R4��u����
���jx8-�uW�5���AW�����,����@������G��������Q������pr�C����q��`��P�0���y���v��
endstream
endobj
31
0
obj
50034
endobj
32
0
obj
[
]
endobj
33
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
34
0
R
/Resources
35
0
R
/Annots
37
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
34
0
obj
<<
/Filter
/FlateDecode
/Length
36
0
R
>>
stream
x���K�����W��3$���`5j����l��/����[j��`��k��1F��|p��E��g��2�$Gg2�����u�������C�����������W���?|����!�h�����`�����Y~����g��q���+���^�?�_���������?�+�F�G��L��'@��������_�1�������)}��o�����������������������`�E���q�A�!�K������8����q���7�=h~^���;!�|���_��8a���4�%'��E>���C��"�	N�����B��;��,�1�k>;,B�����{�!ei�j�2���C��"�	N�����J��;��,�1�k>;,B�����{�o��}�7�	���8��&�����o�{�|�!�8���������',8}����C�/i�j�2���C��"�	N������)�wB���q���Oi���q�A�!��4�	y;> �5�}I������{�o�����,d��}I>��pXq���7�=h>�K�^x�����C�d8���o�{�|Q�^���p\�!�a���o�{�|Y�^���8��������{������~|�k>�[�^Xp����7�z�p�	�����8&�����o�{�|A�^x�����C��"�	N���������p\�!�a���o�{�|E�^H��8��������{�oB8d8�Y�Sd|�	8��8a���4�)�/��8��Nxa���4B�������|A�^Xp������d8��������',8}����C(2�B���q��Pd8���o�{�|�!�'X�2�"�pL�a-�	+N�����Nx����q��p�p�N�������p�����C��"�	N���������p\�!�a���o�{�|�����p\�!�2����7�=h�	�%�'X�2�[�����Z�V��q�A�!\2��k?>�5�%�/,8}����C�2������!�p�N���������p\�!�a���o�{�|�����p\�!�2����7�=h�	�%�'X�2�[�����Z�V��q�A�!\2��k?>�5�%�/,8}����CH2��������',8}����C(2�B���q��`�E���q�A�M(��`!�|���ok!NXq�����p�p��~|�k>�S�^Xp�����d8��s?>�5B�����q�A�!$x!�����CH2����7�=h>�"�/����|vX�8a���4������,d��q\�M�a-�	+N�����Nx����q��p�p�N�������p�����C2����7�=h>�,�/����|vX�8a���4�-�/����|vX�8a���4�
����N@�2���W���!NXr�����p]��^��9���K�q���7�=h>���N���r\�!� �w���7�=h>���N���9��r��;a���4����N���9����q���7�=h�	_����N��e>�q�7��'�8}����C������v|@�k>��H>NXp�����oi������|���;a���4B9��N���9����q���7�=h�	_����N��e>�q�7��'�8}����C8e|��c;> �5�)�/,8}����C2������!�p�N���������p\�!$xa���4B����~|�k>�"�/,8}�����p2p��,�)2>��B�����{���������|������{�!�p��~|�k>� �/,8}����CH2�B���q���d8���o�{�|�����p\�!�a���o�{�|�K�N��e>�q�7��'�8}����C�d8���~|�k>�K�^Xp�����e8��k?>�5B�����q�A�!dx!�����C�2����7�=h>�[�^���8��nxa���4������,d��-�pL�a-�	+N�����.x�����������q�A�!Dx����q��e8���o�{�|Y�^���8��������{�oB:d8�Y��e|�	8��8a���4�)�/��8����q���7�=h>� �/���8��������{�!�p�a?>�5B���V�����Q�������~���� 
E�N�����U���,d�O���C�a-�	+N�����&�b�^8���7���O��',8}������`�p�}�o��7�B�����7�=j�	I�a��}��������q�Q�M(b�^Hs������P�`�����{��_���u��,�)��S�>�B�����{��o�%��������}�)�a���o�{�|����o��{��S�b�^Xp���G�7!K��8���qo�|
Y
p/,8}�����p�p�y?>0�k>�[�^Xp���G�������,d��-����Z�V��q�Q�M�d8���~|`�|
vX�8a���5��(�/\���q\�)Dxa���5��,�/����8����q���7�=j�	��������S�e8���o�{���pg?pB���2>� x���%�o�{�|d��pn����S����7�=j�	��@X�k�7���OA �u���G�7A �u
���}�)��a�Nc�����Ux��^8���{��Cx��^Xq���G�7A �u
���}�)�������J:/���N����)�1����K��^��s��������h���_���=�,��N���bL�1k��s����d��?�r^����q��+}��N/{��M�[
!N��_��'�����%\��
�sO�h���'�����}a���
���>|����l-��/�(B� �3]��ot�������h�@�'L�������7��%��m��'t���S��x}�'�t9�j�g��Ay"��$���c���]R���wp
t�8�sm��W��?��x����u�,�t:�	3�	�������:b���t}��H�'��s��R���:^�A����q�O���r��of��Y�0KD�&������!�S��t*`�8�v��cJ:��'A��^t�Iz����M�D;�g�����+��yC��B�0���o�Vh�y���������f1/1�QgtNhl_eC�B� lv���p�!��v�4��)�_����wBc��*P��){��l����>���E�-�	�|%��)J��;�q�f���\p,`�D�v��)m#���j�F��5�4q"��u��4m���f��e������6�V���
�N�'Bn�"MW����
�A����q��D�	�0�%���Y� �5^\:[e��*%N���?��3x���XqBo����������K���=�o���+����/
;J�qB����7T�����W14ETd��4�!N@�e��<����hz�E�!}B����&	v9�]$��e_���8��i�(��p>!N��������S�}�S��@��fn��	q��|O�
���W~�W���#���7FW���
Q�I��!N���/b	r:���t-�	J>�#y����d:"J�S@�
�D�U��8!'��B�0��K;�$a�$�p
=��3�0���U0-�XN�C����q����Y�R��!Nx|�il���%��

"�CA���4>J���:+:fAG���8a����E��i���8�5>�5Y��3B� ���h��*��g�	�X���P����f�r
�H�q�bEezX���Py9��8�O��
�����
����6�?Y�~z�ib�OC�C�/'y"�>5y�A�?��P~IOF�$���7Ff�t<�)3�	���u)�t;�`���=���2�� ��wh�8����q3��$���������<�Y%��Pv�8zr����/�73t���Hq��SM?��Z_�� �����SM;��m�Q�C���������K�C�U�B
!NhV��f�xZ%����1 qBG.������Z"ur9�\$E�8�'o���*�6��+�B���������
��yl6�'��Z����$C���y"������6������'��n���<O}�q�ONvco�LcBI���O��W��Y�0K����s����S��$�AE %N��v��'���`�E�~��h26g��?�(���� ����>�O�i�QE��q�{[��s|iD(��`�a"�	��"�]i��i����J�Yeb@�����4>c�r
�H�qB��������e*�>��(�B���wW�&ch�P��z���8�G?~OI8���J����'�la���*�q"D���9���a<���;�N}�q�������g*���!���0EO�e��A����qB��R�rIB.I@���>6��H��H*)q"��6����y��v��`g�c�'�7�j��>�xI�����{"��2_���/Cp�|�yP��L7W?��(�����'��k|U����*�.h��	Y�z���o�*�w���F��r9�\$E�8�'�o���=��iEV���8�G��3M��$�`��;O���c:M�J�^��D�B����2�t<�y3�	S8�V�w�dl��U�)�xOa?�'��F(�B�B���o���m�]��K��8A�������+�t*�*q"LO�`&U�8F��� !N�e�<T��1!��%=
H��=�y����(�F������'���n�(��]��$4�u�o�,�	G�%��c|g���z;!��`�r
��B�p�v���)��BQGag�*�QC��'�{���dX�����8A��w�����[Y��2[���y�4f�a7v����(q�����X���!����'z���{ZPe��P�����XP��0pBN�;2B� �u?,���$��$�p�����n*���R�����:�4�d�<&����u�i&�$�<�T)�y,�	?�W�)��Y�Q��'����g��Q?����#4U���|�D8�;��w��}���Y�`�����+��w��&���W�v6f�r
�HzqB���1��
��U0p,�	�DO^����
�3�	A��w�n��_#�L�@����������6C���������q:�N}�q�=���V��8�B���=�]�����0C�����}��1��$������Q��We��P�A�8��n���f�,�
����e��wI�m��'�8aymHh���B�0��&_��{���0<�zB|��
�	�����fa��8���~���������.�����'t����0#��� qB�4y���c@��m������5vfh8��!	!N���Y�4�������#�	��6�]
�t;�y3�	s6~�m�����ACC)��Ao~j:^B-I���cq��.?�&�dP`�8��<�S�,\���',��	f����@����f&�����O@AR����z ��{��k���_��+L��t-O�����mq����r
�#!�	=z���h���L_@]d!N����|��74|��&	!N���������l��FQ�5B� ��������_W-�3�L)=!N�&��
��!��'�'���k����1�V9��0�zg�� ��ws�8���w��NI�)I�� �E�V�C��P���8��D�S��$P�t%�8�S������>�N�'<���f���%1�8a~�����R�a�	0@qB
yt�6cdX
�^�8�'o����T6MB��8�a/�V�-����C �	}�;'��T4����(!N���NHg���Ae C.�8����luR�!��g�'H��w���T6}��)�xO���t�����C����e���-�,I�%	"\�����Ke��P�A�8�7��'G�1p���8q� ���<���PI�B��C���,�(�!�	�9�V����uS����KV�p��L2|�*��J�*RC��R�0����t��,�	�~:%hz�� ��A�W���&h�*�e!N�n�QZ\E���r�-�	���Yo,��nLE��oq������t<��#�	s�|�+�i���N��{,���8O�3t�}'G�4��WG�;��$�����0z��3.����(��0J�2��x�.fX��A��4(]E�t/q�B�"�.g���%q�����nx��r�ATcU���2q��/�0�	@��56��V���8�a�^\�/�I.���$�'����-A���'����b:����7�Xq��"�f���*��g`���'�	?����j1��q��=2�Wp:����7��rV����M�C!v
*��_���JRCj��5C�����x�,�6��5m��"�o��#�	������`B"�a��G��h4���Q�C�z��+���I���7>BkMQV����Za�M���dX�hwi��/H.���d�'t��S�L�M5�7N#�n
$q���f����,�A�	vX�8�?�O_YM��6@B�z��+:���a��` �8a����N��S�2C�0��t[���;3��=����@
A����q��7."�y�S�6\�g�Y�T����AH�a@�@�t":���B�0����"�j��'����
��Q;�����B��z�qB�~.=X��&b[�fl�o@�����D$��"��)�"9"�	��v�a��-m�A�e!N�����7p���M0B����E���X��:#�	}�O}(����oS0B�0��8N}�q�<�>������SP���K��Of�}�f��u��^�Y�0KD�&��~ih<���8�_A������Ta�f�S��',����&����%�8��9�0�ct����=5ho���Gh���3����4>?���.�Hi�M��H����l�)����:O���.�%B����}0�P��8�/�����B�`�8a
��nN�������,s�U<��'�-�e�`9���!N�O,�T���32�N�� (��'o�N��d��C���E'���%��Z�0�5�=x�*�Hg���"D�8��m�Z}MV� :K�B����-��d��!�������Ucn�B�QRD��k��l-����F����}!VC�`!����sBC����I5�	���uDW3t9]$IqB�����WIZZ���Pw��'L���C��@��]�,�	���Yp��~Q.��8a���o���P�I�'.��C�Wj:������u5�L� ��S�r��#�!9�!N�i�j���%	�$a�k,����2���	Q���86���R�t+�'����VI��h�(��Y�~|�it�Y�Q�'h�-Cx���:���+<�Q�U��~��5�*~�4]�w�MG���n��'B��������lY��d�S�E�D���_n`�?�7�W��E�dAH�9��wk�i%��
n���&B_<���L�U�Q�3B��'�x���?D�&�!N����$K��!��'�'�������
G��)������iA����q����/�,I�%	"\a�\��*}eZH�az�W=���oA���y"�]�����
MzB��$]�:���%=�8�G?k�!���������Z�+��8��>V��8��D�C���y"�����7��)�"Y"�	=y7�����0D#C�v���������63��~M��p7�a�F�����<��wM�Ze�
/i�����#_�)It:��t��A��
L8�1!�� �>�&�����'����F��%	�$!�k",{��
4(n'���x��f�U�
x��^��y�	4& �=�W��O%8fG�
!N���E�an�O��CUV��m!NH�����F=?�����i
�����Yid����c�������.�&B���a�%����S_��?��hh �� $q���Y`�ghX��M����D�����U���VF��qB�Y������u�ti�8��I6�f�t<�I2�	�~��D#�Q����D��;u4�f�����'x�f�IRKjI	�D�^�]�hp��EY.0B��>��l��"��q���.���Y�Q�1B�0{^~� ��9G�~���[TAM����!N���_2�o*��d�I��!NP�����o�]NaI�B����yIs���� ��!N����P�a@�X��9|0���R�4+��\Yq����8mo��^X�����!������Q<]���h��E�4��������:��0Jx5����^�'�O��JfI�,I��<��)`�3�	D�8��[�U`f�K&a!NX���7�Iz
e��$q���J3f������8a��z�p|>Mo�P���8��>M�}��d�� &p'�<��%����f����>�����������	��'�����hkS��ay�6��p_A.��7� �����r�������8�����n�'����H��t5��1�	���}'n�
�)�xO��9m��8!'��!N��e�xu�Z�.I�%	*\az�����f%�YU�D�u55��0g�N��w�?�M�d�J+�RqBO~>����%K�8a
NL���5,hv����=�-�	�l9�?�Lh���<&p��<z���LG3r9�\$G�8A�^I?�eJ�x����,�	
y1�l����:c��}��� ���h[�Cc�b.��D��V]����"J�,B������#��j��c�Wn\Q���6����F�'��"�fq���C�Q���-���	8��MV�&��\�#5������D�S�o�I3�p�
���qB���+1t����&B������`%���Gh�[[[�B�|��"���<�%�
���v�={?��v"+�^$O�8��������B( C�������9�0Y�8�A������ Y$�8�G�'#�vd];c!�	r��:�F#�����$��>��d��nd�!�������r/a� ��we�8�w��9�Z�PKH�&�����l����BT�A��f5PZ����1��;O��sc�Z�'+��	�tOyn��A���Br�����9�6�	�.�AD�S�G!NH�������n�H
��*��'t����f��]NAI!N�s����6[ ���'�B�����2G8l��&p��k"���L�\e���r���i��)v���j)���S0B���s����!����'L��-K�9�f:��� �����K�!<�]�!N���[J:\�.I�%	)\��Iy��i�(���J�
{0J|�Gj�n�;��� '{���hK����A*�a��F]c���Y�Q�D�z�f�==PVq��mF��]C�`!Oxc����&UC����4x�,�BN��,�	������=��w��<Y�d�!N�������-dW(q�������(��e!N�K;7g��,�b����8AO��QM��U�6�Hq�O�v�7��
���fq��n6�(�KvI�
�X]�������dUBJ����"��|9�=!N�������*��@V�������YS��(Z�$���1���������6��'��m�h���i*�^d��	��;O���~��w�ZN�I!N��}�U��&MAP����c��q�C�1�[|_�A������Ym��"�	=���Fn���td�8�'?�&��!��'�'z�z�	�� T&A ��}����!�$����1�	_����LE��P�!�8�y��h���Y�4n��'��Yx�6����b��P���I�Dx��h2F�Y�Q�C��tK�6��&�G��-�u�	���*`�oq��p��_l58��
&p��<�:���)�p�$�'4�����9�I��,�	��N�X�_�
2�	�L���3K3���=Q� B�0�7�_i#�<�����'�W��kC��!��'�'�/��{�������D�_NQ�� ��wV�8AN�n�W���KvI�
�Dx|fiU��)�	�	�a���?g���hb����������l%���!��{"<}�7�d���%5�8��7+)|����4U������}���m�|���2cC�������Y��Vt9m��'����J@��w*M���k���B��5�[�_�O��{A��w��
��<���.V�4��2��,�8ay�Gs�IM�PS�2C����t�	��=CC)�A� 8!'���!N�'v<��hI-I��?���0����[���0���?���;A��y"����44��
�tO���s��1<J�q���1�p	��|c����&p��<r��������F!Nh8m_j�e��:;326�N��8Ar�?�i-F����~M�>��'�t����X���"�	>����4��Z-������>���I�c�C����!N���]MfpZ*�SX���[�1�� ��wc�8A����O{1tI�.IH��O���W*��������0���
���� p'�<z�����U*���*HzB�������Q���d�'��l7���W_��(�>B��5�	��;`�YE����I5�	��X&��f�r
�H������`3I�Y���V��?�AAH5�	����������;Sh�*d!N������4A+��\kq��7�0��Cn�u�tpq�����G�3x:�����?^�lZ!��SP�?N��g��n�'h��7]��KR���v��Du:`%�#Q#�8�g|�+�Yz�	@Y�~|���N�D�$]�B���GK���Y�Q�'���5N��V��J�gU�����d]�f���@+�l���M&p��<z�v�t��/�����'H�����M�D��d!N��=���vhh��M�F��D��7
8
���(�!N���;�����t��(���#�	
Z�,Z�q�!����'gQ���/7����H�'����]IjB
}7f����{�K�3tI�.IH����707~W�tD�nEP%N�){��Y�nq�'��G�`-K���(���!�	��-76'3faFI!N��-�<��<]u�	� 
�*`�sq�5]��/sH��`��O&p��<z0�u����_u����']NAI!N��w]��8[W&��-�B���W?�4�fP��AM����D�3�~�@o�l����Q.4B��C6��.�@�C�&�!N��=�Cp�!����',/�_VL���S��rm���%���.�'����tI�.IH����^ZTZ
�"�'��!9�I���E�3t���'��Y��Z���P�IC��B/'������$�'����m���Gh���[�b�T��������*DY�z�n������Bv�4�aoj5��,�4n���=������*��E�a���
PqB�0.��QH�<�����
�+@!�	��6�9=NVX��P0B���j������+$�>i�8a��G��7�'���
�xO��=�	�����'L:���I��5V.I8�����E��%V���=��D����]�~'k����O!�	�>��H���d���=��vp��)���FAsB�TlEn!N��O�G���l��U)&p�<z�vZ���)�"i"�	
�����T�EQ��Z�$��#�6ch��M����D�K��
���DV�E��qB_/�C��!��P%I�F�����a:�Q�!����'��S�&�C�AUt�a�=|v�)�A����q�"7�qJNIr�pM���4o��y����"��^�
������{���g�<��y�S�`k6�H�30p�=~�fmv����#B� l�I\����u�w��%������k�,�����d��M ��8A���u�C
LV1!�H��E�fJ��d�M ��8�e?�J*OV0�B�0�x8��n&��mH�M�`��d����Z���i�-���v�sD�_���d�PM $�cA2�op����C����Q��I.��$�����0����=E��P�I!���0��v�x�fX������G����e�B�=$��z�49Y*��(Z��w?����o�wk�����
�-�	5�}A7^�W��@��L�V�y"���'k���{"��r�����/��pND��e!Nh���|3&��&p�k"L��D��lZ��|Q.3B��0_�����!�.��q�g�L!4M}�q�����%4�
��;���0�x=�������'�)?�JtI�.IH��?����p:�UHY.5B���l�o*����H�1B�����7�Y�Q:3B���'��9���_��PU[|[������*���R��-iG����.�'B������%M����-�	
�Y�D*�A�4!NxL�_8��>�DP��>�1Y��8�����|���&$�>_�8�'o����/���
�xO9�����	A8���q�����-|���&d�$�pM����y���&�B�~�q"2]o�Cj�>y�y"��}R����nBD�'��kJ��M���B�0�W������t�FQT;w[�b��8�����n����pcC���y"t����6�.�����'L��S����09CC��������?!��6���"~M�������32��}����Ot46/�"��'L��h�
���t��f�����`���	�xO��UI�� ���i�8�g�2����]���5o��0@�B�F�q"��jo2��'�H<O��Ck��7�0A#C(��aO����0�$�'���>��}�eoL%�G(����8�B���*���U4=�*�*n'����w� 
���t@�'<@�^���+��8A��/�ipF��
Y�������[����r�-�	~:������*=�B��$��0{e!�C��O!NP�����
�;���0���������C������L�$a�$�p��y�����*+�*q,�����3K�2q�2����V94>Tb��,�	���7pd�,�(�X�v4�m�������Gh��|��PC��������8;?"��2HL!Nh��Wf4�J���
�'H�Ow�!�cl���5z�f?zK%�}���r���fMs���A$�-�8�g?_���t<��3�	���S��~��KE��P�B��D��7�&9!���3�	rgu/H�%���S�6\aze3i'L�AT�S�D��O�	��� p��<���Og���PIoB�<uiLd�,�(�!�	�i�>pLf�6������"CTl�m!N8}��[e���1������0�A\�L��7Z�]NA�!N4Rmfy�s���
��'�S=�q��fTX�QM�F��Dxx�ii�I���+�F������g���|w�Wo��x
��qB�w����A�>k�8ay��kJ0iu�xNA�{"��>�D������'�]Ucd�$���� ��o�t"��Y�$B����iL�2i3(=�J"�	���`��15JE�f�b��k?���E�3(w����-�	��{�Z���nR���<L���y"t���u�c�S�E�D����il�2i4�v� ,�	����b��~cp���5����d��
��X��J#�	�������������'L��n����t��e���U�+�p��wl
@�{"����+��;a���3�	O���w3�KvI�
�D��W���Q�w��a^�Bt�~��y����!��]e�QI�B�~�iL��1<J~q��7�y6�'+�|��)����8!��R���46�QV!�B����n���B�,�B������F�%�"!�X������I��EB�6��z_az��{�MC�EB�B��l7c���d]�`�E�������}�j�H�0C�0�R���� ��w)�8�g7nc1�R�%	*\ap��J��,�&n�'��|[��A��y"���hl����/`�{"L�C+���� DGI!N��;�f�*4"TI��n�5�	����
f�2�.S��!+X�@R
q����V�"���.���8A���
`8�LKB�TC� ��lK����H��H�=�����6�L?�-���'L;�f���Y�TK��-�	:��8�J9��!����'(z��w�;xc���N!�{,���7�g����'�����1>��$����0������
����0�.g>���S���8a�\�m���0��d!N�?���9���1;Jz�e<�?����"�Zo�������P{�����" C�f�y"4��;/��Bf����>���;M��CH�'���M��	�"@!�	��yMNV��>�D�a�49YU�D�Pq���n\NV!;�y3�	���f�(k���0`��=^
A����q���j����#�%	�$!�k"�|7��J��D)q"<{p5�&K����7!�	?zp5.'��
�tO�����d�2�d�'����zAw��zC<Q�U��[�j�M������V��?+�L�>�y"���9��]NA�!N�����hqLD5�c!N���_g�
4�	����S���M�Z0��F�z��geZ���� 
2��qB�^���6c�C����!N���}����X *�S@��r�w+z/A� ��wn�8���M�HjIB-I ������Z�V������0Hy���YznK�'��M��Tz��dQ!��r�����sd
�����m��'��L�od�P!b!N����l`�d� ���9y��?�&v +���'�]MI�6 ���'��>~�h��d����A�Z��'5BM}�q��������g5N �������~.>�!3���!Nx�����,"BfI��D����#� k��U�D����<�e9��t,�8ap��?������I�D�I�(w�Y�Q�C�>�a ���6='�����'�G_��>�	�1&n�'B�<~}����������|��)�"�!�	{��C��
���&B�n�~�
�lh�!�5�U�UHF����>�D����`cN�K(F�c#�	����x�3g���U�1c���	�xO�u/��!:�=�!Nx�.���� cB����D��������B�&�y"^��&\���H�DX�d���13JZq�Or�3���'B�-�6���8!n�g��wteh��#�!}B����bSpC�S�E��!N��:K��R9t+|>Bs�O�)n�V�F`P��[C�����!�)_�����nUC����t�Wt:���-�	��.�(�=��T#�@�=V�y�������(	=��8��u�~�����%	�$a}B�0:����`��P�A�8~���1v��U�j���.M��� $��j�6��yBch��j��$oi���~��T�������8��<�C8L����:0��]����7k�4c�r
�H�q������q���U����k"�����J�
K4�	����3��7L�]E��2�r������4���8"���qB_N|xea�C��O�!Nf3�i��rh~�DN9l�'�o�����C���������@KhI��DX^M��d��P�A�8���t�����#A���y"<=�4�
����^�'L{�jZ~��Y�Q�C��]���>s7����
�k�B�pus?���V��=�KL�F�y"|�>lcj�.�����'4�����U&��2!p��D���,L/32���&p{�k"��I��U(}�
�(W!N�t7oI�at�r(��W#�	��5\q�Vf�t:�Y3�	r���g���S��0Mq����v�}Gf���w�.���%	�$�k"����%E�mWP��'�^6��*��H.5B�����n�
5f�F� �	����I]n���R�
�?�B��w��E�#�J��J��Z�'BC}�{t��S�E2D��->i)��L�N��8ap�;�5L��1M���D��,2LG�dz��VQ�3B�0=��NFO�+�uP�H�F�zx�)7"����:�N}�q���Gs�H���9��0=��/zi3A����q�#����KvI�
�D�����h�"�AEH%N�9z�:�)�%�Y�B�����u����(���!�	�(k�Z�5��,�(9!�	}���4�~�*���}�-�	y����[����U<���-��D���Y�p�~)�\$E�8�oQ���z�
��[�&B�~��`�
��<�@����F2i��D �	�t6[����e
�@�~v]k�i����!N����p������_��HC��D����v����Dx��3C� ��g;h6��]���5�y�����!��_S�h��:N���3Ij�>��\��0���u��j�Z"dC*�a�=ht�Z"
:J�q�����E���<�Q�}�v��!N�����I�ZuTBj�Z���j|���t��,�	���S��U4��YR
q����m��80?�T��'<��4�J��Y
��Z���>��vc����[��u=����C��O!N�Ygn\�V�8����x��{����8C� ��wf�8a��C3NI�)I������*Z��"����WM���NE�3v�Ne!NX�=����V��=�a��,�	s�|��Y�QR�'��R7���R������8��}���G���/B0���'BVO����4�"� �	��h�������+��
(q��8GKK��i�&p��k"x�����k��	�fy"�gy���g�� 8#!�	s�����_�a�>m�8a�^O�$�������=z��>;^�A����q���K�������]���5�7�p��"]�6����J��gVch�!
'K�B���j�m�nJ4-�_#�!�{"����#��~��%I�8����n��x���v��'��g�.��*��g5�	��;O���[��g�r
�H�qB�v�7���� ��'�R\/
���z�6��w_Ar�S�j�J��R/�EE�$�g�����-��qB��45C�C����!N����� ��Pk���D������Cr��6C�0?��B�~f��]���5z�n����*��������0M{����,�w��avw5��p&v�rMD&
!N�?2K3N����B����[�
�VW������v��'����f�����f�c:[����2�[y����WE-���f����>��J��������'<���fL�1M����Df��4����Y��Z"�	��.�@Cm%!N�����E�]N��S� C�0�8����48TV���=��|�8��Cx��-C�����p���]��KT�&����D����*�*q"��u�w�f�h�Cw�}�c���
�WE��PkI7C��}|4+�vf���%G�8�'o6S�{��w�4��z�#�����8�B���y~gl��!N��T���]NaI�B�����7���p<��@H
q��:��a_`���Y ,�	�3���gT�'<���*�n�QrIo�'<<�t50�!��g�'<��vfT8�QM $�cA������C�����i��$a�$�p�Ix�01C��mI%�Ao�z�Y��	`Y��\w/`�t(x�qL�a�=F�Bp+�b\�,,�	�����N�|E�X��*`�nq��p1���*��f��	�<O���}a����)�"�!�	�|��4h\�JkCab!N��}�"�lX��M����D����x!�Ng�^��'L_O�1v�w(��k#�	O�v�gFM�PS�1C� ]{�F��V�t=�^���=~��K3v�}g�z�f&_�l�.I�%	)\A������U0��WN�A���WP�����2�B��An�m1L��p�!�/�hq��b�~���:fAGI!N�>�F{T4����;����
�Q�B�PC
F��p���B&p;�<z��/*.���$�'4��~iT�#�� q��\o&�4�	����?���*��h�`��'|�m)��o��tq�8Az��S�Wt:�����Gy
H�i���Na�{"����"���C�������
^��KV�&Bo>,.��8ae�+Q�A�8z��M2���Y��l�'����k���y��i�����!�	�~^�:�e�#4t����%B�0K�)�_��-��Y��J�sU�&�������l3�i�VX�����D��u2}���r����<�?F�iT:%�� qB��~�0�����7���_�����+�.iUd���'�4kz���$
:��q����!:�N}�qB�~Zm��z�P�'BO���j,��!;�}�!N���o"���$a�$�pMW�~�o��2����� J�?����<K��m��D����1�J�5���.�'�d�y5~�M�3t����#B�0��{�����#�E�qU�����������d�`�tF��L�~�y"����=�|�.�����'���;p�_e�!Q�AY�$��D ���a��6�{�_a����IZ)��#�	��W�m��HTs�����3�Wr:������������g��}��D�'�d�Yz�x	9!��o3�	r_=�����]���5z��3��<U�������J�=|�t?Cg�`��z�=���wU�i��F�D'
!N�s��L4v����&B� ]mSV7(��|��6/l�^C�`!�~P��Z7 �@P
qBO.4���gD�S�Er�'�h�9�1;Y�x���L��46'k��Z@,�	��f^h8Z�,k��[�����k��m�H��'(��G�d�C��O!NX����d1pL�a�=$��;5���'���U�KvI�
�X������q4Y�l�*q,L�fg�������L�B� ���0M��mHJ�X�'2�	jF������Y�Q��'h�����gu:j�*`tq�1]�`��8
��iyV�����D���IK3x9^$M�8������*�6��,�B����ik����n�~M����������rm���[��W���	���'����'���!��'�'����P�v�:�D�'�gn����PC�������3�pI.I8�����1������*r�'����-2zJ?��<K?B�z8�|g]�=��� �4=�Z��������:fAGI!N���� �.nM����	b{uq���_�r�#�o0�h��
���{�=z����&+��
��[���[��V#���m�y�&���s'���d����>��q`N��;c��` �8�'��{v��;�A�>i�8a��&3=�9������Dh�������3����3�	��k��Dc;���%	*\a���~P�M��gH*q"��nM��#����������h�w��R��_�}!;

!N�i���y��_�[T%U�>������� ��00�;�������;<��SN�I!N�3|P�Ymcp��� ,q����$.dp���5e>�%����$�ry���s*��Cm5�tg�8a��31N:��������n_��K*�n�j�T�'�"G��qBN��.C� 9>]�����]���5V9�/(F��-q"���dmap:J��q����0�c�,�(�!N��;�k���A�APlpn!NH���%��O��L��(-�V<��X`7W��c�fa�T�\N!I!N����w�M�A�e!N����w�
�1�	�p�B�����[�M���'��F���W;������7� �	��:HN��S�/C� ��~����B����{"<=�����'���#1�	������N������D��
g��r3�������DX�F��5M�����{"<���!���%�8a����@�(���i,�G����8�B�a����j�Z��\� �,�0��g!N����dd8��M ��8a��_��Ls0���8A�m		0l�8&����F�����QPHH�'���dC8���x�3G��a:�1a&�4��x��s8��x	3a���"�	�����8������k,r��_'5�U4q��3
�0&���&������U7��,�(�Y�����Ce8����cP@T��[�^�����:��\lo�&���>yL4b�r
�H�q���c�F��!�B���7��6nbh���M���D�i���
�	Y���#�	��-w�3f�=��o#�	��7dZ�Q�!��g�'L��`[�J�yPP����DX�boEd� ��wg�8a��_��Y�0KD�&�0G�8t;1E[�D�?�F�	����A���y"<}*7�V�4=T6����g�h�d��Y�QC�����S0�����.T4U������p�gcg�M����n��'B�^�8�����,�B�����A@����	�'�Y�oh`�����~M�)|8���U�48���\a�8�	�$��>���P�H�F�}k�6��t3��2�	�lg�_�;vct(wNa�{":�z*�!5��!N�Q�j���%	�$!�k",���iE��eWF���7rco��� p�<~r75W�4A_������4pE0cf����>��3�B�|I�x 
�*`_rqB���~�������h�;i�����V�����D���&]���r��������k�C�C}����p=3�q5C��m�?�&�"EZX������r��>����4���9�U�u��i��}��C��O�!N����
4�%�)�xO�i�;<���O3�	����w��zP���k"�4e���\j��<O�����H��hP��uE�I�b��%�8�?�x�����o��������-�N����8!������T6M����x�
{��0j9�Z$A�8�S����������	��'�gy��j���0C��-��� ����8J��s���rM�����^R�������^�'����3�L}�q� ���>P�/�kN��{"<���i3a���2�	����;���%	�$a�k",/m3��Hw����)�(q"�4a�����+�c<O�)|��V��8�5�����]�.f���%7�8A�O���,��������8�B�x�Y��V$����t:Y
���eo�f&Ka]$KqB���.�L��Bj�6������da@,�	r����4�&�dnX��A���]MV��@�B�0b�a��0�!����'�.���2(mO�� #�ca
M-$5���#�	OO/�LV� �$A�k,H�}�������	D�8v���d92�t'q��|;�M��hy� Y�O���JdF��B��	o^M����t<�WU�����l5���p`����1����� ��\s���)�"i"�	={�R]�V�����
B�'4��/�t5����j��&��Bo&�N���/��F��L_��)^}��`�8�S�?������>U�8a]��&���)�xO�����5Y�����(�8az��fk7#�T
��|������cd}
B�\Y�8aye���I�,�G� "�a��M�����DG�!N����x���u%��m!N��6�#Z�,M6���'B��	@�1x9^$O�8A�mF��u1���=�_�a��T�Y����5��f�Ud	�!`��#O�){�����U0�B�������>s�8a��G���jd�!�����qY���wj�8A:��mi��Y�0KD�&�g�2-��h���!%N���1m��Y���'�=.Piw���J�D��'s�hx��Q�D�~t����z��(���
�-�	5�
��Zd��U0����x�^�"D�3r9�\$C�8�'?�vp�!�� ,qB�+)�0Hc�������(���y��!�2�r�����u���8$j%��qB_?Ji|FM�PS�2C�0������j�H�'��\�vF
A����q��._h�Y�0KD�&�0s+hsG#DYV��%N�������/A���y"<����J�	�4���'��i�8��cv����mK6v/3���puz *����cw
q����=�%�ar�M���
D�'��6�$�S�E��'y�RI�i��i����pj�����
4t@�'(��%�h5b�Km!N�����b��Q�I�'�p�GG�E4��WA��"�	��~��%�����'h����z�QKjI	�XQWM���0*�(q,,n����S�/}�����q�(����`��P
I��'�3��5f�FI�B����L7�?����n�B��bgls$,d�;��\���dh7��cA��^���.�%,I�����^bT��Q�G���54�������^����G������-��vdl���>�X������dEt[)��	Ra��f�Y�{����&l����0a�	�!3�}����<��gD�$�����0��6��
g2*��;`�����a+��M6�
��XX�G�2��:fAG!�+TX<4���_`7����g@yP�m!N8��]�<�+��`�t�u�~�;��v���i���H���p�J� ,qB���E��8&p��k"g_��J�$�eE�S���k
�9QH/F�<u9��t3��2�	}'z���t�!���=�]���� ��wU�8ap1�k�Z�@KF�&��kI�L���"�'��)����t#�J:O�A���L:*�?q��9�tiYF�Y�QC����x��^�z�(:��]�-�	5����V���l�o���A�K��i��.�$B����j�O�CC�����>��?S�
W3�	�+����;Yl��U�47+q�\Y�8ANp�6P:��x��/��q���j����K��R�#C��s�T[��iP\��{"��� I-I���Lq���4��6-�ET������g���;s��G�b�
�iV�D�{"����G�����PaT�[�������*>�+�`�|�Ar�
{�������j���u�2�4�A����.�F�
���|M�������>����!�
7J�A����J��[n���ir�'�������\������5�n�����r=l��r#�	�����Y��#4���M]k�,���p|����@V
q���~�It9]$Mq��w���4�e�6���a�g��� �\p,�	-�����o���L�ak���xU����`�[.��8AN�v��[�(�6@���Z�	�<��b���A�\Lq�S&o}���#�O�gf!N8~��5o|��h�x3O������)p����8A��r���|�
8�,�	
��x�T<��o@��i��x�YF������^�~�� 	��)������B�����}���c��?���!t�&�O;3��re!!N�)���|�����;"��p��u�pp�����@�������(I���(�&p_�k",�d��/Bq_���8F�$���� g�7M�q�$9+�xD�oN8�\U�8�Ox�?����B0B�����|�A�����b37qB��wt���#>�!p'�<�����&�o��,�B��'�+s����B>�#�B����=+@��A>�!N�������;�{A��qq"H�C�5oS��Z�8�aO��g�,'�!��En�����	~U��e!NH��77Z�{����V��dnn5��S�ERC�<u����,�e�UAX���w�3��a��� �	
�g���y��������w�Qo���W�'�OS�+���\e�8ARn�V����r]!�a���&��^������`����=y��`�@D
qB�|V�����*/���8A���O��p��!N��K>	��
����8at��?��	`�S��L ��8A�C/��kjk!N$�{>��x�\Lq�*;����r�L�a-�	����r����>����8��&Ln�D�^72n��� qBO~�fp��,4�,�8���:�n.p�����rM���w�Qq��r��?�O6#���
[�X�]���f���<`�rU��{7��"�Y�4C!�	�+���r����������B�p������9��@�Vy"4��8�|�o�v9�]$%�8�g?�r��\�9�dY��}J�Q �	7��`\aquy��T�Cz�x'��'�4w��o���F�'���{	&0R��q��7OV������`�,�!NX����_�d�0�*`�qB
y�rT>�5M��y"4�'g�7���)�"	"�	=�
�����'���8�w���L����'H�������!�!N���t��-�v.�DXw����|R���:#�	���j�k� q�c*�2��#��,�n!N��I}����X�Y}�C�j�y"��f3�[�wD�S�E�D�$�����)odY����
�2{��8!N�S��~�~*��H6�@q��|�Oe��Gh�����k�,��
�*��@5������l$�.*��/���8ASn��2�x��������U�B���fe��2����!N�_��P�[��	@Y���[��eh>d�I�k,�.�z��Y.�	�X�V���L.����Z�^jr�|��2�,�	
z}byc��2R���'H�O�����TF��8�g������e���Us�� ��d|��2�!p�8����~����ut�=~�����f@C�~M�GW{�� <���`,�8a}s
����ir�����>-�	�|�2�
\S4O�����Y`�r
�HBq�d�����}�O	�VG��8��v���#@f��mW�&B�~^b��L�#�B� �o��	r�����v@!�	����S��	�oG����S>g� ���r����7��e��GhX
�B����;����	wdY���?�!���,�B� �QA2����'r�&��_&�j[�&�\��(��L��[���7���$�u�x���k
k-�{"L;�h������~@C�~M�Gg|4�<���`,�8��o���C@f~����5�,�	��W4^�y42�$q���nw>>dF �E�D�z������Dfe!N������'�L!Nh�����G��$�B� )?��O�-����D�k����	�6���Dx����?�Y�5c!�	S�pID>$d��G�s�:���'�	yV^�!A�B��8�#��2G��"	�'8�t����L��

���sWC��j?C����a��/f��]���l="j��W�7����
�a��P�~���6��\�*�UC��������O��B{kbQ&q���5�kw�1q���a>z����/�B�0Hx����j�dB�P�� 	o�����=�6��B]a�������x4����a����-���
�D�&<�U�������!u�&����4�`g���'���GH���l�*��
,�c!N�y^�~��A?��p\3(O�)|x?�Y�� l�E�D��z���A?u�T\2�5�	O�O�y�Ol�&p��k"���3�����	�+��0`.Fd�f����'<�U�E�7b?��!g9�q��Sm�?��.J�9&`qBz���E@�S�EHq�4W_�m��;)����,�	?K�7��q���ROB���������%w�Q!p��8��� ���-�!N�������\a���9��q�2a�]}��ri!p-�k"�	7�����
����Bc�/,nSC�`!?�n@4�����TC���7N��@?�����B����J�P>#�oA5�	
m�O��������Z�~x5y��s�6���A?��&�E�����\Tq������[�)�
�4�q����#-�����
���":�X���6���g*V�}X�r q�1�p6�>���tE�!�d!N���_�y���v�,��i���=���0,qB_��L�'06L���5<s�V�T>0���
�B�0�t��(�<�z��E��ti8/�4F�!p)��DX^X?� 3�������� ������������/���?���?����E������_�����R���=�W�������qv_��Z��}�g�}�z�_�����}�g�=�{����A{����{��j���g{����{��j���g{������su������t��������?������T��W�r���Aw���4���������������������������_�K��_����H����8��c����2������/��������_�����/�����/?;n����,���������������':p<w��?w�{{*���:��-�s���m�����O7�u^iw���O�����������;���(�#������O��7��8���t�z ,���_�����au���>��ny�W���5<���}V������>?�9�������?A���T������{���\��G�������������a���{���C�;�\��S��?b_%��g��5��<	�����z���<c��;~l������5��=c��y>�����������������������k����?�l:�����7�����_G��o�����$w�r.
p� �0W�(�����4`�����1)����XK��?�����]��Jf�V�\���O��|��G����]�����_���������_5���mTx[>�G�7��T����rV��n�,}9\'��v����������5������aTz~�J�&V��*��M��UY�4u>e���6.���_��:!���6�O����ox�2��_'k���l2d�2a2D�2�d ����B9�A��d ����2Pk���2P{,�O\�D�	�����E��&����{�`��/�E@�`��o�|�u}X+��������P���_E� �_,�y��u`A��"�@�@�7��'��W������^������'�����`a���>X.vV7?��b�X������8|��������e��hoO���kB��\>}�UI�H�1��� �Q~Xi���5�!]}I���zl��9�Xs���!|��3����QK�P��-������C�v%�k������v�~!]��Dz�D#�"+�"+|�4��"!���S�D�ew�B(��H/�r=���Q��_`H/�5��/%����;��F��	����C���o�S$��W��.������$#��:�V��!�u���������	�c)DyS�"��>��j�$C�����S>vUO��1�bg�M�I�p�u����^�$-E���W�Db��g2�����)��8�T?�.�����M��A��2+�A��d���\����W�9&Nc�s2�����e4p8��B��0Fv�������/���l��b�8P�qH�A
��R�%R����G"A���/A���c#T��0�AX#B����^U{�������F���Q���Zp����3.R�F����^����%�
�!�<~C#�!�b�8�}l#a�!�c�8H[\s#����8�},�c
*p�����OCN�������o�AZ�~#3�����������>[����=!7��d:|�N�uV��0!����;a�J%0������������0G��4���B���/�/K��c���.C��/��1���1_��+_~�m�@D3|!+|A�|A�|A�Q�S�#_��@�#M���j
#{��~��E� _ ���@�����U����|�Z����/S�bo����n��a���Q�����E� <a�/D}l��>��������5"������`�S>����2~�b��C
��n�	%���]��P�!����!��J;�$���M��?$1�rYpj�rz�����1Pq.��R����2v2���P�nTA�o� ��2��YHKY��X�t��a��V����x��f�BV���������z("xA(�Q�/���x�Z�h=�x�h;��:�@����G(���_���K�!^���GUu�<�B�
vx!�<~CCx!�b;������>��Dyn�����CxA�X������{J
[/J�������L_�6�}��t��_�c$�&��}��*��>gq���*\�VhD�
W�`H�p5s�B��@��_!��A��\5Fk� �\��L!]�T8�����oS[X���L��U���^����������(�
$�l�(d��(d�o������"
B9@�r(a�(���F=������r��������.��3���CE��K�t#E�i�A��PE+���E����"�"�C� �_ I!�W;���E~���(B��v�L������������s�]��_��m��M�&�;���P76��:m$o���Z�VA��0�Z�k.�@Ya@���]��E��_q��c�\�� X�	���3@d��
2j-���P�5���G���1k!zkNw�q��v�?k�SZ_B�������~wB��
r-|�7������&pHX��%l'Xd���S�!J�� ����u�0eg���������������"	p��s��p�i?�9��-�g��8�c�����&Q�tVO�4�����|4�u��F���742�3�b�(OX�A@#YeD#��1��c�����������;$'I�X�$��.#����y=c��[e0
�(k�$���N+��D�Y�i�!��	o}!���n
�pc�#;�pyzIC"��$���j������@"a;7$nH$n��k��FA���Q���u�6U ���� �}� ��$&l��#U��X�Q�G�U �Uh�(� F����=w>�#I ���#	D��9�<��������)ZY���z�r�������"��:�V���4��c�XB��"K����g��,�������NyV?�B{V{����N��g5���ho��D@�{�0�r�_]��Jk�~p�p����U4�@�e�`���z��u�F^������hCI���[%]��P��.w>�>��
"��P�_u+�Pn��	�Ml�iK7�p:��%'�N�
N�>N�>N ��$��2��JR ��:�@�@��u�N ������`�O�PMz���h{U���3�a���m}�����^<�����	a��[�	ae�	��`BT��	����XxP_3��W0A��@6���UP1�W�um����=sj{'P���I�8��?�������0L��6d$���r/�6#�(���3���?0��[�LC =!+�	T�>��Qq����*��6R�N|���M��@�I%]���������m�@d3p!+p!+|�4����Q�pA(�k�D9��@�7�@�H��X�������D{a4)���~7]����iv�x����x��S#���B�Gux!�<~/Cx!�xA�?���R�*�Y�Q;;�+/��X����z�^��5P�@��>U����������'�M����� ��D�i.x�E��s/�?��Z��0z�@���6�BL�bj�u~1L����@2X�C\�6����@����AH'Cx�b�^����s��fCV����������,@� ��Dye�o��Q!��_ �s'y����lb ��Nn�/��Q�������\���#���a��[Q�����C� ���w0�h� �j�m z[��|�����t����u}�S~��A�@�=s,��A�f}�T�g5zA`�1����[9�����!�p��0y}� ������.�� ���-qAH�����G�#����2��40���C��>z��G�|�������aw%Q�����>�L�nIE�",�H��I��I��+-�r��;�
�l���T0�z��� _�_{��� �m�v@-���i���i�;�	�����Z�S�p^�@-�����"��Z���oh�Zd],R��O���X�J�o������'.vh�Mc2��.�(w9N�����\���_(�����r��BEh��7�����
_��c���P�|�OI�!$�s`�&_q�!$6fdL�����.�t}��~�d���y�dX
!w�t��Cx�
Z�5���.'Bd����"l�"�!Ya Y���)|� ��_��,�#�!B�����Cd�E9�vd��sgG�,��w�*����h;u�Xr�����Q����.~FW��Q�-D�U��ru��w4������_r�|a��1��I���:j�z�fD�������08�Y�
f;�@��2���g�gQvH��/�G�nb�k#��&LGa�z�Vr1��%�6��\��qZrD��-9B� �1i�W��a]w���'���9�:��Z=�7�CZ��L��������!|"~8�^#
?�~�
~�~b��}C� ��
D9��r(����s����+~�&���������)QA�@�����$��83��w���/�r�T��|�']fa����w4��r �!�e?/�B9�� �l9��:�E�w���������)���I�i�j��D�@���������F�
�D�xb~��e�0�DJ�YNh��6�)� ��Q�1~T����fLq��QJ:A���4�
�!.}��m� �M%�=�$g�"��
Ya�
Y���)�l!�
�PDpQ��\�L���sC�G1��3�~7F�u���{fL��U_��;�����2����!��:�V��!�u�b�zVD���P �Y�Az���1P�j|mG�@=k�v��h���i��6:Jb��O�Pl@������b@D������xbf��v2�������3��;��@���e�A�A`�_s�7�5�Xh'������7����
i�o�������7��V�n��iw�d������M���
B�XS���(�xQ��l�!�7Pkd�Xp{���w��^�zl�����Z�x����3A� v���A�@�����o����7����e�7���7�o�5�����
Q���j�:��x�����
�YCD{���O���>���
T}�`%�&
T}���o �FS�6����z�Fk� �N=
��0Pc�+ �A���
%m�i�MH��@�V]o�0L���X~�B�*\����� 
���DA�T�(�W
D!�����z~��<��^_��n�I&mw���	Rn�B	��Ya J�'L9C*����)g�@�*�b,��/�;;
��i/�A�@-�oz���0����	~�If�������,�n�EZy��f�EZ�1��3���Ef����,����1&�b�&�i����b���V���5&�����;x��W��d�����
C���.�Ul2�f���k����_���������^4����r�G�J:�"/=�H��8�~<#���3�t}P�qj����_�i�hF��
8O��6p ���� �}� ���%�Hd�Q��F0e��R#�5���:Bj���2m��"Bjm#R#��gN��T�i���A�@�S�&����a��{�ae�B9�����Q��a��gE��"�k��a�d���Q��uu������Y���#Y\=U������p@��}(?K4�'@��C�.���I(c��Q�,�@�����PkdI�5'����8M���N%����S8���^u�
�������p��0p!�s��0r!��x`�����+�@";�ub��/����&��@�'���^��c �k�� c��e�ms�1P�TGI��d��#c�:��1��������A(����?,S��c��$��]7�u��<�m���j�LGI�Y�-]:�@��0����uU�MT�9�"�������/�x�����o6�@������t�ct�h��@��K�\�������\G-o!�f t����������&C\��k��!lk�����!����l3d�3a3D�3�@�=���J_ �fhA*�F(}��#��v���^;�-P{�,ph��?�R|�"Z��4�I2��:�V�����@B9����Z�z�-D=k��g��Up{A� =k[Ly��Q�0�YWu�#Z�������,wk_~��:���A��j+��/[i����|�V���	�:����4�0��[
=����j����J����6��	���L��D��e ����Z��#�l1d�1a1a�BB2�r1�b ��
	j�b��!z���p���������{f��b��O�!"��4�C��u�!�<~/C�!�X;������g��G*�Z|�!b ��7cD��Va\F���������Q=b�����i�������yd� b��^{�e� �kZY��y=��t?����j��`���1��c�O)?��^"-
�AH'���I����A�@��������3����H�L��7�
�A�r7�
r? �(h�__t��������~��o���?����������w�_9�_���nw�R���|�����������$�-�����_�p�q�E	���/J��m�_�y(����(����S������0���H��0^��_���nk�/L���������<,���;������y�b��W�������o��5v�n�H��d],��\<��b�NY���EV,&�e��d�,��e�J�e��k`1��V�mF=��i�p���J�*-�o��8��Pr^}�����|lC5G���l�	<���1M�;�I;cJ���zK��k_sy"I�(��F��q+��r��(������(�r���`�����QOS�]F���;�����w��`f������7�vcw���
�1�z��A��A��dB�& c`�aB��#c �F�2�l�g@�@�a|�F�@�a�dD{��J@�@��N�2�����������������o�?�#�a;� ����2~GC�!�d;������^�c����7�^�c����\{[����Az�c�^��rzz�9��i�>[��_?D[��k����8�[8LH�g��+���nc��Pk.7�l9J�LDZ�����(�����t#B�>�s=zu����������Z�G����9��$�1Pa�#���R_�Dm�@D3�A�
�1d�o���1�\�6�@���o������������1��v��w��h;�o�^�cX%�����dT}�TE���c��<�`Q'�1���E� �y��V��u��u/�1�e���&&jJ����Vp/k�������5��(:�@�7��`�L�A@�_`Q�Q���������/i#��X�A��le0\F��<�1
+��@�@�37�1�i���m��?t���������lt!z6�U���'���a2�b�~��
������E�P�1�P�Q^�?���Q�(���Qp���h;��:�@��N1
���c���}���?���\}��#`���0Dl�r�� `���0d},�\-g8��9����`��JP�`�^6��{�e��`�t�_�{|� ����C��Alm��"`g2Q AC���
&���G��������&�V.cH_k.?�0����B:��@-]G-}!������!]�"��@�QN9v�mj�f�n7������[c2�oP�6oP�v�������}�������)�`�+�}BKi��0^w@�=2e�j%@���8��8�j��m�q�;��}������}�K�C��"q��X$J�'a/�!�e�8(/��e���e�!�i/���{�u�l�{Y��i#�N����M��u�&4�����Ii��l�����x�
\8��A������8�5��b
��h���	%]��p?�!�CBCX��cH�xC�loH_�
J:������uZ;��y>_���u��>_�������P������T4.��.��.���S�	���P���~��Z�S��
w��������D{ato���~w:a"�x��;�~7��u��Z��/>�[P�����E��v�"�`;l������[d},b��Wb(�w�T>��M�p=u�A�c�^��V{U�����[f{p��+�NRA���$���F@*�1L���p#���
��@n�Zs 7"��Vz�FNA����c�dG�����4vPk6ZG~M��
j�����6�pwM/�6N ���pBVp��q���.��ep�P�����`�Nk�	D�����	����N �gh�����x�f}���:�@���4E�@����7�T8!�`;���N���'d},�����p���~c�c�u���aTF N��'P����>�H@�@m2�U3,'�J|~�>q�IC�H�jkP�iB��8�@oe(�5�-
�is@�����NlP�Z�����4B�������N`��A+��G��_5���kj`�j�8S,�L������������D9��@�3
�r������C,���
��^;e	^�-O�Z�t�D�@O��TyE��v`!�`;���X���,d},������B��v`A��jy�q�ls#,�}l��
��c�2�&��z1��U_93F,��=��Q���.�y��Lz�c(�p����TV.�VVHo d*D7z8���5t��&�
*���PAH��N�~�z#T���
�@�'A�6����m���-�T��f���'Q(a�*a�*���P��
D9D�rf�������GHW ���&�.W �N��?C�Km2w^����3>�v,��o���c	Q�����[�XB��v,Ax���G��������c	��Z5D=k��r��v,A��@�������=O�~����,����3�,A���~w�%�x�%����j���a�������Kul��/�W
xAH��C kAH'��CL�l����������C��NG"g!�j�B��r/�M,#�T�<�����B~+���L��exA	�IJ��L�^P���������rf�%S��n�^���P����A�L���z�Wm��lH[��_;�T@
\}�$�jP��G
Y��!�c5(e?mA�B5d�,��e���e�z��A
��V�6F����������A5p��	a~{����@
c~��>��c_�9�-�^
�!m!-<�-�_�r�Ek�����Q�}��n�r����p=�2~.����������������?��S.�X!l�V���$����h�q����������I�M �h"
B	��B��B�M ����BN!��oP�D�x�"� ��&�L9���9��i?�+�������R�h�����Ln��co�
)=�3�t)E��v�"�`;J�������RO�Q�Q
�c���H)�>�����M ���"��5,r��k��f�\1�bW�� {r7�������p�8k
��,?�!3b���Df���(����mZ^�Zs����	�A�adE�������.Wt��%h�-]/������+��K	��z9���m�)3���!}�o��L#���E�&D4C ��O ���IS��t�"�J9�)A�C�D9�7�)�H ����=DA��ox� ��w0,��6�;'�U_�:�@O��H��C��v�!��:� ��!�V;� �_�
"u����:�������:�Z�Rj�z�XG�_}7�E�����ta���LP���s�&��,��Q=�F��~��v�.]�������F�9�kn�'����(�-D��-c$���.������F��C�E��a���4t��A�������!\v/�v�H&�AB�GB�Ob�>B ��O
DB9��r��S%1e���s�C$�~�ZT�!�%��P��Z��v�[����'�xj'��>uu���'Dl��r5��0�U��SQ'�@����O���>��	DyU����QOX��������u#P�^����=�{�'�-��&��W�?�A8�����������]�3Y�bhu4�(�y?N�!Cbrg��C���m���G�������f���~�{0��l�Sw�w�����n�
�OI�6P��m5T���w�

*��Q����m�~"lAd3B�B�B��n]$�A(Q^�� �r���F���6�z#����gw�ho�o���@m2w�"x���w����	!R=��x�~;��_��C��v�!�Y<D=k�����Y�!�Y;�@�C�Az�j�q��vv��3�Z|�#m����p
��F��q�����t`<�vJ=`k.�v`��Cz�����0���x���6�!]O�:H�W}���x����(BH���=D�p�_��G��$��t�T���
%l%l&�!
J�'
L9������5CRS����v����{mt}hQ/�^Y�������W����
����l�Oj�'}�P`���lA)�I
Y�l!�b�-�},��\%��5g�S��n
��l�k;%��IC��������Nj������A�����8���������a.>7&JI
L�>���wv�HjP����0�O(���
%]��hS+�t���0��z���;�m
5<j.��4���\�)1P��z���������b�7GU�t_.�����x|}��T��x��vB�1J�FI��>������&R.��H��H��H�)��\|�! !�F;E$D��q��u�uL{n��v��h?��r��qe�}�c���)�GHZ�8B��lK�����������D�jE����P��U*�ZM������\��"����#�_�.�_5�}��_�B�)���4�P{�$D��e2���Y�d���p���J�kF��vvR-��e��CH�#v��j�B��nq;�q�j�����-���3��#.��G���ez�
$�O��6H �� �}� �}� �}�@����A�P�g`0�z���l4b@��.�1��	D{�T� H �N�q���y�B����R� v�x*"J������C	Q����@	Q�����c�PB��"J�z�%��� ����%�����W�=k��g5��)�j����=k��u0Ax�u�"L�u]o10��7�	T��40�
�B��aa@	��%2(����t��?��|�����G	26�3(�t�$��k�0!mk�	i�LK7�p9��
6L �� ��o~�	B�H)n���a6
&d�&�z�����	D�	��O�	D;���h�����v�,"L���9G� v���A�@���0!�U;� �0!��;�u�L��hg�	Q�&�Z��Q;�{�v0Az���e�k�����.
,�S���z����B�&P��[}�w����:Th��'O4���k'#-���#-ZvB��w&��\8�g�FZ(+��?��F�a��:�����'q��N����'H������V��L��f����K*a?AA�L���r A�(�����r}�{��1���)��3)��N5�����������-A� v� [��;5F�uL!�U;� ����aed
B�:/����U�������Y�I��g��Q\F������g
%(�X�����j���S����	�7z>a�z!EKQ�k�����@�����p� x.���@�����b�r���a��%��\�n,AH'R�t`Df|���t9
X��}�p�_����V��FX��Y����������
,A)��	L9�5�)�[�!K`������3��K���4�l/�^;���%p{?#^P��M�����d	�����*���[E�������cE�����L2���%(�ZU���9S��o�2���=���X���>K���(�9M{��d	���,�����R��x�%(�'�b�j��Ar�� ���\�f�.�Y�]1�.lt��w��1
s��4���_=!b 
J:03���3���8C���/����{H�4�o[�U�+������F�����������#� ��L��^e?�)M�^�z�hG/�5��W#���������j��6l����{f�pw���?cl��#Ww��;z!\Iu����[���P���Y���"�Y;zA=I��#S6�> ���5@/�=���������y��^�xV?��/k/24�����" ��G�����a�:z�����t�����������Z9(S�)Ik�����j/����C�E��0����q�:�l	%�
����(F�� �������U�F
D4����R	�EJ�O�`W����A(%�rf�&S6�5Pk,��@
���dj �K�i���h���D	j���!�C
T}��R��D�@�7V:����j��r5Dv����C
Y���A(�S7���C
D�^���q���Q�=7�v��g��P���hS7_�_��?��=u�o��9�H��5���c?��'��1^�C�~��b(���P��eL�����3�rj`!]��:F�
��AH��=hHK��%�H�o#�!]�:�����m��L������yqM6j �� �}���M��G
D8��r5�y��S6�T#j��0�:"j�������5T1�D{��9���oW*�W�A�#p-}}��2��u���o��H����Q����Ht����>d�-���Qg��������t���{����-��uJ@��m��������g|� �l�Z��T}����Q��;MZ����7�zJ*�:�h�AH'�4�g)��rk6�@L���gq@q����S��}%��C�� rH��Cz9�������D��+�d#�A	��J�NqP�6w�[�������;0�w`�FE���Y���#��^:'��^;�wx���w��r������������R��C�#"wH+7�v���r��8��L�S6Z!w����4.�����������!w��������������"�A9Yk,�����[�,��	��2*�����N�6�����-�!n��+���,��+�������A����?��Yd�	�uL�e�D(�z1�@"��n$BI��t9�I�����J�d3$B�J�'B�'D8D"�����C$�(o��(�DPkd2 �=���H"��3��#D{����S3���j�������Gtg�N7SDT}c|��D��v"�b;����:�A_��>d�l� ��
 �e���e��TD��_�� ��5M�S^��
b������� ��>S��	� ��}/_Q,����,Qx�oU �['����b����4���e"�bhV�]1�?�O�?(�zjE�B�^����������C�"u�3���=*o������J/�.�L��RIE�/m�B����v=��i��s(e�K%S���`��w~���A�A��i��S�:���!<�:��{f5��A���H0�����A�!\I�`D�jG0�r�`e^g��"��z��`�ZU���ycP ����ak$��3L�S���#�i�jL�Dl!<��v���%3�-^��� �3c�a����M�5�;/���F������
:E���K�D	��z��~�\�30��H$J�@CJ%hH7 ��t�
�Wa�*�L������s$��O��e��P�H�U ��8��
�!�@����"R��t^tH��Y��r$^�Y��<�#Awv����7��{$Q�����C��v�Ax��."a��2����C��v�Ax���h$�F�e9��m>���e1Gb��n�D�6��]976P���H~�#1���6��t"-BH�	C���e*��C�m
�!z>�2�5����!��(�GIC\��!� 
B:�"}�4�W�H�=|�<a�"�!
B�'
B�'
D�#i�� ���(��1�r�4Pk��BP{,3}!���y!i ��j����F^�Y��,A��>IC�]����o�W������H�PTcd��4�@5���������HC��v�!�e;� ��?���iy���1������I'�ez�4�����d��,���;�������uj�L�R�C&�*�����	�@���b���is`6Ct�1��|�����!����t�1�
m���~�vPR�h��.h��.h��nJ���h��vJ�Ii�����F���="�/����8�@�6�>|5�$�c
(�
b�����Rm�A�o�Mn�!�h�7�"���r�
a_�!�lo;[�
����A:[������3�="c7����?�����I2��ig���h@)6������ ��e� ��	�o�s���;�A���M�;�!o�!�!/=P���0�BJ�C��j��r����������[z�R���U�!���;�W�q����om��$�5�p!�����>w����q�l'8P�w ��a�H���G}�\�����8���h?n��-��h����$8����*��n%�.�Q��Y/��A���+�C��v�AxY�YC��v�Az���8P/�L��������q�47�:�@�W�=,]� <��b��	*��7;�3��SO<��h�_�_������b�Q.���R��p����ALa4���[����w:84� �����?���	�������8����#��!��L�~Z>_r������?����_�����o���~���/��� ���/�����~�wB�1R��f��N��E*�D#TF�	Pj���<R"\�J�T�o��cw��� ��1�p��i;-����uL��a��~`/���Yy4���6����+����S���>.��k�a��%!���#��F�d4T�����M��v�&�p;F#<n�� �������[.B9��\�k�����+#1�2����;���w���������r��zd?����sEDq�r�������I��2rQ��?������
)"T�*I�
u2u|�D���CI[�H��j�9���"�\n�x���\*xF���3���N�!�H�K��7����8~��>�#�;��b����������"l�"��E�>}`f(�H���T���o�'�d��0�j�3+��0��w�h����xh1*��U:����/�y�����
�A��`����w�����!T}�tPE�u�t�UP�!�h;������n���q���Az������FC�D�z�vx�f��ehv����V�'\����y�r��[���p\�����e�Nr�K##�a��)B����"�������!m����9��?P������
&����P0�������M���i����I���!]&'��>�@"�t�������_��lAD3yB�'D�O���FMQ�����������#D{���@A��N:9�j��[G"����(H"����E��'�T��8��k��nt�D!���,$Q7��� QG���i$Bz���AAW=s�TF��l�S|#���v���$�E�%@l$B8]�7$���R�n9N9���
���S[�����C2$B�����"n���������_3L��@�G��K��J���!BH-:w�$��a[#������S�kw����p}t�m��+�T��v��=*��B�<�f��O~��p���p	%ls	n�@��p	������G��%����"
\�i���	p	n��S8\��;���K�{n�#���k�C#r	��0��P�1�\B����D��"�P�>��:Z���V��4.�=m���%���3$���j_F��s��K�J��M�K���n�N�'\����\��?��o�����8k.��b=M��Z���`�N��!?B9��T�E�5e�����U�?��K(�Tn�%�foUY�CO.\��q����������������U7���U��K7��#(�n��`�n��d3(B�BdDD8�"�p=@�P]rEP�z��E�3���H0�wg��"�M�(�/���O�kpu�{Z�"��awDB�I�A�7�]�������������P�P�;Ddm�"���S$��
���L��vz�v(�h?����5�?��U���Vh���A�xg@���5��4�i�>���z��t���?���

�}=����04�Pk�W�|�*k.�@b�	� ���-BI�aj���pk
�>���G�h�i��-D�"rH[�5��k��c|FR#�U6w������!|>���m��q��`�v�K*��8��}�A�#�.�p��%?u����0�M�����ZyU
 ���6
`	�^=^�U6�&�pk���]P{��"dT}i�Z��U��c�]P�w�k��c������o����n]T��"��z��c����/��:[�t��0�Dy�b�2�m�2n�m�=
I��u��e����&�}�.��o�_���u�8�x�]���1�@T}k��P=��
D������A������0y*�����#n�������-�Fz��JA���b�u���)���� ��nL��HP
���$T��:���;���^�Y�{�X�}�/�6� ���
!��f�HB6j;N�+6^R�"�rf���{�E��c��FA���V�"���V��M�������71r	��+�;b�%���y#������n�Ud�!X�P�����X�p�������-�������X���~�K�m�v�"�����\F=���XS,b��~]y�Egkb=M;[�e���q�Y�EP0sz�@Y�FH=��i������t��@ZEz���t9��*�t�q�r��g��:��
��@�	.���~H�H��k.#�
b��C�x��y�u6o �� ��^D8��p�7�z���7�#��
����o��6ZT o �+c_���7����m�9�����
tg��'�<��u�� o�FN�z.gF?��7D=m��r�������
Qg���m�M.oS��:�x����y�^8������S���Az[?�a��~���y����MNS����`���5�w o��>�	y�&�lp�8C8[	����
��z�C�
B:���������A�8�W
�#�tf�~�� u��Hz��o"�#�v�>�;�p��!?3.z`�����Tn�z`����3�L��e��[�#z`�'���v>�!z��^�y�^�����F4��A8g��un��\���=p0s��!�i=d]-��k}��u�����C��"zPw��=ho����r^��������a���v����j���A�SNweT�!�P��>�r�>1�^�$��:a�N��� �����A�5��oB�����[�5�-���������H�
����gHw�n �;dO3�.l������h�a�Yw��x!������Fz=(a;��	Gfz2�t �!�@�C��Z9�Q��w`�1�@�m�� tx��:,���:��}w�m"t��VG�B�������?�F�2�C@������Yg�A���E���tw��}����u��z[G�2�����^�C������8����Kg��i��������u�Hw�)7�@�@}��n���FV���t}lh#D��G���Xs�<�J��=���=PK��[�\�����]1�*\G�<�W|��z3����)C�����.����;�����_��������k�z�k��-������Fx���,�p��%���d����L�����Z9���:���i��~oKnmc&��m�r\-q�x����r��$��7�xU�:/e��\����.�;�C�����P��H�wD�m�;��-2�D��b���m�}3/��<���{���D�;��5�R>�J�ho��U�2�_�N��i�Z����)����a7���S�t����/���r�(��N"��
�kR��f�4��k6�+��\�x#�bL�V���kN�V���c�bS��h3A��U���Q���T�j�������m�@D3�B���`f�sac�it��>L��k���Z9�G�i/������3���8���9���kS�g;;�����[#y������3��A��F�3D=m��r �B�Z��r��Y��)o����z��3P;�g�v��z��Qpq��N���3Pk���b^���u�w��n��p�t��k~!t��HmA� ~(���)�x��������y����<�t�6�;������7�e&3�^ �B�EY�-�t��ez��p�4t�Pk��� ��k��d4"A��-�py�&�*\�G���)�GDW<���n��^�G0��P�v�����#uL���<���WZ�����c�L;5G�i���|�#��
m�����{5�y����l�G�sS���<�_��3�xW�;���Gd=-����E�|�_��u��#��x���>����o.������x�~�X�e��o��GL;�/^`����~5�#���HaC��Wu�<�����!L����z65$A�?�i1$A�����n<�xP����t`�'��@"�Zs��cisx����<pa<�&�a��8�����%�Dp���I#��$z]~vj"?l6� �!�}A
H�`��/v�#�p��S����V�F�N0��#���#���}��������:Dg��s�e}� ��xD���%"��1�;A�����C�����^\!��?�3�^;���6� �D��vB��rj"�a�i�� ���S��ho�6� ^�Y_�DJ�r�FZ�i��Zi� �;4Y �k7�������_�Cw	�j'��Q���h�!���9	0a�2� ��%���T.\�j���0F}<�0T#����9��j`���<�t=��2���D	F�Dw���p%��
�l����A��{`��~L8S���C��Z����~�
��h��0�����4�j��Q������u�������o��z
B����F���5���B������_{��_{�<l �AxX������E�@-]?�h���������|��4|
��A�����.h�;�4u�&��1�.�ar���\qF�p�U^L��������3*J�M��������N�	"mm6A�7�p��d#��F6�����G`!�#I���"!���U������\v��o���5&+������q�!T?�M-k5%D���IE#IB��q���`+Dx^Go��#b<�%_sw���R�u�i���Z�(�@������G�B���c�~>��
5`�d[�ew��l�E=�Fa�p����-T}���E�B��N�-�+�:����-Q�������_?v�^���'*���U(r]��������W3�q��>�q����|����������9�M��z����;l�9��L�����NZdv��cdv�F���$��%Nd�[g���k.��=k6���������"mg�&	��	5G�2����9 �#����&2;��P�^5���ei��zz]�
�h<��o	�f���o��0�G<�%�����m<�<��QO����
M�`���x�h��������:�>w����A�N
?��nL�A�@��bC�@�WF�}��/���
���H��-�����x����_zXC�@m�kA}n���C���2}-��-���|��D����F��q��.�Y0�)��|��2���P���������H�q���F�p}�F�$!��t���p�m���>o�k.o���r�dkD���$b�u(�xC������K��6��q�����_������Y��N����s��0%l�0�H�
&l4�<~|��������
~����S�?0m'pB���WN�
�zi��p�������4����o��F�\}�4�����<�\}������W�=�������C��"~P.��������~�>��A������/�2��W��q����{� ~P>�~;?����]�?����S>w�Vo.��Ay�z���^o�
�=��	&�t�R����(��k4�Pk.����%(�n!�<��@���B��OS���NnSW<��_u�q[������������h�s&��p!�sj�� �N�C�/���9�L����^��!���C���ho��<rj�TW�ATh@LL��WN�!��19U�A�r�CP���e9D��v"�p;!<���"�r;���'�!���� ��5Z$"��>�^�q�s�^����G!|��n�����t�P^�`b�!�W�'ZuB���E!�G��P�5�T�u\�H�����F"��S|q<�
�;��T���[*��r�)"|��C��r��A�C��oS���B���"�= "-�����=mAd3$B���p���dD��F��a�H"�e���:����m$�h?I�?b�io���j��cq2:}j6o��������6�TB��`�JP���m\*A��T�/�����J���7�u�������T�����_�����K
����F����o7��������~
@*6��O8�����8�~��e���p�
� ����P�#�������o��D:Y6j!��D���� U�e�B:�rSI�����4���6"��	v!�����R�5����Cv��Lmc� �.���|�����C���"�|x��o5"D�n�IE�q(!�"��� ��a#�D�_0l�);A��P+�H@�=B5!D{m|[�^�L�z���E�
�+MF�Awv���D�!�����U����T���A�!b���TV�Q_�������#����G�������}0�=���m����I*�������r<2�l�~���#����K+N?s��1�l�}#vk�8k��#?������}�qP�8�T���z`B�}�q�W
U"��$�D����CcL��@c����o�D�HZ�F� �7���7�i�z{�!�@!�Cf�� �FZ�it�FX��(I�!�����:A����EA�S9���I/�rj����D�@���g�<��23�:<P�����U�Z�+w����<�@�E��v�A8X����E;#x��x�=lU�2���F�`��}�'�`�������eWk$��}�3c����7P��cw�
���O��Cl�Q�q7^�#q��q��
2y���
�
�QQy,p��9 �",��!li�����g�U{�e�!�j`�U{�������p��^� �=0�HI���S0�{`�������S�I
�=p+��� {��0�h{`�k�s��p�����\}�V:����/i�v-2V�%������P@�\}�4�����H�r�}�zX�Y��A�X?����F����~L��2� }�>�H��|l} /��c���H��e�������B���7���>([o�38xT�B�;��4�W�d�0�����{#:`�s���7G�%5����D������6q�K���G���.��q���%]��8�W��(��=������`!l�<pC$��`"�D9�S7#���G��U����������;�+/���s������/C�@�i1�b��v&} v��[+5a�K���B�Oz�z�;[��q���� |l;�s��y��QO������M;k��D� |l}Tt����7�4�c������o�n�����}�!�A�z���{D^z�oP����L:2}C����X]s��ez���t���v�>kHXC\�6���V����!m`
B��[;�pm���z�d3�A�)D8��p�5�k ��~�k�V��5k��0�"k �k�2�c
�&N�/vyxU��{��K�������K��w w��O�P���A�K���U�:4	�C��v�!�l;���w����;d�-r����#w�&�� �m������[�����������7�[Tc�����q��7��T}c���;�{o�$Hw��Hw���p�o��u���.'Nq���n��oI%�A���T��:d�~���I]��a�z�����AH'����t�k\��1��^�g�}=?�V~v��[��~�>����+������&zF(aj��(&i\��3�+�r�q%��*S�A�a��D�A��Vj�3�io�j�i�h��k��#�Gtg��"���>
�CT�����U�8OmD�!��P.�&DQ_�!��������EeDQo�!
�m�OTD���A�m�Wjo[�%�q���]���|wlC8�L�Jul�bd��SJ�mg;326ZNw���������
*\�T���
C6EV`FTs)���7�h8CH'�6���!�8#�j�B:��2���g0�������u�6o ��$
!��f�:!����^����c!�7���Pne�]������$��v�O����^��$��_K����IpG�@�W��D�@��Fo��8P��3h�C��v�A(�����$
�nI�����������~�J�o=#��-�����e�7��3����>N�X����|����AU���
��:�F[��F���������0N�mP�D�q-�k�@��(����G
q��d�Y}���OG��hk��T����J��{�2�������P�����F]��D#�A	���	GP����3��)o���5p+g�ap{���@
L{mi7��m�������-��r����U-�U��vx����;x��o����q�K��B��"^P�:����b}��|lq/��]����u��!�=��(����E��|l��#^P>�X�q��:M#�|��/���7�E������*�xT��8�.\O6�B�C^/��P��SF��b�W�`1E�
��e�4���
�%hI��N;�!��F�t���6�������q�K7������D|?Xdoc"��B�nI�
h��3��g�p2�L��8n�U#v��0�Q#v �k#�������?��������;P��$�*��X�g�`���Qp���n�C��v�A(����U8�A�Xg��"v>6����[Cp{d���]��b��������F����]G�����P^p^�;b��u�zZ��:2Fs�������#�E;��!��@�J}W�	�J:0�3-��AH����;�I�����&"z���qKz�yD�Uz������?k:T2�z�~��4s`�����t�d�!�@�l) z����������j��w�@�UOM���K���C��d�pr���F�U�:%3����CQ���a����������EeDD����C�\G2���=F��������oz>6SP�|�qZN�>vk��8O�}�J��z��9R��@/h���e<P��$u��%�4�2h���� �����F� �A?�!-
�!.�H�t�>iHo#����ejIa�����H�������Oo�������������������l��o��I�+O'��������������/o��$~���\v���jK>���r�>�Q��x����{9=������������o�����������r����qrx���>�G�]T�\F����������D}��U����pW�:���+�������=N~!2zl~��N��FUQ��2�=7��/������Q|���h��B���8vn�<NN=��6z*�o�q��uB}���G-��?�����������L�y��o�"b��n�A!]���B��6���B�^���r��c�;������O�_9�-&��^7��	���W��1cB�=7�qt1!�^����h?�x[�aL(�]���������%��D}����O:��������:����������U���!���^H�����Kg#�����q��EFf,��tGg��R�2/wti��n��tS
�`\z���������RX>	P�rb���kx=�&��Y��q;�k5���5W�!�v�	Dv$�T��	2����#A��4�g0d���~�f$����
+�"�H�[|a|��H��/,��� �����"A��t�!����3�E��U���HP���i�H��"c�5D����!�7,0�E�������N�	�[dT�H�o�����0i'\��Zs=�"A���`���5<p�]����:���i��kfo�!7{ 0L�+.�=K8��C�[��]tH�����.:$�K�kw���=�����%��Cj���atH�_�J :�;���U0:����0:����M���-��Cy���t!:����^<v����E��P�"���C��sg�!F�T}������n����qB%]�Z|��+�z7�B&�����M,��}1��z��s���o�|��gI~��@/��b@Ht���. $�1\H����. $�k#9�����eR�[)a�3h�l���W����/��
By��}�! ��. �V1��[d�q��P�����P�"cd��_1 �h[����P��z �!�T&������
i��q�b��B��z�v��s��t��F>��cw��C������l����_��T��H�@�h;aIh���u�&�^-
�@��{a����q�Wi����=L��f�WK30��[�}�E��1'�\����9��q��@��P]�)/T �~���bNz�����S\(�����r�]7jY�Q�������F���0��I\T���O!]�������AI��b���!M�b���(~�`/�v�HUCD�i���i�����������(����w��Inq+�
�C��x����!:��[cO1:�����v���-�����S&��C}�����"��Bt�������I�=�|"�n��`��Q�,��
"Bu^�$"B����PIF�3i�{���h����,j��
�
*�������D2-���Cl(4F�D��=t� ��E�D{iP�.$�k�;i
R{?���&F���s�X����was��A��q�hP�C�Ay��r��V�l^��1��(
��"������'�Az���s�I
��T�h����!_
�Mu �P���������i.(fQV����
����q;�����R�'S����N�n��S5�� �v�F
���%�����U�P�Z|��!(�����^����3���a!�;���_�������F�a��Q��0|����Z�O��E�(��Y��z��.,�_<>��N�9�����������?Wv�"�T+,<LH��0�$L� av��� ��������u,���:���1����!���D{�McpH����o���������w}
RR�/�f�'�g0���o���y���I��. ���o{��bL@��P�"����{�����p�sg1 �������B��3��w�[d4����nj�������- $���\���p�
��&���
N��2���_��t�~N���5,��k���G��[����*����M��O]�I�c���������3��F��.��w�@va&U��}f��D{�c7�����qz�`�)oQ�;R�;�\ ��6���Lz���c3�-2>�c�)n��z1����Y�a&����0�3�y1�a ���)�V���(-�$�[c�-����03,<�J���9��K$&���9RsT��q�m��V���-�@����L���q �~~9+~-�8��{��C�-nu��8��/��m�!�;���v?-Q���E1����a!���c�8P�"�m��E����nz�H1�E��g~�Rms��W}���N'|���F�?+�z�6�-+�@��tKN��A���[<���3���D&]�:�Ou���1u���>?3���=��$�w� �v�Et� �����������3����ck��9t
�A�>7JE�xP�"��=�-+����@<Ho�Q0����E�nb<H-�����Aq��]��x��oC���y���tS����e*L:2uE���\��9�����
,WCC$�>	f�F��Y;c.���;CV�n($��B��t����6yb�b��� ���������~."S��E�k����q��`0H��F:D�[�����(R��� �E���]0(n���Aq����]0Ho���Gb��3�����5�@0H75���Gb&mP%@�b����-�k�7��Lma ���>��a���1�(�/�3b���Z�0�X8H��Q"]8H�c����cl�Z|�`8H����L��9k�p��/�V��[����[Tdl
��'�A8(oQ���<���mA��{���O�-J��Q~�����y��`8H75�3��#V�t�Wb���o�B����e2i's��T80bE��4�F�q�������{��I%��u��q��}��������6�����?mT^E����KJMT�0��$��H�����L�����+�8�n���b��gNX�A,U_%A]K�7N4�T}�4�� V�=��(�	b���
wA,�C�h�{�3��n|u�BX��u����b7�����CSZ�
�:��C�C�6�>nS�@?n.\��i���p�����hz0*�@Fn�z�����=�����q���e���k(����3��T���P�j�BA��6X	��������p���B��i�:`o��&S�"N�,�jG�}n�kC((�#�vF����H��N��
�;4wh��������P��P�����'��O�����lds����!�v"�o�)����Hit���k`����1o��m��q���n!�17����/��B���8DCD�=7����h;�C��h?�������gNGC�n:
�!D����4{��Pwf��C��}*O�p�����#���N�E�����LK�}�OA����}�����E���z����8�u+~�����1r��O���>T������5C�(��1R��C��6D�B�^�}��u`��qwNxi?w/��?wU����t�u����D{���H��j�.|$�O�X��|~�&��k�C��#I��Keb$I��N���$=83��0F�?�Z�a8Ir�P��0��rF�@$I�����$��Z��#��}]8;���p��WwI��U�v�H���Hr�$�_��$�t�B
�rT������K
i#�rj��y���4���!���.��$�����_B�d���E��%����?],I���W�������?�?��H>BT�6F�`PI�7N��A%=A3�aP��;��������BA%�^o�.��w�H=��rr_W��
�J�����]PI��V������_E���t��H2.�"I!��$��I��/S�X��S�NP���!���Q2����u������	 � *���_�O�����j�A]|J��y5��X|J������S9���)g�XT���h��(U�8EA�R��1����vt��C��s�?��'Y���@�)���G\���&��S�f=#��9��'�t1��CF~�PXC��2��?I���������[����xSH���.<m���F��oSvNP�����p��M��W��	��C���3�B��t�M���6r>�����~���9��X�HbC���tg�4�������
cC}���-6�V�T���TO���_'�q'������E�f�jg��'��!$����$7��)z`�J��|I&m�J�HQ���!z��t=�2���2��L�
�����h��l����������
endstream
endobj
36
0
obj
54701
endobj
37
0
obj
[
]
endobj
38
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
39
0
R
/Resources
40
0
R
/Annots
42
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
39
0
obj
<<
/Filter
/FlateDecode
/Length
41
0
R
>>
stream
x�����%���WC�F"�2�n�t*n�1 
"$� ����7�����ak�/3��}9}p�d�,���f�/������������iO���~�/?����W���<|��e��dU����`����i���a����e���!������t@�q����<����yN��B���S��?�_��?��?��O������?Oy�D�'e�i(�)�e=3q�a���g�������2�`���	N��[�}�M�����[����O����:�:s�(�&�,�w�a�-��q��`���	N��[��C�������[�������z�:s�(�&����	�I�<�q��`���	N��[�}�(�w�a�-��q��`���	N��[�}�I�����[����O����:�:s�(�&��d�	�I�<�e��%'t8u�nQ��c����3��g��<�\����z�:s�(�&�I�����W���S�da�����-��	I�/����q\�)X�0qB�Sg�e��M�/����8.�6	������E�7a�p��y|`�}
�,L������E�?�e�p�	f�-�.��A@�f�����-��	��^�����SX$�B�Sg�e��U�/,���q\�)X�0qB�Sg�e��,������8.���^�p�����B$p��t��%>0#H�L������E�7a�p��y|`�}
��^�p�������H8���<>0��>�E�/t8u�nQ�MX%��r�e��%'t8u�nQ�M�xa=����O!K8�����-��!���N0�ny��f���z�:s�(�&Lxa8����Oa�p�N��[�}��^������SHx���3w��o�&���y|`�}
�,L������E�7a�p��y|`�}
��^�p������6J8�3��g����  Y3qB�Sg�e��Y�/����q\�)�x���3w��oB�p��y|`�}
I�/t8u�nQ�M�$�B:����O����:�:s�(�&�xa;����Oa�p�N��[��C���N0�nyv���5'�8u�nQ�M�%��x�e��,��:�:s�(�&�xa>����Oa�p�N��[�}��^X�����S�da�����-��!���N0�ny��f���z�:s�(�&Lxa8����Oa�p����F�^n�����	S�oW�r��vG�����-�>�5I���t�v��[�}�8r/t8u�nA�!�U�����������C�da�����-��!,��U�wL��1���!0���	]N��[�}S��8a���*s� ��,�qB�Sg�d��K��0u�v��[�}�.�wB�Sg�d�6H���t�v��[�}� �wB�Sg�d�>J���u�v��[�}�,L�������7a�:�N0�ny���o�5'�8u�nA�!����	cg]_e�d�<Ky����������������}i��;���3w�aK�}'�����}[��;���3w�a_%�N�N�r\�!X�0qB�Sg�d��i���	f�-�q\�M@�f�����-�>�Y�/���8.�f	���������$��|���!I8�����-�>�,���y|��>K&N�p������08�L��1���	H�L��������0I8���<>�e�$��:�:s� �	�0�����CX$�B�Sg�d�*������}��^�p�����C�xa=��q���%�B�Sg�d��e�p�	f�-O�����8���3w�a�p��y|��>�I�/t8u�nA�!,xa:��q���H8�����-�>�U�/,��8.�V	���������K8���<>�e�%'t8u�nA�MH��N0�ny���o�5'�8u�nA�!�xa<��q��0K8�����-�>�$������}I�/t8u�nA�!lx!�����C�$�B�Sg�d�.������}��^�p��������8�L���%>�$k&N�q�����C�%��x���a�p�N��[�}I�/���8.���^�p�����C�$�B:��q���I8�����-��	� ����[�M�pL@�f�����-�>�I�/��8.�,Y�8���3w�a�p��y|��>�E�/t8u�nA�!�xa9��q���J8�����-�>�,������}Y�/t8u�nA�M���N0�ny�����d��	=N��[�}��^��p\�!X�0qB�Sg�d�"������}��^�p�����CX%��r���a�p�N��[�}Y�/���8.���^�p��������8�L����c�5'�8u�nA�!�xa<��q��`���	N��[�}I�/���8.���^�p�����C�$�B:��q���I8�����-�>�]�/l��8.�v	�������?�4�u8��t��K|�!0���	]N��[�}�*�q�x�������:�:s� ��&�w�|���!m�}'t8u�nA�!lY���t���a��}'t8u�nA�!��d�	�i|@��>�}��;���3w�o�8�����[�}���u|�d��	=N��[�}�(�q�t�������:�:s� ��I����4> �e�:I����������g�������}y��;���3w�o�4�����[�<Kyr0Y3qB�Sg�d�$�������}r�a t8u�nA�!��0qB�^�*s� ����@�p�����CX%�B�^�*s� ����@�p�����C�x�w�a��[�}r�a t8u�nA�M�	�0��5�2w�o�,z������u�q���}]�!�?��Mi��?�^�q��}�n�V����?r����o%�>7����+��a��� ����O�Z��Ge�e���Q%���0qBA����G����?~�������!p`��|�?
��A�?����g@Kj�����0qB@������L��
*@��	�������~$;x]lf}3q�9�s-��R��g@C��I
��v��$i��K#C��X���D�j�1a�;X����Y�P���5~Vm����v���M�&N����9��b�,q�H2����������1G��9_$�@@2'��K������yj����	}j9ma6H2� f��v5��5^�!`c����@��	���q��5q*�����6F��8�Y�`��D`�]�"�eoM���alNL���0qBP��a�:�f
07i]���!Hy9c�U��e���c]e�X����;�8a]]y��X^N������8!`Fu�	��yf�b��	���������/�0'xf#���7*��zQIL�PP/�S���l\A��P���3������z�z������7�f���j�V��.�'���68Yq�W�z����������&3G�g����L�0���SU1K��-��M���@�a��������$�,5'�r�ag���a��$��/9L��p�9Cs��L��8A�,aW5��j�A��	L�0qBP���`�������	|�a�c!*">����������	��E���X��[T����	g�6����0�B9a��0q�P}7j8�`����yZ�2'�+1�yf����	u�O+�C?����2'�����bV�?�'�����_�$ f���m��o�]�^GY��0�x���}x��M!��
�r�r���{�&m
'H/�s/?m+�v.f�	N����8A��=[�������0'�+�O�v��$�,�����
f.,��fcc����A����?#a�m��&	&N�R��g�1Y���d���>��5����!�-�eo���h���I�S���0qB��]��I;C�CN��|U7�g�A&��~�PL������3� ��1!a&N(����99OB�R8�8AJ[����L	�|�d��	A�6+��Q11�;���<�,�0*g�zgO1'�[3�	�����4'����
�b��p�
F�4- ��!���r����
�&
'�UL^�����q�tw~��L�P��^����	�~�y���2'��s��ao�<	;K1a�a��j��cCC�L��D�9|��?H{C0L���7������!���eor�=��st�2����	`�cCh�8
�8H
�IKC���f�_��o��=e�Qd������8a*�������@�I�YHf�A__������Y�'L��8������d��	�i7*��Qw�Y���������P������kc�W��������I��zv�cS���y�[9{�&N(����"�(�<�
h�E��M�L�P���'<O�RL�8A��__9�����C�L�P���z��LPom&	&Nx��9�����C�L�p���i��]Z�-]���{�e����?&�'<Z���=�|�����aN��q��i �K�0qB�`���sj�=��C�L� ��\�F���#����:o�p�>p X�0qB]�g3���#z�F��mU���8���	��#��4.�/l&N�4.�l����!���0qB�0��P�c@v��
(3qB�.#dd#��������&N���`�s��N:���	5<�{����R����8@0q�����(�����]�&N�=��K�r��N6&��
A8��o�M����r�C�0q��>/��/�����d��	��b������&N���[v�����
����BJ�s��1�`��N!��ew9�T&L�P�t�e�
b`Cj�T�il?8�l�[���z�#Jv��;��]���f�3����L�cmI��Jt�W%����	����ZE�������C@�f�������n�� �jQ����=Y���K{���8�z{r���(PM dc!j���i��9<d3�=QO'�V�a�����+	d��j��t�! ���`,�8�<��D8F��N&N�<��1 ��}�����B����+��]�&Nx�m9d{�����P��\�y(�7iY~��B�e1���M���V���L� Oa��H����B�L�PP/��pD�d�I�Y
'��km������L� ����69n��`������JA�T�O�b&N������42f	@wid�8�rQ1���1�����
����a)t{lB�=@^�<�� �q���,L�Pp���p�=:d��j������C�	���z/� ��"�t1'�^�]�Q�����,�
'��u7���I�B0L��hGb���~��26!
�#�	f���3*��M��@�a��������I�YJh&N�"G�_����t�J�����?H���a�� �j&N���d�R�&e&N��=��p�h��K�>�B�i9���I���d��	�����d�tsh��2���L
A��nFw��P��dk��7}�;�rCx���	5����9Ze�
Qf���c���pl��$'t8e����c���='_)I��!�
��!H��
&{���C��$\�a&N(�g���^m�	2^��5�&����'�g)%L�P���3�� �`@��=��P�O���dcx�>��k=��P����r��B��	R��?��K3C����jf�L#s��
1�cCx�wsz�
1�o��0q��v�� ;a�B9�����8a��k\�El��&�j��!���@�����$dp���8�&_�F8�s{&����!�t]��A�n���Boz�p��m@L�L� ��bH��]!���eo��q��fp �.��!��5�p��.R7i;�8��k��8�d��](�*/���zeL������7`��	���8�l�
�%��"3q�P����%|�1��f�
A���FW�9,e�Yf��N!9�d?9�4!L�p���g�9:�8�%a��N!9�d39��$L��������P8�U&N0���@����D�&NPj���<	'Ka��	Q�N��F���ME�&N8�F�Tu8�����zu�1+���1��&N(9�/gA<�.�iPf��^9de�8&0�}�)��;��4�	`�����o����Lw��p	��8a�6��;3���9��3��_l
��fr�$�,������
�������^O@s�MS$������pR�������!H�����R�p���7)��m��s���&���!4��O�0�d��](��a0'L��rs\�'�s.&���!4��#�,����,������j�9�d{If���e8Jd_�&�n��!xj�s(��19ve�f����'��]��gX����7���|��*L�Pw��
�V���m!�r��!<<�m�/���.�s�j0',�"�/� c�02^�5��l]����<	3K�`�aF�8��9a��[$Y3q��Z-6�(�&�M�Ef��6:������1;o�H
!h���*BwiP��a�B��nS�1!����!<���@o��x���|q���Mnw��a'�a���u7O�3��dQf��&��3�yx�r��	W
��8��YF��8��Z�� {��6�^������:�	��h�q#5�&:]��"(�win�8���!{�����8���h?�he��p�wa�����������x6GxD&Nv�_q�8O�RF3q���^	6�2\�"���	�Bw��1�����d&N�P��[9@s$�[����J���]��0��	V5��F\`hH��Xh��+(������M�xw��>����A6���r2��f���oo�P���l�#�L�P@��`�do�Y�'��S5g��ynx��8�Y��7	�1q��<�`�a�]��iA��
������`ssv0�.�
�x,{C�w�3#��:d� !����"H�&�
����
����q�6�6��PN���L�0�E��	A�T![	1'xjx;1'�Hf����	���3�l�B�_Y��9B6't�8�.��A��a&N����~O�.-�,{Cf�#"8�d ����p��r���?27iD�8��@�����������I��	�ss�����@�B�����X��~�g)L� �lF����P�elWJM`c�]~@��	Mv��$�u��8���	Mx�>�wif�Ce�B��q����]y�B��-cC��e��IF�z���L���
q�wZG�&^��5��y���yp����	mpt3=���/nBP��3�8���d��k[���,m�1<�9Pe3 Qf�����#P6��K���	�����z���@��z$�cC������v��w��q��a�3��]�p���=&{�8���|��u��<	:K���	Z�s�kP�P��G�a�)���8C��G�!d^3�BP��X���������	�J�,��4�	@��.���`��6��}���5��4�	�w������������.��nu1'�W��q��}�B�]2[C(����	d��YJ'E�_�*'��G��8�S�O��Y.u�0qB]��2!���y@v����� �{�%����!����j���NN	��p�F���d�� �3��9A�7��Ic��	A���c.���w��>�f�8an��j,�8%��F�!�e&N8�wI�u���8~��z;O��RN�8�Y���F�9q��F���	����LL��1�6��!��,�8/��F�!�6��|i��
��u!�2�eoAw��s��l$c��v� ;���]a��n��AG���w��5p���8!]���nL�
���k|��P0/}��H<O�R>�8�	�}gsC��_d&N�U}r��T�@5������_�
4�CC��B�!n\��Hc~u�����oH���!�>��!\M�`n��x������#K����.S��~'����n�d�#�&�t�8�D�w�|��HN����s�qPN������	�z���@6&����8�;zpN������	���_9����M�L�p��9���>@M cc�jA9�e�$�����8AZ��g�}���.�3�62'�+oNq���&^��5�l�,��7h���\0qB�oM���"3qBA���1�
��|�I0qB��	4'���t*�8�14gC���p���7�+�������\�&NFR�JR7ie�Bin�u0��1�.�S�22'L��*k��>O��0��`#g�A�	C�G�d&N(�'���l�$5K�`�����?�`R�}�@C�JcC
��I*f������!H�����9IC�}F[C����F�-U�y��M����p�{}��	u���E���ZD����n<�C��) ��7_�0��Hr��t�;0M�p�J�ej^��W�,sC�C�#E�<�$�95�N3N�t�i������.���b�U��<J���7�N!�Q���6�$)L� ���}w_d��](�]/',��@^uQ��eCw%�x����8�f���.�S99��$�,e��j��������nZ���	Mx�����6�&�q��kk��a^��,����v4��*5aVS��	g���e���z=[a��`��l@��!�zm��C���Iw����Y�8AJ����Y���T6#��	���O��<<����7�K���9�<mORP�8�Y��S�ye�]('k��f&NX�M���b��+~������'V�97��j���	���8p9��K������,���
xi�iW6W�
����
!��1!�@�U��4nnuE_^�����I�&N�6>��������X�K���|m�q,�1�A�k]`�8���.��M���$��7A���(����E�K��i��j���
��
.���27��������00�!Y895���n��&��%'<����4]���`���3c����6�&)L�P8^50��C�S	w�>pp1���	0qa����>p���S��.�>�P��&N��?���'�f)�a�-�����L'�}�n�W���Nz09�@�]`��������~�V���%O�V=L��j������,|�"��'����V�Y��u���	������W�
��IXi�p��s=�Q�E�K�e��	����2N^��WIv�C���p��w:��_XTeA�
�(}�Q7�D�@�a��������������Nt�8�3�5z0����&�$=L��������:�P:5\j&N.�b�k�O�
�w�n
�C[�*����NA�R2�8�������_�����
�	n�-�����px%��j��s3��2������2L�P�O^���������tj�8����g���y���e�����uw���a�4	$�
�;�J�0�]�.u���.����yj^��
�n��p�ph�.K�,�������g��GA0L��,p��M�����+�8A��iGwf��	<I9a��
���������v��q��>k�C���f���>:t��[��mMco��B�n-��3t����0q�C���;�t�X`-2'�������p�7����
�	o�����mu���a��GN�w�>�/��0q�#�]x<#������4qBA��%��*}"�^�@��k���{Y���=�&NJO�t|F��P�*�enB���Yz� �`Y���!\nOz9�n�� &N��������:+i����~s������!��L}��J7�����	Ku������e?�4~�s���L�S�j,@f���|�����'!g)"L�P�O
t)��F�!�>��!������R������<7i��+
il:[�%il�8�`��-�������:H:7L� ��;d�Y��u�h�����o�=2��?�����z�~�,��"����4qB]��'�x_U�>�W��UX��:�J�qp8���c�F��|��_@9�L�}�	�0q��a��ij��
'4}����cito������:x�+�C���f���:_g?m��i�.����o�
���o
�`����m��'af)L�P����<��l���
��������\
�&����!H]����#��b��{k�M���A�[Y���^'<��t�������4q��"�i~��I{C�'��e�R�`�8A*��c��yx^���
�z���-�s�
��B]�~������{��@0qB�WG��M�N����`��f;����}���>y}�Kq}�a�3�x����>yM�	$&N(�6C�?�g�`�,3'HI��^�����	6����	�zG|����ae&N�i�Z�;���M�L���[��O��;��HX�H�6'<��oc�u�Z&Nh���b�9�^	��IPi�Q���"����0qBD=�OF�c�������������I�#�7id3q�����\��~	�id3q����1x����f��6<��F�3~�\�](]�+0'&W�Q:��M�dK�T��
v�ss���'�f) L�p���a����@Y�d&N��Kz���>�07)��;��4*��-��4*L�P�����S��GX�H_���-�8�4n�^a�u�i���/�,��K�I io�U���U8��P4qB]����-=��!+���`���{�f�`(�8A
~ug��AX�H���	��1Wnt0�N����&N��c�+b���H���q��a�rx�L�0W�}�>�G6=�-L��[C��g7i��:O��RJ�8A��o���p:",Xa����/~�#���&����!����ht;����II�&Nx��t;wt���Z�.'��n�&�u�Z�&Nhv���}��3a�2	+�
�����EOd�e�R�m�8��bcyx^�Wa-sC�4����Qb����SC�nV�ty���cA�da��Gk�.���)bm$&N����8iN�2��	-��k��U�S}�!�/���Ru���O\`��wP(3qB���B�V_@QP�&N����k����	�<��A��f����	_W�uAL����`+�tt�-���	u�|������]�'���aW����������j��- ����_��7������Q��"����4q��n]�0c�U�y�27�;X�����I:�rjWg���u��� 0q�P+_�J_�w��K�L�p�t�dFM�P�&N�4o��i^g�n���m���P�>��d&N�ZW.tK������ ��
t��N���K5H�����	�u�S���(�&���!��|�x1�t>��D��	���>��MIP��B�!�%>��F�R_�Q����4q�t��U]K}���J{C�Z��O���(�K��i���8n�k_fa�U�y�27���r7�I�S_�Q rj3��7I������ &Nf���C�S��Q$��
�b}���7j�$E����g�H���j����;L�`&�=���Nt$�����@�a���+.��1�$�,�3'(��y
�$���aI�H����Z��u��28��,3q��O���kh�5[T%iS3qB��g�n�o�@1'D=)�6*�=��(XQ�=	&N����CgY���=	&N���bb_fa�U�y�2�B���mN'�5DVN�p�1�"��I23q��n[8�Yb�.d!�R�'_��a��	:I���	�F|�?;?.����C�������qf���>�]N��r�8�:���s��!5OB�R�8���~�)���m2>J76��|��-��_�f�����
�F�����-@������Pu�����>��B����o��B]����	uy�7��K.�8ioM���=��E�K��i���uM�&\��W�,sC����
L�:�����B{r,���eA�&�&N�X6�.��L@�{C�:!nK.� 5I�`��11?1�1C�G~�������|9�th&N8L�M��S������&����!�����I����&Nh��d���yX�,�2'�t�	}����n�[�B�G�g��TIZ&N���wDz�;��u���g��	WKZx2���P���4qBP��{�������jD�����{uY�����&N��[*H��P�*�enB���Yz}�RY���!�����(z1co�� 
&N�6Z
/v0�����>'Hy/���N����&N��\��?D�/��w��~x��L���[N?������C�K�[C(���t��'�f)!L� ���"8�+rG�5't8�r8�<��:�����(����|k���	s���e���{�\���^Rx�����7��}��r�&&N�R^���yt^�d&Nh�O>'N��uLVN
���/a�M�K&N��j�	Tz�]�/��	��]�Q�&�$E���-�TwW2�N���3���U�]����a�3����n�7`h�C�@�a�A_X��[<O�RL3q����s�(����M �0q�����5,�B �W�2'\)spc.�pt�6$3q�������l:�
���f��gg�����_����	%���f�{7=�QM $��P�
|�(�e�R�k�8A�����ev^��WA-s,����N�,����&�S,\bGw��I�2,3qB���34<��M i�c!��'�AM�P���L���`.<���u���9<el&N���'����4}�-@L�+�[C(�����g�<	3K�`����'�F��d����O(�
�I�����36���M��sCh6r�=�����K��0q�����;��W��L:7L��d��G�:|�N'����L�',�A��!S�s������r��h��f��W"���'a����SC��{�q��MZ�8�B��
��J��a�4	d�BP�����	5I�`���y�q}y�~���{��&���������c6��-UL���[C������!��=��'ag)&L� �b@�Fy���tGX'-B2'���P����<{l&Nh5t|��^�@���,I;��	�v�z����?���o�8�����6�C������4q�o��[2&�j��D��c��z�e�Rwk�8�=��[�
_g��
;��Z�������w��E/��QFN
�J]��5���7�Y�������CTzB���o��	�����ir����	�	�1q����aK�C���f���<��?�NK�����y��m�b���B�>��_g�<	9Ka���|��E���<Z�c&Nx���vF�?4�	|mzn5��c6����?�uY�v��jt�xx����]�C���w��	�;s��t��������_����]8D[�����|�O~�#uY�����&N�K|�Z�ex^�Wa-sCx����6}"�hYP95)������I�&Nx��t@�N����`��g���=���
�FX"�c6'��|�����tD�B1��@o
����M�����f��'!g)L� �-��^�n����jh�d��	�^��s�	�cL����f�{���`����+IK��	���Ge���`�#�&N�V���s������.{�Ny�A�~�����J{C��>�
���E�K��i��&������
:�BZ�� ���QNO�5PVN
�Y�������A�K�[C�6}pqeLz7,�����	�j;��	x���|0q�������w�p��o>L�`&�\���G�&Wvl9��|�&�yv�2���}����N.
��'��~�Ag'���z�����}����������	�x����s��C2'�deZx@�8���.4L���\D[���;B�1���=.����������8A����U���Yn��L��7t�n�F2�4��8����<����.�S3^6'����W�9��
��-D7�Oo
���j�,k�<	5K	a��f�O]��+�EXf��~�O�s��1��`<7����I6��2��|��5)��y���4���tm�8�������$k�u�Z�&N����ep8
ce0I�io�"F3$'Z#/������	��m,��Y�yx^���
�J���@�m�4>W�Bn���S��z�N'\���b��l�?,����	����-�6')#L�P���s�v����7�B�����8aZ�����8��d|Ryk5�tC5=���Av�B��	5��hp�B���,3qB<T�l!nPn�&N�"�=
GW'wr�
�[ChVwx�}�\�a�P0L��D7��������u�i�i��A��P��`�iov����U�/uw��:��o��7���$��
����`����D�����S��8������	m��E�hr)��Y��pe��W��6a')#L�P����qv��O�\���\��:��l&N8L�te����?&�E��!��C]�C?=���$�,�����?��J'�U�"3qB]������3�	|�ynMv��C���l����a�_��/xt`wf�����
'4���Ty<��A�k]\�8�F���@��a%6	)�
AJ}��y��E�K��i��~��#����*��
j�B~�����,����Y�pqF��A�3�[C�T�������'\u�3j�����0qB{�rq@�������:<�l&NX�#�'�������B[�������P��S��3v�����0qB���~��;���Xx-�0'4�{�,���&����!����fN_h��$

'He�����j|�u��`���	�mO���B]�B��	��gS���1���Pio2���?F��y��4M�P���E���������*�enA;7~����������!3Gt-3}�17�[����d���.Y�s��a)&�&N
S����6�&)!L�����>�V��'��3Vdw!����	fr�M�����}5����	%��
����'!g)��8!(���Q����B'D��L�y`f����c��^F��3�	���|����6�_�JL���8A���J�f������0qB��O.��&���X�zu��yj�{L��.rc��W18��M +�X��[�gs�663q�������p@5��u��K�}�;m�NR>3q������~f��@X��6'���m~FtOW�~	d�![������P���j!5OB�R<�8�.����`�a!��L� ����
dh�t�����7y��- ��,I3��	5���R���F:$,��w��	Mx<��q���^����	Mv|f;��K%�!�����FG�/l�Ct^���F'4��)���lz%,U��rj~F9�#O�&���Go
!�����n	+�I���e:c�M�I�'���)����Y�X��x6'&v^?�U/:��|8���L���[C����j$<O�RP�8�	��C2}.����	��r�L8'c��G���0�u2���_�uR�����U��x���[�rE:6L��n��
�q�:x�M'tk�S�%cB"�
������d.�0����	�5n����Wa�UP������l���au��SC����k���7A���[Ch�r|y
������HzL���Yx7#�M�I
	'�������~<��X!�}6'�����m�@���R�>9�5�}�@���$�,e��
rg�(\������h��8A*���
h�>C������ ���V��8tw�K��0qB]����`�+!��0q�C�[�3C������4q���T���I�g��aD��g�|B$uY���}�&N���-�,��
5�Y��p��Y:��\Y 95�fg>����M��j�5���-������:K�L� �<=�Nf��	<I�`��~�|��������:�9m&N��u�-�����B��t�5��z�Y�p`������&N��WD�`v�|Y�0��	����\���
'gl����.�0�A���^����%>�X���c��)&N�"����q�A8k]H�8����5�1���������M��0
nY��=�&N��{
�e��
5�Y��P���(���.����@�{��!\�
�e�M:���5-�f�����Qz���!%��='3m�LR>�8�R��#�i�K:�B�}V�z}�8�LN�=�!r9�Yf������&��\�A�a���yi���9?���	?�~^8��h@2'�<��#��9,%`������|�Z�n����0q��O�~������:HJ{,hO;��i�,_�n'\�G�
��
<��Z�X�q]��1rY8&0��b!�h�����D�Vw�X�x.�L�0���)�z09[l�h�B��H�����0�&N(�����b�M��2>�<6��|}r&s��M���sC�U}�&���E�I&Nh9���3l�'eK���`��nw�����\����	W���VS=�
��7���=�Dh^���D'<���i�n���m!�������7�I��Brr6iO�8�[��%��Z,*@��!tJg�49iN����	����u��/�B�m�<��8a~����p|yk5��js8����,���
p��+/@��w���P���/D���� ��	�63=�\|8��<l
��v���1/#7^'H�:;�;n�^A�uqi������'r�@J{C���B�aN^����D'-�}�P:�������A[8����MZ&Nxp��Dn�X��~�Y��&�$��.[���{�����w���	�������>���G���P�;�j�V��'af)L���g���t<Xb,1'4��q$���zn_R�B
?Y���d�[�$i`�8�&�l �o�������k�8�&�~+����A�k]l�8���l�)�������������h��r�,_�^N'H��~�XfA�U�y�27�`X�7�J��UPHN
��dR���J�`��$�	&N����������������tX��
O�&N0�k�8��	�
�A��Jr������yj����j��0��2Xq�8A���;P$�1�2'�����7��$I��~�gt��+��f��_�KF�:z��
'D]���Lz�&A�=�������e�Rwl�8��.�{�(p�Z�X�"������9M@�f����Z������=��$���M�I�d&Nh�dx���~?�J?�[�l~���R�Llv�v3�yr|�
J��������'|�X����	ps
��S�#�s,���c672<������y�|zW/&��M��#B�5
A�k��#���^�r�#����o�
�`lx��%��Q���0
uY�����A�GK�I��
;��Z�X�G?k��`8���b!���/ZF�0*��]�X����@1&x��&�$�NB�Khw�s���M�(��8<dk&N�����O�`�
YLn��B�����<O�R>�8���jP���Xb&N�9�_L�bPx���gs�����
��<��H��0q�e*=�qj�����Pa���Sg���9aw�}h���������,B]��C'tJ���8yN^%�en�f�b�>�X\�M
�[��#x�&�M��@�5�N��A����]`������
FM�P�&N�'�����24���{�N[P���g��	���%=�A����>y�5��|�{T�!�'�g)%L�p����h����0�O��
�F�^P�y�`sf�5E�:��
���b��s��X�K������O\&���\����	��.��8�w�����������Wa��#��	�P�����-����rj����n�M���Bs���q�Mg��~��7��g���	5Ia������~?�XL����������x�������i����.������I�Y�	'4�'������!���!p������	�cL����<�l�aT:$ic�8������r���� ��
'4����"��A�k]p�8!��x���9�X� ioW��P�E�K��i���+p�*��J����A�{?���a����SC�~#'|����N[C��g����h�;�B�K��	����Q�&�$������Q���X�](<b���������6c����z"'��������[�*:O��R:3q�������z0M �0q���'z49QO�!d&N�������z���	W��M��[�0'D�p�-��'t�
'(4��g:79P�d�A����Q9���k@��	��q>����$�43qBT��eZyX���.���65'�I���(9���n�!�Y��!�����8��!o��&N(����s��T�0�5g09�M�	|;unR������J�y]Ny@s���� ��	�"r����fD�����]���4�.9�M�Z�&Nh�O�B�)O�o�������b
����,ug��db���6�yv^��
�f�|x��d��A���SSC������l�� ����!������t\�����	�v\�*9Ox���	�7��#Or8�.��
������n�Y��u�!����!����^prbd|�tlB���d�9�L�P���%4]��Y	&N��g�%�[����C�H0q�����-v�{���d�5�rFQ��4���;�K��h������y^����WA,sCf����(�}9��dsj��^������&N���V����uB��	5vE���;�I�'\-k1�����P�<Nf&NX��|13�?������R��j��n2,S@���M�k�f���|����w�;Qf�����\�G�������B��P����z9�4��9l
A
.�9�nF,Y�8���T�9�N�Z��&N��Gy�\N�&��J{Ch����Ud/����/��	A_��� 5�B��@��!<���gr~d|!45�vW.|�Z��B�i�C�K����'�+4x��������&�e��!&v���1L����2��
����9�8�F��w�t~�9�#�_�d&N���(�����oh�J��
t��p:?���m����a���
�~�^;�q��70qBP����� ��.0M�P��,�l������?�����j��{��(�e�Rwl�8A*;������$��
�r�r�5�&�
��an
��������06�D���0q�/q��[2�&�$������3�Y����bQ��y���	fn��3�����d'��v���Lx���Lf�-���-������D&N����JH���C������/_�8}�B�L�����D���%3q��E.|��?'|��'\�Y����`�@D�c�]���':9�N�R�j�8����g1x^�Wa-s,D��A�������;!9�Bg�,<��}'g��d&N�^:�.9�	��{,�JG%���IR3qB4Pz����~���l�������8ax�2������
�/in
A�'���u�'Ag)%L�P��o6^������j���N�c �����97�[n��pt����-��!\h�����n��Fz9L��l����q�:z��M'���#�����x�N�B������|��8M�p���Ql���W!�U@��
r�Wl:3���_�L
�������I���6���-�_��	�dL@�{C�K�����qL��	�C�[�f��y8GW�{��p�'[����.��P��
������yt�b��	���j}�)\�������	|�rl:����t��9�*(I]��	u�g�,��%�b�?��5`1"]&N���V8�{�������}��a���&�����P�#?:���"YjL��FG��S���*��
�L�t������;`���SCh8~�����7�b�(��|������-���	�uo��-,��N����&NxhD�g�^�����!�}H3q�ar������1`��3qBA}lecp,d�/D�
�9<P���pG�4�D�
�.pwwU�o0=�-WL�;������_�b��a� �
&N�Vq���\a�uIi��S�wN?���$,3qBNvn���"����4q�Tv�9yN^%�en�A;�,�����,��B���o4�I����"���.o���X4]�����7����K1h���x0q���p*���������M?�8a{��&�A����2'��M�r���0�&N��F��T���
�oT�
!��w2�J�cK�$�'�-{z�
��q�n�U0qB���s��r��:�n\�8���\L�F���e�R�`��~�
~�!5�B��@��	B��O������?K�95�����n�m�Vw_�8�S:���3<"|�50q���q7j����00qBw����������'�&N����i��^��/Xw'<����>?�|���e9�;��<	:K1'Th�I��-���9�"����]�X��
_R��'�0q�Tz
9�!r�8!��B�!�p�%`��\�-���Ko��S�!y����f�������j�cl����|�J{((���i��E�K����	g�+8BJj^��W�,s(���wi&��jXTdA�
�R����I�:B'���QRP�m��

���BwJ����'8�����/3q�x�����(�G}A������������'!��(��	5��Z�����!����!lmZ:�����c���B�C�Q�I@�/9l
�������)@B'H���~������u�i��f���;~G6�t,��)�
�=d:���e�R�[�8��u�~���Wa�U��fx6K���^�P rjN��$^_!@8�w��
�b%����6a&��0qB�;��FrB�C���-�6�ONn
an��/���^_ P���:�8�`�bdN���dB���cC��M�S}m!0qB���J���k���W��!4��-D���{�C��	�u�b�7�:{��M'
�y��L:�����������
��u��4M���\�OZfA�U�y�27A�����sa�al|d25�����S�� 	&N����5N���9	&NzX�Wq,9�{�\���I3qBrG�������o �������<	5K�`������#���o(f�����[
*\P}�!0q�P���q�o�+�,L�Pp.}U�;��@J�'\k����7��.0M��,pxwA�;o�n��
P�B�I�Q_Pp�����	��6G/���*��
k�B�I�5�1�Z��
DN
�]`�8����Io���2��p��Ca%cl�������
�bU�]���$�����'����}������!��0q�ar}����{�u�	`��
����8yN�2��	u!O�a�kh�5,r!���~��"�]��w3�	|�sn5���8z��Lg��$
'<V��ewt�����
'�����
�f�u�Z��&Nx���v��������� ��mi,|���E�K��i��K����P��*��
k��Lj�F?�uNHN
�.��;�ts����A����|������`�bu%}&NhO��K3N����(0q��zu�ZL-�k/�cYuF��y�8�L.{`x4�G>�:�@�a�e����:O��RJ3qB����3&�VX� 'HqO����������8A�'��2�����4��8AK}����S��
(3qB��EJ�M�� ��.4L��UE@������#���IPi�����l*���E�K��a��`T��-�P�*��
d�c!��8C���a!��S,(���7IW��3�&]�L�pq�*����0J2��u����H�f��	5I���	'�|���	]����C��f����
�o$�������
��=��?��M�����5���K��H����&N���^���px���gM��P��AC�X�j���d����kj&N���� ��^5�� 5~��o��Kz7L�P���X�����B^�R��	R�k�s���34���j��[��Q��"����4qB�;�[��*��
i����z����3&���B���
��1�B�7�c0qBP���d������?���6a&)L����EWw?\8C,�o�����q�p�Fw��m1d�{�B}�� �yx�b��	��n0��[a&Nf�M�n�8p|�1�/��
�Y���)@���R/I���	�Z�W�Z�<�����	����|��E���� �h�=,�&!��!<Zn:5�/����7��	Mx|q����*��
j�B���u?]����R,'�������QB7�a�����=L�T9CC��aA&=&N���J2�&�$��������9-�+z�\;
�����p���p�������8�0yx�&���62���n
��w"���3O��R>�8�Y�h�Y��4��c����	5�t�DglxDc��W_��Tu����&]�-�4/L�0���ttwj�
��
'�{t���n��� ��.0M�P��/�^� �b6	(�
�&���R�8C/����W��	�q����Wa�U�������T�>,��@rj���}�_A��cA0L�p���� ����aII������^e�^��l+�C����a�3���'xc�I�YPf����'�b���~@9�cI��0q���7���(3q���>�r�?�t�J��f����;�n�Y�,Hr�0'����� ��.)L��`��������$��������Tn�e�R�b�8���TL������*�e��G�������HTN�����J�s��7�X&�e&N�5.'�����qL`���9��FO�����L������b����[��bY4��Z3q�p��[��J�g��	| wk�]��OY�h�����&N��W"$��k�EPf�_����&\�1M���sC��{�:Q��6]��{�44L��-����,\���a���]�phF]��uIi���S�W}�9�l���-�I}�E��u��d�\�?`���mD��j���Tz��F���I���	AM�~��~���'A�{C������K1r����p0qBM�mF�]�~7�4��w�tAx�L�0]�& �C�����5H2'4����p)r��Y
	'�K|�-<���4>�;6�v����t+r��&�]��!��oHt(r���8��5��{:����(X�0qB�Q����u�� �E��7�v���gY�����&N��M���
5�Y�����'����"+����o��6an�{ ����!t���Bn��]��PW��?����3HNR �8�������3�B9����0q�r��1U���f���	�.g��������!����!4�'��	��.7h�'Hu��-gh�.x��L� ��|Z��\P,r_X0qB
?��5�� ��.8M�p�?�Cn� io��:�Q��"����4qB�+~C.� '���27i���c����D��.�&�Q7�C����<�7��1F�J�Z���iV���M8I�'\���;�
��P.f����8a��E����B��tlrIf��}����'�f)L� �zE �tlr!Qf�)q�l���
rL���sC��xz�^K�������j��Q�&�q'xj�Ca���BB���4qB���<��9��ud��!\��b2�+@���mSC�9|�h�j�d/7UL|�vkR����p*��*���7�K�����&�$��:�g��{���(a�������rp�9��s�����:L�P���t��I�YJh&N���SI�r��Zb�a���������`�C�L�p��9�T����I��f�)���H�.<�����	Z���q�:g��'���h�7*�3F5������������{�{1L���������yx^����p�#N����a}��S,<\dz3�o��L������L�up�����>e&N�����9 �M�I
d&N��??�������?_c����~�U����������������}�?s*������\���������0W�3�>
K���?���!U�3����u���G)?��J��g�2�I��j?_U�!9��>�����������������?���������c�}���a���m������X������_��?��o~��~�������cIn��}]�1L��>���>�����O?�����������������D��c�~��_��#��O!,�{i���G��?�����K��g�|y*�}��������O�<����/��f�Q==�������5�����t��?FN7��~��#�_�L}�{��H����{.�uhh��ll�����Ck�>�Q'�//t�1�{/�������?��N������v��I����k���������u>
�I���3��|�4l���Q���)}������o>������sI�H?�_�N�#��'����?�S?�_�Mz����I��t��Y3>�tNgu���I�gu�t�������������e>#�u�&���F���l�#h���\U�A�w������� �o���
Ac������A�i���z�6�o��4�����>��Ac�q�A�����\�����2Pl���u^������@�9����@1N��~,�/��?_X]WAc<������
���������x����{4��J������oI?�A���.��wWH46�~:�*��F�����Y]?��Ac#��������d�R�.Y4����1����=�I�
�����1H��������1H���:y2 -���f=��46���Qe����g�>��Ac�q~��/|id���MAc���/�]�a��)h����.���������h�_���2PS����<������o�[7�_>s�l���bX1�|L�������e����(�;�"Pl$�tP^�����AsJ��1����_=�����Q�wD�oN:��{N����qBT���#��t����w��s���0��R���%m��i���_+C�(�/����!h�������(e���+?�o��0������ODE�����=���E������|2R)����������;�=����U�O���;�=���3C=�q��;�1���p�����>_+E��j����[���5��_��qg��_/|$.��V�?�����s+���u�?��:[I?"�|{�u��~��*?O��~�h�=��G���z���	~�M��W�K�D�w����]2��g�\��0H��]��o�eP����Y>��*(���x���%����������/��+��0��^�mV��a�����r��+C��7������=�e�����D�X1Z�>�M�������:)~�>o����m-�������)��c��R��y���I�������
��_+�:y���"nl$�|H����(��F�������;��w�t5�;i~�|w�0n��4��O��D�Nqc��w�����b���qc���&�*n����x��O������F���������z)*-�������w�2n�0���QP��������"nk����U�����_>�qc8��z����v���A7�-����*nl�����Vqc����m��)��A���g�qcX�o������'������GF������C��B�����XD����"rl$��34?��	����G���)|�����Q�o���u�:J�]��i����34��}�'�2|S���'�gO��c�q~ya+W>^Z�8x����52����r��=���u8�~!�"|<m���>6Z����U������~���0���������:�����i%������[�������*3�l$�t�W���������������������^>O��}���� ������
 ���@i�����w� �?^��W�����C���}�!�8��>s��2�8����]@^Zo���9����1���^8�R��������������������2l�����W�F���W@���o�y�w� �����V�v|s���|�a<6�~���oO��c#�w|}|w������.��F��~�����Y�y�.���������������O��O��O���??�Y���G�S��L���}�am��c��s�~�_f�Aqf�x�B�"�������~�Q���W>��~��r;��1?�����������5��+C�(��/��R��q����5ze���_^	;�#A�Q�dhX��q����m�q��p����Q��!m�����>�g����G��EE��E�\F9wk��(z��[$�F������7�+���+���N��GI���7Vl��~~s���N	og
��Wa��oo@��o�5C�w'�Xp�}����Q�/��b� �//��b� �o�s��{Es�N�|���*���~��b�����r������~����E,����cW�`���WR/c�7��*����|:m���������#?���?F���f�X�1�^���X�1��<O��`g=��v:F�z~�@�����Q��������X0��;b�0����n�������"|w��H��I3L�{��z�T�	iy���*������������~a�X	�����kW�`X�_�tQP����b�*[��W.,#�0���F*#��(z6Z+"��M�|�U	����H0E/<�TF��Q��j���?��H�1��st'n��e��`c=����<J��#���)a��a7|�=�oO�?��?i����������o��g^���W����w>|S�>a��H��� �W�U8�����s�N^qdU8��o/��[��a�{e�b�=>�=}@{�|��t�]��>���
������d���9���xZ����d�V��a���1�
�����*4l��ze�5~
�L�
������B��E}i������Q����G��Q���0H����?�	?������������n���Y������6:��wG����r��|����t���0H���ATaa���v&Uaa���/�������{���*,k����0��/�)��-��+���P0L��G��P�9����W���Q��P�9���w0E�<����i��7���Q���������U(�E����N����t-C��Q�rB����������I�Ka#��Oh3 �~���w���?����a��TG����	�6��Wk���S~�5��7k��_?������2���~������D^��Q���q�3�������2��k���f�����W�"��R��-���}E����+��a��GQf�G���.���(z�J�x�rZ<u[�F�����5����`f�F�����03���p�3[���y�3�F}��(�WNr����F����7�Z��zf��J�
��[I�������_��4���}���O��/wT�`���W~�.�� �o�i?�A3����6�U�`X��^��*k���,G��G���0�[��Wn�.��0���\tYF��Q�l�VD�a���}���Zy��>�(z�Cl
6F��+�*l���?�U�`8�~}aU�`c��6�v2F_�R���F}��2�� �WN3|s���9N�
�?�;����|�:���W~�Z���8�gW	�����)�� �w�G�����a�2����\T��A�o��������*k��]��j����C�-����)�S�����*|�(�b��(z����V��eb{=��p�������p��=��1`8���p@������!U�~�_^��F}���t����i3
�~e{#�	��:�8��y.��F��p-x+��?6�g5�����N����l�|W��t��P_��A�_^�tW��A�o	���x���*$����^����[H������� �!$[���>:!a���n��B��(zCH��?��!��GQ�����:eH���W�2$l���c,C�p�o�y�'V!ac��B���}���2$�=!����^��'�O�A���4&���[�������\���N�	I����e�K1E�����0H�m_	���u�u��/���B�����p�I�5����>����eH��/��)C�0�/�\�\���Q��}��Q�����Q��E3EH�E�m�����<�L�'���
�����K���0L��f�*$��������aoy�!�F����J������oOz�7��+�9�����v������QeY���l��HU@�[@B�}�=ji��������_c(��a�0�\23�R�h_����p<���V>}������)��s�������f��0i�<���;� ��L�g�a&�^	�f2�����a&����wfr�?���	�\�Q����L�;���a&W�311��o�fr��!������f�[��C53�[��-3�[d$�B�Y�"}�fV�H�;���-���G���	*���%�}�f�Np<r��p��i���6�q�J:���n�fZ����+&�P�Pb"�~��@,H��$��������?~�3��X�Z�j��� Q�)N����u��u� U�0�K��������}��X��E�6��D���G���+#S����Sq�-z7 rRu/�<����-��!���
]I�U$#t���E�D���� ND��1*|�rQxC�a+C$>-�z����~�"A��p�`$H��2�.$�������oX	R�/�)$	���0�In	R���y#Az^�a"��H��E�H��E�H�Z%����Ej�y��M�����[�bt�`q��T�.�;�f��'����h7���)Sf��6�\X�$
Q`v����s���?����H��VQ4�"�.����u3���v�<�i��O~]8H��FX�����Nb}R�/C=��Ob}�#1��7$w� U_8(	����SS����p��E�@=����jJu��x�<�?�(��x����-#�\����� ���G�B:���HG*���h��y���&&���4���&BH�4�����8;$d�N6	�v�[1�NU,3���{0$��^�CBnq��B��3k0$�;��0<	����!��0}�0$�{�h��0}�0$��(S�R�"��:y��8	�-rf�`HX�����!!Ww2 $���V\I
T����J:���s��^��#s���������:�u3���b����z������W��=Cs��n&���T�M4�����,L�����W��t�0���t��c�J�����a�J��t�+U_;�e0z��[�a�Z�!h�wH��0z
��.ze��y�\nq�������:s���L]�J�W����;��d��C~�Z�������^�-r-���\��nn�� ��pC��1���[qkX����Wd����0��6���R��1�������J���6r��8�����C��@�n�6�8��oB3��iy3>�uq ]�1_�����@j�JcH��R_7���9-�o>�8{������D�q_o��������������|��	���~��i����b!&,��>����B:������' *LK�,��)���m�����aZ�
ia�z�����Wia����c��v����w�����������u;�_�������'����N��~�0D��tw!"U�X(�����B��u�BD�md�b�H�������N*���^'c�#������qm���Oz��.D��[�A���.����A3��d$��_���]H'b!�vd�h��N|�N���4D��t`�K\8b� ]R��5c\�� uA#_��p�A#��5^�m�h�!V���^�0h|�fA�{"h��JeGR�W�����]�X^'��6�T��9��uR�Z h��I�^���:����}�8�	�F��V�a�����S����O������"]z�t���?c�H��N|mN�"���yn�V��9[�A��e��H1�j����Lwa���gP����P��"�^iY)2�G�(�����v���3���3��C��b�\}�4�����;
�0<L�!�;���i�!�C�'m�r�n����!G������������}�0���od��!?9�NUx+7f���TD&��?��a�f�P��a%-�o�a|�-8���O�-8��1n�V�j�|����.�Y/�����;��	�/L����BN���W�`�I�F7�.��[�������j��'������a�I7��) ����o���E�T�W��gy���c�Y^�@�I��J��}�����u�'�N�����7�X#N���!�"����]�9q�����r�������S/�;��5��pa}�X�^q+|��zU���lqfq.�^*i���||���j��u� �6R1$���W�G�����i���'i���I�tc?�V�Rug@n�����Yc0�N]0X^'�4�����������:}A,�����Jo���������u�!=9O@I��i��}*�@Nc� #��L�`d��$�m
Ab� -H<�b
S�}������h���u_�m�@b��0�nk�4�O�,HL�����p~�1H��[��tA"=8V�!�t��t��u��Dj��`@~��F	6��:�S:bX����b7��.0���h��FM�FV6C"�Via!�x�0���s#[X����0.���B:��:.}}��!,Kw	���������,��|��R��0��v�!�vz�u�!�^�c�'��c�E*6,6�������;�W]lH��3�c��:������*�v�
�u������i�q�>mS�����u�]�8q����\}q?�v[En��H1.�"�B:�����H1m��@�K|�)��1�ii�/��L�a���H�k���)2m��#E�����������h/����e[�"E��V,�"E���>d�H��7�<A�X_'�t}��H�[%�t�_�L�m~���@�����h��b��K�c�0{��N:�k�!�b�u#�L����Dnq�(�9�|�:��j��XI�=�(��|f��Qb%�yI���u��r���\6��;l�V�0i�������!b�I���n]�I�W�<�.�$�k�c��$����*�����L�W�8m�1����HQ����:�U/�u
D��u�[}���Ot���j�3s)��7l�����"���]�I��FW�8�x&�,�S���"���[�Y�Y���"�B����[�B���mv5�kuZS���[0xz����B�T[����A��0lt� �^9�0��� c0�$���`����F���.��������`����nRm����U2��ur0'��:9��E����SE��aq��������ZNASon���z��?��5�+�����I��^v�W��Cv��J<J`.L%�SI:}�W
�2}lW�j�����+&�0�T���2uA$�^�]� �h�&2mg�+�O���S��� ��X'�� ��o�~�D�����uAdy���0�u�'�p�8V ���)�=�^'#��b��zN_8��g�v�cq���KQ��N�4��a���-�����t```%�v����2��mL���az��r`����������0��#u1L;U����p]tH����=�������DtH7���a��!Uw�t�!=8N)X��I��!�6�~bt�N]tH�����Cz�6F�
 ����u��1R,�n�.R�{�f|��"��>�uf����o���'R��'��0�t"�1.����4���t"�1�j����8������/���	U'2�T^"�^�e'2���]��gi'~�D��N5��\}�|��8��7g!���u������w����'��������U3s�z�
����c�����06����J�
�x$/�[<R1]I��s�
+���J:�r�����K_�l`���v��o�2|�����_����������OI�x��m��P�kW�t��5�w��B���j?�����b������RZ@g�����Xt:�	��:i
���qr��z@�;����v����5�l�F9@0V�9��)m�'�~8Mi������4��q�0�_�1����t��i�5���{��h��B�	��M�?����)�U����Y���
��c3�*P��^�[����?1��^���x���:�]E�|s&������:�]����a�s/�����z��6��{c������w]��p�3����&���{H�Z���\��o�`�.�fw�x��tq��T�U����`+&��j��b�zR��:�f�\�r�V7p�������w���P?���_3���|�;�A���+������*[��k���/�t�
���3�
D�x�V(��M�
��XWz�4E+a#g�Qa�l��E�@�l�B�@-m<�+�G���X�ho�i�������������G�@��5b�����D����vX!�Z;�P(�B��vX!�]+�U|�!V(���<G�PzWq��J��
D��aJ�F�@���;�aj�����
����+���P��w]8+P�[#��nqZ��A\8���>��!����[1NK�]�/sgC!�
i+��O����^3@���une��0}�U�H!����`�n@��	@��f�
a���B!��)�P �!�@���9�
�����(PK�����b�@�ho��������Baq�
�=���#�����
�B��v@�PVQ��o��B�\���9���l�PxW�++�����B�]@���b�6z��#P(��h�a��nr�3��������@����9��O�T��
8���A����%�W��6����A K!���5�_�(���s
Qs��0),��'�����N_o5		3�gpBv!C!|��@�����G�@ei
����P
�T���O�p�*P�U���P�9B
K���*Pm'��@���iT����)�nT������Bq�?���#U(vt���iT��S6U�V�
a�
T�t�6UH{�F���B�]�4�	�*��U���v�Bq�^��*LxW�X�y���,�8�]�FO;�
�w�P�bG��`��*[j�]�:�O��<�C�)��s�B�@�R�/�(����������\�N~ C|d(��g-�k��8F��7������4�
2���&��!~;�px��*w"�@d���
a4�h(��6����4e���j�H=�^8�4���A����:�@����@����&���p�8 h�;�r>~#h�z�4D]k���
��z#����v�B�]���y�
��F�9
�.��fh��Uo���jo���
���y-h(��������&h��V=�aF��yRJ��
Ki�I� @��4j"�����o`a;�F���N����]���:��rB����F�@���D��O����������{^�1��[Pa�-$�$F�>�(�}^A�3��_��+���I��D�H0@^A�a��F^A�����^�M�:^A�7Nr�
jogzK�+��Qi�W���p���+���x9v���S^u������WD�k�+
e�-d�]����wUS.�WPk��T:^QzW���<��W����WP���u�b�����9��L'�xE�]�F��+
��~L��[j$F�O��N��F+
i}�W��U�(��9����!��Fb^5�BZ�
�����,����^1�m��q��F� �6H��C�$l�"��Ya����}��Y�D8TuA�CUD�xt!\�f%CPK�!j�����D{kTwwp���11:�QX��.���0��wp����h5������B��Q�������B��"\(�k "�];�PzW��Cai}�N�]\g�.�w�oy
����.�U���z�?
�����Z�!G�@�T/Y���'���.6F��i?�����Sd!����g*.���.��5�e�1���E4��b�:�8�&������&�B�t_H[�Bx��/���'`k�"�)�(����B��D8��p�/e=��Q�jf#�������^9����#�j�u*y�Z���.���~tu��/�}���)�Y��Q����BY�-�����Y��|������w�]������w-�|��Eg��a�so����U�]��Baq#�=�+�F!_�;�r�sN_�<������/_s�[�F/S�L�BZ��4a���1�����N0���1�!�j��t�2�������m��j0L]��,��0��*D�����$�����F0C%lc�J��qYX8���Q7��)gz:0�L�Hn�L�Hni�Cb����f`������k�*�����T�����p<3�]�/�
v����Y���!�[3T��Oc����*�*>|3T�U|:f�v^�0Cu��|}��.���w��3T��xL�������������HT�PyWc�g�����x�$*i�(���J��sY�q={a$\� �Ia�QD�
���g�B%�g�\��ttH�h q���PI��)���Bz�[�����~�L6�
a�-�v
��_`��~(%L�x�![�f^����-PK���~�0��X�4!���^;��-P�?��l��ok�(���+��:���O�BX�B��vl!�\;�����
���HT�U��J�������I��B��vl�ho�B�a��fR*�}4�-��)b�M��;Ala����i	d-TkN��f���j����f�H�����F�����
��}��\!|��+�W�2��T!+�:Ef/�wt}9�;E~o�s�� �t{E2i�W$M�s�(�}VA�3���{E2e�K]�*�9����*�52�"����AVA�WF���U���}�c��^�����WN�d�|?
"yT}{}XE�v�"��"�[;Vu���zWd�wU���5
�U��U|9#�(��_n����X�UP�jP�a���(���U'��(����������9o�����s D8C*�Aq�P6R�]3�@P�D6r ����2 ����6��N����'Coq�>F]���(ax����r�'���������h%�~�C!��f�J ���������C%����%PK=%m��C	D{�<�%P{����
��}D	�|��^�����?*�kG���J���%D}k�
��wn{WD	Q�����w�PB�]����I��R�b����v��t(�zWc��g�U-z���V�FD	�w
�=�}��(a�����{��e�sC����zn���sC%-7��,�BZ���z7�������,���\��Cra4�@�up�;���,��a�C�_50���c���	�����fC!�3�B�gD8����Q�m �k��"2jf��<2ji�Ww��������]��[7�����t�������|?�D�tGNY2��O��-���cQ��1��s�C�]Eo�����~w�����'������J��v�<Oz�����1��ups�uc������C�1��������������@0������g�iC!-��+��+�rn$-�{)gCT��]s*Pa���{��@�>�
i�XV�K���x+�m�m�g;��s����m��m�P	�l�[8����3-!�r&�)g����`��Fj;���h�%��-0m�7:�n�����������?�� �D`|G�FQ4���gE��u�����B��"[�����PyW�el����;�B�]�r����N��L{Wd��.�������~���[�\�&���p���l����/�m�fw7�)����bd�5�l�������,Z�B�f�6���J�`s������G�)d�|_H�j��U7�_u���8������.�,��S`7�d��P�t����d.0�L�?���l�D�@��8�-���vt�h;��:�@�ct��{m|������C]�.���tG�&�H
?�WGd]kG�����s
��BY��H
��WGT��������h���O���<����o
���~�:�@������m���6�����G��������5�"������:��BZ�]�-�3.�[]���f\�`����B�}�f��^��B�<#YH�B!-� i�YH��e.�}���:�����y�]��z�������W������c���MR�)�}R��n["������$�l�#�f6[�A�v���i/Bs7�r��7�<��H0��i�o�j?Y��;R�nD����rp�����@��X u��z��D�lD�~�H���r��I�(�������[�~V-�8L���S�2�����-�~�����q5��HF
7�#��H�f����7b�J+�o���*�����������q��Q�9��A��H�(��QI�����W��$�j@%�U*)��$|�a�?�r�R%�M����v���i�6v ������
a;0�F�/���t��Pd_���f���zx�a�m��@�@���L��I�0�I��`���������b7zf���o����@eG��v�!�Y;�u�j��VD
Q�����o=�o���?��?��&�^H�v��yu(�l�:P7k�������9����45n�h:���p�z�)���F�[@��L����@O��tkQI�9�Z5�����.�:���;!j^
�����.�W}}�6B"F� ������n���?���M�h&���	C!�"�!D�C�����(���:���C��Q��*?��o��p�
t;�D�
D{a�j�h�~����
���i��������M��^G�~�9w	iC���
Q'������hC��v����~��J9@
?Hl(�cbF�[���.�*=�o5��0�[�F,�!j�����<����������[�`6�l4�����7W������SM�J>���4	�e��2�������#*����>}t�����q@#
���"q�>�9�3kN|���s�(��g(��dl&1�~z����l$���aC%�q�
�������u�
LY/�E���� a���3l���6��4�ml`����M�����
����_�
����_6���6��|s�����E��u��^aC��"l����6T�>l�����n�
�f?�
��_������+r�f
�3L���q}�;TnV����r��H���:�c	�t��aD
|?u�5Tkt����n
-���L�����HZjC�0#�f�
���!/}�;���JZ~�7�PI�u$
8�����;�pR~�t�d��P������p�m6a���,@�@���

8<)�&��o�����v��w��h?Z8��G�@�7�B�@��p&�"p(v�����Z
��e���Z�����C���
���E�@��F����p�7��
z-���8P7k�����rr��.�4
�nn��
���/�.���j)����
7a������1G����������=�F�����Y��Q�	z����PI�����B:0H#�j����0"m�i��(��A
F�W}:���ew�>]�o�78�~��&lw����Q����� �BX|�!� ����Ly�?D�E����C�A����D�-�X��#������@ ���{a$wX��:�DkP������Q��a��2`��g��F��vX�PQb�������5;��m��U�
������e���/���u��}�^T�����:��2&|k y���F��"� ��2h���'�����F��ic�Fx��4A���V���?+�*��w��s!gc�(���5��O����k�5����q��g2k�n����m�@D3��!B!�f0�F
3�pf�'SA��O�� 5��
!�6��.9����d 7�ho�)�D��v��"P�Og�*B���B���D�:�"��u�D(|�������b����O��x~M�I��:c�x��L�I�f���a����97�4.g���t:A�&�����[L�b�"��{(�S,*i}"gc
Dzk��%Dkt������4����&"[�z�}���Y?��3D5�>Z�8w\��������
��� ��`C�#l8�v�?g.l`��P	����3�p60a# ���������X����oE|;�g0�����L{�d�x�.���'�����*<p�Gy���������~��!�c<d�,��J�/���Ya?�!�g<T~Vm99��?q�j������E|C?u.����L��5�<�n�����������+*7kam����D.�O�8���e�#���(�V�8c�o������~j0�2���2����nM!�p`�Ee�@��v�K�uq�����m�9L�������M!��=�m�@d##/*a�?�>�N�"�D9���1@���3C5�K�G�@w�h����h��Q����_������DP�0�b7�n���~�9��C��v�!�X;���s����9�UL�A���s(|����sh�ca7�1���y�9P7k4k����~������{���^����������~��������XB�H�*i�;g��5+i9��Q�nQ�Y��y~��!��Z�>E�k�t�Y��
�@��JZO���]r�'�0��z[���6&0Cx�f�=[����$���9�>f(�}�@�#��p���
�Q���([5-��I�5�'�v���Qr �+gd"��qZ r��~ta��]T����_���0q&�S����^���~�z�?D]n��>�C�s�Z�����/���&�P�]n�J�����]����i��u��s.wi3��U_[����/��;�Vr���;�C��,�1��x�������PH�
�����J�{1�j��C��m��a�����s�C_�un�l@�������L����r�w�<~
O��7s||��h\c�� �v�I*��(�}�Q�H�g�F!���d�z?�i�s���������u�j�i�� ��6L{eD�� ��~h~�n��S����:���T}k3��E���Q�����g��E��v�����(|�?B����gj@O���b�@t;��6���'�u���Y��o�.��ur���B��@tQ�Y����7��e���K_:��0)��74|A��~��/�5���E!m������2�E� �/
i}
�y�|�9
^Pa^�
(��l
@�[��"}6nGz�rV
���9[���m�@D3����
a�%�o�-�P�Q���d�k}��.����t	��zIq��������:�q��q��3P{/�������dg����$!g����3D�l��^����
Thd�,r���8C��"gx���8�N�AN�������5:�snV���q����4�3P��Tt�����1O9]��-�$�����(��4e(�!����k���DVCa��
�!.}�>�P�F���.N�'#Q�QX9������.ZrD�"cK����;=�r����F�*a�1T�v��0&�aL9S���3��Y�5��o����Q'��1���������d��r{;Y�����~Z�\��o������C���_4�����*7�3����P�Y�S�����Lng��!���oE�P�V?���V�y>L������`��{i�u�o��,��|��Y~�&�G�i���P]&�����	cTk���C/*i#��<ii��}k6����1] *�@����H��hC�Lm������4v�8�~8�w=9�r(�}�P���Z8�l�	��Q��50e9�p��93Y�k�0�E#M1�N
�`�'1����������	��~�9�L3D�j�����Q��a��k�0C�,� b�����$�Q�
����4wHe(b�az-3�5�����?L�����r�s�K��������q���p�RKe�b	��aLe���w�[M��<N��k��Y��a����rKe��,?�[*C%�@���
�!��tC�t �����11��C!��l�!l�1�$��M2�H�D%�#�B�GD8��@�C����<��i4���+�p��L��Q�q��e5�GV�������h���Y�������������!�c;�V���n(�l7d�,�z'u(0L�Y�#]VCq�U#c(}k ������:�@�q���a��n�������D�@��F���1��|7&!wY
�����0>��N8P�} !����� ���Nd5�r�`��A;����N��^�PH'2��>!����PHz5�����
�������������~������?���������[�W��������I�];�n�����
��P
���%��"�!�9*FC��z	p"������X��%r"����8Qv�ZO�����d�m|bG�B��^<��z@�(��/D������gS{���\�C@�B-�q�:�:��F��p�������fF1v,&�g;S8ZUXL����,�P�?����XL����n��jLJ_���8L�qg�OGc����!��1���&�y_kT��}�R�VAS�Z#
	y��oNmO����T�$
���[Q	�	�����-2[�G�_�5�4
�K!m����
D/�-D��n�����yzI��0Lo�\r�%|���_�W�����y�6` �����0a�
"���F�@�C��(�����a7�c<)?�c,���v����
�lo3�%��,�G�����c@L��1��u��Z|��T@�@]��������,��)��
${Dm
O+�$����0
C�kE������$��O�]m�JW+���5�C�gu���cE���ue��Z�!�q��n.���p��@�3o
Y�R��DkaA��)i��������BZo���=
i������8��*�����	I�{�m��!.}���������|�2��T������~����2&�����p�90�HR�c�90�s`�z���Y�9�0��;�H`�lg�?,��%dL���-��m����-�v����K�p,�����OW�9d�,2���E�PyZQ�C�j�����P�Z�#;$5�;�Ij��:�E�P�W�I
����E$���Wc��0�_�6��y�jL-�P������������T�����#f�.��!c��t`&G���Eu'�>�\X�5q�^��+1������������yi�1��:����y������\��U���+n?��h"�!D8C�p$��	�a/"l�Q@�@����V6������?����=�z�lG�Yd���:-�*P{o��Rjq�(�u#N;�
��,
�T!�[;�P8W�Kf�]�L����E@���B�_�L�g�g���d�W��j���t�~����#?����b��f2*W��?`�N��nuqG0P�����N�U�bt�<�HzeV�z��+�
'�L�j�r�C�d�ob�d���+*i9��e2�
�y���		��H>i�pH�Cx�p�=���~�L6�z���!1")�`�!�@�C��(;��:�@����y�?�t�����D{kt������y�!p��1����4�p��du�'j����|k����wU8D�k
�Hc��WO��)��W?���v�j��y�����n�us�v������5�18��]WG�P��w�@F�R#�a|�a���rl���h�P�Y���2�������6�:hY
�-�����4������un2���>���!��N�������������a�F0�z"l7�d���_�DX� ����W|�4E��$6f\"� �N�I��xR~�����/H5��g���G�A���&A�A��8B�A��v`�j�#��@u)K'OAF��# ���~�����@F���	���d�)g�LV�V|�b=����K�T�C��@zQ����'�hX���h;]p:zQ�W�cEG/
���Q�W��H/�����KWH�ih��8Q�Q�Y�������EK�(������N�dPa�k5�*�{4zA�5�CMFx��W]m$�k��"-
)a���ga0�Lv�_�p��g�1���h���(����'�v�-���m=��������v
�;�@��q��#`��t&} `�.��i�������<E�P�Y�>����SP0�V�I��U[I`(|�x>0�V�\�/t�k(]��d��P�zX����JW��(\�����j�u��d�j����
Wk��@�w6�@�����H=(����1 S��:>g��2��<��F{��5Z�73%
i=��4}6�S���9�XC�������#k8�O�N�e
LT�-���#3��k`����3�%�rf���r�6Y��Y?��6��8.k`�['IX��#��Kr����/��R>�|~`
�����*�*?�WeT�����<�_�Q�Z�
D�k�d�����%����%����A�P�W�9
������_�S�����+�X����Z�q�\��oR���M��{���J�%3TWH'c1F^z,��~����	�4�����["C�������S�?�G�P��@*Cz����h/YI��$F�_u�iw����l�@d#�L8���	G�����
6�^dD93��Y�5��Xg�f����2zX��`D{{?�~>���):@�@-���u$'0�R>�52�W���#c(���C�h�V�YO�1������
_��30e��n�g�W�h5Y�Z��d�j�����t~P��a��o�j�7�V��pC�j�#���p�Fe��XVN	�j�n(��&+i�����_u�������9[�M����d^��U'�C��@����s�(�z~H�C� �����������$����?��&���"��D8�l�)�R��s��:�@�_���i/��$�zX�g6���u>�#~���8K?P���3������z��_Y9%2��e")����)*OHq(\�??���~������?���]&�Cq������w\m�JW�"���w��:�P��xd�\���^����|8�A�P�Z�e�j�����TT���u��zO���@��Ya�u���=V1�aF:0�"�j�q�
ic���%�c8�����H�f��
+���;����M'���s�q�24�N2i��$�Tj�H��JX��C�A��V�D��f��(��)��`���aU���[�u���g�I|�.�1���.���iy����{�����3�G:�z�WN^?������"����]>0�.
'������]�U�9BtQ�W�������>����S�)AZAOt��$?�U�����~����f�dp���
H+�Ym�;ZAwt��>ZQ(z�AK�(�u^��%
i���d��A Y���{K@�D!m$K�^�bUK#�(������;��7w>�2����MLP��p�TXn�"l���ga,�Ly��G�"��N�B� X ��v�L�i7	`���0N���a���&����w��`�ho��`��{��&�j��������:�@�J2���o
���J2�E"%�{
�D�5��!�_1'�I�5�8��7:W e(]��}�t��X��2PWk��a�����:�P�Z=i����|Ude�p������$�R4�P�A��*��K�1�4���?/�
'�"�[����N�BZ���NG�0���s����>�l�3�*H9���{��.g`����#c-����
8���d��:���Z�:�g����d��3��?�z�ud��d���:�
���{����9p������K�t�Cs�~e��T`Y?���r�~�������r��X����@~�^c�t�����su�9����l�]�?���Z�o2����E�9L�Z�h�&���uR�=�M���Cm21f6p�GFhV?�6s��`q���PI�)-���p����;T�z����		�cT������[do"0���sH;���w�v�������l�@d#uL8����#��p;�v �������i���������A���=,z��a��HuP�g@,L��q>�#v��d�����t??�����,��"�A�P��v(�_CQyZ��C�jEx�����~�����.F���61M�v��3�=�����S#;PW�1�(�]��h�0�j9k~�w*����;P��^�����azZ�.

;k��@�|�2*i�\8��
�B�����!�}���������]�I�I�t �����Y��61��PI�,�C_�#`w�d��L��D��aDD8������Q6r�9<)�9�����7A�@������@�"��@�S/��c��Z��*�!�R>�6"�WoqO9D�l�
G�t(<�:��C�j�����L�l�	rx���������9��V�O����P�u�zg�9P{o�\�yW��g� r�p�~����:@�!jv���CqZ|�P�Y���]����<�b�rF	@���!�!|6;���lrs��������F��"ng��t"�!-
�!l���u�������2<;jI�t���~��*T��y�I�J"k��d���"������=���BX�e���L�	�lU�|M)��nGD������HD�M�g�uD�=�I��3Oho�w.��b/��3�<���k;B��N����_�xH�X)��x��e�)�����&*e�������-!H�]�������"A�w��#�9�����{���D T���Z�@
��Q] �f�uR1���GEO�h��5�����t������O��P�Q�	2l&RH��H�"����L�
��*�D��&��&��Lo�\�D�X�z:F�p���]��D#L8R���W�o.&��`�FG LYo/���)�2�0�c|?s~GK��Lm����a�gZo�����#OC��z
>����p |?��>�@*�������,��	C�Z��LYO*@����H��~�_�@��	�v���'=���������j
��w��!a���h������ �w5�x��<8��
_�n�^|1���_���7��,*i�~�!���R��M,������6B3�JZ~��f�S
P�Zs*���s���H��n���_0+�V ���&��E�@��7b"�����G��
mTSvB�,P�E���4�,��b<�,�S���zJ������N9���v
h,��|s&C"X�z�,��/��|���2�\;�PxW�{D�]�G4L�d�F��
�}�+,3~�iFq������X��=��n��N�%�������X��M#9����\���
���V����P�)����q���V6�@�u*�Ca}��9"l�V�6F��F�PXY/�hl!-
l���,�W}���r[
��U];%�ai�q=~����������/�@D8��@���k��p1e=�=no�����t��j;�/1��B�T�}�:�@�%��M1P{;��:�P����1��|s�"���r
�@�oU'fb(��_���);�
����k6r�1�1�����~�~[B���=���0�[��������:�P��Q���t?��iL��@��GY��O��>�cl
^10��0�,��\�T�td�0}.�/�����Ba�Q(�D����N�(�:�hD��N��6vD��O��H�%���^�)"����3�D��y�(e�(@-Q6�8"O ����\�	T[�y;�@o��x=z���	���y��5dyB����n|?��}�	�_
�,Dk�
�������'�U<���5�br���yB�[����oU�8�'����A�P�V����ukt(�xB�[�PO�����	���;#G�'P�'*!�M���c���t�T(��L�V�^5�*�M��TBk4�����#�j��`7w:thq�;�l���&�<�B!� ���Z�,�W}:���ew��\H����D�F��,�����F�C2�HwHn_�wyE!lw�d�F�1�
�l$cQ~w^�����1��Y��]��:���>��4�zoB������Z�!����\P���9��?}'�g�����z*�dD=nG2
�����Q�Fu���BY�H	$����9G�Qx�@W����Y���3:���n��w���"��W�0=b����u������N�]_9b������t?�
��X�]o���$��^|��Fq���5
i9��FZ�%
i�g�kNB�b��{J0���gd�L#���ii�q���&&�;����iw�}O�&y��	�@�]#�p"S�
���y�������l|�o��6���J������B��#�hCqW�lR�
����[m��[���hCa��3����r7�<��+Q�����������a�
��T�	C��aH{�FJ��6a���I�_2�����^����Cqu6:�h��8���'�a����8�h��C�����F��\�Z��2R1<f��&��o��_�0���G�PJ��!/=�N��G���0~(C^z�����u�7�Q��&��!���2��r)�H���2���j�2�DI*��D81��
g(��#l�D�������/���H�_�TQh�0H��1f2 q�Q�;�@��FOG���� T}�i(Y���y	#q�z��8n��TQ�Y��#��������C��"q�G�� ����$#q������:F�M$� �B�9Gkt�<�9���R:�P8Z��H�~.�;$t�������W�x�����u|Q��'iKq(������yC�f}������v_3�~��A�8�	��>�m����!lkhq����
ec"�In �K=��$7�v �!�@�C�
����8Q�^�)���vd(fqW������{�����ho�/Kj��^:T5P�����C
t?��}�"������PC�[��p�j�	@
�w���l
�Q���3j���#j(.g$��t��@����Q=���9_�iw�f���`U_UHl��['�a����v�
����
i�a��!.�
iJf)�O�,�e�	ai���2��N��t���=�8wBt�q��F����	���������@�L��$���9��&���>�
�N����FH���(�1_������<�8��;�@�Cy��l@����| �[������;��@��Ni|���0��;���|(����>D�l
G����
����E��BG����rF������C�h�� ��9GkB9�9���f������vW�M�}a�@B�@���wl���N�9�zvFC�t=�m
���62�N��,�C���
i�f� �
�zH��C!-$@ii@a�|����.}{"?UwL�����nkJ*��v!� ��
"��#� �zF1"�B��A��f�CA����#b�jA�����1�]���F�A�H�%�~d��O=���KJ!���k�Q	b���Z��g
�PD]k�1������xFc�_�H��BY��k��ck@I����_������j�$1�1��d��n����(~2��Q�Y'�aw���[�T�_�E��w�,�Vn4�X�����6��e�,�X��F1mg9�j6��hc;a=7���)�?��[�N/�$�/�g������(���
6�����I�L4�3���:�p�H�	Gr&����S�fu�9����e�
�P;I��v&g���L7J~�"�
L;U����4IC���9~7J���l���*7��LT~VT�P9Z?g���~o�l���M{)�Tc�Du#up���z�2~��v����s�4���D c��R/D�P���vH��������\F�gQ�i����JZ_��&QI�i�i���9XoaYaH���,����C]v���[�
Q���1�����:�O�?����gL��LhQI�c0^ }�sr�G�i[7qsO/NB�� ���
&)�`��0B"�)��GB�B<)�d"� ����BA����B�{�� �!x!���i���K#�!U���JB��\8�RBD�l!
7�w���UT�p�u�� ����h#1���io�#JG+�@A��FO6AA��1�q�s�k#+a���~9#=�G���AQ8Z#_�%:��GT�������!c�?�24A�N�����@�Cu�4.��O��N�Vo��J5��(���������-
����3?�3�	���.���}��a���"��
DX�����10�"�
D9�%�Y�E��k�����j
6�{�GLl��h	���ho��K6{i�A�@��NI���'�aC��v��p�j������`C�h�����aQ����G+��#l;�6Pm�FaC��v��D#!d�s��L����]-m:�P��R�G
GkX����F�
5P�8
-�����*Z�C!�_u�QI�SV�Fm�����_s'$0#�j��^�q��F���0��:�8�m���<�/zn����������><��&��d9�L����rxR��l���R�)��a�x;�<��h�/@�@����<P{?J-��*��b7����\;�@�.�'����J-
?��
�����;���������8�M<�S��G�@���Bx�33�D����f�Sr{?&c�s7<�63������FUo�����)�M"s1*i�xH�����9`��9;��S�C!��Q�lji=o`?L
Fp���Cz9���qi@i����G��������������������$����}>�v��_�~�O�>�w��B��=�E���$�Xd/DT���^��N2��a���ryDb�r�>�7�u8Mj/�u�a�<���|T���c�Dm�f|��n?+��g�p�M�]2��_�)����z���q�V�:]Ro�����T����u��!�!���P��x���o�DS�MX��D=o�c����1D�����Y<����}�|�����=������]O��N
�KyIy��5�t��o�N!�_�Ig���O��h&���;V�W�g��5.f�V�FM�q��8:RS8������f�2r��!W�6��y��j
i��Fc5��\����r��:),HMa�D�H!-�NR�3���O44��n��k�_c�4ic�I���o
����%����b�K0QcG�LX/B.����)���F�1r	n������t�
���Y��O��5;d[�����.d��o�F�����1��Q0��m�F��c��������'R�;�6�x�e�Kp���Z.Qy^�%g��"��|������(�.�-�7f@.�}��/��?��0�z���EQ��O�@xD�z��#*�k�!����T�GT���x9������xDe�'	��j�zm �~����#����1���i����)�P�RCN�h4�����1w6����W�
(W�K7QI�U*i��y�|D�5xD��5�5F���s���#���iy��I0a=&�xQ~|��c ��v6���#��#&���6���x�2�#�_�����#���� ����jV�G���6���u�������Y�y6�#������<����2�����u+��U���{��&����b�����G���5�W�s��(\�^����	���GT��#�Q�S2�s�wu�T~~D��w<���Q��*Y�dGp'���CvD%-w�h��U�(�ep�jY*i� 	�D!������-4��&�^50����s��'3s�(���U��~O���@���g/gN�L��$K�m����X�;8A�l<�N�O�� ��'��#�#B����#_Smxp����b��	��qJN����X/���;m�:8A��F����B�(�@8Q��'
�H�(\�?:���"<D8Q�~���nJ����������/u��(��s�N��h&�p��o
>�������D���3��;�N�q�'z ����PKCZ�=����D\���BZ����.���9�j�1�����3O��/�' ai�4�5����A^QH�M2�H[r(��UqK�H��u�H�����]�~rY��y���!� �!^A����WP;��;����4y��6��g�ia-��3	����oN�7�
��uJ��W��"u�)�����G^Q����yE���-����;3;^Qx^�5����xE�{����~�	n��Lq�����Y����g|^A����0W�C2���Vg��W��@F�+&\�:�d�����Q%
s�w�H ��p��d�����y�5�����Id"�"��V�A�,���T�b��i$��\�`��4�H��D������'��U�)��h���).��X�(������^v���-�}���p�_��r�	�6��'�`���0�LX~ �`��F{1�L{��N��Mm��)��3�������x��l�C��j?���
op���M�W���^���o�����[w"���{�L��������u��7����x�����opKu\�7��u�y�����F�m�< ����!�����%@4*ok�s�vm�H�{[���*���R�hp�wU����"��@��JZO�D��-����@yH|���yr��4���N�����������0�g�]p�g\_���h���3f��?n����qu$
endstream
endobj
41
0
obj
51350
endobj
42
0
obj
[
]
endobj
43
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
44
0
R
/Resources
45
0
R
/Annots
47
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
44
0
obj
<<
/Filter
/FlateDecode
/Length
46
0
R
>>
stream
x���O�����w�B������� 
���ON
�xb_�A#� �-C�}�s6cE����d���[��F�2��������S����������e�����������4|���!?�j����A����� �}�w�����4����_��17�?��cyA�]�����>���S�
����/���2������?~��_������N�����/J;?f#����K�IV�����8����e�F*H�0	��W��T��P����l�G8���X�a��+�L�aj��AXM6�#�P}R,L�����{&���tT� �&��N�>)&A����=����7��~�d�=�	���I�8�r��������d�=���C�ba�
���3�>�a��a5�l�pB�!H�0	��W��T�4Q����l�G8���X�a��+�L�a���A����'T�� lp|��I�E��W?b�������b�$[_�gR}=-�����	�� ��$_�gR}#-�����	�� ��$_�gR}3-�0���	��0�r 
_�gR}�-� &���i}�(VL�����{&����r 
���8��ZZDa��+�L����@���8��zZDa��+�L�a��@���8���X�a��+�L�a��@���8��fZDa��+�L�/����@�d�=3����I�8�r���ZZD���>'TBK��(lp|��I�!��B��>'T�� lp|��I�!L�����>'T�� lp|��I�!,�����>'T�B��(lp|��I�E�ZAL6����P��a��j��(e�(�F������W6qrF*t`�����{f�a������r�X}
�Q����=���0Q���P�m_�g��
R,L�����{f�a������r�X}
�Q����=�����P�
��l�g��=����b�$[_�gV}:
�Qh���+���W���
���3��#�(tu���{���0R����W��U_��l�:n��=c�U�ba�
���3��K`������P}���$�_�gV}����G�}����*��'_�gV}����vw}N��
}O���W��U_�q����]����8P������{f�a��Aw����� ��$_�gV�Uh~91�l�<R{f�>�b�$[_�gV}��������P}�X�a��+���/B�P������	�W�_��A����=���0=��A�w�����0=��A����=����4T� L��pB�U�ba�
���3��*�
�� &��Yj�B�+&A����=�����r 
���@8��*t����W��U_���Q����	�Wa��@68�r���"L�����>N��
-�����{f�a��@����pB�U�ba�
���3��*t
-� &��Yh} FP��a��+���/BG��(4������ ��$_�gV}ZD��_'T_���Q����=���0�r 
���@8��*�����W��U�-� &���i} FP��a��+���/BK��(<���	�W���@68�r���"���B��>N��
=-�����{f�a��@����pB�Ui9�
���3��3-�0������L��(lp|��Y�Wax�r b�����b��I�8�r���"����c} �P}ZZDa��+���/BO��(������� ��$_�gV}FZD��_'T_���Q����=�����r 
���@8��*,����W��U���A���,�>#(VL�����{f����@����pB�U�h9�
���3��-��������@��(lp|��Y�E�h9�a} �P}&ZDa��+���/�B��(L��������r 
_�gV�U�ZAL6����@� �X1	��W��U_���Qh���	�W���@68�r���"��B��>N��
R,L�����{f�a��@����pB�U�h9�
���3��*�ZAL6�3��@� �X1	��W��U_���Qx������� lp|��Y�E�i9�v} �P}zZDa��+���/�H��(�������0�r 
_�gV}fZDa�_'T_���Q����=�������@�d�=3���� lq|��Y�Ehi9����@8��*H�0	��W��U_���Qh���	�W���@68�r���"���B��>N��
R,L�����{f�a��@����pB�U�i9�
���3��K��_&���i} F"h��I69�r���"t
�'����P}�X�a��+���/��R������	�Wah��A����=���0uT� ��pB�U�:�~68����s����1����S�v��<68�r���"4��1
b�������b�$[_�gR}�H�	B��~�rB�!H�0	��W��T�0Q���m�mW�gR}�D���W��T�4S��0l�mW�gR}�L���W��T��P��0m�mW�gR}�(lp|��I�Eh���~�d�=�	���I�8�r�������v#n��=��C�ba�
���3�>���������r���F
�Q����=��C�;�~�����a���A����=����=h91�l�L�pD@�b�-���3�>���Qx���	����r 
_�gR}=-�����	�� ��$_�gR}#-�����	��0�r 
_�gR}3-�0���	��0�r 
_�gR}�-� &���i}�(VL�����{&��@�%&�����	��@�%&������3�>�.1��OTN�>�.1��O\��I�!�u����rB�!�u����j�L���KL�������KL�y����y����c?=���OS;��'�����;>_�v�zJ��/�w@^�s�+��I����^
��v�F��Z����s�5�������f�����':�-���]�`d
�$m����>�_�/�^�e����N1������j�o����=~�Nm�sK���	� ��Q�:��u���@@�b��e|L�k�����i�v�Gb��/&A(��s����"u�:�A��T�����|�$��������z���^�(e"�� ���&A(G�>c3r���Gn�<��U�a)��W�?~��GC��'x������_��=3�>���<�D�G�]!���LZ�3
���a�y(b���w��Xk'k�� l��v�q%�!���K!�Fv_���^��oZ��-��F��[`s�V�xuDk8b��!�%&A��������z�f�$��!~n�/o�b�$���	�����m��A�S!xx>me���|%��_�QA��C!�9���>>>�f�I�o7��Q��
�a)z����q��HA�%
��`��
�cu��A 0	B=���	�k�TU��K!�X�����?��i=L��E0	B�N�q������ ;0�a�7��QW��\Y��b�$��?n�G��z��$��i�4�:8�,d�� 1	�7�R����g���$����N���p�b�4�
!2����E5.�p�0	B=����� ��[�&A�}��(W���8�����=����	��1�&A�x�X��3���G*��
����qj�k$��z&�<�����M��D��`�d����V�F��
�q)���j���-�QjL���%`��5\�)R
hX���da��+b5\�
h����I�
3��k���z��$����&L
e��1	�on�^��_����/��=b���"���J2�u/��T�H���c�6
4\a�\wv�&^	z|z�MT� $v'�	UC�l-A��6��T#�0�����j��3M��<g���+�r����6�iEk��h&�<�F5	g�AA��IoG-����� l4K��p��8�&A�����/�fy�ix|���G,�\vB/_�� t���
����!K�#����$D��c�����a �-�gj����6kTZ����	����}�L���`������6�l[M�@����48��
�|�m��K^}���S���S�.&A ���T3|||�
�I��gC�����
;��H��o�[�������0	�w���&�y$�<��r����F��������L�y�����:�O4�DKL�����������[)mb����P��D���)&A��#;�^>j�a��U��#�$������@�)�� ��b���WT�\�T��z���$���!��&��
����UO1	B�R����������I�3�I�j��/"+�~�s*O���j�[_M�����f��$�?�k��� ��[�&A�?�b������]VK�K!l`
���������U� �s=>��Gb�]!x�M���+fP���	5�p�=�p&�����$�>n�g+\#�h4�`��M�@&�a"�@-�I�������������*�ua��i[9�dO$�� �����?H�-j��x���$�{�alEk��n�'����wT&�	���b> -&Ax�!�__�p�=��hT�)W
g�e����� PW���k&b�b���jz��nKc�
�(��XK�a)�����1i������W� �i��:�D�G��]!����V�FAl�fB�C!���gM��D��@`��9�x����{.X0	��;�;5���iy���$��*9���W�4�a��
�9v��|�����p��5 �.H��$~0B<����0	B	���i�[��	�	$&Ax�yk�8��RY0	������uH�� (��>�x >��5bF�&A�?�h�p�qF�:5	Bl]������a����R�-r�}G�y$������`K5��Lu������$�[�n}�����;	5	B9U7�;*z�=���I�{XY����F�JVa��Ym!Lc���� p��=,1	�����~`S��{�v�$���Z����0{�>,Z�6&=��$e���
�U���[�J�Iz+Y��]���!&A(��sR�&`WB�&A(�w:���z|z��V� ��N����fH8P����SX�6��=�{?��$��J3�}G�y$�<��
����O�&��ll��
�y(������P5"�^`��� �|S��;k8���%�������.�+9��+U��,�WA!�I,���>^�sK���'&A ����+\��=�V� ${��$0��
@�I���_�\#���g1	�wW����|h�o����!���-�:>�:�&�$�6�������EP���79;���y$��L��v#��N��.���!����[�N��""&Ax���y�����q�������a"�@�� �������e/�F�^^�� 4�
�������d�IJ�F6K�sK��Z� x���4����4
5t��� x��kyr�be� (���w@o�V�!&A�V������nw��TL�����v������j�}	H�]�6����|���(��	����&A������w��Gb�#���;D��F��D��A���B �~�T�DC
�@`�7��<����!�q)��-�P'�a"�@
�I���(�������a?�
c��|A��w�w�x�#�	Xb�>w'A��%�L
�I|���9}�Z����� 1	=��w!�������I���y�T�<�BL�@T;��V���[�0	B2��_V�������o����9y�p�CX���!�4,�p�354���D���U� ���a�y$�<R�}W	����&8(}
���`�D��0`�r�Tg&F>`�������h�0u��$oG����&�aS�
��&&A����M�Z��ds#Hb��B2qK�sK��	� ��������Q
;�� b�`�h��7���&h�� x���`kh���@�� ���&a5���h��F��5L��t����
}C�$GG�	`+UC�N-A������i�_�{��~(�I��[�i
j�G��#���6[�Sc�Q3!���>e�l�h@AL���!�3Qmk����L�PG�����m�&b�F��������������K���j1I��������5���f����y+�L8sK���$&A�6��
A[�����	����X�[�`BE��*"&A�{5��j[��d�6P��I�o��ib�U4��$���	aBD}Ka���/�5��T
r�Q��\8�|Mf����&A��S����%�y$�<��r��P���\Cv\3��!6���-��L�
.@� ��n
i+\��]4��$�cL���9L��}bjp��^rS��x�Qmbv[���% QxT�s���\��=��������(���%�Lm�I�Ffs�D��1;��Hb�w��6�#�	\a�$�{Q�����O�w�-L�@��7���@��hP�$��2!M8��8�o���|��os���[��P�R��������	��1�&Ax����=���GB�]!����F�@l�f"�C!���WZ�V���{��ar ���j��0| L���{��j�Y�H�8���*�t�F������IP5��D@�$����9G�sK���� x��eoV�F$��z�I��}LT�����,��`��>N��qH�`u1L��Vs5��o�k����4L���-6���G�l5	��z��&l�Zb
K!��r�=�{��~|�I<|7d������H��+�w���<+YcvH3����}��>�X� ,�!���GS@���=
2�!R���F;a1jL�@cko����.�x	6B�tG�����c� kP�k:$&A0�r���g��$����-�s��@��CAbj���'�L?�����v'0i|��8@�  �!i�f0��)@A�$��AD}K�$4����2��l�]���a)��M�XF7Q�
A 0	BB-�	l�A����(�I6����~�������P��B�.������M��y0	���l�9]E�l������X������.�HbB��f�x��B�3�&A���;%!k��($&A0d�{����	�� ��$�����	p��t�X0	�F#����b��� ����\,���Q� $����J�{��~��I|���Y����H�y$T�B9��?���,�gB�C!��$L0�D���`����q
&t���B�[��mS�NP�&�2p�brl��N�n�Y�&A`��7�S��'�<S�$D����:�=�JZM�@��7�����^��$�����u.{5�:z��l�� 0{��D��t��$1	��H�>>>�v�$?�<�F(��BY��o�\��L����t���w�e�u�:���\`��O�
�C�Z�<����i��D�I�I�<�B��yD��Cw`�-���%�s�o��\�z	6D���b���������5&��\�t�T���*��#��%�L��I�|0H�1	{��Hbz�;�Z���->%,&A0���������H�%�2L����Z����#�444�aB��f"�� ����&Axof�H��5a��jX
��Af��������jB=���y$�<��
��f�4�4Da�2i
!�[��+-�1
QB�h��$���FP%�*@���j��yS�0g���$�fP<�>����=Z|<YL��Vos�h�8�QP6)"�w��B0��N5�M�sK���� Dj���6���[��b����S8���E�/8w�@
�5
f+G�����N�a���K��h��UA��Ih�������G�D5	B9Y��a`kd�F�%����n���%��'v���������>��Gb�]!����)����qA��<B�����X�&���L�����S
�j��,E0	���JQ�������&AH��������zl�V�N� ��Ug�e����6�L����S!x���Q`�-�gj%L�`��{ )�"�	�~��)�H���P���A�������;!`	1N��I��T�3��J�����f$*L�@M>|� ��;��O,K!P�?��\���CJM�������8�H�y�b�������/��0����V
a����(<�@!�W��B(O�j�7��D��H0	���o�z���{l"V�"� L��7n��
W�/�z�;�S!�p�J6:@�-�gj&L�������S_������	%&A0l���a�[*�PE�� w��P�.FS���i�`����������	{
�0	B���{`��� ����&A���WoA���EK�a)������R�����j���&��:��Gb�]!l75�`�x���	2�pl����25�`�O�
� ��q;=L��� xt����]Fdi���h���%����j19�^�td��

YM�`�omD��[b��@1	��O�iPY�v����������kl8���W,1	B���jG��
��#����ZL�p�a�5�G�
�j1	�6����L��}Ca�w��	.+\�=��%�i��	u�:�� 05��	G}?��3;�P?�<]m\��'�W�� ����	`k���%����!v�5A��j��!�D[����
[}��X|jWL������C4��L�=��A?�;�a��}X=����u0	B���c$�'+S#�=!�$��a"�S��oW�#��@�4� �W~�B�
�q=u��P�B��}���j|�G)��KG�	�.M!�G�����n��u+A�$%;_�����StX ��C*&A��^�����k��������j{Ug�p��835&A0����a:��5t�,{B�I6��3\�<PB�/�v�������NY�u�:�a�u:���������I5K�6����t�7�$C���fz��������gS��u���$�z ��C�^}�~��)�>�cS��I�E��<v���;�S���sQ����L������u�~���<�K!��^�@!�@��n�I�Wg�P'�_�I�f-�:���w���$S�*N��s�V�@/F*IL����S.���T�L��Iz{�������~��)��Y������%-�~��+jpst����U��C!�-�s�/�����~)�9���~ W1!nS�$�S+p&�MR,L�px����W�^�q>���AL�x����J�����"(k5	�o���[B��L1	�E��=�:�+�Z�j�����:��U9E�Hbn����P�)H�|��� $��G��:S}b5u����^���>�wX���$������V!��:XL�p��u�O~��;i��(1	B��o�v��-Agb�$��*�����`B��E5�@�lc�LKD��� �[�2�uvJ�A?5��O����:M8�Wa�w[��p��p`-M!x��y����K�Q��� t�j��NTz�A!bC=�;��H�=({��$��,���s�^u�b�$�����
���W��I6�3P^ux������
!>��=u!"[�`B�&A�hb8=ER,L��=9��6�9��`�$>�!&A����WU1��i(h�m��<���T��-�gj&L���Gsm@cjk=��$�����y�LM�E�vt�`��s�N���B���
�0����>��/���C�8���!��4�p��p�N��� ��dut��%�/����$09�C<��{�efo-S�@�}<SW� 0���d ����}
�e&X@�)����*(k5	�<����BO|�����v�}�������&Ap����Pab�%(b5	�F����������`'5�h� �&?�)G���<�.������m�a�-�gjL�@�c�E��E���$&A��m���Q��H`�F���_�@6d^!\��#$�=h,�$���S��P'C����R����B��n�a�C�:$�{�.� (�����N��q[�7ps����O�����Ao��
�pl`��sm=S�`��O,�	��m����f7����7�W��)&A�����:�M�����"s{a�u1���/��Pw��Pu��g�4�p``�����g�`�-n� ���!�����r ���S!�;��[���&��y`�
Ug�?qf bj��}��c�"���� l���9�M9�Z�������0�N���_
�������S8���6,18u )&A��������*��
��$br 
�����)��m;BB���B�	�O�)&A0��f$�������`��Z'�?��Tz��P�6Yg�?�f��2L����{<�t����!�4��n�u&�p>Q_�$�O��J[cu��&A��w ������!&AH�{Y�:o�i4YM�p��:�14�\ �$�I����fJ�3i�AQ�I���� ���0��.��bj��VK��?��h��4�p|X��g�u�.� �j8�g�V�F`\(&Ax>�����)�^Q8Q��Bg�?�f835&A0�CW���X��!���M!~�:���4CA/&�
a����g��A� 
�������W���_
��~�����)XKS�_S��3�C3��z&Ax��:�'�-�*��51	BO�����K�g�DL�`�om�>����0	���|�B]�?�dz�[S�6[=�?&g�"�eo]!|?�����)���6���f��;�Sr��P�$�>u�rJ��.������J�J���!&A���ww��6o�G�^b��:A��U1E���IL����?w=ZZa�z>��gj$L�����!��Fgw�c�JV�O������OZ���~���/�4<�?��$�����c��������pE��@�>�� h���?y����;���<�sn���x�l_�V������g���7������
��6A�$~��S�y����������)��IL�0�����?�{��3�V6|��!�PS!x��������}U���������35&A��_��js�5��O2\���@O 1	=o9L07_=��'�L���z�SW���6��=��i�����;�
A�~
�_�r��p��������B8���(�xw"hxACii
�D�����@���!&A�d�J�W�V��������&-��YM� &���0���g��-��V� �h]0X�����gj������h��p�����y��B�&A(�_���}nU��!X��$&A`��PDK8S�R����5*h5	��K�����:����h1	B�f6�������}��F%-M.��^�g����
���������w�p��'/��\�#&Ah����Z��sh�?���3B����za�-�gj%L���G/(V�z,zB�I��.\�9f���A�� X	��� T�����h�OHb��?��+������l���_
��7;=��w*@Cii
a��_��1;������^���A�dG����K����I��������Z���8��R����RgjL�`��r�pt�pzURS�V�2�^M4B�h�:U'"\�!0	B�h�uu��YC�O�ha?�sl:l����
>b��:���s��*IL�������n&=�����0	�G�>���g����n���Hb�����S�}C����z�PW���k�2�5k��t$hz��P�9����N&*z���I�y�d;�iu!t,QAKS�5Z��TT�D]
� �����S�@�_�u(��GL�0�C^i�OSo��#�������<yg�����N*y�&�$%�l��������y��I�I����WK9��L�
:5��MC]!T��t#��7�����$e{}zU��T�B�� ��^utdlz�PS��u4�����4��g�r$_��;�����M)b19�KSO@5�AI�I�U��I�^���sK��Z)&A����,���:����$�6F8�,��h�
:����G].0z'��>�o-��V� ��V�@'8�Pg�I���\���u�N-M.l�_�Eu���=QW�����{w������/����$&Ah������)U��T���P����
\��T�L��IJ�vrlut�SQbb�e������E����B���b)�Os�7��O�!�uLC!T��S�@g>�Po�$��f��7��O�!�4��^��7��OEO��0	B��;����|��Ipq���{����:�	2�2j*O�qF��T�L��I|'�	�@>A���E5��P�Oz*>�NzvzQTW�tr�put�SYb�}�]}��T�B�� l?���8��1���B���������'�k��z�;Y�n���/����$&A�I����3�QO�!��QS!x�.H���WO�-�gj#L����7���+��=�����$���P=�����B�����$���^���$�}0�	�Ne:o���)j�����1���e�7Fu�@�����g=�/����|	ff���i5	��<��I)h�cA����$���v=c�s�2'��[���B1	B��� &��1�'���X�I�>)shY�
�^$�����F�8|��EP�j���>�G�B-b���}�h8A���������Zu��Q
���E��&�.z�`T����/����$&Ax�8�Yu
t�lz��T���R�[���J���0	�'����+��%�Y��T���"o�A
�A-{�W�+B;h	��:h� 1	�'��*�t�R��4L�P��k	���p�t�RYKS%|3���:����B���������/���3%&AhO��Z��T�����RE�����gj$L�@hu�������!��%�����Jv��������A���
�|���C�t�hz��P:OI����D��%@0	��F'��u�yG%-M!t8y�)I'_����,JL����j���cR��G�!�MUS!x�>���a=�����0	����Y)g1o�{b�I~��s�c����^���
�������,���Z��!�P�t�	n�������W?L�st�TzVS1��:
��}������t��#��a��:�hu��qNP!"&A0��~�P��|��$~�X����NE�I���u���NE���pu�p��u��iNP!�=\C!�N"��ttS9u*L�@#�����c����Z�B8�h�	��M�N��0	B�hy�b��a��`<����V� ���B�����BV� X�{���%�L-� p����)N�$�A�]M��v#u��1I�E���!��S�N@:,����������[g(�T���?�]���NM*|��� l�+�tF�%�)�{��$����s':��$����<��"�=�����0	���l��I�
A/�j
���O��oD(^�IzVW]���QA'"�X1	
���`�����
^�_a>~i�� �H�����A�}���'�Yz�UW������1\��|	����)1	B�u��^l_@�"��^M�`����t*R�3�&A����N����E*KL���;�R_@�"�,��y�B���'�@U�A�!"&A(;���=u��:	L�Pv����������D*hi
����L]�T�D
� PG�����"�;�q������ w����H��<&A��7f��u���@e�I��FT�6t"p����B8L��@�@��k���"5�~��:�l<�MCb������E�:��<���$}<*	[G���Q0	�aVB�QD���g(��K���w�B� P��4�8T����z=�.&A8��dO��������
�������3�F����AL�� C_8�-�A�]M�`9��e2���[b��$1	���(8�pAY�I~�G!���|F��������4<�pD�bW� 0�v����.��""&Ax��b�B�"(kir!k���u�a��{�\86��4���i��`}��� 4������3��f`C�;|�B0����n�N�)u��$��o2Y��4S�������T@G��-.�� x���@����7

�;Z�v��R�P?C��B�R��X��3XKS����f�L���6��6�l\^�]C.�CP_\$$&A�����m���V!aU��h*��������s���$��=���!�!lz{QS�^�1��g�H>�ba����_p�o�)�^R4�F�tRg����k���|�������:&A��s4����:��J�B���(�@��^���HL�0��=y
s���	Ao"�
!2���-QgjL�@T;�uF�4p ��CM!n��o:{�T����6Z�s����A�
a��s��e�w��K!��
��p:�����u7b����,:��t�����~�������35&A���������Ng)JL�p����pL:�5�u;]!���:C������������W�B=���K!{gy�H)h�	��:&A0�r�
�D}A���
�8����z	��L��f5	���Tutnl����C�����S���)�/VL����TLM:�5�e6].�P��JA�9I'���!�n��R��s�!#&A��G�Vt���$4V���R�D�)����t��eo��	GG�^����9FL��9��z�uN�-e�I��3)�!�R�L
�I|g
>7�����g)DL���l�����z:��h��������
t<K�� ���&��PgB�%1�R������%ut2pzCMS�s�@���R�D]
� ���@�K�>W��I����4�����cY@C��i�B0�*�+gn�3S�`�pBU_@g�"&A�vw��S�N_)[���+���g�WA���%&A8�����+�.��0	�o�����:Z�R��B�����R'�bz�MW�v�z�����H�
�}FL�0��:v��t�C_�@�[n�B ����sK��� l�N�;���^h�����qt�lz��P�} /�����J&A8��:��x�%�gO��)�HMs�:��H�2'�b�����:V�pt��%�9:�j��$b�n`��R:����$�>v������35QL�@`��!��&����>!��ZM�@��;�������|�^*���g��/��6�H��V� ��V�@'���Po�I����{��#��hut�OIK��^���h{a��:����z[L�@#m����`��}/�z��"�1�Wu�+��

�"hx�Tf�F�^�� p�m�cn�n�*,����5�����\&�^���B���{��o��B��2��^�2��~w��T����\hDaJ�P3q��=�#�Q����0u2f4�s�]]%O��������r��fB����������w/��h��"&Ah�)%]wj������`���w�� x��_({n�=S3a�6��!~!�����<����$��������(��N�� x���k����r���C���x�^��az�[���w�Cx�B��g�B�����;��<%O��0	������%��N��7�PzD�U��0b��8qd�z��8�����!�m4S!x������=�����0	B������V����JL�p�����A�����'�$�>x���?$?h��$z����^��!���~)��������h���^U���'n.�S!��:�^T��A�y����������c�$�?8u�e�c8�)4�`��)W+L�^�2�A���12�`ZG��Q� P�n���A���=���I�}�C�Lg�^�	T�7YM� &��x%)��JA9�I�qQ'�]q#�=�����bB�����$�Y'-��S�jO���_'$��S�*,z�J��>��Y�u��98%�&A`����I��f��tN�������y��z[]�S������o?�{��qJ����$4����z:��C�M'b��;����Nut>lz��T���WZ�����3�&A(�Ub>���A/[i
�z�i�H]��S�z�JW%����7��=0!�+C!��Z�tnO�u2L����V�@g������4�p�s����!�E+]!xt���R�.��IK'��&Ah������l����@� x��������#_��y�6�$y�I9��q�I>%�I�o!�7%|G����9�$H0	B��g�|��'V�AG��#&A(����>E���:����B����������)�o�Qut�O��4L����B�s�S~/���{#&A���B�e��������Z�]���U�@g��:S�`�`��yy�"!��_:|�$1	�%lH>�~���IG�������P��������7\��/�P���tv��;�!�M?M!��4����)z���I���uc�2����`�2.�� �[���]`���sx�� ��,��K9&'�xD��=&A���W(S���-z�NW�6\�&���^�3��p��tFO��*�����G\g0�S��!���7w�:QgC�y�B(���g:��tRO���2	L�t�^��Z��?�gH/� 0�hBR�sK������&I�y^h�!���!�L��hD���z����������6#�f�=�i=�W��^&A`���h�;��9�WAQ�I��wY=�_%�&A��6i��3`��fn����5b��;�0I��i,dzs�TD�O����a�-�gj$L�p�mN�a�
3����KL��f�1Q����z�NWou7���1��Ao�
�$���s�n���n��*�v^P�����7�4�p���=Q'C�{v�B��t3m~HS�����u'��FL��UG{�����?��hz��T���z�����?{n�=S+a����{���&�V����������������y=�A���
���������9�L�����3 1	�r�
�B]
W��K!x��������3{��4�P�;����G�x���I<��B�>���/���*X�����$CS��O��Z=�?�gHbB�?V�����L��I<{����bO�����Jt���?�{-��R��wV�� ��=EC�;��B����i� ��=�^��a��G!������3��)"�C��~m�Kz�����u����mZT�CK.e�B`py��a*v��R�D��zo�T�>��X��[B��H�����V��E�BDL�@
������Gp�lz��TI��7���Q����*��;C!l?g�v��S���]V���h[?�l���DA 0	Q�1��R:�i[?cU@�b?�vo�(z"�D
AX0	B�.�����]C�
�q)�����������5&A(������p��U0>���Q�I���)v�����EP�jb��f�2�������N1	�����*����P�I,[~�Ko:������"�$G������@,B��HM��0��J����Qi��rH�����������o0L�p�!���25�L1,�p�!��"��'j��0L��M5�Wc�@����H�������f���1p����y������L8
P���v�U�ii�[�"(k\r�v�\������5TL�P����3^{l��Ehb��/����{�"�3^[����{�%k��
s���$����J���5��C�
����5��46?��!��6T�:��|swb��drZz�����M�P��������<��44�a���
i}��$��+��G�	{���B�������&��'t������(s����=���GB�]!l?lK�i|i�Nl&�<BB-vi-
,
�B�h`�$��������/X0	B���{Ce�j L�����-sH&� �t���U�����I:L����
�(��<01	�wwf�u������0	�ao�X4����
A�l
��x��J
v��C��I�g]�{PGk@���@
� x��wi�^l���
� ���M��� ��[�&A�Cls���B��ZBK!x�Yl��	����&A �^X�;B�#���H}W�d��.������ �P���Ou�h'���A�$oNg�V��E��h��$���R��D��
� x��e���k5�`C%.�� ��������,ekp������������_�1��Z	� P���P���m[O(1	B������=�-�����ao/4���5u4�ss*���Oj�{�Mp�~�8L����$����A��7XM�p`Ve{IAkx�v�%����������=�z?��$uK�BL��<|��w��6O����R5(b�6d
�7���$�����x��h\AL����]�P5b�FC
&A�����@'�a"�@��I<���g�Kr"��o�h(�^mp}��az�"�t+\c�l�D��k�B���l'������35&A0���H�j�^�'�������A
p�F�z[nW��fWc/�xP�j���@�� ��M�6���B��=
k��D�S�����G�n5	B�n}ML���r+Y� �j-����m��<��=�{?��$�K^�5�N��H�y$D��o�n�O�������L�y(���l�Q�D��@`�������52�&m`��5���jB��rLTjq�j19�������EP�jB����va	��%�L�� X6?^�*��J�����&A�6����#�����^���7��&��;�u���u<�BBM����b�/����b����/?����N�!����5~\�}O��(�����;b�#���P}��������������\8�d�wu�1$ b����H�g�P�}*�2�%�7{P����LL�@�H��2�;%���Y�Dxi��X��-&Ah���{��D�4���!���S!��S&��[b��:��7ww���D��5���r7�@
�AA	+���Wpw�@}�����)b��!�=�S!�SD���
����=B��;GJ>>>��I�>�P%3�@@��R����Tj���#VM�pd��lB��H�y$T��w2B�8"��!�5�@Sh/�#��=��� (���m����F���!�4.��f���&b�J��k���3zg�%�(�~�$�y{����g��:�@� x��/�&��K�
���0	���|IX���2��$�\Bp���Vo��
��Ps�Y�Uc��$>P�B����B��YV�j/��{��ih �$����4�	s|s�-U� �#8��������H�R�����9A�=�{?��$G��sj��<y	�w�P�M&9�V��@l�f"�C!���3�L4� H�0	B�pC 0�lk��&�L�p�g��a"�@��I��M�9@4k��p�6k��	1	�jrxS��l�k��-�����<|���3!�-�gj%L�P6;��N����x��WO$1	�Aog5�	�O�"�g/�B�
>�/��?��
��0	Blp�mc���D?l�hX�$�����4�	|||�
V� �a�V�F@��Z�K!$�9;���M�}O���e5	B9����w��GB�#���h@�
l
~������B����D����}�2L����G
M��0| L�p�ui�y��n"�A/���LV� ��^2�����H6!����$Z,D���=����yb�]��H��5aO�j5	B��S_�qF��D�\�N?����w'�a����H$;��zYL�@���F������D� ��Ns��� ���L0	�p����za�=�{?�`f<e��y$�<��r������5`�2jr!�W�?�)u�% b��k���\��'4��$[�Y��p��8�IL�pd���
B�zm��DV��� <��7�<X��D���L�P��<��+��[b��F����6h�*+Y�v#=��$���6h\��#h�<]!4g(5���5���ca���)�"����"T�/�����k���Q�� ��[�&Axg8��&�t<�@V�a)N��A
j�{��~,�I�e"�p��8�H��]!�sf�
3�5�a�1k
��'��L�
,��I�N%�V�9lvhP�$	u���B����&A(�s�)q
ht/�K�1�n� ��K����5���$`C��FM�`�1������%�L��I|���j<��I����j
�����)
AF��J�I<y��A
pt?	���QS!���L�&��$�~?i(�d|m�����A���VM�@�i�~L��f�!5,����6���Q�������#��50�5!���B8��m��eN��0	��=�1��
P�R��ls��a"�@M�I�=W^��4a��
�����oX�wg�
U'��eEk��������<��E�
�[���L���W�GeV��!lzb�I�H�P��@�A���Bd�\�F��
��0	���/��?�
���I��bf>>>���I
n�eG����@��PK�a)�c��Da�=1{?��$�u�n���Gb�#����������m�k���h&�<B2��������'��FL���p������a�"W0	������8a1jL���v�+r�����`C#��'&A�����z������~Cp*��/��O�j���?=S+a���"�F9��l���<{�wa���E���
��}�|���N��7�A�c�t����~Ho(��Yg'�5�� �}��$�+R���&�% ��Bx��M��A����&A�����	wt����@}W�����F;�l@�C!����[s�A0	��e�]*@���ioy01�.Q�@��I�
w�_>B������\M� &�`���J{���@�p(��UP�j"��G���y�&�I�|�����[��X�Ijx~7�F;a#
{z�g�o7\��
��(����[L�`��G�4���& b�F�[L��Pw����3>�3���$�d�g1������P����;���M�}O��f������<�D�G�].������5�ag6kr!�;?��:�1	��X���r4�a7F�IL������&�a"�@m� |7���FW��
�1W1	���#��i`��G������
���ot[55�tD�3�&A���r�!��!�~A�)��
�`F�(U�xlW���uAMDt��8�5��%$�~�u*O��k�grI���
�-��<Zn�qK<,7L��� ���&Apd���]��'<M���A~h����G���7�l��}H�D8a�=�{?��$����g�w�'�y$�<��
�����~�5v-0�8����L�y(B=i���x�('����$�����D�	|+ZC#�d4�`���:������	{�&B�H����cr��Mu��-�e��O�I�#7�
��9�#2
�~y*�|)A�sK���	� ����Vl�GaC��#7���;�d�� ���G�
�|��o��yG�8�J�T�w�6b���0�b�F�&A ��7�5�=>=�V�I<z�>$
z�F�4���-_X_�������7>h�������V� x�����Qyu�w �#���@}W5����_����C���
�y(��|M��?&���@%l��I����u*|�>�x�IJO�}��^/��`���*�k�b����!���V��*����_��
��{�\#	zn	=S+a��>;��B5Ha;�CL�P?��v��(%h�!n1	B���u�F��1J�r�2L�P����5��(h����7L���������=�=>=�V�I�/?�M��~�%���G#h����CK{=������j���������Lq�y$�<��
����j�0Z_�"����8���Jx��Qy�aA?�>BI.��F��1;*h0	�e:�`��|��#&��D��Z	� Y_�K�r����������*���b��d����r�5<��F�*�Tn|�W��g�e����[b��N���;�����5JbC�IL�`�G�*�Q�"����B(�9]�h�[�e7P/�$������h����
� P��J�z|z��V� ����H�dG��[��H�R��U�\�n�V����D���V� �d����p��y$�<��
�|����5�����5D�Nj���I�VkJ|6�~V�(����a���&(�&B4�a�b��O���������������������~������{�5����"�������I��������,��.����w����������������]�.����l����������������w�og����v���w�og������������k�3NV�_~���1����U�+���`��������������?�����_�������s
���w������Q�G n?���|~��?��O��������_~����^���}���-
�����o�
�?��F��}�����v��?�����en�����G��O��t�f��>J�����T�����
/���e���U��_����e��~��XV�����Q���J���V��~���G�?N���6J�����O����X�m���?��~n�7�8m����h��\�C3n������P�8l�������:6�v���z��i����=9�������=9�����=��s��Y�x��%�c��o_��d�����m;=�������_���3i��=�m����m7}��O�|�h?7*;�����y�������'s��w����G��������/_��|2��S�o_�����;u�~���}��r*���u����l��t�C�Y����X�NCU�/#���EO��S���En���>�����S��'������������3>���w�����:�~��e�������'����N�N�9[�g�{�P��
>��I���o���M:$�v>�a�I���K:$%����8Wi�tH�����'�J6��>�����$�3��k�wrf������i����v)�a���y��&L�!-�����M;$�.U��/������$�vHK�ve�n�i��}%dN��M;��l�&�p��ui������M;��o]������b.�P��s�����}>���������ui����~!��������/wi����~>1�m{����v���������ri�
o{rD��CZ���A�vH�����I;���h�!-�|�D��*���CQ���T� ������#��~���=5�c�7=e�r�����{�;�rh��:������&���>�q�����k�:����r�!)���f��;Pl�!)����#�qO�!}���_e��C����
�q��i�8�C�y�|H��O�l�!)]V�gK7y��?�Z��,����|=��;���ye_f�I��/�\��(����*�wHK�����G���lv��
g{r���C�m�Ih6=�+�p��6��>����@�wH��o����}>�����>��vy����|O�!���_�������=Y�n���8�w�����_��p�����36�Px���#~M���_��G�S�����=������n�����n�,�����C����I��n�@{��(���Ep8��o����3	�y��a�����v�u��������n�.�0OI�:��y������wH
>:o��>)�����J��CZ�����zH��������i;�������?/,l\��x���y�")]�7����ve�nSi�?��C�������A�Ri��^I���CZ����K=���Rg�]w{����=�����t��O4����m���aR����|2���g}S�!}��i��C��_��sc��
o���7-���~�m�zHK������
�u!m��{�_��Ml�!-�����K=���O���b�����CQ����z(�[��=��8������	�~(��#�ps'����~����Gn6q{���N<�)���In�w?��������<<>���"����k�����
�sdE��&��z~�c�Y�����|�g>���J����N����~�n����?��?M��F��/�Lf#��]�%��F>��_y��d6����#��l����~r�g2y�?���l2y�\���d6��?W���U���K�����?�;2��=[�f6�������j��q�"������F�����lf#��&��F��/��`2�eO�@�)�����r�������#[����?���$G�x/$
�=����w�l��r�����y��S�q�L�����\�Y�c���|���
��u�5��G>��g*��>��/n�����>����>��/\51�-���>�����1m���5��G<n�f�����.��O'�����5��O�5�qw�iN�cL��/�$�Boy�#+��Uk6'�|�(��Id���\.'�>���M��H��WlN"}�����������O��$��?/�8����I�����Au��HK�q��R��HJ���N��mNb����-���]y}��$����t�����_����6�4o��_�<��(�����Y��Y�����D���_��6m������KO�|��%R��:�v:/����}]Hp���y�Wb�KF�������~�"�Z�\������K��������^8��'.��t��EU���@���o�9-��&�����F����y=�q��7�tAz��=~Q��������O���{�<���h�i'����ut���?g����a�L��u�L���?T]�D$����GV��+'��Y�W�.��}�0�KF�����&#��}��Y�^8r�������[�6����z�d�m2"��oW���dDZ���W��HJ��p�q!]`��i��|m�nHF���pG�KF���~�vW��(��
��[��; ���;^������.ko{��6Qz��7R�TD�.�&`S��=��v�����~�G]*"���.�\hv���+ �������.Qx�) ��(J?��KE�����3��b2�?������^���
�N���L�d�~����E��CQ��m,�O����l�����������<��8L�����/x���:���=����8��������&������{�I��O���C�$�o)]�!-��	S�~H�=�^�O��Ig�~H������6�����'~�Y���_���
���?�_�|�������mU�~HK]�����CR��u���������|������_8�������������~H��-�g����u�6�Pz�����Jo{6A`�Et;?w\��������
{��6�P���
����#��ZF�U~��]�~���z����S�oR�.�������6�PL�����C9O��R�{G�!-���w?s��X}^O>�<6������7j�������4q�1	����<q{�M
��gmRw?s��(���n�K����_�����H
�p��y#)��~f%�vCDR��W��6�>�K t��>�+kb��(����\"}����'w96����WJ�9���_;���_f�_�|��>FZ����ri���|��� �������A��m]�Vw�r��=����A���B��� �py�l��H����������i��H����Xu���^�'�f ���v��[.�������\"-��w��D�m/�Gb3i���������/�D���j*]�?�k��ob�;E_�����<B������/yL�r���y�9Q<��o|��!n96;Q������9��f'n/Z�7w�=�v�
�bVu�����mr7�/�_��x|.Z���Ep��J��_#�1�����8v�*IV���6�Bo��"+���]&��|�E�y�����M�de�za1b�(y����Hg�WG���S_����q����C�*��Ko�h�����Gg(y��/\�o(y��W��'P��_?�]�ri5?/\�j(y�\y2&�������@���:k���'K6	�j���@����#s&�R{��	�����*c�|��+rN�t��_y��&O�<���F����_x��&O*O{���}O{���I�T���h4����^��V�'�p<��@�$���s!8������.8��|����a�pkE�O.���|��!{c�����Z�Zz��6������m�����;Q�#��Z��;�l�U�
]k|9��zO�!)��
�����9���H^����
I��V�6��v��]��7$e��������?���o�lT���{�6������56���~�S-6���~���.��������6�P�����qHK����F6�p��u�����qHJ����j���K��C�k�'�����l�!���?��2I�?�\@ilT����|����/��`s��=��v9�
_{���j��{��C�k�t9���^)]s���p`c�,����dn.X3i�7|�����3i�/�U���sS��O��T�|�S&�p����1�.X3
���#�P}�
�7?=�qw�5����aWv9��z~�g3
I����|�X�fHJ��XCR���=si����h��I���|����}���fH���4CZ��+o��4CZ�oNq�4CZ��w�]���C��fH^�W���i���?��a��zZ�f����4C�k�����o�0i���^x�6�������M3����W:6��W6�_ov�����k���yp�q(����6�P��������LO��v���\��p�?��8���������jp�9����K"U�w�R�~�����}�>�����4��R=���L���{��(�>�����WO������=q��6�������n�o�@���Mj��n��W���������{NB$�v�`��H
>�?q��������'����mH��H����v������I�\���'���-?��~��9��HK��J���D�H.�-a�����m~"-��+M������1�^������D�j����=C_���Vh6=�]�����/����P��x��m��H{����\�"���^y�����>a�i��/DO��(����%�=o����+�������S�?/|*��%�9����hMZ��w�%�����DQ��/e��C��O�t���w� ?�&0�!���x�x�����81��7:n�lhU��=��?�^�������^7���y���������);�y9��{G�!)��c6��|���HJ�����?$e��H��|w��������1o���?\�zG��?_�%�����]����?��_����Q~~r��CZ��K�/L�!-��+���CZ��W.9������p>�p�'��=Q���9�}(z���0J_{���y/��.������b.����/��m�W��i����_C��9�t�|���D���_	������KF�=�{�=5��(�����MH����iC��(��_H0	����7^jB�(�|Ew����Q}:�aEE�>�a�7��������DQ�����r�f�~o��?���u�I����������&)qs7��:?>�?�,qs���:���*HV��.�B��piR�c8M�#+��[�6������w�m�#+���z�|��:������Mude�y���Mude��r��Iu�}�����TG^��+���:��/p1����W^K2��������_�g�����G-���������;�����7NT���2��|�\�$�Iu�1���D6��?�{n��}��t�Iu��k�A����z�'y���|������F�k���5�Q~�����pG��kT����<���|��cEz�D>��X@V����FV�*���FU���?������A��Ogb������_�����]hn���|����[���y��/��w��������.o/Zo���9k��[b�/'�B���o�
I���;�|��p�l�����K6�����k6��>��'��WI�g����l*����\�M����_�
�����]���������F�nHK�t��M7��_�������z�w|�4/��[�n(|����:[�n(����o�
���!��>�{>��?���q���i�OI�tC�k�������i�
��lB�����]H��tC1�/�������
_{>q��
i��.��e�
�D:��6��b���Q�����&��O�������/�������I5�Zg�j(�|G�!����;�N�^g�l(B��d��h�
w?�l�y<�cU�g�Mh��c9~h��nH
=��M7$�����������
I�W��K7����k.�G}�wB{�!}���dCR��+���dC��?�������W6�6����J6�-�,���|=����NJ�v�%���p��K6�����'g�M6��i]��p�g�&�p��u��b�?7a�
��=y��&�g����
��>��\�!�����%
_{�7v�l(|��k�O������=_�����
��=��K6���z����N��_9c�
�D:�Z���|��I=�PL�;N6E�q��(��ox�O�t&C�����6�P}�m
M8��z���:�����u�
XVE������C�$����&{��87Y���yH���Y��\ �|~u�2�#���s��S����Q�s�e��/�hm3I�?��"m�!���.��K�v�"�y������Y
�����6���~)We3I����
oU��_��������e
W{���y(|���a3��%�P���H����c��>\����7d
_{����<���p���<���v���n���q�'�yH���x���j���z�M0�y(|���������u�H�.g5�D���>�DQ����-n������x������H���"�s2R�4��|B���d0*?�[�u ���0��+��~���?>��'D�=�N"�5���|��)�����W�G����`���z�����Mh��(E�RD04J]}"�J�e�azY2`!	�������]og���oi�FpS��Fpk�G�����](�{'���a��p��>�A�=8z%5�L�:���<������.8�Zh�jG�T/�����aE[/rR#��G�A�SSt�--hy�F0���Q�����a�Z���k���X��}�Q�N�,���<+�
%@�Fp�B��5��+�A������q?o��\t���+��,��l_c��qR|���W|6~�'U`��~7N*�u�*0,>.k�kN	�_���<= !"|�I����GR!,h�,�A����yewj�������Zn_�@�I|�n��I�8&��!GM�`�����
jjc�L���JSP� �;��$Ht/W��$J}�L^Ai��W�+6J}�����A��������}�s�(mP��}�>)��G���B����!�C-�3��i�ZZ�LQ����Q������If��v|i�����K��a�Z�3(�6(z��4K�v+\�d��k�]Ei���[�yDi������T��)B�0<T6(��v$	8B����2��SaE��D�-���?n����#�+c7�)�M�zI�T�\4��#:	
7j�,
4&���/�Ph ��<�Lh`�^&4P;��(4PS�	A&4Pk����(4�ax�^���r���Wrt%5(��C��Q�S.4E����z�#�B�����;z��`DZ/2
F��{IX����(4��6@h�������3��#A�X�|�B���Z�Q&4�V�


F��b��`�Z]a&4�\�rX��BU

F�&���`�Z!w���t�����\�=E3�����
R	�����`@�pDC��z>Pn��s2�WrC����m�^��C4t��k�$7�h��%�,7������Qn �1�+�Z(����](��(7PS/(7Pk���d�;!�7��^*E���@�7J�G��s(���@�wJ�<�
������(7P���
���g3����z	+��l�6@n0cm��@-�@����*��u�1�h����dr�k��H3����Ac9�s(U4K�v/�}&7�� ���kW3����w�������8�B��������2(�����hc��`@��6�
���J�p��5�+5�5�����E ��&�;/��`@�[Q$�!rh�����������SQA�CZW2���
jb�\�)��F���Z�����&C���1&h}�\w��`�<H{����e��q�4
�(�Nh��i�O��b��>\��:P��R���k��(@{0��S!��=Ti����9Q��cgpk�g�f�}�	�Q} �J����9�p�yn�w?��o"������Y�P��	]���r�
�A��fhp�R�`C!��a���idg<t�}0����n�����B7P&����[��F���`s@'K���!it�6��~��#�H=�&��A�0�#��k���RU���c5pH�wM@m�!+��Q��v���M-T�CV��P(���R&�^��;]P&8z�@O�^IC;A��{��(�p�K��I�`����=9�� �2aEZ��
��L��a�Z]��c��If�%��cYr[��Kpk�3�P�`�{el%dE��Z�\b�\����<.D���s��X��<^)�oP�����G��>��[�x�]rG�O�������-������k��r���!x�Iy���5RVD44h�V��=Do"h����`A��_u�,h�[<ht@��s}��w�}=]�p���O�~��?n��������|�\���>���6s�?������������������~���������%�v������4J��
SmM�b�3H'�**���7��n�p.
������&���,Os�/������?n�|6��n}3RzoO�^�	z9�;_����z%��?�f	]�cy�/�kEW�B6��N�_)��H�\p���������~w|�]���Y��	R^1�:�^�r��%�CV��9{+��������6�"BZ�i:�6����)L/�t@%~<t����9�����]��������7
��k��	����uNHP�V�����	[�4I��\g�SV|����R����B���ZV�7<5C��f�����|��<�G��|������?4��r�����W)��!u�B��i���?�W{�gw�C/Ft��A�HJ����p��~�����������z����������k{=^�%��7����iN���uo���W��/o�����/oM�^�����s�0��w����{����?�h}���������~�����O�>�d���Q�f�0�H��J��m����f=��Rf��>]�"�^���h���UxoC��$�vju�} �v���R�nnwn*P��5e���n@GP�h��y��i��e�?�t�NP��dB.��RH&������z|o��o)�w����}��\9�������g�.�e�3q����$$w	z5�k8�$�w�>�}�w���]���)�����/�w'�����n������.��Z9�(�~$t�Aq��t��W�)�2��]����&�h@��\����N<�@�a!����x�u�����������Vv�b��������u�Hq���M$�!�<�����2]��d%T�f�������	z1l��)!A��{IPB���D���r[2J�G%�~$PY���*��F���)bq;���{v�?���=��(�{[2^g���F��J)!�S
�[��R��AJh�^�����)��@+-��m��A�th@��vK����-�>@�&���%KG����<��]L�����wJ��|��~�Hv%��aU1�>=��r{�������R�$���0s�)�;�R:6)���0�H!���
H���!}��U��R�O�J�CRhY���I!�������2<I!GW: )�'F9�@
�#�����Pk�)���^%RhA�����M ���#�B~>��>%�r`�������w��yt� ���p��f�z�C�� #�{'����&���7b��1
�9��&A/�����T��o$��j�����J�j���eT����h�H5��������J�s�%��&�#e>dF5
?�#�4�HH2���GR�����IY����i��S~�:���O)�E���'�z::O�O��4�j�,h!��qE�#������"�~��~��y��;l�lJ�����+�����@�@�<b���8�Ld�����C$���e���8Uq�o�GVq����J�#S���bT���@	~5^��e�����
Xyd9���?Uq�o��{@
�f@"U�U�'�G��������*�����o��?y�`�����"�\:��m���G������<TYn�L�C�nD82T��o�(;��B�������k��������Uv���v�e�������wa�����B��2A�`o�]��U��_�Imy�f�^��F��+!�"�v���.5��K�?���Mi���jL
���8�NP�3�NwU���.�S���]����;�~p�v
?
�P��6���K�������oNz��7��=���:2��;�h���\c�E�|��F8�����v���0z��:�,�G�"?$������C��Q�	�l�P"�,%���%��t���,��t7����~���U����]:	
RBz^6����]�)7��Ho/��"��$�EJ9P;�����_y?{�1���J�����uP���E���B#��C�J��J�F!4"���\���Ma�j?��@����n~�0z�@
�Bx���s!����C����FE�R&#^�mr� !����T����������)z9`8��;*%&$Bh�o��Z@
�c)!��"�%�a��'Bhx�0�2B��vJ�s"��	g%Bc?R���<�v�?��4�-]�sK�-B*��
���nB�W���C�����Zh�U������94����A���TrdX�]rti��m}n���o�[���B�EG�Z{d��`�����rl�MRJ)�c���RJ�EGNt$�}3^��I�ez�=��b	��}F@��\	Ww%�������3>��Gj���_>P�-)�����)a�RP���y�g��#����������MAg-��m._R�~��t�����H/�N��>�tU���%'��-m`�4��KjZ����a��aG� �Pr�W<�N�K�(z1��C�^��bN��4����k���R��a�A�f.N%G�n�d�V�O%G����G����?Z,����C	-sR���C�{c���1��K��R�*�|W$����|���\�(���|�������%�mD>8���f�H�v�#��k?<���q��IS��L�[/@���s?^R�����k"���M�_}�,@�{�&�N-A��5�EG�����@���i��`�E����+
�{#���K������`?�vj����!t����ur#�" ���F��z�^��3D\��WD?���9W�"��Gr{��$�~~o�+�~��������"�g��F�F]�p-:W������'I4\K�d]������7�zt��tM$�141�S3��5OL
`��i��1��X�d����4e���Y"����:o��������N���#��T��#��J2�jtcG��&���7�T���^��[]�b�8"��rY�2M�	�� �"�n� ���b���3�����e��6H���*w@����A:�Z�����Z�����U'BhA��M%�0|��Z�|Y5�����^2�����\���5���B�]	�GF
	�AP����{/<�3RH��Gr�"c?R�x �]l������B9�R�VGRhz���i{��Z)�^R�nz���-#���/c3Rhx��IYF

/R����W�H�IGRH7U�stZ�� ������ ���(a�9�FC'�0�@���%;{�a���q3u}�g2����^���X��>{G��f�z5��t0��{{��uL{'�\������*����G��M��oF�&O2NK����^	���[���@�`"{5�(��R?R
����~$O2���y'���)�;�������
6��2!s&"5N���?��]����\iz��+=�1����`���Q���F�y����]c��� ���5��%6xy��$�ZU�3l��,c�{/���� ��Xd�T�
�bl�[{�	�C'�{k;�	�v��^���;��;�A�GBE8�A�r�
� ��I�
� ��B)C6H�HIU�� ����(�l����D��
R/����`<z{{�w��J��{q��|m�����
h�i<�����<9���/�1���f��A����2��������[@|��I!A-������ d��`+�d��m���,�(!�^������f�n���R��AJH�����WA5����v2%4�B		�V�]�Q��������X,�p���R����z+ =����Z5����v%zA?=���(����S��C�7B�b�
��"j�A��C��>��w44�C���EP
h�L�dk/4&D����1p����v!�pF���K�382F�����1r{������M�62F�������o�zd`��T�c��Y	���1����0�1r/�.$D2��r����Jy���w��rD�$�S\�#�UF�"G��C��/@B$�TE����|���~��y{.}�{���L��z���\&�h?�d�hA�/�'�������,�����a<�f��]m�2�H����0R{��!2�H�+�Q�Fjoe8qF���?�0��N�>���K���0R��0>#��������?�>#����u#a$�[��"#����0j:#�]j�����g%4<�#�����F�.�]���g[+ETl>�=��'c�z?�v��	��'t����������D��������=��GxA��/�������g}�	:������,�b�zi
_���9#�{+hC�%�J&S2��8g��[�����8p���q�%?c3rP����e(]�p	z���A�k���p�e�&9�pM��GTr�R���W9�R�(A/�:�Q��#a�r\������5N�W3�K����r� ~d�b�����h8nA�k����j�>����m#H������#�O�+�&�xy�� �Z*�}� �J�`�"��m�3��,=V������I��Q���<c��#QCHCVHwT��X!A��z��N��o���+�~����B�r��6�B��Sj��R?*�
��R?ZW�+�~$���
�i���3VH�T�q��B#����|>��V��N��?M�~����Jp���\����w�S	:u������y�+e�y�k{��6v_�OL��p�ZD�������
��q�}J�2�H��w>�f�����W�g<��g��IA�H�O���q��Un��'R����O�+/�*�D��U�'��^(���'R�K����I��Zx��tGwBro�����^WO���0�8��O���� %�����$)���BnAt!���n,h7K)1z� %FC��h@G�i��N�q����v!�h!Kd����%2�]K��.�	Y"GF����Tx\b�}�u����K��9�Dn�8�D�����])Cu ��a��"�vv7��6��f��4����
*��qQi��������=2�1eQ.��J�����-h�x�����	#�
Xa����m-��D-houyF���a�k��6#����0R{�_�3�H�+A$�#��J�C2�H��J;F$��~���e���K��0���R�� a4�����0R����p�21F��U^]�0R{J�$�}�X��[����;D#a��	!A6#���nm�F7UI:�-���*9��#��S��K�*m��G���J���$d��Y��*m^j7��y��i/����W�4-�8Q�3Y�Z���0T�K�d�1����1Y���L�d��0}27C/����}3�������$pY�.�� �������qYj��TJ�rApF.K�HX7\�[~$��"�5�H(�B6k����l��#�����G�d���~�����##�a���5-LAIi�X(��� p�����H�����/��_X3%K�#q��Clj)D��l�H"��{/D��2K�9�"��?.�tM����9/��46����o�TO}�
G�*����	������	�Pl��
\��=����x��Gr?Z+#r���Rv�� ����7"����M���'��.9 s���(����P->U��G^@
�_�'ZH��Tha,p���>�����
�/9�N
	�re��B��Q�������)l^�mr^�3JH����F?H	��./������'H		z)U�f���o��>H	��w��Q��t�B RB�UA�Oz!t��(!������=��� �����{��72JH�����rzT@?���:QCzD��H��N���������jH��^5h�t�]��Bb��xa,Cf�w�~�E�����0�R��l�a���"�w�����l����6}3&�z�[���"	[��Y���-���k�-r/R&I��H������h�T�W��)�����s`�z�5�Qe@#rE�����|����~����Tu�����	�fc=R���-��i6Z`��=Z���?���c�j�M�t;�=��i6�Pj��=R{�g�d��`W�eb���W�.��G�.��"{��YH���=R��R��������y�����{D�n������ZE�MG�H��J�ld���R��G����sP����sB�1���?���W��'����?|�`�~�{�1���f�{b��,�0�jl^j7��Y�ejN���^P���������c��^�������������n��?���o��������M���K��>_�c��~o�u}1P���v������mPu��	�`2BN�J�)d��
���2JN��l���?�]�^�k����a/��FJN�~�����	U�H�M?��s?R*l����G��������^�n��pu����#���r�GC�3B-/��I9=2����:��t�������T�h+�Jk@4?��N*m44�����v�3����9����7*�����]D�-_*t�6�Y�bT&�y
H	z)�d�����*o�P�~j��M����
u?���u/�������I�7�D�_��������C_��w�i�����<�9�B�\��T���!W�.U�v��o~����|z����~z�'���=���^��a	�����o�j�S�~;E��_~y��������n���[�������s�0��w����{����?�i}?K���{���g��:~0������_4j�F)�T���_��/�1NIl>���R��
]N������qxA�|#��� �;�=%�Za�_v��|��������T�
��|�����C'*o@��m���z��m]??�di��n~
�.�	���{+�C\����3�s��;��A�~D1&^�������]t��on��_���Wc�]����h=��v)�E=����#�$q�R���>��O��>�,��)�/k?{.=�o ��Z��V��/?���-T|�|�=Z��2x���x��&2���P�����CO����H���?�h*��n^ee��mOG&��L��Jv+2E��^d3�H���9y	4^nk��!=���z1��t?BV^F	z9>��/�C��h:@)���;����U]����_�����9�I���(�-G��+����+��RB�~���O�:��=G/�#%4�L@�>��*!��I��0�����?�����������uk@c��:A�����OL�� �Ub�kz�#$�J�oF	�zl�����]�Bq����;�A�^��`zC(�>4�r�5$��K�� �#��)�A����v ����B�<��?�o�-?Z6!4����$���nc� =�����~��"F2h?gK���o��� �V�`��5�E�D���G��-� �t�~��_���k����]s{{����h����g�AL����#���gD�`����M�}�wfD�`?J&��G����	��wN�'�xo�2�I~�F�E�I��Z�+E�I�+��g�������#�4]��]��a�� ��.��u�s���[�<������~�\�s��>������p��-z����Oz|$1��2��?�C�9s���k���p�niR���%[T%EC'�x=?��b���JuX����K���I�^���q�P�2I��#�W��J���7��<'��R$��E8��ol1�"'qA�H��1���4��>�?���W�aY��J���$�U��K�����(XR�*�b���f*)j/�{V�4|eI�u�`����?Q��������d�~��CY��VB�<�%Y�� ��g4��w19�p����-\J���9�� !wK�!!�5GH��k	9t�y����/�P7�.���:������L�Cz�~��w�]�:$�#�1�N�C�[[(1��Z�[�������{U�D�9�N���:/�{�������������}j#���x�B���)�u0��|w���S�O�o	� Z>%h��X��+��'����|�����I�
7F����I������:i��[������5��n!�"��"���gW$�U��zn���r3�H��B�kF�~���3���D���c>� R��p%�D������Jb+D����R� a�(��E����^��m�QB�^J�%���)��[��R�RB����!�s�i�����G���[9�4����:h@G��`���_3.��*]�2:H���i��A�=\I:i,�A��(����r����'��t?��u*�A����� A/��_}`?1��	� ����� ����"�V�=\�[~������������#��"!��#o7�f�2?
 ���(���>2:%$��]o�����EN��5�)aR	�5G���[�0z�@���U2�Dw5��}���j���MD��"�X����z$�`?y��&��	�P2�I��t��l����.@{$������3��($ov)�M�^����t ������k�&E_)E�H6��_~2�I�H��d���0���y�`*BzFgEH������)}V��S�]���)�#��S�4$����4�����6Q��UOeH��@>����m����^5���U�&������AY��wpV$���I�.LP������e$��4�&��}?jB�|��"��}3�q
+P�����}�����$���{MRD�$����s�Y����R�"i���w��9�bD�+��{U�Ms;��������AI���AI�P�t������A�J�cJ��d�~��CE���B:1V$qO�*03No�;�X_�. �!����cN�����X`�.�^�}���oR��h���������+�"1�B��C��a����:/��Gz�f�H��z$n��z$�.�p���\7�|z5��{��u���;uw�F�|����� �r���<���]J���H��)$��O)����s����/} �������|-�R��v�W�m�|�(�>r
tH���f?���p�$��[:	���p�]��?����U���$��y�t$�;$����;�&�aWB"�����mWF)�^�C�H"��!M/Zg��x��'��=-$

$���A�3m?�k��	�4�D�����������H����#A�FbH�h-X&#��p?����^Z�+��n����h!��{��<��~�6)�����D
����'�z���.yJ	����6#��k&$1�B�a�B���/N"!$��p��B��G����}4!��|�\#!��%!	!�����!!����\	��G��! ����Bh���(:�Gz���GB�B��e.B��x��^�6��yT%Bzb6B%*���	H�����)4�N
�
��@K
.�Y��b�pc%�k��n��+��������{����j{���c]_����/t�p�:1�Jx9��+��
��2�J���-c�_�
���g���	z��I���pR���;���,�D���@�!���D$���9Y �W�G����?���vv?~��Y�~�Vdd������3�j�t����R�����I�C!�YT(fb�t@iS����;�{�&�^3�sGo"0X�+�&F���WBFHPKalD�	�V)OGFH�JY=2Bf��*��g���kck2FH�s�d�!#$��x�������U.��R�]��wn����|�1�7�^�FFH�h���lg���r	�S�����R/UFcd����B��#4b�4�����+E�����Y$��h*��T)��L}8���������n8`rO00�x�'�p�
<����s{j!$�#)d�J�@$�[I��^�mr�������Ynt��|7+��
PB������������^�������d(!�������\h�	��aK�������� %�'�P
��Z'��'�@	��n�6��<2*�(H	�v� ��0%|F���#(!?����������Z�����Z�1��T��mL�a�A�jhA{�0���fb�-����%��P��D�����X"��	�_2�H�qH���9�A�O�,���A`���J��D�^j��K���3��%v��Jf���|
�z�A���qD
�+�/���R&�#'��$�qD#.�{Xd��WB���#>��!��UD�����G4��D.qD���sD
-�f�������7�m��q��5c|�Z���8"�.�:�p{���6��,9"��J���8�����9"�O)	9"E�K8"E?�K3�H�.�[��t���$���T:�#G$�[�,,������@�������_-����t��#��DG��C�\�j���-�����r���p���g����}���b����{����y������������a*�����g�����H���)B�����#�b�zi
C�������pK�1]���E�H����s�$r]�^|[���%��~��~��u���K���Y�>"����2>���Qn��^�����xkn��?M;c�3~�E�g��f�'�Vr?��-�5�H�,����7R(
�G&�4<:����I����(�a�B�9H���	4�)�2���q3���RP(2FH��B�o�	v�TIji��`�	z!5:�!A�HY�<��J+8@FH��V�n��p]�*�-Sl�W.d#"#$�{!c8c���6
�BFH�h-��!��B�n���;,{�_�Y�T���O����<?�?����m6!w��h����'S@i����Kk��C
���L�5������kv��6v��?Haz��:�>}�8�Vjs�2l��/��Ah����a���B���ZD����Oe.L���e<����o��@	�e���D	����)!��)�&PB~��TRoJf;���6(�u�"���Q?YFJ����{���;}��%|F���J�����C��C���&���(�����/�����N�a��S�d���������3WI?�X"�.|�%������3�H�q#�^�X�����i!K����.�}�q-d�]*dF�H-#�d"K4��	����cg�9�A���&�h(�{d���4\9"�O�� ��4.*)G��;e�
r�'���������g&�Hi�W��0�u6���^���������M3ok?����5�i��x�Zl�](��0R{����y�l�F�a��^	�_F)�V�D3�H���H3�H�w
�C�H��I�#���e����\�<���z� Y"a�^$�UG�H�](���0�)�_B�H�s+�hF��n�\��0R�J�����	=��c���Y�F#�����OJ6�����������|���?A�U4��#��@�+�������^E�_�4�jHc/�	�^G�P+�E9c����������I��a��1m@��d��(7�#����^G����WpYz�~+�5Nz�9E�iH��������
����+����Y�o�z���G���������?d�x��o��5�wJ��Di���*��x8t��t���p��,���I2�K��g4tJ�6�������vu��5u�"�+�)�V�y��b��������r?r��Q#-����2���^�z�\Gc���t�>1B�R��#4,RGc�\�j�!��+��~���7��PzN%Fh�Q!��#4��FH�Fh�E"<0B����M���5��\	���:���������~PCXQc�u4��z�����<ocunaW�^0���*%�)$�eJ6�B�])5:�y��D%$��:������R����O��)!A/�8r�q}+L�(!����QB�r�}RB�4��8��$�������	���I�S��tG��e���o�����@W�4��O��QcM�cR_�PMh7���"�W=i����fhB�#jLh7�T�phH����KF�P\�b3c���3�H�K!�'c�{'H5K����%�X����<ad�]�^@�H�7�%�\Gc�o�D:d��2�E�h�%�*�bW�p��a�z��#�h�$�"G4�� y"G��Y	W*G�q��lf���4�8�	��+�}^��$��e��#��Q:cB���G4�#8����9b8t?o������9��//QCq����#�B�,�8"���5m�	�2�/�����(%��o�8G��)��C�H���7�#��.�C G�v� !G�+R<�#R/F� G�^$�9"��0�Gn�m�+w	G����Qc='�d��#R�J�tG�h�F��$�QW��������3���A��3�����3����j�����F��fY6����������w�~��������ua���{YW�'���k����b���������v��������n�s�k��������G��)
?�>��XjR��9d������P"~FG�O(|iN���,�Mw�����=��ub-�&�X�������B�Ii��9����;��>�#g���������;�u���g�?��[@��`�������K�k���z;�3�������0��N��������������N����H�n�{>������c����|�l������<_��T������?�������Ki�n�������g����&e}c	�����8��h�x�yn�����za�����>�^}9���������^���t>����_�F�AN����^�5�C�o�v��O�����$
��O���{J�������@r`��7a��P��!��4�y��3N�~{��������������6�&f5�~���~�����Jhf��?�[%����lf�^��
��xm{��?�	MN���`��?�+z/|���O�_�H��i��I~�B�W�H��k�]_nQ|6�*2AS/�Z�K%H<��SvN��q>�J�O�l$�9E��s����B|���t��d�v�&���g�n�#����������������O�g�~:���z��H�lo�z�U�!��7
��_�~u�G���n�������s�����������?���������	��������?�9}p<>>h�2@���p�i=j�<s�G���~8�D������t����
���:<���	�_��I���Nc�����O��.Az�
<(�_��4mi�������x�~iih����S���n�$����CM�V������!X�H�����/vAy�] #�!�Y���������}HF
��0Q2R�V�U��B�&J��L�[y�����BY�Ha����y^P���SDP��BC`&	��
T��do��i6��d�X��[��2R����3��+��A��3R����/��_��;f�X�U��,�W�	f�p�W�S
3Rx|�
u���@�g+T+aF�3z��'b��qH��S'Bm�/� ;k���2R����[��,�;� ��X��2���?�86�B��m_��hc��`@�e�W
�C���2��'�v�"���F���:��>���)
�)Pu �+F�� �3�3�� ���:���7X�Tji�:U��U����i��9����.f�)��B�L�0��
P z9�=����R����8�)r�a �51V�
P �X��	
�k�y�@�V���;���)���,�L���Vx�d��P��JF1B�!�<�
��9.�a�Z��L�0B��N�ez����n��ZUpgR���`@��5R����`6
?���w�M��O����
*�i~�^S��`l�W�A�!� 7'��0F@�K�������RC(p&5tl���H
6Fj0�}+F���`�<������p��p���/�+���
;(���Zh��b��*;�b��s���C�b��86@l0�/��Clp
>(6Po�*�
��6d�����@Oa��`D��t#��
YhK�b�k��F��Z��"4�X�\7�;P�(�v3�����0�4S8
��{��k/G��iT��T��P����'��`BB3�����S_����'������U�Op+&�?����	N�Z3*���,h.E��0��b��[����@*Ly��4�t����v�O���_�C����
,7e���vP7`g����M?k���
�n���/��D
�,�ZGm���0��
��1
Ev�%R��
j���3�6��Jg�z=�+��gz�M��S�g�=���z���7B�k�g�zFhx��#�$O����KF=� �K�2=���PJ�z���
E���B��F|�
������ez�a�������L�A=�����[)�(~���g��{��2��{��w��7Z��8-@G��0^�,�W����~��"z��Y��~���+�=��M��dtK��"���p������'!$a����������� ,0`��X�����|��jH��v^�A\`�[�Db�Pn�B�SmC����I+ 0�#�R������0���mC������+`��������K 2X�/B�&b�,����i�H����jQd���6����.�|����B���Z�3��r�g�i�l$�
u�R��`������\��h�EKgO��r����������g��g�B��[�����5>x���-�z�r��G���~8H@�7�D�[������E3������#�XO��5�G�$��vI���,������������i+�gD�ps$��v'6}����:�@7g�x�D@C�2����G�Q"�!kpL����!�S(����Na~	��?��K�V����g�W5���|#4l�\n�J< ����������.���&��0����A
���d�Z=�$8�B��kD jg�Y&��V_kG[����H�Uj�P�6)�Q��r���B�6�l����&<�Vw��;`��]{5J�����{����&��,@j0��4I
t@KP��b���BK���!I
�k�w�,����z�t�!�>x�ml�T
<u����$��i�b��q�,=U�(l@�X�`�K�ca�A:A�i���i��3���i�-]��{{p��|����J������!r=�k�!�
�6�[(7�rl� 7P��(�V(7�K/m�����p3����z�����r�r���P�b�\�U�r�������P&6��������.�������K�S���z������u�B�	�tz��5�;PG�S���LcH8�;s4���]�{�@s0�,�>=��2utY�X�v((A�
J������;z6K{0
���"BCI&D�����#6F�0�u!�����@�.b*C"r�A�o'4�!�;��(D���>Kxx�~nv�I]���<j2	�)LL��^�u/�lT�K[�*#j(��6S d���
�jbc-*F��g�Z�V��j�Z����l�(�CP���6d2�r��]�0B� ���Bm!<�3����~t�JRGUP ��W�{N�C-hK��A��O�H����o��B��ZP!�9"2�5*���#2��������8/��6�����
�� �!
�
Hd������|�f~�i�3(��;�2Pa*����+7p��A�c:�2d�w&dd��L���W	�5@��[���ZxE���&+���j��rRP���{��G(^�r,��'�p���//Bck&^��L�0��g�#��F|u��z>�C3�f���3��j���Y�������=�j�5f��_���3����JFF;��rl3�m�P���#�nB�B��~�����jM�tDc�-��fa@�kL@� �B�G�g���y&�+��jY�_�ql^�fh	A��y����4:n`�D�BC�`�IV���'`UV���l�$+0`�sd��Y��/�@V`��dD��wO��}A�������U���/(��Fy�����XWBC��\)7� /�s��<�������?���r�CX��/�O��!6���`Z�x�$+���V��%+�:�}A�X���H-!�X��H�X+
 9��Z���Z�����+���<�����^J_X���\���;XN=����u>������Ak}0����z�Ty���l���p�,_8�0�`�
���I��;���L�������f�����ps�����'%�X����$�X1��_�� �X]NV��@��	�N�*��H�O��K���U���s��/�d������X�ry�,��0��>8�OC�3P��V^�_+Q���12��eH��;�&�������[�z�7��*��p�WB����Q��1��>��v� }�X���X��V" ��z����>F���J��|����S�w0�(��&�-����b�_�Y��r|�����+�
��!����mP^�_��D���~����
��=N�[<{%,~��8�'���h�q�II8�;
'e�p���,d�����|4	t����k�d�D����ubm���*U�9�5�sN�1Gs9l�C(��P`y ��+8���������!�4�������tji�vu��U��Pw�6)��;��=�A;O
���J�y�;�r�L��A���O)�Ie���tYo�a!���5����7������`�W��%:�f���R+������7�dj����q��q�C���,����*� h�����L���Ti�
��'=�J����;�VH��5�X����)�!����`@3O��M�� �����uO�-�?��^:�vIh��4
�=������
�{� 5oa&5\O���R�
i�a�I��:��H
t�"z�2dYN��@�����
�?�,��K� �b�Vz�c�g����Xk!w���PjPx�aJII@���[��G��z�F��A���[NB�!�Yo�l3����	F�u�!��������O���jk!-�m�v =,�Q���z�����`��sQz����4��3m��EXVA���O9�\�y�5�|&��&0�����$
��M �����nDuE�10�!������\���b��s�=D9�h��?
���?���}z�P���5�����1�>��Q�`��|�n5#�$�3q"�$����L��CjA�0�d���M2�u���� �pl���$[������ ������sS[��~����j	��Bi�	j	
�����2�j\���g����j�������4����j	C�w�@�$6��Zb]�<�n!�3aA-��.����]!K �%�A���JVK���>��
���j	��0��l�J�����������"���43���4&����)I���:I$�kN��������Dn����i��0���ZP�l�P��45%�Y��p:?�X��_���u}�pHR�����7���|��[N(�p���=e��@�Ka�[&<��$<�bn���OUj���
U�����Le��Y(��2��X$��X�����`X�	�a���2!�)���@��.��y������:�z`��@��p��:=!����^CAgx�f)p�A���`_���|�}�8�bPg��|����3�\�(IY<
��6R�����$OL�!V��W�L�!�;����U��@���_g�
�=*������!It�����'����SN�8 3���'���������>n 6�W�S'���>�WhH)�,��X�r�	R
��w!� �HrH
���D�Lj����Qj �R�v���D���d��$(5P���N3��:�����Pj�;�Uf���@��qW���bt��?b�k&5�	
F��� 5�mLB�a�'�����Lh����:�?
�Qh�OJ�_�xi��/g���0*C���6dn���?��g�����]�v����
��Fi���B��$'��ft@��n;�V����w�����
�@�I
U��K\�K!�5���e�_5$6��VOl�������@b���]RH������r!�r�K����%X�p��@���*�0��A�/�n����k�i&?���u��@7������T����v{�� A������TSP����)(�N�x����;[8=�#j�M/-��<9@|
���`DD��F�� ������k?j��S�!�v
?u�<�};��R��~\�`���f)������P�W��Q����nJ2�><��>s7�)f����B�Yx�y����M�����������zZ����c#�^�>.��E�>@�0��Z�Bs��=���
@�0���G7��1����@����G������.P�>���'�@A�w��*(�p�9���
=�[ia	��D������|3%����������ez)�}��I@Q���F�kP�����������r�(a �
1���a�W}�_���(��,JT��N��E	����L� ��6�c6��-TQ�x��J���Q?BMtm��F\:I�>A���P��Y��������a<����nz9^�4�_�U�����T	�-�`���u6!i�Op������?�?��9�_8H�{n�����_����{NM����n)�
%j���t���E!�
endstream
endobj
46
0
obj
50103
endobj
47
0
obj
[
]
endobj
48
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
49
0
R
/Resources
50
0
R
/Annots
52
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
49
0
obj
<<
/Filter
/FlateDecode
/Length
51
0
R
>>
stream
x���[�-9����y��]U��<s�;��d>Z�U�a����!�_��������X�Kfn2���A���#o�E�&�����k�����}�!��������?~~-�����x�5�)-K�U���? ����k�e�2��+C�����xI�� ��������W�_�)�@Y�t�����������4������y�����2�������-L@&���7<%5���F��L��S��)>�)��`3��xL��[�`��.��S|yV�7�f�[�1�@nab���p�N�,�*�6����)>r����{w�`-���Lv�C<���-L��S��)>�m��o2������db�=��p�N��A����^}�c�����;<u�����o���Lv�C<���-L��S��)>�2��`���xL��[�`��.��S|�a��o2������db�=��p�N��j9`��x}S|�ZX`��.��S|I-,0��c� ���vx���;�0������<���-L��S��)>�������1�P�r�;<u�������(��d�>E��C����x���;�0������xL��j9`���p�N�d���x�>�)>r����{w�`Q����xL��[�`��.��S|�ZX`9^��������������� ����j}��L��S��)>�I-,p;^����������@V�L������j9`���p�N�,j9`�|�>�)>r����{w�`U�,�����X�r�;<u����o@n�r�0�������v��`��.��S|���c�����yL�L���vx���;�0�����c�����;<u����(7U|����1�@nab���p�N�	�
�r�d�[�1�'n��{<u����'U���1�0N�>�����@J����c� %U|����{w�`���H���1�0gU|����{w��������c�����;<u����0�r�d�[�1�'n��{<u�����������yL��j}`���p�N�$���x�>�)>�����������H����� �01�O]�w��V���r�>�)>r����{w�O�tS���%}�>�c�O����x���;�0���n�������r�;<u�����j9`��x}S|Y-,��S��)>�E-,����1�����vx���;��������xL��[�`��.��S|�M-@&��!S|��L��S��)>�I-,p;^����������@V�L������j9`���p�N���@>^�����vx���;�' j9`2������db�=��p�N��j9`��x}S|�ZX`��.��S|I-,0��c� ���vx���;�0������<��f���O]�w���ZX`>^��@Q�����{w�O�<����d�>E��C����x���;�0������xL��j9`���p�N�$���x�>�)>�����������H�������r�;<u����X�r����<���-L��S��)>�M-@&��!S|��L��S��)>�I-,p;^����������@V�L������j9`���p�N�,j9`�|�>�)>�E-,��S��)>�U-,���c�`U�����{w�O@�����d�>�Z���%����{w�`R�����1�0���vx���;���r����<���ZX`��.��S|�ZX ��c�`Q�����{w�O�:����d�>�Z���%����{w�`T������ �01�O]�w���ZX`<^��@R�����{w�`V����xL��j9`�3�Z��������2���O�����|���y��������������������r��1����
��Y����Z|��g��?3�Qq�oDI�
��D21�d���<L4�fE^�8����.5�����&��6(�u���{G�O���������.��.��db�����MK5�>���h|\��0�fb�����z'�9��s�b�fbU���;�����ouP]�}x�L��d��@���?����9L>=N��'��m�=������p�(�yP�s]o����5
������ &�y������6����"OI��zl��;����I��Y��Y�M�<_��F���� '��J�=��	In��?<�a�8� �5����F�5g5���V�d^}����njLMyQ�Y��L��$H�������L�X	�U���{u]�J��6���p#.21����X����������5�+����
H�B@B&�Z|Q~�Y��J���p�21����Q�)�����PC���� *���'p�P��X)G���8��E=��f���jO�w������RFp�n�@������9��Z�����J�;%����&��?v��u������n�l��L]fE]f����������F
L%@M����t��{|��&�Q/j� &�������X���ic�y
�P5x����g��>a����&��Y����?�>�<�zE�,O�i!Tdb����J���ssQ���T��]�hpV���u
������{7��8�M������L�w�pP��*�+q��%��<�'��<��a7��.LP3���	�>�J�@=�z�+�&*]������$5+vC�b�k(����A�9Q�������R�SR���lb��r+��S���G`.�b.�"JS(f����}�ay|��$�f�m���&��ow��<�o��25b���j�H_D(�!0�E1g5�ab�p~������n���`����
&P7{�� e���� R�����,��+D]FE]T�`b����,"��$I�%�U�.*����B�P�9���5u�s�5�E8���)��x����A.	;5�ab����Jb'���J-Q��E=��f��,Qw��T�J���%	�QQ�5T�Y���J�@���N�0g�j�<n���$
�eV�eV4i
��W��}�T1c�D�@Tr��B�o���PV{&�/j� .����f��xY	7^���+��EX��9/�9�
��53���4n��J)G!6C@I
ab�#���	!v5�!mI�@��8YkkQ���v�b��m<���%��L`k�n^X��XCy;��{�E�s�v�1$�qs	��=�"�`2����01@=TB��z�\W�M�����G�B��m�,s����*���P"1K�������;%���A�&��E�TF�X��������*M�Lb!=���V?�f���XS�R?Bub�Ui�5�LQ����;��5�v_j���ago����j4����:/�:�J��5��!���HO���<��%d�R����l�Q�`{�j&21@V��N��V(B}�S�B�L��r����du�Oy���������U���}H�)���c�{�����A��u�ab��]+f���u{�Q�l&PU>�9�'}�NIQ�z,��O�6��D^fE^f��&��]�(jH�`�Q���}@W�h�/&y"_��"\db��J������K��������VyF��!��c�<h(q7L���
�O��u+�6�
$db�Z3���kL�.��.��01��������k��8��u���V,"D��O����db��B�ZB����h�~	���YR�Bt�+P#&��9P%�
r���B�������lb����R�Z]M���Yw�'Q^�f��+X���
�"OI��z����&_�<wB�wb.�b.�"JS��g8���{���JU��S�e,C���Q�J��IU��l����O�
T�'j-�i���yQ�Y�&�����:J�	m�$��U�@$��gqy�����!�D\db��3�-:��Q�UA������s�	iD�W@A&�[�=	���gjF�[��`b����Z��2�|��x�d	�S����9k��=��01��8�> ]��Z�<�y���&����~�|�e��l`�23�5�����SR���lb����'�������������g�#n(qU������S$3����O���`b��98r�w^wVC&���	?1�C�B�{��P�Gm=��<��f������4��L���A�
uuQ���j��_�X�6fV+���""��������|�jU_�o_��j��=�����CVK�g�av"b����01@T����\�ZD�������lb����\�p�V�J��(�P3��Afq6b�)��u��8� ��3M�������)M��q,c[$|U�o��v5�uD
L%@M-�(�O�h��6
��f�
&P��n��I�,��E����K�J2A�E�U�`b��\�&�����L����}���rdb�Y��?1���m�,����f�L ����`�2*���G&P>�������F��j�k31@L.zZNe
��Y�hK�U{������y�8�8a?���@���Y{�{�\�&��}�0�Y���U^} ���_�Y}���
M�����69�q�Yq�YQm&�-V��E�4	��,����1�cI��S�B	6j�
lhTg������E,������&xSh��<n(��Ff�O�@����>�,�� \db����
	 �2*��j�<����C�'��[21��MK�!&�9x��LP�]�J�q���)�n����8K��\��-j@����'�f0�<(���7��X�8"���a�2*�y
�xE!�2+�R%61����'SxB�Xi�V )9��s�������
&P��h
��F������V�����$�`��(��*
��'V,����JX���ab�����S`e�Q�*��L����[�����������]����<�
21�~�z2V���P�����v�������F%���/p�SYETf
r�?�@���4XGTn
&��*����(!&*'8�"��<=������P0]�0����[��Y��Y��)T����r�<����J�����*&_��@\01@���/�9qS���k<���x��L�U�`b���p����2^,	{�
�U�����;���s��,r*����#�5�=���eT�EU&�y��EK���%��zd�R�.��������I�a*�LP���B�2`��	&����c*s�u������9?r�<������$�j*�s�z�����B�T&/��JS<���m�cT��J���~lT��eO��	L��7-�Ne�9p�k��2K�����Y�&P�|�Cn���JD��v&����$Ym�����("��f>��A(����MPRTdb���tA��D7D��[~V�����vaY�5L�j}��=Q}�n��L01�����2B|�z�\��MRG��\r!��$���P�Q�Ef��
@�eV��blb����O�B(3����J��n1��������J�,r�T;�Y�I���Ny�'��(���<9v�<��N,��8�T�B	������mv��EH��`�����hi��rO0uQ�$�Z�PYcT>
p�T���+�b����R0���L���7�,1*Q�	�@1�?H�B�T�
p��$�^�T���T��s]c�@���"96LDNs���Xk�s�R��"OI��z����������x��x������v��e*/�	`��}�Q�&�.jH21�ss�6���0����A����eNe�`���G&xz�`�[~U���2�t��L���<��2�Q����0��j��l~,sD]FE]T%ab��Z�2DB�2Tn�f��()&21@M}(�,s�
!$n�
&��O��fB��e��01@8�����bS��8L���� ZG�������lb��G'Jr=����dS^���2G�))�T�p61�`���y��x����)�/i?�nVB����*9T���,G�!�>��vZ���x��x�r�-{x�^���?���
�t��L0>�?����d@�hKB�����p�}!�2*��j	(��� ��	�~()*21���?�����x �01�����,$+K
����U�`�v���V\�-LP���SL>�|�+�&p�vV�lqFE��x�[�A�))�T�Y61���$�X��X��H�OV����
�]OQL%��f� �E�+D�A}��jV���
�5�`b��Uf)#��(��j<��r���i��-�,�_�� �����>HqBi�(����)�!n(
q *���>���I~@Nq��59����G�(�
"nD��>�
m�,I	�
5�`b��G��A^�=�{�k�&P�g7CD
m j`"��v�$�)��)��b8�z�!V�I��S;������x�[�@}����1y^yV\01���(O�aj}\��/���O��������u����8�S�K���/�}ssQ���j��7�yR��y���?)*21�m��Cw����X	�W��8������3=m7��a�@��A�m1�o��y��.@�h���>�
{[�<(���7�����N���������XSR���lb��G��4)�2+�2+�4����#~E�.���*9N�6��.j\��������-
q�b+��L���e+������z01��~�0!n�_���<�oo& ������E�v�D���Q�<�8�.��.��dbE}>U�Y�I�k31@L�}�K+QC�z�D&��'�u��ZH���:�Lp��5��*T;5����U.�Y�6VZ��X���k���@��"M����1��d��B�eV�eVLi����)4ece��6�(��}��d�]f�eP�K=~ab�}p�K�F���
�\db������;/�;�Z����B��>�
��x,4��
�{�db�[t���M�[)K�f�M	��5���U�1D]FE]T-abU���rV!l���"r5_
A!H��OO�x�7h`e���WV�
�M�)+9��O,*f!;���<��Bi�|�\W�M��A{,p�b?4*��@<���O�O����f���Y��
)���g�h�2��e"�E�.L�l�Yg6rV"lHT���g�c�0����U
ab�'�[h��J�U��
���db�)�-��2B@qh�O�>���~y�;�Z{�YF�YTU`bU��C��1�n$EB&�kz��sCw��~�x
��[\��7����J������;Yu0LPW�h��B�!n�f��`b�������B�������lb��cL��JV �k8���
��������MP�3r�%���K��aV �'��J���wL��.��/p��YXT����@8��o��;/�;�
��gk,tE��xR��/� ?w�]���r����x��Q�#������!������I�?|A��k���D�9	�g���+�/[���`�G{�%N���F�� L����U��yP�s]Y61��l-������5�����������K=���5���n�f
R�������H��r60���&x��YgT������W�rx|
Rl6�P��s�;�$���3*@Ku@B&��D�@]FE]T�`b�����S���O) �%$EE&���.=�LO���&�������~�f1�
JV�
���/��Pl������V��J@7�n���&x��b��t	C=�W^�����;0kJ�5���M��|:��Y�E(�+M�;k1���
������lc���x�W��	��w�p�EqfU-���@@cT����T���01Lh�����H;dFel����*���,��J���E�m31�NeE��euQ�����ab�|�=c}Q���0�fbM~x�_(����
`������6,��J�@n`���;m��b)�Fel`���5���G�D�,u�A�Wxz���^�P`�R�221�[��=��
��G�.`�h/7�U%/��7�y6�4�.J��'�z����AC�15��E�fU���O
�f�%j�B��\21�frp�O(���ZD����%�p����������LP3sM�c�|�[������mIRDdb����8A
="j���)Bj�~��6d���Y�hK�UW�����	��S�&jH��u}w�%�1D<�x�+�&P
}6+�o�$&�������
��u��6�`w	��8��8��(�OV����"�
QQL%����2G��c�4���jk�eM�xX��R�	&8UI{�A��E�gU'� ��w�~��.���a[�x��L0=wWX��F�:H���%�>n��F<eT<E�	&8UI�����a7���&�OY���k�
�#n���)*nzg��a�W���m��|���sab����{������7��p�G5D�6��}�����`��<��f��~���>Y��F��z�3��@]k��jM �G�))�T�r61������A>,-�6f�#�2+�2+�4�sc\�eZ�8����8��6�*]���~�w	U���[vj���q�4bk��L���-t�������&L�����w$s�q���1c��x��L��+��h�q"����'�Bb��D����[V�a3?�����$	���]21@M�+[�Ut���"5��;,R�S��@m��G#5�`b��Y���Y�$>�J��<�y���&����G��.DA"r�"��4k�K��>�9%�����&x�����Y��Yq�)��,�L�^�8�*3~�7@��P�b��234�����y
��yk���$�j�w^wVC&P��QR��}�(`��nxrw31��>����8+L���a���Kp�QqU121���~��'2���	����6(jy����%X%W��:���L�C�����q�<��)�^&(�#�d�����>a���5��L���z�\�&x��B|6j�'�YF��W�yoE[�J�@���N���45��r�w�����U���������������r�N�`56PDM3���y����Z$J���5�� ��R4���Y�eQ��Lp����y���yQ�Y��L��}�|��w)���l^&l&��T��L��H[�9�%�a��E�������(LP��}���Y'��J��L�l�Y�JI��#�S�]���Y7jJ��e��01�s�,�j!��N��D��W�eP�e���AQ�u����������F�j�
MRLy
��j�RD�eV��flb�����[��Y�hK3�Tr<��,ED�����	/p��I,E3��R�"����Ez�'��������#L �MH����,�	��
�c�db�1���=�"tg�fe�����5��q;�"/�"/��01@\o���F���]TRLdbE}^�@a"r���)9m�wSX0+km���j� l��� ��=��01@M~t�B�q��������bn/���F�
QS^��>{���SR���lb�'G�P<"/�"/��JS8#|7���bUI��Z�d�'���A��^������:�q�b��FL���b�#��(��j���
��o�~��������01@�/�����<�G��.21@E�5���~[�G�eT�EU&��QX�%��,b����T[{:	r�"��/O�[a�b#��*�N-���,��>&Jmq��4D���BoU�f�j�yP�s]c61@������Q�����)�PW?O�'X��9%�����&�+���a�4)�2+�2+�4@]iqZZ��y�&+�$nVD����*9�{���Y��zQ�������8��r����Q�.b���L��0c�#��(������0A�^��c�N��c21������Y���L �����N�!x��LPW�(7>t������q�[���O����Y=7����u��:Wg�`Vx�xX�����0�vuf8b��`b����:)V�#��AQ�u���5�8�q��&��A�<*�$r��:����k(r���:���S����dlb�C�R�q��y>E�q����X[ky��z�u�@���(a��$�zcT�'[�e�N,"8��L�L!��	��}`	����xmx31�����nff��}�0�fb��9�E�%�������%�@����,7�����QR$��T��~e�!j�Qo�����R�Y_6V ��e��dbU�s7��,�{"5����q�o�D�G!/�=�{�k
���&��B�=�z$`���@��|:]-�n�))�T�f� d�F�c��������)M>S�`�M���,�ET�h����mD��!Fx��q����a��������Y��!R#�L�T�Y��8/�8�����KX���& U/���s�EX���&�	�_Y^@p�����l"���L`k{ �`e�SYM��LP��tVA�SYM�8��:X��t&�
�K�Uvs�
����D�����v=M�{X���&�{���&P���N�a���"C=�S^@5���a!vuBA���&8��"��&E]fE]f����q&F�Y���*L
��c���{0eT��QeULV�U�f����07P�k���M�������01��V�����^R Gl�6�"��6��'EX�6j�E�"��1/ ��
�G�eT�E�&�+|�uc���Y�1K��L������7d��	�������I��,|3K#m��f��f��t���X��B�USc&p���.�u�\��M�Z���P�$b�6*��@8��#"�Mq���S=���O}WB��������)M��w%$o�fQ�^�(�����_��#�E�3�4�jt�@�����[35�`b�P!2�0y^yVu���i^�r[�A��6�S��_X7GT!i����w��P<���8��8��
L 8��@�f��n,)&21@M}�C,g��#f��)��4��F��G����&P�G���F�Mn�8f��`b����8�Q�����j��jj��M�o���Qv����*�Pq&��D��uJ�:�C�MPS�L���eV�eVDi
�'+]�0c����(��@Q�bY��"7���i�%j���/,6D�E�L���$��f<������uh21�\��N�:W@E"r�4��a��p�QqUO����i�"j(Q���oPS�'�b�3)�	�������Be��D��D���gg9+��}��01@M��!�~$��
�������lb��Z�Dy�������Z���D�������C0�����S=������pR�qB���=@����,�Eu3~�z	�C�R���bD�@1�q~���@R����U�`b�hL��l����t!L��<�	OFo& ��7vYt6j�%�9l3m&����H�)��)�Fdb�n��,'k�&IQl&p8�`)�
�Bw�u@B&�;��?���Q����(��$<9�XT��
,;���!L&P���?���<(���6L����c�0��O����M������Y$.�9���-4��SR���01��>:��&�\f�\fE�&�k�6�~��Y��+)��d��>u��5�� $���j���a;�F� �����5+Q�EQgUI21@MMm[����AA�n�*Q|R�`5�`399���m����G!���^@P��`�#�2*����>:���Y�3J��LP3�=���G�&����9j������veY�2L��}�y��H�n�@��d���E=��f���gG3X�6j�Gl�F���PM~�p&�q���S=���Q��T)��B*h������A�J�U��T`��Z&����HP�u^uV�
&��~�`x�J�-���i21����{!7Km)���������g�2*���	��k���j��LR$db��g��P�&�_�� l��& g���TV]
(���?"z�-��01����5�u�\W�M������P������QQ�5��:8�0�w�w����TW;�%@�-����s<9�x�E�8~�z	�'�0!E9�6��ab����U�X��X��!L�X��>���Z��J2��k21@>���<�j%�8����!�~NH�.��.��01@�}<g���" ��m�@���(�9*w���lO�l�YsT��k�������T"����������D�Y���lb5�����$"����~�=}kJ�5���M�X������Y��Y�MS<9����t! ��`���_*7�,j����V��Ke9p�k(�����J��YU&����G�k��M�yR��6�`IA���j�>�����!�idaS	C���J������R���|!�C&�����eISyB��~�{
���G*H�,z*]�`bUa��c�R�A��r��=<���b�����V��:�����H�q�
�RiG�'���M�V��c![*�s�YQ�)v[�y~�,h*�s��9�����~"|	��)A���bqS�F�b^�������K�a���(��L��(��
����T�fb29hj!Y���F��
`�������B���Q�U?21�&?��#r�6�����L�[[N�,V�9#�
�[21���A��Jm��c�y��_����e����z	�@u���SB��{�\�&��7�.���n��$y������L��))�T`����G���Y��Yq��tO�|���~�f�T��|�B��gQ��%<YEV3J�qS��f�W��"+��E�dU#21����$�J7�J�H���db�[u3��'@H�J(f���5�aJhV.�R����$Lr��Y�Tf�"�sNf����" ���*�z5���+&�@U����8�Cnab���n�!_*�s�u���S��<�����!����+|8�7E���N� f��B�T�f-�"IS<��
�R�C@��������+��e*wS/jt����Jq���L%9p�k����g�S�C�<�����8�O����W���Y�������:�d	f���Yi�C���@�|�g?�.��.��01�������m��}�o%EA&P����y�v�C�0>�����F;���&����OyD.��*5lab���B�6��e���&x��BF�<%E���&P��8V"/�"/��JS��0������LQnK�',2�2(���lb�g;��b#g9��F�&��T�:!F&��"���01��o�r��dl	XT�����M&�O�n`��\P�a��/PS�c� �2*���	(���/"g}�.').21� ?��+��X	�7������\���q����*�>��Nr��Pr�[=� 
��l�
q!�yP�s]S61������r�>�sF���8]e�4bMI��z���w��y��x����)����a�j��LQ$%�N�X�T����#���&��q���������fb2q�1;�������	`����yK�	�eT�EU�L����0O'�v�$�)6��)�i����
	��c�?=VL��JH��z<�x�){#�Y~�r_
f21@<��f���"��������]O�G0���C����M<I�5%���1�M<e�������$M>��h����1�9�U��u(fn�,j��db��SoT�{�$�)���nXlT@�E�U����#��<<.(]�Fb�|5�`�������FKy���%jn���s��������%LPS�����u������5��|���#f���)T�7�,h9K�g��n�@��Q!a��{9l*����:nc�yP<s]-61��6u�7 g��6bT\y
U���
���XS=���k��iR�eV�eV$i
�'�����E;���J[e_�F5�X��sQ#&')g"Dmcf����h^���w`���8��8��L��������W-#�R����������A�bG��%�%����L^FE^T5abA~����m��s�Y%EB&��iJErV�c�
�#n�1�)��>x���t�����ab��������)��*5�ab���Y�Y��y�\��Mpvp	]�XY���I^���I�����S=���N�����Zf�ZfE����|:	=�Y���*���8]c�7b]���O`/��W,$n#g��K�0���W,$�8��8��LO��W�e�J���-���
��db�T]]�GjPm��!�YiD?���V�w!j�SF�ST�`b���'sF��������5��V�����}DN?=@M~��*����G����&P�G�eX��B�S#&P�~:��������lb�S=��#��ak�W^ ����O�O�G���f���Y��*�����$K
�,�'�C�K<��,)9�vA������$���E�dU'�@��+e�-�K�<�7����3���l�,1�� ���^��>{��������$L �w��BM6N�lw�� ���^ac-!j�
Q�o[O`�L��"+�m���_�`����m�B`��Q�&P�|�b� �yP�s]c61�3��+�e����(�g���N`-�b-��b�jfo+D�<��|�Ur<��<��| ����5���Yy�W�.�5���U�#9<��L@H���7���d��JqN�b31��<��3��q��EU�L��O>Gj�����68M����I!*�8��^�z�2��Uvp
21�j����\H�Jy.21�&?�+!r��U
���tkW���xRR<�J01��Pr3k�k�I�|��]�!:�7���^��5&6�Y����&xv�
�P9'@Ns��<=\YET�	&���db�g���l�Xh����dL&N^�BB� 5�'��O^@�>�=�]F�]Tab�}R{@�R�-@RLdb�����YP��C��;�S<��,,7K�B��o�@U��YA"��
��01��"����X���lb�*�M�X��5G%�`�y
��i�.����4L]��&p���8�������O~BBpTR&_T���!���X��$���5����pBlT�&���01@M|t7J�rE<)NxM�L0�M\�J��D��a��`=jh!3*IU;��&>xB��Jj���-�:���=�J��
R�"@���(�,C*Q�`b���{�c�!�;L01��~ ��(�yP�s]]61�`'s��[0����nu�V7����L��f��=���I��Y��Yq�)j�C].jh�$���Tr��6��������8��n�%N��+��k(V��#������201@��x�M�������������c21�fr;b=�8Y�hB?����<����eT�EU&P��		(�����}NRn����j�����O�_;�E��6�&�_G�@Q�|�
�,m����Oab���|�"�����01�"?>(p[�<(���9� WB�6�4�y�r��x���ryJ�<���M�l�ry�y�W�`w�pR��U
{��8J�g���k#g���G�5L�3�XD�'/�'+�01��_-�������Ub21�\�V���"D(���'*a����K�����3yyQ������T g5R	#��LP��F��l�o��{��'PC�T�0������T�dRY#@�m�n�XbT���1�������-�{�\W�MPq�gr�gV�����-tIe�`��@�M������o�N�;%�����&���2���}{��)0�Y1�Y�)��sz6�s���������K0U��T�Yu�yQ�?���������Y�hK�5����N�T�<.�HlM��g�7�	���<=o�M�C�����L ����kkQ�#��|��7���	`����{�S�P�2�z�D&x�jC�(�&LdbE�������A!��F�U�QQc�L����oz��~�Z�yP�s]i�@U���x�Cb�83L�W����=4�����T�b��u��7LM%����^�{���0w�w�U�| l�;�}��Z���@�0G�>�\/c�'f������N0��3��������db�p|����7��4a�x��Lp;u+Yh����D��m�%��7Q�QQU;������$p�$a����r;H�b�+�"�a#�_�8�<k�F�jD����&����&?k.�f���r�=��01��fU�8�Xl���<(���6�@Qc�����eI�7+�,���k���"�?�o�/�+�Z��:%E����&���MVb.�b.�"JS(f�������L�'0���s���_���d�!�%3�En��������Y7r������Q�EQgUM�@Mg���Y�n�j���k���L&�L��Q+�"�\���������<b.�b.�z01����;xX�AJ�-�����B������DM?�<@L�$�d���Yik�U���!��
K��[�!vHj ��������:���=��f��bU�]��@H�F�b�=�����Z(�#��G�:%E��!�&P1��>E'���eV�eVLi
���<oo�����Y�h������5���Xz}��S�J-Q�������j� bv�2Bo�:/�:����n��<�=�~i�r1� ?wC\��F��D����%j���d�������'L ����^�%��La��	��a=���
E��{�S(V���6�m���O�����r� ��-��01@\I!-+�$��a�J'�n������=�&��$��v%���`�����8�Aq.��a���)��,����N�@�AKy'��(����|�<a�,@��x��L�����b��\%p`21�`}jrwwQ��j��� @�S�J��\dbU���J<m�\�M�<�����<��\`�W|�%��1��*�9b��`b������UF���z��*n^��=��x��%���1Q^�f�f7D���7K-������u�������ML�*�3/��ab����q&���I_ev7P�k�-.���AC��U~����01����5@evxB6
���L@&��7k����T��$��#a�W����*��4O�#O�*�8	`����]���l��90���L���<���!n��N��V���\	�@5��1�s��G�bT`��<����3��������������	`��������p\�e�����<%E������_T�YUT:	�.��J�����GE�3V<�Y��J��'{�M%�`�E
421���Z���T�&�����������RM0yV�$D������3����[21�-������Y�T�	&"�����2��EU&��{��dN%�3~e�5����Is���A�bL01���{������RK�&��YW�UH��)� jd�
E-dY�Tf	�������9�/)��Q�����*�������O��`�Tk61@�|��?��Js��eVDi
�|8c���| �������c�S�.�{Q
&�����/|�@�$�YU�f����O:��I|oR �7/�7����L	��$rR�.��H<�K&��+�"!��F5K�Jy�Ldb��z��<k�Jy��EU&Puv���c<��Jyj�J�-j����,z*�S�oOPSo^Y�T����������@����0@L01@X����=�{���&������V�f�T�/�)����Gx���j�:%E��A�&��]��������������G�>�g��*3�a�s�S��0c�TY0
�,�@H�w����*�kD���[�@�����#Lu������ U3c��V<����L��39��n�����"��X^��>zj"H�eT���c21�`>w������%EB&P�2��bG<�C�!��U�`��um�a���aV���w>-!���&��\01��G��n���E=��f��+Tl�a���lTn��U�U��SR���lb�	N��I��Y��Y��)��:�T�Y��+���xn&F��Q�I�%N77����
���_01��8f�"��(��*<��B1T"� D��l31��X+T��,JC��������R]��v��@���m(e�P�.�|�E&��N{���Fe���ir����<�@���P�����z��5�q:����0U^}@q�a?�k��z����01��>���
��^0w�U�|@�66�b�U�\�h�@*�3��������F+�J|*21����Xd(��M
4�i^}@Q,b�Q97�;�Z�����}	���q���b+6;[o�)b��i�LN��H�F��Hb�F�#��(�GI�@^FE^T-!�P����I��J�P~��OW�rP����c��H�s�$�
�$V('^"��rm��xX$Wl��h�Hj@5-~��x�H�T�$��AQ�uY$5}H?.�Z��H�GP��4��\J�B1[B����bN�fm�@X�/�oz�,��,��H�h���E
,�"qC����a}��'�X�DP/j`A5,�����4����`�W�_{���:/�:�JB5p~�bi{\���]���a21�]����m�,�k"��=^@q�Ja��eT�E�&����,l7KvkIQ���J;G�X���G��K�S����i'�m��b� ������b���6LP���_�������AQ�u������Z-��F���-����5��,L���N��f���9������������:Z���m�����EQr��u#,w�����`^ d��r<J��F���}�^01@HAf�#��(���	�������7���2�~�B��5�<�L&�L�~Es����e�6G�[�K�����1wwQ���j��G_@���mYRLdb����SY���H����Sf���sD�������ab�����!���PE������1��{�?*�yD=�z���&P#� 	����e��QQ�5�w�����sJ�9��M}�"�J�w+�w�w�U� ����[h�F�E;�Eu6LR�:3�m��U01�����/��������=a������~����8����|���W�r[�������?�����~��ic�������a����w��<���o���|�L��������^]���>j��b�����r��j�
�%�j�
%y�}������?�����������������?��6�~��o?��?�@����.y(��4����_���}��{����~���o���?|������y��>����M.?S��c����{ir��T>r���8�G��Z���M��������Bp��������
i������m�?&�=�?���6.�������v���������������2�����]7�;��_�c������V��/�������?�������j`��_i.S8�_�_P����y��������7y������?��������G�_��/��4�~W�s&�������6�e��]^�G`��sm���]������1~L-Gsm����e=�k��c��4���/�s�8.���c�m,�4�s�������i�j?�`�}4�'4������R�-��&�m�1�e��jo��c��h��������Y��y��J������:�����������v��_[/������'���^����7��������a��:~ku|����������hn����9e���kw�}����>�QB�9��1�M�����f!�q�q�RR������u�)�^gp.6~4��	�1������u��c�qA������*����}qW���{vH�V��r���g-�n���yc������3������������������]M_���q.������Kg�*�L��Q@_�����9{���?��s�i8�c����1���'0������l��W1�{|i�-b���1||��1������*��6�k�d^�����>!�-+��;����
qg��M�<��[p'����{2��n�����*�2���n�������k��{Ic�t�����G{�B�\�����q��#*��u����?��:n�������8��Ks|!�mw|�q�����/��"�8�?��8n_�������}�.�18�;��2�������/dt����}#�n[w�et�m��Uu]����2����e������C���G��wa�-#�����>��������k]<7Fsdt!����`������3�<�p�[�^p<w��-#n;w��-#nK��p�"���gr�����������-������z{T�
'm�q�@���������������B ��'��k.���V�(��g��9c3�����1m�
'�5K�!p�����2�-�:d�a�/�K��r�����H��?>^;�����m���_�d�����}��3
W���}���J���0�O������<2���m�z�m�-�d��q��2���q�B�
=8�{B�
����Gvxp����2��va��xp|�u,�ni�{�[�V�bY����,v[���5��t��\����k���O�Y����Skv<7��;\:�Va�`vmc�����kvf����;�=�q!C���n�Wa��;~��a�M~���OG����)���G����#*2�����{��1d"��b~����C���?��s����ap\��V-#A������;Y]qS�u��Y���KO�8�Zn��������(jp{������?P^.	5��_�c/"��n.�5��O��P��
"B
����NjXGG��@���������q��q|M�����e�58��/~T����� �5���~��
5�]���	B��^l_�W�����v���vjp��q������=�md����G��1L2�2rd���<���}���#C��z���B�.�f�����lv�t����L{A�����
;3�����q�a���_:��*���~��cck@����.O�e��DJ�3-u�.����������]~��������S�H��:n���	w�\sq"p���PC���$�<�pu�E����Zk\��h��FH{.�aA��]��E�k{���!��y�u����<��y�i���g��y~��|^)<�������/���r�������������������K�WF��7f�Xw�������x����x�;v�""�y�&��wDD�o��|�����2���%U{� �?�_z��">���NI�G����s�I������4�L�v��1��s���s��$b"�N�2&r�\+b"��h�.��H4���D��������-�~K�D��n�����S��G�t���~���h���&#$�T��>tD�$�j�_ �����@��j�8�q�c���_p���W�rW����.����D��c"8ru[����h>u��%|������;a��d����|�j�k��u�k����D��q|IK�q�/32��8�$������~���8�����$d��_;NI�x�[���1op|���!�L�}�v�h��`�-��'2%c����6Gd���0_{���1�}��R���.�_�C0�����f�����z�D��9�?�e<�6G��9���|�\�w���We�8��=���d�����I�*��6�KO)�O������#��d���z�����s�o��j�F�oD���5�sW{�������~��/i���qs|�o\�Xd����"�������\��	+������,g��_���w|A��K�,�-1G>:����.8N/�`9n��B���n��������xHu���|M	�sGDDF�����{�����/�V���;^����M~�HJ^E\�?{v�2��~6?zn��������������m������T��$��\�����kY�������B0�6�T,O/����vn��*�������"�����#��L$����{�����?��l��Z�������z "���w�����#tUT�����O����5u$�\w7o��zG��\�����)����.�~;_S��eF	���<����/=�<�JO^Ld��'���W�����^�����8��n�F�Qb���X���+}�d���G���fx���?�8�(��x���PF��d������nv���Q��[��x2�����B�5�!��n{�����1����S�\�?:��V1������D��y����k��*�xnlks&����9��7&���?�D4��F3D������ e�������U��m��-��9�m�8q�X��h~�y/{��G����Ky���[r����@���=g�<�"��~��xwp?�+���l����	���I%8��:�H)���WD.��*�p8�:s>���!w8����D��=��!��k�1
�\_��2r}E"p���V!�u���u� ��|���A���o2�8�$���u�� ��$��<wS�!��:b�!�;�,������7�2���v�8\p��m���dhU����'��A�����-�!����+82�S{�tj�B���U����
A\;��D0��N�)�vn��
B�����������{�������������t4��u�q��__�����3�n�?��0�p���=�������T���RYF�g���������n~Edk\7�)c����u����
W��<�BG�D���S�J��<������.����o��T�j>����r+����o��o��������������������������j�>���2c��&-�c���D�9�z���Eq���u��i�Fp<�?��x���7�N��m%#8QS4n�D^�u�=y1|����|���A�wW��|�9�/�pZ��7�{Z�p�}���^���/������y�o����e������W��<���z��C=�N�2�s�d)C=����3��Z�9�3����M�}�9(D����;�'�`O<�?�z�<,rgO�o����D"x�����(w�������"G���gO��sgD�j�S���'���\_f�~.w�'N.n>qr�c>qr�c�;�w|��%Ww�8U������K�}���.�?�9�����sh\��#Mb��-�{�x}�x���w��C%���i�J9j����J��r����?a�������p|�9I!��I�n��������-#X��#����3�eG��~���s%}���i�e~����~��cYv����l}z$�}�?�!��������;}�:���?������'e����>����\`��~�8aq+��������?�����@�;
���Ve ��w���������b�����}	�����_z��������#�G:�u���}h��_������m�����/���?��~��8�\n�������_�v*di����/;�g��~���c
�1;3�We��x���?��/�����xL�IgLw������U����������_FC�������z����%���0��?���"�j��h�pL(p}�y��u�e!>ty��y����]�Z���}�cCw��
]��26t��u�3ofe���K�]>>�����9>��������*�����������@�8�8��j���W�<���)����o����Y�.�m�����S�?:��Up������B�Zq|��7���'qj����'�������P^>�Z�{{A�Nq���?.�|������2$�����a��)�\���'R�9��Z�8�x�1����:�r�|�������,Yr���L+��\�w]h���_{6��t�;;^���`����1������#)n��	O�#)�|�uMK���GG�"~p���s#| �u�|AF�a��
�\F���8�rm�#)���WW���I�s.�6�:\<�d����!��6�:en��R��.!���,S�,�w�~�q�m�D����������[{�d�m����e��q�~���;�������;�:vc2���~�ysT���=/����;�W�U��m��h��;-~Q��m��V�qw�z�y�U��I��M��;sm�aw&��2��C0�����y��7(�����J@q�����XC8�6�Me����_��-c
���s���p�m�	#b
��������s�'����z������U�!�c�Sn�X���j�O������X����FsU��]\}��1D��u�|RE�.-�<��rs�Lq�!p��k����_���e�����ZD�nq������K-�
e��N���m]��x���=I��7x�/�7x�����q�/�"�`=�x����t��!�
�����"�����]��7�����Zo����>M�w^�-��f�^O�����ow����x����/��;o�'���""�p�\+�
�d��!�m�3oD�m�
�s�e~o����kW2����g�9�?�������x�?�z��p�ao�m��3���'yd�!�c����x�?�v�JD����z�d�t�zA�UwA��w�~����/�7���c$o�w�X]�����h����X��E������h �p��'b
��b
��N6\;g�H���./h������?��mk���wg���_&���q�
a�w�J9�>/�9n_������2������W1��K�C2f��~���]�,��z2�������Q��=�(�O������C������g�+����G���������U�Ve,#�w[����`�i���XF0A��,+b��������5��������W��U,�����"�����������K8������YD����=������=2��N�=/�Ua
�{{R��c�l�qe{�`�"����=_�5\��A����EX�u�/�LQ���s���~�b��/����Ek+�������5.n�������]�����9����4��b"����c)/s�z�_:tV��}�7�9D=���J�C�����Q�"�W��|�9�/C���]�8��?���r9D�Q�HY�z�B�p����t"���2�o��Z�lv�����=��9D���gG��� �N��z��~�;rq������C�����P��}w�U9D�y��Md"�w[�v�����I�p|?�"��!������!���S�p��'��8����i�����x�o?��S^"h�XTYD��"Z96��,���|�#������z��P�-t��-bB�t��EyED�u�������9��)<���;h����
��7�����
"��\^j�tD�����(#C��YD��ngq���\��..3���l'��3)��Kr�z��Wm�L������<���o{,(���������S��SZrjpU��K��M�Oq|�u�DW�Oq���!r�������LJ��������g.��i���G�&d(���~��$��\:�V�P�9��5�hR������9�`�mM����w�`���wd9�� ���x5W�I	������f{��*�3��������y���(�|���TD	������C0����]��q;��~�x��=�'��^��C���z��(��+�����B��V�;�����Fq_q�b�r���wl���}������;\����Qfo9�{p������q{:{p��<d��q�����=8�;~���P�A������wG�op|?����D�����s#@��������7�������7�-�����7�m���wS��9�kG��*��NT_{2��xC0�^p�%�`�s�F3l��h�m}E��9�q>�N�9��'����l�C��7��,c���s�e���9<�����q�CG�L��{q���'�*�L���pC0�v<�"�
����'�7�jk�n\��������6���8�4���^���)~-�\N}���l������
��>�p�9E�n�����8ln������\�����e���g(}X��Q��l����_*D��s|I��s��6���%�D=��\�����%�9w��Dx5��#9��Dx�{�M�H�?�vd��H�?������_.:������I�E^�m��s!CD"<�o��������k�������l��d��M4�m���^;��H���#{�8�pf�����x�m�<!�W��2*���YK����[�� q�!�o;�{�����1)C~��v����}�3>���h��	t wj���i� �;n����L�������us>TED�/�rq�k}���E��r�}��A�D��=����u�8����9��G��d�����q�:�}��K�g�XX���~���9F=��9F=���>�pw\�Q��qT�R�2��8�x�cH�Q�����<_�a�����U�1�We����,"�����K/�_,�3����G��+2����=gZdL��NF�{��>�F�����F0#����k������N�U|��v^�z4�����g���AUD�����h�_~�;,����3��s���#P�}�"�x���
no{p�
n�L��@����{ �sI�s@G.	l^�������rEp#(������,.w����-}A6��[Z\����"���!�������E`�m��3��qy��h���>V?�q[�A�u��� D�Q��K���g4.w�b�<�~���V��|�v\��W<<�W��|�y�@$�?zr.�<��8y���L��G����Su��m����U �-�;�O�,�~�S���,��������<`��5YF���5�YF��ue�Q�w�1��������2�����>|�Id0����\#�?;���,����G���ewN��u;R(�#n���dHYF���}�C���83�V���	��D��uJ��,�@d]396��,��p�.��C�>Wo
T��K"C�t��3�7��I�>|���eDl(��~�-�������W$������������C/w��
]��cC���L�{��Bw��bC�G.�CW7�8�r���������Aw�Mq���7�gS�i9����5gS�m�	y6�q�q�_��1��	�oW��qj�s/�
9�_z�-��*��G��V����;\:�g���������[�+�~�=��x��w�Nq{���{c�e@���~�O\��W����?�h4��z'R.�m�)��]s"%�o������~�����/���7��3)��x;H�I	�����Q_^t�&h���xu%h�����A�`�m��]��Y�gG6`y�����+���;��G28���=������)?"��qq%p�|�G�..�9\\jr�x����������Fd��_��I���Q�����!�
�:�r|�7oA�qp�^�a�s����88����H����&��������|]��*����r|8���������yk�qp����h��8�����v�X
-��]F�6���_E��������8���KO���C0��g�&������`�ml
qp<w"����8�!#��z�e���_:�T�p�m�?��C8��?m���9����*���������8��T�wqp������"�|���\�3����@l�������\$�x����)���k�B\{q�'���E���e\���9�pu�������^�v-b
���p�8��nr��/���2�FGbzs�n��o�����opkd��M��/��
���_d9��x�Sr��5���%�7��_:�I�xC0�;���
�8��u���/�7-���+0��6�i�7����z���`�������7�smwN�p��~M5�m��
�t�o�z��xC�]vd��x���o���Sd"�����;8�����V"��;�6��t4�>�@5�J���r��&�����co��o�9�~��'\�?;t�!,s���W���27��@���2#�8nNZ��C�����lC���:���:�Y��c���j#�����YD)�pys|^+\�a���4Yh�����c�
s��Sv��t��u����u��C��8������q��J	�5�:�a�6����������#2<��n�U���K��*<���: �#��oK�*<�!A#q[��' �#n�w%���o��B^�-#�#���[�[/S�SL�1	<���w��1Dx�R��@��������;�K�������������I8�v_	�_{��
���#'�t4�>�_ 	f���+2@���o=Ld�$�e����q"X���F��1�2w\Y�'NO,>_��8����m�_]	]7�a�m��u�m��O�|B#p�~B�6�:n�5���V�M���,"%����������n�\\f�;�dK�w������s�"%����������e�M^:�Q"%i��yxp����������
<�����t������
<8������2�����=93d��m�=�a�����]��d����uK���22��x���j��uw��$R�H�>�;.G_�%�Hw���YK ��~k/�@�3yk�����y����w�p|_��k�ev��@�����~t����si���^ ����k�S�p������"�8��[��3\��(�a�����g\[f�	A��.��U���q�3(�%n?����q���"��:n�%�9'�nci�tT�H��%F���K,�����K�n��78N��i��
���c�|C��1o���?.9�`��
��j�0�S�����+"�������0������~������a���8;!�n{�����3�����a�?���a�G�"��x�Ku$������5 �7\:�V�.�o��
���|�c���^�G�/�����V�����������8�/��Ws�w�t��.�n{�u]/��e_�R W�w�I�[�����'x!���o[@��|~����u
>���S�Op]����2����us>������e����;��<��y��@��_�����a����Z{\��O��)��A���Op�uc{L�$�n
Vi)���vG&����dd�q|MZ
�q�JBF&�i)��������2S�6�����n^��24����V)B����,Uh��x:n��1���z�V&������{e`�m���Le`"�����L8�_�������p�m�x!�l����L�m��)�|������9�9;�R����5�0\���e�������(1����gN� �;��=���Fw���g�������2�f��sK�p{��UA
wN�����{;�G�����|����"���0���XdV�E�<���kp.��*�3�y��k ���D��"�-zFA�t�K
�����~��/f��N�	#��\���b���(��	���n�o���������w
�~^�a��t��3�6��]$K#�8���v���r�BALX��t��S���������7-(�`���n
����Dpmc2#�
��9��U��b8Q���o���������d\��,�*��i�`\��`��"���IS���U��WdQ�U���f�a�����B'�S)�����dF	?3z��	~mp,"N���s����2���7�hg����6�@c�	�	�G���?�F��Ht�u��� ��Yo���D�p��H.("�r�D���p��=����8E,����������x?�����s:��>0�v��;��|:�������������h�o�7���i�����	���L4�V�	�4$$D8���	�/yHH�P�3N!!�V������	�~uX�sM����g�������&<�VT������� 2���E���AFB�h#!��T���sD���kf��#����f�20� �22�0��.q��m4�������]���	���kTpD9���r^��c%	r���+JBs�&���;:t���DT��FNH���I��`�&�h���%���R�������@q�������E�pq����s��gvTaD�/a�Hr0J
F�f}���h����.��kh�3��3[�3����3��>��3���&�=$L�w�/�4���W��h;�+�@c�6h���W���s�8�4�s9$u�D;\��W���c�?�����������o�6U���9�?��L�L�y�����@�L�n�v�-�l���]�am���Q;�������85���8D"s�'S������}�b���g0W���q���}��A����^m��>T��b~-!�NE!Dxk���CnG�� �����K{#�?��
�! ����=J�8�X�8Pa�����\X���@��������W�!����8*o�v!��������gF�����
�>��D�j��-*�����w	�_`
A�@�;��Q���T"j ���
5�x�,��������p���{�j]��D�N���><�
)E
A�1#591��#5�VE
A���E
A��g��sis@�@�����3���A�L�w&�#9��<�N�Uh�wY�4�k���S�Q Y���y�"��a~�G?a4N���'���k�M)
^��2��C�-e8_����^s�/&������/f��l.I�����l�b.Ig6dKs�������pd/}.q`����B����d�������f(�o�@��q����N�	��o>�m	��6fGq`��M�?9�6M0��SL�!H$NS���yB}SL��O;��
\}k5$3�o��Z��"��>o���j�Yx?;2����$�v����8������������]��=����7��zj?����{�=���`����=?�g`��Qw����A��f�H�<�sHP)y�G+��"��[
���-"i}���%����i����\s��k����=�����C{�t���RD�	�"]�@
.�cJ��oHH$��q ?A�&�Mp�d�zs)B
"���#� �)�L��6C�Sv>�T`�j���T�R�`�h�:�x#� ���kZ�~��4��S��`�����7��������
���qX�� ���QzU{9L��w��l����&���0p&�l�ED�3����Nc�%�	�m��S3���_��E�R�}�X�x���BI�X+��Uw|��$���L��nY�8���"{�>kN%I�������lit�\��R1���>h1���>�14n����wr1��N�#���p�����u��]�����u����U�����L���d��m
�	�/��La������bd&D8��)gM
����&���hw��yd&D�O�p�O�Q�#<��1���&4��3M�	�����&D��{D/>��	Q�BnH�_�I�U���(�<�I���
��!>���b�#O��$��O)�3�������v��B�Ih�5j�y$��1u���as�Gx�{c*xEJ�k� )	2������H/z(�$��(��u������+��
5���Oqo
�Q�2
���Q�<>��bv��
�S��p�����a�Y�)��^�q]:����+|~�kX�0���K���k��������������o�����{�p)���T�H(�wF�4&�����������'o��>�pK�t���[jE�}��[
�2��8&�T0�����0�S�u��N�����	��)�ffy}�W9F������Q`W�w�>��"a�U�{\���GU���[�c��Cp2uC	 �\f�a��F>��Cp�0�B�8�]�1~�*�@�����P�A�sj3�nq\%
o�uJRx
Go��2���b�
TX~a-^��F�0}���,��]a�wm��2x���b�
�����K�����\QH���.k0Q������D8���7����E�����H#Z��F�7���=����A�{cl[����-�+�@��r�2 Z�_9M%����0P��}�{�s=��>L�(��#5�VAL(`R��R	A�!+0�*c�����Q�����O�%�=?��D�S������f��R���T�����&�n�_m"uS"g��kpr�h�I�
����
i�f}F;�������e����Xp*lp���������K��x��8H'�bF�����8�.}]z��4T8������&.|`��7w�LXo�����^N�LX
��	������]�gl1��3�D0��y������"�7|�}�oE��/`� �8F��!x�{�E0S�'����,����~h�Q�UaA�Q�U�
�����!�d�VMe[����'�v��!�*�����gFW??��>b��N�b���X�l1����a�N��5�	1O_+��1W���P��3��1C~P���s�C$�c���"����f���R�("i�3�HZg��b9��`F��wv��<T�Q����;�qh��Q���)����eJV@E$���
T<^�He�
*��������Xc2�kL&�_!T�$P������_��U��j�{T����DPA��@����D*h�{��n�T}��cAP<O�4!���p�� ��k�+1T�V|5GP�Zq�*�d��dF�V�&�����aI�p"�����u!{��N�]�O�����F�Xc2��5�?-4z��W��G��wF�X�#h\�*A���;��R����#�s�KH'�_�<(3�R������.e\�(�(b���p�����HlG����`.�J�����>�?�w���
�M��\�;�z���[������������?������������]���y���p
����x��~��g��;^�K�b�a���F_6:l0����L{o\%o�gE�)~�;���x�h����O|�9������X_j�<o��i&��~=��w��9>�0�#c�(�?�-�q�h�M1L}��"T�Px	��=��'P7*
��x@��^!���3�u������|m����ZE2�f�Y[������R���w���R3�������\�~r���>�q�M��2�i���w�4s���$�������WO\�y)�Z.��w0�/����"��w z����{SX����0�5��>�
�kN���kN�������]�m��`�l��=����-|]:�	���[���������#���G�� �#��h|��x��m��`��n��"��cA�7S��:5�x��t�_[z�
��[��'Os�,�����{����yj�wODo|�K�[�����jM��7��.����f�|�w����:�D���Y&@&����{p�Y�p�E.da��
�����=!��Yx�X_�h!���\��_N�+���t\��_�c�K
N��,��3C�������
���r6V����
���"P7�� ����Qp������1���<�3������=�Pdfi�
	�Tr��2��@F�d��KQ��-1���{����������/4W�p�G���kh�:a��&����Vw�@BA�c5�I��{�]g��P����4&�c���D����w<;�-�a*1W�TK�q�:�P-A�_��:VKP��bp�
KXdT}k�b�hD��������%���� �C�
�
�4��L&�9��c
�Ix�5�;�E9�x���F���c�}x�S��H�nMm����T��}k�NW"X��`K9����"�H ��n8�@����o��I�����@Z��)"[D �a�Hu��F
H��si�$x���8D ���������W�����p�H]3�r<������0�����F0a��a���Ya����#x����L1a�;�PD���@<�;������j!ZP������>N����4@\}0
�Ep��2)-("R�_�ED�1�*��(���L����~�3��K�("��>�H�����3�n�� "���{�����Blx�c�2�QD���6�,��(�������;O�c)�n�B�����DD�z{%�&��+� ��R����B�5��d��H."
�L

���e�Q D�4L��v� �5�>�3���
W�������R�9�"y��e#;��xD�|5���?� � ��yU� ���B��C0m�B\!j���~������ h����BA��z�"zj�N�	"�>N�9r����>85.� ����BAA�s�
Aq7�)AP���'� Rn� h0|#n���6�+f\u\+ k���B���p@���~-���|5GA3����GA�������Q�2^��Kw4�f� �z�� ��"}X� ���t�S�1�a2�J7�v�(�Z�h�z��\I'�c�G0D �0�$; PI�;AD ��������f����P	��K%D�!�J��=� "yw\���z;<�/������v&��d2U��m)��h	W��h�
k)��`��������
K/l�`����Xm��A������wSM��iu��t�0KDt���q��:hRy���f\������{���BA�
�����{ ��Q��W������@c�;h0� �E�{��VhF�^�@H�{�#=h�{�������Yy�X=53�fR�B� ���*�A���>T�M������U�#��F�B� �zeg=��kMI���h�1>����T��(uT8��"
F���H:ydK��3�G�tA���<R�Xef��B�E������p���\��$�����Q��O�� ��Q�^1	��w�� �`��J��dA�;���Q�L�h*5(V�<2+o
)Xer��OG�8����i�L&N-��}���2#��I����t������2y>X9o�H'����f��U���H'hN�c
�t�It�fa��!������NYX�2�����3��2�,���RK>>�����2�,�1�����"����w��y�������l9���2��{^1���Y�"AF�o:�2�a�������52������<bA�L3�pF�H�0�� �e��@Z�,�+�+��+����;E��%������c���=D(��|dKj��?o�:4j�"DT��F"���V��(;�&U�������Q���w�����3�g��	��yS>}}�;���o��<ofx�|�r�fUKA�@�4r���N�	�RP��S����okD�T}�E+���i6@ZA�7�p��� �&���W� @*h��������;�]�m$x�2�BJ��A/u�
���P�����<�V�A��g�T�A�t�����2\�� �v����r�u&�^��w��M��\@4Gf�X�t�w`I ������li��(i����?��Fk�(���@��P$?D���}��'�#
x"�Np��
ZY|]����%L6�M�	�_��P�H���H(��������Zo5E+m�����h��b��c�L�����Y`��ZU�Ip���gL�����76`\}���&��{�B�L"R7,�Ipu���0�(���<f�Idg\d�9L�XY0����D"����N���2��wyj������B�Q�5X
`��5��CD9��w�X���z;q��!�������S���������R��F�'����Y�/�5�L��M�r������1�";�P!���("��HG��eJPD$-�c����UW�|e��6� �)n�LX�v�Q^��
A��h��
��U!m�����
A����=5���}�}�@��K�:\���h��
AP�$P
,AP��)\@�PW�)�	W��(�E��3�Z�"��	������f\��D�q7�k|)�x�{x>X�(�'�����hD�|���A��]�*AS���+�hD�|�.��FPuk���1j��F�s�W�CYD$�7�A�S\&�5E�7���f�1��q-��
��'
�"9:0��?Qu�@�D����D�.D<�9�>"y��'��x"yG#�H�_7�����y��H��j����wo��]6�jo�f������ �{cF:Z0��Tm.V`�����|��.��
D 4���8V!����f��"��Y;s
����r�����*�e����������"� �F�"��v�*�X�L`L�rc>(b�0������c�zx�(��@;Dx����
���;��U=F�{���2� ��U0	r�Q��$=�V$����nE@��k��"	��w�V$�����������M��^o���9i����R��"<_���"J�~��Ai���t�pa}*i)�H~|X��e$ ����dH����d��Xn&��G���x�D�	������W�
Qm���BD{o\J*D�"=����@���fQ� ���;�ZGQL7ydVxB�M���iF�Lz<��w�Hzy�����=?��=�h������������P���{s|�����n��DX��9��4':"BXAW�����Y��r+��j �A�
K�4w�0����c���Q��`�e��aTr:}6�|7}�2�6�|g�V��f���������XmR�4���t��-�\f�@�Fp��������I�(��`��$�t�x��i�YD�r�	�j$Kc�F�;��j$?Dl&���t��*r#]��fR�+�"��Z_2������s�F*J	����C��u�%dLym|���}�C��7c!�O����|#�����������"�<�\���N��Pp���o#������W�m�H%��5��W�[��f�5>�CI�s��D����
�Hxv1F�B	��1hD�s�$,��r���R�63�0�~���fF'�	�@�D���@�Ww�� ��r�^*���s��`Q�����AD9�Q�<~�4��'�4�N�����I�s{��.,C��#�`$�k�K����8C�D��s�t��#"�o����?�W]�'�c]�D��+H"{��m����'7C�KY�������������K��H�%h�����m��wYT��{t�!���XcJ�J�o{M��:R	�D�'Q�G��Z��4z"�JP��c"�T"Pw�F�JP���WQ	�>8E�J�&��JW%)@%���@%��+��a�U:����k���D�q�q"�f>���T/������t*&d\c�2	��ux�y)���Mm�$�����Ep���kQ1	��u�^�"�ar� 
������!�t���:��;7�W\:7��A�
#�����YD�nF�.}i�
�MD�f�����{D�j�"�@Z�u� ����v�^���L�`��"��4)T�hwF'o� h�WFi m}������bjD4�k�'=5/L�e��R�Rm�[�������C�{����?�Kk�����_G������3���,A�G���A��'��f�
G��Wu�As�hG�X6��#h�����#�x'����N����jGO���DA���1s�#����@�pD�q�Ks��<����G���2q����zJ�A��M#����>���+F�%��^1E�?AP$H����lD��
�ii�z;��.������"X��R]�n\qo�w}�H>��'����@Z�*��������}�P���&�^'������WR����������L�wh
�a0��`�P!�{�J�0��?�����{cBy�oB���w�����e�T�#V!��g����V���U��[vr��cL�X�%��C�6p�������`�z�Y�Rh�W���<^f�����S�'p��'K�NFG#�W��>�k��<1�Ll���'W��#�B��xt^h��X����1{� b	2���+�d��(Wnt�t^��{c@v�Xug\����oO�I�Tu����^&�q��+W�����Xi}��F$-�!a�Q��tpF���OTf7X��;���9�#}�X��`�
��$�D,����-
�%��dq�x��Q���d��3����;-.�,X������'W��vDD���"�WDt�l�Q��,����h����=#��U�fU��1�"��2�_�Y�IT}p^;��#P�_P*LAO�^�^a
�{���U���MF3�����jK
@
�>ZU ��^��Z!��
!�-{�@��t����T}k�V�"�����
RP��a�UA�@=�*#���R��m��T�s&���)Lo���:�p�3F��KKJ�0��7�_��>c�*O�@H��(������"�ck�l�P��+N���,\�:��o���c����O�x����]V��%���� �%�	�_�G0��Q��-)L�7|��%�iN�:���h/�"�xyL�������s�����O�U�+b\}m�@�]w�G��_�C�Y�5+""u���Pr.��D��q�w
���� �����-7<&+#o!��Yqe�	"�����@��w��G��_�\�UQ&����9w���D������	��5���7��Z���u?p������/2#�suW��J"�3��k�'����+��:���g���B$�3�2&�r�>��3�����HZ��`���g�i�1)e���{��l"�V�5:g\O���hc
"��g#� �9��<�Z�)�vg4�T��h[�V�)��������w�wC����J�Y�'�7�B������@dA��3��Bt�{kx	\�u������q^Ad�����"P���f��1������g_��3���x�$dQ�3x��i�����q�����*&x�;cTv,���1�D`A����@]����W�����u�*`��%,��&����OiJ[G$�0�4}��,#��1K)���e���3Y����(�����gc��������������@�C��(��JN9E{[� �@:��3��0��~\����,�l��'��+dA�_�
Y��h~���6��#���Q�V>�N����)�FH<K�bXA
��3�}+H�}�\)u�U��T}0� V����:����1f8V���o���"H�	�"��*XHAO�1K!E�o��
��s��p��9:���\�c�[!
�,���
�4��
Q'�x�EDA����
Q{�i�h��~:�	�"P7��Q�{�s��53� �VS��~B�Q����@�Y��"��W
�"���N�r"�6�<�x���{><.C��wF����z��G{�tF�����
b�"]���T/:������.����������W
�v�.�&D���d�/�]���vF����E�i[��+��3z^���|p&�S7������'�H���;>H���AH���z������a�pa���$Adt�Z��x�T���o��"p����������}+HB��^��Q�u����������!���F�s���[>K��ki",i�/�E����W������9mK�w0nx,	r��������XB�>S����f��� ���$X���	�$[`I -�,I~��f��j���^u1��[O�_��/���K�0�^#��!�kd��X`�H�
&3����W�s	�����K���_V�D�������C{/�WT"�x�(���n9���������k��%�W�}� ����A\;r	�v��=K{���]����\"P�[�+.A���U�;���%��o�%��1
}�K��k� �H���"����\�������s��}7��%�	�����yj���4��6s�h��Ud�����$���M&���v����k�>:��D��v)��q�Ba�tF!Gp���Dv8��Ks�r���`��������3��!'�}$�I$_Z�b�OM-���������rra�{�����7�����.����6�DS9��>���)�
�~la��Sqn�{��M��1���CeS���O ���)�����){����+�_�����}�H=�u�����3$\}��k���[�+��C)[G���WEd�\l�'��!�#q��+"Z9��	�\��������������WU�63�8U���K��Y���"u�S�W��X�\�����-G�;���b��sn��E�f����!��.f������a��������7Bg����V�����I#s�H$��b�.]�"�c]�"�W]\,"�����.�6� ����DX��Z�	�c��D�3
�+A��st�`����
F�x[��F��;������D�D�w�4��������^������5�S���h"B0A�{���T}pLP���\\�	���
A�U�L�l`d1��:�&h��������(-G,d_����A���X�N��Y����8s����N��:&	E������PP����N��T�������_�Yu�<,�}�D��l0���
~`
� ��^r1
���](�OPa�e�D��D�4�[���d;�"xI�'�XH'XnF����HZ.?XH'�pD��NX�,]�����P�����%�+���zR�
���
�[n2��7�XACm|GXA���Ua�w�+u�uaU�;�V�����V��^4j�PP�M�0S�nA"T}��� ����5�R}�?4�������(EpFSEp�R*'h�]�����
R� �B@@A�_yE|D@A�gg��VuA^�e�O��!{ng�~r���5�����T��N5R	��qv$�M�������	"��2��5���;
���5T�`����S#w���������J��@&2l7�^��&?H)�����?���o��t>�~��z���s���xp.�����_o����z&er��?���I�.�L�7>F���
��.�L{=�Y	�]p��a��~<��3�{M����XEL���Yj��i1�k_Y� @L�~�%�]p���@bB����E|SEbB��9�I����b����1	r�Q�n<t�3��r�=�	�z;�]D��X9�]D�w��A�9���q���	�zg����	�/{��?�� �nS�.�������P��C�����p?�X�������$�1������ bP�A��Q�	�q����~��.���I�]2P�H'8]D?o��E�����8��E����$?@$#��(~������p@�Fr8
����L����;`�$��htW�D{o��WD�Ez�y������	$D}3�]��<2���Z��]���5�$����*�� ��k�PdT���;pFq7���I{R�[VL���N�2	��uZ6�I�\`T �����L�$h�u<2�I��hJB&A#>8�J�$��n8&�g�}�H%�3��H%�~�Z
-�fn�����A���U4�J'�pO�hg���b�R	�>�(**��5���~�IpNu���gH�&�Ld��D -����^5��$K#��[Og�'�o��LPa�cv�������u�S\8����rk?<9���373����*���I�D��$a���YS^�{�I��V��$L{c�] ��1�r�d��.����B!����#E
����!(@!��0UF�o�@!"u��(W����NP��1*��Bp��S�$<�Q�^�(��Uq��{I�	]����z��$�Q�5���""?�"{�1�:s"�=�K���C�-rmf��Z7��?��h��7�������J�9��>R%���g�%����v�&�G����k"x�����.,�P�n�d���('TDD�	�����B/���"�t�g$-�8���H:���KN]D�1:���{��2"�1��������6� �z�GA����
F�H�za��������Ql-���D@-YA�=:��"h��<8���S��,�(�����%�.E�;�x��T��@��>8/��"���
E	W-YAs��WE���O�Q��(����[m�c<�� ����+A#n  ���n�S��D=Tpl��aj��~ng������
D�FdDP��a�S���3�@#����2���k�������&"�'��c�����"`��6H���[�I[��Y6��<6�Q�pho�����a+m'���H:�}3}��)iu�T����A^+lLAd���DX�|�0Q���/�
S������F;gTHo��1U��No�T}��\DLAw���6SP����U���o���T}���T��u���f��1���4�u
�)����o�WD}�)��4�-b
�$
U�4���P�)�������_y��������)����o��"8���z	~�{�]�$�hg�o�M&W���
SPuC����Z�;M �Z"Y�TKP��M.,AsU�<�HZ~1F"������ws���������a3	�"�g���~�W�	�������>�����?���o
endstream
endobj
51
0
obj
43624
endobj
52
0
obj
[
]
endobj
7
0
obj
<<
/Font
<<
/Font0
10
0
R
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
14
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
22
0
obj
<<
/CA
1.0
/ca
1.0
>>
endobj
19
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
25
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
30
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
35
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
40
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
45
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
50
0
obj
<<
/Font
<<
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
/Alpha2
22
0
R
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
10
0
obj
<<
/Type
/Font
/Subtype
/Type0
/BaseFont
/MUFUZY+Arial-ItalicMT
/Encoding
/Identity-H
/DescendantFonts
[
53
0
R
]
/ToUnicode
54
0
R
>>
endobj
11
0
obj
<<
/Type
/Font
/Subtype
/Type0
/BaseFont
/MUFUZY+ArialMT
/Encoding
/Identity-H
/DescendantFonts
[
57
0
R
]
/ToUnicode
58
0
R
>>
endobj
54
0
obj
<<
/Filter
/FlateDecode
/Length
61
0
R
>>
stream
x�}��j�0�����.�1���F���}0�����bz��/��]�������l�<4����Q�ho��0���v�7���j����[
��,��`hl?����[4N��tu��nH��5xc�t��k#���`(#BP
}L�$���f)l��h7a^�������s�F
��
��{ 5�G��1A��+;���G����dQ���<���1��B�HT�H�H%�D�m�D%G�C�&*8R/�t��������tmsq)4�Z�u�I���%����V'A�Q,�S��+��hU]VZ~���	���qxia���y��r�[���
2��
endstream
endobj
56
0
obj
<<
/Filter
/FlateDecode
/Length
62
0
R
>>
stream
x��}y`SU��s����I��M��&i�R�B��Pi���eGj�T�"�#�"�
� ��6�* �K� Q�Q��q\G�e�]tt�����$��m��{���h��>g������<���%FDfZA9&-Z�;�����I�4L�3m���f�B�G�/�.[2�}��(�������L�����QD��=����v~�$�QO9�g-X<�����?M����fO��
B��FG���	��$�H!Z��}s�M�3h�}������1����<r����)�"������1D�!ZO���]�`2M�%t=>O�g������OKi+�����.�h���2I?N�U,�TJ�c�"����F�BV��@�G���������]N�2��F�������y�[��w&�}�^�C0�$J�L�h�t������������F�K����c���o��*c�?��O2QU���OW�0�S��R���C�-��:���3�H=�?U�B��iz����;6�M�A~�4GV�iz��c���t>Ci5��t58v���J�#OG�M2!Qg����`�c����,�yX.����l��~�/�+�V�oI����%�+���!�+}%���V=_��������!�}��K�4�G����
ZI�i-V�N|������&�O�o�.�O_����ug}Y��.c���l/��^b/�z>���_��X��U&�B!��_�P�wd}dW�/�M�������M/x��v�Z����������0>�-z�>���8���X��:�"���`#�X6�-`K�*v���`w�0k�h�`����O�i�586s+�s/����3����i|
���{�A|��W��-�!��/%IN|��<i�t�4N�--��H�������{������r�|��M~D~I�\�^�*7(7+�+*��:����t��I}S����Tm�v��J{�D���A����3m������7����KN������[�Mr�L����J5����0����El�J��3t��2����:�������e;�H�_nf��e�����K�����Co���,��i4�����<��U�KO��T3��u�Hy|�d����S�9vG+�K�O����~7[*}���5�wY_eMU��5�a���v�A�K5��K�Dj���=�#>����t�<My����0e:�������T����?����i�t������_�A�g�]���S�����I�1��\f���Fi�l��G�CO��k,H������f�����Q��K��^r����l;��_Q���4&2��){�/����Yi'��c;����~���
�f�.���B����cV�K�X>
��4���|��H�H�b'_N�����B�/��;��o���%={w����K��`A���y�9�l�����!#��v��:S��v[b��b6i��UeTX�j����r^`���"���	�
�>U��&�k0���mB��mZ��-C--��WFe�}�_�������Y����@�/|�H5�r��ID����J��
_�5�*�U����l���vY-�X:�.�I+RaW`�.����wU������Q���aO�B!,�VN�1���"����\f'&�)0 lMh��MX��n|3�t�z������79hbC0ar`��q�aiB��#)�~+���'�g�xx���5�k3�u��>�]�n�/�edm�Z��������V5��B���E���JtRS����R_�����,H��0�Z�������G���u�����@������n��FO��9��s�.GR���l�X"!�ubJK��2��T��v21��`�A�7����0���2�7�����S�pWx2�aF�<�a���(���\G�����N~qn��X�����DRG���>����!�@,$������\����
�q�@�>Q������~�X���B4��������&f��PQ�.�D��xM�Q�"^�r{C������6����;�R*��	��_�����9��W��!�����E�{���R����R��x�d�B��4�������!���4D�(a����aP�Zg���������.���-6�p��������^�:	��x��c����SW��n]U�W��a��&}����X��o�����l��h�~���p��:Lb:�i�4`W���+���[��'v����9����A]�~Q�(�-�"�9�f����dTe��0je���Ojbd���e�&5�h��(�Oga���+��Zit�.�c]��j�d7)r��G"�&{yL�"�9Il`���'�A��e�e�g��6�Q9��q�����O����L?���?���|�a����y
��F6��2�*WM&M1[d�dKH�T�]1;nK`��!fi	NMK�	��%q�C��aN$G�`���W�&�X��i�,IdJ���z�;�q�!wy�C|�`\�e'Y��4��tM�����^�����t0)����8lO+O?���j��5���u
�������_���j�����~���G>g���R��{�r�?Ul{d,?��y��������]��������><�M��E������)1A6�����2U�c�I�?�����V2iO���&>~���f�)��e�e�h^Ff��v*�bPU<NrU�t��2\:�q������������E����3�'�^�f*�^�K���ek�.�#���V_���_�b+��?�� 
��t����r��H��"a�#���_��������J�%�8���
@S}����O�I=:4��?Vg����oj�C!��.y)3����V���R�|���O~������&evV�)���R�re�t��"����C�$�-=F�b�����0v�~����oE�v��O�����e�8�O� J\J���� �Y�_R���c^�#9��{Z�K��d�<��V��$E:?�W]�$�������S6��;��&����wl�|�����=����sH���2b&�������z��E�}��\��bg �"�u���r�Th���H���KH�q��%�lVGr�=����p���onJZ����d�=�fu�U��*�����d������?--5�9�x���v��L99f�+.G�d{s�����q`������4��-8\����P����6Sk1:��0��d��j6��el6J��x����B��:U%����������~�gd�
��O{����"?��4����f��>}����3����7�s��H�r��+��-]�.�K��e�E���:��!���BN#�,l�����T�
~!�����(\�L&�I�
*d��-�br*������sE�Ck�b��������t�����B	��-�{������'h�tG��L�I�����nP�+���Kc[.��C�l�C���z��b������6�/�>�����o�����K��SEL_�!w�|=�J`���+��?}��8��������U��O]%���j�����'r/�u���dh���Y�%�H�-��.`j���t��_�QX`����%;�f��RJ��{z~0XhItZ,�i9^s�J��ky��^�������&��PV�O��e�eQ�#0'�zV()�e9�fgIY�b�y���~T�m�I�IX���H�]Z~����[T�H���b��OT_�������=z�*��S��g�������W���"�$5��
����f�n�^�$�%O�y���&���\���|����z�k�3�k=};�����w��?�0c���
���~hM��F''�2/�V��}J��O;.��3fN�����_��}dw�m�KJ�L���qx<r�B�145]h�,q���s��K�?i��)�(�<��������R?�����)d��!GR�)�9#�@�r�^UK�'��k��}��u(�P�ax�S����P�9O��&sJJ�������4���*SM�a5j����`2������Ezi�n.���9XI��.�C�;��O���X,���aE�O��T����],���J�$,TG-E3� [[,�Z����U�~�-GF,Z~�y3�t.��VM�y�����tR4����W6|�y|��y�����7\���������{z>x�y���!K�4�9-�6Uv;3���r}�1�q�y����:����Y-�5���h+��
�	���d�U�x���XW��i[�O��`�%���m������~[?�����3�-F��t�KL�w�$�0���Pc(��V������1�m���l�%��\����n�:����{��x���	S���|�j��� Q�a�� Qv����������%�Y��\�%�&gz�	M����4�3��H=�v�Mu�X�[
Sk,S-J��R�Z�X.HU�v{���4'P����m��[_��&�������o���&�����S�|y�Y��e����	'�O�����"(�����gs����8 �bJ10g�0������������|j��S�����H��K/X6��k&��9c�v���S���C�/<��g�����,������v)�����l:������
��&�R+���g_���#�=��s��z��HyR����5�2����NR2K�gR�'�`#���h9#�0iS��d��,��	�����o
e8}��@��r�z��a�c�����/*��|D�c�������0|��cA!*��
_�"�S-����jTR�?�,U���z|�3��ft��~�Z����=����3b3�W1�����7���Q^�-w-eK;$��qvI=�������������N�R���w����%�J�d�9UJNMKKB��k�d5�������P����gfN^(��#���A�,pJ0��RS�ii�d���(�Ew�q��_m���8���8�}S6	�������+K\�'�:�i����y���\h~��%�p Z��I�b- �?yO�=^w��I������,q���|�I��o�;����='�[��T!A=#��@����e������������������R���)y+z*���=ynrnj9�ye�.�.����O�w{<����r�����*N,�:5w�K��&ZTo���6{<��0\���u��y]E���\�x#��&��������K�������8��-�����rX\������4\����#�����_�����<P�15~� �Q�)B|t2���G
m����x�U��.�\*�3�qKJZ���b���b��t����6�g���6l�����
��~s�W�un������v���?N��]Q�u��W�,iH��/)mL����'�ld�w<�����Op�(=�d����z��?��s������M�f����,Oc�o"7�\�`Ve�HZc�K�6M[jZ
;����$U��6����%��s�;���		�D�31���*�l"$�VBBm�y��9������_J����'�N���U���0�f��������z��������~���t������s#�����8��.��c��;#�Zk�����<�����jR %�>TM�v����]s�o��5��*&��R0����c������
|����5������M�>K�����>�Y�c�I67��CC�z�n^a>n���"�f�#�Cf���"�L+�I�\�2s��I����j��\���e�����x�\!����{�MpS��bL�
��E����]�����y�r�_��k�������Q���%9�������kjv�����n��<����'kST�z2���M�)��Sp.+)�XJ��*�{���w��#�|��R���.d�
2|�8)`���E?�du��)!�b�R�z�v��f��]
Hw[>�|cQf���nS_��]*xam(��@�h1K&Y�e�DS"i�V	�r��~%&{��!����?��	��l0#4�a6�,E�d+�UE�M�j��I��\�X�F�c�����4U���$&`o��Ud��o��y�XS(h�')LY_n�)Q�g��qv��$`�5�EF�y���
m62���B�R^V����K��+"tjI��AK5V�Tf*�*l.t���"�bI��X��'��T�/K~���/@D5�}Y�<�����%Vg ���lp���$V2[zl.|,p��%����\��uG�����)|��V�jLcl%O�]]��Y�)���Tl�2��B��':zH�
8/(<e>G)�#����
x}N�(�1��gON�8�NQ�d))�\���&$�I-�f	�����Jt����N�8R8����Do�#�&���r�(�w���� 8�sx�����:'�(����&[��f�B�'n���������<���B1a��5C-�~V9�N|go������M�8��k]���2�l����e{ou��1��K�g�y����q��I��u��|!�&�G����������=B�'b�Y�R���N�F�h=5�9�^��T�/J����'=�tF���$�������e�U�Q:�X���p�`�������"�$�����JL�m
`���ZH���5�����rv`���5���Vk�>k(�b�d.�a7��,X^F�	�abv �q�����,���5��;[;�<0a���k�nH\y��������&�_��������z8��H2l�dx���=�h�~J�O4>Q�e;�YC��l�*��,��96�&��;;���T��"����Y{$��W�XY�>
u.�Ay~��4�6G����ySZET��
�9�u��`f)���4��$���o�"&�������>r��+���w��>�&V�zo�|���=������_�yf��O�x����?��M�G���8��<2C��%��������������+}R{z+�����J���L-�����	�z$&�Ap����-q���F��U�;/�7��9��U��%'q)����b����eF}���Y���f��S��t����������N�5�C��C���/v��<�������\�O]�E������`=	���X}�q�fxw������E��Q�9tq.�����y��G/���������<���<���r�������P���l���>���C��+�����[s��_��B�b��NgB���u��M7�e51-q������I���ro��bK���f�s�������`�c�Z��#(�=���d(6�*Bx��
4���i�������a�z<���Q��p|]o8[��Q�'�OW����*�Pb��k��2������>n��wV�
(�eq|+F#	[pK�Qw��5�����������\�����W"'#5�
�����B�z������I�Ta��[����--��zn��� [�@�D���*��V�����=Q���X�Z���v�w��K�J��T�2s���J��:�{S4�������]�
E�kf�>��2������i��r�<�t��XRN���H�����'��<��s�C��7��Gr�I���-g%��$�{=��h�aSJ�c�,/��/�=AI�`�O����1{���Y�8'7�~����{��U�%�Xx���YW�U3�����+�L�����,�t�=h����%4����=/�����~��_l�%}�oRvP:�
\`�j_d_c��vG�}�p��>I�Iay��l-LJ�u����I�������Fg�9��g�N\`=�3 �d��9�V�y�Y27����������g�q��� N2�^!=��1��=JD��R"�07z:�>���e���+7fn,yi���]�\�e7�>�g~e`9���)WE��o�;'������\-��`�"����|��Q�Q����5xw�k�s���b�)���:ZJ���E�	�j!+r�&
N�S=n�4�3
��j,w�GG��4u�q41qfn���M�x�^n��-Jz~���8\�i��������������DS����bvH�uU�q�=��")�
W<.���[z?S���z��8|�b�G�D�'���,+��8a ���>hx�6G�`�>v2U=v���-r�s�����W��!y��Cn��O�l���}���0u��|Js�����,�)Y���3�h3���4����>�0{�w;�N��=W�\'��^��*�Z������:?6b�$���H��]���@x������`��R�\.������j_��JN'[�����d��&Y,��H�Mr:��I�dI9�'��O�����JO�M:����On<la�&����2������O{2d���x26�7���������G<���=�*�T|����K0�$x{2����q:�@��8����x����s�c��s��/������[
qh�Ue�6���)\�*���L����=������2��;���	D�d]<u�^�|r�s�}�������>;f^�|+�bP����?s�����d|
��yO��}�����i�w������
p��E��@�?��?�,���Z�/r��ScMyi���Y�<��3�L:����l
���@�Y��/��$K����.����h�<��.���
�N�;�`�/��g�`>�M^�������:�.Fz���������D(���>@cQ>�����q�����t��E:�m@�V�B����9����Z�I���/��<s,P�>��^\�vb=E9;B��#�	�UH�B����i2����x"�&x��
���86��7#-M���4�;� P����7 ��9��	����������@�W�����+���T��@���~�E�%��}@(�h17�4s<)O�+M�?�q>���}��`>U�wR�t�z�n�z+}�r���o�>�mTs�1��Ex���x�"C&�������)���w^�O�7�[�
�|�Q����;�L������XwV��	�3m&~��60J���c]��|��g�����������bqr����E�0px<���P ��7�o7�(��W���MC> B��Z2�C�!c��a
�w�9����2`'p?�|"���Y1����l	��SC�g�^<������*����=��S�����C�[P��z	����/�����h�g��c|}�f�d}E��y�B7�E�w�����h�t
U���<Ba�7�r��\��NW��������
�]@{�]��/
~�Jw���_������;�Ob���|���	mv8Z'�@���i��
�k�N���g������$���9�
�����@�)�n7�dM�r�DgT�B�G	Q�/CN� �E��Z(m����4���-x��j����G��_�����sZ��92�V��4.�m���1�2��g��J���o�A�g�>@G0�U��E>��D��q�<WN�#���<��V.�R��@��������(t���B��R�o�����c��a��illo�����<��=��eB���W��4I}��Kh�:�}A
j1e`�_���K�/b��{��
>����U����g/�E��y�:vc�S�F�ji�{O�}h���T)�A�J��7��b����(�/�UFQ�tZQ��6Q���A��[��	����}��2�����-�m@E���},c��������b�Mk����1�'�Cy�d���sb.�AOcNu����W�gi5�>�S���G`�s��y�5�ya������3l�!����Doi�t�6����5�D_��]@���z�[g�,}
�����K���3Ry�vX:�}�ZC�t �nP�}����o��g���6>�nS���%Z"GK���'�K���d���Obz�RRQ�o� �;��D�m����������S��U�i����r���� +��AT��7�DA�@�Cs�0���]P?Zr�WH_��i�����5�%��L�F�H��H���+���i�d�F�9��&���r
�/�I��P�(��{�;��~Z�v�L�������S����^�����}�
��r������A������^G���?�v�<�% ��7�kc�q�3����T*����s�����s-�$1������\�'�����m 7J##[���o��>A��[�]P�C���W�%�V��g���������E���F��2�s��LE9��O��B��^���e(��M(�:7E�3��O�(���7W7UE����G�ex�����#_�����)q�����wP_T#��.d�'~��:�y{���Vv�7��'mm�M���������o�V>h�C|�l����8�#��ts?��2���n���G1j�Q����!�k��],�!t����+A�|�'A���=v���������^�k#�GhK+��b��h����������*�_E��~�����x11����y������q�X�v�"��
1�s����*�s�����G������b���;�����q����[�c]��b������"�N���J��l�x��'�a���<�<t��2a>&G���B�d��K#n\__�����>�������V6������3����g���~Er��{,f�{��U?����7������y����\���k��^1�q�����2���=�#H���g	r�l�p���*��"�G��I 1M�.b���a,���������� _^�S���K�i�5yu��0+����q��Q�B�}�g�%��p<K|�U����c�^����|.0���Q�����������
�r�b������s���r��d�e�������?�c�3�N�����t��8B�)��_a�����8�+��Ga����M)�
�#@���aOR ����>��������3��Yj�� �w3���!����VgT	�����+���-��%�?�s���B�������=�M_�'��_~(��tk[���(�#�s���K����
Z�(4�-b��m�rA����8~��/�������y��������__u[���0�_�sN[�<�W�1�-P>��8��G�����c������/�G~	�mc���HI@%�.�~�}�?��hs��+"|�O����r?(|�������|��I��N�v3�<`r�����?R���������c#c����� �.Dz������0�����}4o@���XD}�l����|7 ����P��E���g)������� <��O�O�����T��S������B������V5t�T/���u�ie��i�|}�>��P@,2����4({���W0����=Ck��y�#�E�����C�}�vW�'�A�J2�3�~��	WX.��O��	��/Uh�41I�R�o�~\Si�2��wS�����!�������fuKG��L��sRq�=qjz���P��F����@��y.�w�3�R�sl4!�u�/�5�qHl�+
�m�<T����a�g�a?���W�����h~�Q���>�>���}���y��[�Fj]�c��E<o��/RHq�7N���K}�S�8+0��#�OC>���<C�# �g�m������0|��7>Pa?[��?�76�X���	�7oKcc2�'>0�7X��]4X�	z53�`�>e&������>��aJ�<n�r�_��V�&�����X��X�%x4b2�;t����������t�Gv�,���#����w/#�����Fu������-��#���F�!Fe�����\Y �Z�juQ�
m���������k��XN�a�����.�R�r���g�z%;�&������T��c~��fGiD��X!�mi�s�_:��?�6���Z��
-my��4��������������6~�U�K�@��wl1��s�Xl�Bc~y��q=g�}gg��c����������*j^nE?0�����E������
8�����@���6�N����Z��g��~�U�N�F�jE����������]��3�����x��>���
�1�C�dc�[��XJ3L�c�=���v��-�{��q����2�x�������<:�W�[���5�_{k�/�&|�=l��=g��o�*�+p��/��g���>�%9���KS����h�r�Dn�O�������_�}c���N1���GC?��+���W�}D4&�����F��c�o��B
�*2��t/���"N����1o lV,��MrP��8�Q�2>V�*&����e-���bCW�A���`x�c�.
��1G�	� ��B��.@���#OE}U�c����h�����t�e���'��93�����U��g�B��k�J5���B����p�]�8{�O]1����si�Qv�Q?H���-"����c�_|�-��@�~���E_�E�[�w����Sq6�g�|E�E�����A�����q��>�{��h)LK����pZ*�=<|�6vZ'�D�>����6����>��{9p+:�q���S���<Q���� e�j����:����/�G����>���"'�����(���I�������.��R>?M�0��t��?G�����a�O@��RW}�\"��O�&m�+�_>��V�a��&
�zX���+�������4
>��b���� #_�W�S��"�;����3��G�wu�P�3�M��Q���3m(�����%����J����p�y���xn�'o#�g����:<�*d{tc�TP��L�q�'���7��L9"��E]�}�
���t��o�~F?���)��5^@����W^���T��J��z�je����������9�+��1Lr���s��wk����\�������}Q���<��k�<N?!�i�;�L�:�v!/l�����	�����N501�j�>�E�~����Y�������l�V)�2
2���S	���� ���J�#�|`.��|���8
� � �� ��o,�j��l��2�
��
9�"0�}�k����$��m�-���l�o����2����,����z@�b��U��S�@}�[�����D��������Oh���3w����W����O=�@�#f�������$2R���5�������aL_��V$��V�������?(���S��1So�}�i������\�x�t��x�~�B���9H#p�������7�g�����{k�/->�D�����:N[LC��.��]�
z������w����(D�q�����x�C�/�-����\`��n��!w.���~�Bk�V����Z`w�_%��6��:-iE)YQ8?#J�'rA��D��B���w��(�����hG;���v���hG;���v���hG;���v���hG;���v���hG;��_����G_S�%�89�����|(�$����c��
��K�CM|G�#����5���1!������vz8�d���p`< ����7���w�7H����W:dhw#���(5�����������"���{�h��[4����|+�x���q-����omL���fv���mL��n?��E�{q����
YP�<\��S�K���7W����x�Zn\���=V�����2���"�Zn\�����h�N��>����,�L����Q�^*d!/���������&f
���v�
�v�}�{A����A������[�H�U#��D.%'�BM��}�5��k����w��7�>t@������y���>#K��;w{���jv{��m2�����M��R��yOx��}����������h����&o��V[
�����{�ww���{��r�Qu�$d�N�Mc�zk}M��a>����x���JTV41��7������qkwq���n�y�.^���hw��c��QoGt�m�R��hN4�lz[��C��]��\��_��W��K��S��U�T�m
j�r�M����lr�l���d2�&��Mdr�_�
��:Qeq��������z��"M�.�p�T��G`�����z�/���@��VX8���/��V7i��pI�:����vc7��4��61����yD���o����z���!�~���:J[T�.O��TZU�3�����ip��'��#���*�6j��4dG#�Id7��;3|k�����u��"�g�U�o�W��=�������v�T��%������j,��b��h�� hgz��E;*7�f��Y�]�h���K�Q�hH���.�=$��v��(�h��z�U�]�����mD�.3�x�h��M�U�F/�F���M:��tii���Ibg�x�m}�6�����3e@0X9C����]&P7p\��9��3�=��o[�zY|=X����T^�6���VQ��u_�{y����u�cU��w�/� ���&��r�����?���r�8	}����C��-���~�������[�K�*����:�u��Y��M��ha��BIji�Rf6���/d���C���P�Qk.�o\�A���`1
endstream
endobj
53
0
obj
<<
/Type
/Font
/Subtype
/CIDFontType2
/BaseFont
/MUFUZY+Arial-ItalicMT
/CIDSystemInfo
<<
/Registry
(Adobe)
/Ordering
(UCS)
/Supplement
0
>>
/FontDescriptor
55
0
R
/CIDToGIDMap
/Identity
/DW
556
/W
[
0
[
750
0
0
277
]
4
35
0
36
[
666
]
37
39
0
40
[
666
0
777
]
43
52
0
53
[
722
]
54
56
0
57
[
666
]
58
65
0
66
[
556
0
556
556
500
556
556
277
556
556
222
0
500
0
833
]
81
83
556
84
[
0
333
500
277
556
0
722
]
]
>>
endobj
55
0
obj
<<
/Type
/FontDescriptor
/FontName
/MUFUZY+Arial-ItalicMT
/Flags
68
/FontBBox
[
-517
-324
1358
997
]
/Ascent
728
/Descent
-207
/ItalicAngle
-12.0
/CapHeight
715
/StemV
80
/FontFile2
56
0
R
>>
endobj
58
0
obj
<<
/Filter
/FlateDecode
/Length
63
0
R
>>
stream
x�}R�N�0��)z\ZpMH����?}hl"�)���������M
��33e������'�a�5������c��[��c2����+����h��i��r����'/�������[�b�S0�����P��>z����7��D�l�	�������m�|+^<�XR3z40�FCh\�q)^���8���j;
���)O�~o���<B��"���?�R�LJR���@���P�V�2��g��O��@YvC�V�Z�R�'��(�.
�`�H��N	${n�_4���u����cq,xp�$���m��_]�?�D�
endstream
endobj
60
0
obj
<<
/Filter
/FlateDecode
/Length
64
0
R
>>
stream
x���|UE�?���s�����K���!��h.U�4)$�HUQQ@����kC�(6�%@����.�Zvw��`]���UH��y��Bl������������3sf�����	+,	����_������!e��Y�g�~M�jLG\1��k&MV��p���s��	�����0d��2���l�����)3��W~z�P���^>��	����,��������;�z+�g��8+��A�1������"���	���H}�������/�9��+l���Ix�M�ga7���c�M�������]�w��%����k����H��a=��z��u/�`Y8�%,�%���j	8!z�������+a,|$�]��f�E����Sw�6�c�S�s�����w���S�Clq<���� ��,���X-��,59�#� ��1�0��=<�o���0[ ���<��K��Z�PS`5�b��|�e���A�c>��������2��xjC�8D�=�����7���qqS��	g�T����Gx���ir�JLI������a$��	l��'�J�������y��f^��Y��!lo�g�5��`������|��o��%�v���G���SJF���W$�����/����F�6���������w�S�_���/�p<
�d^��
c�)l[��d��� ����#�t��4E�-�A�������M���[�/�F7�m�K�?S%��0�a1��X�_��;��|�L��\�gYl$�o`��G���)V��d��/�w�{v��*<�g�l���s���w�!~�����-%�r�R��f���I��w�����)�������'MO�^4W�-`y����E�6A���{��4��>��ag!�8�	�;
��^��M�&s��EY;�]�33�Mc��|����j������8Kc����<]��#/�=����O���*~��o�%�d��R@*���j���<��^�Nz]�@�D:)����l�cr��/'���q����s�s�X�k���M��,U��2w1�gjf�1�a�n~�2��O�
v@�vXZ,������T��7�H���V��R��l9����\�|�~��|��}|-?�����l8L����)~y#F������<~���������U��Gi�^�:�	�5xW�������lc!v�?!
E*��|�i4dI�����z����NYV"fQ.�`%�_R
$>����)�������r������v(e�sx����
�H	�W�Ty��z��S�u,�I&?��j�������6�PzG��^$7]�� \Kavj1\c-��M���<�0J�R����B�*cQ�mG���r��4K�H9 ]�D	��G9!#ME���P���
0��b(u���.�1�����d�"ut@y�,���$�;�I���:���9�L}�S�T������{�^_��<������9�������*�2u��%�p)�#���`��=P�4�oN��f��~�RO�b�SR��x3�`�9�k\����{L���I���<���������-�^#G�HV�wn�9�+�u-/+-����c����v��y�9�Y�XfFzZ4~����]N��f���,q������_'�������9�`B���uq,�{v���xQ-~v�$����fR��l���x%Tvh�����;'������z�T����� �^%�NLgea�x�����:6>����USV��_��n���k��C{�l�c����P���,t	��}3�U����.���FP'���P[7t��>�����;��c�.���rz���
���)������T��5����+T�t|�Q�S;a��:iB5��I`���B�	������F/k�4MZ�'<5N�+����
��i����l����_��^��8px{�K�G��%�e����J���9}�d��x�5�g������DW����dm�F�;S�!�'�b���������	��7�a���l�$����th�Y�h����g����g"%�Sj���3�hD9�� ����q$�s���Q0����V��j���jqE��Y{�_�v�rj_g�Ss�+����c�8�d�^����%�N�I
���D����H����x���whU�����1����8�����ge�����K1S�h�h-�K��@�8Q]����=���Hz��x��||Rr=�����7��V��>S�����<��=8<g��1��}V���v���r��n���T���h)��)�&��H�c�+Sf��N���A��
fR�(a��u��~ZXm���75��S+�i���{���9g���c��FU9p��+lg=CR�:��GH�0btV�W�D����R{�����8e����V�g����������C��(�V�����b��	
�E�����;�������7�!������+�q�����zn�a��mN��������^a���[8���������F��$E)�R*�L�20��Gn�Q?mg`�x*������(�e.k�Z�j�q,����(��1�F�nI=�%�; 5r&l��n��dy�0`�tO��=��&8qyU�:�����&�B�h1���U�UQ>�MKk����p�G�iw$�9�}��+*j_��K�HDbi�p^!����#_�%���<_
	Ig�zk�3�
��w�+�q��+�.N�'k��8�����5S+��*��i��VT�uL\����)�������]f"���1�!S���rrwBr �<6L�,�*�(���,�t�A�\�cA���H�?�H,f5��.�%�����|������.�e�+e��]����v,]��U����7B�����������2|��
�T���<��K�w����4�����[}���*���n_�=x������y�'�k���\����,>K��� �Y��iV���n'�Gj���x����`6~DyV�o��mC3m2`�p�'A^2�+��+��l!��:|�N^�X�Z���J�K�����4#S���P!���N����9����{�TR_$=�7�)oV)L�R;��Z�?�:�=G�+��U
7s"��-�)���Ng�����n>�����)8���*�b\��������6+?}�	|�Bo�����o��]�W�T��A!�5���;��xDMG���m�#�� ��p�'��2�������d5��������H������������/�]��v
�Z��~�{�r��^�����m�m�{�h�pi�4������
�J�i�Bs�����NVV����Q
1E�T��*���q���
=s�b2�M�@�D��QVe�|+�;~tM�����-��$������F?Q]m�J���z�!�����'
�}*q�G���6+#�����-�zN{s�[������z��j��Lf�>3nkS�����?={��p�}�����o�.%��I�R�
�M��i#�M|!���}����S6]^���X�gdf��%��98{�&��F���PC�p��"!5��Jzy��r	��5OF�x
�u���L�.��������"�]��-�gk�(~0S9����B�SA�	5�����(���K����T}�7G��I�<����~���p���'2�,d��N0#g�X�0����W(!JS!il|�q���:�>�2�I4����7I��b*�o�$

Q��Lz����'�����\��m�P<�z8��P"�����PL$���po	�o����r�a���p���I���Gf�����_�}'Z�GR����FI�Qo��d�sL�(��v+��_���n���v�pMw����^������h�h���c�}�����j���*L�Y<�����L�jQ�W������%=*1n��K�L��o�:��<
,���h�[w�F��j#F��67�&/1+{�/�8��[���V����|!�x.*�;6��!��TOh�V�X������K���2W�� �C��v�V3G���@V~W��.��r�sA]G)f�O6���Cy��������!������y��/>26��g{T^����G'M�����|�����oX>�3q���gri/���Ka!�t
�����	'i�����7��v96��L��] 3]�l�nj��q:���J�7��wb��b�����UU�1�.��}�>o��7QB��/49��>��N���"�Ui�����i�����k�K�+���=����� :������e��dk=���d��19��o�����(M8L��Xb����fY��;.>3��ab��"�Q�lT57W5��b;�A����KO��V��:�X�-�7�.�
'��,�W�o`w����!�O$j��r���c� �VP� u�pa��I���u�Eq���AD f
M�Q��{�/���������
K�M]�������_�>���UM_��B��~`Y��������_v��7���<yK���:f���=M�F�B%�j��r��v�G���34?NE�����8�I�sE�VM���lO�f��,��&�"B�ZE���h��j�S�W�����%/�78�l��%3���UI�K�,9�;��Yz�?���%m �X^��
|���������a��
��F���5�4'�s����������������q.qjLm0qd;���\
l�X��&�q���R�LjC=Qy��SQ�t{XFy�v�q�qC����x+P�����VH�*$9#��^Q���u�~G�^�X4�����pd�c��B���f���$p�P�J=����a������w��W�T��=&m?=����(��i�Nr���,����N'}>��^���F��Rg�H2D)���"���A#�H�D)�0�"���zS%��gK���p��4�,�e������nY�Lw������q)Bb�r!�C\�,���	�v^��"�&cE���'|r��x/�b��]EQ���������F��^��U�����]n'�����t�sq���0}P;�2{�D��������T�w���B%,�J�AX
��!T�����Y9��=�y������p��-\�/5� ����%��e��	�$��]����lZ�2��@���~3��F�!���7�?�����O���i�1��;�0���N���-RW�����[�T�=�t����y��-�I�B�
���".�D����O����e1�4�Q��?�K��-$Y*6mK�8��bnc��q3�N�t��f���;m��Tj%�'jfH%�
	���������~�%��j��{k��:L����d�w�w|�wD|�Tk��L����Y�L_bY���������-�d�B���RY����s�Y��C���8�4�&��
���13R8�-���<����)+o�*(Ke����<��l_uU{�l���L���B0g
���*��U�q����!9$�!1�� �
i����5�����XK�;�)5��p�t:s�a-��9�9�@l/3i2/Y:9��Q��^c�d(��n���#/�=��\�x���?n:��-_<�Ac�!��������(wM�4��y������u���@��=���/���fcu���7m����-hz�0+���d2��-��	�N��V�s�$q��!���x�m�k�� 1��RF3�B�E\:3VO���t��`�$�T��+<���G�y$������:A������.�����}����+�i�6�jx�Y�{�!��G�� �� :I}wB��U�
1l����f�|�;v^�f������gNJo�GE���x�{)U,��PkN��-$yzs>*���.���X<����H��H��-|d����L�T��uf�E!'��A�M2�x�ml4(!��=$M.��f��r�o�����|�����f�1���
���E�
���Oe�8���B��Z��	�/=�}Fg�+�`��J�� k�������N&k'v=\���,��sW:�
�
+�Jy�e��f�R�m��=�|�l[��Q���b�:��I�D���c]G�b�
1�i��L#B�f��me�]|2$�J	�R�Y�$���q�5nn���
��d�$,LX��0��u���d W<�s����c#$<�����n
M84N4��f��[Q#&�,*]��V3g6���Y�Hw���@�x,��[����M�u�g��|5}����N��N��;/]:}��[&M^�������|���OHi��������M��]����Oc{�x���r�M�.[v����UC_t��'
qv&��u;����C�k���"��8]L\V3+Ua�S>�R��"����0����;����3����+�/Z8v�ch��y�49)�;�iZ�8�,${�{�s���O�3���k�Kr��0�1��t�e$#�(����x{5%BK���C�'nTI�~�R�#�� �X|�"a�yS�B�g������%��G/&s.^�3I�<8#:9�����+��f�>}>�U�����������A�{�Z��������+���!�qd�S��������A���3�<�]���c;M3=�����=g�������	 �!O�Q�ES��f>�$=��*q���yH��f#���P3��T��$l�
���e��1d�G���`��>����	����uyn�������c�]�_�<�.��y��<����l�z�,��,Gx�tf��GL]��i�wM�7m��n����{Z���d@�9]>
�+2����E���v���
g�@���E��j�5E��S��wZ�\�nu���S�@�F����Bs?�X�=�\������>(��2���:��^/�&!��In�T,'��U��������T'&Y�&�r,�����e.&���e��,x\���x��bW���ZW�eZ����I�7�v�r%RvM��r�������R��\���.��HYZ_��p{!U������y����V�.��MP'�AH@�$���\����h^VnC��oJ���L��K�Tf���V(�~�N������z�4��_�t$�+����)�T�X�r���w�6�<Q�w�� ��bO_W�*�Y��N�	�@(/�],h�XPw����������*�+~!����@@��"T��OP���P��4���OJ�n��\����e��p�;a<�l���QG�*�#����l��4��6P#m�`v���.]�/r���:���& ��r��tq�m��TY�s�������|���Yi�����_q������P����K��[2c��G�3n���%������<�����}�����?���n���t�pPq��9�j��M}!Cn����	!����w#&�*B�UzD����\��mgI
��0���vs8]�3W�l��6�50�L'H�	���>!�q�TB �{���b��|�B�}�C�}�C����
�����������4���Y�E�����m���c��S.����g��%7#���4��8�U��q���m�3cL��r�%��X+�e���&NN��Mr�`�\{"�jq�t%z�dI";��Z��`I"2�$f���X�����r�Y�\e�f53���YH�v�&j�;���5�X:��!��9�����t���sN�D�c����Wk��D�(�g�i;�2q�2����R���o�n�?�|y����6E�Y�q���ngKB;�f{������M��Oo����(��"-}d��`��l\v�9�����ry�E|��B������4�z�|���[�C�"G}G������8K���X"Z��������;�\g�`w^���8����_d���<�|���p�, ����pi=`���;��YJ�����y�Q�l"(D���=LE�9���#��D�1��xIDz��%)�Q��=a���`�u��h=�>f����H��4���25���o�Yp���n��G��Y&�b�����<3gj|%hF(sT�L$�l��vB)�D���Bq��T���<����O�vQ�"fg���B��Q����Z���&�]x��io�4������g����'���~����]���zp��}���W_����{IoD����&���&�Az�c5��H�Di�i�u�� e�O������H��;��'�rgo�H���A����c#�O���NH�����'�*��


��
J�t�*u��UUNK��a�H\"4�0D�R�����P,���Y��B]��N�{���4�NR�4�Nz��������Q���l��/�x���I���u�&LU����5���-*3�Z�zM�[�{�XwMV��nZ��-�����h��`����T6������W�8�RX�^���4�C,�h���o��%�3�t��������[��s��_��,�le��|����[<�F��g1&1+l���5�i�v��^S'��CrXdzB�]2�oe�Hq�S$�y����)�%�,t�E�D�Mk2+��8%�;��<������~�O����rH$Bb2C�t�A�w1��=[;w+���X�*`�$qo$�D��8..G�����^?*��6VTC\#��3��L�0���������ld�If�p"q�%����D�Z)��X�X
y�*��`��&������X��Q��4�(�4�`����Y�qN�'�����+9�PN��������MW]06�[����V��=���E��m}�_���$��e�������8�P�8B�P�\.��v9eQE�B����L��O7��v�����+$�h�y�di����������$M��P�~�P+����6�5J����&0�~�W+�G�����'��� �]��.eu��A>+�.XL� ��������O�8��t�/��i���?&Cb��`����5�1k���rq=`p�����*w�fV��x"�r��+$S=���j+�R\�<��HcN�-�M�����(]��;O�G�W%�YV���~?����Co�4�j����
5����]7����C���	��0�D2�m��E���"dd����i�FK�$�2(���*"4�7FP�qD�%�q��h@EO�4D���,B���e	��=w�=]h��XWY�Y��{�Y�[�`�YgYY��E��)�-fE��,s��H��D�70PL�lS�y&�����:y�|XV���er\>�9Y&�����_�/��Y��l�8&�����)��-��`N�8���N4_l#9:g��l��msyi@��^^__/}������]��7a��V�
J:[��Y���^[��Y+��|[��Yk�9wLb�����������e�Z���g�iwa�PT�M1�Z�G&y�MR�4����2��[6.i�Fol@)����yK�����h�{b�u�j���6��H	�
�K��������f�
�B����8q�M��]?�M*�h���Ov�O�fj��Z�c$2��K7iF"j$2���^�iF"j$�Y���H����H��Sa	���	�!�U#�5#�4�r#�����AvgY�|D>b�8t4n:d:�!K<�N�[%)'3]	��B�������ylU��<�
E]y�<�#�7,_�%��_8��9Lqa;�	,����aV��[Zx����V��4�AZsi��4��y��4!���^	K�4������WD�P�4G�>G���&r��A`�1�1��!(?�-U�B���}DA�A]/�6t���_(�$��Hn^��5��31�DK���,1�E�v��L�qp���?���54P��2qU��P�/����1�3`��b�%aC'��NHH���v�CK=����iW����5���=o���G�^������q����i{c��q����x�2���w6��[�!'����$)>����~*}�;.��)2������Q������p*,�-~�?�E��)A���r��u'|_1�!�aaI��Ua��]��f{�.��=[������{�?h�a�9T�bsm&�����a[����Y�u������xi (�&(h((�'(���z�G�f?oR�Z��&��K�=IokepHxd�4#��03�z��\�hT��Qu���T<V��f�I�����4��yu�)ZLw>�(a���T���+?�~�j�/��o�r�}���Tr}�\���=�z��y�����\��"l����0��N��9������^�-�8_�g�T[&+S-�2���{�<�G��kk�P���/�0����3�3����Y����K#L#l;.�&�&�.w�B������oP��������	�07M����������N]�E�^Ol�(��kwfm(�E��+�df`V�q����U��#�VTcm�0���rhZA���p���+�p�A��������� N�!���`� 6���^qr�������������L���M�M_����!�p�p���K�2��w�}�p�����]�7���{,x���~�tl��eK�l]�l�����j��q��7�L�|������k��`�5M���*����M�s��s���\���X��#'�$P��3cV|U��=�=m@h@Z��b�����i���������=�7��?���y�$�p<��	5(���}�������&��q��>��U0�eW� ��A"��b$������m�m�M���'�[^�%�D���'m�_��5���mD���H�y�W�Ku'����\9y{[���:v��1V���NX�$ ��0Lh&��	?#�"��TUlA�8x@�O��H���a�r��)�D��#j��Rm�q�I.�>��}�>�����#�X�e��5e��iW~t��;:z�j��O����i��+�
[�����S�^�����a���������Z�"a��>L*�1Uf9r��K.O�����c�Z�N������b��f-\ea�����x�Y��������k�$������`������SWY������?��;����s'�������+�\���	��jm�m��(/�<r����/9�g�s.�g���g���D��U��4��c�J}!m���$�����aa�[MZ"��%-�k$r�D���2tM*�P���������sGeO�^`��zs������(9��h8�i`��C�4>�s����c-c�cmc�cc��,���l��������������v]r���������r��.������������i��)��
����,4,�l#�c$r������	��Q���
��&��c,y���d{��(y��#��#6R�9Q��Xdf�������? ���/���*K2����S'��V�L��T�����c3.������p�=�g�>�����HN�h�EY47����J�y��!����:"��%���8���s�����S\�]�b0���.6��E��m��X�I���?�)�n�(��JLa���[��bYEe�K�����E%������LXA�qm��v���%�%Fc�*����r�����

�,��z�����J��E_w�G��j���{kf:�B���N�3�8DK$f�����{�N&t��8B�}J0i�h��3���9&�|��U}��d;�i`-4�1S2���r��Av��aigKc�V���� �f�����@�a*%/^��b	:������K��yyY����l>#	������������������������~��x�s�.������QS�]�vn��9{���+��x��������p��]s�3|�����Y{�3$[sS��"�b1�q�d�h2�E6�I��b$lD�9�eV����Xa�N� �Zn�L��V�!�9�Rc6M�9X�l�c�3�<�����,?��u�=��f�L����Y��\��*�4�^O��f&kf�ZL)�u���]|�Y���Z��Q��=mGNT����JRj��R����U�B�y�I=]�
gq]���*/����7o����(�\�V=o�#����|y�m+��>J�������a7��(9��2����/�������Z|A����<8P4�/A��6�_�y�m4�b�����(�|��+��s	��K�����\�4e��b��QZ���D�G����h]4������b)�A��H��������V�j(Rk�"�}�6�������]�U8B��#g9`to�O�'�R������/;"3Ge��t;�b�(��(�#
�O���h1�*�R?}*��,� �+v��T���%�Q��v����~N�C��f)���j�z[���
�c9�8�.������+�rF����.Zh�.Vr�k.6��O�nfWdnU�����-D������*	��n/sgG*RTC#c����Zp�v�1�Q��_s[��`ET�Y��Z�������b�Er���>�u��v�}op�����u�]���/����6�W��.��w��� ns�(�V�;�f�
m�*�>Ihn���$E����)��$K��n�h's�����;��C�)n����`���y`�X%���d�<��w8$��*I\A��p�m��y�;opd���
I[K��T�*�Ii�����t������`��wO�HcMc4|L=��8�Y
�?����r��c�f��{�u'j���n�2��e.u�bdv�����j�O!�]��
;��=��������U��?�T���
k2����j���[���R)c�(��t��������M|�h���y[��t'���w�7}�Y��w�Yz����P�TCR8�i��
RR�OG����|��"t��3�D�X�
W�Z
m[(B��������%1f��n�.�G�^����^w��t�u��'�D����"a�
�����NW>L�H�(��ro�IIgW>^��L����z�����^�(pvqtq�������~�jo��:0�;�75p�r�����kK�+<+�+}����=i^}������s���F�*=� �����&�{�ovK�H��5��[Q�lW���z�^H������1�v�=�<�

7��._�z����8}w:Oo�U��8I��Wy�^>�����
��v7��>i6z$f+wtrqHC)w`���t��W�������k���R+&���G"�W���a��HA�T�A�$Y���O��v�	B�;��5|`]x���������/�A���<�����V���V����*<��
�L�vP�A�g~ �+�n�/+���J��_N�B�9�+��<�&{��?Hd���7]�#���QeM��Rs���3����\��*>���7��N�\�R�-�e{a;�V�~S���_�p/+����������,�����v��Z�V�
[������Q��|�e�u�z9��_�����<�u�[��-��	����v�������o�L\�C
����
+��SZ|����-6[�~����eQ�S��6�	����jr&\6�������<��4�A��=���v�s1p%]�]�\�]&�N��G�y`���M���LH�a�����yY$��qK���c������8�U�Z�T���qT�� Z@)���/�H_��#.��v,�B�m�,4��{q�"M��H�W#H��b�M��G_�H��Z�i�Z���CB;������8|Oi9Sr������4+P�7��4D�m|a�5���wI���/�����'���������g�8w���4���������������M��U�8����D��|^�`�����~�V����Y��E��`����K��@�7g���Q0�-�1�7[@�2 )?s��F���x���#!*�Q�lbb8���Nj���E��\c��L��T#�w��e��X��G�O�I�f`~��-t�:��^e#�������l
��1��c�]'=m5��
������o��t���>�o��w@,�>�b�1��0��X�^�����#�c�	�_F���z����Wa�\����(�C����B�g	�����"��/����o���c�)�1l	���^�:�����Z��V�/��"��#���~�!_���Q�Hy4O"��ka0��s��VS1H`n�Q~�I'�>�V�����3�$�@%"}���/F��w~!��F`�1.��
Z�X�}}k��
���^�}�&�������,B\N����i�i����
�{��%`yH��h��P{|W�N������s��a�eD��`@��|��A(�DG�Q�#�������B��_I�+�����
��8�86A��7�����z�]�O��L��E�$~!���l6�M<E4c���������h�9F�����i�������L�p/	�1^�t|�,���i^���� O�qe�o�$xc	 G��������x
l�w�W.E�������t'\*��R;�h��e�=X��
Z�@)���?�*��`>�����w>��y�9�-���!f2=���������I�l���bB�g�i���m��(3�N}e:�J���E<a��uB���� !�,	v�e:k0�U8��)'��)	]�=�>���X>��1��n�[�C�w�"X��Rs&�{Q�a_�m��@��xV::��Z����:&���Tc��
Gt�D|�t4i2B�����(�K5zM��L���c�j�g+:���>���u,t�w�Oq��O��d�H�s$g�����W��H�$������u�1~��>�a\��R)�o�	�>���M=��`��S�	����:ut�I���]�������R����
B�|�zt��U�M�p�Q����y��=]�s�V�wD�e��X�Ks"� Lz�t�t�3����&�=��m)x�����p���2��S��"xD�J��(k�@-�}����r%8-������	�
��s��']P��hR�\�/3��`�C�[/�$����1�=�"D�4�N%
{�kXk	!�7/��h���������H��
}}\���e�r�9 �L���4~�|��i���6-�9�.������e�?�F�'Q�A9L��=�BN@e:��e��PNb��b������wo��1]n�}�S�*�e�F ~1'��,v�1����K_�zi,G:�a��a	t@�&�1�Y����c�Q�j1��T���y)�{��H����Ty�H��w=�A�������q�����+)/��P����G����P*����0F�����
y��6#��6y�5�3��t�������`��i��RL��z���>�S�~�A�k1V����W
�5��R����X��i��g�'�������� �[C��yZ�4��O#��w��4�aO�v���m�~-�r9[��(���bL�����MZm�rx����[i_@�=��X�q?�5�YKP??W��������P� ���.B��8�]��.���]��e!��W�_*��Ll�*oJC~�����[c�5�O���l���z`�7�~�8N����c���w!�F��7�h\�����bo�*]�4��|����4�	�����ih�[����^�����0�%:h����<�\�����W�<��>{��y����(�V���~�W�@���X��y��?�2AuE{'�O �%�z��!���CB�y�B�*����c�K����%�7�?��W`<�F��g[�m�2C��\�V�������' ���x����� �"T��>�!UhGB��b�q����t1�q�C#0����nj�pb��e�1~��������4����t�2�e����}�������	�&�����i��/��S`���c�������=o����c�k�_���U0n��!���^�#?�����?���wc�Y.�q�������{�;6��7��{
c�+n�3hk��{�O���k����=��z6��<2��6���h�e�~������c�_���L�+��d�b�^�Lb<#i�/���������5������� ��7����7�@��1JC��.7���(w��x?�30���i�l����
�����Ou��@����
�Tn��������?�o����.��RO���
=o�z����.Bk��'v�o����O�����8��.1������i��g�mF+��OA{y���Ck>n�7=�s��%P�:��h��2��Rwa�
��PbyJ0�
�z��������6�o�1#�Uy��;ZG�o�sk�%�\��8gB���C1���1�Xk�Cb��p����������@��3.���g1���e�_���N�������
���3>�T�r��3@���A?��W������+|zM�6;�9�M�Cc����
���/I5�����w�/B}h%����gB�e��~����[�!�
_2��H_)A~��~�O��<z#�d��j$�_����f������~�Ug�k�/�K-��,�M�J�MX���vxHI�����^%��3�?�eF�}��7��	������i�����u�w���1��A�Q��W�N���3����������u~k?�X&���>�'�8�o�%�R�>���b�����K��a�`�"����{��kq�W���b��������nZ��NY;��)���"����(���7������� �^���4(�-��n��uS��v�k�f�pD�k��HgG`����#a��������N������[?��+a��i�9���o](�@��#��|��v=s��vn���7�o�#>�H��>R��y�5'�^����r��h��AY��k7��
7I�@��
.�<PK`}So��1FK�����w0�S�+�c�L�8W���pJ�U��Y.a"�odY�9a�����XV��wl��[��>A�����{B-o�>��X�IE�kls��B��������F������S��zy�5�������=f�T����K�����������������������K���X��+��X>��8P>�>�i�M��������0F�k��i�_�&������C��7�����:P��h�� p_�vM�`����0�I��(B�����M�i}�}6m��7>���[������D�${wa��X��r��:m�Mw�����}�hWw)	q!��a<���iH�	��#�/��>.Jg��A����uF.���j��PW���X�.2��Y�j������B��P�UB��D;�a�Iv�p�DQ�VS-�&@�d�8��.��DLGa�|����]|>�[�C����In��!����R�	���|Xf����u���8�`7����F����#�W�^_�M�����[9�c=�P_��qPa��{[eXM���r?\fn��!.��eh���yfSW����{3���q��"�q:��@���v��{k�qo�T�sR+�3X�9=2����-���Ph���U��aX����P�NM�s�I��w��'�d�lZ���]9��<lFL�q�?m���a/z����h��w�y�"XIw%Z�5��lS�>�f���=��l�~=naoh>�=h� A�x�'�:��$��� -���y70K?���0�4������|�}f6�n�h�h��|\�^:�_� ^:_��yX�7�3?Q��M,k\��OC,@L�����B-����~�l�V��0Egp����#
boi��w���$>svO���7���F<Lw�~���u|7�S�<�y!���m����[��v?�-�!�����Dkd���[�_���,�b�j|f�g�{1�K�8��^�o�-����S)=��w}w��-j�?s�@��������Z�bM@��X���s~���+h��u#���E��?5	�|�����_�r�CXb���o�y����:���Ab��F�w�F��~�~]o�a�a�����a��
p��l��X!]��@+�`�V��R)�1��<����~���1����?]���u����_{K�w�����)?;n\��� ��l���9���Wu�M@^��]%i"��Dq_���O��6����~�FQ��3�5>��?�����<Q�?s�6O���f{��p�wl'��/�:���dc$[P��w�_�Ig�|���~:��I����A_�Z�Q��(���lZ����Y�+:�i�_j�~R��7�S-�{�L����"��m�c�hh�\+?3.C�J���8q�4)��C�����
�k|���7I����Vt�f�~_�|b����2Tz����W�wrh������D{c_(�K�Q��1q���;=���Dv��;
���aXwX�/�����/�8�Q0���I�>��N�g#fb:��Q�xqt���N~��I����poo��t��@��~{;��M\����m4(P�^}�J=�}X��NIB�B
�i�/�v���;���xf����c:}m����C���e������JyxpM��r\�7���Q8[�5����`�����Y�j::��>x��0T�N���*(T��{���A��n�'w���0|���������0b�4����#�>����d�=�Yd����k��5������"����'i�ch�"���=�B�1���8�C5�l����lh��RLw���t[�����}m�+�U��t_K��X����_�;�,jq�t/����-������~�n�o���I�?<Si}w���r�f����o��!������nec��w �D��� C*%����v�dG���{�����D�O���+S^)|�K���eSO�7�:�������o��R),�"��]����7���-��$kI�
�Aw�q�����dJ�iM�C@�H�%{�{�X�y�.Sz�������Ar�^2���,	�}
$�P�j�*C�j����� �!�1p����~Z���>�SB7���I!��i��(���M<H�[��n[>�*~���.��<���i}��u�O������m�w�������J?|N6�;����u�5���Y�}����{z�o��V�x���i?G���z���8q�37uB'�O"H��6�������8G^��hu�;IB�?�b�� �������c�~��O�B���8�����������!�����Z�?����>��>�Z.���K�W�E0��������)��H��%���)�u���:8�3�A~5
~�lh�:��p�=�xm�#���H�!�8�"@��������A;\����W�9���j
��]OT�G�(9�s$�M��mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC���6��
mhC�/���|��0���
��������&�;a�T�5?;���#��nK"#�S*�2��K6H9[��w�R�V,�8�3��2��2�\�p!bbb7� B����3k����!�o���R�Fp�n)�"R	b#� �!�@�E(���D,D�FO�Rh�]�8���[E�u��%";A�����Uk��aZ���V��V�s�V�����bo^�"�m��==�R?2���!�{���`��:��$)y������-��$.1��Xj���8=%=l<��/��7����������1����?��B~���*�Z�n���������C�!��P��B�C�E�F|�0�0T��D-"�t���1T�{�Y�a���b�]�.��-]+Jv�D�XO���D(MOx�%
��[~h���+����
�A���%�s�A
o��k��n�'b�zt�oA��H�����8b(b<bB����z!V!�!�He��8�:�m��H"�",��������3�#���/Cg|?���_��D�I��`����|������s�6*�*�����_�����zx�n�����*��8�����[jc^|�s�����R���#HN�%�{!�)��~.�0X_�����>�Y
�o�S���S�_�S�_~�(����)
�����CF`
��fGnA����,�����Y�g�j���A�W�/� ���RT�3�:�hW[���i�b�8�:M�u��)q�����j�$T���)^���h��! KT=����J'��*�R������Q�������S�������C{���iN�����J���?����gg���X�!�I��-]z�0�Y�Ph�	tp*(�5��]���:@S@�@����6])^{�M�
B���/��G����8�q\�q|&|���(
�2��<���]�=Y�}n����E���x��W�&�Au\FuR�!,�(WPvP�P(�Hw���D��%�r�S�=�f1�=�\����X�?�q���xv���f4�������
���1)M::!�mJ��O[�~�J��A���F�x#���Z�YTs��Zj[}�"�&\u0HR�D=@�>OT��~�J�P�����-TK�������=S��P]	�����/��5�g����~RW�z]-S.�����h�wzwj�2W�'����*e�1�`�i���"������`�
-��j�u������!^���*�&b"��i�3�m�(��o�}�9.krT��O*�JX9�W�)���4)�B��n��i�O6���_��4�zX���m	)�"��{9`I�T,��@�y��5�p����R"��"�t�
�+7&Y���<�A�
p�F+�>s�L]hp�J'k�P�$m+7;�~m��m�H��l$�>�6�N��b�/_�>5r�e���"�6j�>^iDm�}9������,�7�1Wvq30O
�������e�#�+����a��������$�G��+��A�\2\p��t���n����#���"��D&�L%������a#QUDb�@�4Q��i�\~������*2�9�zL��}��2��=�9�����P*���D��2�>��at^��6w�,���_X��j���r�-$�z5S:�]��L"_%��t�Z2��Z��W����D�P���\�G����y����4w��\i�+�s��c"k|�XUH��P����r��\g��u�?�7�,wn���]�b��x"�ZQ�����Q���w�@s�wE�3��-����hnK��QYr�H��a��8x����'�+
����y5�T�X�����f�UYF��$6�oki)���x�C���6�m�����/�ZlkK��u0cP!�`1kZ�G��^ki����R�����0�����o�)~��RY�k�\T|���.���|����`@���
=
endstream
endobj
57
0
obj
<<
/Type
/Font
/Subtype
/CIDFontType2
/BaseFont
/MUFUZY+ArialMT
/CIDSystemInfo
<<
/Registry
(Adobe)
/Ordering
(UCS)
/Supplement
0
>>
/FontDescriptor
59
0
R
/CIDToGIDMap
/Identity
/DW
556
/W
[
0
[
750
]
1
7
0
8
[
889
]
9
15
0
16
[
333
277
0
]
19
28
556
29
67
0
68
[
556
0
500
556
556
277
0
556
222
0
0
222
833
]
81
83
556
84
[
0
333
500
277
556
0
0
]
91
93
500
]
>>
endobj
59
0
obj
<<
/Type
/FontDescriptor
/FontName
/MUFUZY+ArialMT
/Flags
4
/FontBBox
[
-664
-324
2000
1005
]
/Ascent
728
/Descent
-210
/ItalicAngle
0
/CapHeight
716
/StemV
80
/FontFile2
60
0
R
>>
endobj
61
0
obj
318
endobj
62
0
obj
14395
endobj
63
0
obj
311
endobj
64
0
obj
21099
endobj
1
0
obj
<<
/Type
/Pages
/Kids
[
5
0
R
12
0
R
17
0
R
23
0
R
28
0
R
33
0
R
38
0
R
43
0
R
48
0
R
]
/Count
9
>>
endobj
xref
0 65
0000000002 65535 f 
0000489945 00000 n 
0000000000 00000 f 
0000000016 00000 n 
0000000142 00000 n 
0000000273 00000 n 
0000000438 00000 n 
0000450511 00000 n 
0000044012 00000 n 
0000044033 00000 n 
0000451924 00000 n 
0000452075 00000 n 
0000044052 00000 n 
0000044221 00000 n 
0000450667 00000 n 
0000090434 00000 n 
0000090456 00000 n 
0000090476 00000 n 
0000090645 00000 n 
0000450848 00000 n 
0000145387 00000 n 
0000145409 00000 n 
0000450810 00000 n 
0000145429 00000 n 
0000145598 00000 n 
0000451006 00000 n 
0000199222 00000 n 
0000199244 00000 n 
0000199264 00000 n 
0000199433 00000 n 
0000451164 00000 n 
0000249543 00000 n 
0000249565 00000 n 
0000249585 00000 n 
0000249754 00000 n 
0000451322 00000 n 
0000304531 00000 n 
0000304553 00000 n 
0000304573 00000 n 
0000304742 00000 n 
0000451465 00000 n 
0000356168 00000 n 
0000356190 00000 n 
0000356210 00000 n 
0000356379 00000 n 
0000451608 00000 n 
0000406558 00000 n 
0000406580 00000 n 
0000406600 00000 n 
0000406769 00000 n 
0000451766 00000 n 
0000450469 00000 n 
0000450491 00000 n 
0000467084 00000 n 
0000452219 00000 n 
0000467513 00000 n 
0000452613 00000 n 
0000489283 00000 n 
0000467721 00000 n 
0000489664 00000 n 
0000468108 00000 n 
0000489861 00000 n 
0000489881 00000 n 
0000489903 00000 n 
0000489923 00000 n 
trailer
<<
/Size
65
/Root
3
0
R
/Info
4
0
R
>>
startxref
490060
%%EOF
#14Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#13)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

- Melanie

#15Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#14)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/28/24 21:06, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

That's the number of distinct values matched by the query, which should
be an approximation of the number of matching rows. The number of
distinct values in the data set differs by data set, but for 1M rows
it's roughly like this:

uniform: 10k
linear: 10k
cyclic: 100

So for example matches=128 means ~1% of rows for uniform/linear, and
100% for cyclic data sets.

As for the possible cause, I think it's clear most of the difference
comes from the last patch that actually switches bitmap heap scan to the
streaming read API. That's mostly expected/understandable, although we
probably need to look into the regressions or cases with e_i_c=0.

To analyze the 0001-0012 patches, maybe it'd be helpful to run tests for
individual patches. I can try doing that tomorrow. It'll have to be a
limited set of tests, to reduce the time, but might tell us whether it's
due to a single patch or multiple patches.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#16Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#15)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Feb 28, 2024 at 6:17 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 21:06, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

That's the number of distinct values matched by the query, which should
be an approximation of the number of matching rows. The number of
distinct values in the data set differs by data set, but for 1M rows
it's roughly like this:

uniform: 10k
linear: 10k
cyclic: 100

So for example matches=128 means ~1% of rows for uniform/linear, and
100% for cyclic data sets.

Ah, thank you for the explanation. I also looked at your script after
having sent this email and saw that it is clear in your script what
"matches" is.

As for the possible cause, I think it's clear most of the difference
comes from the last patch that actually switches bitmap heap scan to the
streaming read API. That's mostly expected/understandable, although we
probably need to look into the regressions or cases with e_i_c=0.

Right, I'm mostly surprised about the regressions for patches 0001-0012.

Re eic 0: Thomas Munro and I chatted off-list, and you bring up a
great point about eic 0. In old bitmapheapscan code eic 0 basically
disabled prefetching but with the streaming read API, it will still
issue fadvises when eic is 0. That is an easy one line fix. Thomas
prefers to fix it by always avoiding an fadvise for the last buffer in
a range before issuing a read (since we are about to read it anyway,
best not fadvise it too). This will fix eic 0 and also cut one system
call from each invocation of the streaming read machinery.

To analyze the 0001-0012 patches, maybe it'd be helpful to run tests for
individual patches. I can try doing that tomorrow. It'll have to be a
limited set of tests, to reduce the time, but might tell us whether it's
due to a single patch or multiple patches.

Yes, tomorrow I planned to start trying to repro some of the "red"
cases myself. Any one of the commits could cause a slight regression
but a 3.5x regression is quite surprising, so I might focus on trying
to repro that locally and then narrow down which patch causes it.

For the non-cached regressions, perhaps the commit to use the correct
recheck flag (0004) when prefetching could be the culprit. And for the
cached regressions, my money is on the commit which changes the whole
control flow of BitmapHeapNext() and the next_block() and next_tuple()
functions (0010).

- Melanie

#17Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#16)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/29/24 00:40, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 6:17 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 21:06, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

That's the number of distinct values matched by the query, which should
be an approximation of the number of matching rows. The number of
distinct values in the data set differs by data set, but for 1M rows
it's roughly like this:

uniform: 10k
linear: 10k
cyclic: 100

So for example matches=128 means ~1% of rows for uniform/linear, and
100% for cyclic data sets.

Ah, thank you for the explanation. I also looked at your script after
having sent this email and saw that it is clear in your script what
"matches" is.

As for the possible cause, I think it's clear most of the difference
comes from the last patch that actually switches bitmap heap scan to the
streaming read API. That's mostly expected/understandable, although we
probably need to look into the regressions or cases with e_i_c=0.

Right, I'm mostly surprised about the regressions for patches 0001-0012.

Re eic 0: Thomas Munro and I chatted off-list, and you bring up a
great point about eic 0. In old bitmapheapscan code eic 0 basically
disabled prefetching but with the streaming read API, it will still
issue fadvises when eic is 0. That is an easy one line fix. Thomas
prefers to fix it by always avoiding an fadvise for the last buffer in
a range before issuing a read (since we are about to read it anyway,
best not fadvise it too). This will fix eic 0 and also cut one system
call from each invocation of the streaming read machinery.

To analyze the 0001-0012 patches, maybe it'd be helpful to run tests for
individual patches. I can try doing that tomorrow. It'll have to be a
limited set of tests, to reduce the time, but might tell us whether it's
due to a single patch or multiple patches.

Yes, tomorrow I planned to start trying to repro some of the "red"
cases myself. Any one of the commits could cause a slight regression
but a 3.5x regression is quite surprising, so I might focus on trying
to repro that locally and then narrow down which patch causes it.

For the non-cached regressions, perhaps the commit to use the correct
recheck flag (0004) when prefetching could be the culprit. And for the
cached regressions, my money is on the commit which changes the whole
control flow of BitmapHeapNext() and the next_block() and next_tuple()
functions (0010).

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

This suggests only patches 0010 and 0014 affect performance, the rest is
just noise. I'll see if I can do more runs and get data from the other
machine (seems it's more significant on old SATA SSDs).

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

patch-comparison.pdfapplication/pdf; name=patch-comparison.pdfDownload
#18Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#17)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 29, 2024 at 7:54 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 00:40, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 6:17 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 21:06, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

That's the number of distinct values matched by the query, which should
be an approximation of the number of matching rows. The number of
distinct values in the data set differs by data set, but for 1M rows
it's roughly like this:

uniform: 10k
linear: 10k
cyclic: 100

So for example matches=128 means ~1% of rows for uniform/linear, and
100% for cyclic data sets.

Ah, thank you for the explanation. I also looked at your script after
having sent this email and saw that it is clear in your script what
"matches" is.

As for the possible cause, I think it's clear most of the difference
comes from the last patch that actually switches bitmap heap scan to the
streaming read API. That's mostly expected/understandable, although we
probably need to look into the regressions or cases with e_i_c=0.

Right, I'm mostly surprised about the regressions for patches 0001-0012.

Re eic 0: Thomas Munro and I chatted off-list, and you bring up a
great point about eic 0. In old bitmapheapscan code eic 0 basically
disabled prefetching but with the streaming read API, it will still
issue fadvises when eic is 0. That is an easy one line fix. Thomas
prefers to fix it by always avoiding an fadvise for the last buffer in
a range before issuing a read (since we are about to read it anyway,
best not fadvise it too). This will fix eic 0 and also cut one system
call from each invocation of the streaming read machinery.

To analyze the 0001-0012 patches, maybe it'd be helpful to run tests for
individual patches. I can try doing that tomorrow. It'll have to be a
limited set of tests, to reduce the time, but might tell us whether it's
due to a single patch or multiple patches.

Yes, tomorrow I planned to start trying to repro some of the "red"
cases myself. Any one of the commits could cause a slight regression
but a 3.5x regression is quite surprising, so I might focus on trying
to repro that locally and then narrow down which patch causes it.

For the non-cached regressions, perhaps the commit to use the correct
recheck flag (0004) when prefetching could be the culprit. And for the
cached regressions, my money is on the commit which changes the whole
control flow of BitmapHeapNext() and the next_block() and next_tuple()
functions (0010).

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

Just confirming: the results are for uncached?

- Melanie

#19Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#18)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/29/24 22:19, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 7:54 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 00:40, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 6:17 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 21:06, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

That's the number of distinct values matched by the query, which should
be an approximation of the number of matching rows. The number of
distinct values in the data set differs by data set, but for 1M rows
it's roughly like this:

uniform: 10k
linear: 10k
cyclic: 100

So for example matches=128 means ~1% of rows for uniform/linear, and
100% for cyclic data sets.

Ah, thank you for the explanation. I also looked at your script after
having sent this email and saw that it is clear in your script what
"matches" is.

As for the possible cause, I think it's clear most of the difference
comes from the last patch that actually switches bitmap heap scan to the
streaming read API. That's mostly expected/understandable, although we
probably need to look into the regressions or cases with e_i_c=0.

Right, I'm mostly surprised about the regressions for patches 0001-0012.

Re eic 0: Thomas Munro and I chatted off-list, and you bring up a
great point about eic 0. In old bitmapheapscan code eic 0 basically
disabled prefetching but with the streaming read API, it will still
issue fadvises when eic is 0. That is an easy one line fix. Thomas
prefers to fix it by always avoiding an fadvise for the last buffer in
a range before issuing a read (since we are about to read it anyway,
best not fadvise it too). This will fix eic 0 and also cut one system
call from each invocation of the streaming read machinery.

To analyze the 0001-0012 patches, maybe it'd be helpful to run tests for
individual patches. I can try doing that tomorrow. It'll have to be a
limited set of tests, to reduce the time, but might tell us whether it's
due to a single patch or multiple patches.

Yes, tomorrow I planned to start trying to repro some of the "red"
cases myself. Any one of the commits could cause a slight regression
but a 3.5x regression is quite surprising, so I might focus on trying
to repro that locally and then narrow down which patch causes it.

For the non-cached regressions, perhaps the commit to use the correct
recheck flag (0004) when prefetching could be the culprit. And for the
cached regressions, my money is on the commit which changes the whole
control flow of BitmapHeapNext() and the next_block() and next_tuple()
functions (0010).

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

Just confirming: the results are for uncached?

Yes, cyclic data set, uncached case. I picked this because it seemed
like one of the most affected cases. Do you want me to test some other
cases too?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#20Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Tomas Vondra (#19)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/29/24 23:44, Tomas Vondra wrote:

...

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

Just confirming: the results are for uncached?

Yes, cyclic data set, uncached case. I picked this because it seemed
like one of the most affected cases. Do you want me to test some other
cases too?

BTW I decided to look at the data from a slightly different angle and
compare the behavior with increasing effective_io_concurrency. Attached
are charts for three "uncached" cases:

* uniform, work_mem=4MB, workers_per_gather=0
* linear-fuzz, work_mem=4MB, workers_per_gather=0
* uniform, work_mem=4MB, workers_per_gather=4

Each page has charts for master and patched build (with all patches). I
think there's a pretty obvious difference in how increasing e_i_c
affects the two builds:

1) On master there's clear difference between eic=0 and eic=1 cases, but
on the patched build there's literally no difference - for example the
"uniform" distribution is clearly not great for prefetching, but eic=0
regresses to eic=1 poor behavior).

Note: This is where the the "red bands" in the charts come from.

2) For some reason, the prefetching with eic>1 perform much better with
the patches, except for with very low selectivity values (close to 0%).
Not sure why this is happening - either the overhead is much lower
(which would matter on these "adversarial" data distribution, but how
could that be when fadvise is not free), or it ends up not doing any
prefetching (but then what about (1)?).

3) I'm not sure about the linear-fuzz case, the only explanation I have
we're able to skip almost all of the prefetches (and read-ahead likely
works pretty well here).

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

prefetch-charts.pdfapplication/pdf; name=prefetch-charts.pdfDownload
%PDF-1.4
%����
1 0 obj
<</Title (Untitled document)
/Producer (Skia/PDF m123 Google Docs Renderer)>>
endobj
3 0 obj
<</ca 1
/BM /Normal>>
endobj
5 0 obj
<</N 3
/Filter /FlateDecode
/Length 240>> stream
x�c``<�,�y%EA�N
�Q
����p��o� j/��Q�p��'�@,S�h$�-�a+��I�	�]^RPd{��E!A�@v�����NBb'����6�9��w3����C�2 C���,�200O@�%�d`���� q!�����h���1DX$%��X��)-����r�H�\����&�y2��@�����
�d�cHf����[=�
endstream
endobj
4 0 obj
<</Type /XObject
/Subtype /Image
/Width 1722
/Height 948
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 57428>> stream
x���	�U�?�0�����G���3�E�Qf��2��#��"..���	�5l!,IXCXLKBX$�U�@�	k���e}���Iku���_��~���s<���[U���{��kU�
`�hjj��
��t����9�������N��gtV�����9s���cG�9b��O<q��qO=��@�3�����%_�.�����Mu�Q�W��qI��|���E���>����?��3&M�4{��e�����;14�Z��E���=����'O5j�1��|�>���S�.X� �(�������9s��t�IyW����W��^q�y��&]��������>�|���g���FSw�:�5k�$a��ha����q/I���k�EuIFn�������y������-���7�<���:�*&-^�8�:���S?j����9^~���:?���y��&�{�.��O�|����m(uw�����+k/*�6N�4���$%�W�e����Z[[{r��74�Z5^�!��w�9�����9����T�=�����W/�i����	�O����+��_�������a��J=^���� w����#���]�%)��,_��]�h���=?��_���P���1v��Z��c��I
�]_�>V�=�W^y�P���:+�����#G�W���^��:��k���g��L}�X�H�3�<����~��B���>�����������j�����}����rJ�|������
��V=��������.���^X�~��u�,Xp���f?}�����/@����m��V���7��w]�Fv>��z'��0��u�J�A��h�-��R���i���QR�d����X�j���������p�~����`���OOQ���pZ[[/������z�%0D�c�����+Tx��y��o��U��Z����n����k��9������'�xb�Z}2Z�x��'���F��e���������t�#F��8���K�I��=��>y�&@u�s\�vm�+���jy�Z]���00���E�g��5Z����>���/WY���^*;������v�09��|���e����WKkS]v\}�������K�bF����c�b��[o�u�������#�;��{��g�����-Z4m��3�<��c�9���2w�yg�?�rwIG{��Y^x��Q��;���'�����3c����~��-=o���-��2~��d�d�d�g�q�������W����]�".\x����u�Y'�p���{���_q��=�X[[[�'p���I������{���i�����?~ak_|q�V����Y������Nr����|
������������}�=�
�7a��)�G�>�=�?�?�n����~����_���{��7�]p��kmm-Lo��d��u�K�=K$���0���]���N;�gY����
������������P,)_�����Rr������e��~�R����w��SO�����{+������������u�]������b��~{����w��O$}��e��\aV������K$]�?�������W_=��s*��J�eI�|����k�����Iw��{����**�ECC�E]�Y������b�V�*��N�4��d�������=�[+V9�Z�e�'}��{�>�Vb��	��g+.��d#��g��1�7n\g_�l��W�d�����Ew�uss���[X����jll�X����K+����V,�r���L�����8?����R����?_�Z��p����O?��*k%�������k�J�������jY���_����x��E����IW�(�����h�����F&O��.�������k���Y1`P�v(��Q*J�q���'N�Rf��QMMM�{y��gF�QK�f���k�������q�%���n���.gw����w�c*��M2%;J:�%k=�����"i��#Q�]����o����gc���%wU�l���T��^8��c��?���^|���U�*d����F=�����C=T�Lv �w��]�2<�@Z&;����*���x %� ��1cCO����������WI�T�@R��2�����&�V��N����Ov�Jg~�6�����{��tD4����g�-�Q����|����Hv��*_���z+-����b����PzRI��7�hiiI��w�qG���^8���1f������&���K��p�
�2s��-�E�����1q���^zi�����������f�������[n��>o����N8!��._����m��u�/�����{O�V�+���&�;@.����_~���)�[�m�>}z�B������X�)5j���u�,Y�Hw������tW�<�WQ�GZ���2�'O.�����/\�������~���wY����\��L���4�O�����~�|�
w�U�|���-�O_���Z?����+���D#�#FT|�1�R�������SOH�3��G��\��&%[���HJv����(�\���L��d�'�|rZ���/�n�����%���G}4�+�������s��_��=��H�Q��n"����uZ,Y��b��T���3gNI����T�0Q��k�M?M��%��~����I'�b���{�I��3&�Q�X�<�L����]��V9��g �z��8=��ci����W�~�}��w*��F��w_aSS�N���]i�b%W�����;v���@:ZR����[�+O\|��%Sp&N�0!-P�f���B�a���F=�����O��J�Q>�E�8m:�����o$��7�Hg#-�t~��T��(y��^(�E��Y^,1;��s*��j�7�U�W��4�{�-�����K�K�������O>��{G���7�h��4Ue7Rx�dA�H��/@Z������0(e;��~y�W^y%[����./�����N9���O������[��b���L���~�}mZ��=�}���@��:�1�Z�*��VyK��)S��,^����_u�U�m�F�m9I����V?�.�e�_t�E��N�Pr��������P����&�����+�����zj�
������Q��u�	����3f>�:uj���u�G�K�H��t��3��GQe����[�6���%K
}���mu��5������9����7g&�W+��wtt��5+�d���K�.����������o�2cK{{{�k���"��n�o����Y�2_�����g���O�n!��g?:��S��:{�~���:g�����v��^x!-v���v���^�U�������*�u���vY,���G��n:Z2��n��{�������O��V�V/{P����-���7�:IA��k��&�Q��/�%�Z�lY�L����O;��Z3���E��Q�Fe����}�^,}�\�3�is��h����wSr�&N��������D�j�����D��Wq��``~z���{�����M��X�G9Ye k�.���x�_���X�rey��M�k��� ��-X���[n��X��l�3��N�>���^�rGD�,�4;�P�\����������i'�g����tV,��������^���^���.�,���9:Knj��*dK�>��k���m���Ie���h�_r�%��������$;������<���t��g�����F*K'��	���f��kxO�t�M={oa��V^�?~|r�UV���^���^v��*�1��P���t�?��)y�T�2Uv��[o��3��k������hg���*o��v�wSp���_q��>�����k?��O�<���������g?��2��|������5���x	:+�]����JF�j�{�O�8����e��uV�����U���~�%���^^���Kv�����������K�L��.��<�������Y9?�Uy�[{�Xl����%���7�7F�N��}H�����I{{{�%K�<���S�N������F��V^�J�����A/�z/;�N�g�������Z�d;,�;I:+S�v*x��7
3���d�^x������:j���s�����U�bUF,;S�	�^������K/�`��G�e�����	5����e'Z��"���[�Kz��_�Z��3Y���L/���?��}������8�����!3-��G�$�^�A�8?�{*�B�g�k�a�b��{naa����%��U�W�5I-Z�(}�]���O����_��2����_|����s��_��V/��������U'���bI���7`���C��e,X�}�z�g��m�>ivZ��[X�v�-����)����[qv������S��78�rrj����Hg�kUWcM:+����~�Tf����s��-�We:��k�f����%}���t�����d�����y�6�7�s����$�,0s������-T�������+��"]8y����*�����*q�]w���O�^]��V^/�9���Q���4�������u�z+s�����c�e'�9����0�����e�����eV�N��W^9w�����(���j�K��|���o����smY^xa��U��?����*��*j�v-��&N���-�x;+V���l���f�U�;Z�~}Z�[s�t�d_��L�����d����������?o�������_^XXx_vX�w��]����e��Tn�z%�q��kVsKZ�������U�~������K�U�����j������o�����[O
��Aw�*��Ev���MK����3+�}tx�����WK���en�������>{����g'Q�����O��\v�e%7��u�]�W>{��;��S�~Kt���I_}_>kj��������aF�W��;��bU�iV��5���2����N��7/������!�����b=�Pa�QG���r�w�kU��x������-tY������Q�Hf���x�Jd�:��cj\� �W+��?������?�|���9��mxOew��yu��9��'��i�����A���M/���������=
�:Qc��+Wfo�IvW{�/������w��������x��XUy4���������w�.pg��@z�z�O�����>�������g�I�e�V���5���2������[��+~���755�}�1�d���U��b��.�����K����q����������3g�,,�����?g��Q�����}����!{o�I'�T�Zb�r��UW]�.<���*N�����/Z�e'��>k_"�w4���O�m��j����Lv���f`�����[��~��Q�������'���L��8�+��w����[�>�����e��k�������A��
�x =[����k���ep��k��6-v�m����5���2���.�0aBaS#G�\�xq���]vYI�t�������-]z�������5��J��M}��zjGG�)��R�����������Mz�z_\��V�_�fM�%��\sM���s��_��knnN��n��D'I�W
u�Q����:�����e�.G���K�z���,��,�+���1��g?�>�U~�b�^��OT�F��SO=�+y�S-'�K��aU�����L���\S������
�x =[������|[��jy�da���x��T���}U��>���1�Y�f�Q�ha:���u��������O��q�U�����/�{���8���g�������_|1;!T��*�E�jE�x�����������s��_�>1q��t��\rI��8��_|qZ`��	}^ �Zz7�,������K>mii��\
�w;$��t����d�����r�-i��S�f?�����
�G��:������K�.=����2%�����t���.*l!���x#���5;vl���7�|s�y���@z�z���6T��f�������n���2���.X�re�(h:�U�������G���B���>Q����>}z�����������R����U�V-X�`��i��	�1����+
�����)S���z���������^�������g�z�9�$_���I�1n�����?�x�W���M/�d�AK���f�J�G---��-{������2%������'�<o�������l$��������z������&��������^}���@R��|�I2�UR,��&�{��7;�f��i�������
7@&=�t��x��g��9���^x��d�I�}����{E�*�+\���l�.7������(��&''�|�g��1����ovw��*�We����N]x����T�B���#����Lb[Q���������J5��Q���I�Y�!��jE����k�m`�@������O$n�����~I�n�Fj����L���������;{�F�y�n!���<�\Q�M.7{�]g�|������$���nx��Q:(Q~;M�$}�l'�\�O_AV^��g������{.}�VgF���3��l�����2���Z�����lMn��������y��u��|�O_�q������d���|9�������=5e����������#��9>�����������^z)��{E�yx�����@d��nz_&�qt6`x��'>��#�?�w�w�la���%���8����n`���~Y�n��*��?����~%��U�F���S�
7���QwWR���tY��vZ����*\���l�7��k��}���]����W�uw�5���2���Z�X�"[��a�T��mGuT����|�O_�q�]�<yrZ`���=����9r���������
"d<����O>�����9��/Zz��W��tV�3�8��77�^-��>)���f�����N<��#F�r�)&L���{�7G-Z�(���1c���t�_|��3f�7.�P}��������)S�����l��{y���3���|��I'�Tq��d�I�l���g�uV���d����?���o��,X�������$g�g[(����s�t�9���`/���9s����tV��g��~������y��W'���c�M!9�����~���I���/|E}~��W����\u������>��.�����=?}��_�Tv�|�����9��F����7�xc�����F��Z��3�4��[��]������������Gyd����7�p-N;���/����K>�
t�<����d����r�-�����x�����T>�:��M7�4�Z��K��1"��[l���;�8r��U�V�]�|T�������M�{��?��Ol��V_�����n���a.���&O���{l��6�������O�4)YX^r���t�����%��������7s����0��\s�f�m���%K�M��w��
7�P8yWd�,_�|�]v)��_������@�r����~��nZ�+_���?Q�rH�����������g�uVy��G�l$��������O~2������|��[ZZ�����?M�l�����yWp�L�:u�-�(�o�]��s���&�{�A���lmm}����b'�|r�UP���I'��,�s�=����U�V�\�r��Y���g����r���v M�819����>9�+V$-�w���;$�:�����9s�%�9=z�+���~��W_}u��Q��z��W�x@�f�������f���}�k_K�����bi��%���o�����>6�F?���$����/�K.\�,�q�s��@������;��G��r��_=����+�
`es����&�Y�j�y��%w�y�t���,����JV?~|�|��v���VxQ���^[���+�L�{����j���?�sa���'�j��[m�Ur��GJ�'K��9�j uy�/���d��G�K�bZ�~}rN��f�t��>��d����[R���!Y���[l��]1��������vz�����I_����+Y���O'��O���Y{��Kv����K���:|�c5j��5k��ha���������_���U��_�br�/��b����_N����gb5�>;�������%��q���|p�p����:�����
�����l����;79'{��W�%�z����v�m�W��A/������>��/_��dy���O��}q��D-��P-����
�-|��7����z���[+�����=��"�vy���?�#Y����{���v�m��f�������o��N�'�h����{��Wn��v[m���?�e�i��%g������`��w���f�l&�'
��r�>8��"�f
�����I�>��O�3���?��������R�����W�m�MN�:���h�l�c�����v!�h����[8���<��#]�oll�~���o���?��]����h���o���;::J����'��O���1Z��h�s�=�������<��W_}�o����-,�����[��W�JNWSSSCC�5�\Si�3gN����0��{���{���O�p����3�nmm�o��>��O�2���-�f�m��SSS��������'���1Z��h�s�=����S������e�����.Y�d����u�n��^{��>?�u1Z���[&G�YZ�K/��l>�~f�0u�m�}���L��{��X �.r�!���g^z����)�������.��+J�/[�,Y��;��!Vc�0��������^w�u%��L�20��������M���[%��x��dy�i����x���������NZZZ~���l����']�w�p�=�L��,(Y�����9����haa�|��0��������!VS��_��W+��,I�o��V}��jB��\�29���.Y�l���}�{�Gg�}v���|G����g��Q�|�����#F��!Vc�0����s����%�W�X�,O>��C��.F�<��d����K����k��]v��Ov]M����m�]r��������N�{�����~��6;��s{~�@~f���t������,/L~Z>�8�
�ha���k��`|������L��s�\j���W����N|��%��;���Q�������Q�J��?>Y~���K�����������m��6�u����k��v���������K����;��d�'?����W�]��6�Fc����g����7�x#����/����
��U��vP�x�������o$��9����'gi��eS�L�f�m��j�_|1������o�����^s�5+V�hkk{��w'M����}l�-�Ho�L��?��?}��x��'��0�K_|��e6�l�k��&���`H�&�8����_�^������������.%�������S��o����o�y��o����{�>���_�T�����[n�o����_�e�-���g>s�A���yW*Cpdc��9p�v�m�\����������+��*W�����3�������['g��|��G�z9J69���M�$;���o~����>[��L�����o�DI���g�����m���o��w����7o^���XE�Y����^[�h��I�6�h�����'�_��z�.P�G1l��3�<�J�U�V}��N���?X�`Asss��}��'Y��&�$�G������}�s��
{��G�����+�2{��Gva[[�;��,������XojtWSS�����l��&���U���g?6l����K�O�0!Y~����G�����y��
6����������O�o��o����;��������v�q����O>Y����?�,O>��b�f]���c�6����U2i��o<}����f�m�,\�ti�����n��#�H��7�U|�;�6l��>��)S�444�������&L��?�����~��������.)V>���u�
C��Q����TQ�U����/Y>j��d��\�������?;::J����'��O��XE�Y7�1�����z���
���[���?���~���b�;�>���G��z�nV��JrS���k�f�������e���khhH�o����Q��������$b�M�I6!2	�����go��e�]�?�z���b���O����N�Q��������$b�M�I6!2	�����
��+��,���������^���CI����+K�]~���������Q��������$b�M�I6!2	�n�}�6l��Q�J�����M��7����3�?w�u��b_����cw}[��������$b�M�I6!2	�n�����
��������z�����o����q�>��l���k��-[�f�&�l�����.\���������~����pccc��7��i�!2	��db�M�LB�4z��ae>���<��s�bc��)/��FM�4�����T��u������$b�M�I6!2	���w���{l��&o���>�����7K�,)/v�����������|`�M7�k������~-Vq���]�E�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&��B�
�I(�$��lBd
P/����BL�	1�&D&�immZ[���J�
�I(�$��lBd�P���S+~sH���yWj����$b�M�I6!2	e([;e��]w\��o�.z9��@�����BL�	1�&D&�e+��d���5������]��"�P�I6!&���$��������Y-��������W�]'�F�
�I(�$��lBd�������P�_��x�)�=!,-6D&��lBL�	�I(C���~W>Z��o����������BL�	1�&D&�Y+~{Xq�p�����~�W��W�� ��bCd
1�&�$���24u477���tx�����ov��a�/5?t�����bCd
1�&�$���24�<�X�N�o%K:W���=�����]{u�5�"-6D&��lBL�	�I(C��+.}��&mm��=�l��S7���ZY�3-6D&��lBL�	�I(C��#M���yK��u��v���{��'G��rE^U��"�P�I6!&���$�!�����k���/y��@�c5�����{����{B�����BL�	1�&D&�A�O<R���+�i{��e?���'�����$b�M�I6!2	eZ3iB���cO��XGc��#^:��uS�������$b�M�I6!2	eZ�����Mw�V����=]:�����-6D&��lBL�	�I(CM��uK�����6,�r�u7N/���g�=a�i�!2	��db�M�LBj�}������}��yO�^{�_�
%����BL�	1�&D&�5k~7��L�9�k_���E�=yd^�UJh�!2	��db�M�LBjV����Kg���u;W���ae��L���B	-6D&��lBL�	�I(CJ���K�����v��}��no���q������=��'-6D&��lBL�	�I(CJ��_<x�w{��u7\S:���;�}��>�*��bCd
1�&�$���2�����t|o�yg�fS���[���yO~��������P�"�P�I6!&���$�!e�/(�����z��
��|���}�O�
�����BL�	1�&D&�kV�m����`��=�~Z�������BL�	1�&D&���M�����}���������=�,��]�{����BL�	1�&D&��/>����������~����l���"�P�I6!&���$��c�a?*��p��>�~����{��}�{B�bCd
1�&�$���2Dt46���m�~���m��e?��yO�'Zl�LB!&���d"�P����+������oG��V�����d��������#C�"�P�I6!&���$�!b�E��/-�h\�����q�i����;��'��"�P�I6!&���$�!b���_Z�����u�M-�����u4��]3Xi�!2	��db�M�LB
�W�\�[��������G�5����yO^_40{g��bCd
1�&�$���24�������~4��n{���yO��r��
d4����BL�	1�&D&��/8����	����4��?+�����\
-6D&��lBL�	�I(C����;�k~pn5hmmsj��'��6�	�����$b�M�I6!2	e�k_�|�n;�y��+;w�Y�WM�]7�t��#n�j����$b�M�I6!2	e�k����Kq@��i~��J����o��Zl�LB!&���d"�P���������������'?��t����{B�����BL�	1�&D&�z��n���?�wu��}��Gj��K�
�I(�$��lBd����li�����c���k����g��{���3�{BZl�LB!&���d"�P��{�,N)�����N�u3J�=Yy�/:��Ai�!2	��db�M�LB��]|i�e�]�
���t���5�	i�!2	��db�M�LB���n����f�����{o��fo�q�����o��y�]����;�,;�;��>t&��E�,��^���d�/7?�p��"-6D&��lBL�	�Ih��Z�j�M7�8Z8i���6�h��%K&N���*����L��%�!�����~]�5����=��CJ�=�iF��"-6D&��lBL�	�Ih�v�a��[v��U�>��'��,X����9��>���,�d�M�?��XE�Yw�i����K����������O)����3�{BJ�
�I(�$��lBdZ������6�?�����^q���=��#����m�vH��|���Q����;�4�=����I�]����~U��'�7�	Zl�LB!&���d"��577o�����
�2eJ�h��~��d����K��0aB������b�f��g���)����G��N�����������8�z�?-6D&��lBL�	�Ih�F�9l���}�k���Gw�q�d��O>Y����?�,O>��b�f�A�}�;�IC�������k�
��^^��o��{R?��-6D&��lBL�	�Ih-,X���������E�6T-�l���%K�.-Y��w�M��#��b�f�Af���_Zx��yW���W._���yOf^�w���"�P�I6!&���$�K�����
6n�����������K���!�n��d��o��*���Y���E#~����4������?����]2���'��G��0��8�44]t�E��
��g?����i�G����*Y���Q�n{{{�<��?�U��u���J������t���k��]��{a�����Sv����~���9y��jA��|��}�C��=��ta�h�?��d����KV/���l�?�U��u����*��o��w��lY_��[:����i���y�������$b�M�I6!2	�n���6l�QG�]X>Z�������e��������,�|����XE�Yw0Y����������*�{�k���]/�"�P�I6!&���$��a])�e�]�?��S%���??Y��N;�G��z��`�x��tTm����]�������'��]/�"�P�I6!&���$��G9����W^ye���_~y���?�y��7�&K��3Rky�����wZ[�<�d�������=��1����BL�	1�&D&�=P�$��3�%���kI�/}�K����-VQo�4��|������sCkK�5�ck��r�n;gW�����y��~����$b�M�I6!2	�����5k�l��&��������---�����'K>��766�G��z���������h���:��y���yO�k��AO�
�I(�$��lBd�����1c��?���FM�4�����&����O(����A{�����l��yO���`����$b�M�I6!2	���ct����~��w�����|��n��^{�u��w�k�^�d�Z���_Z���yW��i��_��}�1��.�o6�������$b�M�I6!2	e�i{cq�^�o|aCkk�5�_-��	��{2�i�!2	��db�M�LBd���!3������Y;��
���Y�w��cZl�LB!&���d"�P�U�W|i���yWg�4?p_�7�{2�i�!2	��db�M�LBd�~w��K<�wuT�+���,��n�=L����BL�	1�&D&�&m�_Z��7���]����|��_\:�����}C�
�I(�$��lBd�`�n�u���?yW'��=?��'��"�P�I6!&���$��d�)#�/-�~e�����i���=�U��5y��^�bCd
1�&�$���2xtt,�w�tp������P����t�������y����bCd
1�&�$���2h�.z����o��o�/��t�=K�=yR���"�P�I6!&���$�Ac����O�wD����O����'���o~�c����EOh�!2	��db�M�LB4V�<*[7cJ��	�O���>1;`����yW���bCd
1�&�$���2Htt,��+����0�
��x�������C��=����$b�M�I6!2	eph}�����{yC���j���Kv���gi���?�������$b�M�I6!2	epXw��t�p�	G�]��Vqhz��L�(���mZl�LB!&���d"�P�U'Y|i�����NP�o�Y�����������$b�M�I6!2	e0�ho�������b�
�c���o~1=Q��>�w��-6D&��lBL�	�I(�@��������
y�(���N.>�=����C�h�!2	��db�M�LB���RyT��	���'���������y��n�bCd
1�&�$���2�<��_Zx����[G��}�x�f^�w��-6D&��lBL�	�I(u����[�U|i�����Ptk��������wu�-6D&��lBL�	�I(������/-�ww/-�R��o/�m������j�5�VZl�LB!&���d"�P����W_Zx����SV����������C�����BL�	1�&D&������O�-|��]���t���2���
mmy���h�!2	��db�M�LB�omm
{~��P��EyW�>t455�����5���w���"�P�I6!&���$��������#G��]|�{����CM����BL�	1�&D&�����&��N;.�����@����{���y���i�!2	��db�M�LB�k+��U:��~�
yW��,�����|�nj���kZl�LB!&���d"�P�Xkk�7�P|i����P��N'������]�bCd
1�&�$���R�Z�}�����=�����eK��������0��-6D&��lBL�	�I(�k����/-<����S�VwDzW_pv���Zl�LB!&���d"�P�����_Zx�MyW�.5��]�?���mhm��FT����$b�M�I6!2	�^��4|�?�/-|���+T�Z[�����46�wW��-6D&��lBL�	�I(u���������3��������gr����wu�F�
�I(�$��lBdJ�Z{�e�W�#��Nk}���L.��s�K��]#:����$b�M�I6!2	�N���a���~s���o����d��vE���SZl�LB!&���d"�P�QGss��/�������Q}[w�5��\v�w����bCd
1�&�$���R�Z�|�8������N�k_���k��������FT����$b�M�I6!2	���|I���g��wu�U']<��N��:T����$b�M�I6!2	��8���K��%��������o�WGSS�5�-6D&��lBL�	�I(u���)��l��w���������{�`�pk��-6D&��lBL�	�I(u���G�/-���������������_�]*�bCd
1�&�$���Rw�L��������]���m����.�m��w�4�"�P�I6!&���$�����?M����=��*+~yPzn�^yY����"�P�I6!&���$����~����R|i��%y�hPY?���S�?�{CGG�5�}����BL�	1�&D&����G*g�o��l:��n���g��I�C,Zl�LB!&���d"�P����.,�����yWgZu�	�3|������h�!2	��db�M�LB�/��5�sg����8=�
��B���y��"-6D&��lBL�	�I(u�c��%��/�����li�5�:�����t�p��7�]!�����BL�	1�&D&�����(������]�Ak����y�o��:i�!2	��db�M�LB�#k.=?�Z}��yWg�j{��Kv�)�������]#�L�
�I(�$��lBdJY���/-�����3��8�g��^3������i�!2	��db�M�LB�kV/������\�w���w�JG���76t��]#�D�
�I(�$��lBdJ�h~pn:~������:�\��u
{~1=���>�w��-6D&��lBL�	�I(�b���_Zx��yWg�k<�����:������h�!2	��db�M�LB���Q���sg�]�������	o�����y�-6�&��lBL�	�I(u���1�����W���FC@G������iF�B�
�I(�$��lBdJ]hz���K�?��k��T<�?�q��A�
�I(�$��lBdJ]X}���K/�wu���%�o��u��E/�]��N�
�I(�$��lBdJ]X~����>po��BV���8��s���P����$b�M�I6!2	%��U+����;�����6R��;�����������k4�i�!2	��db�M�LB��i������Q��Z:�����;��bCd
1�&�$������.>{��yWg�Y}���_u��yWgH�bCd
1�&�$�������;�j~pn��rZ�.=�K��K���y�h��bCd
1�&�$���\���Kv���CU��c���k4-?���������]��K�
�I(�$��lBdJpM��U|i�/��:C��k�.^����wu�.-6D&��lBL�	�I(��>��t�j����]�!�}��%�.��/,��FC�"�P�I6!&���$������K~ ��]+O�mq������:C�"�P�I6!&���$����--�����t�]�w���������
{�����w��"-6D&��lBL�	�I(�5��#�Z����������t�����t����P����$b�M�I6!2	%��sF_Z���yWg�[}���r�����3i�!2	��db�M�LB�l��_Z��CyWg�k}���r,����
K��������$b�M�I6!2	%���%�����{��uy��
��QzQ�N�<��9Zl�LB!&���d"�P�j����K�����������|�������h��W��������;t�{Uh�nQ&AQq@EA�QQ���(� �0��0�a&���*��T��S�bpW���J
����Y{�V�����o�����Q�;'U�)����]N���
HFB��& �$#��=jx�����.�,��~wc������������2�M@&�	HFB!�����n�����zc�z_����.�va�$#��Ld��l��P�d��UK�~wc��PwE8��q]��i��*����a�$#��Ld��l��P��[�0|��z�.��������	�S��E���H( �d"��d$2��#|��)_�.?S0��p/���t�S�0c��P@&�	�D6�H(drvm^Jc��,��c�f
��A�gO����`�$#��Ld��l��Pd�=�3^������"�������|���d$��l2�M@2
�|K�s��p��s�{���6hY�+����H( �d"��d$���:Q����]"�<��_-�m���jfl@2
�D6��& 	�@��
��vn�]"s���z����]N���
HFB��& �$#���8}2|����tW����m.�NY���|���d$��l2�M@2
i|���T��}t���YV���}��]P���
HFB��& �$#�������M����T�`���h�{Bw9536 	d"��Ld���BG�������]*b�=mk�������q����j8fl@2
�D6��& 	�(����[��{G0�]. ����[V0����p���d$��l2�M@2
Q|f�oZ��Y����|������u�4uWT�1c��P@&�	�D6�H(Dq
�i�������Y�>{�&�]�o\��������2�M@&�	HFB!����������T�{���]s�1@w9536 	d"��Ld���B�xV���m����P)E�w�������j,fl@2
�D6��& 	��y3�7-|���rg���{����������2�M@&�	HFB!������N�]���v�z�rz?�������2�M@&�	HFB!�e9�k�:N�{u�(�v��y���w����j&fl@2
�D6��& 	�����{���3h��+Bt�<����OG�.�fb�$#��Ld��l��P����i��u�������AG��@@wE536 	d"��Ld���B��W��d��Fw9��U���o�������+�����H( �d"��d$"X��C��]���]�"����'�~Iw9536 	d"��Ld���B��������+hq��j)p`�zm-�9N��4���d$��l2�M@2
	|f�.���~��A��<�%|E���u�S�0c��P@&�	�D6�H($(?F��
�|��T�w�7���y���rjfl@2
�D6��& 	� �0��{�-���[��+����[�����=W�X��}������S'�g�.]��_���"���Z��xU��|��.Ug���Z6
��r���(���d$��l2�M@2Z1�������_���;
K�9q���.���n�-&LH�n��X]r����KE;��.1q
�������]N���
HFB��& �$#�����SRR���?s�L���r����{�M7�6<X��^�^����]������������ch�5�\�2�E�c5rtl��K����r��u������u�36 	d"��Ld���V�/�KJJJ��xW�\���?�Qm�2eJhK�V�J�f��7��>��D�Q,������K�� r�8�k����KuTs0c��P@&�	�D6�Hhx������u��-�z�
m�<yr�=�����O�D�Q,��%p���,9�_w9���q��{���Y������d$��l2�M@2Z��/OIIi����r�����������[�n
m�m"v�(���R�fe��4�9�� Y��{jk���������2�M@&�	HFB�r���q��]w�u�]v��5k��������8�2��;w.�����O�n��X]�3�	/����� >rz?��V�7u�SC0c��P@&�	�D6�Hh�5i��d}�k��f���������
m��"%�,��S'�E�cu��~������r��3��?�Qw9536 	d"��Ld���V^�F�n��������$���T�W_|qh�eYeb�fh{�o�[D�<��-It�Ow�V�;y|2_��m��s-�wv���tW*��$��3gN�z�RRR�,YR��n���/}>_�=K�������[D�<��d~���Q=����$���P�^��������]��Jv��|����:���B_:��2�������n�)�E�c��,{��UO��w�.q���^���6wX>����=fl@2
�D6��& 	��������������F������,�����C�4h���"���Z�[����.�� �L���=���-]���j����2�M@&�	HFB+v�u����������'N�,wR�e�=B_N�:��n�&M
m���w"v�(��jQ�{��&��~Dw9���/���7���t�S�1c��P@&�	�D6�Hh�:u�������2�G����m��/g����i��ev+YFY����[D�<V��T7�5l��rg����f
����gN���zc�$#��Ld��l����m�����/����&N��t:
�8s���1c����K.�d���%�\s�5)))=���}����Bv��9��^�zn�;�E�c��L�������_�sO������.�zc�$#��Ld��l���;v��_��su��)s����#S~���.�8qb�v+�^��J>V�{�T+�;o��r�Es�[�|�m�2uWT�1c��P@&�	�D6�Hhe�]��m�����o.����n��[�n�w���n�f�j�����^���ol��]ZZZBw��-��KH��B/�J�o����������G�]��IwE�36 	d"��Ld���B/G�6��d�:��$���!��S�=Xw9�36 	d"��Ld���B�@��Y����h�RwAH��[T����v� _wE�36 	d"��Ld���B#��	�Dr<x��r�0����N����uT]1c��P@&�	�D6�H(4�o��:H�/��]������t�]Nu��
HFB��& �$#���;o�� ����$��}&|�y�[�Y�+�����H( �d"��d$|��jy���]+��������������H( �d"��d$��
��n�B�� �|?,
���S��i����a�$#��Ld��l��Ph����>*��Cw9H,��go{�z��kuWT�0c��P@&�	�D6�H(4��o�zG����$�{�[�w
��������2�M@&�	HFB����V�#{������"$\����7����+OwE�36 	d"��Ld���B�����q���Iw9H�c���������j����2�M@&�	HFB�K���k��Z_�� I<����=������f���H( �d"��d$�xR�R]�����]��t�l���>p�����fl@2
�D6��& 	�.��_�:��� y�^�n���������2�M@&�	HFB�K�����Q�����A��/Wo��c�`�HwE�36 	d"��Ld���B�c������r�<V����Y�^�
�U���d$��l2�M@2
=,�����Y��!����^�f����6���H( �d"��d$Z�v[�Z��t��d��[���N����fl@2
�D6��& 	�E;��fQ���t�
rz>��O�T��T���d$��l2�M@2
-|��N���Wu�
�3�U����t�S=0c��P@&�	�D6�H(��L�Bu�
���]40�rl-oS�A��]�+����H( �d"��d$Z����D��u�=\C^V�A����.�`�$#��Ld��l��Ph����j��d�.z���V����]����"����H( �d"��d$Z8�G���S't�M�qKu$�-�]�t���d$��l2�M@2������f
����7�+�6����y�<������H( �d"��d$�g�8^������N��#�`�5kh�;��"����H( �d"��d$����N5�r_|Jw9�,��c�x�|=Aw9�1c��P@&�	�D6�H(��;w����Sw9��;of�\�G:-KwEr1c��P@&�	�D6�H(�����8�V�����:$�2���H.fl@2
�D6��& 	E����^w�b��@?�����M�������H( �d"��d$�������d{v�.��7g�C�~�����"����H( �d"��d$�gow�j
�N��r �e:�W�%�u$36 	d"��Ld���"�,�+|Y���.RL�4�R�=u�#36 	d"��Ld���"����P��u�)�S'l��?6�50N��]�D���d$��l2�M@2�$+\�\u��������:6
&��]�D���d$��l2�M@2�$�|7Uu�������[<O�.m����"q���H( �d"��d$I���;�#�����r ������C�-�+����2�M@&�	HFB�dy��U���u����,�������� �����
HFB��& �$#�H2��U;(p���r KQ��RKf�n��uW$36 	d"��Ld���"�,���6����A�r>�!|���Y������2�M@&�	HFB�L�-;��E����D���TI�3�u�#36 	d"��Ld���"�J_gJ#�����5T��q����a�$#��Ld��l��P$�o�����.B���G'���A���H( �d"��d$�T0��p������P�iK�W�w�;h�+�����2�M@&�	HFB�L�w^W] ��9���PVa�����P�oX��")���H( �d"��d$��������M���\����/Z���r�`�$#��Ld��l��P$������+���]�*��K*����y��+����2�M@&�	HFB�4Va��Y�����ft���{'�0��������H( �d"��d$Ic�R�g�v���t����&��C������2�M@&�	HFB�4����������r ����Z�M3�C�uW�36 	d"��Ld���"i�sRU��=�M������:f���������H( �d"��d$I�?n���x����T����1���<(�]�f���d$��l2�M@2��q
yYu~
���.�A����y��Y�\wA�1c��P@&�	�D6�H(�&��C��S�w��rP=�2R6y���]�f���d$��l2�M@2����i��>fn��rP=P�����L�]wE:1c��P@&�	�D6�H(��t������;t���$�g��/��������H( �d"��d$���G5|r����T'�������X'�����
HFB��& �$#�H����w����rP��y����q�� 36 	d"��Ld���"9<�&�nO��Q��A5��_?���]�6���d$��l2�M@2��p����xg��T3�
k���l{�UX��"=���H( �d"��d$����3���_�Zw9�n����:�
�/�]����d$��l2�M@2��p>�A�zY�u��������������r�`�$#��Ld��l��P$�i�Z6:��i���yu���8�����f
��3�+�����2�M@&�	HFB�F���q��Rw9��r���$����������2�M@&�	HFB�E;��&O�3�u����7�:���Z��������2�M@&�	HFB���sU���� �����
���oW�R��Z7w1c��P@&�	�D6�H(��`�8��)����rP�����%�����I6fl@2
�D6��& 	E������]�1����X������]QR1c��P@&�	�D6�H(� ����W�n�xC,���M����v5����H( �d"��d$I��t�j�g��.�[������<�Cw9I��
HFB��& �$#�H4��gk��|{�e��i����q�d��j��8uBwE���
HFB��& �$#�H�@�u&�����AM��B���9j��9���d$��l2�M@2�D�oX�;y/��]j�����r<xO��-'�2c��P@&�	�D6�H(�;�;��q�zKw9�	,����u\�7o�]Q�0c��P@&�	�D6�H(-��TW�3m��rPC��CW��u��$���d$��l2�M@2�Ds
���:�+��.5D�������jl���+Jfl@2
�D6��& 	E��<�Euu�v�.5�e9��-����Jfl@2
�D6��& 	E���
�_����]j������t7��$36 	d"��Ld���"�������m��]j��mk�0|�j�a�%36 	d"��Ld���"����
������rP���F`��}����c�$#��Ld��l��P$T�����k_����4�0��-������b�$#��Ld��l��P$���I�S�>���4��oow�:���V��(����H( �d"��d$	�5<�j��T��������s�*36 	d"��Ld���"���=>�+c��rP��V���e#37GwE	��
HFB��& �$#�H(���U'�8vTw9��r��>�u�7��I fl@2
�D6��& 	E������q�5�
u�����U-Yz����2�M@&�	HFB�8�����j;��]j,������8�OwE���
HFB��& �$#�H��m�U'��'t���,o����������Da�$#��Ld��l��P$�o�����~�u���&+\�Rl��M�"�������2�M@&�	HFB�8>U
��I��.5Z ���Bo���u����d$��l2�M@2��q�5Huo|���.5\����-���u�����d$��l2�M@2���}����en�]j�����x�5oh�m�+�?fl@2
�D6��& 	E�8�_j�;���|9O=�9������?fl@2
�D6��& 	E�X^��Y������-SwE���sRU��������?fl@2
�D6��& 	E��
�m����
�+�~w�����3uWg���d$��l2�M@2���[^r��3��Am�zc�:�����.'����H( �d"��d$	���m�i3������g�U��M�����xb�$#��Ld��l��P$H�'#��M|7Uw9�5L��@ku���-�]P<1c��P@&�	�D6�H($o���cS��\w9�E
��Q�^n�����'fl@2
�D6��& 	E��<������]j�DVx=�f
��gtW7���d$��l2�M@2�����-��.���v�}�����S��]N�0c��P@&�	�D6�H(��q�W�h{��rP���QG��k��e��(>���H( �d"��d$�2�/_��]����w�\r���^��i����_��b�������_�N�:�?�t��~��D�Q,����=;U�&�g�d�4by
�������5d�c�$#��Ld��l���<xpJ$��w�J��4q���.���>�-&L(�l��-�X/�iKT��5����.���y]��w��.'>���H( �d"��d$�b?��CJJ�%�\����8p���<x����-�����+���r��W/��k��{������?;v��r�5���L�n���8�|=Q5j�?�09/
����)|9|��[���36 	d"��Ld���V�m��)))���^��#F�m��_�Z���)SB_�j���>�a�|�������O�n���8r���j�x����~���]������{��36 	d"��Ld���V����mJJ��3g�l?w�\h���_^�e�^�B_N�<��n���m���O"v�(���Q�KO�.�����(PF����q�������fl@2
�D6��& 	���'O���\w�u%_�z���/w��Qf��[�����6�E�c���9]�����(P�q���Y���b�����+�36 	d"��Ld���V��	RRR:w�\�e���C_:�2����x���'b��byl���
j�4��u�D��r_��Z��X�������2�M@&�	HFB���r��_�W������K�\u�U)))�\C�������S'�E�c��8}R�g�['�����-���h��+�	36 	d"��Ld���F����E����o��]�6^|��)))�e���4�����&b��byl���n�,��IxE�<��kosG���&36 	d"��Ld���F%�w�}7�x��}�Jo�[�nJJ���+��}W_}u"v�(����%���V������������: �����r�*�A���~���/���_�!r�
7���8��2��v{h�M7����"�����r8~s�j�zwX��R�jv��N����m_�ZwEHW�Rmf���6m���������o5j�����2��o����A�D�Q,��������o��$�"P1g���1��~��r�����2�M@&�	HFB+c�����������|���;���#%%e���e�O�4)��w����-�J*��n�3S��-	�T���$uL��~Dw9U��
HFB��& �$#��`���/���+��3gNy���1#%%�i��e�7i��t�.���RIB9:6W��v.	�T,t��7T�e��!�U36 	d"��Ld���Vl�������~��_gddT�[AA�5�\�����C������(�g���C[����v��[,�$���������A�L�+��7�9ud�:Zw9U��
HFB��& �$#����CJ���#G����^t�E'N,�����L
Q=6A������}IxE�2
W.SG����@@wEU��
HFB��& �$#��[�n%��!�f�j�����^{����x�����KKK��s�q������D"�MW=���%�E���~{������+�
fl@2
�D6��& 	E|yg~����wu���4B����t�S���d$��l2�M@2�����j�xR���
PI�{��ik�����]Q����H( �d"��d$���Z������t�3PI9O<��O��ot�5fl@2
�D6��& 	E|9@uc��.������9O<����1c��P@&�	�D6�H(�����oW�+��� �g��[�F����=�+�36 	d"��Ld���"�L�]�a����]�kp��B<��]Nt���H( �d"��d$qT�;3|��S��.��pmz�������(
���d$��l2�M@2�8���H�a\��.�$p��"���e��36 	d"��Ld���"�<_}��0��� ��q������Y��D����2�M@&�	HFBG����&�w�L����R��yC�vNwE���
HFB��& �$#����z�&���������:V=�L�]Ne1c��P@&�	�D6�H(�������'��.(�����Xu>�Qw9���
HFB��& �$#���@��y���f
�����,j����j��E�����R���H( �d"��d$�b�:�z/���]p�7^UG�{�����fl@2
�D6��& 	E����z/��>�������#������]��1c��P@&�	�D6�H(��0��{q
yYw9�����sku���-�]��1c��P@&�	�D6�H(��;�;�x��h��r�+�rl�����]��1c��P@&�	�D6�H(��`�'����z��r�3N�5k���<
�3�tWt���d$��l2�M@2�xq���s�\���������-����r.����2�M@&�	HFB/y��Q]�Z����[��:n��
Z���*��
HFB��& �$#����]T�%pp��r�J�<�{�nto�����0c��P@&�	�D6�H(�����j��N��r��r�;$�����u�Sfl@2
�D6��& 	E|�f
��\�7������*��Eu���n����\���d$��l2�M@2��0m�T����n����,g�v�5z��]P����H( �d"��d$q��G5[rz=�� :�)_�8���u�S.fl@2
�D6��& 	E\���R���W��]������Mo5Nd��(2fl@2
�D6��& 	E\��V���o�.�Zn���.?Fw9�1c��P@&�	�D6�H(�����?�]5�����|����z���H( �d"��d$q�����x���.��U���i�c�Z�E��
HFB��& �$#����~��R�:Mw9@U�G��c���������2�M@&�	HFB9}Sm�������"t����~wc���������H( �d"��d$q�x���z�gO�.�"�c�K������2�M@&�	HFB�eky���X�����3m�:�s�zDw9e1c��P@&�	�D6�H(bg�����lw��r��36[���x>����a�$#��Ld��l��P�.p����8�w�]��W�W�s���.�g���H( �d"��d$��o�P������]�����xvtltW��
HFB��& �$#���o�B�]q�5Hw9@L�"��}SuH�Y���0fl@2
�D6��& 	E�<�������C������:������0fl@2
�D6��& 	E����R�O�W��b8�O��3�����
HFB��f|X�w,�#������=�:3%����o$|`�y<�������4#7�Ah��r��k�\���8A5��N�?��A�=NOH�!�LKl$�G:���/�h��OO����k��6�/�]9=���3c��P����~�[���g�F�o9=)�����{�mu������5��������@�4+��_�`0����O���9���.�����d����S�U��m�]����W�~����G/����M�
��uQ6��9A����4��=ig���}��xKtM���h�5��`0F�����'[���hG�W1��]f^��e#u`���]Q1z���d\�v��=\��h�g|2V�E���e���(V���e0��`T~�[s?�{"F�6w����v�.�������|���r�E�ZEV��6�R
��o&�:��M�=v��I��rg�P��UlWj�L�`0�#��d�<���d����P2>l$�3���}��a_��������G*��AFb���=-���f�;�=��L���m-���Z����:���j8�W�-DL,�GuT���.���U�c��]����������m�d�o|����X�����j�9�`0��3V��������W�=���u�������n������*����JF~f��ZE�?�Q�������sjey]���H(ba�:��[������0������$��nV�>�6�<62�����q`����d0�$�hV[�e�*�s*���K���qnFt�����k"\�AG�l��P��h�v�N�}�q������������L_��i�e/�x���������������`$�_��+�/0���*\G��� 4*�stE��e�jf�
�Q6��8��;�Ld���"F��?�v�k�+���)�uD��f
M[v\���������}��-���!����?���T����d�B�����d�c'������I�B�R�����6�3 �d"��d$1���^	�����,��n��|=1���,�f��W���������V��rc��v�{������0+{���4<	��T����& �$#��Q��OJ�R&�.�3����;s>�1hY�\���c�y�#sck����1�4�������W>1�r,	��3c��P@&�	�D6�H(b�1T�R|���.�3����j����m���p[��V�4�� cgg#�+��zcp���g=�yxp�9C�������d$��l2�M@2���F5R�ku���k�@G�����7W�?NkdlkX���N\]�x���}�Y�E��h%+a�$#��Ld��l��P�(�G�-��� fF���ne��G���o��r�`]#����N�����_Y���@^�Kc�$#��Ld��l��P�������N��r�(������c���[��)�����r����y|�e_`y��Xfl@2
�D6��& 	EL[������MSwA@�L����:7�<����������zUo�]nl�/#�>����d��1�I�w��
HFB��& �$#���i�V'::��������<��y�Ec{c���t����|S~��;��?����������7��
HFB��& �$#��E`��-�����rP[�~+�un��5�������@�ob�
^j��wcG{������V��`�#�"�}{���`�8-�(36 	d"��Ld���"�u�T�$�����A���Y�k�S_��;���oL'
���������y�=�6�*���"��o�����]�pn!�2H( �d"��d$������'����]j+`��l����7�<nl�-�~],�Ac��;��_2O}n����EQ��c�����o�H��]fl@2
�D6��& 	E,<S�(um����A5W���6��'�_1vt06�G �N'
^kljh�~��z�:7���4c,�=b�:�]o
��7fl@2
�D6��& 	E,���Q����u����2����}�y|�����������t���?��5�`�g9�������(s�:���o�
��*`�$#��Ld��l��P�"o�K�yR�:Mw9�*�c�6�g������+�vy��36�j��jn��a�gMo���r>�^�������?a�$#��Ld��l��P�"��c�sR�;Sw9���������6�4	����V!Y�c{k�������sY������������}�{�_����2�M@&�	HFB������q���r�t���b���<<����������zcp�UF��;4���S-���Q��;,��>ck�0|�;��Wg�$#��Ld��l��PT�e�Z���&Va�KH@8��e9�'>6�?clmX}SL'
�����"�T�'=��;�������������d�436 	d"��Ld�������������]����������#�;42�7���N������������Z�-��K�wXu���#���U�0������d$��l2�M@2�*=�z&���t����K�����3��
��?��4x���Ns����-�B�{X��gVa�������oX���f�$#��Ld��l��PT�sFx�����]*��X�V�t���������V������+�
12�7�j��b�6����dp��:�]C�'�u���H( �d"��d$U�[� �0yk��rP!�yl�����N\u���������X����@0h����(��K�����yI��2c��P@&�	�D6�H(��3m�j�����r�eX�F����+�<i�2c���C������`�S�7#��{'u�{gMK��2c��P@&�	�D6�H(�,��p�d������X����A�5��I����{�0���ls��}A+y+wTS�����?�g���(36 	d"��Ld�����\o���%���.?2}��o���+�
������y��y�+wm�o�]t�d:��S���e�$#��Ld��l��PTY�=U��h�f���v�{����@�u�6	3�j��(Xd�]i���Z������L�+2c��P@&�	�D6�H(���hG�*1�g�.��
��'�o-�d�����zY�����
W��8:6������d$��l2�M@2�*��{�j�Xn��rj+'���-���rO&��������]i�(rtl�uZ�_����2�M@&�	HFBQ5����$�V�u�S��1��5��[�'���<��U����!���*y��M��1c��P@&�	�D6k0�/�L��G�}��s�c���g��e�=������'����I�c��Q�V��xx��m�����t	E�N�&��k;���V���5v��]�I�v����unv�J���P��� �Z��t&���|�$#��LdH�2��-��|��e4�~j����ui�J6�*����-���`���M~z�
�2��&I�sO�.�&�<��C�V�T�����<�V����Jk���]U<�MM�kE�}���;��������b�@aB���$�#�D6k����h?l��������v���77�^�;�?����'��h�H�<m�H{���`h/,�OOTAa��C����rj"�k��jliR��+�4v=l9~�<T�;kZ�<����B�X�a����g^:&���F=���9�������O��_���i�c��*��+�������7����2B���xrBh�Y9)4b�J�M�;c�<�6������oHu6�3q?����[�S����s��`����c�������\����h���>��g���_���`�����I��`0�G�Eo�-D�������rj�����t �7��L�����O�E5�S}�b���Z���P�wW��y����a������z��O.�jn�?/��`0�����������/-����q��������������b���N���Q����{����n!��`�����_O�]N�P�4O|bd�o�'������rXq\C^Qqp�~��t�rw:,>�z����7}�{��v�n�z������`0FT�Aj��zA-g=�zV�XAC3��*=����TsO�����P�pT�{�P��-������r.7vu
�����	��i��*h2o���&�Dx�;�����s����I;���}s������������f<�f
S��������%/���3�j���`0����'�h?ltY�R����}/����;�D�k�yxi�����;��#�����k�����"�H(�&��3�=��X�������y�-c���=�p���C�Z�C��������,�h�p����-�|���l��o�����&����3�w�����1�wO_������������!���w�f����n��w&�n{�������0��]�w_|v���H�=���rh�iYF�%/�����2��E������{>���h��A>�v�l��h��h��E�VE�3%��?��N_����^ 	E��<�Eu���.�Z���s���mi�En�]n��`�����ZY�4��Oo8�c��ec2�zu��|�X���������?�:p��O2��s�����'������
HFB��& �$#��G��[h:������}����o,���u�ff���])��z�[m{�/8�]��#����WW����v]�����}�}�������r�u����W36 	d"��Ld����*[�����MSwA���$c�����x�U��nV�*���j%�,9�f��Y�7}���a�����#��x���}_X��{[��z���'3��uD[$36 	d"��Ld����
L[�:������r��\�}�+��{2�������<���".���G���u|��#�gt�KW�������m�Q���^�I{f-=�v����������2�M@&�	HFBQ�}�U�0��������n�����rO&L������������(<�w|��-��q����=�G����G���c������#{�����oW�(���o����2�M@&�	HFBQ�u�TK$������2-�Rc����*�d������M��Zk�2N��l8�c��e�d~����-���������c?xm�%�d��Q��H�b\o
R�p��o����2�M@&�	HFBQ����-��o�.G�q�����.�d�50��GuZ��^pdH��=��q��;g�_pd�����9��H�	�QU��-*�{��<���0c��P@&�	�D6�H(��`��%R0�S���c������V��:���iW��[��A��]ku��i��I{g
�4��G:�k��N������#_������Df��.mT:|����i��
HFB��& �$#����wT?���t��h`��6�XuC�W��w����?[w���,8��dF��#}W��G�v���O��7�o7io��#;���DS��t����'g�$#��Ld��l��PTA���T?�p�
��$��6O}il���+�W^m�y��]��PY|F����OoI=�h�������ui�;g=�G
����]���Vn�����u}�����f
��Y���8>936 	d"��Ld����
r��^�uw��r���]g�y"���rO&���<5>h�uW�S��#?-8����a@\y��G��D��#�3����s_���K����H( �d"��d$U�x�^�1���]N"����G����	W��<����Kw�����o�������]�?.82��y�����CK^����#�\��J�h�[2_$�`9(W36 	d"��Ld���"j�ek�H5C,�_wA	`�c���S ��r����ZY���f�iaUM��#K��-Yp�O����H�]J�u|��#�r���qZpD����{���sF������2�M@&�	HFB-3/G�A����]N�Y�,�����?�{2��?�G�}�uWg����9GW���z����~�w��,�{������H�}�^9l��q��Zr|�N�G�����*&��������d$��l2�M@2�h�Rmg�N����geO3��(�I�������X��J���G]'�������^p����%�|����GWl��9�o���2�����[��������2�M@&�	HFB-������[w9���3��V]_��%�b�0����4&G�N��9�������H�e�_�q��Y��m�q���)n�m,��hG����qyVfl@2
�D6��fm�<tf%|��<�2��@Zp��d����EC>�~�=+u	ET|K�/�|k��rbbf�(�d�����=����qN�3�I{gwY�b���Mf=R����'�,8r8��7P�����'���<�-.��g*@2*�77>�qdm���q�}a�g���`����0>m���8�!���O�g/�;^�C|�Mic���s������IF���q������WI�������t(����������'�m�}|�ET<�&�H�g�.���s�iu"�L��v����Q���p���\�����.8������77�������Tc�-����
K �H��I/����v����|(k�Y�C�������`0�QC��n!��?vT����_�.��,����_��O��F���V�>��U�'�������7�>P��#��_������7}ZK�(��g��Z�[X��F�<�T�����Q4���U�V���*�����(:N����m�A���b0��`0j�����������WU�0m��r�����V=^Q�:�U���.���f�����l<�KyM���<�j���tO����Z$��-�F��u�-,tG�����z;fU�����(�����J_T�@M���lS��k���g0��`04�!L�����O2.�4Iw��r2n����/Y�O����`={�LII��W+V�h��}��������K�.���O�n�TR5�/�T
��m�����cx��
J�UX|�q5dZ����a?i2��
.1~r������t�[Y~���]*/�u�bz�"���y{~�V�I�>��K�������'�S��O�Q�������������5���#4���w������;>����(�]��:������~������������H2��2�-M�����&��P�H�}�~���m�I:m������Y"���)�7�|s�EE�N�8���Jm�0aB�v�(��VF��^��Yqy�$����~�*<�������q`��	-���&a�%/M�;�������.��w��
�t��~e�.���gQ������?��x�����}�����������4�Se�Co�g�[@���8>ju������T��T
��2�M@2Zy_~��%�\R�|+�W.��^�z��]�v��w������c���k��&�e"v�(��V���;T���w����d��MvtZ���*�H��Ow~�v~�
�����s�Q�I���n��_r����l|����?<X���F_���O�w����.�����0$��/�����T���i�(Y�V�U�bT���w�N��l[)������
�l2�M@2Z�����uKII���+"v�L����U��
�����C�������"����ay<�Uho}{���d���?kn�9hT�5��&���e��4	[~���mv:�.��*��#N�(n_l�Q��X�vq�����S)����[q�����[L������U�+������i�\�R�R�M����8R����E�j,>S2�M@&�	HFB+����JII�������[��W�����'��>n����>}�$b��byle�N�n��k��-���5��
w��>�;����8}y�.~r��
��Mf=2l�'��w�������y����*��w��?S��������98����q%�o���}��\\���7�]�yeO�����F����f�L�D6��& 	��+����������E��z����;v�(�}�������M�n����(�������=��%���
����"�WY�M�������Z�l��
S(�I�xF��F�<��7���B������7�6N�_�O�����6���W���Kx\���W2�/���&��-����'|������s���1c��P@&�	�D6�Hhe8�U�"v����Xz����m�����[D�<�2
W.+�d�+1>[���
�U��K����k*�o�8�1`���3���$l������/�J�|��M.�'|����m��o��������W7�up���%����5Tg���t��}��\���T������_��36 	d"��Ld���F+b���R�_�!��zC�������"������5Mu�?~/�gK�0����"�G���)�������6~�d�#\q����3-�)t��7��YA���^X�*�>?^����6�O�A7�o������WG�����_��*�/�_|t]�w�o����Y������*��zC���d$��l2�M@2�����/�8������L�m�m"v�(�����������^�nrd��\�Uh[}������v�+K��k��4	��yz�c�e��]le�X�lg����&X�yV��c�<�e����9>j������n�
������������8���.TO�0�;�BE��v|b�K����(�]�Z1;���/�ucFv��Tv�N�"�� q*�AB��na��uC}�������w��W'b��byli�*Y/?�:��}����
��P�U�J��m[��-i��%���j9���8����K?�����2��L����o,����w�R������	��u�n�~������������[%����P=��3T�st�P����yj�������.�,�6�m�X���#C�����=��@T*�AB��n�
7���t:�l�����7�tS"v�(��VF�+�n�?cm���P�ci �2�*4��9�?���3�I{gwY�bEM����m�N���WcY����;P|���?^<:|�'��W�(�
������q�*����*���E��_\���?�
�����T��5oh:"_�\1fl@2
�D6��& 	�V�na�F�B333�l��}{h{�
�[D�<�2r���:�C�c|���
��>�0�Z+w��p���\����4	��zd��O6e�4q�x<E����o
��
88�����\����8���`�G�u�YT��
:�%��$�rz=����6�
���
HFB��& �$#����-���Gh���S�l�4iRh{����[D�<�2��v��,���~���_�����,��d��'�������7�>P^����.��\y2�o%������Q���$4����$��+�N}$����
�eo7��,n��,>	����oY*��T�c�W����H( �d"��d$4Z��3f�ml��i��M�4)����n���l��K)����%�Yhl��g� ��89��7�V���nd�]�k6L}���w�QT���CH��@��^���WD,\�4�I� 
�t�HS�� � ��P��@B�!�@���!@z�����OX�l�f�%�=���9O����Y���/g�����Z@�����E/-V�6ZQ����
�����{���W/��-�{p��WB�����Z0�=g9�P����P@Ld�DFBe�Z���Q�F
��[�n������;wVz�W����V��re�B��b�BGB�������}nV*����_Q/��������F{�������~�v'�������$��F�P�5�qO�?<�W���xp�oy��w���/�I7�q���G�!J�e���s�DFB1�M@Ld	u��j�b��^��*U������Y=;�u���y������V��&��
u������^.,!r�����|i�H�u��%���3�5���	���<���
��J���%�N��M�5D��I9�M1��
���b"����& 2�������76m��f������]�v�6m����uXAc�K8JtH-t�������A��m,��OY�\/t%���������Q$T����jjTq�u{�9M��$�H���Q�3�@��:�Ts��o�C[s�DFB1�M@Ld	���wl6^D��O�>3R�	��������IYW��%�d�-	��u�E�f[��qjqXBd���-z�|r�<�����������A]UDL��9J���C����P@Ld�DFBa����*G���=}8&r����2�
T�����S�_��k�hE�F{�xlnHL�^���u��%��x�z�p�k�����/��st7��9�kR_}��m9c"#����& &�	����~��NU�Y��z�p�K��;����&w����Lm��k�L���SAE��~]G�q0*X��u��� ��Q���:����J ���=�(e.���
9c"#����& &�	����~���SK9�=}8wIz���f��K�\��F�{ *x��
��T$���S�����dj[��$��7��V�R$XV^�Q�q����eo��F)�{��)�����P@Ld�DFBa?�	Q�3��>�<�K#�A>�^����G��9�����6��q�q����.�N�I-�7R��a��� o+u�!����q�<pTp�����]5M�����9c"#����& &�	����~������G�y�pd���f��co��Gw�9���f[��Q$��{���������.
w)@��#���)�������R'�5�4u��[q�DFB1�M@Ld	���[���7~X�������*�����sn9��ya�m	[o�;?l�����8��Iz��&y�[���c���"��y���2��5M��'ef��gl@d$��D6��P�I�HW�7���drF\����8��+�������U�T�?���7Z-6����S�a	��q�v���G��'�d�N8������N���C����n��Le��j�F����P@Ld�DFBa'��kje#�U���2�z�`�M���Oc���[����>�Dn�(6����csCb��v/9Q��R�}������	g6�����"��t��������36 2
��lb"���H(��{��Z�8�q���2:���9���k$��T3�E��Mqt�������i�p�� �>�8��^�w�-�����	���l#_9���C1�������X5����Q�&����P@Ld�DFBa��{�j����O�P��:7�>����&�>wt;��[g,��������8T{�^�W%�`�N8����9��'�)yH5V�~/t<gl@d$��D6��P�)k�*�������j��5��<����J�'���9��?����:����~]Cb���hw=X^��<���:������r��������g����-e}!�u9c"#����& &�	����N���5�|���Z�39�N��n�'%����7�
�>/��;����O4X�Y-*?�s����g����o����?.��$g&y���^RvV|���diB�l���
���b"����& 2
;�M��4&|��P-T�������~VP�8�0�a)#��=������E-�_��@Tp1m�t�r�ry�����?� ��� 2$i?OP����(��9c"#����& &�	����N)#�UkC�W�����-��jb�G�3Y���������xwC7�TXo]�]���Z������=e�N8�M9�O���f</�l����
��T�9c"#����& &�	����Nq_vUk�����%S-<�-��g���c�rT��A�
O����O�Ra��6_�_LkEz��c�<�a�u�y��H������j�����1�36 2
��lb"���H(����Z�1�����Z8de1�u�;���Tx��C�_L��x�gj�Pik"w��ZJ�"��VR�J�p`9yi7�V���b�\���+���6Fr�DFB1�M@Ld	�]t��&�
��X��7e]�����Z��p3�X���_�`�rhKYr����i��n�iZ*\��8��R�)yI���`�:����_9��;�	}\l���������Fr�DFB1�M@Ld	�=��qj)�R�����l2hE�:�p���_�D�Y��_�X*��UY�b����cZl���T8?lM�������Z��xd-y�x9��u���H�_�X��Y
��
���b"����& 2
{h##�R���]v���Q��sZ�Z�vf��Ho^(��hT1N,|\��f��1�����5-�
]Z��gA��O����a�N8�i����&�����{��%�o*k���36 2
��lb"���H(��	>��2�u�&�z����:��,�Z'{�]�0�����R��JR���N�N�xG�R������,�f��~�|�z�p���CV���\%�����m��,�h��a����P@Ld�DFBa���[�:��O���H��?��:����:����_7�]�����S4i�w
6-�<G���96S�I������Y�������SA��>{����������
���b"����& 2
{�,[��1|����o��V�q��]�sy�I�;��l��c��:=7��=���
G�E/�
,�Q��!��*V����������+���p^MY\�����c8c"#����& &�	������g=-����a��k������N��3[9��l���Lm��F��
���;��r����W|.��R'\A^��Y�/�L��]��e���?�36 2
��lb"���H(�qu�p���If�F�:i5#3'��W��^lV*<VO���2H�N���x�Ra���4z����C����/:^]�:RN�.����*k�J5hI����	�D61�M@d$�����jc��`���z�����N�%;AJ:���X-<���s��ms���MK�_�����8w$��%�a[��o[���-��.g����OJ�k�@��62�bgl@d$��D6��P��j��jc����.:h\���o�3/�sK���Tx���j��:I7��4�R�g{Gdj�:��j���_�^'��9hQ��H���f-}�4�g9c"#����& &�	��������V0����J�"�L6�ur1��UE�}��Bo)n��J���Y���n���j2=3�������:����4��l��s��#j����H�fi����H( &�	��l"#�(�����/n}���X+���k�k�����%�R�U�k�������,M�gZ*��s`R���F������^'\�*���@��j�7U�sp�������P@Ld�DFBQ(��j���Gm25V���������:� �s�W6	zI��������LK�m����J��u��F�kz��k��H8�[^��|���{�>o�����L���
���b"����& 2�B��Tk���:F/��3�u�����K�Z��j�P�^m����^aZ*����w2������yQ{y@+u�aU��������p���%5qq���?�����P@Ld�DFBQ�H�=j�"���
[v(W�����l��B]XG�����d��{.<���T�|k��������Z���~������'����T\�������K�~����H( &�	��l"#�(���V����A��&}0���I�?�2s
)Ji'���'�m��xVDl5-~�����Q��%EN�����:���������(:Y[���K�����	�D61�M@d$�
;[-\������G������l�K�B?4N,i`���]�mZ*l���IWz;y�n�S_��NC>�N���P������
����;m���
���b"����& 2�B�v�Z�8�`�������k
)%VK�y�z$������Z*|o�'g.:�~������N8�	9b����S�O������`���
���b"����& 2�B���V-.�h{�F+�$��`�'������O�z{o����Z*|����������!���)��vx?@1�;��.�U#);K��
���b"����& 2�B�l���B���t	�R'����M�8eyy����lbaJ��}�
yk}'�T���.A����
I�w� (mV*\�Q�d:��=����-��e��!s��FB1�M@Ld	�m�9�������..���"��-����536�����X=�����m�-(:���]�R�[�;�
q�m�f�K�X��p���}��X8W�^��>2gl@l$��D6��P�v��6�I}C�"�����~Yq~��>&�#�0+;��SR�&��Bo)��,��q������
��������Cj�<��Y�pp9d�c;�Nw�z\�z�
�M���os�DFB1�M@Ld	�mA!����~���K5�70�!;o&��������v����	����I�����{�N���2+~��|��c;<$y��j3���	�D61�M@d$���|N-V\����m%Y�a����4R�
������m~!�j�M���B��]�����m��U1+N~UN���N����E
`b��'���
��T���& &�	��������bEd�~�n��+���Dr����_P����=��jj���0-�����k��&(cV*�������[<H���o����skWq���w*@Ld�DFBa��7������sbq�R�_�-�<c�������V7���|k/�R��s�xI]������&�z�����M�f��w�r���w*@Ld�DFBa����J��Y�����[���2�OI����qb���V�����������N;�"IF����fu�A����9�q��'��6ox�����p�Sb"����& 2
�V~>Y�T��[��~��������
3�U�d��?,.+���~����'9�21������
G��#��>l��$)�{k5�����`��1�M@Ld	�
������2E������������Z-\�b�O�s$�!I9�w4-N�'�����W^��T8����H��C��?��������:�Sb"����& 2
�S�C�{�e��P�?*���Ra��m��l<)c��\u@�&�������1����.�+,gV*��#g&9}��8t�w������&�t7�y��X�w*@Ld�DFBaCd�>���j�Pw���;�M��R�����=����U���r?�;��T8��4�d��$z���[�5M�|-��N- ��a}�$f,����`��1�M@Ld	�
���n4{O�QH�i��G�{�T�	x���C�Pi-�g\������T8 pb�������ffu��e�3�;N@X�{w�IL��R��=}D,��
��D6��P�p 4C-P�4m��^4�����K!��%������`�v����wRK�}���i��s�y�?�J������;y�������V��<j�Y��1�M@Ld	�
;��T����tn'���j�P{�)Y�����ZC��?���/�N-������,��{��<��R�����a�$ ��_&(�i���%�Sb"����& 2
��
S���wwf�7�*'F�W���O�xR�;s7�^�x+���/��7+�l(��:s��}"��5����SS<}D���
��D6��P��a~�Z������=��{��B���e���^�������j���_��������\�d�'�6����/��|�F2k�:O3|��D61�M@d$6����X-1������Z�
j�P���b@���j�������>z��:�����fu����=0�>uq�$5�I}zx�p��; &�	��l"#���o��4qi��
��v7N,��Y2���q���w�lo<)�����+�W�^����kr�<��f�����P?W� p	������J��K�>"F|��D61�M@d$6l�?�����m+����{'�n0}6U��t��j�����7�����lhggN�+���6-K�o���k��
���o/���N9]���s5�����(>|��D61�M@d$6l�9V�KD�mvh[����������d��O�~WK�o���$��E����4vy���f��i��)������t��@Me��Me�����Sb"����& 2
�u���%R������
�&&�4}�x���k;���E���&^���Y�K�KF���6-F��n����4��J���u���m}�`�>���p��1�M@Ld	EA�:9���jQBs>��mu��'�x��)�.���o�Ra�]��z���S�m���6d�sf��	��u�X�x���|&��f��?��kN^���\(1g������L3����Sb"����& 2��$fH�?l�%t�n����t�lba�����gV���z�:�%DZ��6%&s�[�u���������-�g�Z���D���|k�%������P���-}R���@�Sb"����& 2��\��G5}O-JH�vn�;��8��Ts��.&_k}'�Z8��"���}F����B�w�._v���L�74�O�e������.;���@8�;�WW5���Vx����; &�	��l"#�(��K�%N>hh�VR�6�������)�$}�w�Z*������,+�8��<�����_������_~8w���&�)6��1tU������L8D	����6�R���egO�<|��D61���>5E}����v9��	���Dp���N���2���\K�uj���k���%��d�������l����^=����������6-��H��n�Xx���sk"���B��}���g����
����S������?o��<��	�ggN��s��6-��QpS�S�����5P��8��C�o=���& &�l:_J�u��:�����p���f��u�y3��#M���:�����#uom����+��_OX�W��9����=�H1�����tc�NF�{�����GgXn���W��X�D� �_��z�~]p������R6�������e�r���Kq�1�N�:n����_�z���T$Q�M(��,'*QNT�r�;Zt��k�����r���2z�{&)�5���B�Fs�]5�=a�������W�
�@���^6N,<����'�����>M�N6�67K��cV'XN><��c����]�����1?��	�mffN�������Qp�0�}Gs4PMh|���F��c@E�����;S�
?��UuA���k�S��Mqx���#�����bT|�w=�{4�F���v���|��U;gmQ?'aC�:^��l2��!)�����GL�A�|e�������Y�px
��>�?:Y���v���.�Re�����c^����?m���3g���m������u���iY�D�������%th��4������B���m����t��+W�iN��r�����-u�:��r��YN_j����w�j��-�����[Gwl�4��Qm}<�k�F���v�����Z9�N����+����~��u���5w��m�7��v�sm����~w�������c.;�:���VHF-���-����5�a?�R�x�����B}x/�?U��t��j��k���l^y�:��T��rLD��^>}]�����E�O8�����Tv2lU��m9���:��'LrEq[�"i���bfQ�H��W5�)#������J���\�S�5q��])em\�J�(�w�K���?*'7W�EI�?q�M	]>���W4�� 4�KIa�u����
�G;]GZ�s��u���,s��4z�6��H��r�����R\���v�����Z�v�������k{��v�l)d�;�xl�Z*|������f[]`V*��/93�8��AB��'L;qKN��vM8t�}�sf����Vd�����-o��������MP��O�`�"\bQ��^�l���A}}\��
��j]*��r�d���"������/�\���R��������[5���P4�Fs�E5}��J�����s�����	N��~���h�i��}����3)�����b��j!���{�������m����x��S�������k;�����7�m�'���j�pL9�fq���$Y>K��pn�e�gK�����\�?�.y��5g�^��Cy�^�����N��s����R��KI�|��4}��v�y{�K����t����q�d�:~�K%�o>si�Q���M�F��h���&��(Fm�����]�:Z�Z��x'�Q���n���Ov:�D1�����M����rz��wE��X��;r��Qk�.,�����_�����;��"i���G*�~�2I�����TaU�'���?Q;l
���=PQ�J	;�u�4���SK�]v
��.p|;L����T8��|�dq��B$fH7��J^���n>����r��eZ����>����E��M�;�~�4�p�[���;��^�]����2A����Z�������h4�������iR��6�]���@�����Ii{�r�:;���g����)m��������z�w�j��?�x�wpM�f����f� a������*������:�����QdU�w
��8��3������(HH��w���a6F���3N,zY��m	��Y��
����i�&��<�MV@.+�m-���:�^VN���!Wt�����?�k������zQ���;��n7+����k�l���+�������1��,�es�/��������
=��0�F+��h���[ZD+w��Ii���t�X�������|��+�"�
�J����PWn��q�5��nN���i�r������)L?lt�`5o���!���D:PV��@Y���9R�DFBa��oF�G��_v4QQ�gi��q}��?�������Z-���b�&�Ly��f�+�]�o�M�mo'�MP�n;�U���������F�yYm��f�V���5Yz/��:����kV�[����{�Z\���Vwt���3v���=^���?x�j�V6������vm�w���u������K���9�����~k]�
r��z����s�^��Oq�-�F������X�;p����T�t���|������w�	|{���<%�@d$V�eKQM�S��23
������I���.o�^�>�;B-~�W�Lm��
$��g�R����)A��H�b����MP\��|yS���\��oI���S=���~o}-��z/.��g_]w�����,��o[�eo����g
h����?���;���]m�����[3����h�}w}�7�������W#N�R2�x�M��i4�����t����+<v���.]XW����4�U,��������@d$V���PK�w�6,x����qb��Q������R���6��mdV*\�J6��!d9K��E4���H�n���	�s�h&o������,7��B��h4A�r�w�v�c�K��1�����C��,���.���^ti��$�g�'2m^����l"#�����[j��R�&%�3N,�H��[��NF�{�����G1n��Y�p����Y��!!]�~wM�}g�����2���,�������d��h%�9:�����d��l����89t%�����X)2��������(�z��P����w1�M@d$V��?�V�v�^�0]h+��&g�
8Q-6��ibv���g���f��
�=%��v�{y0iuyk�����|oM��w�d��h��UZ�?�������R��[�)�}��������i���9����s�����4�\&q?�Sb"����& 2
������S_��:F����_N�J�����7�^�����{��N���K��U�o�q���%.�h�^Q��h}Q-
s������m�_��f(��(U�:��n]��J�c��%g2�
�Sb"����& 2
����V�ku��B?�����(=)���[z�����I��*Ar�<�	c�p`99|�;�P2p�DFB1�M@Ld	�US����cc~�2"7Q{��qba�z���cs�R��~]n�����&O}��v������%gl@d$��D6��PXup��j������_�f\������
������Z-�=���8�<��Y�p�w�~3@I�	�D61�M@d$V|��Z-<�p����V{�i�Z��>C/�����
����������f��E�eI��������P@Ld�DFBa���C�j����,��b�'�.k��_���
���p:>"o���R���rn��PRp�DFB1�M@Ld	�U��|�Vo�xV��8��B������>U��c���7��Fy@c�p�3rZ��	P�p�DFB1�M@Ld	�Ug�vP��	��L��R������KC�����7~��$_?&�d,�!G���{J����H( &�	��l"#���R��j�Po��.��Z-��n�x��:��&+.l����?n,��#�{��%	gl@d$��D6��PX��-C�0�I=Y�k|"������2�$����TK�w�f$���iv���}=�>��36 2
��lb"���H(�R'�l���_q�qba���^�WK�J�}R����T�m���P�p�DFB1�M@Ld	�Uj��b���^}�6��Z-L�Z�tKO�T8�����^f��%]eI���J����H( &�	��l"#��J������)�Yf\��P�'�TK���uK�;��T8�Y�����<����P@Ld�DFBa�Z-��[�Sw�]�Z6���Nj�p�����r�R�O/��6��	����P@Ld�DFBa�Z-<9�����s�����_��N-~���<���T8��{����H����P@Ld�DFBa��Z8f��G9P���P-���M�O/K����wx�����36 2
��lb"���H(�R��g~^���d}��}Zn�a(�]����W�nW�w���(�8c"#����& &�	����*�Zx~�:�|}��;��x�|�.�>p�$��
���b"����& 2
��j���{d��M����`]C�p������R�����,O8P�q�DFB1�M@Ld	�Uj��������|��]C����Y��������nx����36 2
��lb"���H(�R���.�#J��;�4�
�lusxc�p��|9����|����P@Ld�DFBa�Z-�%��<��_6s_��~-�\�������>fv����=}���36 2
��lb"���H(�2�
c���n�[�d�_�4L,\9�E�R��>�>X�A�	�D61�M@d$V��W?ljX�$jo�w��}sm��f�aV*�����x�`�gl@d$��D6��PXe�^���0�p��o�m?w�+��R�����O)���
���b"����& 2
���������������k>�<�Y�Y�C*�7��n�	�D61�M@d$V���M����=r�����'h��f�����=}���36 2
��lb"���H��8��m�:u�x{{+v��5((�
����M��v�
��Y��T8�a�r��o��8c"#����& &�	��������T�R^���������&o�l��������J�?<+�D���8�36 2
��lb"���H��RSS�W������{���p�F�����+=5j�P������)qo�MS��U���M�5<�36 2
��lb"���H���-[�����E�N�N��o(���m+�mMiC����}��j�0n���&����q�DFB1�M@Ld	P�������.]j�?�|��_�~�����~/�
���
SG���R��gl@d$��D6��P��[��������'O�T��g�i[S7�WQK���u�?~��36 2
��lb"���H�����������`���?��������fnb��(F����P@Ld�DFBT�J//��+�dee)����������*J���7��Z�@���
���b"����& 2*���K{yyI�d�����~��b��T�F��
z(��#��|�
<0���b��^^^�������U�V-�mMy�S	�����x������-������'�x��� �
xyy�9s��?44T��W�^1m@4_}��������-��,Y�������� ???///��F�Y���D���Q�F
//�n��EDD���*v��Y��^�zZZZ1m@@3f����T�R�������m�~�q���M���Y�\�r�k�n���������B;� �����i����+[�l��5}||��[�����m[�Nooo���]���vnk�����F�U�X�j���Z�:{�����/*o�r�����v �M�6y���)�	��^�_�x�;��S�Z�������K�������F<���������r��=��S�
JNN�?�xn���_[�+i�
B`�	c������/��$I���[�T)�1J���R�/a����|��rr����}�.��Tn��:(�7���@����k��Z-$���egg�l�2�?������Vu��/!!������+��b�M�xn�j�*C�?U�i*�'���O9��-[v��Q���YYY/^1b������?�0L�~U�zu��{����P��(~���JO�5��6^��m�����*=4<Pv��I}����+=�<�HZZZ��u���O�{�i?�<b��!���A�{��MNNNJJ��a��O>�t6�0�x��_?����M�7nh��k��j�C�U�O�m-Zd��2��h�d���n�Z9�M�>����iJ����/��e��)[�ha:F�����J��m�l�����9����V���*'v��c�=�n��qc�g���v�
�;r�H�R��/��h�M��n��]�Loo�k����)�:u�O�#S�/\����={V�y�����	�ALL�g�}�|�z�!����M�U�S�V-��v������X��B�
���{�V.]��b������~���x	;��sX�r���z���P9�{��ix�k�.��3�<c�������a��?��|�W�Z�������_~Q>��z��=�xQ�|y�#�����(?+=J��C<7�R���~�������V�6MVX(ZQQQ^w'Q��[Wyx��i�a'O�T��gm���m�����+��������H���k��*�a@T���W>���7W~��E�l���];����R`{�<��_l�w�p������j�����1bDzz�l�K�\�i���@�Z�x�r������a�:u��			�S}�Q��s[;�u��Iy`x����<��������+���a�tq��������]�R%����h�M��^|�E�#}������V�Z��Q�b��
6��e��0�	x���u���JHu:]TT���c���S�O�
L?�V��E�&�,���T��Y�R�s��z��������R����m���m�f�U�j�"##�
�y�e�����{��h�/
6T>�3g�4����E6��Q����^�hQ�2e���?^F<O�3gN��U�`*�i�I
�'�fV��E�&�,�����M���U���#jg�����_��(���J��������/q��I���rVo����J���g+�����(?7j�H�|Ql�����g�+�0o�<�S���o�t:CO�/Zdp?�m�*T���'��>}:;;;66��������}���'�J*�5kfH�������x��:�xnf�ZX�i���@��j�����]�vDD�i�r�SN��/D�
����	m���m]y���4�r�!!!�/_�����+����/��}[���-[644T���E�l�����|�l�?k�,��e�����p���O+��Z�j�Y�&>>^�f�d��j��)x��mF<7�Z-tC�,�N���m��\�r���j��kbb�E��5L���'l���m]y��c�*c:v�������*?<x��T@@���S�N66��Q��>��3�-�	���?�|z���,��_���+�O��>��#���b�
���z����xnf�Z��4Xp�r&���Q�f�����l�
����9c�����W������������\�r��e
�<������������^�]�
��x�0�l�����[����(����7<$�������7,U�~��'�fV����&7��P���S�T�R&L�:����RNt��/��_�d����o_;�s[�_��o�Q������p;)�^ox������	����ZH6�������=v��E������g�}���x�g��P�
��?11Q�W�5<$���Y�w���@	�}��
*T�\y�������SNt>>>��5�z^ub[�^B��L9'W�T)::��c�F���fx���������E�l��c�����];���'��NA<�k�����
��_�r����A�C�	���ja���
/A`�`������Z�j���6�edd��QC9�u��-"""77W��s��JO������+�:��c����Q�%������� ��_��&�~z��~�����o��z�������V�X�|������'�~6lP>��k����?�_���j��]kX�`��u�a�p3���bM�^��(���k�e�:r����-U��������C`��vS�8qBy�V�Z����;w�R�Jo����+WQU�V-22���)@���lE���k�>��E(��)�h�"�a�p���G��b�����'�NV�$u�,��]l0�q���M���Y�\�r�k�n�����������m�f��I��f��e���DykU�Ti��5k���p%_d(Z�oc��y���*T���#�(�#G��F<���o_�V��`�-[V�S�y�����O�m
��\�i"��JLL�}�O^w��.\X�zu_�b��}p]�V����ja�0� s�P�}�����/�����������V�����>a����4�a��_�����|�Ie���?��[����[��Z|�gCEhh���O<�{��gG����n�[�OEFF*>��cZ��b�J��ocz�V�����/X����J��?�����[�;!!!U�T�_7{��bcc�a��Z����
*����to���vn�v�Zooo�ao���F����*?�����[�l�x�[�nU��g-���g�}V�!<<�t'��MS:�w����3 ��
zyy}������YYY))){��y��������$&&��������s������=z�(]�t�j��������Zh���n��\��2�O�>��]S�������Vz&N�X��-:W�Z����U+�m��U�W�Xau'��9r�H�g��)�����p�o��T�P���+!!��344T�|���'O��<<x���T�G���X���p�������;��	

R:_~���vn����S�f�2e��V/ccc��+W�F���l�;���S�N)=
4P{���J�e���0/����8�r���7oZc�Yw�����g�*�u��U{,�ovnX�^=�a``��C�]-T4H�y����������$��;��O���t��111������C�DZ�d�����|���?�|������Q��]��W����(����#�<�<LII�}��V��?�����/�����+J��3g
���}�3F�\�h��a�6m��&L�}x@	�i���_�����s��s��)c��W�tiuW�7;7,[���P���>�B���g3:tH�����������1��>�����{�����+*O�<i���������={�4,q�e�b�aQc�����f���E�]�[�X�t���E[�������?����x��T���(S�����w���x���%I�}x@��m�6//�*U�fn����
-�ovn��k�)��9����vfeeU�^�f����V�Z�+WNOO�1��j�?���w��}��M�_|���cJ��^z)�e����Jg��5
���{��������k:l���J����X���p����+r�!)����?��R�J��`9��_�~J�a9�^�zY�_��V�����P�+U���A�???(����������o��=)))++�����7V:�u�fs���j��)=>>>�����>p�@�^���)S�\��g��{����������/�5jTLLLff����a��)S��{3\��z�j�V���W��9��T�\Y�388���Z���O�W_}�0�l���^%
������8���8��[��a;v�x����[�l��������p����i~�|||�Z�:�Q�F�����z���4������`����������H�$HII5j��/���]/�����#���,�EFF�����'�,W�\�j�>����{�Z��Z��gC��C�Z�hQ�zuooo�&L����c:���k~�a��U+T���3��x�E�)��g���*������������M����K�*u��OO�1c���W�v�<} <&66����O<������S�<}8<F]��G��>�����W�T�{���>��C@R
endstream
endobj
6 0 obj
<</Type /XObject
/Subtype /Image
/Width 1722
/Height 948
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 48404>> stream
x���	�^e}?���bq�U�!��"*X6[j�Ni��"Z��(�ji�qj�@ ����@BBXC"� @�%�$���z�����9������]~�|>�dr��9�<����\�'gy�}�U��������5w��j��e�*+9��S�����y=����7�M�v�2��N8���F����O�f;*�w_:�����?6h��w�y��M���~�:�D����r�)��s���cg���|����p[��U��}n��M�=���q��
v��'�S�����4i���G}�:�O���g��u���w�jK4������=������wW�zT�;~�}�
<�v�d��y���hJ�]�f���5������nr+�f���l�X���36l���=��e�Z�ET������w^�S1}��+��u��K��a�����D���j�UW]UY�C=�]m�Q�;�p��Fc�+V�~kC)�w��	��a��8v��&��j�.��&�1r���7ve����yj5��o��|��SN9��<<��M-��1Z�F���M�6e���L�������OG���/�]�v��uK�.����R��:��=���������;�J��j�.��&�4i����l��V����l���\pA3�����S��n/Pb=7F+���[���/T�p�y�uc����!C�����/�us�����P�=��0_-�%�����pCO=�T�����_���O���7l��j��W^y����:th�~:7���Z[��U��}������#G>���k��}���,Xp���?}��g���@����D��ni�m��VY�M7���m�C��At�3��4��}�}���c��6c���_����7��T-�h[��V�Zu��gg�[��p�=�J�����5*;D)5Uo���q���#�
[�C/�n�sc������]tQe
,�����}���O���+�� wx���������2�������N;�j�F������Od��
��"�l�����X�u�'�pB���/[�,{)�I'��-O��L=7F+�����������\�5��R(�7���$��>Q��N�n��9�����/X�����T;��3�R�;[�v$����f�kK>��6����c��iT��+������vp��oL�:��s�9��O=���#G��w��{	A�4�>}�%�\2l���O>9
6�0|���i�O=�T�U7uG��������~z����&��������y���}�z���|��i���V��;��S�?����'��3.�����;����I'��6=~��9s�l�������[7k����G2$���5�\�=a������s+�_v�e�Z��M7�V� ��1c��iO+�Q�����7��.��H�Y:7�>���?���~L#����W�s��e���K��i��v���y���\�r�o��.� �HiO/���{��g��������K�^{������CZg��������ft���_x�B�����+��H��{����Zv�Y�o�0��i^����:�kY����+���[
�����+�R���o�C��������"u<�2��������3������{�n��)�od�%��5jT�
��g��~!���g�����o�����U�����j��~{���!U#��~8
=�Hc��{�`=/����������)�qm����d/�u�%����3_!
'�`'�I�Jr�[���.]���K/m��4R������?��3�.~�
7�Qd��7i��)��g������t�jU9
���G�f�����n��?����oTy���B�;�j������c�6j���?~��'�n�������7n�&����4jO�:�]�_����N�,2h����W��������>�h�:o��vV'�3����O���htX��A~��g�Y�vg.\X���~�������j�;|���dK2i�Y�+����E�
xjU�~��^z���.�$uqu����)�l��
&O��h�?�e}�=���S�+7n\V��_����:-��V~P���O�|���+I��c�5d��5k���z���'�x��T&
��x��N�4�x�F��W_}�����tj����qe�m��zE'���l�����&7��Z����n*>P�F���
��j�WR��g�}��O,���'/Z��x����j��$y�<����#F����3����a�
f�;���:?����_�N~"�7��M�:�����b����~��;Ru���S��j6n��M�����uI�T�B�Yy�[���lI��U��/YN�e��4��z�/2�_������$�d��y�j�7E3�L=���_^����k\�Y���J��<.8=/^�UKaoT
+?(8��S��C��3g�������.L���U<x�k��V��4��_q1f����{.-����~��T��i�Y�3f7�n;�x���P��K.I���k��F>��S������c�4�z��gR7l������U�?�}���������JK����Kc�)S�d��i8Yu�dE:�gS��!J����{����{nm#;��Qe�4\-�)��&7��Zm���W9J�;JgQ�u�i���z�m[�dI���H�J_�����O�t�_}:��I��T�v�z��t��'���*S�'ONgx:�V�Zu�w�+T��t�O�>=�p�����-����u���������}��?�x����T�M�6���N��w5�J6w���<>������r�t�K���jmU7�f�#�j6ZI�&���+u��Jk�_�|�e�u���<��$�Y���>���ZR���S4����g�������M�6�*y��W������~Y���J��j]D��s�Y��H�j@XU����>;�~�B��=:�P�$��o�=�4��0�����������Q���QdkW=1���~��rU;8}�����6�����M�/�����9s�dF�U��q��U5>
/����Z��������&M���Mn�Q���������\pA�l~��-���
���zg�	\�d������o6����Y��*T] :�f^4�����O���h[���]�]�6�rO�}�Ev;m6������$��N+i4��C�g`W���{��}���M��j��������d�Lv1[�����i����;+���'���{����3�8����-��h����:>����mHqk��N����������� �v��'7����q����Z[�����?l��e�O���-^���VV�\��I���f�~�d�����O?�� ��;��;J����/�;���0�j2s��U���Q`'N����+��?Z�bE���!C�^Q�i�Mv�6T ��Lc��.���U��_z��u���
���n�[/�4�j������������W_}u�����Vx���u�����:)bY��C�l�@�������
S�N�|���_;_�������8��Cu�A����5�V{����������<xp�	ok`'��O�6m��
����V_e<���>}z���������i�7E3���c��U�W?B�k�������=Zv{3����\u�U���_F���'��+[<
���Q��]w��}���u7���ofu�
Vw�����	�SO=5���Y���.\�h�}����o���G�'q�/������5�q��l����F��t�j��Gy�����\u�I���?�9sf�i�=�ue�kn����#�jk�^���"���}@���]G��]?�����'O���(
�+h�U��/��Ii��P-�c�����f��AN�E� ����j�3�j;��'�_�]�������1c�����]<(QO���x��DF�Qw������4r���Y�Fo��Q������������"?B)��$������Ic���1#�������7��>}��g��z���,YR�N�}�U���Y���V��A�.���CW0��_zW� ��]{�|��nT-_^����0�� �rn\y����M���������_���Y�2��9�z�NE���.|����]��2dH�����{�R~��������'.RR�����T]���t��=��{Q������}bCv�l~"�x[���[n��sc�Z}���Q�F�,X����42?��z�)S��c[p�_��?���sm!�]~�R�4�����
<X�x��Y�f]w�u�\rI06y7�����>;�t���]����n7��+H�U=�=�����3�k#��b��zke����wv���u������f���z����sN�i:K�<���;�4���&�u�����u���:?����
7�P)���������+3<�<�L�l��,��b� wj�u�����������0G��&#�	o�����������[����4iR�M];7b�Z}��������o�f��o���*N9�����?������-�/�)��=}�o^O�
�v�AG�C���[�U2dHm��^{������Q�i�kjr��h���9�F�n��OM4>f��P,�\��������w�la�;\:�xg���j���?u�j��_�U:��f3G��/������~8�zv_�F6P�7{-�����Y�l�g`�!{����l
� 7���j^xa�0�v�z��k����dK2/��R�U4�����yj�U����\�hQ�����h���>�l�m�F�5�����;m���e�+���]��d�(��0P�AA�<O����.X� �����%
?��1�����7���w�����4��1M�54y���Z+�����Njt�V��R�.^�io����l����H����5k���������#�EYi���������`���3����������g`Wu�������R8~���p��q�����u�XU�?�����
{j�U�+m��>l���k�������F����3f��_�W%}�����l��6���/��=���?~1�E]T�;@@�AA��Ek����U�d������*��	&���i��
���;*�4��V�-�B�SN9%+/*��8V����1�M���_��GJVif���-�^87�'p�������U������s/����3y��7W~����j�#7+O������7���~�Xg`Wu��������2������z]���<VU�-[�-���5)���W�����y�����3�������:�����[n����w�%��������F���������y���k���B~PP�H��K�f���[����6��������o�-�4�G+�-�B�����X �V�7��]��aSke������+��nt�f~0>0�la�*x�Y�.x�YA����]ui��Nf���5��{�}?w�.X� ������R8h��
6�q��Ru_y��g`Wu�:ld�����Q{Kf�J�<VU��:���\�"�����z�T��l����_w&�fy�������K��������������5�Q{�W�U�z�3P
������z*������G]
l����}I��G�������F�Z�fMV'����5wX-����5c�����~��F����v��*�`f��*�5�X�^�FW������\�x����e��7�����������|����]u�������*�}�W]uU�T�O<1���Z�*��67r�����^����������]�|#�M�V)������S�N��x��7wjO�p���~��M.�~�S��3~��Wg���K������_w���~;yg�+��&������U�kG��?����G(�s�kM�<9�����>�Q�N�F�2?���
�>��x�������n�����49kT��;���k_���U�06���0tv�����������i����F���x��/�4{L���?9S�u�]��j��7S�����-�u����+�2d�+��R���W^YU-{g���s�������������-��zA��I}g�y�����Z���S�������*;�����V�g|��5�����[�M�L#����Y�ti�:�V���t����_�>�3[y���d�14hP:z����G(ipW���+VdS�i�PU����4���`_Q{�Z����+_����4\���I�&eu{���;��q���/�K����e�|���Z�c�V�\�]E��^�;��x��5�M���V�L��o����5���lt_��r�������t*��jm�T�?K_y��.4����U��n��+����O������l�)�T��d���t�&�^P���={��C=T��i��V����mu�8,Z�(����7��|jE�x����|Wum#�����F�X���V�}�C�-��.3fL���/����q����.�*�=�����l���U��_���K.�*�t�MUk�O"�~��U�n��!?���� !�����"\z��Y������l���3�h�h�&�C�G����;����WWUX�l�Yg������;?�y��W=?��CT��*��I����*h�\P5��y��[o����-���;\y~����5k���#;��N���:uu�w]���og�����[o�UU-��,�����b�>?>����W�2eJ���_R�:��fZ�z�U�V-X���k��?O��Nht�p]�O��8qb���g�Y|�t~S4��E�eu�/������1#�S��k���s�M����N��H1bD�����%2���_�����_�>����O?}���g��N�)�X�M�>=
a6l��|���~8
�j7Q;����1
{�y����_|1���od7@%&Lx���� 1������W�T]����Z���K9�81�W�n�z��{����f��-
����{��O=�T:�� �C}�EU]�M�[�n]e�4���@�����o=5)5,�0
�.\X�V$�����-���;\���K�'@6zM'5>��}�N��_����T���S����L�_6x�������`��/���o�Owir����5��,\�J� u���r�S+B����|X;��o�&���=���={��+����o�W_}5���������o�/��.(>�*R�F��������Q�
�����N�{wU���T��w����"���V���-/_�����R�u��7�`�����g�}6?Vm$
�������k��9����e����tJ�����<{Ym[<���7������'��:����e����L���S�����}���oI�e����d����V�����4���j6l��=��UW7���]5q������?������;>�{kU+�)�l�������Q��A��>S�[<��s�{��J���7���=-���k����K�w�%�,[���J������i����#������w�qG��(�E����E�~��_������������m��j����W%�`�wef^{��s�=�����MK-o��y7�xc�C�Y��Yg�U���Q[<���7���_~9l��Q���:��&kvW�Z��]W�\�2���9����
T{e�o�Owir�V7n\Va��1]X���2d�<�����Z2�r�g�Q{�t�S4��������*�������W��^x������s�i��F��F(i���O\q�it�	'6��k��}�{�4��9sf��v�ii��C��=��{���\~����

>�v
�V��6mZ��r�)�>������s���?��UW]��v��'�|��\pAZ��df�C�f�����`S�L9����n�F����_|���6y���M�R���MV��	���N55/{;I:�M.R,��'N��������`����f��.�i��r��������s��36��N:)�B����SO=U0������]uju�w������t���|����uD�^zi�����t�O�L��=�PV2�#�:��SS7�:��n�)�Nu�����V��3�:���}i��u����S�}���E��N�:b����������3����4:��+�:{��G������wq�Yg�_�s���z�1P:};0�0[T�-*�f�
��@��B��l!��|�������������������9s��u����A�v�i��nE�Z�l�	'����]v����2d��U���Q}���ooo���k�8�����k��v��W�2|����{��[�'6m�4n��C=t�=����?��o~s���������������_�b:�>���}����6mZ�7h������K%�^{m_7���x���C��
�=+V�8��������\�zu_7��|������~�S�����?P�7o>���j����������5�;���j�/~�����j?�)�W���g?�F���?��h��
6�?��?�3��������n`��4i�.��R��������N:)���~��?��7n|��W+�bg�qF_7�W���~z*?�������U�V������O?��S���C{���i��1i7�����+W�L=�w�q�����;/�6k��T����g���/�]���_6lX��N�0�wh���S�X�?�A�p��M���7R��~���jXoz���~������c�=�������/����?��,\�0�t�A}���������o~����u�]_}��|��9s*�h���>p�!����z4����S�����d%�sL*���K�5jT*�����h+�����������	&���N:�OZ��>���T�>��-m�p��vK����4�=���>lUo�������S�/��>i^Lk��M�d�=��J���/��%K�T�\�ti*�}��{��Pb�gm��akZ�/��[��7��������*���Ry��;v�����x���Z�/���m�c�=�
�f����^�-lq���>��i=]k�W������-�J���T������E��7����n����.���o��c�M�3g�liW[������������nr����cr���wXs�����>���]��?y};[��������+��+W�������E"��wK�-����+�-|���7m��x���S+����{ZW���������O�����3��?���{����{~����~{�7�9�f�,Y2a��}��g��v{���;������������M��og+�a����r������
{X(�la��6[��;v�����`��O}��+��`v(�la^�o���N��&M��'?Y������w�v;f�����ve��1y��G:��z�����?�Q�<�L���-G������i��y�������T�>��],b��og�����GWN����c�9��_��=������������������u��.]:y���L��Y��e�E��v�a�z����[��x��i�7n�x�QG}�_hf^���l��{�������*�\[��^{u�.1[����������?��/|���o^�|����z��)S���}�}�y����}��b�p�]wM�C��n�W�T�>�f�0s�m�}���M��=��������;n���{����k�����������NC��+WV�/_�<�p����E���l�����������'N��;��+�l��?��T�x�����^{-��O�e�E��&7�pC��l����?��.��R��$�C};[x�a��!����������9o��-�����W�q��/~�;v�H)f��_������$����n���"!g�~�������g���/_���~7}t���w��`�����L���S�V�O�2%��p�	���E���la�>���WW��\�2��O�c��b�����e*�;wnU��/���>��n�t�>�-�g�}�n��P����W^w�/�3g����?`��/����������!�w�������Okg����la�:�����>��CU���L;��>iU����}�����c��*����zgF�o���W��a��U��5*�s�1Y�]w������������z��@�y��w��{�4�?����{���7�?������~�����N_7��mQ������������~������b��[n��r9Y�o�$��������_�5��x�����J:J��/�8q��{���n�-Z��O��k������;�=�<y���+7m��d���c�������Kv�e:������k���o����.����&O���M�[�lar�9��~�u�%�4��_}���>��}����4iR�7���7n��w���]w�5����[�D��a����1c�QG���}n�]v�o��~��=��}�����l��5��?��>������g��}������������=���|�+���{:J�s�#�<����Cig�.���O'�������g��W�<�l!@�^{����j��9��#�0`@�~���Gu����kW����jeY����������c�n��VUR��1cz�Z]�,��/~���v����Y�j�;���}���_�`������Gyd*�����'������o������G-�3~��T��C�n����H���zkOTk�%@g�[�n�m����{{{A����'mmm����*=zt*?���{�Z+-:k���mmm��o�v�������n���>���|�;s���W;���R�'�x�j��{,��O{�Z]�,�������������!����2eJVm���p��eU�/Y�$�����=Q��V�
|�;�ikk��G>2q���K�n����W_=z�v�m�����<�L����o����C�����L-�D��ZY(P�T��n�*6lX*?��c+?n�������7WUkooO�����VW+���`����y�>�l[[����Z�q���K?�]���Z����|�#=Q��V������>���w�}7c�'>���������-]�4�����=Q��V���cCd
1�&�$���v��+���|����'�|�����sS�������VW+����!2	��db�M�LB�}�ckkk{����{��T�w�w��;�����	��]u�U��g?�YOT���e������BL�	1�&D&���<�����a��U�����_*1bD���S��9���j_����sw�[��V���cCd
1�&�$����������>��_s�5+W���q�k��6b��m��f��w��w+���Y���T����^�p��
������R�;��z����VW+����!2	��db�M�LB;t��g���q������6|���j[m����c{�Z����M.��"�P�I6!&���$�w�y������~�����?����z���j7�p������~���l��N;�t����}��=Z��la���E�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�Ihg�x��m��h���Gq�������<���f������jeY ,=6D&��lBL�	�Ih��Z�j��v�;[8v����������1c��\��ZY�L�
�I(�$��lBd�)?��O���|��U�v�a�T��������Oy����������VW+����!2	��db�M�LB���l��V���kg���J=��|��M�8��T~����D��ZYN�
�I(�$��lBd���������mmm'N��-��O~�J��W�����S������jeY 8=6D&��lBL�	�Ih�������o|#��v����J%O<�D�R�=�X*O��D��ZYN�
�I(�$��lBd���������K/��~�����e��U-�d��T���;�D��ZYN�
�I(�$��lBd����7��_nkk1bD��v�p���O%��y���Ry�~�z�Z]�,�7�-U�3H[�K/��������iS��v�p���N%�7o�Z���=��O{�Z]�,����$}���-�������|�C����s��������.��]��j��}i
=Q��V���cCd
1�&�$���;��#���
�/��-��'>�J�/_^����KS��;����jeY 8=6D&��lBL�	�Ih���T�|����O>�d��s��M�_���z�Z]�,����$b�M�I6!2	-��l�q���>a��������T�����'�����@pzl�LB!&���d"��.��y������C�����}-?w����jeY 8=6D&��lBL�	�Ih���Y���������^�p��
������R�;��z����VW+����!2	��db�M�LB��v�0>|x�}�[m����c{�Z+-JG�
�I(�$��lBd�u���n���_��G?��m��f��v:���������bK�r�cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd
Pzl�LB!&���d"�P���cCd
1�&�$�����"�P�I6!&���$�,����BL�	1�&D&�e����$b�M�I6!2	(=6D&��lBL�	�I(@Y��!2	��db�M�LB�B�
�I(�$��lBd��M�6�5���n����/����9rd*��9s��#�8b�����Ku�Q�g���ju��,�"�P�I6!&���$�������������W��n��|��c�n��VU�R��1cz�Z]�,D����$b�M�I6!2	-v�����
0����_�|��U�n����w�9�z��Y�T��;�����,X�~}���#�L%���O?�D��ZYN�
�I(�$��lBdZl�}�mkk�����{�I����[V2~��Tr�����m����H���zkOT���e������BL�	1�&D&�]��{����m��vY�O~��T2n�����G�N��|OT���e������BL�	1�&D&�]p�]w���}��_�J:��T��OT�|���Ry��'�����@pzl�LB!&���d"��Ny��7F����|�m����������-[�����%KR��;����jeY 8=6D&��lBL�	�Ih�����U�/���x ����o��k�!R�g�_�~=Q��V���cCd
1�&�$���6���>��w�q��EzS�L�>�z��S�����iooO�����VW+���`K��7�t�;����v���WJ��n�����k�jV����G>���je���>%�3M� ����k�/:��'>�~\�|yU��K����w��'�����@pzl�LB!&���d"���Y�bE[[���o_����N?>���U���������/�D��ZYN�
�I(�$��lBdZ���x[[�����_}����N*?w�q��	&TU����R��~����VW+����!2	��db�M�LB�����{[[�������=��T��o}�����S���rHU��k������VW+����!2	��db�M�LB�=��#[o����n;v�����o��i���#G������}�C?�p���5k������v��G/\�p��
���}�{�d�vX�zuOT���e������BL�	1�&D&�5j��[o������Wu������jl��Vc����j���7�,P:zl�LB!&���d"��f<����������j�m��y������7���
7�������h���N;~��w�}w�V�;[��&�r�cCd
1�&�$������{wU���?�Q���������yf�y���?��=�-�[����EdAD�U�A�Ev���!$���I���=U������_B�Jj�}+y��=��r�o����9�so]�H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$����2�M@&�	HFB�_���H( �d"��d$H�4�L�U5�c��P@&�	�D6�H(��\������t���
HFB��& �$#�h�r���K
�M�������ftl@2
�D6��& 	E�e�9��(j6%��t�U`7t���
HFB��& �$#�h������?�
K��v�E5�c��P@&�	�D6�H( ���d�E�	�LLo�q�����j@�$#��Ld��l��P4@��Y��0����=�^�gI�������H( �d"��d$
���jT�u���v�i��������M����c��P@&�	�D6�H(���l������mZ�5��$=�jb��3���C�$#��Ld��l��P4�/����4*2����/��
K��#����Hw�@u���d$��l2�M@2�"2�����F�c����l�Q�sY�kR�O�-�]����d$��l2�M@2���j��~VA��p��5)����
�KL�6��=~���X�Jtl@2
�D6��& 	E��|��2��Q��7�1$l�����c�1�wYt�T��
HFB��& �$#���n���-,l6%����5�&�1*l�����9F�5�-��Y����*���H( �d"��d$�X�����Qa�IY���[vT�������m�voU+�w|����TCw�@����d$��l2�M@2�����xwuQ�)�m'������0������%��i?��aj��/���o:�Ptl@2
�D6��& 	E�d���6Y�M��8!>4����W_��_+�q����o'����"MU5�c��P@&�	�D6�H(����n�
����j����0�oW#=���+��
vt85?���R6P=:6 	d"��Ld�����Y~��lJ����^iTvTxk��fnn��m�b�67Z��bR���6��
���
HFB��& �$#��g6�7��?t��-_(;*�7��X*��43��U[qp��*���c��P@&�	�D6�H(�����S��
���L�Qa��I��7����6^����
������H( �d"��d$�Fh���'�3�Lm����0���k��z����B�������a�A�@����H( �d"��d$�C�M����%}����6.�n�+�����6��{}��~��kj��
HFB��& �$#��nd�f���������XB��~����}��_�gI��
���
HFB��& �$#��wi��ks�vuVvT������S�:N��Mj�#�4����mz�f�n���d$��l2�M@2
��[h�,�H�>eG��Z�b�k{(#-5-�Q�R��(i��bo�����2�M@&�	HFB��,����m����0�G{b|��5��:���7�����n�c��P@&�	�D6�H(���pL��bt�veG�Y���u>f����P[_���|wB:6 	d"��Ld�������/���j~��p�3?����b������G�I�'.�=U3�>:6 	d"��Ld����mZ|(��w�
��gZ���43:�T�|{��9�-���:6 	d"��Ld������|�-9���5�9�a9x��I���{O��Y�Gx���2�M@&�	HFB�_���H����?����%<���u��v����_M��p���2�M@&�	HFB�7L���9w�	�����'),Ho��:E��1����HA�$#��Ld��l��P������eG�7�����^o�*{���,�,���g���
HFB��& �$#���,*L1����z��w����
7�W':��_����B�K�j��
HFB��& �$#�����6�����KmZ���3����������q���6��p���2�M@&�	HFB!�=%)�W�����v�[v���y��vSg7t��-o�p���2�M@&�	HFB!�����W���|���m�>8u�����u�av������
HFB��& �$#����|xzp������o������]qT�:o\����s#��>93P:6 	d"��Ld���B ��C�m�+;*��}����v�WFF� u�A�N,	����@����d$��l2�M@2
i�vmMk����p����YQ`���Fr?�P�U�Y}����@e���d$��l2�M@2
Q
V/+;'t.���wian��7�rp���l������d������
HFB��& �$#���4�>�QvN��d��
�d�i���yi-��b�����L�����c��P@&�	�D6�H(D��L����0��s�
��qNAB��~���[#�zf\9f]��J�tl@2
�D6��& 	������
�Z�c�{'��(�M�6*t*�v�*i���?��pw!��c��P@&�	�D6�H($�[4G��.�i��������]�������J
|����'.k.	
���2�M@&�	HFB!A��7�\��a������+������*l��]sv[tW���
HFB��& �$#����ZSZ<��r'�o
���o������=�w��@wEh����d$��l2�M@2
��#��D�|��ZuWT�8����J���Sr�Ru��"8:6 	d"��Ld���B���+�DnS�������<�==��*o���k�K��
���2�M@&�	HFB�]��j7k�Z��]��r&�U�}�w���E�+B�E�$#��Ld��l��Ph��>�tZ�(Jw9�Y��V��w���S(l����
HFB��& �$#���]����|q�qq/6ss�Z4)�05�Q�	q��D��
���2�M@&�	HFB�W��mjZ�������~��g���SEN�f�q#M4tl@2
�D6��& 	�^�S'�A�������u+U�{���av��WDA�$#��Ld��l��P�u���j���������z�*2��s�&e����.

���2�M@&�	HFB����lT2�Kl��@������3X
��gi�UwEh����d$��l2�M@2
��'������Q	ro��[0S������.-�]":6 	d"��Ld���B���?/��1�&�GKX��T���i89/5��.�����H( �d"��d$]�?@���M����j���_������g����	
���2�M@&�	HFB������y5��=^wA5��h��v��>X_��"48tl@2
�D6��& 	�.�����b���n����E�oW���zz����&40tl@2
�D6��& 	�.�������#��������%�6����������
HFB��& �$#��%�����p�+u���[C�P5O�~�n��������H( �d"��d$�\��ZM�����]�K
�Y�j��u��
tW����
HFB��& �$#����o_�~����}���=�X�����__q���������z��{�u���W_=~���7��;���=%I������j�]�KlW.��Z��rRV\���(4 tl@2
�D6��& 	�����*��o���6[�l�]w�Un��������<�Y����g�w�Vc��������d����|���k���
���2�M@&�	HFB��w��������{��1�������.]=z�s�s��E�J6���y��G�kz��m�Z������s���>���76��;��R�G�������u�SysK+�����+�tW���
HFB��& �$#��k��}@@���������O�����?��q���?�n���6v�����s������Y�����.������_�]N-XOU�G�m4-?���y7����d$��l2�M@2Z��<   ))�����T��������p�����.���E������*���>c$6)��6
?����Z0����/��a�1�����9j�9:6 	d"��Ld����MBBB@@�o���?>����?FD��oXX�s��o��Y����g2��R�����������������o�������tl@2
�D6��& 	�����*  �k��%|�������(�Y�-�O<��76��;����Y_�i��o}���Z+��Y��c����"�'���d$��l2�M@2Z999O=���>U����
�����B��{����U��}}�\�����9��.�������F?=I��q�G�����B�@�$#��Ld��l����*..n�����?~��Q����E@@�i����0�z��zc�J�����F|������������������M_���i�otl@2
�D6��& 	�����S�'�|2&&���x   ������%w�=������R��[��9�y���]mx��Y���{.����_�c~���<��	Rg�Z���������������Yn}zz�s���olV)w�-�{���O]��lz���yU��M�S�h����o�;zNwQ����!KOOo��y@@��	*�m��M�u���r������5j���*������x5g��Lw9ue�]Z�2t��ma6�5���c��P@&�	�D6�H�+�?��SO�u�]�&M�t�~���\�������;�8���S�F;�![��0���]�����������?�
x���2�M@&�	HFBk�c������W��������f�����7/���_,;���f�T�K��t5aK
|&7���wX�T��|����[��^F�$#��Ld��l����EGG?�������O�<Y�f����>�h@@@���cbb���������s�#�<��������D������-�����&��0������66�����P����H( �d"��d$�z/��r@���3g����w�u��ew�4�g7+WC������Yj�vt�L���+{�;���������+B=G�$#��Ld��l����=��.N�6m���E��{��{�y��';t��������f�N]?���u���k���.�]�[7��s�S�W������2�M@&�	HFB�3y�����Gw�o����]FjrZ`���������qi���P����H( �d"��d$>�;L�
/v�������]}�	C��=^��"�gtl@2
�D6��& 	���LY�k�C��.�3��Z�>�������HwE�����d$��l2�M@2
�9��p5X�\�Aw9�Q|!R}��V�h55'���]�-:6 	d"��Ld����7
���VAj��uIwEb�Z��5d���Q6�5���c��P@&�	�D6�H(|#�x����|�a�����~���h��������"�[tl@2
�D6��& 	�o���Y������O���>Z�K��g<���c��P@&�	�D6�H(|���&��Z������$� ?��3��u{>���(�Otl@2
�D6��& 	�X����yZ����+���Q�������_�������2�M@&�	HFB��Q�R�7.��66
tW�a���S������--�]�':6 	d"��Ld����v~yP
�.v�����'%����K�������<:6 	d"��Ld����6����i1N�]�Wd�yE}������MwE�����d$��l2�M@2
o����S����uW��KJ'���;vC���P���H( �d"��d$�v��5��j�fON�]�W�;�>��V�m��Z���F�$#��Ld��l��Px��u�j�v�}k��x�a�7W�t�{'O]���	�
���2�M@&�	HFB�mk��R3�K#F�.��r��W�tI��������
���2�M@&�	HFB�U6�c{���-u�j�y�%d���a��v_P��"�7tl@2
�D6��& 	�W�����i�fh��(�y���������]�]��f�.
�
���2�M@&�	HFB�U�v&��Yr���z���[#�R�������(�]�:6 	d"��Ld������M�Q�����t��u��Q�wo�A�V���
���2�M@&�	HFB�=6�������~�@wE^g���>oR��/MN�-2u����
HFB��& �$#�������jzf=qDwE�����������P���/���H( �d"��d$���`vr��o�ld�d�����Q���=?�����"�tl@2
�D6��& 	��,�}L��nt���)>�>��6-;��7xB�$#��Ld��l��Px�a:����G�&O�]���l����>x���Q	v�5���c��P@&�	�D6�H(��b�����jhV�{���|'g�������V����c��P@&�	�D6�H(�d�	������������w�~��>������������2�M@&�	HFB�%���P��K���x��}+-�q�gO
l�e�������=tl@2
�D6��& 	�7��c��u���������n
}S}����l?k�]�:6 	d"��Ld����.�����e�k��]����Z}�����HwE����d$��l2�M@2
o�t�8��`5.+>wVwE�f�vE}����;L��rw!�F�$#��Ld��l��Px�'+�R���RZ<cZ,�+� �G{509|���v������H( �d"��d$g:��G
�����"=�>��.��^������~��
HFB��& �$#����TcY��jP��p�������P!�m�����~��
HFB��& �$#������G;�V�2��}�+��,������}���n�.
���
HFB��& �$#���Is���US2##MwE��|8J]���-\w�XwE�otl@2
�D6��& 	����pJ��R�u�]�NE���Kq��^�W�����
HFB��& �$#������_�Y����+����Hl\r)R�7��qB^���(�1:6 	d"��Ld��������vu����[7��H����?�8i��l�+��c��P@&�	�D6�H(<k�f��VAj>f���"�
V��i����i[-�+��c��P@&�	�D6�H(<k��X5Km���h�o�]��.H|�^�u��Yd����2�M@&�	HFB�A���GC6����QCtW$�iftk����w\Hl�T����2�M@&�	HFB�A;�mk^��&c�+���H��9��5Y����ZuWE�$#��Ld��l��Px����������5����D��8����v/���PwE�Wtl@2
�D6��& 	��1;5�y��~�0��Y���"L�%���j`����r��B����2�M@&�	HFB�)i9����L,�_w�	�=v��2��/�~���"�%:6 	d"��Ld����S"�����fbys?�]� E�K_�r���6��~��
HFB��& �$#�����l!����X��]�+�HKMlTreR�2����Q{tl@2
�D6��& 	���8P��5-�'��]�,Yz������N_������
HFB��& �$#�����/�i������'�bu}��:j��������d$��l2�M@2
O�lj�+N��]�8��(u}��|���rtW�C�$#��Ld��l��Px��a+�4,y����c��]Z�K4t�������g���d$��l2�M@2
�(�;V������kV��H����%Z�{����+���c��P@&�	�D6�H(<"1����5
����"�,G�K�.x�7E�+���c��P@&�	�D6�H(<"4�~�}5
�����H"�� ����*�>.&���]�	���2�M@&�	HFB������Ws037WwEBe�~[]����������
HFB��& �$#���U����f�f����p�zu�v���6����O���d$��l2�M@2
�X�(T
����������c���&=���<�����H( �d"��d$����jv�����-�o7u��
�v!��]����2�M@&�	HFB��~�&`i>�]�h�K�k�]�1�ZuW�A�$#��Ld��l��P��R���c���n�NwE�GE�k���[K�uW�A�$#��Ld��l��P��Z�q�c5����]�l���r��\�G�H����:6 	d"��Ld����}'.�c��V�/{R�������Cu���3kG�MwE�tl@2
�D6��& 	����K
lT2�J	j���uW$���^5-<�����E�+��c��P@&�	�D6�H(��z]l��;w�]�0��R[6U��������tl@2
�D6��& 	����
)}m��A����FTm�����2.D����d$��l2�M@2
�}����{'M�]�(�v��h���l�UwE�tl@2
�D6��& 	�����T
��W|���`O�W-)��>s3tW?@�$#��Ld��l��P�)�b����|���"���zgu���u#��]��c��P@&�	�D6�H(�t9�8����z�bctW�7��U�mc���O������H( �d"��d$n:z�����z����+��g�u��*h�7�+�ttl@2
�D6��& 	����KR#����t��W���������|���&�F�$#��Ld��l��P�i��P5������r�L�����}�w��h��� ���2�M@&�	HFB��U���>N;r��r��e�nu�B��}����"�F�$#��Ld��l��P�i�����+~�|���37'�E�������iq&�"�jtl@2
�D6��& 	����V�,m�w�t�����Wp��5�7
�A.:6 	d"��Ld�����
�#��a�5�����O���������CV�A.:6 	d"��Ld�������6��������"�c��.���g�,��]��c��P@&�	�D6�H(�q("?5�Q��+%���n�]�_J�����'#��.D����d$��l2�M@2
wl�zI���u�����`���k_�xg�MwE��
HFB��& �$#�p��!j�ui� ���+k�)uc�����PwE��
HFB��& �$#�p��q�J��N�]�����{Q]�����y���c��P@&�	�D6�H(����O��+~�����c9�VWr��B��tl@2
�D6��& 	E����n��W����+�cE{v�+y"�����+�Dtl@2
�D6��& 	E�e��g�wQ3.[l�����q++-�q��L
l4xv��� ���2�M@&�	HFBQgQ�����������]���G]������0tWq���d$��l2�M@2�:;t,YM��6�]��+X�L]�]��m8Y��"�C�$#��Ld��l��P����g�t+�gO���=������/�Z���"�C�$#��Ld��l��P����[�t+f�{���R���.��w��[L�A:6 	d"��Ld�����6�\�F[�f��]N}�7�SuIW��t0���"�B�$#��Ld��l��P���7���V��M�������K���'�,�+�,tl@2
�D6��& 	E���H��w���:������ZS�������#M�EFtl@2
�D6��& 	E��d��mZ���=)QwE�D�����~�oq�MCwE��
HFB��& �$#���s�
R��R��8�v��E;��i������������H( �d"��d$us���j�u�����?�����������<IwE��
HFB��& �$#���]_(}��u�S�������!�f�����	���2�M@&�	HFBQ7�&~�&ZQL�]N�R�b�������+���"HA�$#��Ld��l��P������������.�^����k{���?����"HA�$#��Ld��l��P������V������_L3�suy�}��w��Gtl@2
�D6��& 	E������q�%&FwE�M��)���x}��8�����
HFB��& �$#����L{b��j�e�����Y�*�Y�v�`�]D�c��P@&�	�D6�H(� <<������Cw9��i)Jm�����>��]D�c��P@&�	�D6�Hhm���?  ���
			~������^�_}�����{{3w*������ +�{OJ��a�"���e|���"�G�$#��Ld��l���ZY�z�]w�U��p��e%U�s�W_}���*���.�~�V5�:��{�:,�*������;��x�XwE���
HFB��& �$#�����/������[�����y��G��{��m�Z������s���>���76��;��n���j�u~�<����i��J.rr`�q��tW����d$��l2�M@2������_=  �����tZ�b�
����[�]i������:�o����U��}]���85-���[���������l)���+�ftl@2
�D6��& 	u�C=�/��/'O��tZ8`���������E�9�<��U��}]w�K_5�J>|�#�DE��J����}���������2�M@&�	HFB]q����=://���+�>����������9�;���U��}]d�9b��VS������*�>��s\���Z��"hF�$#��Ld��l��PWddd��]������r�,�Y���T��'�x��U��}]t�faj���s����3���j`8f�1�g�6:6 	d"��Ld����V����G�+�C�������{���f�rg_�=rY��.wp���F�������17
�A':6 	d"��Ld����V���_����f���p�w��76��;��u�j�����Wgz�Y��p_��K���x���u�uW�?'HpT1-|���+�����/�������f�rg���������j~ud�>�W�0�=v,%����#>��]��\� �Q�������sefff�����������Y����E��OW��ss��@T/��!���zkyF�]�p���H( �d"��d$��*�6m������s�����;�7j���U��}]t��;jxuy���+�n���!�����������H( �d"��d$��*������r�����/_���~������R������.jx���Q={R���IAM��I�]��c��P@&�	�D6�HhmU:-��q�se����������<�Y����EFb��jxe���y@�"��+�����]wA���
HFB��& �$#��U��0??��Gu����{LLLqq���]�vu�y��Gr�yv�J���+���������p�hpQ�����o�9�L����
HFB��& �$#��U���i����u�]��-��f����u���[�����������_m������FA�$#��Ld��l�����jZ��i��-Z<��c��s��O>��C����{u���q�upx�65�:3�=�53��������|JwA���
HFB��& �$#�����U���t���dM����>s2
�A:6 	d"��Ld����V�fV��~�����G]����l<U��"h@�$#��Ld��l��P�Jh��jfu�����i@����M������������2�M@&�	HFBQ+���V���	��iXR���.��A�
,����ktl@2
�D6��& 	��rs,���J�U��Mv�����
��i��.���tW_�c��P@&�	�D6�H(\w=*^M�.�k����]]���g�|���"����2�M@&�	HFB�����Q���n��.�!J��Q}�F���

���2�M@&�	HFB����w�Q����.�!��|��
����b���"����2�M@&�	HFB����~�FU'��������lh���mZ~}���"����2�M@&�	HFB��#�MW���3��.�A�����C}Sf��.>E�$#��Ld��l��P��x�QjN�r��r��	c�����g���xaB�$#��Ld��l��P��l��jN�������2s#tQE?��z�����"l�+�����H( �d"��d$��m�V���/��.�����#��������W��R�|���f|���"����2�M@&�	HFB�"�0����!�����"����Q�l��V�=������,�$�������f�]|��
HFB��& �$#�pQF|��P���]�[��-��(;*�i`x�������Y����S�uhX�����
HFB��& �$#�p��cQjB����r��8�~�g�9a��+#q��*k`�vE}�-�[�+WwE�:6 	d"��Ld����EC����Cu�Sf�w��O�����_���_��a��]ou�^i���i��.>B�$#��Ld��l��P���g��x���I�����t����o#��7�a;�q�����������*��;C}kzMJ�4tW_�c��P@&�	�D6�H(\t|���i������3�[��'+�R���y�f)�m�c��6�V�*�z�����i�f�I?�\C�$#��Ld��l��P����q�O"/����X���]+�2�F��i���Yp�~���moD�wE���zf�5����72c~d�������H( �d"��d$.:��5�:����rjf�l��}�[
O76�����(4��,����6.��pW�~0R}#��/,���+�����H( �d"��d$.��r'5��zIw9����#�TrK��O*���"#i����w�~�13u������[�7r��^�/��������d$��l2�M@2
%�,}�53%Gw9U2S�����-�Mk��3/�~��+�Tr�;���"������q�7���'��^G�$#��Ld��l��P��r+W�
Z�`�|���l?���-���;L{]h����Ya���Qt������~���2���2�x���2�M@&�	HFB����+j*����r*a&��z��d�3?��#	�m!��T�o��)�My+�T���n#.&�+�w���H( �d"��d$������J���_w9w�$�#^�pK�����xKaf�Y����������+��c�|Q}/�-^Xu _o=�6:6 	d"��Ld����_mVS����.�����v���o)}�,����l�s��y�a����Rb�����5���b�mtl@2
�D6��& 	�+NO�B��}0Ow9?�$�#�W���!�����r������3~�������"c�4����=53�/�����d$��l2�M@2
W�9E����^�����������{�,���S���mG���S���7�{#��YOU_��v/�>���hx���2�M@&�	HFB���������ot�J��$���������F�<�������m��*��rXS}T@�����y���_���3tl@2
�D6��& 	�+�wy����!���0n.��M�4����0�������b����u���87GS���AKm�y�$�c��P@&�	�D6�H(\q�uP��w/�h��(����-��6�?s8��R��u�v�w>�|�q}��K*��]�s��������c��P@&�	�D6�H(jd[S������ze$.�|��-�a���8WR	k�=�y��":8lY>+�HOK��J	l��V
D�7���d$��l2�M@2��\KP��]l����.�n?���-��	5�RX�i7�������"�������{�T����7����1:6 	d"��Ld����F����$�L��}v^#���G+�Rh^�Y
�33v����jC0�����_}������J����fx���2�M@&�	HFBQ��u�K��H��,�n�pK��F�bA�VTo}��x3������3�b��wt����/������2�M@&�	HFBQ��y+�$*d��^>�i$,�x����lKG�u/���b�����?��f�9/��Ln����f����	���2�M@&�	HFBQ���3K��S�{�Df���o�|�H\���z����v�7w>���q�+��4e�D�5�xcz�U�M��+:6 	d"��Ld����Fg�W�$���^:������-��E7�tF�2����.�q.���x�������.��E��N����d$��l2�M@2�����C�n;��S��;*�R�o��W�|��S)�yL��1��O�_3?�g3RZ<���%+/y�,���
HFB��& �$#�������*��5����m;��;Fj�mE��?���
3'������[����W�l�,���Y��5����#f�j���)~��M}1t9�"�?tl@2
�D6��& 	E
L#9�i�*5�QrZ���`D�+����������(�j/^���o��m]��K�
]�?6�tJ�gOg�_���s���������o����;��M6<{|hG�$#��Ld��l��PT����Pq���=||3s�m�=�3��<|�
~�q���o���[^�1xe��,K���j/�_�S���S3�z���$'�/+9���2=xpH@�$#��Ld��l��PT/#��@�����G�����[����?�����������~NX�V�1�g{�VC��2[�C�~��L����;���M}_�>���#C:6 	d"��Ld����zWw(}!�ko{�����e�A���s���W2�nM<�y������6����������w�5��[
wY��#��y����O���cG8�b�����s�}m��~V>?^X����H( �d"��d$��Z�^M�����#������[:1�4��W�
�������g������+.(�����N�}fC�Jg���c��M=�nM�\��W�?���G^�Ru�������DX�?&��c��P@&�	�D6�H(�>e��>���c�5
��bg?���k<v��H<�cp�������s���+�����m�v�]���w�����[�\wj3>��<p����������6���R����|���5����2�M@&�	HFBQ������[8�[O��<��3���Y�<u���o<�Q�A_�]��L�p� ai��S����}&5��E�9�e���RW�9L��%������|s��#�#tl@2
�D6��& 	E�"{��FO����1��P��_�>�|q�G["��;-����_)7�k����/���~w������jn5������,{Dp�����;,U��X����J_L�R���<�k�C�$#��Ld��l��PT�b��j�v0�G4���.��7�=��u8l�}M��f��*7�k����a_�X�=��������V������VC��>����;f���`f���N3?/9�����W��@ :6 	d"��Ld����z	����NW��r��������13p��N���Vz�����r<r�%�v��V�o.n����VC��Q��?��T�/��)�._4P}k_���G�Ltl@2
�D6��& 	E5LK�:%=��o�{������0.�u��k9�o�\��H��������c���p���aijqDk��l��O%��q������������,~����c��P@&�	�D6�H(�aM���N1m��nM��T��Q��?:ln���c��yvY�
����z}sq������eYrV�l}y���n5��k����]���4���e����/f��ZUeO�/�>���n
�tl@2
�D6��& 	E5�B#��)�SO7�f\����L�V�C�����7��w��\��]��.��G�s:%r���M7t��V���o5<����f�>��'�|*�~���Z�s�[�N.���N�	����H( �d"��d$���qPM�����;�2�/�B~U����u>�������W��
�p��5w�t_�%ge���w��V�.��Y���W�Xn�����S��:�~7f���������B��O�C:6 	d"��Ld�����W��w�>���L��|���S~��)>/��#�T�u�1h������S"�?6��[
��;�i3.���������7s�\)��\X��iZ�)���Vtl@2
�D6��& 	E5�g~�&N�F���q��yw<�����G�/.�������o{.��d5���2������L�i;��7�<h$,���v{b�f���z�K3FG�$#��Ld��l��PT����j������,�j;��2��v����in������~���G�d���;N��{���jn5b^xzL�;���nZ����=�g���X���zk�"�tl@2
�D6��& 	E5�~_����N�0�a��c���uX�\��l��{FV���76:�J�����!G�VG�%��Z�E�+b6W{����9���{��F��������w�����^}}g:t�M6����tl@2
�D6��& 	E5�{�W�������F���.#i��;&���lV�yZ�m��q���g�:N�p|�_����iy�A���:V���7�q~�#�C����L���V�	'�GT���L��v��;f������9)AMJ����Fw$x��7���d$��l2�M@2�jDw�����Gbk�Q|���=��+;�,�"�>��[��s�/�Zo�[k]F9����'9��S������_9�����u�����q���N�E�����a���n5|e����;��jh^���k���}Fa���������Y����{tl@2
�D6��& 	E5��	T��k��j��=�]���u��~{�a��v���~�f�N�M)��k���|��v�c��5�	�ZF>����cU�������-�G'�#FW}���_�pr����?mm1�?�|�/fA%���U+�7��+Cn�������
HFB��& �$#��������O��6o��g���f��;�KX\��Q��{�}������#3j[c9����T>|�n��������pu�������&���,��<��jn5��{�������o54�W�}wL�<�����7��i���g���u�2B7:6 	d"��Ld����*��t5h��*���]i�d��'J�|k~�������������o��f�;����ql�c���|�7���M�K�/�Ow\:�8��c����;������39V�u��r\���U�_t~�����d�+U�j������f~����)�T��!�����w	V���Y{�~1!���2�M@&�	HFBQ��s�j�t.��Z�k?����8����l| �T��p���ma��[Q���Iv����D����2�Q�S�A������;6v�}�1�7u���������}���7]�?�j�~��jn5\wq�����?�|��YxM'~�L�=~��#/F�gtl@2
�D6��& 	EU��9��L'�p}G3e�w���S���N���n���7�S�^wb���~_���9�9��u�{��Tn���^��y���nj�cu����cf��?�x`����s��:��0�'��p�a����p�����f���#X�N��1�u��k�:~v@�$#��Ld��l��PT��7;���p�1��V�a;�d�}n��:�*�f�����!X�������c���8���Y���s��u,�q�t^��G�������qc~��cVS����s���>��~��p�K��j�����������/�=�����a+���E�U�����/|��
HFB��& �$#��J���j�tp�t��G�y06�A3?��-w_?|�����k�R���qx�c���|
7�1������@�������X����{��q~��|�3����9b~�}[����::��[
�O��(����4�=����pu�h�U���w��F�$#��Ld��l��PT���sK����te3}�� _�V��;�l��K�Q����k]bv��I`U��M�������Z��r�n?n|`��G�g6��r�������������k�,��V�n�������o;�O��'�����=nf������
HFB��& �$#����w&������y��v�_��k�o�������F�;��V�����q�v����d��{+���ov���������o��$d��W��l|�5(u��L��c���5��~�B��v�f����p����.��N����L
l�}_�?�����d$��l2�M?`���J��p3�h�����u����f�\����81��%���[{���������-Y[�g~�J��Nq�:V��X�<qIc�rcq���*,�v}�;����+j�_*.�������������.�>�S�'e�i�6���;�������������\��x��Gk^��[~7��d����Q����Wq�u_������
QS�DBQ�3}�V����k���1���������n����r��}��]���;"6����������~����+�������Y��}39F>\��a��_���
S�}�������o��[
W��?7:����������M�l�t�O������%����=�?-�q���?-	�Fr�Y��be]����H( �*g��1�q����&��d��/����K��o3��T�$������?-�>�xp�Zo�w�[g�|�q`���]YbVw=���S�-�K�G�kznn�j�F�s����s�rb���.������0�\��?�&W�\��������x�����'�����e�������������F=�>���K���]]F�_�;RXX~\NM�g��'*�J5-�
��ak{���?�>�|��J���������
�n�z ��K���~�����_��';�;r�k�e�������?����c�����-����wf������s�2�������<�{�������+����J���K�jk���j��������ABd!Um�D���P��D�HB"�D�]B�$d��/�N&gN� ����|�<s~�;gf�|��o���z�����.}FN,e�����8m��'J4���.^"��g��+�������R���[N����CO9,��+t�W�0�S��7bI��e�2}Cn7r���n�������3��H]+R������@��P@�����~��������.$�?r"awd���'nSd�r�?����90+|��_�v|�OF�b�}+�Y��,����?�����l��Y��s��:�����&���ax����"��u]�{�������
<�A�k]c�Z't��R���	u��R[?�'U��X����XI����"'V�<�\��I[�0W��-�N!�x���B(�����[x&����Y�n�'���M�f8gU��Va�����`��_K����{u�7���MO{���������@��S(=����)��A��Kc����]�#����]���zZ��<������en��{6���b�����j1����,���z����T�3ft�t��d���y����7�_}�2P��i�{���=y���pw���g�������?,��>����j�5[�v��l8�.������5���rq&#�|n7������������b/3;��;6����9|1�O��Lx���#�L��E!;f�m�"%t��A�f��]����[V2���l[������6��}Y'g��;�|��O��W��n���"���{��$yU���������y�$���.[���Z�������ta�K��9yQ1���FN�bz"&V1|�t�[�'TO��c���DB!���Z�g�P��}�c]���u�����{���Xxj�����6��^�5������T�v�'�o,��^��9_��r�Q�p����?Tg��.m��:j|%������6�j.po���d�����5����x�j1���o3[�z9���r����}v�����9'=��]g��o��`����Y4�g���Sl�_��QV�Y��h���;���z������W�
_E�N��D���"��2R��t�[���?��#��i21'�7�WN|�������	��C��Q�	]72x�f�����'K�����?���_�����u7�a�n{};��}s����N?{|�������"�^��y�*e�G�����<����u�����Sk=EO������ �������11��7�9�����m�dZ���RE�!���d(�O��Q<�D$"��.�����s�].�vM�m���oJ��)�������
�K���n�D6Lo�}Z��6�6�����V�h.��^<Z,�l��Z���x����\?�_"�gtX���_�x8-�tZ��i��������z������z��������mTN����3Q���NY1�m��o���S�B��������o�Z���������NM�=�poUm�M���'6��
���"�Rx���L������>�C��29�,|9�d�t5!�^vyh���z����o�E��%
��<�]y��%�'U��3wN}q��z���,�x�&���n��t����������7E���n�O��:��wy���������:�vy��v�����wI��W�zm�������&�g��^�f�[���/�M���7=�^����L��OK��^b����F�4���Ux��i&��h&�B�?"�o,�l��b��W��s���������9�\��TS4�!l��	r�����N�z��cZ]vO����~v�5����f�W6y��Ed�<�<ZnrW�n��{f�g���o�l�����R������7��y��.����]���g���R���a�P������/e�����&����z�l^��{��";W�o^�m�����c����$f���AqQG������/>&�n�����y�����L(J�N�u���065=%cO��g��_��[z��>�tLyS��kw�k'�T�m��m.��W�!�c\��Fn��l���N(}�;����*��'�B!���1�"yl����|��IQ���K�l��<99��E����h��X�JaS�+�����Uc�=�Z����	s�yp���q�<��.�n/�V?���a�7���J~	�z%hV���-����z�W�}^��<����w���:O��N!�v���>�>�����U��7&&|������f�0����EB��:��O����������G>��cB2._�J���/S�EjF�BQB�]����_��ur|����jh3����/z�~���?z�&G)l%3]���|O��������/�B�);�L����>�g���y�$��K���y�t�����z�������^���;��o�kv���w���������/\��.r}Z�[S�nM���\����_��w��f��o�����(�'��B�S��(��N�y���4������d/%n���}��?�c�����������'1�����(q��n/��c���wx��6�w���0�n/��5�����Y-LI���"�B���g������G���.���	s%vn��y=L�q�>'}���������~}a���
�L�����l��%q���c!���L���P�������I'��^�fT(E�����wt��$g�e�{b�Yo�+�Z��*��}��(��8�����GXh�u���.������y5,�R����������kH���Rc3+�����E���u���-�7n�4�����//���|���������J��V����W&=��6R�N���m)���4�|k]��F	y�5������r�����]~o�z�L��_"&US���S���01G&;q��'�k�w��sz��i
��	�V?xz����i��\���694���3Z��;^�A���"�����(�o������R�~�,d^�:�O����hP��o�.��fV��6�g�m�Y1	[��}�csu��+A�c�hd����.f^����Z����zP'jP3*�BY���������1�'����J�]��{�V�"��*l"|��;;���16�5�s�B<_�_|�����})(�����������"����_�5K$q������Y5L�������;q�'g�v���g~�p|N����$�x5a�+"������ zF���^<;����/�q~�����\�&�T9�\1ib�'����OM�b$	S��;W���&�0���5�<�c����k���us��a�Kcs��q�kn��7�4H�{��3�����x[�����p��r�z����.�K�P���m��'d�����,qz�hY�WL�Z��r�csl���-"��N����3n�������9u�����/�3�Q�9�s*@��M@��M@��P(:�:7�[������2v��=��|��9����
;���'_==U�r��O8�F�7t��^h�x�����SM�X�'J1�����T�:Q��:Q���Q�P��[�;���+��:��'��f=�\��"��
�^���k'�+'�h�^��
�>���(��<�8bjF��Dm�DmjF�B��A�r��d�f�ig2v��=����4����*|g�W1����,�y��~�pt��_
�1�=����Q��:Q��:Q���Q�P�w��[���������Va��F��t18+b�~��i]��O�Y������S
]^�^�0���k�5�Bu�6u�65�B�(�g/]���!���d�&d��u�/-�;��o��u���<�]��i�Z�K��i!0Gl@��P@��M@��M@��P(:����na��d�������Xx�emv��������
;���p�l�u���UZ���!����b�#6�fT(�N�&�N�&�fT(]z���[�~���U�wc3K��X��2#+����u��6k>��?�0��v~O�)�n�i���,0�#6�fT(�N�&�N�&�fT(�Z�g�k/�*3���C�k��s�-�������j���[�+k����p���#6�fT(�N�&�N�&�fT(���'�v���s,#�:���+!��:��D�*���S��;��#���	�����.���5�Bu�6u�65�B�H�-<��W����>�=������������U����n=x��%w�h}:�O)�t���V�9���
�
��	��	�
E�nah��������t���������Z���>
��3/~�v�C�>����uc���E�x�b�#6�fT(�N�&�N�&�fT(���!�8�3����Xx������W8��jmV�v����<����h�o*���5�Bu�6u�65�B�(�[8�����������Q	���3]����������/��O��7/�C�����Q��:Q��:Q���Q�P��N������ou��[A�t�4T�*�����D�w�<}�o,���9�@��
�
��	��	�
E�n�1��9�72���u����U�j�'O��z���*�PCX�(n8bjF��Dm�DmjF�B��[xb����8C�*\������
���6��*�xC{;��Pq���
��������
�"]���������jJ������Z���U8*``���y?�����[E}����#6�fT(�N�&�N�&�fT(����N����'�
�vZ�^�I�*�r�G���i���}p���;Plq���
��������
�"]�0�����&R�p��Mu���~�<��.O���cm�����@q�P3*P'jP'jP3*��V�����N^'�
���Y�Cj�����2yZ�K����@a��
�
��	��	�
ER�����2C�e��|����oK����������*\3\��]�w(�8bjF��Dm�DmjF�B��n�������oj(�
'�qLa��U��E}g�
����Q��:Q��:Q���Q�P��sk������
�^���=��h��O(�sFQ�S��#6�fT(�N�&�N�&�fT(]qj���y��R�,��{�����L���O8�B�����&���P3*P'jP'jP3*T�v����{wkkk���/�6���+N�nO����r������NS6O�ptm��'L�	Gl@��P@��M@��M@��Pu���/Q��&/1�`��B]W���o<(������*��E���gxp�Gl@��P@��M@��M@��P�u�����F����OLL�����={�{{{�XH�����_��r�s^�^2O�pNG��+�(<1����Q��:Q��:Q���Q�*�x�b�F��sg������-[���7����B�m,on�^����@A��
�
��	��	��B�
�h4�-�������a�����6����*���J�����0p���
��������
U�V�Zi4��G���������������K�V�e����?�B�P3*P'jP'jP3*T�4MJJ�l<99Y�W�Z������Va�����M��
Gl@��P@��M@��M@��P*_��F�1�F���T1nmm]H��;���vx��%���~�*����Q��:Q��:Q���Q�*T�dI�F���-������BZW_�v�G��8x���'�[�6e���h4iii�q���
*����z�@�0����^��F��v��l����b�f����.�i���F�9v��l<""B�;::���f����f��%�����!C����f��5����I6��C�N`A�@m���koo��hz�����.~���K������}����B^^^%J������&�?���k�����S�����j����[���@��n���P�]�vu���Z�j���+VtrrZ�j�����ww��������Z����/���M�	�5eZHHH���-[�B�.]�DEE�&����bcc���l���o��u����6����Z�`A�v�lmmK�*��qcgg�{����Q���]�re��!����j��=r��7nN�<�������$V[���
���I�4J������l�4�%J����Z��7a���LKHH��_=�!qA�cbb����'�����g��jq���5j(v�M�����>����:�7o.�U7���/%%�~����h���~mj)O���/_.���UXM��`�)���S�,--�����?n�81"�}}}�i����������8>x�@���������Fn��uM����_�����KZ��g�X����t7*F�T�r����uEe�����-���&P$F�-����[��������_���?j��%��+��<�"1l�0�?w���������Ro��1�9�'`6~~~�KK�na�V�"
�N��]����C6���.�_{�5iq���b�s���s233[�l)�7n�h�&L\��iu���7o����],V�VM��;��#Ff��m�oP����%J�'�O��M��.^�haaamm����?,vri����t*��'t#QQQb�v����0�������J��e��Q�l5)�`��T�\Y�.]�$ONN��K��
$-Z$����+��
f�&L\��iVVVb1++KZ�p��s#���[����u���;s�&M���|�r�'Z�&`~3g�����O�<�"Q�T)�K��_7".�1��<3(_���������-,�jRD�@�:����I��b�V�����Ge����������L\��i��W��S�o�����Nvvv������?`@�����^�������O��M��z��!�g����4�(����?I���b���^��P���)Sf��qw���*=��t5)�`�`-X�@�z��%-:88�����4���U������8���>�{����b�����e��i~������5�b����\�r�
�hQ���5j�H�����������}��e��m�~�z�i�'P$����y����H333��?/}�����n�	������-,�jRD�@�u��8`�+W������t��9����b������L\��i����/�������+��[W���m��=j@m����m���z��Y���-j0?{{{�K���YXXh�rvv�M�<��2g��
*�
S<���O*�<3S�l5)�`�����w���r��AAA���%K����J��������M\����P��Q�k���;Mf��-������rHHH���D�K�.QQQO�+����G��o��Fff�4b�D���O�����K��?�9z�hZZZrr�����Zc����4�(�*�{�=�:$�������us(O����^M�(X(�q�5bcc����N�"�|��-�Hhd�&��,7q��m��b>��� �������g����/�����2""B7h�D������Z���F���{{{��>�@Z�<�;z���{+W��b���W��g�III.���;����i�'`f��B3T������w���2�|W�]�]�&O��x��5�l��u��&&M�$�|������_~).���_�U{����}�����(v����N����	�_�J���{��y���3g���VZ�<��������t�R�����5z��Myf��-4C5Q��������I�~��G�k[�n-�:v��l<""B�;::����>�M$%%���XZZJo0�S�����M��[�ni���*�9�yi�	�_�-�@#b�T�R�"�	����7|�/}U�n��<3S�v5��&(X�[pp���C�%\\\'8P��,Y"_�p�2d������S����C����K���IeeeI����bQ���C@�L�R���
0@�����'$$��z��I��'`~��	�+t���k����VZ�<3S�v5��&(X���M�J�.mcc���5k������l�C�����X��nB�4��r��]�|Y�N#�}���x��
���b����	���������G������k
�0��m���w�����e������[K��'`f���B�&3������7[[���#����koo/�u�{����MOO?{��%F���t��gY��nB�0q�D���Yb``���'���d�D���/++��7�;���CO�>-��������/[�l�R�tfNy������F�s��=s�LFFFJJ���+�� X�j�4���L�[X��d���`c=z�������exm�%����7������8M���#����+����������k����S��/�������{����R_�&P����'+
???�i�'`~&L0,
a��q��(O��KI[��D�@A�>����k�����S�����j����[���@������uM�&�����-ooo�xDD���xh������+�Y�b�Y���
�xu0q�����.]�J�*b�

2�Fy��s��.]������?��;vN�<�����ZM,������\l���B����������e��	��j�Pq���-,�;����[��m��-�s����
�_�������m�-\\\n��-�v������UKL�^�z������es�o��(DDD��j��)���Wo��qw�������Uqqq�g�j�222d�#b\���y��a��a�����8qB�W�T)++���*��9|�p���
�f
6LNN�M��o_�
dsJ�.�y�f��vM\q�������im��y�����n����}{qa�����a�1.����o����bbb�7���.������g@���m��h������z������7j�H>\�s��5���A�?~���;{�����o��%mmm/]�����[h��.\�������(�F```�:u����k~�
._�\\����lB�������K7b�����^�������M<�ox��.]Z������FDD����kK���O��F�����7���	&�Fd�7W�4i�X��������`1��i��6.��~��-,,������VVV���iii�1�fxx�i���n���+%����b�a��Rsl��e���S�#�Yw��)�xTT�o���nD�|3qEGGG��w�^�w�x�P9r��<c���3g��?I�p#�����%K&%%I������!P,-\�P���j����_��k�J(���W��?����n���f��U�T�7o�4~W�-����5j���Y�fb���c�mDq�'N�~~~�b�n�����������k�����W�~}�9�F�~%K��mJ�|3qEKKK����i�~>�[���l�}�����������������������iiie���aaa��Pl�={�������W�h��1D�Rc������f����2?�����E�4��E\:t��<o�<#��)4i����"::z��mbB��������=�X��q�F�)_���(�y��e�7Wl�����DWLMM����X���*W�lccs��#���N�<Y����g��u���_m���@���
�f���,+V�(-���b��W^IOO���d�1��gO����f���F�2����$_~�e�H�%��l��6l����y����+���M!66V��+W�u�����5k�@q�����h4h�i��������������;b�w����.����''�C�������{��VVVQQQ���zq&�_�T)1m���III���������M�5�
����{FF���h�-<v�����?CBBd�W6_q��W^yE�lii��wI�@ZZ��W�h~9��t�6o�\�L�i�/���a���,X ������)##C7�C����w�����tN�����W�����Ul���	�H�8�y������6mZ���������_�M�������Z����lmm�}��;v��(��LYQ��o_����������}pqq��������?��B�
�K��[���[�����g�6��|�mJ������������!}ta�%N�8Q��@Q����h4=z�(�;��$''GGG��YS�������Pdt_z��o���/�R�
��+��O��w��}���?~���
endstream
endobj
7 0 obj
<</Filter /FlateDecode
/Length 141>> stream
x�����0�w?��H�q\�gG��:�}	'��!d�l�Y�1���MR	8��I.is�m&��a�rL#u�`����#�k�t�+��!�S4�cF�\��w�����n?"lj��,����z�V�)I.�,�/�}�����j�8T
endstream
endobj
9 0 obj
<</Type /XObject
/Subtype /Image
/Width 1722
/Height 948
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 73593>> stream
x���	�\U�/�0OG������G�E�QgDGdgGa�AG@�mGB�-B ��%$@6�6Y���%!a�Iw'���{�y�s�ZU]����u���}|~�[��sn���������7�����Z�.�Acc��w�t�I]]]����
K����o�=w��s�9g���#F�8���'L����Od?#Tw�:~�C��O��?��'�p��u��l"���j�b��>j��3�<s��)w�}wSSS%�����U�XDo��@����X�`�)��R������s��i����/e������>|x�j�s�=7�]�M�����_�>�������G)��P�p�r�(-dd�������y�������������&�c������W\���C=T�����}����-��^�z�{��;�����+�\/*�4N�2��VB����i�\pAGGG%�����V�g�B�g��������s��Q�>��bZ��y��I��&Lx���6m�������0�]�J=�������b���F������VB�P�p�r�(��3*���~��<���Sv�Z=�}^z��\���W��dc����Yx��Wk����s]Cy�Qn1��b������g��bC�<�L���g�]����vuu���777���kw�u�i���.>�{����U�c~��5;u��>��zk��7�pC������ ��M��a�������O�������c���[l(�������<���c��M�Wyy�V����1������V�s���??��%K���/����00������(��Z������1z������|��y{e�Z<��SI�1c���Ko�������*�@]�����
rW��1���P�uw��<�5Q�>�>�vww'7����%�z��r�N=���W����@���SQ�.Em�-�M�T�`p+��Y���[n9��sF�5z����?��{���iSz�W^ye���g�u���#O>��P��;���-6&�����������_�:�d�<e���s��y��gJ_����o��?���a��ch��3��:u����.:���<h����\s��q�N:��O<�7����i������2��������{��y����-�'y-Z�����/���e��z+V���w�	o��	�� ���n\}���/.��
�Bwww�$L�>}����~W�G�����/�yP%�Ba����/���:}��\�[������-BL6n��[���� ����Q�?�K�Gy�gT��k��6���n���^7�xc�X(_XI�&�(���|x�����?Z���xZ�9����e�����-���A����Oe������O>�n�
��\���a������)��o��[C/������[t�D���	T������f�*�c���s�=�WQyM444\t�E�����8�.����7�2eJO����g��������c��+�Xz{���v�m��/�nL�4���l��E�U>?�������	z�����>y����}=�mmm'�xbn�N8����h���'�|�����Y�vmR&��\~6�O�����m�������/g���]�ti�����oJ�^����[��2{�u&�/���rv)*��V��g<��W^I�"�W�(�����o�����ho7W�`pKO
��Q�
�������'�(3f������V�}��#F�3�=z������vww_r�%����"h���M���������/�H&��0����'���I&�}]�����,��~�
7�~7&N��wP�jKW���e���9�t�_�����//}P��Bz{�}��T���:uj���?\�Lz!���//Z��L�L�6-�>�O���=���(������,ttt$K�o��V�]���%C�-�UfOr����Y~�����Ko"�hm�E��5,^�8Y
BO�{���������o��������&;�����fRa>��o����������.p��{�z�y���\�2L�����t����?��0%I_�1y��^xa��
]]]mmm���s��/c�?~z��&/�t�Ia*�z������7���kW_}u��P[�,��������+^|�������0m�={v�<���^��7)3f��%K���V�
����P��0�+qS^Qe��z+6����Sso��M��.]�wi�3�<S~�[�[�8����	m��q���?&L���>K���Jt��YH��|�*;�O>�d�t�+WC4�q1bD��/������E���V��oH�}��[���WaO�j��7�w �����M�	�+��a�	5�z��I��/���#@"��VM2�l|�����2�'E����j���U���&;���7�X�`A^����D�2Qp�5�$���b����v[�j�����s�=I�����_J����>[�o�r���X�H�~��wx����'N,Q�����;E[)�}����j��}���Y^o���r�
�a�{�9�$���rZ�b���<)p�����J�?'M���<yr��K������|�*;�aF�\��Q���v�dY��G)�$��7T��JK?�?�*U�n��G�l���&J������s�=��.��Vr1[��*;��z�%�}�G�&�m���{�O=�������j��J}hJ*l����[zj�������K/��.s��W�y������vZ���{�V�XQ�k��I��5*�R�g��>�s���I��+=�innN��%~%l���I%���Zo�_u�U��P����0'���e��z+��~�E�7�(����t��_M.���}����Y�vm���wUO�g!]��>�e��\��p,\m�3gN��3f��Q�^���x������y���}��GQ���b7nL�������K��O.�+���>
���;�����w&��V�2���=o�����c�666�q`���F�D�������B������.S�����x��V�s���0O�t�i�%/����%���,X� yu����U�l����-���[����W�:::�k{z{�@	e��z+�������7Y-������K�z��w'���3[T�X1��F���B�d
?��������Y�f�_����-�^555���@�]����1��5#y����r��1��4����.���\�=��p�~�p����Q8Y�'O~���+|Sb�h�*�y�0aB������:��-�g��S��������k��	���a��d�������?��!=�����g������`���IS����I���]w����'�&��0��`�2OAo����>�z���sQ~��_�����W��>�����wQS�g!]r�?��j�u�����G��$/�h��_r�%�������������B=������?[��}��GQ������t��s�[e����V��n����-���U���M�81`�����o��e�`pKO
z������T�2%�[�b������/�0�F{���wy������5j��i�{��u�������u�Y���7g�qFo�o�3��|���z���W��e�������� %�V��o���g�yf�jSSSo=O�hV�>��g!]r>����\��^�k����r�����g�l��
O���?��[�0�H���J�G����[�vmnK�v����%��H��\��-����+�m��U�=���3�O�����G�VO�P������o�*e�`pKO
�W��V��z�x��7rOP-G����-�mi��N�8q������$�t�J�X����U^�\���/T�{�#�b����>	e������Z���r�KI���,�,�s����e�����\?��#I�s���m���N��r�����R><	H��3�������TRC��(��a�b��w^nc�w���[�]�W��2{�x��W����[�C��(��V�2��������q��*�F�k�I
Ye���T_f��%�
ny3�0�
s��c���a�����'3�B'�xb����6}%O�B�����#��)Ho�k�VfOz+����J,T��o��}�}-�U��T���_��ic���mL�?�\�*O��.\���e��O?=�%D����x�U*�Jw�w��]n��i���S�N�m,�{z��Wy����d������G�V��9���1c��i�3�_�}���{����`kP�t��2---��Y
{wt��W���a��(;;;�i%�%_|���n�)}_[��^XbzUX��Q��WK�"K�j>�<_`�����P��[�2���K���x���h��MI�>=c��%�*��������8����L�x���?������W\����������_^�qUYfX�2��t'����Yn�-�*���y�GW��2��<����.�z]���h�*���w��u�J�{�����~�-S�k��L�,s�-�$/�}��k��)�=��2'&aN���^v�ey��y���w>}��;��SN�y��O%?}_�$�
z������a����B��4khhH���M��/�dVezS��.\�t��{�
[����s��%I��~8���Nhoo�������>�x��a����-v2��L��1f��>��_-*�,��#G��WN���f����Jo|�����X���r���U*���A9��*�$��5����J.�����@��]��&4W~�/�������p+G&��p���X�~�a������w����y ��^���/�<y�������g�}6)�~�B��/�dVe���\���K��W\��������#�g���9)����r��{�G���_��r�T���;wnn���^��3gN��o��OGZ�������SN)s��q�j�����*�x�g}�S$_����4�R��_9��*����X���9<�@������3&����Pt�0oM��]�S��w�qG�j��a���|*�������%?#6�������X��2���K���L���Y�)��k�I��z��t���Y�)*�s�3i��\U�G�~���r�������%��X�hQr����^Z����?�(����_�;������O;������G��*x�����e��9��V�3�~������5�p���:����U���r�U���*V[[[���9�+Xf���l��Wh��uI�0�O����������v'�pB�/�%�~������S�<��%�5(��Z[��-8��������;\��T�{�W�g!|Z�L��L��� ���kt���Y�)*�s��^c�7o^�,�+��>�/�z�����Y��'e�^�XWWW�cw=�P�'�|r�:J����a����B�=Q���?Z1d<}���?�������uP�7Z��'���TY&�Bu�m������>y��a(���a��l5j��U�
[�?~Rf�����?\�~���}����7���%�@cc�g�������L�V]tQ��0���p�IO�9��������o�����9]���l�-V�^m���K���L��w����>���LQ�����k�&��&K[�I.9K
>�h6G��d���K�={v���������J��Igggss��%Kf����=�#F�v�pQ��b�������N?���wL���A��h�������TY&}Z�K��7/��������y��0#V o���z��.�����PI��&��\�+V�H��~�d���[�.����/'B7���S���P,�^����{�M?O������V���� ��;yHt�{��tg�?��e���
��}���_|��w/S���eHe�o������eE��{��%K6m������g����#�z�������Y�)���N\x����}�nwww��a����j��d���K���^V�JW2�
a�,����h���
6��������:������>�X9S�*���`���������l��c��0���U��0M.�7}�]o�\�lYz��s�9�p^����,J^N�'a����
s��'�
;\��T�{9�/^�8���)1b���>[Y�����L���u����K���n(Z,��,\���
k��d���KkooO��j�p������a��>}z�]�%����G���[��5_�|�����g`+gjP}���~����O>��G����z��~{^
���y�����o~���M�yY�j��:���o���_������,��)��������*�0}']�g�������y ��^f������g���)/���Y_�/�dVe
ex�s��Y��I�2{"��m'�pB������?Y)��-�:ujR`���T2��F������������C���x����:=_�������dR&������0?:���G�q�i�M�4��{�I~9��W^Ij?~|a
a��|��9s�L�0!L���
�����/Z����-o~������J�5*�u�)�}�h�?��f��=n��Ps(Z��o{��7�����U�t��TVC�0��I�l�92�\�`���2��:\��T�{��RWWW8�W_}ux[N<��p�@���<�L������|Q��� |Dsu�������%������J�V��'+U~��g�?��CT2lK�8s�I'�3&��7�pC��~��L��5�x��������A��h����(����~�������N����<�����Tm�p�	�o�}�{1�G����;����{�=��������g���k���|�'?���w��K_�����7n�8�=������S���������'>��8`��)aca�����������>>K�Wu�a���;w�;Tc��YC����-3g��u����_�{+j����z�����;���+_iii�u�Z��������}o�_��W����}����������.9n���b�/��PI���IKK��>��0����~�|�����������|������g��;��cn}��}8'�xb8���>��7����x���s�b��zj��6�J��SN9%l?����������k���7�o��o���N;m�{;�&O�s��w��f��0b�~��{��G�8n���������;���^��i��/�<f����z��W������3'�������7vvv~��_������ci��U���/��~����V?�����}���-K�.
[��s��j m�����;���v�i��_=�����-�
`gk`�}�	����.��k�d�QG�\t�Ey�O�81l�w�}��@�r?�v�5��m���+��O<�&�`���[�x��'�����w�9o������%l�a����%�\6��5�^�6m���]w�5����|&lY�re^�����}�]v�@����+c�W�_����8��0�_�xq��g�y&l�fq��l�v��}����PO�}���?>f�������ja���u������T����
��|��d��/����?�cF�X������Y�V�_���>l��s�1a��w�]��V��S6�|���d������A���+V�%w�m����A�������{���^�:o{����~��Yb)1��k[-����r�[��[ouvv�X�"�����M��H��a�p�g�������<���Gy��?��]w��������*n�obZ-\�r��W^��n������<�����93�{�w\�M�V������0�f���p��v��K�a�0mk[-�L���O~2y��_��_\zi6o���Z�V�����g�����},�i�������-�f���C�xxO}��-�oii�}���'������i�z�v�p�vs������]]]a{x5�C,�jamW/^���~7�1�	�>���^~��l����X-�=�w�]v�����������Y�f�V�,X�I��D�Zx���������gs��;�D�����?�3��L9��@�������k������m�][��O~2�C,�ja
W/^��O|�3����7��������j����g����n������o��X-�i������G�w��K�/x�x��f�0q���~�S�
��=�->K�{��?��^x!�F`+Q�������	S�5k��mojj
���c�,���5\-������k���>}�������X-������q��y��x���=��I����Z\w�u�=�����?���;�X��$`�j�Zx���)��%K��?��s[�3�������:X�Zq�7�����8�R�b��k_�Z��o���}��w���R�\-\�vm8����������t�a����>�����GmW�
��s����>{���}��Yb)Vk�Z�����%o��5k���j�XJ]���a��E�������a��{��I���t�p��v�YxC�[o��{�Iz���?����:������x���7o^��v�ay�s?-\E�x���:��p�=�P���M�x`MzUCE��]w�6s�1y��?���YQ������0����}���a�QG�l���;w�e�O|���z������
>��O�Y�O��^x���#��q��|�S�Z�n]�;8������Z��?�������7�g���7�tS�r��O��������o|�a���#_{���.555M�>}�]w�y���/_^���E�����Hg���f������+WN�2�����;��\r��������'?���O���@�.����:t��Y��Z
lU����g�Yx��^K�5�������{��w�[���}l�����7u��v�!��w�i�����sL�R����j����~�_��_���������>��x������pec��Gy�n���~������������g�������������.��w����z��G�{56�_��_��{���_�����O����B�L�y��t������=�y��?��}��g����������>x����n�m���?|����]��j�zs�I'
)�������N�M�2e�m��+�L�<9][����f_�7���������g�����-��q���������&M�knn���>�q�K�,ikk�{�!��-�m�]��?�U��@	���7�2n����g�uV����}.���i�������Lgg�{���|���Q��j�J��G>2d��+V�m_�re�����/���~������S��M�4)l��O����f_�o����!C����,���{��|�����=��a{x�?�U��@&O�<d��o���?��lll�+�����h+��}��jnn:t�>����{.��O��O�R���7���n�m+��}�>ioo�o��>���<����?��?2dHwww^�����=�����f����*��|D���q���n���K�.Mo���?d��M�6���]���~�?�U��i��TP3e� m����>����������?��!C�455�mohh�w�a��(VT5��3bC�$�$�'���Ih���g�!C��|������������~:o��E���/|��Q��j�"g���I(�I6!N�	1��r,\�p����l�����^����;d��+��2o�W\����?��b���GFl���B�d�$�3	��y����}������p�
���3g��!C��g���_����kw���'@=2bC�$�$�'���IhiK�,��>����y���K[�~�v�m7d���~��K�.moo���o;l���>�������	P���3	�8�&�I6!fZ�����)))9~���W��f�)S��+��X^��/Pw��3	�8�&�I6!fZ�����2W����n������?����w���?��������:3,Vt���&��b���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P�za���I(�I6!N�	1�P2����Zw3#6�LB!N�	q�M���������vu�{��b&�'��8�&�LB�Lw��}�j>ex����b&�'��8�&�LB�Jwk��}����u[����b&�'��8�&�LB�J��5�������j\U��� d���I(�I6!N�	1�P������ja�o���U��� d���I(�I6!N�	1�P����+�ja�o��k�#l��3	�8�&�I6!fJV:�-M�6����W��S0��!f
q�M��lB�$���?�dz�0���W�m���u�`�0bC�$�$�'���I(Yi{ta�ja�o���j�/<��3	�8�&�I6!fJVZ�U�Z�p�?v��Z����b&�'��8�&�LB���;���������]]��Fl���B�d�$�3	%+�^��6~���
3���w0�!f
q�M��lB�$��l�3=Y\7���������_�x��Zw��b&�'��8�&�LB����.O��O���fu�!�%[V��{�;:j�G�oFl���B�d�$�3	%+�/�0u�����=Y?��Z���b&�'��8�&�LB����N7^?+��y�������c���v��b&�'��8�&�LB�J������M��������x�������V�~B�2bC�$�$�'���I(Yi>����`�]�%��~��G���v��b&�'��8�&�LB����~�,	�=x_���s��Y0�w��g���P���3	�8�&�I6!fJV������'I���aC�������to�X�~B�2bC�$�$�'���I(YY��$������{�}�����+)����j�I�kFl���B�d�$�3	%+��=<Y�xqya��C�W������-2bC�$�$�'���I(Yi��!�b`����n��t��I����^�n��	���
1�P��lB�db&�d��������UE��/~f�W{�Gnw�w��b&�'��8�&�LB�J�7�9Y,q����.��y�=�.�NB]3bC�$�$�'���I(YY����5����no[}�wz�G���w5��~B�2bC�$�$�'���I(��h��b�k���/<�^Zl>����#�;#6�LB!N�	q�M������u-��_�A_�b�
W^�����;��P���3	�8�&�I6!fJ&�V��\����Cg���g��������	���
1�P��lB�db&�d���������R�.�������������$�;#6�LB!N�	q�M�������%�~�xD�{m�}U�~�M������zg���I(�I6!N�	1�P2���������<������������7��k�;��M�oFl���B�d�$�3	%m�?�sO�	?+��7_o���z��������O�kFl���B�d�$�3	%�����5�t|���x�5p?��s���P���3	�8�&�I6!fJ&Z���g�p�������v�O{v��I��G�{Fl���B�d�$�3	%����,���sF_wo����������C��3	�8�&�I6!fJ&6^73Y�[w�������������=�A��
1�P��lB�db&�db��+�����O����o�sRCW���{��b&�'��8�&�LB���)%k}��\A
�rdRC�S>�P�b&�'��8�&�LB�����M��6^;��Z����X������0�!f
q�M��lB�$�L�L�M�k}��������ya0bC�$�$�'���I(���+wK5��{gR���+�� `���I(�I6!N�	1�P2�<zX���z������I
M�����#6�LB!N�	q�M�����������=�P5t����w��W������2�$�;#6�LB!N�	q�M�����5�8�����,�����~3�������!Fl���B�d�$�3	%��������K+�d����ng�'��``���I(�I6!N�	1�P2�t�������_���u��T�a��L;��b&�'��8�&�LB�D�w�%Y��Z�Ne�l������q�f�C��3	�8�&�I6!fJ&��g��yme��=�HR���� �� `���I(�I6!N�	1�P2��������
g������������0�!f
q�M��lB�$�tu%�|���W��tw7|�K=�(�]�]a00bC�$�$�'���I(������������V������ge�A$��3	�8�&�I6!fJ����%��o}����O?1�j��7e�C��3	�8�&�I6!fJ�:W��,�5}��j�Z?�������6���`���I(�I6!N�	1�P�������c�SMU�w��T�|��Y�#6�LB!N�	q�M���R��%�&K|k~vt5Uu,[�s��Q��Uap0bC�$�$�'���I(�k_�x�j����������}�����������:	��b&�'��8�&�LB�^�C�'��k��*kk<�����7^���08�!f
q�M��lB�$�������<md�����qImm��Iap0bC�$�$�'���I(��t��d}�e��U�����Im��:���`���I(�I6!N�	1�P����k���u�Wmm���Y{<gL&=����
1�P��lB�db&�To��+����������y���)��a&=����
1�P��lB�db&�To��K���
�.����o&�5~�k��#6�LB!N�	q�M���R������Z8��j���j���
���d�G��3	�8�&�I6!fJ���V�sIn�S}����vRa��g��#6�LB!N�	q�M���R���NI�6�vs�6�>���;�W_!Fl���B�d�$�3	�z���H�Z����
�_>���)S.��B��3	�8�&�I6!fJ����_��^��T_����%6�:��
ap0bC�$�$�'���I(�[�������S|���<�T��?��B��3	�8�&�I6!fJ�V���dq�c�s�W����T�p�?l����N��3	�8�&�I6!fJ���0�x��L�l<d�����WdR'�;#6�LB!N�	q�M���R��#��Z�{+�:������B|��L��zg���I(�I6!N�	1�P��xh�u�]kVgRg����:7^?+�:���!f
q�M��lB�$��5|�K��^��
���a��I���?+�:���!f
q�M��lB�$�juw��w���������H���}�j����I�P���3	�8�&�I6!fJ��[7����3����I����FV�B]3bC�$�$�'���I(U�Z��gY���fVoG�����\���icf5C�2bC�$�$�'���I(U�|gE�j��fXs���&5w��|�5C�2bC�$�$�'���I(U�|��dM���������;�����3���b&�'��8�&�LB�R��%�����{�5������
�.��f�SFl���B�d�$�3	�J�O?������3�y���������f�SFl���B�d�$�3	�Jm�.L������knfQ�U��ey�"�)#6�LB!N�	q�M���R��w�\x��k�Z�����/����;����!f
q�M��lB�$�*m�c~���r��l+o8�+I�]�Vf[9�#6�LB!N�	q�M���R��s�K���76���������'��r�;Fl���B�d�$�3	�J���g�p���V�r�����s���r�;Fl���B�d�$�3	�J��<Y�[��W>}J�R��s����b&�'��8�&�LB����.H�6���m��G�d��e�GFl���B�d�$�3	�J�.8��f�fg[y��/$�7qP��C�1bC�$�$�'���Ih_���?2dH��7�xcH/�J�}��|���C��v����~���+,�XQ���W-g��,�m���l+�nk[��^�����������
1�P��lB�db&�}2}��m����j�5�\S�j��)Sr5��-�'O��XQ��[��3~����}{��7qPR�+/f^?�#6�LB!N�	q�M�������/�{�S�r�����e�~�Yg������C�P(v�G,Y����-��!��l��vm�s�\���i"CkO�U�����}��?�?{V#��y�PG��3	�8�&�I6!fZ�w�y��#�2d�������Z�w�wa�c�=V��i���2���zcgg�{���|��}*VMZ{�OzV�|4���M<��)*��d^?�#6�LB!N�	q�M�����O��O����;?���EW[[[����x������*Q��~��������4iR������O��i"Ck~��d5�}�3���q��I�-g���~�#Fl���B�d�$�3	-�����>|��u��EW.\6�����y�����~�����?���|�[�Z�hQ���{��=��Sy�?��a{x�O���f���>����|qy���?�XR����y�PG��3	�8�&�I6!fZ������EW�9���������l�m��v���I��C�����rV�\����S�����2M�?$Y��|�����Z�2�����d^?�#6�LB!N�	q�M����U���o}�[a�?�����744��������&Mz���������������\����7���T��j�M{�lo�o�����;���\�=����i��{�o��2W����ja������.o��1c��c�9&�����?�����uuu����>+��}�������/%KyO>p|>����I����M�(s�����f��e��N;�������s��My�r�}���S�����2����d)osGG���cF%Ml�c4u��
1�P��lB�db&�}����
6�����?���gSSS^�����}�v�S�������:����}����
�.MZY����
���
1�P��lB�db&�}������W����{����O?�t^�E���_���T��j��@wK�<������V����~j�g���I(�I6!N�	1���*�Z���|$l|�����?��a�����/�;��c��W^ye^�+��"l�����bEU�o�V%�x��> ����&�4yh?��3bC�$�$�'���Ih_]-<��C��1c��m���~�O�0!���9s�����O^�/���%�2�U���|���u���m����V������y�~�uD��b&�'��8�&�LB���j����6~�������Y�����oL�0���}�.���a��\����o��v��w����K�����������|�Cjii�S�����/.KVW���l+Ok��7��:_�����!f
q�M��lB�$��z����c�)���~t����b���/,��6�L�2��bE;S���h��do��y�����$i������!��b&�'��8�&�LB���SN�����������v�m?������X�jUa����n������?����w���?������������2��^���<����G9��?+ih������za���I(�I6!N�	1�P������"^�I��_C���4�2���kbf���I(�I6!N�	1�P��z�m=��cF�_Cm�=�s��/���� fFl���B�d�$�3	�����s��9g�_C�o��4�x�~�����
1�P��lB�db&�Tc�u3�E�u��������b�Vw�w��`���I(�I6!N�	1�P��a��do�������qx�V��g��-��b&�'��8�&�LB���)�<���)��V��#��6�>�_��8�!f
q�M��lB�$�j��hB��������Vze���c�8�!f
q�M��lB�$�j�L�M��~�����6�1�����O��� NFl���B�d�$�3	�-cO�Y-��-��V��g��V��~m�d���I(�I6!N�	1�P��<zX���z�=��V�������qsWW�62bC�$�$�'���I(�X;���
^�c�ws���Z�\��7��9��b&�'��8�&�LB���_�,��?������{'y������!f
q�M��lB�$�j�>�������K����s���<������!f
q�M��lB�$�j4���[�_����x��Is�����Al��3	�8�&�I6!fJ5��/��]��w������O�[�����9��b&�'��8�&�LB�F���$�w�-���\��%�5v@7�1bC�$�$�'���I(�h���=��mm��^g��������B��
��"���
1�P��lB�db&�T��+Y*\�����������*����*#6�LB!N�	q�M���R��
�����i`m>������n�F!Fl���B�d�$�3	�b]M�=�"�o_�F�_�����S/�F!Fl���B�d�$�3	�b�+�L���w��4�����F�O?q`�H�!f
q�M��lB�$��u��B�p����L���.�i��GL�	#6�LB!N�	q�M���R��%�&wk~v��4��vu��%~�K����]��b&�'��8�&�LB�X��������k���}�v�V�3`�B��!f
q�M��lB�$���=t�j�����v���I�mO<2`�B��!f
q�M��lB�$����sG�GN9`���;5iw���X�PsFl���B�d�$�3	�b�n������}����a����u�=`�B��!f
q�M��lB�$��m�av���o�
X�����s���
X�PsFl���B�d�$�3	�bf]��������n�+/%�6}���.��b&�'��8�&�LB�����$�v�]:`�v�����^�oz���[[�i�-#6�LB!N�	q�M���R������Z8���l����5i����i�!#6�LB!N�	q�M���R�u����l���d�kO�����{�������3	�8�&�I6!fJ�Z�:%Y��t���lz�E��\�x���lj��
1�P��lB�db&�T������o���%M��=y ��2bC�$�$�'���I(K�����t�����W����lj��
1�P��lB�db&�Tl�/�,��?5�����UI�
����lj��
1�P��lB�db&�Tl�O��y0������������8��CM�!f
q�M��lB�$��5������W^��W���=W6>���5a���I(�I6!N�	1�P*�t�7�����Wp���9���������&��3	�8�&���������~����S����5���D��
���"E��#���;"�B�{������lvg��gv2���d7��<I~��|���1d�3��3;��<�	�	�2t(������g������
W���^���_�
��,C��	�	�&�&���`���o�y��h�Wo�v�_�f�"+�:�X�`z�M�M��C�D<_6�)��O�sV~}MF��V~6���@Fl��C���`z�e�P0
��$�u�C��S�W~U�i�~
V��e�P6�7���`:L��T�ia�����P1~�a���l*5XFl��C���`z�e�P0����� ���Tj�Y1O��9��J
���e�P6�7���`:L���6���FS�������k���`M�X�`z�M�M��C�4��$9���=�J
�7l���l�R�5a�`:�M�M6�7X����F�I]��/���1���s*5XFl��C���`z�e�P0�:4PN�jV-�RC��i��`M�X�`z�M�M��C�4�~�rRW�q%�"x�|��r\m
�2�#6���lBo�	�	�2t(�����0g��
����b�\FKB,�2�#6���lBo�	�	�2t(��������A������2����U�u`�`:�M�M6�7X��4�~mHO�U���I���#�����,C��	�	�&�&���`��+g
1�����hr�c�>q�2ZeXFl��C���`z�e�P0���9�k�v�V��D���i�i�`�X�`z�M�M��C�4�G��1]�
Ze�
��A��J����8Z�XFl��C���`z�e�P0M��-��E�8Q��b��r%��<��XFl��C���`z�e�P0M���rF���J���%_���C(V`i�X�`z�M��l.���*��_t����em�r�
��|E�z}����6�.���LS�n�!���XI���g���R���0b�
�&�&5M9�*��}%�\�E��-��k��h#�n�z���i������_��^��6r�����/�hq7�K��k����b=����p���,�cH��(V�hU��n�v��XFl��C���03^�7��P���/���!y]�"F��
��
����I�c@Kl~����[�����i\�Rj�-����b�55��)sp��T��&gt-�q+Q���T/�E�K��
�2t(���]�5��6��hE����$[K��M�J����I��#�����gI��:���)��Ea������urLj��h����	�p��T�/gt��t��h��J*FH�K��
�2t(���:M-�k��Jw�"9X���I$�7�=���J�"�$���e��Y^JnV�A��1��!�DQ�|I�����hq2);s���D�����b(�[*h��L��'��r�VV"��������*�P�Fl��C�����������~|����27��-n���M�[������A!�����4�����*��0��0w�w�)�o�&q\����S��c?�������Ey���-�B��� &�_��I�x��KM0���x��gO0M������,�[L��1�S�`9�X�`zz$u1��Ir��[$���e���$q
����y������)f_���s��������t����R�Z�%F������@u�-�W�e�'�EC��49��/�)�81Z\K�.<O�����au�e�y8{�i������|����4���[��`�`:�M�M`KS�J!�O���Hx�R\&x�6rI�|I-��|L��^����K�M��;*�T^���Z���s��\$F��������g�1���?1Z|�~�(o�O�_Y��hq��W�����5o��
���B�z�:z������N��[���Q���t����,C��	�	��s$h��'AS�u����L�4E}�
��L>O������}U9�J)�@����~]`Nm�c��{S]*N$.}�+�(F������h���K��DQ������bG�wB�
��p�D��d_H��O��zv�-�9�+{�?�jtMwo���n^E�K��
�2t(����-\3	����PH?K^�|
E$����	j���O�e|��F}@���%�#��5|��I���iDe}�7[��h1D|]��)�� F��o$�_�O
���������e����b��F��1KG�`�;�������t�������$���T�O�K��
�2t(����L[O��PiF���$	I�R���xc�K�2��Q�j|�!YM�m�0�����z��$�Q����.4i�Me-��;3\�O��-n����9�_��g�'����=��b���!��?&�fy��KC:��5�
&��J�t�b������Cz9�
����"0b�
�&�f����f��p%IK��Z$~��/.�O��P�U����I|t����:.{��L�-�f����zz�45����b�h#-���'N�E�)x�_�O
��H��_,[��.g�<"F�w�h1�D�<���8t(�@��+�s�S>�]Q1�=�$mI�r,#6���lBo��2�1[\&�6IErvK�r��"�C�_4������V��*n,	@27q9{������DK�#����i��h1Z\d�^�w��.i��d}��$Z��~��f#��>`�*��9_����x�m2��7{=t(�@��bx������!���KR���.�"0b�
�&�f�\�7������s����hc>&A��4���|D\�?���I\�������	&1��������L����{b�h�Q����������%��F��o����t�~&��������a���h1Q��h�
&hI�����3h�C���"��x��v9��e�P6�7ij��UI�3�����i�I�=T������R�"�/�`!q��*�'��Ppm�)4�>��z����h1A��o�3���9����K��o���m7��H��F
&�b�lR������:Aqd�6�>�t�C���9��Y1�v9D��KrI��w�.�"�Fl���K�������
��'5���
�M�M��5�����rg�%v�"1�
�/.�$���I�e��0���3d-Zr�+����}��Wqj^�;B�-1Z<(.5>O�S�1Z������
�����%�m� 2��o3��-�=dO��.F�
��}|�
&h�������h�C�-�f�\��X�0\GE��\�I�|�
{U����h�	�C�KN�	S����_�O�E���Y4>*�>S�	�i�
B����p	�\���+-��2��~D�j���������ei�IyE�[��$Yqz�&tN��	U�-�����<�P�?�,�����#�Ey�{N���n]N�Aj��g�����Ijh��A��	�=���m�h�Chs�
�4�F���T���\�m��z�?��<��c����J&���~�/�.��=�������$4����&�L�G.��K|���D.fC�C�Z��W��I%1������lH�5�>�`~�M03�#]C:7*��c�Q1Z\,��:\\�o�p�(�D�0>K.�������@�f���"�O������D��	�\n��\�����iZ��*U5���9F��j�����s�6�SM����������Y�Mm�����������Tl����RA�����K���d)^��8n�x]�w����Z�RI�(q��
��{������l����jzyo�����)F�����'��U����q��xC��_����/�;=^��������������b��V`G��	�&	<��v9���F�Ui2Ri��E��-�F��������_ic�sI3�=%���������\����Y�(h)�}�,����S{S],]�������e�#���#�I����{��+9��S\&x���]�r�.����`�iA`]O�M�����k2&���.8eX�)�S�&�����G������h�q��(^�}%N�p�/�B�E����j�4\=/�r���h�#�Y�X�����v9�5�N<8�����<�/��1\�.��E�.}�5��zH~������3Zg.���#Bq����m�r������@�'�P��Tlb�7�KN�\�����K_)N�5�,�)��}��v��|L\&�%������
��C�Qq�`/���^4�?��\o�Ks���%#'�����W�7~�6����j�����Q2�2�q��R��6�C�X����\���������<h�������T	�	.����[�o�'>����%~��I9�g���u���K� �2�	���j����9+�w�����	��cy�[/X���9�9�U���������IXr�+</N��D\&�2��pa��Sj�T�'Z�)H�N�2_����t{�~�}���G	�
�7��"qB����#c���,�b����O�~�C�X�����\��U��H�n;���
�QMy|�-.k�8�����y?��x��6Rx�����-������R��~1��]�>vyN��?h���s��_�Y�b
�2W\��d��O�~��U����������i�����Y�rN=a��qF?)`�M�X8�q��%���s������A�|��lp�0��T��#H�/sE�hQ��"~�-�3��J�F�C�Xu����\�mG��HZb#���fO�]�<�J$w��?0i��g������I
iy����L��AN^e7�����>]��6�m���3:S^���S��a�gr1eC�U%��ri;��z@��I�M�J��#TzRL��c6y�\p�Ds`y*���a��%�O��/�J�5�Y�X�����R.F�!�_���Wg����b�8���\�LG���j�eH���.G�UV�U�{�v9�{qM|]$�����������{>S�)���g�l�?�5X���M�;4"�j]�yE������s������v���Q����/��b�'N��_����_��q��[��(�
2��Y�L-�'�
���L�Hq��u�+��W����iTk�y�!�G�j��k�k�Y)9�<:�U�a�a=o���W.��P^��h�jsM<�W��4�&��>SI@������������Gu��gZ�~��u�������rt-�P��:����V5������$~�'��/lI_��7�!�8��x���i&~�[�o����+������+��u�������7X����'�r��`��T��*��76��9_�x�������o�����u��\ua�V�5�.����9�Y������M�:�\��dk����Z�~vm]�������N�l���O���������=��H��0UJ�B�E������u�y>B�B�oq��I��n"�y�;Y&�9�Ip�`:LP�p�!����]�A��
��Wn9�.zq�Aq��5��4�:��Y2�P�*���oH�\��M'-����������;U��Bu���k��)^�Nl�=���s8�~�A����)��?�$��d���MF����od������;������y�H\'�eq�����dG`�w(�����&���`��Y��PN��L���������O�`�4��iq���4�?1���L7D&������K�V8Fl�k�h]��v�����,�����:��������k��������m�~��>|}:�\ N�� =�[|E����t��>��I���w����)���i[�o�{��#��(���4p�a���6� ��:@����*��!�y�i�P0A��Qr(����]�A���\X�����f������W���'�����������b�!����[Z�~����O�\2KK?���,^,/�~>���s�~�(t(��~���L)�+�'N�Y)�K�+�i8Q����J�_���L�����Y����dK�-�l�ir�_��t(���X����`z�e�P0A�����D��wcU�4��ra��G�.�i.'���e����or��>�`7a��a�r[�~�i]�yq����Q]����K?%���+�����S��3��4	:��V%3!����#=�����	i����"��7�DF���vs�~B�"^�u����
�����8��5�Y����`z�e�P0A�'�P��chVg���l�+Rm���������N<���Rh��a���x-��b�G��M�'- -�LiB0�g��/�Y�y��K\��6yX�{����?}��k*�3� 
��^J�b��~	Sz���q���)����O?���FeaK[Av6{���U�%��&Dz��k��z�&���,C��	�?x����J�*'7����I������a�M�xp4��!����0b�]����d�y���/����Iu���k]�yL������B���2d~�:���J���S��>jH��m+�N�I��k��+����
�#I�|A;�3u�{�$~��v'a2i������'MZ�(��lqU�j��!KAo�	�	�2t(���8���WhW�Q���ry��^��3!�py��
W�L<��6��Zi�A?�vFl���VZ���U��i��H2�u���ed
�IK?'�j���w���M�_w�C�A����U��s�:��:�>T�R�7���\a�r�����~vg���4@���;�$~I3���?F:�������H5��
��	�&�&���`,�A%�q����]NG�G���5|s�v9`*2��3���L<���WX�O�N<x����	#6�����O���;����s���D��OEk���K?'N��~.8%-�\+.���>|��*^#%~�vYr�������7��Zz�7�C�N{Uz���#����~(%~a����'%���%;��Wz���C\�<Rz����yO��`z�e�P0WY!�q�?�]NG�7m���vm�]t�)���L<=���}��F���d|��n��
V�\$-�\�(-���B\�yY��,��4��E��BX������.�l����5�M�_����Bm��{����?*���O�bG��,�])��~�~|g����!��n��'~���~� 2��39�R��U��
����&@��`:��-�7�;<���t������?�v9�\3_��������vFl`Y�9�u��s���#���Fm����k��M�� -�����sc�������*m5fI�_�I���Gq�����$Ed�#�P���gw�m��$o��?I�7��1���v��y{��H��!�$~�2��!0���}z�e�P0�&+]���f��]NG\Y��A�O�.Zij�6�`����h�����?y*-�|�u����K?�$>gj��`���Ym����G���~����K����]�Kj�_�LYL�p�������8�-�n��|O^h[KqY�nn�;KI���[�Xz�7s�����m~��O��zS.�_
�gO6�7X�c�$�n��7�v9�����o�r5U�����L<�������A&,8��E��f�������q��\va�K?n]�yB�����R����*��6�dS$�:���s�~���v�>��g�U�R��{��V�z)��NjSJ�h������R��2��������l�)���KEM��`/N`*�=���`:��nH���]���Y��
[��i��W��K������D�xp�8���J��7���
@hj�%q��{�K?ol����).����B�����G\��J�R
[�,����������������y���]����$�K�/�l�y���:J��5f��OSM��}��lBo�
�R��Y\�����QP�u�\a�'���R���g�����k��4�2�u���|�����������RN*�����X�����?n]����z����t�_�rXbG��/i����#�_�U)�S%��#6�48{�	�	�2t(���M��j���]����r��S�i��[��}������!��x>j��4��4�'����	#6������|�N�G�~������cR��I���H�f�!���Gz�����fm��`/��}��gO6�7X�c5��%gqu{6�.GA��=���_-�]N�%\A�;s����}&N<�:���Flj�rZ�~�Nn�&K?/�����������$~!���M�F�������������_J�����@��'���,C���o��Y\�����Q�IM�+��:�v9=�J&������i+���h�M���e���a�|]t���'��
�H
[�)����H�6���O]F�p�^gO6�7X�c5\�lx��4����

e��IE���N������.���a��� 3\em',��?}Fl��C���`z�AM����\���{��P0���)9-l�t�v9�*�������.�|�?�wX�8����
��6a�8��&���X�`z�M�M��ZTIU��y��6�����C������~��~
FQ�:dHm��.GY���r�� ?��0�������:��L<�|�`:�M�M6�7����&�<�%��D���A����8U�%w��C�(�w�A\�-{��(�?���H����U]�x��d%��|�-&d>S�
�&�&����P�PV���v8����=�-}�~���A�m��e�P0J���r��z�v9���1,��o+�r(���=`��1�`���T,C��	�	�&�&@wp<�[WXu=�eo���~�G�Y���X������G��=w����n��`��M�� ����v9����r�����]M\���7����/N<XM�40>S�
�&�&���]$�<r%�ig��y>�?�=�������7���%�;�G_�M�T�WW����E��`��5�S��.G���@.�b�������R�wx�����]�#6���lBo�	�	p�+���X������o;L���le��#�Wnd�G�&�5V>�t(�z�,9�k�a���q��.�����.��x.yv����Y�>�vU�-�X�`z�M�M��*���]y�+�{7�Ms_�.���x��9~q�U��&��cU��"�p��D��<P����fR<�r����������x��,�"��,C��	�	�&�&��mVY�{<Yydb����f~������������2�[�U3:�U9}�!-���]��n\iX����v9V�s\���Q���*�vY`mGlUKcTY��T�M�G'�[:�yv�m���Y^���V��z���H���	6�o�I�9���-�$6�4������HUz���x�G����
�M�M6�7����������H��<�2o���]�g��8��e����-�t(�r�p9���.��Tg��u���]���Zm��vQ����
���3�l�>�{}���{��E����&����9����s���>�����'���I7�N�� ��3�*S1��U�h����g*6�7�������#��cU�,�p\u�r����\g������
^����>*�
��N�,0Qvm�G^���+}��wc�d�����)���\�+��+�*���oY1�tx�����1�ig^}�b�I�F��TlBo�	�	=E�Z�T���p>�aS�Q��<�*p����odzte�kB������eX=���v9��/�Y5c<�r,��h����
~�7���8t��Z��2�����s��W�e"l��)F���g+F���7*F�[�N(F��pcg�b��X��u��{�2U�L�&�&���� ��#�Y]y����`�/����
��c�~��NN�?|]�s�+�$�E7�mT�
�=��C�,x�������oR�7�o�+6c�:���5��b��s5�9�$���%�2C1�q�T�p.$9*f>[�N(fDs�7)fJ����AQO����������������v+���\R|����S����h�;��\�=��C'jym��o�6+���6�����P���c�9��J���{��v2��������b����+�����������k7a_����Lw��0�"���K@t7����:d���l��G��pf��t�#/(�*K���MV����M�n�����D����L�XH����������?��ri��5V���K�_���I-���0���e���g�&Ue6k��w�8�WL0�������	�Y^���p������{�7'�.W�����p6l��Ys�8�S����a}����������g��U6��>��"�:,��H?
+�X:���T��[���h����E3�j�aA����Y3�]T�g]s>������w�<si���A7���}���y>��+���������Z�J1�L��|���A�i����i�����i�\���i�'��*���������a���6at���r���M�G��>��3?8�,I8���s�`9�dfgXy$�iG�)�3�ps<��q������b^����f��hK����r�p��t�n���F�k����I=�}T�W]s����mjmKRU�C�����S�W�i?����p.[��L��oA������������3�$V1�t|���Gc�V�:W�S���m�n��B=��
6c��&��=W���u�|��0`
iZuvy#��X>�BwXh��w&Or]���#���hs�i������D��e����;i�cn\�6��vQa��u�b�e�!u-�����)�_oI?��F�����������:�!��u���d�-
�igJU�b�����v^N���v�?��v�����v�p��87Z���M�	�]���4���g��7��R����v(�2��
��l����n�a�'�l�>t~N�9E�[dY�G^�]��S�6�/}����n+>�5�
q��[�����[��=�&��~(��FM3�!����H���p�9��������4�_���G���~��������C�(��$�B��?�]N'���r���f�.���
����G����Ki����6T�Ggl���2a����'
����g3���2MxL	#6���l2�7��������8gq!����+�Y^�G��������i?A�B���}�'�3	$.*�>?�F,q���M�_���+������������5�C�(-����m�����6/�0������1�J9�]T����vY�
��3jr�����4�g�	�tc������=/(���Ib�`:�M���NS�*�)O������%��b�S�WYg���f������G��]��z[��B�g�/�%0�8o�e��<2���Wm�tsl��+�X:��
�����i�����������hd�:m��������Z�Wf3h���*3�����8����7���x���s��>���Wa�Y�0b�
�&*�Y�\�U�Q�����`���!Gfy�}g�@G�>3v�o7n������V��~�t���,/������"EV���G4j���s��C����������<}Q���#+�X:����!���W�.�s�SG�k��i��m�Zm����~��>:�j���U�%�_��Z|p�����	����	��n=z-�vTY�����e�P61����J�*R}�nfz�N��~r����=�s����k:���>���/�6c��^������Q��SWX���}x��`�7����<�Q\y����w����HdYb�]y����`�&79|����v9���j�\p��=��t��Z��]T���E�e�$E�2���S�6K�w�0��[�����{"�	�S��Z8�����
�2t(�zbo���r�
#J���^Mq��2?�{����������+6c�9����F���5�����\�W�Z�*�x����^�'�&�*��c��-��H|EV�
Fi�e�f��������!�`������M�6��vQa��:M
�����|zM�p�9}Q��=���9����"��Gb�x�����!��LC���W�f��,�2#�(�9�K���qze����_
s����xK������`���
!�F_��|�9�;�4!�&��������W�f�d��G�����G���4�~mHO�]N��\n����v9�j�����]T��N�?�t��mN�L�M��#��d�&|Z�2E��I����M����X�`S��Mc~}qDi�kn��T��q�l=:�g��{K?t�i�,�����9����r������N'��g�z��D�'�J��I�M��W���qco��EXy��Tg�����|�C��Q.�1��w�$�r:�-\��d���D]�
�o���]�S�5�����+)N��������3�k�c'�.>�
'D������u#6���lBo����2�*+�8�9��l����s�G�Y^�?�=�,�=|{�a��y���>�/���$���������&�����7)���a�Xy�u��Xy��@��QTg���[��K���W]%\���:���T�Rm���E���tZ���)T�
'�������4���o;L���no��[Y^���NK{����e�P6�7���m.R�F�%�����=o�1�����]��0��	��[���^Qx������J"J����h0��u�+��K�z�s��<��Gzt(���9|k�aC��.)�d�\3WVJ�c����oF���X����8�K��q���ua���w��xP8.��~4��W~H^}1��.��,C��	�ivM��'���8�l�I���u���j#\���0��Y����;�^nu����g�$�	eG'We�6T�>6`���Yh���7�Os_�U��3	�Xy��@��Q��l�����N�����y����Qa�����Bm�_�E��Ct\��,�A�W�j�vgk��I�����3�\6�����{/'�(��}g1��,C��	�ie-��HU]������v:�fs���~;����<����,'~�4s���s}6o=z<��k�����G�&��c
��7�C�2��#c.-#+�,y�~B�����G���	,
F���VN���\i��%u�6��t��]N�4�k���.*���z����u�EQW��V�}g�������&�.�v�z�K\Ej������X�`z�5���������l���7�\�rx��z���@��������<{��W+���8}:��9���0"�2�HUF���-����p����<2z����[wG���#�
F�Y��p�^��r����y�:�G��.��r��l��qj�e�G~}�W~������v|�4����;����j_����>i��Z��M<�M�X�`z�g�x�HUW��[v#��t�������wM�X3�yv�C�N��7����x�����G��^�:����������Zu��<���`�`
:�X_|�����-�������'�<��s�<�����d�o�N%&�Y6��=����)�\�j�r:�7�h_l����=��<Z^�V�����7��L��L���C����v���&�7�Kh�e�X�`z���U�r�
#J���~�r�H����Gg{o{w����-�%�j;f����k����~�t���L������"U)�s�OO��{�V]�X���_y$��W�LV�w4��M�<���;�W�^�������?^����r��9�}�����N���%1��?�
4�r��?�]����Y�����
���x
�����i�)O����%��D�e���5�7��"�w%�)�8�F��&�&��,C��	�����+��#���N'���8�"`�L���9�6aNlc���SG�Y8�k����c.]N����Q��U�������>����#Y^mV1z���7�<��G:�,��=���}O�u�O���O>�����'&%%��j���9R��SO=%����6E���]Q5s���i2������W���{E*{�+|����������
�'������V�0v1��������7�4'|f���|{�I����9�Q��f4#��,C��	�	m�Z���#J���_K�}<����G��lo��N3-�%�|}�0��S�W-���9����7������"Ui��n������/1�8�>���+�����-����������Xy���u�%���L�2�[���c�=��^�tI���~���Z����^����l�oS�����G�i��0��?�j*'}b9�X9��4����E�	����
'���_/��n��?Nv��/���M����F��
�2t(���`���������h�l�3	v�#���?�k�p��fI~���0y��<����u�B��PFXI\ZuNES5�ccf=�7���=�C������������&$$D1-�5k����/v���'����;����;��+*F(�n\ey7����^hX����v9���������:6b�N�Z����)�gx�}�~��g���f-��y2��wAh�����l�X�`z��I�,|��(Mp��M�+|��zt�������������[���^Qx�S�6B
B%�e�BUBm��qzDo�W����|s{��9���9���c��G��c���i�+@;=�C�{���V�\Y__/�o�����_�����������j�oS�������c7���,
Vl�\v���i���J��=�6*��fP�
U-�QeI�R]6��po��#{��(���6���)�B�cj���v�W��
�2t(���`MM�i�9�%������E]X|p���.�LX����-����#�����{"��M��*�N��bp��z�B+����Y��G��]���eSEE�������{N�b�o�+--���_�����;��+��*�n:-���*j�e/�]�s�r��8�������/u�]�^�H�W!|�Y�g���&�]l��������%Uf���i�,�X�`z���Z�T����^�!���l6�[��}���a��_�>��q��N3'�[:�g������������Q��__l���(��~��[Y^�����/\��{���9~	��X�z.�=����U�
���F���<��%�MQw�m���������;?��Z������M�]������>�.*L�g��0���#/�P�������1�����)s�7��(�3jry�f�}Fl��C�������6�&/�4�9��R�����6����~����pKg�����<{��W+���8}:��9�+�(2�2�HUf���NoZf����fa���p�4�bZ���|G�"�w�M8��.�WK|������"�D���[�Go+~��==X�<1��&���F����-��w���;-z�v�������p^����9�k�!^-�G��{�8	�z�>�/���s�Ucn.x���~�G[:N|������tk��;������q����o������=8��a��\/�^��qr��So��0��������8��rk����wy?�{�9�^Hx(����.&H�{@Z���P�bSSS�����{��',�m���o�R|�D{{��[�'��.���!o��G�x�-&)�Js�����E_Q8�����b?�Q�g�9.�����~�������~a.�n��;������Z�=��l���d����fx����+6��w�|���3n�Y|w�F�������f���n����r���v����l����}�������8�:h�����v��<}���n���j���� ��i�3�<#|����l��������yK|�����Ni����r����Q�W5{�\|Kl�J����O�=�������SW��������0�m���3��IU�jm�E�����
�2t(����"UiBe�a��,��	6;�O��3�s�0���m�Y:N�8u������o9r0��v��G�/D�&d��W7+���v��
!��{���G�gOc)�����������_������_?K|�����Nis�
i�����Q�W�m�\|��
Ze������E��,�����N��|6'h�����<��:�Fl��C����"UKc^}qDi��\�k����]�zt������>��sm�lF
s�=�}�b�f_yd}����v�~a��.���X�i���3�/^�|���/\� |}�����6E������%��[����������i�������W�k��lfn��+f��w������X�����
�2t(����R�P�\�T���}&�nw��U��fy��<�,K�ts��#f�����B;;;�����w�y�mvg�oS���������ft�GY_���\|��%�/����x��]T������Y�7�f�<v��BT��a�`:�M�M�h�4�J#J��m������1��|���\��5��w!��2���=������+����o�4�@������B�J��SO	_�0aBrrrKK����+|��'�������)�����:*��-���e}���c�S>������'�E��;-���5������t�X�`z���Ui���%�����V��9�e�,��#n�}�a�b0����qw/��u0��]�������b���'��i,��P�w��o���������-�m��t���@�oH�.��O�2���lP?�����4���_���z�]T������V����im���#�Z��:0b�
�&�&�:���k)R�F�%y�;g{G�'�7VQ,�����XJ�~���������W�����===-�m*��/a�f9-�����?��*�}$��������w4^?n�Zv�����A7���
�F���+��`�`:�M�M6�7X���krs�����h�c��es���}���|����Gm���syG-��)UY�E���.X���0b�
�&�&���,C�B�5�v4�����.�h��v��7\���/]����x��]T�����T�9�qJ���@�E��"XFl��C���`z�e�P��F��r�V��3�YB����l��k����Q��#\�egL����Y���P��Q�2��,C��	�	�&�&����u
�.�i�����M,�_�p��^�/��x>�.*,�`��$T����.*<{���T`�`:�M�M6�7X���S]:mx���i��M[\$�_1r��^�/����A���|�e����H{�ar���h�U��"���e�P6�7���`:�Nu��!-�v�v9����!o��������.w�
�-��U���0�mTx"��E_(��
�2t(���lBo�
]Wt��5:^�]�)�f��w�%1��?�+���|�MT�(_bc��� �<�CTx2�G�^��0b�
�m��2[��|n	�����ui�����?U����o�y�e�P���}������#�rLQ�i�a�9��'sg�G����f����.O~��]Tx:���$P��e�P�[�*)dk��Ev���-�]��v[����7�U���u����~������
���-��n�����yF�������U�\!�����S��%HG����/	�i8o�
]W�s�!jss�]�)T���Y����~,�R��}CT��C����~�������'��
�&�Y���X�sj�R������A���R���*dq'?R��6��1���sq}s���`�yY:�'�~.�_����y��+�����u������&����umo�k���]�)��\�]����,?��;�>*�_n���Y������Q��D������
�2thORW���e�v����8�#
Y��|�,����A���n�[�K�Y���-~���9����:3Rz�]�exg����q7�wuV��=�m�������	�2t(t]��Er����]�)4�	�.T}>��?��=h�	IT�c��N��C���w�
/&���+;0b�jP��1�+�P�).�E!������]��1��2U���}�)dq+����`��-zD�P�~N��{��u��_�B�[��t6��pd.M���a����[
��t�u������h=����	�2t(t]��9��0*�v9��U��.����������������
Ws��(�$�
�vQ��d�>�L��
�2+u(�)�W������P���w*dqW�w��.NP��v����-�1���m���������N��xy���m��;6�Q��]�������Y[$���X�ES=������z�����~N��Dk[��tv�S:,G~�N�������^2�~�M�U��0�m�d�2t(t]����bi�c����{�-�7��p�;�E��O���}:;�$�CTx%�������
���n�&\����E�)�&ow7)D�m�g���_��Z!'97Z!Q����e�#����Q��{��n{_Ux�\���
v�����y�Sx�'�V������������y���	���p��_��v��K<?��+��������-��� ���:��P�����tT�l�L���:�c=����~o���C�����,�l��d����z�,��!��.kk���'|��y�� �8�u��m��oR-;;"0�a#vc�9c��@�e8)���p|���<p���B�c�v�3�Kx��=/+�&oKD�B6��5�Th��oul���)���<����������qH��Ur�J�{2�sz��NK��|������D�;�?�����+<���{�������m�m���%+���|N:���Z'~jsG���[�g���	���C��*��6����M����&�E��U~���}T�$_m�Y������k^K��kRC7u�k
u��u�cV.l�����{�c��E�`���A���D!�8��������W���PEo�&�z�s
�R���*���k��Nt^������Hm.4>����&|��-j3������N��M��	����)��>�6�&����u�?6���E��1Q����^��a�?�2���
}���-Q�,�(�mT���Q6i�]H�%��a�d�$�Ud" ����a�f���y���/
Y��O�8y���[���A\�U�,./B!���}�<\�PPS(
1
��m��%���O6�][���D�O����u����������Vw�a �r���['~���>�z�e�P���3�q���}D�/�E��/���\���Q�O�����_���]Th�~����*����������?�b������7s>�}n���+6�
f���}��Mq�v
Y\a�B�U�}z<\��xmWw�	���xgiD
>orm�t���;��C���
���&���
��x��T�����U����7X���+�������.�D��<y/*���?�����
���[�N�_ax���>��k.[��d	���������@��l�0[��8�����Bs�[��l�i[���wS��������[���g*6�7�#�#�|��O�Q��9��X��[��?5L�`��U������R��.�~�������p�z��t�sB����`���u��.�l�o�j����j�e���vdP?���+��K]�.*��_i�2}
�^�+G��lF9f�Y��E�:�]�#�t��������X��&����i�
���3���`q�
)+In3��e)(��'Eg�V�*|���l;�%�nkE?����Y��5�
nw��>u�O�X��y0�gO�*�3�X8���T9���L�v�MjRg��s)��G���u1��;?�U�1m���}E���Zy�,\����z�|g�����v�`��TlBoB�S��:�c��=&��hp�&eh������6?��u��>�
�����n���r�r(��S������9zei��M��=	���E|S����~k�6Up��vQ&��j��/�w��<��e����Y�>���y�w�
��<-��@������������Yh���#��/.H���]7(�g*6�7���4�'�����1�I�������?��T��mx�xI��={����c�#N�8����~�jyn��,r���4���	]����	[�lS9���.�D����}Q]<����9.iF���9^�h��<��^�i�v����+�����"'ti�������%�����y��,C��	�	`f��R�X��f�G�����G���C��qO?C�H=9����YR���I�gF���[ .d���o�7d�3��c�[��	]����	[��!���������:��R�e��7��6qz����^�b����;D���},��`%Z5�qk�n��;�@��q��N�����?#6���lBo�����eR�V�(e�IwIx��r.Z'{H����7:~�)r�k���cH��K��x�#�eK�1+��rU���2�=���.%��'�������Zb�}��b��w�Zm�g���_�
i��57�CTx'����W���?�;�1	;�P���:�Udr�sx��,C��	�	�&3��~}�����$�>{���s^K�+S�7��dw���">d��oy�MR��	���+���"��H�17��om��~��'t�&+]N�"���M���F�E�������|�������	�������-�n�_?��m�B�+}E�u�.���n>��g��
V�Twa�.�BO��X�`z�Mtz���n��$|��A�8�#$�sZ)�3Q���-)�[��)��������'��'��o�!��w��W�-���Qd���}������H�� 'lA#>�M5d��vQ��1H�����x�6nl����|c�E�q��i�b3�57����W�����;��n�c���|�,k"����;&����
�2t(���l�1�YS@7��{��.��q���y��$�;?��u���
����?�)�C6�:E(r���Q�|��z�/���~%�!�XG�����q�zL�m-�Qr������T�V�2.�`G�����QG�H_�[����F������V����!*t���+��4��YG��Af&�����y�������9�b�`:�M�M6�����!�[�?	�"�� �s	������
�����~���m�����!}�/\����	>G�+���cI���:����7w(��:<X���G�������LT�{��;�7l��8�6fD������\��q+������Q��B���.'Dww�����������Q2��.�:s��
�2t(���lBopZi��t��]!A�����%���I^��%������!���H���A
>�!)��dG�n�V�N�$�X�F����Nn��C���|�x�������#AC�.5\�(�N��=:�Y3�]T�g]s�Ek����6*|�v�W~H����-��^"3���Y���M/��z�m���O�c�`:�M�M6�7�E�L���ii}wo����"���$���/���|�~���m��I�;�C
>5�o3����6q�.I�X�EvY�B����P��f/W9^�9a�>-��S[���[�������C�G��5Z����m���l�z�Z��h��(�����������Xw�#2�p����
�2t(���lBoZ�ZE�������� .���X�73HFw�}��m����=A?E|���R���I�gF����q�E�+�*��?��M#��=t(tQ��[r�f;y�>-���L�.is��5�?x���3�����������np�p���Y���	%�$9�t����d�TO�Vm��0b�
�&�&���=@c
�8*J �[�]���F�")G��n��Hv��G�S��l��'E�{�|n4)�a1��}d��l�>f�����}����.jt������m�����n�]���u��WITx��vQa��t�R���]����������
����4����Br���D��i��q���d}4���
�2t(���lBo�N�
����-��q�'H(���tW�H+2o�=����~���m�oH��$_O�������!�_1ds�����>����.j��*���������4���t���l8���Q�u-�}Q����BD��$�<���
�-y��3�����C	���@Omq��,C��	�	�&�&H�JH��A���$��=B���V����D�|�w�&\�QO�-��T�>�<��k5��cd����>�E���/�}�;��.j��������>-�]�����Tu;&j��D�����TX������
��EY�AAS�.�N��L��_w>����#��*i�M`�`:�M�M6�7�t5$p�	!�[�=	���P��2r�v~,	���N���\�Q�?J���)`�?�}�+�/���~%��},�%��Pe�c��.R�?.��Gg������_I�>�nR;�U�
[����X������sBa{�n|Pq�E_��
#k�|K�������~�;<@����?���,C��	�	�&�&XUe	�2H�y�q�{H(���t�F��n�+$�[���!���"���|�=)`�O&|��W�+���D���u&0t(tQ���rZ��y9-���7�U�m�An8>��/w5��CTR�\�����.�.M���E������l���o���X��e�P6�7����qZiI�t��M�8�$���G�����n�K$�[�K�)�C�O�"���|�CR�73����DvJ�R=�>����mi�t(tQ��]rZ�s�U9-t�l�]�)�a������SUs�X���$;��
���Vg����8�.�W��V��]����t'��i1��h��%�X�`z�M�M�m4�$m+� ������{[H.w�K������u;�E���?��">d[���##���u{��i��y�rZx�CM�4��e77������{�B�u)��Bk��!;��[�D�C����n���z���G�g*��C���`z@�n ci
I��������c��� ��H���o$`\�k���C�+�������8�i�����x�6��g���L�S�^�f�I�m��7�'D�&��U���F]�=��b���t����c�L����6>S�
�&�&����h�%cQ	�������3R������ 0n�	��������Xt(tE��erZ�r�]9-��l#����]lsc��+��C�S���*�����D��Q�[���������d��~���uK~����;����\6��l�9�f�L�2t(���lBoXIC%	bH��p��'I������W�J+2o�=	�@5]t�st(tE���rZ�f�����@�4cp�����i�6ll�����U�j��^�L�]��0�<�\?�/j���8��}��������Y2��_��?{��u����v�����7'�Mv�e_6/��e
����j�������7�DG�f���&:����u$$�����7�s}��0U3�9���|��g��sF��j��ME���g�L�2T(�P�lBm����NR<*<�d���-[��q����:1�����(LX�3��;���/s�GG��*��#l��w���[��"�	��MB8�e�_C.,!�S����g*��B���`j�e�P�P���4R[�&y�6M��
���g����iZ(��,=(
��F��V��'������v�:*�$j������9Q[Fn�%��<��~�����'��`��>��
�2T(�P�lBm�
z<����6������0.�v�<"<��,����-���O�;J�]����X��s���Q��QzD�H�rjY��}B8�u���_KJ���-��,C��	�	�&�&�P����}��<m���
�4-<�d
v�<`,���T�/�~R���|d���:����}�Q�gQ��U�~�}#�~$���#�����'96�d] &}��4�c�
�&�&�P�,C�������i�"�n�hZ���!��sO���,����O\��=I����C.���o����Qa���2:d�K����d���'������)%���`��	�c�
�&�&�P�,C����tiC���'K���4-�r���^��!��2��p���jUE�=���'��c&�����
3Uy~}
_i6��fOz�}H���4+�A�`��-�c�
�&�&�P�,C�����L����������
v���3����O�W"f�c=Y�c�'_}g�mT�e���_��`jH�1i�yp��������}DS�~�wl��B���`j�e�P�Pi��4F;r�`0�V?��mB5<��"��.���O]�IX:W	�47e��������Qa������~�~T�L�/&k?%^v��0f>�w!���
�2T(�P�lBm�
�L4C{����w�M�{�������b�����2������X�������Y��_����W$���
[|����o�A��K��~)
t;�p���$��4���;6�P�lBm�	�	�2T(xB�jh����'qRZ8n�������/'V]S67���X~��)����Z7���v�r�%�����Qa�cC�W>�;`��KK��+-38�7	�������������w�;6�P�lBm�	�	�2T(xBP�hz�����<)\r�@��S?�6d��RXx�#��]�\�������u�gE".���:*l{����G�>���$�{����a��a���79:�d���B���
�2T(�P�lBm�
������,�������p�e#M��:�7$����6+<=Q�S
�A�rE�Nb�<gV$��[[l����
�&�`�������d��O���B�n#��&A�/�c�
�&�&�P�,C��'������En�����{M3����S�������{em��]jB����E77[G�����~��3��>���l�H&��>$\���M���������,C��	�	�&�&�P��	.7��f7��+RKi��B����v���G{b�Ae`a��bm��W�|�Q����=����77YG��O|]P]������;A"F��t���G>���KjJ������,C��	�	�&�&�P��	Sz*
�{Vk���jD�v[�
vm�&��������r������KZ5���:*�pb���'��w��!B�����W�$��������E���`w���;6�P�lBm�	�	�2T(x��r����!�
&�AQ$��ih`�5����Bx�EX������u�������j6}A{��������
r��;���'�����N�!��`����;6�P�lBm�	�	�2T(xB-����{}C�EG�B�b�L��\��hZ(d���b�wO]hv<9����_��o�@�������d�n�I����H�jR��~�wl��B���`j�e�P�D���4-<�
}|�!=M�d����P�TX�b�{�'���kklF���0��%�P����K���~��� QH�9bbn9����,C��	�	�&�&�P������iZxz�L���sF�F\7��
N����,��]�+	�03i����������r�Hiv�����;W	��7����V�*v_�)��X�
`j�M�M��B�EGiZ=�;����&��=gb)!w�2���;����uDa��U6Q��ni�Z��#9��nV�9)t.���Er�	�F�.��
�2T(�P�lBm�
�(�}HIG���sx�N;�be�".�
e`���u�/������
�D���3�~�;|�?*�k���Vic��p�����f8�)	v��;�c�
�&�&�P�,C��'�o�M��SV���J���5��������!B]�������Qa�S����BEYy������%�y��Erb��`��	�F'�0��
�2T(�P�lBm�
��Z�E[8m}\kiZ�n�&�����\.��������pN��$.��
��S�-�<k�9G����������Lz���MN8�%�6�����
�2T(�P�lBm�
�H_�N��d�M
�c���e������4*���LD��h6	�����Qa�ScJ���T/����Zp9��{�S[FV`N�I;�n��p�`*�M�M6�6X�
O��[A#����Y?5f����wmf�X��]jJ�B����W0	��+��Qa�����Tv�	�U=;���jHO����.��l����D��~C
Q����,C��	�	�&�&�P���;��|�����3���l������O��,����F9��+K���/E������#�nZ��w�'��d�?�D�K�Q�[��c�
�&�&�P�,C��'R&���X�F�	���iZ��rpF���8es�K/���^�nL�//��
C����W�8�f����nnJM�����}d��6Q���D_�n����
�2T(�P�lBm�
�H3��c�w��~��]����O��=������6^�k�M�\^d�<3^�2*$��*ZU���|��]D���w�g�#�^��
#B�F{B ��
�2T(�P�lBm�
�H�z<M����Y?�R���p�n]��M,=j5���X}��s
�ql������	*}�'��RS�Z7�_����|�����69����%A���,C��	�	�&�&�P����/G�X���$����D���i��g"�_��2��^O���{}�uT���D�B��-a��%x�{�U���l��I?%����<��X�
`j�M�M��B�w�
��X������
���V�5zS�vLx�KX���������Y�
�Qa�s�����MF����+S���P�f
���
��?�D��E$�k���
�2T(�P�lBm�
�H���fb�W2���IG���	��-A�%����B��^�*��k�Va���]��g��kA�8��M��E���
2��6Q��?������;��X�
`j�M�M��B�i=z�@� %���o�iZ�t���^	��(cF����{��%�w($�,�������z>����:_�w����m�������>^�wl��B���`j�e�P�DVe���9Ev��>c�ia������Us��,�?��SkM�����i����>����c��Oy��BY�Ot+v��MT�����!5�'��X�
`j�M�M��B����4������C�L4-�p�X?]�S��EL^�[sg7�
?:��D[�cg�����N�DU��Q����	<�c��[��@�0wl��B���`j�e�P�DA����������gr4-����K��_*�y~jAu����hZ�=��_z�;z�z>���.k�PK�|n�Nx�\���V��
�2T(�P�lBm�
nqy��C���F���9�M�����.	9����W�%|���~sy�
;G�2�~�:-��SF)��;}�y���{UO�����
����\��K�p�`*�M�M6�6X�
�j�|i�f����iZ�a�&�sbE�C.�5e`a������6�
�-��5?vL(-.������+"�i��'�d��l��y�B������p��
�2T(�P�lBm�
n���hV��#��tY���aEm`�B>}0�
���FOWJ4	\��ciT82v����?�z>���.?\4�,���MT���.�������e�P6�6���`*�*������-3b����i���uF�M�b^�i�X���s�d�Qa��^�U�����S����\�}�.����ojn�F�Z?u��X�
`j�M�M��B�����u�����Q�^L���n7e`���KDO��V�+?>2��������B������+���puZQ�����GM��-C��;6�P�lBm�	�	�2T(�u��C�}�����1[c�4-O���!�����M.�$�G{~��hT����j��x��o=Y�}���0����69�����u�,4$�c�
�&�&�P�,C��[7�rh������cN&s4-\z�����?S�����U��"BhZy�l�zH�,���m���S�8����jaN�9I�"��
wl��B���`j�e�Pp+��=|e����[�<M'���b�����	��H���������B�'���������M5����ytfi6���6Q���������X�
`j�M�M��B����[4�J<��1Ej�����b�������w:{~ftA�
��ViZ���1�fY���KW����x2�l����ua�;
��,C��	�	�&�&�P����=����a��	��9-l�Dc����b�e`a��b��{������iT85q��{�R���|�������:��^2���pc[�����B�;6�P�lBm�	�	�2T(�uj�%el������AK�V�u��h���/e`a�@�O]���F���TS����#��!��W���XS���3���l��������!��e�P6�6���`*�:���2�p�tg�M���i��<.oV��&��=<������>4-��v������^��}��^<���D�~i��{�\�`�2<p�`*�M�M6�6X�
����aW��y�[q�@����M~{y^�%����B�X�O�x%�F��N�������5����|�V��/)�i�d]K��p�OIJDP�	���e�P6�6���`*�:��M���_���}�&�n�d��������_c��'&�������Du�k�9P������*���'��lN����~�p�`*�M�M6�6X�
�"g��IW^�jg���s4-�{D���6�������y�L�u���g���pX��'W�������X5syx����MT��O�</�����
�2T(�P�lBm�
n����\a���D�i���:����;MXx��Uyx���h6��V{��a�h#�*�v�72�U��0�c�U���:��X�
`j�M�M��B��C���1W�������K540�-�y[dC�se`������W}5����om��'~!
�������~g�������������
�2T(�P�lBm�
n����%{�]9;R�y��K
Y#���	�BOg7/���F��E
R�}����E������
O�	v�����e�P6�6���`*�������������P�.��N+�uQQ{��yUX�d��'f�4��i�����w���ds'��p������-hHp�`*�M�M6�6X�
�"��i���	GL��Z�}���E�{}hT�'�����'~}i�
{��	u��?U���m��_���������"4�c�
�&�&�P�,C��k&��7�����s��=a�i���u\�O�I�.5�i�Xz���=J�Q��]+�[��Y�]2�f�Ba�k����k�H8O�Px���
�2T(�P�lBm�
�Ui��}&)iaB���o>�iZ�u��T��}|J{e`���	�hJ��3t<9�F�������.���������#����4������;6�P�lBm�	�	�2T(�V\)^�5��Z�W]��G�291���PT�*��\zIT]����������>�k��}i�K�L�7��
�w'F����E������\Vz��

��,C��	�	�&�&�P����R!��a4�2�u����������z22��2�0���g=��~p�M7����u�L��o��?>:Iz��|MuE����"�8q��c�
�&�&�P�,C��ki�����T���4��d	4-��L�5x�5�Xz�j`aS����'~���F�N�rz�_��L:���MN8�%ry��Q��Ie����m���A�,4 �c�
�&�&�P�,C��k7�������w���l����\��[x�<�/���{�<�d�=��MN�{���PSJV���
����E;>vM�2�usS���(<�p�`*�M�M6�6X�
�.gq����D�����v�+���=��0?��.e`a���&���x��}v"�
�\�!z�+J@�d���j�~�&;;\�iU�/oE�����>�
��,C��	�	�&�&�P����T.���4�J=�:�Q�2���J�A|'���?��P��a#���Qa���U��'���82�-��0�������L�w��4�_�����Og�!��e�P6�6���`*\��i�k�FI���8b�2�|����(cFnB6�*cM��_����<����'^��
7�#�ON�l[��Gn���jPgR�p�`*�M�M6�6X�
��%�
�~L�,Q������&����ss4W�]��2���������hT�I��
}��'������NOlMF��}���_�*=Me���;6�P�lBm�	�	�2T(��-�X��}d�������9-l�XS�\,mW��1Ux��+6��I��������x#	d��{�\\��e����v��s�<O�Rx���
�2T(�P�lBm�
��?��VI�^�;i��/�s��dd�n7e`��y^D�\�8�����|~�U�u��D��^#)�u��������N������
�2T(�P�lBm�
��:���Uq�O�:��]����6;���k��7hZ(��yr�K�I4*4��'��c\�O�o��p�;$�j�/(�c���vy�����u��X�
`j�M�M��B�����JZ���W����vK540�~�x2�XM�B>�_=���7v�I��q�y�1?(�Ff��MT��?Hy��W�?*����WMMD������,C��	�	�&�&�P����mJZ������=�LF�t���!k�2
9g�'���I�����<��c>�sD�ql�}B�*�\[w<�z>��X�_.���,C��	�	�&�&�P������JZ8 ���/g)��{��
��\�?+��U�^�D[����hZvg����I�
i��p�i����c���?�?�������e�P6�6���`*\�������W��=����+�40L���RY��m��[Dp��HZM�����jL�WD�/�'�lrBs;=���SVZ��%��W�BW;J��wl��B���`j�e�Ppm�w7��������EhZ�<�`���`��h���n��R���������C���PC6w��	'�Ln����/�������#@/
��,C��	�	�&�&�P�����WifU1qd��������J���y���?�4����/%�b�s�iT8��T�~6�*"K��MT8�M����z�T%0l������wl��B���`j�e�Ppm��K����pA$=�*��/gY���B�RS9-�y���]_**��
�;�Z^/Z�]2��6Q��?���@��P��iG����}D��VG��	wl��B���`j�e�PpA��	����yS�v���4-�wD��,mU�!����EjL�6����p���u��w2��)o�D�+�����xiB�IW��#k���[���
�2T(�P�lBm�
.82w�q%-\2�n��~*����RM�^�>���L�B��
�Y���F��_�S��3^H�D�7��
�� Fm�_�J��J`�������|u`
��,C��	�	�&�&�P��B�^\4&��U5���R�6�h`x����y
�3e�BM����������;3�����96�~������������u����n��^�J`
��,C��	�	�&�&�P���Z#.��FU����sa�e2���z�#b�qe������1�hT���h�`�sO�3�����p�K���������]������^��@���
�2T(�P�lBm�
.�T�kF|o�n��:_�H�LFn�DSQ+
�_+��s&�87��&�
�-��F���^M)Y��MT8��$�T_���V[�Gnf����@���
�2T(�P�lBm�
.<V	��������r�Q;���G��+�*������2
���F��pt�w�����,2��6Q��w�����gD�Q5�'�FT�� TW�S�c�
�&�&�P�,C��������hH�=�����a�ia��+4*���&�����2�hT�<����B_����82�-��0��H��@���������+;�,��A��
�2T(�P�lBm�
.d?v^F*���\��Vl�DN��LW-L����2���#�iZ�2e�/p��2���pS{b�	����f�6e>r������#�o�c�
�&�&�P�,C��i���A�����;O9�����O��2
�x����\[K����W5>v��3���?>8�\@^�<�5�~;���*���'�W�c�
�&�&�P�,C������i<�?��f�R���5}Wf�.5����W�I���{9�
�iaT�_��H�����^$�������_��C���1>�=�z�;6�P�lBm�	�	�2T(�p=�?��[e�k�E/�5���i�|�LCNn��HA]�F��~�&�������&*��I��������~����h_|B�;6�P�lBm�	�	�2T(�p%�;�{<
��W/�~��Q�kQ�hZ(<Z����14*|�PHJY��/m/i�MT8�����W�;Q��4R����'�V�b�@��e�P6�6���`*\�I�bz�R����}�fRV������BM���hL������pF��D�'O������p��H���J`��O�;J�/���Qv��>��
�2T(�P�lBm�
.�K��|�M�Liw|�&WE�����t���1aw�������k�}]F-Y�%*��)uZ�L���|d���`����,C��	�	�&�&�P��Bt
w��Iq9��_��������NXz�`w���'-"{��p[z��/j���6s�o���K^����|��r������,C��	�	�&�&�P������&N���[�w�}���_6�o��}��,���a�r������.=���������]�'�NXw��Zgs����iT�9z��7���vn���
�
�����������~w�����NA`��
�2T(�P�lBm��/������;w���O~bw���;v��0�|9���k�����<�Z����UI4*T�{������5q�J\��4�F��v�����������p���Q����G�+1���5;6�GX�c�
�&�&�P�,C������4i�l�2�TWW����4�����L��h��=z�y��7����a�����L9;�0J�(���g	y3iZx>�o��s�sXoy�$p=NC���1s||9{��,��Nz�<�����w�K�(�a�����`�wl��B���`j�e�Py����4ir��-�����|L���y�o������h���%<�#����3F�55^��,��_iZ�`�KZ�v��F'����u�F��"z��|����;<�f���~�~0��5}:�����/D�>���@��e�P6�6���`*�/�+�����o
����#F4i�d���v�o������1c�:������K���W�B���$^u�4*�b~:z[�%-4��N���$jM�����k9�z��{A�
w������x�zY�f��T�~E�{��;6�P�lBm�	�	�2T�_$%%5i����?��_���+�����!!!w���>����3v��]�����������0�|9�Y��Ji��E�N�#��i!��fo����������F�-�~Ye�u�
�C2�-%*�����������������o_v�  p�`*�M�M6�6X�
��U�V5i���_��[���_����������+**�N/--5?��;�xu�C������4�*i�w��}��������'j���i��+��E���0��_�����(Q��W�#W�"Q�S
�A�Y}:��~�[�
�c�
�&�&�P�,C��EHHH�&M�x���������L������7���k���jvv�����������jD��Y�E�s��s�Y~0�l��TQ�Oo����������������l,���n�K��.GG��}����S�u��r�����xqv���,���\���`�*$p�2�/**������:t��?_x����������Y�s��s�Y~0�lH��Sa������%-�Q�&��,�=���6�3����v��m����d��4*�Z���[��x}��-����{���G� y� ��rrr�4i������������?�z�-k-��x�
�s��s��rG��������v��/�i���-Vj�6���������?n���W��B6������,���Dc?G�Q�L������=�
jU����;6�P�lBm�	�	�2Th@i�Z����������R�8��������zu�C������2��p���<w�iZ(V&�g����X8���u����JT8�)y������{�[��C�]��39�=��e�P6�6������PU�?�s�
�Lwo���o������;z8j��zD_�-�����jw��;w��7k�������g����[�� ���&V&�����k"���i\����i�����*��~g�\!9��oWf��������'��#�|�`*�M�M6=��)jj}����_�"s�*/z�i����V�V�ae���������4��m�0U�.���v-���n�-����B�����n�����ONN6?��X�s��a���;l��]��G���a�r���/���-=��s�	��hZ���~Jc������Qiu~y������pCi��sB*�
�������%O��'����3@C�
`j�</G^����N�<�~ ��A�N��I��k��E�g��M���������������C�����z����I����=>y�d���W�����������U+��>��S��������g�Xt���<�0��s����S��\z���lu>�
�;0`�Y]�_E�)'��D����T���
_TX��c����<�<��
4D�{�e�P6�6|'T�-A�)3�2D�sNl��%��Y�������1���������{���y��gL�oO�%$$4i����_��o_ee%�q�?^�zu��M���?h�Z�a���7�4��_���,��d����{���/YSS��a�r��V��@T���q<Q��LC�}�p�����<J���w��X��}(�ds'%*�"����$��(�J�9������B�����g���j��(�;!O��F�7w�%�S�+����I�#4�F�*z��e\�zh_F�VM����������/BCC�<��w�����>l��������d���u8���]O<<��gD���93�=�Bx�LCNio�����4-�h}t����i\�^H��f���Y>]�!���
���w���B�{���;,C��	�	
������e����]:+����<���w���v��U���`�a+���OK�
���Dl_�
47��}Y�Pw��/�&�/��l��;>-Y��p��
~{���:t����o��������_VV��aQQQm��}����6m�����k��111u;�aZ��K��z��������
f|rk�
�����r��#{����e[.��	�D���^'^V��5�wV#%���wkI����_���j4�c�
�&�&�3�`�q��p�k	�p�����|WY�������|C���,�GAO��Z7�#����o�pX�����jM�(��&/�9��6|�_�"��7�?b��=���	���b���\���b~�,Z�+�~2���
���r�����F���U��T���oua]�����Z��6��
v��'�c�
�&�&xN�(������7��pZ�g��c�V9�
�+���<��g���qk�[�s!Giy��f����o�|q���Y�V��r.��H��j�e�Ppa��]�D��5u��XrP��|����]rkMG���z��:0\x�`�j(����
_ i'�����z�t�}�\NV�{u�;6�P�lBm>D�N���+O��/�;�_��~�<�o�y�!=��|>z���}y8��_�k�Mg�:��-���E����%�Z�z\n�<�NS��j�e�Ppa��-�M����p>}�2
9�~	����hZ�T|'�>�q�M`8a��F����M6�FM�Co%����:��D�1���:��e�P6�6'�����RS��|�9�gO���vn���X<[�7v�<��������*z���M�����-�-���I�w����e���4��d�S(-�7�=�&�P���H�����o+���_����LC��f����'4*��p_#o2?��T	�Z�_n�=�t�%�~�D�+�#<1��z���������l[g�f�L����A���,C��	� �V#������%����"�����.���M'�bI����z�V��C�
)�fN����_!��pd�<�/1^�� W����{[OP�,C��3F������3����
�:�F����Q�~�`�)�~sy}��J�Ug��f>�����d�(Q��_��<o�����Z��.���;�f���p��<���L��28�;6�P�lBm>�/����D��#��<���qy8����|g�{p��R���M����������|������������"�;-}�.���eU(w��%���`*���}���Iw���W�OQ�!g|e��7����@N��S�zq�>�u`�a�&1��"���l� '����Q�U�����%��U3'�nZ�;y��RP��M��LC���1��XS#���%��|I���P�<�/,T�7m�<�oPy8_��A����;�]��choy8��I�p�
+��|Q�=8�����
����>����Qc�M��
��5b����W���	o��'��2
����SF�����4-,�.�;��������M��g���m�m'������v>}���z���E���q����g�#p�`*�ML��(XR)��P�w��<�/:J��m�<�o�ty8�����Z=�\���Q�7~����,�g�R�{p�o��V�����S��|�� g�L�&8�
gJ��c���t
1��:]��(��c_'��vZI�whT�9z�����7Z�����Q���d��?S��%���t^�������r2��M��M�������;~���^��S�v�.���z"��q��bc�;6�P�l��6��*y8_v�<�/��<���nK�U�j�<�o�hy8��n�p�`gq�k��"��W��;g�<�o�y8��y8��D�W�T �3a���~o�
���3}&*iab�W��V���������wv��p��-.�s�.�6�&0�sXo0b����R���?#%�^�I��PVb�u��q�v�����T�|�d[��C��>���j���6h�Lk���	��X�
�	U���6���-��������|n�O2�P4��:��>���V�7o�<�oxy8_�����U��\�7q�<����C����g�Ny��s�7+3M�W���24��	�2T(8�_&\�9�~�0����+����Eo�{����4-�+���R����W�l�<f������k;�{{��h0pr
�/i��^2G=����>M�����r���U���������w�%8�;6��V�<��H�Z��H����H#���;�n��jV.�S�]�����S������F��;*��_�7o�<�oK�<���ay8��$y8��G�{�8?����lX�
g��
�_|M?��R��8���b^�1-lJ����,�������^Z�����R��:%0�n�^��0|����@�T�����:j�8Z5g��O��6>�����jpH�������NF�?�
jU��"�p�:����2�%.g_?���?kr��q��q_�����x

���c�U��c�h9�^�XN������]��������UW����d�2T(8���O�>�~����=?W,��LC�����=�w����c�xx��q�v]�����4��D��D����@���x��6bo��%���+z����ty�O��U/���������u�p���w0e���B&�[�5P�B�V5s��2��_����G
hhhAi��Z���F
���}7��i����4�wy8����p��By8�(�~�(|�`*�I)���������\�����)����{vJ�r�������Z�8�@u����Q�q�Oo\�0[��.+]�����������-���/��+�t��6�v�
��C��I������
9���}�|��V$���z���>R���?j��5�V�����G�G���m�/����Q��u�����|�/���r��=8jj�}{h����e�Pp�z�s7�	�/*��L����M�j�e	9��4j M���^�J��l=y����k$����?��n��$����F*��V�����;�>T�[=������g��t����H�;64n�B��H/|(��w��4�7"��}��0)
�+/
7����[�O����k��HG5���"e4����Z�P���VS4����5��->�1���oO6�6X�
g���N�/BY��'��rW~k~������;>T�}���h2�^��+]�p��y
���./�I�oG����Q�|����G��q_��^���k�z�T@���3�;64�Z%-�� WZ���uyq�};��o�
i����j�py��>�@��V�NX5�������r��s�����[��u���&�E�)r�c2�����oO6�6X�
gb3��������������4��av�n����������C�����iT���/_,yb�Q���z�����#�U���u'�j7���5Q58��u���]���jp��9�k���O5��#T���}�;6�?��X���3���Z����9!/��j�4�w�d)�;D��#�i��M���	�cK���IR��r�<\��1i����R���&/>�*�M�M6�6X�
g�����|D���|"���i�e'��x�[��{��io��}��A��2)������Zk�^WQ���q�y�a��j�6"�f���qC+z��%(��R=���%s�v._���C����p����8yq��;��~Wb���N����U^�o�7��~��K�����4����KPY9a�}�v�r)������\�}ikQUE����P6�6���`*��N�J[5��k���
�DM�2
9�g��X?��W6��D���Si�x��Ss��+$��[~T!��h�^��/ml�O��XSc�L��?����z�T��>>NcT��R5}�������kBYI���c�c����J�_Q������R�wx���m[g��������&�vk�Ku�g+�����
�!�}�d���m^c����p��A�
`j�M�M��B���I�\I�=<Kx�������v��.����0����\"�^T����� Tk���t����+����������x=Qu�v���o�T���Sj��#��~��kvl2���r2EMm��"����PU)M�-x %`)���������JZ�o�,9���U��:~��Ou}6��������O%/���F�[3���h�y9�+~�h�q@��	�	�&�&�P����8���I������XY��h��������pK�A��XSBf���~����b0�9����a�P��T��>Cc%��\n�!��v���E��#�w���$�]���5kBu������=s�/�c3K(/�r��Y��~7�J���h�
x�a�R�7�[)77T^��Ms_~�5���Q��F���1���Y���d���%�I�_z���_��]�s�P6�6���`*��8������k{��1�q1���6%���O
�������g���(�����p�K�~��E����:04�]��%�T������Gj7���9A5��OYJ��UCzV�����V��)=U��\�q�8Q����'M�M��r��(yS����fN��5PZ��O���y���������J��;w����	�7�8{RZ��z���_N���_Yi��
*�M�M6�6X�
gH��|�EON��Q�!�x���LU�
[$x2(����
��w}���VKl�����5��<0$�i���XP9vHE����2��Z�/R�t���nCB,��+��\���9�`�s?��~q��������I��c�h)��G��z�
~���X��~������-�%-��q�����)o��rS��
�����ao���B���`j�e�Pp�����iA��������LC~�����g�i���+�_�A"�T�
�}����+�\��6���}�Z=6J��U�F*gOh������zh��v-|IxT�U�_�q��x���u��~B�'��;�X[#�~�-����iiq��pi���0)��+/�7����_�O��y��uk)�~�{Z�_�l�����u�$����I������J��i���n�+�g���	�&�&�P����=�����_p�`����i�Xm�s���Y4-<�����iUd����p�;����=�(z��l�<d���
�!���H�H��������GV�l�SR��c���fhvm1���r��fA
��-�*�����K����.o���{)�[�\Z����Rn6q�e���[]�g3�0H��
�'-�7m�����-R�w<R��._�r�{w���8S���
�B+�&�P�,C��3{���?��k���5�4*�������5&M��^����C!��
7���U�
��H2�x��'j��-6%��is�����!@D����2�����R�`�z���N�:UNY�Twd��z"������s��K����J�r��+R�w������E�$����I�cK�_�.AO�<o��J����R�7{����Z$/�w��4�7��4�7+]��J��[a�B�j�M�M��B�����JZ8j����������_�={�0�,�sv��k���,WxbZ�_����l��q��Z.1��*������G�n\U5c�j@7���v-�C{W�����.{��{Q�Bu�������������|IZ��x�����-��~��J���~��~�
�����yS�	������.-��n�����^^���u)���/-��r�O��3�P�lBm�
����Q�����=B������ys��]tsM���qu���d��JT����8e������a�%���1��h2r����X���5K�U�R���/QXy�V�F*���
7$�q��*)�+*�7��tV����r�m���o�|yq��=�I��u�>[y�O��oPyS�%s��o�)�;n�����
���jj��
��>S�	�	�&�&�P��L��3JZ��t���w:+���{���4-�Yr��U��d��+Q�������w!�-�h���KF,bA'TU��S���i����3E�U����=�h���V��;��4�w�hyq���������� �~�O�����w	��L�&�&�P�,C��3������g�s{<���JZX�f����B~t��I��^eW_�9��G}~���M�M`��Q��y/�C����k	���k�B+'��i���q�������(�~3'H�����~�QR��/�~��M=<�����g*6�6���`*��;�M
,qs4_�]j*��1��hs��4-�x����n��
#���}�����V�l���}�c�u�����4������p��'��w��o�_����~��J�|�}+M�
�s�s���~7�J������+/���]�L�&�&�P�,C��3����H���U��o([�\��������ia�}'�?M#�^S����M8�_��["�\k��+Rc�4��-��o]���]��j�8U�.�?�!��*/��h���m\%�~v������r��R�WU�w���3�P�lBm��4bqU��c�p�!�v9�;/P�l*���)pm�E��hC��������F�����
\k�LJKf�?F��C&o�ia��
���T��{}�����"���������F-Y��JT8�
R����B�U�C�����k����Q24�L�2T(�P��x�,w���q^��8�9r�qD�5F�h��~bn��z�P��d��&'=�h���GC{N��=H����l�i����\,���l�������'�iT�������A���_��YZ�8e���
�-��^g�]���������`����.1G��XX!�]�Ta
3��`*�M�M��r��"����y�9����s���N�BM9�8F�j����j$`hhhn���"���"G��i���{\��tP�8)=b����4-\������?T��}C��������/�a���;�����K�����7�&��I��E*)o,�F�^��;,C��	����Z�9��b�9��\�9��;N�.�8�8g�q�q�f�l�0g�[�


���{��cG��*[!<��`.��JZ���~���ohZx�����l2�9*�"Q��M�b���4�����q�9o\|B��b�Hc�lq]������Q�C�X������wX�
`S���j���-��q�v;�q�fn�	�s�������9�8g��q��wr644��smW��Y����m~T����o���0n�EsK.����O��-winFN����{�/�
�G�B������4*�b_'"G�)�-�Q��}t7.91]X������+�*n��>��W��F�����7�:-�`��7^�s|�yX��nSQ�X��c�
�&g��1x�/���
&9�kt��9��c��h��W����F�����v���O�������G=/�xen[O����:''O+�Tj��<����99`:Mk�:���be�������~�p�9������d�'���Z�0�����J��4�K����3w9�exgE��n�����z����B�\�����n�Ik�qW������O������t.g������E�����c?��������G�yN�jfm���g����G�|����������M�C\��
-��vsV�cw;�0<����O��	N�B%�;�e]P�xH@������d�2T(8s��$�j/��8R(����i���x%����Y�(f�V��o!m�������������lVM�|I�gF�,�v�Z�?
Cs��]��a����GD��?<v�C=47�������������:�p�F����Uhhhhhh~i�&c�������s���t%�g����? 9�zs��q��I7~�,�e�Pp��[�B��4-4����`!{��!r���I�>>�����U��������7�>�3y�����9��tQ����s����'�������������n��lC�9���p����.;�v"��?P&d;��2��l%U������B�!O��F�B�]W?$|rke�����[�i4*�p�Q�U���*ia��L����d>���y����i�����+��hhhhhhh��uY����@��,=�8g��8gs��~\���RR������`��7d,C��C�x���JZ����`��o��P�G_ww/M���������p���]@�Pi\-������i��"�������]q����yG�"N�e�����H��{��x�'���M?�f*}Z�6��N��>wW�;��E^�47�/��[�����m�������6�6X�
�*5��n}hZ���wz��L�9�
"
����&���b��q������B�>��w��?�\o-�R�f����������;�o��Xs[��G����l�3�P�lBm�
�U��������h����8e����+�T�
�D��"zV5�g>IU���/�����Fwl��B���`j�e�Pp�H%du�D�B��������JZ�1�>~2?�,���LgFMT����.��X�
`j�M�M��B���2!�}%-�R;;R��l��p}|F�j�nO��?�7��(iaJD��@c�;6�P�lBm�	�	�2T(8�S,������N��H��'�'��-
����`���r�OK=�D����p����Fwl��B���`j�e�Pp(�1_��9M� 8;���M�����{94*l}l� >����JZ96po�1��e�P6�6���`*����Qaq��gxb�!��?l+��A��YIk���)!��*ia!~<�;6�P�lBm�	�	�2T(8t+����E�?uv����lqrS	�\�A����8��bV(Qa�_�!��X�
`j�M�M��B��k��hZ������)[�d�<Xe�i���w(�B_i���(ia�����Fwl��B���`j�e�Pp(��c�>����aB�0%-|fy���D:����)��<��D�^&5��{���,C��	�	�&�&�P�����y4-��3��a���
�U,������R���1ZI�w�[h|p�`*�M�M6�6X�
�b�3hZ������D.�-eCdC��;�F�����3Lz2�M%-�w"�����e�P6�6���`*�x$������r|����!r��,���,�Q��GposJ�A%*��k"p~�
��,C��	�	�&�&�P�����I4-�:��1b�eC���X��y�����������{fICp	wl��B���`j�e�Pp���8�������Je���Q�G���i����6'�������iZ��@#�;6�P�lBm�	�	�2T(8tf�9%-7��1|�WJZX���������M�������/R�����]42�c�
�&�&�P�,C��Cg��P��)s��h�l���3?r��&�
C���HE����������	��wl��B���`j�e�Pp���H�����������l�l��.�����+Sv��wE�
'��h���>��X�
`j�M�M��B��3�*c�-�Q�@���?Y�zj4M�>M�9a�WJZ��O=���wl��B���`j�e�Pp���4-L_������������<�-�Q���x�r�QC����������4&�c�
�&�&�P�,C��Cg�oR��U[�=@(U�8���(�.��i����6G���D�s~GD�~�@#�;6�P�lBm�	�	�2T(8tv��f����|�@%-,�j~d���4-��as��O��0zV����wl��B���`j�e�Pp����4-���������l�\�`~����4-�Q��Z�G�� G���Sv���@#�;6�P�lBm�	�	�2T(8t~�"���9l���q��+"�TU����X������^9��\e`�����]����<L���x�
���<��K$j��(�A��D��F�H�h��q���D4*f����8&�Q�%B�A'�"�� �([0(��*� �6n��V���@��������o�{�T=�{�~��[�X�!f
q�M��lB�$��&^p]�-|m���{+6-�^�����~���g~\ehy���v�<�.��3Vl���B�d�$�3	%�I�^�v_b|��+�d/�<����9����gUi	.��m��e���Y@=c���I(�I6!N�	1�P��|�i�p�������?�^�d�C�_'^�v',��:b`�[�����)@�c���I(�I6!N�	1�P����.N��+&�9��������5|k��c���[�j�����������n���u�,���bC�$�$�'���I(yM=���[���Y9��������M��zA�*<m���qS���
zHeEE�>�w��3	�8�&�I6!fJ^/�;;�����G�+�Z:i���������?6������;�g����:~
P�X�!f
q�M��lB�$��f���v7-�K��*6��^y�!�2����n��%^e��l���&�k_��g��b&�'��8�&�LB���S����mo.�zW����"��UQYq��������}8����n��N,�s�z��
1�P��lB�db&����������U+��U����%N�2��u��V�	c�[Q���	�K+�����x�0O�+6�LB!N�	q�M�����k�81�-\�^����������#�.�v�x���
z��l������6�9@�c���I(�I6!N�	1�P�Zv�W�na���������n�9d�/�n�����m��3���G/,�����
1�P��lB�db&�����/���������K'5�[�pRIe�����$��Z5��M�+�h���uj���3Vl���B�d�$�3	%��U����W�Wl������:���6m��oo-��}�swe[�7^�'��b&�'��8�&�LB�+�.�z����w�v����lj�-<o�O�6��/f��n+�����bC�$�$�'���I(y�����|�j��/�d/�����g
O��������gg[��W��0O�#+6�LB!N�	q�M����W�-��i�V��������;�=�������O�>������{O�t��bC�$�$�'���I(y���}�U��M9$�nZ7�K��LZ�]G���*��V^�W�[8{t����b&�'��8�&�LB�+��z�Y�j���I%^������~��[�s�����
����y�:Vl���B�d�$�3	%��[8o�w�b���K�L=�7��J��7M�{��_��vG_V��C�e���I(�I6!N�	1�P�J��s��~Z�x{D�[���.���i�p�������~Y��[�����%+6�LB!N�	q�M����W�-�}��i��/W����%C���w�n����TN�E�Ux�Q�<�WVl���B�d�$�3	%��[8��W���D�����U����u��7��N��`S����
1�P��lB�db&���v_��k�b��>�v��}i���)��\�R�UxEI����<�WVl���B�d�$�3	%�l�p�
+�m�rA��WO�y�-|d����4I����]��C�e���I(�I6!N�	1�P�J��3����R�af�"~�������W^�W�[8gLa'��b&�'��8�&�LB�+�-����R���i�p�K��V��{l@���������,�Z��C}e���I(�I6!N�	1�P��v���R��k�n�S��v/����z�vG���3�z��
1�P��lB�db&���vg�zoR)��'������n�����~Y��[������1+6�LB!N�	q�M����W�*'w>�T���9�����[��~�m�|da�
��b&�'��8�&�LB�+����������"������3�Va�Q�*���n��_z�P�Y�!f
q�M��lB�$���n����/p\�aV����'vI?Xx�����
//�\�v�'��b&�'��8�&�LB�+�����a�����n��&d/�<������{�Y�YC=g���I(�I6!N�	1�P�J���G���K�M��<���U��G�n�>�-�5����z��
1�P��lB�db&���v?�B�,��7in�Xr����t�}l�U8�}��-��5�sVl���B�d�$�3	%��[������/����[8��{��<������Q�z�P�Y�!f
q�M��lB�$���n�Sf�� r��[�����Va��z�^^��.�s����b&�'��8�&�LB�+��3kA��9��z���[��;���
o:������
1�P��lB�db&���v�,�k�;�$��m�N�7������M��R��B�`���I(�I6!N�	1�P�J����x�|�uI�p�3��V�����m^^T�ny��
�b&�'��8�&�LB�+�~�jm��~I���q��n���~6�-���z��PX�!f
q�M��lB�$���na������t8��.#�u{���+��vg<R��BCa���I(�I6!N�	1�P�J���[7&D�:������2��e��m^��r��BO
+6�LB!N�	q�M������.�|��Tl��|�����L�y�����>��B�+6�LB!N�	q�M����W�-\���T�x4����a]F�;��^[//�v_��B�+6�LB!N�	q�M����W�-\z���_�t/��.#��r�����u.�4�a�bC�$�$�'���I(y%����N-�{F���&eT�.#����=����o,�4�a�bC�$�$�'���I(y%�����+�zD����O��ed�SG�\q������T��F��	
�b&�'��8�&�LB�+������f����;���~�������+��#48Vl���B�d�$�3	%��[���>��^2�+]F��~���n��wz���X�!f
q�M��lB�$���n�_��,�X�yb��G�9��^e�5�vW/)����bC�$�$�'���I(y%��������E3��O������k�Ux�?z��Y�!f
q�M��lB�$���n��?[:����\������~�n�SC
=Ah���3	�8�&�I6!fJ^I�p��J'}������������e�(+6�LB!N�	q�M�������]W��m�7Mhz��>��>6�*�O��4PVl���B�d�$�3	%�U=������E��}�����Me���/+�����bC�$�$�'���I(y���u���N,��8����k�l��.�T��Ae���I(�I6!N�	1�P�Z����;�N,:w�W/����V��=+�K=;h���3	�8�&�I6!fJ^�zv�|���'4��Q�?tk�l���s
=5h���3	�8�&�I6!fJ^�zv�:��������~o��e�[8��BO
.+6�LB!N�	q�M��������)�X��'���a'f[�W�Q���BO
.+6�LB!N�	q�M�������|�tb���O����v�������
1�P��lB�db&��U���w���:�����e��S�z^��Y�!f
q�M��lB�$���]1��������V��E�Vz^��Y�!f
q�M��lB�$���^�q���>�����{�Y�IACg���I(�I6!N�	1�P�*����GN(��I�[�`|�'
�b&�'��8�&�LB�k�3m��vx�*���#*+*
=)h���3	�8�&�I6!fJ^#�8��A��,���=#��
Q�P��lB�db&��z��g�����S����������:uj��x��;����?j]������b&�'��8�&�LB�4|��F�e>*T�
�[�M����i�p������2Vl���B�d�$�3	�������m��d8���[���}��
�v�������G��X����k����v�b&�'��8�&�LB#4b��L&s��'W-���s�1�>n�����G|�-\z�?���v+6�LB!N�	q�M���F��/�d2<�@N��{�	�K/�t7��v����z���e���I(�I6!N�	1��u��5����3'�>s��P���}?bG�p���e�[j=q`��bC�$�$�'���Ih�:u���d��Y�S_�re������i����-�s�1��5��Y�!f
q�M��lB�$4B�Z��d2��H�y��P/))�M�~��������gj=k`��bC�$�$�'���Ih�7n��d***r�������M�Vu
�nal�7o��d�l��������[��M�VU�����}������f2��k���W�^�����n��M���3����ss��g��n����}��\p��L��������~����}���=:�����3���G����]�/�M�6�k�.��0`����m?���*m����a�n���������Q�F���:,��}�O�1c��t�I���/..���c���'M��3&o����1�8qb�����g����������s��Q��=���}�����SIII�y�YgM�:��Q�}k3l��i=z�h��y���{��5o����/O�e��+W���� ~c����P�.���W^^>l��/��m��i���a�v�
7����9�����U�.�������8��+�x����O�3����������i�8�	\���|�=�����t����5j�3&T��J�!j�om�-Y�$,�_����n��x���U�s�g�����
�b���;v��-�M�{[�l9��S���y�QG��������5k9���P|������J��:��#�$Y�~�.L��X�O`��	a5+**���k-Z�y����<8TB��{�I���Wm��
����p����g��}C�]�va�������v�9����������{.l�y������1#T��k�
6���
���.J��T��&��W^������?����{��w{�����?��%c�
��K/
�s����x������K�&��������:3t���W����]�����9���������<�~�m������ds��a���O�:�����c�	�q���������<����n��d3,�as�}�Iw9��B������+��2eJ�F����o�d��[o���I�����K�V�O�:5���:uJ6�
"�(������y�B��H+�	u`�����w�	��{����4�%��L������o��W�\���5K6/����������{B��K/��!j�o-������d3�����L6���?���:���c�O�p2~����~��G����M�{w�qG8��?�����'D��M�)����p;TB=��'��V�Z����6mZ�n��MS^�k������N6�v�6����3l�������P�������w���~�����K�C�������J�*���X�p�
����7�nW�%�P�N?��p>�_
j&�P��U�&����g?���"�P��c���o���2����]���`�6lXX�����lv��)l�Y�&gX�������C�r�Z;��3��s�=�lN�4)l0 �~���3;�a���Y�S-��SRR��E������M�{�;w���e��N���W�v��5o�����{����O(�{��7��{CH����|���������t�xB�z�����4�%����������E�W^y%�$#������7�zIII
G�������/�\��M�6�-
;t�Aa��O?���5�&��8����Y�����I��-�����]�pJ:�I�&������a�	���_��u��i0�{��_��xB��-��i�K`v�m���t�I:t�2eJZl��qX���GIyyy��{k8`-���C��93�0,�aU?�����4�������~�����i�z���7��z��7o�?�@����pVw�����,�T�%�P���-j���w���9s�l��e�����O~��0aB2L<� B*����'�H����_�xq:F<������4U'��Diii�~�:v��`�������0�B�3>�����p�Z��3�a���r���O_�dI����l���w����[o�N������g���o�d�^III8�
�S���;C��SNI6����9s����C�G}t�������+����6m��>���0��:��[XiX���u��>}�W�~��]��]�So�B}��������wg����c���o����sN�=y������{.l�y��5�
a��UW]U�X���lB��s�=�����o��_��P�&��	u��SO
g�C=�S����2U��[<�����A�`'���g��a52dH�{�w���;wnN}������[��\�}?�C�X��e��EEE��x��a��u��{��_���JU�)��{�a�	u������	�P	��M�&��	u/i�W��?�TAzV�'��������:x����S�v���Q�F7�xc�\pAX�|��������_|q
�����!.���0���.J6���*//O6����fX�k�!D���B���w�������_��/Y�$�>��dS<��%N~C���]�6�����xB��-��i���X�{��'�5k��e�����7f���a����gN�G�y��O��'{���YX�[�h��;�$��c�6lH6�{�=��C�Q���lB�{�����{�����o�����S�'����;.���?�|N�������'��	u,o�p���B`�zl���a}k����i�j�i��v����n��,��m[����Pi��m������!��]w]N%}�8i�������Q��FK6������K_
'�%�\����5�b�����w_����6m�~��xB�{�������c�{�����_/--]�f���#�k�5*&�P��vwk���!��N?��L�����~{�{5j4|�����A-�����K/�����C��7y��WZ�hq�1����k�����i�h���}� ;�/��]h���|pN(�4i2t���������^[=�����O�Ky�T���$��J��.5�:x��1'�tR������;v���w�I�&����!�����8���c�y��9���g������U��N;�5��7v&_�	�V������;����5k��^{�Sz��)���'��	&���+���(����_}�xB���(U��4	,���X��SqL ��n:�}����m��|���y�	����-�{�����	@CV����	T�������/���C9����M�6G}��7��a���a����\�����a�����^}���1y�o��1�={v�k����>����o����asT�k��E��>��SZZ�s�P	�dL��=������C=4� .�=��������*|�L�>�U�V��f�z���+�a/��B���s�4k������z����Z�8r������a�{���[+k�-7�?��p����y�O<�D��{s��1>��pc���Ur�m�����?���;���2���������o��y��u�<�L���C�?�A2f������.���W^ye����?���g���q�6m�������r����q���-[��.����K��iL�4����n����S|��G��^�z����O�?��CyR��W_}u��r�-�_����+�6��5�d2k���Z�={v(p����7�6
�����_��^{mZ�i��r����>l�������S���G�q�)~�����o��I�����+�����k�e����~�Y�f�J������U����*@=s���&���~x��ey�$��{���r������]�����[-w���[�|���k�j�����+��o�����;�����$�$�1�k��q�+V$�����@�t���W�������{����1c�/L�k�.���%��m���i��r����+l�[������n����nw��9�����|���;������]w](:4����w����k��c��=���sZy�rH���&M����k��qz���[-w,**
�eee5���v+?�4�/�n��1#����[
�����_�|��[�li��y��9sf���z��7�>|�y���\�$S��!�E��~���i��r����;��������hK�}�%������oj��������I�W_}������w���������q�2�L�V�������������9��Z�x�QG�aS�L�����y���m��o�~���:th�����k�q�������>p���c����{n�s�z�����g�+W�����'�?��O���G�m����|��P���oZ�i��r�A�U���)���>�����Q���\��w����Jr9���??�����{�`�����E������G������n�d2���g�|��w�}w���3g�<��Bq��������i�&Tz�����/n����g�=����4iR\\<o���h9��Z��x���M��a�\s��+���I�&%k���[��%��������4m?V���;7TZ�l~N�6-�����{���G�.**��%
���-[�_�$������/O�=��S{��G�a#F��z����Z�8l���c~U������4��G���~�#��uK>�X�����{��M7���?��Z��P�[���k�9��#����������}���a�-:���������6m�|�k_?~|����������'�|r��mKJJ�n���>�����K�~���l��u�f�:��q����x�]wU���y��X�xq2���n�~��H���Q�F.,�\�B����3�����^���r��W_}u����d2�f�*�t��I/zr��gz.@!}�3�i�����7m�T����}���
endstream
endobj
10 0 obj
<</Type /XObject
/Subtype /Image
/Width 1722
/Height 948
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 73842>> stream
x���	�]U�(����m��O{������n��6*�_k?A�APQ�V���!	S aB ��2��0��@�Ld`$$�JRI�S��r���;������&��j�R��s�>�o��?�9{�6�W���������n���U�
6d6r�Ygutt��z�N)�v��3f\z��C�<x��g�}�e������Y�U���_��J	��;;����n�Z�.B�P>k��"��A��<��/�p��qs��������g�ZU��"B%�@�������{�9��w�U��+WU�������	�U�]�����
��-Y�xq?W56Uw�#W__��R�0�n�?~�{	%sW/e���5kVkkko�<��yku�QH��P��}>|���eTQ��\U����2y����U�]���/[��Pzd����_��T������K���q��q%�%��]��]�����nkk����l���J���*=vJ��zU�)KU����<���F�%�V��G��|z�e����+MMM���555�_��T���Y�9�n�07M7d�����n���������M�<��ga�=��*����G�P�]�����KY���+�d�0r��2��������_������w�+(�9�n�0],���?-Z���^z��L��/�����������ZWW��o<�����
K��F���k������E<z;%�u��*�������w_fw�yg�VA�� ��N����w�+(�9�n�0]l��Y�L�2���2Yk�W�����#F$��8�p������E<z;%�u��*�����W^yefK�.-c�*���`?���u��>G����.����g�1t�����O�>����
���w�/���>|x)����ZZ���E��h��2������644dF�
<��W�U�*���i�����9�n��t�����A�U�VYk����b��{nX���zz��I�����U���o-�M��.v���~�_�v����/���!C��u�YW_}�C=�u��R���3g����k�~�g��f�J\r�%a�/��R�������=���E�M�4)S���.����/^z���;��3c��P�ptg�y��_<u���}���e�n����#G�uO?����	&,X�������������;z���C���V���[�7�����p�����]w]�V,q����=��f�������f�Q8�%K����^���Y�7F�q�v���_|1���w�6l?~|��g�}�W\������M�����K/�4�H�H����Gy���)���^{m��)]tQ8a��L�fCCC��\��^����������e���gccc�b��� ������O���Q�������n�-�������Zw�uW�X(������V�^I�p�KY%�o�D��xZ��x�y���<���y�����W2S����5*��
�3�	C�y���;@������??t=�}���{��v^}���/�<w���u
}�B{�+w/���������;�Bw2��
�w���lnn.t�555�^{m�]��Z��
,Y���s�������z�E�D��M��>g���X���:�����<z����l��:�����[o]r�%�
_v�e�@�UWW��
7n\�z>���g�qF��F�������$R���B�)QO�uKK�����Y���N��eK�b�.M*�����-�y���L�f2���O���(tZ���|���KY+�`�-[���\Pd��i�X�	���*�&�����
7�P�*yExke������k�S�Ah��E��R�X�����S������y���������������z�h�����'�|2�F��ys���Z__�w���S^x��B9�D����f��<yr�������|��B�[%��	����l��zF.aJ���i&��]*�^~��w?Q�F���w��7�U����2�x�3�8c���*t���J'�����Wy]v�ec��-Rf���E�������w����~:o�t"��o�[&�I�	&$����)_\��z�r����zmmmIj������J�R��d(���J�IF]]]z���Zv�J!�Z�*��-,Y�$���&�/��Q_�R�R��r^������;������{��;@��_��:����a��-X����!t��-[��I�A��^�:k���q1v���+W��;::ZZZB�3f��|�f�*^���\�vm��x�5���cSSS��K/��~*����	���_~9����u��UaS�Os��J��y�t�Ma���pt�o8m��$
��Y�'3��Y����=�SVoll�����r+��K�:E�uC'��Cyy���B�r�?~���Y
�(�EY�N�Q���n��n������.b�v��8���G����
k���~��p��V�b�����S�n����x ] s_�;�����mmm6l���;�e�������]���>�uz<U���=�����T��1c�2.���3�������(3�Hw�VnM�����h"9�d���E�p�B�Z�����������-@"�[�"1�,|��g��BM����_�R*9o��t5�|��p����?%o���-����B��������%v��e�F�����?z���@����������O���|��G�2�\rI�j��g��)Y�@�����tW.�g���U�p�����)S�v�3{����-X� )0j����?~|V�C7������g��P�c�=�Yw���=]��]*�U��C���K/M_����m�B�<)�����D�
<v��"�4h�;��S��s���*�5@t`N^4���[�O��Qh_���Z�}�r����"y�6Ik��??w#I�;l�P�e�����{6���\�|y�.����bI����/��J��$�����wG����Sq�Z����G}4���s�-4v��)J�d����-*^�n���#�{�c��K���7�|3���������aC����ok�����M�6%e�<������t��u����sN�,	>�`R&�KJo��+����L��Jf���%�"��4iR��7�x#��������wDM8�Y��QIN2�I{�n��.T,���k���nz*��w��{�O��P�?����������<���o.����������J��-���[&�XR`��aEvWD��u�	��l����3%�������g=����V��(s���r�566&mE����4hP����
{�1cFkkk_�L��V�b<���9sfz��#���%�����J��1�t�����_��k}� ~���7�tS�b��z��d�v%���r�j�~:{��������w�y')3|���[.��M'��:���Gs��M>Z�lY�\�|yR��{�M�~W��R���X�X!mmmI���,E���B����y�����Or���������3'�43�l^I�b`�����z�Zn���Q��?��.�w�����.��B�r��}��d�S�NM����I�Z���f��h���~�1k��H�O)��Q��"�? ��o��%���m$��$=<����P�Xc��}��W{yRb��*�Y��\v�ey�}�KQJ%�
��)4S��������z_d0Iz:����
	}��K���5+=�0o?���7�xc���/�\��s��n���e��g%3�=���3�i���u�g���"�C�z��J:��K��u��5[������'"
����7�pC�i��SF�����~�i�%��Mg���	w2:::�r����Z���
:4�P���+3������k2�l:q"%y}\�N�(�H�O�
=G�{E6��X��r���<*�N$��������{���8o�J�x��Q��Y��)J�d:�Z�i���sN]���WYb�_��}��9%Bx�`��5k���{���^s�5��X��U����1"�t��M�>���n�@�)H�;����[H��/���Dzld��P�=���Yq���=]w[Y��y����)*}��?����O�]Z�����s�[�n-��%�e���V�u���:�{I�����o�,|���������O��/����;�E$���"�Q�h�y�m��9�$�����9�d��t#P|_�����#�����/^<y���L��7���*�i��{��R�R��k�����q��gN�0��g�-~h}W�����z_(��m�LI��C��X�zu���E�F�������,2��P��<�z�6��*R���yOBq�p��+W�t�me�f�����{Z��D�ENo�()���������)�0K9�}����|������=y�?�F2�nfn2-��A��,D����A�~8?{+�B��(K�a�bW\qEfaz�v2�E�����*�&��^{-i*O;��������U�O�s��EV��_�+�|��B�
�5j���?�7m���%�-�+v���������}����K�g��:/��������#��L�9�h����E��p����B�g�xUs%#�N?��B�����Y�������G�A��d����k]__���#Fd&��$��������y��mO��w�y�%!�s����3�������|���2'L��,?~|fa�����\eI��5kJ�nE{kU*�3uN�=|���4�Y�����J644��5+���
W0w���V/�2}�P-�_��L�������d��-���n��L�8��������~1`��C�O������^;��3��E��E�+������v���J�d�Rv]$������F���+=-Y�2���ZoKM�1���3y�]we~���;�b�+73o�K��o����W���2n�x%�	|�m����v5i��GWd�%��,6lHVI�u%����T�?��c[�n-��m��)zz�C��j�����;��v�5�\�����L)���Z���y%`MMMR,�����{o���_�w#�>f[�����������.�^�"�/]}�B���=��^%����t��]�����&[��@E�i�������H�K,Y�2���Z���K*����nK��K�.M�=�������vZkk�<���w��~8?{��[���Y'3�}#=W{)g���y��2dH�keD{kU6����*4�V��R��r'�_�'�|��n��8{������2n����E�~����b�S��(y����o�J��d�����,���|Z��Q���I����K��*��u���J1n��d�-*T,������p2��X���[�g���)2KOr�����/{����v�|R,=�B��/�d���U�kl��5��7�tS�V�!C���~]]]R,�������;k
��.=?��[�Wr������v[�u����_����i/�Czl�9��S�Z����*�7�|s�0�q������������y�����"S����=R�:�#��>y/}��S�&��~���G�'m=���O�w��
��=�������/�.�.]��I�1��>K�b>�`�<w�R<�����i,T,�0��{�<��;r�t�yd
M��<��[�>�����4yM���J��u�����J?���,W���r�3F������C�x����o����b��.L�-�3&�6+~~����)����������6lX�����R|_�8����+�,q�mq�Z������K�6�}�KQJ%��I�����-SWW������>���)��>t����qc����2�&�ZZZ�7�g��^K??�;�����N>
���o��<yrR�����{�%��������N;-��c�_|1)6~���G�6mJF�����I������HU�$�y�V���K��rM�����sk���\|����/P�CO9�LX��K�x��^T����*�WY�uF:�?s���?����U,�>��Ne���D��OY���"�:::���=��S��}���3t�WO���+��Me��R\��V1��8p���s+����Tr��)I������n���6lX��-����@��l��qY�ZZZ�������w����t���������u���Y{	���b�W��������k�M
�>��j��$�x���z�{��!���sp#G���eKV�
6���I���������*�������"U�����-}�"5���K��������sO���$_�����
�_}V29��~4�������{T�\e�*�����ys��NR[����*�9K
�@���"8?eQ����6mZ�������FJ�Ih=����.]:e����\h�p^��Z1���I����;���OL��/E)�\�bER&���=���Y��2y��]���Dn`����j���---MMM�-������BO'���~L,t�f���0������������]��q��:�n���[�^}������k����8q����C'1�|�����J�����)R,HzR��O���z�>�hz�������sz��E]��K/��Nr8�W^ye���������Y1����{a������*���
����e����������aOr����xMMM������.]No89������p����=�~�J��L�r]�D��,0�nggg����5�m^�=?�R����
���p�72�B�\�!�k���o_�
�M���/E��L������7o����/��o����n���f����[^��g r����F�X��g������eK�L)��~8=�"���6��V������g��r�q�E����������}�B.���B}�U�V�_��k��9%V5-IJ�����sOwBs�>x�
����$_���/Y�$�L�k���yg�)���R�\er��Z'{��tMr�
g����y�
m����\J�{�b����x7g���R62��&M����s��Z����dz���}��/E������z�G^��vZ�wJ�R��g r���MMM�g������
6����k%�>��g�yf����x k��wQ���b��.� ��
4{�����\z���z+��}Y���+3�z���.�(��3f�5/��iw�qG�S�SE�������Y��}<��W/q����zzl��Q���z��K��L�2^��M�6�k����H�����N�}�2Q��S.%���b���O
�;��sC�}��'r������2b�����=���G�{����J���Y�7����K�,)��]��C"���>t3_x��1c��~�����~�-����=W����3'ta�>�����a�F���#�$O.���k��.����-�����1#���<��A��s�9y��lkk�?�M7��6d��3�8��K/
+Jf��)�X89�6m���#G���}������{�)������P�pz����;q��U�V���i��$����Jq�_?i�����6\����z����0�B5��I.�z�����c�����
����O�$���K/�����RJ��L��_� ���m�sUhB����d��k�����*{~���7s"=��SO=����Nh��:��������;��S�������x���0=�/�:�L��R����X�b����/�����������3����:��Ze#(#_���B C���-2d��B C���-���O>��_��K_��>��������,�t�*���N���?\�Z��
6<8\��~��������C���*]��(r�;::�L�r�G|�S��w�}����_r�%����\��hoo?~�!���O|�����w���q�����%��N8�_�B������G?���3���@_L�:u��������)S�T�j���;����JW��l��q���������7�l�R����"W�����?���s|�[���OTgg�I'��{�GuTKKK����#s���zj�H�����-[>��O��o��+V���������K>����_+]��3y���~����F���N?��p�'�p�[o�������of�b��{n�����_�s�9',?��C{�������7��9�������a���m����c�a~�K_
��i���b<��_������#G&������s8b��W^y�����W_>|x��N�8����n����/����4��������vX��CU�b�i���������~������_�����Z�*Y�l���d����`��S�W��w���G>��>�������,������p����z5��y����~������?>,���k�V5jTX~���G]�>�����[o�Z>q������O�H���?��?dR�?����-�w�}���)
�K��
��?u{���������cE�����pN>��O$K>����%����*YSS��c��
@�0������������;�	}�%K�d-������i9���	c��_��vz]������������la����f���?a;���7���p�+V�H��Z�*,����2b1cO���G��'l��u����x��a��9s�t�}q�9�~��2�������?�����m�5k���������k��U6[��/})��7n���<3"����|9����������7�|s���o��v{{��5k2o��0aBy�4����^����oX����;���|�3���'?�������;���������8q��>��}��w������2eJ8{��rJ�w
{��f3�a��f�y�p�}�)�C�0mO�������>��`����c���dv+�laZ�����|&,�<y�G>����~/�������d�:�����s��3�t[~��-_�������/�q����l�p���}������ay���X�lae��K�,��O~��
2���?��W_}��G�WUd3��~�c���~NWsssMM���S3���s��e��D�-<��C9��������3f�(R�����c���g?[J^HT6[��O|"t������g�~�S�*�!#[X�l��%K>��O~�������jkk�����_?m��p�?�������e?�,U�-�g�}���C�fW~����'�KD�-L�w�}������?��#y�{���N����r��r���������C���MY�kkk��/���8�bd+�-������n�Z>i���y�\Ud����),\�fM����W���������������^h�����_����Gs�O�U�l�����K�.�Z�x��=gN��=*[������3s�|�_(�!S���>8����$,�w�}���b��n��9�?��?d-������~>������;�sT6[8p�����>}z��i�����.�!#[X�la�9�-[�d-��iSX>-�!S��?���a���������a����_�]S�l��>��p��������N�,X��/}i������+z�@���93t���e-�L~��E���s���?��p�O=�T���C��zhEjUAy���?�x��Y��������W��'�s���Y�G��������g�c��'?y�}��o��ihh��g>z����oV�\����{�)��%�����n�Z�
��=*[����_����W�^���������p��3����^�����~��a��!C�x��p�jkk'M���O|b�}�]�bEE��o.\���{�#�:u��M������[7n�������G�!��<������>������������p����k�����Z�Q����/���y���	
]�7�|s����:E��G&O���������{����}�I�=>����H�
���Y�fs�1�������~��_��	'���OT�R��f6���{�q�}�s�W?�7�����t�*�����e�E]����c�X8K��3�<�����p�������)�$_������������w`������?���������������9���M��[l��9Gq�^{�����'���c��7o��.�W_�
9����s�	'tvv&�����w�+�LX2v�����[,�����C
0���~��!C�/_����b��A��%a����3����>���%�{���K[ZZ��<������`�uW��/�Ev�a9rd���.�(,�����u��	��C9$]�����_�rX~�=���by�e]��}�CX�fM��u�����}�{3���W�
��?>����������7��X^}Y����W0������u�������Y��{���<|�+����u�^;v���>����{��W�u��
Y�2C��o�vW��/�=UWW��^{��_�����3K����z���s�466���y�{vE����.�#���t��>��'�x"Y�g�g����*�����OwE����n��H%������:������-K/���7`��������}���wE����nZ��J*��������#���?���9D����n�����Y�kjj�����{W��/���bC�D(�IlB��&�L�������0`��g�������>z����/\�0,��W��+����u��i�!f"�$6!Nbb&BK1o������]�z�y�����I'�4`���'f-������_�����X_jT#-6�L�B��&�IlB�Dh�f�����������~��w*3}��p�Y�����-��+o����FZl���8�M���������.]�W�W������~�H����~����O~�l���������>:,��>�e��]Q�/5��b&B!Nb�$6!f"������JJ^r�%����]�7n\z��-�U��T-6�L�B��&�IlB�Dhq�{��J���~�A�7�7����������s�Y�by�����.Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�j�����P����8�M���Zl���8�M������P�stV���b&B!Nb�$6!f"����?����[�Y���V���+Zl���8�M������P�ttn��-M�^�����
�h~���N�
��b&B!Nb�$6!f"�7>���
�??�����Z����t)�b&B!Nb�$6!f"v{O�j?��<������5��D����FM�
1�'�	q�3
��uu�G\��d����GW5I������k�� m#-6�L�B��&�IlB�D(���������$������zW��������{�L4���iMs��-6�L�B��&�IlB�D(���~`��N}�5�iK��G���5���5��������
#�����P����8�M������K��y���7J�mi���������P�03���Z^^c>�J�bC�D(�IlB��&�L��niumG�A�cG5l-�,�a]]��'[1��H����'>��v��������P����8�M����Os��_��#�������������t\7���|(���t����+-6�L�B��&�IlB�D(�~F���N��x��S�tn������P�n>����?h�!f"�$6!Nbb&Ba7s�;��p���}�fK����u��rp��P�3������eW�bC�D(�IlB��&�L�����u�\�#�w���M���U�-M�3��Zt>�\a>�]E�
1�'�	q�3
�������nL�{�fW��2���Xt>�P����b&B!Nb�$6!f"v�����
g/��7	�Z�q��-G�����Z���|(}�����P����8�M���������t����������W\�e���7]�p���f6�}���m����v���>�B���r����C�m>�>�bC�D(�IlB��&�L��n`�����������K��n����W����k�=l��?���S����W7�Oy��fo�+���+�����va��-k;����Cy�����b&B!Nb�$6!f"�]]c����1���K�d�*���n��nR�=�9�k���Gw���=�xm�-c����n�+������g-h:������r���C�-6�L�B��&�IlB�D(T��m�O�1C����X�=�o���3U���o}u�1��v���>���?�����5��+G�t�9���������'����g�:aT���[�����bC�D(�IlB��&�L�BU����^Wx����
oH��j��a��1�c��2�������������V�t���;��K�w��#���_m8s`�x�G��o��P�x�U+����l�>�=�b&B!Nb�$6!f"������`G��?&6���Po�=��3r~������Zgss��5m������y�M����W����������k��|^q��_	��=��]�A��W���P����#��+���yE-6�L�B��&�IlB�D(T�
[;p���yEC�����m��p���I������jYv����=���+����M���W�fG^���y��R��bW^���y����=�xuW^��{��<�=���+���=t���3
q�'�	1�P�::��z���xA�s�������j��$iV��m]�R����5�W|�������o��W:�+�������u~ue{�W��a����+�xV*�x�������+�|9���b&B!Nb�$6!f"��
sZ��+�0�5�i���k������oy��JU�Tm��W�}�������:����:��1'^9��g���=��������Ny�
�Z{�Q��p��������������S^q���y��]q���3
q�'�	1�Pu�Z�~@*Ux�����#��o�����wd��J���*W��xe]��9-G_����&?����3W
�b��iO�>�}��-c��]�5^��A��p����z���U>��������������+^�_y���u��o�+65�~f��3
q�'�	1�P]�n�<��i���j���#W�Q����G�V���R���E8�^o�dV�a��O��o��<�i�����|�ho�z��U]�A?6{{^q\���]y�so�+�8����n�+^��W��������W\��Wll�bC�D(�IlB��&�L�Bik���q�;F���_�z��
;��n<��t�~�U�m���o��r�����0�0�|gd�w7?�J{��������W|�+�8��?�o��+�8l{^���t����y�5G~��g���+����z[���+�8������E�?%��
�$6!Nbb&B��\y�N�+����u�--��pJ:��e���:;�l��lm�����Soi:�@�0�uE���,}�wI�tv��_�+��������q�����W��W<)�W�?��H�=���e�w�����
�$6!Nbb&B�Z�Y��N��}[j YGG�������3N���^xc�m����O�����B9����k'�m}k�.Kv+�W|���y�G����o�S^������'�����j��/�����	cv�K1��
�$6!Nbb&B�*����{�x}�O�m�o�1np����)�M������
����Zt>���onj����M������+��=����]y�)��'���+������]y�CJ�+n�����|��G{�� Nb�$6!f"������1;��}������2W?n�N����eKk[/��5��E�C4���B��T��\/|��?����'4LSw���5�����n�t}a��;�IlB��&�L�B�.���N|�\��|�x����\���:j�W���������������jx����w7�_���P*�H��2��
?<$+g�y��:6����3�� Nb�$6!f""7k�N�+q��G���<����&��
G~�����]�����|(Gn�e�[��4,�bw�m�;gP� �#h~tvV�X�SA��&�IlB�D(�l�;�ar���<H�������5��F��K*Z�e�C9��|(?��q���J��R�RZ��g����r�u��Y��*	{,�� Nb�$6!f"�2�x��T����kw���{q����j[���{���:���<�tek�W�w�0���E�C���o�uc�����bw�[���d%7��{��?���=��T'�	q�3J=����B�l�m;�����:�����p�A;A~����+[�*�����0��Q�������q���o�<���_�z�e�--�������
�$6!Nbb&B)���k\�9�qY�e���t
��������������)��;�U�����}��K�����C�i������'�5�p��G��|y�U�X�SA��&�IlB�D(e��������rtg�[�������������[�l��1��O��k+]���c>����rU�����nk��������N9���o�|�����N|��8�M������P����^��m)�>���yt��z�_���������'�s>[.=����}��0�����C������u���c�d��?Nl_�V�+	{,�� Nb�$6!f"�rik�������M��K���6hJS��:`x����vtl>�;�r;t��a��k�;n|$��P��bw64l�����a����4���V�X�SA��&�IlB�D(����3��<������V��u��?���n�x�N��N���*v��h�����/�~>������-v���n8������3�����\��=��T'�	q�3J����#[x�u��LQE�{�����������i�z�\z����Y�����Sd�C9����C��?�C)K���ic�8��������|�,��=��T'�	q�3J����#�?�kA
��]l��y�;��uECX�7N����������
������������IE�C�����w�|(el��f�Us�7�r�[.>����,��=��T'�	q�3J�,Z���a���ICs���z�wl����+<����_�z����{���������te�t5[:�=�z�����r�c-��=Jy[��5om��������ha�v{�� Nb�$6!f"�ry����O�1�0��/�+����O��Ot��l�������1!�����bY�k���P����|(��5Jm��C)����0���m��������j[[[9w{�� Nb�$6!f"�rydi����>��E;^�vQ��:������R��AS�:;��.]T����H~�_Z���5%�n�C9����&7=�R_�C�E-v���7�xt� ��'������vc�SA��&�IlB�D(�r�mK�{�?�N�\8�������M��_�#�t��
u���o������z5?6��5�%��r�]�O�lo��3�����li�z�����39�����u��J�;�IlB��&�L�R.��o}���o��_;��In���W�#�PPk��S��x��A�/y��c�;~��t��q����)=���yi��,^���-�����g7sh� �M8�c��]�S�m�Nq�'�	1�����[�����7�g��Y�?Nj�t��u�}��su�3�u�kO�a:W�0aL��I/m��ykw���d�|(on()��-vg�����J������K���� Nb�$6!f"��N>���._�z���J��3��#��k��������s�1�����`�������v���3��5���snX���<��g�������9�7w67m��	�,��+.�t5)��kJ��������o-v���k�8 +gXw�������w�R�SA��&�IlB�Dh�L�4�]�zW�l����ZJ�p��q�-��%c���E����n_���v�Ux��KO����A~1���l';{�������ltcC}��!��)93l�W��f^z�k>�#���2p�|(�-yb�?[��
�7�������2����T�� Nb�$6!f"�t7�x��������SO=5,�����l�����@(v���.]����%���#�K>���_{T�/����2I)�s��_]U�~i���m�n�U��u�	��x:����W���e������?�{g�.�^TP[{�D���h>��|(��wg�|(��b7�uk�w�5+g���;���P|��8�M�������R���;�w����/��P��k_�ZX�������	B�C9$������_�rX~�=���X_v�+\5��t>�~�����x)��lhj�u;�2����
�}�m����go�����P�j��5�t�������|�|(����R��}�s|V����G�.]��5���Nq�'�	1�����������O?�t�lass�_��_|����(����~����������=:,��o~��b}���p��O�4-���Y����;���)����wz]�E�47L�����������_e�C���n�C�`���=�R����0a�����S�������>|T��@�|��8�M�������R��_���A��n���7[8o����{���W\����/��/>����?X�pa��~������Y�?��say��G�����}t��f�>j�2~��-I��;#�7l��__�bm��S��xC��Y3����{����]�jR1o�t�}��'E�C9el�����Mm��wTV�o�����|��kq��
�$6!Nbb&BK�a����y���^ziX������[�=�y��i��b{��WX��Z��u��������Q����n]9���	~pp���������dV���@��6u;j�����
o?�Xz�V���l{ee��I��~�}��e�ln�z���H����6�9���aw�;�IlB��&�L��T�l�~��������I�jjjZ[[�|����G��}�{�{����/g�e�h��j���1�Z�Q����n�����w�r�g�U�\s�+I~���[g>���=�����l��cf����I�U���[�T���e���M���S��=x��Bi����c��b�<�\��j���k����`��?_������Z�$��fF��~��Y����x���_����,����=���#,���X^}Y7�w��_]��-\s���>������d6~}�;e����������\~��������d��J��x=9���g�<��u�Z���W������������~����=��K�]�?`�*1�����B�/_
���>�_�����_�����e������Q����n_ttn����f�O�}3��hO�4�{u��a����F�8�_���}g��t����#U 4�s�|az��P����o�4lz�������u������*Q��
�$6!Nbb&B{�G���������w~����*VSS�����=*�W_����M���������������uv�zKS��8��������M
�?�j��������?�i���I�*]G�C��~cC���������STY�7��7�;bfb&�:&:&�����&���k�EE)�}/--wK�}GEqGEAqCT�Q�7Y�}��w����I��*d��{��~"��+���~O�y|�=����|���	��to���*�Y:4�y�(o@|� �	@&d�dHhWu�Zh2��v�}����+VTT$�����v�a^��\��b�������i���+��7�V4	=��V3r�q	iD�=�Hk���j}��Qm�*�]��#t^g��z~]��C�pl��IMP�xE�y2S���v5��O���b�k��0|� �	@&d�dHhWy������t��W��J���-�9i�$�?322;p��t���S��0��y�?^���Cf�����%����i��1kshOc�v��z�������Zc.���b��;��,�?�������y��������W����HE��q�`�ey���N@&d�L�&�����Z-�����\�v����s�J�'%%��gVV���={�T<��o�m[���������({#�8�S"`�������{���o-b�
�E��{l�C��j��Q�s�����m)�?������J><c�;���KR�M��H��rAh3�8G�����o��S���BP�Eh
����l�	� �U^��w������������f�����������?���EQ-s8�|�����������,+���!C�{���?�l�.=�+����j>�O}��(����^���<c�tO���F��M���mu:����n�51�m	�4m��rj=F�f:3c[(q������������0�>/6���h24�<�S�w��S�	� �	@2$���w������u����������6m���a�������|x���t������{�Z��k�;�����O[��8�Mm�����'�g��^�p�����g�$X�Z�������o��i^6&/?I���J/:)��5���>���S�~k
�;��M2!�$CB����\�r�w���|����������9s�N����������?������������]�v����o0�|�>�^�D{��Q�r�e��6o��c{�z
�	�ZCh�OL�k��\;�X��b��MZ��.����>_����1��FG��
|�!s��a`��fhY<[0)m
�N@&d�L�&��PP���!�+OA����}^��P�U�q�{������Y.mGw^��j���6��2n��=��i8����ms�[.�6&�Jv�W�b(XL���CC|}�F�� ���
�L�&��M�!���#w\�R�������y���#������U���Z<�
������I���]7���w��l-�|�>/�z����<c�l���1y�	W�9��]�r�}�Q�m��D���&|� �	@&d�dH(�"���Sx�}�_b���"z����;�^�oj�3d;a8��}�j2�}�:����=�3&�������[J��b.~�rcr�
���&��s�Mo�3')
����gE�}c� �w*2!�dB6H���*���T��U����1�
E	��{J��m�y�\����t�O4t���r�E|��=�����������Ld���p�.�nE��|E�:�����]�0��#e��c��A��TdB6��l�	U�(�,��FQ�*}�f�;��A�s�)��R��
���v������Kb���D������f��faF�������\
��<�UU�&U4�&�^U�}�����l�	� 
�����g�_;i���E�4aHk{����F����Lq�A�n.��	1���*�����VB)���ug�+%�����;��d�@�Qd��-�6���W����\TC��t�N@&d�L�&��PPE�����3�����m��A'?�*��Q��LY�����86E�\a�j����.�f[��-v��H���M��������n���������M���?�o�����TdB6��l�	U$�8�z��_zy�G��<��g�t��)�mnmm�y�	��U�������Z���s��>,�fI?�������F'�>�ec��#�:C��D���~��`���-.�	��S�	� �	@2$T�� ���o\���c\��[��V�t��|�S��Z�x�k�����~�#�W����1A�]Z�BJ@g�k�������T�\c�L�c���"5C��_�9po
�N@&d�L�&��PPE���+��[�>Fd������L��dy��]���tp���B�oW_�=qg�S&mV�G�&�3��S�1m/(�r���^����Qo�u��`h�����7P�S�	� �	@2$T�:eWk�l���=�����^��{���;��r��D�������Z��l.�������vU�a}]������� �;�ec������v�:s��}�V�m[D�3po
�"|� �	@&d�dH(�Ot����Y�S'2��H����C�XF��:�l[�Xv�e#��i|�O���3�7�l=�����h=:M���o�sCwt����H�c(:P������)
����lYI��@E�N@&d�L�&��P�����j=��u��L��v����'�<��;�||RC�� ���+�1�vc���
�}����k=4YA��i���������QWJ���TF�.��v5���i��\�i<����TdB6��l�	��b����u=}��,�l���z�<s����g\lb�F�����8"�=yV�G&8&.xR�f�d��L����L���(,8�ec�����@��{Qj;H�dh�:���	�;�����l�	� 
��7
WO������>�x����{�����1	�-��m�~�����!���m��/����Z���A_���� �i8c�����TnL�Lp��e���lLi��#Q�i���>���S��"�W*����TdB6��l�	�U4	w��z�����~�`2JK������=����7��u�*1�H��(���������������>��� �i;c����m��e�a�V�r1��S�o�h2��2	���
�L�&��M�!�����|a����<W]��������b;�-��,��;���$M��'i7��+�>���v���K�qAX a�n4�-��(n�:_6�
X����~U��������|FBB�#d�L�&��P����|Y���U<������o��b@��S<��W����!����Z}���k�����V-l�Vk8$+���*�����D�sl����1��vY���fh]�X���v> '���	@&d�dH(�/������g�.���y�m�����������^�>�{]��OtV��$�����+��sd]VBQ36��3���7*�l�.q�����{k����`h��y����tQ	d�L�&��P���B�)�3����w����{������Q�}25����O8�=������m����E�	�0 �8c����Nz��,��EcB*������_��F|j��I�i���+L(��MR!�$CB�Y���e{S�W��u������I�{/���P}�'���4xG�������m��4i�@B�;cT��w+��=�96]����(���4e����8nWQ��{t�	s�&��M�!���#�=���^�"W�B�i�a��O>������G����t���n�s��lW�'��~_�gl�w���t���D����1�8��d]d�v5������qq�
�	g�&��M�!����cU��z��]z�eQ�e-~����.qE���O������nNNs����>>�o��;��3����|"���~gi��E<���q�E��y�8$4A~B��	@&d�dH(������uz���]z.[R���c��Hx�)����'��9����W�j�l=��9��v�t��I
?6������
�h�C�.C�I���)
��>_;�f��F�]
n�M2!�$CB����o�N���O7���z����yJ�I����O�{R�uk�0�K��#u�������	�����Ls��o3u�@�����;������e�,�hP����% � �dB6H����R�_m��<gnW��<h�^���n���E�b���8��z=�G����z�+��T��}��Z/��n7c���/�'�:���|i��.��(�#�;��}#���v	�&��M�!�����g<k��e�|x�T�����O���9������{;���~�����O^�7���m;$k�	?_�O�t�.��'�U6K�u9���r����Y}�o��m�
�r��Fu���<d�L�&��P�_�/��U����}x��ue���%�����]��rA0;>�������Z�;�(��$~P�14$������}gl^pg?b�nR��c7QY�,��%��F��I�i�8�[\���t�}
��M2!�$CB�i3��n������E�����?P3l����v��fK��B��B��O"�9��`|�B���d���oZ�t�/?�����mr����=;4�Kq�|��(P�3t�_��X��H���X5�����P�P�l�	� 
�������'=����S��=���|�l����u�"����Q����{�>1u�b���f�}��S�`+4@0���]R�O��ec��������d���i�0��8L&����x�FBB�	@&d�dH(����5�����:��&����K">Z94M����?�X~�u�g��Ob�K��;�D��-k����'�NF���!3c���c6n�rcr�D��}�S�<����m���&��/���WP]�$ � �dB6H������=r�g��rA�7E���#}�y�8]��i8���u����N�����
�����>1�����p��7ol*�8~��B���iEy_����,�Vsc2[\h�O1]�gM��U|�K(@�@6��l�	?�)�����8}�f��K����K��e����6��o|���w�V[ZJCwP��?��q<���Kb������ $g��7^�!�r�y�U���"��mX���\����!�P��l�	� 
~j4�7�?�>)��r����T��	�=�n��__:g��c���z��'���m_�D���	��y�:c������rcr����wYN�6C��uC|�b��.�'XL����PM(@w�l�	� 
~�j�������� @���k�mVF���I����mNL����=����m����������Z����T�3��)&]��1yT��a�jC�h�,������ypG�����	���M2!�$CB�O���g��=�n��V��p�������t�i8����r�l��l��M]�W���D~�p�=����%f��&a�/��f�����y6[��k��`KZ':)���P8$�;B6��l�	?�W�/cZ���^��D���q����08��
�����g]*P�x���-���r�[:lL��H��2�;�����:������q����:o�'L
�� �dB6H����n�r
���y��������
������6�����N;v���x�+�fl�K�v����1y�.��K�J��@������T���?���T��pV	�F�M2!�$CB�O����������E��+�u��>^wN�=��K�d X���o�����=�zcR���\E�q� ��`�2�]���C���t�&��M�!���37
��uC���N���e��o��zc����/��g�Y7x;ev�VD�;�7p�rcr�zG�M�fUx}���;7�=]��{��>��?!@��mB�l�	� 
~:q��������z8��	��kL�u��U��soD%�J�p�B ]8��Z�u��LP6�I�~���a�q�ahE��e�O���*�!/�
@2d�L�&��P�S��2���f����5�5���r���|5��3v�N�}����_����*lL�6������>�{��e�_B
@&d�L�&��P���}�5u���Z���N��}[
�[���"�97h�rcr�zG�u��F���������fh]��h������P2!�dB6H����������_M�Y���2��#��c�:lL���Q���dA�l�?MQ04�a
��qUH(��M2!�$CB�O�]h�-�e���e��j
��L/��v�����,��S��1oW3����#Q�i5��	 �	@&d�dH(����,�:���UZ �a���f7dG���	��y��{����4u����8vWQ���!� �dB6��l�	?��;�YA�'&i=�P��}\�{�
&j���p�6*������H�����]�0�s*#���,uh���	� �	@2$�t��d���iO���e��?��(,8�ec��C��f7&�e%����&C��q|C�*�����	� �	@2$�ttRb����@(���w^��w*7&G&8v^a�_�E���%AQ0����y��Z��n
	 �	@&d�dH(�)k�r���~����e��;���n1�6&����}���d&��aP/E����L��We��}!�dB6��l�	��;g�|�z��qE��2��]��$,:�ec������~mL,f��_C����5��
@&d�L�&��P���%^<��Xf��zD�3�T�#v)7&G�sl��H3�?���=�����fh[�\t��<t/H(��M2!�$CB��V�n�X�2�}�T��2���ayw���e���-����?C�m�y�����qx?�)���
@&d�L�&��P�G�N(�7��F��+�@(����&��4����i�/���,
��C�^_��F����"��z��n	 �	@&d�dH(���A(����@���@(����G��Q����a�u��h���6C�U�i�0E��i�P��B����P2!�dB6H���?
���^�y�������BflUp�;��Q�d�D�{��>�9���]��]�0��h�[��P�.�P2!�dB6H���?n�sM�y��n��zD�3��tVq�)����)���
����'��M������7*����	� �	@2$�q���Y7F��pBfl���c�t������m�|�2)�m�JE�P����u�AB��l�	� 
�8�������pBf�@���ll"����L�.`_7&�wn��5C��y������ H(��M2!�$CB��s^yV�5�h=��;p�6q�/�'�:K�|���`2Z�V
�����<	 �	@&d�dH(�#+����=R���8�����5?~�rc�t[�6:|�2t�?���FQ3�m^#:)u�CB��l�	� 
�8�����������q�����Y������{��y��?�����(G�g��=|�
@&d�L�&��P���������s�@���4F��������:����1Y��i�����#{8��rs���m �dB6��l�	d�=��y�2���0cYI?)����5gh�������r����&C��#��W��	 �	@&d�dH(�#sI�g�[�f���q���O���~���c�cX���E��������m�P��K��L����@$�L�&��M�!���#s�zV��[vh=��[+fJ�x�����p�ga�/��������&C����������AB��l�	� 
�8>m�g��&5M���8���*m����1y�)Zg�r[�h�Y�.Q�q��y�1x$�L�&��M�!�����k[����k=��[s��>[��%)7&�ltd�c����7�����ZW-m�	 �	@&d�dH(�#g�������Z �a�&��)n�@�\�l2����U�+��^gY0]Q04�a
b�8H(��M2!�$CB�g��}i�l���u���#q�����Q������K�\M�.oLv�>����]�0�S���"�
��!�P2!�dB6H����(F�1p�ga�>)�zD!36iD���Sn�����wX��m�|]�i�hE��q�@�Ei`�*CB��l�	� 
>����#<KZ��L��8��d���m����G&;Tv�b�;��E}��f���W���T���	� �	@2$|Vg�����g��Z�G�0c�����s�����E�]oLB�^�-+1��W4����4K8$�L�&��M�!�������h�JV0��@���M��g�[����;�bh��#�����C}�W�3'6v�
@&d�L�&��P����!������V��8�����w^a"�M��wRw^tm71���aPoE���p�`�h��$�L�&��M�!���{��g��6�3���0cw#����C^6&/8�j0vac�`�XW,P6��I�����7H(��M2!�$CB�g�=K��>�k=������Z�
���������b��:�+���S�m	�D�=`c�.CB��l�	� 
>��W�Y����z8�3vwD1��<&����!;��e]�����d�3EQ04��>)���K�P2!�dB6H������.��X���z8�3v��Z/�9�ec��LW����E������e��aD{��a9|�$�L�&��M�!�����<�����k=������Q�
��acr�#�C1b'_���4M�h24M�U������P2!�dB6H��������,T+����pBf��d���L�ze���mT��NoL�8������j��_PG��.��BB��l�	� 
>;��Bk�p�B���0c��z�0��������u�-��%E�q�&C���|cC@����	� �	@2$|vb�����KVj=���;��~�
�������u���NmL)���ZQ0����u�L�!�dB6��l�	��X��z�IB���}��C���n2�6&�J�>���d��MC|��fhY2G0�:xP@B��l�	� 
>����Y���H�z8�3v�j0	���1yF����S����d��`h�!��w3��$�L�&��M�!���SS=k����@���������RnL�X��v���:�1�u��>�E���i�HQ�<��PR!�dB6H����r&���F�O��z8�3v�c8w�m��e�a���S�3C���<c��`h��|�a	 �	@&d�dH(����_ZO����z8�3v�h2�KNx��<�������:r@�y��adG�7��k!��P2!�dB6H�������Y�:��i=���;�<��G%;;nLN�H��o3�*_�&Q4�&��j��0�����	� �	@2$|Cs���c=+P��S�G�0c��w�����l2��D�{��+�cON�E�h[0�������;ux
t	
@&d�L�&��P���!��Y~r��Z� �a�O�VqE6�qc��4g�����'����&C��)BsSV�P2!�dB6H���oLBY����'�����Bf�p����G�1��:G�y�B}��Pt����*
��~���\���
@&d�L�&��P�M�[���w�U�h�j="���;�q���}�O"���m��<f��mL�o����T��+
VKP���P2!�dB6H���o�k����<�M7�k="���$:���������9��d*:���C����C�T�$�L�&��M�!����R�g�����������5?.�������gi��#]�����1_)j��mD����*$�L�&��M�!���[��<k��}��@X��
m��;+�������w����?x�	_����E��8:�-+	��C
@&d�L�&��P����j����Z ,`���vq]����R����������������>sL��%|���	� �	@2$|s)��guY1r������}���S������`���d���q��&C�Oc���A|�@B��l�	� 
�9�����,�0Y���������~�������H�g��oLi�}�E�P����� ? �dB6��l�	��I�k�N���p�fl�(�C�p�����pl��I���3���(j����.h����P2!�dB6H���oN%��VY��p�fl���a�>/�W��u��nLmV����&����7�s��
@&d�L�&��P�M��#����	Z ,`���DwN!�����'�:r����f��zQ��;E���v�h�q��
@&d�L�&��P������U���;�@X��
]eu��.�=�)�G�vT��b(47��NQ
Cc�'��9�n	 �	@&d�dH(������%����Z ,`������y����$��������<����e��a����$�a�;�n	 �	@&d�dH(�������c�!��	���g���P����1��FG��}O�!W����HE��q�`�eyp��= �dB6��l�	�\���rl:}^������'�S�r����1yd��A��*��#u�.�G��a��Tf�[�;|�!�dB6��l�	�\>���$������A/����lL^|��h��1�}��8"N�dh�y<��>��'
@&d�L�&��P���A�<F��@���������\��oUnL���q�6�p��BQ��kC}�7����>|B!�dB6��l�	p�;��j��(�zDa36���w�2�	�&������7&3�n~�R�-�g&c�O $�L�&��M�!���S|���N��k�@X��
���Y�����1y�1W����	���t��`h�����������	� �	@2$|�d_�D{��Q����fl�+%�����;��dh���]s�}�Q�m��D�
��I���	� �	@2$|P�,4D~�Y�.��#��!�(ZL��Du��<tu������7�C��~�����H(��M2!�$CB������m�gZ \`�� ��	�{��<�����ac� PG���hW3���H�����$�4$�L�&��M�!����g&���.�;��.0cC�\/�o��19��dD����
����&C���\u�&��

@&d�L�&��P����u�����X��.0cC091��^�d8x;u�T�1Yd��-��m��^_:Ov�^�J	IH(��M2!�$CB�7.��,_��p�fl�:�0�������jt�2 [��0�����<�G�m�&�2$�L�&��M�!����Y�=������@���
Z�U�
��acr�#9���v�E����LQ0�����{^��

@&d�L�&��P����<k����k=�p�4D���7�lL���R���L��3�P���,fMH(��M2!�$CB�v^l��\��p�fl�\�QXp������W��6&F�e�E��0�7�W��
@&d�L�&��P���
'[�����z8�36�n?|�rcrd�cG.cw���������ZQ3�oM]N�8H(��M2!�$CB��V�{}��7k=�p���p����^�M��[���\��!__k�6VQ04��g�J4}` �dB6��l�	�[��z�IR������4�fq�	/��t�lj�1�����������>s���~I���	 �	@&d�dH(����D�r�2�������L*���NE�0b�c�%��lm3�^��T4�����j����P2!�dB6H���.������9rZ�����@,�wg�a{oT6�O�.q���E�e������m�P�w���nQ��;tH(��M2!�$CB�W���Y��9���p�fl �[���$�qc��4g�����L���E������^�������	� �	@2$|ps������w�@���
�BA5?z�rcr�u�Mh��mLm6��_C}������_��P2!�dB6H�����Y�����@���
�����g�$R��a\�S�
���������^Q3��Y,�m��GH(��M2!�$CB��D����`������zD�36t/:�������?�w�6���,����MU
C�0����P2!�dB6H��BW9h��O_���oj�zD�36tGOj��)6&�ul8G��u����}�/��#>���$�����$�L�&��M�!��U:�X��;��N�Y�@���
�'�����6&��Le?z�1�]m�2J�dh7��(�z�����	� �	@2$��V/4E|�Y��y^���������/�'�:����Q�q�}�t�=���?��w��^^{H(��M2!�$CB��^T;<��7Q_i=�0�B@q-?!U�1Y����
v���}^l�_�dh�>�o��z����	� �	@2$��&O�������/]�~���������?J�;l������a���7O���,�j�F����Q��!4��;��w�rcr�&*+��~UtR��kC}�7�s�Z��C�P2!�dB6H��vIff���{�������_jK�g����{�W�<�3�����^�P�5�30cC(19��g�����8�^�����
�5C��Y������CB��l�	� �y�������������V����'��#F���1#�o||�t�'�|"�g ��?���;J<���a#�A�$��zJ�����lL^}���D�b�.��(�#�;7��H(��M2!�$CB;����c�����~�����^��������{�n{'����?�#����@<�+��I7�=�,�J�M����0cCHD���l�f���>����,'�]�r�}�Q�mV��C������	� �	@2$�3��_��w��������{�������T��{�n��i���a^���N����g��l��_:	36�0%&��{�S6���|\��M��Y�C��~l���
	 �	@&d�dHhg��?����v����V���W����������_
�������ty[�g�V<w��/��B^�aj����+��fO��E��f�������Z\���	� �	@2$�3���{���o��l���������_�0��yn']J8�Z-\���@'a��p ��sO��I����7:�e��/M�)�M��q�*�8
@����&����}�y2�q`���:r��{^��OK7���oj���c�� �U^��-[�;�!�t:�����?�a^���N��,����k�����I��!|��b�E:����Q���/��=[u=������g�EA�1#���8�M=[���{�J�[�`f����c~���R�o
���~k��8v�y���)��+��#-YzM�����wn�5����Qhn����f��	@2$���V�������(*�A�_��@<�+�����;3}��K����x$�?�\>n������S��j�K����4��J���� yr�����K3�Wl�T�����l7��D�J����#���;�n����'�,�Q�xne������SvJ��c���8R|��4_=�{G��E������?y�jaWx���?��t���R����������x�W�<����9?y���������
������9U����aT�m����y?+��oc�*���&�R���J��G����������uS���������
�xk��e��^�C��M!�j�O�Y0�j������Sv��+��d�~+�)(��OB��O�\/M=�r�����7��i���&}��q��1��]��Z�������F�Qq�^��������@<�+��Iy��x��T?��@'���Z�@v���2�qc��]T�����V"������A"���6�U%���3'�����f�y���>������3MfY4��m�|��������-�	����s�G�7������H����PMSFI��,�-�I�Z~(��s���LA>��1WS%o��Z��P��&@�Q�X�V�Q�e�cr���/��-��GB��k����?��,..V�_TT$������a^���N�9j��[J���� t�SA�����Hwu�2�&����3;��{1�sxH(@g�o�gEt�%������Y�	C�}�U��6��y�$��%���/v&�>�UW�{��*�l|S#W��}��)|�r
��J���mI�m\iY:�<g�i�h��~��1��?z���R���~-�Q��G�c�6�J�Y������Wb,~"�����q�k���&@ ���U�p�w���=#���������}��v��j��I��;322�8p@�����x�W�<���������#�_:	��$������D�w\�|L��k��XZ��lS$�C�(������\�c���7{�qx?�k_����,�!��e���^l)s)�l�o�:[��}���}��{�y�����oW�9)���� 71�~�y	��7C|���8y���(�nK?E��wM�s�&���rcU���h6���;|n��������|V>��=/�5x{�
�o}�����.�Z-�����������o���m�N��y��s;� ~���������N�w*�Z�u��LP~�����n�X�:�8j��l���PC�^�>/���R�2��7Z��1M�������!1���[W/r�lw�>����UU�6k'I~6E��{��^�}}��,71f�Q�{��U���������qr�����?~�����q�$��q�"���''�5��rc�%��}��ol�~v�a��C
��M�����(�W������������-������\v��r�9_���F�|l.�U^�����O>��>|xyy9����2D��O���f��������,����S[��@'a�h�Z'�>�����v��=����[�F}�HK��:$B�H���� �u������rk��8]d�K������2��i5����=/���������j6]��Q�E���x����x����(����h����'5n����r	77}��r��!r��7�������x.[nb�[nb�(��
:���_��M�4Y��j��cv�Uf�q��=�����-2�16����+�*�S�>��uV�}���v��j�d��M������}ZZZ��u0�|�o\��eL��3]0��M�$���=�mS����E��T�CMSG��5�	
��`4p���[y���;7Y��3Me��T�"d��4m�u�B��-�����\E�`	��Ud�C.�65�
u-}}�+�&���r��Mr���r���-����O5/!~����q���q���qG���x�`K���&��:��1X����@6<v��5�	�'�Y��������`���Q����v^aN���S���
	���U%���QQQ������?�������v�Z@���t�-|`t�
�_y>�E�S������
���)�����{�2fMLP,u�1wf�wq
���2|C�����Y����+���G����P�������+K�/7�]:+�������'�Pb�Qx������SU�����������\�wR����2��DMHu.:��z�9r��{�����"<	F�����\>����w�t�u�51.�.��2q��Q��!���}��k�c����S�51�%����d�����k�e%r����!�����y=�)�z�Y�MOJu���WaP�
�A�?��v��z�������|$��A�z>g�F��z8�36�H���e*7&��{�U���u�e�O��Y� �@�b�*��;7��G��[�+�~c�V���f��4Me]>��k�3+�����?����t��?�E�����������c6���f�&�sJ�&?�]=�:���fr%���o2��p�����,D�E��NUn����]�7J�8,71��"71�Y,W�f����Qq�"o��}������M����M�[��U����51>)��kk�&�.����	!����y%��Q��4=e�3v���P���OI�c��|�N`s�$�������������/��>�f7�}�����g���l,��^Z����H(h����yKi�y*#��i�������1W�N"�Xg�3��a�����3LA>_W#���X����$��(��r��������������~/����O�&�s.�r��eN����#�
v�#�@���&�W�r���r	�R��&��k�&�E��&��#�&F�K�����|-�CG���m[�\nbL�)71�:&71������[��j}'>7!�P�X�$�(��e���?p�%��i���~����y��U�U��L�f	$�������W�/V�������b��n0Q�/��tF��^�)�q���D5��j��B��6+WU����<}���]��k�>�08F��F��M��[���/�v<��q�-}&�U>KB�������q��x�>�rMn�w���~���ZV��E%8F&;�vI?K�m�R1WX�7�W����wM����&��W�&��G��^R��[���T��#������R��Go�A��&�����^����u-U��&F� _>���Jnb������&tS�W��f�V9w��|����]�[�����L�t����q��^��h���|��B�<�Y�� +8D������'-�m�1y�����(eCb�����#
�E��Q\��r�:�fKZgY8�8~�>�uk���'��9�'��e3�q5�DJ���.��,>}�K��sO�������Sr[��d��
Z���&j�.Jz����~Mo�Fr���Q�Ick0	6��
3;����_p'��W��GMMs���S�~�JI/+�xr�������h�Txu�E���&��Wr������*71nI�����������.������o{��ZJ��uK�&��mr��L���z���X��]#OD��@>�w������|��l�aW����z�M�~��\u��w��R��6V'��H(t��s��O�����@x��
�U���m�R�5��)�
Q�7iF|j��(������B'�;W]���u�=�H�i]��<s�aX_��}�5MjY4��5�:r��v�-)����[�X�V(����=`S��m��qMM��{�R%�����>y�sn����'����JCz���(4YD�����l2���(V�W�?x[�gv��EE&��#�����)��m� 7�H���o2�<��]c�3����5����q��q�.��o��wM�c~���.��f����'���)����51^�������*��^��\��M �4�����������49���.��S��O�{�3���:���6S<
]r��m����	��@x��
��s��D���<jqY���E�q� ����7BBAA��eK��k����[�[�2M������zh�y�D��%����,���U�h�e�=E�M�-��NZ���f�^���>��k�ng��������CF��t%��7��y,����Vo,]��S7��X� �(�����s�%'�sU��8��6x;�s�k�i:�#���_�U����m���B�r������W��]��4������^���k����M�j��A@nQ��Lc�5Inb\�H>�%y�\c<�!71�]j9��oz#o�f>t:>7ACoL�9Y���W�_��F�v��o��Z����>v�1g��Q�m�{�FB�Kn�^�|X<��@�����>��.:��19j�%e������-��?���y�D'����Od8���l[����W]��*�����
�,���y�|���-��v&��*V5E�������r�������m��v�}�6d;51�9��K�%�1���mu���7r[ '��g�l:��^^{�{�I���r�Y�T�KQ�Q7Q�:����K�E��J�gu|��{/HAA�5�����M��n�M�gO�M�i�����+-�~���
�����@���{�M���M��Lo�)�{+V���Enb�[nb�(���z�� ��mba5���>q��p�KqF����s�c�n���r��t+�����������������+�@x��
�����]���yX�X������|xq$4�	[VB��J���H�,�k�<BZ���6���ZW��H��<}��w��|!X-�����k��������.�5g���1{��[����1|'53��4�����>��T�s�-�� �����y6��bI�W�e�c�\�=���������o��C�u9����=�����A==4$�.��������u����x4]nb��Inb\�Pnb�1��3P��H�1����3�i��Od[&�<�^(�R�1�O�S��7�0�.8��>UO>d�o�u!L����'t/W�f�V�m�z8�36��X��q��|u��Jd�j�"�����'���Hhi��{-�zp1�q0EZb�����L�%������1?X�Ok�D���g��o������mbu��������l�M�-��c����@�	��
�&���>�Z��u�i����z*m���<���l�]r�����������O�k��r1.I�����������R���{x�u���^nb|Y.������Q������kb\0]>�e�Py����*��$l��^��rj�{�P�u!������N��D����)}��9�J�H��g�V�5:�#�s-8���2]Y��3om���p�fl�4Y��Y�����{�X�X���~($�LF�E)}���d�=9��|�i�(C|��+\�Q����+���8O��\�*�:�@��_��:��K�r���#�Y�#��Mq�������� wP�Hw->!�>x[>��j���Z/�����]6E����������;���92c�8{oT��;2�1��3��?����O��j����{��n�e~;��MK#}����x�����{����f���8{��&�������^_Z��D��_Wk�;Aew���_/�?"���������c�V��.�<}�>{���j��ch��}z����l�L�%;i=���@]�^��v;����xsa�e�g@}�Z'_
	%������.��[eWI�L��xi��fU0�s����SZ.�����>��k=��7����x���~��%�.:��9]��]/�wHu�6p+5.En\�C���Hk��g���|I=�d����R6��X�$�y�K������O�/)K�hi1����>z�!{�'��5�E�A���&���r���r�����V/��b�,�%71N!71����1��m^#}F����jr2b�[�f�|���g��U��F\5��sm}���_��I�hLhJ���~Z������z8�36��8�-}�������O�F}�X���/)�G_
	��`1s/���7�����l��Zh�>�0�����"L?��.�g���<q���'_��Y�d���*������$��8~�s����F����U����Z�N>���O_���p�v�dyw�Q(��/���*����������^���;"w��lB���5�E^��i L| �|�k��L������������'S�i\�� ���pn�����6��|2�@�����&j�~���t�M&��+#��a�	��p�����gf�<yY��������+O�-�3�,�����b�8���#�CBKZ�������m^#�"�c�c�R�*��8��y��������S����/}Pu��v��m)�,9���!���-�������=r[��3��\�-�R1w��V'���y���<��X�Fn�9�/W��f�&�s�OR��=h�\��V�)��B���+�b���l�4�<�g��h������q%}��h��G�N�w�^�Lk�Cv�%f�����B1�R�+���������h�VW�zBW�9�3�����p�fl��*�����7&�\kK���1�E��g��2�{:�
i��U�d��v�9���]���	��}�m��}o�8�y���u�_�<�(���#������'�:�}��nQ	r[���������7���w][���
k!�^�Xy���������=���2xOU�z�I�����n']�3����,��K�Z��@��f�olp�dY��������c�y<������W��j0
��S�ex��{����-z�C�I�f����g�����g>8��	]�p�8�$��_��p�fl�@���l��zc}�8n�bb�8��z���Hh��o�gE����4����3M���*���yk��f���y�,������M���(�U���c;���[n\}��vYn�������[��b��	8d��tV������;z_�Zt\.����rj���ff�����n0g��*y�<.&V|���2L�CG�6��Ao8����[��r��!S��f���Z>�=�*���|S�@�X��G����������������i���+�2��%������k��������oj�����#��X�[T^�	�H�\M��y6��o��^3��d�O��`c�7UC?��s�Ok2g�l������/�
B%PZ��)�������s����'5�6Li
�����M�8h��YxP)W�^g�yrF�
�	�����T���m��c����C=�lC�*���\N[����o2M�H����\m��v�i-�	�r�Yv�5a�����F&���s��Gl~�|,;�N|zB�����L�tC���/���I�J<~��wf����m>�Zn�Y���7m�	t���b�z.u,��m�e�l��a�����
������q�F.�?~�������2naq�oW�K�F%�m��N�[.�����E��ry�p�Yt�	���l���&�\F�}���n�@K���)�U��)�wQR������P�T�u����}��q��Vv���^;q�7k{���ds���k��]]V���f�jVoV�z���.�KT��{��7�$��9�3��P���9���>��g�������?sH;����sq69�Uwdo��/P4}?��Zd�{�h�]6�v�ZO�
��8�������#�������w�(L/���6��%[���	�q�5����KuZ�g�^�b�2�X/�Y�l���������5�|,�hHn�	�F��c�1��Vwl�n���9�+��[����>%����1}y
�ra������ve���aK3������y��8��a�9�-�����t?�����K�{jO�}6Y�5P!P�i��p�~/������]�]���b��]6�y ���Q
�ZL����Z.��Rc���]�D�������^wx�%&�����Q:#����d^}�4������&t���S���M���?��.CU�M���V��.�J�������{��
���:���xa��Yw�ztit��]:����Bj7	N�,�	&?/��3�{�/�j����_x3Gz���F{�w�������v������(rU�@8����
i���;b[�g4��,�U�#���fh=�&��	�[�Ht/�����4���B�
��"v�P'<�����?�~��9�������MJ,�qu'VO���KG
��?yF�+|I���No������ ���i'\�=����~���	�)d3J	���n��	�i*�ZZ�����v�b�(!��p�0pY�����b�n�o[	�f3_�g�
3��Qw��n�����+G
(���K��];����3x��Q��}�g���3��X��mMu3OO���O<"6z�z���u��l>�Xl������M���)E�Q
w)����x{��G
���q�Nq#��WM���W#,�i��F������Ij�M^wu�W����U9vp�����P�p�j3t!g�*#�����������v47D}����]s�t����(v��Oo����\aN��~�����t�Vluj�a>-���\~���Yd-���#�U\Z�)��p��p��]����1JN���=�����sN���u��E��LX9`yA��Gzo���#�.�l�qN�[nDY|�����J����p�lLk^���o���Ln�iV	a�����U�^����]�v�t&�� �{�}9����b6��$����3'�wup3
M�k�0\���U��C��jHP:1������;tWs��o�$����{��x.�������'(��X�pQ�>jO��`�`A��n�4��.=h��F�y�>�$��0'���
,1�����'�6���?�r� M�N.,	�ty7�w?�A.�\���=��^�9�o����*�:�[��t��-p���l������m�<�W����+����'Il��y������a�{���k�I�����>�Q��>��`���`!������P�yU��^�G�����HMFufK��$4S�������_�m����������~�6������J�����Ph+R�2��2y�`���v�b�#��|s�n���]p�nY�w����r-r;o���2RMA~�kuwjW-������Fv����
�����c�m�td�L�I�-�U��0b�~�i��K���������D�-0��T�3�������hv�XZ���1��.^���nW�l�}��������|���%��Z,w���M.+C�D������w�p��S���z��|^N������g��at�C�>���K�:i��[g�\4�{(V�#��F{XK(�,�7QZ!���T{:n+6S(�zFs3��������Q#MYYM~^���e|p[��n�����KG
)��������.�z������K���n���s|F/N��Jc�Dc�.�����g�n��s���b[�p&�T(�r�����'<MX�����	��@��;���_4|���������TAX0���][�Y|����q�]y�f���@?��u�#�:<�V�#�M>T�o�O���1�������y�%��C�������Zq�������FX�2��*���s�M(0(�v��*���Z����������c7��p���n�R�������qY��.�l���pI���y>wm�`n�O���7t����wN<�l��)��]����E�M����S��.������^	b[�pz[���������hF)	L�����y�Uq��!;]��8`�~�Q��Kb%�b���lrq��?�D6�����5�Ns|s���U���?w��L����u���wb�C>�WL��o3�Q_���?'v�^
���y����k	F�_����q�������
���b�f����_5zRJHZ������6�\�6��)������U��^�wu����������9^c��^Y&�Jg���m��o����Sb[`H/����Ps�\9
�=��xb-��������e�-��s���
=6����mC��}��g�����8.*Gl	k���m+��d4����\9z����!=u�VV����^����3��f�|��{Ks+���|�iq�!�^���Gph!m+�������0b�|���v�b�,"2����[��������Qt���N=7j��	�O�:m~���2{n��G?��q��x�y���Jx�V��|N9��u�~�'��	-�����G)��0��r�/��3���v��;��7��b��%���i|zI�����f�/*0��T�x������e��	8v��{'~�yM�S��n�O;a�g�,�,��q;����Ph}�oJ�^���jO��`�`��������;9=>mNU0�W��cn������^�����������a�}�|��r/�J����@��>=A&��_A"��kN�?2o�4�>#�`���*�����0|{�������dcs�C���`0��f�h�f����s���7t�6�����;?=�zt�:b��iW��(l����V�����T��'�K-�v���6�PP����j���jO��`�`��	�J.
������n���3t��q�/��wz��S�C.\��b||��]F4:�,4���amO*$�I�������.'6����v�a������L�|��#-!|V�52tXa?���S.���#T�
g����X]��v���_����xW������	����i
�G���P`��
'��-l�6���v�b��qB)��{�����w�6*l�|�[m:|�+�aRB�����8Ahq8zB[�7��r�)��{�����i�)��=.�"�����������\��+�K����*���&�b/hH9������sM��w[]3m~��q�#���l����v�"�����\���0�P`���
��k��=���eH(��MhJkh|>����
�l�kZx�8����fG���:-n�u�����g���r�R1�EUDxu�",{�]7����_]�
u_4|w����|3J��������x�S�z���g+�U���c���r�����'(��h���El9��t�Vl�!�lB6��if	N��GZz��N;a���U�~����^2��o���&sI�.�B�u�����l�f��K������n�������n�~�9s���Kx_\��WA�%1������c7��X�l���U����?���	�=��AZ����W{:n+6��P6!�����T��\�~<w*����i�9����]YE���n�>��3������;�\T6_PI,��I�<�Uub������9���.x�#���7��g�&��1��4RSe|xG�~Y��n+��c����n��f�+~IJ��	��O[.�Z����=���eH(��M�'U�iZ	�O�.�Y�=4��b�r�0h����'�Vxr�G?H�q�~��3iN6k��N1���<��j�x��e���s�����b�%0��)'���gsp)���G�g|]��
��>�Y4�p��/�o�i��	���@Z���S{:n+6��P6!�JXxkA%�����r'��=Ms�G�k�u��F��uc��3n�e���{�fFl._RM����Z#M-&>I�I���bm���G���qR���`��.���,����Cku&����*��r�p8j@�����@j2�<oh�p���������~jO��`�`
�&d��*j�F>�d�#����y�%��#���\��8t�~�	��k�������
7�{0����"�s�q���3��$.���M*l�.3]�D������s�p��S�����g���g
�
���\����u)�a���p;X�X���	�h!3����{FsG���o�f�6����*���g�~�Q��x�����������}��7�������a�a��>��k��S�^��C{��'(5t�����=���eH(��M��W��	��W"w.����y��q�!C�-.+$��T7��x_��>��*�|u]�.:���.���v��g'����U���?��LS{�����	��
&-A�q�jO��`�`
�&d��F�UFB2����U��f-�~�8l��*b�
u��^2�2{Fs1�|Em;/�GMFsh`��M��8n8�K�i������=qhcp�����kXv2�@k��
�2$�M�&���&��������NZz��GZ"����.:���_�Y4S��C����T��Z�������m������]Zm�J4jO��`�`
�&d�M��Q��Z�{��!�v��_f|x��T�=q`
��u�HZa�:�:��a�`
�&d�M�f�K����j������a��j����,��VB��8�	�,����;������a�`
�&d�M�f��8Kld��=U�;,j�}�]��x�&�(W{��$�jM�JR�����pGX�X���	�`���HE���M����~�9n8�8���Kl�����8�	���k��#��gjO�a�`
�&d�M��:�$��?P5u����>k��3�����=ohmH((T�^,-��?W{:�+6��P6!�lB6UGj�����/���a��r���������bV{���PP(;&KZ(�R{:�+6��P6!�lB6���$�O��1���;{}X�x���E��@�YCBBA���$i}�����pGX�X���	�`��&Z�3���mZY1������kwm2�Q�Q����!��P��(iM�1^���#��,CB��l�	�d���?w�z�����9h8�����i�Kg���g
����B����� r�T�����b�	`�	�&d�
�z�)�G�um��>�G��m[g
������CBA��s���O���t�Vl�!�lB6��l�Q|^������S5=:9�v�z�d��\f����!��P�QO)�����=w��eH(��M6!�m5����;7V�����bh/��U&��V���A$
�sQJz��5jO�a�`
�&d�M�f{���y�,�������a�w�g|�?}�KIT{�`

n9%<x������b�	`�	�&d�]�f�92�v����C7��[������R{��

�9��[�r���pGX�X���	�`�������[W�K�iz��r��c���u�X����=q!��P���
�-�xD���#��,CB��l�	�t#g���;��j�p�
��~�i�,1��$������PP(`���=�w�U{:�+6��P6!�lB6�������Z������a��uG�Z�������

�X!e6��U�����b�	`�	�&d��bI��;����1��|�]>�x�)+Q{��	��&/��s����pGX�X���	�`�	R]e|p[�ni���+��_
�=��F-f�'��!��P���R<�.��=w��eH(��M6!� �RKr���������������j�2����=�v	��GM�R�r'D���#��,CB��l�	���Ng������bHO�
�����l�&��o'�PP(���R3�b���;��
�2$�M�&��MP��H��;^={Ry��4��T��4���|~���n��PP(n�Rs#R���;��
�2$�M�&��Mh���|t[�V����pD_��u�@?j��=��	���
�BW����t�Vl�!�lB6��lB3���z��5��jztrP9��~�����'���g�f ��P��
�
��/S{:�+6��P6!�lB6�U��`
����rd�
��z�6�6�=�u�jO�iH((���)_�*���pGX�X���	�`�	-�/�7\��Y8C��C����T���?s�KMR{�,BBA���
w%N���#��,CB��l�	��E�fsDh��m�c;n8�M�a���.��V{��@BA	��"�����jO�Ma�`
�&d�M�&�����y�f�\M��T�t���U�����8+%jO\MH((�+�6l���S�����b�	`�	�&dT�Y,1�u�wW}=�a����g�5K��<I�F�y�	%�s�����S���)��,CB��l�	�uM���
��E���:�VM����^K\��s���!��Dab���~������
�2$�M�&��M`!����c����v�p��c��o����������PP";,EJG���jO�Ma�`
�&d�M�&0�TW���[Z1����a�WC��4G�Q�Y���
J��DK������pSX�X���	�`�	L�����?y�z���.�8h8������7/���j��e�PP"�V������=7��eH(��M6!��VP���}O�qE���G����LM&�'�,H(({�Gz��~=[���)��,CB��l�	�����H��=V={by�w4��T�`���Y>?W�Y7
JD��-����,V{:n
+6��P6!�lB6�M�z���[�uM��7~�W�}�)���jO\)$��8xEz��Z��t�Vl�!�lB6��lB���f�=N���F�����a����N��?�eg�=k�PP"t�i���`���pSX�X���	�`�	�5�!�;6T������bX/���&����V���@BA�������v�=7��eH(��M6!��������j�����A�����3'�������u$�^���J���������
�2$�M�&��Mp�l6G����Z9v����A�t����m���FBA��E�v9�zZ���)��,CB��l�	�7��n^�Y:W��c��.��}Uw��%)�JI�O	%�g������.�=7��eH(��M6!���8�%:������_8l8����]����-RY�jDBA���K�7j��[jO�Ma�`
�&d�M�&�c���x��v�BM�OV�&��;��m���
J�}=GzsF_�R{:n
+6��P6!�lB6�yK|L��}USF9n8���v�������%����c����q7�������
�2$�M�&��M;HU���m���*tqX9�7���.st8������si�-�H
���$i�9�6����YH(8=|��>L~��t�>S�	`�	�&d@J-�	������+�������?�Y2�p�2_\(~����bh�}Z|�d�!i3��|Tg>����O8��cg�BB����#��_Fp���pS�L�2$�M�&��MgQ���}O�qE��bm��[��^���k��^�������o{�p�g�s/��?o��p�����C��J����������
�eH(��M6!����.�V��o\ER���_�Q����������@����]$J��K��f��-4�!|�`
�&d�M�&���RC�x���s$'��N�s`tw>�8�7Z�(��������q�H�d�Yt�j<iM(5�FF�#��Pn�O6�.��=7��T,CB��l�	��`�����M�O�7N���������>/�t=�|�y��1}E������k��������\1�o�~��M�_8��d�N	%���/U��LjO�Ma�`
�&d�M�&�\5���7�!y�I�b�90�+�w���o�y��9�>~I�F�F����TNjR����;�W~�����_|������E�u�+CB�1���E%]�%T���+��,CB��l�	����R�90�j<I�q��2��,^�+�9��;�8�o����Gw#I�H���������+W��5�y�+�kL����A������&����R�Pp�TS���I��������
�2$�M�&��M`���������S$o�XX����+��o-�����?��N#��h�IqOm������JM&sDH����c9l8,��	��E��&�W������
�eH(��M6!��(/6������h}s�$>n �A}s��[��|�?�����KI�nZz^,N���N�__Rd�y���9��?������}�iy�&�o������
�eH(��M6!��
�K�o<Ir���o�������=��/����9�3�0��� �k���Q]��T���F�b���;��j��'��k�!�`_at����8L���/|�`
�&d�M�&(B-bs`u-�F
�������|�������|s������cz���Y�I�^Z�Q��c����M!�e�;7�+j�|�p�"
�e�J����c�����g*�!�lB6��l���e�6�V��7n"����1b�^��9�_�|s�+|����$i�H�:�9����ZMEj�j�����H(��v?T��9Y���/|�`
�&d�M��� ����Zv������}��w����.
#��|XG>�w}s�JR���]�U��YY�A����Pp(���T-7[���/��,CB��l�	�l?�%�6�Vz���9H�>q����G���-^�������8J�������)	S�W��!��P���R�0p�B�����b�	`�	�&d�� �9��-�L
���yI����|XG.����(n#�.��$�[��+b���hR���n!��P��kR�0`�
�����b�	`�	�&d�!�"���������Y|�����������������\�8���#�����*Z�h5����q_H(8���T-|4w���p_X�X���	�`��z�:j���-�H
������������_�|s�3�������I������������1�J-j�v@
�o>*U���T{:�+6��P6!�lB6]�T@u�������������7����I������E�qI_��oI����@?Z�l�h���@!��P���
��U������
�2$�M�&��M'�:j��o�@�w���bs`t>�-.�?Z������7��L�o<B�o�����@^���$
]������N�=���eH(��M6!�?`���HZq��9pI�����>����������C��Gu&I�H�B�����oL�Z*����:�Pp(t���=�w^T{:�+6��P6!�lr�lr5T�!��J����$sI}s`7>�8�7Z�9�y�90�#>n0I�"V#��Q�'�����V��oX�^	�&	���T->tS���/��,CB��l���e�s�6�jn��b9.�>~�I}s��-^���;�Ul�\L����3bqR�n�����@���
-!b�<�Zv����p_X�X���	�`S�&WE�i���gH�v��Hl�����������>/�7~��%�S�jd�	��M�V�9���XBA
�_M���QW������
�2$�M�&���&%���aT�I���7N���W����~�����C����^����IK���IC������w�VB�I1_�����w�nPM���hM��.~���lo�?x8���EG�Z|����?���p�S��a%�~�N�g*6!�lj�lZ*h]������J2�7v�C��=�U�7�$6F}��AR����w�.�j�o�_�b8z�C�C����I~IjO�}	�u\�Z~����#>h�[�������G�����CAeuI����Zx�qe���qeU��.�qe�T������3��M6�8��?�����0�cX�D>n�����9���8�|�[|t�����$7-�P��m�u.{��GOp(i�`�Z����t�%TK
�����>��~]��_**�F~����OQq5s���j�FEm����+����V]}�o|�`�	�&��i.�x*6�$��I�|>������p�^m��O�?��~/���$u�^S�x��b��Zh�p��������y�EjO�
p5��.�Z�Gw�|_Q������#�7�+�!N��:
C���������R�%��\��S�.���k1-V{	`�w��U����:��Q,5��0�?�U>|��G
�7~���������i�#~����Pb>�?@/'{i�Eqn����S��	��p��r{v���%��~�EP}>�L7VS��F,S$�?��o�*���e��Ptim�\%�d|t7�mi��)�p�|^R�^�����|�">Tz�S���s6�/)��>C�������B���h��y25�������wU��^�Z�e<s��������(�Q-��\���
�����#I�,����V�im������p����u���U�F���^�zZ�Or6
���_=a�~���D��
�A��Z�\yJu�����zX��GQq5y���j�%wS�C�����k�?�c`4��L��_r��b����2y,�'��k2�@M�La����JM���_'��@���)�/�O�.���"����������#��|�;|L����������m���8z���u���TX�����=!����OK/����'��y��|�_�����)���#��~
��qU���U�WV5�Ws68���hox������j�'��V�~��y
F;o������yg�
�yW�|#��5Nl7/���o����|���%2G
C��#����!w���?k���?L���8��U�W��~?���$�wOM��|��^�Mk�����hop���^�p����B9��$�����\�oz��I�JK�PC��BX�T {�W��������| w��I��i�d�2i?������ZL�]�:6��K2�����==��m2��c�w���~Qn�@�-�(��!f��i�1^+�����YI��:u�>���Y>���J+������/��������������/��_:���vb��GO`����aC�����@[`����$s1�)����T?o����V>��:�'��
�2�J��5�r������{����w�|z�I�����>����]�����[��U��F�D��Z8Y������.��6�)1A�&#������/�)����!�����:��Cl���������p��M����Mw���}5�R�0�w_���(Z�H
���������g^��Vx���+�)X�X����U|?������4��O�`��s�?�����|�����![sK�*_U.�kc�'��K&�gk������,CB�����Z����`_K+�H�>�7��s�S}^�#?!i�
�������eH��2�m�.S(�!�c��[�-���Tv������rb���C���?���b�����^���J��VvY��M���b�
�7X���}!qR�0r����&���%gI�t>�-��Y����������Ta���L+6��P`����"��-�N+��"m���_8qs<���v6���ou��|�-a��5��[��v���*���R2@����_6��q�eH(���!UCGLT{:���hM����
��_W����|��$m-���\8��,CB\�\*��G�����������&����z�\��[�Q��[�9�*�.��N.��s!@���&��P�/���T-3S���<����I��G|�����B��K>��x��*?+�o��a�`
�&d�M�&��P�/���T-���[���(��XR��O��A�D|���-�������)Vl�!�lB6��l�	���_�����.W{:.�����$k9���}Ei����|TW���jn[����5Vl�!�lB6��l�	�b�����~���=����4R|��L�C�������7/�Ku1VJ�}	X�X���	�`�	�2$���vB��.���t���i�?��������B�������eW��b�_�`�`
�&d�M�&��P�/b���j���jO�S-�D�f���p��+�����
"y[iu���~
6a�`
�&d�M�&��P�/b�v�Z������x
��6�����s��Q|��3|�?H�TZr���~
Ja�`
�&d�M�&��P�/��u
�-�vA����TR�M�������}Yi���g|L/���V>��:�_CS`�`
�&d�M�&��P�/b�2�Z�������EkI��4��/'�(	��4����j���
�2$�M�&��M�!�`_��o�ja���jO�	_K+�I�>�7��s�{���G~B2��V�F���bX�X���	�`�	�2$�U


:����>>>�������}�Y��><88��'T�0Y���F������!5�I��Zr��N������UZ!x��F�wRm��Z�~-+6��P6!�lB6X�������T�;�������=z�	����}Z��	R�0�3�	�`1�����������<��c>�m�6��zX�yj�����eH(��M6!�,CB]e���:t��q���h��������������d��,���
_y��W�:������������^	�~;�s)-�F���p>/*����|l���V�Yy���AX�X���	�`�	�2$�U�}��:DDD�y���'�������/�<��[o	_���t�a���%"U�B2��v�z��bI�>>q4�'�(	�I�H�����_�b�	`�	�&d�eH�K�L���{��W^!��y��I�:t�p���F_������S�:�����2������q��~;�/��V�%Y������+J+��?������Ts��U�����eH(��M6!�,CB]"88�C��{���c�������{�������cbb�|��o�-<,66���GEE	_�W�&�9�++�WW�Z��U����[��4R|��L�C�������	#I����R^��4��,CB��l�	�`�[�n����?��?7�[��g���������_��h\s+++�����:�0Y��^YE�>���%enz�8��h�?����
����B���>I�K��ZM�j���+6��P6!�lB6X�������;t����/�={V��X,����������?���SSS?���^��V#��qi����j��>)��+����RaY��~�Q����#�d�l,	�R��W���V�>��x�9/hvJ����`�_�����<���r�J���]�V������������RJ=�"|]�_�z���|���1�BC�������B[�Z��O��v&7h������u��?S�������!������"�	
+H�����:��������/�4��������_v�a����O�:�T-����S5HW"��H�+_��?��TR�M�������}Yi���g|L/���V>��:�_C;��eH(��M6!�,CB[�^����_��W�?+++=L��_��7�z���|��L%�R�0�WO���9������E�Q]t� ���&��#$i<�'�(	��4����j���+6��P6!�lB6X�������';��{�=��qqq�#|�c��N=LVs��i��<�Z����S��Rx��-0H�6��%�1��Vz���|L�����(y����d,��7������`�`
�&d�M�&��P���/~��C����F_��������?���	��:u����?.|}��)N=LVs��i��t�Z;`�S����Al������j��%gI�t>�-��Y���7��a$'��[�E����b�	`�	�&d�eH�K8�C�k��m���s�
_��m��^�tI�g���=��O>y����a����O+�����CF;�������*���[-�C��i�I���Fiy���|��$m-�`5����{X�X���	�`�	�2$�%:t����/�9s���������m��=��3���o�z���������+�#G����b�X��;l�0�+?��Ou:�S����}Z�_�T-�bB�~9�ao�)[��V�x�P��i�]�<���7e{�����Gr6�*?l7�&��,CB��l�	�`�*������W_}5))���m�������G?:v�X����f��{���$U�GMu�������g{�V��Q]_����6�%~z���i�e>q4����=JB�F�'����.E�y�cX�X���	�`�	�2$��<x��g�W^y��g���o;s������v���n����g?{��g^{��~��y{{7�a��B�?�����R�0p��&<�C|T���U�P�K��������v� {[b�WM�O�q�����
��O��9�\J5��oQ{����,CB��l�	�`
v$��#U�'.r��Sm���,��|����$�?6�m�\B
��=�W�G��I���&.�n��b�	`�	�&d�eH(�w��T-|4m������P	���������=�9�����.�I�c�%y;��O�k��$�Z�m���3��
�2$�M�&��M�!�`G���R��o��>9��=Y��U��8���p��gI�|+��v>m�K%�k����F�{�WD���/�Vl�!�lB6��l�	;"��h�.���'����[a�<�s�������t�N�YTE���!q�e�_I�r��Q{��R�b�	`�	�&d�eH(��n�T-�]���Om*�|^lh,,�����'Y+9��m�A��������:������H�.�Y�>�Sw��eH(��M6!�,CB���;z���.G��?q����W�]�:�{�t��kW{�R��")�9�7�	����>#����<�g�+6��P6!�lB6X���a�66����������|_�
_���3�[�'o\:�-��w��TA��:����{EB��������\���AX�X���	�`�	�2$���Z������%9�����JLN?C�	���?��{�d-k{;��:Zr��������"���|�Zr����=cPVl�!�lB6��l�	;��'U�{��I������0ws����3��w_���s]3�e����|L�'o�(3�~�'��eW��^��b�	`�	�&d�eH(�1i�T-=��%�I
�=Q
����6����d,���mTa�%�\2U�3���|T����4������������1�+6��P6!�lB6X������K�����\�����~��X���OY���G�&���V^��'w	j�$9��N��6�K�f��GVJ��20
+6��P6!�lB6X�����&J���[��BZr��
;��j.m�s�,|�����?Pm�k��Ihm<�Z����~������j]���v+6��P6!�lB6X���q��H����f?�C����0e���Rp��y��[�<Or��r��	&���tP${�d��u��97h��b�	`�	�&d�eH(��8��Z����g�w�����\2�����'�����:[M.�Y?��<��%����7�	��#?&y[�!�e��Vl�!�lB6��l�	;R����Y���k�������0�%3�AL$m����t�^wn��E5�I�x����+z����F
ZM������,CB��l�	�`
v���%U�J��T�&��;��q�$�\����FU;�2���]��|-��Fr�?�W$��>�?)>i�T���`�`
�&d�M�&��P�#�gg�ZXVX���zr>���fh�����������4�P�U������{EB���	#i����s����
�4$�M�&��M�!�`Ga��jaM����C��9�g�z��u��d����y��-/_�'��a*&���n���������$���[Vbj�Wn
+6��P6!�lB6X���M��u��}ca��F����S��q
�}���p�JP]���M�1��f{�VSC���G~����F��$u���R��^�-��,CB��l�	�`
�P�Ij,,���6�Xh��+��_s�,��$eR�B��kTs��i]2�^���������������Z��a�`
�&d�M�&��P��T�����=>k�����
E����R��I:��]���x���Y����������"a��I�JZ��K7��eH(��M6!�,CB�mA�T-L�����X*9��4�����r�M`*��:?�y�K��������������a�`
�&d�M�&��P�E��'U��
h����UO����Vbv�$�������%��~���L��XMj��{X�X���	�`�	�2$l)�I���q�5�)�:������z�MG��|�d��>/�1�I�1��\�94��eH(��M6!�,CB����x�Z5tt����j��������|��������O��e>~-9+|Q�i���eH(��M6!�,CB��t��Z1b���O-\������]��]�������D��
�2$�M�&��M�!�`K��@�Z:z���N�O54���{�+6��P6!�lB6X���-����ja���N~7�C���X�:�E��f�b�	`�	�&d�eH(�{��T-��������Ol.�cj�m�I���,CB��l�	�`
�D�*Uf�t�{����j!���R�iX�X���	�`�	��4������GBEzdY���f�]$d��>�P-��A�7�����B�ghmB�M���3��P6!�lB6�
1�&�R[��H��Z��������u(���q ����=�c��2����7}<�<=��8�/j��wo
�B7o�.�����>
��1}Zn����X���	�`��V�
������4�j���`�j������-�GeKm�6���F��/[j�rm�KJm�`���	Y�k�7TW�W�]�6��zF�����$�[�g*�!�lB6��l*g��-G[([jQ����4�a�>f�Y�����e;v9�pL�w���#?j��|�`
�&d�M��M�����R��6G��
������������K7y���d/�(U���U�-���y����P����p+8�`
�&d�)��BFVM�lm�����H��&��i�����x�]��c��mE�n4�a02:].��t{��[t��*�w���}�ga��ODY�l�
jKds��%K��`K���R�0t�%�BR�74���j�-=I���eH(��Mp!=g�UIFty��J�_a��R�g�������5a,
�i��&�!wf�7�������^0�m8���0h���~G�I���O�-�/��P�H&We�����U{�a��`K��%R�0��-���i9���O���Vl�!�lB6[S�^c���V�c��Q�`��f{Sa��?g�--l��GklU��z��V%M�]�zi�����m�/�
������hc8�b�V�(y��t_�#��*�� +l�<�Zu�����*�T���J-�0I����!�lb'�Zs��J�p�m�O/{�
�Z�C;mi�#���-
�f�-m��i�*i����jmo��1A����0�P��hl�6��^�TR����U����%��s���G�A�������3_9��Zw}�hlz���7���g�����|�F��������ja�5�[��-R��$�o��v�w�iH(�����s��S#�v'����(�N��S�r�};�1�!����{�N[�7�+mU�lmO�x�}a�����[W�
c���v��KCv�
����v�������6��zc��LQ�K����wMQ�KwW)*s]�VQ�K�z**sm�@i�k�OT)sa�d���O� +���R�0�^����	#���Za����9�P=gpUI'[[���NHI��J:����-��l���1�w��S]���������\�z}C����;Y�����cN�;K��5�V��0��>���G[�����<��fY�V,��Q�+�c�0��v�,s�^���ux������WT�Z�+�k5���8�Y1_����i��>�����j���q�bO�O$_K��i�t���.��U���#�&�U���� �Uu���X�WUo�q ��8�Xl���&�/��sU%�����I�V�����Z�'�,�s��s����h�e;���h[���4;�t�Z�#��T��V/_dK���Zv�|���,����N�����z�C�����������N���'��4L�f��9x4W�y=�}���y+18���4�=���~}���]ws����
r��:$"T�O���@������{��6�V3/`�kk5vv�k�xr�������hs��+�m������!������k����������*i��;����������p6���m\�yU��x�f3����u��}�O���n���_�_:��hCC���2���*m"=1BQW��IJ�[�h��+�^r��tS^�-!���$� U�r�?�VzK��|�?��Af�2��t[�F?X�/�\ty6W�vLgo{�P�.|>�������;bN
g���=��x���T?������`|t�:�U���	���e��C^q�U�-<�r�N[ZXi��JZ���	j�j�x��R��4��il�I��`��������������k�,_
X�s����UT�Z�{�e���^}{��2��&�e�����\Y�J�\F���4��`Kz��R��<����I����&���{J����.����J�����f�,��Si�����B�o��~G87�uD8����j��R�\������Zb``�����HW�t��s��1�o��J:������w^�^������\u+#oR����5�|��6�y��'�	����!Gm��_�l�>l��_`�3�WN0�d�y���p�'�o�c���+v������t�]���wUiCWy��2����/@��j!����3�ZX]Zm��|�Olqr@�OI����1D:{Ny>�<��I����6F(�4p�t
����\8C���1B8�<�rC8�]�y�.�\{�������WF�^���?��8��J�;���r����ico�YVo'^t�m�_���Z���[S:���38A_��1C����'��F�=���O��J��R~i��ql��V�����+�.��^�3�`e�7��������ww������C��]>���l��L��%/<�q�eH(�R���Zh�up�����-No����X���)�������<��������`�����.����x��4���`!\q]YF�.^���9�G�.H8�"l�����|�
�7�����/}�z���!Ra�q5io�Y��m�
�][�����VC({�v<��>S����Q������u��e���XS����5%;]XJ��?*�+x������00�g�|�f�ur����m.D!G�W�O��27��"���2$dQJ��t|\*�j�$�R��-N�
����R
���CKb=�������"tw�_;��H{�T�p{�9Cq]YrefdY������}(�cW��a{�l���l��}<��=�k�]�R������Y}�ce�a�'���)��	����%<"+6�/S��3���U�����Z��n��s�m���/-zU�m�~&�4����5MX�d��k���1����4E~I�W�}��V�Z��P�e�3I��E�>��`Z����I��*�)UY�^*UKV�������������x�����Q���(�U�I[\W�I	/������q�P����c+��L�f�����Sz���z������y-���\�1��4Oa�A���e�����'>c���z���X�'n1�m��=�`��vn��v/['��?������?��������m:7w�_���_������w�>lv�Pi�L���'[�!� K[^#Usz|f��$g�[�LT������+Uz��Xk�+���3Gm�:2��4-[#�l��y��7�eZ�����$�,Q�����{6��P����+��L�Y���E}<�|vu��@a��1���o�Y�x�F������T/e�{|��XMJq]Yu���+v��l�v��,�	'q�
k^�l���d����������q$F;�z����6���}=�~����M�oa��&^���������<���0�]��-Q�P�����eH(�*�)��������`>~XC������?���d�%�8�i�,�+���`^�&E{����!��Fi5�����lmAdY�oA�g�������a{�o���l���}<�|xy������}E�lf�;��0���>ws���'We	�E�)������b��u�%���:e��n�L�{���K�)6OZ�t�y.l��z���_��h��u?|�c���~+��}�^V����5�{��~�D��a>=���xg��"5dPL��'�A6X������\�Z��o���A�b���O�^����aR�fy���O�~o�����G?X��6t��9����,�*+�,�~^�g���D�=qgW����i����wg�������&��\5:].�d�����ofx ����+���B��g��	�����)m8!-Iz|J�v�`���
g�wW}�}s������mVV�N����M��#���������TQ@J0����1�����h$1�k�hL����;F������k,$*]D�"�(X@B�}���u��q���(�sX���g��g��sf�����;s*�.j^iY��oWz��>�������*�@��^�����
=�����;&���I(�>7-�N>����nX�]�d�6Q�g��\Vr��'���=s����6��7~m�K_���W��{�����s������
N]Ov�GcS���|.5�T�j������\4-s�r�����'������n��>����|��/�����q���rY<���r�������;���5��x��V������������� [7xkP��s�:��2�]�����=.���5�:p��i����Uia�������^ya����f��_�����
�$�&���I(���4)�N8��*z�-���I��<r����V~F�~u��:���3��6J ������3+����9��_�z�1��y���/�X����������^�'O���/������`~?��?��6�-�{�C}b��g�xu��7L��j����>���fY�1�?��Z��5F�=[�����o��q��i����u��An��v����������}�+-�U�^d|{����
K/����OAn.���0�&�I6!dJ��^x-������KJg�������U}���[��b��t�UY[���(��c�+c[����3�_x��W�?���z���C����)S�;w��O-pS�>}����~RQ�O�l���K���t��q���5 j�v�V�����Jk��Tya���^#2��3����*+�-���f�X�SA�d�$�2	%���^N������*z��y|�'�U��������'u����m
������?��k�������/;<�O�~�s��8����\��W>7��1���8��C�<o��KG�������|�������� ]�_��tn�����%���_���V�����v��>^��/������~�������kK>,H0as�=�I6!L�	!�PR�tHR-{�EU�,�gv��U-m���O������G��2k�T��g>V���y���������R?#�����~����i���'��I����~������z���q���[�����M_u�7����������W����y7����W�^���+w.�j������-w���z������S��m��������J��5U��fl��B�d�$�2	%����%����}E��6,LJ����F��+����9�;)�\]2��w��Yp��m��������f��X�����F�����u�O\�W��M
_X+���������������gekz/�5�C������V/.��a���I(�I6!L�	!�PR��g@R-s��*�V����'�}��n�ee�zER*�0���k�����lk���F�=xJ������{�k��rk�_f�zIMo�M����g���-x�k@�.��M��
!�P�lB�dB&����e����XY����,qrfe���\�Gb��9�fF��Y1/�<0z��Q�c�������U�|R��v���,��4[�Kjzo<����y3{�^iq���36�LB!L�	a�M�������f��WV�rq���r�8����������]�R�/WZ{��-�Mx2z����_D�}y�K|�o_^���O�5�~��,A{w�����f����hUfl��B�d�$�2	%�+����^{Oe��G�����;�Ee��_��
p��5Kjr�uKiI4gRy���y�_)����-^�w���h��������z����2	�0�&�I6!dJ��W��]����������'e*v�����A8cD�{��~u��|��=�-������7�6xn����{���_]�����1�n1cC�$�$�&���I(�Fw�9������>e���Y���;�]5��O�*)��R��fh���%w����%�~����W��itK���?D���f�mX[��C�2cC�$�$�&���I(�F��3��vw��>��9g���*v8k���R���O��zQ
�zs�lv��3�������m�?Y��ut���F���N���
�z�Ufl��B�d�$�2	%����L����<���d���j���O+?����� ��5?� ����D�����?�.m����+w._hx�������a�f���I(�I6!L�	!�PR���%I���G^H�S��n9K�L�}h��E��?9)�5�O�2����>z#��|����.j�����_���
�%��|����|�B&�&��0�&�LBI5���%��IO�L��~^�'���89���I���O�j���������D/�5z�w�����k�q����W�o|��8���rfl��B�d�$�2	%����L�����b��E��Y��}�Cg���r�w�/M�\�ZT~���[�������t������;������(����
!�P�lB�dB&�����j��C�W�P��u�/-|�I��5KpJR*�6���h3_�c����tu��^��F�/mS���O]\��������y3cC�$�$�&���I(�&��5��;���J&v�Y��o�~��7&��<�������Aoee�k
�{�|���~\����{�V����*_�x��B��36�LB!L�	a�M���j�1�'�����������.q�rR�����r?�����jw�����������FO�!��]ta���
�S?�~���.����w�D����P���!d
a�M�lB�$�T��)���:+�����Y��yTV��+Y�a��I��wC�(-�3�K>,�\p���[������/�:�����n���E3_���.��ab���I(�I6!L�	!�PR���#�j���+�-|.�����3�/�y=)���W���QW�x]���h��Q�c�+w�����-���?/z��h������/�-�B&�&��0�&�LBI5��%������=Z���9K��1�x���L����ZrKfE�}|�w���lDy��/G��"z��h������~�e���I(�I6!L�	!�PR�9��I�p��uy��L<:[-�{���vK����}������3�S~a��6n��k�(����?G�F+�`�P=fl��B�d�$�2	%�����c�?nW\�����/�������e����K!�/�PK]�Q��.�nk�^������t��|:Z��9k�B&�&��0�&�LBI�]�����?�nNv���f�8�;�R-���kpd%���c�wD�����e�. ��K4��h�����G5��
!�P�lB�dB&��J��3~������Y���Z���^�T�7x�f��hb��o�^���q���/�&=����
fl��B�d�$�2	%UR-�~�y�����%N��[��[����3�����`��/����Z~a���w��{��=��_w!u�B&�&��0�&�LBI�T�v���P����_Z8�����3_J.,���E��)�,�&
�\�~�F\@x�6�?�����������g���I(�I6!L�	!�PR%������{�x��9K�L�[.s{R-���G7���J����.������e4�/����Z[N`���I(�I6!L�	!�PR%��7����X7;g��QYIIY�aNI��o.��q���+�-m�q����.*��p��M�2a�b���I(�I6!L�	!�PR%��q��]n{��g�K�����e����R��O��������lN��)�9��+�W�_����/ |���a���I(�I6!L�	!�PR%��Wufn{��=�K�L;/n�s��I����wU��%����G5OY����/ \6�&^l���2	�0�&�I6!dJ��Z8�7����L������q���>7��5����3���J����I��Y5�r�n0cC�$�$�&���I(��j���/�m/�S�Z�j�����Ra�'N\�auU��v�����	o�v��K5�z�N0cC�$�$�&���I(��j��g^�m]7��K��>6}PR-<s�5�n��h��y�����n��7*-��Wu�B&�&��0�&�LBI�T_:�g�X����'��[�0���Z��;����4�+����u�sE���V/��Wu�B&�&��0�&�LBI��^ts�X:���'o���x����eR-�pE��I��|P�G�����R���36�LB!L�	a�M���*�������dr�l���{G�~5)v��O��lv���)u�k��&���u�B&�&��0�&�LBI����'i,��7�K�,s�kw'������I��u��=�����	/l=m�amA^�
fl��B�d�$�2	%U�Zx}�O�J�k�I�pX����?{���Z���7�������=S.)��K�dV�^
�fl��B�d�$�2	%U�{o�W��l���%N^���%�'��C��jCiq�jQ�%�7�7����36�LB!L�	a�M���*�����LK��>�j����7���Zx��[�{<{�����n����5��M��
!�P�lB�dB&��J��/�s`��t���%N>������j���|a���R�C�Fk��%@�c���I(�I6!L�	!�PR%��1��i)y�GI�p����=~\�T�Y�vi4��l����mXS��C�d���I(�I6!L�	!�PR%��W�i)�&�>3�_ra��w�V/�.n����������
!�P�lB�dB&��J����R��vfR*,����7'��������*[*�|�h��B�&36�LB!L�	a�M���*�Nx~|�Y����Z�v��~����j��9o|���a�z�Pg��!d
a�M�lB�$�TI�p��7���z&�����%��#�9=tu����G�Wz�Pg��!d
a�M�lB�$�TI���1����7OH����|aR-�u�m�%-����7z�P���!d
a�M�lB�$�TI���7>�7K^�JR-���iI�p�����
/���F��!d
a�M�lB�$�TI�p���Q���a�3���))��1e���V��T�QCg���I(�I6!L�	!�PR%����XX��?�������Z��{��
/�.Z�����:��
!�P�lB�dB&��J����-/����Z�m���R�������j��
=d����2	�0�&�I6!dJ��Z�r�������
�
�������{��\X���
!�P�lB�dB&��J���KK�}?S-��]�W]�$����=^�"��!d
a�M�lB�$�T�R��/*+-�2S-���3��{n�z���m�u+
=^�"��!d
a�M�lB�$�T�,�����~7���N�~~�c���Q���*[-|���,l)��2	�0�&�I6!dJ�L���#~R6��T8��m3�}k������]^������
!�P�lB�dB&���T������{d���?��A���G:-� ����+�Hab���I(�I6!L�	!�PRe��S;u.��9S-�`��z�������[��j�B&�&��0�&�LBI��N9����{m�vH�C?������.�����&lY��2	�0�&�I6!dJ�O��]O(��xh�q�o�c�^���fK�����,+�0a�b���I(�I6!L�	!�PRe�����y�c�{v��;vT����~�z���1cC�$�$�&���I(�2��=����d���E�9����YN�mfl��B�d�$�2	%U�Z8��om�pp�v�s�����
o�f�["36�LB!L�	a�M���*S-\����C�{�n=v�����V��V�����
!�P�lB�dB&��*�������m����'�:,[*<�Q�b^�["36�LB!L�	a�M���jA�����V�K�x�����+[-�g�B��Pfl��B�d�$�2	%��m���O����^l����K�o��NP�����
!�P�lB�dB&��Z�����������_������
/�.*Y_�����
!�P�lB�dB&��Z�����nW<���~0����j���zh��2cC�$�$�&���I(�th���f+�n����(9�~�Z8k|��[.36�LB!L�	a�M���j��n4��;���ofK�7|����-�B&�&��0�&�LBI�p����
�{������V��^�q���
!�P�lB�dB&��*��`�����=8)���(Z1����-�B&�&��0�&�LBIU:���/~����J�����X�A����
!�P�lB�dB&��*X�g����&��!OP�A����
!�P�lB�dB&��*���{�KJ��/n��/��`Kg���I(�I6!L�	!�PR-�tT��j��G�zD��&�&��0�&�LBI�B�]��i���,'	�B&�&��0�&�LB�5|����>z��vj��q����N3fL-��1��{$���=�o�G�36�LB!L�	a�M����O�>���+����w��5�ob�m�j���.�/�d��2	�0�&�I6!d�����l�����k��S�N]�~}���c��[Z�jo����J�X?S*,;�^�x��xY�e���I(�I6!L�	!��=��EEEGqDncII���8������]X8�O{n����b���I(�I6!L�	!��u����������k���{����>������U<���j�B&�&��0�&�LB��m�����'���?>n���}?��Ra�9�}�a���I(�I6!L�	!�����NEEE�-�k�?~���/����5����?�{���?l����!d
a�M�lB�$4@��7/**��"��5k��������f��n�����036�LB!L�	a�M���~��EEEeeey����q{�h
���@�H����f�m�����]����>p�m���}s���0�_��v���EEE�/�k_�pa����;���@h��o_TT4i����	&�������}���~��EEE>�`^{��}��3�<���B��_����:��z�����M�/�U�V�j�����K�.o����
��'�xb���e�+V���@�n����
�����O��n����/����������u�F������:u6lX^��ja5�B0t��N�:m���
6l��u������~��G���N�7��t�Ic����STs��t;v�����6�l���;v�<yr^�����/�Y�f������ |(�X��dj_iii��������h�b����w�}{���z���n�	�o��g�yf�F�������w���K+vO�5����S��F�4M�X������*J�������,���O�z�����[���>�)��ou����{����o����w��x�����9��������/���P,_�|�wL��&���k�y���������iM��'��E�����y���7����H<�=��#�,T|h��2�92$��6lx�e�M�6m��5��O���{���s�=�n����-[�-]�v�������?�9����U�V�fOQ�}����SN�[F���9rd�y�	'$O7n���e���[�b�&�uA��q�����v���������}���^�t��%K�|��]v�%n����2}�
�������N�:}������3f����/�����xB����W�O����M��T��u�Q��v��7���t�Mq�������<oq��}JJJ<���}���U<E5��f��v�-�\�lYf3�������>�����[����j� |�G��W�^����-���7g��
4n�x����c���O��v�)�)�P�K��y���e���q�������'��y�������O����:�Z�i��J`>�6m�����s������7i�$���[�x������v�=���g�}vOQ�}���Q�F�fiiif3���>�62����������{������d��W����<�H�7Z�	����n����N;��n�	��V[����u����~��'-�	��y���	��n��;6�Z�i��J`6��>������3�m���7'N���m���q{�h��������;�����K�.M�A���l����U6�C�z����?������h�&����;��s�GA���
"�Ol��$��;��-_��W���Z���[w��}���Q���hS�)��lZ�{����O<1���N;���-������_�r������v�	'��#G��l6,����K|���.���sg��Z��N����6m���c�7Z�	�o�}��O�Y�f�3�c���Z��f�m>����~:��xBA�{��Eoa�����>�(��cw�}w�G<�������M��T�	-_�<�0�6m:e��LK�2���T�Y�&no��qG��������o�-D��E�i���;����q�^x���jM�f�������o�=�R���lB�k��U|J����A�E���G���xB��u�]�n�m��=m����Z�Z-��iJ%����
?��6m��=:i�_�~<�U�������=~��Vs��?������u<�u�Q�O��y��q���G���c�z��q���b��'O��q���w���tPIII���-�������&M���W��8q���k�����O���C��tO(�8�?��O3�����������>�	�,�Z���T��l����{��;����o����]<�����kK<Vq�j��E�b����b_{����{/�_|�5k���5�Y�3gN|�7l�p��	Ic�7Z�	��q���Y}������q�q��G��O�}'N���6m�<���.�����7�o��-Z��O����tO�e���ZH��|q���?���5jT��]3_��x�����mX����;Wq�j��E�����������SN9%�?b���C#G��7O8��*v��a�O�K.�$���-�����/})>{?������3g�����M�����_�">{z��������(���jYj���$�_P<v��!���������o�>~h��Iy�&L����kW������~�y��5k��a�������nq�e��e]�|y��V���H�g�t�M�}p@�qK���V[e6�j_��_�O��R�Y-�P�R��5��Zx
���1c����N�������R;�~���D��������7n?��3�8x5���Oq�Yg��8���f���JKK3�%%%�f<�W1BP5���	����N���W_}5���������c���xB��|�0�=�}���q{�hfS<���Vk:M���a�=�\�&M�5k��SOU��_�~�D��C���C=4u^��~����4����M�������d.#_�bEfs����A�:��-���7h�������s^{��=s��O�}|p|����Ky�?�p���}���xB-K��h�j�)���N��o-Z�;vl�V�Z��U�x������o��a�����'���l�2������)2�������]��a�2������-���WZZ���|'>��:��>� �������m��f���J��\<��=��������;�{��3g�,..^�h�c�=�Y�����tO�e���MS-<��uX����������[+>Z�^�>}��0���������z�h�6mr?o2e���M�x�����~f!�-ZL�6���� _$_�	���3��c��P4h��W�^���j�W\Q1�����vO�M�Q�6u�`S�|�Kr;������o��u�F�v�q�N�:
6,������:�V�[������������	&��_Z����:�(k�Sg|�|�&lZ�_W^y������I����.>�G�]��xB�2dH���`6l�0��<xp�n�	���(E�4Ml*����,�	}��~�}��l��>c^��c_\�VS���5:`���~�0�c�j!l��O���[�=���q��-Z�8������+V�u�9s������.���v�a�.]����[y}R�o��16a�����w�9���{t��}����������i����o�}qqq�a���=�'w���|�����{��w�A�y����K_�Riii5���y����7o^�n���{��??�6j��m��6�O�&M
�{����j���c�5n�8���������G���w9�����O?���y���=~4�e��c�=�;S�N�=�M7�7v���s�� ||pQQ����:u��5k�,[���_�g�}��?����>�/�\���[�)S��\����^:��������E��s�&G��Vs���g7k�,�v�g��1#��a�v�m���g���<���G��t��1���G�?��C��x�K/�4n���*�������,ln�4iRTT�h����	&�����kf�����7�?���}�=�����+�HZ��o�������7O<���>c�������Uv���u���n��A�������7j��U�Vk��M=H�c���qK�������X�o	�����;S{���g����'se������>y����m��IK^���;�k�.�|����j����y�������Go�����$+$�����~������l���'�~uR��}s��o�]v9��S��������V�Z�~�_F��-��y��j���v�����-�z��Y-|��������O��7����e��I�$��W^ye���W��f�N���������@0`��8 �����{&�6h����_����C����c��
������������W3�5*�?n���~�v����z�7�|��_��v��m��&�?~|���:��?����o���'E9+�d5��>������cfQ�/~ma����/�x����Yg����?�YE��c�����6h�����z���;��CYYY���:i���EEE��7�lf�<|���>s���[5w����n�G�����6�Y��e���[�^�~}�6m�5k�r��*�WV-���k���]�0 ��������@����V����������[g6/���xs�����aCn�|0n?��c����[5w<���+V��!��_�����z��U��r�r��g��d�c>����^o^��c��~����i����������/���G�EEE{���s�=�d��5k��?�����t���3{��-Z�-:tx��W��];|���N;�A��5�<yrr��Z\5w�>}�V[mw��������z��a��ek�����e>�������8)?V�N�4)ni��Y�s���y�7��13��o�L��
~����X�vm�%N�>^y���I�A�m����=���G�X�����{��\���C����I�C=4����1��]��5�_o^��cf���3�x�!�T�	u��e�.����}�k[l�}����K�,Y��m��i���ow�e�F��h��'?������������cl��QGqD��-7n�����[�n]n�3f���?�v�m�4i����W���z����������?����O�t����*�rd���^�z���N������ZTT��s�B(�������[;��sQQ�o�Q���,zr��'z,@!���^M�6�����U�
=�������
endstream
endobj
11 0 obj
<</Filter /FlateDecode
/Length 141>> stream
x�����0�w?��HM��gG�\�tDy	'��!d�l�Y�1�M�&���� ����6�Qg?`9���A0=���#�k�|�����)�lcF�\��7�����n?"lj��,���vw����$B��A���S����W8�
endstream
endobj
13 0 obj
<</Type /XObject
/Subtype /Image
/Width 1722
/Height 948
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 91823>> stream
x���	����q4������L�����F1���$.uP$��M�K��fmh�n�YD@�E�Y�D@���Y{�����>�CY�n��}o�:E���Ow�ZN���T��S����F1l���:s�7�|Sm���o�>z��7�G���N�Kz����[�p����{����{�~��m����B�[qq���u�VQQ�uqpAi�w�_|��w_~��������P�"�w�^YY�Vdc.+++)))��>��c��o�}��:��c�z]\h���E��;v�V�������la�M�2E���v�:p��������{]�x�3g���V���,��������?t\����L��jjj":�����{x�����y��wB�;?11199Y��E�8p����!'B����6�\+�	G���_������������-;u���E��g�����!C�.Hdf���Z��W�+�l���;����woLKz!����������9s��y&%%E]�c��y]���'�u�i�P8p �M�4)�la������!���i�]d#����~���?���� j�?�e��?�o��-Ddee�v���+�.�g��;�.Bbbb������z����DG���i������"kN2!F�B%&��7���laD


���mw`�^�lK��SUU�ua����k��	~��9sF5|������laleff�F���;�.�g>��u�{�=��r�����lY�p�����	uc�����y����[�M#[XXXX�Ueee���_~�eZZ�5c#�k�����E�0|555��&&L�p��!������o���#��s������&M0�|�W�p��
��S�L�hC���eM����K��<y��7n��,���L��/))i����g�{�=��'�|������-,//w�aee�u��:::j�w���m��U_��#ZUU����:�a���u���-���O?�4�
������^=�{�V����^�����uo�����p��R!�$��9���'�����z&�(�����X�����NIBi�w��������CC��STT�;�F���,����e��i�-\�P����W�=����s��;w��Uaa���+��*�����'''����v?�4	���3{��#F���GZ�������iii�����V��b�
Y_�������S�*-������)�7l��1���V�4������_NM�)M������j��E��n��Mv�f�X�vm��f#M!=��HD�6lN��;���d���rFr����K!���	���u��Y#HII�� _���'N�(;��\8gq���%K������'{���o���F�Z�xqff���z �������6�����6V�
�~�9z�%����z���u�j����<r}��ee�|�����C�An�07���$�C�#��.����C���'������K<�V;t����S
$w���W����R��N�:5o�<U���2d��"
��I�T��v��1�lavv�N��>}��cI����.]:c��s��B!����f�8��.+��w��9s�L�U�cK�z���Y�d����aVD�d������	uo�����#�e�����{����b�Y�A�o��*L�t���r�V�!.���c������
fb���.k��?_�&^YY�xE.`���SW/\���n�(5���4=����6��B���2B��������[�C���/�2i8�M���u��H��EEES�Lq�d�����s,����:*�z�j��
�9rDm�����
�������Kc��:���o�`555��-��KLL\�f�K�

tb-i���f���%K��~�R![����Z�J�a��Yan���I����9���f�[�n�f2MKKS�$%%����zC�����y0������l��6r��
�� ��J���U�;�laqq��	��r��K�L��}��R	O�:U��l�.��fj��.M*:������fETo�P�}����'���y�����UH�j����W��T4h���3g���i}�$��������zM�G:�!���{���{��=b�[r/11Q�D?t��J�I�zX����[W���"� �j�������7z�h[JJ�w���=Ii��;V�PC��&��l����vN���}^s��������o9%�5-�lrPi:�������������C��]��I��z�����l��N8z��:9_�,r3���������XUUU��U�;��������i����S�����/E6S��\
����C�0���;w&|U�����<u��a��A�-����e'L�0���&��eK��
��G�a��an"w�>�5�o��,E���t��O�u�:	�%K��� ���L\Q��t�J�\��B[
��������C]���j9�ZM��JD�����M�6���vr��V[��RkJ�H�M�4I��l�Twj������.!���S���g�<�����N��$�m��rt����l��Y��
�5�5��P��8q��ZR�X�?j�([?���)���&�����_.���nr}�5s��H����("��>q�a@�tGi\���_���v���K����K����F����iTVV����?�m���Y�g�^����C����9�#?x�*ksc��)����O�i�e�=T���|���P�Y�:������*)���{����>�����3gl{��59���^�f���.�����o!��������t��e�� �����">��C�[�YYY��a��� ��7������O�<i}u�1s%
v���i�


���>}�:����h����������4��K��u�m��p�0&�Bw����a�������N����|�z��T*)��X������?iM�����y��^����gkzY�������U����6R�P��u��*�l�T�%%%����u,��K�k����>[�'m��+�0���J[�J���5&[Y:r���V��{��:k���+��/��^A.�-#*���l�1cF��,��x{��-O%�CV�v��N�j��8�����_���:uj�+�sD����Qp^K���1����1���[�n�����g����1�T��W�/^l�TZ1�5�#�4+�T�/��l���k��iii��dee���4�l��W�����q��m���2�5���+GQf��������R�499����<�2N�8����&��X%�N�U���'.�9�AnH]�!����j<��K��o�������=zD42X4�Z����a�"�P��Bz��!���u��w�����G��&{u�L��A���a����zCY��
X�7[\��=*�?H�;��n��fe�~�X�7�M������f����R���T�yyy.+�3���g'�T��������&M�}fE��-�M��T�:��B�k���"�r�-���r ����Q������<��!�/�`����T�+f�(T�k�k+�J�;�4���]��(��@��@u���\�������������v��a�|��-�6��� �v|=V�����9����~$��h������o������&�u/�skO[~F��G�>B�����y��)����od��
��0w�\���!��'2l��h�SS<���h��O>	���lk�����N�����"�[������G�UE���g%��������%d��n�iW|������[�~�":�HIyB�sk@�p�����n����9H�t��N�E�-�;J�-##C���Z����3�2���^m�4��o��]���-�Y��<xPwn����I�O��K���
�/,���)�u��������'�.]�q��(o�`����.�k��MS+���?�%�kKA��w\GZ�z�P�$��kB�����	����i���p�Z'�t���`Y�z��#k���i��]5�_\��B�97�������i���j=����nVz~��b�c��
����m'������Bk�W�.d1��f���j?�NRZZ�{9r������R=:�<���y��Ag���B�b�����Z��7)jDg)������4 [(����[�n��V���;��g�1~�����5��Z�l�>G�q$v�����=>������N��ve5��~�X
J�R���5{��i�p�i�����ol�����w}��Zr�P<���[
�������B5�\^����W�^����JiM����=[�f������]�w���N�^"�wx#��Y���]���n����n�m�6����r�W@�&���O�'�7���{�Z��~���*[����b����h��)((�7F���	+�;����������sdV�6&�>��'�:z��[p��X9}���9(�m@���2���;�z\�=z�.����Y�������053�.�����Y8]���q6���������zV)�+B])��(�;��uxC[�7�r����pKII�>E)� ����~K���	�P��Bjjj�u���B�az��I��Ki�?~|���7nT/kz8;i������n�%��^�|���G�����{�P�?+��zw��o<x�uy8	�0�N����#�l���������Ao}'.���~A2�n�W�u����g�}&m�5k�Xo=qC�k��%AO�����	g\{{�v�`:?�8�[�t�.�-�8j�
=V��q����NM=z��%�����:z�c��~�~�f�Qr3�����
��;w�%t.�:�o����N����[j���o�����'TC�{fEd����MJ�2��1������,h0k��6�t���=���!�%���f������6m�w}��@�tK��YNk��l����}aj,��lam���������(��
6��Cq��IB#b{���-��
�N�����2[���w�l��
D$33�v���<i������dm]+i���:#v�G��9s����� 5���t:�qJ�z��$d�9%���]�����6z�����2Y�dI������~��>��C�:v�kX�P���[j�mx�@ ��S����r���DGFF��u���b��	
�dh�����$��z�6�R8Q�W��r:��~�}����#b{�7�r�us|V6l��ErQ�2u���3g��7F��
���'[��G���q���u����c�������m��F�g�l�����+��5"��b����e��}j�P�B�H_�uD��o_�^����%[���t�m�����r�����G�����l�H��:z�h6���i��F��P��G�$��O�|��������iB����3.� +
��\����5]�;�%''[k�X��\[�a��.=<]xwUVV��
gZ�54h�uy���b���[	5/�b��9"���a���.W�a�����;�611q��9���bE���@�A�����.xq�n��I$��3f���?//O���f��0T�P�
��[7n�8�n��H�MLY[_�PO���[�q������'[����IJJR����"�I���9rd�����S�NY��1c����+++K�:��b;�%[�r"&g���*{����o6��:�oD���w+"�K����7C��B�Z:O.G�����X}�-�SP�+!1j�g��:]��g�������Zh�|9��BE���O9����K*v}�M�Vot���7/���-��o6==]����~�k���,�&�M��s����*�$*��~������m|HG�m>���������/iG��)�
3[�UTTH�e���zNe����W�����&MR�F��R���:'��w�7�=��[�N/~�8L�d��U�B���l����%���4���L]v�mC�_k8�d��+���'�%:CbM���[��errr�n;[(�K���}��6z�h��np������~����LOPn���<[�g����5k��D3����VDo"����e���s���1c��%��G���&�G��B+��6n�(������;w�ubG���l83������v_cg��������$�l������
�d����-�={����#/�*[���[�
�I�p���z�KN�EYY��=2r�H�5�hc	
�F$V�B����ZZZ��[���h�
Ew���aC�w�g(����Z�t�R�d��}�5SSSU
�^���0g����6v�����;�z)R���%[��������ub���j����m'�l���g�&�_�c�.�k��gZ ��2[���l��A��z��
���;�����d"yyyzC[���������e��8!�����������[���U[7,��C�������Y���/���
���u��mY2�l�4Tu	�).V�B��j4/sy�-��
������� ��eM��e������0O\�#*��z�|�����k��f�P�����*�n��]���E��r���Z�Wi}�V#[�H�)���h��-��^��7o��l����O�����93�M��.���������a��-���s�N�\��8$��R����
�:��2V�Bk�u�����#G�DyR@����B�0�.�[� 6,[Xk�^��t�Zg�g�tG1�VVV�z0"�d�M���&Lh@���b���V+))����y����X�20��-T�Id
4H���k��&}�f[��Z�3�q6o�,�� w�����Y�F+'+;���q'O�<,��NJJ��Y,�l�X�r��H'�J]^�gp�8���]�v�M�{���|w�X�B��{4�Yf���
�Zg`��<�BL����(�����a�����l�!z������D�Z�o���YV�j�l��K��4s��W��������ti�
��u?�u�������T�5�3-))).m.i`�;v����*�5�c�-�s\:��>O����w��~��i��,\�P��O?�4//O/�V�����kCm��eEuj����=[h~������s�Nc��p��Q4��������9��c���|}���S?/^����N���/��Q����la�������-11Q���F�y��:T���{��D1����^-�����$Y�z��]��������F�n��n��}��;wJQ�q��z�Y]]-_�����\�Z������&;�	y����e	��>s��~!:����Z��wA���J�Xj}e��p���l�PYI�����V�;w���i�����^+���4o��P����^��(�I�P���>��W�BkBC�u�n�uk���qII��<������Jp�"��B1b��i�=;�����5�[����h��h�u�����o�rWz�	�R�,Y��*����6n��V[�b��>�Z���ut8���l��i��J��������]�zv���������`����gk��
E��C�����~ZYY)�]}��wo�"v���,��v�j~=���0.��f}�Z�%(V�� ��1#�����%y�;�� ��-,++S/|���m
���t�f�bX_�R�o)���z�ci����[w�I5j�(��-��h�"��~�K���!��61u����l�����Z�v�1����uB��*[X[�iP*��5~

�/_����N��NB�[�����!<}�������#J��a'�z������[a��A��������G�?!(�rrr���ZD��h�u�����E�C�XBXw$v|�X��&�z�l���_�0����������A�>��A��u����d���S��.�p�
��wo����Tee���z�����I�����K��,�����o����oWs��rn��Yg��4�oa�W_��Kw����%�/5��e����9�-*���Be/���s��	$D7O4����U�VY��$�&�7%%E-���������K+L��W/�;v�:T��d��1�������]	�r����d}9��k�������
����o���������m��F�-�e����p�(��Wg����-�P�n�>|X��^���K�m 
ji���oB���S�N����?[XPP`�	��G�!��:e9)�	u�T��j�����y����
�h�u����C�Fs�4��K>|��j����OB��$[h%����b��e��	?[�Q�\�w��
�h��$�&L�0y�dy�X�G�����*[(%|����:�U�5��P�6�T�R�K����U��Q9������HL�#X�Fjj��������	���:n�b�� !�����![(���3g&� � ���/i�aFF��!CB�D�V���MRk�C���haa��)S\�/
�Y�f9�6}�PO��>���uW��?n�Y��j��
O���d�����,���gk�z��������`W�Eu�m=GC��
�m��<��E�z���:���n�5����C��6��1C�W����]��a���<xP�lw4f��P���*[X��.�R�w!��}����T����������K�,��O��/U���:R��Tk��ar Jq�*�T������8p��i����k�����d��YIII�$����g�C$��������5�o�����]�J�i��!��-[�8��i_,\�P�.{V�Hs�q����e���!����*?�7n��.�G�-�S�H���[y�-T�����6a������={�e������#�[8|��{�O�>=o����T��\)�'�|b�V�\����� +�yU<���e�?��#�s�LU��|���tRZ�%��nhf�PO��2XhD����=����;�&��5��i��P;$[hs��1�����C(�labb�T�R�HQ]jw��]Zuu���;�O�.5�l�*��-Z�����a���_#q��1�]"�
l��U���r��Q���C���n��]���VN%//o���r��Qd�r�=zH]7v�X	����z�+r����1B�1 w�,� n���GYY��#����k����?�a��m'M�TSS�u��*//��_������?��������[_x���n��y��-[�l���{��WUU�u��j����Z��`��)�����7n�}��'�"+w��a����,����_��S'	u�<��C'N�kb[���z�����T&W]u������s�={�xRf����{�����/���k��o��]�������<�����.]�l����[n��NS����;��;v���K�N�:]w�u��#�<RVV�u����������*[(W�C��B�-������Q�'%%����4h��|���nS�����'���r#��~����i���k�������e��yX~�.]�H[�}��YYYj��c�~��_����~����GJJ��l�V���������?����W�^��9s��[o��o����e���~��r�����D�K��[�n*������l����?��,��kW�������i��2k��@ ��L���#��={��%?���v�������K*��H��:w�\������8q��\%n��f����l����>u������Z�p�����m��q�d�<�I��i��	-Z�x�����_��������W�����Z���1#99���>�Sq=��+�������m���U�B�kYY�5�\#KV�\i]���H.�,��%N%
2s�Li�?�����t�M��� t7n�z��	fU����^�-_�d�,����=)U<������_���-|�����������X�z�����Y����m�V����?f��~��UTT��l����9w��x4T�^��	�������>+M�<9���J���=[N����-3f����Ry�%[���O�G+V���L��� ����k�k�}��aCJ��u�YvOJq��m;��$*��{������_��U������-��
S�-�W�����������T�W�z��z��3g��/k����Y��u��[g=��Ol��$.�B5�����?�����G?�Q�-��i3q���M���b�_,�5J������>�6r�d��n�)xe��l���a�����)P�t��StC���l���w�������s"_��q�V��l��W_-
>\���u���{�M�6j�_�b555Q:,dO�:u��w�|��W\q��~���^{-33�}��g��Is���l��x,Y�$�#����s,N�
�Bo�����c��m��������������lauu��,W_}�|���I��N����b@�0##C�$�Z�z�����6=~���w��8C
������_bq�n�z�-,((P�?������/--=y����So���k���6�m#1?[T~�g�����
���
�*���r�$''�h��y����.��s�O~��*l
��+f���H[~��I�u��]>0`@,N�
�B������S~���l�W�X!�o������X�����������.\h[�m�6Y~��WFy���-�>��9��-[����>Z�dI�-��1c����4f{��j*�9y���cq�n�z�-�������-[f[^]]�F���{w,N��/����{�|4o�<������n�Q�~�e����_/��y�f���3g��-Z�Z�^f���/��:��WUU���?��������l����n�ANy��5���?�-_d�t�"�����o��I�_��Q:,e���_y���;8p��QMM�5�\#W`���z��e�~��H�>�!��lann��Bv��a�������o�=vg�B��j���#G��=zTu���������4����n����z�>��SQ:,��-l������A�l��������j�������-Z���+��^P��6m��>}Z-��g�O�SY8g�o�g^e=���o�q��o�-��m�a���%[�j������N�^�Z%�����[�x�6m��f���g����+��o�����G�k����B�PZZ��_�J�W]uU�v�Tg3��K���/���T��y��z���?�uWeee�N�������:���k�<���7���������N�b�u�!�n��V�Dn���c�n��fY�U�VO<���0>3y.��OR�+���>�����r���u��q����[�:��w��N�����pTTT�=�u��-Z�����;t�<���j��I����U+������~��_�x����7��������A����x]�x����������MJJ���~��W�l����kR�x,_������O~�u��i�f���yyyz��+W�\L��sg�f�������O~��o~���^z�UW]��3����;x�O>�������7Y��+���o�����222~���_}��������~����_�|����N�z�]w}�;���7�q���'$$����Y�h�������7o���%�\��U��n������������������^|����5�\s��w_q���e�]�v�Z�j�}�����m��_��_��_�p�
��������S'Y~�E���?���;���o���9s��bG�-G��~{�f�~��_fdd�%����=��,������b����#�\r��_<u�T����&99YV������R�����e�����Cee�Z�b��o|�]t��;�q�M�&�}�������z�!Y��}{�2G�-Gl��������g�Z�]z���QZZ�Z����������l{���;d����������_[�lY]]m]-11Q�?���z��7�(K�M�f]-//�����d���1�������k��\�2������Y�f~�����+��_��[g[m�����m����g�yF~����m���o}�[����_~)�~��(//�����O:���E�-�Heff^t�E_|�z=9;;[�=XRRb[s����`�����8��Z��/���{�����
^m�������?�l�l "�7o�����5k��K�d��-�����������T"���P~������}�����U+�h����sjj����c��6w�\���[n	U�h�����_w�uj��[n�e������+W�B�4x���J�-<q���9333x�_��z���={��/��B�j�X�^{m�rF�-�p<���*�w���v�m�����%K���n��q��.�H>MOO/,,T{8w�\�j�[����y���K�.j������[']q������TSSs���E��v�m��aQQQmx}333��[�������?��XJ4��l@f�V?����5k6`��u�����w����5��=�2������7��M�y����k���?��,2D~~��G�W�={�|t�m��*[4��x}o�a��`5l��f���s�=�s^^�u*�M�6���/�\�����TOebUSS����_.\j:�A��GO=�T��E�-�Qof"63����P�L����s�>������z�G)))��5�������]w���j�*�j����;vT�����k�^�l����C�N����_333��K/�������C=$�92T�������3����M�dD(`&b���y��5k���������}��M���			���jjjn��FY>}�t���?�_���j=C���+���_|Q/QC#N�0��Zff�%�\���}����.��f[����Dlf"6�����Mw���W_}u�f�Z�n��lIII���u����'O�����d�����@m��&����,��XUU�V��n��fY��S���2�p��_|�%�\�����^(��w������%YYYw�y�,|����j�����9r$�m��6`&b0�	���Dl�k�����/���Y�K.��G?��-����o}K�
m/��3��_��,���+�����}�{*e�{�n�j��j�^{��|��O�<�vh�l7�x���s������


�:z��
6D�-?���Dlf"6������p�>}�k���Z�����.����������c��b��m?������K/���+�|���O�8�����;_u�U������:�N�6�g��������o��o��������J�la8��#�m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0
������Dlf"6�����M��m�L�&`&b0�c��-[T�x�'�������Dlf"6�Y#4��[<y|�#m��{��W}���e�2���/�����M�L�&`2�U���UIB�_����t@�����z0�	���L���w3^|��'���.��u�&��'��6`&b0�	(PZR�`f��B�	���vw��;�ua����'��6`&b0�	�����1��~�K��`�k�+O[����zI~���.2������Dlf"6CT~�� �k�n�{W�Pk��K�~T��#oK4A<=�_��3����M�s��������I�������&'��I~�?�u�:�(����@�����z0�	����(�/y����p��<�D�CEhMnvV����<�'���2���/�����M�L�&���K>����y�����Y���eK�[�������/�����M�L�&O�7�%tv���;��\��a]�=Bs;w��g?�`myy������	�B�
����Dl�PVV�xn���8�	��lW2kJ��(x;��>q����1�������z0�	���U����Feu��1O���s�kV�l^o��L�d���7@���	�B�
����Dl��j��z8�t|�m�Q��}��$��y�	��(1*>7<=�_��3����M �����}�9�$aV�{�'���>��������C�L���OO��m�L�&`&b��@qQ��)�O�s��<�H����ee�3�-7�z���z�����z0�	����W��Q���s���'�K�\�����9�-/�~����;wj�����'��6`&b0�	D�b���r�����S���f��Gh�������#�F����z0�	���������E��e?����w��%�-L�{~��vw�d��������Dlf"6����d�;6��}�y��W�)O[��E���"k��:��$�xz��Pof"63�@������������Z����4�-_��Z��5�b^$�<=�o��3����M�^��?�{�E�$aV�����Ys�T#�����|�:�(.j��MOO��m�L�&`&b%P\\:w�u�a�9��X�`V���Q�����:���.]���~�T6�)��	�B�
����Dl��Oe�5,�W�t��u�}����S��Eh����W���e�2���/�����M�L�&`U�����	58a��~�_���<
���������T������
h�xz��Pof"63��R�bi�KO;N���%S&�r�_�Gh����S(�f��4e<=�_��3����M4q����)���1O����e+�zX�h"�d�D��T��m�����'��6`&b0��&�����!�B�t���/��yQFh��O�����'bX0����	�B�
����Dl�	��t}�_^q~��W�,zkx��L����������+��^��4i<=�_��3����M4������s~��1O��t������^�+����1���Y}�x��4e<=�_��3����M45���{3����y���_,����et�-/�~���#1v���MOO��m�L�&`&b��=���jp��A}��#&Z�}�����.�I�����'��6`&b0��Uy���?<�<8a���'���������U��s����U���sL����z0�	����&PXP2}R��m��9�{�l�"���XEh� ?��}�g|�����	4e<=�_��3����M\0�3���r���y����W���u#�-_������[��MOO��m�L�&`&b�����w�������,�Z���u(����������(.�������'��6`&b0�	+//[:?��������U���~O��6Bk��f��K_��ab�g����	�B�
����Dl��j����V�����'�����kVy]���y��.�m�V��w�p�@�����z0�	�����T�W������{o��d��K����;����T������h
xz��Pof"63������r���c�0��-~����s^�1�#B�O�^��	�b��)��	�B�
����Dl�p��������+�<a�s��-���k�-�2�z��������'��6`&b0�	cUgf�L=��N�<a~�?Vl���26�����g>�t}���8p��	�B�
����Dl�@�;��������m�(|#�:���e������/�X/l��)�q�B����z0�	����Q��-�y�I�<a���L/PX�u��Q#�h�P��9}��\xxz��Pof"63�0AMNv�{����<a��-O[�u���(-�~�A}��^��\xxz��Pof"63��VU����I�/�{[A���{w{]F/5v�Vl�l��e�5���	OO��m�L�&`&b^���&��/9&	���.�f���^��{q����D����&7�Q\xz��Pof"63���@iI��������'�y�����k���.�)�������������k��0�����Dlf"675gN������y�����b�z��h��Dh��e���/�OO��m�L�&`&bqP�{g~���	��ph��cG�.����y	����������8�/���/�����M�L�&U��s_��c�0��J�N�{]F��-Bk���k{��v
�H��A���	�B�
����Dl�1
�K�N�~��<a��O�����2�C<#�t�L��T�{g|��OO��m�L�&`&b�U}�H�����1O������"��}����?�j�������z0�	���D�Tl�����$a�Cw�^s���e��8Gh��#�/�x�[q;4�/<=�_��3����MD���t���gq��7J����x]J���Oo���2
���'��6`&b0���9w����Y�[;�	���R��5^���<���g�2�������z0�	���DT�����$�����T�~��2^ <���/�X���9�����xz��Pof"63��H��+r;wr����)�<�&'��2^P����������w��>�2&��	�B�
����Dl"�������h��'�y���e��.����
��d?�����_)�eL����z0�	�������c�#�{��<a~�?W���u/dFh����������0OO��m�L�&`&b�Tl����5�����U4jHuf��e��y�z�����]��k�����	�B�
����Dl�������9�?��'���C%�����.eS�m�
���������=�*	`���/�����M�L�&�����w�du��1O�������y]�&��-[���6��������<6���Dlf"6!�����$�[�������.ceB���������?PZ�my����Qof"63�M\���yz�yp���O|�&���el�L����'��=?�M����-`b>�m�L�&`&b�i
��y?����y���/[������b��-�;�z�T}���3$6a���Dlf"6���S�E��f���1O�������z]F�gN������|�3{]�c��& �����M�L�f�Q�k[~b��	��p����c^�v�Dh��#�{�x�8�Kx�����z0�	���l
�>Z���S�y��'����(,���pfT��;�z�T=�u����zQof"63��@^n����i��'�����������i�����o�����8�gL�M�;�m�L�&`&b��T�ezaj?���������}�{]F�����b��^*�;���0-6���3�����L�'�����1I���u��#k��������Z8b�����5�Oz]"��&��6`&b0�ya���.�����u��<�H����ee^30B�f�z�~}w�����%<``l\Pof"63�~Ws�T��Y��v��%��b�����33B+6���fe+>��D@����P��3����M���|WA����>p{����cLY�{�FhA�������{]" ���M�#�m�L�&`&b���������c�0��J�M$us�06Bkr��=Z�{y]" ���M�#�m�L�&`&b�G�%����x[�<a���)_���2"�L����K�w`���^���c�z0�	������cG
���k{�c�� �k��;�.#�����K���>�`����qbxll��3����M�Ul�$����I����.�F��S^�����9}���.��u��81<66�����M�L�����K������c�0�7�[�`&����#�d�4��Y���K����	����Dlf"6MS�}�x����8�	���\�q��eD��"Bs_~�|*����.��M�F�
����Dl������=���_aj��/��.#��Z}���^-�<�����	���3����M��Y���s��>��x����\��o�%B�'�e�o����D@��Kl�m�L�&`&b�C����YS��l��'�}����K�.#<���~��������.��|��Z�m�T�&`&b���E#S����1O����r�6��#�(B+w�����fz]"��(6������M�L�f����<�����8�cG�9��]����i;�3��3?+"V,K$(�J\�

��� � ��#���5@B��������������66���$w�~����#���|N���=��,5�9��#�t���1���\t����jo\�?��MUC����D�W6�m@Nd��L��/L�t�8'4v�t/_�9��k�t��P��0tl����,����l�����& '��h����d��}��sB��}�{v����]B}����n�$�" !t�MHs�m@Nd��LQ�m���C���m���D���1��7����o�B�YEW���	���
��lr"������2�_���o����j2�������f�!�y�`\tE@��1��������& '�G���^����]�9��O����k���4���_����;zHtE@��4��������& '�JE�c�d�cE�Z���������^k��Fs�DW��~�	���
��lr"�1�����z5��	�4uLy[)�$�F��~�^���wEW��~�	���
��lr"��������{�9�����O5�Ct��=]'4���\�O�]7��&�!�6 '�	��l6�f���6>�*����Bo����kD��{BM}��.�����r���{6 ���9�M@Nd����b�;c"�t��lc��O���F�	�����`������{6 ���9�M@Nd�>|�-��8$4���s�4�X-�F��H�s���Q�JEW�A
d�
}���D6���q����C�9��gG��������,���e�����%�  R!��N�����& '��Z]��9���p�9�eH�/g���R#�5y�	r�LtE@�R#��>�����& '�y������E�8a�������b�5"��LB���
����L5T���I�d�}���D6�xwl6�qNh����h�f���i'e�9��-��]���&�	�6 '�	��ljv�k�<c�6����{x�o]#�W*%��gGx��;���h�T�&��6 '�	�)���\*��?��u��sB��Ck�]#�]�%�:bP�|��-8^��b���G��D69�g6}�X_{)������1c�ZY!�F�K)�P�l4d4�����7DW4R�eR}����^��z=�V�zw�8'4=���j��v��I��3�;��C�+#��	���
��lrJ�l��j�����-"�	-����]#AJ&���+�Bm^����K�l@
�or"���R>���S�q�G~y"�����"�5Q�dB����:>zOtE@��d6 ���9�M@N)�M�����D�8a���Ogi���H��������PtE@��j6 U��9�M@N��M��p-]h��6������g�:�5��z	�c��%t��>]D�4L
gR}����J�T�/9>�~���/��Wj�SdK�>R)�W��'��h����H�l@J�or"���R#�5y��#G>�����'+��k#5�c����*e��+�+��	���
��lr�{6=����v�8'4vo�^�Xs:E�4��z^��[f�BY�D�W�gR}�����lj�s�LC�?G�Z>���)�F t����)��{�
������C��D69�.���"��7#	�_�	���*R����I�C��h��DW�X:dR	}�����l���������[8?�����k�LG	m4��F8tl��,�7���TB��D69��M��r���������g�x6~!�F Q�Oh\xwo�u�[�7�&���A��D69��M�����{���#�	�������H,�_�!Y�GkN�����I�l@j�or"�����f��<�C#_�0�A���J�%�5� gBA5T2��%�>i�����I�l@j�or"���d��w�Fs��"�	�]s-Y�GH+�%4��kW�G�� OtE@Ti�MH�m@Nd��$��lV��9�N�"�	�/����:fHG�$4i�Y�B ���zEWD�n���or"����gS))���Vu�"�	mo���X ���&�RV�3����,��	zG��D69	���������9{�j�R �4\=]���wQ�����0��k�m@Nd���lz<�5�M=;F��zw��[���@��\=M}��zB�.��"H�l�~��9�M@N���Z]�������"�	�y�w�@r*�"=WOQaxsp}6_tE���3��_�m@Nd�Sr��?u�6vX�!au�����)�J]�Gi�z:>z/�Q(e��+�N�ft��
��lrJt6������4�����k�<�nK��z�����l��g�]�w�7��O�m@Nd�S���9����dD����n��RO:��������g�j�!��M�#�6 '�	�)��T�/9��]��i�9�m�k5'��q@jK������[�g4S�F�_I�l����9�M@Nq����!���#	
�;fNQ����A@�H��Ss:�[���4b������y6@w�����& ��d��a��O��sBS���KO\��
��w�������)�"�Kd���
��lr�%������Q��?�_�W�f��Z ��zY�d�T��Rs:DW�M��6 '�	��q������8$�n����1JIq"��
�g�j�2d4�k2�w�]@6�EQ��>�������w���o|�_��_�w�~���k����:��?>����z�����9s��.]���s���g?�����o��e���6E�i���5k���}��[n��/~1d���Z��cy-i��9�M@N
��7{�������'Z���l�Qq��Y�����nSS�'�"�;�yC��Y�fM�4�����������w�������|���V�
���s�����������7���������[w��������n�-�����=��������&N�x�G�����s��_?������wk������e��Z2�or"�����M��t/_d��qNh����e}��
�gsV���&�e�.��l�PVVV�&M��������Gl6[�N���~��n��������o��k_���jQU����
>��?�a��E��/|p��555�n����[n����rss�>w������y��u:��m����A����$G��D69�0�JE�c�����8'��z��|��a������7��i�+BZ#���v�o���&M��[�.�q��~�����m[�#/��B��g�y��wh��i���3g�~�b�������/E	����|��'��{����>�p����Y,�o����#�����}���t�l����|%���������jeE���
�g8������_T(�"�/�y}�e��I��������G���#	������{����i3g�>��u��o{���v���W=���0��w����/\����[n�z�W=��'��x�r�X^@~�m@Nd�S�lz6�1��������W~��]B��
��UL}:����l7�� }��F���~��I�;v�m4k�=�r]�_���[{Rp���3���4�������;������}�����?���s��by-���9�M@N���,&������8'�����Kh�@�a���������Z�@tEHSd�q6m���I���G���������;�}��`�$�������/�:u��g���g�)�'N��S�N�>m���������V[,� ?�6 '�	��6������##	�_�����?@V�k9�OoP����+B:"��p������-ZT����[�����?���555����������_��?���u>|x��}����i��u�=�D+/���}���tz��K�;G:<��7S5E��/V�<������]��l�.��W�j����/�X����k���{��_r�M7ZTTd��k������>����h����<�����>m��=��h�Va,� ?�6 '�	HEs�]����;�����g��5`���w�Px��_!��f�����y����BM����������9���x���j����t�`�����*[�1�����gN.],�F����k\���StEHG����e���z��7�t���>|�p�&Mn���k_UUUU;!t:��o���o�}���k�����m��!��I�&���O\���K���?�!Z����*�������y����8$�l���QC��m]#����=W�6��c`?�!�sv�����{�M7}���\�j��?�X,��2	w�����?���k����]w+�p�����;�v����nG2a�����u�z/�X^@~�m@NdE������zt�8'������I���.@������)���f��i�l���U������{�����������M�4��m�U�O�<9�x���k����o��#F\�������UU
~[^^����������m��
�h����*����G��D6��S�*�g�lqNhyu��@6�dFB��2$+tc��-5����	B6o���S��r����z����<m��!�����}��||�����l��!���~�3������>����>[������#�f�
Zyy��7��������:���Z��or"�@2����z5������w�R.��>�l2#�����[7��o�������l�P��G�M�v��]�|��[o
>s����7@���y�������������}Z�G���o��������>��g�}�k_��������������}�{�}�`0<����{��]�4����W���
}-=�or"�@rx6�1��qNh������f
>�dFBo��jIx��)�]��������^�������#9rd���-[����'�}��M�6���;jGv��y�����v�=�����}m���W}z��1��������k�����ol6[�s�.��w�������9�M �4����C�G#�	�Y��;6G|!�dFB����{��"�2E���@6�o��uM��{����?r�H�����o|�w�}w�������}�+W�dee���?
>��;�h��]�A�WY�ti�f�n���[o���{�3fL����M��ZzD��D6�����{=�I����6v�������l2#���\,�{������l����9�M �����_�qHhh��9g�j2��M�& 3ZO����@�b��_��l����9�M ^4���x��KF�9��O�������F6����3����B��7~�	�B��D6��)�J�����4��:bPMnNC��l2#���?}"�%��-]R�}�or"�@,|�-��|�qF3��w�����3�dFB����P{l�T�rYtEHYd���
��l��y��U���nqNh����|��r��d�	m��2vnS�$-���)�l����9�M�A��
������#�	-��������M@f$��|G�wK��u�+Bj"��/�m@Nd�������G���F+%���'�dFB������2�k6������&�}��n��a�����O:����`N"~�%���Hh#[�!3t`�m�0�!�M��6 '�	D��������8'4?���mc�>�l2#�����!���f����l����9�M�Z��'lc�G;��6�������l2#��f�:�cK��]R
�}�or"�@8�����^���vr��@5V'��	���6�j��n����:��-�"��	�B��D6��_���Z4���u�9��w'���7�%�M@f$4����X���+B� ��/�m@NdiN))��;�������^�> �0�	�������{�/2=:�.��l����9�M�-��=���E�8a������r���M@f$4F�������d����"�&�}��D��\N����O��8'4vm�Z�Ps:E�I6����9��o���b�!�M��6 '����T�;��cx���sB��g�{v��1�l2#�qa����	��w]R�}�or"�H5�9��"�t���o��\(]���& 3��'���{�g�+���M��6 '��T��z��6��qHh���9�c�j]edd�	���������j�]��l����9�M�$�dt��nx���sBs���-�D�xd�	���2tl�(��,�A��&�}��D���:n3,�I��7������^�& 3G�������u����cd���
��l"ex�o2������3��U��kl�	�����m�����\�YEW�"��/�m@Ndz����p��S��sBS���/��^�e6�dFB�+��
��C���5BtE�+�	�B��D6�_JI�}��h'[���;�Ot��G6�����lY��}G���D6@_�����&���o�eP��s�6M���W�JE�+�	���&�e`��;���.�A�&�}����h.�{�"c�v���'3\���v�e��dFBA�r��u�����`����?d���
��lB��������f����xwm]c��M@f$4A����w���+���M��6 '�	����{9��	m�G�����1!�& 3�8���Cw���At9��	�B��D6!)���n��w��CBC�G����,&�U&�dFBG�X����?]��l����9�M�F5V;g}`h���sBS����kD��d�	M(���;
��
IC6@_�����&�Qs"�6��h'[G�R��F���M@f$4�L=:�.N��Kt9�
�	�B��D6!��
����|�q���'���kL6�	���&��������j����d���
��lB �jq-�m|�U����n�^���q�.S�	���&�����E�uS�P%�"��}�or"�B�Pd��f���-���]�`d�	M��2tlZ�d��:@6@_�����&�����2�_�9a���w�R.���Q
d�	M����e��}��� ;�	�B��D6����Z����m�9��s��O4�Ut�!���Hh��F�%t%��-X)p}d���
��l"���R����F���zywl]���& 3�4��h�l^�j���]�F6@_�����&�w������]��6v���	�5��l2#�����&|��=$�"��l����9�M����^������CBC��9�U�Qt��#���Hh��_����Mp�]$E6@_�����&�H��t��b�|8����L�������dFB�L�r9|AqL�,�"H�l����9�M�E��<��C��tl1�&���u�l2#���Z� |e���2"��/�m@Nd1�lYg��=�I��=����ZY!�F]"���H�����O��@Fd���
��l�q4��9�cC���������/�\N�e��dFB�P.��5�sDW��M��6 '���R.�&��v��ep����kLd�	�9{z�������r!��/�m@Nd������r�hsB���JI��S�dFB2v��[z�Y�D���M��6 '����N��O�]�|�q�V�s4�Ut���l2#����/C�5�EW��M��6 '���P�J��O�n�4����|��M�kLYd�	�>y\��Z�TC��� �	�B��D6�/g�u��N:��~��d��S�dFB������lY�d��� ��/�m@Nd��u����c�!������>P����Ld�	��wg�
���UtE��}�or"���VU:fL1d6�8'4���Y�2���.3��M@f$T��B�j�Bs:DW��&�}��DM~�u��h'[_{�w�����dFBe������O|StE�l����9��t������{�9a������r�5�/�	���J��au���;zHtE�l����9��4�YL�y3
�qNh����l��t�.3��M@f$T���BKX�6/�Hkd���
��l��Y����N:�|���St��
�dFB��^���9f�/�"�D6@_�����f����f~�O�9���7�E�k��!���H�T\��_��E��+�0d���
��l�6�a�e|2#������s����"�LD@6��P���t�[���]�!��/�m@Nd3U)�J����n�4������g�z�5�z�& 3*Qa�2�Z���� �}�or"���wp�eHV���mo�9�'�F��dFB%��xj�z������M��6 '��24���j��G��'g>��1E��]&��l2#�2�z��2CG�g�] ��/�m@Nd3�����3�mqNh����fy�w(�e�a�& 3*�������n����ld���
��l�Z��#���D;��:�_�~�5���& 3*-�;cB��g4S�F�!��&�}���)��5��]#�	�4��?��5��dFB��9��-C81HtEH*�	�B��D6�E5�s?2�oqNh|2���S�a]&��l2#�2����8�]��l����9�M�����{=�I���xwo]#��l2#����:�}��]��l����9�M�ywn1��;���6~�����d�	��j62�����w���IB6@_�������4���x��s��CBC�G��fj��2�(d�	��g���u�� OtEH�	�B��D6%�\*���Vu���O:~��g�Z�5"��& 3���^�K�v�x��+B��M��6 '�)��l����tl�JM>�g��	�����RV��:?�*�"$�}�or"�2�<n���MO=�������VV�.IE6��P�p-�$|I����E6@_������Xje�c�d�cE���n�^�D��E�	�& 3�#�>]Bk�.��Ab�M��6 '�)JM�a����N:��:�w0[t��l2#�:�/*_a]��]�l����9����lXmz�K�9a���w�R.�����M@f$T_3��������+B��M��6 '��4����3���E�9��s��y��.�L��l2#�:���e���OtAH�	�B��D6����m��h'��zywn]#�C6��P��)�_|=�W��	A6@_�����fBywl6�mNh;�_tVt���dFB��>qt�l�h����+B��M��6 '�����Z4���u�!��}��U���z�& 3�G��~=��A�+B��M��6 '�_JI���1���8'4=����S�P/d�	�)��m���7{���gd���
��l��o�n�����tl1�&����'d�	�/������[jN���?�����&��T���f�4����3�S�"�t��C����������M@f$T�TC�!�Y�Jm�<NtE���\3�U��P�=�����?��Y@6@G���D6M�(wL{���C������W|������^�M@f$T��k��/�5y�+B�}5|�n<x������M���9��F������c����}�E��#���H����z����-St9�.4lq<x�W��W�&��T���f���u�L}�D��z�����Xt�Hd�	�;��4|w��&�"���L3�����m�{~p���U_���L6@G���D6�C5V;gO7<�H���;�r-������DJ!���Hh
�����r���	��v��]
����xJ-}O��	(�	�B��D6���d�m��h'������It�HMd�	M
����w]N��u<��������k��W�7�}�or"��x�o2?�#���6fX���5"��M@f$45��
�w���+JQ_���0�O9�C-��Y��
�G6@_������U4���`��S��CB���8gMS����D�#���Hh�p|89|�W�\]QJ�j<8����������^��Y��p<x�	�B��D6�(%��I��Lh����ne��]&��dFBS��k���n���'� }�u<����^��4�������	�B��D6��{wZ��6'�{�w����v�& 3�J|G�����kDW�u��������8�E6@_�����9����^���-3��0�A���JE��2���9���Hh��M��Hfs�l]�|�n<��������^��Y��w<x�	�B�����T*�S'2�E��e��-��
�N_��M@/Hh��lVC��{��~MtE�U�6��r��Z6]����UM6@_�����-��#��^�v��e������k��n��������������+J�/���?<�[��3j����`2��W!��/�m@N��M���v��w�hsB��7�E��B�%��>���d�:�cK���6t�W�x�w���j�G����-	!��/�m@N)�M�X�������"	���>��Y-������t���$�P~����EWo���c;��r�Y�l�f��%Q�M��6 ��f��c���v0���S�-�E�D���R	MU��K����O��(6��`�����EoI}�M��6 ����g��sOG���Zs<Ot��
�d6��ABS�9�W�>��G��4����������QN�S�g�h<x�	�B���J�������O��|�q����S��J�e��J�R	MaJYi���s���+��X��PN�W�?�lGDoI|�M��6 ����r��>��h�zvt�Y�zE�	4@jdHU$4��>��#�\,]Q�/��b��r�9�|�fO����&�}��������2��hsB�_^���]#�z�&��Hh�3��v���"K�m<����z�y�|v��+r+��l����9�4����Z����m�9a����'(e���O���	My��'�w-��%��c�����9{:^��l����9�.�JY�c���F���p-�Ts�E�	�Jw��
	M�����1Z7U�\N�'�����0��KT��A6@_����t�M����^�v����g������eHC$4hn��s�����~q{�X��;���_=��x0"�	�B����lz��5�M���6'���/:+�J �t�M ���4�;z(|���e]#���:4�{w���T_�.p��u�R�}�or�9�jU�c�C������:���,&�e	!s6���a?2����\�Y�������V?���]�p$x�R
�}�or�3�5��lo�v0���n�MkE�$���P����f5�o:�a��������?<�T-|I��pO����	�B��$[6=[���w�6'��z�&_�j���-��������)|o�w����~5����w�#��/k��'Do_J!��/�m@N�dS����g:�9�I�m�;>zO��]&�<�d@D$4�X�d3k��K���������&��x��@�bA�yR���2�	�B��$<���"��Q�&4=���j��q�Bx6\	M�����������*G�1L>�	�B��$0��=�-/=mNh2�w0[Ha�X7����>�����w��yH=;H��0�<%zK��}�orJ~65����Sc��"�	[7�O�\*IfI��X7����x�f�?*G��gkW��Eo	�B6@_������M�������6M#�	��������H�u�	��/���{��?������#�K����Wp��9o������&�}�Sr��;��:��h'�_����%�5���	�����W���7T��I=��v���������g���(��n�B6@_�����M��v����c�9������	�t@�X7��Py�c~����!Z��W��S���x������
�M��6 �eS��t�x���<������s������R�& 3*���`A����Y�}������O���q��<���!��/�m@Nq�fM~�u��h������:��*�M@f$T����Q���Z����\�KpL�~�6�P��C,�&�}�S������l�hsB���5����A@:`�dFB�*�����+�-���h�K��xU��]��m�vr,C������}�or�=�����7�����'?��c��jeE�
��& 3�X_�77v<x����Z��V�,�>��}G���x�mL�g���&�}�S,������`B�S��+>�\���	�M@f$4�b��Y-�U-��z�b�����d�l�d~:""��/�m@N���w�6��}��	-�������j����	�����v<xq\���w(y-���Z��������l������.��"��/�m@N
�����>�o��yN���;c����YHU����Hh����<�s�$��ky����=$��tG6@_������M�R���q���F>��S+��9����& 3zc��[��GhU+�����,����:���.��5�	�B��t�l�f[��v��y@O��MI�H����Hh7������V���U�
xJDoI��W.��9�1���5�	�B��-����^���t�hsB��a5'�_0�&X7���/��4�����k���U�xJEoI�����#�O�]Q�"��/�m@N�fS��tL�l�hqHh�l��5M��U0�&X7��iBc�H9����U�^�%�g��ng�����r�W�ft��
�)<�5���Q�F;�0���Y�2���-H�����%�_��7f<��c��cj�Z����L��$�r�8|����,���t�&�
�6 ��lz��3��mNh����A����u�Y�&44|��`C9?�������k=J�l@��o���s�����S�9a������r�e��u�Y�$4���]���j���am�����L=:����Kt9�(u�	���
HE))�O|3�����m]KjN��2����	�L�	
������g���5������-������*����+J;:�&�%�6 	��]�A���	-/����!�F��������������S/���>npV/�)o��
��L5��[R�)��6 ��r��/6vomNh?R�P$�L_a�d&uBkL�ik#��{�V���xp�����.C������]Qz�:��k��Q��
��w
�=qHx%���q�4�It���& 3���xpB���?U����j����j�[�"|�����;6��(���M��������;l}}p��	M}��l\C69�M@f��xPz�1�B�#�o����+J���/�m �<���v�6'��\�w���d��d�����_��wj�x�gJA��[�qS�������j62����2a�����'�}H�br��i��h�!������Q++�_B69�M@f	O����i�x�_�����q�q3�A�<�������]QZ`�}�o	�\(���`Bc�v���5����M@Nd�Y��xp��)O��k�-�.D,��~����m^���R�'�}H�����F�wS�{w^��d��d��~9�����=�W_���2��z�ru��u{e�'��(��z��������N��E��m��	�o��\(����M@Nd�Yc��x��F���|m�����mBB���w��E��+Jq���/�m ^��r�����f�/N�����kVK=��lr"�����P���+s��u�i�>]D���X=@_��@�jrs��F;�����g����'��D6�ENhh<�����������L�L�~��mB�(��w�\���(��z�����Xx6�6��mNh�jM~#�E69�M@f���s�����=������/��O�%�4���)�9gz���RV*�����	�B�A5�s?4�o�����NV++b��	��l��Ui�_\������;�����/�]��w4���b�H6c���� Y�D���X=@_��@��������`B�S��W~�y����D6yh������
;�x������w5�.���)���s�Y.�����	�B����k���>�������������M@Nd�{Y�Z��{U9��a��������7.t�HF3�P%��������k.������t��z����N��O�OfD��'�VJ����d���L��WK�S�w���i}��;���>����j�Eod�9��-C�%�"�����_������Gf��1���������_���`��� ���1���6M#	�O�r-��Y-	�t�	��l	�)�*��g)��o���'{^�?�t�g�7��;������UtE��*�B��-�{?>�d���]7~`y�����_����	:�o=��|�X_{)�����Oy�nHt
d���Ouk�l�d�R���}W}���nSr[��Gj���S�;�P4������������I��1�:��h��y���{�ck�_g0�k���&��T@���Y����S�9����5���S��D6��p���,R_�����W9�G-�8�(���$��������K�L-�"a�m�v�����Q���:��O5t6������1����M���� �dt��nx���C����c��jUe2K"����&�H�C3�R/�W�������~O���Z��f���o�!$��l�"|�� I#�Y�����gO����X�,��u��a�'|b������uD6@_��Hs�S�mc�E;�����{�R��N~ad���U�U�W�<�?���@x�r��V>;�<��$���e`��E��e�^��S��w!�]\�v����x����c�
�����;G�?��gg��r���z��&��/�m�-��-��^����W�f,�lr"���(6��M�0F9���}{}�������V�Gk�-�5��'���z�r��c��5��w!1_�\�w��%�������\�d,���^ze��i��]�u�x���4��	�B�F��v�g��]2"�	[=`w�r�Dt�d����<�]���~���p���VN��.p��c-$�s-�4|��_T(���v�W_V�iR���Fg4�.$�_�W>�k�ko�L�z����{y��M��6��RVjo\u�����N�\��j��i�#�	��l�Y3nR��P�Z�w}�����P/��L��-A��P���O��ui�t]��j�B2����������^�=vr�'+�o��>i�XQ3�}�o#�r�[����c��=��7���jd��D�r���3�S���m���~��yN��p�IN�$q�/*�Wt-�'�g�+�P��x�����'�_�]H�m~e���f�\��t�Y���m�}�o#�y��5�M=;F��F���D��*##����&�EM�fX����>��u[}��{�T��U/��L;�#�U�P��s����F��4	Z���W���p�[�g���z������U��M��l������Tc�����v�8$4d>�i�9����	��l"�i��j�t������h���W��*\�Do	E<�e�NE���7�*�����J�g��/����iP,����_z5���$�}�o#���,��~-������k��^�e���D6�R|W���j�_����;�]����S/N����K�6��8�)�����[����r�r*�/=�iR����l���X����{���9�?=�zO����8nu��M��6R�w�&��������/��]c�M@Ndz����S�]������A-|Q��(�>/z���"����:9%��j6��U��_��d���Oo�lE�Xf����i�[���[y~kn�)�W�[�5�}�oC�4���h��s��s��M���K��f��lr"���%�j�z��H������WK&j�=�-z���"�4����e���#]���w!9�E��)�>�=���Y1�����W�x��e[/�?g)���@6@_���/�R���m�@�9��s��y��.��F"����&tA��SK'+�;���]�	���j����������H(�����n�����;��]X�f�����>��U�b����~v��+�W\���@d���
=����: �I���^��E�+�	��lBR�Z��j��������<����Y�T����8$��U|�L�7�����g�>~��G�q����E�/�:i:���.$�F6@_�����v�^j��!���6v���q�e���D6!��Y��%�����7�����gi�K��9��	E�T��9�K�m�xt����l�]H������B�hd���
]P�*3�2�G�9k�j��u���lr"��uN��P=�����@��n�xg�t�f�/z���>�[K�_:0����Nyj��c�I�/�B2��c�W���W}�����>�M��6$Ws<����h�zwr�]�yE�d��DR)v��C�8N9�����@x��z��jy�{I�6$	�U,^�1������?6��=����]H��2��W�j����o�������&�}�oCZ������6'�������5&��D6�p����y������i��?S�?��N��Eo�H$4���+�\>���c��������l��}�����Gg-9���������E�O��zB6@_����f���1>�*���MS����R�e&��D6~�f��^������~}��;��i���U�x�*�WHh��(����
wX�x��I�6��]H��|����3������C]���/�&�u�l����!���>it��	�Of��|�9���L�	��l">������g��k����QNtS/}��rDo��Hh��t]�_rn��Gg=���V_���.$}�
����g��s�H�������t	]�O��mr�!��/�m����e�s�����xwm]c��M@Nd�Tc������G�����~[9�\-zM�^�U�� ����Z�����'��8�~�-�6]�M�����
�wS]����V�6�	�B��@���^�������	mo���]�d��D����������j����]9��Z6]��_Z��P�1{my��W������/��n���\���-C^?8e����.�O�]H3�����W����M��6�P++N6�mqHhh��9�C�d]�Hd��������5j�p����;�[��|~�U��j�Eo���P���/�)?�����s���6�O������g�����������SYP�N����k��Y��j�/I��gd����$�����z5����>]<�W|.+�n�& '���h����i����}?o���TN�T�>
��DoAJ!��p�='M��_�5�`��{'>����B�y��������gJ��2��x���)����lX-�] ��/�m$�g�:s������a/��]�D�& '�����V�R=7T9����[���M�}D=��fX�I������r�e8x%����'����Q-�x&���#�z>�}���.8�E��#�
�I�������\5���!��/�m$�f�8�l����s��S'*������D6��f=���������@x�?�S����G��-H$49�YJ�^�?����������w��.$���g�����.�v�p��]H�Fs:�[���=b����F6@_��H�B�}���&4vm�Z�Ps:E�))�	��l�O�V�T=;X9���w����g��(��1Pc�
������c��>���������������d�������/&����wn�{w��H^d����D�,Y��6'����w�v�5��lr"�)K�h�l����	�Or�*����g�EoHh�J����s��^�f��^�^{xe�Xf�m�<;@�]H��:bP�|��-5�CtE�"��/�m���r��/6vomNh?R�P$�L} ����fJqkW��/�s��!����J-~S3n����������9a<����i�^�;���X�B�e�Ww!�X�����W����dP�FCF��}]��q�+��}�o#.��
��w
�=qHh�������s��lr"����4�.��%�q��6`Bx�����j���'Eo���FS��>p��gg��?����zf����?ZX�f���e�+��O$�����5��<�	�B�F�j�[G�v0������_��Q��& '��?��Z�����C�k�xp����6��1�ik@��= �s�rqK��Y'�?�^����x���g
�?���_o�7�q��Do�t�Y�B����)��M��6��q���������k���Q��& '���M3mS/�U�=��}GC ��r��vy^�uF�6���0�F��h��E[������c[�?��`����2t���sO��Qv���������4|7�9{�������]�o��4����C�G#�t���1���Bt��G69�MI9Oi��*����wC �C9��z�-��=��Eo� �z�V��<g��Uo��s�k�W>�]H&��^znSN��*7�i<��������b��%��	)����S.����v0��{;��E��)��A69�MY���q�Z��������0!<�;���������m@��RB�~�q���v~��p���;nx���H���K����w����\8�3p`����)�MH��O�����ay�o�9�e`?����kL5d���Q������?po��{~��g��k�]�!z�X�M�eg�����g��?2����^�'��`����n���3��W�[���}i�_T���Z�PtE�u�t�������/ff��*��Mu_��L�i6 =�w�
I�9���c��������P.�.35�M@Nd3�j��a�z�u%���m
����Z��vea��"�^t�P��+4_�\���K����u���B�~���'L�_��xG��������~hW�uS��e�%��(98�y`����>��F�$|0������gPG�TH>���1ubu���/N�����kV��2S��D6����}��������@�#%��z�m��'��Eo��0���H���E������{LF�w!��u��������]H$��;�	?GtA���y�����tL�}`�?�p0��l�+�ep�SA�������&4?���y�����D6��W�U���}���;
9������+���M_�����e�>9�r��zn��C���$cM��FO����h�������D|G��<{6�]Q�T�_��~`���Z���qS���30����v��Ng��Oyx���8�U_�������J��M@Nd3.4[�zi�r����5`<�}�R�Q-��Y��G�F@F�L���U`,\sa��gO����X�\�d�M������?�T�}�\�]H��>���)9��U�QtEa��@I���o~+��w`J���w�g08������>�0*��i�x_�v��cY=@_��PMF��
�[D>��ms�����
�e��	��l6��L�Z��{U9�`����A9|�zv�V�$��(z��Kh��w!�]\�v����x�����	�����]k�����a*	��80;�����N����->��7�-0���������+�������z���������m���&4>����s����� ����f�i��j�d�xg���6��Q�w
�P������$������7�d�8��_���e��?.{2��`�
/������B��.$i��kk�~��`v?������_�V`�f��~%�����-������	�B�NO�]��/��6'�����[t���lr"�����U.Q�T���P��*����1iDB�������m��;g���k��2|h�S=��e��>9�rg����m)�g�v����;Sb�!p�P��g��c�z�<����� ���z������<�������V4��������}�WU��o�~��V���Zm�V����_�me�����ga��7#l#H�{����{�������
r!w$��������s?�>���s^�|>�=�JSN(<u�l�����&B�	k�'()�K����D��Z$�)������s4?��> ���
�4��d������4z�8��z=�$�fC���<�������;l=E��bu���>��>wB��s�2�n@�np�?��/&<�n�:��{
���C>���!dZp��dK���{���?Er�&��1�L��&B�	k�5t�;U����\�x0�y2gU����y�}@f��
����4$\,t����]�}�A��O!�^��O!A�$
���M���&��K������{\�v6�:�p���u�; �TD��Yx�D!�����Sd���l�4��k�X�t��62N�X�����S
�d�"�5-��?�%��� ��> ��"���t�h���ig��m�'�:`����9�<*����Z�]Lw�*���w�Yf
��v�������3�:������-��#���� 4���Z��SW������~��y��izOZZ����_{��_���o����%K***[ss���k�y������{��W&O�1����7v���^z��g�}���w������`}>�2Z8n�-�\��Y����Ppx��8��V"��62N�R��
����XKd~���d�8�f7�������_!��,�_j�}eY���>
����"v���G�!����2R�Snk��^"V��^�?[G|��Zqg�(��������=�C�����}���������<��3�7���?~��o����s�=������_|�E��^~��q��}�����utt|����/W�������O>3f�/��{�����]��gB��m�Cq���X�M0$d�/�v������am"d���6	>�������iD�+�L |�,YL5_�9L��39�(����9��Y�p��k�B���B�I)U�u��w�����p�=���;~�^G|k6��Tgu���g���3�����)S���g?���O���5��uuu���/�y��{����BQ����U�������c�$?�������W*��/FEE=���?�����������z�������H$�>}���3f<���|!d�p�6'DY���^M�	9KfI�=i�	���&B���jS\B��"�W�f����	T�^�;���
��Fakls���)�:o98�o���g�o�SH���+|s�!�(�[
N���
��x����#�����n�{k`fu����\.?q����p����_�\����G��z�����G___��|�I���v��������{���>R������m<o����\�l��"�����A�S�G���X��Hf��H;X�'��M%�f�Su���o����H��'K�R-W@���oAH{l/����2�H���Q;G�,�!��{�,�����L�(��r��2Y���u���y}�f������A�Ar��)V�H8LR�E,T?������������������OH�z�-�����y���Y����S{\�t����G�>����J��/��B�����z���>��\.�����p�r}>�2~8n�4Z$�x�a��6pN8e���1����f"]`m"d�L�6�T�3Y��H��6_ �&R��iV(�L��9�(�T������6�����M��~{����1�i
�V0�
E�RH��H��_��N�W�Q�
h���;_�����9�R�Ce�����W�SGS��tx�M�hJ�lv������_����.
���w����4��Z����;�_����o;{���Ws����H}>�2~8n�(��I�d���0'd�0E�v����L�&B��jS�M�����d�D"�m&��,]N�:����> s� h�iN�V�`{������e��V��?|&�v`]l)�ZN*�"�P�a'����~D��`�/a�k�	��N�tc�e�'�x@C���������m]3��0	kS+�����,��#G�|�#,�7H
���{�9���������7��BBBT�vttT���~x�m>>>�_�����H}>�2~8n�Ef*�FM������c�29X�'��MZ�C�\&Ki�"L�
��5U{�f���l"���r�;
�U���(r����u�G�,X��h�e�����"��7��6�
E��U��r
v��Yp�c�>�0���������NP��:bEnf��vYT���o`l�6��)-���V���{�=��R������������w~���}�
���O��U�V=����z��w55R��"����&C.��p����
��V�2�Jd0X�'c�ME��O��&s��#�H��F�YS�7@T�t����"v�_m����k�~��L�����6�J=}��+�%�I��[c��B��P���
�!�4x���_��?l��g��=���P��4Y�p����5c��,������088X���~8��~����~[SS#
{������N�0A���7o��mkk��h����������o�����|!d�p�6~�[|�k��CB��"����0�Ld`X�'k��gPM����D���@��?��;B�#���"��7G5�\)���|bz�Z���o��'q��\_��5T���i�=���A�a������j�u�o��1��"�A���u����-��fMz���c�����
��V��[���:������0���~W/}>��\�B�(��j�j�i2a�<���N�L7!���(�	�M?���X����`��
���L��!�`Y�7��@&/&+�n��C���a�f���-��k��7�=��������t���*��������y1��x����m�$��{����+s[���8��z�g�+n^�I_��m����AfGHSZ����z��W^y�#]]]�	�X,V���_�J�����������U����0��O�:�����������T�����55R��>���c"���P]E�,�����fI��+�mD!d`���������'J�^|<(��
7qTk�����9�L�����t��@�������n��P�x��o����G���J���t��1��H.��_������K�_���a�T��!9���I��7>8Pr�81������b����c��yi�L�h�2;B��B���Q&�edd�^��7z���O�e�EQ�Abuu�����M�#�m���55R��"����F��%�.��S�	��:����L7
�M����kSZOw��*��Y��j!��	YnC��q�!��,L
�1�1�R���${�`���)��6&��/���P��g�;x�4R�v�K���v�.�����#
�����p~,������u��Y f3����X]����|�G�[4��6��)-Ty���T����y���g��^�5kV���V�R����G�����;;��(��������_J$�G�9}�t��.\�����|!d�p�6ds�����)��	�s�I<���G�����&B���IIhn"�p�,��H���`�H����?Fsb��3�E��;�-�v����s�"���
��]�"f�}�5�����R�R�t���'����<����-��	�����M�M�pJ�������E����j�(/a�ECkS+OHw�����=��>��#��������~|��w
E�w�[�N������^����U���q���Z[[��_����OSS����gBF�m�)2�y;�kZt�]�L�t�62N:����n�GUl 2��������ut�+H*��7�������2���g��}�|��
��/����7�-�M��t�����G.��(��Gx�.M���&��8��=��B�M���yf�
����9Kg3�������'��mmm�=�������4MC��M6o��z���3A�oS����>S��|�r�L�������y��_��555}�]P��K/������b����zq��}o�J�z���i�Y��)�q�)�L*
�R]h�	��e�L71k!�4��$�4'��?N|K$��E<��Y8�j����@���C��T���/���xlj�j�Z�9��b�[xcR5���?������Am
d�B�Ap]g�{^1L0x��paxX��#~�� �0���C�4����:3��!���T�v��������)\�+����������Uox���F�=r���7�?`UUU��To{��wU�~��g\]]����Q���>�����F~������=}[&���h�Y��)�q{�Q]��k�X3����(�q�bw3�L�0�M����jS\N��&�m��O��@��b������
2m�����l�2��ig��[68�o���}9�}j"X�b���O�<{���
�# �2�m��3��o`k�������U�:��P������z������1MX�O5g���i��m�7�����=��W_��/��[o������<~����
6�������9r���}����5v��_|�����������f$�����!S���pR���4����i�/(�L7�M���OjS�Hw�R5{��ID�o��@�;��;���M���4l�JqnW�gu���k�c���]�[<8/b���sw��S�r;$,��e`x�,�Z���bN���p�+8���������u���:��L����_j��Y�ts�
�&B����,*�k�XSN���Y�=�_y����D�)��3����!������@��U������NA�U��iH8W��!�nr�J���o�m�&;\.r�lJ�����o���s�V�M��;z\��/`��ZG��0^��8��<�)$\�{kz�����R�L�hH`m"��i�q{H�|���M��S�	���;A����;��&BF������Y4�Hy[�x0�M�h6�x��%%e�'��5���[2o�z�J=='l�n������8�����*dUJ�[f�g��*(��K���O�
��x��p���u���!���Bg�]5+�K�� LM���YB����D!S���!����j�L��o%y�J��L7/�M��AIh^2��D�,$�>�.��_2��T������	2j|�(����*�.����]�|�.��~(��������.�=BK9{�����}������[��.���=���A�>�p��D�
�2,Z*a���w���������&B��
N����]�)'�n��'�0�Fd�66� �j�J�Yk'�VP-�iA&��@�KN*�8�A�qg�o�K8�u�
����!�lSN^-���V/�gfx���BMd����pg>��\�$<�V�:����^��R>���\��������[d`fX�!d�p�6Z&��=�,�NSN(8����b���d`m"4�DEt�U����B�xP�Nw����g}1>�
�Q���q��sg��Y�u�'�/��?t:�%�.��]-#�9hOg�g��J(
�������U/�������>�����P}2>�}7�Y�h�Y���]�!dyp����.�r�5}��!��\/�u����n&21X����������9c���%�)��E���_��R������2;
�+��d]Z�S�e�_z�_�Cu�qTGS��n�$��P)_=�/�K=��c�z���?l����SC���#�$��&"A��o(�n�!�Fm"��/���,����i2!�z�,48�k!���._�f�7�H���O'y�,�N����0P>���M$#�%������y.6��&�/�m��w�v�8:�x�6�7
1�1��P^�z���6����������_����0��z��<�f����c���M(r�g���M�BO���nd�!��5����[��������v��4+��;BXI�k&�B�O�j��� o~��`mZ�zAKts�����)'g���-�:`���#g�o���rj����n�'&+��B�����;[���&�}N�h�����9N��~�q�lc�x;7<|0��i��L����'B���B�yb���9��Z�]p$�qz2�M���������,�C���]<��"�;���Iwz��V����4{]RNZ{����CFn�-��`i�.��+U!Y��|���nY���P	�r �����.����7�:������B@��M~������=ut������[dx�D!���� ��5���5M&d/�.�r��b�����&B��$4/�jr"Kih�?Of��*7���@\�O+�6�����+�j�O��\w�+�e���s�6�J=}��;�%�Y��t�,��+���	�~�����p���7ZG�6\�
�����P�-� ����I���� �K�n���!�L��O%O��m]�)'�m^)O�e���am"�-�����d�5����/&��IV��[o����M��4u������+E��OLY�[689p��D�s�!
	�:�����B;��$���&�6
�}`�u���3�o$]��\G��k���^�Kg3���'B��5�%b��{�LM9��� Y_�t3����DJTD��P���/��3>&�VP-Wh����iZ:%���<�r���G���
��]�<f���k��a�]�\Vl��^�4fC��<�+��X8��a��=�����B=������l���!�w�����!dZp�~��.�t�e5v���5k���5��a����am"K!��;<��md�"~�v�`�d�"����%5L��cm31!-`���D����2v�x�%�����o��v���7�5�U��t��~R��.�M�q������|���������#�u����w�����-ML�H/x�D!���v��l�~[M�	9�����n#�X��l��._�f�7�H��v�`�������4'H#���4*��������n��������
N
Z�)����{a
���z���t��BK�{��^�v��~V�A6��8|7f��-$_Q�#��f����p�����nX�ts��gO�2-8n���rV������*���n#�,X��|(�iV(Uw�,�"�^�.L~�,�A����pP�����&��%�Im9.e������o�-���:f�C��WuD^w�H9L�R�!uWCi(�;��Z�8�0K��������� �P�:���j������$�@o�[�;<{"��i��q��q����f=��c���K��N�VD���D��������,�C���]<�8���L���@��tO��9lDJI^w�Wu�C��u��q��u��El��~�v�_r[N����n!-���O%N����t�<|����$����SP����(��(��]p�oB�Luo<{"��i��q���8�4���p�������n&�\[��$Q��L59�%����~C�~EU��;�@Z�tO�ks�T���/���xlj�j��A�`�-I����#�k��L�	iC.R?$�
���y�m�?�o0x�=�����<b\G�L
-���N��I����t�t�gO�2-8n��by�Wj�	y[�����n#B�X�����,��
YfMd|�]<�<�=���B��q9��������:[�n���I;�}�f����~KV�8�{��&��U!&�Lw
ZG9�������}���.���8���V(	��J�{��a(r3�����"�n�.���B��r�mZ,�x��L��
O&�k�n&B?���D&CTD��P���/��U�e}NV���n����n�kS7�(���AU���������]�[<� ��`���i�y�R���=�	*c�O	��W���?��|N�S��`�Q�}�~$����'�B�Y��p=��I���t�����B���m��U������7'���������n&B?a	������������9c������e�T�Z��t7ks�������N���N\�[68#d�m�������R��L�	
��
������������`���������J��oAm2;���X��,�>k�����n���6B������������i2!w�BYd�mDh`�]��H��._�f�7�H��v�`�_��ET�9���9?dks@���������RO���[68�������n��F�+����n��i+����ep�?��e}��Co��?�����d�i�"�Pd�dQ!�odT�9L�H;X�!dZ�s�V�e��y�rB����B��52/�Y���(�iV(Uw�,�"�^�.L�#Y��p���)`�'�kS�#�gu{T��e]Y�k����/��/��q(��������n)��n�'b�������(��$u��g0��eu���L6�@[�A����o����d�;
�r�[��M�2-f6nS���
k���;Nt�,���t3z:3�Md,>�����9D������o��3�z;�J��/�kSN*J95Auqg�o�K8�u�
���]�=��Z�����A+��B�	;�~�oA�N����7�}N|�^��O�H�>�C���V(�TG[���}�6��NL�HX�!dZ�f�&j���k�L�^<S������n&B�e6��FIh^2��D�,$�>�.LI�O�j��� oa�'��j�Q����\��#����
�e��V��?|&�v`]l)�ZN*���B�~DH���B�.R?:d��f�G�W��h�|E�pn�pv�*Y2��{�{��d�����B���myBw�����gk�HMd��i�j1�dQ-W�2k"�c�������_Q���N/�j�]��0��d���n�A�3/-�����|��Q>�D�:�u��28���-�g���J(	��3�`
\��o0��58?<VB�)(��r�{h���#�6���t8���n�`am"��i1�q�	%\���4��B��d#��"Se��� *��\��uD�����#���T���
�����S�M)/fW������eh��2�����+���R����&!n�a|x�P)��o8[����
����w�C�!���������L�Bz*����-����-�M�2-�8n�-M�s'���0$d��,�w����d�L�6���T��T�62g?B��0�s�b�vD�Lw�$�\m�Z������M993d�n�������:����sk���)�� �
B���p�S���������t����:&�\�"������?��#�[�tX�!dZLk�Vd���l�4��k�H�t2��M4�d�t�/U����D$��]<��	YfM�\�YLw�ymvI9i��w+e\X�]�lp���e�������
��,(�q
��j/�B�9	�+�i��o0x��p�+�\�NP
��L�P/F^�
g���7A�3�����D!�b��B.
����ASN�?�SY��t+2$��M4t��4+��;BXI�k���,YL5��y)@I����1����BV�_m�c���q&�-�-��yw�����	�Y-�������Q�t	|6���p�}��]��3_��%y�����R�;i`FU�
������4���=�&B�#�)v���%�w^t<c���9����f"dxF^���>�����9D������"��iN�B�{b����Z~SdS��"�������
N	\�1��|�����Jn=S}A?!bA]*d���=pk68|���7�����>����������p��'�����n���R�.�[�$X�!dZ�v�&����j�L�Y2K��I�����1��DCIh^2��D�,$���.L~�,�I����Pr���e�����R�r����O?7/b�n��X�E+b���\����.*���x��R
����}�������v��o0x���
�l��������;�<{"�AK%�9����x;70��'��D!�b���<.��~�����c�"=��6"4���6��hA�r�,�&2>�.LI�O�j��� oe�m�jS����}j"r����7�o�n��������\�|��r��F=��"t�@i$�Sox�+�&�z�{G��+t_�'��O��!�����(2���(�b�n�FX�!dZ�g��EB����i��SF	�#��n&B��xj�ETD��P���/��~C�M��w��� �c��!�f5�1�1�b���${��5�e���>�:��P��aHG�v�I���C�@�c�n^����s�;��
� 0�Ic�gOdiG�<\�<k-6��Ram"��i1�q�ln:�wO=`N��a���-�3�H���1�&�����p����9c��Z���#���T�V��
$Lwi�sm�����r\�|��;�
��[68�o����'r���D���J|�
Cbh��;���?`�������V��
R�AU�Z���I��'�4���1���I�x��
k!�L���"3��s��E��uK�1�L�
!f�5���5�]�T�2o���v���*��m. *d�h�Y�B�8����:�>�����c}�����?���r����	k:��Y��{
����ca���������wJ������<{"$���,�g�E��D!����-�K�|8��h�	Gw+K��Y4��2^�n�B�!������3>!�VR-WiA6��@:�6����[��p��uS����+u\Vl�5��R�{Dcr����Y<n3T�B���W���w�
w���	�!��>��<P���!�gOd�x[�<\��p��n��=
k!�L�0���[�|�5c��!��u�oU��� d�����|�C58�Es�������J�,�������1��@U�i������������&;�Y�[68�o�����7�j�
Y�B�t�,��
�uB����p�c�}N�l��_��L�	�7�&	��Lw����Y&�����N�k��n���6B�����,)��i2!g�i���!��5�(	�K������D������"��R��47H!�=A &�������s������B�lP������2.��Lk���r����i+�_�r��p�?��e}�������k=$���p`�2�C��gOd�$^n�o�����k!�L�0��������rB��
���!mB����-��Z��e�D�������'gR��hv(1�1yB���U�_s6�����S�V��
�Yg�r�j�����z>�b���</����5z[�`p�o����mD�C��1�C��=�%��,z8�z���	�M�2-C7n������)��SG�����C�����r�"����XGd}�]<��*�?��=Hw����n �����R�����k�`�s68)`�M��Sy��kc���2g�a��@�-�7���
m�����9�2]�>�l�;���gOd�����7\�;L��!�M�2-C1n����3����0'd���:s�"\�����5��I*�w�j�3���E<���7���Mwz����n ��e���b�������������A��'=���6*��\�1�9��BK>�yB�Q��N;_�7<�'�:|7C�e��n��D���'�p�����y�-�2�am"��i1����H��X�i�1w�2y\���!���T k��|��=d�$"�%-���d��j+���
���t�%�dv��
����2v�W��t��
���t�\�kP]�wjPjv���]UPqg��.���o��{
�����E�Q�t����'B��3�mX�ts~���B�� �6-�J�=9Kfi�	v{��b�4!��T�Pv����Y`E$������/���t��pG2��!a����W�e]Y�g������B7�&��T���P��}dM1����Z�:R������?�n������C���� ����+!eQ~�1Y�?�-R��D!����Muu���c�?`H������%��m�#d!��jP>�����9D�������e+��k� ��n ������r�V���4z��E:g�s�6�L=u��~dSJ���_����� �
B��y��l^�l��}u��R�Cu����$bV(B*�������R\��_��D!�����,���i2!g���`_P�����FIh^��D�,$���.L�+Y��j:O�S��2���&a{bk��r��E���@�lp^���igo�z�4����uh��:���bN��5�
{_�7<�&\��^�����]�t���
EH��Xs&�����oc�EX�!dbt�eQ�\�E�rB��M���!j-B������,��
YfMd|�]<��.Y<�j<Es���'+��Ak\K��2�}���G����Y�(r����.e�	�Y�B�L9���*���
��W&��?���
���.�;�����SNz�P�z�S��������m�&B�����4�'�w�����s�i���N�S�2u}M%*��\��uD�������'������HPr���Z~sLs����ig��o�9��hY��#Y��V$����:���]��D,�O��;�n���`���f����� h7d�@m
�p�#�P����o{�y�dZ���X�!dZ3n��u�SG5M&d���<p�E8o!C��k*I%��NUm#s��#���^%��R���� ��fe&�����r�����Ss�6��
��[b��X�U������N	k��`Y���Ak!�{C�q����v��o0x�m��
�l���P	�z�;���eU(BODq�����9�`c�6B��<y�V�&�lm4����+�	���Z�,��_S��._�f�7�HxI�x0�%�G���t�H1d0jrRQ��kL�\�n�rrV�F���I+��<�{��:,���%�2�/s�MV-��A�9�Z�&��?��y���}
�����"�g����da�o��E�L�k!�L���6-�J�����
��'j�i0B������4+��;BXI�k����CUm�;�AR�t7�FRBV��	iH�XxoK����u:g��W�K8r*��oMT^w_������Im
:�&	�n@��>��E�`��Wp�p�B�C�=h����N"Kd&������y�(l��3�J�M�2-���Tg���k��CB��I�[�)��#d!L���������,�C������d�����t�m1�
40�RR��
��u*p��x�*�F�lP�Y�T�	��)dU���;��W�
14�B�}?���?`����������VH�
Uq�ka�����*�!Fu�������H3�6B�������|����&r���B�A�����@�wMEIh^��D�,$�����$������k� ��n���V�_m������N
Z�s683d��d����BJ95RB�t��f���Y�A{����ca���������:�����#d���Bb���k�;;����X�!dZT�v��+\���rB��-��L�����1�k*Z�E�\!��������?$K�P�h~*PR���~�+�u���D����6�����:g�s�6�Hq�R���T����
�;gFT��f��U�������w�=}���/����B�,�����
c����#��B2&�y�����`m"����y\���3'�N-t�'[��n&B�H��D�t�U����\�x0�]�x�x��&��P7"l/����:�!��������
�
��;�������Z���>��M�@�`�]���.?�w���������w,�	�7�{
:��S
#={"�4���������07k!���X'<s�{��sB��o%��h�q�*���1�k*I%��NUm#s��#����@~G������0�
��.)'����*�x�����&�-�-��{��������*��k�h�2���3��^�~�p��/W?Sx�+����~���:H8e��g#d��������������h�o��D!c��H��X�i�1w��<!��6"�����5�]�T�2o"����`�kd�4���
E-G�i�t����U�e]Y�g��b����>�D�:�y���?�-�Ed���\��z(������.
���7��[8�o��"�C�7����6�DHg�H ��\�^8�����u�p~9�&B#�L��Y:[SN(8���,c�������J�M�B��#d�����`�Kd�D�f�����h*z�VQgr[��������F���H�lp���1{����U����K����q��6�]P�.�n���
�=�[s x/d���4�
�]�L&=��(��=�,<p��k!��
��%r>��1a�������c
�c�n&B�QCxME�iN��@�&R��"��5�3���Fwx������������Y.e�2�/��1�g�n��D�e�b8�8?�
��,������Tm*���y�aw��/`�o����N���t*���8,�E��`"����7����1������6B�H(K
Gwk�L�Y��,��r�2N��MJB���&'�d!���VO'!��EUl��n���0�A:����d�,����4?�V��L\�6��c�M�����R���t�L���Q�Aw���a���{G��(�����P����!��W�=-��L~�������^�M�b�<6��~�����{�";���8n#d���MZ�E�\!������{xq�gd�*�����;H+�������%�����
��s68-h��D�����kc
YB��������������s-\�d�m������<=9���
r|�B��+[��J����P��<_���BL����m�����SG����G.����q��6E�t�U����\�x0�C�t)�|����OC`@�!�)�j�������m�9��nK�����A�q%�j1!e�g&������k��?T�g�>8�����	���Q"d	��������p=����x��P���B��ln:�wO=`N��;M�q�
�,���������p����9c��Z����������47H��4�����[��x���6��w�t�g�n�M9y��=�1IuL�����)�[Jl�`���pqx�@�Y(	��*�;��E�+[����YVc�nU��C��X�!4�Yi�]5-:��_&��x�p�F�8
P��&�����K�M$~�E<��{��;���fG�e�C�HB�J9����
�mI���N�l���-�RO_+~��R���[���� ��z���_��? ��2����i&v�����O9A1�l$Y��;GeQ��~�&B
�\��Y����Ppt���h0G�q!��*���D�M�'g�oh&�FL����`Pt1�K!VJ����u�N���Y���
������t��;�%�^��t�LV{)��AOu0x�-�{^�;�������	��'B�!��Eh���?\��p��~�&B
)��-�q�5��CB��	"��T������F5�'K����"L�-�7���Cw�����NX�BT�*���>�{}��)��tG�,X��`����~��YM�v�{f���A��;���-}$��&B�+��#[���K�o]����D�!B����4���t�4�dZ?��m�&*��\���D�?���M����l���~hC�+�v�z�D8����?�M��n��8�������|�"0�=�M�3?�7K����/��`������O�1��M��V(BZ�x��SI6�
�am"������Wh�	y;����{�n�z�����E��'���"!��U��nsQ!�}0s,7����:�!��������
~��le�����<�B2:
;�l�{fj�Kz��S=��C�n���`������y!c����8���{o�h��k!��
$\����	����#�����
9�K�#�z;��["����������ET�y���t�Y����Q�Qr<����}����
~��&����^�9]%l�����L������{���"|��`Pn����y!c����������Ro����M����(<w�{��sB��S$�n��A��m�����d���,Y@�����I^'�S�v4;� 'ks(�K�����*��f]^�g��b����A��'=���W��].P ��C��	���y	��M��V(B:];��~s�h����_���B�P�d��l����k�Hj�o�q!�P�7��5D�g�l?��;���Iwz?�t�M�hu$��������$j�h���e���lN:~��5�.��]%VJ���)P���X�8����
�{M�/W��^Ck!c���.�r������������B���e!����rB�������f������|@U��9c��Zm?HV���n���	����A��-�5����@��E�;F�,�-�.t����B�8�2R�t������_O0�JxsH�A����bm"d��B���f����,2�����D!�P�n����I�����EW�R��C��,%�f�Ru����D�H-���?�%��s4?��>�k���-q-7K���;����[0��oN��������lJ��50�-����7<��3X0xn�:��W�-��k!c������G���Oq
�t6�M�$��L`@�dB���R���t������F���%Q�����D���~�5�����#�����X����7E7�9�x�J=�C����y�����Q���V�of�[�M
A0�zO0��'�6�`p@X�3�P�tF�E�'�����X�!�T��X�&kM9!o�Ej��5�m�����T�3Y����X��M����w��^ �7HK,�6+y���W���Hq��I�`p���E�;d�w)�Mh�j~�n�����A���`p�C����|���D��a�"�yBL�;SEF������B��b������[M9���a��r�[��6�t�*�����Bf�"���f���G���[o��p(�e9�)#�������KE���'���[68�w�����3/��Hn�iu2�3c��Bk�:�>���5X0x~LO0�`6���,�62EX����s����s&j��&B=�lm]p��3������:SC�1x8n#��������d�7D��Z�����%�&'���t��i��)!d��������6'�OY�[68�o�u��c�W=*��;
:%,�{f�g�`Pu��c��Z��q08 s�M��V(Bz�X],��}����'
rX�M��O�����M�dB����� f[��62����S
'��9D�[Zn?hE������s���6EJI�2�.�)���D;��5�e��V��;��s��:,���%�q7Hs�c0��Z>TVup�W(�<*7r�Q��+�P��'
���J���L�M��%����)'������f��j8n#�D���+d�r"�o�l?8��KUo�;=AZ�lL�6
Q~w�_m��<��	G���-��r]��Sy�|k�����
�=32
�z:_��zj�:c�`p,�Oe������
E� ��?���t����DY8���qf��z�E�VcEO��F�N������w��Md����U�e|J���Zo����>����&G���*���p��i����e�V�6�������*EJZ��t��`��:t_���n�`���`peO0����V��6�dX�����6V|�����DY,��Rp�������%^n���f����L������j��y������~�]�x>�t��%���:3��d��Y����a9��bL�_�[683d��d����BJ95B�t������������`���A=[m"���
E�P$n�����
z����DY yr<o�jM9!w��<)��6j��62����P
�d�wD����~�U�`Uw�f�
���:c�6;%������c�W�c���[�[68'l���+E��I��z9�`�G�E!����`�^����	��&B�+!�X�{xWk�H�Cam"�,-K}<��fj�	���2���8n#cF�3���d�"�/Zn?8����;����N�h8k�M����w�"�h��e�{��.�-��uw���%���i����i���1��	���� <��:��J�a08�����1�
E��������R��:
k!d	��V��3�o�
�9��I�[�)v7����q��mw���D��Zn?�	Y��j��|��`CW�-�����r�C�G���P�`�K��"m����U���� h�����`0��:te�`p|O0��c0�,<o"d��B2,�U����SGSm�k!d�������5M&�X�����\�t3���6b������jv��_	/j������yT����>�P��(lKh�r)���~na��Q>t�G�,\��P�E�r����Q��
3mr4�
K0��:<o"d��B20��=wZ�
/o�����2W������rB�����t�����p#�4;���#�I��"LI�O����PP�������6�����7J������M�����,��c�u��2(�=�]b3��Jo0���������� <���`puO0����	��&B�+!�S�f����E��p�M����y\��u������F�� ��n��p�FC����T��Y��H��6�>O�������AZ�t7��`j������\��+���[t�'�/[{�!��AUhVgQ��dcx�`0�'<�~i�`��u0{J��`0h�����1�
Eh(O~����������6Bf���:�4��=�Jr��
�n��p�FCBTH��"�m��������e+�Vg�1��=^����������mSN�
��[6�M��M��Sy���#r�J�2Sd�L�X08�`���5�`�(@"���M��V(BC��Y�&=|�����k!d��<[M9!w�2y|�m4��aH��NO�z�3�����`����T�is�~PgQ�q���.���~N�5���VoH�;���6��U!T���z����`��R���`�2�y!c���Q���)V�fj�q�M����������4����DY1��40�����F�!���W��~�2
U{�f����7��G��v�zV���\[�w��"��!�6'��/�TW�����\��r��`��:<���_���{��R������M��V(BC��s���vs��n��Y�M��)�:�EW�X���fL_�@uw1��!��6,JB����3d�<"�]���EUm�;<@R�t7���T�rj�������O8:9p�������)'/��5&Up�T�d�[�K&�	���K����WzKz�����@������1�
Eh�P�.�����d��S��,�&B��(����vj�L�Y6G�2s���m�$�|��:Y����D���N�YS-�h!��K�N����\�i�|bf�z�A�`�-I�W�<��*y�Lwhxa0��	�72fX�
)i�w��e�|�;�`m"�L�,:�k�XSN���^���t����'$�t�}�j�3��^���!��O�� -rs�~:%�����3.,���!������;"��j�
Y����f�24f��G{��,�4Q��Q�eL��0<o"d��Bj�
���Y:{����D9Z������~��9��Q�3���:��9|p��t�n�L�"����h����d�d��������H)��.���p���2v�8�%�f�_z�_��p�%������n),�6{��u0xw�:���!���{���=�`�����62eX�
5��������`>���2Zdc�����)��	�?L����|��9�p��8���&P��d�D�;Z�/&���*��� �b�L����4$�+p��h7%p�n[�L=u��3�9�Q�:���UmJ�?��G����
M0X�t?�E0��D��`�"4$�n���&�>�k!d����5-:��,�E�1�F���m	hA�r�,[A�������>����Lw�1������]��q�{������Snz��)��t���i�����1�Lq�����eY��[`�33333�
V�a��������xA��t����(��3{���������������\?v����[w�_�Y���V;����HfjmJ�`����o��A��fjm"47`�"4=�7�����_��X�!�(2"����g��clU����^�g'�^����E�2,��)_�Bh�&��?!�4d0H�����GX��M<�B�jC���C�nJ>q��������j
c�i���0����������������(�����Dh�
Ehzpu����&��}��cm"��@�p��Z���!�j�k�7��>���x��%�q(\h9�����?g@<��_���rF�fP�iL7-K��������mK9�z�#\w�T�M�����������j���)�=��a�`0����=O����j!���B�6�7>��=�%A�y��X�!y�5�����0����d�=�$����u{�������*_�>�������O���A�iL�������
�}���Gn7"\�c�����YM�S7T�j��`������� ��{!%�
Eh��~V�W�����������X�!��)�#�6>-'=�����{�J���D�]|�.�wn?�{�f���$j�������K�.p�	:�{cy�>#���C7lO=cU���X�j�r��
~:jS����"?)���|������.}0�� �e�{!%�
Eh:1%�����$�_bm"���8�!���+�=-'�:��5�=L�����ik�>o�~7W���/��}��RN�;��������
Q��'{1x����A��&�(������/$�e���kS
�����Z��l���;R0�n+��s�iU4��&BJ���4�\=���_��5c���&Bh��]�7��{i��	����vGG����u[Y�Nq0Th>��������K�ZN�Csd�A��*T
�-I�K�?J=�f�F#\��H��K����������o�������>\���� B����)V(B�L������i#��g'�3�M��4`
s���y�����P�Qr�q������1Q�(�]�+�pY?4p��

{�>_ ��J������L����3�,��aD6�N��]��o���lK�n�yF�9}�g��	����!�A��`�&�A����)V(B��N���8SR���`m"��M�Q!��V<-';s�-/�{�3^���8�+t����q���������B���)�{S�gb ����6�d��q���_Y�1���"�{�1���f����lmR��=�����p��p��� B��7R2�P�d1zt�'���+��~���6BSAPi�TK��|���W&��>e�"�)��=&��^O��c��o���Y?�+�	�W�������RS��U����6&)�C#���������
��)������}��a�=w����p�E8�3=1�����[�'��$B3~o"�dX��BP
>�E����g�k!d^\C�����=L��p1|W�j�����)A��AB�Q��5.���l?�-��-���8��
�I��R7��&[�z�H�x+|�������e^������l��{N&P�B]<d�I9���`�S3�~)��{��`,��~o"�dX������Ou�������2:=id�����������r�q6���y���:Nh���/�2�o�����'4��|@['�4�J�XgBg�S���,���;��_��-�������
U��#���Q4���	y�q������'t~O
3��`p�I�I"4���&BJ����Fv��������WX�!�����z�������g�f�Y�l��m$�G��N�z
��+��-_�A�r5��<�j3{�=kCN����?`D6�;>L8l�o�S��W6H�='���Q�w!������_��WM
-����1�O"$��DH��B�����/w�������2��1q�����&
	U���z:�j��9��u���B�_��+�_��1_�Th�"'��{f6�LV�k��\t{S��WB��
.��u8��v�����v�\��W���l�[���p�{��'�;q��*���d	��W��c@M��DH��B������_�|w�����2S�?vb��&����	�{��^�?�"���/si_5d��o��o
�'��0�����9�<S3���jS��+��;�[��u������W��N�p��5���!�mP����_�w���L
Uz���j��q�]��DJ�h����2am"�dX��nx���������?��D������-+�����������������EU��z�/��e|���!����A[+�4��U�����\p(����]Fd�/�1���"�������1fB�9=��h��<�8nK�����������b?�n������9�&B������a�"$;�����dD`m"�����z:���5yN8���[���.��9'���6�G2�k�j%��s������5��.{q,_�i�M?���-��;�ku�!��� n��\�����������l-t�@I������������`m�Z�\�M��
k!%�
EH	&������W� �&B��q
��+g��0�z������9��|s��-�������\�
�~�G|����8�4;�g��C5�MqW�]�$�z5d�������e^������lm�{N����" �:l�[�������O�����W�<z�L��M�f�M��+!%IB�r�'?�G����D=
��2�o��r��=���$��8���6�(����E/�C���	q0�N��a*�g�FZ���n�{����n�V#���B�oK9cY���P��������"�P���������0y�����?��J�9E��^��D�s�6���6R2�P��))x��~uD(�&B�q�v��{��,|��\>����9d��yO��C�B���.��n?�w�~��{�5rO�T�����<���G�����1nY��	������������nJ>>-���	����}��8�%��|\A�a�q��t�������Dh���DH��BR��S���o9k!���5ag5���ICB��7�n�������f�=?!�
�����\�����|�:��N��{& ��}�>��v&6.\��P�5������6���93t�B�=��>k���p����goB�NH���Xj�w���6�u�6R2�P��C���������X�!��h����=L8�q9%�0�d��S��B������������W,�.��D������&X�l�.�9���uk���B��
��yg��e^�)5�M4��=�����HH����`�*�������o����o#$^��`��VqW��[��nX�)V(B�B%�bZ����"���zZN8ztS�#����I�T�:��Gh������K������@u�=
#5������*���qi^�v#����?��t�b��ct�@�0���t��!�	B���<��KS��C_�?��}
}�=HEN�	3�6�K�6R2�P��f����7�^w�k�9HVk�����i9���+|G���D�P�=�-�	�'��7��o�������b�h����1:�{S���j��X/��k���q�N������vO��=�'L��-
�@�I�XW���������z�oCc*�*x1�Qtm"4�am"�dX�)�0��w�am"4�p�
K�����������ff<�37)���k��d��
_����������^+t��r���������r���s������lp~��}���*|c�3F��$t�CY $\��p�����L�f��`����nBM6�=I3SVm"���DH��B����V�[��n����j�����R�~>�Y�����w������p���tJ��cD_L�{*q,O���k�s��1,��_�Hh�(�f���Z��P���$Z��oO=�F�F#��WC�oM9mY��_6T�e	���������p�#�{
����m����H�eA�S!���������&BJ���qhF	�oTlj{��6>��O�������'�uIel�i�(�"�:@��!���k��������o\���+�	k�YO�j'�l��j�c���#zV2�Si��^/�~W�w������%�MG�� ���u��im��������yeA�G�-+^�p�l��w]XN_���{N��tAC
d;C��=.���m�,��+ �xC[h�rOR�{!e��DH��B���p0F����>$��
e�|n�R�E�q���o6����%0���s!��{�>r����XaG,�������-
�B�f9*)V���'CB���&n�
}rf:���q0Xh:�����������|��b�'LTM� ��k�/����&�D����}�e�K�w���\�������{NzZ���xK9��
)�;�eS����2��R���"e������2am"�dX�h���0�;TB}�P���5��5\l9R��e��i�}cM_�N�����y�n��%�3�p�l��Dh����G�o{2'^��I%-�D�lJ���Q� �]��q�?0p�����?:m��(3l
�����J����������[��?N;w��+�5�Z�D����bIi�oY����w��
��s���(�J����B�:JZ��>��AH��6R2�P$�O���GY_���/g��o����o�
�s<3Koj�8�]�]^�����@�r8}#�vJf"�j�6�}�����'ib�v	��)���I�sO%P�h��i�W������~�/_��~0�s�i
U�nkI�^��#����MFd�/���t�b��ct�@���yVCMR����R��7��!&���%�1�]���>t���m�� �LX�)V(2�C�b�Zl�*:��f>�������Y�\�#�qHd�c��a��@����'���XeO,��?�3o��z��/���`���b6�����[��.��_�U���t��Dh����T���lT���Zo��������D�������
�b���_�K^����@*�u���:�;�+����0j�q�����;�{��&(���kB�������9.v\��_�a�����!�$���\�P���3�S!�LX�)V���A5!v�M�Be�P��g�q�\x1��zf0NI��X�R8}:�:t���Env%V;KfW���F�����B�&x��:H��lC;&1����������^�4���R���U�����k���km����G
����{�2��d�8p_h:����}�������{=`�r�'d��`fO�gm����+��
����7��]�oL{z��|q(9��P��������������A�~�r��d��mvs�S!�LX�)V��C0�~��U=�����J.��
�c�2�d)��A����]R�G�q ����{M���\������Fb�'y��<H]������{:s7�
-b�*��Z.������N�84.�����$X�������k�,=^�����{t��>�����X��<_>����a�`����5B�Mq4[���1EU�1��6&�x9d����������Z��_:T;����'KAo%�C���6����6y������R��*�e�����T)�&BJ�:�H�'���e@���Z��>���(a���w2�d�&��A�	��S���[��5��2[�{V�gt�����
��Y�/y�>u!������4�/�
)bc���Z.��/������8�5sf��M�f*6\���'�>nr
���]�B�:n��+������w���B�yQ���s���������e^;������GW�:���.,�����c��P3��B�-��7��OL
�~��>k!�����R`�i����
!e��DH��B
B�0��F��A��[(i����*.���g����)�m}5�>L
��x�[���N�����Y��-����#�;y��|��������.�qKc����B6��K��r���v��Wh��P�g:�M�f4��~������������=�$_��������"4��*�<&�2�����\p(�rI�N�����;u���E;st/8�s���t�q�����.=oj0x�Kp���"�C�'�d���tO
=��BH��6R�9U�������G��5�I�\TX��d�.��m<mI[�HY�^or����-�E��.Fg�C7���9�=��>��{���2��O��2��T�F�q��\N#_����
mCB��8F���)�s�6�MD����+�,=�p1S�'���Y�b�����/z��xP�~�����w���{��Ge���;�g�*��q���a�v�YX�z��&W�In�PS�(�"?�9^�����WM�������}���I0�1}�A&�{*��	k!%�A�p0F@���6$��
��|N#�R�E�qA�o6�������E��B�c���>�vr����-��?�3o������N��&�P��e$mO��HY_`U�%Us��|I_�#�
}���V�X�?E��fPm"�>AE�������p�K����CC�@w��aB�)��-.�[n?�K�j��i#�f���G�5�D�`����+��7'�|��-_^�>���BG�����J55:}����H�������p�;�����^��m�r�"��n�����S!�LX�)�tV����1�C%��
e�|^�Z���q!��_6����%0V���P��=j�/��������X8���yV��m���n�o��?u6��I���o�0�YL`>Y�%Uq�
|q+_�-e}�#���9����������X7���3����G������D��
_�������~�����X�l?H�L�pKd[���;��/����G���=�c�V��]�9�7M�W�@m����]��X����~��
�?���P]%�h�i.h�=B������={�jH��*��O(������Z.��)b�rX�4�>Q��.�R'�S|������J;b�
�3:s�Yi����q$���������3A���&�vNf�d2����6������Z��n�y@��'D����*����L!-=�q	��%�������\����t��F3�!4��j�{&�i���roW�;�m�4f�q��{��d\�U����0�6���As��A�p]�~cj0�;����B�1����,���{*��	k!�x���gDl�*;�|}���z3��'�uNfn��������������%6���&b�y�.u:��MY7q�$�+�	�e����
.��+l�+����U�����Cs~{"4#����%oL����C���g6Q!���u;����� _����O��m����*����>�l����C�e������|�j�K`S|�P�;�]}�q�(���kwV��_���L
������=�au	����)�j!�$�M��k����>��OGV�P������{:c��\�z��c�r�+��~�$~���N=����)�{��4������q�������)W_3�m�$K�-���c�#���{B�!��.���%�����	=.��g/����`����������[SN����xpU���y�w���{K�	����*� ��o����wM�f�{p�e��
�VP.�>B���R&�M��D�0<!vK��Ut
��^}���|�N&����b}���}�v�-����{V��u��m�+���.����?�d �����!��Hg����El\�^��7�����/t���qqb��!�����b��#�V��	��-���
���(���/{���O��������B��8����I���]?���n[��'��{���E|0����?�3�e�k
��n��������szGz���`�����_�{
���b�,zb
��f��BH��6�,�!����BM�P��g���\�~?�4�?�e$}6�:t���Ent������nhu��p���I�%O��.�RV��}"�����R���s��\^3_����	*qP#j����=R&2��j�k��
��D���{h�1��8�*�_�+Wp�?5,��	_�Lh�"'7���i��v�xOjw�k���9����c\6�f��i�K=�Z����$75�V�����G�m��C���^���R������uo��Q��
!e��D
��A5.v���e�|N#�T�E��y�W&����K�1}���n�Gb�M��;��%6�5R��=���J7��wz��uK[���sH�x����Wh��1N�	���=R���)K����c%5B�_�����a�`��e�	-g��H`�����Ar8����>���~m���V�
��f]����w�
�+�����y*zBz���_z��{�������Z������au��j5�����T)�&����7*�U]Ba�^�o�[��f�.��m}9�>H����XaG��.|g���Zz�o�����QW#i�x�5��������2�
yk���A������
EH��6RaX����t�1[V$���0m��{G������x0��|��B�aq��-��A�m-K��������mK9�z��|?v��k��������>s��S���f��V����^�6	41<���"��I�P
}��3B���R&�M���4��*��W�����'Vq�%l@.������;��������F�q ����q�{M��V�����N������������d���2.���k��k���PO�k�s���2am"�d��j�dK������C��AB�1��u.��%����w��^0Q5E����v�h[l{�}������#��
��uw�E�r�����s?�7������{��]8�sS���_��Y-5;.���B��1B���R&����baD+��H�;*;��f>���)��
X�,�Y���R8}2�:�K~�A�s&��"�����nhW��]�]w�#��E0eE�%0�i�.^�&TrY
|I_��_�����+!e��DHvle����O>R�9�OvXT�	����\��
�����l��DM�����v�XWRW�k��#�V�c��
��vS���E���K�j�Y���:>-���	���}\�����p]�G �
�3@3:"d��BH��6g�q
���!��G(n�3���J.�������1v	�emL��v�!7�+��E7����8�Yi��"�;��w�������M};���b�
��2�sG~3_�)4��#��V�g�V~X�)�&B2��_>�K�e �h��q��Z�����x0����J��G2�7_���5R;��v;b���;`\6�;V�8�g�U��[�G�gp]�Pr�/��Z��;�����8��� �����l���
xO��2am��d@=!v���By�����pQe��|��ScC_�O���������N�2[i���	��g�w����:$2����������z���ZZ�OH�BR&�M��B������p��D���C������6_�����a�`���EB�EQ���
�c�7����6�T��U���E| ��c�������N����" �:l�[�������O�����W�<z�j7BS��R&�M���7*�
��R���:.��)b��Y�T�6��I�	���>������X`-|g���n��)�&���� �JmG��2��lH![���q��P����;-���L���2am"4�����O����qAm���Q/��	
�������K��O���@�)^�"��}�=���!��l�$2:|3l�G�g�����$U����i�;�>	2!d8��a�6�_�k��s�|��(�9N!B2�{*��	k�-
�q�S-��	e�|N#�T�E��y�g����q>�:v���Mnu#�8Ko��w�F�����c�����BmC;%1^���|6��K��r��;��.���	F�Oh��
EH��6�N�zHs��$K�7.���f@w��aB�)��-.�9C��/~Ih< ���aF�5���S�Uz:�vm����WB�nL:q����!���b�4����!h��|/�<���?��/��������A�4��h��N!B���T)�l�M���w����Be�P����r��\p����%��G_�OR����z}��������8����'6��������`�2��O��1~9l��Gf=_����mC����!�����fS�"4�`m"4m�{�C^�d��=\zl,nLN�.�K���a�_����7/��a�h�z����,���&y1x�	������-S�r����cbI�.���|�����o���	8�	�;!�jba��|����R&����C%��%m|V���#����e����ZmB
�vK�;���b��;#������k���<����@�R8}#�vNf����6��K�����
}���a����	�i��
E�&B��-+�|�������0%�������\��6/�-_�^���ru�3uc�������G�+pX�x��l���7$;_��[��W��(4��=��Q�z�}v�����6���6B�(��J`���"4#�=B�4E�I�0�����/Tt
y�|j
]���Y�S2s#����������!��x��x�J���c��v�����}G��aB]����t& �
/a���������w�q����oO��	k�)%h����&��{���\�_���W.�-����jg�~B��W�[q��aC���C��
��f]�Q�{������^�������#�����zn���25<�e��x~���������S����T)�������1�GM�P��g���\h�����1��i�H�l0u����Enr!V�gf�����+��;vx��������f����d����i�\A3_�%�H�;F	�����Bs~{"�LX�M��kh�K��	U^!���=4e#���{B�!��.���4/�._>_h='������6Hu^������N�N�bB6�6���|�;ua���=�>�O���~h��|O�:)m3x����������1���76��H�T�F�f%��BH=j�Q���5=|�/�@��_*s����W��`��?�K��w����������F��&���.�R�ch�$�+����F�rI�\N#_���N�����E--�������'B�����T`����-�d��%\z<vHTE	-|�{\�wi^�
��u���8d���5D�W�7F_*r��|���u�e�/�^�p�t��gmHFOa�D��C!����E~sv����o���M
���_��; ���a���'�9��2��^�]j��A�����r1eR��l�5���?�g�p�-3�]��Xh�]iGlt!vz���Rg�����n����e�!El\�Q���5�B�����;�����)�&B�%�Y�|�q��w��1�	q$Mh��W���j��b���B����5���)�h��R|{k���B���xu��S�l0���c���q0Z�*}��w=���?g�6��I���.CY�TH]NBf��Th���>�~����5�
)d�����v	����{���n����2[�������5�n
k��m��~_��}�b����)������Qe\J
����w�����	����g��'B������C�&[z�'���'j
�nG�f#��{����#_�E�v5�f��-���{��ek���C7�
��?p2���&(�;�c���A��VAE($Y����2������X�<W@�)(���<���x�BO��Th�"P?j�Q�)4��u\\����=�a��s!��{�^r�����fr���XtC�����J��C��,�)�(�.����?�
/f*�,}����}H�����!��oO��	k!�`���.�l��)ax�f5����P��+��a�`���k�Nq4�,c�5%�5�M��%��S�����l�����so���t��i�
DTE>lLl�:���������@�f0�	S�'!��=��H�y{F����K(l�3���:������}"cM������=����"�_�?�3�Xh���Q��~��@�?��I��_@k������?Z�����;R��DH��62���;v�.=�P��`��t�/y�K���`����%B�eQ�����0�C���	V%�;�,�
�lt6�<v��k���I]�-c���C�u��a�{��]8�3��~.�T��.�#�Q�[ �����)(F�b���2 T=�����J.����e=��D�z}!�:q���K~�A�s�%q�k�W�zgB7��%��h�duS��`=��������a�^��z�U�X�)V(B�����)���C������_%���=�i���8��"_������`����w����P8��<�7�qV[6T��x�T��	�bB6��H��sU@bgv�X�3��H'4�H�C��B������?�7��Gn@u�?��x�FH��6�8�����Q�uP���Z�L}�^�����ccC_�O����;<����
;b���y���������u��vr��>����i�D�#]Z�V����v��U]B���;b@�g"�M��+!e��D�8LN�z��I�_93���8�)t���Vs9�4 L�*_���xH����!L�D��>�%���sg��w#��
.��sX�
&tf7�>C6����L�s��c����~��`�����
��H[V�J��_�^�R&�����`�x����|V�X�E��y�W������/��'�~R���6���p��}�����A���>��{��q_�����aC�]z������Kh����IF���`m"�dX�)�&B��{�����d�����r��8^"����[��?��`������^��0���,Q�noM�)���~���mFg�Kbv��t�����0��o<����xC�i�Z	V���jj0��1�z��q�}��1�5���u!e��T�1����!��G(i����*.�����ze2N�R�w9�>H��>�$7�+��E7���L<����?�^o�hu.�����������!Ell9�V�4����>��H����DX�)V(B�����Z���dN�Z��/���������}|����y��k6
]�X����QU��������{2.���nt6�8z�����~���#�4���C�8tC�?����p�p����G���
wVC�Y(��� ���8���m��	k�,4$���CB]�P��g7�I�\T)����d���8�r}:�:t���Enr!V������k��7�:[��=���"Dj�{+�vMe����B)�K������N��_�R��qQK���)�&BJ���2am"����4����,=�zv�/=����0��_�����`�����+q$
�	C���������T�r���D~dt6�0j���+v������-O�Yz*�,���Mp�E8�S��C_�?��r�<�^��
��~"���)���h��P�+���9�|r5U���Y���f}%�>$�}������jb���y������5��7r���?u6����m�i�T�'�
.dc���.��/����N�8�q����DH��BR&�M����=zx��K�k*��Q�1q8Ih��W,��~d@<��}�|��zAT�kXFJ�t�pKt{�]����+�v�
.������}���j��H�)���Be8�\���`������\�-�.�����
Mi0jj�#�u!e�5�9A�����}By�����p�e\P�����0�q��H�l0u���u���J�q ����O7���nF�y�fw&���T7_��us���y���\}��;?���;W_��,����M�f%�P��	k��CQZw�����=8C�8�#t���Vq��6 L�_���|\����{�3�#����~��.��it68?r����7��#[S��M����P��@�-������f/�
��A�>�t��DP0�)��m��I9���A5.v���q_3�Z���q���o6���������E0u���}���F�q$���?�3�Xl�]eOlv%vy���R���+��8�v
�����Qe\r5��������B�J��R��M%��&B�IX�)�&BOCg$�W-�d�����Xz<Q!�z�u;����� _����O��m���[�H[lG�C��CY�Kbv�
��mW��2����Ju��{�'�p���e:B�~�=_��L-~
�oA�N)o����Fs~���m�����)�}b�Zl�*:��f>���-�B
Y�l�5��O[F�!��j�7������Xf+�}'{^g����v�=����� ��.��6q�s2s'����F�rI�\v#_����
�C���}����&BJ���2am"�$��cF.=&[��{B�a��.�k$�����	=.0^��o�8����T�(�����Fg��Fl��~���3�%�BU?���6�=��.��
?nK�U����v�B�6i�re8������bx�FH��M���	�{Xl�*�q_�cq�[���}�|fU���Z����6���<�G��.��7bi�$�+�	�c#J��*.�Az���Gh�F�QB�9y?@4k��&BJ���2am"�o(J�j7������a����!Q-�X�e�����>�W�:m��l���������l���#�V���1:|'|��i�����4'�
����O�c|Zs�.!Q'�s��7���M
O~n�~��&eA�].u9�������y���}H��J���>��+f����i�]#%~�������o�����y�����>��O���Gq_q+_��qR:��DH��BR&�M�>A�%�W�2*�vN�{tz��8�&tX��+�����d��vIT'7��o�2�����R}�X����}Fg�o�o��faU���P:T�a5M&����� �����������&X��?���P�E@�O��!�n#d���1���O{vH-z��;��S2s#��F��/=����\�4���[`�]aG�w&>� ����]�����I�g����	�\f=_��W?��F�"���i!4�{!%�
EH��6��;ZG|4���mkd_z,j
�nG�f��{�������
MG�� ��?��[5]�]���lpE�����a����,q
l�/��5��3t�A�}H�����p������
���@�i(���\�PM�g�x�Fs����1�uP��
[��:.��)z���m����Lu�.�����B��#Z��w���]~�X�Ll� �?��B)�h�>��Hg�s��b6�����u���KhzG0�Chr�����a�"�LX�h.�i���)�!#�����7�L��x��d�}y��������|�������_�]�q�����v��'����&�x��U���_
]�5������c�������}�P
���+�zN}��`�������m)D�<wh�M��}J��m4sii;Tb}���_v#�T�E��y�g���XE��m�'5�u �����w,��]�Hlu���c�(���E�v	�{�������\zW��Wv	M�B����	F�	�Y�7R2�P��	k�f�wu0EyTt���Qs����M���>�
~v����i]zLu���B�q��
.����?��>:���L�'_x���+����(�_�x�����e������|�r�������J5�
P�6p�c�����G.�\@�A�v��d����`F��6���(!����Be�P��Gp!�����07�����@������p�X~��]����c��v������E���S����x�M���=|��H�}_tzurv%6�EHi�{!%�
EH��6���ww2��R*����tjd�����0�l��j��j�����x��"_������`�s|�;B�q(������%�Uu��	�J����y=t���
����|�R��ctA�����!������p�f������=�a�q�j��s>��u����C%��J�;���*.��
�e������������]��������{V��m��N���}���9���b��2.���k�+:>�7<a��^�M��	k!%�
EH��6����t���Tl���Ys���
��gD*8Y��������@���B�
_�����A�������}�@��UF�b�3�*|�e^����l�����N\,t��U��0R��!��,�K��!<�c�����P	��2^��'(���;����N!��O�������;�q����N�����=�����Y���q,���v 6�����G(��^��]�����Y
|I_�+t��A�8AM������2am"�dX�)�&R&���--��"�^�5W����6i�b��/oY9vr����Gg��c�f��x�����m���d������k�]����������)t�	��*�k\6�B���I��8�zW��e�����������������K���,�<z������s^�g
	cb��P�#����||Z����ni��x�2�>L��vy��\�������wF�w�w&vx���S����f����d����V~i�����s���	=�M��	k!%�
EH��6�r�)��Gw�W-0g*8��OS���tF2�P;U{
b�]�a?_�"����������K�:��/��F��+�"�:�K<�b����q�.�]�L�\o1v�V����!<�-���Y'5;.	��"`�SrV����L�	�K-6�I�;r���j.�����ze2NI�u}!�>~���Cns'?t$���?�3����^o��y}�^�D�3�	�c#J��j.��/k����N����������DH��6R2�P��	k�N�z����<��'�q(\h9�����?g@<��5��U���8T����Y�jmI�*q�(��a����o����������R)�;�-S���_�����s�|�����=��s�u{J��7*�
��Ba�^'��)d}�Y�T�6��A����>������X`-|g���n��)��"u�9D]��m�i�T�/[��W�e�q���;��;-c�4SB���DH��6R2�P��	k�����\9cX*8���M+�N���$�����\}�8:<M#�5�p��~��X�e���������=n0^�{������L�
�}�WD�0"|1`�6���~+2��������/�����2\��X�' �Z�a|`��-zfx��BZ����X�+�����|RQ�����C"cM������Mnq#�8Kff��w�i��j�:���}>R��a�u���xe2��lT�R��5��|���zB$�?�Y
k!e��DH��BR&�M$*!zd��/H70vb���k2����r�.;�z��������U��hf��=����&�D����}Fd�x�s���{�����8`�?�����������b?9.�����z���u��`D+��H�;*;��f>���)��
X�,�v
cG_�OR����zgb�-b�������v�=����u�<�OYS�Q�]�����a���;2���V��Gh4�8�	�<s�6�q�6R2�P��	kM'A=�usP-{�i!���-tf�0��s��b�_�1W�W�������w��3�����Y�
Q
7$3t��e���������������'LbPw\�5��/u:�t��DP��y��if�u{����>$��%m|V�P������{c��XF���j�r�+�j����g%��X�L|�A�%OR��i�8���GPS���r��|e���/���wP���2��U��X�)V(B�����[^<fq�sv����5�38�Y�����$�����5Q����6���z���4�7�6={0��g�n�����o������d����^z\B��r��Au�<gM���nS,�'��a��_�������pQe\`>{'�qJfn��������R���N�2[i���	���b����<@���w�'2�L@.^�&Vq��|i;_�+t������=��BH��6R2�P��	kM-�&�B���zZN8�q9 j���.�.��'��$�i����i,]Wv��������y��y�v��r��/��~�q��'�i�`�7��BB�3�'�p���F$�������5�BQ+�Q��Up!E�_6������W#�3��;���.�J;b����1��v���O��u:��A���.��o6R���s���U]B����c�����[��
!e��DH��BR&�M4E���	'�������9��O�h�.}��3|�<.������?O�Y����D����{�%|�o�V��.�����7)��t�����{.��g;CC2�s����������G{���6 ���|���|�l���;����q$���{��c�(��t���Q7��<6��K��r��v��O�T�*|��
��R&�M��+!e��Df�������P���ZwGa�jA���(��<_������g���_�K���{�7n����m9�������u����o.�����&����W~���H�m}0�1��
M/�}���y@��
[��:��3~9��c[�
�v�y��-�)vg���Z�����B��"�Sg�)�H�V<���n��El|�Q���5�B��00&jH�?$����T)�&BJ���2am"3���>g�����tr�T�7;$�����|�b.����
�/8���qo~���������t���'�������Zu������I���/I�����]�R`�s��2+-
�{�E�?p�B�&�����E� E�K�
RDP��t���RB��t�"D@@�5�'������}��\��@6>���?vgg���|wv�fgn�X.����f�o�6������3�?��w�����"����<3
��+�^�jRx���~�ga��e���D��%�T��|�
��w�4��=?��w-wC���s����������D�Y�B�������v���#�����������wqd��V��Eu�S��k����?�P���F
V&�i����L�9eB���~��v���n,g���5�S[����4����G��]������]�/��]_��:r�������jR��cR�����5�����wgG��o����VE~�>j����vE/�#�]����_��=m��#��Khdj�?i�T�1�����1�H���B�����/�L�~#b�bKhH�|�9�rwG��ob��5�\<�����No��yc����
\��~�k//k��a������Qk����F?4$����R�a�����?~�a�)	���D�G/����y���o��c����3z����kN��}^D�Y����7���v���t\X�������mn�|���#G����)j��h���b��y�.�X|7�+�,����<�S�DlFF��Dl���?�`���G&lR't���CA������]q������T"m�w�g�uK�U?���r�5���h��U��^0��)*��shp�k�3'�a�_&�����ZZ����ck��wJ���!!���,�n���w�b��gc��0�;l^��6g�����7F
��|y�'�"����4#�����cS�����5��6y�[�&��4��U��;T��?�����C����O���h�^���1��1�����1�H*������(�v�������>��-���]�{�-sP��_(^�!���Uu,o��0Xq����<�����1�~���d�J�/�uT����k?�}g�c����<�iW��z?�r���������}&v�Q��_b�����)[��Y��*���D�?'��i�9;~��
wO�����6��;��:7��E�/�`�o�v�t�����4]����g���Bo�r������������D",��Wc���l'������K�QQI����������{�f�m�g�������
������Z��phl���s�~=���c��:����s<�$y����l]��0�n��a���}�`x��v���;�Wz�\����{��J��1��1�vDO��wp�+�����.����h������;j]���Q�wF/���`��#���^�U3wDD����m���M���M���P���M�b	���z��������$�N��Y��5I�u�������x��s	�������m��zc���*�^]�������>��7��*��K��U�s�#����������/�1i�������������y�� ~��13w�^��&j���O�w��Fiy�������d{�W�N�������Wz�F��m��cM��{�_�=i�Jo���'���n�Dl�DlFF��Dl������8~8��;�#�n�������/|{�5�.o�y���,{7�����k|[�lh�0�rA��3k��X��Q%��_�K�eKV���7��uVS��~��3�������)��'e��{8y��K����
�����s�N�=z}��+#�/�u��<3m���t\X����-�����(~����3�G/�^~ f�o�'�r�T��w���V�%,��X�M�n�Dl�DlFF��Dl��DZ�u�d>u�1���Z�����f�_Yk���k��"S�U���v���U�`�%�?�Sw��U��*u`H�k�&o���+���XW���4�zz����gr��DZo�w@�]���V�Y=#~���k�����6�_����'�~���{cb��{s"z�����+#G����%z�O��~�Yu(f�Q�|w9���;w#�*��&�m���M���M���P���M�[�pa�:ur���1c���K0 88����]�����N��#�����=[�Kc�����'�j<�5g�F�1k_|U�W�5W��|8������lT�CC�$w���ea����e]�;�[O���8��;�m�?���k�y{����z�?�������5j�mL���"�����
=M���xl���3�?�>����A�"����c��m�Wz����5f�q���c�3�������n[D����.\�c"6c"6##Bc"6��K�.&�����R�J~~~^^^����s����ZV��y�^��n5��h|��asgX"�Z�����;�.~{�����V�C[���\����V�ZmY��,j�mv�1�*�Y���\��y&�a����o��K��nm=��z��5F�,�!��[!'�8v9~����-����,
���'z���1N��}~���my4��MyIj�k�V���"�-�M�1z}��-�Yz���o�;�����������?�Jo�u0&b0&b02"0&b��-Zd2����s��a���Y3Il����+� r���??�9������K�b�������yWo,>i]�O�������7�p�+]g��>�/`���/�K�����^���m�<,������\�z�f��+q������'�~�M��h�����-�����#m�x,��:7��Y�����w{;N����da���C�M�5kg�|�U�b6������]��8~�k�n�Dl�DlFF��DlV���M&��E������5kVI?s&��m�S��������S����2�Hc[���>S���]z�����}y@��>���6��/��1�E������n����g^�0-����4=co��)<�M�2+���o�m���[����^�?f�a��A�b�]����m4���������m���M���M���P���Mc���?M&S����;������i��1O��?�E�=�v��B���;=-��q^�����>)x��u?������Z���S�����
�	k5)������8o���Q�6E��i��c�/1[�����;s5��m����I�/t��
�	�	
�iL�V�2�L�����&L� ���k�4���ym�o�s%�a0�w�3����v�C�Y���}�F�N�?5�G���|�������������#zA`��1?�f�y�|��m��7��3���6`L�&`L�&`dD(`L��1�3�d2�m��y���+eS��U�FY{O��0x�������6����Ac����������`[����j{�W������ak���h{�w�n[�U�b61�<i�����U�����m��F���x 
��
�	�	
�iL_|���d����7m��M6�(Q�i�����e	6���<�Y��7d�������N$�������s#>]������f��^��m��'��;w#������L�$��6`L�&`L�&`dD(`L��1����d2u���y��={dS���FY{�_�s�k/��
n����o�
����u�������_,���1" ���Q6EM�=sG�w���������������zo�X"�H	\�c"6c"6##Bc"6����K�,�4��{a��jH������A������o_�v�j5jV����4v�X����M�M��/�M��We���&�5�
Gx�\MG2z�h���[o=������+&�)C������5k&�&O��4�0�����L�9s��'^�r����������O�,�Q/���#((H���}���O�}�]-[DDD�x.\HjYiE���M���/_�f�L�2�r���<x�������w������,_��N�:����2e*[���a�"##�3�j-�S@��{���A���-�1c�L�2=�������y��s����S'G���t����):����_��u+V����g�\�6l�y�f�<���5k��C��u��I��y?%J�(R�Hhh��#n����x�o�v��'p\�YVbj���*T��%K�l��W�>u����8�<QQQ}����?���+�j��?q����-�L���cZ�fM����&��5����Q��q�A��o��V�Z���WB�`��R3�9s�!��Y���)#
*���_[,���<y���Cv���
���r��R[���n]�t��m��z��e�T�R�n����[�l���w���?�C���������#�   ��������3g������p�O@�m�&G�fr��kc��e��O/����;��}N���t77�J�*���yyy������7�):�=zTn�d�T+�����j3f��G�J��d'����
Hv��k�9������?���'0�S�N�N���z��e<xP�bEI���_~���W](�6m�e����Yf����8��[o�K�.00���_��={v���������_�kU�T����IVk��n��T�s���XS������t9���wky�,Y"�����D�,�1���$$k��)��W�&�������/�������|��m;w��*/��]�v�}N=�����z�N��,5o��y7n��o�>	���s����7o�,���<;aaar[hz�Uka
>$���.<��U�PA.�r�s���x���r��Ib������-��<y�>|X����6k�L�7o����,+��2e�Hb���cbbT���[��-5�V�_�~����ju������;�T
ry��7���F#�Q�z�,Y��	��B���j�:������M���^��%K����'��{��I�u��I�FDDd�����R�6m<<<\����e�����9�R���|���8v�X-�3�:%%��ie���*Ej�#F�_�$Ub�*U�)��'�W�^������i����Y����F��cG�3n���}�����#G�����3p�����s����:w�\��g���Haaa��+^�����a�<y�T�R��,�c�ZS�!1A������k�\===�*���C��b����� ���g��~��Y%=�7t�]�j�������e��!��Q�r
��+��U��j�t#��U�&��zzni��Q�������Vos����I���Jr5pww�t��}6u�(P��j���m��N�6M����+�N�E��['y�������(QB���o�n��o���={�^�ZKyU�|���3�C���kk�cddd�t���E��������Z��+W����T�o(i�������������E�+'z��euV�_|���j/J���s���o_I�JV�I�`��I�s�����
�j-L���q�OFnNF���\��s������_�����zeGEE9��kl����������:�!�<�H�<�����/����k[�����W_i)�u$e��y:N��w���+'A��Z�3p���D����W�y����M��;#���-��6i����Mk|		)T�P���###�v
#9p����W�P!�l���,R�������!��Y�$�Q�F����d�[�n��q��I��]���-Zd��A��m�I�H�#�A����K�,Q�z��euV�����,����%K�W^yE[�]www��9$�h6n�x��	����0���.�,u����P:������s�	&��v������������UCX�>}Z��+f�Z��~����_��K�.�]�v�7���T�������QC�:$����:'A:��~t����1c�,/X���J�j?����Cn����_�K����o���=��S�i�����������5�Ck����%e���ju����SR�3��(�K�?��[��'J5�-[6I���_��'A����:��m������~~~jY�c+W��+W.�\k|�I� ���j-L���q�)K����uk������m��S=bT�Z�����U/��:u�9�Gq��
�\�Z���sk�$�d7�K�F�2f�x����g���[7]�tr��S����V@��?��s���Z�3p�����,O�>�9����������?���M�;g��jy����|���R�����G���4��;����7<s�L�������@�{����T��e�:Q#W	����75E�R)888��e�������qc���M�C�t��Y�
H+��/�5j���(d����X�fM��3p����:��O?���"V��
��.�/��.]��Z�d��������j-L���q�)h����3g>{��JQc��K�5zC�%\�Mg���u��M�bO��������,_�xQmR
�rq���K���\���G����f��=o�<����$&�T�������.O��;�������jY�V���W�7]�v�����w�Q�<x W�ET�U�|��y���w����W�Bk������,KJO�����g�}�%K�B�
5k��v���S�6:�3�:��|�s6-����oY}����+�m�����-��?��#��}����T�*T��|���C�J��o���S�6����_?�}r����uk��*U�d���\���?p��/���TS&��?_mR�q���5~����jT�Q����+�V�*��`�`@�ZS�!������n�*O�����-QMC��{w��j��������!!!�b~��-������M�}��,:tH��������'7n�(G+��rsx���<y�T�X�l6�^��d7����seu���I<@jrxYqh-�8����R��,�_4jR��;��&M��]������g���j���C��B�
�VC�w,V�X�r��rb�T��2��0`�6�����_x��������T���-[6������;g}4Pa���eUu������J6�A�b����S�Nr3�|aHs���T7!�T4��O��U�8�_Vg��7o�B�
I09rD��L�2��F����9������`��-r���=z�H�yR����Ht��.��Z�O�^.�K�.�O�O?	�����z~��~��[��3���K�V�6]�t�[)�������F�����{�<�|��7�w;h� ��'�[����I*���[��~�z����n����|p������5�>z��C��T�{���8%�!��S�?����~�v�R�����gRu����\�V��hJ�F���������yy{���5�u����k{P]#��Y���F0o�<�AyN����J�J����j���u���w���LY�U���{�4
���;  ��hx�	&X��3{�lm�
�X�bRO�*��o�<$:�^��b�0@������a���ceS�6m�._�\6�5�������9���<y�9����q�F-E��~���#G�����;wJ�O>�Dmm������Z�FDD��o���E��\�B�y���-LR�8�Y�q���<m�4�l��l���}��S����rmy��W�e��zJ�9s��h����>���G��:H�h�6m*�}��C����_��z�>�����C��+W.�l��Y&,,LK�0��g�������_~)��]�V���k?���M�d���~�� ��q�F��Y��O��1�t�W��h����=�e�Tu����������)�n���^�QM�0s�L�?Gf���={v�H}�Z��C��u 9���������9C@@���x�j
���z�����U�8�R�����G�Y�d��E�j�v��7���+'�YUcJiB�v����Z�j��)C����Y3YV
�O8��������G�������#d�d�:u�Z����L�#/iT{�zHz��mz4���"E������������	�$�$�@��>B�R�Mgf�����_�V��pj�4 MP-	v�S/	6m������_69U�x����9�V'N�(��m��e������tU0W����!QY�u A}���+��/��������+�A+�/�����'Ov�s�e?��YU���>|X������f��A�a��MZ�C�B�hYm�������I�&��Q�<q��/�x�bY�U��C6���#G����Cs���������K�18���z5��`@�-2�O������!��I������%K������M�0!���b����������]��n��1���f��)�G+���&5t����'Ie�����e�)~%-��oa���e'�$`�Z��C������35H�2e����H65>���*r��'#ww���/'��z0)V���������~������>}z��!���{k�$O�>���" mq~��'Ie���������M��^�J�r���m�J��8qBK�B�O�����v��I�6
H����"B����n��e�z�?��S=�8tS�g����K��%K�����M���nc�<y��3f$�0,5����s��7L�]|��IR�'�:���R.^�xDD�����olqh���Uk��)?$&�,������;^^^���{�@
�!(G�AAA*����~~~�������=zt�=�l�������_��.]�DFF���K����E8�����Lj��9s:��T�UZ�p����������[���U�$6��HRY��F�*U�^��R�9�/_>I���O�P�S��!C�k���?~���'O__�'>!@�PsiU�TI8����>>>=�tV=�]�p!�e%$3e�$��f��������������|�r�R���T~���M{�i��y���-@� ��bz����G���m�����np3���\u�/�U��%���������=��&�T�N"��)����.���#G�%.c��U]�?�>�I�/_�f���N�r��?���!�n������gs���j���k�(QB��b�`�����I�a����qqqr��������-m��" -rn-��u��A�'(+�`/���zaDnx�������b�6R�p�2e�8��b}tg(O=+W�l��%����G��uU*/���zY�q��EO�����w����+V�H�>�l*R��D���^zz��7<==��)�|�r�l�*V�(�Qj
�O?�4Y�	x�~����Y��_o��[�h���oK���H�>���I���Y6�U���������;�8o�����������={vW�6F !�=Nzyy�`�R�/_��L��D�u ����P�i��^�Nooo���-[v��a�EV��:�Z����G��E�B-v���~lr �5Y�dq�4��]k����1��O�v�n������`k�U_�$x������=z���I��_�Z�-Z��8{��)�X{��Ip��y�J�*%'�X.|����l6O�8Q�&�&��9�,�?�������s�Z�����/��j�*O�<V�D��kW53��U�V��~���~yV�����/��A�����K����x�������?��k	N��'p\U�:�N�+��������5&&��O?���������:@*Q���������C"���+��?�d25h���}b��������H���������Qx������o���}J��������;���Sn-swwwh-�������X,��#Ebcc�___Z���T[e�������Ik!�l���i��y��M�>}��9+W�<l�����;d[�~�����+W.���e���@�	�FGGO�<�������������k�������-���������w��Y+V�8b����P�U�ql/22�j�&rxxx�,Yd���9$�4|�p�?�DV���e�&�v�r�O�-d��!C�rv�4c��&�����^�z]�ti��m��y%�r��<�����G3d���y��>��N�:����6m�4-�skahhh�Z�$����������\�r����d�:u��L�2���k�7��+��V�XQ��Q�$]RJ�*50��l��s�B����W/�/x��M�vr������p��e�����zzz���={��?����;;�'88X�����������b��v����k������5�D�%p����={�'Nh��l�������q��i���Z��{wI�V���SQ>q�����������U�_��RBBB���$���?V)S�Nu~���p��M�\�@�a�[H��M�:�r"�HV��D>x���d��Y��~?��i��eBBBT���h�������yS���QC��7��x��=%�w��j������{�3�/���P�|����f��Z�jUY���y���S�h����?j����f�9w����w�^�<��q��9j�����b��������'6l�P���g��
.l2��v�z���3<x� ]�t�G�C���y��W�TI�:�n��AV���������>}�X�[,���d������c[E�=��*W�\��{zzj���N�<Yk������s'}��Y�d��R�}6o��)S&���>}���k��W��������cj��;��Oj����3����������{�����lj��������9N=��AAA�*���O�8QR��m���Zx��]�+����*e��Y�*G��s�9������G������K�(�b�
�u�����Qs�8��=:�R�������G����P/^\R����VU������zZE�$���?W�u������w'��i���'�����^zI��m�����=M���%^���P��U�^=�R��W��&=I����!C�HJ��}e������+W.�=�l-��s��.\�b�\�v-]�t>>>�������������0wwwY=u�T��Z����s�N��6n������T����3g��V>Y3f�,��������B��%J�����I�&����C�"@�v���3f9��K�,�Vk��)�C�q.�a����Ckapp�q������V���c����s��QI��!CTT��Qka�����8��_|Q�;�^C>t����[����O���#M�3>W�V������K�y��-[��L�^x����Z��b������n�Z��\�RV�e�v��-���7�U�&���OW)���G�W�P���Z��C��{�9ww�������={�#G������W_}U�~�m��`��+��O��p������77�2e�8|e���K�.����s��C�k���Az{{k�,�1����];���A��:uj����������3Z�>}�H����d{����4i��
�h�B�"��ZZ�V-����e�.]������s�I(m���Y24l�0g���s���7U�'N���T�"�z&�Zx���t���I�G����Z�����')��{���g��i��Y�fjL��&�<iB\\��i����r���.]�L�2�-[�o����
�
64n�8w������[���y�������PDGGO�:�f��^^^���E�i���O?���s�����_�vm�&�/Q���������?^>7C���?z���Ek��_���1x��E�M��b���e��Q_j�������]��:���w"��M�6�d2u��5�@j���(Z�������'S�X���������L�7�|3��@�X�bE�-
*d2�|||n����G uL�2���#{��:t�~�zj���wr�Z
endstream
endobj
14 0 obj
<</Type /XObject
/Subtype /Image
/Width 1722
/Height 948
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 50121>> stream
x���	�U�}/���V����&m48G1W������Ij�i�'i�M�k��Cj��k{�J�I&-qV5A�A�8��D N(D�d�����/�>{�� ����y||�Y��k�������w��m�u����n�������e�.���bk���t��������&M���*w�uW��~���Y���������j6n�8y��K/��O�>�����w�qGwoT7>|xq
��7������]��z���[�����h&�l�p����K���
��Z��6m���������������m��U����qcwo�)����Z�a�f�p�������{��M
��Z��}��r���?���!C�������=��3������{[�;����O���G�;����'��%K��.�V�:��s�����^���j�+m�E]�6r�����O_�~}����]��R-��7�x#��/�|�����_�~�����[S��n���[���A�R����n��W�5����M��0�:��_|���}���l����k����W��UwoN�I�sq&O��������o8���{���]o4u�����V����<�e��v�v[v��K���6m�t��w����iy�UW-[���7���][�[]�����7�|s�:S�Li|�:�B:����������qx��W�{[�#RkY.t4^-�����U�1bDy�.�F��%�]��R-l�t�]w�ug`�FE���?���!1w������]R-��uk����p���WT-�r}��-��	�{[�������p����K��?����H�0��s��i��RR����3g�|�����_{���{��6����/:x~k�=�T���?�i>\C�y��g��[�m{��W_������a��5~��������Z�h���E�������ja����;�������<��#�A����{[��~����
E���j��1c��sf���5��j����������;Y��e�.���-]�4�{3%���f�OK7��F��ZX��ja���t�M�ZQ����&�_}q{��������o�=W�������_��Z��k����6o��G)�����jar�����_��._�.{v�6��[o-�9�����o�����[/���\����j@3�T�}�/^<q��K.�$uS�����^{m�������O���{n����x������;�~�5�����+�Wy��'[k�4iR�*7nLk�p�
i������b������SO���\-�����)��-K��_��_�>����|��G6l���#�vd��)i���wO���%�F�z���W�^���S�.-y��W��HqxS���+W�,��ja�;S:V�Z�c�D�k��V1e���3f�H��������o��C���Z#wK�B���c�^|����~q��+���?o���:���K�m:7��N�tB><�_���u2�aTW\qE1%�W#G�L��&>��C��{!my�s;?z&�o�~]7�N^7�B�Y�T���e�Y�q�dHQ-^d������G�����Z�Z�{�v��+K�������	����r���S�,Yr��w6�hU��7a��7�x��R�V�����S���_�����7n�/�����"���O�vj��U-�5kV����FFO�����Z����jaj����������<������Z����Zz��,�&1}a�mX�fM�-l�!j�Zx�-����|
Ljg���N��H�s;mg�N1bDJD����
��/��^35��7o�2�S���n��9�C�'���M�����,�����c�����$.����x��Z�L�����7�^���_2dH�+R����T���M���Z~��Am��>w���2eJ�}���L=�{��7�
������#E�Q����;���O�e.���bJ������7����j����w�}��t:m�^���U�����u6��g��G�Z��������o��yO�|�Y�R�����+i��k�Y�WT-l|��R*�W8p`��,Y�$�o��S.�jU^z���L�6_u�U��b��/��6��t��6�Xe����
����]k��
�O<E��]��������Kw�v7�pC�pZ+���.��������p�Z�]�]����6O�B���u���F���������z�W_}5������l�������l9t����zo{��$��`��7����'�M!_v��7��`�8���?�����zV`�1��\��.��#R����.��/�w�}+��]^��V�5kVy���z�������������:������?5u�����a��vVla��y���}��iSEie���c��I+��&Lhs��������W^ye�����G��rb�����_|q{��X�0��
�f���m/~-����W��f������o��C1j��t�SW����Ne�#��a����	�N�t*����
i�������<L�z��nmg�0u���8�{��|n?����b����u����-���U�6.�+��7�VB�\�emE�V:t�d�����b��������t�V��o����~�����'�v�v�FE��\�i��O����;��R�Q�3��N�>��7���U�@��?�>���o���.����[��G���gW�`���7KjRC�Z����.7�u6���h���i���RS��4w��r
<��W_}��7�X�Vj����h��ogj�s��8)A��R����-s:�����rT>9W�Z��G���^~�������<� ��O�>��������YU<H���W��eK�#0y������%N��W���,YR���V������z�������g���o����G����KU�rf���i��=�XZ+o��y�r��������S7�b�E�I���������H=��]�����M���W������{o��YG���yHI:�c��M?�=z���y�tF�`1�B:�y�tFU�I]�t@�mV��x�����#*]�
m^����i&N�����:e���m��Oo�2�j��[��ja}��/�U��%��u��e�V`���mJi-����W(n������k!+��`9P�R�1c�����L��oS���V�����-R<SHs��2[�!��������R�0�JG���j�SO=�������kjW���c���-L�w�����_���gWj�����45���x���E��C)k�!�_-LMh�����k��
��[o��\�/���X^&}F��+�
�_���������/�G#��|Yz�m��M�0�������X���~���pax���i��i���[�n���y�r(y�����Z�q���Zk�OwX-������6oQ^DQq�U���[�5W�
/��r^��?�q�����sG��������5��T�t�G`���m�c�u����t����]�c��\F(F���V��+�����wb:z���:�����#���KsG�Q�J=�6����W��y��\�Ls�E���]��6uc��������eg�-[�~};T�Fm�f��Q�u�9�T�)��"�)M�������RT��/W�r�0m[z��:���k�����yr�*�{��6l8���N���I{w��o��#�����a����k�5+��������S+��y��1����*��(�
���-^�*n��`CT�Z�h��\	9rd���������f�>~<�@���3�=����)S��O$��*G���\rI�
���Jy�'�����Ol{g-����zI��}���������^��
��[���B�j�������y��B.��W�ZU�<�V�-6lX�L�X�|����{���i����*j��q����G����wSt���;���d��u���Z�)�E�=�\yV�RZ�z�^9�v��x�����c�9<d��:������7���ksG�n._����4�������������e��	������Y�7���1o��bV��\��?~�b����I�Z�Z�fn�Jjo�]���&m���B�'J���T��[�[��$f��M�^Q��L�0mp
o:DO<�D�i���h��g��M��P1q���u��T>y�}�����Z��+V��e���m�Q�.]���?�4�e������vn��%Wt��_�z�tz��H�d�����M�|�|��:r-=���jhv��T��h�w����5�t�����+��T�_-�7Gj��V6c���'�NS�B�m�ja�>}�<�������/\~��o�V�W�g�������=�X�09rdV�|���-Z�K�QyVvX�!�p��wK�w�y��\
*o���?^gG����]�����Q����._�B��^~"y�rY�zPS����^x������KO��S�r����%w�}w^���������������4R[T�$�T�q��Sj
u�����o�Z���C��*T6.��5w�����z�r���d�7K�
Q�������?�����=!�7�����m��}�����J{�3���+�Ve���7�3f��������+(W��r,u@:�F��q}����[�Z8j��bn����]��u�|k���.O/_�����ey�O��H7n�������r-�c��������;_-�uE�����������;�/���^�ooX��F,[�,�^}�gyGv�Y7�[��i�\�Ne�
Y�Y�ZT<w�����V��-...#M\�-�����X��k�-^��)�Z�>�Z����P������s��i�6�|
r����UsQ+����[�l����w��ja��R��u�p��]���l_�w/���k�
Qu�p���y��wP�2_���gI�]�6�KE����9rd�L���+FQ����F���RO^|����yP���W�.����6l����O?�t�SL�<���<���W�_-�w��s�t�ZX���y�ZE5�|�l�RX�|S�u^�������Y(�;V-��(���kD���u��-_�W���o��������e��<�L���z����g?��S�N-���[�U?���Q{uK�0_;��!��u+��p��}��|Ah�8�t����E9�w������o+W�����!C��z��@�Z�(��yp���]~������U���v�:y�dZ&�c������J�S����a��+�����X�dl�����	ik_~��:o�?��*h�\m��mp;���5����r�,_��j��:`"���6o'X��!�m��;uL��S�C`-������Z���wg�U-,w��%_���"l�{�����@�0����c���W��P�U-,�j����q��x��P�:�W�|NJ��j�^k�W��f�����u�vg���+��T$��s8��\��������bJ~<q�n��+����[��\-���������N����(��C��]�:V-L&M�TL6lX����U��F'�r�u��t/^��!�k��8��W��������(�
������HC���ZX��x�c����K�Wp���������Z�[n�������(��\�����;�p�bZk����3w�������v�Vr���{X�W�X��Y�����Q��/����%�uS�0�i���oo��f�u�B�ja�g���mV��;�Z�l��|Yw�U���u��m�7��x`k���\�B���{������R�i�{����U���Z�q��|�j�g%w�ZX~�E�\�~��\J*�'�����_��W�e>|x�G3���J�B��T!�w������4D��Y-,?;�u{
�N
����.�Nhp;s�����K�|��u3j��w���|�k��v�?���y�*�
������~My���?^�7�-��2g������iS���<�����-[������Y;Y-,�BG�yU�,XP�B�u�W�a�0�T��d���v��j������!C�4~��s����R��A�R�o��Ei{����N�_-��#���iO�[�f��Q�5�p�6����w�B{M�2�x�rM��24��y8V>��u�\�~k�T���+�����;\-L����bzj�����_~������Z���q�x���=�r���?��7���j�-j�ZX-mI����o����7��[��Y��k��{�������zk��;���Uq�6��>X�	��\-���,��D���M�6�.�������_����m�k�����������j���S��w���^x!���D���mo�0u�a����k��ja��<�����d��Q�.�n�ja��:��|mi�[��v�6��5����9��R;S��R���2���7t�����KQmH���O�b��AV�v�p��
�vT>-�5�\pA���v�Z�/�L�Q�L.?������ZX~|F{���gW>��{%r��X�0myj?������#����P�Ft�Z��Z�j�����B�Mh��h[�*��o�n��7�\,����{C�<���c���]��;+_c{��w�Y�����
>�d��
���������~:�c�rh.��P�)'+W��K��Z��X����R-\�|y�����c7��+�m��������ja��,�*W/��b~���!CyJ��[K>�7�pC�_$���	�/�V�;q�����i���r.�����}����}���Q��C{U�N���i;���3g�)o��F�k�Q���.�n+=>c�_@��]�������|��:7�m�Z�>�Y�fm�~�qnS�k=�*���bi�tI��68��\pA~��(�.���w^\��,6�X��7����\-L���W�1�X������:���NY��t�Z��:�F��ja� ���o��_!�%�,Y�&����|�j���.tK�0�]�t�PG�Ug������ld��5��5*WiksQ��s�i�����[G�)\������/��������g��U���'o+}��kl3��,o���[��F�V�T�F�0?��
�R{v���^"��_qv�ZX���o��?�����s���o��u���w_�eWU���>}z��(I�oS	��\-l-=��Z�G{�B�|���~�<�<�����������>{�o�o���j��-[r���{�����.*^����Ed��^y������KwUs�&u]7n������iS~�[o����y�Mk�ja�r�W�z�t�P�5*Wc���L�2�][��ukIb�O���|�lQ��MV���1/����*\Uh��N�<yx�������)����S-L-j1+�N:���2��Qwy��<�:��#��*�w���W�|�������^���ja�{�F��xp�-����
f��E������w�Gy$�Q���r��N�e��y���%�s![k�+/�������jM�J��6�a���y�:c�r��o���!���n+���?�A�Dz��5K���>c���-Z����6m�E��vV7l����u��C�U-|����<��M�>��+�L'^�=$����ZZ���&��i����|��:#|*6��rU�\s�5�)��u����n���j+V�(^���/NJq��%�\R�dQ(ndW<�9�m���Z�����p������@��������_}&ty���g���s��gW���2��`���W��������o�s�G`���Z8z�BI$}5<��� 4���?�x�j4h����>���*j�]���V�K����6��u��������S�6m>|x^f���y�s�=W��R�{�M7�na�nE:�z�mng8����fW4�����*�it�ZX~���#k�f������g����>�Y���O�Z��ja��V��5�V����nZ>R|��%m����KsO��T��~����
/��R�>}�
�?���a�W�QMR��X�lYy`akU��|�a��r<w�3���O�.y`J�������:Y�5�����n�����e����J��t�����93W�[��`��gW��D��(�&�(9&�Q���%���k����w���%���G��k=}��
�/\pA������0���:�*���X�cV�^���������l�R~�Lw�����#F�E��^Cy8��+r����6M�����O��s�����?���3�ByS��b3r�'�_}��bb�c�z:�ky����.X��~�!��rw8u�*���|�p�;�!v�%����K��+W��4iR.C
4����i���n�3��e����K��r�-��C�)�iW�0W&L���Z���Z������|�����X6n���O��Y:*����?���x�����������*i�^~��������w~��|�b�~�����+�i�S������|j�e��������uw(_��%�\H��fe���+����k]
�ZX�|���v�����j���3�n��U���6mZ�;����;;����iS��O_
��'<�uyy�(U�B�T����h���xR�[o��+��yLMh���v����DTPld;�����S����V7m���>�N��L�<e�Z�6�LY(��������������<'�r_`��Q���������kn����.����������"_G����6n�����o<x��5k^�������{����3&�t�#�Z�_�:S��L��/oL�9-V1�*�J���]R-L�t�*6����v���������/����0h������SJ{4o����hP��]��U�����yi^���o:����.�;
��������.���k�����(��!5���
2$-�{�;�Z���i����<���#r~���s������[���Q���Y����j������g��S�n(72�Z#�T+���$��ls������X�[��]����J�����+�L_��8��L�nof�|JKWU���^���d�3gN�iM_d)��L�/og���^��8��v������IM\: ����3eyV��Z��y���������
�.�+����T�����'W2�.����p�l��-?����\%�����H�|AS��}�������cf��m��u��V-�j�A-]R-,�4���;�[����f����B���d�5��?�����|H;�{����?{���n�S���|��W*z�Y�������
�����������Y'��aO���(����|����;�n}�9b����m�|�R��M���t2��
�ja���1��6���jaz�'�|�����v�|������A�������!~��W�X�6��g��)m�l�
f:�j}�eC����.����6W����'?�I���������k�)K�,����R���?�a�Gu���G�5m��:wk��}���7��>w��7n��Y��]��k����NV��
0���n*_�����nH�47-3r��I�&U�QZ%u0���-���Sl������������V�X��N�^{���S7*mm����i�:����Y��u�]vYqx/�����OSrM5���x�f#�~��b���5�J-�^-���#N�[:.�����??mI��}�
v�-���1��0��?����Y�VI+��������*.N�9s�%�\�v$-�>��k�v�]vX-���Z��{��������V�����8��z���1����@'N���{�+��"oF�#Y�[jaj-�ZX!�����z��]���|�0mFj�R$��������!�Y���l����G�����b��!�)�>}z����j��nO�����{�m���N���O��i}��6GZ�k;����=�t4�/�����K���[g��]��]�����<y���_^��%}4��3�N��y&��UW�]�j!PP-
��@A�(��B��Zt����_z��_��9���}�c'�|�����l�����S-_������w�����{wo��6m���|�;G}t��=?��SO=u��1�6m�����&M���W�t�x������q�UW]��/9%%-|�i��~��;s#���?|��g����)��2j��tL*��y�
7����������?}�Yg=��s���@{�Z��K_�����{�A�z�����g���g��z���u;�#�<r�������V-���������v��g�y���zh��������_��[�3�]��?��?���Z��t4N;������~��?��b�~����������W�z�q���CQ>O��Y�N�b�g>���N:��CI?������{o7n?����>;��O=���K�S^y���~��i�5�\����s80�l�^��
��U������~4������������N������m��;w��>�������wS
�T�9�����l��b�SO=���},M�1c�N��n�����L��O~���[���E%p���y���;/M���>5}��b��U��������.R����o�������k��V�^�9��\x;���������7�y���w�j�e�]V#��~�UW������n�����k�=���o�����_��_��.X��������*O���[��������&���w�����O��A���_��_�A�)��y���W������e'm1�!?���S���F����>:������������]�ZXT{����WL�8qb����}�[�jgz�����S�\�Zx����Y}����[���s'O�\�7��'?�I:,'�|r���+����/�p��
K�x��i�	&���:�O�>�?`���Y�w�f�p�
;���.X-?~|��SN9�b�W\Q���[���������m�u�}��������5���������_y����U��~���_����=�b�JR�@��S=�����^�{X����z�K�u��UC:���U-����������u��������;�����|y����n/k����>������_{��[R�ZX<���^��/~��o~�����|�I'�5j�=��zt�]a���?����1��'>Q=��B:hi���>���@�n��u�����g�@=����b�Q-��ja2k����6��rJ~&�a�����6E���L�F�����'�����I'�T<�7�-[�t���Z��������?��c��o��������.\X�%K��i���uc���xL�8�zVQ9����b�Q-��j��u������?|�����5kV��f-����7o.��x��w�����c����[7$@���W_�'I�^��������M,Xp���������c��?��+v���n��\�����������n��E��;��#�8���*�l�.�_-��ukQ;���*f
>|�=<:@���f��t�0������g�g�L�>����dQ*���]���������=zt��s�=7����W�b=���X-�����.��?�S�����/M?��c��_��XO�jar����Yw�yg����z*M���;��
	S-��������~���k+fM�8���Ns����.|G�tc�������(��rr�M7u�.��Z����N8!�����[1}������f����XOST���/�Y��v[���7l���w��x���[�v�ai��x�������i��\}j;�����o�=u�O;�����6m��'>�f��=����&��n�q�i��L�R=��#_���VST�>��4k��!���4�����[7�����7o��w����}m�����l�r�A�#��������{�G?�������!PK7V�z��b�/�P�����,M���>�u{Y�ja7V���9�b��/�\��81�
MQ-|������>����bt�����t���}cO<�������^\��,Z���2o���:����1cFg��E����Nz����)�=��QG�&�z����m;YwU��5�\S�w�|������Z�|����m;_�j���[��Hs�����������b��>�s�tg7n\���={�?>?�d���������o�%�'�y+T�)�[��/��/S�������b�Yr��gw���?�����[E��g��y�7������w����<��������i�������3�8��#�����?����Kq���[�}����S����|��W�9���@�^�����_��w�������[�������tz|��_����s�8\,(�6mZ��������e�����#@#6l�p�e��x��|�a�v�i�U?���j�������W����w���[��������>��#{��y���~��_<x��e��{�v���9*�����[�����g>s��~����~�.��I�&}�����'?Y�''�t��a��/_���������������i������'?������{���p�g��9�z�_���_�������8-��~�}����3gN�b��������x��������>�|�+_�4iR�o=v��N8�����{�y�a�����X�������@�^x�g��---���{�^��>������K���}������K^�����[�u�A�����~���~�k��z���b�>��>��4��������/q�-�
2����<��4�G�Gu������{/�x��nvg�����}����_�����ZLY�b�����&�������YSL|��w�}��v�m�����-[�0 -�'�'���+&n�����O��_�u��������o�=�����3�<��w��qi���y����O9��4��SO����Yh��y�ZZZ~�w~g��%���W��c�=��|�����}/��������>M�����_o��������y���b}��M����o�)Gyd�2n���b��/�����4����d]�M+W�|��������Yp@KK�=��S������_�N�Z���W_���|����g�qF���/�Xl���i��{�]8|�����{����o�]������6/[�:�.�^.����n��V\����o�\�vm���<�LqQp�k1���g��������C��O��z�#F�Y���7km[g����'�8��cZZZ�>��b��O>�~���>T����K�B��U���{��W�y����K���+�������C�I?�~����M�0!�:��ckm^g�q���z������=��Q�F�Y�����V��q���Z��k���.\X��g?��|����;/����|�z���9��Z���u�F����]Q��m���;��l����5q��4��#�hs�=z�����_�jU�
o��F�b'�xb�u�u����>�������M�:5��o��jmgg��e���^{��?��q�W�0\�z����.\�����7�t�����^���[�iv1
�(��a��>���������_�M��~�g�}��\�dIQ!\�fM�����y��Y�K~���Y:th����F�b���O��;��Z���u+t��	@7h�vD����[ZZ���/���/_^~�I���?��������GuT~�I��-[�B���?�~���;k=�d���i���������������db�M�LB!&��o��	_��W����?�����r�	'�z����x�b�#F��_����_�����_���S��3�<S�N��eK�u�����=��c���K�r�)i���#kmsg���nCL�	1�&D&��l�w�m���������e�*f�t�I�����V���e��G���|����{��'�z���'��������������F���k��-\�p��w��������������db�M�LB!&������>��[ZZN<��\d��aC�~��K��N�ZL\�h�^{���\}��[�n����&�������}�c�6m*K��9��4��3�\�~}1��[n�m��v�}������..(��?��c�S�.]z��������[�n�Y������]hF�m�I6!&���$b���6m��������������=������(V\P|�����}�K���������������3����7/�J�r�!���v���n�x����y�����g�j��G�r���L�e�#�<��u�f����db�M�LB!&�l��������W�^{���������|�k_�Z�-
���z��_���?��=��c��������^{��<���8�����>���N;-�0~��N8��@z�#�8���.�#�����4#�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l4�6�$��lBd
1�&@s�nCL�	1�&D&��l6b���W^y�g>��?��?�c�=z������3f��^���������?��?N����~�������S������/��/x��������>_��W&M���[�;��N��?���{v�a���+V�hp�;�.�vb�M�I6!2	��ds�V�^}�	'��������C���>�{��{���w���;�(/y������ni�A�g�g���_�y���z�����=�������?��?���p�G�l7d����>��3��=����?������x����p�;�.�vb�M�I6!2	��ds��:����������'�,��\����OO��g�u��_|���w�}��v;vl1e��-H�����I^l����~x������7n,&�w�}{��g�=�y�������K�}���W�^}�)�����zj�m���@p�m�I6!&���$b�����[���{����u�]���V��k����x�����}/��������>M�����_o��������y���b}��M����o�)Gyd�2n���b��/�����4����d] 8�6�$��lBd
1�f}��/:t���l���bVQ��#	�������S+�������O>����3�H�^x�����;7M�{����/��R�u�=�|���+�������e�Yg���nCL�	1�&D&��lv�G>�������'���|�����k���X��g�).
.~-j�m>��������m���������1"���7�Yk�:�.�vb�M�I6!2	��d�c&M�������|�
���O�_?��U/�t�����j���kq����������W��y��!���O?�z�	&�Y�{l�m���@|�m�I6!&���$b��x������o���b�����~=��C���qcQ-|�����.�^����l���y���~��w�S�X�^�rH�����@|�m�I6!&���$b���z���>����������[�8q��4��#�hs�=z�����_�jUQ-|��7�;�������.�|��g�M�^l����3�kmag���nCL�	1�&D&��l���O>���(n��5Oodl���[X�W����6����u+<
������.��[o�k��z��Q�L�i��������>�k-Y����Y�&�����?�<k���%?��O�Y��sO�y�����o|����?>�:���jmgg����'&������������������;���z������2){�����}����������2)��eKQH|�����w�y����}�g]���WD��@W�J���V�v�j{j�����[��Z[�{�6� 2*�e(SV�+a'�����@���?-�~�����[�H��sa���3���+�N�r$���+��w����>���X >�
1ib�&D�P�I�����z�H�"e���1c��������8��1c�|����;�~���~��c�|��q��]6g���g'���|�n����+����]y������3���3�<�����6!&mBd
����O-Z��x��%J��9s��\V�n�O>m/77�Z�j�<���#F|X�j�����'�|������-��rK�-�{���e���+Z�h�"EV�^�)���y,�����	1i"S(������G�}��O�l���%J�(��W�^�/�r�����~�������������u�M7���?������7���+g�uV��E���N���?P\�l��S���u��;�����Gy��ex�������X ��6��M�I��B!&m~�����_Hx�
7���4m����C�=���.�R�����^�b��#���������-;qW�eW^ye��g�uV���?�_/<l,P�Z�[o���4��o��{��kN�����'��Id�!&mBL���
1i��
6��O���������5���T�R�b��T���O�]�������z���.�����+�w�}'��1C����;��)S�D�����U�V'��X�d����c�$���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i�_�p�����g�q�o���]�����\p����\����/Y�����Y��/�K��U�9��
*�}������?�p��w�-[�x��_��W����k����<�����6!&mBd
�����������{����8�d�����;���
.��������W�\���%JL�0�����?�L�2w�/_�{���u�]W���o��c�������<��n���;�(]�t��i���9����m�I��6!2�BL���v��}�=��q�7�x�������fgg-Z����0`@�-���m��)���/<p�@��999�\sM����_�9Rx��Q��/~��g��3��8p����*U�t���{��{��7��������<�nCL����	�)b��?5o�����C��k��d�����
�z��G?v����^p{�^�
?|��7
>���krrr>zY�&M
n���N�R�Z��[���v��Y�T�����8!�����6!&mBd
����Oeee�������ia�*U
��8q��n���W��?��O?|���>l����.[�ti���K�.|���+
>,^���C�>v�C=�l����X >�
1ib�&D�P�I����N�m�V�����������S�C��>����I��\�xq��y
�����O^��s���~�������<�����6!&mBd
��������p���W�X����uk�A��={
>,Q�D���-����_}�]��
+x�}���?��������_/����o>�'�y�g�!&mBL���
1i�39�i����n����>��#G���]������������v��_6��Q���{��O^V�����+O�I~����m�I��6!2�BL��LNvZ��{��~�u���G�y���fee������p��-���?�A�]}��)x�V�Z�/����&N�XpW���O�I~����m�I��6!2�BL��L>�s��[��<�p��A���������y������_<;�d��3g�,��B�
�|����O���W�a��%�_�p�'����k�1bD��:t(x�����'/2dH�]��r��>�����9�_�����';-��s�G_����M�Vp��_\��
7�p��L>*77�� 133�����~�d/GR�9��w�;�'�y�g�!&mBL���
1i�39�ia�������1c�|����;�~���~��c�|��q��]6g���g'���|�n����+����]y������3�����<�����6!&mBd
�����|�ia��u?������j���>x���[F�Q�a��U>��+�|��������r�-��������[��h��E�Y�z��|����@pvb�&��M�L��6?�O9-\�~}�%
����W^^^���7y���n�����=ZxY�]7�tS����<Xx�+��r�Yg-Z4++��X��e���:uj�-[�n���;
n|��GN\v�������������nCL����	�)b��?U�^������+�������W:����.��J�*��~{��/NOO���l��w\v��W��Yg����c�������U���[O#o�����w�����L�<y�g},�Dvb�&��M�L��6��_��Wg�\���x��Y<�@�J��+V�J�'�xb�����37n���SO]v�e�U�X����;�$��2d��w�Y�L�%J\w�u�Z�:���B';-�W$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(��M�d���6!&mBd
���	�,vb�&��M�L��6��nCL����	�)b�&@��m�I��6!2�BL�H�
1ib�&D�P�I��b�!&mBL���
1i Y�6��M�I��B!&m$�����	1i"S(�*���������X>g���+>��`��Y����z��:����M��o*�I��6!2����]��l��u������/X�����OOk;e\�	#����}������{������7��|����&�T������.���bF�r�����[jK��{j�����|����	� �M1ib�&D�P�T���m��5��,}m���K��.Ww��'f���C��6�'i}o���7�����N�LK�bF�K���(�Y����e5(��^�M�K��Q�P�"����|��{�H�����	1i"S(	�S��E����l��y=�Mm�r|���^�������w���m^�o��v��NW�owYF��5���i��Fe��?oS��;j���������/����w�	� �M1ib�&D�P�-m�����iz������z`�3����:������y�7+_�Y���g�����nX���%�.m[9���M��j\f]�R��;��W3a�{���P�"{k�Y�����olP2����	� �M1ib�&D�P��}����������v�����v������{F>���_oy����������]����+�]�������_���
���R���:���*���#�q��<}���Ew�>gs�������y+��j|~f�rK��_������2�^��������WyM�K6T�����v<����~}�#�Y���V<r��?<���'=Ucq��K4_����v]����6��� &mBL����l���X��qZ���K����?�]����c�������=~���-[�����U�_��������-�������z���.z����|��m��w�:gS��k��Z��tf���4)��Y��f�7�4�����_4�Y����d4�ta����bq��.����O����+��'�/.~�����I��8�A����t_��w����Y��;���e���i����wt���U�����������w�M�d���6!&mBd
=v���<;�����yz������4����{8��_�
�Q�������{�^��C��)noU~{�2;�������z���S�`�"G�>�������^dg�b���X]�����4*������g5�`z�����8�E����NmYej��S�]������_���i�o�Z����|z���U�/sj6�S?eN�N��>��������z�+�V�3z����&��1'}��e9kW�n���{W������D��b�!&mBL����/��!���u����[�?o^��)��G?����yC��xWn�[sz�p��Wv�l��{[���������6*���9�=T����_������5�m�]bM�R���,lTn^�
3�V����I-/���%c[U����6�����[]3�U�-o��[#��1���G4���f���/��7�2ub���:�8�������p���o��|?m�����\�mA��ks�m����T�|��	�,vb�&��M���-���*y���Ml�������!���s_>~�����]�9���#�m]�p�����{�q��
��W�p�"Gk~�����8{{�s��97�^�E
��i\!���6�xL�K�o]ex����������hw����^K���)��r���;������
J��A)OJ�;�C���>;�G�q���
>���M]2n^���k�eo�Z�s���>���~9��m���6��M�I�Y�B����6?�����y����o�3���������9������7�;��z��EGZ�?��LN�ss?����zg�[$��Y��O��������Ev�(��v�U��[������OoRiB��?hy�;�������R��z�������k�:����7_h����\�������:=�l���?S�����?���>}^0�������1S>�:oRF�����l��f��m�:�__2�������6!&mBd���[�6���� w�����9c��������t��?��u[��7�r��U��\t�U��-�mvnN������68;��Y�����y����7���(��V��u���_fA�r��T����1-.�����^1���}�_�B��{t�z�.7u�|K���v�zgj��R��G���~��V=�������ul�r�g^y���
>���~0e��yK�gnX�=o��������V����'@��m�I��6!����r�������Z���)��?��mN�{���nN��v��H�eG�^x��{���������g����
_ecc��+�������������_�~�K�nS����^J��W���u�zj���u�f�g�����M��a���n�����?T�����V��r�z�;5}���o��e��^��H������2���^�p��5��8|��8��wO�d���6!&m������ss���7g\����s�>�3����w���vN�jG:\y$�����6/s���9���mX4�^��:_�S����FF�r3�T�����-.y��eC�^9 �+��_����:t��U��=��Z=o�����{���^?�K�_���=���?
���W[�uh��owo8��Vc_�4yX�Y�_N�����cV,��.{����l�{d��������'@��m�I��6��:�7gv���y����=�3�q�;�y�?s^�YN�;r��������#-�mV*�q���r���W����g�U?����[���(��V�uu�]^�����f7�8���c[T���m��������\�j������o4}���=���^�?����s���~�������?8�������M��V�?����>�?�j���f��k��A'��5c���Y��f�\�v��mw�;z�Te����	�,vb�&��MN�������y^���y���NH�Q+��Gr����G9=�����#��8���������������W�h��O����L?����7<����//���>?x��]���������h������_�U���������}���������e���3_�5���c���<q����2l�\�k��}���u���S����{$�����	1i�S�����[��.�_=1/����������d�+�{R�w��G��iW�H�J���=����F%�?�p��Gj9-���8{���(�)��M*}�����������)W��p����u���377y�[uz���^�?������G�~�'?��w
����������9�O?~��?����m��-���q]�O��r���f
~!���2G��=n��)�����y�������l��e����r��>8)�=��nCL�������{��5��f�/�7�_������s_�S���s��(��o�r���+�����y�=M��mTj_���;T���5�:��r_�A_����:g]�c���������&>���������������k�����x������������A����/o��;�>r������������Q��Qm�����g�M��av�^^����!�#�]1n�����g���p��,}���wO�d���6!&m~����sm���������=ol��w�����r��������v��W�h[e{��7-���y���[���ZE��(r�����������u�����oA�r3W�����������=:]���
��9��5{���w���~�����O�c�w��
}��7k��N��k����'Fu�1��F�z���r��C�,|gH����8�\������,s��5{7l9�}��}��+R(��M�d���6!&m&��]����o��_=%�;��^���.���^x����|�{[��yS�k7�\������U����m
J��Wb_�b�j�}�������O�}j�\Q����eg7�8����}�u��R�|)�����|�Gw����o��y����x��������x�o<��+��7����j���R������=�w�IR�yn���~�F��c�?����u��^���������v
1i Y�6��M�I����=��7�o]��n~~��G���j����n{��������>������N�ru�K�6�`}�r���V�����8�
�v�,��v��u�[������4�pL�K���lh�+�������������qk��w<��]������#����AO�nh���j���g�>�o�qZL�a�����`��	oeN�j��-��������������B!&m$�����	1i��9����n�>�v��%�w�yq���G�_���+�*����z|'�����~%�u����nRa]�2�����v��5�y�4�5}{j�\���z�^rwn�
S�^0�y�a�.{��R��B���u�Z��7�t�f���i���
{�U���k�y�������?1�����XsX�����n�i�������i�,�;n����/��v���;�>�s�T���
���	�,vb�&��%j���;�����%{��E����{���e��Y����^���~?Y����.7f��fa��K[\������e��?oK���k;T�4�5}�j�R������58~����^0�E����������~��5/t��G��u���3�n��mz���������F}i���:��l�z�f�����7�L�k��A����d�������fn��y�/��9}�
�D�&@��m�I�S�6���}��
���Z=-k��K�������q-���5��?�����~2��m3��8��W���<�e��M+e5*��~��uJ��u�����O���q��Z���=7�~��F��7��a��G���^���H�����v���N��t�����<��������s?�����/<������I}�{���w9�����g�{ga���u��l���g����b�_(|9i Y�6��M������#����f�������5?k�������7eR�I��N|�o�><a�/?���	=n����)��:���Z^2������_f]�s��*��F�S~.����~����^x7�~��F�f6�����[^<���#�V}��o��zH�k_���������w�u��o��{=�����C��O������g�}���#^;m��E�3��Z�w���u;������e��������6��nCL���>�������v��e;W���t���)�c',|k���L�>r\�#����^}h�����#��uT������6W���dV���_����uKm�]b��x�w�����S2�^�%
������f�Z\8�����^2:����Wk�;�}�����������j��^�~���~?�����6<����^z���F|0{������,����1w�������=!&m$�����	�n{���t`��=��X>g���+'MZ����GM�1r|����������������?��w�w����_���	-.������+,nPvU��6�.��F�S~.���~����6�)��^��
K/nR6�y�9-*�hu���Mj{���*�S/���1�����;~kD�;Gt�gx��{�����;����������7e��%���Y�p����Vo���;o��S����wO�I��b�!&m��8�sh�����m^�k��m���L������������	��l��>������>?���#;�4���c�\9���S�]4�q��
���w��:%w�(v�����8��(��N�
�J�jx^V�2K��]����V���4����R/����i�.��zuZ�uin�����~4��/�t���gkLy!eF��g|u��f��7wB���k3�n[���&}��'��M�d���69����U{�/��"}���Yc�.|s���N�6jl���1��GF���~?�����|cT�����jb�*S�_<�I��
�e�+����q��/�{���;k�\������jR*�Y����/iUvq����VX����v-H����jF���S�OO�9��������<9�G�9/t��R����>��qsG�/L����v��m����?���S��6�{BL�H�
1i����qh��cO�[�hS����g,zo���Nyn����#�~�����������~�;��r������zb���5�xN�J��e�/�����k��/�{�F����n�w��%�79wM�R�Z���U������H)��]���V��xE�e+R�^�Rm]�o�J�AV��w�C�3���h9�w�y/�4o�;��&.��l����n\�c���������wO�I��b�!&m�������w���a����L������_�2���:�{���w�:z�C�^��=�7��-c:T�r��VU�5�<�I���g�/�����j�_�4<�;T����E��=gK��\���5-K�j]zU�����Y�r��v���TX�������^���5�����wW��������[��nF�V�}���`�{�O��0}���
K�m_�}�n/��v�{BL�H�
1i�O�ux���[W�^�t�����f/xs���L�6qL����m����y���z~t�o����S��������iz����3�YS���Z�O��=\������{F_�s�6+���y+[�^�������hWvU���R+�N�hm�K���r}�W�������+:�lY��u�KF���}�e��#��A����Y�����|c��v����	�)b�&@��m�I����Gn;�s��M�7.X�r������3pZ�sS��L|���_����~1���t����7?��|z��}�+,kp~����y�y��A��:�����i�U-���n�2�~z7�\vj���V�^�2����+��\�>���;|/��,���E=�J��,���_X����#F-?3kF��Ek6���k��/�w�i"S(��M�d���6C�sd����l]��f��e���������I��N���><��/�����n����	��:����=���������m�]bw�b��\����������;�[�����e�,����Ym�f�+��Z!+������R/�n���_[���U������e��kq��3��L�%cH����p���i���[�6k��M{�<��'�M�L��6��nCL����9t�U9v�\�n����2��7�����M}��������{�5���v�qbJ�A��s�^t�}eW�;oC��;k;��i����k���%�7<v���y��-�d�>Y�rK�UX�ZiY����dY���������;}{U�f?��e=^��z��6��t�x���#�]<aR��+mX�z���y�N����M�L��6��nCL�,������������b���������:���S_ydb�&������M�p���k�Z_9�E���.�h\qi��+���P���Z��~��q��oK��}M��e�,����K��[�����J��_�����;^���W�v�ai��dv������|������x�]��=�h��%iS��-Y�|��Mv�������6!2�BL�H�
1�m�9�k��M[��Z==s���&��7�����N���}~5���L�r���7Mn{���W�8~�����������^����O��=P��]��m�W|}�����nV:�E����.n[~a�
S/X����,�t����.�|��gn]����,���%�kg����^�m���Kg��^�|����w��>p����4N�6�4�P�I��b�!�S������X�.;-{��K'�Y�~�yo��9��������O&w�}R�oLi{���W�,|F����r+��^_��m���;_x�`�"�k�Z������j\j�������*��M��*f��0�}���U�;_������7et�u�s?^���3�=�d`��o�f��h��K��e���b��������?�{�9�m�B��6��nCL����[�7g������	}����F�Y�����S��=���SR�����i�������f/h|���~�uu��Z�������p�"{j�Z����%��5-�����[�[��BzJ����w�<��es�\9��u��}c^�����;���3_z|�������`T�E�^6����2V�^�ag��}y��$����B!&m$���h�m���4-�����X�^j�k�f�����5���S;~wj�����nz�+g5�2���qT\���A_�R��A_����E��.��^��
��-m~�����9v�7/���*��TuN��fu�n�3����w�����}X���K�4X�n��c,J{w��������i��};��}�?�}"S(��M�d����9|(o����36�������hH�y�����3��3����Ro�����������yM/^������W�/��n�-�K��qz����E��9v����y���^����-����0/��9�.����Y����r��n�ft�yf��g��{N��z|��
���h�+�g��Z4}����7m��k�����/�/7�7!2�BL�H�
���������g�������wY�Z��~�������=��3Ro�����-�������}��g78v���N�]��:_xw_����:gC����Z�����}�[U��r��v�l��N�O���i��M{��i=�����/�f�+������.N�t������^��q������}�|���
1i Y�6I��o_���9��w��`�������j����<���s��3�����<����[;�Kov����s���^���K��Y���x������k���n��
J-o\zI���(7�U��m/�����.�����._I�^-������cj�{�
xp�k��y�A��.Kg���`����k�.��u��=���.�}"S(��M�d���By�w��_��t���������NY��-��Xz�_����9n����Ym�����y��d4�hQ�J��;������9P��S~.����^��mS�k�?�kz�������8����]<�}��N��u���g�M�q���o�������6������;�����f.��r����o����w�qQ���O� ����H�%��������SL�DcGP��(v,�h�D��`W�
T�aEAE�w�7a���}���Fe��z>�cwvfo����������������O��M@��P@��M(Y8o�yde�%%>�y�r9������cv/��ts�����_q�qin�Knmf4�4�������T�1�*db��?G���8�Kc�>�u��3�g�X>t�E�s�kS+L�:�Z�V�3sj��_������-N.�;������}68����{'[x��WX�o����7O�:���[��i��7%#Be"6�d����&/#�IB\�����K�������p�����B�.hY���=���xeV�+�M���^�Z����A�V�&V
�`q��,���/�u��{<� i�Q�����	�A��N���gG����f���g{�����-�{���rl��'������{'�?�~�����g�E^��MLx�����S�&�L�&�dD(�L�&�,��K����'qs�E����s�X��mq;Dmp_�}��~�{\�����6W]�^�n{}Z�S�;[��T)|B���f1����-�:�����^�_�h���&w���`~�����4��3���Y�gv��sm�-h|tq����x�}du��>9�u��^'���[�n���w������������W�������������������}�1��wrn��=�qxc�v��#V}wkI��������&pF��.���jM���\%t�_#�����a�����/������}�N���R���?�����>���g{t~�#�Z��?����5=o�����'�N:}b�����C}"�]���LI�/����Dl�DlJF��Dl@��y�odf�%&<���{�v������3�O�Z�p���+�
[�7d�{����1��
�&7\���Z+x�u��*a�*��`q�����1��_����2|8��=�0'����L�|a���t�S�5O��96�������[�����������!��G�'��]�w����|��]���JOK*������2�����2�P��������'�q�������s�B������%m�������o":����o���:xF� ��i�nN��5�����I����3�W6y�Q�����>�L\AG�mG��gya��}��5���{dN�C��wo���������xox�k��}���,>}q��[>!����Gfd�������&P������2�P�(�������al����[���.e�J��&q�[�����������y���:���
�����M�����V�ly��R�D�{��9�Ov������Y&~���q�a������+?k�����{hv���z������=�����p����^C�{O:r�����A��]����z�Q��jI��	������������������<����s�F����'v&�Z��qf���q��w����������l:���iuoM�:�j�d�p�����&��v4}�P6i�Q�����5� q���q�n�7�P��s��S���X��Q�hAG��yM������~�g���?��~�n������\x����A�G]���H��|a�5(m*@��M@��P@��M(Y��y;+��&���q-�������v.��}z�/#-�"nA��9�"g����������	�V=lj��)�w&W�;��������I�X�����O�%�2�W.|�Y�S�+�,�M�:3����5���{`v�}���^�z��7w���}��;6|�k����'�?1�����y_�w'�1���������������������1��97od\<�r���]�6N����p����=B�w�9���YMo��O�u�����U��T
�lqw��}'���M�����Me;�$b�Y�S�+�*��luz��������vk�w^�][o_�����^�|�����^CvyO�w|���k|�\��x��������������T�2�����2��|��R��=���	>�v~����a;]7�|u����/,}�������:;�����g�p�qyz�k�,��V��\!|�y���C�������t(��������w|z�C�u��5�3������-������_zn��������N{��9��������]~� �abVrV����Wz�M(�	(
(�	�S^F����	a��^�x��sG����pr���~�wd����u9���a�V��79:���9u}f�:�Z���j�U�:�r��
�N�Q�qc��f����2|4��]���-�N�|n������]jr����`��������~����V��������z�s�u�m���c�v��=3!<"�~,���?�6�L�&�dD(�L�&��%37+1#6����;������<rb����w���q���zoZ��+:m�������{���W�[���j�Q�����)V��+9U�o;�$e�a�w������e��G�3
u��6������Qw��;�6���������������
����������������g�O]�	K��J���Juq�����6�L�&�dD(�L�&�W -;=.31*5&,!(0�������~�>���w���<��������]����5�����lE�o������M��o�iN}/�z�g�=�R�w���*�*�;�G�+�<�����^�_�H��������9��7�\����K���6f7�;��Nw�mK�����z�^[�|�u���g�9�q��f��o��������r�m*@��M@��P@��MEI�N�7�����kq!�����8x8�kO���/.���e��9��M���T�O�l�3e]���vs������,��K��/j�xA�Us�lpk�}�����OL�~n���������3Mc��M�'��qw|��	nL��<���i��f��������Gu8�����|th�����?8������l�~�?����.�}����
(�	(�	(
(�	�����c3��$G�����v2��w������d���sONt9<��{��]�������C6����Ok����Q��.�0y���Em�����t���^3���^������^�X����=��1��#_�)��G&�-�`�h6�r�������<���Y���kw�����^g�:�y��=���x���u6�AH~F����r������������+37+.3�n���	����8p(p���Ek}�/9�0k�O�����y���^���k��n��������7'y�w]�v�{+�����d���q}.���M�zi�e�S����y���5� e�q��r����M�t��Z���!.
�f���!pQ�����ur���Q�'���{#?>"?-�������6�L�&�L�&�dD(�L�&�"��5�Qw��(J���GQ1a��N\��u��s�1����{
Y������^��_�Wt�X�a��v���^��b��f��k�vN�M����as�������:[]�XY���f���#
�G%�+�`�T��D����FLmr��m���#�������q��<:�)������������O}���Q���W��6�L�&�L�&�dD(�L����_��K�.+V,[�l��
���������Sv���v��>�q��23���D���s;!( �����W�������G~������]���K;�Zd�ca������h����f���Y���������b}~R��*�:ZD�3�{���i���(�9�0m�I�8����9U8�^�����o�������+|����]K��O�|(�����W������?N+�u	�yP&bP&bP2"P&bS��R�J�*��U���;����U�����ZV���aw���3���(~y	�r�^yp�;������.n���/�<z�v��|�S�[����o�������T�8���)U�9W�X1��<r|��q&���^�'q��=�0sT��1f�c+'���<�A�s�x������>�����O���0�������C}������'F��)���yP*bP&bP2"P&bS�6l��R����dJjjj�^�Db���_^Y������������o���$�?~����z-/�\b���;�o�v.������{���d����k���l����EM/�t��	�Z�\���^����I�B���9�9�/�5z��_�H��QF��MR��%;TNr��8�^��f����\�?������>Z=6~�����i��f_��z2?�|~tP~�����b������
(�	(�	(
(��X��7W�T6l�LLLL,_��H~Ie�rBo>�n'���q������������}r���#��
������>���lvdY��Km�-������9u��u|F��S�]p�8�R�x���&��^���2G�Ic�8�$N�;�����O�5���K��3����^��ObW��}R���qG�'������b~Lp~B������j��e"6e"6%#Be"6�)<<\�R�-[6++Kk���~*6��3�e��t�Rh�'-v�{|��L�KI~�t����#���b�}��������C����S��M���l�x�I�$��	e��R����Y��{�^�_�h����1�����L��l2�:���
��n-���X���������������-����[���*�o7��@a8o�Dl�DlJF��Dl*��m�T*�������Mxe5����qY�.�nO�xmr���UoM����������/k�A�h�h�r��7'U
�\�����g�����w^w;_����z�^?����g\�Y~��W�-��G���)�������6�L�&�L�&�dD(�L��2��3G�R���_w�������m��QVS������W���Q�qcM8��;U�5�*hr�kSm/�6p������e]Z���M�����m��\j�mF��u�yP&bP&bP2"P&bS�&N��R����;�M��lmm_FYMg�������Q�qc�F�3�3�,��B���7&T�>���Iu�Mn8�U���n��w��O"�
}�~b�������\=�q����p������������T�1c��T��~�Iw�����T�F��QV�������
��Ketube�)�G\j�u���f�a^�5Z�X�v�G�y��f��5�g^���w�zz���������F���e���9��yP&bP&bP2"P&bS��v|`���_FYMY9�~6d�({��o��w�������m���m;tn����
4w�\�J��_?�M[�l����^FY-������g�^��;w�8777����>{e(MTT�J�222JO����W�^b����_FY
dgg�R�V�Z��ehhh``���PyCq�����d��G�:w�,���ku����an����e�#F�Ph��y�LLL�r�������ye�S�N=kY%��-[�t�baaabb��i����gffjf(��P���E||���S��M��-kbb��q�1c������\�~}�.]*V�(r6l����!))I�W�����w�Z�n]cccKK�=z8p@+���o�����}����u����akk[�v���T=�P��3g�
<z�Hk�>�S=����1cF�-LMM�������.]����<YYY�G����622j����m�
}��+W�w�d�=�P�;v���;�&*_���Y�fZ�������3�q��UE���QC�����Zy<==5j$2��Ys��iyyy��	444����JKK�U���Em%���v<x��n���'p��gY}�NQ������B�l�u�v���B_q����.]��%��sg���E�o��E�y��E���A�mD#G���O��6mZ�L�Z�Z���0����%�K�*��U���;����U�����}=�^�rE4��&Q������`d���9s�y�Q�������������{�=�Wttt������,7n�-�B{�	���Y699�e��"]4��z�-{{{y����sss�����{q-�l�2q9��g��.]���W����+T� ����J��c��z�M�6"(D�$V;u�������T�k���&7u��U���xN�<���q�F����?���-�]]]�^N�d��	��������Slll�&M�7\\������/����h����K3�>�S=��Su������j�����g���^�J���D�W<p��(�����>��IKK�B�_��-|��E���A��Z�h!N���%CCC�5k&{�����a��bee SRSS{��%{����W���87j�H$���O���2���C��-ju�1c��<�o���...bU�wXQ)�����~�|�4":���LMMe��fo���S�n�,�����l���u,b�~��"q���2%!!A��_|!W322��+�;H�_�~���E��J���7�/���/_�,S��A���E���s��^A�)"Q��ZY�~�L5������O��Ll��M�����	�u�V�J�����C����|��P�A���q���5������+����=�P�������g�X]�f�\��������V�n�z��i�(V```�
��Y\��(����^$��.<�'N������P��G��tq2T�y�E�8�kfKLL,_��H��z���m�X�s��gggY��Uq���To�?�j^������mB}Fn%��Y���|��i�n���3p
�gYJ�l```��M�(�W�.� >,V=<<�������f���w�<�&Mz��(�������o��#G4���93|������S^A�)^Q��k���:uRW�����K�/��r����7�)QQQ����T�w(%���������=y�D�,R�r�O�E��zV�'N���E�[��=z�H��>����"W�Z%�{��QTo���H,m]x>�q������D-..N���{��X
�������r�s����_��/��...Z����HW1���z��5n�X����b���S�)�����k���%���Y�f"�t{��B�YVD�X����������s���L;#�7o������*UJ�����R�f��
fff>�G(���g�W�E�O��j����k�U�l���"�����/��I,:T�u��y"�����>}��?i�@"^D�#��"��6�{7n�(W�	���YV����o���?p��������U��500��S	Poo�������z_�Eb�h���%������D'�������`��i��E�J�����B���SX���u�j�����M�'O�����>����<���/77�}���J����bU��P��)��e�8
GGG�l�n�������~�M�%���s�
&T�����(���o���O��
�N�O{��'����jF��B777�r��1�����y1%�~�ZB	%Z���|��!�DQ
������/��8�����U���M������s��rY�c[�nmii)^7�`�$](q��-|�����/��G�o��rU^���_7���h��mQ�����y����9�<�{�������R��z�HTiL������-[6444$$�k���K�g�.]�h�o� ��~��	rU��P��)��eEX��e���f�"�i���by��}Z�DtW�TI.����x������Q�*�nz���z|��|��W���
���(�Z�^=����l���<w��X����YB�i������j�M>�EN����dmm��i���{{{7l�PU0E��_~���
()���/������|P��3Db�����S���/�g�9n�8��XF�z4y*����E����e�]�~�������[��/E[^��'O�+W.$$D��9U��O����������Y6;;[6��[�$g���Z:T,��sGn����,�����,N���G\�����\�r����.VE��~@�


���*^}��Vo����K��rY\��f�.�oz��A�R����+�)99Y�IDQ�V����V�����z�jy)�c����e���P�������MMMk����W�N�:���������S.�����{��������[W�������LV�?�����3g���)##�-Zl�����E$~�������-//o��1�����������Z�j�*x^�z�����K��zV���I�����$��M���',���FE0�tQp���m���Zh��@E����D]�u�:t����(]��h���c���'����m5j�(j�z�MII�'�����������/���������������-�V�E�0>>����e��999��oWiL4�f�������P���A��z�]��m���X�<'����4H�~�����n�����`J��9�C��E��j��S��X�n�f��=�3�,���.����4i���2�T��i�M�6-t'r������&*;v�X���~��g����+��)*�G�|���1���P�����aBj��Y�l�:Z�]�����LKK�Z�j��5E0^�|YT�&&&��Q�u��+w��Q��`T�[��F6l��}.@1)����_$���/�8[�)SF������������X���>?���M��e���
6��6�M)��"��R�����#F��9J0{�l��urr�L|�����N�Le���Vu�GGG���������H466���W�_�X
8P�9^"!!A��P�.]��
�r�5���'�7?)))��T��s�.�V��h������������qcq9����_p;����zrh��;��X%X�v��Aq��i�&Q%�J���sr���]���w�G��e��:O�:%� XXX���3����,X����;+W�T��f��-[�|�(�=��9.����.//���A�R�=��u���bS�~�tn��El������r������@��r�����:E\��>}�����b���c"��Q���O>�D��s�\���������	�"�An����s�t�-|����g��={�e�l?����$���7n������c�s��o�mff&GJ����E?~�H�r�JQ	(��~(��?���V����_�D���J������eKKK�l"��LZZ�:Q����OXX�\�<y���k�.�Z�jU�����/�.Z�����&&&�|��e���z��f����k��g
M��}��3;;[����O><�������(��b�
���&�N�
��H��WTo�K�H�B[�	q��Clll��M7���;UE��.���g��s����etg�}���<���u�������_�~�:u�M���{���[N����S( �����������Dz�^������������#��=j��j���^Bl�.]*W/]��*�yI�A�W��G�a�����0�R�vm�_�c}Ugbb����}"��)�^�z��^B�R�~�Y~��!�z�-���N�������Aw�&�?�0����e�I�)�L�2�/_��.�>����sgcc����RTo�+�H��,m](�������7�P���%**Jd��OM������s��~��wbU�� ����K���Id���:Ekl�xi���Gu���|����#'Zy��������.V;v���-''�b��b��(����
*�����c���U�j.j�m��AU������\CCC�I\)�����~��b���#Z�,X���///�������x���:Qkl�����P�%K��/��tt7��;���/p���sW�T<GI��;����N��)	(GQ����"Q���u@�|H�F������M������8��+#����^V^���[W���r����_�����L�2�SC��5�[=N2((��_���E�N���g*+N����J�R?�@��84hP�����/������� ����O�))r�4�DHHH���#�afff�������� Z��5K���E������e�T�=
Z~���VVV�����:P,���9o����|��Le���G.*�z��edd�����-Z}����[���/��,m]�gnn^�t���HA^U�X���O�<z��s��"���������6l���>k����7�xC$<833S&������I��������e*U��5*R6������3�L��P����m��Mu\<SYy�F�6m���/S._�\�Z5��n��BU^�9;;k��o����Zv�deeYYY���?��,�V�Z�'N�����g����1��������I����)":�`4y��������=xq��������m�K���{�'�%��H����~�9�����
T���8�U��e����O���(�Ps�y�����?���W�)��/�"��.�(3g����e��-�z����fj�7o��C�Rj����%rv�3fh&�Y6$$�J�*���������X'��~����www~��W��'O��S�������uY�D����z�lu���9��K�7�|S�0"<��U�T)US�	)))�j�j����SZ��j��//��>���K(��G��]e*�z�-y���Q_�H�T���N�:��e��[��)SFl�]���buDu����ccc�i�###���Z�l).��# ����>&��;~�x������F�}������E�%�H�fN=���S���Zu^�x���������$C��4i��M��	�B�
E=�P2��Isss,��-[��s���D������O!'FS��.]�XXX�3y��M�O��uY�_Do��e�&6lX�:u��Z��EKO�c�q]cjj�U�=x��_�~��(�}���(X�����N�-(=�
�?vssm9�����c�
6u���M,�B��]��A���Dk���������Y�p���5Q�r������u/������-���t����?����J���"2d�|2��m����)t�����V266�V����S�C�������5�������^+����NQU��A�����+N#���������=n�8�r"<�N����Y�D�W��9�/��^$���������T������W�Q��xE��4Hqss{yG�e�6o��O�>�)/��p���/�(������4�����������<�����-�����S����-^���[���+v��[��egg�[H�������V�Z�L�J�*�n�z������Z�������������Pd����|}}53�[���������������2$<<\k�yyy���������E���[�l������*��;�5eff�k�����njj*��I�$6��1#���D���v��iff&N�8���>}��M������%����U*���A�n�����U�����['''���9R$�����~����X-U�����:�noajjj��Eb���
$���Y3�jnn����y_|��H711y���z��iii)V[�l)�a��Y"]�4h���@NNN��[(��~��g�7+��8T�E��[�y��o��V������|���"��/���ORR��&6�����P���<�/w��u����{��%�=�[�n�*T�~��:������


���d�no�O?�$R��k��(^���E$���dgg��u�����w��������;���Q�,]�T�Nd�����������kMc(��H{��ZO9�H�j��|��9�R�\9q����N��5���"�>~�X3=::���766V��o�^d�7o�V������#F�U�����9���Z�7o.�w��!W��m+VEq�<>>>u������%W���0''�J�*b���S�yd���U�����
-[���W��L����H\�vm>���U��J�2dH|||����K�.-����8p@��j�J�j����W�ZYY�����Ql9rd~A�e�R��jdd�S��o{�a���w+EEE���7��[�x�b���cGuJ\\\�2eLMM�S)������T�2e�t��i�������7�^�zU>d��A_�7���r����Z�����r��_�����z�����'O�<�8��-����"Q}�.)���W���0>>^��		�)���bU�3}�@�:l�0kkk���mmm�n�*�������|��Vo�����K��{r����O?H}z�z����3g��U�-�g�u}z����	&���]����'O>��
�d����-z��7eo���{���O����^\��P�����=���k����=)�������"e���b���;b���Rs�z�;vL���U+//����K�����z~
��@�+��;�����4�z�������-��V�R���������Z@����[,{����9s�����5���[(^���Vl���sww...O#@��|�r???�t9`����j������n��{���j�&%%��=�U������3���rU>y��9�y�\�"���������-����f��B��7��W�^��!�?^sk����������3UO|n��]�R�"""t�����T�&M���_������O?���}��///�jffv��Yu����v����e��������R��E���u����+W�l``p��5��n�:��B�
�/_�)�������H����e�o��&w�y�����?_$�;�T�R�5�z�Z��bU���������q��a��k,//o��r_��������}�����������9G�)
D�o����>������"��[�����cG����G
<�s���
h�$/�*x.����G�J�*������2�����
�m��/!G�[x�����K�����j�e��Bq���U)u�������b�
���z��s*�_���|�@�������;W�T�t��&&&M�6=z��hCi���={��R����a�j��v��v�ZQ\�A��Px�����K;t�`nnnll\�v�~��?~\k�yyy��������&�okk��������g����u������w����"z�w�yG��s���&��B���#�5�oj��5��w��%�:�������:���P�TC�)�P�222���S�T�����>�&33��O>Q�T�~�iq���u��>}���YS�R���<z����@�X�d���a�
]��P����8o
endstream
endobj
15 0 obj
<</Filter /FlateDecode
/Length 141>> stream
x�����0Dw��H�q\'����,�#����%���d�l�Y��f�&����E.iu�m&����rL#5�`����#�k�t�
���)��1#h.�i��e���b�65���Q��Ki�,8<���.�\Y�_�t���i7���8�
endstream
endobj
2 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R>>
/XObject <</X4 4 0 R
/X6 6 0 R>>>>
/MediaBox [0 0 612 792]
/Contents 7 0 R
/StructParents 0
/Parent 16 0 R>>
endobj
8 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R>>
/XObject <</X9 9 0 R
/X10 10 0 R>>>>
/MediaBox [0 0 612 792]
/Contents 11 0 R
/StructParents 1
/Parent 16 0 R>>
endobj
12 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R>>
/XObject <</X13 13 0 R
/X14 14 0 R>>>>
/MediaBox [0 0 612 792]
/Contents 15 0 R
/StructParents 2
/Parent 16 0 R>>
endobj
16 0 obj
<</Type /Pages
/Count 3
/Kids [2 0 R 8 0 R 12 0 R]>>
endobj
17 0 obj
<</Type /Catalog
/Pages 16 0 R
/ViewerPreferences <</Type /ViewerPreferences
/DisplayDocTitle true>>>>
endobj
xref
0 18
0000000000 65535 f 
0000000015 00000 n 
0000397371 00000 n 
0000000108 00000 n 
0000000460 00000 n 
0000000145 00000 n 
0000058065 00000 n 
0000106646 00000 n 
0000397593 00000 n 
0000106857 00000 n 
0000180627 00000 n 
0000254647 00000 n 
0000397818 00000 n 
0000254859 00000 n 
0000346860 00000 n 
0000397159 00000 n 
0000398046 00000 n 
0000398115 00000 n 
trailer
<</Size 18
/Root 17 0 R
/Info 1 0 R>>
startxref
398234
%%EOF
#21Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#19)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 29, 2024 at 5:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 22:19, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 7:54 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 00:40, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 6:17 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 21:06, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

That's the number of distinct values matched by the query, which should
be an approximation of the number of matching rows. The number of
distinct values in the data set differs by data set, but for 1M rows
it's roughly like this:

uniform: 10k
linear: 10k
cyclic: 100

So for example matches=128 means ~1% of rows for uniform/linear, and
100% for cyclic data sets.

Ah, thank you for the explanation. I also looked at your script after
having sent this email and saw that it is clear in your script what
"matches" is.

As for the possible cause, I think it's clear most of the difference
comes from the last patch that actually switches bitmap heap scan to the
streaming read API. That's mostly expected/understandable, although we
probably need to look into the regressions or cases with e_i_c=0.

Right, I'm mostly surprised about the regressions for patches 0001-0012.

Re eic 0: Thomas Munro and I chatted off-list, and you bring up a
great point about eic 0. In old bitmapheapscan code eic 0 basically
disabled prefetching but with the streaming read API, it will still
issue fadvises when eic is 0. That is an easy one line fix. Thomas
prefers to fix it by always avoiding an fadvise for the last buffer in
a range before issuing a read (since we are about to read it anyway,
best not fadvise it too). This will fix eic 0 and also cut one system
call from each invocation of the streaming read machinery.

To analyze the 0001-0012 patches, maybe it'd be helpful to run tests for
individual patches. I can try doing that tomorrow. It'll have to be a
limited set of tests, to reduce the time, but might tell us whether it's
due to a single patch or multiple patches.

Yes, tomorrow I planned to start trying to repro some of the "red"
cases myself. Any one of the commits could cause a slight regression
but a 3.5x regression is quite surprising, so I might focus on trying
to repro that locally and then narrow down which patch causes it.

For the non-cached regressions, perhaps the commit to use the correct
recheck flag (0004) when prefetching could be the culprit. And for the
cached regressions, my money is on the commit which changes the whole
control flow of BitmapHeapNext() and the next_block() and next_tuple()
functions (0010).

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

Just confirming: the results are for uncached?

Yes, cyclic data set, uncached case. I picked this because it seemed
like one of the most affected cases. Do you want me to test some other
cases too?

So, I actually may have found the source of at least part of the
regression with 0010. I was able to reproduce the regression with
patch 0010 applied for the unached case with 4 workers and eic 8 and
100000000 rows for the cyclic dataset. I see it for all number of
matches. The regression went away (for this specific example) when I
moved the BitmapAdjustPrefetchIterator call back up to before the call
to table_scan_bitmap_next_block() like this:

diff --git a/src/backend/executor/nodeBitmapHeapscan.c
b/src/backend/executor/nodeBitmapHeapscan.c
index f7ecc060317..268996bdeea 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -279,6 +279,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
        }
 new_page:
+       BitmapAdjustPrefetchIterator(node, node->blockno);
+
        if (!table_scan_bitmap_next_block(scan, &node->recheck,
&lossy, &node->blockno))
            break;

@@ -287,7 +289,6 @@ new_page:
else
node->exact_pages++;

- BitmapAdjustPrefetchIterator(node, node->blockno);
/* Adjust the prefetch target */
BitmapAdjustPrefetchTarget(node);
}

It makes sense this would fix it. I haven't tried all the combinations
you tried. Do you mind running your tests with the new code? I've
pushed it into this branch.
https://github.com/melanieplageman/postgres/commits/bhs_pgsr/

Note that this will fix none of the issues with 0014 because that has
removed all of the old prefetching code anyway.

Thank you sooo much for running these to begin with and then helping
me figure out what is going on!

- Melanie

#22Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#20)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 29, 2024 at 6:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 23:44, Tomas Vondra wrote:

...

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

Just confirming: the results are for uncached?

Yes, cyclic data set, uncached case. I picked this because it seemed
like one of the most affected cases. Do you want me to test some other
cases too?

BTW I decided to look at the data from a slightly different angle and
compare the behavior with increasing effective_io_concurrency. Attached
are charts for three "uncached" cases:

* uniform, work_mem=4MB, workers_per_gather=0
* linear-fuzz, work_mem=4MB, workers_per_gather=0
* uniform, work_mem=4MB, workers_per_gather=4

Each page has charts for master and patched build (with all patches). I
think there's a pretty obvious difference in how increasing e_i_c
affects the two builds:

Wow! These visualizations make it exceptionally clear. I want to go to
the Vondra school of data visualizations for performance results!

1) On master there's clear difference between eic=0 and eic=1 cases, but
on the patched build there's literally no difference - for example the
"uniform" distribution is clearly not great for prefetching, but eic=0
regresses to eic=1 poor behavior).

Yes, so eic=0 and eic=1 are identical with the streaming read API.
That is, eic 0 does not disable prefetching. Thomas is going to update
the streaming read API to avoid issuing an fadvise for the last block
in a range before issuing a read -- which would mean no prefetching
with eic 0 and eic 1. Not doing prefetching with eic 1 actually seems
like the right behavior -- which would be different than what master
is doing, right?

Hopefully this fixes the clear difference between master and the
patched version at eic 0.

2) For some reason, the prefetching with eic>1 perform much better with
the patches, except for with very low selectivity values (close to 0%).
Not sure why this is happening - either the overhead is much lower
(which would matter on these "adversarial" data distribution, but how
could that be when fadvise is not free), or it ends up not doing any
prefetching (but then what about (1)?).

For the uniform with four parallel workers, eic == 0 being worse than
master makes sense for the above reason. But I'm not totally sure why
eic == 1 would be worse with the patch than with master. Both are
doing a (somewhat useless) prefetch.

With very low selectivity, you are less likely to get readahead
(right?) and similarly less likely to be able to build up > 8kB IOs --
which is one of the main value propositions of the streaming read
code. I imagine that this larger read benefit is part of why the
performance is better at higher selectivities with the patch. This
might be a silly experiment, but we could try decreasing
MAX_BUFFERS_PER_TRANSFER on the patched version and see if the
performance gains go away.

3) I'm not sure about the linear-fuzz case, the only explanation I have
we're able to skip almost all of the prefetches (and read-ahead likely
works pretty well here).

I started looking at the data generated by linear-fuzz to understand
exactly what effect the fuzz was having but haven't had time to really
understand the characteristics of this dataset. In the original
results, I thought uncached linear-fuzz and linear had similar results
(performance improvement from master). What do you expect with linear
vs linear-fuzz?

- Melanie

#23Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#22)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/1/24 02:18, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 6:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 23:44, Tomas Vondra wrote:

...

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

Just confirming: the results are for uncached?

Yes, cyclic data set, uncached case. I picked this because it seemed
like one of the most affected cases. Do you want me to test some other
cases too?

BTW I decided to look at the data from a slightly different angle and
compare the behavior with increasing effective_io_concurrency. Attached
are charts for three "uncached" cases:

* uniform, work_mem=4MB, workers_per_gather=0
* linear-fuzz, work_mem=4MB, workers_per_gather=0
* uniform, work_mem=4MB, workers_per_gather=4

Each page has charts for master and patched build (with all patches). I
think there's a pretty obvious difference in how increasing e_i_c
affects the two builds:

Wow! These visualizations make it exceptionally clear. I want to go to
the Vondra school of data visualizations for performance results!

Welcome to my lecture on how to visualize data. The process has about
four simple steps:

1) collect data for a lot of potentially interesting cases
2) load them into excel / google sheets / ...
3) slice and dice them into charts that you understand / can explain
4) every now and then there's something you can't understand / explain

Thank you for attending my lecture ;-) No homework today.

1) On master there's clear difference between eic=0 and eic=1 cases, but
on the patched build there's literally no difference - for example the
"uniform" distribution is clearly not great for prefetching, but eic=0
regresses to eic=1 poor behavior).

Yes, so eic=0 and eic=1 are identical with the streaming read API.
That is, eic 0 does not disable prefetching. Thomas is going to update
the streaming read API to avoid issuing an fadvise for the last block
in a range before issuing a read -- which would mean no prefetching
with eic 0 and eic 1. Not doing prefetching with eic 1 actually seems
like the right behavior -- which would be different than what master
is doing, right?

I don't think we should stop doing prefetching for eic=1, or at least
not based just on these charts. I suspect these "uniform" charts are not
a great example for the prefetching, because it's about distribution of
individual rows, and even a small fraction of rows may match most of the
pages. It's great for finding strange behaviors / corner cases, but
probably not a sufficient reason to change the default.

I think it makes sense to issue a prefetch one page ahead, before
reading/processing the preceding one, and it's fairly conservative
setting, and I assume the default was chosen for a reason / after
discussion.

My suggestion would be to keep the master behavior unless not practical,
and then maybe discuss changing the details later. The patch is already
complicated enough, better to leave that discussion for later.

Hopefully this fixes the clear difference between master and the
patched version at eic 0.

2) For some reason, the prefetching with eic>1 perform much better with
the patches, except for with very low selectivity values (close to 0%).
Not sure why this is happening - either the overhead is much lower
(which would matter on these "adversarial" data distribution, but how
could that be when fadvise is not free), or it ends up not doing any
prefetching (but then what about (1)?).

For the uniform with four parallel workers, eic == 0 being worse than
master makes sense for the above reason. But I'm not totally sure why
eic == 1 would be worse with the patch than with master. Both are
doing a (somewhat useless) prefetch.

Right.

With very low selectivity, you are less likely to get readahead
(right?) and similarly less likely to be able to build up > 8kB IOs --
which is one of the main value propositions of the streaming read
code. I imagine that this larger read benefit is part of why the
performance is better at higher selectivities with the patch. This
might be a silly experiment, but we could try decreasing
MAX_BUFFERS_PER_TRANSFER on the patched version and see if the
performance gains go away.

Sure, I can do that. Do you have any particular suggestion what value to
use for MAX_BUFFERS_PER_TRANSFER?

I'll also try to add a better version of uniform, where the selectivity
matches more closely to pages, not rows.

3) I'm not sure about the linear-fuzz case, the only explanation I have
we're able to skip almost all of the prefetches (and read-ahead likely
works pretty well here).

I started looking at the data generated by linear-fuzz to understand
exactly what effect the fuzz was having but haven't had time to really
understand the characteristics of this dataset. In the original
results, I thought uncached linear-fuzz and linear had similar results
(performance improvement from master). What do you expect with linear
vs linear-fuzz?

I don't know, TBH. My intent was to have a data set with correlated
data, either perfectly (linear) or with some noise (linear-fuzz). But
it's not like I spent too much thinking about it. It's more a case of
throwing stuff at the wall, seeing what sticks.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#24Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#23)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Mar 1, 2024 at 9:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/1/24 02:18, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 6:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 23:44, Tomas Vondra wrote:
1) On master there's clear difference between eic=0 and eic=1 cases, but
on the patched build there's literally no difference - for example the
"uniform" distribution is clearly not great for prefetching, but eic=0
regresses to eic=1 poor behavior).

Yes, so eic=0 and eic=1 are identical with the streaming read API.
That is, eic 0 does not disable prefetching. Thomas is going to update
the streaming read API to avoid issuing an fadvise for the last block
in a range before issuing a read -- which would mean no prefetching
with eic 0 and eic 1. Not doing prefetching with eic 1 actually seems
like the right behavior -- which would be different than what master
is doing, right?

I don't think we should stop doing prefetching for eic=1, or at least
not based just on these charts. I suspect these "uniform" charts are not
a great example for the prefetching, because it's about distribution of
individual rows, and even a small fraction of rows may match most of the
pages. It's great for finding strange behaviors / corner cases, but
probably not a sufficient reason to change the default.

Yes, I would like to see results from a data set where selectivity is
more correlated to pages/heap fetches. But, I'm not sure I see how
that is related to prefetching when eic = 1.

I think it makes sense to issue a prefetch one page ahead, before
reading/processing the preceding one, and it's fairly conservative
setting, and I assume the default was chosen for a reason / after
discussion.

Yes, I suppose the overhead of an fadvise does not compare to the IO
latency of synchronously reading that block. Actually, I bet the
regression I saw by accidentally moving BitmapAdjustPrefetchIterator()
after table_scan_bitmap_next_block() would be similar to the
regression introduced by making eic = 1 not prefetch.

When you think about IO concurrency = 1, it doesn't imply prefetching
to me. But, I think we want to do the right thing and have parity with
master.

My suggestion would be to keep the master behavior unless not practical,
and then maybe discuss changing the details later. The patch is already
complicated enough, better to leave that discussion for later.

Agreed. Speaking of which, we need to add back use of tablespace IO
concurrency for the streaming read API (which is used by
BitmapHeapScan in master).

With very low selectivity, you are less likely to get readahead
(right?) and similarly less likely to be able to build up > 8kB IOs --
which is one of the main value propositions of the streaming read
code. I imagine that this larger read benefit is part of why the
performance is better at higher selectivities with the patch. This
might be a silly experiment, but we could try decreasing
MAX_BUFFERS_PER_TRANSFER on the patched version and see if the
performance gains go away.

Sure, I can do that. Do you have any particular suggestion what value to
use for MAX_BUFFERS_PER_TRANSFER?

I think setting it to 1 would be the same as always master -- doing
only 8kB reads. The only thing about that is that I imagine the other
streaming read code has some overhead which might end up being a
regression on balance even with the prefetching if we aren't actually
using the ranges/vectored capabilities of the streaming read
interface. Maybe if you just run it for one of the very obvious
performance improvement cases? I can also try this locally.

I'll also try to add a better version of uniform, where the selectivity
matches more closely to pages, not rows.

This would be great.

- Melanie

#25Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#24)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/1/24 17:51, Melanie Plageman wrote:

On Fri, Mar 1, 2024 at 9:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/1/24 02:18, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 6:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 23:44, Tomas Vondra wrote:
1) On master there's clear difference between eic=0 and eic=1 cases, but
on the patched build there's literally no difference - for example the
"uniform" distribution is clearly not great for prefetching, but eic=0
regresses to eic=1 poor behavior).

Yes, so eic=0 and eic=1 are identical with the streaming read API.
That is, eic 0 does not disable prefetching. Thomas is going to update
the streaming read API to avoid issuing an fadvise for the last block
in a range before issuing a read -- which would mean no prefetching
with eic 0 and eic 1. Not doing prefetching with eic 1 actually seems
like the right behavior -- which would be different than what master
is doing, right?

I don't think we should stop doing prefetching for eic=1, or at least
not based just on these charts. I suspect these "uniform" charts are not
a great example for the prefetching, because it's about distribution of
individual rows, and even a small fraction of rows may match most of the
pages. It's great for finding strange behaviors / corner cases, but
probably not a sufficient reason to change the default.

Yes, I would like to see results from a data set where selectivity is
more correlated to pages/heap fetches. But, I'm not sure I see how
that is related to prefetching when eic = 1.

OK, I'll make that happen.

I think it makes sense to issue a prefetch one page ahead, before
reading/processing the preceding one, and it's fairly conservative
setting, and I assume the default was chosen for a reason / after
discussion.

Yes, I suppose the overhead of an fadvise does not compare to the IO
latency of synchronously reading that block. Actually, I bet the
regression I saw by accidentally moving BitmapAdjustPrefetchIterator()
after table_scan_bitmap_next_block() would be similar to the
regression introduced by making eic = 1 not prefetch.

When you think about IO concurrency = 1, it doesn't imply prefetching
to me. But, I think we want to do the right thing and have parity with
master.

Just to be sure we're on the same page regarding what eic=1 means,
consider a simple sequence of pages: A, B, C, D, E, ...

With the current "master" code, eic=1 means we'll issue a prefetch for B
and then read+process A. And then issue prefetch for C and read+process
B, and so on. It's always one page ahead.

Yes, if the page is already in memory, the fadvise is just overhead. It
may happen for various reasons (say, read-ahead). But it's just this one
case, I'd bet in other cases eic=1 would be a win.

My suggestion would be to keep the master behavior unless not practical,
and then maybe discuss changing the details later. The patch is already
complicated enough, better to leave that discussion for later.

Agreed. Speaking of which, we need to add back use of tablespace IO
concurrency for the streaming read API (which is used by
BitmapHeapScan in master).

+1

With very low selectivity, you are less likely to get readahead
(right?) and similarly less likely to be able to build up > 8kB IOs --
which is one of the main value propositions of the streaming read
code. I imagine that this larger read benefit is part of why the
performance is better at higher selectivities with the patch. This
might be a silly experiment, but we could try decreasing
MAX_BUFFERS_PER_TRANSFER on the patched version and see if the
performance gains go away.

Sure, I can do that. Do you have any particular suggestion what value to
use for MAX_BUFFERS_PER_TRANSFER?

I think setting it to 1 would be the same as always master -- doing
only 8kB reads. The only thing about that is that I imagine the other
streaming read code has some overhead which might end up being a
regression on balance even with the prefetching if we aren't actually
using the ranges/vectored capabilities of the streaming read
interface. Maybe if you just run it for one of the very obvious
performance improvement cases? I can also try this locally.

OK, I'll try with 1, and then we can adjust.

I'll also try to add a better version of uniform, where the selectivity
matches more closely to pages, not rows.

This would be great.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#26Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#21)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 29, 2024 at 7:29 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Feb 29, 2024 at 5:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 22:19, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 7:54 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 00:40, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 6:17 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 21:06, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

That's the number of distinct values matched by the query, which should
be an approximation of the number of matching rows. The number of
distinct values in the data set differs by data set, but for 1M rows
it's roughly like this:

uniform: 10k
linear: 10k
cyclic: 100

So for example matches=128 means ~1% of rows for uniform/linear, and
100% for cyclic data sets.

Ah, thank you for the explanation. I also looked at your script after
having sent this email and saw that it is clear in your script what
"matches" is.

As for the possible cause, I think it's clear most of the difference
comes from the last patch that actually switches bitmap heap scan to the
streaming read API. That's mostly expected/understandable, although we
probably need to look into the regressions or cases with e_i_c=0.

Right, I'm mostly surprised about the regressions for patches 0001-0012.

Re eic 0: Thomas Munro and I chatted off-list, and you bring up a
great point about eic 0. In old bitmapheapscan code eic 0 basically
disabled prefetching but with the streaming read API, it will still
issue fadvises when eic is 0. That is an easy one line fix. Thomas
prefers to fix it by always avoiding an fadvise for the last buffer in
a range before issuing a read (since we are about to read it anyway,
best not fadvise it too). This will fix eic 0 and also cut one system
call from each invocation of the streaming read machinery.

To analyze the 0001-0012 patches, maybe it'd be helpful to run tests for
individual patches. I can try doing that tomorrow. It'll have to be a
limited set of tests, to reduce the time, but might tell us whether it's
due to a single patch or multiple patches.

Yes, tomorrow I planned to start trying to repro some of the "red"
cases myself. Any one of the commits could cause a slight regression
but a 3.5x regression is quite surprising, so I might focus on trying
to repro that locally and then narrow down which patch causes it.

For the non-cached regressions, perhaps the commit to use the correct
recheck flag (0004) when prefetching could be the culprit. And for the
cached regressions, my money is on the commit which changes the whole
control flow of BitmapHeapNext() and the next_block() and next_tuple()
functions (0010).

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

Just confirming: the results are for uncached?

Yes, cyclic data set, uncached case. I picked this because it seemed
like one of the most affected cases. Do you want me to test some other
cases too?

So, I actually may have found the source of at least part of the
regression with 0010. I was able to reproduce the regression with
patch 0010 applied for the unached case with 4 workers and eic 8 and
100000000 rows for the cyclic dataset. I see it for all number of
matches. The regression went away (for this specific example) when I
moved the BitmapAdjustPrefetchIterator call back up to before the call
to table_scan_bitmap_next_block() like this:

diff --git a/src/backend/executor/nodeBitmapHeapscan.c
b/src/backend/executor/nodeBitmapHeapscan.c
index f7ecc060317..268996bdeea 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -279,6 +279,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
}
new_page:
+       BitmapAdjustPrefetchIterator(node, node->blockno);
+
if (!table_scan_bitmap_next_block(scan, &node->recheck,
&lossy, &node->blockno))
break;

@@ -287,7 +289,6 @@ new_page:
else
node->exact_pages++;

- BitmapAdjustPrefetchIterator(node, node->blockno);
/* Adjust the prefetch target */
BitmapAdjustPrefetchTarget(node);
}

It makes sense this would fix it. I haven't tried all the combinations
you tried. Do you mind running your tests with the new code? I've
pushed it into this branch.
https://github.com/melanieplageman/postgres/commits/bhs_pgsr/

Hold the phone on this one. I realized why I moved
BitmapAdjustPrefetchIterator after table_scan_bitmap_next_block() in
the first place -- master calls BitmapAdjustPrefetchIterator after the
tbm_iterate() for the current block -- otherwise with eic = 1, it
considers the prefetch iterator behind the current block iterator. I'm
going to go through and figure out what order this must be done in and
fix it.

- Melanie

#27Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Tomas Vondra (#25)
2 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/1/24 18:08, Tomas Vondra wrote:

On 3/1/24 17:51, Melanie Plageman wrote:

On Fri, Mar 1, 2024 at 9:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/1/24 02:18, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 6:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 23:44, Tomas Vondra wrote:
1) On master there's clear difference between eic=0 and eic=1 cases, but
on the patched build there's literally no difference - for example the
"uniform" distribution is clearly not great for prefetching, but eic=0
regresses to eic=1 poor behavior).

Yes, so eic=0 and eic=1 are identical with the streaming read API.
That is, eic 0 does not disable prefetching. Thomas is going to update
the streaming read API to avoid issuing an fadvise for the last block
in a range before issuing a read -- which would mean no prefetching
with eic 0 and eic 1. Not doing prefetching with eic 1 actually seems
like the right behavior -- which would be different than what master
is doing, right?

I don't think we should stop doing prefetching for eic=1, or at least
not based just on these charts. I suspect these "uniform" charts are not
a great example for the prefetching, because it's about distribution of
individual rows, and even a small fraction of rows may match most of the
pages. It's great for finding strange behaviors / corner cases, but
probably not a sufficient reason to change the default.

Yes, I would like to see results from a data set where selectivity is
more correlated to pages/heap fetches. But, I'm not sure I see how
that is related to prefetching when eic = 1.

OK, I'll make that happen.

Here's a PDF with charts for a dataset where the row selectivity is more
correlated to selectivity of pages. I'm attaching the updated script,
with the SQL generating the data set. But the short story is all rows on
a single page have the same random value, so the selectivity of rows and
pages should be the same.

The first page has results for the original "uniform", the second page
is the new "uniform-pages" data set. There are 4 charts, for
master/patched and 0/4 parallel workers. Overall the behavior is the
same, but for the "uniform-pages" it's much more gradual (with respect
to row selectivity). I think that's expected.

As for how this is related to eic=1 - I think my point was that these
are "adversary" data sets, most likely to show regressions. This applies
especially to the "uniform" data set, because as the row selectivity
grows, it's more and more likely it's right after to the current one,
and so a read-ahead would likely do the trick.

Also, this is forcing a bitmap scan plan - it's possible many of these
cases would use some other scan type, making the regression somewhat
irrelevant. Not entirely, because we make planning mistakes and for
robustness reasons it's good to keep the regression small.

But that's just how I think about it now. I don't think I have some
grand theory that'd dictate we have to do prefetching for eic=1.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

uniform-pages.pdfapplication/pdf; name=uniform-pages.pdfDownload
%PDF-1.4
%����
1 0 obj
<</Title (Untitled document)
/Producer (Skia/PDF m123 Google Docs Renderer)>>
endobj
3 0 obj
<</ca 1
/BM /Normal>>
endobj
5 0 obj
<</N 3
/Filter /FlateDecode
/Length 240>> stream
x�c``<�,�y%EA�N
�Q
����p��o� j/��Q�p��'�@,S�h$�-�a+��I�	�]^RPd{��E!A�@v�����NBb'����6�9��w3����C�2 C���,�200O@�%�d`���� q!�����h���1DX$%��X��)-����r�H�\����&�y2��@�����
�d�cHf����[=�
endstream
endobj
4 0 obj
<</Type /XObject
/Subtype /Image
/Width 1200
/Height 742
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 62566>> stream
x���	�������zF3���F!����L&���DeF����8D��,wA� "�,�(�����l���M�B��B�������N??�.���}�~����:T=�����[��R[u54#���iii[�lY�j���[8PQQ�w�4qg���������������p���o����+�����_~Y\\�w4Y��>:x��;������!C����v����D��c����M���S�t� �W���XU|g��i�����H����s������������/������	8Q6U��4���d���joO�4�������O>Q
����h ��*�Ak�,Y�v�+���������~�hk����C  ����z����B}����C�3f�j6`����2k=��l�����i��m��=D�u�����v���C ����z������_Pfff�����-������HOO��i��+��_���s��y������7III�V���m[�a�WFF������['kY�f�,���WBQQ��}�6l��r����Wo�����#����?c=����k�.�3���7������ ��8UTT����]!�OII9}���i��Qaa�|��d/�������������P���l�����c���D=(_�����n�*9WA�nDT�p6D�.���y��W�~~���dsB4�l���+�q����u!,X�����N�k�������f
<X���%�UFw�f������	�^:8p`����d.2����0��M��n��Iz��$?��ci�������+���\���Q�F���~(�a�OI��m?n�8�%e��e��
���s'� Ek�
�.��K��f���]Zbb�w!R\���{?�������'�a�OI��m���/������{��`���������
�Cdwy�$���s�z����&�_~��40�!Q���3g����9������?t��M�"X=�������3o��Y}|��y��H�p���tK�&�N��t�Ru�m��i�,4h����C�_j%`��c��Y�x��u�����
�9;;K=(���'���j)����%K��=Zp��)��f�+++���f����|�S�a�����t�
�����l�2)a��	&���x��w��Z�|y�
1W~���o����+���O�z�jY���)����
�.������>|���~������ 4���8q����`UJ)����YYYG�q�~2���Q�tqqq�v���!u����u3�[���U��CYH��5K50`@�S��75Z��� �5���j��
z8���;w�����Guoe�_���N���#G��������Jy��"���.&������>W"���jOn������jO�1���	j[t����V/5��C����u3)�\K�
Q}PJ9i U���U�������j	�"�Ws�����~[5x������]�{I�V^����T���!C� R�LKK;v����Y�o_��]��(U�o|��:B���w�;Oz��g����4�
�:��~D�-Z�]��dt��z��}%�l�Rg{X�<�$�������2��1c�k�,�>�(��`|�zP���I�&���X:`����:��zHp������x�����9���$��e��-J_+8h� �/^��� ==]��c���{����[�.`����;��`�|��
F��wnBB�^��.���c���<yr�[�f����Hc�QR;�jO)������I����#F��pQjs���r\�������%��.��bCb���zp������_~����_$x|@����0���+++��P
<�����l����M�;�RSSG��r��]�RB�]����jb9���!������C���DJ1����zP�;6`�V��_=(����?����mt�����:#��S�|��w�s/}���!�3c���{"���|�^PgW�����[�������^���������!.��A�Ws���6$�x���/X� X'��������8�����{���u�`'�d������B�����	XW��t��)!��z��U�V<Q=�o��!Zn�����:������m��^����g��J)��+_��!N�����
%���Y������I?��_x�������%W����M�F�~p����&����~_QlH��.///�'����`�����su��&���eH��sX{����mJJJt�p�#�P����7��g��`�wP������3e�z��R"�����k��V�_h����I����t2dHVV�n6u�TW��g��K=��u:���	xnQ��K�5���'��y��1�-
X���S�A��:��<�&�
��Y|R{�M�� @���C\�.iS^�V]3��m���b�R/���k���|���>T_	x.R*8g?��9�g��_:o�����C/��3�z���mt=(���1��F��c��Q����R'n�a��r��&��L=z�w���4t��:��|gGJJ�����v�m@�zp��UjJ�;]����������R{�M��A�&�Y��x
���@�G��6�g��F*AuW8^�v��9���_~���>Z�bE�W:�_n��%��z�IM��uV���Y�;$���@Q=4u��5���RS�����{��O>��3�S��+��_FEt��Y��W*��`�r
?�.�����
�=���|Q�&�Y�����C\
�����>�x��E�:tH�P���j1��I2���qc����\+W�q:&�zP�]��l�w��T������#�h�}R����k999�j�����t��Wk�-b������rF���'�N�<�_M��5l�0��!]��E#����mH��6}�`��t�r
v�,|a��*L�k�������������VQYY�g�).��?�d�_~=�<����z�TB��A~����!C��U>\O�:u�LY�t���G�R�s���v�������+�y�H���"unvv������x9���>���w��T�o��=s��n0r��:7D�RS�x���Y:_4�I����tI��			����>�2��E���N~��b��z[���eee����BJ�SRw���&~�����7\�s/�sl����R�=Z�T]��#�c]7o�b	�u��?:)|���Z��6]J�����/�}��������G�`��zP�����Z��&��3�-��<�$�z����a��E���|�O�8��E���sg?��m


�i\u5`zz��YF����r�%��:{��db�^�y��|�����!�]x�%�"999��{�K=��o���?~�n������]�Ck�/���>� B������Y��������[o��x����}��u�I���T�������zPH�����u����H��I�����e����'L�l�����3-��MD]z�G�y�f�R��`�Er><3���9sF}������:�m���u�I���ci���?|d�tb�|�K������?o�<����"z����`wli{��Q-�=���z�Y�<xPq���y����[�
&��m[�%���:�[��>�z�EBB�^u�sU'O��m����RW�J?���=�����>�#e��������a>��f=8z�h���o�	���*��jV��\�R/������L=�u���?q5�-u�'s��4E}fM�����z��$�w�}W����z�I����R��r������&��>}�n�r4TJ=���������y1��'B����������o;/^�: Q	v�����u?���,�u�Y:��>����s�6������B���'O�]zH/�����R��8g���8�ct>	'555�J�m�VgA~=x��A���/e������9�Y�&`��':�����s/+g�;�oN�e{%��z���^H}bK���e�T�������^R�v�t2X�u=K��())�o�x�r���H������P����e��-Su�VYY��8�O�q����zQB��5k����OP���W�M�4�u����
��L���{���J��dJ��/_��;5r�H��y�bQQ��������r}rS���[��
�����U�e���]�N�	*W8x{����[�.�VDA�~g�����;���y��s/�n�>����C���B�{����.-�=�Z��Q7�o6����)�W����u���]��]�t�����u�Q~8���{f�R]O��C~��p�C��G*=�'�%R���O��F�.3g�T����Qc<���`\��<u������V����3g������������0��H ��U�Vm��!))I��b*#�o������a���K�,������q��n���2\_[CF��
k������'a���C�{>����Z����`��x�����_��$���K��]�l�'�|��6�@�|+D@�e�|t������D#����;������xUo��RZ�~)�&N���E�X���QoHu=���8PuI~,�_�������<����~w��W=X]sEhBB��$�"S���sss��������*�7o���O��w�a�T%�O��d$�]B���C<8e��}RC�+�d0,���g����FVs�*��k���B����%�����w��1�TV���UV��/^�p�e��W�u�y�h�R]��F~��U�����v��y!��fKF��|���u��(�����������J�yrr�Z����e }���`��
Y���k���)�B�+A���={6n�(�Z�f���;��9�
�(�;wN�H�;wn=.��K�w��/w�������20??��NEC�����o��-))I�E�(--�B�{�m���|�����l�"�57��/�{����7�����}��������������b011���,Y�vm���Gz�bh�6l�p���{����1�a��%~��M�8Q@��ww����>}�_|����w_��T�>}���.]�g�W�=OOO����}�3@����SjL�:����k�����4]������%���
���s�Wo�������4.���j|������
���H��S�&`��Y�5����;��,ht6a��

�����<y�����3~��V=�d��3gFZ6��2!z�����w�
�y�Ch\�Q�Mh������w/��z0�z��A~�a
�sU�a�~���`#��	
�l������A�P6��@=)�A�A�z4"999�V��:u��	���W�X���Yrp{��))���3y����������������2W����Up^j�2����/[�L�\��3f��<x�����X&���k��y�di����/^�8--���s�u8R,p.*++KV-��={��I����+W�������F���8p�����%��w��1}��O?����>��$�u���t�����,���#�a�������)�ow�����vo���			�FY���[����=�z�j�L�%t}A�e��W_�����z(SdWO�6MV*��5������6<��LDn�L\�h��W�����E���o��p�����v������._�dIm�tx�����CtF�,Iibb��W�0���+�����(:��3g�Hg�S�-�����������\�Saa��M����i/_����;-u>O�UJ?�|'���e�"�<K�Y�FF�2E*�`�[��Q������������"�w��322����k�Gd������-SY�n������2{����g��e��>�j���-B�%5�n����g!�����(�GA�'�Z��JdT�6Av����A��_esd�l��_�~�zU6��\e�k�2lV�U��(���e���AY�,Y U�|J�j�zP�7��-[����oMJ�"Ks=^#`�du�=�}�oA�R����zP�"��si2�W�E�GYJ���N�����&K������fJe$"{[2�v��v��G����|S	5��de��gY���z�<x�����
������~��,v����Z[?B����{�83f���(�����=[-J���^�����X�����|�rg�_e�= ���=�Z�&{FR����7�H��������S�V���P#�a����:�?��B-j�&URII��~��1�{x�e����R�H�����N��_F�LY��8��<yR�H:��(�75��1�s�l����U1��E��Ee�,�!_D��C��%�R����tu^R�����k�R���z\����%�W&�M��������[�e�>"e�Z���==//Ojj)���LUGH��,�e?�`[}DoW��I��&_���RRR����}�:�"
����O�xi�,Y��j)S�3D9U��^!'U�j�N�j��d���Q�%�Z�l��"�����������WU�H��Z�����?&�����T]��U~�Nv�@dE�Ldn�K��3��!;J���� �P���T/P6Y/P:&��`<~���^�222T�(���#��M�6I\�VP�`=���DZ~���T����?�3<~Qc*�x��2,��w�,@���{��,D}D�c�Y���-S���{%#aW=(��q5'P�W{����}�"���K�	�����m�e�|�ui�������u���{Y�^���-]�b��U^^����!������]5�[�Kj�'��T������KHHp��l��T���#�(P���n���#pN���T�w���]��uH]������DMm�7cW5]
W��Om�~M*��&e���x�NV�I%����Y�pu�2X���������H�J�]�j�~�@I��a.[���4x�%��/W�W�^��T��A)<]�X$�Sg�%�����Evvv��kaaa��2vO���og����t�j�+#R�HU��Sg��U�xNM�d�*����H;�����sg�6���U�T�����Q�F��d��>~���`K���5K��j��2B�oe7�J��T���O��z�u����wwI�fy�����k��7�)]��W�������'k�5��WQ�d���Q������7��������e	��I��.]%���V�5{o����:����������E�+���{��O�m���9]�35}���76�`=��������9�U2X���V���V����0�����������:�Y�����^HKK��t��2�?��8&L��r���]�vM�4i�����4]���R)ad�zo���Nh:��=?{��Qo��K�`c`uV�U�J$���������#`�����QQx�M@
��*
�Q��%ui�T��Z'5Kr0��7�^~2Q��=�*;J��{���^�w�R^^.���:;&?4g�����;�uX��#�*�,����@�o�~���;�g�]�N���0���G�D�(��*�����9s�D�.����1.���j�pp���.cH��U���W�.S_9���9���`�g@�bur�
g�}�,�������2�Uw<yyub��F8y������W����Pw����:?���*�CtOEQ����Wsq�wV8Cq�X�qA.m
3k��q�s\T?��[�t�'����q>��]+R�w�����u����Dt9t�=�J�H��H(�c8�iBBB�Bt��P�-��\�`����{���a��z'Xn��m��}�����DQF�����^.��m���)�q����)��#!9���P�xDUU��e�T�y�����Hm���>k��.YJo�����[�.`7>_��O}������:��Su��	�K������(��+!Qs���CC�Q�d�lu=��������E��&_�T���S��q��unlD�����!H�j�����zt������]S
`At';�-Ts����"������n�ZII�TI����Gtq�Osx/���zP_����Q��{=h���~DO���v����t�,G	U��#��A�u�!�u~0�zP���8VJB��[�Sa�������>?����%�zP���������%gJ����C8��Ht�`t���������5Q���}�J������KX�z�����P�?h�,++SWE,4U"�n
!��L,���'m���N��X���t�?~����F���/IQ�1m������F?N$��U?��5W��!�pK=�2�z0�e<xp��=��%%%jQ��
����7�)2l�� ���F-�zP]�&�E�<u{=X���E-�����b����Y�������
6t��K��p�������A}�o�Q��q��������(������^���(c�m�&������	�=�����B_���;6�x��zK�wp+�,5�[���{�A�X?�vo2�PJ���b�2�>�_Q��p�������*��"U;�V���z}�W��N=�_��}��>�V/���-[�t�=b�"������Y��W�J��=�I���2��S�:c�O&�U�oSJ?W{�:��AW=X���;����Tv��I�\o������T�}�O��=>H>�����,�>�`o�	&D=(�p�E�$�+�L���Pc�Q���������wp����>������8J_��������PS80��}D�LU�y_t���8O5�"�5�Sw����u�V�W�}���P!�S��o���'����
��zP_W)�u~J
g�T�����P\>���U����P>��d���R��n��1#����`��U���X* u����F��q�(�[����A�XQ�)o���M��zPj^�7�����?�R�{����`��	����w���n�K�������+6���X�j���|)*$.xz�2��nL�<Y�,)�Q�_��eT�RC�[�����hG6+W���m�|J�			S�L���g�����E���fRa�\g�z��n���W�b����K�k�.�����R1)O�I��S�J)���z�����>z"t��o+�+
�rd��>�q�F�c�e��U:�v�Z�!2����e��%�Uc��KVYff��Y_�)��:/��f���]�h�"���/�I)����?�~�m��)$�IL�v6o��o�>i0g�UZ�.��=)��������K�.V���2j������U�e@��ZYC?^r���)�x�}�T�8��dL�~�(���l?���.���I$���^_�6_�R�/K� �w�_�'_���q5�N�V�fJ��Kj��\��W��V������G��.$����hBtX�j9�������n������ur�P��oGu[j7�]{������G���5g���~SL�>���"=	`���e�.u��re0/#L5�T�[�y^C�2�����e)����e��GA�<�d������#Rn���t��N����GR��G����N�D�
M��dH&��j/�y�e���uv8999���������1�������O���Y:���VPP���:mp��j4}m���&2�KM'�Y ���������+���2����J��������s>VS�g�7Q���/}t����2�y�jeeeIY'{@R$�"���~2������oEtR�A
��*�k�f�b%<i�E����5??_����,��kj=Y��_�p�������p��2�����*�[��KR�J=(?R�^��������'N���}�!z���j������=&�M�S����*4
R�3��2
����e�u���3���4y\�b���Y�dI��������G?���{��[QQ�w�|������w������z�-����e��=��3?�������o������>���������3f�/B����Wg��������[��������w�}����[���$+W�|����t�r�
7Hr~���>��#�'O.++s5���JJJ����]w���M���[��������]�|�< ��G}t���[�n}��W��=�Pqq��]�j��iR]]�y��/���l��3����2.|��dJ���srr���=�N�z�����N�z���������f��A���KII�B�c���A���������������~�q�FIN||�/�K�x���:w��I�w��a����7o��m���#�0l������&4[2v����������7�xC&������������O\w�u#F����y��,�
���k8�'J*���N���o_�fSBB�
7���k�Q�F�SJ�x���K]��x��i��I=��?�Y~;���sN<s��:�:t�P��k���]�v'O�tN������NJJ��c�������*����;�������?��{����o6-Y�����S�����y���>��l�SO=��'���m[UU�K�,����T��H	Q��=[0�;k���[�n5����w�	��=z�����{w�D��x�
oc�J������z	����������� ����������1������Tn����A�����sM�?�*����|��e���������{�4��{���5&�=�������9Q);w��6����4���;l��o������v�����;���.]������m=�F�=z�pM�8q�����^���z���C2�u���������/;;[]/�j��p����W��W�2�/��%���h�����.��Z���������w�����z}���������S'b����`QZu����_T/^,��]���,��������|�A}la�2��������X�f�Y��3G��y��%%%~�a�N���is�
7<���~���������KO��#Rgdd��?�������~������AuA�K/�{�9[�;
)���1_E3�TOA���������_��pzzz�[Y)�2:���z"���XV���b���W]�mtx��we��u����\ZZz����}��j�j�����������<��������#�>���z���������/�t������3f���c������>�`AAA�}K���;��{��;���x��g$?a~P2�\s�$��P�&��z���o��[��;,Y�D��:�V��zP����o�������C�3g��y������,��?�iFF��^RR���`�	�
�<{�����7m�����z��m������������ew
80�4:
�TWR��o=X^^����^{��]�t�5k��;-Z�:z�=��������hD�`�^�T�+��;�~�5��:u*�n�����N������/d'�����[n��]Rw�������c���������n�v���4T���C��_�W_Q=���/��W�v�:s���%�u���[����������������'o��f9��Zh&����d���#G���e��E�Y���j��	�iCCiD��?����������V�Z��?�0�n����������OK%x�w�8QO�h���C�ob��AW�z����c=8o�<5t?x��w�m��f�n�FT����]�v�f�zp���1v�n
�����O\\�w��3g�����o����c��^�F��zP���{��c�=v����S*
�x���^W\�Q=x��q�`��%�Y���j��_~c7��k=(�����RSS�+?_���>��5K��|J�A�3H���d�Z{�-@C����?�+���/6D3���-����������?��{����

���	)�b�/����w��z�rG��M�c���<���}��={���cv�?��w���9�-���Y��z(`Z����_����
2��������Q�\��c����Z�t����jQ���z��#G��SRR�s���1���Z�>����}��z��B<O�]�v���~�����[�nm���
7�������K�.�N��K��7�t����5�����-�y��tiv��w�r�-�3����0`��{����$��������z��������m���5���N��g�}V�u���~w��c���H-3{���;w.Y�D�o�m��+W�����H����Q�F�zp���jJ�"|��gR�q�3f�HMM]�l��>(�z���+**�������k	~�������^��kWBB�]w�%;u��|@qQQ��~�+�.��G�6m�|!#�����L��O>��9e�����o�z���(,,����z�����'�\s�
7���s��6��?�7�x{�`rr�_����o�Y���������o���6aR�M�0�w������~����N�����O>_V������!P������.33������#F�|���^z��W^��S�y���XEJJ��O>y�UW�l��M�6�{�����X���Oi&��#�A�a���yR���Adee��u��Q>��g����/]���{���Jp�3g�l��E����M��e�)$/��������m,e��_<|�pi,���g���E�Fh�T=���f�=zH�^xAO)++����d��)S\����{�EI9v��=q��9���o�:�_��k'�����=z�e��B���"Z#4g��������\��������(i�����z���d��/��Z�-��"�������#��o�j��O���{�pz��9��|������w���.e`��-e�����DY��^(W�Z�j���o����������~�L�����qRR�Lo��E^^^��E�Fh�"���o�VAU����KO�;w�z(M~~���������5%;;[MILLt5.((P�B?�&�5@3����'�{���^{�%�\������_�r��eEEE�-���Q���y��GdV�����w�yG�\q�������:[�n���v�Z5%%%���?���4hP�m�h����zPj����_�~���c��i���zhLUU�ny��)UR���{���gO��=�����)m���6>}��ZTBB��2m�45�������X�D������;p�@�.]����O�8�����R=
6LO�6���={�w9�z��YW_}����SO���n���877W-j���j��q���.D�d��O?z["Z# ��C�J���������jJ�z��_������T�-�Rz�X����0�&)%%EP�F��v������0�&)++KP�&MRSx�P�8������ i0���dff����������;��}�-R��y�Daa����&�k��1v�4�F�`I�i�6cO>�������sG��+���z�����}�k������X�Gp�����1��4�F�`I�i�6c�^z���G����{O
��/�\?O�������?��.���p6�?�4n�������=�����r�������8��1c���:����W�w���5]�CW7"]#��f{��e$
��1�A�`Z�����-[���g�s�~���!C\�{��!������)�������)S\����{�E�*�=�'��7O�k��U<�_e��������T"�r6NII����.��B��H����s`I�idv�4��l3v�UW��JH��r�J�>����Z&>������s�/**�����}���7l��l����;��P��9�E��[����/d�|��%�\"+��o���L�Y�`���X>��M��,��r����rVge��4�c,#i0������m����������m�^t�ERI]{����w�����}���B��:H�u�W�s�=s��
�����'�xB*��-[J}��wo�u�����L�G������fG����[�j�[�h��/��1��4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�id�Ms`I�idv�4�F���1v�4�F�`I�idL),,�����;�����7��TTT�1���o���K����N�:��7/�2SRR�|������e��m�����wFFF�����}���f�X>"LNN�t+"Z#��9����42;HL#c��N��Vu��Q���s���K�.���{��R�l?s��-Z�n�z��i[�l�B��K.�Jm��}��2Qf]|���������||��Y�oBDk��1v�4�F�`I�idLH��O��O�_~y�z�G�2��^�S���n��6�8e�W��{�^t�ER�9rDO�3g�4���������v���,)����G�^v�e��0������c� i0������Xyy�M7������w��]�z055�������������#�Z�r\�=��L��]����[dz\\�s��1cdb���]����#��w��VD�F�Gs`I�idv�4�F��y��/�P*�?������^zIf�}����R�l�Rf-^�XO������U�V������2]jO���o�]&�����8))I��h�"///�&D�F�Gs`I�idv�4���3��7�HA������C�����v����z������;W������j�p�B5+''GM���VS]�

���O��t��W�������
[3?������ i0�9g�������e�v�JJJ����-Z��Y�F��.��G�Y�;w�S�y��r�Wx�����l��uj���k����o���2k��A�7$�56^��^�z��{�X5�cl"i0������s�>�����??))I�5X=x��)UR���{��gO��=�����)m���6>}��ZTBB��2m�45�������X�D���������:ft��xf�o�Hs>��&���� i0��f�����_~����g=%X=����J���g{���W/�u��W�)O=��L������sss�������7NM����������z���CoKDkl�J�Z$��������*,��;�^�=��2���� i0��f�[�nW]u��KzJt���/�~=���Q=��[�������{�o���
��p�E�=��2���� i0�yfL]��z�;��6XU�9�T���H��ch���1��4�F�`I�i�0cYYY��o���k�����o+uS�.]����=Of{��6z��<���~w
h��,�����}5i��M�q������E��Y��o���P���}�5����p�����A�/u�|��4Aa�T^^��@���~����?�CO���T����8����G�f��.���}������H���_�+��k�Fs8��! i0��������}�������\�����>�|�H�V��0tN���\'
�[o�U����9'�3F&v�����o��2�{����R���������z�!gIX�s���C�8������ i0��i!�A��G�����UO)//W���L��j�w���.���K/=z���8o�<i��];W�(���}����u�Y��qJJ�e�]v��:�HF���%���uX�lA�[��~�	�{��q��$
��1�A�`��ky��]�J�$%���������:v�(
���
6,[��s���n*3g�l��E��������[�~���\r�UW]�o�>oc�(����#��|�M�6�qY�����#�����4�56��'���*OsN)]���>"2s`I�idv�4�F�t����+��ZVTTH���C������{��g���!������OHE��eK��z�����S�Y�@�Ic��|099������7�xc�V�~k��Q(;J�~�_U��R{����CD�c� i0��������G����l�j5�*7;���zz��i�����;HL#c����42��<e�.�2�}�����>������*,������A�`�$
��14X��B���UUR��pg=�p�G~u���;HL#c����42�+������Hq��x�������\f�/�D�8������ i0���a*[�T{E��]��z����CZ�!��1v�4�F�`I�id
S��Wu�W0vT�6���r�{���A��D8������ i0����*.rz��B1��3�Y��/��$��1v�4�F�`I�id
P�����~��-���rV�����u���;HL#c����42�(�����h��u4~������'��Q��;HL#c����42����^7��+�����+t�/]��N?�9����42;HL#chh��&��.���#g���z��=D,8������ i0�������z���x��p>r.3�y��x��;��q��$
��1�A�`C�Ry�����������G������U��F���q��$
��1�A�`C�R�����?B
������l��1�:�Xp��$
��1�A�`C�������+�jQD�-�_{n����2�
u���;HL#c����42���b�^gAWU\��@/����&:�q��$
��1�A�`C�Q��H]��z-�%�|��{��8|��;�q��$
��1�A�`C���hW]��m\�B��}����z�o;�9����42;HL#ch �wn�}@�C��^N��M�S��{v�c';�9����42;HL#ch �T{���������}�}�g����s`I�idv�4�F��@dv��������,���A�)���_�W';�9����42;HL#chJ����[��b_`��7k����/��c� i0������������J~���x��)�)���	�/��c� i0������|WU\���*�������}@����
�e����A�`�$
��1��d�]�e����ZlU~^���������Z2b�1v�4�F�`I�id���������M��%��j�<���*7���p��$
��1�A�`���Fs^,z.#�>�^V�|������s��
��A�`�$
��1��x��^�}��z_~��Dg�Yy�X����;HL#c����42�������&�2���?<�W��F�@�8������ i0���G��N8O�U��7���Mk�k)����Z&�9����42;HL#c�Q�g�k�������r��'������[��1v�4�F�`I�id>�~�a]���XbnE��:O��^nn]�c� i0�������R��k�� ��J��.�+zuYO?ht]�c� i0�������R7Bh�C�4��s�O9O��nz��c� i0��������|3`��u�X��P����;W�[X)\8������ i0����;���fu�������nw��N���z��1v�4�F�`I�id�8;l���
F�gm�E�Op��(��UC��;HL#c����42_dv������S������y�������
��A�`�$
��1�W�fe��>��fy���g;,Sy���4ss`I�idv�4�F�`_���ko��t��d=���@��}�w�9��;HL#c����42�����wz��!�}(]�����=�������;HL#c����42�J'�B,��O�������n����F3�1v�4�F�`I�id����y]�%L���{v9O��Y�WO��9����42;HL#c��������e�������^�X����'�
��A�`�$
��1�T<+^�`�����3�'�9���/g���f�c� i0������l����t�U�`����>;b��O����J���Q��1v�4�F�`I�id�T�:�<Wu6���\�z_���_L�w��>�9����42;HL#c��p�������P��W8���*���R!���&�c� i0��������~����y�Z�ww�������;����`��=j�8������ i0������{�����J��Q���	�Y+O��GM��A�`�$
��1�Q0f�.�������q�z���kY�����i�8������ i0�����G����l�F���V��+�)��=���Q��1v�4�F�`I�id�m�\�Z��:������}Bw2��3~w����;HL#c����42�}[�Z���������9O��]�w��&�9����42;HL#c0��4�������:��������YO?�ww�&�9����42;HL#c0�4iym��D7��J����S������Q�1v�4�F�`I�id���IWX�?��;up^���p���b�{��p��$
��1�A�`�QUg���j�S'��Q�e�;;\8e��=jj8������ i0�����E�j������;a)�amI�����l�{��p��$
��1�A�`�Q�}{���h�T������������������&�c� i0����������v^{y.#����xf��.s=q��5s`I�idv�4�F�`���������D&��t������;M��A�`�$
��1�������*Y8���D���E�S��{v���&�c� i0�������<u�YOU����G�~������|���4s`I�idv�4�F�`H��Oj��|��~w'e[7:K��u���QS�1v�4�F�`I�id�d����Zi�r������[���G��NS�1v�4�F�`I�id�d�����KK��N�*�s�",�?��5zs`I�idv�4�F�`BUa���2�����$�����h���b�{��q��$
��1�A�`�	�G�^f�����NL��>�<EX��x�{��q��$
��1�A�`�	�;���y��~w'Vq#jK�nwU�f���F�c� i0������L(Y�PPg���wwbU��'e����Q����F�c� i0������L(�b���
?�ww�A�����F+O��G���A�`�$
��1�P�������7��������G�������j�8������ i0���)�j_>������d���S������F�c� i0������L���k��ov���z���G�v���O~w�Q��;HL#c�����f����������:t����/��������~WVV�##F�����/���+���S�N��������'�|����j��e�6mz������qfff�>}��4������#����hT�S����s�g|��	e��:O��O��G�O�=��2���� i0��f�{����w�����:4))i��M���o���L���;


\����:v�(s{���~���K��s�=�W)�.���-Z�h����i��l�"��%�\"���}���e�������.��#�A���Y������h��h��v�r����W+��Q����4�c,#i0������m�}�Q�����������^y��R�������=z���/�P�*�����n�M&N�2��x���]t��cG�����#�o��F��G�k�v�d�tz���G/��2YH��\Dk4�*7[WL��v��j*��uV�%����F��s`I�idv�4��l3��K/��O��z��������sbjj��������;�'&&J�V�Z�
��{L��������r�-2=..�9q��12�}����}������wgs"Z�i�jo���[���#�+�������5&����HL#c����42��
���z�9Q�G�x��w�K��eK��x�b=177��/���V������o����������~�L�����qRR�Lo��E^^^�>G�F��6���R���m���s�O9O}���=jL8������ i0��9eff��E�,Y����}�`�
�j�W�^z���s������j�p�B5+''GM���VS]�

���O��t��,��k��#�X[�M�-	��U�_G��c� i0�������8w���3gf�������K/;v�snEEE�-��5j����<����������;���+����855UUg���SS��]�����x���?�Y�
����hA�g�u�T8e������Hv�Ko���~�����;HL#c����42�`������:t�����Sjn||���={�T�l�S�{�9���m[o���O�E%$$�)��MSSN�<�m/�UO4
�	�����}���:Nn6^����^�q���=j8������ i0�����'''�Y�����o����_����:�����j��������Kf]}��z�SO=%Sn��&o���\������)���SS�����;t� ��~�����-�{�O��6�;/iYUIq��]���|��5s`I�idv��������J����l�n�?Y7n�i�������)�����[,�w��kL��k���(�
QD�� * �A�300s����^��s���y��'������w�y���{�
4fKfff������R�;v��~0''�F~Pyn�.~��U gx?�K2_�`�C�(8r�v���uD��9@�4�h��x��c��]����o�V�4���au�v�6V���S�:3�������A=���b�qh���sG1P;v�P�4��d���!��_��������F���uD�	;�C�DE�@-^\�bd5�M���;������������o�`0(/�e���w����n5GY_uP����3j��-��+dej�S�J��x�u��o�����^y������/���*j��
�����~��y�������K�e?�J��s��Rs4j�j����+�l������yi�uP(
����4N�]�|�\��e�*�t��a����������������=���#tf�f������{�AC�7�|���[������k�`�-��<q�D:��G�r�����w��)����rgOQ������'[K�;m��9/������@c@�4����1�>��3w���=�������K}�Q�?8p =z��Hqq�2����R������~��GMLL�tww��_~��r���I��_��������E�R�'GFF>��c>����dM�����Jwi_�D��j�n�([K��r��9)������@c@�4��������+,�}��%K�x{{���u�Ve=�W_}5--������-[��#F�

���j��mUh�����?�g��������?��#M�6���d�:H/�	��-���O�7oNN)w��+��K[gZ�;���u��woW���"d�ak	\+Y�4�:��x�u��o�����\��C���_z�!��d�>���M�6U5�f6����h��|�O<��uk77�jn��W/�,]������+���B/�	t�LBQ����D2���5��[��9��x��zU���"d�g�l?A�(�_����F[����o�1�P�
4�������Z��6�q��/����7�^�:(�uP(
����@c��d�euC��Z��E���C��]>�R���@��J����:@i�7�p,���X�����u8�P��Zf��]E�A����9@�4�h��x��b����EK��/��(t�i���:��x�u��o�1�@,��J��u�:���1�����:"�uP(
����@c��G],��G�L���m-�q�f�c��9@�4�h��x�b:{�t8l��Z��=b�.�W[Kh���:(�A��J����:@i�7�p ����'�
��q
,�73�lek	�#��JKP�u��o�1�P�
4H���V�Sp`���8d��@�e+��$����9@�4�h��x���aF��H/��q"
=��Z��>�\��Ai��P�
4�J�����MV:+��E��q.�6�Z���%�I��4uP(
����@c��d���w,)�Z��t��N����3&h������@c@�4�h8�2��j�3�3f���d��J���uP(
����@c�Q����%S:��:'E��g��jk	=�h�������@c@�4�h8
K�M����S�p�!-5�SXv^���uP(
����@c�Q��X
�n�H��qj�W�l�`F��7��J%P�u��o�1�P�
4E��1���[4G�p����2;Pto'dgi������@c@�4�h8
���eR���:�z��'�&��-hwP�u��o�1�P�
4E�������}�����������)����;�s�:@i�7�P(
��B?�ts=������t��ZBr�ZG��9@�4�h��x�G�3z�����FiN�A4�������;��#�s�:@i�7�P(
��"��VG#���:����������%4���:(^�����@c@�4�h8
[;�u,��������~����Z��9@�4�h��x�� ���F&���Z�S/)
�����]>�R��������@c@�4�h8��kV#�3�����W
<\��@������:(�:��x�u��o�1���Z]L�������v��%�3X����P�
4�J����C(<�^�c���Z�S���1�����:"G�:��x�u��o�1���n����F�����L�Cz�Z���������@c@�4�h8������������{����^��@���uP�uP(
����@c�!�Nq,
�:���%�f���l-aqd��A9�9@�4�h��x���3�_��y�c���@��_���J�:���:��x�u��o�1�2�}f�-BN���4
=��Z��>�\��A�	�9@�4�h��x��`�Y����a����#�K&��A��9@�4�h��x���#d��`}�A�p ��Sm-a��	ZGT{P�u��o�1�P�
4��9�r�����Z��0�3���oX�uD�uP(
����@c���|J��fO�:����������x�jTm@��J����:@i�7��;���[�Z�u8
����Nml-aQ�y���1�s�:@i�7�P(
�u�v����Z���1_����>0���:���:��x�u��o�1Pw���:�B��Z���1��)�E�vBF��A��9@�4�h��x�����2�^�`�wwo�����z��Ze/�s�:@i�7�P(
�u'{p/�7�$��:�FA��y���,�����P�
4�J���@��]�D���:���n�0[KHQ���uP(
����@c�����ciD�C����q����7�s�:@i�7�P(
�u��z��A�~���q!d�gv������h�=@��J����:@i�7��#�QK�b?T�p��������tD���uP(
����@c������:�����1R�o�3�|,��jT������@c@�4�h���]V'��a���4R
������W1O�uP��:��x�u��o�1PG�7�����������r��%�3X��*uP(
����@c����Q�����Z�����1�����:�J@��J����:@i�7��#���_��u8��){Ho[Kh����1�uP(
����@c��d���>,)�Z������zu(�����A�uP(
����@c�������P�p�dI�������82\��JA��J����:@i�7���!�t������Pv��_�"��uP%�����@c@�4�h�6e��`pO���z���Y�:��:��b�����@c@�4�h�������M�u8��-k��@1��d2i��P�
4�J���@](�:f�y��h(�~�T[K�;c����*��@c@�4�h�����
6��:P	9c�Z������uP(
����@c�.����j4
��k�1O�����%,�p�0�9@�4�h��x�����S:����u8�r,��2;����E��Z�:��x�u��o�1PrF�Z��(��UB����h���F�&������@c@�4�h����_X-����u8�:L��ev���N�HW?�9@�4�h��x���`�/�������_Y��ba��1�����@c@�4�h�Q�mu��>�:`��3m-�n�(�@��J����:@i�7��5���J�:�W�p���&���yK��yw�9@�4�h��x��ZSt>�t�������h0d�ak	�{]T�;��P�
4�J���@�)<�^:��l���� d�gv�������sk�9@�4�h��x��Zc�u��M\6j������������:��x�u��o�1Pk��/�Z���nZ�jLQ������FHK�}S�9@�4�h��x��Z�;c��J���:P
�)�E��b���Q�u��o�1�P�
4jM����S
��j�%�+�Z��1���uP(
����@c��dv��j"��,���G7e��%�����^�s�:@i�7�P(
����Ah�baA����_�a�N�B��J����:@i�7��BF��;d���u8���Y�=�Z�B�#<n�:��x�u��o�1P;���K�85P�p��$������%,�w�]P�u��o�1�P�
4j�)���rgO�:���������Vd{�9@�4�h��x�h5f4���.]���/i���c�=��k�M�:55�����f��e�^��G}��'�l�����{5���������6m��C5o�|���U����9a�:�N�?�?���������H��V���j1���)�<bk	�zu��XP��s��@i�7�P(
��qj,66��g������|���;w���x{{��7t��'�8s�L�?!���eK:a������'O�l��5��L\��8p�����~���t}2��<�95�u���K�����.]J'�����������jt��c���j������
��5e6%�[2�u��Y����o�1�P�M��X@@Y���~�l6��4i������^�OH/�9�z���������...�N���y�����%$$X:t�N~��W�mO������:������{�.b����B�����xu������N����3*���������@c@�4����1��]*w\���������.]j{<**��������D:�Y�f�W�������c�]��7�������=�v�Z:��k��;y��	t�G������!��XWv�����3���%�_��!�m�uP(
����4N�%$$L�4)+������y2P�=8y�d:����;�l�C=D/�8q�zP��=���t������s������������~���=������t�I�&���������!d�eu
���>�1W�����%,�����h�uP(
����@c�x����%^{���T���q��G���������N>v���RNN�r$;;[9���Q����|���W���Ef�6V� ���/hXn%�~�l,8����D��J����:@i�7��-&�I���{����ln��	\�re�?���+���m[�����+��T<9**Jqg��Hddd���z�)zi����]�;:
[���+��|5����h���F\].�:��x�u��o�1[\]]�:���...�LMMU,��]�*������5[�G�JG^|���'���)���w�r���r$%%���tYeE������%�V����:;���	1y{����{;!���K��:��x�u��o�1+�(����%�t�h��2�]��X��V��q���K�=���H����������'�t:�R�6mR�l��Q9R���-Z������S}�5��C(��hu��Cxe��wl)�����P�K�����@c@�4�h����K+]��z?H���srrj�����+�����A���Vk�0a�=�;	�F�Z��!���p�N��������o��[7A������������� ~�4��Ny@[Kxs��#��N��`���}��G>��3��T�U�'S��
+K� 8P�M
�`�����wo��Eg%�J����:@i�7�9�G}��O?-,,���j��x��w��{�����������&��R]���xG���a�����t����#��fv��������
�s�:@i�7�P(
���k���c�=��m����ArU�����9j?�y���g�~�~~~t�.U���+�c��Mf������8pr��W3��ok	�W����F^����o�1�P�Mc�X`` ����[��A���~���m�DEE���<�@FF���#G���j��C����w/7h����o��u���\�v-l��E��'N�H�{��Q�8��ra���u'��.V/`II����EQ�������r+���m�uP(
����4Z�)f�U�VF���K� 1p�@2V�G��)..V��\\\�����?�����������t��/�\�<�?�`��K����q�]�����H
�������N�����g0���lJ����W~�r�4�:��x�u��o��.]�Dn��������I��~�lc��-�OF������m��*$8@�y�������|��Gy�i�����O�����l�2:���y����t�rg�X�By������uA4��ul����zD��E��0g�`{��q�9@}�4�h��x�85�}���������F���h��|�O<��uk77�j���W/rd=������W��i�^��4:����0""��i������J�f�*��jt�ZcI�i�/�����)�l-�~��{�I��s��@i�7�P(
�5�8<�������:�%baAv�M	
[���*��P�
4�J���@M)�:fM����:�1BvVV�v�����H5������@c@�4�h�������k�h��F\F�l-a5�������@c@�4�h���5?[���}Z������ev����%�f�g�����@c@�4�h����������u8�Y(�<Rf�^����������@c@�4�h������9��j���'��q��%��[2����:��x�u��o�1PS�zaM���4����~�T[K�;����s�:@i�7�P(
�5�6��:�|�L9#���$���Q�u��o�1�P�
4j���/]3�S����������������:��x�u��o�1P#,��J��M�p��B:�����%,
�W^B��J����:@i�7���Q�_7~�����82��f��{UB��J����:@i�7��&k���3U�p�Sc��,�)a����t�9@�4�h��x��Qx��5��[����g����2;P�q10uP�n�7�P(
�5��c�5�7���u8��_8��&��:�Z7�h��x����zI�������t��Z��I#��4|���@c@�4�h�������t�������h0d��jk	���ih��u����:@i�7�����ZS��H(�������c[Kh�;�uP�!��
����@c�Fd�e��-	7��'��W��@����(��
�n�7�P(
�5"��'�d^��h�g�������S��$��
�n�7�P(
�5�6��:P/�[��VEY}:�yz��
�n�7�P(
��#�rJGv�~�u8�^B���cl-a���Z h�o�1�P�
4���p�tc�����K�:G7e��%����u\����
����@c�~�#��	�n��Z��%J�#�������k~��ZGh�o�1�P�
4���{�t@g�t���k�#d�g�hWfy����:@�@@�x�u��o�1`?��KGsV/�:P/��s�7�2:|Pn�����/Gj$h�u����:@i�7����_�I�q�����ru�9�r����,!��7M�H�0NP�A����K��RQ�dJ�
�%c��I�_s��:?1�[�:!f�]���b�v!e�pk���BH\,�\ ��#\�.�Mb�Zb��\��r�kK�W�K]-_X.~f	kc���%�?��o������7�����������>a�~���<j������f��g�����9s�_���_4�b>�Os��������2��k	}�]6��%��%���v�������Q=X��Z���\d�b�.����kX����/��n�eo!�G�^��7��Z��NH�EL�LoV�����;���Ow3<��cb�I1�����>]���!b^��).K�h�x�}��	�#5�JE�Rq�d�I�<I0j�}7P��@c�~�V�dM���:P/���)8| �s��������5	4����� �s�S0��
nH�X)?J�s�evF��d�#����G��+��S�V
�K�����y���Mb�	1#��!�s���R7K����K���%����o2E~*�����f�g��"�ek�P�->�3k��4�v��������_0�l>�d���-����%���[.|�\v���nG|����.�K�-Q�,��0?~e 3�����B���x!n�7�9���L<7�3%,���������������-m�xg�x���~��de��>����+���� Q^�_��.2��2
\�
nJ�I�)��0g2�[�L�B���0�f\��Q0�/����7��������l�ug�:���Tt�����~#=&���FA<�1���cX�	)�p�I(��Q��`�`^�������s�1��2��N?&���lo�9���ziH�Y'X�
�5��?3�Y7i�*R����o�����)<m'�����z~H��[Y5��IH�(��"�Z��\�]$�a?�{�V�K�R���z8q���1��F�����o�J�F��!����L���&������5Q�k��`�A�)b5��gPBK`(o�\��JK(��`Y�.@�9��
J'(��������,1H^�r���XsO�����0S�h��Y�}�/����2sJ�)Q}�Rw��S2�"��k��}J�5�((NRj���[��\�N�s;�_|c�?���?�g������3�7�Y�k���86�L>:v�3������[���������^W�N�/����lT:�'�
(�K��I�#;�ak�6��b{�]s�S6�M�%�-{S��b8>`�4�%3���C�cy��6�����3	~�����s����
���	z�U5��6gC�c���_�����x�
��#����3?����������"G��3*G7~�5K/���:P/�>K�$��5��+�MfIJP1LP���-��p����a1R~�.�������a.w��V�n��?�D�
�M���F������������J��(S�������'�������p/!osi@A�'{@7k~n���u8�^bO�n�����yEW��n�h4�'���*M��g^,~��xm�<)q(�g�������NJ���f��!OJ���f���uF�g���<F�'6�����^yP���t�'lP#�3���W~o87�6�
����g�$$-c��R~a���v�yY�l�5��<������D�������%O;"�;�H�#�s�y7��_!���L�s�S�/6`4��1�O���F�>R;"����~z�#>���"���;m-a�e��dl�
6vs�_���K�H���N�����O��1�Q��4�?� �Skf.����K��),4lY[�fv����a�a�zO���	�fY.�a���
k�.>�2���,�d�^a���[�������N^�3#W�[����k�V����1�=�B�����l������b�
�'b�z���
�����9����lp�(]^�D�>��?'����y��V����-��F�����������b�R��O��F����f���}�T����������3��M�[3��V���*���������_bS����S^�%�
~U�
�:����r��%�?�J}�����@�6����Mn+����)���m/O$� �%�(�����"
�y�=��b��Toy~o?y�q�������d�!�)�����o��c��hy��X�)zm���Gq�����K
�0�����Ylq-<?��6-�:P_�Qe���;cBEW�3���Z4�8A=�rKj�X��y��F&�{����+��26���^eK�cP^����"��cI#�M���"y	�5����a��Jl8�8[��ru��F���d4[<�0I^[#K^^R�U5�
�A����>Z�N
��4��V~�7���t~�W�Y,�
��Yf�]�5fW�G�����Y'/������&1u[u��=������gw�+��������aK���0qcK��5i��+�ga�5ON�+����B9��=[����r����)���zB�5U.�^���l��U��=�������a]=lm�8y���z>	��>��#e��f/[�%]^�%�}������~��!�7��k��������Y��G��Z��+��s��C��u��
��u����	�-Jr���_���{\��������A`���w
�����I��X.�&`��(�(��&%�,��H9�`K����},�b+z���R)}K�(S������*�p��R� ����@c�N���lGg��Wj]���������G���������@�<.�Mb�s�0q����G=q1�6��V��.o�v��{g����:��pX<��f�a����� ����@c�N��CJ{�2J�p@}�.u�����4��@av�������8)�+d�,?����E�%f�������:@i�7�����5���8K�p@}��u�9�r��>]a��������8�<1��%z{J������/��5WB���� ����@c�N
��]�_�p@}�QuN�q����Tt�����B<H�����,>�����W���b�i���u����:@i�7��J��)�q�v����9����viEK���s����P��,����~l��{z��OY�z��[�#~@�x�u��o�1`'yK�������9����a��I1j�%��o�!���M"��k(0�]!~�����h�o�1�P�
4�$w�Dk�]��u8�����1�yg����+�_�H��:�v�(�D\�j�&~�\�/��fK}�Z7�h��x�;�3��c��Fi��p�s�L����/�'E���\�j�P(fy
�&�����$��GB�B1�6�A�x�u��o�1`'��:[l����q2�3,1�
�6hG=�w�#d���N�dO����/G��/��I�
��O����g�ID��d���=���@c@�4�h���V����u8N�@���wg�=+���tu��N�S�=�{EW�_0]���}w�`�D�D7�������	I�%�UG���
4�J������&�Z��4�_���������b�9��sF��s
������+��}�������&A��&���%��[��u����:@i�7��!�N�b����:'��/�����G����=Z��\�\������*���_��@_��h�g�i;�M"���I�,����j�-�A�u����:@i�7������e���Z�p4F����������P	�_�a�I�c��F���
u�GZn%�L�A�$b�9��~���/��U-<�n�7�P(
��Pz��B�N�u8�Q�`	���G���KRa"[8����}�Dq��Q�
��B�cY��U�'��x$�^�&�M"����}�r��x�E*�P?R�n�7�P(
��@��5y�[<W�p�A�9���7��b��2�YB�js�+UN"
o+fxh�&�G�:G,,��eeEK������G����a�D��7���]+�������m�h�o�1�P�
4���g�`�/+�Gm�s���^!n�$����c�-�����B����F�g�s,��t�GVt�9�~m��mlN�!Z�$����Q{&E[�����:��.��6�P(
��`����3���:)J�\�S�B1���4�Zb�5�<^��B�X�����D8O�St��vW���%��\g15jc����M"��k(0����X�w���Gi���u��o�1`y��Y��B��2�NH^S�CR��)�j|-�NH\RM�m��R�>��M8�V�wo���A���_�*p��uh�!��		->�ke���~��G$�S?t�lJ
h��x�{��>��*��:������Q�k�:H*��������e���
)y���<8a�#de��Qq�0����p����$b����vm���%�!y�d��u����J
h��x�{����$�c�
��;��|��?�� ��%?�re`����3����)�a�s&���1G_����+��=Y�s[������g��ID��B��z:r��J
h��x�{����5=����b�n��sGF��E\�W���,�z+CKT/1����:y�S�����myW���a����ut���*�l�\�f�&g��\�.�l��=N�4������bcnQ^V�.� ��1�V~Zb^J|n�5]BtN���������+!w��n_�O�p6%�;��WR��D�#7}�o�>x�k�������9�=�m�U��������:r������.
������!�f�_=���iA��.����X���|��3g����O?��w}�&�9���q]���xtD�a�����������-]{����m�#�����`�V��n�6�c�At~��C��82�������v|L�c{y��+�99�������<=��8�{��3�(��g����?�����?R`�O
���������+g������!t��~���$|�����_��2����;�^�E�����6]�Oo���.�n���{�>�}q���y��t(����7�K8K������@�0��
�M	�K�x;�>��i��i��_	��J����+�qW��csn����tC�L�QR����;���;�L����6��W�/�7��B��Hk}�P�{�����������8���%S2���i{!��2?yWL��;�p�:G4���Z\q�0�����i�L���M�s���?K�h��p~���4�P��J����4>*�ZDf4��!w.��R���}h��d.�]�M^c��j��l�6�NO'�����^���Z*2J����R�4�B��`��}M�h�6��D������/�~���HRN��c����z��H&�k��NM#�}�=��;�m���$�1���-�������$����NZF���j��5�B�.]O��)l����$�e���pY�c��]$�
Q{7^�Gj'��9h����c���v�~��O���_���3G�A'�z&����Tr9h�[��RB��t;�\Z��B�D�g\���K?�+���s��7�K��M��������;��N?�;Y���1�s���C/�+��U#K�������8!~v%�q�����j�!�Y���2]�o&��/g��KeI���MEWH�%���c����r��]�D�5�\�ZL�U��b+B
��l��f�L��C��
}��������T]����R�|SB���J
�V�X�Yj���6q_�qj"���S{�2�Wj^��o�����
��Zs�!G�>:�Z��������{��Y��o}��?G�M�h�5���6��Gj�'���d�e��35�t��r'9]vf�Jj�g�
����SvJ�=��Z�/�������R��$�����-���)��P)X����r&@oA�Q�(w�SJ���+�����N����]�f�s����~b����J;�rw�?�z�o���y���cr�@����x�	O)���$�7>%�/��I�<����B���r'*���u��	F����iF}}���d#�&��t	r��DY}�r��B_wR�m�~���$UIB�����$�TD����<�I�E�y�C��`. 	)����'������q�I�Y�C}\����h�c�o�������/�����A��Z)$	J#I-�R��+HZ$6����$xI�Nj'���`���\w��i���99���xJ�;E��C)an�6�R��]�h������.d��^����p;�t��_'��q$lc��*��B��j6��)U������*'�^$�Gi�#�/~P������CEW��j�h�w��,E�S>L�1%��3S�L����%��)'���B�ekZx6����*���GO��q�������^�{���G_�q���G�����m<��
�Z���J���y���w��s����!_3KN�������P�0����0M��5����'J�C�.���C�;�3��|�L��� �\G���<��m@[��$�O�}�>X�P��c�������@��#:I��rlt����)v=N�#�+��'@.�����s ��������{3��t��|�]2��j���d��e�t;�5,

J�(}�&;6��s���
�G
�:Q�f��Y���cA��b�sp�*]aX+1�M�(k�c�`�������M������S��O�K�$�z�V�)�k�x����3n�eq�v�{������6�e���?��d��O���t��O����w��MY����+v�SBX2g��c �[�MR�J�*���W�((((���t���������}{�N~��*m����j|�����+��bO�-������%����^9������~����0�<�����;���xy��������A�f�jb�o�>r��D��WR���\@j�<����WS��Q����
 �u0�I~�l^
�tr�2U�x������PR�����ql$����X�_����~���N�X�ce���/n_��pl^��>�B����!kf��O��s��c�ftr�b�T�%���h����*�C��c�OO�&����>''�������'��w�����GGP����P���y��}P����w��k4�u)��;*U
��s��k-�h��B�J��'*��{VL��uh�s|,������\H\*Y�Z�i/d������w�6�Zj)f�[A5�7���NR�}��*�O���((((NX�R}t�����T#�EK���
XD.`z��JY��Z
2{��T������&oR��
���s9+.&�F�.Q^r$5%�N�1��y���H����V���89&K�I6�r�N�a��Y��)%�rR�^�dR���<9������m��B�D���D����z�/%���y���+)��y<�������t{�����$c���_c��E�N�&�����\%?-�<A?�/ld����S��g���.;h��l�"y>�B�;z���J���N?:��������DJ�������������i/O��l[�����z�N��+h�]�������-]�u8uB��T��`��?B�H
�� U-��{!f�d��:J��1�jv<��TR]G-�����3�*"�p4OZP�,�^we���=�R��t���xj��yM��x��l����kG�Q���&�?�o]���n������������~���}wn���'?k��~�B���?��t��K����.qj�)�T:��x'�S���R'��Nrj��%�U��I���*�t�����nsj���W:����{D�B�P)��.w�+}���P�*��*)��K����Ur�:���/n���~M�	,	�L���M?�m���R�B7,]??�%sC��'6;x�,��}���1R�0-h�wAK��>�I��Db�����+�e��X�<K*����BI-�x���{}M�`<=m�)�QOi}}���99��J��{yN���~��O��v|��x�����H%����p�	JB��$��"�ld����:��GT��@��'	5�y�UY*��4J���T�R�y�G�T�J��[����y9G��c��T��A�h���4lY�u8�����|[��
~�L������ $�1���I���Y'����1����)�cI�J2)?���9��P�e�KrB�A��~y�[g����~�������sm;�`��[
=����>u��1����I�L=�u�����?*��xa#y�e�/�O'o�,_v�:%�������!"y�����(?��-��}�6?���FbP�����y�'\��[�BYv�|�Q��'��_l�����G*%/�,_�Y��.��1f��I5��P��C�N�c��y)	��z|.������t	����97�Wp5��PMx9+�@���@������hrR�W��Tt;�u�I��78��83��o�1pO��/�����Z�S��;�~M+VK�Y��j��u�r�]��H��S��^
jzYJ��������G�|�����S�=����9���B�uh��tl�u�:UIY �:5��A�Ea���Pk/���W���]/y���C���ouh������������������W������D�����5!���]�>%�M2���]�D�C�>M�9�U58���@c@�4�h�����~����u85�k��A%Ci�]��v��1N�i�y�r���4[%����sY�)gn�^?I6��',��{���U���q�phX����-#��-������"�u��x(��lA�m��S�S2_�����=)&���N����1B�*K��f����}��\�-�v�������Z7�h��x��{�;u�5�-
;�u8v#
�3*I��.fyi�������s�_��������>��}�^\���5���[y�[����{m��81�[�9��[������n7������^���������3�}Z�6�������������ZB�n�s�U|g����4�l@c@�4�h���a}�)���5���r|��*&�������������)�WN%��;�>j�����p��/�WmE��n{y�qv��s+�_���v��O����973���{� ��h�_���%������X�S�����,a�����g�������Y��;��4H�����@c��d�����
YZ�s/L��K]+^���d��:���-���O��~�+)`��ck/���n������v���������^�F��;3x���_c��%�=����Y���7���KR�n��J����i���re���9����
����H��P��+
8	�P(
���6��:�{ $.5���|���T����Q�����I!w�<�w�Y�c��5c|�=9���!���O�w�����C�pw��^;"�O�
N���K�*To����9&��>���3��������� +-�/
1���#����;h 4x�����:@i�7��1?�j3;��:�*a�Z�PK�pu��]H�|,���1�WD��
^5�w�W�?u���sLw����)�1�������	�����W)�\�PLwU������9�T1u�%�G��+��<f�� $����cv���+
8�P(
��c��d����iNe�u����$�jm,��z���q���g���sr�h�����^�cW���~!w.]�M�6�V��{�r�O��$��lv�ZO�5�:G�$br�=�����A_��hu�A*
8�P(
��S|9��1�qC��<b�6����S�����p�����x�p����`��5V�z'��^�I��p�����f�?V1V��%�[�l8u�1VH^m��`�&����>�7���N�+�&���B6��H�QpV�1�P�
4���c�����h�
���o,x��
���-�������k�X���B����k���'�����'�����b�V��7�\���gb�q~w��u�� o1���]O��+��u�n�2;�.��L��
.�"'�Q�!Q����P(
��Sx�������Q�pd�p��J�=������_��R�7��\�{���(v/,��&v�N�����.U���kx�mR/����B�"KX�<�_S�����]Rq��5D}n�����I��K���V��S/���P(
��c���t���h�$fx������3yo,h�m�z����*:�agf��nr�;/L�����OUnm�>)�M�
x�zS�g�i{,W��I�����?���_�-g��J���0�����k,���z4�Jsv��R�^2�H��>M������R�5)-ZJ��nEHI�����@����#����=��G���R�A��~)l��C:�]:�Y
�E�[+���|�K�K�S?I'H'�J�fJG�K��Jn������}�J{�H�I;��\�H�zI[�I�:K�|!�o/��DZ�FZ�������������oH?�*-����i����K��,���y���I����A���4�ai����w��X����gk�Z��O�PL����+���ZK��o~��w�{C|�91�v8��s�bn�3���*�Nd1��Cn�����(��c	��]C��D�I����N������+�_�T4�szk�
'Wh@c@����$S�T��YR�)7U�I��nJ��;1��+RJ��.%�H7�I�R�Y)�[�>)]9.EyH�nR���W��K:�"o�7J�%�5�������E��B�s�t|�tt�����>Y:4^r#�!�&�,� ��O��������������si�g����U���H�����7��ZH?�[Z�i�K������f<'}�Gi����>!M~\��;f�|!���(,,�:u�o��-ZT��l^�l��������>���m��qww����������i��=�P�������Q�f����&L���d�����������N���&������HYze��(���}k��=O���;x;�p���UF�:a���J��BL�\�[8c�V�&��b���|�v
^�TH\"�_��=�����-af���UW�;qF���4���r)`�0�X!Q�'�T�++����
Y��L�d�����}����
�*�6�C�
+Ild��fX�d��K<3/���AVbY!;�-�����r���()�+�tnE��"+�z��XI��Jb(3AT�K	���!b%�
$Q!s�{|�������u_��������#�%wf���1��+�KA���
�]Z)����]�/�#��i�]� ����]�F�5��%���.m����/����]Z�Z`z���%oI�^gv���cvinsf�f6�k�����#�{����oh��W�����_~�>�����hl��%�6|������'O�n���I&���8��I���~���!!!d$y�rj�����H�����wK�.���O���]]k�7\��h?�I#��jq�=�����3��|N�-�-��C���[��k�a���c,}�f�G�x>��lvn���]�y2(1���I��v
���;V�����`����<��+���}��7j�����<��a����%����R�'����C���	w�x����4^-�.���w�Dk~�$�JZ�d�rZh��H����0�4�wD�a�I6����,K�r��D�\1���G��1�M�<�&&Q�x���D�r���l����,���&,QJy��M[
��r�s[��%*�dnd�(�X/��c3�(��]��5Q�yv��tf�\�J�?��N���^��;y�����?��O��z�c��(A�rl�E������	Q��z|��E��rW�Il~e����YR��B���h6c�r��#���}�Yr�g(�@E)���l%�;���?�REI��}��*J}���Wm��r����<+��7waeSgiS'�o������x��l�e��>��}*��D������Hk��Y,gn������*+�gs�Xy�
=��_V�����T~~�����+��d	��j!��X��U�~SY�/�����T�����2�e��$�{Q./�,������wi����Wi�_��gV(����\�$}�T.de����gX����wOK�=�
��S�`e���{��S���`F�\+�c����f(((��P���X,c����o~��g������8��9r��HQQ�[o�E]\\������KHH�<t����+����L�T<):������{�.b����kD�7��9��&�i���nl3��oHy|�hV�|�{�Z����q������e�,�i��W���(��~�xM�$������//��|�������-!��?KY������(�I�/��J�O	������J�R��+�}IV������������2}������b��R�v��+I{I�����Ku%EW�s�����+i���+�8��%y����f��{S�]�u+)��o+�6��J�]�`����W��d9�.I��\�e�r
���%�3����YN��l�$I�sc�����+�����\W�r���$����$V�]��UIV)GU�����5��=EAAAAi�e�#���fh�3�kef3�ZQ�5�e��Q�F�5s��Q�G� ���,R�H
%5�[��f���_������f����cY'���LS{}|�I�����3�X����S��%�$P���:/a}�1^,��|�JBCYZB�I�U�Q�q��1���oG��<���BM���������6m���F�?i����`TT����������/������Y�f�W�������c�]��7�������=�v�Z:��k�m��	�x�=�y;5�c���������Z_��)��3���r���Z>t���w��\�����n���U����j4k��Y���[������8���V,�K�{�K��%��J'y��rIxI��_��u���J��������I��? ����@AAAAAile����n�X�L
45��jS�M�8�����c�����e�e���>bc��1�g���:���m�X'$sL�X���o�����X7���lR�������6�{	��]��1���7���zS���y������G����Sl��u?6#�<����:u��Y7o�
�����z��3���B=�O��p��[*S\\������=�������?���q��=��t��	�Ar�>� ���)w���s�����Y��������g�.w���/o��Innn����w��s�j}��c�+3k1�5~��V�|����I��[o0\�\���I�~���Y�Rf<���*��
VK����
��#w�y������R9�����<=�MU}�e�����LgeS[�dE�����%�_�T�gYQ&�~��yV�c��T������zY����sQ&��m�,+����/�L�ew���2���2��M�}�e��O-�861�MV�����~~�e"����L-^�?�M�����-��^Se*2�K���}�>cL;���=�5�;�������6��>���ly�i�<�����zy�i�<���d�)��
0]9��b��0%����W�0�������F8��0h�~��{���^{��G77n�8�777��D�^_��c��)/Y�hvv�r����������K��ZS�;�1Wg��E-�P'�B2�����Q���nU���}NN
��������l!n����,�~+��V��a�o����s��QK�u���R��<��$�J�i�-����R��'��f��9����$u������.*��5K,�"�}79��MZ��nB�!K��j�XZ��
�r��p�'lv.�����~�
��\��/�p�9��lb���lZ/e�[��Y��Cn��:����I�>��:��]?���?�-w
d���$s�6y�R�}�Y�����{#YG��h�|�'���Y����Md��)=<�u
y|'?8�����e����Y%����&3S�zr��L)�������"��z/a��)�ee��?��e����i�i�����l6�����,����|��r��ml���KzCw�'%)�������e90�L��Gd#�_rg�Q,7�|�=�I���D{�y��;���/��f9��3%k}P���+�����%���B�C��!�YQ��4[Y`�-6��������)�8I+������]�K4��NEY�$�������If|�r(Y7Y����X
{�U^>�-������
[h%���J:+�b,��,���,�b�)y����B�\��]�(���c�������7��t/?h6��4iB'�\����]�v����mk=2�|:��OT<9**Jqg��Hddd���z�)zi����_�;�K�M����W�B�(�(1u+��T�|h��#��j��5�)�t�2J�(��t�RDJ;)��Y����/P��P������%�r����J���}%���|%�W2|��K{9�WRz%�gSb�4^���^��-��5
y�4�IS��L�*������������������Sf���%	�����8��JnM�Y�-'��u+)wI��d�+Krl%�V����z���ZN��\�$�>x7��g%sf+������2�g�3d69GN��LXI�����]%�-�o��VIh)�U2X%qU�U%M��T�K�t�b�9�n�+���:@i�7��t/?����X�]�vU|u�����-�#C��#/��b������K���W9�{�n�HJJJ���������_�;��������'�#�"f�(����n�EU���u���1�������2mJ�/�f���\z3{B�f�c\
W�w����
U��!WBF�����t�]�9W:���Jz���q�K���_�R��W	�,'��y�rT.�0S9�����_���������?H9!Z�5@4���^Rq�����M��ZG���u����:@i�7��t/?x��5�R<x���������{�9����{�����O��t��6m����q�r$++������O�����k����5���V�+��-����~0�����]=U-������=�#7��r��m���>�����'N�_�s�������~#�<"zw�����:�9b��7����M"_bF�����OVm,I	���T�'�����kZG���u����:@i�7��T7?8v�X��`NNN�����b]�`�;��Wk���jq-�P;,�����k��AU�������C��U�wCCS��F��|��=������_������;�s|S�`�"W�a�H�'��a{��L�o�7����H#;���M�c���T�I�m�y��AH^-�W2�=��U���0o�BQ�%�'h�o�1�P�
4&a�h�\6Z�N�����B-n�+��D�2�\���C',J�Ku�]L��=B����:��-���'{�l��7~�o��������jG�g��EdO{e��'jQ�W~�H����R��Y�^'�b3��gH�^�w���Ib�)|�NK������v-�Y��Nm
��k����
����@c��)K�
7fL�����.�O��-�I~���8���|�~|p`E'��}�k����vD�\=�wt}���).c���*g���^7Mo&���C|��f��z{���=3�����y�����Z�������<Q�}+�~25`��P�r�79h���]{<������m�]V�N��i���C+���x����@C�N��`��~����}v�7q��q�%{��0�Ku�o�����'|k�6��n�-��>�3�f�g�y���������C�+:���n������'���U�qG�%����}t�zr|�������Z����$&�|�S��h�In���4��I,���{{���{�
J�#�"��T���^���������]V��Y���5�������������)��B1�]��"�=���(�]�����?�1&����>ko���'�����4���Ii�.#���+�c�,I��Y~�aYb`��/���E�R�D�x���q*��0<�������\��C������T)���h?�������;�]��Q�<��FH�^��J�:�`"����Zi�m�=�H����Y��9��V���o���Y`��"��9�5�^fk~g����|��^���)Q�Y���&�tIX�2��irx�$��&e����7m_Z2���ZSa�V���]����H	5�@���Pc�2������U�V�V-==��������F�Q0�����,����[��n�:�N777�����L�����)
���Xv��}�I��W2T'�3��`�0 �������.����["�%���D��tg������s�um�;����.���C��������)����pY�4�~Q?�[�w���]yirs�����'E���@��^*�@l�1�*
����!j3f�nOqq1���s�NA����Z�j��[7>>�����E��5k&��#�\�411�~���"�R��aaa����^�:E���Xv�������*�"eRi�B~�����|��[�Q��6����x���F���7v��wdn��y��`mv����2�'��Eu�
���L���K��i��X�&#/6������Sa�����8k�u`t���@�4��\c���t���(75m���1((��qQQQ��-����#����o�6mJ�R!qww�Q�F�������b��:u����;111��i'=D
\]]�1=�I�&�tzA��+W���'�
�c�'�Z�����j�*�}��P�H*�k��|�� ���s����O�{�����hW��n��z���.bN(�:��Z�@������9�t��m���_��d#�{x�5���=����u�������2�n 
�H�b{�k��U�1
�&��T*�k-Z�����A��~�������������S"�Y�&��	&������5���zbh�������7o��Q�F&k�z����
��hJ��|m0�hy_�����>��Ip����b-|�I7�1���0��r��20�����eV:�
���
+�#aF���'��}t�z�G7�j��J����4��Tn2����H��I�2��`��r==����'''A�S.%������0�1N�������}�J�r����l�>�;Q�>:���@l�1�*
�������p��p�����"Iu�w�+_���19L^>��������Fv�v�Ipb=��9ZE������>G2�K�3�v1N��K�ir��}t�C���Pc 
T�
5�)��M ��O��X�-JB~��A�����eyVi�m}���h/_>4?M{h�����-���{���H�h�������v����k��Pi 6�H�bC�Ai����������-����Y_L������|����yJ���ei�'3��1N�{isZ��^&�s��NO��?�x�0k@w	�+j-�4j��J����42own��w����Z����@�LD�y�SvFy��|���+S�,�N�(��ran�n��v�����{�|��XKqDX�`{�T�;�Y��l���<T�
5�@���PcP���[���!k_X�(�B��g�.6���KM��"��Xxm�qsa~ln�e�sn9s}�$��seQxf�s�K�����w�TX�m�V.���Y*
��i��@l�1(M��e�\q����w]��)�%7��/j�M�Y�oW�� 	�>��n�������A�q\��66����C�cu�������#af��s��}t�J���@�4jJ��`7Q�3���`�uOY�+u�*�L$�6��T�E~�tl�y��0�G���D\��6��-&���T%q��G;��'�hz��Gg�4j��J����4�N��)����)�v7E�L/�j�������������G��(���nyi}a"	��P{u�%��@�S�(������8�Z������=T�
5�@���PcP����q����n�yp��g����Hu��>^l�U��i~/7��G.�vd@b���z��]���$8�����d	�}N�#�nq3��]��|<�}p�J���@�4jJ���#73����A�5?e��� �L���R^�,�/�������;~k	��+[�H��_����UZ��X0}N�T��0w���{R�/����U*
��i��@l�1(MJ�_�9a��l�-"�"��jR|m��|3���=N���A����<)��;�H�N��^�����Tf�7B2�u1N�y��3-zW���@l�1�*
�����g�\�m�o�O�������6x�W���������3�z���;z�H���w����7_����T~Ewe��"L�Z��f�C+T�
5�@���Pc`�:3�����n�I�;����TW��_��P�L1�xR�~\��>�V��P�o��$��'n./=�9�MNV�?sL���_���>�2A���Pc 
T�
5&�<����w�����E��J��R�{S
�6�y�Lc�}�)V�3dh�7����>����l��<GTQ��}�Sa��Q%I	�>��@���Pc 
T�
5&�^��~�{8�i�K�K�+��:��s_��l���ho~t��V����i���N�k"	.�Nw��/��>��#?��������JST��$�J���@�4jL��;������H{��\���l���U���<x��f��&\���'��)�}��"��"��7L$�E_h�}���`i�s�G�����&�I�����1k�i�4j��J���������)��������Hx���O-���>�����Jky#�6?��58MV��}^X�����$8��6dO�_
��>��U��3n�q*��_u'��G'�J���@�4jL�Y�U����;��Qryp��SNU'�|m0ei-����z�[y��=�;�+��s>0�g��
p+�K����<�g3{w4N��K]4�9�>:=T�
5�@���Pc`R��e�4���nvg�#�)�m*U�?_-S]h�������54��|p��r��C��M$�)
�G�e�x)����RQ�scz����G;��y����=�J���@�4jL�>~&7�;��(��~����s�K
��G[�������L63������e=����_�H����>S��J�N|�s^�����S�
�t/�a��C���Pc 
T�
5&]<������o���2:r{��o��_��)z^i����z��L�u����$������������`(�e9����9����V<0T�
5�@���Pc`Rh����.���V}���SFi�5qUM�y�7��T�o!�����k�~XI7���2�w��f>������y!�����Z�
��,��A�,��i,�bC��4Pi 6����37�K�L�?4x����}��8��Vw�7#��|�e7��������!>&����e:	n��M�]�
RC�������/_`�P���Fq�O��A���Pc 
T�
5&����S�<��>�IK�{.<S�dpY����/�7�(?���$S��MQ���
�����?w����T�w�G�7N�9�������HPi 6�H�bC����|
"g�`���	��4�C��S���^p���G��(��MA����$��������A�
������2m�����K4�O�%��@l�1�*
��c�Q���A�?��im������OV��E��o��9(��������X`��y)���$A����,�9����$4rY��U��0�����%8T�
5�@���Pc`������-���d�����%�q��e�7�f�P\�C�}�i��c�8rj�51��?��>����@��R)IJ��4��=)���"D}kT�
5�@���Pc`��`7m�8��f7	.,�
�X������dY�}�a�?��W����s>4�?�fZ�#����y	)���u5N�yg�33DzST�
5�@���Pc`�s�}=��f�����v����"�}����1w�������-�_�s^ZE�����,L�6?��!����@l�1�*
��c�{���9�L��������f"r ����Y�0�*t���O���x� .�/s�	x!��y��33��0q�h�n�+-�^�4j��J�������[���q5w���
{a���#
�C�6�������;9R;�_ap��Ze��>X�(��lo���F�$?�����@l�1�*
��c�/�fh);��o�~�����������Zq�
�;��7��k%�j��a����'��}�d>]����M�5r���>*
��i��@l�10�9`��/�G�>�������
���H=���w�?�81.OY����C��_3���[�A��>8����U��#a�];����`�bC��4Pi 6�;�s71S^~��zF�qa0���=��i���+�0��{H�����>�N�g7w��'��}����7�8f����5{K�Pi 6�H�bC��@�B�m 7%+������o3�e�<�e����6�\��p�;9q�>��y�sm�0���?T*�s�$��o���q*�_��&�"�F���Pc 
T�
5�y�[��q����x��5�����$����G<���WS�J}~��$H����HP����R���[��#a��/�#��b�4j��J���@�A��^�?���S�2_���'�0��?������-���>9��0i����0O���;���=)l��n��uPi 6�H�bC��@D��?{Jk�}����W(�����m<�Tr��
���c3-�q��A�eQ|#$k@w�T�7o�:=�,��J���@�4jB"���WR�_�7V����f�zk����}����)�"�������,P	����+:�'����T��U��MZ���sQi 6�H�bC��@`�Cn������%y*����L��}v���0�����E���K���a��A������_2��=)zwR�5�DT�
5�@���Pc p�x7�����u>��k�'�^|����2����y��e�����Y�l��@e�>*@u'*���q*�qV�g�)�4j��J���@���`n�u{�3-���P�-�=.�n���=�_XH[�#��9k�a��^�?T*�s���'�3z�e�
��k
�Qi 6�H�bC�����~�,+r����i2O��$�-���h�8�����v��f����T�O-��po)?T�s�Yh�
�\M������^���4j��J���@��2/}����f%7���$�H{�-��`'6r��iS�a��I	?T�s���$��8
3N���}TQlT�
5�@���Pc p|�.nr�d��F����F����/%�p�Tpa�����0�h�	�3���i?X������;��'�����LT�
5�@��\�
�B���5�"MQ����M~�&/��rs49Y��L�����4uz�:-U���Ny�N~T����QRIR�%��$����/��_� ���=U��=�bTw�U1��-:R��q��8"�8<����������G�5����V����du�����6�g��\pf
���i���)��:�������{���6�
z+��V���~L��k`IJE�����0�C�����@T����nJ/����O��9��L������i<3�g&���������=Fu'���^���z��'s���7C�o���~Ur�����W/)�\T^��
P^���W\�W�S�U\�S�?���U�;�8{J�wR~����������Q�I�Io�	/�1O��#���e>2ow��!��A�����2�}2��2��Ew�Ut`g���E����V�gk������T�sc������n[W���p�[��5��Vl\U�aU���\�h[^�fi��%��jq��E�+��.�_�w����K]���6/��9y�f3��Yy��[0=o��<�iy.S��N��39w����sg:��t��1!w���i�r����2&g���I�r&��q��<<�iX����C��f�1��G;d��=r@������e����'kh�������g
��5�.��6k`�����w���5�_��>�3{w���1��Mf��=�g����m������ft������������3:����%��g����21TU����X��X�����b�?�c���6�^�Q�����Q����a�h\�.��SI�m�~�����\�d��XM�hz`<�=�kGS&k��*Ko�|��PX�)��������Aj�A�`�������UT��v�n��&/w+�]a7��AA�M\��|q�.t�B+(S9�
6MpQ��[��&�'�A�V������F&/,���'I�b������I����t@�@��JL�8P`��>��l������~��1������~�l�5skT��?o�|l���%6w�x��<�+���
�	+�'�~H{��N�������Mw08MtJ����+O*z�)*-���-�����j�w��]e�A��8����5��4��G�2a��`M�9��� ����_
�w���K���Hv�~��/��y�Y�8/#�b� ��A���Y��������e���.U,q�_<��������y�����N���f1��9��C�����������]���^6����
���	�6l��n����X�t���rBn70��D��K�7���ws��;4� N}S�������������C��E�'W��k�/�A���M���6��kdE�)'q�_���d���.��X��P�WO�K'G�&E��0�`q��=��,�V?>��I`�_�sz����x�� ��%N�	T��$����������T(ne�C��v-�>c��
�r{�G��?[%��*�����%���q�~���m�����v�k���v�m��N�v1��Gw�����#m:���Sx�.�����-�c��N=nv�����zg�k���u���7mW�������n�/w�w���K�v���b��'��Xu0+��c W�%q��j�/���iU�����085h��va�ap���iwL�]f���Z���r������Y�������o�cJB�K(T&�h�����C�Q���d��6l��)=;���<o&�L��9��
��N�u�����=�K����u��_�>�B�!������c�9������g7��n����vcN�{������N��?n�t���1�zO��=����x��z��t���q��L������:�o��~s�������\����w�����p��E�.�9p��%��nsX�m������y��M�Wn�j������Y?d�����;�ws���q��a��8n^5l���[W��b��#����|��e#v-�{��=�G�]<j�?#�-u`���G�{���=��9�2�����s�z��5w��������5���q�g�?>}��i�OM�@��)�Lv����7�����9���N��&�?)`����&];���IA�'_5����WGL	1%��aS�;����n�:xZ���a�o9L�8#r����3n���wfLf��k��^�bi���s���q�s�z���>7�m����}�u�����;�K�����%��%������3ik� ��t��l����=��5����������GKn�_I&��7�q0.OwRVV�v�k�08�Cm������Xx�d����kE����B�5EC6�&���<$��G��W�=@y�j��PU@4����ek�P�V�<�?��8���g���I����E��c���BGL����A�Mg.t��l�.B�F�[ `C�.n�`��5���k�q^�`�����t�b��~s)V�������P��(��q�`s��
l�p\�n(���Lj���l�.&2��������1a���q>�t�E���R(��d���S��`������n����{�����u�v��N�i��M���>�ck��Y%����$c���4m��Z�uEa���=V�f�����"��^[�����:f���h�����m�MF��[d�[e���(��_�1pm���1;ecw����-?���0�t�}[n�a��WR������L����Frap~������`�8�Z�c�LRo�WR�������?�1~�l�!�Bo��S
����������$��:)K�]���X��e)T��R
�9sQ��"MV�&�@���I��$�hfk���34q���i�{��;)��d���j��v+Q���WBr�$8�������%�1%�%��T�n��"Tg�U�o�N���_���*���^���{�R|�r����=��w],�yQ���r�y�f��s��~�ug�k|��O+W�T��T,;�XrL��Q�"��^����yG�s�g��g�O;(�z@>y�|�>����=��D�������a�����e4���F��q4���G��i�����D;.+l�8���i�x��V���l����A6�6LL��d$?��w:���h�I�0�[�8�o��$2`%v]C���l���[1k������0�mZ�[��������[����yc���%�����&_a ��}��>����a��o7��*����y^
���[Y@��fn+SFXS��@�.����0a7�Ww��r�&�c��)�~����>�z�9L�N��9���{+h����b�Q��_z�(n��@���S
 h�X�������*7�Un:��#[�+�]`�\h�QfO 3����?�}h�v�j�������GB�=�{]/�A��
f��1�D(3x�F�eg"Tg#U�"U���������1��w�3��x�3��x�>32��ch���OTG$�#2(Mi$���n
3���J�����LMb&3���K�pJ.3�������������"f���3#8m2%3���n���@\[�Woi�w�O
x���Y��`�,�i�cx�y��r0��5�o��������.r�XD�!�W��N�B���������&���I_����K���zH�*����3#_������t��zZ�o���Me���du�#�����k�������6��_�hs��������FhP8���n�|n�h��A��Shd�!f�����L����D�����F(�h�ZC���b�If8�q�8�h�����o�a�l�Lw�t]����M�aC�x�R��!��ji��D��4"�������Zf�����i@����w��.����y�h.MA����� �<>}��Vnt*wZ9�k�S��n���V���5���cVL�i�9��0�Xh�V���x%����
{����`}�xq����
��o�x9�
)�W>N(l<����&L?I%�ORo9�I�[��G�D����A����M�|�?:���:���A�c����A}�����D\��������������pq��,(V�E<�l�x�&��c��#�t!"2�q������T.;0�A�t���\X�z�r�M�����A�����*����J2��v�q������1g
���6�:*�����z����)�4��Y4
(�$c��
6��z��r�'�gXM�cX(�L�-�0+&O�K����X��~�D�,��X�e�'��]�S��r[u>� �pk\`�eX��.�$.s��1����~i�E$����Pc ����v=
����V�������W�2_�����/}��.����il�1����q�In�o�h��1t�)�,�'�fbh�����g&��a���Y��a�$#L�g�+�R��b"C)gX�2y����K�3�(D�v���a�3���:�*,A]�3��+C�4j�<x��P�~���\,������<�>|?�be+�������eC3
�r���&-4�9��y����(i�5����M�hX���`�&��&6��'b���K��I�����6�<�V�.���a�
{���1[O�l�6�<�#�0�&6��O����l�`C�������������l���j��\���-���?����V��8�
D�H�bC���ow��W]|����/O����G�i}�A�i�:~���25WC�[�j�����<�1_1[��\z\A3g�N��z�nf��|M��v2Sn�F�`6�������m4'���me�uW�`7�����z�1Sz���������l��~��]�`��F�f]c-
hc.��n��`��	�W����m�V2�����2A����l��q���6J"��^���N�5�
��KO������V�F���wL�,�0�s�_0���Z��d-w&���Z���,5>MK�������h����������	Z��tcpv�n��l�y|^�����"��UN�@l�1�*
��.^w����d���`�_�V��<�#�Slm����}H�bC��4Pi 6�py��WngI�.������_^��i����������8�>Tv�s@�4j��J���@������>����`��:-�{ry���S�
�<�z�P���i��@l�1�*
��.�o�`�hm�W���6>��k
���A�=x�����4Pi 6�H�bC���c�O�{J���[��,�u�A���VYd����}H�bC��4Pi 6�py����g�mWy����^C�s�c��#�}��@��@���Pc 
T�
5\L���;u�,6f��ny�;���6�V[�����>��J���@�4j�<X����vp���\\��W�0�������s@�4j��J���@�����<M�nq��C]�0�mg����08�mA�����s@�4j��J���@�����%��y���nq0vzC������}��<A��@���Pc 
T�
5lLh���[u�
������
����>^x���i��@l�1�*
��6�t��I�b�}�88l���]�����}H�bC��4Pi 6��y0�g���^���_�u�p����j��}���A��@���Pc 
T�
5l����Kyp�����A�y�,^�k�#����*
��i��@l�1`����)���j}����k�7�[{X�0�y�>��J���@�4j�<���S����}Fa�fW��j�08�}�<���	�+�9 
T�
5�@���Pc @y0��7s�j�z�3���o,�]��1�s}H�bC��4Pi 6�X%��������I��5k���;�z�


-���������"�R&LHOO/��P�wnByp��W7-�� ��[��C��@���Pc 
T�
5V���P��]�������������q�5jxxx��E����)�Dz:����k�:u�e���u0�e[�����v�����
&~,�'B��@���Pc 
T�
5fuJ��Y�fU�T�@������W�^�Z��������1���8n��#G�e�7oNoQ��I��Ru��"�o�������08��6+��O0}H�bC��4Pi 6������Qj��������h���]Y^�����7N���o������+��dLo��L�����7��C��@���Pc 
T�
5fu�}�E�9s��_�p����Q#77��+���T�^�����7o�����~<�;�\������ap������s@�4j��J����+++�����������!///�/��������<t��q�����2R�������0��]��T�s@�4j��J��������l^3~��7���,X`�E���O�4h`�Pxx8�����e<��k����q�A� �9 
T�
5�@���Pc��o�>6�=|��������C��7�"�������>2~(%%�}�����'T���j����2>�,���4Pi 6�H�bC�Y��M������i�h�-��>}�����{S�/���������7o�\�C���������UK�g�>��J���@�4j����������`vvv���l|��e=������4Pi 6�H�bC�YW%<_����)N����S����^O����T������&
��~'N�(��&@���>  ��W�^�Y�G���R����4���(��h�B���������	�S<LOO�������������oi��u�,{����Je�f�(�>|�����X�~�Z�jEGG������W�z��'O����f��n������N///zYzqz�?T@LL�;��S�NWW�������7i��F������+W�d�8f��C�����qcz:���+��e����Pn���&L�X�fM
q������������7o��Q#�w		�'���E�����,���F����<x�'�|R�N�Z�j5i�d���&�~���������x���u�~������*���Ylll���_����k����/^4�jc���Z����W-���y`kk[�J��5k�i�2��y����)S�����^{�����>������+
�qc�T@XX
����j��AC�����������������������q����[fdd899q���������������������M��������h��A{{����6%%%�|�
�i^^^�>Tf_~�%u>�O�&K4�\�|y��4����+��-3����)�[�>}�tPP���#���-[����������5�f!!!������@��Q'����:::��	�������c&���b<==)����w��v���������z�j4F�APiU�V�j`���4n�:u�_�~T94���0n�2����e������T��`LL��j���|�����}��5n��J�����1������/]�D���o���T������J��N�<Io����gff
��^���No���*��Os'�_��;�vJ�����;w���_��R��v�;�v:88�[:;;�N���?&&&R�����m4
�i��aVV�%?Tb������n�����A�TL@@@����v�ZRR��?n�8�<�2�
HJJ�U�����[���fh�G}�V���Qf`�K���y��}��W�� UQ�f�����;�3>>�^�zT����5j������N�L~�o���:���T�GJ|�f��i�C��J���*'��40������+���#'u#�5�X���L�F�V���d����Bn�_|Am��l���xT���a�^{�����QfP1*���O>�]�67����z��-2����2��Y�f
�����/$$��;��k���(3x*///�q���&53y����P���k�vvv�����T?��UKKK�������T���(���h�������=t<�'�����6**�B*�)S��4hu~�!����ig�5�r��}����!z5n{>�
{�Bll,�#�6
6����4�E>T~4<m��a����A�T{r�.]��e3u�T��7k�L�?==���TZ�N�<�Z���������3G����l����r;'M�D;��Ac��4��C'O�d�����������P����+���������+��b2d�������;�s������l���En{J���(��������W_5�%hx������U�V4����(3��>}���~��Eei�2��ah^�u����p6FGGs;QfP.�� ��G|||�����8UP�$Wro���L?����������?��������O?���_z���K�7���w���kW���)44����5p�@�_J����W���G�?^�r�j��O���H�M�V�F
v�d&���b��N�����W�v�������z{������GsuAc�TLRRR��u�}�~��������e�b>^�x�
}aaa����������U*u��g��U��������i�����k���]@����:��q�����	/����W_}��W^��������������n��b��[�h,����y311�S�N���������������q����_��Usqqa4�QfPJ��f�����}�1���sAAA4K�2�"����G�A��T�~���K��q~~~jj��+�����O��PfP.�� {����C�G�7o^EwQ��G������k����C�n��
���j�*�i��T��o����]�n�:X�����~����i0��c��1~

�l�s��]n��'>��v�k��F#&���U�������8884h����~���p�},����0��g�q�^7�QfP4��e@�C4��������Y$%%����+9��f�����-h�2�r1�7m�����m �O�.������;w���6nLoA�������/�W�����������v�J�������?����T�u��������g��Pi]�r�Z�j�������m����M��J2������@JJ

s�I5�_}�U�����������������K�V�Z5((��S�<�2�������A�������_��
��A�A�<x��7�������������'O�q�vz{{�[���\�%��,cd��*��Z]�EDD��w��f���'��������Rl����c�:��[o5j�����s-!!����?�8==���r��R���{s_"[�~=��������?����*����e������:_�4(��
�[����(	�CM�4�����b���n�����9r�������.]�v���\�x��Ir���M*cv��g���,nIz��mU��/�=�_��~o�A��o���?5�>}:����
�x��-���_]�w95xP�����T]<7nd���U�*��-����7o=T�zun�*�����_������q~Q���\�x=����C�N�>M��V������aCn�077����/����KNNn���|`�lp3���<yr�Kgc�WLy��^���N������t����\�~���*���
w�2�TL��M����cG���<H�#n�*��,?��i������������p{PfP.��Daa�`$�������o��X����Y����-�cFF�q����k���+�G��/%%�y�����>�}a�R����������Z�����ms��6��?�P��+>��3�����������L�)3f�`k��C#�e���P����(�T�7o�l�(��;DhQfPN�}@@{
D��GoR��m)�%%%�?����S���[~�7�xy��@a��O>i��Qll,��k���~DD����w�}���=hh&O�P��U�����ccc�������{����?���20��A�T���g����e���.�rvv������j5{V^�E�A�<5������un������3<<�j�Z�j�+B=z�����f�1j�l�2n{���o�����dUp�(�!55��O?�Kp�3��<Hv�������n�^�������Y�vm����W�����!�n����y`&jQfPQm������q��;�w����=��G�AL�2�J�������V���S� %�f��U1�jhbb"%�Z�j��P�b���_����]d��,�]
�{���?�\�R�������!����;�8u��r}F�l��<{�I�������8'''���o�����=�~l��%�c'N����z�|����|��S�N����o���~�������_7�cHH��%�* 33��/��22dH@@@pp���M���O?�G�Ay���v��Q
���[�V�
���������7��)(30�����P�f�����?FEE7���;��S�NWWW:�����I�5jP:3nL5F�F�9r�H�=��6m����B{��q�y��
�ZCCC��7n��M��;v�a�l///�4h@=R�-�/_.�#��z�����
j��a��5��GK~B�dh1Yf&���2�
�JX�x�7�|S�^���k���'NLNN.�=��K��8p�������j����i�\�r�������V��b�=���	�H�����il-����(9R�Q�QRzzz�9���H�j�g��������R)��~�P.���
endstream
endobj
6 0 obj
<</Type /XObject
/Subtype /Image
/Width 1200
/Height 742
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 48881>> stream
x���	�U��}�@@���� ,7h��P�����eX�[�hc������q4��e���XTAed�����e��X�J@����b+��'����f����V�����a@���'37�<d���2@���?����v����\�r���%%%��.53f�����_��_�7o^��21����}��w�����-���.��;�`��w�y�w^y���#G<x0����z>��)t����>�����^{m���K�,�={v��}��X�zu��	����k��K�.u��s����;t���U��QV����;�zP���'��}�����_\\���|�r�����Tu�i�����G/�z��^���Z��9����������G�
�
���k������!P&�z��A5[�n�1^�n]h�3g���������=����P�C=���l��7�<{�l�fs���i��s�f��z0!���P�(((�?~|DK��a��)j=����P�C=�c��6��V��hy����^{�������U����e���_�x�Td6l�=�/���g���#��Jm�l���������W]�zP��q���+W����k����k��3g�?�<t�����e�j��_������[�l����d!��/OhWx�i�&���-2[dgU�zP�`^^�.�c!������@�7��^�����n��;�.�A�v|���*Y��%K��Y#G���s�Yf�b������CH3I�|Gd�&�*��'����?���l���O������{�K����e������K/�4b����G,SF�2J>|��|�����R���J����X#��������~���_4h�������
��2���>��b-�G�9l�0Yu�?����52>�p!2\OOO��W�;SJ�2�zP�����1��X�`b����%]N�/�80j���o������c��~��?"����:�[�x��w	�`nnn��!$<�����2e����l��oL�6-ViV�
9~�����CW-z��=k��>�������	}������mc9������o9�a��3?��Coq'�����X��/k2��8q�V��/�;w���~j����������O��r�6�������#�^�p��e�mg����[�l	��Wv��=V���S�G�l|!�y�Y���vW�Q8t�P�B�>z��7���E�q�����b�����7l�`�z�f������7s���O7��B��a�KVCk�Xe�d�~��]=�y�f�U�2V�l��E���g��k999U�!{����������%K��/��Z������5�UmdU���H��B.=R��*�b�
;��={��_�
�]X�r��ev���+��Ac��1m222��l>l/���W	e��R~~����O�~4$=������/8�������e��@�[�8�w�����f���c��lR��N���[��I�&��|x~AA���e�z-�������#%������N�W�����WN�A�������n�����)��m&E�o�=�R�I�JB���)S�I��-**��]v����%���r�W��]�VK}'w����%ovE���fd�&�R�IHbET2`�Z��o��'F�i�J3�4�pC�3�
�����l/������o��RE>�����w��eH�l���	r�*l�Ryl�}�����m��={�>}:�����~�i�uI9��G�)+b5K���v�.�n��F���
2m*�e�,ue�*��q��E�
c�����R1�������R����W���Y�Qc��������A9�v'�1"��� ��V�?c=��l���+��d�U�]%%%R��6��kh3)s����p������e��w��]��;v,t�b���vo�7.��n����]�JXU"������W�����6)��o�=�������g�U���+�,"~!h/��%K���3G����^�.��}��j�P=�}�v�x��Q-�e�
��.��Uo�)��`)�l���e?��4x���k�\)�c-����Ju�'cV)eN����e��c��`3�eL���{wc�="~h)��]K�Bdh$3�67n��H=�o�>��rt��f�!B�����x��XW����	C���d��=�����<���Ft2�d�V�������#Zz+�w�}7�'��_��.$�SY�?��S�8��W^�'������z��������
-Zd,[�,�3�-��9��"!#����{S�h���_z�g��H�L�l�i�����?�K�:��g���9RR������K��
������<�:u����X���n�V^i������r�e�'5~���$6�	DY-�t����?��
,�"���7N��EB�w�}h�	��y���~�P��',((Hbu����zLh���z���/��R�����y���+C�S��#ny�^�	��Q��A�e�n�����T�v!�]�w�Z���N=(��=6l�o�t��Pz��!{3g����clCo�����G�-��eTB/����_o6p��Y�����'+V��n,;�6>�'�
�J�~$==��� ��� @
y��
����w������o���#G�����o�a��m���%�_z�d��yT<��`FFF�f�w�������>��rT��'vz�c9vz�O���.���=��Q��wI�$�\��9sf���o��.��P�yw���i�1c��x�����
"�b�O�\�p�����>�����Vk�����ObC���R^�KH���G�� @
yW�?���OA�����=w��_|��AR���%�z��������[FTU�����/^��k~����7��|��W�oWQQQ<=�Z���v���ol��={l3_�ff:����
��Ian�^���Q��"���nx�w*S�ya�}�R�B���x����{��*�;X��Z���ER�[R���3n�8��wMF��j��w���@���������1)����2�������CE��;w��k��[U��P�l����JKK������?~�\�/���J������XI�L���.��C���}F�
��2*��RB�z��W_5O��7�v)/��o�����Oh����l��5�%�]��8u���sJ-�����)�P=�}�������k������Wz�tH�|sb�e�����R��#��Y~����Y�cTM�'�(4'��XaO��SC0R�z��������W+Vx}�[����C��a��Cv{FF�}��y�e��X����"�a�b���������	�J�~�#F����E��#�>������� I��z���C��or�`-���
�+%���-[����'�Ho����)���N�0�L��D�:f���%'��_4�zPj����bH����g��4���J�V�P��
��RN�>=X��=;�^����Ol�X���L��l�hU�<oI"�a����>�"�_E��z������]D�l.Znn�]H��=���y2e���W����C��B����K����)�G���6m��d�n����"��m<e��`�*�_��dN������!�*�/�7�&�J�AK�������c����/9r��L�\�`�m�:o������@Bz��k��f{Qh_����7�y_�P�zP���p��}�����U%�`��'Y�����s�yG���M�v�����}��@s�n��!�f�?m����m����x��������s�����&�����z�����+�1��.���8`�`�EV��D����w���WW�b"'�{9�y,�Z� !�����
�E+o��D,d��e�e���2����Tt}����������z�{�b�#"�d�o��|�~����r���#2y�d�R��^��#e��`A���s��q�&M�R��������K)l��,���R�=:t	�'������5���K�?TU=8~����{o��%���i��-�g�U����"r�f���Tx;*��_~�����X-����]I<y��}a��!tLnx/�������N��X��DQ����
{-����z���S�.����G?�^8^��>�5������������������Y���+��z���-_�u�����~����G�����Y��n~���Q=(�����K����!C��6��l���f��e&�
1?���4���/��g�U.//��!�Sb����y����`��A������M�l��={���C��3f�]���H��A�b-�>Z���<���o��L��y��,�_H�U]=X��Rn��i�%%���Z�H��}A@�]|���OOO7W��zP�f�/eH���S��4V!#���LJB��'Bywc�r�����w�1m����f��Aq��A{uR��g��`{�����.�]�{�CK9���InCL=(�����|OV���^+OJ<�
)�B{+���Z���=��x�As�j��A����*��-�O���X�@t��]���;w�o��������{�������}��5m���o'�h��7���2��Xz(�l���7�^x:v��}��������J2}���(�N_�l3��.4�����YFFF����uk��������jX�#��3����d��y���j���-M��m6b���5&�^�2b]����l��I�,��eo�RTTd������79|fWH5m�#{���X5�m0v�X�))��D�
�W�7�g������fe��Q����W�_$�h�;��:��
)�<�S�+_�`�-[��r5����8q��{��gz2`�_uo^ebT��<0|��o�����$e��}���#n�[�v���{����`�2eJzz�y>�����)��}���8d��E�I�c�m����^
.���2��*I�%K������#���\���-����Y��r'�B%S�K�g��V1��M����{;�l��~({;l�8q�������Ey��q4QR��[��{�������R��()�>}��e�d�����a}��wC_q"�<��u��(K��P���>5�w�;//��kF���n/GA� �6l��������7��s��K�?��z���Y��F���O�7n\��tH�o�$��I�&-Y�D���Z����� !���o����zCF�2�<|�p��v���}��%C;��>}���	+X������.oC�#�{.|rrr:`�^�^�tW���L�-[��4�J9�{������C� si�������\9L�7~RV��J����S@�=zM��z���KJ�E���u�U��_��9s����������u�he��s���7z���]�v��q)�����*R�J�|7���#FD��I�����{��X�x��%K���B�v��#G233��2������m���u�'N�0u���R��sss#�+bIW7n��b�
�����
_`���YJ��R�J�"��sg����9y��l��e�d!R�}�����K�U��>x������'q�P�a�p^���8��� ��K�E�*���*\oAA��M�d���rrrR�����;v�]�V/���@B� �)V=�K���������W�>�/yg������~%�j�z��v���A�����s�-�j�z���c��$��#GR(+:��r��z}���fb�O;��l��m<��e_`��gp��*���`���9sR�#h6l�
��9��	q���q��}���G�Iu_������������g/�C����<xpp�������:q�DV���GW������k�=z��KSp�u�jm��Q���q������7��U�V��/N�2���b�F��h=xA��D��z\&N�XU�[{�`����_�����.�X����?��3���R����
�2�	&$Z^��2=7������P=��	\\�/��p!���l�T������.�C�X=7���F��PU�/��p��� �����K� �P^Dv�z0Q����� ��-\�p���C�3f��_~YXXX9���w��'O�����"��6mZVV����}-���#����*�eZ�v��7o����-����
��m[iii��L��a���Se��~��Q�g����;w�\rN��3��:t���ZV7i�������,���
�����M���u����+\�||��u������OG�){I&����S����k�X��c���8��o�����#F��]�~}�x�vo�������FY����������E��e�,Y��E?���/��8|���}=�)����++�c!E�l��c�bmx_���n�L�5k��W����3��b�����G��������v[v����R����+e�GtF��4##C�k��S�L���{��`�����3�)9�2=333�C:��z��W�Lv����+_.�N��
�������'%����BF�2t�a����,Y"�z�"A�����(H��Ra�XT�����L���F��~����#2��������i,[�L���Pj����M�6�]���#�������S�R����ep[RR�h�� ��
���T%2�7� ;�L��������92E6m�����/7e�|�W���,�f�hPS���2*-d����d��:�S�W#�A)�l�W�Z%�S���$2E��{�Fh�du�=s��Q��,f�o�iH��]�����}��dXtf��=�4Y�����H�`6S*#����y�Cd��=��L��H��3+�m����e�Rw�=�m������7�[BB��}��,v��u��Z�>B6???�'��3~�x���)���I���d{}�m=h:,��z�����{G�X{@(	�{��@K�����g��-�m�F�E-^�8���St����r���0K��{�O:)!�3T�*����v���;e����2 ��R/x'J�"u�"G;�~��2e9f{��q��={��I��e�f��2&�N�M7n�)Fb]���_T���@�%4���}�Y��!���
�L7�%m=h����.u����xX�]�2�o��e�&�X6GY�����uf��ds���G�JM-%@h=(�4u�T
�RZ����G�v�vO�(�79��R����Bc����J�4�C�<zk�,Y��k)3�+D9S��^!'U�io.�Z�}e�f�Q�%���l��"9jR�H���_�L���z���-�DZ����W/�U*+��)?e'{� �"�&27V�%W����e��`p�[(#�2��M����w'�w��������S$J����������0����B�zn�o��|�%������>}�7<�b�T2D	eXnG��Y2���c��'Y�����|���Z��&"�.JF��zPFk��/����C�����:,�R{�+///�M([��}�V���[��1�qY�9d��2���v�m��_~if�9s�;�TC��sY���fV����/*�4�w���������sJ6�w)P�M��?����W�6��?x���7n.�|;�.����}e�f�1�1���.������}�&��
��u�B|p'����'N�f�����X��e�w��c�=�����J��@I��b��7/�4x�-���7�-Z�T��zP
O�?I��U~Ii�/ST����#��������P0�o�L-|;s��U��4�^�G�2P�^2������C������e����h��]p���m��E����|dnG��7Bp$�����w�Z�&�Y2�6�|��}+�1th*�[h=h�7�B/��z��3=�����*��
V+���o��7�%[��!�uX�fV��{��U�_���m�C�;@G�����7�|z�e	��I�]�Jx[��Ve�{o��q�:����W�WX��cQ�m������f/��Y��;]�33}����K�����������+���;�b�3f�=���\��g*����'���x��m�6�@����"�� �.�R����1���C�C�x:�a�����O�2%X�F�eQ�O.�F�o�������w���������������������H�O��������^��5?T�0��K��<�R�dn�����@�efI�C�a� vC��+��������LO��>��
k�3g�H�bCe������~q���X�W��J3K�eq.�����}����^��;-�J�0f��D����T���J�<yrB��Z�1�c��h�:������>��w�_Y|�U����@.�kN�)#��{�X��?�s��	[D���u��u�/����:�X�����c'��`.�Fh�/�|�`��������3Q�Arpi���\��P�<�gp�[[���%K����W&9�(�����.�\�kCj@9��X�|wY�/NB�CG�S�'z(]�T�������7*Br��0?[��@���/��1#����N2�\�fMnn�����#I��I,�������3�}���k
)C���f�`~G$�o����@�?~��y����S����64{�^����K�� X#�k���-�F��E+���}�L�}��3u���C�K�L=(���Q6$8WBb��3&:��M�+��X�h����L��X����59�RJ~�W�<��WV��	u��r�`�4A\^�F��5��$W�����@Ar;�O�&O������2�z0�eZ'O��*���;��-��e��
�R[����y�?R�|=����}DO���:������%T�����}�IFH����������R��b�
[��SX����/U�*�������{���g�o93Be��u���G���[f��#G�@+++�L�?g>e%Bj�AS
��-�F���	���P�~?�P�>}��Z�X�D��t4Br_����z�^����z������`
�A����v�b=�H��������/5�q"��W���\���X�-���D��$��m��M�6�<y�,����>_4�F6C��R$�|���S�{�d�|��-�*_�����
��y`����o|�
m�m�/k�.k�^��$�������]���*b�'���'��EeQ��}O1My=h^�Q��Y�F�i����	���u�^]aoT}��������T�2�2����}@}�����o��!�����$�)��C�
������o���
�Tdj���;l������.B<��}yw�����[����V�2����q���u=h�����*1�W��'-�m��G���,��LeTU=h���~���u����z���w�����S���{�e����g��������$�c��	~����c��&��zP���9��IBw��PPP`�"�\��9w���i������#�#�)�v����]��z�>_J	3e������G�4E\�E��:��Rcqq�-R|�=�K=��n���p��G�!�z�}3f��>�����fC����U�b����Yj�`=(�l3��z�h�}b�<��+Y�zP�8������>��[�y^U����2Wi}7���oE	�d�
?h+���-���(2XJ�k�&��V�gS*��My=X�y�������������M��}��~KD=(.\���.��d��������0�<v���>�"KFJf�%�W��Dg�����q�F3�������Y#���dzz��#d��I����`1���TX2W���^��[��;���l���R@m��Auf��UL�sd���REJ{ic��7n���GODw����8`%CAY���V�\ivl�l����J��.]*;D�����9X�Y3�]���
���N����{{�43����Y�f�n�={��HJQs�����n{Yy!i.b������sss�����Mi���2�{R$��M�'0+2/��R]�l���2f������M�e@n�z��}���E����{�T�8��dL�~�(��#��W����h��u(�Dp������K�r�lB��}���Q���������K��N����oH}m
Ii#+�/�D��H,�S[�Dt�J�{(�����h}����>9o�n��1���-��=s�wp�����yY��F�.�����������D/D�##s�K�!�\���/����^��A���e,$cxFJ! cl��Q�����+���1c�G����Z0�e���W�RII"�BR*;�}?h�d�&C2)=L{�K=(��X�t������	����}��1������S: }����?~��Ys�4t��n4{o���Gd2���N��@V'cc�-2����7��Ae�-�k��A{���>�2�g��(�`�[}d���L��U�C�IY'{@R$�"�RYR_���~��c��e����&��Z��]��G"m����_�;f�u���e���,Y�o�8f{�}�v8����-��er�uIj^��K*�+K�}Il���{wB�����m#'��+W��B���7�Oe�Kldz<�pi���\���Q�K��Q0##���@�an�?~���3�K��m����K���g��9������������4hPiii�;�������p��������Kj��7�����m��v���7i��?��?>����'O��_)0~�x�FH�=Za�3f������;n����M�������]�V��)'�X�`������M��o�Y�s�-�<��c�}�����}���?�x����;�{��
6l���/��:l��!%��[o�%���|��E�W�~��W���>���'R�5Uc���
��r��|���d���5j��23g�|���eJ������R�;={��}�����^t=XRR��SOI]��G�e��eeeI!��E���O�>���������v�m\�r�$g��1��o�&z����bo�V�Z��f��
2����^�fM��}�0LKK����S�	���]ex��x�%���^��;vLa�4<x��'�������#�O��g��!~���o���N�T�s�=2�s��)�������o������_<��T�7�t��5������
������_�������x��su�W�^���]w]����������_�]�x�b��������N���=�;�����n��999����9s�����6��_��z�����e��z�)�����F��?>%S��#�H%XZZj���zp��I�����
��;w����v����{��.h�����v��y'J=��k��P���t�K��?_�`7�xc�b�?���z���S�1eR��={������R��w���7}����,*))II���?�S>���`���Z���<��3�s�{�9�D9��_�>��S�N��y��Z�@����.c�|08�{��2�M�6��J�j[��{���}��
f~T��^�P������en�
��;����������.��}����������_�c'���U��������]�v2�����e���n��^8s�l��*�o����$��`I^Y��*�/)�g��
o����C�����?�S���U��+8qx��]������^����<y�����{N�<����j��a��7�|��?���������U�����wDJ��������{��?��OG���
	/��b��p���L�w�+���/�|�� ����_p��i��`�������
H)W��y��;��OT�3)�K�^_�e���Wvz_r����l�#�<���y��������;������[g���������?�{����o���>���z�������/��M���?~��u�f��i����o~s���J�!.����5������dG�����%?q~PN2�]w�$��P�K^j���o�]Fn��w�3g��m����[Y�A#���X�v�C=dG���5�0a������4of��rKAA��~��I�V�'�^0��w�}�q��������?���;6l���x>���o�����[%;p��`�As� ������g��������_��M��'�[�n��Y���-[������	�q��:t0
|�T(����u�]�w��Jv�bL=�u���_���������k����=��C�N���\�_��z�{��Mu����n
5/�l��Y�k���ET���K���E�|�8`fIe]�nT������}��7�({#V�={��~��r"��j��Hm=x�<O�z�Ha=�c�S���5�7���#f���C�hC�\D�����k�7q�����4����V��P�������x���R	6o�|��*x��(��`��&z��q���&����S�N5C�m����u�]j�����A�2z�a��,[~��G��F�.�zPv��?�=p��=��s��w����j�pIm=h�G��N��m��z=��q!���?5�`�}�U�"�w��e��3�7����f��i�*��������{�����!�:v����#G�f���OI1�}����e��=��B����?
>Q��>_�� J`w�qGp@[TTt�
7�����*��(g���R���}�s�;��z�����_5��eg
*^�m����_t��1������-����=���>�hhZ��oo��&���/({��*���Ob�r��-4hPp���s��U�����;w��������v��1~���SDd|�v��&���O��~8�y2�7.,,LU�R"�zp���iii7�|��p'O�l�������2������}�FY��'����]f=��c����������;�W��R�����aX��m/^,�����o��G}�������5k�,-w�=������6���oR�5%;w�4/�Zf��I����3g�y�D�F�,X��*����~���zp���fJ�F�)%a��������=o�����7����{���T������[s/�m��6p�@�K6lHOO���{eb�V��(.))����e�|��
6�H	�K=����L�dR|��'�a(�e��A�;W�=������?���G���~�u��|���[����[�z��}�JP��	fff��������.e�-������.x��%L*��C�������o��&�	��5{��'��s��~�lq�zR+33���
�)--�������^�^�k���U�VS�N�XEVV��O>Y�~���k7l��c����;u�$���|D>(=Lt�Z#TO����C�|�KJJZ�h!y��g�/_>w���-[�_��]��	j����A��c��Z�J
��u�J����l,e�W\��woi,���'N��%�F��L=x���8��o�^�?���v�������.�8b�_����:u�H9�c�;q�����I�&�Aoc�k���e�tvb~~��W^)���Kh�P�%Tfgg��Q�f���N���������
��m���^x���;��C�8�;q��2�i�����:u��������	������_|Q�w�}��R��][f��=�N�e^~��2q�����]�v�����/����n����o�/^�X���U������Kt�P�%T6m�4�OM5��C;e��)��4���5�9s��UTTd�>|�L����5>~������D�����
��\��u�����~���.X�������V�Z��_�~��<��c2�u��vJ���e��W_l���m��e���)K�.5S���������=zDoKBk�j���RC������/_�z������Cc��?o[�����Tc��	.��g�5�l�S�y����Q�`�����E����)c��5S���l/�5O4���������[��i������{�������������)�&M�\N�d���^k�<��S2��[o
6>r��Y��!C�����)�7\�f������~:z[Z# T�^��z����'N�)���/�=XTT�P=h~�X�z0��
�P��Y8\����LeHX��Mu��R���%���C��>|����d�*�I:H\#c�A���),,���e���h���eq�ob��YfV<��(..6�*��������$
��1� ip��f��'��9sfp�y�����/���z}�n�.��}�K�,�������>t�@
U�s��4�F������j��z����O
N����.�UW]e�'SV~�e�5j��YPP�m<}�ti���&��wz��m}
�;��S�8�;q��2�Y�f���;w������M�����D��P�=�@I�kd:H\���z�v���6m�N���x��w|���o/������)g��1��F��k���S�NYE~~��8u�Ti��qc_�(��������KjRY�,��8++��+������W$]#�B���e$
��1� ip��f�~����R�-X������k��������;�k_RR��E���s��X�b��y�[����B1a��Z�j5h����?����u��������D�%
���#��#
6���B|-���kng�V�I�H�j{��2���t�4�Vm3&����#���6j��N�:RI]��������/b}���T��f��I�u��W�l�r��)����z��'�"�]���w;v��i�,i ���|D>���l�����I�������������(#ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1������n����~��_�jSZZ��O��o��^�z�\sM�V��N������'�|�~���k�n��a��

b5.,,����4����`fff�[������$
��1� ip��R:]V.V=XRR��Ei����._�|���-[���J�~��	�j�j�����cW�Z%�d��u�R���
6��2��+�����4�����'N�Z#�*�s����52$
��1!��?��?\u�U�`���e���?o��>}������#F��5����S���c;v��'O�,��4i"�6��6n�XfIAg'���_y����8������� ip��AI�kd���3��z�/~��?��������5j��Y����������4_���m[���/��s�w���z'0@&6m����S�N2�]�v�lEBkR�st�4�F�����52��{��/�\*������U����2�����M�2�v��2k���v��#Gd�2q�����]�v��R{z'�}��2��7��5^�x�L�U����G�7!�5)�9:H\#c�A��Z5���-[������&���6m����������2e��S�c�����9��***2S>l�ddd�?~���~jM�kR���s����52$
�U���?�����7n|������`iii�Z�dV�~��y���dV�������������:�8;;�Tg��-3S�.]j�dee���G?�Y=z�������Vu>�@I�kd:H\������5/^l����w�)���\���>k��b�<��32�Q�F�����7�JOO7S��k����'�^k�h�!	�H��|��&���t�4�Vm3�k������/�������3%��I�����������k����zJ��z����G�1�2d��2x�`3���C����5�YO?�t��$�F ���9�H\#c�A��Z���#�<R�~})������^x!�z���(�z��n�2�`p�@jU�s��4�F��������1s���m��/
(����#ip��AI�k�0c������������wR7�i��N1����d����,.R����,>�n���M4o�����71k�,3+��M�Y�y�Dp�Ju��R���E������<��CR7������r��Y���z}�n�.��}�K�,�������>t�@
U��.$
��1� ip��Y������Q�F��5

���O�.IKK���;�m�������w�)���8`����Y3_���;��v����Ky��F�kR�st�4�F�����52fE���}��2�����r��sio����999u���W�^~~��8u�Ti��qc_�(��������u�Y��qVV��W^y���{�H&�F �8�@I�kd:H\#cRy�/���J�$%�����[��JJJZ�h!
�{��+V��7�u���~T(&L�P�V�
|����W�������[�~����`c�(��A�>}��|�a���qY��e��}����ikR�st�4�F�����52f+,��_~�����T��f��I�u��W�l�r��)K���z��'�"�]���w;v��i�,i ���|D>���l�����I������������$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�k�6c'O��={���?��Y�����f����O�t���8�����)--�������^�^�k���U�VS�N�XEVV��O>Y�~���k7l��c���v��I�Ic��|0333��Jh�@JT�s��4�F������j��v��]v�e?��Oz���x�����j��!�5����7?~���}III�-d���>�|���s��l�R�*E\��'L�P�V�
�;v��URH��[W*����`c�(�������{Kc��|P>>q����(�5�Rm�9PF������m��q��6m����o��k��F���_���}��2�����SN�>}�]w��#F������SG��;v���'O��M�4�]��6n�XfIAg'���_y����8�����P�=�@I�kd:H\��{������;8�7����P�Z��N����Q�F��5<�����!����|W��me�/��[�w�!���8`����iS_�N�:��v����9	�H�j{��2���t�4�F�|La��SOy'J�(���>_c)k��-�f��m'9r���/��.������L��/~��x��w��7�|��x���2�V�ZG���s�kR�st�4�F�����52�UXXh��3g�wz��Mc�T�Ts:t�S�L�rY�c�����9��***2S>l�ddd�?~���~jM�kR�st�4�F�����52&��;w���	&��g?�W���A��sKKKk��%%U�~���}���dV�������������:�8;;�Tg��-3S�.]j�dee���G?�Y=z���BkR�st�4�F�����526c�������o����`���f��1c���g�3[��g�yF�4j�(�x���fQ���f���c��={���b�M�7!�5��9:H\#c�A��;v�Xff��%K������+���g���yyy���4iR��:t�Y�^{����SO��[o�5����#fQC�1Sl�:t(��Y�f2������������ ip��AI�kd�����a�����D��/��B��`QQQB����be�������$
��1� ip����3�<�s��}fJu�_t-�j,����t��S@�5�L�n��Iu��R���%�����������������_��&f��ef������b3�2���H-N2�A������g�����&M��[�.8���������O���z}�n�.��}�K�,�������>t�@
U�s��4�F����������7J���O���i���z�[-fgg��Q�f������O��iiiRz��m��w�����;e���� �5k�k��sg���];�t)}�Ht�@
U�s��4�F��������1S���?>p��w��c�n���u����>��}{������N9s����7b�_����:u���W/??�N�:u�4n����x���D��Kw��u�UW�BdQ��YYYW^y���_��"�������#ip��AI�k�3c[�n57X��'?y������K�	��
3�����������HIII�-d�s�=�b��y���n�:��
��	j����A��?�|���|�A��u������l,e�4����4��4l�P>.�������|��L�X#�*���}$
��1� ip��fL*�~��=��#7�pC����<����2dH��i���R�5k�L������e��S�L�XEVV�O<!���K}��c��}�����L�G������f���R���������D�=�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�&�9�A������M�s����52$
��1�8�@I�kd:H\#c4q�����t�4�F�h��$
��1� ip����9:H\#c�A����st�4�F�����52@�� ip��AI�kd�s�����9�A������."'��+�Y�{�J��$
��1� ip���bqv���_�8����*�st�4�F�����52��E���U��y������R8�@I�kd:H\#c�(��-����t[^����q�����t�4�F�p�;�+�����iR�#$�st�4�F�����52�_�s����z���!y�s����52$
��1\�J������v�Nu��<�9�A������.dg������s����kH�� ip��AI�kd��g��O�����!I�s����52$
��1\��G���G:������o��wH�� ip��AI�kd��my?x�L�7�dg��n�6�D�8�@I�kd:H\#c�0�S;[�>����b����;��>"�s����52$
��1\�����~�W�0�����^�(�}D�8�@I�kd:H\#c����n�������*������?���N"i�?{������K,�$�j4M���I�����45��Xb�%�������A�*"
6�
bEE����{���7���eA������y�s3;;��~�{�����9@��!c@��!c���P_�b��Q����RT����{�t�j������t i@2t i@2�(UV��_6�r/�V�n>R,�*�<�X*���I��1�I��1��h�
o�KQ3�����e�5S����.��[�'��I��1�I��1��h�/^6G�K�esZ�j����,04��8�J�����
�%C`�:�4 
:�4 
���C��R4*\�=:������f�{�]=�~�f~k���t i@2t i@2������`��A�v����D� ;jd�����o���s�$
HC��$
HC��w�u��������F1b��;AnD����)>���A6�s�$
HC��$
HC��w��z)��(��0��c���;,���\k���A6�s�$
HC��$
HC��_���2e7�<logUGe�������_W���5v�} �9@��!c@��!c����j�_�����4�^�o�����;��>����=1�[��O��"@6�s�$
HC��$
HC��G����_6����R'�.���+o}�s�mO�1�{Wsf:�W2��t i@2t i@2|i�o��Zl=S+��>VS\�*��5�=���E��u���u	��s�$
HC��$
HC����E��~��|�Z�v����Uu�����n<�����W=�9�@��4d�@��4dxQ��&���n��fp�����N�������A�V��s���i����i�����&��n<$�j8t�^�o�K�P���R\D�~�
�9@��!c@��!c@YkYI��i\+>w�x3hx�����n�h	�����A����)zs���i����i�PV�{�������s��	��n�n��B����6�P9�	�9@��!c@��!c@S���f�j�a�t
�l�`�BEew�8�~#]9��9@��!c@��!c@MKqa����&.h�R�|�$�A�%����[���j��C_��t i@2t i@2��)o��V��vv�I�2�[B�?�7�h
�������9�@��4d�@��4d����,�^L��QuTV�������6�X}��D���0�H���H���-���������|�����AFl	���m��e�7�y�@��I��1�I��1��XI���K,j�K[{v4n	�\�\���m�@��I��1�I��1 ���A�k3�xb�UMqU�A���k�-a����#7FG�U�@��I��1�I��1 *?)'�G�e��e�����=�!�a?xe�>��5�l��d s���i����i���R���h����:G���z�`7������������J}ph s���i����i���b���x3��~���-!\����������@��I��1�I��1 d�iR��_�F���o��-!L�1�;Ksjr�����I��1�I��1 ���q]�����9Y}{
n	��e��Yj����,��0�H���H���	�9-�_�:]��SpK���*�BO��O}s���i����i��p�v"��e�4��)�%�kw�r�*�u�sA��t i@2t i@2$8���z��
�	���GK���l��%t:��s�$
HC��$
HC������-����X���P|�b��B��>�9�@��4d�@��4dHp[��k�J\�:���K��;���������O`�:�4 
:�4 
�>��������;�fg:��p�NoQ���B��>�9�@��4d�@��4d���\w�3�k��.!��["�l���r�'����t i@2t i@2}���]�5��}�sqK�Y�������I�70�H���H���A�sT4�Z�=#�����\#��M��!�'����t i@2t i@2}���������&�sqKU���NZ���'����t i@2t i@2}+��5m������&�>�p	�\�\�%�LC=��B�`�:�4 
:�4 
�������/#����%��sq�mG���0�H���H���A��v�Mt3��(��3����+��S��;A����s�$
HC��$
HC��o]U9�5eq���-!������\u�SC`�:�4 
:�4 
��u{����]q�s��mK��M�Tu��S��0�H���H���A�-k���g�)k���s^n	a����'��9;�s���i����i��!��2�7���^[�������@z�s�$
HC��$
HC��9������%K���[Bh��W@��.j��0�H���H�&����9s��/����o8p��a'NTUU���y�[���LLL>����C��9r���NNN]�"<<|����F�4h��q��o�^XX����������������o���d:#	j�D7���I���%�k�"���O�YHIn��I��1�I��3c���/�������O>����s���k��e��1�������


�7n���vqq�2e
��l��)����6s���.\`��6�C�a;5�����������;�oa������^�������X��k���^�v^Fl	a��o���3i����9�C��4d�@��4�������}��gMMM��������?�|AA��[��Y���y�fnKCC���~�n�����9..n���l;����m�z�*���	�7�����������������>l�0� Rvs2��������=>R��7{���%�wo�j��s�f
 
��s�>$
HC��$
H���	�A�]��^QQ���O�/�o���|����y��>�����y��1
��E�����m�8���n?r���FKKKv���%vVRRb�/^�X�+�����GW���L]��r�%��6�j�4��YHC>��I��1�I��3ciii������_;v,�@�^�Z|���
���o����m
��t��mncYY����>��_KK�������o������;�����X^^����zFB�����E(�Q����%��w�qe������|�9@��!c@��!c�y�����&N������nNQQ�������6;��yS�Rii�pKII�p������UUU����k��g$�^Sto���I����/!������n(��t i@2t i@2&���^�}����MMMd7���w|�����M��RGGGx_��;GFF
�3///�OOO�����������K���]�-�����>��8!���n	�����J�=:�;�s���i����i��8{{{�uz�����999��������q�F�=[�-���g�����w������G�JgO��������������e:#!UuL�������=]��%�6�r�TY�����9�@��4d�@��4d�������_����7��'$$[*���RTTd_=z4�e��e��?����eee�C����X[[�t��q��I�K��/��r��HHpjs�_iVU=���*�p�*)�s%/���`�:�4 
:�4 
�wz����Av�����R��A����������9m�@t3���zv���w.��gk�7��>�|�����q�O������O/\����E�%y��h�2c�f+���m��@�P���OF��.����t��z�8R6������!Cf��Q__��U�OF���r�W�%���v�[Bx~�WO��c|���$�!i@2t i@2�vdC��>}z�������&&O��/��7q��-��?t�����j�K�y�D�3�P�����R�y{�;W��K�n���S��O�	�s�$
HC��$
H�������a��M�V[[�md����L����y�������y��v�P�y}�g�s�-���Z����k��O!\��!*i����9�s�$
HC��$
H���y{{����)S��A�����/�(�%22����z��g
�u:��_g��1c������E�I|i(��'����9"������8i�$��w���n_�x��v�=�(C�3��;7��+k�����W���F���U��oU���9hB��4d�@��4��������kjj$^�����Y�6V[�l��466
�����|�z\\���������mtrrbw?~�D���#�Q��������g�J|���p���#)����A��3�����H��:,��UUs��UGn��I��1�I��3cl���J�J���;��l������e��M>>>w���6m���������;����������C�5jT|||�����K�&&&���[�����=���fff�����i����n:�u^)&�O�-�B����������(xD>��I��1�I��3c�O��W�:��L��F�~m��Il�5b��)S�8::vq����%K����A���n�����a_bw`wcwf���1,,��n���&L3fL��W���}�}�:Q���J��].!\�'�������.
��9�C��4d�@��4dz).�%������9'���DKSgL���w] �9�@��4d�@��4dz���t�����5��pKo-Q�j������@
��I��1�I��1�%{s��d�n���G��,!4�x����`�E���I��1�I��1�%��f\��d`�w9�i[B�Q5���x�\���9@��!c@��!c�K����\%7ow�*��^B���W^Kq�u��I��1�I��1�������������O�g���m�z���.|��s�$
HC��$
HC��7x�r�;�.����k-�����(��� i@2t i@2�q��!�m%�Z�w9��**��~��n)�E��I��1�I��1�
{��\���e�w9����.����������I��1�I��1��;��s�V�U'��i�[B�?�7��?/���w�s�$
HC��$
HC���2�[cg��Z���X�+���m	��jC�����|%�0�H���H���A����co&#t��`	���m���mk�.J�a�:�4 
:�4 
�s:�#z���|��	�D���Z�o��P�w]r
s���i����i����]'E7���w9��mx��0���\����|�%�0�H���H���A���M�k�r/\����	�^Y��+���)���k�s�$
HC��$
HC��gr�Z#��"��-*���:'\B����+�|�6���k�s�$
HC��$
HC��g�#��-�������	�.WO�J-��;���k�s�$
HC��$
HC��g��qV���|��X���SE��HN��.��9�@��4d�@��4dz���s\{���w9].!��L�+�����Q`�:�4 
:�4 
��qZ%�CK���|����%�F��
���G7����I��1�I��1�������KD7�		������-!\�;T��p�4���_�s�$
HC��$
HC������o&�ZU�wE]��f��������w]r
s���i����i�������J�e��to�I�B�E��������(9�9�@��4d�@��4dz�����f2���.�{�%�G����4���(9�9�@��4d�@��4dz�q�.�Xe=�w9�.!����+�d�"���S�s�$
HC��$
HC�@VUu���\c����wE�.!��[�n�cE9�u�#�9@��!c@��!c ���v7�i).��"��z�������!�E�#�9@��!c@��!c �N�\K�=k
��HK����#����f|%�0�H���H�����.�w�Z��M[�.GZ�I�%����q��n^�wQ�s���i����i���a�!�R����i	������+�P�w]rs���i����i���c�Z�O.>�����]����wQrs���i����i��$��5c�w\?����wE28�*XBxq�W����;�s�$
HC��$
HC�@&���\3�5�[����p	��VG��T6�]����t i@2t i@22�w�\4~�b����p	�����%�3�.J�`�:�4 
:�4 
��������?��/��Kf����)>������I��1�I��1��=��
S����	�^[��]E��y���/�s�$
HC��$
HC�@&.j�\'ah�w92.!4�|���r��|%_0�H���H����L��)�9g��U����p	���*��O��(��9�@��4d�@��4dd��|����w=�.�'�l[B�1�[�S32��.J�`�:�4 
:�4 
���[��Q�	|������]�����[N|%G0�H���H�����j����smTkE9���_��C�sRy@������I��1�I��1�^VN���}�&�]N	�n���]H��y|%G0�H���H�������D7����P�%���mKq�E��9@��!c@��!c =G�wj�+��]N�	�z.����z��|%/0�H���H��������s
T��=|��s�%�6�r�Seq������I��1�I��1���\�m�w9='\B�������
��]����t i@2t i@2�{���5PV�.�W6����](�����������I��1�I��1�����\������rz������K�+j���(��9�@��4d�@��4d���7�{�����^�o[Bx~�wE�'��]�\��t i@2t i@2�K�9]�
�|��+�%�{����S�}=�E��9@��!c@��!c ���<�^��S�52��E��a�:�4 
:�4 
)�Fgs}S��?�]N.!��=�����p����0�H���H���������F�t����B��{����d�wQ���I��1�I��1�����\��Q��r��p	�����u����wQ���I��1�I��1�����\��� ������jW��������������t i@2t i@2RrW5��� �~��J��%��3�r�����wQ���I��1�I��1���zU�i��p��r�F@�`	��%����:��]T?�9�@��4d�@��4d���w�iJq����!\Bh��$wiz�|��a�:�4 
:�4 
)����k�����.��l>U�Q5Hti�g�]Q?�9�@��4d�@��4d��_��.\B���wu-��|��a�:�4 
:�4 
id�~,:����K�%�n�sX�����g��t i@2t i@2�H�=�!r�2���K�%�G�ZpXif�wQ���I��1�I��1�F�������o���>��T���;w�%��wE���I��1�I��1�����\�����w9}��a�l�B����|�oa�:�4 
:�4 
ix�;��J��6|����K����]c���E�[�s�$
HC��$
HC�@���z���|����K��6�����9�E�[�s�$
HC��$
HC�@A+6r�R�M?���{�O��)����t��|W�oa�:�4 
:�4 
i������2���.���<l������
�|�?a�:�4 
:�4 
id����q%�|����K#��]fc8�wA��I��1�I��1�V]i%�%��!��!\Bh��h�d��|�?a�:�4 
:�4 
�n��'s]R���|�C����:[�+-W��wE���I��1�I��1�V�-�K�_�'���b��a�z�h	�L�+��0�H���H���A�BO8q]��_|�CJ`�`	a�����6%��]T?�9�@��4d�@��4d�h`��H�,�.���������z����!�9@��!c@��!cuuu���O?���I������������>:t���#�N����������K�.5j��A����}�������\TT����������}cXX���"����C�k�|�����X��5��w�Z�|W�a�:�4 
:�4 M�3���5~��������QPP`w��q��������)S�d��N����8p���c/\��6�C�a;�����;����}�Ycccvg�-������K-2�Q&A�o�Z� ;�^��������C��-�?����!9�s�$
HC��$
H���577o�������~���U�Vu��Y���g��������O?���hkk+�s\\�����v,--��x��Uv�	&�o���GaO�6t�����a�����������Z��k�b�{�]��	�f���]osV�E�7r;�eH���H�&�+++5j���#�������###�z��g�y���@|���3��1c�H4\�-b�o��M�8�1����#�---��'N��YII���x�bi.G�3�*m�4�?�M/������K]m�����u���o�v���4 
:�4 Mn3���XZ�����TQQaw���o%��m��A���n���md;��>|(��������?���g��54$������n8p`yyy��"�e%z����9�����G������6��7r;�eH���H���1R��'N|�RAa7����mqtt.H������������V���D����Yb���*�K]��F�3��<9�k������A� �6l���]r��_������t i@2t i@2�t�655
8��������,`_�6Mt�v��#:�)������[<==�[���;���/�/���v]�Lg�U�{0�,Y���<AS�g���%�Z���� �9@��!c@��!cLw�`NN���:�|�W7n�(�g�e�����w�}���yyy�C]����v.\n�����?{X�M��_�3�*��-������A�,S���Y�]u��+��+�s�$
HC��$
HC�������aK�����UEEE����Gs[�-[�n���;�\VV&<����p����pKqqq�������/_�u�2�QV�f������I��d�b[{r�w�U�rq��`�:�4 
:�4 
cz�n��M�~���T�~P�n�7�`�3�*H������:����9�����w��W�]Q��9�@��4d�@��4d���E��q�y�����<Y�R��j��[BXS�wQ���I��1�I��1��i/���E�������`�0U�:t�"��U/���"J�l���<ob������y�n��$��&����/��y��-�0$����E���y	$}k,/���.<�@���(��q�7�=�^[[�_R?��������7�����2��dQUk���d9�����������d�'�����i����i�#E?��SO=��3������_���q��1lc(�}��E_
}��'��#G��o������;v�`�/^�Xb;�J�!���RX��D��f�� O�����{�E��L�+�?0�H���H���1R���5k���l�������(�j���Vb������:4==�������<~�x����Gv���K333���=��������
0`��7���Qz�A���/\���<���W'��V�)&����	�9@��!c@���s���~����}�;��#�G��;���(((��m����������M{��B��������{�����@SS�!C��5*>>����F�%vvg�-���c��DbO333�z@���g�R�5W�!r_����<����^[��]~���|W�O���4!i@2t i@�<gL�������������~m��Il�5b��)S�8::vq����%K����A���n�����a_bw`wcwf���1,,��n���&L3fL��W�����9v�k��)��PO�n
��/p�_�w���<�MH���H���A��L�����)���*8�y�����E��u����I��1�I��1�B�vu�!z`y��rh��_�1�[�hNO����s���i����i�t!���\7�}���rh�j[{w����q�����9@��!c@��!c����K�n(�a\�o�_N�5�p��*��]Q�9�@��4d�@��4d��:[��������-8�y�N?�(^6�����9@��!c@��!c����M�+o��L���Z�������9�@��4d�@��4d�������gL�k�� >l���\�;�9�?p���'��I��1�I��1x���d���9��.�'�l�0�>�*s�z#	�s�$
HC��$
HC��q�=E7]���r��������J�-���'��I��1�I��1x���������rx3[�P|	akM5�=�0�H���H������X�������.�7[���]�}
~�|W�d��t i@2t i@2��{H�j�����to8�J��(�m�]��
s���i����i�<N�M�	�o��w9�	Nm���:�Q�n�����l�s�$
HC��$
HC��q"�m�� ���|�����K��z�+z�a�:�4 
:�4 
���Y������D�]������=��4#B���	�9�@��4d�@��4d'��Y\��w9|:����|�i�\8�wEO0�9@��!c@��!c�8���L+l������9v=S�F��!i��/s�F��m�k�70�H���H���A�Z+�E�����jZ�,&�\���M�������v�kX�'F� ���~���I��1�I��1�Tsz*��D����"��[��<G?��Fs��LK�Z���M�1��L��h��?��t i@2t i@2�*��z�����P����������h���TGS���{��%��gR�x�����9@��!c@��!c���kw����j�m-�n�\�U�~�d�SXHZ�����gR��F�����I��1�I��1�T���\����>�3��7~�y���zK�!�T�Z���w���F,`_�P�F� ��y�(��_��t i@2t i@2��2<��>w�X<SsUK�y��;��Q���9���T�6Gr7��[+��x�������97���%�9@��!c@��!c��UmQ?x���9�sZ�v5���i'�<��������u���P���� R��N�7�-\�},uwo=]�9�@��4d�@��4d:�Qt���'���+C��V<nI`s���A��:���}���Lc�������5]k�},��z�N��a�:�4 
:�4 
�N�,_�5>�������E7����N���������R����b����n}U�Eew���	����t i@2t i@2�J�7�k|�|3{��l��_�=���h3��]����A�_����vMn�K�v4iO�k�h��bQ?8mrk����3�s�$
HC��$
HC��S�]O\ju��X����v|�w�>�[�����n^�����]^����_^���uiM�K<�s��:Yq�<����}2�^����s���i����i�t�Z]%������(�Y�1<v�`���W�<���kl'(>���G'H����[�Dn/�:����Mk>����d��L���rs���i����i�t�����<Q?��k��A��t�	��m-��� �M�;<�K4�����_�*�k�[��"[�6��CM�6��l\��G��s�$
HC��$
HC�����P���^��Gh-t���]���K����97�|\3�
Uo��r���6�7���<��G2������y�4���a���I��1�I��1�(��+����P���|��������LC�LG����`�L��c��2���;�;�
���eV�rooI7���������H8����|��i	��1�
��I��1�I��1�(����a��e}{K�q�.L�_�r�m$��E��eT>j�\3}���+�	8�W�����M��$���Z�4W�Z����f���r�O��uo�&�0�H���H���AG�FV\�sc��lon,lr!�p�%2�����7����on���V�����;�
/�o{DsUs�R�/
��a�:��T:[DK�������I��1�I��1�(j�����(�{�c7�7_L]���
)����Z���Or��-N)�g_���%T�_fv��A�U`k�����%o2���[��X&p�O��G>a�:�4 
:�4 
���6+q��m���1I�a�z�T��z"�^�����^����s%���kk;v��:�v4�Ruc
S��7Q����3��"��o�=RgL�>����Dna�:�4 
:�4 
��bW��O�N���4~%j�<_��]U�5���$Z9v���=)�77���6�qM��p��U�b��5���o�������2/��"��|c��#��?/����I��1�I��1�(�����M��H����v��)p��\���i}�g��4���q�����]��N�_H��Zt���%����h�z"�?��~2����j���I��1�I��1�(k�w\�U,������~���4o���)��Mu\�����T7�XE^�����]�O���&�5*H�v4P�i����;`�}D�s���`��9�@��4d�@��4d:�zja�4oiI�ow���n��xD�Y��E������?R�PevF�!��1�������u�����?������)5g��U����I��1�I��1��Z^��9i��/�n��=
��7�l�����y5EK�(I�h��6}s����9��c)�Xw���MfZ�Ks���f�ErT�M'��K�s�$
HC��$
HC�@Bsv&��D��+�[�W���4�v�s@~�w���)�/s�����;WP[�h�iW�����c�u���0����������h��?��t i@2t i@2����6'`��n�o��o��Z�U;��$���rsKjEV������
�C�v�����yMt!����u}4s#���Z,U���I��1�I��1������9����v�&�OEm��������j��}]����Mu�V���9���>��u�8�����|�;�
�p�>��e�Mf��0-5�;�����-[�{�(C9�9�@��4d�@��4d$$���z��vw�sk��v��x����KSg9��h�.$��������Xf�S���U��"��0�����&��+y���+�z����#]��x�*��#��7�����������y�9�@��4d�@��4d$D��z�����������u��i�K:��>�E���qmmtI�T���2�'��;����\���A�^lLI�f7�N�B����}���`3w���k�DO!4: �����I��1�I��1�f|��q���b���v���������A��L����`_i}E�u�F1Gft�	v*��Y���L�7�	+�]���iW���y����n���������}V+�IFy�9�@��4d�@��4d$�3�^�����W���62�:���.��]����x�9�������{6���K���m-�0w��D7i.�//|�]�N�B�k������zk���[.��/!l����Drs���i����i�HR��O����vk�Z&�=_�x������[�[������
���u������N:;�/�4������q��
f������07���{Lcm%x�-s��iWx��������q;��7��]�}\
>�\ `�Z�4 
:�4 
	Avp
���g��H<c���^b��_����]]���]�+;�q��p���X����|������!�]��g�M����C���YpkK��������'�La��{^\�%ZBh��2C�9�@��4d�@��4d$��X�58����#������$^��g.�C��;��)�2ov���%x��L�sG����~W������������\x+�}��M���/�;vkru�-v��Z�����~�l��%�9@��!c@��!c !j���I
O��Ck��v���n�4�cQ��[��nZ]�,������g��t����U0A�K�0J���\���\f�
��8������cW8���3^�/]O_B������I��1�I���on�k��m��n��j��h�*o�,��(�+cGamI~mq^MQNuAvU~fUnzeNzevjEVryfRyzBYZ|ijli���
����	�E�aE�!�1�F�/����O\wS�]�q�&�7D����"���tO��i��m���y�{Vs����2�-Luq_{��+���������:�1�	�m,�ap%���kt�
���?�>����:X!p��5�I��1������1��L]S[���1�9Le&S����0�ILiS��D3%�Lq8S�1L�?����x2�L����d�c2\���L�M&��I��$;2I�L�����
qgkcN�F�����8VnYjQbVlZdT`X����O��G��[+�[#�so��Z����;3������zW1�ek��-��7%���pcC���q�kc���:��v\��"�ay���H�%W�_Z~iA���!����r~N����gg��:�c��ON8>%������|`�����������K�#��Y��3����Y|�k����G>f�|M����|������|���o��|��=�����|��k����w|����?���m?��}����{�O�M?�7�t��g�������	�(�����`h�bG�������h���j��+���2;���������b�`�����=/�����32Vmd�����#���6w=���]�'�z.����vOW��s;�v�V��2$WyH���|�g��-�1�h����K���T�4�|����+�TmP�}@��3����)>]��t�?��v?G+��O�6c���M������t�i,�^
*�o��9���)�|?�v�P����`�~eJ�^�PM	���oe�O��7�x�9���������%��Y�s�l|n�;�m��G������k���\n���o��l	`���������������1)��:�4 �I���BMS]ucMUcMec�������������������������������������������,��L�����)w2Sne$;g$^M���})1�\B�m|������c�����E��Dz��������P3����{��.�B���V��tC1��� �
Ak��]YxyE������_xna����g���	<�S��Y'f��1�fZ����c��6����#
A����2��� ���->
2�8���`�����
1�0���P����;��������~��p�q��F�i�V������F���1�cbuF����=��Z��k����J���I/%�{1�/��}!m��4���#2���T.k�sYj�e�
�Q��{X�������)�g�v>[�sp���R�Ae*��w�PX�c`���Jj�?S�����O7(��������``��HE?(��~0e����6O}9��!zWE�wWW���b�4����5��U���w�{�7����3N��2c����i��j��g��&�z�G������Mgw:�����O��g�����=CCc����v�h�����4����N9�i�������4���"�]���Wkn����_%�do��^�1��SG;�1���I�
�HZ����������������������������J����/�Td&�g$��'�F&d��e����#*�#2�aD�kx�Kx�����!���C�.�����>��q������������F�w��������
�;���qR�}U�����vJ7�l�q������~q���u��~�vn������zz����^=����"��6s�������,��3��f�Y�hd���T{���gg��������,��?�?{�/��>�7�lg:���S�O�?v0������F�'������?�z����;������'\�?�y�{�
�_7x�������m0����;�c���}W��{zo��y�U��:o>�y�M�uw�1�����5�[�5��|5F�i�
��j�����^	��r���C����R���{^�������=/�J~�������RT_�;��94����<�!�����)
�P|YP����P|���000�s�����v�O\?3w��k���V�g7��m����vol��>t���D���L�-*W���J�G����s)��R�}�C�1&f�V����#*���.��r~���sf������=��o6��8:s������U��L��?U���3��g[���_p�p�9����u4�r�\��R��F+�v��x��)�l�]�
���y����������������4��(�� �2/�";�<3�,=�45�8%�(��0�� �#?�A^����;���r��e:f�g�^�����u6��L�����)����I�{8����)U�S*�7�]���wM7��f�U�({�({���������zvs��?�m���#����S������Y�g����"_��>V�}�������r���Y���{Z��e>��|������y�~�a��a������F_�}�~p���O=|�a����$w�I�u7������=���O�	�z�=u�{���o�w�t�y�C{����>�o�h��������~�o�i���5�_sL���@
��x���F�{5d������J��W��_W�I0���n� �=��Q�n���R�����N�O�������#�/����H�G�)>��
�F������7�������x�%n���������V��%�������m~���c:	���[:%��*��n�w3&���8��Ev�����am��1���p��K�-L�kn�_3�����M'�~t��#C�����o����Ou,>���L�b�����OV��\�����_��r��/U�����+%�����z����:���c�l��v��w����f��v���m�R������������\��s}��
��0��������_ZYem�������r���K�g8��}�����\Y��a���F�[��W��;lM�9�~4?�\y�ck�{k�[k�����%�uYUi���J������,��)�<Zf�j�l�`��{ �w��^��v��F��}I����&�WI����wsk��-��7E_�3�����k#��a�:�~U����+�C/-
��k������]tf^�����?��xjV���'���1�f���T�)~�������7~G|�|�|�{���_�Y~�{x����|->�=�������>�1��c6����>&��|�k�>;|������|�&���+�E
~���3�6���_�m�����
�3@�o����z�����5:D�5v�j�bG�&;^
�x5B��
v���r�������v�����8u��W���#�F$��Hf���Sv����������]�2U�e���9,gg[k�sH����g��<�Xyp����Ae;$�$�
z���r���^vf�&agcvN�h���oX�4�Di;o�-++h���+?��2���sT��v��9,c�����i��RT�K��\R������'�`Q[��`����w�V�}���B�:;^dG;����R�����F�>v�"6�5^�x����|��1J0�F��S�5vh�&�/����i�����5��/~�c������o�	��~Z�������[�����/c��������������{��	�:��������t�d������7Pwb��� �?u?
�a�'����|�;9Dwr��!�_���/TWA0��	��6T��0�������O
��1Bz����Ys"���4`��(v�_e�+;�
�E�s`e��U	F�'�O6�3�ds��_I�[���'��H:��h��h��`�o�/�R3��N�Q��c���
����O���4�=u8���x�cq��c���=6�����b�\��r5��)���C�w�^���}�'��_�m����>q�`��v��a�+�=s���p����x3hd-zK�M���Nf-���A���O��Z�S�o�3f_�>�c`````�
��O�k�
�g�F�Ri@���e;��h�2��.Py6_����Crw��94[uh�������kx���i��K��\��s�j�'�y>q���=#����S�>2F�vD���>���R����4^�WB4_	�|5H�/�
|�#���k~��}�G�h���~�[G0�t���y�C�M���u�r�}�m�}�7���;m�]W���q_<;��O���o������b����w>l���x���[����`~zs���0������
�w}��uC���q6d�w��S��r�p��?���������t�g��s���;�w:���h���G�e�a���t���'�?���9�mt4��d���l����k���Y(_0�z~�6���NGt���nep����cn��cm�r���	S�����p;}���������c>g�����p2����KgB/�
��a)��J��]�5�D'�$�k���So�L�s;���l�{E����<�(q�,u�*��)��-�������
�
�	�
�	���l��l��n��iJ�mJ�kJJhJIlNMjNKiNOi�Hk�Lo��h��j��n��i��m)�o),h).l).j)-n-+m-/k�(o��h��j��n��i��e�����O���[ ��}7����a.�����F������6=�.���_+�vv|���$�sK�1���;c```<Y�A����)�!�
Ci@����*vdG���2�A���JT��\�sp;T�-��l�����������Crw�U��6���e���6,s�p�P.�m��}^8����}#R��H���12E��Mv����b�&;^J�z�I��~%I���1*Q��$��uF'��I�e��H`�S��D���u���y+Qo\��;���&��`0!q��
��h�~��|�p`b��I	?N0�$���cv|�`�E��W	�
	f���~o6%�|j��,~L���p����,�&X�K8� �jQ��%	���W$_�x���k�NnH>�1���d��)g�R�)��SM��;����+��Wt��r�r��r�Y�9��~,����;��\���\�w��p���Z���Bo��B?�������������������������������vT�g�df�e�������o������K��������y_#�~����V��1����>���7���I&�0��j�=�fp�m�������*�;�c�v�����I�;s[�9<����00����KE����T
�wPX���C���M*��_=�}� ��AuH�j����f������_@�
OU���9v$�?����$����O�;���F��CcD��Hv��C��h�����b$;����"t^
�y)L��0]v���J(;t_	�{5ToT���`�x-������d0:h�� �1A�_2|#����o������@���F���	4f���&���4�`:!�����	0}?�������cR��G��>��4��� �����2��A�
AV�Y}|��`������1�zz������CN�	=17������l
�]~fY�����VG]Xua]���1�7�\�������+����k��k%��K�e��b�q�<���L���n�2�Ndy���9��w1��JN�cn������.yQ�b<�|
��RC�S
S����K2KJ��Js���+*�*+���Kk��kk+����z�l��t i@2�~�O_�������/g�+�����������=4�,Kp��?��f29��]i~����3qw��;L�m��e��3���pG�.���@��]`�1g�'�N1�'���e�xa<3��73��	��X������]�E������fni27�	~�z]�q��\Se�T������6�s4��b�lb.o|E{a-s�����*��
AK~z)sj	sr1sb!s��fs�'�����-�6��h�u��W
F_��������V��_���
���5��k�U���2��ej��v�\���2��e����|�Lex���r�!��V�\)���
�m �:@���mO7Hq���{�G+ ��A�B�#�-p�<I0�=����`)\����7�x>e�����OR��{D��Hv��y!�m����cG��/G�}9r�+���j�>���0�Qa�F�j���������4�i���@�����z�_[8k�t����k���C�]o�w�����K����=���e������?������=L�80���G?�8������F��Mv7����w�/�M�r7Up7����w�����w;4E0,~p�����7���Gf���f����\�������f���z���w���'�{_�~z���5��z������y�O���=�o����uI�����eU/��>j>W5|5����:���0��q ��I��y�����G��yx<��m���P�>�#}�"���^�	��� >�#)5*95*%5:%=&5=6-#.-#>=3!#3!3+13+)+;9;7%;7-'7=7?#7?3� +� ��(��8��(��8��$��������������������������������������������M����H�����<|���>W��`��������s�������t�~Y���Q���W{�I|����?��I��1�I��1�����go?�T�)����������9��$�-���1�]3��>S�����?��I��1�I��1��������[Z�v�3�������A��;��|l$�g1E����0�H���H�����L��nir���WB�����o������=��r���Go\/�hj��NY���4���XQ�V����VzPO�IQ�`�vq�R�h&��(4/`'��bY"�(����e���_�l��q�����y�w��������e��~������������P�1��9H���9H���@�O��Z�'>������w����%����nY���~3��?�.�8I���18I���1h�������|gg����5�������?[��������__��us�������������~P�]Q�Ck�Nm�?R���Y^��|��%�,�:�s�$
�F��$
�F�`�����#������<������������~\Jv`��s�48�s�48���>��r�|y����X�Mk��n<ap�?��(l��� ip42� ip42�������U3�gSS���w{p)Q�s������������T?�������T?�������w�q)Q�s����������������WF�fp���u��y1�t���[~J��7��s������������T?���Ni��H5�o����`��S��7%�8I���18I���1�~���?�$3z���.H�|M38�1� ���� ip42� ip42VG������zzz6o�|��!{�T������'��e%�����Tw%��	�fpKj�������N@��� ip42� ip42VdggK���=w�����e�����xxx�Z�����\�R�"O���J}||d���j��/.,����'�������� ip42� ip42V����"""\\\����999~~~^^^6vs����=zT+�Y�FV)/a����������66�So�D�1��9H���9H������$�����
���x�������A����c��]�v����m?��F�`l_mj�?h�J��0��9H���9H�������K�6}�tC��������Gqq��5�;w���]���%$$H�g�������A��O����D3��9�A��hd�A��hd�v�9s���u������E)))�W����F�?������R���=k�[�������i���)��S�l|.p]�9p�G#cp�G#c�k����_���2/

�E�f�����3g����@��}����o��������m�f�4��r���Ol��� ip42� ip42V��-[��������FFF����G[_���#eXxx�yQ~~�Z��+l|K��k�����m|`#�8I���18I������h�"����v��E
6��J�*��������;���x�b�����o6>�s������������X���FGG��<{��������6>�s������������X�������r�4���n{���\��Lm�@m��q@�Y��Diii��7�a����o�U��>==]����5���3�{?z�s$%%I���KC}��	R���5��=,((0
$���g�w��M�.���Pseee���^�Z+������{yy:tH?8++������=55U_�a2���7''G+����je����;dgg7o����'11133s������+W�4��?�:���^2,������y��d��y�BY���Y�Pm����6���S��������<,'''22288����dee����Y���|d)��������7?������������


}���+���&%%�O�>�7������ILL,//7;r����5j���}�]wm�������������v��1	7�A����xzzZC�`����O�<9***  @�������������v����
e��m=<<d���S�	&�8q�����%W�~�d�8n�8�#������
2����)�4���N�'	�J+�e��^�z�~```�����;fs����]����?�Z�@]��sg�|����,��g���f���[�
���S�Sd���s�=�6m��}�/� {�����������7k�,88X�eff��nn����6��6l8r�HG}B�=k��u��J?H�`���di{���������;--m��1*o��`b;H����$��M������.���h��y<1�u-Y��Q�Fj���fgg�>������s322�-["QY�j�y�dL�$�=z���/����{��d�0R�A���T����*/��U���"��w�yG�./Z���N�����d�h���jR��y�a���K�SVV�_~�e)����GN�0A��o����J�y�w��TTTH�I�&g�����
uXqqq�-��������IOOwww0`�������c���Ab;���yyyI>��C}]2#����+W�������t���KC���m��EDD���+Wj���???������*�/���~
��v�%�����u�����S��t|2f�����*M�t�vXu����a2��w�.S�#�<�/�4��`)EEE2�������_+�i���T�DEE��1�/6oUQ��5*  ��7���$f�Oyyy�������]��Z/Y�����Z���>����|�3C�����~G��{�V$f������RIP���~0))IHTu�7���X}q��}�77���O��������L�7�3g�H�G����T����8l�0�����������'gdd���<��Lm������+)zxx\�t�0��{��E�6���g��QG)9rD=���I�&�z�����!�u_zz�l����O>���~���>�8�����2���>S�L��>""�P/((P��DK+3\�|������o���O7����;����b���+�H����6�6P6��(55UU�����C=����5h��e��Z��o�5��@�6b�����cG}Qs��kW�x5�t��E��C�?��R�j/��aC+'A���="I��w�)+� 1�}�
&_��o�i�`b��?�4j��P��o��:����z?���'��[gXTRR������l>U��W_�����'������
8w��T:u���������C���
'����O��3����#����Chd�^��������Rz��iww���p�p������������S�zxx��%+� 1�}�{�0,_�|��]l�����e�����}u�`b������������6m�%W�"1C�X��n������,���� Y4k�,����\&@�,X��<XfHYt�}�i�6m�xyyi�INN��=��z8{�lC�	�����o��a�
8���k�N??��X�BMS����+�2y��?�����������?��r�z�111��z+�+���������3�C+� 1����doY/*����?��7�l��]��%f	�~<1��dW���_�t�=�p���S����'1{��'j3T��~P]�E?~��422���uD��'N���}��y��E��������S�'	�H���O���_���>���7��y��#&N�h���H�/����)�YT3��?��7l���ukU�-��/X�@��o�z������@����Sv���PkdgF6s;v��^��3�A��]�"=�~��I�p�=b�����:t�9��^���g��3T��~p��E*��@X�:�x��a���������W��K��-Z���g����S�
		��e��0@��_��r������_���#��o��V������s���[�=��n��iS�6m���$K���Z#���/�9uP��Dtt�����r2������;������o���n��]���3T����*�E�����_�G��U�������r�-����6m�4i�l7��v�Z�Hb�j�I?����Tg��A��������_~��Y���*#g����)Q[�~�_|��i����J�����c�d���]�����j�R��C�j'����{���9"{��Y���:D�V�{3f��x���
1���H�l���H'(�BCC�
1�}�����k�o��5k���a����^+3TK-/Z�K�.��)1V x��'�Y���?��#�k�����C���i�&''���:5�Riii2��W_U���'����
���q�]N
����Y�f���>�@F�h�!f����h���&$$�"www�B�`�V�Z��Z�}{�7�1C����d*5}�t�i�&���+W����4i������X�FEE���q'O����h�������\:{��I.�^:�L]�X�M�z��:u�g�;wN��c�I��~��s�n�M��m��3�',,L��Gy��H���w�U���.�/-Zd^:|�pY��m[�B�P-v�o�����%�X��D�=�����/�xzz4H=,,,4'6  ��������������l���:_X)++;z��l���vk]�������x���d�����;J���Z���g�V�l��k�����UdK��3�'..��l��Q�v��������~P�C�������}zz�:����W�o�����������n����4n��~��l��}pp��#G����w������k�CZ�h�b�����,����lp��1�~��������{o��v}�;�r� 1�}���k��'p��Y��d��	�
1��\������xQb�j�n?���T��^2�I=66V_��o�d����pE�/��R�^�v�"�U�V��9s�hu�h�f�����]8^�N�:��C�`.qf��K�.U?��n�.\g��d���m8U��M8����u��G���J?h!f�W��}��;v���.���q�'N���v�<y�K���q��d+
1����J�r�UCsss�S�����P���&�W���?2J2�z�����-[v�����\_W����C�p����p��)�����/�>qww�5�-�����R���{7o��}��1c�����{k'8�m��������Kgm��1;;�������[II�����3�u��������v(**�����`�����3f���$����y<1Cu]�t���4m�t����m��H�������`~
1�u;v�P�B��
8P=<x��y�|���7���ILL�M����CCC=<<�;3��I�d�/���dOx�}�UuR�Fhj�3>,��4�{������&�z@�c������"����@���t�2w�\��Hz��<��3M�4������;���n�'D#�JcV����v�$��=�k��~~~���:t�8q���'�O�P]+V�������K;�����SO������3X�na6b��J�K��/!�H,���V.I��QR'��J������H�%��.�z��dU�J����P-�����
endstream
endobj
7 0 obj
<</Type /XObject
/Subtype /Image
/Width 1200
/Height 742
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 65011>> stream
x���	����b���)J4
*�����^�DA�H*�D���K~����(` .("�DPY�vdg�}�gXd��M����g���9��Nw?�<���<��U������t�g��w����jt���>/��r��j��������������ye��}�A=�������xu���Aw�����i��TVV���oR�|F=x����O�4k�,��Z�A�o�/T�����P;���>��y�z�BE=����A���9r��={�p���PQE�>��/��RVV��PH=������z0�������7�R$����/��r������;p�@UU�w���
�p���[�l����j����v�JII���Y�F�p��Q��Q\\,������X�b��U�6m:t�PYYY�O�Y������C���t��
�w�.,,�v!N���{��U�B����v����g���������#{I���;

�Y��s��9�b)���u����]��D=(�����7o����J7�
�S$��o�JJJ�x�
������lZ5� �yo���}<dtZ]�6�����&
4H���%����^s�6v�����0�����}�f����^�����M��un��t&L��?��]�4~��2�v�i����+�����Tv��#|?��{�Ia��)����1c��$)+d�/[��A��:wBR���@��k~)y�$9:����?���_|�w����R��W������2�;��}�T���o����Un���E���.o��wa��������/����>�mH��z��K/�����Z��s�����O���[���7nT�7o^�y�r�$+�=�TS�LY�l���&�J]
8���#a�/������F�Z�dIJJ���k�l<x�s���L<���?��c5UV-%����t���#G�~��'���������=�-�5���>�r��&#�e�e��*��+{)99YJ�>n����R���B�Q_|�E�
1W~��W�����*���O�j�*Y��K���R������@���KuF�S�H=p���x~��G����V���r@*i?u���C�������`T5����w���]C��!C���dLj�6lP�Hu���@Z������.5J��hY�##O��s���_�^�������������2�/�P��iR�>\���s�T�+}I6�u3aeee���������C���[��8qB�I=C���l��]"��������8`�=��B��I��>(��� U���U�VTT���{j	�"���������fx��wKJJ\�{I�V^����;�o���D*�{���o4��TG_��]�q��?���m�����:�J�'M��{���87$�xkrt�����{���*v�@�A�D���$�����_��I�#���g���?K��/,�86�
��������	�rd,�;���SugB-D�}��~PW/�����'}�q^LNN�(}����eT�d��YYYj�g=��������������_;��P�Vu�t�;5))I/a��}�K8|���e&N��J�6s�L5��,;JjgW�)�������5iW�:th�/3Jm.:|9#���.,yu�f����S�LQ��u��H��
�n���������P
4����;��u��<��I�s��#F�X�"L����Ch�%$E��L�YN^^^�sT��������3��%RF��=�v��}j^��;�T+}�������j������<�lQ�p���)����a����{i���a�3c�=��B��?�y�?/�������|��Td}j��z�Vu���^|��07d�����`Z_����;v�P�x��@=�(���k�����2������%�m=O��/������R��|�I���Z�j����"�����lc�9��__�b�����{}��Z�{Kg<f���W*��k�t��8}eV�>�EJ�W���{���:'���>����K�����\uk�zPj7�!��[�9�W>`B��*;��x��!�����������G�?2|���������Y��>�l�a����}�)--��,\�0�.�(T/���Fu�L�,�=�aD^�xX?�Q���,%B�L]���K�X��'�LwL��Tu���o�y��)=��)S\��9sF����^�s/�<��59^R���^�s�M��������}��/����jW�iq^\�t���Y�>)�
�?����N��x�R$
g=�fHuK��{�Zu�8_�3g��0+�za��2P6lX���}���^��
�9���e����#��_�����/��3_}�U�yt=(����q�C�_�1b��TUC�;�ad��������>r�H���{��w���?�wv���ygp�Q������W�\Ua2z�h��P������B)�
�?��I}���n�:�����	����<
F�3{��P�H%���	��eUUU��;j}��}����/_���N����6m���^�_R��`��e�rV���Hm�nPTM]�f���U���r��.�^��������T����/���@����s������P�r�<�.,��
�?�F����@��"�A�D�����}9��0w�yB���k�������8 }(qp���12��aC����\+V�s9&�zP_]����t�T������C�Z�A_�s��������>5U��c9�{)�]��~�X�h�w�c9��L��`'N������<x����.�����}(klg��~P���WO�>�����f=(U�~������������C�����gw��-�������"��+#����?~��M�a�^=	�������j�C�������-�-��I����`U������K�����
}B<�2�zP�:W����'��0/�T�����#?���1oHu�6�|�������%Nh6�A���<�#�zP�.��8))�5r�A���.c�_4�;!�T=(.\��E�9Y^^�.�9o�t>%u��m�q��a���
|���K��������#G��,U�<���X��7�Y�~�C���N�\<��m��!����>����Z��&��3�-}B<�$�z������G�_��G����.����lSXX�/�J�&-YYY��������r�%��:{��d��_�y��q}�O��$�/����Q���^�A-�x}�`I�M���i�\S�=Vu�Y�g�+a�w��=[���r���W_}U/��=���7��]���k.�d�8|�����B��vUG��t��E��M���>99Y�=n��P�u��P/�S�z�D����}�7n�+���X$�������'��-���T��w��� @��Y:�>��w@>�F�'���7O/��b���G���1�7����w�9?��3���������U�-(��n��y�����-[��Yr�{���z�:�G_���HJJ����`Q9v�����n/u'��������8�A�Da�9r��a��=��|X�o=�&���7�v�X�B/������=���5)F��_�s>�S�?����^��l=(�����������{���Z�/�T�I��������&��A��r4T�������z����:v�X=���G�������������Q$
�����{���}�FTPP��zT�zp���a�K�e���ZVV�W�p�B�$���}��'����3�J�l�RgAy=��~�R��2�f��!}��Y�;����-��V�{)T9s��a��DYf����k���V�"��l��Y�3r��P����)�U��\���Q��d^Y������d��+��g����i����Q
�����g��Y���=A?;_�6a��w�dP=x�`}eJ,Y���=U�T�X]:��_�yB]�>|���y�bqq���U�:g����7����y������[�z.���uP�"u�M|��G��:������1���Y�����m�6�l�<Y���d7z}y��]�K!��gX�M���;�Z��Q���l(��S�G���r8�`y�c��C9Ryyy�5�/�$G���f�R]O����u�+�C��#�pX�����9S����JVVV��o*��L����;/�Im5v��9s�H��J	�#�W���3q>������O_�r����W�^-��O1�x��Z�kyB��j���K���z��R�8_c��;��p}m
)�������~�y�����:��p���ho8�{eG�j6)��9e���w����bZ�l�����~���h�~���V_�y��:]����t>������v.s��������RJK�/�����E���U��7����m_�}��ow�=@`�`u��III�����L�:5//���	�YJ��q�����;_�$CS�JN�8~'�H����^{-��S222���w<:II(�v�+}���R#��R���\����=�/(te'�%������5�wKe�an�=��������-���;��U~;���h�R]���z�+))��gOJJ�eR�|��W�W�K�$�������Z�J��*�n����]+��K��]	�T�2���a�|j��5��o?y�d��WUU�/���;��l���]�v��]�b��u��,((�S��#{���-[��^�Z�E�h���a�[_��7�D�_����/{��� ������O��6l�;���
��������%k���S��H�[����:t(�^jegg�qX�ti�=�m����;���(((�>}���~���t_���>q��s,[�,���W�2*az���5&�u���g�:������2eJ}
n������i$\����]�$���?o������q��M�����_��RTT����������C�0=��Y�f���V_>8|�p�K� �:l������z0''g������'O��Z��+��f��m=x~�H����w��u<����&�X���&����8[#�^��������PF(T�U=(��]�/��	�a��z�<D=[=x������	�����T�@���]�r��)S��7u��������T��?~\��9s�L�8q������>�,--����5���;�<T�y�U����9����z.e��3dC���_YY��Yw��1o�<Y��?y��%K�������*�Gk����E�:uJV-��={��	T��+toeCdsd�d�t����w���:�,��m������?i�$�K��ceee7n�3��:TA=x��A��?������o�/��m��5))I�(���y����3gV�Z��)�d���Q���y����X��Ci�]=m�4Y�)jd�

Bmx�2Q��Fi\�x��W���E���E����!�8r�d��]u������pH���J�7l� �<Lg�`IJ���/�U��s����s��Qo�����'�3�)9���������T��������K�Mv��/W~��;-u>O�UJ?}OJ���BF�2t�a�����Y#�zi�� ��V�aj$CD��d,*��O?�TZ���Qtvv���v�Z���:��dT�TRRRd���IOO��{��e��>������2 �IRc��V�@Y�z�n�����p�{R����DF�jd��F]��_~��������j��u�l�O��R��e��
�
�(�b�2A�����K�,��S>%{5L=(�����M�d�Q��DZdi��k�vOV'�S�K0K��F��A��T[���8_�GYJ��@�z��SK�%K����T
j3�2�
��-�W;Dv�w�c������jE���p���Q�n�g���_��/��
���c��x)���m���I��!�������3c����)�������d{]��zPuX+��>�_|��s�0�2��JB�p-P�=#)R���g�t[~���V�^���P�V���T#�a�������t!�5T�*���T�>|X�9��/Bi�z��(��j����y�e�����qlaa�����c�E�yg���R���v������b$���0���PY(C��FwPK�1��R�vu]R�����k�R���zL����%�!��&[]]saB�eu�e���HY�(�G6G����KM-%�o=(�Tu�T
�RZ����G�v�vO�(�79��RKKK�Bc����J���/,�>y���DY���5�tLuX��I�Te�z��T�j~u�T��W&fje]��u�&}P+��&��dX]����U�#u�kQ*��\LP�z�_�������Sv��DV��`"SCuXr%�Q����_����2�]�z���z��1��	��#G�8�e-;;[�R��>"=���/%���)T�u�-��_m��tF*wut,X�@P��J�(�������5I�2z���$Q���kR$�`T�T�D���E�H�U�hmL����z����U�e\�/x����w_�,���n������A����.u���e�%K��������I�vU
yG��5���I�zP�R���$GP���C������*.�(�(��@)6�G\(P"�7o���#�p������]�vy��~;�.v������Lm�7cW�.������]�M*��&e���x�NV�I%%%%�I�pu�2T�����l/((��P���V+���%��399��4x�-_|��j_�j��Sa����t��H"���KJ��L	���O����*C�P��S�����u�W�.S
zeD���@�y����3j����dH����?~��w�m���w_�,r�&�5#s=z�����#���=z4���0qM�������P�[���CS)�|�AU�I-�{aT�#�����yw�T�j��ZQ}S)�&�~s]����bW�e��&�^���0�^��+3��r\(??_o��#_�����%��&��t�*�u�[XU����������o/a^U_g=���"��J��������v[�lq�Ku��-Z�������l��/��s��d�L���Q����[aJ�U�-U)x����:#Y������^��wo�g5��K�)��3~T�1n�8��;����c��	s�����a��(�'�J	#��{Cw�uA��d�����Lo��K�Pc`uU�U�J$��������m�����U_T��	������He)YR�VJ��n�uR�$����� zC��W&*j�[eG��xo}���=�.R��P��c����G��D���P�[��J5I~�"\����7�|�=������i�W��S�F�D���*�N�)i��9Q��~��h�	}����n���d��������:��*�e�{ ���5'����
��C�N����{��.�������o�>��o<yyuf��F8v��nT��S��
��o����:?���*��tOEQ����Sss�wR$Cq�X�1!nm�0k��q�sLL�2�	�@)�TO\Ew��z��X+R�1U`�r�e�q��:�P�}��2�J��1MJJ�|������k�c<�������~wL	��D}��,�l����q�[��H�`������h�"}�����B��;��2�?���u��0/�8w�\rr��m��yiiiR��������K���[#�k�)))���}�h�����o����tO�Y����.-�zP��Z�l�w��DM�:uj�`�6�_����F]����&�����o����P����s{\�`�U����#_�z���26�1�^C�Ml��~�Q�{J,��b��
��9s�_R�^F[��L���T�$�K��#����9�7X�l=��K�~�QI-�z���A���P����YYY�Y�*�oG�����$���`����us��������������A}}0�K�Kl������fk�3F���)�_��Q��o��#����-�+//O����T��:��)+a[�"h������c=����}�b�������ruW�o�������0b���G}������������������F����z��$��%)�:��;���/k��D|���Q����E��[�y����1,s����w���\ZZ��_���/�}#�"�f��}�h�"��=o2\�>�Sq����=_�B=��)���k����]e��������W�8�������A}���_E��d\����	�|QY��g�SL��Y���[�l�c�}�ol|��v]�WW��}��`S�����T{�2�R��rL?��[�����{��I�R�jE�����!��z���m��xR^�^*R��k��;�������.�H�A��n�[����z�7m������q���t=������*1�W��'a�T�1O�2��~e�Q_��>�R�����S�t����������eee�&L��z�e�����g�e����{����S�z����C��&�0��t��s����`0!;;[=�EF��'s9rd|
��6//O}D=�_��8J���������P-������>bX�*��/:��A�����t����o����u�V�W����������E����O ���WR_����R����R#�x�Af���|�yG��u��|�[�����S��1c�����`��U���X* u��upc��q�(�������cE������/Ez�A�yU����J��JE�}������'��[��y	[��n���4��G�[�������+]������,Z����:�e2V���8q�Y2RR�,���%��8���[��]��hG6+V���e�|J�III�|�����=[�w,�"��&�L�q��W*������15/&��u�P;v��A��{o��D]�2e�T�2�����7}�t�GO����m~�J���"�Om��A�Xo�"E=@��]�Vv�e��qr���jl��dU�������=����y{���
[�u�/���d�Y����>^��������BR]����q�����a��9��t�~�{R$��U�'P+R/��R]�����2j������U�e@�~<[C?^r��Ui~�U��H*u��P2&U�z�����W����h���/��w������K�r�t|��~���Qcj�������K��N�����H}�
I�GV*�8Eu#�����&L���T���Ro����m�����}r�P�����-���[{������G���5W���~SL�>���?��	`���e�.u��re0/#L5�T�[�y]C�2�����e)����e��GAc<�d��S�NU�r��m�h�y��q�J}$%�|D
I���Nt}�I������P��`^�A��z�C�NMM��}�z���}h����_Ko�����t`������������KVw��{;�\_"����t��%�:�n���~M���*�n]������;�
�=�Sa5Ux���R����E��������u��))�dH�d[�a�T�����C�/����":����n������#�+��H��~_�������Y�W��z�d����Q��������e�mSs(c[��KR�J=(����r���������G�F�>�0=���	j��
�K!{L������%6��*\�0TW�]e���n�?>_��C�.;c���g����/_����p�Y�ti�n�~���\����w�G}TYYt���7�<��cW]u����t_������?���?��5�\��M�����~�aiii��
��3�7B����_��.|���o���k���m������%B[�n����I<V�X��K/u����o���t�M��&N�X^^�����s�W�����]w���U��-[�~���?���;�<���/���zh��U�7o~����|���$��Y5m�4�����0���}���K93y�d�e-Z��HK�N�rss���=����G��V�z����{��R�80%%%--M
�;��C>(��Z������?��OG��a�I���S����[���9g���{��]�vc����q��-[�.�a�->����6���������>�_�_y�i���g��)++������k�*�O��.\(~�5����O7J*���Ni���w�}�)))��o����G�I=(��u�]'u�����R!6�z�/����ddd8O�<������;������u����s6~���jW�^��F�PCF�����a��%K�����?����====����t��_���jc��_5�z�����
�����}����~�
7�;w.��Y��K�+++u���={������e��m���`G�o������|�I�9��us6J=��+�xg�_@����7�Kx|��2���k�_{���d��A���eR��={V�����R��������`�U�1�rrr�?"����>�a��]�z�H�~�i�9��_��rJ��}�w�^�z��;v��;T���O�`���w�o�!�:w�l�W�j����?������?�X}�0�^��z���2�e��UUU��v�;}���_t�������wo������~�_
J�3s����ta,��u��M�`�����Tp�u��gF��<P�?O����V}U��d��%���[�>u���������6�>��n�%������x�f�Y��3G��y��������������U�o���?~����������G�4���^�`�]w�u���O�<9��������2gs��o�����c|�� ����I�}��gee���u�R.�S���;����3���k��\~q��U�[�z�-��.]�������eff����E����������
���#;L(�����$u��o���L����;w��_��_3f���m��E��������
��CD
����w���W���#z��?��O��?('����Z��z(
�/�z��[n������.]��u�{+�@=�^��[���7����v����9�������Y�M7������KKK�[,=������9�k��/����>h��}�V����H>8h� �]��	��������6[VTT���[�\sM���g���m��������s�={������H�z����W3�^�P�����������qv�n�M=�t����o�]v����~��[�J�~�������c��VS~+�zPU7�����P�2�v���
_}I�z�o��j�U�V�&�<yRM��:�n�������~���^+{#�<�����[�D���*@l=x�<O�zP	�<t���_/^������&�7��64���������8w�\�-d�{��g7�v���������'NH%��c��G��IP�(�z0��&x���MP*�����SC����{���g?��m�������;\�t=8r��8�Q������������SO�<y��wv��������^�l=��G���N��]���>z�A�|�}�.��A����]��G�Q3,]��5)++KM������F��%0w�u���;}�UP�v��I�\�d����t>����\v��'��>�U��1%�����XQ2���[������������^O���G������~���L����m�*�l���u�������<�_t������g���9�%���Y�|�7-����]w����fW�yS=���/cX��"dK?��#��e�����U1��}�C�9������s���1���Z�?�|������y�L���srr��[ "�7o���E�o���
������;[��,U�|���7nT��{�����L����l������[o��{%�z ����aX��]W�^-���_~Y~|��KJJ���=[�lY[��;��������_�u�]������R���={���K�.U�����V�Xt-��E�#F�zp��e�����&M���c��3f���sgrr��~�;��_�����J��������^������G����c��������K���^�������_H�|�z�V�ZQBF�R����������P�I
_�z���{PEQQ�|�����'?����o���N�:
0�A=�Q�i�+��SSS�y��[n�E���n���������T|���{���:t�p�u��Nh���#�<2u�����^���e������I�&�������k7n��Y��m��������������(�Y�f�~$--��Gi��y�&MZ�j��g����P���������&3�G������nTTk�(##��+��R�}��S�L��i�����z�)i���+V�X������^z�e~��������Rf�l�r��i���C�6m�T*5Y�od�����!C������|<T��+�5@����"�_�*++��/����K�������4��}�����x�r���C�q��9��6m����;g�[�n-����������5��DX�E�Fh�T=(�������Q�F2i��!�IQ��]�v��<��s��[o�U�G��l5j�4�m��5s�^���[�n��Fh�:��/�:u�;�e��R@=����������K.�D�r�J���_]�o��6gc�����^s��z�jio��q~~~���u���K������#������3SPP���h�"5)77W��>}Z���?�5saa��T�z�Z#�����I�&R=M�6�5I��~��u����nh����~�����o��	�o �7�xC=�����;w��,%%E��]�V����y���~ ���Q��5k�,)�������
�$�5j��G��?�|��m3f����.3�q��KoO?���K��]��'Tu����Z��T-������M�$+
����p9w�����.�����S�t��z�Lyy��w�-�?�������K��7��]H^^������Z���Z|����];�������yTk�2���al��IU[6l��a���������m��Yz�X�������K5j��CUUUE��+��B��W_}U�$���A�@�",.�W�n����~�����h?{��7K�������'��0O2����42;HL#cR�]v�e��iii����\�`��?,^�8��M���	��`q��$
��1�A�`Z�����5���SII�n�����#��
���o�.A�/��_?�����(����Y�F�eQ����w�@��9��4�F�`I�i
9c����b��{�q���w����l���K�V��K��q���&�r�w��U��y���������G;G�%����s���woi�����]����lWcTk���9����42;HLk�S��/����b�$�zP��q��9��&:w��ZBzz���^z�e�eff��y�����[����#�2i�������#�_~�,D��9--M�}�%�,Y�$�5j��XF�`�$
�5�����C�-��T
���qcW=��#������w{���p�B�>��n�M;v�����]���3e9-[����O7o�<l���M�6o�<##�;�4�$�a���2�|�U�V�qY�k�����+�����Y#��y��}$
��1�A�`Z�����/
�UVUU-[���g�i����_|��W^��s����WTT�ZKZZ��?,Y�&M�������>OM&�2��,����zg���l��M�-|�ZTk�0�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HL#cl��;HL#c����42�&�9����42;HLk�+..�4i����k���q����5k��m��}�?�#���C����[.����������{���fiii�<�H����4i��U��={fgg��9''�W�^2��,����F�QQ�D�=��2���� i0�af,##��+�������o?e��M�6-_�������+��b����H�x�w�=z�X�n��e�����Q�8�U��9S���-[N�6M�/�d��M�R�U��G&}�{�2d��,���g���FE�F (
���HL#c����������)�:t�PYY�l�������~VV��#O>��Lz��guKyy��~�3i���O\3���_z��R�:tH7��3Gfn���|�9����uk�$�n���l���,$�j.�5j���G�`�$
�5���zP�%W{AAA�F�d��!C��;w���w�s����������-Z�p\]�v����{���[o�U�G��l5j�4�m��5s�^���[�n�lQTk�0�9����42;HLk�;t��/�p��)���-[J��O8���H��w���Y��&M���%K������K.�DW�\�����_���n�����Ci|���\3�^�Z�7n���~s�]#��y��}$
��1�A�`s����]����m���������y�2w���j�f^�h������ZN�>�Z��������PM
���h��s� i0�������SYY���7m�4�XYY��qci1b��#��dR�N�t�o���K��y����:KIIQ-k��U-iii���������vTk��9v�4�F�`I�id�i��YR:]}����������:u��#=z�P�l�-O?����p�
��O�8�����Z��T-����/�UO4
�����s� i0�������v����o�]J��:�����J���g{?���������J�t��]Zn��f��yyyjQc��U-c��Q-�_fl���Lz��G��<�5���;HL#c����42�
2�����A�?�z0777�zP}o1�z��F X�s`I�idv�4�F���K�6j�������rM�~Q�q��$
��1�A�`��y�C��M��_���y�6���l��EX8\�"�����������P��y�D��/��}�/v��!��&�����x�7�]c��N� EX8\�l��Y�N�JJJt�TUG�q�V_��0`�E��~��5�.���}��k��N2
I�idv�4���3�n�:)���g1(�}��������;w~�;����������,�j�E�R:��v���h��o�^�G��l5j�4�k��5s�����[�n�v)]��v�@��96�4�F�`I�i
6c���/Y\\������O>)�����7�RQQ�.�}��'�����/����.�,33S7��7Ofn����x������#G�\~���Y�s���4��%�\��"��5�s,#i0�����f�v��!���J��ri��������;������]�~}rrr�N�B}�P��9S���e�O?�t�����
k��i���322�3K�L��*3�GZ�j%����>|��>��2�a�@P�9��4�F�`I�i
3c'N�(,o=X]��Q����k'u�W\q�=���;7�Z���~�a���4i"�]��=��yj2If��df��|055�;[fff�6mZ�h�{��Z#��y��}$
��1�A�``��A�`�$
��16q��$
��1�A�``��A�`�$
��16q��$
��1�A�``��A�`�$
��16q��$
��1�A�``��A�`�$
��16q��$
��1�A�``��A�`�$
��16q��$
��1�A�``��A�`�$
��16q��$
��1�A�``��A�`�$
��16q��$
��1�A�``��A�`�$
��1D�"m���m�/H<�s`I�idv�4�F�����N�A���s� i0�������r./�YVe��GH0�s`I�idv�4�F������`��=A�	�s� i0�������r6���,��>�!�p��$
��1�A�`CT*3�r���������A�`�$
��1D�"m��,�95�!�p��$
��1�A�`CT�7�s��EcG�#$�9����42;HL#c�J��/���������A�`�$
��1D�4y����W�=B���;HL#c����42�������s�}"�!�p��$
��1�A�`CT��Ov�����`�=B���;HL#c����42��O��s��t��`8������ i0��!*Ec�s���_�=B���;HL#c����42��������:t��H8������ i0��!*g���+��	�SH$�s`I�idv�4�F���/����M���	��A�`�$
��1D%����z�4yQ��B"��;HL#c����42�������KfN
�SH$�s`I�idv�4�F���g�p��EcG�)$�9����42;HL#c�������<3x@��B"��;HL#c����42���z�w�z0��^Aw
��s� i0������������z0��'��	��A�`�$
��1D%��]�z���SH$�s`I�idv�4�F�W1(��t�;�N!�p��$
��1�A�`C������t��H8������ i0��!r���|����Aw
	�s� i0������"'u�o=X�wO�]C���;HL#c����42����<�[�oZt��08������ i0��!r�_����������A�`�$
��1D�b�v�z�d�������9v�4�F�`I�id�+����,;2��!ap��$
��1�A�`C���������F�]C���;HL#c����42���&/�}
��t����W�]C���;HL#c����42������k������O�5$�9����42;HL#c�\����,x�����?>t��08������ i0��!r�����������v�;��!ap��$
��1�A�`C�����5`��I�G��5$�9����42;HL#c�\������l�����?Ve��wH�s`I�idv�4�F��3���t���g�?V��t��8������ i0��!r_�`��/�_|N�X�i}��Cb��;HL#c����42��������r�����^.L^t��8������ i0��!ry���`E���G�~�p���{���9v�4�F�`I�id��������`����O��EcG�;$�9����42;HL#c���������K�.�?�< ��!1p��$
��1�A�`C�N����L|s�������Wz�;$�9����42;HL#c�\�C���sOU����}���{���9v�4�F�`I�id���r�.��W}s\�x���;$�9����42;HL#c�����?�QJB����A���s� i0������"U^V[������:q��$
��1�A�`C����^
�}g�x��ok�Q�u"�"!p��$
��1�A�`C���N�~[��.�1���j�H�wO�=DB��;HL#c����42��=|H�~�����_|N7�oZl�8������ i0��!B�_���]���T��������E��	�s� i0������"T�s�.��z>�?��gL	��H�s`I�idv�4�F����t����s��x�$�X4vd�=DB��;HL#c����42���]�K��������t�����!��A�`�$
��1D�������[����/��^4|�g�=DB��;HL#c����42��.�S{)p�[��2}w�Cf�}"�"1p��$
��1�A�`C�JfM��_���Uc�7�k_J����!��A�`�$
�������}�6j��]�vaf����Q�f���HZZ�#�<��y�&M��j��g������������W/�Mf���SSS���������k3�#�x��X7fw�������A�`�$
�5������n�Z�uu���^z�e~���������7n����i�6m�4t���M�J������Ye�����!C������|<T��+�5��h���WK$}��k��N�eE��5�s�!i0�����l���=�������������>�������u����t)�;t��n�3g���M�6������GU�JA�333�5k&����j��)|�]]������Ou��n��:��pak��XF�`�$
�5�����5o�|�����^x�~���]���{�9W����*��G�v6�5J��m���W�^���[�z_cl�����%�u{�3�������_.l
���HL#c������������\���������Kd�+W�tMz�������ns6v��A_{�5���W����������cS0�e]���L���/>���7��E��5�s,#i0������Xu}��s��U_H,((pMZ�h���K���O������f.,,T��\oTk�Y�+�k��
ku�����^7L^�Zp���;HL#c����42Vq=��_�����p�
M�6���~t�}�M�0����5�o�!K���+���s���RRRT���kUKZZ�w���2i������c���gu�W�}�n/�pD�sffL�s-��q��$
��1�A�`���l��Q�=>���m����1��?��|��;�p]z{����]�F�BN�8�����$�2m�4�r��1��m���I�����j�1����k�'��N�^<}R�{(���s-��q��$
��1�A�`��������9s�-���w�}�|��p�w��]o��f�B���Tu6v�X�2f��r��)���%�������Tk����<���������t����\.x�s`I�idv�4�F��#�}m��IU[6l��a���������m��Yz������z������_����/��s-��q��$
��1�A�`���W\q�|��W_�-�~���N<�I�}��V��]�f���Ot
�q	!����O=x��7�g�q�����	�������������'���]m%�L��p�`�S�t�M�z0��/^�z�C��M�I��o������O�s��+)�����8��^�<��>���� i0��UGP4������������n	�v�\�����Y#���x�G�������O\8������ i0��UGPv���U�V���7��o���s�w��U��y���������G;G������{K{�n�\�Rfgg��Zc��)�_��trM=���zjU��8����A�`�$
������A�a��q�F�����;��OOO���K/�����L�8o�<��u���A�r�Q&��=[79r���/�����3���5k���K.Y�dI�k�AUv���N=��55���j_M��U�����s� i0�����r�����F�n��n���������w���#�����w{���p�B�>��n�M;v�����]���37n��e�O?�t�����
k��i���322�3K�L��*3�GZ�j%����>|��"����-�5F������;��C���/>���or�=��!�s`I�idv�4���3&��E~�0t�YUU�l��g�y�m���_~��_|��Wv��y�����������KE��I��z�����S�I2��&3�G�������233��i��E����R�/CW|�=���z���zji��zY#.T
���HL#c����42�HT�L�_��qM-�p��Z<cJ =D���;HL#c����42�H�o�RW|����kj��Izj�������s� i0������"Q����|��kj��z����!��A�`�$
��1D���%��+������_���_�H�(8������ i0��!���^��kje�����<�DD���;HL#c����42�H����+�����V}s����|0�"Qp��$
��1�A�`C$��~\���	���+)�S���H�(8������ i0��!E�G��Qb�D���`���{�D�9v�4�F�`I�id�(5D�{%s��3���[=CU�	�=D���;HL#c����42�H�2H�{�K>�����cz��������s� i0������"Q0�]���X��!�����������w|�������v\�iN�����S����1n��;6`z��#z�M���PEB�w�{���V����gfwUw%�,���g���;3wg��g���H�C`)`�������4@i@l�1`5����^�_�u�6�&=���!�0�i����@c@�4 6�0���s����A����36���!�0�i����@c@�4 6�0����u���6�]��+Hq���=�� 
PhH���P5c��f��m ws���,}���1H��������1TN.�=eA^��!�B��5���!�0�i����@c@�4 6�0��Q���V��m�HNT��"y���1H��������1��P�{����
TE�B��	���!�0�i����@c@�4 6�0������F�����%�� 0�i����@c@�4 6�0�.���m���Jb�i����@c�K��u��+���f�����K�C`A`�������4@i@l�1�%��R�����:jV��$]M��D){,�9@�4 6��(
�
4�D��+��)#;jV�j���9,H�c�(
�
4�Jb��.Q���jI���Q��]�frg){,�9@�4 6��(
�
4��%��`��|�Q����f2��R�Xs�4@i@l�1 
PhtIsd��.��Q3���B��S���!� 0�i����@c@�4 6����@���lX�Q3�����n�f){,�9@�4 6��(
�
4����M0z�;�w��9$@g�,��������Jb�i����@c�K����?��5S$'�����"a�%�1H�������@�4�]�^�Q�����
ue
���������Jb�i����@c�Kd��t�b����Z�(4���=� 
PhH��]�=������NZ���&�z,�9@�4 6��(
�
4���������u��b�����H�c�(
�
4�Jb��.���.�<��C'-�fOZ*R%�!� 0�i����@c@�+�1C]��.����������R�U�S_U���+\�U��� V�Yc&k.b�*�j4w����tI��u��k�r��e��B��� �z,�9@�4 6��}35��Z��K�2_;\����+������9����/+�����2�]e�e� ����������9��%�����-��=��C��S��K���r'u��Xm8��c�4���Z��������@��lX�sy�������Q7��q[�c�(
�
4�Ic���W]|�L_�\e�0E��~���g�������/*����+������Q+c�(�F)&)�fp{�J[�����������?�.<�����N]������	T�E������
YK%S���U�0��.�^>W�#C;iY��.���e�z,�9@�4 6�������*{�*e�2�K��{����7��(�~�xI��"�e���)�*c�+��)���g�R��Wk&7w���
N��.�Kl�e��
��f���d�L���K����y��h��z����kI��IK������I�C`A`����������+�D�/y�2v�"�o
�_����_� O��:�����Y�
oO1�f�r������g
��(�������4�����F*�'*����^��L��N��U���*����7�����rg���P�F��x�����YKS6�[�&��tI��	�,1������9	-�vo��������Jb�����h�;w��$�'Nx������(�F�lW�^���	�w��)jXs	��0Y
��Q�����pW��R�\W]P�P��'c��I��J��H���2a�2n�2�Ke�g�����V�����"�w4��������������b����E�ode��tU���W8�[~���gn�������}/������jCY},}w���#�6{�f�K*'�\�2?����!B��5�$�!� 0�i����@c�Z�G3};���{�"��-Q�ZiL_1v�(M�@3bM���!A]I�+�h���&���Q��e�Y�T�i�-e�2��}��-3��X��"�4C�{���������=���S���,8�7����H
��nc���@*F�U�(���"9AhY5g�T�����#���<d�T��L�v2}1_(B�����������}�������n�J��~��f}��6��Vx��@����\��L�S��g�Mn~NSr��Q��M+^��f�[���������������,����PhY1~�d=�k@�4 6����JN�����������o�|{�dC;����������L_p�L_'@i���Q.��B*�����KYOK�(j�YU�Q����T
$i�M������+eX�������=]O��w�����������jy���A��5 
Ph�l��,������d�������o����W��jL_�dJ�lhr����e�����6Lor��4\p���������f�4J�;���R����Mn�������}����I��qS����k@�4 6�����K&�Wx��>e�,e�`Jf��S�L_�����4�G�/��g���:�������*����Vnn�Mn�����s���5���Wn*������uC�����~�e��qCt�
K�$�!�,p_�����z�������em����M���1}������^#����
�g��(
�
4:GUQ�[8z`���fO��HI��������Jb��}�������`��M�f�^"�?��B���Y���(
�
4:GY�'���I��l_�j���9,H��@QE��^Y������RP�B�{	�����)�8���f��������'Tf�?K�������JA�=OA����"�����t��"��T���(�e*����zU�
~]���
������A*!oQ�~�;�r<���N<������o��_ZQ�=xD|���G��"�S�����2�e����3�o=P3��@����C���(�Y�p����_���R��V����h�������(�#a�2a�2a
�LK��L�������I3�I3�)+�[U�lU�U�\J1�B�Z���j���2��-�����R�
U�J�y��Z��F����Qg����en�*T��iEm[)�${;%c��Ii�rv�r�P�j���r�T���|U�Z
�wH�w��T��������S������%�.<�.<�.<���R�Eu�%u�e�o)�V_U�\��q��P��R[�1�?������*S����I]~�2f���+\5�Uk��H
=�z��*�R�L�/-���c�Y��C%3���x�e��jH�����|��)f
�"�D���,n��{@i@l�1�9��T]	���l_�k��^�q[���e�&��/�'w����L����PB������~4~��}����s��59h�����;H��R�7���u����)�)�����O_|���|C��������/�e2}����+��Xj��
c�}n)J_T�ht�"1N��O��}��B{��e	z$�1C]��i(mMZE
��i����6�7����s�_i�8�c�����L�E���i�4�(M}��Q6��@VK�����������<�OPd�4���*s3�D��	���Qxg?Mx������k*4�Ux�xd��1�9-Qa���^>�������
�I�C���s�5!��L�~�k(41�3zi�6l}y��E8��}�&(�?���������bts�Qxm�U��������D*��Ra��X���F��m��sn���"��|���g���e+
X���� ?����_�e{�����n�f	zL��@]�.s�%]����A�V����<�>��#�����J_��<#d��������S��~�V�3e�f���E5-Hl�����r�RF+��Kh��?`4�*��)[�<��%���c��4;���diT	H��d��!���iK`
�����������hVE	�k#�����kC�/���	�����j
&�[��f��5k�r���*<4+��4�+E�z����_��Y�@OG�2�&��+��Y1g�Y:w�����Bk��.i��]�5w���,��+8�7�4K�N��J�����=n�i�AZ�G+��iV�YQ@/-��Ck�wi�����Y�4�537k������5�:��L_�Yo����G;Z�����R�h�'.�`K�hV/������q6eL��Y�8�T���f��4��j�EN�5��5�%�S�q�X�:�����W��l#h�%��Fk0c����Lk3�j�i~������_|����,���M��_6^�H�Y6���
��?��V�1����-i}���_n�aR��_�?I������?%�3,�	�L_<�B|���>n�>��>q":���'�����C���s,@i����@�4�u�]���]�o	���5�$�!hn��b�z��{�(;�?.R��J�C�Vb����2,�������!s�4�4E5�h K!���<�����%�
27�)��rO��fdJ+�:-9��D��3��)����)9���q'L!��>=r�T'��2G���6�~6�g��0*�$�����2�ig�*��f�>s���������P��E�6�~����(
<�@c�s�.������l�HN��7�3E��UZ*���[t�\S��S\�)��H����"���03a*��c��f��i��0�i�Bi�F�E��?�������Wh���(n��V�������d�"�������\��L�%��(�o��49y��\m�XnIh�8c�&'�!��.�A�PU���(MN���?Y��f�j�7}4��5}��8���Lu�7}u�0}��M 6���F�k���?b�e{UQ��^������EYK�����2g�*u1MRD|@��O��h�[J�qo$�e���*o��T6�������2����h:Y�����
7�.�@����(F���'�������/


�������f~��B0!oR
��O(8a�MI[N�9�����XT�@����d>ECz_c�M����m��i2}����M��(M��+��Oz���%����Y����9s���jy���o���Q5��t�R+�N���������(����z��y�r!F�L�NO��A�?P��DK<0�i�+Jk���
���������\#7�������R����q�hqe�TR3�U*�����y�"����7JS3����-eE2dm��t�gh5n�3-���]C�,VT���wSc���q����_2}������i�z����[C�����ha�,��2�=|4)����Ec}�����������B^]�XY�XQ,+/l(-�/��+��+������K��I��J��L��H�L��H�-O�.K�*K�(�+�-�
*�,��/��+�)�������������������y�!��.���t��n��\��:[�8]Nq��|�|�����gmO%�8�X�������r(������b.��>�'�����;#O��8�5�������o=�>��������V�]�����KvM��r�����[��n����[���#��������s�u�#��5f?��$vv���u��&��H_MI3�>���S�I�Q����C�l����?U�4����}
H�f�
l�`��4RU�� E�(%Q��H����O�>Q+��C9y_V����N��6m����(��M������n�hH:k.����Pcd���+\��elx`��$���~�L�y�d��;�1}��h<t2�i
�L!oh���4��\^U�X)��znX
�k��%�:;�*+�JgXb��aI�,M����������H��x��!�r�����q��{+�K0,6i���aI��5,���%�q��5,���q�r��e�a��>�]��=Q�
����[��n;"�5��VY	�e����~��m�,�
3����k�4��S���|g�D�����u[2�m�(��#]�p�������gq�5�q�@������i��~d?�C�I�nN|���wm����Hl����<���'��F[kcv�7D�EU�7�)j�e��1c���?P���9}F�U��vv�U�	u���W�bs_�.�S:�(M"��i������<�4Wx�R�fm#{���F���4sG9y�Nsy��+������'�-��
~]�������13}5���6�sw�M�b���yq��}�Gn wU�LY�8q��7J�#Os[��7A�}�r����0��o~��w1���7�S��6�����"��m�����1�T��,��HI���G%�<�b��_�O����3u���U��/�����4@i���)k/'���r�|�h���Y��A�iL�Jo�\]~�
�����{z��+�j��J+r���kr*������}
��s3����]Nq<�h{������;#On
;�:�j�����[��Z7�c��E���|~���v�1�������]��}���s���f�.5��4���C�C���}����y��L����D��+�4w�G6�O�@�������)�R�T(��q�\�����f�N�q����q�����Q��N��('��A�����M�1�gMx'L�Q4��*��E����������������H��`�l_��k����O%����]��m����\��B���zo���z����.�8���az�������a��{c,������n����|�0��[_s�?�q�`�Y_��v�������t����������-�fj���I+��Y9�s�t�5�x��yw�,�
�}6���<�w�����w,���4`���=+����Z�]��
!7��vtk����wD��yjO������E��s�`������g},�����\�gm�&�<�d1��R�-�������\l��l���2<2=3�:ey;g������x�z�����=�w���������������{���=�z��
�u~0���]�vm�M)z����E7��[���K��-W���g��@�=�O��t 
P0��9y�����0�MN�_7{u<AI3}��	S)s��;����
sZ��$N�N^�'y.��D����$��-������|�n�_}����az{�0�9�a���_X}��=��^:�2�g�\�-���)�P����
����#�������B�6,7�
��G}���`�qG0,�����0����a	%�Y�U�]�[�W��P��e�\��R��^��U�U��SW�[W�EX�PZ,+/i�(k���WW5��4�q�����reW���h�	���sjV��M�E��K���46����Q%�1xyS��-~P�UWx��{}��o<s�4@i@l�kLYO��Y]��:@�aI#?�i�/m���/���M�L�*K.��-��
p��{#���f���saW���aG��[�{���w�M��b���/��t�����I��>����7e�\N�X��7\��w�
�����)��s�:q�t1��M�+�E�
qTQ����`W��;��p#S��-��;&�������%.��]d�/�JT�:$v��*c��~�JG�����Jb#����v�DV�SW�Z��mBdi��8p�p+��[	n(��8r�
��hp��M���|����nI�1�������j�6��Yni������\nu��]���_n���s��bn�/�8r���2��>a�>s��tzM���\s�-W�Z~u�f@l�1�9U�&���������I��n�f�{hTy
�`��h0�9@�4 6i�^�����4�6_��-�$��0B���.��U������^�uFX�������KG���4��i��`v��Pm���������3G����d���Y��m[�g]��-�G�D�>{�D��sIv����2<��}���F����)OJ�����+h(-�W��4H�S�h��S9e�`������� �R�f��=�u��V9aXc��;e1`������d��/k�,�/�� �*Sk�
#���(��$�]����6-�l�n[3�a����n����7��l���9�S��_���+���M�\���"��n9�=����s�b/�J����p=��>��E'X^w�"%�:+���HVV�T��0�\s���
4:�b�`]1�2��)��]��L��R�.w60�>�R�`4s�4@iMC��[�b��,H��������Q�6��������]��	������k�f]��;+��-�2o�f�
�$���{cl����rc;�u�$��x����y��N~17��qr_������$�^�nn��w�s��C������P��V��[WT�XQ�T��n�
F3 6����a	�N]Wk�.��Ba���C�����k�Z�����S� 
P��h���6V��g��%Ue��'Sl.9~��6i��>p�?��6x���=�����k&x,��p�fEJ�u��g;~���A�3�;��>w��U3�����uY��5�����W�@�E�7����NY��>����F�%%Vf�/�����������'T� 0����@���oF���7vc/�>V����TW�1w�,�9@���e��)6M�������%��M�]�.������$���)�1n��9�?�Z6�6~�>q�6�i�H����N�\���B��+�[rp[��=Qg����B���Tg��;.��^y����-.�<%�*+�6�����
-2sK	��f@l�1�9�sv{5�Z�-s"K����f�����d�`����+�Q!�N�i��k������xD3�v=��b���	7�����I��%L�b�6�{����W��b����_"~��%�K��e��$��/�Z�\�6�$������/��k��$vA�N�n����|�u��"���f����@'�e
��+��C�w�7D����H�JDS���E}3�*8a�>Y*s�4����Z��"�kR��d��)6wMi6�tw���n�-������$�����_�m���A�3�O}SlFl<�!���zS���qw�\�-KTm���_�C��O�_?�do�z�Ax$����k��HK������$�{����6�f@�4 6��Ue�n%�W��c����*)���P
Z*�����-����1�:
��g��B��������~W��^r��k���-�v�~Q����k�i���:�{�T�U���h���0�������X�����6a9[�)6!����fE[n^=�"��)6�f@�4 6��ea�`�*'~i��5�;6�Yr�e�"�3�<��}�l0�����ry�&InBezT��y���j"$�=(�v�J�Qn.�w�����u�<V��.���_�O�
v�5�E�~��[���AVC��8�M���b�,d�������{���0�VX,+���X��F3 
Pht�2+]��g��u�6
;�=n��C�QF��o����#�c�e�M#Y�X���*R�59$=����9�S��5���\�y���UAV��w���D�#���t��-�����ov��Pm�����~�6�?7�=��E���G���wG��sA�1�r��M���L/WM�6�-hs�$WeRqmM����z���[5}�f@�4 6��Eb�����i��X�������x=e�P3mB�,��9���h�l�)l(����6!�<)�8�� �C�����K��$��]�}n{���!��X��}���)wV�q[������3��M����fwLf��Sl�D�������?�`���U�9~=O%�\��b���/{HqlTY��:�n����~��h�Jb��Nh�l]�2�$e�/
;6�:$^�C?��F��T�����c�@������L�^2�&�A9�(m�6�On.�'����~ ���������	������_{�����+�_���S��}�
�����O�8s��<mz��>���^9�y�����>,��PM��[rRU����`4�����@'4���f��w��9	;���,^EB�����|�LYg�N="X��s?rRV�n�$�r�4r��m�$w.}<r�����<$�]M�X����y�[�j����u����l��\2=�w���f�L�L�����/.�W��4t�}Y�����i����@cr�|���������ov�R�PXYY���[O=��O~���>����������c��}������_~y��Eeee5.//_�x1o��]��111�~��hM���������CtFr����AzT�;
�`�Xs��;�� ���9�T������T�n9�-\�����I�����������&'�*m�6~�6��q�_�#���+����t7~m��+�W;�<9�*�_�"Y��q�������4@i@l���^}��������d���.o6k����@ww������r�n�7n<��c/�����uXX7�O>�$wj)))m��[?�������]��|w[[[�?�Ig4���n�o�V�wT$'�����H�������5���S��9u-
e��rN�isN��q�DNjsN�rN���99W�sr��rm�I*��sN�g;�cMJ��.�'�/���f������m����<��Ar�'��l�����������Tm&Im�K����w7 ��(
�M���R��?����o����'O��N�:���3G������o�����'''?����egg/���������Q�1����rC'�������O����L:��4�_l]�����QUT�+\8~h��.=�R;3��S&K5w�,�B^!��V.�:'�<%�8�;?�%��f����S	6��q'�!����=������`������P2���
nEN�*r��������I�������4@i@l��������y{{{���K�v��������}���/-5�ttt�;�����W_}�__�`A���������G���x����o����������F�2���tF��]��Ks���;�����|���%F]y��z?��
7w����EV�X�SW�R�]����W^��lMo��q���\�q|]�M&�MS=)��[�O��k;���J��r#'�&}��$�����kii������K?�l�2���>h�:���?�8���Ux�;����Eoo�V�7m��_��?�������w���
Z5�����?��c555�S�h<
�O��F\:c��~P��g���O����TW���SFQ�\_"+�F#�2#�4!�0�#7�1���T�sIvG�Ys�����o���_&��r���&S���D��"'t9�z����&e7g����w7 ��(
�
4����o��FGK�nn����+���������;;;k��hee��GG�V�����ou����3�D�����k��b�������z���7$(|j`��%8-wUM��
�5��ia%q~�n9����)Ngm�^�u����A{�m�qw���=�q��v��n�zw�(rrm������m��
�
4�Jb�����B�x���x��}w�����l���������m�ug�W���������m��s����n�"��Ig4���;u~���I��l.�O�Cu�R�������,j� ��c(���c���8g����_L������;"N�9�,`��`�X�%���|�0��G�Z�����Y�\N��b����~�WYm;�5q�n\Nq�������/�E��R��r�
K+a��H��������XW~���Pk��\ig�l��Y��-�+3f�������o����X{�k��i_�����RPP��=?�6�i��7��&Q�{�`���M��f�}K�����>�Ks�"��fP�w��cp3�M��}Y7�nN������r�:�s��MKv�
��-��U��cqW�%�]Ku���E��
#�K��+�h&������Q��0`�9@�4 6��(
�
4�������ZKu�f;d.�o����^7n�/�K������C�:uJ����'��TTT�m����?~|��7��&Q�yUO���QV1��%����a����V��a`�M���E����Vz+������3F������w`�����{6��qr�����/&;���9ey{�EE�%$Vfh��T7��qA� 
PhH��c=��,0�VUU����{����K"���7]ps���E��������}����:����>�7����L=H`x�H��&�������v�gv������������:����n���en�������]^��{�>�{����%[��[�.�!�^�>�Ab\
�4���G_	�3'���u���)��}K�����iO��������g��ao`�8-�s���3�}/���v����@G�`W�/�0������9F�G�����������{�8�����-������b���o�Q���������K���B��bt���o2@z�4 6��(
�
4�zVo�����]o���E��1�&�o���D�3�D��	��S��v���F�,���*2zt���L�n`���T2��P�T;�u��\�[��>z`�������4@i@l�1&a=���7�����������P=�G����|�H��)�r�w-�����G�?T-3C�U�F}3�~�)�M:B��z��|��n�1H��������~0..�{���������2�������/��7�����W�&
����;���G���x���v��d����Q�Z���a�n�zF�)��)�*-��A�����Fk�/��MEUp����5�tn����o�����*s�4@i@l�1 
Ph��9S�N�m���'��������p�u�����'�x���������988�����j+����_l��4//��g�����o���O��?���4���S2�c�����q���#V�����;U��������k�4���������C"��c�(
�
4�Jb��5�=���Q�Fq���+�h����L&{��wy���g��hQ!����=��K/�t������}��=����?�|JJJ���E�o`ee��]^~�e�;?H��������w��8���z_����>�>U�N������^9l����
�����!��#���8���9}y�R�����4@i@l�����"���a��
�ko��&�Y�>�l������;9~ll��1c�#{�����[�hQ�8O�o����|�cLLL�f999����/����f��A����8���K����-$=H]_�[ouM���~��b�
�K:��7�������G��<�)����@c@�4 6��1� �9"�`!���x����*|������;&���O����=Q�E�l_c�(
�
4�Jb���P��	�-��~�{��'�-���\��>��
�_��R;��SW3��`����&-r�,c�:�X�d��������"V���rYE+�`���$�%��8����XN8�eYA,#����4o����=X�+Kpfq�������o��k,���_b�X�Y|��`����{���gw�2�=��N����ma����zv{-s\�n�`K��bvs���lf�����o��tvy
�4�]���egG�3#��/�����`vl ;�);�1;��������������l�;l�[l�_��?��d[^e�_a_b����
[�+���l������K�V.~�-y�-~����n[�����g��t"~�����nu�
��1��������U*�eei���5���<�`4b���PU�~-m�g�~��%��-aK|l/���P�;}3�*8a�2j��O�7�b.�r'�s�4t���F�T���LV�*X])�-f��*�Uf��Lz,/Ma���(�����Yn�	cY�,3����4��E��In,���;�S}���eQ�Y�U~��]d��Y�t�g�G��!rw���w�s�����2���es^��V3���a�_�n.d����v�[2�_�+S����).�c�F��_�����a��v|;�;�	;�;�!;�>y����d{��v��v��v��m{�m}�m�=��2��[��E���l��l���������?bK�bK~h`m��q[�c������|��*w������]�.�md�O��+,���6�'�+�����z!x�}�
4:BYT ���!_T�{��������	���VUU���[*������& �:���d��^cn���07kW
..,9����g�g{l���q���W4���
�����$=?�~g��Os��[�g��4Ek���Y�?������$�J� ��M 6��eV�`��������S(����|�;�U������9&���~7'����	�s����1���|�B��g~�i���d�7��:M�����Gx[���nz��������Oa��Ph��<��v�L���ir<�&����HV�Dq�����
0�7��@c�#)��S>��o7�vN����%l8{���TF
�7���	&��P���^J���^-s@�����Xz�>M��������o����������M��GY���e��y�f\�"E�r�������97;���k��(f����z�}�e���'�z|}���Q����(��8������T���:�bem�����C�����j��u�H��}+��z�����V��{��r�	:E������D\��h������������N��wiB�[[��I�u�2���Q�%��'�4� �squ~,;�]~�v��.#���v���WKO�~6��m�-����z8;��{�o����h�������L�1'�V�VfS�ws��)I�}�
4:��^�`��F|��F�p���K�-asxpO���j`�?7i�����oN�7�6i�=�h�@�4��t_�����?���D�����'R�����l�s��;����l!��2�l~���l�#e�O����#��u��(����`?�Cr�cJrl �'99�r��I�?�_O�L��-���
e8��Ms(7PF����r���������_���Q���4���������*�'����\+�S�+y�r�p�q������e���=([l�W5#���d�RF��(��RG��%�O[�A`�ri����2�p.��\1�:���@�}4�_
��JShI �N���~6�2I�+��a�����}�n�+���?d��7�z~�g�����x��������W��������c�+s�@?����s��7�6%5�E��L�+_.n����M 6������9j��C2�N�n�U��B��phUyi����``#�g*l"K��3(*s����>�,~G��pst��X��O�OR�����V��@������z�����)�_`
b���O�$����|�����3���4E{�K��c��4���UJ���'��~b���?%_����+|��}n�+��?��g5�������,�#_Y[,�������-x4���>��P/�o���4�)��9S�qU�b�����0�	Cthq����}�g7�:c�#��������1�}+=;�JTk%�c������6�i6-�<M�%���Jb��4&��	��Vx�r��x��t�5
��=H����(���,vq";3����Gs�[_�������������?)���S������j�kb����J�Z�+y�����J����*���
�G�S�htD���`�����~0:��S�����-a�Q+�vWe�20�A`-&d+mk��}L��80�X-rV�N!�����;z�97Z���(OSK��)�C��	�q=8��d�!���D�4 6�X7!_Y|�W��n������C��\6����&�������?����
>>z��g�K����W��~�R#�W�m�)K�}�`6�4���0���������/l^E�����2�
������-���L������Q�X�c��B�@_#wT]00��/�&�
#a%c��HM!-4��E���RB�����9�����@k�N}�n��X5�$���:�m�{@i@l�13�TO�e*�(H '��r7mC�~Gh)��F�Nc3����~EYk�c{�NQ�~K9m�<i~�g�m��%��Wt)���>w�V��p�#�����)y,���������[+(t�}+][�����[��KC{��r4�xRF��PZ�����4�-�H�e���f�#���������tj����F���*.�ru�������F���Vf�#7��t�� ���s��Up�FH���s��_�����G���?T����k���?-p�Y��_to�����e����Kq"
S��dm�oP'�����V%��K���M^����;�{���c�A�
f�w�IcE�raE�������5;3m/�����r�� �|����3����L�����z?��c�?�~0��1GD�3��4�?�������u�+�-A�{���~fe���Ei��)6�Y��S&�����-�������$����I�+E��]$�rw/I�R#���i�wN�R#{�E%Z���/�R#f�ZYQ~�aE5`4!�xJ�e��>�� �$8os��~�h����Z�k��������f�;?�7>��9=B?��y�����L�UG>����� ?un-Ey�����@c@��l�����N�3��h|�q���Bq�����Y�./N�J7'�RfT�1��G1�;��8���P%����5�}9>�����h����)����kfE��_�OV�� ZCqn4�����bxn.�Yi��*�ZQ�f�#��L�����~0�D%��������M>���lHP�����;
�l�Vf0�R�1�������c;�>yj��E
���7Y����G��T�;��~���"tPhHC�+���Z���.���)�):7����������hf3�*���Zw�(���f����������UV�T�h`E��c�V{G����Z?�~O!����������S�d��������,�f���3<a���~��������zae9���Hw��?����f��z�
tsOp����n���4 6���GMi�:���)d��4�UO��Y�4��|���f�v4v������F��KcE��O�n����z:M��M�j�����p���-
k��S�}����g���{����[(���p�V��m�k���G�4KsvUyi����TN��f+�KA�7������&���-6a�!�!��}�#j�)~#���{������1n��5i����0{n�i���n�������W��4�J�5znEmf�+��s[�� o�:��m\pK�_�.��%6R?j�v�jzUY�y��f�3��m�`di�X���s_k���)�t���A)N�;����58��9�n�bWgP�����������6<:J+��(�Q�x+�o�:+��lV��?��d�� {�2���Z����wK�RF@v���%�����x_�*��K��������`����k����Vh;?1�s��e�������Ou�eR7��X����i��@�iw�(Y� �� +s3�v{��M�Y�kEC/����� k�|��-^����|+�QK���%��n4�z����2�8�lZ������
:�������J:>���uW����v��V�L�i�5��0�Ch1��r�%��O��Js_�G��Ni�������@Gd��!���?��������1�ydG
��*��1����7'��3�9�ZV��R��`���T,���7��E��������)����� ������\I?x�w7 6��(
�
4:"c�d��\)����-�D��T��7f0��Lel��=Q���`��*�E�0�����
~����Y0n��g[^���"����b{�N� lf3�mT"�+N�u��!w7 6��(
�
4:"s�h]���x�n���*�2~���_{�������5�)�X�eN�?�����*�t�*�^�A�Uv�EYVDr|��a[_��J�&1�UTk��CYu~o_����������@Gd�&��C3?8���s���F�O�6�|�b�[e�����:������f���d�A������@+�S�����V��vf$e���b9>��{���'���GiB�.RdiI2���n@l�1 
PhtD���?x��H��|�K1����������T}�~E��#XsS'{o=��f��I���AK#k��*{�9�9�0���S*Nn�\4i��Re�q
���M�S\6�����i�}�6S����?b�^����&S�f�#���������n@l�1 
PhtD�����
���t�����D?}]����5���������������k������S��l�1Y���ek�
���4*���L6-����{`��UV�P�s)���I��(vr(;��C��7������+4���gB)�T]O��/Ro���YEn?�/�4o2����>	�n@l�1 
Pht���
NS�tj��}����J/��3f0a��-��S�k
�n�{+3�����:s�5��/�R�I)G��YvU~Irgq�,��m��V����9�dv���o��i��xr:'�#���(�q���m��(�����U���V<������]������ct��"�������@c@�4 6��}����
k��w��j�u�����*k�~��9S�����*.�wY��Vf���D���'��l�����B��j�q���	��(������;����y���L������*���hH���#��+�����U�
~p�Y�b�T��Z�An[�)+-��e��9Axk��v}38�q�f0���m�Y��O��?ek�6�L�v�E����"N��b'R�������bS=w�_^�k��bV�����(�4�0�+��}	����@c@�4 6�huM�`�2?�_���3��2b�T�0��z?���j�esh���e�����9>�����YE�21�i��V���vm����i��hm-'8���e����{��2�"3�{�"c�(
�
4�Jb��vQ��n+i���z5q�!����z5���N����{���t�G��=���[�%��`iceo��]l�u���~[c�>��-�������4����Jb�i����@c�]��������pm���6r�z�+z�d����7�`���<���*����+������7��n�����������8K�i��1H�������@�(�S?1t���s���<���;g��(~k�J4�=��1fWnZs�xo��!��`���w���5��D�	.{���#���Jb�i����@c�]�c�?2r��E�d]J��W{!����O�����n��2�|��L}38��d��`u>z�7�k�gE	���c�(
�
4�Jb��v)
�`��������boOS��Km[��H�k��
-��wV�����f��"YLkV�B�O�ro�"0�9@�4 6��(
�
4�%�#@��~����K1Z�I2�=T��Z���}��^�\?�}i+3�9����c��������
f�l`��C���0�i����@c@�4 6�h�L�;����Lx}��F��e(�wpe�7���9�{uS�h�E�fp��<��n5�v�c�w�u��S�z�,}�9@�4 6��(
�
4�%���`�|f�^?��$�A������+c�A���5���B^=�e���|gEC�Lv��~��FG[���	�Z�A���y��� 
PhH����p������o^w�V~p�}�im)S�������R�?7��n�nee���m��������L����+[�A�]�s�>	� 
PhH���s��n~p����"��'��p��E��f0�
�\l�J+[����k3�Q�T��X�v��L��$�gG�6��7zz��
� 
PhH������n�������
&��y����"���`���
�JD��&d}�fp��,}3����FEk���?EX�g���hM�����	.yE{� 
PhH������������o�:�K)��uJu�c��1��I��gy�}38�{C��}/�p���%l��0�\D}����\�s���CC0�i����@c@�4 6�h���V��
����[�<�?x���	BU���u%26�����D}38���Y���t�p�{��B��W��6���n~�U���m�.s�4@i@l�1 
Ph�K�����
=r]�-�D]J�e��-�S%�m]W��\7:3�MW]b���]���|H?����p����93���LV��n�v���Jb�i����@c�]��n�T�Y�����j�~����#����A���n����t7�����,c�j
����?f\��OZ$�o�
d-=NJ����Jb�i����@c�]g��������uP&X��U�G0H ��Ku]wdV�\��n�`7�6~��=��-ash`;D\i�J�zz7�:c�(
�
4�Jb��v	��PpR)�|Z���AW��!�����4�z�����nO���k;����������#�OQ>���������Z�A�
�9@�4 6��(
�
4�%d�,�Ie�	i��}D����j�*����.�h����!�6O?R�b���GPfg�OV/���v��[���+��3��9@�4 6��(
�
4�%|�T�F����V��J?�p;U�U��u	E��t�3����`�Y�;H����%�]:��������xv�\�0�i����@c@�4 6�h����Uq/�m��v5���^��]E������^���oA����_aDw>�����-aK�{�X����"��1H�������@���[y'Ko'���+r��&)�S��g���F;�2��`����*��\go����������PdPz0�i����@c@�4 6�h��AC�*)j�����*��;U���^:?�V7�~>�^r0����DK\�A������Qd�,`�������4@i@l�1�Y3K���=���1J��J��>����*k�.�L��������]�q�����mi�p�~V��T��_4s�4@i@l�1 
Ph���^���:?(k��<����[�^��2f�n�`�S��1��`��MnP4v��qT��R��Pd��`�������4@i@l�1���
�~teG��>�(���\]Uz�������T�N_��)j����������f�qm/� 
PhH��mI.R������_	|P��!Q�x��YSO=�}�`G�.��Gh�e��`���j����S#���Jb�i����@c�-�I����������S~p�������g�*�a�y]�}�'��{�1�9;J�	�����a�j?���K��� 
PhH��m	�(�`��O;jVT�������1T&��U���n�I�����	fpU�UO?�������fW���]���A�)�s{�\�0�i����@c@�4 6�h��O�`�2������t)er�i	�"�/�d2U�����=k���bYyO?���m�����[V��
`���
��r��^80�9@�4 6��(
�
4����*x����:i����*�s��u%z��E���7�'�����(� ��ow�EQ����AE�#{{���0�i����@c@�4 6�h��m�`��&L�����������p������e�3����{�	��`+�30�G>f�2�&5��[����^8/�
�9@�4 6��(
�
4��p1\��u��T��tL����[<�<���E�%�Oz����%���O�����R�*�>i��������t� 
PhH��m�q"@����yc���M��_6�t�\
fp��U=�}���EowXdP���?EX5gJO��c�(
�
4�Jb���\�����w�x�%]U���O�6�s.�47������u�msk3r��=d�.�[��'z��s�4@i@l�1 
Ph���������Ww���w��~�?T�x�����������d�n?��~[O7p�����Q#�^6G�������S0�i����@c@�4 6�h���7u��o��qp�R����U�������:-��nN�j��f�[���@�"��QJ�P�T��X��_}�_�fO@W`�������4@i@l�1����s��cW��k�/!t�6Q�}{q2k��#E�S���]Y%����EM:FKT��a��.VM�n�1H�������@[�/>'8�����l?������~U�L�����f�]'��/��MF���|��3���B�A��?q@�6�Zw�K�S0�i����@c@�4 6�h����[Tr��5}{�����gR%z��0�������t�(��y�����u�9�����-�"=����1H�������@[����[Lw�B��]bk������t��`�Y�\���;�L�e��10�gGu�8z����������e
=<&h� 
PhH��m�:}���jl�u�>�B}��r������?�d�?9�W_dr�o��+������G����a����rX �1H�������@[l�l���s�7f��~�����I�ry����3x0�����k��3� S�{��%��u7�
h�9@�4 6��(
�
4�b7~��
�q1f����_tg��7�������u�fvk3w��#t�\^9y��~��2?��O�����Jb�i����@c�-��.�P���.���"3X��+���Z�W��G�:fu}p��2p�����M;�q(�3��+��a�~(`s�4@i@l�1 
Ph�H~���O�����Kll���c�������_^�hQYY�u���/^����|�cLL���4��!oa��	V�94��]T�Gt���C���p�o��R��������o����$�pi���o	���\}
�9@�4 6��(
�
4f$�>��O����C��7n�x���^z�%kk���0++�'�|�;�������y�Eq�o�$��k�_nrcnrc���x5�M�&�11�`������7�������"6PADAilg��00��":����3�g���2���>s�s��2��Z�j�\��*�[�����9�")�7C�:�r����	z�[w�O���c�/��*]�N�\��+{P��ri%|�`Vr)�^&2gL�����>b��� 
PhH��+!���}EN���XLL_x���*U�4i�D�+d��e���i:�066�n���!%ts����IS����a~����|���c��_w��`@�APGc������9�����r+����s5Y�x{Y1)�e��������3��H����9@�4 6��(
�
4VBJ��w�NFl�x�c���*��a�e���6k�LP�����{�(�3�J����$7u�e���5��#�|}�%2���/��;�x3���>M�Q�:���\������''4�r�0c�)��R�6H�������JH���\.�V��0az��y����o��,�����p������/_�����gff��o,�8�)�}g�=siMS�;o����� m��4�u�Ui�����-���:T��n�������������*���\k��i����@c@�4 6�X	)�tww������4�:u�����?:������8qBPY�Pp�������g��x�];��<3C��`*������`��J�:��.������In������.�2��1z��%��h�����������4@i@l��B~p�������5�]��_����~�m��z�^Ps��������o�!����;�z�*Wr���$$$����o�I�,XP�������Dct�_y�c�z���!�'��������E&�
�R�Y�$�(�q�F�N}����-�Ox��)N���<��K+S��VS�A��Jb�i����@c%���k��6b��s����u�����~�-��-Z���
F�d�?$99�sg�J�����<~���~�&Mh}i��V�o|&!q�����O�FS|}���.�Q�<��U��5�7��.�.�A(�r�~X���U��	�
?�!B����=��� 
PhH��+!vvv���,��t?��Y�v��Y����Sa��M�?D.�s�����+��eW"����7o��v�����c+�7>����������f?����-=�����?��|���#�Q�.���<U2)2���,�3�C{l}D�9@�4 6��(
�
4�<pn���k|a1�,##�T~�Y�f������\{P
?h�[��ACh��)F��X���)Z����e7���6�+dw�*����N�>���?Gf�c�x��������4@i@l����~���������T�|����x������W6�����1��J�V(yK8����1${���?8��t����-
����6-������I�|���hs�4@i@l�1 
Ph�9i��)������%}=�=��x�c���b�\|����;�d����oE�e�����������jg�=���������k,�c������-��+���}B.�9�}������C�sw;r���}�����{��[��n����aM�z���=X�(j����F��=o�����tx4u\��1�#c��3(n��C���L���q�����z�M��{r�_����I[���-�q�g�}&���<�����%��R�|��MX�3���:ov�:���������p�K�q~���N��pl�3�}l���O�z�����^4�--!9D[x.n_�~��j��K�>��?{��+���PO��G��
;�/l���{w���-|���-.��F�[�����Q+F/u�Z8;j���9S���h���)cc��M;fp�����%��0���?�<�����.�{��.��;�|b���6��/m�%�^B����p���K�����=���I1O�wrr�R������R9}��<���o,�s�y1D�,N�'G��[p��bd[.I�����yv��
��:�b%��J)�eg�j��0$����*\�k���(
�
4��ePEV��Lc�������`�}��@q/'�NN�-���~:�K�K���h�xjN��=�����R�����I��^�q�b���U���9e-���4=s����SF��g��1����������,�m���uZ�_��~���*�[����E�����a����7n��F����,��w�N�&L����/�|��
��...T��ysAeGGG*�������ajj���T�X<g������Oqb0F:�'>������\�������>�+�cs��_!?v��l��a�WM��^�:���b�2�k�<�����4��4����6�3�i)��DCB��Q�>*B�nN�������k�kW����5gOiN{�O���T����C�k�r��b������K�W.�Z27k���?�f�r��6N�8R>ah��d.(RJ��Uf�A��mZ�ViNm���/�^��>��,�Xn ?H�j��B�c���h����~xxx��5����zxxP�����C������|a|||�z��C��,+�����[�Z�j^^^e����:t�C�����4~��AS�_>|����y?�rg_q����ujT�^Z]���!��;-/��U�l}DDP@�4 6��X����h�&��
)��dg��2M�r2/&y�1Cf��e�����S��O������$&�3kC[\�!��!��!���Qr���GE���#��#����]��P��PTh0�Awn����	�I�(�ml|��m�l���rI:_��e�U���|/���K��>g�=i/������;�l��I6��uB�u\s�Cs�]s����(�V���q.�Cd��G����1��{��:��
~���ba�����T{��v�2�}�r�Z�g��e�+f/���pV����������'��O�1f`��~���&��I��]Z���:�LmV�v?���SF'�N�D:�tB�����SL'�Nw���t�I$I��A� ��r�G���������f�����t='8(�n�><�.�@�x{��?K�����\-�8��w��d�^}��#F�<y�{�7�|C�_�uZZ��[�9R�z��>��������V��]�����a]�
iUpvv�����
���C5W�^��H�+t+�7���7x5F��zF����\�y}���
�d�{���}��w������:Z�"�4�������GT@�J�B�$��w���2�SHO�r�f��F���
��.J��J�u,t��F�i5�g��e�b�
���,~[��
��^���(�_� {����N,�[�'mY<'k�l�/���`F���� ����s�d���,�,G63ci�6N>e��#_0i��q��a�|�pF����h;����6���?2F���7cX�MGb0m=��`Q(m�����E���}:�!��v�^v,R��V��
��#���76�����N��P���i������~d#A�sc�VN�6-�n����h#�oO�����R���K)s������c��9�j]��]�����}����d���?~�y��'�����A�?��p�6��� ��(�kHzlLM1�����V
z��`4���G���Y�z��U�Z����n����m�rrr������^�z�#�Q����'Z�y��.�@��2���l]-66�I�&
4(�������mW��"|���U3e�����,w�������*n�1wk�BfpS���m1������]������.�y���[��D[`ym�(
��<��8^y?�v������$�����y46i���1�v�(�+������Gv����>C�������������n8l�$v3d�lv��yQ�p��:��Ml�������C���4^'(c��W}t�������9aw�pp4����)�����J�)?�1������g����U3���x}o�]���x?���-O��)����/sslvc����������= k�T��5j�}Z���w��R��J� 
P�K�I�nH�c+Qi��h�x���pQ�qU��������f���n�1h�������?�������������6.s�C��S�p���l�z�6��y�r?��%��p�����������������,#�
�E��iLJ4��
�)�s5[� ��@������"b�p�S��nO�_c���������0�X����2���*�H��P�X�vX���|���E��Q��T����4e=c9��� 
PZe@�5f�����@
25^'�n����������T�����S���w�G��^���6k�c��O��t����v�������76���
��#/��Ka�o�rY�tdL�:�d?28���$�`�Cz���>��e���fc���e���f���%��'e���Y���H�s;y�|��+H�h�x��;s"�����Rv�Nf	�d���e9Mg9����b���������y���X&���,1�y�^�X�f)��m�r��\�YF��U,��<���J�u�fG-��2��od	����lS��v���8����x���K�u~�����7��Gn8��6�21�
������(zL �c�;�G�]��jz���������%���������H�yK/|s��Bfp���O��u*����N���Q�C��j�����.��!.�r�3�����;4�,��2�����i/�gk�G�-[�p�<��)�f�����}���b7�'I�~���|�rlI��K��A�oe���ml�d�N��]lU�C�U���|6��������l��lE�nl�
�O��A��l��3���'�j$�N��7
�/z��J.���[���"[�,��e6s�
K�#;��V>	��|��6e)8����G�s�-�r7���{�l�&<,Y��la��H�P�(����<d�uq1l��<Kb�����Vn!���������vI��yg�>�rf:h��bK�(�lM��
i���#��f@l�1 �}�A���\���J�G���`~��~�e���'
7�����-�`��h�F"����z�j(�����!��t�%}�}�,���l���3��W���hs�4@i�b����T���{�d=���kNyP���Y�~E��?3�L�;���W����<����ul������'c�q��(�.c���"�F.�Ly(�H����{y@c@�4 6�p|�.��|�b]�uL����~������������T�����G
�:$���-�����k#�F�E�,���}E
�d=�f���4M�q�����E}x�QV��p��i��J�S���M�nD�1w����D���a8[�}�\���l�C{4'�����o�_j�}��1�U��=hH����p�{�G�]��c�g�$��|���0s���>d�m�v������2�^���Y�CB\��@�������W-��>>}H/�xV1�b�Nl���9��_�?|`����G����U�I�4��b�����k}�jNS����A�v����A �D-Y'���g��.���u���-m1wr��y
��l���^2�l�T��{D�V���_Z������@c@��I.|G����:���-�D���/������8[�A��8�(dw���7U$(�1�>�Gs�C�ks�r'����������������+�MT<�s+�+���9@*��LJ�1���Qt���
?�Eo��Q��]�m.��A>qX�P{�}��i[��g�������%c��I�2�N�^��pq��N��O�u�=���
}x�B�tY� r��(�@i@l�1 �s�J����ST2��I�9�������~�3����v������n�fP��G�~Re�������]��>�F� ��r���~�D	�:��1�o�,G�9)�dCo�_�DE�9@���LJ�1%��(*'4Xw�*]Vt-��RnuQ�Y��hv����	C������)[�E��~O��5cT���YN�^����k��m?{�����[��{l��Y�\E�jTJ�4 6�pj�b��Ot;n]��q�����a�x3H����B�&w�������f0nb�����Q�������Ub(���K{�G�~P�yM����z���'*nZm���.+����� ��L�Y��D}td����kW���������P���^�8k������2L�K��.�C�6wm�uo�>�{���1tug�\@�j�V������������I�.��b��H��N��	)'�XW0�,1/&s�/_�.d/o'_]f~��]�f0s�[=�?��H;:+w���*���+����P����#�.�YN���b?Q�b�Nr���W�'*���P*���2�I������[:_���j���}��[�f�Z��`F���)��.��'�;�b�v?�z�I�=c����c���g�\���F�g������I����� �x��S�\��P�Ak�Jb�g������>�!��������{�������GHD��4�����.��+���r���:��$�o����j�{��O�,����1��(�K�MT�O��b~�������
dOT|y�i�d(�4�FmR����J�p.E6{J���L�I�a��3������diFY*{�Wj
{�WJ��I{�WR"�>�,������->�=),�{dX�C���GQd������bQ��b����=n,<�=}�^(m9aw�#�B�sBo�'����{ZY��������C����#rI��H���D���B����'-d�����DP@�4 6�p�G>�����P�I�A\atf�e��R�7���;�N�5d�NS��m���������M���rl��3��=�(���6.}p����{��.��8��|�p��a����7�mcQ��1z�F���G��~y[���}�-�C����N�+}0m=����9}@7�����G���,��I����OG�}�}{Yo;Y/;Y�v��m)��uo���uZ�������.������N��ul�����?��f�Av?2�����6-l��U���D�#���3���Z0#{�"����}���5�N��}���y'�o���u3�"( 
Ph��g<��nYiC�h�<�S�/�v�7�c/�gE���3�)d��X~��}�ME������iF�*(=&���(�-z��-�l�|�h�_pI�^�-���d����bO0g�nf���J�u��;���h�{��]�	����4&'���.@TAi����@c@���#��G/T��$��x�y��>��x?x,�+����tw,��.��n.��:��H�+�0�2����
?
�����fS�,����q;6l���:�,�o�>�7K��91k����K�C���T�p�^8��N�.X����I�I�m��
�Ai��@��s���LU�Laz�iJH7�������w�������kQ�+�{zW��M'�=o�������?�+Do�_l��n�I)�k�]n�<>�+LR�Z&�f�������k�g|�����"]��>���(?H�Q����^T==f��l����l�l��i��N���j�c��O,���,1�cK����W�qi�]c���Z���a��=��4�^v,���=K���m};��uJ���������1;�;K���%���kYz�}��>,�vD_�y;����e���t�2u�����]�&�;g����H��Q����Sh�9ul��q����m�2P��2g9�m�c��I�s'g�������yS���e9M��?#km3�je-���xN��dn��?����^����){�����W.�v^��jQ�����k��m�2��[�X�B��R��������J�i�b���5�-k���������%j�������7��S�����Eup���������_����hc��Ri��TT�i��*���~����mJ���e�G����{��w���D�.�.�����O����s4 �����~9;}u[/�6]��;�[��]~J���v��v��f�a��
���V����M=h���F��zU�������W([/-"�.�Fa������u������8�^CX�L����8����f���+�fp���9%��G����e�C�	WX�k��d��	[��[�$�6[��nr���O����?�-�>[%*�-�����(�-���-���-��6n����l������D���$�$K��<KZ
[��-���Vn�����l9�Ly��.�Yl���-��R�E`4j�r5�2Le|�ZehH�Vt���g=v5o8�\��+D�yK��?��J����-u������<�]��]���wL3��f�!����	{�cv�GlWqU��������N�u���J%���J�����)�$�S7�R�,�����y1��p���������~n��>�Jua��3�
mQ��L5m!q�fK����y?H�5 
P�K�*]n����O�6%�����)����h�g!��G�Q�H�o��b^�x&D����f������Y���j��+��>��t.y����v�I������<�.N9�q��6�}����K*��l�a��#��n
,���<��k�`�&}��S,�\��]}F��[��,G7�g�����	(F�����xu�;���8�Gr��x���C�-��`v��w�9WO���}��p�v5�p���z�|�~������c���6xA�sd2��D?1�?*&�'cif�������)Y��I�6�W�*�{��ulLD��2q(���:�BKW0y$f�H3$��$#�s�q����}����+(��
�d��"�o8�#�sW���Z�c�9n�
�Ki�^��]����C��lV�����N�m���s%ta�g�����lIX���^���������g%��-�E�T����
%�f���0�?������[���a����
�|����;�:P�1����z=�����T���(3��_�(MT($#@� MazRr9Q���\pq Y� dF.����S�A>Q0E����y���K��y��) \��G����pFA�5�cv����������"C.Q��2�Q��7:/�S7�a��bx:Y]W���c-�����HA>�P����ve�x�663j�z�Nf��VO������2���m2�d"x��$�n/���k�Yo��\d��������l���=������az�{f����
?	�v���Nd.��n���dB�n���Z�ng��m�����m.)�]�y�;��s ����|�����_z�����������?�?������D���=���S��������I�j:;�.�������k�Blt�utV��F]bt}Q�L�]P���uDW]>t�8�H��+��8]&���� ���{���v��~PS������^�W������g'�"�f3����9��4#5P"]#=�R���
6��XsFK����n�/��ScNM75��,?�O�i��J�0�"@�~;��Q��$����8��s^+��~� �����W�c^��(�u�a����/?	����`6
��������?!ep^*���T�l(l��ac#�Lm&��d��D���hs�6f��b��&�M���7�%���S�L�����K������y'O
;5����
2�d�����'�O��Q*�T�3�m��D}��L6����@$bZ����`���A�����������~p����h��f?��������Dq����).�YE�2�Ot	������;p��6���.����/hs�4�4�Ua��k,�)��B/>�0 ?���l.�pSA!Y�e'���|w� �p\�mvn�	5#��
��Vu�KyzQ+`��
�K�Q[��b8l�f���,���R������E�Ys�����7�g7��=�s����Aaj����Q����W#Y�@�BH�#���w�d,/"%��P������{a 6��������d�fR�R��L}���}�lj�j/��(x�e���X ��([���u�M�����V��\f/P�D�E�
N����h�1�ROv/h�v��u��B���pv��N�K���F&�2�n��y���Y��7��O����� �`�5n��K&��\-f���]������.+3;������������w_����n��NH-�j�'�g#�3��C'w&-j�If������yyS�/�X�z[|(��"w���al��W�6]`9]���[�.�h)�]q�]t�KN�X<�(0�8s���e��yK�������N���f��1;�oY��r5���A���?�o#���5�{���Z�gR��e��8n�������=��vk�7F���7F����
��d)X���%F���G5�����"�R�NJ�������l�
����
�]�`)�����Y���)�������b3 ���	m�'�e�`^L&������������J�������>�<�L�=6��2���R��^��~�z��GXNusT��:\���S�n��n���s����i;|u�s����b|���%w���f��L��T���@�#*j�ob��5?�X������sS��Cn2�������%��X�����b��W��lt��]�3N���:6�+/'��Q�)�\�H(��jF��.�O��\����o(�Ir{�n����*�3����y)R�7�XX�eIq���d���:�F�[�h�J����t�Y��S��`g���'�����HA>�W�i��>La�?���$�vQ�~7�-�O�n"=d��^����4�pvO�s!��lgC���O$-y�f��<n�^�h [���5w�o��c��pc�;.35Z�m2,����65��^�n�����S���Y�ns3^-�6��#����@k����
�v��s~�v�%��-�\�d��
�Az/}7��� ��]}����'���Uw9���_w����9�EG�����_�]qw��������0:St���Q/S��
���5x?��N8�O���d�w�����n���U�T�������KuL�QtAA��{����a���SlJ55����)��������o��P�Aa�`Wv��~���,��~,E�d���A��G�����������n�
�*Y��'����������g����`O�1��+i�	�ln����m��!��J��	�0��z�Y0����(��������>qVkA���_
���B5��e@���E�R�'���ZB�X-
��X-.�{��b�4E~�GV�G
�d�(�@i@l�1 ���Q�:�aPZ\47Wk�Y&�������a6�3�j� �S�����P���~�������Y�NA����KT[�,���/d+������������[������h�e������}�6G[���L��lp���y�WT;h����{������O�����1��{x������u��,s�Vs9�t��9�{��C���,!7��`�|�����{��>��N�����|�$9�"���(�
�� ��������Fv�fYn�_1����S��x��>>�U�����N����+(��P���Q*0����6IA�{�i���r%��k��13B�����~��O��,rd����O��_���Zf�1���o�Y�����"��`�7���b+����M�IM��,/�j<o��s��L�|����X�5]��s�?���
[@Ai����@c@�����,7&l4/.����������w��c,;d�_P	����f�\D
w)�
�fs%������������l��RO6�k�!6�5r;K,��BqL�y6n�����-s�?���<��[`ma�k���
S��W��O/��Tb���/6�+������9\�d��hH��x?x��@�rc�(���������=�o������l�5��������4��,����[1lQ��w�r"nl"�V6w~�)6G~�a�6��d�>�����������������]����-XL��9<|�<���_~�k\��/:w�i������*o�wb�i����@c@��iYn�������_�-���>��X���������h�l���L�
���X���K��
A,�o�/�]���M���e��f����l��+��|�^ZD������	E%.?e��E�w�o����-�1�#L>��1�M�B�aE�hH��x?2��@�����d�	�7�~pQ��\yB�dQ�c[?(�pm+rXd�"�2`i�_��a���R�_�l�wb�i����@c@����b.�����y�
~q���k��������lv����6H�����������8�/4�y�����fJo:����E�����f�=(���������4@i@l�1 ���������E��d"�-�����s���M-�,�����A9m�(
�
4�Jb�f?8g9_h�m���][��A���'����kg<(���������4@i@l�1 �<p�:�P�)�����`7{�A�;�}�9f����9@�4 6��(
�
4�~0t�y�y1�U������)~�s�.�����6<rP!@��Jb�i����@c@��y��v�e�6�A�F�O����W�o���f?x`�M�T��i����@c@�4 6����{���S�n��u�� mJ���	�~0����?hs�4@i@l�1 
Ph��`����`
��]���q���������G*hs�4@i@l�1 
Ph��`�/��p�5��_����=��s�v1�A��=rP!@��Jb�i����@c@����J�W�~������J.������=rP!@��Jb�i����@c@����������~�7�-����w5��e_���A�m�(
�
4�Jb��L��E/M>��}��N�_���f?����*hs�4@i@l�1 
Ph��`��0zi�[���q�{��4��P�hv��T��i����@c@�4 6���A��(zi�7����O��<=�l7�n���9@�4 6��(
�
4�~P��^���`��wx3�����E���`�[5�0��������4@i@l�1 ���FY��7z6���f�f3�P3W���Q�
� 
PhH��x?hRd��"y?8�X+�>�mo�������AEm�(
�
4�Jb����M)G93�}����A����~��[2�H��������4@i@l�1 ������e��t���lg����*hs�4@i@l�1 
Ph��`��?���;�9?�����]����`���9@�4 6��(
�
4p~�Q�_�o��O9?���7���@g���f?d���9@�4 6��(
�
4p~�A�v���>9W����k�tjd���9@�4 6��(
�
4p~�~������������}`������`A�m�(
�
4�Jb������������<���`��m�f�6E��T<��i����@c@�4 6����`����������w.mb6���l}��B�6H�����������c�!�=���s����r��f?|��G
*$hs�4@i@l�1 
Ph��`��q���<r�g6��l����a��
� 
PhH��8?4z<�,:��;�^��=<v<?hs�4@i@l�1 
Ph�_Ofn��<���`��
�$�8���	**hs�4@i@l�1 
Ph��`��Nd�����:��l�}i�c�9@�4 6��(
�
4p~0q{��;O~����)u�~�w���T`��i����@c@�4 6�������'�� 38���B��j���T`��i����@c@�4 6���A��z�<�������fpGO[ ����������4@i@l�1 ������d#��Af���t�_3���gl}��b�6H��������������<�����k�c6�������
� 
PhH���fO����t�o���|��O�����
� 
PhH���*V�C~���v]w�.��Lz���Tx��i����@c@�4 6�@~P������u������fp���>4P@��Jb�i����@c@���3�N�nH~0yrm������*hs�4@i@l�1 
PhH����B�y_;�������� 
PhH����nN~���6G}l6�[:���@%m�(
�
4�Jb����d�ku�[���f?x����T��i����@c@�4 6������^�����:�������@%m�(
�
4�Jb����������~pW[�<��������4@i@l�1 @w��d��T���`�)[�<��������4@i@l��rBZZ���C��
k���������;88��Bo�����GM�8155���|������f�4�~i?�b@��Jb�i����@c����2q�j�Z�re@@����?�����������C�9Bo�7���C���k��MK^��q;���?��,���8��i����@c@�4 6�����t�7�R�
:�066�n��5k�,����dcbb��c����6i�������t���;�[���L��i����@c@�4 6���qqq!���Y3A��������$��{w�<~�xA�_|A�6l(��\��7���7.�(	hs�4@i@l�1 
Ph��|��Wd����+(�|�2�W�^=33��O�����U��>>>�]�����o������=��yp0���o�$��������4@i@l�1����^%�'Nv)
n���G����������:u��+##������4��%|%m�(
�
4�Jb���+W�p~-$$�z��o�I�,XP����?����_�B������_�z��������%|%m�(
�
4�Jb������s~�����{�4iB�F�Q��6��5j��zWrr2��,�!��E�9@�4 6��(
�
4f[�l���5�Lf��y����O�>����=Uk����.�\�}���k	����`% 
hs�4@i@l�1 
Ph����5k��~0##��~0mJ]�,zyY	�P*��i����@c@�4 6��m)����~�|O����RRB���r������%%4��)�yJ����7q����>o�4<�y����T^�Z��y���Si�G@\\\��5o�\P���H�=z���=LMMv���*O�0AP���_R��
^�1x~t:]�����=z�/����W�^��5���-+�����[�Z�j^^^��T�*��S'66�/���������W(���n������8��a����9rDPs����|��c�
vQez�G}Do�Y�j} },}�T�@�IMM�8q"��5j�����Wpp�u����&M�4h������������!�Q���������t�������'�k��Y�f��
P��Ox<<<~���7�x�N�:������^�����k����/�j�����\�R���7��W^�q����I�"��{�*U���Q��:�(�?�:uj��M_�uO�F�:u��z�j�Vk]2e $$�:�����W�����>sttLLL|Z}�<j�����g�0aB�5�������������q��Ho�:�)�tHj,��������{������W���8�:���/��/���*���g���S�C�6K��\�vm��������+V�(�-�
�[~��gooo�Q�F��-Z�T*�j������N�
�Z`` U�~�����O�F���^6l�X��?�?^%�b� d����;��o��f��=AAA>>>c����FjT��@ iU�Z�40g��7��9��_?RE�$���x&[�n��_���T�������j���r����������G$777���1}��#���HZ-[����IAM2��+R)i���������L&T[�v-����9/�\A�?�N��@'O����g�
������?��s�N��7�
hY����
)6�^���������,��L&*y������_���������{�^�z��A��
__�j��u���`0X��?��Bf�$$$��Y���m�6�r�6j��h4Z�Cf�x�]j���y��5k��x?H*j��1�9r�_[�n]�%YEA}N��G�������?TH������_R�����%9>�3}�t���i%GY�(�������������}������4h�������d�����+w����fM�T�%M�6�:�9�����*��>���__�h��� d��^����Oj����4<Zo��U�V�%�(����M2����@�>jPP_��g���A����]\\�IEP��A�����044��S�j�����'NPeR&�"==�J���k�I�J�x,���O�������C���S�X�4���?������STX�zu�F#����?�.�4���g���e)DGGs/��y������{���B~(����R��i���;w>�Bf�lpy��:u*Ie���i����o����<55���$-�2��N+���L?����;w��������233����'S�O?�$�L6�:_������DDD���m��uHc���������\�t�z�P�2d]��~��e!�s��_X��������%\J��
y�K%iii�W���k�L����H?��u4��A���>}���_�xqI*Cf�lp4��_������!3P*����(q��	�.�B���\+�q��*�[�+�/JJJ���~�-_A.�S�g�}�����������&�*7��K���_~��
;w�l]�K������5`��;�)))��Uk�����������3������W�^������(t�I�q�F��]�~�m�������_?���!3P6���S�j~��9s��teY��RQ��r�
g�BBB�������k���K�^O
 ��Y���2�����_�K>����5k�����S��C�r/�.]*0��JOrr�k���������Y������l,9x� �L�+6��s��2z�������;t�@{w�����^�������
��<P�U�jU'''�e1~2e@��Q����R�5r���/���S�N2#��x,�Cf��P�\�^=:�ggg?y�d��U$��~�M0Q2��x?���B<~��zo�&M���#��LLL�*�����2U�]��d��M\�I�#~���$�{�������S�N�v�^�/T���&M�SgD�c���~u�\���������|�W����S����Y�����������_���o���B8�~��P7�����������(�W)�<��.
��P��d����{{{^r����=;##CP
2��x?�e�N����-�.����222��|��Q���������,\�ti��u�w}��G�����;w�L����s�n��j��_�vm2��=z��(�\�~�j��_����������A���7%�J���x#���L��TC_��Y�Z�jQ+G-})upO{/��,_���W^����K��!3�4bbb8m��V(���������%�(3�z��7�����{n�����)S�������[���@�x?��,��f�
�`n�������Y���E5����}&I���?>y������~��
y0�
M\\�_���?SSS���*��i������6n�hy3?::�^~��7��;@9�N+E/c���,|Q��O2{� Ip�<���� �j��!_�����]u��<����cT��k�������(6�-�FC�&�� ���'�����}{��k�*�z�U������Y�TS���������1�{iggG/����W�����X,�*$�w�y����`����`�^9�(�������7�vU�V�/��@�����N�����rg�RT�(6\O�H���K�����o��X�^���z�:�����M�6-��s���7n���
^���S�L�Rx�lk����o����g�.�\�����#���y����/�K�R2��� 3P6>��c:��������A�����nY~b��-�{���G�����%�(e~��R�����>o����.��8���j����{w�eZZ��b_���u�����?���M�4���������t111��%��u��r��->m`��%T�rz���~J%���|I�.]��U2����39-�%��q�!3P6���:9
2e�������{9?�?!"2���������R ��<�"i��5y����ejj*���/�����o�P9 3��'�4h� ::��<((����w��%�����{U��AC�<�B����eeqqq�k�����,�R_,������"��e�����(.\��7����RG�������e��0_2���~������^��Qy�=,CCCIcU�V����I�)���,�������X��/��E�y��D�VWA�(��'O���_��K��YnQ~���kw��r��[�x����|u��j�$�rS���{�!�n���@E�?������uk:�����,��x��7-�!3P�N�Z����T)�l�����L?H�q��U
�ON�f���7
8��	�nI�� #)�i��T*����>�L��[�s��Pp��<r���6mZ�~#��A�<�|R�Z�:VPOd�	*o�����g�����C/[�h�Op�����U
�+��[:��7�<s�LDDD��m�tv�F�P����;C��{(�	��2 �������������Da�}zi]2�E���i��4���o�Y�����$2��x��y�������v��r^�k�������[W��������]������4l��z�����+��Hi���F�"������M*��M�����H2�dZ�����?��#<o�J���b(2����������S���y��+W
n"Y"X�X@jj��A��z��5j|��w>>>/��ru"E������(���K�~��u���U������I�&%%%=�>dJ��d:x������d�j������������O{d��{T�5C�)�>i`���$���W�^��>��Ii�Iu�=R �������	#U����K_��o��G�1$�����R����b�
endstream
endobj
8 0 obj
<</Type /XObject
/Subtype /Image
/Width 1200
/Height 742
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 68598>> stream
x���������K��x���\A�`�YP����&*�s��B�%1��&�P#���(((M�z��{�C= ��������y^�=���g�y���|?���)�<{��g=�3�gjk@��:uj[��s�&�_��={���21��:��8q��c���&�_
Wzz�>���~����y.���RXX��cG� @�q��a=�[�x��mUWWW����>����ynn.y0X��9r$y0�����A����<�����ZyPs^�"����&&����]j���=�`L����������w�����_?� @�A�	y��`}��W��;t�����<p�#��<hy0Y��Y����Gee%y�� ��<hy0)����C��_~�em��}���I([�~���%�m�����(�u���:$������,Y�a������7�H��n��y����iY}��������V�<����z��y���� �+�����n��m������Kc��F�l�"{r����Y
$���c��U����/�B�����	�)Bv�4({u���;w�t_yP�{������.Z�h��5r4���i���H���w�, �I5�wDvi%m��A������A>�����Y�;>��c��v��
2$'''B�2b�Q�W_}���o{~��$�pC_	J�kyI`�m!##���>�]��7�����l����w]o�)�����q�~~����iodX+�F��6"�����7�|��3%�Z����pGd������T|������|����w�c��
6���{���p��p��W�^�U$���#G�|������B�<�}��p{CH�x�#Gj��	����./�g��I��Y����p�������w�>}��g��[&qU�J�w-y��pyP��\��2�����3���x�����/k;v;v���K���5k��A:Id����H,//w����O?�9s�lz���2�W��)o����m��[w�������;��@�=���(�Z//�y�iY���r���#4"�H=bQw^�����[75E��@����7�����J�yP��dp5W:0e�u�Y��
5]j�7���QR�z]syp�����$1V�|��5Jb�k��C�����z��-Z������s�M�6y�nSnn�
��5�����8SVg��ez�5c�����#G�8�\�d�v���������#�2�'O�^�������?�W	e����}�t�d�\�QSS��,�[����#jY%--M��j�*o��yP����w��<}���{�Jd�*;�S�Nz�wv��q���Z�n�knff���2P���T[w]L_��9g����R=Wz�._��7O��hT5�/����W�#RUU�ZX��^LB�k�>���dI%�Gv��	�Jp�������(uu����0��d����kea�wrpw��-�Q�Mo(�<�>�4��Z"�I����V����QRR2t�P5W�����H�ty�:&����cG���V���~�6 �~���}M���YL��R)y�	G�����c����z��]����{�Qyp��A��%q�K�.�������z�.v�����5�[����2~�\��
)9N��(�0����]*��w����u���4��*�f��5r�H���~?(Q��!C��.#�y�J��7�(�3._��;Kv]�����X�N
����I�qvFx���nG�k�b�����]/V�t�u��Q�7F����n�Jj�w�}W`PD��Z�[�n�z�c��Lr�������������8��$�������E����9S����N�.��={�[&�<�{�n���a�",�/;��������)�|��t���kO���{���k�\	��)))q�Pj�y2�g�s��,5glQ����]L���:�������K�?��/&h�w!��?R3�e6o������#G�7����M�!Brt������S�0���8>������]��Mj�3����~d �������x9��|��Od������{*KLyP=�P������I`�y�}����sw���{X�`�^`��%:s��1��$,�\}�H�?B;������������N�M�����I�����3�m�������M��9R*G��Km���1���>�mG��������pyP����W����8p@o:��TM��O2����8>�>
R�b�������S>`Q@�g��z*N�����<`�3��^��d��|>afff�s>f$�cB���2��wK�k����un��u�����)p����:/������O�@�6�X�����$e��|.��s5��za;yP��{���$�W7�fgg��9%�x���c�{+�s7Fx������oHw���^.����_�>����������3���-[ya��za�Cx�� ���*iii�>))�,Y�z(��;�<`�3�{}M?�#�0����K�.:th�n�:t�����k�.�����;�"�<*�<8y��p�<xP/����|��Q��O�t�c9z�,�����������-��u]�S���6mZ��}����u�Pz�9w����<e���z����{p���[]�yp���jJ�_����Wo:��[��c�F��8>��b��s)����cHVV�����4| �����?�r�OAs��q�������o�=�K���V������>�%z�<!U=zT/�p�B�\����l��U��b���?Wnnn4=��M��F]���GD�w��!��+����zo�����z��I0��^�u��p������
��NeJ4/��P���o!�� ���}��G�	���W�d�����c�pO�!���T�'���5J/���&�:gZ���$H8q�D���1)��A����7.���>z_���������8S�������A'��������!��"�_��_�����:���
i��@�n�}�����{��.��Q����K����zK=EG�(��.RE��WD���t�d����/1l[�[��'z�S������7n�� �91�A��5]�/�oF���O�q�����_t><D�����8/��~���������?�\/��U��d���k7����T�'X&���999�W+��6'g�MG_�?����(��'O��_G��^p�{)���E����'�W� ���2d�^�u�����D��.�<���3��!�<����������/x����r����m���~R�����Nq>Fu��1j����#F���n��~����d����b���:��M���b�U�W�yP��)�p��)�`8c����A��X ��qF	�Z6:��Y�sW"$VVV�w��/��l������]�F^8)������P��P�V�������u�&�Z�G����l����k7�[O��h��0a�w�@�u>�S����'��I���d������59[�n����n��7����s-f4������y\2�kn�O@1�o�����;Q�_����f��8_��x�!���oB�W7�yg�kO��Q�������q^s�o������Mh��a�T���ZL��^,##c��]�:t�p���QvN�n���������U�5�n���;F��e��e����c�����>Hr��Y�zu ��������0^q]�r&�O>�$B#�Ecm������m�����~q�{����Tt�����H'��������5���>��l��)B#����KZ�����r�T��
����F�7n\�����nt��^��wy���J1|�p��OX���W�[��O��?�G���{�m��EX����D��M�As�y��7����
���1�+������q��cr�y)'\t�n�5:����������{��+�:�o�*�����(;w�����������A�������j�����`uuu�N����H�|�M���n��}��;�����s7v��%�[���Y�?~��h(������u��^7?`��L�G6I��b��2����/��wi�y}_6M�6��q�A����l��-z��]�zc����S�N�����H���d�pM�=ZMw�4OO�w��mS:�^| �������`��Qn��I���H�.l���Z����WSS�����0*��,��})C|&N��<�����+�b	���������Lqq���}3�������I)�C�y���m����%+e�~h)����>���Rc�:�7o�jS6��^�!�����rU�~�$��$�,Y�D?=C����K�b��Y�qozzz�����dddT��F��={�e>��3=QF�:t��2����P��j�w�y�{����@?�c����Y��T��4J�ruL/���o���j�7AK��M�<��v����s��u<\������^��K��]�P����5�{z�!C��n1����~�z��$�;7n\4�;w��m��Fsss�q����&�O�
I����z���z��#G��$���������]����{���|�~y�"!GS�!,�,�R�]T��/�w�m�����/9��wJ���R��%V:��WD�z��~���le$)�m�3dd��6��k�:�^��%�L�0!--M=��{����:�����70`���t����[��������U����d[��L�a������/�x��#D~���{d�����
iJ�H�f���L1�o�����vP� �{����G}���;���EM���)�{"\������^��P�G�D��	Gz7JM�2e��%2q�����~����8�}��	)~���J�����!�^���;v�P�h�����(H=HM~�����#������A�4���v������FI�'��5�����p�o������S�S��}���ms>�^����$srr"�v��}=�I�����r��&4o���m��]���#�{.\222����;n�^�^�4�k�n&t�'�����7O��@����M�Q�������r���n�$V�f%zGXL�)�K�.1��Q��3�;I]�`A�_�T���D;m�4��I����
w�h"y���Z��#G�|��w��.Q��7��"��������%A,\�p��E����O;'//o��
���y�V�\�k����;����0u����
����o��\M��y��e����6m�T����>K4��,�W�������c}iZii�|�%K�H#����X_v�n.m[w�6�S���;vH9IQ�a����&����I��(_.�,R���"<�)��fffn��E�8���GFFF
�`����8�=zT_����

y��WUU�&���������_�~�gb��p�� ��������2t�P� ����s��Y�l���{��Qc}�	R��]�"<@C�_`�K�gp�!������0s��d��}���������F�����������2�G�u��Y�fE�nJ��D������G�t�����^%%%�u������pm�����[����p�6o�,0y��������W��U�V%�/F�2����"��
kL�C�='�����c�������O�5N���l�����YYY���;v,�}		�+s�3fL�y05e4"�\����7�a��	�Z���P�MH�<(��$�'!��kS�PF)\�U����.�<x
u����)�<_<���i�<x
u��`����A�<N!������>|���G�1w�����������KX?~���� ��4iRzzzyy�k�M�6Ex���V����80{�l�s�-�G���k����J��2q���'N��e�a����1c������u8VS�Nu6���-����7����R����{+D>�|(�h��;w������eY}��u�F�4h���Ce/��p+++[�r�^XZ��womyp��=z�2D���������{k��MKK�-�vW�^��:q���T�2Kt�������o">E������#G������P#���� ���+��(�O�.�+�h��i�}��o��]�8r�d�l]u������pH-�O*^�|������%U:y�d���bN�0A��������������Zr�e��
�?����m����h�����Y^�|��;-�>O�����'%���|!#C��0O���-�Q�L�Dnp+�05
�!�$,��x�����)�o�(:33S�_�x�ZE���x2�6�%K��\J������e��e��Vq-���#B�%S��}�,D����8H�$���T"�z�d���:��_�W>�L���u���K���(k�b��e6�G����&���7&��Q+���e)I�����yP�����U�d�Q�H"S�5��5|�'���������%����zP�"i��������}�����
��Tk���_�*����d$D�����!����=��L��H��Q��(���%w�=�k������7�[B|��~��4�n�:��I������o�oO�g����e-Yw��q�)����uT��������9s�G8����4(����AM��T�*�m��I����Z�pa���EX����S�t@�t^����H
��������R=}���2�	��|�t����P$G�!�w�S�����)��qlaa�s��C��I��e����2&tN��<j�(F�]��p����A��4���{�jY���#$����������k��[et�?���u�r�d������0!aYei����:����8zz~~�dj��yP�T9B��3J�~���ZE.��I�R�&�X'���t	k��UWRd}a������&J�R��%�c���u�HJN%;�+�$����R-��L��g�m����M��6$GM������+S�W����TI�~p�1A}��_�������);���
�?���p��������(����an��p��nP>�nP:&��p
8p������L%��V��X�B�����z���N�R�������HrWGg��)��H5��!�w((�r=zw������?I#j��fE�cjS]��{����+�h�����z��}���:,�R}�k�������HVw�Z)�{g�A�wu��:d��2u��\�t���jVEE�s�JC��sm���j�7�[j������=4�{iii�p��@��r]
���Vq��@�>�^�Z�#��������o������vH.v����2qS��[cR�j�W����]�&U��&���������J����fI��be�o���9��� �C�j�u�V��o�R���9{�lok��]���3GM_�`�w�"�A	��?I����R��_�HDNNN��kQQQ��2��>��og�7^�������;R�������'��}����L�e7y��X;���[�~��2�t,re�����=������������,K�Y�������;4����U|�,�{aT����t���KR���M+���k��7�%l��:,�5��b���Y�*��L��g�C�:@����C�V���o}���������+����j����Q��u�������7�����A������mM_�[�f�s��35}��i�6�p=��������������;���5��<����������{L�����]�v�%/���#��d������	?*q8�9����7n����&L�����X��K%�H�zo���.h:[�^���o�7p�hn��*���N"�����P�[���{�$�~�(�Pu�K��<�RjI�Z)�U�@��fI�������W&&�3z/���R=���(��{�]***$���RW����\Fqb�sG����X��%��(�[8r�����+��{�e_I1�1"�'���<U9v�OI����i[�R����vG5���?~\���)(.���j��W������_w���SF��+ ��z9
g�}:effF^r���2�U�x��>�$B�:#:tHOT���_��
��_���`�k�m�"|���R�A��5���n����f(���?���Q��E�����W&>��@�z�
������c�H�c�������Zqb�:�P�>�Ck���9�iii���{����r�=�6�����S�=,Q��$�5k�l��}�w���8�`m��]��6m��o�]����`�?���F��m��<�555�g�V�M�81==]�����M�<�mY��7#�k�K�,�����E�]���#j�}���r�����%�e��-����"QsG��0t���+�p�Q��
6�f���r\�/���J*���_1��W���������`�
�� �������z|�����F��)� ���'T�����DH�{k��M���TR��%w��w�2������}���<��%�
]���	w}�N<~��z�����#��A�}�$��`�yP���9V"���-���^Lb��#�T1(��A�sE�=���g�xo9S|���s�N�*�������������t5Q��������U��-�J�yP?���
���-����ruW�o��TDr�t4���2�*�����W'�<����������q�P#����(��6`����������G����=�n��U���hs��][�l�.\ZZ���/n�����M�a�$�X�/�h����M���x��x�M��E-�A��L�����feee����/n�.[�^�����IDPyP����W�<W�_�p���d?��b��<�^�!��Y�F����������u�^]�oT�}��M^���R���(KM��1��zo����o��!�����8�����!��z���m��x�|/����t�+�}����� �<�_��}����H\�j������N����t�W�|�h�2�W��'�T�1>�Yfq|eT�GS��ky�t����<X���;}�?XVV&;����r��2�y���J]�5j��� �9b��7K��>�[o��������:��v233��Xd��|2����n����*�)�z����]��<��/QBM��sg���G�*�y_t���8/5�����_����u�V����>z�E����:�M�:�����|�A�����Ji���g���yP��j(.�:�h�}��<�U�I�N���=z�h��7:�`��U��D,	H]�u�8�2�
����?�+���-�L�(��%��z�8��������f��kO�]�t���t[���iV��>��b�������]�����"�6m���u�d��1x�`	Y2RR�,���%��8���[�����hG6���[�f��%�����!C���q�������.��b��d��3e���kS���u/&[�v���7��N�����I<QA�.)R��e�S�F������v�� �X�PP��!�Zk���j�zc��U:�x�b�!2����e���u����e��������=������#e1le�M�>]v��3dCE�}���������IuS����+�o�.�?^EK����'!Q�[�>����z��Du�ou�$��Y�g$O��V������:���,H��M1�"��8�C�1I��Q��G6��L�w��z��/)	�gT�/W__R������X���AQ�������cJ��Kj��\��W$_� )��F��#��n$���N4:��jGJ�Y|e|
j{��Q�	�yCu[����d7����e��Q��>B�k��6�m����,}�
����B$�922������`^F�jx������2e$,c!��0R����e��GA�=�d���#F�U$n�~-k�����#�$��IIv�]?h�d�&C2�jy�K���G:���
6��>z=Pw�>4F���o���O���Y:�c����B�����o��n4}o���Gd2��L'�Y
@6'cc�-2����W��Ae�-�kU9jE{{���|*������(�`�[]d���Ld��Z����dH�g���PH�q}e�����E��I=����2�=�rdu�R<R��@����oAA�������uYOZ���/����>�z;�P��,��e|
��$�W��|I������/���<���#�\/#'������B���7�����ldz4�pz�`��\�b���n�<y2?��C�.;z�h��g��]�v��;���p��9sf�V�~��_^v�ew�yg�~�*++���$8r��SO=�����C���Kr��=��'����~u��_u�U�����������d�+	F�-�)����z�:u��O?}�u�]r�%M�6���{����]k��I'�1o����z�E�W\q�T��W_��C
<�����pMM�����is���6i��q��7�t�����q���t;v�A��?�`����W������<�@III��f���#%��N��������.qf��a�e�M�v�}���������&�w�>|�����w"������{LrM�.]�,Y���.A���o�eZ�s������_��o����/��1b�������{��������w�!��5k6`���+W�Y��g��5j����'�#4X2v����w���K��o�-[�n����t���Gy��K.����d����N�*���/��s��(Uq�-���6m�$�o6���]q�w�uW�^�����/��R�5��G����@��_����l���9���c��j�n���/���+�����C���|����.��c������_/��3f8������������M3g����{������f|�����?��c��}�����_~yMMMR:f����/I���R��yp��q�@����f���z�j�M�;w��s���>+;�U�V����~�m������~�iS����9sdv�%�x �������{/)�L�oUU����%�o���k��)ST,*..NJ�,���R�M���;e���7������������K/9'�)e�����_{�5Y��o��;��o�^�`w�u�wV���eV�-��*�lT��g�}�5��/�T?*LJ����<�{�n���q���j�}K}999�~����G�|�6md����w���Z
Jj�eU'�ONa<���j�J�`�����T
���K��3��������I2�`�������3f����+�����|�A���'��	��Y����@��V$z5��<8~�x�{�-���������;�h���W\q�}�
4��hM��n
���;��D����)S��z���]v��a��\Q�����#�>�B�����������M<�O���_�;k��Ij0|����?e=$�e6�1�r��H��Ib�\|q��$�Om���:��kW������
��������M�F�u�����"��;+?�a����3}o�O&�7~���2���nj������=z��u��MSw���(,,L�Q)8R������?O�#z��'�|R�'��$s�EI��Jp�Kn���ke���x��3g�q������� *I��b�����{��7k�l��16/u�ByP��E\}�����zzii�z���'��L<q�����W�X����_��M�4�����Y��������S�;p�I�<��$���<XQQ��k��/��E�c��]�n�����CGo���;��0�P|��W��W*�~wy���.:|�p���_��A�����n�Iv��y��k�J��{��eeev���������$7�ts�]w�n
U/�l��Y���������S,X��5���cj�$��Q����������K.��n�C�]{��r"r�j��HnL�����$���{���2}�t����<5k���}�HN�<���������i�������w���_�������������o����x��(�y0��&�t��s[�� *I��'NTC�]�vy�������k�S(�����7�f�<����&����j����O��}�s�;v�-��p�
���v�����A�>z�/wZ�l�s[��'*��}.����}��;�����3g�t�:~���5i���Q���A)�[o�u��M>�*(P;a����Y�d-	��g�����.��$[�T����?�/I�����3���u�]����������}�H��(��?���$��$���u�+W4M������7v�-[�����}6�����������{Ro<��o����^z��6~W�Y�������86.���������5k����������_�w�^����tk�(�G��>ED����L5�|}R�w�}�'s��Wfee%�oIM\�zu�F����
�/�JKK[�ha��zr�<x�5�8��Q[����n�Mf=��C����o������{%�<�;v�aX��-.\(�������<�@III��f��5k����[��?��s�����dw������H�7n����g����7q�����7/��D�:��z�Ryp��Yj���*���o=z��M�f����?�A�z���*++����={��{	~��_���W�������n��V�x�w8P\\\����N��*�y4i��<�2��<�����2$�8��_4�����z�i�=�������?�����/y�E]q���7���S�z��~��W��	n����_���k%�\}��O<�������$��>��S7�p���^*;�Y�f�>���#��O�]���e�AH�����C�>���_|�Yg�u���7m��]�v��]��?����;v��*����>���^x��g7i��u������������k��b���"+n��!�����}��~�3�r�_����W�Z5w����{N�\p������"y��s�9�������3Fbf���G�)������s���&���������{wYXV�e�pI�WL[��i��%�n�����J���_]�K�;~��k����|eddHx�8�w�^=q�����UW]U^^�\X���+��Y���}������H�i.�-@�����%�����3�8Cfu���5+�<��eKi��W^qM����dz��}����#�6m�Z���^���Z�
|��`������_�����j����g�y�5=�<���w��gJ#���w�z��we�o~���n�A&���;��.\(��:�����`������$@���������	&����fM�6M����USrrr����'�.,,T���nL[x����}����F���%y�}���=����_~��������w���W_�~�(:w���K�m��M*�-Y�DMY�x������]�'?������K�n��E����c%:]t�E�Y��8��^x��o�Y�n��������K����]����y�.������GU:KKKSS$x�)��.�UW�,�h�n��E�KMM�M7�$�i����������3������oe�����9������\s�����<�������_M��1c�f�d���?��1m���{w�GtF�j�*���/_�'FHg���1���M�&��[��Z
X���t2s��3�8�������i�.�@�V���S�~�i��1���(��ic�����{��w�]VV���\s�����~ZO�y2Za�^5'��<E�0O2��J�i����`5&���������JKK�X����v��o�>}z���(**J�}�-�t�����f��.R��A��4jvPi0��������?�y��%%%z���8{���>��C��������S"��S�N���}��-���T"�����5�o�R���%4p
��k�4�F��*
�5�[�t����o���������9����o������+W��o��sz��-e�����Z������}��uN����Ll���k�6m���V�Z��K<���tM�i�����T��I�4RVC>��&*
�Qc��J�i
��T�������]�|�����:'��M�h���BFF�9��s�y����OO�8q�,|��W���vd��7n��x�����G��4�\8==]�}��g��1#�-Z�������%e�HY
����4�F��*
�5���q��-�J*C��u�Y�<��������o���/L�:U���7���L��������3f����q����z����|�����{��n�����L�Y�@�=daY�I�&��4�Z�g���������D�hGf���r_�D�0�9��J�i����`Z�����/"W����5k��/���iS	�?��~����h�b��A�������#�H";���%��n��{��&�dYL�Ud�
6x��o�UW]��Q#���M�).�<��'���h��9�Qi0��TL��`H����3��9�Aj��;�4�F��*
�Qc0�r�����7V�d'�/H!�s`���1�A��4j��/[����d�)�s���`5;�4�F�����U,�7+�}A
��;�4�F��*
�Qc0�x�W*�$�/H!�s`���1�A��4j���������%�/H!�s`���1�A��4j���^������� �p��TL��`���1���e���| �}A
��;�4�F��*
�Qc0$���U�����9��J�i����`5C�[���`�����R��A��4jvPi0��!:�?�����
�9��J�i����`5jN8�`�����R��A��4jvPi0��	U�9�`��~��R��A��4jvPi0��	��;�`A�w��#�
�9��J�i����`5��w���W���!Up��TL��`���1�P2e�3f?r�{�T�9vPi0��TL��`B����<�+�q��TL��`���1�P���+V���N!%p��TL��`���1�P��-W,_�"��BJ��;�4�F��*
�Qc0!���<X:u|�;���9vPi0��TL��`B������E>Kv��8��*
�Qc��J�i�L�z�NW,��V�;���9vPi0��TL��`�+�?�/?��N!%p��TL��`���1�&/����3��BJ��;�4�F��*
�Qc\����<��W��%�kH>�9��J�i����`5��UlX�����Jv��|�s`���1�A��4j�+[��o,_�8�]C�q��TL��`���1�d�h�<X2!-�]C�q��TL��`���1�hp�P���������!�8��*
�Qc��J�i�w��:��~^�w�;�Hv��|�s`���1�A��4j�+��.tM�_��+�<�]C�q��TL��`���1.����X�hn���{nNv��|�s`���1�A��4j��y���;&������� ?��C�q��TL��`���1.���`~^�s������-��C�q��TL��`���1���	�����8oMv��d�s`���1�A��4j������/���eJa��zJ����� ��s���`5;�4�F�!X�;w�����#2�d����F{wKv�d�s`���1�A��4j�*_�2����_����B� |��dwI�9vPi0��TL�����3u�+��O�R��q������ ��s���`5;�4�F�!X'������T^�z�2�9��J�i����`5�`
�zz��Ajb��i�'Vgg%��H.�9��J�i����`5�`���EG�������
��p������9vPi0��TL��,����.P:�z���I� ��s���`5;�4�F�!X����~�����~�B7���2�=Drq��TL��`���1+��t��:�_M,�<VO<��Kr{����;�4�F��*
�QcV��������PM,_���RB4X�s`���1�A��4j��}�D���zb�$�{H:�9��J�i����`5�U?�}�/4�W�;�s`���1�A��4j���U����p��nuO����$��H:�9��J�i����`5���\�C_�w�����C�M��.�9��J�i����`5�����C_���
�ozO��)��!��s���`5;�4�F�!@�����W�EO���/?����KV�t�s`���1�A��4j:���iC��JgL
w�
��A��4jvPi0�C�Nt{7tS����Y�W�^A��s��!��s���`5;�4�F�!@�o��C_����Y�G���
��A��4jvPi0�C�r_|J����-������s`���1�A��4j�~����9����zn���I�!��s���`5;�4�F�!@�+�5�%��ym^�M�zyRz����;�4�F��*
�QcJMqQ�;BO|�I�-�2�~�
8��*
�Qc��J�i��Ru�P��1����@��A�W��~�
8��*
�Qc��J�i��R�u��{�/?�]�l���+;�i��H	�s`���1�A��4jA)_�H�����.P�9=r`DC�9vPi0��TL�����t�;�Q'����z��[��!R��A��4jvPi0�CP�G����'=p���r�
8��*
�Qc��J�i��R��G���cF�.�����W��i��H�s`���1�A��4jA)x���z��L�]&����^A�l��"p��TL��`���1%�����u�'zv
]C�f��H�s`���1�A��4jA�}�q��*���]�x�P�La��{�T�9vPi0��TL����V���W�y�w���sB������"p��TL��`���1��g��Q�}�^&�/���R��A��4jvPi0�C jN��-����],?/���f�"8��*
�Qc��J�i�Qu`_���SFXRb�^�� �Z�"8��*
�Qc��J�i�Q�i�Ny��s�%s��h��3��Z�!R��A��4jvPi0�C ��=(��DX2�}�d��9�z��9vPi0��TLk�5V\\<t��|���/>����?���M��k������V���������^{�y������w�1q���HOO��G/�����>�I�&�[�����pVV�k��&�������a��X?TL[V��q:����~�%���K�f�{H
����4�F��*
�5���}��~���}�{�_����W�Z5w����{N�\p������"����o�^x���K���5���o������1c�H�l�����#�}	���{�$5��od�����������(��;6��W<l�NyE_~a���i�W���B��R�9�Qi0��TLk�5�d��r7�pCee�s����.���?�~}���>+�^~�e=��������L2d�k����s�9G����{�������W]u���\X���+��Y���}������H�i.�-�P��G:��LH��d��E�;K�|�t��j�9�Qi0��TLk�5����%�����3�8Cfu���9}��M�������r����e�F��W��-e�+����u�]'��������O���iS������Lo��U4�(�-�P���������d��oCO"}�a�C�i���G��4jvPi0�a����{_����l����K�z��g������������%�}��2k��zb^^��g�)����Z��w������o�o�����;��^�p�L?������y)C�[4!���:�U�[i���h�\��U�<��>*
�Qc��J�i���e�]��/T4m�4�OU�{��W��	&|�NAA�k�i���Y���jJNN��2y�d�����jV�����ECr����xU{vF^8��z��lKO�A���;�4�F��*
�QcNeee�z���#�������:K&������C=$��7o��t��Y=�����M�T:[�d���x�b5%==���O~����K����i��d=tg(���\xu�}������>�1�9��J�i����`5�4v�X�N]tQEE��x��a�F��]��^P�l�S��y�r���{>z��j*-��?qE���r��!����z�i�n��ECb��������i�cH5�s`���1�A��4jL�������$:M�:�9}��*R�7������*�~����)�=��L���k�����������_M��1c�f�d���?��1m����\���lQ��E>
��p� sC
��;�4�F��*
�QcZ���}�9�������������b"y��E���=2�O�?������\���8��*
�Qc��J�i��2s��3�8������v��~�zUlX��]^����|�������h�cHA�s`���1�A��4j������{��w�]VV�����'�6v���������w��3������'�-0$��pz�Dv�y��u�]���������o��{Q�ob�����?Dx�DQQ�����&�[�W����:��~��hVq>&�-0$��p�0x���7o����DO�Tu���bA���S�N���}��-���T"����b���=fhT?T������S=l�{H)
�$�d��`5;�4���kl���o��vg��O�S��M�6}�����~��y����L�"i�Q�F��[�l��h�\��2�o����}������5s-��M������,]��u��;���w%��F�J�+��^A�a���!�4�sl��`5;�4��`kL���n�����5�����>+��o���RQQ�.�
2��pFF�9��s�y����OO�8q�,|��W�����Lt=����?����i��pzz�t��3�t^��u��+��.�>�Es�Z��z���{eqk��XF��4jvPi0�a����%mIVR�������A��7�|����K/-[�l�����7��B1f�i�q��_�����?���s�=��/��}�wa�(�d�=z���J�&Mdui��d��=����4�-+����.�m\�*�[L����t�:�9�Qi0��TLk�56x���E����u����Y3�Y\p����>a��[IOO��G$��}����Z�n���S�Y��,&�*���
���������j����Q�i��y�a�����f����*t0�C���y��}TL��`���1$.��;t��)���7��������"up��TL��`���1$����(W�>zX������CJ��;�4�F��*
�QcHPuvV(���!���"����)�s���`5;�4�F�!A��v�X���G�_1��B�:<���pZ��;�4�F��*
�QcHP���:������W�{�%�b����z���9vPi0��TL������3CO
}���W<��K�o��i�s���`5;�4�F�!A%������O��W,>(�
�����)�s���`5;�4�F�!AE���XW<���W<��b�7��)�s���`5;�4�F�!A��>K�M�~��-C� |�is=DJ��;�4�F��*
�QcHP~�6���,]���Ud=��X�Z8��*
�Qc��J�i����?�XW�ecL��
��s���`5;�4�F�!A�O:^#x�@L��<�R�[��[C=DJ��;�4�F��*
�QcHP���3]MQQL������^���z���9vPi0��TL��������Qa�C� ����!�p��TL��`���1$���Q���?���G
����8uq��TL��`���1$�r���;#^x2��������oc��H5�s`���1�A��4j�(_�,���{��;�d�_5�C��9��J�i����`5�D����]A�wb]�� ?���{n6�C��9��J�i����`5�D�����hAb`����y����s���`5;�4�F�!E�{�4W<jh-�>�x�����C��9��J�i����`5�D����Ns�3���B~��ue��C��9��J�i����`5�D��B�K�h��o��0���9vPi0��TL�������N�n��	i��=��C��9��J�i����`5�Dd?�{����������ycN9�s`���1�A��4j��-������q�P�gW���<x�j8��*
�Qc��J�i��VSR|R�OyY����9vPi0��TL����#�t��~�����z���M�Y��!R��A��4jvPi0�C�*�n�9.��g�nG���Tl�\��8��*
�Qc��J�i��v��`�~-�v
:�z���)�s���`5;�4�F�!n�3&�^�q���)�Y����C� �9��J�i����`5����s�d���)�:>�+?�`��8��*
�Qc��J�i��V��':���w;�kV�v���`��8��*
�Qc��J�i��V�A�@~�Wup�9���o�=D
��;�4�F��*
�Qc�[^���s\���4�+�9��J�i����`5�����	�*wnO���?����:r(�"q��TL��`���1�-������W�z���A�)�s���`5;�4�F�!n��Y���T��I�t��s���`5;�4�F�!>5'
t����m	�V4�_��_~H��8��*
�Qc��J�i���|(h��%�Z���������C�&�9��J�i����`5��Tl�zi�+�%�Z�:�Z���H��8��*
�Qc��J�i��S�x�Np���M���cGB� lyO =Dj��;�4�F��*
�Qc�O���:������<��4�e�7���9vPi0��TL����a�BO������~���+��M�A�&�9��J�i����`5��~���o%F%�`�?^�
��Z�x�HM�s`���1�A��4j�)����oe�g'����������7���9vPi0��TL����6/��V�~u�
��J7X��W�
"5q��TL��`���1�'����~��gW�
���z���o�����s�mY������d�%�q��TL��`���1�'���t|��
 Un�z�O&��55'
�[�z�����-���N�.�9��J�i����`5����z� T�d���#�6���gk��������V�}k�{�r8��*
�Qc��J�i��P��
>��Yg��)-	�Y�J�N��A�?9jU2fDM^N�{�*8��*
�Qc��J�i��P�ow(����A5��Mb��A5kN������9��#}�����������;�4�F��*
�Qc�CE�Zs�^�kP����j��K��99��l�wT�dW:P������.f=���O��=;������;�4�F��*
�Qc�C��9�g�vz3�f{w��p����5��og�+_��9�|�����G�z���'J����'����9vPi0��TL������C�
��-�f��5���A5kB����pw�������N����?G����c����-�?�8��*
�Qc��J�i��P4���3�C�l��y�_��	����^0����>��_���������G����_������GH"�9��J�i����`5�8���5tc���A5[�mF�15�=T��s�`�r����-_����[����>����]ZSx�\���s���`5;�4�F�!���R�h^P���(%�{n��`�N���o�����HMQ��>�~��#��������t�s`���1�A��4jq�k���-������YM^n�-�_/�p�0�u��V�:�����V��K����h`��C�*��;�4�F��*
�Qc�C�3��R�o�-�����}�[l9�L�r������p�0��.�6���(�-&��A��4jvPi0�C$
�������w���D]�M�-'.�&F�������\��w�}��P����6#J�9�����nS�z�,�7�|������T�L����r��U��Vm9T��x���������%�����T�`x�-t�X�:��!A�s`���1�A��4jqp&�`[.��g��y_	��D�_0������`����q���?����{����t����N�_n�u���y�t����+}�ow���1��(jQ��`����(*�
(�80)
�( 
 �� �X�xj����O����9���g���]�<��z�~j�g?���-0|�mH����z-)�Z��������?@i�k�1�)f����6j�wo��:i���~����������:�����Y�b��o����9d���;�����j��q���}����WB�gm����9��4�5��(
p
4<����^b�X��\�}s��Y��y������n�A���m������c{�
��$}���pjFHWh���JB�C�����'�����]��������i%��;��r��G��OMw��5�k��M�HiQR�9�'�4�5��(
p
4<�p��~���h���T_g6'~����
f���b���-�EM"���c�Sg*�6<4��o�(5/6��O�����m:�[�N-9A�9��J�N�������z����)����������a����^���@������������6�E�h``t\�~���@c�St�/���b�J/�]��.9��V`b{��1��U������R�N��BB������������z��R�1����m���|?��>�k����93x�D���}K*���W����������h3���C����������;��~��V`b�?m&����lS?i�f0��\�MO�L�u�h�g����w*����v�����S�SS�c��
c������}���t[rt�2�����Q���S���	��x
�vy	G��I�+���@c��4�5��ur�}�d�!��_��d���-v�)���W��
�����Xum�0��#��j��m����#�L
����E����T�Hii�X�G~�d���T\c����[n�,3������S����m>�[�a�.�wT;3Y;y�f�n
�����
���V���
��n�k�1�P�hx�r�F:��r��~�����_����Y�,0�u��>�[08l������n�W��G*_:G��������w�
K�I*��
W�S-2$�>��
p
4�J\�O����?�_�������Gx��lpZ`b�)�1Z�C]��[� �E&��>.��[T(��jg���1��9�9��3���a����5z��~F7�5��(
p
4<E:k�����J���:�e_��Y�����g�	F0�i�����H�'�e��H�FhN#�#o&��9mr���gH�m���}$�����������TNG��&��_���<���y��na�H=�8�[��S�R���#�k�es]�#]1_w��K���/��h{F�����
&,�F7�5��(
p
4<B��|���t�����#L/�5�����<�{�	q������cwk��R�Y"��<"���>��_��kk�������0��k�T�F7�5��(
p
4<�Unq��8Y�q|�w�4j�=8
�teb#)!1>���#�Y��H���f�Yr�?�������nq�TxI��
��@c��4�5����:)2<�e7Y]�1!�SL��������^p�A�%H0������������^�/���'z�s���u�N�
��
�Tz��h������}3����r�H#�����2.�F����+���{5Ru��4fQ�&��dRX��H�������������M��
Q��F7�5��(
p
4FQ��%K~��_���v��������^HOOw�����1c�����o���|0o�������/����O����-������~���7��V�7��>K����PnYC?���=a��
�^�t�5<X!<�����M.��J���=�nQ)��������Q;�$�<��B���h���&�5VTT��?������|���8#;�I�r����_����OMM---���}���H�V]]��3�H^����}�v���������H�)=���9[F����E�z��4����S���\<�����e�������_B��]� [�b�b�2}YI��O�C:��T�I��� �@c��4�5A�1��4{��_���G��8q"�x�i�����*<�p��������I����������m1)	���


o��6�	�h��'����ktDpa���xN������q��\<�����H���1f�`�s{��x�d����B����	�������cM*��9O*���B`%hG7���(
pM�jL&�����YYY��.\��xp��Q��s��a\��_�B�'&v[�JHH ?��#F���������^b(J:O�����\����1�O:k������������CZ5'�a�Ce�r������t�TV[4j�����y�l�JFR!pN��n�7�1�P������`�J����n<H"��^{�����Y�{�����?�����������W3:_�v�\����r7g�{���pm�I:8>q#�{�{?o����x������dZ���|:z�s[L1;E���CE]��-���}��(~Ze�W��^�9�����
W���$H*^�vt��~���@c������l	�
�������m/���D"�]9{�,��J������=��\��LO���� ���g�� �s�J�(0�ln�-����a�a���Z4G���u������L-/{���C:]��q�T��@�E����h����d�\�r������z����������:d42����������;=oRYYi�����lWn��a�RQQ����~�;���
\�����������w�|�,7�Z�9k���\<�Q`"#r9r����PqO�N�io��l�w�����g����PZ6d;I*��+�_��h����d��������t���{�N�:������]�1c�m���:	{�������8q�v%55�v��K'+)~�!y�<���=��\��=���J&���pS���pK��b���Q`���!!�:��Y��`�s(��?'��]oQaG�'$l$�c'�>����I�4��9Y��	F7�5��(
p
4��.		���t����?��S��!C�8^;v,���?���Md2�-:KJJ�]�����X,����D^���tm�GO�'������5s��i�:�J�n��=s��<�Q`"j��Y��B0�/�m-��}���^����,f}���-�Ti�,�p9�
��n�k�1�P�h��]<����R[�URb/��":�J���}�Q?���O�'7'�������	v�!NJjR�R�����&���C>��t�^�P~G�yu����#]�+���q��gM*��<�0��
�n�k�1�P�h��� ��w�!�]�j}�����u���S�)��K��:t���[�FU�>�A
sfx����Z��?F��9Z��`�����������-*l�����f����+7,Hn��*��]��s���C���x�O�y����+�~��km�i��0eY�mj}����EHb�A/'|��;?������'���On���AO*.^����e�����!����3 ���	��=���x��KU�=�a8��������������������Z�����z=��O����YYk�T7��_��"���~���>�����}fs6���^i�������P�z���_zh��IR�2$"�9�>��?@i�k��N�����l���%�~��+W�W\T�_�n��X���~�:�Nn��z�N���}I����}�
�v-7%}L?��V������:F��,���`�o�����:�-�=�I^���f��\ZoA:Sn�;K*L@Ra`��
p
4�J\�u��CBB>�����o��m[}+.�Va��Q����s������������>}���zxx8�:	;::=zbp����3w
���#��������~���BZ3�^`�Q���9�Y3��sLM/�I�!�����e%�o�O:��Mg�W*������`t\�~���@c���A������z_}��UU��o�������������M:���$od��\$/edd�������[9v���x���_{�����>?����:{N�W���}�� t,	�+b.}z��ZS��Y�AG��ro�	<���1��I&�1�B���\[���}�
�n�k�1�P��`���
�'q���{����y��s��1��/~�����s�������� �����D��7?}����������������������z��w���{v&�K�Cll,�L�������0z����V$g����'�
Q����?�
=^��I����������|��j��N9��V�����#���N�m=#$���`nm����^�
��DR����h���&�5F���9����f�9??���}��o��_��W������W_<x�`�uwYEEEDD���x�
���7��>O��@����-����N�>�����{����GO���
�\�r�z���I	B��#�a�nr��q����_�S�N��U3�g��9����O��
�T_|�k����#7N+&\�+Q��?	��
�4�J\��<-~LO����w����q��B�q���p���Fb���p�>-�?1��y�T��>���,��X(T�n��s~��Xe���������,$�!��@c��4�5�`�����xp|���Yo�����5��$S#<}����`0y�v��BW�����K������P2)�����]^���yR��}��gH*�'0����?@i�k�1����W����i�'��g]�wpP�P��G�>����w���8���K�n$��>G��h������sY<XH����,�pa*�B��B���h�������CO�o�Z�8����%�� �~f/A(��|��[�`0tm��A�����X4��k�����"�����B��E��k#;��
��lu�T���^�I�,�&��@c��4�5�`���i���x�����d+���I���K>y��-�`�4F�	�o\����=�	�����'�Y��Xe���$�04V�Y��B���h�������}f^�&�x������I	B��%�����n������(0�>���@���1T���1�B��#Y����
'����fe��n�k�1�P�h��d�����1)W����nJ�����S������`�Q`B5��@�����(���!�l�L�\���N���8f7�
��n�k�1�P�h��d�z*~;����f�K�9m/:�c�������1�&:B>1�p^���?>G�y�����x�B����zI*����B���h�������Rz^�rA��8�h����������?���1��Q`��x��@����1>�����
���^��-D�[zI*�@R����
p
4�J\���M���R�y�\������^�n�H�}��@�	��>����1BB��)��6/����V��#N�
'���BR���
p
4�J\�����JO�^�G���/=
�k�~	�N��q����
��`0tmk�`��u��s���:B>��w4�3������#�>1�ER�O��
p
4�J\��T�E�s���O��n%�rS�0��1�V�S�3�K(0�x�����$S#���1^��G/v�TA��B���������{j��g��U/��y���,�J��B?���>}}��n���9�L$������sH�	I�hjl��#� U[b�9I*�]�^��B��������{}n�u�*������{
�)A�q���0�l������Q`�?����o�B?��|B]���S�������$�F7�5��(
p
4��mNg�r�����tNJ���%�$uv��j;��u�h��8�9��6���W
�_f�j��,�\{b���B���������K,���Y�����J~w��D)*7�^rb������`s\�c@�����-8�9��=��Pj|V���\�z���IRa�
y��h���,����9v��A������� 4�+��{g�t�y������P`�������8�Adk��T��������������T�-��@c��4�5�`���9=���-}����M�s�B?+,^�� �d_	5&||�E.�/��	��R��s{����	{47�9�tbt��~���@c�%����t�&��'���a��E��F����,���_r<}�,������������<<�)��L���
���wp��	r0����?@i�k�1�����yuI�L�������nJ�����\Q3z�5��g;N���x4�:|�c�qd(#*T�����NI�i�$�pG�N.��7�F7�5��(
p
4XR�y��QM]H_w,A��M���3�G/_q�Ci15���~	�>����W/b������bo60@R!?`t\�~���@c�%�R������k��i%����8)A�7u���2�����S�9����CB��/���x6����
���s��l`t\�~���@c�%��s�+���J�����&���"��w��vu+0�w���!��156H&�1
U	�������q�H*��n�k�1�P�h��~�~z]�"��^�l/A8����ukf�S%Fv+0�&�!}�^����J���^6
c��8Qb��Ra,�
�F7�5��(
p
4Xrw�v���OG��R����-^.�`�o���1������3��}�UQ����4d��j��&H��=�IR!�O�BRa_\i ���?@i�k�1������wf8�D�@z�������E����U�N�A��G|���[��3'0���Y�Iy��G�w��s�T8.Q�����/(
6��(
p
4Xr/�Gz�|�`��K�J��y3�),���{����^|�
��9��;���a����N�!������@��~���@c�%��f������f\z������O�y0�[���;��W|�����}�5#*�f��.+�n9O*����BV���@@�~���@c�%��&����r���.pR�p�Q����)���^���z
�_�9f�X��{FH(_��RSI���<��D	�
��kJ�4�J\��<	�g��E��/��e/A���wJ6��������&r��� ��s4�����2>��.+��
��T�+��4H@c��4�5�`��aC������/9n�\q�;'r�pX�}D�IKy�p�|�W���g}���cBQ���A��zEq�i�$z��*
��(
p
4X�8���$�y������Z��^(A��u���x�<2��^B�����}�E��/��	es���b�M{����a��'J����-|Yi 0��?@i�k�1��r����S��r	��R��;�74V=B�����}���iFH(����-��z�\��,�0d�:
I�������~���@c�
�����o�����X�P�������nMH�����;�{_����1��I��`D����B�e�ER��*$Z����������m���j������OM���+�����8����.���c����u��P=���,�ivJ��&8K*�}D����@�Q�_�1�P�h��T_GO��
��a�){	��;�p����ez�t�;����]-�2�����O�E���Fz����m��:�����h���l������%a�zv����g��o�=��]aq��>x�k����Ss�tF$c�P�}C�^'�iv�ne@�%���B�S�;�1�P�h���j	=��C��J��G	�}W�q����~�|?�9��XFH(�f����n�[�R=������K*�S�?������^���W&/����6�%O�}���m�Il�}c?L>�����"��/�E��>��dm��Z���H*�c������������3���P�P�pZRK�U������
�mn�_��X$�;��P(_���V	m��RCh�����A�T��J~4�J\�6��=F�~��n��A���	�)���������2�s�)�!�xL�����v1!�J��^�
��N
���P�q�1�P�h����=��7w�~�}K�,P��/��S�fiP,a!��s����A��P��"�]N�-�pl����@��J�4�J\�6T��f�7s�gj��a��%7�������L,�s,J�|�,FH([0�,m�n��&�����Q�Y�1�P�h��r��~��l�}�^��0C�������Y��C��mz*#$���P~Gh���Q�<�0�\&����~���@c�
������.9���!S���%���UD�B��@&�|��Y�82��$m�s�n_U���c��TxJ�4�J\�6<�6���/q������rg�g�����w���P�R�  }�E�Q�_�	�3'����6�9�&��\
����T�)�1�P�h��I�z�[x���>7��%�yR���va���~D�*�l������~�/�*�]�R��4�YRa�amR�}�V��1�P�h��iX=�-*�s���~@���u����)���y�d����156H�F0
�q����Yw��%n���U~�T�J�4�J\�6�HOn��:����
�ne&����pM0�U�FHH�D*
mW��u��/��TXd����`Ph���lx9�zf[����^K���
�g/31+[E� �9�������E�CPyg���M���N�
���\y�1a�(
4�J\�68Nk],�Ms(AX��~�O��c�v^~�sN�)��s��m������,Z�>A�^��J�~�T<JB�~���@c�-����>�y�����%��8�0��~$��l���&�|��@#$G�k�m����W�gT���
�Mi��1�P�h����BOe�sQ��1�M��q��e�C�<+Q�� �9��;�����P{���v�A��L��<���?$���@c��4�5�p���)=��A��������/�9)�N]�2?Yt�$8}�E.�-��	�Kf��B���&�e��^�
}{�wp*
�	4�J\��*������.z9� \z�M	B���k3=�W��`�9�)��P6�|����=��T�J��~���@c�-�E�����Y.z:� ������
�������N)��	r�c�y"��
���
m+���%���/&��@c��4�5�pK��|z��7�G=��������������w����U���!�t��X$�i�Q�:�$�Q��[I�P�h���ni>�A�Z������c	B'��f��s��&��c�slhs2:}�m���/������M�
gI��4�S5J\�~���@c�-�I�������;O?�P����.��F�	]P�S}�dRc�P�k��v����
�4�5��(
p
4�Rk/���d���+O�W
��R�0*�3&\B���>�z�r�FH(�ajn�2���gt�T����I�P�h���n�YC�T3�����X��D�����/����f��C8>�'����O�E�!�P�	m[4��=�'
�J\���h5����;\�s�jo�|�bi�8Q���q��q���WI�m��pK�����`���3J��9)A������8
e&����[��3"����:)�����,+N;I*�KS�P��B(
p
4��Ngjx��]�=����S��G��E#�b
N�l���dc�c�?�c���[�f/��N����;��K�x�9�Uh;'�%OM�Y
|����3��Ni���.�xa��_�3*�J�>�%��#�4�5����}Y�6'C} A�~�4z������}n�h��uK��l�L"��~�pK���hos&��������A'�(Ax���z������������6���vyF�}��8'I���:�<m���@c���&��R����(6����*����M�L��O���x3�������|z���j]�@��a����f��>�-fq�l�w��]�b�E��4��;�]v�T8(F}�����B(
p
4��f��2*��:e���U����!�
��x96T�|�jg���1�������-��C��]�t�6#��P'��
�.�f�-u�F�^�B�s��{+Ax���8-Th�4�*�9,�=�������B��-2��tgI�;5�8N*���@cA������>u����e�:��(qd�w�>���$���W,P���M?N�>��*�B�Bi�����$T������cB��7�p��V���>�p�������%�n��8h�z���1���}Zs��Q3 ��a��qe��Ed*"�]#HR!��H����
�������d��%�Gx9��L:#R�j�*a�6=UWTh��v�����w�I����cc�t�T��$2�x���x3����?�HQ��`��<~�� �Vf�������d�`����8.�;�,	m����o�6�I�����$Bi�k�1��,�hHWxQ�����I�d�dR�����It&_�H���<�/�j����������,2)u)W��*Q�7����B�#��MaO
�p����W�>Lt(A�v�U�P�{��c�h����Y'z���;nw�A�I�W�'�vR!���,r�����Z���QU���9�)��x3���4��}�U{vw��y�X��Bym����V��W� ��!���J:���\���GJ;�g��b��+��~�����j]����O�bd�G����g5=�,����v���e���������^sP�h���($���(��W��*_1_2-B��7���_IgNP�]����:�/�az^���<t���(���#�0����-���:f�� �7�1����������m]7����Y�U�0��=B��y�(*�s�E)�/c�����f�-�\'Bi�k�1A����g5��k����X����
��}�������u?���k�O�o���q_ox]i��VmN�|�"67�����u������6����X[M����c������S'���hOJ����j�������y�9r��OuW���������mC��
�4�5��X(-��H,F"2��8��%�����_x3���ki�$�����;�g����M�u>�U�S�*��������_�t#��[82�p������MS�p�zc��w�w+3!Q�T��&�9����$����[���4�
��3��IR��-�C���T������NgzQ�/�I"2�����h��_y3�(�a�b�2u�.k�Wz����x�����,
����2f�x�`��a��W/��d��[�6��p����������]#v�'u���[��dP�Z|�o����1@K&�Y��OZ����N�
G�5�J\�y������-�\��@�b�r��)$R�b�'5����Y����*��i
����J3=���:&[���.���jg�.vR���+�f�5��<�+f�2���Jv�DZy���IA`��E������}�=�.�]}�a�y��$Bi�k���0��4�+������(~Z%�3����q_� �����+�Hti�����"���:}�MUb��PV�4�Q��cm�0���oFQ��%K~��_���v��h4�������o~�������/���]����3f������o|�����������H$�?>�F:���7���{�Y<z"KD����y���,��:�����5�4�9��,IgMa�����,j�������
�e���l7�Ci�k�1s[���.�N��O�e�l�w�1!���F��}�V��������MM/����#J3�;��l���dq���Q��JW��Sh���P����Y��A�F����nQQQ��������9�_�9�����_����OMM---%��[o�E"��j'������_�����o'��[�����=����'����a��}":����8�:{e&@���P���G�	1>����C:��T��.�J\<3w�*�S�r5G(���-�)��f�"�;����=$�0�+5�l�C�>�42�h�$�h������q�����;B[
z�5�&�i������/F�=q�D������I���h��^�����r1%%�������7�$�X}}=}133�t����;�����$��/644�����&,�9����q��ot���,��X`�����[l�)A�s��PY�3G�zHh��E[�I�������	<���"����4����7�G�,{���oL�l���������3�{e��&�?���J��U����Z�c���@�'������s����e�q�L&{��w����/\��u<XYY�����W��U{{����g��7���{��k��Q���9��W�������������>���y����zxx8����=�~�f��|l�	��*yjb��v]D�	`%h}X�2��Y��W�`�Y*��~�[R!�H^��]P����E&1>y��zI�����I��l��0o�}c���}���F�����c(�cjy)���c�Ei�������s:�p/��P�=]Q�E�d"���y�� �Jm��6\�h�����2��0��7� /����I���k��������k��%����8^����F.�^������k�����.���z��=�����xpS�w9� ��f)�L+A�sxCs�c���*6�\��%�0�r�T���}�Yrc�c�����GU;c���ZOa1Wg�E��D)c��S�S��w���B�������R��x��1l�$�;]s� ���V/��1��6����zK�Ess����dee�
�����m/���D"�]9{�,��J������O��)����_���WX�K��V�pq� ����c����=��;����P���W�$�F�3v�Ci�k|Gc��X[�+*����vo��X �!
��kq����3�[�i��.������E�D�����E&!�Ql\���$�������C�%����_k�[���F����N:����|��o�%/}���������+���N�����������v����+=���w�#/m�����=�S�M�AOS�J����aq
�L�W����E���^�j�3'���mr��,]��0,^�[nO*�����1�Fm�{��y]�uB�K����������.[��r�z�����\����6��73V?�O����F��i��������:(����`ss�-�:~�x�W���lg��Wf��A���������v�'^%�������|�dk=���DS��{�DO�I7O�=b�F�a�.�v�s������mo�(�S}�U���n�
�4�5j��L�u�[E�3���X�v�4j�h�����$F�E+�o�;�+�3T��;��["���E�!#�*~�x�p��<@�t�6#��P'��K�i���kjjl!UFFF�W���K^����O����c��?��O=;�d2�����lW���o�";9���D^���tm�GO���Q�]g9���_%�Jp�(���3����'E(wl����6��?0���$�pm&UP�J��o���^���J�9��]������D�~���o����?(c7i�'�._0<�0����=n�^6j����X�f��xL�r����������X��xp��9��A�T�Q<h�[�O<���n���C�UG��U�e���F�����
��x���o�-��U�#B\��4/PRz����R��
7�� �
m V��=:q�f���
+�|�4et�p����}����s����k^�mS��=3O�^��1�N��/��	��Q>�=�i���t��XX��:���Wo��g�U�+��z���f�j�G�9��I�i���#�S���Wn>�w��gH�M�����~Rq)�����{w�nZ�|at������Y�#_Xk����������/y_W�wE�O��)�q������~h	���W#����3�p��A���!`�y2������z��'n
@;RRk-AX��ku0������m��#�|���)������\vl3j+�����hm��F^5��S����WMEY���Th�M���i,�I���Demb�EdkJKGWkWX[irkk�j-�W�Yjy���$�Z���^�-
"[3�V�a~����_�gm�V�f~�jod��n��*����IW#�zdkM��]�(*�����'^���<�K:�8�{���2@2%\�t�2n��D���%����^E�� 7��5��GdY}�$�G�b��7�Vh��� �����������3��&rssm/��7�V�m/���D�'z�����A��<8&�����}x(l�sG���1��#C����J��
�i���9G��m-E;���p����"}H���vf��E��}w��ft��^�iI��]m�~[�L�gm��i&���	{4�����W-2��������t��]����S��Fu5�Yl��8��85i#v�j�c�-4V=l��
���jC��j�c�mP�z�ksZ�����c��������q�*~��Z���G��@O0n������U��Z�h����E�o��i��v��X'�����[�3����_�N��[����'������Z=6�Q�?�k���*=XOA|�/`(������Q�����s���C��k3~��8}o��I����o>�
<sN�����c������-�>A����;��s��5K��[�R���]��(����h��E<XYY�����W��UGG���������{����G��X4������\OLLt�������, �����Ix�0��'������6�9���@����R�lQ4s���93M%2�\�`�'�
��<j#��\;+3g���?w;�,�>>q����essI�8bm3�n��i�,3���
����1T�W�+�f�+
��NN4T��j��d&O�L���5��b0lK{)))��UUUo���o~�����bvv6���?��<��%��666����%7!�r�\QQ���o���k�+��>�=��e�7�0��V��o��>����b�������;B��h�=~i��,�
�u�����);���u;��:���-�^/��)Q���<]n��Y�C���,����������Gq��
��|�B��ts{���O0k��P]�����������o�����F�����I�����t�x���_~�[R!��������������VVV�c����z��w�������\$/�����3y�|@�Nn��g�t�L��D�����_���H�&�}�ob|\)�(��}�T�;0����\�`�xa&�i��V���l�G���zliO�_�%R�u�Hu�����SGj��!!x�p��wX-!���I&/�N5i��:��|����QZ��NJi�:5�]������*��&Q��^!M���5�SY�Z�]g��(�A.�s]�]�>�Eg|u����]��!_����L&C>m�5�:a����q���]�M?���b�s�j�]�>6a�>��>`�����/��1�c���d�H��}�
�3�`���TDOH`����h$�����gg���;��yVV���WTTDDD����7� ���y�z���!/���L�B�X^^��[CC��~��{�9�W���l�.���,��V��V�f���X�*�rf�B��)��6�M�;P`�^�/��J��L
s?o�>V������Rc������gt��89��E�^z�J���]k�����Y� _����8��6Je�����Sh�1�m�I�rd�f���|���=���U���V�J��Pp���N���f�@4���e���X�x�>hL���Sg:VdXq�rz
��66A�.Kw����3e����6�f��,Syg��Y4�K�J��Q�����0i�.���$�����Q;�6�9����N2~cLT��������X4j��Be���{�{6��)���+{�[�5�����6%���n�,�pZ�v�y]�}�S��
t���������A��il
�3"���	m5W@c�m;�������B��_���1��{��F������3�4@c�~�9�,�;����@�����,r���z]c
"��J��|}�!�nQ�J����/xhl� �0��7��W?��$;�}l��|�<m�IS��
�&�pA�����@��'�6�9~��J~���A���#�]�9���1l�2��/�g���I=d����5�5V�b>s��%G7e�g;K�mW/N�����kLR5�C���7���3O����2���G������_!����h��������9#�9 ���L�M����O�~�E��4V@i���Yr�4j�����e�&��B���s9>5F:�L'Jk2�1�=G���N��n����},?��L���I�z���S�3Ms������V�h��~�bZ�����6�9��*1��/��g5B��(-x0�;�sY���E�>s?m[�=}�T_���
�1��R��t��~�	jx�g����i6��e�1T5#��?�7�LJ]<��i������9��bC��S���{4\P7k6������6�9~�����;��iB��(-���!�+�<���Z\l�V�a��E|Gc�R��G����#�A1���3���t��
"��>��(
�ViR���f�P25B�7���B[�h��n�Z����
m�s��X��,��Y�Bh�zJHL/��i�g3�[���b���isK3G���������7n��M?���4!����Q����U��H<�|Vi�����o^W���L�>6<�x-mz���;�.��8�s��B���E����w4|���\h����FW�������
����/4�7v>l2��6f��%z�x�Y~�:Zd(�3�uB� �/����[�g���������G�(���]-��UBn.xa�����C�����kH�Gb@��F�D��r���t��:$��~_�(�3��%Tn�Y������1�����x$�#��G�!	'IPIBK`�0��?*-h1<�:����l6�J��N�gx$��4\P?r(-������M�s��R!_2�1���N7�EB��
(��(����W���q?��9A��G���X��r�����~�1*d�g���h�����7>kC�!�����7����Y��GT�?j�YB��2w���
4\��%��7|k�����@�����a=��g������e���h�W�M+�K��Th�Pcu����]�Q��%�6��v�e��G��R$z��SZ�a�{�9yT�8����dR�*a��vq���]��pA�7��������&��s��qd(c S%�
m�+�4�Z$"7[�v�(�}������^��������fs�]����}��,�C��	��u}I�I��c�?�� B����$%����{oEkN���4\��������@>'��h5����S���f���Ci����m��8���n'B�����.\+��cl�JcZ}��zS�M��j�.���1�5k3�%��e���!A��������l��E������)���]�`Q��0�a����p�9�A��s�BNG�'��!tW��
J�LM/�Y'�K��/���efjN5=��j���dKI���U��4��%i�����5T5#����� ���R��_:k
�E����D���^4���V���A���^������^�Z@bjl�L�`�Y����-��P��X�s_S�m�����O�������o^'��p��h^J-�.�g�h�xF����_�4�c��(-x��U�k���cB�zN���W.��M�����I�q��M����
��6�������^�.��
|
sk3-�G!��w ^�Z����$�G���)��	���F��"���H��@��9����B[�G����m3��o�v^7��g����^�J(�U�DJ������S�smF��d�%C0�W5��B��%�����C��1�t���)�5CY���J��_�w��h���"�g^�Z`��U��xm�)�-��x��RZ�U��F<�������T{v����j/��Ag�|��|��a]�.2�����q����c����Mj��Z�9�4��y/�>�����c�����{������U�
|c�cZZ�FN�i/�q-�1���L��/���� P�=P�'���jS��E��L�
���&�XPR���LGn�����z6A��O���.���(�X�� Gg���,o0]�4�_l���]4���!_��������\�vV��5/=�)���/
�*����6�����q-HPL`���2>���(��1�w���x����$��Dh���?mr��'�}W���i�l�,<�J�����U>�J���gm�[��s��������������W`��wf��6������1�S��]x�~�����G���t{
�;2�'��y�dn�c�tC��V���YB��k�����(l cH�;����4/b�Wj��4�yd����_*6,�.�3K�B[�9�����0_�0�]��X��������j�^�_}b�	-�0�+,�_��U�2����7f��n�%z�������~���:a���an�t���%]���
�a��
����xr#	m�s�
�\&[0�1��N�!X���IW������:��?�@��du�~>�}h�k�4���6��M��q���������&������:cg������Cc�M��|��t��C�Q;�������|wP����;Vl�z�y���-��w�|��u��S����Qx�f14�"�9G����B��kA����*����>QJ���y]�3F<~�����A�������G�}�1>��;���RoV�S�=�ZG&h�e�N�6<h4�c���k(��u��������������-9AMM��z���Y�v�X�v&�O�6>6���i���>� ��fCi������O��7�B��tZ$gfl� `\N����c�2F��x�������Js"��J��&���&����Zh����R\c:xU�(�r�`��MK�n=���o|����P� ���'�����2��+��gt��Y�v��I��M=i�fa*�%GG�}����S�(�z�?�E!�^Tl\!������~�]����������62�&�9 @���X�*��E�}�3'�[��x��k�����1�����D�X��������	�v�1��Ib)xh�}Q��a�G�u�yV�6������D���(�;^J�{;��~Z�a�E��t*��6�����m{;���w��D>��X����P<z06�~�~Z��6���|v��"I`��AiN1>�T���Y��R��������B[��@c>��Vs�}�����I��K�^�F%_��|j����W����mog�3Sn���
��\�����$���N��W{;3���������>yn'E�o��K&~���K�Fm�	jc�������6����N2)�1�(�o��{�R(��"�Pr�����6$�4dz�/����������������L��e��&x��3z�fu:�v�p������4��T��fsQ�)��!�P���n�1j���N"�![���<s�p����K{;������8����a���c7	m�	��m������6���N�c3�<�����������vI��u�8d�|�m�)s'{wh�Qh;o��Rn����F�y�`s�.����|���h�Z*^�/?2�(1���_�AE�����e>"���*l{;�|���
G�*������!�I�G�Z���-dm�� `\4���"����>��ez����4s{���i���!��_
�>F���~��V�+����Un������~�Q�����3���t��$F����Q���|�a.����s����D|������J�����.�������'�~��
g�/m�s�#��f��	�8E�z�E�����Hi��uC�3F2a��P��b�R*��Y,�n�'�44�`$���#O��Y�a�6��c��+��U�6����S�Xe�j1�����:�[p���G3�����Z�vn�������N�*��>���y=��B�K*� �������3���c����3��fz^�9yT��{6'�H���>������V�1���9������� a�����E��:S�����Zd���+���n.��fR?�Fp��sF������y�.`�vr�?j������s��c��6�9�)�;�D#�bD1�)}�a@*��V��(����~)0��O�t�/X�2�
LRc�7Hdq���x�a�i��z�5�u����Mf���G�������L���
#�|c�t�Nq��s�mo��������1�T��H�+.eVm�s@o��b�����F�`f���@R���C��$���l���Ps<�����
��1�)"����t��~a*5l�gq
	����r����X%
�4��R�b.�1��k vs�uo���Os-Y6��N������#�f�7jF��'W�j�6�9�5�c{�s
4����>��4�LJ��SlX�s��gG�(�o�]����K���"�b��J�������%�Q�9�M,�_yll�:�z�VZ��R�h&��mH��_�I�J�������;�{;�u��<�����������d���F��|p��q�8|#�QH��&~�4���vKgD�Z
\�9u��E:�G��������3���M��YxHb�OP���KjM
����_i$�"���&|+2�@l�)���ZO+n�o���km{;oY�v>��N��F}�7����^����>���T���c�2s������Hi�"g��+0�o8-1~�jg��2E	mx��GB:+^�O�2����z��F�*R�f�������5R��i���S	E^�o��-L�&��~o�Y��������-��������x9����A
� �����:��\�g���l���J�����U��I&~�~)p�k�O�^b����>�B�y��t��~�	��%iI��Yf���������p��s������\����r����f~�
,��@o8�F�[���
����g5��#��2n��7���L�u���e���l�L�������}���/Zd����=�9G��s�"v����`���{;�x3�����W��-��<���[����"L�
.��;J�h������7�#B����a�)�,��g����w4�����rc�]T�g����4'�������������T�bao'��8���������P�c�����jA���]�T�����4c�c���,�DH����
��4x����&sF�a����8)����NQ�]�v�U��L���	Xo�b�h�'*O��3�>�SsS��7��Y����Q��H�����+�� }HO����g;�W�7�`S�Z�y���X�a�)jM�����-��������%�f�)��z�R1t�����>���m��J���:�J3T�SH�F�c�8{���c�#~l�o�J\��k���K��H���|�?�[E��_0�,����}�V���]��!_�H4��nc@q� ��u����;����~���@c�)����L�d����|�
f�H:k
#��/�e��l8Q�^�/��J��L
c�([�9�b|V�e3�oo�J\��t\/��4��Fm�s�Q��L�h�,����L
u���$��������Pe�f}�5�Y� ��7������S^�����	�6�9�������������TZW��+��M�1��Dt _:G�y�u	`��~���@c�)����T�`�2���|�:���x�=Fk�2��������8�,�;��vP��0UB�����|x3�P�h8��H&=���^hs@��8B{�8#^k�O��"�o�(���<�O�D�~�6
��|�BmN�����|x3�P�h8�j�}f�?o�����>p����82���vos��Py_��(��f)P:#R���P�;�f��4�5�p����x���B���)�F�zQ�h����i=���:�%_�X4�3�K���P�_F��3�EB,����~���@c�)?����k��6�9���l''��j)0z���>��B����~���@c�)������K[��������B�������.�
TnY���oQ��6�
�f��4�5�p������������|���T�[\�����5�����B�x3�P�h8�������p_�����>��4}�UQ�=[P<&D�Iw���Vm#�o��?@i�k�1���Q�����#���7�s?8*������Rs����3a����(
p
4�R>�{:,IG�e�5�s?@i�k�1�P�h8�A�d:,�-�8��~���@c��4�5�p���c�x��Z�����>�����w��QT_���T��+6PAEA,�;��
*HDz��K�]z�N
�%����Bz!��������0�lBH3�����?��;����w�3��s��@c@�4�4�����?�~0�#������u����@c@�4pg���S�kqBa������e;�2mt�g"\WG�.�%��&l��m�����r�����[�F���r���k@�4�4�P(����NM�j�K9":�E��B{e�6r�6|�6l�&d�&�M�o��4>�4^�k<>(q�\��Z�S���%v���4/��@MC�����S����V��=1>����p_������:@iFC[$�d�)BQ�PpY���x��uuiV��������=��m��u��������Y������5�C4�4�5�?j|��x~��x�����WK��8<]b�h�M�Z85���]c�����esF���g)����p_������:@i��-J2��$�(Z(��t9n�,{]�y]����	]�A]�.m�m�m�R����^��
�	�	����E��]������>%�K���8>_b�T�mK��1��k'c��������Z�����p-��^�����JJ�u�gJ������W%���>�lW]��.�Z�zJ�r\�t@��S�I�Z{�vj���a�5!�5A�4}5~?k|����%�����Q��r��s%�O��>l|�T����'J�-qz������5i�����t�����i����
��H�fc+	]~�lc�}V��d;��Hfw��@�����@�JJ�u�cJ���N-Atj��vj��n��<>b�F����rj�5��w�o���qI��y���c����O����;�c������������<��F�E���GB���Q���<B��&����iQ4���d�X�jw�R�d?x��okwm�\I��������9@�4�4��%�B1H����;�����YDl�I����f��c����]�E����m�>.�v:��t"��.�B����Z{��u�ZW���*:��D�6QtjE��Vtj�E�f":��Ss�ZX���:�5�����`��=jw~pt���)���d�]O���C��������	�u�{���`�9���9�V�#?�����9-����*���&���	�EpwJ��?4y���1�c���,@���".=�(�s<%�>;,ft�!.@['&u��4[�q�2�!��+�D�Q�c_�Yp���-q����9�5O����;��-��?�v~���M�o��-�_�w��K�;}A��Q��%b&�h������K��K>��`��A_z��.�C����1d�I%Y�I�^��H�������[�S'�����}���O4yan;��'�
�'�(q��i��]�!����~��8��������wW����C�_����	������)|��;����(,v
?�M����%��o�u��t�����J	��������8�g�hr��/0*��������%�7������ ������2m���1�f�����������<���asx������1d�]����%���[uN������#�otzQ\n�JL�������
��=��3���w��Y��>�|}��AL���D�m7l�6|2t������w����)��9�g��t9��C�p���W��
��H����=���tI��j���u�z����s�����%�F�O������������_������@��)/��V|��?g�e�_������S����������5�� >���K�������G�|���d;�9�x��=��E��������2)E5pwJS4���2��dq8,R�������p�Iq8�u�����7����a3��6���a}����{��a��a�K\:��a/�C���d��f���e�����~�� r�����a|�	���4�R|.��o:��I-�gy�!�nr���F�\��`�N}��f@u"���~�m��Z��Z��
��;~��B��<�xT���?D��.O�yJL2�V\�wx��'b��oxe����&����B�h~8>����%�O��7[�)N�=��x��/~������>����B�q��U��E�T���
(�M5��������������07q8����p�����]�p�m����a�����������N{i����ebo�I�_W�=+�����G�_fk���y,�y,]�_�A��77�}4��:�Hv�U�i�K��"�U����_��rL|6xNtj.b�,��H��(�������"����t<�g�[R����E4Jw'����L�~J\�{��l@���������KAZ�z<��NO�S|����5�Ra�z�������W�	���U!a��)��J������b�_]��+���\���#�xK�$������F2.�iM������(	��4K��q�;W�'�����~���P��R����)Gx|�,0�A]��%K��K���8q�1N����vh��%q��c+;���|�q���g[MW������GF�>E�r^�B��7u��3�S����1���E�e�@&��"f�1����M�O���@^��^�������^e�6��xT��2��G��<�?���A��E�~>@_A`?���j�o���O�����������)��x��������#��-/���.}��]��P���?g���)?��.1}��������w�
������-�� ��v���
^�E�qy��G��YH��vz��
���.�{;>�M�'�gXr�!�f���)���K�x�od�L���u�F��[���4��A� ?
k%>
{Q\wvc�75��	���C����&��������M��!/%�����X���cg�-Z4e������4�WJ���:+�A�a3jz���Di��T�)�n��&/���t����5���<�f�
uzuY��<����6��<�%?���K���??�?Rn�
�n[^���1K�F��?�L�^���w����U��)�Byw���o��Ra��u��>�,�I�X�3�����"���_���sl?x�| '���g�� ���K�Byr,/7����������@E|v��~�q���.�4A!����S���R������R�k��j�����|�5���g�2m���sm���WU�-�)�h'�zs:�,����Js)pjq]�Q���cF���M����Qe����)|-���x�l!����7�}����^�11[��x��8�a�p���G������1g��~c8l�8v#�5P<fv#������]�����9=#/[N���V��p��7��@c�"�~�a�������?m����'��y��������!�����@��p�.�<�+�����3e���\��q�+��Y&8�:�{���3��M�O��H=����
������z�&��K�>�x�_n����S|ww���G����".�}[/��w<��4��@qR�(qR�T������������������&��s���Qw=�o���@E�V�)���f���K�i���j|�W���mQ|U�f���O^;S�������+����K��m0��oH�T�E|��:�eA�7�_�O����{�����i�C�4�o�����Ik�x��������}��s����.�w������'/��3���^<������K��rO�W���F����).����x��^������1���������!^�7�|����I<?���M��M���+g��0y^$8�F��F-g��k	yQ�?� x��2����W�KW�,h^����<������<��Y\���'K'�+.r�A���>x��^��O��<�:�?q��!�
���"�c����^\i*.�4�����;^�i�3���E��xD)���x���xE'/���/����_e;�W���c�9n�+�!������b���Ry~<90/�=Q~�&?�����"��(
#x�`a;&RWQO#�����@����x��8����z�c�3�q)�$���kr�v��g�jy�_[������&?�p��p���J������o�V�|���m�N�0!5���biii'N�jT��}}}kz�5z�*pY�E���������;MP�K.�.����H-.�I�gP���������53����L=R��q�&��������:@i@i��jB~�q���*����b����7j��M�6�rww_�fM��M�����U�L��R�&MV�^M��:�������c�8�\-�A�5jt,�3.�����^��=b���5���2.icVh~�)L52���4�����x�����
�9@�4�4�P(
(
4VM�V��*%44��#����h�����A����/..��L�k��^"C'���4o��NRM7W�w�%���~�}k
<�P~�	������r�������A�������4����@�'4>����uW�xz��mP(
(
4�JJ�U���^�z�7n�Ay����|��-���7o���;T�8q"��������-q5[��^{,��.���P8>_I���<�5�Fn�.�U�Y<����>��������z��(��PPh����&���YYY
6$fccc�����K�.�������7������7j�(;;����-q�{����^�����9e�CGTZG���\��\�]0$�[��]2��8�����x}�
��K9�)�mP(
(
4�JJ�U���A333)�LNN��K����K���I�322��S�w�����^������������p����w�8y�J��p^v%�/s�6P}�t�{9����53�6i<?�^��K>������PPh����&������_��^z�i��O>���_�g�������-"���e��'	������T��� ����U������K�/���j�������F�T{��zj����o���8�_S2���v/R�K>��<Q��i����i���X6^�t�3��
��u����@c@�4�4�X5!?x���>���������{����g}��GCoC��r��O���,��#G�H%��J*����}{z����k��;V�^��~0�=��G���Y<�����
��\x�r S�K9�
�F����qM5��-}�-W�mP(
(
4�JJ�U������������d�������������_��I���$w�cG��~��o�J��+���S�N�R�������cu����S���ZD��,QL��[���8�\fd�[�.��,��t����9�oK����,P�.�����]�As}mP(
(
4�JJ�������rqq��pg���5��;v�M?X��C��e?��T����4x�r��
l�|[�+��\O��Yi�j|,qx�f��mM�0m���Oc���6��������n��-[���;w�\r���������s�-w������NG�P�Z�(��e��F/���B�?53��oj��h���r���1�hs�:@i@i�1�PPh�6y����m����rI}�'Cz���c�z�8{U��!�I���:�H��v�,��$��T�����x:��m�s��f�-����\������<5�}��W����ST�8�C�~���������D~~���7Q�o		@6��}���yU�3���/62�d�c��B�u2n���c]��:t��i[#H�S���u����������T�8�;���?��/��%i���9s��*v�_�pa�j�GoooO�t������w����b�&t��Z�T{��J�%�,7k���ndr�y��5���^�O�Z�i'h���T�P(
(
4�JJ�U�����m��b����4���Tn��^�zQ����
����[T�e�����7Sa�N�*O�4��{��mPN�05�0g���j�Rsd?���9�F;MT���}���q��I��z�.��&���uj�	���^���(h�q�)��u����@c@�4�4�Xu ?H�j������~]�v5���q�f����������T�]�vt��y��^211����Z�hA'�S�W���k��y��
��9S�w��������]u��N�r=���q����mQm��$�l'm�<��{�2��/h��F/��K�;Y�^mP(
(
4�JJ�U��}�������7|�pi?�.]�P�������V�����7j��M�6����X�vm��M[�jV�2�KTa��5T�i��-N'1��n�:iDr��1���U�'���=�sH�w��]�E�Y���kw�;Lq�.q79���oam�i|��^Y�K?#\�d� �6����������V�=w���#:v���E�x��'������]��_�~��������C���$7a����<e�%�@��2B���V���}���[W����o��H������uYe���UM�NM��r�F3����n]�Em�����tyM{y�.��X�Z�@��JJ�u����@c��p� ���x�����e�Cn�U�-���8�\�]�9�� \��7��iq����4~=������[��mP(
(
4�JJ�B���7����[�/q{�lD/�[c��\o}�E��vOX5�]��6lL9z�p��
������%����������:@i@i�1`@�I'�z{�����D�h����5�����iH��6f�����=��#�^������;�$hs�:@i@i�1�PPh�s�F��n��T]��w����w�'g
����I�y���!%���������������6�������������~�u���+k~��ib������feN���Z�I�������pkh��&��.i�P�r�>���PPh�����k.�A�I�T]Y?���p/C�����Kkp��T]�~M`��'oi5��i���������*@��JJ�u����@c���Ge?�2������N��������\����2��3K����P��S��?t�����	mP(
(
4�JJ��W�/���7UQ��N��DZc����=^f��_�E�u��k��i�~��~�t���~�9w�RA�A��JJ�u����@c�������,�YE�r;M\5S�bti�f����Rm�.������Wo=��Z<X�rL����A��JJ�u����@c������X��M�'�����U�z4���������y}�Ks}�*Pk��u����@c@�4�4�0�q��������Y5]�=������/qj[X���&d������Q�z���6�����������~�g���U��Qd����e9V5��5_��n
�mP(
(
4�JJ��G�������7�V~�	������@����ti�M��o
�,hs�:@i@i�1�PPh�2t�����+���N���x_���6v�P��;%@��JJ�u����@c����d?x�|�[3h#f��41T�+��9@�4�4�P(�����8��0�8/�ZNZQfJAZB�����+9��1a�W�2"���|RC<��%�9'y�'z�����s>�`m{*��i���g�\�<vz���`�A����p����>{Wz�Z��}�������na9g�����+&8,k�x��z�����x�>\��Q��/����]w�T�+����:@i@i�1�PZM!KUPR�{=?�ZNzQVJazb��������������Z�q��b���N]�dy�D����V��R��bJ�j[�K���������n���n���)�+&:,g��(���m��}q��3�������>g'�j5����-F|jh��C�2�������������N]���F`L����`���Jj\O-����@�k����:@i@i�1�FQ�����(����8JUK%�R��rq��3�����A��*K�)�z���`Jhl�
�w��B�+����:@i@i�M��M�(�\+,)� ��_R�� �zy����l�\2��r2�e���H+��H-��Z��R�N�"� -� 51�*����������$�1��1�	�9	d=�r�"�)b���g�\����Bf$43*$328#�\�����������Q�����U�N
�N
��D��#%��4����&��$�:'���qJ�vL�rH�$Gc��a��n��N���R�+��8�9����c��c����q8coEmgmk!��+6d�NE]:u�<��!������&�'"��3:Nq�h�����-]�8v���a�����a�/�lo���S2P�/l\ta����;8�m<�5��&���}������{�R���<��w�4�u�L�5��VMr\>�~��E#m�4w��Y��`=���I��!K5����N������i6�3���gt��;A����
0&A=~��`flJ�
����v��^���z�������Bq���	�2 d:�e�� 7A��,��7�P'�z���u���'F���~������{���m5��\��=�~�4=l��9_�3��l���ua��3]�A]�����y~����O����sS���L���g'�9;�z_�Q�}f|�3�~�������-���MA��#������w�85��SC�?������B���_����j>�+�A_�
�~��~n��g&>5����?>��z���!��<�K�_�9��~��P�@M���P�B-9}������S+Dm�L�5s\��w�D
�R�Wz�\��g���M���tlw������NQ�v,��i�������[l��k���xW��$o�d���c7���������+�������&���BP�A/���2w�vQ���v�s�8�e����;������%�D�H�<���^��������M���l5����������G-F�s����6�Y������]0�n���SWLw^M��<�
�7���m��vj������w`���mG��"K�?��`��#�-��2�<��%�h�s�����}�O�tN�vK���HM�zy���+�1�*��&%�_M)HK/����C�fAI�5M�qp�1������`%/��-txF����9@�J�Iy�����	����M�����#���y�����B��K����*�5g},���Kx����z8k|������s�"�-����l�J�!�4��.���</�����_���d1�zV�������O�`��{����Z��f�}q�h�R�1�aYu,����{BL�����h����sf�ni��3"�������I��KJ$KU�^�,��).�r��L!/M�M���8!#ZH��^����!�W��b��+.B��a'\�$�Z�g�@!���g*�����}��n�y���M��,�ml�
W	��	���.����S3��S�I��8��h����P��_����}��=�e��"k�g��?[��|#l����{���`���}��<P��+{��r;J+�\��^�%��N.H��K�HDvLhfT`z�o�OpM�sL��Mp� �����5��dtG.[�vjo��Nq��&���|����-e����i��0a�����KF�-��%<?�w�)}�N��V�Q�O��$|f���u3�/H�N?>�����&�f2�K��?)�4�����,�o�����~{���N
%���0��b����bd
�Qd:~�����_���/���q�������!����}�N�wnY�������S���F�d����Sta���.�rQ���Y�^�3��\��Q���?�v�(���c�h��b�3b,����dm&Q8.��*y��N+�9�����53����������������<���_�����"�-�<����<��mK=�]������^;Vx�\�M����>{���!���w�:1���'����?jCf�[5�����)�OQ�R�(U�%�h[j�j4JE�\�����<U-��B�Z�P�%���W��$!+^������p!9DH
��8o!�C�v���{��B�
A�B�)��L�=!x<	���=��N��_�a�`�Q�]'\Z-\X.X/�.bgd9G8=S89M0�,��N����
�!��O�H��������Ga����n�����/���
k?V�'�|GX�YX�QX�AX����ea~a�s�����V��'���
S&7&6��W��>)����`�7W|U2�l�`�j�/�}���^���@=g�3�����BO�x��}����uz:���VNw�0(�]�B���a��D\S#�g>�{5rHKo�N��z]��#�We1H���*�#$�����E�A}$)��I����������(�+%�O�
��n�����B$��%����]rH���&u���.�b����&u������EK�=7)�K�zqrPwN
��I!v����_q7O��IA�>)n��f�K�f�99����R������\H+q�[����q����'
�H����pxh�m���F���G}rq�
jPSvX�~�E^�d�w����b��!��%���*�.�N���oZ�_Z�_Zu��/SP��A���E����+�����b������A����1�J"���������R���5� 5� ������0�jaFja����-�����u-'�87�8�z�������KQRX f�)�\�����Q%���(���|rE�b���bdqd
d4���H� ���������";�#+��Ef���J8���+�P8"��1�y(�#�#%��G��$F Gb����A�&�W28q^��dvb�9����P\q��E���f����N6DvB�-G���3�W�1����]�;z�3�����ca���.�����o
K���&,n/,|I���0�Ya���������>$Lnf|k��E���0���������u.�y0�A���C=
��P��#%��=����l�#��Z�����LuZ9�vu��\��1z��@%>>��s�?���~8=����^g��=�����%a3��"i��1���M�xl[��c���`�����
>�/���8��$�sXF���u��b���$�w��"�|50<%�JJP\J`rr`ZR@fr`nR@a�q��8�������+�B_B��#'_����a������z���3x@����S�	���<�@}����
��g��:s�b��;�#H����
�?��n���������s�~������'�os�x�;`��^�I����^�:��b�&��*��W�N���/s���EaA[��m�xA����q_���9�����<�����'y��������
��Ok�1�a1������;�������E���������~���
_���y��n�������aYW�S��<��E�.��Qg�:f��W��[4���_��u;9#&D]�OL~������'.���rL�3������5��zi�H17�D�eS�V�t^3W\���s�
/N4��{�����v��{�{���^K�����]�������k���>���{C<��{��r���;�mW���4����s\��s�Z����aS��F}��F��B�^Z:)�b�pjz����q��y:�<����s��6~)l��MO�z�Mr:ec
���Dh �a�>�@�.&6�''��M���Y��������
�x����ra+:�c"j�~�O�6|����t�6�Z�=yF����9�F���CCx����<�Z]�I<�{j?����e�%<o��*~�E-���U���g����1e�#Q&�#MW�,� K��z����=���z�b��.�����e����_/H.H����MqL�:c<�����~�-��w���q���ua�og&P����F��"�"f�vr��S��:=r��Q�,�L�;�r�|���XM\i9q���-V��[M�k5������SL-����z�r�y�)6�SNOq9=���$�S��OM
6�f>!�l|���8�1�&�����zlx����G�f�+������,<��������SBJ�P��-�Pe�YD%�d)�P��y�)-��D��IMxdy��<=�In�����<�k/z�[���s���-F_�>?2�Fo���o��<"��'nw����u�����G��F�h��~*ur?��������c�+x]��:�~�
p�.����
x���Q^��o.���xFA�!��'�F9��^rI�><8)�g���t��X�x���3�2x���<��\@n`���{�3xI��,�L(��a�K
S
�#����������:�DX�1�px����.���/ziN����J�U��������������6�&;�X��i�����G���h�g��!��i�
�^�O��O��o��o��_���{�H����������Z�X�4�7	�?�{$��P������/{�
w���=�y[���H�MQ�����^�Yu������b.,��^{vA���qV��,g����prJ����fM�&��tlD������$�r���������O���i�M��3}�O��g��}��n�[����e��w����������~/w�;y+�*X��p���v(^���E/�,h����v�3�Y���<��y�����1�1[	qz*OUm�!M^��P�tV����4��~���W�
�$�49vV+v"O�H
�4�v��<j�!N���B��[r+_C��K�E���w_����.y�tr/O�}�C��Kg��<1�-i���w��PH�W�W:�x���g��y�:Q�di*���x���Q�cF��n2ftz�M��6V:f�������Q�-�adg������y�dR ���z�WYf��b��$^����+:�ry�'���d?��w��K�_�&���<��r&�����m\��s[��6'"����wH��N
������u��-��4���2�sJs���s6��s�����a��2�J��M��b����Utyt�t��F�����#��z�>}4�������a�#����~�9�����A_^*?�3������9!�(��t��?`�7W*�X�_�m?�t���'m��.Y�������7&�M��dB�/��]��W\�o����9x���+�Ck�������S�a8	Q��|���SW��L=y6��g^u(_�6O����1V����������::�g���{���w���fi@a=g����<����K�L�s��~��g8������{�H1%�ciz�+��	C8y���N���R�N6��!�����6''	����P��,����Z$)�	�N��b��O������_���CL��[�>�S�$pH�U8�J2��z���R2��4��SH�Z
2K��P#Y�#�����M)�����S����~�7A}�~��������Vqry��������|pO���������{��pxo�����V1��	^W��z��rN�qL��O��Mp��z1��:��\�#U���=u��������M"�����V�/[;Mv�<�����&;�T�w0Vy����a9�+�AFwpU�g&�����2w����vY��k���L�]��������R��_R�����u*��A��P��:H!�"��\1Y�	��[E�+2A����SfL'��;3H]f��g�������� 4�V(�����41~��P3��<���]�oS6Gk��7��|�?+^���8����X:!M��O*�yY����}c�a�pq��Z�����~����X&�t,q��b�i"�$
7��!�C��t�A����MJ���P(
(
4����_���p-�l��M�*��]����$��{!>>�����:3n���c��t^��s��dx���&:��'5$<+&� 5�z~��T\��xs���qr?���������n��<����'��_�<��������
���d���Q_�:��{�n$��Y�x���!���� �'e�P���7�{� ��Qe�P<}k��A��e�P���A(�=��1k���._�1e�����}y��W�D�/:3���2����R���:@i@i�1`��]FL�/�]5)[<�]�Vy�XO5�Q�������������?�O�t~��K�����~���jk�u�N��6E:mNt������qO5����G�_3��j���n��_y������V�����=X��Nnn��5��/�����%F��%�-j'���P.7��x��t��K�HK]v�.5J�,l2X�b>Er��
�b�4�l��vO��f�#O��K`����8�z(^�T��2�K�����jPM��������e~p�<�rm�����#fVzlAI��3�=���������*�o���b��|i�:r@�����n3>=�c��/�n�x��fn~o��w��k��.�7}`���s?v�������6|�������������������v}���y��z�i�`�b
�?<$��B^h=��	�*���aJs�d���?<TT!A�a&4}���B2�2��[�Z��HGq�{�(�AJ4^F���rSx>�	�Y�n�n@i�1�PPh �A��K��5���%�I5�x`��������/@������y�;5�.��*��X����&��['�g�d����m���]0�n�8���/���l����N+�;����f�������mZ��y���%���zn_��s���5>{���[������n
8LuG��]�'����1�z�`��C�-��[?kamy�<���+�,�m�b���8X�:]�s����{(����C�2�|mv+���:d��F�}�G'�7�cZ����k��O2W�9��2���������6�'� ���	>c����	��H��'+���)��k�0w7�4�P(
(
4(����������Z��Q�4�C.��7�}�N��~���"+A���?�tnYG�[�;S��*���5P�:�����9q���x$���<y�d/q���N�<��V^W�u��2Y��g��@�����gd�r���PPh�������[�Js�����S�a3_��j5.�8O����d�`����P��(k�&5�i������K^�lk?�Y�����������9���<�F����P�����<^��S����Xn
�46hs�:@i@i�1�PPh �A��e;j���%���ep�X���f�����z����"Nr���pm��Cf�sp��pb���J���sj���9���|�	yq��p���}��fU��9�:�ub�f���\E����P�9@�4�4�P(
(
4�����Cr�&xpY2����'9,30��EY�_uMH	|O���?�������O��J���{��aZ�A��JJ�u����@c���������%.��%������9��7�?Z��sf0+��<������\����?�I#����&��ua�e�mP(
(
4�JJ�d?�����H�S.���t,l��z}3����)��F�n��\�0I���(a����C-����\����=����l�uw�6�����������9|A*�e�/������E�[��`��C���r�x�S�9���gk��&6����\X.Yr��$hs�:@i@i�1�PPh �As�D{eQY2���T��k���j>8./I��K��]��-�}��V����*������p�M�.hs�:@i@i�1�PPh �����R�����d2	;���7�_�
����e9m��P�����M<������������:@i@i�1`����J�S��#�,���7�������K�-��g�����8���D�e��v�������������:@i@i�1`��������e�m�_�w-3�&�3"����E��e��U��|���%8n������>�6�������������?]�����^��s�(��^;���������'+��	��p���DE�(��PPh����~�jT
��
_�x0|�g&d?���w���(W�^*�x�r'xt����BE�0hs�:@i@i�1�PPh ���d�Y^��������f������fgV�]������B�*�K����������:@i@i�1`������O����z�M������_a�`9G��p%Npr3�|���zg��
��u����@c@�4�4�0@���o]�k���G����u��w*��}�'7��	N}�w��
��mP(
(
4�JJ����6v������i"��ml���*�M&5��	Nk)X�G����9@�4�4�P(
(
4��`L�������d?��y�lG�.���s��q�$�����`��S����9@�4�4�P(
(
4��`�����%���~p��Q�<~��������<q������x�	p�6������������'A/�L�����E��2kp��X����;�9��
��<�g@��JJ�u����@c����-��~����d3������+5B8�g�Np����v%?����������:@i@i�1`��}z��K9.���=e?x�f�`>E82L��O�����SaEga����'+_h�_�w�S��6��������������6r�d�.>�?Y�h���6}������c>`d��u����@c@�4�4�0@��n��������3��fp���j��yU�>j�O�hs�:@i@i�1�PPh �A��&�8�(��9f��~0v�+��~Sf����tV�#l�F�77�gu�9@�4�4�P(
(
4������������$���;�(g�-��`!#Z�M�������������:@i@i�1`����
�����V������efp�w��RP/A��JJ�u����@c��^^�C���N�)����|]np������K��u����@c@�4�4�0@���{?���'������������2A}mP(
(
4�JJ�$?�a�2��0�G$3���n�C��2A}mP(
(
4�JJ�$?x��)���I~�r�sefp����FP�A��JJ�u����@c���?w�&��a�%�����s������1hs�:@i@i�1�PPh@~0{x;2����K��&��-3��^6���
��PPh�������,���/���������A�mP(
(
4�JJ���o|���X���\�r�������{��u����@c@�4�4�0��`���y$3���������:l1���z��PPh����,����3������238�Ic_�@��JJ�u����@c���?�%?8��]��9���+�}i�nmP(
(
4�JJ�R'v ?����nx��Nj*d������PPh���d.}���S��5zj�2?xl����%��������:@i@i�1`@���W�zs��O�m3�e��w	hs�:@i@i�1�PPhPd������_�����/
�=��������:@i@i��:BZZ�����m����j��o�����5=���H��I�T&LHMM��Ib,Z���m���p������6���������aaad��4i�z�jww�C��i��Q�F'N���I�?N���t8�d��5M�6����kt1'�_>���23���~�mP(
(
4�JJ�����v��5h���\��y���W�����Re2����r���)��}�������G�+78�����pK��u����@c@�4�4�����y3���;�O�8��{��]������*�7���s��T�e���_��e/�fP3���@u@��JJ�u����@cF��w�!�6o�<�r;;;*o��Qvvv�g���j��!U���1xi��T��K��_O���e��n�� �mP(
(
4�JJ�����"�N�2x)//Oz���������I5srr^����^�����%�~0e�3�<���6������������������*������K�/��$�-�j-[���R@@�t~GG�j^���mWW����PPh���3.���ZBBB�W��oO/
>���:�����K_JNN�����j^���?P����9@�4�4�P(
(
4f\�o�.�������v���^����'���U{���+����%�����$���y����hs�:@i@i�1�PPh��T�;v�x�~033��~0v�����vW�>5mP(
(
4�JJ��:8_������]���$�4�����d��>�1��q�O�M�����~VVV5�o�:�l?z{{{*o�����G�p����G@6o�L��S�N��&M����{��=LMM5(���U?~�A�[o�E�[�l�����)..n���6�0..�E��7

�������y��
�9sF���Q�f����������tZ:9����@-k��U��M��Y���q����m�6j�����5��['�3f��KT�i��
N'Y�v-��NK'W�s�1���&L �����������o�j111���o��u��������t8��NE'�8�p�����������W^y�i���7n�����+��D�����/�|��G�5k���o�Y�����b����_~����n���'�|���P����{�}���������z�j����>XE������i������=�����^�����u��]�V�2dj����(_x��F����C��&MJLL�Y}��j��w�Nw����W]3--m����~v}���t?;	R��TG�#�I����p��|@���-[���'66�b�F��sgz����}:@]��7����~��Y�[�������������o��U�B������;w���y�����G}TPP�_-99����j��5U����
t�ttt485b�����C�����q���"U�A��333��]�t9p�����������%��Z*Cf���x�����s��y����r�M��X2�d���?���RU��������I���W���:t�M�6$�'NT�L#!�9����D����/�O��AM2��+R)i���3��>�lzz�A�
6������yu
��S���)�����(Y[[���o��������r���c�p��A�5'M�D��7�����#���������tT��c�edd��O�0���O?�t�-��������
6����F��/7n\E?��Z��qc���]���I3T��K/i�Z�r�T
�K]�v%C�`���;V�IE����:���cbb�7oN�$�hP_���Q������oS!)S��[o�E�gJJ��'9>�3c��K%�J���P7!?H7������5?���~!5#�[���aI���S3r�}���R����/�����TG���;*�U����a�z��%K���Bf�v������+M�4��42����sgaa�\����q�F��If����Cz����)Bf�����S�KR�������7o�
$�ri�w������x�������N����L�EFF�����r�(�������mHHH�>(��2m�4ww�����������/�����F�������%:�\"�g��#�R�������������t:��,��cooO��m������f~2�C����G��T��@��>}:}����3(OMM�� IK.���-��U��pK?(=��7o�A��������l�p��)T����T&H7_z���3RIXX���w��uHc�����y��������!��f��!�������9W�;w�X_jv:u�$�HS����T���&�����_�"hp�A="R��L7�*� djG�����_�tiu*Cf�vH4?��Ay@@��CCC�B������4�G�:u�����<�%�\1��s����
_)�QRR���{�������C�����_��W�{�9�E���������/���
{��Y��4�����c���?)�z�j��
_z�%�OWW������I�����35j$u���������>�����/�<����g�yf���W7������Y�����;�
IW����U�A�����U|��G��/^,�YRRB
 ��_��bej!�����J.y���7n,'�133�
��������
�&��'99���������_���/���9rDj���
���t/�C|||���~��Gzu��=�����7�����?�+�w���<�p�B��*� djAqq1������|�1���K����K'��HH<��!3Pk����E���{�������v�Z���_m�P25�j?(�x!*���}�bQ����D����+V�j�"�l��Mj?I{��_|�$,����5k������O�?H�#&O�lPN7#*3fL�C��(�<���r����s�='�?��Ct�����_/=��mt
��eK�v����p�},`4�3C���^{M^�^���@-�~x�����CTh�|2�C|||�~�d�QS6g����L�j��U�����K���
�pcvq����?/_�,U611�X���^z�����/_��ys��6m�\�pA*���'��QQQ��h�k��$��M��y�r���|^@������x��w+��\��M�Z`pk�%�T$���d��I�j�-:v���Ij����7���v����+W�w�}���rI�� dnFtt��
�����^���6L.��@�9z����>����K���;wn���t����'O����@��?(����V��AAX```DD������3Ts��E�9I�/�������c��x����[Wz1�zMll,��^~��������h���������l�����###��.]����u�Z��2z�h��;5_�f@f�$	I��I�����m+�@f�vHmW�f���555��������I.��@�0�|�J)**�f�d,
���ot�<$�{���s�����_���?Si�-���6s�L����������r�7�|��^:5p@�y���H]yz�����`�Y9���o��V|u���R��
����g�}���J����q}QAf�F1�L���7���;w����j[�h��c��C���������^���$%%�k������b6x���N���|���H���o���;t�@Geee�u~��'*������u�%5�r�2���_|���~���K����\��Z ��'�o�^���K/���\��Q��&���
��B��M����U��DDD��>��W/�������}����7o^����$''�o���g���KGGG��H.������P�6��i��-�:��+^{�5*����K~��g���2+c��Y�����I�!3P;
t�v��Q�����cG�W%?(�!@f���z?z{{{i
D�����n���������LMM�C�z�-�:�<�� wd_y����[GFF��{zz�o?00P.�6����nPa��S+t�}��W6 66�i����w�/��������{�a���@�!3P;.^��@\�U���&�^�4i�\��Z��j�Yy��/
��qK?�y��J�zQ�F��{��/ �=��!N�>M���'�,���'���U��i��SO=%�6�|Q�
RRR^}�U�a�8*����}��D���R��A�U�Ft�l����dTii���H�����>�T����n���w=n�8�B)q�#�<����_��Z0m��7�'���b+�T�[�Arp���kP>kh\\9����?(��fM�g�%J������K~~�3�<��C����r)�u�?�?NN�>�F�P����4��a���*@w��~��8q"����������G��??��#y�CE�����W���:��G={�lXX�w�}���w7yyyD��3�uKzxx���@-HOO��7HC����www_�p!u����?+���@M)**���oIO<�����I<d���T<2U���"�
%���/�H���T�L�{�V��6m�f��u>|�m���5"wV�2i��F�9r$i���W_�lQ��4��b�y��e2�dZ}}}����i��&��w���Jg�������e���"u��i�����1�Wl@jj����{��|�����������1�&R��*}�
��Z@JX�|y����7o��I�W_}u���III7��������9��{w���k����/����������T��UDE�Ri}���	H$�a�>}��z�����9��H{�@����YD�&=W�*���_M�"cH����������v�`	��9v
endstream
endobj
9 0 obj
<</Filter /FlateDecode
/Length 188>> stream
x����
1��>Ef�^�6m�7����M*���=�:�G�
I���4��K���<�M\���E���dL�{^���C���\�^--��N"1���@�]=n����z�Q��0CS �6�(>\�SS�|t����>P���������y�.[L������
����k�����[��3�
��w�
endstream
endobj
11 0 obj
<</Type /XObject
/Subtype /Image
/Width 1200
/Height 742
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 67611>> stream
x���	������/E���I�We�F%�/#j4//�
�D����[��(H�]�Mee�A�}_G�}g�d�ag�}����y���r��;sO������t��}���=�wO���j�!eee��m�����o�~�����r�+������������]�XQPP0{��?��vz��1����"�+��"������wo������p�����/X��:����~W�?�O����4_�����S�N%4F�#��j���;���B��c��7������4�	X�6V:!������}���=~�xg�������J���?� J�6V���,[�L��w�y'33����3g���n�:�5\�6V��f�;E�����#T��={����!��|��"4c��-���sg��6l�%���c�������|����G�3(===@�'N��S�L1VC�Ejj��-[V�\�q��#G�TVV:����}��wk��]�z��;7��������a�Y��u�d	'O�t]Q�������6mZ�j��5k�m�v���������c>����g��3����7���/???��X���<xP�
�711���������9��d/�JJJ��������$�Pa)�s�������u$�A9G���}���
T�F��j��(��w��y��w�~����ds��~��wT�=z�$X�hQwi�V���m����Y}�����u	�F������������W����1c�~=��4/�n��u$�?~�njZ��/��RZ��4-!!�u�N�p���N2d��G�*����$kv�����Y�VHS_��Y@��ZwB���@�����<j���,X�\�$��>p�����]�+{OC�OI��,���o�����>��Y`������%�
�Cdw9�$����s�oZ�^�������0���s����<����|��._��P/������O?�����u�V��y��y��������tI�&�����������S����O�>'N�P�����
�1b���6lP/�0`���l�L]�Ai��7N��UK�����-[6l�0���':���+**���f8��T���k2�|P�]��. Y�_�K�������c��)..v�a�*T�b�
�
�\>���>�@�����Ol��5�F�M�����������$&&�:��i�F)#:d��LZ�95N�<��j�X��F��tdzFF��c������%aT9���#����VC��/��B�6��z7o���Hv�l�JCz��Y�@��=���n��,��F�mnUU��M�ts������,�����k+-��-p��<X��N���T�+��$�f�����<���D�AI1����s���g������&�m�)R��G��D[
��^�z�b�
��&����rR@�`��-�-++:t�Z�D���|�����*�����*���~�����$�O�~�$!Ray���Q�F9������:��p�w)�Q�~�#�k�.B.��;Oj>i�$]C���qC�oM�	���,Y�\��2�����6z_�m���Z�X{�$����1@[�O��3f����%��������S�����@�?^-G����L�Rk[T7�]��>?�����{���s�e������^���
���GZ�K�.�HMMU��:����t�6l��Z���C�,�+�����`�J:�N�6M/�����K8~���e&L�������3U),;Jrg[�)	�������5����8p`�%7���c[�&����x��u3�
�{xG:\�|�.0�|�Jj�o$�	 ���*t:�����U��}�����6n���x=I���4d��U�V����	m�BR��@��dggh0��9rD^�`A����HIF\k^m���Q�\�H�����A�\z����8|�p�2:mQ�p�z��5<h� �,�^�<yr����1C�tvD:�#�w�zA����9sF2��5=���U�t�������L��k:L�kC�����7/Z�����;a�����1�|�G�^cZJZ������.8�,77W/�5������,g��5�W�v��)��
��%7m�T�b�����]�H.����.f���W*��m�t�@�������DI��s�u/9����t.?uv��j�^���^���n*l�@��[��G`B��*;��x��!u�����z����5��a��s����	&�b��I�U�������]��2��x�V�^������L�,�p�����=��x����ZS	�������{�3������Ia���t���_FF�.���_������[=��uZ���q�[��xI��W��g�7���R�|p��������-��5�����Y��HalH��;��h4��`��!�-m��-j�5�|]f��9V*���={�O�>h���={�����EJg-#�gi6�4�~������/��2�b�;���>r-��A�v��#94�C���U9�����H>e{�Mrs�>l�0���{�����������Dgk�u��+g>�z�j5��I@��#G�U{=�����)�
�{xG�4�&�((��C��2�g��*#��z�+�w�UVVZG,T�~������\�����V�����m��N���|����~Y3z��A�����������l����uwY��W_}Uke�7�:�+��F��Af����;e��X@V������eC��������5T��we��
��x�����>�`��%G��:YX�Z�z:I���7o�j�K��j���1����w)�!��|P����c���h���g���kYYY�k��a9�{)�]��~�X�x���uX��6�:��	����z]p��F�,*�AY���:�w������.W�gf����da�]�qZZ��B������b��}�\X�?�d^�W�Z�B���|Sa��A~��R�~���U��z��_-S�/_�����dF�/Xe|^}��L>�_���c������������'O�S�S���G�
�p��aoHu�;����;wN<xp��_�)������/0RG���&U����i�l-gi���u�����	Y+��A�h�"�-�����R�}f���:J��]���A����7ov]�u/sl����%6l��Ru�HG�a]�n�`	�u���N
^]�A-���t>(������s�����=z��	&�A�?��m�J-�|P�G�������Z�17`���*���|����z[T������;F��������n���T����Uz�d�K����$��d�r���^G9���O��)<�I�������%���H��b������qT'����Ak�/����S��������*}��^��9���7��]���k�r�k?~��������A�]������H��I�������x���1c�k�K��i!�o"�|��>��[�����{
�d<3��;w��:���r���J��m����ut'�+5,�����G&�Ak#6��^\�_�<��y��B�/��}�����������Jz���o>hMv���{��9
�����o0`��g����^:r��.Y����1��M�����:u��.�|7����V�Y_�`����X��RF?���G�Z��a&��a����}���B��U���jV��
W�Z��|abzz��k{~M���5�#u��9kMQ����78��ZG���O���C�:�I����R�$st}}�f�K��I��O��Kze��%�������b��y����;z�h��cC��f,]�TU@B�����g��z�]��p
P+���5�>|xee��Lnn�������	l�n�K��9���D�b��E�Yz��}���p����V�c��Z�������^��������/�[�[�����q����m�����������e�^���P>X]�,����$�5m��Y�6l�W�K��)��J�����f�7b���Q�F����k
c��V^������x5Qgjj���4i���1�%t�Y�f�)����l}�����m��I�z���gJ,]���=W�Tg#S*�b�
]��j����������BuS�m���2��)I����m����q�FUs�F���z��6!M�rg
���
6�nE$��&z^�K�v��fd�^�������#:��D�y���7�Z�g65��Q�o6����)���nX9r����g��C9R����5��#��
8�{C��)���V'�r����Rs�,� i�������o3s�LUL����j��7�{���y��ik���V�G��3g���*����~��:��u4��={J�s����6mZ�v�,J�b*-�o��}yB��f��e����:����X_c��i���!-a��5�^��x�NXW�B:kh}����GC9��X��9r�W1I�������|����$cZ�|�$����_}���h�>@j}+�+��,�C�:�{>�#9:t�����'^���%���_��q���lQb��W=�
����6�����z�RU��`��ErF,\�P���o�����	��+���#t��i�N@E�L�2%;;���	��J��u���c�Z_n%�~�J��=x'HK���=z8%99Yr(}���4������^>(9��+YI��k�_�8����������#F�n��:�
�Q�V��/^�X�2ga	W9;j}J4�
����6FNX�U�������y����%�����n��
��IV��������,I�			j9k������#G�^%�Z
Y���������{����Hx��}�7o�O�[�n������p`*++uG���s�q���^��w��U�Vm��Q����\�+9�'N���c���ke[d�<h ��{x�$'��>RC�E��m����������������RVV���n���~W`Bjjj��}U2�`���0d����kF�t����m�����c~�����8�e���]#�6n�8����"%%e����-*//��.�����SF~��F�
�v��FRRR����I�������q�F_�����k|������9sfg�����/��W���w�^	�Dm>�x�b��<y���u��W(��t��|��?r	#��I�������5���A�T.++���hp��M�6Em>x�����GO�6����������R�A8��Fa�)@�U>�w���rrr|�3pE>��*	��
94UUU~�����Ux�`u�Ex��j����g����`�p$Dy>m��*�|��!�a!l@��������F>@�������ku�%K�Xg-Z���������W���c���2e���+�������������^>2c�I�S�'O^�t������-_��c���y����L���r���.�8q����'L�0g�IaN�>�Z^V�g�Y����?x��m�� +��^����f��-[�L�6M���8p@�Y�����L�:U��;��o�Y�j�kSJ�������N�>]>8i����x��U�����[�����c��U�=zT��"G������wKZT������Y�F������}��w�(�J���d��@�
����(�:|�T��!��s�O�
��?�*){L�����x������M���'GYNC��	�3g��~VN��;w��R��=)'��$///��'�|P�����?��ZAA��S�����3���&KLJ%�N�PO���z9�g��-��&��@+++��c�:�d{��_/��k���'����R^�LY�,'33�V��:tHL*,\�`��D�lf�Y�.�J22�K��"��������
����:��-�Pip����OjBB���W����[�U5�i��i�H�L��6�$\*�f�|p��u���)�x��*��EI�Pri�m��Q�2q������8�U��T�K	?�fLx���i�I=e��gd��M(�p�YsaEi��Y����V����}�4�d���s�ij�� 	��NU
 �JkSUI���V�����"��]*�����2Rs���������s����AU�_M���J��{F}Pv��j	I��S��
�J��F��e��m�?%��f�L��Il����&�li�W��� �i�d������XHS�����Op��R����6D��i��@��Bm�mC�L�(���yIle�d[��Z����R7�r2����1CXN�$�m��4�������RF������:��]E�:�e�jwY�����h��c!�����#��}����2��~��7��K�j;�$���U5dg�,�u�|������}���"�$��3T�}��c-l�U�%�ta!�;k���d��j��@M���UE�,M.�����HH���?�mu5��-5����?$i��&�����s%����-������$Y�4Z�����Ks��}�u'e�%��2eJ������~�2%[�������jhwilX'H{I'�l��*q5)�m9��/*)����Z�^T6!M��J�X�v9:+V�����r\������O����p��Ug9d���.�.5�_��_��&f��uY�5$e�6�dqn��,S5�%!������-R�����p��4�U�/W��'%���I���eI^��^��I�;�eY�
Y���Ho���@����!�����.J�^�^�3R^��jw��~��TX}P����V�j[?���ge�T��U��[���jW<���p=�O�8�ZI~�G$��N���>�R[�:U��!8t���Re�ddrT�Zv��U�[f���@u=�B�����*,�uj��\�}rR��Jz(GVo�J3]�v���������������r��
�������eG�\�=��
6�'�Dkd�0�Y�F}�km�+�VMn�D�M��-v�y�;�\�A���\������7����L�������[�	gkv�[@����g�������*,-%U@�vHw[��%[G�$P�|P���������AI�l[��m������2%�T����4��,g.,�P�y9k�7\6�:]���.G��(�R����J�������*l{!�����%%%*�Y�z�s��!��^K���-�������/�Z3,��8���Z��#����.Q�����k��tb�Gz������,�v
��I�o[Z�{RG������|�+�
�r19�C�p�m_�������t5}����j�����F��_wb�u��)/����7o��>R=��9���|�+����s���kpI����k�_a����SPP�5WR3��>TF�luW�^��L��'��G��a�����SKp������T]�`AH�������B/:-:u���2����rm�/����]:t&����W�l������	\�%��8�|Pu�I���k�~�z�.�ma�p��R=��j�6Ja�&�mVQQ����dg��m�"��s+���Y(]+���g�g�C���a����@H�Y��v
����I�d$����w�''';W����;v�����a��~����Y:�VIY�n]\M��mz�{R�����f�n��vv�Kzj���@�=�p����5��K��[m�PPsI��_G(����B T�������:Qu���Mt���o��r8����H�;����8G_[u(�u�L�tH�HR��3�&��y����G������
�W�\)���U�o��N��HAZP�\�;D����B����B��fm��\���VT��-���	�)��!��u���������g���Qqf�A��x��U����7$>>�50tg��B���:��n����x����4MBT��:BT%%���	�d��V�����?�����b�Mzg���15�y��������]���+��6�c��a,P}�"G�5�ux��Y��H=w�\��xooH��J�U����
���e�v��;�l�[ ��^ �Z����^�p����94A0�`H��&���2i��5k�H#��k���je��6r��PiQ�/qPc�!�\kk�����8��4��i��<~����5��kUk��^������qvv�(�#���9��j;�nH�$2���}�J�|0����NU��;�q&Jd��.N'i�[�w�K"���6m�u'yb��k?W[��3a����������'^�\!UX�R���@��s��u����`�7��k������+�JJJ���+V�PS�� M��j��o����)���J�5>>^}p��y� �����'.�|0�eJs����q���/��6��fJ��X@��E:T�]�"���D��4��������:���4P�������
6�V�u|�Z?���l��p�g9C��n��;1�����!������H��U����M�������������Z��������#;V��#?PC3����Nv��E�?��� O��8�:���\����'�>	��,@����@���8e������*)a��zh��sm�J��%Y�j�=zT~����Xx]��"��x�)�P�����If�{�n�N���0���yk�����D�Q���=�P������X>h4�zF�`H�`����L��)��s,#5�k��~���'f��1cO����|P���}����������^	B�G�T�RifO�4����c������H�D�9�i��`x�t��~����[?��:\��A9R���z�V���~���F���<?h&������Y���T����l����u?�~~P���������w�[�i�l\O���c>����$�����x~���t�xU���T�/�~S�r�=��. f�?���O����sv��2��������U����lg_�n;s���w�Y��U���^V����8�������FuM�$�$����+\�����.�<E7���V�1���|P���MRs�^���hJ>���*6~�x���,Gj+s��NtG�k��^��57�P����W*i�e1����m/q������C���	��[=��a�������W�\)�FT4��z|Q�tL�6r(�CC���z�R����{�/�������������$�d�&�����t��u��3�������)��9s�Z<�eJ2��?�o���i�N�zQ�U^���WX9V�>z��o���Au�!�L������n��MMw>V�Gv�������{#�F��=i�{���!����V�<���N2c���Q�Z\�A�����C�,/eT�k�b��:�%�Q�J��Ow~c uS�S���!�����|0�=����:������h��S���y������e�>z�7kx	��Z\�d�A����KQQ��_��8�JKKS�WJ[��^�'N���l"�MZ��Q�$�T�@�[>��i��w�u`j��0�)��8���9%s���/((�I������/����(p����>�������������S>({Cu����~J�H�*���4��>�Y�-��"�[��#���L>� ��G^����U����
KB1�����o��A7�e9�n��q��%��~/!����"��	��W�i�:B���t��Nv)��>g��-V�5Vaq�;-C:1�B���h/���`{R�%!!�:]��ji��k�!���������C���C������f8T�����.��g����xG	�I�$�)������.���j�K�A�(M���K]�c����6�4�v��!-CY�iA�#���+�� e$������F�j���L��}\� �2=99y��������w��$�}�Y��m�$���-:}�t�p�+\�����>M�$����JJ�G�U�/��A�G��={�������U���[���U'�)���"�����g���N���j�gL��V�$��I,]�T6VrsIy�jz�TU����U}��/5Q���:��l���n�����#�W�Lr ��*��=���jKe����5���_7��/_.��>��jU��H�D��Z��TC�w^>(�.��4bU��H�?�W��>_�f���%�h�dU���o��
u9X�?g��)i��U�tk�y���a5*f\M-�!��VX92Wm�����8�e���G]�Ud���P���vI������m_��zb��J�����:��=UT��#�j�W}v;vL��oBP�E��a�I�O$2%`$l����*�g��T�5�U�8��X�����w�^9�dc��;c���� �G����*l�j���E^�Cv�\Z�c����JX��R����H�V�iJc^�f*���o�M��.T�i�J�C���g5�X����?�RX>"k�����BZ�l�4u���xV��W�i�8������B�AV$��4���O�
Kb(-���G��V`%]KcL�`��U�q��#��DF'���t�g�2M��ee{ZJ�����Fv��y�d�H������d
��S��>(uv��\7\5��oWT�1��6+u����Jb���lW`��]R9�jCd���d�xRuM��R^e�r��M(��yY�7!�E��,S���n��E�Qvu�$���,������H��#[Ov�w��j�5��M�u���3K�Q�2�A��~��*�S�\����6/�q?+�<�kT��C6�9�������� �PQ�D������
�F���#@���@+)�n�:�X�R��l�������G������%w�sY�[N9����dz0����4Cu�z�C$B�<��8k������iii���eee���0�.����'� F��%�sH����J�=:����A2P�$���+?@�2���9������j���7F�6�6mr}����������������XWzz�Z�����l��]�����q2W�\�|�  B&L���1r���Ls��],��pL�)S��X�����e��u��������~�����o��Q���~W�g��y��g�����>�����#>>������o{�UW�p�
���������b����3f�!����Sk�E�=�����r��W_}�M7�m�VBh�����;	�U�V���{m������%r~���<���&L(--����Z�vm�n�����f��]{�����t��g�_*��={J���GY�f�����}�]��C�EEE~W���S�JtE����~�m�vIg&O�,�����x����u���,�kg�����|��+~8,,,|��'$������
%�l���|P���:��o��l�o���#Gn��Y"g��)��eb�v�


�����^���E���Go��u������i��_~��_����*�������M�| �v��c�LJMM}��������J�����E�d����������Z�����u��n&M�6���������L>(��5�\#y�u���g%C��|���^�s'99�:���s�w�����W^ye���O�:e������]�v�Z5@
i��z���[�t�uzVV�/�K�~����f��e���m�6�O�Sl��/���l�O<a�>r�H�~�u�UUU�R1���o/�`yy�NR���g��={�t�Z�|����#X����wo��:w�,;�S�N���~����rJ�g�}6R����+�
v��W;{��GdV��}}��a��VTT���l>(y�lx���m�.\�����B_*fXzz��O0��}��'���k�v
��/�,;��W_�N�K�������|�M)|������?��Ci�����Y�{��Ym��1_+�l>�Z��;w�M7n�z���Z���|���#2��k����4\�������]�zu0��u�&������ ��U��W��'3?�{�:u�$m����9Ke�\s��8����#��s�d�k�g>Xx��`=��e�������7����N���d��A��ck�V�y$�D������Yk>8g����U�����C��{����5����x���c�:��������'�`�+"�qZZ�������_��W�'O�������z��uh@�l/��_A�F|N�S������9k����1���Z�����ri�o��O����2>�����*_y~��K��W�O?�T��}��			%%%)))��uk��i��=����wc���:������g����LRk>��g���?��m�������3f���k������|0??��uJ����������cE�O?���O�����W^)�f����7�������:���e�T����#u��Z�*���b���������-Z��9�dWW���Y�o~����4=���X�U���Q�������w��-_~�������Y�������}������W+��Dm>��$4��|�����O?������i3k��]�v-Y�D
:z�=�<X7���]�tQl�T���{��+�<}�t�Q����233���?�N�������s�D]�v�JJJ��
��V����|Pe7�����P�2�-Z~
_}i@���o��
�Y��6���sj�d�u�F��2��������Z��W�S�N�|��r!�=�
#���d<�A��|���c*Y�d�mVvv��5f��z��@P>��'����MTUU5m�Tf
:����]���iii����g�J&x����<Y#A4D����7��O�+L�o�|P�1�7o�j�����������=
���A�2z�g��,�6����]������9r�s��s�Z�ju�m�?~�~��������;��������GO>�DC>�����]�+�w
(<q��*�l�2����T5k���u�F�|�%`������$�z����0i�$�,�?�)I�c�����.56�-@4�vo��qEu��fS8�(i��r�-�mVV�/�K�~���z��@*N��T��?9v�{e|�+v�.�rS����j_�����/J��g��K���g��u�I�������k���o�������U��M=��;���%B�t��Q�Y��/W;��-�d��[o=v��uzbb��k�3f8G������������<`<��������U7_�n���i���_��	����6m��^���o��F�7�k�=q��w���~�:]��y����r��'�|�={��fX����]+����_~���CQQ��U3g���k�j�J6��_T�:t���r��q���ef���{��e����M\w�u�V�����H����!CT>�|�r5����&M�����o�1cFRRR||��>(�z��W��������G��{	~����9R���={�M�v�w��{���:@qaa�]w�%��#�rh��� �/��/����J�L�����*��V�����[=���P|���:t���}��W^���[����WL
�������2��������7�|��9���o�z�)�m���d|c��y��gn���k��FvB�-��)S������f��e��������xKOOw~���|���7�|�%�\������{��7o^�U$&&>����_~��^��Y��]����y�5����RL
�G��R�P7*�5@lR��%222l�[�l)y��W6n��|��{��G~�$�u�3g�l�����^;u��m��I"y��K�����,,e�O��/��B
�G����Y�f�E!�b������,��sg)��k��)�������d���m�8p�EI:v��1=q��9R��n�Z����7�Y����)))�^z�,$�l.�5@,)LJJ:����?����T���B�6mjK�:v�(��x�
�rn���>r�H��#F���n��V��7����:u
��!�bYH��[o�%����N�tI/��B��t�R=Q�y�����W�����2�����u�m��&{��a+�v�Z���I������u��B�o��&�GU6��K=e���jP���\[����YYYYjJff���`�[���|5+��5��b����w�}�]u�U_|�/��G}t��U�����M�4��C�q.����Y�[��Sz��-S.��2g���$��m��AMY�~������,��_�Bf���'����F�q*��o��7n��}��#�6m������%O�>�R�)S�8���+��1[���_~Y�\w�u��g��U��6m��2u�T5���S���X5�i�m	i��>��M��Z'�<y�����%{0`��(eTJ5{�l�r�t�"����
=��'��)7�x��pvv�Z��������85�����E����O����p�����������HM	�������YYY!���������5�j'�d��(%&&�J?Hk���}|d���ddd�j���j
���"��-0�x�D� �`R��[zz�-�����o��'A�ob��%jV0��(((P����	������o0�H�DL��x{���/^����+W����}��z��I���_�n�L�E��}��k|#�D	�
fi0�H�I1o�\r���?����g�I����L�'S]s��y��w������Y/\�P
7m�TC���;�:
�[o�U��9�:q��2�E�����u���:u�M���V�P��"F�-��� �`��b$�$������g���7��_?[���;����zJYY����8q����.��"YEJJ��8o�<)��ys[�(��D���'N���T"��NLL���K/��k�d�k|#�D	�
fi0�H�I1o�_~�z���~�V�R�����+d��/�XYYi+_XX��eK�����n��)>>�u��^��3g6i���k����od��
����e������2QfI��Ja�H�f����[�����Y��ik���k��3�4�A����7��&M�����^w�u]t�dRW]uU�N����[�����K���E��.���{��g���V�����c�IFv��J~��kW�}����RL
�G��			�b)))7�pC��M]�QHk��k��3�4�A��$�
@$pm�I�� �`���7���&o0�H�DL"�D��D��"
fi0�x	\[`�3�4�A��$�
@$pm�I�� �`���7���&o0�H�DL"�D��D��"
fi0�x	\[`�3�4�A��$�
@$pm�I�� �`���7���&o0�H�DL"�D��D��"
fi0�x	\[`�3�4�A��$�
@$pm�I�� �`���7���&o0�H�DL"�D��D��"
fi0�x	\[`�3�4�A��$�
@$pm�I�� �`���7���&o0�H�DL"�D��D��"
fi0�x	\[`�3�4�A��$�
@$pm�I�� �`���7���&o0�H�DL"�D��D��"
fi0�x	\[`�3�4�A��$�
@$pm�I�� �`���7���&o0�H�DL"�D��D��"�^Tf�����x���#*S��]�hD��$�
@$pm�I�� ���*';��Aim[���]����F��5~W-�i0�x	\[`�3���U������k&h��x�]��Q���~�4*i0�x	\[`�3��0TH������2A�O�o�nY�w�}F��$�
@$pm�I�� �BRUTX8yL���8�����+3"���=�k/�����{#�A��$�
@$pm�I�� ��U\\8mb�Cm\3��YS�KJT��3����Z��{�U�}��[c���7���&o0�HF��������	��u�7%Ut�T��e�]_��.|�C��	U9����/DL"�D��D��"-���33m��	>x��n�,*�u	'R���z������n�����_DL"�D��D��"�K��y��w��|W������B[\II���Y���++�|���_W��Dfk�G��$�
@$pm�I�� ����/�x��K��@�������U���i��Is�~P�gw}mK� �`� ���$�
fiV%+�e>��K���e������_qq���Y�<��]�|����T����F��$�
@$pm�I�� ���u+3_x�55���2#=B�-O���y��Z�'�m[�}��l����$"
&o"�kL"�`�V�i]��O��cy�U���CUaA���/>��]���E�gJ1��"
&o"�kL"�`F,GZ��MY�>��	��Uy���*��M������-��Z�}��<y����],G�#�D��D�������]��^�}8�~V�:�o�����fMq���'�����	�m�#6#
~!�D��D���X������./y����)~W�G�v��y�++Log��O*����A��H���7���&o0#v"�<yv��qM�r>�g4gUU9���&��Cu��\���%%~�4���4D�
@$pm�I����H+?���~W�L��7d��V���9=�{v>xw��������B�!zo"�kL"�`F�����#9=�r����z���R��Y8yl���=�_�8~����k���hC���-0�x��5�*N���v�.��KeI	~W��nY�������������8Zc�4D'�
@$pm�I��h|�&��^���qV�k���g���������+1�����U���f#�4D3�
@$pm�I��hL�V�z6��������)����
FV���9o������6���T�9�W�S�!�o"�kL"�`F����������g�/?Y�q��4���������������J��0_��ih(�7���&o0��GZUvf���]���%��%�������]���
���L=g�>
=���o"�kL"�`F�����������k��	>�p��e~W0*T�:��������Js�y�d�j5i�����x	\[`�3b�U������gv��T������`4*�vI��/xe���+�0�2=5rh�����x	\[`�3V�UL�K���.�����������DJ���������.����-�#���ih��7���&o0��DZUQa��q��u��*�?��
6(%%�K�g���gw���'������u6�HC�@���-0�x�
 �JJ
�ON����(����w�������Ko�gwa��J�o��u5�HC#B���-0�x�QiEs��?�'���N�X]\�w�������^~������S'T�d�e-Qihd�7���&o0#j#M2��Gp���������]�F�|R^�^�C����^�������6��(o"�kL"�`FFZ��yO��%��]FU�]�F�� �h�����
3�y�p���������F�x	\[`�3�*���g>�W���cF�������v����++�Wwa��w����44z��H����7�%�V�:>��G\��v���\�'�P����:���=�;w,��MUA~��DI�!Fo"�kL"�`���V�~u����&��Teg�X7X����������-s?�Q�o���}�4��
@$pm�I���1�J7��z�)��"o�'�����
�U�dN�������/>V4oFU��1O�i0�x	\[`�3|������^{�=��2���� ��6�|�O���Z�}����>]�kL"�D��D����V��#���'����S'����23�p�����{%�Y�<U�hNUQ!�4�D���-0�x��"�|Rv���3���U�H1PDN���9���������{]�/�����
	\[`�3DZy���w^wMrz�U�r$�k�I���
���������������.)���h��
 ���$�
fD4�*����M�L������#�^��d����^��.|������*���P���&o0#B�&M���o������<y��Q�����QC�j��]�������&!����-0�x��i�N��y�=��R���z\����N���gwa�{�Gd4!�#����-0�x��i�gN�}����l��zY(	���K�G|���=^�av��I��wM��7@$pm�I����H�L=��E��CJ�o����A�FZ��EY�x�����6���T�9�o����7@$pm�I���c�Uf����=��S����cU��9#�"��O�����.���%kW�Ua4h�
	\[`�3����������t6�3_x�d��z�*4�H+..^</���=��S������W
CD��D���0"�*7� nh��\2��)Y�<BUE�Vk��'���]����Js�y�d�jcF��C

�������'��������8���o���K~����{��������������/����5k��k���4�����o�������`BBB�[��b���o0#�H���+�ez�;�m���;��d�U������^Ya���
&��LO5Pg4\��7TR�����[�l)^y���7._���{��_%�s-?s��&M�\{��S�N��m�$�_|�dj��.o���2��?��_|!��#�A���Y�����������x����

'�N�n���.^��e�:�kZ��=���p�!����Z�e}�*�-��J���������~ �����}�����������w2q���������$;v���8g�)|�
7���������,I������K/�Td6�_���>"�`F��V\\8uB�_[���<P� �/~����U������#�����/�<�23#uF�kC���n��������<��W>���t�y������?�^_�`�|�i�����c��2��7��-��[n��#G��N1b�L����l��|�M���S�`�"�5���k�E���@�VRR4sJ�����Q4g����a��5�,qgn�����u�x�7�@�����{����$�{��������zKf�y�����^x��2k���zbvv�,P&�^mh���?���{Z'�v�m2�G���k����M�4���	�	���E�][�/�
fxEZ�������p�dI�W
Z�\��rs
�O�|�����O>X8uBUNv��
WL�
����$�{��������n���QA��u��EO�;w�z177�Vx���jVVV�������,X��V8??_�
<jM�k�S���x��H+Z8;���.�`�{���**���h����V�cKn��t��z�l���Z���ZUU��?��y��������`yyy�&Md��!C�y���eV�������{���.��Y8))Ieg6lPS��_��$&&:�����Y}��	�!!��K�\[
�7�a����2�|�%�����

��*�H\���3���������g*�>�*�������������w�yk��U�z���O�V)��)S�y��W��-z��/�,S���:g��g��EM���O
L�:UM9u����,V�hxCBZ#����� o0CEZ����rv���Y0vDU~���D��kZ��
9�����e��"�vD��z������g/������<xP�T�g�v.�K�.2��+��S�x�	�r��7:ggg�E�=ZM���SS22\Fvj����z��'oKHk�#�D	�
f|7.��qiB�k�?j�a����U��L��h;�����fSU��j �������_~���.�)���o��F��`VVVH��zn�.��s��_b���(A�!�J6��z�w��/��3�� ��4���w^��.l�2��e{]tB�C�]����s�(Q�pmA� �9�[6d���kS9o����~W���kZ��3���?r�gw�����QU����P������������=��S�7�i�FOQ�cm<�����i_�|�Q����w�$����
�����/?���k������w�l����d���X��'��w�x���������7�d�5+��M�Yuy��s���;��:{gM?�����G���=���]A ��]�������]^����J1h���~��&���!������]�v�7�����RQQ�>R_������O�~��u�d�,�.��w]#��FmAT!�P_��'e������}���l	����V�bi�/ze���������a���:��x3,�������;����??--�:}������M�Jbh���cG[��r������#GZ'�1B&�h��V�[�n2�S�N������_���� �Pw���s�}�=��vE��j"
�D[�U�H�6 ��������+^:������"�o��E���e�?��=���Lu�M�8�V���]t�%�\����'��7O
7o���<��2�'?�T�C"��NLL���K/��k�d�k|����xC]T=��a7�Vn�oZ�>�4���VRR�t��~����;h��	�(�����kE����_�'I�����������e��R��W_��iS|||����*3g�l�����^��7�l��}��A_|���_����,,e�8p���4k�L>.��<x�z�����F��X���_��Sq"%��;���;��'���'�`F�GZ���y�������������]M+��������w���,//�|�E��g]v�e��s���s,911�������/���k����<5�%�������RRRn����M�����k���xC�*N�����kS6�����'�~�H�
"���
������`����1P�5�k�Z4�x��pm�I��Wy�t^�^���x�,���Y�H�
+�����7�WZ�V^�av����\�w5��a����kL"���������F�(����%i0�!FZUaA����/����_�����jH��S~�v
1�D?�-0�xC`���C��g��<U�e}��!�`F�������O>��
��]��WK������?
:�D-�-0�x������/��m�l�f��X�z��|#�`F#�������S2�}���������<w����1��(��&op���)=<��.�`��%k�
c�D�hL�V�{{n�wt�����
�}3�����
@�����7XU����*��w�d��<T�����L����iU9��S'd<��++���VN���T�k�_��\[`�����p����qim>�`��u\>�3q��n�����@���w-��#���8���kL"�P]\\8mb�Cm\2���-�]/+!�`F��������c����.|���b~�4&4�x��-0�x�qE���?r�K��c�����qED���H+��.��.��?�g���~W����x`��D����y32m�2t�����R]RR��#�`F�EZe���q_ftl��]����S�W�d�]��)��
�\[`�����x��f����.�:���8+%�`F�FZ��U��_�]�����]���fc�� ����$�-�/_�:Ja��wN]UP�Ui0#�#�������������O�������D��������Q�rY�s��d���,�eU~^�+@��"M)Y�<����.��~Y�.����o"�kL"���u+3_x��A�@������	�4�A�YU�:�?b`z�{=�;w,�5��7B�� ���$��+��6��']�m[��X��i�2D� �\�/�z�����-s?�Q�7��j6<��H�����F�t���W�um���_��n�JD� ��H9"W������]��cE�fTF�Q�F�x	\[`����������E���T�*F��"�v���K�e�����Z�
�U~`��m�7���&o�FYRBv���3��W�9�o��4�A����wy_�Mk�Wb�������**�����x	\[`���'��z�Xn�*N�����B��"-T��-�����/.|��:F/�
@$pm�I�[�V~89����M���U������H�DZ��������z������7���&o
T����=�v�s>�V~����#�`�VGU�Es�ev�h���n��w��� ���$����8����=�L���������;"
fi�%���,�Q���:Q�x	\[`���T�:am�Y��z�|���H�DZ})��N_a�j�wu�� ���$��A�L=��\�d�]^*KJ����#�`�V��������=���N4"�D��D�E�����������Kwn����"�`�V�r?�����G��:��x	\[`����3����	���7��3��zT�r���dtj������(�<��N������u�9V'�8����L��]M<�xT����QDc��#j<���x�P���CDE@T@�n�n�����@��Nw
]�<�]���R]]����~��xX����7z���y N������N-�_���X�H���	�S�m��!?�uEy1��M��G�TJ����~�8	~��O8����C��$MX�/>�t!u���x�
���4!o�S��������������'Y�.$
�@�������?a�r<�b@o��7�8�F�w����#A���t'��.PH���	�$��6%Si	��<�b@o��7��z��=��������f]���4�I\��O,�Is�G��x�
���4!o�h��
���H���6� �����H��4v['<�>�u9�y1��M�}��H����#A�����{YW'$
�@�g*-��T�J��"����[�&��&��hy������^��a�N��@!i@�&��qC,�J������[�&��]����;	�������jX(:$
�@�������k)��������[�&�Ml����1���?�������d] %H������w�g�����+����hB���O:W>~��H���;���R{I:�4���{[��>>�u9�y1��M���/���8��H�w���pJ�@��$M$U!�-�L��k��x
�
���4!o��N�X1u���`���6�4�e�dI:�4��d^�6�>]X��)�7z���	��,)��w:�\��${��@��4�I������U�&�.�# o ��	ys���X1{�����E���X��4�Iih���z	�r<�b@o��7wp:�:t����j�\c�}�z$
�@��S��d}C��=Y���7z���5���q��YG���2�/d]��A��$MTe}�Xz]M�U�������[�&��	w�*>�8TLo����:��H��T����#��5��ay1��M�[�pJE���G��!}�gO����!i@�&*���������7z����N{x��7���z[������!i@�&*N���~��<�1����[�&��5Y�c;���K�YW��4�I��������u9�!o ��	y������y�_���5����&H����Mi����.�1�
���4!oOU�W��R����HP��M��uq�I:�4���2��h*-a]K���hB���'��|�t~yNQ��:���H���tE����b@o��7;������#����y�XW���4�I�@�?�v��������[�&���SWU�_�8�
�@w*�uu^I:�4
L�%�M�S)YW��b@o��73��C���U[�q:-��|�t it��b���c���ay1��M������qCG���S��XW�;�4�I�C����;_Mg]3���h�r�Lr���o��%1j@������5RN����a����[F�j������[�&��M����;��
�{W�/�ui�I�I��4j���-�S��6�7z�$��U�$�������j�|�\��:�%��H5UWY����Y���b@o�$�7��"���N���0�p�:��|���!i��d^�6�>]X���b@o�$�7N������\�����h�H��9$�&�_7K;��t�u9 o ��I
y����
���\!��F��@�O
IO���T�b���V���u9 o �����f��U1y���$fN4��NZ|;i�9�4��/$Zo���u9 o ���W��)�+9��#>�'���N�|5i�i�4���t�4���L�������[�&���6r��S-O��v�����4�����B�(S};�z������
y1��M>���������%��kS�c��I��%
<�F���	�
~���
y1��M>�7Si�r�,��`���5��XW��4�pHe�Zm�r
w�XWD�b@o�|!o:�z�N�����6&�uq��/$
��F�����������
y1��M��7}|�|h?'sI�_���XWV��4�H}��H�-��.�*�
���4yo��w��;�Kb�x������&
��F�I.�m���������[�&o��RV����\���������7B����l��k#��.��
���4y]��G"d�������W�YWO�uI/��1��f�Ic�����y1��M^����Y���:�K��9��=�KyQ���!iL���eN�d]%���h�������d.���k�2XW.����@�X)�����u��Y�C	�b@o�<?o�=���v��K�wm�~��A#x~��7 i��wl��h��3X�C	�b@o�<9o��x���/V�Y*���|�''
|	���!���nU�YWD�b@o�<3o�E��G���5��c]4�g&
|�������]�N�.���M���8qb����:uz����{��_��W]�v��iSuu����������o-[�|���{��]�]�YYY��
k��M�����oXVV���e2���3�jde���������F��2�����7N����d.�!}�gO�������
Ic�j�*����|��$�7�g�y�7����+SSSCCC_}�U���������[_��t���|:i��.�:u�{���?� ���#""�5k��]������42�l������:�L��^|����W���W���###]�E��#}�-�!<*o�Gd��w����:���-�4�aHC5W����O��� ��
4���n��a�������_&��y����?v�X�|����%������?����0��srr^x�2+((�,<|�0Y�C�v�����k�#2��,,,,l�������F��	����7C���	�G��yA��b���<$i���4�d~�,
�:-�u9��H�f��=n�8�����'c�=z�.���~��g�{�����.���!+�m��n�5x�`�|���v����N�o���vaHHY��cG��g��I������s�G&$�[�C0��(���['sI�X����0���D ilU�Xh}�W�R���N�y3�l��#Y������L����7'�8q��P�P<���da||���.$��~�m��o��&Y�`�����f��)�
�n��{`B��(c�7��=����%��M��UI t6�Ic��B�������I9o2��|����?{��c��O{T�<��1�:ITT�3uT*�����3TQQa^R^^n^c�rUU�����Z��=�"�����[MF�|���$V.��
�������$�1����u����F����H0o&����4""���s��-�l�b���`h��R�[����$�����d���dI���W���6������K��?o^������+��B>Z�dI��7j��H��C��f,)V~3��\�G�n��hBg:�4����4���kY�#.��-66����������v+<|������N���4i���-�%&L K^}�U��=zd������K����K����X�l��F��B�����z�E5o:�z[���$����R�Ag:�4�t��[�{��r�%���T�������U�V�m���_\�|��
yyy�!��C��>c���o�[��������_w\Y�P�7j^�u�V��\��~�N��G����'4j��H��[���?{R>����$���tZ
[�l@���V�6y����+���&����oo�v������Ow}<XQQ������Ew���{`E�����7������:���b.	�@g:�4O��b���kv�������w�^�[=KJJ�K�v���W����_:�K�����N���(�B�X~���Y�#:������<���g�y���'�:z-o���~�����r{�R����2���v��3q�+��c��q�y�b�
��z��x����qy������?re�	�Zm����&����{P&F�j�2��v�,�Z6�S��/��l@��!*���4md8�r�"����}�C��)�J�j�����B�G�h��g\��>))�,'�rg>z�{`B
�<��y3�=V-���\�n]j/�����$�Ch��Y�����H!o��_'����`���9b������}����{����v��G��5��mK���lw����7� �7m�d�0$$�,������AAAd�����r2<�+��{`B
�<�`y��kv��NCl��
|Ow���7@
���$�C��8UWm���f����.--�]�R��������v�j���c�����M�,���1_��[9''��^h��eaa�eatt4Y���^�<��$��_z����^z�l�l�v����V�Z=����W$�G&��[�s�7}�Yy���e��M��F-H������$�s��d9��?J!o����,����\������'�����>������=���F����3�t��))))qqq={�|�C�DDDD�f���k�o�����5k��h��M�6����+���#�Bpp0Y�|�}����d#vk�]��|��vd��=�'�������
3':�Kb�D��"�o��t i�C�c��������<� �����u������?��y��dxH�N���~hh����2^���g�n��{��QQQ��"++k���d�d�d|�x�����@V#+���/fff:�VXXH�m��u��Q��@�Dzx�&��SWUm\�8�����B��e��Cg:�4�a��i{t��z�	y1��MM��.6J6���`�o����(|:���y�o�1B�p�u9�C�@�-@Sc�f�u�b�p'sI,�k�����:���y��
+m���b@o�\�����w	��Zs=K�:����H�G���n=^�����!o �����i�����k?���^����.��� i�F���r��NKa]���7z��`��S����d.��+8u�:����H���\��r��\��u9C�@�-@S=y3�+fOu2�������e��Cg:�4OS}!�����y1��MN���������%��>�_��H������t�G|�ys�
���49�MwL>���`�Ou�V��g�:���$�)|a}�`�:��	y1��M�y3����<��\������:���y ���6����.GH���h2��S**W/q2����5Y�k_��t i�S�m�,�{��+�b@o�H�n�[)���n$(���6����w��H�g�};�f�6��y1��55Y��u�,X�v�R��|
:���y&���!�b���y1��������������|:���y&�\f{�!� �	y1�������][�zw��KbH_��S�����t i�b��G��a o ��>��|X?�����x��uu�����$�ci��Y:��	���b@o1�*��w	~>>�L������H��2�/�=���S�����������p2����5�����H�'+3�r��8�� o ����!��^�sI�����k^y:�4�I�d��!�#�rn �r����[@5����
u2�����RaY
y:�4�I�d�����#^�g]���7z��$����u2���Q�;yv+#o@�t iN���rT�'�a]���7z�C�wGY�w�������;�t}�
�@��$��UmXi96����u9�B�@�-�4��#?r2�����N��o!o@�t i�&#�z����u9�B�@�-�X�E��SG�d������"o@�t i�O���r��N���� o �p�QWm^�t.���dW���H���y�������l�R���y1����t'��}`?���]5v���
�@��$��U_H���b]�[�7z4��w�b�(�����8Ey�6��H���y����Us����y1��@=�p�r�"'sILN�M� �t i@���������c]N�!o �xm�^�����l3�}��#M�&�t i@��tq��3"��.���7z8��H/=���`�k8���-#o@�t i^�S�m�e�{��+j"�
����L�%�yAN���9������#o@�t i��v�$��m��i"�
���O�t��G���U_Hj'����H�����>?i�r�y1���?wJ>���`��;��;���t i@��-Lr���TZ����@�@�-g,�[��X'sI|�
9z
�;�
�@��$��TLc9�i�c]NS o ���T����G����n]i�����H�����>8�u9M����[�I{$B�Q��$���u�����H�1��8��uE�����[���zV���N�����SW��w�
�@��$����,G=����4�b@o�S�c�����%1}����N
����H�wQo�����d]N�!o �����^����\~���4�@��$
�@���!���A���YW�8������������_��E�;���}(D��$
�@�������P�O<����A�@�->�XT��9��\��4�=fR�t i@��u�����Y�u9�����[|�QW�;�Kb����YC��$
�@��NMF����~�X��8�������G��g?��G=��Y���%H���y#2���/�.��7z�/1����0���`���2��t i@���*�������u9�����[|�(W-_�8��l���.����7�I:�4o�O���<3��ry1����������%1����)���C��$
�@���^o{���q�uA�B�@�-^�&#]>�#����?�:���@��$
�@���r�l�s�z���
y1��x)cI�rn��H��L�%��{*�
�@��$�K���Yo�	�c]���7z���tZu�F'sI�X����� o@�t i^�S�m��{wXW��
����]�gN�����K�7md8��\��H���y/��)���f�v���y1��x������:�Kb�N�`]���7�I:�4���>h}����q	�b@o�|�JY���\�G�A"��y:�4�I�^&��������[ o ����/���~.	�����Y������H�W��:�r`������!o ��U��Q>v���$B7p:-���y:�4�I�j��]�c�b�D��4y1��x S�c��9N���h,)f]�[�7�I:�4�f,*�=�r*%������[<K�^���O�DG~T����8 o@�t i�N�g9��N��.�����s����>��K����{X�&�
�@��$�����Xo��&�u9
@�@�-��XT��>��\��)�YW'$�
�@��$��rn�vy��uE�A�@�-lq�������%�w�uu�C��$
�@�|�������O:���� o ��t�Q���o���?��d����H��Z��rV-����� o �&��WL�xY�j�ZN�f]���7�I:�4P��f�'Y�n����b@o��$����s	*fO5>(b]���7�I:�4�@����qu�E��<�b@o��v��~�8�%Q����4J�7�I:�4��Z���&���Y��T���������G~lY��;����K�
y:�4�I�
��x�-�z�.���7z������:� �Z:�$����6�
�@��$�G���h��l�9����[����U[�9�Kb�p�����cy:�4�I���-�i�����qy1���D+��n$(�K��4��7�I:�4�A������X���b@o��N^��QN�����SW���1�
�@��$�gpj��!�Xp�uEN o �qJE���N���9�XT��:���H������)�������qy1��Ew,Z����\~��s�K� ����H�/�F�>�?i$�r�@�@�-��}�h�����=��j=��<�t i@��KL���qS�c��C�@�-n����d.�E_y�q� o@�t i>�b�h��\{x?�r�!o ��&��q�|�`�D����r�ui�y:�4�I�1����g��&�.��b@oiN��Z���7��s:-��<�t i@��c���l��J����A�@�-��?/��n$X��0C�M��y�
�@��$����,w�������
����:�\��hY�wg��0��y
�
�@��$�����X��o�X��3��F���{��~���7k��U�V;v�3g������������e��/��r�=�����EVV��a���i��y�������=me�L6s�L�Y�|�|133��?�Q{�L"��}��H�_7��'K�Y��M�7�I:�4�c��a{�����p)�-77�����3�<��o����iiig��?~<Y��u�s����E���;w&+L�4����N����;�O2�s����2�l��]xx8�>H�h��������C>z��W�^MV&_!_$_���t�G5j��I����Xx���c�?��==�6���H����$�o����&�B�����P��7�4��g��E�����|�����c��%M�:��������YfWNN�/�@�c���&+w���|�ve��������,[�jE6��h�Q{`B
������L'��7�R��4���H�������+�G�e�Y�c%�����d�d�\�R��� �^��vyvv���>��s���cbb��m���p
<�,�>}����������6m�]Bv���n��3g��������F��	)������Z>z��tC�U_Ne]�C��$
�@�|RMF��v �n����B�


f��%��?j��@�3�v������w�}�ne2l��9������
�����'�����_�p!Y���o�.|��7�������H�7k�L�l�
���#R�-����*W/q2��k0����7�I:�4_e����w`���O���}�D������y47c������g��T*���;f�����������$&&�n���*�G�����{`E����>��l�N����c]�/@��$
�@�|�j��9@�����yB�y�����}�������Y�fd��u��2p�@�Q��=-K/^l~/��������Yrr�y�����K������W�GK�,���F��)�;����9��/������$��H����*��x�-�z�.�	)�-22��~������X>|��<���w��W&M�d~g�e��	��W_}�q�G��7��~�2�4/).v�&y�Y�M�/�Q{`E��������~��O'4�Iy:�4�I�Yz�����f6��jI6o�����:����.���3�:���3f��~���Z��%������
������P���[���8}��S�N������_y����d{���^~����I����m���H����H�S��e9+P�n`]N-��m���N_�Y�x����x����Q�A�s������+ ����w�u|oL����I���fr�n�����u9V.�|���'��_4�d2�}$��EYG���8^�������=�K�2�'��!d�e]�.�|Cbbb�->���^��)�' 	��Re��0�t�����
H�y&�4�I�m����������\����e������N�{�:��7��[o=��|��������&�j��#w��p�#+R�-���eza:	V��7`I:�4���:`9U��<�u9���j��g��Z�u�g2�����jB�G�h��g\��>))�,'�rg>z�{`B:��TZb�}��$�a]��H'o��t i��$���3��d[�t�v��2�����`�X�j��~�+�%����>��s�=WVVf�����d���m[20�]>x�`���fo��Y�i�&��!!!da�N��V

"���������]��#�-�����q:	2Hd]��H$o��t i>�b�h�i�6��<q��y0��[7�Fc���x�;v,XM�6������|i/,�~
����^x�e����������d��^{�n�H��,�{����_z�%��)�����H��?�������	��-����O�9�N�������I:�4��	�i���
�LRlR���k��h����c(;��5s�ac����W�L������g��=THDDD���k�n��}���k��i��E�6mrssW&�Gd���`�2�J������F��\�v��y@��i�@��N����������R��:�����GA��$�����Bp�����k��g��8��^4J�k�:u"����[w��=**���dee
:����7oN�w�����yZ���
d5�2�
�bff��j���:th�������G�|��T_N��g7���d^f]���j��� i@�&���r"�;���
��{��S���8�e�j�:L'����
<�t iR��NL�����
��c�Ew����v#���#0��������B��$M
����T0��e�
��3��XR��`Y�o��Y�V>�7�pH���I������B�t�U���7z�f��D1�������C��$M"����}+�2�7���C���O�����9����:o�x$
�@�$���%�9�_7Ve o ��-�Fm��u��[���T�������wA��$M:�0�r�A��Lj@�@^�[�S�mo��t��K�^I:�4�P-�o}c�������������2��s/����t����^
I:�4��������o&5 o ��-���d����+&�0��g]�����I:�4	��m�=7����������UL��q:	m�^��A#xK���!i@�&)����w%�n�_�b������x��r�4L'�u�"o��4�I���X�W�/y1xxo1��.=�~:������d]4���
|�t i�����g#����@�@�[8uUe�R����+b:	���y��H��(�&[NH4{wP�;�b����O<#�0����0��������A��$Mj�Q����<����7���S�c��@'�I�n`]����
I:�4�1�e�''�?i�y1xTo�F���{�I�0���0$
�@�$�b�(�)�6��]#o �-d�W1e��e�~�h#�Y�B�����C��$M�4{wXNTA�i�y1xBoQo�t�	y)@��$M���wmOW8�����7��R�yY>�#��$��?w�UI *��$
�@��I�g9i�����_�
����p����M'��I�0��$
�@��I��z;��Y�������������a:		���@��$M�������z=��"o ���TZ��3��t�B���Xt i@�&Yr�,����tv���h�����v�tR�c���H�dU���r&�Z6��N�7��b��#�>'�I�'�����Xt i@�&Y�W.Y������N�7���E������te�E�/x$��$
�@���-g55i����D�-��Sm��l�N">N�=�����@��$M�T��[�m�����G�
� Ro��
��yN��X��$$
�2�I:�4)�'���#��7�="o 1z��T����N����*�����Xt i@�&iz��y���u�w�����-��bE�'�Il�tP�2�I:�4�S�����n~�N����1���xk���@�
'��L���wg��$���t`�s'�I:�4���������
ir8y��8�tg���(��n��v�����U$�/���Xf��Y��0����{W�_�"�g��	�@��$M�8�����Xx���
|e&Wc���t{�1����OCR�q���*�_E�@pn�8��j�*L'.�����H(�&[N~4�;kU�p�T����p�)w�1���������q������ o 8w�e���������@�pZ�"�g��	�@��$M��w����cS����:�7�����0���_����6^l���t}�����i�2NQ�Z����$V/��Ub�	��N@�t i�����O�����|c�>�x�]C��%��l�l���T���xM�c!���	�E%���I@�Xt i@��;j����\�������������<'��/��1�=��OM�s%���D^[�#�?����[��*�}�d:�?�Z$���$
�@����!����0�0�|f��������K!}	�
����~��i���\�AN��W��_;�bp��hv�:�k����mZ6p,:�4�I�\u�q%a�{��7�3zR^��>��O+���r����y��sj�H�	y1��[7��G�o��]�Q�	>�2�I:�4�LZ^}���4o1��5^a���!�b>���������
��YN�tq�"�\�
�Po��U�k�9�Nbn ���&���@��$��9_���E����������2$�F���^3f�2�_�p_W����}��
�s���D�?�b��������{��7fpo}��E�����@��$M`�bN����7|o��j��gH��!�_}��������M9��
Wp�8�E^����
7�mO�x�^��{�A�@N{�I.S�
t6��w�N��c���HZ��8UW��tg�1����.?��C�[�k�L�g��������Wk_"*��^��%}r��@�@��E}P�aW��`����N��c���H���w8�	S�Zc�d��������?/�c�>��?�T������7y���O�Z����I�|��@�@���Xx�b�h'�I����H�8�H���9Q{�����v����}wY������j}��_71v���,�E�c����Xt i@��k�k_�Y��xkR�����pk��������~��)����G���{��G��-gP5i�oy1��r=r�|�GN��8��:�58�H�!��+����0�.�7^�c�4=��U���b���]�e�-�QU�W�}i�
��*U����|:	��uu��p,:�4�������������=����'�Z�N�~c����4�������B�t��>v���o���,����
z�~:	������K��c���>��'�v�t���n_����/��;�����m��97�����
<���D9g���$�,�t *��$
����i��\��}�O���>���8�W/��N9/��:�m!�n�+��G^����$7�Y���2�I:<=i?��7H�3%w��e��G��\�	�qO�x<�����#/�/��ui 8�H��YI{r�/���?7_�i���.���S)mO��En����E�Wo]�d:�i�\;����Xt i@��+9ej������]�������\�s�"h��DK�K�-��@��d^���O'��M���]������V{���O��	}�O�L����S��et6h,N���
��t�-@�t i@��I3�~v����n_�{�����-��G9��=�p/t6h]�1��^N��8o�z���H��n�4���7Q��q����I#-�^���Bm�
\d,)VMv2���e�Fm�2z���H����=��&����'��KD�����[�����Yt6p�fXY�.�O'��4!o@�t<5i��������/�����p�������qj��ot6��!�f���/�����-��	y:�4���,�J�������B_�K��?/e�*?]�1w6�X[�%�9Q����At6p��i�B��N'a|PT�wq�4!o@�b����������s�&��������c�����[0����u����qE��nE-�������O{�� ��������Q��T��~O�N�A8k��7�I�>�g����p�����Dnf����z��#�^u�<�����9G�_�:=���'�w���9�=�
lq�r����L'�`��/7�Y���H4�&�����
����'���Y�<`����R��_��]7���,��IK�O�pe������c���Bw<Z�Q��$�/$4j;8k��7�I����������_������~����$��F�����Rx��U;f�_>���w�h�������Q�����_tf=:�E��	����}�8�D�p�4!o@�VO.�������w����t��CB4]��0����y��\�5;y��S��`M�q_��1#������5�anO*N��(��7�������q$X�t
Bo��7�I���)O.�e
����Y?]�{d�C$�'�!�]����W�>�.s����0�������d��9_��&'� ;��,��,y�82�+���q0����f�[�&�
�@�$�g��u���+����\�s��?$���!X��8������
Y{�J	s�K2Xj��~���a#�������v}��������S0� Y�F]����M'� ��	y:�4_c����p�>|r�O��x��EH��(�,��(����!�����v���>82^�q_�#�~r�k�Y�q����2+����'��}����y�&}r�|H��$�w��d��-@�t i��������
z�o���\��y�������#w����o^���g���� ���o���g�!�%��{&��f6P�^o{�f�����C���$�)�:^T};���$��4!o@��5�\���������_�;�\����P����G��o�~`��
���3Q�q_�����f��c��K/�&��&���&�r
�����F�$E)���d:��daw��4!o@���4�?���!.������
�?I[�Fv���������B&�/���,�������iCo�-H L2��'�N������)�
@"���*�}�d:��+�0�D��[�&�
�@����s�?]��X�����_���I
�e�r�&m��8m���o?��"���ljJ�B2�$�J2����*��Q�i�Ji{:g,*h���7)P���d:�O��<�D��[�&�
�@�h{r�o�p����QL.��Ik����K������!{�������z��c��&,�.}����N&��cm9�_\K4��Z��]M����j�����d:�=�E�/z���H��jd?]��R��=�����4����������[�6���Qqs�h�����O���x��-�nE�*J�&���*X���h���~��&oy�U���r�w"M'� ��	y:�4�hr8�1S�
�����^vk������O^�Y#��>��x�J5�L���I;o&��������%r� �>����IK�_��;'�������r����n
�\f{����J<o�J�pF6���$��b����4!o@����\E��x���,c��!���������$��{�e�szs�����?=;���IB�������'g�_����=9G��O�Q�_�W�����4�r��=���H$o�a*{��3��t����nwGo��7�Ik�Q��.s����.4^nH{���K��~�������uO��5�����)�+s*��?������/.��E/�n�$�G�s��/SV���}������o+
���M�����3=���M��/��:�n��9���/:u�T���!88�o�[��-_~��=zDGG��~VV��a���i��y������=�C2�l���d5�2�
�bfffcK���=�_��]
�I4Hj��B��$�gj_�k*\m�5�x���|[�/�u0_�������?yc����p�0i��CK/o�<q��������}h��/u�y��K��
+��������qj���=�OX�G~�o��/� ����������_{��g��?�h4�;w&�M�4����N����;�O2�s�~DDD�f���k���F�-Z� #���\���B���/��z�j�2�
�"�zdd����Q{)0����8��t
��cx/�
��n���\E��x�`�|&��{���U������O&<9i��<7]�&����|�Y�b��<�&�1&i���M�g9���>n�@S�]�3�qK��q��������?��W��-�����F����/��/C�=zt����c��u�N�^u�����?�A����������/��XAA�e������:t _�]���yLJt������Z�"qq4��=�������w>�D.�[k<�X�y:$�4����Rw��"�������������xm�)�k��NNy����L
`�4�^u������y��Ww�N^12���Qc��u;<*�TP���+3���s������z%�����I`y�NJ�?W
�O���;�������W�C?�������FR�P�i�&*��M�f��<�������>��s�?�]C���m[�����������m���;Y�i�&��!!!da���V�9s&Y������i���U�_���d:���N�A��e )����I������(��3������;�K�Oc�{��i���9�)^{��/�J��V�)�(�y��&���7OK\<�����B��>82~����J	^�������^�W��z
?�g���7�����C��-��%v}�����9�����LMMME��	D��=�������-'�������N�8aYHF��?�<Yo��������~�v��o�I.X��n���D��Y�fJe�6��=��2���f;��(L'� <k������N�d*5������p��������kgy���8����MRy����M��X}O� ����;q����K]7��7�b&
5�#~��'�����������=�Vz���D��%J���_��������������w�W�7�w��������4�_t935��;[�48�����4��f��aYe~ Q�����c��Y������%111v+WUU�?���5��#�*����t��N������h�w�5��A���I�I�Wfp��M������!�����������U�=��d��q�e@S5-iz�����<s����sV��q�{F�������^�}��DaR��V)�s����O�Sw�����������+���t�}cL���o��[�&g���	�����`h��Ya��u��8�|��gO�����%�[�v\9;;�<:KN~�j������dee9���+����,YR���#�����qC�L'�|����`o��7��C���]w����{>3z����{>�X{�g�gu�|���wX�B��?i��ko�,H�~3�����������7yv?<z��YA������7�(`�a�������\��q>qh��C����g� ��/�������h��G����x����yhgS������T{��u�t��I�w�X�L�0�,y��WW~���yS���7/	7/)..v\�l��F���o���pju���N�3���kWYWgO��B���I�~�)���mu�|~d���n�����{>G��-�J#��L��e���Y��KwU�SJ2���\���������&���{���S�7d���?����e����
A���g�W#����}����� �%�o��_���qr1e_����d�2�n�3�����*�}g����`^^�yHu��!�Og��A>��okY@������++
��BCC�K�n�j^"���'%���^���#�����A��t�����4�$�[�!�
���42.����@�=�#�i�4$�,�=�YL�_rwp��������7���=H��{tU�����G���n��}�c�L�_����[���{.�4�~���!�<il��~���W����o��?8�?�g�K��5O����y���6�l�/��1�������]VTT4j<h~n������>PNt���YSL�<w&V	�`y:DLZ�=��MEkM9S�����^�����u����d���&��
���X�����E�O���aB
��D|b���K�]���������d9�Z''��t���['����L~k~�_����j�/��o�������=���5�4}�Y�)���w��+�c(�/���8��K���ui
�`o��7�C��U�����p���c�����?�����<�{>���(�_(���?�������;3�o�/���3���Y�+V_�^�p���;
<�',]%��*������7����_�Ga.���w~���{F�'��?��.��]���m�5���x���+��nD(���8��`NF���@��^I��~7����)e����_���W7GU��'v{�<�����K��]>��WJQ|Z������{���4���q�_}5E��<{F����|��ysO�
>v�����R/_b��}���S���XX����5���^7�n-��O�u[���mT�;���U7���zI������YN�������8v�
��7��[o=��|��7��|j����;�M8��Ab�����P0k��H�x��k�GXW�]O��}iCQ���������������l�l�l�l�v�z�}�?QrN]:�/9jc��Eg�O?�hdLP�C����!��z7<f��'~�fC�����L=��w������c6���t������2
�nO���W+��nY����!�����n�`9i|8�_c�����7P��~��E��<}RRYN6��|�N��E{���w���w'�Y��8�-��tX�V{����{>��4f
0\����|�lL�g�=����|�U��I�����,J~x%2�����^\3���>�������'fLO�n����nE�*J���>��?�$�4�T>�Rk�������{����0w{~�o���a����Ka��d^�Ao��TJ��G��B�(��58���~��g�{����2��G�%_l��-�.<x��EC�7�x�,��i������{

"���������]��#xc���I#�L,�l�GM,�"	�`y���3�+=h���qR?U�_
	������6f}l�=�+��)���G��$�u����g����9�2c[������%�M�QcF�����"��������r*�*�+[*z�K�U��l>;�OX���o������j)��o�k�7����H�Af��<�b��
��}a.~K�ykp<H�;��3m�4��������0���������-[�,,���������������'Yh���������Kd#dS�+gee�j�������"��=����6����]$��!o �N~�T�����1��!�����������3�T����5�Y�B�W\Uz������CoD,N�4%a��c����>1���;��������K)����/��}�i���������|�W��!���j/�	2�z�_���c���|�F������z-��������c\��t�F�Pg�����q����'����8���h:w�LV�2e
Y!..�g��O{�����h��Y�v��������f��-Z�i�&77�qe��|DV&+���o��|�l�n��k�����6a����/$��������q;���"���y���~�)���;L�_�������|�6��m�>��{>3p��x�]�������'7d��:%��3_�>�������}F��dPz� `�a&lR�u��i����0���'�{������/����}�J�@r�0>�>u'��T�;�b*-�=�4�e�|K:y3O����o0�x�S�Nd���u����GEE�������C��Y�����.00��>O�Y��FV&_!_���t\����C�m��u��Q�����T���^7�����[� o������J#L��3�mL�_C��������Y�n�{>E%�U\��>}?ew�M�3�/v2���7y�{h����3��~%twNt\��ly�/�_��=MS����_�����L���/~M�q�#[��A��������y�T����4�rJ���t�+��7��9����;����]��4!o�3���������{>�����3zs&��N]�k��v2����Qziv��s�7.J�����>�b_��OF���sa�����y���r�T���P����-���x��QA��������`��o�������Z�_�����+��_������z�����|�w��%97��
q�,X�i5��z���IWMY�=�;k���6���W���Qw��~��
o�vf$�}w���^9x���k{�J	s����v��7f���s������}�����\��z��w7�W&�����������w�������F�q�7�Q;�;�,�8������������^rju�_���x'���2x��H�b�H�]w�0������A*z���I������u�|�1���@�|�7��m*�*��^���Ho�����g��2e���szE"��o��iS.N���F��������Y�taxt���9,}2����B>��������/���['��x3F���,'����\����C��?��'����*.�r��p]��j����Wt��V�4�(6�q"�-@���j��<e����;�x�}C�
p����[�LE��,�i�|"ivl�}�2w���jT���Qc�u=4r���������mw����S��o�u
�?]\�4]%���}��_�G~�o��_�>��0��Y�j����W;OD�����}�=18����r��\�E��{D�|���E�D����L,�_j�}�f��eX���u����u'���k2�d)�t
�hB��[M���=�e���xm��|�������p��E��}��|�c��MZ�������o�X�&�����OF��}��l����I��y���a���:��Vv����/l�c��w��+�������v�T;����.U.����p3�z����o���d;�][�X0����t���+��z��V���iW��Ts)�X�~���4!o�������`�����{>����_����~u�|n���S/��$|>id���,Lzx���6d�����q�{D�p��������z����N_|�Y���w��O��)�w��i����������N�q��?����{?��*"}O��>7���
�e9����X��>��X���.������B���#z2�ssX����'n�~��1�&9�X(3����[�&��Ci�q���{>?�������|�5^�^{�g���{>i?X�3I����c�����.�R��q_��3i���*x<,�M�e6�3+j�\�����9�mS��������]�����ew��� ����,'��+����t6��)*TK��9��J���2|���������=�5w?��92���B��#z2��������E���nGb�������hB����q���{>�����Q�{>����s!�(�S]��Owx]�tF�m��������U��������p��q�O�����~�/�����������x��>������T;g��[�{oP�~���
�n���u�
��i�D��ws2�`�W�^��".���������u��k\y�����o<x�f�1��0�;�]Y
z����V�]w��2��O���
��v���u�|�2o�*x���f��I{2�+N��wl��]��W�85����B�����������=�V���������$M~��;�_�^{U.lx�l�.��]Z��(f���/��_�_�����3{�#�@��h���z�����uwoWL�lb��
N,�[b��X=.��a`�����ug��|k(E^-0���������A���@��e5�OUG_�!�,�i|��4!o"�������;�x����n�����{>'�
Wq���&��/l�I�ty�����}y����c��/f��g�-�����R���{�=�9��o���N�[=�������������u\\G�����D�����=�<�&m�m��4�Bq�!�@ 	�=����;���ygv��.� �w���g�`���������9�<J���cP[��P-g����~���J�`��^��V?�RXI-�}���K���G)��x(���L���V\��B��9dQ��P��`5 �e���|F���3p4������Wg��0-��jS�C�,MF������d�5��}��6�����m�,<���l��8��9�BF�������A�]+��:7&����i*S�l����Qm��Z�
�P�tV7�]��m���L�����Yk�1	��4�K��������D�A��<��~+����j\�����$X
(D@��\�gh.jMb��:�vx��O��9t����3p��|�[Z��=��0�<�*��J��J��>*r�}n[7W��5J��Z�O���Lf�\��������	����Y�@nGP�	��Gu��~Z`���w^���3��P�7tMu����$<{�kb�&��(:d�{�z�e����m��Z:8���v�o2�N�����	V2�\�8YL�]�Eem���B���y���Len&>���C��s ���Zm]u�o��}q5i��5r�
=�T��BP��<�n�E�&�-���������_��	��A��@h�a4�/]����?����?8���&>4�`I=c!�q���a���'��lT����F&2���^p��0���������j@����W�4��e�t�~*i�(���|�E�'>�'�>�1C��s <����k,,���v��`�z~���o������m�p�d�u���n���5���X������9\ i���D�c���TF�Q��5�K�,��dGT�����~``���r�g����5�9��0=�a��n��'� �3����X���~���E��J| 9S���R��X����]p��
�A�j@�Gt.T3MaL��wX>�����X*i��t�����T�9��ZZ��-�� �,Jq�o������������*�Q�;
�gs������Sh������z3�=��mPQ�$s�GtL�
���y�J�w��
z���zY����Qy�O�C�u.�����F�t[Z�(��vK��	T�y������e������B�@�����v�5����5���T���*����~��v�%W�:�s�	���N���������W�Ur�}�b�����%��Wr �#���������(9���#:��|t����������4��8�6�<�;�L��i��z�cc�m�7�%<����wM,�����&:���u�!Zf�)�<D�[���0,������
�'Ed(8f�[m�j�1����t���.�Den��'�B���q������t�����*�	�����|��ng�^J0�zn��~���y�������3I���4Z�Pa$���|N#�
Hw
:��|t��W�G����an���Pm^��9��4@yp���{�s}�m����P����7t�L>q��E�C���\�aM���S�1������!
G���?q�C�`5�Cx.�0�>�����4P���#���.�d�m���G��_W��}�&)L�y��Q��S�s?z�ZPYJvBZ�n'2���|�TF�A��>�.|�L�`]�MZ���2�W���2����kW�����
zB�o7��F	.^��HJ��V'�y>)�V��AI�el)k`�r(��9W�V3�Cw`{(�fx34�2A%������jT�BQ����������?�TZ0�H�M4�[2���F��r�o�7��R/9����������7M��,
N����j�Q�7
3@.��l1��R{A�]F	����t�2Jr@�	�#<\A�1
"4n]%]�v�

�
�01�~�l%X<��;�$:j�_��G�����DAcKu3�O���x�w[r�k�_!B���������%���C���V�b&��������J^@����&Lc������-�
y2�o��J�>� �0�j�}J�������S�Z��'��o��������4d�	��EqV����J��:��4`(��u����;�6{���
�-��n:�<��dyWe�J�cxO�R�H�%��-��LR1�/��`}�Xg��j.A��!�����T���.:Oel��&�B^�C����t�^��:S���J{�A�D���FXf�\�7�rv��^9�>���Ni������,I������tVMl�V��cQ�-�;�l� �?�����}X?b��$V�XW�����-*�4@�P���W�L{�L�7����n���2J0m�����2�a��v���d`7(qli��|^�"�{��wy+���&��j��7N.S�I�\��vR	���p��w��iT�6�D��s{t�?�~szC��}�R����
9��;w�:k���{�j��5�"5W��T�����!���x.:�%:0Z���K��d����0C��K|J�`i�|�_1W����{�\{	����Kf��e2J���_6t���<�xac;H��Tc_�r��{�"�`��o�Q�"��(���eLc ]nD�����"?p�����IT���S������s���u��x�=!g{�Q��3�p�*I����6���jd�4��=�TWnD�,�lA���F;��|v�:B�<K��G��P����iH ��1K�K��5�������U�7�'��6l3����\W��E[���`��vM'~@��+Pv���l)�cB���a�3.��7�3.B��!�@�MX�4G2��t�q*u�(�;�e �/�*�*m]��TY1-��j���%�yMi���%��N���w����[��kG���XC����C������Xk������ m�a����y�K�7'G�'-��!���6t�J�C%q�����C�4@��S�Y���(s�
x4�/��y�%�������9]F	���{���p��������������l����;or�^�`5C�>��E�IL�]x�J_G��,
~e`A>�E}C�.���27��0$�Q��F���E���}��
�}b(�l����8sf��K���s�/E�~E�c��g��$��Hw*��s�d	,�@-���](�G�����D[��������L�g�t���x~��-]��������U���[����"�)N�������6��<��8YL�;]�Eem���B�p�����yt�A���iD�R��U�`��Z��[v��>�]���<w�l�\���/�];�5���g:�����g��X
��P����q����K�\�Q]�.����$���I�rr?�"o��@T_���� bXY08h������F�K`o������%���d���7��1QF	�^U����.�����C���G�H�_�f�[~��
q����Rc�������O%�E|2P���8���M��2�������d,���Q�����7���A��M�A�y��3����s=�n�C��wG^Q��;�":�����������(��d���A�G�w�O%K���H�r�n��������J}c!�e������<g������\;e�z����-<!���}SE&��cv��
V����n��$�K�`5FP�4�1�t�*e�(�k����~��P�S���t�e���g(�	�C���E�fX�-��%�����}XZb��?n���1�F��z>����"��b�L���	:8F�������xd4Yo&��P�3*�F�%������,��^aR���
��fS�����~����-g�1MCu}28y����:0Cd*�p�o2��K�>��N���[%S��ZJ��u��#��v�5����5���T������U*�*}=]x���C���H��fA[VcA@Y��lWI�v��q��Z��gw��sq�X���u��~n9����TN����pc��A�����t��x��Q����/�l1���|��(s�����I�@�<�s(� �rW��m�~YZ�3�t�������.��Se�`����De�zc�e
Lxe)<���n��u��
Q�,���m��m�=f�;����`��'�KE�Q��tI=3d���g0�.t�%*s3?Y����|>/��@���N2U���h$jV�*�v7��8�<�:�C+�\%��
��V+B�Y��V�;�t�����&���|�����v�Y������y}�\�\T;\:s�H�>^����0����/]�/�!�{�Y��*�n���^��]���� ��D�]����P�[���>Fx�����;OKn
�A��e��M����y���K|�{�;�B�Q`�(����A�L;�e����.�Ng��g��?����8�JYD�f*���$�b�1�����W&��y_K�T���Wu��:9���^{���9ol���W�����������*�Q�?��%v���n.G:����9YoB'��tF��b����s(�����`QN���
6X�
�.�-���\����l��*�����-����I.��:����-��Q���W�W�q��qZ�4yW��7�6�B�$QHq[�����No2r
*�@c�M��CT�BQ�����)�4��Q����{�W<�����"�*�1�W/��������p�[���zt���������n,�����4waB\:m�#���H�]��t��p�����B�g;\:��Pk��~C�|�c�D����.���$�`o�0����m){D��s�"����Q��Kf�}�����-r���r�;Yd,����v��Z���sWp�+~?��e������7���5f��>~�������7������_�T��t�N��S��8�������U������������x��L��r�}���o<��o���U���}C!���p�d��u+���]�K���yU��O�t���N��(@�[���,�����2�cL!</��LmX*�{�:�����������
���n��i1�����#�-���GU�Ln�XDgQ�"�H�I�@�����;`��j�]���6����F�����&75=m��8�\���@�'�������65f]l+sF�i��=-{���'�ez���i��m
T���M��o�����OF_7N��^�P�^��S�Cb8
�*e�C����K���b���N�C��*���
t���.��Q�>Jv�N`h�i��in��0��H@`�7`���s���cf_nO4��PWR��t��([!-\T��dU��T@��5At;\hxOp������6w�)w�.��X7k�R8]7��l�%�qj��{�~�>/����sw��������k����v�P����:9��r�������7
XE�EA���cN]������IR9��S9��5����c�u�t������6H�v.���N-k��&�	q�L@�(�yk�N��H�G��.�'?@W�p��9���P��t=38�4`x��o�?�4�Z"�7`����+�����^�E6nL���\g[e�����!��il+4nJ9�=�-���H�V�g�\��g��������;u\,U�f��K-��9�����<M'���4H`E<�f����tu�����>�,h�h��Wi��r!�dO���^{����w��������M����Y�T�Z.���H\:#P�
�����;#����7��kl�t���NE���.�WP��
�N` �
(���?�%��F`o���f�@f)8S�!��N7�5CbA�c��@X�4G2��t�q*u�(�;Q�������/+C�g�4���q):d��q���������9J�_������7�������u}xTq����"sI���:��M6IG����TTc��~9�L%��2���:�������v��A��KW�,ls�B+���Ky_)�1��4v�t��A�.#'���;���>��K���p��Xi����0JvD����H��`�s(�8����Ke���
ZT73��eC���Z2W6n�����0e�����A�E�IL�]x�J_G��"
~e`A>?��f�9��2}����z��v>�/�x����������+v���e����.���1Q�e�����&Z��`�F^�o��*,$������*�
L,3��[������K�
�s���p�<��������S�'t�/d����3��%�Y�[�vKJ��U�3���
B���f�;t��Sea[�t7�
�c'��=0�(N6S�N�hQY���i��w��}*�w:k]r����7g�!Z��B|�1����;�<��?���{Y~����v����?��hz�����Z//������w/v���mt2��$>�;7/�������o0!�����.�z����p���u��t>/v���,V"�.�9�*q��YF6������e�O
6��`o������x2��{l+�L�Q�
����3��_�2�3
��2:g?�4[����_�T�oT�F��S���R=�6�����z&�������DNqB�P�������-o���%fq���~1�����7M��Q��]&������O������{�7��)+z�����e<���1�����xTXXay�EV�"�����K�������.�����S���E�\��
`�4@�P�y����`o� '��^����+�e�.�(�-8s"��B��:��L!j��0����;J�,E}-
����#���.�d�m��8D�)�	�����9u	��EA&��'��o	81�m�<u���?�<����/�V�t}��8Y1�q�=������G�����=x�3-U��2�S��y��V����Y�|��\*�����N��������R�O�o`d�,
P4�+�9i�iq�
�����1����A�IeU	�0�
A�~��t�I*m%��(h���EK�.��O07��,-�������\��]j��p:�`���Gy���r����1�(�$��.���9U!Y�gR�������c�2�b����[�cv���|}��0�s��^�(&�������nO+����Q:;�t*>J���$���d(�q?�{���� �
0���(�6�k�Ut��}`o������f���1�U�3����Nb
��M��d������L�
:���T=~@���/��t�*]n�4!����������Wa��|.�xw��E���[./���������F^�K����]�\�������t����6���,���+�k$���:{����9�C{-KW����8�>�G���KK,0;\:��YAD�p�$K��
`�4@����k��%3���A�g����i��*�U'�I'q����h;�\�=����.3�sb�&����>I���T�L:{/]z�����W���Va{vca`Y��l�K	7���[��o��Jy��iN�V����_�I�e��Q�P�R���y6���)������G���Xr�6�,��L�����t��S����.74;r��������U~����HE+����f�L;8�Em��Q�+����;�9��b�_���:�z�5�����op��sw[r�FV�����zY��w����������'0
�X�
n��F	b�.�{��'E�cA���**��+ �-����
:��.�%��MLm+���<$�3�0����@���%���������6R��W��S�fL�M'�b�0)N���e���t����J�%�PVwq��w��iT�6�D��sC�,e?a��x��%!qws=�&�<vq��������j������Z��69!��y�����~����2X����q������Q��1:������>�T����
�������}c�U&�.�;�����s�oT��[#~��r�;������>_�}�5�R]�J=r0s�	w�
���\,�U��z���g"
'�Y�Ew��_�G��/��*9cS���U��K�X�K<	�%��tQp�(<��?��J.���D������N,Q���wl�0x��S��Ch�z� 0I)��-����Z����`���C��A�#4��\����:������T���,��'�/s+]|��qBm)�S�|JP�RQ�h����|�P��5�j�����a����^������`z;��4��9��E0T����	Ug��@�A��r��J�%(>Jg��W
�{���V�\?zE���='���L�y�N�:n�����^i_�M~��.�B�l2�n3�������=hE�P���N9��8wl�j{���
��	L�Hp���B�H�}��9�l�z'���D�$Vmd+�BM-�3�o����-������E��m�@'�9P��H���`�(�_�c�6�����l���*�SvO��3<�2��i�')���Q������K��XB�S�i1���=]��g���b�S���S��Fj��d��<C����kW���8c�L'������F~�L����V��d�������Yd��-FWA�>D*
w�D���+? ��v;������G�%�%��J<���^���@�����s�k8���Gm������q�M���������J���-�����.�%�P,�.�|(/_����wG'/�#�^��-T����}/_�P���^�.�B��^�����M)�����r����j^5]PC�S�\�8�V7���6�[�9��G�O���?���P���L�����A�7��:f�Zl��E����'q����S����LX�4G1Uw�
*}-��(���J?r�o���.�&��>�>+9�	��n��Fiw��u7�;>�u�u�|����Ni���e8x�$�e�r{Xrp�[C1*�F)�(�y�@����ti<:����^G��������t���teE��
�/���/��h_XKV�YD`E�uVX#e��U���DG`5q;\hJ�Vz~�8������������D�
����D�`����
=�e����FY|��Y�_ �9���]p����:�k�����]m Q��7x�)w����7���[D��"�t��X�1;�-|��8�q&��\p���W�����%�h�O��4���y�����#�u$�%��:����	"�D����/�y@������#s��ql�1N,"n���tz9������S�@.��K����x�����6�{��%�#d����9z��r����|�F���S]D��v��C;<����Z����i
a*n��������	��,�>��f����2��������X�%�ey��������xr��v9���n[7?}�8��{QPBmF�n�}f��x-�&��xx��"��H�wt�t�E�+�#���_#����z�v��${�����p�9+�����*����n!l���K��*�K�RB'Q1�d��E����W��-����^�/�`[��X�`]������?��?���
K	�)���w������>�=��	V(X�`�"���@Q\�f�Y#/��Y"��+��=�5�uFD#o4!_����-��zU�th��w�c�q�F>���t"���k�Kb���Y���S�5�Y0qc&9�hd�����<��kd���H��$�^:�m���F�!��0N�����X#gU��S�&�T#K6��F��&2W0�7��?�� �\��|����1'w;���S6��_�|��S��R=�+f�rc:W�J�K��(p�@�I�0��Q����>���������V��[~3��\���`��<w�Q��p�������k��.�b�S����,r����K����|�!����S{"����R�K��b�����6���"LP�;*�CMC8o��A#[�-��>n��Uw[�x=[�P���L�@t4.3�jZRf_&+��W:
���e�XhK�BmR�?����X�hp"��J�e�=k\�*������#�\RV��F��-)X���^����x���Q\6�v��E\����mb���s�����,H�mAT?.{,�j7�MO�i��5�_HIC�,;�o�������5��� ��D�z����{������T�\Q���}��EQ������1
��H��k�mY�eQ��]/���
9��k�/�+���~w�{����Z����|#���[�V.}�����.���SYo�t�K�r�����}��}��"��%v�LC��
�
�A�#��y�j)��=l�ZG
o�	%[��=n��&+R�:��U�|�Z����]����a�6�f�x�ki�Z��m����p�8��U(P�[�\��#0���'t���7���(�Nb�|aj���	�VWM��L�]r���I%NE���#���JYD�b�M�)�KYz��.��6���Z�xh%���]X�����jy��)�kW�T
���da��V��\��E�_Y{������� m���n�������]:_A���p�t=��uP�]�K����_ =8D��:�d[y��C�[���m%���MLy#I�Y\G\
������D���u(��"��unT�K�eS�YT`�( �Dj�I!��3I��(r�'N�1D���ZGtl�Z�
��I�W��U�_p��e�rXK��/�Q|���b
G��q�<jK6p�lx�:"5�k�u���}�
���/����F^���F�	�
�A�e����F������[�M:	sCew(
Y5Q��5��q��.P�[��i���*���E��R��yG�
3�)�+��my���-e��	vy���,��/��U���N^��W�U��������`f��T��T�.dB��U�t�t���1X�x�������N���|����u
��47p�|=��\,�/"���5r]9j'��e
d����h��j���Uq_#��_���#�������^:��hd�D�5�|_#�F���V�5��r��4�hd�{����/qi���'9~x��C#k:�O9�#�R��jM6��F�E��w���G�t�G^�iy�q��}���A�:��p�Jo�F���g�*���k��Bew����
LKSmC����Sq�D!oX��(���J[A��`*-��0$P�q6�P��O��
,�����K�s$Bk���?�������n�"�=��O��7��r�'�����rP���8���]:O"�-�x.K.��A�c��_��2�K�c�����=�X�D���[���u4.����6)XY�p;
���4qHIih#����nRZI�m%��p���J��%�����F"�%������-)$x.�b�.)�����KnUG��>����J"�q�|\�q)#���RRRJ���%Y��]�����&�:B����=s�l���������& 7�0�	���p����W��VR�?��_��~��J[M�b�n3��HX��'���������$����X����_��&��}�,���#H�l��y��oIXj}N=�I��oC��(/%�%.������H�t�K6\:�������n�#.�A�P�-�E�yH����0��U:�`i���,�O-�J���E>Kwu�N��>�~���AE�c��ib�M��#T�Q�w�]s��/�5*�*}-]��TY3-1H��<k���*�6�����W�,�Dhm�w|�������W��2�}��@u�=�t;������j������PE*��E���<r�����k����,�t^������[�.�F(����2��B����vK��
P(2�se�E��d��,��Tv7�����O�������������~�oRq�R��g���Lk<�Z����ZnCFC~py�}��A�5�c;�5�y����V��ORf�n�x��z��a��ka@|MzE�2tbm��YXmy�$��/��N���K�$�1��[�.�� �+�6�r	P�j�,
`�7@q����
H��
��c����-�v�����'����K���{��Y��q�}D��C�O�27�E��{��H��(��cgTU2_f��3��_�.���p��q���;�N����e�c��@Ik%{�-h'������2�q�����X��/��d��S��G�?Z���B�L��ih`.�,
`�4�M��E !}qF������wU�
��2R��M���\����:�����mT����� �����Q�[��KL���A����&�.��4�*�M;��h�����<v�1U_�2�}��{�Gh]M�y+���$,�6����O	�x��:#%���K�� v�\F��h�%p
w�|[��9����<y��3�D��#0����X�&`o��I/��<��;s���b�s����<��i�g�m���T�*~�(�m9H����?���t�S����Y~�z^Sfc~HE�C��a��f��������O�_���e�������C���36M�s-��L�k.n����TF� ����^��K��|�+��;�w�M�
^���� �=�a����3�d��+0����X�&`o��n�8��hKW%��o3UV��n�FX�4G2U��
*}
��(���K���w���w�%�L��d��4mBNaKYLu�GQ�y�����a�����Y�������:����r�6�+�,:�>��X.�}�N;����p�K���HVtE+�C/�p��N5&4�.q���!�Y�2���vK��
��d[p���
��*���Sy�����#��i
a*���cT�2Q�Q�r�����J�Mg��Ku�z/��A
[*�k����K#�r�u�o������c�D���}s��m�?z(��V��e��wqh|MzI+[��e��\:����y�M��i4YoF'P�JqFE��qp}�s�`i;��l���m�C��3f��*[��1-����#��i�G���jT�_���E���A�E~N%��sT�2}��q���[�yM����q��~FiwO��	9��Ge��z�)�?�7��9�/���8C�t;�������"��h����B���������=��lw��{z���N�Q
�{�#4>B�;\:}����(�G.�
�2���vK��
 ie�
=�����KvtU��;���s����'����Ku�L��f�">���#��K*y>��t�!�����}��C��v���<�:��(�"��R�
������v��8�����E�{��T����r�n�g@YTj}N5G~
��PM6*� �Q�������(���L�M������)\�u.j/��>
Y�&.�Z(���N��s��e;�����	��o�"��'�q��h�NW%X�d��S�}^�����8����(�C9���1��o��Et�!���iB�>Gw��dl�����gc�e����|�D���@�E��'9�R������o�#X]^N0��r�,��I+n-��xz��*T�N�T�#�0!�Q��;�IxL����'�0�B��K���.������S��\�X�`i����C�-xh�o����$4�����2`� �gZ��*k�P�J_O��*
}S�/�9Q�x*u)�w��0c�B�b�=m��d7�W&8�������5�rv���)�k��~w��������������h��c������D����mP�	�i�Y�D����:�>:8F9BOR���NJ�t�X��w!��d�1��%������
0����X�&`o@_�l.?����h��A�o��:�xY.����<���VT�
:�Si�4�!AU�:�����q5i^�!�Y�W���/o�?:G�����c�����'�tt�o��x�+�L������P���dv^(�6�f�q�n'�Xt���_��w�G(M���>���;�����
�#�9co�tO���|�m�����2���vK��
��mA������"� �j� <X��pr�z�L��=H%�E~)��~��P�?Ri����L�-�9	j���jN]Z}n@Y�m����;�Q:��N-�����j�����[��V
�t)��E��gQplujQKy����e������.!�C��MR�=�rp�R�4�l/Z�$[��d�1���}/K$�����[�0����X�&`o@/���u_��~�nDgN�������4���.���vR��Ec�#������R�����L�����zH6�[r��#*\
������3�zn���?�7(N�MsZ��GeO����Fiw��B+���y��|�T��T���H�t���I�d�3���~$���L��?�A�'rR��������{��*�H�%s�`i;��l����Rz���D[4��}��>����8��.]t���@�O��#�1�J�Ig��swC�����V&��{���r�J4?�����y����&��\��kk���Hm��[V9����u���c���^i�#��w:��g�=���P����~A��.$����IP�(s��F���d�I`ps�`i;��l��O�t|�7uU�
�	����AT2M�L���N���b�,����/:W�.7gv(xPHV�����D�����NW��os���<w)��s���u~��]��`j���QS�R\���J'q,�=��������m�l1���U+<��2U��H����7$���R����9Ew���+�%��Q��G��vK�,
`�7������Sb���Q�5s's�l��;E�-��L��]U������v�o%V��/�Xcv��v!���"�6��$�:��z��S1�w�^�s`��F��=�c��e���gi��[����&G��G���!��$o��Fd2�$.?��x�D���,:�!�<� 9��"oM��mQ�=u��LY�(��vK�,
`�7�[Zy���x�v�m����L�0
{������%�t�n*i�(b�|�=C����P���L�-��D�H�%�!/�"N����|�����������
U|���k:o�����yW���|�-5w�r�� �Y��H�c���2������q����x��7r>Hr�E��d'���2 �� `.�,
`�4�M�����dQ��1)s�(��esE�?�6H�ZQkScO��27S�SEa�����'T�:k']r���6�* �*��8�V��v����k�O.��;�i�������.�9}����F�.O�c<��pZ�����k/�o?�������(e
����z:�������Q�}S|@/����ze�0���`�4���6{:����[5�Zw���������N���T������T�O��W�q�ot[�W����v�K>e��m��w:�`_��5�j�\7�Q��q{�_7��7���h�1��/hkp�����z��8��G��W�x���K�JUyF#�w��o����rd�y�D��(�
e�d��NqG�Ve[�Hs�`i;��l�������������?�y����/_������$''�7�����[�����������'E�v4,k�,���Kg��rg� l@��L�+]�KN��.%^B�����&���P��.Sn.��I���M>��o��a�@$��[������t�>�_N\�p��7F�?�:7���{�'�L<�r���j���{R�OR��GR�Y������Aa�(�����T����-������X�&`o�����E���#�\�cee��<�����������~~#~;������Q��m������fF��a��nNj�e��~�Sn�J��0���.:Ggm'G���+
|�r��d���1��{{�w���k._�p�u���e�K�pX�'}7�j�,�Y����l�����'u'\������l�}���n���G_*<�l����'�/�$��+$��D�j��E�@�.(?Ue�V����`�7���vK���e�'�|��c�aA'�,..~��gF��K5����cXTT$�ttt��7n��>u�!���6�����e���l�I��������t�q*}
I��A_�^������_��z��}���g\��s�y����v3*�~��7�r�J�i[L~S��ISw���_�]�����>�D�x-����jc��G���s98��m���NA7��[��Q��b,Q�*�B��������>0�l��X�`i�������Vm_}��L����q��%Kzs�����{�������oq���~��cs�f��)�l^9�p�{��"�bZbHP�-:{/��P=��Y�*��d��������w�?�s��i��*�?mp�����i�s��xS�������l�v�_��<�3^G��7/�s8���X��y�T����O+_�u.j/��
��#��I:?��d/��<
7"Y��PI���aX`l��
`�4���6{c����X����������~�����;455=��S�q``���S�N��������)�*��E���@���t���)7%]26P������D���)>/{�������XS���Yu������w��{U�U�<q}����\�Z�����>�}~����O��w����o�5���2=�+;i9�I�py��b�����!��&(��$�+�'�Y��S0�l��X�`i����ICC�cb\]]e.���I.9;;�|'''I����K�K������`����f�L{[/�+��TZ��������}_��^�z^ORNO4Y��1U��L������e_x>���/d���u���#�z������pC���#��|yZ?���+���q�dR�2#)�r�Hn��b���K=
���	��`i;��l��&�������M��_|_:}�t�7����������RSS%��e����J�t�o���L[������4�0��$�g�N*y�(�;Q�+�~cr�_H�9����������p�e,�
�=[wp���Z���Ht�Mt�st�d4���t�Cr(]#g�R]Q~(�L#�5J��3��`�7���vK���M���$z����p�������n���M6o���}���]/UUUI�occ��.q���u2�D������������S���(�7n��n����������;��^O;�b�r���������}���������H�oM�&/�JsG��*�T��7�[6{�,
`�4�M������X�����	���_�K+W���&+V������������$�711�e�2N�Tz����#[�=�|�&.�������}�]�=���x�'u')ws9��7Iz���<�����"MI��d'��C6�J���k(B���	]����	��`i;��l��&=�����j�z�����z�QEQ��{�,U}&��+��?��:���w��l��9���9�r� ��:��SM�!4��8*B^/�
~`l��
`�4���6{c�A�/Z�����}O�<{�%�oX�_k��#[?�����K��4������� k�x2��>�I/�0pz�7���>�|���}�7������������zj ��544���`===,����k�z\�d��z,kkke*/^����W������������30p�'�|�U��������t��1#F������899��g�y������:��f������������������#�@?���~���G����kmm���>���vvv2-���%�w��%s	7�o������M�^��o�o�o��s}���v��}X��?��"n��eIII]��7�����6lrr2~#~;�	��aW�R�=)))jjj&Lx��g�z���_}��9���=�%99y����~����w��7�x��������LLL�����{���K�y`��x�b���V�Cgg��S�����G����o���D"Q�f`l@��������/���6��?�x������|>�k�^[~~�_���s��9r��I����~��������h9?0(����u���}<�5��/�PQQ���xP{06��DEE�I
�\�fzn����lo����a�v���A��������F�����/[�����k�����[��---}z:�v��,�UUU}||���o���g4\�h�"�P��-vvvx�������bbb�x��><dggwnF���)S��422JMM��m����e������;�|����~0�qqqyLLzp���������qFDDl������_8N�f`l@�899a������u+...00p��������i�Kc�o|����z�-�,667��aXX�������x����7+�	��6�'�|[��'�d���^�z5��~�F��=��=`S����?�������LzglN��[�n
���P��LK,�ua[�����o�����z�f:::������(�i���a�2�\YQQ1f�\����YYY#F���LQQ��R��2n�8�@ �tss��{�����;v�������o����������Oss��o�)1��A|��o��lW�w���������
�JHH�SO=�`���:�c;��{ol***�+M����R�Z���;�a����K


r~*`�QVV��El7n��\�-W~���4Mw�czCtt�G}������y��z��k3	���c���?~<������w�}����j�K��p���wn�����{+��>+J������]�<���_x���_����o������Kk$�.OOOi�d/���]Z��������W��a����-[�}���g�>H���������P__�m���OKK�V��2����O?9r�t#/�MMM�\���O���W_�������/�����%ebb�U�]]]����&��bcc%����8i%�K����r�Jlmmm���_�aRSS�=���555��]]]qcl�R�����k&L� m���k�r��F�Ol�����{R�������u�zKKK��������&�/�+e��:u
�������������i������5y����{���
���������P��g�z���_z���y<��%l6�������
�A��<���4�������x������*??_���^z���~��a��=048t�6�O>�D����V2�b�V���D*����6C������_ec��c|���KR����_��9S�[���������������;�n��-:Fvrr�Tv=/,��0R�-[�������6{���5����?����
~`p�WAx�4q�D<���%[~�~�m�K����������2�\�����;���}26l�����"��k���$/7n���O$%%
�	�!���6���{N�>55U2-feeI+�����P=��������� �����'P����J���~�6���|����B����>{��we��0<�|�4v����������wm/���G�%K}<�I������/--E��c����w�}'�`{>���OKH=���S��K,�zI����%=�����c�����������^y�luo�������`%��O��n���;>555O=��8����(lx���(PVV6z�hl�����O�8�+�uu�c��C�`��f"������k]���_�6m������1b�4��D{n��I����=t����_~���
:Wn���1��������$c��������|���F���Gmm�D`�]�Vru��]�$99��'�������A�;����lcc��c:#�_\�/��Ol��-   ""������t���'cKII�w�oILL,--�;w.�jnn�������7�x"�?j��g��1�O��������W�^������c��C�`��f��;w�tm�u����!h�5�����[ ���>�vFF��=z��Y����>���%2q�V�X���T����s������~�IR�We6l����!���eOjX���;��3��7������������=�A�������z	����&�c���c����%���#F�������������J��}�Y����_�vM�)����[�~���?�����=�
yT`�PVV&�"%�a����2!��w���6�����888tm/9j���ov��p��3�<#y�|���/�_�`K

���������Q��x,,,�#�t�����/����\�a���^W=(���<%%���Y��a�4_~�eIpl��Q

]�v-�����
x,@�\�t���������OJ�Jt^5Ic0EEE9r$^J�\7n�$��@B?�
��IOO�~�QUU����@>���W_�O766�k�	&����2����w��I5�������������O�J�tN`l@_���6�YJ����A$6���4�,�F.����-555%����G���������+o��V���t3e��Q�FEFFv��'����,�����S��'M�$�DQ����?b�����C���|�b��sg�Jy��>0�G�p$��M�$���~(�����%��`���A��Il��u	�$�����KJJ:�K��=������J06��(�_�[x<B�1c��_.]��K�1�����)�!�P(\�`^����t��Og�������_����%_1]�|�EGGG�`��}��
�L�:���^�3Q['���$zPZ#uQ�S��nc{d�k����W%�K�z�)i���-007;r�����������i�o����Na!���;������w��zI�w�lZ`l@_Qn<�nQWW��$kE������K/I�����_	� x�3�4�LWz�i���)���n��
�x����d���;w�qW�^�5W�\���l]���1��]UU��Ge�0�G��>��q������D���f��&����{�I#����]MMM�6����5����|`�"	��166�zu��������/�c��@�Mt�6�!���	��o�[����Zq�����uuu]���g�}��gz�t�r}��Ex��9m.������U��������=��DFF>���������������MZ���K�aIXw=zT�2��H��NY�%�(��dd����g���ZZwu����?��|L���?�5����}X"��]����z��#�W�����Y���w������+++������o����:�y��@����������RY����eb0���~w��\�����O�68����������(�0�S��W�)T����(Hp�"(����-���I���0�U[A((����&�"[$)A�r�m\J�h���c����f���3��1��=g<�=�og-###9K��e�Fbjii)��1a�X������fO+�x��Q�����Us��._����J�---�������7�%|����8q"g	�V�������������J}w>��������#����b*��������5�\T����qM���%���wo���������[�����g#
��g����tjkk�����Yc�����Y�I�����y�&��[WW��2��099�~u\[[�S5����2O+����G�������S����w��!����-��uuu��S��l��������(�W?�KW�^�m^O&��6��`�"?2�tl�VP����h<~�x4F|n�*���mmm�:c�������|�2��w�^���c��Tu����w���555����s�������D}}��}����*����s���;�/\��m��[�n�{����k9G�"���M�/S]]�nF8\y�����������O�>M{{zz��3���������[>�����_�x1::C�����Y|�O[���*��KG����D�x��Gla�?>}�tDBss���7�<y!��������?D��]1�K�qzz:��K-%+�V46�H�x����8������LZhZ��}�������c�^�z��Y��M�����=WV�3�����������cGGG���VH��KvJ������mD
���,���-#RF�`+�����c��k��HmG�/�e��`#�����G�644���:t���+����]_Q�T\/]��s�����dwww����/_���{���7�bt/���x���fl��Qljj��C*�E���q#b/"0�0����e����b�vDu�{#��:u*�*&�}}}��������
endstream
endobj
12 0 obj
<</Type /XObject
/Subtype /Image
/Width 1200
/Height 742
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 61337>> stream
x���	�U���Pp����C�������vE�V'�������q4�e���A�QPTP7P�}�e_�E�(�Yd-��)���������yo�{������	����f��|��<73OVUrt���U�V��7o��I�f�Z�x������(|��1�m��	�����7.�r��]�����:z`������]�����'N|���C���G�����M���@|�"�|0��m���k��c����0`����G�~��W���3gN��	��[�����M����<XYm��-�W>�[^QQA>X�*���wo�A3{��}�������w��\:c��%%%�j$�f�z��o?��A/x=�|�n}��G��f�{�=w���o��0Za�����c�=�q�F���`V��C>hf���>�?����:x���\%��-�
����&�|��l�������oRU3f�����W[�6��B>��A���>������f�s<x�Y`�|0+���!�1q�D��g�NS���C�?�����];����EI�����L���l���������o��]�������O�^\\�y���7]�|PM]�p��Y��i}|��yk��9p�@�O���l�2g��W�qP��m{����d��O>�D+�1cFV�"��E��HN�<���_T �����e��,L�4I�B�U�W��D�7���~�����/��$�A};���K��;u���s��l<x�6��qG�����+W���)��!�!����o��cX_����x�
_y���6-��y���F|��WZ������=���=z���uk�uj��Q�{����������&��W�R���R����^����<��#o�����g����F�A��������!�JB��w�}W�������WR��y�+�p�O�>�>�h�`*�2���Tgd����
/��BtU�����>�q��>� z�����2eJ����K��G��i���`</�5���.]��h��'�����?����O>����CS�f����;w4(v���S�Q�F�q����~�7&vf��~�����plZ�=�*�o9�0^��W_}5��iT�l��T��/k
���j��c��}��w|Z}��S�|p���JW}��^{m��1���I�4��`�/z����,Y�z(��ys�v�R5�s��5^p�s�����=Z��e(t�l��f%���z��`��*���;��D�
�'\�`�_���d���)wK���������u4\�b56�I�F)��gC��/^��JJcu��#�'O����?�������|G��]��3��c�MO�:�}1������4���)W�
�!��~pJ�����?Jg�U�9s�\�=Z�W��K5�O�����>���0��W/Wg��a�K6[�n�����UB��&�Z��7I�}����B����R���Z����_g�J�|P��N�:i�G��r�J�l�@u�}�����+:y~yy���5P���TU}]�_�Q
9~������]�>{�h>�b��O?���3g�;#�	!���jJ�BK��Vf�
�Jb�������ZZQQ�������Dc{�����������trW�X���x��<t�����V�� I�����h��{������[�j�4�pG����G��;}�����=|���m��k��]��5k|���
!���Tc}���(8`+**���}����N��������w�y'�����o���DiE�j�>?���|���:���[�N������+�W!��������5xH�1�����UK%��
Zy�����scw�w����Q
��I��G��u���[�x�������Y���t�j����w+�qu��5����`c$�����y>XU};u����z��;b7-6l�G�o���ut���y�%�u�#:��~��S�p��e�N^����u$S5�~����� ���J�E�'��?�:uj���1c4��^��wQ���+��d��X��W�������k���NW������
J�|��f��{Ci�.�y����J�S�d��=�Jm����U*��}�+��8+W��VS.��.z�p�0�o�>������V�"c�����Y�pa�l������7tv�?���P�f��`Z���s;�w����N��:��S>�y��W_M���A����>������^������^�m����������%�|��w���c��
r���>������*))�V�<y��0}��4���q�������F�i���Mmk���ts��(�\8�jC��V?~|�yJ�0�92Mct������C�%�`������G��o���c���A�n�V^UH��������r����S�{�9��gA��&��9�4iR�c���]u$6q�S��]�"�����M0��`�{���58?ayyy�N3�j����A
z���?�p��u.^�x��Y��)��iny
^����QZ_!�����DF68�W��W����;��m�A�����w�
-U��
�[�l�7s��*�Mc{+l�0����	�&�����^.���?����Q�j�U$8����3�W���������#���G���S�<H��>�G�|���k~��T��������1�g��;v|��'�4Q_|�E�2��w��y<*�|p��a��}��W�Z4}����U}w��`v���k�a#x���?����-jC��\D�7#G�Lu���_�����5��a�4��9#F���
�� �_l
����&Mr%�������t��[����v$�m�sIn?�$���(8��}�+���(���-=x����j�(es�[�<6>vV����4Y��
|�)S�����r�x�b��O>�$��������u����o4t�mQQ�?qk����B����6v<:�5^�Sb�+�^�
�Q�~������|�*���}~�l�>��������/j����E��_ ��)Ut����}�����h-��^xA������zO@p���������7.f%�>�X�����Wg4�����E�L�����A�������t7;w�tW��K4���y���=��GW<��{�_�{�a0�J���X>|����,:�F���)U�[y%��GBb3��wd����/1l[����!C���zI??���(�|08�f��E�G��]��'������+J�oNL#x������_���������7���b�Qu�Ql��c�-	^N��`������v����W+�x}*�j���C���9����>l�0�:� ����K�I�/*���~�V�����<��l���_�G��r�~Qw��Is]�����s��I>�e����7�)X��{���������d��]?S�Z�����Q����+TV�����+v������9T.����JX�~�y�����nU�U�|���Tb8|��hb8z��h}�|��7��uRM3����2����d�)��4k��|08E&O�Q'�`ee�W��y�\zK�.�+���C��y�O���6B��C���c�\�������5Q�R>���[�hQ��C���z��R_y����
ur�hpfNs�OH������c�R'����x����;�u>��#��mU3�'N�����&�f�r����JV��x���}����U�mkz�X����5D��C&��P}w3^tQ���U��O��%�F�K�G���M�6�����S�]����{�����VVV��_�O>�d��<�:8�����&r������v��1�9
�.���n7nt���E��������g��9u����3�
��c�ii���Y��}�n��.Z3��_~9�J�O��k�>�
�n�mM�7����{��������.�N�1��}%:�������SZZ�f%�
�5�����Y�)�VD����}��8p`������a��^�t�N�`U�	J���c��a�K�.5nQ_���?�U>��_�N�:-Y�$M��l��'O�d�u����"r�j��dj��5
���<�HEEE���i4BW����_�?�������T�`�u���r�n��#��8&w�u�������}����(��k�~�I�,ze68k��n�P���5�<�����M�H}�����'�|��'��!���c�����E}���~�Se�	��:�/���_s���w����I?e������e&�q����4���Md��:�l�2��T��(���<�r�(8�|Pc���-Z��u��!���������#b�z)U>�\ ������G���
�X�"v�j�{����RUu�V}7�:th�U)�u�b��Z����w���>}��+�N�|P�}���2�f��!�s�*���
VSJ|�D��aL���������wu��5�ZB��l���_�Th�]�6Z��������KVa���	�]On;��A�X�����{�t����R<�%}��Ux�C�o�}�����\��[o�ZJU�O��g��H,v �f��P������<���:eee�����+���������P��'�|R�Z��j���?��S�O;v���z��1#�HY�kC��F
;C
�����M�4�F3h�����a���������k��:O��*��Sg���j�{�c�	��o���������#v�9����TWv���
80����vh����
�u����t���P6���#�Q���W������:_�����u��a��]�jU��(����+������CX�Y]�HU`�NmW_�h�%K��t5�/96������/��t��5���W�8���N�����w�j$��vp����7o��`����O+a<xp�>}����:u
��08��*x`���'O��L�_	Z�xq������Z+K���f��d6�����^p��S[��b1��	���r�C�U�DM=zt0�I��������jG^}�U
���y����zJ�C�
��!��l)�����yi.B�����J��aT
>|���*����i}��b_q�c����M=����X>�N����l�2�kF�o�n���xPL�������=�=59�HU��[��s���?�X��aT��I�o��i����7I���N�:U�}�\�.���J�}�K�,	NA�h������[��m��5�W�y�iP�����&�h>XU�l]�]�����{.B����v�;`V�b/k&�VU�LL[��(S���<�QBM=���H3�������4����)�p�U�����)�}��Y�&@�^0�R*:y��TO��|������#��^������6�����7�w���<�L��+U����/�I��G���C��G�4�6@����n�:eS�L�:ujIII�l��l�����X����O?���/r���g�
S�M���P�_�ti�yE<5u���3g�t�*--��v�R���8+�U��?�^���Wc����W;2}�t�D���������m���f��zB�q��e
'�N���0M
t����$���}Q�j��L�T��-//_�h��8���PVV���PkW�\9o�<���~ �.J���d��
�bV��W(���{�|��&+�+9����}�����[�1�Ln�P ���V�\�fb���'� ����9�U����/�t���v����/�`�~��],����� `����(`��1�n�����>��|7'��U�z��1b�����|�����$���_��"��}�Y00JKK3�l�����i��M����1cF^�����SR��?��|p�����<x��k3p�5�n-\�P0l��z��9�
 ����|����	E�����(�Q0��!�W��4-'��2`�����P����_�����I�9sf������w���O�}����-������"j���9���0�3���.\�p���o���6�X���Q��P��A��9t�P�[���"Vn�`U�����j��7l�`�$������I���`}C>�X9���?��^��'�|0+���E>���?��2e��0j����#F?^QQ1i��?����������	6o�\�:������/��~��)Y��>�����G/_�<z����cS�P4d�����<xp��������G������A�)�Y�n]l}mb����j��/[�,4cL�
���W�6TUO���'����G�q�eee��-Z�H���������;}����c�R:��vn��E;���o���`��=����T
��o���~�+km+W��� ���/�f9::>���WZT�����s���:�������%K�Y�*\�6mW+TT���~�F}0��s����h+�s�'��x�W�v�����5k��W���F�m*�WOgY_C�D�B�~�����k;o�<�,�lI}a�����:��_v}P{�f���o����]����_�����I�.+&��T_�l����=��
8P
�A����80w�\����N�6M�(�1��H���[��T}w0��g������|���?W������a��%�d7�,�q�A��t�\���:�:5;v�H����8�j(T�v��P?�����b�+�������W7�s4�U��.�i�c+�r���m����S5�P�2�T���.�*�	��h�7c�
-T8r��o��&XY�m�'�/K����YU=�S;�T��������(�;�i�EC��(E�����!�J��]�
��.�N]
��k��������ns>t%��q�
�f����ZZ�N���vG6n���u�~W���K��G�}P_�Z�4Y��X7M>����"��e���:���5�W�����q���.�	l
����e��N�bpmZ������cN7�}q�v����
����f] )�p��G��V����+���i_��Z2��x��������~��)��E��G����Q�V��.]�:~>�U�V�n.���"�}��iw����uR\4*u.�-�,��3�sJ�_���g��~��G��+K
}���ms����"�s�>������1q�dQ8�U���[�����+�A�`���,�����Dx�#���2v������W��������~��d%�w�����z3�j�c���@�4�uC��c�F�*��H)���_g7XR��A�/_�z��+��7�Fw�,TJ��W����x�e��T��r% �����]��`��]�4^�I��]V�RT�������J�5�N5bL�e
>\�cw�uv��_�u^����u����{	`����:eJ�%�����(r]��:f�����5��i����(.�:��Y	Q0��pN{�>RQQ�j��Y
�]����U��������W�/+y�^DHu��<�/k+.���E"�#
��������M���3�*��n��3��1�;\E��/��*�	����5CB�I7l��B5>�S��[�P���~����e_�fMl����(��g����?�j��N�:����RU��L��;�:D�UEq�uGR�{�B������G��������/E�Z��C�Y�/.��]�;
i���re�nm��� �P}��U����>����R���j������KF&���������Q��|�r7��_��oqt����������-[����.�|0�u���F8���hv�[@5R�^g����K�f�`��\�����W�B��@��A�����)��s���J�B{��-�v�����e*�t����rnQ4�(�e^���.�u�\��r�R�Z�/v;���
	���z!���������s���I���JC�#d�����PQU}<�_�fX.�����V��G��F_vE����q�������������>����H(K
}\�����������7�6������P.��{�Za��}�bW�y�fW�p��h�]lh�Q�?�������J��|p��Y������o:�0_�
@]��q���8�3��?�0����hbg���kW��J�b�pMt�]�Az��:�u=
���#x�����vk��p�����:l�����}+���T|Z�v��hc��5����5�.�F����E�[F����������Eq���l��+����i����e���G���T+�S>��C����:e>��={v��(���E���0+����WR,X�������9����@4xvK��u�R]IQ2R��s��/]�4�i�_��;w�/����3�G�Z���`���S�U_8�g{$�1�M����@��X���z���Fxn+t�#I������Xa�o�����F��+I����gB?
�lip[T�Ko��]�	]7���T������/�t@���r��E��Ue3]g���I�FDJ��������|�e=�s��-N�0A������Q�O�2�HA#(
����+F'���`4��w��{>����wU1�n��=���%���^�u�
80T�3�>�p3��q����Z�����q����������wo������9������z*�S�j��#�5R�n�Nn_v����c���KN��$�/f����&�+W�t���>���f��I�=�_�|���M�DYEx+t?��,�����wV��2������'��f5��Z����� s�W��5wgW(�ps��������������p�NM�I>��:5�p�sz��9y�d
������F��l�{��K�j|���#�M����gU���?���������W�v��f��mj����
��f��D4���V}$0�1���ap�1����H�l��^��M
��;�+�T%�+��"�D�A��]����?X9�/��L�O�>}�!�/f�R���9�&��2q�RxVG��T���j���#��v��L29�2u��w*�������rQ����X���s���?��h��!M�i���/��g����E5d7n����!C4 �hyE5%.�|0�uj��p���<��k[�!��M
�W�l[���{�B*�L��$:�V�����,J�F��S��A�t����c�;�h�����B���q�gEC��v���;�(�jQpG�����H�����%������ �����t������Av�[��������[nj�P�������4�'t=:�/f���z���U�J�f{$�1���Y��2�p�j�+���W�P�������A?�T��6����RV�F,_~�����M�Zn���E����SH������Sf4�|?N+��4���`�.�4�����g�?�V�|0���~�����f�`p"����F���3�>�u���Jd�s�)^���`�7�������:�s8���>��|�_��������C���^	��g�t�R
�{���e��1zf��}��O���4�|0�uFi���i������N��J�A�)w�7x�W����-�F��d���u��10`@�;�����������:�~�_����/6����|~0�=
��b������?&9<?��|����COI'$U������Ks������w����(X���}�����(n����t"�O*5�]�~��?��k~<��������W9�S+���qC�/n�����U����I��E�7�6j���]�y���>����������Mj����"�M�#���j���^��S�Qk�����_�����+]R-M#��E}���KZCYLn_v���������;W���������:�s8�����'L��#�>��~~�T��z�����9H�<����������liD��mu���F�^�W��d�!���#]y�����P4��������h$��7�x�T2{}��\���=���E�nVy
�3o����}����42�>�&��@4�p�I/�$�={�+�>V�gv�����~����n���=
�S���6����VU?���N��_���q���Z���m9����&Z_u\��b�r��+�q�������@ms�S~m��b������'c�4���_r�C>��B������D�:t����S�Y#������#���n�������/������+5V��j��5�T�}���op8��.(���8������M���:5�,����.Nii����v��IJ���n��D/t�(}��j�>�����/4�����Q>���.���?�=�`�@4���=���o�U��n��G���M>�' 
�G����U���P��P�[-�[����O���Z��
?5n��������.�+����k�~2���j�N0���������W�l�:}��]+��i�����)Dbo�N�n���H��������n���`U �B?������?�<X|}hQz��A�����~�}}F���;J(L~$���r�
\����>����k��f�P����QW�X���4��0o���j%~��G���+�Au��i�����Y�t?�UOb���K���?���������������?{�le�����}���N����U�}}��dQj������;��?�k@�g�8p��Y��fw��O?�TwI�FS���"U_u	��Y�����?���{�T����,(#S�=Z;��\)OQ�%��`�Q�k�F�j��5��)�
����./X�`���.3�D��.��p�\��7�lUu��?�����c�Ww�O-t�J��*�D��4x����y}P��tR�X���R����U��:��'OV`�(�G;�Ui[����:Y:����WZ=q�D?����#�f�,���j���J`]�h��e��*��]%_~�e��������
E�D���{�u�C?�d��t�U�er�t~�����.*��E����v�\�R�7!�����9IwL�
���t:�
�`F�����2����
=?�N����]������X�-��>M�]]�U���N^����'��B?��p	��(5>���@�Z�?j0���K�B3��|��w���n�����G�=�����HF����>��hi��������PG�����g��#�D'����C�pm���jP����o�C���z�[A�
c+k0�1�F�������6�D�'���|��2M=+(������\R��2d�%�>�q�?,(S���E���������G���.������=���� �jU�������R�k�#:�Z�H�@���B��A���.+����o����W�}:,:�Z��2j��j.E�vw���� ��;v��9����������w���Eu6c��C�o��Q�2�A5�?���SA������T��~A�y���p��TtQ�
fnGR�� Q��c����NPc�c#����&�s[a��M�:U;�=u�qi7C��t^�z}��{���S�����[_}��:�g�	�{&��m�K���!�7�3�|������<�j��\�}a\m�gW�O�@�����M$[��{%�w���{�s��=	;a��P�,�������T��N�1cF�
�9sf�[������W��uk���y���|��'�,�6m�47O��	�o$������������i~��g��
SJ�v�^�z�?>���1c��l���?�����n���������w��`�����N=��'�|2�m��q���������N?��s�=������|���{���]y��_?}#��o����#���?^|��g�y��^��_�J!4o�<�v���c����=����_�9�(r�;���n����������C��L���M�����I�&�7�����u����x���5���o~3y��9s�<���������g��|7�T�����Z�0���~X��t��>P.3r���o�Y%��7����w���[�����:�[�����w�y���k��o?}����%�W\q�>��i��<����o��\��[�Y�f)rz����_�B�7�t��]������:�7k��{���~����s_y�%��5z��7��KcW
�n����/��?��
x��<6���M�n���3�<�s���}
31b�v���O_�|�/TT\y��*o��M�f�O�>��s��7���K�L�Ae�g�u���`��
�!H>����E���K�7n����v��1X~�i�5m�t������?���)S�X��4����K4=zt������3�PyYYY��fi��1����������,�|����v��;��w��M�g�}��C���0c��r�2���J�����
O?�tt���c����`C��v����\��U+��-[�>������������Z	�����kv��gF��o~�E�=�\^fL��7�|��\���� �x��mC���wi������0c�7ov�$���Ta���V�;��}��:8��{o�P]������|�AU�����Z��'�xBc�o�1��]�vZt�����*�
6t��V�Z���}�]�Pa^Z�G5��+V�����<x��m����[����&M��~�6mT��k�I�]���=U�6��[w�r/_��-5����]�����:�_8K�7�V�����}K���^V�kq�����Gk��6m�e��`�������_��=�Y���+v���;��jf����A����+���w����z�u�5i���s������y�����	��������
Qj\^^>|�������?��|���
	=�P��p4��u����]?�e��fA��������C�����M�j��5P*W��������n�}c��VN;�r�Q���j�����C��-��R\\�o��U�V�i��Q�FO?����vgSy���.�����7jemg&�1������?�������������g�}6r�Hw������;w��
�����Y�=~j-�������W�d�Au2��v�"-4)
��^~���.�H#�������u+V���^��|��{>(����������Y�f������u����,r�y�������{���*��[o�����z����|��o�q�%�4i����_����=�����>[�v�m>��$���|���:t8�������|��g�F�r��^{���������8�����[�
�W*T}{y���N[�n]-�Q�z�m����?���K/�����y�u7�t��}������"�V~�A���x���[C��(�5k��5|u�0�~�aWa����E7nt��Y��5���`���W�y��:���]����.RGzj�@�7�'���:y�W�\���Q�F�m���-z����hG�9���^x�U��o���C�5��W_}����Y}�����'�6lP&x����U�p8�o>��}���?��}��N��!C����_|]z����=
w���e��`���"����k�lF��k>����O�n��K7n�x��W^v�e�W����F�����G��i����V��'t�C>����c�+�s�Q>�f�Wa��1�E�6mr��Z�f�,�������*--�i��� ���3�H�G�R2��t���:�f3��/��S�������\Q�]|���mEE�g������:��t�Y��R������6�oL��o>k^�������@y���E����E�.������������%5��r����F�{������x,ngy�������[W�=}��������`([t��%�\�r��`yII�Y��_�~�YD4�5�?����������oN3�L��M7o�����E&���9s5jt�9�����w���_ovy=�\>x�����QU��������n�-X�jW_}��_�M>�O?���a-Z��2e��������[o�u��=�n���s�N�v��Wj����?��~����n����W�(�8p��������7q��gO�81�
4�����.]��|p����$��={�TJx���������t��q������{������������Kw/�\��[7��������R�u�]��x����\s����G4i��| /4�W>����DC2�o��f!e���5�M�:��p�k��7�x��[o��Oz�i��s�9��7��gj�G����T/,..������.�Hi�y������.z����2���~���e�]v�Yg� 4k���;��������y��?q�� �Wqq��m��9�������;_t�E���'�|�u�
2$�&JJJ����SN9�a��M�4y�����SU�|�AUSe}DT������������e��P���w_q���=��3c���c�^{������������A��7��������Hw�q���.]��B-:��c;u�����>��0 �=�j�P�\>�m����j�J����>_���K/�T�=z�U.++;��c���\��4H��=�\}0XYm���)����V�:���������,�|�����#�<���6m�,6l�V��Q�P���E������\|��*���[��k��*���C�|�A��l�2�f�E(dY��=��*_}���r��
6����G�B�����V��I�B��y����g?^v�e*|���B��L���
l��=}���"����/�0���.�k���/<x���f����#G�t�***\���[]��a�B�w������&�-@�s�����{�
7�~���w�g�����v��������
4P�.]�D�s�m�iQ���}I�v�Tr�I'E+�����l����d��i����$Z�?���o�>��d�E(p.T��s���1c��9]�vm����4���C���u�\J��W��z���7g�/����Ur��gG+o�����O�>��w���d�����Z���4��d�E(p��/�����-[,��������Y���/��U��T���u��Zt�����;��S%��~���m����w��J���\I�
��Y3-������KV[�����������g�+I�������Y���������-�h��a���TRR�(� a��/����g��?[�lq	�{���J�O�����Dli�T���y��P>X��}�_~��ob��QnQ&����k�[T��MD��K��-0F���D,H��q�#G����yGe��	����G���������N��r��6����"����� �`�H�
"
�
$��?��?��O������J�N<�D?�LU�]�Gy�QGU^^�<|�pUn����`y�-B
�K.�D���uv��U���5Un����[�l*WzjF�[��@���li�A��R������
.Z�(X��7�������j�J���_}�����=z�*���s�1���U�|��!CT�i����QUah��5k�('�J��`����N8����^��v�@^H��z�x�
"
6�4X*�x;��S�{%��M�8�����SOU�������������+���{��w������k��y��
���
4h���G}�������w�6�t��hej�*t��Y���&M���ZI��+���ng
f�9l�W }�	�
6�4� �`�@�M�]��=����}���s�2��O?�e���q��TVV*_k������N:��k�<xp�M����~����6l��������i�*��*�#�`qqq���U��=��F������+����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�T���k����:��#���/��Neee���/�����?���O������f�%%%w�q�)����a�&M�<������*o����T5U�G�����l�"�-�
�oA�o�A���K�oJ����*��{�W\�
��s��3��{�����J�b�����A��7��������Hw�q���.]��B-:��c;u�����>��0 �]�j�����[�/�li�A��R������8������Z�������������K/Ua�=B�����9��c+W����
R�s�=WV�_�6m�EJ�|��U�N8��$�l.�-yQ�}��x�
"
6�4X*�x;p�����������C�|�����#�<���6m�,6l�>��Q�P���E������\|��*���[��k��*���C�|�A��l�2���j�@^Z���"�`�H�
"
�
-���kw��G+������T��C=�EW_}u�\i`��
�h����p��mZ�
'M����3��\�g����.S�SO=�<e��7h�`����w!�-yQh}��x�
"
6�4X*�x[�d�����o�s�|��/L�����Z�n�K�E��cG����#����
W�u�VW2l��P��;w�E�g��v�@�T���#�`�H�
"
�
'�:��_��i��{���J�VVV6h�@��t�]�m���E��7�%���S�I'��\ZZ��������i�������h���Z��}��;���|)����Dli�T8�����y��S�LqM��[���T�z�����{�qs������[%g�}v���
������Jz���J��]����M��HV[��p���li�A��R����5kN<�����/�$U>�l�2�R
80����[k�����K���N��������ms�����+)**r%[�l��o����u�]��%�-�R }�	�
6�4� �`�@���[n9��S�.��������?�|���"�|�=�X�|0�E _
�oA=A���D,B���4Co{�~Q Q����� �`�H�
"
�����e�����7�x������~�������%�~��'3@a�0w8�?�����I��o���/?"��M�5�-��}�v�r�j����k����g������O�s�M7)o���_��7��������}��#2~���SU�U��}��[��{���^!�`�H�
"
�
6���������#�<�����������G5j��0X��E��EC��K.Qy�n���]�vUa�f�B���i���-[���������(��yA���D,l����U�VZ������8p�]����G�rYY�1�s����Z��2D��6mJ�W���K��0��*X�����N8����W$��"��� /�7� �`�H��B�7e^���x��������._�<Xm���W\q�*�{��3g�7n\���S=T(���o��A���?���9s������w�)���t��hej�*t��Y���&M���ZI��+����f�9l�Wh}��x�
"
6�4X*�x�V�#�<�YYY�|�Y�f��N:��k��v���i�\RRr���+#k�����x z���E��j���������j�V�:��s5j{���"`�����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���K��$����Dli�D�H},o�A���Ko{��=z�}����Y�O<��������k���[�n�����Heee���/�����?���O������f%%%w�q�)����a�&M�<������*o����T5U�G�����lw*�-�
�oA=A���D,H��l���#����~��c�)S�|��'��w?���Ux������3T���W\q���s�=3f�;v���^��*��]���4h��q���{��=[��q��Lm�����*��c�=�S�N��������2�����+����Dli�T �����F���E������?�����=�����Z�R�}���K��������G���eee�s����+W��A����������6m�T�����U�V�p�	ZI��\V[��@���li�A��R���C=�_��_��_���������`aii��Gy�QGm��)X>l�0Un��Q(�j����������/��b�w��-X��kW^x����>���[�l���d�E /
�oA=A���D,x�����;�*yT��W_��4�a��Z4z�h_�m����>Z��&M
���gT����,Xx�e������
U�2e��4h�}���m�v�@^x�c�li�A��R!��������c��	�_x���t�\���}�������c��P��#G�E�d����d��a��;w�t���Z���|)����7� �`�H�����n�����?��O�?����z+�����A�J��t���m���E��7�%���S�I'��\ZZ��������i�������h���Z��}����j�@�`��<"�`�H�
"
�
-�F�q��n���+V�*�[��-���W����s������}��*9�����7l��V��OW��woW�v��h}���h�~��"�/��� ��7� �`�H��B��;vO�:���^j�������C�`�e����j������n�Z�N=�T_r��w������V��m�[U���]IQQ�+��eK�~�f������J�Ym��B�[�_�li�A��R!������4i��%}>x���g�VTTd���k�F��K!�-�G���D,x��������~�zWRh���P�2��6n���>����|2�=y�a���s��!�@u����y����_~D���5j�[���&v�����}�-�R�}�o�A���K�o��������g�Em���%Po���/����?���Gd�>��S��\�����c��E!�-�?�7� �`�H��B���*K���st���C]>�KKK�<����:���<Xy������Q#%���-Z�.:�\r���u�,����
�5k���M��l�2T��0��l��E!�-�?�7� �`�H��B�7����?��qc�|����w�]s�5���j�J���_}�����=z�*���s�1���U�|��!CT�i����QUah��5k��x��Z�V�\RRr�	'}���+��n��B�[Po�A���K�o��/w7X��G?z��'L��]~��w�|�\p��
B��{�W\����{���3����y�TJ���4h��q��>�h��9/���q�w�)�,]�4ZY�Z�
�;wVe}�I�&��V���+������4�-�
�oA�A���D,H�)�����-��r�g4l�P��R�o��{�����UVV*_k������N:��k�<xp�M����~��Z����������i�*��*�#�`qqq���U���6j�(�e�E�X��-�'�7� �`�H�%�
@�[`�x�
"
6�4X"�$����7� �`�H�%�
@�[`�x�
"
6�4X"�$����7� �`�H�%�
@�[`�x�
"
6�4X"�$����7� �`�H�%�
@�[`�x�
"
6�4X"�$����7� �`�H�%�
@�[`�x�
"
6�4X"�$�����w��M�y��';�M2w2����Nv�n2s���37���)0�jz7��{�`�1���b06�`c�q7�W�{����S��d%�,�B�:���y��Grt,�l>|�::hB��$
�@��&�
���4!o@�t i@�B�l��7�I:�4�	y!`�M�����R��O/���1g��;CTa��Wd��4�	y!`�M����Y�V�?/ao?gN>Ro������_�����V���"$
hB�@�-@�t i&U4�I�lh����
W�3N���>3_)E����4�	y!`�M�����6p	��'���5A�)�=�~&��x���8�2���M��hB���I�R�����r�����G�r�+T?�5t�l���
����d�i��C��I��
���4!o@�C&M���Ts����X��[���cY���:([|N����?F}?����Z�|���z��<���N��Y�Sq����B�@�-@�t�{��e|fw/�9���ZxV1��
�O��V\P�����y����pr���s.Zmx'S|����{`�I����0[�&�
�����I��R�N*s*R���r�i���|�����k��>��+O4�ylq=���U#<�T�w>�OaI�txv�4p��hB���LZu�R��x��}��tU9��|�>�T�����(��W��h�
��&A��$u��A���=BM8*�
���4!o@��I+k�
�kI�#�u��S���9^��)�+O<R�=g�����T?����n�����6H���SA�@�-@�tPK����q1���D�w�j�E�����~#�e�(v���F�#���r�Q*�Y\������8�;T%�����4!o ��	y:�H�L����"_0q�0�������S���/=�����B��Q�S����Z�J����~�c������i@�B�l��7���Ik��Y����\�z�
��s�Q��A��G�+/*���.%h�s��ZN����m�R���1E���g��He�
��MV��>
R~B������Af����0[�&�
��<i
m|Zw'���T����wZ�z�:�o���u���#���4	li��G{��-lE���N�W=���"�pZ������u����s�f�o�R?�s�_C���5�����#G�����v3
hB�@�-@�t�L�0O��������u��T�xZ��
�'#w������O5)E,y 
?#/�q��LA��y�*���v������X����u-�6���8ix��/�my=�r����rF���^
?�M�L��7f���w�3��^O���^Y9�J��v@6��b�u�_��N*�V���Y���-MlY	�"C���GrI�Rz�K�wK���Kg5��0f�u*^�\�3�9������~E���U	1��&�
���4!o`]��{���W5�U����Y���:([tN����?F}?����Z��X�xiW]��ek�%�?P��&<'=q��kW��5-+�7���8����QZ�q��m�t7R<[<����E3:�:�+� ���K(`
oC<e���5�l�f����0[�&�
^�\����g3�O����b��N�I������*r����j8������"MF�:>Zy/L(;wBz�S�gs��e���I�"�J�~W�~�g�D����I��l[���[v��<�_��z�y�L*WS��d&R��w�J8j[\`���,��JW4�i:0��&�
���4!o`�V��E%w?���Q���Zl��{N>&_��	W]y���c��9��IP�6	[U���P�$�"�)n�/��?��G���-+�5���8~h��~�W<�y3���I��d����2������n�c4Y�li1��h�?����p�[����`WK�3
hB�@�-@�FHkH/�������;BT��(�Y����}�6\Q��#���*-:�*��:��2����E�_��}�]Z�.i^8�q��������:��k�3��7�v��F������1�F���o�S%thT	�D�
����m�*����4!o ��	ysf5���{�z��x����uJ1�UO�9j{��M����x�����������HX�����eu��TN^3r��������n?���g�o�]�����4+��'��;�+ae���a*�?�9~
[����a�M��hB��DE���
I�m?����/�����
������tu�����_94�����A���������I#'g^�b��'����	?����u�o������������GaeF��q��1
w�vMi����k�t`�M��hB�����sqy��'�p��@�������b���k�W{<��4������>z~�w�'o��$�mF���.��w���w��7�~|#�����d��N�p��Q%$�0�8r%�L��7f����/E��=���+�����;��es�����.�tx����^��n�=q��1sSFL�:�|�M\=�~h������#Oz��o�=����j|#OP&*a}]��J�v�Y�a%�S��ZAa�M��hB�l�OWOH�i�Vz�b���)��&,��0m��1�2��*r��O�-���y�=|#/L�F^FxX��H���L�c]�J8y�a%�*�F	����v3
hB�@�-@�F����0gb����.6q�������yv���S����yy������Q��y�q%48��A�O8��^Kv��� i@�B�l��7k!-O��!� ;}���;��
-k7/��8ed�����w�7�F
h�:J�F����]uo��=����S�Gk2R��"�����$���
�����V��������3�f��4�	y!`�M�[/19Y��>�]E�x�����R6uB���
�V���;~Hx�������O~x#O�&�/
I��u��N��},���qka-�����	����:$
hB�@�-@��j�����'����:�uD����.�1i��Y�BW��������.GE=��r��b�&,�����ay�J8s/i��5��3���"�j�I��7f����S�/;��4m��U����r�y:b\���;W\��������N~�0p��������{:qs�,��U�����K	��|���S��1}He-�v��s&V��|���&���k�"i@�B�l��7K����s'�f�1_��FO�1iM��]'f>8���%�����hM����1[KM^�}�q��+����!)��B����g
�F�JeT	��O5<f�Qc�Qe�-�?$
hB�@�-@�f[U!�p�i��50q�T�y��m)1���_C<e�O)�+O>R�z�<+akZ�����4(�-��WB�����$�aJ'�7H�>�H����0[�&��+��Fx�y�d�50y������o)2�~��d�(v���D�#���r���_c��&��y�{�J�����E�����*E\� i@�B�l���\}����������#��{|��B�W�c��U�����?��B��B�_���F������������Bi��%D��&�
���4!o\S�"8��=��_���|?�w��\�W��'���s��D�B�D���F��e��J����0�v�!�4!o ���i���4)B.�,�m��}b�a�
������+.%h��/Bp���R	��L4��jU���|�5{��H����0[�&g�/iU�n��g�f��85����i����]R�z�4�������f�H��+����P����S�3Le�m�4!o ���I���I��C[V/2_�\����5g������d;CT�^02�|ilC�$i6NW	��W�I�������L�Z���$
hB�@�-@�c���I�wo��[j�fz�}���)/���{���
Y����I�#|Ks�����o]����)?�p�Jx�#�j_�4!o ���!��+���wZ7�0_���������I/}�}/?�H�U���X�C&�NqM���p���[+��Q;]B�Q�=UB$
hB�@�-@�#��W*T�"Z��2_�]]��{�������(�4�
��r��9R	'����rC<;U��"�y�I��7f��yS�TQ$����g��|8m����/qW*CS4�m8?
��4����UB��u�����}p�>���o��M��h����b#%�6��~a���<u�������C���^S��d���l�������t�p�kw�0��S%t= +���J��M��h����b${�4��L
,���)�=VE�_��:�;y~B����x�1i����j������qkD:cX	�|��-��~:�4!o ������N�o���0�+35�l���&o\��P��u�1��uz������(i���,7��mvv�z)AcX	'�7�l�"i@�B�l�l?o��O��v5�`���"d��u+��_���S�������O�3#���m`w���}�a%�yR!�����4�	y!`�M6�7MjJ�������������f������+��4��~��i�l�@�-+1���C�:n��2���*��z
$
hB�@�-@���M��\z��a�`�50l��M�n��jr��m�����Hb/����AW�J���x�J������	����4�	y!`�M6�7MV���w��!�/xg��-�n��8�[��MUL.����t���$
�c��>�+����u����n�f��I��7f�$n���,��C
��x��+b��mKC��l�pD~$B���	�?�l����1��2�c���j��N��'\%�j�B��&�
���4��7��Sv�h����k��q�w,����~�I��(un5�c�0������7��(?J�D���+7���cl�Mz$
hB�@�-@��1E��3��Om�>�`����v�-�W\N�T5��0����0����0�_S��w�S%����N.��M��h��7��L��v�X�50r����.��^�����s���q=��fwH%����/��Z����&~����F���Q�H����0[�&���VU�NWOo�F����(p���]�����B-�Z@|�l�H��Z���S%���)�������D%D��&�
���4Y=o\]�<��r�d�50�������T����m�e$
��Ni�'wW	SKY�>8x�,�>���M��h�V���:���2�i�k`��i���-�);�~Q)�KG���~�*a���������s:U��^��z��^#i@�B�l�z�7����RP�Lw�50q�T�y��+���6��������������a%t���I��;��M��hz���-Mu����m�&��tx��.��O5
R�@���f��VB������5��p��\��A!i@�B�l�z�7^�Zv�j����k���O�?~�\��LFfsW�q`�9u|tw��'\eX	g�T�E:7�4!o ������m��!������G�=���d@AB��0��*��q%�~��iwh�J��_����H����0[�&3y�e�,����������G,>��^���@�0�F�J������&HiX	���_�4!o ���k�d-��g��g-3_3]G/�	����5^�����5Y	��v������}�8�4!o ���#o�����w�fy���Y��o-?x/4�V�S���ds0&*ar�.Wkg��T	}��VB$
hr���������=�_��_�����;�|��'k�������[�����������o�������oBCC�<DZZ����{��7�x��?\�bE}}}w;744xxx�����[�7��������#P�$�lD��g��.E�\]1�����:4��@lX�D!���>a�9e�M���Y�O��V��8
�U!i@�3�-77������~�����/III>�={6�����>z��������o_��������"""���k�����|��W�������'E����"M�<��������������L��|#����`��="}�0[@t�U������X[>�\
���x���wS��^��c�dsH���FCC�<�l���n>�*aD:��� i@�3�-66�T��>��a:�-^�j���_������[����M�-���V����������F;������������tl�~�:����?&�h�3���>���D
]�����w�y����m�G� 
g�- ���l��G��o(��L
,:8~����!X
&��2��.}5��J���^2�J�C���H��y��AR���K$������&///���������n�o��Iv~����
���c��e�������g�����p��c���O>��hg�}��q��D=zDQ8�l��mT{�pT��-%��2S��~��fw��d�����)�u&C��+aN57x_�J�Z*x%D��&g�[II��U������5c����W�&���o�3��o���)<<�ccKK�/~��122�h���������7~��gd���[�v���"�������j����#��fP�*���1'�c�N�V<�35�d�7ikw�D'��dpd�l��k%d�3���"������(�J�4�����������P��O>�����6�|���-!!!?k'�H�v�}������f����&���7o�,�J�7�?kMO@,N>[��jZ��$����A�w�|k�V�*{�����7�����/�6�0
����0:�S%�%�h���H���yS�T���;62��O����C]������4`���-;w��������v��������u����7��]�v�_v�@,�<[���r�c4��&^��;�e��X9�����eq?�:�
�@������q%��!�#��J8���N�� i@�3�-88�T����h~:�\UU��R]�x�����?_���-s��%[���?t����FW�.]�o!�S��������n�g45��="�X�y�@O��s���v&���/w�35�����M�kFB��$�IH}�;U�_��d{@���N��t�$
hr���<������:���n����W�k��u�������~���ul�4i���?����---��:u��~���'�[L~���O?%7M�<���{��bq���K(`�Vyl{z��@�����E�����Mw@��$�yW�Q���'\eX	��)���I��6o^^^&O�i���-�����=����-��v}��z
@Q��T�������oz~z�w��ps5pP��%����|�$Q����)���p"��2=�6���L�a%�y�^��X����a��{��?���1c8���P�v������8>�hh��u�3N�:�1l����t���9��?K�{�����-�T	G|���d�V���j�^)@oY�CTT�[o�5x�`�J��V�O�*�p�@WM|P�f�9��M���>�:|�����C� �W�{�@����9��;;8�6��,W3���
�J�;����W��M��7���~��A�)����1s���?��g_o���;FW0s�	�L���7�����bq���r�9��j������=�t�x�5�u�2eD/���#"o@���${�t����.�����';U�c���IB$
hr���2��;�0@���lP�U����f�������g_�>::�l'w�����|DQ8�l����������[���K9�|
lY�X~��I����P��9-��uF����j��S|���0(A�����49O����H����
� q�����0������k����������o��E�����O�����c��i������l���5�x��1���O?5�y���d��q����zh���>"�(�g�89�Fw���7U��dc���&q�����U�a�y�K���G�7�Isf��p�+W_W'��|:U��t�����MN�7}�����r���t�����;)VK�,����h�o�����������o�������CCC��}��Qy$�K6���������%�rW�;����e���0|G��� 
'�-NK���Mc6]Q�'s�V���?n������7���!���H��k���S%�<�T��zn����&��| $
hr�������E���C���O�>Hjc��}��,\�0>>���{��C����W��|��AAA���|����{������;���&����7��|��~H������>>>��6�WxD��a�8�Z	-I�"@�����+<���|I
\6[r�oita������J���S�
�������"i@�3����s?3�k���h���O?����w�}����		1�(iii&L ���7� �n��]���@n";�����[�7���v�������?~���M���(s���<����1���u5p���������1_���T��ItV��H��;]��i�h2�R�X�>8�SVXk|Q3�!i@�B�lq������%��^�{��Gc���.�.����Q^*�t i���j�Q%�[��s:U�QeM���?�4!o ���X�z�Q������~����-~I
�?E������f�
�@��j�q%t�KZo=c+������TB$
hB�@�-�E��>�bv\W��{
3tg���������Ms&�/��j��^>�� i�R	��1�����V���������4!o ���$�o=c�^R����������3qE��}���Y���O�eb/�'����A'J��J(����+�?����%D��&�
���b�*��K	�����*.��6,�6iU��~�j��1�s'��B��o�t i`L�l^�������n��4����+�4!o ��[��~��y��K'�[qc���Afk��Q�����<��o�t i����h\	�5A�*��+=��H����0[l���H�z���j����O�P6�K35�q���#L^�����t i`/�W���j�r�Y�a%�SYx�H����0[���hcs��n�Fx��*2x���A_���]��}��,���A��$
�C*a������e�Y�r��N������{C��&�
���"
�B��l��t����������n+���8~����&+]���!o@�f�������Y9����u-��'�A��&�
���BS��������Y��k���,p��\
�"=�_��\�����7�I�t��}l�J�jaM�RE���GY���A��&�
���BAq=w!V3�L����I��'�e����6���;M���!o@�/��47MmT	K�9�2�Y�P���$
hB�@�-����N<TO������&����;d��8��6�=�gIb����HX�kj4�����eUp��u��dKw���M������^wTcu��s�==�~ ���\
�M�����!o@�"��q��N�p���"�p�������H����0[�����S
���_�g�O��y0s�ps5p�Wm���c��	h@��$
,���u��2�a>�GV��w�^$
hB�@�-��\�]��}C��Y�3��2W�})��Y-���B��$
zDW	't:~C�c��g�*��#��q%D��&�
����wR�KVM�\�����������C�����(��.�
�@��������C;U��[�F�
+���r���w!i@�B�ly�r����i�W�z1~�Kj�����Z�J���	y:�4xley�X�J���tj�s
��e	�4�	y!`��He3����������2��4�[��R���U*_~�Ny:�4x5lyi��NW�m;�s��N���i�#i@�B�l�Pj)���O/	&l)����t�����M���B.��m�t i�������F��t@�JH�~g$
hB�@�-/u?��{��	z���;~������g��^/���j��H�[\�0��N����\xVaX	=�t�#i@�B�l��L�
���?,�84t���i�F�l��SF*�/���t i�KlqA����|�����;]X�l�I��7fKW�-��u��'n.8?c_� �����Z��'}����A�1�9F����k��N��Xh��`��0[eVp[�����������C��������d;��HX����7���F�V��a�b/�&�E�q6��������������/_��mb/�.!o@���dgU��c'\t��)E������Bp���Pk��4���-:4�c�*&R�%�7'�P����JX?����A��s�}p�>YV'�2��a���v����������P��m^���"����6o@����H%��O
�'
+��YI=*!�
����%����������� ^�*����
D����i�'U��c
+������{���0�@N5[b��e���~����������^�Ty!i ]%��dqg�	�J8���Y�JB�d!8�lQj��O5S���C��"��[l�����y�`��^��r���-@�@ ���g��mg
+���
�R�U���d!8�li��~��#�84t�����94t���384Th��7�H�k%���a%\xV�f�^%8"L6�����:��[�����7����RE�{���Q��IA�����J��2��k��!X&��f��v�E�%��J������^��xy�����T���S���T	�]C%+�d!8�l���q?������zs���u�_��[[�^�3r���-C��������p�J��{��P0�@0[$
��z����^����CC�P=�+�z���
��t��}o�D����a%<�{��80�@v=[�y�;���t��+W>z`���=���L����7�#H�Ab�������z����u`���t�<-f�_V�
=��|��Q&k`��A2�|K�����i��� i@�>i���F�>�7DV��V���#�d!��l�Hg��)^~h��i�{��^,�����B�����)n=
�]����Boa���e��)��4c�_~h��
��t����K���!i@�a��V�e�c:���}��jN�����d!��l�n��U
�|�����������^/�c�y���FIS\2|b������������d!��lI/�6_�}Hp�����{�=4t���[b/,b�yG��]���.Z��Q	�|�u^�����d!��ly��,8�������[����;�i2���X���8$
�0�4�?����~���tT�)��f*!�
L6�M��J{%Q3��\wh����Fv{h���\c��������C�����&�;f��U�����<����/�&�FfKm+�{_�z��CC�~a�	6�����U��^/�"�8<$
�0�4�����W�����?���K�j\�z�
� �l���v\�}Hp���CC[����a�=��NI:�'Mzh��Y��/
+�� %����d!�8[�s�����:���C\]�(+��s���/MZ�J��1�����.��l ��E��^O�L��O��{q��n
�5Av]��s�C�s����$���N�g��!�L���Q	}��4��d!��-
R��#�p/����.�����+5���,	(�s���&������k(,&��l)����P����Z�����#��~���z1 "<�H�ay�${�>�
�v����J������a����-	��G��%����U������e@�t�(i����
�6���9��K��Bh����g�����+�;4t�
uJ��l���$
��i��*a���7vT��RTB0�
�`���"��F�'����:��������b�+���`�\t i@�+$�u�J�'���C�m)���!���jN����d!Xq��6p�a��:�Mr�W*���`w�\t i@��%��f������dM�K��B��lI.b�)�
]�����������f�_x.:�4����F��*���r}%wX^'A%0�@��-�i�"�F����=4�����'[Qf�5���s����IZ��N��6��N��Kp
t��Bx�����^��,��8}W��~�
�:Jq-����X6�)<�H�����U]+��m��J8�O!W[u�`�0�@=�-����p����
mY�X�#���~���@����&�T��s�@S����^���K��!t��B�|������
6�d
�s����;
f���@��+$M�4��OG�����(��Rp�l Kf��Lf�As��6N��z����Px	<�H�a��)�����*��u�J�;Te���#�d!��-2�6(A�k��Gc�w{h����(�k���2�I:��4^!o�?���5i���Jx�>>I:�l �����?~����������{[^*���~���@��+&��I�V��;���r��*�v
�
�`4[�*8��y��vvwhh��a���yi��k���2�I:��4R	��L4|��=��F�3�z �S�l ������e������T1�b�����$
��z�xIk�J8dg��&�V|,�;�l ��'�}/�8��\���CCk�m;��--{���\t i@�I�UB���O�1n3]v5�+aj)*���d��o�/^)�<cGw����u��#OLb����$
�(i|Ks�������c��+�OYa-g�G�����_�|h������UQ�^&8 <�H�!\������P������&^������&����CC�W���lq������2�I:M����G>G?�X_	��7HQ	�&�2��w�����MZ��"8�����Rppx.:�4�C��q�u�U�����p���
^A���s�a��n
-�61��q��	��e@�tPH��Np5|���L_	��)��,�3�d�).i�����CCk�of
�0[�&�
�@��:I�j���>��MZ���J�l&X�y\��E�Z1bp��S|K�~g��	y:�4��Z�����*��+����
^*! 2a����,q��zn�-�-@�t i@���J��6��i���
�J����&tG����|��n
-���y�a�{1[�&�
�@���Ic�J������-���]Uf����������|�wjf���H�A?i�J8j��s���[���Z2N.��0��PN���S�?k��)-��,���	y:�4�C����
#�2|���K_	e1�49�dS*�k������������aoo�?��Oo������o��&44���iii'N|����x��?�p�������������Av#;�o!��������G�`/mK=��7��CCs<�i2�,�Cg�- .�
�@�������tW	
X��:�j����~��G?kg�����}���������_��%%���W�^����|���D��[o�E�Znnn���Fr�����{yy�����o$�l����G0CRP�|���A�
-: ��Q����w�T�D��H�!b�t�����+����0��eI 4'�l,�.]��������?}����Awww���E�:��������d������999o��&�c%%%�_�Nv�����7�L�W�II���XZZ��;��;������S{�q�{�g
�?����W�s'�-`#�7�I:�M��i�����: '�l---���^HH��U�V����������^WWg��������}��5v�X�}��eF���?��l���5�x��1���O>1�����l7n�%?N��/m+<y�p����`���MO���Q�d���@��$
�=i���t�������:(�n�E\A�����h�������>�z�j�C��������o������i����/����H���o�N���o3���g���[�n5�9**�l���Okk��������--������CCK\�y�����:�Bu��6y:�4�����H�w�k�:�����N8"o��:[�e/���|�Iw������wl			� Q"��|��m�MU���I�����F;K�R�M��Z��G��<��������c�g�	���y�Y'�- "�
�@��I��y�Q%�Z�O*���r�R�����H�h2���������C]ouss#7
0�c���;��w�}����v������f�<����o�M�v�2��="89^�V�|��n
}2ge��d!�	g�y:�4��v�����_9�+���
%.K�(l'o����UUU�Ju�������?_���-s��%[���?t����FW�.]�o	�o�����?�[�M���G�N�--*��������*v�w}q�pp��"B��$
�������^E|�0�TB��G� l*ot���yyy�Ju�����._��������c��I���?���]wnii����S��[N�<����h���dI����'�_���*6�tA�����{��Lb�CCMr��"B��$
����uW	�]C%t��7
z��-[fylnn�Q�n�7}��#����m����c�=44f����j�q��"B��$
��������^W�ZL*�g����B���	
�������S'�]����������?����	�	g�y:�4��6���~h�c����������m�MP8����`�^�,���CC����������� ��)���Xh��K����;8��\o���?������s���&K�7!���7��z]������G�l�	>��������4��%��{�W��!��/,_��A�X��������g_�>::�l'w�����|Dp<��ecG�l�����|X"�u�p����7�I:l<i���&+aR!+���U�x����>�����k����������o��E�����'��p���c��4���_�B����n<v���G_�r%�>n�8���-����D[<e��&xo����r��'�- "�
�@���OZ�J�v����d9���K����Y�K� ���N�Y�dI��F�k����h����7�|����.--��Jv������#�_�����������/����2�9--��w���/~a��dO�"����d������|�h�	g�y:�4��.���l���cU�p/YI=*�����Y�P��7���������������\.���/�m���d�{��
0��W�^����|���|�����z���������3�Hn";x{{����|�������������<�a3}�G���/Zj�	&��y#C���<�l�t i@��$�d%t���Ix��=`/y�=��"�"�����������������~���!!!f�?--m��	��������X���q��Md���|����������~��������?�="�#��<w�:�M0�mjd`��4�yf��
�@��;J��Z��K�e�c����e��v����<�����;M_Eb��H��*F�%�f���H�a_I���P���/��3O*�������8<^�����j`��M0{���c7���h��	y:�4����&��gT	�I\��P��?_�����x�<�������6��!����d*����-@�t i@�=&M�w���K��~����	R��.x9{����=P2d@�&X2����g��vU�a�M����Y�������ZN.�Rl��&M��m��|������0��N��0r����	����Hk�L��"��	y:�4�h��,�9������
6�/f������1���<|��W���<���V]'��m��&Mzh�Q%����O8*�M������k�sF��<iL����f��+�-@�t i:�*m[*�����������Y���.��?31�3�{=���?l����Vj��R����fT	KI*a@�����)�u��T������L_Rp����Z�h�-@�t8E�T��$�o���q%����l����L�'L�?�����+��l�H�t?�j�W��'���N�J��1#"'��Q��7�R��6i��&�4Mmn�����	y:!i�"�5����U���ws�K����������y�J]���uo���-�6�?W��o��eZ��
��I3�����!�0:�{]`��
�.�>/H���d|6kIuZ���2��	y:l=i�D+��[b���\��\�.g�>�M�����y�+Ju/�����>�fN��<������|�m^��Uv�gOM=_w����t�����	����	�*���-�`�I��d��J8mcvj)*��q����������M6���3���^� 0[�&�
�9i�&�,�o��k�p�G���l�<6m$��_L��L����^����?���Y�����C:����������'����>�D���/l�����=��o�&8�L��X���Y.��o�����^t�0y�AUE�Q�w�l�/&L*������l��7�C�������yZj���\�z��L6u(��9����^{�b�>#�K��������Jw����%)\�!6c����y�+�R���|�#{���#�4�J��2x����&^�u�O)o�����������6���n����^��0[�&�
��U�t��|�7F������\�j6k�/L��z{Z�}�~�&�'�6����n��������Z������-����U���9��9Z�����,l��n^iT	|WX'A%��7�56(l9Y6���M�`�kQ�
�H	f������,�%��O�U��J�ry+��I��L����R�z��d���&�e�F�9��m\�/)D|K�V��8gb�4����B��_��f��7���W��j�=p��fT	s�]��P�{Y���� �F)��b���]�`����3Ab/�*��	ya�R���oM(H�.I����r�����/����;[&���?-g�����t��<��� �*�t�tB��o~���]������J9�Z�/3������b/4o�5��p��lW��M��������J��k�
�hB��W��<�o�����
_�h��@�[r_&��7������2	l?-�$.w9W���:�7���$��T����h{��a3&01�l������+Y����Ou���Zh�)�u����b/
6otH���i���6��A��<��6��(��	ys4
ZY���^��q����9l�p6�?������W�{L�����l�T.W��W���wu'�T�%�E|�6{���]��?�r���,v��UF�0c��=�zwZZ�5�����Jm�����SL�>4o�w|K��kf���95u�V��7�'/��R/.-���>�<���oY��<�����%���������|��6�
A\L3�p����)�,��J�<�H%\>��z���,���y�B��q9=~�L�Mp��O��-@���T|�S�1��:�����V��St��K�T�����ol�4E}Q=�+����k/���ZY���G�+|K4W�Gw-�����O���,|�)�M�:U���n�o��i`���
�����y�'-3����b���`�M��S���'|�-���+���.c3&�O�f�?&�����"�a�~�&�7�6����n�*��u��5h���O�Is@�4��������/K#��,?iJe�Bw�J���"���5���{��m0�,b
r�^�m�l��7�J���5���*�sE;��El�6�&�#K���/�@��)����\����r� K��^RQ�e{�)o$��)K��@�R����K�+Y8C�x��~�T�WSOG������ks�������k�v�l����i2R�^�-�l��7qh���l�i9k�r�G��-l�<6m���pq��t�S����I�w����O{�.��w���7%O�����H�aZ���\�6���Q���,�$i�LZ��&���$��N��$�$o�&<�9p�����L4���	1b/�va�M�� �uZi����	��|t/�_�bS]���������W�?1�����e3�py+��}|�9��	��jU�%H���[bI��������+Y8O�H%�q�`T	������bq�����d���'K}��	��%�!�mf����"V��Cc_u�+���
�s&�OL���W�b~�<�3�|0�5��_�{o��<)����Z����Iiz�G�2�X���O���|�����Gp�������*a��iE�R���D�*o�����\��2����G
i�"��f�����+}/t�c�:��d�����������Q�b��I��Mue_��
6pe>|M��$��L��^�_M�!i`LU���e����-�7��_����F*a��1������VY�{]����`��l����Y���6��aZ/]{���hB�t���e�M�����o��\���Xz:�W��|����M�/�g��q�[���|����r��>]�p�40����w���������%��JN�4���r��N������{]N�	��Ul{pk��c�6��!_5�9�+h\o��`�M��7NAzV{�;�^�����O�*}�����|���q9���\��|�u�%V+���;��8K�������6���GK���x%����N�4���l\�J?q��U%��&8��v����QS�6��A}������U`�M�7R�~z�o��������������]c��yk�G���C%
h�fp��Y����[�wS�����\�)�^����JX���0��I������0��i=-fwL�q�i�B���p��.���l��/o�w�ru����������v&�Iw�AK_��J���VU)�o���_��V�h*l-{V���"1���v����;�}W�z.z�c��#'3/�(z�T�^�V-�biQ��.����I��������������Fu��O�/{Q�
�PF9��p���+L6����j�;����l�l4o�R+���������\�B6uX{���|�=,}����Mh/}>���%��Y��&��f����2�!7�*%�����[�g�M9�>�{����#V����/x�g����k�����o��>�v�j������N�X��?�`X)�t�+��>�D���������]�U��C
_�%��
�
���Jn���kS6�n��<�R%e�-@��y#��9RW�J������3
F�V����lr���������>���sZ�=�Z��riufc~|��;��Ay�Of^�|��1�gq��i���[�������z����i�"V���n����7�'d54��
��$���MwS>��_�?!c��	�*��^�5q5U%��
_�=��B�E9,��l�k������1��ar���|
0[�&y�������oQ{������������������5A�*���d�1�jy}NsQRm��������/����������=3lp��d@��(-��_}�'���lI��=)����^���]+���{��e%_����/f1�[::tW��h�JvD^Z^���/@%�=N6�)��v\l<9��|P?'��7]�,I�5: ���jy������o�������>��
��/��MW����>�����g�lj��*�ZJR�2�'\/�6�����;�����n���c��
�%z_:����7�UmO:���2��������Z�rc�u����y��lI<|<�RH������6�9|�8i�z��:�l�X:a����}i-,/���������(dS�
��J���[��+���&8}�:���ktX�-@S���(�������;.gq{���`���u��K��y���+���,���0��-������������.�� �iO���q�Gn�xw���s�O��}2c��%��/���5�����~YW���W��&-���JV'c^�b���Z�poG���B����m#o/���IM�q��x/R����GW����*������qrR�tW�y6�������d�U���Qz�!���s%�[�I�E9�f����z���-
�2�D�4Ry���ktp�-@���)
�K�E]��]������/��+}��^�Vp�^|�e�9��"�2@@�<�Z�mem��yq����D���������	=�1����a�_�"n�����a��[�8j����~'2/���SM����_.�nUK��[�D��)�1��M������$=t|��/�����4R�=tQ�#5�Ay|VS>������'���pe���qL��,Y����r�+���l����(.q����\���b/���58�����M1��#L|N��Eq3X�:������hR��������]�YW������^�����������l�&�T#����h*L�I�(����T����lI<�,z����G�^�������������;)b���mk��M9q,�b@��[�����i
9��
�=1������+�Ho=��������Z����}u���%���J����`R��������s��s�����g��2	�n�d��G���Eqr~��/
_��n�!��^��#�o�w�������{�#(��*��kt�-`5��������r�����+}�c���Mw�r��^ �^j/}%b�
�*%���7��'�f<(��^x���kS��'�yk�����Y60t��-���K3�_1���U��;�|�]��	)|��"�i]VAki��I����H���~N��H����3��F����G�zs����6'�M�^x?�&�Db��(Z�9T����������e���+Y��~aT	+�~'��^���I����b��Icj����;��db/��`�@�(��K_W��^�F����)P�c���^���J_M��`�j�����FY��F���9�G�v%�:�s��-����)M^�k@����%3lX�g��#��;�"8� �^Y\Rmznsq��^ncv�/��:���J���Jz����G�^l�?�oCgN��vm�������nGU&��Kzr����C9%���+��>wa�k����+Y�<|Q>��N�����
��
@ix��,��]�l;��oi{���L��������t1��H/��g^z�E�$)}i��K�g{����W5`E�F����������i#����$j������Nf^&M!�4:��yVS~���G}��A����w�<�|�
��~+b�N��a��-��6e�����{z�|N(�����v]����m����l�D&�_,�g4[��E��T��?�-��^����|����E]�`���L�}|P�!a�8/e����^j/}�I��� ]�����9�6�&fBy�R�&�����++ ��T$R�H]"��R���I�"e�T�����zEJ��-��L���H�$�s]�)�������ZJ�)��%�JRW��]B��idy-%�����������;@�g��G�^LR�3��T�U������'�h�x�b�&��Y�$��������`�dq)��6F%��f��]�\|��IcF~��*���f��������w����i/}�V�>#���]����k.���B�� o���k����}����	w����,���������v�k�����������(��������]��H�t�tww7�;g.��� ��3���3��s��;���s�s���hux��Uw��>�FZ���y��<"'��=��������<�����#.���r�dMq���u�:_���H?��)�+27��[�I����O�W�z�R�!Z�,���H����k���W���
���>RX��k��9S\�k����F�`li�D�S*�B���s�����.�7W �NQ��e+"���&sR�2��c<S��]���n��K��U�4�N�E�b��Da�\��Ak��$�k9{���W.x���O������R�B������CK�!�0�+-�$��V��q�k�lT���Iw��y����X���p���;:������Y�9�y�~�/Z��=�c���#�+Y���$"	���o�P���^�QK6U�At�n4���
[�
���G~�3^�:/t�wMFg�����o8���>sx���2�����e����&`o��zQ}���s_m[�z�N���].���u#���0�{�d��������2������@�P�a�qN��t����S�K$Y��_�V,6�������������>�!���4���������������JN���*��G��`���O�^
�l���Qd����L��w�3Y_�?0��-��s��/�<}~�����j,��
D�6*��P�W�I��V#
�U�#r��&64���������f��,�J�����rs���k~�e�K��"Nqhv�S���0��>�;�[h�}����c�o�l�|��
��EZ�����'}����@��8.��?5|�J��l!	kF6P_p�c:c��L�r�)F��:�P'}��'/}?}*�g�5}�����@�Yj�W�7������D���D��Q�C���<��l=�;m��������!�C����Y��~�"��M����������lY���V9�YLV,���D93���>��[
���b?�l+s%�=��<�9;�Q����m��lL�=��Q���\����'ss>��tc��19��9��k2n��9���&��Icr������Ghi����cIC�]46Z�%�E2,��T:�t����p3�D������(rr��&D��W�Dr�,
K��,E%��^-O����
�}��#<�oW��[�r�$S�H�-�
*�����@�-������}_q\�p�g���u��t�f�+exu��oo�
���<���w�.z�;�zE�^���`�����Z������cnW.
B�",��9����fG��sKd�A��ni��LF��KeW�)���|������Pu�dso9s}&s�7��*�|�����N��=-���>�����D*9�g3w�1�70���C��c{�q�Mo'�n��z0�ALVSXk/�O�--�0�mZ�I�������a�J���u��l�j��^y����n?
yI�����7��9���3\�9t���DS�J�E����!	kC�@=�_P�q����X0'��N�W�cKm)�g����x��\I��}*����2��=�����������d���zjo��b6��K��y���0���z�:�|q���J���[d��I��^m_�Zi���#.dYx#@�Y��Zr�dq�P�ZP&�����XZY�����3�o���7f<3���7�e�@��Y��Y�\��\������(v�����c�p����X�v��s{1�h
���1Rd�T�(v�f<t�L�&��n������~��hK#z�|1�v#
�|a��#��|�%8,�I�'Q�D�5jc���R�.z)4�P����������u����JojT�"5���h*�V,65������l�s%Z�8r�4�ow��_"���������Z����~�)/�M�������u���/x/�8?��mC������fo��&[!��������;���l�\�6�z
����w<Gu���EG��'z�f����F��������39�Lj��
��2��!�p��<M���wQ�rk!�9�9��S�ME����g����+��U��U��V�-	��qJ�zfv���������$>�z���*�.Z~O#-]�}�`"��D��:d'�ul
f��T������3Y4"�D5�ks(�������ozoW(N�^uP0��Dv����_�����hd������dE�M'���!��S��Y�����Cj��Q�-��d�*\��w����S�,.4�)[������m�e���[�C��L���L-b��,8+2�0��z
�jjliE��/1)��(��Z��.u_4?A7��m����\��Xw|s�{y`]�z(�c��dN��W��R��*����0u���Ju��s&��	���A���Hg{M*���"b��f�)�s�E�\Dv�U?������?9�97!����3�2w���\"��'y��d:�b���m_�q��_c����Xu\~�[��Q��u��G]�l�V�c�U�C�4�u�_+*:�_���,��.�F���|�)�6����Q�"8�w\�$�G�5�S���"��W�As�G��P�����-`�}i=������\�E�	4���E�H���$}w��#�cM\k����w~�D4YP�M3�o�H*"����OD�o2��$2s��"9�����d@)��D��<�'�0���a�B���]a���x4�K����������iLb��cT1�2{[�^_�X�t��xj�Q������YG��^loiQ�I��T��y	���?��d
(+�N�����3��:s�QY���E��8c�D�����v�fPwP�7"������Z��+�4j���R���lcOF5��;m�/2����
	�l�����9�
�-��3ca��������?0����w��v=QIh�FZ�X_�L�l�N�eh;s���8v��N����@�i�cKY&����f���H�����}���[��}���\��������H�&����[ni~l^�_F�C���h�G!/5}u���-���l��/6�P����I.�������-� ���)�����0)+����H��a���}���3��������4	��2�G3��3���Jd�����\6��S����������A���f�-{>��O>�Q��|,e���qa���3q�4��|8o�	R�^f^���r4A����,�S�������4���3�H�A_�V��Zds!�����)��*O���{����O���3GR�OO����k���*��o36��n�%�u�J�K��$^�!a%�pH����l���	�Y�J|[��f��X��]/i cKY���O}N�y����������t���s������/�}���O�Um�G�6�����]�GX����dvF����~�kd��~��g���+-����~�7���>3e��eE$��o��(-��Riat�*��nWy����7g�6��n��u{1��"�Y�����b'�/�k��oE]"U���������s������(H����1QNL�� ���2>�y4����f"����u|u�&��s�1�G%������&p|%p|���_yr�K��)}�r�k���>G���f����D�'jo������sF�^w@�{9��7����[S��6���)�fpt��;}���C��}��j��Y���M��J�����]YRhk�����P�N��N�K�b�W%���.�e^�e���Pn\/5����/nhQ
d��-����S'�������F>��:������,����O�����Bv�\�.�86�%���r='qV�"����i��Y�v���S�\�����k�(���=�u���%�os�����W�P�M�m��< g�v������A�k�x������mV�~�N�;21��o���q@��v�A���p5sk���{1��#���2_�����-
	<�-sn�W�1�*�g��#
�L�	�p~M=��i�aQ�-�>!��_���"/��:�nP'O���(p|]C��6�a;���i���e����J����HW�c=���y�6���!Z��/\yBc��+�^�q��_�������{�t��x��#u�Y���0��r�k�b���WR�Z��9�2���rn���Y[We�m�Q����/����s�����"������O�_�X���Y��9��xq��9�a��8^z*Y3%�,�S��l�aQd��8s�h-������f�e}u�V����4����Oy��9������q��n+Q����9����B���l��HY�������i,������N�mN3\��Tn���}g��_���y��(��.��'=$&/�6+�0���W�\�]!���
������w���a`���|)*#r�&�-"W�|)D���R��
�fb���%R�AWK����C3iz�� �3[m��)MAC��j�\��z�}}�V��@lQ���j��n�)�e������ut9��]���=<��z�uy{�>|Nt�=��W�+�����D7����Ot8N��wR�N�*=B��=�#�h��#=#��<�+�`����b�z�)��W����w���Ir}Rv�M��7c[����s���><{���=������G��9*�sN��=�.���"��Ew�=<U�w���v����RG�R�2���� nL$/)����/�A�I]���NY�o��������?���#��@�cKi?�����}����=��<�c���=p��r���.I���vLq���Wv�6��6/y�Wq���n�m���|�������fs������7���>	}ec����3,��^XY��G]�MkHA!r�c����r&u\<=��y}���Q�/es�A��E4���r��<#����f#!�8O&5T�/���TX5� 3K+���N��h����L����_�w�D���������������4^�f|��?�4�G��/Jv7)�kR(��`O�<�fy��s�6���e��/3Z�����i�-S�Z�(�N>�:�@���m�=�#�&�����G������>.,���	!���$����O~��V�o�����<T���i0��On�Z�/�!?��)����%k�~��mR�Ma��9�[e�o�B����.�f��[^����s�H���I-�\c�h����Sv���LD���u�*N}���A���S��VQ?5��E�M�K������J��/����]��&/UR�R��t���VZ@�q��t�r�EF|
�/-��i:#��w?������^�\��f=:3F�<��^��7�G�R��jo�R��8e�$%:���JF��<Y_�$��J�����G����M���8NC$)�������/Z�!�$?Y���H�Tb�_g�++��O��sL�2���	5�mj+:�o�>��\~����t��P���b��o�����G�����k�*(�)/]G�TAf4���M��2Q��i��E��u'��$��++����|)g��2
������-4_��qZ���6�>
2�/%�.�Ki������Q��8���!���J���6
��P�_�w�_��.�C���������Ku/Uh��k&����=���}���E�����K��o�Uh� ��G�e���l;~�^�qn����A�}��9���o�s����O�S��s����O�H�������|�������m���Z���B�]���4���|�V�cJ����O��2��sI�	�O�O����f]_;����*(;u�g�*�[�Sv��"9�T�/e-�N������i�EZr�����O�h�����/��[h(��j����a�V'��V���@������mN�Y��X�6���t���.���<
7��s�[��l�������>��r����w�r���������9j��������NW�;]�ti������G8��xv���!��9�
p9���D_��}�T{����8���hw/�no������0y|p�s��N�:�(uU���>B�]����
m��$�k���U�����-2�����<W�y�\���MKv7��Hq�=�
|Rx��'URKb�ve���t��i�|`.+��g�����T��k�^S9��%���p��s�g����b��S��s]��$)~#�8+4;�=��"�Q7��V��os���U�e�os���s_m[ky`��	e��o����7-��$W�R�!�OIzk��\Z����ySa���{v���#�g����%[
d�����������b|�<_���w�R���K���^��*HX(��r���
sJ�2Kr�b������������q���q�VQ����>F����.O��:Y��{y�J���cm��7�^�U�������Zw�_�����-Z��k_�W[c����7/��uq%�
|:��?M�-� �?k��}�_x�����'�|.+��gY���"�q�p='s�IT������z�����������s���TY�}u!�|Tn�WZ��8g����������xn��a���j
�i�������<��e����_E�~����	Yu)������z�AL������iY�����;Kh���?�����A;����)�������4e
��&�tG��W�a��u��uH�U�J���	�
|"8a����(��?������8-��
��p~�~�m^�27`���B�n��}68.��>sy!�x�����<O�,]��]�e��yI>�!6	n�o����}�����K���%s�M6��������m��oS6�������(���;�Uvf*47&����M@�+�z��`o����[�.����n�\1��e�Os��g?��VM@:���4����/(��8#� j�L~��h���/���P~�k~�M^�a��J������}�8�c�>�x�r����4C&��)�}	��%���a��FQV���_�������V��}3�6��os�kE6����wn����[�9���I�o�����Z���	�(�;4����@�m��$�M��Nm��U_�0Se�����P���h
���*�7���ae�X�8����U��4 M`o@��X����[D	��%������<�$����`~�9/A�~������3���$u��W��\��Py^�?����f8ue
�R������*��a��e�������Ri���?�-�����j��7��N��ij�< ��E��7������������D��&1�!4��(;�W�\�����������w�I���d�L�����.y��;��9����	��U�3K�	 I�j���	�
H
nb|��M�e=�C;�$�(��S^�/\������#���$u��7��\�E��}��+�tc&����������7����I��k~�Ozh�u8�����W�7�W�Z�W��o%2s��)Uw����tB^���)��VG*��������
���*;[
Z��By�r�4�
Uv}h�o���j)�����M�I�����f2���:��XP��(;_&3�.;2�& `i@����DH��%�]���s���?De
��)������5ya��~K�n�s��JT�u���@�L�O���W�����NR���������@6=���g�=o�w<����"Si�g�Iw�L�M+-h�M������~am�����\(����"����B����`~�*����{���3��;5�9��)�2�N�{�Jv���<��*An�C���A���)�N��ejVM@:���4���ZR���`�����w��:�J��	������������q}q�&�:	�>��\���~�x�J�x-~�SX��H|l)(+����Yl��GX��W{�����6�������zij����������;�|�-�`ii������\�)���WQvy)LZX���5d���Sv�iQoV�]��95�*;�N�Wm�y�i���Q(Pv�i1�rew��<]�����p;��2�����H�e@:���t��i{
/3#H^Q|[���}W�&f ��'�4����O�����Bvq}�q\�rl;KT���z���_�?�K��gX0��5����-I�i����FQV��
/
����=�����L}�f�������N�g<o������wy����S�_�?��`��$��vAf4i��u������}���,F���=������������z��s����:L���k2�?#����2�L~Zm>B�e@:���t��i{G�����~�sU�*"���q��E�#U����^p�KR���Co���\�����������La�D�����Z�����cc�(��e���n�r�j�_+�1����
ij�I�.0�����}g�<�_�{�4��"��=�/"'6�D���R�w�B���>��@������Gn��;_g�R���Y���f�n���������K&�V��"�|��b.���,
H��)Q�A���o�n9�P����8YL�7?����S���T�����u__�����U�e~�m~�"6%r���DF���a��g!Rk��]��7H9=��D`�~�D�&��W�Y�u�gI���,���/1��	�a�^�25��?���^DK~�O�iIv���2�nU?����g7�\�)1j����;����4�\�,
HX�&�7P}R��mv��+A�+-^����s�$����O~��>������q��i/a�����9���y��x��e�E~�%���G�&�M��w�7�����ME'�MVG����|���8gm��b�N�����/z��l�2��!�3 3<��z��8�����"h��GT)d�H���]F+ ���99�9����F���jew�?sz4s�7����y���������^����b����e�s��4 `i@���@u((a^^z��_"J0v�o�j:�*��b� ��a�K���8�
XE��h}�m9�#�o�s����O��������]iAYa|~�oM�b�_z�m6�����$=y��6��5���<��$�F�0.?�\m%�PZ�d'������o�aw3�Vb��)������A2IT�L+_��1f*��EZ����*�X����B����s��4 `i@�������0�W��r��"��;��)M��z�S
x�y�{��9n8v]$����q����-���m7d������\ ���1��e���`�K���]/��=��Ba��&)k����,2��������i�7������s�J������
�c���awV������E���c��z��b'�h��h;6C&�W~��Rg�o1�zL�k&���}����H�e@:���t��i{U��n�����5#��V�W'���Y��������M��q��r��H��s �k����� �����."�Y4}u��,k-�6�"��,�����j;yky��'�����<}e���������H���;Z�Nv�\��Y_vwnB=�ShG����U����e
R�X��,B�&���6ev���s��4 `i@���@���Nk�O�E\;�/nX�j�&�OP��/\����������E�MG��h��^�^�Y~�S~�3S� r-Y%�9q������L��R����xv��CLvL�zz"0W�VT�R�d}\�Z���i�S�oN������c����v�Z�"�}rm��3'���%�|g)�d���������]�=���d�2E��5
��2 `i@:���4��q��<��1E\	F�][,�b��$����OyF�/d'�f�1�N�}�����*�k��_1���*������D�t��E?��f��Y��JN�7[+/1���p�tT����N0s��i{�=�p��GK^>\��`����Q���jM��<�����
�k/{W���7t��������t���<
����;���L�uy��j���z
�2 `i@:���4������Y�.�/���/H�����U��H~�5?�-����5��8P���<���z��
���R�'�+H�HHw���K�x��N����w�\�f���\��>�����fq�������)]�����KF>Rm�>������#bO~�q�o���eu<�
vwz4�d���v������eB�aw!�"`.���,
H��LHOO��gO��������]�.[������'���!/$/''!����KK���.����
��+�����j�|�i?-�1�l;�����r=�H>���7��\��;U�/���s������]v'��,?�.�������ig�����[S7k�&��#W&��4�����|�Tm��j�c=��|p�S�b��}���4���{��+��T�+�d��ky���v��`y���S&�Lv��$"���e@:���t��i{�>!!!D��l�R]]���MGG�_�~��7�����Ituu�K����I��?��U+rZr�����'���`�����HL����?5�������
\'�� A��l�&�z����&��u��]u��jP������s_m�M��)���f������l�1i���^�xBc��#o���6������z:��{�s�b����r����+�mMO+�����
��;As�G��;Z��]�� M`o@:���t��i{�2����n��t�����6m��h���j.88�t&0::Z�h``@N;d����^rb����b����/^'U�<��Vl��'?$�������~���[�Ytp7�ba�����kf�N��Q0[�����Fk��W�M��3���%w�\{s����(j��zy���Q��
{xj���~�*����=�U�R��}������j��cO���<��O��Sg=c��&�d���:��o��(�0����[�4���K���	�M�\�z����#G�������/^��:'Y�h��k�.��1c��vMM��_O���"J�b����������������D��sT�=��<���1�id������F#N��������2�6W�=*�~{4w����N[}���)h�x���sFk��wz�����*����y�:H�c�B�L�/�w7��d��C��@�
��������E����;��jw�c�&�7 `i@:���4��I��������,�nkkK��7o����������5#���E�;v��O�8�����d��1k�~7�����*���|~���Bu�F�������x��-c_�����l�����������^x1���y�7�������u�,����������QZ�����D?�^NG���0�����k&{�V���W���������������>�mgs�g'�.����%�2�%���4`l���,
HX�&�7i����H��������|����a�'y��9�377W���W��CYYY��$���X1�l��#3��k�-X�A��eX��.�j����"����~����l���m�EG��<U�q�:���x����&��S�����n���h7�C_�\1��v��������#�?1�1�SoL9�D�n�9j�
�&��]�u��O��g^���	�
HX��4 M`o������k>>>�G;u�D?~�������n:t?�����������d�e=m��C�Na�Js�����%���n\�3�ka��o^V����07�ch���������������>�����.
��>�������=������xc��o��mh���Ch������y��;�W����h��qv��37I2+��H���4 `i@�����������2���ys�'��q#�6p�@�C������<yR�K������,��F���qtY��b�+�_��\{���~//�5;��F����.:E�o���e�������-Y�2�93��������[�<�Bsc��O��x���hW&9���g�E7^�G��H���4 `i@�������6��222���5�Z�bE�'Y�|9�6b��C�����o��Q�K��WAv��y�}v����{��n��U�2�/�p[&��I�d
*�������	�
HX��4 M`o��j=8r��Z��������L�2Qve{[��Z�:�����+0w���N)�����<�{v�LZ��YV\�;u�-@����t���K��&M���h�B������_d�l��e���^[��o�d��k�U],��������T��Q����Ak'}���a����������R������dI5��=U��(((�}�	���� �W������7k��6��UTTjZ��t�z�*�l�F�i���'��/i'�0--M�q��E�����E���K�555%{�jOii�����j���6����m��E����;����i��Y�f����I7��u��111�FCCCrZrr���.|!!!]�vm���������?~������������x�"�c��C�3yI�~����I.\�@NHNKN.��Pc����������/��[�t����x����!C�������>>>�����$�T�������������'L���]�f��u��u��YU����g��e�~����{��n��5o�|���7n���l��5jt��Y���?,Z�����U����p��);vl��������?��p����@�$$$��m��d|#&4p���s�^�x���D�s5�-""b�����o������joo_�[����q������%P'!��������K��V�Z
>\^^>11�}�al������I��\�f��Y���7bu���;$����[ZZ����-Z�������Kccc��p��1c����������;v�`�


�������n�"3i\�paYY��Ktuu�|��_?7772����!!!��x���'�y��u??�-[��s�9sF�l�z�6lX��0/^�h$�
=�g��a��I�8����n�J�����������@�<�����'>x�������z�����%''�t����v���G�����;�@�C��y{{7i�d�����A��X��M�%9r�H633��+W�!�gb$��al�:{ ���_��V�z��k3���9�sn�������C�S�v"=�$�El�X���)9!�F322D�ihh������-d���S�W���+6&&&�m���8p@�ppp�-� -ld�\�RZZ*l|��%i��k��e��A-[�����x�����n����)P�������;kf������#GG�]��v��I��YS�'�
�cgg��Y�y��q�����N��`��M^^�4��>���#��~��b>�OZ:w����)��u���x2-��u�V�vb9�q���<�b;�
TWW�|��7w���������5�m��	[H�q���Fb�{�;��)))�S��H%%��}�p��}{�(?�^2������N�}��}�+��cG������e��1�]SSS��.�LLL�-�^�����%00��3+W��������M���kw�����A27�����Z�%##��L��������06 ������-[
�1B������EEE�����#I���a��#H��^R7n�W��r��e��&�&������e������������+�a���PVmF���#V��i������FFF�3�O�~���$-&L�!�CZ�r��Br��z���>�N2G[[���������g����5egg��<i������1�>q�Da��e�H�����EEEEd��4iR����l�acggG&#---�g�J���W�������"fC���_�c"���s���N�[��]���b��*""�}J�K�;w����|~�n��<X�=--��F��	al�����`��f�����7��D���255e[BBB������K���/z��)l����14>|��?���?�6���sA���i�&����L�g����EOO��[\�r��
�[�UY8���/dZ�B�[~c��?��e�F�����+V� q55��t����%-��Q�����>]�~}�&M���kw��p��Ub���i���c����`a#�
�������w����������Cde�&%%���������e���������C����[$��0`S4hP�FUU�F�y����O��.��'�C&������1����]��;V��4x����7o�.����S�L!����'~���"������$&���cWW�|�����z���r�J2X�t����^����Ojjj�f����O]\\��	WS�s >>�u���*,,,*�9r�4���c5��z�Fk3�CC�r��%��d�$��N�*l���O�-�	dX��a��������0@}g���;~�����7nl$��������9O�<a[
�����U+2z����s��U��;v 9�g���O��MUTT��U��A�U�t*Bl�56aJ�Hii)�����M�4��e������Y�c#+j�0�R#c���%g /y��m\\������;w�0����G����2�n���m���OO�yyy))).\ ������h��@M�����,11�my���x���77���hii�c)�@b� ��b�[�n=c�	�$��aff�z���[�|9i'RQ�%��b�������m'��u���~/dH!O7m��&5�z��EZ�8���[�7n��a�X�*� Y��CD��"s"kT����06 �����h�����4�h��b�����I�����v����?�~��%vS��?==}��5:t ���'A�In�����)��k�Iq���@������,44�m������Zt���b������i���_�~���l��y��X�~����?���j���������2@�dff���S�N���"��s��'�Y|}}srr��|>�(�����M����w�^{{�U�V���:u���=g��m�����������0V�����������l��,�D�2�b"`�c#�EZ�?n$''��:�XRR2r�H�����d�4a��P_%q�x��)�4�Ps��E��677WPPh��)i)�c5�6zP|mV�d�[E� #03�,f.255%=UUU�s�0`�����g�����=z��(��t3y��V�Z9;;���O�� s�v��mFP����_eq���}��h�B�7UP���� +����Wl�������}��#�Jm,l�����[$bldI&��v�Z��Ib���R��;��n�:66�b;[��I�&����F�)������b2�c&:�<]�d	y�pc�����?S.�QVV6o�<�8777��C�b�+%##�S�N?�����s��K444���������L�2�K�.d&������Y=(l�(�(�B���>[�ZE?(~�
/m�������fmmM�8p�}:s�L����W�a����*��
�^�z�?���;�����c5E��d*EYY�tc��<�m���;wn����o�P�!C�L$�;#N9�MLL�CU���[��I�&>>>������q.\ -�����P� ���z�����


��?+{���>g@���f�?��A�"�������}��f\>|8yUvv����9sH����G����	�	����GW�\I���W�c5�6�&*]�UQob��	�*������p�V\�h�4==]�n��k��M�����@��.$��es	���yyy��U�<e�W�������qc999a��m���^�|)l�����A�PdW��6���P��uG�[��j_�g��5k���w�����:u���&6l�0�Rq��?>��
���g�����|06PSjS����Y���W�_�E�^||<�4--��d����t��z����-"�I��2K���Er0����vD�������w�496�����%lQTTl���*�����{w��Fb�D�������06����F��-q��o����������bcc[�j5s�����_�*���}#��5Dx<^�N�U�_�j�� S��������M�)W��,I�=z3����G���T����v��E�RTT����+�\�d	��*g�� �tZ�hA�cbb��l����W1����E���������������
=H�w���cYY������f��*Nc��Gl���kW�F6eG��+�����~��-E���)>�K���d�L�*����$���o��|2���Y	���Q=X���AQ1�-������Fb��{�����={���,+���d<<<���������b�n C���_|�E�� ��k��oz���������cww�.�j��k���y������]�J#�7o���qc

����4B	��2�Y
`�e�5k�>%�$�s��=�����-,,�������Y;#�
�ddd|��w���~�z;;;777�d���y*��#����a3�W�-@��������OG	�Lqq���M,�����t����1!"���c�����>q��hll��A2��-�f�����X�7r��[�$vH&��
aM�������m��7�������\�MP����O�*��f������K�8���_���_NNN��@69v����%�2�
<�
�S�` SF��V�o����d���C2��5J]]]��I`l@Y��>}z��1m��i�����C���������526���"�!q����;w&��?� �|>���'3g�$�"^Z�h1`��U�V�����%06P5�R�<|�����hmF��������;$�����*�'  ��6��J��i��?�$�"�p���G��o��
endstream
endobj
13 0 obj
<</Type /XObject
/Subtype /Image
/Width 1200
/Height 742
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 66361>> stream
x���	�����$*�7������QP��RA��x�&Q���|��cb�������;� �����.��> �:���OOO�7��>�JUuOw���3��sqyauu�SU�~x����H:~�x7���>��J_'N�b��1�n���`��u�V���@s�o�>;^]�dI����
}e��Q��)TUU����S�9�<Y}��g��)4~�x��Z�A47��'+�����7;��O>�@�E=x��L�����={�������_~I=�f�z�dE=�*R��n���:dOR��<YQ��=!�h�����Q�A����C_|������.]�}��p8�����F��2\�p�������ZEaa�������d-�/�%����wE1�����s��e,���\�reAAAUUU�w5�<v�Xnn��Y����7l�PZZ��B�B������������8p����1�L���29��d/����+))i����v��mb)�Y�f��]�\�:�zP��;V�Z%97A�f$T�x6�H.��***^}�U��}��lZ�z���>}z7�F���6h� �K={����s	2F}���\�
0���8�ze��u���c���W����m2np��<x�?��O�Bdb���e��*����}W�%�]���>���-~�����r�������������l�w�;�	1H�c�I����1/���.m�����<�������i������'����������3��W�]o���wW��t)^���M����I�^|�E��r��L�"3�!I�;U�3>�{����B3�z���V9r��7��6f^�b�y������#��� ��%�9��1b��9s��6U�����^��{w��K�$l3s��}g������d�)[�y���������2����O���j)������g�����q��������F�kkk����\�c*G�{j2�zP�]���A�B9������+%��>p����J�����Q�����!���7n|�����j��$`����F�M���R�6��$��X�~�i���v"� @3'��c����cGn2X��F��td����

������`45]�~�rss�I���W/;�����w���f��CYH������#��Fi�-K{d��z���n��ev8������z;w����~������2���������{]+����E�Ms]L
��}��7�0�I=(%���k��9p����v�F���	f[l�$����DW�_y�;��B��I�h�(��� U���U����|���f	�"����m��/�lfx��w+**\
�{�>V^�c^^�����_����r��������������K9�R�G;�k����6m�A����a��������t�-9:�����3��������;w � @K�<�$�����?����#������?K�iO,�86�������
�����rd,�;���#mc�-��}���~�V�=����}�q��;wn�E�k_{�5���5�5��C��h�����i�&����,�y�l����U�rX���H���G��K��u��v��ek�!C��Rd�7��#3�����U{J�f�d��`�>������{��1���r�c�3R]�����h�n&�!���Z=8b���]�� @K���p��5�yjkk�?����gMM�w��K��y���.//��>X�`A�&I)a���SH�y������G��0'Tn����<u��s�K"e�������V��n�y�Z��t��T.=z�0k����|��e�!��uF�0���{�=�K��4|���;v���{"��i�����j�������"�Vf�{���=g������ ��[�	������[����5�x�d�h)���K/����2���E;�%�m;O��/��������C�����������L��?��1�\�lY��u���7o��Gj1�%��1a��R)%\��A7?��gf��]_L�${���s/yR�do\�-���{
�6[���n�VJ�fb#3��q������cL��_e��$6������)k"������R�%C����'y�Z
g=(C�h�9����m�������3}����$�P�����3CJ�h��=(�a{�G��^�����3m=��s�5a��2�0�#\��+]_������F��������RO��:�{I��=�h���b�����3oR?�������u��}��n�g�L�����+���*��HIlH�����5Hv�d��*� @K��c\i.i3|/Q�����<'N��R�rsse���{�����������H������Y��	�{?�z��������^�sgv���w[J��op#�������\���\ho#C}�/��6��}���.����~����|fGNN�wg��[_�zp���	&�������+H���(Z������;hR_��-]��w�A���Y�����q1nc��0aB�y�4?��������������3�|��G������@�����+W��T/���z����i9+z��?�67(���.^�������m9}w�s/}���
6�ya��|e�_���N�9�Ay��I��rdJ�{9�N�i��5��4>��*))1W����E��-��4�����c\
h��V:�}���3g���}�����y�b��t�@t������Rs-X� �����A{v)	����z�<�^MAA���6A�'��yp�~����[}U�{[N�^�q��e�� f�����y[��6�y'�!C�t�/���y���!]��E�{S��6����������z���h
�h)4�A����^~����B��8?�4jkk7l� �������"��+�����4h��I�1��=IU=(�y�����{��e��G��3�N�LJed���/��?�^����T�����
�s�l>|���������cG����s���D���/��������Y:4�N����4I���G�v��e�{������J�����O��b�����6���R:���v�Z3������]�|����{)��`��^�1�`�>}$K��;9o��b��K��{���I�kL=h%o�A�I���������J�����r�>�[����_:�1��;�$�_)����c���47q����������M�:tH������W^��$�`K���Lc�u^�(G������(I�C$EvvvBk�j�z��3��>�"�"dc��Q�W�n��i�����F�g�?~���h=h>|�{��v!���%��	�����?��_o��]�3��R>���:����>,�>nR�]�s����80�b]{)�C����7�t=�}��+�Je���I*���w��As�}�������r�~�������8o��; �U/��'O�l�}0\B��w^��[��
��S�L��!�������m�)������U�V���;����W�Xr�{i���v��G����=z�]������{�<�gsx�+i��MU6>�)G=�Rh��}���3|������Y�o=h^��ys��Z�`�]����EEE�U������W����ygNs�d���y|�Wj�A�(�-o������?��&��}(��M*G��gX����1��v�h�c@�`uu����k��G������'��v��;IlH���r��-�f=�,�>��#�����8�2dH���Cz�{_������>}��%{��u��;����E[����,����m�fW��P�����������}g���O������s/E+gv��e�(�������H�o!���R����R5�y���-��"�3����������;���9���9�7w�\3�Vj���f������J3������g���f��w�2~v>Rm����������w��g���Y�����J���K����g��v����738/Y,//7�����kjj��M)"V�Z�*d��.]jZ.���t��"s�M|��'!o�7�������$H��,���]Z�v�s�x����K������}�-����^3l�fKK��M+Z�hg�O6����.����a�p���.<77��P����G]k��$����f�i�x�sn����P*�87j\�}�q�������9t�P��'�G��'��}������0`����~4����'xN���8�F��G�1c�,\�p��e�-�E����<�S-��<!m����={�}�w�-���1vo�������b��7�����9��$�/)!�-t>�a����X������/�lR��r�o�1��k/I�4g�)f������;���H�O��%��]����^��O����l��\�����/^�������_��O?��T��1���IoH����/�������� e�`������G;O2e���G�u>o�r��R��X�b��A�G�;��T����	2��.���^�q����|����NR����L_r�����U�J��iB��b�������7m���o_�-�U����Y������3f����;��U>
�J4�
�4]��Q ~_~�eVV�eR�l��1��J|I�$���l����LHo��=��|�!�^�d��]�+�^�g%R���v��������[�����M{!\8�'R'M���KV#{i���rp,X�t�R)KJJR��d����{����-Z$�"[�y��7�m*��7���>,������x
pR*..~��M=�|��T7����C={�4����SS���%K�t��{��)����e�


R�
@�
3f����A���~j Ous|���s�����O�B�nK$''�����Mu��,�]������������-?t�PFLK�.MI��SEEEN�#F4U=���5���p�����5�i�_�^0u��f[��1� ��������
Ev��S���G� �H�`�JxBb��z��e���MU��rMMM�����58��-k����M�0z�����T���W]]M=����$��f��8�h����_�/�c�������`jp�s=(��������� |%WF�_�����<p��~�@�[P��������z���O>���,��-��A�L� |QZ����7�-Zdg�9s������;�^\\�p��#F8p������/**�D�C���m��-c���bA�5|��Y�fm���{���9s��9 c����-���7n�6m���C0d���'J	�o�>��e����R��.����;����$H#���
��[�|���G������6m23�K6l���5J^4h�g�}�`����Pg;>,+%��1c����
�;w�L������+V��ei�8��;v��Mr�(��Y�n��E
nxiiiff�����Q���/�Q�
����d��@I�ki���(o�v�i�wCd-�siO�
�v��e){L�����x%Q��p�M��GO��|�%r,$����}�|l��Y#�4[��|`�%����F��]�([�{���Wv�����.�_	��q����&K&���>h�~0��{��#<a�i��4�4�������W��l��%K�E�'I����r����2����Y��#G\s���-[�H������S���(����R�t��L���Ud~9�rhJJJb�%~
�O�UJTZ��Sh������l�W��+�������a�!�]�"C��@�9����#2l�7.^�X�2E*�h���.eQ2&��E�~K�.���L�1cFmm�sf���mA*�����0&�eF�{�NyU�3�E2&�A�-����!�4�KS�L�Q���j�*���I�&��.�'A
.��@�+�M�$�������f��&�R�(m�:��#-w-Y�,�l�8x���5����2\4e�w��7���]-�2Y�%c����>�.�R��\�R����2��)�4i@�
���ds[C������
�Y�I��\�,\���}���F���Qf~9��
1��c!�Y$�/���6��d�E�[d�Ka+['�b�=(�������Q6���`� ��#	w����QV-�����y��`w����:��I�������r���b�(	�c!���e�#�t}���3!�3��~��g��K���I�=j�!;S^�_G�{�������O�3Y$N�*�����~�����Y�K���B�;��1m�Mo��@��,-�^E�,M�w��������lF����7�����n������l�e��9�W����������`I�$����v���J��M������(%���#3��0���/]�T+2]
�p���]��eee2^�E�%�,�JF}I�ZN<��J�,#�h#�hL5!C�i������v9:����p��r\���3���3�������M���I�cN��v���ex�G�3c����y^CJ6sJu��W�2��Y
"g)-�9�"�����h.��!�����fQB����n�T��^���{!�5xro�,k1��;O�
�8�l�9����R����5�������elvWF���J����qn�l�i�p�'=p��L����*1����jv$��}P=�����} ��y�T��	}0�c��V�N�[9[�l1U�L��L�As�e�Ve�U�I�I	�����o����`�pd����r���E�	w-P�C9�v[L���@�$�R/;�KUh�f�
p�J�)
H�R��r[}���W%{����,s��Kt&$!33�|���[�n5Cn�D�M��[���gf�����w��7o6K�^hO=��2��[F8��e�"C8���\*#%�yF;����O��2R23��N�j+{v�u�J
(W=(���vs�}�\����Q�-��]�c����2��4/y�A�������BM��m��p��t�{f�e��@i�y�y�����HH������
�^L[UUe���z'J�!��$]���H��4#|����2U��
Li�9y��h$�a�����;��lg��`&�z�G�^#!U��#`&��ki��I�p�y�m3�N�zP������h�]t}�"� �������6�dC���j��=�)���]�4X._���������S�LI�G��T<h�!�~
.��#��
�����1eee�^����G�����#q�W�.�������-2�p��:~��Y���K{���S�NM�������^U�-�����m�����|�E��|zw��������K�KF��v��!���Au�_=hN�I��{�`��%f]���k�������R��Q6�1����***\��;+W���)��[��f)�l������\��[�l1�&]z�!�g������hgR������}������������W���0�f��3\/�j��$c����'�\���v��V��=��,�6�{�^��D����H�wc�������Xbo/����C��K���:��_������mF�7���������F���|9���R����+������H"���s������f1.g�CD��c��;k�,k�?��J,��E.�,��F
2�����!�zE��.l=�-+�n�������j��Ut������.{�C����{����M�0�5]��y����������7�y�;�
�;w�o0��&{�{���]}�P<�z���'���~�fIDe�mb)��s��>��m�.����cO99���?�I���[�����>��c���I{�=�o�l���M�=�Jx4_��Q������3+��T��&M�v+������T�����=�
�g�eu�P3Wv�*so����������u��i��=\��&��Lh�2�0�3�
���)�@o�a�jk��"���7a���`�dn��Z��gG�`�d�������v�2������
����u]h�
77����fQ���3��y�0��3@��4H��l��=�a���K�8g��J�Gxgx>����������3'�a�B ��3z�h�N�����h�9�8�����&��
OhO�}�<WB
��x$��D(�I<�Q,^�8���g{}��9���we�WUU��m��y��!����k����|�o������u������'O�������g���[��0��_��O���e]�!��L��l[���y�B4R�����q�a�#�C�=?3b���_�Ih^r����yYYY�����h�����\?:������F4��z��;1��l�sCd���a�H��U��%�����s'���o�}�J��y��[����Vrtd���c�W���\ULrvB�"c����8?�I�q�m=��V9�LtO�}�)�
nd=���f���#cG��UR���������/s��T�f��c��_��fK�������s<�+�D����iIe�n�:;N���������XcHm=h�K�5�#���������=?�V:o�P;cH��`B�`��e����2�{�[�6����O��&�3iMX&�'s~0U��=?���5 I��S�L1ot=�$����Ke�=l�0�7��#���X�?)�7Q���4�z0�ez��>��~�m��{��hRX��2gx���YMX����^�	���:��}����JE{_S���J���yL��A{���>�*&�����	m���3iMX&�'�>I�����#_�~��+��Dk^uu��/�~3?�0`@^]@�2���3���4�����D|!(������~�'�{.�������u��K��U���Vh����7�������ZI�I����npc4X���|�;�o|=I��E�Av�'H��zu�$GS�{L�l���r����}��=��[��G�D{5�D�/j+D��8L���b������dD��������<:�0����`{2��Ee�����7:��A{�h���6r(���NB����8��x���>L$JF���V������H2{��5D�1c���}��=1���]n������7��Z<�eJ1�{~�^\�����81���]�e���������~c�������D����e���+W�4��?+�wvm��*�����k#�F��{2��6g�����7R��\�t��c�z���e4�t���}��=4��eS����HRv)j�y�1c�x�1�����;?�	}0����`{�>���6���or�C=h��{��y�k�Q6����d�hb����/�l��DSQQa���N�
��+e��|.������m�&�_�]���4�@�_=h�i��w�q`�FI,S��~�S��)y������2[���ko��R����np�������A[��u�v�MT��0'�d�8�%[$�ao=(�F�Ky��_)��%v�oi�S�9�#o��A��z�|W��������[gee���,G�
{k���A)3��K�g�|Y���������u�4��N�[���������=�w����,�������	}0#_�B����h����I�I����l�t�u��\��6�z0�����i��Bc��-������^�-v=h>���S�_2�3f����I���\��r����EFwf�/�s�@*��3_��?��WT2��a����ed(�wZ�������=� �He'c-�_�fl��2�W��7���������3-<x���'�����W�\)��o��c����.#v�#��<z�_�yI#����2�1{���pP��pL�0a����fs���+V��M'�)���"e~�_S�H=+��p�_�����lf�'��Td�Y�f��Jm.%OF�%�Tg*�z��KK����Nj+�5i�n����\��9�$B�n
�f6�li���l��R������9s��	>i�U���9�&u/i�y���Q�]�I��J�7H��n��Q_�>����`�^�?���J����v�.K���q���^�`��{/��=l���Q_GK<�U����$G^5�lOpG�|�e��;|�/j�����DQZ"�%
6���w}�����V"�����=���4�0_Gd�W���QPP �!��b?�I�I�O$���|�d�J��}��&�Tj���-{=������gM6�l�7c��T��<�-7-4����gE:y���.{si������`�!J�����@��R���P�263e�����{���w��if�##X{�?������^�2���efy��E^u]���2e�d�#�����������4�-2��U�6����AQ����R��:�����8�D��e0&c0��*������I!c��TO��s2��=������t��3E�����'�n�"�>����d�g�c�(m���|7���OW4�c��mN�T{]��d5��mWl��]J9�fCd���d�DR�����
��T��!���0�?��|���9��L�a�q{�{�H�`7GM�Y����%%%�&2\���v���y��
^��E�h��Kv�|�$��)3o����3:%�������u�-�s?'�{4�T�O�l��%�����l��D�b���������&�\�#��-�If[�x�l�l���K6��lK�KB����rk��}R;�gY�-��Id���xV�db?P�9E�"1w��O��t�S�B���B���555��>0�1�oW��t�4�SJ1��w#��W��0`@r��O�T���������!��f=8n�8�<�4�NZ�ti�
pY�l��S� ���egg�f�;r�H�***2k>|�_|�e�%K���d��?���A@@���cp���Js���S�N��p`��#G��7������gw�������%�\r�����'�P(��J��������>����w��������sy�������/����������?���Lu�R`������0;v����O�����^s�5]tQ������N���5k��r�<��s;v����$9W\q�}��7d����j��uuu�-�����7���m�6m��p�
]�t���MI���G��������V�z��g��������T7M��Q��:�^z���<��l��3���Zf��w�}�L�������S�:=���{�����J�z�����������^�������B��o�7��Tks
�������������|�rI���#�����������9����*�;t�0`��+V�^��������u�����O�&�-������ow~���/��'�|2�
�t���x���.�����>�YN�>]6��/��u��(�����dz��]S�6M�G���������>� �zP*��/�X���H��&����{�����;'<x��]}�����/���v������9���?7�z��E-@=�_{��2�5k�szqq����=��i��T�M�������N��?�����|���e�z�!��~����K/����.%
Sv�=�H%
�l���0a����G�Ks��Y�jU�
m6^}�U��{�1�9�;wvN�z��^��,@���G
����7o���.��"�����~y�g��)i�2�kkk�����:H6�[�n����M3eQyyyJ������%�z���o���_���������?��������[��;�SO=%3_��Z�@��_�1�w��}��W_��:v�����J�z���{�1��O?����0%�J��������m��	���mk��9b�]�pa<�w��Uf��O~p��������p��)M�Z���;�������%S\|����Y�jwno�?��4�%���7G�66�����5K6�]�v�vN��/~!��{������V�^���Jk{6��zp�����M7�TYY����z��m����������A�yo��������o��������M����/��������FsA�?������������������>�]�~�i�KS�L1��C�5z+ �\�m�7����=�����-�04�����T�O�o���l�=�����]UU�s���]��n��G�555M�������uc�o�����3I���[o�%��p�
;v������c��]�v�������������lC\J�G���&�����l��c��G����F�d.��I���4'����W_}���|o�0{�l3���}{�����F��A�f��������;t�0n�8�S]-�4OfW\qEaa��^YYi���t��fS?~|���_|�E��������m�~��G���g����^y��F6��i����z�zPSj�����7�|��/���������];s�Ls��[n�e��&��0-��������H��W��/���}��5�
k6����#Gn���	���n�9��Y#����������-��F����z�T7w�q���P�0�:�~_SiA��3�<cf���t�t��A��T��lF��e=����]t���h�������������U�4��z���O�z�Ha=XPP`���3g�^:z��yi���M�����z��7�03x�7QWW��uky��?ld3�\������E���������i�;A�D��c<o���^;_�y��F
����'����m�����?P�5\����Enn��%[������hXs�e'����_?����������]�v5�zZ�����y��_�t���|���S�������}�+nr-���{��a�����:d^�2eJ#��������o�9//��]%%f'6����y���{�VWW�.U��-@s����o3*���e��dv�5�x��������d��M��hCc���GJ���9�b��7&��`���B_�o��HMa�+�W6lh&������YO6���}����Aq�����������/��Y\ia��+����?Mb��E��~��'�����cv��Z4����^[PP���������;v��."2�U�>��I���S�����q?�v����m)O=�j����[_v�e�_�UVVv��Q��zj�z��+�t>q#R���������}����.����?���k�g��R�G�2�����E�d|�������{���n����W/�w�M7��?�����l����)��k�y@��2&LX�n������&.������J�`1���>0���9s��"6LJ����~���yyys�����.�����
����l���Z�����_�~��rssG�}��7��[o��y��������'2]�r�G��m�RBF�R�����������a(�d��^]�6�5�-EYYY����������\p�e�]v�m����+iu�G���h�������t��WK�s�W��W��^v{��o������������/�XvB�|���#GVW�����/.c���*//6l�/~��/��U�Vg�}v����y��}��E{K(�����W_}�Yg��������:y������y���;���O?�m��O>�daaa������z�)�Mf����������i(??�;�������k��v��+W��?���?.S�=��x�"���7�(3<��K�.�3g�-��"�+E��*��'ef�6mF�%��B��3��JMV��y����f�^�dfy��Q�>~���7*�5@z����R�����B��O?��L����u��!�[{�1y�/���R]]���@&:�5��M��8�)�


���'���_~���9��o�v��%)����;w�}����8����i���R.������r�)�R�^�����������z���:q���2s���]W�N�d����w��������_?���}�������f~���dz��������i�������>|����6m�H�����9����L�����Y���O?]^�5k��x����N;M&.\��5��/�,���:'^w�u2���^r��h�"���U�c�����D�����K\������G������t�b�L�4�k�JJJ\3��1��T\\l�9r�L�:u�k���R�R���$�F�WUU�9�7j�(;1
�j�J&~�����w�}��m��f�������4�����Lu���e�,Y��L�������o[^z���b7;�5���/��\PSSc'�����T#G�����'�0�l�S���?��K/��;����F�m�H�i�����;�,���4v�Z#������n��i������7o6%��	�������t����)=��L���+�3=z�,j��fJFF����c�:�K?�p��'�F�K�^�|o������������Sz���5�X����d�����r�����]/�����N���v89,Z���3����~VUU�}���M"
��y��$
��-oR��u�Yw�qGeee�yb<o�����Z����9s���1�7QVVf^j��&�kR%���y��$
��*oR�}����v[EE��(U������5���_y�����<����tYTc�G��F %��oA��7� i�A��)}��t�R)o��g1(�}����wN�������~���:�O�6M����[Ka����S'�IC��k������sN����L����k��]�����;��Ky�jF�kR"}�4�
:Ht�4hJ���b��?�iyy��%o=({�1)������)555�����C]3o����3�8���v��i'N�<Yfn����x������������s������3���H�O;�4��D��D��-h&�t�4� i��y����jKj%SC��j��[J�x��7�[���?/[�l�����v[��q���r��i��g��Z�����;��3�;����|��2Q^�z��-3�[��m+o����|�������ik��C�����AI��M���!C�|-&o=�����k:t�:��s����[&M�c-999<��Td��~��wO>���:OK^�d6�Y�"o������s���/��u����(�5���oA�A����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI�&� �-�D����AI��t�[ee�3�<s�)�t��!�l���������}��������w�y��~z��m�|�����h�/**z���d6�Y�"o���Nt[Z#�,���y��$
��*oYYY���3e]���g�q����'{�7n\�V���i3j���+W�����3��J-??�;�L�����o���Kf������*M_	���V}R��AI��Mi��������o���7~��_>�������u��M�6I�(�XAA��8q�DY���_^]]��Y����R���;w�<���e!qVs	�H�4�[�L�7� i�A��)M�v�����;o��I����~�i��N�:�������_s�52�_�~��}�������w���SO����;7���H���y��$
��$o555�����M[J�y�i��.\�z���_��?������:���K/�f^�h�Lo����c��v�@J�I��f��AI��Mi����'M�d~�XRR�zi���%[�9r�L�:u�k���R�R��Mh�@��a��"o�A����AS�-�z��_|���.���3�<��������>x��P(����W_���{���������,++�LY�d���������������k��nBkR%
��y��$
��0oq����r�O<�����]�v�����_�%����]�����?�t)�9p����F�m��5�L��w�w��/�\^���nBkR%
��y��$
��0o�����s����S���������n���zH&^y����=z�Tg0S222����{��&�K?�p��'�F U��oA
�7� i�A��)
�O=�k�����Z�|���:+..N�l��}#�A��@z��v89$]�s�=W���{w;��_/���H�8k��Cc��+��R������)�O���}R��AI��Mi�����W\q�������3g����yeee���<o��F U��oA
�7� i�A��)
��`=��g���z��%s���/�h��x:�+������G�x�b�.�j���}��D�-H!�$
:H4�a�������m�z��X���}[�t�sz�N�db�.]\�_{��2�_�~��}���]{��]ez���]��<,,,tMLh�@J�a��"o�A����AS�-�zPf8p�s�}�D��]�o����3�8���v��i'N�<Yfn�������(/M�0�N��{�9��#�E9g���9���O;��Y�f%�F %��oA
�7� i�A��)}�&5��z�;w����K.1��l�2��>�����o|��'��>}�y��C�x���y>n��V�Z�i����>[�j�{��w��g�w�y�����e��$3���[f���m�V�.q������3���_�F@_��-h�t�4� i��>y���k~�0t�������?��}����s�������|�c���
���������x@*��O?]��'�|�{��%/�2��,o�7fgg{g��s���_��uk�c��e����9 o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����Ay�h"o�A����5��m�]��w���q��u�S����+Y)����9���5�
@�[���AI���X�������}h��q�Y���^�����7����6�S��������|�����>u��_wxv�����l)3#�#��Tog� o�@�M�
:Ht����g�7w
e}/�2�I�d�ZrAh��C+��]skm���]�P��������"NM�7A�o�&�$
:HZB����n|��9>�2���4�S��
@�[���AI�������#js�-<'V��uq8�Kx���M��v���������v��B_\�jZ�����yjr�m��&>qjr����&��?59��S��
@�[���AI��U��qj����B����m�#����������H���c���,�;4�n����~�����{�7?Y���k�����v�OB+~Z�.���J���g�wCK����P��v����o4�7� i�A�����w�S����N����;�=qE������}���u���]\W4������O��t�����o���S�9��]��v���_��8���S_~��t���
@���2h"o�A����Ra��u?qmg�2p�]���D�����WFj�";"�yu���������S�}�o�����R�����_�f�]�������]Z�������`I�U�
@���2h"o�A��#��v�6��]N�D�Q�,���J�;�Y��$��M���H��H����U������	������JxK��M�]�Hm��'~]���B��8q���s����~��y�4����t�4�H���+�
��n�]�xY��_�A
�T7���-;q�������W�M��^:�[��!o�A��#��v�6�#ks;5t��6��O�/JusONi�7��[���AIk���c���U���Q�{g���L��I�����v�
����mB_J�6�H���7�@�M�
:HZBj���^��r���}J^�g��*��Oo�����S���<�-mvN���o	�u���������w�o��N��H)�h"o�A�|����8��9�����{�~�9���]u_�?E��������C�����$KZ]����O<g�������q��Mhw��
@3A�M�
:HZ����u�*gL.����������{oM�����X���W���L��#iu���e]��mB;�u�V�H��#o��h"o��>I�+/m�T�x~������h��}��{����������?���x�wC�������nx,��;����������	
W���h�y����@y���2i�Cjr�T��R�i����/��o�~������o:�������o������/�-���2��Y����g�������J(cj�OJ��������������^��RW�����_���h	�[���AG�NZ]eEh������F�~���g�~���������}��R��T5v�������4Lf+6��/�����?��r��HuU����h1I;q��~�koo�6�W��u�;��(-���hQ�[���AGKIZ��PM������\�����m�}�7U�W��~Z��_��x���*���^��v��&iv��G���������~��j]�\sOZ��p����nh�6�?
�|;R�%��E�{��L�-�D����%���v���e�+��*���������My���{�v������6�*s^(c]I�7�����o�����U�����A7#��]�����o}>����nzGxOn��4��h��[���AG
�>\X��]9wz��OJ��^������&;������M�k��
�[9sr��U���R���GUU��)�O<�V������yIj������#��e}/�mB����Tw`$�	m��U��4�[���A�F���jwn��bI����}{{��#��\x�MMU�������{��oW�Y��0�ms]yY�[�8�/����;o��E%���&{u����R�����
'�n�Mh��*}�v�o�
�r��-�yp2�o�&�M�����5r+?�Y>l���z������l�K=;�Y�������l�'�s����k�O{�+9V>v��G���u�o;WLSW��k����O;q��a�9�-<;�mB/
�����$�j7}�o(� ��@y����V���z�R)XJ�����;��&�l�oKO6�l�&���dw�-y�K^�n @ 	��n����L7`:��b�
��Mq���{����2��Q�#��<�-iT���?�������~�{��p��[20CO��l���F�:�4��"7o������(��.v��
��q����0���s������MS&4�}��)�����C0�[cz���H���'�I���>�s��^<Co��lg����g�H��:P'�Ng�k7)��>��+#���n]#{�t���H9M\C����?�+�o���	�`�
�!���`�V���(�����z�]wr���l&����f��_.8�"�~A�����<%�2��&�}-��H��0��4���<�q/��wX�
�y���,��` ������j�(�!������c�2�R}=�������E�yBr�O������B�Wl~�m���Y3'j�{��qP�f0�"���D�v��'�2���������)cm�P�L���������?y&�a��?���K/��W��<yrXX������.]��o<��s������������,�����FM�>B}���T�k���`d�-��z����(��F���r�n\��5I?������Zpt���eYl�������.z��I�����K5/��%	�E|�#�Go9�����x�*,��4eB�V��P&�:��{hff��������J$�q��Q�������������+����S;?00��g�}������)#���/RN���n�dj�z��^pww�&S�>H}<((H�k���`|�*��zt����jyj"����x;6�����#�i�8���n]<#
Pd�b�
�Oa���eE�����7Q�Rs�s$������/��E��m$'Y�f���Cq��m��~�����Z����^����y��'#
�����A??�!�kkk��y�����>		�&���{���L�q��R���`[[��/�LDK7����$�&�
����,��E���/
�����`���#?������']�~�e	��� ��J�� �<���mgi\��~�42�4��(s��L�E�x
]��M�IA��+���x�7�x#44���;v��+**~���������Q������o�����p�Bj���a�q>��#j����OzyyQ�|����NNN���E������`%�0@o)a
���$�}?����]��+��g����8��]9W����oka�rP�f��8h��;s���iU�SB��&�"Z�c����	��zIj
8`�X�=T�Tr��7�����;wR&L�0d����=��Vll��A�i>��3�`J�������?����?��j���u����4j��g����#_��gF�����7����V��b��>^���M�Xs&�����,��wB������x�������(�|!�z��Y�������Q���t���Fi$?�h��e���L��D��	F�
3����4mts��o2:�!Q Z,::z��'V����DDD�,���j��g����0��"!%b��^��"ypG�y�����r�~�����n���n� ��BEyxw�6!��,�������`������� GP�yD�n�2�8b������d�(
h�f��� �a�>�,5�������?>���)S�����Q#��������,33sp$##cp���l���_�z����#����)�0�z3w��^eY�,6B|����>�f������,$e$);I�Jyz�PK�E���f1�-�B��6_jR���� ����*
���x�J,�������#�!a*r����6�����T�����������dd��
��_�����{{{u�����������������V49~��La��`���@��Xs�"+U�/�p����c�@?��|���Fp�����WR����z��fa�b�4�g�"��'��+yx�����;���������9X�K#�	��n+�I2r��Y�"�L�*���<Qx�L�Uk�l#�����AK<�����So����OFlmm�����d�7x(oo�����������������-[6r�:���5��f����Y|���*e�(�FY6=X���9k��9�.���Sd��-�Hf��i�4KEYZ(8�G�����>��T)Y{{�.^��teB�A4�#�F�
0[��=Y=����O�lIs�����~�E����6?������r�:���}�c����L��czc�oi�|�4(@t��v���zy��^<�����.��#{��,#�,f��f�6%6Jx�4��_!�
�4o���+���X�'4�a�?'ZO q�Ab��QONo����3�>������<���}�Yom�
��>MhGiJRe����^
'\[vl�X��w�����������msX�txO�%�����q1L_+`�T�������X�	M]��c�r��|��L;q��lyi��e�T������|7#�#��%���H��ic������|
k�'�����$/�"6���o��3��.�[�v��������_��iW��ql<{���zeXpiz����_���}3'j�s��5�|Fw��\���������I/���j�9RZ���K����d��`�d�=q��"]lB6���=yMZ�4��!����K�3�����M|���?���DLL��[������o�����3Sf0�����^�'��vnf/�6v���
��}�dQ!��|-:�8�4kD!��Er7,���y����Q�h(�2�Ax�r�2���O�i�u�2�VH��]�_���B�����:~�t�����5�����t�:8�#���"����
3����9r�'Z��OOO���C����3#Xan�6H�X��.�v����n�6��S�A�)Xc=u@���P�����Zx�������-�(K
�|R�"�o�e�i��d����Br(�:`������I����:�$�i\�����P���{\s/�T&�g�p�$}�-+�������O��_�b``�����H��o��e�_�p�����|������������R{vgggj|��EC�){8$]��`��`��� �zD^#�`��#�'
|�~����
LP@��� ��9#�B"
���UD�N������+�w�q/��}�,�4�-���j"Z����]����;�Z6F�7)d��G.�s<�W>�mK��4���|�l�z����W���l�����R�|����7drmm���?��K/���=�&����C�#�GjpH�����W^y�:u��'��������<���O$u=#0���A@o���V	��V��v���~'UC��En��d����(
x��(���s�� ���E��(��K���z����f�p��rv]tk���{{�=�'���|���:u�h�1�#S�������7�C%~��E�(���?�y������'K$�q��Q�6m�DMHHH�2e��M�����>���o�}������s������o��F]]���� �5�����L}��w��>Nd�LOO����O;�Q�������i�<=��m��'�6D^�D_�1�.�4`{@�{��pw��E����H�-�x
�q�i������BT�n�iK�V�`_�����!+�h���.�sv�:{��?�9��U���}!����V�������Q~��?�|�k����W_����p����%K�P������������u�O���&P����G����������{����[j��tF02��[S�F)�HC�kZ��^b#yp������C �qx�wX��#x@e�3R������UZ�fj���*Nc\[�w�������j7F��E�����;2O_(���X�_�/�0ru�7�����F��];��=I�����'�1��JT�"�/�\���j$����o�������O����8(r2h�Jc	&��6'�g��r���&q����c�~�kA��S��s�~��	�}����7�������5�	���T����YYV�t�f(��Q�	�����+�G�r�<��H-*lgJ|I���A�4� �u����������/�K��m���[�y�[�����>l���-��3}�4��0�[cz�"+���AS���I�����P�5"k%���E�hl`����=$?���*��'�P�Wpt���d�9Aiz��~
����\��P����L
_7v�7'j��4�3�>����{�;Df���,;����{`L@o����������?�X8M����*��J�"DeD���1]��O��cH<��@�����c/���E��%�� R�C�NP��)%Y=�W*�mJ=<-|����M�=u������SGnt1}�cC�A���{r~����z�e�1�����5g��o����������Y<$/�h��e���Lh�d�����tpEn&�v�->gN�?��5#P�hi�D��+��8�q,�oF�����W)�����,���6�ty�G�~��%<�1�
��2��X����F�IW���8(�����r�f�Y6$;�����a$��^6���E�1�$�z���X�����������UP����jo��;e�]������'p��|�&4�3���"�-��wk������i���t�-�
���cb�zS�f������R�~�hc:FK�:�f����>�+m���F������+��`�������8M�@�W��������>������]��Ko�M�����&l���}��/��N������p9�Wc`j���j��7jm�����]�l������\.�
��-P��l�7b�k$��t���u)�RQ��]>x�
]�����M$;����-�B�6_�P
XQ�C ��������wq^�V�
����.Yg��"+��L��E)�E7�/�l����}�-2�r`L�Do���^e��Z�&��eQ�L�h�X��,U�P�p]������m��H�X���v��+�H�!|#�r\Q�_y�:�!������{���;����g�H�����Bi���4�z]��R��6�?��0�[cb�z����g�h�m�c�"/����W�",%�cy��	��h9���L���e���[TL'<u��`:L�0 �$�g�)��"a���r����R��������������x�/��Q�m$Q�z2�r`L,Xo����-7	�:��42�a�J�0H^����3]��������	5�i)����Kl4����/���!����Zn����}9�l"6j��Eo=�w)��Q��*�D]"
������{�����G>d6���X��d����K�o�3Y|���������H�Y$+�����AcKg��7���t�y�4EV���fOy���&�gG@��d��\���]���A��4�_.]���b����|�B��E0�\�� ?[��U����PUm���4d6���X��H_r����[��W���"��F01,Ii�. ���K��WG,�+�r9���2��`����.�UOM
F����xd:E����'
�-���-���uO��0}�"�C�W�����������%��0�[cbz�;��������L���t���e(�BP�]�x��2�o�����x���
�JS�e�Q��vk�,�.��n"+��uwj�wf��6l���6��T�wl[z����+`��J���~c��<�wK��@-���!��s�������A�w<��}Xc�1*�]i����hs���+�.�����k�����5��
LM�1ir���1��+�i]����K��-���[�������[QK�hLC!N��;t���G�Qz9'd6������d	Q���w]=OX������*�������il`��-nHd��7�Q)J�4�"U-/�[ 
�G�
�>�Y���x8��Nm�Dov�������ye�e����Pt���5�
<�7����%d6������H�@���h��E_�f���I%L�	���f���t��	�z��L�$���������,�������b�x��Q�Q?[�������fu�C���BVi��&�;_z;�3�+�%K@�B9>��L��<�
����"v�����!��3���!:�����������D�c4bFJ3kHV4^�K�=]���d�
S.:jF�4�= �uM��L����N�0���R���l���	.��o����<}�6����e�O�s_�x@������$CG�
C�0&f�7eY1����>�]�U�L��`J3Wp�{�X�E��ed_ �ELGl@��4yZ"��^c���SDW��=]#�����!v_��M���pI�����1�i����o��d�pt�=��w(`-��0fh��0�[cb�z�'�q�W��nf3A��N��0#�&�4�D�Kt]�K���	��'�qL�k$��4��Mt�,k�$M���{�";��|1&��-�V�`S��/��ki'/��z��Tnou�1_�%R�*����t�S�E�32d6������H�H��6{�����P�Rs���T�Y"m$����	������e2������rYtw�r�Y�b�����v�iI���gGm:�{>�1�����-	��V�����
<��j�h?�Kj!�` ������j}�,�f��]<�+�I�����05����#�`9��+���eB�w����UWN��O������NN��w��pu��s�~���9_�QY��r]�H�1�t}6����'c@f�@n����MYY&8��q��~geY1�1��t�fN�b�?�^C_�p"�~�Z���y��4�B��Up������_.��~��9�����RV�^��d�Q�t�}����E�kPE8R���Z�l�-�11��Sq7��w���=O�]�F�SP����!:���3h�����]>H�6`�Jkt�7'����C[��Wf�?4���IeK�R���f=^�R�nB����nEa;Q�I�y���!���F��� ��L��N���$��o�B��F),"Z���Ohl��L�-�`�eBG��J�����*������'��ii�Z�����M�����?��x�`q���	P�=����%�
��7J<��j��X+ �` ������+�X3'�u���Ke��i��2��4A����-X�����3Q�Hr������Fil/�#���w�#���������!���Css��Q�Oc�����ox�}�hF���/!��i<������9>��1PK �` ����z���n{5n���(�3Z0�1���#���6^���c`�/��-�������MJ���6�����������n�6&vdSr���m�B���
a}��I��LCf�*CqG���il�����v�,�7j	d6���Mo��d�����,	���mF`
�l*$�����H�(0�%�t����LGl~<Q�����]�|�9����N	�s�8y�&�x�Z�+t:5)K�9k�hJt��sT�r�[h�!;�C�Ec����@ML�� �` ����z#�i�}��9S�]#y\�����H^:�����
L�^G�#B�t��J���r��s�1�xg�.�up+����&��K���Q�!����+Vm)�|bT�n�@.���������������5g6���No{@|�k�W�7	�^(�3�y���2."����UX�oil`�?��=$?�����JvC@]�K������4���l�S\/�d��*�C�8����6�\!w�rU��
�a
�����t-6��lo�|K��2Fr`L�7��Np����@��y�������&�":���i��"��"�=��������+D�����7$�����&b��l������&#��J��������I�Kg�f�|o�����46p����U�,),�a��d6�����Wo����F��O�[�u.�����F

��CX��t�"^�+�=wk�u�U�����yA���AW&��-����5 �0}��]=��;E�oe�����SM��V�n���g�����xXvf�) ��D?z���A�U����=w���:���xs�"3���k��2�Dc3����B������(��U��qb��m'���E�M�X�_�k5�!K��n��Xsf�4��5�m�+�RT���@���c��RvD��Ef6r`L��7��Q^O�/�������H&�c���b9�M�"�}���X�+460���3������;s����{�G���b���
oNjt"�Q�X/t?:0c�������D��@�^���N���@jN�5K��%��7��-�1����F��C>9nPd��;X��1��&�&ZO����7�L#:/#E��
�������gGm��������3��������H�X|�c�@S.����"��CiLG�.��?�6��zbX�*+
���0 ��dzS�e�vl�XG��>���@����f6��J�;c��������U��� ��X�� �d�}��U���M^����aw�{@}T�a��������C.[TL/<��5����*��n-�_z�m��R���c�z������&�
��^��D����@�A��s�l���{�W���~Mc��%v��t�#6u���qm�������~!����g�}��3{$:�H4'�
C���:{�t�-*6�����bl-*:KU5B=�M�U?�~c`����1k�`�@n��6z#y\��k�y_��~�l�4�)�����1��&� :.�����-O��Bb�j��w�8��Q��������N
Y�-�������
>J�cJ�yz��0Xs���z�=]:Q)E����=:�G�����"���D,�]��`z���������5��i��z�����&��HA�t���������#�}��$�G�evy��oL>�}[�y�[�]
mJl�w�%�U�(�;�E^����4��q�J�S[��0n��PgT�l�k�,Io��[c�Io��\����M��]�U�����l��dE�5���hl`�[�4��t�&J��;�%�h�������"p�������u���/�bZJ�r�,&�k�\c���6��7H�S=�2�*C�.MA��������7�7L�-�1�7Ylg����l&����>(���Id6��}/����Lcs?$���<�6IJY5~5��'�����N
_��u��.�����(�0	���BU�y�8�������g������{���#9�?+�7r`L����%wn�LU��������<����&� Z�����X<������Y�h1<nX��:Q���������c����F-3e��PU�~p��b��u�6�/��r����O�b\Q=
-����0&����c���LW��k�B��t���c��Fr��zG,��460�u������p�1�3q�m��	���h�pb��-in�U��}�L�T�VqU���/�%^����/ �9(�	���2�
�`t �FCYR��e��J���e�L�XF�l�rv���\�
�z���NyF��d&�py~_�����MY�������!M	�d�
c��Pn������-��?']�{��wU��m[��K���0��h��e���������.X2��f6Y���O�_��9�r���Y�+a��g�)�Y�S���k��/��������U��6e�������+B�mo���;�}5��#�������
r`8H�@pKS�c��i�����,Cd6��M4��r�����$��#,�C���{��{�=�Gl��~�vg��;��e�:����B��.*�G~���av��^���#)}�$Ht�k�D�?�9*����<��B����0xO������7	r�/��CE}���-�r �^��������^K�Q��y��R��S|���}���m��9�(����)�e�
t�����(�:7��8���F{P�zgG���� M��U��-�#��G�yF�>��������/�������o������g��M�Gt]�Kgb)/������I^��b7?��=�-)�
�.������|s����r{�����+=�w��8z�:�'���j�`������%�c�5�U3����X0?�`@n��<)���JM_��G��6�`F�4a)�r���~Eh�$��I���v��vm�s�����h�gGm:�{>�1����t�z�lr���0�/����D�U�Q9J�N�8�_��LM���e��PRf��0���
�r0FH�X��j��������]#y����7�8��4������e�M�*�U�|!�sa\�o�p���������$������=�J��;s9r>�W`L=�5ejYy��C]��}�����q��
Y�&�.��;L�T�Y`�z�<�����G������~���E���!���^i����W,�R_�����A�n&��XB�-��4=��-�����'o����0�10���*�*��u��U���A����{���/��}����6�S
�%a�z�����eU��������M�
�����Qi���/��vE(��1�|�Z�\��"���\�����Zz@j����Q���B��/`B9��=:�Uq��Ca;PC��T5���-{�4��k{��Q�&�7,�-�N�S�[Vk�$x���8��Ao�q�4��I4��r�A�1�d*��������y�wj�7����Zf��z��~No�Xi��T�iJ)��F7!�����^��������W��^�~LS�i�}����-��
�!��h)�HCh���;E��E�Y������YIa&��W���Oc�~�W�$�.b:p��Wc��]s/L
_G�gF����|�[���*:�a&���Te?������
X��B�Bl� G���{
�n�zW8c�j�9��C0�[��!�EW=Y�&��$�r�4<�dZ
�E�y��6�~Eh�_�zg���t��&�����y�Nm6��9����A�8�5�����Q��}x�s�)�1�,)��������/�S�=C��VW-8�W�&A�
��]�	z���h>��B�"�`�z�������
���G;���G�}��oMH-����������a�����2���rn ��m�#�,���9+��S1���P�`8���9���P��>��ntG���d���������)/�es���HI���b*���n�m"6�z��1[����.��r�7'��z*U�a<��?
<�
v@�	���	�Iq��s��,��JY��^f
�C0�[���T�W�������$�v���@o�Pr�?�|!��*�
�x��@�"aE�JY5W+��=�M�'��t�:���'e3������}q�Q�Y�W��S���{j�S��n���z�*�C0�[�Z�3 �������2��fSwgR��*��7`�Hj��3x�����te�����t���W�
j���yzb�
Z�6q�w��
v=�Q[z�i����tg%*~�d=�o��b�����t5eH���Xm[
��` �X9Xc���AMKC�[�����&��
�K'vb���X<�h�D�6dJ�`�����E��Do������;Qx-�3W�Y��R#0z�5gi[��(jj��w�f���g������{_�<#�k�l�-V�"'���Q�&��.��r���h."���UX�oil`�����do��O���V�i�Q�.i?��2x�S���
qV�&�h��4	���8���'��WUO������Im�#i�?���l0��C.�Fi����� �r'�����������K����|��s 9^[�������=��C�hm�������LGmh���J�xJ��0���?Xm���eew�*5;lg��0���������z 8l��+j7��n�Kl$n�b�����!D�+���
���hqC�R�cZ����"�����wa�����H�WB{&_a���FRZUz���'�
<�J8����$����%rV�S��a�2EA���l� �[���Yx���M��+�Iq���<�dE���a��XjCt]C�>�n�J������~�r�������P���`:j�e��T�a��k3������|����H�a.|sE�Z�����N�FK.�d��
Sr�e��������	��;+������Q��n_�l��
�
L�^���E�h
�����rALk����������K��������gI&�c�5g�����/������B�iLn��2�����/��?����f:@�`^�
sr��"���Y��	�/:
�b����JW�'��q�+Bs�N4����1��,�Fy�ew(G�)�H����T�925��H����s:��Uzx�[�vq���� �l��	�w:��)����0������� y\��u��o�o\8M��2���fU������+�����D�Y$����MVi������miG����@�W���:�U7�69z�T�a�I����C�aHaum����w���B��I�_$�3��0���Y��b�;���G5-
��_*��b:F�����x�r,��460��x���)�����&T�����{M��@��8�-���]$�-�K�%P�mq��������T�g=`5��-����x�,&�����Ie6,�-��(���A�&�=��c|��b�w����W�f����D�c
�)(�x��J���	.����U������PZ����8��4p�+��|���DLm�(�R9���Qt�"Ev:���S�lX�[�Y\$g�RMNP�~�0��*�7���M���m`�GD�!RPh���RZ���aC�s��	��im���}>U�����	�DK���a��������+LGE�^8MM=�-���J��=p�@n1GH�@r�����j���o�~�H��0�z�)���k6`o�o,������]F���Jc������fGm���s�6�(����'�d�	�
Uq����r����6��W(�����BN3]�r����� =��ww2�h�` ��xW�������7	�Y$�6�]�73F9@v��e����il`����d�C�3��J�`�{W=\����N^��y*�1�C�c���Q�9�Uq���EwV��@$�Q=.�i&���.�V�����i�p:�7�sAYZ����ii(o�fE^�1�z3?D�D�q����+B��B�;���#Va ��I��M�.Yg'�������\��W2P��0��R���C�EoO����Zs5	r�Y�ww
��Qs���R��F&e:@m�` ��>�G1\��7	�:��42�������D�m���L�"�������=*M��3���X��������9�=K��&��e]C�g���&P��������������N�&��J���N+@o�-&)I���OW�Ip��
/��f:L���4��
�+�b���k�2^6�����&ZMq�J��6�������z�qA���������-�(j:�!��@��Tu�����-�4�C���Y�D������i�LGG�
C���{�T�l�T�Ip�<�/���`�f����vO�x
����?�5���D�����)�#�G������:l
�
��w�Xv'����c�qq�Z����D=�|�
9�L��F��PS�t�*ee��i��!��bR(+J��;5nt���Jc:�1z3H~6���y����7�����0�h�49���-�,�[�H��
[{0�BLkW.�?4`dz��/3����
���B$k9�if�B.	���=IM��������S�
C��D��$p7���G�a�uL��@oCH��0�z-�������D�9$3��ZB��F~����-in_.����R��
�����C��i[��?P�j�gSr�i�)�.{�����6�%��7�f!�b�����6�7	��$�v��g:L�zcE�u/����DcS_�+�����3��P�4�B��y(������pa��G�ovO�W0r	�H���\��8��<�_B\�����f���������{_���L���r��������V\���*��G����U.�b/�-
�GJ%����������hq��?�_��_D�6��������J+���*�_����N������4 �0?���m������*����Yr�%�5���6�-�&
�g::�7��P�C�M>.~�ZrQ����V�"����OO��+GvkZ�����K���� �	D�V������O)���%L��br�&_s�81>h�
\�t�FuP����uH�����8�����@��P��(6Zt��,EAw�25�����=�a66��r��o����>���l���H�/���]�q��aeU9�dX@o����w���X�k�Kg�W�����y!RJ�:r�\�iO��Do>U����/�dL���%���8��_�P�-$b?L�i��,!�m;S�o��Q����@o�-�&�
[�C���7��w~U6��������>K�r������m�x�$-ZE���#�Cn*a�E��Z����{h=���;2O5��J0�V���������6���(�	�%1/�4�F��.k�d5���6b������!��2
����/H�Z�%%[��3�<�����7W�m��~�`����o�<�O���$9$����n���$}�	�M/��L�q��wz��g��������)@�������'�����v��\��_��a:j@������8���(��g���Z �Y<�X,�~a`�85�z��'z���
C�E{�rt7K9�S�\�-}T�=��S\��k�����s��n�������J��Q��O0x���6HV^�K�����	D�$�e:d}"�d�]��|�Fo����������-RZZQ&�AUf?:�?�p���];T��"��
�4+����:���.�� F*�z�@n�������9���m�-�i��LVd��7hr������h��t�����l�<�PY�AH���=�Mg0.�s/_�������/�Ov�BJ���Y�i�Y�!����!�����VA(�D,sg�V�aN����<��	P�U��4��8�)@:k�$������!��22=<�=F����{(�����w2�4�{��Np�8��Sx��Xr�v�%�g�|�-���:��W$�Cdw����8Kd6�KAo�"� �=����+B3���~G��z�_�2^DK��l�)�v�6py���ew�*�>(����Q��0���xI�p4�[����Y!���HY��E����7�M4���e����y��#�b�Kj���*T/�&��I
#���M&Wc�)�]�d�������)�>x-Y�\���L���F������m`�D�+)�g:d�!��=%�Jn-��N����s�����W�
�f��k[����-�b2�(�j�'�����f�"�P[�Ao�-�)j�w�w��O�/&(��
�X'8~@��P����������y����H�l���������R�Xyd1V�E������7���D�n�����&��H��t�z���z�6|s�aZH��i��^�aAi�!�Q=��>[������%�B=UL=z@iV�4�>k��j�RlY��T��t�7���I���o�o!1�C�����2yf���{E���"U��N"�Py6Z�)��_��J�B��r��8W��D���"��!^�K}]�����;�2�~�+�1m����������c�����)��:�����\m���~�-CE����JH�X|�k`�x5H����z<�
C�e��L�c��%A���Gl�T"
`/���	
���Z�ps?�����p������.8/�}_���H��:9����7��#:��%����^coI�*.��Y���N	���s.�%�-���\�4c �����0{KoO��"v��L���3�4`�= t?�����	���_?@o+�-R���\�����5I\���@���y��Ij�=k�T��F�8=�>>�U���P��^�y}��3�m~��q�����P`�g��7q%�z/��
�y�h�G�s��X?�:��G;�dKk7$�Y\�i�y�WiF@U��V�a��GW��t/����C�O�����;���`����)�����7������IQ�rW��6��f�?n!��U�4v����&A�!���6<(_y2R��{4�K�\��?�U������~���F�2���X��Zt�H��#�1.�R��#����M�FZ8/z��"���)&�?��X�����8�6t�zx�-t#��DJ��S�GYY���JmRix�X�z�Xan���������� ��2�I
���%r����Ip������k���^"���p�-��Hq�����}e�i��Z��;���V�7BJD��k����m|/�g1KY5W*��=�M�'����u&�)�W�2P0V�4#�Y����g#��m���P�1�G�	P�	yzg�|5?#��G}��1Ao��-m,�-Tc3��arj5���A�l�Y�����B��O:	�)]\2������@�H�r�^3�����^LP��a�������7%�rvx�\,�e��^��dE2���5�;g������N�s��A���Y�������6�]��v�L�w��\�����P����##
d-�VM�M���e�
��!���R����W�Bb�)�g����z�E���.{�fNT�Ip�tI�-�N��OB6��s��)����=�^�}�'#�A�J��Z�y���M�F�{�����w�q7��b:��"�d�]�'�����D�gF�+����#RJ��*�@($�!%�V=��&�|����@��LG�<�4�R&�]��R�B���u�Az�X|n���7���@7�]������~��������\���X�/�x������,�������i�u����$e~��z|�kb1z#�D�,����8�h;�$�L�<V�8
>U�����z��A�3N<h�iv1��(� tW�to=:���p���5J�DlK���/@i���<���������mz�Xpn�+�4=�ZxAr?G)����<%���N�&��;�e�L_
�����*�Z�b�=�<O���l��]��G����Q��o�k4Hv<Q���������Yd�R��"�)'�9iw���P;Z�<a��r��~��-n��m4<^�GUT�6�O�N����� $1}�(
�	�����K���i���I�x����������DAAAj?RVV�t��7�x����{��w4Zr����DM�&S�>XZZ�k�:�������)k����$�D�M��$n����w�6_�.��{{�a���dn#~7Ky(X���h��n�!=%-T�w��3. {��K����6��ZM��"��k#��Wd����.�q���S�������W��GX^f�
�5��V��������<���T��%���0�]i���j*�[V�)@:w�4�����B�����%u���
������������/��"�����lo���^x�wwwj2�����59M��tF0>��[�2���������4�F�)�Gy=�+�U���P>�r�L_�9A:��Q��L��2z���������LeN#> }�R}��!:���o�7f��h�A����xL�q[�jB�K9D��\�%��n]D#����5bI�M[����*����+�P�+��A�t���Qi��Pd�rV/T�=�v��Q������B�A��O-����y��Xkk���������'����B��_��?�����[��{2������/S����tF`��-�������mG���E�BBYV�?�C�&��v���/�Bh�'�����Nwe��<���{N�3@v-I�X���P�T���7,�S����"Z�#�/�����r����.�s<W���[&����e���*�Pj�>�r�\�L��
42}��U(
0$��P��ij��lX�(�2�������)#���0d���>��/_������5������D�/Z�H�gF0����&ODhl!q(X6�
A���_��	
����3�=�|2�������;����=�zJ��W�#/RVu2��#$�iD���gzX:����}��X����/��4���N	]�/�3�%�#�3�n�{fS�R��*���������D��P��tM5,Si����%wn��m�s��5�?�zS��~���=��3�KII��������>����O>��tuu29--���g�|����gF0��R�A�}����:-����P 	��^<]�
�r��������X�zHQI+�����Z���/]uUr$T���o�9���/%$d(^�K�-�
L�
^���B8�f����P�5�m\�-�
�Oq��	��61��1��6��J�sc4�@��]������$��.9&��(
`R�WmfQ�����Do7�i@{?:XgF ������r/��p8�#C&�D���h����)�1��4��n�76g����A��:D�O
��~����� �B^������"�����'�qFg{�������;E�\�u�����Ev���fc)/����w�zG�;�7=s��%�g���������z��'��P���\�cf{��W�:��<��PgT�qZ��k����$xw��m���."/���t��p(?x��[[����//����~��o�������!3���(���k�
?HEE��;������)+S�����_��:z�����tF`
���=���\W��{J�f)�r�,.��w��Ip�yz��a�h��N�Z���*�<�Q^OW{8��x�-�g�<���&��7i�v/���>L��D���������+\h=����.YgC��I�LG�g�)���
t���@����AY�Pg	��a��������9m��{�
�m8����noo��������~�����7n��Go6l��)�8� ����������#�#]]j�����{�[�IG�M�3S�����>R�\zI�/X�%	/R�(��Gq7,��I��^*�2})���������l�[�|�U����)wvt���~c`�T��2R����va���8���_/���k�yW=,g[r�kS�l�^��M�3=:�R�V80��+
0g���uK��&�;�k��plllBBB�Q(&L����3�����������x�����{p�����#l���L?��C��e����Ng�0�{�X�ng(��S�U��4�
#|����5n�z��g�Rz��L�����b�#V��W�������k�c����%,�%� ��6X�1irg���k����������W�������\f�*Pj2���e!�QM�S`q���� ���
z�����A����C�������~��c����La��2����H�i+��i~�w�	=�L��	rV����'�f���0���XDb%��4z+3d�0��#�����
��u9����m���1�X}�q�[�N%���*pm�>Z8>h�c���������66�g6�*�t�tf4�@O~��oT=@�1�n&V�J��\r��5{R����7�y���(�u���'#��^�����
�n����{�S��n�o���4�s��j?��0��m��xi���������^����Lm/pv�v�ny�P��[��%��g\J��]������A��n9�~?+��������m�\�+u��NP��\��;o;������0}�"��i����w��}�m�Z�������aV�`(����W�W�]��)�Xw�B��lMN�u����0��05���������@N��%I�o�e��u/����:
�������{�~�_L���
�]c@f���3sB���~�z[��kiw���P���)�l�u;��O��7���W'>��^��Y����u`Nh�����C���bbb��7!���ob��)L$��7��w��qF��H���������~����b/�=��u4�]o$'����e�McS_�+���S�+����/�(]9���r��R��J}�:u��\�pz%��F�*�������_�������*��e��OP���[r%k�D����z��c�N�:������x22Bw�#G��D�~�����8u����W{F`�sKr��G��{N|;C)�o�9��� �n�4"�d^�=��.&�����X��il`���M$;N������:�7]���l�E��[P�
7�������vB�{�>.��.<S�37z���1%�9��:����gfu-�#F~�P�y����H���{(`U���ccc��;����|������������������S��/_~z��������Lvvv��-Z4d���C�M�tF`sKD1������K/I�����l����� ��;EN#��F7�)���x�
}������ _/A
�����<.���r��2/�k��v�2����N��o�]�]�!Z81x����!M	R�^���Sf���0�]�
�|E�����t{U�")����e��cz�)W�������~_��������?��K/�����d0,,������Rrj�z+88��`GG�+��B�:������^~��g�y&66v�gF0~n���r��z'���$�X,�
��^��	
O�[�3�/�����h=�|A�1��+�����pl(0T�CD�`�q��~RM5oGx��;���$*UbU=�G�G����������wz��@�L�������uzy�oGE�����(��0&���,]��2V?�������������g����~�b��$00���c����:�>��7�5c�7&&�1��k��7�$FS���{�Q�+`E����`AA��I����{g��9g�9���,�������!��g�,?g��<3�s�M�0���6..���p���������!���p\������o�7�R���H�"�{���|"0�}K#�2�������cj�VfR3	.��}�:��C`������2O[)�|���D���.�l�uY�)�$�~�[b,W|���S�����%��p�p4���8��?�R"��{�'Q�_(z�cd����2��0?���$}}}w��1i����G?��3c�����_---�B��w���,_�;������ihht�����+�j�2~~crr[6JJJ&N�8~��G
}"03}KU3u��/m�|�!/+*���)��7.�y8+��t�U�Adm��!kc��D�6��SU-��F[@�D
u��k����i�US����R��:�6�����x?�K��gI�/������Q�G_G7�#�3(���T�@���s�I@o(e�-����O�<����
m��!u���.Al���0�c������D�bQ�h60�S2�����+@xe������5dz����|oa����_��K��Xd�����f�J���,�$�u�-
Ts$2��DI���T���50?���2P^��PD���	��g�z���;4�[,u��%=��P
T��4�@s���7��H�\D�"U�X^�XUvy��B�NuX%�����)��?_��s�!����6�����(�� yR�_��(�h+�`��b������fi�*z�;���9�$�7��2���,�&��Oe�{�}�����j���=o\�;����9�Tk<YpR�����/)�J+$�a���#��q,x�%�.����p3�2������%��	O8�V^�Kz�u�9z�|�-�����[,�%���&6�&'��9
��[�r1��Gy�H�Q�c���Lz@l���$��?%y-���v�h:}\�&���y�n�@�P���������������:WDrU�d��m.����=��L8�a����vy�e��^n����R�1Vx��/-g��Y���F�U�8�,�;os5��������/{��=X�G��^���LQT�TLdU�Eu��l�P����,��0��-�L��#���E�@�s�I@o(��[�d)�v�"��F�h��*�	��+H���T��j��D�������<-�ypd�l��J�O�\��u�L��G�(�NlMj�?.���N��	���J;�����EF���M�i�%O�T�
�0�]Me{ LeU�8
T��@��Bw��[�rvJ�����P��[Z��f�`������,2�m�,��	���fx�(Sn�8�	5d��4S�����/�#� �������\O{���!�p��Z��K��
��oFe�M`�u����������5�"{�1g�)g�w�m�A�q{�Wz�����*D`)t�b#�)�O�.
pj��g0�:�H��w���(� ��
fM��`����}KMe�#5���[e�������������� �� ��N�!b�+�|���d����X�
�u��a�'����6K�M��f���\_H�Eo
��
�=�:N��y���V�����&��7�
]���k��3?z6Tka�>��j�Tx��(�#^�\l��m"�Nq��������I.!�+��:�W-�1������C	���}KI=y�E��n�Ry������m�y~��B��9��;(��P�
Kd��j������b�S�����-;I�o.OF_�)	k�T�j�����EU4Q5dz9��dx�(]��$��Z�?1��bSy�9S�I7�����4��Ph��7.���;n�N7��;�����-7�{�p�ly'xg]��|3��P�m��%^��"
���)�dNYRO��R���T�m�I@o(����B���d�����m��I���09^��(�K����D��������TSH��Q������A����3SV���[�[e:f7
�(�T����F*_�T���Ev1��a��T.>]r��C�C�I�?s�� ���x�_k����w���|)S|���^z������<��;��7��T>��2A��*
��T�V��
Tm���j��C��@��%<��y������:�n������YW���2�x��T�-"e�(����%�� VZ��S�X���+b������C�����L����h����6b�\T�.!���q�ek��y|����.�m0��?��_���]�^^k��j��s���<��7��_��4��Dl�����k��@�����4`Xz@��[|RD��{>�b����c�����&�?gs���� ��
��,�L��,{c`�L��:��ycU�e9ME��������_�+D�&������v�v�������%<@
E������6z�2��L+#�
���/M��(���W*��>����7�v���k_�\w���	gh�J���,�{�r��N:>6���;a���BWISYF�o�L��s�I@o(i}O���j������f�;(u��_��>�?�O�����(�?�6�J���j����gr,k�|J�NF_��e�L��k��D���D>1L���::���:��B��~��o@��QY��7��a��6D�����"a���6M�M��6S�Rac��6Y[-�k�8�vI;Ky�_�+�]L%�6�wbC�	���+��>����b���6���9�$�7�A��O�n�
�%q��G��uR7	���%��Y��A5�������a�'�9{����|cYr}�Y��Z?m��G�����}k�
Jm�PC"
T�����@��9�����P��:��2�T�J��;asl*}������m��+�C�T��������g��H�:�.y��(��t��]$����Df}&O}�Zq��9�$�7��d���7&~�Y�=����v�nU-���
�����e��B��(�JU�i�E�/���1�����m`l����:n�s��V����H��W�$�^Bm��7c(�z�K��Q����U%;�&F7�YS�+��T��J������by�Hg:��E:��C�W�PDdU>v�\uu��Bi����2�-xBr���+���;_;���7	�����G���~@>Ud�5"�7�#��"�{������
�n/��+�Nw^$���(��Y/��U��\�z~����n�J�)��3kj���V�����l*]����C%L�O���g0�J���dA���]�^��G�:��)BB�]dv%}�N=�	9|���7������U=���������Ip�~�����+�,��~+��D����m�,��������&�cO�iy�Dl�?l�a���7P��y}����[��C�PR�fM�#�����*��r���":��a{�/�m7�W��|"�Q���u�|]b��1�D
����=k��EZ�?^��\�T�E��&�0�D�{���B���K�����`��aQ�*���	�L��E�/kc�;d�.����&�m,��xA�1g���u�.����Y'��_iK�Q�#)�Q��+�5]��<����:U?C����1�x���*��sS����"�$���[!�H�'.r��A�"��W^�l��S�~�;��7h?��^��)�>�5,�H,&\�2}B�XO���0��
���Q�h�ENp�N��N���3{�$8o��YW����Br�Z'"c�(d��%Yp�j�g�u
�eYMV��[������t�N�sns�2�?��s��o��_(���R�3������V��E�'���H?���k�;��Z��En�I�*v���E>q���.2��,o��E
=��/B��B<Tu�V�u�|�z���7	�^�u�����������D�<Q�(Yg���������Zm^%����u�(�����|����8.����d��w0�:��;+Q�*�R�3��5
IZ����E�����Ef�.�A���oy���y�v�k�h9s����E^�]�>k�;��vy��!�i�K$9�.��M���@�@�a��u�p�a����a��vI
m����������%�D�TK�A/i���{H����J��2MSmV����8��z�A�gI[%���Q���=�
2���N�/�Q�N�������j�
jh�O`�H�H�`������.r��.���w�r��U�.���)v�.�B���.2�\��z6�@=�2�����P���1}�
����d���@�P-Qd�aQ��2l`�x"k;U����>Ar,��68����q�L��{�a������_M���zQx���q/�����U����~"v��5����E����E��.�
v�n�����\{�a�Q�b�A�"�.r�%W��{T�"}�A���.�Q�("�H.�]dE�"�"�	��P���{��Bb�N���������&����-L�5=#b�����M���9��j�Vu{{ :>�n����[K�����?;�����\�_�mTu���=
���g����]�B���XU?�r�Y�]����]d^5��]d�"]������.����=o�=z-r�)g������.7X�"������"m"�.	�����]d^��l�P*��m�g@Np�|����?_s,���������.���!��R3D-T�="m�(�E�&K.#n��[���e�s�w������2m�j����6Iu������0�\A�kiO'�<�/d>��F��o�^�Y��4l�*��Hl�u�� ���v�v<�{�m����q��z^b����?~���.? ~�Y	.R>�g@&���{=8A�����n,��R�����W�eW���6�&RQ���P�V��"n`y��8�9n�dz�_]6�6�*	m���������"Q�	�^��~������"gM�d��U�*fM3�Pi�@U��Hl�h�&rI���H#�Y��.r�`s��.��4�����nEo�<�������N{I�@��0�]��=Q��7,��/$����z�d=�b�U��`�����L������w�'/X&u����i�n���m�d��(�k60�
"kU�����@Fc�e������$���p���U�Z
�Pq4�y:������lB��<Y���.��	`���4�5�i���"#r�]d��~����E�q��.��v���
&��Z`�^q�������^�<����������
��Z�b�I"�t����""��,���)YW����t��`�D�j��)$��0�|�`�o=o\�+���ll@���Tc��W�����������U��+M�V����QF3�7�^
tX:�,�,�-������6���bO�Y.F�Pn �U���l3���]dy#�"��	l���]����@��7�"����Ys���]$�b*����f����+�q6���������N����'����f0}�c��+Y�A��o&��,�#���sx��Yr8�
�a��M�p�qW'��h�����/��;"���
�[T��j���5��Wem�J��#N��[��������W��g)pg���7�(�a���XnF����B1x�mts�=��|G�b����f�I��E�T����7U���"���E��.r�]�E�*.��5�"{�g�)g�w�m��1{�L��^|�G��m$�b�;E�)���wSfW�%�dM��A�w� ��C���BBS30p�v�������}����D�lYG)��JK$�Wu�;Q��w�������j�p�����7�+�����a���8~�lV, ����n�G>zt6@v��c�1���P���]$�A�
aO�]I�b���vLNq���[������v{+�����nk�5v^=f��~�%�����Y������f
��]:�Yz��v>L��D�l��%J
���2�`g������em�����sA$G�-~vsU�-y����:��v�>�;����z+K����nE�_)f����� �S(�����1=C_i�zJSCxB�/��-Tqm*����<"0S��L���t�k����}���}����M�2�"#�,}�{@i�
��[
kI���.>Uvc�q��=o\���9�����a,S*Ts8��-��(�F~D���������R�l���:���.��%�:�&��{A��%����6t������l&�<N��o�P�c5�����6T����MU5Sx�YA&���d�<�D���{��9�&~���|=g:�u�=�_��opV^������R��Z�z�C���6]����i���I�$�i9��E���X��zw"k�(t����q�#��"v�������_�k:�m�L����C���
�-r�(��<	E�D����*f��������'�T������P�j`����������K�'��c�����<W|�|]'�����������9�M8�{�P���������n)$���/�*�	��#��R�S`,0�Tc ��H���4�,��5�n���,2�7��g)p��C��Sr��A�Ro��(����.MV�j����@��(�5��1��Ri� �(��Qe
t�I��t���Ek�::K���N���{v�3��]>C�����`,�$�j�!���'��
y��XK�: B]�4�[����DLw^/�����d��oix��_�z�LE�V�n'���?B��"�2
�D	P]��cX38�~@i���`�������W:9�%'Knn4,����7	.��cmI�����[��O_ g����
{���O5���O��I3I�^��)�R������s�lmKM�V��bn#�]��H�y������i?��A�}Y0���*
r��&�����,��.w

�t$�i�������z����o�~%Uy�H_%
}]�
��L�!V����jN�]�����SV���s����7����x�u�[U:���v#��3��#���q/��F�Y�~@*��4`�J��C��������C�aK6I�$xTC�7P
���76U�A��E�G�y�H[F��!~���M�#�a���	7x����_�;D�&���U�]�Lo��(�.������N~��hh��^@�R������
`P�$�7b���g\:%��W����s���gOm3:OT�����;Tk,Y|�H�E�xW#���������k.����#��<��K��$���Nf�y���:�^�s������;��d�p}�L�����=��4�I@o0dH)%=��Bb��b�
�J���G'���,��m��U����1�r��&��\2V�
�����G�{���0mB�_i�N��?\7���?9�>��T�W�m`��J�[M6����4�
}^P��M'��A'����J��C��,�Q�NNp����Z�BC�����{+�I��o!XT���G��l�:���������n�cRrn�?\���<K��}^M��X���6��js�S\�5��O��h���/��f~�X�5�V��
`P�$�7��x���+�v:8��>��E��n<q@���R�0�[��(�H���I�p��d��M]��F~�[a��H�_�����3���2�,n�+eq��Kouy(��@W~�3;(d�}��o@��Pq��>����
P	�4�I@o0)k��;m��[g��v��y=;�9?�L.U�=�C����p�
s"u�(�U�60z��I5� ���v?&�&�8��r
y�7�����h�Su�{@1������t:?�_�����O��ZrE"����.=�j@i���`p�G����x���s�����&�s8�)6��v���h�j�������}�H_CU�E�ZU��1�mU��������R����E/���,�%�����!Co�(��j!��H�%������jd�
��@����r���4�I@o0(`��}�p�i������vI�$�s=?�OU
z}�N�qSd{��QD��d�%�������B+��'�X���<K�;�N��v�o)Qu������P�=r;���@�/+fu?@�W���(/���C
����
PO@i���@�)o��}��/v

���n����`���0]������G��)�D�/���1_�y�T�#D|�����\t'�y{�Iy<���,B+�y_�
W��P�B'}�v]�zE1xj�Z���QN����H@="=����&����Oh�v

]s,�v�N�oS{���s~b�\$k�T�p�A�����Z"k�(�=�0�-"cU}	�T����	����'cL�I1�a����vy�e,���4��'�~������<��\�����G����'��g�4�I@o�np�1N���Sh�AM���;�-6�_�u��xjt����[��P���?9�AG���RC�NWu���R�}=���G��,���a�|'�&U��V��R���<�"�?���3�'�B��i���8��~`3�z6`�J���CU3e�'�s�Sh���[�s��:cr�Q
A\�����o�d�e&D�|Q��60v2��j
Ru����kv)����4�i�L�����>~��.��(�yGf3�����co������D,uY����g?�4�I@o���v

�Y�W�������Xf�j�#������D�Q���=`������>~���������;�������O�,�6�>[�����
���<O�����)dEZ��\���N�wh�T��C�����(
`������]�zH�/p�v�������9 �����n}�L��N�������2��Ru��P�Va���7��<I"~s�x"��wIh�@�����-��6q�s���[<�8�q�^Cl*S7�CP��4�I@o�jZ(�G�����tk�[IM(?cr�qMab��./j���3�R#"y�(h�LH���,8A5����������kE\�xB������2�3_�c�jQ��i>��T�j�L��v%;���tF-�@i3��&��$G�:���;��`��SCLg���5�n�b��o6P�6D�FQ����#�#��S�H�[��XU^%�o�y,���m;w=�<�#R�$�`��;�|t��|��T�j�A&��I���P}a��c��4�@i�����"��(�`�)4��>��%[���nY��tAu
����1��?$��Z�p�����d�)��2�<i�E�������gg8����`�bW������2U?A7�
(�����y��<8]�9k�[T��*'�e3��f�LzeS�J���]�j��f��9R�������L�-�T��2�4S4J�p�)d����&�ANS�c�����K���i��b����"���@�!6�Y>t*����������T�������~�xc��4�@i���@y$�������9)54t��l��d�P8_Y}�����&2�������!����uFD���Dnj�����WR����4��k���m�'LR���c�-*|�NpQ�/�;�n.��+d5�G�#�=(�.���F�X0(
`P�$�7p"��$�d��t�G�y�-�$mA�i�j����>�d�Br�?2��(��0�U"u)Ya�x�����'IuYw�]�#.�r���"�2�}����
�r��U���p�P��;�,����V���.��v��[�2Mym��`P��4�I@o0���R����Ol�|����nd��-54T��0-I�
x�oiK"K����d{��g����"=�%z���0���EA��o��=����e�F�9�L���Tu9���r�����j):��b_�A�����<��&�X0(
`P�$�7RJ����BC7MsX}B�
�_����llPu��E�A5Uy�H_-
'�F}B�������,{�VDU����B��9�U��t�R��oixK=�����������!��6��_!�-(���l4��`P��4�I@o�O��E[nv

=��#|����;���<T�j��@�Br�o2w�(�s9�A�i��JK�/W��@Fc�]���h����2��=�:ed��������
D��?���
�����&f�JbU�$���`P��4�I@o�7�Y�� �B�'6p�N����sg��z��(S�[��
�}�O�#g��0W�Z�k��*N�_i�a����G~�_!���q��`�4�����
�/��kCy�(����~��<����^EEQH�A����`P��4�I@o�(ie��S���M�SW����s��Q�
g���~9UiI����K�p�����T�"9�5�+������r�����&�W�h����V�i�,��/�;+���
����kP�1*�@���>c��4�@i���@~|SE�,;������h����]�>�n�jx��l�����+��D�G���*o#A5cM-h)u)�?g��GC!�������w���2T�P�F��(��Y�NOT��}D;�@�&�V�
�f��J��2idQV!�EFOl�"�r�-�y3��z��(?W�
W%Y�w�#�"����Y���:g�E�Zw-����S?9���NqX�9��Q����N=3�����
�P���w�c�
�����rza^M:���`P��4�I@o��i����v�x�UG����?gq�-��fU7\E�J��D�2Q���m`�d�A���\����c��q$�`���{�>cb����T�@;{��:��z-:������t��G��\\��n?@�X0(
`P�$�7��Gi�V�BCO�q�^�Vjh��M� ?U�ZmT�+��K��l�&�����F�Ze���U�]z1�r�#m��t��{C�Xd�EV%��*�:W��R�i�u
]���<��X�|��,_:����2�@i3��&��$Ml�v�`�1��.>Uv}�I����9�6}�(_�
g�%�,�%����^ �f�%�+U�Mb����)73�������A!��OK?��WqHi[�R�U(�y��9 ��Ga���co������F�!���G`,��0(
`����!��v

����R[jh��9�[T�P���
n>YnF�.�,��}R��jPj�r����tb�.��������p���������g�<T����#�c�b}�K�������F^'Q�'jS���:c��4�@i���  C��v��P�=�1VKs��[����9j����u"�w�">�#�m"s#Um��
J�[�-���WR�����R~�����A'�����m��x�z��B%q(�r�F�s��{}t�:2��B��Q�+j�`�)��f��J��[Z8�n�p��N��76����g'8kj���D��a�9�,8I�� G8�h"yYj���w���O�����]�#.�v���"���zq����-%�o��p�QA8��@N�����&�>�?��H�k��P�s(�
52��
�f��J����[���Wu#����[����Z��+J

]9�����g����C�]%R��_�mc�#�QM��n��������8�|����2���l�;o��[�����=(D[-�Fa��a72����������G6��$������2�@i3��&���[Mb���&����J$(S��N�������������V+Q3UcOdm�O�����5�;$l�yc����Q�h��pW��4��
y�
��
�n���W������e?�3><���D�^���;�2�	=��BL�-�Jo���2�@i3��&�������Zk��gQ�n��`{/B��Dh���%77�����=���,Q6dh�����_�0x���,��8���"�o�l,���>}e��.��������ye4���k�Ec1��B������H�����co��3��~��"V�r[>���`P��4�I@o�L\���j�M8�M������:���>��BSjh��\������+v&YjL$��(�q?�'���>Z����S��,�0��&��?����NsZ�3X�z�����V��_����CZ���������������7}���&��DEQC/��c��4�@i�����idQ�/�%���K�IU7M�����OBCg�n<��.~�r���Z;���n�@#l�j��D���^
�����A�:!����D�G�����r�����f�W�8��(��U9�hVe�d���n-�c���K�:���ag�J��@�)��+0��J��0	�
���.�.fP|�����VGKX�B���P��EV/�1�GX?�'�}��T�
H��@2��(�[9�A_!R��f��? ]�R�Zp:�l����,��Z�f�&�e�	��4�	��(��N�`����_���'�r	�<����n'�W`,��0(
`������\&��_s.�����e���$[��`��

i��kqm)�P	
%����D�,�0�"�'�P�j������B+�LSmv���q��p���-���X�G�reP#/��dn���yH���[��#��/����G%;���k$0��X0(
`P�$�7�V]{b7Yp"t���������Q���h���%�n��d�4'�rh� ��;��a#��M�"�~�,�FN$�wQu��9����rmr=�F��Plp��^�����~9ME��[��"Q�M:���Lt�����/���"�u�����n`Lf��`P��4�I@o�4��	$�_Gt����a9���~i�}�\Ih��2z�i6�
5�8�CC��rS"c�(�Sy��O$R���������}J�.&Z�tH!8�y����73���S��~g+a���n�8���7����_�;�����d��f��J���HU3%��L�:���rb'���E��������o����*���N����l �~	����
����Z����?B$L��\����	���3TkL�?{����L�}�g��S��{����i���G�z��J:1_��p{������w���Z�����e3��f�Lzzd��'q�K�9�n�{�t��n����<!�N���xAp��2����.���
�CC�j������8���H_)�xON�8CD���}���\�T��{u��^��<�G"
lr=R��(T�oi,F��(�2�����oL����7��_��^aN'����D@]��`P��4�I@o@w2D�F/4��p�.y	��+TF{��ICo��K�G���:��A���2l��=<oW��U�x�eT��w���*��n{F��J���-���&)�[�OuX%���q���S��6�q-��w#��[����G�k��o��Q}w�d.P�*�F�A�K�f��J��t��C�g�h?��R90S����L\rOm����������/6P{����$�j��M[&Wf@�4�H���?L�	#�����	Ar}�u��v���n[Z\���t��ka@A�\0;�-������^��O��������b��de	��c��4�@i����.�<�8S�]�F�^?*��b	�|��lCfy��?�"{�^��n'�e�e�@/u���B�����K��W�E������d�u�����-i��,>�pc��A����5�/��r��M���N+RP�m���M�~��������Y-E^'!��;0��J��0	�
�$���tv����L.!�s�|�Y��XB69�7[pg�5�����|_�6�Yk�Z�@�E5�������q���������ST�7�e�K���J4O�;D��u���Wl�?j�t�QYd�N��Qi<���w���n�:����F)N��P�f��J��H���I��o����
��R��+�9�:Y�����v!��<���w���>���e���;�7(��MU�!���|��"`�$"kUi��}��ZncR]Vtu��h����Z\����.�;�Q�t{t��(e��5 ������������><8tc��4�@i�����:��[MRl?4���\����S�-����A��;��$���XXK.6�H���
������\d#\w�sH��u�v��S{]
���p�Z[��-(���j�#���������5���"���)!���-cU�V���v���������(dqZ�;D�F����D����w���]G{���M�g������dM�9$���X0(
`P�$�7@L#��}����s0<��q��
�����i����#/q���j�I'K��6��S�ib1���?�?�e�!6P��V6��FVX��EQ�+��-������8y�Tns�_i�y��C��W�h*d�:���/&Zz��I�����L�$}�?�������'�������6�
�d�X0(
`P�$�7@��S��v+�e;+~�"��x�/��rL�������z��p�����S�:m#�:'BW-���Ac�
T�'Yp�H�U���0�-"u	Yr�jE$W�������\���+)�a�x�������m�����%�K���X�w������~%�;>]��q�����d��Lz��0(
`����#�����
�v��_n����n��G�6�s|SE������>�7������6�jK �M��u���I
?����j������qck����/$Xl:����>�?|-���~�4�&�<�������Gin'���_��N����F.e&���`���4�@i����6:u$P�Ak\��u�� *���+\��<��c��n����{C������
�{��6��Y�_����u&�	�DA/(����j�������0z���n��
��vZ�g�7�a�j�����,3��+l�Z�������d�G�������Aq�M�}�$�7�@i3��&�z���9�:�9?�����U���b�qQ��-�������'�*��b�MYjD���OP<)������-%��"-2��D�����~E���������3���Y�X��}����d��s��C^�����}�~{���Y.y���"���-�-���f��J��6���#���v����S�������FF�yy�60g��zG��@^	UcG��'�~P<)�jK�r?������^d�b�?���������w9��S�_b]fKC*OB��!�������N=�����O|i>�.|���B�g�d�Z4��Lz��0(
`��0g�A��Sc[��m).G���o�rl����'���ei��
$�Ts(Yr�H]"
�XR���T��dR�^s|m�}�������t�����k��p}�H�����W������["��������$���m����y��	��-���f��J��6�q_{��&���O�$��X�XV��;����j�'K��B]��I
�"kYa�Xi�;U�j�+��]�bM7����M?��_}w��{��lV&�[Ya��}�W��5:���4}����p����|Q�����I@o3��f�Lz�K��
PusG�H/�����;��_D��(`C^#���Ez���-����?��Q�+}��7�������}�o��������S|����	���b��u�
z��b!��E�{�N�6���o��0(
`P�$��aN�l�������J�D�d�>:`�
�������X��2*=��MR�i��_��[N������?�����l��3>��+uZ/(��a/����3���j��+�^���\����l�o��0(
`P�$��aN���b?HT��� �Tk,Uy��;H$�����������M\�v�!������:������~�����o{�O�3������g&���whL����e��Jg��>�nE�:(�e���4�iR�/�_@�0	�
`P��4�I@o����s�cdn]WuC"y�-���G�&���"�S���?���������6��gwV+L��L������E����F_��0�[����c��^�����L�������j)r��.�[���T��+�[&��J��0	�m�C�4�������f�R5��D�"Q�D9M_���\�����t�|������wx,Y��r������G�Kn�����W'_5�����A��L;�J�f?���~�NODWg ��t��k(������>���`���4�@i���TB}}�����{��������[�bErr��7III�o�o�7��������SFkvU�@�����(���M�����"��p�|���3�ow9M]����v;�T���n�������`�������pll���g�e���N�zcz����se?B�Y�����W���`���4�@i����'''�����������666&Lx��������=~~#~;�������#�m����rj+�j��w��!sv���������W��b��8�	���u�z�����N��'v|Sl.l?�����}a}�#o=:��Xk4[�Ye9>|��@g����S6$���H�X��/vp}�$�7�@i3��&�1�@ �����z�)l�:
KJJ^x��#F������qel���;
����m'N��?b���a]�������~����z_��(o�wo{||��+
��9N��n.v|?�.\pg��iGL�{�����?��}'�����G�����_Bg?C��#�M���0G��<��x�u�}�$�7�@i3��&�1��k��k�4iR�������e���s��K���{���R��W_�rSS��ik;TkY�O$������<���r��^^��������S.��:MY�8}���>��~��k���#�_�����=N��w�N���js��;�� 
�[&��J��0	��a���[l�N�<��<$$�?��s---�������g�����������������~6�j�"�/I�D�c���|4:��
���v�|������>�m<�����>r8����;!���;66������x^�F��:�&����|���.��@���<	������-���f��J���$���O������%�%~������8;;�k��v=����S�RS����6�@�%��h	|)�����o]~���c�6��'C�����4��E����"n�/T��Z�{@�q�o��0(
`P�$�7&	����������+����O�~===\���^��RZZ������r6�9yG��g���&\�y����#�v|G���� �9t6v�S����%�4
C�[&��J��0	��Illl�~������'N�/m�����l��W�����T]]-����lR�2c;)����w��[����F�[��I~����x�R)g#���-���f��J���$7n��������~����U�V�~��+W�j��y������������I����#c+/���xj��9�wW���	�B���[(�e���T����	yr6�@�0	�
`P��4�I@oL���4iR?�`SS��~����]|_��I���2�}��T���.����[&��J��0	��I�0^����Zc���>����M�|3��o���
���������Z}�9��z�7�f���o������&%#-}hh(.��g���^WWw@����k��e���/��kjj��e��u)������K���Kq�}��u)����q�������?����>����������l���#F�����������/<����������<j������B|[|s��~
�����7n���qqq�������s�=goo������x?�������+��L�0��������������NCC�������-_�<99�{�����'�?��3`SRR����M���
�G�0�IMM����<y��/������7n���NNN��%%%e��2���X�}������=��'�|baa����g=��S/^��K�.��z��^����L�>���_5j��_~i`` ��W�=RQQ����?��oXB|�������|~��r����`���c��y���������?z��=O?�tLL�?���aq������.��F���g�ijjVVVJ�b�$::jx�������s31XoXuX{X�X�X�����������1���^Z�|yiii�:A|��W��[[[z:����w�'�ZZZ���			���xD��K�,
���boo���	&���������}������F��/���
���yZZ��;�=�������f�����~�i��a\]]�j�?��~\a��iX�������q��)G��
�gggl���;kk�������]�v�UW]]����b�o|�����������
�?�r������[�nU���3�<��p��	l�|||��Y�����X$����y�z�R����?q����sn�qg,'|����GDD`��1��?�KMl���V�����
�0�������+W���G���P	3f������\����r�������#]�ggg�1w2�����5��'
��Bwww\�w����?�����ojj�����6�2��?---o���Xf����;w��_~��������7l� Y�t'44��g�]�p!A��X'����b������i�,++�������u(��%���jcc�?�~����a����R�+~��$IJ���y���y��������}[��n&F,��;wv��:�|�
.�������_�����F�#v|�����%���t��1�Q��YP1���?��^~��A�_���_��"���x�����p���iG�x�����Q"^�����(�������5k�a����m�^|���g�J��xl?~��\HLCC���O?����Qb��;��?��������t�'�7o��r�%
�m��I�&���(����q�()��������_7[�'�����w��9���X�j�������a������y����Z�r777\���?666����'w����%�9J���7++�oO
���q����m���w�����5577����0((�K}\��w�u��X�����v����v��M�6f���6`h��������������/=��s<��KX6�%mm���q4����������g��u�qV��|��W_����)���C��C�a|��G]������(XG!�
���&�*47C�����~�R�@<������%999��Y�fu��J�������z��$88���!C�{����������������c�#Bo��m�G��:����%�q��U%?
�^�Y�8M�:+��A���W_}��%�X��_t����.�Z�
����;'Oe�����K$�������^��������$''��	�A��k������<--M<,fggw��E���������o�|����%<������?��������'.�����?
��O>���w��������oJ~��d����S������:�����x�������~����o7n��_�%��>|����O�z����O�/-\���K��,���}a 6�|�����mLL�������U��[o�Y�wV]*+$����K�����>������?FGGc�u����@yy��Q��*���$�O�8���$Al�����
��D"�q���q�����/��1��������#:�{�-[���p�B/
`��������fff��[�n}�}w|������>�����3a���#G�����Nl0��['~u���p8�0$%%��g����������%I���b�8�H"�o\/���c��������x~���g���������������TVV6o�<���[�P���_~��o�'�7p�3z�h���������CCC,��~���-�(2��Bs���Jq��������}�S�G�t�\�~]��bb����X�����}/��Q�f��=	�����#��r.���+q9����"!�H�}���������xV�i�&q��R����mC��vo��6.��D�
a����o����O;�����<���\����(XG!�
������%_�S \8b��3�����;��#.����_\nll,^��������a�K/�����}�6�JyT@m(//�bp�v���.G#�82��Bs���\q���c����o���d��^x���&L����/._�p!�KQ�{��W,��#Gb�XTT��G@�466����W^�����R/}���A1���---�)��N���^�-�c�������[��}��y%<�z.^����OGFFv���v����5�����b�B��y<�������K�?������pIFFF�7����t]���'M��?���x�4y�d<Q��I<|����122��h___--�g�yvI�b�?~����w?(�����v�����ia��E����������X�������������c���=G!�<����/#G�������B1	��c�fee��S��������x��wG���o��`����Xv��%Y8P����
O:��.����Oz���:JDlxJ��1���Lri���nG�Cq?6j����R���o��Bl���o�8�H��8����#�(���7��B�!.�������(���Rr���CJ.�P(����O�������?�\`�~w�z�;3���:�������Z�ly����P�Q���^4��?F����������/�����;S.�����9sf���9��BQ{��z��uYY��������o������jjj������I��w�=��Y�������t�rQY�l����s�&�KKJJ����������
�������}�vZa�������4'}���7w������=;�����d���iSTK���?���c��]����}�����/.��h�'J���U ���S��[��mY�hQ��-��������7h�v��%;v�h�K�����>i0���v�������%��d�7w�������`����&[�q���<��>d��x���7i�3fD���7����J��������?~����oZ"�(VS���;6+p���1c2Y�M�����+��;7�|��Un�v���C�����_G������cs��'O��{�^8�49����+W��h����&-Y�lY<u���������Y�������yZ�l���ujs�%[r"s��(��W]]���:wAT�m���Q'{������$���5k�!z���s���g>���O�Q���G�wl�����5e����=}�4�|��e<2r���:]�t1��KL����I�P9��}�9�f����)��={�4�[�&�N�����7-Y�~}��?F����1���3��	c�j��������l�;w.�m�V��������W�%M	�'O��k����2�0Y��}
���c3��5G�?.++�|�zQ�F��s>������;w"�Z�jS���F�^�z���r=z4�D��$�E�w���|��!c�(�Vb2XUU�P�v&w>�Niii�?~�8-L�dWTThC���
����?
�{�!C�H���(0H>u���O�l����~�`�����_�reva���K�.��=�.��`��~��m$WOR|�C�/^��4F�M}I����[�i<�L��mV)�FQ�g>X��,YA���6�q���Q���oy��}�������cvy�O������#G�r���E�L�'J�����_���[�g��z������w����������]�v=z��>������w��)��%K��h�������G6l�8�����I�����$�N
j�Z�**L�8�����/_N�N�0!�;�K��x�����C�]^�x���]��e��2����en��doN�q=[r@����OG�8m�4G4c?~�:ujDB�n�v��}�����$&��m��9����I\�3�<y2�F����@[��,"-�-~���K##��llSa*Yh��~>x��c���F��u���+W�op��^���3�=����n��y���i����555
V4�$���(}��):��3����(���f#������3�������s����
6l��
>�l@������m�F���C��m�4h��5��?o�~Q�� �z�$.\��k���H�7.w_���/_>\YY�b4/���X�`���W{D�QXzTD���}���Y����;#�"##�;V���w�^�vDu����O�<9~TLg���<z
�?���G
endstream
endobj
14 0 obj
<</Type /XObject
/Subtype /Image
/Width 1200
/Height 742
/ColorSpace [/ICCBased 5 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 61625>> stream
x��������$�5'�yO������������E��W���5�RX�E��Y:�����Rw��K���.��l�����pg�Ww��.���f����yf�����	@�5{��vK�,��^�-\��Ys��w���3g�8�G}�w�����}">��c���s� l�k����.]���G����U�Vy������*'O��[���yNN�`�*;k��	���3f�51'8������O��|P��g���o���|�GIII��Z�A�s�`T��C>�������;��:t(� @�A>�A���h��Qr�;u�d}��|��G>�A���e������_���������z�|�r1v��I���#U���&IYRR��+$#��eK~~~�����>|X�e%�JLLLNN����|�������m[�v�lZ��i���KKKC/,<y���
�.]���$_�����h����~���d���Q
�J�o�.Gr���j���z����k�����-[&�B�����\��9��B9������g���z�����~	*����+7n�(g����:��#�$V���R@�I4�5"�4�����#�������A|��g�:$�$�����m���o?f����������G���C�����~*M���$J�K9I���������.����:T�^XX���3�)�G�v����F�9r�H���>����F�aW"���'~����))@�`>([vFf��m+,�����O>q�Jb�u=p>~���_�<�g��+V�v����"�����G�~��W������`ZZZ��!$x���35}���;:�K�3s��`�Y�w$//o��i��}���;w�g��&����
�� �����+����v�������w��l��cm�K�.S�L��j���,1b�N�$es�m�N>XRRb�N��_~9�|���e��I��=S>����;w:�n�����w��}��
��({��K{^�G�,��>rN�<b%��!u�eUr^z�����$B�=���-[�\ko�y>(GLrp5W*0k�,��,�
5]b�5�	�FI�em��w���/%Ic����,_�|��I�K����Z�;r����]��c(�^�r��0�b]j�����������V�L�D�A�'�Lq�5k�����y����n=z�Z211Q7;?���1�4~�xU&!!��e����;��/�^B��������$
�b���J��H���K��lQ�"'N��\�~����|P��}���]�;wnzz��l���A����.#�]��;u�T}�6o�l������qi���%���t�����/.**�s�V��r����V���*ft����a�:#��������b�����s-�������N�>�	���;��.J�n[�����"��^��M����wrr���'�Q�Mo(�|P���\E��x$�BTb@g�r4lWGaa���c�\)&�f
��TF����V1!�s�.]Tg����w��!_~��s���-..N�I�l�*%��$G�����m�@U��.��W���g��1"��$�����Z����E���n��={��������Y�|P���W:{!%��O-Jn��W�!�����1�]U�, +��
m���u�&L�`}����r�A3f�k�A��Vr<�i���q����Yr���WAA�$:S���4�Z�|�S�nG��Nb�>}�U��7�\;vL�I�&����-��*��kWIkjG�����{�V�]�v�2��������$�t�A�X��,B�!������+����/�{g���~������D����O����C����a��v��Uk�)�|gI�t�b?|�����M��\I��������@���d�k���X�,5k�����;�I.�������0���#�������:"]�#1�,�m�6g�"<z���qC���A���G��e��=���z�c����Q�^�z��5�;��vn?2�x��Z��q�f^�|�I�������J���U>��"T\���R���;v�,����g��������!*s��q]R2,�\�[$��b=���v��A���z�+�%q�_e����b�/n$O��9s�����)�G����\��i���]�#�\\\l{-4X>(��z�W
���k��������$�w�}�aG�Y���V�9]�l��k����5$X�,uV��t����2�x������i�@��O��������&4�|P��i������s��k��u�N�5������)�A���l�6�Nd��Z���)���~�>��IZ����>���qVRy�@���'�����8@P���>
k=�!�0R��	�&��4*��K���IIIj����W�����M�Y�&ta9���s��vD2q�����������DUCIK�s��c������;�5�U��[�z���c{����S'=�����{]�y>h}�-��Q����			��:tHs����4t�Q��#vZ�c9z��	���2���q���-�����TD�'����t=z�]�#��>#�a!^�Sf���O�6�Y��F��l�q����-SS��	h3x�`��`/�jS�L	�1��5b�U%�$�������,����4\�x�����e�GA�/�����X�hQ���$�s�J��������D������;���X��6W��;v��|�����WNNN$5�Y[�n��=���T'������-SS��:�
8c�>8I�ua��]k�WW�|P�a�T�D��>=�R�\���mG��G����dr
����SrTU���K�`���x��R9G���4i�.l�D�v�5[���O$#�t���3��aR��Z�2s>����]��8y����U�N�H���������w#Mz�#�?��?���kW�3�!��<h=��{�X?�1`�gk�k)�t>����Qt�����R��������M��������#����U�1c�s�R���u��e��` �NT��utM[����h�
�N��?x�����C$qp~91k7M������$��gG}2`��!���0�*��C�'���&��T�,��*��fgg[?����YY�A�t����2l�;��aOHH��#�R�t���t|Q�������4&��E�����U�=J���j6�V�����F���'OZ[��
��a�W����yQ�s�N�]=R����N��:y�d5Q������]��a��y���A�e����QTTd}�3��4�5���QUW��9����5����7�Y�|�V#��XSIC��f�A�h�a�]	�F����2��v�cs���������+ta_��	T=F�?}��Vu�����h{��Ge)�G�[u��ow]��0�GO���F�>}��@�</j�S������)7p6AV\��J������;v���W�����?u������`qqqa8�p�ams��*����D�ta���S���
�����J]'�|oB������j$���#�������X{�l��p��f�{�u<L9���n��a�br<u�����{��_:u��|Y������{�����V�}��{�v�����������U<�������,X���aC����� �w"��j�+�N+k��_�+�kW�`����v��7���{����[S����E�!"����F_����m����z�n�b%��M�%
����Y9S*�p&��?'M�4u��v����a�}�^Rig/����
J1n�8�5XGX���/�nQ.�vU?�T>��O��;w�(c-v������$�A�X����?'''XI�0�����"��8��k�\�v������N%�\E������M��~4��������b�e���C�?�;��=���X�l
r�����+**�u��6�^ ���\����c��]�ti���z{���+�7n��,s�(�������5����a�t��C6I�T�`����#_}�U�p]���}�D$�5�|�;�|P����#��}�.��W/g�3|�p]`��������,�\ ������t��yz���o��:������8��
�\>�a*7s��`���Vul��;�jY?��_ee���U�"�����Gb3c��9
����������	W��,�)((�Ag
�O�b������wRB�����2�D��z�.�S���EK9����mGT>(1����K��u��c~��;��������j��������$&&��3����=x���",��{SRR:v�h-���ZV�����_�8p��(��N�:�D�k-,5�f�*��sgg�Snn��c����Y�%�:X�i���V1]�����e��Dg-i�.����L������{�vU9x�V���?�9k�^*�>�h{C��,�����bc��q�bt������ZLrpk��S�F�r�a��mh4''G�w9P��79}�PH6��#G^�`9�.0a���$tz������
���W~~��X�j%�r}9���������v$p6T���Y`���:]
�K�yrM��+**�{-�`�E�_������w��������c�H�1�c~�6m��{]�t��e���'NT��������BkS��*�C���
[�|�d:�'h�����pYg���dI�-Y�L�����v�8��#�b���	�i�s'�BV%S�J����f1��<p���qP��H����>SS�L�b}Q����*�wBt�FK����^�N(�1�yA�#}%�f�����(���O�'�|���9�!����w���4W:����d����k��5������Y�x��9r��pdO]OM�;"d���TX��h�"��F���#�L�4���_X�7!!!����m�������:�"-UiIfgg�^���u��$>�����X�7�9��@��u�oy+�Y�sa���:h� �v����[��|0P�0�5m���@2�H���2�P;SI��C���IIIz��������j��z�(�
���GT_f�\���[I*�|��`o��|0P�E;g�������r}{L�:�`EE�\�&L���k��%Uw���/�A3���r��� V�X�r�������9u�Trr�,�t��u�����7�~���Bi��Z�JrC�oZZZ�qE4���m���Y����uk��yJ�,��gI{%y��8p �����$&&�J$#�5D��{�pi��^���%�0���K�I�JN��k�`�''N�q9�rq��H��~��������}�v���*�����Z�� �	��\r��1�������s^yy�~M,�'9�+��������C����"y�@=A>xnKOOW#��;�d@�jt��*k����������hG;Am�w���O�o��\��,�1���y���q�����F0m���:��~W�EFF��1cf��]VV�w])))�KF��w�P+l���[�n�|�Z�Q	Q�'N���z�j_��
S��7�����G�n�RQQQ��P�*\��m�&���Pk��9s����C����w?������A(��H0�m$�|�VExTB��|��e��)5���riii��f@�����YSk�����a��M�8�������[II	� ����b�ka�G(D�U>�m��#A�>}��:W��u��^�����SSYY�w-�G>W�������Vs�;v�|�@��P��P�����|�b��=���-��u��^ �
� \�j��xD�7�V�X���;�:k�����srr�-[6n������?~��%YYY���`YY���{e���xId����z��y{��q>#�`�� #���1#�u*;v��5k��1c�
6z��i��I
s������-[��F��^��]�l#�DX�H%������{�����'J}����TUXfm��]*3a��;b��o��f����M)9��z�<yRvVR�I�&��c��]�p�LV����u���������@�����e�*r�,��IJJ��(�����-_�\N��Q������S�e�A	WY�lWV(Qa[[�1e�`�O��:wD�"q.�	�#��T%����[�v����A9������,�e(5�s!p��Q�e����i��,Um9�r�JM��9b���]��>x�`�������[��J�N�<YN�����T2����9�S/����S�br�d��h���7nT����U��;&1����j���WS� ����������w���
��			rE��!f�]��ddr��]E��9�S���b���O��J����S��������y��E��?U3O���L���4���kmcK���i���+W����L�� X>��KY��	%g�������i!���S^^n-,���NH���|�4cb[g���'������=�6�4�uZd��i�IHf��9SZ)R~��
���)��O��]���$\�:U)��WZ��J�X�6�����)&�R�(u�<]�����,�^��vG?~\

���j�4U��<2jA9�r�%$M����"��G�"(9�����xJ�-�~�"k�
��qi��]V�*�\T�� �i�d������\HS�����Ov��R����vD���i��@��B��mG�L�*YD��$��w�/�C-���Ry���[�e����%��B��G"����Q6-�NKK�2z<������^�*���.�V���-.'EE�D�����,������h/����A���o���^�T�$p��)U
9�2K�!�:��c;�rL�7Y$��Vr��U�/@�p���������.,�vg-"��Y��[��PS���rW�S#k������-���f���Vw3�Rs9�!~����j�,X��9WR*i)��;���j,I�$�=����\	��	���2���R�?>.���a��v����tI@l�Q5��46��������MvYR�������H���YZ��Z���lB�@�f����:�rv/^g���H�m=G�Q���`��}��r�$�Q]<�_j��8G�p�*f��mY�5$e�6�dqn���S5�%!������=R�����qYV��*������I�:�k���|Y�g'B�g�$����lE����I�wD�z�eG���M���YW%i������)/m`u���^T*�����;�����Oz��1�(���T��V��������*����]+ ��ZD2���.���S/���S������w�,U�KF&�Au���Z��e�1I	T�-!�~I�\;X���#�NM����O.��#��BI���}Qi��
�A���|�:]�B�6�T���P��R��2�5���(�+�'q����N����	b�|�r�c�������G5���/���bg�G3�5��q;��k�.�6��v���Q�S����c+/�i�����Pi)9�us7---�
KKI����V�w��Q%	�-�S�\\�b�'Wu>(i�mOu��mwt;��X���j�3���������2/g
���.X���S��,���Vj���[�<����R�mD�;�|����X�;��-sN�4��B�[�9������Z��_k�����R+�y��4b��%���.\���k�Gua�F�z������,�v	��I�o[[�GRG������|'X>(��br�G���~x�+�u�YYYj��m���V�!�k�j�������s�`���k���]>R=��9s�����Wj��������?�K�5n�8���uF�:bL~~~��������2g�;Az�:U��4��H����u�����Ki{�N�����*,��;����`tZt��age���M��.R?�K;�y�t>�L$w���f�U-���G�nK�qn���������`��Uj[��������z�%�����Mb����B�)������]wD�;�^�>�,	����I��e����������AgR ����Z;��|�I�d$����v����97�����7���_�1��~��9�Y:�VIY�re\U��mz�GR��*Pul���
;;�%=�6�c[��I��lrr��k��%������������;�P��3��@��qW�K�u��������m�����C�/*��4�s�R���9�����:u�!-"I�B<������9�Fe=����Da+,[\�d��JK�.
�G6:-�p iAIs]���s��:�
������smg�ZQ���|�������]r]w��K�^^�:u�m����3��p���G��b�~�#.t
������Oo������1������j{+M��6��UIIu�eb��%��Rr��Gw9Y���/���S�L�����,���� �Xs$GRw�G�+�����T�AU���B����e�P��a�f�n#�����
�z�OUj��O��W9�+��CM=�e� ��q��R��k>�g��Y�f�1l�CD�F�Nir��)c��]�|�4���~�-,�C��}oB�Ea?���RC�����Y��8��4��i��<p���l����]Jo��\h�W�8;;�Z����H��RF5���Zw$,�Lk=�k���-�uc-�S����s\�R9����IZ����]��Dr|&N�h=^�1v��s�L�u7��+<�#��I�~��*���*��]��L"9�b����T$���5T�r\���W���������)�B�&��m����|��c�����d]�p�Zp��� ����*�'.�|0�uJs��m�q���/��6��nJ�8=$k����g���TN"�Q�Ur��Qc~����o�I�fY�A�v^bb�k5\�
������tb�U���@��A5vb�[o�uGd��C�������%�����s+����������Z_��������#V��}g���lYLl�B�"C[t�f�B�z���U��=���D�e����#\�TUM?~|�Pw�����A=�T��6p�����P�X���/�����Xl]��"��x�-�h�����If�����iq?�P�:�b
��|P?��<k�%������!z\������@��g1�F�F�?(�T����8�2RC��l�`�/����Y
��1�������A����9�9s�Z���K-=2�j�J3{����_��#�wF4�W�� ��!Lc�c[�����7����u6��:��1�3�zx���i5����\�x����|P��:�S�L	�����u`[W��?��1�������>�,&�����`T{d�za������>&1�?�W>8����-i��^II��_���^�6lX
>]@����:i�����8�a��D\����u���_�������ag�����f��W1�SVh�X��:C�,n�������\I�I��ECW�:�����.�<E7����_�@>(�N����d��Yr6%��T5j�k�S�#����['�#�5�S�t	67�h����O*i�e1�]��k/q�G���q�\;������c8�����/Y�D�FTm������1����t
�`�S��`������1-i�����W`l�b-�'�t���8g�5���q�1���(7���j���&O����a�����O����OZ���}(P�*/M��+��W}����B$��jPi�:.=�e������W������]k����A=���H�S�wO���J�f�=�@�����$����S����j���m)�����Y^��$���b��%�Q�J�&Mr�b uS�S�^�Q]����|0�#����:����������P]�V�#�sm;��{����L�|P���#�������������L5|�����:x���*�&�N���kNRN����������>���a����s�OQ�S2������|����k������z�BW8P����~P'}�F�N?���A9��O��u)�#i�p���hTo����G|%ER���"���L>� �~G^����S����
KB1�����'&&����G�
=4n�������%�ZP?V��0a����0�?GH5�{��|0��.�U���=���������#,���eTf��"��FS���p$�V���������f{��6��K��~��j�'4v��m�n��mVh��Aum�~N����|�����7J��tK2����m�2Gi��"��SM}i<����RE��+���oQIR�y7n����D�� �������h�2��I[K�K#P��bX���>�jK��������j>j�(�SO��W�����_/��Wm�I�&9��]���G��6��TR��*)�uT]���c���k���:�^T}@��['��$NZS�w�EJy��Jp$����g8�/�O�3cRL��$Y��L`��y����K�W����j�@�U��#-|���5��Ine{&�u�U^�e����f�!W��ULU[*�F�
Tej�w��_�`��Su�I
U�R�E
�8���z�������������U��k ��W��1_�|��%�j�dU�����
u9Yr<'O�,i���Kuk����a5*f\U-�!��VX92W������e����]�Ud���P���~I����r�m?�D{a��J�Er���:O��=UT��#���W}u������C���K>�#���D����\trT%��}�
�F���BGx+���r��m�&�����}g�Y�R���C�\�P�M\��V�&/�!�K.-��\�C%,�D	�n�d����GZ������J�l#�[�|����Y�T�GZ�������w5�X������KaYD�"sm��E�N�)i�H�����3�_�G����F/"m����lH�Ai;>�+,��������Z��Lt-,�1i�I\6!�E��lN�t(*{�����4u���m)i�JN��9,3f���"I�N|��)H�OE�ZP��l����j�;����c��mV�T�\���j��nWh��]R9�jG�������@U��R^e�r��M(��yY�7!�E���S]��n6��D�$���I2+Y�����s"���l�����/V���E�l�nK�\Y�r���b�}F��.L	r���:�����Y���\�B]�S�Y����������:&*��a+���Y��
�����+egeO�o\���jkr^��}��kG���Y�e	o���r�:�����l8�������6�7D<�F��_����L>XVV�����^ZZ�*���C���|�
�	3��$�qn��~Wb��a�}w>���7a�,Y��!�-������m/xJ��NZ�z���Y�f��W��>��ukrr��par���l/���������_���;��Z�J���d��=z�s<F���-�����$%^e����/v��m�����7��o~s�u�=��#C�-++��R>8z��+��r�Wt������c���/���o��������nz��'������"������x�"$N�>�����_}���o��������[�q	�M�6���$<�.]���6n���n�������{����G����
WVV�X��m����w_��
��������U�V[�l�������4z������o����>�>��3���~W��	&HtE����o�^�]�����Zr�9s�4i�D�<���999~���#G����KW�:,((h����5=z�HLLLII�D��{���x�������������<x���k%r���������O<�D~~���C=$�5j4l��u��m������6h�`��!~�@�%mWi�=��#�_�;t� [�n�c�L:q���/�x��W���Wr�����=[v������g��(Qq������m��X7�&N�x�
7<���_|�E$��d��\s��5�����������_��IKK�N<~���]����u��W^y��7>|�:q��E�P�X��D�PEZ�w�q�4����g������_�Z�����U7����������}����g>�������l��6}���2���������b�5m�T2���2�����N�*�t����`��
6xX�Z�{���?���krp�7on�(�`����������W�������
v��W;_{���eV��=}��a���������|P� ��v������5K�E�T����,��H��GyD
l���T���7�xC��o�m�(����$g�6m�H�����T�������}�Q��������������m>�Z�����m���#�K����Ga��}����k������p�j���l����e�")��m[)��x\/��%�0��UQ�?�y�<���ysi����v�RY�5�\�;�<U����9T�����
����?1�7o����7�x��I��g�}V�����&�0����}���'�����a��i����{�����h��=�P��
o���&M��1�9�������?'vU�"�gff��5������������T$��_��~��iJ�8��-����FA|�����f����'N���^�!�\��wU�O�_^�~e|��V]U�����(9[z��%���i�����������m�6h��K�.���5���t^������������$l>����������q�������y��9s��'o�~�����j�!"�G����t����GL����?.(7�+��R"�6(
�9��|���n��������W��}��U{/� T|���M��x�	��o������Mvu��|P}�E�|�����zzQQ�����zkM>x���m��}���C����;6l8p��H�����n��U�uN�������&������������j����)S6o�<w�\5���>�kW
<L�:��j�J�}R!p�{��+�<r�H5�^���������n9��y���6m��{��'���k�u�����7T����>j{4T}��Q�F�?�WS�P>��}{U`����Y��W�$��f5����`����W_}��`e>|�m������*@=�o>XK��!T|����U�2w�\��S�N�Y����
����|��*���Deee�
d���Y��jk>���:)>v��d�w�u��C50@]�o>�{=z�����&���3f�����{�s���{����c�b��-�Y:���/�Y��jk>(A���;�?~��{����;8P���C������o�4k��
S��'TjC>�����]�+�qu(<x��*0�|��'N�Y3g��f5��5�������n��R��\u��k�%�G��d�:iII�Rc#������9����YK#J`��~��A�����_�Z��������R~���r��s�c��W��|�|��e��Z�?������������Em����������j�$l>(�y��hQ��^s�5&^���||s
���6.����C�:g-X�@@[����;��#==�:=%%��=J||�si�{>����{��j��I��dn�����,����H��
64h���n��WTT��qcc���R��-��b��F�����d�s�=g�.������o���M>��.]�H3�Y�f+V����G}$�|��g
���97n\U��{�������?w���w�9p���@��2S�NMJJ�?������_�t�R�+h�$,����*\�`����A��c�JJx�]w���o��u���O?��,���o������a���W�����<x��-[�L�8������=��u�����x@��"�94l��|����|������I&��W_}U��V�����m
<�ZW���2��g���o~s��W�p�
?�p�n������K+N�>&�����[o�v�m���|���������$�>|�+��r��w^s�5r5j��E���������f��e��������c�>���W]u�\p����z�����?r�H�E������{�m�]r�%�����C��1#�&RRRZ�hq���_x��
6l��ufff��YYYm���bRX����������PZZ��~����Gw�q��q���_�d���_]�\v�eK�.u."��=��#�|����W/X����J�����'K�y���N�0A�/���_,��l��>2�g?�Y�>}��,"��S�L�|���"�O������y��eee������L��/~q��	�"����������������w���c���NMM����$KOO��M�&�o��&Y�ZX�y��7�,I������K/�TVa6���R���K�������w������u���[�����?���			R�A����Y�f2��w������o����N4h�L���[m���i#��7o�E�E������{���'O:g]{���@��O�N����%���~[aI/��B�5o�<=���S���L\�l��|��]e���{��;��S&v���Vx��2��.8}�t���v�������\����[��*���V�Z�)��O�Q���\[�9s��Y999jJvv�����`+����f��&�-����U��	�����.�@&~���E�{�9�����)��wW��8o��Ueg���j��U�����g�_���2�G����NS�L����+�,--��9�R����;y��7��-z�o�!S���zg�c���UM�8QM��SM9|�����V�h��Qm`SYYy��wK�4{�l��]�v��j�����Z�j%����
=�e��2��[nq>u��Z��a�����85��e�F����^z)t���"��O�>�Ct���|��`NNNT��zo�:��s�amP�E�8�K����y�=����Y��yQ����"��
+V�����{����b�\��jD=���G�� �`���[�IFv�%�<���EEE������]w�����71w�\��B|o"??_����&�[�R��-��3�4�A���zo�^z��?�paa��(Y�����j�{���u�Q���_�r�L�UU�{��[|Q��-��3�4�A����o�W��d���&����?����O���[����?��O���i�>k�,��4h ��uz�f�l���w�!�l�8h� ���Q#[��m��������Kzh�F�[|Q�-�
�7�A��"
&��xS��������,g>(^{�5I�����)����ko��1�����]t�%�\����'��1C
�x����Q�)m��<x��?���DVe-���"�>����=��n�E=���� �`�3�4�T�m��-�mI��r(�.���J�x�=��"o����5k.\���{�PL�<Y�s���~��76l�����_|������9�D�%���+�e��
���[��������i[������ �`���C��=�G!9��@�@���5j�H���.����>}z�����������]x�����n�����&�������,����,���q�M75h���E�E���poA�A��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A��$�
����$�
fi0�H�I�/po�I�� �`���7^����7�A��"
&o���&o0�H�DL"�x�{L"�`�3�4�D����D��"
fi0�x��-0�x�D� �`���[`�3�4�A������fO������[`�3�4�A�USeQa���yzg����%
��]���x��-0�x�D� �bS�kg�������r@���'�<��wk)�
����$�
fi0�H�\e���es{|��;�@���^���l-E����D��"
fia�&o�60��WB���?�)���xmD����D��"
fi��(�9�t�6�O�6�K~��Q�}��6KV<�����Z3�w�6"�x�{L"�`�3�4���aV������/?6�����[�����w�x��|�����2���{�j�
����$�
fi0�H+�����0m��S���}u���j�A���?������O�[q����W�o���&o0�H��3�*O�-���I���	��l�$������d����>���&}[�~o�c��?�=[��eO����Z���x�5�-0�x�D��W����a����9��G�]���}���G��9�����L-���t��
�������vm[WU�f�_�[��x`��D��"
f������03����}a���O5��g��[���(�9�x������`�:]x��w�5��^��M��&w�6;��
�/���$�
fi0�����G��c$#�<���]�Ly��A[�rPA�Y��R���m�Vu��i��G��4� O��9'�
�����$�
fi0�\���];&�:�:��a����7���~�-|eHA������e�E�Z�.�n�\�������\�7���D��"
f��H�nd��sr?���0;�<��+]?h5�i�Lk���������(;UKh������'����y�/�_�9������{L"�`�3�h��&m��e�/E22��������/wH���o�(��dUZ������"|��zkM����-�Au4��r�[`�3�4�Q�"���a�O:�Q�HF�����#����{��9��G]R�vOy����^��.��/}����l���3�n���C������7�A���Zi��%�����+��a�>�����w{g��]�����#��l�W^Tj���j������G��5���Ss���jy����������w�y�5
Q�������2e��")))-Z�����/����
�n�:333�������i#���,"&''G�/Qm0���[�/�
fi0�vFZY����#O�~#��aV=���o}��M*{�w~��EcV�$g�������������]��V���������o�Q�ua���.��73f�p��<y�\p���N�0a���}������%SKKKs��2�g?�Y�>}��,"���2MWQm0�^�[�;�
fi0��DZ��0�s{v�|�q�p{��&������t�����g���)��t����[2�d^���������m�w��T{��S�������O~��^x��W_�$t��\���J�(�Xzz��8m�4��M7�TRRb-,�T9�$tzbFF���^*+�0��j��/�����3�4��{��n��7 ���as�������wz�=��i�d=�'�����oKS����f��w���&������j��=��8u����_>}�t��{��W��`�f�d�����m����.�l�8h� �x����
�i�F�7o��������[PKo0�H��D��d�V��7l����#����%~�:^���S��n(�s����V�.�����~`�'��>�w��QO�l���999��5�J�y����
�-[f���kW������:��;����;w�^�b�L���N�>]�[|QO�-�%�7�A��c�VYXP��,���7*l���G���a�w�?��p���'l.K��9���g��v�����zs?��w��Q�l5�N�>]�����k�5g�5K�����jJBB��p^^��v�Qm�K=���G�� �`���V��������z$#��x��/���I-�J(��\v(�>�#ka�wgZw�4y����A=��E�v���e���_��_�_��_�<���Q����l%�w�.k�����+��u�����U�V�))))�����/eV�=B�?�-~�����x�D��"�*Oe�6;���>6�������l�z���<�����[�����9���%:%\��5��'_~�������"��;��7�|s��E�7o�������Y��{��u����2]�F�J�;����'�)&LPS>�,�M7�,�h��G�E�/���o0�H�5i��K��7��as���?��w?���6����W�t{YN�9�ZY�_��j=�G�];����-�|�i����M�N)))����e�&M�X��l�R&�r�-���:uJeg��
SS������']�W�*���^z)t���"��zxo���7�A���jF����������z4��0��yi�_�}���/��L-�-�������/�)����[�I���~���zxg�$t�~�z�m�]�VO�����D��z�����[k���s7�����F��M���w?����>������v|=��u�~W�����|�����<�}W����v>�0w87����.�L������R���;���E;G\:��/W?�Z�P�,����2p��ik�%�]}�}4��N	��?�z�v��w�L�0w87T'���[d�W_}UOa<�U=���G�� �`F�H+*
l�W>~������l�n���G��������'�F,KN�/��X����-B�����|?�L����~W��zxg�N>x��7���_�;w���!�7����fU�{�-~�����x�D��FZ~q`��������$q�k�oz�y��a{`�_����=���;R�����[�o�N�|��7.���];C���-l>��g�O?��u�z^�c���V�����u�Q���_�r�L�UU�{��[|Q�-��3�4������sw�����i��5vQ�z$��0[[�������6�]����E��o��������&��;[�|�i��
6tN_�n��}[�z�uz�f�db�V�l�����>x�`��A��n�m��2�y�����fff�&F�E����o0�H�w��*�l/�7��o�>l5o��]w6
?2L�S�m�W��*s�t( �>s��"l1� �O������_���	���I>(�n���7��qc[�����.���K.����7�3fH�o�Q��G&���S������.+�UY���\z������y�b�"��zxo���7�A��f=U�`KY���\�f��C�����"f��o�u��=~�����E���d=�Eg�]A���;��P��4o�\�����N�s��5��-Z��?��O�|����g���������w�uWVV�s��'O�������o��f��
�������/�����4ga�(��@��}��,��aCY\Vb+���#����:[��?���� �P}NV�J*�9���/��r��?�$�l������������)Y����sb��s��"|yHAn����g=��2����V���Ir�#7��JVTT,X��������[������?���~��q�#F���[JJ��/�(��^(�]�����yj2K
H1),�������b7�tS�
\�QT[�?���� ����+�o,�:�����q�zoE�#�k�������Qq�6��l]�����z�}�����
z�;/po�I�� ������J;�=������v�yk���F��x����t.������Gz��Aaa��)K��w=��
����$�
fim�����K�O,j��wi���N|�j�����l�$�[������{����yg�4�l]����e���>;�w�+�!�
����$�
fipJJ/�������{�;�x���!���F�y�����Y8e|y�>�:�4_����vXOV���~W�+�/po�I�� � 
K���_V���B�>��af������f����!�J6�
���C���p���l/�����e�|�"���u����[`�3��z+�8�fw���%o�,����[>���6?~d��g���A�����D�_z��AaeA~����I���������[`�3��z%�0�bg��J^�������}s����dd��w�R0vX���Qm�H����p����%��'�4y��u�y�/po�I�� ��yYy������[��W����n'>j5'�����s�E�3}z�\R��[5�4�J�A�L�������3~W��o���&o0�H;'����R������ ���0�\����G�y����[8���������#[��e�3�����~���o���&o0�H;gddU��\�sFq�����a�99��a^1��/J6����i��x��]�����0� �y/?z��:�$�
����$�
fiu����6�v�Z�l�|[�x��6m��~�w������l����Uy*���i��u��Y(.>�����Sm����5�x��-0�x�DZ��z�b����=�����?}���[��4{�p�{�����}���e��
T�H�]��.������P�r��u�1�/po�I�� ���-+��.m�MQ��\r�'��������;E42�KO���q��e��&w�H����0�\&�����c����b��G�9�/po�I�� �j�������Q+KZ�+|�S����0_�y���#�4�����
�O,?���i�AGa����O|���������5�x��-0�x�DZ�QXX��|����)tM����3z�#~v����C���R��/K7o�{��C��Y�pZ��]a�7c~0���=~W�o���&o0�H����@�����K�4�nd��������O=��0w,Z8��T��;�DZ-�m���Pd�����y�UkX#�7^����7�A��w��r���/��eX�P�����~o�Z����F�i���	��v��{��"�j	[a����K�o��S����Y]�/po�I�� �����\������W������n�;��=����x"��0/?����%�WT���i�G�iE�.��^���e~����3�V���7^����7�A�y�Pv����^��[�V��~��_�����?�������\~����"���u���"�<}*��t������jV���[`�3�����Y�������f����w�����[��x,��a��c��A�)u�Li�J���w�m�����X��,m�����
��g����8������qI|�K��/�����K|v��K�`�A z1 �����h��"�B�.�+���z������!���vV���3[>����ggw�%}w�zf�j���H�AT���5� ^�g��:G�'��H;����IVM�����3M�b�?@��Ja�KS���T���v]	�������
���$!o@��O�9��+����XfS����0;��o8��G{�uwe^������4c��S��2'S5�������7j���HZ�H����v-v��p��V�X�^{��YZ�9)����6���P�4c�>E���!��p�D���;��A�@�-@�d i�*o`�*F��.�.�����g�~:��!�[���y�Ub�'�4#�U�!#��L�����d� o � 	y2�4�%P�n�il���pS���:�3Sz��=%Q�wC�f�r+^�"���~�P���jh������7j���HZ�J�?I9���SC�w��^~;�nz/7
�l�|`;��<V��$�8m��a��S�b���.Ea� o � 	y2�4-�Z�s��q�&���]_x���7�V�Y�Dv��2�����( i��o��*���Y�~F�q�y!��I����i�QF���k<5���A�3���3�����"6����~�I3Z�oi�"�^pS�6��T�A�y!��I�����y��\zQ��#��(?��\��1|�`���m �@����a|��S��\^kg�r'���S?��HB��$�SS+{5�������zg�f�eB�m9}��,�;$��m��"TD���]$� ����P[�$�
�@�Jj�C��#h85t�r���3yW
]<���]V��Bu��3�)���T�C�TWFbdR��;�
���$!o@�%'-:�r����S��_�w�x�Z1M��)����������
7��]��"��*�G�
�������B@m��7 �����z���p�pj���AS���6b��
wK�gDX`�L��)B�u���)�q�:B�@�-@�dXT�*�G������1;+]�/d���V����p��o�,*i&j�
�S���9����^2[��y!��I��a!IK�P[nk85t����3�<>P�Z1c�n9�B���=|s`!I3i�e/M&uO�g���j���q��@�@�-@�d�}���(��p���������hF[�/�!h@f�4���u�)����T�T�46�5H] o � 	y2�5i�R�b�b��6p�����������wK{F���7C��43�6E�,��"����C�~S��q��B�@�-@�d�_��*��w�='W�	~0���
����]�`�S&���f��L��y����_N�7j�������,�
w�SC;��Y|1m�8�N�a�RyD��c7��4��6E�RL�>Z����w�n�$��+�
���$!o@�$�����>����#�nJ�5s[��A���1_��8D��=|KaI�k<�����>���T�=���*� �C�@�-@�d�t�J��#��#��O
���7r��	��v�w������c�I�4jS���>�r���j� ��V�qj���P[�$�
�0����S�n��?b�����]������kc{j��c�P&�4��x�w���Ik&t��5m_'� �@�@�-@�d�V��J�������O
]�&4`�J��b���]9�4��=|�fZI��bmS���T�qQb���B@m��7 �T�V���~�s��6�fg�����c&���h/{,�����$
�,���:�Z�6�G�W�W]�W�j���P[�$�
�0��������O
��)����|k���r��*��=v�f�I5�J�!����K'�tZ�qj���P[�$�
�0��=JS�_P��V���sy���?���mF&{�����|T����>E(=����G���2H��7j���F��F{9�}���.��Mrf��\k+��bv�kON{�����J*�6E����v6*�g/i� o � 	y2�*i���_�c���{SW��3�Zz�4][-���F�4������S���p��Gy�CQ��B@m��7 �H��C������6;�.��<f"�Z1+��O���$
���}��e78t_�;a�������P[�$�
�7i2{;�}��K������1kW����b�m�lv�KI
�3�
j��R�"�pS}����������zX�A�A�@�-@�d�����x�b���N
���?|�|�	��9�Z�o0R��}}������/M�V�O������La�(�T���P[�$�
� �4����[/�?b���������	6n]�xKr�`p�i&M�!�n���_��%���P
�B@m��7 �X�J�^�r���.\�6���6�f�p�7�����@h�i&-���)���T�_�6oQ��y!��I��A iu-���x����9��Z���|�`�������f����c��[���o��c�����������P[�$�
�4i�e�n���1ss���{��k�Gj>��.>�CM3uq��Lr
`��!]���N;Dg'�
���$!o@�@I{��\z��SC7��:i�Z1�&�z^cZ�
>0�if@u�p��)�V?O�����T������P[�$�
�0l��Z�k��S�u�?�c��n�FY���y�">�P���fb�z�"��-�S]�� ;!o � 	y2���Z�p������������}��V��a�������Lj�yP�"�r[��2'S�7]v�2�A���HB����'-:�Z��}����j�/�x:��w���s��j�`*P��C�S�-��T/
e�`�
���$!o@F������$��<�}j����Wg�-�������C����oLj��P�"���a���Ik&�>'|�Z��D�@�-@�d�!iUM�[�b���9�
+OZ�7!X;c���e��Q��&5�lD��4E(��0E(�@�(��y!��I���W��%�V��SC'�(u[p*{�(��b68(b�?�
�4s�����)BN������a�r�#D�@�-@�d���)����.�.���u�k������Q������T����(���jY�^p#9B�
���$!o@����K��a�	G�������f����k���l���*�N�I@M33��t_;��[�����j}�:Db�C�@�-@�d�%�����'���7}s��9�%#x���y�����4��S��ff"��>E����v6�/Z1����7j���=��M���}j��U�O&���3m����� ���T����)��<S���p��!�����7j���]I����1�v'���7~����d�����2Ed������f~�st�"d��
�O�������P[�$�
��b�~��|���_�������w���_��:S��bLj�YR�"�����a���z����r�����7j���q�����]k��Yv+~�4�N�n��6�����@M3Ka�:M����eN��C�@�-@���+Y�D�����a�nK���NEV_���{S{Z������f�T�w�����n�$�?.�	=*�
���$!o �����X�����[�(�v)�Z1SmdW�3
ub��j��
�R�N��3wk�HU-/�~���
y!��I�Vz)����k��c��e���V��by���f5���N���;E��[������.1�B@m��70�G�J���?�~]���M�k���r� �{F��@M3c!�Mr
 WdToZ*���7j���A?5��+���v���zw��e���f��3j��'��*���l�����'�����NruF���g�
4�
���$!o�g���_��V����
G|��	JV�g��!��������'�:Mr��u�%j�$�����P[�$�
� �����	�]����2��bl���g��Z$
�@�����~�)BeN�j-�y\b0��HB�@w2��>�������G��g���]+f�"yHP�s�4 I3{�3t�"l9��Z���J�y!��I�����9�P1�`������z��R6l���bl7�OI
�^I2�4K�:Ex�.�!#��L�U�78|$��HB�@��"j���O
���+f�,��b�Nn���}��:H���Y��t]�����)Ed�aG���P[�$�
�$+���������.���	6n��=1^��!i@�f!T���y�9�+�w_�lg�����/�
���$!o����9����-���I������4Bz�$][���"i@�f!��4EX��;EH�HT���	y!��I�t�����v�?b��J���6cy��q�V���^/��H��P�"<xO������j�:DC�y!��I��/n���R����7�����t� ����A��{���>I2�4��P�)BV.����*e�+�j��HB�,YK��>�X���������V����^����bt��H�E�;�=ExH��":\���=
0��7j���Y��Z�p���I:ek��y.�#������H����4 I�(��:O�l�����'cZ��?�
���$!o�&&�Z��q�������:�����%�9W��I2�4K�:Ex8@�!W��Gv��|d�����P[�$��B����	��N�lvV;�_J=���_6�PgR�B��$���O�c�Pv�]��)s2�yt�
���$!of���9�sX:wS����y��9���Ne�3����H�R�"t������L��2z�]?���P[�$������<;N
��p'b��	����d���R-�4 I�@�zL�g���V�[�94�B@m��7���\x�u�6���G������q�"6����4 I�L�S�Gz�"l����Z��C���>y!��I��9��2����V�
�[��V���-�����$���H�e����am��)B���k�Jb���}>.�B@m��7�PPE������>��r��	�k�,����.�����B@��$�b�N}�K�k��T����	};(�B@m��7S�M9\n��)���%V<k�����vev���D��$�b��3E��[`�zu����P[�$��DI�����i'd[��O���V��1��LS���E��$��M>�=Ex,P�}geN�j��]���#"o � 	y39�u�����%������]+f�
Et������H�%����a�1'��IWU�{D�
���$!o&$���p��am�=;G��b�~�r��*/{���4 I�p�S���2E���5�u�m����C�@�-@�f���?z���qZr5y�$�N�~���_V.�Z1�@��$���y�������B*���p��HB��YMs��b���Y�J���	6�����*�`{��H�N�>�e��S�b~�5������������m��u?���?��3�{*�Jgg�?��Oo�������|��7���Z�OII���{���^{��?�p��U���|;����^������{
����d}��^G ��j�y3N���N�����&~�{j�T��Lc����	�d i���!U"Q-��3�t?�E�-""���>����A�L6p�@n7{{������������O����������xxx���q��o��uj999=w�6r��'?9|�0�3�����===u/z�<��- :���<JW�u-;���g#G�u�
k��{R���4 I��)B7���]Uk,�!�x �EQ+V����~4e����g����;��g���][
�_��Wn������������:��um����v�����'����ggO�5t]%�[o�������^G���0���hje�D�o�u�n-_X5������b��H����'�{���I�(��	ry��M���+��x �[CC�{��������5k�h����~�����+UUU������'����j
������������������ntuu�6~���j;�^���nkk����������Fy���v�i8��#q�-�����Z�z1m�b���4 I�N�S�'�z��QD��V��@]�b!ykoo���������k���v<x��v�
|������������4_}�Uncp��I/;v����������q�m���shh(�}������oW�#��Bj	�MD���=�����Sl5�w�������� i@������"d��
���0�ii��)��^��O?���R��nn���][|||:/HljjR����{�u��uuu�[����vnii�|H��5�@,X[@D�y2��~p���I�����#eW�1
ub�`�4 I�Nr%;��{U�S�{�"��*�G����.{{}��M{?�T*��p�����N�8�{h���][v���my��wz�������EDDtn	������s�w�}�{h��������b��D���T�����<��d���|�`�J{y�c�GjxH���A�8��e��U�2'S���7������;[�k���|����s���-.����w���sEEE�K��q�s���G�������s/�������uD�X`m!od$Q'�����_X1rH�'��39H���A�)��OtZ7�n����\��N���7����g�:[*//����\��{�W��U��i��q[>����;744t����g;��9s�sKmmm���!qM�>]���:"�X,�����7�=�k>�����S�:�����wn32��#�d i��v��S����%��[�T���?�������`}}�^�`�u���{@,X[@D��@�Z�^�7��+��{��M��''�=RB�4 IUjS�gt�"l���{a��C�:
�G'��U����!�wx?�l�����gGrH��#0�^�]��������^��Z���L�j{����;��'��@!3���pm���Q��:�g�gd_8-�0,HL|����]-�����<+���j�����eg{����M|���?��~��r�	�T��P�7���b���"B��O*g��N
����
,�X�w%){�bB��$
z��}�����V��U�xV��23�k���F�~�;w��������s/����k<"�(,�������(o`|�FM���	N�X�#5��bt��H��v����"T�d��s��s=������������?|��W���U���{�{�����5���'O��6i��/�����Mu������;::r�mmm��s���0�="�(,��������x����=s�h�N0w�c{b���4"H����F7�_�"li��Y-��T;U�������~�3w�\n����wmioo���swwW�9;;���_��7%��;.���r;��Gj�#���F��KKJJ�~�m�E��R�9%%����z��WUg$�="�(,�����7}E��/=Pl5Xc(=������{�FI2�4��U��9�=Ex!T����LZ3aXW�op\���������^�������������sg�L6p�@n�%K�p;<|�p���|rn��=`��>��������...o���{������sgn#�����3�3��?��{:�"j{9r��z@���G �rj�MGR9��F\�LG�	��S�����B��$
�\�������R/{�������V=q�����J%��}��g\���;�|���>>>Z^?%%e���\G��k�q���U�z����{�������{
�������I$��?���������^G �rj��W���=��	���u���V7'$�=Lc��H�Q�"���i��+�w��������p�
���$!oZd����t�����2��Y;�z^N!i@�Z\���!U"Q-�-��t=���P[�$�M�����;K���	��]p�*V
��d i����%����]_ZX�0�s;�B@m��7U�W�'W#��-�;54k����Ab�$!i@��]��!+����t}�/���y!��I�[��f&��W���|�`��
���b��!i@���M^o�����p����wX�
���$!o�Y���1TcXl�u���tu���4yH���A��D�4E�����78t}:����iiF�@�-@�%�-�q���x�1aB��[l���A/,9i@����!]UY=��������7j�d�ykkg���DO��������A�b��X`�@H�����A�7�}�Pv�]��"��7���2 ���VS#
r��3��LY��);W�a�'�J�I]����vO^��u��S7gR�5�f"o`p�,�,$o��AkKF�����t�i�{���B��C�@G����M�g�v}|TL������H2��%>H����`���gW��=F�`�I#�������E�1E���A>��$s�[[;y�~��Y|�`���aqb���k��� i���a}�"djFA?�g�d~y��j�{)o��m��������_"�0-��%
���S�"���c������L�,�������H2���JBW�+>Hc'X`3"��"��(�0-�9%
��z���)B�"&y!��I������9|���M��}#@�1Z:�H?$
��6Ex=Z�)Bya��I&�7���=}'e�T�N0a����d��	L:i`B�4�������O�!o � �D�V_V��T�H+�m`��!q�5I��&t3����A�@_jS�7��"D�@�-@���M���b;��`������1�2��	�L.i`��4��s*S��]��"D�@�-@�	�-�',~�b�N0i��^��#�2���IC��e��S���]��7j�dy����ne����	�,�T��-�(�&�40H�����L"o � ����PZ��X���5���#�Fm?�PV#�0A'��40'H�����X���7j�d�y+���]��oB0c������\.�0A��40?H���'zO"o � ����y;(y�<�N0n���;b������
I�>S�"���}�y!��IF�7F*M<v%g��m`���;%Iyb��H�fI��8�X�)B�
���$���&Iy���%V�5v��#GD�:SW� �� DOX$
�Cm��+��)B�
���$�������E�|���L�s�O��@��Ce2�4���A/Mj�y!��I��-����)3�:���+S�		���d i�OjS��Z��7j�D2oLsS����������_���_�^Bf0@*���A���LN>&��'�B@m����)O��nO��A;���6!��������
�@���j[��~���M��"D�@�-@��y+�I�v9�����s".��t�_0m�l@���H�)B�
���$	���+>Y�l�:��o�=}�.�q�8��H���S��D�@�-@���F���p+9TcXd�U�Z���
L*�������!�B@m������T��|�c�9]��m5������H���_�� !o � � y�|�>w!_'5ua��\$h�P��$
�x`/S���H�W����.���0��Z�%>��A��
�
�@������&�O"o � �oy���2���X���Y���57�V���Be2�40���Z��7j��o�ZR��W���Lg��]��7`0Q�l@���6E���!�B@m�t�[e�����y�1m���V���S��d i`pGT��N�4E���P[��^��H[
�\.;JcX:|����cB�
L*�����U6�4E��=E���P[�$-y��J���/���N��(k�M�r�L*����\�k�"D�@�-@���5�'d-]�wjh�����W6�"A�*�������7j�����;��v�x�1�1�f�T.�x�T��H�p��)B�
���$u��ij���-����[
�[�Q*�`����HDm��AJ�!�B@m����?]�����;��1>[/g�6�=L0y�l@���9E���P[������EK�N
��4���#\$���d i �)��T%�B@ma����^����:���|2p� *������{i�y!���@�����'JF}��
,����#�Qb�*�������/�"o`p�,�S������7!�<f��7��Z�&�3T6 I�9�wO�s�F����Y��7�[�N0d���}wE��=L0�l@�B+���"�y��g�#��xxM��
,6����w�<���7 I2�4 ��]9�A>��?�������F~��������Tplm������H�5E�~���2������5����0��c�O��R{�d i@�d�����������A��Y|����7�F��k�� �d i@�dp���Z��d!o`p�,1�M5�.���
,�������6m/��H���I��zE�H���{>b��N0k�����7��R����H����P[@����+�N
��0�����"���@��$
�@��$�
������S4}
_'xo�����.�y2�4 I��7j�b�k��*3Lc(1�c�����Z�������H����P[�U��|�v�	����.���0���GA��$
�@��$�
�������%�|�`����=-��"A-�7 I2�4 	y!��X���V�[%S��u�>37_��YR��E�Z o@�d i@�B@m�@tuU�����������n����>_$��d i@�$!o �����,���oB0q��������
y2�4 I��7j�����,���	�.s;�o���@��$
�@��$�
���b�i�����I6��������y�J���&3�
�@��$
HB�@�-��*/�s9Xa=Xc'�l����g��4��\L��7 I2�4 	y!��������V��7n���w���HP�
�@��$
HB�@�-���������:�{SWu����"A-�7 I2�4 	y!�����Qv�������b����p�&)�"t������H����P[L%)�=���j��N0�f�������u-D/�y2�4 I��7j��R�EU�^�wjh����7?�KT���L��d i@�$!o �#���{?�1����������\1/�y2�4 I��7j����j����������<������"A-�7 I2�4 	y!��?e^N���|�)�'�8x\z�\c4	j��H���I�����#�+�/���L���������v��3�
�@��$
HB�@�-F�i��z�xn7���5s���Y����"A-�7 I2�4 	y!�������K��W��\k�����W�V�E�Z o@�d i@�B@m1��)u[��M&��������I\$��d i@�$!o ���?�Z4����b���xS�HP�
�@��$
HB�@�-ba��d��+&����X
�6{����9�w������H����P[���JZ������5����7ks�M�"A-�7 I2�4 �iJ���RO�*�Z�������������+�N
�?s���S����}������H���)�B��T���|�J�Om��
�ed�����g��	�O[�ig�W\{�B��
y2�4 I�b��������u���?�O�C����Y&(��^�~�b���6P2b����6��f��E�Z o@�d i`�l���J�~Kc����	���2�P�y�N;�&�m�Zry����23�HP�
�@��$
���25w������k���oRI#�bV����P[N^�z	_':��m��=RT6��E�Z o@�d i���$�����^z@�'�����Lm K�u=y!��L[[�������:A����I��.��=T� o@�d i���Z�������U/=`��P���������WB�@�-�G�VK������60��3���q-�T�=R�!o@�d i��i{�2���NRq���2
��&�B@m�e^N��-|�Ic'�]vk�W[z�e]$��d i@�/i+�KOQ)�!���������T\g��ty�
����7�����|�`���u��O<����@��$
�@���eL�=:�A�_�O&�����};�B@m��*k������	^���ao����HP�
�@��$�r�����T���W���=������R�~y!������j9}�r�W��\k+�����|����A��$
�@�,K{Sy�������n�S*e,]���������W�����&�N���{��<���$�7����H�%`"��mT���>�g:o=S,�H�7j����UK��u��S�o�~.XQ���u��H����-y)]v�J��y��0�T�t���UT	=(�
����#��z^+���
,>�c����s�&)89TO����H�Y�[�������?��2L��t�.�)���7j�*������b�����Q����q�:��{��
y2�4 I3�t���J���t���PY��*/�je����S{zJ��u|������g�������/����H��R60����o�����a�����bV�)���7j�<�a���|�`���[�G�����H�����1�.�A�������?����@�n{���7���F�"�y��d�m`������ns���%��d�y��4 I3�����T�e������K�N���rO{��!o��g?�OOO�OIII���{���^{��?�p��U���|�_SS�z�jn7ng�)������^G �kU^V�P��`��`��QG���]�W��G��
D��H�������t�e����2L����mLC�����������oj����s���o0��>������svv~��7�N-''����F�����'��v���=�{:_���^G ��jK{jR�G�SCc&������PE�	
���"B��$��H3��#T�He�������Ss���l{�������j��4�����G�+**�����������?V(�;s���Gqq
]�F�D��[oq/�c7��Da!�Et�l��N���q����d�*8��I2�4�Q�L���H������'�Y�������^������F���Am����gn�����FWWWn���~�����������?"�(���0�M2�Ke�5���V���p�P�T��Gb�y���H�X��X�p�0���a�>�s�35wYZ&���y�H�~�����W_�����`��v���m���/T7��o�6n��Mm���Pn��
{DQ�km��Jj�/�����s|��Sw�+qj(Q��706H�����b�_�����?��&?�R���nlk���6$�M#��A��uf�����w�^�C����[���:�����������P�����b1����_�v�����8m���.���b0���qB��$���1���2����c�B�m`��'b����n��e��i�����x��_�����x��R�~��]�����w���"iii��YD��+���wnIII�������=�{�n�c���b1������d�4�N�����\�"rpj���)o`��4 I�,�.9F%�(������>�)���������F\?���������G����n�������YT�z[�p!��k{�HEEEgwv����-�[���z����sq�>6�� 3�-LSc����q#4���C.�=t�z������
L�d i�A5��\�)����������2L�`�p�+���B�4������V��P(��Z�F�R�>m�4n�'�|��E:���g�vn9s�L���������g�C��O�>6�� ��-T��r��r+�	���u]y����F����|�t��� i@��e=+�a��*O������5}T�x*�����*����D�����PY��*o�j�-�y�]\\\g���QKwV__�W?�������yD��hmQ<�-vX�wjh���Gv<L��#����
L�d i��Yi:S�T\�����[����z�}�����zZ����bg�%U��)>�M/����mm���k���/�^�:y<�v_'�=}���Q����&�9HMx��Y�[a�������gW�������O~��vO�OK����g<�qMz-�?����w�O>����f��������;z"K
���Sb3TcX8����:;�My�*�HLFZB@V�U��*��Q������F����9��mO�U�v��O���7\6�(zKZ�=��U�������T����!  @��MH����o���b��������7!�:f����������(�����I2L im��uZj�������t�J*��z��2����#��u�8�9�lCe���6��G���L�V�n	���	���={�8p@�C���n���k��������:��>,,����T�G����0�����*X��������'����)1���9A����F����LcS�K���w������T�`e����w�z�o)#?���A������[��L�m�!��ew,&��������~�s{lll��[dd�����'sW�\���_��n�����FWWWn�g�}�����#����Vm;�VW��}C�#��8kK��O��d�N�g����%�����g��� i@��IS6hZ�s?P���o�g����)�>���R'��K���t�)���i�d[�:n�������\Wu��9��]��6l�����������o�)�H�6���r;��G��^���=�������������^�{)��SRR�z��W_}����}>"�(����u��n'Kx.�1�����T6��=P�+���1$
��W��kXiF����7��ct�f*k�<����2�7����We���_SiS��pSv����qk��B��kA���dgg�5V?���������;�G��_p?�������O�}���>������������������^NNN�����C�������S>��C������y������������Im�
�
7o��L3���[A����3����C��mIST�-�L]Sq�.v���Ss������*���\��Ke��T�0*}���.:�<����g�Xy	�-�/T��h�\�x���~���o���+?����
v����v��%RRR�N��ud������Z���y�]���������pOLNN���D"������}���uD�D�-�������:���_:�^J�8B0 ��I��������E1;i����J�I%W�|��wr�^�����PI�T�:w-9�T\ej�����\�#00T6�h�E.���Yh;��N�s�^��S����
>��$
�KmY�g���iT�Pe�'����k�"�S��<�������e9-*�|m�k���O���Fc�g=��
���Ur�j��Yd i�M���Lc4S}�.;��,g�r*��J���/e����:���-�O*e<�e�e9�W�l ��E����n3������W�{������e@�f�������Ty��nt�v*{��r�����JL�N��,g���L`zP�@djKcpH����	NYv�TDiN
5�,2�4s�^�J35,���������o��?6�|^f��,g[���F`�P�@������k7&�����3��_~K�P�c��2 I3a/-��B�m�2�Q���qS���\���2�3
�r6?e��]�E��$�
� Pm����8Rb���N������	K�3�q�����@����9����2��i�A:w-�1�J�R��������aY��GlK
����� i@�B0xm�edf�^�wjh��i�������#,>��$M4m�LS<Ss�y~�.�g4�re*o0���4��.����I�����*�I���|�`�4�;�1u��e�g���	E���S��_)��[�.�^/������F��2U�/���a�
$�=�4 	y!���0���s�������X
�[�'�Q���|�)HZ��m�4��	�X�3o�6�JLvY��)�>���R'u,��u��/�e��r"i@�B�Om�+��w.����9�{����F�L>��$�w��c����D�E|i���/�a���{�,'��*���YI�e�����{S�&�EoH�����V[����������	3�\��pj(��g���uk�c��*��H��|)���xn'�Q�|��,g���r���oaxH������-%~3����Hp�����R�p����2 ���^�4%t������q�R�v��������e9�J%��2��y��c1���,������x�7�����J3]�����|���/�-;a����g�a�IS�3�1�b�8��K�d���;
{q_�o��!T�,�`{�=����t����#sN�
��kmi).K��Tj���N0����{a�q]�F�e@�9$M^�4F1���}T�b*�Z�e������>��SY��]L����9���~�&���y!h�-��I��N
��4+���z).=���0���s�Sq�.�Me-�4�M3d���2�*y����j��u�������)%
L�B�X[rn�O���	>��]�_�(�S��2 ���Z���0��t�N*s^�-�#k��/�]e������v;3U�LSN��1&
��BP�-��%��b��H�m`����������0�4|�b&�5��{�<�@�o�2fw��=�7��������N����k��L����\����8P��$�
��Y[������+����=������R�&�e@���r���t�:3�>�J�R�kC�}���u��!o]v��
d�Y��#�j������=�g/��������A2���s��2 �`I��XiS{�.=I�m�����(�e��/��7g��K�`�_d����y9��$!o`X)���M���	�,���(]�1���g��w�h������%'���T��2���[�����/*���ZD�a*�2
�l[�`�@j����AHk�b���5BcXd����.���b�>����)���$���.>J?[M�NT��U���[��g��O���t�2Zr����4�X���-j���@?��E9�.�s���q��o4���=L0g�,2Rg�]e���bg:��J����2���}���5�\;�5�t����mNd�k�~�@j���@������������)�����=F��,ST0M�L�-Zr��^F%�(c�G�S��}a�N���J�J���K���{lKZ���/��I��K�dc��I�8��_�����-@>����eLcSq�.�Ge/�����P�i��/�?���T�,:]v��{��r�~�`P��$�
tW[���T�����B��a[�WIjX� y�^�3
aL�U�p7���J���������JJe��v2��L}�Z �{��$!o�������;��
��	f���z��E��?j�����Z�^���������M�[�5}�o�X�O*{1]����`#Yy����j�^���(��H	��]��s"��������!o�E�gD��%|����\����Y�,��7�����=f�_���Q���_)#~c��/�e�����t�
Zr���d��XE���H���A����$�e����J�n<���zmW��C���Z�Y����4���sD����66��W��������V����t|�I�����0���3t�f*}���2���[�������It���S}�mN��s?$
�@��O��*�6'�4�3/�L��}	�#�y�a�������������G�@Uia]�&��������bv�5Uh������B�L��J3���t�I:o�fG��C�+��}��S���i������q�c��>�I2�4�U)����{��[t!�����u��>�2���/�f�����g���
:%�=���7!�1�6����/��2 	y3
��mIej���t�Z*�V��2����">��~Ee����1��3uA�,���I2�4sU����P]��_�����tqS�����'�w��{�@����Tr����7sm&�lr-'�xzDx#oN�d���F�-���.�}��k��HB�����mNb����G�g�������v�i�P}_��T�p*k]��)��4��mEd���O
�������	�y�g3ns�E/g�^��{37�+�!�����|_��$*�4��-�<)�2-�:#�&'�.�{n~c�������BVS�ZW/ojn���mb�3C�LT�����$�2��$��k��m������{�h�;�@�����k?����c�]�=�(�tb���H�����g����2�}:{r$��������?ot��X������n�����
,60�qgMNQ^�e@�&���)�������*e�2�O����~[�	�<��^J`*o0�������I�E��1�� �,�v��������6���>_������g
��g}g��]�q��N
p��`��������i���KBv���:|���
Q�[b�n�=�;����g&�wIv?�r�d����:�V��kZ�<��V��~���5�yBtE���5�����������kZk��^4���4�H�q�*[KZ��k��D����%�����}\�l��� ��3oM��5��������x.N�\T�1���t��	�������b7��]�C�Zv��`�2���=Z8��	��Jr:��k�����HB����`�b��[�� ���J�Q���2�����B�U���JO����]�*o��d���~��!i]�6��}�����{\��)����[��/!�����@�iC�g
��;���\+1�����S����8��:[�vwV-��<t����k"��G��������/����s�I��\qK�8�~�|��{���?����@�������%a�#�����iM��L}Z��R��Q��5�y����2��)�UW��q]|��E�l�S
��%������g!eq���f���p�������6��I�����Wm�\���W�O���������}�:8��������I����?������u��l%�A���y/�<5�������$��0�f�1������RY�T�He��$��_R���R'��k���������T���KK�&���r
��g��&_�����M�����L���� ��_���N
X�5����~����>��$d���
���E����i=�5�.I���_�z!��kZ;O��V�����G%Q���&qM�����yz0��������'�\/�u�~�O.fyJ��1�y�������s��q-������h������gg�����=����]���������~�3�Z<�~�����*��j���=�����L^�Po��Y��&��T��<������E��a���_S	_R�3��Mt��6��f��V
�,��}�N�����s_���o]���A�F�-���9mb�r�������37h�����:��_���X�%��&e���!^3����I�t��z���`�;�K��	��s9��2��w\r��p=,����@VWGO�d5���+O�z��C.:}�������m�����V���5�?Q�|E����g�{���f]����a��b����l�Q6�2�~���`+2�����h��l���Lvw�G��q��R�A���6���f��	��������_�(t�RO��2�����e����<����L7i���������W��N��5}sm)L�7�k���KCv��s=�~�'?(�<1�Q��h!�fe���vi�������vK[*$�e���9��uy)59��q�iQ�Ia��Kc�^��$��(�� �3/�fn�_�����u&������S��$]:�x~_��]�n�cOl�>�>����U��V��^��kr�>z��u��L}�jR��q�Kl���hZ�~�=k��t�['���p-��-����[N|�t������{�����W\����gUk~�����wv�-�/;�t�{j{y���
���ac��4?6?�-Og��v=n�c��
z_������+�	���8z�in���-@�������������^t�����/*i���.��T\c���b���h�<ie-����\k���s0����9���������W.���Gg3nq�TLE
�s�����g0
\��5��M+��sMkQS�5�hZsoE���W����\���4��i�[����xv�kZ����gzrM�[������s�Ns��l�=����y��.��8x;����8�aG�:�����;�V�E�M��lZ_��uc���^>������?3X�g��\������,���X��������4����U@�fc.���l^(�<��/a�B�E��+�A[;��'5p�z�SC��N/�t�-@�����v����"���E���>����2�����I����Lc�(��cHZIK����I��,������x�v��<!�i�={���a{�&�:�q���IlEJaSi%���C�8��6��o�7���W�j�Z*_����4t�����$Vg�U�EW$���i
*�z 	�Wr���W��[��=�o��l��3�W]��&�w�9��t�����\��:������<�._��q~����|\��{����
r�c������M���36�"w��%�~�5tM�(�i�NC��{���-���-�6��@��#�De#s����Is�:��%��bH����I�����/�)w�s�Q�������{����������L���)������_�}���pze��i��C}���}�3���#w�@����W�q��u&�e�5���m�`�{w�������Bi��@���h���E
�	M�$ @�
D	D	������p2�l�k��^��~�G3�w�w�uvvv&-���BB-����fF*���W���1�#:���M��
�>�\��\�H�F2��p_"�]�I��?r=��@r�Gru���<�N^��Wg��M���|q^$#����ZoPM^��������W�M�3&�=�O��l����r�	
J����k5N���E���@���:��"����|#_���>�v}��)��&����������f�dl���k�	�3��vK����%��.���\��L�#��8+�oL�t�gw��be��>�mf�di,`B�����(fccq��x����/�5��$Q����o5
M�
�<XYDnW���{�7	��z��0��	�[�KM�����V��������4����_W�����pI�������� <;�1��Y�+
��'\���>��D�ng��L7���\v���Y�����&�6��y����@=�r���3'i�$��D93���^������+q�d��Dm"w��y��Tf���Da9���v�|���G�=��I��cfYQ�\�T�Nn�����x������R���`.e[�Xw�gA����
H�9�43��B�[�����hhh��u�F���=�-���Zo�Ba��0����7�F��#�y,�� J	����[i9�ya�����7��(�\�a���d�o���#��x�y�K���g�y����<��+-0!?E"_�G��S�!�	��^����aw�kf5��c��I�}v��{k��V�'��mg~��6�^��=d��4c&��� �A$3����bL^T7�1����6:v�on�CC�O��}y^���I�-���Qo��A���Z����T����C�]��u�������|s���������i>���[6X��?w����`����i�Ii���"Q�]�{�����8��8��������^b!��!��6�w�8h��8�!.?�Z� 7�1J8Z�o;^Q���[��3��q?��RC�7A��&=(Ix�k�������K���TM\�����H�xW�0��>�:�n�<��hg=-w>���M�.�xi>
y�*��7=$�0]�_Cc�.�U<���8�S�q��17��B���b!����c@���B\,B\�����_�o��-s�e�+J��K��>�5��}pI���.�=���<��&��D��>C��'�EY�V�.OCM.{?8�ti���^�S����{�}��C��*���i���s��M-���� QY��L�L�{N<�0���\!���y��h�$70�{��K.O!�&��g&�8���U�����T;��n�_�c�SJa8%�!�C�bI1���k���UQ��)���*��,����-��I����yCj��F�O� ���o�h�����/�h�q��2��)��8IC�!��4`��I�&��4xJ�k���X&��l���X�������)+U~eFW6��r{;���#��yw%N�wrm����J�v�/�Ll�^�s�I���a�Lb���J\�1��zh�|�����(F���wRU��pg�C�\��z��&=z����0�9����D�,I�����Fra�oz�E�����*^�.l����|[}$�_�W,4���Pz����>��Lm�]�2#2�4���?x���Y��d=�������3�n�a�a���K�x"�I���pJ&�U:��[����8��Po
J1�8�|��dm�s�,[��P���q�[�Ku\o���a��_�N'�)�H��T���dc� ����Y�s�_�e��>B�������ny����k��u��m���"��s��i�=[Qs/^�3���6�8C������[g���_1S�K<��s%�?95��������K�}~w%�����*s%��1�}F�^��B��HA{%�aj��
�
����M�?z%|�������S\$<kh��o.������I��������mM��H������G
����5��)���f1v��������Ny�K��6�G����z���V�\�^���i����S��uZe�F�OJ0����{��N2+�i�b�V����}����,��'N��]���p�&�QV4Z�7����p����>g������F6���R5����d-A����?��HE��j��K�H�7������~S������
6�G��]w�R�=�Z+*����=1��pH����{[�6\���F�I�
��%v���"3�����4,��'��%���?'�G����	a�w2�|��1�7�Z�D��u���U4i�7�)~�}S�w�������
~Z����B�\����|J��Q��b��w5M?�O�$?������&�&�EY��UrW��UZm�o����}��]n*����I���������#s�
y�u	���-7�Y�<��YF��
1>J����T�����`/	d�C}�K�W�$�+��nbv��� �z����A��;�#8��Po���It;r!z�����s���c�^�{�y�-��w���+L~�>�
�i������}���'k�����r�]�}�GZ�
�9�vc����2S���G��/��Lf��)�F�����$�F��������Y���@��I�3*��3c��Vr�/rq"91����:�I�#G��1Dm����43n��&s�]�I
%��r�T��1��z�R�����=]�;�^�nNJS��}�;6�E��,��P���L� L�A���� "'�)��0�������vY�Xn*�����}S�7�6�'m����~;@�8��-�/&7Q�_CiU����I�)q�O^_ ����D}>3	�� 	����#���������zb��Y�����{�3I� E��|yP
8��Po�ih�,ZTQt^��]�R��Y���@��&?e���R����?���_�6����Gjh�rI�}iy�_[�Um������tW�G��f�q��>[�3�w���m<R�c�\����<?��Af���Q���+Yp��Yof����y��&b(G^�'.�H�	�q#������p.���Uat��a���������&Y�9�%���{�[�V���-�8^��7�>���_zQ�F��X�G��/x��ov��l=M�2���u/e��)���u/��Y��gj`|~��E�0����HG�kHo1K��0�^^�)�d��!De�XHo!/���Ef�� sf���8IeP�p.���I�+k���+� �;�����2R?>�y#���!��$�)�}��G�,��Y,I���Oi���G��7����X�DO����|u��������G��e�e������{�ylhc���X�*������v�,�pf9����G|FN~�,�pk1�^��b}��k��W$���$I�+	�1��z�[���Hu����*J��k��<�/�IzG���P~�0E�]�s�������}��Ky�����
���M�m5���kH��^a*3Yo]���9�[7Z�s8����(��E��OzprA������K%I$��x��k�T��.|.��W��y
55CC���4�8�@]�G��O�>��9c���y/��2�}���?]A�"�wy���bA�Qa�����I��������H�x�'��W|t�����,�-u��4���|�>;�s������R�0<�I"	�$�5�x��.��\\;��Y��l��#��_p!%��	P�^�
�
����_�l�\�A�+���$���zX
��f*?�}�[�s��������wD��E�|������b������\N�^�i���x�D�Uu�����/N�B�_��}S	O��O��H��.<���(�2��iN�;�Y�#.�176�J���\B���0+#I�f���%A�����������J��f�Iz�M��}�O�5��^o��\�M�2�`c�_��m�e������e��OCMl�]��"��9�O93��.�1S_��c��T�L��q��d��h�I�T�+j��M*
��z�^�o��C��������8�4������&� �$������9��y���K~X��������Po�M�2Yo�
S)��g�54�M�m��������&��h��7b�MU4[��EsM[4s���q��d��Ii2�S
���9@��Po��k�"r������_ku���HHz7%}K�W,L���F�4�
}���\���Y.�M4��]��\�c��F;h�����K�p�4i�����>XQ.Ig�F�
b~��I�{���t�<�����Gd�����D���<��<?H,U��l!���7Pi�%�@U�SS�����ZQ4\X��f�P�{�P�oidh�K5D�����E���^(?T����:�7f:��H�x���&����U6Y�����\�lZ�Rv����w?����^�U�����t��Lq���Y���_�o�>������'����W��!��9d������4��
�ro��b���(���P��+�tI�f����A+y��V��G�*�����\O"���I5�7�t.�<������L�r�_�E��[�_O����\24c�J�:��������(r���^�.x�0�B$4���7Pi�%�@���)z��zY��.�[S��+�/�m���4 L�{&�:U��7����}���l�+��zK+�M�r�>�s�c�u�+yy��%����$��dE��t.��$���2#9�N�]L�R����&����w�Q����u����������4��
�~b|��J��?�����'>]�x�iXJ��V}�������|�5<�1�H�a�IJ�_��?�G�bsts��t.N��7��J3i[%e�����f1v�iA�Z��f��@fC<�������2����HN����bn����y��������F�66����4��
@���!i���.��]pS���mV�[I�hc���#�a�T���o,��cM����w�/��0�������T�t.J���t.���x�����s9�|����~��c�WdN\M�s�I"��$�����y�l?3!����Rw��r���v$�0�pj, Z[��af�w�@��IrP���WW��7Pi�%��0?�P�q���%��Kw^=c��������^����\���_[��7��5Ov�I9n
3�1��d~������z��e����^����S���(�E�t.a���%#�Y��9q��\P��M��`n�;5��2���'��;��;3�Tg3��A�_���5�:��
��J.���9��Fg�WJ�5��5��{�o<��M���jC�RsoS��N��G�Z��n��l���p���������)�q%�I�����0����;����u�&��^j��_k����o��L��W�,��{��m��Pl���Q�d��Q��Y�n_gGr~Q2�s3K��>��,3oL�3�LvB�����l�
Tp	���;����*� �>�e��Vy9
��I����J
#�������|��<��x�]j�����|���09a�������2��?L���N���sy�m��C%��<�3�-��%���\r�I�����Cfa;C9�p������.�'��Y�����=���f�����
j��������l�
Tp	�U��F�{P�9��5���(	�X!���h����6z�[�CPD�����1��hd�9|[������A���k�|	~�"�����L��������e���Uf{eJ�s�d`�L�l�lYN�e��hW�oD�n���)�+����R{q�d���2��^�,�`��L��c@"IZyS��W��7Pi�%�TEN!�]������w��xa!��
��'��f���������I�i�|�����a���_�&��<�~u��]���o��?I����T������9��T���u����ny��3��A��S�wTN���\�r�/�������psK��%��"rq"QL�w�.���.Ya����%��Y���X�/��������Pi�%�T������gR��7��Rwl������5J�z��iy�I�.5���(F�i%L�%���.gF{Z�����0��9S�SsA�����r<�;��u��h:���i:��/���\�4��\2�3�d3K�'���W��1��H�G���9�����WD�W#9���_��������f�B�X]"�Z$��$���Z�1�S����@��Po�Q�f^��e��P�DI�T��k�HY4��$������no�18�4��%?P�f$�U��{��9���g���<���D&'�Wf�"��N���"6��+��������\vY�8�v�v��Q��o��������8�%g��4����?���������F��K���%��b�@��3K�3�����\.��(4��
*Tp	����.�3�T������kI�Z���Y��u3���(��uu�uE�d�p�Q�k��6C��*L~����7�}
�����~�}�n����������lGR���gb�s��uM���|}L�2�d:E�3��.X��Z�K�8]l|��Z4p��E��`�����	�4f2��K3���OBc�If,7_>41��g���\B�A�w�(XYH+Te�z"HK)��J������?��7�6R5+�����z���7��Lka�mA�!��
��8�u�:�9��9C�C}^�j@�|8����t.�=���'+�t6^���Bw����#�M���������_3,��z������~b�>����!��^fpi�+f�i^j}��<5��
�Tp	��2��S��JX�WG��Ip���:S*�=���Zs|�)���o��,��B��[
��i�����)��<�����}�]x���>���������0��?
;��I��h:����u8���{����*���e�?
��9^��:1����!|.��������Df��������3uL�3�LQN���a�4]�4�*
��z��$�G��C�,$�o��9D��*�b�Ot`���	�
�4��^Syt�k���;�o�Zah(�$��������dmA�?p�c*�����~6_��&���	"�I���8��>DzQVpV�C��a������7�����J~���k��&=^�@s�����^�����*s=�m�����_���]�;�?f��+S� ���K%fI#��,Q}8�7Pi�
Tp	�����[������4�e�K%/;��?.�����
++����7��~o�J�M���d�!�����f��
����V�]�Y����g?��9]�� ��0E��y����i����.�a��~ON�]��UZk.;�vxN}8o�����;���9�Q���58���������R,����w��������Ff�wKf��`���,_p,n����4��
��@G<aYW/�����K�0���&��
�����7�W/�<�^�����n$h9�M���V�}KA�0�TwU"��^�s��g��.F{v�9��{�%�'��&L7'�au��E�7�y�^i��Z!FW|s���Zq���T�
5�{���Yu{����^�����(
1R�����!���p������("*����'���Qb�F�tI�-I	!�Yu�V�e�
Tp�\B�AY����i�m�X��My+288G�w�h���~��j7x�����/_Xy4[�����������e���PU5�[��$�C��#�:������PG�={�]'���
"����IqRm>]Nq^DN�K��q����g*�w�U��>�����tWW+���p��{���������W�)_u��0���LJ�^�����:�Jsxi��g��pry
�����!����-���D�����|i�
�2�*
��J.�����U��o����_Lx�������.yRTT�w����^�]2��H���
�S2��u2�yEok�nP_>���If�
5�G�~����y6��������A��g�)z$����j��iE�A�v	��t�����)o�80���*���.�3m������?�:�����)
18����>��>������E=����Dy�6�<XO���������{��Zed�����Jn���K�7(%��
���BY�����������Z������h���g���qgUc��f�R��S�9���"�A����
��qj���|��<�x���b�g'�R�����oA��Z{�X���b��fz���	�k{lN�6�7���JR��/������]�'�2���(
����h��������'������z�?{;����x���hm%FG��U��M�lHJ0)����t��cp��@��Po ����YV�SX�muJ���sB���G����5����y�+���3���>r��������������\/a�� �,?h{������h���|�_�~k�����Y��M�Gw'�W�����oc�(��e��G�TwX_f"5E}��7����w�m��}��/'U�\=?�����X��%�3R�s����Iy�����0�������&f'��M�kH��IFT���4���4�*
��zaQa���&����oZ��������Q�2��rn�+vq�<�7wj%10t����.��}��69��4$�I�l{a�}A�q��Z���M�:�9���'?p� ZY��Kr=��
+�]�����me�������:��h�D�Ul���p�_wgl�9y��	G��t^e�M��tN
xy�K�#�>�-i_��=�%��!��g�����u����s����"�IrVW�(���4�*
��z��S�q�����BA1y�_�t��?/�?�� ��&����Y�+��A�g?���v�����SX���0L�n.��&���Y�s�L�Y7�=��{/����
�MIAH�7O-���Mp�����>��.cwf�K�9�[g���������S����1j��?T����������-�9K���S�lwf��?3�.�_���gv�YT��)	~E�<�����x%�f�2�*
��J.���U�� ��6*��tJ�WZ��3K���gW��I��@�9��m>w[��.���a$��O���)���s�����y���h�������~��G�	w�Y6�M��m��S���_�9=
5Q�yt�V����1���oM;v�'�n+�{r���/]�
�����}��V�Ly2���/��Hf��K��m��<3+��&3	g�#��B~�����e�
Tp�\B�%,���7C����������"��NKK�-��k���\~���3
��p�8Y�� Lz �P�����M��|Q7���?�c*?p� �L��r��������x�x7+?]#�Kz�rO�nx|{�����g�3R���ho_���;�H�r�\O�8�����\f�M}f���|,!���7���[\�n�p,n����4��
��3*����G�_3��<��^Qt]����
m�P�S�
#����PY��b��h�U������8��=_��=�].��X��/#9W��N��/��~�[��_��uM���x�D/���H�~E��"W��;�����abu���'���L,�a� C�'�-���4�*
��z������d����:�����K��i�w\����c����S��iF�����|��<��5�{f���[�u[��<��}o@��qj�b.��44�x���=
d$<����g���DeQ�On${��ib�N�tI�I�%�������4�*
��z��������������O7�xX��=K������a��0EGs��������G�r�qk�A+��V���w>��D����s�
N��=�&�`��}Ny<��E��O
{��;���h�$�G��*q{HLH�I'�u\���X�@�7Pi�%�[3������A���������O������������|�|�_x�}*z�%���Z	4[	4>\�D����LK�bK�����)I�<����S��/�N��2>Yc^���&G����cVKO�#9���������Jn���K��f.p���Wl���\(N!��������#��M�d��#xV�+���W2z�N+������w��P�%��B�)/_�M��Na����8����kS�����������IO��$=��H����2�*
��J.������������4!���,;a�A�A��w9��7�]������.��=��|�O�2�	zi2�"d�x���X����]��@c��G���K[X�u�z�e��X��p0���
��Jn���K��fN��nKz_^6�f�&�D�d�����s��g��t�3z����{�gZ(�)<��x�'\��\�6q�;���p����WZ��87L��(%�����{��������:afV�.~����5�z���Po�
Tp�\B�5s�3�<�h��w��*N��	S�	�����������,������\����i�J��������>��H���r��F���~�����'��=3����T�{m�f�?Vi�^��a�������7o�F�vH���L/���Y���Po�
Tp�\B�5s������>���*f�����!�|�e|�	<�oDq/W����bow�R�~�k��.��:�h�'��������Z�]=?B��X�����2����,��l�rS�m�G�/�xi�zfm�����S�'�/}p	��@�7Pi�%�s�%����I�|��f����HE~�6��\���4�>���j�������^�Wzy���s�g���q:f���2�y���{j���q��;37h�^m�o��
zg=n��=yjlc�����X�ZP�|�����zn����4��M"�������������{��^^^�}ooo�D�t�"�����RSk~�W���c��e;2;�5Q�2�
s_��0��h����M�~er�kS�~���:���u���.\���+��T�;{u���st63��I����[:�a��n)~�Y�)���Nk}p	��@�7Pi�%�����i�k������]\\=z����m����T�E����S�����\�p�C��e�����K��tf��Lka�SA�A��D�-���=��s�������������r_��}����G�g�l�,i�����G���{��i]�y{���n�����t/��0��u��WZ`TN|��������
��Jn���K�7�2�E�4�����;u���]�*���� �1
�QQQ�F===��C��oQ�����f;�\/RL����iDPP7��&V���L���)?���5�bv������T��v�����<O~�w�G�����:�Kqt��(���v�;��������5f�h�56�of�b��m��������6�n���}p	��@�7Pi�%���^�JS�?�P�]ZZ��/]��*/�d������K��=���������Me�L?������4K�Xv�Y�����0��<���+���5����� �A�� BA�P�wB��-�tN��q����]�r�g����G��������=��)�S �6I�{���~gGz�Mq���������GQ�Ii�,��@�\B�7Pi�
Tp	�����F��G��j�����m�������.YYYm���Z�z�����}��q5�=a�� �
�o5�~�_v�2�{��p)�_whO�y�����4�*�������a��}ri�3�o���Y)�q:������G����w��A��)��4]�����.�~s^��m1f��oe�$Q5�������Po�
Tp�\B�q)##�E	CC�R����T�"�����99��D322b�����n�bU�^s�Ze�j�����g��?�?����g�]�e�I*�U��/�6E�[���"�|z��������'�)d8�*2'	>$;�_�5�-�%�p��@��Po\���e����w�G{��A:q�D�/���H7���[��|}}�������.eZ��V�w�S���j���!�i��n���x�����x��s=�6��������d�����*~:� �-�%�p��@��Po\z��������>:t�P���m�*�-[���
T����$�������K�\��R��U����r]���v81����W��X�_f�����I7��!���A����@�\B�7Pi�
Tp	��%uuu6�����}t�����U�VU�"+W����1��CYYY��khhTq��������Pa`��9*�d]���1?Ese���	z�c�F�<a����� �O�/��;��=��?#,�����-�%�p��@��Po\�<��������������=����|Os�~f�FZ�����cy�m�	�ug�^)���k�-�-�p��@��Po\j��E��������7{�FM�8q��_����Xh�9����t��$U18@�U��D~~~���066��zP�*Z�������i��6��+((�r=z�'W�^��m�����eddh���KK��x���Z�q��%t�={��j3fmWSS��}��+..2dMm����������;�k�.((H|coo�N�:�i����D��nF7���ctt�������,}q���)����{����C�.���>~�x��m�����.����������R���S���O�N_DEE�� }Y��\}����T)))?��S��/_���Uv�����C������9`�����������/Xvd)4y>>>���?��S�.]��i��w��s����U�oo�+V|t�����={�|��m������444�}5�^-Z�8{�l�|h<�,YB����*����`��)��w�����Q�.\�����n�b�r�����m����%4h��\�x���7e7�b����/Z��k������4i���m�o�k���-[:;;��G����_��7��.�C������IHH�h{T���=��#����������:Z{�i�j���-,,����]�n��-_�<&&��6|>�����srr����!����������������u��h������}[�)����x���G��������h',��@ �<y2
�7n������};}Mee�R������_�a����^��={��E�J����4���?��������?��_'L�PPP ��
����Oc��q�������fii�s�N�����Jm\�b�O�������K7suu���������yyy�j�j��-��	�a���ukZ	G������t��5�~��3-������*h=�R���O�^��<X�s3�+�r���m�6{{{Z`�J�oWjKiu�Z�hbbB_�F���Km���J�N���$b����azf.������sg�~���R��k��v2QQQ�F�����C���E���?���w��<�}������/(++K7�����
_vvv�>}�2�(jjj�GG�%^W�v���6l��e����i�f���|>_���I�<X�b�����4i��������_~�E|�PH[z�����Q��
���8zX�Uq��-�vZ9�q��A�@��U���<p�����w���h����-�;v�Z�6c�����>��3f�H����_i���8p@|��v���&��~V�0�������������w����v����7k����]MMM���t�Z�k�/^���~f��5u�a����uk�.]N�:UQ����}�������i��l����O��b�Rh������o�^t#BO�o��YXX(j�V����t���|Q��#�6���444��h�._�L����J�>WWW�4���M��b�*���Z�j-����������Q�����Z�n���"�nhhH7��)������~mC�����(�D���zk�I@����?~\����{l�#�oMYYY�y�hiiYj������q���ZV�XA[\\\D-


�[��G��]���A�fccCF��_g����<hddDj��mQQQ��h���deeE-(6(���`���l\�b���7=���g��J��z��9~�x�PX�����-�!C��jOMMe���D�(6�"QX�h���y�����[��i��c����	�L�5k�hZi�|���_~)j���*{������������lc����c%��u�V�����h�={�����r�J=hX�Y=q�8q"=�T��K~�G�.�{,9r�����Z����O�>]���Ul�zi���E�(mIKKc��ys�V����j�	���z�*-��]��j���e�AAA�FT�G�`�������eo�~��G�=���&&&�_��g�4{��������}���������J��
M�oJ�oTTTlQr�|��E>�����>=������-[�������z��=f��Rl��;p�@��m��J���)S�C.,�;:�>Kt_�
J4h-���;;;/Z��W�^������5k�������*�����_�IIIi��
};�W'''Zx��)h���:v�H����\����#��V�x#�
���y�Z�f<�v�����Ke���%}h���������]�v�	d��������9s����n�����k���7n���E���e�OJJb�---�������:t��Gjj*0��[�>����br�f����u��


��������t��c�M4%�
���8;^�U�V��o�����=?��F��E��Z����C_�>���366v��y��;w����G���_`�����<�;w�zzb���������B�m��i�n�B�Au}4V��,!!�my��a���m���d
Q�������V ����� %�bw��q���u�!��155eG���o�����F��Oa�P�������?�m�ge�6mb���.���u�VRrP���_�~���3��������c�
&�W��<H�s�C4��}����&jD��=o�����S ���];�9��[l���_}����Kz���_�t��(I�;--m��
��u���������^>*4qqq�!�E������������>��un�����������O�>��g����������[XX��.�}iDD)���?����}�hx�����G�����G�=z����z��>����AV||���Ovv6��P(�I���>c'�f�1j��������������T$����-[�tpp��,���?kb������b+�}���T���C����D��A����-�����HJJ������7o������������O?�DO�+ZI��'O���&�j.^�H��fff���o��5m,���
��6y���Y�y����T$%e���GOE3����-���9p��/^<}��W�^}��-�F!4�p3y��:8::�}�Zc*B�Yt���o��%�O�4�}�����7���+�o�������3��;w�7��x�����'QwTj�6;���D-uRl��Ltc��k��/M��oQf�?h2�~�c��111����o�Z����5����$;^�\EEE���Ls"�u��e�Y�������3�@#�������s33�r7��=��JOO�����������s��STUUEHIIU��V��M�2���?�G�<17n�`���E4D�Z�.���l�s���eeo/m�������fiiI7;x� ���9s��>>>�
F��BlZHhJ���G���v�*��w/-T�d��)���G�f���@ ���s��=E����+�^	
�"h?@�D�ug��dNcccc�����l���U�V�����;w�,�������������@�C��E�����Y�������������
8��q���[�!6�3"QK-���q������>|�p����,�6����-���5�<�P��S���e]�f
}��o������j��D��f��7��O?�[o�\aaa�\q��%��iiie��K�.�:u��������/^��� �/�K�������~�d�Sv�����8::�l�RJJJ��c�������ZTUUq��$��G^^�=3��7��U���(���+��bk�6l�P��u�Q�,6%%%���mb��
�-���_��S�&I���;O��A��|(6����G_��Y���/��3h����cMMM�O3f��6��wGh\h\�d	�L�O�Y;v,5#���;�]mWSS��]����w��uQ���\�k6*������S�H#�U�����*zY�z��E��[eG�}����!QKm�-&&�C�s��od����B���?����H ����E�������>�I5��|}}i��n��F9�vzH7����h���ttt�6�x*ja��~��������/
���0�l�2z*��)��A�]�v�=::Z����=d��J�vr�R���F������1�G�QI�455�u|������
{��
��,�
H�?b��������);�w���� �^�b������/5�:;����)))�&Sz�^��
���l����i��6+TKU�`u�������j���i#����%??��/���Nz�(���'��������M������	bg����O:��>Tv�6�z��m������cWWW�:���[|=�R�t�R����mk�����jTT���[`	�f��,J����i�����S�-�����'O677wpp`��0a�����Pl�JOO�����_y���666...


���G���������{s����K�7255���Y��@VTT4s�LZ	�z��t����-!��}��/�|
q�����l�=�R���:7��F����?��C+��!=hVtS�;��l���s��c�zyy9::�}�z���_��R�������|�r��|������*5��vr�r;%>�Opt7�!l��!��8�&�2�-�r�M�����5u����F�y���R�2Y
�
D����3gF���S������w{��MLL�h�j[��K�]���{��I;�_~���}=���B--�9s���"�^��k7p��u��999U�TN�TDY<(�)�:7��v��Z{�i�j����d���im��.�QzX�6m})-Z����r����
endstream
endobj
15 0 obj
<</Filter /FlateDecode
/Length 188>> stream
x����
�0��}���&i��.�������|0�� 8F�
I�J�-�dG��7�t�b���	rz��qpM/0�\��@���]��������G����hD��A���7p��O��(M{�AU`��Id����)�>��F���-���W���b>W~u/�CJ�k���P9+��������~p)?��7��xO
endstream
endobj
2 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R>>
/XObject <</X4 4 0 R
/X6 6 0 R
/X7 7 0 R
/X8 8 0 R>>>>
/MediaBox [0 0 842 596]
/Contents 9 0 R
/StructParents 0
/Parent 16 0 R>>
endobj
10 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R>>
/XObject <</X11 11 0 R
/X12 12 0 R
/X13 13 0 R
/X14 14 0 R>>>>
/MediaBox [0 0 842 596]
/Contents 15 0 R
/StructParents 1
/Parent 16 0 R>>
endobj
16 0 obj
<</Type /Pages
/Count 2
/Kids [2 0 R 10 0 R]>>
endobj
17 0 obj
<</Type /Catalog
/Pages 16 0 R
/ViewerPreferences <</Type /ViewerPreferences
/DisplayDocTitle true>>>>
endobj
xref
0 18
0000000000 65535 f 
0000000015 00000 n 
0000504387 00000 n 
0000000108 00000 n 
0000000460 00000 n 
0000000145 00000 n 
0000063203 00000 n 
0000112261 00000 n 
0000177449 00000 n 
0000246224 00000 n 
0000504629 00000 n 
0000246482 00000 n 
0000314271 00000 n 
0000375786 00000 n 
0000442325 00000 n 
0000504128 00000 n 
0000504881 00000 n 
0000504944 00000 n 
trailer
<</Size 18
/Root 17 0 R
/Info 1 0 R>>
startxref
505063
%%EOF
run.shapplication/x-shellscript; name=run.shDownload
#28Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#26)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Mar 1, 2024 at 2:31 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Feb 29, 2024 at 7:29 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Feb 29, 2024 at 5:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 22:19, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 7:54 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 00:40, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 6:17 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 21:06, Melanie Plageman wrote:

On Wed, Feb 28, 2024 at 2:23 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/28/24 15:56, Tomas Vondra wrote:

...

Sure, I can do that. It'll take a couple hours to get the results, I'll
share them when I have them.

Here are the results with only patches 0001 - 0012 applied (i.e. without
the patch introducing the streaming read API, and the patch switching
the bitmap heap scan to use it).

The changes in performance don't disappear entirely, but the scale is
certainly much smaller - both in the complete results for all runs, and
for the "optimal" runs that would actually pick bitmapscan.

Hmm. I'm trying to think how my refactor could have had this impact.
It seems like all the most notable regressions are with 4 parallel
workers. What do the numeric column labels mean across the top
(2,4,8,16...) -- are they related to "matches"? And if so, what does
that mean?

That's the number of distinct values matched by the query, which should
be an approximation of the number of matching rows. The number of
distinct values in the data set differs by data set, but for 1M rows
it's roughly like this:

uniform: 10k
linear: 10k
cyclic: 100

So for example matches=128 means ~1% of rows for uniform/linear, and
100% for cyclic data sets.

Ah, thank you for the explanation. I also looked at your script after
having sent this email and saw that it is clear in your script what
"matches" is.

As for the possible cause, I think it's clear most of the difference
comes from the last patch that actually switches bitmap heap scan to the
streaming read API. That's mostly expected/understandable, although we
probably need to look into the regressions or cases with e_i_c=0.

Right, I'm mostly surprised about the regressions for patches 0001-0012.

Re eic 0: Thomas Munro and I chatted off-list, and you bring up a
great point about eic 0. In old bitmapheapscan code eic 0 basically
disabled prefetching but with the streaming read API, it will still
issue fadvises when eic is 0. That is an easy one line fix. Thomas
prefers to fix it by always avoiding an fadvise for the last buffer in
a range before issuing a read (since we are about to read it anyway,
best not fadvise it too). This will fix eic 0 and also cut one system
call from each invocation of the streaming read machinery.

To analyze the 0001-0012 patches, maybe it'd be helpful to run tests for
individual patches. I can try doing that tomorrow. It'll have to be a
limited set of tests, to reduce the time, but might tell us whether it's
due to a single patch or multiple patches.

Yes, tomorrow I planned to start trying to repro some of the "red"
cases myself. Any one of the commits could cause a slight regression
but a 3.5x regression is quite surprising, so I might focus on trying
to repro that locally and then narrow down which patch causes it.

For the non-cached regressions, perhaps the commit to use the correct
recheck flag (0004) when prefetching could be the culprit. And for the
cached regressions, my money is on the commit which changes the whole
control flow of BitmapHeapNext() and the next_block() and next_tuple()
functions (0010).

I do have some partial results, comparing the patches. I only ran one of
the more affected workloads (cyclic) on the xeon, attached is a PDF
comparing master and the 0001-0014 patches. The percentages are timing
vs. the preceding patch (green - faster, red - slower).

Just confirming: the results are for uncached?

Yes, cyclic data set, uncached case. I picked this because it seemed
like one of the most affected cases. Do you want me to test some other
cases too?

So, I actually may have found the source of at least part of the
regression with 0010. I was able to reproduce the regression with
patch 0010 applied for the unached case with 4 workers and eic 8 and
100000000 rows for the cyclic dataset. I see it for all number of
matches. The regression went away (for this specific example) when I
moved the BitmapAdjustPrefetchIterator call back up to before the call
to table_scan_bitmap_next_block() like this:

diff --git a/src/backend/executor/nodeBitmapHeapscan.c
b/src/backend/executor/nodeBitmapHeapscan.c
index f7ecc060317..268996bdeea 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -279,6 +279,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
}
new_page:
+       BitmapAdjustPrefetchIterator(node, node->blockno);
+
if (!table_scan_bitmap_next_block(scan, &node->recheck,
&lossy, &node->blockno))
break;

@@ -287,7 +289,6 @@ new_page:
else
node->exact_pages++;

- BitmapAdjustPrefetchIterator(node, node->blockno);
/* Adjust the prefetch target */
BitmapAdjustPrefetchTarget(node);
}

It makes sense this would fix it. I haven't tried all the combinations
you tried. Do you mind running your tests with the new code? I've
pushed it into this branch.
https://github.com/melanieplageman/postgres/commits/bhs_pgsr/

Hold the phone on this one. I realized why I moved
BitmapAdjustPrefetchIterator after table_scan_bitmap_next_block() in
the first place -- master calls BitmapAdjustPrefetchIterator after the
tbm_iterate() for the current block -- otherwise with eic = 1, it
considers the prefetch iterator behind the current block iterator. I'm
going to go through and figure out what order this must be done in and
fix it.

So, I investigated this further, and, as far as I can tell, for
parallel bitmapheapscan the timing around when workers decrement
prefetch_pages causes the performance differences with patch 0010
applied. It makes very little sense to me, but some of the queries I
borrowed from your regression examples are up to 30% slower when this
code from BitmapAdjustPrefetchIterator() is after
table_scan_bitmap_next_block() instead of before it.

SpinLockAcquire(&pstate->mutex);
if (pstate->prefetch_pages > 0)
pstate->prefetch_pages--;
SpinLockRelease(&pstate->mutex);

I did some stracing and did see much more time spent in futex/wait
with this code after the call to table_scan_bitmap_next_block() vs
before it. (table_scan_bitmap_next_block()) calls ReadBuffer()).

In my branch, I've now moved only the parallel prefetch_pages-- code
to before table_scan_bitmap_next_block().
https://github.com/melanieplageman/postgres/tree/bhs_pgsr
I'd be interested to know if you see the regressions go away with 0010
applied (commit message "Make table_scan_bitmap_next_block() async
friendly" and sha bfdcbfee7be8e2c461).

- Melanie

#29Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#27)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 2, 2024 at 10:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Here's a PDF with charts for a dataset where the row selectivity is more
correlated to selectivity of pages. I'm attaching the updated script,
with the SQL generating the data set. But the short story is all rows on
a single page have the same random value, so the selectivity of rows and
pages should be the same.

The first page has results for the original "uniform", the second page
is the new "uniform-pages" data set. There are 4 charts, for
master/patched and 0/4 parallel workers. Overall the behavior is the
same, but for the "uniform-pages" it's much more gradual (with respect
to row selectivity). I think that's expected.

Cool! Thanks for doing this. I have convinced myself that Thomas'
forthcoming patch which will eliminate prefetching with eic = 0 will
fix the eic 0 blue line regressions. The eic = 1 with four parallel
workers is more confusing. And it seems more noticeably bad with your
randomized-pages dataset.

Regarding your earlier question:

Just to be sure we're on the same page regarding what eic=1 means,
consider a simple sequence of pages: A, B, C, D, E, ...

With the current "master" code, eic=1 means we'll issue a prefetch for B
and then read+process A. And then issue prefetch for C and read+process
B, and so on. It's always one page ahead.

Yes, that is what I mean for eic = 1

As for how this is related to eic=1 - I think my point was that these
are "adversary" data sets, most likely to show regressions. This applies
especially to the "uniform" data set, because as the row selectivity
grows, it's more and more likely it's right after to the current one,
and so a read-ahead would likely do the trick.

No, I think you're right that eic=1 should prefetch. As you say, with
high selectivity, a bitmap plan is likely not the best one anyway, so
not prefetching in order to preserve the performance of those cases
seems silly.

- Melanie

#30Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#29)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/2/24 23:28, Melanie Plageman wrote:

On Sat, Mar 2, 2024 at 10:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Here's a PDF with charts for a dataset where the row selectivity is more
correlated to selectivity of pages. I'm attaching the updated script,
with the SQL generating the data set. But the short story is all rows on
a single page have the same random value, so the selectivity of rows and
pages should be the same.

The first page has results for the original "uniform", the second page
is the new "uniform-pages" data set. There are 4 charts, for
master/patched and 0/4 parallel workers. Overall the behavior is the
same, but for the "uniform-pages" it's much more gradual (with respect
to row selectivity). I think that's expected.

Cool! Thanks for doing this. I have convinced myself that Thomas'
forthcoming patch which will eliminate prefetching with eic = 0 will
fix the eic 0 blue line regressions. The eic = 1 with four parallel
workers is more confusing. And it seems more noticeably bad with your
randomized-pages dataset.

Regarding your earlier question:

Just to be sure we're on the same page regarding what eic=1 means,
consider a simple sequence of pages: A, B, C, D, E, ...

With the current "master" code, eic=1 means we'll issue a prefetch for B
and then read+process A. And then issue prefetch for C and read+process
B, and so on. It's always one page ahead.

Yes, that is what I mean for eic = 1

As for how this is related to eic=1 - I think my point was that these
are "adversary" data sets, most likely to show regressions. This applies
especially to the "uniform" data set, because as the row selectivity
grows, it's more and more likely it's right after to the current one,
and so a read-ahead would likely do the trick.

No, I think you're right that eic=1 should prefetch. As you say, with
high selectivity, a bitmap plan is likely not the best one anyway, so
not prefetching in order to preserve the performance of those cases
seems silly.

I was just trying to respond do this from an earlier message:

Yes, I would like to see results from a data set where selectivity is
more correlated to pages/heap fetches. But, I'm not sure I see how
that is related to prefetching when eic = 1.

And in that same message you also said "Not doing prefetching with eic 1
actually seems like the right behavior". Hence my argument we should not
stop prefetching for eic=1.

But maybe I'm confused - it seems agree eic=1 should prefetch, and that
uniform data set may not be a good argument against that.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#31Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#28)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/2/24 23:11, Melanie Plageman wrote:

On Fri, Mar 1, 2024 at 2:31 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

...

Hold the phone on this one. I realized why I moved
BitmapAdjustPrefetchIterator after table_scan_bitmap_next_block() in
the first place -- master calls BitmapAdjustPrefetchIterator after the
tbm_iterate() for the current block -- otherwise with eic = 1, it
considers the prefetch iterator behind the current block iterator. I'm
going to go through and figure out what order this must be done in and
fix it.

So, I investigated this further, and, as far as I can tell, for
parallel bitmapheapscan the timing around when workers decrement
prefetch_pages causes the performance differences with patch 0010
applied. It makes very little sense to me, but some of the queries I
borrowed from your regression examples are up to 30% slower when this
code from BitmapAdjustPrefetchIterator() is after
table_scan_bitmap_next_block() instead of before it.

SpinLockAcquire(&pstate->mutex);
if (pstate->prefetch_pages > 0)
pstate->prefetch_pages--;
SpinLockRelease(&pstate->mutex);

I did some stracing and did see much more time spent in futex/wait
with this code after the call to table_scan_bitmap_next_block() vs
before it. (table_scan_bitmap_next_block()) calls ReadBuffer()).

In my branch, I've now moved only the parallel prefetch_pages-- code
to before table_scan_bitmap_next_block().
https://github.com/melanieplageman/postgres/tree/bhs_pgsr
I'd be interested to know if you see the regressions go away with 0010
applied (commit message "Make table_scan_bitmap_next_block() async
friendly" and sha bfdcbfee7be8e2c461).

I'll give this a try once the runs with MAX_BUFFERS_PER_TRANSFER=1
complete. But it seems really bizarre that simply moving this code a
little bit would cause such a regression ...

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#32Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#30)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 2, 2024 at 5:41 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/2/24 23:28, Melanie Plageman wrote:

On Sat, Mar 2, 2024 at 10:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Here's a PDF with charts for a dataset where the row selectivity is more
correlated to selectivity of pages. I'm attaching the updated script,
with the SQL generating the data set. But the short story is all rows on
a single page have the same random value, so the selectivity of rows and
pages should be the same.

The first page has results for the original "uniform", the second page
is the new "uniform-pages" data set. There are 4 charts, for
master/patched and 0/4 parallel workers. Overall the behavior is the
same, but for the "uniform-pages" it's much more gradual (with respect
to row selectivity). I think that's expected.

Cool! Thanks for doing this. I have convinced myself that Thomas'
forthcoming patch which will eliminate prefetching with eic = 0 will
fix the eic 0 blue line regressions. The eic = 1 with four parallel
workers is more confusing. And it seems more noticeably bad with your
randomized-pages dataset.

Regarding your earlier question:

Just to be sure we're on the same page regarding what eic=1 means,
consider a simple sequence of pages: A, B, C, D, E, ...

With the current "master" code, eic=1 means we'll issue a prefetch for B
and then read+process A. And then issue prefetch for C and read+process
B, and so on. It's always one page ahead.

Yes, that is what I mean for eic = 1

As for how this is related to eic=1 - I think my point was that these
are "adversary" data sets, most likely to show regressions. This applies
especially to the "uniform" data set, because as the row selectivity
grows, it's more and more likely it's right after to the current one,
and so a read-ahead would likely do the trick.

No, I think you're right that eic=1 should prefetch. As you say, with
high selectivity, a bitmap plan is likely not the best one anyway, so
not prefetching in order to preserve the performance of those cases
seems silly.

I was just trying to respond do this from an earlier message:

Yes, I would like to see results from a data set where selectivity is
more correlated to pages/heap fetches. But, I'm not sure I see how
that is related to prefetching when eic = 1.

And in that same message you also said "Not doing prefetching with eic 1
actually seems like the right behavior". Hence my argument we should not
stop prefetching for eic=1.

But maybe I'm confused - it seems agree eic=1 should prefetch, and that
uniform data set may not be a good argument against that.

Yep, we agree. I was being confusing and wrong :) I just wanted to
make sure the thread had a clear consensus that, yes, it is the right
thing to do to prefetch blocks for bitmap heap scans when
effective_io_concurrency = 1.

- Melanie

#33Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#31)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 2, 2024 at 5:51 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/2/24 23:11, Melanie Plageman wrote:

On Fri, Mar 1, 2024 at 2:31 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

...

Hold the phone on this one. I realized why I moved
BitmapAdjustPrefetchIterator after table_scan_bitmap_next_block() in
the first place -- master calls BitmapAdjustPrefetchIterator after the
tbm_iterate() for the current block -- otherwise with eic = 1, it
considers the prefetch iterator behind the current block iterator. I'm
going to go through and figure out what order this must be done in and
fix it.

So, I investigated this further, and, as far as I can tell, for
parallel bitmapheapscan the timing around when workers decrement
prefetch_pages causes the performance differences with patch 0010
applied. It makes very little sense to me, but some of the queries I
borrowed from your regression examples are up to 30% slower when this
code from BitmapAdjustPrefetchIterator() is after
table_scan_bitmap_next_block() instead of before it.

SpinLockAcquire(&pstate->mutex);
if (pstate->prefetch_pages > 0)
pstate->prefetch_pages--;
SpinLockRelease(&pstate->mutex);

I did some stracing and did see much more time spent in futex/wait
with this code after the call to table_scan_bitmap_next_block() vs
before it. (table_scan_bitmap_next_block()) calls ReadBuffer()).

In my branch, I've now moved only the parallel prefetch_pages-- code
to before table_scan_bitmap_next_block().
https://github.com/melanieplageman/postgres/tree/bhs_pgsr
I'd be interested to know if you see the regressions go away with 0010
applied (commit message "Make table_scan_bitmap_next_block() async
friendly" and sha bfdcbfee7be8e2c461).

I'll give this a try once the runs with MAX_BUFFERS_PER_TRANSFER=1
complete. But it seems really bizarre that simply moving this code a
little bit would cause such a regression ...

Yes, it is bizarre. It also might not be a reproducible performance
difference on the cases besides the one I was testing (cyclic dataset,
uncached, eic=8, matches 16+, distinct=100, rows=100000000, 4 parallel
workers). But even if it only affects that one case, it still had a
major, reproducible performance impact to move those 5 lines before
and after table_scan_bitmap_next_block().

The same number of reads and fadvises are being issued overall.
However, I did notice that the pread calls are skewed when the those
lines of code are after table_scan_bitmap_next_block() -- fewer of
the workers are doing more of the reads. Perhaps this explains what is
taking longer. Why those workers would end up doing more of the reads,
I don't quite know.

- Melanie

#34Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#24)
2 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/1/24 17:51, Melanie Plageman wrote:

On Fri, Mar 1, 2024 at 9:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/1/24 02:18, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 6:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 23:44, Tomas Vondra wrote:
1) On master there's clear difference between eic=0 and eic=1 cases, but
on the patched build there's literally no difference - for example the
"uniform" distribution is clearly not great for prefetching, but eic=0
regresses to eic=1 poor behavior).

Yes, so eic=0 and eic=1 are identical with the streaming read API.
That is, eic 0 does not disable prefetching. Thomas is going to update
the streaming read API to avoid issuing an fadvise for the last block
in a range before issuing a read -- which would mean no prefetching
with eic 0 and eic 1. Not doing prefetching with eic 1 actually seems
like the right behavior -- which would be different than what master
is doing, right?

I don't think we should stop doing prefetching for eic=1, or at least
not based just on these charts. I suspect these "uniform" charts are not
a great example for the prefetching, because it's about distribution of
individual rows, and even a small fraction of rows may match most of the
pages. It's great for finding strange behaviors / corner cases, but
probably not a sufficient reason to change the default.

Yes, I would like to see results from a data set where selectivity is
more correlated to pages/heap fetches. But, I'm not sure I see how
that is related to prefetching when eic = 1.

I think it makes sense to issue a prefetch one page ahead, before
reading/processing the preceding one, and it's fairly conservative
setting, and I assume the default was chosen for a reason / after
discussion.

Yes, I suppose the overhead of an fadvise does not compare to the IO
latency of synchronously reading that block. Actually, I bet the
regression I saw by accidentally moving BitmapAdjustPrefetchIterator()
after table_scan_bitmap_next_block() would be similar to the
regression introduced by making eic = 1 not prefetch.

When you think about IO concurrency = 1, it doesn't imply prefetching
to me. But, I think we want to do the right thing and have parity with
master.

My suggestion would be to keep the master behavior unless not practical,
and then maybe discuss changing the details later. The patch is already
complicated enough, better to leave that discussion for later.

Agreed. Speaking of which, we need to add back use of tablespace IO
concurrency for the streaming read API (which is used by
BitmapHeapScan in master).

With very low selectivity, you are less likely to get readahead
(right?) and similarly less likely to be able to build up > 8kB IOs --
which is one of the main value propositions of the streaming read
code. I imagine that this larger read benefit is part of why the
performance is better at higher selectivities with the patch. This
might be a silly experiment, but we could try decreasing
MAX_BUFFERS_PER_TRANSFER on the patched version and see if the
performance gains go away.

Sure, I can do that. Do you have any particular suggestion what value to
use for MAX_BUFFERS_PER_TRANSFER?

I think setting it to 1 would be the same as always master -- doing
only 8kB reads. The only thing about that is that I imagine the other
streaming read code has some overhead which might end up being a
regression on balance even with the prefetching if we aren't actually
using the ranges/vectored capabilities of the streaming read
interface. Maybe if you just run it for one of the very obvious
performance improvement cases? I can also try this locally.

Here's some results from a build with

#define MAX_BUFFERS_PER_TRANSFER 1

There are three columns:

- master
- patched (original patches, with MAX_BUFFERS_PER_TRANSFER=128kB)
- patched-single (MAX_BUFFERS_PER_TRANSFER=8kB)

The color scales are always branch compared to master.

I think the expectation was that setting the transfer to 1 would make it
closer to master, reducing some of the regressions. But in practice the
effect is the opposite.

- In "cached" runs, this eliminates the small improvements (light
green), but leaves the regressions behind.

- In "uncached" runs, this exacerbates the regressions, particularly for
low selectivities (small values of matches).

I don't have a good intuition on why this would be happening :-(

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

cached-transfer-reduced.pdfapplication/pdf; name=cached-transfer-reduced.pdfDownload
%PDF-1.4
% ����
3
0
obj
<<
/Type
/Catalog
/Names
<<
>>
/PageLabels
<<
/Nums
[
0
<<
/S
/D
/St
1
>>
]
>>
/Outlines
2
0
R
/Pages
1
0
R
>>
endobj
4
0
obj
<<
/Creator
(��Google Sheets)
/Title
(��Untitled spreadsheet)
>>
endobj
5
0
obj
<<
/Type
/Page
/Parent
1
0
R
/MediaBox
[
0
0
842
595
]
/Contents
6
0
R
/Resources
7
0
R
/Annots
9
0
R
/Group
<<
/S
/Transparency
/CS
/DeviceRGB
>>
>>
endobj
6
0
obj
<<
/Filter
/FlateDecode
/Length
8
0
R
>>
stream
x���]��J��{�������F�8��E���_x-�LT��O�x=��"7A@T�������������c����i���?����_�?���o��������������{�����q{�������8T�����������;��@�s����3�����?�������������m��{{����������a���"�[k��x�q�\9|>O�����������dr�$�~{<>���1�W9y(W2�_���>n��G��P]��|��6��:y(W2�������?��}L��k�Y����N��R�"��=��:E�.\��g��N��R�uhJ���v|�mA�����aG�`}L�i���b�ut���<;z8���)������hAy���hG�`}L�i���b�utJ��D;z8���)����8)��..���5��b�"��J�D������JK�v�p��S*-'����D����G�D;z8���c*M
D8��S*-%���A,��N����7>��1��y������b�*��J�D;F�.,�S*-%Ooc����J�����S�]��;�k�=��E�1���"����)����� \G�TZNt��A�|.��S*-%���A,XDSi�h ��Xp�Ri)��b�utJ��DwlX��Xp��S*-%���A,XDSi�h ��Xp�Ri)��b�utJ��Dw|�����RD�D;�hU,���4M4�\,��N���h�������J��~��Nk� �E�_����wD8V��T�&�1�u�`�Ri)����EtJ��Dw|���x��W]���U��>��4��'-�����JK�v|�����N�����;-����}�5��;-��E�1���"����)���������N������T��j_EtM�c�U��>��4�@�s��::��R�-�����J�����U�]�����v|���XDSi�h ��Xp�Ri)��/ZP��)�����A� �E�_����wD8V��T�&�1�u�`�Ri)����EtJ��Dw��Fu���j_EtM����X��>��4�@�s��::��R�=�����J���x����-�2J��D;��*��T�&�p.\G�TZJ��A��::��r�;���*W�*�k�OZP��c*M
D8��S*-%���Uq�Ri9�o�o��
B\���}5��#��X��>��4�������JK���p.,�S*-'���T�������h�-��E�1���"����)�����Uq�Ri9�7ZPW�*�k�7ZP��c*M
�hAU\G�TZJ��F��::��r�;��*nW�*�k�ZP��c*M
D8��S*-%���Uq�Ri9�OZP��}�5��'-��E�1���"����)���x�����N�����>�-��y?i_�k�7+�hA����4M4���p��$�":��R��mK7ZP���J��������x��W]�7����XDSi��x�-�����JK����hAU\G�TZNt�kT>��UD�D;z8���c*M
D8��S*-%���A,��N������T�}��Q*-%�����XDSi�h ��Xp�Ri)���T�utJ��Dw|������UD�D;�hAU,���4M4�\,��N���h�-�����J��~c���*q����q����U�1���v�p],XD�TZJtG�s�`�Ri9����*���UD�D;>iAU,���4M4�\,��N���h�'-�����J����������W]�����XDSi�h�N��::��R�wZP��)��������_�����vl��*��T�&�p.\G�TZJ�c�Uq�Ri9�_��*��}�5��/ZP��c*M
D8��S*-%��E��::��r��g>���
B\��E�j\���N�`}L�i�����w0�)�������*XD�TZN���T�������h|��T�"��J�D�'nhAU\G�TZJ4>tC��::��r�;X��Xp��W]��� ,���4M4�\,��N���hG��::��r�;���*���Ri)��'-��E�1���"����)���x�����N����7�n��
B\���}5��#��X��>��4�������JK���p.,�S*-'���T�������h�-��E�1���"����)�����Uq�Ri9�7ZPW�*�k�7ZP��c*M
D8��S*-%�q�Uq�Ri9�ZP��}�5��-��E�1�����*��S*-%���Uq�Ri9�OZP��}�5��'-��E�1���"����)���x�����N���h����6Te����������7�Q���c:M��F<|J���O	��n|��F{�r�3j��;?hW�|�Z^�"%���5saAy���`��^ym����z��V��k��Mr�/3��5��j�
����FZb3�[K��|�m����[����6�u6���sk��;7l^�W�����H�{��+�[K�FH����[��{��+�-8�6�������m��qn-���e7saA����`��^ym����{�����k��Mr��~��71���x�6�I�3BB�\YPn-�!]�\Xpn-��!�W.,8�6���������9,R��OZ�3�[K�FH����[��?i=������$��;����WKsX���wZ�3�[K�FH����[����2g^[pnm�{�����x�Z��"������[K�n�Ag^[pn-���k��-8�6����v������`�r~�B�����Z�}0BB�����Z�=�E�u����&��/�����}u/^�o�o�����\YPn-�>��!]�\Xpn-���u��[�����$��O���/�nX�����g'.,(��r���+�-8��s~���xm���I��ev�g'~^���H��o��=;qaA����������xm������n;���-8�6�����������
��{���raA����`��^ym����{������sk��w~�x�V���n�r����+W�[K�GH�+�[��wFH����Mr���=;��r��E�=��{v���rk)��	����sk9������[{
n�\��E�^�Q�����u�7^/�-��q���N�a�?�)��F��I0BB�\X���,V���+�-�(m]1/�����I}B~,�	�ra�8w���'�	�rQ�T���|���[���un��^��-��-����*�9�����r�z�����&}����+�-��-���,T������+T������+EKun����}�|/��un��O~�%�����r�O��u�S.,��-�!�W.,��m��	������r�O~�(qaAun��	�raAun��	�rQ�T����y�5�e���p�p����\����!�W�,��-��s�t�reAun�>�!]�\Xp�[�g�����,��-��s�t�reAun��#������:�����}�|+^~��R#$��k�s�}~�����raAun��	�raAun�>pFH���\�����UT������+T������+EKun�����@�Q�<���>FH���\�����e���raAun��	�raAun�>pFH���\��������s�}FH���s�}FH�����:���v�>P�����:���	������r��D�s�����>#$�����M��!�W^[p�[�p��������>#$������>#$��E�R�[����}���#���-�A0BB����:��`z�����r�z�����&}����+�-��-��C�^���:��`��^���:��`��^�(Z�s�}������W}����z�����r8#$������>p���W�,��m��#����s�}����+WT����9B�^���:������U�R�[����}�|/��;���>FH���\�����Q�qN���:��`��^���:�I8#$��k�s�}���W.,��-�!�W.,��-�!�W.����r�w>�N��<����A0BB����:������T������+T�6�g��^ym�un��;�o'.,��-�!�W.,��-�!�W.����r��o'�/��a�}���+�-��-����v�����r�z�����&}����+�-��-����v�����r�z�����r�z��h��-��������y7,��z�����>��|;qaAun��	�raAun�>pFH���\������������>#$������>#$��E�R�[��������W}����OQ>8����s�}����+WT����9B�^���:�It���W.,��-��3BB�\YP�[���z�����r8GH�+WEKun��O>�N|�<����A0BB����:���'�o'.,��-�!�W.,��m��	������r��|�����:��`��^���:��`��^�(Z�s�}��|;������	������r�w>�N\XP�[�0BB�\XP����z�����>�|�����:��`��^���:��`��^�(Z�s�}>�|;�~y�
��`��^ym�un��'�o'.,��-�!�W.,��m��	������r�O>�N\XP�[�0BB�\XP�[�0BB�\-���>pn�;��2�U_�|��)��t�ra�un��z�����r8GH�+WT�6����������>pFH��+�s�}�!]�\YP�[���z��h��-������]_�,��z�����>?�|;qaAun��	�raAun�>pFH���\������������>#$������>#$��E�R�[�����������>FH���\������v�����r�z�����&}����+�-��-�x��������>#$������>#$��E�R�[���������nXh#$��k�s�}>�|;qaAun��	�raAun�>pFH���\���|��v�����r�z�����r�z��h��-��������y7,��z�����>�|�����:��`��^���:�I8#$��k�s�}>�|;qaAun��	�raAun��	�rQ�T���������2�U_�|��)��t�ra�un��z�����r8GH�+WT�6����������>pFH��+�s�}�!]�\YP�[���z��h��-������o�����>FH���\������������>#$�����M��!�W^[p�[�����T������+T������+EKun���o'~\�w�B� !�W^[p�[�������s�}FH���s���3BB����:������T������+T������+EKun���o'�.��a�}���+�-��-����������>#$�����M��!�W^[p�[�������s�}FH���s�}FH�����:����o'>.��a�}���+�-��-�������s�}FH���s���3BB����:����o'.,��-�!�W.,��-�!�W.����r8��w�e���x�y��(�������>pFH��+�s�}�!]�\YP���:GH�+\����!�W�,��-��s�t�reAun��#������:���'�o'v}���>FH���\������������>#$�����M��!�W^[p�[�����T������+T������+EKun��;�o'~^�w�B� !�W^[p�[�������s�}FH���s���3BB����:������T������+T������+EKun�����������>FH���\�����|;qaAun��	�raAun�>pFH���\�����|;qaAun��	�raAun��	�rQ�T�������������	������r�_|�����:��`��^���:�I8#$��k�s�}~��v�����r�z�����r�z��h��-�A���N������������|p��W�,��-�A��z�����rt���z�����&}��O��W�,��-�A��z�����rt���z�����rt���z��h��-��I����W��a�}���+�-��-��I����s�}FH���s���3BB����:���'�og.,��-�!�W.,��-�!�W.����r�w:����:���`��^ym�un��;�og.,��-�!�W.,��m��	������r�w:��\XP�[�0BB�\XP�[�0BB�\-���>7:���_�w���A0BB����:���F����s�}FH���s���3BB����:���F����s�}FH���s�}FH�����:�����o'����F��CQ>8����s�}����+WT����9B�^���:�It���W.,��-��3BB�\YP�[���z�����r8GH�+WEKun���;������;,��z�����>{��+T������+T�6�g��^ym�un��2������>#$������>#$��E�R�[��F���]_��[h#$��k�s�}��|;saAun��	�raAun�>pFH���\������v�����r�z�����r�z��h��-��������ywXh#$��k�s�}>�|;saAun��	�raAun�>pFH���\���|��v�����r�z�����r�z��h��-��������ywXh#$��k�s�}>�|;saAun��	�raAun�>pFH���\���|��v�����r�z�����r�z��h��-�������@��/N:����!]�\Xp�[�g��^���:���������M��s�t�ra�un��z�����r8GH�+WT����9B�^�*Z�s�}~�yw���ywXh#$��k�s�}~�yw�����r�z�����&}����+�-��-�������s�}FH���s�}FH�����:������?.��a�}���+�-��-�x��������>#$�����M��!�W^[p�[�������s�}FH���s�}FH�����:������o�����>FH���\���|��v�����r�z�����&}����+�-��-����������>#$������>#$��E�R�[���������nXh#$��k�s�}>�|;qaAun��	�raAun�>pFH���\���|��v�����r�z�����r�z��h��-���������W}q�y��(�������>pFH��+�s�}�!]�\YP���:GH�+\����!�W�,��-��s�t�reAun��#������:������B�~y�
��`��^ym�un��2������>#$�����M��!�W^[p�[����raAun��	�raAun��	�rQ�T������vb�W}���	������r�w>�N\XP�[�0BB�\XP����z�����>�|�����:��`��^���:��`��^�(Z�s�}n|��x�<����A0BB����:��������s�}FH���s���3BB����:��������s�}FH���s�}FH�����:����o'n�����>FH���\������������>#$�����M��!�W^[p�[�����T������+T������+EKun���;�o+C_�����?E����W.,��-��3BB�\YP�[���z�����&}�9B�^���:���	�reAun��#���+�s�}�!]�\-���>?�|;������	������r��|�����:��`��^���:�I8#$��k�s�}~��v�����r�z�����r�z��h��-�x�������nXh#$��k�s�}��|;qaAun��	�raAun�>pFH���\������v�����r�z�����r�z��h��-����v������	������r��o'.,��-�!�W.,��m��	������r��o'.,��-�!�W.,��-�!�W.����r�_|���]�w�B� !�W^[p�[�����T������+T�6�g��^ym�un��/>�N\XP�[�0BB�\XP�[�0BB�\-���>p�|��}�/>����C�^���:���	�reAun��#���+�s��A��z�����r8#$������>p���W�,��-��s�t�rU�T������/������>FH���\����!C�\XP�[�0BB�\XP����z�����>{��+T������+T������+EKun���o'v}�n�}���+�-��-����������>#$�����M��!�W^[p�[�������s�}FH���s�}FH�����:�����������>FH���\���|��v�����r�z�����&}����+�-��-����������>#$������>#$��E�R�[��������W}q�y��(�������>pFH��+�s�}�!]�\YP���:GH�+\����!�W�,��-��s�t�reAun��#������:����o'�]�w�B� !�W^[p�[�����T������+T�6�g��^ym�un��>�N\XP�[�0BB�\XP�[�0BB�\-���>o|���qy�
��`��^ym�un���o'.,��-�!�W.,��m��	������r�7>�N\XP�[�0BB�\XP�[�0BB�\-���>|��x�<����A0BB����:������T������+T�6�g��^ym�un���o'.,��-�!�W.,��-�!�W.����r�O>�N|\�w�B� !�W^[p�[�������s�}FH���s���3BB����:������T������+T������+EKun��������������OQ>8����s�}����+WT����9B�^���:�It���W.,��-��3BB�\YP�[���z�����r8GH�+WEKun��O>�N|�<����A0BB����:���'�o'.,��-�!�W.,��m��	������r��|�����:��`��^���:��`��^�(Z�s�}�������nXh#$��k�s�}���W.,��-�!�W.,��m��	������r�=d���s�}FH���s�}FH�����:�������]_��[h#$��k�s�}n|�����:��`��^���:�I8#$��k�s�}n|�����:��`��^���:��`��^�(Z�s�}~��v�vy�
��`��^ym�un��/>�N\XP�[�0BB�\XP����z�����>��|;qaAun��	�raAun��	�rQ�T���������2�U_����S��z�����r8#$������>p���W�,��m��#����s�}����+WT����9B�^���:������U�R�[������/��a�}���+�-��-�������s�}FH���s���3BB����:���'�o'.,��-�!�W.,��-�!�W.����r�w>�N��<����A0BB����:������T������+T�6�g��^ym�un��;�o'.,��-�!�W.,��-�!�W.����r��o'�/��a�}���+�-��-����v�����r�z�����&}����+�-��-����v�����r�z�����r�z��h��-��������y7,��z�����>��|;qaAun��	�raAun�>pFH���\������������>#$������>#$��E�R�[����������������|pH�+\����!�W�,��-��s�t�reAun�>�!]�\Xp�[�g��^���:����������>p���W�����r�7>�N|�<����A0BB����:������T������+T�6�g��^ym�un���o'.,��-�!�W.,��-�!�W.����r��;���vy�
��`��^ym�un��2������>#$�����M��!�W^[p�[����raAun��	�raAun��	�rQ�T���|��vb�W}���	������r�O>�N\XP�[�0BB�\XP����z�����>�|�����:��`��^���:��`��^�(Z�s�}��y����r���8���S��������>�!]�\ZP�[�����]�\ZP�����	�������>�!]�\ZP�[�����]�\ZP�[�����]�\-���>?�|;����;,��z�����>?�|;saAun��	�raAun�>pFH���\������������>#$������>#$��E�R�[��F���W��a�}���+�-��-�x��������>#$�����M��!�W^[p�[��F����s�}FH���s�}FH�����:������3oW��a�}���+�-��-����������>#$�����M��!�W^[p�[��A����s�}FH���s�}FH�����:������3W��a�}���+�-��-����������>#$�����M��!�W^[p�[��I����s�}FH���s�}FH�����:�����o'���������|pH�+\����!�W�,��-��s�t�reAun�>�!]�\Xp�[�g��^���:����������>p���W�����r�t���vu���	������r�t�����:��`��^���:�I8#$��k�s�}~��v�����r�z�����r�z��h��-�x����������>FH���\������v�����r�z�����&}����+�-��-�x��������>#$������>#$��E�R�[�p�s(�W��a�}���+�-��-��C�^���:��`��^���:�I8#$��k�s�}���W.,��-�!�W.,��-�!�W.����r�_t����U_���A0BB����:����og.,��-�!�W.,��m��	������r�_t�����:��`��^���:��`��^�(Z�s�}����y�2�U_���{(��t�ra�un��z�����r8GH�+WT�6����������>pFH��+�s�}�!]�\YP�[���z��h��-������������>FH���\��,J��raAu���������+T�6�g��^ym�un��O>�N\XP���(#$���������FH�����:������?/��a�}���+�-��m��;��%.,��-�!�W.,��m��	������r�w>�N\XP���NJT���s�}FH�����:����������nXh#$��k�s���s�s������>7>�K\XP����z�����>7>�N\XP���NJT���s�}n|���(Z�s�}~��v�vy�
��`��^ym�un�>p~�9_�����r�z�����&}����+�-��-�������s���I�
�raAun��	�rQ�T�����y��me���x�yw�N��z�����&}�!�W�,��-��s�t�reAun�>�!]�\Xp�[�g��^���:�I��(��+�s�}�!]�\-���>?�|;������	������&}���s������>#$�����M��!�W^[p�[�����T�6���z�����r�z��h��-���������nXh#$��k�s������|��s�}FH���s���3BB����:������T�6���z�����r�z��h��-���s(�����>FH���\�6�gz�����r�z�����&}����+�-��-��C�^���:�I����+T������+EKun����o+C_��[h�#����s��Ag��^���:���������M��s�t�ra�un��z�����&}pR��W�,��-��s�t�rU�T�����������nXh#$��k�s�����|�m�����>#$�����M��!�W^[p�[�����T�6���z�����r�z��h��-�x�������nXh#$��k�s���������s�}FH���s���3BB����:������T�6���z�����r�z��h��-��������y7,��z����M�����������>#$�����M��!�W^[p�[�������s���I�
�raAun��	�rQ�T���|��v������	������&}�|��v�����r�z�����&}����+�-��-���������M���D�^���:��`��^�(Z�s�}����|[��/N>����!]�\Xp���:#$������>p���W�,��m��#����s�}����+WT�6����reAun��#������:����o'�]�w�B� !�W^[p����|�����:��`��^���:�I8#$��k�s�}~��v�����&}pR�B�\XP�[�0BB�\-���>o|���qy�
��`��^ym�un�>p��|;qaAun��	�raAun�>pFH���\������v�����&}pR�B�\XP�[�0BB�\-���>7>�N�]�w�B� !�W^[p�����o'.,��-�!�W.,��m��	������r��o'.,��m�'%*������>#$��E�R�[����}��.��a�}���+�-��m��2������>#$�����M��!�W^[p�[����raAun�>8)Q�W.,��-�!�W.����r8w>�V�����>GH�+\�6���	�reAun��#���+�s��A��z�����r8#$�����M���DA�\YP�[���z��h��-������������>FH���\�6��'�o'.,��-�!�W.,��m��	������r��|�����:�I����+T������+EKun��;�o'~^�w�B� !�W^[p����w>�N\XP�[�0BB�\XP����z�����>�|�����:�I����+T������+EKun�����������>FH���\�6�������s�}FH���s���3BB����:��������s���I�
�raAun��	�rQ�T�������������	������&}����������>#$�����M��!�W^[p�[�����T�6���z�����r�z��h��-��s����2�U_���;n�s�t�ra�un�>����+WT����9B�^���:�It���W.,��-��3BB�\YP���NJ������>p���W�����r��|���~y�
��`��^ym�un�>p~��v�����r�z�����&}����+�-��-�������s���I�
�raAun��	�rQ�T������v���y7,��z����M��y��������>#$�����M��!�W^[p�[�������s���I�
�raAun��	�rQ�T���|��v������	������&}�|��v�����r�z�����&}����+�-��-���������M���D�^���:��`��^�(Z�s�}�|�����W}q�yw�N��z�����&}�!�W�,��-��s�t�reAun�>�!]�\Xp�[�g��^���:�I��(��+�s�}�!]�\-���>?�|;�������A0BB����:�I8?�|;qaAun��	�raAun�>pFH���\�����������M���D�^���:��`��^�(Z�s�}��|;������	������&}����v�����r�z�����&}����+�-��-�x�������M���D�^���:��`��^y���{�m�����zm�{;�?�|=��u{�u��_������?Y��������������9x;��p<?q�?n��~����_��[�����.�������x%�v�y��y<��
������j/&.�x�r<�K����1E�����}���C�NP"���=��s������?�	����Z��tn0������q��xCu%�1���
m�n��������6�u��o%S�����m�c�yS~+�&6�������U�x���	�7!pW2������� �:E����W�������$�w%��
����VCy��9�p:�X~K�����������p7��+����=��>�������f']����Yn�+������oC�>k�S�j�Dr��3/�?���oP'��J�������������p��x[����+�p�?��6��?>�����o��lk��6�3W2�Vy��9�������~�R��9�}�[��}��H���h�S�.d�>�y��~��|p`x�'�[*�f�
o�����Lb��qv}���M��o� �-��g����]$��D�.�)�>+�]�0�����
�T$>*����[�����b����mp{=���j�m���T����j�m���M��'~�3������I<��t����\'w��w-�Z;/����)�w��o��)�v��X�.����1��0��m0��I��'z�e\���1�v<G�c�w�
�P!���S3����T��VF0�����u���i0���w
�f[�����TP;�7�k�����f�����o�r��m��D�'���������C���0�Q��	��A],��WO{bL���X,(��������5)�0���t��],(WwQ�Tn�9���pp�`Q�L���f9"���>����N�2f�?�w��O�G�Rn�W��t|�;��	�V���}����H�����n����N����y=9����	����W��UbN�%�h���<�m��^�����Ae���.�1�1,�e��X
������c6ztL����F��t���rkd���b�_`0$�����>b|��o�t��c-/���p�X�&�.\:�_����O�X���bAv�N+',}����=\,(�_�&���X��t'],8X�����0�b����X����p��1��I�#<\,����Ts/�<�R��z ���b��%&P�S��@,�U�����(���B ����D#:�M,Q����l��*�<��9����u����^1lb����?�H����u�N�6����q��[���x� \G����l�\�&����-�Xp�|@����G,��,w�p��`yq���?xa�a����XP�h/����>=��p�p],���`0�G����],���{�z/Gw�`�5��"��X��1������T���X�[��7�����xg�6�u��� :O�!�:���+��'_	&N, cqA,X\	f
>�u[��m��Jfo�QB�8c�B,����Q�������c�?��@�S���	��J[����5����	b�o.��c'��7��)-y��^x��'��1���_6X���>%.����n�G�x�}�.���C�?R����@�s� _�����p���L��g|:b���������oXv������=�-��O�w�h�����FX�;Y��!��*����x�����<�XP���uL<�����q����k<��������[	��o�������d�o��"������6�I�z����������o��2B��!Z<��o��o'�.���x�9`�
;~�bA5�@���]�-������������D�E���y��c�h�]�"���S`��!�-��'�L�a�N���n���:F�.���|%r���4�c8t��7��9��tu?�^����\,�K��d�]{�]���������n������3�v�����a��0���-d|Lq��o��
������������m�.&_�!c��X������0���l���8���'5������-V�7��v�m�����;8}�����a���m�lx9�1j`��������b��;0>�}�e���b���|�s&��
���bA��%*��#�#\��<,���KGx�X��������#<\,X��o������pm� _�wg�\���;@,(�������^����A,�c�`���o�a�������~������������>>a��6���>-���
�.��c�-1Do����
b�����}�C�p�D��[.>�[#�m���h��?d���]�#&����Q���\X�T�}� �.,/N�|n���Z�:�1��k�q��s/�8�9OzN�b�����c�/��p������b��s���F���],��ua�u��q�T�1��}��^W0��x�=jL���EgW��s[�c�O�XP��7�},��,�Xq~e�g,1lbuj��n,r�����!G�s����#�{�@�5i�_��$��G�C�Gw�p�6�������q7�czc����X��?���c�od������zp�
��TX!:�G�����|D�2tP�.�^��sc����'�;�W���V����@~�@L��������],��W<R��ci/b��Wu^��j/�j��@,�c�a�%I�;y�s�ry����O����X����^�(Gw���^���������� \>@
������p����a7�:����p�`[~�;C}�(�N�\,8�>&xL�S����~9�|�
Gd�'�Yt��\�������@xuDp��}������9��?�&\,��%�������.,���r{�x ��`��bA�����\lxt�#����xJM^�&�Gm���!\^b�����cz<S����\�]�9�c��c+b�u���>�c���F��m�������#<\,�[
chtG�>�A�n�����z��kk���	�XP�����x��Gkc|�S�����G.�X�_�����7����������-1�������XP,�����|������bA���������88�/��E��T1��������b�o�*oD;_b`�1�w����o%��$�������
L��������A�3����n�����>��1=��^�����X�����t;L9l3�N���Q�����������~�{���b.���c��������.��b�u;�f������b�__��,1f����������$�i
����6�D�����F���t�w��?���$q����|&���F�;Y�X��}1/,1l��t�.��"}����m�wYt����X�1Ca�66�����br�[�F+V�'�����}�[�%�]�w�CNr��%��t�'���b��}�u���[�r�>��R�_m���"�6����}1w��d8:�E;'�cg�v��lw�lcB,��Ebr�#�������l��e�2&��}�+��?�NL27�����5r�Gl������|����������������>���F�;y�XP,��|��%&6�������e����/�9�p���Wq��q��{�c�b��U-^V���^<X��T'.�:��)��������u�_��������,~�B������;F��OP��W�0�<:[�Qc� �����W{�W����c�-1��G=v�h�����S�i;�X�~��1����E89F�v���W��`xT ��b�u�����c8�N6������|��� �#8������o7��5����b�u������g���Gl\,��g����a�od�����������0Y��t��],�����N>Wc�:(t�N���09��s5������_^��;a�b�zRq�X�K'LMw���=���b�IM����s��<~����-��k�����b���&+Px�;y���@,��u�����`�^��^��M�[�xp��b��>�DX��_��6>��>^��X� ?��������&�g������.���z�X����xD�����N.d����l����<��s�\�ct� �=�?��eTU|x(G��M� �.�w�����vxLK���1z�X������;��k��*����xO�	
�O��0����pp����n��u&��EG�X����G�n���t:�G�'�U7�	K��`��������i�pj/rjc!,�>���V�s���������O�v��m,u��.}�����Q�6����&��]��&��G�v� _����������~2�,������0�c[�SpE���7XLiXn�,���A,������������l���2B�~��e���a��a�od��C��� ��vCLp<����-T���D�k?������Ao�����C����<F�.C�9�����gw��������b�/R��7���7��'��.��b<���-�],�M��}\;�]���cv���c���������%f�[v�������
bH������it��^�Z	&��a����A;3jN�/���-;���9=g9�zbL����>^��-�tn�1{��<���vv���|�F��8#\,(�������y75����C�K�����������r>��n��n��.d����6���	?�0�bA��z���\�������0~yuz�|�����a�bA������@��#\,���H�x�>s��O�0��a�Io~�>r��c������� }�����bAq���'��"�6&b��P�@�/��������9A���~�+�|���.d�o����=������X��K�h���9�=���V�X��[����0��<*��|�t��1I���c�������%o�����17��$��7��)����~�oL����Z���[��	��^�Y��{�e���b�/.Q��������c4p���]�/7�h�����q���9��rK7�"O��.d�/^�|�m�x���n��%�OX0��a�7��m� �Ocz�f[�>c!d��GLcx������	�XP�f���0�������	���,?9�wn���
�m�l���a�.���!��fb���]l=w�O���_���><^�an�|�X�
�^�����;��#�7�j],����4f��wrp� ^�P�3��0��t��(�s��w��b����Q,>2�bA��Z0p������������1m��k���b���~�0i`�s(��c��bA���������g����l�'��a�7�$��g� ��l������l/�lc!d��g41p����c'�vN�-��N0��qa�����m�_<��!���������c�r���*	�G���������������T��9�z/�v�wH` ���w��lB\tcz��o��o'�.����	��?o������~�)F��z~o����z����o\��0���h���_%4���#& ��'�L�3:=V��sC�@�*O��],�[J1����v�.��d0��-0��|��A�3�����[b�z4�����ez������E���1�]����0�b�����jd��w|~�����X�.�2�/Z":��G��	�n��1�zt�sg,Tc�\,�k�aK�%�f�Tw����������5�������rA�se�������=�?N�b�"��#������N�],�v�������m�cXt� ;~w��1��������r��Y������1���h�bA���]&������I5�bAv��-�a�q����bx�6�6�4��?�v��b�>A��Z<0���*���� d�������"�6�%�����G��3,���<�9A��w��qlwrlceB,�Lk�q���;cX:~~'�6����v�����j�������S�*�b���6&b��+}v���5���B,(�g���k���|���F����]��~>���o��������-�k����������d��!�C
v>�bC;(~������T����X��������?1��3��*����x��z�jn�"��������;�|�Fw�1~����o��A�
c��*���
�}�?�MR7����mL"�����^D�8�9�1����wxa��fl�n;�s��wu�xrJ1bc�b�/��4����~��_��M�����`�����q��T�1������^Xg�L��bA���yoV��X&������/,�F��x� ���i���g�c��B�F�����}��^7}Z�q��q'������X�:�G��W����y+�A],�����a��<������l��p�#�9�'U���/~-��
1��Q>��X�
�?���
�F7�1~�����2��6������8~~�|� ;^�"Ll7�<�%vL#��lx5l��k/�kc!��^�1���!�y,�;9�s�R6_~�",1`c�� ,�Xo�������E�c�_�D��n�{�>�b�|q�����a{���������������ym�M�XP�`}��AJ���3u�s�.<�����>I��`>�;y�X�-��2��������t� �]�es���c�1�XPrz��	LR�v��a�����d��5�Q����s���}�lW�����<�:�/���	����
Q86����#������}�
c��*�m���h}�3�
1ac���`X�Yb~��������X������n����N���o%��N�m������=��=��F�6���4&7���O�������#<v���A,�mE��v/��X^��&�-_�|����6��e�}���?���q������? ����zN�f����d����wy������X����x�������f������ ��XP������O��W�C���I`:�!f7��'�L����.����Y�#�����D����
c����1�XP�}{SXb���8^���������|���X�.
����9F���Uq�p����i�L^��v'�6��5s_��lXbn�z����2���c4�������j�����1fi���
t���Y����������f����W����ro������������-k������	��P����xX�:�������q;�,}���x�G�e}��;�x�<>��.��K��?<,�?��~� �]�}#���������s�r��5�/��F��1~s����7��o��a�X�??��O�
�{KVb��>7^��bx��a��#f`�s�5A,�������������	��`y�.�v�0���O
�n�^���c�t��E�k���X�����a���b��7���/�~�|���c�F;=p��~��>Q����=b�z#~������^]��}����:~~�Mpp���M]0�9C��/�?'��W�Q���}��a�p�bA6������0�s.;~~~� N���|��::�C~q�����?s�s���?�d�oOM?��n�c�&��5A������x1�<0,�>�_���?�+���=w��$ux��:�����"�6fbAI�W��a�������	����a��d��V�X��V�[8��	G��h�	�#�����*G�s��::F�G��~�"7����)_�
/��r��4��o���|�o��o�]�XP���;s|0������
h��U_}sP�ajb��],�~���p����A],�����������c4p� �]�LF�������'].��~���0����r�b�_���[��g���p� [^}�)&�b�a{z������W�>��^�����X���=�K����v�h��n�;��8�;9��4!��RcP�!��:�C�Mp0\L��~P�8"�����n"X�l�q�g�]�:xa���x��4+�o�Q��F����@,���<���y�w\N[,�o����X���|h���o���������yC�SlL�������}}��Nx�C�����K��4���1�X���~a<��;b�b)|R��X��z�Q��N
?G�XP����w��kta�b������������a��	J�~��0���mp� ��R��b2������	�XP*��1K���w�h����/=��;��	 d�o%,1�cCl��n��-bX����q�����|/1,c���8�F��j�l��D�}�N4��o���F����A,(��6�1���
1�cO��
?����_>)�9
�}#���w���kzbD�8V�7~������7%C�>�cA=��-��J"F�G���j�������(G����N���u�`u%���(O#\�|k0
�kq0+}����h{F����E��2��1i.��*c&�������t��wW��f",1�b
��G;3���[)1�b34\,��5bF���;�1<�X���G=z���Zt���u��-1�bA��=,��~�����F�[#�m�k.��@L���1�bC|#~����w�^�����V��7�������wy��#�
1��>u�.��x���+��4�� �.d�/^��!���,;����?���s�F*6�'�������n�����I���������n�#<\,���}.�1j���c8�}�lx��C�Rw���EqL#���x�F>d�^d��4B,(�S�������~�a��	���y~������
�T51��c=��F�6��Z1�6*G8�X��;������q������n�!;��h^��~Y21���5���;��\��G�1����������qz�x����;A1���o���������hLr������1<�X�-/��YG���Yd���r���f9,}���#<\,(y1�0�����J����a����{a�c�|�t���V���86����p��\m�m�Y1�}�q�pm��WM�V���H�Mv�����0f6����3�l��n�!���<�9��]�N7�`��u|��X�����	��n�#<\,�m����^1Vc��b�//F�[b��.{'���\��v#����6�=�}h����nS56�7�OoC,���[\���p�7r������Xf��a�b����Xp��x���%�|��
{P�.�K�z���
K�������<�����5;"��������(�Uk��XP.o|�
���(zo���^���W;X:�G;'�����^>bb����ON�y�<L���;T�p�6��=�,�Gx�Xp}A1/z��&�3��b�����7Xa���t����H��P	����6�'����]���[b����F�����O��S����'�a�bAv��l�c������������l��oH�#��XP������02��<�v�Xp�UNx��/Gw���7�W��)�O@��b�/�1}�11�by/
bA��/]�c�^d����Xp]�1�<:f���N��9�o$������X}N�d�$��*v�FQ�m�__���Gw�������cF��1�����C��!���������<��rkd��7
b�|y��f��"�!�L��;���_��bA��#�gA�.�c��F�;9t��hx�>����k�?��bA�������%��po����r������C8�1,�Xp�������0��<�0�X��f�G�W�c��bA-��W����lt�:�GV�	���|�'�?���q�G�w��%&l�ic�\,�����/��8�9�1g.��"1W�S7���<��Q,��������X�.��1i����A�������2flZcV],�]����S3��;9��������F�[#�m�,.����u����h!Fg�[o����X�N_���\��wrp� ��j���v����:F�.d��/[��	C�������r}_� ����i�|������$C��0R��=�`\,(v����n����I������3����#\,(
���J�3��
�0h�����n����B����:~?~�E~m� ����_~�$,1oc�������������k�����1O��/�a���m�?=��r�1<�h��b��2��;�t�u����8���0�c=�S|�R����a�nn���B,��W���i��_��I��������>��@.����'�|���.d�/����gX�a������M��Nx����#��XP������@�s� '��-��C0tt����7u|���xw �z��fd���:�C;'����+�''��@8v���I=gI�v-K�t�v���,�P��G�s���=��r���3����A,�S'�����C�p��M���_9�Xn�,���A,�[e��{�
�yG�Yo����X��}q���/,1�t������c����X~��b����y/�"O�������{�/Gw�`��}�$6w��������?��.n�AO�G��*��r]Xb����fA,��U�|����>z�|�g����=":����xR�v��:z<���!�xr:��C,�m�����F^��0���J������0x�)�_���.�����}��w��bAq��M�a�GZ<}���--�G&<���b�y�A��b������ 
��JWx�1�w�`����Vx4��'�IN���x�v'<��S�����'���jt�:F�.�]���/�R�{�����?���������^����#��XP���V�="z{Q�6������_'�%Rl
;y�3cuA'��'����],���C���$��p�����������C�����9!	u������]�	�t�e���	��`f��,�<Q��T�{-�&oz
�>��Y�U�"�������I���
k�g�0����a��GB�[X����Yb�M�N$$�7��UX�<�&���*������<�a6��^��D������0���JLo`���!q�0�|�<Ls��$�����f�o�����y�+'1�&�{�XU�^H<�&�������������m ����0�� R���,�M^��sLb��X�.���
����������	����B��\"�"���{�M^�N�q�c��G�����|9N�e�$'!�����5�����q���&_�5N������Va�L$;��g��}l��v�Hf�}���%1]����f��x��8���@����I��7y;`���l�xW�p�M^w�����s*S��G���5q��$bJE����	���D��A������f�/{3'�U�cH �lR�S�[���6"FH�6�3��E"1�2�����"gR��.��w!�&gFM>�y4��e�7!�6�o��i�b�eP�/�M��28�3oCQR�(��
`�Q�0�|���Z$'^���D�l��@���������e��������H�Z���f�
||�
3���O�+3�������d��������o�}����dw���`�"�u��Cq�M*q���D����Z�q�M�t!��8:�Td����0����X 1�"�}��l�t�����*}����"/��'9�F2���m ���9������:�M^
N�8z�����-�M�m&�@b�dZ��Q�@���97�3'��#�va;u�T#19S'#dF������b�q�0�|�H����Y$���)�_��o_����W�k���+�&'���T\�W�9�1D�I�0y�M�m�[�+�Dn� 7a���"gg<1�!e���l�#�f���p������0���_��W�0�!�}�t���4�V�0�!G}���l���y@$�3Q����l���p���cJaZ���a69���M��GXuV���a6y9�o�1�0'm��m �[��'1�0!-����d����I���,������0���[GG,*&}��lr��s����L�����';n���+G_�}�o�0��q�O��?��Y �(�9����\~�����5�`>��^L`n�07en���}��P�H����]�������������������Sh�+J�z����6 ���Y��}w�]h��
����Q�2�}�]���E�o���oQ	�2�� 1�09Hs���fhpj���.����p�~;�9;�K ����� �
���� �!��y�f]��0�~��):d�p��9>g�� $�n��u�&"i�5�S ����(=��J��*�U�M�]�����[�����"���������;�����7����~���S��������u���S��+���z��=��P+��c��B����P~���,`��\��Ql��m�m���Q��v�E���n	���:_~j�G����^R����B�G��w����C����9�E9�?��
�Bg�O.�=i��/�]�[U��b���*��~��>�p� gBF�M�
���m��G���U�,�����GS�i7�����C�M�\���EGt��{��=�����Y�qK�$���{4��@pjf�Z��:������p�
\����n9��FwW�����9O2��������<=o�y)%t���w������A�4�lT�~�����km�>��IPL��������Z�}�0.�8��$��W�0�][c�� [?q��'��"!���o����c����	�zb�����}��
'N�5��������P+���R�{����Q��~�
�||���]�Uz�~����i��r~fv�R�P+t�)��[�V�T�wm}<^��I,�lF����;����~'�����_�/Cm���������+��~����t`9�3�.���O���������*w�sK������z����|e=4~�~������cv�9������V�S%�3�1�����6�}b��LhL��������Z�O_5��*�rP�����~�TL��b"��i��Cm#��g�93�Z��B���?�P�j*&��r"��P���oC����PL��B����w����S;f��Y�7�wm��'�8-��iT����6���3?��A���*�����HO�,�p`��W��Z��%&er��&h��R����wO��Y|e(�SK������.�qp���iO�~��Y~��V��rr�w�����)��
��+#���#�����B�wO��%,�|B�U��B�w����0����n@D
MH�]+�q�������b��Z�5+@Q90��k������A@Y8 �u(�����&�uA0Y7 �����UCYZ��B��W��e���!�4!uj��~91��`�j`�����2J���]�Uz�~�
}��fYT�
L��Rjj�><����uQl�k�~���}R7����r��P�:�,-:����������_9�Y50���������5AP9{#��U):�����w���i�[�wC9=/?2�����^����w
��:-'h`�U��b�����+��������I9����TF`~�7CxQ��wm����	TL������Q��9:������:����[��Ng����$�D���~�����s����
ML�]�pz�%�����#:�NH�F�/��-������Y\�~��]<hk����]�U:~�oq����\�4�)���6�SE���9�3����k��O��r*g����#�����A-:�B�~�s���7gsfq9���~������PC'E�?���Jf��U�Z�������uw�R?��H����`?4~�~��|V�i�c���*uS
���:�0�����b�����[����t�h����T?q�*'s����W�]_6u�'��r2GN

��_�VN������-�����bs�i�$�N�H,�U�Ui��;������z���*����������	�S*s�����Z���%�.��2d�wm�}����P9�2�V�������]�F����e��lyps6eJ��J��W���eP9���	������kU�*g�~��n���?2�~��_���u�o��.�p^t[�)~�}|X�cp����&'����0�"m���9�($���{�,{b1_3������tPN���_M��~{b9#�36"�WO,���;�2�������:�4 ��V��6/g��r�d0��:�Q��r�d4��C�k�N���E�U���;��vs"'J������C��C9�[��-2D�wmM�N����\N��r��w}���X���oQ������gL"���UN��_��8�?2an�x������:�/�'������/7��V��b+g��r�D�
MN�]+����0���!�����6��739�SB^h@�w�����9�3B�W;~�SX��E���dbC�k�>�
k���92R49�w������$TD\P��B�k���e��B�t)���\:9���2���������>Kl][�b�������*�jF����;�����@9�8$���9������������np9!3O.��)F�~b� �_���UN����s�u-���HN��t:=�����G���,P���9�		�k�>��A�`IjhR��Z�����L�p���~��}��s"*'J����1�����=��v1�I@�v1���5���A�I2�4)uj��?9�)0��"���������~o��D�Q���w����PN�L��Bjj����Yor>d�\���7�sorr'?������C�
����(������v��+'0�G�F9������I9M!E�U:����^����D��t�����k�'�4��@�V�nJ	�k�N>4E*�GD�C'���6��'�s��#��N��w}I�{h*�e	=4!�wm��Gf�L��|����~��|���n��A���4��}�>�iN��V=���	��wm�|{@s>�:!u�w�7g��rFf~���������0�uWj����Q��"��4����F�������E�U.�]���s���7seUL��w����A-:�B�~�����/&7�pFM9�����(�.&s�rA
�G�	O��~U���*b�S�k���wN8��V���)�������^��*�?����mU���]+�i?�@Y N�&$�������P��E!�w}���/�$������@�q2���?9��?�����:��wmm}z�@`9U3�j��z���r��
j��O�A��uG�d��7���c�!��6����/+%����24�w}��o
����uS@mC=��f���AV�#��o�g�@p�ef�z��;�z�~�$�E
40��V��#U��t�+'�~��}��79�9���N��G�|�����U���]�]+�����r������|���x�]�)s_?K��*tS���0mq�
('d�������@��Y/���r�����\~��m�yJ:�����?���B'��&�32��W���_5��m@���~�
}~������][?<�U��fI���
�B����X�L�������3�quW\������r��fRY02oJ�m�����o��e���,����gGU���������]<X������]���3�����9�]�����|8�L��^g3��;�	\�W9����[���?����c�������7��J�=��K�1���
��k�N?QF.�ep��	�k�>.c�%6&fbC�k�>lc��2������T[O[��b��]+�����\N�qjp�w���9��)P����Z�����~�3%��A����3��XL��BS�P���]On]�[e�����^��@`������M�$Hn��
��_r9�s��p+��~��]����@@��z���3�V�r�w�}�P�s6<>k��%3��������w
�y��y;����M!�wm��g�0A��	9��
:����b~f�-
9��
��06f_@1;3�~~��������a�:����������$
jhR��z�����%���
MJ�]�l+����5Ad��I��Hu�Y62Y0�J�����L}?���r��(�����������IvSJm#�����xr���*�
��_�2���P`�����#=��A�&���
MN�]����~��f���+'~�U@�B`�]��:�����\�W9y���4����M��_s������������������J���k�>~D�e@`Y& e�&&��{��K��b�f��($��
z�tR��A�|�d���
�k�>�|N����X[�k�v���3Ps��\
���z����`���r�d������M��h�Ze�������M��7�i7��6��Z��{9y1m�-�~�vVgSpr��Vhp�wmcx�s����*}L�����y+���D���Y���1�D�U��I�]���������L��y��x��~���/�V�&��*��'��L��*tS��;�y_�{JT�8�!������Z��t��)
�H���&&���8�E�%'#�G(��������������A����>���*��g�y�o�1J����u���s�X�j~��&�o��]�p��uD
��o����U[���������"��=�&W��~�*�&��C}s������QD�!O���M[�������������>:h����]����� �G����������}��X��\�P���f7f�8/�$��J�:�wm��{���f]����w}��>
jEr������Y�a�/s�P�\��!
�����^���W����~���|����$����e S�~�S�������i2�������������
A@��������w@m��h��	�:@�~������R���"�	��������R��-V���]k���W�u�����~����`�b�X1L��������c�n�k���m���_�9�os�P]�Z�Rw����u����8`���������Z��_�H*np��&%��;�]8���
��>r|�]k+����LXf.�����aJ&����'�U�����Q��3���2
�]+�yg�	�W/jp�wm���:�O@P

���\�Im�6����hiOm:�X�
MJ[���pb,��i�~��z�A%�2\h���������P�.+�!�w��z|�=c	�uWn�[,��_�'SI@��g������f-Kn]�[u�6��v���G��`F����G�]���3��L(\����k�><���#��'XV�e�������}>�pPh@�w=1gw�.�HP�W�

����&�I��PhBt����63�Z��F�w=qR��L��`Z�X��������$�P�z,V]��z���;�� �L
��&foC}5��E��Mk���GbD����[|�~��L�	�Vn
��u��3���9%�I{��	��Kl�����Pq���HQJ�]�{w�+� �
p�qx�]O�LF�2�`[����������#C�������"��~��
��@�l�>���{+���uF
��
��$L�`
��N�]_����d��}��d���zpQ��0d����'�w=}�X��1���]_�j��L}���?���YP��oF�| ���*�/�]_���|��YV�m����~�
��g��Z���5>�uQj�Q��7��7���1�>$��P�
�E�q�]��AV�"@�EB�����Fd9�����e�����=,����dH����J=��� E���Qw���mky�h�V����_�1�\�UY��0�]��$�jP��b���oN!����b�X�E���6�z�X����
����p�-bE��H���������Q�]�oq��H?^��k��R�U��R�����$����t��K��N��w���t~��T����_�r�]_S�t�}��9�(��=41�w}�}���e�����6��{��C,�D��U(2h�w�����yY�c?������x�4�_���	��Q'�u9H�6-4�~��M��S2(p��(��#=��l6��w��B�(\l^�:9m����6�UMh�����c��w����������!6��0������5u������+���������'�	�Y7����6l��|G7���B����c�Y�q������!�eH���C4����,C����K��y������d$	 #v(v���~��; J`�;�d�����3�����������e4	 �w�M�N���3��L@+1�����~�q3���Ue��~�w��a-!�������=��2�0t�6�~�����]���}�U����#���
���9�gD���Of&P�U��R�w����B,�
��C~�������.�$w+������ec�[#�"���]w��*o�
�WO)C
���R�]_���5�&6�v��_�]��2����
EF����{�A�W�;j�w}�]`Ho�B�����nC
�1�u(
h�Pp�RI"�GM.	�]����6	��+�i������M��@��:.�qH�]�^��s^U��
71���wm�Q�n_���W���B(�
�5����b#���]�UG ����������Bj�n��������3�[�V������x6�����
�E�+��o.���q%�}�qH�]���2��q;,��W�]���SF�����&#�~���c4	 �7A�C�w=;�e4	 �w?���N����z�a��(���������E�\�l�U����>y�BjM[�������2 ��Um���~��
��I�e�
,41{�W7�LI�GR���/�^�s�������^O?�5����M9����w�;q���	 �y����lf����a���'�]�b������2�H�"B��]_6����J�e��~O��
���Y�I0Cv�_�]���LI�e��&P��D��ACo7���uG
���6�i	�]

�����tY��$��*���z�/�,�������m_2b��[�r�w���Qb���,�����:k�HuWR�3�����L�m���:~��'r����*�w)���W�u��+ D0Y`�b���km��E�&l��X��~�/�b���2t`�d�qJ�����Ku���2|`�������Ts�\f�fH7���ze�#�/����YR�������bEZ�"�~�o���?�Z����w�������r�X9G���I���e4.49{j�b�~�������r���5>����v���QR u[��)~�������4���<d�]�bb�*8����Q���w�����(�E44 ��V���a�X&l�4={��V���YY����K)2R�w���Y��){)E���_bY����50�������6+}Pwm,4(���3{��f���^����}��\:�M!�}��������bGP� n�����Asj��q0�$h0�w��w�r�X��	7����h�a}?���b���]+�����A����m=���~s^���}�E�#���o��3��p`3@��%40����/�;�K?�viP��������� ���hrK�����2����	����~s_��P�h
M�N������-��������(��EC��M��`Z�U�*�����aV�e%Ph@�w���������+��������w�[�����n�R7������_��bX��B~������c��bC~��������I�*������������^�=��������P����"#�~���;�B Jz����l��8���5��6�,���&T�D��&�]O�3����f��o�P��7���&��~��g	�6����&�-C}�&�DT�8$������@lOM@����0X]���(���~�������'����:�w=����%�x�un�����6�i�����E�U�e��m���D�"jM@���i����\f�858���� ��@�:I����dH�@h�w}�&D !���!�w���c*=������9�_�-28�U��*N�]O
��+�����]_���G�n���:�R����������pG?�#�v@�U��B������m�j*�z,g:)���Q�~��E;�����^�r�]_����V���������u�����j �z��7=��w=
���f]��"#~��@��d]���"�~����(f���^j�<~�]�7�E<��604�w=������y���}�������Q`�k~����tP���r��������%������|'�� K��N@���� a58V�\s������O��"�yp�����1��������l��m���w}=�^�����(��(m��m��O�������k����������?xY��Bih?��G#w����}�X�cWa������MV��`��-�&�~��=��}�X�s!_z~�wMZ�6	{@��C�,�?�z�,���}�]__q�N�k5m��~�s7�A� W��bU/��_�6��@����>#}�uu7�����Cw��{|��~��?���_�����*uS
�������YP�d�d����6��;�*�����������7w��(�!�����w�id�	 4���k_&��	&��������u0J�`������r�\|��A%�_��������y<���]�	����z��7��8�
.���m��a�!"�\��q���a�\������z�; �����M_�C}9JG��e�(c��k�=��&y#o��@��b����C~�����7��m����~��]|�:�Z�V����
��i�?cD`3����p�����2�����+�����z���88���A���w}����h8F��A�����l�E��<��/�I���=v\6�E���u�E���\�?����`YX��������������D�]O��5=�Z���w}��x����@@��{��[��k�L�I_�X����������R��e��V�n����%�����.vB�~��}��@�@q���EQH�]w�����x�q|�][#���!����}���~��V^�KL0S�I�]�]��(38��;#E���o����E�C��z����M�����M����<d��z�M�� �}�d�����M��`���z;d[�Z/��d`yT��\����k�O>����(����z��wm�}z���y`�ur�N���b�K}�{��>�.J�z*�ur;w�].d]8��X�_�
����������U{,SB���W�,����{��_�]_]5��C�"�M���_^6Y���<����w=�=?rD.�z��k{W�����,r�+���m��~��X�'W��be����3�zp�2+V����m?��.�@p����P�-�Y�$l\�?t=>K��������u[��)~�J}~���&�X�MN�]_sG/�p���[ ��R��Z��^6�c���"��]+u�jb
�������Z�O���j&�?������^�&�Y�EF����p���~��~�S��V����]+���x��2X`��[����6����`��2�\9���n����3N[#�B����6��{��� ��X�~����}P���E�
���I���`t
,��(�k�I<�������+��������s�����f}����wm��\�����G���Y'�a'�d���>��_�2`a�b�a���wb&��	+Vl������%�}��x���������A��)�LW�"i2��w���LN�d����t.��_5t-�P�*n]hCW�+��'o���-�B�\2��������I�U���n�]�9��i`jE]������fHT�b7��_�r���ThR�6�vSzX����H���X9�~|y�~���]c�mU���]��e��2�a�#4!�w}���3	����-��+E1�w�������@E~54(������Y,�j��iz�wm�,�.C�o��T�]�q��������"��~���b�
�W�-j�w=�B�.wm!4���oa����Z�<�}��������xD�(����������-yr��MN[�z��1\Xu�@�����\@�.�-iO��z��LTd�����w=����a�������F�]�9�R�m����~���l���X�N����W��Wu�BCT`�����������e�:���b)�]�^&����-�]F-����q��@���&#�~�7��@0?q�H��~�/OWF��2�`��,��Y_����Vdx�0�U������a;�yT-1�����~���,�j�Y�����^fh	.CMp����P_�����db�~$�����e9>�k��_��Pp[�) ��{����Wg@e�����r�]��y�����qG�(�������gN�P�C���<~�]O�W��8�����1���4><	����f���S��
��A3/�~[�X�}�"~�#�(�1��[0����z��{�8&���(���=.[�4\�(�� �����&cD3����%��g��L��UyU�
�]O�f2E�)��,���w}}^p&����������u�8`�Xud���5t�-��{��6��f�~��W���u+��Vt|6��v��w�����=�E�g�]�_��0�E,��& ��'���p���]F)�����Q"����i2^�w=}�g� ��P�C�w��  6q������� C`YX������9��\�
�b)��(o����da��<d�]_������v/?}��������u�f�����V�mzx�]w8]�?���������
����t����V�c�@�*�$�0(J	�k�><�"T���~���n�(�Fb)T����hz^�w=F7;�e����"��~���s�O+|l\@������K|�������dw��K|���H����1��<����&#�~��F�W��������]���������rM���wzY�8��\�������Z�'����N�_;��~RY�s�_)���:��r����C~�����.|��Am����~�W�����Y��Z�V���������,�������W�].��}����Lh�w=w�da8��U�e���z���u}�X�c�������}�_�!�u?��?�w={��>�,����(@gi����k�����X�H���[��V����U�����0�w�@-����6�A���:��#�m�_��3U�I!_.�z;>qL���
��A����4B��*vS��
;�=��XxMN�]_6w��	���q��(%�����	\$pC�����^p�1������g~��}|h�Y��f�vC��L�k���Q��L��8P��Vf���Q��B`��W�BjP�w-�v���X���Ubwm,40����~m#�W~�'#O@��
Q�����'�]��l�(���C��w'��'��\�7J[���f0&���,������w�@��R��F�]wT�� �:�Yg�����;~3S�uQn����C��C�?��\���/z���[.���������������K?�v1X�����F�5�� ��
�/h2��w}�K�
��|��qx�]���fOnY�[d�������@+���{��~�4p��+V�����i�@h�V��������:8�M���znpfh?�6n������9�5���`H��
�~�P��N$��2!`�>49�w}n��_9<�C�\h>�����q�Ae��M����k�>�d����fy�������B����P�����@��A��I�k�.�����tw���WG?5 ���E��`b�
��M�~����?�������w@Y�s��(��Cm�\���J-�o`�G�M��]�i=������wP��*4)m��&��a�NZu0A��wM�&�L"�N������z��"�9�C��zvN�L`�Xul���n�?�9#����YW���r*mOg��.J�:6��n�n(���}�EG"��_�'�����k�������?��� �����W�]�kn���2v`��������d��?��N�������z�p
n,zH-��G�����Z�X����������%W�b�$����\�6�r�X9I�������2����
����Z��-�-��n�]f�\��P~�����1��H��N��w}C=�3Gj�\H=tR��k���P�=49�wm���#o�|hhB����_B�(�I��A���k��l�qP�@C~�=�gm� F��jt����k�����hA���
MF�]{_>d?dP
@
�����Q�>��"T�PC�~�������'��I
MH�]����E&4tB�w�z�9@���"&�������0���'����:r���/�����5��f=~�w��f��<@D�a�������P����j�����~;m��.3B�����As���zL�0C��k���mq���"�����.~x��?���&&��G�����b��	��Z��b�bYQE�F�w�v�2c�k�i��~����!����i��~���	�"�:)�g��{y��>w(~��Cw;��;�����k <u�n�b7����������"��$������5u��-��lhb���;�F��"���]_������#�L%�5izj�w����9:f�l����V�\H!��{&EF��
�P�3��� 5(��V���A�"���Xh`�w���of	nl��MN��Z�1"�E�>
mr����mc������=�������~F����
�]����h���2$qWC�~��w���2�)�{����b�~�9��+������LcO/������u1�����Y3@q�C�l�n����b6
 ��9���6`�D��X���!�wm���GN��J�_������P���B�6<�����m�&��~�6hj_���2%q�C:�~�S��9<����]�E[�j��QE��w}u��AN���
j�]���2��%s���~��F-��Z1���w���c�XF��B����O��*���l��z=�3L����f'P�U��R�w���uO>��o{f(�QB~�������K��?������+�����7E1�w}����g%
�����������B.����Y�]+w.�3v���a�]+���e(v���&�]�v���+�_�������2�)���6�]tn��TF3��|�R�>��M��j���B�\4��6����WP�����~�oFs�UG4��~f�jUGcw��;�wm���%3v���I����%v�������+��������������f}����w����{Jd�{���$W��[r�uQj�!�������b?�WP����������9.����������Z��?����C������{�0rf��2�ak�����uD����2�q�Iz�~����g��6�a��N��Uk
�������(��uC��W�a���Z5]��������!���t�z�~��}�i��g�j=]��������:��M����z���$Z]??��V�u��T��u�y�����h�n�b7������]b����f�ct�vSh>���[9L�)����M�����>7�>����^h~�����$��
{jM�%������c0�6���Y�]K;�_�g",���"�]63���"���~���~�zV���wq���Vh@�w���W������������Bg�cJl�(��eC�k�IB�GSYP������~�/�`Xf(�1i��w}{O�J�LO�^��������uW`�Q�k��N 5��f}	�k�U��sg�!`����#�Y��s�>������m�E
��/����a)����������r�����������f
.����*�]�^������m&�`�]�^�����M'm������|�YV��E�E��]�=�[���X�Z������v6<�l�
�~�o/�!p��-V����m73�q)����m��G���1k��Hp*�r:t;>QM���?^���Vn
��u���9P���������������7V�4���t�2��`h�w�{�2Cf�`2#a[������f����1	�ZEF,�����*SPP����Ud���Z�O��3��W5(��V��wVm*C��6~���Ah:��P�$�1��}�g��{��!��Ql���~��N+CPP����C~��N+#�U�4 ��6�cR�:������=
�k�>��e�
,����k�3=l�0��Zw�V��������Ld�m����~����Ld��E�U�m�>n�>��7Y@�����������b��l��X��~�/f��b�dV���.c�~��l��r,�������D7`����d4���\�t��:�<&5�1I��������e`�.��s��B��u�#�,J-r�����.�z�g�s���~���oa~u�Z![�����l��(��H�&`oCm����b��	N�[;������5�����C�n�b7����%v�|E���2.a����9��
;�e����������z���\(r��&$��{�}pc(
 C6��������9�<t�2/a[��������I�up��e`��R��ko%���% �z�A���wm-����]�����~y��X�#n���}�
���E�@�G�M��]{[��L���2q/Gl�];�a������)4)�w���2�����H���w=��~E��'p�E�E�������'q�;��]qU�i�]_�����c�	j�>m���w}C������(��0m�����F�(�y'��C�HZt����h����
`&�X�M@�]���3����T��R�]_�rm*�P�(cv����]�*>2�����F�������m��`P�iKW���g"3M�(-V���z��������U�]���?jZ�N���t	��&��<������d�%�\��H�����]���u�'l�H��*vS��
{;�DT&l��&%�������m��#T���iS�~����,�p�qx�]�q�_'�Q�CMO%�����>�e���P�K���;^�f�	,�����]+v��[�7���F
��
�����Me�u����Z��Wd�	(�7i�B�>�}X�g��}���Z���R�"X����M����n�p������	�]���)�1�����4����6����'��@��Q
��������0��[w�V�����N���`�	l�Nn���������GMj]�Zu�6�������:�N@���I������`z��Ff��gh�w=��@&#l	�2v�w��$��Xf#l	5C���<�W[8�_�#n�H�����})P`��G��]������TR���"����v�V��)V?���w}9����K�V��*l�]���/,0x�9)�<����[�����S~$8}�Is���f9����v#��N��v[�)~��}z�3�P`���a�������72
�[�i�b����N=��@�%C��i �P���1��|����3
�LK�*2j�w�������2,a_������RG�#�PP�[��+~�J_����-�?�K�k�P6:�K@m�6�����+��M��Ot0��Z������*��C��w�TT���h������O��%�el�^�b�w}9�������+������]:���?yW�P�ur�N������gBx��~'$c	�uQl�a�������2�I`\��������%�!�7�K�#C�����3Z�_�)�K3�A���w}y<t�hLFl�4H�������K�2�p�E��~�o��m+s�Y�������������(��EC�kE}a��@����jL�]���e@W��bE&��'/����8h~oC�f�4R$���_9t9>�N��������F@�V�nJ��uG��	�	C
v:B���wm�|@�B��-�;,E9�w����@0T�
���k��1�G M��������ewf9��Q��Sd���Z���X �!;:EF����]��?0���!����F
����������1�2d�w����C�m�6����l��%���2�p�C���
:����V=������U[�C���}�P�]��e	&C
�8�������9�� ��]�Un�������5_���6��f=�k�>��i�NfH�6��f����<��:R�Q���������)���fF�5\hp�w}=�e�s	vUv���~wW��XF��4>��>�D��X ��������~y
3w���;��Ugu���gq3w[��N�w}3r�"E�*�XK���w�����j�r�~�o�$�NpP�M����!����HX)��8�~|>�~��������*pS��
��<9�`�FBh2��;����83k���70�r��Z���a��(������B�>��$�(�;iz�wm���b�����[(EF+��������X���P��Vl|���J~*��#�_���A���P��
������"���6�]kc�>o@(37Q�B�>�
}
+�M����&�����v)t�M�������z^�w}��Q3|�����6�]+�a?��#�L'��P���r����W�3}�Zw�V;����#v���&�f=����w���i���&�����������3(�G0L����}~�6��?k��q@3��J-4 ��~wR3��I;(��`�]��u�L"�eR�&J��D����,�H�T��!�K�kGOl1��9��L�]_���9�(�"�\ ��~U�d	����Z�]O�?���-V���z�x�f�c�k���~�g�h&�Fp�A�����6�W�a�b���p�W\t��q��O�����!���}���mU��������7�b����j��~�7�}&����a�z��~�=u�)4#xh��z~�98�"�B���w=�c�	Q�~M�����8�H�P��@
MJ�]u�@�z�A~�}z�f��""����6���P���(��&%���:��?����&%��G��x%�>���& ����O�������b��r�w=�NT�6��f~����,�I��R��f�����B���$�B����H�HQ������h2��'o�,��C�\h~�v��70�E�lhb���z�<<k.�pC�~�7'��;(������K��E�P��k�R�Z
~�wMC-M�F�
'�]O�4��	���X������uzQ}:{i?y����y0�����?tW���;��:����Y_�����k�������aT��X�MJ�]_Q��,�Xw2n���uG��uY]����8<��oq�j�8V���hz&�w=��>��������E,��/������,�o�G:��V��;!�~�j�~�F�{�>����]+�a52�e��%��B�>�vmN~��X��X���p�����e��ez�(�wm�x�U�S ��?���D����]7�{P����g~�F����X����z�Y��������7�cf.��j�����w�,�� �E�E���������?�bY�]���O��1`7`�!K�����E=��?���h2|�w��v�e`�</�K�k����)f(�����N����{�(�"�\�������jUc���~�W������c���be%��o��y��������,�M�]�
cIp����P_����=S��#q����Co����w������!Y������A���Q��|p��O<g�,ni\./�	�k�>���9X�`C��{W�g�����C�][3�o��������C�k�����@0��Z_d$��Z�?
�0��^����Z��o�0��kc�����r��D�x��\hr�>�3��OIm�6�l�wm7��7��b�n� ������!�[uHA�k�>�B_u<1q�B{~�����=�n81����{������}6��uWh�1��W]f��6��f=��Kj�HN�<o�f2�����f��|�I��@f#�`,:Z�w=
d�9���b��]�N�����Lv��������e�	*�vL��]��'d�	(s�2�g�w�����'�F�����ZJ��O?��,jY�Z�:���e=x��S�r���M��-b��o�u�s���~��5��;!�2����3��]z��-��w{-75�7�v��u�o�4���p��V�n
���A��|"�Q	��I	���z����l��(z�������b_f p���

���o�1�!	�)M�&�����o���)EF,����q}��<�"��6�����0����5��6`w��x��m��!�w}96/����2�`��[����V��G���R�G�M��]u2������������)7>V7��~{R�m�����N�]_O!��?m��������r��,�uWn�!����]�4�\�f���w�w}s7h��9������+��+�G*CLr�������4�!�f��%`h�w}�������� t�w}}�2����=M��_^�[��X���K�]�4m-�4f��h�V����g���(��E�E.�]��&2��j�b�/�����S7�,�ji[�������s�q���X
L���7mn���,\hr�6��c6���G�T�H���F2���_��7�9<��V�n����b���hTF'���&%���z�P~$@q��fOQH�]+����x*���A���R�-��PF(�35=���~��t@3Ha��������o���8�m�"C�~���jf��2�`�eW*�����d�L`�w��"C�~���<TnF�h������*?�L��P��;���6�2pB�����|�$�uWl�S��W7������w��.��������.
�zCh��m��So���h���E/L�]+�y��	��fB��Vhp�w���������]F0������F�����&c�~��nJ����;J�������^����E�EF0���\6Y��J�b%����~�bT+�b��_^7Y���EW���~����f9PhB�6�W�����Y��?R������?���U����*84��VElz���ZzA�n���j;����]�v�<��:���qK�(���z� d�Jx��t����o�14��d������������\��)20��z�}Y��5;�@�������t���8��o�����xpY�so@�f�]��K�dq��r+�w������������9�����hk���F�b�B��t�f'����z���>���Ab�uq�.>�����Y�XV���uo;w��V)����8�2����w=9v�47��X�;tr�����+#�~~�
u���������K������K�MP�]��g��V��8t���~}���=�,����M[u���"�
��(��%~������h%Z�.���oY���Y��-��o
�x �+V�������u|pY���go}�=�+������tu�������u��#��n[����w�������aX�X�ML�]Z9|��c<�3��^���w}������P�����m�|A?q���`��$��z�����K�E�(�����J�}Y�c���h���-��~���^S�8>����'�Vm ���6~�vN���2opm�(��C}y������>�mr}��Z������Sb���ML[�z�.�<u�������e�g��)��V��������mF����VR�����]_������(����:`�w=3}���Jn�Nn����~7mf��.��:`��r��cs�������EG.����d���A+V�A����N�<X�-l��2��w={�� @-l�4L����O3V���E:�~�<?d�&n;,zH���_�[��Z�>-V���zj&����+P�����>�L9j�Z������%�=DF��2���
���}���Q��D�/�!�����u�o_���gg�v[�)~��}�PFJ`��?����6�(v�/�s����%�b������W�N/�w\D#pC�������W�\f$��4=����������jF%l������'R���2/a������uG�lD��H
����E��-�~���Z�\ ���5R��m�s����3���>�kra��z��v�4�=���M�]_�f���>:V�����c~���d�	 �}�#�w}�N�!���7OP�����]���2�[w�V���~y[���f�����w}}����������C�Y'�a'�o��q���2
ah�����a����s�2��34����y�2a�i��K���;_���1�`�������t�o�����Q�]f�	k��a�	$hY����
�eU`YX��������~u���P�.V#���z�������a�]_������t�X�[� ���]�v�S���!�6��s���_�K�G���-�C��C�����wK:��*vS��
��Y��K�e���Khb�������aT�{#wz�>��oq��'���������e�2��	LM�%������E0s����Y�]_�s���EAen�>S��C��K��;����G
��/���TE����~���z�����S����GM���\/��6`����]���~{�����X�m
��o���f���x�����v����(��
�:�w=���<��k��������7������}�E���/G�E�2(��z
��g/�
d��N�.��~�����	��Ae��vJ��~��Njf��2Sp�C:�~�F}X]�X�w,��U'N���O�u��(���C���w���r�X9G���StV��j�V��������X&��B���~yz3���{z�=�z�k��V�3���J��~�S�.�`��	;�N��wm��w�9^����E!���AnR@E\������7����eX�NK��~���hl������}zE�� �L�i)2��w��@��^~�����a����<���
ML�]�;��ef��HQH�G�m[�����:�������L�f��y
MH�]��5q�P	�Th�������>�C`.�S�������_�(fp�����'��{�}&e�`��m���wm
}~)�Y3�p�Bo��:�
;�����X�lW,:f���us�^n��XL
MN�]��'�������]F1��_�3��	&MF���A`�����_�]��!f|	(�
�3���N����P>��fY�Y�������nE��b�m��~����2��-V�������Y	\�m�������RG=��TF���N��F�r�������_��`�s������]�2
�yr�xG>�����M1^�
����?�"X�`EH�/�=t�K0n�����X�oZ�[b6����TdF����|#�D�q
�)������ �c����e�2=�>F �D���l�}�������#:�v�<Y�j�����E�I�����n�HJ�")�����?u�8���\�H����%@ ���C�e�Gm��f!���@���MN�:L��@B����w�}j�����������c��]�"v���e�����"5[w�V�H]������l���:���5s���u0b�UGh�n���DC`�@.��H[3���
�n�q)��[q�-P�LO�l��D�I+LZ�on6�E@ W�\�C"W��C �R�e���� .��R��4�_��>��Q���"����������V�+w��L�qO_O��Z`+@��L�>��&�"���lC��Fz������*�?}�9t�m��;������
�����M)�������Tf���&%��;��v���p����wf�?�����aT�PC���k� 62����AMO(���]{���2�`'������-�����1�`������e�^�.����F
��oG�||`��2��kC�w=��Q�cz	�6`�G����n�E=���~���c��������w=h��{42p�eS@���u�`8�����w����w
�+@��R���]�\����E`��m������T9z&;��uQl�!�������^�d�*vZ���~��L6H,�B������2q����e���z���i#�L#��i2��w=w���8&n�Hw��z�}k��1�p_E���D���]�2,V9���������A�j�X�H����a��@-�����4
I�"����!�6�v���23��#�c������qf�]�j����mU���]s���Ie��FBhR�����_r���-�_����u�h� *���A����<e���I��
��K�xRf�8�8��Rd������\X���O��~ub3U���5(����w�9Cx�������7NwL��x�<~��z�}�B!�}���B����}��@��w�h�������H`�
��o����7��r����k�,>��a&�;��P
��/�����%����::�w}}���0��Y7�b�]���4�bfn{�@m��m����.L3�e������~��Z�0sP3��
/4(���9�Yf.}q�e P��B��wSY&��2�`�������-"�M��|�7"}K�k����Z�E�:���Z#��?O#e�+���\����(KnE��bq���~���l�$P��b�2��oN#Z�+��w={�����|<hoC��o&��v��h�>8��?�|M`��?t��p;���r�\��a�dvn[����w��lb<������*��5B�~�F}����.���O)�	��Kn�@�<�"^��]N�����c��N��
��3�b)���f��N�AK��i �R���Sd��������^m��������2!�k��qH�]�m�Rp�l���QN����i�*�`��Uw=$�����g�	d���v���w}yw��K����E�U����x���c����EG!���/?V�0��Xk�~�S�z~&�\��X���Z������mpY�b���8���r'_y'�u/����w��N��npY�b�,�������3�Y��J�b���gGq�jUQ�������ee\V���&g����6����T��K���{|H~��?�e��n�7��u|��Y�u#��������s��'7���~�}z�/kB`Q3{hb���-��a`Y;bQ���
�k�>�<��A�k�E�/��������"1�,"�"_d4���eg���^{������A�U#���54!�w���,��z`C'��#=�����Im�6�t�w�r�z
*V�A
�����S��hOh������~w�`MP��:!�;��]��7��(,��
ML�]6W�{l����(��J�:d���aj=��N`��m���w�n5�[&���`m��m��owg0	*�V���w=�T���lr03��:^h2�����7�I@\�P�������;R���2�`���H�������$�X[54)�w����sB���"�~��.�L$���X��k�_�>�V�T-j����������U�M�����j^�]�IXR�A)��������1z0��8+����g�CwY�s|5�~���|�/����M1��6���2���������u�=/]��T�p���w�����w�z7c��M�~������(�MXpoz.�w}���w�������"#�~��N�]�'�I	��E
��g�bf�~��~��-d�p�B��{���%	d2�Z��(��C=�B��2��]_�o�_On�S	
�����@��BP�C�
�Y�_|�m��o�wY�Pf�4|�k��
%��uWj�A����+{x��%�6��f=����t�RR����w�f]��]|3se��	�8�����O>2w��%�*����z���#x�$�K�e������ CGpJ���d���z�~�y#���B 4��~���hC�����hCW����_lf1��[��N�wm�?���6����jU�]O5��Rr�:,V=�����d�.�Hp����P����
s��#���-�C�����w��B��Uy�~��:�l�	#�L ��MN�]��
	Pq{�vJQJ�]_R�J.�������r��3p���8M�-��c�.�.	�o�]�]���W��c��M�D����1l������w}�]�	�d�f6����U�]O���?p���&C�~���]D����Q��:\�w=���d$����~�vr���c����A,C�t\������8�_Vd�j��Zu�������7"~�c��l�>n����~u[����(���i��m���/��_�2`a���K��O���!!VD�������63@���m�������(K��1`��������(K�2`��Hw��z����?x�����:o��_������(��A���{k�����X�H���6����@@������}�[�Y����
��.�g��
�� _�"�r|��~���^�G������k�>��!����
�:yhR�������Q��7������%��m���54(�����_
g�X��hzb�w���Yk����9Pd����%wPY�c���p��uG�)��c���lG���F�p�X�r
[�~���c9
\]We����p���X�1������Q���,x������J�����|���Qf��Y�C��w-e��f����w�n.�r��(���������o�Y��u0������0X��,c����.�������.��~��8���c����&c�~��8��c1�ub�����{X��
�b�
���okY	�UJ�*�~�����+��:�XC�������5����M����e{���?R*��H��u��WW9D��V�n����%��#?6�eq�E������b�3{�?3��o�y�VX���.����R���T���~���I�,{��k�M�)���s�^��M�.e�{`�.�u�!L�k�~����,{��+�E����<��=��J�W/>j@�w������Rwm*4(�����%����l>V�e��uQH��Z���13�vK�,�Am�6�d�w=����i�,,SW�u���_��V�C�a���	�]�:��e<����(����?W@e<���R�w���)3�[w�V�������;  m���z~����������0�	��u�6��6����A����5�E,��/����@f��Y%-��������y0I@�X�`�����M�}���,�78��>��-
���a�8h~�����>�2q]��j��?����
,��\��~w���<�V1���w��������XIM���0n�eP��b�4��o.
��@0�����P����X��������?�]�o�����{Lf,@�U��B�����/:��E�C'���6����	���;E!���u[/N,C�a�����~�e�
.��(������5(1����u@3�a���(���A��
�VP��CQd<����u-�V@�zB~����#y�>t��������	�k���:�R�V@���IR���v�d6#�}��������0�n���,1���$�
��w�c�~m�A��c)4!�w�-}ZGa�
,��l�C�����W	����Xf1n�(&��_Mu����B����6�������P�M=�w�S���c�	 �Q9�w�v���sp3�juhr������7����3��Ug���,��T�Y���u�i2"�(�i�?�8�]N���-��

��}��g�������nN��~���z�5*����)2���~<�O�q2(�������]���@�<n��[��������/�|}��X�n�U���v�dw!��Z��~�w�|��8�V��*_�]?;W����	9ZO'��74�W�LU������#��u����	�����]����@����%*�������0��/yqa%/4�~�]Gy����������Z��oh���*4(��Vj�;_��*��/�XE�.����+D3� ���&4��V���3HF�����~�F���r���]+tR�"��(4!��j;��A����Rh���~���tI4�E�"6
MH�����~�����	�]�����$�&P�I�������g����Ej�]��i�����C�U,���o4�����k6���~�\�Y�fS�tF\�E�lJ�lJ�C�i�B�S�Z���"��	-�5 ���{��3��`�"��]vVd#���,40��~8Z$1`����~�W��Hj�B������	j�(�l�-r���Q}�����jl�]?9}����X�M��gCE#U�b�6��.c�1`���&�h]=\��>������7�O����1��:��&W
��G���w}��v���8X�5��B~������2��K,;NE�|�]�(g�c�"��]/M��2�����h��Z�9+��Nj�4���,Z�]+uR�3��A
�"+�~�
�}f�A,�o=��A���|�/�����]+�����'o������nSQN;�����h��������&�]+��Y�}d������}=���6����\T�&�}th����R�J:{�h�]c��M��(~��K���&����z�wm��������l���1��m�ko�'�nJ�z	l6��;�����������~��C{�7�TleC��k��=�1)��Qhu���w=���
��T�(4��,'�]�-�� Q ���c�����p��1�{L:��������T&��ZEY�����{�#�����X�I��g%a�`��,Vy��zt���yAR�^�
M���z4����N�	3;;?�����w�N���uM4����J���QW
��l�����k��@ >~�7�@00���t��w��w��tqg8���)�L�w����V�Ae^@c'4(��V��g$��5N
���
���C
��������T!�q�]�����V�$+1
�^
mr����F:)����q�
=�����]�����v�
~�
����e\`�C1��^_���`�����~�������4T���C�����]r�eIV�d������]w��o���zldB�k[��!?����XG���ED�k��wh�(kut<��0���?�kuvd6�wm���_�u�t\��������Ql�[������B0
EN�b[���~�6�i���K�
�b��;{�l���x�6��'�]�^�� �A�	8ZW����W)�Y��~$)TvN}|~$������.P��Rw��������W!�N��V������p���c��+*{
E1�w=l���,2
�������FOw#I�X��hzP�w�
�}1����+�nY���������7�//20��q��"��~�J��)�0���v����Z���T�n������R�d,����d���Z��1T�:@�&�m]�l~�� ��Q�~�F���a$�+l2����z|��m�3��Y�=���z���?P�~)�
�r����p���Hp�Mq�)��u������M.���Z�Mn����� ��
�.T�]�R�g�9��bc~��w�:dB���J��e CN���h�J�w��s����=Ae.b/A��~��"h����Fl&�h?z�������Qj��Z������A����*�b�,�����n
�Z�+b�w=>3��i���~�O�Np���M���z��e�y�H:�������`4���_~�������]9�w=��~��X�t-N�������7\�Z@�u����������20�����		��gP��2�e������AgJ1���LAh�Y���~��2��1]�"�	~������9}�	MH�]t���r=t��		�k�N?����_������}�������Rj�~�>����U@���?y��k�fWe0��W�V]N��	�k��}��P�/vmtF��za�;/������B������{���
�z(���
�k�4���3_��7����~8�fs������fs������mb���6�t����co$`�:��bo:4�w�����v-.�
�������!,�i�T5YJ���B���Pf4��dz�w}�~�����q�-#�G����;Y��M�E��]?��3v�*�b6��}Fo���.V���������mgN��bE5��{��}�
<F�������.��/.|���^��D�~��-��u��=�F*c'�A����z7����u����?�����s���EF748���go�f�	��CM��oq�J*c���X��P��C����m<d B_�����������<�}���~����>�<Ae8a�F�,��m��/`1|��^Jm�b�w=���n8�G`O�����k�N^�f���q�~�6����>�t�>�N)���b��b��1�k����VF�6g�q��zx��{y%�uSj���l�m<��'X���=�M���
�i��I �h��'�w��Y��qd
@���I���������4Y0��~v��R?�����P,����0k�@X�R�����m��ii$p�C
������[e����XaE����d�������<ZW�������������K��f�����i�]��i_#��G��r�w=��}��T����MJ�]_�wu+Wp���uP�����x�_?V��6�(��
�����G��eM��E�
���wK�����(�~�w�vD��+s�*�, �]�('��b����s����Z��u:���]�����Z�2
�iP����V�j: ���������Q'�3�j?�Ll�����b��UW4 ��~6�,���0����(��m�q�k�Pk�����@��h]

������VLb����k~��K������,#������x�w��f�U0�
�y��������>�����[�����z���9 p�	����w=\F���3�1��&���;��H�����.48����10r�O�������]���.Xf`���"�
��V���km���~����I8-e�����~:L&��2�������[k;����O�]c�^~$���h?u=?�L�������'dHu�(uW
���:{��G.�1�lMJ�]�X�o7�U@�E�[�E)�w=��,L+�"���]����V�0�C���v��1h0Y����u4)��U��,�.C�uD�k�����J0�z�Q��ke�}�+���]+�c�<����$�CQJ;����2���^�lr���z���SJ@�b�^���k�N~|�)%��������z|9��I��!�L�������{�����C�UW���7����jl�)n6���~t�a����)���i6�m6�����X&46]?���\��]%f��&�w�����-�;���^�!�~��o/����NG�%D�kd�e"�V��(2����`��QC,�
;:������/n�d�l
-rn��zx!���\�[�������}��X-\����^
&�\-]������>5��n!�)����W�y�=|���#����r���~2�����_�q��o	fv�(vW��;��e
,s:!��	��!��},Pqae��(%����/T._8`I	��������c�(��Hh�4=������te:y���)�x�w-��>��_�+���e\C�Ih�YD����9yD�)(�o=�����A�/A0�{�`�����p��7�������KQL;�Z���|�
m/�69_�w���;5M1��/���w�B�~�%�U40��~4�h�������(��m����1�������z|��/�|'6R����+~�������m6���~�Cn�'d3�����.�f3��g��c�
��;�.O�][�2�c�:���b��]��)+La�$�:�w}�`�
#�FM���.��Y�ec�Ff�~���Y���2���)E���zY{�Z�D-V���zTI����X-Q�����~zp�x��"�XK���i��0�F��&�h]�p�|������?���O3���y1����Q��������tf��1��r�����������@L�`q}c��(���^�~�$Lb���=51�wm�����x�D��Q��~�>��k>'6��GE/��
;��w&��2�}TdI�����w��}��S����Vl6��m��'j�|@=t��I	�k�%�u�x&��2��S���6�4>0��^�mr������e�	,�{:�����f�o����K*49�w�4�_g#����$�����[���f�	�G�'�����1�Y�z(��
������:�m6���3��
;i�6�`f!v�t�6������0�O0��8�tu�������%����x����	�k�N:"��`�(@C�k������PF(t��,%�]?,�2!�	�-%�`�]?��O����h��h1���I�i�(�l�-r���z���D@���U����U�7���8-�������o�L�u�X�\�������2{��,��p�������������N}�j��G����/>���A��Q���]��C��EJ����V���T�`��%���������"�	��������=]��D6�]/��	@���64��,Z�]��N>��*"�����Z����D����58���u�{���)��:Xh@�w��I��(������:���+����t���agoU5]��E�B����^���F�"
��XD!@��~�v���Y��z(��������/���M��&����z������Z7�V]=�f��g����^���@EZ�����v���n�@0�?����������@�"�@�k���v
c��E�B��g��`���~�C�]N"�ThR����~="�[6�9I�w=^�:@X�Z������l���X�U������"Z��\�w=���'#r����&�h]=(�������>�t
F��	F��N]�od��:��2���G��b�w����YXAeB'4)�wm��O1p����(�FE�w=f��q��*���A�����2��i����~��J:
\�!t���\�]�����u	]d�q'��C�PYC������������u����Z��_Ga����B�k��� �Np��(*�iGW���a��Rh��~�
�}��a'�hV�
MJ��za���I%��j�~�v�_���L`��������p���������ec�H1���i�m�Y��C�U-��������m6��&~���j�c�&�1��#]��&�}O2.����������K~���[�M?����,��������-��T����%���~�K��|���+�LehV5YF��~Vf�
,S�F2���~t��T�2v�t�-,�����2v�[6�9i�wm�������XYM������k�����XaM�����1�Z<+��w}3��]�`.4�����Yra��~$�v�N���c��:�_'d���\����J���R���qu��}������{$2q��(�DE�|�]�(�>b�T$2PC������f�G��+��d�P5=���^���\'.3:TE�-���q�O-3m�i��"K�~�:�k?�J�[O6j@�w���Q+����~�����;�1k�Y�=���vt�2'��Y��Rh�S�~�6��X�(��K�.�����5����T���
~��.��z�T����]����e�����|�w=���W�`�Mr�I�������`G�)f&b�HP�)n�)^l]��`�����~���L�7��{Nj�����~�����w,�c,B����K�k�*M~)��'�EhU5YE��V����=���'��D������sK�����C��0?zO����El�[�t���������r�X9K����q���j�Z�������7	G�j�Z������4�l���\hr���K���dz�Hfj�!������f$������h@�?J��~�N��{�f����~���r�]u��b@�u�]������f��[Z&!P��@=5)�w���$T&%t�����S�;�LD'6�XE1������U&�21�Ud%����%Df������������%S�G�����c��1��91���2,��T����L� 
3�^
lr���z�X2��}#]��w�>>��.������8���V�e��<��������L]�e*c�H9�w�|��2aQET]��w�[2��R`�
\��l6��w}s���W[7�V]��&�}O���a�
.��C�.���w��/���������	������*�\hE�6�w��,&0T����&~��k��',da�D�������H�Z�X������!d�B��bE#���A\-�������v��a	l����
{�3.2�?�Pr�K(y�_:��u���*2d����+~��mG%pL�]����k����-����������V�l3����~��3{�����4=������
�y��e�@���z��ug|�[$�D�7��)�v�wm�k�����S�����.���#�=th����z��1>���m���]�|�l/69�wm�:���#�������Q�]?=���V]G����Z���
2L�a���U�]+u��cLe�`#F!����Nd��J��b�wm���o�1c��7�`�]+57��y�l�A���E�l�[w�'_����d�@f����',�����;�����z���~��\f��Y�������Xf4��,(�]?�������������p?E�
"b���B����F�'�eSn�3�~�OW�^�,*V��n�w�p������X�K�������$CPP��
M���zxp����>?�^����s~��~��_������?�����;7}q�<%�.B�����7o4@,q�c��( ��;��.�pHG����������~�t��L��������e<B;��:��ug��q	@�#�c���]��h������~���k�����;t����3��.b
&��"E���!s��m/�69=�w��z������.W�]�@���LB�efa�B�����k�X\�v/t���z�r�@^=�Wu���z�x��d 	*��z�w�tv����.��G~�C�����!�i������I�lTf�3YJ��^�sf&3�M��]���������.F�9����b��Q �,������S��+�����-V@+��w����8�ZG���w����xpY����u��s%���G����.���w�i�U8p�Gq��y�]_p6��g�e���������A'��,���e����������AE��@���~�+�������nGW��!��ug��`a~�pG_�������m���`��NF�C����z��,�����~����/�X�x�������Y�Ex�X,s����]�z&d1@����%���%�����~������&Y�sW@}w��1c}8�����?������k���A��R���]�Ps��UvP�Mm�����R'����uSj�E�l��l�o9�X�����t���z<�w�����>B��%l'�����C�1���TY��m�&�~���v�[�J?�L���)�����~�-@�	������8���eSl���~�kW���:�X�J������o�h�
�~���W��@0^�ru��k^���#q�pW�����4����\�����+~�����e�*s��C�~�cj���������������Po#L�!e�~��<���1_�/��X��z8����2D���Y���^e&��1q�9Pd�������@�{�yF�?������GG������������ ��E�Xhb����������?����&����gv���e���
z]����o_�H`��
��
(a��za����N������'��i����b�w=��}�,��Pl�e	�k��~�;SM`�Mr�I���ay��_~�o�]S�uSj���l����]��f�������~��
�L3'6�Nl�B���$���z��dP��B��GeO���2����d��z�^�)&pL9l<�����Q��1&��9�>l:������������b@-�R��,��~v��4X+���������\)�xZ+��w�vM�h�V��*d�]���;���M�������,U${5�V�t�=?S
�k���A�@�?J��~�N����%Xf-�:N����z�|
KX\Q�b)�9��o����eIE�������Q/���\�:�`����izh��z��|� ��Q,����)���w=��wk�����O�����-A���������YP�����2�{�h��z�������D����(�=}���P�-��KqMN�]wp���c�
��
����q.��������iS�h���Na�]?��f�
,�C�	��1���}�Z�V]��w}C��H������������?���b�.�fs���x%��h����K5���^q�NlF���ML�]�'���5P���:d�����z����m�&�~����Y6F��1��$S���{;��@�2v�t�-����(�peS\�~����Z�b�X1
�kv�<��P�U�������.3QpC'�h=m��%���:O��&�S_���@4�����*e&P��Rw����B]�qLB�������o\�Hf��.6�������2���jhP�w���c�r����S��	�k����rNl� ���,]�]�Q�<GZNE���4A}�9F
���:y��q�C�

�������2��T���V����^
mr�����H�j�����.V�]t��>�6�V]I����������o�����'��z����Ce>`�	(�D
����H���Ij=�Zu���z|To>	@j�	n6���^o�A��3��O�K�����~G'N0��$�t�����i�|sR3��f44(��~0�L7�d�Ac��L��'�L7e�A_��J���
�����L& ��dr�wm�����e�St�Al�8?Z:��_'��eSf���~�On3�vj�r�B�~�OV.��Z-���w�h���J�V��*j�]?�2p��,��������=����:~$���/:���H&s���#���?���k�N�Fc��\hr����������+*���	���.�"m�������������,��������a+�g/t���a�]w&�W�"x��4�<���q�0���[�9j�wm�kE�"��1A�O���~L����HcB���~x`�"����������zw��"�Xhb����3���m�"�
������kG<�" �

��W���Dn=�[u����B��Ig��Mn�����p
�~�9�uSl���lv����~��X�#`����]�p��;�e>�?C
�����_����,t`�w=���g�	ThP�w���2���,40��^;o�x�CB�^�����o� �W6�9_�wm����V�P�r,VY��������X-����6��m�R�`��9ZW?�L#�?�^v�rN}��`��u����#�����/�W��6��g~�d����Khr��z��v�3��K[;E1�w=����^�$�"���]�P��J&��2��������zH�O0����vR������g0	*�:LE���/���2���g5�>����e����a�C�	�����y��\f6{�r�����;J�]����&���
x
�&�`paWGW*��;k�Wb3�Wu�@����zy
� ����2�]?��f
,�9������r��]R����~�J�<q|����>p��fS�l��w=�����3%��������3�!	��M�+����03�I��{�����z�@�N�v-.�	X����z|���U�X�$4���'�]?,�2�)���e�]��>�>6Mc�+��y�����V�Y����be-������!W��be-���w�L=@h�Z������\~���C�&�h]�v�����HB�lch��u�g�]&��1����?��/��b�G	T\O��(J	���w0!A��������7��4�$��I�C
���`���j�N�l�]�/��4�$�J��D����{�TxL"lo�����s��|�!q�~��c9	$�2���Q�����Lk?y1`����]>��^�WV��U=�������]6�� �:�]�^g�>"GS����w��ld�l=[u���z�������ln��-��������l�Y������i6�m:�],K��%zl�B��gw�,��m�CV��;y�3+���BG�����������0@Y��� 3L��1��"���P�������_yG�
�W�;4������p��+V��������`�h�I�]�b�<��:h��t>��K���v��n�M���-�,�A�?J��~�N�~�
�)�����~���~�������X\g��_s�]�G���ks`Q�{jb�������6,kwt�������X>�����f��&B�u��������4*Kw4�,(�]?\�Y���'!41�w=>io_�O���
ML�]����������~QL;z�����Y��^�kr������<> y�����k^,����;�:���~z�X��%<��~���r�Kt`����$���ge���=��&��$���p������kIOj��Zu�4������r�;��27`�}�N�]�N�^4d8q�b14�|�]?c���2-`C�����%��CR�2-`?��"��uof���tn���.s���C� p��W�t|�o��_��f�l
,r~�����
Z�X�������<k �@,V@��z|��l���L���9ZO?+�2r�������>�.M����=�������])���Po�M��2�`k=4�w�
����5._��/����Zg��f���E640����9)	2d�!
��G~��G3��	����A�EK��G�6�EP�?�:(���w���x���p����Z���s�.��?:V�P+���:y��"����/
iGW���p&@�K�M��]/���/���R�Ii[W?��hR$��R�~��0�NP�K���K~�6��/h3t�YeV]9���+�5�1`�����N�wm�9y\:�uSl���k�fi�g�5}1b�=�MW
�����ze�8��DbW�]?X94�� ���!��~�v�e��r���x'�Am�&��~�+y�1�t��G�C�������1������fRK�H��~�v���{�����}�Z6�9s�w�����#�V�+l�w�l��SR�z-V����Y��IX�b�U���~4��AeL
(4!G���M����?�����GR��-�S��w��w��=��A��������bg?��Tf%�2B�~�O��,��������{�$O�!�������o^7"2�!	����~�K�z�jf���Y	��"K�~�Cn�i0f��2+�WSd
����`v�|'��g5��6��d�	�	{�@�w=���G���^�m�P�w=�
���
��(hc�t�����p�B��z$�������d�:6@@�O�wW�f����l.�!*�;%J���M���I��R�\F�w=�~J�6�2��i��~��n"D�������~�Cl�7�$rb3��^-40�����WfHeVA���E��G���"AeVA����C��gS�Q$��*�e�����v��c�R���a~�>����y`��l�(r���zxj:{���X�X�����]�&��3t��eb�2�~�����k���2�XI��gw���e,	,41G��N���g��$��l�����e��u�W�m����Q���]���[6��T��D��Fh2��z���X��,��l�����p����1x�`lh`�w=m7�1��]��~���i�5�	Z9E�1�������Ie<A+�������:�u�B������]_��1���C

���gk/
�Q*�{*E)����a2�^
lr���������e4b#E-��;���HV]7����3��#C�?�c>
4�|}w����{
��'��Gl�(~��.�����b�.N�]����[��5��fs�ke�Y��#g6�Lc���m6�m:��7f��`�����t���z��?K��ub3���040��~2���0���!��~�K�X�Y��X�1t��,'�]�]2e�)���Z�]�����2�2��u���h���~!2x�W6�9]�w�z}��@+�����6�<�����j�b53����s����+���bE3�������d�
 4G����������xU~$�U�fN}�a��u�W[7X����J���R�/�p����������h��'�P��������������H_��~���eO���2}�=�����z���0f�:����*���w=���S�����P��D����|g�
�[�=j�y�]�&)��C�
�����{���*�]l�����G�P@� 6jt���z�(2�W�(B���������cb�FG�����.���n�R�w=���_���l=[u���z8�����m6���~���v�t���a�="��5�������e�	*�ZD�.W�]?*2����B�


����D3��a��C�1��W�fYz2��Y��&��~�cj���<�e&b�H��~����]F����#�Go������L>��M�E��]�EX�fEN�b5k���~����l,�Z�+j�w}34f �D-V����s����E�,@h����.��u��d��-�?}l�'��w
�Z-�Y����])�w=��4��dBk���8���9��	��|�#Ts�]+�������g$tE�������u�<Q��z���9AeB��Q
�kj�\�6�u#�9��fB��
���Q�w��-Z>/�1'��A�BYM���������a��`�����|������Z�@x=t��		�k���9���~��'���:)��i[�q���z��������]J�w=����@�}�zPC~�����@AeDb�fWJ}���+p�`2 �[�����2���3��W�U]3�w}����lJ�Mi�]wp����M'�;4�:�Mg������A�:AeB�f��~�>��#�6'"�O�������D�K��zO�D C���1e~	�
z=M����u���%�L6���$���nL��cb�a�E���;����V��Q`�Xd����nL{��]��,V����w�����	pZd+B�w��,S���X�	�k�h,?�,�L`C'�h=m���}V��5���n>����w~�������+~�����8t9B������r�6K&pqUdw�('���;�*�"���]���������T�$��N�#
�k�ns�_XY�_�
��d��)�|�w����T&4t�,'�]+�>�fR	�[�<j@�w������6�?�o�&��:Rh@�w���o�U���h\�
���!��vt�|~/!.�7	m/�69k�wmgMN�eo��}��Xf6^����Z/���PF�]tl�����E��)f��2�����]+t�m&P����k~�J�|���%��������z��������M�U�N�n�����&�8h�lz)���r'��g�9��yb��]���O�d�	*�z=��b�]�z��
LF��2
���d=��zX��Op���u�)�����Y)�):\�$�]t�����_~��Q(�Vc�A�w=� n����Z�X-J��g��L-�j�Y������zh�jM�������P����7�$�����@�:�k�L�R��Rw����B�&V	�H4B~��a~=����������V��^0�	�f

��
��[����>��x,������Z��
�IPg�h�Y���V���W������5���8*4(��Vj����s�
�N���g50���#{�9��_�eB!���B��k�NJa@h�&�]=�5j\���Bl{)���C���X�;F��C(4!m�j�^Z�����!�����������b'��b0A
ThR����2<{S�XD)`�����;x���Rl=[u���zx�����pj�9n6���~p�c2"�n���h�Mp�N��Zb0A
Xhb�oWv�;�dX&��3��������{���d*tP�w���d(������Z��/�!��*4(��.��\,r���hy��~=j [6�9y�w�l9�E��b%u���~�����ZV+��w�p������X�M����	aX�7`��9ZW���������h�?�
�C�n����w�k�����Lg��
���hw��������6MhR���3��o�b����+�BE�~�]�(g��e>�
�����Z�v�9<R���jzD�w�c�7�{����f|C7������R���Os�2��Ud��Z����Us���i���t����Z��4�0�{�h������v��a@,�CE1��j��Y�����Rh�S�~�
�D����,��o�
�t�����&�{���U48��V���}K8�ge~cOJ�~�
��o�;]���gAe|cOJ)������������b�.Z�]�`�_=�x�fS�l��w�p����	�=)]����u�x��b@*zR�.Z�]+��X��Nn&��V�~���|�x��@(t@�w=ZO���	-�Lp��5YO�������he�cGJ��~�6�IP��X8��t�-0���"��=��eSf��~�����rR��.Vr����Qe:T+�b7���+��G�%u���~��sY`��M����6i�������o������{~�<���_~�K����]1���
6�����YR����������S'���T\Z�+J���v�l�=��o�����~���o�d6(�ZoM���wm��,��nh�Y��w���,(�:oES�];t��*B�z��N��w����M*{Q�������r����Rl�~�_'�%�������2D������v�,����2A�������H$5�n&��2A��z�]�]���>#R`���R��w=������z(��e7���������fS�l�O���)��H_R����K�����-�2��	]�M���w=>�����fr�=�S'���vj���^���	��C�o�];v������W��~�73<hS�t�����)����N���`�c����7x���Y��.Vb+A���k����_]LVc�A��z|Y��]����j���~��V�0�S_0G������C
�Y^?����q�.z���:��-�| �����]!��B�C�j	*�;4E)�wm�����E�748��r���cz*�:CM�~�J���K]��pb3^�5Td=��z���zaz&�:C�����2g��3>��g5(����_������~���}����$���-�����6���*�P�K�M��]+u��#K@i����k���Z����-�V]N������"fj	*S
;4:����PoQ��@��f��'���+��C�UW+���G9(��T�lZ�M+��;���Fc�Ie�a7F�h�Im�IL&��2���������=s���{��`������P�t�Y����,�~1��@&4�, �]w��{��cra�E&�~������Ut|g(��h���~�cqvs.��)��)B�k��3$%���bU,���+s0�L=�eP.48��Uz�/,��g�?�^lC��s~��~��_xu���Q���]_�+��9 ����MN�]+�rq���s��
E�w���� :D(04��6�����&�7�?�]�<Ng�8��@��(�N�w����$�eA�������Bg�<1b���5(��j��_����B��k�v�z!� �o����:M_L���b��&���^��Bb�A���5�k[N���]�U48��^Y�Wl���&��*���W�I8�a�m���z�
u������z(�������#CG`��r�Y���b�U��h�Zu�6������g.�;�\�^���~�
����oV]z��'7�Il�B��k��*+�GPN�b9d����Q��wt��T&�X��&�]w
�/�U�68dV�w�Ze� �	�������'a@�\�U�����|������XAK�����Oh����j�b�~����t�=|�C����?ZW��f��������.����w�����;�%h"�~�Cj��)Pq)a��(%������90y��dfh0�w�l�#AeXA���Q�����f9��T�+)���w-���
�E���vI��D�k��Ex�����<�~������,��c�~���4X�6.�b�����vF�0�0j{)���C�k��>9�I$�L*l[����2�%5��U40��6����C������N(��/���$HP��P��W�5��_J��R��V�]s���<�l^��+����k��lrM�����lr�tr{����Tf�/6]���^�~��+�Mb��]���/�f�.�	:'��`�]�U��c:>��p��I�E���
�u�8&v3dr�wm�k��StD�g�?������P�Y��
�b&��o�����k~��G�18-N����^�B�2����u��&�}�6���#���Mr�v~��~��_��f�u�(uW
���:}�K$��Ah[�&&������6Y�`q�b��(&��/�����"p����w=e�y:F��2�_�����zxHs��R:3���Ah�Y���V�d��'��@h�YF��Vh��_O�\�o=�����BgO1��z�P�A���
����K��|P��M�B���
�m�f�	&�{���w�h!1gZ��B�k���P��� ����
~�#l�%u}�i#�L#�[(~���`�G{�/��CqU
��m����d�j��m6���R���6�[��,���ln���.$?���2��a��r����)f�8��Eb��]�����3h�A]�C/���w��3i�Im�&��~�v�HTx�t2}�]!�I����r��EE��~	���-\���������)���@����+�L��:-V�������\pZ��Z�w�9b�d��a	 4�������������Q~$�46)���{~T~��������Q�����v��Lg�wy�!�F`E��8ubN����v��2i����#E)���x���=�$���������^���X&4e����~6�L'5	�2EV1���:{���#��$��YN��6��;��A}�MJ�]�X�������C~�������P��G�B����<�����Rj�S~�F]k���(�������6�r�����)41�wm�Y"�����"���k��oug�	*�[$J	�����<��C�U�l�]�`��.���2#OP�Mq�)���)�<��l���)�U�l��l�����<�e&B�d�U~�7����zNl���,ML�]����*f�	.s4��d�]_��i��'�LD��4YM�����>�O����8�y����L�\�_�.:Jf$�O6�G�
��K������)������i���%���bE6����
3�Z>+��w�:>&"��n.VW���q�;t�0�"t����toD��������5����^�G��w����G��b�w����/3l�a������p����E*b��I	�k�Nz�{�X�FM�)���p����0����Eh�YO��~Fe�	*c:5E,���:������T�~�m����C��M����B��k���-�"y	�]R�LEl������:��W�@�K�MN�]t�6P�%�\�n�.a�]+����e������	�]�^x���b4b�Fg~�����Sn�2�q��]_�v/��D=Qu���Z�6{ �A'��&�����z8��_�0����k��d���4f��8eB�f�
��GP&��	(6�����h���2��-t�Z����U-��>}�<����,!�]wx7O����V��)��^2��i�
�M9Z<�������b�c���~��zd���_]1V:+-�w}34��@0�ru������������&����1��:��o5f���Q���]��������|�FhR���B��b,���U����>��u������$��~�6��OM0p��}���~���;�8�5N`f�h��]�]�8���b�,�z4EV��uz�@�[O<jP�w���|��a�C�

����3RF�,)JiGW�P;��a��Rh���~�
�}��Y#��"l���������g���b�~�����	��"l�����Z��O2g�9��e����:k~2{[�V]�����N~��#��&������7�`f�Jt�6��������l�F��+~�������f8��ZhP�w��I��T�4gY���~v��X��h��%�][�2O/�d�6Md��w��6�,T�n@�&E����:4��M�E��]g������?�
�b7��;�Z�s������.Vj���Sz��%�8-������^�E���a-����G5w��[����#������������:���s��G���w}wk��<�"��
MJ�]��]��E^\@���~��Q~���j��~��q�^HB�
8h�y�]/N+�V���>�Y����i]|��T�3P�A���R/����BC���'5 ����7��z�P�A���u��;B���&�]m�;y�q���Rj�S�~�J�>p����Hg�B���V��{/]KI�B���5������zEJ�]�%p�|R��Pl����!��^=b��,�BS[W/�����B�Ej�]?�"���%�58��~tg�T������7�=td �Q��������3��TdP�A���j�����)��z��ux���+V���z�2a�O�p�
<�]/O(�}��+V�����4A$���������,K������S�w��w���:� ��?����!�{���?�Lhm�&&��
;��f�.�T�r��z��_0`�����z������	h�4=���R{�	0��h�Y����<'�?�yyP�i �Lh�YP����N^�g�[�Aj@�w��iW�q�C�

�����5b�Y)�iGW?�b�@�K�M��]+t��@T�Ut��Z��o3[u=A�k�Nv����1�}�Q�]���'G�C������R�w��B�9�z(��������H?�xy��)$��f�������5Hl�[u�6������[Q�>�e6Boe�E���XF���(6n�����3lf��2��s�:�����&?��q(��Kh�4YQ���=���h��
��/\O���Cc&cE���zB����1z�[6�9[�wmC%���YR��.Vg���w��6	�
�X�M����w?/<���U���^���-����&���Gr��N��~m����w
�j���v�(vWL�]�O������������r�]�{�]����vJQ��w���'%��EH�������#�X�4ts����~��vb3���Sd�����O�f*c�:E���zY���g�[OAhB�������GG���F�,b�]t��;�!@�K�M�0��
:�\�����6�.����+���[���&&��
���eVbwE�3���c�N"w��'`��]QL�]/����(h=Z���k���vpy��Y(��f������>��FZ�	fTb?G�l�	n�	��qr��I(�LJ��l�d����z��`3)�Nvhb����g
*��H��a�]��z�y��AeNB[��j�����_^:��D�!�M�];b4�O�1���#��m\���U�L=��MqEN�]����������[�]w�9y��@�\�U����?��i�8-Y��������Q�z��:1G���{��������53�������L��?���~�?
���peS!�Op����	MN�]+w��W��v��T~����� �����ux��Eh]5=����v�a��eB��������.��������d##���,��.����V����jp�wm������+w)w�%C��g��V����#	M��u�����wY��� �<��;+u��.������~������ gA����8�Ze���9�z��Mk����e��;����F��������������;6*��'�w��J�vp_o�B�~�v$'�d����~�����Wv��F�~�*�V�V9���~6�w�9���j@MJ-]���W/�?����\
�7w�O��_��u���,���?���k��?��5T@Yca[64!�wm����uRqrp3�(%�����yrQi��]������r*�,�������Z��o���:�Yta��"���:*��`�������R���lfIT�\�o���C�k����K�S��/���p�w��`�u��G�7��(��Z��_�f]\�]�������;��ful=[�X��Z��wiXd�E�'�`����50k,P����������K��+X�`����$������E�	��,vF�����[[V\�)�������S�*�@n�J�[���������,�

�K�8��l4��
.2n��������Yq}~�B��u�z~^�~����R�J����]�<��
w��f]�]��	�?~����*+p��
MN�]����&�,~���t.�wm��~Y�����#$K�~��c��M X�`�g���,����p��
��?E8��V��c���R�.+�~�F����p�=�8B�o]=\?�o�g�\V@���~��K���%���z�wm�;�X���7�� ���s9��06�VV=����lZ�pZ'[R���~��'%�����eN`�:�I
����'Y�����Y���~x1�z&��w��>��7��+O2��� n�
�Ko0����;Z���	,40��^,AX��?R�Tn���8?�H���/�!d��Q���]+t���&��}�����6����,m���������^�~��nbqB�]+v^���
./�:5=����p�/���N`V\��%L�k�t�eVpY�aCh�(��������UV`Y�qKH���m~m���I�KI�� �]?\AYZ�{��&g���{uK"VT�c��������0YZ�57bt:�w�9Q�k"������l��;�ie�J'����	��y���q��9�Y	��4��^�e�@�"�y�~��S2�� ����[!���N�,.��UqU��;��z����M ��'k�������3Y�pS�O����b����v�E��G��r�����V��	(K���N��w�6���O�b��{���~�W���H�^Du��	���G��KpY�`[��Q
�k�No,bNn9���U����W;���f��Q@�=m��<X���
w{d!�����Z����]������E����	������l���	*kn���~�����S�Gj=�Z� �����b	T�W���C~��C�}$���������fS���vR��_������gd�];��PT ���������w�|Vd�@VR�dy~�7c�),���"�	~��cb�`�
�r��w}7&I�`���'k���w�������:���z��c��u���
�J���������{Sg�8VQ�:	�?~����r*�X���)
�����J �'C�k^;����J	�@M���W��%�	��#��w}���g�V���5�]�'1� ���CN8�]�	7-?Y�u�&d���zy.Y�wOn�����tV2�T�B�S������Qg[|�m����F��~�/�y�.���=x�~�K��]
ry��6�\�]?\�yg
.o���~��]�
���K��{��9����������-����]1��V���g���[#rwhb���F���Ub�R��b��Z����]T�%A

�����W�3�wN�14=������~_�7�����7���b�]?�`n*��[6���QJ�]���C��-��mF}YK��~2��O������J�����bK��C�)4!���O�� �,��z@���:�=#���z(��!���]��?cK\l9�MNm]�d���0+%�~=��f��g����,��B	�����~etB�L�T
���,���2	;o������"(�,��M ��~�OG�"�Z�[��������;��4*4)�t�Rg��B��w��j;�
N����Km�:��s�b�����]9��V��+[��4����6��fB�Ej���&%���:o���"7j3rC���%n�X�������!�WpY����(���w����bE��PhBJ�j�.��E*�%P�A����z������C��]�eb�Vj`Q+
���'�]�Dj=�Zu6�w�����PJ�BR[Ww��q^�[TIV=����u�v����\J�B�S�zy�(z�")�5���v?��]/���0q����wmW��~���S��"������ll���\hp^z��?h��Q�"�,�]?\�,��E.49�t����%������f�m�?��=_���5��E
�+P��Rw����Q�O��
,+0��:1���a�_�J.NB�S��~�>��>K,`q{jb���)�V`Y�a{���
�k���Fh�_���u���X��������V��QJ�=�pg�X������~x`�	F��R�.�	~�W��3<	<���N����
z-�@b��
*����GBk�u�PD��~�~���!��w����u���>���)��1j6��?���'��������g\�]����c�v����}�����w�|d�@t��:de���fefuVo��z�'�����A��j�T�z���,�]��%k5kU`������dY�m������e������kw�K��/���:�+��Y�����+~��\}��X�l�G
ML�]_���&�1q�q��( �����Y���
������^���<�Y���k=��O\����d�������~�
,����W�}�RjW?��*4lX������ky�b����]�
����i�Z�z������������Yv�e���d��u���W3,����(�]��k�dTi��c���c�q����D���f����:��'���H���'��;�����N\�h�u�?���K��s_�F���,S�]�O����
;]�C���6����N�&�$�3�{�"����$���VVY$��^!K��T 4�t���e����:��}�S��
��:��Z�%p�Gq��y�]_pk�]�����K��	�k�u&Ye�S�{WE�d�]?�-pq^��]�Iy �1��5=���^[2Ye�����c%+�~�����c����V����_jW��:/�����T�p�w=^�YZq�B�O��Z���Y>�:Ae-��#9��w������x���b������Y��5��tR�w�p��f�����|h6��?�k����	�J�����Y�,zNDE�1�?	�k;���������K�l�w�p�dA\L�\z������}5Y@Y7q�I�����{_��U�U�����/Y$�ET`�����7+����YYq���%����O~�r�M��	����]����������
�A�I	�k�^c[�{S(�@�9�=�����V��#W���		hh@�wm���KXM��6��U�]?i�T'4k �m�������NPYq�H*����{��O��R�.��~���[O�M�GS��u�B���b�\d�+�s�~��������C�U#���W�~���V`Y�q�H�$�����YlZ7�V=��f�ugx:VV[�e5����*��v�����p>�Y��n4 ��Vh�Qj��Y}����d
����z�h��+������>��7��=fo��&K)�2�.�R�����v�Hn������w�d-e�Pe�&�����f�s,�>?R��>���7^`�k��n�,��?

�
�#jW+t��(����.��Phb������m&�#w��b��Z��/$�$������p��O���{aM.��;{����I�Y�U�R�w�p���.�B�Tm����KK���3bY�a�j�cK���km�eE��3
�kC��<Yh�����d�����l��[�V�9�]?�e�X�b���S[W��d�@�C�:�ta6���=����@d�������~v}��&�,�I$+�~�WN�8�e	�M���������=����I$'"�����UNpY��]�WP����ff!���>���ik7����n�����~�W�B���;�X��")
9��
��zb��=51�wm��W����3Mi�];w����f���"�-��Ns����?6h��bJ�i�.>�*��@
MJ�]�;xE�wW��R�.k
~�������zPC'`�z������@���=�����'��������?7Et����7���&�n
�:s������3� Xa`�c��~������	�z#rh��z2���@V��������Z�d��
���������8�,1��!�~�7�%��@��Dh�������{_;�>��1������_��!�]���$W?������]9��V�|�K`Y� ��&&��m��/�%��������5#�@���~B�����������!^������ ��B��QL�]��� �,�C���k%�p��rwY+������W*q�Th��}��o\�Fc���� ~�����&Z�����G
~����>D +l T�?�]�M�������
����^'���UE�\h�w�v�fk
�"��������UB XE`��}��������B-��F?�@h^z	��
,�?	����w�	�G��w(N�9�@���7����O�V����J���R'���D&Kl�&#����o���/'e��_b��<��X�w�S����M�����~.����;/�
!���A���
��p^�����3�J%��d�5�����Z���f�rR�����`�]��w�>��,]���G!�v�B��������:����n�T�]���bN0	`�`h`�w���G_�e��=������~ti���z(������F��h2��A�����.������1��i��l6��{�'m��+@�;����D���x��n+k���5O�qhP�w���fq\?���%L�����n��R�Cz���4;+B��{���������0
 4���C9�
�����Yq���5�W��������r��rw���Z�k�����	MF�]+sV������I	�k����w��o��J���748��V���<K���4�&O��
�k����G�����R
hVF��5L�k��Y}Vd�Ya�e�(���~x\��	.����~�c.k�+�:��/�����w���r�$��Q�5��ZhR����2�������'#�]_�����
�z(��Q���]w��'������6�K��;C3R�Id��
=T�&�}O���	o�UAe��]�M�B�]?��eeur���}hp�w�t<�[_������,U�]?oX�e���������_��g�TlP�

�Ko7���w��	,k��B�����U9~�8+�.:���H1�:���"��"u�(uW
����V���RLh2��Z���K+R�d 54)�w��^��b�e�q"��]+�~[�e�(��~�
]��
*����"Y�������E��2PhBJ�j����N���%��XTa�B�k����������]V����&U�z\�	���V��a�U���]_��V����z(��A���t��*,@Q�
MHm]m����_��k�Fh�Z�6���=�����Eu,41�����^mV�`!��~��F��
X�a�B�~�K�H�.u�����F������������v��~������@�~���#�X�7-�����.���>�����VB��Bw����A~*eVpY�a����9����N���z������TQ��wm�]�-��S�S�~�F�IYj��v�����v�t�����b��S���wm���Pc���>
)��}��*��V`Y�qoJ���}�wu~VZ`�/e����w�k�S�][�,�@=���N����Q�����
,+1�V�u~��.�Ym��7�tF�����'��
��7�tF�
�u�:�g��	*#lmz�����Y}�b��f���	����,��b��G���w�GvyS\K�>z��;����o���z	�GoYS��~x�fAl������w�6��v�,��:9����{���l���l���l���
�������Z_�%u�(uW
���:o��.�4� �&'���;�5D
*�I�[�����vrk�"X����~���/c�(k4l�5=��������4@�@���,b�]?i`e��m����R���K������V���w�l)e��R�.K�~���Tl������
M��u�z����+�,��g%W�]�(�J���C�U� ���'�e��F���g��~�����f��j�Vz���n����>�,����i	���U�B�f!{+����V������(�1l#�J�k�.�g���F������z�Y�������$��ez�������z5$���MJ:��$��$X6 ��wwWeDTM���XQ�U��W�DfDE��)��?����d��u�A����������b�JVr�q��,�t����
����$C��5<7C����y�������Y2�2js���LG)��?OF���o����	ZV�B$��2�������]���d\e���_��a������.)c�q�aKFV���0������K���\������6]��������B�[����\����	}5������t���v��jVV���u:N���?W�q\I�����(���y���6he5�*�6����d?����?���x�a����g�9���a�sJ�5*��PX�� ��?�A����qs�4����u�,��?�0l6��M�n�a%3�l�����g��9���d��4����mf��w���~��kV2������Y~?����x�!4���\ �����/��D�aIW�-��0�����W�����_)�_��.�~�����~���6�"�r	5Y+���y�-���wSKJ�5�[��8�������Ky���a���n�T~?n&-/_�4eP�z
33>�A�����A_n����}(�P;g���y:�R>"YM�l�2��\F)��?�F��*5�����P��:�������x����Y�pB��$��?�F]�o$������B��t��s���JJ3�*)��B��$��?����������6��$��?/o'��JJS��[�e���>O}�0��*9�pC��(����Y�X>)9O������t%�����q�aIf3*���C�u,��?���7�l,���C����l|sm� hn3�*�O!�NS-��?�F]j�)��0��C#�Q��0���g3lU~�LgP2��K��,��?�������M��
��O!�������|�o��"X�<���E3���p��0����u��"��?��b�Q�J�5X�e��u����W]O��N����[*������/��fTe��:��������W�~%J�W���Y?6?��s?�m"��,�W2�2l�/a���0�����a�M��������s��~��'�a%�+��m�������
�9�0��x�0Mv��~�<�W��|��p������t��v��t�MTR�qPI��`�l'���y:���D�����y:j3�O����t����4�+���u-�2Jsr�g!�����CH^%���|����j��v�'��:S�����g���p����P	�3��m�G����8�u��2��T��9M��~�<��r�2��T#EQ��8�����n}��+���>���~���M��q@��
t��L������I��m��4�*�e�����g�����%,�e��������d6CR�|��y>w���E�������'�d��:���2�~�lG��_%�����p>�����?����G�&7e��B4��A����g�.����Z��:<� �����A_N�����~�6]������������j�#<�d�����d`Ml�A%�)4��:��������.���cJ�#�d'����gc.�$�������6��T~?���%y:h?]��YiN��lP ���VR�q�Bu�q�gg���y>��������q��J���?{q�m���&�I
&��t
������Y;���v����to3�����kWR�B/���9�~���,��0��_#a1>� ����������8��_�:M�o�����G��2��_�w��������H����~	5�K���g���8���v�MT~?~����*J�78>�]�=�,�b�ew��j�'��|�K����O����'�J^W�m��a��0������Kzh���A%�+���,����?O]��$�+���3�~�<v��TR�2nq�2��\�)��?O�}���*	`a�n��-��?����g�fx���
5������t��R@I��Q%,4��:������*I�8�$�BCM���~�<u��WI����y:h3�K����O�U��2h?]��,�4'��G�J�7*`a�.�� ��?�A�|�$se����MW��~�<��4��tO���j����g��5FNG�N�Q��r�f��}��,�$s������4u�����t����2��{#=S��8���g�o4y��\�PN��������F��q@I��r����~�\��$m*Ct�t�n�\����,�x��+��8ly�a��}���=
/�S�{�l]�����_��~�<�~��O��2\s��L�����f��=�[i3&cJNUx��Y�?����U2�2h��Bn��A���������k�T-�Tt|.�������J�4*�T��n�%-��?�������/
�j>%��d������a_��*�J>U���u:J����Q_=t/�JF%�d;����?�N�1�A��t�f����������`4g*����-�2Lsr���B ��iU�*��&QA~?��I�A���~:^7]�����"�&Q���d	�5]����3�l�������v���L{�n������q%�*��i�����������%���4kdE�s��~�<������8ha����yD~?�n_G�%�+����0}�L��W���m��4�vk�������"M���]7���"���y6��
3d\���q�������t��Oy�������	�5<��NU����f���������u:l3��~�<v�(��z���
�i|�a������.di���A�+
��N?��b-��Z���:>�Q�����Q�|��%�loV��B���[~?~e�o'����
�5�������L���8�$���:]�����<�[_lt&�J.(D�d?�����asRI����y:n3�Q���������te%,����-��?��S5m�ToSR3���-��?O�\��+��8��fBEM�Y~?��f���V�������6�[o��� TJ�5*�Y!�NSG)��?O]Ve%����l�T�s��~�<w�����&Y+���[i}6}#L��H�2�$g�����/�����d�(��pd�m$��?������]7��l!������n��f[�x�����g��Z�y��,*h%�z���uB�=�o��G��������1��q��t�f:����3�{��dWe����1�gc���y6��y�1��QGg�Q�ge���y6��=�t���d��Y�?���8�$Xe����q�gg������J�5�+)Y'L�d#����g�.4�*V�dde��Yi;�y6�k�2h������2�~�<�����J�l��1��n*��?��|����O�t|�A���lu2Da����@���?����V��l�a�~:l7]������_�3����K�W�u���=;z��%k����t�n�R��YoKf����aK�W��u���=��3J�6�)9��Q�e������g����AK�W�� �������$le�����g`�v����g����qK�U��e����2��pDM,yWp|������I^5����K���<����������V0��Nl����������+9�8��\��e�������/tK+IU�8��Q�t������_����:n��2��\�)��?���W�JJ5*)W��n��-��?O]:�"	�0��>�:MF������������'4YW���y:�b���7e��<��,��~�<s��f�����Q��t��6�9���c�{�^r�q8��
#t����~�\I��"���v��+��?O����I�3�+��pP��+��?�q�y�j����		5]�������]L4����0P�n:Hwt�jb�z�q5+���\�)��?���stL����P@�����se��m�d�u�!�s�<O�����tw9N������d����g��g�d@�z������3����&5���$�,���|[O�����������M��N�m�����������76JF���0���2�~�<u�>��5e������A��������5�)����:>�A�����A_�IF���M���������.t���fTX��>�,��?O]�nUh�2��Z��9]�����<��KY�$S�����2YW������&HZS���6.�e������{44i��5�x��3qL���y�g.���������Q��1��������y.S�e����}�Y��������v���|s
�b&T����2���������.7���fW3��@(�e����3���j��dg�De��|-���������~��I�U��K?��F����H1jn5'�W!b.�M#��?�p�4�*�v�t�n�o���g'�T)Pr�q��,t��<������������qzL��������������?;�n����A>O����g��Y����o��E���`^EW�g���%��f�g������>���K�|�����?�����}�;���f5<Mc����I�����=?�n��X�c�����������������w�>��?�k����;5�����������O��_���_������������o���������������������������>c�?����_�����c�O�����������~�o����*��(2�T���Ec���(��?#�����7�0�_�\���k����������u����������B�w�X�o�xI�y#��}��8q�8�����c����Bh?�������<v�z�����:���0��O[����c+�<��}�����%��w��
�]�x��*3�$�_���x���_�=o��o)k������=��O��Z���y�`���Ng��Eb������n�w��O��� ���������2��c�����g��oI��N����q;���}{���9]1���Mo���
���=��}�v����n}����Vasa����Z�v	#�������T��O~���{k�+��q�>��~�s��:���t�?�����������cs����U������2o.�8_n�ysy��z����;��[��!���v��K�������M��:���2y6�8w�����:���Y���f�q�����Y��)3�V�9�}w��|�q9�+������V�?�m<40������z�5V�4.��i�L�r�u�d��e�L�r����L����|\�qi��2�K{]-��t��2�K���i\n�53�����c3�KZ3����7�i\��3���[1���.+f��m�L�z����L�z�W�4��������1��4��f�L��P�_�4��e��}!��f{�0$� �������\��MF�C���R.�3���)��!j���?��?��9����|�Q���l�G�w�=��'�����!�����?��_�
~�{>W��I>�C���p�L�g���s����>�����'�^}��������!�����?Cn�_������#&�g�������+���0o/)?�l*:z�����[���y�KK�7}����[}��>0������U�����H���{{>]Wy���q���c��G���^������W.�~o����������xr���6���k����q�����}��^������:���;�k�������=�f��~�������_g�q���?r���������=�����A�y8(�����>��$;�}{�m;_�_�����k"*��'t,w]u��@���\�������k{�zw���
������7�7_�t�<�/>��>��;�W��V����������Z��n4K,�9���?6K�y��Pw�+�������x�������OMm����0}�|������y>7�
xq��<_���y>��s��jfy,�;��f�p���\�w�i]�x��_�����/��O��o�����^�����G�gH���.���G�������h7IS�0?z��.w�?��-������/1?�t}��6���ks�+]sB�����A����U��������E������5����h���5�X� ��;���_y�
 ������y��m�{r���z����]���h�Ku�>������
n�]�������x�1�
}���*����+��+��Bo��K������=��7��
.��:��*�l�{&���TVZ;�y����%)��*���<S�X������
�aY���0I<�WV��><3s�U���{��
��[��SY�<����
p1���Z�*������Up��`*~��?��(�U~���6�
��*@?z��\X�G��nV��S�U�o��^�>*�����J���K
wg��G������m�=�p������na;���}���_��
�������X!wd��MX�d�hn�v��#B��CH^7���B8�t�>9����}��$���� ����|�������|���;�H@�����$ �o�DK�};~kE���W4��)����@�P�����	xM����'��(�-�B���6F{Q�kE)l���1��m�\K�!R�(q�CX��{�����r�lY������	5/b���p����3>���W��������i��NTF{�W��B)��EQ�~���� �T������*���6L8���H. sD�B9���>^Q��%,'V�s!��,,C>�H3�?:�be���\��t���,#zVH���9��{���
�������zr',MS��f�_���l/�~5����#�#
��b�
�<{��/I�<����0.�v<���y�+��P���f���E�a*^D3�*���Te�_��<@/���(�P����e�Qg%�y�^�������W���EQla*^���y�xQP�W���.
~7���>��(z}��u��e�^�b�,z1we���p���<����0�����t�r��?��u�����#
$0t���a��u%�4m��4��{�%^g���C��S�!x��X����C�����[�s��(�C��h��Pkm;�������.n��b39��\l&�3���=|9�3���7����P�
����(�7�XQf���'�|�xQ�{U���E���6�(����(��z�6>s���+�?@/"%�����s]u�/���0�C�����?�5
O*�P��Xd1��������b��^)^\���W6�)��z[L�W4��6���x��&
hQ�^
c��:��������.�V�&"� �D�C�oa"�g�LD>�0+@�s��nn��t��[��|��Y�Q>"}��G�/����������n��/b���(�y�����K���A�~�>�;���`��>C���C+�h��� js
u��\5�	�x
u��?��-c���[�(��N���)f����=(j^DS'/
b+u�(~��P'����>C�T�(8w�N��f��e����	����6�E�������P��eQ*E�(��R��o����B�eS�6��+��kX�PL/���C��(���ateQ��z]bh���
����]X�|haQ 4�#ZX��oK����(�$.4��p(+����s�Os��J�l`9���u$���:6�*�t?Y��w���I������7���,��=��,�c��lLd�-q�����o	$����V��>�B?;FY����+v��OYdB�yQ�'T�;�W����7�UyQ�Vt�Dgp`�3�z���EA�_�����C�����^�����&>���^)^��P����\��E�n�J=`/Jh]��'��@��N�c	�[b"�h�;) I.M1�MQ�V `�-f>p_�q�B4d�XZVd�
��g\h�|��f@�����f������'4C�����x#�pn��,�������������N�\l�3����q������������qE�����04@?H�f�x��agv�yQ��J�*^D��&�-��f�^�q��^dh�E����f��ch��E�o
�PyE�X�^�"�f�xM3@{�))C3���34�"��P��5KJ3�w�><w�\��>8�	,4C�����*D04}�a
��l�
�!{���|s(��L�l��b�
�_@�
Yz�
YZh�dK+��\h��M��C����k���#��p.v�{�������?��~�{���b�������-��S���=����=2:sy��*^Ds/�q�P�"�{�x[h�����R�h�����{�������Gb�{�^t��+�P�"�Gf���b�r/�bw^�����>�pAq�'�$���o�6�C�]E��(���{p�3��t��=d��w��y�B��c�{��.u+D���YKw��YKeE��S"Z=$��z�.�)��!�)�7�t�Xa��3��CX��s�\l�L7��p��N@{��*��N:��%�*
-N�v�,@O*�+�O�#�L�a!*^<��,D���E����>�_��B@/J)��'n�TzQ�i�a!��E?�B@/"n�P"��Q�"����E��^�"��C�]D����w�5,�"����
��hz�!l���5�S&�&:e�L���D�9�?���������D�]��|���m��<�-LD�/*���z"�r"��F��Z�����l�lD:�#��5�;���&%�gU<�(�G&e���F��Go2����m�����N�9oH;�g&�#	G9�M����-o}fH}C���D+�%��!Q:SgoH��|���E	!Q*^���D^D�P����CI����(����'q�Zf��D�{f"�����(/
~�*�R�"����El���	���W���>��?��&J�@/",�$
�"���_��XP���8sQHM_7����,K�
��g
��?sq\ZD�M�
�B��}[�5}����I������{Z�r��$}oh)I����$�[��J�����C\�8��	��r����9��c�����sNp {o�+R�|���)���?��B�|@+�4S���tR�������h���?����"����w�b��)<%�}P]&NU��;�U*]u���)|a�e���V�5/
~�P��(v���'8���qK����T����(~�J��Eq�T������RG��3-�:�|����w�in�XZe"`��F}��=8����V��3.�2���t��6�P
��#��\��|��j$�A�h��!�B4d;���H_��f��h������w�a���{���f�����D���
��b�ja�s�x���a�'��a��I�@�$�g�W5^�!�C����P��hw��:oJ�W�����2��8qD�����"�jVe�u�8T�(�-�C����5/
�P���.
�0M}����������T����2U/b;W`/�w�2�@'�fJ92����p.tB��t`�������t��5����>���m��a��u��<��}�!{O+��\��l`����J$�)��/����p����1��`�f"���.vN�L;�k���|5��;^�n�h�x7A�=�OBc6�X��bP�����'5�{�x�5��E4���E�{^�I�q����5[|��=@/:�NU�<V4��p����)�{H���E������p/��G����E��7��RN������U�w�V��Eq��.xB��|���mC�����C�+8
���B�5��%[��[^�lMw���V�!}�I��|[K��f]�U�0�Rn��2�n��V"����b�Y���5v�p��}��3}\�k��"\���`������C���Qy-�q�B�,mB8.���8�j���s�G�����5/�����m�e��D�zg�(-N�E��E�3��]E���_�g���E�:���x�;��EQ��/�6f���r���"�����
�E@/�wZ6\|2*/��(~�O�A�Eez36���`#����Aa# 4�;C��3����l�6b����y6"}�)�ta#����������6"Z����%[�lD:���o��x�g%�W�w����~_N�cP�:},z<�q��d;N4��SH
`��!C�������1�v �kC���]b����C�����1p=��%c\��xd&XP�d@���
��
S����!c�U�;��^/�:�����������I}�[����30L�uh���%��������n5��B��)��T^O�
��.����3��D��P~��z���zb�~����I$���@IT5)?����
����'�Ne<+����ag0_���'EJ���IT���8z$\;cd�B:cd�X:cd�X:c$�X;c$�cec@8��S��@�h�ec t��)�)��.&���!�9\F"LL���B%��O�z�z3&9�J�*�c3e��A��;�h�r>��=��@��G���@�_Ot����?�����}�������-NAv'�
��/�Q[�o��c0�,�A�8�=�A�j��4�px����3�A t��Tm�w��� ����U�]���S���<xZA8�X����������8�{��z"l.^O��p��?i�BO� |p���p>�'��c� p���p8�O�p�3.�&��H7E� �������M8� q��g<v�@��F��@!�*j���.D>�0�����N����1����>�pQ�/�����fR�?���_��<
��b�/��{P������oD:�?t�M��\�����3WS��*��R�`u��W�h��"���n��������������X����;���1U;�;��}g�+�����w�����8���{(�Py-�=:}l�7�|-�����+�O^�8�lx���q�(�P}-�|Ty�+^�!��� ���> �xUJ����w�^<�p�h�Z�q��F_�q�A�p����;��i�����	u(:�<�'��\:sf+���+H�g\�O�X��
�����
K>��p�d�{�wt�y�����|p�?�{;��=����4�@�"N���QRc����]E�|��G�!�w�O�+���g��|V����x����1���|k�X��G��%�����1��S�H������������]��`	���#_���P�^P������C�7T��5<|C���CT�Pl
��q�����g���p�	m^x�!8
��tA�!p��[x���mc�!p��k����
�!�m�<�oA���?�0�����K"X8�d`����V	��d���}H_>� �/�
�v��q�
0\l���� \���j8;��{`f������Q�����+~�@9��w�Jf8���r3)��>�-���>l�A@��)4�y0��p�����r0<�{�,���VF8`�9����E[��_9��}$�AT�P��
����2���>��
����R8���(o8���=�
cq��!>x��?���3��J�8���p���A`�;g��L���J6"X9�t��A�xqG� p�D� 0�Ad��s��]���9�~��&��7��v<��q���|�
=3}\�g�����Qszf����\C���K�W�b'��{o����%���|��%`=?	��%.�v<<�(�t	@?0sW��=�g&��.���
Q��t	�����.q��t�����K`x�!�.�&��C�E��27H��o�/S�H*�%�Wf�k�p$�*�3P�#q�D�&����R|'����H9�ZbNR\�hG(J�#���xwU�H\��^��?��g���|��l`�H�M!	\��d�B8�d`�H�>�{e���\�ZX0����s��-����%����+@�K�C_�����9�O�).I?��)�5\hFeV���f��)��B3�J=[�[,�se��<������S����?���u6�hR,��9@{�����\
Q�#��9������7�U%.�����}�lgJ�l�6�����H�jH	)��(~�N������<�����f�K/�R�E�GH��w8���NhIp��..��[0_��/M/\�&��/�H��W��P`?�F����og1�����~��`������l��)@K���8-���	5�
9L�|�}w|�<�O�@�����<�
�	j�zG�a���`��	������O�����+�O���@�>��r�z�'��D�Q�'�6��;,��W(��L�V>�����i���B�S��!����K�$r�xL1$���[�c��h���!|����!����+LBPJ"��C6Mu�d]����?�$r�����D@o�x�YC"��<1�+����|-���pL��]-n����
�B"����l\!|\��B�|�D�]7)��t�
��!�B ��)�H�����)�>HG�!�m,�{x��WX����A�����
��Ao	q�pt����L,�!��_T�I��R�%������C��?�"q�!���8W��x�$��|���!x��p��)�(���g��',%�s�p�bn�o,�! ���Qy���8��$������9���W���so�r>��9U�z��;�������!x�<��+9�|����C�q���CH����9��r�t3�d\�r�������p��A9�d�
���+���S\v��3V����ma8���{%�](]���zCt07�o������:���������
�!��_D3�!���'[�C�sW��s��T�����)�oq���r�I����!x����|[o�]b8��0�C����������[Bt7�)�-�!�6'�,P�y��Nu���d�C��<D�DS�%��!�7O��ph)��T�y��T�y���!x��a{�<��b�?�����Zd�
�������j_�C�q�b�\\�|��=���q�w����,B���E�q������h����{BY��9?R�[s<�'�����?[���L��t1�6�.hNIz�dc�.\�-Q��|�q}S�`��X���� |�d(	�;�b�������r�����qf��<l`�}|��w���)�>���aO�q�1~��R`U��A�&B}�/��V�l�w��^���K����B��Qy	��'\h�PG�`�
3���KJ��	�>�R�)�|	�#�R�%?(����p|��)���pq������S*#��?�p��q<�P����H����
�����B��q$? r�����C��K�H�'VF�]��H��82�H���H����{bd������	.h��	�I���Ar{���\�����;�M�m�!�
�&��_��M@K�5l�^*0��#�&������&�6Oa|����& {�
(��A
��M��<g�3,�����81`���)l���oL��	>�;SM�l�y����	��3.�/�����	��O6��5Ci6���=s��/�'�rR�����
�����Ke<l�+Z��l��&x���Ge|��u�M��@_����W�K7t���&��WR��]!o����(�q�1
�/�/����U8�c�#�Q
��69�����	�v���_�;�M�@szB��LU�a<��Zzx��=!����Z�&��_���&�Ky �~6�_�qW�a|��ve|���	�y����& ���.�p�'�n��b[�5���B@��q�%\J�m��f��~|��+�O,�|��$
�+��0IF?�<_	���7(4�]�v ���a�9�7�q���;
�B���O�{��L]�����J"�3�WM���_YQH��Z����+$��KwtH������@����/4B��P!�r!y�B" �wU��\H����s��m��_-,�����K��7���a<hF2L��A�F0L�o�-���0	>x��/����0L����Z�$���q
e�O��$�'�}T&�7I�VS�$��C�W&������P&9��B��<�z}�$��93���<���$�6��Yq�0�o��7Lv��y��.)]�+*���2	�y��a�����2	�y�6W&��&J�0��Kt���_%Yx7��,<��K�.p�+*.!�������nz!w�)����=��MY�d\a�W�{���g2�"d[������Rb{C���M��E��szC��;�k����"��[�"�����a|k'�J@K�\^!,���w��"���Ia�"���X��6T�7I���a|�!��P���`� g�,���r�"�K�Y�E��ZNe�N�37�E�m�(�E�-N|x*����(�P�w��h��$�A��E�p2,z�������<��eX�S���(��a3�@��M���7^zPX�toH�K�/�=_a|\�A��K�Q�<_e|\�7�m���,����>.�"��|c��}��r����q�?�_�q��t|��v��w������x���������_�����O��)�1�������?R�d����t<�>��4e,
=�Y��d7���^��o��1��q��/*���=$V�Oeh\���M`�q��24��[�Ceh\�R}�
C��h$�
�����8O�F)M�y��;*�����8O�Iah���H���:[1�gCYeh���24�y�	#���?��I�(CSq���<D�ES�%�����9Mu�l�������!�C�'��T��3U:����3���Tv�5#9|&�m�u�0��@�"�[Y6���o���#�v�`Y����q��}����#���&{���I�9�?�qYe���G�����|��i%t�����|Y:�%>�
��Ao9��	��P���A%�N@��
'�N���c�6*���Y9
~���^.'���i{>s�P�BC-��fH��W|(��/n
���6~�D�d����Z���
��#���1��o�m������{}��/�q��P>8��j;OZ����O]�����,+��6���?_g�d�M�oQj9�,S��<�&Tj��d4�p��R�����*d����.!��R�cu���1��C9��m�|\��%��nr����(��M���}�DB��	��k9����U��mCH��uI�{z����%<�w"a6$��D"x�;�6zC"�V~�1=������+fC"������D���T	�9��/&�h�>�����bYq��X�M���<�Y+q�;O�VC ��+��8���%����w���!��d��9O
q��<�8�o��e�y�m-����]��y�	U#�����{:��D�����:O|�(q�atB�[0\�!�A�|�8��-g|��"TW��by��8|�C������+��>��J�ZB.�L�mJ $[�\���vB!��X�"d�XI���
�|K�����������p	t��A3oi�%x�����K�m�'�.��6S�a��H~�+��/�;q/��|pF�6\B��.;{�&4I��dS�5C�.9O\Z6\r��Ag�% �!�
�������|�=A.;O�A���7���I���e��! ���o�%�������N�K@�%�Ps�p��t�������	2�R6���_�Yj�%�U�OH���6�#F!�R���|[�3�)��e�n�^?=��<�������UHG.�-����B����!��-�X��,���'����N4w2���t3���#��f�����M`�=q��0��w��c��m���/����6���'���/(����v�`=�2�yhf!�y�Ps��9O�:�, �Ia��0yv����;'�7}J;O����<�]��y���Mu�N;H�4�]���J�, ��w2�r�x�a���E
=��a���W�q�S
���+��:�gB:��
9��@x���
�������B����
>n��(g�-!�B��)���,�B6��
���Jv����=w�H��������������"�����.,�8��dG��L���:^������P���� �����g����&�����P��*�sGh�J�B�R���<,�,��b���� 8S�Q��<�j�?���4��Ky �+����}�����S����G�y�B���VT�<lw�<LEu��7O��Mu��?o�7B�7q���`1�����)�k��`0�[��\GB�8�26����kBG"�I�����LuyXX�0�P(�|[�b�l[$}�M�7+!����'$H��K�X��%����q)�H�q��!��Z����<�B'\����t�������g|
��Ao���<��z/�4��P��^��[��H����2�J'���gJ(����s��N@�7��8M'�&�8M�Bgn���zC(��N����)L�
������	h��)C'`�	~�+��b!S(V�i�����P@�!��4�]R�����N����x�:�_�-����;�����4���4uOS����)n��(=.}S(��o
��Ci�=_��q��}��B��+'(�q�������A�_H��l;q�;_%�q��}�M(�8���@4�sL�%<�w�k�!<�A7r]u�����q��>��q��zK��8������J�����n�1��aXC����,��<l�`�x.n��$q&��q��!������9O���y�i�8��#�8@���Jq�������<�����������
���5�]��j`o���C,���C\����)�����K� �>.}����Ea�	����B:r)�X��`g�#y'+�����B�����+B2n)�H�J"��XI����$B�������L����
\�
q��a<��I�s<Wg=0	l�H`�-A�&�����&��$.94L������	~ T&�$`���s&��8�Z+��L�V&;�*:��Q��<
�����a��� n�0L
�D5�2	�o�$d�y���<Q�n-�1LB��<%�TwIy���"��7m*���<{�L�)��e<��k'�q���+���Nh��y.!�p	���% �p5�p	9,�K=C���z�|��'����t����3�#���,-��DZ:�#�V����Y�;�E���ta��<�
�)�0�1���a<h�)�a|[o	��0����V��Y���,)zB�1���m	wJ\�7�v�h?Ga����
�IR�z�8��( �!N�(����h������T�(��/���e���	N3�y���<�['Ou�!*��Y��C�Q@�C��4�]R���z���/�Y@�C\����)�v��+�_��K(\�n!W�d	�
�o�x\X=�Y$D�{��>g�r���p�sVn!���WB:�����]��Ae���]�Gn��������O��D����?;�3=#]`�g�����tAszF��L��� .��8��<�q�Uy`������t�K9�C�������V�
���8����<�	h�V��<�or�A�����)�goO!<t�xi�� `1w���f^�<Do�,<H�y�Z����<H������C��h���{�(����� U���jq�;�Tx�S��@LN|����9�+����s.\D��Y�[�p!�s.\H>r�B��Q���9K����P�p���l�R���;r �+W?$��0 �3���dK�F���t�����X:�M)�p�s
6\���
:�����0��|k�Qm�N��?	9��	�b�	M��	>��1��	hA���J'�'�J�����'����i{g������c���|�/�V5t���D�2t���;��S��Na��:;O�T���A�N@�*���[�y���'�Xt�tR:�_J��E�1��������)�p�n�����P��{F���=#n�UE�	p��J��l��32��gd2����A��\�P� w��<H�Ci��=_�rq��C��8H�� �/F��=~Ge{F��I�����3���S��B3y�!|[�\6��S��?�
q�/��XNC��L�.C`�a{FV�'�Iq�L/�hj�fN����<�/d%����q��'~^��bRd�(���� �yq��<�8��C���O��������Q��.�<���9A0)q��<DQ�h����6����B��	S�Q���u���]#�-!'2��!�r!����P!wgH-F���FH������4B�|�F������U!Wh���Pz;���-�v��)\��t����
��A�C1[.��5��p	����|��`{;���W.��8c��<4������L�������	�'~�����2!��_��&�%�����P.��"z�.!��c��<Ah������Pq�`���K������|�	����(�P.�y�����vJ���r	v������=_�f��uBg�LwvX�p	���%�#�V��tv��t���]�lB��I_��KMC������Z���3��C����C�nf�t<��7�6��}'.DTn������#~U��>v�Qd�An�Y\�d�Ao��AY��I\��Z�=!�*���K�3I9��
$����EY��E���:o�j�������(��T����F�����\B�b�Q�l�y[���.R�Y���C���Eo�����8���� B9��E���ED!p����{m���=�r�������=	9�|OG���?�m������bd!0�`����
�&"���M_`���%�%[WX�/��>�:�L�oD�&��G����"��
�������k@�k�Z�|�s�����}5|���+o�/�����O;=�Y��d;K��g��N,A�ao��l%	�Di�%h<���*x��4h���	Z��&��4�z~�\���oG���k������������4��q�G	�*q��4��W�4����^��=��LN���T�������p6�o��O������,g�o�w��p6��?����l���-g����*����S��BS�+�����K�{��Y���g�%q���lj�� �d8�z�w3��">�'��������3w>(e'8~
elY�\zV }/�6����"���8�����5'(���6n�t����1��C���K}����0\L:�r1��y����y��C�E(>��(�<���#�Cx�Y<�o��*l!
^�8�cy=O���%�Cx���f9����������6-�[=.�Z��
�����q����k<�.��@���9����x��42<���E�������{J�Ld�x8�<~=E��S��vTLWu�q�����D\������y�_O������������^dx<�����od�!�'�>p���(�<c�!|�p�S�!�M�<D�)�������&���@������E��K��t+����/��������F����m�����h~g�{K�zX���f$&�<x����e|{o���y@��\�����^.�v�P���-[f��y��?�;�g|��0��%*�1e$Mu��������1�gI?�N>��I��hiwT��S�H�-�5�!����?W
��� �|���~`������n�����J>�7s�h}�n<hC>�XI�~5���D+�~����l�7y��e `�a��E��)��/T��&n��-^���3V�!y��|���!|����_"��>[��C6��>p�9R�����<�mL7�LV�!���I�}�S�4��~��'���R�e <�!u�{�b�e |{o�*	�@�#7Z�G?��-��o��a�����
-��j�[=���o��x�	�@x����7��������6���L=�@�K�c6�9��/�S7bh�������2|���^����3�C����/���J2�t�����`�85�����z��E{����<���N�����J;�3������1���x)��6V�!y�J;����>p�rO�|�8�!�����!y�J;�����36�C6pW�q����]!�����,��\�
����`�vW�w����+~��\�B;��bh��E���v{��9w���-;��C;������)��z[h`��n1�����\�)��=�����`a��s��
J;���1��*��/�X)���DM��*�4�vV?d���D�eP�����k�_K�K�
�_K�y�`���61���z��E�rp��\���'��8|Z_hL�4�3|F�0O;��`���w���l����8����`����vH�q��w����g��C���vH����3�G�����}���;������
�JcsL�m�����1]�w"�����!�\���KG�8��} �����f��Y����qH�2$>�'s��0$z��%��*`U�
/,C�[�(�0	�9I���A\�k���C���.,q�aH���Q�~���;�X�_��������:���{�g�eHPK����Z��A*��(�Q�+�"�|-�_z�!A�?�h����iC�^Kq�z����E}K8��B��r$pF;�t`�H|`���Qd�X9�d+G�,��"��>JcL�}������tFi�	�o�)LI����8g��|s�$��3	�p���L�.*S�a��i�`�{�4�<��} ��,���{8�ce,��[��8�n����7��<�G���o�}8w<�a�U�'W,��[��hh��*�Rk�?x��E.��������paS�a����R,��/�p�rp����7�e��?�vg.�P���:�_���������R�r��z-�_��@�%����|�O��,����=�,�P{-�v�9���g����0�����>���One�m��C���}H����3V�!�����q�	�l�r%��A g4�9�����9����)NKv�d�9��a����Q��{��i��C��<���A]l���<����p����dh���oL����z��T�x���O�=��D�}�=���s���:!`���JNu��Eo���S��f��&�������=���|I����Z�yQ�����S`B�'4�V!�E�{}�|��?���^)�� Yb�����z��@��h�0�N~�H4���N9���� �p���;$+��'��J8d���w����(�r��P>p���vH����r��N8���/��-�C:�:~C����O6�
�����xs[����w�[����b|{o	t�:�#�H�:�����[��C/����G�`�S��_����:�R���U���u��?�>��u���!.������I�D�: /�3��u�WtK\�`Y�E��|�: ��Ew�:�wQ�����`��{�W��i�{���x���^��>�gN�K������:��G7����:d��3�c����������8�/��>�����Pd�;c�9����X����I�u���a|��u�r�!�z���s�14�x���:��C6�a���{��e\��8\l�vw�:����V�:����CY`o�s�:��������y�u;|G�3�@?0�@�u���	Z=���J���a\����a���&�u�11^8nX���M
�u+�4�3��/�Da��?3�;@���"�uV!�B�u������]D��h�{���lX��J�u������w{���(�p��Wa�g,��q�����o	��-F�u��Y�t��nc��"yW�I���S���_�� Dg�uH��9$kL'3�%+��C�>��[s|@�7������TL������]0]�wB������!�]��x�I� .��9�a���Ig2�������A���,;��?��v��v�G?'�,;��j;�[=��h��.� ��������P��](������_��P�(���i`b���8�b�����%J�k��BQy-EI���P��BS�+��D�_K���%Jj�%�(�H���_��A���'.�P���J�x�L�!J���(�����@�$�X��l��n�0� =0A�cNQ�:���N:.�]�>k9��ok%L�p'LNK���`�9���3$X������f\T��F�>x��up�}��w�M����D�n���["A���o�7�.�}��?)te<�rK)6�GO����>�V�eT�@����h��� >	��z�>�}i�-,Q�c�����-��/��mt��?z`�;Y���{JK
�n)������Z���}@��M��i�{e3vc�[R���� ������L�a|�A��'�*��g��3N`|�x�a�g�������=ce�����36�4�}���� 5�9�[U���lc(�����Y�R�C�A��!��������]�� �>x����������y�}��wD��>x�L
�e|{o�/x�>��b�z���>x��E,������A�Gk�USn�V�9��[%�w���q��V���f�UY����)K9��y �C���"��EW��v�����r�����Z=~5���EC?�(��U��@�sK9�wA 5����F��zD��j�"�2�G?um�rp����fNR���]0���r��(8~������G���m�p�r������!w�������!Z)�lhC9�C�k��P:���o=l�&�M���b3�-��a'��t�����w���%��-��[���h,���3�}my��z����
������z���r�'�
�5�������`x��T��;���Icy�Eo)G��2�4���K����|����]��
�������X���\�	�E)�o�wQ�my����'�w�Y������;x�}0]���7�g���?�x�M�|�����`���N(�����rml�:��4�f��3G|�0���C�1��"w��u@s����!��u@�	���n�h+�:����ik�:���~8�:��;���a\���
���;��X��`L��3�Q�����6X
��@���*^���X}�V�Z%��QY���a��7Le�Q�nX��L��a��n�[O�u�>�?5���;s�����	�*)w~�w�h4����um�{��t�|���VtGq��}������!	���t�����\`����`��v	�;d����l�����y��?���t��Q�r�!��;dCx��K'�l`9��/~$�\�2�3��:�C��������6���w��������_������w��������o�/�����s��h4��tQ����h�{�9��U�yE�x���-�8xz�R�q�0��V�q\���*�&N�OUd����Y>�|c�9��
�|���5���� ���6s���S��7un�$�o�����v���|V��cu���Z�Re��:��|�v���������T����
�W	���������ZE�G�s{m��k����U�
!����]��l}W����.��e)�}`��m)���^�����g���n����^��B��q��z�t�r�����xt�\�����{Y��A;��Ht�����5x���G@&w��nO����<(����
|�k��$j����bh��5�^���w���Y������q!�2gb�"x[��O��;!�%�U�w��A���\�����q�A4��q��Z�4���x9.@��,��K�>wv9�f�K�4��A��fOl���Z����D������M���-'V�9��\p�qhQ��9��s�ZY8��m��s��X�n�����4+E���6k�9_/K�.|���	�ts9������o����s=j�g��+������������`/4E�B��Vm�3�/���&m���S/8~��*^r���U�|c�w�U�<�
c�xy�;F72���=�*uF�������Q�|�J�vR�����a��_�������S�+7�Z�+7�Z�+7�Z���hs�Su���\�x�{;C�B��W�pt
*GF���g�����"���(^~t�70���o�C���[����o/?����j/E�R-�x�FW�x%#_��$G���\�����Z�+7�Z�E��?����x���6]/[i���qw��
����*^(��{�Z�����x��!�z�
�����`��k�&X+`|�p�N�\���5u+������������|a�����c��*3V�+�9��"F�Jn�����I'y�Z������V�s����[��P}+���%Z������*v6��=7�^/+��z��8��F�J��j[�6Vm+��/^��m%���m��N|c�-4E�B�����im�N��B�����h[2Q�d�-�9���=h[���F���w�UFF���m+�>������8Uo�-��DK�m��{O\9d�-E�F6��J�m�V�m�FV�m��V�m��Ws!d^����V�B�58g�m���6�����g�-�?S�-]��V�m��k�]���|���j[��Z?�n�-EwL�$�m�FW�m�FW�m�FW�m�FW�m�FW�m�FW�m���}=2��h[8��
��p�qT���5Zou})�mb�-Z7��4����?�@b�-Z�]5�Mw���Z��3���i�_<[������������(��B�D�mw^�w@��.���A����Z�6�]:\���]�����l[����Y�K�/L�k}W>t��C�����+Z*��wH�w�����qg���h�5�_�k�-Z)J�7������.n������[���,;�������+�.�D�2?
�)5��Zs�����d��������i���p���x���Wj����P��������0_�Y��NQ�\���0`����f�]�����k�3;�2�����D�3`�Q�`�3��?=T�3����T=�a*�,�Yr4�D_tR�s�z�i�,9��,9���]�z��g��JW�U�k�&����J���������z�Bt5����E5����3z��g���Q����Q����Q�`�^sY)��,9��F��
���N���g����g����D=��� ��g����T=��5����g0��Q��VB���_C=��e���HO/�		��Jj0*��P*���_�|�/A����-����^�%��
W���6_���ui���<������
"�Z>t��/G��%
���{��������0�U
*^�-����{��j�{_U�|�H���Y���t���������.-#���^���S'U�^/����!`�*
����Q��i]�N�c�E���|c�����|{���Z]��f4��y�����2��o�O����|��>lVW�c����m�2FW�Wt�d�x]-7�Y]-��j���P�u5�����������Pt
W���T�o��W��u��������e���hs$6h������m��Jl(��KW�������1(��-7��[n��[n��[n��B�%6hy�-7��Nci�
WZb��5z�Y_��q����Ph�W[�
��x+���J��Hl(���eh�E`�M�������]NT�N%��qr%6�q��E��yk#��� \f�r�W����>k��4_��t���6�W���Z���Y������q*�-;�#���bK����h�M�����t����FwK�V�-�	���>k���#����g��[v,3�[���	$�@ .8[������v<>�j�� N~�8��;v���q��,-m+]��7�]��0�[�1-"���fB8E ��sB9��oB�oq���>v�Nt+z�[������4'��o���
��|'�e+��_L)��� J�@���@��y�07�Z��@^ �
�V ���V D����-=�ZU���mTA]�-1���)e�����TN�*��k�m�UQt��+(FD�5�QYU07�ZU07�ZU07�ZU���1�`nt��`nt�� ����l���^�VI]�:���8�F�������~6� 
��MbUAZ	E���(��S�
��`�`����}MM+��O���+�+!t���v��?���v�Q��S���^��l�@d����r ��=*"�����Y��>k��g�r`:����Q90}�r�[z�2w��K��#��{h����D�K7�\��l��-X.u����.+�Bu�l4�^>t��-�r�[:p�����D�F�^`V#�@S42L�!`Z#s��QD��c36�����C�)���������0�F#��w����X����$Nd[���������o��s{�b42S��hd>��hde5���j5�dd����V����V��!d^#��v�F��k�����Al����\E�����E`w�y�B\�����=g�kd���SV#����K?�F���@��Yn�Yn�j5���j52�����r����r����Pt
6\��0I#����n42��g��F�CkP�1
����i52Z��B������V#����F���������/U`�*7��ah-�C�q�MT/�Q���^��/��f�O�~��s����������*p�������������/,�N�)��y%���
��L.=��s�u�o�:��m�.���r�����g��V����d�n��:���Z���ke���w���yE��}��YU�MQ���������r��+�<�U�C�Q�|c��Zv���a�(lU�\�&�h�j������_��7Or��r���oO�'8w�j���J��Vn���B�+�2�27�ZU!��!s��U�Pt
��Q�pt
*�F���5�-F���5�k������KhT-]�k����[|�h!��=�]|�
L��������;���
\���
\���zh��P8���r�X+p�Z+p���V���F��q6zE�\8���!=h&����9�!Q��`.�����P��[F[C�=����+ZD..�R�A't~������_.y�R/�P��>k-���n��u�����I�W����+ZK�����+ZK�4!�������A��O�0�����+}U��/�j�vG�I9f��4rL���b��VQ,XD���lD���(���X.��4������,Ue���P� 0[��YeX�W� 0[���(c.r�2�������nJ�1{Gl<�������Re�{O��n�1`���w��*c`S4U�gT?TK�FK��F���2C ]��\�2�]�2�+��U�kP�Re�:�AT�1]�U�Fs�?R_�1]����2�k�'�����u�T������rXrt5rXrt5rXrt5r��A�Q����j����j�0]�s��0GK�*�U2�h)Y_��'�r�qO�0Z����6�p�+��*���/�U9��p%��a:z�����AXr�/a�Nc9���pR���=�K6��"��C��-R�
��z�.R���),�"�Ah��!����|�����R�A�����Z�"4M\+5b�4��f�;Ee�����X�W�,�o���?k���?k��,�"�%;|��K����B�!���yYq,�6��"�%w�3�28E C��@��\�"�d�1�;�
d�=l#�y�I�c.�'�j�
d�����0V �-�-U�@���7��+����@,i2Yn��B�2��d���
d���
d����Pt�2]y���uF�R�����(b2?�n�L��|{M��@��k���
d��~g�S3�����19�Z�,7�Z�,7�Z��@^ C��9����19�Z�G�`��
d8���T ��5����Y/v+���5�!"���b^��*���r�Q��he(���UD���v�v����nd]}Y����D7[fC�f��*��\���n����N���gm���Mi��|�fi�	�Y��U;K��jg�����D��th��t�����M\LT�l9��+^�z����A�����Y�k��g���g����e;�����U?C��:;���w�}��5kU���UA�6���
����z��q��������#@�S��(�"]����Q�\����p�V�<���� 0�(��Q�<��=V���A8����7��j���\"a�>�@p�V��m2�"�)������':}�@.������ TV���V���FV����V����V���W�����>����kP53j_vt�j�o�����/�\V���V�����������+}����xQ�Q�Pt%t�/7�Z�/7�Z�/7�Z�/7�Z�/7�Z�/7w�j���]��#�;���SW�;d%s��>Z�z�u1��#X���}\�4�p(��������/����N%>�����:����:��I	�M�S�B^�9�
40g�
���T�K�V/�Yo�"�e�i#���Ze��Y���-2^�A�����yL9����r�rEZv,���8,����3-]!��������l`�$-X.IK�p�2Xe����!���Eo���J���]z�.�W�;�������_���0������0]�������s��|c�T�y��V���wT%��_��h)f�/����������o�
����_��~#Z�Y��G���-7�Z�+7�Z�+7�Z��@��
!������ucF�B�5��V������pt
����|_�_�h�/?�cF����{F(��o�w"�Z��G�z��(��:w�t���r����r����r����r3W�!����z���Pt��/]����_>�Wx������U�F��C�>m�/Z�����Ph��l�/Z�����/��x]��������*�A�	O�~�9�E*)dC�	- �����L�_�:��s��=�Y	�Yi��cS���CU���T���+�3n�����I'y�����Ku+{�"�����T}��s�j$i����$U��uj�n��d�n���n%�X����mg�3Vm��:����g��V2��v����������ly�)���-L+[p����c66����ly����l��������R�<l��t�l����fF����gz!e����'hs�l�����y3�����h9F��
�V����V��
�V�B!�W�2��17�ZeEW��#���z4�l��N��e����%j]u��L�;�l��z�+F�B���j�([��~'��ZeE�]�([���*[���*[���*[���U�r��U�r��U�Pt
������([8u
V1���3�`��*[8q�^Ev]������o�
q��*[���W�|��N��t�����'�M]r��m^�l!��
j���2�C�5*�v��\/C������P�S�Z���Z7"��k�tB�W����+}�Z���/�����t[k�W�A�uc���uc�7j�����V��1������J\����w�i���
M���Yk���Yk���YkX>��d��cT����4mL7��d��D.=kO'o���4�\���bf�2`a��3��At�S�29E,�H)s�7��b���PF,s�?l����O�2��*��o��F,�{(�y��:s������#�� 2}�Yrl5bYrp5bYrt5b��A�O��Jt�/=���d�2]�uT�DWBR�F�xG#��o�+m�X�����@_z�k��6bYrt5bYrt5bYrt5bYrt5bYrt5bYrt5b����g���U(bY%ue��J����UW����)/#���JX\�2Z	�R�2Zw��(e`p���'�� t�
����5n7�A��������,Z%������o7��a)A$��������������K;���l�"��;�Jd:��D��2r�����D0���9b��,}#�H�>k��g-"Y���H�-"�
�����Zn7���e���,1?���������CjF*�`S�2LKe���<���R��rc���#���H�+����<�U��R���I�9�R�o�A*�o�������F��c�2���J2RYn`�RYnd�RB��2�UCF*C�t]�ay�He(�����Q��������E�>h�j���{�aU3?��/����h�E�V5�7���*t�Dh��6�j�o�����(��:������<,9Z�,�Z-)%f����f����f(���Yn���Nc�2��f8��J[����5��j��V��f(����i�����������W#����x���fh��+�D5C�D����-�@{F5�_��DAC�
wlT
A�e.U����(h:AA��n���(h��V-}������t����-��O>���NkmDU����x	ns�\_��J)����lh=�j��l����l����l����l�����C�������!�p���l��ZU�l�s�tw<>>��y�����bw�}9�-@}���3y�����)�����.h�;���.h����-�����7�t��.��8u�S��|rz�����������
�e����
�05kUG{C\lnUG71w����>��[����5Fu�-�N�SdUG���L�����*]��cn@��#B�U��XkU��`kU��hkUG����R��WB�GT4�z��w)�z�kn��Fw��3������M��������LG�;��_�TFw��s(�	Z������7:Y�17�Z�1�Z.9�cn���cn���cn�������C0�Z�7�G��F��=3�.���~NKT���S���fD�ZJ��7"d-�
�F��������B��?�����>�T��=�~���Ov���xlX�k����7a5U+������Z��9��n��z���u�q�T3�g�r���w�Z7`�x�����S��n��r�[:p���
,��e�c��
G{���n0����6A�o�����#�\����%/������tXS�0Z���m�B/��0}���C�^�=�Vv�
��Z����!`� �Z�k����
hY���r�V�{���>�5WF+��7��V+��w��g�2��(��Z�o�=A�Z�����hi�2���[���F+������V�i�V�j�V�k�V�l�V��-_���������j�	Z�o���w���w����>�/V+��=���^2�Z���E���T��������U�^�f�!����Z����Z����Z���P�w��Ml�V��i�l���je(�J(��=�������i	�O�2���m.���+��V�R����=��it^+C)-s��he��3^U'{:�$Rn���a�O��t�ha^:�Jc~�
��*���	���A�T3�g|�*���	�X��U���:�Jc>px��4�l
���g�m,���)�����#��78��j�J'�E�5�)���s{n�Y��z�#��FK7��c���^�ls��n���+-����5�(v���c3+�y�)��E1L�bpJ�J8N�ZQ��r�k�t>�0�co����|���pb�0{C|cZ!���������7co#����M���[<K�����
a���[6�a���
a�Q�
a��Mu�9���FX+�%#���;;�K�|��a���
a~�%z�!��>0�WFC�&Z!���q*�
ah=���V�C-u=��rC��r3Y+���Z+���Z+����s{Y�T�^F
{%�n�0�g%Ha(
3*���6Z���f�\�i�0d�MJ��o�w���Ha>�'q����H�'�F
Cn� ��O�)�:��)A���S)AG�:#��q<,z��7��U��v�o;�1W1��s��K��dc��
���E�u�����6V1,�Z'�l
�K�=�C.6�Ja���ub�9�j��������]B#���q���d����-m������P����U�1A�u#�%�������FOD 16C���"�YEX�/s���j�������y�"EC;9^��r���!��1r���c��Ts�?K+5N��������i�����9�E�a��~1rXr4rX6��a����a0��r������0x9=^Gd�0��q���a �Z��a.����0r�7!��,�F�F�f�*��P�{���2��a���a���zp��FK�F���KNeU[5�1fYa
B�0��|Eh��%T���t]4�&^+�bLi�K�T��(D�F�@��qV�0`v�1� t���"�A�(+�bX�AD��a�M�0k�����0_���gf�E
���{"���x��wEx�"�e�X�0V��r���2���M�:���\���_#����H%�a
B�Zr�U
��
�^�����j��g��'ud���,�"�%�F���Ma��{~���1��Hgl�t��i����o�(�a�38�������^�A^�����<���<��q�e4;KF��?�+�����{�X��h��7��a+���_D +���?T�E#��FC+�%#
!U#���0�;VFC���,9���P-t�2�o��w�x�<+���6NcZ��>�}�����\t�2�o�7f�FF��?�/���ad4��2Y-7 Z-�Z.92
����"/���Z#��j7	2���v*�������@���*��q���22Ji7q����;3w#�������:.��=U�������/�yS#�����u�����3�t��u�������@����������k���2��k>p�L�58����������������
��,{�*�%�wS�0.G��k���f7*��0[B���0�X������������%GZ����$_�_;��1U�r��m.�
�w�
���%o8��|`�7c��/��x;�%��?��M����#��S��)�$]�Xo�?4C�K�gL�pJ���1#�y�F��"�����|c��|{�o��q��
~�'A�X���w���[|Ct�����}��F7���~x�G�=��������y�/7�Z�/7�Z�/7�Z�E�h������V�����6��x9�j|�/�{�Y���>mt����{��!AU�h|>��F7z���:���2^~b5>E7��@R����V����V����V����V����V���]/�v1�;������F���q�C���g��K���'����v]��E�V�C/3����z(q��q��J\��i��P/a)A�+��C�����:.}�Z���R�������������>T���I��N%<8,:���[9��������7
���e/�Jx�3V	/X�MKwk�7-���]d>���L�F��=�hy�'�r����%�.����Yd��3�\��0�\��U��nW�����������`�.4E�B�t���.���OM�t!`Z�������ty�����J�o�xW>�ty����Q�<��	�(]�@��t���\�U�|�oE�*]��~#
Y��G?d����j����j����j����j����j�.o�K��U�8�g�.������-F�B�^G�ty��3U����Z9U�|�/��N�t��%����_�
See����j����j����j�.y�!G�H����+7�Z���F��b�t��8r�(]8s
�$T��O\	��%�D�C�t��5�[�%��MtF���)�����x��2Q�tX�i�B�x�qa��\�sV�+Zu.�a�A���U�����N�r�!*L������(Q���E�J6��\���r��	*W2��\�����+������U��tg�����l��dS���l����i�-�uK�[h'�k�T�B���������[�*���u���bFx��kAw��J):��xtb3�s��:fu.��\.pFEfu.8E�r�St.`���3:���!������1���\�g����=�\tE����tS�������������j�s%V�s%GV�sAd��#������������`t
���\�����:Wzt5:��q=��\.����:�����lt.`q��P�s�/�����`t%�E�������������W�s%GW�s%GW�s%GW�s%��F��D�X6�:p���.":�����s��5~e���`�oE`t.��7���W����\�@��F������h�xl�o���6�/�?�:L�/���L��|hi�����Tz�C���/�G����d�xW������E�q��hb8.�M,X4�lS�&�
,��pauW*�V�.�_:._��/M\���5k��B���S��C����z{9��AU�����vi~o�x^���2�vi�%��Z�D���Y�Z��6�h�����}����M��0-�!`Z2�-� �!`Z2��s$39G2��o�e%3{���e$����7��di�3k����g(�<�� h`�������0V��D$.p����R7�0��U�i?3��1����&��&�M��\"3�����"3����5������Y�Y�e��Yg����V�GfYwEd�����x4�VDf��?%J�w�3p�q����S��"+d��}AfviX�{�2��������<���,���������S����#���"2��+"���"2��U{����WW@f�[�7 ��Z�/�u�g=��������u�HiX��j�:d�S<��>�0/�~��N`�OuIlv���p����V�k=�V�~������NZ���7�z�UCF���������)��A��ei����p��qa��,�����/�,�����e��f�/0�����#P���@����Z'`jq����o�B\��)2,��=�U��@k�`�V����V�7�����@���JJn��;�5&k��
�:a�e����NX{����D�1�X����\�����T��xG���/=U�U`����H�#X�0>GF��������W1�"����!X+X�Z+����Z���"X��+���]}�����E�g���+���5����1s�Z�����#~o�C������k���y�j#'�$kYD�V���$�:k��u���s��\�+�5
��k<�:�*����EU`�[��U�����k����`���������e,��s�	���~�\l�eL4z.Ri����:�u
�����u���/��� h��A�f41i��)���ga��g\X��V���=�������?�����#b�`\/H����B8dW�f���>����k�68�����F�6���v��n{�`
��PX�A�u�/Pe��>��C�������}��>�?�����o��w�����Q�G|�M$���DpGE�.,|\\�]��#�������������`	�����nwL��C���i�9���x_*���x��q>������W
K���N�wYkEp��Vw��=,-������9�>\�����//_��^^�����IOdx���M������7���Y��w���zhnZ���$dx��>����e�^�h��e�^�h��e�^�h��e�����N����X��d�UG��g�~3�}#����������;��2���opdx������n�����1���wN�����.���NZ�|;�����uk��cnZ�f���N`v\�����s������3b\�.��bv\8P�>�679�@��C-?��4��s�����i��?7-�b t�� t���j���QacrZ>E��#�'���\k�mW�.��bti���N;"�"/&A^��]��	����W~���	���	gj���1���y1�K�@��������.�����.@���}���@��?�D^|�9��W���_��5VD^YgE���VD^����S����	������~
�D^o��C�h`�B^�X�����~u
�y���h|q�����m�yu?�O:x�������?B-k����F��+k����F��+k����F��+k���x4"�����%Z���%V�m@^�;,"���M��������!����FO@^����N1�l�{U��
zu�*���>���Id��������L 
xqa����+�QrR������/���-�p����=b ��_i�A|��(�>���:����4����\�+��������������l���P@a�[(W������X�n�:c;�7����\-�Ba�[��NZ�e�Fa����b�0*�@a����Za�Q�D�W+��0*AaT9���	��f
�Q�g�W�0��|8(����-"��PX�
W^(���������;�T
k�_������PX����v������as�����Ba���m�h���5g�IvW�_������~5>����2M������� �����'j�|5���h!
�+|m��m�_a��vW�_aw����
�+��&�3,�5���hm����U�T�5W� �j/��yh���P/��^\#����:��yhD���sb�����C���?K',���/��1Mntyl�����J�����1/=�Mo4�/H�Lk��j�+@�_Z\�
�a�~��ZZx�|l�\�y���k�Q��t����d���1-�/����US7��)knyFM�m6aU����+��k--<0Z~�
���F����h���ik�����l��u�6K��m��#`i�����p��1�HYY}�9�4��$$��1�'c�4�}ai*�*���}aibT����;#�����}g�4���T�K�+����"K��}��Y��xXZ�\��e�YZ��>K��0v4�4~���,���q^��1����j�W���]
�,�G�����j��t�__�j����b�2 K�z ����n�'�h��,-�������,-����������X?�z	�4���Z���U����:k}��
,����YZwq�_s��uWc����	�3�l}��������f��������L�u�Cn
Y�,-
�,�����fAZ/	��I'��5�~�Y#,�*KT���,-<PYX�PY����h���������> �����g�
p�I�g��YZ�Y����������������������
��5��g�F�q���n��q\��.��vGvS����l�u�64��mh��#�����	h��3���I� 4c�_)Fq�@3��d���1�7��
��w
���;m����}�}h��/����Y������u�>4�,P�>��S���sW��sW�4��x��@3~�u�Fh�c��HDh��/�LL�4�~�����x���� 4��^{��t����;*�*h��@�fa���O2���@N4�^]�e���:w��Y��"�*h���������1�����w= ����������>�%���k�q���������2���-*�����{�-�9�u]g�5����60��s���:i�uF�K�yeT���*����e\R��i��h<r����D��~�����h\8�:�0��6�z�	���g��P���g��h�e*����:�P�;_.��=R��&uh���i\8P���}d�ai7��������E����O����?�������?������������?����~��q��4I|�=�~o����Q���?�[���#�S�������~5�����%~���v�b��X��LXOv�d�z�+��L�h���;p�6pK�
�
����=�-���15�%������6pK�K[:�q&?8/N$pK�D/={�\��rq�N�o��9�X��2���-;s9p��]�8���U\3p��]}n���_�����/�[�����������J�[v����Bn�����[v�j����+r����e��b4�[f��e����2{wEn���=8.~wn����L{+pKn���4p��Z�R�����/9�-��y���D���-��y4694��)�zc�\�t���_
�k�����N:@#;i��hd'����@Q_'-��lWK1���V�K��6���*�}\f|E%�����#�w�~�~����d��C'L�@'��{T_��s���b�ii`���6�[��$w�����z�A���1,\�|]"C����(�������dW�$��&HX'l�0&���	������t�z��0&���c�zU�0�/������'��k	����zH����e�&�0�w#�$�G����I?8�:�0����L���>����"	��}�9���HX�����\}����7��u�����]�1o@�zwU[S	��z�� a�]�����x�9uj@�:wuSn�k�tW�U	������#	�<�'a�{+���}�uW$a����s��3@���O�zw�+�zs��^��j�0n�z1:���Zd�F�Y�������c�l�� 	�Y��j{������~u��������r�Q��v\���2�;�Sa�
o��
�F���6�U��
�l��/,\x�P�J��<��
�������8W�o��o]�H^���N��M�s:��2�;�1V�?~�67	T�uo�vE]��AE]X��V8�����V���k��qq��q^��f�^���.��kq��������Z\XO��k1\��Np-���Z��Hp��	�*��X����MX��\�����������.��N� [��yu�����?�����l�(�A���Zd��@�.m������������"[��j^Rd��FG�A�f�*��A��X{o�-�}�n@��������Pd�w�w��Vd�wWg\�i�����r�@����J�k�����J�k�����J�k���MIW>�����53W����l���j��y��w�G� [sku�V�7�]������������i�/&���3(���G�\���s���^��@�i��^��=�������z���G��
V}���o�Q�u�U_	Xo���ni��k>/�Y�Z�u�o����|�k�r�E~3����}(ok��,o����WJ������,��kX�	G�-�O�9�����K�N�[����������J��5�mV�,ZKW6����<`�N��fL8P���`\8�����r�1�6���� ����3�����������Sl�����#6�1�JS��l��������s$%B�f���,����:��Y��c��^}l���?���W���*>C�f����Y���s���_�W��g3K}�u���#"g������q}6�	#8�\Pl���S#��;J�u����u�*>���
�
��)g�Y��fs���8��U�6��r����l��*�;/�����Y��F��3��/NE��*��r�R��NZFB������RF�������[1������#0�t@�����K�02&ad�������Y|�]{"��rS1���QF���������9�&��`
���.�K_�&���������Y�qG���{�����K�6�>Y���,������:��������C���������F�Y�k6P���:�F��e���o{���n���g`��3��2���YoI������m����;�����x�9�0=1o��<�dD��fA@������bd�����5���FXDB�?C|�1T���1"��d�ctW�#����ac4�F%��������Q��/[����P_u�\��W���Xc�O�**5T�bQCE&5TDb��_J5Tb����xXsCW|���������k��"��L�v�5vjDHX�~� ����o���;5�f�����V����<e�-��H-YsdnX��Q���%k���Q6z(n��r��Y� d�;�C���E��{����k�vR��y�'���c��������}�X���5��X�bi�*�(��pX������<��������&����aa��{�������l1�����+�~��i��|�9n�����exv�����G�3���DS{�\G4��1�u������>�p]��=1�uDW���n["�#����g���%k����_|��~���>H�
��1�S#5��J��ww�$^��P��h?_#��g��+�,�LwT���p������5�~m[�"Tp����Zgu'����:k���s����������g��v�� ��:d��]c�z��]c�/z�`��N�z^�v���E����T�v�[*b�����fa;El�����S��?�Al��"�k��.bk��n����Z�v���;�[�R�����j*��f�x�!����9MB��-��=$�>�k�6���e�Ul�Q����5��
�p4�����_o���vr�agt��)J��E�"y^�J�~�E����:��� Pi������q��+�����@�Z\�{�Ys�e�X4.�b�q��
4�Q���mO��24r�:3�q�>��������38��&��W�������ZL3Q����\��F�V�kO;#��24��i�H�3ehtGd������c"��q6"
,�H����e�X�|�0�"4�'c�,z^.�]q��,�0����"���"�j�}��x���aq����n�,��Sq���;����N�"4���*B`Y4�z�^dY�N�t",��S�$
XV���{5�,z`�O�eQ�Ke��"XV�N�eEo�����YV#����NE2t��^�eE�YVk�"�(������d�,e��X�R�=%���K�������GdY��>��E�������D�h���W�QF�UZ����b���3]�^����t�Z��v�'d���|���
������P�����>�u���UEFu���C�����^	c����K5N�O��f+P����c��~��Mw�z2��t��������z���������>�u�=bX�p��[,*���,j�q����`�(�y/��Eu��1��h����-�n�E1��b��wD�E��aQ<�F��bQ�8�|�uU<�%�bQ<�%�X?/�FX��F�������aY+�y���:a{bX����0&�r`Q�������0Z����U�E�v�Jg�~3X����)T��
����4r,���^,��S�~,*k���:a{DX�N�Eu��������n���+������S��g���r��+��Q6��
���h�X,����s�Eu�\FuR���K
�V,�?�;�������gU��QW���:��Ac��F��WUU��\�4���kUU�5WUU��O��yt<��y�Ru�~��NY��[�u~-U<��*�|�4q�QK�e��Z�n�>������Z�NY�K��a�l��:��Uoz
���J����J���l����lW�*{�(~�u�)\W~��=L�q��a�7�&{�?����]�EU�N�X��[R�t�\`�F��XDW�+���ncac`,�#2�><��`�X4���*&�sA���"��h�/K�%���yy4�c��y�X"W�uR�X��=���<{�W'�c��M��^L82���Sc�]�7�B�����'P�*�����i@�X4��K�E�����c5v��X����0V�Nc5�>���)b�F��XQ;E����=�+k���Z;�X�j/�*l+l������=��/�?%B��x�n��/}�%`��K�O4w��5	MC��0���S����k.x�(�Uz��e�4��U��W����.xW�/�Yn��:�W�'X�*���W�5�j��*��1��������t�=�@V��d�_�-`:����PV�<��+o��1�+}��9`\y4�+���\H�QN ������W@ZD5�%���+��n�2����}j�Et3H��#Zi�a���E���E�E���gi�K�{�
����W&�GZ4�OF�=DZ��\�����}�w�'�������j�}��x���a���j��GZD8���!�� -�+t��H�9��^�EO�����~7� ���~52���h������l��_�R����+�bq ���"�j�}��SDZQ;E����_��SDZQ;E��S@Z������V{7�\H��Y��Hk��v���K3H�����������weUf���3e��x����j���W��
Go5�����2��FYN �J���V\y����
�:�[�5�J���Vz���eB���u�B
���W�9q��(��Uu��f���n,�^3��p�u���+|�u5�:��,�:�v��\�+�|Xx�ru\���������~��|<�P~���<���W��+.���Q����6
P�h����5�v��M���t���#�:-(Gt�����>���p�r��%l�h�
�P�H�9�q�h�_����h�
��P���{�U����b�]b�x~�Y�J�5���K��)B��M��]�����\c�����vj��J�)B9g��#@��NUnVP.n��&v�C��N�"ufT��0'�r��)B���"��^M�E��\�r�P��S���k�T\�y�y�S(������k���P��d�oN�H�r�����	�\����h�/u��j��o�]�����3��F�����NH�P�3!�����r����@�F9Ps�(����\�,���K+�?A�r�5�o������{CV.(��sA��r�����ab:���h����C���1���[���[�����l,j�WXw���r���n�}�-�<�%fc\�-��
��cQ�-�CW�u>��u�L�5�va��0�F�.,#���_D7SXF�3#�����J�O32,g��2,"�*,��~1�� �����JW���G( ����9+�����V���<�a5�>�j�T����;�Vc����a�v�����aX4���q��7�Vc��@'`X���1�=0� ;�V~�$�����o`X������0���"���)2��N��j�T�n����V��"�(�����|��������h���L���x��S���R��V��z#P`X4��)��(��(&k��.����;SE��
���&��������8���>���LW���q��I���ze���&�l��O�����6�a��>7]���I���L���x���`Sa6�}r���&O�yE�\*z��Ke�[\*���t������>��[���\�W�����m~��i�f����`�(������t��*��hs���4��&�2��b���]|G�_i��/B�x�#���qv���F�X_h�:l�(��������G���WX�n��Fu�g��N��Q���m;a{rW�M�Fuv*��hTg�b(�F�v*�&������h��A��Fq;�[s����L��i����@�fv*��h��N���Q���m;a��a�N�Fe�hTg�v�C&�����=���
���/��|�+�J�M�Fq/�?�5���m�_.�I6���K�o�FuW����!7��W���NY�F�*�NY�WU�,��
"��-"��3���QC�)�5T�5�����{NV5Ty�����+��OP�������Gc���Vx�.���@c�.JjM56�����i����NY���a\y46L��jl�>AUc_��Y��Q��m
�+<+��������*��5�k�[��kQU����u���nk5�6�"��Et�uDX�G�����Y������~rJ~k�7��
b-�_������~���G�E��������v�f������{������������+j������:a{�W���$/~����>0���
��xD\��=�;����q�H��]�q�X�:Wc�k�E���o���4[��wGB�fW�z>�j�}�������v��+j������=�+k���Z;�E!����������{	\��T���n�K��*qM��bLq5�T�l�_�?��{K}U�����7L�j���XE�e5#�+��]���3p�.��wy���X�!�J+��+�o�������m���?��S�����v��G��.�et�.�+���?������/��A���
�,`�FYF����?f�����+��{��?`�t�Gk���|��<�v�:R;,<A��`Z�����}[{G�ET#���������F��_������/"���"��;"�����t�'�o�/"�������~q��~�h?)�_��<~�qD&5]�a^�m��|^����b�a���j<OlQ����W��>�j�T���!��x�]a��E_x�����������Ec�j��Wc��W#���)�@�����,�W�z*I+��S^����+j��;�k�;�k�;��Wk�6�j�T���L���^4�:�F��xidJV��F�H^���_��x�F�r5o^�,�A���Qy5�d�T�3����_�FYficJV�,O�)�^30��r1�F9��e�v�����5��+����\�+�<�W��O�����PcJV��?����w	�vT�[i�+�>����������Vz����k.�>���������J+�^�LY���?|\�>_�N���_���x��]�V.�y�_3V��53����h�H4�7Z{�h������n�5���Gt�����
���9lo'*m�,�{TZ��t�>A��=f;�l�{D�����Gc�lw ���~4r�H��������������E��^#���5�����C����X���q������o����
�
��9�r������3v$|tw��{�����U������X?~m?�
��F��M���y�o�G-���H���	_������T�>��^~��5�j��^�������g���9wT`|��F�e���7T`|��j�,`|�/���s7}��9�'0>jxwFI62�����t`|���"�)��[U��(��f��Q�w�x�9b���:��B�e�4&�u���$�#��?\og�F���z�tb3&������Ib|�re��$���$�c�X8�����n����b|��S<��"��1U������b|�2�S�����nL��p���4p�FY'��[���]�W���e�P�t,��5�����{�����j����5����u�Z*���M`�N��Gc�z����^pT��K�
[qi��ca+��tT��I_fj��.l����&:��x�>��G�����b��_*���V\���K���)`�N��V������Ra�����-UD)���t[qi�*��N�������
[1�W����~r0Ja+�;�����(l�-���z+l�9�XX�*k����wT�VYKl�Y�Z���{����o�b��S���+��u���;���WTW�o��W<�F�/�����w@p��_��^��;�j�xw�|'����EoWl��X/[�g+�����pp`��ra���+l��C�[���q���WN�l�u�2�����������?7[u�R*�Ymf��u��*|���8l������,�{Tefi�,X����~��d�6PU	���t�PvTe�q�
Gb`��������]!�f���]HE4#���u�&2]=�
����!��_�R���?RQi�!@**��T�	�o������GH����� �������F���.!�u�
.V�����F{�T�����~���1>��j������"�j-��TTZ/�EH�sy���#4�����jt/HE-U�� ���~2:�"����5�����>J�r!���a@������N������"��Z*B��R�=]�U��][��Q}D��Q���BT�����������>��U���{"*���(��y���6"*��/F;���3q�Y)�S;7������TX5�~�U|���eY]'�qw5&�g�����L�����r����
�l|XQ]�~�<�:X�M��>!l���zG���$�����?^;G�}��#v�r�Wa��+�3T�
�*�[�����6q�U�'w�oW���h��-h����0}r�zYE������������U�ks+�)�jt��p+��	��	��3�UT��4����{!�"�O��VD:U\�
�hO���F�������?~�����Q	��*j����~���1>�[E�Uc�~qUk���FnE�3��9�	nE�i�[QK���������)m�V4�OF�����Q����y����i���/r%7�V�����[5�b8�[5�'�6�V��=���T{�W�����5TQ�<u��U3T�V���>��������[Q7}�k��[�@?k�V�U��V�U����������V5W}:�`U��^�u��>�VG&�l����!*V�F����T\�C��X�-�Eu�����n`Q]9�_�����X�����AM��s��C,��%c��(p��.��6
���_q�^��-�������d07���#?�B\Q]@\TW� ���AeV�� W�,��+��}v�����7�\Y��\Q]�\�#��j���"���������Y{�\���r�Et3�Y4��E�3�YT:S�E�`�8�H?��/�"�����4@.���?B.�G���Vw���rQ�Wcz=B������FXDF���!W#,�D�\QKE��T�\T�`~�����r�G����\D�����-r�W�P!���8K%h�h�/��\��|�Q@.j�ON�8�\QKE��T�\QKE��T�\��������@��Z�=���9�0�0W{IuG_qC5�Ha.zE�-1W�����������$
0W� _"�Y����U��C����c�<�9�2����� ���_�s����[��`XH�����E��Wc������QE���-F������F����J�F�`�r��i
zTe]�����Z\�^��?mw��_�^M���^}
e�
��O�a��4,�}
��0���n����XXv������G�(����~��i��|)�p���;��'��X���?b�a�T$��;`;���Ul��jAlGt#�����`;��7�;�g�O:���g�z?$vtG����������E������H_��
����X�8�������������&���
���q<��5�~YZ�y���FX\1��M����L�I�j��L�1��������Y��@�h���r�u4�F���&�:�GZG���BZ��2���i=�NI�����Z��uQ�FZ��"�k��y_�����0u=�z�=nc�H���xJ�:���v@������Z��^M3����8�H�����.�����"���^��A�~h��}O�:�`��14Rl�����5�2],��^s��FY�hZmWse�m��;�A���k\��q���������]�C���
��l��e�C�Vl���qL�>�j���Xf�Us�v�"m�r����qX�v���6��'h�����k�N�����
�Fuu�vX�or�?��mv2LK���>�>�+����?�k,�(<�t]��t�;]��"��s�E����c������E�����,��T�I?I XL����������a@��yy�:3�@0.��d��`e�V�J�`u�g�N�&X���<�?�����M���0�Q�?>�o*,g�� X<������v�@�x��-�����������ggPU���DbX+k�@��WS X��M�:;�	Vg�b�c��N�Z��v*��A���s8��`�wS�����o	�5����wE����^����G��,�,��*��R���i|x�V��\'5�U����Zs�l�8�����r����V��5����������O����Pu/�.����%T|G�=w�����z���mt�|����?��8����[�d��bXw�C��r��Q�u���&��ouCL�������R�*��S���e�5�����K}<���r)��R�����F�T������p)���RD�hX\����}xz���v���K��l4=A.Ec��F�R4�).E����"�7pr������NX�.�x����~un��B���
\��S������Y'<����3V
\��id��S}<
r��N��U<��N�E�R���;c��KQ�7���T�z"�.�S�R���;�T#l�A�^N�KEo���;��y�y;�@q��M��*n�FK��R��TEG�%/�p��j��,"�j��/���K�gy�R"�U?�s=��Q�k�@��HyTVu�j��*�:e5KZ�U�5WeU�,�
,V��*�l���UQ]9w^�*�;X�
���n�*�+��bU���j�n�}�
���z����T��>��ZOw�QO�)��T��_O������Y�T��w�ov���;.���{�:��^��p,`���/���������W��������9�W�����n_�'�D	���+�#��B�W���C_�8�_�7�����
�W"�+�'�"����I� ������D|�8�_V�R�W�������U���0�+"��W���-�_�v*2&�W����9_Q;��+i���Uc�z��+�������=0��L6�WT������q={�W'�����"�j�}|�S�W�����Us;Cq�z�_�3����3���j���/���i ��\M}|�\MuGB|5���|�\M�/;_���_�&�}���FY/���QV�
��F�o�)���q|�3�+����u�*���WT7������v���W�8��;��)�Z��F_5�r�_���
�&���o�j���[��'(���W����(|Eu�v�i���~���������_��_7����+���k����WD7R}�����>��"���+"��
HwD_���7^A|E�����"����4����4���~������_Q�wt"�j���j�}|�x�H�_5�b�_5n����N�J&�W��'�Uk�~�}|/:�|E��x���h���4��h������W4��N�+z`�*=�WT�������q={�U�N_5������"�j�Tl�w��^_5�S_�]��|�^N��}_�wSq������}J_5WSG�<�Rgp"���jj�������Yyu�!0����
�~(�	��0v���_��"��Q�S���e�z�PV�@Y��Q�uCD������
dQ]��@���\��l
deudQ]W����
���FY���qU��O�JG��V��
j��j5�:��Ow�1�j!��i������~;������������V��@+�'����~��|��P~����q�������_*����������F4#����"����s��5��z��G9����#�a��QDotG�_F"z�O�����Y���N5>��~5�
�7�z�+��yy023�����s ����"zk��n����r5��@��M��\����;��z���(��F�qH��8�����H��$������?��F�2�K\9����Q�	�����g����[�zb�<@oQ;E���"zk���\��)���N�z��N��o������Z�5��r���i�r����W%Do��T������]�5WS�����M�
��P�3���@o��|���(�	7@o�r���QVc���{�[sO���5�(z�^��d
��������n�e�P�-�;�[65�+��qi�K��?0�j��\��!��]�[��j���vGj��������It�!������[X�p�'w\O~�����k���\�������R��u; 2�D	Y����1�D	�}�qSq,&���wD���?<=U���]_uq,&}�X���c�X�8h�8�����9p,~^��������W�m��uR�XY+��y����f
�sS�cuvjs��Nm��w���p���x�8���c�H����cu?]������p,5mg+�r,�f�8?��_CgDbQ+k���:a1����
8�cu�6���T<0����_Y���T\�y�y����?��O�`B�c�(�u����T�;�X��T��8�����qi���iy4������T��!wz^�v�j���v�2{;���S�?;����Q&v�}8�h���7���D�j{��3����W�R�$��W�[�����^���l?��'���=O�������W|���K����;�V���Y$�&���j����:n�;���'������1��ze�=�w����U���j{���T��NY��.X�)���J,���������*����\��j�����nb`W�k�*��'XW�H�C&l�\Ew��1.�*����~���t���g��q����k���
W�h?9D	p=/�\E��
����q<��a'�������]��
�U���pUc�����NE:���Sq��������WQ;��Y@\E�T�������K\���;��;������bE\E���0�U����*j�������:aq���;�veo���;W|�z���Wp}z��WQ3�+��^jt�j��zI%���K��%�U�������{���<����h�����\Y�4��e}H��UDY�`W�U����NY��7��:e��!���+/:Eu�b��S�]t����k��l|�NQ]��*�;�LVwW����j��8}<�<r�y�S�}���:e8W�,��QP��b`TM:�fT��*�@��������3���+�r�n�~��2���,W�b*����S5��`.���jtmLEt#UUD�����pd0W��:�T��9��
S�8�O�����qHS5�6B��F;4����sW���_0�=��s<q�`���"�j<��T��=��sS{0�`*"������
��b*��2���iS�H?�9l�T����1����M
0=0�_?b�`��N��TQ;EL����vS���\O�>��a{0Wg��`���"���B?&�����f����F0U��"�L5�������>�SM��>������K��\<�zw����|��0r?�����-���8(l ��r!��2 �F9��������}z��~�^#�_�������nYQ]W���������?��q���w����%*&�|�[�*p��HdW\�Q��su�2)�^s5
���W��u [��d+j�@������V6�E��+.�VF����K.�.�"���F�&[D7B�]�l�� [D���d�g���,��2X4�N+�"[D����*�Ec�bjA�E��{���#d���� $[���X�����l5����FX�1���M�P�"���' [D8C�Z;�d�9��p�"[�N
�	d�F�(�������l�h?%�H����|P"� [T�s�+j�H�a�+j�H�a��j��/�j�TP@�;O�y�yN=+�-�������n*��a6h��������r�o�H�����T�Vs5����ECnLts�~*��*}r�^�����?���j��&�x5�FS��A�
Gf��l���E�,����>�j�/��/�+����
�/�+���_Y��G�=��B����d��� �F9P��(�\��5V}����BYWt����r����M~e#Q��Yq���s�����X��W8�����?�����_���?����������b���I��������x��]�V.�i�e~u�B���N6�:���@�?^}{�Ht�PE���T���o�����@�
�������7�A������r����~�;��Ht����D�3�F����<������vS�W�&)#7�N!e�������0�26���0��T�������qV��el�U��@oU��~��Wy�m6������z&�X�*����nQ���45�W��n?�J>�v��E=;+?f+�6 ��>�������e��>"	��d�jo�b�QsE���"sl�U����������fn��z��a��OF���i?7Wn�S������p==��_.��^��A�����������O@9qnu"�ynQw_N">P�����s��q�$���<�Jyt�l������;��C9N�76��K��.���Q�	M1�FY���Z���E?~/o���6u��na���,�{C��~���5�Nk����*�K�����5��!���b�W�b:���4��v5]�b��`�D�b'.�8y���������������f����+>��3]�#�o�u���yQM��m /����g��������� ���}? /&�d�e�����/iy�����B^<��F���{�Nc!/.�f�k��w�E�
yu�F�B^\�������F�R@^����+k���x8�P�b�F��B^�q��\��I_���yqs� ��\��^����
��3W��w��yu�g4�+���P��Wg�F��B^���F�W�\ye��Wwq��Wg�b(
y�P�$�W��
���������>��Q������3bl����u�*>=����M~-��9����:s5�'y��E�V�+������+y�O�<�k���N�����4���g|�~�n�FA�a��=�+��)�=�����(����.��Gy��x�G)]8��.�{-��r[����o����LW����AF���j�+����,��� 2���a�'d�0�Vv��Gb���x���#<`VXwT��uS���;PV�4P��Y����	�"�zNP��3$���ne]�kRDY4z��,"�d�nB�E�S(���W��FDY4��FkDYt�=9a�E���6�X�(���{�6����1�E�/�B���5�{Dv�*�
@Y���(��#��s�
������	P�~69m�������f5���D�E��f q�Y����>f��}g�f5�����L�X9��F�h90k�r��`V�^f5�*�!�YQ{E�������.'�Y�^un�=����(x<O����#�Ti==������B�E���qVc������I�=*���W�Yq���ji�F���������E�,e�S@�Y���=";e��j��FZ�5�
��V{-��V:�f+�|^�u~�V�,�Q�����k�VVw�ku��A������Q�_����+��V.��sUl��\����'������5��k����6�i������@]Q��F��_����9��|:�/� ^D7B���������#!������x�X���~7�_�x���t���D�(��E�?S��L�"^T��H]!��;��H�"����F�8$^T���W����(��Y}��X�X?���V���"��:����� ^D�*%�Ew����x5���c@ ^M����H����j$^���^$^�����x5�z�c$^T����D�5q���"�j�U����=%��W�x�P��W��$^���S����zz���J�#��G�����Ws��D"�jP�$^���r ^����a@�&�n�����V�����Ly�y���f^���g��W{��W8����j��b���v0����^s1���yao���OP��Oa�,s��^�8�j��!h��\�v��.�_*����QW,�N������������k.�~����'X\����B��`iG
v�����(Q�P0�iaH���"�zqR0�#���/"��`t��)C�`M���W@���{6+ ��oF)�)���H�����6(�D\�-@����S��qV���(Xc�>��HP0"��`4o�����g��;��h����W�Z)Xo��`Q0��/�&���5�H����H�q�#�`���K���W��(X�^��5��S��^����r k�U$�@���P(Xc��:<O�J��J����_�jEh����oq���f�����H�&�4{rW���kR�f�FQP�F���Zg,h�2�@����O������"bq�A�e�r��XX�X��6K���X\y���k�e6QD�Q�+g����QD,�<P�lL�:��������[y8���g����w��?����k��o�6>��>����r��p�������`��t���M�Y�	>k�U|��8���ju���jK@��c�����?�+���#��.������^�68��INq>��s��|LW�op�����v�t�����H�Q��x����G�]g[��y"�� ����{�����]�>R�����h����_�����W�����Q���;��H��/���8�	 ��^{�Y��v��|����d�S ��X��y�
.Z����{�r����j���<������W���d  ���O��� `g��"���D^��8�� `g�� �����>�1/��V������n�d��$��bk����*>�������5��o;�L�|�[��t��c~o�a��`�����wj�
v������Z���q;k}0�j��w�S�*����AsW��)�-%���S���z��V_|������!����g*}�u�EO������+O�_Y&e�����������6��E��NY���v���������0�|%���QKw��g�m��
\
��rs4����O!��
B�/��ha�~��.���i�*ZW�0m2E���v�rI���q�1]�)M{��m���^��1�@��M��d�z������������h���������1����"�N�<���q�f������A	���?�G�n�7^��������;Mr�7',����w����WUfWh�1V��p�M7�5���
���jw�L[+�5g��"���Z�XZkbmT4Z���F��}�F�
�5*~)]Q�����?Z�y�Q���=n�U�{��#E��VDkQkE��\Z����������Zk��Zs�mh��E���5j��CD�����L���i��}����j\��}�h��V��'���Z�Z]Dk����,���~��� ��z�����u��j|s}+G-]����w���&��t������v�+�d�������vs�\��3]�C����DW�����5�~n�#���j���j\W&���w�^W�����6���A�q�[����N�����q_	��� �n���&���v`����'����}�c��M�����6�aLJ�����[��?T�<`+��VD7���&F�1������[��I-�V4��������3�
������[Q�7��
�U�(
����?~�>�5��������FlE�/�P\9`+��/�x�j|����Z�U�*�������i`����������GlE��D���]:�����m�V���v[5�j4�lE��
Al�X���l�X�^)��jb�~EX�Z[5��W�5�*RS�V����Uk�b0S��������
b+j�z@[5��$b��Z�� �j�U�L����V�
'`��Z�6���k��#��{���m���������PN6�<\�.d�:`���EWe`���
c5�~C�N�o��F5��������5�������r��Y�s8�����J��1�������)���:-~��K���_Ul�Y�b+���1�f��
�
��
{3Ti���k�k�6�N�bX�+�t���tE@���)�Qh���}n��.�h�Ht#���F���n�v�g��h���\@����v��T@����1ei����thw��H��Gi���E���2L� 4~ ��6LH����S������P���W�Ah���+�E�!W���>0�;�2��E��)��q�K+�v�7�!�jbm�hWc��J;�V��]�!���vQ��s���j�Ug�H����������Z���]������V{Zg�j��q�Z�������0���ji����]�Z�q�H�h�/%��l�����@���Y��ZiWsk}�����V��iWsk}�i5���(�����v��nI=oE[������W��f�r��b_ae`_���m.��^s�������(��Wz����Q44l�uF�]x~���i�1
��}o�W�����s`��_yL@K�f@�F	�Yx����|m��������Cd�S8�Q����iq�����+���a����aZy�H��2`���������V#��"2��jD7RDFt�W}�j4��[-b5c��b5��H�v� V�����!�F����5��(��F���j�x�������Q�7��V�{��G������c��Z��>V�>������j4���� V�q~�!`5"����Zk=��X��V=U�X�>�'��`��Z_�+	b5*��4V�F��
�C�F���S�X-zeE��X���k��Zc�>V�16
�S��`5��V�q~��`5j�F��zz��XMq�����c.�����_�U\9`���U?�����"Vkn���b���j�]���d���jtK�S��e�{c��5�2�*��(�!���5�F��ow�3�k��@IY\���`�Q�����DV.��k�'Xee�5L���)�v��r��^`���I�S�J��{�|����[�'�����f��'���
��FY��V�-l���e���I������?^Q��������'z���G��cu������	�kgI���dd�z#���LW/*(�tu,SP�o5Qq:m~[���4��W\�<��p����y��uV|�I�~�<�U����������O�<�B~�^�������������+��������|�;�!�r������-�2��������ag�v���{��i������!7H7�1�[�7�Q6�Q��o;��7��~��sq�.�z�pC.���+n��ef�]���/C��l����?l�Pq��Z
�T���V��(p��Z��i�k-p���7��U�qq��Z��i�y��\��o;co7��6��zz���1r�
��������A��v�V�p�ag��o7��Z�r���M����Ov;Q�6X!W6�7V�)�%x�o�z9���?|g��L ��;����2�����o��QI3 �M�����
V��S��
���S�!c���;O�����.<A�z�S�{W����������R,��i����s�W�W]^�~cD��6g��`z���2�<X`zg��y�����������a�	,�|o������z]��4�w*@kDW����M��d��6�<��r�y���ky��$w}�F�����b3����b���/�,�)�z;�(��4�����/g"�y�����bIp3*~IK�e�����7v9r��W}n�����������]�f4��;�f����v|��.���F�M����X���u`"p3�(��� 7��o{GnFO��o��Q�#������;g4p����Yc�>7�Z+r���j����j����*�>�ft����V}�'r�&�z?z�f���&7�c���������_>�p����=2��M��������q���������37��!�}0	4���DQU�u�r������B����4�rjT��c�_o�������mt����`����;��q]��Am���w�����w7����6�sQ]��J���nu��v:f��z��i��j��tG�Hk?��2�m�q�q�i�^9m��L����u��^��^oA��_!�~�3��B,��XD7�4�����b����4��16�T�"�O�E�_�z3�X4��N�@,*��� �X�Q>[!w�{b�y.%r&�XT�������K"CL��j|�n���4��C��E�,�9�2V��Z���b�8��g�X��`$�b5�6Zt��X�ZYv�����W�������S|��g+����j�U����V�)B��Z�Yl���+��X��b5�*>@�X����8L������h��j8�X���M#�X(h3=��~�~���ZU��[�V�#�����z��X��^���{������'�z
4��[�*������������
$;e5�W
$;e�f��V�i�,�NYN�W=W8�P��(��@U��V�z���\D�@�U��^qUs5�2*������`�#����>�:�k��D;�>����U`iG�*�FYEU�M�*��CX:U�V�*���:�z%�3�+w
-t��-t�����k��S���i������?t��F��M]c�~F��e����9o�g4�F�=�gD��xqE~Fc�h4�D~F���o����G�h�gT��H� ?#�^���*������F_!�g���E`�����Y��>?�^f:�����h�H��� ?�q6����i�J�Ykc����Z�����5��F�3jPw��.�gT�2tM�������@�����S�U���V�a?�Z+���Z}~�X�_Fc�_����(G���8�������_= ?kb�wwE~F���}����Vc���ku��sk}2�#?kn��1�3���o{�y"�,�)f�(J�e5��,���g��+��C9��f��_�3G�Y���\-DC'[��5����{�Yz���Q���m��>�mP�����-�t���qw���g��x�pU��[����+�*jv��z�/�. h��e�S-��������5��L���A����hD��~c�Z�����7�v��{G#��Ft#s�h�7+�hDWow��8S�Fcl�.�hD��At���������X?)S�hT������<J���v���x���?�<�hT�������L'p��WE��1V���p���F������5�]�]��h���h4�X�F��Y�����X���9Zc�/���F��Q����V�%!p4*�l��!G����f�t�?:T
8Zc�>Gk�U�5p��ZEp��Vq���h����h4�/:a�F��t��Z�~�A����A]�c~��#G�t�c���
�:'l�d���e���[��
��5�V�89Zsk5`������:���W�����5Y��g��jb�-�QU�FO�1q��[�,���n����
�5�rG��n��L

�5���(�[z��������"��FA�z����������X�����d����,���~�"��� ���b�+�@la��(��o������'h�*[�
U!������j����~���w�����z�:p���-����W\�������ijo��?^.����&#�M4�d�/r0�@��j�<����<z�q����n�k&��+������
��o�#q��?�;#����_��6n������p#3�n����k����
7r�G�V�pc��",����=���Y��n��V.������6����L��(F���/u��t�F��������n����4u��f���`8���q��k����G���X�����8�;k�g�eo��;k�g�u�j����^��e�[�n���/�����y���+�����3�}��u?�o����w~4�=vn��8���
����b�|�������e���{\��zZ����~7zH�z�N������z��(7~�����Qn\�@��^��������r=����r�^��� 7�+��1�-�{���7}?�Ani�� ���8������q��+��}�N�(�����s7��1eg��q!�2*��S�+����y����+�_�@�8�_�@�8�W]*�	��T^��v�s�.�b��%�����"�z����4����s��h,��3�^4z��^?�v���.���nm'����>V�=r�f�5|���������$
�J8�^t�_f[����?+G���������W��>�"��qo���k��{5{C���E������^D���B�E���Q������w��+7���{5[����;�V~-����������� �j���^����p�%kU���3k�[("�j��v��Q���C��=/���C���~�]"�,�{���Aw>�C��X��|�C���[��v|��?�������n�&�������6������;�r���[��<�������(�Eu��x�-z�������hdUp��WN����2|)���C���>+��p��������Fww�y�����8���[�t�8���zJ�8��\e�>L�����O��_�������4]�\���Nw���s�Z��Qki��t�;� V��}C����>�B,����t#�[D71e���5�h �ojb����0:���!� �{b��}I��� }��N}@,*�h�HbQ�W#�����!������E�S�qY{�Zg�"�����8� ��\��\a��
#�����Tb���Sr���G��2B,*~Y����0[��w�����mA��!�J��` 3������������V�X���Ua��X+B��k�\�{����a_�Z�*�Z���]��.�j��z{
�Y�V��D��X����v��[�xVc���6��+�k��g5WX�����wbb[�,��bZ�5�J�������k����1p����U������q=�C�iQ]�3�`Z��L+���d?D
����Q-�Et��B��G.�i���g���1$~VWZ���ey��U^q��.��n/�k�i�&����nwe�P�+��
we�[�+�[�+��`"��#����e^TU.�*�Et��`^D7������,
�
��A42/��
��~1�k��~H3�u`^���2#����������;��yQ���S/>\`^T������~��
���C�E��������Wc�>�j|�/�j��/�����n5{#�������G�E�S����Gg����oF�2�f�����yQ�G�h�j.�J�����1�W��w�*��X���k���1��j��/����'-"�j��b��y�;�Aq�������WX���WYd_�UVSC��X��!>=�W���5��W�b\��}5���#A`_t�;u������j\���i\H����8X�h\�^sq0����.zA4.����Zq0��`4j�p0��`����`TW~n������v���`D�������=����r��1�����
���_(�>W�<VC�f�zC�����_TW�5����N�Yo�����}n�������0�>9�a�.���0��g���Q�1$��>�4z�a4�:F��O�F�C��Uf~��/V���a��^J�T�V8��3O�k>�0*����F�������~o���Q�'g����"klV��8�gJ����+���)�a���K���k���7�C����h�#�����]t��}�\�����Z&���Q���0*�fT4#����i)8��VU�pXc�>k�U�-;.Y����;�������w����X�y��R}�{����}5��������]�6�
�����q����3�����F�&�}5�\�d8xW��e�M�w������*��b_��&�����ks�}������E��Eu�!X�}�u��}���r����5U�/�+������q��[2�T����b���v�����+���Y�������	�Q�����r�Vq0��o
����|�8Xv�U���E���a{���i�:���j}"/���*�������#��wl����|�:��^������Q]=�6p��K�N����a�f��}�����"wM���o��&��~��{�Wchv��f_�o����hA����Wp�56��r��5�������m��W�k~�)���Z�ug��+����Z�uK�Z���kb���*V�D��`u���S���k5��kb��E_�uV���~��Ew��5����4X]#��e�.�k����^��9���U����l�[k�����k���9�Z���X�;s����s���]^��0�V���H]�~�*�6��wCE��[�>�H]kPzc�"u�����E::H]#�������7�y�|���R��q@�fS��m���U�K���.��k�Z�,���~w#�����gR�/�FR|�]��_y���z��de�tyT�MW����@�
��+�	�]}��7�k�������@�
����
��,��k�Z�l\�6��2����@����|-W�����/�
Yy�[x����Ze�>_jn����F���q�o��+����"�����u�����`LSN##���5��'$�]��j���) $_4�FI�/"}Is�4��~3��#���~1�LH�h�3Mq�
�/zf�����|Q�'c�#���V}�/���R�+��H�����+��H���1�
�Wk�n�Ze��!�/��i _�G��5�/�'�#�/*~�R�.�/�(�������?;��3��@�E�����O����r�Wc�"G��X�O�k! ���Z�}
���V�|�(��Vch �/j�z�2����j�
�L���w�k�?c{ku����Jo�����?{�3~��F�����0���xMSm�f�]t�;3��j�U��;���X���jV�&�v��B�e�p�Kkb!��k]Z�
�ugQ]9�V8���ui�����������y�������������pVs��u���;�"�tT��n��k��FW�������}��5�2���5;X6V�7VZ�V�6+�|X/8��3���t8��V���cV?�����fc��"�z
0����h���h��h���6�X4�!�n6��0��P	w�S!����w��,*�l4C�E���v"dQ�'�#�����DqYt��9�d5��Nk��m��z���d����&��:��E�l4.�E����C������&���~rv�,*�f��"�j~'��YT���3@�E���(�E�E�_�6�����A&dE�AV�Zd5���JY���1��Z������RPY�����E��(�YO���7�AVsk��a#�j��qY���X9������,*�t������K�%\�{����j����A���U��(���j��\-p�����������lQ��I\�-�kt�+�E��O�d��������N�����~(�Eue>Rd��
���!��*�
{j5�2��B���A�V�,?�*�
+C�V8@��[(W���)W�,Oo+�W>,�9�Lk��3�5�J?��\i�S�������������"���-��a���XO>"��1��."��'A��~�v�0A?"�8�.�{#E����?�a"��g�����;@r�������<x]t��1G����;W�5Vt�p$@�1(���Z��5]�y���5q�+Vt�H��A���)�����Q=������Y+�.*�n5B<�V��U!�@1z5#����_1�+�������Vu��f�Z�R�����s���.�������Y�=G�E������[���AWsk5X�fz���E�����,
@vj�tQ�7��+���7 ���k�����2@��~7�N��FYo)8HWz�E�ey�[��p4�A��>�s^)��@=��iOQ/�����������������F7P���E���E���{��\Q��g��bq������b�W�y�@��(�O�|��>J�����Eo6{�������/��A��<kJ�D�Q��<K���Yz����,��gae�g�iN�J1�SM�3���g<
><c��:1`�U��q�1�'��3&���C<��~�:x��}o��x��/�L�D����3�'x����!=�����@��$���8����n�u+6�+����
�������g+~�I�4c��`���l*�x��* i<�.��c���3UY�i\��90��_��D�3��5�?�&�@q:BH����1u6�i��� -k��:kU��K�j�>L[+�4eH�q66]�4&}i"�XO���
� F��1��H��u
�q�7JZ�q�g��'�4.�f@yi|�;g�����V�-��g\�*�^���F��:���S�����T��/!�����i<i�70��4n�2� ���pA�����q]�|����c\�ia�����'��E�����j��
@��F�tZ��e����J-���5h���)��g��N��B�����u�>H��y����a�	�����������_}*<�������G������/0��K��5$��n����f�5$������DkH����N��/"t������F,>�?n=����H?~���.������T���/F��?�c��?*��4C�G��S����_>��{Drq�y��qW�3�*G��X$~����Q@�h���:������S����(?�q�G��~���Qk�?kk�@�����8�}�wNQ?*v����������_���w�F��V$~��+��Z�ag����s������{�����Qk��@�G��(�ZO�����7($~�[���rz���Vq����n��������a$~���@��G$���������*��(�3�W�B�u��;~���.^|�w��@��+�����z������O������$J���d������z
��;� ��G
R]6(Hu�ii�i�#Q �Q��U�ba���Q�[���F
]\yt�L+�K+�k�e2V4/|g�>'@�����]�w~�lf'Pu#`ya���v�+��~��p�i�������8Ft#�pD7SG���"�16��#�ON�1"���d"Fc}�&WlVD�F��h��D��;)D$b���9\	��LM�����ej������=~g$.��5�����"k�U�K@��p��do�b���Z}"�Z�i b4�o�41����N�M b�Q��R��Q�'���wZ�!���)�G"F�_8D,j�H�k��Xc�b�Q b��U$�@�Zk9�a��k#��j�G"F����%����Xsk������w)G"F���"�6~���Qqsj�l�O�T,j���j�j�7y�lg�����7z"
x<�g+V�Y���&�
�&r*�*�C�+���^9���zf5wvf����s��G�ZEr]y�V���~8�6�'C���4���,�zO��LW�v:���h>N��#��t?�0h�D���W����fw��4�0o���4�j"!#�*Dk��h�
���/�^}�J���.�"��f�D7�����)V�WD7�h�3���XO�!�"�V�>�WlyJ�W4�NS*�W4���i�Sd�+*����=3�F.��������F���N��U��"Vx5V�W42=xE��1T�h�#��zk�8�8�S7^�HG&��X_O�W������^�G�h4_CxE���3�W����^Q�g��+������r�WQkEx�X�����V�l�Uc�>�j�U�a�No\�W4�F�"����*+[O���7K�6�c~������Q��������oe�������������d�Ih?�s^����w=�S��:e���4WV\5	-�\�[�8�
����@�F�k4A,�E��7AH+��BZTWGpiQ�@�F�+��BZY�j����F���n4
\�3�F����8?�r���+�<J�e�~�o�%\��/(�j�uR�=�� ��V�V�GX�,CK��XZ�X88��t`�K.����D7��n����f@
p��g���'#��n6�79�;��
���Ax��h����8�����q��S�L�@F����[�����������\���"klVd*���$��a}4b1c�
��(��R��8�����A���X_��*�*,F������l����F���4"{��N��0��/�F,F��
��X��V�Yc�>k���k�X�
�b���%y��������.
X�H;��57X��h3=���������eW��A]��T�v���a��������������Z6/j2�)�(��L����"�W�l��X���������5�r��c���C���_69�]|��F��5�6��z�����q(>Fu|������[��%Wr�qV/�����f��K5[�+�w���?>��������U$FE�D�]����F���rA���aa�&�5�:~;,<�$� �fud�	&$c��j1���d<
~���S��x��D6@2c�� ��:d�oN�U!2k�a���
�BT~���K���"*/��8�2�X��������we�2.~�2W^���_*��>�U9����Q����X�r�3Y%"�� ��fE�T�����v+D���@�Cg# ��x����Bd]�
�Y����;�����7+�����3�]9������q���@d\��)�)D�Y��Oq ��Z����%k["��UE!���"�Q6��"�q���"�7�4������������_�u��W��1����.����1t�Z������X���;-�����[�����<�����@h�������=9j��q�&9�����]��-�?1,��hq�A��%�4fP4�k4�����`W����R4��S4��7N���>��m?;z�����z����m���(��_q(�iu{������G���n�
�e�]!���CFA�u�2&�-�|<����ZOM(���8��?�j,������lN?D�������_�����?��_�������~�?�����OMx�>W�
�c����k�v�Z���_P?��������3���I4�� `�DW�v�&����=m�]�O�B�Ic�l�X�H_F���jS����Ak��q"��
d�z��i?�r;�m�;M��n���7��M�Eb�����2�Bk�Y�b�h-z�7��f%����
��(���=������f�������?^E��.~8����������p��4�=��u�=DX/�F��vA����]�2����]�A��v��r{���{�F�=Ow��w?�e���;cd�nuX:�:���7K������&��3i��O�w�jU�)����q��I,F!N<�e�Q]^�x���_��O�(�Y�F�p��I�t�GyH�,���)-���� eQ�A�]1J@�O��eW|��V,=lW�g'�2�n��Z�yc�L_�w������;����@���>����z�������~]�%c���X����;"�ju���
����	�wD��B�N������BL
B���?}�'~�;*�h4���]s���]s���	d��p&{G����9d�h���1{G�����
H*{79�bP {G������w�j��>V
�w����;�j9������C>nu�1{�v1��;z���;��������S�������{ {G�}g��w�a��"f�&�]��������t�k��9�t�vG����-t���q���11}���G������9�l$*g���������u���u�w�!j�7����P���s�l]�d�����B�.����j�^=���>7y��������i|���w������T�y:����!OGt�/o OGt��O� OG��������1��0��������t4 OVg����:c����j�y:��/���� OG����z O�uU��tD8��k�*\y��a�<]{��������Na��9�������v?O�v�3���a�s:����S8y����y��E;�����H�����t4��h�������nr��u����:�[,a�<]s���O�K��(��<]s�������������k������Q�����q���]Z���k��o�*gG�P��h������7z~�������������k"!�����k��ec<&�v+�����[�����.�������]X�����HT/����e�44>��m�M��H�,��|nGt3i<^�~�i<c}~�����Q��i<��e_,9�4�vb[�B�����4��)f7!�G���Y��k����k���A����^?�i����k�4���������f�6�]}�����5��NO�A��������x����i���H�E;������������k������_v1]
i<z��i�����vQ�<��_m��/���������4=�N���&��b��J�������w�L�8�3]����.�������%���k�����B�FYO��{B~��O��1�o��EbsX����*��(�i���K��Je�����|~����������w3������OO�����99|&n��G"o���K�����~�,������c���yL8���1��4!���_������y2�� �����}Q�y�I1n����@���^?������MxPzUR��+���b���z�cI������$���/��z<��zyn%����_!�7;�����^w���� ��|���J���x��������^w��x�aW�mf�]��z�a��;$��_y�c��tW_�zb��<����n���~��o��y�7�I����]W+����������g�����z��5�^��*����6u��WR�[��.�~���m���b|���=���U--_��M^�b�:u|�^�H�u+����������^��UJ/��*��W>/<A�S�v�	�����������ju���o�+��L%����OYw��t'n0��G�LW��r�D�M��b��;}�1�Hc���#
�^��L�|'�~H���uW��l����s�C��v�������>|�p�u�\��)���c��c�1z�1��|�_��o� ��|1�������o�������;6���4ds��a�������iRy\<�F.��p�_�������{LC6�����;���n��l���m!�|�zV��4�F�����s�`��cF�9�zk�H6��o����ds��o�1#�����2�4�Fke$������W,W!�Z�NY��VV�Q�����
�k��dx���L+�j�x4���s���r�&�'r��(��
�����+_?7�Q��0\��eu�Z8�+�Z8�;���uGN2|� '�>��,����]7�G4#_]��d��n�C���4����1�G��B�����k�v�?.�n��`f��?|7B�3{�a>	��Q�Wc�f����g����UH�3��������3&\@f�=�����������w�����������r,1�z\8����d�������tt����=�����/2��?��W����q��V��[<�����5�^+�����k|!���{}(8f��so���C�o�z�����MN�iv��C���'�e����IB<��Q�)IT��&=#�}���Q]}���4��:���TW�4������<��z���U��W�pX�r���C�+O�}���-��]����^��/��wL�H�~�=���������I�w�������������>�����v�J��;�awDW/vGt#Su�p���g������w#��{�!��G#4�%��������������F�����iF�����������/�����r���b8��Q����V}��P�9
�������~��M9�������?O,�x��}���^l+/�{�x��/�R�x�9^{���vy@6�$���������}�w�%�����n��3���/yH��!�����/��g�;��������]��������N�������������i�qrRb<�b���tg��:R���)x�@�Q��F�px�P �(@^�!��O H��$���������K��j���H6��=^9H�h���M$zD:��G������P�-�~�7!P<��;#
)6z�#�k��6,��x���%�����l<�L�mkvy��L�n��W�X"�k|���}�7����5�7�!�U��')^��G�����E}����=����E��^C�����,9�x���_x���/y�x���9�@���w1P<���
�G_�u:8(��gm���&������/�/a�xTW�b����-���oq�����i���+WAm������X^�bo\�X^XX^�d@����ee���k.���I����3y
p�wpU���M�e���>�<&|}�w���?�5=������:��[����F��=��Qql��o~�U����3�a��q���iW�l������c��4�b{�����b{���!��x���/`{����`{�}��u���K�=�����w���E�i����a���^�Y�����f{LXo�l����b{��m��}������S=��g����������[���~�kw��uf�am�=r�A�=�I��q]�vf{]$��y���6/��j��)��<��s����h���`|���S7_�,�����g���u�~�^<���u�r9��|�5�K?3����R�/��A��������~�������>�����^[o�vgz0Mw����H�����t����D�)DIc���������NvCI#�l�� �$�/x$���L�g!�H*�7�
�����G6��+�;���xd���#���t��q6���\��!S1�������^�Myd�{������3=:���LX�yd��G����5�}oW������o��������xD�4������C�h��?��H���&i�����ee��$�8��E���r��F9'e�����Q3=��(�q.@>UL�}�����\W�c<�d:�`x��`X��d8�0��,�^�(%�x�L�^#���_��y���K���������_�@��n�����2i�����i��=�i�y�>�������o~���I�@���:�FH����r$|Q�#���	_c|����/2��G��9�G�l���[��o+{����?��$|�����">��>E����J,��=>"�!|���P�k}o��}�>�{�� |����k�	_��H{@��'��H�����e |T���\�=��3[w�=��F*_�=�b�= ��������(+��2�e���B�aV�������������x^������l��P4/���y�����s,���S8FS��n��������������=>����Z���D/@��f1�����1�s/��i��z��l��>�wT�h��!�#��D�]�;��;��z�wT��h���������x���������]\3��������Q�m����(��*�Gz���Ql@�����Y<��~� �i�����^�H�����@���Gz���������o ���%�n�����w���� �w�}��S�w�}��L ����;%�;��L���TW/H�.��bwa������0��.�o����-vGu���i���GqFZ�7�zQ��w��+~��q�
�#Q��i�����x�'P�����/�{Y����j���MN^CM��T(��&P��$�5�������_�����3���n��}��$���_����1�9)O���������z\�����z��m���=`���v@~�"Iy���A��������>������������y>��^�xX��?��H8��^����������S�z��/��z���6����A�< ��`y���������<�����['�����\�<�����x|+���o�Ee��x��?����</�[U���+�^� z�S\D/��A���Lh�����y����S�y�L�:edo\yP������5W�m^���������G��S��}����
�c>�j���D�-��?����P�����j�{Dzo$A���`�����Ix�G��_��:��G7s�#.��6�("�k�n���z�^cv;U�7�������L�5�(���t�g��sC��S�m���Gy��{���jv��������A^������<:���z{���y�;��5�Q������6�>�
A^cv�0@^s�%��������f����i���FZSv�u��<������;�u����������
@yY��,/��ya��k�����;��`^��#�����5��4�����w`^z����`^\yZ�����W��//�ow�7��{�y�������E����7��� L���4�� LSO�8�l���*�.K�}�g�������iq�[��q&���j��x#���SB��^{��=��>�|���6��^��g@�T��j�Wh3j����w���o�F?3o/���O���uR��^��n��Q'���������X�:����'����n�������["�|Z1��uF����
Ot�9��,u�%�'�S�����%@��I_*>*�����y��%B��@7B���K�yHT&����*��:Z����(�}6��LF�^}���B|�������������
~fu+�1�{�O|GW����*9�c�����?%��X�<�g�b�*y1�j5�p�x6���2���x���;}�����X5��������F���_+������H��������Ho���	"Lzo����������n������������n�������_{���e@����������gF/oG�GO�����n���?"��d~�kn
���?
���������T�h\H��I�^uv#���j��w|	@�~	@�G�T�+��5�s�$"�k_��"�;��#E������H���>�*H��g�V_9����Xs�gA�����T7�Iu���������i�?�^cZ��y�>F������������E���3�g������sW��R��)��\�p�+�1��I��1����GWB�b����J����%���M��O	�����Q�}�W�Z!����>���v^�����1 ����H��V���E���n��@-����B��n���
��-��q+�o|9��U�X_k~u������9����3�(j&�)��l�^�����������N��y������D�_sR6:z��_��<4x�}���~���v�tW��|@���x`
I������)�G����������1U
i�����������}����Q]�#��}T7@���U`
	_�<I�h�������8r��zefT���W&0E���-�����}Q�k�dvV���X��;r��.�Gu��+����k�H����>���E�" }Q]�Oxz9�#��p��&p����;���}���2��n�1������I���q����zc5D���_�z���B||+���A@||3��!@|\|oT��c������_�aQ����%���8p�RS�c�OFu�������q���JY����
�DPy^1���d��=Ytq�}�����{�p_���@�������=���>~��
�����������q�]��w��|S�
��}�����C��&(��_���\�:�u}��t��|�~i/_�?t8�;-����;p_�_��������Y��N���_O��~��tS��~�r]�
��I~�[����=�������������Y��o���T��~���������#�#�4f"�#���~|+3��H_��g�o��H�@H7�h� �V'
 ��������������[�����\����K���E���V��C���_�9@��S� D�z����Kg�{��������l t+��$$t3��2�X~k��"a������ ����^~d�_���5�q�����������}2~�E�G����^�����/����sg�@����3�yL6��2�*�G?.��~L�I�����O����\����SM�������bT�o�^o���z�<���:U���8@���~����~�_z���EW\�~a��}T7�����,�W�3������2}	y�_����n���g��uG�0Mw����	�cf2��^�(�?9�"���kD;
�"i��/cD�D��C�D���?R���E���n�a�$6�#����eM�H��)1�q���OF!����#c�{��k�H����R�4�z>�������������w�t+wN>�y����������b��Qx
��f������N7��Ov�����j[[��tG�J��4�Fl:���fN���a?��
�_�i����o�����_�w�tC���|���]r_AGz���(�H�+'^t��rm[AG���(������T7�p��CA��y������������&�)�k�;e=�q�Ge�w�y%�~�qv��j��X��1���c1����/w��z_���z]�G4�e�����>/�W�BE�G�7F�3�y4�z4��������7�ln���;��dO���G�uo��G�G7vk��"���{�$�kl/�F�#�;}�@����g
�^k|q�@�h�
i {��j0T {���)�\���S���G�rg�&�d��_q�j��;����5f����E/����5���x��&�� ��(���a�����e�;?c"�knv��F$xt+�����L}(<*~0��!m�yx��*m��yJ�����i9r�_1<�t���Q]0�

gu��eu����H��[1��3 m�����#m������k�,3��wt�2��B��nM�"�S����OK�w���p�.�<�)���]^n�.�#��Gt#��@~gC�G�S��4���H����a_@�n��E���0��
���m���H���}�K���Q��3�^c{��k|/�]�#�:�G�G��!
�FYOA�G��W"��y0��"�����n����f�9Y���?:��V�~E�b6���/z�#�k�.2G x�����H��[^�����v���K���v:^�������7z��k��I/��G�F�(���9.��UB^�lT�-+��xGJ�p�W\8�>�u�Q]�y4�G���p^6������^8���8���g��xGR^\y$���P�=�����)y�=t!!������^�9@/|��5�r�u��2t<��iu��L��j��1]=������B�c��wX�z<���<&���@�-?o��q�$>HU���<�@��f:���qq��H^gu;�	��H�?���u�O�.����s^ y���t�{����U���~c4m���������98���{�+@����K��u��PA��P/�{�z�	����(�)���%oT�����S�|Y<�3�S������9���}����u����������=nO�u+���j��ly$|���-��u����}�;���[�q]}:�i1�>��������9z3�K?}j���������{�Rx/�;�^��2*x�S��^�)������7�}��=�*c��{D7�������x�o��	��h���N�{D:��w+����O~D}�x�y;�9"�>��{c�
�>�����25�Q��3�P_������I{LXO�@��?9�����!K��q����[���������`|�#����e������G&�kn�������������5�]���^,7��_��L@}����������-��v�����}Q_�<�L���{g@�h��M�O���z�������������0]��Y���0���Ka>�+�������j3H�|��[��i�9o�?�y{��^�;��e�`��X/�<�)�U�W.�Wp/|.���<��eo��������o�����;�w�������aL���4�<���w��f $�ii!i�u4���_��s����T��9@�H�24��o�nN�2�#?�g��L�#�L�`��~������FY6������$�ja��$����t�6R�o�|^4�<�C���b�G�������6F���1jv��t
n�����pm�7��^�\��F�U��y�:C}_�}o5���\����\�z�:$6�q}��\-�)�3��+�?����M�8��?�#�^ ���q��~�?�+7d+�Hu��\W&��X�20�FY&m��_�����?���.��2�tB��H'�����8�O�FY��}���q�Qv�w����n��"<��#$�:��Gt3�o����8�GH��O.y�7�,�`�#d����%���o����8�n����C�G���,�����y�p�d�?��
p=!���<���F�G��z+�<��K|Z:���y�>��[��7��)��V�~��T�[���������ba,����"s���������O�F��������%�8�����j�ytW�����}5*��Q�k/T�������?����s<����o�<�0����������{_8���8����P^X��_�����%]}��xT7�8���J�������������<�6�(j�������J�e����y{�]�G4#���=L���/T����������X��A�G��N�9��#�s&��,����nDwt+��Dwt3��0NDwT��$r�k���������!\����q�;e�E&�;g��������:�tG�N]4�;��;'��b�+����?�k�E�uDwQ�#����������������]~�?�g����2k���Bt�\�]{]�����Ft�\��C�]s��?���7�?�����v���Q�s��X�S;�n��}�]XwZXo��7_�wQo����a���+��kV�7C�x���<p@</�U�j��Guyx��;��������?wN��V|h�7}��$��dxL51���&R���>3�?w��1�'O�c�{�<B*��4��^-���vhz���3��x���3��x^wj�Y��������=�<&i����Q�[<�GY?���x������x@zZ<������y��;�W�>��������$�����y��m����������y�*k�[^�<o��?fx��%o��-]�������������O<*k�����f��)�i~s:7�>Zc�y��A���y����x�^~\���</�����L����2<�s���QY�)���3�K?��u�r����'W��~~�XTb^\yP���ee��������^�%������#��zT����t�:��^.�\��&�����#�#�{Cr�����������G�S�<��{�;��f3w�W�<*���F��X���y���c�z�2�����$^��$^��$�[e6�C��G�G}�l�~�X��������[�fZ��.�X����0/�{�z���4���b�9�z�������1L�����E��^s�;�r_�}0J�5��^E�X����z4�� ��������?���~�<����r]ynpA=������z�6|��y�aHA=������}@=�+�[A���:z����N�*�����6���y�<��'���������k�U�����P^�bx^�����1�K
endstream
endobj
8
0
obj
158227
endobj
9
0
obj
[
]
endobj
7
0
obj
<<
/Font
<<
/Font0
10
0
R
/Font1
11
0
R
>>
/Pattern
<<
>>
/XObject
<<
>>
/ExtGState
<<
>>
/ProcSet
[
/PDF
/Text
/ImageB
/ImageC
/ImageI
]
>>
endobj
10
0
obj
<<
/Type
/Font
/Subtype
/Type0
/BaseFont
/MUFUZY+Arial-ItalicMT
/Encoding
/Identity-H
/DescendantFonts
[
12
0
R
]
/ToUnicode
13
0
R
>>
endobj
11
0
obj
<<
/Type
/Font
/Subtype
/Type0
/BaseFont
/MUFUZY+ArialMT
/Encoding
/Identity-H
/DescendantFonts
[
16
0
R
]
/ToUnicode
17
0
R
>>
endobj
13
0
obj
<<
/Filter
/FlateDecode
/Length
20
0
R
>>
stream
x�]��n� E�|�t�_IR���}�n?��E�1�x��/�4
��3�2�a����&P��'�B�����<-^�`0�d9�F�_���#,��u06��H]S��s�+�=���;�^�o�@w��6r�8�
#�@9�j����t/r�P�ot������/�cu@s�,�&
��
�����%h�� `�M�'U�'�	���Q_��O}8�����H�Nt@��D��*������-�����������a���	��1��f��V2����~}����j�>������h,\&�&�����
endstream
endobj
15
0
obj
<<
/Filter
/FlateDecode
/Length
21
0
R
>>
stream
x��}y|SU��s��77K��i��kR����h��h+��R[�Rv�&�"�
�"8(��
��(hA�QW�mt�qqAE����s��R��������i��>g������<���#"-%�l���\�Qv1J�&R�'��2���3���xi��'���GNdy�(�<u���o��N��M�S4���'�����:c��i7w\�|!Q����9a��m���O��`Vt�������g��I�����E��Ed���D�)I�"�i���})��3�����a�>��0��F����1�&�BZ��Q��V��t3�GshmE�	�$�E��'���R&i'i]���@v:A/R5���gqd�D�K���t\���%�bW�d������%��d~��R�hy��������;������`�1=��>C�d�J_�]J'?�@��&z��c��$>�o��+#�;5��')��hZ����N��3�8v�}(����_��b���zS%��l����-����F����/�f��<EK��a�����;�FR=]C��c�����6�t�{b�	��0�b�����^��X��2YG���`���Wy)_����%E���Hz@�/�KzW�J�'/�?2X�lm�6U[�m�k���n��K��1t9�����e��Va�����L��1j�t�^�w�}���gV���del2��-`��~�8{�����8~?Q�J���V��
y�<G~%H�������K�U�������M7x�	��Q
MB�7��tz�I�R���Oz�>�L����9Y���X>+bC�06�Mas�B����6�;��,�1���3��v�}
�����c��w��<�w�����o���~~���5�&�'����b%��,��4@#��H�%�N��y�=Y�����r�|��M~T~Y�\�A�(7)����
d�.25L5�jh2��J�0u��D�N]�>f$�����bw��L[}���^eO�;l���;�P� ������Kw��)�O��� � }����/=���9z���M��d[�v�Z>�/�c�e�Cr3�+�"K�m�_�~�A�6���`���B3�^����V�B���5����z����;�/������;bY9]�}��P����"�E�����z*si��F�X#,=�Na���dSy)O����}�G� ����(��1�L������_�������(��Nx�.����g�������t��$����k�)�T�r��
��]�(��-���I��)�Cz���Qy��m�*���[�vy��G)�S���o�m��v�E��s���v���}y
v�lp�B;q������T&��M��x�6vy4�%t9�;f�T��i0�@�yo�c��U;�����WQ'�y��A�K���.*������{aA��]�;���r:ew����vH���RS��]��xG�=�c����MF��`U�Vz��=��������/O���P0�UA}�����<�z3��-�h9�MK����%�y��,/�S��^��z���a5H����z��� =-g��hd��q���5��`���@����+�+��=s_o�I��\�c� iA*������������{8�1�@���2���CH���&����HNO���
���������M���M��7���x�������#��6�h|�/j�w��15i\��#��~+�E�\��x��o�������J�4���^���2��um�������gV���B�k]����JhR������
O��������z,H��
_��7)�@{��*=�/��������*R�8h�����~O��5y�{l�!n����Q���Z����\�oa'#���<<I�)�I%�zB	��S�pW`"�aZ���~���(��L����[��{Oqa��p�!��-���C}$��99B.��XH�������;��yg�< `
��m�=����t��k��4���a5����'�%��6��E��HM�HQ�4R�r{������0f��cK����#�~�zR�~���a�j<�����x��P}IK]8��[#%�p�'Kz-$qLKc���
�����K��&�Q�K��*`��������������.���-<�@�����/^�j	����KG�^m���
zg��*��ju��qM���^���������UYY�&����@��ZLb*�i��g������V�Us^�g��5{9�}�����@]��_/�-�"�9� �{�Q�J>�'Z���z�����H/3F�Mh��2�^�O�0�b�|a�T���'Xgx�*/�K���:������~F�F�"�9I�o�i�S.��������se����i���t�����#�~�HG~�+�y�#0�����#|q�/�����b��Td�X��Te�o��F���f����M���E��O�����~]���bW���i7)ys��I|�����f����&�����B���$kl��fI)�����[%b;��c��ee�vg�k/-M>@1�{{��!�)���{%YQ�A5��h��c����9���	N�+~��h�4i�{,J�x<�")J�=�aW��x#��VG��c�&�9�buX,V�<������M���l#������X��l�&�������W#ob=�6,�b�)>��rmTLVk�v����P���:��Ym��|�f��i��:�����T����3c�M�F�G���z�)Jb����Y�.g�.�����V�����������E������E�����k�(�����2�I��no��rG��(�=]f;M�`���w�����]:1�*��h������y���VRR��k��]�
��E���y���*�JY
�4�u���T�E�9�6���;�O(�k~���S������<���fi��U����`���{K���:��s-�u���2Vy��[(W{�1:�0�I{��B"�[8���N�H.2��K�"&��BT�{pQ�%3�(��m���lH��Z�B�,55�����������X���9{;����s{/h,1�tkFW]���$�����Cv�'�K
�O9��^�����4���M�-�\�9�i�wu
��������������S�SB���:�����+V		���v�����EE����ja����A5�;�����!c�>x�5�]���H����9������I�������V��/���eC�o�h�AD9�����9����~`v�;�7<V���hS|L/�E��+]4�SjuUv����>q�[BW<�}d0	]A���L6SlaG�'it������x�e�%
�*��rZa��g�yvSv48���sc��5�-C-�,������I�~9�Fb����	M������B���kh>e;W�p
�WN�}Pe+��C�i
���CV 	��wE�qHs0F���mz�����YGg�=�tc�M����Y�	��xV��
S��S�������]W�e��C����O�"�"��t�?lt�4gZ�Q��=�f�7�/K��.��X����h)�2���>).��-)���5G;������9�����,s7�dq��$0�����|�!�(��F56�,/�ji�X{!���f�Ii��z�.�`�Gu�A��������������u�/�`����B�
�
��*�`'�e����`P;
���*���f����Y(�.�=a��a7������|����/���3sj{�$<sQ�e��]�g��Q���6����a����Z��mR����W�9+��%C�]^�>������K/?�a�;���A���K?�''y`'��EN�9/~u�C�b
�b�3�3/����oX��$�#�Ci�R2$�;�s/#��H�p�
j\6�]���c/Oa���R�2$�L���������y�I����&V�O4u!�HCh,�$Ug�������.c�E�u�Z7��hPH��1�g��J7T�w�qV
+���2}u|����@��U,����]���=e)�[<�a��P�8U_{�B}�����k/�����K��h����l����'/;~k1$�����������c�g�>��uXu�
,��o���y�Ss���s2���K�i�)��d�P�#m����5�|L�4�5���;������d��jx���aaa]��6�9!�����nD�5��qv���Q�Rbj�j�r�����Bd���K�il��Ww��|J�%&��;��i��W��t�(����i�#_�������9���2zAM�}lE��������>zts�����/_��FH����	HT�i�J�����b�c!W&�`�S�iQM��Y��#������z���p�|�n���6O6+=X7sY�@��< ������X�(Jv���������5Q/�b�����#�4����m%��u�e�[���>�p����} ,9�������Pb�3�{1����_�R0��%�]�vb���NZ�/����.�WX<���'��>���{�}�/�������U���KG.}��%7�X���aW���������t����=�$����;�q�I�]�'q��'>�(eI����V&�$�RrIv�J6DX���
EBf#�����
�-��v���R���?��c�7��wz
)�3+�]p�WFV��x�B�b�.�km���=A��>!*��a����yHXjzX������@V������r�[��������&��f�K���s�i�_�8y�nv��/^<��x�=�����U7o�.�����E=�����l��R����Cq�,{�]��b�x����4)Q�(�b��&$xIq�`��Y=&���R8"K�h���i�
~�}.\���2�s3�����;�9M����Yd�Z((��S�|%�Hc���"]��	��qj�%������b++S��h��8oqAq/�RuM��^�������]s&T�H��{���\�sG�;���0�w����f��y��������!A����������nB��������eW�id������L_��<��_NenNJ��i6'fGg��f',��e��E��_��v��l�!�m6�Sc\.Sbb
�d'�er^�dng�s��e�<��6��g�3!�����?�{����glY�fFff.�v��Ns�9k�K����>����l���f�����f��rX����W-�4��X�<���������j{�R��.�9��cb���������6��L8�������Cf��[��g��m����_\�����oxg?���?�O�YQ�q��>�L/����+6ad������jd�w<��'��'���nx"1�x��k���w]|�s�W����)|5��_}���T��rGs�4�gU������b�)�"�"��'�O�d�l��:�������D3ST�7��������
+
�6�P^mZoc6�)?�<�����e[�����3����&~�?/	�!����ikhM�l������^�C�V�_���Z�m��Y�P�������������VW�����ah�M�=��?{V�_���b��I9ca^_?r���M������}�4�@x/�&����|��A�Y�c�[I6�������!����&�m�7m6=j:l�L��2��JbR6WU���d���A1���\S��d�M���x�\*���������pS�0��L�5��	�"�e�����m���r��+S�5�
�Z{��������J��)�!�759D���znobz�����kVT�z:���M�*������~:����+����|�����~����*��U���M<@f�����V�Q��h�
y�|�|���d#y�����5+�L�K�^���Q�?�dC�f6IFY�e����hR�-l�6K
�<�`t6_Y�O?����R1�r�h"�?�a2�fE�d�
�$���!�,q�@1;�l2��F�j@�fg�0�Q�[bm�`�6��<M���3����-���-�3�m;�C��0�jX�WKX�:6�Y��	���Y�������+"�oI��AKU#V�Xf,�*�:L�B�#PW�*V��)n;�������DJs�����y�S�{��A�Su��G�+l��T9�HF�V������aEST.Ia��9�[����;���/���L~���r��j!��C"M~���""MB���5�9�2	QE���!
���a�"L�� ���E��~�\�v�nq�u9G�j#��r��*p�/�a)lf����*���M����Ox���<����p���������O8
��j�H�e����r
&������X`�2r���D�
�N9���N2�������u{Q�an�'�n��9Q�`qq�L�!���lC�;M�E�M��#�d�q�(��M�G�Smi50�n���E���-��Y�aa<6��'TNH����`���SO3����qa�B$a7�a��0y^c������)Pu���U��:������6�M�!~X��np�����>e�v�y������p�CWt�&g=�P=��������|)�:��l��m������B��G���v�k��3��jw�{y���W��eQ��B����c�|�`<k��Pw:����Jg�k6�6����%��X��93dG9����S������F��7�O�k��svp���5����Vk�:oB�b��C?5i>�[T�m,���Q���K��a���~h}����A�/�5,�;[;N?8n���������\�V�9����k�����Z~����}��cCOD�1�����Xx�#�-&� ����w�����xG�T�_�V��_�6�U�\�|���Ei�$%�-�9-1���RVz��T�:K��9�&��5Q��DH������l��i����E�����W���#��<s�5�O��af���+��7_5rmCw���������q�_n�tW~���'���y��/��,i4�C���M������M�!:!z�������d���r	+���B�'�Zc�d�11�
��%�TbB�1a��j+$�P��p�E����i��Y�vh�%��������Z���u�{4
���#=��Nh������s�toZX����+���S�;N����TCDDB�����7���EC���=^:J�zk���;:�<��y���\�z�%'�h��F#�$�D$n��;���|iQ�&��Q�E��G����U7Hk\[-���*i�e�E���H��-��=Q)Tf����q��X�$w���;YR=~x�sY�OM��#�Q&�/�-O���5z(���3�&��ft*�[/�%�\}4$j
�A���O�!9�4�YC���8��u����(�����s������g�3�xG�87�!D:f���eY�������V�w�o�y������]{��z���M������WU�����Y��if�%��U?��[����Q�#�r�������/����D��9b&���Ys����M��#)��A�1�c�n������,1gc������� ���FG�)��'���k9��!��d�,�V�i�I25����%�����w��9�C\C�Yc�0UHO����{a�Q��%���y�yZ����wIZ�>u}������Y���)�xKl��J�>m-S�
.Y��V����r5_��v��%M�ZS3��K�?f�>�F�������CcGs�k�:�<7j�����m���c��D�vB�#:�:,wB�P���a��md�b$cb���5��-�.�����hTl����c\5����8$ql��D9�Oc2v���)Q�.
;����U�|�\�J�Sq*I�����t����N��e�M�/������B��!-�~�����Ym�����Y�~�9	����R����o��t�M��_r��������<x��u��>�'5���/�;`Iu�j�<�oF�����I,���a"�Iy7�wJ�8�����������Z�t��u���O���YS�"�P%���-�j����X��	N������.��,~��
�$��9�{6��Y��8��#�0!��q�Dr�I�'�8�I�����Y���#�����F^�����{���b�R&&�[+����A�5|dk��.����9qp����\�l�}	��oO��G)����_8���\������.��������8��K�W�%���w\�Yg���������x��[����?��y����rV�<�6z��I<�����n�������=vL��y�����*���&����)���h���������=��_�S���?�����Q�>�Wp0�5?���~n�NT[���C�)/m��w/����45��)�t[�d�0=��6J����j����l,�|^����7�sX>�`P�����F�y�^���a��M3�j����V9F��H��?�:C)�q����2Q�G�Y�
�(�OD�(�}�z�7�>
�g���nUk��>��nxN4��^%E�9��0��3G�c���h'��]��ct;�Q_�t�����C�����q�`�K��"}?��Y&�iq���w�t��C|�v)��54o@�sn���/���>�m��c����A�����	��^�E�!_����(�#1�4
s<-O�k��=�q�V��>�[0��wS�t�JP�����B9���w� ���2�	��ex��.<s�.�R��Y�����}��;+�'�����:Z��,v�x�cF�p�R��@�\�;�n���6��t���1j��`]��|��g�
���������b�r�����E�p�'xv��A@�#oD�.�Q�.��!��|@6�����e64�]��=����sn2����N�!��D�!�b��g�2��|O��xN�����*����=��P������T"�T@EBf��E���>~�G�'Z���j_�N_�aY_�^��
t��������l/]O���4�)��`-�kK����t��	M9�;��������R���th��:� ���S�T!vB�����_��`GBu�
�������������H���i�����P?g]O��|/��1������II6�9��~����X��!�Ce�|�����QO�s��������x��M�(��o�
�|�Y����k+K���T���L�T������������m�Y���:ty��j��4�D>/�S�X+���w����T�-���}*�Fd�B?
't��s��eG�����g�'w�z�E����	���8���],t�z�0�&���R
�7�B_P����1�/[l���a{�-bK�P�E��*]�����2]��@y�����4l�fC��{��}����� O�M���O1�{���7���h�^GT&��^���?�M�6�:h�|�vJ:��^��P^��
=ib��DPQ&�ox�>�1G�!��o��c�����g����Q�P~mR�c�91���>�Z��������j�q�S��@��s��y���y�����i������P7�����e�x��@�N����a�;�������R��<�(}
��R��+�e�3R�#vX:�}�B{S�t
 ��S�}��������'6��g�m�����2-��C���;�Kg��d���O�z�R2��{'�;��������a��_�>����k��t���K�����]�*'�6��@�A�	�9v����!��+��ZN$=���b�f��(U��>��B.ba��F��"�P��tu�A��GIR�}��_&/�A�E;+�;V��*�����T ��G���o 3��O�	�W��>�>8$�>�|V���i��h����r?�}��V��A�1���'
�R1^�_0^��e���'�1��������>�F��������
kE����z��nv��:�
��Z�,vZ�g�#j�
<�v5�_��'�X?�i����FP+0�h�=��
9{%����
�7���|�<�cD?��!4;@o��T�?�+4m(���y?��{�G��;��3"�����wP�D~0U��/���u��������X	��'mm�M#���������V>h�Cd�l�����#��ts/��2���n�X�Ga��!����!�+��	],�!t�����@��}����#���O�wA}Mku�MZ+�����c����2�P���������W�nL�?�r��"�@RMz|X^���"/ll3|i�K�/6|
�r������n_�i9��L�\����iN��l��H����z��$�M��-��&�R��������������(�.�/�	i0��.�-�g�.7a^F��(����o�"�MTo����������^��W|��Z|������>>�v;����}�*��W$��g�����(L��u?�U��V�.�?��c�7�%��_s(���0���%����o���Az�:K��Cge�-\&���O�����;b�RM�V�uL�X8m�����5�gA��@/.~�{L{8��*/�.�f��2`��y(�S<@��Y|�@+�����yr����X���Z	o�Q-?��w> ���8Z��H{r�*���4�U��q�x���c@1��y�Bv�eSB�����?�V}���N��+��t��8FW*��_�����8�)��^�7�QBq�j�!@?j����H:�{����W�	�}q��w9/��1;{�|x���#�{+t��r�t��V��r����Y���#�S�[�p�~��o�S����/���?��h;>�X��
�����o[�^A����f�E�<�-P.h��@y�_�o���q�VyV[�<�a��\o[���;��(�?�o�9�-P��;��(�v��B�XP���a��.�������N"
?��������_�X�x���A���Y��x�������HFy:(|������~��	��N�v��,`b����q���|��A���������<|L��$^�����L��C�o�'P�����Bc���1�f7�]0�#4�@=b
>��
�!�~h���\����^�>�>"��'S�r���V�FP]�
��\{���:����N2 n�������}�=������a�"H��{A}r�v\�
�����gh��=�wb��T��A��>����awE�J���X�<������p��
��gp�7�Ij)�ELR��h����T
�G�M}
�Q�����"��������f�6�������� ���#��=���|3
�o�f��<�3�\��Vg�����PB��_k��%�1/�}4����P%��P��~F|���cy5-T��Z�1l#|��ur
���J����T;��J'
�x^��_$�� w�
#��*2���qV�������|�?my�8G@,/����5?��O���-�od>��~��?L�o��Q"���o������O|�����?�{��a'�u�hH�����o������i�Mc�q���l��6i�������:-������^�^�����NCyp/��P���
�+�G�&~/�0�?�a�;�#�>"^bo����(�1*��*f0�q0W����jC�d����oC���W�������]�o�]��Z3����g�Z%;�6��F���T�c~��v����QB�������uN�;~lM$F�����uZ����h����%�'�������6~���KVC��wla��s�pl�B�~y��:g�zg��������������rj^iE?���_�!��;���
8�����������F7m��'����:$F������
8�������
'�A����<������xO�>����1��F�>��-�],��F3�1����g�N���=��_"�ks���s�_�Qn�������o������K��$L���n/������\c���,������%G��wi�
�m_	��_����)�|���A�>B������D��k�Q�������x��6`��/�^�����k2S����u=�=��w��Gir�����5������dt%��#t�qm�2��	`|ia
���/�,O��nA��A��Y{
8���P-=���w�/!_UG�p���/�?�{%M{E9����7g���9X�
���U�CJ����[���.!~� ��P��{�"E�?�v�eW���D��"��Tz>���������o([�\&�S��x���T����_~��%b�'��t-�q�'���~�eZ���"��;N����'����&�VK��~��w�u�������^l��A�=I������Rb|(dq(�Kh��L~#�5����f�����A���!����5Z/���N���������P6?K���0�et�?G���Vj��B�aR�q��\2i���m�(��_���S�a��&�z@���(�������.����L��w��/��X�1�[�������3R�G�ou��(��%�������O��:�������hZ�w%�}����"��(�[d���Y�k��V�GY��a�����
*���5�d�����W(C�B���+a�O"V���������oa�#!����,X���\�a��������YF����BYN�C��������>�s�o7K.�D?��F��Q������i������Aj�������c�S�������T�m����ml����������1���e��d�%>1��(>O�	�*_�C��;�*��|�����:b� 7��t����!�a��bY�&���Z����@����] ����o�B�v�w�����?�	����Q{i-�x���^i��.�^�`�}�i���xP�9���2]�����(m��qm}7q�.�2���S{��6��5�Z�ry*���k�]c	��x~W���0����B��[�������I��V f*������y��  �E��M'/���'��	��4�N�|xx8< ~�&������j�{������x	#�A��p���^`+������;x)�rQ{c��4��H��~s��v��B�����Yh�1D�>D��Py���?Z/!�Ak���(v:u	�9����j�(��D)7��fnG;���v���hG;���v���hG;���v���hG;���v���hG;���v�������2E
q�Q>�$��� �I�si�'��h��;������F[|7A��"�Pc���u�c�vz8�d���`, ���{�������I��a��
z��nz��/D��!j��]
D����D~kc��|N�P>#���V���~��5(�dt��1>5t��!n{�1)�[�a�Z<��������j�����]�>�R�^�_���r���_c�������a���~�����u�~��_���4�_��9�����v�e�f�\fs3.���fb��������_\������x.v�����9��y@zN�������'#9�Dd�5������+��WF�����������z�AYtW�	�{sf����=K��;���kb�{�?���l��wg�8�������p��>���}����nr7�h�%���������cp���W����UW���-�	�iT�(w��I�2���r��y�]����&�s��r���v�>����������
u�)4�lAswDg�^*�#�M���
o�v�����z�z���
��
]�
����!S���:�v��h5F�F��`���HF��3�>��0� Y\e=m�����^���FN('
�G�aG&�����w#�M�<lT@��a�@xiW��7�I���}���5{��������5M,Q��,���X���%������������bK�*~�R����������`�kU�E*�#�� �D���4pDM����@7��Rk6����9�v�]��#����r�����\��������A�w�v�A;�T.�Q��
���B��z;�]�]���z;o���vi��.G�s�Giz�4�{���9������F�uPos0��@����F�t��[��7q3�7�:�$/��sK��zO;��j����=�����>>_�4!+Ck��Om�1!�`��K_���^���+�������'`����r�������h�3��$��Ll��:
������y�E�WTY�?I�r-���|��W�P�>Z�s��y���rZE�s��ya:�rF�U�GU+���Z�u��Y,�M��Pag��BIji�Rf2���
�eC��C����P�Qk���_�A���0�
endstream
endobj
12
0
obj
<<
/Type
/Font
/Subtype
/CIDFontType2
/BaseFont
/MUFUZY+Arial-ItalicMT
/CIDSystemInfo
<<
/Registry
(Adobe)
/Ordering
(UCS)
/Supplement
0
>>
/FontDescriptor
14
0
R
/CIDToGIDMap
/Identity
/DW
556
/W
[
0
[
750
0
0
277
]
4
47
0
48
[
833
]
49
53
0
54
[
666
0
722
]
57
67
0
68
69
556
70
[
500
556
556
277
556
556
222
0
500
222
833
556
556
0
0
333
500
277
556
0
722
]
]
>>
endobj
14
0
obj
<<
/Type
/FontDescriptor
/FontName
/MUFUZY+Arial-ItalicMT
/Flags
68
/FontBBox
[
-517
-324
1358
997
]
/Ascent
728
/Descent
-207
/ItalicAngle
-12.0
/CapHeight
715
/StemV
80
/FontFile2
15
0
R
>>
endobj
17
0
obj
<<
/Filter
/FlateDecode
/Length
22
0
R
>>
stream
x�}R�n�0��)r�	�I(��i��hl@�E!
���_��n��F
���l�ms�8y�F�B��u&�4����uL��X�#|���,K�v�"��GV�<{M���Wwf������`�����m�����0��\0���>%z��S7���nL�m�����x�=�cI�����wB���j����CZ��3xA�]Oa�����.`���G��T$C<?�'^
�IIj������b��@Y%W*�U**����`�������F�,	�/��	$_i�=����e��1�Ci8ul��t���c��/.�_����
endstream
endobj
19
0
obj
<<
/Filter
/FlateDecode
/Length
23
0
R
>>
stream
x���|UE�?���s�����K���!7H��\�HG��D�)"UEE	*EDE]*E��.tt���k����euQ^_dW ����sN��������>�O�~���3sf�6��u���@u������5�<���6����_=n-��!.�������}�g-@����N�r����6`�����[���_1�;}��E+N���i��)���<I���`���>{����g��?b����S���3���K��M�!������a���/)n�����S�����:��g�x���������!����~+@��Xr3\�&,�
���6�<l�X�B�vC��S�%�Lz[-'dC/s�V68uL������a.�K�M���3�	�]�SM`�(L���oLM}���p?|�����$�R�5���V��Y���IA\�c�a`{y�>�`a�X��oy$U��������Z��*�y<�4!5$u���"|���
v�_#��c�����1�@1����o��Rs���j�1�R��'s���2b9�>��0����kRo���h����s�O~=�-����S����r�6�cQV���1����I���=v��)0��>|�G,�vr?(="?%�R2��\�"��</0'~i�-`7�w�������H�����l��_}1��[�)�'���l��Mg��
v��`�����g�o���<�wro�)/�o4-7��|�<�y_�����*M-�HKq�w�:��]p�����fbv���8�b����w=��=��`O�������}��g�8����x���>�_�������A
I�RB����q��
i
����&G��r
���t�i��	�S�M���X^?�HSQ�G�������m�
��A�0���*�$����}R�x�9p�����d�qf&��l[�3y[�c�-{g�/�[����1w��7���|_���
�~R2Kv�-�"�<�F�*-����������O��i�K�69&g��rB>O�(_!�����0M0�f�L�)���J��_��������������,�H���,���KK�~�������y"L��p�T�[��c
<��H9�����19�z?_�O�s�!l	3y�m�_��Q��8*?����y��`��olc�+�����rBz
��>ffy#�/�X���K��
~'�4��,�A��4�];x?�)�j���l3��Q���KJ���"u�>�a�+E>^	��)��p����<�\��t�R��+|����Xp�I��J��$�nb5�Z�[�.\e|$=��?�+
���.`�����0/��6����.���<�0J��R�����*P��D���r��4K�H9��.F��X�������f �_�R�
hPF�F���b(u���/��������py�N���`Ej1��	�n�'���ka.d"�|���������|�������8�y,_��o1������#�:�:�6Rw!J���G�+��H{��y(���/����F�O��
��.�a�<<j6�$s������Z��/H-��6��y�g!��u����}F�����yn�9=*�w�(/+����S��DQ���������x,3#=-	�����Q�.��n�Z��I�8��~9�k�����r~��)�3	&�*���cQ�����kE���5�XsZ��I�f��&S�UP��8�/'^�oN���1�����?*�CDz�H;1���
�������Ym�_}�+���W�_��n���g��c1l��1i�T}(g�V��D���������A�Gs��������Ky�&M�>bl��iYY�:��>�s.��������}D7�J�z��&>��n�o-��ju�
��&Sr�L�0�^�4���$�����k���d���>cW�~�&������U+��F�m�4��q�������]��^��8hd{�����g���8}	}��}Ss�QI��x�5�w��U3kqi��������E��]���_5jlNV}uZ��I}���a�Wo�$����t,��z����r�	��ubj�3��)5����e4���� ����8��9�M�)��VM�����8�����������]���rj_o�Ss��������8�d�^����%�NZH
���D����H�����S�+:_��sr��q�p�`8���q=Jp���h�oiL�%���1V�����m�,I�����d��$0���OZ��� %7���zK~���j��oz�z���S���F�1~l���Z}n�:+�=���LO���������i�x�D9��2e�:��<��"�zJ���T)JX��Z;@������F��c�JDg������8;�Y����X%��QU5~�*�Y������#�x56+��F#g���S{����'q��P�?�H��U1MO��D�����[��N����U�Su�����U�����Us������}KZ}���p����zo�a+GlM��#�����^a����8�}j{��������$E)�R*�L�20��Gn�Q?mW�N<�E��Ond �,F���\+S�2�e�V�e��dL�Qc[S�`�q�9�	�b7dy�<y0T������I�����*]�zUYozw
!H���I����(�n���5��Iw8��#���;���>������O��h$"��p8���cX�����gO�����_�=��
�������8~���'�5G�UO`�G���UjU5B�4�x++	+:%�S�u��su�V�!3��x������\L9�;!9c�|Le�Xi��b�9s�X���j���o��?f$��_y��R��JNv>�V�`Yi���|��1�3��Zw���._��U�7�w_��}��������V��T�o�xy�C��g�+��K�u����-8�@���Ov������l��V/�8Y�X#��g��'#s�\�aC8g9����X!"��5���Q?��!G�t�y�Y�^�k��� �����}�y�0�����%h����y�}bIjh1�t.�(�>p���N}!{L{A��N:����h��n�=ZiL}��P���Y�0�J���ja�x2�t���P�vPhV)������h�l�g:�!+6np��hJ$#N'�<��::�Jp�`p�K#N����M��M
����S$�IF�v�^�R	��T���3�lP�5E"2������/��:�*++�J�J�+.��l�~�����>i�|"��2��O�]��M��_�\i���B��|��J�=�����}w�e�4Z�IL|�@���%�4I��dVNyg+�j�������t�a]��u�����B���b1��q y"j��j��k2_���?�&qCJ��I}X�<��w�1n��*	���%�z*G�(����5?'�������+�-�=���o]}��'/~�����o2���������������}���������g~3c9Q��Hz���l�^��M�m�A�6�+D(%���Y�~;��"?-3+(&.YM����616�E`$�S�T	�1�U�#�+]��K��y2B�cP������Pn�w��]&7%M���fUlh�8O�G�3UC����:T�<�4�Pc������+�v�V�O5�zs����,����8���^�����=�g!��w�9�f���!��L�B	Q"�
Ic��+�������N��G$�IZUS�~S&QP�*df���t>�t��f6���n��1��y<�����"�D5��J��xK�����V���N��>>:�Oe��m�j�8��?�b��7�H��z�%��c:Gy��Gy�����t���q�Q�Y�)�k���n�>��,�Y���c��YOS��5SU~�:��x,[q���6��(��G���QKzTb�M���j#��}��yYx}���3���j3�F�*��mA�M$^bV�_
qPY������O�s�4v�\T��olWC
0Q������
5a���h��N	*@��(�
�5�f���y���nHA]I�d+�����R��?�|��=���'�����.������������g��U5y���>�6��W����3c7?�i��.��cR��A��k�)���o�)��[�o{$����#�H80�:��P[�3m���t9�C���3��Gx�*q[��/����KH�(�?�VVW�G����G�������D)����:�9�;�~�=W�I/Sg���p^�_�\��9�Q�����N�lf�/�5%[�9F>H'���	���|D���Gi�a:��{�%���b����9q����FU�Q��R�� _��|�j>�/=�,��_�1���o���v��8a�������SGBH�<>��i�MG�/���X4ZA�������G���-�'(���$
� 1Sh��i��=k����+���4.�9c��!���.zu��)7�i���R����+�oX����/�n�
7�������L|�S��n�����d-DQb���(����]�H�L>M��T������s��8WDh�D��!�Dh��b��i�-"4�P�U��Z��uLw�u<�x�a,
v�F�����P$��f���O��W%�/I���p�f�9�X������,cx�&7�i��L�dF��f(�fU��7���5�nI�9��Sn���0�qsb��_h�����1��������p5��b��A:���qb�*�sU�
�x��*Oe%��a�������
�.p�>���Di�V�^V)ew�����*z�8$���;��JG��JG2�����q�J!;������A���S��H��i��?t���
�l�����m������Y$'�>�2=��t�����]
a��)uF�$C��	��+B)l4���J��	c�+B{X�7U�}��g�I���]��@ �K*�����t���9��^�"!$)�8�U�RM�P�����J�-�A��3Ve��{���;���,V_�U���M���Q�H(iT�-���^u��.���v��I�h I�w������[fo�(B�����<�9��vUVE���P	3�a6�JxM��<�7�9��6���.����Y���
���P�A�>���)aB�����a�j�t��Mky�B����P�@�o����������gV_�������M����������lbu��[�=�v��� �������|�O/���0I�!H_�CP��]h~s�i�qc�,F�� ��2���'"t	b��� K��mIgtZ��bl"�=naf���N�b�L��~�-�A�J���D��DS!��Bb{���:��d�V�Qu_
�V�Y����������������Xfz��Z�H_fY���������-�d�B���RY����s�Y��C���8�4�&������13R8�#���<���Z(+o�*(Ke����<�,����b�l���L���B0g
���*������9�%!9$�!1�� �
i��F��=�����Xk�;�)5��p�t:s�a���9�9�@l/3i2/Y:9��Q��^c�Vd(��.>��^�/��������C7����C7���M���6t�����f�<�5����=��`rm�?�����l[��|��OX�y\����l����-hz�07���d2��[d+*4�9���I�4����'������5Cb���j���%���tf���W5�����	�-�8dVz*5����
H�9����m��cu��A]�����f��3��n�6�j|��{�A���D�� �� :K�wA��U�
1l����f�|�;v^�������gNJo�GE���x�{)U"��PkN��-$yzK>*��.���D<���
H��D��-|t�N��L�T��uf�E!�w
�A�M2�x�ml4(!��=$M.����r�o�����|�������b �1E���p�_���0q:�M��-��_z�����/V����nA�!x~�����l�vf��ul���2�>�q����-�����[��or,w�z�����F��-=�(/��c<�dJ�C��ap�06tb�f�#���$1"�h��=Vf��/��^)aTJ����w2�����������������	&��^bR#�4�s��\�0wA������������B��-���z�V��I$�J�5B��������Q��	��+�a<����dNk�f����={��5{���'�}����,�5}���.]���5#�>��
K��:�7s�{o�vo��}+�Oc{o���~��'���tj��a�����	�G����p�.p#���t�Z(4�s4N����AU�����T@�f�s45)L����������,��
��VN�g�14N�<h����4�HK��=��=���	{���L�+���\.?gLl$��G��>��=8-��DM���b����U������h5�3_�H�|��?���}����uG�����d�E�s�I�gG/��&z]���-�k�OF��~�<~"�;7�.�LP��a���Z�A�
g��xa�0�D2
��K��pMm7� b����^��nV	v��������v������5�d$Chr�|�g�����<I��I��G��u�9��H445��c5�~d�X�=yEyii������|&�D���}&�x����we]����43���������O��_{t��mO.�n#�^s��%�����,���k�?m��������#�?�s���QU#�L})��=���'��V��(��upU:����(:���YS4�9����*��k�D�t
5:�������������
�E�9�a��o��$����z)4	�]Ars�b�X8Q\T^)W�/(c��f�����w�?8Hx���������J�����t��K\���]�])�i�k��[$�F�D�5��H�E4M��EC�"_�K��K!vs�����#eIh}mN:��B���OO7C���_��4]�w��N���I8\I1���U^������?D�� !�)��)�4��\�;�P����F�+����
�in#�(�*H�W$��9K��	�����Q��c$Hy���R)$A&Rs��J���U��<9�^��P^8�D�r���A�%�{��
�)�
W�B��5W��.�KE�v%L���O��OiB!��.�[�����q�d�:?z�xX�D�g���8�@VI�<�-m�a�������XhK���GH�t�&��k��TON.�P0����G;��5��JR��]3�<��������[��������n^�y�j
e?��d��	��gL8?�����Z6t�P�����]���q���n��4���c�����}X��)P{��s��=�����Q��(��]B)�-|7b"�"t�P�G��>������v���0
S��n7��e;s�Zj�X���t�����o�RwM����Y,����'4�72T��
=���:7����3b��gH3MW8�:���9vXw�v8A�r��\reOt�q/qKnF<��hP�8�5��1���m�3cL��r�%��X+�e���&N���Mr�`�\{"�jq�t%z�fI";��Z�+�`I"2�$f��X����O:::�4������.jf�Q3��:f�,M�6wI+�g��t2=C�5��Cc�'�>��?N}�aW��_�9��#�D�>���XH�a�����9������f|�����9��7?�AlKd����7�4�6�,��A��lO3�t���Y����w^�%s���M��lOr����<g����T��H����]��~)�b�j���M�{������g�������|�q8��c�D�*X�[3w���N���9��s����~�m��R�g�����Ke�eW���K�[�^����xV��e���=+V1��6*�M��T�����1k=u9�$��	?��K"�#�,I�Bt�	�g�;���E��!��0����D�V0�B�����j���fa�i��{���Sf��c�Y2g
��������� �QA3����b�i�DbKS+��;RUPS���f7W<��YD
�,��UA%�F�2km
w��o��W�|���{J�7�����G��v����V�zd=�V���]'�s������������z;%M�c]2��n�jL5�����,��T�%@�F��#�(��.�%�wM'�'�ro�H��^�!�^�#�"�O���NJ_�,
��'�*��

���`�{��A��*������o&.�N�b�Td��}(B�����Z��BI'�=�[t�a')l�y'��ZPT^�d�(�s{����S�,���I�N�u�&LU����5���-*7�Z�zM�[�{�XwMV��nZ�n�����Ch��`���yT6������W�4�JX�^���4�|C,�h���o��%�3�t���ov���[���m�b���m[6yu�{|�����?���i`1&1+l���5�e�tv��>�#��Cr�3�	!�!���2w�$�9����<�x����u:�#{#r��5��gX����nc���dI�z?��|b}I9$!1�!�f:� �;����]�����Dz�|
�H��7�t"��_���l�g(��������4�L$>�L��4x$y���,8�lN$N�f8���R��M�!/P�8����>W'�����3������,Q�t)K ?�/��T�U�w#��i�r�o[���������^���Ai��y���_�}��������!��n!}����J�R��n7���y���~~���(����s*�]����c�c���'m�\�r�z��,\��xC��kV��������u�5������j����+�2���o<��h�[
�}f���8t����!@�_�TM��n[��t�-(�+k}���q��d�8�����J�jCu!����.�8$�q�E��4&��(�J��T�\��4���9/S'
^?��.(g���AvLSLSLS,w����cw�-����ahih�e��vuG�V���	�N=kgn!���D��,���g�t�}#�ZB-��y�����#�U���y����F,��^$�Ce�1�o�����^�g�u+�.ve���.����_����7�����n��\�����y�S�w���U}xc���;=�_=%�i��������+$��������R�P�8�u�\!��v;eQE�C����L��&��ns:�a,��V�����gM�u-OY�^+
�L��ZE�������#�bgb�R=,=�-��Om%��t�M�$tb���

��P���>x,��7�����~��~��~���<!7�*����#��X��^r2�B�n�PZ�'�A!!�\\28ox���6O�UT�v������I3{�]����Kq��\�#�9-(!���,��;)C���zr<b���gE��{�����+f
�������;k6=�4�o\q����kz��J\\|D7�����S;*"4��������Q���I�eP�k��"TDh!6n2L�&������M��
�E��#BE�f2�a����B-!z�!�������n��[�Z?��������Y��E��)�-fE��,s��H��E��3PL�lS�y&����zy�|XV���dr\>�9Y&���[�_�/��Y(
�P�h�F��F� ��%��U�8�:�r=�}������U�$\��


���
����#.��n��lH��z-�Z?���z��Z!����z�����$f�nLm��]���^^����hqv�v�*E��3�7}l��ap�$�LsMu��IF��qIc7z�`����������������V�'&_��]Ek3������0T>{	h
h�O� $���8q��
��'���P�G���?�>]�����h	���0�/�H�������(zJ����p�g�KF�e$�F�g�P�Hx���H�Q�	���	����	��M�;���#���B��Mo�N�y������VI��LW���L��FT��<�&oC�����5���*,�O��$�P~����u1��F�!6R������Y�)V��[Z�-b
��Ici�����Di���PiBR��7�6k*#�A]��4��xY�x}�P9BM���C����cP
�P~�[4�T���j�Zmu�p�� �'�BAh$)t(Dr����Y��m%���j�B����|��~S�~>w�h\�<B��<��Y��>~_���Ic^g�P���s������E!q@"��0@[���������������=gB���i;e��r��C'^2v���M���&��{S��|��E������nU|��d[�>����j�������t���t���$w���S��Sa9n���A/ZL	:mN��e���8�A�	�
K",�
��'������v!F������]���A#��'�-�.�0Y��g&�UL�E�X��
o��������AA7AACAA=A!�N4x<�4�i�������2)d]��Mz��(CC����O32�3��	���[�4����3���j���6IQ�=�+��m^�`����D)Cw_���_�a������h������n�7wH�uM���g��������7��\�+����3 ����sbq��er*�"���l�8�SX�(�,�*3,�r���G�"�O���`�`�@���/�6��NQg{g���b�br^$�2��]��L�j�j��a��f
*�A1~��'�'��4��H�cn�Pl���I�!��~}C;�5k����t���w630��8n���M��1J+�1�\�v	rq94?���\p�h{��E8T!]P�p��CHK�3 ���`� ��qq�]��.�/���u^��D���l�0���_���YG�FZ/1]b�Y�8�K�����������n~�}���[>n>�k�����/[���X�mW6�����7�L�|������k��`W4����*����I.t��s�A�\���X��#'�4P��;cn|M��#�#m`h`�8�E�	�	i3-�3���Yi{�o�?}3���H��x*��j"P!�P�����g��3�U��%��I_�]vpE��!���,Fr��jK�jmu69.�"���
~��q��z���~����f�j�F�]A�d[�|e�LwjN@�!����5l�g��c�l��0�I@0�a��0L�!�@FBE������0q|������y�����HS.b�y���m��dF�����g��<����8�+�H�V|��wN_yh�_;��N���\���lm�a���#V��{���-�{4��6�����������H�������CJ|L�Y�\.��G�����b�X�����:A�0�X0�Y�X�%;�c>�}�O$�M��.����W��J�*������FN\e�6r�����F��Zs|��4��J�j'���p]��&p>�1����1��\�p��]��w�s.�g���
��x�y������1W������t�PCjn.��������8-���*���59F"�Hd	�l�\"vd��������c��f/��f�)�1�S�/JNk(uT�N���Gs��2[x�e�u�m�}�c�s�e�u�m�}�c��!���]��[���k�x�8���)�s����e{�qg���ww�d{��H�����/�
K3�H��\#��b|�b|�b|�B��GIof�xKA��&G����)#J��H�p�G�#�"#["#�;���|�c��#<�;�����'�T]eI�Uv�q`*��9�������3�iB�e<#=`��sR�G���~�������(��F��py)5����WG���"qj�S��8��_/=����/s���b��[�/��^y��Q������U�v�K��Wb
����R#�*(*�-�[��K�Jy)9�s!��������s�F&�KPK��T�u)�cw���L�|qI�%<`�7L\wg��f�.���f�����
����C���Dby�[�G�|+A?�'bi��LD�Q�~��L��cf��_��Q��O��lg<
���4f��A��Y��4��q:,li���jSr���|�;F-�rQb���-�3L���|��-g]�/�/��+��v�g�I��B�\S�����7_�xQE�]����{�#���xO�c���3�������;f������M�5j�ss�y��/z������k/
_0��n9�>[nY������i�����x��~���o6n�4�k��;�ZB16"���r+Q�HL�E0���$�����:S���l�f����MSc�2[�Y�������k�2����\o�k>dV��I�5���{���X����8���d��"U�)E��4������0��uZ��=*�������*q��TEJ�SV��B[~�j^H;�"g����'/.}q5:�����o�i���Da���j���������[W7�5�8J������2�n�Q:
��y�,w���y��	������Q�yp��,h�_���l����!�hD�.&$�/!�pt���	�j������[�����6D;'MY*���Xhh���6-�cQ>7�!ZMEe:p'?�XJ�Cw��(R��b�z�z�*[
EjmQ��o�&<�����V�k�
G�uh�,������DS��^�U���Yd�����n'W��b��Ev����I��-ES[�g���ed5b������}�#�T{��s������`����*�;������#o_�+O��+��<B�W4�g��knb�_�����B9�,�Lw�@�C���"tj�0\3I���&[�Z�a��%��q{��Kz�q{�w-���$�F���"aoA����N�>J�N�,��qo�IIg�������*f��t���G�������u��^�-�
����������\�\���s����2�*�j�j����lO��W����e�����I���J����I���i����&����_����5�JKvs��������|y^�3n������P��|t���� ]M�%�{�yz#�����H�����������=^�md�w�Y6�K��#1[����c�C�H9�kl/�+��!-�N^�<�9��QL
���D��G�a��HA�	��N	�u�>���g{���.����oP�k������c�C��%�S_2�1��3����*m��*](�v*=���qD�0�&������	H�
���ce�`�k7_�_��d/��S\5 ��7��g��a";������^���)o��I�07m�;C.l��������N�qK�q#IHo!-��;YX���-qo#�����*��7�VL���Y�{19x��D�d���Y��r�u�:����,������d>��k�B���[�2����q�����������/�����(���J+��)�4�a�q�������y�tY>���/�Mr���S(�������b1����4��F;�l�W�U��ss��(����z��s ���9�Vf-�������JGq�8�G�j�U�g�1>7$�V\�Ou���H��:{G�o!�P�=�%�^|�f��RT�_�����>���I��/�M��Z�i�Z����J!Sm�J�GD��}�����)9YYf�Z�(���m&Miza��3��wJ����.������%�>"�vA��Y�U�[�,������E�6���'�4]���!�K~L���=��BNn9y�
zy�?�8E/����z��X^�����4��0-��)���0�n�|/�wS[�?�1�
1��� &!FR��������/����1�I5a��^�i�u�~X��P*a6�7a�=2@7��m�Q6�}X� >��e�0�������:�i��V�P�P�����{���� �7��q�������p��#a��+������z�c7b�+��W��{���jl���1�q(�Y�B�4 a�����_�}7�e�N���M8~}L?�6�A��}���+S�alm5����
�����Y�4�~f����|�o�$R��G�s�)0��9��k)�"� �$?����]����1�����@G%� }���/E��w~)�a
���;a\&&hh9b5���1O47�_��z�u�8��D���R������������1��X���@���~;�$�����<�>��X�V���������3�l?�'�P�N��#f!z !
�o�~%A�H3D��>�6L/����j��N���3�wQ?Y��0KG����h���x7�����%���N���yO���1D�2b�;3��=��\��Z���fi|FL�B�&�yB��Z}kg�#K9:��h��\���a��V�e� /��p�|�J���3���`�z�5\`�e���0��>��m6����)����!��y��<[~��LO��n���)~�H�(n�W{F1���������)��O��2��J���I<a��uF����!�E���2�5�G��G�������n�^\��y�,m���n����S��:��o�rs&�{P�a_���@��xn+::�������6&���Tc��
Gt�@|�t4i2B�����(��5zM�l��W�Q�o1��
��jC���t�6�����8����'�H2�d$�9�3F��q����f�c��`����:�?�y�0������?����zB���PJ1�W�)�8~���:6�����.���n�QS����&!o���=:F���l�%�S��(�x7�<�����%�������i�#�#&�����^ �(���L��V�Qz�j[�/��B�+�u*�Tf�V��Ry4���0������Cko�w��oC�I��� � 	���������0O3��P�C��(�$����&1�=�"D�4�N%{�kXo
"m4��F4J��	|���n4��E���.B�Z��i%��?>uJz
�g�u�T�s��Mu8������5���G��D#��(����V�	����[��V�I��,�	��3����>��m��o�rj[M���/�$��:a��)���w�(
��H��,w�<,��H�d4f"�h��u�� �T-fY�
�Q9/�?cv���]�R�!��R���:�B^���0Q~�a5�eJ���
h[R�AN�������U�~%\.O��V����&O���v���Nr��w�^�S/�A�Z��ROS=�GC�B�<:�v� �j���� �����8^J�5^k�8�1����w�{������P�D�7����S�
�=�#
�����8���`@��\�#:��,b)��1�=b��G���G,�w���v�xo�J1��C��x�x���O���)-�����5v<����>�sW���|nj7iq AY~����
�<�������v@�����~	��s�yL��Fc=0���U�X�
����O���Q#��h4.�N����w@��@D`�#�}�|���w��6���4�m���������v�������� Wc}D����IP^�g/�8/?�+E�Z�`����0( �\k�� �!Z�QF ��h��������5D��
�Gh5�]i^���sc}�ui�>8�����q>����x�����|����%?U�
ot��w��	�;�"^F���/H��|�vH5��o�}r�mBYr����Q��P{7w@81���K1~�������okHq9
6�ve�v�m-��Fj�O���q���������/��Sb���a����M��=o���+�c�k�_���50.F�^l����C�������1�,�q�1�ya������������^�X�_�[����<������[�}~i�c�����!�N5�M� ;�lY������b�&�X��o�d;��J�3��o>��h���q�z��le�aBE���,��/H�������=��60�B���:�����n���1>����7t�![$cE��o��S�?���:&�������|B[]����t��X����n���O���7`�	�s2����.���+�_�s��|[��?���K�|[��y[�3��(D[����S��B�q��7����[�M���k
���}��������Xv��4�Z��R��@��l>��z��zv+��SM����|@��c���s[�%�\��8gB���C	���1�Xk�Cb��r����������@��5��y�g0���e�_���N��������
���3>�T�r��3P�������o��+�O����mv�s�Q��?��2��_�j��s��w�/D}h%����gB�d��~����W�!�
_2��H_)�@~��~�O��<�"�e��j4�_���Y�
��KC�y�|����Y_�u�)���D�7�#=7b�����A%!�WFz�t�O����m�i����&������_���?����J�c��m�:~b�v^�:��������s����l��m��`�t=����c��������K���B�m����O;�!���9\1��u>����<���O�������"��!"��|��|�|����X����+H��]��&X7��hw�vn��DT���a��tvd��A��<V	�Z�a�O��x>M�1������F	���3��\(����(�?�j���o�c1WIl��}}#��:�3�t��#�������$�����C�4���(��q�����F�����d�S��
�5�h��WX�.�w��B�x:6��4�4�xm�~�K�J��Y�~N8NOghi,����;6�c���R� N��`��a
o�>6�X�IE�kls��B�������F�������S��zy�-����m���b?W����s��m��������������������s���X����X>��8P>�>�y?�M�������;��1F�k��i�_��������E��7u?����:P��h�� p_�q��`����0�I��(B�������i}�}6o��7=���������D�${wc��X��J��zm��w�����}�hW)	q��a<��whH���"�/��>.Jg��A��,���\���Z�������Z,_���=x���+������w)�}UP�8�yz��@2�4U���4u�}2F�����I~	"��`�|9��v�]|�[�C����In��!�C��R�	���"Xak���u��8��a��V���������^��L��5���G9�c}����)��t0���l��h���>�l.����?�t�
���p��nF�-g�f�c�c�E��t1X���v��{k�qo�T�s2E�g�8szd����[���C����W	���a�r�CA;5!����s������B�
�7�����Q`3b:�3�h�m��{�+��t@Kl�����`5��hk�vT�M��Z|��`L������������}���	�H�X�8��������=0�,a�LS��H���4���� L���,�����M?�-:�qm���~�x�<��b�_Ok�H�E��7��i�^>�1C{N�RK�t�������Z�&�����V���5�}H������Z�����=�O�_��M�0����3���]O7�h�}�<z'��#��n������X��?�������6n{����������}���/����{9���'s&N��������>������'w&V~�j�5I�c�~(���n�/���
Hgc����$�egC�����a��E��	8��R��Z����^!�������u}���_����+����93r��+b�t�/���[�H����h�~�����[�l�����t�O����i�����3b������q}�[��K�|:���O!^�qy%Jw���HOS�}��6?��[qoJ����EA�������h�q?5?�����y�v4��3��~�v�.�r��a�~O6F��.�yg��v������S��4a}�i!����1]�2�X���%h ���t��c�f����� qx3<����$P�o�Q��&;v���/��3�2d��/��S�K�b=\��{�����h/�y�4	z�����mEwn��e�����8/��'Z�7���{5q'��i?���_�7�����4���w��������NdI��0
C��uG��$����B\��3�M�Q����Ch��|b����"��.����I���d����	��&,�A�j
�\��w�������zo�6��^}M�z����������
>_���h�w�+P}���c=S�t���A���9���+��������5u"*p����dGD�l��a�U��^�qN���g`��\�hjB�����Pe:���P�z�i Z:A{�it�X�%~;����6�����%8�������?���;Z�#��S����4�L���xM����p#�q����4�|mP�=Y��Z(?
�G{�f����H�
-�W��N��nb�������Mu��
>��k��i����� �������!�}����C��y�������?���g*m�n��]�_��9s���2�U����^��lN���gw�|�D�!��Q�^�Y�#o/�=�����D�O���+S^-|�����eSo�7�:���A�S�7Gv������k������w-~�rM��d��t��i(o��l��@?�� ���,~��8��"i^����`�e�-wi���W�Lri2K|_#�3����������oi2��uG|Eg5��{j����M'59)d!�!1-~��������;�_��t���6�sF�kv���)�����g7�K|B'��no���L���\�W�s�A�����]���v�����<�����k~���Z�5=M���e6���E(��y���q}��?� �����3�r�^�yl�.E[�3�I���V��Mq��xT�e��`���:�%�!��� ���TM��o�h^Z�C���@�.�8_��je�f�Hu0����]A�v��f�+���#��2������ ���G6�D\8����6������n�����s �u��*�|����8%�g��
��~�qJ�(?���$@ls�c�.:���{���hG;���v���hG;���v���hG;���v���hG;���v���hG;���v���hG;���v���������;����T(��������`�FI�����C�K�0�K�%2b��)c�9�d����(u��(��m%"�c8��!�D)�U� �[{�
��4���X�8LO�)}[<��*�"�6�ctK!��BH��11q;b=B��db	b��x��B��,�����"��3/+�IZvB��n�p���}������u)��;����b-����Qls�������A�\�n� ��#���%I��=7�t�I&q�����Jl��S���S�[�B���jO���.O��^�'��!�O��o�o���9����q�-B����c���n�!� ��{�"��CU�Q�)]���U�>~����{�z���C{s[���]"�(��<=J��`i#���: E��J#E='eCO(����u�5J�mU3b�����DlC���-�Gp�[��[GG�"�"L���w���Q�@*�PE������@gD1a���a7�������^A�B8��E�:�/���K"~�L�_���e�����Q1V1.��&���\o,�������0,AT#�!&"nG(|��6%���<�Zkn����1x����d~$�8�=������y2���1KA�mwb����Vc���k�b�������Sfb����1EA��Q�����{6� �m�,���W�,]��t��U ���~�ill+*�[�Lt(���fu���X���n*����-euU��bV�`u��.��%Y�s�Ocg��F�������vBpM������l����$.��]���&!��uY
�P�uz#�C$"�	������bl#k� �'r��H���'�fv�6"H�������{���k_���05�~{�9�qm����k	\��� ��8�Z\����L��jf�M��4<}|\f4
k>
�������Z*@��
��z�9����'Goe��6tl�eh�_A�p������
|Pf@n����t@����o���H�&�� � ]l8� ���6�g������5�(U�~����\["�E�t���(@��
����x�~�E�����m�0\����x�,�U#�+e_�_��V�@	=�L���D��1$rA�6���k$��|��jIO���?D��������l�qC�,[�O�����%�����A�����G����:U-�#� } 2G�v�0�������4�4qYRM���2�
��M]�}Z�k0���`_Y�X�|7i�Uu����i�
~��������/�	~��pN��Kp���~�s�*t���.��#�I7FnV�s�d�Ow48�"/�tN��a��� }Y&��,�}}���a��#}>G���;�$����y�X���V�}ja4_�p��6B��Zqa��q'D�+w�3�L_�w�-������m�<U�{�\�|6�(�t��N���K�m������UFq��������Jk��[x�qH�G���9b���C����6���
R������{<�sc�����Vd���1/��3�q`�q�jh�1��eH�!�HDd��D���"C�!#�y�l�L.��m�{p�x�Q��Q�)
n���R���c�
H�|v{5Hj��\_1�C&�Dyye���
1b���4��*��.Qw*��Q)?_�����H��|lI3������\�'��f�6C���\���$uh�$����
j��Bl�����J�nr=��^�����?L�����C;�m��Qr.�#^������.����<�}�+����v���so,���������5�m����p�T��:��'��fV����N2��u�k���<�������m��Ijt�N@j�Jm�����9�mk[�v�X��*2
���<
��\K���.E?LN��
6�c8��������T���3UG�=��y<%'�,�d�����S
endstream
endobj
16
0
obj
<<
/Type
/Font
/Subtype
/CIDFontType2
/BaseFont
/MUFUZY+ArialMT
/CIDSystemInfo
<<
/Registry
(Adobe)
/Ordering
(UCS)
/Supplement
0
>>
/FontDescriptor
18
0
R
/CIDToGIDMap
/Identity
/DW
556
/W
[
0
[
750
]
1
7
0
8
[
889
]
9
15
0
16
[
333
277
0
]
19
28
556
29
67
0
68
[
556
0
500
556
556
277
556
556
222
0
0
222
833
]
81
83
556
84
[
0
333
500
277
556
]
89
91
0
92
93
500
]
>>
endobj
18
0
obj
<<
/Type
/FontDescriptor
/FontName
/MUFUZY+ArialMT
/Flags
4
/FontBBox
[
-664
-324
2000
1005
]
/Ascent
728
/Descent
-210
/ItalicAngle
0
/CapHeight
716
/StemV
80
/FontFile2
19
0
R
>>
endobj
20
0
obj
292
endobj
21
0
obj
14208
endobj
22
0
obj
304
endobj
23
0
obj
21100
endobj
1
0
obj
<<
/Type
/Pages
/Kids
[
5
0
R
]
/Count
1
>>
endobj
xref
0 24
0000000002 65535 f 
0000196679 00000 n 
0000000000 00000 f 
0000000016 00000 n 
0000000142 00000 n 
0000000255 00000 n 
0000000420 00000 n 
0000158762 00000 n 
0000158721 00000 n 
0000158743 00000 n 
0000158918 00000 n 
0000159069 00000 n 
0000173865 00000 n 
0000159213 00000 n 
0000174247 00000 n 
0000159581 00000 n 
0000196011 00000 n 
0000174455 00000 n 
0000196398 00000 n 
0000174835 00000 n 
0000196595 00000 n 
0000196615 00000 n 
0000196637 00000 n 
0000196657 00000 n 
trailer
<<
/Size
24
/Root
3
0
R
/Info
4
0
R
>>
startxref
196738
%%EOF
uncached-transfer-reduced.pdfapplication/pdf; name=uncached-transfer-reduced.pdfDownload
#35Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#34)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 2, 2024 at 6:59 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/1/24 17:51, Melanie Plageman wrote:

On Fri, Mar 1, 2024 at 9:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/1/24 02:18, Melanie Plageman wrote:

On Thu, Feb 29, 2024 at 6:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 2/29/24 23:44, Tomas Vondra wrote:
1) On master there's clear difference between eic=0 and eic=1 cases, but
on the patched build there's literally no difference - for example the
"uniform" distribution is clearly not great for prefetching, but eic=0
regresses to eic=1 poor behavior).

Yes, so eic=0 and eic=1 are identical with the streaming read API.
That is, eic 0 does not disable prefetching. Thomas is going to update
the streaming read API to avoid issuing an fadvise for the last block
in a range before issuing a read -- which would mean no prefetching
with eic 0 and eic 1. Not doing prefetching with eic 1 actually seems
like the right behavior -- which would be different than what master
is doing, right?

I don't think we should stop doing prefetching for eic=1, or at least
not based just on these charts. I suspect these "uniform" charts are not
a great example for the prefetching, because it's about distribution of
individual rows, and even a small fraction of rows may match most of the
pages. It's great for finding strange behaviors / corner cases, but
probably not a sufficient reason to change the default.

Yes, I would like to see results from a data set where selectivity is
more correlated to pages/heap fetches. But, I'm not sure I see how
that is related to prefetching when eic = 1.

I think it makes sense to issue a prefetch one page ahead, before
reading/processing the preceding one, and it's fairly conservative
setting, and I assume the default was chosen for a reason / after
discussion.

Yes, I suppose the overhead of an fadvise does not compare to the IO
latency of synchronously reading that block. Actually, I bet the
regression I saw by accidentally moving BitmapAdjustPrefetchIterator()
after table_scan_bitmap_next_block() would be similar to the
regression introduced by making eic = 1 not prefetch.

When you think about IO concurrency = 1, it doesn't imply prefetching
to me. But, I think we want to do the right thing and have parity with
master.

My suggestion would be to keep the master behavior unless not practical,
and then maybe discuss changing the details later. The patch is already
complicated enough, better to leave that discussion for later.

Agreed. Speaking of which, we need to add back use of tablespace IO
concurrency for the streaming read API (which is used by
BitmapHeapScan in master).

With very low selectivity, you are less likely to get readahead
(right?) and similarly less likely to be able to build up > 8kB IOs --
which is one of the main value propositions of the streaming read
code. I imagine that this larger read benefit is part of why the
performance is better at higher selectivities with the patch. This
might be a silly experiment, but we could try decreasing
MAX_BUFFERS_PER_TRANSFER on the patched version and see if the
performance gains go away.

Sure, I can do that. Do you have any particular suggestion what value to
use for MAX_BUFFERS_PER_TRANSFER?

I think setting it to 1 would be the same as always master -- doing
only 8kB reads. The only thing about that is that I imagine the other
streaming read code has some overhead which might end up being a
regression on balance even with the prefetching if we aren't actually
using the ranges/vectored capabilities of the streaming read
interface. Maybe if you just run it for one of the very obvious
performance improvement cases? I can also try this locally.

Here's some results from a build with

#define MAX_BUFFERS_PER_TRANSFER 1

There are three columns:

- master
- patched (original patches, with MAX_BUFFERS_PER_TRANSFER=128kB)
- patched-single (MAX_BUFFERS_PER_TRANSFER=8kB)

The color scales are always branch compared to master.

I think the expectation was that setting the transfer to 1 would make it
closer to master, reducing some of the regressions. But in practice the
effect is the opposite.

- In "cached" runs, this eliminates the small improvements (light
green), but leaves the regressions behind.

For cached runs, I actually would expect that MAX_BUFFERS_PER_TRANSFER
would eliminate the regressions. Pinning more buffers will only hurt
us for cached workloads. This is evidence that we may need to control
the number of pinned buffers differently when there has been a run of
fully cached blocks.

- In "uncached" runs, this exacerbates the regressions, particularly for
low selectivities (small values of matches).

For the uncached runs, I actually expected it to eliminate the
performance gains that we saw with the patches applied. With
MAX_BUFFERS_PER_TRANSFER=1, we don't get the benefit of larger IOs and
fewer system calls but we still have the overhead of the streaming
read machinery. I was hoping to prove that the performance
improvements we saw with all the patches applied were due to
MAX_BUFFERS_PER_TRANSFER being > 1 causing fewer, bigger reads.

It did eliminate some performance gains, however, primarily for
cyclic-fuzz at lower selectivities. I am a little confused by this
part because with lower selectivities there are likely fewer
consecutive blocks that can be combined into one IO.

And, on average, we still see a lot of performance improvements that
were not eliminated by MAX_BUFFERS_PER_TRANSFER = 1. Hmm.

- Melanie

#36Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#33)
3 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/3/24 00:39, Melanie Plageman wrote:

On Sat, Mar 2, 2024 at 5:51 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/2/24 23:11, Melanie Plageman wrote:

On Fri, Mar 1, 2024 at 2:31 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

...

Hold the phone on this one. I realized why I moved
BitmapAdjustPrefetchIterator after table_scan_bitmap_next_block() in
the first place -- master calls BitmapAdjustPrefetchIterator after the
tbm_iterate() for the current block -- otherwise with eic = 1, it
considers the prefetch iterator behind the current block iterator. I'm
going to go through and figure out what order this must be done in and
fix it.

So, I investigated this further, and, as far as I can tell, for
parallel bitmapheapscan the timing around when workers decrement
prefetch_pages causes the performance differences with patch 0010
applied. It makes very little sense to me, but some of the queries I
borrowed from your regression examples are up to 30% slower when this
code from BitmapAdjustPrefetchIterator() is after
table_scan_bitmap_next_block() instead of before it.

SpinLockAcquire(&pstate->mutex);
if (pstate->prefetch_pages > 0)
pstate->prefetch_pages--;
SpinLockRelease(&pstate->mutex);

I did some stracing and did see much more time spent in futex/wait
with this code after the call to table_scan_bitmap_next_block() vs
before it. (table_scan_bitmap_next_block()) calls ReadBuffer()).

In my branch, I've now moved only the parallel prefetch_pages-- code
to before table_scan_bitmap_next_block().
https://github.com/melanieplageman/postgres/tree/bhs_pgsr
I'd be interested to know if you see the regressions go away with 0010
applied (commit message "Make table_scan_bitmap_next_block() async
friendly" and sha bfdcbfee7be8e2c461).

I'll give this a try once the runs with MAX_BUFFERS_PER_TRANSFER=1
complete. But it seems really bizarre that simply moving this code a
little bit would cause such a regression ...

Yes, it is bizarre. It also might not be a reproducible performance
difference on the cases besides the one I was testing (cyclic dataset,
uncached, eic=8, matches 16+, distinct=100, rows=100000000, 4 parallel
workers). But even if it only affects that one case, it still had a
major, reproducible performance impact to move those 5 lines before
and after table_scan_bitmap_next_block().

The same number of reads and fadvises are being issued overall.
However, I did notice that the pread calls are skewed when the those
lines of code are after table_scan_bitmap_next_block() -- fewer of
the workers are doing more of the reads. Perhaps this explains what is
taking longer. Why those workers would end up doing more of the reads,
I don't quite know.

- Melanie

I do have some numbers with e44505ce179e442bd50664c85a31a1805e13514a,
and I don't see any such effect - it performs pretty much exactly like
the v6 patches.

I used a slightly different visualization, plotting the timings on a
scatter plot, so values on diagonal mean "same performance" while values
above/below mean speedup/slowdown.

This is a bit more compact than the tables with color scales, and it
makes it harder (impossible) to see patterns (e.g. changes depending on
eic). But for evaluating if there's a shift overall it still works, and
it also shows clusters. So more a complementary & simpler visualization.

There are three charts

1) master-patched.png - master vs. v6 patches
2) master-locks.png - master vs. e44505ce
3) patched-locks.png - v6 patches vs. e44505ce

There's virtually no difference between (1) and (2) - same pattern of
regressions and speedups, almost as a copy. That's confirmed by (3)
where pretty much all values are exactly on the diagonal, with only a
couple outliers.

I'm not sure why you see a 30% difference with the change. I wonder if
that might be due to some issue in the environment? Are you running in a
VM, or something like that?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

pathed-locks.pngimage/png; name=pathed-locks.pngDownload
�PNG


IHDR�e��ai IDATx^���WU���gf���$x?V
x�TPS�	�����4�:"&^���M�(*��
�H%�o`�c�A�)C����0��^{�a��wY���Z��{�R���z����_�-�����6@@@�H �6�2:��@@@@@�� � � �d!@���C@@@ Xs � � � ���:<E@@@�`�9� � � �@�,�8@@@�5� � � �Y����P@@@�� � � �d!@���C@@@ Xs � � � ���:<E@@@�`�9� � � �@�,�8@@@�5� � � �Y����P@@@�� � � �d!@���C@@@ Xs � � � ���:<E@@@�`�9� � � �@�,�8@@@�5� � � �Y����P@@@�� � � �d!@���C@@@ Xs � � � ���:<E@@@�`�9� � � �@�,�8@@@�5� � � �Y����P@@@�� � � �d!@���C@@@ Xs � � � ���:<E@@@�`�9� � � �@�,�8@@@�5� � � �Y����P@@@�� � � �d!@���C@@@ Xs � � � ���:<E@@@�`m�9��+��M7�$��_���J�>�h�<y�{��-*�����k��%K����[��#��)S�������+W��}���%//O�*��M�>}��7�}-!�@@@ '����7�/� ��
�]v�E�9�)((�_��W��'����k1bD����4H��_/���w�c�z��p�����'����+V��������l��%w��w�������w��q��7=	�F@@� X[��8@����o�!���_X�
��z����S��Y�P���e��2o�<9����UW���cY�j���������Gy��^�ZJJJd�}�	�_�p�>\��'�f�j�!�}-��@@@ ����F��G�g�!�s��}��MPW����?��{w��-�E\]A�{������n����_/��z�,[�L��������e�]&��{o�q����7KQQ���o���@@p_�`mi+**d��������j�z�Y=�����.]>���u�]�����O�+��R���+#G�l"�������d��������k)-e!� � �Z�Z9�L]�����&��~�������C��^���O��?�u�]r���7�l����n)=z���3'�}/��R���^�0`@�qg��-c����~X����I:�f�� � � ���k�z���{�����THV�6�}����%�\"�<��\p�M*W�j�g��m����o��W�0M��l��u
�W���b�5�!����e��� � ��D�`���UW�������������g�:w�,��s������<�����o�~��t��=|����?����%h����3^*�7�,X�����'r��W�/LKu��8@@pG�`mq��-������g���H|�A�����[�����[�k|U Og���;/��M���Y]�Z�����������g����@@@�]w�5|is���� X[�&���~��5���<�6.��k��
����^�6s���S[�_���g���|:��C�c�y����C������������ �����.�����;l �L���jQ�,P��u��)�����!�o}���=z8!A���M������w���;��&������^r����/2S�W��	&���n����r��'�w�!�&MJk��[��}�Y1bD�q�?�������A�n1Oe�Li����njMl �<�����?x�!�$o��B�����W�z���
$L@=�������"X'���.w��Er�����x?��M�y�����[�3�/��7�.�=��[}����$�w\�/���[�/���i��5W}����_�-[����8�}35!Xg*�q�!@������l���q,��������U������+n���i��p�	��}��W��_�zX�z+�z;������3���>��?<��9j���t���W�*�
�
����_x���{9���d��q�����t���`��� �����^�2 Xg*�q�!@�����W��L����+�����-�~���Tn��&���jR��B�
����*L��}�����~�x�����?�!|��z��zA�g�}&O<�D�	/uu������7L�u&j��?kz�J�T�`���!�����>����^z)����zi�z�z���2r�����|���/^,5552`��2eJ�,v�-�}�m���ru��k����o|#�������b�t�M�`���#�����~�2 Xg��1�#@�����$F�u��L��k�@	�,@���L�@�����~���#�@ S�u�r��?kz�J�D�`��� �L�`�)�@����?�G@	�9H��:��g���� G��6���(@����P8(@�v�i�l�����P&�&��;�v���0%@�6%�<^��n/�C R�`I�x/@����,�v�� h Xk@d X;�<JG@��Z$� ������Q�]k��A5� X�g>� X��*B�����6sy+@����,���)1�^��n/�C R�`I�D������>w��!���:5'�B�W����e]F�F��������0.@�6N��X%@���������Q7z�z��.w���^�`��!#  kN�-@�Nv�Y=J�`�y�@����?��$@���08*@�v�q���F��FL�B�A���M�d������0)@�6��\�)@���/T��)��)i��Z�`�u{Y��H"v@�{���-f��+@��A@��Z"C ������Q:��� G��6��� X���A�����8�!`�����P&�&���[����ea�$@�N����Z�`�u{Y��H"v@ Z�`m��,@�����
����9��
�}�,�2*@�6��dX'@���%��q��qr&D�*��U��W��v���#@����(�,@�v�{��@���
!Xs �l�u����Pk��-@�Nv�Y�&��&H�A�Q�����l4
�5b2
�l%�'@���'T��I��Im�B�N���}�*L	�MI3��k����� XG����o1D�]�5'���7���$@���08*@�v�q�m����~P
�����������0)@�6��\�
��m-C %�uJL����k����� XG���h#�@�g����em�&@�N����U�`�kgY�Q��Qn&C�:��u-� ����3!V	��j��*@�v�s�����GFA�e�����v� Xgo�����d���V�� Xs �l�u����5	�5A2�
�me#�Q�`���pP�`�`�(�>��}=�"L
�Mj3v
���U!`J�`mJ�y� X{�^�@��:���^�`�}�Y �
�9A� @����8,@�v�y���&��&H�A�Q�����l��v��j0-@�6-�|�'@���'T��I��Im��V�`�mkY)	�Sbb'� X{�^�@��:��� XG�>�}�.kC 5�ujN����k_;���
��r3�	��k	!`\�`m��	�J�`mU;(�U�����n���82
.�]��#���:{CF@@��$[�`����z�����d���V�I�`�	�apT�`�h�(�k�����k�F��	���	!`R�`mR���S�`mg_�
SkS���������8"��D����k�[�hW�`�	����D�@�a�����t4	�5A2�
�me�%@���T��i��iq�C�>��}=�"L
�Mj3��ko[��HI�`�;!�������8"��D��@��:��=�Y�`�swY�	�Ssb/| X��Y�eT�`m����N�`m]K(�k��L��Uk��A1�
�]�u#�G�`���QpY�`�r������2B��$@ ��d���#���$[�`����zMkM����kGG�h Xk�d( X;�4J�O�`m_O��k������k;�BU� X��f��^���!)@��$b� X{�b�@�kN4�5 2�n�#�I�`�	�apT�`�h�(�.��]��L�M�3�	���	!`R�`mR��� X{�Z�@J����	��^���!)@��$b���F����k����HM�`��{!�������.�k��L��uk�ZBA X'gB� X[��qU�`�j��=k=�����k��G�d/@�����5'� X'���%@��<@ ��d���k Xk�d X;�8�F@��Z#&C!������Q�}k�zBE� X��f.� X���B�����4�x-@����,�H�u$; ������@� Xs� �A�`��!pX�`�p�(MkM����kGG�v	���� `Z�`mZ���O�`m_O��k����������0R X���Nx-@����,�H�u$; -@��6b| X��]��@j����_��v�u X�f2� X[�
B����89"`����vP��kW;G�� X�qd\ X��=jG {�u������9	H��:��g�(�5�� X'���^��Z$� ������Q6�1
�6��� X��*B�����6s!`�����P������k����eqD
�#�������"����
k
����k��G�h Xk�d��������(���9��2d����9+F�������&�������6�����)�)g�M6��\������?�d%d"@��D�c�K�`�W?m_�E��7���ZU��q>�����:.y��J�`�U;Yi��&�� X{�Rk���j�����7���+��jS��1�3�_k���jHW�`���#��������������H��y���u]k����L	�MI3v
���U!`R�`mR��FL/���������v'&�uL�L�����~�� X�+���'@����6�H]��an��p]+��.y2���2zHG�K��6����ea&�&��������0-@�6-�|�[E�?��|R��F�
�c�t����08��)@�����
�T��J��
�����+[TR~r���+x����Yk6�k����������,R X��nx,@������|u����J���1���m�>oE���tG�?��b�U3� Xs �A�`��!pX�`�p�(MkM�	f������&W�^(��uhUeMi�\|���v��r�(�gm�T"X�g>/�^��E!���:e*vD�[����������^��j������..Y0������x�ny2�����V���r�u�L�������"� X�����)@�����\�
�S��K���jS� k����+jqK�:v��JQo�=x�>��K�����A�r�:�mksl�u,�L�������� X�����(@�����]���U�����LR[[+yy�_���5^Z��sg6�����=kl�T��e��N����� X��KV�@&�L�8��~���jN����i�u��Oh�������V��rh�4<H�l��cagR���u�� ���:=/�F�G���]���������o����	�o��
5-���'_�:�sn�f�6��h Xk@d X;�<JG@��Zd��i�V��+�u����l������'	����P�ck�F�h Xke8 X;���KV�J_?������Z���m���y�:���1=����P�ck�F�h Xke8 X;�4KJ��}���-�����V����)�z�K��2���&��p��\�)��)��;�����I���L�����>�
2 Xg*�q�#@�����W2�����YM����pU��'w
�3��k{{Ce	�j�"��uP���5��r�^b�'u��
"u+��R�>{E1����o�K!X[�JsG�`�N���\�s����%@�v�_:�}s}��_Y>��n�=�SZ����7������\ce.@����#h Xs2 �l�u����P�d��WW��s�D�h�?��.L��WM���9���>1��Q[|��-n��#@�v�WT�@.��PeL� X��/]�^4{��-m�M��No������t��\���nu���{�����a;��2ix���'��2d����9+F�������<�����Oe���qkmp;ymx;����|u��o�^�f�����P�#kGE��H�`�#X�E�!��C��X����z��7�]��Y�e(�6��� X��3*F@��Z�&c!������e[���6�+�p]V�s�~}����S�:�8���}�
���7���R�`�% �#�����&f�u���JY��&�m��Mg��ak�H�v���U ��:.y�E���=��� X�����	��k)B -�uZ\����k/���HY�`�2;"������d���V�� Xs �l�u����5	�5A2�
�me#�Q�`����[���X}
dt�i��E�-�r� XgM���9H��:��g�p�:����e;D��[� \�8�d����`�������s���8#@�v�U�@��b�3Z�o+ykC�l+�����{w�kw��n/k����+
����urz�Js(@��!.C#�����&Q"9 X������I]\(r��"|P�Y}f�����
���)�.t�� X[�"
D ����28N��hS�E���� ,7�T�^0����FL/����?~b|�6�v�@���*<�WpE|X����!Xs �A�`��!pX�`�p�(MkM�1
��V_<{{���w[����r�����F��'w��;�:V���j'��:=H�lN��n��"@�����@<�x����6u#�Z���g�h�y�.�,��osPuzQI������{������g��oQs��"�0-@�6-�|^
��l+�B e�u�T����k�[{�3����MCo�>�r����-������Q���bsW�`�n���"��E��b X����X&@���!���Z�\R!���{�Y��[�������{\� IDAT�o���M��Vs�|v�/I�`)��:t��O�`�_OY����b_� X��W�����R�[�����������*��f�KM�`��{!�����d���V�� Xs�*�^x6o�)�R����C�^O���+@����h	 X'��,�/��
 @��@ ��d���k Xk�d X;�8�F@��Z#&C!������Q�}k�zBE� X��f.� X���B�����4�x-@����,�H�u$; ������@� Xs� �A�`��!pX�`�p�(MkM����kGG�v	���� `Z�`mZ���O�`m_O��k����������0R X���Nx-@����,�H�u$; -@��6b| X��]��@j����_��v�u X�f2� X[�
B����89"`����vP��kW;G�� X�qd\ X��=jG {�u������9	H��:��g�(�5�� X'���^��Z$� ������Q6�1
�6��� X��*B�����6s!`�����P������k����eqD
�#�������"����
k
����k��G�h Xk�d X;�8��K�`mW?��k�����}k�zBE� X��f.o�����!���:%&vB�k����eqD
�#���h�u�{ �������6R X���^�*@���������(7�!`�����P�������V��b\ X��9�F@��Z�#� ������Q;���7d�`�I�@����?�G@	�9H��:��g���� G��6���(@����P8(@�v�i�l�����P&�&��;�v���0%@�6%�<^��n/�C R�`I�x/@����,�v�� h Xk@d X;�<JG@��Z$� ������Q�]k��A5� X�g>� X��*B�����6sy+@����,���)1�^��n/�C R�`I�D������>w��!���:5'�B�W����e]F�F��������0.@�6N��X%@���������Q7z�z��.w���^�`��!#  kN�-@�Nv�Y=J�`�y�@����?��$@���08*@�v�q���F��FL�B�A���M�d������0)@�6��\�)@���/T��)��)i��Z�`�u{Y��H"v@�{���-f��+@��A@��Z"C ������Q:��� G��6��� X���A�����8�!`�����P&�&���[����ea�$@�N����Z�`�u{Y��H"v@ Z�`m��,@�����
����9��
�}�,�2*@�6��dX'@���%��q��qr&D�*��U��W��v���#@����(�,@�v�{��@���
!Xs �l�u����Pk��-@�Nv�Y�&��&H�A�Q�����l4
�5b2
�l%�'@���'T��I��Im�B�N���}�*L	�MI3��k����� XG����o1D�]�5'���7���$@���08*@�v�q�m����~P
�����������0)@�6��\�
��m-C %�uJL����k����� XG���h#�@�g����em�&@�N����U�`�kgY�Q��Qn&C�:��u-� ����3!V	��j��*@�v�s�����GFA�e�����v� Xgo�����d���V�� Xs �l�u����5	�5A2�
�me#�Q�`���pP�`�`�(�>��}=�"L
�Mj3v
���U!`J�`mJ�y� X{�^�@��:���^�`�}�Y �
�9A� @����8,@�v�y���&��&H�A�Q�����l��v��j0-@�6-�|�'@���'T��I��Im��V�`�mkY)	�Sbb'� X{�^�@��:��� XG�>�}�.kC 5�ujN����k_;���
��r3�	��k	!`\�`m��	�J�`mU;(�U�����n���82
.�����<�l��[Y2��S ��$��w����F�`mM+(�e�����v� Xgo��.`{���d���"T�Y�I�"���u��� ���im�[jd[y��w�ck-���$@���0� X'����5�����N�)�	��YGu��O��6�k�4����d�AY7r��Z�an��
����:�P���������k��Cm���i�"��uNX�l	�*T_4�s)
n�[����H^^�+���"&gm~�3�����-�yb|�\g��6�m��9#@�v�U�@N�9aeP��%X/*���+Z���\����������~�����Z���'w��;:�S�E �u:Z��@kN
�-@�Nv�Y=J��`='xA�c��^P�|��-OJ?m�J���W���g���^�j��v�lT9���]�F��������:��������Xs`�L^$on��_��B�lj��s�����g��|I���Z����C{��q<� X�R��#@�NL�Y(�
�91@��`�:1�������/S�v��;o�V�a�+�/�S6nX�2fH�P�^|��{~�W������J>eTQ���s�!`����Q�k'�D��L�`�3ZF����B���R�\_-�����1���@���]���c�7�_uzQ�[��Bv���;sPh���?�!@�����+@�v�wT��.��u&�RA���-��>���m��eo6hS�`������D�@�a�����t4	���z>[�pm����D�0X)@���-������Q/z�z=
�.v���'@��g�H	 X'��,�@�`�i��k����^u�>�i7e��Z����[|.�[�����
��t��_�`���pI�`�R������U(V/[k�����������n����!\��-gw�%d�9m�#��G�d)�	���gfl X��j@ ^����E��7��z	�g]�%�P�^b���:8.��d�{Z1�Ck��E��
���
�!`B�`mB�9�[ �`���3�Z�~^��[`7�!�����&�������
�S�`�>s#`����>Pq	���g^��^��� ���:m2@�;�8������v)�P�|u���[�<yY��Y6
�m�
59'@�v�e��V��VNC�I�����\���6}��� TO�������h, X[�Jp_�`�~Y�����X��;X�+���o+���c~�V��!��C��T{�����0!@�6���-`K��[���W�`�ooY�A��Al�B�B���M�$�
�3�	�-k��)@�v�oT��.��.I�A�]�����rt�u(2F���?H��:�'�G  Xs �l�u����5	�5A2�
�me#�Q�`���pP�`�`�(�>��}=�"L
�Mj3v
���U!`J�`mJ�y� X{�^�@��:���^�`�}�Y �
�9A� @����8,@�v�y���&��&H�A�Q�����l��v��j0-@�6-�|�'@���'T��I��Im��V�`�mkY)	�Sbb'� X{�^�@��:��� XG�>�}�.kC 5�ujN����k_;���
��r3�	��k	!`\�`m��	�J�`mU;(�U�����n���82
.�]��#���:{CF@@��$[�`����z�����d���V�I�`�	�apT�`�h�(�k�����k�F��	���	!`R�`mR���S�o�?����Y����v�nvIU �3�u�h8I�$u��"�R�`�Y�@��.��E%U
�����u��E�va�$I�`��nk^�K/�$��z����+�}�v�����.��'JAAA��>��C���ke��%�u�V9��#d��)r�����*�}W�\�����K^^�:T�M�&}��i1n:��KE�NW���K�`�W?Y
�,_]-7�-oq�)�v�I���}@�a������t�U(.,,�3�<Sv�uWY�x��^�ZF�%O?�tCy��4H��_/���wd�]v���zJ>�����O<1�}W�X�������-[�l	��}����������a�t����`��� �����^����l�<����a�������4��[j���t�gpD�`�H�l+�?��?��>u�k_�ZX^EE�|����^xA~�����������=c��7o��u�Y������Z����j�*�����&�}�<��0�����>���p�B>|��7Nf��������X�3Q�� X��KV�@�m�~A������-�3�THYE��c�t��C:�;
�#���k�dcyk���8@.��By������t���v�	&�a���*�����{��o��d����>��|��e2x����U�~���r�e������d�!C��o�!�7o����0���o���L�8?�~��U ������r�C�7g5Fm��}w��=������[{���2�_�L���T�`micl.���>����K����@�x[�|��`{�%��}��'��_D]-n-��p��������>}�\y��2w�\9rd�&O�,��v��Z�=�XIg�L�	���q~���#�@ S�5�5r������I��&����G�����|��	�����]}��r��w��>(c��
��V�?�u�]r���7Y[�����G��9s����K/��������4w�����?��|�{��t���`���!�����>�
�P��~�O�O{�?Z��`�5�U�u6����k;��dU����~��R\\,����t��U�������#�<�1���n�V�X�q�����&�}�9���Ee���kx��~lu[�@�>���o���L�8?�~��U ���
�?{n�,]�G�0�k��5�#@������D��nWAW��#F���s�=�B��O>����N������a�����Ok_��_����>����{6w��aX��O~"�
z:�f�H��T���C�`�GY��{�:�d�>���>���2~(�:k�E�F���]q�&��o���w�}W����0H�o����.�(��[���x��b���zcx:��w�yaXWs7�fu�k���J:��C_^^���
@��^Y m+
���em.��+��u�7�y����XF|e��`���
������������&�H��o�Y-u�ZY����[����g��X�����������9sf���C=�����X���t�M�e;v����?<d��5RVV���
�'��T�����0l ��������7�������~�K���c>�]�[]]-������|�n��?���@��������E����p�� +B��5$u��o��k���w�+V�C�
��>�h�[��l*���Y������]�|��r�w��I������g�}�������?�������A�n1Oe�L��<S9��Y`[��K���4���z����6�km�
+?�#�S��>��&���@f�_w[m*T���?1��g���&<�]J6�|E�1�-�v��08�Vp#��M�^Tv�1���UF=S�nomS��F���������n���?��Or�q����Nu���x�OnM�6����s_����l��%������i����q���_$���P���M}sU}{�������T����.��kw���Z����ry�����>��2i8�<���aeI X'��Y�Y����M��[o�s�='���7�Q�\�\}���3������7������{���oOu��~���-�*8���~���������N�q����Y��Jg�Lx���q��m�������r�J��6����@v�WW��s�[xZ���u[�����z���(@���+��T�mj�,�
��m�
�u�]����4��6m
oWaZ�x���?�E���'��0D:����(��,�^P��g��O<~�K]o���t����`����,0bz���r��O���5���g3�!���z,���-�����skW����VT��e;����-u�%@����FVS�2��&SA���o�E��K=G�x�b������)S����o1L:�����-�����n�7����3[���o�q��7]H�u�b�o������{�Z>x���d���/��}=���`�ka�G ^�5�5rCp[w��u���g�'
/����n+X�W������=6�O�`�_OYQ���2�������<9����H���'X;�,JE�uUzm������?�T8�Z���>Q�x�[�`�wY�!��!h�1*�^�37��Q]�VWg��R���6:@�6zj2Z�[�C���ls��N�{Iw#X�+���%@�����&&�uL�L��%kKA�)���o>�H��'	�i��;�	�=k(��G�`�;�"`����NP�	����L>�E�N����M�`�[GYO,�X��k����BHK�`�;#�@;kN4�5 2�n�'Z�[��~��V��VNK��:��g��	�9pW@}c��e;_^�^\�^`��������?~	���'��I�`<�"`����FP
��m�)��}�{aY����s��=i$��W�`�?�#��:�0?���� ��:N}��F�`�M+Y	�3b� � X{�N�@����8��k�
�-@�Nv�Y=J�`�y�@����?��$@���08*@�v�q���F��FL�B�A���M�d������0)@�6��\�)@���/T��)��)i��Z�`�u{Y��H"v@�{���-f��+@��A@��Z"C ������Q:��� G��6��� X���A�����8�!`�����P&�&���[����ea�$@�N����Z�`�u{Y��H"v@ Z�`m��,@�����
����9��
�}�,�2*@�6��dX'@���%��q��qr&D�*��U��W��v���#@����(�,@�v�{��@���
!Xs �l�u����Pk��-@�Nv�Y�&��&H�A�Q�����l4
�5b2
�l%�'@���'T��I��Im�B�N���}�*L	�MI3��k����� XG����o1D�]�5'���7���$@���08*@�v�q�m����~P
�����������0)@�6��\�
��m-C %�uJL����k����� XG���h#�@�g����em�&@�N����U�`�kgY�Q��Qn&C�:��u-� ����3!V	��j��*@�v�s�����GFA�e�����v� Xgo�����d���V�� Xs �l�u����5	�5A2�
�me#�Q�`���pP�`�`�(�>��}=�"L
�Mj3v
���U!`J�`mJ�y� X{�^�@��:���^�`�}�Y �
�9A� @����8,@�v�y���&��&H�A�Q�����l��v��j0-@�6-�|�'@���'T��I��Im��V�`�mkY)	�Sbb'� X{�^�@��:��� XG�>�}�.kC 5�ujN����k_;���
��r3�	��k	!`\�`m��	�J�`mU;(�U�����n���82
.�]��#���:{CF@@��$[�`����z�����d���V�I�`�	�apT�`�h�(�k�����k�F�Rr� IDAT�	���	!`R�`mR���S�`mg_�
SkS���������8"��D����k�[�hW�`�	����D�@�a�����t4	�5A2�
�me�%@���T��i��iq�C�>��}=�"L
�Mj3��ko[��HI�`�;Y(���F��oae��D�v�gT��N��NM�J��:��g��kN��T��%RVQW��!�d����-��z	�V��b0.@�6N��>
�}�*kB u�u�V������e��-
���B��C�:Z����Q6��� &��d���#@��pI`��2ee�����������R���`mU;(�k��L�������&R X�n�����\�,~��Y!y��O�:������P< X{�D���:�Pq
���g�t�������|�y���]���� Xs* �l�u����5	�5A2�
�m\���an�����Uk�KO�$#��LN
�u&j��?kz�Jb X����X @���	����������V�8����bl�3�:s;�D���]d
��co ��:V~&�@����E�9�@nU���B��@ ��d���k Xk�d X;�����'�n>�HT�Df����������c���+?�rm/�`�i�@����?��$@���08*@�v�q	/[��l�s�RV!R\(2fH����S����[?q�	���'^�`��Sk�����kw{G����^�����H��y�5 Xs: �l�u����5	�5A2�
�me�+���F.����}��W$���2��j����$�*N��o(�-@�Nv�Y�&��&H�A�Q������H��n/ku�.�>k=oE���tG�}Z{N;r"v X{�D��@�,�ryhEE�<�9!@�v�M�@��9�e��f.�!�WV6����\��f����E��y��c����k�����M����j�*y���e���RPP �����s�9�r�J����L�2E.�����d�(�u�?G�o����M���,�!���
����K��_�j���j�$>�M�N��)�?�����^{M�?�xQW�U��w�}�����e���!�"�7o��7������3���R�� XG	�s� X��_V��@{���k�b�y�� X���������y������N�����_|Q>��3����������?�9�J�:J�`%���[�`�wY]��.%�^\V���1�����+�I�8�E���:�3�G���o}Kf��Vq��w��	��h��[�GyDT��� X��*C�����2s�(��\D�*��^����AF�hc�9��`�sb&@�j�u�������@v�w�U6L/^,����}��'�5��3�[�n��R�� XG	�s� X��_V�@*�T���1��+_�����G-Z$�����o_�o�����{XUUU�z������|��+e�(�u�?G�o����eu�"@�NE�}�W�`co'O�,��v��1B��]+�
���M�+��R�.]*7�x���������L~���X)SG	����9~���/�C �u*J�����{[YY�|Pjk�oA�w^��u�������������� ����� X��*C�����2s `�����P� X�Z8���m����k�����Y#EEE��/9��%n�u�`~� X����uo}�v��}���,_]-�-�������|���N2�o���}�`�cWY��S����[o�~N����>��������F���O�`����pQ�`�b���yMi��0�<�j��=O��]$a8���oT?pa������#X��%jD w���F���n����?/l�ouuux�
7� eee���l�
���
�!`B�`mB�9�8w��
��~���%c���)����nq�YGu��C����T 	��(��
�c��
����.���;����^{-|�Z�	�[�nr�M7���b�W�`moo�k������Z}�����dsuy������[�~��r�����l-��$[�`c��[����?��c���-_�����k�����_jjj�����L�:Uz��c�L���:%�A�_�����}e�
�s�����U�X�z�z�@^���yA�����C ����F��a�9��Sd��u�������V�]�����<8�xv�C�`mG����q�3���vyoSM��z���c;g��\���M�Z�^�v�����q1�H�v�Q��@��9�Mg���7�7��MY�b��~�����

x�f:�q�K�����@��x��>�kk���v���u�Z��I���dL�|mi���S��#N4�u��Nd�I X<������'��7�7n�(��z�~��Mv=��S
V�T�
��c� X��OWV��*�������%c���I^����Z9���th��^b�fF�`m��Y�U�`m�3y�w�7�
�!�������K��6����x|g��_���H��m�7�����t�]cF���f&A�Z�������?�x�+��2�c90���36�m�������j���Zx�_uz����O�VE���!���a��ap��S�`�g_Y�
�S�b�t6n���VWImm^x{��]%�������"�u�<��>��6zHG3��NG9��9�Z�"c ���:���g�y���W�"'�|rC5��_�%C���.�L:u�7���9=�:���Z�`�u{cY���*����a��[���cA�T�=R����?e��^�`�l�e����`�p�(
k
���i�&9����o��L�4I����p�������*t8P/^,��w�t�3 @�6��X,@���9�������V��Z�d�FQ���F��Zm��k�����m�;r�%��< ��M��]�ti����R���>����e����w��� X��*C�����rr���"�w��;"�\����.�p����e�y����U�qkMx����}��	��Q3V
�clK��}������s��Y�g�!+W��?�0�J�:J�`%���[�`�wM���m�;�o|���=��N�[�3�����U?�:.y�E��u�}���sx�z��mV1q���juE����b,��� Xsj �l�u����������������V�Z)n�~�/�R��F���#t�0�zaY���@�������&���l�������8�1v�k_��t��Q����HAAA�Jjjjd��A����;��X)SG	����9~���o.W�B�Ol���*@�P���������*\w+��3�*o��xv����~^�����)r��� Xs& �l�u�����;�������G��Y��������7���^+>���r�-2y��+e�(�u�?G�o��������|�B�]�l��x�3h��q��FL/��f7��<9�X�r7x.[����X��k�1�B�����O�����/����t��-�B������b}�)�����0����Z�����0���0{9I}@�y��.P������o*</�X,�WW��������N/�a�:x�����.t����:w�)����c�=&�������D>������r�!r��������VoOipv2&@�6F�DX)@���-N5���������_|J��hu��e��_����qk���N�l��
uG����G�� ��H��7�d!d$@�����h*@���@ ��d�?����i��Zu�[���O��u~�l���	�s��8"@���Q}�Q����2�������u�Y��^{YP!%D	����9~���o�W���������D:t���^^\�n��{�����}�\7$��	��q��cn�������.�������6�9.��-u;8��k��Cu�Z�`�k�d��3�����?�U�����:����)Y��`�P�(��s����K�.
_N��~�5������+�[�l�e������*~������!C��:,�� @���)�H�`mQ3<(e����d��fu�����Q�����m�u!`F�`m���YN:����������}��['Gq�}������6�J�:J�`%���[�`�wM�n���������o��Ho>�uz^���o�;��.�����-��/~�f\p�,\�P�w��� X��*C�����rr��<v���W�O9��L��7m>�6w�����:��m������w�+�f�js�K.�D���#��l�
���
�!`B�`mB9ys���Z��P-����9�~��M�Dr(@��!n���������o�n���bw�M�~����{�)+V�����(@�����@�`mA(���17���Y�`c�-��G���;L���9��c���X�'�^z�%������7��X���� X��*C�����2s `�����P� X�Z8b�+��B�������v�*��mk�k������\%�G	����9~���/�C �u*J����kz���/�/0+))��R������_s�1TH	Q�(!~���k����HE�`��� �������2�k��L���k�BI Xg:, X[��qS�`�f��]k]�����kw{G�� X�PLq�:��g�����2>�s/@���13 `�����Pf�f��[�;s�	'd<��/�����{�u�����6w��0#@�6��,�*@���3������vQ,���I�������*@�����`���/�����\v�e�������+�V���0*@�6��dX'@���%�r��Z�Jjkk-��r� Xs~ �l�u����Pk��-@����k��b9���
O��4v[��K���tk����'��e��P{VE%.�]�5"�;�u�l3�`�[��co ���z��j)Y_-]�����
��^���f2�
���<��[�>2���L��� X����x'@����k��b9���
O\�3����++�t����dp�]��|�B��������IF���R��A���M�d4
�5b�j��a��;������c8�0$@�6�4X*�r�^SZ#���B��Pd��bK�[/k����dCM��rh�4<X9 X���p@�`�@�(�~���=�Br)�r�V���87������+��[�s)�w�����!e��Nz'c4�	�9%H��:��g���� G\�o�UO|�e�v��ukkQ��5���^d��@.���el� X�Q^^�����-���`*�uh��G.k�������\�
�s�����-���ec������<��#1K!X'��,�V�O�SO=��lo���l��I��g9����G��m�6Y�re�=����O�*����J�*]�u�b���_�k�6mFU(U�~>�/���e5�����16g��r��g�O~����,��h��=[��'�>���=:�J�:J�`%���[��`�ww2[���
�*j��<3�DE�Nd�Y4
�O�~��I��=e���mV1b�Y�z��ic�W�`moo�k�f�xaU�<�|�l�w���{�fO	>=������K/s3#�,�k��-@����EEE��{����*~���C=$��l�
���
�!`B�`mB9�s\�x�����a�����$_:��H�_��?�W�^�s��o�s3��k#�U�`��3��>�`���������Bv�M5����]v�E�|���go�k��L��uk�Z�vA�VT�}Kw�r\]�n�����.�������>�`�wYQ�(��|��2q�D9���e��)r�GH�N����B^y����k��W_�9s���u��ch��E�@�]��������j�
������0�������������pV�M�`����pR�`c�jjj���/o�V�zyYaaa����


������o�9�*�:�u*J����kw{�&�,�
s��t�
�jS�~�	_~;�����?��K�>�_wN����I���K]�~������D�l�"���kx�Z�	��C��BJ� XG	�s� X��_�2�sg�IYE����t]�n�	<�������"��v���n�=gU�sF��8!@�v�Mi����Q� X��7��Up~,�>���U���y���Guln��j�1�Z��V����z+���\���'>G�����
�h�u�Q��X�|����_P�u����Z�����>�H����f�����P� X�Z8�����[�2zHG3�S8���*������v���%O��^g�Tg���"X{�b�@���O�����&U���'L� w�}�������V���c���� Xs~ �l��}�s}�L|����/\[�{�����������
//k���z���c;��X*�B�`mE(������<���r�E��g�����g��[n�%|q����/������G
m���1V��Q�(!~���k������.TW��������S�+o��y��k����Z*��~f���;���;o%�o�T��:N}�F ~�u�=0`@8�������M7�l���A��g�}&���c�����QB�����W��������>��/5��h�|.����tlkJ����������=��
)����������Z*�A�`mC������KQQ��@v��w�U�������3E����^�����2L�M(�=�
��WV��-�a0<C��F�\�#���M}:��Z�������Z��5�����X� X����v�MN;�4y������F��_|1�5��^�����2L�M(�>G�+�ya��eT���;?��|��
Y[��;����Og-��{L���?3���%+A �u&j��9����w�������r�����b��K/�	'� #F��y��i��ar!@���*c"���:�^]�L���nuP�������Z��������7��`_�|��`�[GY�	�����wII�}��RSS#����e��
�p�B��/)������
��~��W����:7�� X��d4\ X���qm��6��+�u�G��j���;��^�Q���u�=N9��L�g-���?3���%+A �u&j�Y�l�\p���{���?��?��G��C�j���r!@���*c"���:�^�_��U�Y]���j�U�����uE[m�WT���}�^�r�9��[���V�`�� �#������UWW�W�����l�"]�v�~���I'�$�:�BZY�:���Z�`_{�3����v�^���]��Bu����#�[���])���)�/��n����;���83�����&R X�n���)@���@ ������\d�������t})_\��2�����n���m*�;�����k�w3��k)B -�uZ\��y��U�n�:)++k�
����s�9���Q���02�
��k�z���'�t���'g
� �W�rk�N�j�� t���!�C�`�C�1pW�`c�6o�~nk����U������ X[�
C���Z?�K���Od�H�]���5U��L7�Fu����.����A��e-�ua��w�������H�Nn�Y9J�`�y0f�y�����#����=����j��c�L%@�����-@���_��xb{�[�zu����P(�?���{��d��������yy�2��bywc�L]������X~��
]k]�����������K��=������;�X	Sg+@��V��p[�`��3����+[^an�sYj�K����vH��uww��=����;���v~����^���w���U�HI X'����X�zt��E��������c���� Xgo��,@����	�o��
-�V�o�?�������3�&�zC���-���E%U�qk�t-^Z��#����2F�B�`���@��bc�O8����e�<cc�L���:$vA�c�������}��� IDAT?���L\���@��2FB�}�5g� X���W_}UT�����e�����o&��YMM�����p^�`��������8��[���vV;��p-/"��F�D�`��� ����`/�b���W����/����p���s�V+Z�|��J�*]�u�b���_k��T�����3�{�����G�l�^+��z���6�h��!e��Nz�`4� X�	��x&@�6���]�f<��m�2>�s/@���13 `���lw�,�l�
>����@�v��Z Xs^ �l�u����5	�5A2�
�me#�Q�`���pP�`mA��~���s[|pC5w�q�:T�8�*��(�u�?G�o����eu�"@�NE�}�W�`cow��!_|�<���r�M7��7�V�}�v)..����"�_~�L�>]��[~:$�������S�d����>�UV!����O]�<c�6����Y�T=8{ `����&P1
�c��:u�L�4I�.��r����?����F^{�5��O*����3f��	b�����QB���m�w[�����|�����h����C�oI��%�+����_���u��~�a����]�Fr'@���m��_��W�{����+�����b=p�@QMz��w"�c�����336������U����Z�0��"��W��F���/W�?�w����*���k��x��
g95D	����9~�c�o�.]d���2m��6����+��{�u�8��k{{Ce� X��<bzYxxk[Q���^�
d�����R�Q9//�������]���9J�eR X���>�+@����}��u�����o��#F����.~�a��2u��:J��#�����������j�?����`-�t�������P����;�c,�[F�}�:����� ���:+������d���2k�,7n\��~��_��1cd����>l�
���
�!`B�`]w;�z��tk]P��=O��]$�~�J�K�
���n���/�TA|g���b�~�s��������������3��H| X�����R9�����>��}�k2h� ���[�L��J]RR"_���e�����{�X)SG	����9~�E���yC���v�v���/�V�Y���'5AdVT������H����o?�SC�����A`gC�F���]�&�	��Y�:�G}$�\sM����>��a���B9rd���^{�s�L%@�����-��`��V_<{{�&�9�E��R]5�>\7=?���L,n����U��eu��z���g��Y�`msw�
���so������n�:���O�k��r��J�N�[]�� X;�&�D g����-�]������o�n�o���-�~cp�y����sv:3p���8O�16���/���>[�f�[�+W��g�y&�J�:J�`%���[ ��Zuw�C���/^\�^�{v��o�$��_�|�q����F*�������g���ww�5�~�S� ������D�`mI#(���1��i��D���^Q/1kmS��y������M**��VI��3�N�5g�Hz���U�2xj�&|�����?���0]w+xmm�_�����/�n��^_��1Cv>S�����v)�P�����:����z���]�&�	��Y�<��m��U�K�v�m�V�P�Q/6;��������J�*]�u�b���_I�-o���u��n��W�K����P�M������[Q)�-�{���vs������p��Nr{5k��G�d+@��V0���?p�;�8��qcx�?��O����$��;_�R?��/�;v�
~��w��G��L�jZ�`mZ���K ����[�������d��\u��g��|�B������}�:�c��p6l X��
jA�����y��Q���XS�)@�N���L�`����`]�=��OdE��L�y|[����_���[�����r��t�u ���:37-G����wx���m�����z�Hr�^TR%S�|��U �|���b��g�[�V��~pl�l����*@������]�`{�
(//������.uozQT������-�-j�g����2��?H�@���j��%;d�������Vm��\_\e���{����Keu�s��W��o{��w�} �K'�o#��O�v��,���Y�ew�z��5�\#?��l������wv3rt����e\�Hz�V]�|jzMi���@�����n/k�W�^(��up��T�@kN
�-@�����'O��n�M��c9��#���s���}��W�}�]Y�~}�����[�=��+e�(�u�?G�o�utU���]��;�Z>o�����@��d�!������Q9:�:3�����>�,���z������m�������g��!'N���~ZF���,fB�`mB�9�W��`�>�5��r)�V��s\'��;�M�q�������[� O/����1��}�A�`mC������KQQ��=Zf��Vq�����WM����/�'�tR����/�c�L%@�����-�s�V�HO|"���lK�;���G]������_��`���!�X�:}f��%@����P����~ ��O�����{x+�2�����9(�	t/�5�@q�_
R���L���	tF��>�%/Y��L,Q3hLp2��f
�-A�W(�hT*�������}������y�~o�5C�^��|��f�������2c���� �����n�;��C�|�MGJ�� ���=�M �b�{����L���O/r��@��������f����z���7$�C��gf	������>�1�c�=���Z^x�9�����?���q��g�����n����	_|8�H	��d��4R�,�W=�%O��Ou5B�t]���.�=\��/2R��j�2��b�(2TO����
��o|�r�W���E���kd����1c���{�-<��u���SN��#G�����
��b];��� �X��z�Ts�zRe��5��r���>=".�i,�A<qg��$�X�>@ �k��wW�s������w�+^x��y������r����9����H����!��@�	�Y�5r����{OL�yf�������4��@q�5o�M��A����[��c���Fs�����w�----r�Yg����`����W�&Pk��U��;2��l��{�>��������~�+o�M3z���46$��A$n�����d�����z%�}f��z����+!G�Q�NmaU=������p���b���0�@@�.�	�R��/���[�g������j������[T��%se:�T�l������\��^�e�1!�<��1
�x�I�\�h00�����B�&��`��Q��Z��9��;w�>��#�&M�����)�'�X�?F��$P+��������S�d����g_��B�}���V��*K�-A�6KW�OYT8Q��sH�V��?ai�K$��#�XW�������d���V�2-*�z��[o�%����~��,X�@n��W����@�k���!�k73r��Q�=��/�Z�HX��(���O>[�|�����.v��}��V�����N�� k^D�b�a����z����f]�5o�<y���g�f``@�}�Y��������{����{�����K@�K�{��@��z��#�������!]��z��������;f�J'd �8m�s�<��Z��R�d��3&+.�@��������^	�b^{M���O@�y m�����de�b��]������u���$�=���#��R�R���&P+��f�]p��<�sc5{�w���
�u���b�T>�;-����hH������%���������!#�X{�~h��_���r�G��Z�~����eM�/����ad��Z���]�(/�e�<�R����V��-9�
-;�w~l����_���=��
��[��O��N��y���A��@���0��@�=|>���E]$_|q�QL�>]�x�
y��=)]�"�X�"��7�Z�u��]��S6m��/f���i���b��;
~����zVm���j���Z@�kA�6!�������/�����;�����Q���M7�$W]u�<������|����u)�u)B|�p�Xgg�7�a&���Q����>y������Fs�8&�v���8����J3�* �U@���b�a0�9�Y�z���o����O>�����Q�D���_�Z�|�M1b�z��y�\�~��#��\�5��M �b��oV�7:��!T����V9�2aG��f��@�+�E]��b�aL�^u��v���Yt�b�>SZ���	��g]��j�2(b�������[������cV�������qV�2jDL��F&l?����wk���A��������@��Y��l�Y���o��S[��W/}}}w���&��ze�l��o�tf)v�������L�o
 P��,LT�@h	 ��
-�'������(v����7�����k����.+�x�,��d59�]��y�^!@�u���!�"��E�4]�utc���C ;�Wz��m�����Z����������c�W{i�o
 P��<N��@X	 �a�,��+������X��G�[���w��-}�?��6C/z�V���F�2O^4:
,�:��c�p�b�
F�:�:�o���
>k����a+���=�����Y�J�Ib��J��=�"�|�1�d��K�]%�X���� 8�u�B���H��cT�'�fS�,^�-�v��]����j��L�~WWB���W=�]]"_�q�<�����%<�z��f�1���~xQ&�XG9��b]���K/� ���O ��L���)���/�`�=���Mv���������-�G3yo�������:�={(�}����u[�
Y�k���C�	 ���/��@)�u)B|�2 �e@�
BL�b}����������W�k��~��f+�v��[N�X�\���
�+���@��d����	 �>C�:8�b���Z�u:�w��2��b���)���Cp��&�=��hh�!�XG&�L	 ��p�b�D��@�	�B���q�9
���3b�Rub�b����&��Vs
 P=��zv<	�0@��E��9���0xJ�b=��d�d��.	Yn���#����/7����~�����l!�3��������N�Z-O_:
�:4�d"��b]6�@6��7�&��X�/Xn��(7��*G�0(������t��Y8�U&�o?�����hG��C�|�u���	�0@��U�Tw�u���!|E�m����~����b=f���{~����\���x�����S �	 ��3�E�b�h1V�@�}��pC�7n�m����������������m���e'�����E�v�]��K�5]�E��������.��!$�X�0�L	@�+�EU#�X�n@ ��"�z_������l�����&-K���_�0��bq��RY��l���W��R�E;��C#�X�OC ���G����b��00xF`(b�_����X�vD;=��S�e���A�����V_Z[�w`{��!�u@�0!P#�u���l� ���7��@.����jm�>���e�(]U.����C:��sH��A#�r�y�m��$fOl��	cRI��5!�J ����.�G�_L��k��%|@@�q_��K6nM�g�qx���������}�l7��j}<�R�'d�}e�=DN8�I>��8��&LE��b]���@���(�u���`!��b���=������������J��df������H�"x_:�Y�����\~�M�� ��k^D�b��3{� �.�������t����O5���*X�v�����Mb��
�n9���0#�?���3�{gnx	 ���-3�@9�r(Q% ��"�&�K�u�&sMVnJ��3w����<S��_-�����h�z���k�!A���:����@�����z�W�x�'���s�*Nb������o������W�Oy�S��b]	-�B |����y@��:]B�'2�H���\vR�g����^�o}���](�������;��{���k3ZX���{�0 �X�@ ��h����D�v	$�@ ����w���>�U�`��>�yu��[N�����}������e��Nl������!w ��p��b��1n_@�}��P�����C=�����L����K<��������?Y�^U�<�G�v�%-A �� F�1��b���0 ���P�:��v�U[:]��M��
I��n:�@A�5/�M��v���Kk�@�J`�b�~s�\��d.K����T���������iX������:;D���@�
�u�x�k�	D�@9b���������y�5�Ls�V����T;+�	5Bd��v9��������,�
"��-_���;�=��e���X�EF�(���(2{�b=4~<
��@��A����/��  ��Rb�I��l������\��Ym2�5=d�~�-����Qk�2���+��p�g[��z��1mX��b+rL
m����?aV�3�J�sp�b�>SZ�@� �A�c�-����a`�����9?mg��;�,���g����f5Y?��s�����=����gLfLj�y������S�k]�>eQG��s�.��D�b��3ed@�y ����4�L��z@W��2�������^����LI.��L��m�����eG���1t_@�}��@�k���@��B��#�L�oz�l��`Vo{;}�y��a�@���3>�jk�a1������m�J�qk����Z�y�n��n�y�B��R�n~��tb�O�.�5!F�u����N��;r:���4����(��k�����L�uk��efov9����$��4�����O��y^:&�1WW�{�0K��0[�W�3�N�De��,W���J��E�z������>;wj����TF����!6�u�"��|�/_.g�u�������^{����7��+��B��]+;w��O|�r�u����;��6l��}��g�U�i���-��"c���k����bD�+%F}���n���������J�|�J^v��nY�;;wv�����X��Z�)��s�"{���������Ar��r�?�p[��3��ZtU;7#��u=r����;�^{Z�}�I7N��&�X����%�:�a���6n�h	�
s!�~�����#���^{M�<�L�c�=������>���r�q��\I���~��W���� ������{��^��o~#�G�N�[I�j�!��P���@1��d���X���V��e'�6����Vp���������no��l�w���<��Z��-�.]����h������r���1
��b���0*��b]/�!�������b-��z���h�"Y�j��z��V=�l]��w�}��_�x���[I�O~���y�f��i�p����W���N:I�?�|Y�dI�z%u�	b]
5���?��������J�rJ)��6x�O��XW*a�}_��?��8��'�o�����.�;��j�
����3~����R�@���D-��b���x^���r�E����=k��}�{���u�X���Y����~����g������n�A��['G}�TRW�uO�4�������v�L�"���o�������J%u���XWK�� �=M.������+Y�-G�u�g��[�������u�9.-�8��s�������?gm����������Yj�h9+��d������� x����C�M���4#��o�a���3���o�K.�$��;�����>+�Z\H�{�1�L���W��U�������_���\��Cf���+��_���_�^&O�,���6��u��x��l����5M����V�����	���C�u����d��+yX�b����Z7������N|�Z���k���l��@�����lu�	���lg���6 IDAT+y�g�G�@��k���B���Z�
q������^�#�<���g�QP���Y��o��VK�3��-[d��qr��g���K���s����|�;����������{�����V��=�\��n�!C��%�s����g�59�Q7��c�����^�����k�%s������us���:��XgW+G������a�������y{���@�:�uu�x
a!�X�%����X����/}�Kr����9���5J���g�O9����,��u�����:_�4�����~zJ�+�[-F��Zr<������m���-�A��/�%��V�u�x�y�����K3���p��������;�4�h��YB���w������n��+VX�3��|#F������#�<"���$h��_�%z�����,?��O,Y��7�!_��W��i�����N����zD��?��;'�/~D��}~b���?�����9r��������[���{������;�F��+���J���W����X��M{��h�D��������Ty�}�	��c	S1�
��X�u�]r�X[�s��Y�V�������5k�%��]<��jg�ZE���/�J�V���.+�9��������e���^r����=��hF���f���W�\4H3K@�@p	 ����/F^L�s%7s��k=���+����/^l]�u�a�e1p�X;2_I�J`��TGG���&p�m��(��������������WB>�������l��U�������I��>������� P���V�?�����D����A@��h�g�:���,������	��K/����,z���S�����\~���$�[��6��C��'����s���~�+9��#R[���[- �XWK�� ,���y������n����k�~iV�W����l1Y��L>��d�n���?a�F��G��r3�������5��M�3����k�/&�zY��v����}����_��r�1�X����\��Wn�r�-Y��=��<�����;����������A��%�s�~�:[���$��������+ow�g��r��F�����l��z5�f�@�"�X�+���@�+%F�����V�����������������|������w��XL�UVV�#���������������~&���g�����%K���ZI�jB�XWC�g ,������,M�o����'.�� ��z��l9�k���k�D�b���6���z����Dk�l��2���4k��5k����K����?�������}S������/�������l����
b]
5��@�������*��=�IZ������3�&�9��u;��pX�\~���z-'�X��@ ��h����&������j��~��G�+i&N�(�]w�{��yc���n#�-��j=|�p���>e]��	�rK%u+�XWJ���BwP�,���&��E���(��k��X�����{��^e|������b�P2TE��
A �b����en��tY����NN�E�����d%/���F�����V�����;k����s��G��d��"3�@x	 ���-3�@9�r(Q% ��"���^��]��5��#�*�����q�����-�-\�z���G�e��	?&.����<:�3��:B�f�(@�����k �L��C=4��`���P �C���>�:�1d> �X� @�=�O��	��'�`��b�x�
�:\�d6�#����3�L?��_���d��d���wJ��j��Dj+�Pg�X� �C �����@`(����Y$	 ��
����e]��Huf)�y���=�j���{�I �wJ;����b]-9��@x ���%3�@5�j��r �����&[��,Y(�_����R��}�����2�tk�����m;�csM��r�w#�����!���_"�8 �
����2�u��tE@e���������2�5=���w�v�<���Y������+�K��j��:P���@M �5�J��:0�b�~&�X�9:�-�^�> ���3���6�������M}�L�5+�7=���g:��6���-����[���o#b����A�4��4#j@ ��0G����b]7�t���s�&�M'	��b�^L����~d�������b}��6�����t��b,}��X�bB�5��M��v���Kk�@��@���������T3h�����c���i��m�3&5�Ut��/e'@�'�=�U�>��BlxQ �XG!���	 ��p�b�D���	�&1K�Y��k[�?�����){z�9W�$'�-����'�(���Rrd�X�DD��b�3AJ����k ��H O�S[�M�9����
�uf%:��}��6���="^�l��<b=���8B@�A��@�<��C��]��?���d�~7���nm����m�+N)�]���r(Q�&�X�;��� ���=� �X��*�����U�������	��;���=�*>��f�7m��d��.�u n�u���� P�b]��C��u���:���n^m�r�m��k�nmW��]����s���f��u5�x�"�X�+���@�+%F} �X�Z@������<=&��u�\;���j���������R���'�X�?���@�y? ����4�!��S���t�������uE��!�X�j@ ��h����D�v	$�@�Jg��e;r���7��X�S����4�U���^�0X����!>�u�b�� P	��Z��@�5��%p���$e�d��Xf��)�v��9���?v@�,�EVpo#G��:<�d&��b]
5��@��W�8��]�3��q�<g�����r���z�=�o����4�8��[�k�H��K�n�9� �X�A�6"O���+�	�Y�)��5����\�������s[e��b�n�3p����� @��=���@����  �5/�%��K��;w�[*��[{��e�������.99��$"*@ �����	B`P�5/\ �X��&BA`�V{�x�Y!��*q!`��H�������bC�B��� ����.�I�g\��%�X�K�z�b��u�b|��.���?�b��f�1�i�h�{�_��l�{�9'=�;��<�
 ���J��:X�b�p�b�6Q��$�:�ag�nz�[}�/���s���$l��>�yuwV����"��7��?b��p0xB��;�B�7k�����b��1v7���C:���j��)M2{Js�]����-�=��t*���J��~h~{]�N�;p��\R��@x	 ���-3�@9�r(Q% ��"Q'0�����]�:�e;�������������;a���c����������!�n���b��1r�A�v�"mD�b�W ��������fqhoYr�����=�R�\��.���z��^k����|���M(<#�X{���!���/�� �N�z����7�r=j��\vRK���>}�.���kg��_����]i�v#�@ ��@���C`��!#��X�@ ������V��	�~�vK��Y�����JB�b����s���� �X�@ ��h����D�k�@�L�	���{g�t��s��Zm���/t�ZAM�Eg���b��00xJ��?�C�s���!`a �X�!���*��=�#��_vv�!h�o�����Y�|f~O���/��Zg�V�����"�n��-�b��1j�E�v�$�D�b��3�*	������5]���Fp�j�g���r�i�r�!
U����k�X��J�j�7�!�X���V"N�����k��G6�������F�;���{�o}�[V��7y���5��\��;����sN������-�����~ �X�!
��@��cO�!"�X�(�LE2�{;8�y]b$���������ts^��h'/K���!��~k;�]���$��4�5�!��X	C �P��I@�j�u��xi�5oC�cG���y����������b�W�u������-&�f���?��yM�������0�
`.��b]7��@X �a�$���b�)~:w���{>eQm�Z�^�|�t��u��v��LK�m���j��
����{��j������ P�u@��!���%�4m�u������}�l�������y�*��z�V{�9n�A��N���$dz�V��F��%�
s��w�#(]�.��;�:�f~�b� �.@�	�x��~�ze������Nm���D���b�Go���������������Y�J�v�
�b=jO���j��
 ��7�/��gk���1|A��ED�	 �A� ��%����dWwB>v@�<��W��7��w����Oz��e��	�r�'��V����N������������U���"��5T�B�U$k���/�C��O,	� �X{A�>CG�]H�P���<_p���<m�>��jo������O^X�~�L���j[��9����X���GT�W��B�}��	 ���!�1����}8 ���#��'���^�����/
%S�����T��s����ks���?���T���M}���nk�z!��ul�Z�}��b��1B��b]K���udB������:.]�^���N���S�m�������So�y����Z��/Xn:�)n^V*��u)B|��@��cf�� ��p�b�D�p����v�pO�[�+/�+����3[�����7d���n�c%/��;&�M	������~_�@�<�Rv�4��������Rz
b]�t�@�} ��@�k���A��F��4����:������YmU���ww�+;�k�lI��������o��l{G���sk�K?�*=�#[�2�%�����(����j\�x.]�)���ze��(s���&�x=
b]��@��F�Z@�kM��#A��D�3I]���xw�x[��g�0g����/�L��O�o���4Ym���5�zE�\�gxLV�V%[9w]�Y��Nw��'���4��{���<�0��LF������/�����-t\[����>��{
b]�t�@�} ��@�k���A��F��2�b�����t�1g>�3�%���d�{.z���X�\�J��C��c����z�=�}�qs���?�4����x�n��6pb����#�X��--C � D�1��b��Ej��
���&=vN����_�7+��1������M;}���\��7L^�>`e��?��p��v������-���>��������e_�U�`����)�m�zeW=b]O��@��F�z@��E�~BM�ux79]��8�����*�������y��N|�!
��p��o��q������	��v�� ��������Zb��u�"�| P9��rf<�0@��M����3�t\���2_m�eo�>�R����g�����N�-;��,�)�l�6���,s�w��i�H���<�����X{I��!���?��( ���+��*�u����hR��fw�r���Um'���Zm'����^(;������8�AfLj����%��:Af�(A���@�	 ���?�w�b�H��)���+��;�����9g���"�y���X�5Ld�%�����	����K��:ab����fhi8J�(E;xs��������K�&1��$�W\���3�]��(��Y�n�%��bY���3.�_l�:B��P��*�@�y5 m�u����]"�X��fjB��Yj'C�sG��ns���
k��yz��9;�Yz����������-19��%]�,�59H��u����G��_L�I��'m�
-�:��
���������c��V����������Rg?`',�����K}��K�n����Ij�r��kQ����r�
<�"@��Y���	 ����&�H�cT�S�	 �uGN�e��Su*��+�������F��Nh�%��#�m�[mg
����g����[����c�dN[��^5�:x1c�(F@��<i�e?N>�1�6���!��S�6�:��g�.@�]I35!p��N��L\�t0j����h�������)��o]}v�Zg�^���)��n��+�������K��;��Ww��M}�~U���V�v��"�uB�Wk_����b��Ec�*�W�L��������A�=�YF�.����IeO
t�����3�j�����K�����b���0*TB@W�/��3���n��Oo-�b] j�u�����E��i����S/�����%�����lg��5�9�j����;�luj��Y��5g{e:�������L�$���^�����ik����C'��u�o&�!�?K��L��${,5b��!��@�	 ���/����N���"��H�w�N^�U�QG��l�NIsz�:gow����|O7���{�?u}��X�
���4��)�����k�G��A�4��[�s�A#�r�y�sD ��Sa&�X�9���n�����2	���3L6�Ns�V�%�:�<����V����E\2g�<���d]-i[n�p��c�r�9���X�)��%���7g.�����;�YfLj*��.��
5�:��er�"�X��4��K`��ypC���l���f������o[MFp{+yf�o��Ad���e7=�-�>��5��r�H=@�������v���5��
u9R��D��-���� ����	(�:����S��3�����r�H[�;��rz��� ��S����l$�����k�K�v�q���j��������?���K�� q�u�_�y�u�_�A�v�"m�I �Z�)�qs�������}�:3�Y���|�>�cM�aK�9G���m����Y��������r���^yy{���l5Y���4mA~!�X�%��@���N�!#�X�,�!�N��1	s������`��tR�3��m�����U���*����z���:-_{Z�}��������B�����&�XG;���%��K i�U*�K�cm�~{�����V�Df��jgv��T�p����Ze�i����w���9��I��1��'�`��b�!|��� �>C>�:�1��~��>Y����y.���P�b��s~6o���s�s���{������L��A�Mk	�6�r�
��J��@�	 ���/��@)�u)B|�2 �e@�JM��0[vXW]�6�2�~���^y��~�WL����?�J�`Ln�3�4��>�w��NKez��������}�(b���0x@��:]B�Gk���b��u����g���������;wZ��g����;�-�����,�'s�Z�][f-�OH�@2)�~���������g��i��4���Z����q#����!�b��1p�B�v#�D�b�7����ze�<�9s�9���=��Fy��~���g��������m_���\�}�}qi1���G�e��F#�
r�=��n���e�QG���w�� �G����� P?�u�X�S�	 �!������s��9C��c
��#��	<fV���mqNn�������Z�N]�����]��5��o�(HCe^���rA��}��b���h@��f���%�4S����:e��B���U��>i[�sKBZ�b�ivs������2RmD<���m����)������k����K��b�3AJ����k �D��f���w�,�"�-"��i��^��'_������Zs��*K-��1�;�9&�{�����"�9��S�e�$;A����
=�D���L�5�!��w�&�XG;���%��K i&E@3y/X�-���G5�>���V�����t��o{Sw�D8P�Rmm�_��SMB�y��h���K����NX��g��+�k��B�k�D�b��3{� �.�������G���#r��
��� IDAT����Oe8n~Z}.�����F������v������^JV���D-��b��27�&�X�fD
�$�X�DD�
	\�@W�-�"���>��g���t~�������g/[���v��r�~�b^;+�e��.U r�u��� P�b�+ �.@��,k6��������������{�����B)�������G����&G�m��y/]�c�}��S�;��\�UL�	X&���@�y m�u����]"�X��f�e#�O�$a�v���J�o8��b���e��i�o<�%�����}��B=Nm�]�\�nk����J=��% ��"�b�;�h@��f���%�o�P��#�6��������Y��d�D��j�o�����Yv2'aY�vo����t����S_vb�Lo,����g{x/����j1�:��ej(�b]$�@���!�/�����e{�b���
[+�v�������8�����S�	���r��MVf�r�
����-g|�i0R��`'�!���E��@�	 ���/��@)�u)B|�2 �e@�JI���Q�Nf{;����93�������������dN[Y��2�~�\�a���Yr��*���VB�CX��
 ���*BH�aP�R�	 ��g�UZ�`�����z�;����[�NX�n�g��2+�����ea,�HM���dAym��Q�+!�C��Kk�@�J�h��� ���GPF����/��[	�jU:a����Z�	kG�����������2j�������e��Z[,W���j��XWK�� �uxb�L P
��j<��5�D5
�Um_�����X���:'�V��>�/��M"]��gV���*G�s���m���w����k��O2��A�y	 ��w�&�XG;���%��K #��n����n�U`��V���tj�9?5�%��+��0Y�g�W���h�<�b�m]���)����}�*/�������j�/����)�?&.���F��$ �:y�"J@�yE m�u����]"�X�2�hf�'�=��rl��u8��Cz���������&-�gU���������&�����d����1
)��������?�dB���b�P9�����g�4���@�y m�u����]"�X�2�������t�o=W��Z+]2���
��lX?�i�|��s��F��:�Av��C���H+2�:��c�:�z�i�X��C@��]xOg9U�u�5jk�w���V=U��7��i��.vF��+�*t$�"��;��@���&�XG;���%��K #����w��ws�ir2c��<N@��\��������3[��[o��_c��*�o����b�D��@�	 � ���	 �C��P�5�A9t;�mkzL�n���������9_�sW���#&w�?lP9~���^���Xs]V9�+]�.��;�:�f~�b� �.@y�{�����c�����isOu�yj�Z��W�cf����������<p��R���l�����Wv$��J6q��ME���<�O�v)
B p����C�U���8i,���F��y/]�#���k�������j[�U��5�h}��[e�9��\�5}|���BE�����d�V[�U�gOifx�!�&b�H��@�	 �C��k �k����������UUf��Z��M��	vSCLF�9��
r����i�V���#������z��f��w���;�B�Ok?E��@����3��@�CT���|�=&a�Y1�,zU�������;�S����+��`Ww�����U�b],�B ����iA�L�u����� ���r}���������+&�� w>���IT����T�>L^�e�p���r��
_�5XB���Ze��
���:��+��b���0,��b]'�tn�u��[�����N�B����������i��������X���V���J}�!���L/�3����al�=�����!���)f�y��<����U���1�sN����U/vB��3�gO���Q�K��/oz��	 �~�
c�@� ��cMO!&�X�8�����k����{�I"6�d���WZ�Y����N7����~P����4Kx�r��-E3|��\�����m1;�A>=�NnF�?�����~#�X�-"��%�X��7���b�����ddc����Ym�jC�
rn'~��:;���>��������[�.t���Ed�y�d���h�	��3E�=�O����a`��b�z:�:L�|.����'�Nm�n����rW_����k�s�-����ny��~����m������7������"%�2�]�m������w��~!�X�%��@���N�!#�X�,����V��O�H�I�=aL����l���Nn����0�b��J�����G����G�{�?�AV�V��gK��L&�es�
��X�pX�\~�����#�C��b���0 ��b]W�tV�u�"[(1X�9J��o����	��-����l
�<���v5���-�1i3�3uv��/��,{�;�|�����d�����b]_��?@�����@�����BL�_pO^�a�T+N����q���VFo������%�&��������s�m����'O��/����c��J>���.�{�l7)����c�r�Ym�D@f�X$P5$�X�.MC ��!��b��U:��o�(.�������ztZr���������q
��.~�z�1[��7������Z4�xf;/o�'7�[����$����R����X�>�L%	 �%Q�&�X�:�L�^�z��M?�v��fg��������4�X��(u�|�N����>���,>�~�����5��"��]������X�@�5��M��v���Kk�@���;���+�������H�e'���b��#am�.�����l��:F�Q���|����m]�����<�zU��9���:��n�!�uCMG�-����a`���.��$���E8?9���{���]����/�~�-��{[����Wke�;�[�����;�}�ii��5�UO��������>~E{��}��u�C�!P�b] j�u�����E��i������n1����]i�������WV�6����d�N�s:w�9)�	M�m�R'�Y����~�I�Z�o��"���o����Wv��=c2������5c��rs0;��J�O �C��X� �C �����@`(����Y$	 ��{f��Y��N���A����^��o�Df��k��^U�q����������&A��wwZb�Y���$��4/�>1b���0x@��:]B�Gk���b��������^���4}|�\v�-���1 ��������
��P�T��i����/��%D���f_��[���'�[bfu��v)(��K i&�X8x.@�]�H@����d��������y7�0�E�����
��V�Wj������$����7��#��q�)��b�h2TN���O@ �b��BW�Lf/�������t�S��S�'1��d��*�`�������!>�u�b�� P	��Z��@��_
]���<W<vd<���~7�������_��0��f�w������l��;�YfLj�/F���5�4��@�:W ��`���@������W�����k�Eg�W��T�|��=�������Q1��Mf����yv��V�����F	=�:�!f�(I�.��
5�:��er�"�X��te��\l2'��yR�z�y��+?����Jg�N��J���3��[��W���q�I�������^�?&.���D�b�83KF����@�	 ���?�w�b�H�����]��JSCLz�l�VaV��k�3L��s;���,��&����{����j��mouqB4�k������ P�u]0�	|K��mhX� ����6�R=��X�[��������l��~2}�����u�zF�{/:���[P�!��cMO�+����a\���>��%�k��e��ikz�w�Q�	�4�n�v~���n���Z+���,m;�X?~E{���>����A�L�u�����@�CX�U_�u}y�M3|���G�o�3[�cr�!��wI�\�!��	K������O��U(Y�J�t�w�i���w�� �^��o��b��80
xE���<���b�}85������b��k�������Db�8����f���f[����NJ�m��z�����Q7��������� ����g��b��H0xC���;���b�m@����Q�w������Xgg�vF�)�E���[���1]���Oj%Q������#����@�s���!`��b�)~:���H���������P
��^�eV�n���9Wl�����\������o��b���WoQ�K��n��9�5��M��v���Kk�@V��O���o�1����l_����s�V�d�sSV�>tG�}�Z����3�>b���-����z/��y��XW��<�X�%���@��g���:Qd�@���n�����e���=�C
�d����������v��l97�m]j�2�`j��pg�|���,3&5y��='�X{�	 ����@�S�����<,k�"�fS���:sxz,�o�������]�?�����v2�xr��x��;����$��4{��='�X{�	 ����@�S�����<,k�"���H_c2�*�������l�4;��3��'+sV��Y�n�\��sN���{|�3b��00xJ��?�C�s���!`a �X{E��Z��o7{�9="�pu�*���sV:{N�����m;���u:1��������zF��
�o ��p�W��b��H0�@@��	��
����=y��mYv2u$���������8���Y������F�����d���������b]/���@��F�z@��A�>BO���W=�+w<���q:�~l'#�o�6��K�V2��u���N�t75�Mq]�����xm�<h$�)�����/"����{D��F�z@��E�~ �O��?���F���.]�)���%8=�B�j�Z��u�VZ��k�T�?���cv���}@vu%d�^���h����}���L>�����r_��X�:<u!�X�3�@��k�����b]�h�w���#_���v��6�m�Jg^�5~L����L����0T="��
'��@U����BC�M(�������������z�~�)��
"7��*�7?P ����4��@�@��!@����!���������ozuwwN)��Z���}�a
r�I-�4=��b��21�M�.!J�u(����M��
�m;��������Y�w[��NL[���Z-�n�{g��)���n>�w�������,��"��
=�@�b���h@��f����z'�sn�Oo'������0L�s���ZS2��k��`��liu�����&w����[��`����"o�>���[����N���
b��3w�k�D�b��3{� �C�fS�,^�m�I]h3�����Ze�N��{�n�R����*^�v�K��k�
��sN����H��XG:�L�5�  �5/\ �X�QW���i]�5"&s��XR{��e����^����-r������Z���#���n��������������TK����A <X�O,�	�!�XWC�g �C�.�����/��3��G6�>�[T���XL�X��m����D9�!�~z�:���n��Oo-o��@�5� �X�@ ��h����D�.d�+������;2�u��9�]{K�]�;��v�fn$7��G6�s���P�Y���T�$���w(@����@�	 ���?�w�b]�n��o]����_ZE���������������F����gZ��2�Z�N�`g���\���M���l�n6c��K�a����z��@���b=x<
��@�CH��*	 �U��1d@��������s���g��=�I&�he���e_���lo7Whi���g�Vp[����Fg����?.���.���b��	�r�A
d���+kW0�M�t�<�L�2B��b]�-���.y2�R�]#�][W��?�M��������d�oZ��Z�������;�����zXsLv���io��	��5�w}��9C'�X�!-@ ���G��C`h����iX��/���:e����b����#f���n�.���?j2}��	������\��n=�I�}\z[�����Y�t�l�9 �G�e�1�2k��������>���@���i'�X<�C$�X �C�.��d��z������s�m�g��/����m]6Rm%��Ib�Hvr[xVoI����E���^��[
���_r�0#����JC�
�u�x!#�X�,�L@�+Fu"��u��bW�X�So7-�c�7��bV�U�u��9C��O�/���;��;g�:%�	ii���s��A&�x������Wv�+�*������V�w�M���4i�$�X3n�n@��"I;�&U��{����]����n��]�NH<� ��~#��j�������
Om	O	v�k��,�_,�R�YS_����kU���H�u�����`�Q�b�p1X�N�v)
F�@��Z����]���k����f������+����fy�Z���y[?k���K�������sg_�U��:��F�\5^@����C�{���1`��b�%}�
����L���j'��4�s�i��yu����+�*���Y�Rpg������~&}uV�����������|h^*&(�u���`!P�uM��(C�L���	DI��M������������t&E9n�z ��L��N.\'���V��b��-�6u�?�?g������A�=;����c7�:��ev(�b]%�@ ��������bm�^>����+�7���tbf����,��[�:s��p��^��|;�(��9\����:��tU��,LT�@�	 ��/��@I�uIDT�@iQk�1���L���A#�r�ym�/��������-��9���:+����5���yl/�VR���z��/��b���0*��b]/��jQk+y�����FK�Z��i�����W~��Y�N.G;g��de�[�_{%�^�N'1����3&���Z���P�`L��k���B����#���b���0����X;q���z��
����7}r��z���No�Nn7����A������s/��{����,`�:(�8N�:�Qg��&�X�F@ ��h����D �b���3��<]��i;�^��y�V^�p[���k��\�njH�#�w)Z4�	 ��3�E�b��1^�K�v�'�E�@���37wHO�H�sm�-���l�G[Y���+�r_gE;����9�EfNn������@�B�#jK��-_Z���	 �~���(��S/����������8������)����6p�ym���T�������
�4ExF��=C�7k����@���'��4l�"�������z���2�f��V�/.���l��.��N�3Bl�T$����$%s��3�����~�^>wj����Ju����q>�u��� P��2^��@� �a�(���@�z���r�c�T;E��Zr�}7u�r�=����u*Y*9Yr���c�5Z��Vm��>����d�@ � D�1B������u��b��1�@�X�$9���O�$[vHWoBZ�b�j����j��;i�r���3~�f���i�p��m������6�%�n����w�b�81J��b]K��
�@��#Fa��v�-���?yP\�yE�z���+-�y�dN���k���9l�5�L���7��i��vA}xN��<�@�=���kO��yX�A�oz�[}>������3x's�e{wr!�Rf���������tb��3�qM�(����{��� IDATN�@	 �C���k���F�X��?	�A�w����.��W�o���M[U~3�sW�������,�����f�y��
�b>��&�=��j������!��@�	 ���13��`k��@ b�`x��~��3!cG����}�����c�������ZF��{k{w��im5�������6��Q_3�O��B4h�'�X��9=B�ok�E��@���������Xg�H����d�vV�m��W���BWU�e�I\�H��<S�m	?hd\�:�-�o���:
Qf��b��h@��f�������fe����oe��^{�-�����<�\��V��l�v���F��OX�dsW�K/"�xF��=C�7k����@���'��4l�%�zzWw����nr��\wYg��,�>kwfI����8s�w�:�o��\S�f�h�C�����>!�X�$@�=O��"Pk�V��yu�9��o��{��;�U��s��*��%/m�W����:.��,5,�<uvFp�~�*j����+���@��F/ �^P�����X�
���L�b^mV}���>Y��������bn���u�V3[��5������������G���`L��k���B����#���b���0����XcGA��U��ip�k{d����
�;Y��dd����W;	����L�oK�-�9�#M�O���g�)�:le>��b]93��@� �a�&s���Wb��U����U]��m�2�"7�m~O]��!��4���J.P[+��������V�	c�i��L:���^���%�X�76�� �X��2}��@�����������N���K��Z"��&Q�����������U���������
��<����o��Z�������]���3Ad@�y ��w�&�XG;���%�k;Cw���[�J��i-2}|�+3��3!��6m�+��2y;���[;
�������O�?.�fE�Nj����k��&��+�d�A�2�	 ��#�A�b�p1X���X;�~y����J�-�
U�J�������	F�G���^�K~�c����T;��S����^�N7���5��������>�=�Y�����3F	 �.��)�b��1l�D�v	$�D�@��z������+���$���z���1�u;����}Ku���H'��oS��F+������r�����fS��-�=��w-��E�iP��X5r��@��cIK"�:�Qc��#��i�{���t�m��\�������s�v-UsG���-�3&5��5�w.2 �����K�-G��`J�j9N���ti� �X#N��"�X��,�F�@�:}��I6f_���u�Y�o��$i���S���},�1|���Hf�.�TNI�pX�\~�9O��:2�f�(J����@�	 ���?�w�@�Z�-��l[Ne��l�i�*;�mo��[3~[���������������>�D��K��b��1h�J�v'�A p�����������t�S/�e����UZ�v���8[�MMk����\%;3aY�IL~���]����6���z��u��e��L�Q�E��V��-
@�y/ m�u����]"�g�~��~��C�UU����=gg���9��m��}��
v�����k�'l������g���������_��7�X>�LC&�X!
@ ��@������������!�=vR���ir��Y��f��z��&6;��
V����<mo	?{J#+�~y�gk���1|C��M(<!�X{��N�F��b����r����3������M�����O�\|B�L:HW�E��������������S;l���.�:��g�p ���6�:��g�.��Xk��_�< ��]�}O�}�t2�X�I�Xk�2��t��p5"��&�Z�t�l�> �4��c�e�([�)�2�:��g��	 ��	�6�:��g�.��X_m�T?�Y�}�����Kn�.r�V��j}��Q�r��V����O���!J@�K�{��b��2�:�Z�u%���{��m�������I���-�zO�������)�L,�de�L����"G�P'zt��@��Cf��@��J��!l�u����}B�K�^e����zT�m��-�����Y�T�u��gY	��m�q��&&��G���E;��O^+� �u���P!P#�u���,B�H���	x)�'.�-����f�<��sz+xR�@T�N:����h�/��dd�~��	 �>
C�@�	 �uNw���ga8�$Po����w��������m��N�]�����N������K��e1Y2gr�W�Q{D��<�B�Gk��@�����2|�)���^iFn���
m�D�����s}V�L���)��k}V�`������r�a�r�Il����jE��Y��@p ���#�@- ���J��#P/��e���������T������nl	�~�{'��%<���j��-=�m�7�K����c�r�Ym��#�@��j���C�O,�	�!�XWC�g �C�^b}�=���v���Z���f�
uC2�w���z�Z%����9V=bXLv�����@e��xQa$�X�1��	�@��gEM%PK��U�'6����O7�%�������Y�.6D]������f�+��	�2�C�r�����;����Ze��\��+�r	 �����K�ol��!�X�C�:(A�Vb������3%���L�~[[��_��j�8WWg}f�O7��*�	��{br��FY������}b�O{\6n���F�e�1��a��
	 ��:BH�aP�* �XW��(F�Vb=s�n+�w�(�V��n����L�����������~�U~��~y0)�N�d����� �C����:Qd��b]=;��@�@-�z��YF��b'S�������
���:y?�n��5�������?��"���Q0r����J5�4�$�XW	�� "�u���T P��
h<�\�k=[}�"G������1���k����[?/9o���+*����"����S �J	 ���>�G�_L�*!�XWB��(B�-��3�ZF����V��Vt����gz�����D�2k%;���l7nj�yS[��O��|�9��ik��l�|��a��RI�x �Bk�@���@�	 ���?�w�@�b���7��o�9&�4�}�zR��������cv���j�����;�d�Mkm;gx�d����Dg
��=�������mV�]zh&������C E��e�@�	 ���?�w�@%b�fS���:}�U{��]w�:��5m�S�����Cw��(�Y��0�I>=����n�f��akb�	�Z-V�]zh&������C���,�5/\ P�X�&$��e�cG����V&o��;�	�q��c?mo�n2���uB~<���FN��G��kz��_	�b���0.��b]��r��u�ju&[�u�Z�Z���O����M�����pK���zfz@B�C��1=�@�����@����� �G�����G�\�^��_�Yi�ag��*tB��6���c%�Ju�<b��p}F�����_�8va �X�!��C#�X�OC ���G����@�b�g�/�{wF�0�oZ�X7q�������B��jm�X'������'�De����Q#�XG-���k�
D�b��3{��+�������������j�������mm�.��,��t��f�����m2n��`S �z@��M�� �?���b�� PO�u=i�Wh	T"���)[��U����~i�<u:yY��>�L^f�����KHX�����b�01H��b]S�4�@�}"���n����r�/z�Sr�g^���V����ZW�5��}�:�$��#���O5c�@h	 ��
-�@���QQ�$�X�2�L��k��M���[�3��RmV��<��f}Of��Q�d��\����`Ln;�s���7�A �b�; ���6�:��g�.L��/KK�������H���7v�Vo;������F�f�4!?�If�(����@�k����xO��>�^@���O��!PL�_6g�/4g���[���J������^�N�Qm��&8K�u����� ��y��H�	 ��!���	 �CFH4�:��c�~!�+�*���;-�
F����f�9f�>���<Km_�e��2W���mm���a2zD����B�q@ ��p���A��u9����@��VG�X����d�[��[D�(��l�V[���t�de�`�~j�n+a���Y���<3xzR�����ucLW�b�� ���6�:��g�.��z�a"����&)��:������-<}��y��h�tu�@�.b�R�h.@�]�H8�:�d�"�z�yJ@���a�Il��2��+��;�sY�5Z&��fO��0�i�v�����w�.x���n6W_?���]���@��	�� ����g��b��(0����z�|���79]���:����G1G�U���U����U�;s���u���Y[��4�f�}N�u����b��80
xI���>}C�{���1`u&���o�W\!k����;w�'>�	������c��z$�X�������
��=�����S'/�2�h�1��|�=1���_&�m�3�l��F���7����~y��
r�D��W(�@� �5K��:@�b����Pi���z�-9��#���^�3�<S��c���������G}T�;�����K^��<���^k�YW��te����j;Y��xB�4�YN;����@�#�X.d�@�]GJ��:P�b�C%�`�Y�h��Z�JN=�T�9�l]��w�}��_�x��-��^v������5�lB���\���m�u2+x��U���YV�o[��j����=��<� �X{A�>!�/�����h Po�u����g������}����~����g������n�A��['G}t�c<��N����DO�,���J��$�LR����mow�����E��������|B��I <$�X{��!������C��g��O~��r�E������N{�1�6m�%�_��W+�go��.M���le�v���V+a�������hD�l7�2�`?4�,���2|D��Q0
<"�X{�n!���O�0jO�G?��|�_�[o�U.�����l�"������>[�.]Z�`���~���S���g{-:}7V��X[�i�1��j#�V]{��)���������/!@��F/ �^P�O��b��X0���w�+_�����{��s�9'��������SN9E~���=��n�m�M+u�De�v�fk�z����g~��ho��4�W�
���!���AaH�3�����>#�X�, �vn��6�k�V�Xae�,�a��2}�ty��G�DWW���B�f��l-I�J���L�����L�2s��+S6�����-���a����
�'?�n���:� �;[�n���~9��}76��@ww��u�����^{��Sz�|C@�qM~����>�����^[�r�L�!zC�����.�����[�3��b���5cx9��W^���s�%�vI^����[��g�S����r�� @� P����_�����b�u ���A�\�RN?�t����/�8k���s�=W�����5x]�~����K%@� @ �F�-��3I�:0���@7m�$&L�K/����:�<���2u�T��7�)�_~���h @� �L�vhT��{������ce��
Y�v����/~!�sLT�0O@� @ �����ikVp������?�y���_]>���[I~���%��v�7�� @� �O��?��Qm�����;vX��U�5K�[o�%k�����;.�`�� @��B�
=��W_}�:G��������L�8Q���:9��c�@� @ �H��IB� @�@� ��"K�� @� 	�u$��$!@� @�V�Z��]@� @��:af�� @� P+�u���. @� D�b�0c�6l�+��B�y���b2m�4���[d��1����@�l��E=�P��(�����f���%7�t�,[�L�x�
9�����K.���??���o�i��_�v����S>��O���Vu#>���	,]�Tn��vy��%���	���������+��[�y�fy�{�#g�y�\{�������-�V��CU�AD��SO=%_�����g����>9��#��+����'����W�
��J(����Y�����	�M����w?K
Q(I!m�F	IE%���T(��H���XJZ��dB�([�
��T�d�,��������s�~���}�sO��y��f��|�=�s�=�u>�������y���&M�����m���V�`A���/�p��I;!���_}fW�XaS�L9���#G��;����{�j��ee���3f���k���>}��^��]��R�J�q�F��[������o6g��Y�f�e��P�HII��{��-ju��u?������v���c/���u���.��r���������s��np�m�ro�l"�C��z�%�>��c�]���W�u�]�-[6�0a���wA����g'�)�W�`�W���"P�B�4{���V�xqW�|`���s�[#G�L�q�����Ov�m����������������6�`�v��A���x��uV�X1��]�t�!C��~�w��S�V�u�B�b�bA���B
�_@��K.����d�;��3�Io�����+g����M�6�������g����9s�te�v�j�����[��M��U6����_=���\t�E�3��W_��h�=[��>�l[�~}�@A���
���+D��+����#�b����C>|x���U��>�;v��\�r�> ��?�du�:p����9��t��-��b�f��-[�����I��7�h���s���K=S�?�|[�jU���wo����-Z���V�XY"��@tF�em���q��Y�f�R��>�����=TS���������k
6��U��3uU�����f�{(:W�3E�����z�^�J6lX����\�	��M����'�)�O���&X'C�:|	����`����R�F�x��t�m�:0;#�@�zR��_��������J7X�����aY���s����������,=MN���~tk���^�zV6av@ ���p�Bk���{��s��a���qc��L=��`�@����A��?������U6��C���6I���d���9
��������'�)��u2���@�v����_v-�e��MU��t|�����U+_�ag�/�������+�����W;��s�S��S�uP� ���V:i�$7����C��f��&GS�o���i�����W��\��-[��
������t�����Z��n��7w�n���J�(HY=����W�O@-��W��������_���[����g'�){|��"X'C�:|	h�=����c���
���	���������������[+U���{��6v�����1��%\�zu�3�Z�l���Z��e��A��
AD\@]���N�:n�Bm�tTC�4'C�M=TF�{�DY;��C�|�>�-p������[�����H��z��sP��DrC"e�!nG�u2����&+��GZBG��m��i�G��A��g������ �\�ckMj��w��mk����Q�$G�|���2���ev4#x��g���/��}T���*�\jC Z����|��_["S����w�}wH����s-���� ��~�������lH��Z��;D���?���a^�>���HnH�l2T��P�_��s��G����]��k���S��!�@�8V�����5X�74�#��ku��s������z��y-��1��T��>B�IDAT�#�+A���h�a����g�N5�y���Z���;���X�!�f��Z�3�=tr��j����{���?o�<�H`��DrC"e��J�N�"u�H{����c���n_eg�-p�`�6�=��X����������7���A��
ADP@��j��Z���[��o����xc���A�U��Z��s}E��q�$]@��^y����[A���
��M�:���K��*�-�_������K�R�J���� �\�ckE];�&�f���Y�5����3�Z��6��S'��u��-����b=z��lrU�
��h��&��h}��c:��u������wo)M��f�lf����8C�#����iW]uU�J��H�"v�u�������'�)�!�u2����7����Z�io�Z�C�y�!�:;#�@�2
�Z>G����F���c����SO=e}��q�\j�k-���&�7����pV�^=��I�"" ��~5!�f�WWp-����-s�%�����ik}�5�z��y���*����\6N��h���THo�����5�����HnH�l2���P��Z�CO�����]}z
^�n]�����,�l ��2
���_?�5�J���:t�n��F7a��y{s*h-l�5y�dk���+�i�&�$gZ�v���n����f-Y^
YS@]��m[��Df����_�>�
�ZFS�4�Y�z�<���6~�xk��i��D�D����8�
��%�^g��������9�i��5j���7)a���DrC"e�j��
�R��Z3�j`M4�w�^w���(�b��-<)��%�Q�>r����U�����t���c]��~�iSk��m����h��53���&4��k��I�f]�;#oMXM6� ����[�Xu�~�\�-{��c�w�n��Pu�� �&�=�K�i"�[@-���l�7v�9�w�������|��������D���!X�d��	���~l��:O�<v����e�J�(��cP$O �`�������d5��&4�q�`�J�Mk��%k��9v��a�����Z�U���P�Pk��5k2<9����M�X���8G�R�Cr���^���[e�
�U��H���%K��]��z���R�t�b
6�������D���"X��c_@@@���#�@@@������"� � �D^�`�� � � �~�~��@@@ ����@@@�#@����� � � �� XG�- � � ����=�E@@���:�o@@@�����/ � � �@���� � � �G�`�G�}@@@"/@���[@@@?k?z�� � � y�u�� � � �� X��c_@@@���#�@@@������"� � �D^�`�� � � �~�~��@@@ ����@@@�#@����� � � �� XG�- � � ����=�E@@���:�o@@@�����/ � � �@���� � � �G�`�G�}@@@"/@���[@@@?k?z�� � � y�u�� � � �� X��c_@@@���#�@@@������"� � �D^�`�� � � �~�~��@@@ ����@@@�#@����� � ����a����x a�<y�X��em���	�{<;����c�=f����5jO�� Q�uD/<�� ��!P�B���?m���	�`�0; �� ��	��� �DA�h���?~�u.6��DX�`����#� ��:ha�G�
��px
 ��`u�n���U�^��{�9���M��u����[7��={��k��a�l����n�:�����X�b��qc�����������[+U�T�������O��m����6m�4��}�/^�Z�je�>����������<�z��i��/��O?�����^c�R��j�*����-X��4����.�:�sH�}���6`�[�r��G�t�?�8c�O�{��#�'���d�j�f@�,�{�i��@:h� �X��M�>�����	bG�[����9��V�jW_}��������u�����W^���w�[o�����U`�Dd�G�*U�d?�����U����J7A���K�e��6f��X���;�����V�L����]����e���^���]���
6���?�f��m+V��N�:��!Cbe��Z�h�����n{���)S��?o���`����!�Q XG�*s� �����������7������J++\��3�n��&�7o��p�
���z���%�\�&*��gO����
~�}������/��>+[�~}�������'�|��Dk������k��/������������q���y�-Z���}m�v!{���.�_{���!�Z�����'������y:t�`��@ a�u�d�� �@�b�<�L����,[�l�Tn�"Eb-�?���}��G.d�,Y2D�:ul��Yv����+�����Z��`���E9�L�j]V��]w���q�5�����3UWt}~��[o����5kZ�v�l���^����E�m����������A�
\u�oj-��7��{{sF �@����9 �Y_@!�Z�j��w�MA��.�/��2�Oj%V�l���x��?���ju%W���p�����{���KM���F��F�Ie�:�����v������M�41����������OUV������u���M-�^||��#G����c�����B@ �	����� � p�����{����|����Z��)��k�Z��iB�*U��	�TFc�U_z�Z��+W��&):t��k��V7�����o��Z�5�[�e�)��@����q?��S�:��w�}����N��	x�qH@�d X��W��� �@�5�����S��_��W\�f�~��w�df�K��'�x���+g_|����s������a�^�f��K3u��9~��<�&;���
�o���g�q��{-�q���O�>�<�%<~{����}���$������:jW��E@ �������M���SN������\7j�_|��o��V@V���4�����ey��u����������Vp�����1���Z�5���P���#��Z��5S�C=d
�����8p�[FLAz��v�-���SRRR�U�r�}���AHT�`���@��7�Z�w���P3dk	���e��5�Yk@�K���mZ�Z�Zi�dcg�u���/��-������i���n�����f����>r��[G[-������m���,Q��[[�X����2>z�h�P@�/��"���@��k�L�:�;�:�opN	X�`00�#� p2(�f���M<�.�Z�J��j���`�=��;
u������p����U+7I���Z�*���&(S�pm�M]�+T���/+�kY,�X��VPW�U
��c�3�u�^�zn�-�L��\Ko���u�]����8qmj�������p�yuA�4i�;'�'X��X^# ���Y�z�j@8!^������6lp�WAW:~�gC�������u�5X-�j�>|�u��������\�i�j�����/����j���c�kq���:��kkK$X��f-�$f
���\u�!�&,�f)��Ca_��k���MKmiM�-Z�O�;��"�'�����~�z@�"p�����@���C~�9=@2#@���e@H_�`�;@���@�w���Q@���b�K�	"�(@���@@@�/@��5�@@@ X�K� � � �� X��s� � � �
���j@@@�����9C@@@���R5 � � �@������! � � �@��q�@@@ ���_c�@@@ @�u��T� � � ~�u��1g� � � ��:@\�F@@��:���3D@@P�` .U#� � ��_�`�k�"� � �(@���@@@�/@��5�@@@ X�K� � � �� X��s� � � �
���j@@@�����9C@@@���R5 � � �@������! � � �@��q�@@@ ���_c�@@@ @�u��T� � � ~�u��1g� � � ��:@\�F@@��:���3D@@P�` .U#� � ��_�`�k�"� � �(@���@@@�/@��5�@@@ X�K� � � �� X��s� � � �
���j@@@�����9C@@@���R5 � � �@������! � � �@��q�@@@ ���_c�@@@ @�u��T� � � ~�u��1g� � � ���!���ZIEND�B`�
master-locks.pngimage/png; name=master-locks.pngDownload
master-patched.pngimage/png; name=master-patched.pngDownload
�PNG


IHDR�e��ai IDATx^���V����i�26���8+���G��e,��2��h�����D���1Q�D#F���	v'Q1a�J��>�{��{���~�z�����w���z�;�����S�����>� @� �"P�����J.� @� @@k6 @� @���<.� @�  ��@� @�@�ux\
@� @@��� @� ����� @� �X� @� @ ��q) @� @�f@� @�
@���R@� @�b�� @�  �X���� @� ��=@� @(@�.�K!@� @�5{� @� P�b]�B� @�k� @� @���<.� @�  ��@� @�@�ux\
@� @@��� @� ����� @� �X� @� @ ��q) @� @�f@� @�
@���R@� @�b�� @�  �X���� @� ��=@� @(@�.�K!@� @�5{� @� P�b]�B� @�k� @� @���<.� @�  ��@� @�@�ux\
@� @@��� @� ����� @� �X� @� @ ��q) @� @�f@� @�
@���R@� @�b�� @�  �X���� @� �:�=���}M�~��VW���/�7�����}��Gr�����O>)s���w�QF�%lq}��S�NM��6m������A�d�����O��fb�@� @�*��`�6��E��G���woq���s�u���[o�����g����>�#�8B�Zk-���{���?�I�&�>���py��S�LI���w�a���9s�y�_}y��W��U>Y�f#�h@� @�G� 3wB���;�e�]&��s�jW4r�H;v�<��2d��d��lwj����3�C��?�2v��v��3g����e�M7M��8q�t�A2b�?~|����
/K� @� PU�uU������o���;.��~��m^�t���y��7�?���M�]p�r�%����?/{���d�����.��)��"�^{m�y��sOy��W���>��]�J����g @� ��&�X�_�d��?L�����/�,���5~����{��\�w�y�e��1c��3�����_�������/�^z�L�<Yv�}w�26�,� @�@�	 �UG�~����_~���'
����������6�H�9������:uJ&���{������*9����L��;��[l!G}��q����t�II]w2���&��r�-2|�p���[�S�,c���� @�j�b@�_��W���?�n������mY�bE��n�@��|�;�W��}�7�p��x��r�m�����d�������>Xz��Lc?���Ae���^������)��a�d>����@� @U'�XW��,X�@��rK���{���M6�$���O?�<0�J�M7���_s�5�����r��w'Oo�����_��������<�X��|P����Iy��#�<�����_.g�}v����c=��< @� ��
����Sj��������v�M��o�D��`�p�	�W��W�*'�N|����=���YwOo��������SO=U��m��U#/^�<�� @� �u�Y'y�T����� �'���_��k���b����������+��x��{��}��~�,c�������jk�m�mB�r�uE�������/����?����N�����e
�B ���/����@������_����c�j�bn��,Y"���=z��E�a,�^�0h�����sg���K*0%$y�����y�z��WHk�1��p������W/q�Z7�����"�������o$��d���OO�e�����O''�W\q��u�Y��V�b���������[y��K/�$h��y��y�����~]O| P-��u�/_����U�y!�����&��n�9���j������62�R~�S
��Y!�~Y��N��wo��W�
T��s$�@�M7���
�'��,���]w�uM:��o+���O����on�����7y�t�OE��{�9�k������[y5�{��{2y��{���i�d��9�o%���b���e!�Xg���"�"��6-�:-)�%�X%��i �i(1�	��s�&�,_�<����*��{"����+���Z�*�o~���?w��>a�9��C���0�a��������
_�2v���N�L��y��7O�}������1B�����,c���X���5Y	 �Y�1>/�:/9��B��B��E �E�qmZ�uZR�kB���o�����������
��i���_�'?�����?m?k��D��������L����=[�x�������2��g�I�(��,�P6o�<�����Wx����O�26O��uj\��b����@�����,�,�[�b]���%�X�%���S�/���Db�C!�C�����vX���!_�>�I�&%'��~�Q�F����u_#w_)w���>����;y��f�m�b�,c���Xg%��<�<��&�:5��J��J��y	 �y�q]�uZ��@k���Z�25��}�A���L
G�fh@�5(S#z�u�� bD&�X���{�����,�6��Fk��)�:�$���;��V�X��f�� ��f����
��:�\XU�@�k,�].b]���������X�`h5�d��F���e#�5�
�bf.��
��-�p�A���&��!�1�v/�u����:�:�$��+��+~3�k3Q{o���� �&b�I�:��_b}�4�A���L
��=�E��"m�bm;��kM�vk!�v���	 �%�d�6	 �l-��i�uk��kv�Xk��[���=��H�.&S!���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@���X��E����n+]�v�7�x�E��>�H�=�\y��'e������;��Q�d�����N�:5�w��iRWW'�
���GK�>}Z��elVj�uVb��C��<��&�:5��J��J��y	 �y�q]�uZ�m����c���.�l�M��={�0@>��9��#d����{��G��)� IDAT>��s�4i����>
�f;e��D��|�v���3'�w����W^yEz���0o��ybF��P��������b���e!�Xg���"�"��6-�:-)��I���_N�y��e�����#e�������!C�y�d�S�
6�@f��!:tH�y��;�����9S�O�.�n�ir�������#F������el���<��&+�:+1��%�X�%�uY �Yh1���=�MK�NK�q�X�t�������k$���W�&'����y��7'�?\p�\r�%�����{�!Y���u���.r�)����^�d�=��S^}�U�������g�7f�:/9��B��B��E �E�qmZ�uZR�+J�.J���@��PbL����
9����{�8��D��c�N��iqk��SO%�D;�>���$��1c��g�!���:����z.��R�<y������el������.�:-�!�X���i	 �iI1�(��(A�OC�NC�1�x���d���K��=0����\�����������JN;��&����;��[��G-w�q�d{�I'���_��L��������r�>\n��V9���$���Q#�y�q]�uZ�-B�.B�k�@���b\Q�uQ�\��b��cZX�bE��1��owB���k�*�7�p��x��r�m�����d�Umw���,=��d{���'*{������L�N��
� �Y�����K���@���bl�uz\��b����@����4�4����M7�$'�p�<��c�W�����k��F�t�}������������������K���!h>����xm��FM�}��GY��������N��vl���=��~�ir�[�������E`��Y��c���!| PM,H^���Z����Y��
p{��5����CL
���*p�u����C�^{�*Vbj��,Y"�
G������^M���?-]Q+�t���l������|'���5�����ws���X;�uO�2����Jj�������X;Q?��S%��,�-^�8y�9@� @�b�>HM�����>+�������N��Kn�"�{��}��~�,c�}����K^�����6Y{����g�B��|</9��B���g���"�*xz\��_OK�qE	�U���>
�
��c����k�H���N|���'��~z�.�����~Z��o?qO?���IN;�����~X�d��k�^z�����Y���X����.�:-�!�X���i	 �iI1�(��(A�OC�NC�1Mz����8q�t��%y����o��B����N������O���"��=�����^��V^��^���H����c�^�5g��d=Y�����K���@���bl�uz\��b����@����4�4���@k�X��S���'L� �rH2���t�vHn���7�r
�e��������y��7O�uS;��e��2~���ug���f��<��&+�:+1��%�X�%�uY �Yh1���=�MK�NK�q�hK��S�D��f�'�;�vsO�{��'��vU>Y�>��3����������'w�uW�
/w:��i�Y���h+�<��&+�:+1��%�X�%�uY �Yh1���=�MK�NK�q�hK������~r��I�d�����5j�8���Y��������Sk�
����;y��f�m�b�,c�m���:+1��!�X���5y �y�qMV�uVb��K��K���@���b,� �X�54 ���� ��
��ej8�5�@�b�A��@���8�� b0���D���D��G`f�����6�X{�O�X ��$v�u����:�:�4���7��V�X��h�� �a���j�b]c���r�
���X�`h5�d��C��%#�5\�-����Xn��0s�mU�ul���bn61���)��{A���'��!��$I^	 �^��)�X���{����L,�6sM"�A��"��#�A
��ej ��-��i�uk��kv�Xk��[���=��H�.&S�I�fsh@��H���X��_�{�Z���Z������D�u�0�
�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���}��_|�E�������_��K�����*�������-�������s��'�|R���+;����5JXh���S�y�M�&uuu2h� =z�������Y�f��Xg%��<�<��&�:5��J��J��y	 �y�q]�uZ�m ���O����/k���~����cG����O���������7��={�0@>��9��#�k����d��I�d�}��5v��)����;�0�3gN2����/��������a�,c���X���5Y	 �Y�1>/�:/9��B��B��E �E�qmZ�uZR�kB`�-���W_}U6�|��gN���v[��������
�G�)c���x@��0��Zo��2c����C�����i��d���2}�t�t�M��'N�(t��1B�����,c�D�X���5Y	 �Y�1>/�:/9��B��B��E �E�qmZ�uZR�k �����,����\}��M������������^{��+��y��7'�?\p�\r�%�����{��i��Z�.��"��r�\{��M��s�=������k���el������.�:-�!�X���i	 �iI1�(��(A�OC�NC�1�,Y�D���+�/NN��=���kwZ��?��S�=�N��;��Lc��#g�q����2t��&�s�y_z��2y���~�,cS5�� �:/9��B��B��E �E�qmZ�uZR�+J�.J���@��Pb�j	��7�xC.��2y��g���o���?>���{�M��������Nk2�;��#�+�G}��q����t�Ir���''����o2�-��"���[o�U�;�8�26o��u^r\��b��c�@���������W�b]� ��!�X������h����O>I�8Iv�6w��%��o��9�����n�c�=��<����k����z(�X��4�����{�������{��a
2�el������.�:-�!�X���i	 �iI1�(��(A�OC�NC�1�%�N��w��<����}���V�[�nr�5�������;y"x���|={�L�.����g����>�^�������GId���/���>;y`Z��y�F�����,�,�[�b]���%�X�%������>
�:
%��&�����������Pn��&9����z��������_'�Y�u�Q���'�7gu���I����*Y��n�~����=�� @� G���h����	u+�?5�R��t'j�m�]����Knc$�{��}�N���uC7n\��-������=���26Kd����~�ir�;qw���/���X�G`��Y�;�����@��,X��������;W�s&����k�{�nx��a�^E��-�gh�=�����@5�9��=���X�t�5��7�I^�����7i�=��+_��80y���~�������������������O���
9���2��|�������7�����^zI���4c�f�W�����,�*xZ�-B������i	�U���W�_/J������i(1�	�'�xB8���+�7�xc��=�����V~�Nu{�������O���"��=�����^�{��������rk���M�u���6m���3'y�Z��y�F�������a IDAT,�,�[�b]���%�X�%������>
�:
%�4!�����p�:e����b��B�[��7�|S^|�E��7��\��
��>a�9��C���0�a����x����c��zkq'�N�7�|����{L<�@1bD�t��'��<q#�y�qMV�uVb��K��K���@���bl�uz\��b����p'���c�D�_��_��>�?s��\t�Er��6�w��I�o�dp'���c�w���>����3�$OwOw(�7o��u�]�+���x���g�'j�:5��J��J��y	 �y�q]�uZ�-B�.B�k�@���b\/��B"��t�=O��K=r�H:th�����~r��I�d�����5jTr/v�O���k��+����=�b���N^���f���7���q#�Y�1>�:5��C��C�k�@��c|^�u^r\��b��c!�����A���L
G�fh@�5(S�@��k
����b}�A4�X��E �&b��$b�=3@��D��Q��+~��B��%���@���'��!�1�n/�u����2�:�D���3VUc��F��X�hp5�l��C��%#�5Z�.����jl��u��r�$�X��Kl�B�cK4�~�p��ie�uLi��bv>����%I��J����Lq��L��E��G`b�����h�"���XG1
j@�5(S�fh@��H���X��_�{�Z���Z������D�u�0��M�5�C�b�E�v��v���#�����B��fO�%@�K��T�5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L��5{�;��{&�X��9�&� b�~�u����Z�258�fh@��H���X��_�{�Z���Z������D�u�0��k��w���L,�6sM"�A��"��#�A
��ejpb��"�Xk��]����f���&m��k���y��a2'���k��Xbm"� �D���!�E ��GL�k
�����=�E��"m�bm;��kM�vk!�v���	 �%�d*N���	 ��#0���D�A4�XC��@����5 �����5{@�b�E�v��v���#�����B��fO�%@�K��T�X��@��G`b�����h�"���XG1
j@�5(S�k���Z���:����5�G�5i���X����K$�X���8�fx'�X{���k1�$bD�/��>b� �XkP�'��-��i�uk��kv�Xk��[���=��H�.&Sqb��N���� �&b�I�:��_b}�4�A���L
N��Zk-��� ��������m�bm7{:/�b]"L����=��b�=@�M�D��u1D��:��iP�b�A��X�� �Z�m�A�m���=b�I�n-�Z1������V�X��Z.�>����� �X�� �Z�m�A�m���=b�I�n-�Z1�8�E�W_}U>��S�t�Me�]w���[O���/S�N�3f���o.�
�n�Aq���J��J��y �y�qM�uj\��b����@�����,�,�J��#��!�"�_~����?��'���r��1Bn��v9���K��te�"���\��yb��_�>����H�����Qf���X��p8�!��d�J����no��#=����X�g������
_��v�I�^�����js������3�O�S�zLP=V��'�/�f.kr�z�������^q��X��oH�!�!��Z�x��Vg�����G��%"����Wg�s�v��'�n�	S��O�.���t������k�����k�{�k�������^��*~����7�,.��RJ�G��X�{��VQ�9�k���@�����W@��
k
���x{�r��-�Z4��C��[��� �k�-��M�7�F
��7�� ������j���C���+�����~������Zk�%������R�=��}������u�?��c���'�X����@����,�'�X�C���2a��-.��O��{�V;�����zY�^�����.��vkdY"c�@�=n��c����#e����Q�F��;�(�;w�%K���/�(��s����Kr�wp������� ��������6���}k��5��:�F)8�.��S@�S�b`�ux/���%2��+����ST���6��{v�c��l�4-�%�X�%W�u�����?H���>��e]�tI���^�c��r�y��O���1E5	Xk�5����Xf��{�[�~���������e��������XkP��#�X�4 ������W�]wixu'������o5}~�������v� �T�b]u��p����s�L�>]���#���Nrz����o|��	����v����27i�������|]Jg"�:���X�t �:�c������}��\<�����N������\�<�����k�Y�o=��,�,��6Xkw��{*�k,m�j8�����:x���XW�0�Wpb�^� �XkP����O��HnAk|����+oU���C�'z�&�n���+�=��w����/V^�a�v�U:*�b]��sL�<Y~��_%(�;wn�j�	&��,��O��'l���{�V&S'���r\�����W2�T�[b^&����5���B����VW���V���Y���>��/c�f�X��u�������U_�N�u�Z���� �z�[�����k�i�3w����.W_}�8P����K�w��y��_b���+��n�4���>�P|�'�X���['�X�34 ����q���
R]����##W����X�����>�W���W��!b]m������n�N8A9���e��w�\|������_j�<�L�����v���{\)��#`K��p���^��Ox�V{;&���|��*;�:;3��N����+�p_	?�^�[�4��X���>r��5e��������SkvWQ�uQ�����r�{��{��E]����g��2o�<���������,���������R]��O�z�<��:;��WfmI�fWh@�5(�]cub����N�/��y��u�Y�w�:����b�A��]�v'dW^ye2�5����,�����[�m���S�b�^v���d��=�}�j�������<�F���_��:\��f�!�X��[�����]��I����`v��n
����_�17�|8Y��;�r��u�?�����7��A���7�������(w�yg�b=l�0y��g����	�����w�vO�ti���|�:{��WfE��~ �~��V��/��T�We5~x���~!g������n�:9���H�M:���~�	 ����2d���7��������;�8�~���[���<Xx��+�t{,�us��)y�~�e�.<���=����uj\��_�C�k�@��c��8�v���N���~!'���X?}.fg�C�.�c�Y�O�.����,_�\������~('N�_�������Nn������_|Q��~�\5�H��e�v��fo�Z�o{����*f��5�A�b�A������G��]��ok5�}���2	 �e��1���?/�{�����-���W�*��v�4(��\�I��X�wG.����=��w���T�b]]����b�n� �XkP������}�[����N�w^y*���7�?�ZyB}�v�d������@�Uq�^l��e�	�{:��9s�G���v�����+�;w`�,�=��'�/�f.k@�����%��Xg�� ��81���?�W���/���W=�����4~��;���j@��A�9��&��3��Z�-���G�����W@��
k
����\�K�����s�?ui���o��b@*3f����{O,X�����v����R��kb���-�!;w���-�j�7��Y�mN�fOh@�5(�W��G���?.m��n_�(��j��u|� ��k��|��g����N���*�{���K�^�
b]�=�XW�/��"�X�4 ������Xo���\��U��n�9b�>�#��c*�s�������v�I���6�`�6W3|�p�+�t{���S����ZuoS������d��6K��#��qi&�u&\�I��	��e|���}��c8�������K^�u�����z��pikb��5���{��
x��6�	����E��"m�bm;�"�7�K{�����m�MK�NK�
��\sM9��#��[n���L�I��XW^����kW�?o�aM�fk!�f�Wo�VGn� bm2����_����g-������W~"��ag��@�=n�o}�[����c�q��NA��X�?��k�^�p�k��I��C��w�-R����L��b�C
@�#d�����V�b]_��_z�%qr}��g����/k��K���w��������B����'w��?��_(VF�#5���@��lY�ud��bp8-
�Vs�=�hQm��������k�[l!����4���'+��RY	X�}/[�*�_�u���X���U�	 ���qEv�uvf\��b��We#�Xg�Uht�=r_?����ra�	 �]e�-;V��
���
��>b��p)��p���#�����C��O���"���X~�����+�
^�^Z�l��k��k�;@��Z�3UDkv��Z�r;5�_������j���W\q�4Hv�q�V��#`E����.��L�py�d���d���<��
R����@2M��v1��u	�"�:&$�XX��/��B~������.]t�\x���t�-������+���N�1c�H�����j_kE�+?��B�/^�PW{c5��Vn�bm8|��kE��K!��7�R��������g?���:K:� �����_�~�����������.&L��c������q��n��5�n�?���:\��%��]�A���L
G�fh@�5(�Qc�����={��/���wb��.��������R�=�u{��y�2(2G�uJ�)J�.J���@���b\�uz�]s�5���O���G�9�g�!�\s�����	�bn61���)��{A���'��!��$~�u���B��c�}��wj�����������i����>��RJ�G�n�?/�b]E�HC�NC�1E	 �E	r}Z�uZR�+B�.B�����r��7N��/#F�h1��~�+9��cd����>�@���&��!�1�v/�u����:�:�$���?�V�X{Lq��Y���;���e�m����k���S�N��O�.����?�2e�l��FWJ�� ����e@����i �i(1�(��(A�OK�NK�qE �E��p��,��sN���y��5���K:thr��W���*1E5	 ������5{A�b�E�v��v���#�����B����������?�\z��!_����s�����e�G�n�?/�b]E�HC�NC�1E	 �E	r}Z�uZR�+B�.B�����v�z����{�9�{����S����+X���I��&]��@��Zk-��� ��������m�b�1���:���k�=����{��N;�$o���,Y���J)���=B���u�#
�:
%�%�X%��i	 �iI1�������x���HW>3f�HJ�����:������V[��o����5	 �����B��f��9b�M�f=��f�>�F�}P�W�V�|�����^{�'�|�T��_�*��� ��wo�
w���S����W^y������+�TV�uVb��C��C�k�@��P��������b���e!�Xg�U����
^r9��"���p���b�f�"�Xk��]����f���&m��k����O���{'��|j�b]������ZI����X�~���b])��F�:�C��$�����e��=��}��������.O<�D�8d����X��*k��'�X�
4 ���� ��
���6j�'}�s�9r������sW���p{\.�WC�f{h@�5(S�@��k
��@��Zk-���9�����K/�
6�@v�qG���~�<%|��6���zK>����gW_}�y��WJ�� ����e@����i �i(1�(��(A�OK����W�b]�^�k��rK�7o^�*-w���!Cd���2i��d��c����#��{��a������$�Xg����2��_���l�a�l�X_�u�Z��r����=��X{�n�$b�1��]���G-���OVq�e�%�r�t��R6��w����g�}��J)���=B�~���/����h���t�Q�v�]��au$bm5y��k}�+"�S��3b����������������M����b��	2t�P����,�4�}.���������>��RJ�G�n�������2y������IN�9�$�G!���Wn�Vn�bm4xm#��,�X{}������Z+���}�x�
�v�m�����~���?s7���kd��WJ�� ��Z��;��B~���-o��N�>y�t��X_�u�Z��r����=��X{�n�$b�1��/�\�=�\���W���e�M6�>}��:��#��w_r���,�z���_��J)���=B���{u���wK7��Q�����[G���-�X
�C����K"�Cw�������=�7�p���?�o�1�zx��m��&�{���R�=�u{�V��=���q[>z�Nr��|�=��u{��yY��H2�� ��-��i�u����g����}�&����{���o�.]����������T���:���<s������`��k��:=;�:=+F#�X���� ��81�8��8Cfh�b�>#F@�]�u��Zx{�r^��b��s@�s�����Z�b]�$�X�U�a�����e�>��s��z��'���K�*.��|�'�X��Q+D�cH�6z@�k#�Z_%b]�	��������W�X{Lo���r��G&*s'�����g��E�I]]��9RF��q��NC�^=%����.O��eGN��l�V� �9�qYf�ufd\��b���"�X���E	 ���9���/��.�(y���'�,m�Q2�������_�3�<S�}�Y���[����+�4s�L�n�����&��
��7���"�o�F�)�?b��t�X��D��@���7������w-���l��������>_|���w]w��I^{�5�+�t{��	�_,r��
*����E���������@��Zk-��� ��������m�b�1{������w2`��6W�N���_���-_Q�q��nF�n}K��������[��9�����#{)�:,�"�X���)	 �)A1�0��0B&HA�N�ZC�����)��"��zj�%����_�"3f���2���u�W���NV�������~��?ZSzt-��)kCa{n���������h� K@�=���U}�i���7�����c�U����U IDATw�>�+��R.��y��G�;�����R�=�u�����B��WJu���?���'��V~��b���"�Xk�������3�J�.u���k��KT�:��C�
�1����X{���c���'����w�x��e�m��
7�P\(�����>��={�7�����<y���S�9���=���>x��Vx��kJ��ul���Z�b]����?��=Sc�����6���VQm�V�m�b�1�=z��>����ra�����=k����E���{���C�:;3��G�����U�n�iJ���d���Z�A�����k=��+!������ �m�<�����}rw���������b�����V�|�F]��I��?}n�7A ����j���*n��k���x���iN��L.�����y�u���X���U�	 ���Y�����>�@��M+V�Ku��*+����,Cw��bmi�������Ju��J��YU������>1��d���u�������	��2@�3#3q����g��;���>�o�Q����
�������'��l�	7�|����W>���mD��u1D��:��iP�b�A��5{@�b�E�v�$�|�B�U����'��]������v�4��b];���J�ZO�6��X�FN�2p�u�E�<�:� k�
��BR^b��y7/����}/k�m�Z�X+�h�bm8|��kE����bo�!u�X��F�kA���7Ow�����a�w<��������T>��� 7
o�dp�:O\��b���d%�Xg%�x�B�f[h@�5(S�@���	���9��[Zfw���'^_*�����{
9yP�;C��gZk-��� ������ �%�d��@�� Zk-��U��Z���-��\��k���a]�<�,KG�uZ�-B�.B�k�@���bVC�f{h@�5(S�@��mp'�o�Z��x�
;�8��B��B��E �E�qmZ�uZR��b��L���������=��X{�o�4bm,pO�"���S6.�X��g�� ��&����2
�#�:�T�\bg��u�X����I�uM�Vs�F�k.��]0b]�����������X�t|5�x��f�b�!@�CN'��!��dz'�u�	��>�:�k���R��5"���!@� K@�
�H��u AD��:��j�(����XG.��@��X[��X[N_�w�Z���j������F���[��X[L���_x����K��_�E�I��}��c���#GJ���T������s��'�|R���+;����5J�b5Y�N�:5�w��iRWW'�
���GK�>}Z��elVD�uVb��C��C�k�@��P��������b���e!�Xg���N��w��E9�Yg�ud��I2s�L6l��{��
cg��-�>�@�8�Yk����{���?�<�f�}��5v��)��|�v���3'�w����W^yEz���0o��ybF��Qs�A���%�������o����_�B�C�����X�fn��j�:����e�����Z.�o�QN�Ez��{�������jv��u�FWSG�k*�p���]���x�m�I�d���w�+O?��<��cr�$���`�;Vx�2dH���d�S�
6�@f��!:t�<v��vJD~�������&�O�8Q:� 1b��?�X��y(#������������\��r8����&26�6��vk���)���/�1�E�Q����}r����$b�>�me�ul���bf.A���w��-��B�?�x����������J��}���'2�t���y��7'�?\pA�U���^��c�Lc�����.r�)����^�d�=��S^}�U�����k������<b���'sW�Q����',+V��?��N�Nr"'�m�D���3F#�X�W��O�eQrR��s�~�e�.��Y������2ak���Z�rd5>��c�0a����/�����'��O<Q���:y������&�	wr}�y�e;f�9��3������C�6Y����/�^z��������el�����^�`���������	u��/rr�6K�:�>cd1�u1~���/g���}��Y������c��%-g9z�Nr����N�z=b���t1��t�j�#�j�m:�����+���n�I���k���������Nk�r�}��G�w��i�I'�$�_}r2���&��r�-I�[o�U�;�8�26oJ�u6r+�b��z�_8��:y���_0�������"�:��W5��v�>+ow�Q����[,����4�����J�M�>8�x����._f_E�f7h@�5(���?�Yv�a����������G�������n�-ybx������������z(���?<yP�{���puenw���V��,c�D�|�rY�`Ar�/~��d-�t�O�^z�N�z������?l��!+�_m]���=�n������| PM��
�f�J�Z�n��Y*�����NN�u��}��~+d�^�����yur��"��j���Z!�>���>�p��q2u��U���c�����e��������-�| P
.����/�����z�(Q��u+�?��������������;I<xp2�5�\#�4����N����~���gO�������4�=���j��6�����<�H"��_~���,c�@X�xq��5>�|������M���M��u�e2j���M�U� 0�����w6h��u�})���N�.���������/�(}�������V��	 @� �� @���'|�����[r��W'"]�����p�	�W��W�*'�N|����=���Yw�����rb����SO�,c��������&��_�����,�Y;��Nr������N�WH�N���=�N}�������	�{G<�mo
p��q��n�u�\[��l���'��E|��w�7^g�\v��Rj�0��cn���crbC����N�������k��v�ee5M��!��f����-����^��N������5�4���?��c���v�Cg���7.y����n��f����g��$�Xg'��e�������+�\������U���{�w��
�����+���l���v-;���-2V�+Fb�Ws�u5�2wc�c�~� �=��#�1e��D��o�o���_�vm;�uO��~�1
������O���
9���2��|����n��ye��k�^z�%0`@�W����b�����.�I\���Z}k���]�X���U�	 ���5�br�/
�����s'9y���9!���3�#�X����b�b��^�T��n������S��
���}]�W�^��o��}��?~���d���J�c�vl�5^��[�G�n2�{���i�d��9��K���x��7P�:;�}/[�������?5w�-9�n�
b�}�qE>�u>n�]�N�{�l�A��U�������W�X�bj��f���2��bw��{7����.�>��|���]���S�������9��d����=A�=1��7�������2v���N���${��7O�������#F������el��uvj����i���%�v��r��t+�J��+
�
�:��bY!bK�a��X��OL�C�cJ3�^�p�	ve�wS��j9�n��N��;���G�aN��������L������x�	�g�}��2��g�I�(��,�P6o�<�����Wx����O�26x�:;���\$�?\�������?~M���:�>��|�|��^�N�{t�3��q�u�������>
�:
%�4!Py���8����;������}��&M��������Q�d���-��2�}��}���Z�'=�����k�6�l��f�5r�:+1���[,�|�\Z��$_	o������"�:���z{����6.�w���}���(��o�����M���(b��&������X�|�4�:
m�k��s����+�@��l��#�-�Y��Tl�qr=�{6����>c��kv��Z�25�'�X����Z������j����n������|*8�f/h@��'���d�]��l������<�F���g��:����A���L��	 ��#v_��Q����������!g�%���^�XGl�m!����:����5M>9�.�1#b��G�����@���9�����_��%+�{�o���Z#�X�g\��b��U��������/����� 7
��v���!�Q�t3�XO4�C����F|@�}��S�����N��$�N�r���vR���c����:��Y[@��k
����b}�A4�X��E ����	��X�vb]�}��� ��
��ejDO��>� D�����"k1{o���� �f���(b�?�c!�X��d�} �a��������:�lb[b[�a��X����1�u�V��E�k4�\6b]�������F��X�hp5�l���c�a@���%�U!��%n?�u����2�:�4���;�XV�X��$}x%�X{�o�8bm&j��"��#0���D�A4�XC��@����5 ����X�� �Z�m�A�m���=b�I�n-��n�t^"��D�L�&����E��"m�bm;�����\Q�}�:�<���&������)�� e.��eBj	X�"PZ��X������P���
�b�Y!Zb���E�����/����3�,g���s������O�������}�o�-����T;�s��k{��G�>��G�qBW`�	R��u*��M�#a��/`�xc�A(�Be��5�@P
��R:����m� w�R����N���sX�(&�5�@�
�C7A*�N��#�I�u$���E�obl0�A��9���J�uPJ�{�u�����A�������=v��k������]�u�&H���0s$6	�����u�M�
��:�1<�8A)�J�t��N����=�:H��;�:����}T`���x<�8�+���X�:f��&��0C��N���� X�2���g (�A)��y�����X�vz�X������
�}���g t��� X�����$�:fH�"��716�� T��X���:(��=�:��r�� �N�\���;�Q���b�Q�X����:t�b�T�9�XG��_�:�&��P �`���h��>E�Q��A��9�(�5�HP
��R:����m� w�R����N���sHX��_�t��j�TE:(Cs'5��C�>��X{�7T���B�p�'�����U(��B<��Z��k�p!pV i`}�M��P��zC��K����:D�S65�:ei����O���=�-�CS&O�$��x��,�8p��tf3
c�5F8
���=����h����^����N����7�:X�1[BHXgh����0�:D�S65�:ei����O���=�-�CS&O�$��Xg��v�Z(\&���4?��Cst��M����q�68�D��R��q�P`���CX���:�1G�HX����n\��p��|��2s���c�i��:�������$���Q����`]Cq�h�k� X�2�X���:(�1O�HXk���O=t�����J�p
����Ym�9�������k�� X�2�X���:(�1O�H*X���C��k'���Y��:��v���f�8A(�Be���J�uPJc�D+�T���a�����:j�,=�5��:��;���i�'�q�W`��i�9�i�|��X�7fK�q�]�]k��nj�J���OkC���_�I����H���n�e�v�����jm�������u��9��V���V����B�u*cQ`�s�� T��W �`m�����s'�e����n���g5�}Ov�W��~���j��7zX� zJ�X���o`��)�`�b��u�u�bc��*g����z���"�\�`}�T_�����'����o"s����Q[���O�X�4��:�1�(��9B�u*c��+g�>����j1�Ec����
����X���<�3��j�`�
�V�4��N����;�:8�1S��3XO[���m4��3h�q��T\�y�����#g��.`�X�Fjc�H�#��X'�����:2��B��@�����z���\��0����ES�������Zx�m����h�x�`O��m���Y,��X��vqZ9�:N��Z#�@��ZD�^�Dm��G���h��������������������s�>��\dm�����l�h�
`-{$u5��Z6z�XG�&I\�:�V��W �`�bC7���vu��XY��[-�f���@�6��g7�-&�X�4��:(��=�:��r�� �N�\���;�Q������]���Zz�Y�e��q[_�B7Mnr���c]���K�������+��^C<��kw:���XW��v����V��r��k�;�@�q��oh5Au>�G�L�����O��*��2���:����P��������
��k�+�W`]��x�;��t�U�)��N?�
��/p��eK����������[��K=g���<e G�?0g NK�
����V`�Z*\X��*����X{�W���B�p0*G����=��u�f5���/�9��R��	��0�]w�����D�W`]^#\��kt�SJ+��		J�uPJ�{�u������@\�Z�Qmk�E��c������J���"x�a���W�y�����!��T�1����-��������Ry�'K��1�x�/N�X��Z�]+�:������q�X<��������)W�`Wo���O��i��x���p�jKr��FqA4��&5)�,��������^~=O}f�8i���=��?��#-��OQ��u����������*���� ���*���	��+��9�a�������wX�X��|��X���a�`���3q
��5c\_'����WZ<�����~����0$�eXv�������� ��pA+�v:�_�ehd=	X[���ivO��y�����i��e!�������:��Z)��ZX�L��:�1�(��9B�u*c��+��#������S7�weh��}��F�u�V��l�[/-��;�����:���[3������r���fb/Cu7�%������b���~A����X��|��X���a�`����`�N��k�u��c�D*���g�-m���x��E^��7���5r^�J6��%�pk�����`��`9�|�*�N��_^us�u"}DrS�H�%q�X'�����:��I����2'6�I���*��6���lv��,���n)VV���^
Q=���2����
���,��v�n.k�m*<�a}�0op
���:�3��l�`��V����N���o_H"X�~Ck�/���^����������������h��Qut��9SEp��k:i��y�{�.>�A���dX��g���Yw���m�Z�>�[%���x��P�p����J��Z��*���*�v���F�u5��^(PP �`�*���v[�Q����/6��g]�`��zWg^�����Z����s'E�Vl�"��6(K�*������G��Q�����a�u���kn�u���n�a)��y���y;X��:�L�I���x��em(��Yg
��G���;@.7�v).�Z�u��.X�	�������2
�qD��
$����l�n���~�I�t���=�}��(���#(�A)��y�����X�vz�X������
$�E	�^�I
�s���#<��i����i�x8�X��{gX�����`���1�
$�h�Xo	`k��j��X�+��X��t�[8�:v&�����45�Q�H2��N�]��+�u���5��g���`U�$k]�d��	I�uH��lZ�u��v�!�����)2v�[X�l��L�N�����*������� IDAT�x���'!(�A)��y�����X�vz�X������
�}�rT`������N�<�t�?����T;�s��k{��G�>��G�cz��~KSLoY6�:v��.�Q�Pr��N�-���u�����F�ulL���cM�����n_��,n`#��4�I����X��X�
�U���*�p�����+��X:�t��8
�>�K+��V63��M<�>RXG��bV�yY��
���^4���
�Do�.W�v).�J�uU��f
�=��K+V`]�t�
��7n���o���s���v�4���W�����I�>��a��D���q
��u(���t��v����p��t�.[O�
��������r
��)������/%��R
�q>��
��c���<]���W��H�G���d8�������1��2�?�=���+K/��ND��=3�X�s>J�z���h��rf���s�~Y��%��`�+X�
�U���*�p�����+��X:�t��W��A�=�[d��3����E���53<�;�_5��%��`���U?p��.Z����:��c��L_����k
���h�.X�	�������2
�qD��
�	�O���V�g4����������7���;�.�A��)a�HX��h��H����m���>�d9���:8C���S�:�V������Y\W������n�u����FT�4���7�Rk1�r.r<�����Tu��.�mCwg`�\�����/���F/����Gc}�~�����*��P�(����B��_
��R�)���
��@�Z��
�*��7u��TA^6s`,{�J%�k9g�:��g�n�L��F���u��t���'��#���
�j�(���d�6��x����/�����gT*�WR�`���;�:��z���O�|�t���Y�$�����U�^�Q�st�z������!Y����P@�/3����6����ir����2�`�z�
.c�au�UAX�eq�cw~d�/�o�s�_��~�.����:�?��M}ys���&5)��
����o�|�������i�
�q2�R`����`�n�c�>)�T���������3��S`:Nc��n��^��>�e�E�
�E�
eH�������
�*�0<���X�S(�������� /�n�Z������per��:������o�^.�`�YJ����Y<�����>M3��dm��f
$��z;������9�W����vy����?�@��><�����q*�k�����sDC���5�a���[�i[�e���g�b��J��X{<��"����*P`]�h���k���(P�@:�:�m����Y��~����3����~�������]�s��`�����T�=m����������������_.��o�$�`�+�c�x�)��X���X$H*X�������,����~�L7e
<����@97�{z��ju�:V
v�jq��Bm��_�/��5H�1���J��[G�y�`�����i�|��X�ygX������
$�E()^���v��z�-���G�16��d��w�zis$s��(����n"��[��r�������\@M�X��S/�7rx�n���N`����M�#o��,`�SFz#�H����Ik��S�j�,|1�����m��;�oT��0X�'�]4XG����.���Vx�MR�o��\�H
�u�6M����X:�}���AV�N�����+�t����z���"����������������`]��r,'�qU'�����������I��Bj^{Y�cyb�h�u�L��ck�X-`+sa�QU �`-����PR#���wu�#V��_v��7��jy��rL�x��Q�J�kz�{S_����B��X�o�4�`�+Gc��h�!��X'���_ 
$�ED����m����>u`N�h��k�w�F�{�z��������Z��M<�^Y���m���u����q��Z��x?[�}I��M��<j��JU��9�:��!.�X��R�_'�:�6���q��y��vF���jp�l��@z�jk�������T\���E�x���:���I�������8
�u���Z��6�+��`���6+�:mo����O���4Y{��i��oh��4�6VN0���^$��X1�Z����-M:�[���e��3P�z���A���������P`���x��nT�5�*��VA�X���
�q�Z����6+�`m���
	�����Gs�BZ��[O_�n�e��rfs'
([	���:�'(�}���;����l����Nk��`�
�v�b��ES�i� c������P����S	`�+�T�k(��e3��I��\�Vo��?<�K�
:�����:W�F�"��m������.�u�����A�������=v��ik�����L
�c(���,�����3
��4�h����
 !��r�<���U�ZJ���wr��W{��T�x�>YZ<m@���z�]�Y+�:�K�������X�vz�X������
��5	�{(������"0��|���5����|B
?���g������*��
���#��^�Z����L�"?|Uy��
����$�8�"������;Us�5�X�(��:�1G�H;X'���
�yIGpe�E�{8���@�6�����'MO�P���g2�V-Cu\��+�6��G:�Z����#c�^��Q;�V����z�������Y5��X'��Q��:�VI�����)v��Da��K�i{���Z}���J������;|�,]xb=�<�[�/��Yy�N�������z��Z&c�>�4�����"���r�2���>s\C'��)%�d#�H���J"I���OrV`������N�<�t���I��OBF�1j{1#�������H`��uz�j�m����o�T,`]��S3���aY��������������K��l���V�@H{�.�u�%dy��2�X��H	X"�:F��W`�
�X������W
k5�����k������}E�B[���b+Kt�l��z����w#�����
���fm]*P��o����d������D5��U��W�p}�
�+U�yQ`�E-\X'�h���u�AC2tW��i�Kx�Ns�8g���'y���p���?g�8��8@���c�h������P�).k��F $�t�`�F��g�u���uF�uZ-���������:��5l�[�w�o���"Y�\^f����.*��������W�w:�P�>:O��nq]T
`m�y���_�a���|��>[��l��]f�{�2?>�k?T�3�)�.�~��k���sJ)����>(��A�?B���
���Y[���^~y�pn	9���6��3�g�sL]�a�E����d��<����7�{����4c\}�%�Vn(��?��]~���U���u���
�=K�*T`]�p���kOr�b(`��:�'�Tq,���<iy���:��7�T�]��>������e.���9�bdk
��N<4�����3}q�J;k�(UM<�'��3�uZ,�>�������i�vx{X��=fN�����<\�2�O�����Q
`m�����/-��<���x\y����KD��m}t��,]|r��`���N�	f��`t�,Dk�� X�2�H����x5{A�=(.M	��Y�^�~�<�|�;���=lp�N9���j�y]���@�J.���3��?��F�9�q���7�y�e/Kg6��Af{�u�A�`����`�N���k�u��oN�u�l��@������
�	
�M`�`RF�W��w���k)@�����^yNSU��<	?�5����s'5�v9����]t��9�#�>��/sR�����l��������\;��^��{�peu
���w�S`�N'\J*�&���[���o��[N%��������%���G�����	v
5�V\��Y�[6s����Z��o_�m�������5��������H@{���U��������V���M���2����^�:l�c~�u:��]��`���`�|c�(�&����vz�����~�D`��M�V/�L� /D1_�^k��u�r�������:��0���Nz�E��nn������{X��(�g���"(�A)��y���?v��Ik��j���n��D[���9��S�(�����k���6�r.���@�DP\uO=����G�G?jOG�t1��r�p�{������)��N?��N��;�p(�@R�z!��]Q�����:`���=�v�������^�������ni����Y��
L[�N[w�tw��Pp�l=g)�2�n����~�&9	�)��f�^
\���F?��?v������X��
WV���:�p�;��t�UP u`m����`u�os��@�X��,�����?��c)���l/����f���gz�"f����@��6�@��S�k����D<����5����/[O���G��>������dj�� ���9�I�h4����]��*�u��=��g�(�
$�c}!WZ��T��G�M�d@���t����4�{H$P}-{X�C*K�1�Yr�wu���Z��
���'�./3�?�C-�?�Ng���$�3{���4������H�G����I4������
�u�-����c�$�`�d�bo�)�D�v�
,��sy�t��}�B��S�����U�I'�uW;m�V\�����A���f�y��hh�@[������������<��[�
��L���G�*������~�u��	�X��W�������
�qB��
$�o\�iB,��|���dI��x�'�*����{��HU��>0'�`����mX��������!E���Ys���G
���)	)��*�M'JB�����~��j	�
�]��K|Q`���xH�8"P���Z,VsQ-�Xj8�����w��VS{'�������C��mns��������AE���R��Zyi7�4Y�������I;��=�Z�hp����S\�u���gn�uzl�N�a[ ���ag���
$�5�n{��~���Y6�W����V{<
l���/�U���a������H�Z����7���$�������^r���z=�BK����� ����;���W��0�3���1�X'�����:z6I���I�l�����=���*�d��|��Nz�Zei�Sm6�3����>���-���������j�^
l	X?���t�c{=X����n/�q���y1�@)�8A(�Be�!
�q�P`���#�
$��s5�
[{���>��������6�,��Z��bOj�����em{�,����!��w3]#?@c�|*�u�
���cb�,`�#�`�	K��I�k�=���6�/rWq�0�����+��<��v[V.9�-\N�s����S{ZKK�O���8J����)�.�~��k?T�3�(�v���V�u�
�~(�
$��[g���{P��sAr*NG�`[�X�Z���������w��5EK�u�������j���`=�$qE�$Z{
\����7Vv��g���������9��x����3��j�F����������xhy�6zk���z(`T`���� T���� �A��9�@��Z����z�S�^�KNn��p%�af\m1,�j��m�����?>���*����1E��N�y#�9�u������kZl,H������Cu^���ZK��PK�l�tX�.�6Z�����Ou�P�^*gK����u�O@p�X�u�gX�����`��i�
`�V�c��*�$���X�t�!}��_�����l���zT�~C���uO�e�7RGW�����Z�x��6�i�xx�ukI����j�T�6��z:�S70�@%
�+Q
�T����p�W�^��P�F�$���������3�i"��t8���D
��{��,�a�/�s>�T���W�a�C����{�����{�,]rJ�pH�������>�
�����]�������2K"�,����4������
�'G�url����n�d�`�;b!+�$�)�-n��;��ks��6�?Kz��J8����J���n��,��Ps�Q�Cu���?��[n]���:h�6k?�<��7)!�a�u���kn+XK��	T���T���~�5w����T�[�u��	�X��	WU���:�p7PHXK11���e�&���pj�k��@��)8�:Gw��"�w��M8��S���|���\�m����<���K���\Y��3s\�Po����2�/��
Z���*�W�qXW� �w���g��N��N�/��B�/����EC�u4���U��`�����XAHX�It���[-�����}���O4��%��n�T�[�����mj-�������t3��c9{�ny���Q7Mn
�'4��+�n���D�l�)^j�$�q$�q����"W���$K�u������l���
`�[b'!*�D��\������A����2����{�����~���D�K��|o���_Z�Ao���:O9���������k)���w�����������W
���C�?U�[�ZK�o�|<�>��T_6��EF<��k"���XW-!�
���8�9C���S��qU�l���:c{�:vV_=��u�`������:���J�O%]�^�^��^4���
�2��#�g���C+�(��lc�/��e�W�7`��6A)`k������{��P�������+�	O�ux��mf�u�,�~�����Y�.]JS�L�7�x�\���_~����*Z�v-���[��������K��rJU�n��Ay��O>���7�������������Z�J�������Q�8�0.[,Nh'����!�7��I?�c5U��:hH������w��n�}��9�����j�k;���2H��P���j�
��O8��>7.���k7��5~(��nK"Jvu���7��{���~���<���\~�������.n+X��b�\/�:�v���7n����X����t�������/��'>A����}����k����N;�?^�}��'�y�y�����7�T����{�_��6lX�s�\[��Ik7z�7K�I�3���g]GW����2����3m�����}��%i<�z������?�m�\{��������U��U�	���/����o6u+/�����i�?�V�4^�N����3�:��6+�:m�y�?�0}�c#bv`=g��?>�X��&L��\'�-^�}����z�)�K���r�>�z���h��M��w�[����s�9��M�F�-����k+�(�`-�������^a��u���V�W*r���\��_m��4E�8y�����,�����!k���s�)P-X���:(C�.m���|�����U`]�$me��Y4��XG�.�_Ugg'}�s�����'��x�}�%�\[����G���@�q\}����o~���[G'�ty�V���;�8e
?��M�;v,�����^{��������
�V�s��g4���|(����R�u^4��X;�����%�������������*P-X�~����>�u���$�y�D�5�AP
��R:����m��w��K/)�<q�D���~D�_~yx�1����3����z�!%'Z��k_�y����n�/}�K�|�re
��������o���>Jc��!/�V*�ZW��{�G�p.������a-�Y���[��g|��6=���������K�i��v]n�X�Q	���@������'_T���[z_�>�������u��5��i���`7�Ed��������N8AY�\`���s���|��7+�m[�l��>�.��"�������3f��[n�E�L�=���%K����So��>�)�rm��&��R��g{���	������������k�����?���>hHVi��gn��o��N���1�\�W� IDAT��]M��J�����n��u�*P-XK��M���|��~����[����
��k�+�Q`���xJi�8!�(��?�������,���?�K.��4��jK��y��G��wy�V���_����.^���?���\[�I��wu��m��Y�����\���C��R}�������%�H�����E�:�<_&����5>xx|����|~������A�z������T�'y
��g���`U�$k]�d�3��8��~��\�l�R�8��
4���O���o���R���I/��6�x@��o�����|E)���Z/vuu�?��O��^x�Z[[i��Q^�k�{��n������}������^�����09cRu���9�[��BV@��vtt(g-��,T��+K���H���h������P{�Z��8>r��t�����cL�R�E�[���b�Q"�5a�d* Jw��E


��X�KI2U��j������vx����^{�z:_���G�+o_��T��X�v�m4}�t%�[B��C�X�J�p/�N�<Y�u�.n�Y�y��?�����k��_>8R�<����I<3�6��S�P>v�,}w���l��;G��u���
��L��st��t�;i����8��Q������_T���O�'>���26����`�sP�N`m�\�Z���AK>��k����V[G}�i�Z���^��T����K�e������V��0h�5s�/��v��J�%�)y��x����@(8NCP
T
n�N�����z�5����h4�A(x4���U!<�V���
=��rEN`-�+���f�RzY���>��3�;��]y��
$��V������s�5=Wk���?���?���s7�V*~��Zt�e���H�j��7��bm��~Bq�Wj���x�..�/�
�,J�u��>|��� -+X�����`�����	�%�`��!4b����qh�����N>�d����k��\�r�����������'��7�|S���rm�X{SN�X�YZ:�����t��oN����8B��%XGh�XJ�
�C6@��X���!n`��I��	�e�R\*~�\�����G�����}�{�����O�-�r��GI�����t���_���t�Yg��i�h��E�{���$����E�jB��X�M�2&W���:�{IB���[/��UW%���=�8Y+�kX��~qY=�:.���:���av����b��R`�c��w���T���c���:�^��N;���z������RQ\*�K�2���t�R���x�����\[��Ik	��c��bG��6_rr#�������*�=Cs������r�5�;h�s��]<2G���Z�jx��O!���O'��D�u%���
��*��+U`]�r���k/j�ZGJ���$m�$�z��5���G�G���s��)��R�L/�J�����Z�u�z��J�����=E��r�WS���r�5��h!=�+��,�O�tf3md/���ut����Q�*�w�6����8Z-�kX��nq[5�:n��z���]�V�������*w������������#{j�0�u
���M
�q �P`���CX���:�1G��;X����6m�[�h;��]����'��x��3��G����o�i��K��#��������c��(X������6nSSE������h����`����`�Z��q�u�rc��*w��������Sd�Z^-X�E+7t�������h��
~��'�iQ:(C���V�!{��f��"C��W�B<�������d�����h ���d��5(���m����q�94Gs'U�B/���r��T�=�M�C�=u��Sgrl�
���`��ZMU�������s�(/[�l����Y�^�X	�5<[�y���2|ZG�*�[���	|w������o���������"�qS��K��<|�Y}�
�X�����#�:vH�*�I�0��qkI�z��.��S��=~��1������jYa��z�����.^����{akP?�_"x��O]�:h��f��� m7��#Cw~���e�YP�_�����q���sv	������u�m��@�:�LS8y�����!�7�(��Ol��7Z�����3���+��dn�amv���X[�.T^���mdx;y����u�N��1g4������mE��%Z����)V��k_���J(���B�u*c��+w��X(\&��v�*����z����Z��=��Xg����"����Zx�a�TXg9���6����}{�O�0�����2��Z�����A���C� �Z���c�v�����34�&J�F�X'��Q�!�:*�H�:���/v�qk���V+T�L���{|�r�|�����\'�t��r�4�goF\�<�����^V��������=����[����0�����:�����Z����/���X�i<��@P`-s��!���hN	3-� X�������i�~p{X�5fJ�q��wu��������x���b9�k�����@�xaK=���vk$
��B��k��W{�{�����9�Z�R��5����G�����w�~2��g?�;l��
	�5�q�7P���N�1#��u�����G�����7�'&��V�Nk���+�����[I�['����X�]��n��Z�.�Z�7��=��>�`��pv��
o���V^�4����G5��>�\�->��4�
��j�d�`�,{Fy7�(['9kX'���I�
D�%z��}4�s�!�n�Z���S��7�����^������������j�9v��d���l���Y�h�Y���]��q�7o���:����H�k��g��%�
(��@4�R���d�MX{�C;�
��P��#����^%��U��f�5�W��j��3�h����S-�Nk�����M�}�Bk�:y�����?e��~��O������w�����+���!�g��>�*��{.{�!���Z�6�������N�<�t�?����T;�s��k{��G��N����Ro�P���WAn��2t��W����Y���_P-��;�c����Q��Y�'oi����S]�h)Vv�19z���h��Hy��3/�����bC�Z��<?�\��gpK��g4V\0��������JN
��D�u%���
��*��+U`]�r���k/j�Z(��@���������zngc�������@,\+P[�Z���������%m��Vs��c��Z�E�B^����>��@���?��:��<�^�N�����e'WS��>���>.9�=��{�����P��e/��������������)a�n�X�=q��Z��*���(�v���C��*��X�S?�.�"X_����B��M�-�b��.�e�rK/up).�k-����.0+`���y)��v�S�%7��2.|w���,�9��
�}v\#M:�����P|�+5Y4�<��|����
�p�����J{���W'�����h�(�
�S`����X���:�1G��"X;U�������v2�]A.��C�p�2�RC�{�����p��Zm������K��Z^X�g�-��6-%�����1P|5_��F/��
���<��K�o��ES�_�_L���^�.m\'�7KxX��}�fX�����`��i�`�Kc�5U �`-�0�k;���al��8��N:4WS-�W�X6�b��uSy\�2�Ak�n���[2t���|��v��SB��C�?xd�����>�b����Y��������������w����s�c������m\���nm��}�k5,&K��D�72�XG��_�:�&����0w�
�Q��M�i��X����y��6����D��z~O��KJ{�e
���y��f�~����3�=��u������������3/�m���pC��SH��u��n|�a
%7�E*��<%���p��X��'�f��'#(�A)��y���?v��Ik����w��-�li���BK(�C��o���:����{�[\8������Q3_�!u���W��^i����<{����Qu�
�Y�*Z��Z���\d\�s������K69��N{E�s�i������ap�~9�^[�����gt�w����P`�3�� T���� �A��9�@\�Z�p�CR1[
[�������vU���*�g7Mn���[9�����m����{���a�����m���.���n�0;��Z_��S������`�{�VkNZs�uv����Wc�0����W`}%a��$X1{X��Nq_%�:���#�@\������;/�9��cs�u���k!9��K	=4�1���I�V���!��g���G=|���k���`�Q`S�z��X�/V�X��\�],�:������@\�����=�������i�kF�S�����"�W����6�P�yH��x��o��+.������_���;y���7����8�[�O#��-�w��,J��%^
��e���`W��o����,�+X��jXs��+XKg���Q�����g�E���o_�"!:rV�gAR��)��g;��P��6ZV��r�/f��r�U;�=r�����Cgi�\+�5���:n��������q�T��	������z�u������k;�<B
�������=�;��1�����u�V�V���c�q����0���C������)Je��\Y����5<G�uDOl����(��\
\u]���v�fi��i��6y����8��&�M6o�L


t�a��L}l7h�A+������{�X��z��X����q
�:X�=��U�&[O�m����P'C��g�k��mc/4���������^a�7{���\���}t�o:�5K��#����o��[m�pps��V�L�8��C^z�Y��X����K�����������k/j��JXW�������b������{��E����S��������^�h�o�Q7;��r���g�=�2jm����xp��*������!��zn��
���uNy!!���������
�����J ��5���\�5��`G	��V`�5e���2$�n�k
��jA\_��J��}^X{Q�V��ZUo#;R$rQ����?X��'��R������ZFk�$P'0Z
 ���������!��U���O?���������X��Cs\��������og��_�3�K^�WY�������_�m���Z���^d��V�4��/��+^��K�r���9���p��^����*��T9��U����8=�{�F�H���z=E��X��W@��
D�e��<�2xk��z>p1�k�vh�<��e���/C#�9Ox��9�����>�g����i�{i_3���+Z���~	}�9�}n�m�t��/.�fT���Z����kk�0��T�`]���}^X{U�W����pO%
���j�h�J4�=�
�q*��
D�%�x�C]���yt]y�:�x���V��U���� �>�@i�{����5�#p�hj3L����v�^@|��W2����fV�����a�58c�N��
�v�_��{.{���B�`]�����k�J��jXW����@����@������)*-���F�
�U �`-O�jn�%9�Y�T�F?X�\m�P-�<�����������9�#�k-��z��q.�����������\�i�B����l����A����$om��+;9���b���/u,$o��b����c�}sX��(��X�$$SR�5HP
���-n��;�T=�X�{������T�8�u)���%[�����z�(3k��va�D����}���v���a�D^C�ez�s}�:f��g5��H���vz�����24C������z���Z�������\�x�3�tf�oP-�X��L�X� z
�X���!m9�`m��E��q�E�I
����ia�
�89N���E��X*w�����}O���o��[*���}�
$�P����V��CH�{���cG���:��km�J��Ws�+�X��%W��*k�V��9�0/����a�*F�kS���T[�l���3���:��u���R�t��,�c�����s�5�5)���J�����l,�:�k�\��������bg����w��"����Ku�DP���<�([k��Ik[���G��/���qR5��NJ�L�K�~��9��%K�='a�*z*w*���L(?���jol��_�����M��n����U�����
c�{�r��|��~�s~�����&j�W�d���z��:_=��~��z�2U����k'�/&�_	Y(�:!���6�7P�������-�9m�H��z����H������������V�S �`ml��gO�a�\-\�a��n7{�U�6����l��1�z� �Q���zw�g��g��X�`�������k9<K7O).�v������{���W��o]f������8\#z
��g�$�`�D�FsOkov�;s�`t���m��\
�N�-���3X���9<Z+�%�<%����Y�@k%�5G�9�X3�NO��ps+.{ci��JM��X�O0V?/��[�(~.P�({���w/���C���S]n�qk����4/�~^;���O�X�4��������lI���?x������3\	�*X4o�*��p[�y��J�Y�U�GX�
��M�����b|��E
#W���}E�n�C��8�������2>O�#�-��N:��T�\��B�wu��]�\�����WRh���S��Z�������������+������_=�4{�8A)�v���BK��s������+�0t��x]	�������*E��c]�R�B�J�Z��r������V|�?�B��`�(���������,'c���_�����kN�~�>Y���:�x\}`��/�����k9��f{���}����0�.�����
��<.�KZ�Y� d����z���)����x����!(����������q�������o�q�,]|rCM��x[i��XG�XML�XK��k�3=Z��#-���������W�P��RyLW�Z�����ik�W�^����?G�>��Vl�"-�k�������/;�`-�����������Vu�W5<����
����W3�R`���� T�����9���v���R��Hr���4��22���3\
l�X;�2���/�-�G��V�IYs�u~V�X�V��,n�����3���2T�G(�`}��n��|w�K�TV�-O�}�\�NZl}���1���
��T~�qf#^�Ts jx/�������
�q�R`����`�n�c�>)5���Q���R�k����^��N�B(��6�5��v+c����%��E
�?w{�����o��=��#�����[#�
�#o�D,`�3�b�X�)��X����@�X��R�Ym���R�S���O
4d�r�o�`��v���i����[+
�K�)%����]t��-=�K����Je��.�u���s>�u:����a���9���9v\����k�h�57F���c����s$��Z�.��Z�VTJhs�,�nsA3%�Z�S+p��Y�s_�N���\���
XK�E[m�������������V�um���U�8	A)�J�t��N���{������VVZKZG�mP
KH�yv*9�2���W�m��~=����Fk�
?;:�-����[���1�u����C/��&�J���ym�)�V_�H��k�_��=5��������yFc���S<�w��k� w�R�t��N����=�:(�1O����j����8�p�����h���~��~.��E������vz�esK����������{z���fc��7&T�?+��ra��
mf�����-������ia���>����
����Bw��
\��/��]�1�:V�����a\v������N�u����GD���Z� �7����z���&����V["�5�Y�s��m@V�g�vB=��Wi��y[/��f����'r���g��R���h��zAM��C8�U IDAT9^��@�>W�L��U��?�h��<]qv���N��5X��%�A�{���������eM�0�t!bAM(�w?��&:{tz��s������V�u|m����f�x�`O�a�S h���[���ZEo���j���Rzh�[�c��W�W<��_\<�J�o����������������q��z_��6��5���l��&j�����M�-�VK�Vl�!������,�yY����x�j��al�V
�UJkI�x\}�>�X��k�� X�2��8A(�Be��x�k���Y*����0�f����h���>��7x���M��}]I��u�s�3�����\���{�~.IO�����[��~����z�xE�~��.�N@�X�\��"�~W���o�����b�t�Y�s`��}=�78K��C(��CD�XG�	_�:�����2F���N�q����o\�Ik6K��bO��J�Y�/����~���{~SQ�2��\�
��[;�+���;������-���+a�'r���Sn����Zm���}��{2t�~ZpI�����Z��7~�I���*���N���6m�����1����
Yj�R_������������X��j��nX�Q	�������r
��)��C
	���j�M��g�*3���J��-p+�T^��y*-����.��u�B�������!Y�3i2~U;��n��v��E�~E������aY�����w�_��[��>tp�&rhzG��z"W��4`���FJ�^mS�L��K�)����
������c�C�u<��U��n���`[�y��8[k��A��S���3*�a�gn���o�RGW��7C8v��nOf�
J��[��a��</��������/;��n}�8��.�\3�m�t��/I7X�^�yt]y�^}\�Z<��G]]�����������o�xgI�r���*���
�?��z~��M��;}��&�O����|.�r�i������=�Z</�Z�}m����`��Fg��k��`X�3fI�A��Hi�2��q��T��J��*n;�"���6�i��>��zz���B����;���W|���9��+B����i�u|u7�z�P<K��&�������_�g����]i/�y=�{����U�X����aq5[��hl�R�L���xY�T/���Gu��/��8��:��y��F����*X��R�^'�:������������V�u|m��GH���Z�.a��
���9G@������Z��?Eo
-��������aij���=[r�V\��Y%8���~��v�'{-�6K�p�r`%����+60`�r}yMY��t��Yo�5O���A[��}K��:o^�z�U�'���
���;�I���n���
�������9���Z����V�?_3�������i]#�:��v��`�N�l�4[?�����3%X�0�����+���a�pAm���P^�z���!\��w�87�ZK���<]7i��l����<�4fh����-���"mv��/8���?�Sh�U�����O���Z��Z�4ow����`��J���9��������	cc���{���������n>��`C$|��8B�XG�	^
�:�����S �`��;�����Bg���Pv2�����������Y��-�ji�$���Yj�+���'��_�����']B��ZW��
�570�S�UK�1������+��z�F��Z4(��,o� ������-�����2�k���X+v^}��m�F�v���@(P�5��Q`�c�� T��W �`-m���h��"�2�1O���R�T�g{���y.`���~����)�r��Y�=����Z�'R�z���e���?tq��������Wn���=[{} k_yyK�<��k�H^RH>��AYN/��G��������y�����%{������N�Y#�)�u�L���k�Hm`)s`1qU j`-�9}q��R��������}(��������-�|Y��C���7����ou�e}.O���s4�/ec����J����S�8���#Cw����I^R��B]�,���
��[�?�5X����8��z��v�W{��
���k����X�d��:(��=�:����}R j`mT�S+�����Xl����kw�S[�x�U0�p���_��FZ����?��u��+G?�l]��v���Vo������������pn�S�(;��W7���"O=��Z��_������o������~��9O]������k��Z�;5�_�k�P=��K?s��*������r�u������m���`Ka��V �`m���ZT|�&�Z<��Oo�����V���u��-6���8���_�sl�vO��s���C��Qg�D~��9%4���{i��^������������Y��3�
�M[��}�5��y��pU	���*�y}�P���&���CX��^kk4�\��/Q�}�y���c�]�u�-����a�$�`�+F���+��Qk�j��]go�Y���uv��ol��c��sk��c]7����s�M��
P�8e29�^����g�[�p~���O�e������s�.�<���Z*^��|�N���!�v������w�(��.���;,���J��VP��)��1�Zl��s'��/x~���D�uh��jb�u���f��������156ZK��]���v*cK%�+�i2���k5��
����?qB����673���6.0����N���k^�P�{S�m���J���K�.)�������k:�e��i��4y��l"/o��hCJ����H����2�;XG�:�Z�:Y���n�Q��+�����i�*�v9��"g�NY&��P�S�n[�x�7n3�XA�2Y�8��
^h�3t8���x��U�����S�S�\>�����n�W7F�n����d&����Y��+���
�c�dD+��;�u���^�/#.����{�X��z��X���a�8)`-�y����#O'������1g����������/�^����+_��z��zh����9[`���|�rn]��]��!�;�S��s�������*=���M�t��-��u'm�����n���!�Y��eK��Pf�0��K������+���Pve��]���>�H�����%���u)}������w��%'������o��l��w��~����I��(j`5�$s=�d�5��JX�EZ#���}���N�����)5��0�I�o�������;��z���j�-������C��=��Q���q[�,s`6����V-��\Z�S��7���3TN���2�
n?�"�W�1\��|�}v�����o��V��h���<}v���}
��wO��k�r�i�o�'��f�������.�%�������*�������0P�`��X��#\�;�<�I����S����bX�2�X��@��)�n��f�cu������!��x+5����6����m�d�U�E��o0V��hWCL��ZJ��}�
mE���Uj���ojNtK&j�'���:K�s���_B����*d[}�vm��5���RtK��2t�������[�3�Z<������zx-��lN����P�^�x���>�R����Q�`m)����9X����m���Y,���+X����k;�/���}�.	��j|OBmW����xzJ�X��e	}vV�6����+Cg-���kMt.������s�5/�������
a����r�5@7�(Ps��y���?M����+�[����zn.�v��,�6�����9���&{�s��
�i��5����El�zs7��?%�M��hM'��E�
���l�7v������|q�k���vhR(m�.�t��,��y������#X��v2j���� m����I�*��Qki/5g��m#������<kiI��!�A���-�7����r����t�@��r-�gyr�\��%4�0t�PaZ��v6�������Pp�e��%�����\��[/�����	pI����r���g�u��C��n��:y���;�����M1��������W�������}�����`V�/�*�k!�a����T��vn��A���g�Q�;IE9��:�:Ai�y�W`���x��qk����U�����7��Q`C`�V ��/��?���j�M^�f#�������^f���/�_<�C��i.��=D��G����|��6v�#i���>�
��Z�ig�����1��}0u���jy�	�� ���������';Wu.����O�9^�F�/�irc�O�`-gAr��s�0��%V��g���rC7���^��8����`z��B�Q���R�l�����yi�uW��Z�����z��.EW���{�����q���f��.�>x��k����F���nY��{�>��sX�?�(�v����Q��K�k�/���dv?7z�g��H]g����n����=��^���`�bg��h�,���*�;�����������v�~�5w��O��u+��\�����jp!��o����`��5��y�w���������y�
.����Wzi�K�q��R]���5Gu�bf�����%���yX�]��9���?v_�����mW�JK��y���������������e�S��	ky2�}6�:X��<[���X(?#�E9��:���u��)���I��8*$X����8�Yz���g�a��7��B������_���[�oL�C���u����
�ogO�x|�s�U��6T2�C���1Db���WW����='O{4g�g�i�\�c�f�WK�"�����{��M�����2	���!.�14�o~��c�����|��0�M���N/f�5����z��c-}��@��|,V����xa�CehW��L�KN�}����A��QC;O�1���%,[4�!/h$'�:���wVu�_��?�C��9F���������/����#�m���e�,�*;A����g"(�����7�o�2��{�-��������y�q��I�k
���(n�cv9��Y�p~��]��[\)��#�����Y�Sq��8��#��)aFF(T���A%��Xi[�e���a����#��
�����6^��V���y������-�$��)���S�g�/�L+�~���_t��T��{�[C����Q
����[�Y�dk��5�_\<�2�<|��h�Q������'����)*6��_�!��.�?[��)JF����Wr�o�C����_F+���_,��K7=���a^�"5&��/�E�Z�uT-��u������A��h�Q�u4��U�L?�Z i�Rck(5wZZ]�����;��~v>`�X��.���^|�8��:	�Z�8�14K�^e���n�Z�g��N��o�U�������]��+S�Z�m�b_�����������rO�g6�<�����|��Qr�l8��S�c��>��i��g�;�^���6���Z>f�P�[����rH9�j�2�q)4c�]��6�9��z�q����J�{��vu>xd�6l�-|���k$�a>��>�Oa�W�u|m�����
M�8��I^/�:����S��v��	XKH�c����l�}����A�@�'~�Fm](����?�����N����p�/�2��"���4q������r�xR���F��v_����W������-�n��G8���������;��ik�7��~�]�y���~"?��`���K����t�;��`>������i]��PqR
�4�g8*Amg%g4���/�w�c����j�r]��n�����F�x�v�UOWsT�����H������Q�u��X��~���+X;>���Z��tY2��XG�>X]L��� ��=3�������_��Owq���G���{���/t�~u������}i�������P������[jh����Z�H+�I/g�����p��(=�����{��N5$�E����YL�Y��F��9��x���T�.� 
��v�|yQ�lf�����]rk;us�9��z[���Z_}�������_��uV�`Mu-���*,+�6+4�����_��1�B����((�=�:h��;_\�Z��I�Nc^*F���k�,F
����1��Q������������m|�5R���s%p���K���N���k����M[�����Z)(R"7���R`�h��,}�C��a���k����BO���=����Bp�����t}ho��`m�RD^���WG-'�9��z��������+�����ZM���/<������W�3���y�������_N�����I=/��Ay:���6���:��J��������<:�[s���J,t��Ov�s��!Yz}W�^z]�=`�<t�<��`q^G-��G��^	�:������
���D����5,����Px��t��kXG�6XY�����p��A�Te�g��]��\��v����j���N�4)@4lPVi���N[���+_} .vI��*,�+�W�a�Sj�F����C5<�>�T��n��Q]7(��o5\zg����*��Q�#6ea+�c�*����z���W���1��/���W����s��������@+�S���M�+��������r����i_�#*g���v���zM�F�T5��#��4yQ�=�B/���
.�5)�(C�]��`�k���\%?�:f/�K�G��bO����5 �.9�RI\}��k������h(������8�u���=��bI�#T�k����xc>����~�S���;�X�yy��y=���K����wg�����5SrJ5R��m��Pcy�V�����[��
��Pq�I��v�@����|�pCa��>��s��6��E��l.]�����P��Y��Z��r�����
���=jv�<	^<m��^K�v[f�tFXGCvW���a-i?�4���h+���\��m����dO7�-w�S�G���i�����X�K�Y{�V�\�X����?�{1%�����Sd��\Z��52$W��yv�_\��ptO���4Z=�=���3&P���N�r-~�������\�I�i��<Mc�N�����6W����r��D
���V�WqO�W������'Y�E-��Vs��!��������_������\�f����M�i7������!�.���M+����c�]O��\���������G_���::e���/p&3�Z=��s���=��Y�al�^x�`�c���j1;7C�$p*lU�<w�d6W�7z8k	�n���5��Z�������`�_�v���e���4��-0|=GS��������1�+~�{�&+ng���X�R]<����!�A��9�@-�Z�O�����zk^)`��O2,���F:��m���Z5A%��r�5g[
�� XChN@V*����������?������^���0k�G��J�����[�i�]\�m�Y�����O���~�����e�4����a��|�m��������T���T>0���*���}{��C���`����p
�������a4��6��r���X~�w�v�&Wk��}Ij�x8G
�������[���X\L
�q �R`����`�n�c�>)Pk���!�;��=���M)d7�V��_�D7��U�d�=st�%<���*TJ���������h�[�q��vp+0}8A��G������/�p���?p�,�vD���B[�>�e���oV^H\��9�~��\�p��r���m����^���8����9N����h���#�g���?����x�%����E���������y2$�^�s���Ns�����y�@6��>���~��Z��K�s7����Sw���d9[
uFq�2�C���d({n���{}~-����s'�Oj^z-���g��n���`[$y%�$[{L���������b+�}��,�x�s~�|�_�P'�f�k�B��B+!%�h�|���Dow���I��_����i���
��oPr�����)�sx=��8�W��1\�u�5�`������*�&l��
�
d~��m�)-�l����l���4�9��O[z��w��o%�Y��,�6��Q IDAT���R
��
	i��)�U}����
�����_s��<W��O�qk+6��2�������,�6M��e���Nz�������j�����t������R��j�^�jw���[z��?w+��2F���;�}Uy����5���x��O�v3k��Z�?{��Y@R��7��"UZ�2y�����9pMx
���>m3��f�p��Gw��0��zN����T���L/
F��P���R���O���H�����4�>��:�~�����F���_���6��8��Z����{����.z��c�G|��:����������m��Cge8�[��G��.�|���D��>s\�#\N�����Z�n��euV1������^���w�����^��n=���)�x{���Z��F.�����
�:2�@���]��?�}ut9�N��9#2����Zd��p����
�X�R`���u��w]J��N�#^��{���������c*����EEwy�a��u����;�1���c�oO)�`]�����k�J��jXW����k��/��R�l�i��������).UA�d��"���Z��v�j�n�x?Br��C�p���e�3����mqX��3�;k��������K�����xK�������V�v~QP�dO��6U�e����Riw�d���b=*�*�����D�$��=�?4��fq���a���G��{���&����/T^>H/a�s�!�[�O)���������������:��>yO`��������q�,����.;Y�m���^*�[����K
�^��_�H������-o]��~�!���>�V^Ie|5j��x[%�A����E��go��}4|�����n��<9�N��(�.i��Z@sw6�ir3G!y�`��`���������Y�i�8�[�k	���x���S
���;g�������a���s^�RK����X�_��<xN���J����Zx�v��W
7�C��B����.G�M5�������:l��&����U[��[����������� �r�����<��y1���^��&� ��:����l)���V�������o��y��P�r!lV)&g,6W�#��JS&���Y46��R�!p����-/6�wV�!�r��5�
��6��������j1-h�]���C�w�8��:z��>����3�w�_������������5.���T��������bqs+:��Rm�}�Vw�W����������X�/XG���N�����\I#�}��~�)B��c�.�te]&��XbFL�
�q�P`���#�
����t��n��
�(�e���/\���,�q��kw�QuE�k��!��Xj���o��I?%hC��~/������!�Z�(��'�=�R�j�W����I�2�.���`vC�C��V����g=}����_��]�6j@g����`����l�Z��HJ?nC+0��)'5*���*���s�}�������y��������?5g��6��c�n%������F[�������c=��
t,G8H��'�7����v���3�yn�s�<�5��S�=N`=�+��F�z( [|~������U�(�����������'r����x��q^�)Eq%�W������p������^�Z
�6�H��l��%
b��:���S��X���95�M8�1
A^@����������E��_���~�Jm`�c��ck�X-`+sa�QU����{%������\i���j�{�J�j�(AUg
2����������B[-�7V��xD��e/�o�V��I*u�fcM����o)o�/���/��3`�o���f��xe��P�D.y��^z�W���Q
t�~�d���?wq�6������\��7�B�jhW����WY{y����K����������T�q��}3\k���g��<���w~1��������~��&��/9B�����Y=��'c��7&���������K]3�o��`vQ����nz��������H5�Pk�<��G�r�~��.\����Yn������������Y���z���D),�6p��YoH'��U%����y�Hk�9�����s��������G��G��h{��#�@����n�R�k����'������q�J�������vt�+_j��ZY��*���B�u*c��+P-X;��2���k�Zk�f�{>��~�t7m{UC�%���������TP��SZ�_��o�R�L�Q=�����a���e���z����������{5��W�,�t�9���`�%ik���J����Kv9�x���Pi�rK���k��U�����?�y��^r��������p����2�~����r}����r�0x;x��.�������F��P�Q��r�����O�rf�,���!^������Q=�]������e�5��+ws%z�w?���}������y����|b�Q�R������N�"}��F�$��s@��T�Pg��Y�g<�|���o>Q���sN�x���p
��
N%.��TuM���������~�s0�]]����~�Mc�.N\j�sh��^a=����j�-���<x�����^���>p�:_�7d�]���
��n,��y��A�����a/��U1p�y�c%�C�6�����c&r�����8+
�(�J��������3j�
�LV:L����&�}��1�A����J��D��yE�_��I�P��u���{V�j#��q�gk���[���?���@�muR@��Q	�~����Ju}���$W���G�$b����M����+e�������=x+��[h���&�:�����7�{q����V�X
���9=�T���^�h��l�����=Ss$���V�Vn��>���.����=K��z��4#�K���P�,�zq4O�rC�9��f�c���B`�fp��	��^0�%jC�����@�@�K�WU5�������5���d�M[�w-������o���<��f$�C��W&���y���� ��}���E�x������w�����c�d�$W��)����^4m��=�����
���JY��~�v�:=�c]�G�L�c�LR�5�d��/*�RX�z�,��;���Ia��k��PX'a�9��(TXg�X���M�5�7��|�|i0~��hq�VX���,��D���W������Z��m�pW(!�,��q�����!n<�qYv�2\���[	.���F�y�^xGY'Q��!���L��
I������\}p#��x�q��v�H����V�^���\��}�~ur��p�V��}?&�r_$�)O��-x/���Wo�ks��Ow�������/������������9g�V'��~K
\���Q�{g���{n���s��j�����������d�4�x���Z��g�'�L�o�p#>��g^N�M����hK�-1h��CX?��\���+�\���q�Y�}�m�Y����	�G&4����<�5�{�)�N8~�Q������^P!�����,�����IMe�,Vx��*�Z���3��{�
����:���L��"`P�`������
U��\~�������R�<:��-%�k��7^��(�K��W���. �"�$�au�� ���0k�u���?K��c��\6�rLFXEX��H���fo)qkK&�O=��l����N"a%����i��%����4�q���F����2�r�Y��qON	~6���
=���������yA�Mg3|�:�Z����&��f������-(Zk��VA�c�����.�������b���+��b�������&����MJX�X�0�h���1���������[�,��c����*~��Y��W�9��c�s�Q8����.�Ro���j�-��q�Gv���#�j;�=.{"��P��[����>qZ'��qAJT�a�Rz�������J|E�{������Y���D��@�������@ZS
�-�u�~�B���'Z(����:
�r]Y��M	�5D�y*6p�����Q����,��������e� ��y~�4xBC]1k]l�����{�_��U�����IM���KR.��Gc�Rq�y�������	Nb/�hN��,+t��u~�J&�Jv9
�Mx�'he�����*sr>
�~���8M�E����$�L|.\�������>#��;=!�?^�M.���;v�k�m�����y**�oE6���{6�������YH�)���ac�m��7�+!�C��.�r�a��Y�q�����}�`�c�g��Ur���K�������������P\�l�.��x_�[��-j����+����	;6��v<N�b��a�i��@}�ZX[�m���]�<[�,����iMr���������T�y�L�����N�RIQ�
�����:�KJ��_#�c),)��f�{���Bl3�vd���:S����H��)�yRX���FoN��[�(���b`����;Hz�<e�g�J�l�����/�{L�_��A�m�V���1a-�#Z�u�I����`�*o����_hi�q"�R)(�t��'�!�x�V����<9��I��-e�����=��p�
��/�re�K>�=�D��e�y/t�5�MU���VH��c��P��^/p�������{-x^�k������^����}9�B����{]��g��+x���g��_�t�n��ykcbj/��C��)������,0}�fA)�*�~��4�,���Z�}V{g���jq(����E���
�1/U:�db������m�u������Y��Vg����
�s��~@��3%)�1�
�V���������H
y�����"�&j���Oy�Ga�
T����.�E���(�#�(R�x�5��M:�r�z��_=T��w�VZ����3W�M�/��&.��aV����Rg����1,�Fd�3�S:�(3���;t�r�[������������s���}���G���5h��?�Y-R��W��>z����V��Q���y�_�J�!�F�]7\��w�^/����	.W/S2?���<e�s>F�3�0���t����?�~p�[�r7|������2�������7n-m�����s0e�T��Z�����U-E�������*S�Z�$�IC:TV�/��Vq�������P��g^����^�!��.�|b�-9���U�F*��/|�����X����O<F��g��MoZGn{]Rn����%,x������x�X/o=�s������S���o[(Sf�����)�����
f�w���^��-�j�����F�Jy��b�IX��^��:S2�|�ZN{#�s��N�����)���9�X����Y�P}�sa�vDYi������������Y�.���	�:�[}���J����R��Z��mY4k������\?���{T)QU%�'�*�
yPX��$eA����Sm�tT��:����V��I����7-T0c6��B����.���2Y-���*�|�Y���V�=y������&s�u�A���f���aj=L�!��}�0���8�V<p"�`)���J�Go����b��d�:N����)�fV@�.��_���6��t��Z$��i����}�UwS!��]�_�F&z����/��O�jk`��r�r������������~��/�n�X�C�����0�
���B��N��2G��p�������
{�S�x�v.~�T���>����'���wy�A�q����!>����9��ab�5y1�BXc��k��O�����'�k<��E>Y���N�zs�%"�����D�{5wC�����&r�c���&^��'{����������/\��K^m�2S��(�����5�f��[��R}���F�9���4v��0�2��YY��m��-]��h��O�]��W�������G���@fQoy����4���-2��VP��Y����[��&�6�]�y^��i�.�OX���K�9����L�N���D�c��U2mv�!���2�,��3�<�X>����m�r��_�R�^������Qg~Y�8���i^�g��1blW>���^o�*��+�5�:�����5*�wu� F���>h��-PVz5���Q�X�/�U�-!SR$_�
�������^[���\k����j�����g��xK��@3����U��<�/�V_�pj��2�2<��D��>��� >a����������� [�����}������<�ZSi"�9��h��������(��mE9�v!��W*�8-v���v���VN���D�k�q�[�{1j��%C�uSI{P�,��2O	����#n]$Sg�XDc_F<1\f4)�X��E��tCI%m��?��~�al�/
��y��8��T��og4�����V�("��G�>7b�J��il
��~�t�Y��bob7����Z�y�dfA$���
]���&��7V�o�
^	V�e���2ct��cvv�)�m���T�����������_K��U���k����K�-Q�����e��3+	��M������d[�Z���b4�6<9���;�8Z�Z#������R/RLxc)��&
��ZAo��Ui7��c������5G�(���z��Ia��5��K@�+�a}��H�`�*c�\�W��q�RON�����{�m*cvP�L�u5�r��*��z�n:���q�[���3��!e�x���u�>���
"?����&h�$����l�yK�A@{�B_�2��
Go���:�Uq-U����<sq���o�?�9������!l��8R�����k��[�s�|�*���z�l��y�a�r<����U���l��=��;�����+�3Yy?��3���-HX�5Z�V�(�64O�P����:�5���GQ��-��5>�%��Ga}T��YK�KX�����X~#��^�������~���6���2�s���c��6J�QXGi5�{,����Q��uTV���5�����%r��������c�^�r��&�5�yp���g����v��k���o�5�Y�e���Rg"���;�1*y���9�����������z����V�[��0�q�tW��w��FvTq���q�b�f&���np��6b�$4K��;x�u��XU���QJ:�����*��!c�z����L�)Am�8����/BD�VI���k��;g�L�������$}{����e��q����dV������5���nz��n��=y������-�������w����y����������:*��M���J���Y��F��]�o�N�n���}�A���Z�3����E�W2���:���1SX�s��6j
����I�r[���\��VI;�~��y���DC-P�|��2�����j�U}u�V�nt����9�����jS[+�#��_��C��a��Lg��o�e�\�������B��Z)��T+��&��?T��T;����������%��3���.�3�4m�Z�;�TJg�v?�7[@<��<�E�����r��B�B��^�b��7�qpc���!��}'���.TX�{��3��!�/�+���_X�=��f=�_��^)��0�����uy�J��DO�����E�;����P2
�����RX�

Q�9/�z��T�b����zw�}����-�&��Z�y��q^�x���:^���RX�u�8�H�
k�����l��A�;�f�������)��������,��-�����e6�b!R��K%�SVp������f>��Ft�����<�o�:m\��lJg��\a��^�f;>�n�b�����g���XY��kj������[_+����$W�*O���as
=��s��U�u����hn~�Z*W�L%r����Y����S!�i����:�����p�\�NE���IhKa�M�fiv�g�=�Z��++�/h�u��%JK����|��K�����-PX�e^��	����-�7���3h������*[s��X{�e���+z���.V�A6���fph���n��=��6nb����vD�vg�����+#��)���ZIs�4O}� �}Z�,��R�,�
*�b0a=��\���Bft���N6������B~_�,+(++2G�3�P���fb9�9z��&o�f�=H�����H{VN��3���
2(�b�X�=�	 v.��z6�{c�Uk���n�>�g�����/p��U����n�k���C����k���'�_VP�kk�+���Xue���FNL
� IDAT�6�V#�5[tPXGg-�}$�������u4����9����j�<����vEk��t�$��V��N3��i�4���h�5���+^��*�o��g�x���[��[��F�B����_���y��Lq�U���\��e��;�eMn����Y�J�W���{���vmX������?�����i�Z9cW��C�����C}8�O�r����\��?��IN���zkr��+���Q���#�VX#�z����XmI��Z��|��!r�*
���#�{������(�����;Q�l����B��b�a[
�0�����:*s���(���i�("j/Nu���u����FGa]N���PXGwm8�
k�}o�/��%md�O����C�w�#*��*�
Y�{r'�V���X]�Q�+����W�	�_x[qi������7�m��l��4Hx]�C\�+�g/���|�q�=�X�$��["���G����y�E�[��ZcT��L������^:��oR+��.�[����F���ze!Gmo�
���R�*���
���������i&A^s�g���X�����:�f�:��O�;xK�����@[
k���.S�����|'�~?.Q����8cU3����;,���lB�`��qG�X�i������������(��i5�;
���
G#Aa���y�B�P�V2���}�V5:��?6�W�n��V���5�$�L�����������k>S���x�j9����kU6}�]�3S�I����+�X���Z����p��7���{�����xI��l�^�Q^}�*S�<0C��[e~t��
n��>_�y���g?�X�*Wq������g�u����l�}����
�a|x�����1�\��/^��k�anh9[�[Ynk���,yf��=���Nr�����t��{0�rK+��s���%S#��w��F>��Q[���Ub0����J��hka��z�}�������RW^�_����uy�kgEa�U)�1QX���rF�@ (�M���Tr*[����J/y�uW��$\��-nVuZ��lz�A>��QU���i�0���^�9��a��O))+z�y]�m���x�����rd��k�3���������s���
��ffF�g��
��}�J�k���%���z���Mk]D����{K�G��������KL����>X
������nY����z�r�J���%S�'Z������8��;��Z�����5
&y[s���zT�������.����
�x�W�GKa�����)���Vi�	���W/T�p��9�M�+�D���m���z�����:���
,X��M6.%���c�_�l��2����H��n+��Y����xl��������m�:H���\�_��$5c_�w�:o��������$4�^�@2���V�L������W���&��a����)�0m��~��F9�a�<��`�\6��.	�c�_��

�����Pu����v�?�$j�K����b������/J1y
�RPe�A��mE����H'�:��^��H��������)�i���]��->�{�/�l�t:�:�%1�����er�6vl_�)>�w�00I�+y���kE�^����_Pl���Qe�~q"b���y3���{2�>^Y��Vb����9�_'���V"&����A0Z��-�+uk�5�7��F���E��/�]��>aH�l����q���pYF��WsuQ/��Q$�Iw���� �G����~_�����l�����:*+Q����.�����(����;
��][��
	x��`�i�];��5V�U{U����%w�������t��j����)��xc�="����^���*�_�{-������^k�.��X��"�/�T���Z�OSv{������Yt����X#K�������s�ez�m��&7�9.4}��>�0��5�����|��c
�l%���6S��?�����~��'F:M��zR-
k��
����k��5�A[��n��F��
�A��s-�m��A`$����w�o$:Z�g��?��`I�q��n���dd������eq�t����
�)Kt���/��v���/��B��7i���R����}7y�?���8�+U9�����	��;c]e�
9w�:������&�}������QuR��U/2ZJ"���&�X��#v�a��a��
�e��.�^��u-������}��v�cS��������Y�|�u��xD�(�g�r#@a�'U
����l���u��6k�������x�6��]U��!a��-�d&�r���Zm�������F��Vp|�Bz�.�=���z����	n��}��ZL@T��{�����+�#UY�>�*e�J�5�)���$Fh:Ai�#���T�u� ���P~�]Y}�Bc��m�u|mN����$�k�%�:����6c�����PX��\���{�����O1N��N�}.�
n���+V�v�T��g��C64		��(���B�1>
��X�8���:��1RX�
9��k�
���z��Mm��_h�|��@�,
�g;�p�n�����M����������������m������U��Rba�����;�,V0�"9��[�TW6�����T"-����������xhk6�����P�A�������)�U/s��q���?=Xy����1�-����o�J�����d����������_����n�%�o���XF���&�Ry�jOW�����6V���}�Z��Ja��o��RX��$]��:I������?�z��FD�U��.�5�5+��
��9����8YWj-kE��5ha�$��YKs�E[���Q�k�������R�3��:�Tj��m����Z+S�y{���yM�2Q�A�y���B�|��b��[�rF��Y3���X�M���*%`����q��������Tl��fJ��������^,�|��4�/�K��
���@���:'+x!������'�������B`������BC�</�`�8�������g���Y�����:�+��SX�c�8������g_��[�����*�=��K(��V�*�B:����\�m�MY�}��|��u��X�k�gk�G{���@Ow}�1�����U���2{�;�nE����^��X����p�Z.��[�� �O�P��F�4����Bz���;��`�H�e���������Q��,��r����tU�{���r���	�P?�6x#\sp�q����s�O��:�kT#��.�U��(���Nq%�u�W������]	ko6k7�������6RRY��bkr��^E���n�l#mPh9g�S��uL�}��KK��nLu�U��\����Gz�N�/�LYwW�U%����i��	K���/��
F�����y�r3w]�����{��z�>�r�J���YK$�P���N)a���G�8���Y�Ju�T!���c�����������K���L����@�](
kn��"@a�V��}
�d�?g_$��ep�6n��+��Nz�c��>7�^c��
���Y�3����lO��:]��T,����[c�����d7����v����<[�m���%?�"�$��^�@~S��l��`�_���#]����D�y��R���QY�o;�cb\����xr����q%����]�J6�[)�~����T�E��c7%"@a]"���G�����PX��d_��:������WXT	��H����ck���b�>�����:��=�~��F��)�l�=�����$^���I0��X��������AaK��W+F������i���S�}�+K��YM���Ur�����\�m&��Cn^(?�����2���t��_D�2Cv�1G���Xl�Oq	PX�'{'@a���V(���t��Ca������D ���&m����l���^��6m�t�l�XlmY����9��N����g�Y�����&"\�
kvb��T]k���T�����
����:sDx��@i����|����,���-�
�O�K;��2#�j�b���xD9��.�U��(���F�2B
�rY�h���:�������_X�3b�c�N�=�9A|����e�p��:�2j�L?��UHw��j�|.�mg��}���n����2[gtS��M�w�*��#K�������?�X���|7\YeW���\�k_�����o(��7�Dr��F�a�������q-�C��:9k��3��nO���6�u����fKa�^�y��"t��L9�;����Qq�Wnk�n���O��+��RB9M�����;����u�m�.��jZ��8��P%�L3.�zi�����������6-�K{��}�#�����,�t�l�ful������?"a��\��by�#U
1� �S���FM�
W��K����	�ZO�g���u)��oK���{��PX��d_��:���������;�&��p,��Z��>5�0�9���AWn'F��&�X��S�"�u�B)e%�����T�������������B>����U!���;��H���������V�$���k�<6�>5����^��fy��.���_6�����������h%�5u��&]�z��(��rYF���W�LL�2@�WX��O�6�u/����M��������P��u��t(�n(��pQ#8%
�.J����L6b������p8�$��u��"�7�0�������t������w#n�����~�m3�{���i�85��7YY����:����L�Yo��������n���t-�i#�]���g�<��Zu���R��96�{����J����R���Q^��Af��\�/�QU�:{��g9^.v��FX�n�p$PXGb�~�e���� �ud���Ba]�����-���\���l���R��km��>�l��"7x��������)��}��!�����f������V%�~�LW�^�T���9��������U����Z�m;^1�)ye������(���]{h'������g>Q���:	���zvp�;�<5"w���X�z�uTW���Ea]~k�QXGqU�sL����Q��u�V���%��y\ft�����I���G��[�I�D\��q#Z����%����g�K�kC�O��m��[����U���,��hR.�"�O\5��%��;�t[�q�}�y��+����B�[�R��!gWc\������{��I�Na��C,Ma�e���)�c�d�0�ul�.V����rq�� ��O?����+/������o�������#e���kU�F.���YR�Q���l}������BL��[���IK��MP���^c��5R�������Y��j���-|��5r�V�kD��N��}}���0m��C�Hmu����Y�^K�t���k,[�3L_��b����ey����g��@�F���6n��Z^��Gv��+�Fa]�+��QXGg-�y$�������u���\GCa]�+�y��3g�l��2u�T9���k��������se��q2p��������ZX�2[���^k:�[w���"�q����y,����a2��`�4g�V���a���r�_M�+W ���?�g�����INQ�����?�Ve'���L��Z��-J��rQX����ZI�����xZ^(����� @a]<��3
��Q��r 0b����k��G��C��)Ad�j��W/�4i�rg�����U����E#�n��5�����(�X�%���
���R���!�M�l�Z�N,�[CqN�dI���v����U�1�/��2�IZ���.�����o�L���
���,��,��f����	���nu����KL�(
�r��c��X�����:�+��SX�g��<R
�8������Yf�ed��V�e����.�K/�T�x�
0`@����V����Je-5��]���v�����r#��@���[D����Y���h��{?��h�����
5�t����4[��CB�����E�`���q��]�����)3��w�dc���DF�����Z'�����FY�{�X�J��d�����%�QX'q��g����=iW��N����|)���}��La���N�\?��C�l����O�o��G���_�v�A����;/gRC�\(KMvlX�M����sX]q�uw���Z�����Z���Ns�6��^�FP�V�+����}�#���+������UJ\W�8i�YA��n��������M��,�g��|�C���_�.������7�s �u��x|k	PX������u>�xl!(���ss%@a�+){=��6L���Z9��S|��<y����r������cs������&g��l��dq��4:�%��Y������x���dd�/�sQ}]�RV�Y!?�nP�V"\�o���I��<c��I� rM�n��w�Vsmj��e�����}{W����WR-�9o�RXJ���J��:WR<������������m-
����y�#p�-��q�'w�y�>�7�Y�f��=��C�x����f�5��F���homg����2Y���Z[�����r������1�6S�J����61���8�u���&����2�t�.��2��2��^U�����i�k�'6h����m�t�����+�[�
�3�Y�[�Je�N��s���S��m��+}����PXs3�
��"���PX'{��r��mI;����N��'n�7�p��|��r�}������_�n����!C��^����E�d���K��;1����K>��fs�����
wno).��+�c�.�����a#����K�p�e��!M����)����{I,�z�"����������$���C�pI�,j���un���h��Z�2��TU6������I�S�u��V�;'�<(G�}��TWW�<l$PJ(E8c���:v�',�u�w���r�c,����"��J���Q����G�o��JA`����6�|s���g).Q�>+�e/��V����"0f�9��c��7\���Z��)�siS�L����JV���6�[���3���b��K[�2��$M�fHU��>3����_I��9���9_H��'����f�!RY�E��E��Ky3���     �"����������E\�$u��#�����+�\�t�I�����?\�������b�����t,"    (o}���W\16�����REk�'N��6�HN=�T]���^y�<x�\q�r�YgEk�
	�	�	�	�	�	��u��&�;����������2a���m��^{M��v�� �<I�H�H�H�H�J��:�_�i#+8��?��c��^{�.��t�M6�I���K�V1��>H�H�H�H�H�H �(���.���BD��9Sg��F��9s���/�(��<8H     (��u!�x�|���:�z��q���$o���9R��n;�!     �D��N�2s�$@$@$@$@$@$@�"@a]*���H�H�H�H�H�H (����$	�	�	�	�	�	�@�PX��,�%     H
�D,3'I$@$@$@$@$@$P*��"�~I�H�H�H�H�H�A��:��IN�0A�=�\������Bv�a��?�)+��r<&�Q������e�
6����_��s��k,Z�H���J���{����}��)��"G}t��?����c/������o����f,W�cK�������c�_���L�4I*++e��6�3�8#t��w�}������Wz��!p������;�]?
��
O,:�i���\ ������g����+'�x�><��)~}�K��G��c�=V~�a�g�}"w�����]��	������������w��?��O����y*��T>��������E#�������]�v�a������?y��e�e���>�H���S�k����������O���O;����������>*;������O�{�9���/�����S��3g�l��2u�T-�����������8�����|2Fz�W�9��#+������.��������	'��q�
7��'�,�������NzO����2h� � �m����X�x�����/�f�����
+� /���|��r�����5�E�>���x���F	1��z����a����S�|�4W��m	,\�P�t����!��m��Q�T���IDATz�������}*�c%Ia](A�_�m���M�8QV]uU��3�<#�����<�z��E�;�����^��c�'�����O?-�����t�I�����k�����|�����*��#F�5�\�E���C�g�x����W�bY�c�C��G��_k���o���,��Rz���O�M6�D���'�2�2����j�xN����Z},D��W_-��{�x����([���y��r�w����%Kd�-���?�X�L��������2��s��D
�(�����.�)�Y��t��7��.�L����J����}*�c]%
�B	���	@���_���x������f��1k�,���+�Z�  ��?�|�[Q��W_}5TX�������P���S�{��Wd���r�%��~`����J+�$�}���3/��Ry��7d��%;6��3��o�]�:�(��������M{����<�����
,�g�y�<��#���{�����K����Z[���plrV13��/l��m#G���.�(���p���q<�TK���
�\;���<���i�:
��\��[�+�����.9������������}*�c�A����GA`���'���N���o��^��A`�5����c���1��w\������X���s�������x�?�P��2��
��!��;��������,b��k�i�\�p�6��pA��~���=g��|={����1���������H�UH�H���A���D�>�����I��!��Lx������:
��\����"�7k������?��-�=-��T>�c�(��A�}D������o�Y[�7�xc__��7:�cK�]�s#n��[n	��W\v�e���O<�b	����������^{�Nl�mH�!���
Y���d�\y�IW�{�=���1�����X�`;��Ct�<�����j�8�<V�<g�=�}u�m��'xK�k�T��|���q��B`�@����z*TX��=
/�s��������"o�������;���[n99����kxMMMI�i����9�+Ea]��� �����}��w��j��ug
D]�'��@&a��W_������-)��,�x{o����;����
	w^+�Kull�'|�9x�J$�CC��� �?��q�M7�^F���/a�����<��#2�#��&�,��'�~�}�����6���HK�]������S��������y@�X~��u*b q,�!��?��	/�a���^����9� )��A�}D�&�@K���6�m����������.�:<9�2	k�O����c��	6$�B�]����OQ	������K�n�o`��[�c�I?Y��k82~�a��O>I��C3�|�������v�i�������Z�x�q�H\�����N�����:�^��=�����x�'�h��d�
7��*$YD��L����S�:u���;�+R�#G��W�:@��M/BT���7����$�{O>��s����b��u1(���t�A���`�jk��/2?�%�@&a
�#��"�P�`��oTQ37yp�z��m�b��/�Kul�V.^3����a��_��t@y�:hw�`�k'�c�E>����{���<��c%���sO��q|�#,�e
��P-��n��,��~�wE�{��R������y�������N����������9�+Fa]��� �Sog6�:LtQ���uP'�k��@e{Acc��@/�������5!�T����}I�cc����(��%���a�nll�!+�����/����� �Q]������8m�$���>�5,���v���x�H2G
o�-���~�m��i����9��Fa]��� ������vfK!������[t�O��5fw6�=G�go�Y����F�������kY{�-�u�W���RO��?j� �	b�W�Jl����l�k{�-	��!+x�-�U���6�"�k
���^[?������?����y���q|��w�_|����oq�6d%
��\��[�hS���%Nk�m���8��q?+��T>��|�-H
�bPd���Qr�
�(e���p�dK�l�%C������K/��c�24.��B]�_����������7���v�mKvl�V.�3F�d$6AVxo�Xp��\G�f'�Xc_!������iQ86���3Bk�������?g����,
�)~�so�^���
�l�����|5�t��T����\�����Ar<$��6�<�VY)�=-��T>�c�(��A�}L��_<d��z�DG}�.K��L��5,AF������������u|����������eDL#��i�I�`MBi/T�c�����5\���vx�����������h�p������{��<0�����hO���u�c�>C���C��2��T��|���q���L��Q�����]>+���;��MMM����:��I!#��A�t�O�����R����O�sl�+Da](A�_�� +3�3#����V�c0[xQ.�NbA ��F��z@�k��M7�4��=r�H�5��3fh����1��y�!YJ����XO� mmKXq ���g�!������%�\����K���m�
�n[�M�2�b�(���L�{�w���I�&���������F�>���Xl���IXG�����wN��AmF%N�8���
������������7,�T��|�S�[(D
�B	����%BV�.]����o���V[m��]���@6a�����e�� �D,��2��1pae7n�~�
$�v�m��T��o�s��VC�dk�d�=�����'^����~����U�E���\�x���~���?_��C�"<��0o��)QmgV�{O>���8��,8�l����}*����X�����.��2m��K�~������
k���|�S�[�*QXB���	�	�	�	�	�	$��u���	�	�	�	�	�	B���z<�H�H�H�H�H�H �(���H�H�H�H�H�H������$@$@$@$@$@$@�'@a��-@$@$@$@$@$@$@���.��%     H<
��o      (��u!�x.	�	�	�	�	�	�@�	PX'~	�	�	�	�	�	�@!(���sI�H�H�H�H�H�O��:�[�H�H�H�H�H�H�
!@a]=�K$@$@$@$@$@$�x���@$@$@$@$@$@$P
�B��\      ����N�       �BPXB���	�	�	�	�	�	$��u���	�	�	�	�	�	B���z<�H�H�H�H�H�H �(���H�H�H�H�H�H������$@$@$@$@$@$@�'@a��-@$@$@$@$@$@$@���.��%     H<
��o      (��u!�x.	�	�	�	�	�	�@�	PX'~	�	�	�	�	�	�@!(���sI�H�H�H�H�H�O��:�[�H�H�H�H�H�H�
!@a]=�K$@$@$@$@$@$�x���@$@$@$@$@$@$P
�B��\      ����N�       �BPXB���	�	�	�	�	�	$��u���	�	�	�	�	�	B���z<�H�H�H�H�H�H �(���H�H�H�H�H�H������$@$@$@$@$@$@�'@a��-@$@$@$@$@$@$@���.��%  hSo���TWWK�������	�	�	d#@a��A$@$@$O?�������C�>���1s�$@$@� @a��u�,I�H�H �n��69����������jr$@$P^(��k=9  ([�e���	�	���u���   ������|��2h� ���+d��I��G>|�\r�%���/�E]$'N���[N�9�9��3���"5��~�I.��2y������������t�Ir�����khh��#G�c�=&S�L�N�:��[n)���l�������_|�A�D���+K/�������N���N�<y�,��R��N;�q���*�s0�s�9G�{�=9�����/���������z�7���d�$@$@�N����W��#  �V��������3GN9�Yy��e��12a��a}��'��k�)�$����r��wk1�6k�,�d�M�����v�MV_}u�>}�<����h�"�����XF;��d��Q���;j�;s�L-���?���__��'c������O�<�H�x�����������K�|�I�`�
d�v�c����k������}���:�1a�w�uW+�  p	PXs7�	�	�	����?�<��SZ�M�:UV]uU�w����O�}�����wo�e�]	��.��Bm1������#�H��;`��'��5�u�&������=��3���N;M���j�q�+8D���.��
�{��G[����}�z��e������
�M7�T�y�-��H�H�H�(��A�}�	�	�@����U��������s�^~���W�^������Q����?>M�v��Q6�h#m��7o��p��Wd�e���755����]�����ga�z����7�xC~��-��m��������c|VXC�C���	�	�@�PX�$�!  �2"a��Zk�G}��U�>}t\�W_}���������a�F|���~�c�!��������hp���{������,;����V�e����u��]�!#F�H�?~�x-��{�9������B�F$@$@�"@a],���H�H����5���|��4a��2�����UX/Y�DN?�t��p�B},,��q�����>�@�cm��/��2�/D�w�!�����,(��m]������VX����Z���	�	�@�PX�$�!  �2"P���	�`y>��c���
+��	�����n��^lp�~���������,�a�����r� ���e�A9 �
��-�C$@$@Q P��F|4Jf�eY��%� �a�F�pd���8����=x����������eY��&�DhGu�<�����>��cQ��o��B�/oC��i��ia��k
�(�,��H����uy�+gE$@$@(DXC#!,�?����h�7}��#�<�]�Q���P����^K�v�������k�Bb2����r�a�i�p��B����t��=��Sg*�5��
��ld3Gp
���O& �B�����H�H�H �@!���J<z�h]�z��������o��F���;�l�h�~��7�:��#;����(��6�@�j4d
�U�{��:��k!���^z�%-���Kx=��C�`�y��'�/��>����H�H�T(�KE���	�	�@�	*���u�x���l����w��z�����>�L6�`��l��Q��)S�ha�cO=�T�k��R�b~�q�	����b1����r�5���w�-�'O�.��������Fa�
���	�@�	PXG|�8<      �h�����pt$@$@$@$@$@$@'@a���H�H�H�H�H�H��M��:�����	�	�	�	�	�	D��u���#     �6
�h�GG$@$@$@$@$@$q�_ �H�H�H�H�H�H �(���>	�	�	�	�	�	�@�	PXG|�8<      �h�����pt$@$@$@$@$@$@'@a���H�H�H�H�H�H��M��:�����	�	�	�	�	�	D��u���#     �6
�h�GG$@$@$@$@$@$q�_ �H�H�H�H�H�H �(���>	�	�	�	�	�	�@�	PXG|�8<      �h�����pt$@$@$@$@$@$@'@a���H�H�H�H�H�H��M��:�����	�	�	�	�	�	D��u���#     �6
�h�GG$@$@$@$@$@$q�_ �H�H�H�H�H�H �(���>	�	�	�	�	�	�@�	PXG|�8<      �h�����pt$@$@$@$@$@$@'@a���H�H�H�H�H�H��M��:�����	�	�	�	�	�	D��u���#     �6
�h�GG$@$@$@$@$@$q�_ �H�H�H�H�H�H �(���>	�	�	�	�	�	�@�	PXG|�8<      �h�����pt$@$@$@$@$@$@'@a���H�H�H�H�H�H��M��:�����	�	�	�	�	�	D��u���#     �6
�h�GG$@$@$@$@$@$q�_ �H�H�H�H�H�H �(���>	�	�	�	�	�	�@�	PXG|�8<      �h�����pt$@$@$@$@$@$@'@a���H�H�H�H�H�H��M��:�����	�	�	�	�	�	D��u���#     �6
�h�GG$@$@$@$@$@$q�_ �H�H�H�H�H�H �(���>	�	�	�	�	�	�@�	��+��v;HHIEND�B`�
#37Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Melanie Plageman (#9)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

(Adding Dilip, the original author of the parallel bitmap heap scan
patch all those years ago, in case you remember anything about the
snapshot stuff below.)

On 27/02/2024 16:22, Melanie Plageman wrote:

On Mon, Feb 26, 2024 at 08:50:28PM -0500, Melanie Plageman wrote:

On Fri, Feb 16, 2024 at 12:35:59PM -0500, Melanie Plageman wrote:

In the attached v3, I've reordered the commits, updated some errant
comments, and improved the commit messages.

I've also made some updates to the TIDBitmap API that seem like a
clarity improvement to the API in general. These also reduce the diff
for GIN when separating the TBMIterateResult from the
TBM[Shared]Iterator. And these TIDBitmap API changes are now all in
their own commits (previously those were in the same commit as adding
the BitmapHeapScan streaming read user).

The three outstanding issues I see in the patch set are:
1) the lossy and exact page counters issue described in my previous
email

I've resolved this. I added a new patch to the set which starts counting
even pages with no visible tuples toward lossy and exact pages. After an
off-list conversation with Andres, it seems that this omission in master
may not have been intentional.

Once we have only two types of pages to differentiate between (lossy and
exact [no longer have to care about "has no visible tuples"]), it is
easy enough to pass a "lossy" boolean paramater to
table_scan_bitmap_next_block(). I've done this in the attached v4.

Thomas posted a new version of the Streaming Read API [1], so here is a
rebased v5. This should make it easier to review as it can be applied on
top of master.

Lots of discussion happening on the performance results but it seems
that there is no performance impact with the preliminary patches up to
v5-0013-Streaming-Read-API.patch. I'm focusing purely on those
preliminary patches now, because I think they're worthwhile cleanups
independent of the streaming read API.

Andres already commented on the snapshot stuff on an earlier patch
version, and that's much nicer with this version. However, I don't
understand why a parallel bitmap heap scan needs to do anything at all
with the snapshot, even before these patches. The parallel worker
infrastructure already passes the active snapshot from the leader to the
parallel worker. Why does bitmap heap scan code need to do that too?

I disabled that with:

--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -874,7 +874,9 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
node->pstate = pstate;

+#if 0
node->worker_snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
Assert(IsMVCCSnapshot(node->worker_snapshot));
RegisterSnapshot(node->worker_snapshot);
+#endif
}

and ran "make check-world". All the tests passed. To be even more sure,
I added some code there to assert that the serialized version of
node->ss.ps.state->es_snapshot is equal to pstate->phs_snapshot_data,
and all the tests passed with that too.

I propose that we just remove the code in BitmapHeapScan to serialize
the snapshot, per attached patch.

--
Heikki Linnakangas
Neon (https://neon.tech)

Attachments:

0001-Remove-redundant-snapshot-copying-from-parallel-lead.patchtext/x-patch; charset=UTF-8; name=0001-Remove-redundant-snapshot-copying-from-parallel-lead.patchDownload
From 265d77efa2b56d5cfc3caf7843058b7336524860 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Wed, 13 Mar 2024 15:25:07 +0200
Subject: [PATCH 1/1] Remove redundant snapshot copying from parallel leader to
 workers

The parallel query infrastructure copies the leader backend's active
snapshot to the worker processes. But BitmapHeapScan node also had
bespoken code to pass the snapshot from leader to the worker. That was
redundant, so remove it.

Discussion: XX
---
 src/backend/access/table/tableam.c        | 10 ----------
 src/backend/executor/nodeBitmapHeapscan.c | 17 ++---------------
 src/include/access/tableam.h              |  5 -----
 src/include/nodes/execnodes.h             |  4 ----
 4 files changed, 2 insertions(+), 34 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 6ed8cca05a1..e57a0b7ea31 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,16 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-void
-table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot)
-{
-	Assert(IsMVCCSnapshot(snapshot));
-
-	RegisterSnapshot(snapshot);
-	scan->rs_snapshot = snapshot;
-	scan->rs_flags |= SO_TEMP_SNAPSHOT;
-}
-
 
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 345b67649ea..ca548e44eb4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -721,7 +721,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
-	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
@@ -841,13 +840,7 @@ void
 ExecBitmapHeapEstimate(BitmapHeapScanState *node,
 					   ParallelContext *pcxt)
 {
-	EState	   *estate = node->ss.ps.state;
-
-	node->pscan_len = add_size(offsetof(ParallelBitmapHeapState,
-										phs_snapshot_data),
-							   EstimateSnapshotSpace(estate->es_snapshot));
-
-	shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
+	shm_toc_estimate_chunk(&pcxt->estimator, sizeof(ParallelBitmapHeapState));
 	shm_toc_estimate_keys(&pcxt->estimator, 1);
 }
 
@@ -862,14 +855,13 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 							ParallelContext *pcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	EState	   *estate = node->ss.ps.state;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/* If there's no DSA, there are no workers; initialize nothing. */
 	if (dsa == NULL)
 		return;
 
-	pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
+	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
 
 	pstate->tbmiterator = 0;
 	pstate->prefetch_iterator = 0;
@@ -881,7 +873,6 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
-	SerializeSnapshot(estate->es_snapshot, pstate->phs_snapshot_data);
 
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
 	node->pstate = pstate;
@@ -927,13 +918,9 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 							   ParallelWorkerContext *pwcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	Snapshot	snapshot;
 
 	Assert(node->ss.ps.state->es_query_dsa != NULL);
 
 	pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
 	node->pstate = pstate;
-
-	snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
-	table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
 }
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5f8474871d2..8249b37bbf1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -1038,11 +1038,6 @@ table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
 										 allow_pagemode);
 }
 
-/*
- * Update snapshot used by the scan.
- */
-extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
-
 /*
  * Return next tuple from `scan`, store in slot.
  */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 444a5f0fd57..27614ab50fb 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1689,7 +1689,6 @@ typedef enum
  *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
- *		phs_snapshot_data		snapshot data shared to workers
  * ----------------
  */
 typedef struct ParallelBitmapHeapState
@@ -1701,7 +1700,6 @@ typedef struct ParallelBitmapHeapState
 	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
-	char		phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
 } ParallelBitmapHeapState;
 
 /* ----------------
@@ -1721,7 +1719,6 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
- *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
  *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
@@ -1745,7 +1742,6 @@ typedef struct BitmapHeapScanState
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
-	Size		pscan_len;
 	bool		initialized;
 	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
-- 
2.39.2

#38Dilip Kumar
dilipbalaut@gmail.com
In reply to: Heikki Linnakangas (#37)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Mar 13, 2024 at 7:04 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

(Adding Dilip, the original author of the parallel bitmap heap scan
patch all those years ago, in case you remember anything about the
snapshot stuff below.)

On 27/02/2024 16:22, Melanie Plageman wrote:

Andres already commented on the snapshot stuff on an earlier patch
version, and that's much nicer with this version. However, I don't
understand why a parallel bitmap heap scan needs to do anything at all
with the snapshot, even before these patches. The parallel worker
infrastructure already passes the active snapshot from the leader to the
parallel worker. Why does bitmap heap scan code need to do that too?

Yeah thinking on this now it seems you are right that the parallel
infrastructure is already passing the active snapshot so why do we
need it again. Then I checked other low scan nodes like indexscan and
seqscan and it seems we are doing the same things there as well.
Check for SerializeSnapshot() in table_parallelscan_initialize() and
index_parallelscan_initialize() which are being called from
ExecSeqScanInitializeDSM() and ExecIndexScanInitializeDSM()
respectively.

--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com

#39Robert Haas
robertmhaas@gmail.com
In reply to: Dilip Kumar (#38)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Mar 13, 2024 at 11:39 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:

Andres already commented on the snapshot stuff on an earlier patch
version, and that's much nicer with this version. However, I don't
understand why a parallel bitmap heap scan needs to do anything at all
with the snapshot, even before these patches. The parallel worker
infrastructure already passes the active snapshot from the leader to the
parallel worker. Why does bitmap heap scan code need to do that too?

Yeah thinking on this now it seems you are right that the parallel
infrastructure is already passing the active snapshot so why do we
need it again. Then I checked other low scan nodes like indexscan and
seqscan and it seems we are doing the same things there as well.
Check for SerializeSnapshot() in table_parallelscan_initialize() and
index_parallelscan_initialize() which are being called from
ExecSeqScanInitializeDSM() and ExecIndexScanInitializeDSM()
respectively.

I remember thinking about this when I was writing very early parallel
query code. It seemed to me that there must be some reason why the
EState has a snapshot, as opposed to just using the active snapshot,
and so I took care to propagate that snapshot, which is used for the
leader's scans, to the worker scans also. Now, if the EState doesn't
need to contain a snapshot, then all of that mechanism is unnecessary,
but I don't see how it can be right for the leader to do
table_beginscan() using estate->es_snapshot and the worker to use the
active snapshot.

--
Robert Haas
EDB: http://www.enterprisedb.com

#40Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Heikki Linnakangas (#37)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/13/24 14:34, Heikki Linnakangas wrote:

...

Lots of discussion happening on the performance results but it seems
that there is no performance impact with the preliminary patches up to
v5-0013-Streaming-Read-API.patch. I'm focusing purely on those
preliminary patches now, because I think they're worthwhile cleanups
independent of the streaming read API.

Not quite true - the comparison I shared on 29/2 [1]/messages/by-id/91090d58-7d3f-4447-9425-f24ba66e292a@enterprisedb.com -- Tomas Vondra EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company shows a serious
regression caused by the 0010 patch. We've been investigating this with
Melanie off list, but we don't have any clear findings yet (except that
it's clearly due to moving BitmapAdjustPrefetchIterator() a bit down.

But if we revert this (and move the BitmapAdjustPrefetchIterator back),
the regression should disappear, and we can merge these preparatory
patches. We'll have to deal with the regression (or something very
similar) when merging the remaining patches.

regards

[1]: /messages/by-id/91090d58-7d3f-4447-9425-f24ba66e292a@enterprisedb.com -- Tomas Vondra EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company
/messages/by-id/91090d58-7d3f-4447-9425-f24ba66e292a@enterprisedb.com
--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#41Thomas Munro
thomas.munro@gmail.com
In reply to: Tomas Vondra (#30)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Mar 3, 2024 at 11:41 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/2/24 23:28, Melanie Plageman wrote:

On Sat, Mar 2, 2024 at 10:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

With the current "master" code, eic=1 means we'll issue a prefetch for B
and then read+process A. And then issue prefetch for C and read+process
B, and so on. It's always one page ahead.

Yes, that is what I mean for eic = 1

I spent quite a few days thinking about the meaning of eic=0 and eic=1
for streaming_read.c v7[1]/messages/by-id/CA+hUKGLJi+c5jB3j6UvkgMYHky-qu+LPCsiNahUGSa5Z4DvyVA@mail.gmail.com, to make it agree with the above and with
master. Here's why I was confused:

Both eic=0 and eic=1 are expected to generate at most 1 physical I/O
at a time, or I/O queue depth 1 if you want to put it that way. But
this isn't just about concurrency of I/O, it's also about computation.
Duh.

eic=0 means that the I/O is not concurrent with executor computation.
So, to annotate an excerpt from [1]/messages/by-id/CA+hUKGLJi+c5jB3j6UvkgMYHky-qu+LPCsiNahUGSa5Z4DvyVA@mail.gmail.com's random.txt, we have:

effective_io_concurrency = 0, range size = 1
unpatched patched
==============================================================================
pread(43,...,8192,0x58000) = 8192 pread(82,...,8192,0x58000) = 8192
*** executor now has page at 0x58000 to work on ***
pread(43,...,8192,0xb0000) = 8192 pread(82,...,8192,0xb0000) = 8192
*** executor now has page at 0xb0000 to work on ***

eic=1 means that a single I/O is started and then control is returned
to the executor code to do useful work concurrently with the
background read that we assume is happening:

effective_io_concurrency = 1, range size = 1
unpatched patched
==============================================================================
pread(43,...,8192,0x58000) = 8192 pread(82,...,8192,0x58000) = 8192
posix_fadvise(43,0xb0000,0x2000,...) posix_fadvise(82,0xb0000,0x2000,...)
*** executor now has page at 0x58000 to work on ***
pread(43,...,8192,0xb0000) = 8192 pread(82,...,8192,0xb0000) = 8192
posix_fadvise(43,0x108000,0x2000,...) posix_fadvise(82,0x108000,0x2000,...)
*** executor now has page at 0xb0000 to work on ***
pread(43,...,8192,0x108000) = 8192 pread(82,...,8192,0x108000) = 8192
posix_fadvise(43,0x160000,0x2000,...) posix_fadvise(82,0x160000,0x2000,...)

In other words, 'concurrency' doesn't mean 'number of I/Os running
concurrently with each other', it means 'number of I/Os running
concurrently with computation', and when you put it that way, 0 and 1
are different.

Note that the first read is a bit special: by the time the consumer is
ready to pull a buffer out of the stream when we don't have a buffer
ready yet, it is too late to issue useful advice, so we don't bother.
FWIW I think even in the AIO future we would have a synchronous read
in that specific place, at least when using io_method=worker, because
it would be stupid to ask another process to read a block for us that
we want right now and then wait for it wake us up when it's done.

Note that even when we aren't issuing any advice because eic=0 or
because we detected sequential access and we believe the kernel can do
a better job than us, we still 'look ahead' (= call the callback to
see which block numbers are coming down the pipe), but only as far as
we need to coalesce neighbouring blocks. (I deliberately avoid using
the word "prefetch" except in very general discussions because it
means different things to different layers of the code, hence talk of
"look ahead" and "advice".) That's how we get this change:

effective_io_concurrency = 0, range size = 4
unpatched patched
==============================================================================
pread(43,...,8192,0x58000) = 8192 pread(82,...,8192,0x58000) = 8192
pread(43,...,8192,0x5a000) = 8192 preadv(82,...,2,0x5a000) = 16384
pread(43,...,8192,0x5c000) = 8192 pread(82,...,8192,0x5e000) = 8192
pread(43,...,8192,0x5e000) = 8192 preadv(82,...,4,0xb0000) = 32768
pread(43,...,8192,0xb0000) = 8192 preadv(82,...,4,0x108000) = 32768
pread(43,...,8192,0xb2000) = 8192 preadv(82,...,4,0x160000) = 32768

And then once we introduce eic > 0 to the picture with neighbouring
blocks that can be coalesced, "patched" starts to diverge even more
from "unpatched" because it tracks the number of wide I/Os in
progress, not the number of single blocks.

[1]: /messages/by-id/CA+hUKGLJi+c5jB3j6UvkgMYHky-qu+LPCsiNahUGSa5Z4DvyVA@mail.gmail.com

#42Dilip Kumar
dilipbalaut@gmail.com
In reply to: Robert Haas (#39)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Mar 13, 2024 at 9:25 PM Robert Haas <robertmhaas@gmail.com> wrote:

On Wed, Mar 13, 2024 at 11:39 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:

Andres already commented on the snapshot stuff on an earlier patch
version, and that's much nicer with this version. However, I don't
understand why a parallel bitmap heap scan needs to do anything at all
with the snapshot, even before these patches. The parallel worker
infrastructure already passes the active snapshot from the leader to the
parallel worker. Why does bitmap heap scan code need to do that too?

Yeah thinking on this now it seems you are right that the parallel
infrastructure is already passing the active snapshot so why do we
need it again. Then I checked other low scan nodes like indexscan and
seqscan and it seems we are doing the same things there as well.
Check for SerializeSnapshot() in table_parallelscan_initialize() and
index_parallelscan_initialize() which are being called from
ExecSeqScanInitializeDSM() and ExecIndexScanInitializeDSM()
respectively.

I remember thinking about this when I was writing very early parallel
query code. It seemed to me that there must be some reason why the
EState has a snapshot, as opposed to just using the active snapshot,
and so I took care to propagate that snapshot, which is used for the
leader's scans, to the worker scans also. Now, if the EState doesn't
need to contain a snapshot, then all of that mechanism is unnecessary,
but I don't see how it can be right for the leader to do
table_beginscan() using estate->es_snapshot and the worker to use the
active snapshot.

Yeah, that's a very valid point. So I think now Heikki/Melanie might
have got an answer to their question, about the thought process behind
serializing the snapshot for each scan node. And the same thing is
followed for BitmapHeapNode as well.

--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com

#43Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Dilip Kumar (#42)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 14/03/2024 06:54, Dilip Kumar wrote:

On Wed, Mar 13, 2024 at 9:25 PM Robert Haas <robertmhaas@gmail.com> wrote:

On Wed, Mar 13, 2024 at 11:39 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:

Andres already commented on the snapshot stuff on an earlier patch
version, and that's much nicer with this version. However, I don't
understand why a parallel bitmap heap scan needs to do anything at all
with the snapshot, even before these patches. The parallel worker
infrastructure already passes the active snapshot from the leader to the
parallel worker. Why does bitmap heap scan code need to do that too?

Yeah thinking on this now it seems you are right that the parallel
infrastructure is already passing the active snapshot so why do we
need it again. Then I checked other low scan nodes like indexscan and
seqscan and it seems we are doing the same things there as well.
Check for SerializeSnapshot() in table_parallelscan_initialize() and
index_parallelscan_initialize() which are being called from
ExecSeqScanInitializeDSM() and ExecIndexScanInitializeDSM()
respectively.

I remember thinking about this when I was writing very early parallel
query code. It seemed to me that there must be some reason why the
EState has a snapshot, as opposed to just using the active snapshot,
and so I took care to propagate that snapshot, which is used for the
leader's scans, to the worker scans also. Now, if the EState doesn't
need to contain a snapshot, then all of that mechanism is unnecessary,
but I don't see how it can be right for the leader to do
table_beginscan() using estate->es_snapshot and the worker to use the
active snapshot.

Yeah, that's a very valid point. So I think now Heikki/Melanie might
have got an answer to their question, about the thought process behind
serializing the snapshot for each scan node. And the same thing is
followed for BitmapHeapNode as well.

I see. Thanks, understanding the thought process helps.

So when a parallel table or index scan runs in the executor as part of a
query, we could just use the active snapshot. But there are some other
callers of parallel table scans that don't use the executor, namely
parallel index builds. For those it makes sense to pass the snapshot for
the scan independent of the active snapshot.

A parallel bitmap heap scan isn't really a parallel scan as far as the
table AM is concerned, though. It's more like an independent bitmap heap
scan in each worker process, nodeBitmapHeapscan.c does all the
coordination of which blocks to scan. So I think that
table_parallelscan_initialize() was the wrong role model, and we should
still remove the snapshot serialization code from nodeBitmapHeapscan.c.

Digging deeper into the question of whether es_snapshot ==
GetActiveSnapshot() is a valid assumption:

<deep dive>

es_snapshot is copied from the QueryDesc in standard_ExecutorStart().
Looking at the callers of ExecutorStart(), they all get the QueryDesc by
calling CreateQueryDesc() with GetActiveSnapshot(). And I don't see any
callers changing the active snapshot between the ExecutorStart() and
ExecutorRun() calls either. In pquery.c, we explicitly
PushActiveSnapshot(queryDesc->snapshot) before calling ExecutorRun(). So
no live bug here AFAICS, es_snapshot == GetActiveSnapshot() holds.

_SPI_execute_plan() has code to deal with the possibility that the
active snapshot is not set. That seems fishy; do we really support SPI
without any snapshot? I'm inclined to turn that into an error. I ran the
regression tests with an "Assert(ActiveSnapshotSet())" there, and
everything worked.

If es_snapshot was different from the active snapshot, things would get
weird, even without parallel query. The scans would use es_snapshot for
the visibility checks, but any functions you execute in quals would use
the active snapshot.

We could double down on that assumption, and remove es_snapshot
altogether and use GetActiveSnapshot() instead. And perhaps add
"PushActiveSnapshot(queryDesc->snapshot)" to ExecutorRun().

</deep dive>

In summary, this es_snapshot stuff is a bit confusing and could use some
cleanup. But for now, I'd like to just add some assertions and a
comments about this, and remove the snapshot serialization from bitmap
heap scan node, to make it consistent with other non-parallel scan nodes
(it's not really a parallel scan as far as the table AM is concerned).
See attached patch, which is the same as previous patch with some extra
assertions.

--
Heikki Linnakangas
Neon (https://neon.tech)

Attachments:

v2-0001-Remove-redundant-snapshot-copying-from-parallel-l.patchtext/x-patch; charset=UTF-8; name=v2-0001-Remove-redundant-snapshot-copying-from-parallel-l.patchDownload
From 44eb77162ccc6f18a0a5eaccf0c083d4fefd076f Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 14 Mar 2024 11:56:11 +0200
Subject: [PATCH v2 1/1] Remove redundant snapshot copying from parallel leader
 to workers

The parallel query infrastructure copies the leader backend's active
snapshot to the worker processes. But BitmapHeapScan node also had
bespoken code to pass the snapshot from leader to the worker. That was
redundant, so remove it.

The removed code was analogous to the snapshot serialization in
table_parallelscan_initialize(), but that was the wrong role model. A
parallel bitmap heap scan is more like an independent non-parallel
bitmap heap scan in each parallel worker as far as the table AM is
concerned, because the coordination is done in nodeBitmapHeapscan.c,
and the table AM doesn't need to know anything about it.

This relies on the assumption that es_snapshot ==
GetActiveSnapshot(). That's not a new assumption, things would get
weird if you used the QueryDesc's snapshot for visibility checks in
the scans, but the active snapshot for evaluating quals, for
example. This could use some refactoring and cleanup, but for now,
just add some assertions.

Discussion: https://www.postgresql.org/message-id/5f3b9d59-0f43-419d-80ca-6d04c07cf61a@iki.fi
---
 src/backend/access/table/tableam.c        | 10 ----------
 src/backend/executor/execMain.c           |  6 ++++++
 src/backend/executor/execParallel.c       |  7 +++++++
 src/backend/executor/nodeBitmapHeapscan.c | 17 ++---------------
 src/include/access/tableam.h              |  5 -----
 src/include/nodes/execnodes.h             |  4 ----
 6 files changed, 15 insertions(+), 34 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 6ed8cca05a..e57a0b7ea3 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,16 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-void
-table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot)
-{
-	Assert(IsMVCCSnapshot(snapshot));
-
-	RegisterSnapshot(snapshot);
-	scan->rs_snapshot = snapshot;
-	scan->rs_flags |= SO_TEMP_SNAPSHOT;
-}
-
 
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 940499cc61..7eb1f7d020 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -147,6 +147,9 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
 	Assert(queryDesc != NULL);
 	Assert(queryDesc->estate == NULL);
 
+	/* caller must ensure the query's snapshot is active */
+	Assert(GetActiveSnapshot() == queryDesc->snapshot);
+
 	/*
 	 * If the transaction is read-only, we need to check if any writes are
 	 * planned to non-temporary tables.  EXPLAIN is considered read-only.
@@ -319,6 +322,9 @@ standard_ExecutorRun(QueryDesc *queryDesc,
 	Assert(estate != NULL);
 	Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
 
+	/* caller must ensure the query's snapshot is active */
+	Assert(GetActiveSnapshot() == estate->es_snapshot);
+
 	/*
 	 * Switch into per-query memory context
 	 */
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index 3f84c002dc..8c53d1834e 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -720,6 +720,13 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
 	shm_toc_estimate_chunk(&pcxt->estimator, dsa_minsize);
 	shm_toc_estimate_keys(&pcxt->estimator, 1);
 
+	/*
+	 * InitializeParallelDSM() passes the active snapshot to the parallel
+	 * worker, which uses it to set es_snapshot.  Make sure we don't set
+	 * es_snapshot differently in the child.
+	 */
+	Assert(GetActiveSnapshot() == estate->es_snapshot);
+
 	/* Everyone's had a chance to ask for space, so now create the DSM. */
 	InitializeParallelDSM(pcxt);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 345b67649e..ca548e44eb 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -721,7 +721,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
-	scanstate->pscan_len = 0;
 	scanstate->initialized = false;
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
@@ -841,13 +840,7 @@ void
 ExecBitmapHeapEstimate(BitmapHeapScanState *node,
 					   ParallelContext *pcxt)
 {
-	EState	   *estate = node->ss.ps.state;
-
-	node->pscan_len = add_size(offsetof(ParallelBitmapHeapState,
-										phs_snapshot_data),
-							   EstimateSnapshotSpace(estate->es_snapshot));
-
-	shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
+	shm_toc_estimate_chunk(&pcxt->estimator, sizeof(ParallelBitmapHeapState));
 	shm_toc_estimate_keys(&pcxt->estimator, 1);
 }
 
@@ -862,14 +855,13 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 							ParallelContext *pcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	EState	   *estate = node->ss.ps.state;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/* If there's no DSA, there are no workers; initialize nothing. */
 	if (dsa == NULL)
 		return;
 
-	pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
+	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
 
 	pstate->tbmiterator = 0;
 	pstate->prefetch_iterator = 0;
@@ -881,7 +873,6 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
-	SerializeSnapshot(estate->es_snapshot, pstate->phs_snapshot_data);
 
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
 	node->pstate = pstate;
@@ -927,13 +918,9 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 							   ParallelWorkerContext *pwcxt)
 {
 	ParallelBitmapHeapState *pstate;
-	Snapshot	snapshot;
 
 	Assert(node->ss.ps.state->es_query_dsa != NULL);
 
 	pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
 	node->pstate = pstate;
-
-	snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
-	table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
 }
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5f8474871d..8249b37bbf 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -1038,11 +1038,6 @@ table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
 										 allow_pagemode);
 }
 
-/*
- * Update snapshot used by the scan.
- */
-extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
-
 /*
  * Return next tuple from `scan`, store in slot.
  */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 444a5f0fd5..27614ab50f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1689,7 +1689,6 @@ typedef enum
  *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
- *		phs_snapshot_data		snapshot data shared to workers
  * ----------------
  */
 typedef struct ParallelBitmapHeapState
@@ -1701,7 +1700,6 @@ typedef struct ParallelBitmapHeapState
 	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
-	char		phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
 } ParallelBitmapHeapState;
 
 /* ----------------
@@ -1721,7 +1719,6 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
- *		pscan_len		   size of the shared memory for parallel bitmap
  *		initialized		   is node is ready to iterate
  *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
@@ -1745,7 +1742,6 @@ typedef struct BitmapHeapScanState
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
-	Size		pscan_len;
 	bool		initialized;
 	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
-- 
2.39.2

#44Dilip Kumar
dilipbalaut@gmail.com
In reply to: Heikki Linnakangas (#43)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Mar 14, 2024 at 4:07 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

Yeah, that's a very valid point. So I think now Heikki/Melanie might
have got an answer to their question, about the thought process behind
serializing the snapshot for each scan node. And the same thing is
followed for BitmapHeapNode as well.

I see. Thanks, understanding the thought process helps.

So when a parallel table or index scan runs in the executor as part of a
query, we could just use the active snapshot. But there are some other
callers of parallel table scans that don't use the executor, namely
parallel index builds. For those it makes sense to pass the snapshot for
the scan independent of the active snapshot.

Right

A parallel bitmap heap scan isn't really a parallel scan as far as the
table AM is concerned, though. It's more like an independent bitmap heap
scan in each worker process, nodeBitmapHeapscan.c does all the
coordination of which blocks to scan. So I think that
table_parallelscan_initialize() was the wrong role model, and we should
still remove the snapshot serialization code from nodeBitmapHeapscan.c.

I think that seems right.

Digging deeper into the question of whether es_snapshot ==
GetActiveSnapshot() is a valid assumption:

<deep dive>

es_snapshot is copied from the QueryDesc in standard_ExecutorStart().
Looking at the callers of ExecutorStart(), they all get the QueryDesc by
calling CreateQueryDesc() with GetActiveSnapshot(). And I don't see any
callers changing the active snapshot between the ExecutorStart() and
ExecutorRun() calls either. In pquery.c, we explicitly
PushActiveSnapshot(queryDesc->snapshot) before calling ExecutorRun(). So
no live bug here AFAICS, es_snapshot == GetActiveSnapshot() holds.

_SPI_execute_plan() has code to deal with the possibility that the
active snapshot is not set. That seems fishy; do we really support SPI
without any snapshot? I'm inclined to turn that into an error. I ran the
regression tests with an "Assert(ActiveSnapshotSet())" there, and
everything worked.

IMHO, we can call SPI_Connect() and SPI_Execute() from any C
extension, so I don't think there we can guarantee that the snapshot
must be set, do we?

If es_snapshot was different from the active snapshot, things would get
weird, even without parallel query. The scans would use es_snapshot for
the visibility checks, but any functions you execute in quals would use
the active snapshot.

We could double down on that assumption, and remove es_snapshot
altogether and use GetActiveSnapshot() instead. And perhaps add
"PushActiveSnapshot(queryDesc->snapshot)" to ExecutorRun().

</deep dive>

In summary, this es_snapshot stuff is a bit confusing and could use some
cleanup. But for now, I'd like to just add some assertions and a
comments about this, and remove the snapshot serialization from bitmap
heap scan node, to make it consistent with other non-parallel scan nodes
(it's not really a parallel scan as far as the table AM is concerned).
See attached patch, which is the same as previous patch with some extra
assertions.

Maybe for now we can just handle this specific case to remove the
snapshot serializing for the BitmapHeapScan as you are doing in the
patch. After looking into the code your theory seems correct that we
are just copying the ActiveSnapshot while building the query
descriptor and from there we are copying into the Estate so logically
there should not be any reason for these two to be different.

--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com

#45Robert Haas
robertmhaas@gmail.com
In reply to: Heikki Linnakangas (#43)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Mar 14, 2024 at 6:37 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

If es_snapshot was different from the active snapshot, things would get
weird, even without parallel query. The scans would use es_snapshot for
the visibility checks, but any functions you execute in quals would use
the active snapshot.

Hmm, that's an interesting point.

The case where the query is suspended and resumed - i.e. cursors are
used - probably needs more analysis. In that case, perhaps there's
more room for the snapshots to diverge.

--
Robert Haas
EDB: http://www.enterprisedb.com

#46Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Robert Haas (#45)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 14/03/2024 14:34, Robert Haas wrote:

On Thu, Mar 14, 2024 at 6:37 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

If es_snapshot was different from the active snapshot, things would get
weird, even without parallel query. The scans would use es_snapshot for
the visibility checks, but any functions you execute in quals would use
the active snapshot.

Hmm, that's an interesting point.

The case where the query is suspended and resumed - i.e. cursors are
used - probably needs more analysis. In that case, perhaps there's
more room for the snapshots to diverge.

The portal code is pretty explicit about it, the ExecutorRun() call in
PortalRunSelect() looks like this:

PushActiveSnapshot(queryDesc->snapshot);
ExecutorRun(queryDesc, direction, (uint64) count,
portal->run_once);
nprocessed = queryDesc->estate->es_processed;
PopActiveSnapshot();

I looked at all the callers of ExecutorRun(), and they all have the
active snapshot equal to queryDesc->snapshot, either because they called
CreateQueryDesc() with the active snapshot before ExecutorRun(), or they
set the active snapshot like above.

--
Heikki Linnakangas
Neon (https://neon.tech)

#47Robert Haas
robertmhaas@gmail.com
In reply to: Heikki Linnakangas (#46)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Mar 14, 2024 at 9:00 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

The portal code is pretty explicit about it, the ExecutorRun() call in
PortalRunSelect() looks like this:

PushActiveSnapshot(queryDesc->snapshot);
ExecutorRun(queryDesc, direction, (uint64) count,
portal->run_once);
nprocessed = queryDesc->estate->es_processed;
PopActiveSnapshot();

I looked at all the callers of ExecutorRun(), and they all have the
active snapshot equal to queryDesc->snapshot, either because they called
CreateQueryDesc() with the active snapshot before ExecutorRun(), or they
set the active snapshot like above.

Well, maybe there's a bunch of code cleanup possible, then.

--
Robert Haas
EDB: http://www.enterprisedb.com

#48Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Dilip Kumar (#44)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 14/03/2024 12:55, Dilip Kumar wrote:

On Thu, Mar 14, 2024 at 4:07 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

_SPI_execute_plan() has code to deal with the possibility that the
active snapshot is not set. That seems fishy; do we really support SPI
without any snapshot? I'm inclined to turn that into an error. I ran the
regression tests with an "Assert(ActiveSnapshotSet())" there, and
everything worked.

IMHO, we can call SPI_Connect() and SPI_Execute() from any C
extension, so I don't think there we can guarantee that the snapshot
must be set, do we?

I suppose, although the things you could do without a snapshot would be
pretty limited. The query couldn't access any tables. Could it even look
up functions in the parser? Not sure.

Maybe for now we can just handle this specific case to remove the
snapshot serializing for the BitmapHeapScan as you are doing in the
patch. After looking into the code your theory seems correct that we
are just copying the ActiveSnapshot while building the query
descriptor and from there we are copying into the Estate so logically
there should not be any reason for these two to be different.

Ok, committed that for now. Thanks for looking!

--
Heikki Linnakangas
Neon (https://neon.tech)

#49Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Thomas Munro (#41)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/13/24 23:38, Thomas Munro wrote:

On Sun, Mar 3, 2024 at 11:41 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/2/24 23:28, Melanie Plageman wrote:

On Sat, Mar 2, 2024 at 10:05 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

With the current "master" code, eic=1 means we'll issue a prefetch for B
and then read+process A. And then issue prefetch for C and read+process
B, and so on. It's always one page ahead.

Yes, that is what I mean for eic = 1

I spent quite a few days thinking about the meaning of eic=0 and eic=1
for streaming_read.c v7[1], to make it agree with the above and with
master. Here's why I was confused:

Both eic=0 and eic=1 are expected to generate at most 1 physical I/O
at a time, or I/O queue depth 1 if you want to put it that way. But
this isn't just about concurrency of I/O, it's also about computation.
Duh.

eic=0 means that the I/O is not concurrent with executor computation.
So, to annotate an excerpt from [1]'s random.txt, we have:

effective_io_concurrency = 0, range size = 1
unpatched patched
==============================================================================
pread(43,...,8192,0x58000) = 8192 pread(82,...,8192,0x58000) = 8192
*** executor now has page at 0x58000 to work on ***
pread(43,...,8192,0xb0000) = 8192 pread(82,...,8192,0xb0000) = 8192
*** executor now has page at 0xb0000 to work on ***

eic=1 means that a single I/O is started and then control is returned
to the executor code to do useful work concurrently with the
background read that we assume is happening:

effective_io_concurrency = 1, range size = 1
unpatched patched
==============================================================================
pread(43,...,8192,0x58000) = 8192 pread(82,...,8192,0x58000) = 8192
posix_fadvise(43,0xb0000,0x2000,...) posix_fadvise(82,0xb0000,0x2000,...)
*** executor now has page at 0x58000 to work on ***
pread(43,...,8192,0xb0000) = 8192 pread(82,...,8192,0xb0000) = 8192
posix_fadvise(43,0x108000,0x2000,...) posix_fadvise(82,0x108000,0x2000,...)
*** executor now has page at 0xb0000 to work on ***
pread(43,...,8192,0x108000) = 8192 pread(82,...,8192,0x108000) = 8192
posix_fadvise(43,0x160000,0x2000,...) posix_fadvise(82,0x160000,0x2000,...)

In other words, 'concurrency' doesn't mean 'number of I/Os running
concurrently with each other', it means 'number of I/Os running
concurrently with computation', and when you put it that way, 0 and 1
are different.

Interesting. For some reason I thought with eic=1 we'd issue the fadvise
for page #2 before pread of page #1, so that there'd be 2 IO requests in
flight at the same time for a bit of time ... it'd give the fadvise more
time to actually get the data into page cache.

Note that the first read is a bit special: by the time the consumer is
ready to pull a buffer out of the stream when we don't have a buffer
ready yet, it is too late to issue useful advice, so we don't bother.
FWIW I think even in the AIO future we would have a synchronous read
in that specific place, at least when using io_method=worker, because
it would be stupid to ask another process to read a block for us that
we want right now and then wait for it wake us up when it's done.

Note that even when we aren't issuing any advice because eic=0 or
because we detected sequential access and we believe the kernel can do
a better job than us, we still 'look ahead' (= call the callback to
see which block numbers are coming down the pipe), but only as far as
we need to coalesce neighbouring blocks. (I deliberately avoid using
the word "prefetch" except in very general discussions because it
means different things to different layers of the code, hence talk of
"look ahead" and "advice".) That's how we get this change:

effective_io_concurrency = 0, range size = 4
unpatched patched
==============================================================================
pread(43,...,8192,0x58000) = 8192 pread(82,...,8192,0x58000) = 8192
pread(43,...,8192,0x5a000) = 8192 preadv(82,...,2,0x5a000) = 16384
pread(43,...,8192,0x5c000) = 8192 pread(82,...,8192,0x5e000) = 8192
pread(43,...,8192,0x5e000) = 8192 preadv(82,...,4,0xb0000) = 32768
pread(43,...,8192,0xb0000) = 8192 preadv(82,...,4,0x108000) = 32768
pread(43,...,8192,0xb2000) = 8192 preadv(82,...,4,0x160000) = 32768

And then once we introduce eic > 0 to the picture with neighbouring
blocks that can be coalesced, "patched" starts to diverge even more
from "unpatched" because it tracks the number of wide I/Os in
progress, not the number of single blocks.

So, IIUC this means (1) the patched code is more aggressive wrt
prefetching (because we prefetch more data overall, because master would
prefetch N pages and patched prefetches N ranges, each of which may be
multiple pages. And (2) it's not easy to quantify how much more
aggressive it is, because it depends on how we happen to coalesce the
pages into ranges.

Do I understand this correctly?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#50Melanie Plageman
melanieplageman@gmail.com
In reply to: Heikki Linnakangas (#48)
14 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Mar 14, 2024 at 03:32:04PM +0200, Heikki Linnakangas wrote:

On 14/03/2024 12:55, Dilip Kumar wrote:

On Thu, Mar 14, 2024 at 4:07 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

_SPI_execute_plan() has code to deal with the possibility that the
active snapshot is not set. That seems fishy; do we really support SPI
without any snapshot? I'm inclined to turn that into an error. I ran the
regression tests with an "Assert(ActiveSnapshotSet())" there, and
everything worked.

IMHO, we can call SPI_Connect() and SPI_Execute() from any C
extension, so I don't think there we can guarantee that the snapshot
must be set, do we?

I suppose, although the things you could do without a snapshot would be
pretty limited. The query couldn't access any tables. Could it even look up
functions in the parser? Not sure.

Maybe for now we can just handle this specific case to remove the
snapshot serializing for the BitmapHeapScan as you are doing in the
patch. After looking into the code your theory seems correct that we
are just copying the ActiveSnapshot while building the query
descriptor and from there we are copying into the Estate so logically
there should not be any reason for these two to be different.

Ok, committed that for now. Thanks for looking!

Attached v6 is rebased over your new commit. It also has the "fix" in
0010 which moves BitmapAdjustPrefetchIterator() back above
table_scan_bitmap_next_block(). I've also updated the Streaming Read API
commit (0013) to Thomas' v7 version from [1]/messages/by-id/CA+hUKGLJi+c5jB3j6UvkgMYHky-qu+LPCsiNahUGSa5Z4DvyVA@mail.gmail.com. This has the update that
we theorize should address some of the regressions in the bitmapheapscan
streaming read user in 0014.

- Melanie

[1]: /messages/by-id/CA+hUKGLJi+c5jB3j6UvkgMYHky-qu+LPCsiNahUGSa5Z4DvyVA@mail.gmail.com

Attachments:

v6-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From e05474410a9771479232f25b21f11222ccabcb21 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v6 01/14] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index e57a0b7ea31..e78d793f69c 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index ca548e44eb4..6d756001fdb 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v6-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From eb824b3cc826fc722ea07eeec45dfcd124aef88b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v6 02/14] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6d756001fdb..05cf610f9b4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -742,16 +752,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v6-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-diff; charset=us-asciiDownload
From 95e4f932bd9debe72d257498d5a61d289e3e5c76 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v6 03/14] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 123 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 100 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 34bc60f625f..e7bed84f75b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -951,6 +951,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1039,6 +1041,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1058,6 +1066,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 680a50bf8b1..c9b9b4c00f1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2122,6 +2123,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, and the bitmap entries don't need rechecking, and all tuples on
+	 * the page are visible to our transaction.
+	 */
+	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2234,6 +2253,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 05cf610f9b4..df382580ac1 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,11 +185,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual == NIL && node->ss.ps.plan->targetlist == NIL)
+				extra_flags |= SO_CAN_SKIP_FETCH;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	node->ss.ps.state->es_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	extra_flags);
 		}
 
 		node->initialized = true;
@@ -207,8 +211,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -228,32 +230,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -301,52 +278,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +476,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +528,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +598,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +607,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +651,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -740,8 +694,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +704,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f68593..3dfb19ec7d5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8249b37bbf1..c43a8b3dea5 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed.
+	 */
+	SO_CAN_SKIP_FETCH = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -944,9 +951,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 27614ab50fb..4e5aab8472f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1709,10 +1709,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1732,9 +1729,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v6-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-diff; charset=us-asciiDownload
From ed046b2ea088b8294aba1046086a9cf89c4224a7 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v6 04/14] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index df382580ac1..6a34f10646a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -470,15 +470,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
-
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -529,7 +523,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v6-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-diff; charset=us-asciiDownload
From 0f94cdd27e2b4a7550f93de2d59398d47392ae3c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v6 05/14] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6a34f10646a..61ffc8d0ee8 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -228,7 +228,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			if (!table_scan_bitmap_next_block(scan, tbmres))
 			{
@@ -337,7 +337,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -356,7 +356,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v6-0006-EXPLAIN-Bitmap-table-scan-also-count-no-visible-t.patchtext/x-diff; charset=us-asciiDownload
From 2a783e5ce456695ce5ab6da02eab151b655c9597 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 18:35:28 -0500
Subject: [PATCH v6 06/14] EXPLAIN Bitmap table scan also count no visible
 tuple pages

Previously, bitmap heap scans only counted lossy and exact pages for
explain when there was at least one visible tuple on the page.

heapam_scan_bitmap_next_block() returned true only if there was a
"valid" page with tuples to be processed. However, the lossy and exact
page counters in EXPLAIN should count the number of pages represented in
a lossy or non-lossy way in the constructed bitmap, regardless of
whether or not the pages ultimately contained visible tuples.
---
 src/backend/executor/nodeBitmapHeapscan.c     | 15 ++++++++++-----
 src/test/regress/expected/partition_prune.out |  4 +++-
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 61ffc8d0ee8..38b4596a775 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,6 +211,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
+		bool valid;
+
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -230,17 +232,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			if (!table_scan_bitmap_next_block(scan, tbmres))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
+			valid = table_scan_bitmap_next_block(scan, tbmres);
 
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
+			if (!valid)
+			{
+				/* AM doesn't think this block is valid, skip */
+				continue;
+			}
+
+
 			/* Adjust the prefetch target */
 			BitmapAdjustPrefetchTarget(node);
 		}
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index bf0657b9f2c..9c20a24982f 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -2848,6 +2848,7 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a;
                            Index Cond: (a = 1)
                ->  Bitmap Heap Scan on ab_a1_b3 ab_a1_3 (actual rows=0 loops=1)
                      Recheck Cond: (a = 1)
+                     Heap Blocks: exact=1
                      ->  Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1)
                            Index Cond: (a = 1)
          ->  Materialize (actual rows=1 loops=1)
@@ -2863,9 +2864,10 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a;
                                  Index Cond: (a = 1)
                      ->  Bitmap Heap Scan on ab_a1_b3 ab_3 (actual rows=0 loops=1)
                            Recheck Cond: (a = 1)
+                           Heap Blocks: exact=1
                            ->  Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1)
                                  Index Cond: (a = 1)
-(34 rows)
+(36 rows)
 
 table ab;
  a | b 
-- 
2.40.1

v6-0007-table_scan_bitmap_next_block-returns-lossy-or-exa.patchtext/x-diff; charset=us-asciiDownload
From 8a0ec9d8b58fb1b1aaa74254ebe046bd85cf5614 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v6 07/14] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c9b9b4c00f1..10c1c3b616b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,7 +2112,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2240,6 +2241,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 38b4596a775..08e346ae7b3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool valid;
+		bool valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -232,12 +232,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index c43a8b3dea5..f1d0d4b78e3 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -796,6 +796,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -811,7 +814,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1951,14 +1955,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1969,7 +1975,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.40.1

v6-0008-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-diff; charset=us-asciiDownload
From 466846b691f5cfd3928db6b6193699f5bbeb0b35 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v6 08/14] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 08e346ae7b3..248ff90904b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +202,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -221,9 +219,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v6-0009-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-diff; charset=us-asciiDownload
From 3734de02a94812b88317c873de5b46ab835de620 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v6 09/14] Remove table_scan_bitmap_next_tuple parameter tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 10c1c3b616b..a1ec50ab7a8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2248,7 +2248,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 248ff90904b..04ad14f70b3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -287,7 +287,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index f1d0d4b78e3..e35bd36e710 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -787,10 +787,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -821,15 +818,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -1988,7 +1980,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2000,7 +1991,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v6-0010-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 292a2c77fd967eacb34a669f13aa00bbc83d1a11 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v6 10/14] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 194 insertions(+), 150 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a1ec50ab7a8..e038e60cd8f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,18 +2112,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, and the bitmap entries don't need rechecking, and all tuples on
@@ -2142,16 +2175,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2243,7 +2267,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 04ad14f70b3..0924613b247 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +109,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +161,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -202,56 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -273,45 +232,59 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can validate that the prefetch block stays ahead of
+		 * the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		Assert(node->pstate == NULL ||
+			   node->prefetch_iterator == NULL ||
+			   node->pfblockno > node->blockno);
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -337,13 +310,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -357,14 +334,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -389,7 +369,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -467,6 +450,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -524,6 +508,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  !tbmpre->recheck &&
@@ -585,12 +571,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -598,13 +580,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -635,28 +617,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -689,8 +667,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -698,9 +674,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e35bd36e710..d214abeb201 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -780,19 +781,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -811,8 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -949,9 +945,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1011,6 +1011,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1021,6 +1036,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1944,19 +1974,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1966,8 +1994,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 4e5aab8472f..9ec7eaceeb7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1707,8 +1707,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1717,9 +1715,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1727,8 +1727,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1737,9 +1735,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v6-0011-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From e71b4d941eebc3fb4c8589c16004417c4a856844 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v6 11/14] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 29 +++++++----------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..d2bf8f44d50 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1467,8 +1453,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..432fae52962 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.40.1

v6-0012-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchtext/x-diff; charset=us-asciiDownload
From 562a1dd739dfef88c8dc392635b242c6ecc88af3 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v6 12/14] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 38 ++++++------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 7 files changed, 108 insertions(+), 91 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3aa457a29e1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..033d5253394 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e038e60cd8f..022753e203a 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,7 +2119,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2132,11 +2132,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		CHECK_FOR_INTERRUPTS();
 
 		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbm_iterate(scan->tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2151,11 +2151,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2163,19 +2163,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * the page are visible to our transaction.
 	 */
 	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2204,7 +2204,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2213,9 +2213,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2265,7 +2265,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	*lossy = tbmres.ntuples < 0;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 0924613b247..b3b9448627b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -320,7 +320,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -334,8 +334,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -370,8 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -439,10 +439,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
@@ -450,7 +452,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -459,13 +461,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -480,7 +482,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -499,8 +501,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_shared_iterate(prefetch_iterator);
@@ -508,17 +510,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index d2bf8f44d50..7d038c2018d 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..3b432263bb0 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae52962..f000c1af28f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.40.1

v6-0013-v7-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From 0ee4d860f46367a0eb005065a9df060564824f67 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:59:42 -0400
Subject: [PATCH v6 13/14] v7 Streaming Read API

---
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 659 +++++++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 642 +++++++++++++++-------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/include/storage/bufmgr.h             |  45 ++
 src/include/storage/streaming_read.h     |  52 ++
 src/tools/pgindent/typedefs.list         |   3 +
 10 files changed, 1227 insertions(+), 210 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca20..eec03f6f2b4 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 00000000000..bcab44c802f
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 00000000000..39aef2a84a2
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 00000000000..d5c29b750d9
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,659 @@
+#include "postgres.h"
+
+#include "catalog/pg_tablespace.h"
+#include "miscadmin.h"
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+#include "utils/spccache.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		need_wait;
+	bool		advice_issued;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index;
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+	ReadBuffersOperation operation;
+} PgStreamingReadRange;
+
+/*
+ * Streaming read object.
+ */
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			next_tail_buffer;
+	int			distance;
+	bool		started;
+	bool		finished;
+	bool		advice_enabled;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	/* Sometimes we need to buffer one block for flow control. */
+	BlockNumber unget_blocknum;
+	void	   *unget_per_buffer_data;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+	Oid			tablespace_id;
+
+	/*
+	 * Make sure our bmr's smgr and persistent are populated.  The caller
+	 * asserts that the storage manager will remain valid.
+	 */
+	if (!bmr.smgr)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	tablespace_id = bmr.smgr->smgr_rlocator.locator.spcOid;
+	if (!OidIsValid(MyDatabaseId) ||
+		(bmr.rel && IsCatalogRelation(bmr.rel)) ||
+		IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
+	{
+		/*
+		 * Avoid circularity while trying to look up tablespace settings or
+		 * before spccache.c is ready.
+		 */
+		max_ios = effective_io_concurrency;
+	}
+	else if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
+	else
+		max_ios = get_tablespace_io_concurrency(tablespace_id);
+
+	/*
+	 * Choose a maximum number of buffers we're prepared to pin.  We try to
+	 * pin fewer if we can, though.  We clamp it to at least
+	 * MAX_BUFFER_PER_TRANSFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/* Don't allow this backend to pin more than its share of buffers. */
+	if (SmgrIsTemp(bmr.smgr))
+		LimitAdditionalLocalPins(&max_pinned_buffers);
+	else
+		LimitAdditionalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+	pgsr->callback = next_block_cb;
+	pgsr->bmr = bmr;
+	pgsr->forknum = forknum;
+
+	pgsr->unget_blocknum = InvalidBlockNumber;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * Skip the initial ramp-up phase if the caller says we're going to be
+	 * reading the whole relation.  This way we start out doing full-sized
+	 * reads.
+	 */
+	if (flags & PGSR_FLAG_FULL)
+		pgsr->distance = Min(MAX_BUFFERS_PER_TRANSFER, pgsr->max_pinned_buffers);
+	else
+		pgsr->distance = 1;
+
+	/*
+	 * Space for the callback to store extra data along with each block.  Note
+	 * that we need one more than max_pinned_buffers, so we can return a
+	 * pointer to a slot that can't be overwritten until the next call.
+	 */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * size);
+
+	return pgsr;
+}
+
+/*
+ * Find the per-buffer data index for the Nth block of a range.
+ */
+static int
+get_per_buffer_data_index(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	int			result;
+
+	/*
+	 * Find slot in the circular buffer of per-buffer data, without using the
+	 * expensive % operator.
+	 */
+	result = range->per_buffer_data_index + n;
+	while (result >= pgsr->size)
+		result -= pgsr->size;
+	Assert(result == (range->per_buffer_data_index + n) % pgsr->size);
+
+	return result;
+}
+
+/*
+ * Return a pointer to the per-buffer data by index.
+ */
+static void *
+get_per_buffer_data_by_index(PgStreamingRead *pgsr, int per_buffer_data_index)
+{
+	return (char *) pgsr->per_buffer_data +
+		pgsr->per_buffer_data_size * per_buffer_data_index;
+}
+
+/*
+ * Return a pointer to the per-buffer data for the Nth block of a range.
+ */
+static void *
+get_per_buffer_data(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	return get_per_buffer_data_by_index(pgsr,
+										get_per_buffer_data_index(pgsr,
+																  range,
+																  n));
+}
+
+/*
+ * Start reading the head range, and create a new head range.  The new head
+ * range is returned.  It may not be empty, if StartReadBuffers() couldn't
+ * start the entire range; in that case the returned range contains the
+ * remaining portion of the range.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_start_head_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+	PgStreamingReadRange *new_head_range;
+	int			nblocks_pinned;
+	int			flags;
+
+	/* Caller should make sure we never exceed max_ios. */
+	Assert((pgsr->ios_in_progress < pgsr->max_ios) ||
+		   (pgsr->ios_in_progress == 0 && pgsr->max_ios == 0));
+
+	/* Should only call if the head range has some blocks to read. */
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If advice hasn't been suppressed, and this system supports it, this
+	 * isn't a strictly sequential pattern, then we'll issue advice.
+	 */
+	if (pgsr->advice_enabled &&
+		pgsr->max_ios > 0 &&
+		pgsr->started &&
+		head_range->blocknum != pgsr->seq_blocknum)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else
+		flags = 0;
+
+	/* Suppress advice on the first call, because it's too late to benefit. */
+	if (!pgsr->started)
+		pgsr->started = true;
+
+	/* We shouldn't be trying to pin more buffers that we're allowed to. */
+	Assert(pgsr->pinned_buffers + head_range->nblocks <= pgsr->max_pinned_buffers);
+
+	/* Start reading as many blocks as we can from the head range. */
+	nblocks_pinned = head_range->nblocks;
+	head_range->need_wait =
+		StartReadBuffers(pgsr->bmr,
+						 head_range->buffers,
+						 pgsr->forknum,
+						 head_range->blocknum,
+						 &nblocks_pinned,
+						 pgsr->strategy,
+						 flags,
+						 &head_range->operation);
+
+	Assert(pgsr->pinned_buffers <= pgsr->max_pinned_buffers);
+
+	if (head_range->need_wait && (flags & READ_BUFFERS_ISSUE_ADVICE))
+	{
+		/*
+		 * Since we've issued advice, we count an I/O in progress until we
+		 * call WaitReadBuffers().
+		 */
+		head_range->advice_issued = true;
+		pgsr->ios_in_progress++;
+		Assert(pgsr->ios_in_progress <= pgsr->max_ios);
+	}
+
+	/*
+	 * StartReadBuffers() might have pinned fewer blocks than we asked it to,
+	 * but always at least one.
+	 */
+	Assert(nblocks_pinned <= head_range->nblocks);
+	Assert(nblocks_pinned >= 1);
+	pgsr->pinned_buffers += nblocks_pinned;
+
+	/*
+	 * Remember where the next block would be after that, so we can detect
+	 * sequential access next time.
+	 */
+	pgsr->seq_blocknum = head_range->blocknum + nblocks_pinned;
+
+	/*
+	 * Create a new head range.  There must be space, because we have enough
+	 * elements for every range to hold just one block, up to the pin limit.
+	 */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	new_head_range = &pgsr->ranges[pgsr->head];
+	new_head_range->nblocks = 0;
+	new_head_range->advice_issued = false;
+
+	/*
+	 * If we didn't manage to start the whole read above, we split the range,
+	 * moving the remainder into the new head range.
+	 */
+	if (nblocks_pinned < head_range->nblocks)
+	{
+		int			nblocks_remaining = head_range->nblocks - nblocks_pinned;
+
+		head_range->nblocks = nblocks_pinned;
+
+		new_head_range->blocknum = head_range->blocknum + nblocks_pinned;
+		new_head_range->nblocks = nblocks_remaining;
+	}
+
+	/* The new range has per-buffer data starting after the previous range. */
+	new_head_range->per_buffer_data_index =
+		get_per_buffer_data_index(pgsr, head_range, nblocks_pinned);
+
+	return new_head_range;
+}
+
+/*
+ * Ask the callback which block it would like us to read next, with a small
+ * buffer in front to allow pg_streaming_unget_block() to work.
+ */
+static BlockNumber
+pg_streaming_get_block(PgStreamingRead *pgsr, void *per_buffer_data)
+{
+	BlockNumber result;
+
+	if (unlikely(pgsr->unget_blocknum != InvalidBlockNumber))
+	{
+		/*
+		 * If we had to unget a block, now it is time to return that one
+		 * again.
+		 */
+		result = pgsr->unget_blocknum;
+		pgsr->unget_blocknum = InvalidBlockNumber;
+
+		/*
+		 * The same per_buffer_data element must have been used, and still
+		 * contains whatever data the callback wrote into it.  So we just
+		 * sanity-check that we were called with the value that
+		 * pg_streaming_unget_block() pushed back.
+		 */
+		Assert(per_buffer_data == pgsr->unget_per_buffer_data);
+	}
+	else
+	{
+		/* Use the installed callback directly. */
+		result = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+	}
+
+	return result;
+}
+
+/*
+ * In order to deal with short reads in StartReadBuffers(), we sometimes need
+ * to defer handling of a block until later.  This *must* be called with the
+ * last value returned by pg_streaming_get_block().
+ */
+static void
+pg_streaming_unget_block(PgStreamingRead *pgsr, BlockNumber blocknum, void *per_buffer_data)
+{
+	Assert(pgsr->unget_blocknum == InvalidBlockNumber);
+	pgsr->unget_blocknum = blocknum;
+	pgsr->unget_per_buffer_data = per_buffer_data;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *range;
+
+	/* If we're finished, don't look ahead. */
+	if (pgsr->finished)
+		return;
+
+	/*
+	 * We we've already started the maximum allowed number of I/Os, don't look
+	 * ahead.  There is a special case for max_ios == 0.
+	 */
+	if (pgsr->max_ios > 0 && pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/* Can't pin any more buffers. */
+	if (pgsr->pinned_buffers == pgsr->distance)
+		return;
+
+	/*
+	 * Keep trying to add new blocks to the end of the head range while doing
+	 * so wouldn't exceed the distance limit.
+	 */
+	range = &pgsr->ranges[pgsr->head];
+	while (pgsr->pinned_buffers + range->nblocks < pgsr->distance)
+	{
+		BlockNumber blocknum;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		if (range->nblocks == lengthof(range->buffers))
+		{
+			/* Start as much of it as we can. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/* If we're now at the I/O limit, stop here. */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+				return;
+
+			/*
+			 * That might have only been partially started, but always
+			 * processes at least one so that'll do for now.
+			 */
+			Assert(range->nblocks < lengthof(range->buffers));
+		}
+
+		/* Find per-buffer data slot for the next block. */
+		per_buffer_data = get_per_buffer_data(pgsr, range, range->nblocks);
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pg_streaming_get_block(pgsr, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			/* End of stream. */
+			pgsr->finished = true;
+			break;
+		}
+
+		/*
+		 * Is there a head range that we cannot extend, because the requested
+		 * block is not consecutive?
+		 */
+		if (range->nblocks > 0 &&
+			range->blocknum + range->nblocks != blocknum)
+		{
+			/* Yes.  Start it, so we can begin building a new one. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * It's possible that it was only partially started, and we have a
+			 * new range with the remainder.  Keep starting I/Os until we get
+			 * it all out of the way, or we hit the I/O limit.
+			 */
+			while (range->nblocks > 0 && pgsr->ios_in_progress < pgsr->max_ios)
+				range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * We do have to worry about I/O capacity running out if the head
+			 * range was split.  In that case we have to 'unget' the block
+			 * returned by the callback.
+			 */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+			{
+				pg_streaming_unget_block(pgsr, blocknum, per_buffer_data);
+				return;
+			}
+		}
+
+		/* If we have a new, empty range, initialize the start block. */
+		if (range->nblocks == 0)
+			range->blocknum = blocknum;
+
+		/* This block extends the range by one. */
+		Assert(range->blocknum + range->nblocks == blocknum);
+		range->nblocks++;
+	};
+
+	/*
+	 * Normally we don't start the head range, preferring to give it a chance
+	 * to grow to full size once more buffers have been consumed.  In cases
+	 * where that can't possibly happen, we might as well start the read
+	 * immediately.
+	 */
+	if ((range->nblocks > 0 && pgsr->finished) ||
+		(range->nblocks == pgsr->distance))
+		pg_streaming_read_start_head_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	PgStreamingReadRange *tail_range;
+
+	for (;;)
+	{
+		if (pgsr->tail != pgsr->head)
+		{
+			tail_range = &pgsr->ranges[pgsr->tail];
+
+			/*
+			 * Do we need to wait for a ReadBuffers operation to finish before
+			 * returning the buffers in this range?
+			 */
+			if (tail_range->need_wait)
+			{
+				int			distance;
+
+				Assert(pgsr->next_tail_buffer == 0);
+				WaitReadBuffers(&tail_range->operation);
+				tail_range->need_wait = false;
+
+				/*
+				 * We don't really know if the kernel generated a physical I/O
+				 * when we issued advice, let alone when it finished, but it
+				 * has certainly finished now because we've performed the
+				 * read.
+				 */
+				if (tail_range->advice_issued)
+				{
+
+					Assert(pgsr->ios_in_progress > 0);
+					pgsr->ios_in_progress--;
+
+					/*
+					 * Look-ahead distance ramps up rapidly if we're issuing
+					 * advice, so we can search for new more I/Os to start.
+					 */
+					distance = pgsr->distance * 2;
+					distance = Min(distance, pgsr->max_pinned_buffers);
+					pgsr->distance = distance;
+				}
+				else
+				{
+					/*
+					 * There is no point in increasing look-ahead distance if
+					 * we've already reached the full I/O size, since we're
+					 * not issuing advice.  Extra distance would only pin more
+					 * buffers for no benefit.
+					 */
+					if (pgsr->distance > MAX_BUFFERS_PER_TRANSFER)
+					{
+						/*
+						 * Look-ahead distance gradually decays to full I/O
+						 * size.
+						 */
+						pgsr->distance--;
+					}
+					else
+					{
+						/*
+						 * Look-ahead distance ramps up rapidly, but not more
+						 * that the full I/O size.
+						 */
+						distance = pgsr->distance * 2;
+						distance = Min(distance, MAX_BUFFERS_PER_TRANSFER);
+						distance = Min(distance, pgsr->max_pinned_buffers);
+						pgsr->distance = distance;
+					}
+				}
+			}
+			else if (pgsr->next_tail_buffer == 0)
+			{
+				/* No I/O necessary. Look-ahead distance gradually decays. */
+				if (pgsr->distance > 1)
+					pgsr->distance--;
+			}
+
+			/* Are there more buffers available in this range? */
+			if (pgsr->next_tail_buffer < tail_range->nblocks)
+			{
+				int			buffer_index;
+				Buffer		buffer;
+
+				buffer_index = pgsr->next_tail_buffer++;
+				buffer = tail_range->buffers[buffer_index];
+
+				Assert(BufferIsValid(buffer));
+
+				/* We are giving away ownership of this pinned buffer. */
+				Assert(pgsr->pinned_buffers > 0);
+				pgsr->pinned_buffers--;
+
+				if (per_buffer_data)
+					*per_buffer_data = get_per_buffer_data(pgsr, tail_range, buffer_index);
+
+				/* We may be able to get another I/O started. */
+				pg_streaming_read_look_ahead(pgsr);
+
+				return buffer;
+			}
+
+			/* Advance tail to next range. */
+			if (++pgsr->tail == pgsr->size)
+				pgsr->tail = 0;
+			pgsr->next_tail_buffer = 0;
+		}
+		else
+		{
+			/*
+			 * If tail crashed into head, and head is not empty, then it is
+			 * time to start that range.  Otherwise, force a look-ahead, to
+			 * kick start the stream.
+			 */
+			Assert(pgsr->tail == pgsr->head);
+			if (pgsr->ranges[pgsr->head].nblocks > 0)
+			{
+				pg_streaming_read_start_head_range(pgsr);
+			}
+			else
+			{
+				pg_streaming_read_look_ahead(pgsr);
+
+				/* Finished? */
+				if (pgsr->tail == pgsr->head &&
+					pgsr->ranges[pgsr->head].nblocks == 0)
+					break;
+			}
+		}
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead. */
+	pgsr->finished = true;
+
+	/* Unpin anything that wasn't consumed. */
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	Assert(pgsr->pinned_buffers == 0);
+	Assert(pgsr->ios_in_progress == 0);
+
+	/* Release memory. */
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f0f8d4259c5..d0e9c7deffa 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -19,6 +19,11 @@
  *		and pin it so that no one can destroy it while this process
  *		is using it.
  *
+ * StartReadBuffers() -- as above, but for multiple contiguous blocks in
+ *		two steps.
+ *
+ * WaitReadBuffers() -- second step of StartReadBuffers().
+ *
  * ReleaseBuffer() -- unpin a buffer
  *
  * MarkBufferDirty() -- mark a pinned buffer's contents as "dirty".
@@ -471,10 +476,9 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
-								ReadBufferMode mode, BufferAccessStrategy strategy,
-								bool *hit);
+								ReadBufferMode mode, BufferAccessStrategy strategy);
 static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
 										   ForkNumber fork,
 										   BufferAccessStrategy strategy,
@@ -500,7 +504,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -781,7 +785,6 @@ Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
-	bool		hit;
 	Buffer		buf;
 
 	/*
@@ -794,15 +797,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
-							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+	buf = ReadBuffer_common(BMR_REL(reln),
+							forkNum, blockNum, mode, strategy);
+
 	return buf;
 }
 
@@ -822,13 +819,12 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 						  BlockNumber blockNum, ReadBufferMode mode,
 						  BufferAccessStrategy strategy, bool permanent)
 {
-	bool		hit;
-
 	SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
-							 mode, strategy, &hit);
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
+							 mode, strategy);
 }
 
 /*
@@ -994,35 +990,68 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 	 */
 	if (buffer == InvalidBuffer)
 	{
-		bool		hit;
-
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
-								   fork, extend_to - 1, mode, strategy,
-								   &hit);
+		buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
 	}
 
 	return buffer;
 }
 
+/*
+ * Zero a buffer and lock it, as part of the implementation of
+ * RBM_ZERO_AND_LOCK or RBM_ZERO_AND_CLEANUP_LOCK.  The buffer must be already
+ * pinned.  It does not have to be valid, but it is valid and locked on
+ * return.
+ */
+static void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * ReadBuffer_common -- common logic for all ReadBuffer variants
  *
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
-				  BufferAccessStrategy strategy, bool *hit)
+				  BufferAccessStrategy strategy)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	ReadBuffersOperation operation;
+	Buffer		buffer;
+	int			nblocks;
+	int			flags;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1041,181 +1070,405 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	nblocks = 1;
+	if (mode == RBM_ZERO_ON_ERROR)
+		flags = READ_BUFFERS_ZERO_ON_ERROR;
+	else
+		flags = 0;
+	if (StartReadBuffers(bmr,
+						 &buffer,
+						 forkNum,
+						 blockNum,
+						 &nblocks,
+						 strategy,
+						 flags,
+						 &operation))
+		WaitReadBuffers(&operation);
+	Assert(nblocks == 1);		/* single block can't be short */
+
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+		ZeroBuffer(buffer, mode);
+
+	return buffer;
+}
 
+static Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	Assert(bmr.smgr);
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * WaitReadBuffers() (so, not for hits, and not for buffers that are
+		 * zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+/*
+ * Begin reading a range of blocks beginning at blockNum and extending for
+ * *nblocks.  On return, up to *nblocks pinned buffers holding those blocks
+ * are written into the buffers array, and *nblocks is updated to contain the
+ * actual number, which may be fewer than requested.
+ *
+ * If false is returned, no I/O is necessary and WaitReadBuffers() is not
+ * necessary.  If true is returned, one I/O has been started, and
+ * WaitReadBuffers() must be called with the same operation object before the
+ * buffers are accessed.  Along with the operation object, the caller-supplied
+ * array of buffers must remain valid until WaitReadBuffers() is called.
+ *
+ * Currently the I/O is only started with optional operating system advice,
+ * and the real I/O happens in WaitReadBuffers().  In future work, true I/O
+ * could be initiated here.
+ */
+bool
+StartReadBuffers(BufferManagerRelation bmr,
+				 Buffer *buffers,
+				 ForkNumber forkNum,
+				 BlockNumber blockNum,
+				 int *nblocks,
+				 BufferAccessStrategy strategy,
+				 int flags,
+				 ReadBuffersOperation *operation)
+{
+	int			actual_nblocks = *nblocks;
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
 	}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+	operation->bmr = bmr;
+	operation->forknum = forkNum;
+	operation->blocknum = blockNum;
+	operation->buffers = buffers;
+	operation->nblocks = actual_nblocks;
+	operation->strategy = strategy;
+	operation->flags = flags;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	operation->io_buffers_len = 0;
 
-	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
-	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
-	else
+	for (int i = 0; i < actual_nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		bool		found;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+		buffers[i] = PrepareReadBuffer(bmr,
+									   forkNum,
+									   blockNum + i,
+									   strategy,
+									   &found);
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		if (found)
+		{
+			/*
+			 * Terminate the read as soon as we get a hit.  It could be a
+			 * single buffer hit, or it could be a hit that follows a readable
+			 * range.  We don't want to create more than one readable range,
+			 * so we stop here.
+			 */
+			actual_nblocks = operation->nblocks = *nblocks = i + 1;
+			break;
+		}
+		else
+		{
+			/* Extend the readable range to cover this block. */
+			operation->io_buffers_len++;
+		}
+	}
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+	if (operation->io_buffers_len > 0)
+	{
+		if (flags & READ_BUFFERS_ISSUE_ADVICE)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
-			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
-			}
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
+			/*
+			 * In theory we should only do this if PrepareReadBuffers() had to
+			 * allocate new buffers above.  That way, if two calls to
+			 * StartReadBuffers() were made for the same blocks before
+			 * WaitReadBuffers(), only the first would issue the advice.
+			 * That'd be a better simulation of true asynchronous I/O, which
+			 * would only start the I/O once, but isn't done here for
+			 * simplicity.  Note also that the following call might actually
+			 * issue two advice calls if we cross a segment boundary; in a
+			 * true asynchronous version we might choose to process only one
+			 * real I/O at a time in that case.
+			 */
+			smgrprefetch(bmr.smgr, forkNum, blockNum, operation->io_buffers_len);
 		}
+
+		/* Indicate that WaitReadBuffers() should be called. */
+		return true;
 	}
+	else
+	{
+		return false;
+	}
+}
 
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
+static inline bool
+WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
 	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
+
+void
+WaitReadBuffers(ReadBuffersOperation *operation)
+{
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	int			nblocks;
+	BlockNumber blocknum;
+	ForkNumber	forknum;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	/*
+	 * Currently operations are only allowed to include a read of some range,
+	 * with an optional extra buffer that is already pinned at the end.  So
+	 * nblocks can be at most one more than io_buffers_len.
+	 */
+	Assert((operation->nblocks == operation->io_buffers_len) ||
+		   (operation->nblocks == operation->io_buffers_len + 1));
 
+	/* Find the range of the physical read we need to perform. */
+	nblocks = operation->io_buffers_len;
+	if (nblocks == 0)
+		return;					/* nothing to do */
+
+	buffers = &operation->buffers[0];
+	blocknum = operation->blocknum;
+	forknum = operation->forknum;
+	bmr = operation->bmr;
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
-
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
 	}
 	else
 	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
+		io_context = IOContextForStrategy(operation->strategy);
+		io_object = IOOBJECT_RELATION;
 	}
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+	/*
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
+	 */
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
+	else
+		pgBufferUsage.shared_blks_read += nblocks;
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+	for (int i = 0; i < nblocks; ++i)
+	{
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!WaitReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
+
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   WaitReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
+		{
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
+			{
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
+			}
+			else
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
+
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
+
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
+
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
+
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
- * BufferAlloc -- subroutine for ReadBuffer.  Handles lookup of a shared
- *		buffer.  If no buffer exists already, selects a replacement
- *		victim and evicts the old page, but does NOT read in new page.
+ * BufferAlloc -- subroutine for StartReadBuffers.  Handles lookup of a shared
+ *		buffer.  If no buffer exists already, selects a replacement victim and
+ *		evicts the old page, but does NOT read in new page.
  *
  * "strategy" can be a buffer replacement strategy object, or NULL for
  * the default strategy.  The selected buffer's usage_count is advanced when
@@ -1223,11 +1476,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1286,19 +1535,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1363,19 +1603,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1407,15 +1638,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1769,7 +1994,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2034,7 +2259,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2057,7 +2282,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2372,7 +2597,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if StartReadBuffers() was called and
+		 * WaitReadBuffers() hasn't been called yet.  We'll check by loading
+		 * the flags without locking.  This is racy, but it's OK to return
+		 * false spuriously: when WaitReadBuffers() calls StartBufferIO(),
+		 * it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2381,7 +2611,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3449,7 +3679,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -5184,9 +5414,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5199,6 +5435,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index fcfac335a57..985a2c7049c 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -108,10 +108,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -287,7 +286,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -297,9 +296,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca27..739d13293fb 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d3353..b57f71f97e3 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,42 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+
+#define READ_BUFFERS_ZERO_ON_ERROR 0x01
+#define READ_BUFFERS_ISSUE_ADVICE 0x02
+
+/*
+ * Private state used by StartReadBuffers() and WaitReadBuffers().  Declared
+ * in public header only to allow inclusion in other structs, but contents
+ * should not be accessed.
+ */
+struct ReadBuffersOperation
+{
+	/* Parameters passed in to StartReadBuffers(). */
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	ForkNumber	forknum;
+	BlockNumber blocknum;
+	int			nblocks;
+	BufferAccessStrategy strategy;
+	int			flags;
+
+	/* Range of buffers, if we need to perform a read. */
+	int			io_buffers_len;
+};
+
+typedef struct ReadBuffersOperation ReadBuffersOperation;
+
+extern bool StartReadBuffers(BufferManagerRelation bmr,
+							 Buffer *buffers,
+							 ForkNumber forknum,
+							 BlockNumber blocknum,
+							 int *nblocks,
+							 BufferAccessStrategy strategy,
+							 int flags,
+							 ReadBuffersOperation *operation);
+extern void WaitReadBuffers(ReadBuffersOperation *operation);
+
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -250,6 +292,9 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 00000000000..c4d3892bb26
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,52 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+/*
+ * We usually ramp up from smaller reads to larger ones, to support users who
+ * don't know if it's worth reading lots of buffers yet.  This flag disables
+ * that, declaring ahead of time that we'll be reading all available buffers.
+ */
+#define PGSR_FLAG_FULL 0x04
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index aa7a25b8f8c..8b5c2a1576d 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2099,6 +2099,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
@@ -2269,6 +2271,7 @@ ReInitializeDSMForeignScan_function
 ReScanForeignScan_function
 ReadBufPtrType
 ReadBufferMode
+ReadBuffersOperation
 ReadBytePtrType
 ReadExtraTocPtrType
 ReadFunc
-- 
2.40.1

v6-0014-BitmapHeapScan-uses-streaming-read-API.patchtext/x-diff; charset=us-asciiDownload
From 42475042baa09b3fd3ddb8f39f7a6304c49449de Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:04:18 -0500
Subject: [PATCH v6 14/14] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
---
 src/backend/access/heap/heapam.c          |  68 +++++
 src/backend/access/heap/heapam_handler.c  |  88 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 352 +---------------------
 src/include/access/heapam.h               |   4 +
 src/include/access/tableam.h              |  22 +-
 src/include/nodes/execnodes.h             |  22 --
 6 files changed, 116 insertions(+), 440 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index e7bed84f75b..0f370bfec3e 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -111,6 +111,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -331,6 +333,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -951,6 +969,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
 
@@ -1089,6 +1108,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10246,3 +10268,49 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (hdesc->rs_base.shared_tbmiterator)
+			tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+		else
+			tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 022753e203a..9727613e87f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2111,79 +2111,65 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck, bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (scan->shared_tbmiterator)
-			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
-		else
-			tbm_iterate(scan->tbmiterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, and the bitmap entries don't need rechecking, and all tuples on
-	 * the page are visible to our transaction.
-	 */
-	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2204,7 +2190,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2213,9 +2199,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2265,7 +2251,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres.ntuples < 0;
+	*lossy = tbmres->ntuples < 0;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b3b9448627b..c437718f980 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -86,14 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -109,15 +97,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
 		}
 		else
 		{
@@ -140,20 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
 
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
@@ -161,14 +126,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -212,37 +169,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -264,27 +190,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		}
 
 new_page:
-
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy))
 			break;
 
 		if (lossy)
 			node->lossy_pages++;
 		else
 			node->exact_pages++;
-
-		/*
-		 * If serial, we can validate that the prefetch block stays ahead of
-		 * the current block.
-		 */
-		Assert(node->pstate == NULL ||
-			   node->prefetch_iterator == NULL ||
-			   node->pfblockno > node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -308,225 +220,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -572,23 +265,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -627,16 +309,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -669,18 +345,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -720,13 +389,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -803,14 +465,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -841,11 +499,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3dfb19ec7d5..1cad9c04f01 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d214abeb201..5a963f9293f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -792,23 +792,11 @@ typedef struct TableAmRoutine
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+	bool		(*scan_bitmap_next_block) (TableScanDesc scan, bool *recheck,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1983,8 +1971,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+table_scan_bitmap_next_block(TableScanDesc scan, bool *recheck, bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1994,8 +1981,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, lossy);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 9ec7eaceeb7..6a48f583d7c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1682,11 +1682,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1694,10 +1691,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1707,19 +1701,11 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1727,19 +1713,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

#51Thomas Munro
thomas.munro@gmail.com
In reply to: Tomas Vondra (#49)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Mar 15, 2024 at 3:18 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

So, IIUC this means (1) the patched code is more aggressive wrt
prefetching (because we prefetch more data overall, because master would
prefetch N pages and patched prefetches N ranges, each of which may be
multiple pages. And (2) it's not easy to quantify how much more
aggressive it is, because it depends on how we happen to coalesce the
pages into ranges.

Do I understand this correctly?

Yes.

Parallelism must prevent coalescing here though. Any parallel aware
executor node that allocates block numbers to workers without trying
to preserve ranges will. That not only hides the opportunity to
coalesce reads, it also makes (globally) sequential scans look random
(ie locally they are more random), so that our logic to avoid issuing
advice for sequential scan won't work, and we'll inject extra useless
or harmful (?) fadvise calls. I don't know what to do about that yet,
but it seems like a subject for future research. Should we recognise
sequential scans with a window (like Linux does), instead of strictly
next-block detection (like some other OSes do)? Maybe a shared
streaming read that all workers pull blocks from, so it can see what's
going on? I think the latter would be strictly more like what the ad
hoc BHS prefetching code in master is doing, but I don't know if it'd
be over-engineering, or hard to do for some reason.

Another aspect of per-backend streaming reads in one parallel query
that don't know about each other is that they will all have their own
effective_io_concurrency limit. That is a version of a problem that
comes up again and again in parallel query, to be solved by the grand
unified resource control system of the future.

#52Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#50)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/14/24 19:16, Melanie Plageman wrote:

On Thu, Mar 14, 2024 at 03:32:04PM +0200, Heikki Linnakangas wrote:

...

Ok, committed that for now. Thanks for looking!

Attached v6 is rebased over your new commit. It also has the "fix" in
0010 which moves BitmapAdjustPrefetchIterator() back above
table_scan_bitmap_next_block(). I've also updated the Streaming Read API
commit (0013) to Thomas' v7 version from [1]. This has the update that
we theorize should address some of the regressions in the bitmapheapscan
streaming read user in 0014.

Should I rerun the benchmarks with these new patches, to see if it
really helps with the regressions?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#53Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#52)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Mar 14, 2024 at 5:26 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/14/24 19:16, Melanie Plageman wrote:

On Thu, Mar 14, 2024 at 03:32:04PM +0200, Heikki Linnakangas wrote:

...

Ok, committed that for now. Thanks for looking!

Attached v6 is rebased over your new commit. It also has the "fix" in
0010 which moves BitmapAdjustPrefetchIterator() back above
table_scan_bitmap_next_block(). I've also updated the Streaming Read API
commit (0013) to Thomas' v7 version from [1]. This has the update that
we theorize should address some of the regressions in the bitmapheapscan
streaming read user in 0014.

Should I rerun the benchmarks with these new patches, to see if it
really helps with the regressions?

That would be awesome!

I will soon send out a summary of what we investigated off-list about
0010 (though we didn't end up concluding anything). My "fix" (leaving
BitmapAdjustPrefetchIterator() above table_scan_bitmap_next_block())
eliminates the regression in 0010 on the one example that I repro'd
upthread, but it would be good to know if it eliminates the
regressions across some other tests.

I think it would be worthwhile to run the subset of tests which seemed
to fare the worst on 0010 against the patches 0001-0010-- cyclic
uncached on your xeon machine with 4 parallel workers, IIRC -- even
the 1 million scale would do the trick, I think.

And then separately run the subset of tests which seemed to do the
worst on 0014. There were several groups of issues across the
different tests, but I think that the uniform pages data test would be
relevant to use. It showed the regressions with eic 0.

As for the other regressions showing with 0014, I think we would want
to see at least one with fully-in-shared-buffers and one with fully
uncached. Some of the fixes were around pinning fewer buffers when the
blocks were already in shared buffers.

- Melanie

#54Andres Freund
andres@anarazel.de
In reply to: Melanie Plageman (#53)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2024-03-14 17:39:30 -0400, Melanie Plageman wrote:

I will soon send out a summary of what we investigated off-list about
0010 (though we didn't end up concluding anything). My "fix" (leaving
BitmapAdjustPrefetchIterator() above table_scan_bitmap_next_block())
eliminates the regression in 0010 on the one example that I repro'd
upthread, but it would be good to know if it eliminates the
regressions across some other tests.

I spent a good amount of time looking into this with Melanie. After a bunch of
wrong paths I think I found the issue: We end up prefetching blocks we have
already read. Notably this happens even as-is on master - just not as
frequently as after moving BitmapAdjustPrefetchIterator().

From what I can tell the prefetching in parallel bitmap heap scans is
thoroughly broken. I added some tracking of the last block read, the last
block prefetched to ParallelBitmapHeapState and found that with a small
effective_io_concurrency we end up with ~18% of prefetches being of blocks we
already read! After moving the BitmapAdjustPrefetchIterator() to rises to 86%,
no wonder it's slower...

The race here seems fairly substantial - we're moving the two iterators
independently from each other, in multiple processes, without useful locking.

I'm inclined to think this is a bug we ought to fix in the backbranches.

Greetings,

Andres Freund

#55Melanie Plageman
melanieplageman@gmail.com
In reply to: Andres Freund (#54)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Mar 15, 2024 at 5:14 PM Andres Freund <andres@anarazel.de> wrote:

Hi,

On 2024-03-14 17:39:30 -0400, Melanie Plageman wrote:

I will soon send out a summary of what we investigated off-list about
0010 (though we didn't end up concluding anything). My "fix" (leaving
BitmapAdjustPrefetchIterator() above table_scan_bitmap_next_block())
eliminates the regression in 0010 on the one example that I repro'd
upthread, but it would be good to know if it eliminates the
regressions across some other tests.

I spent a good amount of time looking into this with Melanie. After a bunch of
wrong paths I think I found the issue: We end up prefetching blocks we have
already read. Notably this happens even as-is on master - just not as
frequently as after moving BitmapAdjustPrefetchIterator().

From what I can tell the prefetching in parallel bitmap heap scans is
thoroughly broken. I added some tracking of the last block read, the last
block prefetched to ParallelBitmapHeapState and found that with a small
effective_io_concurrency we end up with ~18% of prefetches being of blocks we
already read! After moving the BitmapAdjustPrefetchIterator() to rises to 86%,
no wonder it's slower...

The race here seems fairly substantial - we're moving the two iterators
independently from each other, in multiple processes, without useful locking.

I'm inclined to think this is a bug we ought to fix in the backbranches.

Thinking about how to fix this, perhaps we could keep the current max
block number in the ParallelBitmapHeapState and then when prefetching,
workers could loop calling tbm_shared_iterate() until they've found a
block at least prefetch_pages ahead of the current block. They
wouldn't need to read the current max value from the parallel state on
each iteration. Even checking it once and storing that value in a
local variable prevented prefetching blocks after reading them in my
example repro of the issue.

- Melanie

#56Andres Freund
andres@anarazel.de
In reply to: Melanie Plageman (#55)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2024-03-15 18:42:29 -0400, Melanie Plageman wrote:

On Fri, Mar 15, 2024 at 5:14 PM Andres Freund <andres@anarazel.de> wrote:

On 2024-03-14 17:39:30 -0400, Melanie Plageman wrote:
I spent a good amount of time looking into this with Melanie. After a bunch of
wrong paths I think I found the issue: We end up prefetching blocks we have
already read. Notably this happens even as-is on master - just not as
frequently as after moving BitmapAdjustPrefetchIterator().

From what I can tell the prefetching in parallel bitmap heap scans is
thoroughly broken. I added some tracking of the last block read, the last
block prefetched to ParallelBitmapHeapState and found that with a small
effective_io_concurrency we end up with ~18% of prefetches being of blocks we
already read! After moving the BitmapAdjustPrefetchIterator() to rises to 86%,
no wonder it's slower...

The race here seems fairly substantial - we're moving the two iterators
independently from each other, in multiple processes, without useful locking.

I'm inclined to think this is a bug we ought to fix in the backbranches.

Thinking about how to fix this, perhaps we could keep the current max
block number in the ParallelBitmapHeapState and then when prefetching,
workers could loop calling tbm_shared_iterate() until they've found a
block at least prefetch_pages ahead of the current block. They
wouldn't need to read the current max value from the parallel state on
each iteration. Even checking it once and storing that value in a
local variable prevented prefetching blocks after reading them in my
example repro of the issue.

That would address some of the worst behaviour, but it doesn't really seem to
address the underlying problem of the two iterators being modified
independently. ISTM the proper fix would be to protect the state of the
iterators with a single lock, rather than pushing down the locking into the
bitmap code. OTOH, we'll only need one lock going forward, so being economic
in the effort of fixing this is also important.

Greetings,

Andres Freund

#57Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Andres Freund (#56)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/16/24 20:12, Andres Freund wrote:

Hi,

On 2024-03-15 18:42:29 -0400, Melanie Plageman wrote:

On Fri, Mar 15, 2024 at 5:14 PM Andres Freund <andres@anarazel.de> wrote:

On 2024-03-14 17:39:30 -0400, Melanie Plageman wrote:
I spent a good amount of time looking into this with Melanie. After a bunch of
wrong paths I think I found the issue: We end up prefetching blocks we have
already read. Notably this happens even as-is on master - just not as
frequently as after moving BitmapAdjustPrefetchIterator().

From what I can tell the prefetching in parallel bitmap heap scans is
thoroughly broken. I added some tracking of the last block read, the last
block prefetched to ParallelBitmapHeapState and found that with a small
effective_io_concurrency we end up with ~18% of prefetches being of blocks we
already read! After moving the BitmapAdjustPrefetchIterator() to rises to 86%,
no wonder it's slower...

The race here seems fairly substantial - we're moving the two iterators
independently from each other, in multiple processes, without useful locking.

I'm inclined to think this is a bug we ought to fix in the backbranches.

Thinking about how to fix this, perhaps we could keep the current max
block number in the ParallelBitmapHeapState and then when prefetching,
workers could loop calling tbm_shared_iterate() until they've found a
block at least prefetch_pages ahead of the current block. They
wouldn't need to read the current max value from the parallel state on
each iteration. Even checking it once and storing that value in a
local variable prevented prefetching blocks after reading them in my
example repro of the issue.

That would address some of the worst behaviour, but it doesn't really seem to
address the underlying problem of the two iterators being modified
independently. ISTM the proper fix would be to protect the state of the
iterators with a single lock, rather than pushing down the locking into the
bitmap code. OTOH, we'll only need one lock going forward, so being economic
in the effort of fixing this is also important.

Can you share some details about how you identified the problem, counted
the prefetches that happen too late, etc? I'd like to try to reproduce
this to understand the issue better.

If I understand correctly, what may happen is that a worker reads blocks
from the "prefetch" iterator, but before it manages to issue the
posix_fadvise, some other worker already did pread. Or can the iterators
get "out of sync" in a more fundamental way?

If my understanding is correct, why would a single lock solve that? Yes,
we'd advance the iterators at the same time, but surely we'd not issue
the fadvise calls while holding the lock, and the prefetch/fadvise for a
particular block could still happen in different workers.

I suppose a dirty PoC fix should not be too difficult, and it'd allow us
to check if it works.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#58Andres Freund
andres@anarazel.de
In reply to: Tomas Vondra (#57)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2024-03-16 21:25:18 +0100, Tomas Vondra wrote:

On 3/16/24 20:12, Andres Freund wrote:

That would address some of the worst behaviour, but it doesn't really seem to
address the underlying problem of the two iterators being modified
independently. ISTM the proper fix would be to protect the state of the
iterators with a single lock, rather than pushing down the locking into the
bitmap code. OTOH, we'll only need one lock going forward, so being economic
in the effort of fixing this is also important.

Can you share some details about how you identified the problem, counted
the prefetches that happen too late, etc? I'd like to try to reproduce
this to understand the issue better.

There's two aspects. Originally I couldn't reliably reproduce the regression
with Melanie's repro on my laptop. I finally was able to do so after I
a) changed the block device's read_ahead_kb to 0
b) used effective_io_concurrency=1

That made the difference between the BitmapAdjustPrefetchIterator() locations
very significant, something like 2.3s vs 12s.

Besides a lot of other things, I finally added debugging fprintfs printing the
pid, (prefetch, read), block number. Even looking at tiny excerpts of the
large amount of output that generates shows that two iterators were out of
sync.

If I understand correctly, what may happen is that a worker reads blocks
from the "prefetch" iterator, but before it manages to issue the
posix_fadvise, some other worker already did pread. Or can the iterators
get "out of sync" in a more fundamental way?

I agree that the current scheme of two shared iterators being used has some
fairly fundamental raciness. But I suspect there's more than that going on
right now.

Moving BitmapAdjustPrefetchIterator() to later drastically increases the
raciness because it means table_scan_bitmap_next_block() happens between
increasing the "real" and the "prefetch" iterators.

An example scenario that, I think, leads to the iterators being out of sync,
without there being races between iterator advancement and completing
prefetching:

start:
real -> block 0
prefetch -> block 0
prefetch_pages = 0
prefetch_target = 1

W1: tbm_shared_iterate(real) -> block 0
W2: tbm_shared_iterate(real) -> block 1
W1: BitmapAdjustPrefetchIterator() -> tbm_shared_iterate(prefetch) -> 0
W2: BitmapAdjustPrefetchIterator() -> tbm_shared_iterate(prefetch) -> 1
W1: read block 0
W2: read block 1
W1: BitmapPrefetch() -> prefetch_pages++ -> 1, tbm_shared_iterate(prefetch) -> 2, prefetch block 2
W2: BitmapPrefetch() -> nothing, as prefetch_pages == prefetch_target

W1: tbm_shared_iterate(real) -> block 2
W2: tbm_shared_iterate(real) -> block 3

W2: BitmapAdjustPrefetchIterator() -> prefetch_pages--
W2: read block 3
W2: BitmapPrefetch() -> prefetch_pages++, tbm_shared_iterate(prefetch) -> 3, prefetch block 3

So afaict here we end up prefetching a block that the *same process* just had
read.

ISTM that the idea of somehow "catching up" in BitmapAdjustPrefetchIterator(),
separately from advancing the "real" iterator, is pretty ugly for non-parallel
BHS and just straight up broken in the parallel case.

Greetings,

Andres Freund

#59Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#53)
4 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/14/24 22:39, Melanie Plageman wrote:

On Thu, Mar 14, 2024 at 5:26 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/14/24 19:16, Melanie Plageman wrote:

On Thu, Mar 14, 2024 at 03:32:04PM +0200, Heikki Linnakangas wrote:

...

Ok, committed that for now. Thanks for looking!

Attached v6 is rebased over your new commit. It also has the "fix" in
0010 which moves BitmapAdjustPrefetchIterator() back above
table_scan_bitmap_next_block(). I've also updated the Streaming Read API
commit (0013) to Thomas' v7 version from [1]. This has the update that
we theorize should address some of the regressions in the bitmapheapscan
streaming read user in 0014.

Should I rerun the benchmarks with these new patches, to see if it
really helps with the regressions?

That would be awesome!

OK, here's a couple charts comparing the effect of v6 patches to master.
These are from 1M and 10M data sets, same as the runs presented earlier
in this thread (the 10M is still running, but should be good enough for
this kind of visual comparison).

I have results for individual patches, but 0001-0013 behave virtually
the same, so the charts show only 0012 and 0014 (vs master).

Instead of a table with color scale (used before), I used simple scatter
plots as a more compact / concise visualization. It's impossible to
identify patterns (e.g. serial vs. parallel runs), but for the purpose
of this comparison that does not matter.

And then I'll use a chart plotting "relative" time compared to master (I
find it easier to judge the relative difference than with scatter plot).

1) absolute-all - all runs (scatter plot)

2) absolute-optimal - runs where the planner would pick bitmapscan

3) relative-all - all runs (duration relative to master)

4) relative-optimal - relative, runs where bitmapscan would be picked

The 0012 results are a pretty clear sign the "refactoring patches"
behave exactly the same as master. There are a couple outliers (in
either direction), but I'd attribute those to random noise and too few
runs to smooth it out for a particular combination (especially for 10M).

What is even more obvious is that 0014 behaves *VERY* differently. I'm
not sure if this is a good thing or a problem is debatable/unclear. I'm
sure we don't want to cause regressions, but perhaps those are due to
the prefetch issue discussed elsewhere in this thread (identified by
Andres and Melanie). There are also many cases that got much faster, but
the question is whether this is due to better efficiency or maybe the
new code being more aggressive in some way (not sure).

It's however interesting the differences are way more significant (both
in terms of frequency and scale) on the older machine with SATA SSDs.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

relative-optimal.pngimage/png; name=relative-optimal.pngDownload
�PNG


IHDR��� �L9tEXtSoftwareMatplotlib version3.8.3, https://matplotlib.org/��XS	pHYs��7���IDATx���y|\w}/��d��lK��$8N��I�L ta1����4�7�[�������D�){��-4|����5e/������bbH�$'v��8���d[����l��$iF���x����gf�f��u>�}�*�J%�	�Q��T p��8a����RWW�e����6X�lY�����O}��C�������K]]]��@
��$���~5uuuy���\�����>����������j&��j8��}�kI���E��}�S���M��$O{���z�G>��illLKK�����j\___���o$I^��Vy4�������FK�q7�pCv�����;/��sN�����$�<����K_���\�2.Lccc�:����e/�~��	�;������
�$�����g=�Yy�#�3f��xG��_���>G�?����_�U�zU�.]����,Y�$�}�ks�]wu��r9�{��r���f���ill���K�����y����r�<����_�j���n������=�yY�hQf���E��y�{^�����w^��W���.�x�+R�T�O��Oy������g���y�����}�sC~��"���d���w����m��u����h�����������<�����9sr�Yg�O��Os�}�
���;���_��,_�<���9��3s�e����k����C����|^���g��U9��S�����O?=/z���q����p��2$I���!�|�;�$����?~���;���w������_����>�gV��]v�e��?����,X� 3f�����}�{y�^����477�����������<6l�����3�8�w���o���~z{{�$�f���y��}��l��=7�xcf��=p�`����}��}y��_����'If���������3���7��o~3�\rI>��Og��YG]�%�\���������s��������w�����������9s�d��E��kW����y�������������y�y����?��l��=������s��w�����w����p�
�����\t�E����3�����e��m��?�o�1�6m��_����W�2��p����9sfv����}�k������.�,��F5^�/3�H��~��y�������y����k�����7���y���$y����o�y�����(������5��{ov���={���E�����<��O�m���|0{�������������;mmmC~���}z{{��g=+[�l��}���d�����O�w���Y�l�������,���/�x��<��O����mo����SWW�+��"��v����;w�mo{[�����|��������_�j���/���~wx�����+��{o��O�4I��O~2�����v���s�=�����$������s�=���t��Q=�7��
9��S��� ��������?����;7��v[��������~�����?�i:;;������������_�O~��C�{�I'�MozS����twwg�����gO����������Y�r�UW��_�����4V����K+I*�~������O~���r�Yg����y���^IRIRy��x��}�{�������{���Q�w~�w*}}}C~�C�P%Ie��9�������{������{tOp����V�T^�������o�^�9sf%I���m�����o�$���5k�����p�y]q������?�����p�����{�m����$�������Yg�UIR��'?9����_�hQe���Cn���+���G?����3�>�PIRy�3�q�q����Qw�������s���$�u�]7��=c�����o���z���6l�����{�����������y��;v�(|<��dF���K_�R8����\~������������������_�����3gN���7
{�_��_'Iv���o����h������'�<���~�����7�1


G��-��2���������+}}}��}��;�����7�)����`�����\�r��5I����O���>��<����������a~����{��]��3gN���g$I���������s��7f��}'<����;7�tS���c�~��&I.����~�G:�����'<����	Ox�Q��s���%K���E8Z+�E�
���/<�}x��ao���{����=��[���O>93g���W�X����U���0����$��W��K.�d���I2��466���n�/��={&|l�'�f�g��_�����?�����y�^����'y����w����={v.������/��_��,\�p�c�����J���<�9���>�_��WI2��G��������g��������0���x�9p��������+k������~�����s����.}}}��sg�d��=9��S���&�p ��^��W���7O�����?=�P:;;s�����{������Um|���U{��8��3���8����?��?����<x0�_}���������w���Q�w��d8���K.�����j��l��!>�`���������T*U-�����'�tR����=s��r�{���
#��3�{zz���8�>����:�3f���~�@���������{���r��w�e/{Y������={D�����w�����9s���h��p�@���,���������D��P������w�����|��v&-o��&3���m��$�z���
���;���DiTN:����?�#�x��5�$�Z���e/�����$9�+|��-#���7f��}y�S�r�������v�a�����z���tww{�/~���������_H�Vg��o'��z�Q����6@m�����$��������!�o��9����&zX#v���f��9I�/}�KCn?x�`��[7.�}�����+�u=��d^���i\��{���3g���'��;�}��o�&����5kV~��~o�����7�����=�yO�d���y�3�y�m�Z����o���{o����!�o��=���&zXLrw��g=+3f���]������h�o��|�_������^�����o�&_��������y��_�[n�e\��n����������m����&94���n��_��$�.Nz����h���
�$/x��4�3�8#ox��$W^ye�������w��W\�����I�7���Y�x���iii������[�.]]]I��;w�
oxC>��O'I����!m|���$9���xmi���O~r����J�����������$}}}������=�i�����(�l���s������$�����,Y�$,HSSS��]��������n���~�����sKKKJ�R������_���=��-[��7�1+V�HcccN9����=;Oz���e����??����F|��M�6e���y�c�e���y\�7������T*y�����O>9.��'�<0;��K.��������E/zQ~��?o{��r�I'e���y�#1�=���/�����
��?��?Lccc~��_��3��i���e��e��e��+?ZZZf�_s�5y������455�9�yN:;;��O~���`�����,��|�3y���9s�d���9�������-7�|sN?��j���,Y�o�1�y�kzr755��/y~��g������^xa���/���}�����SN��>�����Z�*oy�[r�m��)Oy�����N��/|�	�m���Y�~}���/���.��'������|��������/9����2k��c�����|>����q�{\8�y����~�����|&�����m�s�9��{��^^����SO�����;��#w�qG8pB��(���o~��y�������8p g�qF�������O~��+WV{�L2u�Z��LSg�uV������G?�\P�1�����?�����a>��OUe0���5���o��w��3�<�ja;063�=�������������$$p���'>1O|��=`����h*�w(��
 p���w(��`����>�U�V����7�������S�L=w����?,��0����n�������;7��{n�������}�����/��e�RWW��~�����7���<��O�I'��G<������}���xZpB�{-?��>��������������&�;����<����3������+������,���/Ft{�<��O�g?��,Y�d��;;;����5��mKGGG����������`��Z���w������Y�r��?'�Z#p'��-�{���\p��?~���g����N���-o�Yg������X�"��o��$����s�E���3MMMijj���^�$������������x���[����{����G<�Y�h��Y$��������Y�`A.����p�
����;/}�K�`���J�\s�5�|^�\sM����\q�ill������^�:���gGt��������y�S�����!���^��>��ijj��y��������s���Q��0vj�����.���\q�Y�p�^m��E�0�>����s��\�����v�i�?���$I������n����������?��ttt���O����������tww�)OyJn������/�[����w�})������������~��s�����������7�9���/�$6l�����|�S���]������?�������$�g���wg�����w���|�3�|N��rK��Gg��Y?[�jUn����>Z�6m�y����3g���`,��Co�/~��y������|��0�����_���J���;7�{�����}/��o�����;�x�#R__�����WJ��a3U����},��������^f��������o������rJ.�����5+O{���l��l��9Ir��W��o~s.�����1#/y�KR*��a�����e���y�{�����O�����c>����!}),X�����>7�|s����������N�Z~�������o~s����iD������������E��������+�w�G?��iii������4;w�<�z�����s�9G�}��E�-��7o�(��uk����e���m��9w�uWv���}��6������kN�mjjJ�455���������Lss��n�-[����.�?��?���|��~N�Z~�����7�9�~����|�:�;�8���;���_�*��������w�3��Lx�����;�y�cR�T�$3f�h>����P�h,]�4W]uUv��=���={r�����SN��Y���w�9���<�)��vww'I�?����g?������y���"�����eK~�w7���8u&�Z~������|'��s�)���SN���_�������������LFw�q���~4?����w�����o�S���<���������������D~������E�����_��W?{�k_������W�����3?��F4�K/�4������(�J%=�P����d�������K_����_�uv������;�������>��Y�pa�������76l���������=Iz{{����J��������'}}}I���������=��+_����P$���k������[�y��l��9Ox���7�9��GG��Lvw�q��W�*�\rI-Z����+������<�9�����r���~�����~�'=�I���G=*�~���b��,X� �]w].���|�K_�{���,\�0��w^6m�4�1<�����W^�����9����|����?�C<�$���?�����u�Yy����?��?8��f������������
oxC��_�5g�}��n��s����w�������3gN>���&I>�������_��_v
���:0������O;��,Y�d����������SN�k0��U��{�P��-������E/zQ����Z��2�
 p�h)0�
 p���3��������%K�9�	[�n����\�������`r��>����Yu���������d.i���y���T9p_�dIn���jj��+&M����`�(�{�n�������)��8"�zV�X1������)����8���imm��8��V*5
�a����J�R�!L����j
1���dd��������m�����je�444d����5kV��c2��dd�������m[����l��i1��R�������m����Z����L�:>y-/p�**�Jz{{�l����1����uuu9����s��T*�i�s��1��d����yE�I�-t�n���i:��#y�w��'<�	�^�lY��Gg��UY�jU�l�R��GS�u��2L{?��[�����%K�Ti4�H�b/p`R)�{��������J���s���9p�@!��Wt-_�u���I�\���u;�������??�J%�}�s��w�#�f�*�1`:��Z��x=��4��{�$��7�\�k��67�|s�������?�>��������k���0i��*�;:z[.���K�$����k^���p�
�?L7�]��J���F��������p��g�����e���������������>LG�Y��R/p`R)���o{��{��y�K^�����/��[����������f�j�Z���L{H����f����0"�X����@�P�;@��@�P�;@����y���s�9�������;��;������y����>��y�k^����'I����<�	O������>�����{�$�x�;����y�3����>;o{�����`���Z^����S.�s�������o��Uy�k_�K/�4W]uU�.]�SN9%���������O~����|��Oooo.���|�c�-����?��y��0��-[����F~�������d�o�^�`*����B�L��r9;��X^����R�����7�)O{��r�
7d���y����k��&\p�������9sR.�s�i�
����~u��o�v`=�}�s3g��$I�T���[�d��Lv����0i���'I�/OoGGz��)�|�����#�J%>�`*�J��/�"��~��n��������[nhh�w}}}8p�c��`���Z�0i4��&Iz;:[>Q�'�?��?�{�������s���|��������$<�@:::��G=*��sO6o��$��'>��?�������R������X*eq[[z�����Z����}�s��cG���7���.���7�e�����q����&If������������}.�y�k�o��,Y�$���'Nx0�M�Z��R�T
_��X�"��zk��*�T*)��)�JCN������'[m<��@1�k�����R
 p���w��������|���c];��<s�C������!��N>��iq��J�����?


���0�L�:>y-/p�j�.]�m��e������ihh���K�=��X�'#���T��Y����:�NG�.3����c�����PuBh�|��C�h*@��@�P�;@��@�P�;@��@�P�;@��@�P�;@��@�P�;@��@fV{��(�{��������J��L9w�����[�c`��m��
��L���I���[�#p�i���P����{�2P-e`(����XwGw�&J�FA;�#-e�w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���3�=`|��=io�MkkCJ��j�,�;La�rO���1����X�����}��e�7o^f���$��g?��+W�@���0����&I�/oHGGo��{�0N
����o}+K�,)z��8R�������$���=l(��20��J�ik[��;L�E����~V�Z����������^=0��0��J�Y��E�������k���7�����>?�����|��������X�b��x�����xu|������T*��X�������������>+V�����:�J���#����/T������{����>�$�����������E��x(NaM���{����$L___~��~+��Y���q��������f���E���x(N�M��J��@�P�;@��@�P�;@��@�P�;@��Y���r�'���immH��X��0�	��)�\���u;����7Z�SV{{o�d�����a<��)���P����{�2�-e�)�TjL[�b=��w`J+��L�;Lq�r��0�0���=Y�n��r[�b�;�M�)�����B�/o8l(������CA{GG�a�@����)�TjL[�b=�a�`�+��0�����w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��j�r�'���immH��X����'p�I�\���u;���������I���7I�|y�a�@��`jm=�wt��T��20	�J�ik[��;��;LR�R��j��2P3�)�{��aL�+�{�n�������BwFLK�����&I�/o8lFB�����CA{GG�a�0Z�<�TjL[�b=��;� �R���1�R
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p����&B��������6�Tj��p�����W.�d���mm���NK`�ko�M�,_�p�2I�Ly�����������HZ�S^������z�3����P*5
�WZ�@�P�;@��@fV{@1���������!�Rc�������r�'���Xnk[,t�	��L���I���[&������CA{GG�a����R��R�1mm��p�*��Q*5
��������w(��
 p���w(��
0.����^��3g����q���Sx�~����������H'������7�_~y>���Z`������z����W�:��zj����:�QX�~�-���o�+_����������+�{���zx`FR�'jy������>��zk�/_�e�����/��-��>8p�K/�4��z��'�tRQ��H��D-#QW�T*����3g�������+r��������R+��H���v��6�6.��;LW���dVP[��0vf�@�P�;@��@�P�;@��@�P�;@��@�P�;@��@�P�;`f���r�'���immH��X����%p�I�\���u;�����J���I���7I�|y�a�����$��z(h���=l�xZ��$V*5��m��P�0��J��v�w����3�a	�`
*�{�n�������Bwg.�
SP{����._�p�20~�0��
�;:z[���20�J�ik[����uOQ��TO�����4����T��p�A�R��8���Hw�I��\��u����	�a�����M{{���1��`�moO�4,_~�20:z�S$3�&����$IoG�a����uO���Pc���mmz�C���(w�I��T��=��w(��
 p���w(��
 p���w(��
pX�����/~���0�x�
�����Y�n]����:j���2k����?��������@�WW�T*�0k�����%If���J�����q)�W�X�[o�����ds���D���Z�
��gy����'|@��Q�@�
i)�$���������I�_��W����'tP���������W��|�#���?�$����+^���0
�x��!��7���|��_���s�$�/Nww��9u<T������1uuu����9���@�Q�@�
	��w7W\qEz��|��_��^��\|���0B�x��!��������������g>��\|��y���^��#�����y��������|e^��W���_�r^���L����S�@�
������g������N�`��Q�@�
�p���ks�5���{����������3}}}Upl�x�����s���<x0������E���/}�*��M���R�T����o����;!�b���z���XP�N�6��:>Q�@���������g������y�{^-Z�����A#������k_KKKK��?�3�����y�a� ���������q�G���w�����Y�x��
u<T������5������}-�|�3�w�����1�x��!�������Y�zV���o���9�v���W^Y��#�������3'/~���`���}���������_��#����������g���O?=��~�.]�'=�I�0B�x��!��[���\s�59����s���_�>/x��16`���P}C�����~��9p�@����/���^;�FN�7����3'}}}Y�bE������3�HOOO5���:�o��}�C��wo����>�r9_������|�cFH�7d��\�$ijj�'>��	0z�x��!�{�\�����l��u��c�\s�5:0`���P}C��/�8�^zi^���f��!g��������;7����1`���P}C������������ 


??��3't`�����������y���������RWW�$�������>��FF�7$p���>�_���9��S�1`��P}C���|�����Tc,�������p_�dI���'���.:�������	0r�x��!��#��<���L�������:�oH�������N�:�oHw`��P���}���0�x�=�/���������~v������O|b5���:j�@����?�w��������?�c~���	OxB�������~v���_�q�P�@���T*��n�T*�����o~3���������~���>��+r����N�����'��O���opm|���Hw�}wN?��qLg�U�G�������x�q�;`<�t`|��`��8p�N�8,p���[��o~3�w�>�N_���'rL�	X�jU��@�+�{�aCg���j`J���������?���;/�G�}�Cy�K^�$y�{�3�o�v�{��C~�u�����~��=$j\���u�v,��-N��X�L��?��?�G?�Q�����_�2/~���c��\z���T*�#p��sNN9����_�eR�T���<%�����=4jT{{o�d���tt����W�P����R����9I��G>2�\sM��������O]]]��7���|�s���^����������3k���u�Y�5���!I���{�2'n poii�������s�I�,X� �������8[�l���c{��^�g=�Y�����|������=$jX������io�Mkk��������!3�����o|����0�F��SN�g?�����GN?��j�������}��w�93/{��&l@��=�9��s���j�����g�H���'<aD+{����U�Ve���������������i������M�\-�rO6l�L��S�qa`��
7�0�*�J�o�>������[ZZZ�$���~��y�;�q���UD�����Z�h����T3�?�)O����S�T�����sD+�/�<����!=��bQ�'jy����.����������7#{�L{{�����R�����#��!wZ�t��W���8�^{mV�\�|���`(�{j�``z)��O���I��X3�-[��MRI�`/0�
�p�[�����{e��=��
����������%K��/~��������X�b��x`���-��A�_�+����v��\�D�~��U�'jy�c��9���l���s�=�VW���|�����>��|�k_;�}V�X�[o�u<`Bm�����we���tt�f���Y������z.r"l?�k�T���(�A`*\�|�w���|�+��m[�d��%y��_�e��w�]]]�������s���|��_�����GP�j��C����s�?���"�a��b�H�����Z�'P���2��G��g>3����r�9���s��}���g=�Y��G>r�uuu�/xA�?�����9p�@����j\P+����kN���`'��'�D��D-@u�J�Y��eZ�GS�@K�s�=7?������t����r����
p��L
.�����!c���Q�'jy�w��2���C�<��`�R�QP���~�����6��^zi.����]�6K�.M��y������?��?����S�p"�mP����
oxC��Y��|�+��O~�J���K���_�z�9��j�8
u<cU.�d�����zT����2��sN�������+I���\�A#��`,��]�~���tt����W�p�f����{���^���r�)9��ss������O�+_������X��D�X��6$I::z[`��K.�$^xa�������#;v���m�r����K.����P�0V�Rc��g�������R�T��T*�\.{�G=�Q���^���X�"��zk����f��q5��D-���3�-Z�����}���o����?�s-Z4���K�c p���?����Y�hQ�.]��K����N�5�\��}�s�#p�x�3��q�������l�d��]�T*9����60����P;f������O�����L�x�1R�@u
����~0Q�
����8f�^�T&j@A��P��o����Pu<T��ES_��������w���>6!FN�c`������<�IO��3����4�y�c���<&?���2s��c��u<����
��~+�\sMf���$��o_V�^�����*��W�X�[o�����ds���D���Z�
����p���������������������r��k_��<����_��$����������&|`��������o~����g>3�\sM��_��_�j���0
�x��a��������:+/|�����]�ve���=6`��P]Cz��#������.K��s�=����'|`�����*���l���r���C�!��G?��\��innN��}������&|`�����
����[�#�����u;�����%0LK�9s�d���������`*ho�M�,_���������Tj������%���{�����p������9p�@n�����5������Tcl����
Z[����k��Jgg_Z[�=$Fh�����0�	�����.��mKccc^��W��3������j�
!u<SI]]�G�h����=l���J�R����X�"��zk�j�d��'�x�6l�����Z��]�0k��T{X�P��������6h'��2�6��}�������ttt���?��'>1q#FE�T`���V*5
�����/z�����=.O~��S___�1���`*(�����,i`��?������?\��c��`�8r��6%�d2����W���7�X��c��`**�{�n���_�+���H��S�!���s�9'uuu����G>��,Y�$


�T*�������^�q�P�0���������^����6��;���8�1P�0���*0��g�uV����o��%K2w��$��={r��wWgt�1����\D�l��p���K2k����Y�f�e/{��
u<SU���5kZ����0�����V���=;�����A������\�1�j���---�����������?B��:�r�'6t�\���P��rO������we��5���a�������/�8'�tR*�J:;;��/~�cFH0�������O��fs�����d�/oHGGo��{���L�mFbH��j��������?O�RI�T���C��u<��Vk�k���C��6$I::z[�D���� ����2�z��2s��<����c����93�z���16`�����h���hp�;xy:+����8k�.<���j=3��A�!S^v��y��C=�m��M����S�Lo�Rc��]��n��/�7�fs�W*5���������a�����w�]�zW���2{��$I�R��y�����U pt�x�C������$S2����D�����*�Je����7�����<��+r���N�c@-;��x"��D-Pk6l�����f1�]�0k��T{X����5�6�R��H��kWzz~�����O���������g-o��P�����n''3�a��h�w����}��9���s���g���y���T��#�����{�wu���yF���U��1'��������-oyK�����w�y��sg��_����0B�x�d���Y�jn�__,�(�/�9��
��uuu9���s���$��_�k��v���:���8�D^|`���}��9�����+����/g�q�a= �����TjL[��q��>���
������w������}��/�27�xc>���Tcl���H����.�9���-��!��\�$�����W_�9s�L����Q�����~mm���0��p���~�/�0K�,���K��'>1?��O�16`�������-L�!������+�������;w�������W��
CFJ���������//x������e���:(`t��L�r�'6t�\vq������k�.�N�������~>���f�����wo>���V��G�D(�{r���s�U������'�R�1k���a�U*�����5+}}}�����������o���|�����[[LV'ZOd������~����}���iF���-o9-�G�V{XU5�6�y��N;��G�����
i)�Y��9+W��������s�zus��PS��p���J����%io�MkkCUz���=U}|~�{C	��R��j�j���u�v,��-�V������B{{o�d������x����I���P����{�2�{��R�I�TjL[���������d�
~/�p�_�0i����W_5��C��R�IE�p�V	��T�j��2L*���J����8P������w(��
 p�������\�I{{oZ[R*5V{80���	+�{�n�������Bw�-e�����$Y����e�N�p
�}��tv����>��
�L83��R.�d��]in������]�P;�%�;pB����Z57K����h�z��	�o���{�2L7z�'�TjL[��������A;�-�;p�J�FA;���2P�;@��@\4�)�\�I{{oZ[\��pw��r�'���Xnk[,t&��2L	���I���[�����l���r���C�qg�;�j�����
�;:z[�z�u�t#p`�Ld�Z*5��m�����\No{{Z[�X*����:���M{{���)MK��D�y)��fMK�hcR��r9;�������c�������g0���@���l���$Y����Y��\�1���I�������������rw����`�+�{r����e��$�l���+�\RH8Z��U������$���8l�xJ�F�?���`�ko�MWW_��u���+4��_O>���6&���T���k����2��G����;�4�������l��/��W2wn�����/�����r9���O�Q]8�M��J��\y�����'���ge��YY�~Wa��S����.t��Ta{q�p�����Tj���K{{o���G����Nk�X{��t"p ���>I�:�}��R��i'� p ���>/���>:�K%A;��`����){�����c;^0>���B��d'p���[p�<7
`��V�?Y����7��m��-�x�3r�y����~t����Z5@��[p��T0�[�A���we��)�{�=$�������~L��3g���������n��7�����._����Z=@M���[[����k��Jgg��|nS���DQ���`?&��Z�,^�8�/N���=;�{��r��w�z��2\o��vj_]]�G0vS��@����t4�jw��909�K�]�v��_�j��?�s<VP��*}��C�$ZZ��j��tt����w�=��t�%;{@-Q���T���^&�~Lg�������_�7��
)�J��v��W����X~���~x��|j�d
��M�Y��bKv��Zr�:>Q�S�T���~&�~Lw��}}}y��^�U�V���.r���^�K/�t`y��E><@�L��:1kb"��j����D-LS�v�����u�Ksss����"WP��ZH}�YZ���P+���t2�jwjK]�R������>O~�����<&���I�W��U��?������+r�����PS�LUZ�����Z��X��D-�����p������{���LeGk�"4;=�jS�@q
�h*Lwz23�
��A&�C�P0=���z��������5���������
�Idj��s��&p����QO����
,/nk;f�>x�v�	jC������s�� p�q�'3�Mo{{��a���vt��������d����0���,0fT{T_Ckk��������*��fM�b�dp�<x�V�����L3�Hc���mm�����j���k�,[s��ew��I�#�v;;�w�
��09U3L>^���r9s�0/i�KwW_����J�'l|�i�7-e��j�z�o��\�����M������Q�Xuv�X2;g��	�D�0f��
����������/7v�\���D�5^���l�p�XN��2�Y����.jIWW_�;oN������;0���u�68ce�;'d���,Y2;]]}I�^���TJ��55�'�n��|y�a�'�w`Z+�{�r�����m����-�(�;0mi-R�R�q��v��0y��ikpk�����z�3�M�����;0mi-@��p�-�E(������(Z�@�pF�\���	�A����W.�d���mm��>p�;<L�|t���I���������^�
Awx��Py�2Ik��������e���p����6���/�]����z�� �Rc��k�� p�#T*�Am*��pZ�����{��R��<�9--�Z��b�;'�\���F�)N��`��0�\���u;���O��]�r�D��������,_��������N��Z�r`��p��������
�!f�La�k�p��`
��0|*�a�*�er��Mnw�����moOCkkK�j�0S1o�rO.�|{�����T�+�\�5d�M�OWz����r9;�������c������'h���l��P���@�ly(�6uU{HLq��������'I�/?l��������r��OK�����$���8l�������/{���l������,_^�����8����=����'p8A��R��	�`�����T��mm>j���e�J����%5|��=u����&p(@c�$L�7�!��VS��mo�Q���c77�����f������Z>�����M{{o���=��ia"�������������l����[{�qcg���jkD�����\N��
.�`�;0-LT���f����cv{m*�s�E-���K�4']]}�f��D���)������������,��J�5C��;j�D\oa��n���\��97������$3S�(���k�����%3���o��tm�4��m(��WS=|&�����T��^�E:k!�<���)>�U��?0��WS9|8�T��^�E:���j�1�Y�2�c�l�W�N������N���i^����vn���
2��S3���h���&p��T��4mk����t���Z�d�X*e��W�mwn��;���r`����/�--������g�1i	��q5��'���w�����3F�����t�;;��m����=xu�`�9��=����������������s��+���qLZw`��B�0]���ci�R�E:���M���qcgn��;7��=��e�:x�!=�r�_~y���R���%W^9���y^���<v�Jz{S7{v���'����;#�IkF�@q_;c����U�|<�rO6l�L��3�1�J�Y�tvZZ�G��E)���������6m��-[r`�����%]�6���Z���Y�h��w��W���x^��8;-]�@=��������5�j}|p<jZ&�H��1��*E^������\������5krW��m������$'�a�o����E�$�)��R����Q����<r�u�����R)�����n���N��~�c���J����.�����>���l��%p������qc�����|y�W���o���p����y;r���Y�eY1Nc��&p�~�aoGG�]����0���=6j��3�A������uv���+�]vYZ��)�1?���������[�d����oi����'{�����	"Z[�������JR��;�zu��}�K�,���17��6���G��<2iq[&7�;�d��VK��`�0K{����g<�m�������LoGG���s�UW~����g����������>N-�J/R����.jIWW_�;oN���Nh��D���'r����]1�	��$�������X����WK��dd���MT�=�W?�AZ[�����k�M}s���Z[��������75eFss�G��up���=�������_�g�m����pCw����L���S��T�������9='Z����Z1P
fi������4&������}������.��5�-d�r��n�c.|�K���|$3O9�� <��{�p�����-s���:��4�^=i���6YgW;
�I�L�)��QP�LSa�&+��'��2����=��}�����������GyY��
E�� Ho{{�[Z2w����?z��t�pC�/����,\�v\���uv&I�[Z���>��XN7��]].�T=���@k�����S�g��X���v�r12�tn��{��*���G����b`���Y���T�p��������������<�|����}������?�/������k���!�?'�\���u;���We{��@k�����SuSe��D��)�Z��0U��c��������������uk���mv&5�4��7����0Q��T�p�X*e�e��?��Ql>3�<rR��>�������m�r�;��y^��5kN�1�������ihm��Z����$���
�������x��^_�;U7Uf]�X��d>H1�b����X��d�N����=3��S�������uuM�GQLLnS��o��M�	'+�<6/k}��;+n�������m�r����J��?�����P�~�{����{-FkkC:;�r�u]ij���&�����������A��I�N�M�YE:^>�RL���4�����C�z�����.���i��N�4L5���S.����b�1�&�5�JNF�c����/w����$iX�4���e�M7��,�#���wn����k�*�j�`j���-��.�;U'L�xE�t<H1�v&�T�N|^L=���������c�:;�5����b�1��f6��s�g>��m�R���x�����7--�Y�jn::zs��-Y�~�}�M�lG����%p�&Sw�BH��HL������3�i���f�J;�5�Z���j�1��f��fM�L������>����W.�Tu����4gn�=��'��hVZZ��f����P�FR		�	���;���������5c��5kk#S���B������=Y�n��r[��	�������+�r[��{n���<���g����T:���P��B!L]�����WC������hS�7t{��k�,_��������Ve�{����������������w�g=�Y�3�2��a���LMw`�f45�A�!f���Q���B���O�����\/'-����l�������5��4��fi�e��?2P��S�Yr05q���>�������������_*5���N�UW������o�?�0=	��I���/'z������y�R����Z�q�����6L���;U1Uw�81#m2�����$�a���V��0�o5�e1�`������%p���9`�M[���xfO����_�����75e��WN���Z���x�~���Lo�6��*Lo��s��6�� ��x�����)m������vt�k��)�/>���jL���/�e�td�n������c
�_��������`�G@�M[��]<�uG�*��$��n�"|d:1Y�6	�kX5����R�1k�.�UW������_�K/w�1�J��m[������zu:7nL_WW��/O������V9������}��oG���E��tc�nm��0�����h;�K���V�L�k�T�-Hc��%W^9���O������66���]I����6�|�������uvf��y��=��~}�];e�C��;~h������h�'p�q�.4N��v���&��
OE^���k�/^.�d��C!����z�d�$�����n8���0��m�w����/w�N�����n�;SVc���k�����J}ssv�_�3���i�N��;�N�x���Z�����I���W.�����g���I*���3W^�d�C��R)g�{�v<|���B�]�VsV��������=�-K�=��71��^�D[�"pgZ������c��G�M���B��[��V�$����N�}����tu���iF����/wl�����M��}��{���D\�������5�--I���f���=�oi)���b�&����=5�O�/Ij���~Sm'b�0�&��@�Mv��ELb�J��d�lmmHss}�n����'��=�6~6�Z��L��{����iKV6���Vd����~���]�p��V��=7��Y��6�?V�s���u��$��m[!����	��������/�����uu���.K��5�����~
�����K�u?OSS}O�����Lvv���OZ�vm��	��M��f���J����%=�������~���{"b�rJg_����|����e��I�c=��S.g��������-[2g�����v �h�O����O��n8��u
��3�v��dm�������������W]���Q�J3581[�,��+2�rg����,�O�E��f'j�d�a�M��f2����������I�D|���x������"�l��S�e��s��k�����w��y�<������W�}����c�S.g������;�MMYr��S�s��������uu
�Q�hn��#���Z���hnmho��-���U+����T��
�������z�?(��@&��V/M��i�������'��>�c��>�H�e~����9u�n�����(����^����J6n�������'���{������O=9~�3^��;z]�6��-[R������tm�T�6l"�����R)�]vY�����hn.������35�n:��}1]���I-(�{r�U�d���45�g����t,��2YM�zi2���S�=.�x|_���E���^��1&�l�#��l��/sn�!��6(�-���,)�=�?@��6m���/Z�������O��{�z�>�q�u�ii^�����X��d:�2��T�����������$iY�&
����r22��8�rO����S:���Ug��4�����P7�sj�l�h{{o�����T����tut�g(�ar����'{�S���a���Fs]�����x����t���3rW�_?�$C>K���F�
7���3��G�u�=9����du1�M�o��W���F����f��������~����zu:7nL_WW��//tp
#jU��Im}@����'�l���\����o��{����{rA~����i?��������6�stj��dU[[��rhf{WW_.�lQ��y2R|��2�f���lY�����	S�=�X��������E���^O����IA���7����D�c_����,�C?�q�����Z����k��M5�1#	�G��r���{�tF�H>�&z�Rc��%W^9.�����U�"p�*�#������M���e�Cij:3����Y�P^����z>�x_�UD�z�\M��\�;��-8�bb(�ar�J��'���X�HH3������}�����E���^O��i4���������c_�{�������OyJ���
=�o������2c��$�i�]6�J�4H��o9p�������_�+o�������3��7����|Uk��xM�����&��}��Q��4az9������yp�ii,�Z��L�c�����XEtQG�{���/O�����T���5������=���:���3-��0�L��Z{���Z�>}����jU�~�E!�Tx��f�u�x~_�����z"��Z��z��tm����S���d���p����������������#{&p�zw�_��� }��������9�^u��������l��/���{R�$���\x���Y�2�}}F���;����x�H?���qj��}�6�I�W���b�8Z�W7g���tu�e����^�\�!M������q�B��#���T�O�<���f~����T�c�����]k7��\Q;�������0����������%IR��R���c1C�"�H�T�W^�Z�[����}���w��,���Bf�mc<��?���(��W���t�z�]��k�Ie����N����\� 3�����qm��N*�s�y�����r�I3��S�M7�6p�>�H>���Y����HU
�+���s��q������&�i�W��5<�Tj��W.9��7�vYTZ��Xv�F��Z���]9#I�8wg�����z��������p�nR�N�d8���V��0Zc������_�]������,\�v�<�����x�M'�O[+���X���s`�i�e�-���;���R��k���o����h�=�L��������hnN�I'���}���f��E9��,�"T�U�h���+����������R��}��G?z_�C���X�qF�94�����D�j�~`���Z�>��}�N��%��B��S��}���v���%9�v�,[�%]��hw�F��Z���Y�Wf��?���;���3���W�i=w�����/M�c�0���n���Tk�/�e�\`j���m����Sy{�#_��2���dz�4#5^u�pur��c�>V�9���������5}���.:��C�T*�YNt������g�x�G�w�����/��SNI�S���k������Z������g�������Kg���n������K����/}�.�J��G���W�9�\��9��9�S.��x-�US
E����ALj[�[����m-��8��Z�`��>`�y���\���/O_WW������+k��n�\�b
�Z)dG�S6������x�w���?���'�eY.��o���I�����;��^��1�������'��rp��S+��0��n���>�o�1�d2�4�L�kd��iSWn��{��c��c=��h���n�F;�Z�X*���������s�dF����D?�F��2������n�
������|Q��r���~Z[2o����7#&�������44��g?;t!������;����~p{<?�Ot���9#U��}��lG��;Q�hg��w�>���}�Ts�h��M��eKf45e�������&�X��.2���\�/6�sW����gd��S��~I��@���H���q�/��Z���Gfkf��s���Z:p��x��!�0���n�=Vm=��}2m#��a&{�2Z#}
�+��I{���}c�f�	m��{~��
9���9x��9����s���u���Js���w��p,!��j�r�'��j�q�i��g�������L��z�k����(�4�A�����zu:7n�C[��`ww��//��}4A�h>k�k�I�:�s���������������k]���Y�����=cT���������P��v������.;-W]uo����sL��*�5�PO��3��j�����$�}��]�0���Krx������z-k=��o�HU5p�y�)Y�v���E��o6�D�#��;����/��
����2����f�	�g��#����L����E�o�c;P�S.�|�{��-%I6�����uo���j�1��%9�����{����\(��W���T�L������l
��������F���C�W�����>��������0e��c�t�����x!G��M���I������|����%���m��6�,[��|*�u}IW��k^����8?���<��s�;Qe�����=��o��'�7�MK����W�d��c�
7��������?r�>�g����K����}��:�g�D�8���S.g����������������X?��$O�r���������~�P��gn���\y���J�Y��%��
y����]w��CU��S��}�w��l�z(Loi�?�s���>?�����mOww_��l���+�\2�����k�L�d�"_����tv�e���j�{��9#U���n��a��[7�$���2M��ii�?��c�`��#���8�E��
�����T�����������������/"���f<g)��&���N���i^����'��H��������moOww_lZ���;�����\�k;��i�;;��[I���3���W����-[RI��q�������Z[���l���X�\=S�(�4�������l�Znid&G3\-?��z4�{5����?������}�`��}f�H�����t�3X����]�����#��#��~�������g���y�����0x�Uo{{ZZ���Ugg����������%{���1�����4��06t���/���?3f$�J�|��Cc��X�������O?����~����<�0����^?���X�x��G{__`z��T��3���on���n���H�������{��'{���-e�����)������������s ������9��9in���7w`V|�tv������g����Ur�����P7p����i�L�d����l��CS(��`�>&#�\e��j�~��;=��aG[���
��YN��76-�o/�?��cm�{4}��v0��C����rp���/X��������N(p��r���G+fG���,��#f��p��p_����v:���ihmMSS}�wl��$.?��;5�a�Q��:�3��$=�+:���~��eYv�"���=}]]����$���UQp�����-�5G���miY�f�����3}]]9���F�w<Q=SG.P�FZ��,�ZK��<�e:?wF����{������ug���I�N*(��j4�?V������K]�/b��p�9�|
�'m��]��{�_l*g�]�2���4wm��KG;����
7��g��)���|�6����9����K�Y{sFX??������'A��J�w����}�$���������w��'����Y�dvN;m�q��r�'�t�u��ug�������O��jGGozz*�=�.

3R�����aTg��3�\���������W��os��{����������<�����uu���=������x��E�m�����B�������g��_}S���R���X��?������u�������RcV����|�'C��5kZ�����/yW�.m�m���m����%��K��\tQK���r�i����v��{����>��7�=�DN�(�=]�r���Z������
����{��f��uY���������e�];3w^}��-�]
C�X�udv�_E��}�/��~�k�v�i������{�����e�i��z�����^�${o�-��m�m���G��/����d�M{rR�I���YJG�����h�6mJ����o9�|��ek�
��y�b�XGv�kPc�������p���+�:�~��'���c��,������>;n8��<^��ag�)���o
���on���[S���k4E�h��.�N��My�Y�g[f����W]US!v�XO��e�w����ta��!�2^��\����oOWW_���Nc=�Z��\Kc�7��4�����+�ER�����}0����45�g��M�i=|Vf��Y�I1�U����������(�uue�y�
�vE}�����7&������
��n���P�s����ol�:z��[���s�x&/������<���]�0�6ue����z�p�e��5Y�vm�����77g���A���y�����{�$���������NK�nM������-{n�)
�����)}]]���`f����||S��Q},8tF��lM������c��<a�G2��>{����M-)�.<����	���������7gq��,��g�NOO_�;������^����
�G}=�;X4�q������-�}Il����{�����������y[������s��O/*�s��\���^�=?�I*{����������]9#[�{�����{���/�w�s<r?����������C�wN��i4��pY������L>�~����e�w�~��X�c9�0���������)����<��t���l������,_^������g������W��E����zusn��;��}�9�.g�9+s���u�;���i'j�T�����
/�mujQ-��P[��Rf��$�����������}����{��\p�����������r"G��u�����G��*�=�������<&3��33{�����x�:�h���{��G����n�o����{����r����������I���c�g�_Gn��z_ww������+���?��J���Y���Po{{�3�T�R���������g���R)�)���#~^���J�Y�~_v���1GSP����f
�{������!K_��Tn�6;�����<��-���p��p�kO���������r`�����7�ukz�Me��4��M�lF����	O��hz���w�Ov.;-~�����Z�=��1^�G&���M���e��45�����;�u8�4����2�D�iR���sg���UwF���%��:+s����onhOp��U=�r����<������7j��]��x3��W�N�
7������3j�v]�^�����5Ih����n������e9p�������z�c�j�/��`�;��>\�~W�d���������]w���$��8�g���\�q��%gUv��d�����~T=��tdk���9�p�;c���:���X�.��oO����������*
;���/�~������]W}9���������������m9#w%9z�������/�����������+�����8=Y������<�P�qcg�o�?���&��{{{o�w��yM�������_������%K���nm]v����mN�����=3��o����3[����!'�vm���?�Y*���r�@*�����+���}��y��eoV��sX�y�~J�kq��-9w�C9��'|�H�#��_��\��G<K��#�+���;n�����70��=�3��e`����-�}O���c��)�{rG.���k3�����P;��������Rc��r�1�SF:�a����q�;Z���]=E}�O�����B��j�^��?I���[��>���d�E�����?�������h_z]�6e�]w��H�`�;��?�n��������~�9+W��*�#�`��Gsf�W�<Ys�z]�6���(������4��������_�������5���������>r;��=yh���75
�E�mo(\��w^*=�=?�a��4���5�x�u8���cm�E{�n�I�����v�����+_�_���>~�����6*D�;�>���?��6�"�]}�}���{x�K2�S��ek��������$o���~����TZ>�{�EaW�����[s{��������uN��]yp�}�������_l*���2������%��iy��h`}G����S1�vJg_~�G����S����t���T:�L}���U*#����6/��
��ug���RW?'3S��'�����U��v���?W�LLr��r�����#G�����KwW_^vyU��0v#��t-��4`d�� ��z��{����������C�O+��6o����H��-y��Jz�n�I������������_�����}��=:���o>4sr$��HC��R)��Mo{�a�c��m��-[�fK%9-�Xz�q�?�{�J���Y����:����iF����oD->:7l��W]�����0r��}{vo�����']��8;�7���	�����:;����9�yL�w_�'20�j�y�e���i��Y������`^�����uy�?�I�q^v.\��^~�<~��<{u)6�Mw����|n�^}��.������i����=�SWW���;reN����dI�����������}��Y�v��������6���!��|f�l���l��9eFs�a�+�)�5u���}i���P�{:���x���f�J��/�T2s��t7�z�`�i�I*�7oF:;��~��������l�yg'[���L��O��i������m7����2���Gc��=x������66���]����l��?s�����/��da��}{zn�5u�f�e������c��c��q"~}Gg��8%OZzON^vJ�����z��X���LX�������o~(�^����c���moO_g�������;��X&�D�+OU����>�z��3g����7/���#/����l�G+jO�4���$wT��\N�����������]�r�Ki�31��$g���J�Y����)s��a�'��}����pE���m�C��mf��>�����y�\�u�
��Tsu�<w�!���H�H�l)��������y��>��&1''�y��qr�(�1;���,����d@�ZR�Z=wuw�Xs��=~��Rw�%���u]\����~���~���u�{]���H#E�$�\���x�y��n��%�^�mh��L(<C��	��q�<���;��V�������Msn���C IX�l��v�e�W[���,_)����]d�������}�3���(z������wv3�"�k5>���%��j���.6/��'���d�����O<n�L�<�`-����tt��������d����7����k��*W�}|~���	m���aS{z���;�(���G��{��}��j�XZ[70������G�L�Y�/��x���p��s|��K����7����a*�1+Z�x���e.j|�U��EC��ZG��?x3s;��/��RY�Lul������f������M�1X�e���kY�7�^/�^A��t5%�Q��8������H�XS)��V��e������������mo������YI��?��/���j����-I� hD
�m�Jt��"k���
���x��?G-c��+�e�c�n�vB��9qB�=	��Ta���B�`a����������W��+\o�;���5n���'"5�p5?� K��eK��=����W1M�O�l�#\$JDv� 74�T���.�~A�E�C1j�)���$����|� ���E%u�p1���2�T+gf�_	��k��_�D�����T��O�S��� ��L!����B�3���c�i��B������]u\a��	!�2dmK���t���&2s6�����(��OPy��������y��U����H>��w�h`��&�C�Z���[:�%����T2��7��v�d�r�����x::�e��������DV���#�9q"sIE����M$Z����A����
��W+�9��NN��d:��L�����
�����y�;ZE�p%��n��WI&
3��6�t?��.w���|>gLWHN����<�K��:O��=/�n��7 �!�{�����j�Fo�i�C����}���%��z��7�W��^���6�d������[�����[���x�m���_��@` V�$^
��r���)cy#l���Z��E�?��Mh��"X\pP���|bk���`�G����H#V:�
]�^�lW6`h6CG�4���s��r����)8%}�&�����*���ee ��>z�r���QW6EH���Lb$T�C)+^�DP{{�s^
�8�\�c�����8������z�k����0�QlMs�����J-������[�����&�z�ed�T��Ar����N!�-�@3�f��'���G������}�=<�UN<^Oc���G�<������1�G�H&K�L!���v|o��x����O�03c�J���1Y|FG5*����6���B��mLO���7q2�DE������P��`����������5*�����'��W�������%����h�{�����O�OO�U���il5���F&���_1���0T|g�?���V���;���Fv	���D����|��K]����,���IZX<�`
��������<JE��%��z����������}�����?�5G����@;��{�%���T�t�xL!�I����=8��`���p�'f�R���,�[p�����������$����t��������%�s-�0�����Z��`�mo�|�
���(&)?K�����h���C�� -Ln�CZ����� �jl|Ch����Z��dg'Z8�@��]�����a��*��rK��I�y�jr(���������u��Xy��V2I��� ��?�,r���E�r��c�}��jY��m�^�����\�O��������>6���OP��N��m���d2���lopP[��/EL����h�8Q4�P��58N`b���A�7Qy�M�}���;�1
,]	z�{RG9�-�Q���p���`�����7����3��c���m2	�A�0�*������4�h
�u����.���v��|��|u��b�s�8������������b�(�$�2*�P�����^~�_����&�O����:�G��s��m��V��>,�������{>����M!�4-�
`������^/���>C{ZH�Y����#�j6_�h�}����L~c���}z{+�f-�����9�����98��;�S��,vXan��^;:<h;_&58��f���p?����/��*��i��U���k��]�]���px���~�D�>����X�!�����3��J&/���==h;��������bX>���M�cg�����">�D.'#�9�y������W�s����ZW���������OG�>���������
��e��9o���F��*�>�
%�C��t�
�h�f�����X0���nX���R��-,bf2������g~�T��G���Lv]�ddAi����c+������{��%ex�pz����L�}�S�wq�/a������2W����4�es�v������q|�E;�-��>$S��2d�)#���Z��@��mhK����������W(1�kr�����o��n�I~��������j���2z"����'3(�k��5����c�����-r�%�D����\���|F�N�����li(��H����9���g��}�����f����A��
��z���j^\g��}�W�nj�&���2��l��c��`������3�
�����(�bq(]�����-�I�1�8��
s�kWQ_�btT��c�nk#7�������.j<��)���Q+	���>N���6�N���<K�gwml��G����H������.��Q��#l�zm�����:��!T|���I������K�o` G<n����4>�w��N[�]E9v���qR�k5�q��Q����^�Fr������q�#��O�����kZ�W|2A,j0�Cs���R&�@u�S�6^���r�{#�����r���@&cQ��y4�d���a�e�W0^Oe������*r"��1��ov����_��{6�~����c��6RI���(��v��xo��6s���M0(14�6��n�mYK(/w����j������
D��Iv��*Vq��c��R)l]w�w�.&�������2��M������YR����ul���}���!~~olYO��sn����%j�	4�_���YF(���/
��a�$G�l���q���x��
8�h��17�\YYL~L���:4�,�6f6�h��>��d2>�#yG����-DO�J�H����Pd�*.����fF&g9Q��$���?�������'�'G(����Q��{/��B$2���A`��Gy�����v������1���%������(k���M���J�R������
�S)�d3�e��������������#�M�$�D�I��&����X�{����'������e` G4�N���������U�����M�I��S�$��e������:�"S'�8~,���|1�M���G2�m��57������8�J~E�=���a�3IS�y���i�@��3�w����c�M�.^��������7��o�ME(��A�DX�q��u/���~0���K|���=HS:��Z6��R����vn�)z��3*b�d��o]wI�bG
��'�Y�����h�PB�Rl�]_�-�\3��8�{�����1���+��T��)��Q�T��z��T������mY��b}�+_!ur��6�����!:{Sb����.jjrI?�ibj�"�(��������O�����..�����n��Z�F�m�p������p�7��#K��m��io�]��a���s�x]���K��G�\��x��8G��������&4��N�	l/'m����,�������$%�a��_�i��=�o���D<q������$S`1`RpSc�p���,`����9y2�����v���/�e�/����C��mY���I��x�����/����`����J�B�p}`�Fc�)��o�9;^7��.�@�
b�y����|�Z�f���Z�$�4/)%,h[j�0��z8L<F��������Q�:.A�T�������R��h���b#Z4��G%�?Z?��C:�adJ&c�"��Tm�4+���6z��R��o|�x��,������J6�n�F
	����A�|��dY��/�n���q�v��T�������i�r�E7P���(��X�ooN�]�AU���6n����G/0;�sR�E�l,�b���M\���}�9�	��q��R�J%�Z=���.c/%��#������]�B4�~�c\p_I~����4���<:MM�Rt0���z}����(79��\��>�-�g�,���K>�m/+k=hmM���Xv����%�F�/=�"Z��9����-I��������������)�e�;�������gp�YS�-����G����A
2�Y�{>�����G��Gyc)���;�D��%�g�����_�^-�S���h/�`���H�(|���/Q�?�f����V�7]GUm���K������BWc���@�km\�<z
��J�7�'y�������X�[�����}#��kW��^���F�k<���}�K���,6�mC4j`vq�����������������V�ttP������`3%���7M��uk���}��gs�K}�������\�b�j{E����wvQI���[�����G"X�,��!HRI	�����#��I:��UX��q��[C�9p�����M��S�����^`�U������(��|v*�b��Z�0���M����Q������^��bC����!���(u�W���

�i�a��������(|X���"6���a�����?o������*�4��Hl��/����q�D�	�AD�5��f������3XFc��{��X��'���~=��4rM
�na����Xy���[�f�TT��'�X3�m�g��������8R|�3��O���
I��5����
��!f�+C]���02Y��r���s���9;��t�^T�z[P�� ��S���@3XQ7Jm-9R)��K&M��>���w�hir�,|�Tz��P�U�L�?O�6C��B���I���~�h-���xn2�t����^6�|�����~�e�����w0��c.��a8s��3Y�K�jO���3�����<��k��a+~�S	r�8�4Y�&I&�%�K�j���|	��~����]O#�=C��!�P���xg�Z���1M��-N�����*�s` G"�����(��Yf�|#Y�������v�eP�V`��"�z�%~��~���@?1���CT�c���
6 �Y�����g9���_ ��������a�~���,�E�_��]��SNk!�VX����z�������������������2n�n*���oQ_:E�&Jpm�9��#CwT.xG����m)��Z7�|=��C����,�d�����7�&����]W����v��p��$r�������sLFtz�5�3���<�p��\�5����i���1E`�?!��S�F����@il��s�{]���a)G��!>��G��.c_�K��h�dg��%������M`^�	P�};����	M:
w�/�'Of�=v��c�sr����G�CVtz�?�	V4
��H�'?Y i3������dg'��=$&=�Z9�����Q��V7rw��h9�2.J�q3&j_�� �|�[[��Cy��'������t�L:�/��F��;K����
��O>�����72u���U�$�'{�(e����J���\�tl)eC�n����a�z��5�u��e?5�v�����[Q�,��m������z�g:��x
���ub��a�&\MML?���. �g��2�d���g�2�10M��5]7Q*�����)M`"�`�7��c�J��#��	63��O��<D�����[������G}�EN�P�e�h3��RS��iS�������oH�����7y��V3����/�7���^A���EIy�1'����/-`R������P=�m��Sck�!A��O���==j����e����W�,x6�D�t��aBR���S��������m��|��g/���p8q3���P��E<�R �Qh{[��;K�L���(u4���:i��������~�
Vo[Gxcg��Xi���t=���z�|��s��8A�v�����*�2������c.9Al���L @h�V�4�22:�[�7������wqo�{sM�q�3�sg���������?�����0�e[�h��g��=�T����%�a��8���xw��������u5��`�0��x�*6"�a`��$;;I>�����%j��k�����_	\/TT���U�PXl�����L�9�k��h2iJ�h�.e�{9�I��\�33rq��v��_���R	���]-����m�7m��u�N��|�}����l�.^�

6��T
��8Q\K�E��n�^�b_\��,�d����+�a�����N�$�]�B����
�u
kz0(A��FW�b��oA�a����������[����~�
�:���p���~����$c6�h�Y&V�9L�F�p��C��c����e����40A=��9*�y��G�}q���������R[���3�@c�������!���m��*����4U.!>�Pq��U�Rl����@TY�����#i�q�F�@�9�''"h�������V ��G-�	�9pup�������EQ0�ha�w�{���I��t�<�(����d���G����L�z_x���a��P��f�� Rz���6��0gs�G2\3�
�c%g�1��it�����!X;��J�m"!`.d��-z�Y��v�"z���|5����3ha��S�D�-I&��ed�������5f�y(�	a�aB!	)*��>���(�k8C���������\Gl0�-��%��b1���%0{�e�Y<��p�P+���\b�:�
�+��*n2:���'A��I�3G)��� �V9]!��JJ-��kh����&=���9:�����'WI@�����M&��!MM.J���X��9y������\%���3����dY��5�*��Nllx�,��,_��9��#:��j�}[��h��[?����q�t�;
�E��������.�G-�}*��Hsg��^�R�nO�����/=�,��R��C�`�z�(�y5kr��ta]m|�!`��;e��OOb6�@��;U.-7���(��3	�[���2��/00�c��H�{���H��,T2w������v}T��%������"#_�����{�<��^�;F�g>C��>u��X\9P}�r�O�ght���n`�u�����"�(���R� �CH�������<�)6����5���4��uY��w~�T�dn�s�m_\��Q*��/�S8��	r_no��&���������nk��1L��z&�f��W&�I0������S�R�)��/�m��(9=
^���o�Z�K����_nAX�h%;;��Q`*b������9�\�����f������D���n�K---��[���Ooi�d������;�HD�(�����������\u��\���� z.j�-n��v�����G���~��b�-
�����	�#�l���O��
SaDx���4�������bU|��i�!'����������A�7{-$7B�����JA2�J�������2G}���%`�H�Dw�d��D�|OoE`��/X���������s��R
Y��L��$;B4����I�l}�����=BYaf;�s�4p@w��_a�h��s#S}*?{�$5�3L��T9djh�b&���P������@���3b7��$&�mb�	���$A'd� �F�M,��[2P|&v&�l�����X���� B�g�?�;y�fu�k'����
�k�bt��>w���E�E<V��f��f�u��y��.!bb�BA#�Nb�����iZ�"���:	I#�K0�e��:����PG�v�3i`Ug�� )�c4��[[I&����(��`j��Dee�r�<��������S��q��$�R��0�Q��������R��N�� S��Wqq�|���,|�������������O���,��|� ��)��E���)����u�����H~��[��V):9z$�6:���Z���4� ynp�x���H�����PH*��5����w�����'�U.��Y��6����B����H3c��t��d������C
���a�`��L�����s9�x��
�q��-��#g�����]��q����ukhIM��R]��>"�����R��t��,!p�����ob��W�

!���\C_g��Ne�����o�����%7��b�e*o��f�q�#G���Q_�/�� \"��j�����_�����=��{�����wGz�r��.���}���?�:��}��&�&

��W^�;jOs;b�P�@@���O]S��7�.W9���mo5��Cm�t��^F���j7�,4�|�I�+���rI�B��M3{����.��M�O�PQ�����r9��7_Q������d�U��$�&��I�����c�����I�j����&�?�������B��)n��*V�.��_��C�*��
X?���)7����,�,z�F}��>=���.�����z���=>R�)|^�`�B�@!���<I��p(��s�(�r��H��$�����{���^�����6	��
?�~����*�{����n�����!`2�\��4���"N��}
����|�����2���5E�z�������R�T?)~���)����;��4�O������K)G��jn�\u�L?3?��,�&������1��wF���g�Sk�q�'��i$,,�N��������`;~��D�{�}�w9��iJF"x�!`c"1�����{�'	Dn��q�{��������c)�����s�cs�((��N~��
��0z��������D�.����JH��2(� _����O���?n'4�oj��D�]@���PA5���1v�-f��8�M���N����6�!5������xf�2,L,����Z�A������Z{m�Y���3�r6��=�f�����}�WU���Q���s�G�2=}���Q����O�"��c�Ut����<t���{)Y��T�l��k�X�,���w��L��U�3Zp�`�2�2V���n`�?����������@�@�I��"rM
�={8�M|uW	��D($���'����}��� %A�y5���&W��gO��Sh�N��+�KY��:�u&�&�����F';;I;�&�pNO�B���v�'#X]���
Z����
������q3u8|8E�Q�
���"Z&1V�0/�����?�7��w����%R�	J�ZBe����U�5��g����4��Xd�(�_����K������$��@�����ca
Wr���8�$r���(������M5�0�����"�y�% �|B��g;�LA�����t_�����w�\\!U?8���N:�������q�*����
����$�lV�����D���O�v/�����[p�tt������_>��h5�lwm��L����L���UU2��9J#X6$�n@�"���X�WS���&�i�U��\����_3�A��?��TqQ�QP|k�.8v�8Mw��D�45v��R��&�=�h�;hJ�����5�q�PH�7�;�x�lW���|��E�O,��~�wj�a�r���g>S����$� ��
��@�d�$��ls�������a���{�:��Qf�H&Y���o��9��<1A�{cj5��SV�\Y���M�g�
�/��Gt%���������=�s��CA�����,���9�b��k�H�-J6�����������L����^|^Or����*P��w�t����=q�iA���Y�1_q7��nMEr�d�3�����J�f\�!����0)g�:+������i����LK�E�Y���i�����"��L=�0v�f�F�����5��9���%M)���dlQ�*�gZ�!�*�z��L�q����CL��F���dd7^K��s���l�O��p=���,�����7����s�}Y�G
��J=J�9����[d��E���.��Y�uec��x�)��sx�:XqJd��qB�7�3E��z�����w��!�y�,
�2�4������0��_�?!k��b`[���$�T2�����v���������J���i�E<��pj
�g�����;1�I"����k?�J��YrO��,��a�f5bU5��SO�+!�T�{�����2�v�Clst+�����&{gn��C+X��$X*J����B�&�r9l@��#6P�r���|�v�:{xbO���#�\�PR���`d/�?\Yl0\X?��������-���4��B����s��;�eA�i���TR=7�2�����*l]G*-%s�$��n,��V�b�a��I��1\

��c1Sw�v��+�+-a9��'���q���^m�����������67���h?�-t�O���p���I�u����iJ�*&��$e-m�>r�����������(�?�5G��i�����������.��X/K�m#O�� z�O,�����`���b�����[�����JYr�]����Dtv���68BIr�������'N��PhA�Q���w���L�LW�Jcc��nH"\U��q~�W�/>���������~���)��������MK[=ti��=!�H� 5JIr���;^��o[�r�m{���6D�����X/����_LI>|U���[���r[��������lM�d&a��������E�/����������b��t@a�/T�$�xf�:B��h��F�A�%�{���������4����"��\��j��rLg$~a���^�X��VO!`�c1��k?��x��d�������?[P%��6m*����5��-��xDD	�� 6��M��<�
��d�B�t��:��S�E�$�	��Zc�r#�����?k�zim�`me-�������pG�|�{Q�m/������9���?����R)l��@D��ST*�*R��oW.g�����>�G��T���^��q	���,�����$�&a������+���-C������Sg�����1��qELM�$,A�U[
�9O9��:�:)Bd�����u�>z�iw#�6���("�$�
"��f`�Y�t�h�	�������������e	

�1\��������/��_m�C_i��W��F3%$=��
A��;8�9nf�
�����C�������+�f�o
��&NN��hb���K*/�#��<K�,���Q���]�D,����P��!��fQ��\=Jm-�1
���������1��V"��L��Q'��l���$-�����Q�������0J*�~�_Y?�b���_���b�� .����m���>�e[��	����n#�?����!�w{El��p��!�BE�5���$X���N�D����P���e�pXC�����!����S�D>����)dS��"��/L��cL��F
t�D�
b]t�������I���+���49D��
�n��</�^<~2i�Z�����3q����Vf��8|8���)�o�c��������#x�(-��-�C���'�F
�GPm7~�X��D.��>r��}~���d���]4�����#�H�S�'r����n+������n��xp�H�(���q%f�&":7|�s��?�?��O�����U��"a�����j���,��w%�~>F5z�Ob��$����>r����>z����J!@S�R�b#q����Z����W�_+	��{)�m���2�;8����������F&y[��@@����Q,0I�������h�|b4�������������������z�5T�c���x���
���������<�CY<��`;qZ8P��'2�0����EPG��S��wv�G%���d��)��4����
b�e�IX��=�,9�@�5�>���g{��>NS��~��d������B0(���#5$|�x���`jJ'�^G�k��#"���r�,�:����5<��K0��I>B��$"q��0���`/��>hl��!�G� ���9z������s-�T���_���rJ�b3���^F�6�
�Y�\�U�4���,�
:�	Z�G2.��M2��Q����UB P���0��F]+�|dzG8���Y�C�~��@��M�[�(!��vQxrT�s������]��b�[�<�����n~2�C��A�
����33��8��}��
�
����uJ9�����/��fE��X�+�_�C�7��B$���EF��M7I��I� H�60p#%f�''I���"x�.3M?�4�X��"@���w��������BAG��F@4UT�M��i�BE�hS$�9B����HQ��"I5��{������N�������WD����G8���[����7|��h�@&n�P�>J�����	�h��b���c5LT�������`�*���C/�'���	�Bu��R&���"�F�2�0�~\V��i��U�@ez�y%?;Z������Us��]�=8El����_�RY�M[��w�����!��	2QH�#i���)J��gnH�${^�H0r��p����"�s��'1S)f�n�y�L���4�d,���LW��]O�6L���&����PH��6�0����F��IB�n!3� ��AJ����@������fAQ�'')���4	�z�0P�����G��/q�����I!D�u�o(@,�����, ��I��z��d>0��0��������Arr���C����9��"�g�A��E�������#b�GHU.'(gIw�����5�,���y�t$J�T3�299�/�VQ������Ui?�
��z�;�-��/E���45���U&Ia���h�}A2�8�����Pu����gU�B��.��4zz��	��<z����oo)&4���h ��J�-j��6��t��i��������2������7��"aP��>�����0Dij�����*h����,z�����Mpw�i�ly����tXJ��e�v:�]�����$6���J�����/q�/���������y�7�X�����9�T�g��E0_�.	K3�m��J�,u��2�.'���������}tU��1YU��I4��LKu�)$�B��14���\1�)��[�$Q��x�S1V�a2Z���*n�e�,����Q�A������o\���~c��h��5��-[�`�)�����r�p=]�u�~�I��Q��:>&��;{������-)M�.Qqw$��PG����J4<G�/�9�2��$�L��p�@�������7q]�9#*�L��'�+��������}�TIh��X����>w-Tspg�O�a4�����\���:y�
�Ge��(��
=&���mYy�4A�{,�\�w�{�7s����{��:{'��Y�2�p�5�Dnv�w�<��	#x�����w��Ra�a

�-��69S��K�i �m9��d,=������&���8IST3���g�5dT��M�����r��g�M����m$�qa#b!a!apg����8`���et,�bR�@�T���u���a�z0�G�����������,��,)�xP�}�AJ�g�d���u$�&������7M�Q�<��4Y��2�7;��n��@��=J6���n��
��;��JR��C&��6Hh43�Ik=?�#P����W���I&���)O��s��dN���z%*S1�v�O�0��C,�uQzd99@���
5��2���l��A��������5��K����1���I�\y�}�������w�ZB[�����K��*�/AP���!b��2d'�Q,�"���������5��c�O�s�l��P��Y*H)�c��
��h�d%e|�OlJ����k��(Q'q�)l&�2n-�z� il�hdTl����j�J6���������
�m���Q��B��7J�����N�gxg�`f�a�BS1�qa bc��L�NP�D3q�4Y�"��8`;���������m	Z���%���:�B����DC��j@��E1M[B�s����7�Y�CW{z���;6�M*{'�4W��=/��Ng��B_
X(9_>6��O���5yf��������s�r��(�@M0����e�k_#������,�;gg2���\Y��v�Q~�}���n�K
]k�����������oo�Rz�^���wX��������&yG����}��R
ZV����s[�$��e4����`�1fX�k�H��>)X$��KN���H�'5���Imm-V2I�'?	88@A���T�g���jHr�|���~f2^d��OM�8���cY��X�%����M���]C9\Z����"Hee�f�&���F��G�ulj����x�
�,���hn�0�M}|��O��
�h����j����8p I.g3>���/�����6��6���?�����t��D"Hf� �T0�dZ��� 	i��f��k8<��z�,�t/--n��[���m�L<N��1��^"�2���yx
e�Ws��Je��,wvQ9�m��t@T�LL�Kr2�-���D�2��Pi���I��dl��!���B������w0(������ 4iq]���	��C�T��bf�l���S�x�b��1C+�n<dQ���}��C��*+��D:�����)��Z���)�s]�)U�1�j����0��Xs`��X'z�(�H\����86":.T<��x���"+��&E�"��1]�m�=���4�T�
f�df9��'�$%��#T2]�B$�1p:&���?��&"&9B33�sx��H�8N����M�9���C�`6�����c����8��HgX�4U���%���>}�3�/�������(&*�P�1�0M����K�;w6�b�
�i�$Cd�0�"=PfD�����>����9 �8
x�2��R�������Dw�z1�R?^+I@�cw2�i��e���i�2*�>;����7f�M��L2E�����r��,}5CV�L5�F�����M���b41�����zb���O+#,�B���0()��4����
���4������D���13c�w��vm����\>�x�V���w
�RI$A�/��Mk��},�h��n7}��<IA��V ���0�I��Fq=�8-���DBTg���/73��r���hS��TC���l%��������`�=�6j�i�2�r�O���c`��I��M���>=��H��Y4-E���3��cR)M���?���0�]C��7 �����hC�m��&)��;I�����12���;�9��&6�����ad��8W�I��Ua��5��PR!Fv��=� u@d���A��z��90ZO8�#
2��)/�"�IB�&���r�H)�������~�(nMC�M�r��x������G�V"�4)����h���Z������[����RF�����OGGq/}5���4W���_�`�w���;Fw�Jc�S^��+1��N�kq�/���
�_�|��Xo���:��������o�AaN|��b������K���';;��������X�Wzw<6m"�?���0�iO^���/:+Z��UH�x	�G�����>�u���j�Hb�����o��:@� :��'1�R[Kl.��J�!�����_G� ����DPbnMC�9����P�%}����6av�i`5��U��J��$� �SJ�Z
n3�r���	X��������a����dW��n~�)��2�=����R��I���5�!�����W7�%�T^�q���p����c�����2d�Q��DG��d����M��X���Q����oepp9;w��qc��'r4MW��N��_#��Bt��o�������0b1��0?F�ELI�e���q���l$�6�<�<�-���[���)lS#�@��bHeT��������t����>L�8�X��HX��l?A+��}t���L��3\�6T1E�4.4d�� C=��S�n�7���G������AR�2Q�Dl�a�SJH��)&*A|��y{p�E�����	7���,����!#���.���c��2��DL"c�%[�sx(g�z�����u�R�8n�"y����@� `�Y��LO>f/�|�c`�i�"?����C)�"Y���e��"
&�_���S����G�h�h��!�`�*#)�a�Y�cl'�(e�����)���e�j2��l�$�(�&J�3fw5�i���}��n��?��(g
5�B�(�;�FCu�m�]Z�lYP9���2}�8��gPGF�'��F����1��Q��0�{�Uy�O���j7��D��}j�\JE6U���^#�����NU�7(�n�Xd���%�oG<�$Y�O�9�'�ln�N�5���}�|��<�`-G��y��$�n1;k2<�����u��e,K������>����}Hn�����f���X��������nGa`����#i��mdl�i�^�\�J��D�������#�Ji-
��.8�iG�]q;"O����n=�����z��������E�����s��I��y�����o��9	�_������79s��vy��������
Ux�Q<)����NN�7rH���V�������>���[ID��=����
b1�y
�k��7�A��1@*� ��v�Y���*w%{�����z�������~�#"�F�y#������V���p��|m��o#s��"�l�Z���~����m��S�V���$?B<��pO�xJV�!�%}�HQ����x#���q(T��/��Ki�UR����*�A0���y�-g��4��D�=�y^�����C�Q���h�~��L�Pj��tue���Q���b�q��!j���3�iHF��r
��>B���:�u���U���eh(�$�r�
������v�[1��{��i �A&��N�(����^r&��Rw�,pV�s�����6���9�w��������h�
B�0���|�h5SS:���G�>��0;[��<k�Ds��J(��4�l�W�	0GY������������bi��)��rB�4����� �%�T"��C�"h���\���XJf�IF���=�D��(�����q�����Xqrj)���T$��U!��$;�/��,�:�����c�.�]h���?[��������(��Q��2����(H�d
7��,��{�05}��e76$����D�B�C���g/�f!�I��;��`�#����O�yG�F �?���9
*2:2&
:n*�inK=��I�"P�8��~\�l����A~L��{��`�2�H�,�������8r��G2M����}���#O+�x�'Q��#�����hH�X8�pV���pXE:��X��`Z�8L���8�YX�Ez6�b��]�/2g�
���a�����l+�XX���41L������{`�'��
��]�u
����|��g����L�m�f�;�#� >���ATSF�ry&���NRnO��:�$�L��"
4���(��1�_F����o�3%Z�v�������,���1>
j���I
37
G~J�h���T�D�Y��5�0���9H2S� `C�j9K�5��JC�$q�����9���_w0:���+�����Ba���#�;�F�N�t�j�%Fd�M����Ns_�Mg��|�VJR�b��H��������TV*<�`-��<F����-��m&I
�*J	o����a�bH>��V������y&P����ua�,c�?��j��o���O���w���|�T$	]�`�
Q9��793z7]]Y��el�����O�?����`���w����g�.��3��}�������/�/[�������z�mq9���;5���/iz��,��pI��?��A�i���|��n��8���0��A.���T���1Ic�Bo��m��ERw���Z#����
���*��_����l1q�Z��+������Rv9��>�[���,�k��/U�y-ztv&���H�80Z��.q�h��?O��Y\

h��$0��sy��L��6�~���v���5�4P�V�M+(�R�J��2�4��!8�$�������X�� �*���������U�1���;y��/��k%5���95����O�7����b�qq%B��N&~����������4���=��l3.��h�������m���(��q^JV-�$���� ��4m�$�	}$,��Q$�F�s��D�T
�w�j;����	��D�@��4���,��L/kS���C4[�������}�O�����zEn��@{������0o�����/��Mb'��]��E�����������O��q*�*n�������/m�R��L��0�!8��XA�9��$E��l�&�$!b�lZq�����?G��B��q�^�{xYJH�W�$
:`SB�����3TP�,�4���ErN�D @
>R��������T��mlt$RB������Q�������c���.t���4~4�Y�-��A��n�W�EFC�b<5��1x������}Pqsr����>$+����GC�m&���L^/�I4�(m�#�pw3w���
���3�_H#�l�Z9lB���1����,G'�����)!F�X%�L�V�o�X�i*��,+��2xpsD��r����m�,��'���=��>���}��QmB�6�����It�	����gU���K��sH�
��`�n���������5P��b��)��x5��0����=.���ye9��I�p��js�^��E�&q�}}�y�\PZ�P����/i���������N�ws_^��6�I�[j�1��i������J"R-����5�`4[J�x��d������}����9/�(b
N������Z���0����P]f���[��e[��}���)=�S&v�Z2� �t�Z�J���K�UdOf�;Omm�  ������x�vJ�4��������jtT�������&|��3tw��������'Y�/^��`8��U�����utxh�-O������K���S��r�����M�qn�Y��%�b��o�vm���������x��Z����������K�m{�v��}�Cl����|��km�I^�~=6��Zk�����30���Y�k}�
�N�q�o�a�o[���X^���L-�S:�=�X���>}z)@��D��,:��lgE[m����6� 	<�T�ee~�~WzY��lz�f����K�+���su4����P(5s��m*+e������1��{����B��n������:���IN���7���9H&c���j��)LM9�����;M�o�G���+�����KsH�����~\����L1G9!����%Tm������^/R0��qa�5"����t�7�i��gf(��u��2*��&���F��/���P|����n�$���pQ+�M�0�$:@y�����t�6d=�/mT��f�&=��$���@�*���F��W��
�3���W�Qn�Y*�A.�f�`�Y��z��e�o��4q�KQ{�����6Y��F:.����x����@)�SY��a����w��:�oi�������\�0�]�2A�yZ��g���x=&nT:8G����/�$��~��3!���^��<�Z
�>m\���_�pCf�yH��p�DXh��+�(*�G&��bx"��/+��(5�3h������`Sp��C��O��%cs��5/�)��.V3��'a-��|h6F�������$�������&�l^z�1	���!��a&��v~q������5�v�]����!07�k���+�k�d�sVI��1[\����
qJ�Mv#bb��I����Np���8�S�>p�z3�G�E0a��"��
��������,�D1��:6��,"O����9f��*#�/���X9	�MY>O�y�}����YB�(:4l�&�"3A@�4tA �d(�m��IV
�X*9���������J/'F�xcc|*���d�$V\o
k]]���u��$�������zI���j�����O�zWdR��������45!�B(uu�=�����-���{��=��B��\�g?����W��y�]]mt)$������h� 6"#{$"?��w~����zx��|�n�3}����Yi���^��}�������Ep��������pb�D�F7],�]������L�T�x@x�_d��4q���n$"	40J��J�����(�q�U��-�,|�X��9��i49?pha���G8��@���W��R�2�w@Q.p����GG�J�[�������/W~mz���1,C��lK�@�t���sY��wvQ�y��o�9yK�����]�,�������
~�Z��}�Zs������/W\i����[�BpX�)6N�7��j��L��=xE���OB��tzAM����%����06�Ig7�(�������<��~.�++2eia�M�<d�0��{����R1�`����������s�r
�����v������M�������8�A�(��e;���e#�v��6,$�@�$�z��`<]B�
�au�C%-�Pb��!�����g������3��������"�Z/p�����6:��Y�������q�^@\���m��3�=<_��)�����AT(������T�d}UcC�f�G�dp��m�!C�B�S�^��w�h�=<K-�<�,�!�v<w��7��O
�PM=,c/�0u�'���CX��|xQW����q�Z�����F�O4)%���F�����RF�&s������|�{#��#��jf����r��M
7>@d�
���K�BJB�,��c�k>C)q������gF2E�\������X��c�I��^$�x	�k�Qr����pw�xib�*c����5�"�he�x�������/^���Q\F:??,t�����:�3\��h��'P�sd������m	x�9\�9���5;�<3���;�W�g�`3#LJ�ts��F�II`Y,l�B����m]O.��{���$�����%��L�gn;�� �J����q�����G��E�TU�44*H�6l&�j�c��S�s3d���V��Na��[1�y��4==Y��&fJ>AYf_��u�q�#p�p��:���_���|r����1)g1���|��f|�&O�XG�1B��B"���=����P)��6�����+�;a>����eKp
�Pz�j���w���@���Q�&N�g60,� I03���^��tG�9�a��2��#M����w8
u���yZ�=��v�d��_u��F�����qt�gX���7]G`�F�-Av	n�B|��T���km9���;��h}�Pk�%}��b?^�e���K�m{=v��;���M���>U�6�/�N>\��k�q�����C�^����^������-�fH� ^"43�id���)2D������Y�hKU����Nwc|�������'5P���7�1��!�#�EVL|����mK,3YgCk[�pg���s�::h���i��)�--.�e�p&Z�25�*�Q��Ib.��t�
��<��(��+��	
I��(l������9���/NrO�#�����f��	H$��Rb�x��@������V���ks�d��������M��3������D���, �,2�������';��x�Y���/A�p;��u�����A �a�,g
]�0��A%�E����
	!��x19%�g��d�Ksn�S���9`i�|��U�3���H�YN��n��&lLd�f�@&����
��V���Y��-���^p,;?.7��Vc�R�iaj��
t�����^,|����p\y��������������8`��;��<�~�iI���<O���R5�\�;1�~5��|+N�t�q�G���a����������������.�����>/<���g��W��x�������t���0�������t<"�*.�uB���J q��`����T�+�4���p�r�D��#�9-&>Tn� 7Y���e�"���)b"��_e�V����RB��������aJ�Ir����.��>X���D�m�`e�)^,|�,>��85��5��#��D���x����#����!$$+����$~l�q�&��q���x��0�9��9�s���������s����aa�X�|X�&��>���8�g5��K��[�f�$��E9�!P|��e��:������h���z}�hc9^��8�A��?�����o�/2�]�;KC�;�1�Xm�!Nk����q��Z��?sC�����"��:G�����r��>�>���'�1{,E�6B�L9�D+M��F�L�j���(
��N�wp��4�]���}�S��1F�����%H���;v���L�"�~+-����u9����aO.�h2��/����>������F{�o�~<�
�����w�y��Y�I�EX��1�qg-J�L5�n
�L�E�e��b�������������?��Z��W�"{=��-[���5���F  ���Z�\�� ��ee(��(����{.��@e�~j�<�\r����[�"WU�ON�M+^��--��5���Y�4���q!�{�"
�9�}�=��y]���&��/\V#���������J�Ax��(�?���q�"A�J�"��EX�!�[��m�i`�r(��U�_�j��!�����:��������6�E=#��)*�it������nb�j2e�(5����E�M\j��$�������gA�/��ib]=�s	bJ	�27������e�>�eI`|�zv������-[DU��0���Y4�K�}��o����I�������V��s�u��BBUMzR����*&1QP$�������Fz1#�`��,&"�
�� D9��R�$��p�R{�P�OR=�;�c��Cl`-g���  #��&@��s4����~���g�;�;�3�2�RB��
36@���x���}�{_r 5��B������m�c�7��FB���"b`"���G�V�B�MU,wa��0�|,�Xs��]%/Li/8'�������������Gf��A"��0���#
�(H��)��Q���I�&2�<�������Xf�S�^�x���.2����l��x�0B�.~G�`Cb/Y|��M��buv���h�#�*�IW�}�B�!aQ�����@D�-LABF+�C��d�������m��^N�1�{j�_�LM:�O��sO���0�m�b
���h����)�h�A�}���-m.���N>�6pOQ��%a��)��/�#�/�L�:��xJ|?�2��Euv�J)�����#U��I�8D{z�q��
�?�8��@0gs(�)B�t�����4�E�WgP4���mF�p�>�?�q+��m�B����B!�B`�n(��d�*w'f���(�C���l�XL��������X��7��KH�����Dh��Ra�� O=C�A�4�ft��w��>P<n�'jJ��}%u/���}>�F�������tt�2p����4�B?&OG�=��Blp���4[��6�w���hv�D2F�
���Kk^������{��������?��_�p�4����K>������F`��6��Z�Z�v� z2�����<�KQ�8��MQ`�J��}�4�I��F�p���AEq���<����i����e�����1��j�����ff:
����d��cd��c��X���o|e���~>����Q�k���a���K-`����C�S��{01�b	"�%�w!C�#���|��@�(i"��'X�;��#11y��d@��i�]�4&��X����$��G�v� cKJ�Gd���Q6�Js����57+$����r�s�V����Q��z���l��Xt�|��q2�qJ��2M
��F�[���)7��	M/��V�>���|�!y9��,����K����:�g��b'��aZ8�&�p�����fP�r���V��\O��	l
������M��Q�M�
��H��6F�V!�J>�V����[x�%��T�C�%��p��@� 1"�;�#B"q�;8��,c���K��NG�P�O�<�R� ,�b�r��6���l��u?i<d�f�M�^��!�������viRa�9�������
V`���>W18�����qc/�d5[�
`����p����y�	��L��d=�pY�Ko�����K��W?�������P���������-�.,�$X����%�������w$�b���	������Z���xn��G�RJ���4'��Q��#�c ����@��������Z�����W%8��
����������T��c_��1��_!������w��V�cK���4��k`�o.C��Q���!B
���5	)���?�EL[E8~���������t���b1f2n�e/PN��6v�O�;h��b���&����!�|H}�3��������Or�x�n�H@&���O����6T)>���Xg��J�E�:�.�`X�f<�i��*V��:�<��!|����_E���L?�*�:��������Y�����F����|����-(����1���e(�E?�?�!�C��I{��~�?�����>�B�=��C,�=����E�h�>���3D�����'QV���N���?T�pA��]fj�!��ez{u���z���#�g�0����������,�.�+����W|3L�M�I�����������_��m)_�����_�(���O{ho�������������b'��[���rR{��72b��f��5�e��������R��|sd�}��jnfLQL��=E��7O�1u4����~�����~�������gg�9u��S��|���uW��M{�D$����$M����
!;��_��p�d���O#`s��j���]���G��w��r92��x>���GQ@h
;�b�u�.��@���a`	2�O����V�a%n@�����55��"����ca�����_M*UM�^��,��)j��d�!n.��o�^����A��6�}������,���)e�x�����J����:�yk9�a�IA�T�H�)���TiaJ�8�V{�O`��Ij�����i&��G����Y�cx�,���j�����y�{?�r9���$SS�
a��r�Ne�a����^�d��h������;�Zfh*"�+o!=�����PG$�����H���sxQ��U\J��7�@Mpa�2r(�X���O��q�]�t�~tA2��g�b^�q�b%I�u����J=�h�da���<b�??�wtj�Vq��D���j�I��6��1q;�8�w��.dt�y�.t���rb�F)�R2���/��-������b���]+Oh���
����(�����>r������v!�:�����!�k��nt6���7���2a��;��Jf����S�:����n �=��d�+,�I���"�g������%*L[4�F�\���cV�hc�Z�hf�i�
)���.+��C�(T��1wG�M		�x��<���,�deY����_r�y@�!r�,FW�� Qa�����*x���I��H�)�-��W\�1M�:�8%b������&�\����e����s^i����:p�`6�]]���!h:n��YnM����7�?Y^C{���Ejn&��N����,�K�:����_��8���,�oJ{;�����������t�r�%�=,o�Z����g�;����������q�����S�$�<���>;��?���##&��T�}��#����h�S��d�~k|b1�eLA`F����������&=e#��SE�q�������47/�]����9�5in��W2���x���u��� ^3M����g�"�]>���
�m���]�\�������������{�����
�?��#<��#������fO;@B]#L��==L�]+����+�0����74��f�dR��Q��i�La��,pf���K���[��{�;���3D##&��q��a���iy�u���������v6�TZ�q�����3�K�����0�B#Tjq�b~2�IT�|��4���>����X��7S����)*r���,��������	�Z�h��GT&'��X�1��+�y�4���&�a#�*��=T�	�[�l����$�����66��W����gsI�<��#���b?��
S��	�p���{e���&3�l��R.LQ%����i�?in�4���s/7q�u������$I�3I��f��OM��y���0#42L�\����|i�z��(jM�f�k+����3������@b����1	���Yl��&D����
�nV6��Mn���6JH��8"b���<3�/qpi�%��b{5�����hjb�{x�f����O&��
J"�<������~��Eh�r���TNS�/I�z��<��-v�Y��������9, �������<y�m>��F�q-��j�����Rs��'	����E!wIir�$l*�R@��;<�r�������s=/:��1>��/�������P��'��q��a%����=����8��i<�T0��6�rl���U�����k#!�&�m�`�@������6����QVL!T��iP�T��,UU��FX���D�bd���R@|e]�)��U�	`�
\�����K�r%�Q��v�?iV�]��+x~�A69q���/Q��@��QmM�V?��%������f����N�P�`<�l!���'Xu�a�pXV�/G�b�
�9�&l7�N������r� �lV`��3��T�j��[�m����oQY����7��4�m�a������6+WJl�,s�0��G���1/\@��W[v%Pjnf.i�>:��/P�}�ke������5�o5�_~d���@h1��k���~�����P�dE%��X����������8�c�TV���	�e\h$��FI���\R{������e����D,^8Z�=a��m�e����''!����E���	sd�[ni��q�t�&����n����:�������N����E���]��Y�����P��u��'�D.�:���������o��w����9�wf�f�&
`c c.=�Ca.��$�A1���U�I�p����`P�������;^O�i�Kv��/���Ur�"Y�h�*+�(	�^?B6�`����1G���I���_`Z�H��DN�v#���qA�a)1F�5�2�A,(��l���!���Y�$c�8�U����Y����/�w�'E}�w����8i��,��Z������^��yZ���h[�{�>$]]��Y��T���D�
��YR��SN-_o7"��"BPK.��5\�D�cb�
���� ��HK��:0��w�%���5���M�Hf(���M`���hU��r���1YLZ����^f�`�|����|�����	Gv�` bb!�!#`�};��6���9��S�$*^�"�7�e�������.��;��N3� ������b��5_e����h��CxS���C��w��0�����>����3~]p��/�5��`��;C��	0ML���U����������%�\$78���!�A
s���f60K�We��0F#�BR2�e�HDJV#&�T3������q�����d$/y��6������U����xD��s��������X|A�sr'RT[�x�2�R����O/��sT����>�{�F����y��$�#��GS���*��������]�do1���_|�@��m��>�1��J�1:;�7oF����>�KOQ���,����E�xZ����P�R�����t�}��yP[+�:v������I8l���:'N�$�6��*�����?���3�-DQ�:7�P&"H� 8Y�`����XR��LZ��`8�����9�0��_�P��-��o�w���|
�m�����-�����1�,Q�I�$E��M������e���.�m��w�����������������
��������l���W��}	G8����f"���}�;�����67_��]W���T�.pw��);�G�p����g�Z����b�Re�����|i)���qv����b�c t(p4����Z�u��$����>$������FF�YZ���y�\�u���PsUWW���CuuK*
�$�,	�%�8v�`�6����'�����^���^c'&�q��������������T=V�Su�u���SU]������c=O��:g���>g�����]���^z����r�Y}��=������`��t��R���FV;$�B
��A���l����K���x-���H���b���y��E/�2������Nu��?�a�u�� ���'j��V���9�v#�N��1t$�8I!"
���)c���+���	����)C�j#[�s�����dHQ�(+�2@�BV���m<��h��0&M���E�=O��e%�
���q4�@������������0�D���(;}�[�?�Q����9[�1
�S,�S`�rrX��|�}�\+�+���F	P���.K��"��
�)'���=��� 3��A���4�3<.eK9@g��Kn�%�
F���_-n)'n9�UX�{�A�"-���S� 
�)��W
�.���{W��h������������HL��5�������z�������g���W�nv�r�@�dq'(C����� �O;i�ymz(}�.���V�$$�����%�\�:�+x=��x8A{1�(�3��ab�3,���
V���b#Av�����D&�J^`+o�>�P��e�@��7���P��
�i*�`cg�`/����3���gp�E����:M���r� Sz9L�l\`�X��w]���2\.���4�� �mA��je�.lV��A7d(�v����C��F���&z\��g��l6��*����V=H�9!��Q��JOn<(��H.Q��ccTn@�DF�2����������)O3GP�z4&,.�o��&*��|��HT��FN�Ro`SF�x�
���%��~�E��l��c�.��9s&F}�4�VI�>���;�l��)Jw�p-���EZ�,$����j�.p��?���w�H�>����O5mce��#e�r/��l���+J���!��m����NOO��_�Rw"�\E�h/��W�t
9����T�*�K��d�����Oq��c������3w�_����i=���?z��5��K�b��{����z��6]K��_���A�xp^u)]G����/�n�6Z����,��5����G��c��Dt<�?:���)��v��5P�eB�Id�&GTQ@����!{<�������{��glL��|--�S4�g����0�	a+�p8��/�I&}�?#�{��*X����e����;hl���_��r%�4��C�%r��6}A@����8%��y�@�qk+����?���9��vP���$����G'0F�P�U?A�.�!@�c��APK|Q��vQ����+criv�W�v��aXh`������8��E�"��q��G��$I`�e�Ub}�zz2A����3�
"EPO2TP���8uC@�����������a��q<4�����"3$	�gIi3�53���|/c����w�?EM�]-J��2���$�8�a���h�Y����Kc'MKQ�����IUX3�� 2�i�>6�0u��7������Er.K�tVp������,.#V7�AT2����&,���M�$����k��_7J�_*f��R�z[q�Wd����yP�@@������x9O�����aa�����������:p	�y��
���WuLV ��Lh��V���/J/-g��Y����H�@&����j&p�%�4$����
��y�0��Q�2&��s7S�HX������VM�	0����R����k8M�^&��m��b���|a\
�w?e�V��(_���F+����nC���Y*���~2���I���Ey�E<G�x��q���@2	����g��)��9��8q`�,�i9'� ��;#�pz������Q�������:r�W�%�L�C�@����wk���1��#G����6���=��mY���=t�� ����I���d5��,O�`h-�p:�0��|���/��9���.�������.�[]���2� T�j����f|�{�����-����+_YE$����|��cI���KCu��������W]��d�����b����-{����*)�����_�����U5#�����-����H$��+q�k��@���!~��a��h:��<������O/�Rm(0�����/K�!�1�{�r�Q �RG����~=�C�pm�� �d{{���Kf���=�gZ�/�,6&vjG���2�����%8�d���i���>��������7[K�Ytt��Xle�~�6�/���G�� ���P.��iD��9��Q����X�z%ZZl=���;y�vV��v�����<�36p�Q�d����'��nC�&�i�����>�	�����F+������IM�����p�3Y���S��I�0l4 IP��2j�� �S_XT3X�,� �^�����i�t~����S���(W�*��`�m��Y�FB�=����_h
���p P^.�0~�(#��JG��6^X���B�QC ����c��|���b�1L���0g�N��FP�*�c�|b]7���bv,tvtJ5�/���j�"��*26�hH�G
2f�N�����V"����\:&��d��2)����
��g�1N-?�v�p������v��K��cS�
s����H��R��7�=��(�������P�*�K�C����x��l~����s��Z<�J?+5S�����eXQ�0��Y|������������>dt�<�X���s�E
�iK�^f�����q������{R�v�|&����C&��_/��_��	��5�q~�>��	��Q��Y�@A&B1�i!��y��lQF�%8�.d�j�4 ����U|~	�-�r�GNV���nd�K��Fjb=hX�! �
V2���`����\����m$9�6����&���`B�f�����{����u�v�4RV'%��e����[�����,�>_�d;����\�N�����T+��_�������A��VT����B!�}? ~f�������/���+�z%�|�dG;��fI�d��;�v��i.�5`�\�+@��v�I�J�
��/���-jA�\
h�G���U��7�'��b�l����� a���'��-T���Qah:��%��%E�M+h~��

V�o���4���]����/�a,���Z�\��H$����X��-����j0��%��h��"�>��=M�P��'#xj���58�z&��Q����\^�
���<�M��2'���V�	�Q���l�+��_��������u3�`0�Pw�]8?�JEU��(���G�x��q��(��F|&70���8N�Z�
���@�+��d~o�8��������
!�xA�MFg�Q��&�U�H$��#!����)��l��.�9M��A��������Ap{9��}����#�r�t���4�!P[+����t���|�zi�������
2��P���$t�{y9��p^����=��CxbS�>�0iO��F��?�.c��>�Y����O�~�l�)w=��,���Hk��t`5���)����8:0H�����
�T��5V��m�{�42���rI�f"���9���>\��4�/�����9An.E@��b����F@��b�g?����p�EOH�kX=��)�l�%R8��R+��	y�DU��8AuGZL��bs/B�����q�g�x�T�K�A�o��J-T3��������'������o`��M�#���i$%���b�;YV��,>f)g�j\�����A
1�!�"�<@�����o�A�(��Ac1HT
��K�,���Y��#�����/*h:R6�Z�Y�-Sx�	D}��~�6�����_��.d���#���)�Ec&I"�*o 8�o��n.������*cQ�Hx�"4-��I_~����P���9���>>$<A�P=���U���
TGo��(�$`>��>r��/�����D77f�����i��[G���b?4���"z�#gX�B&�UM�3�Z�V.`%�,>��1������:z��C���,����$�0N=����zW�M�.�7���C�?�-�3+�c��&f�&l�d�q��@z�:�LD	CU�Yj���(��R��>Z��J��\i�{����Es�H��������dk��b��Z��M$p)>p�&�0�����_�_���r���eo���7p���{��/~��i444����gA����Z���2��s����p�����WZk)�;2�=?V�;r�����������&q
oo/�k3�`�[������0���4���� Z,� �H.�������{�����A�z��ZXqU%C�3����,S�q�db�8K��U���w_5������� Otu��_�V���\��������e#���+��%��f�j���3�dk���bC�;����������b��H$���`���s�m�a���C��;���gs�.6r$��9���?��!�v?@��M����v������U�R;u�����6���3�YP���O�=$���h�����&s��7@7U����SV�E���'�M��QUNA����Ps�E�����Ur��M�QO91PU4UGPs%��&�At�A9J3���9C���J�"!U0�43EI�X}�%N!MN���f�f�����Z������f� R6�d7,3�PD%����Q�y�~������('���Cd���PHY+Q-UT%�\Rg{��j�R�6Z�^���j����������}Q��n�SK��4��4����:��2��1E
,(�0�Q�)a@a6��z�FQ�����\�������X���o2*sxH���	���Iq9Vh'F9��k��',HA.�^E�E����Ei�
rqt�Y!�������J,����9,���o
,5�������g��|�6,��(����+�&��a=�3V<��@1|T1��Q��f����l��b���F1�,�|P�����+l����3K��D	�0�E���a
����ndt�y&~���%5��Y��q���~Vj�Y�����)��
 ��������]��n	U5x�� ��~�O�/H"�����x/7)Oa 0 ����(����n^	~����LyBx=�Z:3+x��Y��66no��3����=��7p�����
����9QF�2$��Te'�+��O�Ep8��aZ�3������Pf�/��*�(m�Q<�[�Z��7�������\���66�N>�����u�,�x��s��*tt����^2=�az�n��	��o���F��?���Hf�����������<{��L��K����p/��P!ph#HK4���ol�R+�'�����s��x|]�8�br�79��%b�j��n�������KIDAT���3"���u.���������^t�J���l�~]_�������9���F������
<�x��K�zrY�1��t��S?q�5NE@����/k��v��m������:��%$���]����r��RR��4�^����*��M��6IC� �x���UHb���P����������������t����Ts�����"��ck ��g���eq�_-#~�������kf�D����z5���W���u�R�
�e!~8�����H_�p�\���zIT7��������455L��0:�P[k���hmu��+i.������\���=m��(�b%Q��N�d$Uvpc����9J�7
�����Qt��={����� }���:3A�'�Q��j-J�2�A��S�M��4&��D	�a����'�M��6��1V�Y�1����8��F9 .I��o����5��~:D:m0ek���`�~��SK
V���0OP)�L
v�1���B,�,^c�����!�Z�B
�a���������>�
�Y�
�����S���`����k��V�8�LLDcF�@��7=�KO�$�L�*L�������k1-a����Kn$S����zim����b9>f�`�6�_�o6���z2��c��{%�q�5.���K����/��r�(���]8W!�Br8D{��UF��&���q:K?�v�����Y.��[����&��%f�cA_+*%�7����]I�!����Ew��=)-�������
��&��X�M�[P'��]ev��3~���k�2�6�X��;�@&���J:����
�x��Q�=>����C�lA�2�}Ca�p�H9��*NA$0q�����m����S���_����r��W����Cl�|���c(F�����fub���O�G���?��_��=>��i�XsY�����l�_����J�I*q*��'q�T4u�0@��E	����q�w��Bg{������C5,��-g���"�����YI�$a]��/���������?����`��]&�~�~-��.�p+�����K~�����������_�����Sf��gi���R[��&`�������i��-��.c�7�(�a+�Z���/��P�Vd�+W�v�� @�(>A���y<xw���������������.ff5����mld+]8����q��f��g��}}�J���b�Wi�%��k�W�����]~��[��$V�q��E6������uM`��G��R���j�n��a���������N��i[��&?���O�
a'��/��5Wma���w�d+��~B��A���->����2��;��+�V=@]���x=�F9~��P�"
2R�N�Xh���S��-�9����S���������hV�L�����WsS�`o�'ZV��`f.�u���L5�0�U�m���d+�%�c�E��@D�|���BF��n~�le'P�Z�s������x��4��+��8�����6.``����t�-�	(,lN5����4�^Z�����`��b����������d��O�uTd�d��Pu
+���i���M�c�5�x��M �5��Ql�����te�����FY^�}�SkjCV3J[�&��^!H�������.���~����0���������i�%��_Y����	\���q�5�;�E`Y��4}��Q�~i�X�=F�
^8�
v��H���I�Oe�9,(y���kl\��h�"J�Ts��(��i��$)���QM�������q��~�l�r�����V=L=�!H*nI!c��J�2A5�D�bZ���`�e�S�^�d��5���Ql����;�	{>MVA&��*��c��),�9f	��UM��:v�X�;-�o�8��X�:=jd^��)����h�G0���:q�	��l���^�:&����J7�������1�
�c�2V�$��[�����Kg������4���$9��``w���dp�
�
;9*�dU���\=�S,���~*�I�&�z^�������������3.��4�"� � �JV&�*��R Y�K*Zp��z��G�Ck�-:�{��x�	�ca~�#�V$����� U�([��Y�7�Tg������[o/�g��&[��!��%��Z��q�����Fo�v�}n#���a�����Anf���O*+�4����:jk-]1rC*#������'Q���k��z#����vU�W@��b;�����`e�P�
�8�0����zq�[���0�_�==����5�x�f�������4�z[H�,��^��=�-��`%����A��v
 |���`=�}1�^�������/�_�5]�-��e�m��/���a�k�HY|��f$W���~�>q+mr?��#x3�$T�9�jV�L�s�Z��J�(m��l.��a���C��/22W�}e�������]����LOO�����xD�q����b�N/A61����&�$�V�l!��cXg�f
���
���@����Q��	��l��B�E�h`�j@��c��=��C���HdU��������
��5��B�F1T�QK,��c���1�����1��b��a��3T3��d�����q��Yfv�A\+nR���`fFEQ ����D2�SD�tT��Z��]��T��q�0x�mt�n%.i�i|oA_EL���l%�;�Or�n���[R\5��#��Q���1�v�g�	�Tb`�d4]���P�"�*��j<�_O���
ccu�,T�A�z?S��a�z������������L��J�p�d�\=7�P�D�0��P��'ig�.(D.��^�j��k�� 8d]��D0f�X�G){r��*%��B�u,�������T�8�@$��'u@m��"��a���_:��	������S8�����[��1���ji|W�vA�t:O)0JHA�E�v��1�V�fB	
h)[�~)-�@�'E��hhy�����y�^X@d��.q������/������TQgI�*��o��Y�����Z^9,H�b��c>������3:�ZdD'd��b2�%71��0&`��y9\
qA\�x���on���Z���J�a����M�y�\�������G���C�q����w=���dq1����(�

p�����)IRSc����p ���itOV����}X�x23��9R89c�fm��<�n�?��=�K,��'�[�a�{��7�
��~��� �0R��<�!`�k���H$��%a�Z9o��@�f�dIP�LbOdi�<i�A&&���������7C����fjR��{<fxX���P���m���%��K�}_��w������=����{�a�<V�$��S��B�,��}�����2#�4{�7e���>��b�j�C���I�M))f�+!ry��R���]��1���4������������m<�D�+Ju^:�������?�
��>$���F�;w.8~)�������{v|�/������?z��?�4���X&��#E�dBK?���
��>vv��Fs��H�.��}�\*GN�c4��h�5x����p���]~"�l�>���F4�czZenN'f	1[�����>��-2L�t��B�Zl�;�-;s��J�p��f\�������O�%����C}����R�N�P��D$U�G@�p�ilm!,��8�I�s��_���u�����A��o~��J!���[��D��������4����U�U��4���
���������g��|AS�� �a���D'S��2���8bv�i�>����}�-|2�*�$����1l��-��<�:�U������M1?SrI�
��)�c� Z,L���e,�1�g�J �8�\�l�N�|�f��N��l
��H��J�i��O�&��@���r��B'KCB�������>��jc�f�Y3�E����bx���>NE^����P�G^[�Oz��[������j���>;��P��m���p�8%�(~.,�"�����Y�zK:Y�P*e���5H����wR9��D6�D��-J��&;)[�����_��?���]��-�`����Fq�W�FVr"6AA�z��[���3�^I��Q�4�	+)#�U�R���7[4�X��h%�1�B�`Av9)w���6a;w���B�
o������ /�*<��nn���X�8�m]�������o"k�;$��~��0p��D��Vn����L��tZ�Ak�$[�_!K��P��7.����5��a73zZ������L�H�QD-C�1�I�a�R��%r8���V��P���O�����f�	�CF����[h~���R��|�j��}�]k8U�G�&��}���P)��?��2I(�&�����3�m$���������o�Fc�������p��D�e��� `ij@�����q���)�
tv~���&���������T%/0�m���&����������"J���2��L�;Fe��8������0}��h�f�����q������$^z������}�}����9q������V���X==��c��!�\����Q[;Ao���j������zC��^�D��r�
��D����J�YhGO�:�s��n*���,����-4^Gc�����b�t���8I���w`��\������S���}��4'&p�=�r�������C�k-$c�;�t�S��7��mW��^����s=w�V���������4�����M |�������&����l$������d��Dk	�6������vI�* ��f
�W�n{�u�0������$�'������R����,6�
�f�z2�/pv�3�����d���2�duv��C�xH�� ����

����Q����*�"�g�<���C�
�
�so�JM����yD�Z��^���^�������#F��/"m�����&��TH��yS�b9�&��I��+����B��A�b�u��7�"�,����88�6�H `a�&.��s���]�������C<4�G3}�����U^`�r��.�}
�Y|4�D���z�0���X��!e����H��6�w�<���7&�$sDC����Buv���O���������;I��_��4c�VS�8gX�����#+������N2�Or��Q�����������2,70�A�(
$q�������5i����a T�S���33�b�M�����&8��	����(
��)ce�>�cc)&p�P�|d���q���a���|.af���
���-<���`�(���]n���c�B\����������h;��j}	�Nlv�y=����B�s�@Q8w9�(XH���\���Y���� �TB�(�Lf��)}W�,6
|S�=�'I�|�30"
udD���X��?[��Pz��M�a������;���u���H�g���8�'�g�	
�
g"Z�Si~���|�"������S����Z��OJeT��!�;�O�=�&n5���'�
�$uZ?I�XQ��ou��})�-��_��qk%~q#�Z��o���&X�Y��l��9M %:�fD*����� ��Wid�6�ox"���1�
��r��!�]��Y�P��,����,E���%�P�ff�TI1D#����0H�\})���n����g��������H-�� o����u
��#��.TC�a$����H��_�j��:IL�aq�q��zQ������$� �c�zjcR-CE�<O�(�[��x9�����j��V��`r��Rs�y��:M�Yrw�1_�������~��g4v��.�,�w�Nl���Nb��1�g�_����K�=����,_��$3��d��&,��I��qD��\_�����7��i���2��s������,���+�S�`�+���i�`/��R1n7Z"��%�����#�w"6�@�����3���8bVE������E,�qa�qv/{w��'��}1'z���DQ�LC��|�O5�%0�2�_``*��������������9��e��3����[P���H^��A��$,Vi|�4r9�2^t ����������R[[����pWC'�^vo9��D�����bef���E/�kw���a���a����~l������|Z��i-#_���4�S�����[k 0+Tb+3w]��^,�@������s�d
�5� 7���=�i_f)��&�lml$}�j<)�9�����fMP�*.!MY�<z�+��#������&�-kE����s�����O+���7�T��R]�4���)��3���a���&Z����b-��]��rm3��$C��1��B%����(�x�*�K�lu�����v'���7����4������Yf�������}�b	Dc��E�	v4E��" 0m���i����YI���"��-g/����y-���N�0�_T�+-�E��o��9T�������YQ�%�n%�)g��0=� `@Nr`�
l��.��N�>�h���=6��2tt������2���:���#���0��=�M��I��k8���3�9q�5���������QF����2�Jj�^p:E@v��{���w�����v�z��&�NO&qm��������������a��A�$��������0���b����S`s1��b``��u�!V���t?^7+V��yZ��I,��H�1��{�-\��~�����t
����}?��n��<v07f��0Yf�� ��p����+��TR�l���EL�p�NC�!�j�:���[���+y��n��.sq,�NZw2nT2E��������+8<�@c��3=T���d?�6D�uRmK��T������P�T9���m{�����	��Y������N$�ex��XS�U��?�g�������nw
�W��N��}6f��e������.���x��{������94�G�d
�W�@�&���������S���"Xjn(���A�� P�����z)o�bk�����1��,#��(�9Ud4[�O.�%S��,��V=�a��7�b��B6�q�DB����V6��|[�z�����7Ks|�����g�a����i��TP��H�u�u���=~q$��mE���a��7��Z�����n��|���
[C�PzM�k����9�����������zz2LN����7��B!��@��9��w�H�ug���	�}���-[.���u����8��Aq)M���8��Y{'A�3��%;�,;�k��s�-7%!w��Z��"��d�\��_P>����>��/�����r�9�q��z�v��W�sr��.@����>�KB�@d� /�KT2�F�\��k �����2�g��.n~���{�4��V��t����\"��_�������B�k��m8�^y�,*.�x���QS�0��Y���O� Hk��������&QE�2[f_g�??�$	���,�zn$3�<=�$��L�:z[0H[��������O��?=��zNR$q�4�Qe���o�S�:k5�"qW�_�j�8���j��� �a�WPU��<f��fw�����
I�9�!��$t]E@@-`��:N���~�A~��?chD�)v%P���	������5<��?��H	�h���M?R����
19�y����#��{|���"3M����(�i���x��O>��LSAX;(T1N�|`���`�)�h���0/R9uDfc������	~��a��+c���y���%�8x�k��#X��"Y$B�)e�/�3[`��D�/�O��E��K���0��$6��1�$��!M���l�"PAhP$-��J��\s���J���J�dq_T,HN��E�@��b��A����'(�X��	���������\ug��Z(bK����YlF���=�,��u�Dt�\"��&��&A*3i;z��2'c�������LR�RL�,g����FE�_j�E;O1��b%��VzQ1��5��\
C���;P�^b����h~��g��PA
'�]�r������p�K?��W,W�pcz73�eQ�p�-9�Id%G���\4��y�3�
&���3��$z(���~���Ob<a�J��g���*T����H$p3�^�KH�����E^�VQ����;��{�kfh"�h����a��MrFX�t�Zn�_�=|b�&��B�3�T�D��of��E��hl�rp0G��V���2"���f
����5\��L��?������%��gfFE�[���;�%~m���	��4�����)������~�'T�;(C���{c�)Ks�@�DB��+�$#�6��x��+�`(
��W�)�����P���O��� �.Z��Dne9����z[(��k�\)	��4c�����ioZ�.�
K�����K�Y�muj����=����h�d���b�����w���b�����)����������d\�����%�0���'{-��Ld��Rj
��z%Z��gF�z�`�
�r����*�JS��ub�L"���_`K��LU5P��}*�e��>BvU3��_K��A&��m���((�u7��� U�� ��Yl2�@��mPH�q�b��!�� U�7|�����4��)+�H��0�����#��FE$�g��O� 
]&@��+��-����Ug���lt,�FC[9�M7P��&�9���s��z�d[qH9�H~Q��
�j6����,A�����o}��/}����"�R��aw�������/'����P����*��C�w�Tm��TTJ�=a��8�n��{?'{n��1H=�j~��y�%6�1{~���T�<��6��@��  �lT���<����p�"���hIiH��U�E��}n7�~����vm+��o{����glW�t���6�>�!����Bu���]Y�RW�\\";5��2
k��(9;��uL�V���p� �����;x�x���Lh�$WBr�D�3D]G�F�wv��V��u}��tO�>��A�8n�����J�:��@����h�?O��b�
HZ�����d�,������M�ed9��,����+�DM1��=�n�)�@pn�@�����+w=������|���ub��T�(CC�<� �]���x=�C�PG�hvd�LzZ�4��|�����Y���rQ�������D���4�u��s���DW��=����l�`��8���Fjw�����+r���8�d�(u<�R�(����-q�P�
��lLG��Q��$�%�������"I���Bc��Q����t04&��t��.xO�$������5�ty5��\WE�
����N�/�l�V��� [�>��@^O{C�g(����#(�	�s*i\71nma��T��%���39�����\,��ed1�bu�ex�"1��2_����p.)��&����R���>�4D��T�'����c�CL��?�� dSi��*Zm���.�I��i�{�S����x#lY�L����(��d�y�t�b��t�:��M�w���li��w�����,���$��C]$���Q���x�xDT�J��>���k:���v�M8vw�����q^�wf�����q.*�����k���m|j���x�}���������E��3x��d_3y��/�%}��-��s���J��
�qno�S{W���,����D��r��u5L������|�k��6��5h�|�C4�-!�Z,	YXz��H$�OL���+�s9���S�mr�#���������f0WG�>��CI����y7F"Y,8n^x!��%16���fR�ZN�<`��ld�	d����E�|����m�n�d2�5�l	�a5Dmv�i��	�dd���|M�8ld��.��8":0��>B�D}�X������P'Z"�R�����9��fxXA����6�H�{�Mw����?�=�2�d�W?w��G���G�����.��MmaR��[�Mv�X
$e���������PZK���]�gS���3=�22�2#����YtO%;j^���ffO�#9G�%��iY�!&����E?��������#�8E�@1`�J+����jq�UlE�+�
'J�1����q�id��Id6#�TS�#��z5S?���HtG�1j8O?�^����nPZ��� [h,�26#�l�2Jn"I�dpb �.)_�����d��
��/}��c� H����)QR�
�xA�;j9�j�������_���ud���1{�n���g����})/�<�G�������!���yY��0��`A�b�038b�����ogGf�%�3:9�{f�x
��:����g�E1�����4��X$��Q����y��p�d�zj�q����Tnoo�x\c��Z��_"��a�t$]����$�|�|e"����&���8�_K=Q��a%�!&�f
�z-2

V����I*��@5��t��;X�|�v�4����7�f�T0M[1�`)��	������3��03����!{/��c�$H���#��/a�����C|����1<�/��59s8)���Hu����d���
��>���2�$0D,����.�
Gx��'�Dv!�o�v�9�3�(u��{3����c�kSX���������G���7��y��+W����3��S��!�N���L���t��� �|]:�hef�r��l�V ����f�?�����b�
D��B��r��W���vSr#~��f���(km-����r�DB#H/�=��+�J-i�� �N?�����N\�a����4}��EO6!H(��i��j8� ��e��B!��IEAt�,���3<�����T�����C[�:1[������#�R��HC����|��M2o�x��y�w���k����6��=���������+R�x�~�����oB3iq�|j������EI L�Aok��v�Zmlq`�\����3H���1��1�e���
;u�`/3�������S�T[�p)|w����~�}�oX�����?W�D���0�O��(�w��Y�aKN�L$��n$�gY�����3�V�tZ�D��~!H+b�O����=X�^,���&:)Q��GB��%0
e����}�����
������]r�<'��{X5yW��D�,e���4a��I�8�s��r>�2;�v�y��	�{G1�z�P#����Q�u��x+��v���1��C��e�&����Qj�A��-�����{�u�%}x��7B
m��s���(R������qj����9>�UF5��lZ�5�W�)Q�+lx<�;����.���p_����	��A�3��x�!���&��T���*w[uf��L������N;�G%�;Lv �UI �v�6����V�:\x��+�������p����N�X������?��	�$������:>����C!�jw���� �f��9�O�V����NU���L�T[(Dp'���/h9		�����38�Zqd&�v��!���U���e���9������!�;EM���f4EGJ� ���W������<���������7 "q������E�f�)r����jp�zQFG�������dw7��gQGG�6T���������y��=F&��Z"�}��]���}��]��q
=����L��?!������"4�D���pu��v��`��ab{��c�����q}}��jk-Ei�P�������]|W�]l�n��<C[�����?k�z�o/g�b�b!����+?�d]-*.�@K�Y�>	��r�,�:����i7�H�b���W���;6������,��vV~�w�h����.#���z���m�]���LO���G�!Ux���T����D����gS��a�uW%����t��#1u���b���d\U$�,	����7�]$r)[�s}�i{����^i�^�P������f������h��h5��

�;6oo��]���|�W�����?�.��]J�{��$B������GS 	�[���m.eK1FK����W��tQ���=�p������dB��D���7�2�B�x���YS�[���[�s�{Ykb6�����)K z�21W�%���-+���^K�+]thd��q>�eiR��f�.w�����t-��rK�QO�c���3\�������{);}������������>�`z�dZ�"CC
���|bG����	���8���q���tI���#x��V�B!�����i�n	�S��H&
f�*�Z
�0A\��A�

��P������P(dChhA���<m�$l�a>���?B���FG�!d�1�*��b�������hi���YWr�z�l$���*f�*�q��VI2���%J�ob�9_����$���S^'�s�x�~=X#E18�����d���H9�H����?k�(>����5&���#c���1$	����v����q��tg]%����*��2`v=�X���v���"K�D�"�8d����B!�H���
L���	,dqa���=�&ZL����?���` �~~��f���Q��O����l$����of��,3g��g���j�S@��q�����nf�
6��96�<��C��<�g��5o�^Q���SJA��`!����"b�]�b	����9A��q�FE&��(�i��i������G��P��TQG4��m��z�%���~Z���1C-(9E�	����.jW���UD	k�h��*�K*YU��������Q���4Qif�"�������M
C	�,�mX�++���O�BZ����L������m�j��sG���x�:�iiqa�l����r�,����lH+:v!�^*�!T������0z���Ige��7m����T0����c�A�[��r�f��[x���1%B�y��7�X�����?q��}f��I</$aA1c|fc�����n�����r�m���f4k�+?��#r��Ft>+p���������!�M?�GJ��� �<��X���>�3�;��?a�h@J���#�L�����f���Lq����c<�7��V��y��kw��?q��53aQ���$Y9I[@e�]�$W��g���f��FM�HM���CC9�_��8�)�qP�
:|,���1����\���L>��dsI6����r$���}���k�s)D�=�bd���A������V��r�k�r��� �A�$�U�����n�������	V
v&<������r�sl�E67�P�)���1��#�33�O��������/v}�����/F<ny��=�p��{�e���
�bA�X��p�_{�*%�l6Tk^�Dc�����i���\.�d��.pc��I$4�~�L���aS���Y��9�d��G!u�HQC����^X?�w��G��\�����M��:�uo�f����nS#��u�O��}����7L���/H���>O-Pn���Em��?�3��]!��!|�NB��K��'�Ld��+���_��L����o��h
�Bs�F����;��>���p�z���k���3��=��R:��*��N*��Ltv����t�emr��P�3�>�w���.d�#������������l�����e�b�l9�EZ��XR��o~�xw�������M���#�"��.
4�;7R�o?z�9�z��X�C�E����&3��q3�z���h��Q�0�$r6YK��Yp�t#�
aih@K$].rCC���e���P?��jI3�
�I4(��	��~S�9S
���������b����JNq�$LO�T
<�F,ChI�l$��(�����s8���;��#G���ftdO���}}X[Z���;wziT��we�V��>�6�P���9l��P���#�cj���u����!77��*&)�3��{Z9����9?_�!��]���a��b�X��)G%�ki��N�w���5�{���)0���L4^�� X�P�=������HMO��N#���
S�'���6188I?m������F�hW_Mj�-|�H�o��Y*��Z��g#F~��az�n����2F����b�J��PN����>����In�i[,�����;w������O�_�E�8�m{��7������&�W*�;
��9��cN� �I��;��B+���d��Q��0�vw���G��hetTa�o���w��k�m��m���}�v���i;|�3gL�A������>g2��y��)c�9O����5a;�2D"�G(t���z���E��z{��������w�$�7F|�t����he�NoQ�D:������'��Z*w���x��'��.�p�l�x[�#�qW-��"�������Z���H-�������c�2,��Y����+�����kx`	����_�.��f)������dx����Bx�[Z�H�m\}�����o���[������|����e��V��/�I�F��)����B6��4���(c��'�]�4����W�=�5j��}���>�E�\ �s�����z��G�f
4
��X}p�pz������^fXk��T-��.:W�
�S�q���<�|I�O��@Dmm4����<7���L����t]�9�bW�d�s!����n���������2N&��$�^�g�t� MFy����Z��n��rZ ����B
�`�Xg����o���7���Sle�S�j���x����rs�6N���e��&�#�::�}�����O~���S�I ����56��^��k�f��g�tmlow�o��np5���Q�j��0Y�L�*cdD�M��hw� �����.54X�=�d�v���N~��.�
$n#C��
U�������\�*k?�F;)�-� e��y!Y���m�AF��|fg��^_�7�������#x<*L{�3������j]��`P`�:7����q�3�uS��~-�����gp8DF��c�
cC��������w��<Lj.C:��U�V�LE1
}`�S���	L����5M��
�4O#�� �X���D�f�(�~�
6���:�.�I����d^�����0k+k:�IUCD�e4A�U��R��YSCvpmx�D��29�&�a��&e�5���������o�����.�8�9�m!�����t
�Tg��nG<�E�d ��
��WG�H�
����[C�V����s���y#�]g��.��?��$��4�wv���p1;��������NX���-]�J&+Y�J�--G�8���������UaM]��� t��SaS1[������g��#xI~��$�M�����VD
��
b�v-������5���u��l�5G���sn����������kSg�2�p
�*^f��&8<Z�G�v>sg�3��L��0�������&��4b~s����
���J��mfTx4�>��`����L�rz
uZWv�4.T
6��cF�q0�����<��Jww���zZG5*���8��W	�hh�d�j��NrC�$�G�9p H���x��eT����^��A4��dd�i�U��b!�yAqk�H���vc_�����*��yyZ���`�H�4jN'c+Gd|UN��R"�P��D�j2538�C'G8m���]��}��y��/�������1$���p�D��c1��$�)
�����	��{�_v��{����� �up5]_x�a��A��:i��������(�*��l�������	
S�9CQ�B���`�-�����x�#�����������aoj�~����8x��S�:���Y�����!K��%e�oD��H�w����4s=��u���r�5���}��M�i��mE�q��J_`���W�wn!S����Mrs��,�3������f|���*���]���sn��a��iR)�����(����a��P�25U1\;ogz�<�`q��rW����=�j�b�$��jU�x-_�N����K/�%�~��H����������|fX-�3�6���m��U����K�=��U�S���SH����F"�.���b�����=9�EM&J�0M�>��7�������g�P�+��`����|�st��u��{��Nr���O���xK��z���Y���n�������+`�� x%&����U2�����nwQ�)������f6��c��~r�
���!5�px*�TrK�[�;�S� ��56�����!_`�p������T�}7/LPup(@_o�fG�O���Oz��6����k�?�z$F�����x��D�_P(�h�F"X�������yV\��IHzr����([��!	����'�c�N/��;�,�|9��K�ngx>��0?�����x_���!\y���}����������f4��Y/�g��X��p�SG������?�5V-p�
z~����m%�����^��������a�����w���/�����^v&OaN8�a����O�6�??o/����u�>D%N�7�7���\E'/e�1�K�������/U�r�B�����i�XyW���$�9�y-��R���34�c��K������B�#�^���R��kWRx�-{��2�u�r����R��o2����=z�����7����a;�zh��^D�����A��,�M���wv���*�\ ��h��k�x<����=qXH���bm�4IF"��c��;w�v]]	�q��Jcc*����i<F�3E�+Nyk�\_=�,��E����L��a;�/l���jN�m�xW��f+�R?������N�h
��~,55�:F�j��L��b��G�au�G;���{�L��n'����r�q��b��������\k���h���+�a�S�.W�osS�������sM3	�55���� }���Z"�	=,�$Y�6���'��G����e�X����mx�~+�pn����J��������U��XY�����,>�f��+|�g��T���@��E���L��1���"7^G����
��[��\��X�Km-�lC���^�s��H���Mh�Y����\|�s���vo��������U
V������\���l�4����q��w�J����:t���h�8��F�������/N�p�s��s�g�,�*��#?�����3�SZ�~v��5�$���VW����I4���&`ih@�z���j|1�L��$���rLa!��C���t�X4�����aA����%��fB�e7���~���L��@P�]�($l�4q�UF-X$IU���1]�1� *���I2fk�^�GR�y��<�&qA����C,+��ulmm�ZZ������1���-w����g���
9h�Y�Ui;�N���f��S@l��"�6���J�b'����FB�a���^��������r+i���#VrX�V�6#��,���1 )�n��c���9xW�)~��jJ7�h�����P_ceG�1��sc�me.����Q�������	:���x
7�7��BT�xB#�#���Fs|��V��S�5��6������>l��N�~���	�wr��L��I�Ulz�����3�g��u@��MNh���;� y�/����!r��cT�,��a��)��s|�=���_mb�N/�����I��"s�sO?MUx/�������M�_�&m!�����.���H���X�O��)�������'"��"�v���p:�D�^�������/��{��x�'!���`O�X���q���Q��,Y[�w��3���qn����s��Q�a�J��m�q0�� �]��a� C{~����	��=>K�{Ss�S�0t�b�PU���x���_Iv�����{:�W�����yy��D��G�<�p7�l�.���3�_�zG;����x��?��x�c�Z�����:� ,�r��X����H>�9�M
�/�D}����j|��i2L���Z5��!�Kf��&c3>�M|jQJHQ�*�Sm���`��JSZ
���F+���q
�G*~_
*�1r��.H�9�bzZGQ��u�}����26����������H��X�~/�109��l���@}87o.+�u[(@������������n$A`�^����_�u��	a�f�?��*��
�W/�����p &����b��F"l�
��$�k[�?@�~������k+�k��;�
��8�������;�n9��p������Q/�_�gz2E=�K��p�r'��
���`�~�e�$�����b��F�z�����n�N/��M�NPyd�������B��::\��D�l�(s����`.�B0�=��x_=?���!��� �9�_��x�������k��P%kZu���.5��\[��w����<G��@t:��)� 2n'���2���N^R��R���~Wxwtk��<�i�Sm#H����o.�^�����_��$gGv������\�'>�sa,���v���X����p��O�������\��K�����q���d�
�,�2��w�3���r�~]P�����u]��v�L�hTA���,�69�z��d�/g��)T(������/G{��������b����JA��{���e�������t�u�]1{����J��D~���)/�cA�]��x�!x���*�Es��[�,����o��F{��k6�c����5�
��qc��$�����K$R���d�8wv����K�����e����Z�w���w�����&��(�*�sS��Y�q�J���gI��	��.Zr4�E<���!��n3�
�e��T;�Q�HZ��t��T� �J�
�[�Z��k���krG����w37���j�{o
;wz��}a��.�I���y���r`���{gXS6�5]����	�N	A���ZE�}�q2R���k���-b��1_�����y�c�~�2���W���b�l��G�[,.~�/���t����0�����\�Ku}�
����y3�=S\=1��r5��^�4,�s��}�V��H�<��}1z{s��fiow�������1���h�8�����*D������@�h(y��b���dR:����U���}TT������������������DP+��$�H�rM=��L���/�i��\�D��BH'�lyEt���pd�H��T� ���n%��f�`���;5���CUu��E��ss�Y�R2k�	6rUV�uj
�fC���H-M��Sn�$ ���M!��a������sJ]/fo��D�Ho����\�
���G���p����N!E{,f������g��#��k�����R���z�����D'�4�F�N���#a%� � J����a[�OM�Y?jx#�Er�q�1��4D{�;���1��2��%7��Y��:��waW���jp}���O��H��{���^��7��8N,�q[��x���l�Tn��kv����[�-w���Ulrc���@+����,o��g�AL��S��'���(Cks��:|Wj
�������1�9(�7�+k$�9t��Z��6��TM�?����ils�������
O�������F"(�����i���~�75>�O�!RI��O����q�t�����sZ����;�{;����W���:}�V�s\K�i���m ���s��+a���$��������������cz�����w�w
���,�{G�X�����#-����anT���#��^��5������x��b1�x�������9��8��F�����>�������e	��G��68cn*w�1�E����}��;����G��8~<
�s<����s�@xA���1��(�je��5�����~�xg'��(���q���:o��E���aoj�}�$�5|���L�����X�0A�_'(�T��d�el.>.���w�6�z�)-����R��$��&V��]i�L8l������3:�P[��������`�b&���03n�b�AB�Z�����I4�����r �����)�j��|�O��zA���3;w��o�����)�sg9P:���<��>�Cm������B�;;�Ns������\F@��u��K������]���c��%���`j-��p���k���r���ah�q*c���8�q�=;����[p�DHF�����O�\j�+7�� ]��X}���`Qml����!-dq����[jA-��B1��
���]��-���+(��L<�(	��8��WU�D�����4� >+28�c���z�5{����O�[������#%DC%�|�f�f���r�f��]��k����|�k���>���3�"?����]�� L�>>������D�
`��PU��a+�����K	�9����o9 }�1��R��8>���w�km�-e�-
�K�r��Z�������;���2�Z�����w�(��'��������(i�+�_g��-{����z~����e'��,W;�[�Np��gQN�`�Z��������[�����.��1��9�m��
_V
��
����@���v�Ur}}H�Eq���v�'�\���8�}@��~=��w����r.�����-B�D���I,3�h��e�j�F��$9:�C��h�3>���fg�;}��f��/���B6+�<Q��Al��b1� ���*�k�=�����S����
&&T���
WB�#��oX}�O"������4Q���Mw�?�w�h�L��~�:r����x��EcQX#O|���8�b��HY� rg���eX~�.��r�����Cnh�@��}���>j/I��yY������^N�.]�M��|g����l�q���Wd}2V����|o��SL��|�^�
�[rD��8��j��Qi�[aG������H����1��q��~������9��Y�GA��	����XP����l��Gp�(�����D	0B��gI?�����\"s�&>�#�v�0s'p����� {��:�("��wQ
����8)mb�v�������2��}�Wh(y���uDQ$s�4��8�@0	�0�(��bO>�������0T��(��-PV��o�������-n�����8������x��F�TA�)�����x�$�zW;��/"z<��#�D����i����SS4nj�~e�?�%c�����Z<��p`A��R�+PU|�QCw����g;���e�D���]	��ZH�	�����rZ����������'����#�T��@�����x�	����ZdY�=y��������^���p�����1���
?�'$>�i�!����'gQ��-|�q[���ww���*:;���'q8>�����x5;F�'��!_���\��/n
�Y��~����J�Tif��a��!1�K�{�H���^`+��4-�3s�Bz� ��,e�6����G	 H�	�FH�G'j������rg=LO��0�1�9]������C�S��O1V��[G*e�h��zo�[�N�Z�q�f���z{�$?<������>�$���HA4,�4+���Fl.��14
#�C{�'�����[\�?~)S��_���?�8FE���
�b���[���[I$�Em	�������s%V�KA��-����������������w�� {#����=�.�~���t�}X
��Rg:�p�DFG�n�m�<�>]$U�����:r�H���D���P
`9@�rl^������Lh[K��	�t-�`������;;��N�T�B��Y���wfM�����$�"p�X�t����J@�R�K����=?�d�	����S����������6z�)��Q{�E�+����>6O��������{������C<�]TC����;;��8J��"u#� Z��bX
�mQ�3==L����v#L�!�����w���i�d�����JbwWQ�{n��@���c��^��86��
���F^b��\+\�gT��a�>X����fJyV`]�����Z�	��F�<�����B���1H��1`�|3��R?���$)�P�v�6]M�}\p_.�<_j��cb/>�r�+}w_	`���oS��J������o��bbB%���dR_�����Rh `}����R-�����g��t�_7;i9[\;��kG#u�����c�c��*��_-��:�����7�e`~}*�9Z,F�x��D����u��PV���O�q�������B��=.7�hp0W]�^�w]�c�3�8������.��*N.�����}G��:����t^���p��CY�����������:o+��m�5}�M�Ec����KAM�W��k�<�k�d7o`��Y�H����	��]z�	��- M����{~�u���ee�E��u�����3	@��k���sN��������!�W�nX��FC����3�c�;M��>0 ����!���w�N����73� ��>=�P������R�����1��z�6nfg�<��`����j��<
�0#�Asz�4A-�D�@���9l�����X7�$�����J�����GVc���<�@;�c 
�ev�7q��23��P
��H ��(��u��<�3��a`w�������&^�c��s�z�\����*I��Ee�~?�����^��`��X^������i��b{��8x����d���l�8�uDCCp8Ple(*�f���k��b�?�G.Z�g�2�+8�z�/�or�a�v��7����	�7z(����~`>./���G�����:v�f#��+���~�>��b�K�b���#��E���XL�����x��7�����rap���H#������0������QeV-���k�Qj4�O8~�m�sl��	Z.G�[����8������
�[(T�8���D��;�ie��YN�i��L�5���3l��G���>����PDB�%j��4�����=�s���O�A���e$���\N�{����4�
A*�e���>��X@��d��=E[����5��&��F"�����I�������v=��;NO���Y��(��6&&TN�N���#���iv���W����sZ��9HH��}������v�\�X�Z������By���#��cRC�
TU03��9Cg*+"����*h��o�)�{��Z�,��/��T<VJ���.�Q��u�QZzF9����sA�b���"��k2��o��o_�DB��RftT���*J�.�i�z
����E(z�^���w�c3_��
����;_��J�����QAAOO�o�s��7��X������������C���<�==�;;����+��3�or9X����Z<f�7]���7*
�r������H�%Hn7����8`�	�N��+d/��t�)@��x��9��Ls��7^8��9S��B�\%2--���(���
k8���n�!���<��{6��PAG������b��G����|�k�������]6!�xq"DYb�������c1�X9�4��������1�����h9B���s1�i�l��R�T���\4�#^PG�
QQ!��[Qte�qn�?���Q���L>��M[�a�H��nq��6�w,�O����3g�)T�����U%`���<_�s�����\�|9������z�0FK��,�=x��qD�j�%�B�������T���-{��o+��7��R��!��S�q��h��]�+�;;I?��v���#��yQ�b��w���~�B&Hz�@h��|;��a�Py1pq�,�����-���|���8�_XsD	����o������Oq
9/�\�JI1��<--���n��a���B�����������L�T_?��Yz/��f��	�����5��/V�|Q������=|�9O3�����@���Q��Z�	gz�jf�b��#�=��p�5����T���ZV�nz�w�]U�|�6��r��Y�N��a�Y���'����0���E����6
&�V�#H������u����H��`��d��/�N��iB��k��eY�%��v��.�u������k�.�:�o�%Y��M�5�p�t��vI��xi�g'�������,������,Y�I�����s}�9��=��{�}�zy���h��SN����b���?�V�r�#T��0>��n23bXAw�u�[�v���=����aB0�D���c�U�A����8+�9Y�}s��4����}�l=1@���b����5�_s
c���zm���k��9)��!�#�b��c���I��7�p��3�E���:�|�[tyT��(]�+�m��������~E�~r����}��}�%��zM�)l�������������p�Tgs����a�S�Ao�0oY���M��n^���7����_�4�A�������uX�*�La�z<(/�@hp�����%29����a�?N��H����h[��r**(ll$��EG�8tO������Zi:��h';����[��uD��6��q�7zT]�Q�����1��y�>��<�)<9�@�gBo����N�	����N��i��F:���~������������\=v��0�����F�J/��T;a�rkj���R�	 ��G����/g�� /���J#��)w���N���5�0r�������tw�q����������:�]�K�{U���)0tQ��C���|Cl.�s%�Q�z5��hh��~�(��~�,=j5�jv#k���
�9���W���.����a���Dz����G���yv�/`��Y_�yo�
����������[�u������Q����T�'��#>�~�c�]���V���|�k4||Nguly����3��xx����@l���e�����}}�lz�v����C�������
����z�1�~�|��<�5A�u�2UY������sF����j���B`��S��?T2:qJt8^��]S�K~�>��/:	�t�l�N���Ld!��D�l�n7}�����E+������S&oMG��uu5��`\L=?S�(�23�'�g���3l��^N��S�X�%.uL6748�X�>(6�_Lc�_��s��6;x�pac�P������H�������c-��%���C�~�e*���L/Y>�OK������L��Y�k}��a%�W��XC^��i_4�C|�h��^����(�_s
yW_=%�]�����S�N2��#���t���
*�k�Jg�q������#r_J)4�2q>��!F�����Y���z&����}f���	/���
��'K�{~����3������ �������Bcy�#�&?�**rb�=��F�o�N��Z|.�~8����a�p6������#Z�
vw����e����r�����O�R/��\����N?V����w�v_���������r����n��XG�fM�4y9�6�'���]L]��+6[G�����G)�b���=��E��C��^
z��A���tw�1!'GO(��Y�v��U�S�����+0�V���D�t�Q)b�C%�1\�����ou��	jFV0L!�b���Q
&�%E(g��X\z�����8�)8J�P�i�rkjP�������0�=C�*#��o�7��2�c��V�������EQ�xT�h�����������	�(?��M���r�SV�K��u�"��\��c�����B��G�do��#*�����-r�c�o�����������C���Ua�-�<_��%�
5S�g�*n�^f��^e]��C�xPGF"
�f�7�a��bv8b�u�����)��rm�^���H���-o��A�)CU��]����~����#
�������[,�t���'NGc&8�^�	
��
�������`x����9�siR��,n�������F�\`�tF�������Oq���>k~���>�yU5F�4C�:.�K0Xm�{�jXKoo����x��ZZ<��DG�X�<�w�w���3��_�9�����M���s9@���N�7������w���]�����!��U�uMC�O���'���������F_�n?D��n����6m���x�N�]Td��� ���X�W,��������S�i�l|GlBg'$���2�������x�	���{������x{;���L�5���g`�:N�����B�����>��=6OG�,�� ����<��?���S^�3����K����,F�c�� ���P4����-��{����+���*V��{�U���s&e�����
(����5p'_�Mf,N'��zTE!w��	=g�������xs�IL���H���.��I����2zXW����	��$^�R9n����g��<���������i8|.�].Vz����k�h7����nH���d�����_��V�������{9�DA�b�4����;W�T^gz������3~�x$�w|�')������E�����i}��ZM����Ez��L�t =Y���L���
*�&��4[���q�4��*���'�U~.g5�V,
�0�E&��H���<m�O���l��d�c4
�uR�:���I�a35J(�:C2���o�O,G3\���FfN�%�z����j30b�o��w���L�{�s����70�7�~��47O�0]N:������m����?��N�RA��wY����9f����:�����%q#�'���X��B*�`��+������3l_���;Y��[V���WNY)��dCg>����3���-����j�Aim��}��������	�4��{%��>CN��]�������k���*:)u���*�(gx}M=W�~��s$TE�{�0����+�����)�����������X���R��?C'Utux���^GWx-�9��?��i���������X@����o
5��i����B:J�NT����}E5M{Nqm���[�	
b����&��
F�]�|����s9e|4�$y�q��W0Pu+W��mBy�����a�B��e���[b=�������
?���0����j(F����`m�������������_�uL�_���^_���UQ�FG!�5�p�_]8����)e"=��}A��c�h����@$
Jt#
v�Xq�-J������s�e������]@�����o��
��guHa�����B�Np��1�2�n708bx8������H�[o�������aF
7Pm��v�)u?���p*�b��
��n����������vu=U����+�dB���{<?�w�mG!�W�B�=��0.��01�c4&��4��f ?_����U��l[��������x��#Q�7G��~t&�U�?~��g����|o�������������r���5-����!`0�F����5-�`��>LGG�r7��	�r���~�&\�Q�J�{��18�v�J�C�o��zp:���R[��L�&O
��c+o�
���w�`0�gm ��N>��Ee����
?�f>�����������r3�)��������M�(6�u&%{\��6S/�x�����k>�1T��?E�=N��>�p/�b#��+����*nx[�f��z�gz���_U��P�/��T��(����'�(�������P--�Xo������-���d�?�}��F������
�d{j��H�wqH^I1�b�g1�����X��&����4�3'��x)5Cd����	s&�����-���T��������'����&<�&�������n`G� ^���&��O�� ��&�_Q>���}��wvb�Z#����T�y2���68�C�1F������u�������Jnn$�^Wg���K?/��W��6J��qn�8�;947��O�������]����������'������xo�����[�.��N2����/�qESro$8z�2T��i��_>F��Hoa��r�h����wb9��6CMM��������u�{L)U�s��3����l���;r����������9^�`�yV_/W��0*��-V
�x�H�k�5ln�[���$������n����a�z����:l��������b��=_l����+�p�(��(z�=aV�w�[ld��7����������OY��Pq�V>�85@hv8P%�v�b!���v1���M66�z$����pn!���e���S:M��n����U�����
w�z�	��
�����g�8����`o/��"����HUEO|7�]n��2l��Fy���0��(�vM�������s�����}A6�4��>�XeEeq$U\�O���Y]����2��`���0�y�Q�j�z����b)|GGUt:���
]
[��v���"���\���E������
�>�����!'��������sp���T���WY�������&�?��m�t:]�A"�7`�P���in���XY��#^W����V������*v����w�y�~�b��_�sL�����A����3g@��������O�D�1�XA�g>3�3�������VW��3��^��fc�]wM8�V�l��#�Q�����l�v�y:f�}���I�tyX|�x��7<�.��zp���l�[l�[R��h�������)0Fruec  >����p���jq:)ll��v���Lt��+fr}1��,D���p�Tp.~_�TW�_��v��>�1�<c��,�p��������?i��=WN)on�EQ�Z�x�S��E-D�Z����B��gs#�L�&HY���"A��#y%�d�h7_��\{{���:��?>Q��T�#��[���3�1�y>�W�xt����o��>Q#�t�4������`�a�ZQ�^����5���;�nS�bkM��5�Y7�����-��n��?��NC��PYib���Xo�[�8��S��W�{�/�����
4
�G��w�X���W�i��\Q�Vb���]S���t�|�k55q���92��r�Y�
�/�k��0��o��j�,��r
�9u��)�:V�g)�������'^��D�;r��C��b���������y:��N���_���~4�BAV��m��)A����7J��Y3vf��o�����TV�������mB�z��	���
1�_O��)��8����v�����n�RF�
u�	�,�K)/5�-"l6�z<`2�WSC�7�9a���������������r���&M(=����XHmm>��xu#��V,�.��y�u�����e���H�{U����A_lT�0WW��K�����\bg��3#�Or�t���R��e��-�>R��	�W���5W���>��Oa���p��5�����_.���LW��M�,�����:]d$Ht.5{C~����a������?�i���R����R�G(��o`�����SB>�g���.P��aw:c2s�og�����k*aF<�r�O�tZ�������������;��s����(u�`�m�56
55�8I��1��Os3������%�(p����(>�������.T����m�,�6aoh��>�pd�b^]�y�=������N��@����,E�������)h�v�Z�\�=>��(�'2$[����whtWt��yL���N��66��	~��BL�7��B��3�Kf_g;�3mK���8��=��}9��L�4)�C��0c�����fsJ/s��-�{����!����d)�>�a2	�.��VL���v�u�/�h�T��b_��x'S�Hv$�|��d���5��A#�e��H^��jTEa��]i_c�����~{�uM7*��G�38�e$�����
�sgdb��23p�(���	�+81�����h��w���m�H�D�2����oa��6������	��o��c��iz�Xvy0���#/��pH����3��������`���`_��H�nUQx�����FB���s
��o�:��X��q�*�z��=p)u�{��bj�����
�U=�|UQ�g����A�������y�XCNs3���
����xc8������(��Bmm��9��)/���t��'z(�XFu��&�9G9ee���7(�%U���ET0�����sE��N�����k8�Z�����X�ka���_�G']3�T����(/��3]g�k9��c��vP��?�m��������l�\]M�=�P������ZjP��>��<����������Na+��P.�N��S�C}���C�(��P��kx��Z|����3tu�],{�Aj��Eg6GR����Q[���i����'l������EF>��,(�=�l')�l�����v���g��
-��k��r��i!~��x~�;�7�FG{�54 �� ���C'U��U����bcS������)��w�{R��������RZ�[V�������W�iD	�4
��'���	�������1m���������*��fc���>�_����_�K���������;P-K.�>�g��6���m=���������#>�4����3S/��x�J���7�L���7R�\�������M�S&M����4k:�	���\&d����rmhHd��D�!�������cy�[�F��4/�h�T��b_��xgk#U35����T=��rQ�v����X���:�����5w���rir��b�������Bs���;=�1���9���t�<���T���O��F��@����'���\>��
���)��������qU��rF���Z��Q^��cN���V���h)�������	S<N':�|��a������j~�J>_�3'��s���:�a�{�Ct�	�P�:����;���c�L�	�#�����C[�(����z'���K�y���1����N���������/\ �2N�������8F��
��������5�hhXAC�3vL�5m�3����v
��Yw�"�~�8�>GOO\��yjg����������Yik#�������<����O|y�BsI\�=���|����.'}n.�mm	{b�\>y��d�������9�n���������N3���5&:�^�K_����gil,�������	��������[�"48Y~>��c_y�m�?�h�gSU�3]��*:M%`��o$�C�+9���O�g�������m'(��;X��wl��Bz�^O����6:fNwS<��n�`�����$R�[]|j����\6�����?E��#������p�O��{�azz�z������������&��_b>�����jUl�B�<]]��gDNE���h|�Q�����5���=�/���(R�v5N�8u1;�G]�������1�����Km8�B�&-�c�Ht���a�����*�������B�`�s\��8��i�`v�\������&��%�����9/s3����d�rmh��b��l�&I93�.��&��b���b^��xgK�n��{��\�y��\��9v"p:-46�o_6����!3���������^�S�i��6��a��M��}����5��d�rMWl����LW/s��������*NkU�a��FG���U�$���&����D��
�A�<���O���/��9�c���|��	�������>��T�N��:��`9U�j�Q8zt�_��W��
r���Rw?f�����|�����e�Y���k��	�+��*��-�0�!��*y���	���	���8��\@G0����Q^xa�~��|��U44�q�����^���}�T�In�?���x������0q>�h��L�����������i�QU��������G*�|?z-���	��in��:�FG�;���$2b#���\>>���8y2���;P�V�Vn���!��q����0����q8�(J��a�+��
���k8|���z������~�k-��q�z0�ZE0B�G��F����<�Hk+yW]��}���.�a�7����p�s3��j�T��i�������ZVzV�1['9���kn���g�'�`�F3��E��o�w���V�����),W^�/�y��Q�F���o�c��(���p ���.�/.�+_9@~���/ic�c�Oo1��ShC+6���s���Z�RV��{�Q*,�
a�E:��{�a<���.,�����d�yF��~9�;`'U�./���L���8���(��l���q�Zg Os3�w�$
��	�=���Xr��8b�z�,�c3Yt�id��og�fK83��n��/��z
�{
d�!����k�`��B��9�]����!�������S�)��T+���F���-��[�7�W'��r���l4u�/~q)������6?�\^�}3�������u��i�5]���af�F��A:;�X,PTd��(f��!^x���`����,�OC��p�;�c�)�N���,>�������D=_�w��}��v�g��1�]lw8���+���rK�I������q7kZ�����W�?�������h@����s����������&w�&�
28�9��Q���m����h�0p�*l��������`������&{�*V������yTv��������N���{�t)S��\>v���-w���E��|����).6���k�-���A�Co6�1�]KNy9�S�D��C���������Y���+m�WTs��7!��}r:-���������L����|�7}<��{h�����u\�� @>�z���*N�3���J��%��u��LJ
�{��y�+��x��8�����~7���#d���Qik��+�n��\O��OQ]�?����6
h�Ze���|tw��Fco2���.@��!��kY}��~(�Ph�����B��������u/?���Op��8:�C+����]�cp��7�:�r�w5��ctXo�u�������&[d�������?.=��;���\���gA���C��������_*��:����bg����������Bs��XrwXz�d�r86��x~�G�]��	�����B����a��5���\:�f.��|���=g�@�A�h~L���x���2�����R!��L��,��+��4#	�{��{�jcd$�[���-����7��������>�F=_���	9�'��q&������[rN�C��zv�,����C�p��G(
w3h�`���d���9���!��Vc�
Mh�hn�\����n7�gO)��4\��cl��Goo��1���p�A!���@I��k��|���1�'��wt`<M9��u�����SF�.�����s�G����@W���mWP�kc` ������g����Y(d���:�L
ER�=:���������f3`�X[���*�.�V#��	u�d�k�B{�V���,u���#�t�4��oFR�66�=p�����\��\hiAxZZb��O��}�4�Q���s���y�]
�����`���0��#�	��T>8�~�������0>��
�����~��������
���������z�����6�H�Of�t�yC����g���U����a�����4��"��E��uu5�'m{mm>��f?g���i:�����
[K�#'�e��a��f����I�����u���Y�����n|�}�����[���V���b�c4���*��;�������/y���2p���\�p6���M;(�8��WQYy��IO�����N�U5G3�H,N'�;8�w/�������w:����G'4��=oB�Yj����bt:Z �N��T\<��.CK2�.�����e��[��d�9�|�s}�����|<���*�_�f�������l)�����P!D�,�yW�|�sM��mh���oW%�a=���9���t�3�������[
�zU�)��dUk+���7V��W�b2�(���J�6��Y�s%/PU=��n�5D�\>��������j��:��U�����������)X����Yc�c+��7�?�S?CC�X
�+�l��G]�mB��*t�{������p
�9q]�ug�����Hr����&+nd��S��}!e#��U��������Zw'�?���:~qz}J�|����9]9]�*L�H>��*s��(�����������C��*��O�.���/��B�z=�rKA�K�8�T>�h��55 o�VtFc��m+y��K��gtU�j�8+q0�qh���P[��_�	U44lx��C�
��Az(�����&�G	xX�����N�a�����������tR���������s����2��]:`Vk$%�N��v**r���3�W
��f���� ���Z69�6�>�n�P^���>d��7����B��s-�*��o���mw1��j��C�^m�j50>�#/t:g�UX�g��Ym-�8��g����jj"9���
�����[�k7��s�z�''4���7���K�~����b��'	�;���{{ceg�����y���pac#��,SQ�����IYiY��������~��d�9����z��tpy��\��R�����jt����-�*!��[j��,��x���9��`O8����>�����^7�Dz��Ei�o���_���������������TW��nO���h9U��cp���l������(���1mj
���q"�Zt�sO1;wS[������HI�i��M��}b��G�N|%����������	���2���������s��:���/P}q���t�{.?�O}�_�h�6|��y��1a�O�7=��ln����+������b������_�OG���� Fc$��]w���=*Z�}.c��y�x_~����X=������{��`�3���_��d�Y\.�K(*�tu�W�������n[I'v���nJ{~�m��S�pL�56���h|��=�������S������'H0�j5P[����ctv��j��s�A�|WW�	���`��\]],
���`4���=�������k+�g��A �B�b�s�����������+@oo��yf���f�z�E��h{��O{�77lC������K=�	a����:��h��?L#�>Ot99h>�`t�X��-.9]���}�vd�����d]\�<W[�w�� D�2��t�xTNt���������g��_�Vn`��X[
�bTF�!��M�/�@@��OK��<��-U*���X��(-11���0��\t>�}���av8&�G�6D8f��H�vEQ��k
N�Osd�c���S�qjjr���3:z)��t
.�������Dv�,���Nx�����N.}���JV^�u�LY��e:�J�tt�*%g���xc]u�A�d����_�l�	��n���q:-	��3^��+� t�����������O8�<R����N��������&����X������p��U��������r�T��v���78�V[n�K�m8rd���������mn�P\l���06R$��'��s�|�_���!�����hi�L��L�������::��Xa���2aTK�x5��Gl���c���	�o�-k�m������.�������W�6��L���H����==�99������_�5�$��n���[Jq� ;�%p����,�=��A���.��be�`<����/=�~�Z���R�51��!�Bd���8.��S
t������	����������&���s��x�����M����w�f�w��&n�_��tr/��\.���"��?F?j�����nW�`��i��w�������)��#�w����n��yXe���	tR�3`�e�X�k��
@�SN�'��t��v�����Q���rluuS>�jg����������z��������
�_p�C�����W��KC��/}i-w�y���8�
�t�e���G��z=3���P5�}����V������0�")i&���;�N_���	���e?���t:q>r.����p8�x<*G��j8�������)�{���(�����Kf"����.K>���<!�Y&{[�N��K��<�LtB���6�kk��%b�V���cM!��r���e�v���.}~>`,*"�����ENY�������q������|�`�.�`{T���r�iv�C�TQ�����2qk����n?���������A����uu6������Ln�2^���@_QM����m'b�T�%89
q�|�.�(������eK.�Z��5��(.6N9/

v���
>��3`���W+x������#���^���8q�n�y�}�w:-��*��G����������M��r����EQ����[>e}Ss�[���e2.��k`h(Lww`�F�Df����'��K�5A��x�*Vk��"���/�^B,G�< |.CMMK��������!�B���Fog[�h`+<:������`���VW�s�R
�C�����4t���dBo�L9���_4p�����>��5�2l_��=W��K;��a�W�JF;U
��"3/O��s�`�\F2�=���Z(Dh`��5��H�<���H�S��������kp2�
q�E	�)/�a�J�6Y��20"���`����,;wSQ�3aBa�������b9�'�n^���Cf2�X����`�q��7����U��}�UOgg��Ve�4)�r�������c���=�#G����<��O����2��k��y�j5�������������z-�\%��X
/��:�Q!�B\>2�������?>�.����%��E�Gg4�#��f�TR2�'�Jk+��nFr����[����x�4���N��1�v���+�lY����v���Nd�`s���\����/�z<��1��������E=�������pO75L&S�f��ia��5��44�`���X��5k"��&���y��N�>Z9��%�W��O����?���JJL	R�j����|����	���/��*q���t���^��x;�E�]�f{@d�K�B!��Jp|�]:��j*��F��?U���9��<39�g
t��W���"0��L	 �����#55Q��8%�<�?��G���I�q'FK�>s/����J�)����&F��V������t��������o_��\�����rM�1���\.�w�FU6�{�&}�]]�}>4MCg0���N9������$xG\�s.�a��T�4*@,�z4�I���d�/���l����;`O4��f�����s�$�MMCw3--�^��j3uu����|f�H��i^z���"�������yY��x;$�.�X0�J!�B,��/6���SA@���������T����������z���e��g�2��\D�P;����3v����@�����V|o�F#z��+�z�
��`{s�'acB4xYc��������9����]��74L�:U(J8�3�f3LD�\>���&,7�3\:�Jk+����L&|CMM�}����Y���p0�0��Gx||��N�<���kj�lv�I������z:���0SE'��w��Mc������aN�����G8w�?L9����/*��������`�F�h@~.i�2mr����/��$�yin����iK1�A:$�.�XP�J!�B,�:G��f���������Pm6/����Uc��;�>��3s������s*o��)��`o/��aT��������{�1a������k&L
z�?IE�K��^|�����['@��=��U:!=I| z�qlk��s�q��AB����A��yfJ����JJ0�����~V�~���%[f
|f[j���/;}�
�����T\��k�eECJW���-����q�����mr������r�1����(*�6��(j���RM�z9v����47{x��3��18�.��	�!����*������U��^Y�� �	!�er@g��Z����t������h`���q@��L-86���yf�z3��+��tR�����N`#X	kF��0�1=�8oP����)�d|,L�C�������E��k�@���w����fc��-�����

��=���q;rdEQ�������p\].�y�y+�������v���luuxZZb�h
�=^����K!x������R~�4:�(k��(���������������0����������p�z<(/���f��p$<�uu6��(*�|F�D:�ED����I�Kc���XB.�@�b
A�s�|���M{{�E���������������&�	!�->��������h���V%���Gpl1z3��+x�`�����m�����7?��G=��A;�j.��"zOz��#�����X����!<������X�fu�Jv;���	�N��R�s�6������pDR����+�\���^�K�$R*��|+o���+ 5��fq:)��7c��|��$��.��}���U���Y��P��t�++	�x0�XA��E����e�w�.�D���f.47SP\��?Ko#u��Gmm>O=58���L�C$�.�q���}������(*V��7{ze��hcC4�����0��h����B����`�s��h���:��k�_�����
�.�Vl���?c���c�����u���=GX�%t!L�
�T��<��?���*��������`z|@�����@�x����m6����]���~3���9�J@��57{�H}�pw=��oP����c����Y�=>�<���%���t���e�aE���O��*�����@���-x��k��?�s�������?z��R�/~q�AG����nO����L�G?����3��q�[}t�:�D�{���E�$�.�q�����:���"8fl6��@���</�+�ck�B{�V���?���eu�Ng�3y���
B!�rI����#W��k6s��Fz].t�W��V5��Bzr���+��Q**rpA�>����� v�_����3��p&�������
�\.�����y�lp>����P^1��_��
��,�����h)V��<��M���zw�dV��]������@�z���/�q�w�Ncl��Wo��]��p��mk#��{C����������O�E&��B��H�e:Ae�K������h����~(w!���pN�r�P'��^:+`�!}>s�/�qL�n��b�3u���G	!��E�s;f�v����u�_p���\{m>��2�<��h��}���w4
|>
PQ�0--�v�J}�}J�9�����������d�TTDxt`3�����w�
'|/�>����o����!��n?�}��rP���P�s���c�%����h���Te�����O�]����]%�������Mvkw6L���T3�q
"�f4-������]q��#�k��d�]/����,��C	��D,���\d���b=�������w���:��������VW���-�&e��l0�D���G	!��I&����P��Q�'�\5��nz(�$.W������b�j#�JI��Q��f���x�*z'���

TB�wt4�@WW��XV*ho��N_�n��D&O��C?������+�@����/�SQ�U�f�iXIe���w�>{����#�
/VNu����r<3w����NG�����u�g�%46��`�t�n,N������G�����������zo,��R%���'<::������5���~(w!�V�����a��,���B�TE{�_�
c�,���}D�B����=A�=�H���N
|�aB�K�[���������ml�X������HOV�3E�\�7L�
�R��a�PRu���!/N��� o����(h���F� ���B���VR�0�]�L�-������.��be�`<7c�::�����w&�����g{��������O�x�Nv��0/�F2�o�����@/TjV��t�%�.����G0:��Lk��r.�qL�4�%����Rk B�������b�dL$���-.�����v�5����_b[��P�zW��jE���gz���������bp�9���a��k�������I-7��66N�LWWH�7�\���N���vR��{�d����#].MMCx<*���eU����60s���l��Hc��Lww�K�)	�y�����f�H���V>skjb=����YEz�y?�������`t�/������0\��(._K��@!.���v��u1r�$�[kp:g����N���=���w������r���r��#��rnj���q�g���yk���E�m�~`kU�����#���c.���t���y'��7�m�d���&����t�����b�ho��*�'"�������_\;���sidJ��1��|��V����B)G������a��>@��3�����L�'������F��:u:-l�d���W�B3���a���5#�g2[�4;���m��g�'y�^��	�!.;�Fgk>qyX!�b9��:�Bs8��������(��<���r,�a0�����G*��c����V�6[������m)-��rQ�vS5��n����V�R:�����"�)/'����8L�uW�����IQ��l������j�*F��7���*{�t$��e���Vz8�cS���o��K}�����G��t\��������|�,�O�����^m$?_Occa�������6����*�H�L\�

+hi�@S���6v����/�{�l�3�Gg��#w!�e)���l�'.�B��H�+���pw��^s�A�L������|����D����{QZ[���`��	G��C������1��H�����0�+[%�'Bh���4��a'��SL����(���`���VW��y�<�l4�
���4TU������hHe��>��$��Ae�������=B����D��k;��q��5y��r�H�K;��4aU��p)��Y�O�n��U��'������4�f����.U���6��:�#��q��U8�	?7��4��RI[�*jko�=��x�6����>:{)�2Z,pB�9�k!�B��'u�K6�99w0�H���2��g����������X`f.� �%���`���@im������A�&}^��V==���!�����:�����R�N'���~�H�^=�v�F��
:)��\k���3n������q�U��Q	�4
�T�A�C���|���{���w�=B���3l_Oo��3r�$��5l�a_�����a3CMz�z�������X�9'G���z����]k�����Xu8�x<*�=�p�B��g�tw���|��uw�x�9��ih�O�Zh.�1��s:W��Gk�BK���,�QF�E�B�K��Z!�b)�:WD*��J�����H��n0+[s�G��p1�s
���r�ii�������2��+���$�}�s����UQ0�l�����������o���+�����a���
�77{��u�1�'l���z3x����)=�����R�R������
��+P^��u�3~~�^�����7�<v�:B�q8�8fZZ<(�Jyy6�!c��-������6����(���+��z�	
�Icm6=��r�=���]�4T�1�k�8����P_oGQ�%����$�.�B!�B,1�D3��'� �|�I'���9���Y��5����j3`��������`���m�W_%w�6v{�}SZ[ooGo���$���@w7��3e�������8T�����p-��{���J�n?U\C�[�����(0R]9��u��5�h����e]]��e��[>ar����9��[�~�+���(���>�3�T5���L86�����p��8]]�E��������ihI���6���t�������q��s�dc�b���B!�B�Le2�lA��������?]�z�����;��N?#�
vTCY���TT$}^���31���3'�~2����@��C�0�YCXQ(���)����1�����z<���w�ANE�]]l����_�}��2z�;�]\�6|�/`lu�C�T�P�~����A�Tkf�'Z������T�-tJ�D��hS�E[��8����4WNJ'�v&��0uu�EpG����1����H�XR��&zE�����M�r�$w!�B!�"��%��P�x�)��b����g���g�V��jo^���D���5���������z��ss1�YC�������\>v����U�Z
	�u���v�z<�;:���<HNe%9��Xm6��sp1'���9����N'.��../��@�H#�(�m|�J�l�\�X�~���> a��`�f�.�

)�3U���7J�1>�������{o��������x��QV�0�����X�t?��"�g���_,�����(���x�I�]!�B!��b���<�l�e�9���Y�p�������z;����������������
g���dq:)��7�jj�mSe�tqb�*:�|[[����Z#9��	����B�������N�"��P��J~mml������Vz8�cS�����5i��y�=��C�x{�y~UR��5��7�����������G������^�����Mx|���������f���m���EV�����<��KJL���1�u��y��d8�q��Y1�f�r:-��~�vC�S�-wpB!��\��
!�b�[�|�"5�����[�����{KZ������y�$������V��`�u[��7;��nz(��M�+=����~�����~����Foo0���f�.:���z�4���|�JJ�74�in�l��r�r�x����~�8���<J/6\47{hk���6|$���={0;x<*���j5���,�+�3��D��lWO�x��o�b���~=�[�8��I����o��M:;w��)+#��;!����:����c�<���t�����h������������q��B�N���:[�tu���:[����lq��eS���D�B!D���$��Bq�Z�|�"=�����Z�z�^u�����B��2��c�������'o�K�`��j3��������aB�������C=:������1\��z���74�v�nz��T���tb���/�n��a�zz�����')��a��Is��8h�>�
�T������w�SM�j���[Y=�:�����*�
3G������XC��a��7}��8Excp55��l���&��]Q����&������(���`���VW���J �TTL!m��,[�0��N��Eg�����nl����T�N�e�������H0���i��R%
����B���/W2|O!���-V>r�y���@gg���6��t�|tu�xT�#c6�5��Fg
�O��D]i���aJ����p�����C8��(����)�����
.47c*.���1V~�+��mlW*���;�Jhk4**����x�M��'qL+`�� ���)�=yC�9�Z��Y��v���X�z ��

v,gt�tP>�AodC����~<����w���M��n?�n?�������J1������_�*f�%�K���?����`�'����Q1�Z�������~�	�g����rk�����I�]!��R2|O!�Q���|��z��5}��"�xr��D�G;*�J0�#��� f������jn��o_6���-
�B!}]v����nb����q��EQ������T�74L��{�r�c�5��������S�tu����v~��,NQYr�o�.�tXJ)�P��	�p���*��Z�/��uTWb��uk/�T�S|�R�ql����JJ(J8����6L$��N�8x������� k�7�_�COw��9���GX��O�t5%%&:)������s�s�tu�&���G��v�R	�FG	tt����|��%��Y��w!q��N�f�;�qAim]��"I'�|H�]!��R2|O!��b�^���45�1�G;vw���QTd �(/7QQ�3�w].���r���Q��a�����2��"���N�&S�X���r�'#~�RE	SQ�[f�7%mm����8x��Q���g�h;Pi�g]��1���j�u���\�O���g��).6��X[������WG���@W�����h����.4l6v�!�2>���.`���w���`�0WW3p�(��gt��#]��{�
w�����&�'7�|�q��o=��������$�3����U���ep0D8_�B9I�=�.o2#~�S�����:g�eS�[��./pB!���B!D6�)E�L�:?&�v�����:��L3w��J�7L0���i	�>S s�zhk������j����[���iih���uu��~�N���7���r�������q]������������?�sN���~���V��{��(a�F�z#i}v�*H:h
��C�o��������V�9?T���Ho��b���H'��D�*���Q����j��!v-N.g*}et��������40`|<�c��O��D����~��8�z�V�;�8�3���O����{�`R��lpK:��E�B!�B!���L�����#��y[�('N�0���il�4s0<����~�9�������7������P���r8�I�i�o�4�3T��Z�6��8�M7%N�s��5���`m�Fq������*�
vF�z��HC8������i(�`m|����AuE?��|�H����`�����Qjk�q8�<���)�*a��&������������{��EW�T~{��f���H8th��=>_UU�x��1v���u���a��Qy�P��J�<��u'�Mf�o4e����{���{Q��W��N�|dS�|����B!�B�e&�9�g��U&u�?��rWW��������������{�v�LH7��D���+V�1u�B��9����5����R��������~����|��y����/����������Xn�)c���������j���(J��\7�X�����
T����b��|8���78���%��J��������QCu5��:<���~��lRT�u�������w����s.��u~�����+G�Fz�)(0$u|�NW_��o;��&:;����Mt/�.�U�����5�m=�EbpB!�B!���;�vN���3M��
��.guu6�|r��N���M���f
b64�c��������m��������^WgKk��<��lmn�6�������Ij�-N'}�����N��
+����b���S�t����O9�5�������N�\�������B�����A�uR����t�N���n����ESr�O�(���Qe]]
�u{'l�PSF��e%y�'�t���?���k8/�W���=:t�:�m�CQT:;�x��	�����D^��YG0N{�&���Ky���e%���m=�EbpB!�B!���=8�;v��T��OG2��N_����{~O�K��ls��8h<�� P�G��
Xz��9�s'��!�p����EU��@rep]]
?8XJ�����w��-*`�L>�Q/���_/d��EQ���B��<w��T�In�?���������z���%N_3���w)���9N7�L8������S��=�	�b�c�1���9_��A���qom���d�O�����W���9��R�/+�z���$�.�B\$��B�|M���}�9��k��L��YNRi��T�uH��l[�(��j��3g|47{&�r�d�r��
��C�h!��#�55��������o�_�����`Ey!����B7~����tt�V������y�;ltt�9�v��$�&7V��T�t�s`oh��{�1��XT�Pu:.�/���t�O�\d�'*��W���B������\�pB!�9��'�B,o�{p�����������O����Rm��T�;�`omm>O<1����h?��1w�\���i�� :��z�
���:�D�?��	�^�&
����N3<��(*���G}X���kk7�{��]g$���Sz,d��������{�nT�������\>v�����1�A�-[�x��uim_��~���y*)�����>h��xf��u�-����XN�	�!�����B!���zp����'h������r1��H6���`����x��a�n��h��U�L������t���Yg4gy��)ef��$��}-N'�T]�g����={�X��@Q��������(����)��
u��E���`l,���N��'��e!�����{g�.��Ooo�7����1_l�TD�~�~�Oz
;w�y?����GQT�V=^oj��&"������pB!�9��'�B,���4�r���p��KE:�.2%�`occa���J��������xW{���Jq��)ef��$��}�~�|B^�H�=�C�(bO��456��'|����4����)�p�z���M�>=^������d���}��
/��epPEUa��.**r&�$�����8�p�M�i��v8��l:;�Fu�yN�O�2�x)����B�B!�2����	!�b~����b���L5�����%��V���n���(3��������������<>wz|���$�m��@}k�BEE�v����tZx��~zz8��(�[��C�\�&?�D(�^&���Eim�x��� nt���:��AI�)�<�ccaTt:���������_t�i?��`J�}���\���pO5p�
���%�?�������BqX�y��B1����0��bv��%}.������O��TV���j����&�=��z&������JK���\
@�\>ZZ<tt���SS�[��=�<�H==A�f�`x��F���^T�OK{$����������uu6JKM�<@��^Gqq�0��
��QTdd` ��
uu�	�Ov�3��{���N�z��!������|=����N1�\�pB!�B!���S�C��b��+*;z0���r9�l�MM2����]]�N	���~�v��v����L:���
��������X���id
tu�=x0�9�3�2r�	h��u:-|�����������k(����l���B�t:6n�L	l���.W$�|���LI��#�����q��K$R#w!�B!�B�h��:o��ut����~=@���L��Ad������)����(*��9SR�D��LPON#�I`}.��;rUQ�����#)#��=r�������l=��������_��^Q������nh�O���vww��N?��+b��2�N�Nn�X�4355���b�I�]!�B!�B�����P���^#��GNYY�i�2='�t��m=���K�dq:)ll�o�>6[Z��g�������}}tv��Z
TW�S
�&�K;��,���.��G���VC,�=��Z[��������r�SV�3����d�fr�B�������
��>!w!�B!�B1�G,y�5�`���VW�V�9�sM��T����kU3�]2��g<��\��~l6=V��WEQ���s��������>����������h��������AZZ<tv���PU���7�()1%�-��D9�tR��OH�]!�B!�B�����r���U��A/O$X�kW)

S�o����h���j3�f��5)b��K�����G���i�r�q�������)����=�#?_���C�qG�������+p������d�n�����=�n@���]�$�.�B!�B!��r��?9�������x���	{gk��\{=���n����5h�Y��E��������$�b�M�8v��84!��w��,��������}mm~��
�.	�!�B!�B1��f�'���;�����'Hk��0����s�����3V��PHC��QRb�M�
�}{��&t�H#���a2�GS�$:/�	q���<��BN��?���w����Ux�N�B!�B!�B�br��������v����[63���U=��N{�����L����I������ cca��	:�}v�-[�p8�&���G���:;}��8s�Gs���_*%�.����B!�B!�HQcc!���(*6���:�bo���?N�����l�\]M���Yt��;~ro�h~��[s
�i:B!��Q��R�`B���e��x����iP^����J[��������B!�B!�)���N7�|�47��WE����	�����fE�}:����a�A��k�D�����
i���8MMC<���	���+y��A�{NalLt���/��Lo1F47{hk�|�@�B!�B!�B�a�y���h[�3��T���?�w�I|���z;��c����
���s����Ty�|�@rC���{V�}.��w�*
�mAF<�x?_��YL&O=5����_pB!�B!�b�������Kp|4
��Wb��[��JI|�F]�m�h��;��z=
�<����A�h�=(�������Z	tv������c���(*��z@/iu����B!�B!���l�������������������N'3���	4t������	M���	V�aD�6����v�)*2q�L���0z}v��Y�$�.�B!�B!D�t��>��s?��t����?�z{C��\.G�~��"��s�PZ[	��`*)�VW��~��Zy�YM�.������U"=��N.���>�^����VW������\]=��3��9���5��}�I�]!�B!�B���4�������wt�w���n�:U�{}}���r&��-��a>v���!�4��V�iiI)�ycc!xRTd��6����io4ZZ<�Im������������s���N#����|����}���K���B!�B!��(��9����,��c�����`��}�ET����)��O�P�vG&K��6��������FU0#]�u:0Q%�c�tZx���X�����(*V��W�������W��4
�NGWW #�si��8���g��}�#��F���Z
��[.A�4I�]!�B!�B���
�C$�Z�gO�����?~
�u:S@O�P�p������?/����f�P(�|]� �`��t�aj �f3��4���8f��FY����n��Q��
f�b.
3�$�����>�xc����A?�����$w!�B!�B!.J7h��t�S�gJkk$���C�Jz���TR�,�hJ���p�����wo������<�� cc*&Sd��L4B��a&�D����t��G&V��i���&�y�f�;�X�B!�"k,���R�^!�b������1��r�����m���������}.��.�y��p�xT���DI�IR��(�n,w!�B!��R�/��B!�XH��x�����F�y
�G��a$�R_7��2B!�B!�B1It2Q���&Y��x�����#������Hmb�T�6��L21R`����B!�B!�B�q�|���M{�����3c�����ts��OU��d�Y:1k4M��=�tG�B!�B!�B1�����U�Z
(����OP����(av�ZCCCz���O�0�����F��TW����O{|.7pB!�B!�B�8���@G��Q]m��0'������Q������������V�tK���G�N�=�c����r#w!�B!�B!���tZ���<���E	�z��l�������_N��={J%��$pB!�B!�B�I��L����k�����f3`�O�~���������B!�B!�b�8f��=�'�]�$�.�B!�B!�s$����x6j���%{,���B!�B!�B!._nwd���j����"	�!�B!�B!�X4����	?/E�RF!�B!�B!��q:-��S�$s��\>��p�g	�!�B!�B!�XTK1~4��������B!�B!�br�|Sz�'��HO4������N�B!�B!�B��D{_G��S
0�wtO_4�|0��~'��
!�B!�B!�2�}]]m����w"}���������B!�B!�B,3����	?O�;�����z�_���B!�B!�b�������=��D�H�]!�B!�B!�!��2%���w"s$��B!�B!�B�pB!�B!�B!2 �����-[��a����nTU����B!��@��B!�BdF���p���������<y�������gj�B!�B�y �x!�B!2'c������v�Z6o��'>�	}�Q>���fjB,y>��������t���������N��IyY�nC��<��f�[t�r����&l�l��{T�s�����������)ll������4�g�]���Bim%�����[]]Je"�����J�B�g.�c��6�z���1� �x!f7�gk�^�N=~)��������\.^lj�H�67l��0'���fF�����������KB2�|��47{hk��6��{�e�����/�������.��z6�a���wwwSQQ��������L-^�%��rq���c?����Ve������s�k�#P���nHzY�nC��<��f�[t����)���v���{��Y���PSS�m�����0��NnM
����������������;	
���P`����u|g��d���{�}&���s������C�
c\�OK�{�&U&RY�\��d,�z�b>�1�ks1����c�)R�bfsy�F���J{�87W�����S��/��}���'�����r��}�k�E������&�&��M3�����3<�>����A�d��l�in���g���*��g�������o,��(�K����r�!��N�4-���~�O~��~�i�?��w�����c�y��Gy��Gc?��n[�g�(
6�-��H��s��tf���Im�bK��.�:�YN���D������~�� :�	-�PP��jM��x�aFFTr�1��
��L�PlY�	{��##S�!���M&���sZ�L�z�����!�((0`����*���=E�h0���C�;W��UQ�u:���4����ssA�#`��	�b2��j�e�~���	
�i:@g2aZ�z���n?�^/c��X��Y�3�}��{�}&�����'gl-DSUt:�	��UI��d�.R=��3[�I�=���U��L�k�,����d�%}m���(yF%���c<��&�uJ�f��1�2:;;����y������T%S��������'��t���t��R)�sYN����<[��jM���0�q�AoJ���<S���L�T=����������ch2�).��iG�_`<h�����	����3>[C����1������'�'���5�r1�g��Cx<��n�(.��/SQr}>T��R�������������R1�{M2�2���D����%��Ju2e�=�$F�|�6������D~�2���_�n��������/��n�-#���G?�����3��m��M�.7[�rL{�,'��d����w)7�_G�����&���s����Sn�J���r��y����3j~,�r�����T�O�s�l��ud��5����5{�!����T��r��h��)7K���e9���y���dl��k�����n�;����mn����,�C�PF?;����=�j!�!S�Hg9�~'�f�_
�J�Iw���$�9��d�:����3j��yF���Rn��X/�z|2��{d��#[���|N�M��C���c����d��Rf��y����Xn2�R�����������SWW����-������z�7o����,)7"RnD����tH��|\��x��.R'eF�C��H���*)3�+���[o���>���w�bo�X����tH���2#�!���q���A��H���)7"RnD���,���pB!�B!�B!.W��.�B!�B!�B\�$�.�B!�B!�Bd���B!�B!�B����<�c���{/���������?�?��?��o\�MK�/~����n���.����-���%��������$�����������D��JCC��k��'�x����tH]^�J��"]R�_pO��>�)���1�~�����e�6l���w����<��3���������������l��R-3�W��;���V�Z��Y"�r�����'�x���~�g�yf16Yd�T��W\�7��M�|�IN�8��,Y�e��_�:��zS��3���tH]^�C��"UR����|���{�����W_}u����0w�}7?��9y�$###|���������J���X�m�+�2#�_n~�a��O�d!7Ud�t����kn��vjkkzsEH�����a�Xp:����B����E:�./�!uy�*���tH]>{I�=E�x�;())�����6��]������'>���c***���```������`��R-3B@z���������n�mA�Ud�t�����n�y�8 �7/C���_��W���[<��#��'?���g��Y�tI=^�C��"R���z�H�����q����twwSQQ����2V9��������x�����c&�i�6Sd�������S�������w�>��bm��23������������q�\|��_^���f�r��K/���D0�����g�f.3���?�<G����lQ�Q�L�z�H���E:�./R%�x���g	�g��i��-//�'�|r�F,3����7�����T�Tn��O�D����f*77�p7�p�n�X
f*3Q7�|37�|��o��L��"R�����H���E:�.�$�L�78s������E"�I���r#�!�F�J����Hy��r#�!�F�J��H���� ����k������c|������o_���L��H���)7"URf��D��H���)7"URfD:��d	��h��������*����w�}�x�	>���~�z�V+�G���*����)7"RnD�������w�)7"RnD����tH��^:-��>B!�B!�B!����pB!�B!�B!2@�B!�B!�B!DH�]!�B!�B!��	�!�B!�B!� w!�B!�B!�"$�.�B!�B!�Bd���"�}�+_���~�w������������3��_�2�73�g��9�{����"!�B!�'u���./��H�]!�\:��P(4�w�>�,eee���eb�Mee%������.��!�B1#��O$uy!��@�B�!F��/}�Kl������m���k|���+�`��]��=�����RSS�G>��~??��O������};W]u�O�����4���}�v���w����s���r�5���w����v ���������n���~���������?�������/r���r�UW�������^���hhh`��-����>�]w/��������q����}�v�l��c�=������\u�U\u�U������� ���8���'y���NMM
�<�H�o����������O�B!�I������"c4!�h����4M�>��Ok����5���UTTh��i���@�;<����o~S�4M������=�i�����i�����i��`�}>h�]w�����i�����+����vM�4���6o��)��p�����������������4������k��4M�����^���;4M��?��?�>���k��iG�����/LY��}��������<44�i���y���W�����g<>����Ci��i_����\�4M��|�5�\�=zT�4M����6l��p?�B!�H����./��b\���B,:������`����;w���B�N'���TUU�����?�>���C8���o�#������?Hee��u����=z����}��


����|���p���;Gqq����\.JJJx����'>�	����p���~�i�m�FMMM�e_w�u|��GQ����r�M7�������?�S�s��1�1�������x�����o��&�7of����={6��!�B�*��K]^!2E�B�!z������l���P(Dgg'_���9t������?�#�������?>���k��������
7�0a���~�z�9�p�����>�����'77w��u:��?'��O�S���/����444��K/��_�����MMM<���	�7�1���O?�4��o��7��7e?�B!�H����./��"9��b���������+�_��_b;q�W_}5�������XE<//���Q ��FQ�}�Y R�=|�pR���eo�����_y����������|�[o���n�)�������_���9r�G�������NV�X��������+������o|��u


�x������o|UUx������[�&��B!�Bd����./����B�����*n��f�N'������o��������<y����u���G>�����5�\Cyy9��_�������g�g|�3�!r���s��W���|�<���\u�U~o6���~��w�M �����|�;|�K_����b��-l����[�b���,�7��
����d2��������7��
���^�n���`����<�����x_����g?��m�(**�G?��>�,����=�B!�B�����./���i��-�F!�����|�����^�q�i�@ �N��d2��[oq���r���E������/~�#)�B!�r&uy!�X:���B\&������>Goo/���I}���s�������i���7=����g���?/t!�Bq����B,��]!�B!�B!���4U!�B!�B!��	�!�B!�B!������%�j��IEND�B`�
relative-all.pngimage/png; name=relative-all.pngDownload
�PNG


IHDR��� �L9tEXtSoftwareMatplotlib version3.8.3, https://matplotlib.org/��XS	pHYs��7���IDATx���yx�g}/��%���(r���D&�����Y�R6�P1JIq����SH-)sJK�PSZ=@Ji8�����]
?���
�O��)�N�$�mE�-Y���0�W��"�^��+~��<�<3#}�}���i(�J�g�����@�e p�I��'?����,[�lR��7�;����@�e p�2�0#���?�W�����Y�re-Z����\|��y��_�o|������444��~���$����r��W���~t��w�+I���}-


ihh8�����k_�����������W��UY�ti���������������Nz��b1�{��r���f��yiii���K���<%�x�;R,��8@��U�@5����y����(I����s�9'Ir�����{���������`���7Ue|�_}>�����!.Lc������������/LoooZ[[3<<����/7�|s6m�������E]4�g���/�/xA����$�g������k�����+���73g���	�)�p`F������������C�e��}9|�p:;;��7�9I����%���w+>�o����>�����y���o��<x0�|�+������%y�������+�<�H<��7���5����[w����
oH����l��=G�����s���|�{����e��ee+�:+���^��������,_�<��388��n�)7�tSn��������7oy�[r��7�~���9_|q���j��|�_]A?g�����/�<�7��M����|����YG?:<������$��'?�%K���WKKK.���\~��e'�+������'In��������1o��+��w��'lW���(Ir���������[[[Go�{�����������3��{��'=�IY�pa���F/&�f��$��]�*>�K.�$�~��+������9��/�������o��s�������$��������A���o���#S;P�wf�/|�Y�bE6l���|�;�������G?:�/�����$9x�`��V��=9�b�DFZ�$�������|��y����z(�~�����<%���y���������z�I��8?�p^��W���?�z�����}-�Jwwwx�����'��_��555Um����<&���w�o��oy����'=�I�������mo�%�\��~���&T���0�l��)�<�H�=����?�s���w�m���S��M����}}}iii9�6���S:����<����s���$IOOO����9���������������{3g��)�+��qv���$�������I���|��C���v7�O�����oVj8I���y��_�����J�<����}{E��&p`�ikkK��}�����;����m�g>��Jk�.�����;7I���}���g���S���]ud\��U�0����q����466f��}��_���w�}I������gs��W��b��`���y�K^�$�_�������h��� /~��s��wN���n��+��2�g����+���I�R���[��
oxC����=W^y���j����q�{\����&I>������=.���v��,X� �Q�Q�����s�����gt�mmm)
�����|�����}o��=oy�[�b�����������9s���=-��o�9����|�35�W(7�;3��7��[n�%?��?��s�f`` �\rI���w����n.���j�������o~3�y�kr�E%I,X���?�G����d���S�����*���g��7�!Oz��r�����GIKKKV�Z����m������g<cJ����T*��=�wV�@���Pw(�;����@�e p�2�@�����'?���Z��l��m��444���������;@�������V{�t�]w�iO{Z����K/�4��O�4��9r$�^{m�-[����|��_�������g>��9��s��G?:�^{mv��U��gl���c}�cKCCC>��N�#�w����@^�����~v����|�y��_�����������Oz>��O�����������������3]]]9��s�����b������G���y�����+WN�c�w�
Y�lY������O|b�9��<��������$y�����/�8���Y�bE����>I�����k�Iwww,X����nK�|��_�����d���Y�dI��_?n�~����G?:�/>n%�������+����s�UWe�����;p�@^���f���)
���[O��n���<���y�;�������/�bV�^�O}�S���9s�;��;y�3���������/y����g���?~~�w~'���73888��gFfu�����.�|�;�h��	m��'p���o�9���g�g��\p������/I���?>w�qG8�?��?��������+��w^6o�����������7�x�3���~7/z������-=�P��b~��~t?����3o���w�}��qc������?�a�d��M�����|�����}��n����/��?�$y������{��W����r�-�|Lw�yg.�����={�k�V���w�9��O��-[r�e�e��Yg��0Y����?����Gy$����	�@��T����
���7/�{�������kW~��~-�~������_��_M�P�Z�X��������y�K^���g���-Oy�SF�������������s?�sY�lY�m��$��������5O|�����_��_N�P��M�244��7�=�yO.\�/�0o}�[O��z{{��M�p�����L������~7�|�;�g�g��Y8S����:����[��������'t{��B�PA_|���/^�����w�}��?��\~��ikk������}/{��=����G?�����~��������?Z�s�=y�;������m���w�}��wo�92n�c�}�m����`��$�����=n���imm���'j������k��8�y�s&��p6����t�������~�)/�t$p����G��~�����������]��-������������+R*��$����������]�h2�.]�
6�����<x07�pC�?����={�8�����?��=%���7Ir��W����~Fo�m����"����}����/�B��_?z�.T�:�����W���|��������??_��������y�K^rF��^�*���h~������y����g>��y��G����G=�Q�'>��|�{��������'>����^����o��o��/|!�������7���	����������|���N�T��C����|%�v�JSSS^������r������y�����{�3��E����}o����i��|�k_��x��'I���R*�200����

%9���~�����'�|�+'|��\��������o��;���m��m��<��O�[���|����q�Gw�
z��^����eY�xq����|��������\{��Y�re.���|���������������������+�p���~��y����}�sy�{��E����.��-[&4����������6��{n�/_�?��?���p��C�P,X��/�8�z������������g�������/9.�����|����%�\2���<��s���{��K_����;7�����$����z(����;�4��+v`*��'_�_p�ioo����9mmm9���'u��MCi�\'���e���~0��K�T����`2�p�2�@h)e`�;����@�e0��8�s�9'����T��]���#�T{gM�L3��/[���7�9�����g��&I>��O�}�{_J�R�������}y���5��koo��;�5<�i+V�����Y����i���ek)�+��+����5�k��/�W����y���������e/���p�v	��Z��l+��������>�������+���������\���Z��b=�����.+W�T�p�R�T�!TLCCC��0ijyNd&����j������ws�
7�+_��Ios�M7���n���%�@
d��������P*���9K�.�����=�	9]-���yfb�L��o(�yb��Y�ZJ����;�{����O:?��?;��Y�b��-Ls���imm�y��W�+�'�T*���NOOO:::�}���r����8�Z3��O&^�O�
�]�v���~��/�rRa;�_�TJ�-[����j�"r�y�e���)�J5��D-����:>�x-_�#����>���J{{{�������Q|�����o��U��j���s�=��%�@-��S��Z�����v�U���G?��~���x�vS��O~r���o%I�-[������e���>��+WVsxSN-@=��:�"M�Z6R����������*���Z�����b�/�����hN��R��<�b�@������:^�@�(��~����u���-t�/xAJ�R�����]�z��i����D-_u����,u���?I�|y���r�������~7_������ ��Z�}�L3��|���w�FG�������v9-]�4I2����5����[���i�����:^K�F���u��������fhh(��sN������}.W^yeY�3�T���T���+�B���mO�x ��������

�g�g�?�����}�L3U�|-��wf����$IGGG�m�V��R�u��Pw(�;����@�e p�2�@����h��m����twwgxx8?��?��~�����>�����������5����@����o�����\y��y����={�$I���w�7~�7��g?;�\rI���wT�a��W�������W,�{����e��U�V���}m����l��!K�.����������7�������������o�9���y��^��}�c���;��g=+o~��G�k������������������kWY���L��g���@����~����u��R(�������^~��~.[�n��m��������[��'>��~��2w����\p��_��_�?��?���?���;wn��P(��{�I{{�Y���L��������$I������JggY��Gy$�w�N�T�#�<�R���������������w�9n���a�vss������288x�c��`���Z�P7�;:�$�]]���������o�f������xE���������s���$��������������={�m��$�'>��<�Y�*�`:�)������B!K��Kgg�;:��"�3��Lv������-ihh�����d��������<���L���5+�������3��L^������#ioo�'>���Lw3��o(�J���k�X�";v���0�"�R)�b1�B���9���=��R�N������:>�X-������@�e p��j��BSf�=^���X�N�1���8�8


inn��?���;oF\p�T*���Nss��x�L?3��O&^�����K�f�����wo��R1���Y�ti��gl&����jy�;U3{��ttt���Qg�
 ���X�'���T���:�x.�
e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���P��=����XLgg�;:�R(T{8��������^�~t{��uBw�iFK�
���L�4/_>n��C�^�I����q�LZ�T@K��%����0�	�+��P�LcZ�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@�������oN{{{f��5��7�pC.���\z�����>W�]gI�Q���W~�W��o}k������d�����~������������������:���������\p������}.�x�+�����.�(O{���������-p��PS��}��]Y�t���c�����s�w�u<L�������J�	����n�M7�4�����RM�+��������
�3�:&o�W�/]�t�J�{��7�����������;F�;��s�zh5��X�����o���^�>}�b����������������O~2CCC����r���������������$I������Z��0ye
�_������=CCCioo�u�]��<�9y�S��K/�4?�s?�|�imm-�n�^sGG����k�6T�:���4����b���������=�f��R�N��5�����21-�����Myw�	�Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;�A�����O�����Z�*�x�3����R���:&�"���C���7�9_��W�m������Z~������:&�"����pJ�Rz{{�$���Y�dI%v
�!u<0��}���;�b_���41�;Y�`A>����+�H[[[�����������3����b�/����^�nI
��*����"+����|$w�qG����\{��y���>�67�tSV�X1�����+14�$���t����$Y��y�6������mK�T�e�]�$��_��l��u�m�������c��s�=�CNBLgG�����q�p6*�R���=?��r�}����.������X�����:��
���[�$�����h�N���H��d���x��y�s����g�Q�zT>��OTb��R��]��"h��J�R���8�+Vd���T�t������[W��;Lww(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�;����@�e p�2�@���Pw(�q����P����Zc��:j������)�����X�3����p\K�5k��o��or���j�8�x���R�T����gghh(I2k���J�444T�p_�bEv��Q�}@��m�����[�:��pv��P}���I�/}�K���?�$y��s��wWtP����������?��G��}(I244�W���0	�x������������7/I�d�����V|`��������[ZZ���0�����c��
�u<T�q��/��/���|g:����/��/��k�����	R�@������NGGG�����r�-���k�����0A�x��Y�~�_�B^��W���|���>�������+:0`���P}��p�{�s������Vd0��Q�@���p����r��������_�k��������SS�@�
����388������`������>W��������P*�Jc�p��w��K/��xF�X�";v���0�"���U�@u��������O}*����/��/f����������8u<T�q��?��?���-��������l��m\/H���������~�+_�J~�W~%K�,�����Q�@��wtt�
oxC���1�y�sr������1�x����O��������/})�����o_n���j�
� u<T�q����s���8.��������\y���0A�x����/�����Kr����+����K���=�c&H�w\�����=��zk.������77n�_��j�
� u<T�q�{CCC.���&I�����v�m0q�x��Y�~a�����+����/]tQ����16`���P}��p�����>|8��S,���>��rK5�L�:����O|��$,�'>����<u<T�q�{�X������s�=�����[o�����S�@��_{����������6���u�j�:����}��yy��P��gH�w\�����66l�_��477�~�1�yLEL�:�������7�������LCCC����!w�}w�L�:�����/��/���0��~5��u<T�qWSZ�|y����1������[������=�i���k��~|�;�Q������;.p�c��>��I������<u<T�q����Vc�YP�@����<�;��h��{��j�8�x��=�_������/�}�s���???��?]�q����1��k_����/})������|'O~�����??�}�ss�9�Ts����b1���i��HK�P��Lk�x�
�R�t�o�J�|���������K_�R,X��~����+�c�������+�{����%��	�&�\��:*kl
<�d7jhh�S���<�)O�������� ����3I��|y������)p� u<TO��or��^8��`�h��H��wu���:��P9']�g��P��u��pf�;e�R(��g\K�;��3���������?��J�	8�V���`F
�?����k���>��\q��B����=Upj�^z�q����c��@�������?�o��imm������/����s�u��T*Us��I<�q��������?�g���S*���g<#_����=4�qF�R�����$�c���z����_��<���ihh��������|�3���^����������3{��\|����8�-e����_��_��X�pa���/g�����}{U���_��|��_��7��W�����`F]�~�M7��}�������|��������;�����O}*��o��/�����i4p����������p������y�{^��3R��o�<��O��qe����]��u����T*e��]0q�x����3����^�:�R��uwwWtP�����v���B!������>��-]���wt������o�7���444�w�w�������f2u<�����mo{[���Nx����=g�����>�_~y��o�&�R)=��Y�'�t�x�
��{Zf===������{���5k�� ��+�c��)��Z���pzck�qU��~��|�_���;�$���y��_�e����;;;�x����o�V��?�3_|q>�����/>����@��}���OGGs
��jjN��?>����9�yN|��<�q�����<��C�������|��v288�m����k��w�����/��^��q������b�������V���@TJ�����wg��}Y�~w������l�����^��|�;Y�`�������O|b������w�����/���{�$���^���g��
�Lr���:��M���q��,_������]�(k��U{XPuck����hjj:��'��d-^�8�_~y����$I���/���/?����@ett4'I����m?1�����������]�6K�.M��{����g?�����:���_�e^��W����Y�pan�����O����@�
-Y�n��p
�-e��������/|!�v�J�T���K���8�{��*>0��0��M�����[����=�qy�������$Ikkk�GL�:j�h�x �z��r�����K/���^���;/�|�+�{��j�8	u<�����e/{Y�����{����{wv����;w������^��j�8	u<��������������7o��������F+c�F���v���/�_��_���#��<r�H>���g���Upj�x���������k_�Z/^��K�f������r����3��L5���:j���\x�����>�$��o_J�R�;���
8=u<���}q��E9�����7������:������o|��P&�x��S��R�R��D�q������n����:�c����}�k���p�~�c�����S�@�]����?=O{�������}�{���+r�W����~f��u���D���tL�������������g'I�9���W�����[���X�";v���>�Z���U�@u���������g```t{pp0?�p�FL�:��b�/�6u�X���P�fw��k_��<�IO��^��$�?��?���}�L�:��b�/����^�nI
��*�j�q��[���<�9������$���?�U�VUz\�$���J���O�,_�����tv��!'�����%_|q^�����7�����E�*=6`��@�tt4'I����m�Lw\��|�#��_��\��I�={���k������S��T(�d��%Y�v�v20�q��G?��|��_Okkk���K.�C=T����*�Ph��5m�v���}����3g�����pEL�:�����	OxBn�����;��k^������|5�L�:����������s������U�zU.�����������	R�@�5�J�R�q"+V���;�=���R�N��5��u�7����������������?��OTn�����������~)Ox����?=MMM�0I�x����Gy$����1�������h������o~�c��:��b�/�6u�X���P����p������

�#�H�������R������}���'p�x������_�{t{��%)Z�8"����W���j�8�x��:;��$��M)g���;��h�~��'I�������g��yI����������SR����������~{O��l�����[����p��^���g�n��=;/��+:(`r��@�
-����,[��k�iK[[���w���������s����#G*:(`r��@%�^����9��Jrt�;p�����-��~���m���s�9���&GTR���u��d��E.�
c�:����k��6��{nJ�R�������0A�x&�X�Kgg::����B����q\��j������?H�TJ�P��Y���!�x&�X�����G��N(��Z�\}���5kV.���\q��5kV����j�
� u<5rq�����mp������;n���C��sg�L�:����eWW��m��h���w�;�g���m�2g����3'�g���^����%�#p�x&��.�NC�T*���[���|���xF�X�";v���0�"���U�@u�������H��o������~��/�����R�@����+_�J.���\x�����+�t��<�iO����	R�@����mo������.�,{���������c&H�w\�����/�0���I�k��6��v[�L�:����s�����PV�X����}�������j�:���}���OGGs
��j�
9n��_��_������?�b��������[�16`�����X������q���_�;��	P�����O|��$MMM����2w���
�u<@����O�,_�����tv�[����8��V�����UW]����,]�4?��?��}�{�0A�x������$����
��38�����7~#�|�;���g�����?����������R���B�%��-�����n�+��V���1v8������#y�_8�����������Q���B�%k��	��v���v\���� ��Gs���>|8�����@�Q���8��R�T����gghhh���������!G����V�X�;vTd_Pmg[����:��������N�������k)L���@�e p�2�@����>����wv���#-�B��g�X�Kgg::�S(�T{8��;e�W,f�����K���P�����_�{t{��%BwNKK����3I��|��m�G���I�����m��X�NY4wt$I����m0���6+G�����q�p*w���P��u��p��fR��B�%��-�������i)�p�����al�����tv�O��u��2��'p�"3i503�6+pjw�)2�V3�i��&p�"V3i�''p�"��N�M������Shd5�~��_c�0���>v��C�P��LZ�T���������iSw���`��j~��i��p�w�
����M�����}o�Rn���$��sZZ���;&)e���$�o��	��$I���M��S,�U{(Uw�U��4d���$
?�>=�pf�RH�����w�n�[�dF�@:�>�1����b�;����$������g�5k���x��{�;�X����hH���?n��+�������%pR(�d��%���OGG�V(tl��k%�c8C	��$GCw!���m#3��}�-h�~��qF��X�}jZ�0����6)��-���V<�%p�)R����m����_W��4�x!p�)P����I�3#p�)P����I�3�X��tT�����T��0�u�x=��������H=^L��[�L�b�/7��+��CY��)7����0��2��zn�3��l�������C����P�l�����1V�����T�B���c�?!p���V8Sal?����<�	��l��$���MY������	�N`��}kkSn��'{�$I���-k�.2)�q�p8����tw���zr�`)���r����5J�p
s�6fpp8�
g�����6��~����8������5e��y������;�������4�"��w�Z_�����4wt��P��p(�b�/�����h����GB����������_0���zL85�;g��X����G���['t�s�b_���=��n��0
-Y�n���x`��p���wv&I��/�
@��O�|y�����Ph��5m�v&�
w�JsGG����k�6�kl+�����lZ�h��D	�9+-�B��[��;�42�Z��"g��EI&��]{&C��Yk)��L��2m���-r�m;�
H{��$����lWW:;���q��*��������Y2~�7jy����5�m���g(����O?��0u*V1�v�m�������2Q���v���k��y��������1==Cy�Ke���	����S�"�{n���|��_��?��J�(�<Log��|l���b���4�Y��j��tu�g��9��G���}���[��IU$p��?����������J�(�<Lo��O>6���J{��tw���S���l.\z��0��O_,�e���l������tw��k��zu���q�<p���;��o~3�y�{Ny��n�)7�t�������zh�)L��W�@}�l������)_��#����:t�{mmMS���l.\z�-aF��]����{����,���G{�o��;����?S���_��;�|��$���P�-[�;��3��s�������\w�u��+V�����0�Z^�m�a�H���o����?v������o���)�O410�3�]�>�H��ess�=G���N���.�����)[�O}j(�J�J�p��Y<��V�X�;vT`DP}�P�N�������M�����<�o}�P/�������mK���Om�j���F�	O���~�P����|����5pEz�S�L/,:����q_f�j�����;�1��7g������XcW�o�����Z���~�=`��3�����DV��G-��l.,:Q#�UV���$y��e��E�'�{�L��}�g�����
w�����56�nkk�J�����PO��LOw�*��{�����e������-=5���}w�*����b_6m���!�������l���"�L����J���-W�N^��y$[����U���r,�;0����J�����+��n�=�U�t�t����Q	�+�/�V��U�L�t`�������}���o����'�k����p�V=3i�����|���288�Y�Oz�J���5c����I&F�����H�RZZ38X�����y���$����32`>Q��5k��8"j��g���,X�����$G�����7�����������s���3.t����9�9!���zukV��������+�f���l�����p��K����=���L2��}��C���H�GC-�u�X���M�)��=���XL��M�+�=��Ph��7����/��}���$��`)���Hh����k��g8��M��q��?���P�N�KYk���+�{����%����P���(�c/��zuk6o���=���5���������?�1��C��0��@]�Ky�6S���3I��|���Sq6B}Y���W��e��������wW�����i�����7z�}������e�;P�F�Ytu�����b_:;����<�V�6wt$I����m��L9a:?����}�������}Nv�:���e��E}���zZ�rn��o�����/�O���B�%��-�������R(d��u���LsG�i���=���Z�����yr�1n���{����w��������>�j��F&T����i��7m����CT���[����3!`n)&��}���m���gh*�U53�9���O[[S��fan�������U��U��V����	��������/]��K�$I6n�7z��8�����Pf�����
���]�(==�imm�����]/�����<����,_��.�]��;rv����*pwv���{(]]�����|����=f��`��eV��n���}��������z���XN��cc�l��S�1�K%�OGGszz���;�����8�8L��&G�0j���T:U`;U����N/w�}��y5��Ot�c��M���g����1[��N�v*�BK����l��@Z[���4��1��Xw�����
&��wz-^���}���l������l��'������|y���[?��5m��h>�5<'�89�;gm"��T�g�r�/rZ��$'�l���;;��������;�����NE����8k��e}�+��b�g��f�����o��#I�O6�Y�6�}wt4���������\�bA4$i(�J�j�DV�X�;vT{P����.��3S/��r��[��5v|��CI����$g>���z{]�d����p�,���F9�[�-j�:v|O}��,]:��B���Z���r��Y�VK��:v|�W��%��z=�q+�k}"�M�@���6$S��lM��&����'"�����zmCR�-u�=����o��'

��U���d���(7�;5E��0v�zkk����~/���('�;5E��p������0���)����cW�
-)��iS���I�@����>�k�}(��j�����=S���/��=��
w��X�������k�@���HJ��j����'��8��s\���$E�l��/I)����\~��l��o�L^�]����������OK�f���8��r\*��dd�b��}����tw��fg���\p��$�{'���������63��3�`����q��*�����C����wr��p�����8��B�%��-��h���0��I�iS��	�C`Z��&c')������=�����q<S�B��z�O�0��3�o�D.�Z���H�m��1����t���r��`3�B��4�0���S��h���������h��I��;�;�;�VK}��2�����������;�����<?==C{��4�SE��+h��VZ�LuX[K�r����-=~nF~�P������u�����}�g��9�����m��q���]����E��
+h�F-�-����2�p:c'����ysw�������>��==CY�r^���-�W���W�D~~l����'9��z�2����Q/mA8�S����
�Z�X8��;w����~��jR�l�;����o��/I�j�<�Sf�;P7��-H=���=�[!]/+���D�{db�X������z��lR�l�;�b_v�<������|����k������I�����V�?�T����
�����J%'!�����S��`�MM��Uo��~�6	���2]C�Z�O?�-{::���=��o���MV=���gr_��q��F�}��yd_�6ug��}����Y���,A����+�I�Pj�?}%Z��Je��	���;�6��5;k�.��p�Z$��"���CIr��n������{��r�-'y��	�k��Jm���Z_��Hgg����r!�M������(����!�����t��UH���J9Z���"�����R��F����IJY��9;w���;N������&�;@
����S�����w���p��o��#���;P3+���x�����.��`�����>�cC�����[ny8���(��f������~���j�t�O�T7�������������?{���] s*Z����g���(���.�G>�`�?V�n�=�W��t~�r��@]������F@Y,�%I~���d��Cg���/�9Ug�����B��K�d��yimmJ�x8[������2�����|2^%C�r�^����8��d!w�Pn��'IC6o�����I����$p�F=��D�'L��z��dV������y����g(�]67==C��K����#p�F��U�	�r�^\ s��^`udr��{(��M��J2�y��e�qK��
�g}���I9_/.�99�N�<���t��q��tx/ks���@]|��jL�x�T��*�c�L��^�z��0�m�8���v�x�]�!de��U���C���pV�������]�(I���P�+�%p�-��FVy���������fM[�FU�\q�����~�m�0v�#��N���������BK��i���
w`������KcWy�����~b:���L�L	{+�bi����~b����sr*c/���3���_<m{��m����������7N5�q�q�|}�O�0�	��Q:;��k��tv�gp��
�L��w*[,�*P?�
�c����w��;3��}�����
IR����4U-�N��ne�����J|('�;0-����x��l��tv����1�����T�X:]@>���'��S��L[}�b�;;�����B�����\�q<��x>8��������.Jgg6n�����?m���������������l	�������^�~t{��uBw�D{�����\97��7������3���oO�Rn���$����D��������MLQ��L����$I��������B�����X���M�)��:�j��hN[[Sf�jH[[Szh0I)K�6')��;V{�U1���Ph��5m�&�;15v&�
w�����$IW��mf�ZiOQ+��x�n�o���8�;7o�����9r��m����x,�R+����Z2QG9���Z
�,Y�Nw����)j���S�����v�����L6m:���:��_��nK9L���T��~-���I~rLf�k���3m�
�v(�S�����Ow��h?�z�?����g���u?���S����F�W��H��;�t��4����@)�\sMy/6Z�#3���D�Mu ^+��L"QwN�T-i�/����h���~v_V�n-K@Y�#3�����Mu ^K����IJI�6����3����R�!����sNSZ[���"�-F��?�r�';s�V����s38X�������H��Ci���_�BK��~q�-k����ikk*���Zi1�O
-���7m�N��7��9sa��}Y�~���Ty��uW_zh �7���df����*�|:[��-�e?��l1��qri�s��WG=�B�%�\�����
s��3Tsc�v	������+�a�T�����w�G%L��F9�.09~��C�����/]�����Z��X��5[����g(��+�8�;0#��*�35���M�����}o�Rn���$��N����(�������Ow�P�����;�
���Ov�B-�vk���=��i�����GGW���tis���J����������v[O�����k�\F���ke��E��������9==�����?�����ql/�Z{���Q��dX��H�u�t�H���������sg��\u����������+#���H����
{���t����}��EI��k��K�3D_�����4wt��P��pj�T���z�H�h���+��;�8����_�v2����mmMY�j^�m;���e��E5y,��T�w&r!�c>I��v�t�0����~����u�����U+]��Z�H�l��5k�*��YY�m��l�~8��p����O���M1r�F��c���~��_���wX}������$i^�<�]]�����R-]t������%�q��$��U�jv��t��)�����r�5mY����O����.�
3@sGG����k�6�tSk]�x��c�Ph�������T�c��S]Xt�����������~_���=��.L:��a��
w�Z
�,Y�Nwj���8[�	s���QO���i��h��w�]���R(�MO�P���N��z�����0C�
�vj���(���g[N���N���V����gnlk�C���k����5�5D�n�%M��?�;Sn"�s=�q���b���g`"�����-�����������g��g(�{��N���|~q��y:~�4�S��L���N���X����G���['t/���?�c�Wm���5���\x�T����p����3������4/mmM����Y�Z#p`JM�pv��x���I����������N�{�M�)�+?�t���s�eKO�o?�R)��0���$9������;Sj2����~���#I���5n���H[�3�?|���N_�n2gNC��{s�y�N;��$���T*��=�Y�bEv��Q�aP�z�#�Z2]����8�V��~f���4�R��g(I���.����.hL�[[��������
��3�8��B�%7��~����6j���)eu��8S����s6�L�Q�L�����o:�>�T�D_O&��w���T����S�@z�����s�m;���e��E^o�0��SL��42��eKOY��!p`�X]3�t^�
L�d�l���;�8�����5k��j���G>�l�v(��Nr�1[�>1}�bv�_?��d��S��g��k�����{^�4�;S���0�U{%+P{&��f�����o����[ny8�c�*t������97�K��Z5����������4����������B����'��k��i=���-w�c��V^N���m��<���3��7w�q0I)��7;;w�g��g�Wj�y����k�����g����)%i��v_��]7�����4-X��o}_Nv!�t8�z�x�����u����	�����m3�t6�=S�����D�\u���|����q8


�����}g�Wr��~�gn����+���g����=M���+=[��{ONf!�t8��g����=���=�w<�m������;��g?;�]vY.����[��������$I�����O��XL��M�+�|l3E���M��S,�U{(3�:��	6��]��e1����1�����Z{�u?Sg�����5��������-��sF��9S#�����*2�uko�n�������sL�?�5wt���-
�f���-�I~�����?:a�BK��i���I�c�O���
�Y�f�O��O��'?9G��������?�c^��Ub�6�����k���XS~�b_n�aWzz�����ol��	�����(-�(��axW�h�r�L�?���E�GZ��(G8^�U���V���h)�d����b���9{��q���Y�tJ�P�ZW�N�����M���i]���Cb*�/Y�$K�,I���3'Ox�r���Vb��r�?�'R�3��-=���p,h�=���-=uU�L7�x�*�O����j���S�Wb2���jUk���P��k)����.l��������qF�7[
���x���U�*��}��}���������&��?�'cU�Tq�@-R��R�0|�u�tVK����L�z�^k�Z��{~{��we�_��wT��h�~���\{��y�����1/��n�)7�t������+94�I�*��V�n����������Y����C �x��M�Qkak�������&��E���CI���$srQ��68s
�R�"K����v��<�1��>����~����cGF�U��������V�_u<����./���m������r����w0���y������`B���[�����.�����aC�v	LR���c��+G�(
^w5D0��kuv-��S���n�������6���k�X���3,����\�d���������B��H����=���'r�W�	OxB��U�zU���7Ub���R�>f��b1����^�n��
�F���e��A��]�R�s-.�����l������`Ac���H�l���q�'�BK^sMo�6���c���3�3��;��"������T�s
p���<����$I������RP�u<���=���Z�r6�M��x�T��+�k����}n�ZQ�e�c��d\����[�$=;�$�UL^E/�
��Z�X�L���Q#TW��m��qf&3�T,X9��&�^�52���������g�������8�{(O�~(�����VdA�������;��CY��9�W�N�>���B!K����38`���8�|u�z���Q
*`��qf�3kG��S���X�r��M*�x���?��C���Oo�P6l�3���	�G��$W��s���}me7
-������������R(���6����J���	0����X;\��h��h����������<�r|6�����������w(4���it�`��D[[S
kW����������\w�*���n*�
����3kGgg����8~������h���
���g�������}�W,f���IR�������Ph���/��
{��������cX+g���3������������t��������g���8�44����.W��}�tw�~}���Y�rn���N�>���I�}6Y��-�'|�����hf*��S��������T���DC���re�����^�8I�:W��������TJ.�`v�R��o��������^�jy���������w��	�8k�}5�����<�P��;:����$�=;�����.C������$'i��������U+-S8�SMl���;�8�����5k�*<���9wj���)e��3u5�t�h�5c��$���H��E����[�|�{&�X��6Z�p�6m���_��������^\���T|��9wj���)c��,���a*=���$�W����_i#as����o�q��uw����\���j�������a����0��7f���l�t�f���Lw��q_�8c������D����j���
�V�n��hf�����m;�o�_en��$��������l�����z��44$G����pt�VM�g��	�����^�>C������_��5k�zL�d�Np��;@���"2q���J�{�\���H����b�p�l��v��������$����?����Mi^�<�]]us���pD=MT[=�M�v���zkO�����������=�����tg�wvf��;�]]���6��	�����	�jX=��S���T"������?6<������5�]-s:�������$i����Um+3�����I���-�'��,O���[����$us��^���(�I����l�B�%7�t��c�-��?�5wtd��'C��i�5+C�g��i��?�b�/[��d��������t�[[��5����Nu��q6��D��������g�@zh 4e�����eN�Ph�5����g(�]67==CU{���Pc��}
_���b���<>}��.l�(�D�L[-_�g���?o�aWz{��`ASn���&�������P��_�����3p�}L���i]�zZ���5�{���������������	��`�V�{	��3
�&��],pt�w�`ASz{���3<-k���[�ukozz��T�^�5&�D����A����D��j��R(d���M�n�'�P����kq���������'���������m���~���5krd��������B!C==u�J�\~rf��tu������}���[[o�P��Gl�z�T���D�TD�o2��X]?v���MY�����==C����SV�T#P[��k�O��W���)5�}
'���N�4��%9�
�z:+`"c=�d�t^�^k+�Od���������f�����=��0�f5dp��={�>��x?��]�{rQ����������uk�z�N��K+�r�=��3��+���k�������C��SQ7V����z5Q=�@�h)&�Mte�������(��6��h
�������io�3����*����c_���6%9:��o�����s�3�1����pV���=r���h2b�������U�&�Fj�[��E\�����JWWz{��a�����fg��Y�+�/�`vU��T�����~1_���rh���{����`Z/hK��7N�w��N"O3��~��C��BQw&�u��p���fb�	���VYO�V�	5�],0�uN�/:9ck�m�����?�����w(����4����T�9����`���m���$����3o����v������������	����sx��$GW�Od�T�F��~���S�>{�}���H�������8�;a���l��������6e������X�|?to������\�3�yG�%C�9r�Q9���I_��L&�����{����j��;�:�J8�Y��>c������q����RM2�Z9�j�Q��NN�H-�m��|���3�R������s��p��:4<�������;�$���\F&��m��$�����w���k�9���V����#��H�?o����dxp0�&�����Vgz�g�����9W�����������N[[����B�%7��^�
N�+����w��Y�20�%M�!I���)5�7���+�o��<�P��\�9K���$7�O�VE����qW�dg�����J���nhr/���D�TGTr�u���$�DV��{#���?�`��z�������#G�3o^S��g����<���Y�vQ���Y���P���k��������ioO�����j�=��GNe������N���uW}���m�1��V�;{�D�?�E\g��i��[[�r������������'{���q'�S�zn�.�s���r��7m��;�����J��5gt'�T|~��U�s�-y�����4��MJC)
���o����<��o<���+�����������P*e��Ui�����I�����G�UP���L���k�T�1P��?�
M��0=�j�j%W^��JN2�j��T�c��#n�������f�7~���zkO��k����������~���S�����gg�S������)����GF&!�����h����z{O;�w��V��;�W,f�
7d��7M��g��k�%==�����xG��$�]wNRJ�p|�����H�����,������c?��L�M�{�{�������R��o�%�I�8t?��|~9�$E��5�`�������L)G����{s��s8��o~3���oN�8�;;3�woS���P�Wgf_pA�Nr�j���ijk��	��H�N]�.�/a�T�1P��?�
M��0=�l�j�_�m*����4S�
~*�c��5�%/97�����Kg��o\�$��w��@���/Nw�Pn��g�O���|�
�O�������=9�fc��������@���:������b1=[�$9~��T��N�w�g������0kV����~wZ�����^������(Z�v��l��'��M��q�)��c_�����u��eK�h��druxgg�������������a�{'{�F>���w���|���s����fM���}:}�b��G2��#iY�<?��w�Q���L?�to��=6���������K���g��G?��;�8�����+�strh��8�{���#��??�?�;C�C)54��`)
{��^���#�����S���G�^�u'&p��M���Po����J���nhr/���D�Tk��y2�u�DB�J������������U�F�^,���gh�G��74�e���������������h/�r^�\u]9��c{�����]�2������:��]7��������{�����9�������+�s����/ijJ�����N���	��d�l����������s`�����/�����M������G�5��PXS�H��<_�������G'�6dv{{��?W�B������������?~l::~��g�}L�=1�<���2|�@����hQ�_u�����sd�Ir��-��c �/��\�z���[_��6lH�=��i�����1�����uw��XLCCC����a{)I��#���D���B!�tS���>��-_I�Y���-���5���t�;:2�kW�w���#����?��.�qg��;�;5o�Wm�J���.*��g:����z:/��T���_%. :U��cW������ 6<���������)��sr�]��eK�Z`��
���+��|�L��w��tu�5��M�����{����������~��Y?�FB�������������)�w�s�h�����
�w�_���0)����$I��9i\� C==�}L���#�\�=�s����<������0{67���co;��}�q�`B�L���B!�������0
�R���'s��bB�UGGsZ��W�q��rN��,������7�?��q�{��=����g7fAkS���N������Poof/^���sSJ��������~��c�������?Lip0-^�s��,}k���~�;;�����2�=�H�������MK���k����P����{~�')
��I0�������R(�����7��sz��#����W]�M��'�;����G�89�}{����#�d��GW���}�rn1�	��y�j;T�L>��N�-���9���s[���������^>�u����R�����[{G�?��Y������c�$�7w���{30P�'?�7K��)k[�z6����;?�����m}�c����}����,K�
s������:���9ey���]���%Gv��Pww�����=9��j����������������9�<���Nf�N�������`���p�s��#|�6�������:���������}�u��G�����~�Z���f��;������+�q�?d�����g0s]�?�����>5s�.-k�8g���������R��KC��C��e��I�c
-y�5����������w(���#�[�rtl#-k��O�����������9���<��/�N�7wt�i���wu���1������]��qc��V�<w����������%CC���<��O���c_��$9�����[o�����k�u���n����{���>�#'5$)��d����O��I�^
-���>����q���&:v�dC�5�T�z�g*|�;x��dp0�mm��@��K��e������E-�S�&s�v8-��-6�{K1�v.����l��J^��L�4������z?pzS�Bk2�]��b���T��i�qlHy��V�������m��l��/k�.
��>�k�i��=9p`(>8�
�T�~��	�SM�L���������?m���x0�5�����n}l�d��y�������?Q��3�KFz�7��f��'�z�����>2���9z����>I�����O~rz����^�8��������wv�����O6�3�1,�
uw�08y��zz2g��>�Y�������r�)<���[��u�	��c?g
���C����r` M{�����S�����z���i��^�z���#��3����k�s��I2��d}���vevl��{��<;��7��b����G�r����J������,?�xZ
���x�h/��={�s�m���>�3
�5������3|�pf�J�T=c���yB����<������P��ICKK���e����f���>�}5�s��8��=�V�<�s;�;w���g8L�����_Skkzn�=C=='}�N�d�v�wvf`�����9�fx������;���?�s�������P~�"�K�N]�����p&������c?tw���d����\�M�1��56U�U�N���j��z�M�?��>~�iN�7�T��T����}��>��M����C|���8����5v�:�{���5�,<a��cC�S����Bo��l�v(��Nr�������K�d�����7�E�f������jy��T�?�;?R�.38P��������\�����<q��N_���Mg?�v�vEg��[�j44.���b1I�0kVf�sN�,��#����%C�������<9+[w����;?��2��_5�b�{��to�|\9v_��#���}������{��G�p�������\��]��#G����-S��W��b��g�����39z���|f�+��[��/���+�$���+�8~�Lr4����6�t-�B���Ws�������9�s<g����������������k�>��=�d��O�������u�
7�HWW���2o��3��r�w(}Y���������>������R*�=������n]���;
MM������8o��s6v��^�(�3<<����������e��og�d`����^}����^�c���9���s�^(����b1]�xEx �/��O~��g>�`J?~]%9���#_�R�yg���<&'��9���Qw�q'��7rzXR{:����[����Q������&�a�dl���c�[QUk+��;:����|��j���^����UJ��f���Ir�@u*WhM��{�l����GO������k����]67��s$���\t���;&�S����ci_�j���Y�6u�������7�G���`���*�7��'�O6�3���#5z��-9T�����`�&�,L^>fRg�m����g2�m�76+�B�c����3Ir��;����s�������kf����0����d���,�����~����[3��C>|��g�����
�Y�����Y�,�/�`t�����7���>�������Vk�%����c;$&�!K�I��-j�6��m�%��6�$p_��
7��J�K�%�����HA��ll#/�6Zf$�v���g��qf�#i$K^�i��^��t������y>O���m�<�yG�� F"�������
���t08���u<_j�.��C�}_�Xw�������Z��z4�.�����e9���E�(G}=�[n�����,z�(��t�c*�k�z%Bjw7�����r) �};��'	l����N���qr��b����~�DL^z)�e��o��jv,�h��eh�r��*���7mB�QWGl��y(u�m�1��!f
���
��^��|G�	��L��=�Fh��^l����}�A�G��|�
�}Y����$q� �&j?C_�M���H�/�\)@��?]��~�-�W+�����������FF��k�_mF�[I.�?4����I������o���B��\�Xr!�!��F��%�J�����\��_�krM.�:c���ns�Z�t��>[���Re9��[���dY����(u�R9��
��������`0]P���I�sg������ ����������j�z9�|VG�o��=�L��m���YN�b>���+T0.?�j�>q�p�`���}%y{yb_��G}��2@�����R�X,�\�m����X�[��+K��E�g���v���\�@]:$�B0l�i�������ZS{����6�����Y@P��,z^��2d��T���a��U������i�,����&�#��&�!V@2T�C������<.��7MlLg��X���a�`�@����p���.��{����1M=��c6��_�:� 7���a�������E��R�v$O�Dt�$	G�Bd>�K��1�u0Mf�~�"��`[y9���ld{����"��x�lYR;���E�*�-�p�������N��6��e�����������jC�*e��������[j[3l���r�BT�Y������J
��*&�fS�d1����YuM���e�3f!�f.3�s9�n!�u9�U��mD;:�e��qI���I��V_�^����V�nX����4~���-16�b�����T��r��j��{��ZZ�����[Ng��0��d�~�B��B����O.�7�������#L��Mi[�Y��`�P��H�3�L���D����j���LQ5A�z�vt�����������>��8^h��*���TMi���6�
Z��,��	Tex�/������1(�-��w7���=|��'�1�V��7���,����{	��qY�KWK��j�nS
�x?E"�b1�OZ���m��J�LA^����m�uW���#��h�������EUM��7��:��\Cjl�x�����r��I~?RI	z,�`���n�@b�^�y.�JJ
�8��������uHd�GM
���[E��9����V�����@�eq�^3�/M�1^��V���j�i��2��������3�2��#gS�E��7E|�)��d9�������w����.EQ[���B��7q�������9%����2��V��=}�b���YuM����Bg������.v�-��.5��j�
�-���R�r$�����K���\���l����r1��r������3���_�u�oojrH�H�"�����2_��\����C�c�H[���A�l[|n�
��S{*,����s�>6w?��uxhy���,U��:�G�X�C#�_������B���G�zI�;X��� ���!�|:"=��4L@�z�v�R�����r���M7 h.2w�aCN���G##����������9��=�--���b����Tv�(f��!�Q�aR�Na��}�k�>��e��u?'a*����G��wp���������E��J>�F#+��i���r|sGC��`�hZ����M����?�9�s6/�'��zm�`�~	��+���*B|������,$YC�����WT��7�=���{.il��A�\���s�g�����R��,#�rL��uA,��M��X��A�Q����@<L��������������$q��ks�v�����"~+(��|���t������:�/����s���S��;��'�����S�*��b�j=/�������S��\��Y
�1K�m.e�].Z���`j���	=%�o&�t.����|�[�F	l����%"���C�J��(^�~���/�F"�o����>�����s|p���i�^�hTg�fo���&��J��
=8k�D�:��IZ[K��[5�9�u?��$[Xtn?����'1L
���E��d�#>����L����b�#�����!��a��p����Pq���>��\a������������ G/���!��m����e�������m�gG��Z�9��v>H[y�����#��X�V�bd��������j
^�8zcj
����9/J������I�;�����`����������[��F��a++����o��������
ml;:�n.���-���p��1i���/�{���]��*WK�w�F��X��^��.��w
,���U�p��0���KS�/FY�Xe.+[�#|�}�����d_�\.l���6S��4!�A-���s�B2��������r(����hT'R��I]��z� Z)�o�|��X��t���q�_Qu93
��%��}���r��jV��J�K�����5�&W�,��Z��KYw�1���X������S�H�xW��w�ZZl����niA���%����;;I�>��t�>u�����H`��E��n�,���� ml�r�s�����N�BAC��gd�A^����c}��;x���`�t�yu9�����=�� V�e��Z;����]cD"*��hk+�*��+,3��|��5�W��O�e����j�4Cp~?559y���x�N!|��E�N.�z���2�	�])
��'Eg���m
m�H����
��n���������]���8x����S���p�9q!��K��Q�����ON��*F4z��~���K~?��$�&�����Kzw��ZZ����"�s�E���7�T�m�Ya�����7e�&�\<�e�{��������3��������kRX�z�����j[+���m�;���^�2�������iE�}>���W����Bc���`��4{�9����/��`0MI�\���
������,4�s�k����K
�m�dE��������������c����V@��-��-�u%�s�{�;�;���]����\�T:��q�6?QdY��Qb�6�����r�.��=r�s���kk�j��j�++������=���\�Y�di���k��.u�-���^��X����ZZ(mkc�k_Cb��G�vtP��/�������]�]��%�\����QG�X�&��h��8���1m|<�B�P��m��sn�V����-�%�Ig;{�T(jY�_-)X�� ��������*b�h�����U�8�����4���l���|�B��������B
QN�L24����������[��%���:����w���uYs�b�#k�X�j�qcQJ�B��
RK
��Yk����IR4�����=�N�;�hk�����e��~D��gi������G���%�}r�����im�������q��Pc
�R�����5.j-6���w�A��=;����Il���C��\��$O�d���'�w/�.�������U�S�,���,��m)$�p.t��]�����f���}�r����U�_Y�z�{����E��,mk#���hu��,���A	����7�-�TO�O?�66fUu�%}������c���������D
�HD��V�b�z
�yOO�����p�AX��H��7����`O�����~��Zh�g������o��s��8L�i���Dc��#G��=yY5W�����b��I�Q��:�����t�����V
\�`A��njj���$z�����b�N����>Sg!Y��t�d����f8�
}����i^Z����3z�,���R.�oo?��[��z�&�_.�����bf����qM�&:��z�
-z��^w�`0�]
,	u>W�uf������6:����������m�
\M/wv������[V���O��)R�NY$��d����J�im�Q������xWz4�$�����s/�$��C�46.�� ��}m������{�
��p�du})��y3��^A@M)��WD1|Hn�5���u�_n
�l��'��=SD�6�@q��XL����k;]�����J��:���l�~�r<��}�b�c�m�m�r����B
��o��!�:��c��g�j---��l!k�:��m��l��"���+K���)�������.Pr��G��c8�<�JJl��.:z9P����8��-�	����!w%]]��f��O���(���8z]����?�H��H�uS�e�?Nj`t3�&��Gd����s�K{R���0��/`��uE�h^-��������{������j�F�r��\V�,/[��&'W����0��B��H>�
-��.'�6�p�m�Z���-�TO����W_�L�P�i<7.)�}��b
���-��o��?�1��)��'qu���������oU��ZFl����yyO7���.i�D�����1���g%���,v�]
u����������K����bJ[V�=r$�A2X�X��'��2�u��-�t���z���o�DT�����,[�����-�w�E����e�B<��kZ��{��']
����$z�?�1	X�x9����b���F��zz8���#>������b�����s���i��k�5hZ��;G����\Y��`v���7���{����[�\���Jv5P���g� ���A6�7�o>]S�9�]*Rc���0Wg.mkC����QLU�^Y�	����)$��VS����:��R'N�X�
%"���,�P���D�B�k�l������)��'g�-'��2����-�Y:`>z��GCJ_�,_��"��
�E9���qK��1X�������+�a���j��~R������T��u}��-�!Cm�e�(������NS��pS4�9T�K/!��8������������J��?���J"a��Y��|}U�u������c�{/6P:w����s�\��K9�.�|��h��)���������lg���3��T��}��`�����A����7M,����F�7�!q��,z�l_�-\�n)��r�s3��y���"V��Q����l��?8�P��3-�1]^�D�e�I��]��l��B�x 
>1�-������<y3����<���'���	��L]�@���3��v�`%0��$^y=�Dr���]�����W�u����^4������f�uo��mo'��ob�W_�Q_You]���r������[���)����	��]��=#����*\/�){�:��^��������P��D�S��l��+5,��k�QH��`��N.d��x�3�4*���xW>b�.FT���sm�_��+Z�N�Tj��V�y�����^H!�wua��z�������b���"Q��$�g��f�A4��L��������r��u�(�M7yf=��=JWW����k"�|iYN���b������M7y��Q Vri���������e����#����=:E�>����7_
�I����!���S&VX��MQx���SZW� o��N���7y�u�j�������e�szPaso����I�\���;WK��j^�v/����. �U�L]j�rn�sGG����/�}�����j�-W�q��5e�:*��m���A����.���[g;�|[����S�s��,��Q_O:<�/��{�&w�&��3�++�eSH�<�>5��L���2��������s���}����NL�:{��={�����P�����VZ��Lb���ZZ}><�6����vB!�#�|8�659ge!����cc�+P��q562�{�����3�
|��3����HD�����J*e,:VY=n�:7}}
Fj��k�c��^?K�Q��@�0d�
8LO�Q:���ze���"����� X������CUy�U?|����&'��N�n�dRg�FO�;�����:�����s��g��x��d�t�*&���e�{��,�!�X`9���������OI����<��c*`�	�o�)�����������T/��O�����[�f*�z�����D�ub1�O"]�����;r$���I�}&��AI���(p�]��r����:3���Ot%1y~ZZ\�qG)��A����b�"F'�WT0�g��?+�
;��#�m�������������h0�H�~��6����7���[[��������l^�U:��\YHor65!�l�V�@9rP��������/d{v� �c��Qv~��_"���/'�%��g������]]����G��m�#o�����\��K�W�&��������ZH�]hB%O���--(�0��;q����������m.mkc$S�"_�s65a//G	1U[I	���K:$.U��JD��u�����3@QA�^��$������>}���~{U��n����L���veV���s��zl����x��U
LV�s,���fR�����R��f1���"Q�[<����s�C���$z����9��t0H4���I�UC���Mc~���0����V:�'���I{{�Oz0Y7�:v�[Vc�z�:}I�,Z����w��s�_LA�G�e3S.tO���MM����}�pX@�u"�WD�u���bV��B��r��oWK�����;1�_�T`�<��B)���e@���������4��I����/M_���j��1�;^[�7nV1��'�X���
�g��������X.4�&gS��J�*��&w�F�F)j��'�9y��g�;v�_���WA�LLS��;S2

���K�#�:>�E���n���P�.G�%+�JJ��!�\�f �5e�:����;n���(��~��x7=��<�o�}��N�Q�\j�s�
���*}}(�w�5��nmE
�����B������/}�����97�s'��X�.�6=M��A���X�'p~�p65a�2��b���ffH;��t2r
�|=������O�
�fC�D��f�S�B���WU1�;�]u�7�b�z����|���H���W�'N ������2��2H[�Z�������l�Ys���Nk�;W�g�y������+�`LL`" �~G
��E�z��t�#Gy�A�-�����c�;�o�z�i��	$D]a��'r�����,���+��V��`0M[[)���}�����M��4�o��C�_����]]q�� [c�L"a`��O+�����;#���B`��J��~:T�����^1�u����R�ww�����G���U��;��/{���{�/}�f����E
�����*v�����������)��:�:
l�|�jF������6]��r�o'w��;q�5�?�l�oE�����>o�������1L��F���T��7\�[�,1^J� "���j*�D�8w
C�SQV�_���c~_�w)�P��R �TV����?����6>��������������\�^�28�s�jl���zv�w-7���'�W�:���	��\��yK�b�X��S��;��'��f��^i��B��@�$��E�����������L!Y.���B�_A�j��b
�B��BJn!�����+>bd-�U^� ,D7c����NWK������ulOk+���s�e9�S�zzRV!������a\�we��q4�=|k�����Dw7��$�a`�j��rL��9���`������F�P}4���}�Y�����B
A �
�XJh�/k�=��oN�D��q������4�?���@g7����/1��Z��&b�NI�������#S���P�-��I}���D=���7d���-�m��h?����
r"B��2*��i����f�p��'Q����s�;{�p�>��0��������E��Q�������&����uo!�!L��>���.����c�|������{���X��_��������1��>����"e���;J����B�n�n��|e�R��/�B�5"�o/��'��~�fj����a+/�g�d��c��ar����U���Q�s�������9k���zP~I������G��V>���QMMN����R&��`��7K3�+�0�XS��_��OL��%�p!#�r��/'z�r�.���r�@xkJ8�����:����C_����w~.|����?��\H������ �o!)dC�H�O�C�{�������d�e![ ���R#�UU���#��^/��#�����Ie�l�6`���6��AJ����={0�q��!tQ�^[;����������|h��BE��D�5F��I�H&q��He&6��d�=�QWG��)�XD�S��^��q�	9�`Q������n��HU]W���lzK��w,I����UU���G��AD�L�X���(v�gs3�#GH:���Afd��#@���z^@"�=�F0
`�����W���[���E�D�Q$�{�nZP���g��H�L��u�Q���(R�4��DQ��H������U@����d��PHa�:�n@���&=�8��Y�H"a�s�e�XQ�������������3�fK3g�/��
������<}�2W�)�ho����N~m0�9�I�����:����(�3S�5��Fu��f!������������2Y �vg�#�]���(0g�DP92��ocF���M��q�U��2��j�]XMu�VfL @��wmo'��������b�Y�'CQ0������
�v����K/��}^���D��1�qL��2�
mtS����g��d�fX<�;�n�)��aD�[q��
M/U�����9q"I,�:�����'��]�`2��[�v�s~^�����,Y&~�'O.H	�Y��5�f�r5��y�j��b.jgU�_?�����*{���m�=kl��Y�|��>��>q�����f�0`���9�
�X���~��\��3�baT���.���)����'������;V]-V��������!�|���G����amo'����(����fR����/I��L�������q������JN��#�����|�YPX!��a�h?J�W~8����'�w��������,�xV��� N��������:�B.�lj�!b=7��������M][o�c2 �R>;vPz�}��Q���Q:}�Px����-[�<��8�N%��	���S� 5[���\�s��P������%#9>��`G����Qf"QNt��`��?��ZT����qV�H��
����r�vU5I$�O8�<tw'�������Xez��b��Y)7�������g9��7s
�q8�p/��(v��G����(������V��C����,�oV�I���h?JMx���I�B�G��o�)��[
�-����Nm��m��8��hcc�CC���+��W�U�E�D���� Y���P[��4�U�Vmk���^"�Bv�,�P��C(�$lvNzn����q#[���_ ���(�6�B!�={&/�)u9d1Can�o�k[Z�b�����BF��F�_.�����_�kRH���~W�����s
�����8��j��0k��
����R6�,\���'���#�9�����,���o�f�pb1�y\�� ����`��9�y��2�)7��/X��=9I��dr���O�MM!������	����#�$��	.f"�69��p��bd�ND�)���{�noGA��������w�w�^�EYih�w������v[�6M*W6Q9����1H�>M��tYFt�AU1ELt{y9��'AUQ#�����n�� �L;������G�,�y����_d���L��y�r.���=���?�Z��gu}�(�R�N����S����[�uV����Dw7BO�t�*cGE�����D�=��}����z��1f���w�u��*�os�x������H5}iAP��������@E�D<��������M�C�`�YCq�4�=����x�Ng)VA��I���m[�]����`����d���)�D����37;f~9��V����4��g���Lw)}������M������	/�)erR�������d����Z�<���&\uL�Tq{� ��{����\���"��R���D<n$�����mvVru�s������<���m����OXk\�4q�q�H8<��g�U��N&��]]'��_Pu�}��].���=�V�&u����G**B�V��^R��Y�SU0MLE�(��N+���a x�����#���%��s��u<p��������b�/r�Z^3A��>w���r�]O��J<~>\l���S������w��K_���'E(�`�B�~hl\<[f)��������"�:�����/����A0�����`�zAj�����_���|�K��N����	wM�>�����!�lj�R���w�-u~�7���%���r�]H*�G�x6n$q�p�TP�M���.t0)�0J8Lb\�������Mup,����3�R7��hT���6��4�1�ElPa���u����^��6������/�,�����4�{}f��(��d)��O�G"�~?�,Sq���E����_Oj`�tI�����4�nR�:��;��L2�^I�t
�~����B����|�u>Wy0��&r�rc�!g��:/Ev�
o�X^��h��.�8�}����!0��#8��-���nf"Q����e���|�mv��<[��F����>vO��-�`��KS���f'��*��vnik��e+`!B`>�:���m�������@Q��G���kh��L�q0B��Le�Vz���hm��bfq�Ln�8����[��RX��//�1:���P��6?�=6��^������3WyU5X���49�3��)�+�#�l��7���zE���<����7�p$���G��R @��:��)|�~|�M�����
b1�,�w�6?�����!��T^�Q7���c=~9�h�B���5.�9(av�o!�p!%&GC���dj��y�����s|��0f�{;��E'����Js��;��_Hi.�`�X�Z$��H�R�G����P�t���5��0J��pz����iT��}Q4��9�������Q�a�o��+�W����Si�(��3��c���E����w���/��'���|S���fz\(Hae�D9p n��u\�^�R)%��jY

|)�����!�_})����y�\�V/:uM.�d��w�
�?�0c�L�>���O���7#�OP�FH���m.����T��"	)t�h�X����V=r�������--�=�@A=Q�e�d{m-���q���sl��J8��^J�H��������|v�Q{����������D�i�CQ�N��_O��!��$������3����G'�	{S�P���2��#���z�H=��4�G�����v��#��H>����a����J�U�#�"jH��1���(�`��i���Cp:�aq�h����L%F�=��v������:��{����49IK�w)�����������"3�~�����HwG�*f~�2n%��L�E_�6�H����C��c"��CIxp��P�#���!���)�N���kj�US/�$�ln�����V�H���qn=7���I�moCQ��uLS ���P�	�C��$�ir�o|����W#��������fS�m��mw����^z_�������Z�Q
�N��M�G�[���A�42��>e��j��o�	��^�������9Z����h�[�Z����=���M�g����zyU������A�1Z�C�f6���*��N�@��:��V�y����R^�f�X/����(��|�	�
�`h,9��B��l�d������RU��i��}�']�z�����C���.������$����c?,R���}�k�� ����c�Q��6+� ��
���|PL>���pPy��V���?����.���q�[�0������'Y�#�����e��y�8��[�%�3��i����x�Rt����)��$r!{%�p�����w���������{	������������qH��"��D9UUv��tv���nUU�y���*�M�O+��{w�YpYt���+O��b�b�$��1�x��h����e�e�7��p����|�pq�8%&��G����^'���e��u�;�J��!�jiad�_pZ�^��m.���EX"�R��?+����h	�7��x�|!���}$O���y��^�m��|[����F��z[��Td
��zz�����#S���T}tG�� �:~��z6�}qo���	"�6��q���9C�o%�W�Fr�1�&C�v��=�Hc�l�E��@��f}{g����$>�H_��
0���~�s8O�i�9}��(��<��  �l�#��T��Y�R��n�xC!DA q����h���@L}����a�w��rL3�+�`=E�z���.��h���gq�7�Gl�E��4���8�g���o|��S�}}����l������Wxj�S��������I�����xW_G��q�� ������tn�Q�����W��� k����QB,�#�|(�.Z�<;�[�%�k�<�1��G�$�e#��p��3�u�X�l6��I��>��~u�O~��������e������S�)�����W�"S��^�*�i�CF�*�r<7+#{uS�Y���2��f9��I�:�����\GS�������|����C�F��e
<�6�@K��]]qN�N����(}T�E�jJ��{)���'1L
��(�`p�~�*�K>8�m�t
Hy�h,V�_�����4f�@[[)���C�U��;��9q�"w51�J����s�k9� L�D25$��h������ey��y��������������Q�VZ�����oC!���M���x���RX�7�s��Y��������U�c�E�����I5Qo�x��c��'Q��>�{�����z>�Y&�����������v��*���B��(���\�<cr����=��8
�c�$i=�@L���[`w���������E|>�XLG��Q1�[f����qGi�����^}5�,���������n��m[��B��5b���K����1�h$��1L�#Wc���E�������3|�4��������)�N�}�R���@���&J17���[��7==)�����_AQ���x�C�'RaG��]�c}��l�Ofk��.��������N��>D�upp`F�����C�DPQ�
�T�b�O���OU0z�	��!�
A�-G���	�ib��6��C*-���L��i*�i�q+�&��ceRG��s�	�������S�UV��o�u" ����	�)�����Swc+��/��� �l���]nD	�uD�wk+w����]����?���tZmK&��~�7���L��}(e�;L*n`3���$$��K�����svTC��Yh�*�?pSU)!�!���5��	L]g��oc�Du
�D
$]��%���8�����~��o����IijA��"l��A���v`����8uM)��/0��Ocf"�c�*����(������of�h@�LD��M�$�T��Z����g���3�4��k����w����V�f%�s��v��	�U�w�m����h�����q�H$�������&��I������)��n������RT@
�m��������I��
�%p�>�����K����9�j�<�f�0�'�y��
����Yc�������'����c}�*��#��Xu�?������n�K@�]��7���6����qZBQ�'���<�a>�|YG	+�"��AU����9^}��u��n\�
������<�<�����[EO/�y�_�
���s���Y6��p7���t�!���m6��:�����.����6��|3��@@u��_�:�#;w����2�s��H���}y�^����C�����9����v���������;�
=��y����������\�@���3U�
f��+�=��F5mH��o�,��,��|*I]�/X����:�^	���
���@UM���!�����v]]q�IM�������
mme����������8gb������-�xy��:�cr�n$��to/���Y���U��Pe%�,w���Ph����?���7�N����e����Jv�\2�Svm���� #n� 5��$����C��#�������l�k:������~������	��K�\*����D�D�Q&w>�K�N�x6r'^o->�D��I�b���/����MM��0uj���S$�)B?����������@/��0bb���~<k�A�x0u�a��*�p����M��b�40{M
��$�3G�N$������2d#��j�~�15����4�'']V��8�B��f)w���v�a`���+uTa�������"�0�����)�=�~�d����5������pLG�u
M��h"�p7�����*/�������hii\t�����y������B�����^g�����.�V����UP� ��J��b<�_������t{;Bf,O����������7R�qf�;������p����y�GS==Tu���"3�z�lg���$��H$Q4u���ve5�S�8F�Q�>@���Z��L1*WK��Q�x��DO��0m�3��K]��zG+z}s��*B������ wC�mV�khj����������������b:U[��2�p��BH�2�X��sizh���������"b���d����1|�Jlq�� �h�}����A��s����Pz�*�n?�k'K��5�g�$��BI�m�wq��$^�V�l�7����_�N��Sv�j�=���s��lE��KC|��	�.��vY����\�F�#������)�����S���g)�l�N/5��;4�x��&>��m��?����MS*O�)�W}����S���ZZrH���!3�G�,���1��*�5.rk"�A���BJ�_���oh�KC�[����z���ji���{g�^�)y�������\7�b;�`�?�OT�7r����I4���KV�::�%Q�
�X��8��SR��m�T ��Xw8Mh�S1GF0u=#�;D��nj����!"1>�j��p
����;��N�]wa�*�#������Y���D#�QD�$�T����SK�T�����i�8�iZg^���g)�s�[[)���l�e�{��������(U?<���2�����>��O���q��������u�i&��a��"*��������������t�gAN��|k0�����1Mk-�37��sk�_3}��;�w�U3�bR@������.0{M�sH6������K��OQ�<�cR����a��0����k�-_���3�������+r�������Oq�(3���^�c}�P���PW��J�oZ����	��4����Q2|��� j"M|R����|5�'C��:��^��.vQ�bS�H����U�e)��(�H�4x��qVbl|���s�o����Oy,��V�)DLt���Q���A�t���TZ���<G�f���VVF�����s����GY��/�=��A-��]����P�"���`
)CB�AK�x�\�J��sE`uY�0���)I`Z��9>�
���&����*ny��n���8�/��r�^�4��a�k��������Y
�W�������3r����W�'�c�2F*�	�J��� ��F�L�����c��H���M�q8D<�If�[����&CEW��PA����3�|vT_)�cN�t�f���������2����H��a�2�G���_��O��6�v8��M�0�7��
��
t=���*�<���V���}��A���^���.�#%�/��uk��T����eR�
<��$�frY�������ld����7M^zi�pX��Wc8"����N>�j&�,"�2�� �p<�8U���z�]]L���p
�gx��3!�iZ������f���p�2��/R���~����3]��v�^�
����P2RJ�^G?
����SG��:b�F*"gx��I6��-�!���A�� 5�`~uu��$�c�E�������PB$}+�z��=����1��]�,{x��n~#}���$5�(�h�b��E�ke�e38���(8V�D���0=�%=�Ux�� lk��+@��5ho�$�<���g#8�"~Y&u�$��������%�d+������I��q4�uh[w�"��L��������v�t5�9������9��Rij��;��W�e�M��FF��}�m>��t0M�$�KH�R������up�hG������%�>��MM ;WP���8+l90����c?���?���9>�cO�}���nK�������k���Mm�D"*��������DTv�ehh6]j2i����e��i"��i�L)=��4"�`0M5�i0uY��~#�]]��*��S[&U��`���8��d�j�-�S�Z?V-�P�*,����������	�����(UlB���lj��H�Z]�q���������_Y�j�P�0E}�2� ���]��oq0�yg���=��������[=���Qh������;���f�^�W
Q�1X�w~�����?�(����:��b<7��p`�a��>�)1'��U3������3)*�c����$EJD��E�	�(��s������fS�����:�2?��i����L��1t6��h�a��!����XZ�����m������l.S��.��������L#������%�@������V�<�����������"�����e��1�T
4
���L��$�2�Hq�[��;r�����>����|Y�(����f,��a�1�w/��n+z�����������B3�m���A����2H�������#!	����/{�%��jUD�Us�3�y���ml���C�p�����9��1i�'X�����>���4nY�q�U��)Vig�OM��B�v	#����}UG��@���F_?zZeeO����7G24����2�~_?���I���CLIU�Nr��(�l0���V��#3������D+P��=��I���hu�����s����u4}��}�OB=4M�}e�z{_�YU�o���{\����3�N���$'�p:FF4��+���Co`�&�
�A��H{p��~�C��:�h�#x<��}�D�Q��}����S&}��j=���J�������Hk�T���c:*����:�U��i��D�:�S�z�E��Hn�����������
~g��L��q�n���]�9�;�>�<u�2��+�������&r��������g��G�����Tv�=�}	�oD@�����`h&`�lj������s�����g�j������>�;;qF�������-��A�4J�\J��^����v<�9���4�����S�U W=&�������G��j�|�,��6���O+ttD�8t���<���8��mB�������;rk7���;��c���E��RG�U��hCN���S����Y{� @<n��K%a5������n���zzw}/�@���|(�����Y��Aj9�z7�Z��������l����������'_f��](�*���I�qL
���\�`����"r8�ff�noGn}�#c8'���Qm��R��
A{e%�����vy��_�4���R���as�^(�����I�{�d.}!�w0wv�����0L�d�&UUv�o���!j��Zd�E,�c�����3�+Z���hT��!+P�i�i:n�8�
�"�}}


�LU�!���f�,�@�h?������
��M��+���47�r�W������!E�x�Zn��f`qZ�|z�<��/]��W��=+����5��#--.��m|'|u'�cR���6�
���0?�p�t�l�:���c�0@=a����&���x+K��3`�r����I��z�������JJ�n��.���ne�;L�����g�$�TSB,��)����:K�����������ST��e���a@Ls09���#��W�pL���g�*�D�4���CFA=�������X���{I�;���O��>D:��7W��N��IQB0,�����!������D�@�I�1&q*2F\G]����"��7����x�U+��r�X���=����D]zN��x��1�.�V�;9�GRH���1���3��XU�92��J1�g��*|�i��Wt�D�Q���]������(�8��������F��C�*)@E����i�Ti���G��=�5�"�K���)����#���NN`��������d���41�����Ys������$��v;e�������3HF�jR|��,�������1x��$}}
k�8�Q��t��*}���Av����'��;�<����4��x�a���$%#Q��)TCb(�2��Q,Pz]

����D5��BGk���.��&*lTJJl��6��/������&��R�3`��iN{�k���v5���Qc
7�B3��U��Sk	�'F�5���to������"��4M�#�l���)e���Oa~�^nQ��iTg�()��e��I�C���.U7otd�h�l,�G(���{{IM���&��
,=��/�����	��"!���mE����S�	�B���!��B��j���:��$Ou�
��2T�����������I���Q�� �"�L�4���e���p�i���#k����G0�f_��W�?�����"�pq\Ilj�(�e3���6=���By������7����sx�&��8SSE���m��>��q�eL,}X,*%� I�i�j%�g���v�0H-�����=E��c����6JPZ*�v�������f,�n�$M/��j��-*�T
���^YIW�����#=�N��[nB��fn�����}�w��>b�+	����)no'5�f��p=��>��7�
W:J������P�!'S��_�]QB��u������liqq��+����0MU5����������GJ���'��4XE+�07&y�+���[sFA`^Q,�{S�3S��<
f`�v��58����S�p��R��_be�������A*iPt�_�������lp�9����-���Sy���\�7+����=���d�n�����'e(h�l���f������Q	��
;7n��7��b��)Z2���*WtsM���rU;�����%�sl�~��CL�)��wo�h/]�2��}�������V��~���P���>�������b�a�p��|^,�'L3�_��'��BL��j��)��'����o!+����`q`�L]t"M�S1�f�F))&�J�)��@j*FJ��PM�47z"I?n����������3M��il.�x������`� ��G�����jldr�������pt�����2�Q�(i��$������f���A������B#�TZ��/~��a��V�s��.~�����7��������`�F�CVP�IB��,��&leeL�g���pxx{}=���i��&�����WD���4)7����f(%|�}E"$�&��_�h����� �����*�O5�8�����������p"���S����}I�����&���du��n������eh�V�D3Q=����I+��0LE'=��e$0M�d��4�L__�?6_��~l3������q����m�A�N��V�-�p����p�o0�
^:gU�.^L���4B�S�M���#x1�i;�S�P9IL��m��Sh�6��*H�4��?���U��kH���Vp]��H� ���5�c4D�f&J�
Zl
� nd����~Jjpgm5jI-��FJ����Q�H*�����L*^n�q��*�0p"iA%�2Q��HP�i���3
�'����hY��lb?g;&����u�=��4��3���rh��m��G� w{yw�.��5|�H�l�g�H���5��7���m�}��=������-�r]�/������tU����S���S�SgY���3L�0��y}�S����2���C�����X�`=%�����*��/�b�F�"�Mc"`#������
�G?����}���7b��9��o����h��TPN����V���W�$y[�AMs9��?�������R������Kx
A�1MPT}:M_�+��c������;y2����D$J�n�����P%��Rd$�6jh��?B���������Qz�}�^�|��$/1�Ko���tlY���7���1=C��Y?�,�<������l����9j���;r�����L8�+�X��t��c�x��J6?�`$C��r�0�_�u�9�oXM��ql�����e�S^MI��'�]�v���3`�������S������lp��'E{�J��>V�
���W�����i�^��P1M�_�i��I��1
��������!������=�q�(��undY�U`�z33Z�|����e��#��4�����r��M��&��>6��w��������Y��,�>��
d���������$kT����P��D�@�L��K���
����2�u�uD�
�M�_>z7����Y�8��Y���tt�I<b$2�KH�]�r)|����\ik+.��*�8.�.��AOO*������3@e���Y�g�m�~�F^v�b��Y���vQ��N�La,�:3�M���7�y��a%��d��tYF��Yq�6p���S�-Be�ji���;�no'u�$J�;�Q_�Dw	*:��4!9i���b�Q��;��*�5n�em�w��t��.#6DQ�L�}���F4S��bm���+V�kd��Z3��s�$��3�O�dyMDSU��>�M8�W���a6n�����b��4G�*��%�T��.`��6!�I�1b1�5�L)2������6�S���"���3��D}f�dy%�tA01�43���<�����t����$��d�a;�%����g��'p�&3��q���t~��	~��l��?��Kb�f���#�#$�r��q��^"S0�
6UA����2fI9��(�X��q��7	��A|eE�E�
�1�r76	&�Q�$�����
`�C�E��&���&�)K��P�1������[����?�a�B4l��
��L����#oCU�b�u�a�Su������B�^=M�^��F:��Mk�q��v#�t�SC��q��
�m���)co4���s��T} H�W���az�,����j��a��Z��4�o_�&����!J�Q*�!H��fbLQ��E�5��I��q�vI�pq��d�iJP�c��XW�!�{�RO0Q�������{4�"G�
�����DTc���c=�w�����cK�H�0��*RF����������_��<��YFlZ�u��j��g9��C���3|���S���b�jF��9��3�@}�'���$��$	�T���#�+����`K�Q5����o�6b$M/:^t4��(����������ttD��;�8v}����I�7
4�����g�p0X���d0���oh����g@�%1���e��{���k�����H�9G�a��2e��ib�Z�����JJP�ab���Bv��-����S4��i����������Y�������/��P���B���l�[q1��������y�,���#�)��o����8�H����g)Y�����!�
#����Q���=��q��D�q5�7]O��Yk������o�=���`C2�$���rA�l�`��S��"�z�>H|1o5�o<��M&-9��Q��)$-�iw �f12�
!���,*"��py�g�lx/��������S����kZC��}�p����o���sQ���������]ctw'��n���������6N��Q��^����>j��3�����S��'V�u�����:�a2rtV��t0h�{K��t��)�E�����$��{H�P�iT���/|#����7{�)�������D�2�a��0u�����Kv(759s������������L�8��6�A��\4�<|�}�3�[[q1���G�]wlK0�fU�������(f�JJO�2ki�U�Yj��krq"��\o��!�����	+��e��1���du�g�~W3�x�'���_w;���B���4�P��O|��/})��lQ�g:���n���>�{�w��'J����q�?���v�K�>���hu�������`J6j����R1u&���-�E��4������I�����&��]GS�%��������$�����4��I�z����<���T����B��������0�)g	��}7~[��;��m<==)��Y�����3J/
�b	h|���@%t��#]@�%%`�a�`�H#��R��������|�����%5%c&�����Q�0DQD/�$=1��@\Pf��RJ�9�
A����!� 9>��-�����9Lt$N��2o����2H����>�CMEStdO%��PD!1��y���0q
��|c�cCBG���)J�E�U�h�C��S89��C��6$C'e�3Vt��S7v0wU
n��IR���(��Q)��tTD7��?���J�F��@��1@L4$B�*����M�S�bxH"` a`""	&	���$:vTL�&��iw!�:�r��.I�^�:6��cz,��%q�D@�:91�nb���vt�)B�E�h�(B�mD�i@%j�~(���LQ�0u<��9�&6�:��� 	�����E
*���)�I�^�>���|�_�M}�z������t���\������A��YR��+R�c;5�������=[�w�8%�8c
�M������cJ	���A%�������j
S�PvR���D��|����(SG���41%;��F��9���������g���M�0�L^��v��A��G��u#���8����~�X�V^Vs��`��'��S��Y�����F6|����h����|�����:�p��`�����
��=�oN=B�1�Zzp�I$t e��������������w��(K�1�HU��^Y����]��Z��T�BJ�P��!��������G��q�M�~=g�,b����8Y�!|�q�X��%���1�N�����Ep�W&p��"*qK�����b��Jj��E���O�����M�������[���L� aC���n����B��x����`fv���E���h�un����V��C��-�������?aS�(��C�|�V����K�����D"*�S=�����$Yy�W;��O��I:mRVf!4���uj�?����Fg���.�;�:��'�1��'Uu�8���=�[��p
]]�y)���2w
�p�E�����Q���Db[��(*�]��9_~���9������	�SgiU��":��mw�<�?>��N�����~��4$�s����+>�sz0y%}3��&R)��zcc��nV�7��~��A��q��]448�IxS��D�:�������$F�;�S���#����|��-��Y�ay�e�Eoe����q��������:~�7���O*(mo������m�D�Q"��4���~��o�=�+�f��V:�P��f�F���d%���.���7�����}��F�Uf����2����~���C�U���.�`���b�j�I8��$�
���������I���$��H�`�#�����`�[��R ���6;1G9���W<t�fT��:������������������0AQD�WW����TDQ$QT�T�FEz��<�sc9����a�-?o)�/J.Z�sr�Tm1G=���������OJ~��l�� J�>����]�1��[��3OU���8?)�$�����<�~�0��4q��"��'����t��h]T�N\��rK���G�L���x���M��C�%�����
�z�(Zg�������������}r���d�����l��SgAU�7�
F}�������ne?1|�ts���Y�	���8g��S=�
u��@��(���E�aG��i<$rs+�����N�r����(Eb�
qUr3�{�k1����O�(&P�>[�Zi7Ii�^�������L"hJn6D�SD�18d r ��;�E�H������T�C���1G.����w�8���#���$6D��D)��!SD�:�	��\��L�����
D����n����v��Ib���f�(.=�
_���;����t�s�p����ZxB��`�0�S��W��UF/�f�"�B��q����P�/�_c�������J|���y��L
ut��@��}��5�#��LOi��{g�:��N`
"�n���qz<��;� ��!7p8�l��q���r��{���/R����I0����\�u|{y9�w���}��Vn }�Gs��m��9�%����9:����Sr����K�����_�!����M���y=�����q�]�s���	��'�4�H���Y�����{�
�zG��Q��)�����������e
��W�I:7uD��J����c`S�W�B�� )+�N�#��D:��T|����ha|L�~�el�<�b��������i�g�[�����6�e�1��CH�L	+x:7w���E��j���\�u��FM�����H�7����)��,V���)V����l�^L��I��]��i�f�h��H��
���9��0�+�tAO���+������z}3�����8"�����c����1�I�~�����S��N�������PL�qG\���� ��(Ur�� `�#�<�N'.}�����F&�BTc�@N��^�pP����d�����'�����;����f�0�?���d��Ri)�������TO#>H���,:�����\�U,*��3������7�� S��
-�PV����W�$�{��?��E�M�z����e�����w�:�)�2�6�S����[���H-[�x���s�h`���5���������Q��R�;��y��]x����I�����\'�)��K�����3�����G]�mm9��*c�v12�$��S��*uQ$�0E1����G���)F�S�����Z6r�b���8t�����B����@����,GfVL@G�H�e��\����I��O
��K25j9���'���9F=��
2�(�~�{�("�����/��)��x�
���PE��uh������BGBs��+�y��;����g�}`V@��/�~��R����TE�a35�������N�$��c��������q����\����u������mL(���V�V
b�|����N�}�������*o���^J����3�W�����&�`�D`�
J������	N~Y�����A{�w���:��]��Q�c����_�!dZl"��[T��T�g:z�M&�bC����<C,_4f����{��s�Y��>
�����I��=CG�\o��������"!S�X��448Oe"��PU��H�3AA��g���
{ZF�����I��xI�!�{����
;NR��T�9�6Ql~�z�T�g9�]��M�}a������eZAM�i�����l"�)�2l1od�y?3{������'��2�7�D�UC��!�[�`����9���M7y��O�����{��������97NI�k��P�\G�c-?���R5B#�X��	cC���)�	��X<���������T�;4���dqp��A����[y�i��4.������n#�.�X��A:����H�$$6�7e^���^�Vl�I�w���O��"`"�c��@��0f�
[M
c%���>��4^ub�\52�-�v���[�)���u�����7	���4<���f�0��Cl�������L��S����E����Rl%%����[M������H�:���I6�e[�iN�i������aDnK?���<��CV�t�[������P�H���o���L/?p�1��*e�0�f'�?���\_��3A)^���I��"dN�nf����E'7���!���L�a�J~n�0+�=�5���������3
��D�����H�$��QVpZZ�+�;i)��������~��xH��yPQ����;�^��hnv��K|d�(��F��wp������+$�������k'�����
@U��5�Z
"����^��2_.�	��e�����s�V_.��zn!���k.$�J���o����\����^Q���?_v?e�cs���5�?}�5���>5�;?���)[YJ��?��Huu��y������m?��'K���g]�����S�N��4��b����[Z�vtXt+�z��iUa���p�����D���U7>�3����oQ���P$/�R��f�%���v� d�<O����4�8I�#�D�a�t�r�;�Y�GQ�@)Cb-5�k�+X��!y��&�7Il(��p���we��d��a���PT�Y���pG��6uj�����'a���c��$t�	��;5\�	����$I\xH2Ne�$i��)��R��
�4J6�f��9�f�\?���*�1bL���h��V���61���]9q'F��q���ka��k����@p�`E
��(5��)�L��d a���
�6�K��tW���43n�6����!j)c)l4i��Q��7)���2�y�������^��8Vt��s8�Sf�"@D�I18P�2�����T�
��
"|��)B���1c�3D���E�A�DC ��bb�����8t�J|����Y�~�D�s\��s�c�3y�����57�tD�)c�:*�I�1��I�������~��g��������Vs?qtDL��<�v>���"E
�HM����Tg�����P��s��s����|�eP�6T��`���0�
V0J'n����lN`
�4��E)��#!�4���G�
�b[�2��HaGC��U</}������U�QG�X���J��c�_�{����:�;P'��\C:2B��L,np��N����������G�����c�8�`e����)J>�EB!��������I����=O�5���������ml���=K|p���_�6*���0�09N*�F�%HkN��������,�YDd|����&0!T��)���0��V�%IM����df���o�����*Q�g��|`H��d�F�q�x
����V�-;�S8rv������*������b7-en}�"��j�k�2*����/�[�e����
JJ$n
�;5z�����.�zY�ce=����
s������&0M	����r��y��)�Ra��2��{)�dD5�.9w7�4r":��d�R<(�x���di���l��u�@��w�r��h{;��;�25��&'��r���E��)�U��G�q�g����H�vp��?+��TO���$���:�������>��r�nF��0�3����)9&
l6�|����~j��u*��k8 ����D#yM.,o9����b���S)�F�U<+kI����K���rH���9.�������s��Q��1[	���'��Ly/�������5�EU��R��/���$Z��`����9N��G��\��xW���C��)��~��y���C��cc�t��BA�w33���Ilh��I�"H#�p+����m�~��R���g����3��NL�F)�����8����pu=����	-���w�d%�Up��*�[d��i}%[x��z~v��B9���>>��I��]��;�N�s�*O9'���}�gy�)�-� k83���FN���#���
�Y��wl�DF�"��U��R�,��
A�a�:I\�L3�l.~P���o�
�����������9+1�8Q��t����<FTD��$e�d�����PB�"���A�58��1����!������J�!��^���/��V �|4}��\�]������h8p������K��0��Bs)�sn@`n{����=�
����F���i$l�%b�Jn��ms��5l��Q�!�3�
�7s��%���	f7)4D$L�	 �E[&��������'s�����`���Jq�
���X�u*JS��?G��1��IJ�d}V��h��]Y�_������!/ s��lvF�/����d��d���HF�9b��F�><��~�������$e��XA7
&6D�H��Wb����S�F��p�B��5���_VOZ�F*vD@A�����_h����A3��sA��&�p���E�43���H:���sY���5��������U(P�
�MS��42^��L��UB?vSEQ4C��7o4$b�
�l����Q\��Ho����k���x�"~�4��+�wXg�j$B"i}��(c�b��[��@�������<����&C?��ZimuS_��q��E��;��|E4j���4��p���\�|�^h��������ihp�cG1�wO���T��\���5������:�����I���P���9�s�g�_����Ou���A�D���k�k�$V���O��K��������2���Db7���f���
��4<+;��u+��>j���u����|3��K������Q�auuLQ�??%��~�
FI�d�8�cZ)3��#����A�(7s�$.|$I	<f��$��K���I��C"�<��v$4O�<�C��p�������M��� �4(O�5�3�%Jn�{���ws��I7��������r��y^7/t���s���J���K1����K,w�4���u�8LQ�(��!p�X�������.��z������<�?=N 1H<-���P&s���L���9q�8
��:�y^{�1D'��e�9��u./��Wpdh&�Y�W�}�ni����4nB���m��K"����G�yi�O�6c9P��	m��3�S��?2n���Q���sj��;A1%� `U���i��eu����|Ia'�2��'s�LF���1fe2du�7��U�Q��,�`��S�M+U�R�(������!j������90�K5@�N�*jF�Xd�8W�.�����Q�$%`+��_�Q=�=��l� "1|T� 
f�b����.}s��f�U��	QJ��fzH�eT���}=o����}�$���n$0I��E�����o�6~L�OV���R��)�89�d�G�gu���������me��(�����B�\-��i��@����4�(g
	?1T���	�=�$�����:���d�W
Q�	dn�{4�������Nl ������v/#5�P4�����!-xp�$)�(��!��sx���w�����5D
�[/k��>V��u��������������Z���c��X����>N�������#<u�,�������������G/|��T<�mJ�\�=I��'�������F�o����O�~j/�t~���7�Y�U�,����)�������czz���Aq�]K�7����]�##(��V������u���\����_���D�R�w�5Z���r�yb7��
�G����q�������G��!<zWb������bH[����S�F����%w����u'���S�B��<��?&v���(�ic�����_b���M��|}�G�|	CU��������={P���C,��e|[��~���}��q��U�(�p3H
'��b�X�(`��0 �Rc��0?�����F
ur����
�����AD�P�n+���Mp�1�cI����sh����V��t�����c�H�� B��b$el��g�����R�%3��I��_�<bZ@AG���t��>��{+]1�����2X������0I@� 
tl�e(Wz�B�����(>�3��yUg�����dA���;m�g����(�����(fjI�R������>����b���{���\����g�����3�(t���}�5��Y��������S����"���9�z
�e��;�m���A��&�Qp��7��+a���y�R�[Ev�r��V�s�4T�S}���#��&Im�:�}�|g{����`�3��8�=��oQq2���4�G�G0�]v����3��[kqg�s�bm�:U@�U����MQ�I''����c�BT:3s���k`���]s��`�)0R���������\�q��1�~P������8�f����]c���S���I�YJ��4����C�|aV2N�~��5�!�E���9+xc��u����P�Lg'�����QRI��/�4��LH��sb��j�M�zG+�?:���aO���q���������p���_����������7NP5�*.��@���q����%���e�����f�j�E1�����{K����s�DU��
d����0=�s�h��'�<��8�7{����PH�����4z�y�_/~��
�3��$��?���uzgi|����8���U[����BV
��N������������l+��,G�nY�y��	ff4��w����+�b�#��"�����f(�z
���w0�s�Tg2�����8�a��
uM3�.�F"���X"����B�������7X����+~����D>�q������Quu${zP#��)�h4A�p�^M�m���`2<MLvo�otw'1�_�~���	��D)���RD6=4�K9V�S%#H9���nZn}N��u.���V��\:���$��)�E�f&�UQQ����Rl�c�������uAgj������ �lz/{�����f�
n��w,$Y�c�>�cGB������f�g�#k��$��D��S���<3��i�4*$R�)J�������(6�mn�'�9��,���S<���$�O�
�:�LDC��Ne0��l���D���g�u��������������qr���?��[�K��Z��Z���"�j�@��`��%��1�L<L�/	���|'�����&2��6�m�-[�%�������V�����~����Rw�eF���[Uu��>���=��|��`#�F�i�t���nW�0�&�$���h&� Y�y\$id�(n�8�_L^G�=��N]��Yh����9��	]���5y>������lh��E4��3Px���Z�]��f!,��(eL���Z�(����D�k/��,�cP��L���
��]���y����+�)��%ZH\��W�d'O��F=�)3�X�>C|������I�7����G��(H�o�1����K�{	��F�4`�r�HyD��u��:�lv7"���v��2���w�E}���Y��,��E�`|������H�<-����U��c"!�2$IS�i���-V[L<D�3���ON��
&��w�z,�j�J*�Z�������<��j���m��������L�����_��m#MP��E�1��NR���0���MN27�������w�	���X�bs��w�BPPdF���{�'�����������i�,��+��������� ��~�]]�4���c�/g���v���1w� ��n0�cY�����

_��<�����4>��b1�z���;�`YH�\v7a[�s�i|���0����^�=�%�I�1"��q���l)��8��3x�}��s�Ex��#�y�G����(1`zJ���%����86J�d��������O1��O��,�$���8�N�D���L�H��:p`Q��u�6�5�
�����b�b$��#��#���(l0�sZ���N=Cx�`""iC"�t��}���0���"�E�(f�$N��9l�)3�p�*&�������[�J�����>�������i�o�	�41B���B��ex�"�.�o�#b�����W;�{2/�l{�_H�>����i���NgF�][������,�����Y{��[��X���E���W:g��_��������M���O.u����9�+�W:N���J}�j����=�+�_f_/�~y=�z�,������m�wD6�&�;��P����f��wm,[���%��ba�
re��1"�p�+L�72�\%k�
x��2B!���<�����l]�=��)�L�wN�.�y�5���h'_��S��M����B�qr2a1	_�G��BHh�c6���C�8>�y�	M�h4�a��;~
��*g��]taI�4���9��\�����9��<�W��cB��L~��p��)��c����Q^����t)����8t�����]R{�3��"VI��@�K��'I4�����f���c��Y���_�25����B��^�l�8l��{�7��/s��8�i���I��f����1��AE�����)�s�d��9�M����l�^��	4��*�Q*�a�S�4�G���bb��t�8�#G05
mj
����jEL���o����ky�����=�������QZ��F�����1�4�l�8q���z6p�$q��H����u(bM�L 3�
I������E�z9�����%�J�>�{�Z2���Tgd2F1s��|����#�F>w���:�<�~+��8��$�L`�b�Z`f~�Q~�S�|�s��u]�>�R��,Hf��
��&��TF>�iD'�D��a�*��Il��V��X�����P.d�O�5�������]HxXj������Dv�-b>#��d���2��'b�~���r}z�w�R}�T���V�faQ���my,���O�
,e�����>�����D�#/C9k+U��c�����R��-0^E ��q ������Wi�m
}&+`Q��E�^i�d��f����~�/������^���y�w�>�h9r�[��=��}AU ;�U��b'�l�B�E��T0��J��(;.Wj��5�4��8��$��3�<�{F��O�S�X����t���L&14c�<e��^HLS��E�Q�����U
|�5�����/�c'�x/�4�����S�h3�^��K<���:0��1�%Aw��[]Jy�u,�
A�0S)�h{ss���b�y�k���k���#b����N���D��*��a���T����FH���S��y�������@ji���[q}�_��v0�rs|���f���
�1Bo�)�F���'i��������7S5��x�f����>ET��&�,%V����v���s��	�UbDN�B��B�h�n&~���2��V��a�TU]��������F�n���^1id��������1�e� =�Ie����K����x�j�����mV�p�Z�h���$E����I�x/Sj�@V�@�@�a@���sY}��G!��Ix�fIFX\?
KP���r�Z�y)'����0��F�fZ��J&^�5/u}����f�;�l[���bW��]�+�������	�,����I�:@�:�H�*��bw����}4%���FB�#|�42B��U�U�0}��Z����L����2��`d��L$R�������m�U����8�7l��
�x�{�s���[�-�P���C��s��? ���[=��7l1����qE���vD>��*�^����(�m��p�p���$�i��&g�����l�"s�����O:hiY^@���4��J]���������y{{u���$��+��SL4D1I(�a�J'��1dy���;����37gb�pfn+��	�
F���d���g���4}���Y3'~�	������6�`l������-2��O��;�d������js��H�������q5Pm�PD���3V�e	Pf�N��?��nN��B�LJ������g���6I�#0C)O��f��E���>�P��$�R�� M.�87H��H-
���U���`~f�9Bp5
LLN�+���(3F;����d�s4G��l�J��	��>B�TD�n�qnd�z�A�d�[�s��Q����C��0�X��8�	g2�,�:��b)�_.��\[���IH�6,��V"�,um����o+��O *��!�,��,�}�{�J�H�*[��K����.���o��vY�0�a�u��mC�f�v�	�
���_�{�j���1V�{�����I"/��(��0eR,wl2�{.���~{-YS��c����3��>Cg��"���}��r����P�z
-b�v,I��9L
;G��Qj���H��r�����%�D{+�������h_BD�f���?x#�R�0���_��<��=���0���2�|0?Q�E�N���F��VT�8|#C,-EjkC,/���jFz{W����:.�44H��zo/��H

H--�>�{e�k��l�f���	�j}�&���2�M�$��$4�B����	4a
qj
���Q��C��J��W���^��p16�2U��
8B#>6kQ{u&�=�����Z��
���O���.����k&q�c'-��@�*I`�����i�Y |4�15N'��0�W7qW�����M�3�$��A'��D�1�I[���,M�wN���h.������Ix�A!�3�:���h�%J#����3��}s
��\���������?���QF�A��:.d&��3p�E)�(Y�-�o�����B>�o%S��b���_��
&,>_�v��s�M�]I_��]�+v����$t&��Mw�����>����bd`4/��X�
j��	��Q������@���g�
��7^���T�0~f�2E�e46p�.v�*�v�!;�3����e����uu��[��UW1���,��e`�F=����ihX�-h�.01a�i09	O>����:n�@k����������u��a#��e.X@{���n�����o;���J2��PTd]_�0�)@U\�k������0�2S�:�����7>K��?����w���_od�����	>q���e����/�����A�����8���:&�&���8�(�^�nnvQ,�bYQ��jkt���ix�@%����~��hFs[C�������a�r&q�FD���2R(��2!�b7���Y5KMk�Y�H9&|/6��P�U��@ e�H��QT�K�?���[�/���@�f)b�l��d��I7X��C&���M
qh�����W*��V�-_��=���^�V��Z�x>�$q`CE��,YMv�j���]X��XIDAT ��v����z�rl��Sx������^�����.X�e�+�o438���i�\��j�3W�xq��1#C��x?'��f(��?��#�W�@M_t��ns��2?�I��x�~Z�*��s��7�H�uR�����r�:���fN0D!J��c�f�Rd��3B1��{]d���nbY��Vq���.�$!�_�����,�O�U��Y@i�,l����&�����9E������l����$�\}��S�����A*e�I��]kt�6�T����2*�Q��el1�$���h(��S}������=|��*��a��:L6Ic���wg��N���	�	�-�6��Q�i������A�[����)[��
t��A��hk�B�&0�qIB������42�A�	ccT~����r:T�]��k_���#@�d�F��^&��q�	;�n.*�#�\:A%G��������\�=�h,c3��~��1���.�e�B�����cs���w
Z|$�eN���3��D�w�\Dpf�f��t,��]\�d)�O���V�w����o��dc����/)S�����m4��"x3���_��vl�bW��]��|[m:7X��(t$F���<^bX��)�Hh�b�Q$4R���}�R�4�I-���5T3J-���A��
��-<�;�q�>�@�p}n;Y�q��y��zF�����)6�(oc'/^���<����ok��}
�a�
KbP
����cL��Ih�����M\w]{����hi���)���I���$�&��LY�
��p����__MK���2--������&y��1T��^��r�f��w�:������Q~x�M����V�������?$��D<B/5��GT2A5�WI|}YS{��J](�0��;	�}�>�:���O�df��*��tV�~`A^2�j�j>)����L��������K7��`+r ��X���� �����"�:�������y�:�<{�E8�CJ�D-�@6�������1����D�2��3����P�J8n��(��G��O �:��A2ebi�k�e��]��P�B����"�,E�<�z']�0��xi�m���xor�F��yl� 6!�~�q��..�x�~�������������6��g��K1�����v�RM
�����2��/u+�o5��B��r����1/���\�~�����z�k�6_j.�U����[x�Z.fs����b�^���H(KS��R��&	��
��B�V��45� >������<�YG���U�r���q�E�
��a���\��2��F�0C!���T�u����8�{�&*��s�����g���zCl�����`�L#>_L�����4B^/��fR���h�+��/�~mw�O��_m��/���O���"�(.����J����6��Rlj����r��8t#��D.+����� ��L5�#L'��5��ye�u[�{[CCi����U5�������a` R���f����x(�kB�&=E�l������$�hEK�^���XF�S|>��������C/�:�bnf�_p���v^���\v~��K�Jki�Y>f����3�p1A�4������C
"o�g����c33������p~(M��;������V��ID�P��EE:��<.>d�m3��^Xt�p��*����::2a|�HdXC����?���eX�b=wNHb�F��E�Vk����#�����+���bW���>��\*m��
����+|�i���1J-��$N=�M������y#�r�o�'ierBcD����gxo�$S�F��	Q�x/��8����L ��i*��aL����jrr]���6H�q��Q�^����Y��z�����D�v���gx���_�!�N����#3���
<������X3t�;<�����7�}�"
�T_�]���g>�;<�i��������m7����������{y�����a���i
�uW%������%���_���o�7���%9�v�������b��8��5��T2A����0�
L]'���RU@-#LO�PU�f�(�D���.�8�2/�m�H��_T`,����=���uZ��\W�Q�����F
��1�f��N�AFw��*�q�������
GGN�?v��b5FB������6��yv[�#L|x��)3}�L;.�$p2'WRi��A9�]�����:R*�SV����\��f.�I	���J)+�U��b���w��&��]t������Dq�K�5�(�������YP44����/�M��z#��R�_v����0r�2^�-��&�L��` #����W�]�-���q���Y{��ZWl���l�b�<[�XZs&:6-�l0�o��5f1��X��%�hC��y�	y����
�:I�^I��&Q��w�6��v���=\���7�2��W���H&I�?�NzpGk+��a����������ZE
,�2�T'��3������<���o ��pE�u�_[���s�_���NY��]wU���'���}��I�Q\Ln}7U���;Q������uy��t������8z4�����@���4����0J"a0;�30P��M�������=�#$�U�*�J��d7W'%-���#�s7�gI{<4?����]K��D������v����`_��q;�nj�'�E�����8Z�	�"e[=�v�#``b��Q>h~�]p�L3���P��HL�!"bifY��+h��";(�r5��A^�`p��ZFQ��i�(�3-�3���V�j�0H���(�8HQ�$.��
*���13i�.���F�2��lQ������&�)Dc!$����JF�O�Cz�Z��fe&8�����3��K�jY>��a�4����e�g�{���g��������o���JW�,{=��PZi���j��
�X��� �R�_
 �������_�1��=�/���Wz������p���]8��r�jBN�R�rp�K�-d<�4^
��r���NGD�N'n"��V0]D�]D���lz+E�/��38DI$C#�I�yN��s%��������10F���jJS��� v=Brb]�0��:��8�A��w��P��^/�`����Vzy7�k��lb�'��2?x.J<n �hv���n�oa��Y?[�;��00`��659���I{��`p'���|g������}})�n1^wtl�DOOGg���Bx���}�����q�0d�jZ�C�k����G0���=z���u������a��1���MG������Aw�U�}�M�F�����)��Ir�@�
�p��`���������v���("M>������G"�EE�Q���]YLs�����2?�
�s��DB�*s�5�?=
�SK��I�����D�5���3�7#D����W8U��p�R���"���[n)aM��q�-~���qk��+=�
���0��l�}����BE#%�iz�;�x���(���2"�PRgXM!:���1$4L��y$J"�a������gIcG�d���1%T������Am��i*��"�c��q��n�D�����9-"�0l���$D	�/���G������\�T;��.�i��@#X��4
v��Wc�$�*~4�������3A������m�z��k�#\���i��oZ{��v�\���.s�v��������f�wk;c���b�h��_���J����"��D�����&��
���S�&.�����-rI	F(�p�d��o��������c��_��n�tf�+�`���]N<�b01��u���Y��:���xMA�+�����Y[�Iw������=�P�'�7:H��|g��*UU�ENrG�?�8��7�������O12��t�x�"�����`������R}}*g}�y��)�c�$�I�w�6mR�I0S�����������c�;�Y����Q��l���"����(i�MT��F�M�aj��*�	��8	&����[�H��LR��Ky�l�E��&a|l�;�pYh� ��[q:EvVMr����p}�(o��(I�I#��p"Z&���=�*�����a�d\EUt�y?t=����(���\
3	���13,����t�4J����
:")���,��1���$�I4)�P#���%<�7U�S�3zp�A)����K�n��=�7�$}������q�u�:K��:���*�+���8#�Q�4��������^X��d4H�������B3������kf��,��v���X���\
T\��?^��K-�V�.��vQe��
(K0�������~���V3������51�T��)slY
� ���)/u\��"1<��I�� ����@�A�Q�Q�(aBn�l � �U����\ZbU����V��><��!(`��Hg�V������LQ����D���2��Pq�i&�H��!��03���g:�#79H2��"�������+������v��1�����y�<)�L����.nL�g�H� �D�!
:.��2UE��3�U��KGD��,E��
A����4��K��#�2�$�3�GFr��������4
$�P�"H�)f6�5IacDhB4U.�-h�1A�0O�9����e�����ULS� @�<���whj�3s��AMa'�8������/%�z-U�B�LY�Y�c'@6ttD��BI��
���,��H�DX3���&80%���-����)��r���#��(��JM]7��)hb�����g89U���������}��0��s � \?EHNP���8}��[nY��^�d���!����������������9v��_V�����e�1L��`�a���{�����R)���L��v��s=�S��C��?��
������;Vd�o�����|_�r,���$a^�e�����^hK1�� �Y	��.R��H~?�����P���O��O/g����Z�����yj~��u��NZy|h�����������@r�9��8U��Y��	���H�����g�j���Z\C�c��p��&6����r�E���<Z~��G��Rx|n��3�	�E�[?H%�f������w���2����\:Ic�f�{�D��a���+9�Hz���L�c!���B��p1/���\��b���������D�D?0C2*E�`�b������.pq���[h�u�$���n�<`�d�Qu�\}'����|�NC"D	n��	�Ndt&���\�R(����<+�W�UJ�s��(��Hh��R��y�VD(�|B�:_�r,_v�r�~�~��r���o���������~�}������/��zn�h��'��3A�
�fm9	�����b�`�������S�w���������������!\�I��R"�!�K����4�����"l���:1A���5�{z�|��������)lz�y��p7#L�^�x���+vi���a��[G0��`0��i�M�m��@��n�f����&33*V}SM3�u���]�m6�r8�����a��H���\�5����e���Z~�c���Ji>r�r������2==I�����}7k��Dp�	6�.���AS�`��cT�SdOrl��y��Y[%;�O`h�	L��4��S$*azKi�_��&��#�����<RFJe?6��a�����v�#����|���PIb�:")$�3M�9����q��c��������S\�����GP��ez���?�Z�����i#^!�<>��<^��e�$���1�L=��W��B�2G�T��"���H�8�|8j*�C!��E����{����rn���^���	�l7_d��s�(���(�8E��hUCC#?]7��z�x�4��~j=����
	]��1�x��"���_"+�#`2@UL��A�"&���I�b��� �RA���L!.+m�,k�g
	��DN�c7��#Z�"1���Y�^BX�Hy�q���J����e��c'��mKc�F:����0	�j�%&�MA�������m��w����g1W� ?�dq\�����8v=����xn�$vdQD1�H�u���<f7����f�m�~g	��H\�o!-�hC2T3��'��:V�s7�M��F��tnPE��
����_���|�wE�7�L�B�&��0��f����6��fz0�=4�;=����W��HtN�����u�I�M����\����Km�
�'��N���#d5�a����]$�b"�c�~�R�F��e��Y����/��C���y3�_��!�F���xO�D��M��d�'�{(�'��0�,&l��>;��x���Q���"���f^�_Od��0��Z���1��Z�'��ISD0Mdtt$LQbN,��^�C�������>�I7*	����*���p�s�\:)��������������� J��Tl�F��� ��G���'�4�e���G����HC�8��4-�2?�T�N&����{�[L[�{ ���L���c�HZ�p�����b:=D��|�-l��D�o�����E.0�m���^��w����#�N0����G]�f1G�]�UT���&��U|��W�^$Q mJ�;*HH^"�������������-�7(zUMc
2�  x����nN�U� �R�u-���v:;#<ZR�Z���b��j�����S�?>V������^>���S?#�,���$�7���b�����e��9������|���4�����Ex��0��8-D����R��QLDC#���)��a�������^��� Z������Al��[q|������c��`�
�2���/���,��G"������/�]!�y)'|9�l)�����%Q47���OQ_o[�xK�����)���U���������l������f%��#�8J����=>GL(�b[����M0~bM51��*�v��"��*}}�E���y3n�q|�={�|p��zz���/E����S�C���2+S��g1p�K��Y�h�r-O�i���L�U�Y�����]��|E(�<����r��*B����i���=�gO0���(�	l�@Q<.�[����"�xp`'oO}��z*Gd�AG&D)1��YW=���+Q_o����9�s�oT�'^�f��Q$t�)�F_&����� �h����	�HR$F�a�D��}��a&�$&��7Dtd4 �;)�L����,�}`�z"��9��(����8��
�X'�c�
�Z7v���i�t�����8LPC�iJ�]64�������k�("�"~�Al�NRw�"�3��/ez�%����7l��rk��m
����Jd��l��g�v���+d����$���K�^+�MP�2-M�c��Y������(�?;�}�JlA�40�q"O<�\\�������f����O����z��RII��1v���foh@t8�'�����<C��?Gt�	:����U���FFT�j���I�0��kb�I�5�����v1i��m����X�"n������%���^���i�q�b�&^���
K��Hg'���� Na��&;��I�<Me;Z�:n�����x���?��P�k��APU$�=&v��"�=�����d�E��	����)���S����*���*az��T������)��vgYO��G(��E�|����t�����
��&��]������/��=�aZ�������F��[��txp�|���G�zi���*����8�L������i�G�P�AC��'?t#�"~���K	�E��t�53Z����e85�>���/E��#F���5I-(6��J�w}����}�#E�s�����)*x������f���R}����5|��ux��)�����:�[�0���mf�|'I��B�Sl@����O#YE������%�:���Fp��U��RD���;�`�k������.���n��O���������`��Lx#���
�8.^���x�
1�j����'�7s�q�
s22v�$1E�C�^TS�0L��F�f���d�
f����8��;hM<Otp���3���a3$%71wc1/m.s���'q1����F6�NS�]@������8I�LR��$����T?��5BMTlj��.���":���{#Fl��(���������Q>�2[T�(Xv,���`jHn/�=��%�f�p���1j1�5,�7=3���0>���W��E�#�DVc��$�3N
�Z����_w�Q�M����/����F�Uq~��G��1@��L-	$	C��3��^��"<R
[2�n$IccN�����M(�n!F�g;�f=N���Q�M���N����B��!$�h��l�v�_H�)H4F� �B���#i�	>&��a��e�y������C)�{���<d�&��U�z��7ov�2^���c�{��E�X��7����.�T�M�=K�� �#]������2+�2��I�T�������,EL��
*���T_Z��{!�X�Ml�yEtt���I2}��a��P��&+���[J��?^G�|?bC3%%2��j��8~��DT'58>Iy��a}
���4�i;�����GA5eKg���tB%�q/��-���&Le�<v[���H�p���D;��4���_���?�s/��f�/}�5��\A�,�Q��v

��S9@5v�(�����q[G�h�T��=z�����u����B�'�V�����s�q6V����hb���g���.�>x0����V������n��b<���#��x&^��&P!�\��g�j��FZ�G)*�9=SBi��=����r�r�j�E{����&�2)����3w������K��3�q�����3;���w����J�A����P�Oha���7����w�@����<����� M��_���	��1�"zJo���9/������x����<�o�Y�d��d����4���|�J&).�	��a���<����L��pb�m|�������Z��r��B����B�,_�����-�������?��]��p�2�VQ�R%�����Gk6����S}6=������h�����LA���Z�o��y����$���Cww����8}H��������=s���YJ��C!��l���KM4�#���6E�0���������(����"��O��/�y����M��O ����K6\�\��{�����(�����pm�&<J�0��3�H�!3J��S�qXh���r����j����g?�{f'��(e� g��f�,��>;��-\���pJ!��d��$t���W���~��\n�l&��!,X�CY�� ��:��0�X�=>E-#:�b�7�B����
:Q<�c�JO��&-MjfY(�&}E�+�X���K�%$��KT��`@?k�e�zp,���
 �	�42V��KJ�|>��y�����41<�l��EL���,�o ��������\z{h�#����k���K1�/V�y��Zp����Z�+a�_��_-�����e�+���4(���^o!#�r�3�9���R$�7�>�^)�)��7��?^�������������(^��m����#�|��R��G�{�V����Q3���l���wq�h���|��sh���#���_��`:�TfXnb��LQ�m�n��1@�H�=����k�/���H8ot�����,�h�;~���Sv����$������
�`0�_�e
��7N,f00�b�F'uu���������'�����	_��b�F�(�o�^�Q?������-F�[��CsD":���7����B��+�T���H=��O�:��t3�D�	x=���z$�$6ct�Nv|���3�Er��(
�##����&I�CB.����(��H{$��q������-���b��Y3��I#����3e��4�"�OZp���G"xv��V_Or_�o�;��38U��DM�� !�)��H)]7��N4l8�N����o���(��a}��l�M<� �������������q 
u���$LUETU���h(�u��� M�7s�[��I���e-�l�y���?��."���5@�Z�#����Sy�������y8����8��*�"�s_�H	s�T<�[Rq2��E�(��#�a.�d:qL��dTS���� �-�=�����a�hD��[�!�]�����q	�yW5���|+�N��q��f�q�2O%>�Z�(JTG�{1���$:u�bu�$ ����0�uTR=���;�&�l&Cj�#���OUr#���vl%�s��V��SY7J������I�lP�#<��H�p�R3����y�B1���k-�E��I�d��oh�
;��VN��w�FS������ww��c=��!F�<N��������#�"*�B=q��K�n��
��B./�V[�\���?�srR�Q���O�/����)�H��,"�"�CA�8(-o�[������0�0����)c#��HRp1\~5�\��J���)����(�;�(�������#�8.lG��&Y&f�����L��?�i:��8k�l�_��)uu�^"��"��g����
����nv�4~9�����0|��i���S���y��)z�%V���C/q��78�h`��w~�Hg'�<@|`�dT l���7ES���i5Rj�P�r	O���c/#r3����U��IRV&�����86EOO���4��i��?��-����0�DY��u����e��{8u�%^<��1��"Dj���7��|D�UL���cC��y�����T~����������SP7���|h�+'�J�4��ms����7/r��i9��g�H�����"�M&����$T�koDZ��"�%�I�~i
�uA��_�4�6*zy�Z,�h����$mOc��������`�:��u��px��]j�B�j�:&����
G0���*�7v�=��0��n��\S���y���[x��g��������3��@�N8�s�p8t(�H�����*<�y>&~M2)�����I�l�����C�"���e����-�~�������^`��_�$�������0��Ns�=���s���|���-�p���3)��� �y������M�[�����I��"F]��P�(������%50�����Q�5yF��o8��O����9�F$�|}=�=�|�}e������Wk���
�	�K���[0���y#��^��i�=����^,R���a����i5]]�+u�/7�n!����R�D����Xn|�6���R8���l��)IH<�|;}}%KJe���0uu6�^�.AU�T�Mc8�4&^9�l��T�x�d=/b��������4W5	G	�����+!>[�1:�j�R1s����'�;�i1��*|B�Y�7���)��ut1�_������4�	��ZV_�����-$5�~np��t[�u��$��X�	�#�������ZY`�<1Y��
��"fr���N � �����$����P��C3S�Ox��n���V
)����a8U���F	�46t$�x�"C����4;
��F�%U7l�2{���"���liW*������x��0��O^v�"f&#�@$��g��:F�b�y|�]��v��.M&
�����.H8�4G����K8H�g>'�y)�#�W9MyN"�@�F1�/dLZ�n��Y���k23����l�3�ka	��ge����,<�r�]�q^��t�l�����_P7{�5������m��Ky�x����R���=��])�����88&\E�9D9�8H�&�1�������_�����������,�����j�J��jB�����kq��+�.��f�g3a��_&y�,�={r����K8t(���f�~�X������&��)e�#|���L�=�2~c��U ����k���6��no������NU���:;�l����S��E>P���6Z���)�}
����A���/|���(��<�`�Hg'�����%���h����r�/��K��!�����#q�4�������T_��A,��,�sUw��L|����I�t5�5;()$)���9�����CA�`>��CXs�H�
�L�PYC/r����l��J��9�C\K��E$	�n1�e�IQ���[�`���WH�9C��N��Y�~�s�f���s��L����fB�o�h_����4�#�0;���������;���<�i����fb�;P�jA���������T[�'P���!w��z�FeJ����$TI$�*���7�����aD����P�Q`S���<��`0W�9;I������NNv�Q_SDl��t�zo
��s�~NL�a
�6��-7��T)�����W��?D����X"�ST$�n���	R����1�������$���(I�K����)��'��NM���9�X������)�[N}�E�J���5��8e����O2�O�Lp�q�Fs���h�/qUc����p8SHkK������.���'\��M%��0�7J����f���ee2{�X����
��������j�����������7Y�8y��]<r�*Z�i����)<���$BO!�}t��$��m����v����/qn|=qF,���s�No{O<T��	M����RT,ak0������%���E_5^�~�L������w���=�-���g������O$�-�6s������o�I]q��&N�I��h����v'%��34�����q�}�a��-F)1$�J��	^lf�
�)�[�!�SbIK=
�k�N�A����v����z��b�m!�u>��R�������<�N���pqWUO����?�]1u#��k2�b`=?�g")j��������� �;{�t�����C��B��bF�q���&n�W���Ki)�"�i�Z{}������tZc�/O>����	������$33V`��i��t�^�t<����<�}e4-)�e���c��Yj���+������2��� }})&��CRqi��MTqz��m����c{�b0�p��������.:O0�`����R�@��j��+�ms��{	�����))���e�"�Uj�~��0��Et5��+�c�:��?�(��l�["��$�����I�>
�4�u���^��iQD�e�$h�~�'����lq��r&p�	��b�x�q�r�z���c��Y�o�d������&�����}��D":��N"}��y��[�b�flojA����%�t{
������������P�m�+8j����n+���mm�������l���f;�uu6�����,��n*������_�J1�V*=��F������h��S8�GD���Z'E�k��ta����{������72���Fu�OO1����
����+��wW�fG�����1������C��{���SMtg���i���>9���������
>��$���^�iV�l��uL�+�@ p���e���E��9���h��P��"v����$�J:D�m���ng%�>Ec��\�({ ���bS��f�p����n~�F��4u���$;\S1J��j���f����/r���������3Bww���w���H,���������\��$�9���x5'�Tj�1*���iv�j&�T�'�����i�Q�D�m���^@�x�gf�n��p�p�����lm%q�4sz=��$����DE>-�b���0����^j�h�W1IgX�9i�T&��$�n�[�G��Xn�2B-#��][J�Xf��,g����s��l�@�_C�H`fX�8���4��b���xz���x�e���e��C��a�Z~x�\=�E���i�3gh�4� b`gHla����|)S�d1�	���DRp�������0���]�$��
�4&6���xR����G(%��S������(���9���������!5(�f*�{��]��������������Y`�b@CC@��0[���*.
JX��+W���`�2�e��R�����������{`������*Vj�R�"K�/���@���T3�j��j�+�85��i4������$�R�������R������Hb'���LF�+3����m�P����~%��	�����$��f^��P���f��8�g_�-u���CrsU8��w��������{�!���g?[�}�M��.����%���'�F�4y�ff2�,K#�2fvd|��>���v��b���U�T�AG��x�~����%�5���������L���5��YX�m�p}��`��J�$ji�D
mn.�x�5����3~�}���po�D$g)�|�=|� �����Hus$������\�z�~i���-���$��j���OSS�,W]�����5����EL�b�Th�9�����,c&��N'Jm-��I���TU:p������y3�C��S��i��C���������v���y��V�����k�E�R~�R�ME�}�G���S!���C��"�*<���������:p 'y�p�.�T��A�?6�"O����"�g;������ ���������8����>��J�>�A�{��n{�����.�F���_b��
������8���D���]�w�M �X:��"PTdMZ����k����<��,F~�'�����nM��4F4���#�\(��D#��Em6�]�z�6�;��Y�|��8-����h2��z�CG+(������&�:j�a�jm|��I�,S���������f��8�jRV&g&���x~��	���?e�&�j�����nN{���m��8����v��O>O8m�6u��B��{�7��j������-==5�z��&��if_���^�������"fj�$~�Dk���b�}��a��}VA��88�/5m�x����%���q����,�`�=�4��;'�y�`��f;"�`l���{����5�����b�W���A����y�A���N�X����;*(���~��/��\�Io��VN%#�*���*-vom+[o�M�){����<���k�x[�������M0CG�@���<|�=IS&�����X|�c�c��B}��#%H��$U�&�4CeW�|��h}����2UU
���?3���*
����R^�0:��p4��E��#1Lq����e�hv!�:_�zC���L��Els��%�eR��H��L��m��u��F4�:6{%����Y���-���v��~	?c������fCS�h�e�2��6�v�Dt�1b1������1>x�
$f���������}L?������������(�j������)l�������S�E��W��(dq.�@��{����X�o��
��qbk���<��j�|6��#-�]OO����"�9v,~����$K���ms���?��8c�������FtJ��yk�V���^������gw�=��P�74-�$_�v�o�eY-~��[�j�b��R}} �*+."V��A�e0�Fzy��?�����������=o���xbcT���%����sU�}����'q�mf��D��F6��2\U��v;�3gpm���������rm�[c���(��P�	�tQ�����D5.h��2C��*�R�(ZS�z-������� �j��!����L���u�V�+��s��i 
&���.��;_����/����M1o�9�N��@��o��3�M�rE�$6�$Q�J�n!� =4���>������~�!t���bg���������������k�a<]�h��'��!����V���'��������s�@�����-Qj����)��2�����h��a�G�D�����S1�X�tZ"):�?�Q����;�5�oC
�����Q\�s���b�(!�4T1NZ�c�sB�f[�0�le7��#�@LQ����OQ����#����4��e�3�Ee*�����;�)q$47�����?�c�(~F��iv� �:,PDDCF�d
X���L�o���#�����zs��� ��)y�,*Wb��3���,HeK��u���	Q�	6r
�EF#��\�`Y�jv�d��g%S#he��DDE�O���+�Q��E�46�$Q���d�<0��^���&9 ��=]v[�i�R��(2�%�\x���
V��`��Hc��,/���;g��Y9�������8~}���)��.f����E�]NFE��{��FI���[��v�$�������H%S�
Ng�y'��[yyQ����L����-��M�*a�O����I5��/k^0�0O*
�|���\�o�����H��0��/`���s~���S�w}I���A.8����P�E���_�nkv��� �6H$&&T�������K��I�Y���/j�j�=e����*/���~��<�3��\
�?�[��Dzz��p�H^/iUE�zQjk���.����.R�������H�������x����N]f0Y��j����@�J�<���j��0�M�k�m��-Z��z$��H :(�ee8��C��E��mog���$~�8hz(D"��^QAm}9��I�~��b!�e��_��k��*f>4DZ������n����)���]]����P^�?������mo�\x�I��d[s3`Ir����>�0�M�d�Hgg�O��7�{b����E�L���S�;;sZ�Yf��J!��8�G��]�<�v[9�?�I�U����vVr��S6��������$��1�QY&=2��(�8��f�w�p���@�N��x��	:��bon��ua�����\Z��m���?��OF9y2@XY���E�m�Q��Jt[��z���-�z�2������l������;���
z>3D�K�(6��b����\���)4�x�/�������_]��$��$���a�3�A�F�<��,���L���R�#�Cm�qZ �����OP����n���w����������&���Nje�:��)L�^_OjhGk+��������^`�P�������(�n��f��`��S����{�yo�]e4�/�{@���0��O�}�_�f#���\`R��&>�y)�{��1�T��p������\�~��K12�27gi��_�����z/�D]���P��G0���	pF����Wj�n��� ��C(UU��!�������������*w�B����������w����3x2��T�u,�mm�83@J��K��k
K~�E�����RY��;�^�d$���y}^�36W���t�������_�]x�����3gY���#�����3��k\��� �����g����I�����a ����r�d��7����|y�����r�^��$��T? 57���S���������w&����6�������G�T�xZg�v'�~�����)����id����N���6�F��=$�A�s������S*+�#��L����Gc���m��I�����mT6�\S7��'����8M(I1���x�i�/Z�d3��~�����2_��DQ�_�������!�Y��a��b0�!�M>�&����c����1�Dw��bj�C��Y��V���������~{ @����!��i�����q���5�e3s�>~1��I*�������?#�����$1�#�������z+�:4�f�3J����~�y	��D�&a�������t��RnLr,��7Ie�����	�����p/��8*2ND��!F�9����7�x���xR y�%�Dp�uj����$�0��8�(�Y�g7���@�-I$�&B���
��MU��6���p3]a+s�V�M71<c'���[x�
��A����q�?%��Q[)����T���4��}U�E����nC����Hd�����
@X����
mX��"�22:.(��@w��kh5��E�$������� ��1��2s7QB�"2�e��9������2����R����Rf���e"�VpB!�7��2�=y�f]��;�r@p���f �O�0E��^���x1��Uq�$AJ(2g�������M�Z�&��(b/��l�.bR�<1��2�{��R(,�b7���2/�Vue��2H�BG�N?s�=�����!e���������Ex���'	��[(M�`j)R8R��k�F��H������#����N29Tdlh��������SH83}�!��zlh4������s�L�������Fi�����,���O�/�3M
-�q��c�������^i�.g+���0D���y��`B3�����l���������L�8NB���PB�����)�K��h�����s���I�	hg���/�:���������q���K��������{�������4��A��;�����q�����rHS��kM����7���n6&�����}~��;/�]o{C��`��{�%��	���&�X���YiQ��@]��^��:;�==�Zm��~� Rq1�����/b�;�A�����/|udCU�<�mm�@��u���	������_��W���oy\E����z�"����N�C�T��D�z������E���z8L���E��|M�����f����~���K��d�JC��U�@���fB�L��c�V�q�=��a��Hn7z4Jd"��y��[`��w��f1�������{������J����_m���`�>��;V�.5����n�4]_8�@"	P�Uk�e�yfj!����+��>�$C��$��$���[����r���$�����& �E��6<��+V
�tHT����u�w�8�z<�&��������~*���?t������X4^������
�	W]���\���UU
P�`���f;��8�e(����}�Y|��|�6�]����#�?D*`��
|2#U����=������LOk�rKI����	�X�� ��'v�(���\[|
������<�s�f�����R��L������<k�c5`t��`���r���\Pc���J����l�-v�2���[w���}�%��R��>W��s��|�V��eY�Y�����������o���3W(gsL���6�Z�����|��,t���v��gx�3���"��E�
������q�`;@���^�^A�j-7�����������Y���6_",��e��4aN��H��q>QM�b
��/�y��)��SD�:��FA�>�@?�PK����@��%���k�����f���.r�{���cW�M:���j��
�p�Zs�9O=��_����q�KI��Rs�2�(OM#��f�GH�[23!��R��_bW��2'�=���T-��I��l������E�����;�r�rc�f�������}~��2��3�M��)�
��R&3�H�h-U����x���F������2K��c�{�>��Tt3k�SD� a`"��S8�4^w���?dM���2�-������
��Z�m�G}�$���S��PQ�U��NS������������[r��1vr�U�\�w��'}�<����J�f�Zj����ac/�����.��R��8
Z�������y1T���R���	\��D7vR��h�Y�KK���
��;)*�B!�T�$�2���e����$N��������W���"�lLQA��Z��={�A�x��1HvE�k���/�o����u�S�N0�cf�u�tr���6�IO%[#O������B�r�H� ��bf1���Jp\���09O����c[�kq�'�*��L,�i-�!���fs��Ud�DC�I����7q���������>y�0���\KT��&�����7p�������MPq�1��2��;�1:�o���C�N<�{�wdt�QP���k���E������1�9�:����8If[��[��#��b)��'���E^`;`��c����)<hH�3����N'7���T0����d�����e�1R�L�1�F�B�����
�M ���6���-������Mb��d-�jHDq�&�&��t60�������E��lb�31�����`=::)����E�B��3�ZR��E����,?O�zF0�A��`�����I*��^h��t����a'(c
)�q�B����b���>�#�;W�(g��_p��t���qW�,�.�
���qvp;_����:iL���q1F
%���r�����I��A
aQ��}�������og���H_���NQ�L����d����JUZ8����������������:3C�������D&7��I`�^��-z�`��j��$�D�|�4Q�������}�����Q�
	����&��Bv�/����
����,����K�t����3��wt�"��()�����(UU�fgI� �X���j�z9�����[r�n������Z��ion��Dr����������vu]2C���?>VLE�$��rCi�+<������|��R�N�bE�[G���,b�{���tv>t�R���|�����qG�e���x�����p�D_��R�Y����>�����I���Y������6e���d_lZ���;AM����T��NS���Q�AZb�]Rn���R�X�D4��4�o���8�A�������.
-DeA�m�\?���c�����j��[g���8~<Nww"��l`(��Vr-�a������R9�Y�<��B
�i��s9�����3��8/��������nW���F����I^��^�rs��>�h4W���~j�4�+�W|�*�	��?Y�i$���le�����������/%���d�m��+���+��6tl%����[Y���=�v���
���_TSa�g-����=@���q��,������\��X�����������|��*::���$s�M����=;9w��:�/��)�)��8@<0M����#��+q]U�E������������H��jm\�����o����|G~@�:��L���W�����}0��g���3��p+/8�i��]����nW�>5�}���^���O�{���_7�������4t��
���0��q�le�-� 2����QGU�A�U��l��Le{���P��������8N\�uT�uO������i'��N�b�KD����������^ff����0i��.XF��������G����a��jRUk�zG���� |��
���>�`��!���c�[����(��8a���y�����f���Xk���\�x�N�n�x~�m��	6S�$EE�����+���V0��dl��<�^���T%z��'2�"Ix2���� ����V���uT�K��a����#�TU)�W�����vd���
$��I�0irLQ���$1�����ko�@���&0G1��A��l��[b|��
s'�G� �
	�4
2#�����x'��Nj�aJ�In�Q��u�'���x�����������,�8I"��#�5��)#�`��~��^�^�@&��Yt$$t"�
��o�Y���^WW+/��&��r3?�7?�!�`
/��H4�d���hY#������U�aZ9M=�x��dQ�DHc�A�1���Poa/�R�(!���T��#Hh$��"��%2	�c�J�D(cY�Pu&j��/��i6�I�x�'
��8M+e����Z�Q�4ST�!��H&3�N������bs��ux{�%5�1"�"��Z��S��3�h$)e��y�/�gc�w����0��8��I�@q���zy8r��a\���^�r#��z��%DI����'�x��e|��&#�1H�c��2c�G�s���I��rXm@ay��|��D��0�c/�r�����=<�&N�$F/?�=����A���f�����g��|�*F��f���F�D�Hk�����A��.��A�?s8�3C��c���p���v�M/������8�v����0YC/��P�$�L�&��p�D����33A���(e
����~e�)%8qxl	����]K��wRq��D:;Q��9{6�s���nX�$�{��4^BR+���EY���@VP5�������qwuT-�����O}��B���WkYdh(���J[^��Wk�={��Z5���=�~�MZ�����Wc��i��, ������d1��z|�C���X���������������K��_�>Z
H�����?_(��r�u�;����+1N��2�`+;�,�,h�g��4�=c��6�o���W���Z�(<\��s��"�M�!vs�&�;�Xp.+Aa#���?��X�-<?�<t
ob����y��l��:1�:J)|n7z8���p9�-�{�]��K!���
����D"�+%��(�Lt���3>n�3�����k5��$R��j�s����)+1P����541��w�0B������/u�K=/���,���>�ka����j��`�������c�R��U�iap~U�A���-�B3���?N�����^�H���n�Hnf�g�R��B�}5��J����xe$��Zx��_�C�[��l
_��(�	UU����ZFpns]D|����D
�����MQ*L�_�W�����l��}6#���h~�v��7�������t�������{���0�w=&1F,�����'A���������������~����������/�OC���,��=���l��2G�Fy��k�����G�8y�d�f+��x���K�i�����!��T::�r@�U,����c|\������������VR�(��9��;��>����5m�e64��:y���\Ky�o>�x`���1����?��Q?����Uw���������R��}�����[�A�:��F��6r�@$��m�u���c��HDG~�k{�z!"����k��	vD;�����O0H�b%m���MxxV�M���B��qt���5+��	N���m�QL(-U�W&@�!'�^"�IS�0���S�(����\gf:]I����^�=g7�@.b��gL��NA2E|fUt�6��QS/d�����aI���TdA���J��7�.�J����:l���]gQ�N�)FER)�s�o�X*�I���#���uW�����/$���:�V����L�� �9PH��[�����vJ�R�
3!���?��g�7��$1C&,��
~"�����Q��cs����Hi��t9��~�r��J��r���F�z��&0lNN�[6����	?K��n:	r�ELH5����?������3�^�'����� �8N��Pn�$Q�*�c���:�w���D�8�9�1A���(�
<-��j�(N���)����;��w���T��huT������*F2Z��$!�]����%���	*�0��k������R���
��Qp'�����I���[����c{)V�r�2����N`b���f0�
�b;/V� M����%�B'-�a��fN*�����������c��3��L��j�L/q��`�_b�ff�������r�?f�u�u(����<�vF����7�nm��\����0:�����P�M�9��Z��8��R-�.Y�GJa�I��$�Gs���H��S��R��3C)��������I��h�B��F��*J]
_��"�`�'��{�.�$����JJ���&�03D&���$�(��U�+���f
u�W�;:����=�s�����]l����	b1��'�K<�������Y���O���'�~}�-�,|b)����m%V��T3J,��r����}�-���>�z8L�����H~?�w�}YZS�c�P|q5v9���H<Y
�{��Q���.G�9����T�&�.�����u��+eh/g������:V��J�_�F":�e2%g�=",�����x��������)FFTT�D�����u_^o)�����	��2-+�����!����n�X=�_xm+=/���P=~����,��&[����v����uT,�
�P���]��[nQ�x�_�)_�e�6K<k�d�����=zxGk+E�����R+����^���Bk��S�==8�=�n���J��|5��W%t���R�i9��fm��n~'��]�D������}�)X�P����$l��(:X�d������tw����m�������>Kp�f�w>������_��������5��+��S45y�������������=��K�����Q4'�����o7��g||��z������4�v�or�w��������F�������t�YKQ�E��#c�����u�z�����/1w��@��E1n���g���|���v� ����E�VQ2��t	wS��
�H
��O��)�������?���w�{2B�p��I
��T�@D����1�C�1
�(nL$������{}��;y��$64���O�R����=����(����<��$63�.���
��)���:�(i��H��W��������/R/'�OwcK'�U��B�o�Cd�[�}�����������3������J>0��l�����w������m�������2!4<O�������� 	��5�&l�������kc"��QY����� s����p
n���"������	��Fb�J4����Nc�����[����qc{;���|�$���*`7T�@0u0t�����[o%t�m�S�L�:�In�E����O�igC�QV�����*����������@l�H�O���W��������hn=�'g}���h�����������R8��^��Wn��sgE��<H��IN1��H���(�$Rz��87of�GO�7��=m�������T__��_z���e$e��46]�������j
f�)��Y=@�q��sc�%f$�(��#b3[NP�i6Q/�Rm�"��z������&�����X`]���s#9�~b]���Ioo�>���$����o�����{�'DG��CN��:j�aF}���'���j�c�� �aX��s�R|�3����n�v�Y��8�]�1��v��RT2A��S���Q�`�������������	0M$�:�H��=���@�X��:|]]��N��2��D7�����V�! P�����rQ���$q�Rx���������-����Gtl^/���R[K��d��,��)����%�h��������9w.��������6�a��|g�5[;��~�"�=k�zG���������X��Z	h)��d������:���-�P�n�U����}�����_�/\�U�6�6�x�r�����)B~����r��W�_Yy�l��l��_�
C%8m���W�������@�Ngg��q5�:������q�g��]U�/j����Rd������ !X�lg�O�o�d rff��$$�|�'3Nr�f�3CV��,  /o������RK-�z���?J��ly��m���\������z��������l��3���|/�q�/���X��1���;��c��8V�.�{�����)��N�����������Y�W��D�l��=�+
���&�{7�60��o�]��S���l"�t�)��._r	��.�[�wu��0����O�FW��}��jp�p���&����a_ �|GU`�1N|s�Y5�	������&7����Z��x��������Js6�"�������6��[�����f��M9+�SI�����#\A������#'�����]�o�%S����V_����LL!�I�V7������O������z*��u���ZH[.E_�n�$��tl3��z#���0����-���C"��eK�M`��b%���
����
V�R)q_-��B���x�r}����|��5����;����������
5"��MIe!��"d��P,��&�+�����J�>�w?�s�������bK�>�{�4sX�v`��HN;��2���r��f���$!Z��WJ#X%F�r��!|��_�U���o�=�����(z�����:��ul���x�I����|d�R F��n��������T�S�����l�@�g�nh?t�X��^`��B�74PM���G[�u|tM(�A�MMS��7Bm�7z��������Uu��G��Kp�C��d�_�x�A��T9'2ss����S��7�H��8��J]����������?�]���������g��k�<���e�~�J����(>��%��B����tUE�xHl�L6�k���q$� �|�4�]���A����@R�CWtt��d����UMP�=��d%7�k� M*p{d�����1���*PcFN�@�y�~
���'����A��6��hc#mmQ�������u�JN{I�����C�Q�`��U8�������c5�����U�m���oc\��#	���Ya���VVZq�%4ME���v���!z{�r�C���_3UY�z��D��-^��
S#`�]FzW'�� ��J�g>�k�gS���{�|"��+;4�.q.m.B�M��
�\�0_��X����������XF�n��)`��E��jk���"�B���o�����{'��T�iY�P(K:
���b�|���S3���R�*��\���~p*Y80����J�"�	#�?��s&��O���x:7�c�X�e������BIw62��x��o��x��-�6��RHrr;�Q���,��<�s�l����X�K ���'y��f��s���)�zN����������O�k����������;w��:��Z�������_YU=%��Bd��������h���\v��Qg�<7���Z"��(���������Nz�L7�0V,L��s����;�Yk�G��l���H��a���!`V~���X=�.Jy��YT55�����J+�����O���=����BE
���<�kkm��
��Q���{/��UW�V�V�g�a9@US��Y�Q
I2�+.�v����d��#a�(2��l��H��aJ�)�
�`��"���1��J��K��tJ��^n��4�����a��=�5C��������P��X����N*���g��L�C�e%�~����$!�2P�����op����'�T�G;�����g��UY�c|������)zU���U���=2=}x��F���ik����u�#I/N-�*����N��l�.a_b�e�*�y
SQDT��������:��g��P2�*bzh��CT���~W$�n���r8<����e1����Fz��
IB
�����
Q�Q$�5���&��N��1��U�� bw7�7|����t��� a�l��Z��?�G���������,��a����tu��I��{���b�~;utm����x������N'Hr�XKJ@Pc1���G%N^�imEK$�TU�g�v;���l���FA��'�M�:�gI��!��K8�%���V}�l����Hwz�d���/�})���fv�B���x���FBe>{X|w��j/S %���E8������x������"���#Aee
{6���0�5�F�����=AY"����2k0E�����!"���	��rE>c��d�Jtt��z�n�}}��~I"�q#��Kl�F����r��w.����K
��e�U.�RT���j���t�^j�����jO'�����������~�T���t����M�G��P��@��HB�*+���WQv�N�a�83e13��=����b��g�Y~��	Sp?K���r:"��*��4���s�9��N��3}Jwv2k�����c�X�{)8�=]F���G���t�t��3M���16l��iS�M��Ge�����N_Mw���5<��i=�M��b�u���Z{������<�O$����������g�A�l���=Db1�0%��ba&�Q�z��l���Xv6WG97�:Dj�NA���97���)'�Ln�t���=i�}��"���em�����[���y���.�����-����������%���D7l �i���{�"'n�H"�>�G������w����a�>�V�U@Qt*�>2�������������W�L��5��7��%��i��jD7���}������r���S����z����Xq%�V\K��tuex;[qq���9�^������W�j�V;>�
��G^gxX�E7I�d!#�I �:Rw'��Q@VG@��u���TYDO����Vs�7�L�;R�#�0>Q��Af�K�H��7g���2��/1�����(�)������3��P���Xc�&��$���C*����9����XKK���h�$�"���Ff`�j������_Ob�f��!��Q�d����T>�P~[����vwc=��R7���_]��DB������+�s���+�0����'�C����-�_�Ng��G�O|_����

������CK$ �%s� ��J�~?��Nb����_��H�=t������UW����mu������, b����n�!����2�C����jvR���Z�D�I�����2�l�����D_z	y,F�5!�V�� &m,}��l)� ��V|�w�:_�V}#�9D=58��HGI��Z"A�����
��^MKK��:�G'�>��l��c�w��S�83�"�Nc��Dp������o�
}H^/��V�hl���h�f�RX��!���T����X��������r��Y���U���4����N�?�<8��LR��O���X�����#V!MOc�����bk�jU�D!���S[�`dD��#qV�������,T�Q�6�W$�d�������g
�g�S���v6���{e�p�Y�����C�x�5r}z���T3Z�k�s)����[g;8x����8���q�����L����x?r����~n�c���0������H����nj"��LQ�!����3���=kg���T�n.�����k'�����?�,�� >����������Q����G\q�H}�y���^��v46�	���06�!�b|�
�,��NN:����O��������^6l�
��R����y[��g���q��\�y�������4P�����Y|>�{�-����f������
��(	V1Kq���Fz������C��:F7���N�k/���M_f���k���3�?j�����n��E�����������?`�Z�b6=�HbA�"g�U���XP�^�%�k��H��GG�U4 ���A�YF ���#A4�2����'j�yq�i�F:c���r��M�����7�Q�V@���;�N��_A����I���VT�0s(J�!�"����}�c�]@M$��Y�����9�$� �F��O7@&Cj�v,���YC�����b����	D����o0��
�,��;I
pq�	�c&`�����YF~�S����������)N�FvR���KD��s"�������.�:5�?>e�V7Z,�.���Z�@��c���X���&Td��$ ���
qy�l����K�$�bP$t��C���A@����:@!n$Y&L96��Z��/H��mk#;���
x��B�*i����:������B��$ >i��B/��.�Xy|��������U[��n2�i��q��q{Y�;�\�!��@�$TYF@�UR��&h�J�XS������#�3��6����!�Y@G��rOCk�2{���>�N�6���X{;�-[�����qBy�Ej|�U!mmQ����Y��1���vQ]m;���t�Zr�X�yf��c�PS�����t8�Y����=�OW�8��<Sp?���w6�*M����z ��������������0Sb�t�����^���
�z�;��:��0�}�~Y�t>r6��|xn�c�����7Q,5'&�	6�:/y/���?3\������D��GGWu�����7������g�������{���X�-Mnc��G������5�:r�v��X���w_�����*��^���
>�|��T��������?QZf�a�io�z��@��c���R��*��R����^�H,�r��ey���@�F%
�=\�����D0Z�v�_s9!�
VRR�_�l��>���d����O}�����>\�^�uz�����M����� �8�rJ�(EABCD]GM$��cH.g7Q� ��jq�E�4�i@�5����>��Y��v����F}����q#�Y2v�T��sj�9Z���g~��@d!z���!����Kd5	+*)��ns�,�b��6&�(^v�������!Y:.���h��d����l������d@5��/���J����"���"H��@b�'��E�g��r��u����Yi��I�m[���k�;���3��gq���4-%���������3e\W�v�������Cr����i�{w��9B�(�=��"����AT]ADG��C@����x�����3�T�6�dt���a1������ ��������Hr��fX*���a�B��_fv�����Js}�4t428�i��a�=�|AV,V�������h
6TtEA�����t��������W� �����8�(��������'�$2�����\\�!�|j��� �Cv�I�dd���������iPlHA!!�AE�����U��<>s��1�yu�������,��2hz&Cf�>�{lZ��#�J���(����z��n%���V�����#AS���d��������M��|�t��L��,p:����495�%��_ g�E�l	�R��L�u��3�i�#��������_g2.��2y���|&&&����m��8�������}x�e�98[�UGc#�w���H0���\2���=j�a=������L�����?��/�����a��4;w���7��ss�S]�����_Z�r7Y=���l��d��x1��iW������q�!�����G)��n���~�C57������e�
K�����f�?�I0���#���WV�Y�C<^	��v���^ye���U��� �o����FU^|1��#oS��GBwQ��s��2��b��J<�����V������B��Q�c�q����j!�v!�::"�&�k2���T�����$���/(_r%���)�h���0+F~�������6���0�
yB�H�)�L�NG���J*�$��o��R
�lW���!���,q�����^���/u#g!�i [T��pB����b����A
S�E�HfD����:��y���a2��=��GU�j��}��"� i��B������ky9��!�Y4���uH>��Y���s�%�A��5������
v
�QU���#��75Ki\�b�X��St��)V���a�tD��Hh�������(��E������
���h����G����G�FI���`Hfx�A��C���5 �L:fA�Q"���Y�"�V�q8H���22�24d���1�$�!#P��X���WY��:D��N�'�sQ������
kE���QdM��u���h�u���GF�u	M�WT����`��0����`���pi��Is3�(����,�	�C!���D.����v�+=�s���v��%y��Hk+�?�9��3v`�9�,v������A��=/�N'�GZ[���T�5�c�E��|�)�O��>�=����e����0�[��h���I�jjr��s#����@�����{��?y�����u�t:�y��~��r�d�^�L'��� g��w6��%�s&����9����������t��t����W&�=R�������^���/���X��#����w��L�d9�Uos3�M�p��!%X�����q���g�*�T�6���]��0�=������Fdb1��/w����_�{%W^��`_t�!�lTK=9	������*����5���6���8���#����#��^���J4�f��/���I,1��G�E5}8kl���|}��}���J�G:�<PC"��i��Z����(
�%����t����:?��a,[KUW���j�.d��J.6V�E���'Gj�3��4��culd�5E��&r��8��DBe��^�*8���DPT��D(0�O��g>��:��A�b�Y]�h�0{�i�R����P`�QU%-hXU�)^������g��`�l,���U�b��������,���o�����};�Eoq1���t��$�z��@M�(�T�T�X��H����J)��(h�����"�p���������r%{~�����=��bY1�xp)���@��'�� �W�.���C)�#�\������ 
�?~��|�]N��~��6��T��9x!|���*r,��>��k����c�v�-4��l���JV(�h�%d{{	?���q�Z���A��m+��L
+9����Z��_GG`���B�l�~*��x%�B�o(#����~��1c��nX��*z2�h����H�n��M�����H�G���q2,�lb�e����jk�~�S��.������l�&�t�G:�Uy�M~�~?���qc��w��=CA:D��Vj�'�]�����26Fr�6��FID�ca@ u�],Yq	}T�������y�����$�oG�
kZa�B�)��qT,���]G%�a������h�4�����5C�z�s7�|')J�<Xdy�B�'�L�=o�����������5��-��y�	���O~�� :�y��#1������>�tv�y�� �������en���dF������������Yb���U��r����9�7�E?[��Xw�{�t;f�9��~������L����1�q���t�����D����g���:x����� �����yj�$��T���?���(�v%p�E��5FGB!���,���SN������=<Ku�
w�Hb��Pkx���x#FI�Y������vR�`���<2]]�T_������6Dq�%�q
A�������&��Tx������(�����|�k���im��d9#���-���K$Q���YT���$��gtTe�s6����bc����:t]a�U��2��iIQ,D(td�$wf�dJCA�A���R;R�S;���DJ����U�Xgz����N�GREWs�������+���}�7Q�LP`��]E��B�%��������M�nE�F�&�Dhrl��2�+yE!���� :�Ct]�	}�;��lX������]K�*�P�N��)��)(�H�u���P<%���qw��bD7l��+�K�R�b�VL�l)��F*+;I�w��.tK	C5W3<�p����#�0D���!bMhd~�����`q���&��e�gVtIA�[��*�\N��?@i�+X��]H&TR�H�u�E8"��`ex�:2���s�VV���"�tqP����hHL��2X�I�eT*a�����6���/��9_���R��_$�oRq1j:
�j<A@*+C�dp.^��H�D�d4�����b{��}�����r}x=�M��..���L������T�X���>�����3�����J�kl	+t����n��c�� >���u "#��B��������m��C�(������}y?��>/����}�#?��$m�4D	�J+�Rl�Ji�mCAK��M\���|�lO���oV+��8�l$�;G�HY�Z���!�bk9�VS3�yu��m���z�ID���M��	|n�����W�77���~)^�*_@�x+����~.�������5���B*����e��8O=5�=��9��{�)����Y��f�$���:S��X���>r��ZS�411111��8�������x��G.�<U��4z�����\����|�>:�U~��k���#����3�~&�/9F"�`���[p�%6m��iS|����$H��l�L)n��\B���}����x��8��F*���	�d���'���FjV�>J�:r���U��b*��QQa%����'EM��=:y�&�g�~�9���f�k������a?TL��X��|�Yz?����� �:�����8��1L�qD"F1��T�S�/��|�%�-�������xv���bdE��Q�%���Y��������_��V>HQ>$�D(|)]�{�^�F*�N=H�%A�eky)��Fjh����X�$���n���>@���ObxM��
��������,����fxX%� �@EEt��atQD����bY�ZZL���b��WQF��~"R!Z���o$����W]Ac���SO��	[M
�{{������T&�S&E���E�m��g���Qc1�������.�b��E��M�8I:�
X��������d�Y��(��{�.2z�*q������w����2P��^�B�e�;g�Ji���R_CO�@�<�o�J�MMD�����>�O�������nCe��C�.����X�����)�L%+���p�T������TP�`��F"���"���!��������T�����������V�r��O����l%�a����_�e������-|5%dB����a��8��������J�fo��lV�o����0��A4�sB!���L��^���0���P���H����}����C����f�c���)n�kgq��sy�	TetQ��v�w�����ct���TxE����B��4����bE�P+;xmk�J������
!�j�
,�N+�V(/�f���r�4�k������#�:���,kS���Sp�0�*���	�����g\��ST?;�����8�y����''I����;���b'���d�FU��2��*k��N�9{�>�=�s�.'��tg'�������\IA(��&hl9���'����x��9<��

�����';�kltP�j���,}T����ZH&UR)�Uc��$�V��j���s����d���|���������������cUM
G�=|����tv�y�@g���5�u,[������E.6m��}���4���cC��M���g��e1��J�v�?��0���1,��:+?��/�1�2�E�;��D�m}E�P�GRN��T�e�n��	z��`����|����	�d\��x����cU��p�����������
A���Db�����ETU�����%�F���������%��T-�%�q��%��.b�k���o��������Cil6���&�������D���q$]���v����!�B�R6���BF��E��vU��s�����LRf=�_�U���kJI�#G��pd��,��
��3~`�� vY�j�mf������CC�����ov�NMd��"z6���&~�t�{Or<�U����v?�~�f�Zfp�����)����K�H�A�l&��*
��j������a3c����n�e���`�e
�Yn��	�2� `����_�GO+hX��$����)]f� ��[��e���Z����N-=�Hh���dt;VW�t�bE�6^b{Y���45����3����"��E������\�-�tT�RT��E�
7�ki!���d{z��Icc���EKQI?
���1�b)rqU^lOwvko'�cj4z��|�?@�u�	K��F��A�}���[�c��E8��;���3r$��^���12b���:������)����"�pi23�lv�)h��_�s��`bbbbbr����{�$��U��Y���im�����o'��>�^�t\��T�(���������,�X����#�|�<��_��E�c����c����m�xu���GX2���$����`�@a�!cZZ|�=�9V��o�������v>��e�QB��2�~v�g���XQ��$���47{�V=�����N$������W��p�����H�ilt�����3�;����T��,��mL$4����7Uc&$T�?9E���5��:�S����� o���Q��W��./�=�@5��2��k|k������I�B�m��|lU-7b}���N���R�BD��5K�[���c#��p���%Er�����'�MD�VZ	
"��d�H+�v�����k|>
W�$����s�$�����cXb���)�.7�T*/n������B
"�2�bmM=#�"�����k��7�K�w)�s/K�P��P����/l�L���)tD$5��fq��P�uq�c)g�4���:��Ft��	7�e�e\������� �#"ccL/�p��9s�D���|�pzp�G�o��:6����i��Q�|�PMQ����i��L�XAU-�:��bWa��B���"�O���a�����d��,��=���{Q�IPT���r�iQl��^���TT�E�j��huG�K������(���EQ�u[:JE���Z���OpmC�h� -� �'�u��N�����������q�d��E��tY�����b{���In�����2���A����C"al��B��*�����R���c��D��VV�h����(	������N�.��j�����F�t�Q������p�X0w�S�d�6_����H8�W#�W������c�������L��z��5kBx�>�tL��t�(����C!��Q�-�@p�������%��q\��T��|�gF��M�4�W��v� ��'���e�0���=^($O9�3�+��v�	�����E�-s����SVA�xk0���K�Ya��-v&�W��Nu��c�kW�y�y��������X�lAv��dn��d;c�z�C�����rS�\'�����n��I���a��.��YJY�2��{��[7Li���':���$�q;o�W�D��O/`W`��vb���;���<��g�r�T��a+���J`�
d��@�(t���ewh��^j�0"6��+�3�����y�2{�N�|�
m����q;��,V8�������n���`�4w=����x�9�����g��5=J���ZHw��F��C.��U�`�����O�r�j�B\�����S���S�{t]'�A) JV�����n��������[n��%�A�jR4�����Hp���AJ12���m6#�=�DW�Ib������"��&��\V}���H�4��+�(aDD������q�$��o~�G�[��f����1N��K��Nk�����(�����u�j�n�	[���p[�.
�A\d���>j�����;��?���	@PD+�hE���6Gk�D�2����n6���B�H.�������Tc�c�L�lw�Q��$��*}(X)��T0���
����%�i�������I����~;���MM�}�=��iZ[#<��06<��0���)�9;]�����/�
�W^��������)r2K�/VA�B$�����|011111��8�b�3A.��Db���QN��m��Dr��t,2��������$������n2�ifn�@c��� �&��Uz�bF��Gf�O����%I($SYi�q��_�����'�2$�������F�V�fM����RL?^|e�8��P?U�Z[�s-->#C�>��"u��I���Qp�D�Y�L����i�iS���h^����d2##
���l�!P�\R�!�N���Kis?����djfr\�� �;�$�+�2�vSWg'���
,�D��Gq�D**�45���(F;�����~t��E���ca����)Jx<��VQ�j}�=F��?G�4����Gv��������!�����;p���<������e�w�������oo;�9�N>����a7��K)ORI?Rh�/����~���m�`�]�H(�����8�*r8���`wz��g�p%W���;B�D2����D
;�Z~�����)��;�����Y��2�b?Q�G"L��d������VV2�����"����Rp��xu���H(H��X��PQt)��%��}RNZ�R'�1op�H�(�6������R��D1X�BKj����������aTU��:z�:��,�����u^-N�v%����_�������
��������7n�H��}NH&���t
��������V������"$�KE�\�����TU��i��B*�E("�~=��ZR)%�M��B���` �������&g:�;w�z����
8������Zgg����	����.N�F�L���?[A����MLLLN�-m�X�-�`:��s=9211111y/x���76:N(<���t����Z�A�=J?�Y�3-�lO�gme�������556�nM�J���@ s���	��=�O_��s���m[���k��fM�mb�=���G}m������$����YZ��'�5�����tt$���R[k��7��
Q�I
�ME�t	uBx��5���^�~��'MMn|>��s�HI��fY6�I���,��F1���=������4]���}���JQ0�������RYi��F/�����I�?H_��gtu��h��S��D�2w��>�2��6���TVZt^��x=Y����>��3W-��
��$�W|���v�MM�o��u+jV��(�+��r#��wps�9n��E-[|+�W�L7����UW�P�[�0:��X[��U�Y�n5��h��B*��*�����X"��J$8r	�N�����Cv��5�s��[�!�v�^\�v���S��������wY��!������p>����l�A�����k��%��k"���k��>�	_���c>����_B�H�����m��yW[�� ����������?�q�vsP5j4���R�_H�c��^�=5������5@�3�=����?S��34$\E2������a��2���&=�~�(��7{���l�6�Q&�D�*mmc��v{��}�c)[*iigI������H�O�b
R�yX�'�IT55����v#@�?�:��#��PP?��&s� ��sI��&�������?8?�\�e����
< ���[�����OR;��d���.t���fp��)����(����FU^{-��{��Y�q���E�����������L������,p�
�Z a&_HV:'�LL�.�>11111��x/��O��Q�Q|+W��{�s��}~�����FK$f4;pr{�mF��������X{�����vrs���V��
7fY�&DM�a�r�+<�n�K$����2l!V�*�o������E������?0��tA"s@e_����������"�uv���)N}���R�����_���W&�����,��Q����w�n�0N����Ja�Y��(+�����F��!���LO�d�:�dX���:�a���3���
��N__)�x1^��8�B��v�JOx���cI>X���R��\��u�tw������_@��G���q1�<r+�0��YX>��GX����N���z�D��\��u��O�������o�,`�����#A8,3{�6�_������������u\��R1J�A�Z��D/2
l����2����Z��,���xWTbM��R:%7����F����$��Y�i��G�
���(����aX����O���A<���na46��(�#�Q��u\}G7�#��0<����0��6V�*fW"��=~��:P����3�o�n���B�y�H#fS��gU���4be
�=70���!���(�
����������P�)��F��}}Y@GU�\��$	���|��3$��g���x�����|�e	�-��X�6����M��[��[ ��Md|��x_#��Z>�
���(��wYI���ijr�l�6�`p66�!���+Z�w�3����)���a��GYtL\k�KRkk���/��K��L����GX,W]��w���SM���4��N������1��o�&�8��;c;�s�)������%�U��\r!f���B��9�}bbbbbb2=9���%�����8�M����>������3���;k+��~?j4J����e��g��V[{��"���uMU��4�^)/\���ho�������~;�.���EUuB!x���@&?�:��vd_�L��$�(D��������\{>�!�??�>a�.IF���a�;R��
�����$���A8�+�aU5�T�;_���")o���`lLA�Q�
	A0�{�P]�q�$��TU�H	�s��e|�����fX��!������'Uq�E	�C�;�B�E�(\��.�����G��
k*�f-��1�����il�0�Q}���;�bOh'�������b�f�����r.��I�k(Xu�����R�f��_,p8n���������E�������}o���3x�";�������7�VV�������ji`A��|�&����1����z;��S��gSSc%�0��`0;a?T����O��,��Fo��t/�Q��m��qd�H���s����4��Z,6��[wt=�5���"\?��k���x>�p$V���7���	���>���~{���io�A&��m��P�gH$T�)�O~���NK�r`9��i~8H,���J������et���ZY�sK)~Q�~����K���It��X�Gb���|s	.��|W|?�c=�p�m�jv�yu�^�DWW�hT���X	r�����tjk���f��HL�$�W��$�Y�L�G��m^Is*�r��1��O#I0:���;o��r��j"�:2B
�\�3�C;W��������)q1N��f�s.0�������Iwv�U���������VT���������\��s46�[��(,88H��=��w�M��U����u�������O�y���.�~}��n##w�����0�����}7��C*�Qvq�\*������~Q�����*���"%
���w����V�`��a�C$���u�L�Y� ����,���(����f5,���2:� �V�!��:��v�G�nE��J+556����|s:���� �[���1w����(��!���0K2&��~����4~���J+�����p�`�_�2�g?[��)@�����x����d%��
���EG��������=���d���&8�y����F��?���'ME������v�_r�{��7�W���;�9,��#��H�5�Kwr0[�@���k����H�+8@<��v��aO�C����q���R�<B����v�3~ �H�B"������E��4��`�D������z��6VYl���(�+%������v��38���]>��t'7,#�	������C���DJ��S�
�g�t=EE>VTH`�(V��QU�BF��@������Tr�}e����g?;J��4�f�=��Y��7Kw����8�F�����|�;�:��#�Gd��k������i^��7�gs�HD����cG��z������67�	����9��`\t�K���[��b1JZ��������x0+W���
Q��f������G�������s�������drB��og��4cc*���fM(�&���e�`km��Xqd}($32��i��i\G�����*�Tg'�y����/_�\Sp7111119��������c���������d��������&d��[��e|����#�-'�mnf��g�����Y�H���}���m��^}A����c1��a�.���x�<WO9����JA������JJ,S�R'ZI�������(V
UI`�d>
�>x�}��{�q�DB����w�N:>�����b��1�lVC���b*�������c����N,��pHTW[����e���W���������^<�������fY���RRba�<��fC��}��D�
~��u8$o�L{{��Z����Pv���@*���g�"'���sk�w��	�D�QZ����������9O<A�c�e��C$�b ]�~VO�A#{~����D�X��M{{lB����2�-�$�6,sA�7�WSv]
�6,��P
�1�TJ�j��z-\z���3t�u��n��q6�J�W3�?9������%���%��"�;P�
�L���&���{�n�@��o�/����w�QLm�a���j���D,����������B2���5��mIv�H!�:EER~|o/����
�P8���U�x'0�_�������vnA\x%���rJK!���5���7�m[�T*X!�q8D�����^����yg)�c��Ae��U����������D��8>.��(��"�&18(�����ys�e��l��dxX&�6�g�C�_7��%@	�~c5K �������������Q��<�&>������|($�ukM���CTVZ���2`j��������$6D9t(�����-12��v��`��8G^���Y���r��_��!��dt��?#�����������QY�
������\�����y�92��Hn�#��)�������.t���J�lc���������������"\P����1Y�^�ul9fp��v�C `�#tue���|���9���������4,J�nG��.����c���!�VVZ��5r���&47{�v5556���x�5Mg�����,Y��v%a�����}��������v�?�;�x<��*�����*�rI�����Ji
)�����/��i���i��X,:N���y>������O��?�s�`���,���CU����� ���XE'�N��^��Ckk���,������PXhA�Tl6��q%�y���I�im"�YC����b*�=�X�������HRZf�vEF������|��.���t�u�O�pmE#+;Q��H�������y�~;v�H"��i�(:+Vx��i.o1��;���K���&�]>XA{{�o}+@����"��,��4cc�(*L�hWVZ2dC2��F4)���� �� #k:���{��D�_�O>9�
7xhi)�2goo��H�4E#��pX&S��$�Sd|\���jB�_q��u�2�!`��D��B��d��2h���@m����q�^����b^{-F*���+��/�i���a�����r�E47{�������nREC��X���n������K$���$o�����hT#���c<����2N��_�29�(J+S���z5�ZM
�kd�����cy���Z� 6V&hTVZ��u���@���cu�Mg��Bb1��2 ���s��,�����8p@�_k���������:X���S���E�!S���� ����������3Y�\`
�&&&&�1�P
�����J�D�}bbbbrb&���o����f"��#��H��{�
�~��XL#W�x$�^i����U��m�Hr�v�dA���v��B2cc
�Qt�2'MM*+������i���i���W��e�O�V��eD��@t:Ob\*��*�r���J+6���mmc����f����b��X��~����fl��)Ns������C<�AU
K������/���X�����2���fEc�@($�����atT%�P�������(�/9���BQ��(J�2N���%n|��8_�Ua������c�2��5��	���W~����Kx�@�� M,�QP`ET�pf����1=4d�^���)RT��Hh�rK��W6����5B0���ii)���
��B���h��XLE���(�iFn���o����T5w��`�����W���������������o����������+
�l�0���7�������,�h��`P�[%��9�JH�a�ZG�P=�'�B?��mE@-]]n��C<nd��D�MR*e��_�p���\�z*e�wI�0<,�~}�;�(f�7�D�TJg�\;��_�/����������)��i*��$�>�(Y0-�?��h��v������lJ��M��l���GfM�s,_��g?�
FF����s��V@�����v����S�
�����lT����b���Y����&w��=���ys�����zT!�dv�HSSc�b�e.���������+^�D{{�M��������/Kc�1n���������s�������y��"T�^�&&&&&�gf�?������H�C1�f
��{V��N�xuN��@c����`��^�tL!8g�koG��VV�=��G&�D��f4���JQ��LF#�����RR���<�����7/Ybd�.]��v?��f��]Fr�.D�ke�q������z)������z{���ZsuX��*��c�lo����p��)�[GG�@ �����O�����������^<�8��� B�$	��a����f��8����ao�a�	x<��FF�R�
��f�����C��>����
u0���hR���fg�6/h�~u��>��K1>nX���w�]J8����F�z������Z*
tu����RZ[G�F�@������:�|�Y38����Yjkm�\�c��Q�^#sz�R�e@'��OdtTclL���D�
�>)��O�q������\.�a���Rk�kj�x{��tZE����J2�N��?��h����Ji�B2��[Foo6?^Z[#tt$E�V�V����� ��W������:����H����f��Bu�����8���'[�(
��!���*�W�����4��Z��Lu�I2V�����~�d2�wo�'����>#�r�;n�]�b��m��K��()�����su!�Y��j_�Z-->l�l}Y@B�2vR�A��&���0��)�����Y�����R��q
�"G��94
����u�EG.��A&��t_w�H�%I`��!~��(��]]-r������MLLL�S.����61111y�3��&.���~�9��n���hi���o���G&�������z5�D��w)���|��n{����_?���	,�tZ'=qf��6&��}>iZ�=�+�X�KWl�
� �^B3�i�t���#������+���V�b��_�z�`0��\v:E:;Sx<��Y^x!��#;�f3D��!�dR������(��6�oO�r	Y��W����7�����i�i��J��3b���w�����o��7��O�vK�/���;���N^�3��~}�;�S�z��cl������N+8�"��hjr�����=y������;��1DWE��B���)��cGG�"]]"������v�������
Q�q��t7�������Z�)Y����_�CU�~�����U����qR�DU�<.K;T8p��w��)6#���F*�Md����1�CU��Ce�ub5�N*�3[�����=��'���?��	^���^{�4��^���
+s������xD��T,!���C�!���fFG�)��K/���?�#(SP UTu2V+���L��#������W{��7����Nq�h�T&����^����o��U��J���������eX�f���ZY��-�OubAA��UW���I��O�5�'�"�P���8���0���9��n���MO	���V" s8�,]�� ��s�)�������\,B���m��Mgbbbbbr1p.�.��05N�R�l���7����$��(�2���&�������76:���"	��QE1
�on>9��F���.=�L���s"��I�KY����##*6�o����W��V�1�y�����y�N�oltP[k��5�/�
�y�u��Sp����(� �n�D}��W�V�k��^���e�|_�:��~��(V��5D��o/�g��$o��3|��� _{s_�j"H����F�"L��N����	FFb1C�����$>���)>���hd���X�Z�y���n+��1!/X&�:���?O9!�(:k���n�8�w�={�"�WW�1w���-F��8�^�Es	�y����o,��WbF�G��y�=���P=u|�:v�
�Nk87�T��w��E�#WP��2<�L�e����ZW\�"�I�4n�a	���w�P��&��y�Fu/�h_��Z�,+ 

$�n�-[����A:��I�t�nA0��x\��@����4	���N2���/�PP ��:��q�b�`�T��Qw������+�������r�)�����{�-������SO���#��*�Lj��*�.PQa���k�y/����H(�3�������IA ���2V�Hd�!F�"{8������W~Y�H<��Jb�������m���qN���{�)������<���E�]LB����m^g�3��31111119y�W7���)mk#�f
��p������L�aC���l���t���m?0�*$�P�&T�3��on��iS<����C��`nn�2k"��+
�7� ��H���Q������x��@ ����dtv�J�i 7�7�������C�O^F������������1�������U�����������j����`J1�%K\��z��Q��q�LdYG��|F���
)�m�ZU��x��.E�w�M�ys�g������G�X��8o��cG
Y����
��ZU���>�;�MX���2���O$��y+�\��[o%��4,��[��`��8����y|�8��@&���Q����X((0,lr��=�JggI((����N�"����$��
���e�N����n��>�@1R�Y�b��.q�F�OY��x\���Xmp�}e�;;������]J7u�����l=Z�=fl�(8


ZZ|y�����y���X�&�S���fM��#��H|�����h������GLR+�qH�������<l����+�,C<�����xc7�I�t$IE��Z��N�oO����TR)
��d��iv�N��
n6P��)�������v\9��#S}����=�C��n��{NJtO�u^{mE1����TFF\.C$����{����EJJ,\~�����
k������]+���+�M���w�����O��x�v].��R��1�t��j��"#s~��^V&!I��F6{b�>>l����J��g����us�m<���?����������o���M����}���~�9��v���;���(��b&��LLLLLLLN���
8�5����YC���jE#����n7�
�Y��������>��I�r����}���vB����b�hZ��L���g���6D��{��E���|5G�$�lU�	�Ys�}����x��q
Y6�
e�.>�x�*�H�U�bx;���	n�5�Wko'����B��?�9���<��������$�����x5��q�%|��������,�����;I	��n9/�i���ZP`���GR?����C���������~�:t������>��%'|�Q�5V�e���A�mKr��e,.�J���x�4�f
���Oc��{������F�
�}�^��������&��Y�?�����,Z���15�YE��(O�������I&
��:�	�vc	��WM0�e��4%%��
{���g�F?�,��z��Wbx��p���;HB�>g5��V�-s����S�*����?�5�5%���7;QUa��O=�DB#��$�d�>Z�L�a9W���@ Ce���a��z�(��+�-M�zJ����W����;����d�#���ne�����2b�u���MY����q�(����@�a%�vKx�"��V��!����g��b�	$�j_<n��k�7x�oP�(:��m���M�+�*H^��@i���BCy^����n�j���U���j������y�BF�s�z�$��f�Q����Gy�O�.�{�����
����*��vV�����;��_wV�)XQ��b��Z����'�Q_��5k��;�8�"�?^K[[�_�z�����-r���6n���::m�c2�>5`q�P���,��2�����5��-�O=E�0y'J_��������Sp71ys�x��k�~�89�y5�����"�����������,l������"y<���h�4��J�5;� |��!S�����ld�W=�(��&X++����d�+�W�4S�x{�x\��:�V�DD$;0������=�q�������,_��
����h����j��ZAQA��ga-�������	}��h������Nz�.�_�2����,w2��={PGF�v��IY�����hm�:��)"uJ�lU�p�E������w)����+IO6C�V�����&���
nL���_�!���S������JD�idY�f��,�B2mmc,\���;��Mb�&y7������XL�7�A�o���j\�6`]�^���y���y�����7��NSd��|��U/'�X0��~K��w�~{%�a�_�LE���V��D��lVgpP���(+�PU�T��f�s����#�7���z���N����O��%��T����X{;�`�����WVQW7��{�8"s��8t(�Yhi)$����$��vDw���^g�+����YH�(���0�����dSi^l�������a���_Q�o�F��~D��
��ER���m��+u�E�3�yQ~�����N�!�Y"w
�hk���>�(
��
#^�� ��s	�d���u'6���J�E�����Q_TFY�%�]��Okk�W_G�O�Af���Q��jdqO�s��k|�F:��0/���7�t�@:��t
��:##�H����	�y'c��5RA�e���{�A7uG�U��L����7�����5j�v��:�=����;&����'��aC]���)/O��<��,ZZ|�w_�'?����"�5����?~M����L�����)��B��ML��\,����.N�u^���3�\g��������B��a���|>����.�:r8� �H��g-����r\����irEN��/�,���Z�����o��ZQ���"`�'%�o����C�FI���s�"$�������f/?$��&E,IU�cUt��C���*���NCM�)�������D�x��q�~?�QQ�H�WUF^|���!J���N�ZFF"���(,hn.������{��wF��� �F��hN;���P��(�#�(1��Ht�����y����FV����5��/F�D4R)���,}}2��(U	�*5��F������� ���W^td��EMr�yV�����Q�y�y�p�8y����K��&>Y
��R�r���G�3��_����8��*#H��O�{��I]�V�
R�Ndy��G5::�� ����-����c�>�!_��#��It���v���Ke%�����b�,\�D����P5MM�	;c�%v�F
��84��a����C|<�#���i�x���/�E`�cfTU=�x������>m�n��������^�����I6t��C|�����:��rF���]�0882x��{����&�(��'�p���Y|d��Z	��oe��Ifk]�������1�+{X@0�%S�/���&�XO-�|\��M��n�X�=Td@���0�����g�6��"}}
K����X1l�|D�2�s �[�f)��rJ��0������]����!FGu,���r�U������O�=c||���Ki��D����@������w6����op�dWS���G����kI��I�S���*[ndA�b�|�����DT�NL�����oFQ��AC���a��^�2Az�a)[Y��q%���(�N4�0�3_vr ��5B8,���&|R�Q��TRr�u8��Nb�����Z��KL����}���~.1����X������e6��������0-�-G��Nf�~�L�+�{o�=���[�z�b�����r��n�����~,��\�S��c��|
{�^�N��z~���1��=�&�7��[WG��!��1c�������bS����F���o	=�8��H��B��~�m�+t��x��f���up���bo#]�,���	![��D����q97���k�\-Mz����S,��x����d����5�\"�} @<8���n��������P�*-�n���"�$�����i�����X�����;��S��@g2��$AQu)=���s��MI[P�[_�`�X����
QR�Fv:���d��|x�d�l��D�u����hi)���A&@��Q�q�T�lW�w�*�b�K���n(�a���G��X5e�Z�@��_��S�v���2�h�������X������� �hh��g���	R��WNB�~b��GV�^�V���+*��}h�1����4<����o�C��nb�t�D����X3!��.�w��[��$�K�'�v"�d}����-�����$�_��bX��q�K_���XP��k��u�?Sp�R�����L����c�$"B��PE�Y��q��{���%B�����a�����2��Q����H-������:�L
�����3�t�0dXG�c�S�i��.��C����n��ih�Mz���_F�������hjr��s#D�*�  I���4���~����Y3��+��I�sc���� ������'���+���O�8_��G������"����CFq��,7����\��_��vY,�-:��u.�����	��%�P����t@����ML�������o'��W3;����������<�t?��R3�\���8j\������%F�n"q�l����M����3~�c>�����Z;������z5��VF_|��5G�z���K�C���G�ZY����dd�:+Qf���7T���n7>r�E

D���y1���H���F�7����8w	������l/���/bc����t"Nk9�;��g���i��0	<0�4!�:�r���v��77���������s|{�w�Fc*9re<�,�$,EH��X�1e����~��~�N���Y��*H+.D���s�������{�X�rI^������~;��2���v�X�B�����������`����!�9��A�]c��F�j�����m��t��������e�Et�+�]��$�����nj�u��h������i�ij�'>%���4]��BB�~��������@�Y�?�)�[h�m������B�G��vt]g^�m�W����X�	�u�b��,�����	�l������I��l��P��9�!��|���~���L>'�?��o\��C��H'
�$4]�;��.�����'�U��~��=�=H��H�q��#2���:�=�@����?���y�S��	H�������Z�$%����
�i^4ao3�����Vjkm�&
vv�Y�&Dww������G����n�����,���u��j��|��^v����p��U�_&��-�GE!N;��=���^Y@O$H+���8����������	0��MLLLLL.��5�Yx��g&�+fb\MnG�Si������(l���745�q4VQ����ZE��9�[�ke����������nE��������l���J+����^*+���|�������[>E���X[����tw�q-�r��k��o�B��64]�#&q,X@p�M|���T�@\���?���U��;N��ZZ������������!�7@*�"�9�@���j|L���3
�=���v�]������v�BWl���e�w�C��;a����.��eD�(��!w46R~�����������vRS������JX� ����A�-�q<�ed�D�^�#5����P��oPM�Q������7o����^��Y���1�~�[���X��g�F���(Z���Y�n�a�
���d�=��!�z���v
n��L ��]���#��ho��aC�XL��Pd�b�@u�
y�$C��,6J�NN��#�����uVd_f���w�
I�������(�g�V����i����e�
����T�;�F>�����
]�I&uJ+},g�x�N�g������J!:�����)����H��q����r��_K�����9�^���#18(��d�J�i
��.,	�XE�]T���8��NkB�X�n{;�P�&B�
�~[w��G�_�#�wA��[����3���Sp7111111111111y�p.����g�\1S�j��<&g����Ow���~�CF���;������	k���Q�D��x�����^������M[�]l����T���q6?f���������ld�{no���V��x+V��+QMje��!N���FUV�l����`�`���$��J��/1��rp�D[����.����i��\����ID�/�r�ws���6�ee����z��f���XW<t�q��w�
���ne�&P���)kYL.�|j���>|_s��m�u���8�$������XqRE�|����<�k��0v����jV�N�Z��tw7E��N�}��l��Fs�7/��|F�������_c�gE� bE
�y�hX��c�g2�j����exD�4m�d�/H��G��wAE��}��������lzbj1P����Y|x�3z;��of	o0�Nt�8�n�<��cS�-��'�����i��Jgg���"�>���7p�cX�,a[-��F��=����o������3>���I�����{���.
�U����uRA���?��55vzzd2�Z
�����n�q~� ��
����X)��o#�=�������bT]�@B������{�G��+rvu���}�]?2�p~�`�v���^7������������p��/��0�8x/�F���������W�� |gMLN����pN��d������~7YH_�����1������E��g~kk�W������)W������i~�����9��{������p�eN�}���>kk���o��w��qm�|��47{O���z.�O=El�F�
��s>I8,��R��o����FUb1���<���q�+z�mm$::�T.���F�~;�@���1���'��8�?r��1S+�r��]������������];���BC��/y���Ls��]�l�M��2E���p<�W'=V~8�[o%R����%��P��;K(^t	s����d�G�{��Y������,�|����<B��9�p�����iZ[#������Ae��^��+CE���/��r6�a�;	��j���V���|���<�h�Q����qo�9s�����]��U_�\^GG����������_��Eim����a��}���nbbbbbbbbbbbbrr��g���,�nr1s����\L�T��#�;45���Z�h������*��";v$io�M�<�0�����s��GTul61��t�����c��7N��>V��S=e���H�]|��C��v]�_�2�g?[J4����!WY�f��~�����}��GbdeO��`�v����=p���^@`hH!3
~n���'��X���y�����H7u�����i���o���/���+y��wQv�������:��@ ��e.F�.����I�T.����O��o
p��45����@�8?����p�:z�:�1������j��$�=D	�dJK-���������X��{���B���K���������m������D���ok�������y A0�E����m���xH�c��o���������E���B<���K[[�G	�NkY���������D�*��i)cbbbbbbbbbbbbrs������,�nb��p:���|���N�>h��!��d�vY��=�E����,�8�"���i�>|��U|�����##*f�V����XX<���2���& ���!n��*���+�����)-r��I�L�����#�l��63��5��o'�X ����n�lVgxX>n��E��z�e��Q���r�-��~:������x��	�����cD"�����I6oNL�b�������`�}�2�l�H���:?��h�����\u�����m���x<�("F[r�������;���tv��������+������L�v���
#��_E�����O=����g,���J'�0ok�r�}���e��Djk�\y��;�,�6�?w�V�� �h���DBG�@�t��ejjl���1
����X9��YR�!6m���#��Z��)��������������\t��e�^ g�r�
����ML.N��������f��T��%������������������������a��$5566lc���	��S���SZj%�"�:EE�|q�5k������2�n�'�;}������T<����L�et�X
 IFVs"�!���+rtt$�O"QPU=�����K���
��������8Q=tp��A��o����NY��;��;����5���E��h<��;]�g����c�����G8�Y�(:7����2�~;��J4��Ey���7n���������q�LF������������-��)��,��2+W����E��#��#���=ju�t�EQ4l6E��$���Sl?�s+
�Im�/�I��b�;�8�������n��f3d��16m���{2�������p����L�����������������x�i�bbbr$��2�5��i���`����@�h���+}3n������'����{�������t���	
H$�i��#���x�R����>�oZZ
��/�(�FY���~��pX>)��&7�=7B4jX�H�����m�����x�����������X��rMI����&o��+Ci��HD��7��aA ��E&2�
��������ck�"'����5b:X,+Vx��{��J{��t:M4��(FQ�+��`�e����D@�������Z�:;STW�(+3liN\����3��d��D�B��9���c��&�)?6� ���9�
t�Q��F0(�(:�@A�4�;���;Ur��+���h�����<@&���O=��$��f�%���������\��mw���|-J��p?����=G��=�~*L�p�����v�����D��pw�����\�5���r����q������Sa~��!t]�����C>��hT�{�O����7Mi�DS�'oE��
�������N�hi[[���1@`�"�i���D)+��R�\`i�"W~\���r�tv����%��t�Hp�4���~��_�`����n��6����c���������������8���<����������e�����*�s@�T����<>'�2TUU�`���o��'�x��u��sobbbbbbbr�r���'�cp!�9��q�'��������{��������]������������&�<������������8'�'�Z��O��O����4'K,��=�a��r��>����oN�{����|6::JQQ�	��^p���9�b��s�
s��8���c��m�|���3��c�>�I��
�j�9;�����T��c�d�k���c��87\Lc�T~c����c`�?��3s�������s��o���p�
������?�����~������Lm�t~��9���;������O�����5�10s��m�c��0�����n���8�����m����4�j���93�����8N���8?�m��s��4N�7�8�9f���>3�����9��Y�l�`0o����O~��3�����3��������ds2�;�wN������fs\8��c�t�a������s��m��c�x��c`f�}!�������u�����x?�����9��m�c��p1��S��9c�����B�t�$������x���d2477���Oc��G������&�O�1`b�s��c���9���0�[s��c��&�8�����M7�d����x��n��{�9L�1`b�s�?0���ukb�s��c��g�s��nbbbbbbbbbbbbbbbbbbbbbr1sN<�MLLLLLLLLLLLLLLLLLLLLL.vL�����������������������d0w���Mf�d2��w������w�����9&�CCC��_�57�p�{�����^z��~���y�����?~��c���~>���q�=��O��O�usL�#TU�������\ ��xso�\������s����M����������b�L������e�]�%�\�g?�YTU��_���o��'�d��M���^4�d9�1P^^��~�#JJJ�����Nu�v�m<��3<��������E�Mf�S�^z)?��X�n���{/�l2�����w��G?��s�T�	�y��9�7s.ob��M���{�)��L��>�)6o��������?��/��[?�m�Q��q���F�E&���h�t�6k��
����P��J���~Ym���f�����t*n�\��K.(�����\/�&>q��������}v���>�z{{�x�b}��:{������}�vIRcc����%I�C���!��u���3����[Z�dI(G�N������bM�6-��b�h>��c�*)))�=�x\E�]t��a��>}�&M��g����u���+99Y��h�"}��W����8566J�Z[[5q�������`�N��[�x@�<�LHg��N


���_���\%9
�h~��g���k�����g�.\�����=�xHty��A���������*..��8>>�_����UZZ������GUttt���
����.�������Sii�6m��11�e���>��]���c����S�����I�2P[[���w��������o�((���s����x<���
�������.�<�����;���}n�����uk�A8�@LL����C8
�!P�,Y��Oo�2�������N�p�����)//o��0$�x��!��A�]>T�������J�����t:�8B�����>� ����@����!�:u��^�N�<)I���OT\\��Jdddd�����D@@B�wh���r:�������Tii�"##���k���JLL��	�p��p��B@@@�[�[�H�dd �"l(7�q�;A��;A��;A��;A��;A��;A��;�b��]�}=����p��$)!!A^�7h����J���_s��y��1#D�C���`�b�n1�)�W�\�����F������
�Xa/���_�5������E�0Z��#$**J���JOO��)STWW���"=��Cz�����[�r��M����4������K��g��\.��n�\.�;wN�W�VOO��n��x�	I��c�������LM�>]���t���(77W����m����;�����S�r�4s�L���H����TXX�����3G���:x�`�����?���/�����}������V��7O.�K.�K;w�x�����e��)++Kiii��q���9s�h��m��G��O���b�!�>��s33[�z�%&&������Y\\����ff�������+WZuu������YSS���]�t�:;;��,22�����n���6��kff����,33������d���p���kii�?�<y�566���3��iG�13�w�}���y33[�j������������H������{��
�~�z����633�?��]��������AEE��[����^�u��������Yff��8q����^�=����O�F����p3�����UDD�f��-Ir��jnn�=��#IJJJRCC�����j�����|�������+I���SII��{�9��5K�����q��i�8qB3g��okkk��\TT�	&8_ss�G���N���I�4e�I��E����oK�8�;vH�������6�������/���C3f�Pnn�$���~��������|v���?�����M{{�N�>���d�{��jjjp�F����p3Xp�2f�EEE��������+W������J9rD�C�������$I�����=��{�������������f���Dy<�g���;�o��������q��l����x�����;���K���_���B�������o����wk��M�/�9����c����~��|�~�z<=n�p�0joo��q�t��w���K���O���9sFZ�f�


�e|������$]�����C555�����G���)))��������VKK��x[�lQ~~�$)77���������c��^���x��xTXX����u�]Z�p�***t��!I�SO=���*�������k=������ROO�$���^����s���:��
�,z<=��F.�KyyyJJJ���PVV�|>�$i��5:{�����4y�d���H�V�X���L9�N���/���o�j�*���K�|��������q�c���F.������}��gZ�x�����t:�e�IRyy�,X���=��#JMM��w��o������
�1c���w��$UUUi���JMMUdd����4o��A���^{�5���+JOO�$M�8Q_~��$���F�>��PO;pS���xL��Y����_��Y�f���6��M�������EGG���^���:s�LX�������}����{I�=����nS�C����ZZZt�}�
�w���5{�l�����T]]�{.655�������=����� �?M Xp ��3T�xGIEND�B`�
absolute-optimal.pngimage/png; name=absolute-optimal.pngDownload
�PNG


IHDR��� �L9tEXtSoftwareMatplotlib version3.8.3, https://matplotlib.org/��XS	pHYs��7�����IDATx���{��u}��W2�$�I2��)�;��+���Z �����(T�����Q���`i���/�z�
rP��
_A�Ve��.`7ws>f��$������t�=������������6��;ye��y�����,�8(N��P��(�p�n��f9��_��0�p8t��7�e�<��Cr8r8vG�*B�����Gr8:������$7�|�>�������;
�b\v�������3�8�� Kt��7����$��O��~/{����z����B��C��X�������^I����ns��������;�lXRX�{�1�����x�6l�`w{A�I�������o��s��QG���vy�^�b1�w�yz���W<��>�99��%I���N�|��
�Br:����>'i�����K�������|@�HD�G�pX]t������m�_��_h���jjj���U$�����+���m������H����~�]w��x����������n�����w���c.��9]p��,K���������
�
�:���t�-��v�����XN�������v��i������;��������^����e��|��b����+���-��L&��X�x\^�W�hT�]v�r��_����n��V�����������%�����>�q�����%~����$I_��W���^�����`0(IJ�RJ�R���W}�+_�G>�[�]v�e�����p8���*����;������NS>�W P�V�������o�����������c���~����T�T�$��n577+��(����'�Pcc��?��]�}~~^���u�m�I��N�ZZZ4>>����'��O~�s�=W���w�v���8��{�n��������������G�<�o���X���������I��e577�����x


��:R������)�����Y�ZM�TJ7�p�~�������/�����m���P0T�ZU:����_�'�xB���/v{��o�]��.��r?��rihhH?������X�]v����/�W^�_��IR__�>��������fgg599���9m��]�\r�$��K/��O>���~��������'?�I���hrrR�Ba�,]N�z������E����533�B���n�M�@@������+v;����J��N>�d=���������������3�������8�<�>������[���z��_�_�^y�������p8t�UWibbB�����W^)I���[u�UW��1~�����o��W_���)MNNjddD�W%I�������}ma�w���������������+�������K�����\�|^�|^��z��������^W]u���O�T�~����3�(��*���k_���������n��q������\�<��������U(488����r�������{��g��`��%����-I��^����n���d�b������~���$K�u����u�|pa�}����>������7[�ju�c������d�|>�\./�?22�p�������%���`I���/�b���d2����$YW\q�����K-I����-�����������=������d���[sss�l;��,I�g?��}���b�$���n�m����������w�~�UW-�s��GZ�bq�}����Y���������'�]w�^�]����p���z����Gyd����t������<��W^���jv��>77�^xa��@ ���������������~��w�R�����S�������?-���r��;��c���|>}������|�3����I�����o\t�E������?��?Y����^*����}�z���~�?�����T�V��x�?�X�}�v}���k_�Z������a���o��%I�Lf�s~��
�B+�\ox��x__���'''��������U�t�)��3����x�	���t���A�����~��s,���kI��^�����_���M�s�.���1����7l��p8�����������^���^��}�355���###��g?�7���������Z��?��#$�xq������@�t��w��s�]���$�Ay�^9��u����g[��]z���=q��wt.���l������N;M����t��W����Vcc�^������O��^������r�=���,�r�){<{{_FGG%i������|��/�������d2{=~9,���b�T*�����W�����vMOO/�������$���j����qIR�PPgg������MLL��.P�T�[��=��C���U6�������������|


�=�RD�Q��������#��^����V���G�'>�	~��������{���`q�JE��{�����y�f�w�}���Q.�[�������,������������M��o��������!���|�s�X����m�l6{H38�N���������\N��o��+��B�TJ��w�R����x�\N?����r���;>��@;���S�<~�����r���~�d2����{��{<�5��`u�w(�NK�^�����l��x`%#������?�x-/��O�TI/.qr�y��������
����|�����k~~^oz��vy}K����{������]�z��_������{���?�a����|;����j=3|��IWW�^��Y�?�X�(����I���?�b����-[���[nY�XK�q�F�|>I��w����Z��k����<�bG��K��z)v,'s�gP�w��]r�\*�����=��w�w*�Jr��z�����}�����/~q�����IR{{�N:��]���������&;~�GFF422���L&���Z�X�s���'�,�����I������2!�������u��'����������������o_(��{�9�y��z����s?��cz��^�/������Z�&��3�{�1}������I_��W-�1+�����>I�i��v@����u�%�H�����^���g����i]u�U����$I�^z�z{{��8---����u���*��I����u�%������$�����m�W����^\�h�ei�p�q����Y�e��s����?/I�V���O�O<Q�����7���
t���K����.��a���������~��~��?���k�U__�r��B���m��I>������C��O?��.��Rq��z����Tcc��=�X=���
����[�|��_�������_�j�q������N��s�,���������C������X8;��s���W_���8��3�������+������v�B����������G>��q����^����?(����G�a�0�E��_	---g�?���z��_�@  ���SN9E�lV7�t��)Po(� ������������|>����?�p]y��z��'���gw�}
��z��'��~paMn���������o�N8��<��^�:�~�����?�������������^�6o��O|�����7��MK~����~������Q��v������moSGG�r��:::����Mw�u�n�����}>�����o�Q�y�kT�T����7���������~��{\*g��
z��u�i����KJ&�J&��T*�����>�!��'?��'�(���J����~��_��~��������;"���Z�W1��X,�T*����7:���m�p�������?�|�|���d�
g����O>�T*�h4j[��������e}���e9�Q����_�z�����;���2,.�
�2�w��;����e@��2�p`P��:t��7k�����x[�l���X���g����Q����C����������^�{�����q�F�s�=K�>??���>[�a��p�G?��.���'?������6�B!�}���d2+������g��}������W���C�J���pr�rY�|�;����U�������u�y������K�q�����
���=~6��'?�I��i%	�A�s�9+�����P��;�����QGu�_J�����/|�:����'�'�$}��P,S �G��������	��moS6��������/�KI�����7��
jmmUoo�����]�����V(Rww�ng������^��W���U�{����c�-l����9�����Vm��I?��>_��?���	]u�U�z�z�;��N8A���������Q��G��7�I


�=�y���SO=U~�_�����G?�'�xB�Je?����c�?�Y~��/�XW]u�����������V�o}�[���[4<<��������$�������izzZ���g����O�DB���w���(��+���Moz��|�I�~����'>���1m��Mo~�����g�USS�t�m����/���K����>}����7����I]q�z�;����	I�G>�MOO�4M���?�����}����zJGy��n��}�7o�SO=��������^��W��r����`��}�R�q���������%��;�2����i�&555������*�������
��������=��i�.g���7��
��=�����.��n���������wvv���.�����'�(�0�e�I�
7���/�\G}��N��:�,m��I��w����n��6]s�5jmmU__�.���}��|>���������rK��?�|�I]u�U��������Y~���������_���^����Q��*������-�����}��_��G��������g�����^'�Lj��
{�������������4M]y��jmm]���e�4>>����]r���_��������$���l6���e�Y�%m_���~Zo{�������I'��_��Y~�������u�����@=�p�U&�L.�yttT�RI�rY�������}OSSS����+_�JY�%Ir:w�u��v�P���D"����������B��O}�S�������%g*�Z�����������yI��^�*=���*���m��e��H�m_���~Z���k��v����Jb��}�bx�]�����Tgg�}�Q}��������z�`7
wXe��_�E�=�������O~R��fff������.�j5}�;��3�<�pLww�r��FGG�����t�������V�RQ6����?��_|����:��7��eY����<�L&����s�9��g>���i
���������joo����J%�w�}z����h\l�$�J%�EY��r��b��j�*��5,����X�\s�����|��k`91���,����������-[�e�s�1�����/��/K���jB���>��{���������~����SN��g����:J}}}z��gu���.����\^x��8������G��G�;��S_������W����/~���|�;������������x<��~����j���}�k�����bz�[�����}�|<���{��G���Z[[u�%��?��?��%m��}>�R���9��|>}����$}��_����>���������5f����{zz��<�ZZZ����_�{X-���0lg�������3��;
���,�8��eA��2`I�g��(�X�,��VB0T8�;��J��j����1����g�a��jdY����%i�Y~]��pX[�n�;���,
kbbB�`P��r���V%fy�6�BA�dRN�S�a����^��.
w`5�,KCCC���TKKgpu"��+�L���A�x\�g����
�,K������Rkk�����p8��`�\N�TJ.�K�x\�����C���������eY�����������|v���Rfff�N��Y�K��p/��J��*�JvGY1�G�HDn���(��eY�d2�f�jooWoo/%�Z�s|CC�ZZZ���%��iw�u%��*�N���Q�x|����.�������Xov,��������;�0����ZM�LF333���Tww���?��8���e���(�N+��	`����V&�����a����nw��T*�d��9C��p���C����,k]�9�[�VS:�V.�SWW�B�s�AX�s���Q���yfy�255���y�^�!�k�:}��;��Au��^;�j5�R)��y�B!�B!�#��q�]/���LNNjppP>�O�XlIe�$1���s���
���G���7k���z���mL�U�V�L&������M��1��Me�R�l�a�����������O�S��a���`�(�ggg�������#�`�X{���5<<���&�b1544�����i����o/���<����,��r�T�T���`�j�*�4577���>����	b������422���f�b�Z���}?l�V���-�����e�w��w�S�e��SO��>��E�|���R��4M�E��������Hs<���,���jllL~�_�h�������a���$)��r{9������O>�G}T�=�����/.�s`�U*%	�E��a��U�9{cY�FFF466�@ pPe�D��_;��=�(�r{9E"IRss�>�����[����*��J$*�J�D"jmm�;v��=�,K���W0T$9��]bI���i�WW\���k?�P(T�VU�Vu��w�U�z��>�����L�T�\V4U0�;^�9/eY����499�����a9��~\
���i�����(I###:���T��T�V��7�Q�7sH�o~~^�DB�JE�hT�@��H��x�`Y�555���V���/K�.Q��
�JE�t�a�i��-�����J%���J��X,&��ow$�0�x��cY�4==���6���-[�.Q���T*)�H�V��0577�	�",�R:�����:::�����e�D���b��D"!��d������`�ZM�LF333���Tww�����;�dsss2M���#�ZM�tZ�\N]]]
�B��l�(��%����i�r8�����|vG��Z��d2�B��P(�P(tH���X�K�v��kw$��V�J�R*
���VWW�!N
w`
������N����<���,�Z�*�LjvvV������X���p�"��+�L��r�0�v�T�U�����9������}������\.�T*%���x<���F�#XD�R�i�*����W[[��>�sE�
���e�6l��l6�Z��7����������}M�����W�Z��U.�%I�<���9���U��������aI��>�9���z�[���?\W^y��/�����(�J��vS�c���V�J��D"�b��p8��e�D������){�}*n��,��y�f]t�E������/}I�HD�������O=������~'���o}�[*�J:��s��o|CO=��������K.Yx���~Z��{�~������nR&�Y���I6�U*�Rcc#e���s��,����e%	�J%E"������%e�Cq�6
]{����+��w���~����:����c�i��-����[=���:���_|�bQ>�O��mSOO���^x����a�qN=�T�|>I��M�d�����A�X/�����d��x���r1.��j����V���y���r��h4�`0h[�A������$O<�R"�����2����hhhH�eiffF�e�c��>������SO=��m������/�����J�r������)
����0��5�P���<������H$T�T�Fl���2��s�a��R"�����������>�/|����t�)����n�������%	���/�����l�"I��w�����-��`=�������|>g��A�j�����T*���X,f{�.q��~�n���+�Pi�vy;lY�����[444�K/�T�C��{��~�i}�C���/Ir�\��W��x<�[n�E��5??�p8��|�;�`=������������`w$,�C1�K��v�Q��j5����f�#I��eYv�8��8�m��u��,���m��i���>������
�'cccQss�����e��fV��}Y���z~�;+�J$�,K�a�����<;�����uittT�������F�r:YmX����d���)�_����eY������"�e;Pfgge������|>���vC��u��,���h||\�`P�p����BA�dRN�S�a����i��}�nY��Z�p,��G�eihhH���jiiQ8^Ws�Z���xI��jvG�E>�W*����T<����;�^�����p���hbbB�bX�,K�x<����`Y�555���V���3���:���e������i]�f�������\.��X�e���wI�D"J���;���x<�D"v�X1�ei``@���jkkS__�e�[�s|CC�ZZZ���ew�����J��r������hw�E�����v���[W�����'�e)��(�����]����Cks<��733�t:-���x<.��mw�%Y����kO�VS&�����:::���������`m�f�J���x<2�n�v��kP�VS:�V.�Sgg����)g�:0==�L&#���x<.���*��J,�V�)�J)��+
���k�����������jjjJ�z�2���v��kH�VS2�T�PPwww]\`r�����vH33U����������|>��PCC����;��j��d2���Y��������HK�}{I��v�����Ce||\���jjjR,���]�p�P�Ve������������#-�a�y$I��es`����iddD����F�u]�K������T*J$���S___]����i�WW\��`���X���,���jddD~����l��3�P�*��L�T�XT������t@6m����\�;����1E"9�kc�p@]*��2MS�RI�HD---vG���4<<���	�A���5S�K��C�rY�DB�rY�hT�`��HaY����499�����a9�c-+
w����y%	U*E"�v�X����AMMM���U���k�l�(�PGJ��L�T�RQ4U �;�EX����MOO���M}}}k�l�(�P'J�������b���~���,��,e2e�Y������w����;�@�X�i���j2C���vG��Z��L&���utt���gM���;V���9��)��d������`�ZM�tZ�\N������^�e�D��UlG�.I�x\>���@U���J����
�����.�v�������L����P<����;�E�j5%�I
uww�����H+���N�PP2�����a��@�V�J&����UOO�:;;����(�����y%�I544(�����	�"���L�����z{{���aw$[P�`���rJ�Rr�\���jll�;�ET*���b����>�����6�Xfff�N��v�ee;Pv.�������fw$[Q��v�lV�tZ������r��vG��r�,�4U*��D���bw$�Q��V����d2�x<���r�Q���\.+�H�\.+�*�iU��l355���y�^�A�����y%	U*E�Q�#����-&''588(���X,F���R�$�4)���w5XqRSS�b����`�RI�DB�ZM�XL~���H��;V�������)��:R,e��B����lw�U��+fttT���jnnV,����;�E����4MY�%�0���dw�U����eY�����~���(e;Pv���������
���w9_|�.����>��?\7n��w��p�3�<�������a��8�����:+c�����/�m����kY�FFF466�@ @���1�`g���J$�(��j��������ex~����c�������>��}�c�?����k��/���7�K_�����m[Q�^;��n������t�,K���W0�l_�����B� �4�t:����z��T���N�T��>�)}��_\���;��\��������c���~�3���(�J���O�$]x��g��1X���$I��g��/eY����411���E"9����c�����<e�Z���o��ou�����k��L&�H$�p;�*�N���=+���^,���.�wfY�499���V��a��U�9;�r9%�I�\.v�a�xv���w�v����zJO<������]��,k�����=fg7�p�n�����SSSK:�����+�����%v�G�6�z��eY�d2�f�jooWoo/e�*���x�Y�N333J��r��2C���vG�;�v����>��[�*��0U�U�����]�^I�R
��
��{�_�"��~���/�X[�n]�jkk[��	�X����-{,�������:::(���j��%fy�d�Y�R)566*�S��e+�?��kppP�i�4M544�4M�w�y����U�V500�GyD'�|�zzz�D����L���o[g�u�$������c`�Z��T*���uvv������0�`zzZ�tZ�G�x\n���Huk������N:I���6n�(������^�@@����]���.��b����~��>��Q���yuuu)
Q��9�x��ajjJ�z�2C.�!���4��?*��#�8B[�n�;��T���L&U(
�
���T��Y�����399���A�|>�����#���gV���Z�*�LjvvV===����;�%������������(��	�;��e{oo�:::��`	���5<<L�~P�`�U�U�����9��������H�`ttT���jnnV,����;��B���R�Td�����������fw$��,K������W4�l?(��d�JE�DB�RI�pX���vG���422���qE"��C��KR.�e��J��"��ZZZ��`�eixxX
��D"r8v�Z�(�����y���r��h4�`0hw$��,KCCC���TKK���0e�!F��}���W"�P�RQ4U �;�EX����MOO���U�����+��{U*��H$T�V�������`�e)��(�����]�����+��{T,e��j���Pss���,��,��i������C===��+���)�J$�,K�a�����HQ���N����������n��F��]����4MIR<����7�E�j5�R)��yuuu)
Q����fgge�����l�@�VS2�T�PP(R(�;��E�IR�PP2�����a�z�vG��j��d2���Y��������H��;����J��t:����x��`�jU�ijnnN�������;��G����r9�R)�\.�A���J��d2���9��������H�;���s������hw$��T*2MS�bQ���jkk�;��;�:533�t:-���x<.��mw$��T*J$*�J
��jmm�;vB��e�Y��iy<�A���r��D"���yE"����	/A���LMMi``@^�W�a��b$V���y���r��h4�`0hw$�������I
R�ud~~^�DB�JE�hT�@��H��a�����ajhh�;�E�J%%	U�U�b1��~�#a(�����q
���I�X����bQ�i�V��0577�	��pX����422���f�b19�N�#XD�XT"��eY2CMMMvG�P��Q�eillL�������F���@����i���x<.��go ,�;�dY�FFF4>>�@ �H$B�����Y��)��!�0(���;�cY����511�`0�p8L���B��d2)��)�0��z����D���X����!MNN���E�pX���X����L&����x<.��cw$
w�5��,
jjjJ�������l�@.�S*�����a��u��`
�,K���V[[����(��:033�t:-���x<���F�#� P��9����d��f������^�v�d�Ye2��n��q��n�#� Q���Z��L&���uvv����������d2�x<2��}��p�S�ZM�tZ�\N]]]
�B��@��������^����EM�V�_��j5�R)��y�B!�B!�#X���I
R��Q���3�ZM�dR�BA�������;�%�������|>��PCC�����(��H�ZU2�����zzz���iw$K0>>���a555)�Q��Q�u�Z��4M������O���vG�cccQss�b���N���p�P���J�"�4U,������6�#X�eY�����~���(e�G���U*%	�J%��a����	�",���������D(��
w�U�\.�4M�J%E"����	�",�����&&&�)��	
w�U�\.+�H�\.+�*�	�",�����&''����p8,��aw,�
w�Uh~~^�DB�JE�hT�@��HaY�555���V���S��3��L�T�i��T*��b���vG���400���i��������}�pXEJ����j���Pss���,��,e2e�Y��������}��pX%���L�\(������`�ZM�LF333���Tww7e�:F��
����4MY�E���Z��t:�\.���.�B!��u���f���J&���x<.��gs"���jJ�R���
�B
�BvG�*@�`���Y��)���x<.��kw$��V�J�R*
���VWW����JP���P((�L��t*�����	�"������fgg������N�#a�p�A>�W2�����a��@�V�2MSsss���S{{�����P���\.�T*%���x<���F�#XD�R�i�*����W[[����
Q�������i��n�A���J��D"�R��p8���V�#a��pX!�lV�tZ�G�a��v�	�"���L�T�TR$QKK�����Q�����ie2y<��q�\�a�j7??/�4U.��F���U�wz�������zee;P����H$T�T�F���:��=�ChrrR�����|2C


vG��R�$�4U�T��������:A�p�LLLhhhHMMM��b��@(�JJ$��j2C���vGB�p8���422���fE�Q�v��E%	Y�%�0���dw$�
w�e6::���Q577+���t�	�"���d�&e;
�;�2�,K���S P$�l�����L����P<����;��;�2�,K###W0T8�l��K�v��kw$�1
w��dY����511�����a9�cXD�PP2����T<����;��;�A�,K������Rkk����)��:����L&�r�de;��;��,K���V[[����(��:����J��r������hw$����,e2e�Y���������333J��r��2���jY��u��'k���:���t��gkffF=����6o����7��3�\�``@��6n��O<QCCC�����j��
:���u�
7,���`Y�������:::(��&0��� ��*�J����3�qH,k����P[�l��O?�p8����^���7�A[�l��-[t��w/���O~R�}�{������s���W^)Iz��t��7��'���O>��|�+J$�<`%�j5�R)������S===��X���Z7==�t:-���x<.��mw$�A�Z����Hz��h�X\���������������?_?���%Iw�u����w���+����^��v����l��r
�B����l���,����)e2y�^��q�\���CcYwI:��3
���s����.�$��7��k^�����O*I���Pss��^�$���Yn�[�lV�LF�Hd�1������>�8�j�����������
�(���0���hrrR��|��8������������.��B�q�:����L&������SN��?�@ ����,k���n�a��"�����E��Z�*�LjvvV===����;pH0���f||\���jjjR,SCC�����-����������=����%IGy��=�X����UGG�
�����$�P(h~~^---�D"J����J���y��.��bm��u�����P�L�T�U�����Y���R�c�c�k����������L���l�{.������?r}�=���#�������,���~�#�<R�C��z�����I��������N���GYo��6��y�r9�q�:��3�y�r�T*2MSsss���SGG����C�Y�5�������l��Z�%er��N?�t�J%�j5��
o��?�i}�;���������^s�5��i�$�����u�y�����Soo�n��VI�����}H�7o�eY��G?��;l��,�e{�XT?g�bMc�k�eY������"����C���Gk��)��#�8B[�n�;��rY�i�T*)�����HX�Y���X*��422���q�A��a�v���gV.���r��D"�r��H$����V��444���I���(��p���;�����W"�P�RQ$Y�X$����,
jjjJ�������l�m(��k��F��`�ei``@���jkkS__e;lE���R��D"�j��X,&��ow$��,K�LF�lV�������l��(���V,e��j���Pss���,�V�)��hffF����l��@���b��D"!��d������`�ZM�tZ�\N�������l��A�����9��)I�����|���Z��T*�|>�P(���.�v�*�`�����i�r8����z�vG��Z��d2�B����nuuu�	�
�;XW
������N���l�@�ZU2�����zzz���iw$`�(�������L&����x<.��cw$��V�2MSsss���UGG������p�B.�S*����R<Wcc���,�R��4M�E��������H�>Q��5offF�tZn�[�aP�u`�����_mmmvGE���l6�t:���F��q��n�#XD�\�i�*�J�D"jii�;�$�`����V&����Q<�����v�rY�DB�rY�hT�`��H�����ISSS����a��@���W"�P�RQ$�lG���'Xs&''588(���X,F���R�$�4U�T�F���7�}�5ebbBCCC��|2C


vG��R��D"�j��X,&��ow$��P��5c||\���jjjR,�l�@�X�i���j2C���vG�;XFGG5::���f�b19�N�#X����L��eY2CMMMvG
�;�k�eittTccc����F���@�Q�KR<����7�(�@��,K###W P$�l�����L����P<����;�,(�@]�,K������P0T$����;�E
%�I9�N�A��5�����444���I���(S�u ��+�L���A�x\���H���pu��,
jjjJ�������l�@.�S*����R<Wcc����eG���eY�d2�f�jooWoo/e;Pfff�N��v�ee;�,
wP,�R:�����:::���C���l6�t:���F��q��n�#��;X�j�����r��:;;���M�����ie2y<��q�\��X��	�Z�VS*�R>�WWW�B�e;P���400 ��+�0(��.�SV�Z��d2�B��P(�P(dw$K099���A�|>�b1�v����U�Z�*�J�P(���G���vG�RSS�b�����
w��T�U%�I������WvG�����l��E�V�j�*�4577���>����	����jttT�����br:�vGV�;X5*��L�T�XT������`�eittTccc����F���X�(���P�T�H$T*�����jw$��,K###W P$�l��F�lW.�e��J��"��ZZZ��`�eixxX
��D"r8v�lE�l5??/�4U.��F��`�eihhH���jiiQ8�lD�l4??�D"�J��h4�@ `w$��,K���Vkk����)���A�lQ*�d��*��b���~���,��,e2e�Y���������	�;Xq�bQ�i�V��0577�	�",�R:�����:::���C���;XQ�bQ�DB�e�0555�	�"j�����r��:;;���M���;X1sss2MS�������
`Q�ZM�TJ�|^]]]
�B���^P��1;;+�4�p8de;Pj�����
��B��B�����U��r�BA�dRN�S�a����	�"������fgg������N�#��;8����R���N����<���,b�����WvG��;8d������\.���l�@�Z�i����S__�������
wpH�r9�R)�\.��q566�	�"*��L�T�XT�������
w��fff�N��v����v���`�JE�DB�RI�pX���vG��;XV�lV�tZ�G�aP�u�\.�4M�J%E"����	�K�`�LOO+������0�\��j7??/�4U.��F���-��e155����v�����+�H�R�(�*�	�k�mbbBCCC��|2C


vG��R��D"�j��X,&��ow$��Q���2>>���a555)�Q�u�X,�4M�j5����f�#k�;8`cccQss�b���N���,�X,*�H��,����&�#k�;�o�eillL�������F���@����i���x<.��go `��p���,���jllL�@@�H������2MS�C�aP���;X2��4<<���	�A��a�v�
%�I9�N�!��kw$`M�pKbY����499�����a9�cXD>�W*����T<����;�fQ��EY����AMMM���U�����@��rJ�Rr�\2��8�(��>Y����MOO���M}}}��@��l���jll�;��Q����,K�LF�lV�������l���������n�����n����u���Q�VS&�����:::���C���l6�t:-��#�0(��D�vS���N��������P(D�����)
����0�\��J�o�E�VS*�R>�W(R(�;�%������ e;`#����ZM�dR�BA�������;�%�������|>��PCC����u��H�������fgg������N�#X���q
���I�X����s9���O����u�QG��������$�S���?�pm��Qw�y����<��^���j��
:��3�����1��T�U�����Y���R���<�illL���jnn��v`X����?���l����~Z�pX�_�x�=��cz�������c���`��}H�^{�^x�m��Q_���$����R�(�HhnnN�������;0�P_,�����FFF������t.k��,�����I/��Z,�p8t��w��.PCC����u����g?��FFF�J�t��'K�.�����_���*��L�T�XT8V[[�����Y��aY�FFF4::�@ �h4J����7��3�T(�s�=��.�L�LF�Hda{4U:���������������"��Z[[���f���~�eixxX���
��D"���*�����n
*��;��eY{�oo��k�����
7��#�8b�kjjjI��^�(�����F�l��1���Y����!MLL�����X������F��=���w��H$���+�TJ�pX�px��K:�cvv��k���_|<��5??�����\.+�*�	�*�,��dY�599���V��a9�cx�e+�s�����$����=���#�<Rg�u�n��fU�U
��G��'����E"��g?�$}����Yg�%ItX\�TR"�P�RQ,S �;�U�Y����,
hjjJmmm����lV)�r=P.������R��Z��7��
���?���&�����q��N������7�_���u������/�+^�
��?�$�t�I�}��e{�VS,����;�U�Y����,e2e�Y��������X��RS�cGq��n�jwlS,e��B����lw$/���g|_�Y�VS&�����:::���C��B;���v�;X����d��,��ajjj�;�E�j5��i�r9uuu)
Q�u���5lG�.I�x\>���@U���J����
�
���`�(�X�fgge�������^���,�Z�*�J�P(���[]]]vG�(�X�
������N����<���,�Z�*�LjvvV===����;��D������L&���@���j�*�4577���>����	��p`
��rJ�Rr�\���jll�;�ET*���b����~����	��p`����Q:�����a��@�T*J$*�J
��jmm�;��@����f�N���xd��n���,�\.�4M�J%E"����	�A�p��MOO+�����(������jW.��H$T.��F��`���:655���y�^�A�����y%	U*E�Q�#X&�+�NMNNjppP>�O�a�����HQ*�d��*��b���~���,#
w������������X,F���R��D"�Z�&�0���lw$����:3>>���a577+�R�u�X,*�H��,����&�#8(��#���Uss�b���N���,bnnN�iR���;u��,���jllL~�_�h������J&���x<.��gs"��;��eY������"�e;Pfgge�������^���b��b�eixxX
��D"r8v���B��d2)���x<.��cw$+���U��,
jjjJ�������l�@>�W2�����a���:B��*dY�4==���6���Q�u ��)�J��r)������HV�;��eY�d2�f�jooWoo/e;Pfff�N��v�ee;�Q���X��t:���utt�������lV�tZ�G�a��v�	�
(�X%j�����r��:;;���M�����ie2y<��q�\Tn�z��~V�Z��T*�|>���.�B!�v�LMMi``@^�W�aP����Y�VS2�T�PP(R(�;�%�������|>��PCC������U�U%�I������G���vG�RSS�b�e;I���Z��4M������WvG�cccQss���(e;����R�(�LjnnN}}}joo�;�%����������t:��`�p`�U*���b����~����	�",���������D(�����T.�e��J�����Z[[��`�eiddD���
�
��������R.��H$T.��D���bw$��,KCCC���TKK��������R�����y���P��A�#X�eY����Z[[���O�`�(�8�����H$T�T�F��`�ei``@���jkkS__e;�EQ�p�J%%	U�U�b1��~�#X�eY�d2�f�jooWoo/e;�%�p�)�2MS�ZM�a�����HaY����fff�������vKF��!P,�H$dY��PSS���,�V�)�N+�����S�������;�lnnN�iJ����|>���,�V�)�J)��+
������~�p`����4M9�A���Z��d2�B����nuuu�	@��p`�
%�I9�N�!��kw$��V�J&����UOO�:;;����Q������������x��`�jU�ijnnN�������;�:G��A��rJ�Rr�\���jll�;�ET*���b����>����	�@��A���Q:�����a��@��l���W[[������l6�L&#���x<.��mw$�(��2MS�RI�pX���vG��P�p�����d��xde;P��������"��ZZZ��`��p`?MMMi``@^�W�a�����j7??�D"�J��H$�`0hw$k
�arrR�����|��b��@��l�F�
vG�F��D����ajhh�;�E�J%%	U�U�b1��~�#X�(�X���q
���I�X����bQ�i�V��0577�	�G��"���422���f�b19�N�#X����L��eY2CMMMvG�P���eittTccc����F���@�Q�KR<����7�u���=�,K###W P$�l�����L����P<����;�u�����,K������P0T$����;�E
%�I9�N�A�`�Q����444���I���(S�u ��+�L���A�x\���H�!
w��eY����Z[[���O���\.�T*%���x<���F�#X�(���e�������������>�v����(�N��v�0�v��p�{�e)��(�����C===��@�f�J��jllT<����;�u�����j5e2������S�����@���V&����Q<��E��~�&�[�ZM�tZ�\N]]]
�B��@��������^���l�j���.�j5%�I
�B!�B!�#X���I
���)�Q��i����o/���<���kw�5��H�u�Z�*�J�P(���[]]]vG�����ajhh�;PW�m+��k�n_qE/��2s���T�V�l����l�����������D����K��x���m,�p��jU�ijnnN}}}joo�;�%����������tr)p ;���=�(�r����.T*���b����~����	�",������������F)����i�WW\�����;`��T*J$*�J
��jmm�;�EX�������+(�P��`�&/E�!D�X����L�T�TR$QKK���,��,
kbbB�`P�HD���X�(
w��5??/�4U.��F��`�eihhH���jiiQ8�lP7��s8�tZo}�[��W�BGy����
I�C=�@ ���7k���:��3������7��O�������~����a�?�p�p�
K:�����H$(�`������,
jrrR���������.�K��������z��'��#���?��$�
ox��l��-[�����^8��������������9���+��R���/��o��O>�'�|R_��W�H$�y;�J%%	U*�b1�#���X-,�R&�����������O���,[�����c�9F��������5J�R�<��{�����~I�����0��u�]z���-���@ ���>{a���1H�[�W�U�!��ow$X�����eYJ���f����Poo/e;��tH.�<99���G:���$I���o����F��~���J�&&&���,���+�677��v+��*��(�,<^4U:���1�Em��]�ZM�a�����HPW��v��jJ�R���Qgg�zzz(���e�h�����>�l]r�%��i�����L&������SN��?����[��_���
7���z�SSS��"ugnnN�iJ����|>�������9^b���fG��������P(D���-���jU��w�6o���.�L�.Tw��G��c��o�[utt�P(�X,J�
���������H$�t:����TJ�px������/���[������eV�����5�
��l���Z�x�Y��Z��d2�|>�P(���n�vuoY�����P �����������h��~�+y��r8:��S���}O����~W��v�$��3��m���|>�\.�;��Cg�y�>��O���2MSN��3��1�VZ�Z�i�*
���Q(�;,��?����G}T�w�^��W���A���|@N�S_����v�%I�]v�����I�����;�<
���W��z����%I_���u�
7��,}���_��_/z��q���u�r�L�*R(�L&�v��cw$8`v���y����`-�V�J&����Uoo�:::��e��u������R:�������������.�u�Y+t�0�������L&�r�de;����3�����e��e{<�0���������9��������Hp�v�YwYR�k_���>�l}���+_�J�u�]������M	�^�r����3�@��q�n_[�n]�3�A�RQ"��������)��I��o|����o~������<�L


���/�2�<�A���Q:����V<_X���
6���S�7#��#����7�I��������e{�TR8�eUXKv)�-�R �$��e/��?�w������*��e�Y��iy<�A���'?��n��}�����p�	r����bvG@�rY�i�T*)������Hp����LKK�^x�������������c�����^�p�0==�P�sf;�������~�#}�[��\�J�bw$4??�D"���yE�Q�vk�.g��p�
������t������o_�`�055���y�^�!����A�uvv�������?�C}}}v��s;��J��h4����e�4�~���������;oE����I
����0544�	V�SN9E��r��1�X�TR"�P�ZU,����;�������c�9�9��������D��9�������j����l���r��c�=���,�R&�Y�@H����FFF����X,&�s��F�s<`��Q�[�%�0���dw$XQ��oz��t�	'����v�f�+
�����jttT~�_�h���X
���d��$)�����l�K��i�&}�����^���v�D"+
�>Y����Q���)(�P��0��6;;+�4�p8de;�uk���������w���kV$`}�,K������P0T8�l�%b���P((�L��t�0y�^�#�m��>w��q���u��1{aY����499�����a9�c��bf�3�/����y�R)9�N��qy<�#���yfu�tc2���w��t:-I
��:��3e�����eippPSSSjmmU?e;�x�J���J&�r�\2��$��Y�o�Q'�t�FGG�a�m��Accc:���u��7���FY����MMM�����s<`��r����3������������V~���r���>�h���+p9�1TX},�R&�Q6�U{{�z{{)��k3���9^b���hffF�tZn�[�x\n���H`�}.)�����{��U����d433������P��Ab���l6�t:-��#�0(��%v)�/��b}��z����H$"IJ�R�����W�W��-�ZM�tZ�\N]]]
�B��p���+ajjJ�z�2C.�n�q����o�K.�Do��u��w�w���,�R$�=���
6���F�j5�R)��y�B!uuuQ��2`�j����l�E���q��
��'>�\.'I
+
���j5%�I
uww�����H��0����	


����0�,�}p�|cddD�������7j�����������khh����:W�Ve��
��zzz(�`�1����q


������`����s���^�:�R)


ihhH�tZ�{��t�����P�v��������Ugg���`�a�
cccVss3e;,�.�����>�����i����&��_�%g��[�RQ"�����������aw$X������,���jddD~�_�XLN�s���������������������o~S���+P�*��L�T�XT������ks<`��(�GGG�F)�`?����[o�C=���nE"E"�������-��bWF@�)��J$*��D"jkk�;�i����`Y����566�`0�H$B��������>}����$MNN��,>��/;��r��h4�`0hw$X�����,


irrR---
��r8v������looWGG���/�r%�������o�N�6b��/��488���I���R��Ap-����?�9u�T*�4MU*E�Q�#���X
��400���i������������eY+�P�J����j��b���~���`�c�,��,e2e�Y�������������O>�9u�X,�4��������H1���V�)��hffF����l�e�K�~�E����7���CP?���d��,��ajjj�;�K����Q���N��������P(D��d���w�q:��c�t:��3����|�^��W��g��������udG�.I�x��l�X�Z��T*�\.�P(���n�vXFk�;���o��?,��-I����	'��_��W+p9q���u��1`�����i�r8����z�vG���3�Z��%fyXN�ZM�dR�BA�������;�	;���=�011�r��p�R�hbbbe�V�B� �4�t:)�`�a��M�Z�i�*
����l�Cd��/��������V��~�$���������Y�`��'��+�L���A�x\���H��0��dG�>77���^utt�	��=��_~�N:�$=���������y�J��2�\N�TJ.�K�x\���vG�s<��*��L�T�XT__������k�^����z��t���+��krr�_��N���(�N��v�0�vX���;�\���a����	��=��~��7�}�{�.��2I�����>��
X���R��9�V9�x��rY�DB�bQ�H��V�������>�@  I:���566�������V:����Q<����;`����������F�jii�;�{\R����rc�V[�@��ajjJ�z�2C.�^W!������y%	U*E������=������F����T�T��SO�������7�t6�M&''500 ���x<N�u�9��R��P��b1�v���/��J���z���>���~]w�u+�
`���	
���I�a�����H�%b���kG�^�V�����������,����G��[��V���q
���I�X��V3���}���E���Z��X,���f�#�������5�����o~s�cH;|�;�Y���7::���Q577+��������s<�?sss2MS�e�0555�	��=�g�q�^���������FX�,������������F)��N1�����l��x<.��go �����}�k_[�,�fY�FFF4>>�@ �H$B�u�9����Y��)���x<.��kw$��r��N8AO<��Jg� ��4<<���q�A�l�5�9��B� �4�t:)�`����
6��p�Z���oT8����eYr8z�����	XF�eihhH���jiiQ8����;�1�������L&����x<.��cw$�Nv)�x��r���m*m�.�a�����k``@���jmmU?e;�9�xXr��R��\.������x�]
�X,&Iz�����l](488�����m�������%���������v���R���k��������n���l�Uj����{��r����n��;��X>���%I������f~�{uttP���kS6�U*�Rcc#g��*�����ju�A���Q���+
�|<�&Y�&�yF�JE�G����vX���`����V&����Q<����*�J�����=��#���_*�X(��i��Q���W��oU���+|�q���F1��/��u�}Ym�V�;
�CdjjJ�LF^�����S��_��g����6Y��l6�;��c��R�VS2��\w�z�:J�P��H�C�9~�����k�Z�}�����kc"�mrrR�����|2C


vG,����7k��mz���dY�6m����@��V�J&����UOO�:;;��8�������K��x��D����K��211���!555)�Q�@���2'�|�\.��<�H���������'����h��������	������<��D���m�ollLCCCjnn�l�:���]���w�=;;�t:�"��Z��4M������O���������K:�0g����~l���W���w`�����B��t��<I�*��o����Zn�[[�lQcc��v�����w��]ve,Q�RQ"����������k��m�M��k����A�����M^���-���`Y�FFF4::*��O�ul���W]u����>���j~~^���*������5�\cWF��(����������$������ks<��e��������(e;��=.)s���Kz�������	����2���\.+�Hh~~^�HD---�X���x�/�eixxX
��D"r8v��=�<��>��)�����kjjJ�hT�Db��1??/�4U.��Fw����~0�@��,K������Rkk����)�`
��g�>��O����+^�
������n�i���������W"��k��k�������,
hjjJmmm������pw8���S�R�$�}����/����V*��}�vU*�b1�#l���eY�d2���V{{����(�`
���2>�O�jUGq����Q�����	�W�X�i���j2C���vG�����Y��t:���utt�������=���O��O����W��m��Mw�u������t6��E%	�v�n��`���jJ�R���Qgg'e;�Q{<������$544��n���[�P�=����i���x<��g�.��`u�Q���yuuu)
Q����3��������6����oI�%��e;���lIM��4mz��4��Qs����n��B���0��C
�p������`c�[�:`7K��)%Rh�m��$���,K�u�~�v�����,��|<�H/Y�����?z�����g��~577��v���~��~��E(���o~��9����G����_�����s�N���K<����O?��.��"�}�����k������&''
�$I��p����%zyXK�|^�����������;�`�7p������\###�'>�	�t�M�>PII���/�R�>���x�	=�����w�����:z���{�9��?�G>�������oWGG�^x����K��s�$��9��%	��a��fV�t:}�D/k%��)+�H���^uuu�.	���
���������������2��������/�X�TZZ�.�@]]]z��t�M7�b����I�^z�~�a
���KW^y�$���o�]�r:��f�����9����B���N�����`-������jhh����]`�����o�������)MMM��_����})��������+��B���r���_kiiQ$Y�vI�ulF�XL����X,�z���l�.	���i/���j�f�
�����Rcc��m�V���d�MS����J�\N��;�3{��b��w�-���t:����i�����?�a��~�1���}��-v��<������-�<�H&&&�DTRR"������B���������`5����dRMMM���.tI�u4�
�L&�|>?�O&�Q&�Y�I��r����o�>�y���$��=g�JWW�������<���{�����?~|�������j�������t�x�^VC&�Q(R2�Tss3���4o�~�n��V9��9�]w�u�����\.���=������+U__/����~X����~U�]w�i��E4UWW�JKK��ze�Z]`���33���i��nUUU�$@�;R�t���?�?��?��s��\ Iz������������=���Kf�Y���g�t:%I_��u��7��;��9���o|���+��b���f066�����vy<����?�,�^�L:�V8V&����Veee�K��X�0�"�{�n?~��e��FGG���K�[=���.6�t:�P(�l6�����7[��=+il###���SYY�<�,K�K��T*�P(�\.���V9�B�(0w(���a������\�����@H&�
������x<���(tI�
��
hhhH���Pkk���U���H&�
�B2C�G����.	�A�@����!
��p�����(SSS
���$��������P�`�����
��t��v�E`rrR�pX&�I���p
wXG�a���_###���Tss3a;P��:;;e6���xd��]`"p�ub����4::*�����f�L�B�`	�x\����X,�z���l�.	�A��:0C���SUU������"��������y�^����$�F�k$(���������qUWW�����(�D"�Z��x<���%��H����a���T������/VCCa;P���"��JKK��ze�Z]��S��T0(�0���M�LF��	�v�H���+��f��V�����&	e�Q�m6�_ta;P������#��.��������[VY>��`y��7���x\;.�Pv���e�
,H*L�������`�Uoo�������J�X1~s�*��r���R"�P��^����B�6�@ ��������Bw�FFF������2y<Y,�B�(B�p�U�������D"���z�v�,�`J�����X?������Syy9a;����VA.�S8����USSS��@������P(5�������***���*������G�g(��*+�L���I����.	�����f���0
jhhH�C---���3F�g ��*
)�J���YUUU�.	!��N��#�0400���a9�N��n�v�� p����d��J��v��r�
]�%����~������Rn�[&���e6	w8
�LF�PH�LF---���,tI�`����4::*�����f�v��"p�J��
�B�f�jii���,tI�`�z{{566���*555�V�;�@*�R8V6�Ukk�G�K��0������qUWW������&�`�R��B�����<�***
]�%��H$���	m��M������5C���L&
�d�<����]�%��yE"�b1m��];v� l�)wX������0a;PD��������U[[���:�v��#p�ELNN*�d2��������%XB>�Wgg������TWWW��[�;,����n��$K��r���R"���;T[[[��[�;�#�H���Sf�Y^�W6���%XB.�Sgg�&''����m���$�C�'������TII�<a;Pr���������������B������XL]]]*))���Uiii�K��l6�p8�d2���&UWW�$�E�/���P$��j���!l�@6�U(R*�Rss����
]`#pI�hT�HD6�M�GV���%XB&�Q8V*�������*tI�-����7>>���n�l6y�^���O#����i��ae2��������%@�`kSOO��v�<a;P���B�����ZZZ�t:]��la������UYY�<�,K�K��T*�p8�l6���V9�B��,w[�������U^^���V�v��R)�B!��yy<UTT�$� p��

i``@jii!l�@2�T(�a�x<*///tI�����288���A9����l6�$K���R8�$y�^���� @�`K0C���������&l��������L&�<a;`C#p������
���R�����@H$�����l�����n/tI,����f����4::*�����f�L�B�p�@ �`0%��&��P��������l�����f+tI,����e�z{{566���*555��
)H���o������[Z<Wgg�JJJ��x�E��
6%�0������1UWW��
-LI��^��c`+��b�a;+����6�0����h4���544��
���C���c`����P$��j�����j-tI��;�M%�����[��m����	����������wli�hT�HD6�M���P��l�|^�HD�XL��o��;�@�������������-��&�����
@q�7�M!�����K�x\uuu���%l�����zzzd����x�E��b�^>�Wgg���v������B�`FFF������2y<Y,�B��!pP�r��:;;599���zm����%X���a������\������M��@���r
�����RCC��m�V��,����TQQ���V���B��� pP����������USSS��,�0


ippP�C---���M����$�������O���a{SS����P%��X�7��a�����N��n7a;`�!p��Iut����7�ya��d��J��v��r�
Q&��X�7��a�������*++���L�����`C	S�$��6�X��C�����ZZZ����Xo�0�������\.V�65V��P|����Pj�q:�V(R6����Veee�jX/�F@�0C���SUU����d2�
]k����������0gNi*�R8V6�UKK��Ng��X��F@�0C===Wuu�	���;�
������L�R
�B��rjmm���(pu����(�a���[�hT555jhh ll	�6�d2�p8�|>/������B�`	�|^��������m�T__O��2�lHSSS
��2C�G����.	����"��b��jkkUWWG��R�l83a�$y�^���� K������R<W]]�jkk	�[�;�
errR�pX&�I^�Wv;�J��.�����S�DB;v�Pmmm�K� �l�DB���2���x<��@��r�����������}��B�@������:;;e�X��ze��
]�%�r9��aMMM���A��m+tI�;����b���RII��^�JKK]�%d�Y��a%�I566�����%Pp�
jbbB�HDV�U���('��MMM���.tIl��z���jnnVI�+��C9�N���O������^;����]~����k����7���o�k����t��gk���:x����P|������d�ZY�@��X�L&�P(�d2)��M��	V-p�;������_�����'���O>�o}�[������������������.}���$�������'�xBO<����o�F�Ph�s���qE"�l6�|>Y��B���E/`�f��t:����\�B����j��e�]����e����������J�n��F}�;��$��������z99�N����m�:@qSww��v��^���t`���X�t:�`0�L&���UVV�$6�U�����\\p�.��r=��C����UTT�n�K�***d�Z�F���-��={~KK�"����(������QYY�<a;�<��TJ�PH�lV---r:��.	�
iM��/�P�������3�<�����z��G��l��n�������[~���������T^^���VY,�B�@/`�L�������*��Q�����t�{ee��G�����K/�T���/�m�6%	%�IIR"�P:�������V$�}���.577/z�����?~|���7<<L�@�� I�d���X�����ov5KOO�~���h��=2�Lz�������O��O��O����%I�^{�:�x<�X,������^��96���A������B����"@/`jjj6l�x<���(tIlx�6R���n���*�����Y�����s�9G_��e�Z%I�g&��/I����u�
7������������$���K��~����'�0�{��{��|��`c2C������PKK���5�:��<��MMM)K��^����
[E�d�d�b���{��?^�2�-e��g����*��#��Wj��7��z��q]��799�p8,��$��;��1���=��n�
`k�z�Y������OH���>���r���2�I$�����l���!l`�Xn
`U����WfhH*)���P>�Q���B�`�x\�pXf�����&w��0���(�r�Z[+S>�|"!������]��b1uvv���D>�O6���%P�)`U����nE�Qm��bU���k����RU[�d�
jbbB�HDV�U�G����.	��E�����H$���	m��M���256����,ti�F�Dd����xd�Z]E�������D"��b��}�v��!��T��,a||\�����l�z�*)!"�L���i������R<Wmm������"066�����vy<�vV	�Q��|>���N%	��������%X���Q������L�G���%�i�XR �T0���g��oW.�Sgg�&''U__�����D�022���>���������UF�`Q�@R}���Gu*+�����m��V`�������O��2�[0��$y�6�����K���jll$l��������UQQ��+�,���I����b������&����\������A


��p���Ef3k�X+������X����K;vH�_�����B�`	�ah``@���r:�r�����1w��d2��������v���r�$K0C���Qee��n�L&S��`�#p��t:�p8�L&���UVV�$K0C}}}���Rss3a;�����@ �`0%��&���P(�l6���9��B�`	�a���G������RSSa;����������O����t�
i��jmm������L ���Y.������nE�Q���������uF�@��$In�EO?Ug�Y����
IsyIjoo t6�0�D411�m��������`{r�$���\.����aH�}�{6l�^	��^��c����������	m����}$EV2(t)�"�
w���VC���)E"%z�k����j��}���=J�9P83a{<Wmm������P2P_G��qC{��~+w���T8��g����SYY�)����joo`�;�A��yuvv*�H���Nuuu�.iSH��$���T(�T0H�X6w`�K$�����l������p����	��
 �����S����������]��a��$I�Ph�1�A�la�x\]]]2���z�����$�����r
�����RCC��m�V��6�����v��A�|>V�V�������:;;URR"��C��u$���7{���@���lV������Rcc�jjj
]��d��	���\���X,6����)LI��^��c,-����lojj"l`b�;��LLL(��j�����j��$l!>�t�
��cq�lV�PH�TJ������*tI`��&w�|����"��l6�<a;���oW{{3�W ��(
)�N��v��r�$�w`;q>f*��
7��{w�<�JJ��?
����/S:�V8V&�QKK�*++]X3��Mlff}}^SS���E"�N+
�PDH��M���)�J)���b��^�B��T*�P(�\.���V9�B����
������kWR6�M�\��={*
]�����R��l>�$�����/pe��L&������xTQA@� p6��G{��9 ��"��L���%k*���C���F%I��7mho/��=�L*
�0y<����$��p6�0488�'�RII����&���y��f�
%I6�W�x\�XL6�w��6���)�B!I���%l����L�>88�W����
������y��f6;F&������T��{�k����l���xTVVV����`��������|>��~��}�0������UVVj��f55���{���WC{{��pO$�����l�����N�@�"p�P �TGG��q{{����a���O���r�\jnn��d��o'h��b�����9h��x<���NY,y�^�l|2�b�H`
��M�zms�W�a����������f�v[,Sgg�JJJ��$X�������Pj��j1C===Wuu�	��"011�H$2�����$�
��5�������&s�
�Pww����jjj���@��h4���nY�Vy�^Y��B�V	�;���b�z>�Www�&&&�m�6����E`||\�����l�x<��l2�@�����D"��b���U]]a;P������#��.����^�����("�|^]]]������S]]]�K�������%l`��7<P$���:;;�H$�c�����$�022���>�������b���%����c��'��_��(.�@��r�����������}��B�`���������r���n�����C��n%��}��65������e2����r
�����Tcc#a;P$����������
��]�R��r������R/�4{����$���*-RSSFMMM���.tY�`�544$�����������S>����d�J�����l>_�K�h�P ����y���r��>�1�v�����
��t��vE�.Iv�_;��S���3{��;�d�+@�l@�?�P<WC����r
�
]�%����~������R���E��p�����)�a*����`2����A��y��W���*������P__�FGG�r����,��T��N���'h�4�H:�V(RKK^��D�J������]�����^������JMMME��3C�l�TJ�pX�lV���r8�.	��POO����U]]���F�v�0w`H�R
�B����x<���(tI�`�����FUSS����v�8w��������l�^^^^��,!�����[��}�v��A�T\����������_�~�V*�@��|>�H$���	�����Y�@�LMM��'�����}�L�7�
��.�"��������TWWG��`�PO<1���h`@r8���\�PJ�`J~�����G.�SWW���v������B�6w`>�w�3�_�rB��fE�6MMe�O�������D���r�����������}��B�6 w`��{��>����9��RMM������-Q,���������r���������������B�6(w`I}��}��r*-�Cz����f�.��B�X��%�G6�U8V2�TSS����]����u����*/��j��Y�**�z�������
�'l,�lV�PH�TJ������*tI`�#p�X4Ui��KT^^����>�����ZI�)�|6��H&�Q8V*�������*tI��kh||\���*--��WV�l����l����	��
&�N++�����E����.		w`�������G==V}�%2��$I8\����i�B!e�Y�������g.t�f4::������)����l��;=�=L�:�I�R�a{kk+a;X1V��lddD}}}*//Wkk�2����B���}-7Ge&<
%(���������	����<�***
](B����������UR27������s�N���K<����O?��.��"�}�����k������������'{���W������������Q{{����@R}:thT}
�k�}��C�3������C�����d P��V$�L*��3����;��N=���sn������G������~�}�#�m�o��vutt��^��]�t�=���9@�
j``@��~Y��O�o~s����oW[�kMW����at
X)�x��T0(I�y�s������B������Qyyy�KElU��.�L���sn{��t�M7�b����I�^z�~�a
���KW^y�$���o�]s:��b�488(���m��d2�����Q5�1�l.��8S6�O��
��ot���
�\���%lgl�g�www�����=niiQ$Qww��n�)���9@!���������Tss��SS�����]�w����v�_
��E5�}rrR�pX&�I^�Wv;�38sk�����O��<xP�=[�y�J����~�����r���Y&���/6�~;A;X���%z�bf���"h��D"���N��fy�^�l|:��U)3��=g�JWW�������<���{�����?~|�Ouu�Z�h�"�������0���jddDUUU�a���/W[[���8Y!�x�^k/�+�b���U����u�]��}�k��r������>�+��R���r��z���%I_��Wg?~z:�k!H���O�����O�@R�a���Gccc���VSS���`3���f���������v�&V5p��������\.���f�q����+����V�v����}�������$}��_�������V ���H�i���`pzR�w�������5>>���566���G��`bbB]]]�Z��z�*---tI`2+�X�v�����������d�M7�����m�T__O�V
=���.X
�hT�HD6�M�GV���%�M���u�7M���oW{{�^|qJee���������c��v�������[6�M^�W%%�k�NX@2��G��T�k�v��R]]�jkk	��"066�����vy<�v���6��I�)�|6���u���@@���LO=5)�����~�~���t�o��n58}������UYY�<�,K�K[�;6���KR{{�����`P�XV�F���� [nJ�����Nv�]jpz���������r�����uc.t�B���$����9^%��2�S��*�7)Zu�N�R����`����������
�v��X��
����C�������f�o��������e�����\.�l>���`�588(��������1�����oW{{���p�f�
��J&�r������j%W+���1N�����������t:�v�	��i$^�@!p������mn{&�Q8V*�Rss����$Iv�������������UYY���f�vl�@@}��
���>�
�.�t�
��N��v�g�v�a�������\.+�����#f�z�6.V�c�K��
���d2r�����,tI�`�z{{566���*555�d2�,`U��#�
��6.wli�tZ�PH�lV---r:��.	��POO����U]]���F�vlJv�_
���p�"B��-)H�����Z��j���U���eX�a���V4UMM�V5lg�Jl4�+���[J2��G���e�Xv�0�O~���(�|^��������m�T__��a;T�3�n2�2f����]���iwyXG���-�.
����"��&&&�}��U�%6�g��[F*TztT�xL��5���JJJ���
]�E��yuuu)����N;v�X���lP	�#e�e$�I�?�����
�O�t��5����.
����:;;�H$�c�������b�Jp���%$	
(Vw��mU�R����?���r9uvvjrrR�����}��O6�g��2��������JZ[U��C&K���
M8['lP�\N�pX���jhhX���L���Z,SWW����Jg^���I�"!��I���8`�f�
��J&�jllTMMM�KXwlZ�D"��2����R��1I�jo�~����N����T]]�d �\uP)�M)����KV�U�L��f�����1�`����O&�Q(R2�����
��::4��/���;=|��e,���t������-��&���|>+iB��t���v`��	�3��ZZZTYY)IJ��E�J�B�����V��P �T0���gc�&k��Ek��qllL===����x<*))��_���L�-��q�J��
�B�f�r���a�$�|>�b1��qY��N��A�e
�����=noo���"pGQ��i���Too�J{{U�J)�����&����Tla��W*�R8V6�UKK��N�����~��y���Gf�S�K6��@�����^�M�PJ�`��>k��E�����'�t��Q������_W�dRTRC{;+_@��A�R)�B!�r9�����p�{?W[�l>��������`}��(��4&�)���T^�PU:���$���T(�GM ��q#J&�
������x<���X��ayT�|����~;#6XG�(J3M���������r�<�s�N���
�$���@��F355�p8,�0��xT^^���	tf�	��!pGQ2C���u���V%%%���ts��~�����)NA��1������zUVV��9�Z��1����������W*))Q���*�����`c���T8��d�������`��@��l�(*�a���_###r��2=���/��a|�q%	uvv�l6���,;l�	�>��A���a����4::*����={�jld|���������)��"��+�m�+�	���>�s��E�����/
����woN���]MMM2�L����1v�0b�����TRR"������B���,�	���?wlx_�����"����}Ojl,����
]�c7�����"���V�<������:{#���}��<�������a����W>/���5>n�G?�����
]*�o��h4�H$���Ry�^Y����Vg>�=���4����
q���?wl'7���;TQ1�������7i|���d���;X%�o����quww�f������d�/=�:;H��{���pX����n�8�y��;6��`0���4���3���56����u��N�v[m�+@�b���766�����vy<��
�����Sr:-r8,��s���E�B��<�����gSu�%����R�m�<���W]]�n�]��6���Q������L�����K�_�����rM�l��r����`I��0<
�F�5�J�f���������(###���Syy�Z[[e�X��1�tu��lxZ��'wl�/�(�eJ��7�>:����B�`��������a��Z�MW�V�\��d ���~W����r����f�����4l2�@R�G$]��188���~UTT���l��]��G���k��(�������g4e6���P�
7��t�������<l"����0C������PKK��������;�h4'��R�������!l:�@@������Z�_���/��\$"{6+��)W[a;V+�W�a�����N�������iV,�������
X�p��I����=nho��'�^)�E��2��iY�I��`���p�Rs��2�a���_###��������d*tYs����o_�������k&J�l^�R��R��l��N�5h����P��g�<5�w���v�������)�|6V<��0������Q�\.577o��]��P8�X33��S����t:�P(�|K�Z>�	�0�������&�0������qUUU���iC��o���!p��%���e��v�_
��s�I�R
���f�jmm���X���������0uww+����F


6l���+���,K�c_������W ���?����a]t�Yo|�WkY20+H���o�����0v��P$�����m�����
�
�;�e�y�K	���?���O�%I��9�s�EL��z��D���)J)L�/C>�W$Q,�����c��v�E�]��B����������������R%������h�\>�WWW�b��jkk	����X����/%���_����x�F*~O}Y�/p���Dse���:;;�H$TWW����B�P��l3�������S�?��r�r�3}z���)��Ku���8Xwl��<�\N������T}}��o�^����;�D<W(<&�I��-R^�xlz�m��.
�N��m��B�PT���U�������7�N#�~M��5R�*�������^ ����Q������599���F�v���
w��X,���.����
7]����{�y5����m��<`S����S4�S,���w�P[�k��������������T]]��l>�8#�@rv�����"���V��^��V�v��O���`0�h4�P(�x<�{��_r��l6�P(�T*���fUUU�_���;N���g��R�������\�GV����[��gS,�W<���a��iQ0�Z0p�d2
��J�Rr��r��^
��1��mf���/N*L���9�T���(���;��!��&��&��"��6�}���B�����ZZZ�V+�q�|>���R�F3��0��������=���[W[�K>�mv��|��g��l6���9��T
�������/6+����&t��Y}��f��:TUU�����{O����;�J)
)�����U�c�����W��\���
E���g�E�%���/=#��Zo}�^8�C����}1�h3���dR�pX�|^�G���'�AQ�oX�.�U�$I^�M�Pj�
�����Q����j����?Ty�TY2����u��\�={
]!�:6kO�L&
�d�<����W�qO~����kt�����fz�`)l���fF��B�9��,H��O�EO}A���?��vL� �D��?�7J�.X5������R(�$y��U���oPH��c�9�3_�
X����~���6��'����n���r*�rM�<?��l�F�K�������]&�*�~����F��%�E������
��2�L�x<*++[��?�
���+�6��E�����y����n��$.�)���V�\B��j��Q��-t��<Ng�x ���R�i��:;;e6���xd����1��#��V���t�c^3/L��R�\cj�@�����m����R������Q�������\�����f�������%��,��+�m�+��������6�"$��Z���G{����}��o�>=��S�����K;w���]����������E]���>[�\s������:�#H���8��������������������������p����u����Hlb����<[|���7��X,���NY,�9a{2P���e��4����C����S �\������p������<{���_G��s�=���~��u��������p���oWGG����J�������}���\������.~�n�	��r���z����d2�������%iw���(�>~&(��I�b�e�W��2�b1uuu���D^�W������������5�����^L3oP8�=�������Xo���}><��n��&Y,555��K/��?���uuu��+��$�|���+`:�#z�����:g�qUg��~Q��z������W,}�����XNN�Y��.{���oW[�kC���V���PWW��V�|>�l�.I�`P�d�z�/���)����
�Sz��(����������v���O�����d���-��=����E"�o����pf��+t��r���*��L�J���X���la���77�j��rI�+����V=tH}��{4���.�������j��9���I�R�������v]u�K^o����J.�e�\?���n#e~����v+�H��o�g>��1�}�}���8x��<8{<66��������*?�9���%I&IV����V��H1�fQ8}���K����8�=�)I+H���]���������PH������Y��vy<����R������]�`P6�o�q23p����b�����g���j	���__�n+�gV�TTT��[n���G�v���j���Rss������}�q���;��C����S]]��?ZQ����O�X�?���A&I����_�S�����q�(���������g��_r�����G�+���F�8�����TJ�ee���3�~�\mm�
��W��������a�����Q�qG�����
u�V�L�81���m]�D"���	IR.��<���;O�]w�����)�����G�>�����J�����v��t��W�����N�<�������xF�O}[�*W^f����>������n�P�6K����v�������^D��h�@ ����:r$&I�>o���V/��*�n�A{����.�����g$u�=�
����0�(�`5��6V�i��u)300����N�|^�\N�{�����}L��������]�v�l6������N�$��_��n��F�q�:��s��o|C�t�W,xV&H���~�K���l���MS����3*oiT������v�v�P�f��O-s��|fV*IR4�[�yg"�h��$��oW��s�(/���)�z����'<V �T�������^��Y��.�`JN�E�E�xN�X�O��Me���d^�h2�;L�����[��/t������~���t����|�Q�X^���A{��X�|��e7�8s���[����Y��@R���G?�i�������%��t�B��
Pg4��/��

i``@�15���~T���j|��)��%I������/�����tF�a�W��1�Yk�)��7.���b�����^mm�5�~�$u������������N\�36�QWWB��&�JzU��Z��r������W
�������~��;���lR��Y�&�zk���'o��
�
������p8�������{M���2�y�b1�|>U_s�R��~y���/�25��<���U����,��5
�g���a*���~��W&��o!���%^i�Y�����f���q��~V�`S9q���EWu�����VUU������j�_2�����'3C��������lV��_��)��r9�;;5��������Khg�2���*kD��]���vM����x��N���Mb9���l���������I���[4�:K��d���o���	��^�B�����g�D"��R���J�rY�<���u���a���_###���Tss�����T��z���e$�2��*miQ����6U�������5jWi���4X��`�
�M`9�v���>����L��eM�����TD
�;W�r`�Y�f�'�@9���X�m��#������Q�\.577�d2�~�y����?_���e�Ze�zUs��j�G>U6�W�}J��&��x�^�����8�r9�oK��	���?�Q,���u�Y����,�����o}�����J��o�(�a���Wccc���RSS���]��[T��I�����_��w_��#.5�Gf�Wc�*5��70�JF����}Xh���
�PhR�XL��R��<M��}�'�]o<G7~����
����/�a�������������xJ����k�����B~�g�/i�$���*�����D`k#p��[�3�cl,��������
�JJJ�[����S���Z2Xt���0C����F����Q4Z�������������t�u2PC0(���twg���e�?(^�����v���FG�z���&'
���t��U:p��J�%�ut�7���Z����������	m��]cc.���c]��4$)�`��w����I�[u�����B�Q�:thTN�Y�XN��Z�k*� s���hl4444��qCfs�*+�����@ Y����������G~�������z�H`��I>]v����D411���Z���C�PZ��.�����zI=z���s��!l*�$���9����������s����C�F����n�kf����W����u���x��}�����������/}I�����O������<����r�@@��n��/�P.�Uy8��{u��e���9=�JG���yuuu)�+�VW�]>��j��
�u�e�w���;��PipT�__#K�y5�G
�g�{��2CC�jk���m��m>�$)
�9^�g���.��qY5�}��X
_�9���0�M$����_��U������A�}mTf��RJ&��&?�<���bG�H��,0��Q�������,�������4yN��W�r9uuu)�Hhb�F_�rJ�����~������n����g��Ug��U�%��v��r����=�\,&�L�~�;j�����������}Y3�cG�h���dq8�
�;rdC��
���3`!�����Q}�S?�k���L&C��?=�;z��ur�,�����������Y�=��S2$E|p�U�f�]�xB��S�\�c�K�p����r�@ �_���6���������e������U��w�?���%���_�5�G�dd���b�a��p(��*q���U�v�������7�B�'����"�O����������U�t�j�S�!��N�yg��W�{Ves��A�b1�IR.W*�7�v8����F�PH���F/�m]y��t����{��8H�/��W}}1�b9������s�����M~bP?}n��K���*��T>�M���`T������K�����JjjT��i]���>��r��,^�������o������=�����n��J����Iu�s�sw����^�����=��������t*������8���j�����,-�b���8H��/�0���	E"9�����Oj����A}[�kNo��w�������d��rM=���n�v|�sV����?����9�����
�����Q=����
S!9�Y�r2kJe���2��s�\�S?�
`���y93�g�:!������y]~yJ�x^��E��V9���9�+Y��<p@��G%I��������g����x��n���@ �{������R��*+�$CR�V�>����kYE,�j�K��D���DO?=�LF���z}�K19���^0��
Q��J6��,�����Q}���_R�p���uz�����Y�K��K�v���j6�@ �#Gb�4�����������������z���������������+��Mc6�
b9�
��C�R���zU�_Nk\	�S!����f���F���u��������[O=5%���Fu������|f�pCZ��I�~u�.�h�����R��lF��rf~�������J�X^o�=���lVn�H��65�w�j�X`^�`J�XN�Y����u�I*�R8VKK^��O�C�@`�10���h!60��o&,��}Xj��g>��<��4�)�+����.��{5VZ��{ib�E�|69���iI��^�)#NV#��>���c���_��6I�a{(R>����QEE�����::f��o����t�
LW_!����0�l���M����1��S�T�����49d6K���l>,�����������t��au}�C2$��w�Z$��.�O~���f�.m�({���>�R��$)�tk"��G:���}57e��53�(������x"B}���p�l�|�9��=?W�����
��2aI�!�L2dQF����~��+|l>,�b�MN���<��C��s��E7"=9M;&C���V*��������Q������K�.��"I���zE�G���$I�*9��S�jn:��������zjR�E�PJG��V=�S	'�
b��O:����^���C�&_��<jU�L2$I	�t�������{������L=��q]���TMV�O��|�������pn��_#���T$�L*�����2���������r���S�PH�HD����u�Tj�����:������{����l`�:f�d���H2�|�i�SN��#1������)[�=N+������1����S�	�r�%���~C/*�2��Q����i|��:��_����m�B�lX�
�f���GU?I�)����R���y��V8�x��m�}���G��g����%1���h���H�5�������efM�m�$Y3�jR���s��jn:��g����hNO�$������?����@ ��*J+Ji���
��V��
�+�
��_����t�xD;�/�2��rhB�������nON��3*�T
�x+���$��>��c�T�!��N�X6����p�������J��q����D�*u6�r9��g�x����Ve�K�q�Ej��T���RO�2C�{j���~C;y�UW��v���������`J.�EW]����N���\>de����u��C��:4�'�L��s������V�T���������,������;K�d���'	lu�
�N��T���MM2;�y�r80�c8���F���QY�Y��U����%[�\�U�Y��#�W)�������"�x�9�t�Qa�h�z\M��I�����
��9�'o�{��{��|�X,����3^A��'`mp]������~t�������a��e��_���7U��M����B��]��������B,�r���7;-��bU�����I����W��P�����[ku�=�j���������4�VR��c����-�0�5����8����?��� I�����Ed�����<-����Xs1��@�!p_+����c	�:�#]`yT���2+/i���yI����_��?�Vh�AU�	���$U������d ������SO�$)����n�ZyB9Y�U�,�*�5+j�U[������TIIRm|D��������X+k1��i1��/�������X����c�C�2M���vI1[���m9A���M-�^�^��\mm��T0�\<.��!I��bJ�����g��`J9���Z��x���J����;�o��2�!�e�LyUkl-\)U6�5��GW���R��������??����viz�LV
j��}���-����s����D6�O�C�PH&I�wv��$��'u��y}�����&���O�����4i��35�a�K��R��)I�TQ��k(~��jR����i9#2�;F`+!p_�}t5���C���W�c��"����t���f��s�n��o�w�^f�����4���Q�O?��m6�M��S��K��~E_J)��k��V�J�FL�R�eL�sv���wh��j]|��Qzo�\.���7\����+�	������>�4z����?����|����U����-q-
+P`'ol�����*u���J)+�i����J�}��rh�����?��du*�1)v�G�c]�_=1�++~"I�V4���9#j6����\�M����}���l�K��=.������de�����
��������(�6��'�Tj`@2�$�Y���lV�x\c��������TGeu�(�s�L����`TGMQuwg�mW��(����\�9#j6��Fd.�>[����k�	h�'����UF^������$K��?��(l��C|<�H���4V^��m�����a�_0��V%M6�����#��������4�c�~6Z����$Ce��u�����3�����lE�k����%�ez������������������'��U��l;�����3��X}�@@�`��0|ppP���r���_�����M%�S��S��^�l�����k��JL��TV��s����|rH*-5k��r�nk�t~a~�e�oD���`�!p_C3s
GF�����a���������J��a�N
����_"�����+��x&K[�"��1�3��e{��488���!9�N��n��fe�������2]]�OM)�����R��TFlDf�d�y���Who�L�XN^�E8��G@���!���g���zP��!��T�2��������!K�B�w�k����w]�������l�8`�"`q��H%J�l^�R���/����*��g�-��_]+���������G�|1$S>#I�'�*/3���o��PF�k��u�[d��u��O�l�k���[>�2+�R��R���+/��]�R��\�l~��omS6���]:��/��L6(w:�Tf60M�B�F����Xt��=z����H��W]WL���j�oXF>'�����$i��o�y'�e?��_���3!��I��!p_e�Gu�XB������.��7E�KJ)���z��N���o�����*5����
�����"�����v���g���[���j5>.��Y��������.�(��T���I%�(������j�'>��&�'���Fs��*��'\��t������?=|X�c�T��\mmk�=�
��*:|8�o����O�k�bv����v�W:_���n����7������K��X��.R���U��OK��R���X�����JW�'�1.#m(����IE��z�v�"������Z����>���{���G�+�����)��b�����{�t��rYVt�j�>��}H�����S�D� �U���/�}#!�r2N�ZZV=�����gs�P�s`m���3!�B}w2���C�*��W����n{����I
h�~j�DF\f�d���LJ�JT��k���{�f�~���d=3���}vJ�!�z3��C��V�I�sO������^���]m�c�dH���JE"J;F� �U�����U��M'�nH����M��� u[�r��DVw{�R/��\^���?�&��9�U^�6��b�+9eWL��TTr*i8��4���l\v=3���������r������/��g��,�:?L������(�)����������5r�}JE"2�|�-���q%�E�)��_����D�)��^�Y�W��Tq,���V����6�����/iWE��O4(������������G�P�r���|^�%M��&�d������S5Q�J��z%J���moR2P*���[����}$�A��|:p���#Oi��_S�Q���J
��sB��_�|6�\�+�c����s���!��S���6�H�p8���s���������k^-��sV�K�Mz���c���j5i���9__�
������.~����%Y"��8�]�T}I7V�����������r�#��T�k�F�M�4�z�e��+v��#�����N����H���P.��SO�l�^Y\.y�������"���T(�T0�����Z��\������{�b9o^lt["p7Y���d�R�@R���/�O&?%l�I�X���������k���SV����F�V�����+Z�,W�[��aI�������%S��T\v�O��%)/��&��z�l��b�����������G�z��U�M*0Q���?��y^o��l7WT�x����m>���B�4{�������3��%����@1�����HZ^�\��;����Nb���-R��~P�V]������|����^[�����e�K}������T��Kr�����%#'��a�������B1M��4R���y����H��������-�����.�c������-�H�����kvwC{��[�=�&��+�g,w�?�F�%wKe�������sT�>�jUd�9���
I�%g�}�6�n;���h	6��@{��!%����>��z�e�l���'��&Iy��U����&gRo�xBMM5�k�B_��E�%Z��%��ZF��w]��	6�������P}�������r��b+�W��`#�����X�&���_j��.����L�!����6���q�,��m���U��
���(?U^����J���=��qR6��~]�	�*�a�������>�����g��6�t���:|8���z��_��{hT���S�f���J����<��V�o���`����r�EW��|��m����3r�>��;��g,j8P����������	�e�22��cCRZV������w���>U�:K������jOy�7��ti�t8�?�������$u�HL�t��s]��73}��++�����M������"p�t����7{|���@ �/��������2����`�~}���X�l�@R�����<��YdVf���e�IyY_������}�-jks�{�d ��]�p(�d*��o�)�A�PJ�hN�HZ��+�e�����[O=5%���Fu����D���������5�����X����������MKZ���?�����keS��s
I�%�zO�g�U.�E>�wt��U��j��(U������������E�E�����'��'z�H@?},��GwhG�W���j���%I>���q=�]�s�HL�PR%%��dV 0����FGs�~��m[�|0���n^��}����q�bK��x~�fY�|>�$)J�9>|8����^�q�fU)q�y����Ro�D�I`�I���Gg$y4�
Ui��q2��X�o�]jP�r���b�K,z���~�����d���-���=jR*e�A���H��&��g��\.���<�t?6���HV�a��b�s����[��L&��H�xn�q4gj����u�bK�9ut��2*f��oW{{�������>��.}=x������Uo�E�I`m>��c	��_��6�~���J>��.Q���q]��y��I�u����Ua����:���vO=�/�����/���w�{��s[���U7+
���Y�����:v,����zz�r8,��l
Sr�,���*}��2C_\��(����$�C�f5{���S+u�|����q��a���c1[�������,�����s�v�_�D_^�i��0YT���gWZ|�$g&H�����~��d�0L:~|J����;��?�5krJz��Q����Tb��]���C���X����n����>�X��dt+hx$I������������{�HL?lV���\V��z��1e2y�L&�u�M�E�`J�G���&��l�}�PRb���������I��BRuuV�zk��~���,�/v;:�����SS���L.���C�Xix�b,�%�Lfz2��j��|�����#W�:��IS���Um������<����z��Bz���9��*���eH2MIqU�
��J��iF^�O*�$[��h�n���\��lHc�u�s����$���oQ �������P]]�z{���d��f�0����$���[�@R�������N���<�UW��v��+_��xV��'55e����_�s&����WT�%/������t�sc�-�WV.�x��\8|8�w�b�12�r���}��5���o$
�����K�SnoR�I}j����|za�93�g��{����tK���!��Y&uk����[}�MRz��_���jkK��#q��bJ��488��LR.7�G����"��l6)���LNJ_���FFr�=�XB�}m�2��**�J�
gf_SH�/�9��|����$���\.�Nr:�9������5)�����A$u�]����?���?�E���1$=��4��C���kNi�NI`��|6���z{���P\W��jT��#d�����j4.�����|�_���-������:�������/����r�aH��o#
�2�Z�79����LF2�M���D�d���-2�&&�s���@F%%&��6E")I&Y���ge�����<K-�9�����?��x=3����,�["p�ML���C
��������;r$���'�j���*=�����~A�������o��?���|$��)c��.�1949��K'�������B��/�.W�=����5�z���������W4�Se�Y�������m��
�3��L�fMz�+�H����lN�������JJ��ZMz�����o�)���W��o���Fg��w�{����m:|8���]�k����ih�����nx��`k����:=�=*,�)s�&����a�1](�S_%l
l������yV���A'�9�L�>=|ezE�kv����F���G�KU5X��#i9���N/���*��K(��7s���R���?�G�ak�^w��j=�wN���������jks������#1]~�S��V����:v,1�uI�������������H�z��oU4���}�
�Rz�������yW��%=������W}�4�`�/���{����(��sr��u�����}P�������������r�f{���K���v��O*\���a�d��Gbr�,������'?�8�xC�����{ddS2�Lr�cX�_��m����t�m��������6�i����D�n�Z���Z���JE��z��)I����-�2������m������V���3|D�f�KuT5����>���vi������v�\��wC�L2$�'�U[��`�G�D^��%��r���/8�;��#2����d���(��_8p���%w#�����T�t��o�������������a�1�e�@�G��{�~,�����G�j@-�R��K��3*���zB�*���^��n�,C%�w�������S���*���t��s���y�����e$��$����|����m��=c�H&)
��_>�;�w���}
IU^�w��k
���{'t�O���!iD�t�_v�~���e��M������z��r�9}���W��������n�$����'����~����ck�Si=���^�H���^��6$�\���PGG�.��!I�zm
�R
S��:*���4������v���Q�W^f=]�:yS�����3���O��~F{�������������8�Jz��eQV�1��l��]�zT���%y�sg5.4���*I�u��M�%�k��w^RRv=��&G�6�J2�$���L&9wyu���,���*����?�������;w��[nQ.�[�������/��N�L���O�}�u6`?p����]}
�d�U��^^9��X�&�yI3��7���~�.��|y�69��f%K�4e��`�^������`��H�|>�[n�E������w�]�z�������o\��4����tc���&
\z�n{����l�l�D#������cfe�L�o2�e�y�JrSri\�M����^v�F�y��j{�v��F��O����Scc�v��-I����u����j�
ISo�m��������wI��������/���FH�@��@~���|\?��a5{��+��J��n5����MS2%'e��T��&���T0���z�����L]����-��={����H$rZ���9�c�%�:$Ijho���W2P_G���fn���������A�N���|����\?��i5{yCRF��Yi�*]V���[�����"�O
�
x�\mm��d�.����]�n���9x��<8{< �]��1����d./��������p(�+71!��:��x<�����V�2C?��E�N���(���s������z���|����z]�����2\������ke�^+��Z����B���V�����q{��K3J�
9�Ro��I��O+�1T���%��>���6Co���V���2\������ke�^+��Z9������]��v�������Rss����q����;f�w�������[���le�^+��Z���q�V���2\���z�D��k���2\���z��le�^+��Z���q�NOq-��t�����{���~������
\����`�+���b��+_�����w��������o��o�,K���fWt#e$�Moz��>�p�GR�<\���z��ke�^+�5[���p�V�������-���p�V���r\���z��ke�^+�5;=&c9;�E�H6"wV�����j��=��s�n���r�B�T�G{����}��o�>=��S�����K;w���]����������E]���>[�\s������:��}��Vss�JJ�nm���h�s��|���?���N�����k���ZOO�.��r���Kox����7���}�s:����s�N<xpY��H$�7���:��s�g�����~�����^<�v��Wj��}��w����whbbB����w�x~-��;����>�/�%��W��/�>~e��W�>~e��O������z�udlb�\�8����g�y�0�x�;�i|�k_+pU����jD"�9�}�{�3^����l����6�n����0�K/��x����0�?��?4>��O-yN����~d����e����F�S���^?���7��������~�q����a4n��&�0����7v��e�b1cbb���s�=������3�0R��q�e�����y�-`���sla����������'?��k�]/�_�{��G�����������Z����^~q��+C�2��+Cz��W�^~�������{�1��������o��XQ�����~���W���������0x�����p����c���������x��5Z��b��F��rSSS�aF<7���
�0��������?>{��������{=g3���>d����-��e��^<�������n�����>��kN�^<��L&�K.����w���}�\���C�2����>~e��W�^~e����^~�m��2���r����---�D"�������k��}���>�L&���Y��m�k���h�\��������t�������$������Bv�]�TQQ!���h4��uY��b7::�o�����+x�-���K�9��k��Vuuuz���t��w��Z���K����O������U[[;{�/�%����_��Z9~.�>~e��W�^~e����^~��,}��eF�K�0~����v+�H��o�g>����b�m�]���F[��]x�����Tee��y����o�#�<"����9[�z��i�����?�a��~�cK8�z566�[����-��i�|�����7�_K8�z]w�u<����_�J?��O�g�gsn�����sb.z��������_}����������/�|al��n�{�;*]]]jnn.`E�3�NSEE�n��=zt�������u�j�t5��b�l�������$���G�^z�~��_h��mJ$J&���D"�t:-�����Z��b���t�
7h��}����[�|�����JKK���������kN�^<�����X��������Q.����Qmm-�/����s.�^~���2�\}�����>z����_�|������%��^�w�fK���P���_<7���a����[n1>���?����������	�0��K.����'>�	�0�E��,N�e���h�s������������aFww����b<����a�
7�0g�������a�s�=w�&%/�����������M7�4{����b��^<��711a����1=���[o5���y~-`����kyf������D�
z����_�����_�����_z�3C/�>6u�n�������9��c�|>�}�{���d
]��{������?���w��{�n���o6��a��'��|���;������_�����}���;wo���4��S�n��V�����d455���X�k��9�f���w�w�������?�8�������o��]]]�e�]f����x��_otww�~�����q�Yg>�������e�Sl}�QC�q����^��}�s�a���B�����zzz��/����w��g�������;�Y�_]/�_�sb@��k�>~�����W�>~e��W�>~���W�^������a0h�3��g��^�X��wV�;����*>��O���^V��0��E�_II�������f�*))Y��,�<�V��SRR�O|�:���u����������j�}�����;g���}H������{����G�TJ���o}K��w�������;O�����G>�\.�}���-oy�$�W������7���.�e�]���zJ���O}J�~��u�����+�X�)zy��X�[��d�����w�������}����~������Bg�}�y�y<���h��m��������={t�m������C=���MMM�d2�n��Y��d����^<�����t��1}���O�S}�S��7��M���?���(���
�<l||�����k��V��o�>������F�������x���|G_���L&�F���%Iox�����G�\s�~��]---�|���{N�<��������6:::��W_}5
:�������a$���+h�J����.��on�
�r��K�/W��V%'�3Bt��c��?|�{xxy?�C�<���p80�Je��b�R������z����[2�Ns||�����f�$�p8LY�yyy���mF�Qnnn�|c�����$����=C���;��L������7��"�Z-�f3��*OOO��|>O��NQ�����z�����$��k��e&�I���^��?��,�_
w�9??O��I��J������vVE���ryy�������'I��~������R�V�����`�������f<�k8�<�~�i*����
w��;���v�?7�x�7�tIEND�B`�
absolute-all.pngimage/png; name=absolute-all.pngDownload
�PNG


IHDR��� �L9tEXtSoftwareMatplotlib version3.8.3, https://matplotlib.org/��XS	pHYs��7���IDATx���yxcw}���$K��U��M�9&��%$@�~��L)�!_(i)�@�������Z�'-%@�C�.�����m���*B.���h��j�%Y�����;N��3c�H��q]����#���x�~��s\�m�g��t
w��;p�n��&�\.�qZ�n��
w��;{���=@����������z��^��=�i������W,�e�]��������\.�^��J�n��;vL�PHn�[��%I���w�r��r����N��;�����}�/~���-oQ$���S8����6MMM=�cOLL��~��t��������+����}�����ibb���@��8p�'?�I}�C�$������K��L&�L&������'>�w����{�{�����^.�K�`Pn���+��o[�����|>���N�j5MMM��o�m����������cn��v����T�T�$y�^���+�N+�N��{�Qkk��/�f��hJ###�����?��?������e
MNN���|�$���~���������P�_�����jnnN���Z[[�����=�����z��_������f�Z[[�W��uvvjzzZ���1o��U*�t��1=���������
��|�A}�C�a{��w�����{��{����r�4M}��P�R�
7��n�A7�x��f���z�������n�6���X,���u�����[o�<����U�{��477�w�������/|��x��a~~^���/%I7�t����7��������y����9�F���6^��WH�����n��������\�{���]��U�z�$�P(��?������������9��@��p@���������/T0TKK���D_���K������:��s
���~�W~e��GFF6?_^^��<�%/y�$�e/{�>����{�������;�������G��c��~��)�����C�PH�������$���x��*��G�X���%d$�\.o�w��7��x��g�gz�s����N=�y��G?��-=�L(��t���t����T*��/~�����h}}]�LFsss�������5�����8����F���H�����w�����U�����_�\s��9�������1��ES�tn��6e�Y���������������:�lwN=��X,���?�>�Lf_3��n�����~��~M���������:~�����.��2%�I����k��p�;�N*��$=��O��l��;��� #�����H��Z��{�9�8�Y����.��?�yI����x���8��M���[�����L�b�1����>�|��k��9�@  I���[��V�������;]�d.�����f���s��1��n-//����555%��2��_���;���^�W�}�k%I���/}��_�,�~�a��5������/�}��w��O�>�����?��j��$��m�}��z���.I
��z����/�zE���s��������$}��P8V0TGG�^������C�W�p�'v��	���(��mf����������o�����=�<�w���:z���~���������.�H<�����t��7���_��F���t�u���_������(�\.��s�����>�{��q:�
�����{����U������������~�����/���}�����~��z����/�P����f����:���u�5���?�����������e���tg��(����
w��;{���=@���p`P��(�����n��&���{�x��w�\.��=��1�@}�p�C�;�������1��O�S]t�Ejkk��#G��o~s��766t����0�\.��?���c����Y/x�����P(�K/�T�t� ^pV�}�?�g?�Y�\.}����W��������^��W�%/y����u������.�/~��]����=�y�����p8����d2z�{��T*�x<���.��u�;��V�=��4==��~��z������	��;��0���|D\p�����k��k����$]s�5��b������G���}M�����_��_W&�QGG�:::���}O�t����W~�W5<<�'Nly�?��?S(����c�"����{=��OW0����l�}����VWW����N�`P������;��u�y��ZZZ����~��~��o��.��b}�K_�����V������������1��e���x�:::����?��?�=���J�r_}��1���,�UW]����������W��;��o�Q7�|�fgg544������$=�����huuU����7�Q�x\}}}���uww+��+���������^��U��5�\���MLL�E/z�����'?Q[[�������|EW_}�~��_J�n��6����n��&-//����z�+_���%I�;�������,��������/>�k����u�y����n�v��������������~WOy�S��x��x�L0�?v�n|��_W6���������W�Pg����k||\mmm����}���V:��o��o+
���E��[�����-g�<�g?�Y��o��^���������[�}�s7�����=�y��^�^���0�w�}��n�AW_}�.����n]r�%�m���j���|�+���?�`0���]}��O�����c�����r��:���^������?���>8��������]}�������]���;��X,������|>�������\��w�������jqq�q'�H��s�}�����[����7�b������O�`p�������������%����{��|;lGG�$���C�Lf��e2uvv�j�n=����_�u���������������c�������W\���	�;��D"������J�����>����_��VVV�����>���m[��v?��y,�r����D���}L����kkk���k���/���%g2���������a���$��O�~����\.o������� �N�w�����������o���c����;����_���~����������O�D�}�k�����(���|�3���?�B������z�^�l6���
�V��_��|���c���4??�y����6�����n��VU*e2��?�U����J��G���P�mk}}]w�q����ZZZ����N��������i}��}��{�^���^}�#Q�T�m����|�;�k4��_�J�����l�V�\V�XT�Z�����������z������5����O���~����_��w����>=�Y���W_��|�3���@=�p�:����Eox�488���)}��_��^�2]z��z��������'?�E]�y����d]q�:z��������.]p����[���|D���z�S���~������W�R�]w��������G�i�����j��$�S���:::�����Xo|�����^����o���oW0�;��N}��_�9�����'_c P2���^�:}�K_�$��_����w�k�[`O=[�o���?�

)o~�|>uww�������P/\���0g�>��O���~��Q�fy����	
w�K��8��=@���p`x�p�������&��akc�Vk�K��.IR�RQ�Z��������	��<��m������-�|S��pX=���1��&&�:qbfs��k��jiiI]]]z��^�`���,�z����D"!��-�0t�l�cI�LN�$I���m�������������DN`7���,�����i����[�7������|�����
�����
{5::*���p:;��rJ&��x<2MS�������Yo�Y���3������!���O����/������Y`��A�f�J�R�z�2c��]j���V�iaaA�LF�j��8���)����:�������E]xaQ����D=C�rY�TJ�R��(�9�9�LF�TJ���2M�	g��-�S��\.�b���^oS��c������J�466�t��Q���N���f���������?�K*�Rgg��h��#s<�sVWW�N����d��'@4e�n�����u�����8���\.���iqqQ�m7�'N��jJ�R��rP(b;�m�T*�0��n���xg���hjjJ~�_�a����No����f�O�pppj��������B��B�����f�k���8myyY���
��b�*�%���:��g=k�s�0t�y����������x��d8S�jU�DB�|^������s<������Y���������z�����[������
�����:Y����kxxX}}}NG�>`�8|5;;���6�b��^����4ML59Y���O���=yL���J��'�gU�UY��B�������:	b������5??���v�b�3Z����4LLu��������{6�����|�l��+^�
}��������JE�e�X,jttT===NG�����l���������h4z���d
��09Y�$��o��^�����{��W��������/��/��9��*����������0e{a����m[sssZXXPgg�Y����i{d@��K[��R$�$�����o}�����=��r��x<�R��H$�`0�t$��9��m[���Z\\TWW�Y��K����q�����OZ[[S�ZUWW����n��=��O���������eY*���F����r:�9�f��fff������n��a�\��~\
��4>����%innN�\r�j���������������s��mll(��R�(������Hx��8��mMOOkeeE�`P���{R�K�u�R�H����t�}�9�R*�dY�*��b��:::�����xl�V:�V&�Qoo������l�(���V*���U��d������`�m+�J)�����OCCC{Z�K��i)�����m[�a�����HvP���J�����������=/�%
w`�
��,��$���@ �l ;��jJ&����P(���]�pve}}]�e��r�0�v��j5%	���)
)
���Q�;X[[S"�����a���NG��j��D"���u


�������x�|^�dRn�[�i���9	�N-�������w �K�<�|>�D"!��#�0(��P�VeY�
��FFF���{`�M�l#��)�L����4M���:	�*��,�R�X����zzz����lx����O��{�2��j��^����_��>��O�9�y����g��o}����$��������,=��O�+^�
���J�>���Moz�^�����s�����>'_@C�f�J&��z��l�c0���J��x<�b��p8|�e�D�~����v��{�x�������������>�1E"�����������@?������u��7�T*�
ox�>���������_�b�����|�x@��O���������[���=��L2�����Z[[e���^�������r��x<�R��H$�`0�H��9
��	��8��=|�����g���G��������u�}��O��Ou��w��.x�y�EMLLhhhh��+��B����8�x�+$I����,K�p���4���U��i��~�!��q�0`�8�666dY������������O��49)I���J��J��{2�g�Y�����me�Y���w��]��?��-������l�\�-��^����E�J���4���MMMQ�B����������*�����:;;���2��76&I*��[���������+��G>�]~��z��^����������G~����z������Y�w�}��/|�z��_�'��������d�&e�!�p8�J%MNN�R�(�9^�K��~Z���>~\��I��������o�Y333z���-������<�+��R/x�$I�G���'e��n��f���o����������/�u�f������Y���)������H�c���O�X�eY��j2C���NG�$�l������=��zhs��mMLLh||�1o�<����<�����������X,&���7�>zf�#�����`;�bQ�x\�m�0���9�����3��tl������������h4�h�`w
��,��$���y��zA���b�����������NE"�v������,�\.�Qwe�D��&b��fgg������.��a�v����)�H��v�0��~�#m���Z��t�j�%��e��fff������n��a��n`�m7��s<hf�|^�dRn�[�i���9�q5e��r�������)
���6��n������������d���������`0���Q���r�������������sd��,��)�L����0��.��&-�%)�haaA�DB�j��8���)�8�������)������G###��
.�(�Jiqq��(�94�l6�T*%��#�4����t�5m��v�588�����z{&?\�fb�����2��z{{5<<�<tx�^���1�b'�v��+�4��z���+M[��������jJ���f�������s�!��'����d�J����dF����;�Z��T*�\.����B!�Y����hjjJ~�_�a��i�
���;��jJ&����
�B
�BNG�������n��]�p�!R���H$������A
8	�.,--iffF�@@�a�����Hg���B�ZU"������������t$�������Y���)�5l�.Q���V��,K�BA###���u:�]XXX����������v���tV(���*��,�R�X����zzz��`�mk~~^���P4m��]�p@�T*���*�J
��
�NG���577���Euvv*���]�p@�*���,K�RI�HD���NG���5;;���%uuu)��]�p@*�����*���F����r:���(jr���1����N�a��fff������n��a�\.�c�)
w4���
��qU*E�Quvv:�	MLu����������h:�mkzzZ+++
�=te�$�s�p��J���=��}�.I��%I�i��l���mMMMieeE===��l�8�
�d�^��d�������+cc���xi�6�l�V:�V&�Qoo����m�.Q���E��q��-�0����t�]����a�p@���jJ���f���������.�%
w��B� ���l?i|�O���R���J����400�P(t��v��ul}}]�e��r�4M�#�A�VS"�����B��B�����;����v��3��zW�V�L&������A
8�@Q������)�H��v�4M�|\h�w�jU�DB���V__����;�J>�W"�����a��@�V��,K�BA###���u:�#(�P7r�����<�L�Tkk�����R���,�E��������H��p@]�f�J�R�z�2��h�JE�x\�RI�pX�`��H��p��2��R��|>�����u:���eY��R��H$���n�#9���Z]]U:�����i��xQ�z���!��T.��F����t���O3p����������ee;�666��U�T�F����t���O4p�������d�ZZZ��`�RI�e�R�(������Hu��nqqQ���jkkS,�l@�X�eY��j2C���NG�;�8P���S{{���(e;�������l��ajkks:R]�p���������:::�F�v���`�BA�eI�L�T p6P�p���m[���ZXXPgg�"�e;����eY�\.���l��;��m������������)������D"!��-�0�����T�(��ol������������p8,���t,;���J&�r��2MS>���H
�����mMOOkeeE�`P�����@���J$�x<2���4P�`������)������G###��@��rJ&��x<2MS���NGj(��S�m+�N+�����W�����@�f�J�R�z�2MS^���H
��{�V�)�N+�����OCCC��@�d2J�R��|2���Q�`O�j5�R)�r9
(
Q�
`eeESSS���2C���r���^u�U[�P���Z�s�9:r��n�����|�A]x��:��s��W�Z�|�������(���2��(�x�Z��d2�\.�P(D���������2e�����{�������;���w���~X������w�ks��W^�'N��?���9��}�cg|���DQ'N��+_Y��3OX��j5%	��y
R�7(�x��������i��I����p/�J���k�������r�-����������Q]t�E�������9%�I;vL�t�Wl�s&�`�LN�$I�����h�jU�eimmMCCC8���;���gqqQ333jkk�ajiiq:������������+����V:�V$���F�J�R�{����36�H����l��d�������a���hF��x��������Y���S���={������{��G�����n���������S�p�
���6�WVVvu1>�������,il���q����JE�e�X,jddD���%����9^b��O�mkaaA������P4���/��lZ{��������zH�i�0U�U�����-g�$�I��a���mo��H$r��������C=������W/�i������w?a��)�\=���<�~�m[sss���Wgg'e�>�������vMOO��,Y����Y���.�L7�t�������t�]w���cR$����-I��?�y]r�%��K.������+�����*��D"
�NG�Yb�8�l���������H$B��O����/}�Ku������#r���������)I����k��Mo�UW]��<�)����|��`�,�������������}�p8�����-//���[�pX.���X���>����G��C9�amll(��R�(�n���;�����p�l�����VVV5::J��N�Y��w4�R�$��T�T������t$;�m[SSSZ]]UOO�FFF(��;W�TR<W�V�l�m�J���d2������0e��p�����,��,������`�ZM�tZ�lV}}}�l?@�x�B� ��d���P[[�����V�)�J)��i``@�P����Q�`��e�$���@ �l ;��jJ&����
�B
�BNGjJ�����.���r�d���~�����Z�*�LjmmM���p:R��p�$immM�DBn�[�i���9	���������544���~�#55
w(��+�H����0�v�T�UY��B�������:��Q�4�\.�d2)��#�4����t$;�T*�,K�bQ������q:D������R���^���l@�RQ<W�TR8V0t:��;@��d2J�R��|2C^���HvP.�eY�J��"��������SP�4���U��i�|>��)����w�,K�rY�hT]]]NG����@�YYY�����~���l�������*�����:;;���m��@Y^^�������PKK�����T*��,U*�b1utt8	����I,--iffFmmm��b��@(�J�����j2C���NG��ph���S{{���(e;�������l��ajkks:v@�p����k~~^�����br��NG��B� ��(��;�!e�����������NE"�v������,�\.���@ �t$��;�!d�����������.��a�v�<�l���NG�i�p8dl������������p8,���t,;X[[S"�����i���|NG�i�p8Dl�����VVV5::J�4�|>�D"!��#�0(��;�!a��������������P�
 ��)�L����4M���:	g����m[�tZ�LF����l@6�U*�����a��
�����j5��ie�Y���ihh��h�LF�TJ>�O�a���:	g�����j5�R)�r9���kpp��h���J����|2MSU�a��"@���jJ&����
�B�l����������ee�!��$@��jJ$Z[[������`���433�@  �0����t$�!
w�S�V�H$������!���;	�.,..jvvVmmm��b����;@�V��,K�BA������s:�]XXX��������F)�)
w�Q�TdY����FFF����t$;�m[���WGG�����n����O(���e����zzz��`�mk~~^���T$�l?�(��\�\�eY*�J�D"���v:������Y---���K�p���	P���r��x<�r��h4���.�#��m�������������r����@�P�666��U�T�F����t$;�m[���ZYYQ0���(e{�p�C�RI�eQ�
��mMMMiuuU===�lo2�u�T*)��V�)������Hv`�����2��z{{5<<L���(��H�X�eY�e{{{�����V�)�N+�����OCCC��M���N
Y�%��e������`�ZM�TJ�\N
�B��M����,�%�4Mg�Q�VS2�T>�W(���e{��pp����,�����i����NG��Z��D"���5
j``��H��Z[[S"�����a��@�V�J$Z__����������:A���|>�D"�����)���t$;�V��,K�BA������s:��;�r�����<�L�Tkk�����R���,�E��������H�3�,��*�J����0�v��Z���a�A�#�Q��L&�T*%��'�0��z��`�rY�e�T*)������H�S�duuU�tZ>�O�i��a�]�\V<W�\V4UWW���P��)����hjjJ~�_�aP�
`ccC�x\�JE�hT���NGB��'=�}������i�����#�A�T�eY�T*��b���p:�;�>ZZZ���������(��P*���U��(�qZ(������fgg����h4J�4�b�(��6����v�#��P�����y������]�XLn���HvP(dY�l��ajkks:�;��m[���ZXXPGG���(e;�����H$$I�i*8����`������9-..���S�H��h����,K.�K�i���;	
��`�����Y---���K�HD.���Xv����D"!��-�4������F�p�l�����VVV5::J�4�|>�D"!��#�0(�q�(���m��������zzz422B�4�\.�d2)��#�4����t$�g��m��ie2���jxx��h�lV�TJ^�W�aP�c�P�����J���f������!�v�d2�R)�|>�!���t$"���V�)�J)�����_�����@X]]U:�����i��x�G���?
�4�j5%�I��y
(
Q�
`eeESSS���2������v�V�)�HhmmM���p:�]X^^�������PKK���pHQ��B�ZU"������������t$�������Y���)�Q�c_Q���Z���,

�����HvaaaAsssjooW4�l���px�JE�DB�BA###���u:�]�������������v����&@��8*��,�R�X����zzz��`�mk~~^���T$�l���p�F�\�eY*�J
��
�NG���577���Euuu)S��@Q�<J�\V<W�\V$Qww������m���hyyY���
��r�\N�B��p8�������*��"�������`�mkzzZ+++
��l�#(����e{4Ugg������mMMMiuuU===�l�c(�$�J%��qU�U�b1utt8	�l�V:�V&�Qoo����)��(
w�����,�R�V�ajoow:��j5��ie�Y���ihh����pM�P(��,��-�0����t$;��jJ�R��r������ e;��;hZ'�vI2MS�@��@vT���L&���
�400@���A������,�����i����NG��Z��D"���5
j``��H�������)�H��v�0�v�T�U%	���khhH���NG��4�|>�D"�����)���t$;�V��,K�BA������s:�-
w�4r�����<�L�Tkk�����R���,�E��������H���pM!��*�J����0�v��Z���������H��p�^&�Q*�Rkk�L����u:���eY��R��H$���n�#;�p��������|>�L�������r��x<�r��h4���.�#��O���ZYY�����~���l�������*�����:;;���?u�CiyyY���
��b��@(�J�,��
��<�����������)������HvP*���U��������t$��Q��CeqqQ�����@)��,k�looow:pF(���1??���y���+���v;	�
��,��m�2CmmmNG��;hx�mk~~^���P4�l���]�L�T p6p�(�@C�m[sssZ\\Tgg�"�e;����eY�\.�L����w:p�(�@��m[���ZZZRWW�"��\.����`mmM�DBn�[�aP����p
��m���hyyY���
����@���J$jii�i���|NG��;h8�mkjjJ���
��l@.�S2�����i�jmmu:��(�@C�m[�tZ�LF����l@6�U*�����a��8�(�@��m[�TJ�lV}}}�l@&�Q*�����a�z�NG��;h�ZM�TJ�\N����l�������|>�L���C%�����@���jJ&����P(�l����������ee;=�u�V�)�HhmmM�PH�P��HvayyY���
2C---NG��;�[�jU�DB���R��������fff����X,F���A����e���������`477���vE�Q�v4
wPw���,�R�P����z{{��`���5??���v�b1��n�#����J�"��T,5::����#��m��������:::�F)���(�@��T*���*�J
��
�NG���577���Euvv*�P��iQ���P.�������H$���n�#��m������������D�r���8��8nccC�e�\.+������Hv`���������`0���Q�v4=
w����
��qU*E�Quvv:	�l�����VWW�������v@��A�RI�x\�jU�XLNG����N���d������a�v��P�G�EY��Z�&�0����t$;�m[�TJ�lV}}}�lNA�\�XT<�m�2CmmmNG��Z��T*�\.���~
R��B�T�P�eY�$�4�
`G�ZM�dR�|^
�B���6(���Y__�eYr�\2��h�ZM�DBkkk��������E��������n�����w:�T�U%	���khhH���NG��;�w�|^�DB---2MS>���HvP�VeY�
���������t$��Q��}����L&��xd��Z[[��`�JE�e�X,jddD���NG�;�7�lV�TJ^�W�aP�
���}ttT===NG�;��LF�tZ^�W�i���:	����,�R�TR8V0t:�P(���[]]U:�����a��@(�����*���D"���v:�p(���ZYY�����~���/~Q������|�;�6666��U�T�D����t$�!Q��=������i�b1���81�����aJw���J%Y��J��h4���N�#
��tp8,--m���a���hr�$I2M�$mn��Ri���X,F��%�p��ML59Y��%Y5;;���6�b1���H���)�����m�+��,K�ZM�a�����H@��p��ML�~I���������]�XLn���n|�������@�)
�,K�m�0���9	8(��c�.���49Y�����m���kaaA�F�[������u�����d�������C���:V�K������9-..���S�Hd��@}Y__�eYr�\2MS~?'�{���:V�K������Y---���K�HD.���Xv����D"!��-�0(��}@�@���%Yl������������p8L�4�|>�D"�����)��>�=6�`Wl�����VVV5::J�4�\.�d2)��#�4����t$���p;�m[SSSZ]]Uoo����)����f�J���zee;��(���m[�TJ�lV}}}�l@&�Q*�Rkk�L����u:p�Q���U���J����������A�v����*�N����4My<���A�o�V�VS2�T>�����B�e;�VVV455%��/�0(����6��ZM�DBkkk
�B
�BNG�������V P,�l���jU�dRkkkR��������fff����X,����#M��l�V�J$Z__���������`5;;K�8��Hz�l�,K�BA###���u:�]�������������v���4-
w�J�"��T,5::����#��m��������:::�F)��Q���*�����J�������������m���iqqQ����D"��@�p����eY��R��H$���n�#��m������������D�r���@�4���
Y��r��h4���.�#��m������������)��:B�@���P<W�RQ4Ugg������mMMMiuuU�`P�����@������;���?_O{��t���*��J����Z�s�9:r��n�����?������u������~������39��T*irrR�JE�X���$fy��m�J��Z]]Uoo/e;P���p��������O<��������z�q����������������wm�W^y�N�8�����:r��>���I�vV,��U��d�:::���N0�P�l�V*�R&�Q__����)��:�������j5�E�\.�r�-����������Q]t�E�������9%�I;vL�t�Wl��r&��'��������H��<��V�)�L*�����_CCC��@���]�^���(
����{����iE"����hT�T�qo�tF���W(��%I�i�����D��<��d����400���A�v���y�~���jzzZ�pX_���e����{���h�s�n�AG���XYY��qF����e�a
'P�����ZM�DB�|^�P��h{^�KRkk�~��~K��z�"���3W�����������K:�cNu�UW�����������	@�[[[�eYr��2M������p^�Z�eYZ[[����B���������\N333��
�7��M�w�y���Kt�M7�Z�jjjJw�u��;���!E"}�[��$}����%�\"Igt�*��+�Hl��~���H��<��d�������a���;	�i����r9��U�R�TR�V������O��O�����o�]G�������_���NI�_��_�Moz����*=�)O����eI�K_���>��\.�d2)��#�0�������1�P*����
��FFF����t$��e�v1�v��Q=��CN��@�Z������V�#�f���u4�J�"��T,5::��j@9uf��3������R���^�L����u:���eY��R��p8�`0�t$g���C"��(�J����0��-�'&���,il���q�u�T.�������H$���n�#8�+++�������a�x��'~b��'f6���t���!��T.��F����t$g��tpv���wU�K��dI�d��-�������8e;p�p�;
b��`���433�@  �0������16�H����l88�RI�x\�jU�XLNG�G(�h�-������������v,�%i|�����Y�pH�X�eY��j2C���NG��(�h�.��t��sz��rjooW,����U������������l��ajkks:�=F�@�n��S�\�er��R�����::��FO�l��B� ��$I�i*8���p�a�-���}|��k��8�������nE"�v������,�\.�A�b����N].���S���`pU������R�
bmmM�e��vsf;�8���\.&/m�>��m���hyyY���
��r�\������J$jii�i���|;��Q����q���v
w��5==����A���R�
 ��)�L����4M���:	��p�����n�m��������zzz422B�4�l6�T*%��+�0(��&B�@�m[�tZ�LF����l@&�Q*�Rkk�L����u:�D�@���jJ���f������� e;�VWW�N����de;��(��#�ZM�TJ�\N
�B[������k�p����������e�<j7��7�:Q���L&���
�
�����(�����������t�����������(��&��~�@�ZU2�����500���LN�$I��S<^��d�q���-�����%���(�0���8	���N��U�U%	���ixxx��]���|��x��e{;����n�;������Q[[e;I�������,�R�P����z{{����~?>��ebN��p����5??���v�b1����
���T*Y��b����Q����x���WK��N9`�l���������h4J�`�;�T*���*�J
��
�{��-���m��������:;;�D(�lA��+���,K�RI�HD���NG���5;;���%uuu)���r9@��p�mll��,��eE�Quuu9	�l������������p8L�`[����
��qU*E�Quvv:	�l�����VVV5::J��qQ�pJ��,�R�RQ,SGG������m��ie2���jxx����p`��J%��q�j5����v�#��m�J�R�f�������e;�Q���������l��ajkks:��j5�R)�r9���kpp����P��O
��,��$���@ �l ;��jJ&����P(�l�k�����uY�%��%�0(��P���H$����P(�P(�t$
���=����D"!��-�0�����`�jU�DB���R���4 
w�P>�W2�����i���|NG��S����a���9	@��p`���y%	y<�A�4�j�*��T(422���^�#h`���\.�d2)��#�4����t$;�T*�,K�bQ������q:�G��Y�f�J�R�z�2MS^���HvP�T��U*������p�,d2�R)�|>�A�4�r�,��T*��D����t$��;ghuuU�tZ~�_�a����U��mll��,��eE�Quuu9	�!B3�XYY���e;�@666��U�T�F����t$���iiiI333
2C---NG��R��x<�j��X,����#8�(�8
������U[[�b�e;����,�R�V�ajoow:�C���]ZXX����������v���`�bQ�x\�m�0���9	�!F��l������������h4J�4�B� ��$I�i*8��G���m[���ZXXPgg�"�e;����eY�\.���lp (�x�mkvvVKKK���R8�l�������n�����w:�&A��6l������������p8,���t,;���J&�r��2MS>���H��;�b���������`0���Q�v��r9%�Iy<�A���Q�p
��555���U���hdd��h�lV�TJ�G�i�����H��;���m��ie2���jxx��h'�v��+�4��z���IQ� �V�)�N+�����OCCC��@�d2J�R��|2����(�M�V�)�J)��i``@�P��h+++�������a�x��8��B��V���L&���
�
���`���5==M�������j�������488����#����%���(�0���8	$Q��T�ZU"������������t$�������Y���)�Q��+���S�VeY�
��FFF����t$�������9���+���v;	��p4�J�"��T,5::����#��m��������:::�F)��%
w@��T*���*�J
��
�NG���577���Euvv*�P��[���P.�eY�J��"�������`�mkvvVKKK���R8�lP�(��^�\V<W�\V4UWW������m���hyyY���
��r�\N����DQ��%���4>�w:N��pj����T*�F����t:������i���(jtt�������N����>~|�������U*�6��X,F�4��555������P��ar�$I2M��m�pJ'��Z�&�0����t$;�m[�tZ�LF}}}�lN���#E{<^����C�8t������l��ajkks:��j5��ie�Y���kpp��8M��~?>���p*�BA�eQ�
�V�)�J)��i``@�P��8C��~�vQ����uY�%��%�4��`�ZM�DBkkk
�B
�BNG�3F�8]����6�w�jU�dRkkk��������P��������n�L����Ea�zW�V�H$������a���9	��;����y%	y<�A�4�j�*��T(422���^�#���p4�\.�d2)��#�4����t$;�T*�,K�bQ������q:���o���������Z]]�r�7��������������^/e;l����w:�Q�T��U,�)�:[
�O}�S���K���~VO}�S������<��d2J&�jmm�lIG�y��C=��9��\.+��T*)�(:	���%e>�����?��:;;��_�R�y�k433����J�m;��M���J����|2MS���������~����|>�l�����|�~��NG@����!��T.��F����t$�[Z
�����)Iz����;��S������%�\.Gp����������ee;������7�����-��G>��/�X^�W�X��hhccC�x\�JE�ht�{��h��2��������u��������<p��8iyyYSSS
�������������u����R�8	�J���=�Q�8���7�p�c�d���'}��_=�`�������Y���)������HP������/}I����������\�X�eY��j2C���NG�}��p�3����<]v�e�S-,,hnnN����F����/{���������&V,��e���P[[����@�w��#���g�gc~~^sss�����v8C����V(��%I�iR�h*[�p�������m�J����5??���uvv*���������0������,�����a
NG���p�����/�X�m?���L��B��m������������)�`���z����D"!��-�0�����nK�>>>��}�sz�����;F"�hN�mkffF������V8~�����pZ>�W2�����i���|NGGl)������m����@��m�����������FGG)�`���N���J$�x<2��@Ss������9z��z�!�c�m��������zzz422B���0�n����\.�d2)��#�4����t$8p����G�L$���[�J�$I�pX�y�kd���4����d2������0e;��x�A�f�J�R�z�2MS^���H��-W����?�������������s�=W:v��>��O;�pH�j5�R)e2���Q��b��L&�d2���V�v8��%e�9���G����r�\.�.�@?���<�^�m�PN���\N
�B��������u��������hjjJ~�_�a��y�
�T�pI�������m��Z��d2�|>�P(����v8K����������i�vx[�+^u�U�������^�HD��L&���~U��H@@c��(jr���1������_���H$������A
8��x�AXZZ�����������-��;��N���/���������m[�HD���7u���:�� &&�:qbfs����-�{�ZU"������������DL8t���mqqQ���jkkS,�l�������{�����k���$I���
��&'K�$��)/ir��Y�W�UY��B����a���9�x�~YXX����������v���uk�w���9��-oQ��9�#G����Oo~��533�x��$il�'I��K[�+�����
��FFF(�`�1���m��������:::(�`�|�|���g?��J&��������R�����g�
ox�S
b|���������n.'S�TdY�������z{{��	�s<`������9������S�h��v�e��}rc||\����O~�~�����=��z���t���,�R�TR$Qww����n���zX�x�Y�`��fgg������.��a�vx���[�[�����6666o�����>�9
lJ@C+��������P4�l�}��+�mkffFKKK���V$�l����;������;����D�D444�;��S7�|�S
fccC���*���F����r:j����`���������`0�p8,���t,h(�S7FFF��/}I����,�������J%Y��J��X,����#���8[�mkjjJ���������e;���}OPoo������������J�������*e;8�9p�l�V:�����z{{)��,xv��~����hp�bQ�e�V�)������H�����Q���N���f������A�v8;��mD@+
�,K�m�0���9	�s<`'�ZM�TJ�\N
�B��p�v,�������h EMN�46�S,f��,I�i�
��Hb�<�Z��d2�|>�P(�P(�t$8��o{����7����g�=��MLu���$�R��
o(�IOj�i��������8�jU�dRkkk���������r���=�y�����v������O}������'?��<�O�4����$���������?�ill�����j��D"���5


Q���2}��Mo�$��������Ny�^I��W^��/��������OKK%���kr����O��q[��N'�����j�*��T(422���^�#��������%�����J������_��e]xaQ��[�xE�z{��g���x<�JE�x\�BA������O�}����6]x��z��^%I���G����?4��d�Y�R)=��>MN�j}�����|�Hb�l�d�^*��������m{���w����NI�^�����kO=zT=���1��e2�R)�|>��_��������|g�v8[{5��9^b���U.�eY�J��"����������3��^A���+��U�z�������y�4���U��i�|>��)����q/E;�!�x�I�,K�rY�hT]]]NG�Co�5�?��O��o|�����H�fggu���h0@}XYYQ:�����,���9p������8e;�m��|�3�������NI�9������
p�������6�����n�-����������R��x<�J��X,���`�m{�b Pkk��v�V;�@�'&T���olLk���Q[[�b��ZZZ41Q������W����������x����V��0���;	�����3��L�x���T*������O|B/z��:�'&4s��#��*��o��iOS4UKK�$�����������x���~7G�u�9��LL��9�M�bQ�x\�m�0���9	���K�|��W*�����[���������Ag����$�
�X,����yf�V�G�P/�����DQ'N��+_Y��3,�4�B�@�u`�3��~�>���C��A��S�������4U,T�����xy�s�vo����w�_�%�\�*�l���$����29Y�$��O�xI��%�r�����,�����i�
NG���m������}�s��8�_�����S�����k�U��G���u,/k�9�Q����9n|������u�S���el�'I��K[�4��e����a�����I���~����g>S�{���YJ��N.�3M''5��*��%�O~�������~��q?E;�)���2>������"hbkkkJ$r��2MS>�x�m[�g�Y}�S�:�,���$''U(T�f����T��/4')�����u��?>�lP�ia�o>�"h^�|^�DB�G�aP�@�����/�X��s�Ag�����n�-#K����V���D�7�Qj�T���!wG�����Y�����!��m�����e����{�\.����>��O+�����m�\.��g?s*'�,MLu���$���7����/To�z2M}�*Y�\�ZLs�,x@�c�����f�J���ze���^���p@&&�,#4�-��w��T�>��|��j�����dE?�iU��!


�52��u�)���J�:/���d��0�@s�d2J�R��|2�����z�$?>L���-�{,�$��g?S8V[[��G.�1==}��{fl�'��|pY�JEO{Z�#e��%I���S�@�b���ouuU�tZ>�O�i�����|8�N�@e�>��%MN�(��:���ox����������.;�P��51Q�/~Q��^T�K^R�5������7�v������������~?e{�{d��x��e@���;t�Z�2����jcc��B���DQ����]���Do��s����#N���x8|���433�@  �0����t$8`|�����Y�h������������=O����}O]]]p��*MN*��z���C���O���66Z�{ "Q���������fgg����X,F�������@��p��'?�K/�T===�m[�LF_���:�q<t��5�?���������e_qbB�~X�I�~�C
�Z�R)�g��^�jJ���	�W��px,,,hnnN����F���� �-��?�|MLL����m�g}0���c����!I��%�n)���;�A\��������.yk%����v������a����m-,,h~~^�F�r����m����c�x<:������>U�G��;�l�mL���$I���e[z������������	��"qE��v���h��?���+�xhl�mk~~^�������l����.���[�����J�$���5�}ccMW �<��f�(�R����J��
����x���%�v����V����3�����8 ���cb�����C��m���jiiI]]]
���������g�?��?U�ZUkk��G��������	�V����������7U����1�s�5����ZZ
�y����G{5���\`��c�o.E�81��}��0�;��l������������p8,���t,��R���������~�������_�T&xB��II��4U��U��l��]z�t��R7664��*�[��'�Jjkk���|4���29Y�$��O�xI��%
w�������i���(jtt����K������U,7o9�T�|cc��R<�e���J%Y��J�"��/Tgg���`�occ>IR<^��
�������)������G###�����-����]y��J��������������Un�����>~�i�p�R��x<�Z��X,����u�&�����:~|���g�����2��z{{5<<L������5�\�;��S�x�+t�����_������t6x\����/�%�X,���������u]��1�7��q?��
�V�)�N+�����OCCC��pHl{�k�����U*I���^��u�P(l��n�ZR)en�M��> ��u]��^�p�1�@���jJ�R�f��l�Cf�3�������=����������5 �*
�,K�d��\��fN��$
f�������$�u]��0�@}��jJ&����
�B�l�Cf�3�����J�BA���'411�o|����x���X__�\��4M�&'%I>�Tww����y����,'M�9�W�VS"�P>�����B�e;B���~�H�ZZZt�
7(h(������H$�v�e���G�t���$��_E�9�������8�9�S�ZU"������������t$�>������'z����p8�H$��<�9z��:��|^�e��v�4���]z�"������������\P�s<��j�*��������a�v8��-����7�����������|�����8��\.�D"!�����1�|�]��?>�������s<��J��x<�B�������9	���-�766�����������r�|`��-��*�L����4M���:	P����~T*Y��b��p8���^�#����+_�J}�3�Q�PP�P�g?��-�;�`d2%�I���R�v���\.+��X,*�(:	p@�-���/�Bo��������v]y��������z��I�Rz�K^��<�):���t����}�^{��9�9rD��r���>��.��B�{��z��_�|>V��a����T*%��'�4��z���s�����e������������8@���rY�Zm�G�\V�\�������x������O�{��Ww�u�����?���;t��w�������m��]������J�8qB?���u��}�c��3:�����i��~��)���t$@`�gmllhrrR�rY�hT]]]NG�m�31<<�g=�Y����V=���T2��-����/�\---�E]�o}�[���S2���c�$IW\q��0gr������R �l�;�x��RI�x\�JE�XL���NG8`�
�S-//�������T�tZ�Hds_4U*�z��%��1p,--izzZmmm2C---NG4�x83'��j��X,����#���Mnll��K/�;��N������m��x�?��':�T7�p�n��������]NZ\\�������
�*ol�e|��X�&Qs��,���EY��Z��X,���v�#��g�W�U]v�e:�������G��D����L&�����L�9�UW]��zh����g/_&����������_T�k_���*NL8
��e����4�B��x<�Z�&�0(�{[������:;;�\��K.�M7��j����)�u�]:v������D��o}K����^�\r����m���i~~^�+%�K>��$�&'Nh��p����eY�$�4M���9P�lI���������>��z�3�)Iz�[��w������u����n]�������k��Mo�UW]��<�)����,Iz�K_z��@�9Y�/..���S�HD��V%��qI�ol������9N�����r�4M��~�#���>����G��C96�����Y---���K�HD.�K�T��PirR��1�Y��3�����7kkkJ$r��2MS>���H��:���ESO��m���hyyY�`P����e�$���)��:����H$��xde;�1(�������)������G###[�v�)��)�L����4M���:	P�(������t:�L&���^
S�
 ��*�J����0�v���p�`��R��������444D�4�L&�T*%��'�0��z���c���j��R��r�����588H�4���U��i�|>��)�������Q�VS2�T>�����B�e;�VVV455%��/�0(�����Oj�������488����#���=������_8!�%���lC��q��Nj&i�T\���j5��M��qZ;��������&�w����q��]�l�&o=���6M��q'�;rl���|) ����0`�"%�"	�|??d�/�����~��%�0;;�������.l6[��$"";�w�M���D"�;;��xH�R477���X��������:���011AMM
���
�ED��(p�$�p����1M�d2	���x������DDDDDd��������������]DD�����-2��i����0�������SSS��]��""�Q�p�$����F<N��C��wVzH"""""r
�i255���4>����v�V�'����(p��\�q�>�q�����p�B�������p�H$C0�"rWz8"{�i�LNN233��}�hkkS�.""7D����
��rD�Qr�������JIDDDv�p8��������-
�E��i����3;;������
��R�a������""7 �������v��"""r]"���k�e�Z�i266���,uuu
�EDd���]Dd�Ja{>������W�!������h4��2����V1M���Q._�L}}=�R�.""�F����d2��(�a���Immm��$""";P(������`]�fD��i������ihh���Ea���l*�""�)�N��(
tuu��z+=$��B!�a��V3�h�H$��]�
FFF���g���477+l�M��]D�:��i��(�i���EMMM��$"""���Z����+
�H$hll���Ia���l	�""����H, ��x*; ���j5#"��P(044D2�����8p@a���l�""��J���bX,�n�zEDDDD�]�P`pp������8p�@��$""��w�kXXX`pp��JWW��v�r�4U������ �T���f+=$�����H5K&��b1�V�*�EDDd�,�4u�eY�0��b�R)ZZZ�����Q�����CCC��v�N���C�]*N/���MSE6.����H��:t����JIDD��""����gxx��AWW��v�2}}q�����������c�i���[����R___�!�����]Dd�x<���0N��@ ������DDDd�
���=;A,����F �"�
�������r9b��L���v�~��$""{�w�%._����.��@ ���_�"""�u"�>���Z��A"Q t]�bFD�.���F��rttt�o��JIDD�(%I""����ctt��MWW��v�r����X��H�<��������Z������,�h�|>OGG>���C�=Li��0;;�������N��"""�-V���� p�f�-fD�J�L�X,��]DD��%��.]����8555tvvb��*=$�CV�j]D��e�Ed�L&C4�P(���Immm��$""��]D����&&&����H�X��]D�K���b�r���z+=$@����1�p�L$�+d�����)�^/���X��JODDDx��=N��W�.����"�X�4��������C)S�."{F:f��iL�$�N���G���7�����]DDD�F8�&)��9wn�|�6Oy#lx<��HDDd�"�c�F�[���D0M�������}��.)l���9}z���,>�����!�00�P���R��X��B �������T�"�#-=��U|9��4����N�����]DDD�J��=p�$����A�������e�YXX`pp��JWW��v�Z
�EdGZz0�f�D2W=�4M�9���G?�on������#�5\�u	]D��~�������?�\��Gd7I&�b���\�JIDDdM
�EdGZz0��2{��:f�V:��r��.FGG�|�2���������M�"#Y[(�������1�p������}Dv�D"���v��@ ������DDD�J����Hk���a��~���=�3���G~��<�nX`vv���X,s��b���Hu
��W�Q�����f����p8���R�."";�w��V;�D"�����������D��@�������eNK�EDDdGZm�#�[��q���q�\tuu�p8*=$�u�n�"����^�������4Mn������M7PK�
g	��������,u���r��������]Dv����5�c�������}�d^~����{k8>����
�EDD����4}}q�Kd����cdd��M �n��|�Y��KDv�t8L&�����i�P`qv�������T��7���7�AKo/�P�H$��o+��H�����TL8����q�q����tw�4/�=gvv���1<]]]�l�JIDD��)p�'3r�F2�������a0t�4��A,V+��6l>�@�L4J&�
��7Z��������ym�*"""�-����x��9�xb��'����Wxt"����K���SSSCgg��v������� u�"��Z�/�L�3��~� ��1gf�X�X
L�H$�D�������
���"�0<�����6R��	]���=�ba���0���q���V���0==���$^������""��)p�����f.��J�~�e��H�0m6L���C���d���<{���������PO�p8���I��beY��]DDDd�y<V������z>�U���MMM155�������U[�������]Dv_w7��~�D����������
��a`���?Nvx�����~r���jk�-f^o/S�HU=�EDD�RJ���uW
_�����<�����b��L�djj���ijkk���P�.""��w�q��mg�0�'�����v�������t������L�0M{]F2I!����/r+h��Y��L[���'���/����i	��`�&���������hooW�.""��w�q��0���������m�r8)dsX1�j�4!?���v�� �2��z554�<�;���X���p8��������]v*�4������K������v,��(""�C(p�%3�o�-���sbpK:��HSo�B]=����������0����o�����uw+l��s�w�Hq�m�.;�i����177G]]���
�EDd�Q�.";J���I$x<�,F��<6���:/9��\�.����q�;Db`@A�����hK��,�,�S�����(�/_����C�)l�]I�����L�)��4i\�`��E���n,b���hj���fn?s��+d��@��Nf�&###��qhiiQ�.""��w�
��,�N������O�����	���g{;�`P!�����*K�I==�JG�������0���������f��""��)p��(8g�������+7{��8���mm��� 555��7���&�(d�]aeB8�f` q�y���D*�P(0<<L"�������&��""��)p�m�9}z�x����E�3=����:	c�&`�=w����`���8|�J)[w�B
�EDDdW(��JN�h���Y^~9M,���~���nY6OZ���a�H%
���H&�8p��*l�=�Z����S�l�z��Ic��/ol�J���7���oo�n��+"""����8�@qt������\����~u�x�X�Y���h�$��P(088H2����I��""����]D�]�@qa�X��-=���q?��>B!7��i��������������&�9N4Z������I�y�C����9~����}�c4O�j`����R)���ill���DDD��w�v������eUXK��&�I��l��M�&�]m��h�����	|>~���n��#R)�a��X\\�������WzH"""�N���TD(�^��0�H044��n'�t:	�������z��N�(���O0��j����Jd���yb��t�C����P�!���T�w�V�p�����u��x&q8tuu�t:+<Z����&�
���-
�[[[������DDD*F���l�p8��S#$���6��i���q��,�T�O~��{���pTx�""""�k�&��h�H$Sa�j"%�\�X,F&��������JIDD������Hp�b��Z�h��|f���,9�3H���r������T����Uu/��=����hoo���WzH"""��]D��������a�A6����G}�r������j��Z������,�h�|>O{{;������DDD��w�6��>���$339�V����9��������NDDD��j��^�U�Ry�L�X,F>������W�!���T
�"�mB!7g���d���G����n���7�����.�������2��h�0��������C�*
�Ed[�Bn�ttd��<����������SP�*TmU�R9�t�X,F�P����W� EDDVR�."�jzz���I�^/��k�X�V�X��x�V
�*""""RE��b��IWW555����HUR�."��4M�������������r�^r��"`R�XUDDDd�
��j�"U��<Oe$""R�����3M���Ifff��|���_�=�)W������+��p8�V{R5R��X��B ���������(p�-e�&\�t�}�������re{0�������]�=T�m�Z��d\D�����YXX`pp��JWW��v�uP�."[�4M�������������j����J�Z:-"""{�j�z�� -��B��d2��� 6��@ ����C��P�."[�4M�������������5���P���]DDD����:C�'��k~$�-�H044��n'�t:+=$�C���l:�4�������3?�@��EDDDVX�������m��.�0??���0����.��"""�I���l�t8��?�3/�L��c�{����&���(�G�""""��V�����n������t:	8�JIDDd�Q�."�"3���J�[�����ZWG���e����:p��n�J�|�2###�\.�v�����_P�!}}q.\X����7<������q8��$���:p�m"/�277���(n����.��"""7@EEd�|�Oz������y ��+cb���.������;Do�EDDD�C���v���ell��Cgg�����pZ�	""��(p�
	��<���d��ot�?���2��qn��Nn�8�P�h-""""Re.]����8555tvvb�������4�O��/k�'�-����D"������R��X(ta`�����PnM�EDDDD����	��x<�$XDDv�"rUk-�4�t:MW��O}���n��������T���)����z�tvvb�Z�}�$XDDv+�"����y��B���_Fp���.N�j����u�����H�2M���)����������"a;h�`������V[�y���o|c�B���o�c|�R�Q������������$333�|>���+��h�`�����qk��)����6���D�Q�����x�a�������T/�4������K������v,����l�"{�Z-cJ��;7��g%�0����p���fs��]]�r�S�?EDDD��t8L&���*=Y'�4gvv��O[[��v�-��]d[�eL)</�v�]5���"��>l�������}��."""�W��aFN��H$��|��9��}0M���Q._�L]]���
�EDD�Xe��HE�Z�D��e�������H$���tvv�����""""RQ��/^$?3����$*=$��4����444(l�&�p��B!7��-W��)�u���err��V;�~w��[�����H��+��,��SH��i�3??����innV�.""�M���q���P�M8���/��s��A2��g��{������#�J�uw���H&q��������W�SH6�P(0<<L"�������&��"""�H���,;��������L��r������q�P��3g�{��k�W�SH�_�P`hh�d2��8x���v�m��]D����f��Ja�[�z}9�����jh����{��k�W�SH�O�P`pp���<���+=$�=I��������Vk���'MMM�B�
R�����)"""R!;���������c����R)���ill���DDD�,�"{\8����Y<�SS)~�g�|�c7�r�v�������n�����'P/�)$c�X���EZZZ����$""��)p��"��\���4v����f\.W�6��w""""�`3Z����+
��N>�gpp���E:DCCC���c������`+�GDDv.�"{\SS���R)>��[o�-����DDDD*i�V����&����H�����R___�!�X�p������[z{7�o��������]d�������y��	>�I7��An����9tp'"""�q��Z����sj^����y��(�L���6���*=�-��
�D�d"�
���<""��)p��n�j*�3<<���������p�z?-���\-��u�$���F�f�������+=����F�]���������]d�H�T__�'����c����KWWv�}S�������6s�����l6K,{}����W�!�
�P�������Y�#"";�w��z�����<�`�|>��b����������"��Zp���s�E{yC�l6K4%�����������vw(�)�S��<""�s)p����jj``�|>��C6ff�|��I�v;��Y@S""""�j7��s�E{yC�L&C4�0:;;������DDDd
�Ev��VM��������bef�J6/��&��%7��_1%"""�����un�-�^��2�N��(
tuu��z+=$�
�"{���4���?����:�}v(��x�����v������v�mq�����t�h4�i�tuuQSSS�!����5(p�E����D2|�[In�%����������+?����%����n��v�27�g�mH���H, ��x*2���/""��(p�%��4���S�K����q����0
<�������Vk����������,7�g�lH�J���bX,���*��H�}��H���.18p�����t������?E������������"X��}@EDDD��*��F,,,088��j�����r�C7�w_DDd/R�.�K$��n&L;�������/�}����$����oSU�����REpe����r&�L288��f#�r]_���v�}�EDD�"�";�����,���cy��<������a��[l'��������I����>
���?~_w��	��CCC��v�N���CRJ�
P�.�C-=���
�x��!�e��e?��<!���~��RDDDD�P0�"7x�����{m�L$���#��S����i�����}~~���a]]]U��lG���2ADDd)�";T��"�k��S/2��2u40�
�>��� ���	��RDDDD��iVz{�+`1�x��H$�D"U���q���q:�G�����;������(p�"[�YV��b��W�<���0�\�-������|�x����������.����������f�P���^���1	��ys5�|�2###�\.����\�o�2�h�� ��"[`;6�r�B,��/���#���p��8�8��5�{+?���&�""""��M&+�
���uwW}����9FGGq��tuua������	�L4������N�7���l���,kioC�-����u���x�M�$�����H�������w���������&����W���Y����x<tvv����X�P�'HDDD�k��U�B[Q�����i�������LL�x�h�h���N��0]����6�����T�vl2);��K���������f���*��O����\�"[`+*�2������V���0���9x���n����<���e�~���BDDDDD������������]DDdR�.�E����Z�������)r���,����q-�H$������������z3W����SSSx�^:;;�Z������l�"U`=�����x��o:8J��a~�����'��
��c3W��b;�QL�djj���ijkk���P�.""��)p��m�Z�>t�'2����4�\����m~����s`�U��������4�Q�b�&���������hooW�.""��)p�+7Y���px���_$��
�vG�ll#����UDDDDd'��b�4������K������v,��=�fK��$�uwk_(�
R�.RVn�:0�`t4��	/.���g`�X���o����]DDDD���,F1M���qfgg������U}�>����_|��A����3g����l�w�*Qj�������i���
�������p���uDDDDD���*F1M���1������������v�����}2H��ML��D����l�w�*�Hp��"�B��n2H$�f��J��\���P�."""""o��b�4!����@KKK���%6�#�����b�VzH""";�w�*�9uj��S$�2��Nhh����$�r��nZ[���.""""R�L�dxx���y���Oss��	�}������MLp���U�.""�A
�E�@$�!�4��`q� ������1o�~��.""""R}
����$	ijj�1a;�;���2��`Pa����
P�.R�A�Q`b"G:
n��B���O&9q�A!�����H�*


�L&9p��Qa{�;R�.""�	��TH8�&����8��X�����%^���z>��H$��]DDDD�

YXX����<x��C�
S�.�	J��j-_V���/�#��17�cr2O�`��C[���o��J\��6�l�B�a088H*��������JIDDD��w��9}z�|������v�g>3�����d�4�j������;y��C�z������T��a{KK������DDD�J(p�A��0���h4�����LL�������v�Br9H�
�w���E�������\�a�b19t�


�����T�"7���%�,����x���?��D�X,K���y��\��������\�|>O,#�N���J}}}��$"""UF���
��������}�m��Y>���{��J���N���e���r����BDDDDD�&���F�d2���QWWW�!���HR�.�	B!����K���3�3��0�7n�Z��������7��y�NFDDDD���r9b��L���v�~��EDDdu
�E�P8�&���cS����/�l6���q�}>x�@e)"""""k�f��b1r������C�*��]d���i|p�^H15UX�>N���ov�������������d�Y��(�|���|>��EDD����l�p8�g>3�SO%�fW����Vvs��
k��Y�yW�/"""""�+���F1���Njkk+=$���l�p8��@�'�����V
�kj�����wzhmu���=Ns��x�roo�Bw�-�N���b
����z�������
�E6I)��4/���W���~�w;how\W�z$� p�f�D2
�EDDDD6Y:�&�b�&]]]���TzH"""��(p�}}q{l�����6����O�O���
o���F3�.�������X\\$��x<������8
�EnP__�dv6O&c�o���nH&�|�����AO���
���mQw��t8L&���*=�M�J���bX,���������(p�A.,����Z�Z
<���������'�.���<�����P��j���TEDDDd���a�O�._n���5�������X�V���p�5���#�����k~.EDv*�"7��1/�G6.]�����v�8?��wb�)��H��������$�f�""""�2��@�L4J&�
���/�L244��j%�r�u���p��S�H]������v����9�M���D��_�+�����h\}��)>�-��������������{������?H2�����l�p8M__�@������>��{>���O�?�.]�8s�����C|���j's5K7S]zYDDDd�4���p�d����R�7�;�����#�N��+9���H$�f�)l�)�`$��jk���b$��c""R����O�$�<��������p��y^~�e���������.O�?��Or��i����s�-�p���
?Fd���iN����	~�^%�J����]�
�$��H�P�MO�K+��������(��e=��-��4�8Qn'��D0	����jk1��U��t8L��������y������
�e�r����B2���+���������|'�������?�S>���a��hmm��x_������dhh����}���/��/y��vH���)^ye�������&��f��������m�S�L������
�\^��
���)��p��|>
�d��v�<���}��9�O����}~~���a�`��Y�!�l�;���Z~�Wh��_Q;�*��=�GFF������������������7���66�av6����|>~�����?��r�;�����6S�(����W7�O��d"\�`y�[
����}��������r��������XD6�;����""ru[���y]�o�1+}�������l������+r-�B���8N'���v--��C�c��JQDDD��i.����a���`��i�x�B"A����{z�k�}��~����9FGGq��tuu]�o���������E{{������!�������v��mmm~�J>� >�`��m���i�I����K�B��}-�7���b���[��67���JUDDDdSi.����G�"����j��/��)���^�x�t8L>g��G�U�_M�������6;;�����v�R���}5?�?��?�y�`tt���z����}477�������e�������t#��
���?��i|p����9�gb����Nl6�����$�����6k���\���YN�'No�7��60%��I2CC	2�X���z�����.]������@ ��]DDD����<�mmm�A[[>� ?��?����vn�����w�{��{�|�J�?��?�W�W����	����/���#�"����K/-���-���1.^L�o�����e��������"""��i.�~��a}8����Y�q�|����R�;7����R���s��������{ ���f1�qr�����0>>NMM
]]]�l�JIDDDv1�y=
w��n��_|��������9��y�9r�!k>�������S�FH$|>g����]DDDn�����m�K��=7��7��
l6����������+=��x_c�<��������s��|��t<�h���.���LNN��z����j��E�"""�G-��j��
�p�o��6��q�������W��Kt�H7G=s��j�m����H�*�����^z)E:
7�����.,TU��&?=���������cq:�8���,�\�e�&SSSLOOS[[KGG��v�
��*Uj�p8�����o�9m���������fW�~��[A�����\��=���\�Rp�R�p�����[E!�%?9��J�>r���r9l>u==���L�drr���|>���
�EDDd�(p��SZf[����18p�;���T�.�U�������_�������R�RqI$������VUu;���3��0;O?�����^_O]O�*�M�dbb�K�.�o�>���������D"����m6,""��]�Ni�m �"��d�<p/U�?�W�#{�`�[p�����r��e�Dw�&:""""{�f��\�Z2rW]���}�~��E�v;F2I�����������4M����y�j��8���*l�)3~�t�rKo�Bw�D��T���l�^�*�����,�_����1�d�V��!��	>�)����*��J����V�##2�Z��q�H��@�4����b�o�
��������J��J?�@�L4Zu?o""ru
����\f��3�p�G���?����at�9>N+#����;������[N��q����H���
�JYYY�t�$��>_x3��b/BVS��i����r��e��/c�xp�
*eG���`�������y�kS�.Ui;6%
���:5���m�t����b�.�V�m��m�3<����.4U�{�{f%����SH$puvb����{/����	�M�ddd�x<�����;v���~�L4
T����H����;�����Hp�����7Y��gE"�����})��B��V�?��vy%������m;W`VZvx����#;2���#u�"F<N�]w��Fq��WM�W(a~~���F�����������&e�*��*��������]����,�X�Nb�2�(m����V�����^�d��+�������we���c��#�&74���[X�x��Z[
���I$8p��b�Xp�B
�e�*��i�������]v�p8��)N30����x��%�O�9L�|��q��7���7'N4��*�>�}���}}����z����a�oy5w�M��Ud
YXX����<x��C�4�PH�4DDv8����<(:q��s�f\dh(�[kF�fa�C�Z�y��K����q?���]u%""""7f�o��8pcn3�"�������
��������a044���MMM8p`S�_�h�������]v��E}}�Y|�{�mFH�
�A�v������������mW8������������<�;��b��?~���������[z{7-84���AR�---���S��d+O�������]v��A���/bD"Le�y��������*���Z��ZDDDD�j7o������?��p���������{�]�����<�
]��h�L$�)sl�0��b,..r��!n�9���"""��(p�]ge���;����!??���f���!����LrO���|�������y�n��D�76���������?q�}��b��|>O,#�N���J}}�
?�J[u�@DDD����,���?����ZR�/x�%&����3J+wTx�"""""��
q���������<x���g�7|���D�Q2�mmm�������e+N�������]v�R�v���SO%I&
��H�V���q�
��r��8t����}�����o����\�X,F&�����������>Q """{�w�uFFr��,0?�'�����(�4fq&����o��o��7����v�r`�����|3d�Yb��\���������YM�_DDDv.��+��i|�s3LNf������7���������&���0fi���fR�.""""R���,�h�|>OGG>���CY7������?�\�_Lc�A&��������i�������������T�L&C,#�����Imm���M��j#"""UG���h�p�s�f�r�r�|~��8`���==[��QDDDDd����;�N��(
tuu��z����p��c�����_w����c[z{����HUP�.;V��}t4��O/��S����iBM���f���B#�}63�N��D�QL���������}�S���/|����C&���F�D"{6p��D"�+V��u����l-��#�*��q��&`���q�Fic�.\.����������4���@n��
���bD"��X�VJO�p�&�jo'�;_�:������������T�T���B(�&Ns������g���6}����l����&���������Z9��� ��H���|�i{��z;�����RDDDd�[+���smB��J���bD�&�'.����/�_��c\��HF��<�g`�fO����EWo�����7�
\D�"������D�X)�20�������6Q�.;F�"ix8�;���i�e^�k�0�r�WIQ�!�y��Y^�)D ����W������H���I��F8��r�C!Zn �^XX`pp��J.��=yEp�����������X�G�t{Oh��%����h�|]__�����FV�EDDd;(p��T�T�l4���1:���6��������B,��
?��
x>����""""��x��������8��Z	y�������d���!�V+�@�b(�,�K�_����;�w���W�}/������O(�;7@<n����b1U�$""������d���������s��}'i�8Ie�hl����[�!E��������Wz�""""R%B!7���I$���H�*j�^�d���A�v;]]]�\.B!����e�����V'JV���Bn�����e�����T����6S�.U/N3<�%�0:�����"�
+y���#�>�1Z�p�����������}�?�$�0UIWB"�`hh��N ��t�o+��+vx#Dnow*<^b�F�+�������He(p���t����&&���I+V
\�O�C?��8���EDDD�J-m�����7??���0��@ �����>+7-Y���^��F����<�R�"���A4�a4����q�9���l8�������P�.""""R���8����\.���V
�KFF���~���n��>���Xyr"�����g$""Ra
����.�����}0kt���4-N����z��������������U��iN�!�0��l�9��pr���1::�������}���p8��s��|6�������G_�+�l!���i�}v"""�K��T�P��?��~~�����gr��n���b�{��{��K�k�������Zz{�������\��Hm��X,��@Ba����ell��a;�Q�}�]5���l��F��"i�V3;�}����4�J@�j����x��1
�p��O�����J�]�q��D��c_�&2�H�G+""""��\��l�K�.166���!\5l�������p�p8��c������C��Ns���U�?N����1l�P�}E���f�^����]����l8��s�~���s��t8�����I���l�������5�����J��r��>����;G��������v��������������v���BnN�h����H�?��f(~=��4g�N�����Za�����j�fDDDd����T��%�'N4����[���)GM8W��ro����P���� ��
�NFDDDD�*rs�L��h'R�����������������:�R���,�X�#G<$�P|3�V�H��Fm��d� �(�F��g����6m�a�V3"""�=�K�-]�x�����'���*V+L;Zi���a����_Q����������7@n�4���fjj���Z:::�������h4�K/-�����
�`���_�	��'���W�t_o0_��}.""R9
���J���������j�����C��p���7����4������!Wl��i�LNN233���������vXr\�08z�����tw�6�`����6]+�Y�RQ�p��H����B����_fa������������7}�N����JUDDDD�*��a���������n[�n�&\�t�}�����v�a;lO+����KW�F�"�==~�d�eV����R����'��T�����8�9l���
�Lz;s����n��pEDDDD�R:&�����F�P`����Hd[w�4gvv��O[[�e���Y�P�{P���j�""""%�����<A��l���g��e!i���D���.��j�a����p�~��;�����z�QR�<�	���W���mo�n�k�����sss������zCa�f���bm0*"""����8�R5�}}�������x���aP��c��4}��������PEDDDd�����;��/�a������-�dL�dtt���/S__��C��"lH0:�%�02����YN�h�j��[�DDDd���"n-
�eK��aS8�f��_����V�b��	d�b`�������he/""""���.�)�w�A�����6���m	�GFF���444���R5a{8���?N4���W2�f��H$�k��"""���wE�w�t�p������[z{��������Z-���a{��E��C���iz��m��IDDDD���]
�S|�!�y���$��&>����^�P`dd���yijj����_g�����~���y<w�U����"""���gE�w�t�HW @&%���������P��@�k<��]DDDD���.�)��������7b���P����I$8p��VU�o|]	�@�xP����"""R����+m���F��u���Y�'�c]q�1����(l�-��7�t�B�6�^m��;�P(044D2�����<xpS^o���:��k."""�K����ZU.�q�B�����D�2���Rc����)R�,V��z{��z���7 """"{�6�������Q<�F"A&�q��

���@SS��0�j��Y_s�N
�����r����,�{���gY(���9\[�w�	81Zo��EDDDD����v��t8L���l4J&���Q����J�hnn�������j
���V��~���������W���0���i��Jy�����-��my""""�w��iN�/_��m�����T�D"��~������K����L��,�R:t����m��������]�ieO����d"�x����+&6L,Cw��C�a����	���-�7�\D�"�����w�ji�o$�"�[\�������-�����n��]�iiO��T����s���c
X(��,&��n��i9��-������
4�������zW���a4�8�aL9�[[ikk���n;�-"""��)p�uq�B��_x�/x���3��8�]���~�`����xl��?N���
�EDDDDnT(����eO�p_�J�t8���S�.^��n�����<��6�������9d�O��l��F�S8�Y�2�����T���n����8������\���.��{O�%�Y���D0�Il�������4�h��{�e��}��������]6�kuK����mI];@�;�B�--d����|UDDDD�Z���r_x�j��K�*��Z+U]� ��Z2��\i}�[�����l�w�a�p���4uf'���7���j���;F&Y���"""""�(Ns��8������=�������R��}���'O6��Sl	��W�tw�B|���/�m?�c����J��O��lH8�����M�+�9t����
c`���Vl��c��}|/�Q~��=�{��^���"""""�me��*U�{�V�$�7�20��h��d��
��������.��1r�T�uL��3��x&�a������9��N�^o��/"""�(p����������?��Nae��������v���wa�����������g�U��R�/9q����0������,<�|
��J��n_�B�`�E"Q �4����E��G�q�]`������@>Ob`w(D:�&�b�&]]]���Td�""""��w�n�y�����+xY��I��2���c�	|��{z����Y�T��x��g�N���XwK�P�Moo�H�x��G�xH$"�L��P����M�=;A1����R��k��s	,55`��&&X\\$�)l�d
����2Jzq�:�������o�����g��T�N�F3$|>���h4s]ay(�&r��D2$������?����s��a!�k�G��RH��x<��N
��D�Q,�@��S�1�����&
���}����`b!��!�<�q~������""""R������v'����f�����QT��63K��7�~3��K�r��X�"��Y,V+�����X�b�Z������\�y��H���K8�f��_�/@��l+x,���o�(~���Wp�(��	���:5B"a���8s����;7K<np��"G�z��m�j3S�v���}�����3w����W������������(8������a�.��T���otSZ��L��\��>~���_�����`�����U����7�dZDDDD���s���?&q�,X,<��B!w��������R����U:ap�7L���{Rb�,N'��<F2��x��7������}�p}�&�����/��/�����n��]������������aYq��y���?���}���������i���q��9��v��}J��
����~���=�����#����.M���(�)�^oV+�T���a\����~�N�5�s�*�������>�.,,��NX�FU�"""�Q
���f{����`?������������HU*��##Y&'s8���^+�������b�21���1���s��0�H���?J��8���|p!Nf<�3;f��;
�Nc�d���Xw��2X��W���@(��?v�K$�)_�	',VZ��������wY�T�p��?��?�u���,.&�����&�""""R���d�x�d����b��nr��b�fi^[j��U��p������[z{7�'X�x{��9;�<l/q�i����w����s�`=r_��>������]���Y�RV�D��gS���g�#�yl��/���n����_|�{}�v��������+i	�����%�.p�����	��}�@u;��L$��c�z),,��D6�/^�Hvj
�Y0����|������������?�\�D�(_�Z�^�~�gT�Mdo�j'DDDD�K���E"&&r|t������V����wb��Y>���DDDDD����s��F:]�����������`�pX���s�L��Y�qcK��R���0�/b���G����_�d2�{�=��A]?�Q|���C�u��	���8������=;@O����������P�.@������=���a�	�]~^��_��v�&�""""R��A��A*U�����	��^�L�@>��8H$�?�\���=�o��62������&
~��}}�y��������c?F����~��o�������}������fH&
����S��^8� """[c�\U��p8�����o�����U����������e���e�""""R�B!7���@.gb&##Y��K��{&��9���$�W��b+�'�,��O��ox,�HW ����b�X�vl~?�`���/��G��_�0?�q�r1h�x���q�������o��H]���O0~�4�px��/��H&
jkm�|���Y�*���G����������[k'���h7?��*[DDDDdgkow���y�|9��x���)�iB2	���=Z��&|>���q/�������HP��8�����e5��>Fz{)���hj�4M�7�L��a<��t���c�Z����������0�s�F"�f��P������=;��g����p�M8�V�����a/�=����
]��W
�M ����������>�A���a�����lX0��������+����X��pX8q��s�f_�4���p����
��P��'�8{��G��yZz{�;lO��L�=�17��H`q�(
����������Z���>��SH$h:yO-��$���c$W������6�/
�N�/�������:�����@DDd3]��`���z'�p�W�}��<���g��%������s�������'��U��2�
@����e��l`�������G������S�,�w~g��G=�����mm�2�����W��D��|���1M��������Mo�=;K.�}�3�(F2�����`}�&&����w�����e�9uj����������U
����{����}�
���^���}�X��#3r��G��4i�XVy>p7���w����s�9�]�������&�	n7��-����"�������������x<V���-nu#�eJ�w&]v�z�v]� 6�gW����=���������b�����H`$��jk��|$x���Px����_���h�����j���/�����f�����b����Q�|�R���ls��,�a�'�DDD��F�+p�%�3����=����o`�_�G�*�e	�!:�q�������DNDDDDv�`�ES�����$�������3������N�h(WU<�����"�����B�����C!Zz{����S���I��{<p�����w�K����������g��'XH��G��3��]��><#���������[\�vfsY��67;8q�a]U��.W[�}��n=',v��NX���l���
V��K,�|�8��a��py��b����#�~��^��N�p�\�<&��R��7c��5��/rs�L��U����d�|9������&'~������q	���ss���\�l�O������M	_���m\�V8���`��)R��6����������1�d��~���}��5�����'s��3�����I,�W�)�Y�������x-I2��emg6�b���W�<���u���t�\���������:	��V;a%""��6�7X��.Q�|�6AJ�?O������e�&���^�pK�i����%.S������6~��{	�j#""""����O���	����C���"�,����^�PWggb"������Z+��Z_o���r�h�����i���R%{�������n"�����t���~��L;��7���)����Z�^/�C��&V����� os2�
r�'�)�'��%mg6�EG�$�F�J���
{��F8���@�*�����v+O,�������'�DDD����
V����C��&J~?6����}����XH�{���p��r8�����x��8}���n��������v
��<�������_����m��q?����cex��_���Ai���c���Fc��\��UVV�f"�>��ss�q�Z�_�D������\���Anj��?�s��7��f2Inb�E_�����+�)�i[-/5����?�;Nt�t������MX�`u������A���SO%���r��l��cF2��4���?k��	�^/��6@�����!""[G��.���`���������$�/5�����3�<v������+{vi������>�� O>9O&c��d'7x��?|�'����gp8,|�;)>��=ZC2i���'l���%��_�0;��g����2M��������Z���X�75���>F����7�7Y���b�Zh���)���sE���t~��
�V��?�gb"Gcc��y/nR�J�0@vx���O���������K����aq8�z<X���c����j!�Z��w?�Z
�����P/�/������18����P�)�&\�C1p�v�r���_�������Vm������Sjr��5���3;��n�r�}�
�T���^������@�Q��l�+_)���v��������Dnb�Yp:��z+
'N���//��P|+��"�������)������g�`��������t����,\�����T�>�������b��0
�B"Q\[���i��3-�O?���';<���s���+a�j!:�j�~�� DDd{)p�b�9C���`��/�?�>���pR(�i��:;�
�2
��)c��
�DDDDd�)m����{������>POw��G�"�2���F.W �0�a����[�������d�a�Z�?���q_y�-��=v�L$��v��&o8,&G����X3vRc1f�����?�)�c�9z�C>o����|��	"���on@&�����&�Xl6luu��/�q��b����f��<t�xR��&��af�����������.Y�Y�����T��*��3����^Z�`n�z�"��B�,`
�����h�����V:��F3Zz)""""�����p�S�Fx��ssy|>��NN�l^��5��������v����V�����}{s39����>=�s�Bn�}}�}�3`���z!#�t9���N*jbq:)�r�MX�
������/���L������������b����y�f>Oaa[]��|<^���b�[]�C�����I{%L^� ����$���e�{�g�r?��~BBD��)p�b�9C]:�H��'n�x��ff�|�b�v�
!��r����
�!^kl��hf�e����b����K/-RSc��u�rY����Y�^q�
�t8�����_y�B2���f���7��B���,���*��*_o��:|�\]���9?r������
xcv��I!���t��v;��6����d_{�B>����:��YU(����yd����O'9z����o6��w7�v�B4�<�������-dGF��F���n*����@�g����n�W��Yz`��9����gf�n'7=M�/�b�}���C������
���z�P�Bn����y����|k��zx������S74QYkl�U�����TJ8�f` �O���+.]�c�@C��P�K{����8���.b��:�|t�t����������
O����n��f13��<���3���>
pEE}������
>� ��!��Q(V�[��P����A��M��G�pa������������!��������������a��3�)�N�Dh��� 71����e'Vnh	������RU�����-o���K��}wMyE�z������}�������|�m�vK���=k�����F<�����=,��\�����-����n������i:f������zu;��}�-���:�)Uk�m=�/EDDDD�Z�Zxt4����H]���X�����8p�Ao���v����~������M`5����/p��b��q��'&0��y�Dr��?�e������	��
�;W�57�cJ$N�l�����g>C.��`7�a��l�v+Y�<g}��:^��%�>�c�Ef���'�%lv�3�-�����������b��z;Hg{;x`�gUn�c��~�L����������M	�J'?��}��b�U��%����g�;�I�����zV��>�������cvK�����{-<^��u������SO�i����H$����
��{DDdgP�����a�>�_�:F.�c����b��bM��&3""""���Q�������Q[k��{�=Z�o���/�y�e���g���6��b�����1����tw���s��GI<IK.
�E�n+����w�UC4�����X����'H�
�R�I��g'�"Fn`��1'
��ux<6�Gp8m$3v����
�/=SG�}��;���?��i&����Od�`
8��p47_��u:f��G�B��17W��yr�r�P���b
�������-��KW�g9>y]cX����g��o���L:;�?�_vRb7���kV�g]���V[[����F�������]Dd�P������M�E?�\�*�1�V�����O���������W���pXij*V��}w
/���d�P(��}��,�_�� �� v2�z|��gw(�17G�f�0mXYr'�������.U&;�%��f��l,,���Z>�������F~l�,������k������&�����#����|���a��r�[n�6�����?�����\n-i�����b[_w��m;dGG1�i
����
,7��!���?����Wr�����p8����-C$�ab"G"Q\	�]��f����KVk�����kz����U
�w��KK��}�����#�8�f������D��w��_�n��J���.mmN��/�����&�b��}�������y����g���m���6,�}����_�%�|������w}�-tw���}��AW�r$����I|>+~��C�n����IRC�rv�?�/���3mp���r�����'�R��8�?t����I<�4�
�#w���M7�t�dy��c�����A��.a��{}�E�����c�`�Em�����B `[wh���Dm�-�F�P�\/�hX��?ta�@.g�pXp8�<���I�|�j���u��M�{�[�t��r�������E�����P��Ay�9X� �v;�6kr&""""���`���"���"`����As����y��}k����R�4�����7�V��z����?0��6~��O.QW��r)�/��~���������}��s,8��R����sG���nO������8���q�_e!a�����n#�:���Np��?������M��#��s�>�	`s�X�Bn��i�P���o���F��\�\��*�hH���P�����G��X���Q>���>�u�ADDD���*�t��s����/��/�oZx+�������Ng���[o�����F��]DDDDv�����������;~���|����A���-��8�=�������b����D2<��CCY���|������e���������+C�o�f^k�]���:F[������O>�N��e��mg�lz����������e���wu==~.\X��1�����v����������{.����81���0�j�v(V�/PC����{�,\��������kn�$""""�������	��tw���������p��c����l����4��#��b�|��b��c��/�����yZ?�C�v?=��W��%��M��L�{������;���	����M>��ty�@s�c����h���/��������W>����Z_�>J��6R���V9"""���W�P������K�}��\�t����M�2��t�����@�`�j�$������&WV�����lI�^r��,/�T�;�qO�Y~�v��:A�5|��x��9��������/K�����_��vT��z�?����yl6������/}������y��A�i������X�zg�����n������)��UDDv,�U`�j��u�_�����g_����U��/cq���/�{�����X�F�y����21�[���TE<=����������h������ �+���sd��c��w��m�Fm�>2�H����^�=t�Ye])���g$�ab"G2i`P(�
&��Q�Wg�u��z*�KU���\bf&�i����{�7qEu�z��\���t��i��u��0��O�/����XVDDv��Z5B$�������3d��������F�?0�ry_���.\��
���L���
Ks�x����E���CI��[�Ja�&_�R����f@]
��x#�����k����1�8�����'9�k43J3S���8�F1�Y2���&����}�3R)�55z��k�^iC��}.��nd�7���gY\,P([��&d2jk�eJ�x�����>����cX�B|������S,,H���m���m�p�}=�����8�l����T:��
�����H
�+le5��@��}������#�*u���Bf��dM�I�;�c��t�"""""�a~�����u��(���^+`���������������pa�T�Jg"�x�L4��L2y��U+���0��8Azd��A�g����~���� 6�E2v
���
#a��W����N`q:y����>@g��
��l7��|��������6jj�45�q:-x<V~���9q��G����V+�x��I}�s�s@�����N�����~{
��>��1���������������S|��)�b�_b�[hlt�V3��{�	�k�����VC���Sz�_m�H:&;<\��+�������h�gAdoQ�^a+���5��s��^���s��x��q??{� w����]DDDDv��8#^O�pin��P,,,��m��D"9r���v��W�]� F"��Lb������Yq��y��~����O�0���>�!&��z���-�0;���1m�Fs\x�"r�qCay5��h�T�:��d��2����LM�hjr������z.^\��~i���,N��t�$������.^L{l�W^����
��pX8x��W�:�wxx�;}<�\�G�dd$��D����a{{���f'���+o|�$F�>>�
��Xy����>����l�������\m�H����G����?~g{;�����O�en����o������\��
[�t0����]�d���<Vfh��������>�!�=��@� �3����X:�.Y}�����p_+�N��$�9B!��������^��/�=O�����}�b�nb����"��5��6'��F�9���tXi;z�_���8g�N��Y��m�<��NG�x������"`�-o�22����q��r�l�6/����e��+?G2i���LLd��&;y�V�`��k�[������11�`z:����ea;��b���1=�gd$��#^~9��`���LN���rq�]5�<�Q:!P�vl��+W	���[�X10������Xl����K�e6���_�[�O|���R�^J��p����{��l#ci�<�1��z?O�nnw�����!�����l�}��/�-�o�02r��O��1��������wi�����,>�,���`������8��n����*P��~��y�p�bm}�	����L�����[z�2p�8���8?��\�}�8�+����'Z��U���p8����bjkm�uO���dd$��v���FFr��d	�����0�b������[<|�u<�@�()tQ[k{����f'�d�x�������p�6��B8�H*eb��,,�\���llG�{L����X,�e����Wg8,x����������G������g�IQSc!�2y��)zz��~/W2h��)����lp������|�R�Z�����L������O����R{��Nv�f+��o���Z��������Zm �s)p��p����~���q����X�UC������;��8}�]��EDDDdW���n��HIiC�k����{�'��`��#��y.�n�Z�������a{is�D��}���*�B��z)T��������}��Pl-��������n���H����{z���R���*h��d��l���H&������R�w"a���8~��O���� �(�~y���i7N5�����;�����()rs�L������O>����|��;�pa�����y=�eh(��uuVl�6[�5���}��o'�7��29�!�.��?��;�I�L46�9r����.�����������/��28X|!�,V�[,`���s���d�{5��l$�+}-�>E,��f�B^xa�_��jj���X���s�L��!�;���I&�����-[1�hn&76�������������5{��VK�*H$�����}6{�K����-J�RJ�w�C�
Dv6��l����_������;��_�o{i�n�<�u�M��~<K�����+""""{��
���Kq��$mm������g1.�������u���E������
���f_��w�3����Y��>K=�xY������/��-8���#������V2����.^��������i������������M�|o	�}6���<��9hks�+p�|r���N�����'���*���i(�.W�����������,V��~���z��~��}�>=^�7�n�������N�h(��/����T�{���HD"�q��/38X��/)���z�x<�e��n�1�F����/.2?o��i��N��l&�|��U~==�U[��{zp�W|���9Cb`��C�$W��w7�zz��>=��h��_�PSc!�7y��)���&Z���UC���h�f���'��sW-�
Te/�1
���j�6.,p���5��5�����aq{��=��<�f?GN��_|"""""gy����YL��Y�z��^.��K�@��������.�D���W�`���ma��z)7���zo��������
��p��S�H]��7��Z�������e#a��D���<���~��O.����i^|����4�n��?P��V<���*���������~���s��v>�������o@$�������$�/���dx8�c�M19�<l�x,
&MM6��+7��Q+OJ�;7[�@��_�}�l\�\�`J-|�N+�Q 7�����u�h������f=';��fijr�����&MMN�$��>��I�j����]�w��(�h������RW���a����E6N��X��mib���x��~��i��=�W�?�YG��@-|�!����.>��3�"""""{Y__����	����9~���d�X���������m i��]SS���Bn������t���0.sq���5�_Y�n����,�_:^w��}������V���������>fXo�r�P~�0/N���m8�fz:Gm�
��B>G�z�m`�~:I6[���/�l����j%t555:;LM������j�����k��2�je�{.�08z����~����=;��l�B����v�����Ik��������yC�c-##����9���K=��j���n��q�I���i���8��47;p��?�����rk�V�r8���?N4�%��0Mhnv���n��Z6��~7������h4�K/-����f�^
�
���^d'R������6t�<�T���<���o0~�Z�W���yk=��~�}���l ��_r"""""K]��@6[�����X`z:���b��,6��{��cmv���3L=�X���=�}�i9O�9�
����WZ�����e���_h�J��x__�vq�&F�x|�
6%l����W�����<�� ��V
�4����<�x'����'��(�����er��9��J��lp������|��Z,��M5�9�V��7�Z-4������hh��@���PWg���n�{XK�����r����T�\�p��5��������@]�����[6���ZU�����y������ZzT�k���O��\��J�WTC���N��}�]��m(����k����y>n����Op���#|k� ���"�h)������
��fg
2�bt�������x���ra&�Bw(�8�X�d��H��������$y���js��X8��C���D"@10�Z��t8��#�������h���������<�\����+�K6R
�d���a�����.\X(�~�]5�}w���?t��V�����?������~=��KC��>���li/��F;'O6��%T-}����|6l�b�\�\W����e��|5;���������mm�r0���^u�P�*�7j'�]���o����}��y��%>������7q�[sBn���&zm�1����w�[��GDDDDd��Nv2:��f�`���h���C�o�6���k0;[�R�9��J���4��D2g�a�5�,���+]1�w:���������x��z&]vy�����Q�t�l"���~�!{__�8v�{�%��[���)������$����i�����da}������F�H�\�@}����<�=6��Ky�r+��m\�2���s���Bn��0��������da���a!pb��r����,�;.��K���a��������s�Y��l'�4��c�$��l�_��p��G~�y�����k�u�������[3����)jk]�]Z�#""""��7��,�i2:�[�c<���nb��$��c�z1M�n�l�y,55L�����?�mc��<���j/�^
�]w����n�==�{z���;���w]=��N'��1�q�?�#��?��!��_�t,�WV
/m�LN�x����q������`�Es�����|�����`����K�fq#�{��Y�r}'A+����=w����
��&l~�U[	���^m��jU���
.^\��Q����g���jvUQ�N�����5���o��~�f"�SC�
Wo!�������������Q��O�
�$]:�-""""���f�
,,hl�c�_�����IC�����X�p�K_��T���,F:��'��#_�������65���Db��u(�������y����M��#��v�
'N�c4���������p��mT������9��<�c���q��O&iksp�|��U�K��O��H�4il�33�gn����>��=��?�C����I����y����n�NK���>�f��|"QPQ���T��i�5lWl���,�����?��in�9V�-�����������>��O�/_-��~�q&����4M�� ��,�PhY����1�{���}���4���^]�c����z��@5����P�����������9��J������/\bx8X8v�[�m�>�����s/����4&��l��f��4�4����C$�H4�)W_������D����fzz��w�����833y,���[��S�������_~���$�T
����������k���K���'>q�|�����N�/"��(p�B�?`]�������_�j���a������4O�}�o�?�U���\
���y�����_�T
,r��;��Oz���==,\��|�uo�ZbR\��0,3����Z����������/�������O&���G���^wt���c����I
�������cf�ynO���������v�t=�����?�P���b_�kUG"�r��d����I�A<PP�|2�}����w�t8\�j����Gntc~2p�����{tT������Kfr��@L��@!>��^�Z�����Z-X���j�=�h/�>����xm=��i���s$��/��AqDIIH�}�I�>��c2C������������3{���|�3���a���s{�S���
�x���,:�""�G��I���m���;���k��~�N�4�e��v���5���C'""""2�����v[��Qo5t������
�<������m�m�&�F��	4=�bc;���b�|��z%9�v�W���r���k8�(-���k������#�{�����Jw������E�D\V�e���)S��ao%k�`�������mpJK��������'���c����?�,\��������Gc�n_^��6��1����b���?��r��!�n�#��G{�S���
�x��}I9��(""20
��HMM�\�V�lx����Xz�6��k�C��~�����_�>��ng���/9�u������K����{����&�m���M��MfYY��{�����n�����������&��B�v��xf���}v6_��LJKl_��p]���d���L�p��������k���F�f���C����`��>��l>�O�(��`��Y�X���{�K0��8Y�$�+Zp�,���~�����k}}~�vBC1k�/3������=L*lwUT����_]���
���k�l��������vt_"8����V��ED��!�[���/.����kQ��s�x1�v���|.��k��K�DDDDDD--Q����q:���{����Pz[K^%O=�����|���i����44`�����|<�AQ��A�f�e������_C1u�kj�W�cq������v\D3��@`�:"����v���s���������b�-��3��X�u��x�o09���~���t�i6|O�.��v����Y�������nS�a����\=��xpUT���Hu�}�4���T� "2����eY��v��2��Y������h��E���i?���k��c��"� Po3B�R��������R�OV�l���dfZ��L��#@��`��?yacc������++	y��m�@�����cc
�	4����FY�&�5c2c��|Z\���a{j���O�� s��G�b��%@r�Hc#!����=�C�����#y������Au�@�u_f���:����:&��3��S�-	^�����/)PX|$mB�.�:wnr�����?������
Q_I����������t��`����S[)9r
��P���h�d��8�����,�A��}@�1����S��2��#<?\�'""""r��x���eQUu�����<U'��&���D�mI�%��k����q�`�%�������]�-7�
/~���^r	����J!�0F�O#'�B���|n���x��������l���
�����b��������5Di�������	���&��?s�,�~����~�����UU>�����D���Q���^���
Q]��������:`�������I�����_#�����$�5��������|�Kw��VT����f�/%��q���<��**\� %���K������.�r:
��k���{z
�M�fX9�?{��*����~��=-b$""""r*��pQU����SR����T�\_��9Jyyv�~^������ ����w�A"��`�q�2���}�3���L�X��Y���5|��V���&��6��6���ml�.b�q�X��?�A�3���/���Um��{��y}}�U�v����H�������{\|4�r��!B]]�y����a��
���-j<'���}�/�7~�h�
��R�i�~��.�:kv����kvw.��2�yM�+��."rt(p?B���<��.�������F��mM`�����O���l���Vg9h��d��u6�����&�k��eR�]>��P���\9�����+��'��sq�Q�����'���A��/0��_���e��M��ih ���#n0l�#��X-#�H�i@��H��o���������jcc������$�7o8~H�h^o����H$�n�D������=���;�&eRW��
b��rY{m_��I.`F��z�������sYP����EDDNQ
�(uI!��	�Eo����7���.������vPx.""""2P]g�f�w|����W����X#����������VQ���Md�6��~��I1�(V"n�9�D>����V�QT����	m�B��#R_Ox�6�0��0�p����s�0��������Rr&ep���QJ
���a1�}�xn��N���wZ	u='7�4����)��}��^o������c��8ee������(�����z������1[�l;N��~�����z�nw<�j%sx}Y;@DD�D���:��W'/�|������1��q��R��|u�oTH������7���{�����������j~��Xv3�����O��_���/_A&��.�����n	,`� +�3bkm%��D�M7� �D{�I�l�.�d9����9.����'T���f,yW|�w2�(��!�8d8F�A`���l���f����8v����K>�L�d�H[�s��������:zA�}�G���9��D,9|.gt�u�@�����LV�����MOw_�|����H�{�
��j�!�`Lp+����q�5l��}��s�
�A���������46&�s�D���:�{��Cr�������0��:�#���&�D0��F{����7���4�A{GVl�8f�n�����55��Fmm����������� {������_b
������������x,l}�rY��� ���CZ��tn�����hi)g�����������:}�z�WWmn��������������p��g���we��\���j?��<�L��xzlv�����"""�;�}TSn�����)�����
z
���.�3�Z���Y���o�EDDDD�!H������MArr���3X�x������Q�� ������r�?�Z�weqL��X,6HD:=Gj���tb��g�wd�adfBF����=?�Y��sTW�������������L����x�@������i�ui��/��o��*_����9O.��{w��>��a\P4��g1�o[�����$�~�� 2�4���c��4�xw�-���E
YOb^o��*����g��,��8nh��rY{�rEDD�xg9�&������sg��:~���9|��v�|L�d����^���j��=��{�����32��,��@.���N�xN���^�������Q��2�g�F+����f���<&`9�����CNy9�'�5u*��,��@�7�����(�;�pi�<�|6u�xl�L��x�TV��m}2o��������m�����.��������)+������������8�c��b��������k;�c;�d�o��m��q����&��me�<7��������.��?��Z"""�3�p���s]�[`��A���L������
�r,�B&�����"""""�=��/�����pQU�#�SR�8d���WV:7�,B��q��d0~�Xb{����d%��(V n��N��QdN�������!� nX��-�7������1���R��mYR���
ml����_S�q����������o���}���~���C���(��lx�7�fPZ��O��X�v�V;�����0!3�~K6AK6���)-=�_�+'����ft����M������gg9�(p����i���FNgk�3b�S���o��'���F���rY�
�����H?��t����8Y���~��_�
�/�3�yo��8�	��w��L��X���J'Q��=%lX1�>�#��h�G�n)�'57�2����b���_�J	���/]:����������C�s��;��}wVS�[~�I�\�sA�<����|�**�UU��c"�����rru����%������l�L��'���������>����aC?�x.#��k��d�#p���[9���U@������H?efZ�m]��E*�.d������_��S��A<q���&��v	��E��'Rbn��:�I����OFQ����������.&;�l���� L��e��L

2X�t,p�M�G���%������v.B^/���N��{���
��}o2������s��s�x��s���g��a�WWN�����	����'��Lvy9���n�SN^��A-<+""'�����X�j7��x&�D�-�S���f�������Z0�x������*��f`�x������E����|��7���*�X1I`V;�`[{+��l�#�;y�v
�v�Q�`0�?8��J��x�|Z_����������5���q��]*�����6b1�������;��j�����#�Y���������+��Y����QRB����
��Uob��G����Zg[�����a�S�fe1����qf��O������YOc_DDD�
���Z��[������.��?�Eb�g0�e������������a�N��|�<���Qv
3���x��|L��7x���9'�N���Z�^�L �I�����/1eGU���	,�b4;�1��s.�m���,��G2������6o����Kt���mm1�yfg��Ei����n�`&mm	��|��V������^�-ZD`����|��hK��j�!�u5@z&~jfy����0�)�(�UQA��?O��3f�]w������=E�������`��������o�w���)��R��K��e���������4�@DDDDd���X����5>�-���g��(@����g��D"��G���>�F*hO�����h"��/z��b'�y�b���xh#����Z���c��%49p L";v{y�n�����(YYb19�B0���0hn�RX����s?��pM
������-'�[�����&��������$k�L�n7c�.eb��XU��NrJ��X��u��L_�������R55a��o��<��Jw�����f��+Zp�,����~��Uw�z����{���,)q�aC+V�PXh���"""r�(p��c���>�Y7GjQ�n$����>��OQ�9�!�~}+v�Av����55a��I.P:���}��<���v�T�a�J��Kj{+1b��
���r6S��j�c{��O;8������d[k1�&zz�>�Fa��L��#���m�`���mQ�a�w�m������cY����~����8#���l����)* 1I����l7-�a��{p6n�������%;�o��we%����m����/�0����iS���L���l��f��3X�l�
�|u�������Hz������^o�+����0V+L��8��]��.X�����6|��L����0~����}EDD��Q��A����M���$��s��n��ORDDDDD�F~��}���	L�<��.&?|%y��������������q��1��n�M���sg�@2d����P7��������VB�6�A8�<�x����v[o��J�}n���Fy��X���ka�l7����?��%f�i��.��j7�4�R�	LL�ZcXZ0�`��R`p�������������$41�Z
y���
�����!��O���{��=����qF��������+t������'5	��6:t�����`���O���+='K��M?���{������=
�;H0�&eb����	�Q��8��w�@���zC|��
g�'pg�g���6/=����:�B8i%��|���&�m�;d?�:
h���^����IDAT���'8��f?������t�4�f�#i��&���b�������7Z��@~����a���566�`����5�������]�XG3:���8A���s�4�|&�/�EKSpkkr����1�N�H�H��n75�>���C�7��c0f��h4Af��h4A"a�v[ik��~}k���z���X���n�������w���������/��TDD������7D��\r��H7�����/s��k�\9��EDDDD�����z����2_����?�k���pp6���v;1llf���d�~3��_���nC�[x�[���W��F�a�X&����-|���5�o�������)��IE�*�������=���:�G]K���e��c�q.�Iq�����v��]_���Gss�7�����0�Z��5>��oe��s����f�c��r%�ghmM`�'��������c���;}�uF:��%��z�w
�{k�[�~$�I��TDD����y�������^@����������������Q��������l9t��y+�t��_�Y�����3�u���8���=��-�hbc�A
l���\�@��~��z,����A�q,fG4�	#��bc�����G]]���u�,�u��Nao����TW�Y�v:�6��>5���GYh�5��puZD`���� ��1�N�_L��?\��5���������T��f��=��q�S�)����n�	y�<]�]�T�\�mdRa�_�5���#T(�����e��9|�����+�3g������m � ���Y�7J�F
1����h��tBn���\������M�WW��l���>�k�=4�X0	��89����K��i|�u���l�n0j���.�����1\N��G�P���:?����K��O$�n7��L������>�`}N�iFzo��@�����������H���J��t)N��7�s�~��k��qQ��a����;�+"""""<��.�{���#-�|	�%��9��!�������-��O�_����*L�n��RK�Y����R��������}��kL��EE�t�7a�kp�����m��e'��cF"`����c�}�����x���Q]���9J~���kKu]�3��%%?�NQQ�����v�0��L��omM�tZ�;�5$�����Y�"""�P��()!\[K���:����WY���CJJ�����cM��f�������������om�������y�S;�#�o���%�o2�b3��L���|�fG1�����SXQ|�	�n�l���p��1��+e++��]�a����������m�8�KiY��
�55�_�{^#���t�n�]�7Du�H�u�����8.��y����GM1�~��\��}v���L��n^xa?�h��O���_y�f������S"p72����kkp����W�������d>�g�f)������w�(��Q@`pQ{����Q;���}�4�����Q��Tc�`�t�n�1����F�\0���f��0�n���W���<'+W�o�5��~�������{K�`x��]l�L��|�yf�6���PWa��(���0M�x�q�N~��q��TY����Oc���~�Y9^�2����K	���s�JN���=�&PcL`���E�.
9���7��lLc��|�1�F�$x��y�4���U���q4�����F{�u>ri�p^�,�����w9��S��~Wj&���~�L���^o��j��!Jkk����T�@ ��]Q^`��c�0����$31�5y_�@Se�[A�����TN����b�����^b�^�u6�6������E*���c)����WEDDDDdh��(&P@#���%�6<��y���<~oq	k�@
E��$�8����c�3Z��G���y)r1���lwL#�{�&y��1e�1�����������o���7�i��o�����<�TI�B�����>_���8�@0))qPY9���(�@���&��;
���CYY���p9��{$b����r�g�������0V���uO����2cF��a�Uo�����v��WEDDDDd�DL;����l��&����>�����{���<�B�f60���V�g��1����{Xl�1�<����_Jp���\�G�����	v^�e�������?�,��]CS�XJ	�)���	����a����eKK��-]R3�kk���V,���>�?��ji�����]o����������]m���Q��R�a{���_�h�d�lh��OP[��R@#�y�U�"""""C+���|���L �0�	lM/�j���I�26� ���1�_f��ZxvP��0��b%����f�uW�/-�����p�d��0o1������=A�M�`��]���>-:ZZ� '���f�0$`���1�~�t�x�,]:�������Y�UDDDDzvB����:�-"s�y�����c�Z{�>�a/��@*@+���a����a&$��b�4��y�U����������Ju'��w	�;� �WO�GY_(�`�G��l��lVs-�l�b4���o���q������X,��	�zj7c��������ikK�������������{�������}'\��H$���[y���<y2�^{-����������>#b��.���2��y���`iE��� ������.""""�?�������J�oD��A4��q[&��<l�YeeS)��}������)�wp6dfZ��/u����y��]��&��
���$���n��������y�z*$_�0o�XDDDD�'\��~�z���������[x���{-�{*�M�6��io�M���qz<
�EDDDD` u��H��q��q�F,�ym�|r�n�\�������������@������g�&00M��`����]*+�,[6�G���Q6
3�?D�WzQQ�z������bN��������������S__?���o�����XDDDDd�
f�U�61{�e������.s
v���*���_�gd���5�LJJ,^<���,�����kL�����?���
�QQ��b�""""�v���iv��~��~8}����620� �W���_
�A�)c��}�����������+*[�����X���K}���
���Q�;H�����4C�_����a�N��	23-|�������I[[�?�p�U�7�Y��O�/'��%CEcK����������?�����N3a�o�Naaa�m-Z��E���'O�������1��CcK�����+*[�}��A��W2T4�d�hl�P���c}�5k�,����'�����:�G%"""""�Q/""""��.p�Z���������f��	����/��/���DDDDD���EDDD�Tp���8����u�C�KRE����-
W2T4����[����
�+*[2T4�d(h\

����E"""""""""""�����������������H������������� 8���_�)S�0q�Dn��V����>$9��y��b�u^�����c����q�<�����?��Cf�������W\A 8�}��T__�\��I��2e
K�.M?��%G���/f�����q��Ws��@cK��E�:�M���cEu���x
��e(�����Z�8a�����9a����>2M�4�������:�G%��7�x�ljj2�Vk��������9s�X,f644�EEE���7M�4g��m���+�i��=��c.[�l����k������M�4�p8l�{�����?��%�b��������N�������A�v�Z��oL�M���cEu����x
��e(�����Z��qR�����9g�����_~����������c�~�m��O>�d��W����g�5���������^��,++�>r����;�_��[2�����p�Bs��e[r�B��y�9��;w�L�M���cEu����xJ��e(�����Z��rR��ihh���(}{�������#�EOc��15�}���w�^��y.��"�-4W^y%�G���O>a��%[r�|�An�������i\����"��d0�����:^��j���I���y�ANP=�����@���_$������;����hl��y�����c���<��3[rD6n���u�����;��q%����������:^���xl���?'u�^TT�������SXXx�HN=�������@���[<����c��,Y���������W���{�9�-9"o���7o������b��8������i\�1�:^Je0�����:^�j���I���5���6o���O>�UW]u��JNW]uO=��x���F�|�M.��b���)**�/��yL
d9�-X�����+��il�����455�H$x���2e����o~��������:����Z����q�u�i\�1�:^Je0�����:^��j���P7�?�^}�Us��Ifii�y��7��h�X�g,X`��YPP`�~���i&W\.--5'N�h>�����?��s�������.��<p�@����#'�7�|���S����O7�O�n���?7MScK�Lcc�9k�,�����2e�����lmm5MScKO�5��XQ/��:^���x*���hQ-���&<"""""""""""G��n)#""""""""""r�(p
�EDDDDDDDDDD�w�A��]DDDDDDDDDDd(p�A����C�P-/"2x�4�c}""r���l�b�~�����lCtD"""""���ED�f����bl6?���>}:g�u|��_~9��~:K�,Iow�wP^^NYY7�p�p���{�i��1c��M���m����������1�/���7r���3s�L�=�\6m���e������;w.]t��?"""""'(��""�?�p9����O?�5�\��w���/�����w���9���Y�v-��������#G��o}�)S��p�B�M��+�����c	������4+&�2g��}�Y


X�~=�/f��u,[��?��O�[�����cy*DDDDDN(��ED���GD�cW^y%3f�����#F��x�������^x�G}�P(���#�Hp�y�q�
7p�W��/������|�	}��^zi���{������U��������jy���w�S��bI�Z�X,8�N��b1���X�l���yyy������>������>��_�������=�g����i2a�6l���1dgg��9���9���������dff���K[[������m���3�<�{����.�(]�gee���
$g���~^}�U Y�����G�}������jT���[
�ED���M�������p�p��g����{�:u*3f�����n����3s�L.��B�v;�?�<?����>}:S�L��g�=VoGDDDD���Z^D�����"""""""""""�@3�EDDDDDDDDDD�w�A��]DDDDDDDDDDd(p�D���	?�IEND�B`�
#60Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Andres Freund (#58)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/17/24 17:38, Andres Freund wrote:

Hi,

On 2024-03-16 21:25:18 +0100, Tomas Vondra wrote:

On 3/16/24 20:12, Andres Freund wrote:

That would address some of the worst behaviour, but it doesn't really seem to
address the underlying problem of the two iterators being modified
independently. ISTM the proper fix would be to protect the state of the
iterators with a single lock, rather than pushing down the locking into the
bitmap code. OTOH, we'll only need one lock going forward, so being economic
in the effort of fixing this is also important.

Can you share some details about how you identified the problem, counted
the prefetches that happen too late, etc? I'd like to try to reproduce
this to understand the issue better.

There's two aspects. Originally I couldn't reliably reproduce the regression
with Melanie's repro on my laptop. I finally was able to do so after I
a) changed the block device's read_ahead_kb to 0
b) used effective_io_concurrency=1

That made the difference between the BitmapAdjustPrefetchIterator() locations
very significant, something like 2.3s vs 12s.

Interesting. I haven't thought about read_ahead_kb, but in hindsight it
makes sense it affects these cases. OTOH I did not set it to 0 on either
machine (the 6xSATA RAID0 has it at 12288, for example) and yet that's
how we found the regressions.

For eic it makes perfect sense that setting it to 1 is particularly
vulnerable to this issue - it only takes a small "desynchronization" of
the two iterators for the prefetch to "fall behind" and frequently
prefetch blocks we already read.

Besides a lot of other things, I finally added debugging fprintfs printing the
pid, (prefetch, read), block number. Even looking at tiny excerpts of the
large amount of output that generates shows that two iterators were out of
sync.

Thanks. I did experiment with fprintf, but it's quite cumbersome, so I
was hoping you came up with some smart way to trace this king of stuff.
For example I was wondering if ebpf would be a more convenient way.

If I understand correctly, what may happen is that a worker reads blocks
from the "prefetch" iterator, but before it manages to issue the
posix_fadvise, some other worker already did pread. Or can the iterators
get "out of sync" in a more fundamental way?

I agree that the current scheme of two shared iterators being used has some
fairly fundamental raciness. But I suspect there's more than that going on
right now.

Moving BitmapAdjustPrefetchIterator() to later drastically increases the
raciness because it means table_scan_bitmap_next_block() happens between
increasing the "real" and the "prefetch" iterators.

An example scenario that, I think, leads to the iterators being out of sync,
without there being races between iterator advancement and completing
prefetching:

start:
real -> block 0
prefetch -> block 0
prefetch_pages = 0
prefetch_target = 1

W1: tbm_shared_iterate(real) -> block 0
W2: tbm_shared_iterate(real) -> block 1
W1: BitmapAdjustPrefetchIterator() -> tbm_shared_iterate(prefetch) -> 0
W2: BitmapAdjustPrefetchIterator() -> tbm_shared_iterate(prefetch) -> 1
W1: read block 0
W2: read block 1
W1: BitmapPrefetch() -> prefetch_pages++ -> 1, tbm_shared_iterate(prefetch) -> 2, prefetch block 2
W2: BitmapPrefetch() -> nothing, as prefetch_pages == prefetch_target

W1: tbm_shared_iterate(real) -> block 2
W2: tbm_shared_iterate(real) -> block 3

W2: BitmapAdjustPrefetchIterator() -> prefetch_pages--
W2: read block 3
W2: BitmapPrefetch() -> prefetch_pages++, tbm_shared_iterate(prefetch) -> 3, prefetch block 3

So afaict here we end up prefetching a block that the *same process* just had
read.

Uh, that's very weird. I'd understood if there's some cross-process
issue, but if this happens in a single process ... strange.

ISTM that the idea of somehow "catching up" in BitmapAdjustPrefetchIterator(),
separately from advancing the "real" iterator, is pretty ugly for non-parallel
BHS and just straight up broken in the parallel case.

Yeah, I agree with the feeling it's an ugly fix. Definitely seems more
like fixing symptoms than the actual problem.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#61Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Tomas Vondra (#60)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/17/24 20:36, Tomas Vondra wrote:

...

Besides a lot of other things, I finally added debugging fprintfs printing the
pid, (prefetch, read), block number. Even looking at tiny excerpts of the
large amount of output that generates shows that two iterators were out of
sync.

Thanks. I did experiment with fprintf, but it's quite cumbersome, so I
was hoping you came up with some smart way to trace this king of stuff.
For example I was wondering if ebpf would be a more convenient way.

FWIW I just realized why I failed to identify this "late prefetch" issue
during my investigation. I was experimenting with instrumenting this by
adding a LD_PRELOAD library, logging all pread/fadvise calls. But the
FilePrefetch call is skipped in the page is already in shared buffers,
so this case "disappeared" during processing which matched the two calls
by doing an "inner join".

That being said, I think tracing this using LD_PRELOAD or perf may be
more convenient way to see what's happening. For example I ended up
doing this:

perf record -a -e syscalls:sys_enter_fadvise64 \
-e syscalls:sys_exit_fadvise64 \
-e syscalls:sys_enter_pread64 \
-e syscalls:sys_exit_pread64

perf script -ns

Alternatively, perf-trace can be used and prints the filename too (but
time has ms resolution only). Processing this seems comparable to the
fprintf approach.

It still has the issue that some of the fadvise calls may be absent if
the prefetch iterator gets too far behind, but I think that can be
detected / measured by simply counting the fadvise calls, and comparing
them to pread calls. We expect these to be about the same, so

(#pread - #fadvise) / #fadvise

is a measure of how many were "late" and skipped.

It also seems better than fprintf because it traces the actual syscalls,
not just calls to glibc wrappers. For example I saw this

postgres 54769 [001] 33768.771524828:
syscalls:sys_enter_pread64: ..., pos: 0x30d04000

postgres 54769 [001] 33768.771526867:
syscalls:sys_exit_pread64: 0x2000

postgres 54820 [000] 33768.771527473:
syscalls:sys_enter_fadvise64: ..., offset: 0x30d04000, ...

postgres 54820 [000] 33768.771528320:
syscalls:sys_exit_fadvise64: 0x0

which is clearly a case where we issue fadvise after pread of the same
block already completed.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#62Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Andres Freund (#5)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 14/02/2024 21:42, Andres Freund wrote:

On 2024-02-13 18:11:25 -0500, Melanie Plageman wrote:

patch 0004 is, I think, a bug fix. see [2].

I'd not quite call it a bugfix, it's not like it leads to wrong
behaviour. Seems more like an optimization. But whatever :)

It sure looks like bug to me, albeit a very minor one. Certainly not an
optimization, it doesn't affect performance in any way, only what
EXPLAIN reports. So committed and backported that to all supported branches.

--
Heikki Linnakangas
Neon (https://neon.tech)

#63Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#59)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Mar 17, 2024 at 3:21 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/14/24 22:39, Melanie Plageman wrote:

On Thu, Mar 14, 2024 at 5:26 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/14/24 19:16, Melanie Plageman wrote:

On Thu, Mar 14, 2024 at 03:32:04PM +0200, Heikki Linnakangas wrote:

...

Ok, committed that for now. Thanks for looking!

Attached v6 is rebased over your new commit. It also has the "fix" in
0010 which moves BitmapAdjustPrefetchIterator() back above
table_scan_bitmap_next_block(). I've also updated the Streaming Read API
commit (0013) to Thomas' v7 version from [1]. This has the update that
we theorize should address some of the regressions in the bitmapheapscan
streaming read user in 0014.

Should I rerun the benchmarks with these new patches, to see if it
really helps with the regressions?

That would be awesome!

OK, here's a couple charts comparing the effect of v6 patches to master.
These are from 1M and 10M data sets, same as the runs presented earlier
in this thread (the 10M is still running, but should be good enough for
this kind of visual comparison).

Thanks for doing this!

What is even more obvious is that 0014 behaves *VERY* differently. I'm
not sure if this is a good thing or a problem is debatable/unclear. I'm
sure we don't want to cause regressions, but perhaps those are due to
the prefetch issue discussed elsewhere in this thread (identified by
Andres and Melanie). There are also many cases that got much faster, but
the question is whether this is due to better efficiency or maybe the
new code being more aggressive in some way (not sure).

Are these with the default effective_io_concurrency (1)? If so, the
"effective" prefetch distance in many cases will be higher with the
streaming read code applied. With effective_io_concurrency 1,
"max_ios" will always be 1, but the number of blocks prefetched may
exceed this (up to MAX_BUFFERS_PER_TRANSFER) because the streaming
read code is always trying to build bigger IOs. And, if prefetching,
it will prefetch IOs not yet in shared buffers before reading them.

It's hard to tell without going into a specific repro why this would
cause some queries to be much slower. In the forced bitmapheapscan, it
would make sense that more prefetching is worse -- which is why a
bitmapheapscan plan wouldn't have been chosen. But in the optimal
cases, it is unclear why it would be worse.

I don't think there is any way it could be the issue Andres
identified, because there is only one iterator. Nothing to get out of
sync. It could be that the fadvises are being issued too close to the
reads and aren't effective enough at covering up read latency on
slower, older hardware. But that doesn't explain why master would
sometimes be faster.

Probably the only thing we can do is get into a repro. It would, of
course, be easiest to do this with a serial query. I can dig into the
scripts you shared earlier and try to find a good repro. Because the
regressions may have shifted with Thomas' new version, it would help
if you shared a category (cyclic/uniform/etc, parallel or serial, eic
value, work mem, etc) where you now see the most regressions.

- Melanie

#64Melanie Plageman
melanieplageman@gmail.com
In reply to: Heikki Linnakangas (#62)
13 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 18, 2024 at 02:10:28PM +0200, Heikki Linnakangas wrote:

On 14/02/2024 21:42, Andres Freund wrote:

On 2024-02-13 18:11:25 -0500, Melanie Plageman wrote:

patch 0004 is, I think, a bug fix. see [2].

I'd not quite call it a bugfix, it's not like it leads to wrong
behaviour. Seems more like an optimization. But whatever :)

It sure looks like bug to me, albeit a very minor one. Certainly not an
optimization, it doesn't affect performance in any way, only what EXPLAIN
reports. So committed and backported that to all supported branches.

I've attached v7 rebased over this commit.

- Melanie

Attachments:

v7-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From 2a03eb08e41300ca2a59e2185535fd3480494d20 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v7 01/13] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index e57a0b7ea31..e78d793f69c 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aabe..93fdcd226bf 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v7-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 7c3f18736677ca63df36682c89122187ab6234b2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v7 02/13] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 93fdcd226bf..c64530674bd 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -742,16 +752,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v7-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-diff; charset=us-asciiDownload
From 97d1a9563293ac6a19b31695ff315efe78f11211 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v7 03/13] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 125 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 103 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 34bc60f625f..e7bed84f75b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -951,6 +951,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1039,6 +1041,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1058,6 +1066,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 680a50bf8b1..c9b9b4c00f1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2122,6 +2123,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, and the bitmap entries don't need rechecking, and all tuples on
+	 * the page are visible to our transaction.
+	 */
+	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2234,6 +2253,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c64530674bd..81e3166d51b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,11 +185,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual == NIL && node->ss.ps.plan->targetlist == NIL)
+				extra_flags |= SO_CAN_SKIP_FETCH;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	node->ss.ps.state->es_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	extra_flags);
 		}
 
 		node->initialized = true;
@@ -207,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -228,37 +232,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -301,52 +282,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +480,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +532,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +602,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +611,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +655,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -740,8 +698,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f68593..3dfb19ec7d5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8249b37bbf1..c43a8b3dea5 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed.
+	 */
+	SO_CAN_SKIP_FETCH = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -944,9 +951,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 92593526725..76153b63d76 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1712,10 +1712,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1735,9 +1732,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v7-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-diff; charset=us-asciiDownload
From 445f49b91876a3eb94f281e9622e23ffdafff47f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v7 04/13] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 81e3166d51b..dc8c312cafb 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -474,15 +474,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
-
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -533,7 +527,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v7-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-diff; charset=us-asciiDownload
From e3c76cfe8f88346e45e30a16b098efc16c4f314c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v7 05/13] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index dc8c312cafb..a6b98fa12a1 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -230,7 +230,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -341,7 +341,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -360,7 +360,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v7-0006-table_scan_bitmap_next_block-returns-lossy-or-exa.patchtext/x-diff; charset=us-asciiDownload
From 842be33052d781fc368d1e371448bd28c9fe4bd5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v7 06/13] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c9b9b4c00f1..10c1c3b616b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,7 +2112,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2240,6 +2241,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a6b98fa12a1..b2397fe2054 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
+		bool		valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -232,12 +232,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index c43a8b3dea5..f1d0d4b78e3 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -796,6 +796,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -811,7 +814,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1951,14 +1955,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1969,7 +1975,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.40.1

v7-0007-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-diff; charset=us-asciiDownload
From 9488a9cd0704af64dae236c322ec0250a1acc934 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v7 07/13] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b2397fe2054..94a5e2da17c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +202,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -221,9 +219,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v7-0008-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-diff; charset=us-asciiDownload
From dd1264816e4612735ac43292d092e6d3c742d6bc Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v7 08/13] Remove table_scan_bitmap_next_tuple parameter tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 10c1c3b616b..a1ec50ab7a8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2248,7 +2248,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 94a5e2da17c..bbdaa591891 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -286,7 +286,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index f1d0d4b78e3..e35bd36e710 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -787,10 +787,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -821,15 +818,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -1988,7 +1980,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2000,7 +1991,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v7-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 3bcfc23d4eac0581eb10b5e9b1c69a411304ae50 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v7 09/13] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 195 insertions(+), 149 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a1ec50ab7a8..e038e60cd8f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,18 +2112,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, and the bitmap entries don't need rechecking, and all tuples on
@@ -2142,16 +2175,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2243,7 +2267,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index bbdaa591891..b1dfa582c7d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +109,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +161,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -202,55 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool		valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -272,45 +232,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno > node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,13 +311,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -356,14 +335,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -388,7 +370,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -466,6 +451,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -523,6 +509,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
 							  !tbmpre->recheck &&
@@ -584,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -597,13 +581,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -634,28 +618,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -688,8 +668,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -697,9 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e35bd36e710..d214abeb201 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -780,19 +781,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -811,8 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -949,9 +945,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1011,6 +1011,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1021,6 +1036,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1944,19 +1974,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1966,8 +1994,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 76153b63d76..3b136782f38 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1710,8 +1710,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1720,9 +1718,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1730,8 +1730,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1740,9 +1738,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v7-0010-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From adc021b783f1f591f6e8e46405aa4c3ac617740a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v7 10/13] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 29 +++++++----------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..d2bf8f44d50 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1467,8 +1453,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..432fae52962 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.40.1

v7-0011-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchtext/x-diff; charset=us-asciiDownload
From bea77dce5cbb967edf5961352013283818bf1369 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v7 11/13] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 38 ++++++------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 7 files changed, 108 insertions(+), 91 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3aa457a29e1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..033d5253394 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e038e60cd8f..022753e203a 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,7 +2119,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2132,11 +2132,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		CHECK_FOR_INTERRUPTS();
 
 		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbm_iterate(scan->tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2151,11 +2151,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2163,19 +2163,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * the page are visible to our transaction.
 	 */
 	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2204,7 +2204,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2213,9 +2213,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2265,7 +2265,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	*lossy = tbmres.ntuples < 0;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b1dfa582c7d..43df0ac9964 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -321,7 +321,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -335,8 +335,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,8 +371,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -440,10 +440,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
@@ -451,7 +453,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +462,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +483,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,8 +502,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_shared_iterate(prefetch_iterator);
@@ -509,17 +511,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index d2bf8f44d50..7d038c2018d 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..3b432263bb0 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae52962..f000c1af28f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.40.1

v7-0012-v7-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From 4126c2da2e963409055de628328419e577f6fc0c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:59:42 -0400
Subject: [PATCH v7 12/13] v7 Streaming Read API

---
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 659 +++++++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 642 +++++++++++++++-------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/include/storage/bufmgr.h             |  45 ++
 src/include/storage/streaming_read.h     |  52 ++
 src/tools/pgindent/typedefs.list         |   3 +
 10 files changed, 1227 insertions(+), 210 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca20..eec03f6f2b4 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 00000000000..bcab44c802f
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 00000000000..39aef2a84a2
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 00000000000..d5c29b750d9
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,659 @@
+#include "postgres.h"
+
+#include "catalog/pg_tablespace.h"
+#include "miscadmin.h"
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+#include "utils/spccache.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		need_wait;
+	bool		advice_issued;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index;
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+	ReadBuffersOperation operation;
+} PgStreamingReadRange;
+
+/*
+ * Streaming read object.
+ */
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			next_tail_buffer;
+	int			distance;
+	bool		started;
+	bool		finished;
+	bool		advice_enabled;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	/* Sometimes we need to buffer one block for flow control. */
+	BlockNumber unget_blocknum;
+	void	   *unget_per_buffer_data;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+	Oid			tablespace_id;
+
+	/*
+	 * Make sure our bmr's smgr and persistent are populated.  The caller
+	 * asserts that the storage manager will remain valid.
+	 */
+	if (!bmr.smgr)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	tablespace_id = bmr.smgr->smgr_rlocator.locator.spcOid;
+	if (!OidIsValid(MyDatabaseId) ||
+		(bmr.rel && IsCatalogRelation(bmr.rel)) ||
+		IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
+	{
+		/*
+		 * Avoid circularity while trying to look up tablespace settings or
+		 * before spccache.c is ready.
+		 */
+		max_ios = effective_io_concurrency;
+	}
+	else if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
+	else
+		max_ios = get_tablespace_io_concurrency(tablespace_id);
+
+	/*
+	 * Choose a maximum number of buffers we're prepared to pin.  We try to
+	 * pin fewer if we can, though.  We clamp it to at least
+	 * MAX_BUFFER_PER_TRANSFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/* Don't allow this backend to pin more than its share of buffers. */
+	if (SmgrIsTemp(bmr.smgr))
+		LimitAdditionalLocalPins(&max_pinned_buffers);
+	else
+		LimitAdditionalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+	pgsr->callback = next_block_cb;
+	pgsr->bmr = bmr;
+	pgsr->forknum = forknum;
+
+	pgsr->unget_blocknum = InvalidBlockNumber;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * Skip the initial ramp-up phase if the caller says we're going to be
+	 * reading the whole relation.  This way we start out doing full-sized
+	 * reads.
+	 */
+	if (flags & PGSR_FLAG_FULL)
+		pgsr->distance = Min(MAX_BUFFERS_PER_TRANSFER, pgsr->max_pinned_buffers);
+	else
+		pgsr->distance = 1;
+
+	/*
+	 * Space for the callback to store extra data along with each block.  Note
+	 * that we need one more than max_pinned_buffers, so we can return a
+	 * pointer to a slot that can't be overwritten until the next call.
+	 */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * size);
+
+	return pgsr;
+}
+
+/*
+ * Find the per-buffer data index for the Nth block of a range.
+ */
+static int
+get_per_buffer_data_index(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	int			result;
+
+	/*
+	 * Find slot in the circular buffer of per-buffer data, without using the
+	 * expensive % operator.
+	 */
+	result = range->per_buffer_data_index + n;
+	while (result >= pgsr->size)
+		result -= pgsr->size;
+	Assert(result == (range->per_buffer_data_index + n) % pgsr->size);
+
+	return result;
+}
+
+/*
+ * Return a pointer to the per-buffer data by index.
+ */
+static void *
+get_per_buffer_data_by_index(PgStreamingRead *pgsr, int per_buffer_data_index)
+{
+	return (char *) pgsr->per_buffer_data +
+		pgsr->per_buffer_data_size * per_buffer_data_index;
+}
+
+/*
+ * Return a pointer to the per-buffer data for the Nth block of a range.
+ */
+static void *
+get_per_buffer_data(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	return get_per_buffer_data_by_index(pgsr,
+										get_per_buffer_data_index(pgsr,
+																  range,
+																  n));
+}
+
+/*
+ * Start reading the head range, and create a new head range.  The new head
+ * range is returned.  It may not be empty, if StartReadBuffers() couldn't
+ * start the entire range; in that case the returned range contains the
+ * remaining portion of the range.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_start_head_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+	PgStreamingReadRange *new_head_range;
+	int			nblocks_pinned;
+	int			flags;
+
+	/* Caller should make sure we never exceed max_ios. */
+	Assert((pgsr->ios_in_progress < pgsr->max_ios) ||
+		   (pgsr->ios_in_progress == 0 && pgsr->max_ios == 0));
+
+	/* Should only call if the head range has some blocks to read. */
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If advice hasn't been suppressed, and this system supports it, this
+	 * isn't a strictly sequential pattern, then we'll issue advice.
+	 */
+	if (pgsr->advice_enabled &&
+		pgsr->max_ios > 0 &&
+		pgsr->started &&
+		head_range->blocknum != pgsr->seq_blocknum)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else
+		flags = 0;
+
+	/* Suppress advice on the first call, because it's too late to benefit. */
+	if (!pgsr->started)
+		pgsr->started = true;
+
+	/* We shouldn't be trying to pin more buffers that we're allowed to. */
+	Assert(pgsr->pinned_buffers + head_range->nblocks <= pgsr->max_pinned_buffers);
+
+	/* Start reading as many blocks as we can from the head range. */
+	nblocks_pinned = head_range->nblocks;
+	head_range->need_wait =
+		StartReadBuffers(pgsr->bmr,
+						 head_range->buffers,
+						 pgsr->forknum,
+						 head_range->blocknum,
+						 &nblocks_pinned,
+						 pgsr->strategy,
+						 flags,
+						 &head_range->operation);
+
+	Assert(pgsr->pinned_buffers <= pgsr->max_pinned_buffers);
+
+	if (head_range->need_wait && (flags & READ_BUFFERS_ISSUE_ADVICE))
+	{
+		/*
+		 * Since we've issued advice, we count an I/O in progress until we
+		 * call WaitReadBuffers().
+		 */
+		head_range->advice_issued = true;
+		pgsr->ios_in_progress++;
+		Assert(pgsr->ios_in_progress <= pgsr->max_ios);
+	}
+
+	/*
+	 * StartReadBuffers() might have pinned fewer blocks than we asked it to,
+	 * but always at least one.
+	 */
+	Assert(nblocks_pinned <= head_range->nblocks);
+	Assert(nblocks_pinned >= 1);
+	pgsr->pinned_buffers += nblocks_pinned;
+
+	/*
+	 * Remember where the next block would be after that, so we can detect
+	 * sequential access next time.
+	 */
+	pgsr->seq_blocknum = head_range->blocknum + nblocks_pinned;
+
+	/*
+	 * Create a new head range.  There must be space, because we have enough
+	 * elements for every range to hold just one block, up to the pin limit.
+	 */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	new_head_range = &pgsr->ranges[pgsr->head];
+	new_head_range->nblocks = 0;
+	new_head_range->advice_issued = false;
+
+	/*
+	 * If we didn't manage to start the whole read above, we split the range,
+	 * moving the remainder into the new head range.
+	 */
+	if (nblocks_pinned < head_range->nblocks)
+	{
+		int			nblocks_remaining = head_range->nblocks - nblocks_pinned;
+
+		head_range->nblocks = nblocks_pinned;
+
+		new_head_range->blocknum = head_range->blocknum + nblocks_pinned;
+		new_head_range->nblocks = nblocks_remaining;
+	}
+
+	/* The new range has per-buffer data starting after the previous range. */
+	new_head_range->per_buffer_data_index =
+		get_per_buffer_data_index(pgsr, head_range, nblocks_pinned);
+
+	return new_head_range;
+}
+
+/*
+ * Ask the callback which block it would like us to read next, with a small
+ * buffer in front to allow pg_streaming_unget_block() to work.
+ */
+static BlockNumber
+pg_streaming_get_block(PgStreamingRead *pgsr, void *per_buffer_data)
+{
+	BlockNumber result;
+
+	if (unlikely(pgsr->unget_blocknum != InvalidBlockNumber))
+	{
+		/*
+		 * If we had to unget a block, now it is time to return that one
+		 * again.
+		 */
+		result = pgsr->unget_blocknum;
+		pgsr->unget_blocknum = InvalidBlockNumber;
+
+		/*
+		 * The same per_buffer_data element must have been used, and still
+		 * contains whatever data the callback wrote into it.  So we just
+		 * sanity-check that we were called with the value that
+		 * pg_streaming_unget_block() pushed back.
+		 */
+		Assert(per_buffer_data == pgsr->unget_per_buffer_data);
+	}
+	else
+	{
+		/* Use the installed callback directly. */
+		result = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+	}
+
+	return result;
+}
+
+/*
+ * In order to deal with short reads in StartReadBuffers(), we sometimes need
+ * to defer handling of a block until later.  This *must* be called with the
+ * last value returned by pg_streaming_get_block().
+ */
+static void
+pg_streaming_unget_block(PgStreamingRead *pgsr, BlockNumber blocknum, void *per_buffer_data)
+{
+	Assert(pgsr->unget_blocknum == InvalidBlockNumber);
+	pgsr->unget_blocknum = blocknum;
+	pgsr->unget_per_buffer_data = per_buffer_data;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *range;
+
+	/* If we're finished, don't look ahead. */
+	if (pgsr->finished)
+		return;
+
+	/*
+	 * We we've already started the maximum allowed number of I/Os, don't look
+	 * ahead.  There is a special case for max_ios == 0.
+	 */
+	if (pgsr->max_ios > 0 && pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/* Can't pin any more buffers. */
+	if (pgsr->pinned_buffers == pgsr->distance)
+		return;
+
+	/*
+	 * Keep trying to add new blocks to the end of the head range while doing
+	 * so wouldn't exceed the distance limit.
+	 */
+	range = &pgsr->ranges[pgsr->head];
+	while (pgsr->pinned_buffers + range->nblocks < pgsr->distance)
+	{
+		BlockNumber blocknum;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		if (range->nblocks == lengthof(range->buffers))
+		{
+			/* Start as much of it as we can. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/* If we're now at the I/O limit, stop here. */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+				return;
+
+			/*
+			 * That might have only been partially started, but always
+			 * processes at least one so that'll do for now.
+			 */
+			Assert(range->nblocks < lengthof(range->buffers));
+		}
+
+		/* Find per-buffer data slot for the next block. */
+		per_buffer_data = get_per_buffer_data(pgsr, range, range->nblocks);
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pg_streaming_get_block(pgsr, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			/* End of stream. */
+			pgsr->finished = true;
+			break;
+		}
+
+		/*
+		 * Is there a head range that we cannot extend, because the requested
+		 * block is not consecutive?
+		 */
+		if (range->nblocks > 0 &&
+			range->blocknum + range->nblocks != blocknum)
+		{
+			/* Yes.  Start it, so we can begin building a new one. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * It's possible that it was only partially started, and we have a
+			 * new range with the remainder.  Keep starting I/Os until we get
+			 * it all out of the way, or we hit the I/O limit.
+			 */
+			while (range->nblocks > 0 && pgsr->ios_in_progress < pgsr->max_ios)
+				range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * We do have to worry about I/O capacity running out if the head
+			 * range was split.  In that case we have to 'unget' the block
+			 * returned by the callback.
+			 */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+			{
+				pg_streaming_unget_block(pgsr, blocknum, per_buffer_data);
+				return;
+			}
+		}
+
+		/* If we have a new, empty range, initialize the start block. */
+		if (range->nblocks == 0)
+			range->blocknum = blocknum;
+
+		/* This block extends the range by one. */
+		Assert(range->blocknum + range->nblocks == blocknum);
+		range->nblocks++;
+	};
+
+	/*
+	 * Normally we don't start the head range, preferring to give it a chance
+	 * to grow to full size once more buffers have been consumed.  In cases
+	 * where that can't possibly happen, we might as well start the read
+	 * immediately.
+	 */
+	if ((range->nblocks > 0 && pgsr->finished) ||
+		(range->nblocks == pgsr->distance))
+		pg_streaming_read_start_head_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	PgStreamingReadRange *tail_range;
+
+	for (;;)
+	{
+		if (pgsr->tail != pgsr->head)
+		{
+			tail_range = &pgsr->ranges[pgsr->tail];
+
+			/*
+			 * Do we need to wait for a ReadBuffers operation to finish before
+			 * returning the buffers in this range?
+			 */
+			if (tail_range->need_wait)
+			{
+				int			distance;
+
+				Assert(pgsr->next_tail_buffer == 0);
+				WaitReadBuffers(&tail_range->operation);
+				tail_range->need_wait = false;
+
+				/*
+				 * We don't really know if the kernel generated a physical I/O
+				 * when we issued advice, let alone when it finished, but it
+				 * has certainly finished now because we've performed the
+				 * read.
+				 */
+				if (tail_range->advice_issued)
+				{
+
+					Assert(pgsr->ios_in_progress > 0);
+					pgsr->ios_in_progress--;
+
+					/*
+					 * Look-ahead distance ramps up rapidly if we're issuing
+					 * advice, so we can search for new more I/Os to start.
+					 */
+					distance = pgsr->distance * 2;
+					distance = Min(distance, pgsr->max_pinned_buffers);
+					pgsr->distance = distance;
+				}
+				else
+				{
+					/*
+					 * There is no point in increasing look-ahead distance if
+					 * we've already reached the full I/O size, since we're
+					 * not issuing advice.  Extra distance would only pin more
+					 * buffers for no benefit.
+					 */
+					if (pgsr->distance > MAX_BUFFERS_PER_TRANSFER)
+					{
+						/*
+						 * Look-ahead distance gradually decays to full I/O
+						 * size.
+						 */
+						pgsr->distance--;
+					}
+					else
+					{
+						/*
+						 * Look-ahead distance ramps up rapidly, but not more
+						 * that the full I/O size.
+						 */
+						distance = pgsr->distance * 2;
+						distance = Min(distance, MAX_BUFFERS_PER_TRANSFER);
+						distance = Min(distance, pgsr->max_pinned_buffers);
+						pgsr->distance = distance;
+					}
+				}
+			}
+			else if (pgsr->next_tail_buffer == 0)
+			{
+				/* No I/O necessary. Look-ahead distance gradually decays. */
+				if (pgsr->distance > 1)
+					pgsr->distance--;
+			}
+
+			/* Are there more buffers available in this range? */
+			if (pgsr->next_tail_buffer < tail_range->nblocks)
+			{
+				int			buffer_index;
+				Buffer		buffer;
+
+				buffer_index = pgsr->next_tail_buffer++;
+				buffer = tail_range->buffers[buffer_index];
+
+				Assert(BufferIsValid(buffer));
+
+				/* We are giving away ownership of this pinned buffer. */
+				Assert(pgsr->pinned_buffers > 0);
+				pgsr->pinned_buffers--;
+
+				if (per_buffer_data)
+					*per_buffer_data = get_per_buffer_data(pgsr, tail_range, buffer_index);
+
+				/* We may be able to get another I/O started. */
+				pg_streaming_read_look_ahead(pgsr);
+
+				return buffer;
+			}
+
+			/* Advance tail to next range. */
+			if (++pgsr->tail == pgsr->size)
+				pgsr->tail = 0;
+			pgsr->next_tail_buffer = 0;
+		}
+		else
+		{
+			/*
+			 * If tail crashed into head, and head is not empty, then it is
+			 * time to start that range.  Otherwise, force a look-ahead, to
+			 * kick start the stream.
+			 */
+			Assert(pgsr->tail == pgsr->head);
+			if (pgsr->ranges[pgsr->head].nblocks > 0)
+			{
+				pg_streaming_read_start_head_range(pgsr);
+			}
+			else
+			{
+				pg_streaming_read_look_ahead(pgsr);
+
+				/* Finished? */
+				if (pgsr->tail == pgsr->head &&
+					pgsr->ranges[pgsr->head].nblocks == 0)
+					break;
+			}
+		}
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead. */
+	pgsr->finished = true;
+
+	/* Unpin anything that wasn't consumed. */
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	Assert(pgsr->pinned_buffers == 0);
+	Assert(pgsr->ios_in_progress == 0);
+
+	/* Release memory. */
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f0f8d4259c5..d0e9c7deffa 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -19,6 +19,11 @@
  *		and pin it so that no one can destroy it while this process
  *		is using it.
  *
+ * StartReadBuffers() -- as above, but for multiple contiguous blocks in
+ *		two steps.
+ *
+ * WaitReadBuffers() -- second step of StartReadBuffers().
+ *
  * ReleaseBuffer() -- unpin a buffer
  *
  * MarkBufferDirty() -- mark a pinned buffer's contents as "dirty".
@@ -471,10 +476,9 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
-								ReadBufferMode mode, BufferAccessStrategy strategy,
-								bool *hit);
+								ReadBufferMode mode, BufferAccessStrategy strategy);
 static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
 										   ForkNumber fork,
 										   BufferAccessStrategy strategy,
@@ -500,7 +504,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -781,7 +785,6 @@ Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
-	bool		hit;
 	Buffer		buf;
 
 	/*
@@ -794,15 +797,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
-							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+	buf = ReadBuffer_common(BMR_REL(reln),
+							forkNum, blockNum, mode, strategy);
+
 	return buf;
 }
 
@@ -822,13 +819,12 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 						  BlockNumber blockNum, ReadBufferMode mode,
 						  BufferAccessStrategy strategy, bool permanent)
 {
-	bool		hit;
-
 	SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
-							 mode, strategy, &hit);
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
+							 mode, strategy);
 }
 
 /*
@@ -994,35 +990,68 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 	 */
 	if (buffer == InvalidBuffer)
 	{
-		bool		hit;
-
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
-								   fork, extend_to - 1, mode, strategy,
-								   &hit);
+		buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
 	}
 
 	return buffer;
 }
 
+/*
+ * Zero a buffer and lock it, as part of the implementation of
+ * RBM_ZERO_AND_LOCK or RBM_ZERO_AND_CLEANUP_LOCK.  The buffer must be already
+ * pinned.  It does not have to be valid, but it is valid and locked on
+ * return.
+ */
+static void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * ReadBuffer_common -- common logic for all ReadBuffer variants
  *
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
-				  BufferAccessStrategy strategy, bool *hit)
+				  BufferAccessStrategy strategy)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	ReadBuffersOperation operation;
+	Buffer		buffer;
+	int			nblocks;
+	int			flags;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1041,181 +1070,405 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	nblocks = 1;
+	if (mode == RBM_ZERO_ON_ERROR)
+		flags = READ_BUFFERS_ZERO_ON_ERROR;
+	else
+		flags = 0;
+	if (StartReadBuffers(bmr,
+						 &buffer,
+						 forkNum,
+						 blockNum,
+						 &nblocks,
+						 strategy,
+						 flags,
+						 &operation))
+		WaitReadBuffers(&operation);
+	Assert(nblocks == 1);		/* single block can't be short */
+
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+		ZeroBuffer(buffer, mode);
+
+	return buffer;
+}
 
+static Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	Assert(bmr.smgr);
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * WaitReadBuffers() (so, not for hits, and not for buffers that are
+		 * zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+/*
+ * Begin reading a range of blocks beginning at blockNum and extending for
+ * *nblocks.  On return, up to *nblocks pinned buffers holding those blocks
+ * are written into the buffers array, and *nblocks is updated to contain the
+ * actual number, which may be fewer than requested.
+ *
+ * If false is returned, no I/O is necessary and WaitReadBuffers() is not
+ * necessary.  If true is returned, one I/O has been started, and
+ * WaitReadBuffers() must be called with the same operation object before the
+ * buffers are accessed.  Along with the operation object, the caller-supplied
+ * array of buffers must remain valid until WaitReadBuffers() is called.
+ *
+ * Currently the I/O is only started with optional operating system advice,
+ * and the real I/O happens in WaitReadBuffers().  In future work, true I/O
+ * could be initiated here.
+ */
+bool
+StartReadBuffers(BufferManagerRelation bmr,
+				 Buffer *buffers,
+				 ForkNumber forkNum,
+				 BlockNumber blockNum,
+				 int *nblocks,
+				 BufferAccessStrategy strategy,
+				 int flags,
+				 ReadBuffersOperation *operation)
+{
+	int			actual_nblocks = *nblocks;
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
 	}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+	operation->bmr = bmr;
+	operation->forknum = forkNum;
+	operation->blocknum = blockNum;
+	operation->buffers = buffers;
+	operation->nblocks = actual_nblocks;
+	operation->strategy = strategy;
+	operation->flags = flags;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	operation->io_buffers_len = 0;
 
-	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
-	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
-	else
+	for (int i = 0; i < actual_nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		bool		found;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+		buffers[i] = PrepareReadBuffer(bmr,
+									   forkNum,
+									   blockNum + i,
+									   strategy,
+									   &found);
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		if (found)
+		{
+			/*
+			 * Terminate the read as soon as we get a hit.  It could be a
+			 * single buffer hit, or it could be a hit that follows a readable
+			 * range.  We don't want to create more than one readable range,
+			 * so we stop here.
+			 */
+			actual_nblocks = operation->nblocks = *nblocks = i + 1;
+			break;
+		}
+		else
+		{
+			/* Extend the readable range to cover this block. */
+			operation->io_buffers_len++;
+		}
+	}
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+	if (operation->io_buffers_len > 0)
+	{
+		if (flags & READ_BUFFERS_ISSUE_ADVICE)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
-			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
-			}
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
+			/*
+			 * In theory we should only do this if PrepareReadBuffers() had to
+			 * allocate new buffers above.  That way, if two calls to
+			 * StartReadBuffers() were made for the same blocks before
+			 * WaitReadBuffers(), only the first would issue the advice.
+			 * That'd be a better simulation of true asynchronous I/O, which
+			 * would only start the I/O once, but isn't done here for
+			 * simplicity.  Note also that the following call might actually
+			 * issue two advice calls if we cross a segment boundary; in a
+			 * true asynchronous version we might choose to process only one
+			 * real I/O at a time in that case.
+			 */
+			smgrprefetch(bmr.smgr, forkNum, blockNum, operation->io_buffers_len);
 		}
+
+		/* Indicate that WaitReadBuffers() should be called. */
+		return true;
 	}
+	else
+	{
+		return false;
+	}
+}
 
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
+static inline bool
+WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
 	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
+
+void
+WaitReadBuffers(ReadBuffersOperation *operation)
+{
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	int			nblocks;
+	BlockNumber blocknum;
+	ForkNumber	forknum;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	/*
+	 * Currently operations are only allowed to include a read of some range,
+	 * with an optional extra buffer that is already pinned at the end.  So
+	 * nblocks can be at most one more than io_buffers_len.
+	 */
+	Assert((operation->nblocks == operation->io_buffers_len) ||
+		   (operation->nblocks == operation->io_buffers_len + 1));
 
+	/* Find the range of the physical read we need to perform. */
+	nblocks = operation->io_buffers_len;
+	if (nblocks == 0)
+		return;					/* nothing to do */
+
+	buffers = &operation->buffers[0];
+	blocknum = operation->blocknum;
+	forknum = operation->forknum;
+	bmr = operation->bmr;
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
-
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
 	}
 	else
 	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
+		io_context = IOContextForStrategy(operation->strategy);
+		io_object = IOOBJECT_RELATION;
 	}
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+	/*
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
+	 */
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
+	else
+		pgBufferUsage.shared_blks_read += nblocks;
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+	for (int i = 0; i < nblocks; ++i)
+	{
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!WaitReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
+
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   WaitReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
+		{
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
+			{
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
+			}
+			else
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
+
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
+
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
+
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
+
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
- * BufferAlloc -- subroutine for ReadBuffer.  Handles lookup of a shared
- *		buffer.  If no buffer exists already, selects a replacement
- *		victim and evicts the old page, but does NOT read in new page.
+ * BufferAlloc -- subroutine for StartReadBuffers.  Handles lookup of a shared
+ *		buffer.  If no buffer exists already, selects a replacement victim and
+ *		evicts the old page, but does NOT read in new page.
  *
  * "strategy" can be a buffer replacement strategy object, or NULL for
  * the default strategy.  The selected buffer's usage_count is advanced when
@@ -1223,11 +1476,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1286,19 +1535,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1363,19 +1603,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1407,15 +1638,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1769,7 +1994,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2034,7 +2259,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2057,7 +2282,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2372,7 +2597,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if StartReadBuffers() was called and
+		 * WaitReadBuffers() hasn't been called yet.  We'll check by loading
+		 * the flags without locking.  This is racy, but it's OK to return
+		 * false spuriously: when WaitReadBuffers() calls StartBufferIO(),
+		 * it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2381,7 +2611,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3449,7 +3679,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -5184,9 +5414,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5199,6 +5435,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index fcfac335a57..985a2c7049c 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -108,10 +108,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -287,7 +286,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -297,9 +296,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca27..739d13293fb 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d3353..b57f71f97e3 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,42 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+
+#define READ_BUFFERS_ZERO_ON_ERROR 0x01
+#define READ_BUFFERS_ISSUE_ADVICE 0x02
+
+/*
+ * Private state used by StartReadBuffers() and WaitReadBuffers().  Declared
+ * in public header only to allow inclusion in other structs, but contents
+ * should not be accessed.
+ */
+struct ReadBuffersOperation
+{
+	/* Parameters passed in to StartReadBuffers(). */
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	ForkNumber	forknum;
+	BlockNumber blocknum;
+	int			nblocks;
+	BufferAccessStrategy strategy;
+	int			flags;
+
+	/* Range of buffers, if we need to perform a read. */
+	int			io_buffers_len;
+};
+
+typedef struct ReadBuffersOperation ReadBuffersOperation;
+
+extern bool StartReadBuffers(BufferManagerRelation bmr,
+							 Buffer *buffers,
+							 ForkNumber forknum,
+							 BlockNumber blocknum,
+							 int *nblocks,
+							 BufferAccessStrategy strategy,
+							 int flags,
+							 ReadBuffersOperation *operation);
+extern void WaitReadBuffers(ReadBuffersOperation *operation);
+
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -250,6 +292,9 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 00000000000..c4d3892bb26
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,52 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+/*
+ * We usually ramp up from smaller reads to larger ones, to support users who
+ * don't know if it's worth reading lots of buffers yet.  This flag disables
+ * that, declaring ahead of time that we'll be reading all available buffers.
+ */
+#define PGSR_FLAG_FULL 0x04
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 042d04c8de2..3ea4d350242 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2102,6 +2102,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
@@ -2273,6 +2275,7 @@ ReInitializeDSMForeignScan_function
 ReScanForeignScan_function
 ReadBufPtrType
 ReadBufferMode
+ReadBuffersOperation
 ReadBytePtrType
 ReadExtraTocPtrType
 ReadFunc
-- 
2.40.1

v7-0013-BitmapHeapScan-uses-streaming-read-API.patchtext/x-diff; charset=us-asciiDownload
From bea56f91232e835f02dd0a6d8de8f373bd9ac397 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:04:18 -0500
Subject: [PATCH v7 13/13] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
---
 src/backend/access/heap/heapam.c          |  68 +++++
 src/backend/access/heap/heapam_handler.c  |  88 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 353 +---------------------
 src/include/access/heapam.h               |   4 +
 src/include/access/tableam.h              |  22 +-
 src/include/nodes/execnodes.h             |  22 --
 6 files changed, 116 insertions(+), 441 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index e7bed84f75b..0f370bfec3e 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -111,6 +111,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -331,6 +333,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -951,6 +969,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
 
@@ -1089,6 +1108,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10246,3 +10268,49 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (hdesc->rs_base.shared_tbmiterator)
+			tbm_shared_iterate(hdesc->rs_base.shared_tbmiterator, tbmres);
+		else
+			tbm_iterate(hdesc->rs_base.tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		if (hdesc->rs_base.rs_flags & SO_CAN_SKIP_FETCH &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 022753e203a..9727613e87f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2111,79 +2111,65 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck, bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (scan->shared_tbmiterator)
-			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
-		else
-			tbm_iterate(scan->tbmiterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, and the bitmap entries don't need rechecking, and all tuples on
-	 * the page are visible to our transaction.
-	 */
-	if (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2204,7 +2190,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2213,9 +2199,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2265,7 +2251,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres.ntuples < 0;
+	*lossy = tbmres->ntuples < 0;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 43df0ac9964..c437718f980 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -86,14 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -109,15 +97,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
 		}
 		else
 		{
@@ -140,20 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
 
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
@@ -161,14 +126,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -212,37 +169,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -264,28 +190,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		}
 
 new_page:
-
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy))
 			break;
 
 		if (lossy)
 			node->lossy_pages++;
 		else
 			node->exact_pages++;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
-			node->pfblockno > node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -309,225 +220,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (scan->rs_flags & SO_CAN_SKIP_FETCH &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -573,23 +265,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -628,16 +309,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -670,18 +345,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -721,13 +389,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -804,14 +465,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -842,11 +499,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3dfb19ec7d5..1cad9c04f01 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d214abeb201..5a963f9293f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -792,23 +792,11 @@ typedef struct TableAmRoutine
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+	bool		(*scan_bitmap_next_block) (TableScanDesc scan, bool *recheck,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1983,8 +1971,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+table_scan_bitmap_next_block(TableScanDesc scan, bool *recheck, bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1994,8 +1981,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck, lossy);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 3b136782f38..bcffe309913 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1685,11 +1685,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1697,10 +1694,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1710,19 +1704,11 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1730,19 +1716,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

#65Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#63)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/18/24 15:47, Melanie Plageman wrote:

On Sun, Mar 17, 2024 at 3:21 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/14/24 22:39, Melanie Plageman wrote:

On Thu, Mar 14, 2024 at 5:26 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/14/24 19:16, Melanie Plageman wrote:

On Thu, Mar 14, 2024 at 03:32:04PM +0200, Heikki Linnakangas wrote:

...

Ok, committed that for now. Thanks for looking!

Attached v6 is rebased over your new commit. It also has the "fix" in
0010 which moves BitmapAdjustPrefetchIterator() back above
table_scan_bitmap_next_block(). I've also updated the Streaming Read API
commit (0013) to Thomas' v7 version from [1]. This has the update that
we theorize should address some of the regressions in the bitmapheapscan
streaming read user in 0014.

Should I rerun the benchmarks with these new patches, to see if it
really helps with the regressions?

That would be awesome!

OK, here's a couple charts comparing the effect of v6 patches to master.
These are from 1M and 10M data sets, same as the runs presented earlier
in this thread (the 10M is still running, but should be good enough for
this kind of visual comparison).

Thanks for doing this!

What is even more obvious is that 0014 behaves *VERY* differently. I'm
not sure if this is a good thing or a problem is debatable/unclear. I'm
sure we don't want to cause regressions, but perhaps those are due to
the prefetch issue discussed elsewhere in this thread (identified by
Andres and Melanie). There are also many cases that got much faster, but
the question is whether this is due to better efficiency or maybe the
new code being more aggressive in some way (not sure).

Are these with the default effective_io_concurrency (1)? If so, the
"effective" prefetch distance in many cases will be higher with the
streaming read code applied. With effective_io_concurrency 1,
"max_ios" will always be 1, but the number of blocks prefetched may
exceed this (up to MAX_BUFFERS_PER_TRANSFER) because the streaming
read code is always trying to build bigger IOs. And, if prefetching,
it will prefetch IOs not yet in shared buffers before reading them.

No, it's a mix of runs with random combinations of these parameters:

dataset: uniform uniform_pages linear linear_fuzz cyclic cyclic_fuzz
workers: 0 4
work_mem: 128kB 4MB 64MB
eic: 0 1 8 16 32
selectivity: 0-100%

I can either share the data (~70MB of CSV) or generate charts for
results with some filter.

It's hard to tell without going into a specific repro why this would
cause some queries to be much slower. In the forced bitmapheapscan, it
would make sense that more prefetching is worse -- which is why a
bitmapheapscan plan wouldn't have been chosen. But in the optimal
cases, it is unclear why it would be worse.

Yes, not sure about the optimal cases. I'll wait for the 10M runs to
complete, and then we can look for some patterns.

I don't think there is any way it could be the issue Andres
identified, because there is only one iterator. Nothing to get out of
sync. It could be that the fadvises are being issued too close to the
reads and aren't effective enough at covering up read latency on
slower, older hardware. But that doesn't explain why master would
sometimes be faster.

Ah, right, thanks for the clarification. I forgot the streaming read API
does not use the two-iterator approach.

Probably the only thing we can do is get into a repro. It would, of
course, be easiest to do this with a serial query. I can dig into the
scripts you shared earlier and try to find a good repro. Because the
regressions may have shifted with Thomas' new version, it would help
if you shared a category (cyclic/uniform/etc, parallel or serial, eic
value, work mem, etc) where you now see the most regressions.

OK, I've restarted the tests for only 0012 and 0014 patches, and I'll
wait for these to complete - I don't want to be looking for patterns
until we have enough data to smooth this out.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#66Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Melanie Plageman (#64)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 18/03/2024 17:19, Melanie Plageman wrote:

I've attached v7 rebased over this commit.

Thanks!

v7-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patch

If we delayed table_beginscan_bm() call further, after starting the TBM
iterator, we could skip it altogether when the iterator is empty.

That's a further improvement, doesn't need to be part of this patch set.
Just caught my eye while reading this.

v7-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patch

I suggest to avoid the double negative with SO_CAN_SKIP_FETCH, and call
the flag e.g. SO_NEED_TUPLE.

As yet another preliminary patch before the streaming read API, it would
be nice to move the prefetching code to heapam.c too.

What's the point of having separate table_scan_bitmap_next_block() and
table_scan_bitmap_next_tuple() functions anymore? The AM owns the TBM
iterator now. The executor node updates the lossy/exact page counts, but
that's the only per-page thing it does now.

/*
* If this is the first scan of the underlying table, create the table
* scan descriptor and begin the scan.
*/
if (!scan)
{
uint32 extra_flags = 0;

/*
* We can potentially skip fetching heap pages if we do not need
* any columns of the table, either for checking non-indexable
* quals or for returning data. This test is a bit simplistic, as
* it checks the stronger condition that there's no qual or return
* tlist at all. But in most cases it's probably not worth working
* harder than that.
*/
if (node->ss.ps.plan->qual == NIL && node->ss.ps.plan->targetlist == NIL)
extra_flags |= SO_CAN_SKIP_FETCH;

scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
node->ss.ss_currentRelation,
node->ss.ps.state->es_snapshot,
0,
NULL,
extra_flags);
}

scan->tbmiterator = tbmiterator;
scan->shared_tbmiterator = shared_tbmiterator;

How about passing the iterator as an argument to table_beginscan_bm()?
You'd then need some other function to change the iterator on rescan,
though. Not sure what exactly to do here, but feels that this part of
the API is not fully thought-out. Needs comments at least, to explain
who sets tbmiterator / shared_tbmiterator and when. For comparison, for
a TID scan there's a separate scan_set_tidrange() table AM function.
Maybe follow that example and introduce scan_set_tbm_iterator().

It's bit awkward to have separate tbmiterator and shared_tbmiterator
fields. Could regular and shared iterators be merged, or wrapped under a
common interface?

--
Heikki Linnakangas
Neon (https://neon.tech)

#67Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Tomas Vondra (#65)
3 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/18/24 16:55, Tomas Vondra wrote:

...

OK, I've restarted the tests for only 0012 and 0014 patches, and I'll
wait for these to complete - I don't want to be looking for patterns
until we have enough data to smooth this out.

I now have results for 1M and 10M runs on the two builds (0012 and
0014), attached is a chart for relative performance plotting

(0014 timing) / (0012 timing)

for "optimal' runs that would pick bitmapscan on their own. There's
nothing special about the config - I reduced the random_page_cost to
1.5-2.0 to reflect both machines have flash storage, etc.

Overall, the chart is pretty consistent with what I shared on Sunday.
Most of the results are fine (0014 is close to 0012 or faster), but
there's a bunch of cases that are much slower. Interestingly enough,
almost all of them are on the i5 machine, almost none of the xeon. My
guess is this is about the SSD type (SATA vs. NVMe).

Attached if table of ~50 worst regressions (by the metric above), and
it's interesting the worst regressions are with eic=0 and eic=1.

I decided to look at the first case (eic=0), and the timings are quite
stable - there are three runs for each build, with timings close to the
average (see below the table).

Attached is a script that reproduces this on both machines, but the
difference is much more significant on i5 (~5x) compared to xeon (~2x).

I haven't investigated what exactly is happening and why, hopefully the
script will allow you to reproduce this independently. I plan to take a
look, but I don't know when I'll have time for this.

FWIW if the script does not reproduce this on your machines, I might be
able to give you access to the i5 machine. Let me know.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

reproducer.txttext/plain; charset=UTF-8; name=reproducer.txtDownload
results.txttext/plain; charset=UTF-8; name=results.txtDownload
relative-all-optimal.pngimage/png; name=relative-all-optimal.pngDownload
�PNG


IHDR��P�^D IDATx^��	|�����O!l!�%��X���Z-^�u	�X��>��VP�R�j��*j(����b+�r�6j]�7����"���.��Od)�`K$�����iH&�����_�x��53�|��|�9s�|��#�� � ��H#��n�(@@K�0��� � ��O�>�8�F@@�0�5� � ��O�>�8�F��SO=%=���^���jg�����F8i�]�0o;1 �����[���}O�����^�F����������U�VI^^������)S����������/�P�{�=��q����K�x�=�x�	�:u���7��o�1!���M�0�g� �i����1�c�;��C�����~������>Z:��
�s������[m<���q����[e��I��G���+���j)� ���O� X��C���~�#����$�|���p�	����^(��z����IMM�4H���n9������?�V�����W�^���E����O����/r��w������{���KIIIl�����}+���Y���J���G����e��M2|�py�����O��W�\}����o����k��n���m6����+��w�|��g���a�1y�d�0a�5��~�r����"oe��s���������2�_�)
�S�� �@<TU�Va|���r�5�������7��g�yF����H�~�������.�L�����|��2���|�[��X�Y���k=���������Y�fY����������a��Iyy�����?��1c���_���a���K.�D�m�&�=����j����o7��-/�
��e�b��1c�|��G����~�H���������r�)�y~�@��\ ��
*��Un�
���o�V�U�W��-*d���?����q��z#���`�R�~�0�V����c?R��*���z�j~���[����zc0m�4k�K��=e�����o|�����@m�i��3g��w�}W^}��X{�������_���t������]�d��q�'j�y.N�D�@	�5��"���/�K)..����{wY�x�,_�\~�����-[�����w�<`�x+�EEE�V��������7j[�Z�?��c��O?�m�Q�W��������_n��P+�_��W���y�kK�
�*��u�Y�.U�j���_�~}��?~�ale���w��k��jS=�^����*@����P�Z�����c��
�j�\m�QG@v��������
�K�,����<�F���/�>���I��3�<����V�[?���j�Lte^m�Qo@�[�W[_��~�ICt����X����s��5���w����_~i��Gmm�dff�g�am��� p�a�+�A@����tk���3���TVV�m��&]t�u���2���kO�:�Q�y���}�k����|�+Ve+W���N:��k���~W���s����V�.\h��B�
�����>(,,����Zv��)�K�j���g�m�^���V�^�>)P���.hs�M{?W�Q[�T�#G�������(/�)���c3���7$��O�#�<����I@���y��#��GZ�f��������V���t��|��[�Y��=�E�{�UE�Z�7]y�EZ�5F}q�w������ �9�-��(�%���R����S����3�z�����/���rrss;=�F�����^��dD��Wo���~�l��-����D��l<z�SxF�0�����@G�.i��@�]������ �tb �1���&�r@ ��`�#�@�.@���Q � ����4@@��a��G� � ���@@����a�O�>��<@�����M���6Fnh�&4K�>��3���� `Z`��-���}���]��Ex � �5��������ce���F����keRD@7�r0@�*�WV6HAA&A�</-"�@�<� ���� i �'L�@h_��5\8+����l�.�����n��y'��@�#P^^+ee5���)UU
R\�#EE�� #A�#���7KCC�G*�����L4hP���m:#���O �!`e>��=!PYY)YYY��_?�h���(B}����K]]]�{8�y�4� �@\��sa `��
�2r�H��%<G�655����#_�/l���y{�9ZG@0$
��B��.<�LG�&�{r�(
@@�������	�����J:t����+��}��2j�(cH�7FIC � �n	x)��4Pa~��e���g
a�VE@pR@7���}��]����c+���$���AIt�S@@<&���:i�u�������&O�,w�uW�c$u9Y����u � ���	�v��e�W���s����#�^z��?^JJJ����Q� � ��[:a�����������3G.\h��0o���@@��	��V;�������F��������M��|�+r�}�c"���!@@�t���F���;��{���n����	'� �<������X��yc�4� � ��������y'��@@��|����f�{�cZ���YJ�Q��h�� � �xT�0O����IY � ��	�	��]#�@@���y��G/M�B@�L�0O����� � � ��=ziR � �@g�y�|g�?G@��a�0��K��@@:�J�_�z������{�IVV��v�ir�5�����e����� 'N��{L222d��er��7����e��A���O���������*��e�l��Q.�������0p����~� � �y�0__Q!
���YP ���s����v�Z=z��[�N.��2���/O?��t��E~�����+W\q�}����+���q��������RVVf��?������oKSS���+VH^^�a5��L� � ��)��U��.-���[Rb$���}�)�X��j���{����^���k�U__/���w���.�����
����_��#���>��|cc���9�������Y�~�I'�����@@���N��-/���*xf~�4D���KvQQ���P���<xP�.]*���o�-4j;M��Z����+ca���V��]�v�;���z�����[���$�|�2��t� � ���:a����/�P��/���2�|������[n����G!�v��V�hm�Y�p��3�
���������V�	�n_U�� � ���N�W���3�����o�[y��7%--MT��0a��������z�������'�l����'?��������,a��K�N@@��
�n��j�l�IU��#� ��.@���y�/B
@@� ����^� � ��a�0��EH � �z�0?r�H��Lay�3���_/��^�/��||�k_��>�(i��fs��2���
uO3 � �.	TF�����%���kl]*��nU��������N
"w�m�����y[���@@�	8p@6o�,


�����nH���A���3P@@ �.nq\������2��t�! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@@�����! � �f�fi@�P���^*+�� S
������FA@�PA���:����\=���FA@�(/����������).����l�HY�0�2!
 � ��2�b�a�.Y�E@Z�g�������� � ���y��@�-��|���������m@���C	�
@�����@@ ��d�+�������u@�+�!�l>a�f`�G@�3�5`�a�.Y�E@@�f����4� � ��]�y�di@@��6�< � �v	����]@@l ��L� � ��%@��K�v@@�Y�0o30�#� � `�a�.Y�E@@�f����4� � ��]�y�di@@��6�< � �v	����]@��
TT�Kee�dJaa��:0p�_�0o�1= ��H@������KJr	�!������y���@ ����RVV#���RU� ��9RT��138pO�0��==#�P���N*CB���yO�!��S�=���7�F���y?�5#� �  �s � � �S��O'��@@ �s
 � � �S��O'��@@�D�:t����K222�Y�`��5����-��F@@ H��8�9�0����e�$///�&u�N�q�� ��A��4�IS �F@7���@�D�Hq� ����	�}����?y�d����b[n��m7&�#� �R���V��j$??S����8G���AB�	��b�+��7o�A���={��K/����KIIIl�s���O��k�.���6�@C ��!������-<�[��k�Y�}������n�L= �N�g�iq�C \������Z�oll�>}�X�;m�4��W�"��wa>\�"�E@HR��0_YY)��{�455Ya��N�GyDz��I�Or2y: � �@�\�:��E���k@@���n.6��FF�h��x
 � �^����y��(u!� ��F�0��f� � �A �mF � �@h���j� � 4�|�f�� � ��F�0��f� � �A �mF � �@h���j� � 4�|�f�� � ��F�0��f� � �A �mF � �@h���j� � 4�|�f�� � ��F�0��f� � �A �mF � �@h���j� � 4�|�f�� � ��F�0��f� � �A �mF � �@h���j� � 4�|�f�� � ��F�0��f� � ����z��l���L),���������t� ��'��|iiu��%%�z.�v�\ � �����k���F��3���A��s��(�CR���^�
jA@���2�K )�|R\<@�_�=����|Pf�q � ��N�0�)g� � ��+�NI���|x���#� ����}���c�y.@@�N���&���(@@X���&	�\ � ��S��wJ:���2��g� � �> ��|)@@ �����=#G@��fc30�a��@�A�/���J�m�\ � ��
Mi*M��@@'X�wB�>X��@@l`��M�4 �s1 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ �s
 � � �S��O'��@@ ��RY� �RX�=��et��ym:^� ��#��|iiu����\�=��o�0��)d � 4���Z)+����L��j���)*��0���D�@@L
�2oR3�m��=��@|*��y�N��e��;@@L	�MI� � ���;@@L	�MI� � ���;@@L	�MI� � ���;@@L	�MI� � ���;@@L	�MI� � ���;@@L	�MI� � ���;@@L	�MI� � ���;@@L	�MI� � ���;@@L	�MI� � ���;@@L	�MI� ����z��l���L),��	 `�a�V^G��
�����!�����t0V\ ���N� ��(/����������).�����`�Q!��'����@�+�A�E����<��O�.�����v��[����j@�(��y?�5#�_�\��y����K�w���<��3�y���� � XO����9��S���_���\�|`/7� � `R�a~��2l�0���+�k���y�3L[ � ��p=��]�Vn��&��_�"iiiq���9sD�}���K���u�W`g��!� � ����a�����3gJ�n��27n�(C������t���@@��n.6��(*�l�ty1@@;�v��6 � �J��K�$L
x.�'28��i�� � �v	pc1�d���n.�m�M"S�[t"m�@@�.���Z)+����L��j���)*���;�
��n.&����`� � `V��y���&B��*@@`����!��0�If� � �� �s^ � �@�!�d�� `�['�7�h+@���@@ E���" /Gm��6/D@���
r% ��[�y���@������2����h!@��42@':
���wb�Z�mUMT IDAT�&@HP��4	B�4pL�0�5!��]��4~�A�G x����)#B�Q��46��4$-@�O�� � � �
��7��*@@HZ�0�4/@@@��yo�U � � ��a>i2^� � ��7����@@@ i�|�d�@@o��1T� �s����R>> ��t�(@�;��;sA%�M�0�g� ����k���F��3���A��s��(�x?4�� �sM � ��+�)�r� �k��B@�%��y�pC�0��:}"� � `@�0o�&@@pC�0��:}"� � `@�0o�&@@pC�0��:}"� � `@�0o�&@@pC�0��:}"� � `@�0o�&@@pC�0��:}"� � `@�0o�&@@pC�0��:}"� � `@�0o�&@@pC�0��:}"� � `@ �0�y�f���D�oQQ��q����i�v����o�a�����-�x!4� � �����8�9�Pu�q�r�9����/������WKyy�������ce��U���[��Bh@�N**����A

2���;^ ��Q�\���o�[y��Gd��E2e�Y�r���Uc�E/�@�@@�����3JJr	�\1 `T@7���1�#|������
����$%%%�o�>k����n����=@:(/����������).��lI�
0&���ca���n��N;��������U���Z��a��b�
�m�D@�V��<@�n�\�v�}�����>@�-���p�?�G�n�\�P���g��/4>���B� � ��(���
���M�6�n���A@@\����0�z�|t,�����~[���k|x�E/�@h%��.	pR@7��|��}��g��^�zV�
�����}�v���-�x!4� �@�����N����V�g��!�&MjS����e��5���[��Bh@�E���N���X������]�Z�8��-����@ ����s�5n
����_���������e��t���(G@ "��y.pR@7���������+�H�n�D��?p��L�2E���~���5>���B� � ��(���ca��SO���?_.��R����5u��SO=%�=�����[���[��Bh@@tsq,�F>R��;��#G�����O�h���  � �.
���X�W��\r�%r��[�l�c������O��d��%���[��Bh@@tsq,�o��Un��6y��W�w����y��f���RZZ*yyy���[��Bh@@tsq��ljjj�0��_?[��[��E�8 � ������������^���7[����s�=W�b�pt���E@@�%�\�s����zH�;�<<x�5�M�6�/� 7�x�\{�����[��Bh@@tsq,��1BV�\i��o�P7�7n����0><���B� � ��(����k���=z6�%���G�]�\�F@�@�a�����\���e��A���f�n5m�4�����m�D@@�E�\|�`?��y��e��-�i6*��s�92|�p[��[�-��( � �.	����GSF��v�Z9���l�n��D� � �� ���;�����K�v=t����E@@�
�\�a�;v��Z�����m[A4� � ������0?o�<�:u�m��-���h@@tsq,�o�����h|X�E/�@@pQ@7��|~~����Y���#)�8�k8_|��uG���*���-�x!4� � �������6u�|QQ�L�2����e��E2w�\���-�x!4� � ������M�5j��[������)�1���E����@@pS@7�	�'�|�\z��r�EY�����/y���e������[��Bh@@tsq�0���_���d�k��I��������~�m��C@@�M�\����vH�h���}@@����m��?��O����EU�V�?��k��5�\c|<�E/�@@pQ@7�	�g�y�\u�Ur���������������K�&��[���i@@����6a~����b�
+��Z��_�79`��M�@[ � ��-�����fS^^n}�u������Z+������Q�h���  � �.
���6a~���r�w�����������������ud���n����=@@����qO���k�,_�\�����N�~���26��m)�F@@pI@7�
�����}�v�������4�t� � xca~���2c�����.]�Xp��Q6l0��[��Bh@@tsq���a����e�$77����m{at� � �����8�i6�&QN<t�v�6�@@@�)�\��>��U�:�r���r�9�Hfff��/���Xt�6^
"� � ���n.����/�����������n���A@@\���qO�qj�E;U� � � ���n.n�o���4��}�Zu�����Y�d������[��Bh@@tsq�0?v�XY�j�aC7n��\����t�6^
"� � ���n.n��;�8+����[�9p�������n���A@@\���m���b�f����k��<��c2z�h�����O�h���  � �.
���6a���Y�|�Iy���E���g�)W]u�-C�-��bh@@�tsq�0���/����{�0��7��-�D���$+PQQ/��
RP�)����}����rm���@�����6a>��]��/����q*���B� �@'*,�~����Qz�N������@�j+-�����$�3�qa!�$&���ca~����d��;w�L�>=�kmm���f����U���t�N����7oG��C���D%r�o�L���H��6R^^+ee5���)UU
R\�#EE��6��@����0�x�by�������i���J������>[�
f|8�E/�@�N��{������kW��En�����_��+����@R���m��l��AF��R1��X��D��y ��)�2��[#a>-����;zfe^��=��f�v@wtsq�0������d��uR__�O<a|d�E/�@�N��g��C���n.n�/���������+���o����/�<��q%���B� �@�~'��S@�tsq�0�n�n���v�Z��w�|�;����~[���^�[��Bh@@tsq�0�V��}�]��7�!����dggG�8+������[��Bh@@tsq�0�����w�-/�����={��I�&Y���~�m��C@@�M�\�&�������/��Q�F�26��m)�F@@pI@7�
�������W�*_TTd��t���E@@�%�\�&����?�������JYY��t�I��_�����~����g�E���(#G�����K�>}�}�n���@@���n.n���]�)6��u����~�d����N9jkk�/����7�(Gq��u�]��N�x � �@���y�
����K�^�,���w�Yg�%K�.M����I���Z�����������x" � �@����/�X��������=IKK��_~�:�R����w����9��c����J���	�a�"3 � �@����:���GG+�����9W^y��v�ir�e����3g����]�vIuuu���� ���-W ,ca�������O<!���J�M�m�F�A�(��|ii���6J]]��|�W#����@
�����O������_����=��\s����O���~�|2�<����)/��,����������2thf�S�!�����Q U �$-�z���u��}�����`����?^}�Q���=t�NZ� �@����hC%%����U�Ps1}�&��������%??S���?��z��
���n.������jU���n�N�H_ pH@����X�Q��]�8�|<��6��J�	�.��rq2�0 ���ca��SN���z9��3d����	6v?t���.�G����{��`������@]�\|���/���:c^}yu���2a�+������\�.Z�?^��	S����;�5��		�-onn�w�}�
�*�����|�M�3�[��"h@�t�d�@����8��l�\h�H�h�E� �����������6�E�Qm"� `�+�v��6�����y��=#@��{�}2Q����y��@@���1c�����M��
��m+��@@pA@7����1�M��~�i�6�C���a����-�x!4� � �����8��y�Gy���1C233EMy��'��e��a
2���t�6^
"� � ���n.>���>����;W���>�4i�Hee�m��-���h@@tsq��lv��)?��O$==��I��M�l�n��D� 
���
i�,TdF,��b�@�������)_{�5Y�d������\�h�
�a��
�����q����?����n.��y��-"��A���r�)+���|i�����b�.*2�M!� ����a~��	��{�%_U'��-�x!4��`e>4S�@@_	����������X�j���_�m�fD�h��� �J�=���n��B@7������:�F����w�yG���gB�h���  � �.
���X�?��c����6��0
$�7o6><���B� � ��(���ca�����7^�����K/����t�6^
"� ��@EE}��.
�{�dJaaw���[p[@7s���3G� ���D�P�VZZ���$�@��<�%^0�7n�(/��RlKM^^��s�92t�P[��[�-��( �So�}���5JVV����G ��\���JYY���gJUU��HQQ�O��L0)���c+�s����zH�;�<<x�U����/� 7�x�\{��&����-�x!4��X`��2{�6�������$��:@�N�����tV��3����tsq,��1BV�\����a}�����q����Gg5$�s����� �8��#~�G�|c$���}4�l���dQ*6
�������5k�G����w�^=z4a����i@ ��6�U�g�M*��pG �0������?��W,�(J�P�l�{�9�6m��p�
�G�[��Bh����>�@�G������N�Q[i�`�l�b�<J�z�������[�-��( � �.	����GS�}�����e�pt���(G��XN��'#� W@7�����������lFF������e��)r���Knn�qz���B� �%�IZl�@�6��8�O=�T9����;������@}�����������[��u�6^
"���gdk��"@�����B����K;r�HY�~�qv��qRD�QV��N�3�@%M�@�tsqle~��Ir�%���_,��u����<����`�Y�d����m�Dm�6��/�����4�����0�u�V������W_��8j��=2y�d)--���<�m�D&���M(�A����[
���XGS����V8��m-��@�#�*+%��@�G�9�~�2oZ��@{tsq��)��^{��2w�\�*�-���hp@@���'��Gn�$1�}ee�dJaawFF ������0?n�8Y�r�nM��N��N�	 ���j�����L2�����Jr"w��.*�p��� `��n.�0��;VV�Ze[��E�V
#�8�2��P�@���n.�0����ft���.�G��{�����> ��Y�\�?���$--����x�	�GZ�-�x!4� � �����8��y������M��]+?����_��9z�h[��[���t��Y�A_/I��!���m���p�	�
�222,Fu�(uC)�M?t�6]�!�@x::�1!�#*�{m3r���n.n�G�!�W���={Z{���1c���
���m�D��
�ws���`n�K��#���tsq�0��_�J���/g�}�E�p�B���+���o6N�[��BhB+�^hJ����^�B#�����f�V��V�����m�����-��Zh�+o;M�Bp����d� �\7�WD�N�~�zku~�����������E/�@�8�`.@�tsq�0?w�\���/�v��O>��������7�|��Xt�6^
"� � ���n.n��1�+V����?>v��Q�F��u��O�h���  � �.
���6a��������;2v�X+�755Y���]�]�F��e��S�@[���k��F��/?��<��3��CI�����G1>���B� ���A�2��L4��Z@7�Y�������R)//���f9�����;����L���E/�@�r���D4��^@7�=��)M�����~@ <vn�Qa���IVV�dg�KII�v.#E�T@7�	�;w������RUU%�u�n$e��[��:h�-`�6�h����RW���W��(;���@���n.n�O:�$���'N����XG?�����m�D�P��
���C=i��n.n��;�8Y�v�#<�E;R� �@h_=o���0�zn���d�V�dk�� �����6a������.��:g���n�v�E� >�C���G��w1���!�Ko*�wu1b@�s�\������4ill�O?�T����l��6��o����*�|�n�Iv��@�N��&���t�y �q�\�7n�p�C�1N�[��BhB/����[��v~���@���n.n��F���U��={Ze���G�n�*j���C�h�u� ���N�ah=�v~'�+@���n.n���_�y�����*���|�[��+V���E+�E/�@����V��� �\�&��3FV�^}����e��5��t�6^
"�	
��z���|t���*���i ������M��4i��w�}���W��K��w�a����n����=@ a<�7����s��7��y- &�\�&��U���;O���k�dS[[+/�����y���M�A{ �@"lWID�� �����6a^u~��AY�~���k��:5u���;m�' �6�X���,�D��n.n�O?�ty��7#���L��m�o�@t�����k��z��@���n.n���'+W������W�	7��qm���B� �8,�'=������0?s�L���{�;�F���m6�z�����r���'�-�x!4� ���|�ap�C��������M7�$>��#��-����@X�������n.���[�> IDATX5�������Q8�8�n���A@\`���t��Gtsq�0����U�M�&[�l���{��]�d���RUUe|��E/�@@pQ@7������*�'O�U�VYg��F=������[��Bh@@tsq�0�N�y���e��Q�n�:kH�O�15N��M�O; � �xA@7�	�'�t�,^�X.��B�H���:J���>������S�h���  � �.
���6a^�1?b�����3fHmm������	�O�h���  �.
�EX������vO���o�5�=z�6D��m+��@pX�#*�;<*������?�P.��2������4)((��������u�C�-�x!4� ��K�<�%x�E�c���M�W�i~�����)S�!��m���.y����Y�h���  �.	�2�<�"�1�\�&�w�q�v����7z�hY�f��!�m�D@�E����O�xD@7�	��K��&Q�\r�5�����e������[��Bh@@tsq�0���!����
%==���j�����
S�hc� � ������f���t�v�6�@@@�)�\L�wj��@@�v�\ � ��T�0����l@@�\ � ��T�0����l@@�\ � ��T�0����l@@�\ �)	TT�Kee�dJaa����� ��	����� �@�A
�j,���1���\}�W�^A���x� ��s�5�$��[^^+ee5���)UU
R\�#EE�.�����]W��IF�@�����x �-��K�����0h��QC ����O0�Co	8~��v��Y�����4)�m6.\rN^W.�.@��<� ���![�q��[���Q���e��<�B6A���������1R�@���y�@ ��������I��]d��&���2uj[F�[X�%�k��E��PY)����0�c
���a�y���8��#a>=�#a>��0���7.%�����*T��.-���[RB�����0o�f@/	����3�Js����n�Q�fE��������
t~�j�����L2�����Jr��%����2i����t��)]���m����|�����#m�2�������ee����`��yN
%!���B����_��z�����T~��3�k�0�9f� �Q��t�]��(e!z~�C	t@���@\��n��H�i2jT���Y�uaR������M�}>����P�?��6����5�#����vN%U#��
�]��s���+�aue� �@��a�q���0�g�/�yf:m+�9�����a>�� @ �;�Yg��?���T\��7o��.�L�n�*]�t�)S�Hi�����n��b�z@�K��K�aO-��=���@�tsqZs�a���Z�����	d���r�i��-��"g�}v���m�^�@�"���Wf��:�c�li����bca�5���_/�������0���q ��mA�O����p\Lj���T�����1c��o�!������]o��+�
t���_hO�3a^m�9��3e������o>��9s���'���k���9<@�!�������7:�D(�>�@ UO����F)..���Gn��`�c�-���y ��+������Nu����"���UR��D��+sG� ���n.6�g��+����&�?����u*�[t�
�@��J�>��7+s���F��3���!� �#EE���#��{���X�������N�������nI\q�����C�h�����@��y�7:���ys��$�����\l,�������AH^����Y�� |%+���������n.&��{���U����m �
�8��}5g�FK�y7���@t����Q���"��}�=��s��_V��;w�r������@�
����&YY����.������0�3��k�0����t�*��%~���������x6 �#@��Q�5 �-�y��t�{!��n�(|(@����Q2~�`�����e��p�d�m���
�����<$j�@�W�<@{����:�P�������us����Q=�p�����'@� �k��������Y�����������U�+�\ �@����F�����6���YOZC�(@����Q3>P��+V���{q�x���i1)�r@ ��L"C@�/�$���C��o�����s���� ���o��B��+�����;�6F��:�O:��� ���o��B��+����7F�,i	��a���G��P��W�Lo��8�
 �w���g��pY@�����R2
8/��������t�xP�0��I�$�"��|uii�����_&�:@!@��42��-/���2������*�).���"w��W@B(@���3dL	�2oJ�L;l�1�H+ ����~�-jE���������Xo�U �N���?@�����&@�}0I��t&��|gB��a>����@ �����3d�a>�� � �~ ��u����,lB8"@�w��N@:`�?� �'@��s�U ��i<O<�Cz��"{�4��W����l�=� L�|0��Q!��Pa���6Ejn���&�>:�0o`��d�&��a��Dy �@X�7?�l]2oJ�xQ�0��Y�&@ dO�������"^ �{qV�	��
���Y#�4)K
��P�������D��Z��a�sF� �@ T ���-RW�(YY�2kV�>��C�
���/^P�|@'�a!�~�7o����Mz��"�w7�����S��m������;�	�=7%��S�P������H�o���\�|8/��F��|R\<9���N*CB�(�f���
�A�f�-0N]�X:%M?^ �{qV�	�@XB��!��66�m@�I@�`
�z������������r�R�K�Q!`�a�vb:@DL�@,�0���R�n�����e�����Vd���{e�*m�M�0���^����������������S[M�������52hP���7��^��
�W	1��$����c/&�;FMG V�����k5}od@i��������V��+�v�#��*���:�����U2Z�?�O��7s��y���l������J�,(�������Y�� v&�����3�{�F�9��us���)*��
 �m� ���������	��_��m�������{e���Fx`���y�����r�M������ �'*��@�7*�W�����-)�%�'��!����������L��>���Q��y�����.%%���6�k���$��yj{����n�T�y���lh�k�����L2�����Jr��%���h���a�(�<�NAJ�%�e&���7��n���HAAf� �����PL��</��@go@u��zj�!)�0��f�U �kk���N�|�������xo:����4�:?^�
�>�Mv�8����#���7�� �9K��������T;���s�#��P��,\���5����	�P���'d����H��>t��?��5N;���G��D�YgY}�^�<�'�i��o�%�re~�~�������|�a��u�,������>e�����e���\p���:�\Z���o@}3�J��d2�(�Bu�e���?���]%�wo���NG����n�b�]�H���E�z�P��-��������0^�cV�ee5�hQ���f���������+��jg�����u�"������o$�gM�d��It���9/��J�+��d����|��������=&�G!MH������+�z����'J�A������_���$�%==��6�M��l�=�9K� �����~��\m+S+�y�f%�w��'5�?/]�w�=��'��@�}����t&S?�Eo��1T�)�p�i�t9�s�dy��3'n��+lg���[n�"������&��u�L��?)�_j�';�Odu��~u��i!*�o�=[�D>�j��[�z��^��7uo�m�.c��9z����j�_����#��9��9KZB�:Z�4������`�B�|r���Cax��GZ��WV6H{'��4V�v���s\�a\���������k"���?�>��U����y���1�[����k���J���@�Mb�c���c��������m��Oaw���	�^�
jA-�������.��j/{2g�������q�u�"&j�s��z�Y�|w�����n���'���u�M���u����F��
��n�Q�D�t����/����\#������>��l�r�V6a�5z:FS}IPQ����D��O�/�x!�T�Vaq��=2qb/�K}a3??S���[h2��ro���5��zn�xU�:a�u=-����d[>/��y���Ry#`�#m�#�7��Hz�U������@ A�x�9���}m��J������c��&���4SobZ`"0k(���F#���~�d�%��S\0}��0�L@�0�OA����E��k��h�e�h����k�L�����r��$�z��g"�t��FMg|��};��utT��\ ���4���y��+��MT"�v���~�{���q������>��R�����|*��Z��a�{sBE�F������v���m�	k���>Csa�h�g��i�N��v��A��IB'��[~����h��������'#�4b@�k���&��Ai�ce��J�m�_J��cE�[��YP�}�u'���g��O<�$�r�L{:����8�,�v5�7��S���I���t�n�/���8h#�����y%�{s^�
���^�i�����dX�����/{W�u��nyy�o2�T���>Q���w8M��So:�W��3�|.�����g�9M���%���T_��@�a��/Y/��O�wJ�~@���V����
UU�5r����O��]���>�2� =����m��������fG�3�+w���1q�;���:�k#��;��m{���m��������upA ���z����������O?��F�n ��[t����D��T�m�>]�~������?��qO���|GM?�i�e���N�a�G�N�-^,��Y�[�������h��o��z�h�0oB�6@�s-��-�'�f�)_s���������|�����e�������V��k�G��|P��a��V�s.��zm���L��}����E�� ]���e�4D�,q�Y�v�x�|y���%�����I^�0���@��
�������'�����#�b�z�g4����V���l��['i�'����H�i�F@}�v��%�%++�)@�W�[^v?�Z��u�h�������=J�\�je�[��p���be�38����'�`��y��4����w�(��a��D�2S���J���o�~����x��n+P?��4�zJt��jO��?Y�O���Z������Wo��=s~��F��;]f��K�xH7�	���|�H(��MP���������	��5�~}�	G�8$��Y�s%��3��Z	$�_h[g�in������+�����fk�Rm�i��[�*����n��=$��;{v��U����\�:�B<���r�I����P���j��QJ��D��"} ���D 'FcP�y
4^�
���yC��*Z�p'���l�����y��z�lk]��[o��S�&��a���������:����m�0�%��"a~@�a����K��F��[�N��q�:Q�0=�0����P��q������L9����{4Wa>��Qt��W�@|:�x{��_}����OlD�n�����
��"a�K$�7E��a^���$�V��%�fSW�(YY�m�����x��P�4�mZ�����w4�n�|'�o��K���#�|Xf:`��k�-`L�N�Sa6{�,�� ���Fo����_�
��3�����6���d�k*+����i������'����3Fc�h�T>�P����\'�o��K�^�@P�A����+H�$�S�����2��Ut��o~S��g��2TJK�c����5�k�K�m�SM*�����!�{a��9���������J@ �U����S�l���y�Lr
���7������!jn��Dn:�S��g����s�9���3gHR'�����k�z��~�����I�"��w���HH ���*KB��x����ya�=��9�c9�`�L
|)6-g���8���a^G�� �!�-��xh.�����0��M��)�|r����C��S"��@�w����X �U�DW[��p���M��X�G&N�%EE����{�8V �P��3�|.|���bxvv��:��������1�6���3J����PU��]It����Zy/��+����V�������d[�a��!
q,��~������������/Jcc��=���<#��,lW���F����v�n�����^h-�|"J<��X5o�4���)(����t���p�����8���x�{3��O�KFW���\&�^1A��?�8��u��]_�td!������c�m��E��k���n���N9�'�`�,;o������#�O��k�J������#=�����~���f�C'`�_�n��z-<*��o_&��������)�����M���MY�����g���UC%W���]�#'��'���@#]'��)��)�FRPo����S������$��O�5+/�;��W������+eH0*�n�����D���y�~�����g���o�vm�:���	1�$�0���V�N�M���R�����y��\vf��7�v���.��/��cm�|��ZY�/_j{����������'#n�q����yt�7�����SO��/�l�.]D�
�.?���7������{��j�1`@�������A��F�H�4���
����'����={��GH�I'�2���^�y=7^��/�[���~nZ�����{_�V�9M�?��L���W�[����z���%�FM�!�FQ��q2�������y�9����I��]2o��5{�M�e��������K����d��C�;���D��\�r�8���Lw���)�9hi����+��m���-��.j�|��}���s%����?G���~U�y���
�@Go"��*=���;X%�;7�����3�N�}Ry��h�K�]��_�{?�Xn�"�
��d���J��Su�������!W}GE=��jb?�(�G����{e��z�������(C�d�9�����9���2hP7k�>��M��b���8��O�����n�;"�#�=�H�^]���:o�M����']�@7P4��zI�������.��5AH�/n�����:�%[�N�\����m�gKc}�4n�.]#�Z�eFBe��|�s�|[�f�����&���fD�y�\}u�v�������./��K����{�.���&����M�:�r�����m�W�vK�H�2��G������u{#�J����Z[m���i�9(.�I���\SAy�����q$/@�O��W �[;�^����������-GO*L��VU�'�+��r��m'�MT*o>���d�������NWhM���;	�i]�����|Fde�G��py�f%u
����6���hM-_�ti�|�Q����"w�<�h���������^��E&L�%�
���=��|�n���#_�-?{E�9D6o�#/�D��qYT���Y?S���O
jk����e��,c����������^?�8'��0��G�;�<"������K���"`�*Q4����,=$C#�����InII���:+�a��DmZ���H�n��A�[�WhMF��4���B��\pA���NtNZ��^�W?SA���y����O������� IDAT����VZZmu���|�y���E�j��R�G�{�M\OAj������h�Yg�w#H�����2��|k�������.��`����Z��k�(RT����r�Y_������f�G���tF
u?m�}]�s��o"�$�����^���}&=F��t�6�������D�n����
�������Q(����������!K������%?�B��T~��/��rx��E��}�N��,txyl������7�(�Du�i��<~A�sMQ�G�Z�W�Uc��u��E�V���Kg�3"un�d�EG�og��W��?�P�������7�_Fm�<�7A:����UmIY�n�������Y�6U�
��]�)2����N��t6��^���FQ{�MW�Y�A��])A6cl�	�6���y�?�KV��3F���Z	L��g�0��Qt�be�
j*�����5�?o��Vo��4 ��\SK{�t{���+����������$-r0y�q�d��9	o{
������O�(;w����.�_~��}�������wv�1�����z�9)��)Y{u���3��@�l�� �\r��
��a~��������x�3Kv\Az��o����X�|��{�������dV��x��]I
����tB��1v$���KS�(���+������B����KW�'�gKG�<^��R����s��OU��{�����=-r�L��w�ju��?�$O>�32�f���R�>��|����Z=o�:��N�/��Y�W�vUG;�EV�{:��mre���9�}!C�F���q��|���?�X��7�^5�/��0?27W�En#�5i�%�Nm`�����{+�����V�����ht4>Xw<���]�F��%�C���?�1�����3��7M�.��~*��{Kf~��������w�&A�'^�V���O�����)e��������e_�F�2T�c�G��o&U�g��������t�*��N�SN���1���>����n����A9���H�Os�X�����{Yg����u�������9�r�u���r��J;�-���@���MM����e�9��eu���Q�>���������71����	C~��K����$��F��yV�J�e���>���k=w���W��oT�V'��7	�nQId�N��ku'E�M(�;�*���7
q�x�-H[n���7��W/:~BoH:s7��d7��P��&o��[����s��!����d�����/�>�|�uV��j��*�S��&<�;�F������qTW�g�V�WK�%��^0��B5%-$����QB�/$�B
��BBI��@��������%�X����9o<�h��V.	N<����������w����k	�S�+^�@s�����3=��������{��w���(�A�oZ����[�A���w�|�����3�����
jg�������lv�h����`���x m��U�9��~~V=���tG�r�=1�]s�UW����������������=�`g`��;����B2�A�>{��E����w&��]�:%�~:2�_Q�/��G�S�7'����re�n�����@�<�		nz�����b���]���||i��x��Q8��JL�������������R������#y��<p��:���T���Mm(+k'���|���^��������o�>;����Fo=�w��m�y7��Mc
���k�;��9�v�N��{�y����0��_����>w���������*��#���}���r�����	�����f�9��!@�|��1a{���3�F�B]G�Q�����:5��aw�l���<�N��]�����t����C� ����O�~<����[n�
t�#n������^�a��6�t #��
�\~y�N'��������2�I�����8��/����c������s;;�_�j�K����y��:��w�����m|���;6O<Q`
L����3����;�����G��}��=�^	���������x�n�N[����p����H���7(���SGb�	w�}~�7@�+����������.�������m8�T��W�xg���+jJ�&)g����]�L�m��~�{�Jl_��w]��IT�����E�<R>��k�%'�����+?{g���i.��U��^�As��������pj��R��.���g.���wB>��f��G��e����g��!�W_����SY�i|.�,}@�����p����\�V�nEII<�+U[��s�Ma���EP/���;�G���}v�[������+����=�oOo��4Q�m���3?�8�I�__�/��������M����X�������@��������{����E��{�Fy����XV�4= �����>��Y����;{~F�����a7��
�`����L��Y#���`0M)�a���nZpd`w����L�8���X��.
�'$xp��9�����`���.m���k�QY��?��J���ny�[Z����p�U�a��%����/���}�HG���p�e�4x��������+�C�������#Ir��u@�c����p�G���U������w��x�U�=����E����7kwn����]����]mK���S�op�!T��nyeO=����6"��sp�Mg���~��7;O�x�6�������h+EE���1cF|�����7E&;�/T�Yot��T,���:����m�:~�����������Y���B����g]hw+\������}����v[��q�k��U���h|�);$����������1�'#"+��R�}=��Z��=w=�}��x��R$�&�x����W8���A>B�e���t/iMy�W�����{�iS;e}P��p
2
�|��HG8��UW�2SE�M�s��!�H�x��j��KHO�@aa������=�p���s���p�1�+�;�?��J0?|�h���_�M�������_>k�,@��RXywm�}M��<y������vxr�&�I�1,�������g~�e�#��1��=�z�
��E2�n=X�0�Q3ZJ
NOb(���_�l�oE��t�������c���Wn&h5�q�]�����^�<
w3�A�(6����G������Qg��#�}T�]����|��
 ��2�d������������~�W��-�fm��&>�m�D8O��wn������\,2���������a(0\��?���u��&��@�w9�k��5X���?^���M�h/�����o�������qqn�{?n�!�_�J	e?+�z
�TYk+*B�y�!�����m�����"%E����L�������������R��{���GGa�F'����^
?�*�?�y��v�����XN���s�{��{`��II#�!��yJg^�8�M*"SKLr��|8ug�-{�5���<F
C|CQ��%��~�����@��'������Fmk�&��_�^I�%��i���S�T8t���CC9�Lf"�<qoHu����W{�����|L�}�
K3a"�[��t�Yw���v��7-pU����(��,j�	9�FM�^@���=O-�R�����}���4 ��;w�H�AN%��$��c�Y�D�Q�eL��|
�c8Uc�}��������8flzq�	FVr�
7�2�����jU~tX��H�����R�F�x���H���MK���[z��8�H�q����sf&
M�#��#w�F[�6z�W����bj^������:����#�
�.H���p"����|���p��8��X��M;�N����S���������)��Y`������3��I�Q���7��5���##�?i���E�x���x���5:.l6&������v��?���o������k���?��W��!g�7��x�-K���yK��bsQ�2��+�����]Y���w����������=�$t����R���gW<u;{���^�
"��6��s;�
�!���f���%w4b3�1��!���w=����Hh,���	�{kW_������$W������&`��+p������of�����-����kI?6���3[�\�h �b.����g��&����]H��C�HO�����QT���a+��G�	o��T����[?���A�Vytu���m�K�=��x��q���=��@6�~��gp��� 2%~���!UiS�.m�#�pj���Q�'��4|��I��N�O������:�!���p�������u�VUik�s~v!''�Lc8������+���;��'cB�f�rs���U��|�O�7c|���p�6��5����
�oiH�=��`���-&X�(���*r�������-��1���-����<�L]	gl�9�9����,���y�����p�,���o��=�W����<����Q%�����V��]k@�wt�)"3��R���&���;	G�����z$E�!�����z^����_�{�0�������I���t�C}_<S�]N�_|a��C[nt������/P�2���V�ub	,�H�H���8���;4?�.���o?�
��U�!��"[�����\t,���Z;
K������h�Q1x�I����x�RV~�c]��HN������?r�����'pj������9��Q����k���t�	Xz���7<)�#1�*�`���~�$7a�a���5�����Q�Cj01�&������T�K����2������1m�)���#�K������t��a*���u1;PT[Z�9_l�����+��)��1�
%�_|���C&'���;\����9�������)C��2�:���������>�o�f��Mu����I�.��������p)N�/���n`���PY~��8�	�����_t(�!~0���k�OBa��;DW���3R�������1�N�S�7��Cr��X���n������xjA��;�G����{���Ann����PvR&l/��5������?�����#{` �d�{�z`��y���_�T4%
FA�����2��7�
�����O�N��o3�{��\��a#��������a>A|{%&���j���==��-����������9=u�<����V[By@T�R�����a$�"���K/���A��o!"%�����7*_����O��3���3���V��Kf6o�����v45�D�F���*�$�h{�������rT��~u;������-��OCA��{e��]��D�E�e�qpv�1�i^��7������u���@+�
���
�QH�[���"}l^����u����v�G�`q�	6,�2��;��>�v*�G��9s�I���4U�36i��&<�r$R������zg�%�1u����#�$U�����!�
��?���8��9�W�8�D0�c��&<�TA��a�}��^e�=�~��������-��y����������G���b�r��akD.���#��������Sh�L���B>yS�������$,6o�w1*|�8�uK%�j��<����9��|#���u�L��A�q���wM<�M|�f�O�A*�;R5��Y�#'�i��������F������B�7��.<��+|�>��p�oy���]8����d2�B�O�����z{�:�{�5�����������L2����ZdJQ��@�B��&`��O��u����}y�����������o���/�
�5���wHN��L���k�^����p7�p���G;X�L��
��yg)�n�0�S���*G��w>3
~z�U�������c��~��p�F*7��x�,N����a�@y��,^���a��+)�6&��u������"�w}�>"=���������/�v�4C�(��6C�r���@��:�%�������C���'��������tC�:b�#������b�3���i���L���G�#j�+���"�W �,*V3��MD��� ���E��
�p��z����9QSR�jo���h�z6&M���N5�w�����B�199��^@���{
����	qi�[���,$jQ���
R�I�X�o��-�A��*a������O��)1�5y0.�B��?��*���I;������'3�#��D���>y�vf��K�{���z%����-�&l3��GX2�
4^d��z��)2�������6���!�����:�T��w��~)����������zk%*c��onFb�bc`�yb����o.\�H`���G��K���yE�1��ay��&�!�a��6RyHM����M�<x�Q����&���1�c-2������6h|6>��]�u'�q�
P���������MG@�QKQt�7�I���'*M{w�,b(���3�l�m �������-k��Q'��������MZ�����~K�]�1]]��)1�m�^�������r�8
t'������;��4m�9�_�]��������������K���q"�a3���`ZnR��b�j��MB���y�w���M]@Az8Sl��<nm����X��JR�br`�I[����0^��-�{�����jKJ|�����\�'���@�K0��������
p�Pa����<|mk����	_sQ�����~H��6��n+1 B�f��>	���X
�H+�O4���NS�%�$�w���|��q7Ub:M�t����cL�>����9oV��m���r7�Vo<&N�F�u� E��x��7"�H�v��������-�c([]��A��/���L�9�#yVALl��Nx�9z4�O����k3�7}E4O�����K�#��a���.4`�;#��]����I\��<���0�75�-�|5f�����9t|:M���XA����y����1��q~:>��%�5Q�8y�f`/�<��|/<���4y��fVEOA���c�s�9HL��at��F\�7�.A�+U��eL2%�%X�'�\����9�����j�s�n���8i�/���F�#�0����A(:�����f��
.>�(C���u�w�3�\���o���@s�u�������8C�������[��z%8r���+��\�M#N2�9��I4m,���]n�9C�y<�(����N��?�����$+�P�����1��A������xrv��i75If�������"��c����op���d����ZB�rd~@��u	(?��s�5g4���n�����n��J�V�r��;��w��r�v����]��	��������� �����4*z�
����u�>�
�*�����E[UHy0��JF����	C#�p?�����y���N���g��e�I�}�����O�H�������"��6�w^Z�"V�$�do�w����{��J0�F����n�@��k�A[�ASD2�O���G���O-������fc�����������a�/`�A���kz��f����������yU�1xi�5�<�,�.}y�z+��3��i h#�[�:���P �&��������b���
��B�%
5RyNO��Q��&�D�l7]���P�G��,���G�� ����:�n@@���z������*�D�*��<]!��>H6��>�b��7C�y�+g�G\}ps�NjG�Q�@^�_�����������8�O0�X{�H�����#�����h=���S���Q�&�������#�A�9�HF���X����K������k�`Bk9��k�<y������]MX��b�bU����9�Q�����Q�f�'B��1�}~��Y+����&��������C��i������#W~��+h�x�ZQ�B�P3�K���	�_�9E���/�����`^���0��1�����,l����*��D��2����� ���;�M����]��Q�p�6����"���w��JP��~��A0�����������������PVgM���G�7�=l��|���f���p���!����N	�bn_�P����!��?"��j�_���y/���[�,�<"�����^�c?y�<4����e�lZg����H$���;~���������q����\��1q��$V�y�������(�@�H�st��H�I�.n�M���w�}����Q�G�~����m�7lEJ��0jNv#�|��K0}I����h��@��+[:N; IDAT�T��i'���4�bz�������o����xe�8�3�4�u������Vby9����kqN��fM�R�j���b�rd���{��\X��oN��)#9z�}VBtoG8�y����nA���7tHH����_�}g_���=�{%��o� ���f�Ah
p��r���L����'��������#mnvRe�����6�U<���!0�&��A�����m{��&{��2����'QZ�@S#�H:��!8$y5��0��H�X��2���y����Dyf^��~K?]�`%�)���c0��M���Z�$�)��8_����>�����P��G�������g�����[S��#�F��6�+tu�w�Z��2o:J���������$+;�aA`

�\��"����I&
6��	.��o�j��+>E�+��dv�:���zxH���� ���_BjP�H�fWZ>��-��&�TG���~�o�w�H����C�9o�;(�yD4U#���/1��aR��M��%2�L5}����H�^���u�R���g#�F�^��|�-i@�����YXY��u[�zCX��$�� �[�F!�q
�h��a�*>�s:�����Y���5,Q�Do,
�!9�8�L���Z���ETG�#kP��$���%S��5?�n�=��kV������M�N�\f�a`��d�5#d���x}A�W����pF���	�+��k	��Ag�w��.�h���\c�O@���qQ�V���K.1���Q��������]Q���~�>�z���=xm���9c�m�o$�p�g�U|U��i�b�s)��T��g��P���k��}�6<��CX����`�E 1
k�N�������F��E��Z���%]��(��<������M�����4�x�����MF�R��s���5�k!d���D��qHc$T�C��.��v��d}����]�v��5F�z�����HV����{0JWt���������k\_��������&�������@�E��x�%:Q���3������^O�_��������=������5[j���G��:���Y��t��:��+g�l�j�6�a�	��4<�6a�����=�0�������?����lI�*�q�%��a9���d��D��a+E���W�1f|u3��������v����kQ�����`�}����{%�F.�k\�;�����?�r��.~_o������0a8�7������t��B������9��T�ik2<)pD�<�DH�P���=��!��7�>q�I�WR���X��W�4q��,G�?WJ3���E���L*J���"�����c ����9v{�k97���HUA����u���)$u�#���
����3���O)7/+�ZQ�I9=�Rg���C`d�����c���3�Xe����+���T�gKD�R��������h���L��:����Q� 9+��84�v9����1���g�5��9��o���]�p�����=����[�qUsDL<����	-��y��L?y5!}b��Pj=�a]�v��n���uE����X��v>[��Cp�����Ww�g=�1IhohB$��>�8�f������{
9_&o�K����
Q�vx46|�
��`����Z�(���
7���A�>�l��]j�-J�k�lD��
��l��O�(�X^{
.�aK�$D�'���31�������Ov������L�������?s8��r#�~�Io���W�������7F)���~m���Q�����N��z�I��A5A��P\���q��!)���={�g��43��UC�D`^�\��'!����:�('����y�j��E.=`���?/���g"�e#�����-���������L��1�	�G�>���������19��(��7k3�0�DZ,T�����6���/����y
0.���<MIS+��n�r ��sD����x�����4$7���O�����r�Br�u��{�4�(6���,`y��R�2�|��ff�}�axiA:�`:Y����)�M���	�f��`^�G�?n����T��G�M���������t\�}�{������B/���`?�F��������y�*X�U���8_~��W."�m���9��������S#-*������8����w1~x�A�R�s�_��+2��>�D#W���.p������i�s�:�oFq������h,�R����p��?��v��$��������Dp�w'���O#'6CR�w�$�eR����rz�x��h}}��2*jY������M7��o��SUG��v�U��%�������V�|�	��1��S�vX�y���_:�����[W�����������z9S��t��oS��E��6�sol��	���b�H�����0wc~��W�HE���[�9�/b"���A��9�b�3�;�����J��7~�_�D[o�����������������������������G&)����ek-��bX�F7�r�`�
s������$Su����@�C�kL�/���,4��[^*�9Q.������j���5-x��&��q@�����`.�)�����4����Wws�T��!����T\Iiuu6L��E�����|�!�2�����u�����O�7y�?��X�<"6�DR[���Hk��5����o���E����H�c%s�����"��c�;n�������g,��y�@�M0��E����w��z	������m�x������w%���������1���\�r�����*���!���v*o@�	����M3�w���������W��.�[�I��/�[��v�����l���/D����|��u!}�%#`(M�t���GJ1IG�<��[O�`�f�??�o���cL���^/��N�a;y���]����i7L�����C@I���%��}JZS0������D��..c�"2�@>�:@5�7�xL&m!k��>�\-,���A��0�_�m&�Wu%"��p2�l6��GFOb*
N������*c?v����&�Wd%��X�?�9�E#X�2�M�����[��~^W�x?[�%�))
����+1	q5m��7�F���@V�&"�~
��D��Xn�����%GR\�0Ex;,��:�dF�U��G��r��3Q���9i����3�x[�:E����[�mm�]������?+�i�+�3�`z�������6��y3���x��H,�>UU]������8���{[�����\�U��8!����Qd�4!��F�rZ��IIH���nz�������z�nC)�0��O�b��NC��_���f�-�p��!2?�}'�5-Z7�y����#E"��}O�v��'Q���h���s�bA������Rgup��;�,3�0��	��?��L��Z���qq��m6r�?~��&r(�=�8�2���n����s���;=��f��[��F���J�����������a9������:���Y�D7���2[�/��'���&��&
/�_�bt�p���Fp@9?2bd|)�����O�@E
�\��Q+	WF��"�r���!)�5������T%��$���������n����l�W��������|��VI�W�G���yOJ��2����`�����U��;�<=����`sg��U��Pe��bl�f��20KYq��kz���6���7T%{�e������[qB�J���Q2�FB#Zc�1l�`�0�c /���+�;!����0#MhW��u+��nc)��,����w�w�w^��p�E�����X��&��/C����3���7���z��E�Z��Q��3.!���������(Ys��v���Fw������(*P�Fh�LoZY�i�����U��C[
+6]v��	���}n�Y��:�0���O�!����3\�$�����Q�����{��9��/t���p_�=�:j&��6�����4�Y4,]	/7�z�R�sv�"x$�&�$���z��5�����L@m������E�i D.���B�{��"n�FI��B��Of������\�'W��U+9?i8l��E��(4�6x���p����v��8"#;W�+@:�X�����9�tk�T�Z�s%�a�����F���r� �p���� �&:�����bc���}�����Qh��G���Q��<�|>�r]�(�[K04�9�'��s���jI�I���xg���|��i�VF��'�N��cj���u��vj
����i�db�;kqJ��]����&�2�S�+�a���C}��|��H7 T
)��z��������}�M[��L�6#H��T&�w����s��y>�2��x7 ��HYj]g�J�;��W�������g>��x�s�Gan�qpP!���Mb7�y��iV�	b^����T�a�x?�����b���K����1R��[�3�s-��e���"bGgUm��o��n����nC�e�=��#�J�{h����u}�L�+8��I�P��_��1�Y>74���6P��g��V�Q{�"��P�M����zLl��1l�
�C��3�l���AmL����o�")���G���lEQ�!\�1"��m������{F�����Y���6��GC �������e1����������?"'����~�sf
��eL������S�H��8��s��0����4i��B�5oIE��j?l=�83d���'��>�b�O9J=�*Nm|�LjM����`��ec�����&zb{_�?���������^�1�(�)@��6R�"�~������.|�=s��Qk��t��$���5|x�Z�N/��K�^~���*3|Y�&��x�f�����p�w��s�gFi�i8��X\kW��5���+����K��h�Q�&B6rD����y��'��.���m�sGJad������mk�^	�����������A�C~`=6��b<#<O��������u#f�����3�\�)\O�m�z��C�VdU�I0+#Z�b9����+�������M�*O�a�RUURT��%
��F�����Y\��`�
�Mj^����W��y; )4U���D'P�V�����r#��o�f����o?l��o7G��F{����	@j������
�
`��Kk0���/�]m<\:$u'���+)�L���c��3�����r<7�j�5RU����ht]��wZE��@�(��7|��%�@���r���t1��?Gnz�����k���+��#�������u(�G�Y�7s]�p49|#G�;��e+8&��'�,�]Co,	=��k-#���Z��'\�5��f���s~����oy�CL�P������J����=��w�0zS���c!+B���s��C���~9o�?��y��w���`t�b�����+7���,����8�cy5��X�\���I�8���%FM� �g�})p�h����+
�k�3]I�P3{T��RL0^�������!B�zs�v�6�&�@S$#T%_����GW��d�@���d�;��1mOb��E����!H��[��nF�����������s������4'��[P�e%�B{R�Kd=�s��3��/����<����|ff.��UBb�V�g�y��W]���]5�8	>9��4[�������=����{�i�[�����Y������b.���O1O�cT��o�oGpm�]��7��F���>������+����2���N�����!����3�C�����G��8�o%������x������I�Q�����
��_����A�(jP�6�/L��u�����
\����'����aQ�`#����g��_Dn�`�F.+�����`t�B���g$���p�/�Q���7&�`���<������sP�J&I��$���c�"���}+��F����,�l<�	��p]���ZS�3�o���L���o����/p�������-���U��%�/�	�5R�M��c�3��������5���&
 �~��	�a=��3Z���B�'v�����Q���+��h=�G�����

�+)LEVU�A�_�����f/S5`1	�8fD)_�F���@#��V)���d�����D������{�3k�E�`��X�:8O���\�>$}Cq���^�ny�=���XD�x�X�����u��`��?�)�/sQ*#>�Iu�m ��?�u���0���pk�1^H��$B)y�H>�h4/[f��D���K�3�* ���C�;��%���,t�]��7f#��y�;��<n=v�	&�P!�p�a5�O9e
7��G���Q(��_D���%�FB�
X����)	��$ �&(��(o)B�rq���P��<3��O�� ��nXq&"�.��/������'����f(��f,@�2�g�^��R�t�z`'%�,y�>y
e�n0^2[V��w�(m�L���@�:���w�?@7�q�1I���P�M�:c������$&�m����R~�� ���_��y�B����c�CJ�4�����/L�!�`5����f���
�1��y���cOZ��+ix)>"0J��6�'H'����Z�������K8��-�\�bR5����3�8��p��}����I��l@���d��f-��V�b�+@�>�h�>c��������?��+4P��Ew��	ly��H�6iL3������U�g�g9���b�vD��' �8�1$sI^v���0�EI��	)�"IEsl��
��"�}�q&@�L����e�F�0�F�3�BwT?��v4���(b@��O�7�@}g?�����d������yxc�q���<���
�'���s����J$�������8��)�%t�N�@�=��m��`��cp��������f#b
l���3hP��DZ����������L�D6���c;��g+��iQ"�D6�����w��d��c0:9��eH�=�p!"[�7o�:�OL�RwFR�?��A�����_)�o�g�����\��f����T�����dg{p��J1�cn,))6����eQx�����1�������|�{6�}�q�0��y���&1[bs4�(R�3�p*
b+q��?���hL����<�c��@�/fS�D��v��H�&���OJ#�##���O1�����g��3��v2):1������X��H��tdp��3�r,�����)���#���5�\��A]d�FT�"�+(+�^�����er~��(q���v8�4���3�����]`�;'�`?�nE9�}��8]u�����s��j�7�4��ND�������x�i���T�#����;r��#�(1
�gOi	[�m ����j�r`)&??j���P�K��iO�l�g�p������:�O�v)�B��+�c�F�P�#��������a���e#���]=���i�{�����so������;������
��3?.��\r��m��W�gmx��"�]�8�4�$ZC94%��+#������..<*��:�t��~

�u�!���,��AA���
y����(�����JL���_
\����2$v����������[I��u$�����$�i�&@
����0C����<�3�L6�U�N#Uyr��3DS)������������n���	h%%�0*�����!�U��y�#L�k���J�*��#�n�3c���T��P��"�:l�����4�
��oA�A�Lr�m�I���/~����kX�����D|�^�@��\
F��k���p�(�5U�az>����kIA�l�J��r��<��l������C��9��Vd@���l�$��3[	�����&���CE���+���iu�SF0�[�K��	���AO��O�\�1;���eC�'[I����-E'�����h�!����w������r.�t>m�6�����.CL�����Oc0��MoB2�dd����x�-��4��R����l�8�k�m���=+�S�s�O�M��j�O U�f�Cm��X}��WT�L�G��.���i(5�f>Y�}?��B����'�%���X\���}]d;��kI~T��������-h+-GCG$��L��6����L�F�%�k2P4���4�<m���w�zf}O��1�{jm�L��&ft��8��k�4Z9���������12�������i	h��F)������������mP?*�� IDAT���&��P7PO*������;��������#-�<��)'G�����&�JN��BJiG�G�/�1��L�)��-�i�/ ����e`�kG��(���X{DG;��D������w��X�;X��w;�7)/��&'o�?0�}5���U!���GR�Hl����%�����T�"@?��=�t���
&�":����$"u32o��{��-m��Mq�j�5"2 ���5�[�X�7Q����v�:�$�
h����V����*�������c0�gU'��yM��~d�Gu9�=�660�(}��;�_R�
)'�+������)&�xy��Xir
T� �^U%�J��Y��9�m�r)����4��P��������j���f��(�g�������~�i�vZJ�E���v8�� [{�r,B��SI��������I�
N0wVZ����@��������v����;���%�5\���!��f��a����>b��8��
!h�V�
73	���i�����0|*4����H_�KGbs� \Z{'�C5�<i�XR�>")�(.����K�U2�]w�*���>�=�����/4��7[Q!
�T�%�W0;�I�-_s#�'���PB,erC$�:_y/dH��"�;)�w���^8^Sn+�w�}�(�W��8����a)%�3�����89����c��
��(� ��Q��N��'7�;���$�)��Wk��l����i������Nd���_G�vr���
�<���V&�|Cn.[eN=�L��1�F��"�i�g��D�S	~���=	��Zp4	
J��W�	\�=��`�FS�~�k��f�#�|=��n�p.���O�+a���6�^-���[�tz�u��-��q��m����*�!
�|Fy���G<��K�����a}��1���s�g�CT{����%�M04>4��P��"�\����/����7������(���X��<��q>�=���f?�}�S
�R���L��y��'Z^j�]Da9�F�/�[�]c������V�����'���p��R��9���"or���z
)>�p�M���?afVt@sB����H����T�tV��J���2���[�p��(����m7�����W�Gt!���q!e��m��*r�R��j�29)���P��b��������=Of�z�#���Gz����/����L�g��L�3K������FMS5dq�c;��v�P��������=�WAG
�um9���yE���e��}U�ePI�J����N��U>�(t����f��X����s��4�PS��)����RZf������cN�X���2�{������$&y��w����e@R0�jQ��$~%��K2�������F��-XPJ%0���p��]����G`�7�j����:���i�t�1�u	�~9j��/�f��#�{Y3�t�GY�p�1V=�L[�WS��Q���l�gR �I�Q)��Q��������P��!��-o���f��Jt�x�����,��$P�j<k%��g�7h{{�g�R���"������z���
�7wB�kP?���� S#����;{?��By�{�����������J0��7��m/#r�'8��U�b���YN%��MC�B�/"����x���#����a2lo���3i�9�������8�E�����8�l�f��9���f��o��q�aBj_�x��V�{o+�V���1�P"��E��s	�BP1��q�[ao�_�>�����zD��!o��.V�k�[ou�Cn��\�4�k[w�6yF���M:��p���x��s�����z�������g������O�v
DJ�\�Z$�����o�!��xp��-���N��:�[=��O��I�]L������L4ux��M��g-9�>&��3/������x����zD��\Z��e�	���e��h�j��'i�I�-���P�.H���?�tk�s��-5i��]=��<C�(J���J���R������P���s�#�8PKtM[����O���}�1"@(Z���h���2�t�����9�g#�8��g�1���Y&{��w����k����2-~9�����[9�=�Vd#�����3���{�l���}���) C$�m��J�����-#:��wJ�<�^y�~F�>��,�|�T$�����/��8y���gw>uc���L`���2�"8��;�c��Jd�[�@���?.=
� �w4W������4'D���;\�L0v#Z�`�j�1�y�����|�msK}/#Cs[�WC/������a1N���;{�����GT��I"+�?��^��5Ol3��8
�_#���r���
�#��a���8��=��bQ���,?�^�����	Vuf[�f��z����7��7��N�`kDX���c-��������c���I/����C���	g6?�	]���H�_o�5V�o�>�������ny_���C<����a����G�\�>��r���"&ND���&V�����K24���TK�j��P_����b*a)����(R�\T�:�|����V���Q_	�L�|=+J��Q��Cc��������h�Z���l����%���ET��-��`���/��������E{Y5�Dh���w���4��������a��r0���}������?�i�E�6�Z��;�/_�<"R8E�V������������R�]�7�3dHX��xhO��u��/9>}��`��N��{1�aD{�����/����]t���m��aa�2���w��("���,Y�I�&o�}f����o������9�=��hgD
������3��#�����y�],k5^y����:	��������y@�����b�)��~Y�h-�#7����\4�.f4�,hye��w �����7T��5"Q�	���RD�sN�������4��P�4���(�`�\�C����=z���	��7\�5�x ��d/��H���i�4���}3F�V�#�FZqH� ��Q��_����UK�Q��~���	�7�(4*��@�)m���u����Gb��.�(Yk��*���P
G>"
��m4�m<u�s��@�HQf�P�g���E�9�B�7)�����5^Mmb�7*���6�	(���or)U)����s�h�R�(��X�q(����^�@�]�#��N�n��<����/��|]�+j����:�y\.���xE�8��P�UI�fh����|��l�c*�C��<z��5*��y+@�[�HA_����Y�L�
kl����;��@��m��}No��2�<���������D	��
���d"�������
4�]�;"��1	68��,P�dw3�H�!j�.zGL��v��p���8������g��m�"^�k�
B�Q��f��%�2L��h���8n7��X�uuA_}�i�}�4����
��gEK�USL&.�y�?c��%�(�M)�;��L��������CPu����@��
�|��e��du�c)������"t�Hc|�i��g�����9���~�m�h#�'�d�N�U����������Qk���������+�#�y�F6WF�n����q�y�sI���m���j���Ph�{���/ ���AirY���A���u�3�=�����T%��}s��]4z�b�l��$����*���;M�p4{���3Q���#k^�����v
Z�R�O��Z����c�w
��5�)B��w����h��x1��VSQ�d���i�P����y��M������0�p�m�����-7�	��~JF�����|��?��Rj�F
$��DJ�,0���o��U��E]t|G��`�Bm��hO��dB�a[�:!o,�en��l&������!���4'�%�1����9�4zm�N�"\E�z���)t��M���N4g�W�=�W���~p���{���0�H���7��k��QPA�����#�<���F��p^���F[^t���l�Wu�qp������CHQ(���7X0E��"��};u����Wh��k
*���<��c
I�7-�=�Z��2~"P!�)�87O�[�^n9�����^�k'�J�l�\&�mc���J���Cnu�Cf���;�t]w��7����T/�������2VS��Mn���+��(����p�b��F��_���6�!N�������bpt"c	���������;��g��)^���C ����g�P�? 9�K���m�Q����T���8�zn�j�\����8A�:��v�����B�HP-`bQ9h9,O�}�J$���w�1��R�Y���������OM=��(r�D�.0��#(+J��(XE�����T;�)����}����(/���Ij�� �)5V�X<l�?�}/�<qE�;�d����t��WQQ�d�
�i�Xf�e��O0�
�������] �^����|����M�
+4�=�h����=�8�qn��"��o�$F�:zR;j���a�� X��������f��}��t��c���a.6{$]�������x���by�5��e�j'#$Q'!�{'�����XXb��5��Q["���2�d�X?2\,#I���v��B��lh��	@mJ�}.����LV��y�WbX�4����=/�d;GB}���7��k[iDty
K���]�%��C���f���r\=N�bSY8���EU���w���((q�"*-�5��da=O)3�].��� E�=���eH�c��5T�1T�J��j�WG
F�/�5��_�j�����{�O��tE����>��i���J&��k�Q����X�)�5��hR�w(|m���e��l�?%Y�Lui9�D���}��8���a]�������r�e&@�~�E�7��
h� �wD�Qe���+��puT~~�E m�IgEt�,HH8�N���E��Q�^x����CI�g��b��)Z
C�
:Pp_����>�T%)R�'+j3���u�}���{`���8-���3��'�I�C^-�n���qC�u����m��`�����.�q�'G4����X��\"RS0����M�����_c�@�^�Nq7��3h#��L���j��Z$��X�������������~�]V��gG0����~�u�_.�>#U���o���g��J^�����+�c���l���n�ZZ�C��2x���-��6����gf�(>��!C��0l0y��T*)���6X����'q��15�U��,����H�����gBW&��M��C��f��sF6����4��z��+�'68�I(��H����A���������p���6����yfEy��n{K
~,��/e���pe�]����h:�sI�}���mGtm��iC%*����`���U�{�2+)�����P����}�~��;�c�+��m@������|a�6��N���k�� y������nZC�nK=I�'��
��C�	���u�vp�1��2���mL���
�>��IE��u�P�l��z��"6����-��>��o�-����w����rw��e��9.���s��S�=N��"���&PV]/��C�3��"pj���z�������k���|���O����O����R��=Ta8}
o�yM���� �F� ���o���pn"|RR1~�0�����EY����Sk�����Lx��g�C����+L#���n�3~��	�>�0��>��^�]��y.�a��-��������RYb� �8i�U+Cmq1/"1��7r>c�o`�!�c��fO�"s�V����f�C�*3�5���"t�,������q���/K����$���hG��_���b��?�k�@�����x0�x� ����W��0m��P>��FT�7�������h�}�B�b��{���#�����T)���6�T�8T!H����H
|tNq��*�$K�R��E��]�M�
�F�������.\yb-n8��=��������p���������J���C\�io���O�����`�2z��z�-&��'�� ��rJJM��u6Z�����v����z��hJ42�i.Z>~����11�^s��*��r���'���D�y��b9����w�}�b2ZL|������~=��<�Z�m��Z��c���=�QT�����	kQ���f�1��{��c�!j�8S)����tY��=�x(2v�`����{8��e=6m�J�����_�md��%�iJ<���z�!5��r���3mZ���6b6nl�W�zf%���3��<���E�c��e�s+��O�����7=���Z�C�����/����?������<�	��0&�������O���x�;r������~>�EC��`e.������Q�!&���y�G���V���. !���bKy�:By}������V�������ny�T���3K&PI��k���.��L!MH���F���M���JQ(�v������JR��6����
HZE���������;^�6���
@�^�c����_��l�H@^�]����&���F�X�4�������kRM�Z�����'=�y��+z����m{����=-��9(Z`��j.�{�CmG
�{:�mv]�V��s8)M�&�v����]U�G�O�dz����\� 3�����&U2&���"��
�JI�|�bXU��|S�������U��L�U��e�����1�kw0��w�8	8[�������D1b}z������g���/Nh}'n�E�]��R�K�eV=��X��|������Q:������y�~����K�t���k��gV~����=���E�S���hq����[�����(���ne q�1$����&�u��B�:i�nV���
Q�x�b[+E~�$��4�6�S�QTM��h�����f�������P��3CG2�RV�����Ic�����1�V�@{���"��e�z��,D��\��Q�����U-�#��Sr�-(�5�w��Pv6�I��}��a**�0�d;U�l���q��Kj�)�)C��[KH;��.����}c�DYJ?��j?c���n��]�]�O8!q@W����4F�������`~g���h�������g�l�.�"��6&-B���������Q���a[����/�	�nED���5�uU��6��\RI"z32��*�w���=d���g��*�}���� �D.G��[X
P��*�fK/��H�#���2c��Mf1�?�G��$�ZZEp�lt�[�+Cy�%!��H!'��$yy�,�0��n�M��b����vS��	H����DP�>���I��^t=��7[��J�)F�/��ub��W!��Q��s�	��=���)�9�g���Q��8'7���h��
m���@#'��#�`:��B����H��n���{�Bjm��*c�z����
�h���u?�������$>��!�<�9FO�b���ge�4�oY�s�1���@�������'��6C��A��3=o�Q����0�Dh�����p�HFfy��%�hmK��Tg������"���o����>�P��"I�O��������@��md9�������lC�L����~/��2��u6��I�E��?��d�������xy5%p+c�8�"c��~�����9��]�~���P�����]+�A���	eAX����;�Y��6GC�Q�������PP�T.m�x��4;�������H�%��0��}���F~*��p���W�Oo�@��yU�O�2
�6[�����4c��lj��?LD�w:���P6�����H�YI�?��X�a�g$���k;�Xh�m@Q���f���
Xs�9F�<�����hq���=�ZS6�}|���<���"	*
���q����:���0��3z������V"/�
w*|9����a\J������u��#�8_*IYL;
����*.��d9�J~V�v<"��o
����W�(���|t��!��WEV�RK$�Et �����������J����KY)����q��T����j���q&����xqQya�d��W�e*�U+/���E��oi�?�P^�����g��VRm���z�Y��F�Z�-�h{���#��h<�^9[}g��Fdwl�h�����s���f$e�� ������SCIc�+
���~�o���y�g�������H� IDATR��&iLE�������E?2���&N���s����Y���~����|��G��5�jQ6th��g>v�T&_&�}�����L?y���<����3�At=��[������/-�g'�E}f����7.<�����Qp�,-"���RR�J��������<�����Q"�����N&���i2C�������b_l��P�
]�(��>���?�h�)A�v����ua���C����0{6�����vkU����c����Z�
G,�����&Z"@kUzU^C�I����op��,�~�Q��p@b_��i�N�A�$np��j�������*���^o����ss:N�Z���T4>����*�*�����s�fJ$��/Y�CI�����
"nl��'�n�nq���L�j��H��,d ������H�g2
��y���%�Z�����(���a��K?�:�
�Y���)�*�X���rC���T�LD4��*:)i�,�aM�q�55�h	
��6�u�u:=��1����r����fi�~����iZ���L��������_2_�"����[}���~*�r^��D���t�����=�]���X|��}�sn�y��I���Q�����a���"u&aP<j����������9�$�Pt�����l�
t�1V[��"pn%�Z����M����1*I�E{�h�|�)�!��������0�P���4����B����6)�Y�P31���
@g�dZV���8��S�q�9x������Az����1��z!>n?�kx��G�:"�������������2��(�R���l�S�a�o<����E���=G@��K3�Y�����5��J}1�A*4�M�`�-V�����W�c?��E�{�m�X�R�3k����l�
>bt6>M�:����_S��B����KrQ�����������cD�B��O�hA��T�F6��kv�w�K7�e�RE,�f���v���=�WQ��:����a#�r���E�1�D�}��t��y;TC��������*^����vs���;�����G(u*0�Qn��y��&�-��.�p����h�[�PM!�1��2*�*F��Q�9j��2������b�P?+��#�Q������=�{=��-��,`���C���VB���@G�/C#����hz����;�|�#���_<���s�����d@�2%��W���	��FP	&��Q�=���V�_�d�����I/ �h�[
���*O�����J�O��4�h#����J^
��v�����Y��H�9�(t��e\��8��r���D�z���y�O@\z������]��x��(���	���Q�Z��K�~�$}�a=�U��. UB�wW�cz�;���B�{,fe�w��>��(����I �0����k�+e��YImR�y�{)�����g�:�������Cz/$@�M@�{Y��*������"��Z���.��.6����* R��@HH#!!�g�����;�3��@����W����{�r�sJn�Z�h��0����h�
���<��
�|D��J�S��!������d���/�������@���t@aW����e������w@'S����b��7���u�ua�T���"��3SthH��vP��5�g�!���9A���./��Ej�f&�l��l[����F�oA�g��^C�6��B�������oC�f5Lh�_���������l���c��{��S���P������6��oc>�(,���y�i2R���_1�%K9QI����b���1kF��cRS����c�Up;PtJ��Y=�P/��_#���Q2��q���'���
'$���*�`�(c��?6C����/�3c�1?C��>+f�
_;�N9g�@1}������T�>�R-cM? ��������r�`7!��l4fg��a;�o�qq�!X���xw�M��VF���Rm���9�v)~�
�9-uP;mFu0���ARr�m���22�C<�.F��#f�:03i�9�[�1�&��{`����<�8a�4���*�$�{b�\��72�Jy<>�L&��4*��s�����6s���������2��yE��sJ������@�x�L���m���9����1��w�r(xP�)���j�t����\��������|��2�2�)�� �a ��
(�6@�w��EOK#��.3��j"�pp�Q�����wo�2����r���3�+#���b�W^G�T��D�!.M~*aD�oe1���$��;
���/�}��%x�2E8�,��!{1��9��Z.}XG��gX7���}����?7���de�S����������Ki�Z�\�T����q�
Q��_2G����[N�|Qz�(�j�P���x�����^l���2���v�z�%��}PF!+�_���vw���yv�6P�?,'�Pm��@��X������x`+��8�i7v<'��)7J��]�;�`f�AM%G�Y*���bT[�:s�>UU��1�s.����_H�G��������H7���|4�tD�+�e�Q���D��]��Y��
�F��������no*�b3�h�A�"`6)��&��.7������y�V3d�K����B���j�
f�@mbp
(��!Nl��Y(�m%�7t�-����o)�x��yl�^PN�knW��M0*��)�!-����h��7aY�y��w��/����o�� 7�V�e���R���2��)n'�.M_"n�i6���#����L��-W*'BY�Wd\"�8!�L���xUi(��~�n
�J�:�K��!�	�������V����*�~/�W��WR�2���:�=����hB�{_K�I��bd5��z�"}�[�f�����:��������)b������XfA��'�bn�bj���;���������������c��^,���s����)�}�3�?�ch+�`4�g@���n����$�.����'6�$�t{�U���o����
��g��!���Xr����C�6��b�U���v6�4hid�1���y�z*�Zf��eP����Gv��2-W*��m��
fV�Ri�h�H:Fc����3C8���v���K��K����3������X:PF����kU����gW��9I�Z)���<�W�4���"v5���o*����0�s���AZ<��H��8V��ZpL����vK�?�����,���X�|�s��Y�0�|o
��}��2�Y�b�����������G�B����gd��C���6���f6��;���X0�	Z��a��.~X��}�?����eH�"Yi�`���7�5�#R���'�E��JV�i��4���I�GO�?"��0<�x^��Y�
���1.��&��}mLn���y��R�Bw-����H8���q���5q����W�^���������j��:9�h�����/6:�,,mH�/o�\"C|�]l�`�
��E�����O�r�7I��O�fj��n6���t�"#_As����=n��Wf���u���
��
l3-���!�\9e�`��c�0��5{������P������}������j�:���Ag���^9�<&O�����@t	e��>]�����s���M��qq���� ������v�~��\����w����������M�|u.���zS��J���`�:	Bp`�$�Qy��#�'W�]��3��S��#��XI_4���~,�-�{"r�h�~8S�d�w� VABm���X�lT��cA��/a8�+��09�O����~��[3����i��Y��xk���DF�"��Q����Y��y���U��A��
���� dQu�-�xQ�Y K�V������g�+�n���}�W����V���o��&Mi|gc?�{n���"����Y���f`<��!���.h��V� ��Xg�ZC1�a?�v�\{����z�/*�:S��Y
n�2i���u�jm���B����U��no�4T�X��ib#��9:� � �Z���u"Ym$����	��Z!^�l����p���a��od�Pf�G��UW���G6mT��A�i�hh�������[���OJa*�@�'iB�w*Q��/7���(��'
������RsV�����3��2�
*p4���R�_
7��*$eQ+
`O~���S�|[.wFe�WB�@c%h����
>��H��V2xJ�[���q�N�_K5h�dW]�����I:*�x����`���BUfV�xe�)~�7���[��$��~8=aRSX
��G1	���QG]Waxj�\���`�s�@�.�,������g��'~����VB�	#�,=zTj|�,�m�k����K�n��s(�dV�������oe'1w�\���7�*2��:����e������>��R]�\.������j�]��yA�X�,�-�W���se${�UHu���y�l��H��vH]5�����^�y�6F�s�M��B,?����y\w�<Sy�n�F�~[zzHKM��@��Y��dp�:�3 �TN�GM�Y$���FE����bS����2Q�@u@��`a�[�����XhR
�bH�q�T/_�6�I�ndo��(�-��*'����%�<C�^*M1��'���M��^V~,?c�������w�����o�l=X���S���J*����Z�|0F
�R�]:c��c<�
R���{r��V]�"'���~�*�Pb}���-�T��}�Y)2&�x���i����s����/W���x�C@y�t��W�����"�T���>1kH@Xq�`9����a[���p,�"����O5���L*�O�/F�����*dg���#�������N���t�����S@Y7�Y�����eKe�Rj���?w���A�tN�b���cm'X��h2�4��?�t�����E�,�-��-T������/��5dfJ�I��9�|{���#d�����&������HOS�[�>�w��2�>sV��qt{�7e�����9�y���R�Nt�00�!�f�aw���(#������7��l�ye����F��j�r��6AD�h��
�<zg�r�i&#�'��������J�(�)��]P��#i4|��'{�!�m6���L��/0�(p
6����w�����x�L�EJ>7���t0�9�n�����$e'-T��8
������!�.�����!Mm�������8�Y��~��P�{
Q��������g��8q�/R|q���{��U#�>(57Z8��y��c3L��������S�g���,
�zb��~��M.��da���Y���{e����_<�a�Bf�b*�PC4���z��J��8	�]�e��~��|��C���mS�7�R��f����s�c���,���=7B�M�V��}��_�sE����.�&�����:��-P9����~��g��2�)~���g��=;���E�
=��O�
�8v�&w� &�a�d��l��B!t�l�� ;J���
��
nc�W�R�0����.!'�0'���Wux�8l�R�^ �p������^������dc*�	T�F5
^�����u���o�+R��~h�Z���������"����@aw<L��V
�m���!���VY�x��|7]��
�hL��$���y�z=!������~�d�L��=}�j�
0�����QK���v<0���l+�T�Z
����|�r��Yu�AE��D�(,�(���|%VA{�����PpG��]�l�9�r�;QEU��b��r����Z�)Q�"mf�S��{��I�	?9c�w<=�#�N52)>P/�p(���������?��9Iu�j��n�����K����A��)�8hwP V�{(��u����y�=�m��t�
R�Q(z]%�'��X�|rw�L�>�:R}����2�i�����{��IC|�4�E]L��R��'A�+���������`��Q��pd�+��T�N��e����hL�i��
�zNh��TF���H��C��Z�#GJ<U4c�� ��H�2�h�l���d?D��5�*��>�z���z���� nT�2Hy����3kc�\�������:�9?�S�����,%���0��=poK��*a��k�KC8Y;����C��k��$���`�\R��<���4b����S�i�I�``����1r���f#�Ks+4R��4�.o��Y>)>	��rc`�M%�������m�����G��lD��9R�z��X3�k�9S�,8_k|&�)���Z#�U9���<��y��95b4���w�?GV#p�����1i_�S*�e�0���e�����t�z��p[PUm��i���VE��r�����m9�G�Aiv�)bV
d��b�>�,�����g�B�4�u]]Tu���b%�wx��Ore�����{D��wY���w>~^���o��7�dK��-J:�)cbP|S%��H�N����
f�?�`���_��V��x�3p����fH��9�%�?nv��#!���.�io�tA��5("�Q�H��.�������5�}��G���C���D�)�g�����{�b�����<�yDk���[�p1����'��I_�}rq��
9�g�4!����<zX]O�(F�W����mf�`�>6)l8))�����"eT�;�}�\i8P"�-P����2^�8`������~?�P������eR��4����1zU?�d^�h�b�`!-��tX������3G9��Y��_�6!_D��<�O�OL�>�=s��������*>{�8�����;$�6[{�����v���WN<Q���n�=U�(�R�������B8��Xb���D��Z�o:Am~d�9�_�nIU��;I����x4�	��?hP�������������/��o�����xC�=�6���l���5��N�d�&��c�Qi�6�9���7���o�[�D�)a9k�LD�)�����dH���P��0��8�[�]���=�vV6Ct��
��=�d��w����}R�J}d~�����?��)���m�r\M�d7�Vf�����&Oo�����(���I������$�h<��*#���1,&P|�a�"!1�h���o��T� �V�Y��Q�%LB��6�������g=����dz�q������H�����z��y/HS-���Z�3&HeN�TT�0-n����})�1���O���BY�V��<�xK�	��Wt�����$ck�d��@��>Q,
���8��y�3��d����%`'��2@r����$Qm�P�ZoU�G���A����oX������b~d�pb
���� �CgS9\f\�yD�F ��% �X_������s����y���]C�a�_r�x���2J^�1��r�l�?E>�
���J�	Q�U�R1�bY�9V�
B�������`I��$E^p<Z����=�	�*8�p�x0��-�3�(��{_A	���/�)'�xE���!K2+Bdy�$����?��,1���&��#PB�] \S�s"�($�v�V�0#h���Q�p����4���#�{��J���V�l�~�7�)������:����{

&�����M��cQ?\���F9u]�����{��R6�"������kF#�icS�0���U��<�l��I;���(��R��#Z^KZF_�w/��,e���U�G������Py#��^��������7��L�`����|�����_���48����;�^�^+@O����T!����������B����_����K�7����������2� ;_�0H*+
�l���"�;g�Y��9kK�x{�O��q�B#�;�$�	k����a��N�cmg�x�%k:j�D��_4�Hcc3�!�n��t������)��:��%��*�e�t�=��1���\\��X�e�"�c[~TQ�fo���H���j3b4��
���%Q�>����R�#��[���?$����:Iwr���
@����\�����F��BDEti^�O�1����-���#g�$�"�2����B�A���,�s��U{�C�~�S����x���U�M���a������T�c�-+�A��m�V�D3h�RtBGV�3�!���Yg�/p��"3�]3�0�4wn��Bn2J����6-
��� IDAT���el��TP ^(�A�z#�AO����������tu�$��u�s���~�)T����X���F?�q��3����M��J����!���6����K��te<p�O0e���P�$�B(����!��>f��*�WQbj�R`���r���P��.�e�
�j��#�jo�4��r�*���`L������������( U���,)�y��K��W���A����O#�����c�T)}{�����l#�T?��������k�^F�
F�Ufq��w*a��E����>�N��CE}:R��y�h�����b�d�?�
Tl��){�]	@$��6�f�U��oDt�����@�)e�M�>*����&B����T��Mmo��_����z�PE���	1����w�<a�4��$����(�3K6(D7I��| _E�<�do���L���P� z�o������k�")~�u��	��f�x�J���'('3���Rq�J����s|'��@�'����V6����Te���-���W0���&�mCI���A[�<
�
�l�d��n�`��=��E�:{������w�\��)�z3��\����x����Mz���W�I,��4(�`�m��"�H\�	U �&��)�����o�P�4�lI
.����hTT'����M`���Jt2
B}$yP��~�Z*v�H=�S~+Tj�4Nn=a�\Z�����-�KEJ��Is���I��l	�����q���'��Jb��}���fd�2.:o���������ig�g<�Q�2hCC���#7J������2D�c����
�?��m�v?��J�4X�L5�0����������hF�y2������|_���4��M��J��UB��J�|����e<��X����:ZR���i�ha��x���i�9�6������x����������%\�A�-������\#���'�k������Ka�%+�.$�S�W�����8��H��N�8���^���	�1�X�X<q��]5�R����93[^~�H���3yr�,ZdVx��4������8�f5�V�z�=$L]u����JR��}�����>�o���%2����K����V8�1��Hg�:2o]dJc���K�=�[[}�8�Q����d�
%a[w�����T�C�U��G�t����3�w���~O<�_9E~�����G�9B���-���W����q����?��z�7e��[hXm�����$��On���Q��-�}R\��Xw3?������	�6�T�[���F�����Ut��q���{!������b�}�!���8�������3S���7<)�%P�
cb��6���U�4��o�w� 1A������(kzK�B��3��>S���02o��@����S�����E�}��pVV�b�����r[���_�������������{ u��l`��8��}y��g���
 ,�	
y�#
�-O�)����I���I�*��C�Q�7���t�k@f�X'�|���/~W.�Az�5�f�FoZl�������%AK��������ZD�U��� ��?G�l�����"�,D�����T����[���j�&�=Gz -M*��K/Um
3�kf�(�Sh�0���r&����������r�8T��������=���lMi��B2�15O1�fD�V���z�UbJ���=�>�)J�r�b������WH��K�
x���qKx�o��`���p�q�y���4L��
��o�@��03Z�
������
�I��C�-�����������v�52�*!nP�y'�A*����"�x�n<��[/����"��`V������(P��Y�����x
�R�%�����B@p���*0N�_���'	��o�
���nb��}z����2h�b)�D�t���7x���G$�2�A5R6�I��K8�/�&a��$����t/��
(
9�5����p�k{Se�G)��!
�����k52
�{�x�2�B���r��L-�<���1rq�w��p@
dS�*���[8��-��3�i��A=Q0#�� #�U?����v�l9E�doU�|�c�2�jjZdlB�L��+Q`��4�I1�n��<	p79�v�$LG������Xew��)B1x��H�K�P����Z����xfIPE�x$�H�������uF�������V��t�3�|�}p��a��A��U+5�|��Gj��y�5)�
�`��rw��$�'c{��-g)>W1��{�o���\�`����dy��J��B�<�?{���1J�~�t���)c��t����Z��������#% :T�=v�"R���43\7�tev����|2��G$�)!Mn3=.uK>��*���Py!�$N<k4$�sx�}+���W`p�!r�#~7�n��
l~s\Y�{h�x[0��5�����1����������:�VUe���@��8o����@�����%��g��:����~L���*��AG���<���D ����b���z8�����~s�<����P8�����_���)vo@`��������`���J�q�f�V�TiU�L��Y�
MX�Wa��w�"T�Z�+���:B��GMN������"��q��`�I����1U_����%d��� �Et�U�M�6>��[o��[��^���Qq�ej�QU�H�u�#r�<ZK[[o|�"�F#���	i�����

F�y?Jyk��#�xV:+Lw�0��:�F���[���%���o��{��)�P�����������u�27YbdI��y���D��������_n^7��n�re���M��
�D���3�6�����`�n�1OFb�U����T�4�Y��(�[v�Z0LE�c��-��.46����<0Q��q�*�R�
r}�\�����p�$���XM0�U-
�O��5��"�e�o8R�e�#�[*��:�'��	M_K��5P�K���F��u!J�d������t}pb��g��2Up����2XCl��E���������r b����~�R��}Q�r dV�z��B�F�No/���Il�����]�f���d��{�S��an��6J#�^E9�sDmh@�_�j@�����Y�X�\�n�H��#��O]c��T�KB�^���I���l/!�Ly�
P��h.e�c?|P��w9!:��HD�Mq����L8X���
��h-"����b���g��f��^�L,@�
Q�V<��[�=l�N���O�+�f�������J����7��7�X�����C���%��?��
������2!��	��q�����$l��rZ�k���P�K��{p������&��S�r�	5a�1��	r��A�g�	{����j�B���=�������������8���FkR����[��o<��B��?�a�\Y�4`TPo�#��,���q�L)9�lVc�C��&���a`A(
Nm�j���Eg
,�g��������>Tn����C�8H�<��!'�n�U���'_��)����8�����'`"�F-QN�x��Bu��A�g&6&�L
��-�=�o�^|R�2�����r	��|3��+������K��P�b�K��^}��N�����G�M������E�F{�����0)�;�O�j�i����V���1����n���1]�0d���S�7[c�������6�A73���!�����Q,;�������KW����u����S��6���g��^\P�!��Z�EE�����Yu5�����L/y�h����z�j����a�ZO"#/0��Vl0�E�YV�����e|�K��?W|�w�
��i�����r�c���5m���.���^������gS���3�P}�����������v����,n�,2��\*#J������tl(��G�E����:el+��<fNh�d{���r��R��\}$�������;����]�GF���V.�y�Ax���Ah�+�u'_I*D4W�WfT��Y�VJ^j����#�4v�o{U��K$*��������8�4d��!�2k#hL5"Z�
y�x7?8�C$=b��s�t��UZ�WFG{���_�n�~�I����/���������]��P"V�����QcR�$�5�P[u6�����
'�������_�!M�����r�KwOH��!�Uq�-����Bq^���"[�G���	� ��p��P�|S�4~��*���/~��B6`$M0�y>����GK�G�K��2��c��t��0��O*_\
��xUt?���rA�;J�B����s��m��#�cE���\�u��i��!��j��z@v���8@��G(��8I����-(P�.+�����p�`$L[!�?5�����S�io�"'VP�=CN
���'�?��&1�Gm�Z=r����n��Y��G2* ]B��2B�l&��_��f���S�$g-�����4���!���@Vg0����MS�//�������o����w���$u'L�8t�3�'����)��y������8:��nUQ��������6Z��|N�����`�Eh�hg�1r�1HQ}N�*9�e��,l�*%��2d����g�%������@���p}���bf��{G)�&�)aa�6ZH@��� �P��}��G�����&�78�EJ��NJ��$�!I��	OJ�a�/�p�C��	����R�k��:%�Zs<��
�T���p�9����*[C��X�&�K��=J8+)��65 �G����g�=��f+@e}��ud�cr�P��n�>�����w�9������{P��4�0;���7g�ic{YGNVG��k��7e��������B�"��3k���2��;;8�Lo�WF|Q�:�C:�y��S%������c��[��S�_|Q�y�}\��x,�\<���-��<���>Bm�6�0s�>��$���h.{������F���b�Y:��������3����>��8!�d������P"����?���'��S��{�����mEU���o���1/�7O����J������
0�O<U���*�3Aze%qu{T�>�D�R�/�CQ�	��s���O�_�v#�K�o��@#�4w�rsP�V���"�p��A���`�F�"���������`w�(��Z,`<|�n�'����D��'��|��i���d�a��SwA�����`����7w43�������E�����,����[R�=Y�#�#:���W���|�i
����F�����7}��JweK9 =,�W��0����K��J�
e�h��[��"������6V��-P����[*o�/O�������L�K��@X�����M�uym�Ut4�O�����Tn��L@�b���Q%�
����-��3�bJ�B���1��s���)H�e�q]w��<k��9W[2*t>9o���G���B� 0��~��4#�/�{x�����E�c������yhQ,
	���Ic���?l�_�r!D�	��$����JU�9i�	�BL�e��6�f�1����
�y��)<�Q��>�����q�����>
����5@���3�&<��u�^V%V������9����pT}>����920�8a����hc��E�����u*������1*zL������zP����X��P^%�&���@Ey��w��jy�}v��y��2�����:��f\���yp��N8M��y>����H�*A�	�A����e����9|J���'�b��dx��2��RY.%����������-����E���c:b��co���j���}��x������v�leS��=�u����������x�E�e����;w�E���r�t��9b��2�m�0�����Id��t�5sn��=h���M���Q�^�����tp��l?�w=��a{c�����'����8c��r?�s�����x�Nw����� )�!�|���o�n����Zm�\�qd���b2����}������;���Q��Xj�e0s��B�kU�$-�����}�E5����W,�H�{@\�7��x���1K�W�"��|dE������6���
���5�6GO����~iRr�������_�Xi�Of&�G�J�������_	����w=6-��%(�m�F����aj�iD��=�SGaVm����-i�;��J�-����>�����������O&dA���$��"{0��Z�
��_�(�JrI/�\`��I��5����m���l}��n��\`�OjY�Xr(>r�`)���2nF�|A��K���mX�H�Hx*�0:z��]s�jK3���Ya)
H�
�)o����n+
��+2��~�b���	����P�L|U=
,���������,I���$o��[��	���'*�u:"�PE���9�_�.9uQ�qx�c��m���Yix���G�?R�5���<t9Zd��8y*n�b(�����>�^�JiJ��P,8�U0R^�!������220�w�N)�O��j���7��"��.���v��z��(��zk(�����mFh�o�U$)��db�g����Y-?�N�j�����A�;�J��}I����M9��`
ku(�=��`i��!_B�kq�
0��Q��'�s��IU�"yM(��:�k(�T�n(X�(O��`�v�V
�^������
�E~~*�(������@ba�J�.=v,�d�+SGI���$�031K������M{{�������w��E��
����K����������<������5~���H����>V��M�� 9�����,w�����1��=������syo[\�z�����^��w�w�u_�E����}Y�;��i���g��(%78F�<)���[S�$K������R,� �����a�)��q�~�}R�X�@��B^F�Yt�%Y�\�z��B3��
7�l�C��C���������(��`Q�$����]x!
��c�C����[G��n���;��R����6�L��7+�[	��I�w��r�)���a,V��6�M�74�4��������Q�oC���[#�A���d9E�KS���fF�� Q�
+o���3e���eJ_����	X���)������>��h	����Z'ha�4��N���NR'����w��{%����l����2��!����
z`����,�9�������=����2c[����h�_��?��&+8�f��F�>�jZ W����W������w��4����*	+��s��� ���8u��4|�,ya����Z���J���<K�7���sY$N�?F����{�x��UL)<H�(������rO��%j�k���-\���N+�W���nI22[98_E������\����� F�7�7<���9���`���,dM�hC`����G�h���AM\��\U�2:����{�<�����3�����p��x
N8��@'Iq?�����3}���+H������������<�	�	i��]W=����Y%�j�ClP1�����":��m�}jh*y�9�F�*g�Z,�����k�!����&b�C[	%����5��6�Xk����6������6����]����=��xd~��K+�@�.��Ct�1>���Q#��^����k��9�g��{g��l���#�������4�]�`X��}����������o ���,���$�y����9�/95������O����nWp�$�C����H�J�to�H��7@��W���MDF��z����O?]�`d�1�_���$n��*�����n����w�H|�REO�4:MF'+����-F
��0.1�f�u{����d��VG��Hq������j:8F�N�{[����D�uQ2����������
�~�������k#eh�l��za��t�~ �-#j5r9.,,����v�T��2�ut�
�y��?���p3��*�	u��Hp�*U�Q�n��B���29��]��q>�
�^���f��C�d���**������/�H=�$i�,�eyo=��\R����y#p��C���r���
�x�d��
��K���j
�����m�o�[��!-���V�;i`�VJ��K IDAT���\!����]x�4g"�L�<"����M�f�h�]�7�+����)����h�]���Lqg�^K6����B|K��@o���.�L����Q�I���?k�'����ie�6s�MJ�)���/C*�)#{��T�c7����k����+1�>
[��`��j��h	��$1�fFE�kZ��F���0�����C��Re���o�Q4�<x2[R�������i/��{�B������-�%�mr����p�gv�;�{��|'G�|4�Q��Wm�w�����k�>��g��������4b\7�])�BN/�}>���EG��9���Y+������z�c���
��	����P�<�b�-�z��Ab��W���p���K^�<
W��_�z�H\ 8��(BLP��GT�4��n���W��N"�<+-��SK�0/0��JwFc��{�$�(���/�tR�l����w����BGa�*pc��/)bG�/������j4�Y6��_qE�Eg��2��Y�wk��J|�t�JQ/��[[���7���X���FZ��EK������O����c~s�s���|T�i\"���D`{@��FQ3w�c���@(�2J�B
$/=�^�r�l�l#��e{y,�w��5WR�P\�1�@-�TW�(#i������=�����<1��H~��b���D����������#-q�#��_a�m�u*��������A
��sf�	�=/?y�c���!o6���� �4^�0�6���(xV��8���`�����)*�Y���
�����"���o�3����F!y����:�q-K�NV��%`��n�]�!�*��D�����_*�"g��t;4�O���J=�|Y"�n���Y��C�����y1�ij���>���k���lt�BV!�������������oo\�����w�s�������oq3�k�#~�F��9��4�E|�����y�.���������s\�#�<�g��5H�&�n�2=R�.��2����t����+�R�4�/6sW�c� o����6��+��]�^*���������9�-'�{��T�f�3PG�������9�I�U/(c^���~�#�S4�o�-[Ps�|_�H�X�,I0��<oC��+�.{�;�0���lJ�8����%�}'���c����4wZqr��Y�>-��%�-K�H��\�g����5�'
[�������+?�T	R�r�8�T�d����IL����-VQ��Ht`�gR��L)����S��%1K��
�s!���$h�hU �
���Y�
��nX��c��Ap���������0�[���5�%��J���'M�A('@`���o|�'gV���I.c�}V��0C�i���Az?��i�T����s���t�������H%�=����H@1T�Q�����z\J���|�j[�V=y�t�^�P�-���]i���G�����/�)���<����C��2g�����y@�	��*���N�O���8���
������������2?�n�J�kC����0�,Jdwc�R��xD"���
K2������0eJ�*���[���=9����������-�|,�����u�=�/8/�����	�����{d�F�)�(�7�o>����@�<�QRp2��hbQ��&9{�q{����Y������s��G�g��v��.�y�@������{`�5�/��C��l�A�����+NFg���G�zM�fmdt��zN|�I�bu��3��r#3�%i�c���y��������U���948��6�"�2>)_.(y"�����Dg	xO��47>Y1��Y#�lxBEn�32�N���Y�B��M?&�/[8����a����������4��w62O�l��jy�w����)\�C)^���b��A��?KdOm4xm��k0�L��kN��+g���&���]����7:p��kfy��@������J\��u�*KC>n:��K`-�}����
�*����/�;���;��d8Q�>����/|l�\V�:����5��I��s��b���Y�N_s��Xy1�ny��3�l���SU�,�1B��"/|1Q9@z.r23d���pB�$3��0�yL��T����Z�'�j�L�����(����4y�b��A��;j�`)�CM�|�v���W���,�!�����7�����p�;�p	c���[n���i.���E~������hsk�7_����,[�n5��^�R�%vXO�2��O��9����v���oh�}�����uHt�)&g��j���<8�>�����~��aA��/4\	�D, YF�X����Qg�}�a.�p����`�����	9��S��[}�D�����T�	�q~�I�g����ri�$0DSm�Yq����eUN��y�T�����K��o|�$�����:E�^.����*��?���dra�L 0/b�a�J�%��������2�:}��m������-2��d�5��9b�R��7�[<�wi���3��=�!����m������
���m����L��#���H�~���0���;�j���Cu`MCg|����jc�&uIj����V��?�P�"���[������������7���(�5�r�%���O����6�lT�u���M���^Y��X���0��R�
F�i���?���������w$�c���/���V�^,��i�}{����-��X"�����z����%��]�����(#e�
���G��%���� ��r�������k�<gTd�����5���L����C�z�����!�ohl@
������{�+��@�������p�6J�@�x��a����BGk�<����T>���=w��@@8 ��
k����)M�3�Z���o��<Y_�"�U���r(3E���:�����g����*��7f���Mr������Re[u�b��C��r{��V�GQ�1������~���9I)�2�{����f�1�b��<�/O>Y����)��"������i�oX�\���"�)T
�������>�N�e��
r�����Ao\c>��T�Kt�(�EP��F�9����='n�t,�M���-�v����Hmm�*��C��vk�E�n�Z��y���L��������e�����=OE�#k�Y�H���
4-��Ee�:�P���<�l�{�+2��u�C�eo{���9�R�mT�Cr������Z���r��R�����Z1.�����}�)\�G��A�� }_}���.���+��.Y�������u1���'���~Hw��X�������t�Qz4�#��
��+�q4���g�N�3}e�����)L<�����\�Mq��|IO����B����p��gAL�[K�0�������H� �7i�������VA����Xsn�4b��[�h#
&���X7Ub[ra�#�)���J<�j�4���9��0:&�_}���m=(A��w���S��<��r-x�R���(�\6����6�>���N;m'�3�'�/,\�"w������B4����x�v�,<:�a��G�H�u�eI@��G���'��������Fg��|��{�@f���=�_o�=��Z�:��1��*yqy�l��t
���/�T���H'��5z>���A����F����*C$�ro����HR�0)�����7)C�J��<�_91�'�{����|�M��a`�����i
�R�YBj#��.[�|�^2L�u*jG���I;t��-O�U�1�6����	�2�l)������O��x\ye�W�lN-������o+�u;��Q�S�������q3lf2*
*����X����f����1Y��J}od(�Z�UyK}a��4���As$t�@�e�:��~�;����7?5^�O����������ITK�L��^9���a�����2TB�BM
PB�9x�8%��Q�AG�q���	hP��H����l�ru
9��+8�}����-|g(a�f���������(�H�;�����V��H~\G�Y����nok��i�q��x����n�O(C���A'J�?�a��h33>��|������RU�,7M*����K>���-=���>���@A ���su�h,�8$d�I�1�0��AV��+'�����G�_pdow��h�����o�}}�����`��u�������K��!m��R���{9�'��K���,��c!����l/�{��bt�[��u{��ly�MyE�$B������PsB����YV��p���d��ePT�|#T|�i�Gz����32w!�? �������H���"Y�5p�I�~��*�:??7��������rb����OjCojknhg�dK���U��>��T�$t�'�?�Z�f��F��VFG�-`��Vd��9k�[���\��&2O���+�7������c�a|�������Jt*�gl�V]����-J���&g�xR|������C�E��Y�r��Y�Q���7M�����e��H���]�_t�����x0�������!\����>i�>
��ud��J��V`����^X�f��x�E�E�7_�wc���
K���{9���'gp��z��h[���Z\]���������\t�g}_���tw���yv�����Y��S��w�������������+���0��r&��

�����n���2f�9�6��]��.��\�5����w�r��}���1J<Fc���N�GH?_��L��g[���_7�b���r�1���\�ft��W�)�5����9�!8)fq[Bb��*{�1��?��^���}���k��[Y�'��$���
�!����>W;a��s�[3�&|�0�=����q><P�z*Q��hP���0�}��9G���mG�)��&�y���\���_91�H*
*T��2G����,@�G��5X����
� 7����Q
+dF���:�o��f��9������F��3�yF�Y�p���NC��n&E�z���~�l��<{������kU=DH�k�
QB��@_qE�����^�h�B��:����!���T�v�����
��f��L��yC�Q�^�.d����?��<t�}_�,�Z$�C�d��aj^�����.�y�aj�3�556���a�'W�Q�O�/���P�v7I8�����QJg�z��4��u�3�k���c�\{�xG�]�>��_W<��=~�����������[?�F��,>]������=�1U���1�EJEF�B{���xjC����!��1r�������~H��=�j������6F4u%G<aB������F�f��|�4��`���1�]�+��6>�������a���A7^dy��p�t;���7N.^aQi��e��_�M�����qS��P���W��)�\!K=���5�26!_�D/���ZY�C�<_~���h|~�N4�5v?)�C����r8��5������n��^^Gg���J��8L�+��Q��,9���~o����+����
�3���� ������4Z2:�{{A#M9������y��]{m�bC�a,����3����W%��AP���l��c�o����������JQ:�:I��]��:C{�u���c�]56���t����u&���=;z�qc��=��uGk���G��.v�����G����y��/}�(Z6��E�&�<]���a4�m�)�w��g�*a[*�����H��w%05I�sr$3:��)B�����?*��h�0�^��/Xh�#���2�b��~���G%Q�R���\x��7�De�h����8�mu�>����	���o��?��B��.�*����N�r�?����������9	�Cz�HvS���jcdd�=\'��������kTMk\5��9o�9��{<���x�a����BiO�V��W��R7UCa�j�����������~��Xu'����q�����\��D��I�o�z�)��#'O�{H���e8^t$�5G��h9�G+X���:�����qc��z��}��d�������.�M=�h/�6�.o��������
�~�_(A{���7P�X���c�M�+��[o��>���������O;��6�t�B��9���g���9+�� ��(	1�RDL;+�N�oX�|�
�v������M�>p���(�V�3C��]"
�&v��������d�v��V����P+}����)�u�hU���'f�t{��{{������R
�!��63��.o�a�K�=�����!!��C%���-T��@qk���W2e���}�{����;�����c�etb�a�k�I�^�EF�����vk^���:sN{F��ksw�)#�a�D>�s�h�CW�	����|gz��k��d�}{J_���G���?8(G*v��S&>��]Mr�����dw�T:C��L������gi��b1.�O��������d���S[F�>��^7��MT/����0�F��������������A���~�{�A��������Z��i���iio}p������85Rk�M�i3z`����vG6Q^c��d��Yz��86�F�w����BsAg@���`E��b���hE;������F�ldm�udl�����2�������x?�'Y���2|J�v��^����t[�9��y��{w��`��t��x�X���$;�^���Pd���d~��:n�������=����#�#��WM�8O������9��_3Ff7�]y�K8]E�4���z
���[���b��FK���T�9gGN�-����3�(!1?��E�bz�;�"-���U��y��OX�4��oO!�Zf^��}����iL�*���Gy{��c��x��v����3
��r�iA��=mr�;;���3���X�_�0�Nz�s�R���-g�����5���n��������Wq�����zg�
ab�'ib���a�j�h�������!k�5^z)�b�wt�td�o�����@-����Ru5~[F���I��^V~�n�8?x�~���z^8�v�
e�h_u�u|�o���X�|��.�wg�������m�qc��=x���=��0I6c���2��a���5�����������b|�u�����Y8����0�n}/��C�{�Z�
�Q5��wu�(i����J�D��5/�3��v<����&?y��/2���B|�e�JD$�A-gf��8�!'�?�������� ��_G?���BQ����-q�9���)/"���L,}��:
�p4�t��=!���P�Y�B!4��#�M�W9���^[��x��+E��G��]9�	w9�_E��E��0���U�M�u�
�0�mb���I���
�mi=X��^ ����TG;}��R:�K��Qu���gw����+���4h���6������]�~�����f�,[�#F���6GAc���#���
�)�1^�Z��������}����|e1��A�.�ug�������]����|W���{����5}��5>����l2l���\���
���.�Z�����`+�NK�>���]������B[F�u���ud�h����S������w��T���M:������En*.��i��T�� �s�!/O@��c�$�����6h���1yr�s�Iw�Y�����!q[�'��J��%2Q�<�em��R|�l���	9i�qo�	�A_�)���:���IH#��g���R�2��,���wTd��/Uv�R�l��R����	
�g�)�����a�����g�3F��.���L"o��aP�Q@������+!��,#�s��u�K�:8��(�}�*&����G��s����9���pvl;��k���]����|W���{�n{���g��.+�"y�
v���}^G�h9��sH;HV����q�\yz�����n�Ht%�l]h{�5���������*�S�����+�Nx��w��l}�CW�G�5F!����S�4:�1���AW���������+���OJ��-*����%�����Ud~���dX&����;5U��}��w����>J�Y
���Jt���'5��Px��s���O��&W#�������w�'����Z��u+��n�>�����O��������Krs�ZH��u�QV���W������q4�2g�hg���7������w��B��V�E� IDATO?�`����Gw�������3w_x�4����d7��W\t�,��QH����
�NH��m�x:�����/WW��j������p�:���:0����y��L:���L_������+>�����{����-��S3%��7eB�7�����z������8%�}SL��i��`L�G���e|>���_K��O$,!Dj1'�.��a�D��x���H8�c��r������{��N�|{P���A?�0)�I	�L9��%�.J�����+���$t����XW;�������v�;:��]����|W���{Xz���8uD���o�L���s��&o��t�����<�`YY�0�CS�4�5�6n�?V�*��QV{����o����7*M�S��3�����0E�5I����4��m&:C���WD�$�R�u�����^�m{������c��Y��������R���~�~��v���"
�>���
�X�j���g����xh[s�h�G*����:��;�c������wO7����dd�k����X��n�o�����={~e����w�?���~�G4����x�8w��� 
�����>���h��F���&^�5����Zhl��b���5���1�r�\�T���V�������m*\����������_{��}7���F�@�����#c��\��#E�g
)��o�H-j��1�ap�Z�����������vZ;��
/��S�}�����1{5/?g�9R�\g��k;���8��Fu���k%`�(���c�1���Ug��Uc��vt��������_��:�����"S����O4Y<��=���������yG��4R�^�V��&���ba*�z,��oK������])Bn�?��$���~4P��&&Z�kal�����k�p!�6;c:����g������a��Y�����[��c�H;��8rl���=*|�)��$��N�,�����i����[.5��dG����h_{����������<�G{�u������1���
]�Yc�h.N�!����������v�]�����N��b����wM��VA>�_�Tr���F���1yJA���=�[8���������]�zQ&�������4��J]z���OY:��tfl���;w���qf�}�2���(�������7����X�����������*v�������L�#�}3gJ�+�`�������o�m���z��j�t��;3gl�s$�DG���:g��h�q��������z�����6��G���g���p�<n���������
��	Gkqrf�;3x������U�3���s��v�bB
�������`A�A�����{��yl�� ��
c�Aq}3roO��V2�c�|�Xi�>�s������x��Z��q~%�~�D�J�����#�e�;���T,-�����U�ob��a�;�@��E���|2F�M
-Rr���0�|Eg�����m��Q���L�"�%�Lx��I���Kt������Q��Wp0W�x��7y��8w8olq����9��5X���� ��/��G/�8{�����u�?����o�V������X�@*�����k=�3&S�l�Z+�\z���qc��>�M�m1��TI�y{7�j't�ff}��Z�������>�I�@
;���g)x%�U@C3�
9����QF�x��8��f��U�=:�����=��%�%���A��
Sx{�����Q�<�q�������l�L�1)%��+�Fem��	�.(� ���������1��f��:��w#D������������XoR�c����Z�a�������E1��Qw�d����{�s:o��	{n����6�='n(v���w)���>��a~��
|���������]?g�`�~���'�E>R0�6�R�hS}�h����Q���o�X������U�����.<w��?m0g��e��*E�F=��2�y��?F�XhFG#S�B���
���;{����#�ZQS�r�r��o�*�n� �i�|�d��M�T�0��P��u�7�BG���������@yM��(�M��_����U�k9KN(�B����	�����g� �6��S,�~-}�>3�����O��W��������w1>�@����$#��$wD���Q��e����[�S�5:<�JUV6w��a�@d�BGib�+�u4���<��������'��,<������w��pf
6j'T�Z%��G���~�y�r�S� ��l�3�����p4���^�����h��������I]"���6��m���-|pP��|����������g����~���h��3��o}L�����TF�3����HHA�XZ!e���W�"(A���?�[P��"���}s���yO�D�/[b���+#,m���T���4��+���;F(���p��1�y[�����V�$��NgLU��^W�\?��.�UY�Q� 1�����`d]���(1�;iC�37l�4��H���*�B%��J��2��>))v��\�{W�����*o��1R�r��V��NW�c�Lp��W�7��{s�_?�Jz���S$W�g�`[:����*M�i�X^���m�������2\9�}���P���R�3�[�������3k�+m<~n�{�Q���1��>�M���]���8���
�;��h���:�\(+R������:i���F����"^�M�'W*x���5��=f���M��,��
G=�]2�i��%PoHdP�D\p���b�<��H%T�
�{0g�'7��s��i��/[V����"RW��#����t�U��!RV�$��^'�zI�>����06l���m�NB���a]qjl}Ol32�����IU\}����>0� �8n@�D7���b�*�"Q��P��./D%����&�����KTA@@6A�m�uvf��_����������=���>�H��[�����:u���"���Rb������3O��m�PB���/���<O��������9n�6c�x���A�������9���N�_�=z7?^)w�~��4aQ��X�����5_s��|��	?�	�%`�z��� ���u�+�������[oQ��3�n0��5]'�����b�+�i_bI�}���~��]b����ZSB�M���Q�?g��2�<*;0��m��'������2�*v:��������@�6��s����u9�m�V��~��d4%���}N]w,���m;���+h{�K���J�75mO�<�V+����If�XG|�������^E;��@]/�).V����A�?��A���*��>�&��_.��p�
��y�{����v����A�����3u��:u���z�1u�z��#r�~Z��!A�k}/t��e"����+ni�pS�[?f���(���t���-�|t�Z���w%�N�;F����?����YWTx/R�fae���
*�g��Z��d�����Y�9B�n[s�v����s��Z�A3�����]�O���_��1F��$��X��N����bR��������)���(����i��>�Y��q��(:����[YY-���;Pg�.z�X%�f(��>0��3_��~���^��q��"�T���S^�/�����9C"�.��=~��FN �?@n���n=�N=��;o�^����-�D���o���1�4��:5��T�~=U�t���lj6aR���Nv[�%�$e:)%j!��#=aB�O���wq{��gs���e�g���6F�)��c*k��R;�������6.���M	�<�buK9@?�����=i���t���C�r
�����:�3f��������e
���]\V1�U(PD��I��3�s��pw�[o���K����,]��G;[�;VU"Kr��	Y�}}�#��g��@���emp�g��{�����7&�"&qteCu�;�Ez��#��#����~���&u���4����^Y\L5"�k����������?+��/�q1b��[E��I����8��YT"b���v�m���.��U�1?-^��"K������j%\�|X���-�s�M�$��+�����
b"������?�$���O�!�H+��O���ne5�^x
�n��8����s�3�+a��a�)m��T����_��]�� 0��#?����hL��ch��u^N�f�=����������69}N0���H2k�?q�q&�;8X��+����@�������m�2��3��;_>��2�c�i�{����=(1'G�Z\�.=FQ��u�����ZL�1Q�Q���y�eL��S�������l��p������S������V��D��!^x`���iQ�U���Z�I����u�In
���+��>���!����Yrga�ps2�{���R����_�����>���]V�����7�n}��B���8���u��_�p6�8a���G���{,�&&����d��&���o^'9���$��i�Zr����F���EY=:x�t��`ya��e��cG���!�����QQp�Z�����Yx3-������E��|U�E��Q��3O�=7��G=93���K��O�
a2>�$�&$P����d�`j���7!����u�9,s������c��I�O0��Q|���b��:	��_-�<���0^��$J�\�vx����iVc��#,��g�
�������>���},��a���L �	8�{:����|N�o�Rv���]P���[�����m��!\������_Rz�"d[�r/2�u����Y�t���2����>�G�������ie������F^��]h����U��?{��
`�2s���T]*\w��{�8K�q����������88<q���/�8|
am'k-�a��P����HM�?�4����Wd"#Opr#z��q��/�vt�l,c�9�����e�.q.,�y0&��	��~+��$�7�����k�r��v���/J��ZE�K�PlJ
��YC��ZQ�p#A&[3�"����%�J�g�-#��r���d2���C�il����6�\���h(^�~%}���_W�@�D�R\��n�t�w��~�5Uc$��IbG%Ad`�?^�Q��b7o�o'�$���g����gu��{VS�Q7�;�a������x����;~��p����9���->��}��lU|q�.X$����`1�3�	0�FM���0pOmd�����:�?+�.:�t�t�GW	���+���q�1���u�.VI����O��*3����nO��vX�z��������������?�����>����������I�)��U$�DY��[E��_���Q�N~��f�F�T����O���g�T������M���Y�#�7��
��2�&�|6g
�i����&Q��&��d�3��2;{a�u)\�TfG��C�O?�=���{��\	u}v/��`4��x���C��<�&�=�?�����V������v4xT��O��R�^M��<�ysJ���g����?�o����]����F����V_��Mdm�^F�w��U�R��)��{G��i����	�\������"?�R��>�o�������T�,�J��IA�����}���9\�R�;����;�Y��E����2�s7�����Ls��c^^!-ZtR��d��&���Tq5k��v*�+]����`�H�|��bU���3��~�R���,����[��q`1�8��{���	��)>�s@�fW�>�"�`B|��=�R\m����l�={&kW�-f�A�������)�����3����=g��~q�2���y���rS���7
�R�f�6�;\��X(M��_x�����&�^N��{g���~G����c��@bWi�F������}������D���tz�Z����������d�Yu�L����3�U��G���!�K2e��b�s���u%�����;���g������v�n�C��aN�������;�1v<��jG����4���r�rL�-,��"��0&V�ER��B���S����b����hM[��9@��z+�5�Z�}����DC0E#��U�E�����a-<0e�2nS[����G��[�� �jR�n<����~���S�(@+VS�V�BT���KX�|�����+�9��7[�QT~��
���Oii������+VQy�8�+�4���P���A��uK�?<�����P��3��$�*>��4?S~��`�l�����T��O����'�q����j����gd���-�4lX3�<��I��J1&%%U�I�;���\����q��A^_.Wv��v�n��h1���
�!����������y�a�,������4	�������,F����4h�l!FE�c'���+i��!>3�>=v	U��%&�Ruu�p�x�FL�
�hv)Q�>3
��~��B���m���I7���jJN����j]O�&����^������R���U�6�iiT-Y�5����������)��t	�+*��_���P�F�)a+?����=�RLz/<�� �`�x����V�.��j�>�=.�Q��ox{G�U����Y���mg_J2N,N���M��f���i���#��&&R�,	Ym�J�,����5%�m�p9��c��s���M�u�q��
:�{�����B�{��C0���jn��w���>�W������4��~���5;wN"��vY��
�Y��P��=������@v��0�\��y-L\�	0�H#`-�~A���'%�	Q~����Q'V�w�p����D��n�6���dz�5���(�!�rr�5[Y��gM��Kq�2�fM1�8Q-Dd�~j=��Z� ��G�.1�-~M��O$����������CV�������R�J������d�J��:�t�=�S��-�`�K��0x3�%���!�k�l ���4����i�����Ld�-�?�bW�F������R#�e�o�8E;�P�E����?�f�����shO�K�!b�B_�y�w��#2�.M=dS-H�W���G�������#���b������hGh���Bt�S�:�RU�v����e�*:�9���N��Ur>��	�fQ�t*��l��������#G���c[������j�C�J�����C��|p�r�L�	��5�����������������ol�J�zu�t��W��_;X�y%|�����e2�� .9�~(��a��m����x|���Y�kt	���F��7�T�b��b�����P������!'��+��E�����g�W��2���g)~�fSa3_~�0�����{O�!A!�w�g
���w�j�����G�x���#��u�w��qtZ,pN����.��^;�����S����0�����k�9�`����� /��SO�g�`����:�j������Az�/����mhOl'���]��,"��7������R��/�.��}��. ���G%��f�7eJ[-���<�xx���C}ei��l�d�}��B��������v�� �v>\)�y<
='�nRD����k�������Z\����c�v[�>gX�;��w1&A��	���_OI=zPbN�e�!���CF\��
�_~��V��B����me�qc���C�L��-�(�G`U���S��S��F\+7#b�A=/�\ ��O��_���_���1����M#yX��.0t��v9�
>��7�IQm�C��L����������U�({��T����NeM��DBk*�n}R��s�Y�~Xi��t%S��2o�;�J���v��������[U�y����v�S������IW�+1�)++N� �v�I��a����3���q�s�[�Q����,N�TE�3�������j	Vmu�Z���[�������WVV�1���t��9�I���O:ym�������K������Z'Ht��V����`1���	0�FO����}M�����1�
���E���Z�Z�m|�S>��X*�j����V���+�������m��H',���+�|0���W-��)x��S(5��j�NQqRs�;K�r�R������c���-�}���d�������m��2aa�����\|����n+:��Zp#~�Hr���u0����'8;r�H�\aak2��""��!r}uc��r	�|g&�� IDAT����:.K��SAA
N��zo�'�8�����<�H���U��p�1�����:��~Dk�,��u���L �8���	�g�ry���X��H��;���H��+�tr$�}
���(��K�!6�Ej=a��AY������O�Y���U���'���v���ZXI	���$;�Z��MK���������r�{N��������;I��'������v7cm�T"C����I�[U��c������q�}-��F��l���>�z�]�,��WK7���8��6~|�.������O>)�<}���>S�}=,���*�����2ol��o�j����(�M��Ts���A7��/�V7��hq�/`aI����G��jDs�����=N;��v��T%b��
�f\V%�q�e<z���J��G�����*��/+����U^�H+������O����^��]�R�-��L8Y4�YL���������:�N��_Xxf��5������N�GN��Ac(���z�?|����[��}��H�%B�n�V{��2o����/S��3(�I%TSvb^�d��	�D�������e����	tx�I:<�f�����,�5���	��f0�)u������v2&��	`�}���o��s�q
b��������Tu�%�|��gkY�u�if�DlyDu�����U����R�v��,�F���n]	�w^�c��N{u�(W�x�@���Jq��u���1RK���<���E�P��x����Z��,�� o�*�"�"�,����E��(�zo}�.��
QZ:����M�z�h:�:�u�(�������m�{�L�r��R�w���z=���C�j��X�u��,�
tHx�;�z�T���bq����%��6�\�G�et{v�m��v^
�N�g���Q�61&����������}��t�&J������kA�W��s�G_<55N����7�:vL2��*!�A��G�H3W;�	��:�
���Y�J���\^y�@F::y�"14hPf�o%���������GX��������o+<X�Y�Q"+!�J�f�R���L���{�;J�!N����E��R���G�����n cftY��P&�=��-?�/���I�f�9����S����z��#��W_G�����*qf�C��v������v���p�;��pn`L�&G<�_?���Jl�G$u���R��L���e�)W��kK��sS�%�A�����3�m�u
�A����x)R�]+|� ���G�����h�����a���K���a1����E\���<EA�{".o������C�8�������s*��w"3oQ�����6����"�l�Hh$�f��l\�K��'vTD�Vq������Y/T����u�j��3����9�m9G�+8f����X.�i5G00�?�yz��y���0g��c���6�����Ru�Vv�y����|0�r�L�	0�P�J�O����
�I�Z�����f���W�Z�c��_�a�<,���+]�����yl0B��;��D������{���<��G�h!��d{a�G&`qd����?�c�W>����XH�RBYf��t�X���%V~X��2�z�<������NPJJ����?D|�XpT��c������C�3�����=u:���BF^
!hu��)���8�������z�Y�-�����n�+�j.?�	0&t�#����H�JU��� ��g�o���X�X�������?��*��%�x�'�W/*��E�	W�f�����p2(N��K�5~�����7O�c�W��q\H.�X[��9s�)/�������+++����R�M�L�M��Z����{�3 �#�|���XHQ
���Gm,t����L�[����a�dl|3��/���3��9�z�����6�s����n��^8,�����A�v����0	E�P6���S]S#.��[��F�����`�F������E�=�X���Q2|�-�c��Z�����2�(b��B_&)K�q������="�x�p�I��>��P���U�KqH�[�z��7�<*WJ��]w�?��>Y�<�;�)�z����jj����f��&2�q n�9�A��������E.���	�s�����������Px ���������b��>s��L�	�D�9�����$IQ�%�cYY�}Y��)��/W�3��(Z�\�E��R�K������5���`�U�[��*��484��+D|W��V���G��z�+���/3��@8��h�����C��2;22����\+v��]��`�������j�J������n;N�)�y'}�{X���hp[�`PCO.ZDqMj�X��[m-���5��-k���e(@�!������+��}mQm`��:5G���K��z�<��6�[�����[=W�BX�E�NJW�P���e����>������]�S�~��)X���zY�G�Hs?��*�
j�m|+!p�4�G�D���7�'���^z�J���zY]^�������0c���`v���p��y���
�E���
�<�ik�� +�n������)�\{�,��s��`A"`&�����@�%�*���������.o�uL,R��W_I��
���d|�y����"�2��s��9�2NA�F�<�������wF���3n|W#%��G�����n5v���j��L��
��U��>�S}��h_��3�c��������{��-�������S1�}-*B��4��,�r8���x�Y(�,��Uco���>�Q��@_l��XF�F��`
�F	Lt��>�Z������%"�N
5m�I�N���Y��>��8_bM}VYYC���HH�i
dD���JN��sT^|n�=��\^�v�"�<���R���>��������b�}�\cp���u����t�@0\C\l^XV���<������������;[�&Dj(`�G}�*��'�HJ���!D��e1���r��Y�8��e�eR||��W^��4�:����T�E@u��,�M���������j���o��i���p����B�_*A�0�>��4�Q�jZ0,�V
w�<X�3�J6m"������(.3�Z�uWX����������+��J�w���e>))��>;E&���K�en�T,K!�xZZ�yfJ�FZ�5��p=n��w��������L��y�mg�62�!���N����:��N{	mt�7����gV��9sd��}��F����6�O���������[����Me"�U���^IYY��W����I��� � ���|H����a3�@�Q�Z�u^g�GX�`[���XB���g�%����|��yd� ����Y�O���T"}lr2e^t�e�.�jCV�O��GT\8���@���*������^VV-��"��z��D���<����9)*"��l���Av�h��V���nWf��v�3,
��
�����G��_ �{-��j�����	4�~(�z�s�lX�g�<"����������s<�f�Yg���}�DO�P���:��hj7���E�j���X����~coY������@� ���(:��:�T�;]42|!�Nc�
1�'`u���TYY{8633VZXq0�u�J���Z��$H������U�(�_?jr����~�Z�T��+�h����m+���s���i���>��-���)�y{��4�x����!t"�."�R�m���[	�S�������K.���'����',����yT�h7�TLz�	�
��g�8a��?Q��3]��.�=`���{w9}�u�8L#�1t�����P�BI��b^��d��o_6�a��	h�B.�E�M1��(S��Zd���s��o9z4A�|�q�� $�Smz�R����M�K�P������� ����������<|�q
�!�������%�oO�{�R�[nq��1�S�$�
'������Q�XQ,�O��C��=�1��I�2�m�y]R\�	4lMj$��kn�t�� \�_~�����XXB�v���w��wR��e��N�EE�v���s��z� ���{�L�j����'��3������}H���LK��
���y��>�'����`����������i�YF����|$K��L�!7-����1�FM��0]��O����1		2,f����_\�2�������R��YYP@YC�R�y�|���gn�^�^��l�@�����t+H�B��)4}z;�%���y(��S��=)�g����P���=�vE���h�_��DvU�[�&����e��=��+���������2&��@D�uV����������-)1'�T$�y�y3����}E�w-�&����5�ii�/iC��"f}��Q������e�w������`�9�����PN�`��N������wSt�
U������/�8I))q�pu�X����v���`��o�|��P��g1&��@�h(+i ���g���)k{�E��b��)6��C����.�W��R[:���s@R}Yb�8����m����@n����<��C�Ql��3�����w�#���`L �	(��_8����C��m������|��i�<c�����9	���.]�����+1���8��hCv-�����38e��3��`L�	0
�|��X��,�f"�C2�������������
ht���1[p��
���KqM�x\�����������Tg�2�6���{3x�H����d���3�>g1i#��eL�	0&���-�|j����Vd+we��:y��B�"<e8d�U����h�
J���b�����p"t�s��I�������F����N��o���[�E��JO�sth���*W,7��,����u1&��`�	��{��|�RTTE�:%�\Y�O.Z$-��`����[��N���`Z����x�f���p�05�"�=�����?j��ukm�X*��WTT���mh����1Dj4����odL�	0&�� q6f����LZX��=jTK��y,V�*�~��L��kt�`���1�#���;/U�GN���=Z)����#�|m23�W���a1����`L�	����(##Nd�#>�(?n��.8������	�H������3_�%Y��tp�	�;
NNNeg'�f����|Cc��L�	0&���$`�c������}��[N����&O��<k�"���M�����b������/:�e�p����b��H�=L�	0&��@����7h��u���;/�Z;/������f8�1e���b1�P���L�	0&��@@���T9��:;;/�?��B�i��}�aC�(QC�"3����"J����l��0&��`L�	�uV���R��e�x?>����p���p
n`L�	0&��@8Zwy�"�[�h���@���X&��`L�*����_��UD��o�Af1����L�	0&����/�8�H05|x��r�h`|�����5x���g��{S#.�w�t�y�@r5L�	0&�"�@$Z�C)�"h(mSC9G��>�p0�8��6S����
L�	0&��@�"I�	;���r��%)�"�:n�r(w���>�������6b����
L�	0&��@4�v����E���I�2;s�-�����FcL�	0&�����Sb>�}�C)xb�C�Pa���a~&`L�	0&5����6�`�[�C��
�����l�avp�`L�	0W	��j�j�]���[�]D�U�y-L\�	0&��`L�-��q�$�y�XrML�	0&��`L �X��7?�	0&��`L�	�G ,�����i��1T^^N�
���gS\\�e/�6�=l\`L�	0&��hxNu�k`����{����GI��a���UW]E#F�`1����[��`L�	0&�\��\�����>Z�d�������s�='������a<�4A����0/�*���l�8��{����a��y(��S��=�|�B��|�NZ��X����]=�g2������5�����t`�6j��;�y�9�H8�A��
e{�p�=PqJ���C#������&;����1�1*9�q`�i��������h�����=t��[�������)�S�iu�h0����v�dV�nN�j���v�>��L7��q����~��g�=��.v�2�����{��G������l�B7�x#�]���|������}�&Q��5Ty�8�7mJ�}�P���������I������S��M�����Q�p�4:�����^O?��AE1i���z����8g2�l�@1����\O�VB��qS=�?s2�v������`��}�aC�h[�������l	z�Iu���
z�{��?Q��[�i�x��sv=n���I��F�&���w���/��&�d��7����y�#���MO��[�5j���u���fB^'t��X�m�N9�2N_:s4��w�n�m2+�g��9�m4�g��v���6���3�������h�g0Fz�
.��y�z���}�yX����v
[aU�UXXHA}�[�pZ���t��+c�yuQU=JU���X)R�83��@���Slz::t���k(�J��xJ�����M�g�p��STVVM1��T�D551T��NYB�%����*Yu�z��8�U�<E$�O�$�jR����*�O1��j(33���cM��?N'TQQ5=ZIUU5����8j�<��f�Q���tI�`X�����J�����$(���P�x���Q��Wv�$�W�������SJ�LO��"F,���C#���b��5_L�>C�����2J���4*���D����i�g3:c���37��>Xs�����"1w���a�1S_���>����b�R-����PF�bL}}�����0&4���?n:�et��]�f}�m����~�����t����g����w�z��ycw�2�n����k���v��[�_�P�k�x���O�;�n�y�f�7s��5k-X��f��/~������k�Wl���g8���}:e��q���UgP��r}t�Mn<�iv��-�����}})��_��e��N�j�>������?R�L cag>�p���I=v��)��Lc��b��c�3_i������W���	�w�kb�JX��8�Z�p����!Ch������r|�]{��A�������O���2N?�I�;��Q�_��x��:���[�_9_���,R�������	��e��:e-cu���@���|���S��z���S�_����	����Xg��N;��-����y���<��/���c�������9s�P||��xs�( �>
07�.��itC���	:�F��7�rX���p�3���������@.���<o���� �s���<o�P��{�a�����9��gL�	0&���`,�#x���L�	0&��`�M��|t�?��	0&��`L �	�������3&��`L�	D7��=�a��#G�����h����t���h7"�	�����LRWZZJ��#F�w��uaA��3f��km���'�x",���o�}�5��w�=������������>(2���e�]F�_}P��b>�x��������}�]������Y�����H6�!4h��=[d$��|�\���W�p:g@j������F4�12o�����o3�(#�d�<���"v��L^�b>������y���G����K�[����>}����������-[F��u�v��y�|uu5u���>��#OR������E��|t������6m��|\}���/�{�d�|�����/P���i���QL/:�nw��Z���������u������ic�7
�'66����i��a���`^,��I7��F�0e��������%K�H*�~���
q�.�Q>aD�����{Lf����\��3o*,�����������s�Xp��?�����o�I999�	�{m�7J����+���?*=�A���_�p�y���h��y��-[��o��k�J�lCA�c�C���t��K/�D�<�]t�E���MS�L�N`�kI@w�|���4�|����-Z�|E'�9���M�-��9W����7�;�|�	IW������������|	�IDAT������w��V031����V/J�3<7t	��F��Sx��\pB \�
�y'���h���9k�,Z�`�V]\(:����qv��<o�&����9���8=�y�b>��uJ�I��^�o^�p����!Ch���L�	x�������'����3�=�N{��������,	�=Z����!�������K;v���8p ��3G
~����N��qB-���9������>oX�;Y��	0&��`L�	40�
<�x&��`L�	0&���y���>&��`L�	0&��X�7����`L�	0&���S,������`L�	0&��@`1����gL�	0&��`N	��wJ��cL�	0&��`
L��|?�	0��$�����#�<����v���/��~��G��|���h��e���/���~�����C��m��������i#�=����,�555��?����#��=�����?��%K��/���n�:Y���C�F������1m���[�����{�/^L�?�8��_�r��`���S'��]�v��O�>]r���[����	0&,�C����@c#`�h��`������t��K�������U�h����}�v����i��5R������g�Q���i��
���Lw�q��J�o��M�����:u����Co��6�{����w��7����.��E��/,,����/0|1&�"���H5n3`��0�8q"-X�����_���\)�a�.))�B���KK�3�<C��s�h�BZ�a�F��'ORll���C4_z��t��WR^^edd�|@�Z����RY�w�}'�������������5k&�tUU��e>++KZ�����bj��=;v����?����.X�[�lI����p4hP1�
����������k�|�z�",T ���<v+`��5l�0���ORR]q���������O�'O������t��Qf��4i�� ���H�~���#4�t������e��C��s�=rlRRR��^�����k��\�(��	0&�X�G��q��p�D�s�=Gw�u}�����c��������.-|;v���6Z�!${��I�����VCp��


�K�.��`�u��<���R��Vu���/~Ao�����
7� ��
���w�zb����t��g�v��u���C=$?������_��%����.��6n�(����,Z�H��Q�����k���t�%�P�n�����g�I��{�\���y�B��������_|!9C�cQ�EY������N`���<��/���.���������+e�x�	�'��/&��@$`1���mfL�UJ0����z!`���+-���n��Y�w�y��i�7�y��#FHK����Bu������R����W�U,pa�0c���g�����w��x��c��k&�!L��1�y�������g�8|��'�/��b;
��?��u�M7��|�������������yX�7m�$-�C��:��������������@�%��l��G.�������V�^�3��^zI��`1�`L 	����Q�63&�*+1.|����2��7�Bu�������[M�������w���C��I��W���C�[�y����imo��i7������n6X�L�0�����.4p�>|���WX�!����_O��]�Y�y�o1��_���R������?q�]��>��s�G0��3o1���#G���+���I�x&�(1���`7�f��I�w����~��9��1&�BE��|�H�s�[��w�y��O�2E
K�_��WR���;�R
+;Dsff&<x�`���fc%��
��;�(��%��o�QZ���
\S���@$��G���,�p�����,\W���.o1�>�,�������?.�e���>������@]�{,d�&��	V>�h{���e��v�<37��cA���K��*�=F1�x&� \v�e�-�������7n�\`1�`L 	����Q�63&�*X�a}�aK�V`�nCP#l!���z����_K1��?�Q
R�]��%�2p�y��7�}Vb�������>����d_`9���BtVVV��y,, �q>����/���:�
W!�V\������I�~�y�������(�r�]w]=�(�x��=y����. p7�vK���^�=�_q�������u�g.4h��u�Y��O?IvF1��a��;���~,��	X�dgg�:��2&��@���i~`aK@'�d�6����/�C�8��{�|zz�,�C������!
y}��72�������l?�	0&�����hX��EX�q U�����.��������\�`�GHO��`�J��|����	0&��`L �	����)��`L�	0&�"���H9n7`L�	0&��@�����2B�J@IEND�B`�
#68Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#64)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/18/24 16:19, Melanie Plageman wrote:

On Mon, Mar 18, 2024 at 02:10:28PM +0200, Heikki Linnakangas wrote:

On 14/02/2024 21:42, Andres Freund wrote:

On 2024-02-13 18:11:25 -0500, Melanie Plageman wrote:

patch 0004 is, I think, a bug fix. see [2].

I'd not quite call it a bugfix, it's not like it leads to wrong
behaviour. Seems more like an optimization. But whatever :)

It sure looks like bug to me, albeit a very minor one. Certainly not an
optimization, it doesn't affect performance in any way, only what EXPLAIN
reports. So committed and backported that to all supported branches.

I've attached v7 rebased over this commit.

I've started a new set of benchmarks with v7 (on top of f69319f2f1), but
unfortunately that results in about 15% of the queries failing with:

ERROR: prefetch and main iterators are out of sync

Reproducing it is pretty simple (at least on my laptop). Simply apply
0001-0011, and then do this:

======================================================================
create table test_table (a bigint, b bigint, c text) with (fillfactor = 25);

insert into test_table select 10000 * random(), i, md5(random()::text)
from generate_series(1, 1000000) s(i);

create index on test_table(a);

vacuum analyze ;
checkpoint;

set work_mem = '128kB';
set effective_io_concurrency = 8;
set random_page_cost = 2;
set max_parallel_workers_per_gather = 0;

explain select * from test_table where a >= 1 and a <= 512;

explain analyze select * from test_table where a >= 1 and a <= 512;

ERROR: prefetch and main iterators are out of sync
======================================================================

I haven't investigated this, but it seems to get broken by this patch:

v7-0009-Make-table_scan_bitmap_next_block-async-friendly.patch

I wonder if there are some additional changes aside from the rebase.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#69Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#50)
3 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/14/24 19:16, Melanie Plageman wrote:

...

Attached v6 is rebased over your new commit. It also has the "fix" in
0010 which moves BitmapAdjustPrefetchIterator() back above
table_scan_bitmap_next_block(). I've also updated the Streaming Read API
commit (0013) to Thomas' v7 version from [1]. This has the update that
we theorize should address some of the regressions in the bitmapheapscan
streaming read user in 0014.

Based on the recent discussions in this thread I've been wondering how
does the readahead setting for the device affect the behavior, so I've
modified the script to test different values for this parameter too.

Considering the bug in the v7 patch (reported yesterday elsewhere in
this thread), I had to use the v6 version for now. I don't think it
makes much difference, the important parts of the patch do not change.

The complete results are far too large to include here (multiple MBs),
so I'll only include results for a small subset of parameters (one
dataset on i5), and some scatter charts with all results to show the
overall behavior. (I only have results for 1M rows so far).

Complete results (including the raw CSV etc.) are available in a git
repo, along with jupyter notebooks that I started using for experiments
and building the other charts:

https://github.com/tvondra/jupyterlab-projects/tree/master

If you look at the attached PDF table, the first half is for serial
execution (no parallelism), the second half is with 4 workers. And there
are 3 different readahead settings 0, 1536 and 12288 (and then different
eic values for each readahead value). The readahead values are chosen as
"disabled", 6x128kB and the default that was set by the kernel (or
wherever it comes from).

There are pretty clear patterns:

* serial runs with disabled readahead - The patch causes fairly serious
regressions (compared to master), if eic>0.

* serial runs with enabled readahead - there's still some regression for
lower matches values. Presumably, at higher values (which means larger
fraction of the table matches) the readahead kicks in, leaving the lower
values as if readahead was not enabled.

* parallel runs - The regression is much smaller, either because the
parallel workers issue requests almost as if there was readahead, or
maybe it implicitly disrupts the readahead. Not sure.

The other datasets are quite similar, feel free to check the git repo
for complete results.

One possible caveat is that maybe this affects only cases that would not
actually use bitmap scans? But if you check the attached scatter charts
(PNG), that only show results for cases where the planner would actually
pick bitmap scans on it's own, there are plenty such cases.

For the 0012 patch (chart on left), there's almost no such problem - the
results are very close to master. Similarly, there are regressions even
on the chart with readahead, but it's far less frequent/significant.

The question is whether readahead=0 is even worth worrying about? If
disabling readahead causes serious regressions even on master (clearly
visible in the PDF table), would anyone actually run with it disabled?

But I'm not sure that argument is very sound. Surely there are cases
where readahead may not detect a pattern, or where it's not supported
for some arbitrary reason (e.g. I didn't have much luck with this on
ZFS, perhaps other filesystems have similar limitations). But also what
about direct I/O? Surely that won't have readahead by kernel, right?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

i5-uncached-cyclic.pdfapplication/pdf; name=i5-uncached-cyclic.pdfDownload
relative-all-optimal-readahead-small.pngimage/png; name=relative-all-optimal-readahead-small.pngDownload
�PNG


IHDR��� �L9tEXtSoftwareMatplotlib version3.8.3, https://matplotlib.org/��XS	pHYs��7���IDATx���{|�u}?�W��I/!� ���E0q�ZE�R��`��x�nn2/u"n�e*���D����LEQ�9�Z.�J��t)��VI��mz~t9&M�&�79�<��G��9����k�����}�*�J%�A�R��D p�����>�������c��up�1����.����j=�!���~��������z(��H}7L���g=�Y����{���Z�PwF�7��������Oz��2(��������7?���j=�1�����RWW�?��?��P�f��zL���7�$/}�Kk;�A���>�5k�$�3#w_������1����4��g���0������|���N���%/��h�������BMm��%�]w]���?������R�Q�v��<���y�����;����@���w�k���~���={v��5#p&��~8��o����>;'�xb�������}��9���r�
7��������������k_�Z�8��q��2eJ����=�e�m��+���������}m-Z����,\�0ox�r��w�s��r9o|�s���g���ill��E������y����r�<�����F���n���������7o^�O��y����/|a����}�����O]]]�?��T*�����k���'��C�!���?��������~='��i'�w�w�����w�Q���N����z�������5�{��2c��}��y����x�z�;��3oz���x��466���}l.��������m���|�+y��^��O>9�y�c������/}iV�^=�gx�����~n�������o����|�;��+^��u�Qihh����g>����'>�;v��"�n������/����3f���|��o�6��_����~���}���?~��������y����{����\z��y�S���s����!�-�����?��>�w�-����}oN?������C�)���w���y��������|�������Y�fe���y�����~���~��R`����+I*I*����C=����P�]]]]�������g?��J���G=��;��K�V����V�q���V���+_|q�R�T~��V��?=������������2{��J�JSSSe�����,XP��iS�����W��j��i�9s�T/'��u8���U�Tn���!�����r�9�T�0e�����Z�2eJ�w��{ne������W������W���������U�������{���������2o����i�*I*�f����7�������z���>������~��z������p�����O�^��	OxB��������O����$�r�!}^��=�i�]�v�[~�{��}���\�9sf����/���{n�o�^�5kV����r�=���=����>U�7o^%I��������gL��m��u�Y}�!���5�������-[���`�*�J�������������]�T�|�#9���p^���9_���������>�9��*���.���n���z�s�3�|����=�����;���}�QGU���������<�y�����3gN���x�;*K�.=����H�L(���'+_|q��?�i����R�T*�w�����V����T���*����������;��{O��w��r���W*�=��w�Q�T�
�=����_����~��J��'�^�re5l{�+_�o�=��g�QY�~}����o��r�-�����0P�[n����2��>��`\x���p���.�<����J�R��eK�]�zW�1����w�������RWWW���K*mmm�J�R����+o~����(tl(8��}��9��O>���a����|�+���o~s������~���[n��R��y�?���V����������oT��o��r�u�U�n�Z��=��S�����jP��o~��}�����oW�T~��~o���Y����+���+����]����T*��m��V������T�TZZZ*_���������+���7+---�$�������q0�	?����;=���gU?O=���9s�;��n8����;g���������_���N��[�V>���U��E���=��S9��#*I*/��+?��O�;������E]T}lW]uU����U��|�s���y����uuuU����W���'W�TN=��~��T*������~f����U_�������7��������T.���J���^��~��t�������u��+2p���]
.{����J���3*;w���������w������%I��o|����i��j(�|��o�s���i����'p�W(Y��6��;wne���}�+2p�7o^���w�E]�g�rggg�������$�<�9���8��}h��-"p��PI������{������5�\SIR9��#�U����+�f��$��t�MC����<��J����_��m[����?�������������W���������������}m%I�������{f�����������^="��k��s��w�]����3w���V���h�p&���I����n��=e������u��]���)�K�����o��������������{�7���>���}�k��kW��w�s������NCCCv������3f������x�{���$��-[���}oH��7��
9������y�{^������ihh��mn���!���=���8���C���T*�|�[�J2���I��W�2.����K����q-Z4�m.\�g?��I��~��CZ���y��������e�������=/Oy�S�����}�����~����y����d��m��wvvV�M����W��UI�_������=���gg���I�?o_��W�k���~�z�[0M�����������������M{{{v����6�6m�q{��9��#Fe]��{�7��,XP�y��-��g����<�9������?����?����/�)�������X�����x���={v������?��O�$��vZ9��os����IOzR���������'=i��?����p��l��)?��O���hHc�'?���~��y��O;����f_'��������<��_���o�=mmm��m��������>����n����s���f��%�^�����}^w���'��t��mmmI��tvo��N���^���������~���=����6s�����;��{�~����93���vvv&I�8��}���;����{1I���o��_�bn����w�}}B�{?o=���}��?��u�Q�=�3�x%p&����*��{n�����;��C����������#?�p�n�:�c��=�3c} S������sg��>��O��/~q~��_��K.�%�\�������N�K^����u����s�<����:�J%������?����������zfG��~o��QG�M�6���E�kr�������u?����l��<��#����=;3g�L]]]������&I�n�Zh��s��K_���Z��>��sO���G���>z�e�
�;��{a��}��O�ym���H��y�y��z�z��m�����?��|�+_���C=�����-����|������2����C����OWWWN?����G?��m��������/�7o����l|���5[�`<����������g��/�2�������w���������{����~0�����k���{��y��Gr��'g��Uy��G���^}��p�
��W*�B�_�k���F�l�O|���9�~�}�s������	�|mz����}����g=�Y������[�������>�y�{��_�:]]]��eK6o����7����*|������hz������Um������k0���=[���3����n��6c�L�2%�{���=������o}+��/�]w����;/w�u��������?�A�N�Z�W==3�����}��>�L���G�(�"���?��w�����|���pV�H��o������<�1��S���YG�y�����;ls �����p��w���e�����U����#���|��w�����������I����������os��m��9���w`���qc�������Z�|����!
���Z������'?��h
'��v��w^�����w_��_?���^�:;v��3���>�o����'%��z_;y��>������4^���������G��d��,����c��}�����7���$�_��O�[���������|���N8��S����?��>����>j���v�i��b='�����r�)^����������}}�~��_��<�A�L���I����9a`o�����Ik������3�$_����]�{���X�bD��c���^�3�$C
W���+^��L�:5�������o��| ]]]�6mZ^��Wx������������}�K����������>���=��������{uo��)��/�2"�.������oL��r�-��'>���n����{�`����S=���?������?k�����|mf�����;/I��������{��'PN~;�_�����K.I{{������H}}�~?s������gw`�8��32e��l��%��\mY�c��\y��9��3�{�Z����W^Y
o�����e/��7�<"�^�vmN:����?�c~��_e���I���^�vm���7%�s���N:iP���kWV�Z�$y��_<�qu�Qy�[��$���Ks��W��Gy$]tQ>��%I����f���.���9�\rIV�XQ
|����-o��?��$�E]�������${Z���O��3k��T*��}�������������~7�z��RWWW�z�����p�
�9sf��E[�ti^���$I.�����_�uZ[[��wuu��n�����}��}Nvz��	�\rI���S.���� ��v[�=��+��2g�}v���3�}k�����>����S���|��_��?����������e9��s�����~��S��T����������������?��;l��u�Q������g��������������>��S�@���wT�T�577W�M�VIRY�xq�K_�R���}����$�}��C��@.���J����Kx��7V,XP��i�*�rH%I��������z���>��������@��}���v�a��S�Vw�!�T����A?�����$������}���U9������2eJ��C�L�2���s�=��c��~�}��_]IRy��_]9��s*I*����C=�RWWW���^��Jwww���~�������z���W9���+G}te�����}���$��~����������
����a�����k��O|��k7{����?����W_����=��O���$����%C����������������8�~$�l����}�;�R�T>��O�y�477W*I*�R����|d��
���;�@��[o��r��������;�2k��>�z�s���~?�p�T*����9s���������l�m�����>�������{�;�QY�ti%I���/�����p&�K/�4_����'?93f����;s����]�zWn���,X���C����'?�I^���W�>��=;�z������<K�.���v�i���+��7�)������?<�>�hs��'��o{~��_��x�����r�%/y�A�m���Y�re������3��a�����v�a9��3���=_���3m���.�+_�J>�����SN��]�2k��<�)O����|����U�q�����y��_��<�1y����'���k�A=������Y�����Y�zVf���]�v�����_��_���EN<����Y�k;X��O��>���]�6��~������;9��#��g=+�y�{r��7���~��	o|�s����E/zQ�������}��Y�|y���g��&��k������|����'?�3�8����T*9��c�������+r��W����9s�v����_�U�9�����g���y�����|�+���������1�W��?��?���O����S�T��g<#W^ye.����|�5UW���3@0�}����������,��zjM�p�������|^��W�s��\M�0�l��-�~xv���{��7�y�cj=$3�p�p7�tS����<����Y�����w�������O}���2��`���sg.���o����5kV.���!���B�@����'��O~r���8��3r�g�z0&i)p�T(��P�;@��@�P�;�8���}.'�|ra�[�n]���
[00�<��#pc~��e��9��~��W��������93�|����A_�c���u�Y9��cRWW�o|�}����|'�|�3s�����#��Yg��M�6�����2�k��������������F���Mw�d���y��^��<�9��eK>��������o~��A]�$O����/~1.�������������a��r�!9���G���D5��|�{��'���r��'��ck�#��c�������z��9��C���=/��sO���o{�>��455e��%�����$�C=�3�<3mmm�={vf���k��6I���}/��{��9s�d���Y�bE��]r�%9��#2o��~�H����='�tR�����N;-k���^��#�������9sR*�r�5���q]s�5y���r�E���1/|��t��|��_����O�_��_��xF����-�����^����=;�f��_��_�'?�Iv��5�g�O-?�Z��\��.�(s����
0��F��?��|��_����s��G�O��O�$��;��o�1�<�H�������|e6l���;,�W�Nsss:::����g<���������$o�����\.���~vu=���/3s���}��Y�re��������$�V�������s��\�l������E/zQz��$�_��_��G�w����������t��7��N��i���;���s��7���Z�fM���'d�����?�Z�������~5�>�h^��W
�>��`��MoJ�T���3��~0?���i�����q�8����������R*���T��W\�?��?�+^��L�6-�����������~x.���L�6-�z��r�1�d��uI��/�<o{��r���f��)y��_�R��U�V���;+W��������3',������>����~})�������A]?7�tS.�����?����C-���y�������-����:��LDw�t��GW�7o^r��w���s�	'���9s���-���|p�����;s�q����y����<k��jQ|�w�]�zW���S��n���}��y���c��>������^[=v���I���g������������4��k���9��3���},�0����R����@�����u�{�~/�D'pAw�yg�����?]]]��sg�����_�B~��<��#y���J��$�2��W��G��DEC�h��\v�ey��G���n��w���9���3m��>������??�������$9�����_�2;w���n��u�"���X�~}����f���Cw`4���_ �������|$�~x?��\��y����W���z����`}����m��������xG���g��GM}}}���d�����g>�[n��z�y�����=���wox����|%W]uUv�������p�
��\�}�C���~�J��m������~6m������}��y�{��Gy$��sO>���wy�|�33w������OWWWV�Z���G���>I�������J���;w���3���I���|�s�����}y�k^3�����z-�
7���o��u��n��<�IO�����|�����0�	�F�k_���{���7o^����|�K_������u�Y9���`������������}����u�{]�,Y�9s�����������}�ky�����s��	OxB��Y3�1��E/���^�7��
9��C�x����?�sv���$��G?���g���������W����]��i�r��W�{��^�������-�����c�=vP��<�3f������g��3f��_�b����px����_�u�C`{������z-��Gf����


inn���>��`<����@��9����?�S^����z(���.3��w(��2P3��w(��
0��+?��C�p��Z&����y���L�V��;+9�����m�<��;��#��rJ����ZeP�����M�����&�q��p���z���Lz�rgV���zy���)�k8"���,Y2n��D-=�,YR����;P{�Rc�/�������4�`��@J�FA;$�;5W�Tj=�QSWWW�!@!&S����P3;w�������U�������,Z�(��M��P`X&c����P37nLSSS�9��I1��R����������R����L�:>|-/p�&*�J���r�1�d��)�������a��|0�Je�l�0qL�:>|-?y����:O����4���<f�;���������sLN8���|��9����~������X�k)����������~��Y�pa�F�X����+�rgZ[�����R���eN�:5�v�*dY������b/p`�(�;�b�������/,t��E/zQ*�J^�����}o�M�V�:`2�Z~,��z�0n��v%I/n�s�H�^{mn���\����������u�d3���X����--{��
��\.��E��$�f���_���]���u�d3���X����`�(��|���{����uk���s�!����;_���r�I'���F��Ku���q�Tj���Ir�}���/yv������<�)O��������`��Z~,��w&�]�v%IZZZ�n�����X����@�P�;@��@�P�;@����n��w�qikk������g?;W^ye>�����O~r~�w~'����s��$�u�]�'=�I9������ �7oN�������_��<�9�����w��]�|X0���Z^����Y.�m��t���,���O����\p������h��~��������p�
��/~����|���NWWW�=��\q�����s����-oyKuY������������g?��l����1�D0j���<2��r�]��zy���i,�z��7�g=�YY�vm��[������5�\�SO=u�z;;3c�����y������u��?��?T���� 3f�H��J��q�Y�p�A����R��7�Z[�$
��k��t��R�?������{S�T�����R�������W�W}nw��7��\WW��rCCC������������d����`�hhiI�tm�������?������Y�������������|����#�<�$y����a��<��������n��$�g>���~����&��R������X*e����jmMCKK!3b���/��{��[����������v��_�?��?�3���$���S�����Y�xq���/���}v�����3���A�&��R��U*�J�K�%K���[o�����J��r��R���p��l_�{����m�c�����jy-e�w(��
 p��jxJ���l���i2���y�SGa�O]]]��C����'\�T*y������0)/�d������wjf��E��qc|��Ze�444d��E��d������wjf��iiii�T��N�@L\���OW���9!4�?����4
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(���t�����3��^��ys��������*j�P�@1
��8���[��z���}n������#D-�(,p���{��O��\}��#�x`���`�F���W������/���3Gb��Q����H����������������_�%K�T�=���#�z`���0|u�J�R�o����q�����2e����%K���[o-r�0.���X-C��6.|������w�y,���E-����V*�|��_�����"�0�<�B�����y��E.jy8x����w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p���w(��
 p�����[�n��_��<���O�T�'?��"�u<cj����s�	'����|*�Jx��"�u<������=W_}u����$I]]]�8����u<���2����7o^���7��SO��^���y��E-�x(Na���]��n���u�Y������Ey�k_��6�_~y�,YR�����z`S�'jy��J�R)bA��w_N8��<���I�m��e��y��G�y�%K���[o-b�0���6N����G���������	'������I��}�{9���Z<0��P��N��$���'����.[�n��9s��O���#@�(4p_�dI~���H`���������L��@�P�;@��@�P�;@��@�P�;@��@�P�;@��@�P�;@��@�P�;@��Z�cG��������4�Tj��p`\�I���+V�[��|�|�;��2@����+I�xqC������$IK���}���>����RH��J�Y�|��0Lw��Tj��0i)�@�P�;@��@��z��Q.w���+--
)�k=W�@�=a���V//_>_�C���$im�J�,^���208w I���'h�����e`p���$�Rc�/���;���*��0LZ�@�P�;@w��\�t�T&�;�dO��b���������h)$IZ[��$�7����H����	�7l��s-e�$I���������$p�J�FA;��2P�;@��@�P���@��������4�Tj��p`X�@M���Y������������j���+I�xqC��0����ji��o����2�7Z�5U*5f���z�3�	���+���{Z�@�P�;@��@�P�;@��@��z��U.w���+--
)�k=��������Xqo�����������sLf���i��%I���/��O,r@�������v%I/n��
]im���~>�����n.\X�b�������$�����e``Z�*��|�|=�a������E9���������sg��F�:��R�1��5�a

������t�M����s�m����p��/���,Y������.r��0��O��0u�J�2�����\~���������,Y�$��z�H����R��O��x��z����p��uk}��$Iwww�������N*j��P�@q
;i�}���������{w������<%��[�����������d��uE-�x(N�'M��J��@�P�;@��@�P�;@��@�P�;@��@�P�;@��@�P�;@���www��_�j���:��>�{}}}V�XQ��������_K�e������|v��Q���������T*����6mZ����$S�NM�RI]]���K�,����Z�r`�9��x4��D-=z��S��r����> ���������I��~�����>�$����s��������S�@m�����w���x>���&I���s�������!P�@������o���Ff���$�?~:::F}`���������������^����^�U�u<�^�����}n.���l��-W_}u^�����������AR�@���/���������N�����u�Y����k16`���P{S���UW]����5y�k^S���������/��������7��}�{_��������������p���ks�5������>���
������]������������;�v������s���
�����}�k5��x;�*�J��/n��������%K���[o�u�Xv���h���Zz�����p����������;/|�3o�������<u<�^������f����_��_ijj��u�����u<�^��}��=������?��?����G}P��������---y����o~����?��l��={�y�u<�^���K_�R�8��|���MSSS�l��K/��cI��/p�1cF^���e��9���{RWW��N:�cI��/p�����c�=6,�I'��E��iO{Z-��:j�_���w�#�\sM���'�����+����cI��/p������k��$�Yg��k��v��:jo����1cF����d��|���QG����Z�
$u<�^����/����������R.����=_��j16`���P{�f��z��I���g�3����:u<�^���\.���`����j��$���kFu`��������g�uV.�����
o��)�:�c�:j�_�>s����Mo��X�aR�@������7���.��_��444T���>vT�:j�_����������'>�����%I���r��������Q�)�;��������J��Lx��������������x�aP�{+�;�b����������w6�������c�I����+I�xqC�����7�}���y����3�<�O��w��]�:0`�����ZZ��6t����~�����<�q�K����s��:�[����������_�~���b�AP�)���;�*�_�LlN�
#��IS���	UadT�{��w�� u<0N�
#��R��s�Mggg�����/xA���'�r\� ����pBU���G?�Qy��|�����>�����?�������/�����r�!�'0u<0\�;�*0<u�J�2��J%?��O���|'���w3{����?(t�K�,����Z�2`<*�6�:>Q�@����>���s�=Y�`��
&����G��O����wm<����"Y�x=���}�@��7�|s������G�s�����9&� �|���LJ�����h�:��\q�y���'d���W���w�����w���VF���>��O�g?�Y��������y��^�{��7\pA*�J-���q���?<������T*�<�������Z
&�j�^�T����$y���k��&/|���C����f��;��N���/���}m����g����6mZ�>��Z
&�jK���������^1g��|�{����k�~��!-��.���S|C���w�y��7��O��9����k��a-G�ZM_~���f���1#����s��Wz��^{m:::�!p@�~x���/�?��?�`��!�_��R`������~����7�����pf��%Kr����z�jY��O����wm<��M�<�IO������>�{�����<f��
����Um)�v��oP�T�i��.���o�O~����}���m.���\~����?��P�
�e4��D-�Q
����gd�����L[[�t�����[o�����$���9��cr��7��CI��$L\pA�>K�,9���h���Z�����N��W_��=�q�n�h��l��qH�:u��0H���kQ�'jy�1`���������:��
u<����`V�1�j��6^)�k�������;s�UWU;]�pa^�����c��A�������R���x��� ���;��w�qy��r�g���x-���:��jK���?>?���3{��>7hoo�����_������a���pk�Z���Zzx��$����w��~��x�=�/����z��9��s�h��$�]w��+��2o~��k6@`���0vT����-Y�lY�������H�R��E�r��W�������}P���1�����;.o������$ijj�����S���P��~�}����}m?����9���s�a��5�yM����Z��u<�����s��i������+��{o����l��1��vZ�=��Z��u<�����{��������9�z���3����f����������7/��o��;vT���cG>��Oe��y5��x;���W�����G?��y��h��,Z�(Gyd����|��_���}P���1�����_�b�d��-�T*9���j60����@������v���!�Rc������~9w��v�a��?���0L�x�`���Y����\�%+V��r���C�qe����
7�0Z�
������+I�xqC�����7p�T*�5� �x`�ZZ��6t�����]y�M7��8������*��|�|=�a�������������W\q��<u<P�R�Q��Tm)���?=O{��2e���r�-y���'>����/��S�;�u<�u��<>�)O�5�\�i��%Iv����K���?�q�+_�dIn�����������Y�'jy���6�w���z(;w��^��kWz���0d�x��~����
o������%/yI��[��V��O�t��:j�_�����-��k��&I��/})'�|�h�u<���gQjll��G����%�����-[2w���0�x��~=�?������|e.���$����s�Yg�����S�@���?��O����OSSS���c��<0�O��/p�1cF�O�^��{��Q0t�x��~��)���O����kWn������������Z�
$u<�^������q��466���}m�:��|�C����AR�@��U*�J�V�d���z���Z=���6o�����6����>�`>��Oe��
��kW�����gFo���������/}�Ks�)���Oz���k1&`����H(�;��������J���y��G}4��Gk1`���@�����Xqo�������p�N��t����'?��X�aR�Ekm�J�,^���2�o���w\����������Y�paR�TRWW��o������FJK���}���>��}������k9`���H)��|�|=�a����G�$�����p����93I�u���s�=��_�x`$�J��v�~=��=��L�6�zy��i9���FuP�����������}
����g���:(`h��P{�����\w�u���^{m9��Q04�x���{������s�Yg��CM�RI[[[�����bl� ������'�|r��rn���T*��J�L���f�������R��3����Ss�	'��O|b�N��3�8�cI��/p���\��m[6n�8j�N�W
�/���L�6-�������3}��L�6-,�+^��Z��u<�u�J���o}�[���|dTV�d���z����.��6�:>Q�@���q��(��[�lIggg��,��C�����������~�=��,X� '�tR-Z��=�i�0H�x��~������\s�5y���|0+W���_��Z�
$u<�^�����.,��]��$g�uV����Q0x�x��~=�g������,Y�$��s�QG��	�=�x��~3���_�%��o�?��?�\.��_�z���/�bl� ������p?��S�$�������3c��Q04�x��~3���_���N����h��<��O�-��R��������������E]��z(>�`�������������R�@���w��������/|��s��Q04�x��~���^��|��������}��\q�}
w`�Q�@��U*�J�_L�6-���}nT__���uu��cGa+_�dIn�����������Y�'jy���6����;��G����0tw(��
 p��;i*0����im�JKKCJ��Z�
�;#Jx;����Y��������{�`����������$Y��!6t����k���;#�wx��2cWK���j���>��3��#�J��,_>_ �;#Fx;>�J�^+�;#JxLz�@�P�;@�p�TFE��������48�*0!��q����������?����g>�C9��U#@-�H+�;�b��������N�-e��?�#��������p��|�#)r��Q���rgV�jK��Y�����+I�xqC��I�3�����$�w�Nggg����\<0B���[���w�sS::�3{v}.�t���=���'h�����e�����/{��r�����O��?�����<���fM{��������aCW��is�{��������>����dPhK�$����r�=�d�����W�����/�<K�,��{����^=0Ljy���n����R�1��5['���W\�@.����Z�V�!��(<pO���������r�UW���\�[o�����C�������.m��'����O��'����M���������l���;���e�m����QXK����tttd�����{w�����p�	E-!jy���Tj���.���1���!�����hj�Okk��*N���K^��tuue������������.j��Q�L�R���1�Tj����e�mNSS}����8�	���}������Z0J���hX��9--
��`B+,p�Gb0���IS`��@������N��F��`�)�;�b���������-e&����$���
}.0��LK���}���>�YZ�L0�Rc�/���;�(�L@�R��`�i)�@������N=��qO�@M���Y����������qIKj���+I��T�M�vd����`x��TKKC����zu[���+�W��\�����LKj�Tj��g6���;�����w���K[`�1���[��)G5=���I��zo�p��J��,_>?��]iii0���p`L(��lYs�d�*}����w��r�3+V�[��|�|���q�w�����$���
}.�w�����n����2�x��cF���&�������P.w:1.���1�'���}b����@K���'�)����1G/���k�d��I�V������x8x^S&�;�^�R�<Z�b�R���c�X^S&:�;@/c1x
��ko������I�����;�W.wf�������
�c����Y���
p��p��&��8c%x�z^m��'p��
C7V��5k�s��;R*�H{{�����k�;���x����23��Z��rgV�n��
;�aCWN<q�z
&�a$�ah��X1Vf�C��������yfs~���9��f�<Hv�Hq�Tc�;P*5f�2�9�'=������p��,]�T���"�a���#@F��U����&�@1d7��;�m<8X=���^@��Bv����$p�R��0��n{�aCWZ[�lkBAj���!?q��0Fi{�W���U��R.w�z(pP�����p��B�����`&;�&.�;��e���0���6q	���f��3mb�0�����v���K��=��^��S���c���qC/���Is/��z�}�rgV�jK��Y�q��>9�����2�5f��_civq�^�Z�Lv�0^�������Tj�O ���^����)w������;�c�P��(jGK�:������;^8/��5�r!�pE�.�E{�����jq�DkkW����aCW::�s�e����0N�
0�����K���e��:����/�ps������,��4��}w::�3{v}����'(��56�f`�=M�-`�ps�����$#�Y(�s���r�e���T���z�	
#p���vR��4��4E��(����wo�U�����ga�����4xOP8�;@���������w�\���!��N~9; �:�&#k4�F��=���A�Pc=3���i���mY��#k�vL��2����5����'S['F��`(��������I�Zf���jU�����`�F(: �Lm�Yw�1�����	]�<f E�>{E�0F8�gf3��@|��mio�}�����(Sj=~�Tj��e���c�1)�s�9s������)Y�rK���a-�\���UmI���A3��1��c�g���u���EM�Lg�����4����T��p��
�$�L>E��eE���Y.��+���/_.t`\(�;�bgH�8�A�"�&p���8�jmM�4,^��
���*p`�
u��\��;�����q���K
���=�A�"�&p�����_
--I��
�\��2���5k��~����=%w��#k��>5ZQ�)�L�{~��<�K��_�<s�9G;jb�������=����Z��r���C�2���u���b���j,���L������l��#�r�~3��K��zu[::��xqC�.m�v2��g,t����_��O���S L\=��k��g����]���k;��)�J�������V�QLN������+��]^w�4�;��Kmh��:0��W*5���+������M=���d��a�t����_��(��802:��t�����E�I4�t���P�7�����������*�s�9ss��[s�i�|�q�����u���w��������'����:���O��dO���]�P���'{9Z��t`<��_�rgV���$�$R���g�, &����$I������!]����I�w����3�l�p����{��:	�P
6x-z�����?����;�5�P����Y�������ce��Y@�d�������$�����e&��m����\w]{���������!mm�����45���������u0�����l�3����H�A)�;��wn�����T�zu[.�t�����{z�&:-&��R)��/�t5={�l�����cG2c����ur�����jP���u���c�hm���?�I��~�����vuXZ[��������$I::.y�uO�Y@�D7�3L��{K�IQ��_�����[r�m]����'�����v���>'�<sTf���������r�6Cg���TX��q��������{2e�����/��^�W���g���4���>w��#I%�78$�F&�����dc��L?���S3�a�)�s�i�r�M�2k��l�������q>���0���i,�2��s���3���&E�A��O�:5����'=�I��cG��������f^����
jh$f��J�����z���yO�H�Z��-�]�9MM�in��1:HvR�u��6R3Lk��XKKC����$��}������m�?����\���+�D�-F\a�����3��$����s�)�����*j���H�	K{�'3�GF����.�/w�������xqC��L����10����H��f���t�Py�o�O��?����~��&����e��|�������������Kg�F�����x��]ij������������$��g�h���9�g�x��g����K��j����G��T6�����#g�uV������Wxw������/�^~����^=#h$�h���?����s8���
io��/��$ik���TOa�h��!�n�����>������������D-OB=�&c��f��jyd�x�T���www������'��/����\pA.�����%K��z��}�!������m��_�V�e���I*I�j=�1�Tj�9�����_�r����y�c2n�L��U&����Z`"��5[��f7jr�S��OK�1���k�6�����oLSSS.���"�8��?��t���3�
4���gT<�m����*��y�c��x���L<�x��e��l��5���f��m�),p�������|&O|�s�)�$I^����/��/�Z��������?�����f&I���'m({ �1��y�c<�vc2o�2q��&��V��f��3jvm�&����=�i�T*E-�	�@�}����gb�l����y�y�|����������|&[�����I��h�����^�dIn���Z��Q��-�/�>���qe����m����&+�;#�wm\hw��>�}�����7��u���jmMCKKK�Z&����ug4	��)���Vg��{W��^��|��}�0C���>���d�	�-c%$�jmM�4,^��
���*p�Ad0�O�D����>���RH����$�����ejk����}���J3����
"�.H�Lrc)$k,�2�r=���r�3�W�����r�-�r�	3'u�r�3k��'I�.m���P�D��Q+�e���}+mVF�X�K%A���Cf��)y�����m���w,~���������~��$uY��-�^�pT�7�#Qju��v�@"p`c���H��?--
io�����3o����7m���������tttg���$��:C9��G�h�	L��{zV�/OT�Rc�-k��O���/<2�������\?�GA�����ug��-)�;Gt�{+�;�jU[����4d���ttt��cw��F�����dpG����V���w�X�o-[�����Q;
����n���_�=��~�f��k�}���K/]X��C9�Q+@-	��G`}�f�������[�$'�<sT[���%K-[�e�Z��"p`@+��R�1��377��-�^�>f�����`����9�`��4`jm�Jss}����47�������Na;�0��0�(�`b�Ek�}�0u����m,`(��D/�`2�Ek���0u�+�;��wnJ{{w���s����z���������/<2��5�����HK�	�wq��20>�J�Y��y�B��|��5k��~��<����_�=k���>��]ik���
]����\v�})�;Ga��x%p�@&rq��R�1��37--
9���fv�oU���ZZ���������]���)&6����R�CN���\����[�d�mW,]������������ti��S*5����e�����=�V7n��r�s�</@��L����������YS�u��	���Tj���.���e������5k��zu[�������z�,'n�:��t�����%��R��C�	���Z����o���+u����2�	J�Rc��iOGGw.�����Q��s������Y.��+���/_.t���cL�!�P�x���w�(�;�zu[6l��
�r��3G��Y==�/n��
]��
�k�����Z[�$
��k��t��
�'9'M������Z��r���C��w����HkiiHss}�N�Kss����c]����'4�1���3�l����5������=!���[�b�������j��vtCKK��k��>����p�I��c�CO��������\x��Y������\����;������u��J�Y�|����n��h��Q[��^�����q��~2����R)��/O��5#9<��;L=!{������Md=':���+������0��=����ti������s>������^����v���Pv\�c������Onw��zk�6�HSS}N>y���x0~��4���;��=�>MMS������Vg�����4����T��-Z4}���&�����N�1�jg�!�*;��������&������"�:6	�J����#s�e���i��+&2'%d�:����bE�������rL�����\���5�Y���NO���X�.D?x�}�;�����1�mm���D�^�=����y�S��?���e�iii�!�Du�m	�<�[ZV�����Z���.�/>�3���+�����S�&���'�.�;��O>�$�����5�{�4�����i�R��'9�;LP�����0�`�9)���w{���3v�Y����{��z>���\v�����]y���twW����h~��gO�����w�sS���W���K������i6}�"a;w��:�u����&���z��
��e����R)��/���@z�����l_�>3N<1����}>Z[���T��S��{w%�Z�E����Sff����Y�>af���v���;�gOI�tttO�Y��u����$��n]v��������z@�z���20:J��,[�,�Gz�T�}y�5�JihiIWkk:��>�u��i[����GR���2kV*���������O���S���7f��i����|�������w�sS����x#���!MM�����������|YU�d��+�d��{|�6�J�{�9�no����lY�rT?��Mf���V���W{��������q���q���5u��}s�~���Gu���qG��r���	^*5��Kf��=��'��}���8�/\��\c�hjG��CX��V�]z��o����s�%9����z�h�x�����|��w�\����m���I*Y��a�L�u�}�n8�g�d�Z��c���5P0�'��<����OV���K�Q��{���������$S����n��o{���xE<f�3V�h��Nf��b���0I��p������s
�`����|�|�d&_=���s�%�2gN������������}�g&8cAWkk���2e�����uHG��=\��u�]N�
�D�N4^��[V���+V�IN<�F����/Ov���n,�r��q��l���R��H��~�$i^�lLy�8�+��?�9�`m����
���0A�PT=���wQ��=��`��W�=�t<��E��i^�,����y��_��'>1uS�V�K�ZOQ-�&�Q��jU[n�qkN;mV�-k��p�e���M���32m��L��#��
��#p�	`0���)�E��kc������	d�K==���s��w����s0-��&���4�Z�������sg%������]�?����zX���sTvLo������15w���������no��/L��e�*��&����n������'=������s
�`L�����zz$B���K�V���g��u��re��s���5���=!{�<p����H���Yx��I��6���-���c�(��p��[�sg%�����������$�c��KO����C������?[zb�Z����tm�����l���1����E��D?u��������f�F�1��]���m��e���{���:����rg6n�����Am7��U�y�m�y�=�?��tm��-+W���5�MM���������~;���f�c�?�<��)S����Y��]�>F�J���K���h���dw{{uGR}S��?R���a����2y�O��/ma�H>��[��_�<[V�L��<��!������S�:����{������Tv�L���Q�on�;�L���7�e��s�9s��/=�9s�3eJ]6o��U��l��{M�X*e��f�e������J��D=���`�I06M�#HG�1��g{O��
����7��\>���n%�h�����g�O�7/Sf��C���3r����m{����z!��y�����M;�����[w�?��-7��-����o���e����2�wRSj=��hj���w���5�5�F����/��t����&I:����+V��\�������g]s�9'/�4�~$��|N�1#���3;wV�e��r����Tj���.��g�M�l��#����l��������X*�y���~���Y��-�rgA#c<3���kiiH[[w���=I]V�ns�!&����o,���Oon��Z�nA�dP�Nz�����-;]����{� 
�7G��X���R�1��]�5kJ}twv�������#���M�@��J�9�����w�	O�������v)R&������
?����� n0�����:����{J���N��c�z-�����[wg��J�����d���#h��M�e�0&,]���k;����dp��0���9�����s�����Rc������5�9*w����?�p�L&���in�����Z��(�;�G7$��v]�n[������1b�C]��z�#L�g�'k�;LN?�{f�����a�y29������mio�NSS}�.m���@Q�`J���s��\v��45�g��-�i'9�;�3�d"�9���i��#�iB1�&��2�zN��y��n�p�tmeH"p�q���@�g{�`��ppz���������fM{u�� p�
�y.��	Cs0G|����������pLG�1:Fzd<n�w{d��O����}�������\w]{���^���K�
}����Y��=I
_�d�s4B[[w���s��Gf���Zk�+��G�����1���Z��1G�x��Oc��9���0�� �u��H_c���Tj�)����
�y�gf���B�\���y�;7e��������}����������������+mm����+�����l���"��p�=��yE����92f�g�����qEq��a�� ����6��������@3�����t��ttT����h�����>uva�lm�J{{w�M���-������-~6y�����1�b,kiiH{{w::�3{v}�����������y�`�5����m�����E�=^7��(f�2�
r0��x����##��e�|u�����w���=�MMYx��i,��������<�	����Mww%���,Z4��v%--
ij�O[[g:;wg�����J�{�����iX�2s�9g\�_F[���/<2�]v_������~L~/��#pg�+}�&�^���8���
��������[�j8��@� {/�`j����3Y�T����}��fM��_�)�gg�w�}��4�J�m���2uj]/n�C���7n-$p/�s���r��|�S��fz������}��l;rZ�Z['�L��U����3�����l����lYsZZ����	`08w��Z���({q'��(��6x�WP�"��q�deg!��x�a��;����6�@�9�Z���8��H�~+�G���O~���r��|�����v&��i��*l��Rc.�xA�<rZ.������<���9�433O>y�[�����v����c���+3e��<��/����C����V�������f�����#p�A�({qG�q��`l_<=��u������>��m�1��Y�pU���e������{���y�+�_FJ���i[�:��v��I����R5?��Y#����>&�M��7��?��,X��������]t(��V:��3���(��H*�L�93[o�q��{�U���qW�J�����<��_�"��M;����P<�;�D��;��1�?-+�s�9s���^}V�����~���(;=}E���Z��j���=5s[[w����O�����k���J2������8P����5�JYx��i_�&m�W�c��t�]�����e�#>K���X�����G<p����H������=����xc�V:Ij6����u�N�C��m���uk��M���N��n�qk�J-j���]�������
�Y.W�WMK��=5���O��0Q���q��D
�.�6��e�'���0:������{j�Y��$�����Wg�^V[���-�������n(;*����/% k,��������>�s���=����d��_������aC���p����y�m����dO+���7�H���jhiI�����)�:wn�47����u�������f�_x(7v��6@u;}$���}����YI�����} K���>��y���i���������M����D��9���L�pE��E��=�������e���in��Wg�,���>��m���9��������2��V
vG�p�9��[�$�i��n��F�~��mmI]]��������$;��;3J�t���h����>� ���}�3������M;t]���no��i���������|���������;��L�;0����/��P6��c��l����Mh<|)a�����c<��`M��| ���{������w���;���t��mw�N�K�;��m0��Q������j�;*���ZdE~��n�3R'��������S�xq��.=�u��T��n]���s���g��EI�����aC���gI��]=T���C�jU[V�z$I]N<qF�.m*�
�m���,��c��$����L���]����M��o��y����I�V�2j=�`�=>����$K�6
i�#���Z.wf����^�6��q'b����x�j�0�z�Hj7+s(����d|��1���@���Um��7��Gw�����<�)S����Sf��s�V��wm\������j�;*����.�`���V����.K}SS����
�y���~�{f}�Sa�9����{�zz�����?�����
�~�;������+��w��Umy�����-��kWr�!Sr��3s��G�y�M;8����MMi|�g�Og��#/7?��u���D�>�L�(���1�z��;����{�{�K�6��H��`^�r�3�|��l���-[�����I{{�7�sb&��=ca��w����g������;�r��<�#5+s$��1��x�EL`)�o�`�SD��s����s����qcWN>yV��}���\v�}ij�R�e^������j$���,�`�3;���w�e���������sT�g���������Y�p>�����?�.�����Kw[[���s�
��������������U���Gv��;��{������Y�>�k������{��eO���|����z&�5i��}�����`M�(3+�`�{�w����]�Q�~0��`O�4����{��3����@c��L��flk��g��m�6mJ~xW~���y�����0�3M�?��y�c��g,�a"���;�?{�
����)f����vg��{Gd2��}�;+��u�p�<��<����&�����RL��=��8S�������������r����{���4���v��C���/��of�e�m�wte���,^�����,[�\�N����s$���6SWkk�45�~��twtd�����qc:���C�dp���V���o���N���>��w]�1t���m���7����}�iyt��=�u��i�������<fZ�L�K�RI�L��L�V���wf���!����n��g���Zw�L�ko�NSS}.�t��~=F�D�[2)��}�����`
gO�D�0wV����^o��d�-��w������u�����cG�t�����^�L��-~luih����N���4+o~������3����#i��u,��c��j������p��T����	�M����w#�c~�>���N�u?�1�R�Lc�����5_��gy���yx�!Y�R�Q�rgV������AO��g;f����nk��Y��{�����{B��~����=AK��_�������;+����}O�}�s��/}��$�i�����5k�������U����9����������}�H�-�v��������77�a�����9��f�c��j��"�CS���Z����/RI�����&��c����vl����k��m�9�d�i����|'���]t�c�\��s���k��aCW|pW/n��S���<�/��z����5��k���{��s�f��-��{���R��=�m��lY�2s�9gL��,�=�g�����=%w��c��0������4�y�A�Xx��������L�P���%�mmi���=��`/o�7Z�2�Y�^�{�I�vm��
�����C�q��~���KKC�<�9�7����O������q_c/���C^7�����,���W���.m���mio����
�������ygv�H�3���*�jU(
����Y0��D�y�?�x~���8#����	{��s�L��j11�c����	#����;rL�\xH/n��}O�}�a�!���v��M��u������;���|����������<����[���l�3�7��-���=����@�����]������������c�lYs���\y����v�����3������k��/���n�F�oi�v��k�����c��d�;TJ�	����L����S��g����:����9g�E�}�<�[v�$��,�bH�
-[�[hiy���������P�^?4�o��$��B��$y�"��k���f�K3�}���?��x$�k��}]���9�9�y���������MMd�A���K�����O�� Qs���o3��$��[po�-[����.�u^\����}�-+��`P�����q9w�L:=��}��uGG��1��v'�������9���������5�)�b�1�����ch����7
�ta�sc�������$����=h��k`|���$���Q����(�{7����O=:/3��e3lZ.��+�BH~�1�s,�-P��L:�"��m)m�b}~s���p�����1�tZg�*�������d1S^�NJy]|��q��m�������6
���f�xcu���������������z��w%xy:{#�����=���k���s���,o%%����FW��B�[�;O�������\'�F�d����vkc#��V�d��~_����8;wF����s�Hh�k)b���G�U5��t������$w�:���������qoj�f��c0�dR��DB���������R�u+�����[?�W��>���w8���������k���}��j�L���;X�����;�;w:��B���j�
���������-�)�rE���k]'eo���������fD����%.�o�
��'��e�z�1S!fZ����/��Ci�l��a��(����u���177��m-���\t����;�D�ZQgf�TL�Wcy�_"a���Lu��(��k��������Vc����9�})`N�+�O�c4���:ZY��(�/���v�	��`?��v�.���������0����@Zz,�s�<]{��l�Z�+�$��C3�2�7�3��OY����V3<�e�FMM�3&���h
�))�09i����	���~�]�%3���S��B
�D"��kK:���#p�`}GG�x\c�*sS��d{M�������y5����k���P�(�"�C���?�(���:���,����k��_oM�3Ix��7��Fr��U;���Gx���<�M%��f��Ymq_]H�|��3����z��Jww��BY��b��R�x���q�1�o���������>�q��Z+

�)fq�ut���V�u��|O��w��8bx�=8���]J($d����p��=����L`��g��<���>f������Oa	'�3@j����I��1@��G	�$�Q����c����}�}�dg����������9t(���a6lp/��7j����tw���;���H^*�x��h�������!�Q�}��$�<sOj]y���������|a��-4�i5��os�P�w���I��F|L���X�FIuuaml�ZSC��w_09����s�����Zs���F5t%�onc��g��(�xU.�� &�.���'eZ[,�Lj���Y7�y���j����kE�8_b����,�E"���H����~��j�~������Dw�D����U����������|[���W�2�Ww�YG�9���b���O����'������A�:t�0�OggZ�_�����/�y6�\j�5]��9��jZ<�@G/_�g?m��b���\K7a���XI��1��6l��y9�Ih\q�cjJa|\F����������t4�q�H���`}�4eQ��m��-�gz>K�d��G�S��>�fV�X��j�/n���9^/6����tt�y���@���,

Ko�� ~oo��Em�&�v&��t�s��s!��3,2��������������}�m9�1�fZ��I��,�7[�VY�7�{�`����W�:����7[��[��g�c�wp��!�t����[pb���3���kQ�y�BGG�$���w��|�0����m�,_�b}N������&�:p[2�����55,`p/^o������\�8����{w���6y���{�{��d�`������L<�=$}�1�]�E���A  ������Fgg�o~s�U�����t
x��`�;��z����������ebB�"�`��/I�\�{�����{�8����n~��r���DA����Q�6�*|���������4�����7���'�f��s�c]��Hhx<����6(�b��;BLN*��)�_�:g����{"�Q���H������=S`�������,`��f
�9c4���v"���R����2�������_UE�D�bA��&��q�{;[_x���O�����2�_�`H/�9[I$��#���$f�+_i��;Cd2�����v�q�tZ������Hh�Y����R �5i��5��|�a�u�����5���(�m��_k��s�M��T{���~������Ok�Ab=������*j��� ��TP10���]O�p�����O�}�{A�);S�������������8Uu��D�������|�v^h�����>���r �s�Z�&�	�d��a.KP��$��%�sl�ax��h�����)EL�1���:��I��#|���O��a@*����pH�z�@;�R�8���z�����Do�v�M���,������<�<�#�n��a��$���y�h���'���J#~w���(���d��#�j�����lK�y�j����`�:�j��O?��+.���)��E���85��~Z��T�s6���Gavh-G�x
Z|��#���v�$��Y��Lc�TNo�B~6N��*�f�����.�5��N�0|=��3O�P�>���>��[����ud�������l40v����~����7���y�r�<��
���O�������U�l)-d^�*�sg��a���,~�=Gp���������VU������
(���}U�j�`o���[.%�cph�wt�gX����y����4��X��u::�l��=%��i��e�l���3b���(�f�;�p�z�GB7PUe����l������j��"������Q�����)O��I�D��^G�>NE:�+�V��,�=!��Y�N���?����q[�?l���������g���,^�kh�����"SS
�a��,5�����Z[�����ZHN��L�q|���A$�2?��HhK4\����
S�����"�|��y'����3���9���gH����e���>�R�*�������3X�~�������������%�\F���^DRgg�f3i��������TF5�/[~Z�u�1���}���]�]j:W""�;��L�2��Kt�N2��X���~z�z�	��Z��l���6�����k��1E��x$>���xb��2	�G*�~{-��!����������6�_O{������������Y���V;e�Aj��O�Z�/�����G����7-=�w1,�����4�ac��'��2D��Ly
��h�T�`��G{���i���������-`�j�����7���N�����+�gd(��:z��)io������v��l��g��3��L�s��4���TZJj�;x�`5r�+\~�������O��Z�@������t�bZa�����o�1�5�j�� �������833*ee&&T"
MI2�A�6���������1�4�PO��S?�%����'c4p�;�3�dr<MIl���Q-�����$!��dv��)d��;
L�'�����L�x���_�k,_���v*pv�C7}h����4n��'��V9	d��,.�p��i��O�V�>N�W��+���N����P����%L�s�������|�3��S�����G������E��K--�����]])TU�b���g����xG�}�
?�mq��B;Cgr(��tww�~�03�����.�>���\1�er���oz]��W�
�}�a�}����������I��R�lP/`�Q^S��1f%���=IW��^������Y~��]��5�U\D{�c[���P��>$�����R�������J���~��+q�P
�S���\�������y�����������Xa�����
e��$6o����f�*�_Y�T��N��h�H:}v{���z�Q��*�=�j�`=�YH���Q�;wdf<7���6��48���7r��!\.�l���?�c������)~����zs�h��E��,���)���������=:n���]��>?o����^�j��Ti�@_�P4�V�q�D����1�G�zf#�����P=>��{��>k����>K{��
�|�{s�R:�������O~\MN*<�x�����
�����;G��TV�	.��MW�����������}o��S�e���dYG�
4���WR��X�,���+<v�@��1�kh��[��������2���A���v&|��x��;����d����g)r$g����,I��v��z>���f�,�=����\3��	,����{������M���noo�Oz}����h~���S����<�����M�Nj������x6nd����TU���x�v�XJ�x������dh��K��_�^0���yn�����~R��g>SC(����&�VNY��B�����s����ke�k)����2??�
�#�;�-��x5r)`c����|ls�������h� +�<����L��J�I5�_
{�����>��0W���{����Q��[Q��P9�PW�d\A�gh���z>���E���X\�$���	�YjB]���������]��Tq4��~����gpr�X�������NWga�k���km-�{gg�
�K�e�~��#Z��M�g���
!y�HZ"���f��*|>��.�P�%Q����Lg�CCYzh&�2���r����V����U@2��tag#����+q�G
�����oXQ�(�(��/������(���@2�}i?�yf�4��>Hr_%��>�}l���O����������!���yj��c���t��{�CO&HKs��QF���dox?Z�������qsdh(���~wr#B��B�%}����g��OWt��'������a�O
�O�T_pZ�djUUY��
7����Vgoo��;�O��tL0(
���g�52��d������h�������HZ�N��5�[F�L�`u�Uf
����o�}�����4�}7���Qff(��������x\��/C2�QZjA�(�.Ngg��������N5��Q�P>X�Os�56��i����!5&�'p���2}5�V�����1b=������g�
Z�^��7��>������'{��}~�K&�5y�*'+g�INF��-�i3h�����Ik�����~���cD��MVe.R
���������r.���c��?l�<��Y�`$�{�4UU�0(c��`d�e�C�R�|�Ismq�#W�fM�~fF%���z��@}�<�P?�%����6'� pEe[��~O	]s����l �s��L.`�/��<y�+�O�k����k����dg'����56"�B������
�����Vm�ii�Y��MFwm���1������C<�s��5�v�fFHgt���&)!L�J����c�\��p4R�':�+C��1�X$����l�l�6���h��1Go��!�O�D�q
C���XtN���V-	 g���8�b�y�	�ji�18(SZj>>��zZ[�l�frR��/C6����Lp�u<���+����qer���Q��2��H/��yMp��mL{V`���V,�C(�����;��g�����& ���H}�������NW�����<=/�W�G������d��|���?����,��FJS!���������z�9p�)�T?�uRS2�d�G��/��+��=����Ho��k0(M��.1Fk87�������bYndX�m}cT9/�������������m<^	��	R��d�������f�Q'��K����	��f���X<��
�������I����Z���S�������+
��jbS��HtRa	���j�;���:�����`�f�i<��j������=�Z�c�����$���j
�������io(���Z��4����#�KK|u����j���dRG�	���x���L�x\c����^�M��s��`�[ �R����0�+=N�<�.���N��:��~����������'e�p���~�?��$�8(80��n�k��]��e��(*�H�K$4��e�������dz^�|��"�~����eY��\�p]�)����w�i=y#q*�bh(K������!�3@���8��Q:��e�yq
��~��P���(`����q����(��.c����>��������?_`!��i9��V
Ma��]"������:�6����dt^����G��F��[xh;
�q��)��.�Bfx�����l�0����?�6mZ���Qz{��I.�%�,��~�z�em0������$���/��3H�n�����!��b�x
u�����K�Z��h#�e���;�������$�>�
a[b�=�n8����2?}=	R1'v,�q�3G���x�7���}�����12w}e$������|��;�h�+�'�\�1�

�i�W4��,���l8t(E<n�������K�.�=���^LxH�qi�<xg��o/i��g��Z+����?nnR
_����F  ���p:En����xM�t,�E@U����������3~�]��4�����.X,f'UVZ�Lqc��d����y��s�ug))�E�������e�oX����p��)N���n/��/C__E�eS�H�4A��v�6���kO9��	�[j~K�����;n�����^F��
�>���{�X���$#d���&0���J��E��?F�Z���Y(<{��x5��1Ipf��L��9������7d�ZU����Mo������L�}����=���,'�����%�����?]�DB��W���UJ�}�3:v�&��?�\Hd�������M�|x���b�mY|�]d��H�e�q�+�yM���jC��e��n7z2YX���?��\Lu�<���u7[�~���,����J2<��*mmv&'jk-����l����he�Z���mP�YU=��T5CC~D��N
�����|��q~�K<�c���l�
q���3�Sa��{���Q����2<��6����w�y�63�,����1����������:�`�����2����r�TRg�j=��CH���Y*����u�/i��E@ ��������Y�w���������ZC�@,���[H���%z��~������8�q��Z��9.b<�b�1�y���
7	��!�'izY�O2��Y2�=Dc:/����T��?�S*L��W^��j4��,��F��`���Oz6F&���Mic��4����7]�a8E��jK.q�����������U;0�%��.���?�o7��a����Ml �j2���%r���2���,��(U�cX�D�'�K��W�[��~,�Fu�K�'�[�|L
�Udn.���]��Fy��������)��c��R��b��O��}>��f��?�������sl8�<����v�
l��;-�xh(K����#��E��P>������1�Y�����2��Ls���v��=���ad�eN/��~&�U��.�r��S��b�����m4FCT,[�W7�]p������Q�4]����~Jzn�a�1�����:p�������=���$D��p���2�f{���I�`�Lo�i����~���������G3,��;v0��o���"`�����_������~;S�������)���_RB�7����@<��)�c�;v ��k��G�����}���S�-i��-y�J�������f���'���6:����8g����[�������v��V���il<����?�����W;�k@��N��y��\�C������P��������{�o�aa�-��8w�`l�F5�Z?�c:���v�0d+��X���D
��fqG)VUa�?�C*c�������T�W1	/|G�)�c2���,<7
e��
)a��K��s���=�����T���;�DT~��.��a�Or2��F�96���H6�=��q���6�����~�������������xQo=��Qz��m3u�~jjlD����w�Q�'>Qu�~��>����W��dG���h��a�nO��I,7z*IW�����\�����`��������������H�t��d�4TtDQ�n7�������`��
#/b����P���5����7H�9�t��X�~��//����}w#�����t�k�+��H�K������s��M�P�QJ������P�A���t1��g��
e������2�d��Y~IB�'U���J���E��8�'��BD�PL��:3I�n����H�q�{*�SN���a�5U���MqE�BE��5>�P�
�f��d�����-��1�)���$zp��G���}77�����Sx<^����j�sk�Oq�Q0,V!��{�1��������8�H��W�Z�]t
���o�8P34�eY�9Vj��V�����	�L�kW��o�-��b�m}���al��}`�#���<2�`�2��C���C�P-�s���.�]������mX,5�D���\];���Z���� ����r�I�DBe�-��l���c������0��!i������E���/��)�������sI|�=�(�nad�O�`�K�px��c����� ��\�� ���%�����!���>��p�E�7��
�%�q�����yx�y�ZN�`���=YX���8e��S������ZlZ2ir].�x��������}E�����H�����\w�Bvbq���-��s>�*�d:�����`]k+��A����,��.f��Z{K��-{��,��t�c>_l�0�V3x��/�����5^oV���������pZ2*�uVR���,��c2��������C���a����g��7?���
���"R�z[��34�%R�F�%��ay_G�
~3�hG����;v`����a�P������F���zPU��+��N,�1;������jJDe��TE�4�0���b���j�(�a��E����m�[Zr����+-�&40F�-2�j�25�E����k��0�tP�b]���f�S�,�S�c4`��Q��CW|�'�}��=5���`m�S/Ns\k�QD�L��pe�	��XHfc�Wi�y��LTv �J��[�i�����b��Or��I�P��T�����T53�V~V��pE$���Sn��$�-�$#[)�d�����J�1�����]��A��#�i ���x�#b�!�K��6�_���e4�?YG_�� ������=;S�2��%i�A	��lC
���3t�����"I<X�8����������S�u���bY�Z���I���$���#���Ljd2'�o0��t�<���v�,���o����]�`�&����)|`���b_����XH&�7K�<X,
Bx�2M�R�F�0����U�v�J�o��v��ws����]F*e�J)$:�>k��������x�Z^��`>��=�����+��[MRHz��y��.b-�D��q���Vt�����5��:�3>���`�'���hm5e}������ ��exC2�����&���r�XmX�Xx���,��na��c��vj��Hk�J��`����������4��F��K��w��v�"0��Q�8
���u��gy�z^R7[�����a�Y� e�tw�����d��\<�����<9�(A��3�8kE���P����=��M��Gp����g����Ll8��Y���D�Nv�n|Er��}��� ��7z&�.��dg� 8��i��>z&�PR��s��o����c�G���uTEA��G��
�����O|unC��TV�����2�O����z�S�"�y��������
���K�%W�����d}�I��Y���<�7}h��1OV$;�P�5Ny�Wkoe~�~�
��:���\q_a��'�Kd~^%������ZP�5�	�X�r��f��:6Q@U
fgUV�FhK>�,sT����~���b���td���\>?
��+_&�����S�Re��,��jJd�V��C�%�MIR�^�������_s�XY�������������oG�FI�����n��UR�Kx<`vV!����R�D4��M`�Cl:��N�l��������0-z�a�J�4I�:Nut�������V"�q�
�@^��vI�}�/%H�8�q�����+���;����c�
����@�����*���c45�NP�c����,C��8���+�Md���
m�����!, ��X������y�-z%���r6��n�[��h:��p����`�
��K�"��x��A�K�S8��T���6���HZ/&'5���l�����(W�q����Ns�G}�FB�1����)#�;���44����>3+��#t������2���Py���sc�?I�S�d�
t��Q4���9!n���!K�L���A��4(��2u�F���X#����5���f��~`���Al^f
���,���G�e���[B�2h3=c�}��/esz��E�"P���j�MU��I<F�V�1,�|�Y2��2C��2���R��n��0FF:��&Lvq���@Be����n����a���=�Lq��5�E�w��19������:���g�]l��g�o��|�����r�Z�;~����XE�Q���{��_�����u��[I�e%���3o�3����8M������JMz�1D�>���.��0�Y?�p�������a�����V���@��M���kQ�`�R`�b����#�C��B���ecx�S�c�9*X�����!�s3O�+ne���j������=]����N�v��u�\����4�{4�_��d�����7���{��p'	M�3(ccd�f���iK���lr=����Exa��l��@fx���
��;���~/��f�W��:zH���H�q �����%����!�������Z8\�Z\�����G���������9�69�?<�%���6����/y�����0G������
=	@M(�����^���<�x����T�o)�o{{3���'���[�o�����0F��\Z���a�,_���'����hT;'y���.����;z���d6�	X�A�WD��A�~x��s�b[,s���eMT��G�,m 4Xf�c.9A���n2'���C�����x�H$��}��[b�JZ>�!�/p��\��r������p�O}������b��k�n&��$'�J�C���{F�G���J� `_��X���<sh�+�#<�o���OR��Y��cs���6�b>���*����>�a@OO��2��RK���w�d��B��[z���.���p#�=��������_nX@v�����H��G��:![##�Y~�*�=�����`p-�8���L���~��X������6�W����*���wP�]�(Sb�cE��$��
2�W���m9������sR�"k�q8}��z���424$jA.#@�b�H#?��D0��6�4`0A�]\�n.�i��U�)g)�(LSM�x�G�@	@`#{���T3�������������8�5��*��&�2���1���;_���R}�g�#��iu���@�X'il��b�M�u�=��y�\>6E�����G��l���4�f�i'��l������H��
�"�rE�%�*��B��^I_��z&�w�%�c��U���ld2�z�_��E�ia����E�X'���y���L�f#@�6A��L�TZ�T0q��>�8����d�l��f���eQ��*��F,�r���8��o�6K���?�~���@�q�O}�~FKhi�)���������L6�|�0������OP����Ze\en���E&ZoZ@��v�����������#��a��P���3CeD�B���G�E���h����d�w���;W�q�)���2����u!9#����/~����4�y>PO*�s]"�Z}�$n�h,�nhH��g��gSX���Ns��h4S�C�~�(S=�^>�Nv&���>c?�������{x���@]QN�����nh��O*`B������~�U�#�')��Z5Dl���-s�����u�����v�#����$�(������{���FM$D{c����_;�����9H5����R]!�;����(���*����Yc��������}�K����(��s�V��������K��g�\-���P�L?��,��`p)*����~���~:�7q��c(�q2
���5p!��T��K�>ot��[va�
��N��?������;5�0?�&��I�\J��x�
����)�� "f������OJ�&u�l�bom-D��FW*����"���,C���+C�pN��+����o�����Q�UET��E/1��y�E�H���c|hQ���Z����;���]��)r�.4D~����J�L�;wc�@p8�S)MC���"���bO�2�+�H���*$��b� �u����.Q��F�������=�S���V;��P��F~��r$)���O�]����?���������0��x�W�,\I�����*4&0�H1����#@8������\�=��L!�j�%@iv���"���h��A��H�h�G���������\�4������jM3��(���-�QL�v�ps�'���D���)=bt`gV%����!@tTD$CF@�@@C��(e��}���e*``CE��G+2��%���(���A�kx�����1��@,cG#���l��2�����������q��CM5�!�f��in9�]@�@�@A����Jf�W3�K\�#|�,���K������
p�FDG@�a�1��hQ]1��f�?CA�(������.T4U�Hg��PCI<����k)���,�qm�)�m[������n����Y�U�x�����%G�e8���)�SdnN�W�������%����(���D�?o�B��d����$�
��h)b�2*��8<SEE6D�S��i�\�*b�8Jh`�k���]��g�T�hi��#��T1m�-����$�����i���t���q��m���7�:U�>�\&.��� di�����u`�
+���$���?�����DMx�W�P����YFi2��,
6<$h"�����@��r���Or�F�0�������=�����j���0���7����&c4���q�R1?�,�j�g6���NztC3�YxJEZ#G�K���u���wL=�W���Q�hfdv%����<��r�������=��V7���p�����[MFP|�.�~�1P��O���&�8�gP�K0����A��I�pCQ].l���:/���ca��>�����U�^V�=��p����g���.p���J+��'�Zl�����5	��r���k���)�|����k��g���d3:�#a�K+�56"������Q�?~CC��������1,���x��e'n�98_p�">�v�q�������z~\�}?�Z3����y3s���=�0�l`��]?�_H_��r,(�w.�|�eg�,����M��=]�4�P���"h�~�n5T��Iv����h[R�T���(����u.jk�l��}��������[��g6���w�-�|v��$�Z��f�����g�e%��P�����ox��mL�v�9z4M�f���Y�(@����{�i�R!���!*����������4���b�x��q>a�.��6�}Gy���tZ�����#�.��m�i�L���2"�6���|ls����,����������j��2"�ve�#��L�������5RM"!���ex_�;(*X�0��F<G��e��y�l�(������{�&��D6o6������w9�o,�,����8�?L�9��uH��������N���H��yx����2�I��$kqf�b�c�\���`�y+f
V���Bs��
���f��aB4��.$������$��.����g���R�������9�@*��������(�SIup����H�h��)��d�D��:��~��86�[]g��i��0R�@�,G��j^�]�����������w��������>{	+:s�F?��W|������ �������a,�]����,i��F� O��aI��y�R���,#P���f��y�z��$�*�^��}C�$.A"*�#aP���Q����wx��%�����D%�\�^��+I	"�m�:�`���`'K	�fQYfX��e6S����du-��$^BZ�SV&a��/2H�"h42nA�Au~��y./���cD"*S�\��,�^��������d��Xh���SS
��
|4���aE�Y�?����|�|��Ed���%[H9�8��P{Q���4���fnvU�"`��J=c$
���W0�4��c�x�S����.)8���
9�S�X��7�e$ZB�{?���e|��U��a&'*���q0t�=+S�J��"�/1�O�C� �{��t~�����T��S^6}� 
�"����j% *:
Fs�1n���'����o���Q&'���24�%0����>����~�Ca�+���9�i�k��d�J�{& $��$=�9t���B|~�8������u�����e>X�4:��+
,}C9f��.�_�^����6l@{�[��,��#�2����������I�$���`�":h�8��n������B"�L$�b��k��J�N�9��&�C]�2
��6�� �]�,�--L��b���hy7_[����P�1��Gx�G�]0��l�2��}��,������?����������I��!�S��j2)�^������3��
���(���q��d��b6�P�����JWW��Z+��V���lG�r�P�}��T��%��NO%��b��$��#�o�[�����7�����=���~p�:L!��F~���q�����UFfT���rRSTs�s+.i��
W��������7�jG/�]S�FF�P������A S����>n�i�nEC��O,~�d������0_��H&cR�p��TTX���.X`���=sV������k�3�������aLkdD��?�arR����iow�oX�+���J�0�&IL������9$����E�
����S����x���LM)�B
��5���S�'�xQY�4(���A�\L7)�f};�<�-�L;�����npm��P����x���*���>�����4V=�J�ACDBg�*�(�F,h��������HaAA������a �`����Qa`E1���"N-��b�gD����j<Z�2ck�e�2��s��A�(X��Y�8��%�1����9ld��rA�Or?�PvrX�����G"�nf~R���
���y��F��01�����bEF��I�k
�\_���X�Cvdj�����&r����������(��B9sX��Ha��V���dJaBjd>k�x�@D�H���H�H�����z��x����Z��:�T;�LO����qbwi���<u�����n���������0RI�\��X�;q4���8HS�$3J5�rc#Y.���dp!�`xw�b�?����d�be��O�����L�QR"����c(&�����.����4jV #V���8�"��c'��y���#���4�$��~A@�3����q�P����b`u���D��;�W24����#��\������~���T���
��f�|h��
YjZAD49Ez.FM���S��2�-������D��Ad��6:L�p=��g�f�%ann����a�3QR���y��e�#�8�/�6�D|����Y5�
e�D��Z���{[���r�P����w������L�qDw)����M�UK�{B��.v��n��%Y��9��E
M���J��?�w�
4�(8�~\�u�b�AH�h|7O�����xg?��>P���dj/�O�w�!����o���M��$�G#aF^8��lP�V�{r������ogf�����$�*;vD����������UVl}w�i�qV��2t��(�����9�X�c����}���g���m���o���,-5���y	g"���?�9u�,��:��z��\>����e�QC����y3Z<�@�������(7v�n3��%/}k�A�;����(>k��-���z�v�y��4}}V�p��c����+-�'*^�_�~���M-<w��_L`��<��,�����T��S��\~X�XJg��������~^�Uq����vW�||y0��c�E
��[�QU���|�I���$>8CS�����X�������9���B�ci�^���
��8I<<��L�f�m�_!G!#����t�w����s�<pt�H�pXg�>�q1���jJS!J��.�7)��.�q�W�>�����j����G�OT2��v����i	������az���s����$��`�"F�)�Ucn����1�XC��#8���)�8u�������+l=�]��f2�yd�M��f6\G/���s��2�8������E��F���o�60a�&�'�`o��R��k����Z�u�.�������? ���~u����Ow���+E$�r���M���(NRH���9�:�e�I����G)��������Am,E�x�&�10���:�� B3��!Or�5�PM����8*��|-�@$H�A�6�4=c�Z&�R
dp!c��I�rA�R"����n��8�~�2��[�a�����������<��9�@�m�-��60F9�T0����&����<�FD����(�v~�VFr��ml��i.�.R��!yJ��)$�t��|��}z���e6��p�R9�=�E��_����)!A�����l41��d�����E�J�AV�4�������"������#�:��8=��������&���`���:;�J�q�$9U3��x)TISl��+�g/m?@y��3L�|��0+8NT,���l�U��T��h�h���R�[(�
\+��3<l�	�V{|-����vR��J.1��rO�J�2��O��g�l��;s��v���D�u�n��;?��?^E�����aU��xx�w�B"�a�M2���VU��*��4>����J����d�N��eb42���q�/y�����J�B������Mk��O���B<n�RE�V.#ix�(-Et:��$>=J	Q��\��f�N��ML|�+����W������4���� K.��Im#�7�m��=8��HP�,!HUUq���^07�2�f2����H���
1����������t��s����b����v-Z:M�R�Z>K�e�Y�[�����3���SgL�"��>;I���Huu!��7m�qA�����M���|��
��X�(
Z$��7������I>����X,WV�m���4������D����wt�����-����Z�Q��{����P����QlV�
7������C�G���l/���P���i�����I,��� �_��X������9�����kp��?�c���N�|p�l6�hTc��8����k�cD4����#gL3?�f�b��PHf��$�b
),3�?{��c��:k{�e%k�F0c�%
z"�c�*�x�dg'pv���f����,�X�ze���Vp`��q$���3U�	P������J��q�GN'������o���[.=�~^�����["�����0Kc4�N�#f����v�0�4�����������T�y7������ �Xp���q��)�`P��7�tw���68��3��EI��Z�E���LSm��1f�9r$���N�����������G��,4�#��CNV_���l��\'#|���q��}\[��l��5@ctT��H�u���?�}j�@�B/�+��r��}ER-�	���"Q� 4D]CMK���M�V�p�"��r�������Y����(k����*f�0�2���D�^�$�;��^$J�Y��s�J�����!��"R�V3hXHd](@��F��LR��$��R�%����K`�1vL�7�7�D�"�'�\D+6d�����s���C��3�^AG���.�J�!��)!��
:"
�"�
�uD���@+�8�"��$]��|��������&�����cB �4hN�M��q���4��2L-MM��E�@�A�X�,��X;:�\ BGAO�����'��*�na��d9������W��9P�ln�t�Tq��2�n���&��Jc�H@���ij����3�������i%`�OM�$4rG&E�T��Q�ZRH�M�	s��^�=��u���	�����l~
�8�]O�Y���?""VP�NQB
��c�eP��� u��y��������VFA�E�[��!�z^(���~d	7
R|�k��AT����G)��,
�F}���+x����38:2���"��A�\�G,��JM�e	��Lu~/��13��G���dz��[���#��'DF	�����L��X������ubR���>A}j�,�a�JJn��cC�*eU{�8Z��o���O���c4f�p
iJ�0�o�����!l(*,g����{/j���;�vw~v�������T�ts����W�RF����y&Ck����F,L��Tk-�z�:�b���if����:�(���d��O���O��Zx*�l��0tm��L�#�if��?d��md�y4U�z����%�019M����RHdc����a�y����A=���Wj�p��2���x�E�8���i�[fh�|����c5������k��'�
�g__u��+<������)6CY��Q��1<N)�x3Qn8�u~�����*��Gqw�D�3�F��,/��w���������%����_��d��1��1_�F8�����_�b=R���������W�2AYt���(r�zVo���Y5y���mj�ox3��S{�v����,>������P�7��X��l���g��YFFd�V���
�v>��,�u�8�@����UN:;�tu%�Z������/���Hp�U.lK��<SPO��q=�D��Nb�wt��,������E�J�bSe/�������	�n����i�D�*�}�����~>�R��s4j2��4"��Qi~�6�����V����LI�R%����������6����~���h<���t
������EM�I���2���5N������h�F�� �g�m�@__Q\H���a�K��^�~�������2�a��/��i������&E'��l����@���������������V?���2#�'�/�03l��1#V�[�n�:o��2��6��>US����5,�J��'�_CB��)��(%LeD���K<g���&b���0��������0�$�B@�s)�@�����n\ldMq�&�i��s���y;ff��#CXQ����G�����cJ�aA�N{��MtP�,b!{��������������F�r���~�������	l��S�4�|��S�,n��9��Bp��v���"A3I�	��CdM���a�$1rg��%��I����5�P`�Vn�i�8x?%�1|Ds��L�f��J%3d���c\���%}�9�x�a������R����[\���udE1H�..���9�(kdd')\T�Q�z4�?l��R8���]���+��|+k������?����Oc'C��1�2���
c������?6�j`�S���l)>�9��?�������]�%�1<9���#J���g����QA�6B��b��+>���r~���� �O�E�$>��3�cVliB6A<e�~g�f��1����-8�P��)S&�j�Hz	7I��q�&��n���?���_���Y����++������b���H�8u7^]��W74�?lm�~o��34(���wU�K��C=�V*��������h`5jTc�`��(uG��gqkQ�8Q�w�y���K/u��/�I|W��~�E��1$�K/���9���������������NL�������Fw�`����f~���}���b�<��Z[K����MW�^Bd�"��<R}1<�m�.�5�f����l���$�b	L�}qJ��f�x-�BR2��Z���K���JT�`��#8�����U1=����>��R�d;�CC�����?��'M���qpR����������l��iS���E��5��:F}�K��^��P���;������;�_5(po�pJ��|%���7�]0�����;���l�7���5V�r
��c�["�sML=�3�c��H~B����j��#GR(�@"���1C��@7��9n�9$t���
Y��U�I��bkh��a����������c���i��0���~�m��3
���!d�h$��������<�;w_:k�}��������[y��I�8I3I���
f����]��$j&����x�0�Zd�I���5���5e�Z<<�-��3'�9]r�D�����=^Pl)o�4G��d�M�\=��$*:���#�O4��{w�x\g��r��g�����K\�=�SM��>l�GqYJQ1Y�s���s�����G��A:m:W�X�$nD���L3�2352���z����ir��#a���x�������*����_2�q
	7	,9�7���H�<
:
*������<4D\9�(�-��
V��[y��6p���y�F<�Q�$"e�&�������,>w�g���Y��x1���J�}��t(��)d����!J����46R����:�F��42VldA���w�	@a�1�}���0����L���MC>Pr�!6EW1rqQ[$��������Gx�8%xH-���\0(�n��,:��w�Z&�<��K���BB3�(^�\�����2��>��a���0�-7��o�wb.Uy��%$
S;)������MBw�!���XL��lZEO�=#fI����_�yj��m��9�(��RA���3 �~�+*62�
�9f����s\�`�Fld_FpA�9��_A����������3F�n�H(l�	"J)�L)��8�`A^����%{���1��F�����i$A��f�1G�o���`�&5L�:��B��a4��5j��!>����Id$#�Zv�J��%�$���� 62���X�����T'��:���C�grY#`!�j�R�� �qd@�.~�����Q�����E"�
��>jm������s6=BRw��r�l�)��4s�����!��j��,���O��:J�+�>��'�?>���2s�z�M�(c?G �.+X����S�/����3����`9���m����T�Y�-x���Xu�����#c��+�<�#�3�d�v��t������H����gW�=�P���";;������G?�O;}�;�)Y�c���n��Rd2u�a��GH=���(�k���5LN*��Z����	��(�Z=���.�m��f��o����b�;N(������V{��x^Cs��n�����y�J�$�����4�uQ{z�6>�X��o�=e6�R�~q������C),�-����s1C�_��������N6��H
�Hoo��mm&s�fI&5b1�����"���V���������Iq�l��|3����+���4�������dp`#���@�����q��l���R�OW�0��E���������5F�t�w�Q�8��*f�:LVu1a���E���pEu���^LH�~��~��t
#���-���k��(wfH$4�;)��k��h��$��'(���L
�,vIZp�{��������(��X�bmb'�F$��
d��m5S)�=|�@:������Wk����>U��k�J
NR4�ah���V1i&o��:w�=���Q���z�^�L��5{��*l��H=����R�9!s^-�x���d6r�������1�^�*��0��0YXQ�f
+M����n\�r�t�k��4���3�I�#����A�2�����f�71�
���[Pia���I/+��R��(��$L��b� �C1��+�0����d/��'@a*X�+���&�

��������r^����I�#JC�q�$���k��#��S�d��'n�;��')f���Y���K��86��'�S�������X���#��M)�?L����a^�x7c�F.�`�>��lN�^��c���P�g��2�t/I�$���p���H��S�Of��o��Gs}�!�r��#c aCFAb��B���n}���bjk���q;��`A�H�,���������9D�V��f 2�%�bK$��HSe��\NcZ�N}��E����W��A.���j/SN�Y��)5�
}`U������YI�g�Ij�g����Y�����W;��������{6�n�L���)��v�L��T�
��8�i��COR9E�vM�S��91&���hw�9)���Fh�L�1�f���������p�����Z�]O�]\4s���!dC�������Q��L�����qq���������4�t���������<�}�Q�T
�nG��b��GN�����������������+�d~�Z�n��8&�����Z?MM+���l�F���4�9�LW^��m���a��y��^.��b ]���v6l0~8��;�P�Q�ozw6�E��\|���0c��A��2<A�n0yELOg�R@���@��0q?����MMd���v=I�r�8J��OQ�O�WD�t�]�m�N�K�(Q�wn�-��������<�Y[kejJ��#NE�w��DSuT��������>o�o�����,��A38�����?����*��FA�=�57�SS������"��N�����B&'~������ �� �(w������:d����* &S��X.�n2Z��_GT�D{qW8V�Fx���mkC����FG����Zap�S��
��:��0oD�B��H�L���c�r����������$�*aQ��������z�f�h�����LO�����{|
^b40�45���:���������j�j��W^Lh���#�����E�a����1�Y�Qr��a��v�@��9��������m������L9�ry�9,��=	�5a���f�ej~FG3�b����PW���}���I\8I�"e���R���3��r���d��m�F��Dp��Ps���!�j�e1l�\����1�?�1�n�@��D��&h�2N=�X�J��q<����xK��<pO��3Sk�m5���I��c��1�"�hq��������q����#SA�,�@f%F)v2�P��p�������r��������VtZbX\E�R�U�#p cEA��T��	p��mA���@��Xr�9��7���:������n�L��
�	�6+�~�2bK�����S}w���a!���[��������[y
5�Z�6lg��R���`��RI=�
��F)���g��K�g���!���1?���O^����g|�����X=U,X���%�dEe=l~k�)l���$��Q��cKQ�����t.��8m?;"PI�M�����g%����^DA���F�dq ��x1p��<�������b������d���g�,�������tjO|��@�Y*�f7�\��i69F���mC����"����,�8Mz5&�@&�')6�$��w�}"�H����h.cFB@_�-����	�f|�o�F�����8n �H�O���x�I���Eon.�����^�>�E�l���O=�-��Ik��g<���l�Zm%�"����8�d=)��2�=��h���lDjk[����L*T�|@�Fu�4�e��D�d��5Q>7�r�EHi'��Jx�
����������#tv�;�����#�k���T|��Hmm��=�z��K.�v����W\������R
���Qdg=d����.)\�u��9&�<T��"K.��j���nc�hAU�_�u��u�88������O~��Ax ���F(dP[k��e2��9:�a||�����^�����A����z�4M�jU)+�x���\��!M���LN�2���)|>�EY�o�VX�r�wE���g��b����A��u�Lsh��L|�
-H�6�rH���0d;�i�/<�\_
�$�����Hf�lV3��x����'���
W^���o�������O����)g��%#���I�\��B�
^H_���n���"m�S�w��?�1:���,y�{.T�����@&�f��p��S�)�ur7�O�D�fL��B�^��;Xn���t/S�B!�UCLH�?V�y���TRPkJ8��(�%5��
i���;L�{�J�����L}�i\���V,����p}�
�kP��6�[A�^��,��3F���{&�����F���x<�O�A����)28x�w��WH�d_nM3�fa�r}�i*	f�pg�"�L��
������"��K�Z&��E����\P:��~."������)�P��L���r��z�����P�1�*�1����r�,$�$�����)���CU�0�@�)�H��9���x�&F���)JNj�Y�'�W��x������dQs�6���@�LR�����pV�ra�f���b.Q�3��U
�4LpU�����n����|��,c�rm�K"�|=�Ro�2��b_.�Q�������c�+[k�k�|)��IL��}!%b?��d��-�#	�&�'���/E[��)�����=�V�s�3��l�l� �����Eq"a�P��2j0B��y!v��yJ��g��� 
\�.tD*�E*��=���1r"8�!Nm��.�������E�8&�q?~��\a��)�@M������Ib�s\���R�#�TRf��*�A����{I\d2:�=O�eJg�u���+�_�q�����j	��t�BM���u2�'�����I��Q6�
aw������h���Lc"�&�"J3<���
���(Zn�T���?Nf����n$��!����#66����OO3��R]������������.�CY�@������<�b-�"7�v�|�D����� >GQ4��M��3;������&�H����o�ZV���4����c�V51}<�^�M��u6���F7�^�����:�dP�@�$Q�"jE�E�����s�����eXW�`p�����\�78*2���,�
_k�Ls��+�:J$�1�:�����:���\�<������ZZ�[[�IM5L7����=47K|��0:j��={��N�%��ZZ4D1����{���.�)A3Dt!���������4��[��k�+�~�}�q�}�>k�v�1uu"�l�N/�^Q`xb1A���/�����Zp�������Dy�e�K\k�j�bc#ZO��<����f�}��&-���3���1V��0�L`F��L���=����.�Ojk;i�z:kn�(+80�g�-�;�[�������������G��h��gu��6�O~���/+tt�<�a��sC�=���J5S�H�$
���w�;^�.t��� �3.^1�����)!�MIRI�4v���F�O
"��<����]*W]���&18����j�������9��\�dp��R�pG�������#G~�3�_�k�\$�2XP���&`nzn�i������g)��^6�
64�$���G��*-���.nd�pka���.�V8j[O:
7��PJ�}\�>�e������=9���z���b;��������"@W-�g��h9&9��Cf��j264l���t����J53hX�+�^"'6.gr��#��.��eFA���t>(u6f�m>L��Zp����qi`,b����b�_��R�0,�����
N��-8�?��l�������sz����y�W���2_��9���6S�G]���1��0�:����lq�f���C�����@\��g�Oe6d��hd�m���:*,�w�����)~_���I��T $o"��c�)a�Z�3T�����(I�"��$�
��42�\���������Q� �9��2N:W>0�!�������#���8*�,5j���h;���	�P��=� \��b�=8����a]������t�.�#$�ZS$T���� v�d�'d~����*������T
.VC�IPJ�I�63�flt#��)����VP���<{��!��5���c$;�J����:04���Kh�������?-\�������V-M����B��R��H�,:s�6���6��1��A�YN�f���Sjn���-0:���I�o�EB!�����B(� ��v����K�r_[���of[���l:+WJ$�:mm�W���)��g8���r������g�
."NgRs3
�K����)����aT5���\I#��T�x+2`�6��s�8� ���#��!57�hG�~A��6���K,��*d29���$�������}�V��2���/���^���G�0>n���Y>������Y[�����%��vTR"��L(bC��96%~�sA�eu���������L�3��T�M�Hd<�8�,�)h���m�k���Q��Tl�0<���s������@��5��q^������2Ic���~����������E�[s�EtU����F,4h#��(��(��0���.�?��>����Y���p��C7�o/B�q�Y�����d�4�����jf���u�0xI��V�8
������������|/B�\�����	����z�E���R�4��Mp9/)SB;����I"�P�l�-��2�F��?���h~��s"CF2T����c�������A1J���W@���IKd�� ���|b�6Q�����
�.J��\^�K6n���Q�c��
>�q�y���H�8.�d)%R 6�t�m)�EA��N}AK3SZ	����,:_�`�����N#�������]��]�lo_���*fyo���a���9�K!����t_��#�<e��qi�j����`.���g��V���XK
7���$�_�-��l	�Hf��L�	�.�_^�u���1���b�b�������B���B�'����������:��r9{�����A������Et�	SB�����/;����1��F�0kxY��'G3�pec����3�
��z�$	C3��� !����������z!1�	z$�>1A���0fgAQ�}�����n@��^[�2��O��ij�1\$����d�h���i�I�|3���C����k��V��>y���K���
2.4�5����1���Xg�q)n��>�X�q:���d��
�v�(�c������W:	�I���
���:|�PU��~���?i�>h^l�~���7���@���)��6x C<n�L��_���F��_�z�d����+�0�q�����������"44����� �z�(<���[N�h����(��'?���Y*"g(l�bebBG��+�����I�p��dR��U�v(�,�p" �����/���e�����������?]��z�jT����pA���!�X,El�b���^z���4�\�[Q�x�Q���uw�	�]������oh�����������y�}A�JTc���#���� c��[|�h���H>p�B�KY__�d2�ah��?��!�0&.+�����4���?�B��<�x�a����������q���.�S������[�1�S��0V���PR��z5#���*c�Kg���X��d��S����N}�U-���G__�!]���6�S�a��[X5L��A�$��a�/X�%%�<	�qq����H�0o��q
/���/��YlY���
1t�����(�d�s��9�k{�6���Qo.$l:���43�n�-<�������;|�FB�3N/YlX	�4�
4���L��+g.�Kn*����)�E�v<��`JP�����F�9L.�	�k9�	?#�H����38� �/��-~[��XZ��)������t� �T3Q`���L&���,�j�8��z*+n��M���/�/��b��K��|���`G�t6�X���}Q�w�%��<��}n�"]�89�-f�����m��R��Ka���/q\��?��\�m����#*zX�u�E-����������$�/�����NFh��qT4����7�y�W��r_����m����/��9�'��}")-�N�3��L��5lXD��n'����m����,	��],�e�K �S��N�Rd����8
8�����$x����?/l(��y�E�XD�Y�T��nH����G9"{*��w�}������EL4Q�
I�U�W�1Z�z���q���������	�8��H�������2z&��A�.sM#L��m����f���E�4t���i���el�j5S~�A|cc(N+�~��^�����mhqr `P~?.�%gH�<8�n#EV*���Y����p��p���z2���I\w]mm}CE��{������:3m�nS����M��I�o~s�U ���������}m,���MfK����_+i�G��'X�����]b���B�fz{�x����V��w�Zc���Lss��Ol/���:�;'x)T����p-�p��*63J=!�Y
1	���a4|�#T�rK��Eab�n�����p����^sUWC0�BU2�{?�Y>��8������q<�Ph"���O�S�����oG����%Y������z:���i<�8vd$4�$(��Y>�z�Xg#6k����B�U�������#;�������qj��[�9FX�aB�:;a����q_Lh<EoH��~�Z��U�������r
{���3�ja��NR�%LN*l��F
���P�����
�$�\�>��O8�zF?�pN|�;�q��+.���W��������lP��"I��u|��a�H(PUj�d5��+n��W@cr���alMM,�����$p�v&�0H�96}=c�3G
�Hhhdq���3�,�b?��SR�(K2,�X��'),8r�fM1�5��_�YG���(�\@� ���c���Eb�r�����6,���$<�h9�IK�!]�C�Sb%1�"���yI�����'�:'Mfp�FV<�R�j�-��;�Y0p�6/q	�(1������{������:0N#vw	.�{��n,S&�F%��������YS��m�;W���[-\���l�����
�������p��I���dt���B�����rY �V���X����D�h|�����~F�4��������Y�w��g�}F�]#id�F^���`��- ��j���@��&�,����6�����Wh���W	
$-$)�v��L�$�`��o�lk�h��>�,�?���h�1`��}]�lK3�s�s�s�}�������f&�K��\�QD��X�0��1�)c-����I�4DIFP���s2�&Tj�>��l9��6����l]�s?7�$i+vMGT�@CePU$�
Q� �AM���Q+��C$B��E:mD)EU����H����i�Tc���|�Q�O�];�B����)��T76-�=;�iT�8(c���N�N\g"a�8�S��Ze.���Sk3�t��c�C��R���M|x�0�CN���dLnj����t�j����Z�����������������3�x�iK��v!���,E�z&���_��<����������E��3����y5����������j��
r��~���M1���c��.���'B��W�gE�i��
���
�`�u����r����^[��Gw�������bA?����k�T�R�������g5����-�y�|��\��k��<i��Je�m)Z2L*�`������������O����20_������$"�<G*g�
�����B:���V�w�����]���I�"��.�gQ��3]$�U�2�3��Ib� k(a�`��b�{q�L!H�k�<0��w���!���b�{���Hc�a���G%�Y���H��!�Y��s)�T��n���
#5M[��:�e��s��&(�Cx�����&e��N"��!
T��xG����E�r&�02������%��i����O/gG�N��n���2��p�D"A��\�dw#��3vD�eJ�g���(c�	�X$��Y>vJ�c���di�����rVZ '�P�(�4�r���H@�tA��P�����ts���_s?"���S��)�	�1���d5�f����FD�:�
:f��@B����%T$tTD�pSD1+|����a#�'�<�e�1������\D�HaA��L�\ B`��<W�'6Hn�8���$z&��"��X������s����Y�Ql$���l���w!�}�{.���D�|������mX�o3����y,�3��@{������PIf����Id���L6�w�**�Ip��d���m^A�4�,S~�m ���EA���y �B��^'�������3�\�(��)���d/�X�I��I�c�s�;�f*�� ��������X����Is�u�3N=���6{�\�)w#��N������!<@-��L�Q0��L�JF��[E�E������#�~NQ��,f��L�B%n�(��f�W*0m�e�t)�'�CK�Y��J����@3�XL�z�j.�j��e���k�|�$@�V�0B�)L�&�Q����D#k8���6����Qk=��(:F�T�Or��!r�b]���C�2��U�;�j�/�j�+Rh���%����������0g����C�|5�~3��&N�J1�x%����)4b�k���[7"�S� ���a8��1�9��`//�Wo������V�g�T|1	�x`������:�|���[o���g��<�����c�l���e�@�����,"E
��B��?�!�`p470��"�'��K(��C��is5�M����$�u
�o�!mr����D���b��_���t]�u@��:�gmmap����f
�������^���}�V�=#��~�01������\�=��N��#����-���|kn����K6��x+M�q��9���y�
���"��T��5k�	2����Y�9
��>u�Rc��C��Yi������x���-<��2J6h��(�n&��C����=���3��any7�����
��`&���%TI�fT�IJ�3 �L���=mGiHyY}���T�x��ud�P%P\,16f`�f����mn���������	i~&�(��y�r~='�t�x��|��[��?��7�c���t,�25�$[��3�����S#�U�M�����������n�[���##�5/q�A
C���3I)%La%�#����{E�0I���
,����D����d�"�?r��G|(f��X�.b-/� �%��Y?UDG&�����G0;���g��!��a���NeC��	-+v'a)��tT�$H�]L��">����f�2,�P�:�v�������?�(���`�qa%r�m�4��'1��X��<?��>s�&�Ic%������]������$
YUHc>#��#=i��
*�QD�i����86�0�c�����|�S4�!D9�����r���l�Dl�Y(8�A2vbR�]Hb��lQ��WX'�����/���.F�ih�H22��T]�GW�19�����s
3i���~�@���T
��(�����$a�����"**�,)�\[����<g��:l/�����4B~���^A"��q�q�L��S��&�Z:�/ji�@��x�0L��	��k	�%yr|%�/�GK�<��f�����8�+8z4�f�^qfk�8�bH#����J��D	JBe=�q%�D%����haQ��������q�ek�F�Ds�������8����3��}�`
��a��o�L�rh�J�Y��m_D��6R�IH&�u������}7��&%H_F��$k����U8��/@�����?�8�a��S� ���GK����R&Uq:%\.�����	���6K���k�#C<�h��F�����<�W�r��C�&�T�Hi��������y���g�,����7��i��hT}�u}f�����iog(�!���O�4����.��g�
p����y��GQU�������Y)�g��� ��gl��{T�qm������b��@ _�8����-��.��]��C��8��fy���&�y@,��n��a����/���@:|���f����SLN��sv�S����	��g�up����'�X�1P�LM����u�����X�s�Z�^���{�t/=���D+F�B!�$3����8t<HY'QEF�2�cC��Hl�|���vM��I��_N��������oDn <X��6�]If�F���A�"m�M�����$v�
��$���
I�N?�M��
6L����+i!����:,���02�,�N�V	�N���*a�J�(�J�%�@��4C��k���et�����,_����VK�>�
���/��+��y��z�i4��D=�j�E�X�d�!�X��,�����,K��R:d�7�|�v�$X���2IN'���"�x���q"�p1����*u�c�	4k/1�S�*�����S� ���g�3��39�����}"IK���i��vAD2���<'{�uf�����U���[Mg3:��L�d��M(Y�r=�;f����[�"
���2:Ca^FA��g����F��zI�6�������4nF�Z���Y��B+l�Q��8������Q������(���iX	�8��i��q��N�`���XB��~P����=~�>7�2���1�}��AJ��iC�EL
%����Z��aF�$��Z ���V�9`��Q�!�� m� 1�Q~�G��g�"��ox��8K�X4�o��X���d��u��D����@���\B#=3E#��l�q����OpU�8� 9?e;�,�L�%�;6�@C3Tc�b"��K����T`��������2����`Bt��_F����$�G�3�!�(Z��k��2��|p�^��*�"b�q��S������u)���o����V��z���EZ�b������������s����R�x���L���0������^���d2F:� >�r���D/j��4e���-v�	NI���GEP$�V�����mX���0��	X�����}�T�+.������u���U&�z�<9B�x*��������d	����|3mman�}�=G�Q��gH�e��a+����#��0�\�M��dY���Doo��*[)�)6�	������Q�Y���$	��"G�[�6��<���������yG�9�������3x(���B�R��EL+�]W�S�%8���L�D]~����n�H�����;��<�W?�������l	���5`��Gs3��V��k��@�Ul�h�j�u���pt���\����n�fsA��~��[p�����-���Y����M�g�^�/?�<6�H"�����q��x����p�5%\�\���=g����IZ[����_Cd2"�����>�O���9����BZ�P��PFG��\�
���������$���K��Os��8"���N
R u�]�Z~��)ZZ\�|������3�r31�2M1Y���I6�����A����r	���qtEAb��]D�M����&xJ���f�x�8o-[fehH�l6�x�����^s��~���LO�P�:q\��@C�l���A&����uuv�S�X�?A�i%C����Xi���"��Ol��?����J?'�45��ZW�����~��q��4��<���Z������d��">zHgt�	�������'���}�1�
YKR��}������E�?#��;>��=4`��,�EC�J����
"�r����SC�Fz��a�f����CJ&��r��D$IX)���;1R�)c�2F�`"L��.(�r&3|(�����8�����.��l��(��n�C���tqv���?S�1e���;�.�`'��F�0�
��7g?9�zz���).����K�"T��XB�a�����\u��n\O��-��G�Rga�Bj��=�9���c���G@g�
��I��r�� :��)f����/_���4kCMW�h�F�.�Z0x���&R	��� {�4��@�C���y��H`���q�����-3��13N9vb�����S�9��{,|�ze��C���#�h@
��q�aN9�sit7vu�`��L���hc{����4������wIfR�$h��#.a�tl��j�gm��`�M[�����R�*�����+�	+��h��.���"i
#]���g�J��eTM�������J	�r5B��V1L�T=��-=c�����<�||���(�V��~�ufzo�	%E�
���/~��O�C�����r-d�mD����t��E�����R��j����(#L�P"*�{����-R�,�oIDAT�����id�I{������e�D4��$���~�CT�r�@�u���I�j�Y��N����������4������wVp�]!z{S�L

������N0�������@���0;wN���8��\����7���{�}��-����I�VQ4������;�$;;����N)����
n�g+�wq7>�f�hlHO�#���%�g.`8�2I�fE5UH�i2�����mO����^3.�D(�ax8�g�K���S'��\q�`0����ic�������^���D��"��|0�u��!�������>�n���P�P�0��dE�r�Q"������d�Vp��S�T��I��������:s�_x����r~���������`�"�l�0%n�l����;U�
����
�����k�8���y��L3i����(�"�44����S����L�|V������8<������VFh�w��F�x��Kna<y����TgN#X,$���'EFLui"�h���dFFT��d�n�a;�i�z
E���38���\��2��w���3@���xW�A��A�����T
A���d�rs:�.�����2�2�1q� �Q!�(+��c�@>�YY�q���$J)���<�����h3�F�2!"����a�qs�&Cw�4�����X��y��9�6���>�AF���5F��������,�����g�����Y�Q�Ig�sJ.bJ-���q[����^�T��&!8��'�+���5l�1�5'6-�U������8V@��4	l@;W�z��G0�B1������P�"jZ#�	U03�W`'F��H�$e�M�'��tu��j�`&2,��k��wA��	�������_p
#Tq)�0E	/������g?��|d�����E.}�a��+j�\��->j*j	���N����an�^��DDC��p�Wc^����S��#(�|��@W�m"���`3U����2��a�����xz���xy�>�"��e0v���9�S�1gk�f����d��VDT��zTYF���h�L���M��b@F���E	��n�_s�G��n^�=XC��u��aS#�::�M�%|_��	S%A��D���e���������,��Rm�~���W���/|���t�;�]�EJ�3]�H���7C]U�����0z���?�r�4��������^��uKy��{�a�TVJ�O�����O'�e�u,�zpkS�+�yJ��S�"�*>'~�2m���P����-^�2���Jk��}�����!��0/�����9\����7���f�J���~����N�oY���?�����o�;��a8�m�����U��G��������^�}�z���I��D$�br98R��57^�	�|��CH�����^MI����Vp(R�����iu�����=��-Q_o�;�O�cl���� ���&��R4|��-(��}����[�xL�0���L#+W����j��.3����v��*v������l��p><�2����5Dw����=������'�+��$uv&g1�a4���������?�����\��]��o9#��x�����nm����g�d+Z����`b������	����_��ZZ\46Z���/��OLhLM%��f�x��)����y�����uuf�^3�B__�zz���a(+�!���:�6�����v�9��0{n(�N[�t>��^n�~l�Zy�����,�Q�R�8%<��<�
�
G�q�;vT��\��9�W�[J��[y�{8�6�b`�p6Y�^�@..F��&=8�d�a[�
���~�I��8�X?�w�4���W���/~�e��X��N/w�=��'6x��x7N}�S4R� W�8���Y�7�@�D��k3���R\u)����bL���::3���`!��n���Y��9���������mV�OrR�1������@<�z��4a����F�vt��"���Q����>Fj$���� 
aB�����lHtF�bT��B���Y�hf��L���O4)���`�T0�-�[(_�c!�^b/U�d'��&T����f�z8Hb'��QS:r8�D�����0���;Hf�w����	J���%�8'������\��`S8�!$%��/,Ow.�{5�&�X��Wc�B �d�UvLv�S��Z�������4��n��nl�
������f��0!���!�:�(���z0F�t��\M-�������� �`��}1?���(�\���q��<���1F#X�����	J�X�a:�L����q��������){�/��$���v�l7f2�H��NVp�4f�������Q�p�����22/��r�1e�7ELe+��\�K��f�m�nN��3Q'�q^�"6��;���>����G��5��Q��Qfr����3�'��������l��%��}5/���J%iJ?��#����9�I�,bT��c	�>��?���/0g�;�j��A�2�q����V�����1~'��wp]�GL��T+T]���>�f��.9`w&k���.�r�t��A�M�e��I����c����|�k��+F+
Z�(*�b�kC��������E��b���?�,�[��z=�������)�Q}����H���y��x��%\�X��7��H��lU%�fbReQV����8������hj��}�B|0��M4��,�c���T�:�w����;����������~�M��'Lvv2t�Y�k�-|�����8,�����]Rf����q��ae����''�y�u�9>����uu��
eE8`��E��#����l`��T,�,���IDI������B�)l�������qGU�QU�Z%LK<�{#�A���[��(�g�@�?�$�T��4���^�yp���\�]77SWg�������N7~F)c� �&#M�b�RUE|U+/,f���aOO2��9(�c�p�I�&s�w�8�%���d2�5 S)Q4�����i��l��;vTs����\A{�N��D��(������m���R;�O���B} /G��[���CId(��WX�����/%x������|�6c���/MI�LU����$*���������K�`���n�"�[�c�<���
GL��<�<E�6g
ky1����iL�@�E�w�rI����C\��^"�>��Z� �JLk%8��<�����f*KYz�Wq��b��(���4]�3	�	�d#���� �K��R��
��@�&�i�0��I�JFX���z\B��L�������M''�+Y�=W����\�&�A�'Y�����np_������&�X��`A���\�e��L�
R0!�e�P�d��|NH^D��Q^��S��Q������`E4Y0g�z�U/�XK+�bI����1I���HPF��CV����p�1�;�Vt����Z���By�KD%16M�Md<a�������qj$��h1q��Q����G�'�����X�b�UC*��|�i�}F������Gt�A����~�]M]���#���:���+����)�����{��4R2���=W1~�$������I>��=DJ���q������c�<�������"!N�R���Mk���m�%�������o�wrBm����;o�������N��u����������5���`O���-b����((z��K#L1Oq�q'mvrH_�L��0��r�;l��-k���/���/�����O63��~*�R����tQ��T���!��"��q`�KE��]�n|�/ �������(���t5)�"����i�9e
��H,w
aZ�n��
v�
 ����;J$���L����K������^m�dL��
vn�e9`��}�s�?2����4�;�M����e��;8z����Ec�RV���c��������7�����	6~�V����'>��R���1������,b��	2����l;(�����|��
<��8����^�������h���Z&�!��������1��d2�������;Eww���hT�oi�����$|�
`��cT��A��7P�(x'+--�����k�����{�*�G�.��-�N���f��	FL�0/]���81��c��
h��
��N��4�p��=l�]��;����s���,�q��u��8'Qg�����
�����VWg����e��+p7��������V��x�v�`�;7��xc90F4����b�<��$�hT�_>�P�}{>�!�������-8�==��~�8�R��8d�C������r)Cw���}����&����i���*]DJ4�m��t�6�XI���s4s�u`=�x�>������>W�������b���2�&y��3��4.����
���-$������'y�(���%1�1�'�K����@�P(����y�!0 �r�-��ib_��h�~�5���*q�k��<�
6��K�����#V�������~����T=G�2K�df{���&�(1#
��o^-)Q4���������������R��{��,���d2�H$���p������U�*[�F2d��y�q9��)�T/�C3��s��0D��@$����O9��D���Q�1Vr1���h��,���������<�	f�)�Q�W ���'��H�c�Mj���NZ�����U�^�����|��x��1��|c�e�+�i&A%��f��)�&.�p�
id�$��v!K���E������P�J�f���X�Q$��3�93po�dtME�Y�A#5�!f�cb +�:YC�]Fx0E�6�ERH��T#����yp3��p`C&=�Wk�*�9`������]\��c!��\"K�����[knf��9c^�p�b%���K@�F�0n�D��AM���iRX��e�<���%��N�K%�����uMY
tm������),T3��?�B����%�	8�� 1D
���z5#LP�e����y)1�a��g:��� ���4fdYFPf����
����!�?\�/������*�H�Q���#%�����|��yjdG+og�����`��J���}:�������k��4i�YW�����J������&^H\�@���-��$��>zQ)c�9D6;Q<j?�Y`T�b�\��@)aN+��W��t�C��TT�qgg�/�?/�r��^v������������IW��a5��$Qq���������2:��/��"%g<�>���iV,Z�m�!�IX�����I��E�L���T��h�I�'_���JOO#�m��"^$q��?�!z4�M��0�Qn���m�tv&���� AU���������|�QF�lTd�Uw�29�QR"QUe"Ls��F����L�kse�N���PWg!L�o_�-	����p��no9�=�������P���������#���yI'yu��9knv�����_�e{�D8�������r�0�UR�_����`�<a}������"�����%����:��^��f�7;��JI�L"�.YLL^����X$���"�q#"� 3B%�f6�8a��E\yF��Z-L��b)���UWS�8U�i��n<��b�xp���*�����~����PGU�����(�>�.�|@�'����V'���LQ��:�V�x��(���6r}sG�e�7f����LZ�I���g�@��O��#_G�3�x���8���3���T����-M|����������?p2QK����2E��r�`0M&���h'40��VCK����R��%���^B��"�FL^V�����$��SS��-�����a���"�e��|d�4�n��/�����f��RbG�NP���rL&���������K���N&�Q@�%4����+A��*�L�.R�e-/� J-D�E3�c����$��:,B��
��2���KJ�"����R��+y^���Z��~B��L���/�q�4U��x�f"�S�(:B�0���vL��;���@
�D�4
�->���*�5*�u�mb&�(�X�I��9�$mr�(%�d�L�}5��x�}������3ID`HZ�������l������r�U$�-�6�mW0���:�CFA�8�-�B�D��8��a",W!�:�<��o�F������V��o!���H���]T��.v3*�+W��/H~�Bg�Oe��U%�8�Yq����n	�x#�u�?�����I����2�A��XL��k�w�`Ln��RZo�
Gs3�}�0y<D;:�����>r1��~�z{/������#��$SU�"���o��F����&��B�C�2����z�V����{�s��b����D�;1�eR�:�4t��g��|P��<E���������i[O��_ �i�$8�:��	��|�8�[��}X�{��#D5;��9��"���K�i����$#j���I �������Y��!��2��'�����h�,��G3WQ��g��(���Lt
�����u{i��Y0U��	��@��&�g�RpHZ�'�p:%l��W��[��@��;�lm�n#�;��UL�����eVn��jK0�o���GB�L"��7+����;�+���2���Lo���c���e(/7�u����(

�������
�����zZ[�����c�C�:Xv=�MN&����I���v����.j�����'�}��^|	G�����
��3�C���$Q���H��~������I�_	h���|�"�4�,�S�X��g�.)�������1g�k�����"4R��v�s� �;�fdND��Os����]���������������\*d���������{�P�$��%�t!�8�
~/^M��
>�����[[�����1��!�:E��]neb������G{�|v	�p�`3�9%%��N���g�#�6��m9S`�����A�]�$ML`��q)���I,

�V�"����F���0f�������S����{�����Q�{��SL	�$6���.3��\m��P���h���hmf�m��(�@�8�W�&q� z2+�&8J�^]�{��������p��lq���%8���� `v90�0y<(����$&��p�8O���:j�y_�F�HQ��`8@{�jjJe�a����]S7��1j�#U�4���q*�J
�����d-zV����N;q��IQ��l=������IO[�j�S�C������H����8���c�p�q�q��'�H�u�����@��������|��|��B����-`&��$b����Dc&F�u��}$�Vu���Y��q���
�b&���#������L^C��h�9��=c�����)*����PK�p,�d��z�-���i�\@@7�3�3���w,��+���~����-�RY�$��� ��K���s^�me����i���� �q�S�$q��2��0F�bv&��{5-����H����/�e7�#�PA��[3�G�F{I�H��t9&���Y��N����������LL f�1�,�nd���H�F�J1[S���`����`��$��n�����8@\.F,�3&r��q��X��"�����;6}���CTS��L�"#��v�bN������kH�&!/�T���r��_�	�I`��<2�&���f�I�������"S��xx���.7��F$�������()��7�+�1�'p�%�d�Dq���T�������b"�b"�5T3� I�@Bs h*�L�{ut��Qs���ex�!DUg�Z�t�����x�	>(>����d��ho/���8�,+��9�m��p�m5���2��c�v;�2�T[[>+��3I7��o�������B�B��d�k�$;��a��(��x�.ce�Jm���[������67���I��"#u������&*�tv&��h������E�1]T��>�����Jm�!{v��}��59�F�E2����h�F����
�Q�����vE����v��u�_����n��g�ACN�������F[��p-���[_u�������+���r�]!V��s�x�LTUGQ���(��O8Y�\��t���"������:;���9��wo���e�6�w��R����]H�K(�U�.[6��5&���H.�+2fr39����`0��l
�5��J�^��4�X�d����C��o��@���i���8�^q�I���*�6����JJ��y����u���n��?��Z��b�Mq��S�wPWg"�p����k��Y�u�����y:�9M����_.B��h�"&e/��v�S���/����I���W�Y$��kQ|x����uKik�brR���8 01�"���&&&�y�] `5�������o����h�bw��\���r ;��<�=$�Hn7�[�h)������a�&���
E�	����4����w�N�t�k����a�)QY��NOO��}]��$�JW���X������V{�v��J_��'6r@��Z�q���	V����%pU���Rj��)W�	�e�i��SF;6-�E�2�XD�Sb<���YJdZc����]�w��\��� �%{�|�%�!���`o
��*����S������$3a ]�-9F/~D*��J���MX�PdI3n�%);I�� ��@�����K��s]D����8�8��4.�L�=����.���hT��$���$�����>�n�N����@����&8�x'��'�E)
�������Lk�$�i�"�q�'��y~���1������L����.�����6���mW������.�����x��8]������e���������������V'�[�P	�7�=�4��gG��3��3�P�!W����������MQQ�a��V��7��.�t����o���W�7jH��XY5"�P�a)���V���=�8~W��.	�[��s��v�s�{�5{9��������T�M�7�|���fc���Th�S�g��|j>����;�Q������u5r�M��=������fv��BU�3J�|1|���X7S�s�Zz�sP�M�,�F�k"V�n��������H{;���d{Cq6������I���<�kZ�L0,{��u���\�F_�����B��5`�wn����j��*��
8
�|�;��j�ttD��I��������l@�]�P���w
�!g����_}6��dg����uW^���_n�|�>y-Nrww�Iw#�kW0��������"V	�tv&��
Y�������v��X���;wN��������	��d���d��_\?S}�����#-�x�D��G������	/f3���p:E��m���x����V7���>��� ���|���HC����z��l^�I�O�3@T4-����)��8iY�IN���#�v��k��,4�9��y�[������a#AP�%�;����������:b{��e�K>���c�>0K��bY�������Uw�2�������D&��S���5���J����v��kp����@�D��F��}��..F��Fr:)y�;qm�������O����G����eCvr�O=����[=|�?��]7���n�����1R���[�.]����������P�7�h�LF��=]�*�'x�'&�}W)�=����X����hoo`P���tZ.w���`���-B���B�J����FC�$K����L��T3���� q7���x����>����i�)ApYD�-��p�l���{�?�����P$�x�����,l�Udc��w�����9#���D�H��YQ��`,fQ@,�#o�H�A��6{+����]�z���Z
�k����<�.��/f<3��V@p�b����D��I����	�u4m~�@C��4� ��I
�bQu�_f�������R&�$&��h���,%^���|+n�@~�{H��c%�C��P�I���`���U2�,%�	���<�H*LIf�P�����G�6R�8�g8�f�8�f3���I��"�R���f��K%����#���c� j�2�%��A,���)2i��!��Z�'I�3�d1y���%A�@�F}K�?�G���kL���96R���-6��J�{�j����T�� w�x�&���
���"n*%�l����L��QB�D'�E��vG�n�>��(}4O���)�x�f��ZL�2I�>�� ��!1���	��T�K�DC�����U������dc���\��#J��f���s��2��2cO;|8���n��"O����a��-<\�y�?�]\�$���(����To����"��#R
n�
��
~�W�Qd�����-������b�?��]���=���+<��+���
K���$�2�+3���G�u���V�J��c����%�,n�%�. tA�Ta���fV���������
��w�5�]>U����l�8bjRe�l#O��U5$h��������+�C��Sfz*�fs�,��;�{n��@�Zp�
�b�r)���l�/,�7���fOuw~���@�H�8���oac�5IU��N~�]��l�D^{���6
��^��I��,������A�F	�u��������3��LC����p�:�&��8v,�$��,�x�2��oh�=����,���@��m��������a��Mx��,�>������W�tN����%ya;�az&e���N�w��A��3y������>g�@���_En���P%-��=���y��;���~7��|��$�A�P%M�J����k�O&'U$	-\{mI^���N9��P�y�����1i�cI��J��>�"e�I���
�f�ZJo�2�����EL�g����c���;��bW��u�����)��+���C���"�\��A����f���n�����L�M��nR�fl6�bIf���)I��j����&�rIy ��y)�n�����J�qD��
0`�s(z+�CZ��g^�B�T�$C�,���	���p�\��^&�J�H���UP1����rJ�	~)\���u����%q��e� Dn�v������:�D�/���]Q0�3L������sZ4�{�6�/��5����eLO�$��Y������r�����z
K�Zy�@	w#������W�eV>��>��_����d�{��n�(r��n]O��2�]�����H�$��"�[�a2R���R��&�t�(�R����W�#6�f���o���[y������(�}��%�IZ[�l&�D����wO�`
���������$��@�i	v�����Z3���V��/a��k�E��G��Q(��������KH���.��~��*jj������ndy���F,r����{�n�B�����y�,J*��h�'x���{F��U�p��(��j4N������<9����1��Xf�@��
5�K�i�{�;����������2=��A���&��ww������d�ea�S��:�f�Q����$sm.pT�����f


E�_����^�k�N�{�����]y5v66����y�\���G��;LGGt��������\�M��Ym������+��~��I�al���o!���B���Y'r����+82v	��2��`2	(�N4:�%;;��U�m���x�,r��LM)�%}�[�Du|)�����.���2�����Y��`�h��R,��T�]|�z�YK����W��C����oXF'���H
3L��W���Q#��r��rQ��q�Y�����(��f:���1bk��awwj��7�)����1q���������n,*WV��A<��4<y��u�I�s:D�D�-_��P�}�,���K��)��S�|�;�g,6nt�lX���K��zy-N�N����<�4��Z�w�A:��m�j�~���P��2�hT%�1i$�\�G�[8��chh��n���_N ���nnv0>�����9�h/���h�f	�[[���X|����v�6��s#w�.��V���
<�k��}]�O�h5=�ou9u<����C�K3��a�b�,�����a���d���d5b��~���F6�e����K�T��DY�����t�����vdTR�0i!�(H����P��2-E��fE��2����c�6Cv����%���a��C�����,��"!���.:rx�a���YO�l���=���<� ���[D��>j�#X,f@GIh�:�

����Z'IW ��1���������:����QS���X�*�������$�$����o�x�22��(z<n�}���)�%�GY1�4��0��q��%()���c���|�/4�&�	p�zz�X�)]�%y��q�4�1��b����n��Q��I��lMM�ZZ������&�`�Q�I�g�^����4p*�o
F�<9�=���)���^���4�6R)�o,����~�&������O��qp��V����a�k�������������q�$����LB�#�� ��1�����o�:���@5���(2+\��>bo'��2�,��"��0�A���4��\���.������V+��MFI1��2"V�������0O��1Ev�����m������q$��$���2f��Ud"��!k�t�\sM)����v�� 6����={�]�=R�����wM���V~ZL?i�[�q�x��d$xJ��)��w�O"[<4)/RT"����4	�����
��[��E�j�=��Li���fs"��h�L�>ldz�
��Cx�������f#k>���������������<���A�\A���>���� �`�q'�O�S?y�A��<�p����0��!<���D
\M���4�h7w��f��.�X�4��w7M����j�����y��\����P����>��E��tZG���)�ZA@`�T�=���9�
����^�`�$�\L2g9f�o�Y�~�H��
r:���/��foI���P����Ekk���Sx<&�^�<0�|�
-qWVO����\NB�"�������_7�qnk��T%��UaZ�yW��
��(_�r?����m6�����9��$;K���B)99@��e%������
�/p���k�K�3c��if��;%�.�4���P�}�
����u
����j)��3�R��f>{-���s�s~���=�P>��T$L��3�?
���O��DM���)�pXA��6o �@����������ss�����'�v�*E�QV��29��e����b�����|l"��M0�����F�G�����dlL���cj��eq��:3�,����E�,��,r�
e��t����\*<�9�J��z/�hG�$Y�2�Z��j`���O}�2+����/��P���;���qo7d�,'����������N���t�v2�����vQ��E��l����P-�O���O39��L��\R����/�s��Q�E�a�F�,��1��S��3��z����O����O�����W�MQ�b�9���+4�����m��L���*���� �l��XL!��X�0)7����zf�l^Yv"����-q��V1�y�[R�����XJ�^/��FNm�=���K�h)��2������I�v���A�5$*C����4/�8�M+WZy���SVfZ��s�s�g*t�s>w�~����2���Z�D^�w����C��\���k�����������k>g��\���hI�
${����3��X.s4�����7�n0����=o�����:��Q��e���\V&�z���q���<{�X,���s����z{)��
5yU����\������>�A$I�b9x0�����e����\NM�$),�WR?�ZVK�QM4r8���Z��@������N�=2
�,��p:%�eU`&�iogr�.������S�L��[��P����lz����)+3��s3�����a�M7�o_����f3d��|S3{\�����4��\D{y���Y���Ai|�5 �n�����o��s��~�I�F"���|f�V:�����,�D���r}^�/F�>Cy�v���n;O<���:3a����j.�E&��%8�sEb���+q}�C��m5��$io���CO���/�)��~G���($�L�QYlG�px=A�Gu�D]����Cn�{LL�GL�dPUI�C�����
j�����Y9�,��F�,'�)��.�1+S�v;����_� �$��`0��Eq,��/�<=�C/.r��e%���Q�zNbh�H��"�x9�K�p��Su5Z�$6�N�}5��n�AI#�LdJk�F���"uM0c1�,*QpI��Mcw�\�4��<���WrIl)%�8�,0��oxfO-E'���q�*�eX������71MB4L^W���}0���dFL�`jp��o�����;�<:�6������Kc#�m�0��������������#$�(/�I:���0�2H�*�h'R*N����>���5r�_�2�P�kJ���i��$��2>�/-h��	�uR�����^Z�US�d,�i�m��6=J��b��k=�/���".����x�`�tt%c�h���
���C
*�����d�cI*���i|x9��41�8D��U�h[�8�t/%#��t'V�
l+����:��j�?������VL���?����tw��T��� 5�H� 1-�Q-��4�	.���mW��z6��m�����6���������"5Z}��UY���#���v�7/mu��:]�i��=^����}����|��d:Lul�j�����m;Skz]qX5&v�b���q��5��b�����#�)Sm��)���s&I�0�_�#��Zz�1=���k @�w�3o/��-��O�y�*�A&EX,��E9r��l��.V��UF�#DvM���t\.�dR���R����������f���B�Z��8�/uK�X�23�_+��p?������p5�B]�T^N� #Ih�r��z3^�����S����7����1x������u���,��w^�?y#|bk @�����.�,���x�}��[p?��6Q�xL�B������m�36�Mt��:OE�7�*�V@�"o�r���Bzh�["������[n�|C^������|�^o�T��<3�L� ��fH��mi��u��45X���^��j�Sh�:�C_������Bo�
eh����+� p�]!FG3TV���2��� �\�����o_��DGG4+/ P\,S_o��]���{�����d�c��X5W���������r��������sN��f
��4����{�e�n�x�QdP�k�55��������}&@:h�T����kO��<�c�.
�+�i�W;�1���������k(���d���1�V���^�	C�����F�?+�u5b�h���U�*����Cw�]x����1+�����mQ*��2���9��#IL&�U�l����_���[����Mx�/G�l��.W�D&�R^n��_���a�_4����~�K�G�x�X)����X���Ra�@���R�^��H>A��v�p���F��o�=:;�����'MOO��&�9 ^+�>
����O����,���_���/C*e 3�h0���7�_�X-)���4���������/qy���FU����P�m�r���$:;1��b���y��������D���n����}F�|�����_`�^��A�u���$C���������������\�ns����v3�������)����������gZ2�-G�4�b.����V��"�y�l>H�}��
���A�3_�r=����!��P��\��sY��M�^J�m��g�D�B+<�Z��{�B>����b��38"��J_�!���I��"������w�y��~����/g~g��/m7�A�7�/��m����pR����>��>���z�M�P����������V���4��*p���c����
������2���� ���h�
@'
c]��g>������p�p
ex����N�TK��q����_V���5�Nw�}'�9�l�P/
�,���)Cc9+��U���0�%��N`�����J!��Q��;y|������N�S|
�j'���:������L�����G�G��b?C�����G;y�~�������]77SWgfb�JR}Nb�<3SpN�;M�����5��a\0��4������)6����y%��^�������}���c����@2��
��"���45k9]����~w���p�E������ce��v�/�h����NF��1���V��h�6R#�b��qK9��V�rI��[Gx�n2��dd5��r�%4�Wp�2����Dl���,p�Y�i,J<��.eESl$�� ��C��"�}�4��IJ�0�fAG�*��*����'_�G�����a���"AJ����������S���|qn����>���e7#�z(N
�����)T�����)���M�[���>c�����>`�������[���"L�k���ij�����:��$1�|���q����	-K��+��~��h��D]�L��
k0��"�<���Q;����Naj�>,�6�j
[���t
z��lyI"�8���0������OZ�n�>E|�a4s�NmU0s��Ow��V7��z{S8�R���#���5�����*��:�>~l��E+��D��4�l]�esj��V�K!v�S���n��=�� �P���0Ut}�n�h��\�(������ITm��-#�F����<����$t�]$O�D��F��H9B����2�rv>}bwkk�`|�����-	�������LF�?�c�
�:���,4���p~�9�����t8�F��g�W��[x`	�����0����m��-u�Tw��$o�?��-s�u�x������l�WJ�-LA�r�J���oa���s4��Y����r���S�����}����Y�
w�1D��������flL���H�tzz�yVT�-��W�����������%q�w�s�EjD�2���c����F�n�pXE��Q�t@`l�`��Bl6�,���^|����b0�����������F�g�C#���T��K'�������Ngg��+m�;[f��`��h��>�zkU>0�s���J�����W���+d��1�|�sv��?��g��F��mn�K�*D�J�Z��W�.��O������^�������!24���1�s��y�L���c`�ilw�a���F"�\IS�m�p�Y��f����s��\��Rk>�}��xI=��O0)���Q�1������^q�}3��1���n%�?�AY���d�%[��n�`-L���4����DT�/?{��|�����_����%���<���0�6�����y��^$���m�������"�I.t�*�l�o������-E�X������(��g�����k��rv�T��������29��8�N����L�O�?~e���~�,�	#���h^K|�;9��1�HKa����$w��n

��e,C6�����2>��Jz���1?g;n����/����\�)Z�D�4$���5���O����+*�L"��X����[o���s��o�(�b����t����V�{���mgF�%3L+�(r%�
<�_L���$,q�H��8����]K����P���������H����l�uufm�c2<��1���$j8��?�
������y�t�Y,_���CxZa�r%���q��qzk/'��F�|z�ch������
����(��>��j)�3nk S���L
�������������S��_��Se��u�YY�r�M�y<���'������R:�rz����U�WH[��j�W�d��]f����8��<�,��25
��>@����5C$�'B���;'�����������*����n����j�\�n�������"�K3���h�[8t��<�l�tZ��Z����Ti��6_/C�ajJ+�������0����P=��?^;��{-����S����LQ��V�����Jy�����i��&������h�,�/>���o�x�9nkC���b7�si�������������B����_��
a�T�/�WQ���l�������%����s��@�1���`V�u���z��W
�V`���I��\��eqK�2|g��<���Tw7���h��i��"����Y.�0���w�}����Y��loY�}!��-��*d2:���������gr��@���L�7:e�l�j��o(4��}�2t������[��6�s���i�s��j������
l��B8���3�<�������+8�|����4��	\.�d��I&'���YQ�Gky�a}��	�����(U�(�a�#�/�?��k��C	^x!F<�1=�
)��B���iz�_�qq$�A�={�|�;����:�6�K
�B�0<��j�p:
6L<>��{�,�WZ�N�~w[6�z��������7��4�c�{��o�Ad��</[�����R��?�g�S���x��Rv�4~������7,�L{��o]��]O�t��v�R����l����j����\��M��������~��G$�y!Ty�kv���������^�x�<�T��z{�3�"��>���/�k������B�7��&�H,��Y7L�Oqd����ML�1���B~�+e�<��w�@�����Kq�%����B�B�N�H24d0�7mr0���z8�l9u�(`>>�y~{�T�
\T�"������WK��<D��A�k�`���H����p:%�Q�HD���J��?�����BE��l��b|\a,��a�\�h���O�V\�&&��!q���.%z,�Z^��F�S�V+���)�����q���vK�^u	�����-���@.I&� ��E�s�Fk\����<��9��l�����X�It��d8q�I�^�o��:K�N>/ry9�$a�� ���a+��r����q��~u4� �������+�Z��L%�=#Ws�D"A��H��7)PZ&S�x�rOnw%Sv�O�����qe	6j)DR\--XW� q� WU���Gs3;wF����*5bKNp���a�������9���z_���H$T�u���5��7��o{�����lb/g����(�*� q��r��y��ST�~i�JJ���l/~���~F:����2�5j8U�������x�^H���{��*G&WP9v�fL�(g�^��-�[X�����V�����=|M����}��~��Z^�'��Mt��iY�DQ����"zm>b1�����E�H&b��?�77,J�%%S|���:��~9��1����k�V�uuX��(��p.nkC�F�U@t�X���k��R��;N|���v��Q2��\�c�FLZYWX.tQ'�����$�:��SY)���L��W:����f�[�f�wsk�)���p��;'�����
�rIy9����X�~$�k @"�F������'����p>X:>���o��z!�taKvv��#o+�=����Tr�m�L`6�yM�?��Qrpf������^��H�	X�@!�T���[xz-v�q,�������v�|&��@�����������1�����m�< u�����g���7���� ,��B_{�]O���O,I_����9��P�=��q�E��,��S�����&3LK7������7����Z�P���l��Q�=���Y:moD0��\�����io]����7;8����S|�?5���.���f���5$����o?�klN�f��`p5��������)5��g����k�B��|�X�5�����)x�z�����K�����:�����"�n��O�<�~J(^����gsv.~�\�FT�]��������0?����!��$*��*��r��x�/~���Vw~\�=a"���:J��{�(���h��_�t�*����iN�!h�����"f������d��-x<r�N����5�s�E��@��u9/&���8�>���P�V���E;���2��i����RyZ��7���t?���c���.��}�a��(NEH[���b��$�����Dc��\��"��{Y�}1h*K�������8���@�@O9���qtUE��H���X����;�$���������C0�0y<g]_��Z_�>=O�����7�Y��=�.�����>�A+^���_���XV<�:���j1��!��:/)Z����iw��}7�'��T^N����c��������QEej�N��5�O;��UJ��d����e3efE�����b���Y9z4���z&(��)DZM(�`�Q{�Z���9J/��h������55�p8C�l��*���y��&���Z����-qe`����QC�?��v�d�Q�y�b��������au��o��?��k}���jN�#�2������q��{�.)1�	
Q��J��FG3��z�R*Z�	��ASQB��|;4R~����h�-�A�:+���3�?�1Y�����rE�L:��r�&��?s9z���v�==�d���:��TB6k�����c���%|l����?M$���?h+��v6�m�����Sz�u�\t4��Iuw7��{V�?�����d�FG����k��d��<��)�sv&���3�?�� ��I��R�G�n`��-gm��p�WC���e:�r��:=����
pC����|���o��o����]X[g��P��������g���-�x���������:w����I]�y^�o���;�:��<��_@h�G3���(n�d�Z�6���C;��
e8p ��� f�@��a�$�j?���E|S�������s%�����u��^$��x�����l�{#��j��govp�O1���L�v��7�^�o?�k������w�$
P������W�o��2��=K&���B"
����
�/��/|���>&���\��?��p�&�erg��k����D�]w
s�`�<��~f{{���;���=#)q�
�yv��gQ"G���$Kzh��K�����_^��������<��g���QB�4V�����-�|����tr����������:��1�~:FYY���Kj��'��7�U�kw?w���G/;w"�\h�U������p[�!����1���Dz��R&(!)��p�?	�*��x7Z������wR-Q�I�d��Th�0.���t$�3'���W_&Pf�����5P0�ug�n#�m���B����g]_r���%1��];���
�S�|�����"���"���)>��*v��d` MG������8�I���m>&���$E���c�����kf�J���tJ%/��t�3�����a@�X!����PY��6k�30&2�(
�H��R�C�#Ajr��":��F�%s���twW���y���&V����y����+��}	c��������zo�����7�����<f� ��������5�b5�p�5ln��/���Q���n������I����*q%]�
�}x�fN�L����'�uuf,�[g��1Qt�I&��d��L���0{�r�����2��qt�G5a�����wF���=���x��=�f�����3���:y�h��D�
7��/�dB�d
���0�&����#���xY9_cg��HD����������������o:����7�Q��N[[��=�d������d��I����w�j���n#������K��:�����D"*��i����<�y9��+����"���������C�����C���|F~,���B��m�t��3����W����F%��v�;��t��n�vam�	X#@�7Z3��h�w��|6�l.����z����R�����e�g>a��ja����V��m[�N�(�%D���E��c�b�o�-T�8����r!9���(j$�G
f]`S��7*�{��vu�.n.�{k�[=Hr���3��������}�L��Y���U�����+�O���~������_M���v��^������0�CM��N2	w�9���W���{����.T���O���������Ql;��p��w�z���0�$R)U�))�im-�{��w�tz�tZM��Q�������2d2i��#T�u���������j$B�������zx7�Iz,�H��1����A��x�5���%���Y�l���,f/���$�x����X���e�Xtv&���E��(�?�'=�,���B6#�%0~��D���T9r�>T�(��n��z��4�������w������+�>|����j�D��������}�����\--�����~��)&�:�#�2��	*�>V�"��8�^C0�H8�b�(������tsIJ��YR�-��?|�4�����}��}�w���X��c�5 ��<|�L�1�����-��L����Ug*2�8|8A,�~��8,h�������1�?��#��X�����|��u��t��{�:�S�i�
�}�S����t#��~�x\���H�Xa���������6N}�+TN*0����A0��|��CLM�s�&�Ww�oO���$�����V�v�5��As�9�F<���0��W��������vLUUk��n��E���@.-%�J!Z���"����'Q��P���.[��[�nY�:��������A���l	�s�0uu��s������i.��P1��,���J�E��z���I�~��%0��ncciA�l�d�n��2�h�zk������l6�R�4H
v�R}�����iALd��~&&JK�Y��Tw7j8L��12���z{�8p�@���|3-����`��p����8;�~�A�7R3��l�g���j����}5����L�������%PG��|r[�-75P���{���s�1�gih�������6�[��������`������o���Z�����7;KC��rc{.����_�}���������>k��h]�g�7����<����x\����l������
����jhmuS_o������Z2�s���4H�
�������.��9�S>7+`��Q��Ql�	���$�g/�� e�0������j4��#G|��>��Z��;�g-�c���q�;�������=LE-u�Il�B�����ms���l|�A=�n��
$�������c����1���f''N��q_a��p����Yd��,��{EF��3p�md���v�l���+���sNW���i:��������
��|<;�:��'Nd���N�zj����G����K^���HQs-�������J�pHLM)���(MW��
MMvn���/��HD��Z��[��� [,W�J�0N!�b�S�F�i�Db�����>k|b��!�JW�H�|py�e�d����d?���u��n�mm���c��������$|�On�Rz�dW��[	�|3;vTg����b��B��;��Ouw�l��o~s��O}����hF���.���c"
�hn���J��/�I	�0�-7.w�5L2id�h�L6��]w
��L�;���/F&�sP\�*�A��Qk2#9���3�BXSn��1$������7�+_�z
���b�N����A����/%Xq1P�����vM22�0=m��,/������G�DP�aYF..F�F������7�r{�����vp�`���,��� ��v�sI�{5��\�6� ��.��������o#��Jimu��I|+�[�={��������`]�\�v����X+_��9�����BM�7�������	�O�����~���C��a��o�|����Df@p�C$]Q�s�3ev|���\{�I�q�s��N���E"���f�Eg�dU5�7L&p:%*+Mx<��d���M���S.���|ZX:;�x��H
�d ��1
$e�r��h��z;�Y��s�:�O��k!��QOo�?=��������{����	����]/�����=/�x�R7#�g:�"�kpf��~�>�)�6��h\7Y�[n3v��\pL~�����9��KmGIW�s��"���B���N*Fu��E��$�l!��
D���L��[����������wV������8r$A8�P\,3<<��4X����W�Vr��0v����$�"E�r%�si#�IC|�>���{G�c4�YCh(C��I�iV����5�I���f����n���V���00��D�Iu����~�P(C�Ginv�����@0�&V���������CSTf����8���tz�>[#C[���*Zov����9�ww�p�D*+e2�DBc�Jk�g�������Q�����������\�X-"���3������}�P/������`z��0������c��g�+�$�`�]w����5���[��v2h��!/�'�7��f
����/��me�/0������Z��=�2gz�7���v��J����M}��z�v~/��`�����7�h@���?��V�wyd	��r�]��H�`�:;���a������F��g����j5@����To�1,���J������O����b8"N���uv���a�q�tz��.�@q���-NJJ$**L47;���P(.��/������x�fv��������TU�:=M���)*Z��e�V�L��\r�e�_og������{������[f��0i��isi2�:���B�-B���FEE%��+>��]����*}t��k��U���,����*,���J�vZ`�v�6ms�t��3���t��d��$�d�|^��If���w�����s>�H�;v��[\?�*���/L���������u)G��X��<���s��&����%��
zY�����.���"��p�������t��pyS���j�����l�|lX-|��������p�����\���9��7.5�P\_��SO��9�F�E���z����l�J���AQTt:
uu��~f���x���Oa���������O�Ga��B����2!
�������B�m�����d��������=�����Z���~����	�gO�)�#���i�����79[�������D2����}b��#y
��j�T����?�=p~�����e%2�=��b
+W��]��X/��#AOOU�|
��tfo-�Ho�{�9FG����'��ib���Z#��n�qA��Ls����X�#����t
�,�8���
z9k����L8S�x��#�u>����&bw~������KW��6�:����X,:t:
+V$�eB��O[@�����I�]�;����t�s����2��};��I7��|j�����)�6�B�'��n�D@<��s-��;;vTs�]����SFf��y�b�z
��Z|�xf�D�0��~b~������d��0�4,\����a��04�|��1�t���[�	^���d����������pr�jl6tf3��.����h��b�,��Bc]���+��i)5tr��K��S�:D�����,
��4��u�����	6|}�d�>�h��bX��a%**
���^O!J��Q��Xt\��9���\����������<r�`P���0EE.�����Z<�:&����`6�����A~��A���������j�%O����[(s.�O���h4>_����x��R��,���_^2����wl����a��J����?gY������
�J-��8��%�E��sN��(�FW_mI����a�p%�\����.���@O|/Ry�~}o�0�x�DcZ/�b����Ge��'�-G�9x���qlO'w��"��L,(�������mW���^@5�����.c`@���(��O'imu�iS|��}�g����y����,���r�io_���n�RC���{�x	��9�q�e�+�%�R�s��r�o?���s��8��<�����A�b^�:��5��M�>n�+����6���0�I�&��.2p#�����|z�����D�,��o����f���M_?u9�!����hTe` �-��RUU@G�oXo:!��U���������a2�����b�1��Tn������_���/��ma>�Q�|3�ml6��`O������r]��O����`�n=��:m���5��tSC�3DS����\�a�Mz-<�U��3`����*ji��}tS��Ouy��|L��;c��Xttw��������x�Q�/Q�d�2RQQ0l������7����Y�'���`����,Z����j�siC����%��`�X,>8���/M��lF.�H��;<(��L�Nee��{v��,���P*+���T�|���}����YS��&��� Q))�c4jX��2��oR��"
=�z�`�Bb��h�zv��X[����(��J,g��p8�E���
c>�3�9}���D�w8���{3�L`��I�=|OO��r+W�hjZ�7����7�IL���I���5�&rK�b^���sM>?n�+#;#�`G�o���������+7�B!��$y&��Z�����D������$�n��"-UU�L��$��:�n��1��_��X��w.�6��X8�ysr�����K�w��v|G+�[z1{��/��d�����f�~k���L��V�w�<�[�,�f3&pR`�u��x�<�P��������,��{����1^3x���l��v{�6y[��������Y���t�'Q�$�'f�e�j��W��������D�QQUM��yJ��M����p�M��v�������@A�[W4�4���67Ph�^6]��}����A���kS�BZZ����8}:J$�h�������6�j!j�`�O�:��til��qc1'N�AQ�sC(J�\��MV��
F���7����sDl�R���<��;�������}��R���������>b1�^��=v�\�m5�xD�T�dcb�~��[�A�b^���$����t��mp�D5�������O7���b/���'!���<3��@��.����L����������x�����?��ns'�X��b�7��p�������v���9j�9A~��g�����IT��*6�X�0(�9VU�Z{������Q|�M��
bm��n���%'��z�o�����R�E��C��<�m
:,i�+���
��;)/��34�����J�~�q>��I����J��d&;A�����~/�����[����tru��n_%2���jl����]���G��d
[�.���2�S�'3���}�_{
�����{�/�(5,��z�>j^3���
�������r�6Y)/7P�G�d/Z����`�c�-'�r�������7��g��;��&����pr�l�>����#G�x���Q������n���zy�E���ts)$$���|�O4�b4�gO�������TcbA���{�E�x�Y,Tn�6ai���A�	���PYi.�XC����r�x��|�^��n
���`�t�.7�p������1��=	!��e$����R����43�7N��_YiH.����q�d�S�T���>�BiiArr�t����Rl����m�l8�C.R	�L��^�~�C�j%Fa�v��w��u��}��g���rf�J�Y��e�Z����U0�uX,� ������^@�����&J��������U�a�*�������K�|Lb�$�qO�__C7��(n7�v{X�e�����?��,��de����/���6���9p�������2�jl�����;N����/I��^�'6
*+	:��CB��q*�Al��\���� �;_�����e��s}}16���.%����d����={%�r�!>yn��F+�?��]�x��+V�s>��t��Xt��"����vX[������������q�\
	�8�C���>��V������'S��y��tv�5�	ww��}v8�l�|�W^�������_L0���C�����B w1�\�^�_��)LW#0�69]7���&v�,��!�I!&g2AbI�I/\3����"�t�<�9rpd�����w�Z[�����St�,�>�se+�q8��z�#�]A/o��Eb>TYi��H�����s����r���Uj/����~'C��9���S������<�"j�����UU���ex�
#��'J����������c|���tS3�{�.#w��'�t������P�^��o�h��t.���$�H����#���GS�������aN��"��b�u��t��M��Q��gm6���/B8>?@������j���8�#�-��XC�1�:t������h��������D"Kx�y������ ���ik�'2��V���q��\M������*+VvOWR���Hb;�����EY�PG4
������9y�jLLM�����$�p��>;�!��#����i�xT::|��p�h��{}�\�i�
]$�.���~�5W�k��K�N��T1�3<U�u�9_nb��������br&$����A�PW���s%����n�y�qd6kb�.W��v/u'^=��X	w�/mF�c���E�c��R��M�b����oI-����'8r$��o�'��j5� ��
v�����(���}�o�c
W8��5r��������&���cR������rS
S��KN��2J���M������#���1m�U-��`6�:��v651�k���_O���
z�� 1u����R�!�d�c���y<(^/:���B���f����$~���"Vq
����5(��
�������
KCC�)�1���� .W���0��a@e��!��:N�ko��2�o&���M(��V���h�.oj������k��p���hc�7UQ�ru�B�����t��H�H$^n�`��Wr�����G����b�������I�W��7�I-��&����d��S�����3��U�������D��P���p������lFJK
8��6TP����i��Rn��#��d���H���p�|
��'���k:#;���^��-��`��2��|���/bfH{B���� �|��[>]�<c
����8V6k"8~��u>�����^��l���>0����ury�#�u���
_��)V�%�K�R?y2��P�}��L�{� 

�����D�\|nbT�#��~���''���r�z\��^���%G~JX[�"��S-�q"�B��^������C��
����O�fe�����2�����o6��Z3����&�:�������X�n��Uv��ng��-�m���bI~v&�����\�o��hz�`��0�l�*�x*��/By�aT�����a��Dzw�?�|�!�
`t�pd`9�o�R2>_��2=+V9����z����4��/��nm��fv���o{{�������&Lv;�vhl���cG��@��k�Ek{�;�g�'���w.���c0h04��gJe����������v'�R[j�f����E�v�[RK"#��H��3
V��o�/m}�|�����n�r�6�����?����Cv���;���*~�n�HD���p�>),wqA��@�|�i�tN<���t���6cK����b�H{B��Mw�x�1������Ur�x��v���6yy�K���*Op�����L��N���pqY�)���a��>,��r6��G!P05��JI����<�&�,J���4Y�}�F3{��'�btv/�� ������U,
�pFkdq��)�m*V����zBN'�W�S:�@UT>�������X/Nn[���h����6$�	:�m�����D#1�������=��
kc#F�m�q����r�im]@��\�9����2����{{��!#-�q8��{o����b��X�����[6��������^�0��>.�<F���c
?'�G�n�M�����o�n���#�<�'���K��g�&RZ��\���f|�:�9�d������K7�r�eTU������8�}�:qk��`�`������	����Z���7��f��
������{���%��	9����6�a�����e��x��N���{�fP%�$�..h3Q�PL,����x0]'�f�2�����v*�B��h:��"w�
��2id�l�x�#��|8[[=�k��zOa�-��;k��z�#�vv��-[�y���tu%&A��.O�o����w�
��$^�2���
m�q��,�g������TUa������m%���;�����w7���x]�������,����BN'>_���}4HDS)�������w5q����+L����������<tv�1�u�Iq'��s:Cx<
z=h���(tw�����dS�s�
��G1�G�Q1Z"��%cv�8���AV�0�����Qho���ogd��W�X�`��z�mX���CocmmV�����Q�Y�',J\h�f���	��3���\&���&n�y����! ����4O���.d�H��Rsf{P%�$�..h��j~�$�i�'L������l�;�TJ)	!�B�o�����������s��[e���v������A/|����D���/��L3��;&��\Y�~������PU����4qA�wk+����|���3r�z-U�*UUX�����Y(�
%�2k/�
Y{��,o8�x4�}�D	KF��` FD_�j,D����N`]T3#���K�������.��
���a��({6�Ru��m�f3b��'��D�$V��E��{�������V�b6����R�f)��n����0�]�~p�}���9���xi��*�����Mg��#��R�{���Fz{��z�W^���/�P^>�&��h��h���Xww����	��{���qi��H��<Tg��?��3�1���EL�������/O2����MU���Ow���:���Y��rs�N�D�B!.$�H�������n�������'�	lMT��d���ng-co�d��Ng�^;��v���[��=�*,Zd@�Q�e�C� D�BAEaC�������t�0���g�?BQT�����_��/6��l�6a)�]J�
w�y���
f4����O����)��L3��s�B]]6qlO'��{�������#�4<�4=�O���	n�y��5��m���\v����)/7+4�m+0�����7��^HOO���_���>���X�V����Hf�'�==|>��u��JE��_�QR��������K�P�1B^/C�wS�e��=�eR��r��a���������b�����FJ|G�Q�W_����D���K�\�2��m��(�LLc��.g���OU�f�F�X������\�S)Q#�B��$L�L�S,G\e���X�$W�7V�'u���w�����������E���h��x�E"��+���b�/���.���������}t��1�T,�T�k]�v��8%��h�a������/�������e�+Y�xi��(U6�#����u���?bR���L(e�0�u�

1�8��}/��?=���v�eT��=\jMi�� ��n���tu���1b6���T�Sw'��8R^C�k������~v����&����0�apPa` J,oG�H����2�����^tf3��$������|1�=n�����8t(��Q<�	��6����0{��U�y'��/z���"v�\~Aw�A�1�|�7�$�.��35�`j������AJ)	1���B��$L�L���� ������d�o�ur��Ojp��'������,8�����}��ng��-����"==x=�dFn
p]�^�j�S����y-�4���u��{X)
�G��1S�z���c|���tSC
�,u"�
�3��D�X�Z�����j��%������p��h��R��Zx15���O��r�X�>���@���X��H��Q����/�b��FS�3���c�&+�����)�.���q�W�����X�������LOgg�X@����+
��U��<�-��n��)ey������(Zb6������=�2,��=O[���������'��v��U�L����@��3�7@L�\$]��nJ�M�	�\���b^���qc�������Rb~�����b6H"���tp&�VM5���:9�z������C^X������TU$�3,Hn�a(/G�z��|�,�aF��"N,����.�/��������S������;p���k9���hw�!k	���>/%�i�~�F�v������j�z��X�3�w5XW�
�Oe��(2�_Zn�S���JV�l����@�[{(��1���4�IF����7���a���Zu��/M�l������?_D}}��c�r��u�++��<��DK��[��+����U��Q\���������,����Vr�PCe��������|�S��U�����l%f������c��SO
��
���v,

��m�)(��&��Ia]:�5�4Tcc	����S�"�*����(f�T�.�t�[a�>?
Z[�l�V9��ApB�+#�2.����Z)%��b�.�:�B��I	&o���3��jB��7Q���R��}}����1�z
�w&KR����F�V+E���?p ^�b��������#���*��ia2��X��K���`�!�tZf'b(���$�>�
�{���<B�\)}i)���
��x=
o�X:j���nz����Ag�P�m[�}92(��8��I������h����@���"��}�e�^�����m�s�:����Aq}}N��8A�o?Iww�YGm�qD�HM�[^nH�[Z�<��q <���:*k�f3��(x�
f���ruuE:4��Ct:
���\����#��a)��f��G.������������:����UbF&5#��::|�JU��+DG�o�5�G~��X��b�s�&~�[y�����5��}~JJ��*u�c17%����Z��:��X��"yq$w!��22+����|,P���C�r�����b��k�b�d��1Q����I���<���%����3d���tF�{�`%��2tV+e���������m�{B�7�,5l������
����&�ra��2���S������^�����MQi)Q@��'�4���x��p��w�]��a��t�X�j#����l&�����m�wl��	��X�r�������v+G7�L\��d��j�w0�9������_r>�mo�R�=�p�ik�D_��W�����Ng�E�����U�x��>nh������U��5&�G�<�[o��5��:��"��yhk��r���<�O8r$D4�d��p��IKM�	�Q*Xd<�%E'hj�`���L���"1#�ppt�f"��JKY�s��v�Z��b��m[%���<��.W�P__<�g��&�/�A�������#K�$&9�L��$����w�����	CCJ���l���b^��Q�x���"7f�q~!�b�l��L��IB�Ic]'�[N"h[YY��Q���Ji�!��_�P����Oe$�w����<������`2������A�����+*�����������t����]���{~��bA�xXx��x��9u�����*��=l�l6#�Rs��K�?��'�oGk��{�e4�0��RA/P�����ng����1_1�D��-�3���0~��/H�j��+���}�����l�xbl��d�����r���&z}��H0����
p�lUU��5��o,�����f����,)����V�(��
�����;����6j
).6��-�
[�����7�4���#������_y�Z�G�pj��w����R=��a��<�qGP=a
w�#���Gq:C�:��D�������t�)��R��J�|���N7x ����z���,`��~B!�DT~���Y��.w!��3�����IV��#�7!��edFt��r�^?�d�6�]''Z��f�b�Q[[���
�h	w��xT&������2R�
/~q���P����!����I�U�K�t'��vd9����n)K6�Zx���WY@���X�Bl�hVs>HC|�I�cm-���Q�*u��D�mq1��N����x<\�`gkCn�S����p��Q�]� ������b��A��������s������7!]{H�{{#�
F��S����~�?��Of�,Yb���QV�4�\!�a���;����.��m�����Nj�����>MIcvO�5���=T������J
EN�F��P#�Fq����4����9}}ZZ��l�a��t)������#T��oP��>����1���T[���_���P�����������w��
c4jI�=Ue��$�.��`M%cf&�'�$+W��8�B�.9�����������}�H�J��t9��Z���46Z'�S�
*���^�Q��i������d�~�����DOUU���d)6���+�jr�`(��f�:��v*�m��6�T���{~d��`s3����`������d��xf>�{b8�����0����^|�������M>��t�8k��PB���]L����,�� ���`?��@���;v��7�9C8#����F!���0_���}��i
��^Fy��_�z��~�3��=������tu������p]ZZ����km'8�y3�W^AUU����<����}�ik#��C��U&|�(�����*ild����E[\LAe���mj���R����m?q��z�����2���<e����~N�������>8f�}62��I�!s

��)��� ���r��'�I�]��&{��j��t/Ow�f�Jp�� �!����������s�^?R��6R���#K�1������K\d�>����oG��5_fe�	����2��p:Ch4PYi VY����Nf��~v&�����~. �~"�z�fm���v�������O75��'�n�'��4�ZU8,�j���`O�-\}��(P�����&�;ZYvW�������t������:E��F�����Z�������*�K\W�6C���r����%T9}:�����Xtx<���ZZ��}�1@���x������^����X4���cT�=���������Pw7��n�f3���B?��_SPU��kc#���|���TV������q����{��5r�����x�z��JKx��3��(�h�`�b��f!��A���c1�z��<S��dz��P�3u?l����s9mm�'4f��H�]���������N1cf��f��u�.�--nZZ�PVf��H�\�n�$j��<AU�����Y�0���@�d�k��#�!�����p�^������L�e�}}:#�6&���XF�@����=4�p�L��x��S���O��DS�B�o?IM��C�j>x��hm�d������f�l�����DT����������:5S:���{�i����A������$Vy��_�U��+2,K}��j�q��e�\aZ[�x<
nw|BD�#����o-Y�5��Z�aB3������y����	�����<��q�CQ��	,�c4*��*�h<�����b�F������k����_��^HWW�C�TVp��e�m��<���T����\!�^��KK�8��"�0X~)�~�4@r��l'CN':���M�8X��
����2B�W_��/�����{�����;����0��,��t8���{9p�������:xf��W-g�������yc�����]��io�PP����tjl����C�9EQ@Q���=�`����V(.�������]���,��$>	�!�V6��'��6UP��3fF�j�\��B�t�����
E�h4���a���yu��)cu$��<�������=���9q3��Y��]�\l��3 ��k����z�����������U�n7�e��n���WP()���*��6d�>]�0>���3
�H�'���������o�v���o/����������Q�=�]o�h����T~��~n������Y�2�
9�(^/:��YC�������������oh���<�o�����,-�r�9u*���j�Z��#�>b�
��_������b����^���ej��<��F�h4�����TW��5RYY������0��V�D���(�����1���5���Z������I�W���y��\��au��,�kg�����:���������V7�6�S2DI��*,ljbaS�z����(Q������;�44$�O�~o���v����������n��K�e�{9��>�7�
[������&�����QO�dj*����G9�����.�Ii����Z��1_s!��{����y+�����y75\;���T����t�g��r�](;:|D�1�����*���ywM�#��k����%��1��z�b{d�!��]�u��k�����	�>��qz{#D"1�f]�=f�>� ���`���PYY@ ��+�U o�J��#����--n�|�����,Zd����<3���Hu` �������t8���y20�l��fB]]DU"���-������<3�������������h�0���W�\9��_���
����:z�����}A,[V@����7/��y�G�n/��D���A������c]�P��:���������l�Q��;b���=�IR�m�z��	V�6}5Y����l��GI�7�A���q�|3C���!/�FG����6k'�J�n���Qth5ztF����:�u�K��S�����V������2L����2cM��Nb���� 'O������'=���|��%�',��������
��	c����L��IKpB��l.2�N����|�f?���l�Z�X��P��p/-��IIf�X�''n�D�v�&�^���|{DQ!���8��5o��jy���	��h�f3���I�t:�%R����s��15?!V9uj�+�(��
�lFzz�����A�,oa��>�l�W_ma�^.W�F���E�������������/�Y����"[�,I0�,������Z��5�$&dM�p7U�s��#�w�g Y���V��������������1l6#6��������r���c#v���1�S�877�����	c������~��&���e��B�O4��y�����6��~GW�
J�&*���-:L�Zb�.�wauc�w������#�����W4���hh���`��{�����H�����W�8,�������
���Nt�BB�w�'�ACg6c���m���������KA�����/B����0����gUC��q�p��^��(��o�?'��{��E&*'�(�T^n�����}j����Uj�Kg��03����%	�!fE�'�lW��'����������v���_.5������-�����d�+_�G!���kD��Ey���	����������~g�Dq8��tp�t�3g�-����d
��6O2���I����+���UU������`2`�����TU���]�g�����!Qozh(�������������e��O�u��A��[n)MnCOO�EGee�?�a�^M|=���6/XH����X){~�������;?��J���\���gg��XtQ�BE����\M�S?'��"V��"Yo~�F>��(!���j�����{.a��8G���\�%�^��n���;x�����a(/O��q�<�Q��b����a�D�����k���������>�f3r�dE�O��(��������UU����(�H�hTe��">���U�}���	Y�s����3n�N�s�d>]��r��t�vd��|6V���m2_�{�����#�b��5"?����tf�NUj�
��{��(���������{{�-��t�X������U����$���(X,:<��Jk��m�*��cy2�|` ��cb�*Z���*�����y0Y�������(,��F��NO)X�������x<
���w����^���E��
O�C�D"1JJ�a�3g",XP@e��-[���!mm�������3�{�M�+��kXx�|#B��k����fM!��
�8�!��+���2g�C��u\wG=�W�z�A~�j	��,���=|�v�N)�x�������_C���"�.9)�d���L��R�B�b1tz��"������Ex�
������n7q�-e|��'P��`�b}���l��ji9��P��b���'"i�;���aB��@�B�''����>��P�M!�B\��Ky�D����MUU���	A��E���qO�������lY��f�����4�ZU����������B� tj�o�^��z.3 T�����3���K���<�@�H�~�pX����Ui�tR�:2�x<
��xb�x�v������JM��[o-#����w|e���_������,��_����g�'���D;��TAe75,`u��������>��(�#�q=�����e%��-�4���v��m�*'�Y����q���M5M��yp/���������TGe������y��/�����2>�d����h4��t�������d'}����s���3NN��MW6N>g�!�B�����f�������8x0HAh�,��k:����n]���4��n0h��KC__��w�=6��K/-��?BQ��%K������z��/J>iPUU�Ws�x�7�$�9

V�6��[
��F6m��{� ���v/[�.�����:��By�!m�=��z��5����]�C}�p���1�F���(���={<���G����G��:<����I�Q�����|V�\PWW���#,[fT��s	w�Q6��\J���d��D�;ST��2��fu~I������������?Bi����Z0�rY�&�y3C�B�''x!�B!D��.�0�F��I��>�>H���KL�	�����Q(-%��$?����UW���
�q����\�0�wr������IO���d�!�������(�N��
�\i��P"�h['�RC��������wpv�y�����?A�BAA����E:zz���Q�n���
�yl�j��%�����wX�Y��(����������z�����O��(48����!�Q����`���x	cG�;N��+^/6p���3�gs~����v��oI�Q?]�y2$1o�I�]1+�/fK6�8
!�B1�c�!u�6��3�����;,���8���$���~{���\�����te�&*5TC7���h�l�0kc#�46r������>���Z�// ��t���T���<���d��X�=�<���,��a��@��`F�6Y����}7*0��ST�'�RS�n��6%��s)Q�j5��J,/d0h���Mz0�#�-�t���?7�@��_�����-3��=
�������Q__<��G���R.K�&w!��F"[��V��PWW�����G��B!���D�������KW
%���('�nY���c���(P�ik#��K�����d5G�w���`�m��<���
�?�����Gq����?VF���6<�l��(�::PcU!�_GG�o:���/�x�x��3����rA~t:
��Jaa<�^__<��:�!N���+���@ �d��6c}� yK����>F8��GO��_�w����o���ypB1o$�����z�_���>!�B!ri��_>f��W.g,A�wk+��.B]]��e=G���hjZHk��w�
��k�j5x<���d��a�s �������"�r�9�sb�B�I
PLdd� ���H�l�l�lF�,)���(�
������0�{A�D��t�']�|� yG��p8F8>_�G9EUU�����4\u�������f[�&u�'��M%�?����$�.�b�Ht�}�����
�O)�B!��&���\��
9���V��68t��MS��&��o���D�QQU
[�,s���`�H��F�aT
��[��ik������v����t�K��Oj���/�p���(v{!��������v�;>����3^��X�P__�������a0h(+��k����#S	���0��g����vv�
��n�m��p_N��|��/����B�yc�U 5��B!���9qm"X�x<TVbih��r��:��/�5X1�Y����d�=!1����aZ'O�v��;�iiq��<8�mmzz��ZU���PYi���hXp���v+k��b=���h�����G9EY������X����BQQ�i�lk�;�!�^�9>I��3v�����O�:��GpB1���	!�B!�h&���[�NK�8�����&������Z������$����E=Q�py��~�����P���N����k�{��((���l��Yp<Q�?�����=�eh(�F~�I�u�z�����;�]jku����S�#����V8p�����3������@�B!�B!�bN���q�<GOO����6�d�����O��A�!�3��D'�?jn���h���U(-�SYY@k�<���9r$D0��v�(*�O����TU?=r0f�=��Q�z�Fc���/��f��nb���Q5��:����x|������z�b����wpB!�B!�b��9V�*��;�����`����Zy������Fq�	tvRXW��jM>�0�}�xO�>AU�d����p
�V��?�%TPU
�(��*EEp����o������b7�� ��K���X����I��t�5�1M�}OO�Y���E�:������e�cy����B!�B!�S��{<
uu�l�d�(h����+�A����b�s�673��S���SOQ
jK����D"1-2p�=Khmu��(��8~<J0��@���D�*~?�|Q��Q����Sho����@K�����JK
��n�hT��$�r2�������b��}M>p��p���'u,�2	�!�B!�B1E�]�c�??[�Ioc>�s���V"�O���*B.���,�V|9>�����]R����yx��Siy��xy��Q�FCi��[�+_q��F��0r����
�����c��^�������6s�t��FkV�d&*4�1�{ /����c��r.���B!�B!�90��9�����:�m��f#�tr������(���j�������n7%�.W�'����;���`�`2�b��F���x�;�iiqc6������(%%:��f�����?������L`�I��������q/��g���&},�*	�!�B!�B!&���t��M3�n�[��N5Lk���`uC���6}}��
�,�x�w�h@U!Q�D�V
,�������f�Y�ny��[o���
��F75M`;��e���8��2I�]!�B!�B1��$�	K�n�I�=kc��g�e��lFZ[��<�?����A��%����`���o��!����8U~%����e�t�	l�Z����c�/$�.�B!�B!�W������PW!�s����n7�����c�)�|�7��{��e!�f�F!�h����Q���4���\�r������P^�������=>�N�B!�B!�B�q%&9
uu
��Be�����z��m�8z��������:t����7���3���ni���w�Q�Y,h��q��R�m[�A�Lj����RCs���B!�B!��J��T����|�N�w���|v�7N.U�OW�M+W�����T@WRB��UU���D��lnfaSS����fT{>��RC���u���B!�B!�bB�&9��Lv;���������}�1��MM�^������'r�4X_\_��SO��9�F�E�������	9���w:�%p&�=�*�������o�����:��L�B!�B!�B1	v��m�*',Op8�l�|�����Jm��o|c���	�kml���p�wv���h�����'j�gR{>!��P��Ag���:�����B!�B!�BL�T����yx����J CQ�l���qukc#������2/�����Ml��]���RC�������X$�.�B!�B!���`�������h�b��2*���T��Of� ����f�Y���L��$�.�B!�B!�����Bkk1]]!z{���=&�V]F%]�2[��s���M����x	�!�B!�B!�,I��OLZ
�m0y��5��x��|!w!�B!�B!��ES��k����D�B!�B!�B!��X����'pB!�B!�B1#2���.��@|>���B!�B!�B��>i�x� ������`�����2�m���;pB!�B!�B�9`.L:��6���f-��a��<sj�3���B!�B!�B1��ICS�[��^X$�.�B!�B!�s�\�4t<

���(+�SWWDC�e�W)����B!�B!�B�sa�����&�m�����		�!�B!�B!�����Nd���DrZR��^`��5\|���v�m(����!�B!�����B!�����c���v���/y��w8{�,?��Os�x!�B!�4�~�B!�����2,[����W��/|��;w����!.G0Y�
�I���7>���il��jUgL�� �tb��0����������=��&s�&���6��e���,'�\l��mW��(����L��w�������\�W�O��"s�q-��'��W'�����@���l�A�������Gb���N���N9����PUU����������q�p8�<��	�����V���[�N�D�������*O=5T��@%�;�'~8����['��N�=����-{��M�8Mf;sm�m�d�3YN�������l�Q��������d���{{��*��n�m����W�_��"3�q-��'��W'�����@���l�A�������Gb���N���nUU�\,������g�e��]:t��n�����'_�s�Nv������tb���x<X,�1�?44��r���n�m�K�;�eN����'����5��Q�7���
��?@Q��HD���t���Wz:}:��_f$�b��(+��x�L����Kp`���"�H�E�5�'|�r�,�a��������L���e�Y��4jy����w����*���f�u��94u�R��X��v9�2i��vo�&���8�f������=-s����8wN��c` ����Q:��E������k�����x�����n6l��K/�4��3R&�x��<��5h6�9�����.����]O&c6�h�}�L��0��|.��#_��LU�������1-Z4�~<��94�~&���6�����.c6����f��h���r������u~�zzz8{�l�5G����^u�U���������2~�_��_���U�VMv���D�:�>w������}O&���k����g�b���F3}�T��������8�f��\�Q9�������yRi��xU�?�O��S�\�������:�A��N����L���Bi�r����:��t��/����<��~�#n�������O~2W���fk[��s�����?��d��\��B1����s����=��V��yr���g�����	�F��~�������a��?�~O��r
�^�F�����e�:i�s�3�^��$����_��q9+)����s�]w
�hhh�?�z}n���^�:y D>�6*���O�����|w������������&�S�;i�"�I�l6�g�z����^;m�y��iY��"mT�3i�"�I��Bo��������M���w�FE��6*��l���f�!�B!�B!��U�j�!�B!�B!�����B!�B!�B����B!�B!�B�s6�������[���;�����^!F9u����UW]5��"DZ���o��������y��'g{u�������_�"��z+�w7��#DZ�����(}�I����w���L��"�I_^������M��K_�������a���X�f
_|1��v����3�����Gy���v"��l���G�m��/��?�1�-����P�m���(?����k�<��l���G�m��\r	�=�O<�G���U�L�m����.�_�L�j^����w���L��"�I_^��|���M�����,�������b1n��6~��_��;�p��Y~����r�����������_g1�d�F��i�m�?�0�W5��*����������p�
�������y(�6�����d�n��������|'}y���/����E>��~|��?��P^^>�w,[����W��/|������
��@?���3��b����
1�&�Fz�!jkk���>6��*�����}�C<��3���G�_�������w�����f��<��������:����|'}y���/����E>��~�~����������?WWW';�7�p�7o��^`�����ZM1���FC�_���x�����y3;w������xm�_��_��/~�UW]����������x����^����H$��
�:/f�xm4Q���^���TTT��:�3���|'}y���/����E>��~|^�UU�oEEE<��3�6B�6^5�<��c3�6B�6^����+yU������W^��W^9�k#�h����k���k��f�Wf����w���L��"�I_^������MI�tR58v������FB'mT�;i�"�I��N������N���g�>E��6*��l����_~�����p��A~��q�
7��Z	q��Q�����|&�S�;i�S#�O�;i�"�I��N���g��>�&�~�wPYY��(TVV�y�ft:?����g>��+0��|�����U���Q�����|&�S�;i�S#�O�;i�"�I��N���g��>5j&Em�B!�B!�B1���pB!�B!�B!�2	�!�B!�B!�9 w!�B!�B!�"$�.�B!�B!�B����B!�B!�B����B!�B!�B�pB�<����lY�gFoo/555����l������������c|�#��5B!�b��/?��������"�M���FG������������\��������������^!�B!�%}���//��$�.�9����������Ky�{��������_�%�\��-[��������������}�s�B!�}�Y��[����Y�nG���{�AQ��_�u�]�o����^�e�]�>�:;;�xF��7���W_��>��Q����O���|&������\~���[���~�����088Hcc#k������4W\q/������<y�k�������f�y����ijjb��u�[���������T�@�/~����}�����;v$���O�'�|r��"�B!D�//}y!��U!DN����UUU�{��G]�b�:00��A���J���RUUU�����������{LUUU���S�?������~5����:�.��p8�^q�jOO������+���{��TUU����_]�z���x��_MM������y������R���ZYY����OUUU���G��oTUUU����Z��������8p@��t����Q���}���o}+��������z�M7�>�`��������_}���TUU�o|����?�����A���.S�z�-UUU���G�����n�B!��������"W���B��F��S��������,\���Nww7555��W���G%�v���b\s�5|�s�����$���'������������h�w�����_�������w��	���F���pP^^�{��^���/����`��=����K/����������+���[�x<|�#���������y��G��K����A����@2�����>|���W�x�b�?�v]�B!������//��"w!���V�^�O��h4�[4����x�}��QVV����}^�u��_������������~���r��W�UUY�bH����c���d"
QXX8���f�����?��?��������Ecc#/�����o��7�Iss3;w�L������m��k�����`08j;�B!��,��K_^!rEj�!�:{�,���,X��������%�v��6l��������}(�/**��������s�=�;���������Y��o�=���y�{���K~���c���Z����d����N�x�
 �}s��8@cc#��������������W^y���|�{�K~������ ��M�������(�����={6����]��v!�B������BdB2��b�[��k����NYY�{�������-���z��������}������.����J���?�����_�5_����D"�p�
l��a������y���X�n����F~���q�m�������?�1��w7�|3k��a��U�]���:j���?�����1h�Z�������}�;����k��������FSS��� ����u��o��K/����R�~�i�{�9>���g���B!��2��K_^!2�QUU���B1�N�>�'>�	^z��q5M��h4�~�m���Z�92����b1���J~���$�H
!�Bq!���B���.��DYY_��W���c�������|�S�BQTU�����z����k_��t��B!��!}y!��;$�]!�B!�B!���4U!�B!�B!��	�!�B!�B!�9��v��<���IEND�B`�
relative-all-optimal-no-readahead-small.pngimage/png; name=relative-all-optimal-no-readahead-small.pngDownload
�PNG


IHDR��� �L9tEXtSoftwareMatplotlib version3.8.3, https://matplotlib.org/��XS	pHYs��7���IDATx���y��e}?��d��$d��H�A0R��q�q�T�VE-V��V�2V��:T�u)�Z��������M�V%�GZ�	�2'������1�d�I�������\�>�s>g�������n)���_�4��	��w`Z��g>����}�����>������3��L�K��.�,---iiiiv)L��zg����3�LKKK�<��f��rw����FZZZ��'=�����g>����]��e�]��R��}�Ciii�����4���6�����O�<���on!c���|&�_~y��)Oy�no���>4���������������T'p`������o}+I���=���4������.��6n�����*mmm9��S�]�Z��[W_}u������9��c�]
��o;��m�����,Z������ p�����������E/zQN<��|��ioo�QG�������O~2�5��]�JKKK�%�W����r�)9���2g����]�J2���o�����������U�zU�<�����e���9���r�-�����J%�y�kr�q�e���ioo��G��=�qy����J�����7���$����k_�Z���gg��%�?~�,Y�g?������������aQ����<�1����<0Oz��r������&���d��o��������������;�_w�uW���7��}h,X���:*��������~��n�)�{���������<�!�9������]>����?_������<��/���������#������\z��c|������;�6y�;��r����C�����\s�5{<���`>���	OxB:������_���Y�f����t��My�;��O<1���$���~�?��?�QGUo/���<&�w�M�6��1��U*����q?������T*�/��/r�����~[�n�%�\����5y��������??�vX���g��_�b���k�/�k�d��-���>��>��9��C3��~��y���������������������;.p@-Z�e����o|cn�������/|!O|��������<����'>��1?g�IQ4�y��W$)�����AT����/kii)>����������$�QG5���Z��+�7��M�::������8�����(�����:�d�6?��G\������-*����s��q�����G�������j��y������$�Z��C��"I����d\���j�g�Q�a��9�AT��3�~�K^��b��-����W��HR����c��---������,�o�^������K�,)���W$)8��b��%#��|����u�QE������������l�t�������_�����/�����?��?�C9�HRx��#��'>����m�F��9�����,.\8�};��sv����3�'�7o.8���������[�u��������c�9�HR���������w���]����������������|�#������~���q�W�e�g����(��*��/�r���h������>~��V�x���c���(�K/�t����E�����"I���U|�S������{?�y���q���CCC{�����)������N8a�����_������+V���8��CF�>���,����]�w����+_����������#~o4��h�����y��W���?-j�ZQ;�j�Z��
o(ZZZ������?����Nt�>J���o-�����(�bpp��52p?�����>����~���(v���V��j/{��Fw8?��S��k��/��ys��_�������]�c��_���l��9��S��=������.��(6n�X���o�?�������;�uvv---����_���EQw�qG�����~�]����v�a,����������O8l������XX_���GuT���=���/Y������h=�����Q���7�Q��_�uq�UW��w_��[o��������I���u�F������$�c��q�w����e�������P�}���?��?��=�a������m+����������_�g�7��M��g?���Y�z��k~O-ZT~��������I�u���_�w��E����+.�������*�b������x�#Y$)N>��Q�a��u��x`��8����k���(�'.���b���#N�=�5�\S����Y���}��3QEq�]w��������������iSQ.��$�S������.+��(�{�����������}�C����7�������n����n������k�SO=����������^��_������m�q���w---��M�4�����>��"I��W�z�u�')���7��v�������re�G>��"I�`��b�����o����}��Jy,����I����5�������+f{zzvy��o
��7oT���{���s������O��HR|������G\���}��%��w�9��s�=�~�N8�<��e/{Y��x�����:v���n��������*��{���}���~��T�~��������������F\�o��o��v�~����@����k~Oww��(�����hmm-,XP�Y�f�����{��l����>������u�+��r�._��k���}y���/I��>�������5EQ�~���d��~v����(��}�kE���Cu�=��m[q�I'I����#���ysq����D@Q������s����;0�=�Y�J�\u�U���s���[���Iy������3g��l�������?��?��;::����aC�������?V_��W�m������mo{�.o��w�#mmm��uk������6,�_��_���w���I��7�{��������:+�r������g����7�)mmm���u�]7�������?�������'EQ����f�}���$�y�kr�a�����OLwww���}��UI��?��9��SF�w���9����$���/�v��}���SO�#��]^���|&CCC9��S��G<b����������$�w���q=�����(�����}�._��?��9�����x�z����7����v{����I���M���>o��]���~<���y�����~6��[[[s���&�{����n6n���w?�����-���c~<��$p��j�����������e���imm�o��r��$����'��c�9f���Dx�c����8�������dG ���?=������|g����l��e�k���[�_��_Y�hQ�1���?�i����~t<��]����������G=�Q�������K��������<f��/Y����G?��{���w����o����w�yy���C9$s�����-[�d��������O~��n�-�sL�q���>���>�;^���W����>��OMkk���������^���(�� ������O��Ivl��@�������_��=�i��oO�%���@>��d��9���2���c/\��~�=�����[n���:������k���U�lvW���W^�3�<3�r9�-�������]�=�8��#s�1������������n�/�d��������%/yIj�Z��<0���iii��-[r��w�������&+lOv�����s7e��u���>��O���}n~��_���������������~t�������~u>��q�r�%��(��z���\��'w�qG���~�o7�����v�?��Y�~�n��cyO�v�m������?�qV�\�{���~��E��p�����dhh(w�yg����������Oa��o.���W�{�����?�c�l�����C���������~no���$;^���N����G�����������\��
7���?��#B��f�������~{��wg��k�_�$���7|������C�d����:(���O�l��i���x�4��@S�u�]9��3S�����=-�]vY����������o�m���/��M�ox��T���<$?���������������^�o����Gy�[��c�9&?���}�}m'��m��-/y�Kr�=�d���Y�zu�����?�?��O��/����?��=���yy�[��b��V{�s�e���������|e��_���>:_���s�]w�����w���n�-��r��<���q~��_��u;��3������W�����<k��M�V���s�m����n�_��_5�n�f��h�������7���-���q���"tppp�}����'��9s����|f�g���@���o���'7�|s^������o��$�������?���s�=��cxu��Z
_����;��{�~2���?���s�M7���5����v�rw�>�7�pC*�J���	Ox��<��v�aY�n�?���������o��?<����w��do�������r�-y�������s�n��\}��I�/~��y��7���_�~x��7�tS������o��oIv�kp�E��6{{�������p�j��uI��=�a��������d�4.tP�����������*'��v/}�K���~����|��K/��-[��'?y����{���d�=��3�������?���~����������7l���T]);�9y����6����7��$y�����M3'��{�����nos�e��������?�������������?�]www������>���������m;Q����>��|�7����wWwQ�}����u���7���.os����k�V��$p����3�����
���Y��/�x�����;.,H�|��_u�������;!����Q��J2�pu{|���/���s388�������m�����V�e��yy�_���l��9��wy�{���$���g<�#��hu��S��g���o�����������|dB�Q�����_��$;V����u��m���w�;I���?<��^��^����;7w�yg�;��=�v��-#N���{������EI����e/����>_��Wvy���N�_������\L���:+I��������k�x�n�;\���Nv��ju��=�����;���wy�������y�k�,w��N9����3'7n�����l��%_���r�)��qs�f�90~����/}�K� ����u^�������������s�I'�����_�*��oO�c���W_����uIvl&x�I'�����m�����$�}�s���?��y���$���r�y����{��'��{n>��$I���7���k�������������$��a����|���M��{��������W���m&���'��HQy��^�n�!��>����w���<%---
�;��#?��O�p��Q')&�_��<���M���E/��_\�����//|����8IFl��H}�Cs������/y~��_����m[��Y�w���9��c�f���u���������#w�yg���g���QE�������N��7}�?��<�!I�����+����)OyJ����}{Q���s���'�����<��O�?��?�[�$;~�/������/������=��S��������_���{��������_�E9��]>�����g?�����o�?�������??�{���x��F?e�}S4�[���"I�Oggg1o��"I���]|�_�_�@�����$�QG5�������+�+V���m��[Wq�����Wx��E��������������?q�����}n;���w����r�!���s��x���W\1������HR<���}v�V�/z���u��3�8����9s��/{�K^Rl��e�}_��WI�W���g�Q$)Z[[��:�hii����/y1444��7�pC���^�%K�GuTq�QG���������*�����Gcw�������m���vy�=����O�4��[�hQ��C=����Kv{��~f����d��x���7��=��^��(�+VI���;o�u���/N8���q���_,^�x�g����>����tg��o/�=�����rH���:������F�w���(�o}�[E[[[�6���$EWWW��O}j���7���?�.,.\X$)8����o�����[��=�q������/����s�1�����-[�'?��#�����g=�Y�;������*^�����}2�^���/�{���p���.��>��<�1����u��s�1y����k��6GqD�K���K���k��������/Z�(/������<+V����}���/}�Ky��^���������{��7���Y�|y�����W������{2�r�y�{�~�6���Z�*_��Wr�i���C���@9���v�i������/�8�����q���/�c�X��Gf��m9�����?>�������~v��r�=�����?�s���<�A�]w���n�)7�tS�7x����������<�)O��E��m��<���_��_���EN<���?f������?8?��O����y���������G����e���~�������ZZZ��w�;�]w]����<�|Z[[�����:(Ox���7�9W_}u�����}����g��?�y^�������-[�d���������^���������~v����<�Y������m��z��y�+_����gy������gw�8��\u�U�����>����������-[������s���|�C�W\1�~����w����w�y9���2o��E��<�1����\r�%imm�����3'�������}�����m[N>����?���n;�>-E1Ew�`�u�Q��������,'�|rSj8��3���~6�x�+���|�)5�4��=��l��%6l����f�3��$I�����|��y�C��������|'�7o���a;L���.��a���9���&��	�u�����W{!`��$I����1�yL��`�r�)9��S�]�xZ�@�4�
wh�;4��@�
 p��Ls���g�|���o��5iiii���]3��y�S�e�]���7��=���~�'>��Y�pa�;��\r�%c�~��-9���s��G���%���7F�����v~��?tP;���~��Y�~�d<-�/�}.��O|�iii��>��	z&S���q��uk������Oz6n�������K_���������O�'=�I���?��K��:~����f��u��������E���`������[o�5��r��'N�s�j������{����|��9����g>3��zk��-oyK�:��tttd��e�����$����r�i����?�-��E�r��W&I�������}l/^��������x���??�vX�,Y2j��������N������G?:W_}u��{��'/z���x�����\q�{|^W\qE�����{��ioo������X�"�����t������7�1O~�����:��/}�K��g=+�-��7������k�m��q�������m.?����������>x�6��"p�@���'s�����n����?��?I�<�������{��;�����e/K___9��\z�������M��i��<��O���^��=�yy�[�������T*y�S�Z��������s�-�d��Uy�������7I���W��������|&7nLOOO��������J���_�e�����x����~��}�s{|N�]w]N8����7�~����s�u���������s���g����t�������|�+���{����|���I��u�{]��r.\����������������s�a����5/~��S.�G�Ty�O|�y��_�����7o^:;;���=�~����s�9'����S���}��Y�fM����.������|���3gN���0�r9�W����PV�Z����=Y�xq�8�����o��s��i�����/�������k��6��{n���a����a.?���������7�9����<���Dw�	t�QG���d�������[n�?��?��NHggg/^�_������;w{��n�)�{�n�_�d���P��x��y���������Y�&��rK����l��eD�;���+��v��EI�E������������cL�����ks�i������g<c\���e.?���y����W���{|�3��`�t�M���q���j��uk���w�s��\�����s�=y����(�$s����|�QG���h<�<��\x�����{�������mo����y�������o����O~r����6mJ��t�I�����l���~�5k��7D���c�v�����Az{{�_���d.?����������������C=4?�����w�#/|����LGw�	���<�����y�����o�������{�Mkkk��e������>�_�����,Y�$���;���u�Y���������m[�������dL5�}����>����g)�"������g���imm��^�������=���[o�5���x��������������jY�zu.���z���]�$�Z-���)�"[�n���`������a��y�{��W���c~������?���O~����.k����5k��G=*o~�����|��;�t'p�@�z������$K�,�-���/|�9��Ss�����O�G����������}������~u�-[���������'���~��y�{���>8�|.���1����<'\pA�:��t�A�����?��l��=I���~4�-�QG��=�iy��^�����7/�\rI����e���y���/|�9��c�t��s\�`An�����E/�����>I��~0���o�W�W#���j�h�����~��Y�ti�O[[[:;;s��������Z���=�PG}t>�����~�K��\�}e�;4��@Kh+����wh���|�<0K�.mf	0%�_�>��{o��3sy`��o��mw��b��d������y]]i�?����~�y.���}��������YL	��-kv	�b.��`����>;�oL��Ei����^��t�\���`��<�oXK�;��#��/��9�������Q�&��<0���~�9i?���uw���3m�R����j�
��;,k������� �G����\�,�+W��TJ�ZM[���r9�������	i)s�����?�i.����8<3LQ�.a����4��=2�&Z{�<"T�T����>����O�i��m.?!�����<������'���[�n��u�R���]��ikk��G�y��5��]2�&[�ZM��uw����Z�*p��f�<>�\~B�����_>�������.�E]T�}����L���KGGG�>��)������]w��u���4E�����m��{��o���k�������[�������s�)����o��9{��u��e������LEQ�R��a{�^��3������_�:�ry�?N����\h=����:�O�6�o�
����y�K_:�^l��lY3l*?_sy�Y����o*�k'�X�sCg�EQ���/�����4��0���G��~��G��N�����|���]����Msy���8�o�
�����t�M�<$L�����#����w�t��&U���L7Sq?!���D�TS��R*��\no�1����m��5�X��5z.?��w��Je0����������;{�s���(��g=+�z��2o���?�&�1��
�x�!0mT��$Iww��q#]y�����k���(������~�����D����<^���Q*������F���#�L�p���?��\}��
��J%��Wg�Riv)L����O�y��2L�r{zz���}�}������x���W����t�I
}v��z{��������M���6�s��4��0������=In������a�o�����<��������L�c�f�j5I����Z__j���}����T������m��$)�JY�fMs���J�$I��o��c*�����j/�����Z���R��vf�;0���eA;3��f3��@�
��;0%V*6ReZ�M7X�dCoo}���#tg��Rh�Z�������e��?�j��%��	�����Y�c�=6�����}{�����K_�R>����1�yL��G�O��O�u��$�UW]�G=�Q9�����g=+��v[��]�zW^��W��Oz�9�����oo����6�]�M?�I6�]��R���\^���2X����V*
9����s�Yg������^�#�<2�zh��?�3?��O��_�"�����'?�Z�����%��'>����.O{����7��~��k��[��V~��_����t��_��f�'��E�{\�xb�Ka�����L����������<%W_}u��Y�w������+r��'�x���,X� �J%�~x��W���������q���ge��I�r��o�1K�.���f���R��������R��e�`�e./p`���X[wwj}}�U�
���{����aC��������(�W�Wy��8�v�]w��qKK��q[[[�������m�~�0�=0�=��3�$m��
Sg��2��R�icx�S��o�x����y^������}o�<���z�����?�{��'Ir��w���/{��r�m�e��5I�O}�Sy�����f��C�am�Rj�j���05�����L��r�zzR�V�����/��
��7�)---������k����}m~��?I2w��|��Nwww.�������i�l���K��S���~�0[=0�M2!mGh��2�o)��h�Q�h��e�������4QQ�T*)�����9���yO���t����{��l��jU����g����+�]";����dlsy+���i/�G�vnt��,w`J���#0�������0]�iv�nM�R�)f��`f�����<g+�h������������!�2+6\*�"w�uW���f��`�����d�sy�;Ms��Gf��u���;�]��ikk��G��2`���y|2�������7o^J����:�lY��5������w�N
��y�hw�f*��T���Jm)���]��0�T*����P��t	�a�������VkI����c���0��J;������1�|Z��4R.����Kw���0�����v������@����wh�;4��@�
 p��@����wh�;4��@�
 p��@����wh�;4��@�
 p��@����wh�;4��@�
 p��@����wh�;4��@�
0���o�RI�ZM[���r����� p�Yf�R��������G�
���2�j5I���=b��;�2m�R����7b�-e`�M�~���r�zz�TM0�`M�~������f-e`�����0��r������;�;L���/}�������-e��������������|��o���	`��\N���M�+���^]_��hu������sNN8��|���MQ��o����<f��h?��3�L�V7{�
SY�����\r�%�����$---9���ux`����������}*���mp���R�Z�f��%y��_��O>9/x�r�M75���0���cW��N�V7c�
S]��m��e��59�������<�y�s��W�j�m.���,[�������n���`,���\f���[>��|��U��T�]����J����UWe�����a�h)��h��n����p�	���;�$���8���s�=����e�r���7��`Zk��x_����<Lg��-�`���o{[������\0mjg��yn���K�,�	'������I��}�{9��ux`����3�������vv���ONkg������a��&�?��?���~u����,^�8���'yx`������^���t����a-e������mn<��F�TR�V��N'��vf����
]�L}����
��s��|w����j��R'�`�T����>�����a�`���o{[�6mJ��EYz�S�NH�9�.�|�j5I���=b<�\~y�_�6�~����vm.���%�n	�`j+��$����������JK�����t��L���+V���K340����t�X���`���Sa#��ry������,�����V0w�dSi������t81��&������R�V�(O��f��@lY�>��Y��y����<���&�`����V���#�r�g4mU�p�_��1���20��W�/\��t7K{�����)����;L��������8w�$��Jj�j>��$��f�;L��J%z{����a;�06M�IP�V3���b�����{�3��0I6�]�"IK�&��&��O������kv)���$h+�����$i��L[����v�������0	���t��L�p�F��Xw�$����
��7nm��N��/�juJ����f4�p[�Z_��1�o�p�Yj*����L���Tks����h�R��f�;L��J%�_��������6���I����I���8w�D��J���m��vm���/s�����=/C�U��zV*���[7#���dN����V�fh` s-����Sl�����U���T��Z����{��7V��$j+�����-7��"��N�A/zQ:V��������o��7w�D��r�^pA6�Z����m�\���+�VKWO��� wh���-W�jj��^.��A�p�I�w:�Lw�dz�����L2��af�@��3��2�wh�;4��@�
 p��@����wh�;4��`n����J%�j5m�R���f�S�����J%z{�����;���2����$I[w��10�����R)IR��1F�R���r9]==z��^���j/���Z�@����wh���V*�U�i+�l�
c$p�Y�RL�ZK���r�}�u��J6����]==Bw�;�2��`z{7��==]#B�Z��$i��N��/�jU�c��;�2�j-I���6b<��TJ����F��=��f�RiG���W1�^.���'�_>���t&p�Y�\nOOO�n{��t������{'p�Y�\n�m�����B���7X��V���T
7�>�0~w���J%z{�c�Oc���0vw�����d*��o/�g�k	�E���6[�X�����im&�>���l���,(�3400cV��L'p`��I�O+��_zi��������'�8#V��l0��@#V*�_�:��J�K�/�j5����<���}t:O;m��L���
w�����|x5���@�/]��+�\0Vw��Z��$i��N��oZ�<��=�a��0���J����UW�u��i��|����T�0wf��hv3�Lj�����L{��v<��i������������akGG��_���/oZ-0]X���7�B���7b<M����mz6]uU�$��^��+�r�=�0����F�����r:O;-C�6eA�����i�-L�;3�T�htM���+Vd��Wgh`����t p`Z�Tf����J���R-0��v�W���^�9i��lZ���2�V�O�Z`����`<+��v��������2��_�{�Lw��Z������.Z��M��}`@oq`J�R�i��TJkgg���340�%����	0%44p?���s�d��yI����9���@���0����<g���0�5|��w���,]����&�y<��L��s�R�����x�m
3��0�o���=bLm
�����d��������l�����&�y<L-������F��������W^�k��6?�����_�:��G\�Ee��e�?w�}w#�{��'��0����|����4�RE1�����\t�E��7����,[�,�_�D<<L+Sen<�y|2u��f�yn�����w_����$���P�������Nj���	`�3�Q����������}{������?>�7����<��`�RI�ZM[���
�T
�K�R��Y�����<��n�R�����X�s����d�U�I��������c+��f�0m��JI�Z__�2+��f�0m��������h���w�;0Y�Lk����P}x���
x�� p`�x��w����$p`F���w��0���L p��@����s�]��`��Z���R)��r��h
�;�e�R��������G��JZ��_j�j����{�`���_�J�$I��o�`��R���^.���Gw`�������)���h&�;3��[�f������@�	��l�
4��2�6o�M���1U6of'-e���wh�;4��@�
 p��@����wh�;4��@�
 p������+������Ji/��]��$p`�+�l�����zz�����{T�V�$m��#��d�;�,��v1m�R����7b�Hw�Yl,�b���t�����Z��bcm�^.��TJ�Z�`�2i�L'V��b��a�_�&�v{;�����X{����8#C������V�r�L�8u�RI���V�
e�;��ti���S��K�Z�z}&m�j�>0Q���X����q����ww�`_�f���������+�lY�.C��3b�>0���a��<����'<!+V���
L��0+��J���3��<R�4���Ya&m�
LMZ�0+���_��I���1z����4��@�
 p��i*��`��Z���R���@�	��+�l�����zz��@Ci)��P�V�$m��#��"p`Vh+��$���c�F�R�Y��\��g������r�����pwf��J%W�J�BK�j�RI����T�]�>���hV��G��J6����]==�re���D��G;�����V�N����\NWO�v2����G3iex{�,h&���=�2`l�����{7���L`�;{5X�h)�w�h�R��������G��Z��G�j5I���=b�H#����|�+_iV-�>0�`���JI�Z_��1#��[[[��������<���^.���'�q�v2{0�����+���~6[�liF=�>0�`�����\�R��-EQ;_0o��

%I�����(���2!�e������o�q`�����d��sy���x����u����xh�Q-e��;��N���1Ir�w��n�����3���������>��|��M�

��3�����q0�����[��7���,\�0I����M�6Mza�����H��J�W��`���R��Q=�������R�j�<`_U`�1��Q+�l�����zz�^.7�"��RL�ZK���r������7j������s������K.�$���s���7�6`���h�Z��$i��1f��T���!�VmLo��T*��.	f�Q������R���N:)����r�������kFm����(m�R����7b��S���$�Y�~K.�|���Z�|��_�+_�������_���}-��8��cg@�������I�ZM[����V*�e��-��������K/���Z�@�Z�����g���������g�}v�����<�Fj/���r��}����I�,\�#�^�4G}6}��W��+���������}����ghhh����+�i���V	��y<�^�j-�>/�7o��MC��R���e��V_��}��l��-��o���[��,Y��~��c:X�V�����|�������1�`"
V*�_�:��J�KaJ��tv����-G��s�Y��4YKQ���p�
9�����`�7��>��y��^��s�f��m{���e�r�����c�L��s����'����`��
���qWO�3SP�2�j��R�M�M���xT�������������g?;K�,�����������5�\3b�������l�������{?�0l"����<�lT�V�$m��#�L-�r{V����1*p����tvv����n:::�f��� w�G?�Q����tww�������P�>���{�����}�������:���>��&r����Fm�R����7b���}�s����������������5���u���^���x���x�����#�x��\NWOOj�j�J%�d�	-f��F��R)�{�����?��w^6o���y��x&B{�,h�F*����n��{z���0�F������SN9%���w�����7��.��������@�ZK�tw���gT��`����/����s������%'�tR3j��<(�v�}}�c`��j)���}/�{���~��,Z�(w�}w������6���x�\nOOO���D�V����o�W\���?>w�ygV�Z��>����
#�x ���\�)l�&������#���n<���s��WNza����@��j)�`��

e��ey����?��lFm���@��Z����|$�7o��>��T*�|�k_��>��f���y<4���'�|r�d��E���>5��g�7*p�T*y����o����1I����I-;�x���Ts��I�+:l0KC�
�O?���}��9���2g���3�d�w��`����Y���$-����\p�R�;
3*p_�pa^���5�`���]�Z��MCY��5I200�j�&p�aF�g�uV.���<���M[[[���<�!�Z0v��{W*�e�����������5�R�^�c5*p��iS���w���������$iii�
7�0��cc�w�r{.�`��L�Q��G>����7������z�}`06�r���	3*p���Nggg3j��y<��U*��Vk)����4���}���y����N;mD�������Z0v���S���wC}���%tg��
������}h�d����^0~���s�����-)�d``(�jM��~��w�y�����cW���K����%}}��x���Jm{�#���f0���Z:;[s�i�9����vZ���4���U�W�e���Y����1S�[�l��!]]]��'�x��+������j��R���v����%/���`���g�Y�zV���4�.`���M��.h�����e�]�{��'���w���������G=�Qy����g>��9���Y'���LE��Jj�j�J�����.`��EQ����(r�5�����v����d��E��~��_�lY�������F��'c����{��J6����]==Bw`F�yn<ww7jii����<�q������[o�u�
��y<�V�V�$m������V�
��Yc���q�Y0���lm�R����7b��U*�6��in��;�M{����=���RLo������K������j/���T���$��m����Z�	�a�������������s�=#n���}m2k������]0N�R[����6bL/����G���~4�|����,��G����I����=��S�q�7��o��~�
7�0�%��\nOOO��0�������~��ttt�7��M^��d��
9���SE3kv��c���������I[[[�������|�{�kvi0�L����r����z�^E:::�$}�Cs�W���~v�������4�@`����o���/��^��������+2o��u�Q�.
f�cU�����������_�x��|�{���W_��k�6�8`�^������F>��O��3���m��]$I+���^��J������74�y�@��]t����,�����|�K_�����;��C���>����#�8���@+�l�����zz�^.7���n#3�������G<������y�K_:i���SO������2 �j5I����Z__j���
��F��3N�{4g�7I��GMt@����Lm�R����7b<]<��L��\�)l����������
������'� `��������t���V���T�V����������p�������O~���b��E1�F����Z06��Le��������������IF���������r�����C��Q7:��#'�(`l��`�����P}��'������WK�Z���{���-o����.o����g�
��<&��Z�<PK����N�e������o����1�����^h=��]�yn<w�+n���|��_��u��$K�.�^��}���^$06��09vn1�+��2�����g<#w�qG�=��{����o�SN9%����Y#���0u�[�w�q����E������@N>������O���P`�}�7c��������sv����u��wu0u����P��~��g���O�g��#�<2Ir��7�K_�R^���7�@`����
+������Ji/��]@���7��
Y�re�������E����G�K.�$�{l3kv�<�f�T����>����q�{�2�j��R�������yp����-oyK�$M)
;�x��V�&I���S��K�Z�Q�{�2���
�qOO����z��o�=�z��r��������q��C9$�|�+�a��=h�x���TJ����F�g�j��$��n1��z�����$�~��s��7g��
��aC��[�G?��y�K^����0������t����3����dJ�A{__m��R�����T�V0��EQ$I�\N�R����������u�|��e����~\�n�un��y|b.�������;�yn\_��d������k�l�R���-[�/��/Y�d��W	��y<L�r�=+Wv�Cumf����_��s�e�e��%9��#s��G����W\��/���5�a�o�63��CY�n��2@��Z��l���)�"�r��>������O�<>1��Je0�_>�K/�Oggk�e`��eK��|��9��C�����Z����`����9�����l�Z����+���LV@������Jj�j�J�����.gR��Y���lor5�T����v�m�����l��J6��f��U�����J��%M�r�=g�qp���1'�Vm��f�=��^{�d�4�y<��V�&I���G�g��K�g���I������R����JKK�no��O|bR
��<����TJ����F�g���2}}�c`v��Oz���$?���s�u���/~q�d��Uy�#����=2�`*h/����3�z�';����t�Z��TjK�����������1i)�����|������7/I�e���X�"?�������-���_����t��s����'��0�'����$�Vm�_�����f����sx�]w���[��'���m�]w�5��b�K�2���
����v~}�������,_�0}}�T�5�5�5*p?����{��{y����$��7��?��?�����3���ex�uww�x�����e``�>�������o~s���g��+�H�|�_����'�.`��f��JeV�Eg�l�:�v~};;[���<�~�����=I���s�QG�y�{^6m���7�������q0��Y+�l�����zz��ST3z���uby}�Wsx��>����e/�9���$����r���Oza�����<�j5I���=b��2��{�������Jep��\n������	��e_�
�?����G?�Q:::�$�sL~���Nza�����<m�R����7b���s������4����2���x����Z0~��3O{����=��8�����
���G����d�m�����.������>��cd03�����)N����}���F�������[�.���y��^�?����>����12�����{fkf�~����(�f=��e�r���7��`��ns��V/0��c�zu>�����������5�yPV��lvYL!;��G�����;�/��/�����m����S���
�q1��jx�����.��^�]�9I�����0��
��������|d���'����5�d�U��c��������R���{q���+�aOF���{o>���6�`��cU*�%I��j#��Z�����:;[�^����}�����k���>����<�'<aQ�d������\nOOO����I=p?��c�������|�c���K�����(����n���u�`�|��Jj�j�J�����.�����W��hb5�G��.hgL�������f���x���T����>����3�
�o��hM��9�_>P���m�������J��p�
Y�ti.\�$����r���6�:`�����V�&I���S��K�Z�3��Jm���UW
$i����1�^�_�Q���%t��0����%/��y���y����/}����y<@s��JI�Z_��1LU�r{N;�3G���N�L�l�4���������MS���FL�����-[�LjQ����4G{�����	���7<e���\}����c�����A{��������]����������'=)Ir��W�������3�h��r����po����
��s�I���
}f�r�===]������p���0*p���?��O?=tP��H����4�6`���f�Z��������2�iSn����uV��r��p}����v�/_�<�J%����SE��r��u3`
1��Y�J�
dh���.Z���%�]xa�/]���a����6M=��S2w���p�	y����s���SNiFm����,��r?���}t����Ri��H[ww���&��bx?���8�	!f�QK^��������?��������3��y:W�L[�T�7�Ze�0S����@�������y���������??IRE8������oZ������l;���������f��2��{n�n��7�����eK�l���[���{��{���1��SN����s��'���O����;a����'���A{����+�Ly;o���f�Q=�����>I�q���z���?c��/9k�����k�t�������?���\h�2�������?�}�k�~��,Z�(w�}w������~@����3I�}����������<>1�k���$�X���2�UF�p�[��+��"�|�����Z�*�}�s�|���9�����_�:��sNC�vm����<�����o���l���f��nT�����#�8"��mK��~�����+�|�������[�t��|�+_q�E]�e�����}���Y>���<>1������v��dhh(��-�����|�_�����:�����/�������}�������:����H��y|b.�����F���G�y��|�CJ�R�����|�s�����a��$;�>^r�%9��_10����sy�q���t����3�HWO����:-EQ��b���Iv���[o�5�{��R���}��<����G?��,\�p��Y�lY����}(f�F���;�O��`�<7���+����;g�yf��jZZZR*���O}*���x�#�8"��_�51{�����\eTK�W��9��ss�]w��;��;����y��M(
+�xh�Q���-[���>�>~�����[�NjQ����S�`�����3X�4��T���<�9���?���7g�����'>1b�L=����0��l�R����l\�*z{}��UFm�:o��

��Qkk����d��-
{p-��;7��y|b.�?���a]==i/��XQ�U*��Vk)��R.�7��S�����jU���S����g����+�]L�=n��k�0���L�j5I�ad�Z���{�2���
�qOO��}�k+��$���c�
F�La�H�j-��C9��9�����Vk�i��\NWOOj�j�J�Y}B��G�0�����]�9I������ ����6���`���0rO}�O<qA}���u[�zu�~���$p`B��O{�������u�^�_��L7s�]3[�ZK�tw��'I�������q��9���tv���v����	U*����vl��n��T*�������\��+:����~���2L��U��_>�K/���Wo��Wo�2f�v���0�Y���+��s�����2fx������L��[��<�)��`Rh�tw&M��.hf,�;�4W�Z5S����E�0�U*����P��t	�`���9��4`�Vwl@���6b<�U*�Y��?��`�K��2>�3+���RiG��f��jr5�ow+���`:������3s	���r�=g�qp.���tt�f����:��yEp__�>�����\nOOO��E���23�����|��$��m��Vk��tV.�g��Na�,a�;�0X��V���TJ{�<������[��?�����E����3����+�l�����zz������r�.�CQ4�F�Ts��I�+:���
I��d�j5I����Z__j���W��.��	��Z:;[�|��z_���\��Je0o{���]�9I�K/��,�~�������J�$I��o��fR����Z�e``(����E���iHO�q�T�zu*��f���������t���s��n�����J��tt����$)���6�'@*��i�9�T����>����v����L����}fr����\n�,mJ��X���Mk�L��Y�N~L��Zk��A���4���L����L��Zk��A���3���4;�n��3Y�e&�Z#�|w����S���T8���g���t�+������9�M0X��V���T�Y�~�U��s������[�%����;����F�g�
�e*�T�������������\p�R��6���6��J6��f��U�����J��%Mk��oGGk�����/��y�%I��zSz{7�Rlf�IvvW*�Y����~}�8���Z�>���O�j�����,Z4'��f��������
w�IV�V�$m�����l\�*�q�������=]�Jm���UWm��*����j-���Sj�{�'iJ��F�g�	}�'R�������x��$E�����������TJ���fM6�]�dG���S��B����\n�i�uf�����200T���
��������L��,����d)��s�K�p�E��g�����������U��$�/O��/�j���zc������MJ��`}���^�~k������:eN
�NH�.w�������W�O��r9�qFj�jj}}I~��=�{���O���R��U��1'Cy�k4ek�N���}���|��t������2{*������a�����+��d}�E����.��j���^.�6H��2����7��:�F�d���a��&��5�['����gO���m8����&�L}�����w�d�
�=�l����������?{~��b����+�u�t$p��*��q��U�������g��y[�����?s��������ji�Z������9��l����ve�|���C�0U*����P��t�)to+�����f����r@G��; ���
�l���)��4� s�]�U��$Iww�������9���*�.Z�;��-�;r�����:i�'��E�{\�xb�K�Y�
w�)�T�����F�������9�;���
9���Y�>���Ji��L��vv���Eg����Lw�)�\nOOO��{�[����Y`�o,:�7�ef�LQ�r���vf����h�ZM��uw���7�6�e��Lq���>�t��l�EN��o��*�;�V���wC}���%tg���-s�y�SX��c��������R����*3�e3��f���JmI�����1S��SX�����.=���;�W.���-e���wh�;4��@�
 p��@����wh�;4��`n�`f�TS��R*��\nov9�����;�RLo�������d�8�x���l�Z�0a��Z����m�����av>��j����nH�2����%�;u��`V��o��TK������1�8��@#8��Z��db�6Z.�������`�����d@c�I2�Lv__-�j�!�r��&�y<�7c���d@c�I�L6LG������[0N��?�;I�����<��}��XW��kw������<���~f"���m���`��Z���R)�������-�j�����p���w����0�������s�����#�������e�>��|���I�$-�-`��L3��Jn����n�1�����;�juT�>^'���������4���0s������H��E��)Ci+�����R[:;[�$���{���hw��+�l����w��Af��R)���i������,9����7�x{�0����Z��$;�6��7��V*�&O
�5&[{������~�y��^o�wF��45�U�Z_����T*����]�n�w;��^�$��T���wC}����5�?���;A��^.�q���L��������g��[o�5s���s�������h���f��M�����~,,j�}7���;S.?z�����Z����-}}�T�5��~bo�0����\;�{e����j���q����hN�4w������]~��_��k��UW]���o���]h/���r����=8�$I6��c���&B}}���n������]NsU*�Y��?��`�K�U��L��3���O���?k�n�������
��a+��������$�?~��G���on���8fE9�.]�M������9f�MV���6�2e�'"���z|��9��L%��3���WV���$Y�|�o�L�	���q��|���w����8<������/x����L��JS����
	�v����=]N�h��^w�*�x`6�-e����q���Vk�L���[�l�����7��
)? �����r�E��w�}w����m�3�V*��S������>?!���|"b,���u�^w��=��sy`f�me&s��l9��;

��������4��/�9��3����>;g�}v}�l��F><0���$I[wwj}}�U�M
��hL7�u�^w�����sy`f��e&c��l;��+

�_������#^xa#�[m�R����7b�,B4�#�:h�;S�y<0�X(31f���jX����(�������?<�|�#�$�z�������z�Q���t��L���B4��x`6�Pfb8������O|b��h���l�����d�V�4��i*���l'p��M?��`��Y�RLo������K�����`��gO���W����?�������j�&H�N\0����7s�]�T�v����'��v��f�2mU��$Iww[����j��T*�M�
g����cf�;@�O\P_��Hcm�Q*�!����~��Z�Y��1������0�;0��Jm��lM�tv�
�v2��r{zz��j��$�����W���c�3��;�#pf=!����Bc,�y���3�88�j�*`f�r���vK����
V*�U�i+��^.���l�/-4��f+�;@��oH��q6����]==�:�����Kx>SN`0;�u���;@�oH��Z��$i��N��/�ju\��]��9��x����S{#ph��
�w�V*�8f_���X��}���L;����C9����X�����x�)�=�4����;k/�������iv�>��_�������5W]5����\}��=~nK��������hQ��7�uB��	��hC�]o����1V�2���[������d``hL�����9!��iv�]{����+�;l��k3S���4�����'���=n��Z:;[��'w����~�i,v>!�����
wvkWmf`*����c����I%'�x �;{��630��s�?'���������?'���bgw�*�A�u����$;����
�qOO�����*�;��Z���cww[��j�Vk�C'�6��05�JmI�����1�g;���y��c�;Ivl�����-���U�PW.��a���b���`��Z���R)��r���v��"���7X�dCoo�d��?�����+�0N6M�Y�V�&IZ;:�y��l������7��J�+��E��U*�Y��?��`�Ka���JI����U�$�oe�p���2�V�2���
�qOO�>�3P{�����\~y�/�4CI~�c#p`���Z����5���\~���}�j/��^.�c�
���K6��;�;�U*���(W]5��%�^��+:��3�p�;�yc�$����9�=�`��O��T.����:s��m9���tv��W��G�Z�P�m�2�����nX���~�4�����MJ�c�;0�l^�6E��f2�	�`^Y������Z�����	W.����+�j-�R���RN<1s8 ������LYw�al^3��������1�g����\n��,�V*���3I�����R��MMw�Al^�TT�Z
�@V7�w�������8#If�	����2�YE[wwj}}�U�~�5�l]��3}�&������]�l�D���iv@���������lY�.��J���z+���^=������6�Z�
���`������c��v�w��c��j��;��5+�ai/�������/O���f��Wg��W;����:+k���0�����Y���������^.�V����B�;����g�-�dA�����	{m��`}�����
1�������������$����J%��^�-}}���e��'N�k�F���03�~��l�^.�=7Fw�����6��������W�J�i�M�k�F03i!	���a���6��}h` ��.M��M�h��J��`�T*�Z��>��b`��_����5���_K&S�2���
�qOO���h������{X-��3�;0�L���3�k�V���S���$��m����Z����q�������V�����S�L�Z��*������s�����.f�R�-I��W1`��yet�i�Jz��	a�L�/E�0E����V��������M��r���[�S@�����.�>�B�{�`b
�������nK�d���I��*��j&��35�h�;�2��Z*�e``(�6
e���tt�����r���"�1Z�V�f��?���l����l��,H����r��l5S����_4����{`��s�9<^x{::����U�
��	-v�~>�m�R�2�iSZ,��;��}?�YZ.lvi���zf��P�=����te����Jm���3�����jnh.���\������/�0C���
e�I'�e�x�?�4T��c���������c������b��v77�M���i+�2p�������vv&�9'�`&��P��b��j#���Ll1`n�7���c��w��]����"p�������ti��!L��x���l�=��h8�cfn8ylP3����g�-�d��%���7���1K^�z��&p�����a"7�o�?�_+�.+��_zi��l���d��l���l]�>K/����%p�)�����-&j��Je0o{�����5\�t������8a�TQ�Vw�e���(�����2�iSj�jS>���ww��&r�2c3z�uw���W��R0;Q�^~�@����E�������������k5]���m�R��2gNZ��O�uk��uW|�J�I�g�'�f+�;�����3Q+���`���WO�`vo����h������^��d��0���yb��\�����[�??��-)��2����^���|.�{n���_���X�ry:i�J��r9]==#j�_�:��
fw�A�����X��K/���MC��n��{���^��d��0�m&�d�o?������q���?�<���h���e�vd'��$$NRlRn���-t��%��m.��o�[J������� ���
J� ���cG�e[�E��4�F��f?�����d��w9�����,��s>�s>��y^������O?��t"��T=��M�.�u���M�Ln��s�j�X��^�l,��NE�p/��
(��
(��
(��PP`_Y�O��v�RQ�;Z[g]�z"f/�mmu����4��}���s�	�� ��pF��mw���Dg'�u��:�Z�l\igo������k��iPU��2�[�\�q�������9��Z�7��{��@�P@��;%4��r�P@P@W���\v�B��w�j���I�}��������D�FIuu�\������w�l��:z2����0��4B�t������Dg'���h���2��#y��dZ*�M��<�w���
�{W�:������N��
(��
(��+�w�{!������$��z_���h�Q"��f��H$����k�#���Itvb��2$:;��5��v����c��0H��57#�|�lZ*�Mv�(�o�@�pU�TBX�)�����,��
(��
��x'+�B���<X*���W������������������b1��R��=/�@f`��-���J;�|�6���t�VWckh(�A3(�o��;�p/(��=�j(`����N��
(��
x;�`�p=�`g^>�Uv�RB���\�:J&�m��Z]��H\�y2�Z4J��-g�*������hm��ss���k�+�H�m�T�b�����x��e���R,�l\���z1 !�P@p}�`�p��`g^\��z��� u��������{�8Z[)��9'�;W:��k{s3Z,��#y<�W1��|)<�#`�RWK�����A!��\�c������/���N@!����z��7#�]@P@Ks7�K5jr�m�X�\v��"f��^S����!���S|�����H��Ln��26F�y��������Uyic���>��O?����� ���d����.-�]���!��Fx�$�wI.�r_��}����6��;K��CW��\@P@,-��\�Q�ucW����J�zMe�O�z��)��9�b�4qp�5m�b����{�Qo��A�G?b����#��#S��d�����Q�Q����Y�l|�n�����bx���LS3��0�.�ui� ����r
��c�<�����'���[�H���l�B&D�xL��r������!��zT���)�VJ��hTAP@p�a>���i����,�/
��(�q����'e}>�G6���
<^	������8^2���8���`��+
��N|�6]�������
!X,(���::fE5���I��$����QD�=�X�m�s�ut���Ln������
��m����]]H��^&���Y�g��R���Nw��&8�n���b�%��Y���R�;�p��=��cog\K%�R3��}�j�b:�=VEs�}����
(��
���Z�dA�X��D��8�cJ�����z��v���V�77c-/G0KI	�u���w>:Z[�m�H&�R\��(�����h�(�]�=G�E��q�e���E�������������7 ��4����1�K�x��j6m�]�k?����1;V��Uu
��=����R�~�
�Q�{>
��x'�Z+a��d�F5z{3��_����V|>	8�3���/��
(��k���n��,��}�a!��@h�}p����c~XH��hme�SO����R����7�<x0�j��ap���b1��W���F*+C�����o��J���6��b`� X,`����K��r5����h{;Z,��|9��c�D���s^�2�8���7� ��-#Wm2L�Zo��Lw�������i�����b����
��%����b����\d��\:((a����N,��kx<&��k�z�����B��
(��
�v�����-U;�j��9��.���|v�R�pyp�u�k~8�Z��n�Y���{r��R����~��a���M���E��%%�^�U#������f$�TCUAU���������k6��Z����6"mmX+*(����vdm���b��� ��HhWM���p�b
P��G7�\�k^
�l�w4�>.������T7
�����#9y=;
J�3hmu��cUl����r?�3b�(����B�^��y�yj��K�]P@\���	������3~�k�R�?]���b�S�������+���\�C�(N:��������h-����f9E/����|�xF�lA�z�|��Fj��o��r6�{!���}��:-\����Ouj
���,{��\��m
��$k����E1H���&f|�r:o'f!�<\N��|��z�(����)L.7�W�\#�zh��b1���M�Yy������(������a����\��R}7�j�
(��
�p,dO_�M�R$vav��.9��v_���b�������:���P[g>�@�/���-y��Gk+��7����er����E�dz{��qF�l�*�e>I{�T����kM$�8$:;�����e���Y�D&@�04�J��Q$�X��|�����T��o�\(�y���������9W���[
���@���tt�j�
��|��F����K���#�����s��m<�z�/���\�s�%{?Y\L_�k�Z*����m����
(��K�B�����-Ua�|���=�����z!X��})��u������?#H����b�?�i�\��z\��3��<�9������;�.���NUc���������b�\�����%����^��pn���C|�����Z^>���H���a���ssE����Z���3�	�Q�p������s����s������\k��b��=��:����3���4_�B���$ ����'�/�����
��^�$���e��z+p��y���Yh|��������1��EyT�����p[h��_E��+���N|>���������\���-�vP@py��f�\���ag.UaL~���1�m��7con^��`)*��v_���b(�}=z�4/m�O_}0�����O�
Z4�o�F��Y���"�����YD�bl��R#����L[s-����;�w[r���X��������n��T0�!?��6�V���J�c�]��.�r�,v
)����6mb����`w%F*)A����QZ+����k�a��~x��G�(�=�n"xA��b�}�b����^�9�}��W�\�.�Z1�����c����C�r.,��2��x�b1�:��c�.l�����G	3�2���WT�q���R���6��j_H�.%�ZvL�DK��+�M����.�8]�-�@�hT#QQ�[���B�{�yj)�����m�����*��
x��J�$m��4���@��@[n-�v�R���^��.���<��k~~A6�r��I<��E�Y�"��.d��O�]�%�c���K���m��^b��N���������������	_��O?=��)�J�d2��N0(�v�3�n-��in�S�A��O�����3��z{M{q`@��O�:�B��}��uz���w,�b��}Y�����}�x�a�>w.�����V��i�eO�r-����*
���m������n/���L"X�������+�z�;�p���K�=|����L�3"�X��,���7�r,~�Z1����Uw����S��|XL���f;�4C���[��~�1@mw���_�S����&���Il�X��������]I���>�K!��7?�����
��l.�0��6��TZ����������v����7_�;�����+�,�D":##
uu��z�����u.�����nW�KQ�Y@���$I���{[�0|y��O:�x�ut\�T�1�vMn����[I:D��+�K�vd���i�KQ[kEU
::be�\*�S��o������;���9�]�m{A���9�������Qb�v!y<:P��+;R�1��������96��A�LM�E��O�@��B���M��fu?��{�/~q�hTEQ@�s�u
�V-g��{h"�������
k�����q�'.hx�h�Gkk����e���Y}>w��c��x���}����z%����c�J"�V\��0��-y�"����{�Dg'�����������\.``���b���/�/��mk��{��)}�5WQ���o�&��������	R@s��!��'n}g?#	���_"D�e�H����z!	���_���\���b1}���B���p/����O��m�$cc*���=Si��~b�^7?�,�s����O��R�������n�;��+�n�n ���>�B�{�������[��]��s}y��w���bI���8t(IW��	o{�I<�|y��|�]���	��������K~�P\i��NU��k��+������;�����[�dU0C�>JTsu���9Oh�(��;���#�������#v�ek^-�?�4��lU0m$��
g�;�l��-���(
��
_��

6d���9Q���o�~?�/|-C�z��I�4�e��`��>ZJF��������	���e���w���}���y�a��]�_�2Z4���<�9��CsskZ<���W������m�hT��[]������(/�0|�L��%x����[Z��XQSW����m��04
�� ��?�[F�%�f��/q�X
�U���Q>����3�����|�Yi�uo|>)���utQ���Lss0{�	��*��Q�]�bd�g^J��}���'�o��?�s�����m��r�������]����s�i��F��"36�(
X��s���$i"H���L0��\�v���r���L��T��
�6H���w�F�X���=��Z@��5%��q}Q������B��2���6��_"�2�s�$�� ��H^��/�9����v�G)��~��;X����j{���`���l�����W��������g=�zh��iz�uQ��i��d��8�F4�Y($SF���9���N��}��S<�a��LN*���O��#�tu�����Jm����B�<��0��B#�����m����������1�m�$��6��/L���������,�����~5��VG.EX��w�BH�����xY�������F�s��;��%S�K���Z�tq|��$l

�=�@�z/�R�\v��v�g�fz{�54�{��ga���X����v���#�Q���:+cc
7���_���ut���B�x��Abj�zE� �������_���p��\���h#���o�4�|�\?���	��&���"�}����C�&6n���`���Y58������
}�S�vz�����Q/�����F�X�77��T���}�*>���x�Fut�T�/�BL��X�!��I��4��Z�'���/�:|�����nE�#��e����z<�%q�O���d�
�������f����;Noo�PH���������FPk���}�b�W;��N�v���k/�}<�{����31o1��V1��L.��r+��k�|)l���G(�����NT2u��� �������Cn����bAG����U�������;UT�|6���>��}>�7n$�����q��.�2�Z�����A
8KY�Z�x(�RqM	��i�/y8v�]�/��+~���3n�H���rs2QC��<+�0�����u���bH�?�W����X�9������g#[��Z�v����������9Z[��Q~�5S;��n&���t�__���?��N�>a��6��
^�j�?���CQ��q�[G|�F~�A�/��X����m��S]����Cx�6/U�
vM���1�;�������l�?��&I����fa�����`0�=�!�p����g���.n�Y����	�.&�RO����M������;����B'������>�b��������0� �|�y��������#��s�b�Q��6o.���$��Q�X��g��\�x5�����}�;f�#����0\}7��|����x��Z:����P��s��{��,��]���oG���e���C�g>��u�\�,��<t%&�s�I�_�R�\v}_G�B]�^AW���8����Sc���d�o���WI&5 ���.:�b`����NQ�]k���.h���V�Z(�������U�Lm�*��&������0H�c��I�"�qQ���qw���a���[ou�U|������I��}X$�H.��8Br�� ���#���b��F��V�!�����O�cG�[@U
��l4���u���������F�������`��j��7�e���y8��8o�d��.>��J~��x6o.e��0-f(Z��76@&�uS��q�U�?��8cc
���������
����:����B����9�ff����ut���@�Y�`[[��}�Y���WF����������l����s����.����>�����,���eF���s���������^;��=,����Z<���57RG�U��#��kR�M3�e�$��By�%w�*@��������a�����:�a��j��k�b��]i���8W��Z*�{!���K�5%��V�hTc���^3���-��^z!��c������\�v�n��h������������
/]I�]��w���OQRj!�r��+��4*��{��x���~D����'��E����Q����{�?�p"�]D����k\�����,%%�S��
S��}'������|b�U\)�e��(��~g3���3�m$�0�p��������M�	�_�t�Z'wT��h�#����1>�����p�#����t4��Q�������[R"Q������p�D��_c��Q�a&�o�
���G�������dN�����cpV�R�?l+����o��	�:���$�(a*0<������;����Wp��^>o�Z8���� �7�����r���������m�?�,�lL���������Z�F��CI�na�Z�7�u/i����.,�"��uD"*�??�_�Um�^�Gpg
�x\����S��,�����������g9�����������D�L`8~�=�n����Y-��h�(����H�������0We���K1�

���k�t*�����kSC���R�����r���D#��C���d��oA�F3v�fN�<t�$W���v�uu�x�����h��I��9�����t*�r\���in�p�S]�3~�5g�$k��<�arRC�
N���l���6m*�`{w1��X�=�*[qI��Fp;
�<�>�/�R��>,QJs)����]+�:��	�Ey���NE�����?�m�7�G	��r����H�����oS�������V'��n��^��e��W���uw���`�=����u�C�(Eu��x��������ur8\���$�L?���~��Q_oc|\%��1(����;c��W�GY3���Q��>2��.���f|>9���h������,�2\N���/�"D�7b<T�f`�@ C�&���4����Zo	5�WA{���u�y���R<�4��*�Fy���������9�����#FV06�������
}�$�����5�x��,�MggY��eH$t�~z�,Bw�/��Qb1���3ci�X�Xn��?���8�F({<���>Ed�6Fcv�F���_�/��������������a_�-�����:~�������X?�������>oh�a<�=�� 
��m
����}Q����N�={�D"%%���}��=.����}0H]n_mqbA�s�0w��C���%��:��pku�E��Y��\
�~pM	wE1��4��`��2�2��XI�t�m��������?W�}b��	��Z�*���9����%|
O^����X�����\���N�sI0����'�LOw����'4F-u����+K�g'${s3��'�UT-G	��������r�(\l�,vm���X��m9�D�&��|��1�V���&��Sj���"���s.�E��F5#S`��)��#��(S��4� `UF����O�MT�Ks��H05�!���VB!��f{��oh��N�l��c��VB���G��*��d�9v�����*j�n��u�����?�����$x������V��.B_�	��M$.r��/������q=����B<��qc1��I��:�n!>
��"��0��!�tcG����q��uDNr�i%���!�����?���Li�%�����]�bO7V����J<��\��|r>�&H����$�;�G�h�e<�ya�}��_&y�j$�s�j��a��~�{����Y�������8�t+�q�f���BC�
��B+�r"M0� ����(��s�4��m~j������'�r���vqg��D��s*-���������:;<���ys�^��~������m� ���*	j3t� *��2��5�`r��Y-��Iuu�*9Y&���<0@���x�aV?f7��<3FWW�Z9���F�����5�n�hk�{�W��s�+��r^�k�9_�P�4p!�K��
������g��b������������z�%2�������L.X'���s��nU���wK�&W�5�����81pA�t!���1��/� `����b�/����
7�xb���(�(�iLM��b�>l����~Nw�E;���t�����G��4������?E�
0��c�s������qq������b1K����^�*���|8#<h"�}�V�'N�9x�R]B4T���_s��zpNp�-N,��3����9�|����#Bw5���'n�=41�}����xw�k�*h���Q;*Y����o����_��Y���r{F	�*��6Rz�Pw�H��t�"m��~��+��]����0�>����gq���'ie7���qTy
�S��r%��)<�P��������IR2��HZ7�x��|/<��q��[������=��-�9��S����}�8��0�~��T�r^��8<�`���<��(��i��$y�"���K���utPs����!*G�������@-G�xp���n�3���V���0�B_��(����*PQa������L�[(�R������AlLr�s����2#�o���F��Fq�����P����4��y��rm����R�k�b���V�yr��s����x�a~K�&�E 2�����?Zy�����"2��(��f��hT�7�fGG����H0(��y���hW�}k?���e���r�_���z��Z�Z�p��O���;E4�SUe���O9G���SSX����^����5%�����������">02�"����F/)�p������]}L��&_��1j�J�0������Be�
0+oG��QFFPGG�3��"��
�tu�X��L�q�G���GIYj�x$}�>��
^>XB�E��_(uF��T��>��39���� ��`h:##*ous����5H{{ez{3459����G=���l�A�x���1
E�k����7?Lw��f.�^���G�~Ke%Z������?d����0��%���[F�P�xL#SS��C�qqMC2@5$LS�8Q�3�D�yq9%;:btw�(��f�bP�g:�L��8�=�&;z�9v�
M3#;�S��v�xp
�aE��(6�<��"UR�� `����w�����,�,��e��h��A�va���6 ���*����M�#�X7G���n���������x��!�����`�"{��L�V����X�����zE��|k'~I{HfbB%a�����Fw�����i�����
���]�}x�4S�1�����'�H��Q��#f���v�J���Q�4Q���f�Q��F�btt����5Lm

�O� y������R3:�����h�X�3��m��E	�:�gb���Z�a{�MWZ�fz�h��Z��}���
-b�**H�������D\y#����z��l������6m:�!��C�
P���GI�=���@���~'����3���/X�p�����c^��q����$���4�0i�}��y1�l���S��*�he��n��U|��w`��Q���|���}<67�v��L�N����Y�e�#/���P�������O��[S��I�����$Ca��$��x�a���6m"���k[��{p�E��}�������o`
Ln�E�p!�����f�����TW��k�|>J7of��gr��1��A](Z��q��!p�)/f��-�x��.v��q�D�tZ�0�Q�{��}���]���H##�6�(��c(�9�!)���A"q
��	o�$��)�G8�"QF������i���'� y��! z<��q"\)���`�*?�aE1�4UQU�pX���������v���3����Z���I:��cC�_�K{��W����q+CXD{�l�C[����O�H����\AGG,�W����k���Q�
�r�lH�L"��gz#��]����(���T�����}tw����{ihb��U*�8����4�ZZ���v�Y��K��6��

�rd�-�>D���DB��Z#H���]��g��������CF<�J['ii��Q���_�^9���	��1@Vqf�(��f|7bkh`��.�����H�2n��7��S�K�X���D1t"����bq��t&}��"���D�%BH�S���-���L_F^����8y���o�Q|�
����3�br��YB�]��x�"��d�������z�o�c��>��uh3b��5�x�a�:OR]m����9y-#=<��e
�?g���n���M���������TTX�x$d��4/o}��??�P�� ��z��D(~���.���Yfz��_Y��$�"���9��3���5�����%2��)l��3�#\�_|���~���v��a$�w���3��'f8�v��m��4>��k)W��E�O*4<o�������a����"2��	5�R����v`�N�LO�t�� GI��~�6�����p���Z��o.g��36V5�7����er������U��)�M~Z+�CdhH!�����OYG��K�x�R���������&�{w�]����V�������zwG�nE}����*}�U��x+������}	�V�=�������<���������;�C�Y����-�Oa�"�����$������#|��=[xW*����#�E����t�}��q��NrG�(��etw��!����/����FK&s��\NE�������&~���w���OI1H>_��A���Zb���*9�|����<��'1�q�?��?I��^jx���i�~�����
�/�u>�P�iX'5�����
����F�z��E>��G�� ���15�fw�N�T���f�����id����!sV�k�!���-��������
����H�&axxe�!���B�_�n���z��1����c�`���^"��OT���(Xy�D|�?�4��!��K8����<	�(���M�&4^�43D�����0q��O�#*��T���
��"6Jo�h��r������g�+�O�paO�(���Q�p�&������x��X���'9`��j���c#��Q���T./�[U���)$����<�K�!"��`h�������wb���D����n��)������y�w�����H��3��--��wrC�h�tw7��b��
a|���1u����S����	���:t3��k";����9�'��>Bb#��EE"i[�n��Zj�A����x���?�����(k��v��r,�4��&�3��/��w5�:utt���s�h�?�g�N2X4������mo�m��X������r�X;��X�"M��xz���5r��5��tK��rD���c��d�������p,h�������1_~�/y�e��q��RZ����h��|���C�dT��nGL'�&���y����~�-n���<@��!��{_��17=Q���3_����h"����?�1���X���0�L���Pc��2v+��[(����o���W�C8I�pT�R�pH_KJ���iJ�sz!��������#�4U���|���
�����	l{�D�����Stn=����E���Z��"$����P��B)}���|�;C��#\�>\��A[[4��v�({n��W����X,�p'�6�9���!��n��[��V���e�V���5g���B��|�������@�qnlR�����$-�ct��6*��h�����l��������j�t�������9��D����I��^N��f����T]m�i��������b�\��3i��[�M��1��r�3��c�_�6�h���G#MX,"����}�~�&��`�E5��N\Z�8!�1f6$�����H�����,[f��t;?�*�����4p��X"f]#+
n����V������7������%������Nn������i�:�%�����qb����E��"z{����a�'�����1��v����21�n�X�>d�D�U�)o0w��A��V�l�	qt�xP��t
w|�o�1���-���)� P�B<�zq7�
�tc�e���b��E�0f�!�����DU�c�d���Y��S���\D������?���W(7F����[S���s��{���c(���+s�7����s$�z�L����� ��!z2��
�~e��[a�
;.��c�U!
�$����"���M�'�Bw7�pM�#��
xP���G���A�SO��O��a�7'J��;N{{���t��Z���4����	6����L�cG��������.�����oYb]0p�������T~���������!N�L�|�� ��F�1I�/C2������V�KM����W���c�m������x�aN>��4Mi��C�1��8���RUSJU�kT�L'�����[�^��&4
z���D��[;��`���%t�
�^�
WR�2����@��Q����y�+R���q�}�)�k(�_���;hn��]k>��\�u�b��6����q���B/m�O_��nu��p���d�+y���������J������N&'5�vhmu��1
{s��m�*�L���Q��RP���sqM	wY6���nrr�TE��$�ZE�q�X��z�/������X��
b�i�T��e�+��c���i��Nt@��VW_����i���!�5 v�@2�35��H�;����E;@��QQ��&HYKH[�Ia��u�b�47����g7�j/�{������]��0�h�����Km�SS��$������-�0���{l����w�o��/M��v�I����x��������.�������Y�X�������`�<�����������i��);V2�C?��� V��}�����XJ~a���a����`��4��Q�IR�
h�4g��l��U��������h*�$�����7�Wz���F��TLfT�@�A�B�����1�����{,����������_a
qn�"#1��!jY�QJ�Q,��7g-;p��$�"Fl���Q�d��P
�f�@�0,�4�����$/��X[>�2)D#����CJ�i�I�Vd�
��B���Q��C������t�/����Pk�8e��(
���?c3�HA@DBE0��J����62XQ��[�{3�'!�#x2��;�D������j����h�("�aq���S�b����	Q�1R�I��0������K)I2���@X������$Ihcc�(3�,:$,+���$��?�&��K�b�	��;o#�2�����v3�cHd���)�\R�2&�����p�h-�0^��]�^���p_�T�5�K3@S@�AP������h{;�)����S�m�����FBG44�@���N�]]dz{��AM�gu��TO���M����:�g�O�������^J�����(�'04
2i��MIw�F�U0)��^�������[h"��.j�����^lc},����;X�12��2i,c��{��n�����L�T���F)��v�!J�a$�4U�dT/�/>�U���_�9G{�u���o]��sp���� V���*�1�j^�S�[���et7� �uj8��HN�I�L���aZ(��5xwx�~�d�6��%���C��k���Wc�@�'�I��{�����m��f�������>������J�kIV~�����m>j8�PPFF0�I"=C�	��b,��+��(����q2���=��*��D��
)�?�kOtR�?A�+h�_C��O30 �j��E�����
��OB�F����%	�wP��ctv&84V��M��i��,�5�N-[<x1�/�d����F
�g[,e#90	�[$���Y��j�\v����>�h�L�u�t��B�j1��z	�^jVx��1�a��1]�x\#V�J�p���u�(��n9�w����
�``��3\z#uw.���U��+��/-�|sM �a��Bx��D�������v�@�����/C�|
i�Ax��KO��U-E�u��(�*X�����Nv��F���Ph-�OH��s�44�r�Y��
^n����#�\\Zj��s���9��/?1N}�U�������Vbx�%�V�]���d�3_��������s+a*�S�:�2��M�ZS�xU�`P>��1^n��#
�S�`��dg�������Fi).����X�`EA�J�S�9���|kkk��J'�����}b��"j��5~�C|�'J	�����D'�	����T&����J$Cf�2*�#�������}��>@����
�"�
��zJS!2��TFR�Cn�XQ�1�a��a��~
�T�t�����
�^F��F�&�T�L����e�IrO��!3l�xp��N=����aA���bC)�hW���~n� ":�Y�RV$���7��X��h�41������'�����L������&��i4�����ro
����>�n�����Ox��Qt$���������Aqf��V#)�����::��[}>������S��O���4�A��8�>���mi���G����i��:��uL�����O=xV������&�jO�|�
����S�^VK�+�85���R	2�������o~{ssn�������aNO�[���X�$=�e,�G�x��#���K�>�mx�	_�o�U��rh�>�6��������1k��g����Z��?������N�Hk*o���JF�E=���#_X�2�:mk�����pJ��7��}c�
���z����;����0E����"%Q��r#)��������_,����J#B����O��{��im}���2Q
����<�4������U�:b��c3���c���s:ik%B�F/9[�� [�!�kW.�v���4��9��x5U���;�p]�����J��O^������,�}F���F�����	����	��������*
s2s�jjl���3�F:����?��n�E��a��v�p����x=;F�:z��H���Z�)�O\�P��;H:���%"�{7���/h�	2�Y@JJ$<����fX�g���1�cDuP1����)��w���� paDv��:z�"t����Il�8E�Q,����r8p�r������VW3�};nK�j#]���I�%�4�O���v�W{I�u�q
E1�$���wo���MMv�^�,,�m��D��q�����q$���YG1$�_��X����t���G���j�*�w�V��J�#E��TQE�T�����K��
�[d�6�8�����HLM�����m4���	o�����un�:��O:	EG9>�c�H?��o�a���}i*o[���DvS�������8�Ex�E&O��w-L7*�*"%L�"N'7q�#c�Vu�bum���1Ub��
DTD@0,��)�� C2��h�
nx)"0�{�1��>��1�v	%��1
	T����P�<�����PF�n�R����Q��j���Hh�Zw�<^�9`��=&��2X�L�_I�#��|���x�n�L�@�F
}��W�
���(eI�`��
�"�R?�#��h`Q�qi	����F�`
=7n��:@2I:D�P�"�����"�F�n�J�2��@e�$��A��$Y�p�&��i�#5d����x��1���f�h��$���i�N�����%9��C#N��2/�BU�T����Q�n���U���V-�18�EMa5�>���3#��$��1,���]J#	��0:�M�),dX?r������A�}�8��V�8"�K���hi,zi�7]$�3C�/��!K���n�����hG�bk\F�`$V�'g��/����%\
�b*0	��s���Hqc:�=���d&]x�Id0�U�����)�J�"
����~�g��8���� ��@�6��c��5��0n�Q$[��^��C�7��5�n��O�����%�D��Y�`rk;kK�$�x�ree.�{;9����K?���;(�z��q���������3�P�d4����|]�$y
Ufz��-/�N���a�^I�Q���>B�����-N��t�Q9M����]l�I�������
cGh������ss��5�
�{��p�j��\��O������u&����f���7:�����(6�����v�
D��&V����6n��ix<�<�k9b�\���
P��q�>�}�J��sZ�����E�B!���Trg�������?c`@��A�����E��8\��|��,�R�����~;�&����\�u/��l�]�!�$t~*�xL���/�
$gk�d��m���:I�"<\A�����{sE�/%�/�r6������w�K��������b�H�tZC�!6���v�z:��9�m������B2��r��:��iY#�:�m��\w;���SnZ�B���q�s�-��������������qB�M�kp{K���b4
�8H�jJ����K)g��M���|w*�&9(	%�f����;�������`6I L��!����D�*_���?��G)��w8���/34$#I"�����KS[�9>�U�b�uJ�	n�(Q�y���I$4@`��$��i��7oNw���8�D+�t��I��.���� �����p��e�Rx����n�����1D�m�r'Zw��1s���i��#��OP��<�o�������u��|�K���Q����E���b�*��h�;4"�bN�p����d�+<D#}�2Nb ����7������`�MD#��Q����,=�(�a��u��ur+Y%wc�G�� :�c�H?=�,
���������@�1B%�8H�$��4"%D����OcA�@��C7.x&�(�	�jch�g\g==X0��R"|8����2Rr�Lb
]��_�G1K��G�T�/?�K�Y���S�#9f�6���A�����7'�`����iS��+D���H���J2���#�2�?����5�v�'��8m��?�Oh��T1�*Z��������H���UC����MXB�x��"��4=_:@C^Z������$��
V
)��b���\�.�U�Fa��0wp��::��|����n�������L'�"��������&��-N��>\r�3��D�:TW�S�G������q���o�[�W_
�Y���j�N�/�'��D%MFr�)%aq9H&u��~����O�)�F�3H���!N����S����]���t�9�1��lA�R������Bk�&[/�b�,/�w��/������0�J�:PUb����w�:�������}8]"������oV�����cDUM�]H�8l

�95y������s�����e�R��������mEp�8�b�4q~�
s"�����5���n�j
wGk+����q���L�"��e?G��\jc�Ob�fs��g�R��8j�T��[�b����w}�����vS>S��]/"���zqT\6��#��?�8������f�"��%��$�����!29����PX��<pY/W&�N���qg���
�S�W`�y��M��]'�x<��]K4�PU�D�XG��~s���*�8��TVZ�����o`��b���K�?v"���kHh��B)��V0�}�������e'���n���)�:�]OQD���t�����T��w�6	����:��9"���Q�FI%�g�Q���i����C"a `�x<�����N��u�a�z��'���$���8d]M����a!�;)I�8jL���8DC�-gd��i���6�����^�!a��_�������^e`�o��������H�LO���L�������������'�:�i��C��r	�$����"����UX��1������u�1�	nj�1vM���41���6&(��A����FM��@"����Q��"  �I����NCE�L�Q��dJ��Gf��� ��l��+��D#Q;��������.T����@�>C�K���"�k�8g�e�� �s��[� �X������O�K�E�4$d,8H�g���&=�|M�C~_����hH������8�o�q.�i�����O ����G�eJ���2 7�P��&C�:�������>B��Q����m���t
U����24��ql3-)g+��y���u�&��.�Q"(I,��H3O���t�*!2�
�u�*3�����nn����q�������
<=$��S�%���Q�k.t�$�g�\�Xct���/�av!
��3#�p����Z]�(�{��_�E�!�]L�Ag�Hy+.=NL���8�C�����Rzd������f�kA�I�*�h�����q���s$H�J5C���S�8	E{������g�H'������#����D��t�S�����sXK_����D���c?o�D>��x6��:�
QD���q����j��p�6���WCX�sbj5�b7q��=H�d7.co<���W�zq;����)�n�L���*����H�^g*natL�g�Gh������H�_���{����i����g�p��f�{;�>������x��O�b]��tZ�>���4�}#�:9�X�]��v��FT����9%5�m���G���"��Oj�����}�w�T�l<�s��Et��g���a�}�&OR���e��i�)�z��u{��;�!���������Y�	��F�#�ih�1H�<3F��q��op/��}�������06���U4�A^�S\��81t�C���D���X���
����Y�w�6@�z%>����z���s���o��nN=�m*���>�G���Y�|�q�"��=�=
�459X��\��|2m�����4��KS,_n��[]��fxy�[v�q:E��Ey��������6����2���2�z����n��o{8�#����L�� s�O:r�;;_%n��@&�a�zO�����Yt3�}�m�nh�^�]�b�b��Q��mD�7���=m�E�o������h����M�t��blyQ4s~��*n���X��r��`,�]����3�Pg��h	��_Coo�u�n�����"�>����c���0�H��������g#pd�S<<�unT�N�R�����'�o�a`d
c�T�Do(���u����M��x<���BE5����M�q'��l�b�U�sn3U��pC�U������IdD��d�n��?���z�is}0��^�bj��_��O"���4�G��d�����8NL�'Q���1�;���u�������c.2�[Gi����!��o�i,����M�iSqn>mn��._F���2m�2��R=�r�Uo|�t:	l8Ia !���8#J%��F�G�F�F���2�p:UC��A�	��o��"M��b�0��"I���g���D�A�`
��2=#u�`'�}t0Jv��P��L�%�?70����2'�*��u��!��v�)�1@S�u��6�
�'x7q�c�J&(%��A�X��H��A���&�P�"��XW%E�r��q)b��X�K)o(B{��TD<����$I7Q���c�x���A�����5���������DH�\(H3����2�b�d{�/#�a��.6���YD]��n�����W1$�V6-����R����O``���V�s�����i�i���bj�v<<@Mg7��3���}����X&�H�1^�����gb�����lcG��U�	J�Xl6\����g��T�K(��MOb��`F�3��$���R�����n$5F�S���XS������\�c�&�����)���5��#���Z+2�1A	@<��X���R��a�Wh�����073����m�*���/��mO��n-%�:HN��m{�r&�	vpE��M�8-�1�hV�����~���tM�����@�a��e(X��A��h����{�D�TNOak�$�������(b�X�N�S4�(W��0tKi���;�����Y|&�t��YEiK7o����s���D��s3����G�S��w�����z�����_T�FPFGI��C#\T��%`�6��-����n�p�Ee<���v|>�,���������'�X����y�<��;�S�j<�Xu�,]�l���@��8z�~��k1��u|�����Z^������@3���S�zJ�y����/<������1�q�������A�ud�\�a���0������+0�4qw�q����"�#"7�\Np@C���(r����$����j���b1l��������O��&�;bu��0L-��)�;^buS�Q7����i���C�32�P��zQ��V�}/G�5����h��3���8�7�@t����f�
�9B
�(*�B�����a�5��|��
�
���jtTE�`��n��jb���9/c��=�PU2�	\�A�zT$	�U��3�KE�m�$w�TZ(
������O�ZQX�@�S�ql���q5��L�4�v����_�������n������#j�If�+z2J
Ar;:�V�8�q�3N�0ECLR�sa��
"�,��>l��I�b��C�3s7
D��q����g?7����4����}��,�+6,X�H��M
+6T$$4l,��r};	�a`� C�L`CF��Hf�~.�#��a�jP����<�6�������Q�8���A��:LbZ��������z��kg��������H$]�9� �)��
�J��_9��H�H��s7�|/��bV�O�1��;������1�aF<�}�f������v[P��QJ2�����Wr��C��q'iEQ��b'��n����N�g�!�S��QQf�
�f�4b�+9f~!
��d,�8f�;�|��^���a~�����s��+�7
VVp��g����j�*�������L�c��I��e�n���\_63A��y(�.]G��H����_�`�������W�R?���g����e$���E�& ����)2�I!N����������y���0��o�~��TfH�G�������Z�8x7?8���x�Shc��"�Q�O
`j�,8s��~5����%L��B�������HbA����j�����c'I.���f���"	�i�r�i���>�V�pD#���$q
CU��.2�1N|���L�1K��7������p�`�������/���>�Q}� �� =�@�e3�%8H�A��OfLu�I����O��3��wQ1��S��,��i�|���������N�v�`����X�������!C?��~D�C���R���D{�q�'b��w�S�n\.=p���3�G&��D�2�bu��v��x��D��v�Qy8�Pt��}�+�A
q�=�A���NL��������Yi���"s���e��N����|5�?�k�:;9�� u��y�vA&,�y�[�#'��+<�.b_f%�Z�N�I�3���jLSn��=��I�Q::�(Y�C��'��/���H�O>Iss%��Cj�j��ob��8F�	Jz�P��I����v��y��Jz{3���&<|�=�x�u�T���qF����=�rw�)�����H!����=�J�blyIH�u�n��b�����J<�a�<�H�%����"��i
7���J�S��WR]me����jF!�Y�������:�H�mo�(�`�Z'�����i,#A,v��^M�1FC�
y�F3�Vd=�6�CD02L�$��u��%���t���V��)N0��w5�w��t)�X!'��I��+���(�]70�^I��]l����'�����f��i������jd���$�����P	.ob��?d���^�������p��8�q�#�N�4���O�'�u���mg9\���L�Z8Y~?�D,lj��8���`0I[�}4!I`����97|��
���%}r7%%���p��q��+���PL71<AD�%$1_�n,Z�x���S67�q6���6���|/��>�������5C@Q�X���G��X���� ��BDCG��5hf�R*���A$�V� ?���Y���F�����T&�~�u���X���H�@��u8H�"��4n�36E�F�
J�6������m^_�.d���oM�����c�r�$X�.`%'Qbv,�i,d��]���T�x�P�"�����k����j��Z1�A�U�����gi���@����2�����7�����?c��x� #�� ��_A�.V����7oif4F�6�����JF�S�eV{��'�1���o��x7�U�0F�45�Q���O����fH��i����3{��H�X2��x�x5�A;���Q*���^�{��in��#���In��ftZeJ,�NS��e7�6�<�w	���
Z8��T2����8�#������oq���G �w�������Bk�ctua������p�>�x_LD�5�L�ds�#�z�U��8�4&���}� D�H��1t��/��/`����N������@QP�a�
��|��f����S�������4���Kb�~��x��U8����I��6��������F��k�N#��/Q\��=��n�3#��FW
��:����N|�6q��0���#W,�%�X(��\N��l�l�S�?5#�FF�3�����w�o;���}���~,�q(-C;z��������b���(�����*�g�[SQ�����e
�q�[�K�{���.7�+,����B8�2��W(������}����(��'�56^���I�����~���C���"-��y#��K�|��X��\����iw]����p��JooQX��TI�bn���ca��oG��.+--V��}�����A�zz�,���#GP,�{z�zzH���b��q	'��NQ�J $e��QN��xQ-��\�J�L��I^��X��@04�J���$�}���]��Y���?��g����$o��x�s7oRe���A,����8vz1Pu�p��n��{�P8������8���G<����!!x8)�@�&���5:�mt���0��$��$$z,����e?u��9���gy��7�O���F�?�p�����G�h`B�fuc�Y�t���dJ���m�$�����n �S���N��a���+8�|�_'�}3�`����5�$n� 7kG�;�����Vg� �����a�����R~K5h�$�Q�'�����Q� i�8HP�G��h)���f�l	�)�@��A���D�����+���P����R�$��&1���bj4sHDSo��@�!�M��3�90�*39��Z�����	3�%S$p�l���R� �YmX�T�� J�C���c5�4�+*�s������_
26�$P�m�|d�IR+D���!i��RgT�g����8�9��4RX�����({���`p��=s�����|"P�4k�.l9W����f/�=������xns6�������c��92�������g��B�����|��������d���j1S�H��6�P�}���t�6{��!�����a���i����\d�=�����'�x�a,�V���A��YN+�LaCa�j���J<��>  �)��Q\$Q��8������I�m���0Sp�!ct�B3���%b-�j{���]�F���OQ����]
��Y(������X�j�#"JW�����Q$�|�VTn�k9J7Q|�2��7�S�@�'�IJ�	�w���?Z��0��{�2��1�=�W8���EzyD�7,���D��Ll�b�M�����c����-�B:��"�^>��2��.n0���_�T�/8^r���a����#� ��)\������
�,���(��
LPN)X�q�{0���G�`���%r�������W�z�i���8h�����8��c*{S���I��:���������?��o|���X�z�5���k!��_��"X2)������:k(��G�3�$O�b!�YI4�q��n�����n����;ii�����/�9p��F�DH���a���GF���d��������)��?�����0����OO"����fjJ�E
�9�x2FI$��r����+���o������;���Mc�	���kW/V�����l����� ���{�������6==���*�v��V��2�D2D"�m% �:/�<���S�>�,�]�Pb1����l��g���)
)TU�=�����d�YYJ_����y���H�A�p#7����+V�Eza���b�Mr���*�-���4Az���@����'b�40qi���#a��i�w����>e!��h|��i�a���rZ���S|�/��uP�r%��(������<	�J��E��#Y���<�A�v��J�������$	@��b3��D��.�������)~���C���I���Jn���I�4<�	b�2��#���h���V��n�u������5%>�1Y�+X����	DQ���kh����JF������ ��}Eq�'����Sa�:+�����UEO�����4�o�tw��^H�n�"
"*{��V����4�6+�.r��+I�E��zYn�b��'?	[���#���J7�T��?�p�;�#<�+x�85���^��T2�1c��H�H����H�(����L�&\$Y�l���s^1g��������ix����0hiB����.��4M��
���<����6�|�k�����O�>����Q�g�&:����W!g�.d��g��N��
��3��.	
���d.\�����8�;�j@�T4:�R�0f"c���4��qf��L�������)�q�`�����1T~FF������Pf,��	�4>c�`,���������d�(�+�������
fla���b��!�i�'�MM�  *v�#�������e���C���WjyqVh�I	0�YQ��tVp�j��(���J����Q�����!������Pb	tM��e�&�uTP�����n������e�z{D��M�F>�����a��f�2�~�>�iL��&������������I���d��kNvUU�K�}��ko [�H���D	OuIQ$��[���D�r�q8��������GDho��>��" =�$�N���MM��s�U���=��W�S�Un��0N��^�dJ9��_��{�3�� `���}��q
�Y�XK�t��|�E��j��FR��Oh���Nc}�!���ioX�p�
���}L��_���-9"�LLN�����CC
��2B����^�q� �L-2	+��;[v.d����y>�kr��Q�d����!9�~��%��$������7����	�_�����k�]
^]���T(-x�a���b�����W��b�B����alZ
�e�/��ql�LZYE��@��o}����r<���C~�b6X��.����?�H$t�n1gs���mw'v%�l(��?�������:��I��z(��H�����m�\P���_'��o"��^/��|e�^�w����2�N��a0l5w��q��)n�Xzz�s�����m������\�����SO=�SO=��]�����$6l�P]-����vhd2:/��`�@G�:3Z��	���g>3�Mf�X_Ob_?>)���}�w5�'��J��i
�RM,#��������^e��B�R��3�T��b���v�na�L���T��'(c6	�M�����]���5�u��_���?��~�Q9���Y=��i���n���G���"��2\II�10H���+6%�E�����'t��QnP=���4I\�CL��|���������8VcU�����r�4.����f���S��A�pX#4����`"��u#���xH�c*��CE"B	I<3������f07���&��}���Q���#������YD�
N3I	���g5���B��2N_�1���#�.�$Pu;��~A��$x�G�S��}��kDf�{/w�"��G��u����~f��Q��M�����:`�S��)`�qT�P����E/�cw�&��$����LJ��������N3���=VB�������L���I��7&���N��&�������Y�������3���,��s������;��s���\Xg�sf��R�
V�������i�t=�,Q��.}>'���B�!p&-QvC�P�B�w�u>X�Y�}d����?��>���|V�������Y?�4@�d�d;2�T��P���L���gnn���kn;�f�o�Mf��2	�8�l�ss�0Ced���1��25�+<�F����!���$�D��#�����m&"&�LE�}%�i�e&�Xvd�X�"c�G�R�17�"�&�:BTC8����2�l���2E	����_����Q��BT�"`��Q-X��c���nJ	�d
*tS&���W&�K\�bV4t����4Sw#����C����3�i}�H(�������m�1rB�}�f�Q�i��� ��D�d-55"���O�������)�Xfz*�bj�,��i��
uA�W�������Z�z�I7�1�1l�8�3��F��B;zi0��)�A�9�!]I<Q�S�7�����k���w�3��k��F��i�,qs�l��"�N�}<���&��U��n+n�H(�������_��5���O=2m�9�[>)����n7�%lb����.�Nu���m���R�b���
���|���sn���F@����~F�7�"I�V�w41�����Cvm=����b��S�)w$�L��Y�Xfd|j���H����hI�@h����OpS� CB7"��ud;��uM����z��X����6����8kn�Hux8����D���pL���Euxq�),�0��P�xM%��b�"� i��l���ft�	0y�P���Y���=Y��<�K�a�v�����������h���_�2q���b��gWz��P��X���PSsf��M�(|�3��h+������$�()D��D	�hn�x��	���$B�s�'4~�w��k�b{Y�	Q*�0H-u"#�B�v�#���
���@��W����Z�M`��>�)n��
��=6�0���@�U����(e��f����q�BSq�&��.D�����#�uD<�)e
2��!2�i���ART4$T,��H���&+��j� �Ta,���0D���]��J��6�S��,[�\�����H�9=�3��0qn��=o�����o'����V��e�����N�L���y���$�g%�'=�3�A�)k������Q*���Y\�s���?6tn�P����a PA�O��������Ny�$��$q�Jvfn$l?A���PR�0�u4�XQ��@�:c��I�����&G3�����#F2i��ofH&��� M����H0(.�N�L��hd�xf�m�Kx���M#�T0��D���)	U��d�	��i���h�N��E�U�����c�t�Z�9�\	���)c4�!9���L�u�]TDEEA��G��&�������*��� ]~%�n#�e��S��i��G�h;v!:j?So`R��:2����"H�:��:��4�"w�e���V�����HB����R��W���D����[�5��%FF^~9���ijlD��P��3�SG���D�uX�uaMM#�i��>��N\_�����������(
���	s}��73MX�b���U��\t��k���@�e
7u,ga��|�fv}���#{O��?|����E��~���-f�7�S`j�`���&�1,���� ))������nsd$h��i�`�u�{}�u����$Y���}_������P:;��[�����w,f00�����Y���������r|'��GO�85s��{J!exa7U#��zq��l�\f�	�4��N��p�B!���Rhi����)S3X4����F��2<#�)�U�{�q������v_P�j==���M�P��F��G��u����D����y3��~Bzl��q$V+7������ M4�f�>�?G?~<�n��G��"�J�����������>�(�>�h��+V��O.���~��������M�8$��U����7��piEax�N�F��������Q�*��_��������`�&N
C�3��k��STjg�o�7��k^t�C~��C9?{��-Et�+�S��2���������b��P�# #ce@h��|�_�:�3�.*���������_�5u���m�)"f�������VD���&ax�P�T �3&Hgl�����Y�tF�#
8qR��U� �Z��o��>�{�OQ3�]�S%j���1��e�_8l�������$��6�Z����������#���J�T:TJ�D���P�����L��� �R���p@��)��#4~h��|0���f7I&)c�Z����K�I���@M�oy/�&R[�fxh5���0D!�k�f ��������2En�/�~n�&���b&�#���,�HC���s	K��������g��s&���$��E^{X�n��^v�MeN�|���R����0X�4g����SO����h�
��U-�A�F�j|D��f��XtE��Q�-s��|��\#�B����bxMn�l>C�W1Kd��k.�Z:W��l|����{n�:��&�+)���R��C�t������)��piS�c�\j�s�e.���e��Qr}�!b��Y���*��c��q��6,d�3A������E=S�c�{����H�TR�$eLbCf��0Lw��������n��>;�����HV(f�W�bE5D-;f#
4J�r��ltq������!\R�0�b�sS+�C����3�k�F��0h���\�� J��^2���Q��A1Q28H�^�IP�\�cx�������e����:��G?�!JJ,$�:���xe%�k���)�k���
u�]�����2)ti��b�67�D2iFb3����
���X].*++Y�~9;w��b�{k��~��X���Fi��82]�KE�]uc��/�q/M|��~��5�Q(q���f�#���ySB�8H[<x�I��".�����^C0��9���Q��^���h����`�������V�?�B�����EWU���'�o��#�"������j��DM1�W'�5��e"��x����^�qdJ��F1V7�r9S��XU���<�P��gr�gs�g17d����K���8����'��z��m���ad��Ksm�5k���������O�L���Ut�$���)B��|�Ec��eZZH76�V���m@��vSR^/�__��@-[VS�9��&����Be���%P�����s_T�Q�?M"���&�3�����e��+Z+��w�r��"������e����d��s�PEI�s����]���%z3��J����*R:�&X���X}^,������8�t�}���i)��~~K}�o���x����?o��Gg�� `���f����������N�������qr�e���,�WuuW�]�[u�����`��(�i\QigF�*8��q��������87��+�x���3.`�� IHB��V�������������TU�;�
Aqn>�K:���:�{����y>��!3:�K�#�@1���q������
�=�c���|s%�.�K����6/�u��d����(�n������P{�JM�����@]W�x$�Q���I���]Ke|�f&��SK�V��@�(Cn-��9N!F2��n�q`�t�L���u������Y��w���w4Q��(j�Il�q`�V^F����s@��#��6=��
f�l�j'�5���b�[H��x���0Iyo���$�ur���a����81+)@G����_�t=��m���A��r}���W�\�=Q<,�&���/��U�Y��?��L�$sE�9c�8_,2��v'�,'�12��!��tQB�Z2��r�9sO��!�1���d>}�ZT$�y�w���y��3���4s�3�J	8���N�!VpW�z�1L��Y4M�����7���FT�X3�/�1ei�P�(^����4��)*2dQ1�RN���T�Z,�5M6���3^���ar��>��x</l�����y
�]O����`�L6:$^	#���E+V�FJ�24�aV��O�Ax�-�"�j�B�� H�N�6�L�f��.�y�l����Av8�f�h�������Sq�7|��o�:~�Hfh��fH�)^4���ib[:�!Z�,���O���C_����vse�f
1���b����U�9�%�#F�H��������i��72li��r��#�]���B�u�d���s�*�����K1'��J~�g���S��G�u���On
���s<���F��9��~���7��&N#�l���
a�[���udRM8_��8�=B*���k�����]������#�T�Ns:~����Y��z�u��X��S���v��#����

1�nC���r	LN�$�����K:����f�H��A����?}V���!���h>&����������f
�I�������1����al�C������?@Q���-�h ��(��){��d�#�b�t��
���6hI+�!���>������H�����x/�p/�����[WN<���K�U$����������W����?��$
V���_Gi<�-n8!��������U�o�7�<$����j�����X�P���cL���M&�	��NEM
Q]G��@62���9���ta��"�:

�����d��"(���s�Y�z�{t�X]���I&uT�����E�4���������{���Z�9ha�D�XLa` k6y(����$-������J��at���.Or
�P�,�����bdp������9����Z����c	���!�-��g3#�Zn�}�j�Ig��S$q0J=��}��-��Q��x�d?���=���/T�ERN����b�l�#�
6)�.Jf���A*��;E:����Z�:�,�~u=W�I&-
�6��h�����&��t�v�k���(6K��?���*�`z��B��e6����Df*���(K���B�7�\&��@�'��)�����1�`��d���*�R�0���Sr-�Xq��0n���J)��l�E�����S,b5�`74��$����c�m~�+7�9�97��B��V���������~���$g����42��w1L�d"z�"�����'��8p��@�A��������H�R�"�qd�����"LR�WLPkL�a�F���	S
" ���MH":��h����
�d�c���D��U��i1���}~��
��QN5�����,�)U�,t�R��1�3���Qd0�L�0I5{Y�����`���"1���&i!���!�(�
r����$�p)�s�����@yA����!�o+R��>w#����F��+
�K7z�g_���j����h*tDe|��Ydq�^��-�e��4�Y��Ig�6FE�tq#9#j�k�����n
����QV��������d)$�4@����Z�@�����"�HSo�AG@��pI*R]��E����oQ����lBY�a�d
���h��27������=,\SA-`�Vt]����IN!�E�"��( ��H���r!�491�==������PG%SV;��2BF���$��w�8�=�@��Pq�[G�m
{���g���]�}5�!����������
��{��I�����b������]�����=Df,L8����_����]M�@�E�[b������/b����L���3F'�q�����j���~+��X�:�m�?!���|��]�Bvba+���K�T��.���j��.������?c��~���d��1����9'
�*�����x:;�.��m����������W[���:����j908X�}��PV&2���\�����FWU2��i�bN4��;�x�b
WG����Cxf

�^�j��3�*�����m8g�n��w��b;v���X���� ��c�`�������O1y��N�\�>�+��f���4��y�i� }pp�[�{�f&�d���hB�n��N0�����1��������b���D��K���"�S����H�sGc��@���e�|2F,f�8�.~6�r����������b��������9z��cLO�����t�������o�������*}=��,�����RTW�(x�O��1J��rN�B,-��3�S�NR�pR?�w���`��K�-�|m����E���(P�O��as�U�Y��_�Z���a&�A��y�r����[�j�����w�L���W�i�FYY1V���:��i�hT{�5���<������+�����a�*��� <��Kr�^��0���e�������-�^q��8�d2��Wn����`��oIp��DD�CR�9)�����`�U��C;6�d�!�,��4b:����a'-��f��Fz&�w|�L5_-Y.���Ts�}������8��4e��������:,���e4S�8I�&���e�|O$�F�Q������!��L�Q��%�Oo�>��j�8I���$QF�G�>2�������8t(��x%�T`���1���	6JQ*<*�����X���[H"9
���HVtb�S��~V�S
	s�aA�����u��]YiSfaZA���s<	:.R�j�����JNv��x��?O��8��d��}�]��+�Jq2���"o!��}5�)����r���g|������%#�%7���D��4{g�Y�X���\�<��\�-�2�)?�_����l��b�L��D���f��|��BZ��R=�����JZ�S+8�1�"��p�Fv�o�i�z���G���]BI�[8�!H���B��A��,��^`(��N�M71����!���@��;����s\C��Z�k�����@��JRp3V����������q�W��'��u��o*�I��IT�@�����8�I���W����h�fo�`�����i�z���`l�l_������P?��X<����g�i�
GL��� �y��8�3Ch��������W���A,��o��^�R;v���^8�=������J��G��C�-�c�����?aL��+�_���]��5
��K��']]^�A��Eq�%��q�����������!��#�"�{��:�H���}�>�<��&��/�1�m-���=���Evt����$ffT��,T��h6t�V��d�����{���z����/~q�S�-��������	������U7����=���+{	8�Y��L�������clXG}>~��wOO�;b�u�����P�x\���L��5.��ew���_E�@]N���c'�Q
2CO����f���������[���gp������-D�z�����=�m� �;���c���D�*�0^[]��f�D���a��p�^��O����v�S��>�h����e�s<hVH\����8W��^3����n�����x�{�3���B(���M!�N�E���sl�:vI�
(
�C�i��	�sdG�����I�N{��TN�:�,e�,�����+o�rV���-d�-���S��C�lO��6Z[����a���1��+Su\�O*�f��*���dz�F���t�C����<t�%�)Z��0N�du;R^�\ �f
7?s�1oK��F�����t!L�!`��M�>�5<�r��9�0����DF�-���i�s�x��QXR|n���X�y��vIeR���G��2��"q�F���x��S��H��b�L7p�[D��i����M\5�F>?>�������B^c��`f���C��28�<$�:��9�j,I�ru
�!Y�������$���>;�����`c�X�~uk�WX!�"�������G���|4M�'?����s,�@�����5�����GhG�t	�N�Fp�Ad�K
N5�bX�b'�	������,I<�Y��Q�v89���JY��\Bf��T�����FTq�%��9C�WZ��L�%�0�����1���l��Rh*Y��6R8����d�F6V30�%
��lw`d5U�(���T���ei##�hh���Y����-`>�_�
��\"�LRCF%J9y��h�`�_"P�.lo���F��"��c 2N-�}�}��@��]7�
z�����8��*�0	s��K���V��
���0��d���)*���x�t�l;�
��e4e�#������y9�g"*2�� a���E�
�|9p7#4�c
7�����5*|��5�����l���4W0@�!iY��*��)�W&��X1���Huw��E�ri���bP_�{��j��MT�2iDCE��M��#����Q��������3x���()\���P��4!�]�b���s�V�1j�E\s�
Y����g���:9�kv��A��E]UQE;������~�*���#���S��^f�L
��f�Y���m)�&�������Hc���Tj��"��IDAT�}"n�'�7p�x/���XV=CK�EZb�J�l5G������(n���v�����kk���kS�e��|
�N���J
+9���P�to/�~{�}�I��8US���t���l`���8K��((����A*/���[���6������9"��:��7������)�S����/��QU�w��D
���F�/�����y��n�	��$�_��I��c�#c�Q��	��y�Xtw�4�U
D6xi����C[0HU����v�i��l��U�`c��� W�B����<�wx?��u���69�73�
[�������M�c��29���qQg��������F+�W��
��x�y+��9����AF#
������}N�������
SS*������s3�E�z�����Y$o,=���3���gQ
t��oN�|_���Z���Fsg=����j��|�
�
"�����?/t����Iy��>��~=�jb��Y�{�����^�22mm6J�p��?~�K\;�M��f[�c���� �+
l4�<=L�/�����]js��3-/�q�e�Q����G��q	<�O��������?��Q�U|��#J���`q_0�s?�,�<����=W���~���X�4m�DB��n�1O�{���
�'�
w�����AUh70�]�w��9��att��������{�Gu�t��������66�|��H�*�&�hc�!�F@D�������4� �������Tim5���M��kk�64�+���Q�����G�����s�������rQ��CY���+i~���E6����,S�IF�~j����F��@�=nT��F�=�	M��9|)�@��M�oA��0���{��g��O�&�5�8AJ��[1�N�������RI-��6[��y������S[,fUY�$���4�*�(2h	��m�S�0aF8���������$ ��I&
���^v�$��|L�^����"�@>:�$���������[�dT����$�m�#HJ��6 �QP2����F-����)\�W,t]���*��:{.�U�P��Tr����D����Q� 8��*b���\Q<PP� �R�����������9����D�>����c��v�3�+�+����TA�+���+Z��~nJ=LE��%%���f�-?E���Z�88��m��Sa�Sz]Q��,���LY��P�SK��x�h93�L�`<c���Jo�~IPQ�����@G4�M�4���K�%Ja���B��Br���FD�,����#|�������I��T��a�K��6
��jd/s-O�{&$AQ�P
]@�O1+WQ�N�gC�Cz���E�����e��U��I��H���gS��YFi`j�����,� ��m���d8����(��_���X��6�d?�����A�%�e��a����i�q}��z{3l�%�p�DraZ��	�ph:�����%�Q�nQ%?L�D��O��{*�z?������u�(Nz/��BU�u��@t�}��y
�q
��EIaMi�|��g����-�bt�oj���A2��\[���u�L����
�W��T��%9�
p}���������L��m7�(	�=��ab/U8
?~�X�|�jW��lf����2��>*{��P��h�)�f�g���28���G�,[��p���M���q[0�FZX��4�������X�g��^&t72V$��o�W`��K��
����Fv��c	��Z	mg�����cU�����3;@�u�w�~�,�`��,�_��~��sx<.�n�DB#���8�(� �3&Wi��}��O3i��P�$+W:�t�;x:\��g���ed-�D2������Z�Qn{���p-p!��kF�?������Q�KD�����@^�*��"���_U�s��P�����<�b���$ku1m��H�P$)�g��=���e�
8�Fl���4m�]��e�����13'�����X��~pzZ����R�i��o�.�����o��E���2J<�������E48��~7|��8������(��r�e�*� B*A�8�@��]*+e����SQ�A{���D8��z��H�����!��CV���@�2&
T������B6��
K����&sC�k�N�}��_�Zd���u�S�(�,��SqY���V�O����b��*�b6��V�RWY�sz���2��kkQ���f�$�0#Vs��U�J	[k+z<�29��p �����z����j��_G�g��~�e�
��=�-<���n���#������"��f&��T6403���j�����E�(����+H��4f���t;)$rdE7:0K%'�F��Ky3�h����'b ��OkG���`km��/����'�����b��o��������I�D��h�;��y��q=�(�`���J�m�L]�f#��Jc�I[3��)K�P'&��&�(���L+6�$q��(U���-*�&�m��$��aj��VS6r]=��St�=��X�t��QD@����F���0E5 a']T$��m_���f��z2��ih���T�.D��T
�	<y��s��<�oY�uzc��D1�a�/��
������FBc�J�n�����A@If0�94����v����N�����cWFyS�y��QGd�}/>���t3�{3�Q���c����aA����#���`#%���UTMB�X�x�X,"��D#���c3T�$��g�O�U���#ZT����`%�������%�
���C�
�+m��G��'=0L�������`P�H�
8]5J��������nH�Iv�>��J�[������yh���k����b���*�GN�������C5�9�
U@��o�)�I������E�}�w1>�E�#Z��N'�U�(�!�	p����B7V�@��EL{��y�$z����l6Ut�u�TB~�<3� ���������=�U���Yr���?���ZX�������f����J������? �Y�lGC�P���2��g*��&�{7`����=������Tt�	-��x���mh�8V�?���\woqM�
�>x����5k����\�������rGOg'p6a7ga�d���E"��vKl�^J=w�������^�k]��@�u,��lU�J�K�C!B��=r�P~[�9v�C��^�D�{-�e����ch[�Xl)�������amq1�l0c��T�TU������������s�c�m�%��d���<���X�'�W�B�,���
�I�_U���w��#sZ�Fr���}����������R���01��v���+���S$�m���H�j�r<��K��<W<���c������~��0rc+����/���J���D�m+������x��$;v�h����a��E�1��j��h�<�wz�2��\��1V��f �w=���0�;����������V����<~�KH��rb�A�2��+9,�F��g(�Z��h6	43�$Q����0�B�/_^.28���7C�~����n�p�����mI{�9�����#��%h:cB=�����~L�����,6���U�b���}\�����R9���"�+�S{���������Q��OqLm9��LLh|�s����������S�|�a�TE(��tM��JJ#���c�����RB���������`�S��w������T������Y1�I����M;GX�j���+/B00����X������5��iZ���&����� ��IX�q�R��G@e�
A���^�Fj��7���p?���5�s+����Y*�sa~�x0��,V������DQW�+����Ja�V�v%=O�rn!��F�p��p^Il�(n���B����1��Z�	��`�}�T�$>�1p(Q�<�,"��BF�bU��g%�=_,"��"HT�������
UL�-�Vs��xnAU6��VM0���}M�sv�h��d��bc�F~����4M=_+��
d�^��B�<�6��>l�����a&0�b

1ogk����jM�0D]�s\��L93��$�����g�~
�d��+,�]:�����Q����$�S`	�t+j�Q�����x�jG��N=�b�s��������,2I�p��#�1��������rn��#r����9�!��(�sob��	~��8��)�<S�7����F���������2q�-9���,�zkc#{7\��=��&��.~��lq��(4��V,hT�QB�cfu��X�������8>�d��4�"�p����h]�--/���o�I>����������\�s=&�~�]CD"
��
W�yw�[����M��L
�X�0R��wo��.Y����x�!��F��V���dl(:��������E1���&�3�;�x���H��(���(#_�"����;��7��]�H����]�G�m�|��MAc������$��[��������k�4�=q_��bj��S^��('}�(��=�PG�����b��.�\���m=�k��\�����3|`g��]�E�ysg{�/|�kM���9x0�?�g���F���J��������ul�
ma��&
�u�P���w��u��.�H&����'�
�a �l4����kc-|Z[��5������3��Y��}W�m[��|c�
��p�����sL{�xj�gh�x�k�^A|�i�BV^xn�A����W�2� �(�w���o�����{��)EaF"
������LAhA�>>�2��01f.�x��=��.��Nf��B`O��z�(����,��Gh�*2��Q���l��pF�V�9�����������8���H���iO0"�Y_7�T��"~�_�f���e��v�lI�������D�������	K��v��;jia-CCm$���33@I`b�S&���V^����E�q�@������-����J��V,O)��7��v���OF���r�~��&�^�	o*�dbB�(k���Y��I&�������jz{3�q���0��������t������}a���Y�y���A:��a��5��5�7�2:�PV&1jk�[�?��n<���Z��0�'����*^dR��P�Kh�8u�������8��dzk8��qr����#�r��Y�U����n�����c��"�Vv��3��%�/���-���	��Q�v�1O#}�"��Qk�4�EE#+z��I�V��bh��<��������|:���$�:�4�������c��.��-�x�u|�.]��3�`
��x�.n����DP,�=r��J2U�f�@��!�;��*��aWf�����p���)�H�b��t)�e�8�D/�{�M�%�8��@D/ib���fx���3iP5r����\��Dt��%Z����bo%w�$����������"9���1HI����y��� N�q"V@�������G�x���)*�����{
km5�u+�;|f��^f�6�@]8�,�.�!�B�a3��ZN��	�d�$�^Fm�5
wm`��%���2����NM'KI�x�w0N
�9R$�md�\�!����"	13e�� ��p���|��*��,�>��lr�a2}�R|x�!����Q�������aa�v5��kG�Qu�7�<W�"�x�a')T,��F�K�v����=�F��eq���F+��Ab;v���aw[���w0<�����}�[,O�F��hh4�#����ZNk!�\��'���Zjh���v�*uput`��^�X���8J,�7�?�(3U��������p���uw�'�12�������<�f,$����`WK�����l	�sac��`�:���im5���w\��E�7��1��i��_�p�Q�2���WD��:��t�>|�*��O[��5| �05��V�;��"�E~kc#�/�'�-(6������6B���*��(�������n�>\WT\����P���_4I�����X���eU��?�y���X��(��>����uw_��u!�Bv��/0�~������u��
�:����[���	����O/�^��s]
!�j+��}^K\�@��
�b���g�xD�-sp�D���sd2:��Yio�������^t�����P��-�T��E��W��3���+�Y�\���6<��L�o>w�D��6��Kq�d�
�A�>����J��,����L=R>�
���!�h�9�K��J�H?.��(
$��l
�	���#��|�S�34���~�:F���rN�F��Md�a��)��*��1
����2���Z�ez��?Y�hT���'��+����0�^KYb���>
��=bl�_0y�J}99�*X��o���j60�(��#�B��� $�:����%�
��	���I�7q���J|���F�LF��U�����{96���K��k=��(�>@���~�Y���'D��~y=��8�b6yr)�:������<j>�i2����bT��]x:;I��GK���'�?@��(����m6�_�@
�P�86�X���*V"�q����,����L����,�v?m�#x�AD5CZ���Nc���"�i��(.�h�)c���o����g�R��?��F�ULr�cA�Gt�"�@hk%�_
�������V�\
�i�b���b������_�s4�� �����������)�|�L-O�W������J@@P��mv\+i���TG u��k� ��������5h�3hE+�G0<��h�A����-�����R�iT0�$���_�����s-\���,� .x����3��0;<��-�����=��Vr�V|j�g�-�l������"c�$���A�}���PpP^mA���g")=���0����������A3����e�����E�*:��C,���^�j�(��mOk~����[#����o�W����U���E������7�9��4Vf��1�����������}~nSr�yzI;��]�Y��X�����;nHq�g;��B�t�����5�FW
Rr9E��.t�Y-b����Z�Y��X�~�*�R�(
��T���~��� -dhVO=�����`���`(*�n ���,��~�AM�/Q>�K'v=E_��_���Qh��u��3����,�C��$�!0��������f9Hl� -T�ll =���'�
���hi�����+>�����Ir���?K������c�0eh�D:M��h�I�l8\�Yh�.���!D���5x��hm� �I��;���):[��?�[�8i��V�#��h��Bl�Qb;~CN18u�g��b��������#�o��XQ�r^�<?v���o���~�aKOy��o�������\*.$.�?Y ��?7S��q�x�jE*+���8�x��>>�)���������P����B<�a��b:�=6�/$��������`�*Z�g�S��F�X������1b��;��������h�������p/�������(:�"��Za�s�<B4lZ[\�:�b��6L;���z;���O���6_9�Z/���v?���6�<�����^��m�c����r���0NR$-T�&�%'q�V�����x���,��e��~���/�}����;�p�%1���v��6s���?��M�O��3I���
��B��F5+x���r+W�8~<������o��2/�����\8�e��Fd�_2{�$����TE{=�\;���*p�1���V����s(l �+C.������Vn�Ma":LF�P�RN���r
]K�rj����/+Wp�%2u���DW�����L���/���� E��M|��R�Xq��'^{(D������^~��aZO>N
'�kU<�^��&���i�F��:��V2u��;��������,����XA]]���S���14!��'%�$cw�q�ZF3#����6�,��b���x/���!jid42ip������9'���5-��+B�FQ?#LR�w�[p�E6K�"�����ifs9�M�5���fE�.`�L��]n��My#UV2e
�[l�6}
��e����=JyS
��Z,F��2�b�	����G q�*)Jc�$v��Y�D����������i�F�6H�^A�G�b����:��_~�lc1�!��l_����:���^����~�VM�E�����w�����{���|�?�Yy�!G`�a�O_�b'~v���6p�
�m�*C�p���V����tS���`�rm�{�������X���h���o++��ww�S�cmld���>����e�$�6���L�����!����T�v[�8�`_8�
?-\[�P����������dp��2
q��j��Wk�X�A��eKK��c�-���eW�n�8�&v�%�[4�a���T������":�A������OP^.�TQ�����3�=n����.�}��"y�fy��b;��?���!j�0��'l�gs���*����8�k�XY+�U��Q~����C����`�����"�2���/[����zWGG1���`�o�U������jVb�--V4m)�����xS����d��G�y<���nK;7w�$�2�����`5�=h�������s�P��`�R-5�����:�k� �C!W�_��}�(��2^��������sE�hT#�����:�:UO2/��[�.��[�@��#/T��z����4�����W,s>�Bv��u����<��_z�7�����2��<�m�4W���<��d-�0I�&�6?q����
�J�uw������~ZH�v�e�q?| �]lV'Ir~������a���3j�Lf&�:�
m/��8��f��f3i���������i,M�5w�����k�5i��y�k���Fe$��(����@�1B�8�h�RE/������������(6���Ux���h9��"=�]I�8hV��rFYK���?�d���;�3x��}>L��\-��l�����m8�i &TqRX�j�A:���Z��CuG
��S<Gl�v$���5k���y"pe
.�6�-ly���B+�=�fv9�{�H�b!�I�Ih��G�:F���r����2��I�'c��:��b'�VF���*�1l5�"����LT�b����9���t�8���Q,?)��'�x��X�1q�����Cfd4B���`�g^��s�b8�����P�A@^�
O���-����������%OP �u��������q���X��MPA
���7��}W|���x)Y-.��3� �Q�V��;�����'d5dR�Z<rbS��=���T)����mu$l�J�*E�Xt��9ig��#�l��t-��P����2�X9c�2'Q`�HNZ*='�T��*��)
z�v�Ra���XS�������\^�E���E�����Q{���1L
c8�=E��c��w���@d6+���S^_���������,g7��L@�7��0L1�8�*��8�N���K�^���I�;��4��S*�c�|$���R���bq�������,m%5a|ZDU���9}�t$N
KX# |b��VR)�:����uh�,�J8���x|�gy�g�{Ie��������$0xo����i$��73����7{�SY�K\`H�T8JA��k)�hD[�n�43��������N��!���P2
��J���Eu����zYT�����W��4�/2���

Ki�f�������><N�
e�<������g�������7�&^6�c�Ty�d����F�<���Gl ��RW�@vpl6S<38Hr���w��vi��bh���s-#����L�L
o��C�T�]LX(*��#*\��x�	f����NQ�qh�����k��+F.����c,f:`8-�^$�1[�������[����w��?9�j�sZ��s�'/�����i���tQ�Dn��� �h�����4�>����rm���]]����P/��
o������c���������k��7&�X�r�TU���T�B/�@�A��	YGI��L��^��I7-�8��8��Ba���M����{iy����BF�f����#?B�'II:��2��d�#�O�P�/|a���F�_�!Q(�w�Bw�1m� z<��/�4��������{�a5��$V(�����kW���33:�p�E9�z�7O�����PL
��$�C����c����K|���\I�W�f�"j���i�4��3dS�K��GVP���T��%����29M{��+��5��#��J�k*4p�Z��3����>��
�2z���Q��B��sx�j�
W3{�$�����4�F9������mm6dY(z{�w_���i����3D���1���fr�AD�z�	�$�U��m�s�z&�;�������
��>����������e��k�U�����S�U����mu��oa��:��=A�y
K��|�e/
�*��[H��R
�Y��q�TAH^/��6��XgF 6�l�&�Q;�#2j�6z�#BY��������8��Cp�R��,��W�y�����k�dtNXV����Gj��5R��g���_���LY� Sb
���o����C��d���$��j�[�0���(����!�n7��:�}}��J���)V���.��m\�i��~�35��������pS1�W��ip��"�,�F���|7��=�K���{3�������#Txt\�a��>�YAC���`>iX
�<�W����-d���H���,�2���8���a�|\�v����f����f�[u-������=r�����j��$���S�FH�����,��s�s����m�Us�����` c*��	��0IK������1������Y��y}�����twg��/U��x�Kh�����|{��M�r�&�l����OOUS��f������*����7C�,��~�������g��|�}}�&��I�Z[(��Zp=8��w!Bt!������V��x.$"� k^c;���v���
L���RQ\
^kK�7�E�e\�uTs����P��V+��Js�P�h�m6���}W]���|�|����p������`CC9�!P	�������;�,����#��,X,��p�����*fw�)� ���r�$,W�;s%6�T|��&��E�E�2�n�M�=��~.J�C!;����{��u��&+�p<�l=�C
l�y��c�C�(L���M���Y���IL��a���e�w�����)��f���O��!
������n}�InWm�3�h�'��'�����JXk��n���g��5�/�\��t4���L��A�r��	i��!2�\�����cs����D��s<��A��(�g!�� ��y���Fg&��a_�������7"�|�fe���"�@d�qf+%���)�l� Z,F��gq{<|�������;�������o�$�B��qU���#4�G�+tlF�vT�d�	��v��euT
dC�)dP
���}�Ut����!emXjkP���V�*�!~�=�u�a�C�a�d�*W��~��MD�n�V�KSy�x?��49�bf-{i�L������=y_�<='Ih��i�M%�Eoo��^_M�n0s��2'��a���cQg��;��i�3YK�wIM��
��,���|S�3�"E�pI���Q2b���(��l�����~��;��>����������"�lb�teI5��$�X
����c��6���6����=��@
7V2d���KUA�V6v����xb�� �2{���tX_!�l�}�Gph��������a
�1r9��!��0�v0��
.��HJ
��I�@B+Z�h�H�8U6�b����,�Z]$^3����w�j�x���p���aV0J�9B2UE�[��r��d�d�1�i�C��D���,�-4Ev�f@���YK��"�*������5}�&���x�������6�Yf(�b�p@Z��E���J���|44��B��uR�����F�Y{
n1�5�p4G���r�`?k�f�%�"�U��g��x�jq���v��Y�������
����?\�&��7��h��q�A�T�X��[x��������+q']��A���v�B>6}���C!L ~]��."H2��%[��������7�xo��xko/�������Q���*6�lol4�a2���NF��U��w1�+6��b�5t�l_������Re���e���]��K"�p��e�~C������q3�6�H�����\������9r��� �0i!\H��P�����M��la�o����:7D��� ��$��5�(���$:��'���}w�$�'�&�3�~��k�;bs,�_O�B�G���$�v%�"����������z��w����|�8�=��I�,��\�{1�����}��'����:H�P��(��R>���g�bz1�xC�������GG�����\Q�&��^�$u��^^?�LX��f�3��~e�]�LI���Z	�}���Y�i�����9��<C��\��~�77FU4���G��de�8P�>�u�0C�]������s���C!*n���=� ��jZ��??G[J�B������a��(������O��B?����}8�;'������TKU�D*��{w��v��p�^�Pw{1�\����6�l�"��i*�>M�l�{��A�B�e2g�����T���K�P�'�����/flK5�G��b�j��>��o�����afq����2
����OU�(���y���(?Nj�~\���"
��h��v�����������p"e��[��q���
���c�"VU%3m"��X[1��j���Z���$��yq��ehx1=�k��oW��[���#�|dFJ�p(
���XjkI���'s��	4����p{�x�l�����l��>�V���O�����>c��T�Ii��3�0����y%Q�{���:��m96t����^"��D�����,uu�|�s��`��f�������c����e����w�]�� ���;8�,�������*�^z�el�d�7�����]	VW��!�o]Jc�Aec9�[*Jvx����e�F������$�B�="p�}��?�={pm����)>a�%��j�����7IY���1�n���z����J3��C���@��El�$/��yt�����NV|�����~|�>��#�a��jN�&��0���2L���,�~5�d���i?����w������GUf�w_S�`��B�����i�g���\H�{�&~�k��z����7�e\�e���RqI,f6��e��*��j��q�l8'AK������s�����2s�|'k�1����M-���D����o��T���V2�l�z�p�%H���d+����
����D�
�=;Q�"lN�%^����E���V���9zh�!&�g4[Of|�����/[������[�LT�x�>9'�j��6�7e=���N�]`�Zg��������V�O������<������ ����H7w0R����������{z���C�*���,�M��ob����C�2�PUI��?�����]���I���b/��6+���Ms���;�d���%�g��.m���(��SR���\�k_��n��w������W�jI�
Z�a��FlX�.,�I
m,��������g��=N��Ex�C,�M`��6�M���S�k9�
j�P#LqC�!*�Q��U��%*���3?%:��+�����7��v�d�[�I�RY���2��VD�<������-���r��7x�iz�4�a*�CX�"
Kx�� ��l������ia�"p��m��I�4�TA�I�&�Q����"�!g��6TS��NSs�����7s���U���T��.�F,�=c6��4$�
2ip{q����{�4����`�X(T{��E*+C��I���@�z��[�mX������@RQv����^�5{q����B��
^��1����^`v&���n��U�H&Q"Z��O�~�dz
��i��zNgWS;y�����%~;�G��aZ����YR"��5��y3S��>F.�� ��Hv;-��6�v5����$����`����+
������eeT�2|�+�7�,-���a�o�S_�'���8=.a �&I�J&��!���c�)����x�	��b���T%jMtrL^�^c=��0����4U��'��*��mhB�X��i���������\��2�a�����4^��0����K�(�X��a�?E�����2�K��B4E�'7��LU�9o'�;_�a�y��[�;ASg'q�\4u���)��M���qO��!F����$6����SM�i����?�����!Z*6u�D"�F��a�mUd����v�N�Y��k���A�4N��2��y���������'���Q��l6�@��>�����>z�����������i�����c����e�u��/G���v�E��4��UmK0�	�dL�<Kp:E�sxk ����P"�9U��|{�����tv�x�qN�����5:�����_�����B��"���w<T��]�ug%[��6����y>
����fe`(4��N+��M����qoo���������'.���b<�_/|�w�NV�e?��kb������]�w�p�{8����X��YT��iD�@����(��:C��*�&�\Q�����yj}��<;�(4u���uw}i/��z���$;v��jp�Q|�i�2��8X~�N��Vi{y��T���`7����F�W\��r�'�E"�B(T)6_�$����/����^\@Y�
��P�D�����ZE::\�C
M~/�Z����dz���������A��g?{������X<����cI�Rbn�T�����ID�I����C�g?�g0�0~>����mw��O��+��H9u\�Sx���!��m!�Myl?�����!���9�X}0���zv�Nr%�h���k.��(/�W1��/�4���B��A�����x].���� �dv�d��ex%��l����$���9A�B�������
5��%=��J�e��F�0�PJ���n[]R�ln���n-6N��x���667�w�$#�����-C���e���a��'f����bZ����c�����~>��.	�Tb[��Ecr�U��	j��h��f"[��O�$���\������
Q{�EOl���_��f������too��[#��gq���q!�'0	��X���7�������47g��3�G��;#����,�������c��V��W�I+G�z������.��b�������o|�U7���#��n^�|�gF�|�������|>.��\�e\���T\��J�z����[���M`�\��U~���kn\(����b1W������=��~/5i��q:E�@+����%=���;/�Ru>��w�I��7��8��A�7,!=��Wp�%"�u�X�����A�^��>�9������8�S�X�952�J���i�=��,Cnl$���������+����q�R���[I�
�N��/Eoo���K ��������
X���2��$�k���n�Iq�2���+�L����D�M�Z[�N,uu�&{
@w��rK�Rd2~��/})p�&���E�#I�_�
������x�Js?��,M�_�Bk\���dd0��5��!2�����������v0z�S�(x%6��>"L����,�D���51�1}��W��d�B>j6_�L%C�c���g�HK4j}�R����sn��������D�V�O�V�.�,��`�N/��(����0m�C�YI���/=�{n_[�{B!;��5r�]C4�Mb�q������	9$CB*�"�|���q��)DM�v�.�@T*�)�������c�JY.����C�k:��q��v��N��b�:���1�t}fA����#7���b����
F�_EE�xP�QD����,w�ZA�Qt��RDDAE�� ���H�
r���[scz���$r���%�$�b�
4e{q��%@�����G@��%MRX�12����
�q�@��Q2S�G���F�X�c��VFv4M�i5�Q�����G��������WG�m�p,[�����G�3���N���"�IL&Q%;��laY��C������E���)����A��7������.����
�Y��k	����qSJ=>}[c�O.�"M����@LR�n8�v
��B��qD]Em8�/�����?�'@<N��cx�Z,�w��H���X**���D���S;�(Plp+c���\���>����������1�kc#��/���S 
��Y�o���}'�����#�<�-|�m4��H)_��Hv���qm������� >X�Bl� �P���h���7!��p�c��b�������,�T��C!�i1����s.{������O}
uz[[��n~��6F��4�����H
��$�Q����d��G��;�7�����&4M#���� 744��kc#��Fb;v M
��t0��c8*�,��B���������X�~�������x<��E	��B���|�c���N��~�1�����,�=�{i��I�F�4Nl�2��0��.�������}�P*((��B�\������04dVU/[�D�/�F�w������[?���<�.��o8��B���c��=d$�D h�s_��_�$��u*�h?Nl����m�<y\,At�}��b�]�(o�RV�P�h��wf���DG����B�o�k��k�HP^,.%[4��*,�� +��ToY�*D"�������������}(d7��L%{�[t���|�����H�+
��Z,������ER��7���$U�zj�,B��#�i���9c����_5��0����X=SG���+D��������T���(��M��BR*��b�R����-�<H����w�� ���\Y�\UE��O�t�� �"�y�R2')<��U;�C�D��)
���d�re����:��1�s'���n�����N��n?�M
|�k��h[j����������bx�l1��O����^J8�����gx�u�m��!������K~��?���fS;	�["�0���������������\���DF���lP%�����V���9M>���������ez{y���,>��r�U0��	ms�����ze���I|Ye~�q(8�|���-���z��O���xO�9��a�:���JM������Bz��!������9�����CK$�l�z�D@i"Lr���8i��je2n46mr����0��2��A��Qj�}����z}��Lo/����0����x�X���MT�.f�/Wr�.�������b����ys��5��uN���p�r�T�
\����o����(����>8��p�,����3�UE�&��A_���
�[��~���0mq<M|�{p��0.����b�ng����w�s\���:CD�mcl��O�U��\/���,�6�'>������[y��Q*b):�����~�-��z�c���c@��wjl���#���9P��
�������/L��n+�8m�8Z�n����8+\H.�w��-D��������d�a �D� n���f	����G}0X$q*bl���L�Q�p:��M/�#�u���r�
&�}��n����t�����.��'�
�g�D�L�fC�� ;�!�H�r���������4��0RE��
��:�W��'�����d�����%F�r��,��S�����Vl��c���U4 �z���b��CR����$�g20���n�l KW0��4���!m����oW����?������t�Dhb���� ���o�%��jOph	DY6����~����p�O�B�{(��`���~ E,�alK;����`�����F�	$]������w����@�ux�	��(��o��M]�K�d:��l8���I����O �2v;���������������2�r�5?���[X��yN�}�;�\�����a�*��N�v1�T����2�w��5����'��!��3s+�����5ACw�e
��q,����A���5B�P^�6�	�j]���[>����������,?���	mV���CJ�f����2�l�:�|�����w�d����u)�}���z���:D�P��t��t'�������������!�o�Y��=�	�	��v��8�8t�����9����n�������z���1���q/���tv�������Fy3��&���������0n����3����]>H�+_A���������X*M@���}.n�2��f�{���;z]���~��
G�/d7R�����|�B�����0��"!/.������O�S&���p��	���aK�H���v��������f�B���|��l�|�������3J�������sn��6>K�]����`�������(����"}�M��5�g���G��v\.��,����������.�t���AR���%����+��me����������mxb1��JhN[>�q�k;_��||��l�|����#��������7$y�k��#y<$�{�J��f�4x9�N���c�4��={5�\Z
�k�y��A���G���>
cJO&�Z���$
'���@���Y�U��
�qT�1{��->����,�c��{�l���6��U��q����s�W���{�i��c���Z,f*��"���������v��F9Q��I��Q�W�IV1��Bm����U���R~��<�K��K�����v%hm����q��C��6���	U��/�!�V���X�}�k�����=��FH�Y����n(���h�v!�)���q��*��+�7*x��r��eiow�����{��
��ET��Bv>y���8�#jL+���&/t}�?S���%����� ��U�$��i+a�dB���G��~&G�n1Zx����<�/������������R;E������E�w�M0�B,����*j�?eUf���r	�u||K���>������=���I�p�
<s���1�t������@
,���'(�zt-�@�
�z9�������G����t����+��_����$���m�+���t@�Z��N��(��,��#i&������MN�1���>�����U`$��4=�1�����)�p���p�����B�F�d&Q$�|�XY�H����OAM���b���"z*���~�\Q�����5
g,3��������,��&d��m�4����4��Q@(����T�k�"��$����9�x�?����������$_yT�M���	�!;z����zv{62�m�����==q���/iRN�
���a�a}��z�������b�)*i�e�t�q,��7{������#{(�v�W�7����s�j�Q���e������������t�r�O
�P��V��������N����rSE�����2<Lt��9
����r��w�~:����I,��U�o����`x8Gm��p8������U^����@L��m�W)
F<Nz�n��f�����������(>�Kh����rE
��V*\mH'��hs��Js����3I>S���������21AyW
��3/���d�=�pdNb(H��c���������jj�S���1Rg���N��e�g=~����z��b��3���6=
��:6F������'
�*�how,h��F���o����p�s���O
�jq��^���?������{-g�������=I���9����ho/f_o��o����=���B8����8_�Uz���P���v��N�UE���o� ����J��V:��},[�/>.Dl��o��w�S�,��}f|�9v�~Tm��$��T����H$I�r���l{=����������$dV����XP��+0.�\~���/{��"����|�"2�~luU�^�~����:��m��q�q�Q:7�I��uN�K0hc�����A|���1L}0�H����3D����i��
����=��]	����1��,�=�sn�[��A�^�M�S$�6������3q�����1�o�p^�`��z�[�x9z4��-���x�|�`���5�BD�B�s1�w!�C!|w��[�2�ib��V���RJXU�m�Ww�D"����-�8s���?���c|�#+X����,Z;5
(6/��PW��k���b�D���i������r�����w�w(|�R1J$\���&1	�jA.^W,���s	�O��V���2��_00[�c��1=�!����({��|�r����o����m���@44��(�����J�Z�=����?�3k&I.8�X�A*n�	"P�����T���m6�:60��A���v7��Y���-S�<R����Q��6A0}��NS�/I�z6������y�������{�"~^�����~��n��
FM�T������H����s�k{����%�(cc(���}7��������7������(�����<�:e�HZ��('O�����{��&�V^��V�oDe�%~1�!���L��#y����\\C?-<{���L�dt�1�W/e����N ��p�����)F�}��`CU�N��5'����),�8&�4�@Q�B��--���Hgt���wI45����(���
�>���W���	$I��/����L���������������7�Q�.-"�c�_�������`9���I��{�fu���r�_��(��]���`��:��}�c��<��|�S$w��PU���.�/yN��y�*��T�w�x���69�k�[6�p�'_������P�U���v�=FB�
��k$w�6��|%����^��(�(�����{�������5B `f����s>��|�/�w���8��Za~�������1��l�������/�8/�p;W04��#�]�[�����.��}�������AR�?f��c1��{Q�V(5.��xO�;��q�X���}H^��L]((}����u�|�Qh���~�x���������7
sc�����]��:W5�|�]��]4w��&��B�������t}�X����z����@�z�M���B
����%�_,�Z�������;��i!���^��p37����q��2������%�5���I$�T+�����q|�NSVw&�TWg����,A�8�`��
������7�[[m�w`�/��V��m��'�:8z4E4�q�[=�r��n��	����b���b�Lo/��=�Kt��j*j�M'K�ee(D�3D�������z�e��Y�$D�������$�4�$0Y������������g&����;Tr��T�v�`��{��R[k�A��\?�*��`mm�}������h��"���:9��`K��B]�O��=
Z��\A�@�<F����<	�j*�eiD�j
	��������2�M<��L>�0�������UU�m��7��0��K��{{3��*(����m�(I Id���~��)��f�V��D���v��9�=����sX�Cr+]uh�9�<i���s>H6�F;9���`6SFT�M;h"�>�$��B�D�}J�
�bn���&O���a�	fb���a�
h���8"��F.�#�p�@���x�{x��h���8��N�&=+����?�7���R<��w�gm�b��s����������yX��e�o���������ep0G�C�E9E*"a��%�m�����P.���v�n;���p)�A�^8��7����@��1R)�P1�Q���==f��R���������pq(�9oh��������&��n�����\A�|��M��/sSz����~�x�=�.%�����v\�������}�u�?��-�b�8��]�������"�w�KM��WD�~���q�q����b����y=�(�����������E��Z�?^+����Bd����2����6������
���T�-s�����8���4>{�6�I �{��v���Hh���������EOO�m��s�g�[�xY��I]�e9���a��D�� Qh�#��������;v���+Ql�������B�D0*S�Hcb;v,X�m/��������A�	$����~�����{	����Q�H���}��<�'��'�
���s�������B�D@h��g�vuQ���������uf��-���>��s���sq6lp11��N��_���k�P�8aC��(�(e�(�82
�`�hZ� �W��������I��o�s5�t��*�������p���MDgV#��J�D�_�e<�7fB���K6]e�s:f�d5gp��9��=;�,#^�G����sN)�m��I(
��D�r�B��o%G}�91[���os��4
2�T�b��;,\s�����9}l�q���eFl��L&���H,Y����x<��*�f_�Qp""e�q�o�����L��s�}��s�}��:/�.�_;��X���~�����-#E���F&�22�@j�~3! ���c���.��PxO��2��,-���������.�|�����TW���>�9��f���!L;v����������������8�}-C���{���/����p�?a��(�o�^x#��_(�}�3.����B����K��^�����������k���s-����]����x���NN���7�|t�qo,�6���"��^�g�Z��o�}���b�]�/O(d��B������c��(/���Cd7G�K�������P�,�`��1��O��X�PQ!�o��� ������Tw�������Yx��IRG����C���}Os8���H�<2EW�������e���!<�N��;����66+H������.rCC�33��almmD�3��il���3:��k��#1��I�[)3�X�!�3,N��r:\�2}�=&�����.�D����f�%���{���yMeg���"���>�9T�`�J��W���QV!����x�����
��v��j]G�FDkK�P���.�����A�_���4D^�[�4w�m����'������-�?8���~^/���"AX���Nrhg��e���{Tz�
���`��J�������
��(�����!v����y
a$�(BF����Ml,;�j��2�`_w7`zr�m��!�]"��2^�^��5���u����})	
�����n��,<��O?=��!�rI��Y�\s��A��-]J��	���n�}�s�)���p�]��������$!�"�#G��I��Nad��]';0`^�I�@#��{I�������O������s~>6�f\.�dRC�������B8�%�����=r��/��L:A4c������o;�jn�~d�qZJ����F����}���;��@������V��F'c~���������CH8�>p)�-��J	���_�����E��'>�3o�M��;iq�q>�!�G�q�q��_o�}����b����(
@�a6{#5�,����?���{.^t���`|\-���q!AGoo�m����\?v,���Y`P�c�k��� ��������N���Q�V�]��p-���TCqYA*+.�.����5r��66�����wqz G��/��mOc��f,���C�f��Q?���n!����?�������{��n�<#�����{(t�
%/��
���#�Y��!�\HN����Y���g�{����������L$������C��	��m��VUg}�3��G0xU����J���'M^�g����#��_������P�@0�@x���=��s�}��Dy��^���F������!a#��Q�����PT��	�Is�c�?��4W4N�u��^"[��=qmf������o������L�d~���1H#����%��,�
�G���2�J!8�>uw����ce��}��LM!h��#���6l@��1��"d�h�T_���
��>�����}�]�5.4�~����R�d������F0h�������2���aFb6�z���~�����9y�~��c	���Y-�v#��F��������	�R\L���Dt��C�~����!�����,<ot��B���Y�(]�b1�;bx�f&z�������r�2.���}>������������!�Xh��d�A�a�h�!n���z���Y�j��h�����9/$�(]�����D��q�����T��Q���u�dLb�T���|hY��~|���j��="����d�^X�>0�C���yw5��>Ay����)�]e�*�C�������ISI=��t�1��`�x`��j�{�i8�\���me@�9g0�����U��f������-�ia�a�4P�'{��/x������U���^^>q��1U�!�G����{�w\hl���E�`&wf_���?���g]���a�q/$����r���o�p�OK���W���E8��x��
N�-�HO��8����W������I����R��+5�����"A�7H?-�u�==q�I�G�K_j��3(�N0hcb"����9���'8���wMehq
#X,x��v��MT��-�m���PP_�������xOJ$���B|�>��������������L&O$$<&j'��D���6w��ik�������]���C��k��n��mM��n�k�>�A��nm���v[�hd��a5c !BH�`����0�30��u�����:�������{���t)C����1�X���@��@�F���}�IwG�K�q�qb=�L���}��,'��>��<
�p���r��i@FFh����gTld�g�;8^UE�4����D��w+'*�wN���*��d���o<se�a&�\~ZZx<���'R=�9�pce�F�������D{��[�%U���HD�/~g�JC���@Ee�2~��8�0%���x��S8��Q���O����3���(/����D�����U�29��l(�|�sr�q�7.���|�8��C���}}����!^�\�u7�o�n���>h�����#c�f�QYi���z�9~�+{~�� }��|�?�>�^� 
o�bz�\
h�0%<�l���{��Bk�Vk:�7/vM��qx8[����@�����!
�//s#�{����V���o��}�a�r[���9���u�=~|`����Jggsi)����U]=���D�p����y�T[��M�n�2��-[EJ!�*),����z��(�����X����N2�� �������&�������_7G>S]];v�����OO���~-J��,'��={:���[�������'�8��7l���z+���a(8��'~I������S�s�c�r������t��,����~��������f2��x1�����S[�@[�� &�eR������b��N��\@7�g����5Ft_��>�����{_'���aN9���N�<8S�j:��x�D~��u���U�������7w+'*�w^�%yR��d!O8�4�$x���	W�N���T
����}kb}�/%�+2����HD������Xz��4�p�.��������^^|�KWW�#�'bfH��v���c��jYYp�����X���*�R]�EG�r��%|�i�C@yy.>��Cw$��n�f��E��������}^����"�A�Z��_�h=L_�)�6��|k�������)�	�rI�b%�YK3G�J���z��k�'��_�d�\~>��&�y'���s�o�	��P���wq1����1�������2~X�y��w��*�d��@T�R	�1_��+m���'�m��B��C�p�56��E�m/)/R������{�!l�E��8���;�8N�������������O>����`G�]]~?���Os��'��30x�y/��Y������>�����7���#�q���������;?P��o�C�/?2�{��[�� ��S�8�����{���'����x���g�~�U45��H�2��r��vhia��=R�gYe%��:��O$��d��Q��55`�t��5F����U�W����U��<oRw�O7n6��������w����K������v/���z�D%�*�.qSVJj���<	eM�V�T�J_���S��"sQ*��Dd~����BK�4�pS��s����@~FFw����}��'�4����t:m��f���u��}S5��=V9�p��m���� ��\��&����Mj�DOh9��su�<Ct�J*�8�|/'��M[D���\�����#3o+����R�;.�6R>�=�Uv��`��E_+�l&n�)/��D�m���������P����t��1��>���&��6�i�V��%c�u�s8���;�r�=vr���*T�|���.v����x����=x<CdfBO�:���.���h��I�q��b�<c��pn�"���������.��;�h��
b�����pX�=���ZQA��MOC�?��{�a���?pN�V8��knn:�_n���G__(���3�a@C�����wY�6kX�gw1Ng�� 0�PZ��S���SS���o�:`Pqr�:��`���]� Q�e�����Z}>\cd;|p�����d�s�h�z���n�ON�����,�v��	m�l�J���\�|��p��)+e�����N�[vu�|9����*����V�w����zi�D6�rWg<Y��r~��bz(/�7C���G�EI��n[���d����
��<��H�ZA����K��`�F}}(�Q_���R���9��w�f��i�������
�c-��S,k}���,��(�� �m�k�w��w�������>�� --T[`��El�n�+�?�����L���m�F���z��{��v�_~�i��
-���ss�yg����I�P	�>,�t����y#��L����jJ����e����%y<a���Js^	}}AJJ�|��E8���UW�e������z
���������w������o�r����������S��44`{1��pA����?
����=�o�����N�:k�^['2�m.�!O�]R#���g�fe��rU&Wm���}��������p��)+e��@��N2�EDD���
�j,=wKC&���T�E�d��UJ%���l�vk_Lf����=����|����uy�����H�h<����F�
����������rhi��~����ef���3h}����L��v���H����p������T�b���A22�
��t���U�����_bm3�����H#����2VW��z#�H��y:��57k��rxp
��9x<A�(+��f[��>w���=���-Z�u0���E��]<��Mcc>�	�gf�EY���c2�a�f�yW�����(v�G{�k�K�D�9�����s��?����4��<�}Ovq������o�s2Hq��#�x���'t�EL�LT,��V�>�{<��'�f["���������Om-Y^/&��������pREZff�w
�K��zV�|0�:���D�����v�T7�_����D6�Mv��r��Y*1�������f����K��#-#�`O���|8��*������bs~�E�]'"Y���$0`���'�#%:h���U>��!�Zt6���|�XA�����ZM|��Kx��>��vi��<m�{���w&�z�4)wY�Q2�1~�mi������rs����t<� �j�����/�5��k-��)v�X�����n���,ee9�v�Jn�m��5c.r��s.pi�q�Uw>^6��bB��u����s��
�~�UzC��X�����������N[����=��}�Am�gX���>�V���{�x���1�����x"'H��b��J����r11>������]�4�9-�Da�YZw��T�\�T/|�HD&T��������4[��#�D��TM��h\��p��cG�����6Y�����M��L���U@��Exr���R@�����lN��I�=E����)`�\��I�S�bz{a�!
0��b��Ge��Ufj�b�C�R?���Fm':�z����s����*���/��ep5Y�Glxm�P,��g�@�|����PM��^������C���j�,�(���V��L�7��K�y���w�y�%��=i�jM�f3M����tbs:�������;�\2���g0��m��
����^u���z�X,��|�+[5�������X�>�7H]�7R�
R�Z<��!��N����w/���'����&,�Taz����p�c��@f�JD&T���DDDD$~����P����N--t����8�^
hc���Q�k��7��Vl6��O=�^�!SZ(��'���;�~���mKo�y-/�UT���Om-&[(����;�,35�b�%4G2���[>���98i[�7*�����Re�T��7\Z��z�8����C�C�!�|���k����\��;Dgg(�577�7��%'��������GKK`����g:��=<������������,JK���~���R[���,�+����_x�
�p����������n�j5��JK�)�]��^W��������T�O��A���m�v�>��V1p���,��s��}�TWwQY�,a�$U����p�~��&P�]D$)�	�*�T�j>|)������P��o�u��bkE��z��P��Xg���w���z��G���.����;����F���P��
�����8�6\��1�y�'eJh��6���>mm��BA��%flN'�*+�ih ��<���&x<5gJ?�����t�����o�2��"�)a[��fk���;��w�FOF���������l8�<�w���~���%�PX�������oO��3�df�10��m��,����U|�wD�(������3�����5�|�x�C��L�����d�u8����0��7_�Q����jx{����(��{E�uX�����s]�&����"kOD��������tY�P>�w��E��qg�\����L[�oG��	�J�T�f���Im����w\�Z	�L�%�7����f������)�gn3�������5AJJqV��?O�e�pd��@��e�g�x�q8�oj����������.]����;�Ox�o�~ �����{t�?�E���1KWE_���"���VWwE~o��ik�p�JxL7�8Q�����w���X�����O�����i��t����x�A

B%^pA.���C_��]f��}M�n��q��\��������	�;%���u�~�m�#eB�Z�w,�M4�].�����>����X[Q6�c���n�9/���i#��B��d�{���_?j���98���yMM�	)��v���ij���RU�>/���"2-�r;b���\�v�)���O�T��w[�j����1I%����w\<�Z	�e����E��q�z��rGe�v���y<AZZ�\~��H@���E.g2�����`�d�y?G�q�z1_��urO���}����fYe��mO(x��h{����PRb&��2>U1��7�5�L,�<|���t6o^��}���z�������sd���e].?��YU{?6�)������'#V�g�$�l<i%���&6�=�y�
���Y*�������[����������IbeFG���]�r,�>���&���^�`����{��A�/aw2�].Z�����F���QX�����\�6[h��#����D�G6���p��#���������x�C�|A,V�)%K�L��"2-�u;b*�$D��s�����f������������6^���Z�����Q6&\����G}����e�����%���W�����������-[x7��[�+(-5s���6
8���/��w�'�e;4S��k���{�nk1_'�8�]~�v��
7��c�&�X<���
e���[����B#+�Z�_{��%���D��p0wmk#�4��i����i]�F�%aii���{��������pi�=7SBu������\��CcM��/���p��x���p`���~���V����}�>c�n7�8������x���g�~�U��6S������@�8s�8��	gJ�������������j�j5a���E	�EdZfk���4	�|q_(1����C}RDDDRM<�_�e����J�8�����L��o�����C,^�����1
j�H�������`=K���X��,�<�`[���2VW�	j-��92Nk�d��mku#������dA���lm��id�3��^/&�u�R%c-��2�p���df������MF	�����M����~�z��$�����n��X��}M��p��v���������.�%����O��C�au��j��q9Y�2��o"�����v���&_�}<f���|OM
Gn���A��A�
?W]�x��$^x��SS��~�Uzg�D�d�)N�
��<�J�(�."�2��T�I��1���H}RDDDR�D�_fRt�����"/����[��������;Z9�gfh���p�q����?�����k���Yv�8���e������q�K-y|��0V����q���*���>v�}������+��u&���f��{5�5�;B�uu�56�n�hn��DI2�����>��V���,Z~���::��	�QB3[$s����Jn��	������!L.*������lN������|b���v����NE�>_�����b/���de�d�h'�#s�
�����nW�L��1�D�T�2�o%|p�iK��r*�$���o_���>)"""2��u������r��[^'�>������z�5�o��t
�O518�D��sH�z�����~���55��6�<`�8���W����~����x��t7
�Z���]�B�<<����d��-')�\
@M�g�e�c�p=�S��f��%\i�X�K|�oD=&-���0��8N�����fuy.�>�����
���s���g��34n{
h��t���Md�I{�$?�K�x7���?�)�--���yd����3��|���'�D����4�\�F���)\�f�l�X�+�����[��9������V�	4��G�e>��""I�II5����)JDD�]k|��^���SXZ�2Vi�pr����X=X�-X�h� �e�������o.����"�ZX0��-����G�_�8��B������d���������"�1s�w�r&�(����7*���z��DNu~����c�_TVF���\Z���"2i���.[$P���D_�Wi>��g�v�������Y�4��@FFZ���x��f��\��^�� c���-js:)&���[^>,�=z?NeLk\>���������d����D`�����Om���5Ruu/��KF��TWw�s�����d2}Rw����������k#3'[WRDd!ZH�Fggz�A���J#���s�s���'<�8�+���`�2����P8����\����M�{(
�c�����t_�2��@F^+V��
�DOL��Cm�fa�Z�s��,����Vr����=	g���O���9���[On!xZy��U.F���vrW-�x��`��v��OKK �����z~����;8z�=��140��bIXI��3����������?.\�>�o�c;:0���t�N�!���I�]���(�.""""��T�""�����w���<DggB({6Vi�X��Y�;9�p�5����y^�s�oC����f�������rL�[B�3i�@���@G����a���3�Z�A�����z���~�Om-�����#�;2�5��zV�������������p���d��h��/T�D�����V�7/����tb����8�xbM��&X�,�fM�>=l��G��������088���8�K��.%g������p�yMu%ED&'�Qj.-���)!%:R]tv��n8�w�n7S@.�������@g'�+V�v��Q�
geg��~�[>���=,���Jf~>&��%����ra��=��)��m�N���d��:��nw�����B�XF	;)��6
8Y����|�f;��pp���kNg�����x�x�C~�F9����uu^��}������xw���]/����j��w/A�_}=�������=kih���<w����QW���-�����Tr�,]������d���i����������k�+)"29���X5���X���8�`�cVoK����5��U�����f������y�e�22�?���{L�?�=*�;\�f�����U6l�R_}=A�����au��Z��ZQ�&�>�f��'���K~�z���qp6�N��JDDO��l&n�)/��T��9�6�����T�Q���^�)��}��c9���!���� ������CSS���~��)9c/�5��/HU���;LDw��QWRDd�Y�|�g�O����p���M���6��-buTp���SW���c
l����R���'Xv:08�����)�@�w_9�c��Y�<z_��9��$�8�Q��������fJ�1�e�q�n��%L��'��;�Ir��Z����2#�	P_�K����Z{���D��RS�������),��� �?�uu�ET����;4��}���������1�,Y�����/��b�jM�s�X
���������0�Q�#U�������}������GO����mm��VR���b_>�9\�t�y�i��~����W�2F�OL��)���B�������d�N&9s;��N6s��r�z��66Fj������{��H����S�|���D��RS���������3���$##m�����I�O�x�A
����&t��������X���l�9w���""""""""cz�Ex�kx�5��C���/��p�P�T�o���9��8������d��=4�������������`�������O'��<���3��D�u����v��0YB�������F
+Kf,�=�����?�X�kd��#�@�x���z�l?kh������vo������q��dN��`jr:m1���+pCt@��%@}�/��z���-���RQa�9���tb>������^���(�_�|Xf�x������G�[lp���L#�{�#�����"�?�l�c�X�ojb0`p����������{&k�%Z��N$3��W1��������+�X.������e3Ej�g��/�<:�=�����\~���81���\{�2*+��D U������d��������������8����?�VwE���
k���������_����%���RP	�O%������	N��`8����n7���s�`&�^v��'���^,���#������RUu���L�L�7���p�.�uu46�Q�znB����x��j�zz!����
P��������}�-�uuS�GO���Nn�)R�}�����r��0�l�.|:QF�T&�B�������s���$�t�-d
�������HJIV6�le���1V��d�Sx;��{�%K�Y�.���~z"���d���f�����
�\~��������YY�����z�j�������H���j�����"Y�� ���������DOFTU����%��S
���n��� Y�A��2H�����G
O��]�������b���Ly�S�z�!���@�3��Q�]DD����E���y@�]D$u$+�NYz�(���>��l��GKK?�Fyy��^���f���q��������tu
b����k��
F�i3=6r����Ll��hXP���S]����������Q_�c��^�"���<O�Nx2����
a��c����B�������v��|�z1k�_�O��5�XK�`����e:�`dMv�4`���-����Li!�����f<5�Y�4�]��-���fj��Fw%<�g���U�����b66�QV�3��Ke�-��&Dd.IV6���$�D�?�9'�������� �����{`��7D 0@AAf$n��d�v[�R3�4VP/��p ��(�;�\Muu�����<OuR$<a������0��R3^�;v���>�5	PS� ���x�Z�G��dceYdA�D�OG�dki	�V�3�������[n!���'��B��.�z+��d�X��i��������.��k��d�����}�E~��|�Ee�Fw%4���bI��9@]�W_��������q�_t�>����B�P��%Y�t����u�7����HN������l6pfPQa���CS��+L�Z���]�lX �j5�w��/H}�/�c���z�>�G6���p����yNBev���FyynB���I�a�������d��{���#<}���ly�0y]oad9z��das:'����jz^~���n7]�����s�mK8)���H���3#�a��
si)�MM�*�3W���Kg��""2c��g�==C@==C1o���c�`������?���S�^��\������pM��#|��45���6�\�����]���y������m���0p8rhm
�����z������<�~���z������~�z��nw?��b�0

��%33����)�::�0H����|Z��j���ih ��|J��v�G�&�z�TWw��1@^^f����n���i��"�Q�]DDF	4}� ���Y_<)�D��t�>����|�P��)Y�t����t���q�����Z��
O����JX�k����������������(,�6**�c���������g�X���>��~�xz����W�7<1S����[���v����u�Zz=uKNi�����Oi{K�N<O?���K����~���[��,��Yi���O)�I��v3����6���!z��7HZZ�?�e���	?f�Z����L��""2�L4�]��?�����	I���O�o�����R�R�6�r.���L	�p�h�1����~�z���-��D���
����SQ��M����������������2.L��chlx�[6����)g�C(p�v��Q���p+�����A��b�[Z��M}g@cc/�����N `��9���]�G$
���HL�2�����YDD�5��	�m�70\�y�p�[N�8��e�M�Y?^��D���KO��N��%��1��KGO6�:�*h
D�
�9������Q��	������-�--��������55�~���������bEfR��|]�B�Cw�_>a>M����e2M�YO��D��8���p��c�{���m�������h<���$��.D55z(/���?���O���?��#9�6��YKM����p�3�9�'��d��|�!��"""""""��	!�h�(�~6j�������{-y��d#]9E��n��'����0��={:����df�����`��9��8Fg�O��i����v���ij
-�ZUu|�L>��H�����������"�#��6��������uV~t��|����E��=t�������yk+�8\�^hY�a������5v�s��<��q�� ��C$f��x����(55��2��v3^o�/��b�jM�L|���w�1Qf�\,�2~���;�������R�kW���y�j���x��NN��������� �_�����X���#�����Fyy���YS����30���M���vV�@�N������TU�jM�f3-��.�:�EDd���6""""2�MT�e.�x��~����K��@�����D�lv�\Cyy.

=��gR_���=V
|��n��0���n�e����55N�$77�S�����x����s��x�A�V�v�N�
����L���""2�����������
f���J��0��F���p��p�����?�$������
#��L���������Nss��:oR#��Mw�Wfc)I�l���]����`�������~�%:�\Y�������9���TV.K��!��UW����:N����L��""2�h-""""2�d;�
�G[h5���#�����rL��b{�4jk=���@(_[���RZj�����6��������+@������xT$�$������|A,^o0�]�G6�v�:RBwI)�X�t���������H��v3����i�����z�^G��S�]DDR�<����E�$���\����Hb(�."")C��M�F�M����H*P������n���H�<����5��D�?�������g�p���O��}#s�&�DDDDDd!R�]DDR�n�����%�$��HwI
M������B��"""""""""""	�������������H(�.""""""""""�
������������$��"""""""""""	�������������H(�.""""""""""�
������������$��"""""""""""	�������������H(�.""""""""""�
������������$��"""""""""""	�������������H(�.""""""""""�
������������$��"""""""""""	�������������H(�.""""""""""�
������������$��"""""""""""	�������������H(�.""""""""""�	
�?��sl�����:�o��`0��������Hh/""""�	�

q��7��_��C�������?��������Hh/""""�8	�744�f�6l��
7���~��Dm^D��������5�MI)��_t,DDd<��|�����w����Q?X�t�E$�d$jC���E~...���%Q��9��rq���"?���N��YlQj����c!""�8^�:�wfG��}�������c/"�&aw�0&|������{w�g��MQQV�5��O�<���K��Y��z�|�s�u���lc2�����x�����|>����efb`z�Y�-����t�9S�r���6��/'z�T4����/�}�t��e��n���x��s�lkmm����g�����d�����x*��4����g?z���%{����e�^3�qf2�
��o{4^J��/�::0$��g>�3'�w���z���/'zL���acy#A^z�%���.���������G>2����o�v���_�>M�u���������T�1�����D<F}3�^s��L�~���/��k�z�����}��e��n��M�3g^2���1������|}��G�r���x)y4^���u�L�3������=f.����p��u+�������<��#\{��>��k�ITR�l��D�n"�7�mL�9�<6Q��f�}&�5���T���<N�rn�f���x�sf�|�.O�6u��4������|}��G�r���x)y4^���u�L�3�������}�T�fq�C�?����v�m���SQQ��~�#22�^�f��
���H*Q��T�~)�H�RR���p������&�KIE�����7%��~�����mK����[�-�DR��T�~)�H�RR���p������&�KIE�����7%��~��w��*a5�EDDDDDDDDDD2�EDDDDDDDDDD@w��s���^>���r�-������#�{�������q�e��vSD"~���q��7r�������d��#q��A���/���}���������D�A�N���I�q��"��%Ui,/�H�xIU�6��������%
�������{��7r�Ygq��7x�����G?��>H}}=��l��&�/W�\���>����g���@L�_~�������'�������&�1��y��g��C��c�q����h�,���������W_=�M��4��T�q��*��%i/�h>��g=��������+�~744��7��/�K:Dww7�?�8---���Ggg���Y����K��0�~y�}����~&�*�T����G���Z���g���@L�_644����������I�K*�8^R�����4��T4���p���K���������Y��
������~@QQ---tvv�b���m�,���"3a*���{������|�#3�VYX��7���J�z�)��ye�JRL�_���7������5mmm3���F�xIE�K��X^R�������8>c������V���"?G��^{-��z+�=�_|1�����LY`������|�K_���_��[oe�����LY`����������p�e��r�����g�����7_|�E���`��-�.�3^��!}�����o����N�xIE�K��X^R�������8>%��a���E���c��`kDB���f���zh[#2^����?��Oe���7/��.���l�H�x�2��+���+�H~c�)��%i/�JcyIE�K*�k��Y/)K���G����p[$�~)�I�RR����"����>�T�~)�J}SR�������/S2��u�VZ[[y���x��G���kg�U���_J*R��T��)�H�2���%�_J�R��T�~)�h���Y��|��),,��[o�d2�����O~�u��a�X��g>3�M�D�RR����*�MIE����},�H�RR����"�KIE��_����q�z�������������|�������������H(�.""""""""""�
������������$��"""""""""""	�������������H(�."�������m�����hkk��������m;���n���o���#G�p�UW�P�DDDDD�Nc��4���@w�7�A������=��3PPP��f����b���������������Kc��4���@w��������&��w��>���:W_}5g�}6;v��<���o������2>��O������k6m�������i��+_�
�`���7��~�7�x�m��q�p�������2J���z.��r����Q���O~�'?���m��w/[�ne��M|��������.�N'7n���]t{��������m�66o����y���������M�6�i�&~��_��������/|�/����2x����>��O����d��"""""��5�ICDD0�|�I�0�+_���n�:������7������&�0���3���o��x����0���2�����aFoo����g�a�L�����q�E����a��/�l\x���a���;�
6^�7f�JJJ������k��5ZZZ��o����a�������u�]g�a|��_4���.�0c��}��d2^x��Q����2����D~���2�0>��O��sO��'N�w�������{
�0���4���c�a��~��.0�z�-�0����8���b�O���X^cy�D�������|�����?�q6o���c�X�l����fJJJx�����������044�W\��?�i���>���Q\\<�5�y��z�->��G~�����������}��#//o��].�������p�
|���������'��������,��/��">�����z������������������c�}�������H�Mww7���6l`���=z4f[DDDDD&Kcy��EDEw�IOO'###��f�y��inn������W_%//������������������������K.��a�n�:����
���c�/;;���~rrr��>--m��c�����-���7��w������_����=�������f���1�7�>�^�x�	6o�<�o~����*��5�I�p�A�������t�Rz{{���~�����e_������+#�E������k�^/�<�����kq����9x������}����=�z�>�(��m���/��jlll��7�B�7���c��}8�N���Y�d	���g��s'/��2�������#����5�>��}�v���~�� ���;���=���������H"h,����H<��."2�6m��W\��� //�/�������u:DFFk������4��v\p�����O�7��
_����W�����^{-[�l������j�y�6m�4��f�������x��
y��G��7����_���Y�~=��{.6�m���}�Y������$==���������[n��s��d2q�]wQYY9�>����|�k_����`�����'�<���G���"""""������""�H3���F��H�utt���}�_|q�[M�����������l�����-�CCC\r�%��w������4��;��."�@�����o|���vV�^�s�;��?�q�� �a��C�z���G�r�]wi�.""""���""s�2�EDDDDDDDDDD@�������������$��"""""""""""	���?�Z<j��IEND�B`�
#70Melanie Plageman
melanieplageman@gmail.com
In reply to: Heikki Linnakangas (#66)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, Mar 19, 2024 at 02:33:35PM +0200, Heikki Linnakangas wrote:

On 18/03/2024 17:19, Melanie Plageman wrote:

I've attached v7 rebased over this commit.

If we delayed table_beginscan_bm() call further, after starting the TBM
iterator, we could skip it altogether when the iterator is empty.

That's a further improvement, doesn't need to be part of this patch set.
Just caught my eye while reading this.

Hmm. You mean like until after the first call to tbm_[shared]_iterate()?
AFAICT, tbm_begin_iterate() doesn't tell us anything about whether or
not the iterator is "empty". Do you mean cases when the bitmap has no
blocks in it? It seems like we should be able to tell that from the
TIDBitmap.

v7-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patch

I suggest to avoid the double negative with SO_CAN_SKIP_FETCH, and call the
flag e.g. SO_NEED_TUPLE.

Agreed. Done in attached v8. Though I wondered if it was a bit weird
that the flag is set in the common case and not set in the uncommon
case...

As yet another preliminary patch before the streaming read API, it would be
nice to move the prefetching code to heapam.c too.

I've done this, but I can say it is not very pretty. see 0013. I had to
add a bunch of stuff to TableScanDescData and HeapScanDescData which are
only used for bitmapheapscans. I don't know if it makes the BHS
streaming read user patch easier to review, but I don't think what I
have in 0013 is committable to Postgres. Maybe there was another way I
could have approached it. Let me know what you think.

In addition to bloating the table descriptors, note that it was
difficult to avoid one semantic change -- with 0013, we no longer
prefetch or adjust prefetch target when emitting each empty tuple --
though I think this is could actually be desirable.

What's the point of having separate table_scan_bitmap_next_block() and
table_scan_bitmap_next_tuple() functions anymore? The AM owns the TBM
iterator now. The executor node updates the lossy/exact page counts, but
that's the only per-page thing it does now.

Oh, interesting. Good point. I've done this in 0015. If you like the way
it turned out, I can probably rebase this back into an earlier point in
the set and end up dropping some of the other incremental changes (e.g.
0008).

/*
* If this is the first scan of the underlying table, create the table
* scan descriptor and begin the scan.
*/
if (!scan)
{
uint32 extra_flags = 0;

/*
* We can potentially skip fetching heap pages if we do not need
* any columns of the table, either for checking non-indexable
* quals or for returning data. This test is a bit simplistic, as
* it checks the stronger condition that there's no qual or return
* tlist at all. But in most cases it's probably not worth working
* harder than that.
*/
if (node->ss.ps.plan->qual == NIL && node->ss.ps.plan->targetlist == NIL)
extra_flags |= SO_CAN_SKIP_FETCH;

scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
node->ss.ss_currentRelation,
node->ss.ps.state->es_snapshot,
0,
NULL,
extra_flags);
}

scan->tbmiterator = tbmiterator;
scan->shared_tbmiterator = shared_tbmiterator;

How about passing the iterator as an argument to table_beginscan_bm()? You'd
then need some other function to change the iterator on rescan, though. Not
sure what exactly to do here, but feels that this part of the API is not
fully thought-out. Needs comments at least, to explain who sets tbmiterator
/ shared_tbmiterator and when. For comparison, for a TID scan there's a
separate scan_set_tidrange() table AM function. Maybe follow that example
and introduce scan_set_tbm_iterator().

I've spent quite a bit of time playing around with the code trying to
make it less terrible than what I had before.

On rescan, we have to actually make the whole bitmap and iterator. And,
we don't have what we need to do that in table_rescan()/heap_rescan().
From what I can tell, scan_set_tidrange() is useful because it can be
called from both the beginscan and rescan functions without invoking it
directly from TidNext().

In our case, any wrapper function we wrote would basically just assign
the iterator to the scan in BitmapHeapNext().

I've reorganized this code structure a bit, so see if you like it more
now. I rebased the changes into some of the other patches, so you'll
just have to look at the result and see what you think.

It's bit awkward to have separate tbmiterator and shared_tbmiterator fields.
Could regular and shared iterators be merged, or wrapped under a common
interface?

This is a good idea. I've done that in 0014. It made the code nicer, but
I just wonder if it will add too much overhead.

- Melanie

#71Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#70)
17 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Mar 22, 2024 at 08:22:11PM -0400, Melanie Plageman wrote:

On Tue, Mar 19, 2024 at 02:33:35PM +0200, Heikki Linnakangas wrote:

On 18/03/2024 17:19, Melanie Plageman wrote:

I've attached v7 rebased over this commit.

If we delayed table_beginscan_bm() call further, after starting the TBM
iterator, we could skip it altogether when the iterator is empty.

That's a further improvement, doesn't need to be part of this patch set.
Just caught my eye while reading this.

Hmm. You mean like until after the first call to tbm_[shared]_iterate()?
AFAICT, tbm_begin_iterate() doesn't tell us anything about whether or
not the iterator is "empty". Do you mean cases when the bitmap has no
blocks in it? It seems like we should be able to tell that from the
TIDBitmap.

v7-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patch

I suggest to avoid the double negative with SO_CAN_SKIP_FETCH, and call the
flag e.g. SO_NEED_TUPLE.

Agreed. Done in attached v8. Though I wondered if it was a bit weird
that the flag is set in the common case and not set in the uncommon
case...

v8 actually attached this time

Attachments:

v8-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From 5a98d9d714e5fb081c34a3a648fffe7f0893d22d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v8 01/17] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index e57a0b7ea3..e78d793f69 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aab..93fdcd226b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v8-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From b4f1ebf5885202601378007b9df1ca31c73604bf Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v8 02/17] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 93fdcd226b..c64530674b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -742,16 +752,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v8-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-diff; charset=us-asciiDownload
From a353da0564b478d63408c668c246f9ff77ebc3cc Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v8 03/17] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 34bc60f625..e7bed84f75 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -951,6 +951,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1039,6 +1041,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1058,6 +1066,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2b7c702642..7fdccaf613 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2124,6 +2125,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2236,6 +2255,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c64530674b..83d9db8f39 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,11 +185,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	node->ss.ps.state->es_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	extra_flags);
 		}
 
 		node->initialized = true;
@@ -207,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -228,37 +232,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -301,52 +282,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +531,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +601,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +610,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +654,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -740,8 +697,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +707,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f6859..3dfb19ec7d 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 65834caeb1..1bc5f7c057 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -952,9 +959,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 1774c56ae3..6871db9b21 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1785,10 +1785,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1808,9 +1805,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v8-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-diff; charset=us-asciiDownload
From 1c6ac92b28885098809b7ec3a4555dac04d23415 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v8 04/17] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 83d9db8f39..5df3b5ca46 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -474,14 +474,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -532,7 +527,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v8-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-diff; charset=us-asciiDownload
From 7abe75616ad270c2e822cea81221a9069a59384e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v8 05/17] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5df3b5ca46..404de0595e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -230,7 +230,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -341,7 +341,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -360,7 +360,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v8-0006-table_scan_bitmap_next_block-returns-lossy-or-exa.patchtext/x-diff; charset=us-asciiDownload
From 42bd8dc7d3d882464f4c655041e35ff31c171117 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v8 06/17] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7fdccaf613..849cac3947 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,7 +2114,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2242,6 +2243,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 404de0595e..c95e3412da 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
+		bool		valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -232,12 +232,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1bc5f7c057..b9ba4f9fb3 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -804,6 +804,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -819,7 +822,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1988,14 +1992,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2006,7 +2012,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.40.1

v8-0007-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-diff; charset=us-asciiDownload
From 85175100810f3389d0a98e2eaf4cc28e695d8003 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v8 07/17] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c95e3412da..49938c9ed4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +202,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -221,9 +219,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v8-0008-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-diff; charset=us-asciiDownload
From d97d2366e680c1e830c7437f880a59ab04c84d3b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v8 08/17] Remove table_scan_bitmap_next_tuple parameter tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 849cac3947..cf4387f443 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2250,7 +2250,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 49938c9ed4..282dcb9791 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -286,7 +286,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b9ba4f9fb3..bcf1497f67 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -795,10 +795,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -829,15 +826,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2025,7 +2017,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2037,7 +2028,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v8-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 805ddd029fb08f60b84fd4af67ba80f35e2c2cdc Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v8 09/17] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 195 insertions(+), 149 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index cf4387f443..2ad785e511 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,18 +2114,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2144,16 +2177,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2245,7 +2269,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 282dcb9791..7e73583fe5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +109,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +161,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -202,55 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool		valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -272,45 +232,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno > node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,13 +311,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -356,14 +335,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -388,7 +370,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -466,6 +451,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -523,6 +509,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -584,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -597,13 +581,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -634,28 +618,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -688,8 +668,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -697,9 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304a..92b829cebc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index bcf1497f67..a820cc8c99 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -788,19 +789,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -819,8 +815,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -957,9 +953,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1019,6 +1019,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1029,6 +1044,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1981,19 +2011,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2003,8 +2031,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6871db9b21..8688bc5ab0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1783,8 +1783,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1793,9 +1791,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1803,8 +1803,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1813,9 +1811,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v8-0010-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From 8a43b6676dc25c51013a06e3bebe306443a929c1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v8 10/17] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 33 +++++++--------------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 28 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fc..1dc4c99bf9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1463,12 +1449,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	TBMSharedIterator *iterator;
 	TBMSharedIteratorState *istate;
 
-	/*
-	 * Create the TBMSharedIterator struct, with enough trailing space to
-	 * serve the needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639b..432fae5296 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.40.1

v8-0011-table_scan_bitmap_next_block-counts-lossy-and-exa.patchtext/x-diff; charset=us-asciiDownload
From 9d82872fbadf30f1a3b595aa1cd9bd6fac096bee Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 17:09:12 -0400
Subject: [PATCH v8 11/17] table_scan_bitmap_next_block counts lossy and exact
 pages

Now that the table_scan_bitmap_next_block() callback only returns false
when the bitmap is exhausted, it is simpler to move the management of
the lossy and exact page counters into it. We will eventually remove
this callback and table_scan_bitmap_next_tuple() will update those
counters when a new block is read in.
---
 src/backend/access/heap/heapam_handler.c  |  8 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c |  9 ++-------
 src/include/access/tableam.h              | 21 +++++++++++++--------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2ad785e511..266b34fe6b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,7 +2114,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+							  bool *recheck, BlockNumber *blockno,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block;
@@ -2267,7 +2268,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 7e73583fe5..96b55507a3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -69,7 +69,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	bool		lossy;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -267,14 +266,10 @@ new_page:
 
 		BitmapAdjustPrefetchIterator(node);
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+										  &node->lossy_pages, &node->exact_pages))
 			break;
 
-		if (lossy)
-			node->lossy_pages++;
-		else
-			node->exact_pages++;
-
 		/*
 		 * If serial, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a820cc8c99..1d4b79a73f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,8 +797,8 @@ typedef struct TableAmRoutine
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * lossy indicates whether or not the block's representation in the bitmap
-	 * is lossy or exact.
+	 * lossy_pages is incremented if the block's representation in the bitmap
+	 * is lossy, otherwise, exact_pages is incremented.
 	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
@@ -815,8 +815,10 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+										   bool *recheck,
+										   BlockNumber *blockno,
+										   long *lossy_pages,
+										   long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -2013,15 +2015,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap table scan.
  * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy is set to true
- * if bitmap is lossy for the selected block and false otherwise.
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented if bitmap is lossy for the selected block and exact_pages is
+ * incremented otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+							 bool *recheck, BlockNumber *blockno,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2032,7 +2036,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+														   blockno, lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v8-0012-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchtext/x-diff; charset=us-asciiDownload
From c020e4afbdaf94a1783ddc8806be165038238bcb Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v8 12/17] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 38 ++++++------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 7 files changed, 108 insertions(+), 91 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb..3aa457a29e 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544..033d525339 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 266b34fe6b..adfc77684a 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2122,7 +2122,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2135,11 +2135,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		CHECK_FOR_INTERRUPTS();
 
 		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbm_iterate(scan->tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2154,11 +2154,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2166,19 +2166,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2207,7 +2207,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2216,9 +2216,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2268,7 +2268,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 96b55507a3..51c4360205 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -316,7 +316,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,8 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -366,8 +366,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -435,10 +435,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
@@ -446,7 +448,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -455,13 +457,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -476,7 +478,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -495,8 +497,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_shared_iterate(prefetch_iterator);
@@ -504,17 +506,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1dc4c99bf9..309a44bdb8 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae..3b432263bb 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae5296..f000c1af28 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.40.1

v8-0013-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchtext/x-diff; charset=us-asciiDownload
From a654ebbcd43dcc7cdd633c7d60350a58cafd34c2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 09:42:23 -0400
Subject: [PATCH v8 13/17] Push BitmapHeapScan prefetch code into heapam.c

In preparation for transitioning to using the streaming read API for
prefetching [1], move all of the BitmapHeapScanState members related to
prefetching and the functions for accessing them into the
HeapScanDescData and TableScanDescData. Members that still need to be
accessed in BitmapHeapNext() could not be moved into heap AM-specific
code. Specifically, parallel iterator setup requires several components
which seem odd to pass to the table AM API.

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  26 ++
 src/backend/access/heap/heapam_handler.c  | 268 +++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 397 +++-------------------
 src/include/access/heapam.h               |  12 +
 src/include/access/relscan.h              |  11 +
 src/include/access/tableam.h              |  38 ++-
 src/include/nodes/execnodes.h             |  16 -
 7 files changed, 388 insertions(+), 380 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index e7bed84f75..c12563a188 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -951,8 +951,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+
+	scan->rs_base.blockno = InvalidBlockNumber;
+
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
+	scan->pvmbuffer = InvalidBuffer;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1035,6 +1043,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
+	scan->rs_base.blockno = InvalidBlockNumber;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	/*
 	 * unpin scan buffers
 	 */
@@ -1047,6 +1061,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1072,6 +1092,12 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index adfc77684a..efd2784e03 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -55,6 +55,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
+static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2112,6 +2115,76 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+static inline void
+BitmapAdjustPrefetchIterator(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	TBMIterateResult tbmpre;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = scan->rs_base.pf_tbmiterator;
+
+		if (scan->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			scan->prefetch_pages--;
+		}
+		else if (prefetch_iterator)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblockno = tbmpre.blockno;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (scan->rs_base.prefetch_maximum > 0)
+	{
+		TBMSharedIterator *prefetch_iterator = scan->rs_base.pf_shared_tbmiterator;
+
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (prefetch_iterator)
+			{
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblockno = tbmpre.blockno;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  bool *recheck, BlockNumber *blockno,
@@ -2130,6 +2203,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(hscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2273,6 +2348,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->bm_parallel == NULL &&
+		scan->pf_tbmiterator &&
+		hscan->pfblockno > hscan->rs_base.blockno)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(hscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2283,6 +2370,157 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
+		else
+			scan->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = scan->rs_base.pf_tbmiterator;
+
+		if (prefetch_iterator)
+		{
+			while (scan->prefetch_pages < scan->prefetch_target)
+			{
+				TBMIterateResult tbmpre;
+				bool		skip_fetch;
+
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					scan->rs_base.pf_tbmiterator = NULL;
+					break;
+				}
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre.blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		TBMSharedIterator *prefetch_iterator = scan->rs_base.pf_shared_tbmiterator;
+
+		if (prefetch_iterator)
+		{
+			while (1)
+			{
+				TBMIterateResult tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					tbm_end_shared_iterate(prefetch_iterator);
+					scan->rs_base.pf_shared_tbmiterator = NULL;
+					break;
+				}
+
+				scan->pfblockno = tbmpre.blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
@@ -2308,6 +2546,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!scan->bm_parallel)
+	{
+		if (hscan->prefetch_target < scan->prefetch_maximum)
+			hscan->prefetch_target++;
+	}
+	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&scan->bm_parallel->mutex);
+		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+			scan->bm_parallel->prefetch_target++;
+		SpinLockRelease(&scan->bm_parallel->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(hscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 51c4360205..f241f4cb2c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -71,7 +67,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
@@ -91,83 +86,53 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
 	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
 	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
 	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
+
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		int			pf_maximum = 0;
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
+#endif
 
-		if (!pstate)
+		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (init_shared_state)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
 				 * multiple processes to iterate jointly.
 				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
-					pstate->prefetch_iterator =
+					node->pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+				BitmapDoneInitializingSharedState(node->pstate);
 			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -197,8 +162,26 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		scan->prefetch_maximum = pf_maximum;
+		scan->bm_parallel = node->pstate;
+
+		if (!scan->bm_parallel)
+			scan->tbmiterator = tbm_begin_iterate(tbm);
+		else
+			/* Allocate a private iterator and attach the shared state to it */
+			scan->shared_tbmiterator = tbm_attach_shared_iterate(dsa, scan->bm_parallel->tbmiterator);
+
+#ifdef USE_PREFETCH
+		if (scan->prefetch_maximum > 0)
+		{
+			if (!scan->bm_parallel)
+				scan->pf_tbmiterator = tbm_begin_iterate(tbm);
+			else
+				scan->pf_shared_tbmiterator =
+					tbm_attach_shared_iterate(dsa, scan->bm_parallel->prefetch_iterator);
+		}
+#endif							/* USE_PREFETCH */
+
 
 		node->initialized = true;
 
@@ -211,36 +194,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
 
 			/*
 			 * If we are using lossy info, we have to recheck the qual
@@ -264,23 +217,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
-			node->pfblockno > node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -304,224 +243,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
 
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
@@ -569,22 +291,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -625,14 +336,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -665,18 +370,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -716,13 +414,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -806,7 +497,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3dfb19ec7d..22bdccc2a9 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -81,6 +81,18 @@ typedef struct HeapScanDescData
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
+
+	/*
+	 * These fields only used for prefetching in bitmap table scans
+	 */
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block */
+	BlockNumber pfblockno;
 
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc..93168bd350 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -26,6 +26,7 @@ struct ParallelTableScanDescData;
 
 struct TBMIterator;
 struct TBMSharedIterator;
+struct ParallelBitmapHeapState;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -46,6 +47,16 @@ typedef struct TableScanDescData
 	/* Only used for Bitmap table scans */
 	struct TBMIterator *tbmiterator;
 	struct TBMSharedIterator *shared_tbmiterator;
+	/* Prefetch iterators */
+	struct TBMIterator *pf_tbmiterator;
+	struct TBMSharedIterator *pf_shared_tbmiterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+	struct ParallelBitmapHeapState *bm_parallel;
+
+	/* used to validate prefetch and current block stay in sync */
+	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1d4b79a73f..9cab4462d6 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -800,17 +800,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the block's representation in the bitmap
 	 * is lossy, otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -961,6 +950,9 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->shared_tbmiterator = NULL;
 	result->tbmiterator = NULL;
+	result->pf_shared_tbmiterator = NULL;
+	result->pf_tbmiterator = NULL;
+	result->bm_parallel = NULL;
 	return result;
 }
 
@@ -1029,11 +1021,23 @@ table_endscan(TableScanDesc scan)
 			scan->shared_tbmiterator = NULL;
 		}
 
+		if (scan->pf_shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->pf_shared_tbmiterator);
+			scan->pf_shared_tbmiterator = NULL;
+		}
+
 		if (scan->tbmiterator)
 		{
 			tbm_end_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
+
+		if (scan->pf_tbmiterator)
+		{
+			tbm_end_iterate(scan->pf_tbmiterator);
+			scan->pf_tbmiterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1054,11 +1058,23 @@ table_rescan(TableScanDesc scan,
 			scan->shared_tbmiterator = NULL;
 		}
 
+		if (scan->pf_shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->pf_shared_tbmiterator);
+			scan->pf_shared_tbmiterator = NULL;
+		}
+
 		if (scan->tbmiterator)
 		{
 			tbm_end_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
+
+		if (scan->pf_tbmiterator)
+		{
+			tbm_end_iterate(scan->pf_tbmiterator);
+			scan->pf_tbmiterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8688bc5ab0..7a3fdf9cd4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1783,19 +1783,11 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1803,19 +1795,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v8-0014-Unify-parallel-and-serial-BitmapHeapScan-iterator.patchtext/x-diff; charset=us-asciiDownload
From b3dce275a956b109be270a49a0fe3b5adcdf8c10 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 13:43:41 -0400
Subject: [PATCH v8 14/17] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to
both TBMIterator and TBMSharedIterators. This encapsulates the parallel
and serial iterators and their access and makes the bitmap heap scan
code a bit cleaner.
---
 src/backend/access/heap/heapam_handler.c  | 40 ++++++---------
 src/backend/executor/nodeBitmapHeapscan.c | 62 ++++++++++++++++++-----
 src/include/access/relscan.h              | 20 +++++---
 src/include/access/tableam.h              | 61 ++++++----------------
 src/tools/pgindent/typedefs.list          |  1 +
 5 files changed, 96 insertions(+), 88 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index efd2784e03..1a9f7b02d1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -55,6 +55,7 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+
 static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
 static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
 static inline void BitmapPrefetch(HeapScanDesc scan);
@@ -2131,17 +2132,15 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = scan->rs_base.pf_tbmiterator;
-
 		if (scan->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			scan->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (scan->rs_base.rs_pf_tbmiterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
+			bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
 			scan->pfblockno = tbmpre.blockno;
 		}
 		return;
@@ -2154,8 +2153,6 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = scan->rs_base.pf_shared_tbmiterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -2175,9 +2172,9 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (scan->rs_base.rs_pf_tbmiterator)
 			{
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
 				scan->pfblockno = tbmpre.blockno;
 			}
 		}
@@ -2209,10 +2206,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
-		else
-			tbm_iterate(scan->tbmiterator, &tbmres);
+		bhs_iterate(scan->rs_tbmiterator, &tbmres);
 
 		if (!BlockNumberIsValid(tbmres.blockno))
 		{
@@ -2353,7 +2347,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * ahead of the current block.
 	 */
 	if (scan->bm_parallel == NULL &&
-		scan->pf_tbmiterator &&
+		scan->rs_pf_tbmiterator &&
 		hscan->pfblockno > hscan->rs_base.blockno)
 		elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -2427,22 +2421,20 @@ BitmapPrefetch(HeapScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = scan->rs_base.pf_tbmiterator;
-
-		if (prefetch_iterator)
+		if (scan->rs_base.rs_pf_tbmiterator)
 		{
 			while (scan->prefetch_pages < scan->prefetch_target)
 			{
 				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				tbm_iterate(prefetch_iterator, &tbmpre);
+				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
 
 				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					scan->rs_base.pf_tbmiterator = NULL;
+					bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
+					scan->rs_base.rs_pf_tbmiterator = NULL;
 					break;
 				}
 				scan->prefetch_pages++;
@@ -2470,9 +2462,7 @@ BitmapPrefetch(HeapScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = scan->rs_base.pf_shared_tbmiterator;
-
-		if (prefetch_iterator)
+		if (scan->rs_base.rs_pf_tbmiterator)
 		{
 			while (1)
 			{
@@ -2495,12 +2485,12 @@ BitmapPrefetch(HeapScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
 				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					scan->rs_base.pf_shared_tbmiterator = NULL;
+					bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
+					scan->rs_base.rs_pf_tbmiterator = NULL;
 					break;
 				}
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index f241f4cb2c..b548642088 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,6 +52,54 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
+static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
+											 ParallelBitmapHeapState *pstate, dsa_area *personal_area);
+
+BitmapHeapIterator *
+bhs_begin_iterate(TIDBitmap *tbm, ParallelBitmapHeapState *pstate, dsa_area *personal_area)
+{
+	BitmapHeapIterator *result = palloc(sizeof(BitmapHeapIterator));
+
+	result->serial = NULL;
+	result->parallel = NULL;
+
+	if (pstate)
+		result->parallel = tbm_attach_shared_iterate(personal_area, pstate->tbmiterator);
+	else
+		result->serial = tbm_begin_iterate(tbm);
+
+	return result;
+}
+
+void
+bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *tbmres)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		tbm_iterate(iterator->serial, tbmres);
+	else
+		tbm_shared_iterate(iterator->parallel, tbmres);
+}
+
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+	{
+		tbm_end_iterate(iterator->serial);
+		iterator->serial = NULL;
+	}
+	else
+	{
+		tbm_end_shared_iterate(iterator->parallel);
+		iterator->parallel = NULL;
+	}
+
+	pfree(iterator);
+}
 
 
 /* ----------------------------------------------------------------
@@ -165,21 +213,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
-		if (!scan->bm_parallel)
-			scan->tbmiterator = tbm_begin_iterate(tbm);
-		else
-			/* Allocate a private iterator and attach the shared state to it */
-			scan->shared_tbmiterator = tbm_attach_shared_iterate(dsa, scan->bm_parallel->tbmiterator);
+		scan->rs_tbmiterator = bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
 
 #ifdef USE_PREFETCH
 		if (scan->prefetch_maximum > 0)
-		{
-			if (!scan->bm_parallel)
-				scan->pf_tbmiterator = tbm_begin_iterate(tbm);
-			else
-				scan->pf_shared_tbmiterator =
-					tbm_attach_shared_iterate(dsa, scan->bm_parallel->prefetch_iterator);
-		}
+			bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
 #endif							/* USE_PREFETCH */
 
 
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 93168bd350..65092d7226 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -27,6 +27,17 @@ struct ParallelTableScanDescData;
 struct TBMIterator;
 struct TBMSharedIterator;
 struct ParallelBitmapHeapState;
+struct TBMIterateResult;
+
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+} BitmapHeapIterator;
+
+extern void bhs_iterate(BitmapHeapIterator *tbmiterator, struct TBMIterateResult *tbmres);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -45,12 +56,9 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
-	/* Prefetch iterators */
-	struct TBMIterator *pf_tbmiterator;
-	struct TBMSharedIterator *pf_shared_tbmiterator;
-
+	BitmapHeapIterator *rs_tbmiterator;
+	/* Prefetch iterator */
+	BitmapHeapIterator *rs_pf_tbmiterator;
 	/* maximum value for prefetch_target */
 	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9cab4462d6..2ded1a124b 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -948,10 +948,8 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	result->pf_shared_tbmiterator = NULL;
-	result->pf_tbmiterator = NULL;
+	result->rs_tbmiterator = NULL;
+	result->rs_pf_tbmiterator = NULL;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -1015,29 +1013,15 @@ table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
+		bhs_end_iterate(scan->rs_tbmiterator);
+		scan->rs_tbmiterator = NULL;
+#ifdef USE_PREFETCH
+		if (scan->rs_pf_tbmiterator)
 		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->pf_shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->pf_shared_tbmiterator);
-			scan->pf_shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-
-		if (scan->pf_tbmiterator)
-		{
-			tbm_end_iterate(scan->pf_tbmiterator);
-			scan->pf_tbmiterator = NULL;
+			bhs_end_iterate(scan->rs_pf_tbmiterator);
+			scan->rs_pf_tbmiterator = NULL;
 		}
+#endif
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1052,29 +1036,16 @@ table_rescan(TableScanDesc scan,
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->pf_shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->pf_shared_tbmiterator);
-			scan->pf_shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_tbmiterator);
+		scan->rs_tbmiterator = NULL;
 
-		if (scan->pf_tbmiterator)
+#ifdef USE_PREFETCH
+		if (scan->rs_pf_tbmiterator)
 		{
-			tbm_end_iterate(scan->pf_tbmiterator);
-			scan->pf_tbmiterator = NULL;
+			bhs_end_iterate(scan->rs_pf_tbmiterator);
+			scan->rs_pf_tbmiterator = NULL;
 		}
+#endif
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index e2a0525dd4..58317eac44 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.40.1

v8-0015-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From e92e2f2f2925bdf79d5fd8a28021ce5b62d2ce06 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 15:43:10 -0400
Subject: [PATCH v8 15/17] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block(). Heap AM's implementation of
table_scan_bitmap_next_tuple() now calls the original
heapam_scan_bitmap_next_block() function, but it is no longer an
implementation of a table AM callback but instead a helper for
heapam_scan_bitmap_next_tuple()
---
 src/backend/access/heap/heapam_handler.c  | 48 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 45 ++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 75 +++++------------------
 5 files changed, 61 insertions(+), 111 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 1a9f7b02d1..9dfc99d8fa 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2110,12 +2110,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
- */
-
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
  *
@@ -2148,8 +2142,8 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
@@ -2511,30 +2505,43 @@ BitmapPrefetch(HeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
-		return true;
-	}
+		if (hscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			hscan->rs_empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2916,7 +2923,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index ce637a5a5d..1d6b03d1ca 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b548642088..2683d8bc0c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -222,44 +222,35 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 
 		node->initialized = true;
-
-		goto new_page;
 	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346..cf56cc572f 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2ded1a124b..5ad3eff539 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -788,36 +788,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the block's representation in the bitmap
-	 * is lossy, otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   BlockNumber *blockno,
-										   long *lossy_pages,
-										   long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -2000,44 +1984,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented if bitmap is lossy for the selected block and exact_pages is
- * incremented otherwise.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno,
-							 long *lossy_pages, long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   blockno, lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2048,7 +2001,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v8-0016-v7-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From d1a23704e59b3a12e3e9b2028b4eaa0147059aeb Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:59:42 -0400
Subject: [PATCH v8 16/17] v7 Streaming Read API

---
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 659 +++++++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 642 +++++++++++++++-------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/include/storage/bufmgr.h             |  45 ++
 src/include/storage/streaming_read.h     |  52 ++
 src/tools/pgindent/typedefs.list         |   3 +
 10 files changed, 1227 insertions(+), 210 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca2..eec03f6f2b 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 0000000000..bcab44c802
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 0000000000..39aef2a84a
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 0000000000..d5c29b750d
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,659 @@
+#include "postgres.h"
+
+#include "catalog/pg_tablespace.h"
+#include "miscadmin.h"
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+#include "utils/spccache.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		need_wait;
+	bool		advice_issued;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index;
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+	ReadBuffersOperation operation;
+} PgStreamingReadRange;
+
+/*
+ * Streaming read object.
+ */
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			next_tail_buffer;
+	int			distance;
+	bool		started;
+	bool		finished;
+	bool		advice_enabled;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	/* Sometimes we need to buffer one block for flow control. */
+	BlockNumber unget_blocknum;
+	void	   *unget_per_buffer_data;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+	Oid			tablespace_id;
+
+	/*
+	 * Make sure our bmr's smgr and persistent are populated.  The caller
+	 * asserts that the storage manager will remain valid.
+	 */
+	if (!bmr.smgr)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	tablespace_id = bmr.smgr->smgr_rlocator.locator.spcOid;
+	if (!OidIsValid(MyDatabaseId) ||
+		(bmr.rel && IsCatalogRelation(bmr.rel)) ||
+		IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
+	{
+		/*
+		 * Avoid circularity while trying to look up tablespace settings or
+		 * before spccache.c is ready.
+		 */
+		max_ios = effective_io_concurrency;
+	}
+	else if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
+	else
+		max_ios = get_tablespace_io_concurrency(tablespace_id);
+
+	/*
+	 * Choose a maximum number of buffers we're prepared to pin.  We try to
+	 * pin fewer if we can, though.  We clamp it to at least
+	 * MAX_BUFFER_PER_TRANSFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/* Don't allow this backend to pin more than its share of buffers. */
+	if (SmgrIsTemp(bmr.smgr))
+		LimitAdditionalLocalPins(&max_pinned_buffers);
+	else
+		LimitAdditionalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+	pgsr->callback = next_block_cb;
+	pgsr->bmr = bmr;
+	pgsr->forknum = forknum;
+
+	pgsr->unget_blocknum = InvalidBlockNumber;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * Skip the initial ramp-up phase if the caller says we're going to be
+	 * reading the whole relation.  This way we start out doing full-sized
+	 * reads.
+	 */
+	if (flags & PGSR_FLAG_FULL)
+		pgsr->distance = Min(MAX_BUFFERS_PER_TRANSFER, pgsr->max_pinned_buffers);
+	else
+		pgsr->distance = 1;
+
+	/*
+	 * Space for the callback to store extra data along with each block.  Note
+	 * that we need one more than max_pinned_buffers, so we can return a
+	 * pointer to a slot that can't be overwritten until the next call.
+	 */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * size);
+
+	return pgsr;
+}
+
+/*
+ * Find the per-buffer data index for the Nth block of a range.
+ */
+static int
+get_per_buffer_data_index(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	int			result;
+
+	/*
+	 * Find slot in the circular buffer of per-buffer data, without using the
+	 * expensive % operator.
+	 */
+	result = range->per_buffer_data_index + n;
+	while (result >= pgsr->size)
+		result -= pgsr->size;
+	Assert(result == (range->per_buffer_data_index + n) % pgsr->size);
+
+	return result;
+}
+
+/*
+ * Return a pointer to the per-buffer data by index.
+ */
+static void *
+get_per_buffer_data_by_index(PgStreamingRead *pgsr, int per_buffer_data_index)
+{
+	return (char *) pgsr->per_buffer_data +
+		pgsr->per_buffer_data_size * per_buffer_data_index;
+}
+
+/*
+ * Return a pointer to the per-buffer data for the Nth block of a range.
+ */
+static void *
+get_per_buffer_data(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	return get_per_buffer_data_by_index(pgsr,
+										get_per_buffer_data_index(pgsr,
+																  range,
+																  n));
+}
+
+/*
+ * Start reading the head range, and create a new head range.  The new head
+ * range is returned.  It may not be empty, if StartReadBuffers() couldn't
+ * start the entire range; in that case the returned range contains the
+ * remaining portion of the range.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_start_head_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+	PgStreamingReadRange *new_head_range;
+	int			nblocks_pinned;
+	int			flags;
+
+	/* Caller should make sure we never exceed max_ios. */
+	Assert((pgsr->ios_in_progress < pgsr->max_ios) ||
+		   (pgsr->ios_in_progress == 0 && pgsr->max_ios == 0));
+
+	/* Should only call if the head range has some blocks to read. */
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If advice hasn't been suppressed, and this system supports it, this
+	 * isn't a strictly sequential pattern, then we'll issue advice.
+	 */
+	if (pgsr->advice_enabled &&
+		pgsr->max_ios > 0 &&
+		pgsr->started &&
+		head_range->blocknum != pgsr->seq_blocknum)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else
+		flags = 0;
+
+	/* Suppress advice on the first call, because it's too late to benefit. */
+	if (!pgsr->started)
+		pgsr->started = true;
+
+	/* We shouldn't be trying to pin more buffers that we're allowed to. */
+	Assert(pgsr->pinned_buffers + head_range->nblocks <= pgsr->max_pinned_buffers);
+
+	/* Start reading as many blocks as we can from the head range. */
+	nblocks_pinned = head_range->nblocks;
+	head_range->need_wait =
+		StartReadBuffers(pgsr->bmr,
+						 head_range->buffers,
+						 pgsr->forknum,
+						 head_range->blocknum,
+						 &nblocks_pinned,
+						 pgsr->strategy,
+						 flags,
+						 &head_range->operation);
+
+	Assert(pgsr->pinned_buffers <= pgsr->max_pinned_buffers);
+
+	if (head_range->need_wait && (flags & READ_BUFFERS_ISSUE_ADVICE))
+	{
+		/*
+		 * Since we've issued advice, we count an I/O in progress until we
+		 * call WaitReadBuffers().
+		 */
+		head_range->advice_issued = true;
+		pgsr->ios_in_progress++;
+		Assert(pgsr->ios_in_progress <= pgsr->max_ios);
+	}
+
+	/*
+	 * StartReadBuffers() might have pinned fewer blocks than we asked it to,
+	 * but always at least one.
+	 */
+	Assert(nblocks_pinned <= head_range->nblocks);
+	Assert(nblocks_pinned >= 1);
+	pgsr->pinned_buffers += nblocks_pinned;
+
+	/*
+	 * Remember where the next block would be after that, so we can detect
+	 * sequential access next time.
+	 */
+	pgsr->seq_blocknum = head_range->blocknum + nblocks_pinned;
+
+	/*
+	 * Create a new head range.  There must be space, because we have enough
+	 * elements for every range to hold just one block, up to the pin limit.
+	 */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	new_head_range = &pgsr->ranges[pgsr->head];
+	new_head_range->nblocks = 0;
+	new_head_range->advice_issued = false;
+
+	/*
+	 * If we didn't manage to start the whole read above, we split the range,
+	 * moving the remainder into the new head range.
+	 */
+	if (nblocks_pinned < head_range->nblocks)
+	{
+		int			nblocks_remaining = head_range->nblocks - nblocks_pinned;
+
+		head_range->nblocks = nblocks_pinned;
+
+		new_head_range->blocknum = head_range->blocknum + nblocks_pinned;
+		new_head_range->nblocks = nblocks_remaining;
+	}
+
+	/* The new range has per-buffer data starting after the previous range. */
+	new_head_range->per_buffer_data_index =
+		get_per_buffer_data_index(pgsr, head_range, nblocks_pinned);
+
+	return new_head_range;
+}
+
+/*
+ * Ask the callback which block it would like us to read next, with a small
+ * buffer in front to allow pg_streaming_unget_block() to work.
+ */
+static BlockNumber
+pg_streaming_get_block(PgStreamingRead *pgsr, void *per_buffer_data)
+{
+	BlockNumber result;
+
+	if (unlikely(pgsr->unget_blocknum != InvalidBlockNumber))
+	{
+		/*
+		 * If we had to unget a block, now it is time to return that one
+		 * again.
+		 */
+		result = pgsr->unget_blocknum;
+		pgsr->unget_blocknum = InvalidBlockNumber;
+
+		/*
+		 * The same per_buffer_data element must have been used, and still
+		 * contains whatever data the callback wrote into it.  So we just
+		 * sanity-check that we were called with the value that
+		 * pg_streaming_unget_block() pushed back.
+		 */
+		Assert(per_buffer_data == pgsr->unget_per_buffer_data);
+	}
+	else
+	{
+		/* Use the installed callback directly. */
+		result = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+	}
+
+	return result;
+}
+
+/*
+ * In order to deal with short reads in StartReadBuffers(), we sometimes need
+ * to defer handling of a block until later.  This *must* be called with the
+ * last value returned by pg_streaming_get_block().
+ */
+static void
+pg_streaming_unget_block(PgStreamingRead *pgsr, BlockNumber blocknum, void *per_buffer_data)
+{
+	Assert(pgsr->unget_blocknum == InvalidBlockNumber);
+	pgsr->unget_blocknum = blocknum;
+	pgsr->unget_per_buffer_data = per_buffer_data;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *range;
+
+	/* If we're finished, don't look ahead. */
+	if (pgsr->finished)
+		return;
+
+	/*
+	 * We we've already started the maximum allowed number of I/Os, don't look
+	 * ahead.  There is a special case for max_ios == 0.
+	 */
+	if (pgsr->max_ios > 0 && pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/* Can't pin any more buffers. */
+	if (pgsr->pinned_buffers == pgsr->distance)
+		return;
+
+	/*
+	 * Keep trying to add new blocks to the end of the head range while doing
+	 * so wouldn't exceed the distance limit.
+	 */
+	range = &pgsr->ranges[pgsr->head];
+	while (pgsr->pinned_buffers + range->nblocks < pgsr->distance)
+	{
+		BlockNumber blocknum;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		if (range->nblocks == lengthof(range->buffers))
+		{
+			/* Start as much of it as we can. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/* If we're now at the I/O limit, stop here. */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+				return;
+
+			/*
+			 * That might have only been partially started, but always
+			 * processes at least one so that'll do for now.
+			 */
+			Assert(range->nblocks < lengthof(range->buffers));
+		}
+
+		/* Find per-buffer data slot for the next block. */
+		per_buffer_data = get_per_buffer_data(pgsr, range, range->nblocks);
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pg_streaming_get_block(pgsr, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			/* End of stream. */
+			pgsr->finished = true;
+			break;
+		}
+
+		/*
+		 * Is there a head range that we cannot extend, because the requested
+		 * block is not consecutive?
+		 */
+		if (range->nblocks > 0 &&
+			range->blocknum + range->nblocks != blocknum)
+		{
+			/* Yes.  Start it, so we can begin building a new one. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * It's possible that it was only partially started, and we have a
+			 * new range with the remainder.  Keep starting I/Os until we get
+			 * it all out of the way, or we hit the I/O limit.
+			 */
+			while (range->nblocks > 0 && pgsr->ios_in_progress < pgsr->max_ios)
+				range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * We do have to worry about I/O capacity running out if the head
+			 * range was split.  In that case we have to 'unget' the block
+			 * returned by the callback.
+			 */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+			{
+				pg_streaming_unget_block(pgsr, blocknum, per_buffer_data);
+				return;
+			}
+		}
+
+		/* If we have a new, empty range, initialize the start block. */
+		if (range->nblocks == 0)
+			range->blocknum = blocknum;
+
+		/* This block extends the range by one. */
+		Assert(range->blocknum + range->nblocks == blocknum);
+		range->nblocks++;
+	};
+
+	/*
+	 * Normally we don't start the head range, preferring to give it a chance
+	 * to grow to full size once more buffers have been consumed.  In cases
+	 * where that can't possibly happen, we might as well start the read
+	 * immediately.
+	 */
+	if ((range->nblocks > 0 && pgsr->finished) ||
+		(range->nblocks == pgsr->distance))
+		pg_streaming_read_start_head_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	PgStreamingReadRange *tail_range;
+
+	for (;;)
+	{
+		if (pgsr->tail != pgsr->head)
+		{
+			tail_range = &pgsr->ranges[pgsr->tail];
+
+			/*
+			 * Do we need to wait for a ReadBuffers operation to finish before
+			 * returning the buffers in this range?
+			 */
+			if (tail_range->need_wait)
+			{
+				int			distance;
+
+				Assert(pgsr->next_tail_buffer == 0);
+				WaitReadBuffers(&tail_range->operation);
+				tail_range->need_wait = false;
+
+				/*
+				 * We don't really know if the kernel generated a physical I/O
+				 * when we issued advice, let alone when it finished, but it
+				 * has certainly finished now because we've performed the
+				 * read.
+				 */
+				if (tail_range->advice_issued)
+				{
+
+					Assert(pgsr->ios_in_progress > 0);
+					pgsr->ios_in_progress--;
+
+					/*
+					 * Look-ahead distance ramps up rapidly if we're issuing
+					 * advice, so we can search for new more I/Os to start.
+					 */
+					distance = pgsr->distance * 2;
+					distance = Min(distance, pgsr->max_pinned_buffers);
+					pgsr->distance = distance;
+				}
+				else
+				{
+					/*
+					 * There is no point in increasing look-ahead distance if
+					 * we've already reached the full I/O size, since we're
+					 * not issuing advice.  Extra distance would only pin more
+					 * buffers for no benefit.
+					 */
+					if (pgsr->distance > MAX_BUFFERS_PER_TRANSFER)
+					{
+						/*
+						 * Look-ahead distance gradually decays to full I/O
+						 * size.
+						 */
+						pgsr->distance--;
+					}
+					else
+					{
+						/*
+						 * Look-ahead distance ramps up rapidly, but not more
+						 * that the full I/O size.
+						 */
+						distance = pgsr->distance * 2;
+						distance = Min(distance, MAX_BUFFERS_PER_TRANSFER);
+						distance = Min(distance, pgsr->max_pinned_buffers);
+						pgsr->distance = distance;
+					}
+				}
+			}
+			else if (pgsr->next_tail_buffer == 0)
+			{
+				/* No I/O necessary. Look-ahead distance gradually decays. */
+				if (pgsr->distance > 1)
+					pgsr->distance--;
+			}
+
+			/* Are there more buffers available in this range? */
+			if (pgsr->next_tail_buffer < tail_range->nblocks)
+			{
+				int			buffer_index;
+				Buffer		buffer;
+
+				buffer_index = pgsr->next_tail_buffer++;
+				buffer = tail_range->buffers[buffer_index];
+
+				Assert(BufferIsValid(buffer));
+
+				/* We are giving away ownership of this pinned buffer. */
+				Assert(pgsr->pinned_buffers > 0);
+				pgsr->pinned_buffers--;
+
+				if (per_buffer_data)
+					*per_buffer_data = get_per_buffer_data(pgsr, tail_range, buffer_index);
+
+				/* We may be able to get another I/O started. */
+				pg_streaming_read_look_ahead(pgsr);
+
+				return buffer;
+			}
+
+			/* Advance tail to next range. */
+			if (++pgsr->tail == pgsr->size)
+				pgsr->tail = 0;
+			pgsr->next_tail_buffer = 0;
+		}
+		else
+		{
+			/*
+			 * If tail crashed into head, and head is not empty, then it is
+			 * time to start that range.  Otherwise, force a look-ahead, to
+			 * kick start the stream.
+			 */
+			Assert(pgsr->tail == pgsr->head);
+			if (pgsr->ranges[pgsr->head].nblocks > 0)
+			{
+				pg_streaming_read_start_head_range(pgsr);
+			}
+			else
+			{
+				pg_streaming_read_look_ahead(pgsr);
+
+				/* Finished? */
+				if (pgsr->tail == pgsr->head &&
+					pgsr->ranges[pgsr->head].nblocks == 0)
+					break;
+			}
+		}
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead. */
+	pgsr->finished = true;
+
+	/* Unpin anything that wasn't consumed. */
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	Assert(pgsr->pinned_buffers == 0);
+	Assert(pgsr->ios_in_progress == 0);
+
+	/* Release memory. */
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f0f8d4259c..d0e9c7deff 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -19,6 +19,11 @@
  *		and pin it so that no one can destroy it while this process
  *		is using it.
  *
+ * StartReadBuffers() -- as above, but for multiple contiguous blocks in
+ *		two steps.
+ *
+ * WaitReadBuffers() -- second step of StartReadBuffers().
+ *
  * ReleaseBuffer() -- unpin a buffer
  *
  * MarkBufferDirty() -- mark a pinned buffer's contents as "dirty".
@@ -471,10 +476,9 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
-								ReadBufferMode mode, BufferAccessStrategy strategy,
-								bool *hit);
+								ReadBufferMode mode, BufferAccessStrategy strategy);
 static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
 										   ForkNumber fork,
 										   BufferAccessStrategy strategy,
@@ -500,7 +504,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -781,7 +785,6 @@ Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
-	bool		hit;
 	Buffer		buf;
 
 	/*
@@ -794,15 +797,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
-							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+	buf = ReadBuffer_common(BMR_REL(reln),
+							forkNum, blockNum, mode, strategy);
+
 	return buf;
 }
 
@@ -822,13 +819,12 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 						  BlockNumber blockNum, ReadBufferMode mode,
 						  BufferAccessStrategy strategy, bool permanent)
 {
-	bool		hit;
-
 	SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
-							 mode, strategy, &hit);
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
+							 mode, strategy);
 }
 
 /*
@@ -994,35 +990,68 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 	 */
 	if (buffer == InvalidBuffer)
 	{
-		bool		hit;
-
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
-								   fork, extend_to - 1, mode, strategy,
-								   &hit);
+		buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
 	}
 
 	return buffer;
 }
 
+/*
+ * Zero a buffer and lock it, as part of the implementation of
+ * RBM_ZERO_AND_LOCK or RBM_ZERO_AND_CLEANUP_LOCK.  The buffer must be already
+ * pinned.  It does not have to be valid, but it is valid and locked on
+ * return.
+ */
+static void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * ReadBuffer_common -- common logic for all ReadBuffer variants
  *
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
-				  BufferAccessStrategy strategy, bool *hit)
+				  BufferAccessStrategy strategy)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	ReadBuffersOperation operation;
+	Buffer		buffer;
+	int			nblocks;
+	int			flags;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1041,181 +1070,405 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	nblocks = 1;
+	if (mode == RBM_ZERO_ON_ERROR)
+		flags = READ_BUFFERS_ZERO_ON_ERROR;
+	else
+		flags = 0;
+	if (StartReadBuffers(bmr,
+						 &buffer,
+						 forkNum,
+						 blockNum,
+						 &nblocks,
+						 strategy,
+						 flags,
+						 &operation))
+		WaitReadBuffers(&operation);
+	Assert(nblocks == 1);		/* single block can't be short */
+
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+		ZeroBuffer(buffer, mode);
+
+	return buffer;
+}
 
+static Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	Assert(bmr.smgr);
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * WaitReadBuffers() (so, not for hits, and not for buffers that are
+		 * zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+/*
+ * Begin reading a range of blocks beginning at blockNum and extending for
+ * *nblocks.  On return, up to *nblocks pinned buffers holding those blocks
+ * are written into the buffers array, and *nblocks is updated to contain the
+ * actual number, which may be fewer than requested.
+ *
+ * If false is returned, no I/O is necessary and WaitReadBuffers() is not
+ * necessary.  If true is returned, one I/O has been started, and
+ * WaitReadBuffers() must be called with the same operation object before the
+ * buffers are accessed.  Along with the operation object, the caller-supplied
+ * array of buffers must remain valid until WaitReadBuffers() is called.
+ *
+ * Currently the I/O is only started with optional operating system advice,
+ * and the real I/O happens in WaitReadBuffers().  In future work, true I/O
+ * could be initiated here.
+ */
+bool
+StartReadBuffers(BufferManagerRelation bmr,
+				 Buffer *buffers,
+				 ForkNumber forkNum,
+				 BlockNumber blockNum,
+				 int *nblocks,
+				 BufferAccessStrategy strategy,
+				 int flags,
+				 ReadBuffersOperation *operation)
+{
+	int			actual_nblocks = *nblocks;
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
 	}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+	operation->bmr = bmr;
+	operation->forknum = forkNum;
+	operation->blocknum = blockNum;
+	operation->buffers = buffers;
+	operation->nblocks = actual_nblocks;
+	operation->strategy = strategy;
+	operation->flags = flags;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	operation->io_buffers_len = 0;
 
-	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
-	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
-	else
+	for (int i = 0; i < actual_nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		bool		found;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+		buffers[i] = PrepareReadBuffer(bmr,
+									   forkNum,
+									   blockNum + i,
+									   strategy,
+									   &found);
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		if (found)
+		{
+			/*
+			 * Terminate the read as soon as we get a hit.  It could be a
+			 * single buffer hit, or it could be a hit that follows a readable
+			 * range.  We don't want to create more than one readable range,
+			 * so we stop here.
+			 */
+			actual_nblocks = operation->nblocks = *nblocks = i + 1;
+			break;
+		}
+		else
+		{
+			/* Extend the readable range to cover this block. */
+			operation->io_buffers_len++;
+		}
+	}
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+	if (operation->io_buffers_len > 0)
+	{
+		if (flags & READ_BUFFERS_ISSUE_ADVICE)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
-			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
-			}
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
+			/*
+			 * In theory we should only do this if PrepareReadBuffers() had to
+			 * allocate new buffers above.  That way, if two calls to
+			 * StartReadBuffers() were made for the same blocks before
+			 * WaitReadBuffers(), only the first would issue the advice.
+			 * That'd be a better simulation of true asynchronous I/O, which
+			 * would only start the I/O once, but isn't done here for
+			 * simplicity.  Note also that the following call might actually
+			 * issue two advice calls if we cross a segment boundary; in a
+			 * true asynchronous version we might choose to process only one
+			 * real I/O at a time in that case.
+			 */
+			smgrprefetch(bmr.smgr, forkNum, blockNum, operation->io_buffers_len);
 		}
+
+		/* Indicate that WaitReadBuffers() should be called. */
+		return true;
 	}
+	else
+	{
+		return false;
+	}
+}
 
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
+static inline bool
+WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
 	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
+
+void
+WaitReadBuffers(ReadBuffersOperation *operation)
+{
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	int			nblocks;
+	BlockNumber blocknum;
+	ForkNumber	forknum;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	/*
+	 * Currently operations are only allowed to include a read of some range,
+	 * with an optional extra buffer that is already pinned at the end.  So
+	 * nblocks can be at most one more than io_buffers_len.
+	 */
+	Assert((operation->nblocks == operation->io_buffers_len) ||
+		   (operation->nblocks == operation->io_buffers_len + 1));
 
+	/* Find the range of the physical read we need to perform. */
+	nblocks = operation->io_buffers_len;
+	if (nblocks == 0)
+		return;					/* nothing to do */
+
+	buffers = &operation->buffers[0];
+	blocknum = operation->blocknum;
+	forknum = operation->forknum;
+	bmr = operation->bmr;
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
-
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
 	}
 	else
 	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
+		io_context = IOContextForStrategy(operation->strategy);
+		io_object = IOOBJECT_RELATION;
 	}
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+	/*
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
+	 */
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
+	else
+		pgBufferUsage.shared_blks_read += nblocks;
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+	for (int i = 0; i < nblocks; ++i)
+	{
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!WaitReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
+
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   WaitReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
+		{
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
+			{
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
+			}
+			else
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
+
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
+
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
+
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
+
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
- * BufferAlloc -- subroutine for ReadBuffer.  Handles lookup of a shared
- *		buffer.  If no buffer exists already, selects a replacement
- *		victim and evicts the old page, but does NOT read in new page.
+ * BufferAlloc -- subroutine for StartReadBuffers.  Handles lookup of a shared
+ *		buffer.  If no buffer exists already, selects a replacement victim and
+ *		evicts the old page, but does NOT read in new page.
  *
  * "strategy" can be a buffer replacement strategy object, or NULL for
  * the default strategy.  The selected buffer's usage_count is advanced when
@@ -1223,11 +1476,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1286,19 +1535,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1363,19 +1603,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1407,15 +1638,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1769,7 +1994,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2034,7 +2259,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2057,7 +2282,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2372,7 +2597,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if StartReadBuffers() was called and
+		 * WaitReadBuffers() hasn't been called yet.  We'll check by loading
+		 * the flags without locking.  This is racy, but it's OK to return
+		 * false spuriously: when WaitReadBuffers() calls StartBufferIO(),
+		 * it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2381,7 +2611,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3449,7 +3679,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -5184,9 +5414,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5199,6 +5435,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index fcfac335a5..985a2c7049 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -108,10 +108,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -287,7 +286,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -297,9 +296,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca2..739d13293f 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d335..b57f71f97e 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,42 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+
+#define READ_BUFFERS_ZERO_ON_ERROR 0x01
+#define READ_BUFFERS_ISSUE_ADVICE 0x02
+
+/*
+ * Private state used by StartReadBuffers() and WaitReadBuffers().  Declared
+ * in public header only to allow inclusion in other structs, but contents
+ * should not be accessed.
+ */
+struct ReadBuffersOperation
+{
+	/* Parameters passed in to StartReadBuffers(). */
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	ForkNumber	forknum;
+	BlockNumber blocknum;
+	int			nblocks;
+	BufferAccessStrategy strategy;
+	int			flags;
+
+	/* Range of buffers, if we need to perform a read. */
+	int			io_buffers_len;
+};
+
+typedef struct ReadBuffersOperation ReadBuffersOperation;
+
+extern bool StartReadBuffers(BufferManagerRelation bmr,
+							 Buffer *buffers,
+							 ForkNumber forknum,
+							 BlockNumber blocknum,
+							 int *nblocks,
+							 BufferAccessStrategy strategy,
+							 int flags,
+							 ReadBuffersOperation *operation);
+extern void WaitReadBuffers(ReadBuffersOperation *operation);
+
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -250,6 +292,9 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 0000000000..c4d3892bb2
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,52 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+/*
+ * We usually ramp up from smaller reads to larger ones, to support users who
+ * don't know if it's worth reading lots of buffers yet.  This flag disables
+ * that, declaring ahead of time that we'll be reading all available buffers.
+ */
+#define PGSR_FLAG_FULL 0x04
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 58317eac44..162fe9300a 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2116,6 +2116,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
@@ -2287,6 +2289,7 @@ ReInitializeDSMForeignScan_function
 ReScanForeignScan_function
 ReadBufPtrType
 ReadBufferMode
+ReadBuffersOperation
 ReadBytePtrType
 ReadExtraTocPtrType
 ReadFunc
-- 
2.40.1

v8-0017-BitmapHeapScan-uses-streaming-read-API.patchtext/x-diff; charset=us-asciiDownload
From 830584b381e185e824350c2750ddfd7b7f091d41 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 16:51:40 -0400
Subject: [PATCH v8 17/17] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  96 ++++--
 src/backend/access/heap/heapam_handler.c  | 346 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  44 +--
 src/include/access/heapam.h               |  16 +-
 src/include/access/relscan.h              |   7 -
 src/include/access/tableam.h              |  16 -
 src/include/nodes/execnodes.h             |   9 +-
 7 files changed, 116 insertions(+), 418 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index c12563a188..1beb0bb99b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -111,6 +111,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -331,6 +333,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -951,16 +969,9 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-
-	scan->rs_base.blockno = InvalidBlockNumber;
-
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
-	scan->pvmbuffer = InvalidBuffer;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1043,12 +1054,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
-	scan->rs_base.blockno = InvalidBlockNumber;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
-
 	/*
 	 * unpin scan buffers
 	 */
@@ -1061,12 +1066,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1092,12 +1091,6 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
@@ -1115,6 +1108,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10272,3 +10268,51 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		bhs_iterate(hdesc->rs_base.rs_tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(hdesc->rs_base.rs_flags & SO_NEED_TUPLE) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 9dfc99d8fa..fe9ee5976f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,10 +56,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
-static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
-static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
-static inline void BitmapPrefetch(HeapScanDesc scan);
-
 static const TableAmRoutine heapam_methods;
 
 
@@ -2110,146 +2106,68 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (scan->rs_base.rs_pf_tbmiterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-			scan->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
-	 * parallel workers.
-	 */
-	if (scan->rs_base.prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (scan->rs_base.rs_pf_tbmiterator)
-			{
-				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-				scan->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno,
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(hscan);
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		bhs_iterate(scan->rs_tbmiterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2270,7 +2188,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,9 +2197,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2331,23 +2249,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->bm_parallel == NULL &&
-		scan->rs_pf_tbmiterator &&
-		hscan->pfblockno > hscan->rs_base.blockno)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(hscan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2358,152 +2264,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= prefetch_maximum / 2)
-			scan->prefetch_target = prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= prefetch_maximum / 2)
-			pstate->prefetch_target = prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-
-	if (pstate == NULL)
-	{
-		if (scan->rs_base.rs_pf_tbmiterator)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
-					scan->rs_base.rs_pf_tbmiterator = NULL;
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (scan->rs_base.rs_pf_tbmiterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
-					scan->rs_base.rs_pf_tbmiterator = NULL;
-					break;
-				}
-
-				scan->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
@@ -2538,41 +2298,11 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 			return true;
 		}
 
-		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
 										   lossy_pages, exact_pages))
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!scan->bm_parallel)
-	{
-		if (hscan->prefetch_target < scan->prefetch_maximum)
-			hscan->prefetch_target++;
-	}
-	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&scan->bm_parallel->mutex);
-		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-			scan->bm_parallel->prefetch_target++;
-		SpinLockRelease(&scan->bm_parallel->mutex);
-	}
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(hscan);
-#endif							/* USE_PREFETCH */
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2683d8bc0c..c21dae466a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -128,14 +128,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -146,15 +138,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-		int			pf_maximum = 0;
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
-#endif
-
 		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -171,13 +154,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					node->pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
+
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(node->pstate);
 			}
@@ -210,17 +187,10 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
 		scan->rs_tbmiterator = bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
 
-#ifdef USE_PREFETCH
-		if (scan->prefetch_maximum > 0)
-			bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
-#endif							/* USE_PREFETCH */
-
-
 		node->initialized = true;
 	}
 
@@ -319,7 +289,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
 	node->tbm = NULL;
@@ -363,7 +333,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
@@ -519,14 +489,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -557,11 +523,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 22bdccc2a9..1cad9c04f0 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -81,18 +85,6 @@ typedef struct HeapScanDescData
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-	/* buffer for visibility-map lookups of prefetched pages */
-	Buffer		pvmbuffer;
-
-	/*
-	 * These fields only used for prefetching in bitmap table scans
-	 */
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
-	/* used to validate prefetch block stays ahead of current block */
-	BlockNumber pfblockno;
 
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 65092d7226..00a123ee92 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -57,15 +57,8 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	BitmapHeapIterator *rs_tbmiterator;
-	/* Prefetch iterator */
-	BitmapHeapIterator *rs_pf_tbmiterator;
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
 
-	/* used to validate prefetch and current block stay in sync */
-	BlockNumber blockno;
-
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5ad3eff539..4bc021f0eb 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -933,7 +933,6 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_tbmiterator = NULL;
-	result->rs_pf_tbmiterator = NULL;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -999,13 +998,6 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_tbmiterator);
 		scan->rs_tbmiterator = NULL;
-#ifdef USE_PREFETCH
-		if (scan->rs_pf_tbmiterator)
-		{
-			bhs_end_iterate(scan->rs_pf_tbmiterator);
-			scan->rs_pf_tbmiterator = NULL;
-		}
-#endif
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1022,14 +1014,6 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_tbmiterator);
 		scan->rs_tbmiterator = NULL;
-
-#ifdef USE_PREFETCH
-		if (scan->rs_pf_tbmiterator)
-		{
-			bhs_end_iterate(scan->rs_pf_tbmiterator);
-			scan->rs_pf_tbmiterator = NULL;
-		}
-#endif
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 7a3fdf9cd4..c1778653c7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1758,11 +1758,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1770,10 +1766,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.40.1

#72Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#71)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/23/24 01:26, Melanie Plageman wrote:

On Fri, Mar 22, 2024 at 08:22:11PM -0400, Melanie Plageman wrote:

On Tue, Mar 19, 2024 at 02:33:35PM +0200, Heikki Linnakangas wrote:

On 18/03/2024 17:19, Melanie Plageman wrote:

I've attached v7 rebased over this commit.

If we delayed table_beginscan_bm() call further, after starting the TBM
iterator, we could skip it altogether when the iterator is empty.

That's a further improvement, doesn't need to be part of this patch set.
Just caught my eye while reading this.

Hmm. You mean like until after the first call to tbm_[shared]_iterate()?
AFAICT, tbm_begin_iterate() doesn't tell us anything about whether or
not the iterator is "empty". Do you mean cases when the bitmap has no
blocks in it? It seems like we should be able to tell that from the
TIDBitmap.

v7-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patch

I suggest to avoid the double negative with SO_CAN_SKIP_FETCH, and call the
flag e.g. SO_NEED_TUPLE.

Agreed. Done in attached v8. Though I wondered if it was a bit weird
that the flag is set in the common case and not set in the uncommon
case...

v8 actually attached this time

I tried to run the benchmarks with v8, but unfortunately it crashes for
me very quickly (I've only seen 0015 to crash, so I guess the bug is in
that patch).

The backtrace attached, this doesn't seem right:

(gdb) p hscan->rs_cindex
$1 = 543516018

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

crash.txttext/plain; charset=UTF-8; name=crash.txtDownload
#73Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#72)
17 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Mar 24, 2024 at 01:36:19PM +0100, Tomas Vondra wrote:

On 3/23/24 01:26, Melanie Plageman wrote:

On Fri, Mar 22, 2024 at 08:22:11PM -0400, Melanie Plageman wrote:

On Tue, Mar 19, 2024 at 02:33:35PM +0200, Heikki Linnakangas wrote:

On 18/03/2024 17:19, Melanie Plageman wrote:

I've attached v7 rebased over this commit.

If we delayed table_beginscan_bm() call further, after starting the TBM
iterator, we could skip it altogether when the iterator is empty.

That's a further improvement, doesn't need to be part of this patch set.
Just caught my eye while reading this.

Hmm. You mean like until after the first call to tbm_[shared]_iterate()?
AFAICT, tbm_begin_iterate() doesn't tell us anything about whether or
not the iterator is "empty". Do you mean cases when the bitmap has no
blocks in it? It seems like we should be able to tell that from the
TIDBitmap.

v7-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patch

I suggest to avoid the double negative with SO_CAN_SKIP_FETCH, and call the
flag e.g. SO_NEED_TUPLE.

Agreed. Done in attached v8. Though I wondered if it was a bit weird
that the flag is set in the common case and not set in the uncommon
case...

v8 actually attached this time

I tried to run the benchmarks with v8, but unfortunately it crashes for
me very quickly (I've only seen 0015 to crash, so I guess the bug is in
that patch).

The backtrace attached, this doesn't seem right:

(gdb) p hscan->rs_cindex
$1 = 543516018

Thanks for reporting this! I hadn't seen it crash on my machine, so I
didn't realize that I was no longer initializing rs_cindex and
rs_ntuples on the first call to heapam_bitmap_next_tuple() (since
heapam_bitmap_next_block() wasn't being called first). I've done this in
attached v9.

I haven't had a chance yet to reproduce the regressions you saw in the
streaming read user patch or to look closely at the performance results.
I don't anticipate the streaming read user will have any performance
differences in this v9 from v6, since I haven't yet rebased in Thomas'
latest streaming read API changes nor addressed any other potential
regression sources.

I tried rebasing in Thomas' latest version today and something is
causing a crash that I have yet to figure out. v10 of this patchset will
have his latest version once I get that fixed. I wanted to share this
version with what I think is a bug fix for the crash you saw first.

- Melanie

Attachments:

v9-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From 5d45746e8602559f60fea6e32b108dc23a9f41d7 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v9 01/17] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index e57a0b7ea3..e78d793f69 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aab..93fdcd226b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v9-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 321b320c40e6e5d7ef81cd62710e0d06e80ce9fc Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v9 02/17] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 93fdcd226b..c64530674b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -742,16 +752,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v9-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patchtext/x-diff; charset=us-asciiDownload
From c110baa11fbb6a5ee2639a34169e557a36498f05 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v9 03/17] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 34bc60f625..e7bed84f75 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -951,6 +951,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1039,6 +1041,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1058,6 +1066,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2b7c702642..7fdccaf613 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2124,6 +2125,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2236,6 +2255,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c64530674b..83d9db8f39 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,11 +185,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	node->ss.ps.state->es_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	extra_flags);
 		}
 
 		node->initialized = true;
@@ -207,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -228,37 +232,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -301,52 +282,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +531,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +601,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +610,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +654,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -740,8 +697,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +707,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4b133f6859..3dfb19ec7d 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 65834caeb1..1bc5f7c057 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -952,9 +959,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 1774c56ae3..6871db9b21 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1785,10 +1785,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1808,9 +1805,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v9-0004-BitmapPrefetch-use-prefetch-block-recheck-for-ski.patchtext/x-diff; charset=us-asciiDownload
From c07c20bce287f6266f58cc2179b1f9dc16da8850 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v9 04/17] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 83d9db8f39..5df3b5ca46 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -474,14 +474,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -532,7 +527,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v9-0005-Update-BitmapAdjustPrefetchIterator-parameter-typ.patchtext/x-diff; charset=us-asciiDownload
From 8bc7c42a7d6264de7f9857f6541ab12b0f3ddbe0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v9 05/17] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5df3b5ca46..404de0595e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -230,7 +230,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -341,7 +341,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -360,7 +360,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v9-0006-table_scan_bitmap_next_block-returns-lossy-or-exa.patchtext/x-diff; charset=us-asciiDownload
From 17ee3d0b26b631c0e2edec8242219adf5532280c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v9 06/17] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7fdccaf613..849cac3947 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,7 +2114,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2242,6 +2243,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 404de0595e..c95e3412da 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
+		bool		valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -232,12 +232,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1bc5f7c057..b9ba4f9fb3 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -804,6 +804,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -819,7 +822,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1988,14 +1992,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2006,7 +2012,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.40.1

v9-0007-Reduce-scope-of-BitmapHeapScan-tbmiterator-local-.patchtext/x-diff; charset=us-asciiDownload
From 8bfd073e2f59ce4f5979fd433290e51e54597d85 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v9 07/17] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c95e3412da..49938c9ed4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +202,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -221,9 +219,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v9-0008-Remove-table_scan_bitmap_next_tuple-parameter-tbm.patchtext/x-diff; charset=us-asciiDownload
From 8d60908ce61e967376b961081b973df9baeae5ab Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v9 08/17] Remove table_scan_bitmap_next_tuple parameter tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 849cac3947..cf4387f443 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2250,7 +2250,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 49938c9ed4..282dcb9791 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -286,7 +286,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b9ba4f9fb3..bcf1497f67 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -795,10 +795,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -829,15 +826,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2025,7 +2017,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2037,7 +2028,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v9-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 0febaee773a45cf19065a23d19023196bf7b4628 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v9 09/17] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 195 insertions(+), 149 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index cf4387f443..2ad785e511 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,18 +2114,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2144,16 +2177,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2245,7 +2269,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 282dcb9791..7e73583fe5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +109,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +161,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -202,55 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool		valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -272,45 +232,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno > node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,13 +311,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -356,14 +335,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -388,7 +370,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -466,6 +451,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -523,6 +509,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -584,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -597,13 +581,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -634,28 +618,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -688,8 +668,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -697,9 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304a..92b829cebc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index bcf1497f67..a820cc8c99 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -788,19 +789,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -819,8 +815,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -957,9 +953,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1019,6 +1019,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1029,6 +1044,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1981,19 +2011,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2003,8 +2031,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6871db9b21..8688bc5ab0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1783,8 +1783,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1793,9 +1791,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1803,8 +1803,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1813,9 +1811,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v9-0010-table_scan_bitmap_next_block-counts-lossy-and-exa.patchtext/x-diff; charset=us-asciiDownload
From cf97448fb2c952354d85f43ef6a6ef1ffb654166 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 17:09:12 -0400
Subject: [PATCH v9 10/17] table_scan_bitmap_next_block counts lossy and exact
 pages

Now that the table_scan_bitmap_next_block() callback only returns false
when the bitmap is exhausted, it is simpler to move the management of
the lossy and exact page counters into it. We will eventually remove
this callback and table_scan_bitmap_next_tuple() will update those
counters when a new block is read in.
---
 src/backend/access/heap/heapam_handler.c  |  8 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c |  9 ++-------
 src/include/access/tableam.h              | 21 +++++++++++++--------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2ad785e511..266b34fe6b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,7 +2114,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+							  bool *recheck, BlockNumber *blockno,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block;
@@ -2267,7 +2268,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 7e73583fe5..96b55507a3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -69,7 +69,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	bool		lossy;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -267,14 +266,10 @@ new_page:
 
 		BitmapAdjustPrefetchIterator(node);
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+										  &node->lossy_pages, &node->exact_pages))
 			break;
 
-		if (lossy)
-			node->lossy_pages++;
-		else
-			node->exact_pages++;
-
 		/*
 		 * If serial, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a820cc8c99..1d4b79a73f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,8 +797,8 @@ typedef struct TableAmRoutine
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * lossy indicates whether or not the block's representation in the bitmap
-	 * is lossy or exact.
+	 * lossy_pages is incremented if the block's representation in the bitmap
+	 * is lossy, otherwise, exact_pages is incremented.
 	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
@@ -815,8 +815,10 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+										   bool *recheck,
+										   BlockNumber *blockno,
+										   long *lossy_pages,
+										   long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -2013,15 +2015,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap table scan.
  * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy is set to true
- * if bitmap is lossy for the selected block and false otherwise.
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented if bitmap is lossy for the selected block and exact_pages is
+ * incremented otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+							 bool *recheck, BlockNumber *blockno,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2032,7 +2036,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+														   blockno, lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v9-0011-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From 095b063651c492b7040440e448dc375e36a31fa1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v9 11/17] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 33 +++++++--------------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 28 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fc..1dc4c99bf9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1463,12 +1449,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	TBMSharedIterator *iterator;
 	TBMSharedIteratorState *istate;
 
-	/*
-	 * Create the TBMSharedIterator struct, with enough trailing space to
-	 * serve the needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639b..432fae5296 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.40.1

v9-0012-Separate-TBM-Shared-Iterator-and-TBMIterateResult.patchtext/x-diff; charset=us-asciiDownload
From afd06b79a7a0260bf6b3194a5c608be0f843a037 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v9 12/17] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 38 ++++++------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 7 files changed, 108 insertions(+), 91 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb..3aa457a29e 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544..033d525339 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 266b34fe6b..adfc77684a 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2122,7 +2122,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2135,11 +2135,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		CHECK_FOR_INTERRUPTS();
 
 		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbm_iterate(scan->tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2154,11 +2154,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2166,19 +2166,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2207,7 +2207,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2216,9 +2216,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2268,7 +2268,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 96b55507a3..51c4360205 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -316,7 +316,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,8 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -366,8 +366,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -435,10 +435,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
@@ -446,7 +448,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -455,13 +457,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -476,7 +478,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -495,8 +497,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_shared_iterate(prefetch_iterator);
@@ -504,17 +506,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1dc4c99bf9..309a44bdb8 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae..3b432263bb 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae5296..f000c1af28 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.40.1

v9-0013-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchtext/x-diff; charset=us-asciiDownload
From 5152ee50a21ea8e39a0f33efc0c83519f418ed8d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 09:42:23 -0400
Subject: [PATCH v9 13/17] Push BitmapHeapScan prefetch code into heapam.c

In preparation for transitioning to using the streaming read API for
prefetching [1], move all of the BitmapHeapScanState members related to
prefetching and the functions for accessing them into the
HeapScanDescData and TableScanDescData. Members that still need to be
accessed in BitmapHeapNext() could not be moved into heap AM-specific
code. Specifically, parallel iterator setup requires several components
which seem odd to pass to the table AM API.

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  26 ++
 src/backend/access/heap/heapam_handler.c  | 268 +++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 397 +++-------------------
 src/include/access/heapam.h               |  12 +
 src/include/access/relscan.h              |  11 +
 src/include/access/tableam.h              |  38 ++-
 src/include/nodes/execnodes.h             |  16 -
 7 files changed, 388 insertions(+), 380 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index e7bed84f75..c12563a188 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -951,8 +951,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+
+	scan->rs_base.blockno = InvalidBlockNumber;
+
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
+	scan->pvmbuffer = InvalidBuffer;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1035,6 +1043,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
+	scan->rs_base.blockno = InvalidBlockNumber;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	/*
 	 * unpin scan buffers
 	 */
@@ -1047,6 +1061,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1072,6 +1092,12 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index adfc77684a..efd2784e03 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -55,6 +55,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
+static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2112,6 +2115,76 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+static inline void
+BitmapAdjustPrefetchIterator(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	TBMIterateResult tbmpre;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = scan->rs_base.pf_tbmiterator;
+
+		if (scan->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			scan->prefetch_pages--;
+		}
+		else if (prefetch_iterator)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblockno = tbmpre.blockno;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (scan->rs_base.prefetch_maximum > 0)
+	{
+		TBMSharedIterator *prefetch_iterator = scan->rs_base.pf_shared_tbmiterator;
+
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (prefetch_iterator)
+			{
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblockno = tbmpre.blockno;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  bool *recheck, BlockNumber *blockno,
@@ -2130,6 +2203,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(hscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2273,6 +2348,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->bm_parallel == NULL &&
+		scan->pf_tbmiterator &&
+		hscan->pfblockno > hscan->rs_base.blockno)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(hscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2283,6 +2370,157 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
+		else
+			scan->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = scan->rs_base.pf_tbmiterator;
+
+		if (prefetch_iterator)
+		{
+			while (scan->prefetch_pages < scan->prefetch_target)
+			{
+				TBMIterateResult tbmpre;
+				bool		skip_fetch;
+
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					scan->rs_base.pf_tbmiterator = NULL;
+					break;
+				}
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre.blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		TBMSharedIterator *prefetch_iterator = scan->rs_base.pf_shared_tbmiterator;
+
+		if (prefetch_iterator)
+		{
+			while (1)
+			{
+				TBMIterateResult tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					tbm_end_shared_iterate(prefetch_iterator);
+					scan->rs_base.pf_shared_tbmiterator = NULL;
+					break;
+				}
+
+				scan->pfblockno = tbmpre.blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
@@ -2308,6 +2546,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!scan->bm_parallel)
+	{
+		if (hscan->prefetch_target < scan->prefetch_maximum)
+			hscan->prefetch_target++;
+	}
+	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&scan->bm_parallel->mutex);
+		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+			scan->bm_parallel->prefetch_target++;
+		SpinLockRelease(&scan->bm_parallel->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(hscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 51c4360205..f241f4cb2c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -71,7 +67,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
@@ -91,83 +86,53 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
 	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
 	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
 	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
+
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		int			pf_maximum = 0;
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
+#endif
 
-		if (!pstate)
+		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (init_shared_state)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
 				 * multiple processes to iterate jointly.
 				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
-					pstate->prefetch_iterator =
+					node->pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+				BitmapDoneInitializingSharedState(node->pstate);
 			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -197,8 +162,26 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		scan->prefetch_maximum = pf_maximum;
+		scan->bm_parallel = node->pstate;
+
+		if (!scan->bm_parallel)
+			scan->tbmiterator = tbm_begin_iterate(tbm);
+		else
+			/* Allocate a private iterator and attach the shared state to it */
+			scan->shared_tbmiterator = tbm_attach_shared_iterate(dsa, scan->bm_parallel->tbmiterator);
+
+#ifdef USE_PREFETCH
+		if (scan->prefetch_maximum > 0)
+		{
+			if (!scan->bm_parallel)
+				scan->pf_tbmiterator = tbm_begin_iterate(tbm);
+			else
+				scan->pf_shared_tbmiterator =
+					tbm_attach_shared_iterate(dsa, scan->bm_parallel->prefetch_iterator);
+		}
+#endif							/* USE_PREFETCH */
+
 
 		node->initialized = true;
 
@@ -211,36 +194,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
 
 			/*
 			 * If we are using lossy info, we have to recheck the qual
@@ -264,23 +217,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
-			node->pfblockno > node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -304,224 +243,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
 
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
@@ -569,22 +291,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -625,14 +336,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -665,18 +370,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -716,13 +414,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -806,7 +497,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3dfb19ec7d..22bdccc2a9 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -81,6 +81,18 @@ typedef struct HeapScanDescData
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
+
+	/*
+	 * These fields only used for prefetching in bitmap table scans
+	 */
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block */
+	BlockNumber pfblockno;
 
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc..93168bd350 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -26,6 +26,7 @@ struct ParallelTableScanDescData;
 
 struct TBMIterator;
 struct TBMSharedIterator;
+struct ParallelBitmapHeapState;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -46,6 +47,16 @@ typedef struct TableScanDescData
 	/* Only used for Bitmap table scans */
 	struct TBMIterator *tbmiterator;
 	struct TBMSharedIterator *shared_tbmiterator;
+	/* Prefetch iterators */
+	struct TBMIterator *pf_tbmiterator;
+	struct TBMSharedIterator *pf_shared_tbmiterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+	struct ParallelBitmapHeapState *bm_parallel;
+
+	/* used to validate prefetch and current block stay in sync */
+	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1d4b79a73f..9cab4462d6 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -800,17 +800,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the block's representation in the bitmap
 	 * is lossy, otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -961,6 +950,9 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->shared_tbmiterator = NULL;
 	result->tbmiterator = NULL;
+	result->pf_shared_tbmiterator = NULL;
+	result->pf_tbmiterator = NULL;
+	result->bm_parallel = NULL;
 	return result;
 }
 
@@ -1029,11 +1021,23 @@ table_endscan(TableScanDesc scan)
 			scan->shared_tbmiterator = NULL;
 		}
 
+		if (scan->pf_shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->pf_shared_tbmiterator);
+			scan->pf_shared_tbmiterator = NULL;
+		}
+
 		if (scan->tbmiterator)
 		{
 			tbm_end_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
+
+		if (scan->pf_tbmiterator)
+		{
+			tbm_end_iterate(scan->pf_tbmiterator);
+			scan->pf_tbmiterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1054,11 +1058,23 @@ table_rescan(TableScanDesc scan,
 			scan->shared_tbmiterator = NULL;
 		}
 
+		if (scan->pf_shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->pf_shared_tbmiterator);
+			scan->pf_shared_tbmiterator = NULL;
+		}
+
 		if (scan->tbmiterator)
 		{
 			tbm_end_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
+
+		if (scan->pf_tbmiterator)
+		{
+			tbm_end_iterate(scan->pf_tbmiterator);
+			scan->pf_tbmiterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8688bc5ab0..7a3fdf9cd4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1783,19 +1783,11 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1803,19 +1795,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v9-0014-Unify-parallel-and-serial-BitmapHeapScan-iterator.patchtext/x-diff; charset=us-asciiDownload
From 9972e4838b67ea63550505577d1447925d7f97e1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 13:43:41 -0400
Subject: [PATCH v9 14/17] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to
both TBMIterator and TBMSharedIterators. This encapsulates the parallel
and serial iterators and their access and makes the bitmap heap scan
code a bit cleaner.
---
 src/backend/access/heap/heapam_handler.c  | 40 ++++++---------
 src/backend/executor/nodeBitmapHeapscan.c | 62 ++++++++++++++++++-----
 src/include/access/relscan.h              | 20 +++++---
 src/include/access/tableam.h              | 61 ++++++----------------
 src/tools/pgindent/typedefs.list          |  1 +
 5 files changed, 96 insertions(+), 88 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index efd2784e03..1a9f7b02d1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -55,6 +55,7 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+
 static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
 static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
 static inline void BitmapPrefetch(HeapScanDesc scan);
@@ -2131,17 +2132,15 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = scan->rs_base.pf_tbmiterator;
-
 		if (scan->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			scan->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (scan->rs_base.rs_pf_tbmiterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
+			bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
 			scan->pfblockno = tbmpre.blockno;
 		}
 		return;
@@ -2154,8 +2153,6 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = scan->rs_base.pf_shared_tbmiterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -2175,9 +2172,9 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (scan->rs_base.rs_pf_tbmiterator)
 			{
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
 				scan->pfblockno = tbmpre.blockno;
 			}
 		}
@@ -2209,10 +2206,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbm_shared_iterate(scan->shared_tbmiterator, &tbmres);
-		else
-			tbm_iterate(scan->tbmiterator, &tbmres);
+		bhs_iterate(scan->rs_tbmiterator, &tbmres);
 
 		if (!BlockNumberIsValid(tbmres.blockno))
 		{
@@ -2353,7 +2347,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * ahead of the current block.
 	 */
 	if (scan->bm_parallel == NULL &&
-		scan->pf_tbmiterator &&
+		scan->rs_pf_tbmiterator &&
 		hscan->pfblockno > hscan->rs_base.blockno)
 		elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -2427,22 +2421,20 @@ BitmapPrefetch(HeapScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = scan->rs_base.pf_tbmiterator;
-
-		if (prefetch_iterator)
+		if (scan->rs_base.rs_pf_tbmiterator)
 		{
 			while (scan->prefetch_pages < scan->prefetch_target)
 			{
 				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				tbm_iterate(prefetch_iterator, &tbmpre);
+				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
 
 				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					scan->rs_base.pf_tbmiterator = NULL;
+					bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
+					scan->rs_base.rs_pf_tbmiterator = NULL;
 					break;
 				}
 				scan->prefetch_pages++;
@@ -2470,9 +2462,7 @@ BitmapPrefetch(HeapScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = scan->rs_base.pf_shared_tbmiterator;
-
-		if (prefetch_iterator)
+		if (scan->rs_base.rs_pf_tbmiterator)
 		{
 			while (1)
 			{
@@ -2495,12 +2485,12 @@ BitmapPrefetch(HeapScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbm_shared_iterate(prefetch_iterator, &tbmpre);
+				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
 				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					scan->rs_base.pf_shared_tbmiterator = NULL;
+					bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
+					scan->rs_base.rs_pf_tbmiterator = NULL;
 					break;
 				}
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index f241f4cb2c..b548642088 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,6 +52,54 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
+static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
+											 ParallelBitmapHeapState *pstate, dsa_area *personal_area);
+
+BitmapHeapIterator *
+bhs_begin_iterate(TIDBitmap *tbm, ParallelBitmapHeapState *pstate, dsa_area *personal_area)
+{
+	BitmapHeapIterator *result = palloc(sizeof(BitmapHeapIterator));
+
+	result->serial = NULL;
+	result->parallel = NULL;
+
+	if (pstate)
+		result->parallel = tbm_attach_shared_iterate(personal_area, pstate->tbmiterator);
+	else
+		result->serial = tbm_begin_iterate(tbm);
+
+	return result;
+}
+
+void
+bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *tbmres)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		tbm_iterate(iterator->serial, tbmres);
+	else
+		tbm_shared_iterate(iterator->parallel, tbmres);
+}
+
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+	{
+		tbm_end_iterate(iterator->serial);
+		iterator->serial = NULL;
+	}
+	else
+	{
+		tbm_end_shared_iterate(iterator->parallel);
+		iterator->parallel = NULL;
+	}
+
+	pfree(iterator);
+}
 
 
 /* ----------------------------------------------------------------
@@ -165,21 +213,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
-		if (!scan->bm_parallel)
-			scan->tbmiterator = tbm_begin_iterate(tbm);
-		else
-			/* Allocate a private iterator and attach the shared state to it */
-			scan->shared_tbmiterator = tbm_attach_shared_iterate(dsa, scan->bm_parallel->tbmiterator);
+		scan->rs_tbmiterator = bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
 
 #ifdef USE_PREFETCH
 		if (scan->prefetch_maximum > 0)
-		{
-			if (!scan->bm_parallel)
-				scan->pf_tbmiterator = tbm_begin_iterate(tbm);
-			else
-				scan->pf_shared_tbmiterator =
-					tbm_attach_shared_iterate(dsa, scan->bm_parallel->prefetch_iterator);
-		}
+			bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
 #endif							/* USE_PREFETCH */
 
 
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 93168bd350..65092d7226 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -27,6 +27,17 @@ struct ParallelTableScanDescData;
 struct TBMIterator;
 struct TBMSharedIterator;
 struct ParallelBitmapHeapState;
+struct TBMIterateResult;
+
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+} BitmapHeapIterator;
+
+extern void bhs_iterate(BitmapHeapIterator *tbmiterator, struct TBMIterateResult *tbmres);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -45,12 +56,9 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
-	/* Prefetch iterators */
-	struct TBMIterator *pf_tbmiterator;
-	struct TBMSharedIterator *pf_shared_tbmiterator;
-
+	BitmapHeapIterator *rs_tbmiterator;
+	/* Prefetch iterator */
+	BitmapHeapIterator *rs_pf_tbmiterator;
 	/* maximum value for prefetch_target */
 	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9cab4462d6..2ded1a124b 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -948,10 +948,8 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	result->pf_shared_tbmiterator = NULL;
-	result->pf_tbmiterator = NULL;
+	result->rs_tbmiterator = NULL;
+	result->rs_pf_tbmiterator = NULL;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -1015,29 +1013,15 @@ table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
+		bhs_end_iterate(scan->rs_tbmiterator);
+		scan->rs_tbmiterator = NULL;
+#ifdef USE_PREFETCH
+		if (scan->rs_pf_tbmiterator)
 		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->pf_shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->pf_shared_tbmiterator);
-			scan->pf_shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-
-		if (scan->pf_tbmiterator)
-		{
-			tbm_end_iterate(scan->pf_tbmiterator);
-			scan->pf_tbmiterator = NULL;
+			bhs_end_iterate(scan->rs_pf_tbmiterator);
+			scan->rs_pf_tbmiterator = NULL;
 		}
+#endif
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1052,29 +1036,16 @@ table_rescan(TableScanDesc scan,
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->pf_shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->pf_shared_tbmiterator);
-			scan->pf_shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_tbmiterator);
+		scan->rs_tbmiterator = NULL;
 
-		if (scan->pf_tbmiterator)
+#ifdef USE_PREFETCH
+		if (scan->rs_pf_tbmiterator)
 		{
-			tbm_end_iterate(scan->pf_tbmiterator);
-			scan->pf_tbmiterator = NULL;
+			bhs_end_iterate(scan->rs_pf_tbmiterator);
+			scan->rs_pf_tbmiterator = NULL;
 		}
+#endif
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index e2a0525dd4..58317eac44 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.40.1

v9-0015-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From 4f69998bd52da1e6dc4e9e019072db839e24c550 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 15:43:10 -0400
Subject: [PATCH v9 15/17] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block(). Heap AM's implementation of
table_scan_bitmap_next_tuple() now calls the original
heapam_scan_bitmap_next_block() function, but it is no longer an
implementation of a table AM callback but instead a helper for
heapam_scan_bitmap_next_tuple()
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 48 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 45 ++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 75 +++++------------------
 6 files changed, 63 insertions(+), 111 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index c12563a188..9ddbaff4e2 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -322,6 +322,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 1a9f7b02d1..9dfc99d8fa 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2110,12 +2110,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
- */
-
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
  *
@@ -2148,8 +2142,8 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
@@ -2511,30 +2505,43 @@ BitmapPrefetch(HeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
-		return true;
-	}
+		if (hscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			hscan->rs_empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2916,7 +2923,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index ce637a5a5d..1d6b03d1ca 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b548642088..2683d8bc0c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -222,44 +222,35 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 
 		node->initialized = true;
-
-		goto new_page;
 	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346..cf56cc572f 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2ded1a124b..5ad3eff539 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -788,36 +788,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the block's representation in the bitmap
-	 * is lossy, otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   BlockNumber *blockno,
-										   long *lossy_pages,
-										   long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -2000,44 +1984,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented if bitmap is lossy for the selected block and exact_pages is
- * incremented otherwise.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno,
-							 long *lossy_pages, long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   blockno, lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2048,7 +2001,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v9-0016-v7-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From 8eebac7992268b45eed0042abec10cd86795a540 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:59:42 -0400
Subject: [PATCH v9 16/17] v7 Streaming Read API

---
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 659 +++++++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 642 +++++++++++++++-------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/include/storage/bufmgr.h             |  45 ++
 src/include/storage/streaming_read.h     |  52 ++
 src/tools/pgindent/typedefs.list         |   3 +
 10 files changed, 1227 insertions(+), 210 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca2..eec03f6f2b 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 0000000000..bcab44c802
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 0000000000..39aef2a84a
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 0000000000..d5c29b750d
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,659 @@
+#include "postgres.h"
+
+#include "catalog/pg_tablespace.h"
+#include "miscadmin.h"
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+#include "utils/spccache.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		need_wait;
+	bool		advice_issued;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index;
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+	ReadBuffersOperation operation;
+} PgStreamingReadRange;
+
+/*
+ * Streaming read object.
+ */
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			next_tail_buffer;
+	int			distance;
+	bool		started;
+	bool		finished;
+	bool		advice_enabled;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	/* Sometimes we need to buffer one block for flow control. */
+	BlockNumber unget_blocknum;
+	void	   *unget_per_buffer_data;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+	Oid			tablespace_id;
+
+	/*
+	 * Make sure our bmr's smgr and persistent are populated.  The caller
+	 * asserts that the storage manager will remain valid.
+	 */
+	if (!bmr.smgr)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	tablespace_id = bmr.smgr->smgr_rlocator.locator.spcOid;
+	if (!OidIsValid(MyDatabaseId) ||
+		(bmr.rel && IsCatalogRelation(bmr.rel)) ||
+		IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
+	{
+		/*
+		 * Avoid circularity while trying to look up tablespace settings or
+		 * before spccache.c is ready.
+		 */
+		max_ios = effective_io_concurrency;
+	}
+	else if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
+	else
+		max_ios = get_tablespace_io_concurrency(tablespace_id);
+
+	/*
+	 * Choose a maximum number of buffers we're prepared to pin.  We try to
+	 * pin fewer if we can, though.  We clamp it to at least
+	 * MAX_BUFFER_PER_TRANSFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/* Don't allow this backend to pin more than its share of buffers. */
+	if (SmgrIsTemp(bmr.smgr))
+		LimitAdditionalLocalPins(&max_pinned_buffers);
+	else
+		LimitAdditionalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+	pgsr->callback = next_block_cb;
+	pgsr->bmr = bmr;
+	pgsr->forknum = forknum;
+
+	pgsr->unget_blocknum = InvalidBlockNumber;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * Skip the initial ramp-up phase if the caller says we're going to be
+	 * reading the whole relation.  This way we start out doing full-sized
+	 * reads.
+	 */
+	if (flags & PGSR_FLAG_FULL)
+		pgsr->distance = Min(MAX_BUFFERS_PER_TRANSFER, pgsr->max_pinned_buffers);
+	else
+		pgsr->distance = 1;
+
+	/*
+	 * Space for the callback to store extra data along with each block.  Note
+	 * that we need one more than max_pinned_buffers, so we can return a
+	 * pointer to a slot that can't be overwritten until the next call.
+	 */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * size);
+
+	return pgsr;
+}
+
+/*
+ * Find the per-buffer data index for the Nth block of a range.
+ */
+static int
+get_per_buffer_data_index(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	int			result;
+
+	/*
+	 * Find slot in the circular buffer of per-buffer data, without using the
+	 * expensive % operator.
+	 */
+	result = range->per_buffer_data_index + n;
+	while (result >= pgsr->size)
+		result -= pgsr->size;
+	Assert(result == (range->per_buffer_data_index + n) % pgsr->size);
+
+	return result;
+}
+
+/*
+ * Return a pointer to the per-buffer data by index.
+ */
+static void *
+get_per_buffer_data_by_index(PgStreamingRead *pgsr, int per_buffer_data_index)
+{
+	return (char *) pgsr->per_buffer_data +
+		pgsr->per_buffer_data_size * per_buffer_data_index;
+}
+
+/*
+ * Return a pointer to the per-buffer data for the Nth block of a range.
+ */
+static void *
+get_per_buffer_data(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	return get_per_buffer_data_by_index(pgsr,
+										get_per_buffer_data_index(pgsr,
+																  range,
+																  n));
+}
+
+/*
+ * Start reading the head range, and create a new head range.  The new head
+ * range is returned.  It may not be empty, if StartReadBuffers() couldn't
+ * start the entire range; in that case the returned range contains the
+ * remaining portion of the range.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_start_head_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+	PgStreamingReadRange *new_head_range;
+	int			nblocks_pinned;
+	int			flags;
+
+	/* Caller should make sure we never exceed max_ios. */
+	Assert((pgsr->ios_in_progress < pgsr->max_ios) ||
+		   (pgsr->ios_in_progress == 0 && pgsr->max_ios == 0));
+
+	/* Should only call if the head range has some blocks to read. */
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If advice hasn't been suppressed, and this system supports it, this
+	 * isn't a strictly sequential pattern, then we'll issue advice.
+	 */
+	if (pgsr->advice_enabled &&
+		pgsr->max_ios > 0 &&
+		pgsr->started &&
+		head_range->blocknum != pgsr->seq_blocknum)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else
+		flags = 0;
+
+	/* Suppress advice on the first call, because it's too late to benefit. */
+	if (!pgsr->started)
+		pgsr->started = true;
+
+	/* We shouldn't be trying to pin more buffers that we're allowed to. */
+	Assert(pgsr->pinned_buffers + head_range->nblocks <= pgsr->max_pinned_buffers);
+
+	/* Start reading as many blocks as we can from the head range. */
+	nblocks_pinned = head_range->nblocks;
+	head_range->need_wait =
+		StartReadBuffers(pgsr->bmr,
+						 head_range->buffers,
+						 pgsr->forknum,
+						 head_range->blocknum,
+						 &nblocks_pinned,
+						 pgsr->strategy,
+						 flags,
+						 &head_range->operation);
+
+	Assert(pgsr->pinned_buffers <= pgsr->max_pinned_buffers);
+
+	if (head_range->need_wait && (flags & READ_BUFFERS_ISSUE_ADVICE))
+	{
+		/*
+		 * Since we've issued advice, we count an I/O in progress until we
+		 * call WaitReadBuffers().
+		 */
+		head_range->advice_issued = true;
+		pgsr->ios_in_progress++;
+		Assert(pgsr->ios_in_progress <= pgsr->max_ios);
+	}
+
+	/*
+	 * StartReadBuffers() might have pinned fewer blocks than we asked it to,
+	 * but always at least one.
+	 */
+	Assert(nblocks_pinned <= head_range->nblocks);
+	Assert(nblocks_pinned >= 1);
+	pgsr->pinned_buffers += nblocks_pinned;
+
+	/*
+	 * Remember where the next block would be after that, so we can detect
+	 * sequential access next time.
+	 */
+	pgsr->seq_blocknum = head_range->blocknum + nblocks_pinned;
+
+	/*
+	 * Create a new head range.  There must be space, because we have enough
+	 * elements for every range to hold just one block, up to the pin limit.
+	 */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	new_head_range = &pgsr->ranges[pgsr->head];
+	new_head_range->nblocks = 0;
+	new_head_range->advice_issued = false;
+
+	/*
+	 * If we didn't manage to start the whole read above, we split the range,
+	 * moving the remainder into the new head range.
+	 */
+	if (nblocks_pinned < head_range->nblocks)
+	{
+		int			nblocks_remaining = head_range->nblocks - nblocks_pinned;
+
+		head_range->nblocks = nblocks_pinned;
+
+		new_head_range->blocknum = head_range->blocknum + nblocks_pinned;
+		new_head_range->nblocks = nblocks_remaining;
+	}
+
+	/* The new range has per-buffer data starting after the previous range. */
+	new_head_range->per_buffer_data_index =
+		get_per_buffer_data_index(pgsr, head_range, nblocks_pinned);
+
+	return new_head_range;
+}
+
+/*
+ * Ask the callback which block it would like us to read next, with a small
+ * buffer in front to allow pg_streaming_unget_block() to work.
+ */
+static BlockNumber
+pg_streaming_get_block(PgStreamingRead *pgsr, void *per_buffer_data)
+{
+	BlockNumber result;
+
+	if (unlikely(pgsr->unget_blocknum != InvalidBlockNumber))
+	{
+		/*
+		 * If we had to unget a block, now it is time to return that one
+		 * again.
+		 */
+		result = pgsr->unget_blocknum;
+		pgsr->unget_blocknum = InvalidBlockNumber;
+
+		/*
+		 * The same per_buffer_data element must have been used, and still
+		 * contains whatever data the callback wrote into it.  So we just
+		 * sanity-check that we were called with the value that
+		 * pg_streaming_unget_block() pushed back.
+		 */
+		Assert(per_buffer_data == pgsr->unget_per_buffer_data);
+	}
+	else
+	{
+		/* Use the installed callback directly. */
+		result = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+	}
+
+	return result;
+}
+
+/*
+ * In order to deal with short reads in StartReadBuffers(), we sometimes need
+ * to defer handling of a block until later.  This *must* be called with the
+ * last value returned by pg_streaming_get_block().
+ */
+static void
+pg_streaming_unget_block(PgStreamingRead *pgsr, BlockNumber blocknum, void *per_buffer_data)
+{
+	Assert(pgsr->unget_blocknum == InvalidBlockNumber);
+	pgsr->unget_blocknum = blocknum;
+	pgsr->unget_per_buffer_data = per_buffer_data;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *range;
+
+	/* If we're finished, don't look ahead. */
+	if (pgsr->finished)
+		return;
+
+	/*
+	 * We we've already started the maximum allowed number of I/Os, don't look
+	 * ahead.  There is a special case for max_ios == 0.
+	 */
+	if (pgsr->max_ios > 0 && pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/* Can't pin any more buffers. */
+	if (pgsr->pinned_buffers == pgsr->distance)
+		return;
+
+	/*
+	 * Keep trying to add new blocks to the end of the head range while doing
+	 * so wouldn't exceed the distance limit.
+	 */
+	range = &pgsr->ranges[pgsr->head];
+	while (pgsr->pinned_buffers + range->nblocks < pgsr->distance)
+	{
+		BlockNumber blocknum;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		if (range->nblocks == lengthof(range->buffers))
+		{
+			/* Start as much of it as we can. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/* If we're now at the I/O limit, stop here. */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+				return;
+
+			/*
+			 * That might have only been partially started, but always
+			 * processes at least one so that'll do for now.
+			 */
+			Assert(range->nblocks < lengthof(range->buffers));
+		}
+
+		/* Find per-buffer data slot for the next block. */
+		per_buffer_data = get_per_buffer_data(pgsr, range, range->nblocks);
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pg_streaming_get_block(pgsr, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			/* End of stream. */
+			pgsr->finished = true;
+			break;
+		}
+
+		/*
+		 * Is there a head range that we cannot extend, because the requested
+		 * block is not consecutive?
+		 */
+		if (range->nblocks > 0 &&
+			range->blocknum + range->nblocks != blocknum)
+		{
+			/* Yes.  Start it, so we can begin building a new one. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * It's possible that it was only partially started, and we have a
+			 * new range with the remainder.  Keep starting I/Os until we get
+			 * it all out of the way, or we hit the I/O limit.
+			 */
+			while (range->nblocks > 0 && pgsr->ios_in_progress < pgsr->max_ios)
+				range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * We do have to worry about I/O capacity running out if the head
+			 * range was split.  In that case we have to 'unget' the block
+			 * returned by the callback.
+			 */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+			{
+				pg_streaming_unget_block(pgsr, blocknum, per_buffer_data);
+				return;
+			}
+		}
+
+		/* If we have a new, empty range, initialize the start block. */
+		if (range->nblocks == 0)
+			range->blocknum = blocknum;
+
+		/* This block extends the range by one. */
+		Assert(range->blocknum + range->nblocks == blocknum);
+		range->nblocks++;
+	};
+
+	/*
+	 * Normally we don't start the head range, preferring to give it a chance
+	 * to grow to full size once more buffers have been consumed.  In cases
+	 * where that can't possibly happen, we might as well start the read
+	 * immediately.
+	 */
+	if ((range->nblocks > 0 && pgsr->finished) ||
+		(range->nblocks == pgsr->distance))
+		pg_streaming_read_start_head_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	PgStreamingReadRange *tail_range;
+
+	for (;;)
+	{
+		if (pgsr->tail != pgsr->head)
+		{
+			tail_range = &pgsr->ranges[pgsr->tail];
+
+			/*
+			 * Do we need to wait for a ReadBuffers operation to finish before
+			 * returning the buffers in this range?
+			 */
+			if (tail_range->need_wait)
+			{
+				int			distance;
+
+				Assert(pgsr->next_tail_buffer == 0);
+				WaitReadBuffers(&tail_range->operation);
+				tail_range->need_wait = false;
+
+				/*
+				 * We don't really know if the kernel generated a physical I/O
+				 * when we issued advice, let alone when it finished, but it
+				 * has certainly finished now because we've performed the
+				 * read.
+				 */
+				if (tail_range->advice_issued)
+				{
+
+					Assert(pgsr->ios_in_progress > 0);
+					pgsr->ios_in_progress--;
+
+					/*
+					 * Look-ahead distance ramps up rapidly if we're issuing
+					 * advice, so we can search for new more I/Os to start.
+					 */
+					distance = pgsr->distance * 2;
+					distance = Min(distance, pgsr->max_pinned_buffers);
+					pgsr->distance = distance;
+				}
+				else
+				{
+					/*
+					 * There is no point in increasing look-ahead distance if
+					 * we've already reached the full I/O size, since we're
+					 * not issuing advice.  Extra distance would only pin more
+					 * buffers for no benefit.
+					 */
+					if (pgsr->distance > MAX_BUFFERS_PER_TRANSFER)
+					{
+						/*
+						 * Look-ahead distance gradually decays to full I/O
+						 * size.
+						 */
+						pgsr->distance--;
+					}
+					else
+					{
+						/*
+						 * Look-ahead distance ramps up rapidly, but not more
+						 * that the full I/O size.
+						 */
+						distance = pgsr->distance * 2;
+						distance = Min(distance, MAX_BUFFERS_PER_TRANSFER);
+						distance = Min(distance, pgsr->max_pinned_buffers);
+						pgsr->distance = distance;
+					}
+				}
+			}
+			else if (pgsr->next_tail_buffer == 0)
+			{
+				/* No I/O necessary. Look-ahead distance gradually decays. */
+				if (pgsr->distance > 1)
+					pgsr->distance--;
+			}
+
+			/* Are there more buffers available in this range? */
+			if (pgsr->next_tail_buffer < tail_range->nblocks)
+			{
+				int			buffer_index;
+				Buffer		buffer;
+
+				buffer_index = pgsr->next_tail_buffer++;
+				buffer = tail_range->buffers[buffer_index];
+
+				Assert(BufferIsValid(buffer));
+
+				/* We are giving away ownership of this pinned buffer. */
+				Assert(pgsr->pinned_buffers > 0);
+				pgsr->pinned_buffers--;
+
+				if (per_buffer_data)
+					*per_buffer_data = get_per_buffer_data(pgsr, tail_range, buffer_index);
+
+				/* We may be able to get another I/O started. */
+				pg_streaming_read_look_ahead(pgsr);
+
+				return buffer;
+			}
+
+			/* Advance tail to next range. */
+			if (++pgsr->tail == pgsr->size)
+				pgsr->tail = 0;
+			pgsr->next_tail_buffer = 0;
+		}
+		else
+		{
+			/*
+			 * If tail crashed into head, and head is not empty, then it is
+			 * time to start that range.  Otherwise, force a look-ahead, to
+			 * kick start the stream.
+			 */
+			Assert(pgsr->tail == pgsr->head);
+			if (pgsr->ranges[pgsr->head].nblocks > 0)
+			{
+				pg_streaming_read_start_head_range(pgsr);
+			}
+			else
+			{
+				pg_streaming_read_look_ahead(pgsr);
+
+				/* Finished? */
+				if (pgsr->tail == pgsr->head &&
+					pgsr->ranges[pgsr->head].nblocks == 0)
+					break;
+			}
+		}
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead. */
+	pgsr->finished = true;
+
+	/* Unpin anything that wasn't consumed. */
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	Assert(pgsr->pinned_buffers == 0);
+	Assert(pgsr->ios_in_progress == 0);
+
+	/* Release memory. */
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f0f8d4259c..d0e9c7deff 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -19,6 +19,11 @@
  *		and pin it so that no one can destroy it while this process
  *		is using it.
  *
+ * StartReadBuffers() -- as above, but for multiple contiguous blocks in
+ *		two steps.
+ *
+ * WaitReadBuffers() -- second step of StartReadBuffers().
+ *
  * ReleaseBuffer() -- unpin a buffer
  *
  * MarkBufferDirty() -- mark a pinned buffer's contents as "dirty".
@@ -471,10 +476,9 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
-								ReadBufferMode mode, BufferAccessStrategy strategy,
-								bool *hit);
+								ReadBufferMode mode, BufferAccessStrategy strategy);
 static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
 										   ForkNumber fork,
 										   BufferAccessStrategy strategy,
@@ -500,7 +504,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -781,7 +785,6 @@ Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
-	bool		hit;
 	Buffer		buf;
 
 	/*
@@ -794,15 +797,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
-							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+	buf = ReadBuffer_common(BMR_REL(reln),
+							forkNum, blockNum, mode, strategy);
+
 	return buf;
 }
 
@@ -822,13 +819,12 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 						  BlockNumber blockNum, ReadBufferMode mode,
 						  BufferAccessStrategy strategy, bool permanent)
 {
-	bool		hit;
-
 	SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
-							 mode, strategy, &hit);
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
+							 mode, strategy);
 }
 
 /*
@@ -994,35 +990,68 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 	 */
 	if (buffer == InvalidBuffer)
 	{
-		bool		hit;
-
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
-								   fork, extend_to - 1, mode, strategy,
-								   &hit);
+		buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
 	}
 
 	return buffer;
 }
 
+/*
+ * Zero a buffer and lock it, as part of the implementation of
+ * RBM_ZERO_AND_LOCK or RBM_ZERO_AND_CLEANUP_LOCK.  The buffer must be already
+ * pinned.  It does not have to be valid, but it is valid and locked on
+ * return.
+ */
+static void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * ReadBuffer_common -- common logic for all ReadBuffer variants
  *
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
-				  BufferAccessStrategy strategy, bool *hit)
+				  BufferAccessStrategy strategy)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	ReadBuffersOperation operation;
+	Buffer		buffer;
+	int			nblocks;
+	int			flags;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1041,181 +1070,405 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	nblocks = 1;
+	if (mode == RBM_ZERO_ON_ERROR)
+		flags = READ_BUFFERS_ZERO_ON_ERROR;
+	else
+		flags = 0;
+	if (StartReadBuffers(bmr,
+						 &buffer,
+						 forkNum,
+						 blockNum,
+						 &nblocks,
+						 strategy,
+						 flags,
+						 &operation))
+		WaitReadBuffers(&operation);
+	Assert(nblocks == 1);		/* single block can't be short */
+
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+		ZeroBuffer(buffer, mode);
+
+	return buffer;
+}
 
+static Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	Assert(bmr.smgr);
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * WaitReadBuffers() (so, not for hits, and not for buffers that are
+		 * zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+/*
+ * Begin reading a range of blocks beginning at blockNum and extending for
+ * *nblocks.  On return, up to *nblocks pinned buffers holding those blocks
+ * are written into the buffers array, and *nblocks is updated to contain the
+ * actual number, which may be fewer than requested.
+ *
+ * If false is returned, no I/O is necessary and WaitReadBuffers() is not
+ * necessary.  If true is returned, one I/O has been started, and
+ * WaitReadBuffers() must be called with the same operation object before the
+ * buffers are accessed.  Along with the operation object, the caller-supplied
+ * array of buffers must remain valid until WaitReadBuffers() is called.
+ *
+ * Currently the I/O is only started with optional operating system advice,
+ * and the real I/O happens in WaitReadBuffers().  In future work, true I/O
+ * could be initiated here.
+ */
+bool
+StartReadBuffers(BufferManagerRelation bmr,
+				 Buffer *buffers,
+				 ForkNumber forkNum,
+				 BlockNumber blockNum,
+				 int *nblocks,
+				 BufferAccessStrategy strategy,
+				 int flags,
+				 ReadBuffersOperation *operation)
+{
+	int			actual_nblocks = *nblocks;
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
 	}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+	operation->bmr = bmr;
+	operation->forknum = forkNum;
+	operation->blocknum = blockNum;
+	operation->buffers = buffers;
+	operation->nblocks = actual_nblocks;
+	operation->strategy = strategy;
+	operation->flags = flags;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	operation->io_buffers_len = 0;
 
-	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
-	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
-	else
+	for (int i = 0; i < actual_nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		bool		found;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+		buffers[i] = PrepareReadBuffer(bmr,
+									   forkNum,
+									   blockNum + i,
+									   strategy,
+									   &found);
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		if (found)
+		{
+			/*
+			 * Terminate the read as soon as we get a hit.  It could be a
+			 * single buffer hit, or it could be a hit that follows a readable
+			 * range.  We don't want to create more than one readable range,
+			 * so we stop here.
+			 */
+			actual_nblocks = operation->nblocks = *nblocks = i + 1;
+			break;
+		}
+		else
+		{
+			/* Extend the readable range to cover this block. */
+			operation->io_buffers_len++;
+		}
+	}
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+	if (operation->io_buffers_len > 0)
+	{
+		if (flags & READ_BUFFERS_ISSUE_ADVICE)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
-			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
-			}
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
+			/*
+			 * In theory we should only do this if PrepareReadBuffers() had to
+			 * allocate new buffers above.  That way, if two calls to
+			 * StartReadBuffers() were made for the same blocks before
+			 * WaitReadBuffers(), only the first would issue the advice.
+			 * That'd be a better simulation of true asynchronous I/O, which
+			 * would only start the I/O once, but isn't done here for
+			 * simplicity.  Note also that the following call might actually
+			 * issue two advice calls if we cross a segment boundary; in a
+			 * true asynchronous version we might choose to process only one
+			 * real I/O at a time in that case.
+			 */
+			smgrprefetch(bmr.smgr, forkNum, blockNum, operation->io_buffers_len);
 		}
+
+		/* Indicate that WaitReadBuffers() should be called. */
+		return true;
 	}
+	else
+	{
+		return false;
+	}
+}
 
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
+static inline bool
+WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
 	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
+
+void
+WaitReadBuffers(ReadBuffersOperation *operation)
+{
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	int			nblocks;
+	BlockNumber blocknum;
+	ForkNumber	forknum;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	/*
+	 * Currently operations are only allowed to include a read of some range,
+	 * with an optional extra buffer that is already pinned at the end.  So
+	 * nblocks can be at most one more than io_buffers_len.
+	 */
+	Assert((operation->nblocks == operation->io_buffers_len) ||
+		   (operation->nblocks == operation->io_buffers_len + 1));
 
+	/* Find the range of the physical read we need to perform. */
+	nblocks = operation->io_buffers_len;
+	if (nblocks == 0)
+		return;					/* nothing to do */
+
+	buffers = &operation->buffers[0];
+	blocknum = operation->blocknum;
+	forknum = operation->forknum;
+	bmr = operation->bmr;
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
-
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
 	}
 	else
 	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
+		io_context = IOContextForStrategy(operation->strategy);
+		io_object = IOOBJECT_RELATION;
 	}
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+	/*
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
+	 */
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
+	else
+		pgBufferUsage.shared_blks_read += nblocks;
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+	for (int i = 0; i < nblocks; ++i)
+	{
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!WaitReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
+
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   WaitReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
+		{
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
+			{
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
+			}
+			else
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
+
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
+
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
+
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
+
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
- * BufferAlloc -- subroutine for ReadBuffer.  Handles lookup of a shared
- *		buffer.  If no buffer exists already, selects a replacement
- *		victim and evicts the old page, but does NOT read in new page.
+ * BufferAlloc -- subroutine for StartReadBuffers.  Handles lookup of a shared
+ *		buffer.  If no buffer exists already, selects a replacement victim and
+ *		evicts the old page, but does NOT read in new page.
  *
  * "strategy" can be a buffer replacement strategy object, or NULL for
  * the default strategy.  The selected buffer's usage_count is advanced when
@@ -1223,11 +1476,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1286,19 +1535,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1363,19 +1603,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1407,15 +1638,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1769,7 +1994,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2034,7 +2259,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2057,7 +2282,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2372,7 +2597,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if StartReadBuffers() was called and
+		 * WaitReadBuffers() hasn't been called yet.  We'll check by loading
+		 * the flags without locking.  This is racy, but it's OK to return
+		 * false spuriously: when WaitReadBuffers() calls StartBufferIO(),
+		 * it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2381,7 +2611,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3449,7 +3679,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -5184,9 +5414,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5199,6 +5435,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index fcfac335a5..985a2c7049 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -108,10 +108,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -287,7 +286,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -297,9 +296,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca2..739d13293f 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d335..b57f71f97e 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,42 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+
+#define READ_BUFFERS_ZERO_ON_ERROR 0x01
+#define READ_BUFFERS_ISSUE_ADVICE 0x02
+
+/*
+ * Private state used by StartReadBuffers() and WaitReadBuffers().  Declared
+ * in public header only to allow inclusion in other structs, but contents
+ * should not be accessed.
+ */
+struct ReadBuffersOperation
+{
+	/* Parameters passed in to StartReadBuffers(). */
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	ForkNumber	forknum;
+	BlockNumber blocknum;
+	int			nblocks;
+	BufferAccessStrategy strategy;
+	int			flags;
+
+	/* Range of buffers, if we need to perform a read. */
+	int			io_buffers_len;
+};
+
+typedef struct ReadBuffersOperation ReadBuffersOperation;
+
+extern bool StartReadBuffers(BufferManagerRelation bmr,
+							 Buffer *buffers,
+							 ForkNumber forknum,
+							 BlockNumber blocknum,
+							 int *nblocks,
+							 BufferAccessStrategy strategy,
+							 int flags,
+							 ReadBuffersOperation *operation);
+extern void WaitReadBuffers(ReadBuffersOperation *operation);
+
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -250,6 +292,9 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 0000000000..c4d3892bb2
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,52 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+/*
+ * We usually ramp up from smaller reads to larger ones, to support users who
+ * don't know if it's worth reading lots of buffers yet.  This flag disables
+ * that, declaring ahead of time that we'll be reading all available buffers.
+ */
+#define PGSR_FLAG_FULL 0x04
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 58317eac44..162fe9300a 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2116,6 +2116,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
@@ -2287,6 +2289,7 @@ ReInitializeDSMForeignScan_function
 ReScanForeignScan_function
 ReadBufPtrType
 ReadBufferMode
+ReadBuffersOperation
 ReadBytePtrType
 ReadExtraTocPtrType
 ReadFunc
-- 
2.40.1

v9-0017-BitmapHeapScan-uses-streaming-read-API.patchtext/x-diff; charset=us-asciiDownload
From f206f41cf66d80882724a96ab3ac9970e25bffc1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 16:51:40 -0400
Subject: [PATCH v9 17/17] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  96 ++++--
 src/backend/access/heap/heapam_handler.c  | 346 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  44 +--
 src/include/access/heapam.h               |  16 +-
 src/include/access/relscan.h              |   7 -
 src/include/access/tableam.h              |  16 -
 src/include/nodes/execnodes.h             |   9 +-
 7 files changed, 116 insertions(+), 418 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 9ddbaff4e2..0ed820e045 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -111,6 +111,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -333,6 +335,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -953,16 +971,9 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-
-	scan->rs_base.blockno = InvalidBlockNumber;
-
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
-	scan->pvmbuffer = InvalidBuffer;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1045,12 +1056,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
-	scan->rs_base.blockno = InvalidBlockNumber;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
-
 	/*
 	 * unpin scan buffers
 	 */
@@ -1063,12 +1068,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1094,12 +1093,6 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
@@ -1117,6 +1110,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10274,3 +10270,51 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		bhs_iterate(hdesc->rs_base.rs_tbmiterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(hdesc->rs_base.rs_flags & SO_NEED_TUPLE) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 9dfc99d8fa..fe9ee5976f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,10 +56,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
-static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
-static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
-static inline void BitmapPrefetch(HeapScanDesc scan);
-
 static const TableAmRoutine heapam_methods;
 
 
@@ -2110,146 +2106,68 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (scan->rs_base.rs_pf_tbmiterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-			scan->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
-	 * parallel workers.
-	 */
-	if (scan->rs_base.prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (scan->rs_base.rs_pf_tbmiterator)
-			{
-				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-				scan->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno,
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(hscan);
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		bhs_iterate(scan->rs_tbmiterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2270,7 +2188,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,9 +2197,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2331,23 +2249,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->bm_parallel == NULL &&
-		scan->rs_pf_tbmiterator &&
-		hscan->pfblockno > hscan->rs_base.blockno)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(hscan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2358,152 +2264,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= prefetch_maximum / 2)
-			scan->prefetch_target = prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= prefetch_maximum / 2)
-			pstate->prefetch_target = prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-
-	if (pstate == NULL)
-	{
-		if (scan->rs_base.rs_pf_tbmiterator)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
-					scan->rs_base.rs_pf_tbmiterator = NULL;
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (scan->rs_base.rs_pf_tbmiterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
-					scan->rs_base.rs_pf_tbmiterator = NULL;
-					break;
-				}
-
-				scan->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
@@ -2538,41 +2298,11 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 			return true;
 		}
 
-		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
 										   lossy_pages, exact_pages))
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!scan->bm_parallel)
-	{
-		if (hscan->prefetch_target < scan->prefetch_maximum)
-			hscan->prefetch_target++;
-	}
-	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&scan->bm_parallel->mutex);
-		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-			scan->bm_parallel->prefetch_target++;
-		SpinLockRelease(&scan->bm_parallel->mutex);
-	}
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(hscan);
-#endif							/* USE_PREFETCH */
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2683d8bc0c..c21dae466a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -128,14 +128,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -146,15 +138,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-		int			pf_maximum = 0;
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
-#endif
-
 		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -171,13 +154,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					node->pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
+
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(node->pstate);
 			}
@@ -210,17 +187,10 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
 		scan->rs_tbmiterator = bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
 
-#ifdef USE_PREFETCH
-		if (scan->prefetch_maximum > 0)
-			bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
-#endif							/* USE_PREFETCH */
-
-
 		node->initialized = true;
 	}
 
@@ -319,7 +289,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
 	node->tbm = NULL;
@@ -363,7 +333,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
@@ -519,14 +489,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -557,11 +523,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 22bdccc2a9..1cad9c04f0 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -81,18 +85,6 @@ typedef struct HeapScanDescData
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-	/* buffer for visibility-map lookups of prefetched pages */
-	Buffer		pvmbuffer;
-
-	/*
-	 * These fields only used for prefetching in bitmap table scans
-	 */
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
-	/* used to validate prefetch block stays ahead of current block */
-	BlockNumber pfblockno;
 
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 65092d7226..00a123ee92 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -57,15 +57,8 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	BitmapHeapIterator *rs_tbmiterator;
-	/* Prefetch iterator */
-	BitmapHeapIterator *rs_pf_tbmiterator;
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
 
-	/* used to validate prefetch and current block stay in sync */
-	BlockNumber blockno;
-
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5ad3eff539..4bc021f0eb 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -933,7 +933,6 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_tbmiterator = NULL;
-	result->rs_pf_tbmiterator = NULL;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -999,13 +998,6 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_tbmiterator);
 		scan->rs_tbmiterator = NULL;
-#ifdef USE_PREFETCH
-		if (scan->rs_pf_tbmiterator)
-		{
-			bhs_end_iterate(scan->rs_pf_tbmiterator);
-			scan->rs_pf_tbmiterator = NULL;
-		}
-#endif
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1022,14 +1014,6 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_tbmiterator);
 		scan->rs_tbmiterator = NULL;
-
-#ifdef USE_PREFETCH
-		if (scan->rs_pf_tbmiterator)
-		{
-			bhs_end_iterate(scan->rs_pf_tbmiterator);
-			scan->rs_pf_tbmiterator = NULL;
-		}
-#endif
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 7a3fdf9cd4..c1778653c7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1758,11 +1758,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1770,10 +1766,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.40.1

#74Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#73)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/24/24 18:38, Melanie Plageman wrote:

On Sun, Mar 24, 2024 at 01:36:19PM +0100, Tomas Vondra wrote:

On 3/23/24 01:26, Melanie Plageman wrote:

On Fri, Mar 22, 2024 at 08:22:11PM -0400, Melanie Plageman wrote:

On Tue, Mar 19, 2024 at 02:33:35PM +0200, Heikki Linnakangas wrote:

On 18/03/2024 17:19, Melanie Plageman wrote:

I've attached v7 rebased over this commit.

If we delayed table_beginscan_bm() call further, after starting the TBM
iterator, we could skip it altogether when the iterator is empty.

That's a further improvement, doesn't need to be part of this patch set.
Just caught my eye while reading this.

Hmm. You mean like until after the first call to tbm_[shared]_iterate()?
AFAICT, tbm_begin_iterate() doesn't tell us anything about whether or
not the iterator is "empty". Do you mean cases when the bitmap has no
blocks in it? It seems like we should be able to tell that from the
TIDBitmap.

v7-0003-Push-BitmapHeapScan-skip-fetch-optimization-into-.patch

I suggest to avoid the double negative with SO_CAN_SKIP_FETCH, and call the
flag e.g. SO_NEED_TUPLE.

Agreed. Done in attached v8. Though I wondered if it was a bit weird
that the flag is set in the common case and not set in the uncommon
case...

v8 actually attached this time

I tried to run the benchmarks with v8, but unfortunately it crashes for
me very quickly (I've only seen 0015 to crash, so I guess the bug is in
that patch).

The backtrace attached, this doesn't seem right:

(gdb) p hscan->rs_cindex
$1 = 543516018

Thanks for reporting this! I hadn't seen it crash on my machine, so I
didn't realize that I was no longer initializing rs_cindex and
rs_ntuples on the first call to heapam_bitmap_next_tuple() (since
heapam_bitmap_next_block() wasn't being called first). I've done this in
attached v9.

OK, I've restarted the tests with v9.

I haven't had a chance yet to reproduce the regressions you saw in the
streaming read user patch or to look closely at the performance results.

So you tried to reproduce it and didn't hit the issue? Or didn't have
time to look into that yet? FWIW with v7 it failed almost immediately
(only a couple queries until hitting one triggering the issue), but v9
that's not the case (hundreds of queries without an error).

I don't anticipate the streaming read user will have any performance
differences in this v9 from v6, since I haven't yet rebased in Thomas'
latest streaming read API changes nor addressed any other potential
regression sources.

OK, understood. It'll be interesting to see the behavior with the new
version of Thomas' patch.

I however wonder what the plan with these patches is - do we still plan
to get some of this into v17? It seems to me we're getting uncomfortably
close to the end of the cycle, with a fairly incomplete idea of how it
affects performance.

Which is why I've been focusing more on the refactoring patches (up to
0015), to make sure those don't cause regressions if committed. And I
think that's generally true.

But for the main StreamingRead API the situation is very different.

I tried rebasing in Thomas' latest version today and something is
causing a crash that I have yet to figure out. v10 of this patchset will
have his latest version once I get that fixed. I wanted to share this
version with what I think is a bug fix for the crash you saw first.

Understood. I'll let the tests with v9 run for now.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#75Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#74)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Mar 24, 2024 at 2:22 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/24/24 18:38, Melanie Plageman wrote:

I haven't had a chance yet to reproduce the regressions you saw in the
streaming read user patch or to look closely at the performance results.

So you tried to reproduce it and didn't hit the issue? Or didn't have
time to look into that yet? FWIW with v7 it failed almost immediately
(only a couple queries until hitting one triggering the issue), but v9
that's not the case (hundreds of queries without an error).

I haven't started trying to reproduce it yet.

I however wonder what the plan with these patches is - do we still plan
to get some of this into v17? It seems to me we're getting uncomfortably
close to the end of the cycle, with a fairly incomplete idea of how it
affects performance.

Which is why I've been focusing more on the refactoring patches (up to
0015), to make sure those don't cause regressions if committed. And I
think that's generally true.

Thank you for testing the refactoring patches with this in mind! Out
of the refactoring patches, I think there is a subset of them that
have independent value without the streaming read user. I think it is
worth committing the first few patches because they remove a table AM
layering violation. IMHO, all of the patches up to "Make
table_scan_bitmap_next_block() async friendly" make the code nicer and
better. And, if folks like the patch "Remove
table_scan_bitmap_next_block()", then I think I could rebase that back
in on top of "Make table_scan_bitmap_next_block() async friendly".
This would mean table AMs would only have to implement one callback
(table_scan_bitmap_next_tuple()) which I also think is a net
improvement and simplification.

The other refactoring patches may not be interesting without the
streaming read user.

But for the main StreamingRead API the situation is very different.

My intent for the bitmapheapscan streaming read user was to get it
into 17, but I'm not sure that looks likely. The main issues Thomas is
looking into right now are related to regressions for a fully cached
scan (noticeable with the pg_prewarm streaming read user). With all of
these fixed, I anticipate we will still see enough behavioral
differences with the bitmapheap scan streaming read user that it may
not be committable in time. Though, I have yet to work on reproducing
the regressions with the BHS streaming read user mostly because I was
focused on getting the refactoring ready and not as much because the
streaming read API is unstable.

- Melanie

#76Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#75)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/24/24 21:12, Melanie Plageman wrote:

On Sun, Mar 24, 2024 at 2:22 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/24/24 18:38, Melanie Plageman wrote:

I haven't had a chance yet to reproduce the regressions you saw in the
streaming read user patch or to look closely at the performance results.

So you tried to reproduce it and didn't hit the issue? Or didn't have
time to look into that yet? FWIW with v7 it failed almost immediately
(only a couple queries until hitting one triggering the issue), but v9
that's not the case (hundreds of queries without an error).

I haven't started trying to reproduce it yet.

I however wonder what the plan with these patches is - do we still plan
to get some of this into v17? It seems to me we're getting uncomfortably
close to the end of the cycle, with a fairly incomplete idea of how it
affects performance.

Which is why I've been focusing more on the refactoring patches (up to
0015), to make sure those don't cause regressions if committed. And I
think that's generally true.

Thank you for testing the refactoring patches with this in mind! Out
of the refactoring patches, I think there is a subset of them that
have independent value without the streaming read user. I think it is
worth committing the first few patches because they remove a table AM
layering violation. IMHO, all of the patches up to "Make
table_scan_bitmap_next_block() async friendly" make the code nicer and
better. And, if folks like the patch "Remove
table_scan_bitmap_next_block()", then I think I could rebase that back
in on top of "Make table_scan_bitmap_next_block() async friendly".
This would mean table AMs would only have to implement one callback
(table_scan_bitmap_next_tuple()) which I also think is a net
improvement and simplification.

The other refactoring patches may not be interesting without the
streaming read user.

I admit not reviewing the individual patches very closely yet, but this
matches how I understood them - that at least some are likely an
improvement on their own, not just as a refactoring preparing for the
switch to streaming reads.

We only have ~2 weeks left, so it's probably time to focus on getting at
least those improvements committed. I see Heikki was paying way more
attention to the patches than me, though ...

BTW when you say "up to 'Make table_scan_bitmap_next_block() async
friendly'" do you mean including that patch, or that this is the first
patch that is not one of the independently useful patches.

(I took a quick look at the first couple patches and I appreciate that
you keep separate patches with small cosmetic changes to keep the actual
patch smaller and easier to understand.)

But for the main StreamingRead API the situation is very different.

My intent for the bitmapheapscan streaming read user was to get it
into 17, but I'm not sure that looks likely. The main issues Thomas is
looking into right now are related to regressions for a fully cached
scan (noticeable with the pg_prewarm streaming read user). With all of
these fixed, I anticipate we will still see enough behavioral
differences with the bitmapheap scan streaming read user that it may
not be committable in time. Though, I have yet to work on reproducing
the regressions with the BHS streaming read user mostly because I was
focused on getting the refactoring ready and not as much because the
streaming read API is unstable.

I don't have a very good intuition regarding impact of the streaming API
patch on performance. I haven't been following that thread very closely,
but AFAICS there wasn't much discussion about that - perhaps it happened
offlist, not sure. So who knows, really?

Which is why I started looking at this patch instead - it seemed easier
to benchmark with a somewhat realistic workload.

But yeah, there certainly were significant behavior changes, and it's
unlikely that whatever Thomas did in v8 made them go away.

FWIW I certainly am *not* suggesting there must be no behavior changes,
that's simply not possible. I'm not even suggesting no queries must get
slower - given the dependence on storage, I think some regressions are
pretty much inevitable. But it's still be good to know the regressions
are reasonably rare exceptions rather than the common case, and that's
not what I'm seeing ...

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#77Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#76)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Mar 24, 2024 at 5:59 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

BTW when you say "up to 'Make table_scan_bitmap_next_block() async
friendly'" do you mean including that patch, or that this is the first
patch that is not one of the independently useful patches.

I think the code is easier to understand with "Make
table_scan_bitmap_next_block() async friendly". Prior to that commit,
table_scan_bitmap_next_block() could return false even when the bitmap
has more blocks and expects the caller to handle this and invoke it
again. I think that interface is very confusing. The downside of the
code in that state is that the code for prefetching is still in the
BitmapHeapNext() code and the code for getting the current block is in
the heap AM-specific code. I took a stab at fixing this in v9's 0013,
but the outcome wasn't very attractive.

What I will do tomorrow is reorder and group the commits such that all
of the commits that are useful independent of streaming read are first
(I think 0014 and 0015 are independently valuable but they are on top
of some things that are only useful to streaming read because they are
more recently requested changes). I think I can actually do a bit of
simplification in terms of how many commits there are and what is in
each. Just to be clear, v9 is still reviewable. I am just going to go
back and change what is included in each commit.

(I took a quick look at the first couple patches and I appreciate that
you keep separate patches with small cosmetic changes to keep the actual
patch smaller and easier to understand.)

Thanks!

#78Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#77)
17 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Mar 24, 2024 at 06:37:20PM -0400, Melanie Plageman wrote:

On Sun, Mar 24, 2024 at 5:59 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

BTW when you say "up to 'Make table_scan_bitmap_next_block() async
friendly'" do you mean including that patch, or that this is the first
patch that is not one of the independently useful patches.

I think the code is easier to understand with "Make
table_scan_bitmap_next_block() async friendly". Prior to that commit,
table_scan_bitmap_next_block() could return false even when the bitmap
has more blocks and expects the caller to handle this and invoke it
again. I think that interface is very confusing. The downside of the
code in that state is that the code for prefetching is still in the
BitmapHeapNext() code and the code for getting the current block is in
the heap AM-specific code. I took a stab at fixing this in v9's 0013,
but the outcome wasn't very attractive.

What I will do tomorrow is reorder and group the commits such that all
of the commits that are useful independent of streaming read are first
(I think 0014 and 0015 are independently valuable but they are on top
of some things that are only useful to streaming read because they are
more recently requested changes). I think I can actually do a bit of
simplification in terms of how many commits there are and what is in
each. Just to be clear, v9 is still reviewable. I am just going to go
back and change what is included in each commit.

So, attached v10 does not include the new version of streaming read API.
I focused instead on the refactoring patches commit regrouping I
mentioned here.

I realized "Remove table_scan_bitmap_next_block()" can't easily be moved
down below "Push BitmapHeapScan prefetch code into heapam.c" because we
have to do BitmapAdjustPrefetchTarget() and
BitmapAdjustPrefetchIterator() on either side of getting the next block
(via table_scan_bitmap_next_block()).

"Push BitmapHeapScan prefetch code into heapam.c" isn't very nice
because it adds a lot of bitmapheapscan specific members to
TableScanDescData and HeapScanDescData. I thought about wrapping all of
those members in some kind of BitmapHeapScanTableState struct -- but I
don't like that because the members are spread out across
HeapScanDescData and TableScanDescData so not all of them would go in
BitmapHeapScanTableState. I could move the ones I put in
HeapScanDescData back into TableScanDescData and then wrap that in a
BitmapHeapScanTableState. I haven't done that in this version.

I did manage to move "Unify parallel and serial BitmapHeapScan iterator
interfaces" down below the line of patches which are only useful if
the streaming read user also goes in.

In attached v10, all patches up to and including "Unify parallel and
serial BitmapHeapScan iterator interfaces" (0010) are proposed for
master with or without the streaming read API.

0010 does add additional indirection and thus pointer dereferencing for
accessing the iterators, which doesn't feel good. But, it does simplify
the code.

Perhaps it is worth renaming the existing TableScanDescData->rs_parallel
(a ParallelTableScanDescData) to something like rs_seq_parallel. It is
only for sequential scans and scans of tables when building indexes but
the comments say it is for parallel scans in general. There is a similar
member in HeapScanDescData called rs_parallelworkerdata.

- Melanie

Attachments:

v10-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From 62f6c877d130325748bf18724fc8166932605091 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v10 01/17] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index e57a0b7ea3..e78d793f69 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aab..93fdcd226b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v10-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From c6ed55265735c2d2a47da1fc6339d3cc1db954e4 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v10 02/17] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 93fdcd226b..c64530674b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -742,16 +752,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v10-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From 844cfbb2c2700da1fd8a290776523190e9c73ef9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v10 03/17] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index cc67dd813d..6b2863391f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -948,6 +948,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1036,6 +1038,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1055,6 +1063,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2b7c702642..7fdccaf613 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2124,6 +2125,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2236,6 +2255,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c64530674b..83d9db8f39 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,11 +185,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	node->ss.ps.state->es_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	extra_flags);
 		}
 
 		node->initialized = true;
@@ -207,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -228,37 +232,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -301,52 +282,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +531,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +601,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +610,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +654,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -740,8 +697,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +707,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 368c570a0f..cef54e2d5d 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 65834caeb1..1bc5f7c057 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -952,9 +959,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 1774c56ae3..6871db9b21 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1785,10 +1785,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1808,9 +1805,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v10-0004-BitmapPrefetch-use-prefetch-block-recheck-for-sk.patchtext/x-diff; charset=us-asciiDownload
From 8075018e79311547895034ef25be5294aee9e9fb Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v10 04/17] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 83d9db8f39..5df3b5ca46 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -474,14 +474,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -532,7 +527,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v10-0005-Update-BitmapAdjustPrefetchIterator-parameter-ty.patchtext/x-diff; charset=us-asciiDownload
From 370a50ea551d440476160e083a20ac356bb35c0a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v10 05/17] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5df3b5ca46..404de0595e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -230,7 +230,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -341,7 +341,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -360,7 +360,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v10-0006-table_scan_bitmap_next_block-returns-lossy-or-ex.patchtext/x-diff; charset=us-asciiDownload
From 1538728ba1424299360e5845afbbf51ecebf5947 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v10 06/17] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7fdccaf613..849cac3947 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,7 +2114,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2242,6 +2243,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 404de0595e..c95e3412da 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
+		bool		valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -232,12 +232,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1bc5f7c057..b9ba4f9fb3 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -804,6 +804,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -819,7 +822,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1988,14 +1992,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2006,7 +2012,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.40.1

v10-0007-Reduce-scope-of-BitmapHeapScan-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From b03464c30573a28e1f2e5e0915e75dc26a823a3d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v10 07/17] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c95e3412da..49938c9ed4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +202,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -221,9 +219,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v10-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From 1c32c668a87649990c072dbdde69f14d8ba6b2ce Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v10 08/17] Remove table_scan_bitmap_next_tuple parameter
 tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 849cac3947..cf4387f443 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2250,7 +2250,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 49938c9ed4..282dcb9791 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -286,7 +286,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b9ba4f9fb3..bcf1497f67 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -795,10 +795,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -829,15 +826,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2025,7 +2017,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2037,7 +2028,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v10-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 9f6b3738ac4f6648d830168d8659aa49510baecc Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v10 09/17] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 195 insertions(+), 149 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index cf4387f443..2ad785e511 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,18 +2114,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2144,16 +2177,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2245,7 +2269,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 282dcb9791..7e73583fe5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +109,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +161,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -202,55 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool		valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -272,45 +232,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno > node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,13 +311,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -356,14 +335,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -388,7 +370,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -466,6 +451,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -523,6 +509,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -584,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -597,13 +581,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -634,28 +618,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -688,8 +668,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -697,9 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304a..92b829cebc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index bcf1497f67..a820cc8c99 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -788,19 +789,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -819,8 +815,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -957,9 +953,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1019,6 +1019,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1029,6 +1044,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1981,19 +2011,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2003,8 +2031,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6871db9b21..8688bc5ab0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1783,8 +1783,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1793,9 +1791,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1803,8 +1803,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1813,9 +1811,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v10-0010-Unify-parallel-and-serial-BitmapHeapScan-iterato.patchtext/x-diff; charset=us-asciiDownload
From 64d69f1249731b740c510cd86163517a8b1320ec Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 25 Mar 2024 11:05:51 -0400
Subject: [PATCH v10 10/17] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to both
TBMIterator and TBMSharedIterators. This encapsulates the parallel and serial
iterators and their access and makes the bitmap heap scan code a bit cleaner.
This naturally lends itself to a bit of reorganization of the
!node->initialized path in BitmapHeapNext(). Now, on the first scan, the the
iterator is created after the scan descriptor is created.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 163 ++++++++++++----------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  29 +---
 src/include/executor/nodeBitmapHeapscan.h |  10 ++
 src/include/nodes/execnodes.h             |   8 +-
 src/tools/pgindent/typedefs.list          |   1 +
 7 files changed, 116 insertions(+), 107 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2ad785e511..c76849a98e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2133,10 +2133,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		tbmres = bhs_iterate(scan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 7e73583fe5..fe471a8a0c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -56,6 +56,56 @@ static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
+static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
+											 dsa_pointer shared_area,
+											 dsa_area *personal_area);
+
+BitmapHeapIterator *
+bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_area)
+{
+	BitmapHeapIterator *result = palloc(sizeof(BitmapHeapIterator));
+
+	result->serial = NULL;
+	result->parallel = NULL;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(shared_area))
+		result->parallel = tbm_attach_shared_iterate(personal_area, shared_area);
+	else
+		result->serial = tbm_begin_iterate(tbm);
+
+	return result;
+}
+
+TBMIterateResult *
+bhs_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		return tbm_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
+
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+	{
+		tbm_end_iterate(iterator->serial);
+		iterator->serial = NULL;
+	}
+	else
+	{
+		tbm_end_shared_iterate(iterator->parallel);
+		iterator->parallel = NULL;
+	}
+
+	pfree(iterator);
+}
 
 
 /* ----------------------------------------------------------------
@@ -97,43 +147,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate)
+		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
+			if (init_shared_state)
 			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
@@ -154,21 +184,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
 			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -198,8 +216,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  dsa);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			node->pf_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
+												  dsa);
+			/* Only used for serial BHS */
+			node->prefetch_pages = 0;
+			node->prefetch_target = -1;
+		}
+#endif							/* USE_PREFETCH */
 
 		node->initialized = true;
 
@@ -280,7 +311,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			node->pf_iterator &&
 			node->pfblockno > node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -321,12 +352,11 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
@@ -335,7 +365,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = bhs_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -348,8 +378,6 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -371,7 +399,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -431,23 +459,22 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 				node->prefetch_pages++;
@@ -475,8 +502,6 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (1)
@@ -500,12 +525,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 
@@ -572,18 +597,17 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	if (node->pf_iterator)
+	{
+		bhs_end_iterate(node->pf_iterator);
+		node->pf_iterator = NULL;
+	}
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -628,12 +652,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+	if (node->pf_iterator)
+		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -671,11 +693,10 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
+	scanstate->pf_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc..fb22f305bf 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,12 +20,12 @@
 #include "storage/buf.h"
 #include "storage/spin.h"
 #include "utils/relcache.h"
+#include "executor/nodeBitmapHeapscan.h"
 
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
-struct TBMSharedIterator;
+struct BitmapHeapIterator;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -44,8 +44,7 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	struct BitmapHeapIterator *rs_bhs_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a820cc8c99..29387166c1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -957,8 +957,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
+	result->rs_bhs_iterator = NULL;
 	return result;
 }
 
@@ -1021,17 +1020,8 @@ table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1046,17 +1036,8 @@ table_rescan(TableScanDesc scan,
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index ea003a9caa..cb56d20dc6 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -28,5 +28,15 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 										  ParallelContext *pcxt);
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+} BitmapHeapIterator;
+
+extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
+
 
 #endif							/* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8688bc5ab0..52cedd1b35 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1778,6 +1778,8 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
+struct BitmapHeapIterator;
+
 /* ----------------
  *	 BitmapHeapScanState information
  *
@@ -1786,12 +1788,11 @@ typedef struct ParallelBitmapHeapState
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
+ *		pf_iterator        for prefetching ahead of current page
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1806,12 +1807,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 4679660837..6d5cb0bdaa 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.40.1

v10-0011-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From 8776aa053a556d61303f9f6d4af6ce7bb6732121 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 17:09:12 -0400
Subject: [PATCH v10 11/17] table_scan_bitmap_next_block counts lossy and exact
 pages

Now that the table_scan_bitmap_next_block() callback only returns false
when the bitmap is exhausted, it is simpler to move the management of
the lossy and exact page counters into it. We will eventually remove
this callback and table_scan_bitmap_next_tuple() will update those
counters when a new block is read in.
---
 src/backend/access/heap/heapam_handler.c  |  8 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c |  9 ++-------
 src/include/access/tableam.h              | 21 +++++++++++++--------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c76849a98e..d85fee1e50 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2114,7 +2114,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+							  bool *recheck, BlockNumber *blockno,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block;
@@ -2264,7 +2265,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fe471a8a0c..076e1ff674 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -119,7 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	bool		lossy;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -298,14 +297,10 @@ new_page:
 
 		BitmapAdjustPrefetchIterator(node);
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+										  &node->lossy_pages, &node->exact_pages))
 			break;
 
-		if (lossy)
-			node->lossy_pages++;
-		else
-			node->exact_pages++;
-
 		/*
 		 * If serial, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 29387166c1..edc54ecffe 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,8 +797,8 @@ typedef struct TableAmRoutine
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * lossy indicates whether or not the block's representation in the bitmap
-	 * is lossy or exact.
+	 * lossy_pages is incremented if the block's representation in the bitmap
+	 * is lossy, otherwise, exact_pages is incremented.
 	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
@@ -815,8 +815,10 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+										   bool *recheck,
+										   BlockNumber *blockno,
+										   long *lossy_pages,
+										   long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1994,15 +1996,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap table scan.
  * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy is set to true
- * if bitmap is lossy for the selected block and false otherwise.
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented if bitmap is lossy for the selected block and exact_pages is
+ * incremented otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+							 bool *recheck, BlockNumber *blockno,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2013,7 +2017,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+														   blockno, lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v10-0012-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From c7e25c55056880848dea5f23ef62b859475f8973 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v10 12/17] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 33 +++++++--------------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 28 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fc..1dc4c99bf9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1463,12 +1449,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	TBMSharedIterator *iterator;
 	TBMSharedIteratorState *istate;
 
-	/*
-	 * Create the TBMSharedIterator struct, with enough trailing space to
-	 * serve the needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639b..432fae5296 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.40.1

v10-0013-Separate-TBM-Shared-Iterator-and-TBMIterateResul.patchtext/x-diff; charset=us-asciiDownload
From 99f7c9224046b021bc82a9f3d48048fd6916a29b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v10 13/17] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 30 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 47 ++++++++-------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/executor/nodeBitmapHeapscan.h |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 8 files changed, 113 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb..3aa457a29e 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544..033d525339 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d85fee1e50..105137396b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2122,7 +2122,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2134,9 +2134,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = bhs_iterate(scan->rs_bhs_iterator);
+		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2151,11 +2151,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2163,19 +2163,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2204,7 +2204,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2213,9 +2213,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2265,7 +2265,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 076e1ff674..78f79aafff 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -77,15 +77,16 @@ bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_ar
 	return result;
 }
 
-TBMIterateResult *
-bhs_iterate(BitmapHeapIterator *iterator)
+void
+bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result)
 {
 	Assert(iterator);
+	Assert(result);
 
 	if (iterator->serial)
-		return tbm_iterate(iterator->serial);
+		tbm_iterate(iterator->serial, result);
 	else
-		return tbm_shared_iterate(iterator->parallel);
+		tbm_shared_iterate(iterator->parallel, result);
 }
 
 void
@@ -348,7 +349,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
 	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -360,8 +361,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = bhs_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -394,8 +395,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = bhs_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -462,10 +463,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -473,7 +476,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -482,13 +485,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -501,7 +504,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -520,8 +523,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = bhs_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -529,17 +532,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1dc4c99bf9..309a44bdb8 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae..3b432263bb 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index cb56d20dc6..3c330f86e6 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -34,7 +34,7 @@ typedef struct BitmapHeapIterator
 	struct TBMSharedIterator *parallel;
 } BitmapHeapIterator;
 
-extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+extern void bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result);
 
 extern void bhs_end_iterate(BitmapHeapIterator *iterator);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae5296..f000c1af28 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.40.1

v10-0014-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchtext/x-diff; charset=us-asciiDownload
From 4d5dcb8783d92a2e2a37ea37bbf346545cd09337 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 09:42:23 -0400
Subject: [PATCH v10 14/17] Push BitmapHeapScan prefetch code into heapam.c

In preparation for transitioning to using the streaming read API for
prefetching [1], move all of the BitmapHeapScanState members related to
prefetching and the functions for accessing them into the
HeapScanDescData and TableScanDescData. Members that still need to be
accessed in BitmapHeapNext() could not be moved into heap AM-specific
code. Specifically, parallel iterator setup requires several components
which seem odd to pass to the table AM API.

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  26 ++
 src/backend/access/heap/heapam_handler.c  | 262 +++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 341 ++--------------------
 src/include/access/heapam.h               |  17 ++
 src/include/access/relscan.h              |   8 +
 src/include/access/tableam.h              |  26 +-
 src/include/nodes/execnodes.h             |  14 -
 7 files changed, 355 insertions(+), 339 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 6b2863391f..3d92fb5135 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -948,8 +948,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+
+	scan->rs_base.blockno = InvalidBlockNumber;
+
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
+	scan->pvmbuffer = InvalidBuffer;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1032,6 +1040,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
+	scan->rs_base.blockno = InvalidBlockNumber;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	/*
 	 * unpin scan buffers
 	 */
@@ -1044,6 +1058,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1069,6 +1089,12 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 105137396b..867061325c 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -55,6 +55,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
+static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2112,6 +2115,73 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+static inline void
+BitmapAdjustPrefetchIterator(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	TBMIterateResult tbmpre;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			scan->prefetch_pages--;
+		}
+		else if (prefetch_iterator)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblockno = tbmpre.blockno;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (scan->rs_base.prefetch_maximum > 0)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (prefetch_iterator)
+			{
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblockno = tbmpre.blockno;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  bool *recheck, BlockNumber *blockno,
@@ -2130,6 +2200,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(hscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2270,6 +2342,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->bm_parallel == NULL &&
+		scan->rs_pf_bhs_iterator &&
+		hscan->pfblockno > hscan->rs_base.blockno)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(hscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2280,6 +2364,154 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
+		else
+			scan->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+
+	if (pstate == NULL)
+	{
+		if (prefetch_iterator)
+		{
+			while (scan->prefetch_pages < scan->prefetch_target)
+			{
+				TBMIterateResult tbmpre;
+				bool		skip_fetch;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre.blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		if (prefetch_iterator)
+		{
+			while (1)
+			{
+				TBMIterateResult tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+
+				scan->pfblockno = tbmpre.blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
@@ -2305,6 +2537,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!scan->bm_parallel)
+	{
+		if (hscan->prefetch_target < scan->prefetch_maximum)
+			hscan->prefetch_target++;
+	}
+	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&scan->bm_parallel->mutex);
+		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+			scan->bm_parallel->prefetch_target++;
+		SpinLockRelease(&scan->bm_parallel->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(hscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 78f79aafff..187b288e68 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
 											 dsa_pointer shared_area,
@@ -122,7 +118,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
@@ -142,7 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
 	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
 	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
 	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
@@ -154,7 +149,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate || init_shared_state)
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		int			pf_maximum = 0;
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
+#endif
+
+		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
@@ -169,23 +173,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * dsa_pointer of the iterator state which will be used by
 				 * multiple processes to iterate jointly.
 				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
-					pstate->prefetch_iterator =
+					node->pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
 				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
+				BitmapDoneInitializingSharedState(node->pstate);
 			}
 		}
 
@@ -216,19 +213,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		scan->prefetch_maximum = pf_maximum;
+		scan->bm_parallel = node->pstate;
+
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
 #ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
+		if (scan->prefetch_maximum > 0)
 		{
-			node->pf_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
-												  dsa);
-			/* Only used for serial BHS */
-			node->prefetch_pages = 0;
-			node->prefetch_target = -1;
+			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
+														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
+														 dsa);
 		}
 #endif							/* USE_PREFETCH */
 
@@ -243,36 +240,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
 
 			/*
 			 * If we are using lossy info, we have to recheck the qual
@@ -296,23 +263,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			node->pf_iterator &&
-			node->pfblockno > node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,219 +289,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -594,22 +334,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->pf_iterator)
-	{
-		bhs_end_iterate(node->pf_iterator);
-		node->pf_iterator = NULL;
-	}
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -648,14 +378,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->pf_iterator)
-		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -688,17 +414,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->pf_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -738,13 +458,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -828,7 +541,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index cef54e2d5d..29fdd55893 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -82,6 +82,23 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
+	/*
+	 * These fields only used for prefetching in bitmap table scans
+	 */
+
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
+
+	/*
+	 * These fields only used in serial BHS
+	 */
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block  */
+	BlockNumber pfblockno;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index fb22f305bf..7938b741d6 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -26,6 +26,7 @@
 struct ParallelTableScanDescData;
 
 struct BitmapHeapIterator;
+struct ParallelBitmapHeapState;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -45,6 +46,13 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
+	struct BitmapHeapIterator *rs_pf_bhs_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+	struct ParallelBitmapHeapState *bm_parallel;
+	/* used to validate BHS prefetch and current block stay in sync */
+	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index edc54ecffe..284ea3d864 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -800,17 +800,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the block's representation in the bitmap
 	 * is lossy, otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -960,6 +949,9 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
+	result->rs_pf_bhs_iterator = NULL;
+	result->prefetch_maximum = 0;
+	result->bm_parallel = NULL;
 	return result;
 }
 
@@ -1024,6 +1016,12 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1040,6 +1038,12 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 52cedd1b35..60916bf0d0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1785,18 +1785,11 @@ struct BitmapHeapIterator;
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		pf_iterator        for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1804,18 +1797,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v10-0015-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From feec27e011ef4f1f15e65afca2564192b85b17c1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 15:43:10 -0400
Subject: [PATCH v10 15/17] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block(). Heap AM's implementation of
table_scan_bitmap_next_tuple() now calls the original
heapam_scan_bitmap_next_block() function, but it is no longer an
implementation of a table AM callback but instead a helper for
heapam_scan_bitmap_next_tuple()
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 48 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 45 ++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 75 +++++------------------
 6 files changed, 63 insertions(+), 111 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 3d92fb5135..8de1a11164 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -319,6 +319,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 867061325c..6af1791faa 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2109,12 +2109,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
- */
-
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
  *
@@ -2148,8 +2142,8 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
@@ -2512,30 +2506,43 @@ BitmapPrefetch(HeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
-		return true;
-	}
+		if (hscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			hscan->rs_empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2917,7 +2924,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index ce637a5a5d..1d6b03d1ca 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 187b288e68..2f9387e51a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -230,44 +230,35 @@ BitmapHeapNext(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 
 		node->initialized = true;
-
-		goto new_page;
 	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346..cf56cc572f 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 284ea3d864..44d0885d9e 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -788,36 +788,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the block's representation in the bitmap
-	 * is lossy, otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   BlockNumber *blockno,
-										   long *lossy_pages,
-										   long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1998,44 +1982,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented if bitmap is lossy for the selected block and exact_pages is
- * incremented otherwise.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno,
-							 long *lossy_pages, long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   blockno, lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2046,7 +1999,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v10-0016-v7-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From d5f6f3f2e80e9f85d054dfa99b186b24571930da Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:59:42 -0400
Subject: [PATCH v10 16/17] v7 Streaming Read API

---
 src/backend/storage/Makefile             |   2 +-
 src/backend/storage/aio/Makefile         |  14 +
 src/backend/storage/aio/meson.build      |   5 +
 src/backend/storage/aio/streaming_read.c | 659 +++++++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c      | 642 +++++++++++++++-------
 src/backend/storage/buffer/localbuf.c    |  14 +-
 src/backend/storage/meson.build          |   1 +
 src/include/storage/bufmgr.h             |  45 ++
 src/include/storage/streaming_read.h     |  52 ++
 src/tools/pgindent/typedefs.list         |   3 +
 10 files changed, 1227 insertions(+), 210 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/streaming_read.c
 create mode 100644 src/include/storage/streaming_read.h

diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca2..eec03f6f2b 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 0000000000..bcab44c802
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	streaming_read.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 0000000000..39aef2a84a
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'streaming_read.c',
+)
diff --git a/src/backend/storage/aio/streaming_read.c b/src/backend/storage/aio/streaming_read.c
new file mode 100644
index 0000000000..d5c29b750d
--- /dev/null
+++ b/src/backend/storage/aio/streaming_read.c
@@ -0,0 +1,659 @@
+#include "postgres.h"
+
+#include "catalog/pg_tablespace.h"
+#include "miscadmin.h"
+#include "storage/streaming_read.h"
+#include "utils/rel.h"
+#include "utils/spccache.h"
+
+/*
+ * Element type for PgStreamingRead's circular array of block ranges.
+ */
+typedef struct PgStreamingReadRange
+{
+	bool		need_wait;
+	bool		advice_issued;
+	BlockNumber blocknum;
+	int			nblocks;
+	int			per_buffer_data_index;
+	Buffer		buffers[MAX_BUFFERS_PER_TRANSFER];
+	ReadBuffersOperation operation;
+} PgStreamingReadRange;
+
+/*
+ * Streaming read object.
+ */
+struct PgStreamingRead
+{
+	int			max_ios;
+	int			ios_in_progress;
+	int			max_pinned_buffers;
+	int			pinned_buffers;
+	int			next_tail_buffer;
+	int			distance;
+	bool		started;
+	bool		finished;
+	bool		advice_enabled;
+	void	   *pgsr_private;
+	PgStreamingReadBufferCB callback;
+
+	BufferAccessStrategy strategy;
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+
+	/* Sometimes we need to buffer one block for flow control. */
+	BlockNumber unget_blocknum;
+	void	   *unget_per_buffer_data;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* Space for optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+
+	/* Circular buffer of ranges. */
+	int			size;
+	int			head;
+	int			tail;
+	PgStreamingReadRange ranges[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.
+ */
+PgStreamingRead *
+pg_streaming_read_buffer_alloc(int flags,
+							   void *pgsr_private,
+							   size_t per_buffer_data_size,
+							   BufferAccessStrategy strategy,
+							   BufferManagerRelation bmr,
+							   ForkNumber forknum,
+							   PgStreamingReadBufferCB next_block_cb)
+{
+	PgStreamingRead *pgsr;
+	int			size;
+	int			max_ios;
+	uint32		max_pinned_buffers;
+	Oid			tablespace_id;
+
+	/*
+	 * Make sure our bmr's smgr and persistent are populated.  The caller
+	 * asserts that the storage manager will remain valid.
+	 */
+	if (!bmr.smgr)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	/*
+	 * Decide how many assumed I/Os we will allow to run concurrently.  That
+	 * is, advice to the kernel to tell it that we will soon read.  This
+	 * number also affects how far we look ahead for opportunities to start
+	 * more I/Os.
+	 */
+	tablespace_id = bmr.smgr->smgr_rlocator.locator.spcOid;
+	if (!OidIsValid(MyDatabaseId) ||
+		(bmr.rel && IsCatalogRelation(bmr.rel)) ||
+		IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
+	{
+		/*
+		 * Avoid circularity while trying to look up tablespace settings or
+		 * before spccache.c is ready.
+		 */
+		max_ios = effective_io_concurrency;
+	}
+	else if (flags & PGSR_FLAG_MAINTENANCE)
+		max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
+	else
+		max_ios = get_tablespace_io_concurrency(tablespace_id);
+
+	/*
+	 * Choose a maximum number of buffers we're prepared to pin.  We try to
+	 * pin fewer if we can, though.  We clamp it to at least
+	 * MAX_BUFFER_PER_TRANSFER so that we can have a chance to build up a full
+	 * sized read, even when max_ios is zero.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, MAX_BUFFERS_PER_TRANSFER);
+
+	/* Don't allow this backend to pin more than its share of buffers. */
+	if (SmgrIsTemp(bmr.smgr))
+		LimitAdditionalLocalPins(&max_pinned_buffers);
+	else
+		LimitAdditionalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * pgsr->ranges is a circular buffer.  When it is empty, head == tail.
+	 * When it is full, there is an empty element between head and tail.  Head
+	 * can also be empty (nblocks == 0), therefore we need two extra elements
+	 * for non-occupied ranges, on top of max_pinned_buffers to allow for the
+	 * maxmimum possible number of occupied ranges of the smallest possible
+	 * size of one.
+	 */
+	size = max_pinned_buffers + 2;
+
+	pgsr = (PgStreamingRead *)
+		palloc0(offsetof(PgStreamingRead, ranges) +
+				sizeof(pgsr->ranges[0]) * size);
+
+	pgsr->max_ios = max_ios;
+	pgsr->per_buffer_data_size = per_buffer_data_size;
+	pgsr->max_pinned_buffers = max_pinned_buffers;
+	pgsr->pgsr_private = pgsr_private;
+	pgsr->strategy = strategy;
+	pgsr->size = size;
+
+	pgsr->callback = next_block_cb;
+	pgsr->bmr = bmr;
+	pgsr->forknum = forknum;
+
+	pgsr->unget_blocknum = InvalidBlockNumber;
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  As long as direct I/O isn't
+	 * enabled, and the caller hasn't promised sequential access, we can use
+	 * it.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & PGSR_FLAG_SEQUENTIAL) == 0)
+		pgsr->advice_enabled = true;
+#endif
+
+	/*
+	 * Skip the initial ramp-up phase if the caller says we're going to be
+	 * reading the whole relation.  This way we start out doing full-sized
+	 * reads.
+	 */
+	if (flags & PGSR_FLAG_FULL)
+		pgsr->distance = Min(MAX_BUFFERS_PER_TRANSFER, pgsr->max_pinned_buffers);
+	else
+		pgsr->distance = 1;
+
+	/*
+	 * Space for the callback to store extra data along with each block.  Note
+	 * that we need one more than max_pinned_buffers, so we can return a
+	 * pointer to a slot that can't be overwritten until the next call.
+	 */
+	if (per_buffer_data_size)
+		pgsr->per_buffer_data = palloc(per_buffer_data_size * size);
+
+	return pgsr;
+}
+
+/*
+ * Find the per-buffer data index for the Nth block of a range.
+ */
+static int
+get_per_buffer_data_index(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	int			result;
+
+	/*
+	 * Find slot in the circular buffer of per-buffer data, without using the
+	 * expensive % operator.
+	 */
+	result = range->per_buffer_data_index + n;
+	while (result >= pgsr->size)
+		result -= pgsr->size;
+	Assert(result == (range->per_buffer_data_index + n) % pgsr->size);
+
+	return result;
+}
+
+/*
+ * Return a pointer to the per-buffer data by index.
+ */
+static void *
+get_per_buffer_data_by_index(PgStreamingRead *pgsr, int per_buffer_data_index)
+{
+	return (char *) pgsr->per_buffer_data +
+		pgsr->per_buffer_data_size * per_buffer_data_index;
+}
+
+/*
+ * Return a pointer to the per-buffer data for the Nth block of a range.
+ */
+static void *
+get_per_buffer_data(PgStreamingRead *pgsr, PgStreamingReadRange *range, int n)
+{
+	return get_per_buffer_data_by_index(pgsr,
+										get_per_buffer_data_index(pgsr,
+																  range,
+																  n));
+}
+
+/*
+ * Start reading the head range, and create a new head range.  The new head
+ * range is returned.  It may not be empty, if StartReadBuffers() couldn't
+ * start the entire range; in that case the returned range contains the
+ * remaining portion of the range.
+ */
+static PgStreamingReadRange *
+pg_streaming_read_start_head_range(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *head_range;
+	PgStreamingReadRange *new_head_range;
+	int			nblocks_pinned;
+	int			flags;
+
+	/* Caller should make sure we never exceed max_ios. */
+	Assert((pgsr->ios_in_progress < pgsr->max_ios) ||
+		   (pgsr->ios_in_progress == 0 && pgsr->max_ios == 0));
+
+	/* Should only call if the head range has some blocks to read. */
+	head_range = &pgsr->ranges[pgsr->head];
+	Assert(head_range->nblocks > 0);
+
+	/*
+	 * If advice hasn't been suppressed, and this system supports it, this
+	 * isn't a strictly sequential pattern, then we'll issue advice.
+	 */
+	if (pgsr->advice_enabled &&
+		pgsr->max_ios > 0 &&
+		pgsr->started &&
+		head_range->blocknum != pgsr->seq_blocknum)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else
+		flags = 0;
+
+	/* Suppress advice on the first call, because it's too late to benefit. */
+	if (!pgsr->started)
+		pgsr->started = true;
+
+	/* We shouldn't be trying to pin more buffers that we're allowed to. */
+	Assert(pgsr->pinned_buffers + head_range->nblocks <= pgsr->max_pinned_buffers);
+
+	/* Start reading as many blocks as we can from the head range. */
+	nblocks_pinned = head_range->nblocks;
+	head_range->need_wait =
+		StartReadBuffers(pgsr->bmr,
+						 head_range->buffers,
+						 pgsr->forknum,
+						 head_range->blocknum,
+						 &nblocks_pinned,
+						 pgsr->strategy,
+						 flags,
+						 &head_range->operation);
+
+	Assert(pgsr->pinned_buffers <= pgsr->max_pinned_buffers);
+
+	if (head_range->need_wait && (flags & READ_BUFFERS_ISSUE_ADVICE))
+	{
+		/*
+		 * Since we've issued advice, we count an I/O in progress until we
+		 * call WaitReadBuffers().
+		 */
+		head_range->advice_issued = true;
+		pgsr->ios_in_progress++;
+		Assert(pgsr->ios_in_progress <= pgsr->max_ios);
+	}
+
+	/*
+	 * StartReadBuffers() might have pinned fewer blocks than we asked it to,
+	 * but always at least one.
+	 */
+	Assert(nblocks_pinned <= head_range->nblocks);
+	Assert(nblocks_pinned >= 1);
+	pgsr->pinned_buffers += nblocks_pinned;
+
+	/*
+	 * Remember where the next block would be after that, so we can detect
+	 * sequential access next time.
+	 */
+	pgsr->seq_blocknum = head_range->blocknum + nblocks_pinned;
+
+	/*
+	 * Create a new head range.  There must be space, because we have enough
+	 * elements for every range to hold just one block, up to the pin limit.
+	 */
+	Assert(pgsr->size > pgsr->max_pinned_buffers);
+	Assert((pgsr->head + 1) % pgsr->size != pgsr->tail);
+	if (++pgsr->head == pgsr->size)
+		pgsr->head = 0;
+	new_head_range = &pgsr->ranges[pgsr->head];
+	new_head_range->nblocks = 0;
+	new_head_range->advice_issued = false;
+
+	/*
+	 * If we didn't manage to start the whole read above, we split the range,
+	 * moving the remainder into the new head range.
+	 */
+	if (nblocks_pinned < head_range->nblocks)
+	{
+		int			nblocks_remaining = head_range->nblocks - nblocks_pinned;
+
+		head_range->nblocks = nblocks_pinned;
+
+		new_head_range->blocknum = head_range->blocknum + nblocks_pinned;
+		new_head_range->nblocks = nblocks_remaining;
+	}
+
+	/* The new range has per-buffer data starting after the previous range. */
+	new_head_range->per_buffer_data_index =
+		get_per_buffer_data_index(pgsr, head_range, nblocks_pinned);
+
+	return new_head_range;
+}
+
+/*
+ * Ask the callback which block it would like us to read next, with a small
+ * buffer in front to allow pg_streaming_unget_block() to work.
+ */
+static BlockNumber
+pg_streaming_get_block(PgStreamingRead *pgsr, void *per_buffer_data)
+{
+	BlockNumber result;
+
+	if (unlikely(pgsr->unget_blocknum != InvalidBlockNumber))
+	{
+		/*
+		 * If we had to unget a block, now it is time to return that one
+		 * again.
+		 */
+		result = pgsr->unget_blocknum;
+		pgsr->unget_blocknum = InvalidBlockNumber;
+
+		/*
+		 * The same per_buffer_data element must have been used, and still
+		 * contains whatever data the callback wrote into it.  So we just
+		 * sanity-check that we were called with the value that
+		 * pg_streaming_unget_block() pushed back.
+		 */
+		Assert(per_buffer_data == pgsr->unget_per_buffer_data);
+	}
+	else
+	{
+		/* Use the installed callback directly. */
+		result = pgsr->callback(pgsr, pgsr->pgsr_private, per_buffer_data);
+	}
+
+	return result;
+}
+
+/*
+ * In order to deal with short reads in StartReadBuffers(), we sometimes need
+ * to defer handling of a block until later.  This *must* be called with the
+ * last value returned by pg_streaming_get_block().
+ */
+static void
+pg_streaming_unget_block(PgStreamingRead *pgsr, BlockNumber blocknum, void *per_buffer_data)
+{
+	Assert(pgsr->unget_blocknum == InvalidBlockNumber);
+	pgsr->unget_blocknum = blocknum;
+	pgsr->unget_per_buffer_data = per_buffer_data;
+}
+
+static void
+pg_streaming_read_look_ahead(PgStreamingRead *pgsr)
+{
+	PgStreamingReadRange *range;
+
+	/* If we're finished, don't look ahead. */
+	if (pgsr->finished)
+		return;
+
+	/*
+	 * We we've already started the maximum allowed number of I/Os, don't look
+	 * ahead.  There is a special case for max_ios == 0.
+	 */
+	if (pgsr->max_ios > 0 && pgsr->ios_in_progress == pgsr->max_ios)
+		return;
+
+	/* Can't pin any more buffers. */
+	if (pgsr->pinned_buffers == pgsr->distance)
+		return;
+
+	/*
+	 * Keep trying to add new blocks to the end of the head range while doing
+	 * so wouldn't exceed the distance limit.
+	 */
+	range = &pgsr->ranges[pgsr->head];
+	while (pgsr->pinned_buffers + range->nblocks < pgsr->distance)
+	{
+		BlockNumber blocknum;
+		void	   *per_buffer_data;
+
+		/* Do we have a full-sized range? */
+		if (range->nblocks == lengthof(range->buffers))
+		{
+			/* Start as much of it as we can. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/* If we're now at the I/O limit, stop here. */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+				return;
+
+			/*
+			 * That might have only been partially started, but always
+			 * processes at least one so that'll do for now.
+			 */
+			Assert(range->nblocks < lengthof(range->buffers));
+		}
+
+		/* Find per-buffer data slot for the next block. */
+		per_buffer_data = get_per_buffer_data(pgsr, range, range->nblocks);
+
+		/* Find out which block the callback wants to read next. */
+		blocknum = pg_streaming_get_block(pgsr, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			/* End of stream. */
+			pgsr->finished = true;
+			break;
+		}
+
+		/*
+		 * Is there a head range that we cannot extend, because the requested
+		 * block is not consecutive?
+		 */
+		if (range->nblocks > 0 &&
+			range->blocknum + range->nblocks != blocknum)
+		{
+			/* Yes.  Start it, so we can begin building a new one. */
+			range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * It's possible that it was only partially started, and we have a
+			 * new range with the remainder.  Keep starting I/Os until we get
+			 * it all out of the way, or we hit the I/O limit.
+			 */
+			while (range->nblocks > 0 && pgsr->ios_in_progress < pgsr->max_ios)
+				range = pg_streaming_read_start_head_range(pgsr);
+
+			/*
+			 * We do have to worry about I/O capacity running out if the head
+			 * range was split.  In that case we have to 'unget' the block
+			 * returned by the callback.
+			 */
+			if (pgsr->ios_in_progress == pgsr->max_ios)
+			{
+				pg_streaming_unget_block(pgsr, blocknum, per_buffer_data);
+				return;
+			}
+		}
+
+		/* If we have a new, empty range, initialize the start block. */
+		if (range->nblocks == 0)
+			range->blocknum = blocknum;
+
+		/* This block extends the range by one. */
+		Assert(range->blocknum + range->nblocks == blocknum);
+		range->nblocks++;
+	};
+
+	/*
+	 * Normally we don't start the head range, preferring to give it a chance
+	 * to grow to full size once more buffers have been consumed.  In cases
+	 * where that can't possibly happen, we might as well start the read
+	 * immediately.
+	 */
+	if ((range->nblocks > 0 && pgsr->finished) ||
+		(range->nblocks == pgsr->distance))
+		pg_streaming_read_start_head_range(pgsr);
+}
+
+Buffer
+pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_data)
+{
+	PgStreamingReadRange *tail_range;
+
+	for (;;)
+	{
+		if (pgsr->tail != pgsr->head)
+		{
+			tail_range = &pgsr->ranges[pgsr->tail];
+
+			/*
+			 * Do we need to wait for a ReadBuffers operation to finish before
+			 * returning the buffers in this range?
+			 */
+			if (tail_range->need_wait)
+			{
+				int			distance;
+
+				Assert(pgsr->next_tail_buffer == 0);
+				WaitReadBuffers(&tail_range->operation);
+				tail_range->need_wait = false;
+
+				/*
+				 * We don't really know if the kernel generated a physical I/O
+				 * when we issued advice, let alone when it finished, but it
+				 * has certainly finished now because we've performed the
+				 * read.
+				 */
+				if (tail_range->advice_issued)
+				{
+
+					Assert(pgsr->ios_in_progress > 0);
+					pgsr->ios_in_progress--;
+
+					/*
+					 * Look-ahead distance ramps up rapidly if we're issuing
+					 * advice, so we can search for new more I/Os to start.
+					 */
+					distance = pgsr->distance * 2;
+					distance = Min(distance, pgsr->max_pinned_buffers);
+					pgsr->distance = distance;
+				}
+				else
+				{
+					/*
+					 * There is no point in increasing look-ahead distance if
+					 * we've already reached the full I/O size, since we're
+					 * not issuing advice.  Extra distance would only pin more
+					 * buffers for no benefit.
+					 */
+					if (pgsr->distance > MAX_BUFFERS_PER_TRANSFER)
+					{
+						/*
+						 * Look-ahead distance gradually decays to full I/O
+						 * size.
+						 */
+						pgsr->distance--;
+					}
+					else
+					{
+						/*
+						 * Look-ahead distance ramps up rapidly, but not more
+						 * that the full I/O size.
+						 */
+						distance = pgsr->distance * 2;
+						distance = Min(distance, MAX_BUFFERS_PER_TRANSFER);
+						distance = Min(distance, pgsr->max_pinned_buffers);
+						pgsr->distance = distance;
+					}
+				}
+			}
+			else if (pgsr->next_tail_buffer == 0)
+			{
+				/* No I/O necessary. Look-ahead distance gradually decays. */
+				if (pgsr->distance > 1)
+					pgsr->distance--;
+			}
+
+			/* Are there more buffers available in this range? */
+			if (pgsr->next_tail_buffer < tail_range->nblocks)
+			{
+				int			buffer_index;
+				Buffer		buffer;
+
+				buffer_index = pgsr->next_tail_buffer++;
+				buffer = tail_range->buffers[buffer_index];
+
+				Assert(BufferIsValid(buffer));
+
+				/* We are giving away ownership of this pinned buffer. */
+				Assert(pgsr->pinned_buffers > 0);
+				pgsr->pinned_buffers--;
+
+				if (per_buffer_data)
+					*per_buffer_data = get_per_buffer_data(pgsr, tail_range, buffer_index);
+
+				/* We may be able to get another I/O started. */
+				pg_streaming_read_look_ahead(pgsr);
+
+				return buffer;
+			}
+
+			/* Advance tail to next range. */
+			if (++pgsr->tail == pgsr->size)
+				pgsr->tail = 0;
+			pgsr->next_tail_buffer = 0;
+		}
+		else
+		{
+			/*
+			 * If tail crashed into head, and head is not empty, then it is
+			 * time to start that range.  Otherwise, force a look-ahead, to
+			 * kick start the stream.
+			 */
+			Assert(pgsr->tail == pgsr->head);
+			if (pgsr->ranges[pgsr->head].nblocks > 0)
+			{
+				pg_streaming_read_start_head_range(pgsr);
+			}
+			else
+			{
+				pg_streaming_read_look_ahead(pgsr);
+
+				/* Finished? */
+				if (pgsr->tail == pgsr->head &&
+					pgsr->ranges[pgsr->head].nblocks == 0)
+					break;
+			}
+		}
+	}
+
+	Assert(pgsr->pinned_buffers == 0);
+
+	return InvalidBuffer;
+}
+
+void
+pg_streaming_read_free(PgStreamingRead *pgsr)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead. */
+	pgsr->finished = true;
+
+	/* Unpin anything that wasn't consumed. */
+	while ((buffer = pg_streaming_read_buffer_get_next(pgsr, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	Assert(pgsr->pinned_buffers == 0);
+	Assert(pgsr->ios_in_progress == 0);
+
+	/* Release memory. */
+	if (pgsr->per_buffer_data)
+		pfree(pgsr->per_buffer_data);
+
+	pfree(pgsr);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f0f8d4259c..d0e9c7deff 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -19,6 +19,11 @@
  *		and pin it so that no one can destroy it while this process
  *		is using it.
  *
+ * StartReadBuffers() -- as above, but for multiple contiguous blocks in
+ *		two steps.
+ *
+ * WaitReadBuffers() -- second step of StartReadBuffers().
+ *
  * ReleaseBuffer() -- unpin a buffer
  *
  * MarkBufferDirty() -- mark a pinned buffer's contents as "dirty".
@@ -471,10 +476,9 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
-								ReadBufferMode mode, BufferAccessStrategy strategy,
-								bool *hit);
+								ReadBufferMode mode, BufferAccessStrategy strategy);
 static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
 										   ForkNumber fork,
 										   BufferAccessStrategy strategy,
@@ -500,7 +504,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -781,7 +785,6 @@ Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
-	bool		hit;
 	Buffer		buf;
 
 	/*
@@ -794,15 +797,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
-							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+	buf = ReadBuffer_common(BMR_REL(reln),
+							forkNum, blockNum, mode, strategy);
+
 	return buf;
 }
 
@@ -822,13 +819,12 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 						  BlockNumber blockNum, ReadBufferMode mode,
 						  BufferAccessStrategy strategy, bool permanent)
 {
-	bool		hit;
-
 	SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
-							 mode, strategy, &hit);
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
+							 mode, strategy);
 }
 
 /*
@@ -994,35 +990,68 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 	 */
 	if (buffer == InvalidBuffer)
 	{
-		bool		hit;
-
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
-								   fork, extend_to - 1, mode, strategy,
-								   &hit);
+		buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
 	}
 
 	return buffer;
 }
 
+/*
+ * Zero a buffer and lock it, as part of the implementation of
+ * RBM_ZERO_AND_LOCK or RBM_ZERO_AND_CLEANUP_LOCK.  The buffer must be already
+ * pinned.  It does not have to be valid, but it is valid and locked on
+ * return.
+ */
+static void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
+{
+	BufferDesc *bufHdr;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
 /*
  * ReadBuffer_common -- common logic for all ReadBuffer variants
  *
  * *hit is set to true if the request was satisfied from shared buffer cache.
  */
 static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
 				  BlockNumber blockNum, ReadBufferMode mode,
-				  BufferAccessStrategy strategy, bool *hit)
+				  BufferAccessStrategy strategy)
 {
-	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
-	IOContext	io_context;
-	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
-
-	*hit = false;
+	ReadBuffersOperation operation;
+	Buffer		buffer;
+	int			nblocks;
+	int			flags;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1041,181 +1070,405 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
+	nblocks = 1;
+	if (mode == RBM_ZERO_ON_ERROR)
+		flags = READ_BUFFERS_ZERO_ON_ERROR;
+	else
+		flags = 0;
+	if (StartReadBuffers(bmr,
+						 &buffer,
+						 forkNum,
+						 blockNum,
+						 &nblocks,
+						 strategy,
+						 flags,
+						 &operation))
+		WaitReadBuffers(&operation);
+	Assert(nblocks == 1);		/* single block can't be short */
+
+	if (mode == RBM_ZERO_AND_CLEANUP_LOCK || mode == RBM_ZERO_AND_LOCK)
+		ZeroBuffer(buffer, mode);
+
+	return buffer;
+}
 
+static Buffer
+PrepareReadBuffer(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	Assert(blockNum != P_NEW);
+
+	Assert(bmr.smgr);
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
 		io_context = IOCONTEXT_NORMAL;
 		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
 	}
 	else
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
 		io_context = IOContextForStrategy(strategy);
 		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
 	}
 
-	/* At this point we do NOT hold any locks. */
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
 
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	ResourceOwnerEnlarge(CurrentResourceOwner);
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * WaitReadBuffers() (so, not for hits, and not for buffers that are
+		 * zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
 		VacuumPageHit++;
 		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
-
 		if (VacuumCostActive)
 			VacuumCostBalance += VacuumCostPageHit;
 
 		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
-		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
-		}
+	return BufferDescriptorGetBuffer(bufHdr);
+}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+/*
+ * Begin reading a range of blocks beginning at blockNum and extending for
+ * *nblocks.  On return, up to *nblocks pinned buffers holding those blocks
+ * are written into the buffers array, and *nblocks is updated to contain the
+ * actual number, which may be fewer than requested.
+ *
+ * If false is returned, no I/O is necessary and WaitReadBuffers() is not
+ * necessary.  If true is returned, one I/O has been started, and
+ * WaitReadBuffers() must be called with the same operation object before the
+ * buffers are accessed.  Along with the operation object, the caller-supplied
+ * array of buffers must remain valid until WaitReadBuffers() is called.
+ *
+ * Currently the I/O is only started with optional operating system advice,
+ * and the real I/O happens in WaitReadBuffers().  In future work, true I/O
+ * could be initiated here.
+ */
+bool
+StartReadBuffers(BufferManagerRelation bmr,
+				 Buffer *buffers,
+				 ForkNumber forkNum,
+				 BlockNumber blockNum,
+				 int *nblocks,
+				 BufferAccessStrategy strategy,
+				 int flags,
+				 ReadBuffersOperation *operation)
+{
+	int			actual_nblocks = *nblocks;
+
+	if (bmr.rel)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
 	}
 
-	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
-	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+	operation->bmr = bmr;
+	operation->forknum = forkNum;
+	operation->blocknum = blockNum;
+	operation->buffers = buffers;
+	operation->nblocks = actual_nblocks;
+	operation->strategy = strategy;
+	operation->flags = flags;
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	operation->io_buffers_len = 0;
 
-	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
-	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
-	else
+	for (int i = 0; i < actual_nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		bool		found;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+		buffers[i] = PrepareReadBuffer(bmr,
+									   forkNum,
+									   blockNum + i,
+									   strategy,
+									   &found);
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		if (found)
+		{
+			/*
+			 * Terminate the read as soon as we get a hit.  It could be a
+			 * single buffer hit, or it could be a hit that follows a readable
+			 * range.  We don't want to create more than one readable range,
+			 * so we stop here.
+			 */
+			actual_nblocks = operation->nblocks = *nblocks = i + 1;
+			break;
+		}
+		else
+		{
+			/* Extend the readable range to cover this block. */
+			operation->io_buffers_len++;
+		}
+	}
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+	if (operation->io_buffers_len > 0)
+	{
+		if (flags & READ_BUFFERS_ISSUE_ADVICE)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
-			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
-			}
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
+			/*
+			 * In theory we should only do this if PrepareReadBuffers() had to
+			 * allocate new buffers above.  That way, if two calls to
+			 * StartReadBuffers() were made for the same blocks before
+			 * WaitReadBuffers(), only the first would issue the advice.
+			 * That'd be a better simulation of true asynchronous I/O, which
+			 * would only start the I/O once, but isn't done here for
+			 * simplicity.  Note also that the following call might actually
+			 * issue two advice calls if we cross a segment boundary; in a
+			 * true asynchronous version we might choose to process only one
+			 * real I/O at a time in that case.
+			 */
+			smgrprefetch(bmr.smgr, forkNum, blockNum, operation->io_buffers_len);
 		}
+
+		/* Indicate that WaitReadBuffers() should be called. */
+		return true;
 	}
+	else
+	{
+		return false;
+	}
+}
 
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
+static inline bool
+WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
 	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
 	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
+
+void
+WaitReadBuffers(ReadBuffersOperation *operation)
+{
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	int			nblocks;
+	BlockNumber blocknum;
+	ForkNumber	forknum;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
+
+	/*
+	 * Currently operations are only allowed to include a read of some range,
+	 * with an optional extra buffer that is already pinned at the end.  So
+	 * nblocks can be at most one more than io_buffers_len.
+	 */
+	Assert((operation->nblocks == operation->io_buffers_len) ||
+		   (operation->nblocks == operation->io_buffers_len + 1));
 
+	/* Find the range of the physical read we need to perform. */
+	nblocks = operation->io_buffers_len;
+	if (nblocks == 0)
+		return;					/* nothing to do */
+
+	buffers = &operation->buffers[0];
+	blocknum = operation->blocknum;
+	forknum = operation->forknum;
+	bmr = operation->bmr;
+
+	isLocalBuf = SmgrIsTemp(bmr.smgr);
 	if (isLocalBuf)
 	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
-
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
 	}
 	else
 	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
+		io_context = IOContextForStrategy(operation->strategy);
+		io_object = IOOBJECT_RELATION;
 	}
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+	/*
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
+	 */
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
+	else
+		pgBufferUsage.shared_blks_read += nblocks;
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+	for (int i = 0; i < nblocks; ++i)
+	{
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_BUFFERS_PER_TRANSFER];
+		void	   *io_pages[MAX_BUFFERS_PER_TRANSFER];
+		instr_time	io_start;
+		BlockNumber io_first_block;
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!WaitReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PrepareReadBuffer().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
+
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   WaitReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
+
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
+
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
+		{
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
+			{
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
+			}
+			else
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
+
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(bmr.smgr->smgr_rlocator, forknum))));
+			}
+
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
+
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  bmr.smgr->smgr_rlocator.locator.spcOid,
+											  bmr.smgr->smgr_rlocator.locator.dbOid,
+											  bmr.smgr->smgr_rlocator.locator.relNumber,
+											  bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
+
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
- * BufferAlloc -- subroutine for ReadBuffer.  Handles lookup of a shared
- *		buffer.  If no buffer exists already, selects a replacement
- *		victim and evicts the old page, but does NOT read in new page.
+ * BufferAlloc -- subroutine for StartReadBuffers.  Handles lookup of a shared
+ *		buffer.  If no buffer exists already, selects a replacement victim and
+ *		evicts the old page, but does NOT read in new page.
  *
  * "strategy" can be a buffer replacement strategy object, or NULL for
  * the default strategy.  The selected buffer's usage_count is advanced when
@@ -1223,11 +1476,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1286,19 +1535,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1363,19 +1603,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1407,15 +1638,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1769,7 +1994,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2034,7 +2259,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2057,7 +2282,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2372,7 +2597,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if StartReadBuffers() was called and
+		 * WaitReadBuffers() hasn't been called yet.  We'll check by loading
+		 * the flags without locking.  This is racy, but it's OK to return
+		 * false spuriously: when WaitReadBuffers() calls StartBufferIO(),
+		 * it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2381,7 +2611,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3449,7 +3679,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -5184,9 +5414,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5199,6 +5435,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index fcfac335a5..985a2c7049 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -108,10 +108,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -287,7 +286,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -297,9 +296,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca2..739d13293f 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d335..b57f71f97e 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -158,6 +159,11 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
+/*
+ * Maximum number of buffers for multi-buffer I/O functions.  This is set to
+ * allow 128kB transfers, unless BLCKSZ and IOV_MAX imply a a smaller maximum.
+ */
+#define MAX_BUFFERS_PER_TRANSFER Min(PG_IOV_MAX, (128 * 1024) / BLCKSZ)
 
 /*
  * prototypes for functions in bufmgr.c
@@ -177,6 +183,42 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+
+#define READ_BUFFERS_ZERO_ON_ERROR 0x01
+#define READ_BUFFERS_ISSUE_ADVICE 0x02
+
+/*
+ * Private state used by StartReadBuffers() and WaitReadBuffers().  Declared
+ * in public header only to allow inclusion in other structs, but contents
+ * should not be accessed.
+ */
+struct ReadBuffersOperation
+{
+	/* Parameters passed in to StartReadBuffers(). */
+	BufferManagerRelation bmr;
+	Buffer	   *buffers;
+	ForkNumber	forknum;
+	BlockNumber blocknum;
+	int			nblocks;
+	BufferAccessStrategy strategy;
+	int			flags;
+
+	/* Range of buffers, if we need to perform a read. */
+	int			io_buffers_len;
+};
+
+typedef struct ReadBuffersOperation ReadBuffersOperation;
+
+extern bool StartReadBuffers(BufferManagerRelation bmr,
+							 Buffer *buffers,
+							 ForkNumber forknum,
+							 BlockNumber blocknum,
+							 int *nblocks,
+							 BufferAccessStrategy strategy,
+							 int flags,
+							 ReadBuffersOperation *operation);
+extern void WaitReadBuffers(ReadBuffersOperation *operation);
+
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -250,6 +292,9 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/streaming_read.h b/src/include/storage/streaming_read.h
new file mode 100644
index 0000000000..c4d3892bb2
--- /dev/null
+++ b/src/include/storage/streaming_read.h
@@ -0,0 +1,52 @@
+#ifndef STREAMING_READ_H
+#define STREAMING_READ_H
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define PGSR_FLAG_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users.
+ */
+#define PGSR_FLAG_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define PGSR_FLAG_SEQUENTIAL 0x02
+
+/*
+ * We usually ramp up from smaller reads to larger ones, to support users who
+ * don't know if it's worth reading lots of buffers yet.  This flag disables
+ * that, declaring ahead of time that we'll be reading all available buffers.
+ */
+#define PGSR_FLAG_FULL 0x04
+
+struct PgStreamingRead;
+typedef struct PgStreamingRead PgStreamingRead;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*PgStreamingReadBufferCB) (PgStreamingRead *pgsr,
+												void *pgsr_private,
+												void *per_buffer_private);
+
+extern PgStreamingRead *pg_streaming_read_buffer_alloc(int flags,
+													   void *pgsr_private,
+													   size_t per_buffer_private_size,
+													   BufferAccessStrategy strategy,
+													   BufferManagerRelation bmr,
+													   ForkNumber forknum,
+													   PgStreamingReadBufferCB next_block_cb);
+
+extern void pg_streaming_read_prefetch(PgStreamingRead *pgsr);
+extern Buffer pg_streaming_read_buffer_get_next(PgStreamingRead *pgsr, void **per_buffer_private);
+extern void pg_streaming_read_free(PgStreamingRead *pgsr);
+
+#endif
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 6d5cb0bdaa..4558c2ecfc 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2116,6 +2116,8 @@ PgStat_TableCounts
 PgStat_TableStatus
 PgStat_TableXactStatus
 PgStat_WalStats
+PgStreamingRead
+PgStreamingReadRange
 PgXmlErrorContext
 PgXmlStrictness
 Pg_finfo_record
@@ -2288,6 +2290,7 @@ ReInitializeDSMForeignScan_function
 ReScanForeignScan_function
 ReadBufPtrType
 ReadBufferMode
+ReadBuffersOperation
 ReadBytePtrType
 ReadExtraTocPtrType
 ReadFunc
-- 
2.40.1

v10-0017-BitmapHeapScan-uses-streaming-read-API.patchtext/x-diff; charset=us-asciiDownload
From fb7740a535532673e50b87014a0b77e565c46af8 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 16:51:40 -0400
Subject: [PATCH v10 17/17] BitmapHeapScan uses streaming read API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  96 ++++--
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  43 +--
 src/include/access/heapam.h               |  21 +-
 src/include/access/relscan.h              |   6 -
 src/include/access/tableam.h              |  14 -
 src/include/nodes/execnodes.h             |   9 +-
 7 files changed, 114 insertions(+), 422 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 8de1a11164..5421b552d9 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -108,6 +108,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+										void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -330,6 +332,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_pgsr)
+			pg_streaming_read_free(scan->rs_pgsr);
+
+		scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+													   scan,
+													   sizeof(TBMIterateResult),
+													   scan->rs_strategy,
+													   BMR_REL(scan->rs_base.rs_rd),
+													   MAIN_FORKNUM,
+													   bitmapheap_pgsr_next);
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -950,16 +968,9 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-
-	scan->rs_base.blockno = InvalidBlockNumber;
-
+	scan->rs_pgsr = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
-	scan->pvmbuffer = InvalidBuffer;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1042,12 +1053,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
-	scan->rs_base.blockno = InvalidBlockNumber;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
-
 	/*
 	 * unpin scan buffers
 	 */
@@ -1060,12 +1065,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1091,12 +1090,6 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
@@ -1114,6 +1107,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+		pg_streaming_read_free(scan->rs_pgsr);
+
 	pfree(scan);
 }
 
@@ -10025,3 +10021,51 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+					 void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		bhs_iterate(hdesc->rs_base.rs_bhs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(hdesc->rs_base.rs_flags & SO_NEED_TUPLE) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6af1791faa..fe9ee5976f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -55,9 +55,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
-static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
-static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
-static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2109,147 +2106,68 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
-	 * parallel workers.
-	 */
-	if (scan->rs_base.prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno,
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *io_private;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_pgsr);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(hscan);
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
+	hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(io_private);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = io_private;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2270,7 +2188,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,9 +2197,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2331,23 +2249,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->bm_parallel == NULL &&
-		scan->rs_pf_bhs_iterator &&
-		hscan->pfblockno > hscan->rs_base.blockno)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(hscan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2358,153 +2264,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= prefetch_maximum / 2)
-			scan->prefetch_target = prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= prefetch_maximum / 2)
-			pstate->prefetch_target = prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-
-				scan->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
@@ -2539,41 +2298,11 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 			return true;
 		}
 
-		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
 										   lossy_pages, exact_pages))
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!scan->bm_parallel)
-	{
-		if (hscan->prefetch_target < scan->prefetch_maximum)
-			hscan->prefetch_target++;
-	}
-	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&scan->bm_parallel->mutex);
-		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-			scan->bm_parallel->prefetch_target++;
-		SpinLockRelease(&scan->bm_parallel->mutex);
-	}
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(hscan);
-#endif							/* USE_PREFETCH */
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2f9387e51a..f2662ea542 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -131,14 +131,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -149,15 +141,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-		int			pf_maximum = 0;
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
-#endif
-
 		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -174,13 +157,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					node->pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
+
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(node->pstate);
 			}
@@ -213,22 +190,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
 												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
-#ifdef USE_PREFETCH
-		if (scan->prefetch_maximum > 0)
-		{
-			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
-														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
-														 dsa);
-		}
-#endif							/* USE_PREFETCH */
-
 		node->initialized = true;
 	}
 
@@ -525,14 +492,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -563,11 +526,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 29fdd55893..1b8ce82c9e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	PgStreamingRead *rs_pgsr;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -82,23 +86,6 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
-	/*
-	 * These fields only used for prefetching in bitmap table scans
-	 */
-
-	/* buffer for visibility-map lookups of prefetched pages */
-	Buffer		pvmbuffer;
-
-	/*
-	 * These fields only used in serial BHS
-	 */
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
-	/* used to validate prefetch block stays ahead of current block  */
-	BlockNumber pfblockno;
-
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 7938b741d6..02893bf99b 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -46,13 +46,7 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
-	struct BitmapHeapIterator *rs_pf_bhs_iterator;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
-	/* used to validate BHS prefetch and current block stay in sync */
-	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 44d0885d9e..b1b09bbac2 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -933,8 +933,6 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
-	result->rs_pf_bhs_iterator = NULL;
-	result->prefetch_maximum = 0;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -1000,12 +998,6 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1022,12 +1014,6 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 60916bf0d0..430668f597 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1758,11 +1758,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1770,10 +1766,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.40.1

#79Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#78)
17 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 25, 2024 at 12:07:09PM -0400, Melanie Plageman wrote:

On Sun, Mar 24, 2024 at 06:37:20PM -0400, Melanie Plageman wrote:

On Sun, Mar 24, 2024 at 5:59 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

BTW when you say "up to 'Make table_scan_bitmap_next_block() async
friendly'" do you mean including that patch, or that this is the first
patch that is not one of the independently useful patches.

I think the code is easier to understand with "Make
table_scan_bitmap_next_block() async friendly". Prior to that commit,
table_scan_bitmap_next_block() could return false even when the bitmap
has more blocks and expects the caller to handle this and invoke it
again. I think that interface is very confusing. The downside of the
code in that state is that the code for prefetching is still in the
BitmapHeapNext() code and the code for getting the current block is in
the heap AM-specific code. I took a stab at fixing this in v9's 0013,
but the outcome wasn't very attractive.

What I will do tomorrow is reorder and group the commits such that all
of the commits that are useful independent of streaming read are first
(I think 0014 and 0015 are independently valuable but they are on top
of some things that are only useful to streaming read because they are
more recently requested changes). I think I can actually do a bit of
simplification in terms of how many commits there are and what is in
each. Just to be clear, v9 is still reviewable. I am just going to go
back and change what is included in each commit.

So, attached v10 does not include the new version of streaming read API.
I focused instead on the refactoring patches commit regrouping I
mentioned here.

Attached v11 has the updated Read Stream API Thomas sent this morning
[1]: /messages/by-id/CA+hUKGJTwrS7F=uJPx3SeigMiQiW+LJaOkjGyZdCntwyMR=uAw@mail.gmail.com

- Melanie

[1]: /messages/by-id/CA+hUKGJTwrS7F=uJPx3SeigMiQiW+LJaOkjGyZdCntwyMR=uAw@mail.gmail.com

Attachments:

v11-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From c8bdc1f2143adb2d9a5c9f8f69c249b307287a1a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v11 01/17] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 8d3675be95..a254e3175b 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aab..93fdcd226b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v11-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 6e41737489dbeb07bc9f0cf9c595c11115cb985b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v11 02/17] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 93fdcd226b..c64530674b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -742,16 +752,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v11-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From 523d1a454c77ccb8734a16b02338145deacd0a60 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v11 03/17] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 2f6527df0d..ed3a3607b7 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -948,6 +948,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1036,6 +1038,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1055,6 +1063,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6abfe36dec..5ba8cb3657 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2182,6 +2183,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2294,6 +2313,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c64530674b..83d9db8f39 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,11 +185,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	node->ss.ps.state->es_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	extra_flags);
 		}
 
 		node->initialized = true;
@@ -207,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -228,37 +232,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -301,52 +282,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +531,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +601,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +610,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +654,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -740,8 +697,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +707,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index f112245373..c7a538221a 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index fc0e702715..ae758857bd 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -62,6 +62,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -963,9 +970,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 1774c56ae3..6871db9b21 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1785,10 +1785,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1808,9 +1805,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v11-0004-BitmapPrefetch-use-prefetch-block-recheck-for-sk.patchtext/x-diff; charset=us-asciiDownload
From 54afa2d047bd10d451c7120ec33e476974534219 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v11 04/17] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 83d9db8f39..5df3b5ca46 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -474,14 +474,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -532,7 +527,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v11-0005-Update-BitmapAdjustPrefetchIterator-parameter-ty.patchtext/x-diff; charset=us-asciiDownload
From 227a1ea3d6ceeecc57538a3a4ecb4839fd769445 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v11 05/17] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5df3b5ca46..404de0595e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -230,7 +230,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -341,7 +341,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -360,7 +360,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v11-0006-table_scan_bitmap_next_block-returns-lossy-or-ex.patchtext/x-diff; charset=us-asciiDownload
From 42ad33d1f16aeb9f763a896f8677254292f9b4c2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v11 06/17] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 5ba8cb3657..ce47a158ae 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2172,7 +2172,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2300,6 +2301,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 404de0595e..c95e3412da 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
+		bool		valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -232,12 +232,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ae758857bd..5c2a7b7422 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -815,6 +815,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -830,7 +833,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -2023,14 +2027,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2041,7 +2047,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.40.1

v11-0007-Reduce-scope-of-BitmapHeapScan-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From 8fec5f876636383e802dbb10c107892bb71a4d8d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v11 07/17] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c95e3412da..49938c9ed4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +202,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -221,9 +219,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v11-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From 836b7922f3d2c85472525d22304436409f06fd90 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v11 08/17] Remove table_scan_bitmap_next_tuple parameter
 tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ce47a158ae..ddcdbbaf7e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2308,7 +2308,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 49938c9ed4..282dcb9791 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -286,7 +286,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5c2a7b7422..9c7b8bf162 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -806,10 +806,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -840,15 +837,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2060,7 +2052,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2072,7 +2063,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v11-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 9affa3100a127c747608e3cd8726696aabe93530 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v11 09/17] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 195 insertions(+), 149 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ddcdbbaf7e..196f69e30e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2172,18 +2172,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2202,16 +2235,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2303,7 +2327,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 282dcb9791..7e73583fe5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +109,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +161,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -202,55 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool		valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -272,45 +232,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno > node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,13 +311,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -356,14 +335,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -388,7 +370,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -466,6 +451,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -523,6 +509,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -584,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -597,13 +581,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -634,28 +618,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -688,8 +668,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -697,9 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304a..92b829cebc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9c7b8bf162..68478d16b2 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -799,19 +800,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -830,8 +826,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -968,9 +964,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1030,6 +1030,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1040,6 +1055,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -2016,19 +2046,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2038,8 +2066,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6871db9b21..8688bc5ab0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1783,8 +1783,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1793,9 +1791,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1803,8 +1803,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1813,9 +1811,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v11-0010-Unify-parallel-and-serial-BitmapHeapScan-iterato.patchtext/x-diff; charset=us-asciiDownload
From 3f3bb4559e8a9862fb6c56c8de0c2e4abc69e5c2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 25 Mar 2024 11:05:51 -0400
Subject: [PATCH v11 10/17] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to both
TBMIterator and TBMSharedIterators. This encapsulates the parallel and serial
iterators and their access and makes the bitmap heap scan code a bit cleaner.
This naturally lends itself to a bit of reorganization of the
!node->initialized path in BitmapHeapNext(). Now, on the first scan, the the
iterator is created after the scan descriptor is created.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 163 ++++++++++++----------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  29 +---
 src/include/executor/nodeBitmapHeapscan.h |  10 ++
 src/include/nodes/execnodes.h             |   8 +-
 src/tools/pgindent/typedefs.list          |   1 +
 7 files changed, 116 insertions(+), 107 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 196f69e30e..2d9e0e1a9f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2191,10 +2191,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		tbmres = bhs_iterate(scan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 7e73583fe5..fe471a8a0c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -56,6 +56,56 @@ static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
+static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
+											 dsa_pointer shared_area,
+											 dsa_area *personal_area);
+
+BitmapHeapIterator *
+bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_area)
+{
+	BitmapHeapIterator *result = palloc(sizeof(BitmapHeapIterator));
+
+	result->serial = NULL;
+	result->parallel = NULL;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(shared_area))
+		result->parallel = tbm_attach_shared_iterate(personal_area, shared_area);
+	else
+		result->serial = tbm_begin_iterate(tbm);
+
+	return result;
+}
+
+TBMIterateResult *
+bhs_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		return tbm_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
+
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+	{
+		tbm_end_iterate(iterator->serial);
+		iterator->serial = NULL;
+	}
+	else
+	{
+		tbm_end_shared_iterate(iterator->parallel);
+		iterator->parallel = NULL;
+	}
+
+	pfree(iterator);
+}
 
 
 /* ----------------------------------------------------------------
@@ -97,43 +147,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate)
+		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
+			if (init_shared_state)
 			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
@@ -154,21 +184,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
 			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -198,8 +216,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  dsa);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			node->pf_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
+												  dsa);
+			/* Only used for serial BHS */
+			node->prefetch_pages = 0;
+			node->prefetch_target = -1;
+		}
+#endif							/* USE_PREFETCH */
 
 		node->initialized = true;
 
@@ -280,7 +311,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			node->pf_iterator &&
 			node->pfblockno > node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -321,12 +352,11 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
@@ -335,7 +365,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = bhs_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -348,8 +378,6 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -371,7 +399,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -431,23 +459,22 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 				node->prefetch_pages++;
@@ -475,8 +502,6 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (1)
@@ -500,12 +525,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 
@@ -572,18 +597,17 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	if (node->pf_iterator)
+	{
+		bhs_end_iterate(node->pf_iterator);
+		node->pf_iterator = NULL;
+	}
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -628,12 +652,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+	if (node->pf_iterator)
+		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -671,11 +693,10 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
+	scanstate->pf_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc..fb22f305bf 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,12 +20,12 @@
 #include "storage/buf.h"
 #include "storage/spin.h"
 #include "utils/relcache.h"
+#include "executor/nodeBitmapHeapscan.h"
 
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
-struct TBMSharedIterator;
+struct BitmapHeapIterator;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -44,8 +44,7 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	struct BitmapHeapIterator *rs_bhs_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 68478d16b2..459e123e92 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -968,8 +968,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
+	result->rs_bhs_iterator = NULL;
 	return result;
 }
 
@@ -1032,17 +1031,8 @@ table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1057,17 +1047,8 @@ table_rescan(TableScanDesc scan,
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index ea003a9caa..cb56d20dc6 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -28,5 +28,15 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 										  ParallelContext *pcxt);
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+} BitmapHeapIterator;
+
+extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
+
 
 #endif							/* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8688bc5ab0..52cedd1b35 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1778,6 +1778,8 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
+struct BitmapHeapIterator;
+
 /* ----------------
  *	 BitmapHeapScanState information
  *
@@ -1786,12 +1788,11 @@ typedef struct ParallelBitmapHeapState
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
+ *		pf_iterator        for prefetching ahead of current page
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1806,12 +1807,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index cfa9d5aaea..a6562d19a6 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.40.1

v11-0011-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From 5621e637fd815e6c7fd5ee492678c943cdac82ea Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 17:09:12 -0400
Subject: [PATCH v11 11/17] table_scan_bitmap_next_block counts lossy and exact
 pages

Now that the table_scan_bitmap_next_block() callback only returns false
when the bitmap is exhausted, it is simpler to move the management of
the lossy and exact page counters into it. We will eventually remove
this callback and table_scan_bitmap_next_tuple() will update those
counters when a new block is read in.
---
 src/backend/access/heap/heapam_handler.c  |  8 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c |  9 ++-------
 src/include/access/tableam.h              | 21 +++++++++++++--------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2d9e0e1a9f..81a7488007 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2172,7 +2172,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+							  bool *recheck, BlockNumber *blockno,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block;
@@ -2322,7 +2323,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fe471a8a0c..076e1ff674 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -119,7 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	bool		lossy;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -298,14 +297,10 @@ new_page:
 
 		BitmapAdjustPrefetchIterator(node);
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+										  &node->lossy_pages, &node->exact_pages))
 			break;
 
-		if (lossy)
-			node->lossy_pages++;
-		else
-			node->exact_pages++;
-
 		/*
 		 * If serial, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 459e123e92..bb2b79717c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -808,8 +808,8 @@ typedef struct TableAmRoutine
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * lossy indicates whether or not the block's representation in the bitmap
-	 * is lossy or exact.
+	 * lossy_pages is incremented if the block's representation in the bitmap
+	 * is lossy, otherwise, exact_pages is incremented.
 	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
@@ -826,8 +826,10 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+										   bool *recheck,
+										   BlockNumber *blockno,
+										   long *lossy_pages,
+										   long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -2029,15 +2031,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap table scan.
  * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy is set to true
- * if bitmap is lossy for the selected block and false otherwise.
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented if bitmap is lossy for the selected block and exact_pages is
+ * incremented otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+							 bool *recheck, BlockNumber *blockno,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2048,7 +2052,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+														   blockno, lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v11-0012-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From f457af280f8d84c43e4f6cf5a0cbd76bb06f5f19 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v11 12/17] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 33 +++++++--------------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 28 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fc..1dc4c99bf9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1463,12 +1449,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	TBMSharedIterator *iterator;
 	TBMSharedIteratorState *istate;
 
-	/*
-	 * Create the TBMSharedIterator struct, with enough trailing space to
-	 * serve the needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639b..432fae5296 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.40.1

v11-0013-Separate-TBM-Shared-Iterator-and-TBMIterateResul.patchtext/x-diff; charset=us-asciiDownload
From 7fa873c6bc40682f58193d8bc00848d5e2f5cb16 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v11 13/17] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 30 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 47 ++++++++-------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/executor/nodeBitmapHeapscan.h |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 8 files changed, 113 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb..3aa457a29e 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544..033d525339 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 81a7488007..f7e4d1094d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2180,7 +2180,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2192,9 +2192,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = bhs_iterate(scan->rs_bhs_iterator);
+		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2209,11 +2209,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2221,19 +2221,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2262,7 +2262,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2271,9 +2271,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2323,7 +2323,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 076e1ff674..78f79aafff 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -77,15 +77,16 @@ bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_ar
 	return result;
 }
 
-TBMIterateResult *
-bhs_iterate(BitmapHeapIterator *iterator)
+void
+bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result)
 {
 	Assert(iterator);
+	Assert(result);
 
 	if (iterator->serial)
-		return tbm_iterate(iterator->serial);
+		tbm_iterate(iterator->serial, result);
 	else
-		return tbm_shared_iterate(iterator->parallel);
+		tbm_shared_iterate(iterator->parallel, result);
 }
 
 void
@@ -348,7 +349,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
 	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -360,8 +361,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = bhs_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -394,8 +395,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = bhs_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -462,10 +463,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -473,7 +476,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -482,13 +485,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -501,7 +504,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -520,8 +523,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = bhs_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -529,17 +532,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1dc4c99bf9..309a44bdb8 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae..3b432263bb 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index cb56d20dc6..3c330f86e6 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -34,7 +34,7 @@ typedef struct BitmapHeapIterator
 	struct TBMSharedIterator *parallel;
 } BitmapHeapIterator;
 
-extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+extern void bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result);
 
 extern void bhs_end_iterate(BitmapHeapIterator *iterator);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae5296..f000c1af28 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.40.1

v11-0014-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchtext/x-diff; charset=us-asciiDownload
From 5eb00d2b400eb58e532a128946a57f79aef6434d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 09:42:23 -0400
Subject: [PATCH v11 14/17] Push BitmapHeapScan prefetch code into heapam.c

In preparation for transitioning to using the streaming read API for
prefetching [1], move all of the BitmapHeapScanState members related to
prefetching and the functions for accessing them into the
HeapScanDescData and TableScanDescData. Members that still need to be
accessed in BitmapHeapNext() could not be moved into heap AM-specific
code. Specifically, parallel iterator setup requires several components
which seem odd to pass to the table AM API.

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  26 ++
 src/backend/access/heap/heapam_handler.c  | 262 +++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 341 ++--------------------
 src/include/access/heapam.h               |  17 ++
 src/include/access/relscan.h              |   8 +
 src/include/access/tableam.h              |  26 +-
 src/include/nodes/execnodes.h             |  14 -
 7 files changed, 355 insertions(+), 339 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index ed3a3607b7..614d715fc7 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -948,8 +948,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+
+	scan->rs_base.blockno = InvalidBlockNumber;
+
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
+	scan->pvmbuffer = InvalidBuffer;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1032,6 +1040,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
+	scan->rs_base.blockno = InvalidBlockNumber;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	/*
 	 * unpin scan buffers
 	 */
@@ -1044,6 +1058,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1069,6 +1089,12 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f7e4d1094d..68bbb6f88c 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -61,6 +61,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
+static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2170,6 +2173,73 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+static inline void
+BitmapAdjustPrefetchIterator(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	TBMIterateResult tbmpre;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			scan->prefetch_pages--;
+		}
+		else if (prefetch_iterator)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblockno = tbmpre.blockno;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (scan->rs_base.prefetch_maximum > 0)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (prefetch_iterator)
+			{
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblockno = tbmpre.blockno;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  bool *recheck, BlockNumber *blockno,
@@ -2188,6 +2258,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(hscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2328,6 +2400,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->bm_parallel == NULL &&
+		scan->rs_pf_bhs_iterator &&
+		hscan->pfblockno > hscan->rs_base.blockno)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(hscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2338,6 +2422,154 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
+		else
+			scan->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+
+	if (pstate == NULL)
+	{
+		if (prefetch_iterator)
+		{
+			while (scan->prefetch_pages < scan->prefetch_target)
+			{
+				TBMIterateResult tbmpre;
+				bool		skip_fetch;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre.blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		if (prefetch_iterator)
+		{
+			while (1)
+			{
+				TBMIterateResult tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+
+				scan->pfblockno = tbmpre.blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
@@ -2363,6 +2595,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!scan->bm_parallel)
+	{
+		if (hscan->prefetch_target < scan->prefetch_maximum)
+			hscan->prefetch_target++;
+	}
+	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&scan->bm_parallel->mutex);
+		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+			scan->bm_parallel->prefetch_target++;
+		SpinLockRelease(&scan->bm_parallel->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(hscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 78f79aafff..187b288e68 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
 											 dsa_pointer shared_area,
@@ -122,7 +118,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
@@ -142,7 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
 	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
 	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
 	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
@@ -154,7 +149,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate || init_shared_state)
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		int			pf_maximum = 0;
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
+#endif
+
+		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
@@ -169,23 +173,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * dsa_pointer of the iterator state which will be used by
 				 * multiple processes to iterate jointly.
 				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
-					pstate->prefetch_iterator =
+					node->pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
 				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
+				BitmapDoneInitializingSharedState(node->pstate);
 			}
 		}
 
@@ -216,19 +213,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		scan->prefetch_maximum = pf_maximum;
+		scan->bm_parallel = node->pstate;
+
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
 #ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
+		if (scan->prefetch_maximum > 0)
 		{
-			node->pf_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
-												  dsa);
-			/* Only used for serial BHS */
-			node->prefetch_pages = 0;
-			node->prefetch_target = -1;
+			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
+														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
+														 dsa);
 		}
 #endif							/* USE_PREFETCH */
 
@@ -243,36 +240,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
 
 			/*
 			 * If we are using lossy info, we have to recheck the qual
@@ -296,23 +263,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			node->pf_iterator &&
-			node->pfblockno > node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,219 +289,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -594,22 +334,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->pf_iterator)
-	{
-		bhs_end_iterate(node->pf_iterator);
-		node->pf_iterator = NULL;
-	}
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -648,14 +378,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->pf_iterator)
-		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -688,17 +414,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->pf_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -738,13 +458,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -828,7 +541,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index c7a538221a..4726d31403 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -82,6 +82,23 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
+	/*
+	 * These fields only used for prefetching in bitmap table scans
+	 */
+
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
+
+	/*
+	 * These fields only used in serial BHS
+	 */
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block  */
+	BlockNumber pfblockno;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index fb22f305bf..7938b741d6 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -26,6 +26,7 @@
 struct ParallelTableScanDescData;
 
 struct BitmapHeapIterator;
+struct ParallelBitmapHeapState;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -45,6 +46,13 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
+	struct BitmapHeapIterator *rs_pf_bhs_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+	struct ParallelBitmapHeapState *bm_parallel;
+	/* used to validate BHS prefetch and current block stay in sync */
+	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index bb2b79717c..799ac013d4 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -811,17 +811,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the block's representation in the bitmap
 	 * is lossy, otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -971,6 +960,9 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
+	result->rs_pf_bhs_iterator = NULL;
+	result->prefetch_maximum = 0;
+	result->bm_parallel = NULL;
 	return result;
 }
 
@@ -1035,6 +1027,12 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1051,6 +1049,12 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 52cedd1b35..60916bf0d0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1785,18 +1785,11 @@ struct BitmapHeapIterator;
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		pf_iterator        for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1804,18 +1797,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v11-0015-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From 7ac2a79503d7110c19a7c335fd5ab5422166b6a6 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 15:43:10 -0400
Subject: [PATCH v11 15/17] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block(). Heap AM's implementation of
table_scan_bitmap_next_tuple() now calls the original
heapam_scan_bitmap_next_block() function, but it is no longer an
implementation of a table AM callback but instead a helper for
heapam_scan_bitmap_next_tuple()
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 48 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 45 ++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 75 +++++------------------
 6 files changed, 63 insertions(+), 111 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 614d715fc7..5fc052f019 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -319,6 +319,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 68bbb6f88c..80f210b405 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2167,12 +2167,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
- */
-
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
  *
@@ -2206,8 +2200,8 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
@@ -2570,30 +2564,43 @@ BitmapPrefetch(HeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
-		return true;
-	}
+		if (hscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			hscan->rs_empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2975,7 +2982,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index ce637a5a5d..1d6b03d1ca 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 187b288e68..2f9387e51a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -230,44 +230,35 @@ BitmapHeapNext(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 
 		node->initialized = true;
-
-		goto new_page;
 	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346..cf56cc572f 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 799ac013d4..5979ddee8b 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -799,36 +799,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the block's representation in the bitmap
-	 * is lossy, otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   BlockNumber *blockno,
-										   long *lossy_pages,
-										   long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -2033,44 +2017,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented if bitmap is lossy for the selected block and exact_pages is
- * incremented otherwise.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno,
-							 long *lossy_pages, long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   blockno, lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2081,7 +2034,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v11-0016-v10-Read-Stream-API.patchtext/x-diff; charset=us-asciiDownload
From 88dde25e1b9a9b340ae57161f098b6351d538f3c Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 26 Feb 2024 23:48:31 +1300
Subject: [PATCH v11 16/17] v10 Read Stream API

Part 1:

Provide vectored variant of ReadBuffer().

Break ReadBuffer() up into two steps: StartReadBuffers() and
WaitReadBuffers().  This has two advantages:

1.  Multiple consecutive blocks can be read with one system call.
2.  Advice (hints of future reads) can optionally be issued to the kernel.

The traditional ReadBuffer() function is now implemented in terms of
those functions, to avoid duplication.  For now we still only read a
block at a time so there is no change to generated system calls yet, but
later commits will provide infrastructure to help build up larger calls.

Callers should respect the new GUC io_combine_limit, and the limit on
per-backend pins which is now exposed as a public interface.

With some more infrastructure in later work, StartReadBuffers() could
be extended to start real asynchronous I/O instead of advice.

Part 2:

Provide API for streaming relation data.

Introduce an abstraction where relation data can be accessed as a
stream of buffers, with an implementation that is more efficient than
the equivalent sequence of ReadBuffer() calls.

Client code supplies a callback that can say which block number is
wanted next, and then consumes individual buffers one at a time from the
stream.  This division allows read_stream.c to build up large calls to
StartReadBuffers() up to io_combine_limit, and issue fadvise() advice
ahead of time in a systematic way when random access is detected.

This API is based on an idea from Andres Freund to pave the way for
asynchronous I/O in future work as required to support direct I/O.  The
goal is to have an abstraction that insulates client code from future
changes to the I/O subsystem.

An extended API may be necessary in future for more complicated cases
(for example recovery, whose LsnReadQueue device in xlogprefetcher.c is
a distant cousin of this code that should eventually be replaced by it),
but this basic API is sufficient for many common usage patterns
involving predictable access to a single relation fork.

Author: Thomas Munro <thomas.munro@gmail.com>
Author: Andres Freund <andres@anarazel.de> (optimization tweaks)
Reviewed-by: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Dilip Kumar <dilipbalaut@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CA+hUKGJkOiOCa+mag4BF+zHo7qo=o9CFheB8=g6uT5TUm2gkvA@mail.gmail.com
---
 doc/src/sgml/config.sgml                      |  14 +
 src/backend/storage/Makefile                  |   2 +-
 src/backend/storage/aio/Makefile              |  14 +
 src/backend/storage/aio/meson.build           |   5 +
 src/backend/storage/aio/read_stream.c         | 733 ++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c           | 709 +++++++++++------
 src/backend/storage/buffer/localbuf.c         |  14 +-
 src/backend/storage/meson.build               |   1 +
 src/backend/utils/misc/guc_tables.c           |  14 +
 src/backend/utils/misc/postgresql.conf.sample |   1 +
 src/include/storage/bufmgr.h                  |  41 +-
 src/include/storage/read_stream.h             |  62 ++
 src/tools/pgindent/typedefs.list              |   3 +
 13 files changed, 1386 insertions(+), 227 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/read_stream.c
 create mode 100644 src/include/storage/read_stream.h

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 5468637e2e..f3736000ad 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2719,6 +2719,20 @@ include_dir 'conf.d'
        </listitem>
       </varlistentry>
 
+      <varlistentry id="guc-io-combine-limit" xreflabel="io_combine_limit">
+       <term><varname>io_combine_limit</varname> (<type>integer</type>)
+       <indexterm>
+        <primary><varname>io_combine_limit</varname> configuration parameter</primary>
+       </indexterm>
+       </term>
+       <listitem>
+        <para>
+         Controls the largest I/O size in operations that combine I/O.
+         The default is 128kB.
+        </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry id="guc-max-worker-processes" xreflabel="max_worker_processes">
        <term><varname>max_worker_processes</varname> (<type>integer</type>)
        <indexterm>
diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca2..eec03f6f2b 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 0000000000..2f29a9ec4d
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	read_stream.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 0000000000..10e1aa3b20
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'read_stream.c',
+)
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
new file mode 100644
index 0000000000..4e293e0df6
--- /dev/null
+++ b/src/backend/storage/aio/read_stream.c
@@ -0,0 +1,733 @@
+/*-------------------------------------------------------------------------
+ *
+ * read_stream.c
+ *	  Mechanism for accessing buffered relation data with look-ahead
+ *
+ * Code that needs to access relation data typically pins blocks one at a
+ * time, often in a predictable order that might be sequential or data-driven.
+ * Calling the simple ReadBuffer() function for each block is inefficient,
+ * because blocks that are not yet in the buffer pool require I/O operations
+ * that are small and might stall waiting for storage.  This mechanism looks
+ * into the future and calls StartReadBuffers() and WaitReadBuffers() to read
+ * neighboring blocks together and ahead of time, with an adaptive look-ahead
+ * distance.
+ *
+ * A user-provided callback generates a stream of block numbers that is used
+ * to form reads of up to io_combine_limit, by attempting to merge them with a
+ * pending read.  When that isn't possible, the existing pending read is sent
+ * to StartReadBuffers() so that a new one can begin to form.
+ *
+ * The algorithm for controlling the look-ahead distance tries to classify the
+ * stream into three ideal behaviors:
+ *
+ * A) No I/O is necessary, because the requested blocks are fully cached
+ * already.  There is no benefit to looking ahead more than one block, so
+ * distance is 1.  This is the default initial assumption.
+ *
+ * B) I/O is necessary, but fadvise is undesirable because the access is
+ * sequential, or impossible because direct I/O is enabled or the system
+ * doesn't support advice.  There is no benefit in looking ahead more than
+ * io_combine_limit, because in this case only goal is larger read system
+ * calls.  Looking further ahead would pin many buffers and perform
+ * speculative work looking ahead for no benefit.
+ *
+ * C) I/O is necesssary, it appears random, and this system supports fadvise.
+ * We'll look further ahead in order to reach the configured level of I/O
+ * concurrency.
+ *
+ * The distance increases rapidly and decays slowly, so that it moves towards
+ * those levels as different I/O patterns are discovered.  For example, a
+ * sequential scan of fully cached data doesn't bother looking ahead, but a
+ * sequential scan that hits a region of uncached blocks will start issuing
+ * increasingly wide read calls until it plateaus at io_combine_limit.
+ *
+ * The main data structure is a circular queue of buffers of size
+ * max_pinned_buffers plus some extra space for technical reasons, ready to be
+ * returned by read_stream_next_buffer().  Each buffer also has an optional
+ * variable sized object that is passed from the callback to the consumer of
+ * buffers.
+ *
+ * Parallel to the queue of buffers, there is a circular queue of in-progress
+ * I/Os that have been started with StartReadBuffers(), and for which
+ * WaitReadBuffers() must be called before returning the buffer.
+ *
+ * For example, if the callback return block numbers 10, 42, 43, 60 in
+ * successive calls, then these data structures might appear as follows:
+ *
+ *                          buffers buf/data       ios
+ *
+ *                          +----+  +-----+       +--------+
+ *                          |    |  |     |  +----+ 42..44 | <- oldest_io_index
+ *                          +----+  +-----+  |    +--------+
+ *   oldest_buffer_index -> | 10 |  |  ?  |  | +--+ 60..60 |
+ *                          +----+  +-----+  | |  +--------+
+ *                          | 42 |  |  ?  |<-+ |  |        | <- next_io_index
+ *                          +----+  +-----+    |  +--------+
+ *                          | 43 |  |  ?  |    |  |        |
+ *                          +----+  +-----+    |  +--------+
+ *                          | 44 |  |  ?  |    |  |        |
+ *                          +----+  +-----+    |  +--------+
+ *                          | 60 |  |  ?  |<---+
+ *                          +----+  +-----+
+ *     next_buffer_index -> |    |  |     |
+ *                          +----+  +-----+
+ *
+ * In the example, 5 buffers are pinned, and the next buffer to be streamed to
+ * the client is block 10.  Block 10 was a hit and has no associated I/O, but
+ * the range 42..44 requires an I/O wait before its buffers are returned, as
+ * does block 60.
+ *
+ *
+ * Portions Copyright (c) 2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  src/backend/storage/aio/read_stream.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/pg_tablespace.h"
+#include "miscadmin.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+#include "storage/read_stream.h"
+#include "utils/memdebug.h"
+#include "utils/rel.h"
+#include "utils/spccache.h"
+
+typedef struct InProgressIO
+{
+	int16		buffer_index;
+	ReadBuffersOperation op;
+} InProgressIO;
+
+/*
+ * State for managing a stream of reads.
+ */
+struct ReadStream
+{
+	int16		max_ios;
+	int16		ios_in_progress;
+	int16		queue_size;
+	int16		max_pinned_buffers;
+	int16		pinned_buffers;
+	int16		distance;
+	bool		advice_enabled;
+
+	/*
+	 * Sometimes we need to be able to 'unget' a block number to resolve a
+	 * flow control problem when I/Os are split.
+	 */
+	BlockNumber unget_blocknum;
+	bool		have_unget_blocknum;
+
+	/*
+	 * The callback that will tell us which block numbers to read, and an
+	 * opaque pointer that will be pass to it for its own purposes.
+	 */
+	ReadStreamBlockNumberCB callback;
+	void	   *callback_private_data;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* The read operation we are currently preparing. */
+	BlockNumber pending_read_blocknum;
+	int16		pending_read_nblocks;
+
+	/* Space for buffers and optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+
+	/* Read operations that have been started but not waited for yet. */
+	InProgressIO *ios;
+	int16		oldest_io_index;
+	int16		next_io_index;
+
+	/* Circular queue of buffers. */
+	int16		oldest_buffer_index;	/* Next pinned buffer to return */
+	int16		next_buffer_index;	/* Index of next buffer to pin */
+	Buffer		buffers[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/*
+ * Return a pointer to the per-buffer data by index.
+ */
+static inline void *
+get_per_buffer_data(ReadStream *stream, int16 buffer_index)
+{
+	return (char *) stream->per_buffer_data +
+		stream->per_buffer_data_size * buffer_index;
+}
+
+/*
+ * Ask the callback which block it would like us to read next, with a small
+ * buffer in front to allow streaming_unget_block() to work.
+ */
+static inline BlockNumber
+read_stream_get_block(ReadStream *stream, void *per_buffer_data)
+{
+	if (!stream->have_unget_blocknum)
+		return stream->callback(stream,
+								stream->callback_private_data,
+								per_buffer_data);
+
+	/*
+	 * You can only unget one block, and next_buffer_index can't change across
+	 * a get, unget, get sequence, so the callback's per_buffer_data, if any,
+	 * is still present in the correct slot.  We just have to return the
+	 * previous block number.
+	 */
+	stream->have_unget_blocknum = false;
+	return stream->unget_blocknum;
+}
+
+/*
+ * In order to deal with short reads in StartReadBuffers(), we sometimes need
+ * to defer handling of a block until later.
+ */
+static inline void
+read_stream_unget_block(ReadStream *stream, BlockNumber blocknum)
+{
+	Assert(!stream->have_unget_blocknum);
+	stream->have_unget_blocknum = true;
+	stream->unget_blocknum = blocknum;
+}
+
+static void
+read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
+{
+	bool		need_wait;
+	int			nblocks;
+	int			flags;
+	int16		io_index;
+	int16		overflow;
+	int16		buffer_index;
+
+	/* This should only be called with a pending read. */
+	Assert(stream->pending_read_nblocks > 0);
+	Assert(stream->pending_read_nblocks <= io_combine_limit);
+
+	/* We had better not exceed the pin limit by starting this read. */
+	Assert(stream->pinned_buffers + stream->pending_read_nblocks <=
+		   stream->max_pinned_buffers);
+
+	/* We had better not be overwriting an existing pinned buffer. */
+	if (stream->pinned_buffers > 0)
+		Assert(stream->next_buffer_index != stream->oldest_buffer_index);
+	else
+		Assert(stream->next_buffer_index == stream->oldest_buffer_index);
+
+	/*
+	 * If advice hasn't been suppressed, this system supports it, and this
+	 * isn't a strictly sequential pattern, then we'll issue advice.
+	 */
+	if (!suppress_advice &&
+		stream->advice_enabled &&
+		stream->pending_read_blocknum != stream->seq_blocknum)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else
+		flags = 0;
+
+	/* We say how many blocks we want to read, but may be smaller on return. */
+	buffer_index = stream->next_buffer_index;
+	io_index = stream->next_io_index;
+	nblocks = stream->pending_read_nblocks;
+	need_wait = StartReadBuffers(&stream->ios[io_index].op,
+								 &stream->buffers[buffer_index],
+								 stream->pending_read_blocknum,
+								 &nblocks,
+								 flags);
+	stream->pinned_buffers += nblocks;
+
+	/* Remember whether we need to wait before returning this buffer. */
+	if (!need_wait)
+	{
+		/* Look-ahead distance decays, no I/O necessary (behavior A). */
+		if (stream->distance > 1)
+			stream->distance--;
+	}
+	else
+	{
+		/*
+		 * Remember to call WaitReadBuffers() before returning head buffer.
+		 * Look-ahead distance will be adjusted after waiting.
+		 */
+		stream->ios[io_index].buffer_index = buffer_index;
+		if (++stream->next_io_index == stream->max_ios)
+			stream->next_io_index = 0;
+		Assert(stream->ios_in_progress < stream->max_ios);
+		stream->ios_in_progress++;
+		stream->seq_blocknum = stream->pending_read_blocknum + nblocks;
+	}
+
+	/*
+	 * We gave a contiguous range of buffer space to StartReadBuffers(), but
+	 * we want it to wrap around at queue_size.  Slide overflowing buffers to
+	 * the front of the array.
+	 */
+	overflow = (buffer_index + nblocks) - stream->queue_size;
+	if (overflow > 0)
+		memmove(&stream->buffers[0],
+				&stream->buffers[stream->queue_size],
+				sizeof(stream->buffers[0]) * overflow);
+
+	/* Compute location of start of next read, without using % operator. */
+	buffer_index += nblocks;
+	if (buffer_index >= stream->queue_size)
+		buffer_index -= stream->queue_size;
+	Assert(buffer_index >= 0 && buffer_index < stream->queue_size);
+	stream->next_buffer_index = buffer_index;
+
+	/* Adjust the pending read to cover the remaining portion, if any. */
+	stream->pending_read_blocknum += nblocks;
+	stream->pending_read_nblocks -= nblocks;
+}
+
+static void
+read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
+{
+	while (stream->ios_in_progress < stream->max_ios &&
+		   stream->pinned_buffers + stream->pending_read_nblocks < stream->distance)
+	{
+		BlockNumber blocknum;
+		int16		buffer_index;
+		void	   *per_buffer_data;
+
+		if (stream->pending_read_nblocks == io_combine_limit)
+		{
+			read_stream_start_pending_read(stream, suppress_advice);
+			suppress_advice = false;
+			continue;
+		}
+
+		/*
+		 * See which block the callback wants next in the stream.  We need to
+		 * compute the index of the Nth block of the pending read including
+		 * wrap-around, but we don't want to use the expensive % operator.
+		 */
+		buffer_index = stream->next_buffer_index + stream->pending_read_nblocks;
+		if (buffer_index >= stream->queue_size)
+			buffer_index -= stream->queue_size;
+		Assert(buffer_index >= 0 && buffer_index < stream->queue_size);
+		per_buffer_data = get_per_buffer_data(stream, buffer_index);
+		blocknum = read_stream_get_block(stream, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			stream->distance = 0;
+			break;
+		}
+
+		/* Can we merge it with the pending read? */
+		if (stream->pending_read_nblocks > 0 &&
+			stream->pending_read_blocknum + stream->pending_read_nblocks == blocknum)
+		{
+			stream->pending_read_nblocks++;
+			continue;
+		}
+
+		/* We have to start the pending read before we can build another. */
+		if (stream->pending_read_nblocks > 0)
+		{
+			read_stream_start_pending_read(stream, suppress_advice);
+			suppress_advice = false;
+			if (stream->ios_in_progress == stream->max_ios)
+			{
+				/* And we've hit the limit.  Rewind, and stop here. */
+				read_stream_unget_block(stream, blocknum);
+				return;
+			}
+		}
+
+		/* This is the start of a new pending read. */
+		stream->pending_read_blocknum = blocknum;
+		stream->pending_read_nblocks = 1;
+	}
+
+	/*
+	 * Normally we don't start the pending read just because we've hit a
+	 * limit, preferring to give it another chance to grow to a larger size
+	 * once more buffers have been consumed.  However, in cases where that
+	 * can't possibly happen, we might as well start the read immediately.
+	 */
+	if (stream->pending_read_nblocks > 0 &&
+		(stream->distance == stream->pending_read_nblocks ||
+		 stream->distance == 0) &&
+		stream->ios_in_progress < stream->max_ios)
+		read_stream_start_pending_read(stream, suppress_advice);
+}
+
+/*
+ * Create a new streaming read object that can be used to perform the
+ * equivalent of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.  The callback should return block numbers or InvalidBlockNumber to
+ * signal end-of-stream, and if per_buffer_data_size is non-zero, it may also
+ * write extra data for each block into the space provided to it.  It will
+ * also receive callback_private_data for its own purposes.
+ */
+ReadStream *
+read_stream_begin_relation(int flags,
+						   BufferAccessStrategy strategy,
+						   BufferManagerRelation bmr,
+						   ForkNumber forknum,
+						   ReadStreamBlockNumberCB callback,
+						   void *callback_private_data,
+						   size_t per_buffer_data_size)
+{
+	ReadStream *stream;
+	size_t		size;
+	int16		queue_size;
+	int16		max_ios;
+	uint32		max_pinned_buffers;
+	Oid			tablespace_id;
+
+	/* Make sure our bmr's smgr and persistent are populated. */
+	if (bmr.smgr == NULL)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	/*
+	 * Decide how many I/Os we will allow to run at the same time.  That
+	 * currently means advice to the kernel to tell it that we will soon read.
+	 * This number also affects how far we look ahead for opportunities to
+	 * start more I/Os.
+	 */
+	tablespace_id = bmr.smgr->smgr_rlocator.locator.spcOid;
+	if (!OidIsValid(MyDatabaseId) ||
+		(bmr.rel && IsCatalogRelation(bmr.rel)) ||
+		IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
+	{
+		/*
+		 * Avoid circularity while trying to look up tablespace settings or
+		 * before spccache.c is ready.
+		 */
+		max_ios = effective_io_concurrency;
+	}
+	else if (flags & READ_STREAM_MAINTENANCE)
+		max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
+	else
+		max_ios = get_tablespace_io_concurrency(tablespace_id);
+	max_ios = Min(max_ios, PG_INT16_MAX);
+
+	/*
+	 * Choose the maximum number of buffers we're prepared to pin.  We try to
+	 * pin fewer if we can, though.  We clamp it to at least io_combine_limit
+	 * so that we can have a chance to build up a full io_combine_limit sized
+	 * read, even when max_ios is zero.  Be careful not to allow int16 to
+	 * overflow (even though that's not possible with the current GUC range
+	 * limits), allowing also for the spare entry and the overflow space.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, io_combine_limit);
+	max_pinned_buffers = Min(max_pinned_buffers,
+							 PG_INT16_MAX - io_combine_limit - 1);
+
+	/* Don't allow this backend to pin more than its share of buffers. */
+	if (SmgrIsTemp(bmr.smgr))
+		LimitAdditionalLocalPins(&max_pinned_buffers);
+	else
+		LimitAdditionalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * We need one extra entry for buffers and per-buffer data, because users
+	 * of per-buffer data have access to the object until the next call to
+	 * read_stream_next_buffer(), so we need a gap between the head and tail
+	 * of the queue so that we don't clobber it.
+	 */
+	queue_size = max_pinned_buffers + 1;
+
+	/*
+	 * Allocate the object, the buffers, the ios and per_data_data space in
+	 * one big chunk.  Though we have queue_size buffers, we want to be able
+	 * to assume that all the buffers for a single read are contiguous (i.e.
+	 * don't wrap around halfway through), so we allow temporary overflows of
+	 * up to the maximum possible read size by allocating an extra
+	 * io_combine_limit - 1 elements.
+	 */
+	size = offsetof(ReadStream, buffers);
+	size += sizeof(Buffer) * (queue_size + io_combine_limit - 1);
+	size += sizeof(InProgressIO) * Max(1, max_ios);
+	size += per_buffer_data_size * queue_size;
+	size += MAXIMUM_ALIGNOF * 2;
+	stream = (ReadStream *) palloc(size);
+	memset(stream, 0, offsetof(ReadStream, buffers));
+	stream->ios = (InProgressIO *)
+		MAXALIGN(&stream->buffers[queue_size + io_combine_limit - 1]);
+	if (per_buffer_data_size > 0)
+		stream->per_buffer_data = (void *)
+			MAXALIGN(&stream->ios[Max(1, max_ios)]);
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  We can use it as long as
+	 * direct I/O isn't enabled, the caller hasn't promised sequential access
+	 * (overriding our detection heuristics), and max_ios hasn't been set to
+	 * zero.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & READ_STREAM_SEQUENTIAL) == 0 &&
+		max_ios > 0)
+		stream->advice_enabled = true;
+#endif
+
+	/*
+	 * For now, max_ios = 0 is interpreted as max_ios = 1 with advice disabled
+	 * above.  If we had real asynchronous I/O we might need a slightly
+	 * different definition.
+	 */
+	if (max_ios == 0)
+		max_ios = 1;
+
+	stream->max_ios = max_ios;
+	stream->per_buffer_data_size = per_buffer_data_size;
+	stream->max_pinned_buffers = max_pinned_buffers;
+	stream->queue_size = queue_size;
+
+	if (!bmr.smgr)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+	stream->callback = callback;
+	stream->callback_private_data = callback_private_data;
+
+	/*
+	 * Skip the initial ramp-up phase if the caller says we're going to be
+	 * reading the whole relation.  This way we start out assuming we'll be
+	 * doing full io_combine_limit sized reads (behavior B).
+	 */
+	if (flags & READ_STREAM_FULL)
+		stream->distance = Min(max_pinned_buffers, io_combine_limit);
+	else
+		stream->distance = 1;
+
+	/*
+	 * Since we always currently always access the same relation, we can
+	 * initialize parts of the ReadBuffersOperation objects and leave them
+	 * that way, to avoid wasting CPU cycles writing to them for each read.
+	 */
+	for (int i = 0; i < max_ios; ++i)
+	{
+		stream->ios[i].op.bmr = bmr;
+		stream->ios[i].op.forknum = forknum;
+		stream->ios[i].op.strategy = strategy;
+	}
+
+	return stream;
+}
+
+/*
+ * Pull one pinned buffer out of a stream created with
+ * read_stream_begin_buffered().  Each call returns successive blocks in the
+ * order specified by the callback.  If per_buffer_data_size was set to a
+ * non-zero size, *per_buffer_data receives a pointer to the extra per-buffer
+ * data that the callback had a chance to populate, which remains valid until
+ * the next call to read_stream_next_buffer().  When the stream runs out of
+ * data, InvalidBuffer is returned.  The caller may decide to end the stream
+ * early at any time by calling read_stream_end_buffered().
+ */
+Buffer
+read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
+{
+	Buffer		buffer;
+	int16		oldest_buffer_index;
+
+	/*
+	 * A fast path for all-cached scans (behavior A).  This is the same as the
+	 * usual algorithm, but it is specialized for no I/O and no per-buffer
+	 * data, so we can skip the queue management code, stay in the same buffer
+	 * slot and use singular StartReadBuffer().
+	 */
+	if (likely(per_buffer_data == NULL &&
+			   stream->ios_in_progress == 0 &&
+			   stream->pinned_buffers == 1 &&
+			   stream->distance == 1))
+	{
+		BlockNumber next_blocknum;
+
+		/*
+		 * We have a pinned buffer that we need to serve up, but we also want
+		 * to probe the next one before we return, just in case we need to
+		 * start an I/O.  We can re-use the same buffer slot, and an arbitrary
+		 * I/O slot since they're all free.
+		 */
+		oldest_buffer_index = stream->oldest_buffer_index;
+		Assert((oldest_buffer_index + 1) % stream->queue_size ==
+			   stream->next_buffer_index);
+		buffer = stream->buffers[oldest_buffer_index];
+		Assert(buffer != InvalidBuffer);
+		Assert(stream->pending_read_nblocks <= 1);
+		if (unlikely(stream->pending_read_nblocks == 1))
+		{
+			next_blocknum = stream->pending_read_blocknum;
+			stream->pending_read_nblocks = 0;
+		}
+		else
+			next_blocknum = read_stream_get_block(stream, NULL);
+		if (unlikely(next_blocknum == InvalidBlockNumber))
+		{
+			/* End of stream. */
+			stream->distance = 0;
+			stream->next_buffer_index = oldest_buffer_index;
+			/* Pin transferred to caller. */
+			stream->pinned_buffers = 0;
+			return buffer;
+		}
+		/* Call the special single block version, which is marginally faster. */
+		if (unlikely(StartReadBuffer(&stream->ios[0].op,
+									 &stream->buffers[oldest_buffer_index],
+									 next_blocknum,
+									 stream->advice_enabled ?
+									 READ_BUFFERS_ISSUE_ADVICE : 0)))
+		{
+			/* I/O needed.  We'll take the general path next time. */
+			stream->oldest_io_index = 0;
+			stream->next_io_index = stream->max_ios > 1 ? 1 : 0;
+			stream->ios_in_progress = 1;
+			stream->ios[0].buffer_index = oldest_buffer_index;
+			stream->seq_blocknum = next_blocknum + 1;
+			/* Increase look ahead distance (move towards behavior B/C). */
+			stream->distance = Min(2, stream->max_pinned_buffers);
+		}
+		/* Pin transferred to caller, got another one, no net change. */
+		Assert(stream->pinned_buffers == 1);
+		return buffer;
+	}
+
+	if (stream->pinned_buffers == 0)
+	{
+		Assert(stream->oldest_buffer_index == stream->next_buffer_index);
+
+		/* End of stream reached?  */
+		if (stream->distance == 0)
+			return InvalidBuffer;
+
+		/*
+		 * The usual order of operations is that we look ahead at the bottom
+		 * of this function after potentially finishing an I/O and making
+		 * space for more, but if we're just starting up we'll need to crank
+		 * the handle to get started.
+		 */
+		read_stream_look_ahead(stream, true);
+
+		/* End of stream reached? */
+		if (stream->pinned_buffers == 0)
+		{
+			Assert(stream->distance == 0);
+			return InvalidBuffer;
+		}
+	}
+
+	/* Grab the oldest pinned buffer and associated per-buffer data. */
+	Assert(stream->pinned_buffers > 0);
+	oldest_buffer_index = stream->oldest_buffer_index;
+	Assert(oldest_buffer_index >= 0 &&
+		   oldest_buffer_index < stream->queue_size);
+	buffer = stream->buffers[oldest_buffer_index];
+	if (per_buffer_data)
+		*per_buffer_data = get_per_buffer_data(stream, oldest_buffer_index);
+
+	Assert(BufferIsValid(buffer));
+
+	/* Do we have to wait for an associated I/O first? */
+	if (stream->ios_in_progress > 0 &&
+		stream->ios[stream->oldest_io_index].buffer_index == oldest_buffer_index)
+	{
+		int16		io_index = stream->oldest_io_index;
+		int16		distance;
+
+		/* Sanity check that we still agree on the buffers. */
+		Assert(stream->ios[io_index].op.buffers ==
+			   &stream->buffers[oldest_buffer_index]);
+
+		WaitReadBuffers(&stream->ios[io_index].op);
+
+		Assert(stream->ios_in_progress > 0);
+		stream->ios_in_progress--;
+		if (++stream->oldest_io_index == stream->max_ios)
+			stream->oldest_io_index = 0;
+
+		if (stream->ios[io_index].op.flags & READ_BUFFERS_ISSUE_ADVICE)
+		{
+			/* Distance ramps up fast (behavior C). */
+			distance = stream->distance * 2;
+			distance = Min(distance, stream->max_pinned_buffers);
+			stream->distance = distance;
+		}
+		else
+		{
+			/* No advice; move towards io_combine_limit (behavior B). */
+			if (stream->distance > io_combine_limit)
+			{
+				stream->distance--;
+			}
+			else
+			{
+				distance = stream->distance * 2;
+				distance = Min(distance, io_combine_limit);
+				distance = Min(distance, stream->max_pinned_buffers);
+				stream->distance = distance;
+			}
+		}
+	}
+
+#ifdef CLOBBER_FREED_MEMORY
+	/* Clobber old buffer and per-buffer data for debugging purposes. */
+	stream->buffers[oldest_buffer_index] = InvalidBuffer;
+
+	/*
+	 * The caller will get access to the per-buffer data, until the next call.
+	 * We wipe the one before, which is never occupied because queue_size
+	 * allowed one extra element.  This will hopefully trip up client code
+	 * that is holding a dangling pointer to it.
+	 */
+	if (stream->per_buffer_data)
+		wipe_mem(get_per_buffer_data(stream,
+									 oldest_buffer_index == 0 ?
+									 stream->queue_size - 1 :
+									 oldest_buffer_index - 1),
+				 stream->per_buffer_data_size);
+#endif
+
+	/* Pin transferred to caller. */
+	Assert(stream->pinned_buffers > 0);
+	stream->pinned_buffers--;
+
+	/* Advance oldest buffer, with wrap-around. */
+	stream->oldest_buffer_index++;
+	if (stream->oldest_buffer_index == stream->queue_size)
+		stream->oldest_buffer_index = 0;
+
+	/* Prepare for the next call. */
+	read_stream_look_ahead(stream, false);
+
+	return buffer;
+}
+
+/*
+ * Release stream resources.
+ */
+void
+read_stream_end(ReadStream *stream)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead. */
+	stream->distance = 0;
+
+	/* Unpin anything that wasn't consumed. */
+	while ((buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	Assert(stream->pinned_buffers == 0);
+	Assert(stream->ios_in_progress == 0);
+
+	/* Release memory. */
+	pfree(stream);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f0f8d4259c..577bcf6e5d 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -19,6 +19,11 @@
  *		and pin it so that no one can destroy it while this process
  *		is using it.
  *
+ * StartReadBuffers() -- as above, but for multiple contiguous blocks in
+ *		two steps.
+ *
+ * WaitReadBuffers() -- second step of StartReadBuffers().
+ *
  * ReleaseBuffer() -- unpin a buffer
  *
  * MarkBufferDirty() -- mark a pinned buffer's contents as "dirty".
@@ -160,6 +165,9 @@ int			checkpoint_flush_after = DEFAULT_CHECKPOINT_FLUSH_AFTER;
 int			bgwriter_flush_after = DEFAULT_BGWRITER_FLUSH_AFTER;
 int			backend_flush_after = DEFAULT_BACKEND_FLUSH_AFTER;
 
+/* Limit on how many blocks should be handled in single I/O operations. */
+int			io_combine_limit = DEFAULT_IO_COMBINE_LIMIT;
+
 /* local state for LockBufferForCleanup */
 static BufferDesc *PinCountWaitBuf = NULL;
 
@@ -471,10 +479,9 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
-								ReadBufferMode mode, BufferAccessStrategy strategy,
-								bool *hit);
+								ReadBufferMode mode, BufferAccessStrategy strategy);
 static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
 										   ForkNumber fork,
 										   BufferAccessStrategy strategy,
@@ -500,7 +507,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -781,7 +788,6 @@ Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
-	bool		hit;
 	Buffer		buf;
 
 	/*
@@ -794,15 +800,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
-							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+	buf = ReadBuffer_common(BMR_REL(reln),
+							forkNum, blockNum, mode, strategy);
+
 	return buf;
 }
 
@@ -822,13 +822,12 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 						  BlockNumber blockNum, ReadBufferMode mode,
 						  BufferAccessStrategy strategy, bool permanent)
 {
-	bool		hit;
-
 	SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
-							 mode, strategy, &hit);
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
+							 mode, strategy);
 }
 
 /*
@@ -994,35 +993,146 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 	 */
 	if (buffer == InvalidBuffer)
 	{
-		bool		hit;
-
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
-								   fork, extend_to - 1, mode, strategy,
-								   &hit);
+		buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
 	}
 
 	return buffer;
 }
 
 /*
- * ReadBuffer_common -- common logic for all ReadBuffer variants
- *
- * *hit is set to true if the request was satisfied from shared buffer cache.
+ * Zero a buffer and lock it, as part of the implementation of
+ * RBM_ZERO_AND_LOCK or RBM_ZERO_AND_CLEANUP_LOCK.  The buffer must be already
+ * pinned.  It does not have to be valid, but it is valid and locked on
+ * return.
  */
-static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
-				  BlockNumber blockNum, ReadBufferMode mode,
-				  BufferAccessStrategy strategy, bool *hit)
+static void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
 {
 	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
+/*
+ * Pin a buffer for a given block.  *foundPtr is set to true if the block was
+ * already present, or false if more work is required to either read it in or
+ * zero it.
+ */
+static inline Buffer
+PinBufferForBlock(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
 	IOContext	io_context;
 	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
 
-	*hit = false;
+	Assert(blockNum != P_NEW);
+
+	Assert(bmr.smgr);
+
+	isLocalBuf = bmr.relpersistence == RELPERSISTENCE_TEMP;
+	if (isLocalBuf)
+	{
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
+	}
+	else
+	{
+		io_context = IOContextForStrategy(strategy);
+		io_object = IOOBJECT_RELATION;
+	}
+
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
+
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * WaitReadBuffers() (so, not for hits, and not for buffers that are
+		 * zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
+	{
+		VacuumPageHit++;
+		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageHit;
+
+		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
+
+	return BufferDescriptorGetBuffer(bufHdr);
+}
+
+/*
+ * ReadBuffer_common -- common logic for all ReadBuffer variants
+ */
+static inline Buffer
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
+				  BlockNumber blockNum, ReadBufferMode mode,
+				  BufferAccessStrategy strategy)
+{
+	ReadBuffersOperation operation;
+	Buffer		buffer;
+	int			flags;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1041,181 +1151,359 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
-
-	if (isLocalBuf)
+	if (unlikely(mode == RBM_ZERO_AND_CLEANUP_LOCK ||
+				 mode == RBM_ZERO_AND_LOCK))
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
-		io_context = IOCONTEXT_NORMAL;
-		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
+		bool		found;
+
+		if (bmr.smgr == NULL)
+		{
+			bmr.smgr = RelationGetSmgr(bmr.rel);
+			bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+		}
+
+		buffer = PinBufferForBlock(bmr, forkNum, blockNum, strategy, &found);
+		ZeroBuffer(buffer, mode);
+		return buffer;
 	}
+
+	if (mode == RBM_ZERO_ON_ERROR)
+		flags = READ_BUFFERS_ZERO_ON_ERROR;
 	else
+		flags = 0;
+	operation.bmr = bmr;
+	operation.forknum = forkNum;
+	operation.strategy = strategy;
+	if (StartReadBuffer(&operation,
+						&buffer,
+						blockNum,
+						flags))
+		WaitReadBuffers(&operation);
+
+	return buffer;
+}
+
+/*
+ * Single block version of the StartReadBuffers().  This might save a few
+ * instructions when called from another translation unit, if the compiler
+ * inlines the code and specializes for nblocks == 1.
+ */
+bool
+StartReadBuffer(ReadBuffersOperation *operation,
+				Buffer *buffer,
+				BlockNumber blocknum,
+				int flags)
+{
+	int			nblocks = 1;
+	bool		result;
+
+	result = StartReadBuffers(operation, buffer, blocknum, &nblocks, flags);
+	Assert(nblocks == 1);		/* single block can't be short */
+
+	return result;
+}
+
+/*
+ * Begin reading a range of blocks beginning at blockNum and extending for
+ * *nblocks.  On return, up to *nblocks pinned buffers holding those blocks
+ * are written into the buffers array, and *nblocks is updated to contain the
+ * actual number, which may be fewer than requested.  Caller sets some of the
+ * members of operation; see struct definition.
+ *
+ * If false is returned, no I/O is necessary.  If true is returned, one I/O
+ * has been started, and WaitReadBuffers() must be called with the same
+ * operation object before the buffers are accessed.  Along with the operation
+ * object, the caller-supplied array of buffers must remain valid until
+ * WaitReadBuffers() is called.
+ *
+ * Currently the I/O is only started with optional operating system advice,
+ * and the real I/O happens in WaitReadBuffers().  In future work, true I/O
+ * could be initiated here.
+ */
+inline bool
+StartReadBuffers(ReadBuffersOperation *operation,
+				 Buffer *buffers,
+				 BlockNumber blockNum,
+				 int *nblocks,
+				 int flags)
+{
+	int			actual_nblocks = *nblocks;
+	int			io_buffers_len = 0;
+
+	Assert(*nblocks > 0);
+	Assert(*nblocks <= MAX_IO_COMBINE_LIMIT);
+
+	if (!operation->bmr.smgr)
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
-		io_context = IOContextForStrategy(strategy);
-		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
+		operation->bmr.smgr = RelationGetSmgr(operation->bmr.rel);
+		operation->bmr.relpersistence = operation->bmr.rel->rd_rel->relpersistence;
 	}
 
-	/* At this point we do NOT hold any locks. */
-
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	for (int i = 0; i < actual_nblocks; ++i)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
-		VacuumPageHit++;
-		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
+		bool		found;
 
-		if (VacuumCostActive)
-			VacuumCostBalance += VacuumCostPageHit;
+		buffers[i] = PinBufferForBlock(operation->bmr,
+									   operation->forknum,
+									   blockNum + i,
+									   operation->strategy,
+									   &found);
 
-		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+		if (found)
+		{
+			/*
+			 * Terminate the read as soon as we get a hit.  It could be a
+			 * single buffer hit, or it could be a hit that follows a readable
+			 * range.  We don't want to create more than one readable range,
+			 * so we stop here.
+			 */
+			actual_nblocks = i + 1;
+			break;
+		}
+		else
+		{
+			/* Extend the readable range to cover this block. */
+			io_buffers_len++;
+		}
+	}
+	*nblocks = actual_nblocks;
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
+	if (io_buffers_len > 0)
+	{
+		/* Populate information needed for I/O. */
+		operation->buffers = buffers;
+		operation->blocknum = blockNum;
+		operation->flags = flags;
+		operation->nblocks = actual_nblocks;
+		operation->io_buffers_len = io_buffers_len;
+
+		if (flags & READ_BUFFERS_ISSUE_ADVICE)
 		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
+			/*
+			 * In theory we should only do this if PinBufferForBlock() had to
+			 * allocate new buffers above.  That way, if two calls to
+			 * StartReadBuffers() were made for the same blocks before
+			 * WaitReadBuffers(), only the first would issue the advice.
+			 * That'd be a better simulation of true asynchronous I/O, which
+			 * would only start the I/O once, but isn't done here for
+			 * simplicity.  Note also that the following call might actually
+			 * issue two advice calls if we cross a segment boundary; in a
+			 * true asynchronous version we might choose to process only one
+			 * real I/O at a time in that case.
+			 */
+			smgrprefetch(operation->bmr.smgr,
+						 operation->forknum,
+						 blockNum,
+						 operation->io_buffers_len);
 		}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+		/* Indicate that WaitReadBuffers() should be called. */
+		return true;
+	}
+	else
+	{
+		return false;
 	}
+}
+
+static inline bool
+WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
+	{
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
+	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
+
+void
+WaitReadBuffers(ReadBuffersOperation *operation)
+{
+	Buffer	   *buffers;
+	int			nblocks;
+	BlockNumber blocknum;
+	ForkNumber	forknum;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
 
 	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
+	 * Currently operations are only allowed to include a read of some range,
+	 * with an optional extra buffer that is already pinned at the end.  So
+	 * nblocks can be at most one more than io_buffers_len.
 	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+	Assert((operation->nblocks == operation->io_buffers_len) ||
+		   (operation->nblocks == operation->io_buffers_len + 1));
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	/* Find the range of the physical read we need to perform. */
+	nblocks = operation->io_buffers_len;
+	if (nblocks == 0)
+		return;					/* nothing to do */
+
+	buffers = &operation->buffers[0];
+	blocknum = operation->blocknum;
+	forknum = operation->forknum;
+
+	isLocalBuf = operation->bmr.relpersistence == RELPERSISTENCE_TEMP;
+	if (isLocalBuf)
+	{
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
+	}
+	else
+	{
+		io_context = IOContextForStrategy(operation->strategy);
+		io_object = IOOBJECT_RELATION;
+	}
 
 	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
 	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
 	else
+		pgBufferUsage.shared_blks_read += nblocks;
+
+	for (int i = 0; i < nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_IO_COMBINE_LIMIT];
+		void	   *io_pages[MAX_IO_COMBINE_LIMIT];
+		instr_time	io_start;
+		BlockNumber io_first_block;
+
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!WaitReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PinBufferForBlock().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  operation->bmr.smgr->smgr_rlocator.locator.spcOid,
+											  operation->bmr.smgr->smgr_rlocator.locator.dbOid,
+											  operation->bmr.smgr->smgr_rlocator.locator.relNumber,
+											  operation->bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   WaitReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(operation->bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
 			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
 			}
 			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-		}
-	}
-
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
-	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
-	}
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
 
-	if (isLocalBuf)
-	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(operation->bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(operation->bmr.smgr->smgr_rlocator, forknum))));
+			}
 
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
-	}
-	else
-	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
-	}
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  operation->bmr.smgr->smgr_rlocator.locator.spcOid,
+											  operation->bmr.smgr->smgr_rlocator.locator.dbOid,
+											  operation->bmr.smgr->smgr_rlocator.locator.relNumber,
+											  operation->bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
- * BufferAlloc -- subroutine for ReadBuffer.  Handles lookup of a shared
- *		buffer.  If no buffer exists already, selects a replacement
- *		victim and evicts the old page, but does NOT read in new page.
+ * BufferAlloc -- subroutine for PinBufferForBlock.  Handles lookup of a shared
+ *		buffer.  If no buffer exists already, selects a replacement victim and
+ *		evicts the old page, but does NOT read in new page.
  *
  * "strategy" can be a buffer replacement strategy object, or NULL for
  * the default strategy.  The selected buffer's usage_count is advanced when
@@ -1223,11 +1511,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1286,19 +1570,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1363,19 +1638,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1407,15 +1673,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1769,7 +2029,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2034,7 +2294,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2057,7 +2317,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2193,7 +2453,7 @@ MarkBufferDirty(Buffer buffer)
 	uint32		old_buf_state;
 
 	if (!BufferIsValid(buffer))
-		elog(ERROR, "bad buffer ID: %d", buffer);
+		elog(PANIC, "bad buffer ID: %d", buffer);
 
 	if (BufferIsLocal(buffer))
 	{
@@ -2372,7 +2632,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if StartReadBuffers() was called and
+		 * WaitReadBuffers() hasn't been called yet.  We'll check by loading
+		 * the flags without locking.  This is racy, but it's OK to return
+		 * false spuriously: when WaitReadBuffers() calls StartBufferIO(),
+		 * it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2381,7 +2646,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3449,7 +3714,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -4560,7 +4825,7 @@ void
 ReleaseBuffer(Buffer buffer)
 {
 	if (!BufferIsValid(buffer))
-		elog(ERROR, "bad buffer ID: %d", buffer);
+		elog(PANIC, "bad buffer ID: %d", buffer);
 
 	if (BufferIsLocal(buffer))
 		UnpinLocalBuffer(buffer);
@@ -4627,7 +4892,7 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
 	Page		page = BufferGetPage(buffer);
 
 	if (!BufferIsValid(buffer))
-		elog(ERROR, "bad buffer ID: %d", buffer);
+		elog(PANIC, "bad buffer ID: %d", buffer);
 
 	if (BufferIsLocal(buffer))
 	{
@@ -5184,9 +5449,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5199,6 +5470,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
@@ -5691,7 +5964,7 @@ ResOwnerReleaseBufferPin(Datum res)
 
 	/* Like ReleaseBuffer, but don't call ResourceOwnerForgetBuffer */
 	if (!BufferIsValid(buffer))
-		elog(ERROR, "bad buffer ID: %d", buffer);
+		elog(PANIC, "bad buffer ID: %d", buffer);
 
 	if (BufferIsLocal(buffer))
 		UnpinLocalBufferNoOwner(buffer);
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index fcfac335a5..985a2c7049 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -108,10 +108,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -287,7 +286,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -297,9 +296,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca2..739d13293f 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index abd9029451..313e393262 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3112,6 +3112,20 @@ struct config_int ConfigureNamesInt[] =
 		NULL
 	},
 
+	{
+		{"io_combine_limit",
+			PGC_USERSET,
+			RESOURCES_ASYNCHRONOUS,
+			gettext_noop("Limit on the size of data reads and writes."),
+			NULL,
+			GUC_UNIT_BLOCKS
+		},
+		&io_combine_limit,
+		DEFAULT_IO_COMBINE_LIMIT,
+		1, MAX_IO_COMBINE_LIMIT,
+		NULL, NULL, NULL
+	},
+
 	{
 		{"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 2244ee52f7..7fa6d5a64c 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -203,6 +203,7 @@
 #backend_flush_after = 0		# measured in pages, 0 disables
 #effective_io_concurrency = 1		# 1-1000; 0 disables prefetching
 #maintenance_io_concurrency = 10	# 1-1000; 0 disables prefetching
+#io_combine_limit = 128kB		# usually 1-32 blocks (depends on OS)
 #max_worker_processes = 8		# (change requires restart)
 #max_parallel_workers_per_gather = 2	# limited by max_parallel_workers
 #max_parallel_maintenance_workers = 2	# limited by max_parallel_workers
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d335..241f68c45e 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -133,6 +134,10 @@ extern PGDLLIMPORT bool track_io_timing;
 extern PGDLLIMPORT int effective_io_concurrency;
 extern PGDLLIMPORT int maintenance_io_concurrency;
 
+#define MAX_IO_COMBINE_LIMIT PG_IOV_MAX
+#define DEFAULT_IO_COMBINE_LIMIT Min(MAX_IO_COMBINE_LIMIT, (128 * 1024) / BLCKSZ)
+extern PGDLLIMPORT int io_combine_limit;
+
 extern PGDLLIMPORT int checkpoint_flush_after;
 extern PGDLLIMPORT int backend_flush_after;
 extern PGDLLIMPORT int bgwriter_flush_after;
@@ -158,7 +163,6 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
-
 /*
  * prototypes for functions in bufmgr.c
  */
@@ -177,6 +181,38 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+
+#define READ_BUFFERS_ZERO_ON_ERROR 0x01
+#define READ_BUFFERS_ISSUE_ADVICE 0x02
+
+struct ReadBuffersOperation
+{
+	/* The following members should be set by the caller. */
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+	BufferAccessStrategy strategy;
+
+	/* The following private members should not be accessed directly. */
+	Buffer	   *buffers;
+	BlockNumber blocknum;
+	int			flags;
+	int16		nblocks;
+	int16		io_buffers_len;
+};
+
+typedef struct ReadBuffersOperation ReadBuffersOperation;
+
+extern bool StartReadBuffer(ReadBuffersOperation *operation,
+							Buffer *buffer,
+							BlockNumber blocknum,
+							int flags);
+extern bool StartReadBuffers(ReadBuffersOperation *operation,
+							 Buffer *buffers,
+							 BlockNumber blocknum,
+							 int *nblocks,
+							 int flags);
+extern void WaitReadBuffers(ReadBuffersOperation *operation);
+
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -250,6 +286,9 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h
new file mode 100644
index 0000000000..9e5fa2acf1
--- /dev/null
+++ b/src/include/storage/read_stream.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * read_stream.h
+ *	  Mechanism for accessing buffered relation data with look-ahead
+ *
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/read_stream.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef READ_STREAM_H
+#define READ_STREAM_H
+
+#include "storage/bufmgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define READ_STREAM_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users, and thus should be governed by maintenance_io_concurrency
+ * instead of effective_io_concurrency.  For example, VACUUM or CREATE INDEX.
+ */
+#define READ_STREAM_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define READ_STREAM_SEQUENTIAL 0x02
+
+/*
+ * We usually ramp up from smaller reads to larger ones, to support users who
+ * don't know if it's worth reading lots of buffers yet.  This flag disables
+ * that, declaring ahead of time that we'll be reading all available buffers.
+ */
+#define READ_STREAM_FULL 0x04
+
+struct ReadStream;
+typedef struct ReadStream ReadStream;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*ReadStreamBlockNumberCB) (ReadStream *stream,
+												void *callback_private_data,
+												void *per_buffer_data);
+
+extern ReadStream *read_stream_begin_relation(int flags,
+											  BufferAccessStrategy strategy,
+											  BufferManagerRelation bmr,
+											  ForkNumber forknum,
+											  ReadStreamBlockNumberCB callback,
+											  void *callback_private_data,
+											  size_t per_buffer_data_size);
+extern Buffer read_stream_next_buffer(ReadStream *stream, void **per_buffer_private);
+extern void read_stream_end(ReadStream *stream);
+
+#endif							/* READ_STREAM_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index a6562d19a6..16bfdf3444 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1215,6 +1215,7 @@ InjectionPointCacheEntry
 InjectionPointEntry
 InjectionPointSharedState
 InlineCodeBlock
+InProgressIO
 InsertStmt
 Instrumentation
 Int128AggState
@@ -2287,11 +2288,13 @@ ReInitializeDSMForeignScan_function
 ReScanForeignScan_function
 ReadBufPtrType
 ReadBufferMode
+ReadBuffersOperation
 ReadBytePtrType
 ReadExtraTocPtrType
 ReadFunc
 ReadLocalXLogPageNoWaitPrivate
 ReadReplicationSlotCmd
+ReadStream
 ReassignOwnedStmt
 RecheckForeignScan_function
 RecordCacheArrayEntry
-- 
2.40.1

v11-0017-BitmapHeapScan-uses-read-stream-API.patchtext/x-diff; charset=us-asciiDownload
From bc1f127ff17a27f5bd9ac6dff96576707bbe1855 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 16:51:40 -0400
Subject: [PATCH v11 17/17] BitmapHeapScan uses read stream API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the read stream API prefetching. Heap table AM implements a read
stream callback which uses the iterator to get the next valid block that
needs to be fetched for the read stream API.

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  96 ++++--
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  43 +--
 src/include/access/heapam.h               |  21 +-
 src/include/access/relscan.h              |   6 -
 src/include/access/tableam.h              |  14 -
 src/include/nodes/execnodes.h             |   9 +-
 7 files changed, 114 insertions(+), 422 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 5fc052f019..f7b1012b26 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -108,6 +108,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_stream_read_next(ReadStream *pgsr, void *pgsr_private,
+											   void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -330,6 +332,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	if (key != NULL && scan->rs_base.rs_nkeys > 0)
 		memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->rs_read_stream)
+			read_stream_end(scan->rs_read_stream);
+
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  BMR_REL(scan->rs_base.rs_rd),
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+
+
+	}
+
 	/*
 	 * Currently, we only have a stats counter for sequential heap scans (but
 	 * e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -950,16 +968,9 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-
-	scan->rs_base.blockno = InvalidBlockNumber;
-
+	scan->rs_read_stream = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
-	scan->pvmbuffer = InvalidBuffer;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1042,12 +1053,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
-	scan->rs_base.blockno = InvalidBlockNumber;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
-
 	/*
 	 * unpin scan buffers
 	 */
@@ -1060,12 +1065,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1091,12 +1090,6 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
@@ -1114,6 +1107,9 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_read_stream)
+		read_stream_end(scan->rs_read_stream);
+
 	pfree(scan);
 }
 
@@ -10130,3 +10126,51 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) private_data;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		bhs_iterate(hdesc->rs_base.rs_bhs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(hdesc->rs_base.rs_flags & SO_NEED_TUPLE) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 80f210b405..2e17a85d00 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -61,9 +61,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
-static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
-static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
-static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2167,147 +2164,68 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
-	 * parallel workers.
-	 */
-	if (scan->rs_base.prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno,
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *per_buffer_data;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(hscan);
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2328,7 +2246,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2337,9 +2255,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2389,23 +2307,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->bm_parallel == NULL &&
-		scan->rs_pf_bhs_iterator &&
-		hscan->pfblockno > hscan->rs_base.blockno)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(hscan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2416,153 +2322,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= prefetch_maximum / 2)
-			scan->prefetch_target = prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= prefetch_maximum / 2)
-			pstate->prefetch_target = prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-
-				scan->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
@@ -2597,41 +2356,11 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 			return true;
 		}
 
-		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
 										   lossy_pages, exact_pages))
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!scan->bm_parallel)
-	{
-		if (hscan->prefetch_target < scan->prefetch_maximum)
-			hscan->prefetch_target++;
-	}
-	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&scan->bm_parallel->mutex);
-		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-			scan->bm_parallel->prefetch_target++;
-		SpinLockRelease(&scan->bm_parallel->mutex);
-	}
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(hscan);
-#endif							/* USE_PREFETCH */
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2f9387e51a..f2662ea542 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -131,14 +131,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -149,15 +141,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-		int			pf_maximum = 0;
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
-#endif
-
 		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -174,13 +157,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					node->pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
+
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(node->pstate);
 			}
@@ -213,22 +190,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
 												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
-#ifdef USE_PREFETCH
-		if (scan->prefetch_maximum > 0)
-		{
-			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
-														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
-														 dsa);
-		}
-#endif							/* USE_PREFETCH */
-
 		node->initialized = true;
 	}
 
@@ -525,14 +492,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -563,11 +526,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 4726d31403..bb701cca08 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/read_stream.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	ReadStream *rs_read_stream;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -82,23 +86,6 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
-	/*
-	 * These fields only used for prefetching in bitmap table scans
-	 */
-
-	/* buffer for visibility-map lookups of prefetched pages */
-	Buffer		pvmbuffer;
-
-	/*
-	 * These fields only used in serial BHS
-	 */
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
-	/* used to validate prefetch block stays ahead of current block  */
-	BlockNumber pfblockno;
-
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 7938b741d6..02893bf99b 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -46,13 +46,7 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
-	struct BitmapHeapIterator *rs_pf_bhs_iterator;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
-	/* used to validate BHS prefetch and current block stay in sync */
-	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5979ddee8b..2b24d7441a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -944,8 +944,6 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
-	result->rs_pf_bhs_iterator = NULL;
-	result->prefetch_maximum = 0;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -1011,12 +1009,6 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1033,12 +1025,6 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 60916bf0d0..430668f597 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1758,11 +1758,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1770,10 +1766,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.40.1

#80Thomas Munro
thomas.munro@gmail.com
In reply to: Melanie Plageman (#79)
Re: BitmapHeapScan streaming read user and prelim refactoring

With the unexplained but apparently somewhat systematic regression
patterns on certain tests and settings, I wonder if they might be due
to read_stream.c trying to form larger reads, making it a bit lazier.
It tries to see what the next block will be before issuing the
fadvise. I think that means that with small I/O concurrency settings,
there might be contrived access patterns where it loses, and needs
effective_io_concurrency to be set one notch higher to keep up, or
something like that. One way to test that idea would be to run the
tests with io_combine_limit = 1 (meaning 1 block). It issues advise
eagerly when io_combine_limit is reached, so I suppose it should be
exactly as eager as master. The only difference then should be that
it automatically suppresses sequential fadvise calls.

#81Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Thomas Munro (#80)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/28/24 06:20, Thomas Munro wrote:

With the unexplained but apparently somewhat systematic regression
patterns on certain tests and settings, I wonder if they might be due
to read_stream.c trying to form larger reads, making it a bit lazier.
It tries to see what the next block will be before issuing the
fadvise. I think that means that with small I/O concurrency settings,
there might be contrived access patterns where it loses, and needs
effective_io_concurrency to be set one notch higher to keep up, or
something like that.

Yes, I think we've speculated this might be the root cause before, but
IIRC we didn't manage to verify it actually is the problem.

FWIW I don't think the tests use synthetic data, but I don't think it's
particularly contrived.

One way to test that idea would be to run the
tests with io_combine_limit = 1 (meaning 1 block). It issues advise
eagerly when io_combine_limit is reached, so I suppose it should be
exactly as eager as master. The only difference then should be that
it automatically suppresses sequential fadvise calls.

Sure, I'll give that a try. What are some good values to test? Perhaps
32 and 1, i.e. the default and "no coalescing"?

If this turns out to be the problem, does that mean we would consider
using a more conservative default value? Is there some "auto tuning" we
could do? For example, could we reduce the value combine limit if we
start not finding buffers in memory, or something like that?

I recognize this may not be possible with buffered I/O, due to not
having any insight into page cache. And maybe it's misguided anyway,
because how would we know if the right response is to increase or reduce
the combine limit?

Anyway, doesn't the combine limit work against the idea that
effective_io_concurrency is "prefetch distance"? With eic=32 I'd expect
we issue prefetch 32 pages ahead, i.e. if we prefetch page X, we should
then process 32 pages before we actually need X (and we expect the page
to already be in memory, thanks to the gap). But with the combine limit
set to 32, is this still true?

I've tried going through read_stream_* to determine how this will
behave, but read_stream_look_ahead/read_stream_start_pending_read does
not make this very clear. I'll have to experiment with some tracing.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#82Thomas Munro
thomas.munro@gmail.com
In reply to: Tomas Vondra (#81)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Mar 29, 2024 at 7:01 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/28/24 06:20, Thomas Munro wrote:

With the unexplained but apparently somewhat systematic regression
patterns on certain tests and settings, I wonder if they might be due
to read_stream.c trying to form larger reads, making it a bit lazier.
It tries to see what the next block will be before issuing the
fadvise. I think that means that with small I/O concurrency settings,
there might be contrived access patterns where it loses, and needs
effective_io_concurrency to be set one notch higher to keep up, or
something like that.

Yes, I think we've speculated this might be the root cause before, but
IIRC we didn't manage to verify it actually is the problem.

Another factor could be the bug in master that allows it to get out of
sync -- can it allow *more* concurrency than it intended to? Or fewer
hints, but somehow that goes faster because of the
stepping-on-kernel-toes problem?

One way to test that idea would be to run the
tests with io_combine_limit = 1 (meaning 1 block). It issues advise
eagerly when io_combine_limit is reached, so I suppose it should be
exactly as eager as master. The only difference then should be that
it automatically suppresses sequential fadvise calls.

Sure, I'll give that a try. What are some good values to test? Perhaps
32 and 1, i.e. the default and "no coalescing"?

Thanks! Yeah. The default is actually 16, computed backwards from
128kB. (Explanation: POSIX requires 16 as minimum IOV_MAX, ie number
of vectors acceptable to writev/readv and related functions, though
actual acceptable number is usually much higher, and it also seems to
be a conservative acceptable number for hardware scatter/gather lists
in various protocols, ie if doing direct I/O, the transfer won't be
chopped up into more than one physical I/O command because the disk
and DMA engine can handle it as a single I/O in theory at least.
Actual limit on random SSDs might be more like 33, a weird number but
that's what I'm seeing; Mr Axboe wrote a nice short article[1]https://kernel.dk/when-2mb-turns-into-512k.pdf to get
some starting points for terminology on that topic on Linux. Also,
just anecdotally, returns seem to diminish after that with huge
transfers of buffered I/O so it seems like an OK number if you have to
pick one; but IDK, YMMV, subject for future research as direct I/O
grows in relevance, hence GUC.)

If this turns out to be the problem, does that mean we would consider
using a more conservative default value? Is there some "auto tuning" we
could do? For example, could we reduce the value combine limit if we
start not finding buffers in memory, or something like that?

Hmm, not sure... I like that number for seq scans. I also like
auto-tuning. But it seems to me that *if* the problem is that we're
not allowing ourselves as many concurrent I/Os as master BHS because
we're waiting to see if the next block is consecutive, that might
indicate that the distance needs to be higher so that we can have a
better chance to see the 'edge' (the non-contiguous next block) and
start the I/O, not that the io_combine_limit needs to be lower. But I
could be way off, given the fuzziness on this problem so far...

Anyway, doesn't the combine limit work against the idea that
effective_io_concurrency is "prefetch distance"? With eic=32 I'd expect
we issue prefetch 32 pages ahead, i.e. if we prefetch page X, we should
then process 32 pages before we actually need X (and we expect the page
to already be in memory, thanks to the gap). But with the combine limit
set to 32, is this still true?

Hmm. It's different. (1) Master BHS has prefetch_maximum, which is
indeed directly taken from the eic setting, while read_stream.c is
prepared to look much ahead further than that (potentially as far as
max_pinned_buffers) if it's been useful recently, to find
opportunities to coalesce and start I/O. (2) Master BHS has
prefetch_target to control the look-ahead window, which starts small
and ramps up until it hits prefetch_maximum, while read_stream.c has
distance which goes up and down according to a more complex algorithm
described at the top.

I've tried going through read_stream_* to determine how this will
behave, but read_stream_look_ahead/read_stream_start_pending_read does
not make this very clear. I'll have to experiment with some tracing.

I'm going to try to set up something like your experiment here too,
and figure out some way to visualise or trace what's going on...

The differences come from (1) multi-block I/Os, requiring two separate
numbers: how many blocks ahead we're looking, and how many I/Os are
running, and (2) being more aggressive about trying to reach the
desired I/O level. Let me try to describe the approach again.
"distance" is the size of a window that we're searching for
opportunities to start I/Os. read_stream_look_ahead() will keep
looking ahead until we already have max_ios I/Os running, or we hit
the end of that window. That's the two conditions in the while loop
at the top:

while (stream->ios_in_progress < stream->max_ios &&
stream->pinned_buffers + stream->pending_read_nblocks <
stream->distance)

If that window is not large enough, we won't be able to find enough
I/Os to reach max_ios. So, every time we finish up starting a random
(non-sequential) I/O, we increase the distance, widening the window
until it can hopefully reach the I/O goal. (I call that behaviour C
in the comments and code.) In other words, master BHS can only find
opportunities to start I/Os in a smaller window, and can only reach
the full I/O concurrency target if they are right next to each other
in that window, but read_stream.c will look much further ahead, but
only if that has recently proven to be useful.

If we find I/Os that need doing, but they're all sequential, the
window size moves towards io_combine_limit, because we know that
issuing advice won't help, so there is no point in making the window
wider than one maximum-sized I/O. For example, sequential scans or
bitmap heapscans with lots of consecutive page bits fall into this
pattern. (Behaviour B in the code comments.) This is a pattern that
master BHS doesn't have anything like.

If we find that we don't need to do any I/O, we slowly move the window
size towards 1 (also the initial value) as there is no point in doing
anything special as it can't help. In contrast, master BHS never
shrinks its prefetch_target, it only goes up until it hits eic.

[1]: https://kernel.dk/when-2mb-turns-into-512k.pdf

#83Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#79)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/27/24 20:37, Melanie Plageman wrote:

On Mon, Mar 25, 2024 at 12:07:09PM -0400, Melanie Plageman wrote:

On Sun, Mar 24, 2024 at 06:37:20PM -0400, Melanie Plageman wrote:

On Sun, Mar 24, 2024 at 5:59 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

BTW when you say "up to 'Make table_scan_bitmap_next_block() async
friendly'" do you mean including that patch, or that this is the first
patch that is not one of the independently useful patches.

I think the code is easier to understand with "Make
table_scan_bitmap_next_block() async friendly". Prior to that commit,
table_scan_bitmap_next_block() could return false even when the bitmap
has more blocks and expects the caller to handle this and invoke it
again. I think that interface is very confusing. The downside of the
code in that state is that the code for prefetching is still in the
BitmapHeapNext() code and the code for getting the current block is in
the heap AM-specific code. I took a stab at fixing this in v9's 0013,
but the outcome wasn't very attractive.

What I will do tomorrow is reorder and group the commits such that all
of the commits that are useful independent of streaming read are first
(I think 0014 and 0015 are independently valuable but they are on top
of some things that are only useful to streaming read because they are
more recently requested changes). I think I can actually do a bit of
simplification in terms of how many commits there are and what is in
each. Just to be clear, v9 is still reviewable. I am just going to go
back and change what is included in each commit.

So, attached v10 does not include the new version of streaming read API.
I focused instead on the refactoring patches commit regrouping I
mentioned here.

Attached v11 has the updated Read Stream API Thomas sent this morning
[1]. No other changes.

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

I haven't looked for the root cause, and it's not exactly deterministic,
but try this:

create table t (a int, b text);

insert into t select 10000 * random(), md5(i::text)
from generate_series(1,10000000) s(i);^C

create index on t (a);

explain analyze select * from t where a = 200;
explain analyze select * from t where a < 200;

and then vary the condition a bit (different values, inequalities,
etc.). For me it hits the assert in a couple tries.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

bt.txttext/plain; charset=UTF-8; name=bt.txtDownload
#84Thomas Munro
thomas.munro@gmail.com
In reply to: Tomas Vondra (#83)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Mar 29, 2024 at 10:43 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

Thanks for the repro. I can't seem to reproduce it (still trying) but
I assume this is with Melanie's v11 patch set which had
v11-0016-v10-Read-Stream-API.patch.

Would you mind removing that commit and instead applying the v13
stream_read.c patches[1]/messages/by-id/CA+hUKG+5UofvseJWv6YqKmuc_=rguc7VqKcNEG1eawKh3MzHXQ@mail.gmail.com? v10 stream_read.c was a little confused
about random I/O combining, which I fixed with a small adjustment to
the conditions for the "if" statement right at the end of
read_stream_look_ahead(). Sorry about that. The fixed version, with
eic=4, with your test query using WHERE a < a, ends its scan with:

...
posix_fadvise(32,0x28aee000,0x4000,POSIX_FADV_WILLNEED) = 0 (0x0)
pread(32,"\0\0\0\0@4\M-5:\0\0\^D\0\M-x\^A"...,40960,0x28acc000) = 40960 (0xa000)
posix_fadvise(32,0x28af4000,0x4000,POSIX_FADV_WILLNEED) = 0 (0x0)
pread(32,"\0\0\0\0\^XC\M-6:\0\0\^D\0\M-x"...,32768,0x28ad8000) = 32768 (0x8000)
posix_fadvise(32,0x28afc000,0x4000,POSIX_FADV_WILLNEED) = 0 (0x0)
pread(32,"\0\0\0\0\M-XQ\M-7:\0\0\^D\0\M-x"...,24576,0x28ae4000) = 24576 (0x6000)
posix_fadvise(32,0x28b02000,0x8000,POSIX_FADV_WILLNEED) = 0 (0x0)
pread(32,"\0\0\0\0\M^@3\M-8:\0\0\^D\0\M-x"...,16384,0x28aee000) = 16384 (0x4000)
pread(32,"\0\0\0\0\M-`\M-:\M-8:\0\0\^D\0"...,16384,0x28af4000) = 16384 (0x4000)
pread(32,"\0\0\0\0po\M-9:\0\0\^D\0\M-x\^A"...,16384,0x28afc000) = 16384 (0x4000)
pread(32,"\0\0\0\0\M-P\M-v\M-9:\0\0\^D\0"...,32768,0x28b02000) = 32768 (0x8000)

In other words it's able to coalesce, but v10 was a bit b0rked in that
respect and wouldn't do as well at that. Then if you set
io_combine_limit = 1, it looks more like master, eg lots of little
reads, but not as many fadvises as master because of sequential
access:

...
posix_fadvise(32,0x28af4000,0x2000,POSIX_FADV_WILLNEED) = 0 (0x0) -+
pread(32,...,8192,0x28ae8000) = 8192 (0x2000) |
pread(32,...,8192,0x28aee000) = 8192 (0x2000) |
posix_fadvise(32,0x28afc000,0x2000,POSIX_FADV_WILLNEED) = 0 (0x0) ---+
pread(32,...,8192,0x28af0000) = 8192 (0x2000) | |
pread(32,...,8192,0x28af4000) = 8192 (0x2000) <--------------------+ |
posix_fadvise(32,0x28b02000,0x2000,POSIX_FADV_WILLNEED) = 0 (0x0) -----+
pread(32,...,8192,0x28af6000) = 8192 (0x2000) | |
pread(32,...,8192,0x28afc000) = 8192 (0x2000) <----------------------+ |
pread(32,...,8192,0x28afe000) = 8192 (0x2000) }-- no advice |
pread(32,...,8192,0x28b02000) = 8192 (0x2000) <------------------------+
pread(32,...,8192,0x28b04000) = 8192 (0x2000) }
pread(32,...,8192,0x28b06000) = 8192 (0x2000) }-- no advice
pread(32,...,8192,0x28b08000) = 8192 (0x2000) }

It becomes slightly less eager to start I/Os as soon as
io_combine_limit > 1, because when it has hit max_ios, if ... <thinks>
yeah if the average block that it can combine is bigger than 4, an
arbitrary number from:

max_pinned_buffers = Max(max_ios * 4, io_combine_limit);

.... then it can run out of look ahead window before it can reach
max_ios (aka eic), so that's a kind of arbitrary/bogus I/O depth
constraint, which is another way of saying what I was saying earlier:
maybe it just needs more distance. So let's see the average combined
I/O length in your test query... for me it works out to 27,169 bytes.
But I think there must be times when it runs out of window due to
clustering. So you could also try increasing that 4->8 to see what
happens to performance.

[1]: /messages/by-id/CA+hUKG+5UofvseJWv6YqKmuc_=rguc7VqKcNEG1eawKh3MzHXQ@mail.gmail.com

#85Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Thomas Munro (#84)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/29/24 02:12, Thomas Munro wrote:

On Fri, Mar 29, 2024 at 10:43 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

Thanks for the repro. I can't seem to reproduce it (still trying) but
I assume this is with Melanie's v11 patch set which had
v11-0016-v10-Read-Stream-API.patch.

Would you mind removing that commit and instead applying the v13
stream_read.c patches[1]? v10 stream_read.c was a little confused
about random I/O combining, which I fixed with a small adjustment to
the conditions for the "if" statement right at the end of
read_stream_look_ahead(). Sorry about that. The fixed version, with
eic=4, with your test query using WHERE a < a, ends its scan with:

I'll give that a try. Unfortunately unfortunately the v11 still has the
problem I reported about a week ago:

ERROR: prefetch and main iterators are out of sync

So I can't run the full benchmarks :-( but master vs. streaming read API
should work, I think.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#86Thomas Munro
thomas.munro@gmail.com
In reply to: Tomas Vondra (#85)
Re: BitmapHeapScan streaming read user and prelim refactoring

I spent a bit of time today testing Melanie's v11, except with
read_stream.c v13, on Linux, ext4, and 3000 IOPS cloud storage. I
think I now know roughly what's going on. Here are some numbers,
using your random table from above and a simple SELECT * FROM t WHERE
a < 100 OR a = 123456. I'll keep parallelism out of this for now.
These are milliseconds:

eic unpatched patched
0 4172 9572
1 30846 10376
2 18435 5562
4 18980 3503
8 18980 2680
16 18976 3233

So with eic=0, unpatched wins. The reason is that Linux readahead
wakes up and scans the table at 150MB/s, because there are enough
clusters to trigger it. But patched doesn't look quite so sequential
because we removed the sequential accesses by I/O combining...

At eic=1, unpatched completely collapses. I'm not sure why exactly.

Once you go above eic=1, Linux seems to get out of the way and just do
what we asked it to do: iostat shows exactly 3000 IOPS, exactly 8KB
avg read size, and (therefore) throughput of 24MB/sec, though you can
see the queue depth being exactly what we asked it to do,eg 7.9 or
whatever for eic=8, while patched eats it for breakfast because it
issues wide requests, averaging around 27KB.

It seems more informative to look at the absolute numbers rather than
the A/B ratios, because then you can see how the numbers themselves
are already completely nuts, sort of interference patterns from
interaction with kernel heuristics.

On the other hand this might be a pretty unusual data distribution.
People who store random numbers or hashes or whatever probably don't
really search for ranges of them (unless they're trying to mine
bitcoins in SQL). I dunno. Maybe we need more realistic tests, or
maybe we're just discovering all the things that are bad about the
pre-existing code.

#87Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#86)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 30, 2024 at 12:17 AM Thomas Munro <thomas.munro@gmail.com> wrote:

eic unpatched patched
0 4172 9572
1 30846 10376
2 18435 5562
4 18980 3503
8 18980 2680
16 18976 3233

... but the patched version gets down to a low number for eic=0 too if
you turn up the blockdev --setra so that it also gets Linux RA
treatment, making it the clear winner on all eic settings. Patched
doesn't improve. So, for low IOPS storage at least, when you're on
the borderline between random and sequential, ie bitmap with a lot of
1s in it, it seems there are cases where patched doesn't trigger Linux
RA but unpatched does, and you can tune your way out of that, and then
there are cases where the IOPS limit is reached due to small reads,
but patched does better because of larger I/Os that are likely under
the same circumstances. Does that make sense?

#88Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Thomas Munro (#87)
3 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/29/24 14:36, Thomas Munro wrote:

On Sat, Mar 30, 2024 at 12:17 AM Thomas Munro <thomas.munro@gmail.com> wrote:

eic unpatched patched
0 4172 9572
1 30846 10376
2 18435 5562
4 18980 3503
8 18980 2680
16 18976 3233

... but the patched version gets down to a low number for eic=0 too if
you turn up the blockdev --setra so that it also gets Linux RA
treatment, making it the clear winner on all eic settings. Patched
doesn't improve. So, for low IOPS storage at least, when you're on
the borderline between random and sequential, ie bitmap with a lot of
1s in it, it seems there are cases where patched doesn't trigger Linux
RA but unpatched does, and you can tune your way out of that, and then
there are cases where the IOPS limit is reached due to small reads,
but patched does better because of larger I/Os that are likely under
the same circumstances. Does that make sense?

I think you meant "unpatched version gets down" in the first sentence,
right? Still, it seems clear this changes the interaction with readahead
done by the kernel.

However, you seem to focus only on eic=0/eic=1 cases, but IIRC that was
just an example. There are regression with higher eic values too.

I do have some early results from the benchmarks - it's just from the
NVMe machine, with 1M tables (~300MB), and it's just one incomplete run
(so there might be some noise etc.).

Attached is a PDF with charts for different subsets of the runs:

- optimal (would optimizer pick bitmapscan or not)
- readahead (yes/no)
- workers (serial vs. 4 workers)
- combine limit (8kB / 128kB)

The most interesting cases are first two rows, i.e. optimal plans.
Either with readahead enabled (first row) or disabled (second row).

Two observations:

* The combine limit seems to have negligible impact. There's no visible
difference between combine_limit=8kB and 128kB.

* Parallel queries seem to work about the same as master (especially for
optimal cases, but even for not optimal ones).

The optimal plans with kernel readahead (two charts in the first row)
look fairly good. There are a couple regressed cases, but a bunch of
faster ones too.

The optimal plans without kernel read ahead (two charts in the second
row) perform pretty poorly - there are massive regressions. But I think
the obvious reason is that the streaming read API skips prefetches for
sequential access patterns, relying on kernel to do the readahead. But
if the kernel readahead is disabled for the device, that obviously can't
happen ...

I think the question is how much we can (want to) rely on the readahead
to be done by the kernel. Maybe there should be some flag to force
issuing fadvise even for sequential patterns, perhaps at the tablespace
level? I don't recall seeing a system with disabled readahead, but I'm
sure there are cases where it may not really work - it clearly can't
work with direct I/O, but I've also not been very successful with
prefetching on ZFS.

The non-optimal plans (second half of the charts) shows about the same
behavior, but the regressions are more frequent / significant.

I'm also attaching results for the 5k "optimal" runs, showing the timing
for master and patched build, sorted by (patched/master). The most
significant regressions are with readahead=0, but if you filter that out
you'll see the regressions affect a mix of data sets, not just the
uniformly random data used as example before.

On 3/29/24 12:17, Thomas Munro wrote:

...
On the other hand this might be a pretty unusual data distribution.
People who store random numbers or hashes or whatever probably don't
really search for ranges of them (unless they're trying to mine
bitcoins in SQL). I dunno. Maybe we need more realistic tests, or
maybe we're just discovering all the things that are bad about the
pre-existing code.

I certainly admit the data sets are synthetic and perhaps adversarial.
My intent was to cover a wide range of data sets, to trigger even less
common cases. It's certainly up to debate how serious the regressions on
those data sets are in practice, I'm not suggesting "this strange data
set makes it slower than master, so we can't commit this".

But I'd also point that what matters is the access pattern, not the
exact query generating it. I agree people probably don't do random
numbers or hashes with range conditions, but that's irrelevant - what
it's all about the page access pattern. If you have IPv4 addresses and
query that, that's likely going to be pretty random, for example.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

run-randomized.shapplication/x-shellscript; name=run-randomized.shDownload
results.pdfapplication/pdf; name=results.pdfDownload
%PDF-1.4
%�� ��
1 0 obj
<< /Type /Catalog /Pages 2 0 R >>
endobj
8 0 obj
<< /Font 3 0 R /XObject 7 0 R /ExtGState 4 0 R /Pattern 5 0 R
/Shading 6 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >>
endobj
11 0 obj
<< /Type /Page /Parent 2 0 R /Resources 8 0 R /MediaBox [ 0 0 1872 1872 ]
/Contents 9 0 R /Annots 10 0 R >>
endobj
9 0 obj
<< /Length 12 0 R /Filter /FlateDecode >>
stream
x�������u�7���!9���/�5���L6a�Y �4�n�I�D��k}�������u�L"	��2*���}]{���������O��������O�������_������������/����S��?}�k�����_��^��O�>��O��z���������{N{���[��]g[[�F���ry��?���U�}��S���|������r��?h�Z�}i�����y������|�[}�������M�����.{��[S�W��.����>��o?���/9����y�~�������J��__~��>���������O9�{�k�����|����;�Y{�y����-���J�j��������i�RS]�����-��q�}�Q��������~�Z��W<�nO�����m<�������L������q�p�j������������=�1��yk�|A��Q�%�����~���jO��]�0��V��i��{�k��{����/z*����C��X}���;^����V������y������w���~����������������F�����R�}~������R��*��}x
�=��6o�?j]�7�����BzI���:��B��}h/�G����8������[��k�r`=���h�����2�}�&7W��p-������}�������7�2��Yl�R�Gk������~o���>����k-3��h2bi��������2�{�������������L��Q?Z��T�[�\�6�h�i)_��[k���f��+�|�����t�3�A�VD��M�1Ekl��w�����>�%2PXN9�{��+`���OY ����O/����������]�P�Sf�/_�)z{KA$�~��O��/�7��^!e"����>���?������Ca'��Rn��=��{J[���^��/���������+��7mcUm��8Ni�lz"k�-K�_�=�7��q�_��6����o.�Pz%�w��V���HU��^�Z��9����^y���nUKZ�w���e�*d���2uY�
9QA�����l���"~�,:�u���I����#2X�X
e���{�
��:�I��;�uKJ�mG��'�G�-H��J<��c3G�<��,����_���z�E66z���W�;�B��/Vm|���������j����/qkw��\&���BE3��#����U�w}�����X��crF�<~��C���
�t�����-#���dmF��������Vx��]���NkTR���M��";zK�����Z�,�s�f���C�+��$�����'��Q�=���/s�O������p�~$c�p��V�sp��g�u]���$�6�.�0z'���M�]��^�����~���@��ZT�$��	U�T�{������F���n�,g�+������b��wS<A����Ve��K6+�g_AJ_Y�����4�J�6��SVTq%�S�Q����hs��|�2�������d�S�zw���A���_�W=z�?��l����e����
��uL6,9'��)U��%���iid������B=sE������e��k��ctmK���������M/I]tw����-�od��L���D+�p�8��Tx;f,�����&���X1�
�:d�=Raj��*�'�+/�a�[���j��o/��$��4�}�-�]��7���=��E_Nw|�0�A�0M�����d�B#�@mvi�y_fB���s!������h�e����DE:��`��`���Sh2.�z�Xvh�M�F�L~c�����,d�wP�����*5>=C�v�����_��ymh"c�[���A!B���5z�z:���Vz:�M�@�)40�f�h������/��6�Ar=��e�2�f����6��F[^"����P$7�F����[R<��	���'=@�*;����[�c����J�PjIE�O^U7 w������k:t�d�d0d����0&6��\�"L��]C~<�`�r9X�e�)�T�QB/X�^�2�z�hYr���yT�4=`��C����g����%O�l2H�=���:��Fr8:���N�&��[&�V�!�-|��� B�(~$<�dZG�,�����~��+7):g�.W���$ ���k�_����)��ah�������t�)����$��u-���j�������!tj<�$������K�C^'��m��3���������iV>�tO��*�������I�����2Q=��c���
��$�-<��������U�,�&�����D���R�'�6�vE�:tN��W�B����U�u���:dEa���:�������"W�{��p�UnEse�����n���X�d}���[#*u�q�:�
Z���&��u�?K5<�7����Eu���:��Ym���&g�������Z�M�0�B�:6����M�Csr^�
z/�6�~�)�a^�!�
�9��
��=�;%�S�S�+�q��8��I�.����`_���2e��x7&!�'W@�V'+��d9u��)e��n
�xD%����$���>E�N�Q�^�M��NRX�-/!���!����wE��YY���w]���k�V.��D��1WS���jG�5(���P�f����o:���c�/�M���1�|�w�A<�=�9�HR&Q����:�����O�;5������o�Gr�W%���(�t�t�E[1u�V��
��/\,e�ce�k�$N*
uyU�����-E��������[�C�z�������++!����F�v]�|+L�	Z%�
z<�B��K9.������-��X�F"����V���5SV�W�������V`�i��KP�3�y�������E+��U)Gl1(���!y����q���96�����.��E�tX��� AZ��5JV|���
L!o������k���1�<�!_����.E>6:t������N��<~M��#5�(��z3���QD���E�I�sB7�_�?6/Y�����%�:q��TfV�?~E��eLC��������J���k��M�O���>H;���KoY{������*hT:���r��2��^!������Ls�%��+��%�zH�����S�"�%fY���u=/W��Wg�8��T��x���K�d)t2�>�K��M��|D)8u�5OeP�[9��
�Q	�\���o��:�2��.�c��>
A*d��Z�L9��NUV'n���N���Q�t��A�Z�(�����3��c3p���9��
]+.]�IF�%/��bv��s�t�q��^E6��)��a���8n����8���h��]��R�b�8��f���x�\��\��\��(Z-<rH�Ek�*�Y!=��@X�6iE�Z��*�)��(	T�X�=�V���w�E!M����a��`G��fL������r9�xek�B�W�C�$<r���>�Y��k%��%�L�L�s�q)E���GB�zQ��pdI����+��xW�b�W�(E�m��$�n�:������ma������g��2��/�/aAA�l�����xn|����#��i$O��U�x*�V%�r����)L��������_���5y���ee�tS��Ji�B��C�AvJ�p�zR�����Fu�T�i��^tPt\���z� M���Qw,��|��+��n�m0:����ur�dV����Q�}X�f(�.2Y�/�i�����M�oRA������t�*��re�$:='2��9�=lH(S���Z-��2N2M2���k3'�
�Vt�N�s����!;��2qn��<������x��\�oI2��{)��V�Cn��G��� W
�����G�������v]=�g��U�J&�u����6�*�w�+h���
�;�5��f���b��1��s�$�.�o
m*R����� 6v(D���j��{�G����b���J�Q���e�
���
����J���G-;>��N��
���U��[0��$��\'���6R�����I�W\�ro
{wr���:�V���lW!�����:�����v��������;G=TZ��8�%�\i�s�*]���zf��:�s�j+�������+��"����.0a�qV�V��3z
�I�r��<��	X\�P���'d�6��^9SG]&�:�aY��\�s��K�K����HD�R�u)�q�S�zT��RT�]$��%���.���'O�d]Aq�9�#��C
sX���
s6*�J��o���W����������>@�%�Htf�bVo�����)��)�l���J�
��mS	�p���u�H�c�^�D3Q��S��776N�,x�����O�.z��*�jq��F�������X-�1�D[OWWo�����s����U��G����Ri��S8�Uf��r��W��4.�����{C�`�����{�6�r�F�����b�s�}���u�IS��}����P��t����,�+k/���HI��-�}%��L�3�^E�Mid�6��7-F���%�2�a��������wz��q#��9�WS�u��H3'���	�	���������:M>w@\��Z�vw��B�7��	��:T���Lw�.�4M��q�6\;��^WQ�#�-y����
1������d��9�:��2N�k�^�����y�-�{���.��W.�K�u
�����N��������*�"I�+��a��.6sb}6^i��~�x�e ��%��y$�Dl/Q�d"��9�MF��7E]nP,��`6��R���sQ����v`=d����`8a<�%}:����s��x�c�����![_��OVW�x��I���';���2�C���]�����[tK�{���;U�Pk��"�M�u�X�������
���7�}����k��o����iV���2�O���*i�w'��Z�bgPk3`��G��o[�>)��Y���dC��di�=��O�lud�c����h�f�d��n���i�V 
@o���t)��R<A,?���{i�b.?���=Sj�R0���{���at�U����P���I,��*���yA!HrX^�����N �Hs��%|D���	�G�H���L�D��te���+o��}�J��
M�����(��Q�K�%4��������������z���}c&���:WT't�h����k�z��j=*�Q�#Oo�N���l��R����X~M>�9�3�u����I���?^J�e�g������}J�M�7�(��`Lle�����o��o��A�Av��UH�[�eu������&�Gx�G���P^�X{����.��2��u�N�$���#"�4��uc�Q�5�BB��0�YvX���A@~U�6~8iq�p���5x�Vr�3�2�:��9�\$���x;�2�;�6�[�	�A�w��C�O�J_-�rej������"���K�R-qKK��v����f��������x��xve�+���``>
�P'\�~N1�������0��0��g��Q��b�F['��l�2P�=���I�0����Ob����U������2���U�(/�+v��F37�a:�i��a�p������2�����7#&�������:�/qV�c����=:��5��:G~F_��E12f%��.3C�k`�vw���
�AO�#�}$9U�3�[�rW�L�OW
�tH���[1��N�7��bt�z�K`�\�O��
S�<�E���4b$n���V�]�J����m��-�%.�i%\8�euP��Q8
}��Tr$����0��]����h�+5%��T�}�P>�%O���1wM=+z7�e2�nvS��Q
���i��mKeTC�&Q��`��/�\cQ |N��
�K
�4�1]�J�A&X�H��Oa����keJ�+���ciT>�c��r+{�>������~A�f�3��z!f��+F�n��Xm!9Ss�:�5m-R�����6�7��l)��{i[

w�s��+r�FRN���!�[Q'V�5;!$��/B����vH$�����PU��j�Mw'�2����o��zk7f��i��a��n���rq�M�L{*����Z=F�tp��mP'�M9K�|����'$��w�M����RHX+�.�b6v�U!�$��2k�q�q�����!b��oW0���/T`\�$�iY^�}��,K�h�����;p����jj7z4a|h*��@B�
��e��CF�Z�L����&���������B���M	3�SCg�A�`��v��W��$��to�����B����

�h.,%���n.�NG:���1����w{r�?��GI��2��� QdM3.���I���]h�`�JAu�i3xnb���)�:�(�dt�<�ad���V<�v�0�_j�<��G4�7t���s��V�i�-����-�t=n�PZ��*�9q�N1���b����i�B�����f]$�oD���0�a��S(���)�kL�(��p���6�oZ	��B�,����
���c�ph�E"]����r)b55���������r,=�tj�6��2���-`}����p%�g��Ik<�86��)��I�y���{�lb�9�k}=������,':���6t�^�>��W�2h�V�\�}�e���@��H�k��vr���-b,����H���@��f�����\������d*�!?�MH���]������M��������B1��	�k��-�Q.�t%s�nr�����;)*�?� �.�a���Aq2�h�`��!�Y��N-�4��VZ/<�6y�$����vU|�L��D;��
=gf�U
�uj	#N������u��$�Ig�j���&��{�z��pq�^�tu1���	d��`/~FjC�
��i�1~��DWR�q��H�� I�+����c@t�,�D�����St�#�<(!�m�T�M!�����w	 %t�<�0�h��)O:�T�,n�-D�:SO�/hn�W���&f����c�yf��sd{Q��1�1�&���e�w
wOq�f���Zy�_��jy'&�o�f�c����g� ��0�b=�h�2�i��tb���{-����B;���Z�R��q�x����i�=0#9������B@D��]ugI!�����M�W�>��`�q��EQ2��dnu����TC���	/N���D�<m���w�+�
J
q��B�Zf�BLx0+�(��pwt��7�S:x@�/�
�C:u�E��lwF�h6f���mP�dP����:%�W�Q�KE���&l�����G��t����4�C�.E[� J)������	����tY�c��^*���"b�a�d��D����
�$�S��\��������g����31�,Z��i����M����F^3v�(�B�PN�x�0$9��Pg�{if��Q"���C���]<�1��
�D\10���-�tv<�r`�Q�
V�0!X�`����2A�^���t�����JtW�x�J[���o>h��^�bbV����{m���D.���7p�j�V\��|��Q{Qp�������*N
���� o�u��Ca�E��*cs=�	&�4+�c�����J@�}Us+s����4G��n�Q��NA�R�Z��R��;�H��N�(���P�����*8�v|'�c�3��J�BI�����=���`i�g�,=!HX�0(�@�E3����
��1{���u����Y��\���r�YL���77���M������H��S��-c�Y�
wcX9h�rMEg�8x��x!m�0
+��fN�U.'<vC�:��Gn�Q������� S;����������(C���(��(�b��qm�d�xA%u���1���_���6����4v��(v'�F�CD�(��-�Y9�|E?� ACqj��L
�NsS
��2'�ff7��:����9��v�"��U��h���=L�?�zD[�1�
L����
"���
��0�\�n���4��7�
�)%�%,��i��W/1	_�Ev��@.��(�&�of�j�W�����g���i7 �#D^��F��;����[&{�0��
�u5�zl���9��b���-|wFu6L'�^��r�YxED0���*!�(��S�����\�=��F�6^�����|����r�B�J�
�)�SD���b���V)&������+�	�VX���K��d�@	I�V����h�O����1�*s�r!�^�X�f�((g�l\A`)��l���%|7�%��_�WA0h7��:wJ����(�,d���$����5�An�C���I��Z�C��DPA��dZ������Oa{���9j��	w�^��p�lB�B�<S
�!c�t�
��IaW�=��*,O��y��I�;#}�DJ�<ic�d�1��NuQ��F3D�:�:�a��
!���
�-��CQM��e)��]�\�HQ����.w�
�r=H�L�d;�1���W�������i��<9�������j��ET��e�[JQ�=7��TB�n(l����t����X�83��k5@�N8-N�\WL,P�$�r��u,�������e�S����W�;5�������a�'���aX�(5�Qk7�S*��y��G��@���O��0l��$�p?J������/s}�����D��xt�R����M���*���I�Z���3����Q��N�D��J�)2��y�
�9U��F����k�.`������Up��5%C��������-&�3�Hy� ��U�?-�T���(A�C��0�a�������L{�j�IeJ/��t�@f�P��2���%6�<����V�W4K��U�#�������
}6�������1���COH��eC3��Q�2-�P���$��-���;�z���
h���O��q`8)�����f��b!`�c��(���B:�������`f��R7E.��H�W����y����VhGBv&C.?����mOL���(t��S��E�q
E������I�!w���=�{�(�
sM$x�7�y���i���v���
�������TE2�0�\��;�l1<���C&~���j=�S�0!�a@���(1�i����_���/��^5&�f`S7��q�%I����9�p&��M:�h�x���7
_�P���C�l�Y��$q\�]�`���k�PAP1��n�����3�[^}96$1����A����	OWc<���j(B�D��uc\��90{p��15��2���O���V��Z\3����5�������Co&���^U	ZL��Ob�F���sW3��k�wm�l,
{
�=��+9aG�d�+�d��$C�2
��F�T��r��V�G~�������|�F��"*'NFF��@2L�>�^�B�����S�\��$�2��@P�j��5(>�d�����E+S�E��r��b����W������nyg6
D��l�+�{:=� +FQ����L�%o�{������qU�:���h�q*�~?)�o��1S���	pT����O�Q	f7�y��x�1��4�{)eB��|�Q�����q���}�#N���
�����Mw:�������"lgf�!a�R�����?1�z�����r����LE���*>���+u���.��bn�0a��&!o��X��l;p���'�R���-��#��l�A�0��"���f���Y+��c
J1M,E�j]���rX��!}������P�������!�M������>��Az�C!�_�b��O�}���%�{^v�
vx/�2(2s
���N����hA��_�����O������??���7/?��g���y���~����'���w�����?������~�������~����Q?�������������������_?}�}yU�{��^?!�Dkz?o�f
�y�>�������_��w���?�P��J�^�FQ.��Q��v����m�?�x)��*G������k�������F�����G��
d�$&xZ��>^��z ��_�oBo�������#'}=��?�[��s��z����N!�����t��iA�?�pA�9�b���U�[��Jg�i9?�x9����������iu�����1����$������R����W|X���
_�`��;5���A��Z�����B���_�a9�u�����r�O	��r��/�Z�����b��y��������}z����^��j>V|����|X�{M���|,
����
��Z�1R�#H�����(3��K��>���|���&P��"��������
���n�A'�#�%�#�XJh?s����
�:���B+
�k�^hi�LA�4��J��s�^kK���4J�����*
c���eGo�F%O�K��t�����"�����:m�d{��C��B���1mOH�m��R�n��V��{���b��0��b�;���h�1O��Q(������)�.F�	����g���*��1d���[���s��
���>�8��&J�St_�w�91�
4��0����E�O��\�G���	B�M����P�������l�u�M�7�w�>JO����[>��!�a^�"��X�Y�m5��
L�5{������&��0M1)M+f��Cj�C���l��5N�0�:�g��w�V�`-�����| ��F�r$`�
|��	u�hA��b p�7\��{)�Pp��������0�'������EM�
�P�R�~:�����e��St�=>��	���4���[Z|4H�0�D��vh����!���+�o�nkfJ���0/���H15�a��$	��&z��B�6��X��E|@`u�)[�L�pV%';\J��R�������2�f���iv�43���Ln�e���=�D��L)l�m�1������N���
���g5�fb�G+��udk&@I�
`��fW�][��/K����������n]��r���WL��*n�(T`O)-,���(�����MF]�A��@*�{z�xr��a�����Tst��*
���/0,�a��	S��v�2���-�dy�(4�:T��o@5{��hd�?
��L�w=!�Y)x��7kZ%����E���oA���H�P|�"=Mf>��q1T0����B_�:����Y��Gs ��Nu�t@��Y��d� ����a,K�\�s���fZR�gi�
������Vw�����I�������k�f���L>�h� a�~����^��nEC�#xUP�0��������r5;M)Q`���	�����K�`4B���b��F �U(�Ck�:_b�K���w2�����������L�.6���{2+�!����MR��:M1/
�g���@���������32T�`5*����a����&)nf8R4kF|Bu�$���L
�%z&�rq�P�Z1n��n���+F��(�"���\�Pl]����Y54��u�G��)d�f�D����	:X���]�!<��#	y1L����e�/|�O&"�%6����V�p/�iC��H
3���>�AN����V6����,L;�0���H����V��S`����d���9�����d�_hQ_=�k�\��Cp�e@�52����B�b�x��>KaD^�V%E,�c* u�:�5�
>��<A��j-��0���&G�&��
�@L�Xp��:��}��q��P?;\eR�/�OG#[���z	�.rs��b���oq�^�-���,q�h����� $�(th���YiI������_FP��j�����iZ����6(�w������f�F�a2���B����Ca����Y�V_�Q�7(�����G���-�d�Cl��r�
,9��l���2�G<������
������p�q���@b[�
�!7dI��b�D����)'��	�r��P���d.�9�`���R
������~�P����B���^��������"���?�&�����kvA�W�?�����l�L���,E���8!���k<A��=��y�m� �ge-�S���j����[V���f����A�Mo���o&D���������r�9�cN��b�[���R����9�@�Ux��L��(���w��u�V�Lz��Q���w�C�pA����e/�Ut.�����IOY��Sm�T�����Jo���p�*:��i����z%�����t{l;�5�!�J�f%�����W�#�F���uAPx,�6�;`[
��^p�v��;H�Dc.w<���B��|���MH_,6�<b{wR_L<�n��<�
y}����B��e�#4��>�W����
\|�xz/B����r�Yo��*��]9�bZ�Xy��}(�	A,Czrl��}XE��gX���3#S{�-��$���()��������9�4L���a��%�"y�����^-�����(�]"�QF�����'lCu�����
��G��YN��A���v�&C�4�W�4���K�0�-��,���p�P�<�;�K��*��XMsv7��\�m
78\�F��_���US\&F���q�d���!eK���>CM��*���l�0���&6����|�=��-�Z1�pS��*��&�CV�E������(Y�>�W�tj�q������\A;&S����C��sB�]m��dEL�.�,6je �j�����������F�|(@�OJ;������b�3�~::�4�s�z�a�+���@ ��8"TEa��/�\eiP ��Vd_Fl��Q���1�5���O�v�y��)�������B�7]]�L(�/_f4���vA��F�����E7��
���B}���!y-D|L�7�M0~?���TIj���I�4��)�E`�h���C~��9���`|�~�G�� �x��|~�
[O8���N�:�a�\@NFQ:�������HlCK8�8S��@������l���u��pB*��{��$9|"pv4f�HHnX�bi�C"�f��K��,(�����F6*��/�i��B3~�z��s���9�@:s�M�/�����j32�t4qQ��k�qq�(9� u�+�FJ����P�����U�_$~�.��3Gqj�H3-����@>����	_Q�LP~�QhB,����Z�{{7���������=���N���*��O7�vb�l J���z�T@����T�~��1/�a�.�e���Q���>A=����)?��rhx�k�k�Z;.D]h����^#)���{�����1���`��'mTy`�W�(��<Wx6�|J0����-�P��b���-mO������Y�s�����a����"�CAA��@�T��h��/��0��f��u#�gy0��]��^/��a�w���@��p6�E 1��~^([��*�R�{�W]t�J���I�*�Q�R�1R�R"�U�h��IC�K��W�������s��i�xhU"t�W�'QX�!��++����qeE��x�%S?�I[qz@��ZfUA��
���*eI.K���\�1�go����h4|d���
�pc�a0a���� ���c(Pi��h2��e��a��tn6�&>foR���B��-!H��\�����������������x� %��@4���r|���OW2���	�f������J\��H5$�j��0���E�������f3�'zF�;q�~��]����a��)c'�G-�M/��z?��`>�k�raV����C�<JP�����C��9�%�6�����E�D@����n������:�1�y�/�-�`n����U'�V.<�.�#@XaF�� ud@JC� ��#�xAR
��������H�A����h%�Ey�`�D�;��0�������f�S�1[JH�t������?��*)2���L��O-8=i
O_{���y�4G��s��� ������_(X��fz����p%4��q���9��~)#<���>�nk?'W�P� �YV�1�1�l��S����)���ot��aIh�`���y����qh����� ���^�4pz $�!\����������/7�����8���c�=%�
,(� ��!���XCX�hk������3����b'����Q���0��^��d����e�a����Q.�:mP8-��m�u�"��A�m�x��Q��>���J.AV���i.���0]�<�"�?���(B�m��K��
H��-��Q��V��*���6)�2�j����Uv����[I6[�B����B��� $3���&���C���W���$�V<��B�D)YS5��*��!�	�P�N�I3����t]>����VK�L~�(���&_1$�B��1���IDyl�;
~��4S��R�������	"�eN�:�aXH�MZ_T�&�o-x����Ea��I�A�EU=l�3H.�^�2Q�P���3Q;C�W�^�yWc��<�2P5/�I�F"���9�<H��}
o;�0� E(�X��g������y^�0��dVaD�o��
G������D��q0�u�`�,t>#A���[4�.E5�%X4�F�I������o�}`6����
�L7��/�F�dyWQVe�dB��8��5����n���9Ns���Z1����_�����0d5�������P������Q���Sf-0�y<x(�M�e�����&���C������C.O[W12�O�O��S�5'���u)7�����%�JV.�Cm�x_63�����%C���}�@�Ao,������;�WB��f�g�,��q�'+�`�(���g�C"��-O�,���W����,@/�r��r��ny��b�:uh+��>��|��xF.qV
U�
�[<sG��X����	�
�M�O����W��e���v�|gn��=��K�S�mb������}0
�����22D�PI�,
_���Q*f�l���g5��Q�AOz��8CO���.; =���q+�h;2�0{J[�2�&Wp��������������� }t��g����S�r�ySa�\��	"��8��h|X�.|,��5���,�����~��(�!O��dq���~��\���J��cP5.�q����-t�;M�����S4��<��?LN�$�x��Z�4�Fh^���H��U�f��C+���d��|�`Z��S|U��Wi=���o<�6�LGN�^�Q�5������G�����"b��)����������\�a�|&�}e���Sx��)tq0����2�G���r�p?�������L��c3d�49��F���&�\\@��/�=5a@x�������8����VB��I!���0`$����.�
L��d�!�	�-����S�.��-�[+E��C������Zx�p������`(%|�&nJ��;/�����N��n��KM���:�*�����T}4��8��6��n-�����^!n������8)fb�R��s�
5dv���q3����5�Rx�e+����f6>���?�Qi��wC��X�a�C%+
�����QH�����2�DK��s6���q�[�,��49|��������D�<����"e�=���;I��/�ncW���<��!�T$�V�]`\���Nb�t��T�M��hm,�@Ym59j�k��c�5�����.�8�}M���l-�q����Rh�G��2[�Gws$����7P�[D������MIuA��SL�������@���E$3�W��s�:�W�"s�>i�Y�G�������^�v_�@:�CUv��S\��Z���J��w���TZ;����%���������	:�aN#�~�l������?m�ac���@r�m�Bn�dj����n�F6Sr�{~x��ya57N�(�.?e\��B�:A>4<����{��������4�<H1��P2�!cc�W������P�O��P�S��@Uh�n���v���]J���UJ�!iDqH�3���L�����Y�T�����,i�A@��e��n�VPr�M��fO�x\<D�#�4 ��aA�Y�I��8PNXc��
�������JAEE�8����E�������IB^k��M��Q������|����u4��l��xB�B��"V�Dqe(����Z^�:A�e�F�PY	`�q�[��q���c^~P�d�Xu�x5�:�����p��;�����r<�	�����u-�0�U�������|�
7. �����;r�c����3��R|:Dn��&Y����]2�Z�i�t8iV���;AUv�T<�'Yy���o��W�P;�0v�)��3XJ���Z��(4��4�y�F�n\��)�$)�W�j=���%��-�S�u���g��*A�~�"2�/�sdQ���t�!</�PYc�]7����M/D�_r����k�K{b���H4�AP��j���V�x�W���y1���+��`���KU��";S\VU��
Dx��o�l��r�����5H�F�����q��1�m8#HM�Q4��,��gp��}�Y@j5���*��T7w��%
�&��+�"��:3�7��F��dIhG�&p�l�dT������C���$���}m�%tV�I7�'�p#7��+���g�d2��|���x��84��Ip,���m�X�Cm������JO��qh<wP����I]�v;+�/���,�M�G���r���-��B�!(46rP4.L��8������j��UM�� eC����c��q(G��t6{:	�2Z�q����\0`������}sQ��f�p���Ae����\`kb -4a��@�P�H����3����Y�^����I�`����<�,d�%k������LA=p��M��cZ,���1
uL�R���1�0����
�0��x��n�E���D?��wC�n�W@ Qg$���)P+1	��0������&c|{)Y�6�Vh"��6��`���������Z�
]DhO�Gsa_�������aF��@�w\��t��*P��0�T���S�FA���P����
�5?���!������X�3�WL
�����)Q�)�hx�7��q
*fE��U�&�y���!K����nm�������N�]���w8~��9P8��Z^�����I�^Y�f&��-���29���)�SN��t$
m��9v?���W�������q��jl��(�J���������I�^!�+aKVH#^@)>�;���B��Q-q5�_��O���fw��*%���l<��+,T��f�fe�~����������V�#]��	}4�����qWvS���O��<Pq�������W���M��:<e�.��@�#)�@����s��[F������G�:�FG���'��p1x*���/����U������0.	u����7$&':@
�d2��N���N�������ycR�E1C�I�3$6)����IT%��@�+F���P�MGp����}�CP8	���c3��]�1C�>�
*&��J���9��g�V��N`�-��N~L����J�a�C����Y�8�ET�Iw�a&J
����+��a��?dB�dL%�����8����C�4��a�r��D�}@�*L���1���e*y3����M�jQ%NN�P����e|8���l@�20�7�e�u�Qk�)������BLTmm���w��b,[�b'X&2��-�����A)�d����0)Y�-D��&�[����Zz���z���F�G�Z�q�unl���`���v�!����9���K`��dmq���!9����H����P����acn��x�BvDO�{����0�l��)��9�������i�M����HkK���e:`2���TH����K�����1�ps���/)�1�~`�<K���M/ ���y�{�������Z#;�Tm����{&�c����_1�	d���;BT������������b�dw��l��*������#�M��[��L��b�AbL�T�����S�Ukf=�f���TnB5>�?8�<�&2�|����p�,�qI*�N��]-�y�����A��9��;WL���:��I_��v�
m�����+�b8�Py���%N���*�{��ks1^��B-
��e�m5�"}�� ��B��:���qw�[=>F
�$U	����^Ccd����%]�r�����FR<��Z�
3H�@�����,������T��N�ce'���a���Rv5V���V9p��'�Bf
eo��UR�z#m����l�S{`��H��l��lR��8^90E���D�4Iz�N�bo�����}e���
���PV��B��!)i��W�a���7\���� �s^����X#�Q4b�h�R�9n#A5�vhc����
7c�"H��-�J�k1;'"`Y\�~4��q����������&c� w�:f<��y�x��>���u�yL��v-5��P���i�@.��.0���F���V�2y�~��X\38�k������*p0Pm@���[`����3*27x�@z������y����{�w�7E�
H�|D�!f��=<.j�Y�Pf��O�mp�:�
��\>�na��*7�@�ht���c@D�)L�Y$�E���5%�Z&�8��y����!x�`C�y�R������$����c��@^I���c����e����D��hk�t�) �������R�j��r��b��JOM�j@��������s����F��@����5��9L��0z�0�%�l
�d�����]�j�b
���p�������,-��AR��b����G���(�2�:{w��a��
F,���`���������h����b�Al�������)S6i/�<by,�<�r�1,7������8���bR5����p��/)&���FIq�yaO_���[��-np�K(^+t�����Z\,ha�k5�e0E��6`(q���T�� ��+hH�!����(���8�f����6$w��a���Y�a�����l���kA#���K |0B������f��r���.2�A0`f�5���F����]�|$X�[efaT�ee���S���Ty*��������-n@��J�k�*T`]]������1��y(By���h{�Q_�'B02ld�d��I��6%Q����W������I{���t��'tee�.��]�����kc��������Y���p2��'��>0��^��b� � �b]��b��hSa	�d4����zYvdQeF'���w��-�J`(��[�hZ�U��:p��X�
+�����s��A�{B���+z0�	3N-�c|$����a�-����u�E����B��~�z����
��n�(*a��-+M�������u>���t�z���?x����+����x���j�{QBb�����s�[�x1���#�?�p1�?��p��_{�;x�g���|cAsA��G�����wf������O>^�rr�M����%3=8��%=��KB�~��f�wi�:K�?�xML=�ZS�s�o��G��iM�?����b0�n��J1�G%�f,�yE?�xE
��@8�?H�9+C@	��w�1`�@}����M��=Z��x���������0Y�����~-Z����
-��������������Z���X��a9����~9Z����
-����N-�����b~X��Z���>-���y���~5k1�_�wj1?,����j>�b~X��b��R��V�sh�~��/
@#=��t]�^�y��opg�5�� A��5+���}O6m\���{����Tl�<9{���������	D�|M�Y3����������0��6�\!(��'#j�;i��2�j�*:yN3<��m����ex�i�E(_�.
�
k�x��.O��,��3��*���Hry����&swy���AK�{aB��
$�����k�i�PY&����o���E �c�:]�}t�����#x�\p`*3��*ta3`��+��F�k��),��� /!q������M������m��t�i�'���T�B����)���J?<����[V"TX������;��bn�0�����A�^ J��Y� yb��.jEnA~�c�L|�>�2GZ<�jOK�g��3����R����.��W�<��lTm�4�7&:
�3
�W��,*�k��1�����[.�"��&}�ou��g�l��#P�B�Fh��b�w��f��g���\P3���8p-)�@�h���������{T��
�tZ�^�>�'���|�I���ae�����1����,SqYA�h�i�:R���T+c�����[y:�X�H�����l�u�����|AW�x �{Cb?[Ox��L7��n��])���[O};�7�5���|�4��lx��E:a�W�0AN?^�(0�]�d$���x��*,rn���g��P!d�P�1N��Fy��=P�������'�7��>�`��N��`0d�����YCKd�Qw����1����V������������������<��E;��I������s��e���M���I�Uc�]��'�'��n�M;�x#�q�V��D8P����dO`�����M����r=�i������J�|/��'�96Y���>�����o����M������f���DL��+_r?	�Y�8�y�>a�wh�Cl��#j��+������m�(�%�d�|�*��<�Ml�a�z��?���l�W�������ed;�Tq��b�����}7����V<92H`�@t	���\�V���B�&�x�d�t2;	�!e�1�s +��n0;��Q0� �C���;bh-�X-`t
S_t!�:����6��R�����!z�����n�A
Yb���Y�(1 ��H$�ea��+�����D�����#��n\T^���*'w����9��V�hb���\����c:Q
#-u���z,����a�93D�*gV�p��[l9B�d������ZbF�g������k�\=�7^B"�����in��/��Y��Rw����a����&���"O
^;�}���F��qf�`�0PR���G`A��m�$m��b�I�V>�Q����i��h�p"y�<b�:J�X��YB���)��a�h*B��v�m`�_��-�E��N�3��"q`��yM��4��L���/�tQO��1����>���l��I�E����5��4�rVL1����f�3����!W��|z	�
�J/�H�.r|����JX�]r���'�'�]�L��u-�/#����&�|!��,e
1O�r��zql�^�'�r�<����T����N+�Xzm��8�o�%0'df�O�oGe���oE��|q��>4��	�6PC���7�^�Z^kJ
K���@\S����!���%���@`a��VJ[v����M|��	,:d��@��_�K_�����I�~�V#�;�r��"~��&�~Lzb���bL������1�9�%���"������kG���N�h�2Y4J���~�)��0����"�[�l`��r4~"��f���Go�[h�������#Y���m���#'m#�5��l� .�5��6����������D	7af"$��w��'�qUP��o���}�������WLQ����	?�RT�Q�v	i������x	$V+]0�f.�W �6f��e*����O�f��W���L\��p��!��.8�p�i9<m�~%�HV�����K�])�����0�,p��%�VS�L���HrT��l�0F,��A�����r�L��W=��]	�����=rV��);���v���6��Vl���n�}6�"L��v��#�3��Q���he?dc���xn�,�)�����z�M����L_�= ��o���u�*G�/R!7��n6��+4�(�����I�P��aB�� z�e&x=B�F0��	J���0�Ra��
P}�D�b�tv����7C�	7���y�0�rJ�4Lc��T��#�\��N�.�j2_#[0N��fI��/����L�����s'����o�bV'�f��L��"f���IW�3��>�! JJ�/�{�HyS1y20�C��\��M�%���n����O��_���ia�I+�@�B^��+����X����+��-����*2�
���\�k~��}~�3u�.9c�5,K���eiz�v-e�S��}�gU|~��i�n��[�,�!��G�ymMey��;��6]�i����v���j�����q��?C�)�sOGL'�]V��*���G�<��D
���O�Wl
���-�lw���������P4�Q�v���(���E��i�gx��1�'S�h��������po;����Y\�.��C=�J�Z�n��J���2�����Z�D�&��Fx���<�|u��f#!8!�fx;��)�uG���5���I54��M��Ut���q�z��<��=;�=f���OO�����bW�<
���yGp\����R����7I�S"(z�,���H�+i�3
�pI cV�L��
	`@No1G;��������l������~7y>��Wm�Q�b�5\���YX���O����&�D��E �m~�8�q'���3�#�(���n�9���>A�<��	@�M9U��<�<��yK����1�Y���!r6��F�m\�,������2|zW���:E�S;}��w�=*��e�M�e�q+6�������/{Y�m��W����JH�1V����F�$����(
+��<��a/��D�j&"���@�����	��0J�B���M5����:����ElXu2�6
�%��B�g�V�`�����'��/��qO��t\jx=���f�0�Oh/a�<��� Z�WRb��C���M�-a��G"t��_�i���������/Q��/��e��81�x�c�������D;i�
�(
I&���)�+���>�
9���Ns�#�����7H<�n���� �;����.0��%�M���#
��&d��bA��������	�z��7"Bz��6Q���&��4:������-��)4:W:�E��S`���[�.c��v�QOj��[d0:���23�������:b�{��eq�qmY��n�n���/)w@ix�g�N���QI�� �B� Ad6r)��'7/�
�����Y�q)Gra
��e�7���
#�������Y=��3Br�f*/@�A��[We�*"%x�f�;&��}��
����*H���j�U��0p�����	
i�0�A�5���'T��2R�I�Id%�������c,P���)�S���	�*>N�#��\�i��:�J���� ��hj��������������;u���WyH*c	�BoN��u����� ���%9$�)��Ijy���X�K<d������$^DC-FFP�@�b^�qV�q8�����~!���wh������J>�q���V~��fq�g�U	���i"ejZ��(Z����~������9��@������H���C%���sL���P�d�h�rJ�D�`TN���f	�\'9c
7�T����$Pa��1*E���x�8M��T{1?:J�����G��^��P�z�r�B�\uk�����=-��b������LI	(�����nt����
-�A�&���n9lr~|g�8[}�>7h&��S�u���@i�|ZV#v����
����
����d��F�DFsM*�����r�k�+�����m����/��&���<�������U��Z�������R��0G���������$�S�cA��B���q���hR��d�?��	�&^I�<H@i��L��!f���z���,aK���>��%�B(�5]/�������@�%����Y�*=���Y�K�S�'��o	�PX��(�� ����oI�92Q�8�bi�p2:\��=�j�����������4��~GHzg@\<���FwM��k��;�+��h�J�2�"O�i�����o��t�`��7}c[
@6�6��������t�Gu�	�7�8�	K&�\�M�^�?j��(@�E������qh3������8���5?]���SxX��2��b�2o#�.�"B�^��*�	�����W�A.N��{���|���q����7�HK
*��f2�J:�S������-;���(9vI����J�LP4�D.p8`����G�'CPH
L/���0s��HP�oWg�Bo���9_���n������a4����A�AK���m���H�nw�i��8�fw��0M��BIG���(vu�14���.�k�:%�� �PC�an<0��@*^	���%(|�dH[�B!.��,�KK�NOh����$���8��m�GDrm��Qi��.�Bj�s��D���n���tz�oOS�o�-��n�7vL��V�z��e���R�_jU�(&��a��(;�����9��d���U��!
E��2���@�I�PY�C���������#�����<����D�/>F�����G�Byg�l���u��(�������"� �����b,����o���P����sA<FHW`vLBi��������S1�K�s�������\X�~��]#
�v
�����6F�p��UE�oS�b����p���8	���8����71���_h��%/��	��1&�Z<�6E�B<;���<;nP��h���Z���@wI�%2�9�`���hru�~�Q�����(�1�0PN��t�S����t�]�a�S����8�8�������,l����\�j���D����j!���L��)�]z� ��e���	�yQ�P��,�T�:�g����/���2�������~LP?�`%]:aM������S��B����Gh�lDTuw�q�P�����*fK��@Q�tp�L ��A)z�0G��SV�R�)���<�W��$�C� ������0���{���%����4�'���cPS�!,�J�,��`c�!>�SZ�}qqw���K�ptN��=�0�����r�,B�7���3�����y A��n���������R;�E��Z�.qx�"��[x���J`�:�UwD
�aI�(�D��H�fx����1�hX	!�n���(��5�2�����C�i0c^=�]^:t.������$ ��TRAC�0@���2
�2i3��l�tY����������F����5O7������� ���#�,�h���G�T�J��w ��=K��;4����h�B�!�vu�@�N��p!�v�tR)����#'`4�`�%�\[$���2t+��L�Y���e�����0�$���DQ����i (���
�9k�B�Q�nz�mS`d_���'�l�)�8���`�+G�+!�2"6������A�B��,3+]<u�L�Qcx�%����(2)B@*��uPR%�;'���{9<���EC���w���]��+��Yh��0G�?
/2�:x#T[��ij]���Rrx��������<�@�a�8�Ik�H��/3�F[A���� 
����f,���A��Q��|����Fa��������'?ep�q����H9.�b��
M���t/\�,4l��p1s<F�V���w+5��)d��[��J7>|xO�K(�`��]���!T=�]dS�{l�y@=8U���f[���y81]<D��J�s�&�>�
��9�q��!���C{����P:�$�4~����1N3Y�D���ze4��-y�s<tY��W&��z�;f����8��DZ�\�����R�3g�b��:f�-�Ax�cW�#�S��S'���Z������+gL��0M����9\��p�Dq�"�n
���dz��>��2�'�B"4O��X!��������������^�(�2�<��5}4|�T-Q��~�L���m�Q���z�����f�C�8��Yx�6M������(`�V\;J?��0�Y@���d��0�?�n�R�e|�0�N	�q�����)#�x�3�����+Y���In@>���;6\;w�{TN����+�H=|L�
��tX���B��9���{�aN����\�1�
�A��N�q���*�e��
��#({�TPw���kt�O�I4����D��r���q��'L��gX,��8L@�R��7DCf�CE��'�CCA.�`��1����5������NX��d������h�$��*$�����SP������m�u%��\��0�S���%V!Y;.c��k�`��}1 ���n�V\�f�!P�xR�|����
�:�>5k��V��g��3:�N��'gx��"���Y>5�F��_=���6A��grH�.���������,o�N-�x��df��8���`���S6V�v���T��	����a\�A�C,��8E3���p3���pj�;�� �a�8��������p�������]�Bz�wZ��D�g�:��G������n�.�/���
��\��W�HM�
�V�0�1�Gf����@��!O����j���i����C�\(���:����W��4bE�i��8`��a�����uy��W;����F���JW=��D���{���6���K����������q
���3�#�k���_L�g�;w�V�;��0�3�m�l���Ha	�K�t���a�N!�Z"�����Jc<�O��)�x�#����9
<1�����T@�D f�j�� �f
�NT4�������y���>��U��q�{�l��
��Ug-G�y�1_�v8��3�T;}�������r����!�_�r�^�j=O@�q��
�h���50���Y��������,�?8%$�Ws
��#v�h@��O�1���R���h�����l����)���������9=5fM�.0b'�D�;]L64����1������5f�4/�^��^$K/c���<d���E����On�(�xAP7�#]z�@�Y��������\,�z�T�C�
K�.u|��{�Zgu*�2�*�.���TO�\������P��P`(r&�A���	�y���b��Q��CH�x���`��;����E��h��{=G ��t����b�7�R���Qx
��Oc�[T�5�4��t��/�.	@8��S��������KcG�-��-z�-�x��M�N���1�]i.�(l�j����`�W����C�u�������0u�����-����OS�\�����i�h�l�A;O���( 9��xP9���@��	}��P?�>��u�uar���R��������S/�N�q%+�RL����vy��p�W��a8�)n��Q��[9{%������i}q����t�p�k�`>������|��X
;|�>��u����7�-�����b��2����Q�L�(c��`���q�sw�^^�'>pU�T.`�$�~��G�E.b���N�Z�H�NV4C16���F�z�m� b^Z@`�K;�������C���yR��*n�@b�������d�7>��h�������'�N^B��b�`�u}��D-�:��#�=
�V@�_e�I��4J'��h���5�
G�,��\�-`�y��?)�&��x4-�����1q��&u(�^�=N����SPnd�%y���'����uYL$�'��E�6������������&P��oPLZa�2�c
���z���70M �"c��!�`l�O���_o�B��QFa^��>��;��v��b���b�C]��H��v�D�:���M��'��kM���8�('3+�"�NC;'���]B���x���r@�+�
����k�~���6[���
�����5,x\��N0n3�*3�`p�a��Z��(c���<�L��P�1��,K�������)_�������g�����3����`<"��#���<��w�E�}�
.y��e_~�X��?zz��7}C�Q�]FJ��S��������z�{�b���
 z�@�0O�������I��+�?X��O>V|Spwb����=�X�O�y��7V��Z:g?@���(������R���	��P|p��qaJ����o�i�L"�����*B$��������4Lf_�����*x�����O>^�L
������"%��<���'�XSWF�� ~�����b�g;����W$�F�	�����h���w+>~h�P\��'�]ip��B�����Z�?>��c�G������wJ?>,�A��a9�����������������+�X��qE�'�����}C�aE������"��+�X�qE�'����:��X�a=������R���X�qE?@�6F�v��V��������e!j����� ��K����G���U�/qo�#��t��k9�x�G� �$���oy2�\N�{x��(��	&=�v7�f5ho��hSG�x�~�,�ou!S�5�QZY�E�}V6����]���y4�E�������h���R����0���D�����x[E����p?Eh�[���C���,0D���N$���{dr�����Z�B�)	[G
O@"Q��E�a�����o����'&�m��P�Ta\b��Gu_�8��\}M��������^r.��JOW��E0X��
��*&�}V
$Sj���(��$�GLc�Z�j���\���M���A�$:@w�YFGX&5��k]x+�
Q#�+�G����-���&�-%�xp��*�r��r��)�f���]�u�vz��n�i�N��5��V~���NJ=r�dSdJ���x�$�j_H�D��",�QN��"�L��b�
��P����_���E�����!�"��3.Ee/�����g�#Ne\��e��������v$�3���_E��.�,�'�s*�KAG��,�.�N�0��j�_�)�+�(l��F���S��"~s�V6�8���`\�b�@��;`��>���SQ�)"���)����"���=m���'�x��c��$C�dhv�4�����%�������v���8���H��h	}��4�-�����Am5���jb?;��6z�<�&;�Jv�&�3L����+��,�l�D&�:%��os�_.����:�sO�����M������b��`0S�q���fz�<�&��.���k)���~��2������u�m��)�}<^������f���������i��k6t�� ��5�k�Q����~I�*�q��{����r�E�@�X �uf�_�zJC�J(����������������%�w��!�x�����K�4�6#��%���I���b�a�MQ��������Ds�vW�K�Y��0���C����P6v5z�G�un�$:�u
��V�a�wL��
"��
�L>�������Q.�t=3����*t����
OQf����?q������ZP�������.�HM/�Xv�
�}:xA��V�R�(��@��>7�6��QE����z�-��a'
p��A�>+�j���������]s��4�
f�]��G�a%#���8���f�_�������V40P~�������:8�����	�4�����R���3#}!RB|�'����f!�4
�������Y�G8��xyM���5��b	TWP�<��t}ES m�k��R���8��
F���q�Y��v�����b�����r!�!9��]���u	����/R�A5=���7�?��Et��� M�L�������j�����8+n6��8�K�u2���T[�5)�%���*��(�QM��B��A��`	VM�OQqp>����0�P�<� z��J�W��;�x&=_��l~� ]��}����2A��|��2�y�U��hU��r\��L$��=Q;.�:.��e���47���F�i�����)�	���}����b�B�R7n���e.`	
y9����������I�_���/In�@����v�XX�%G'r��������(�����>�������_���T;�o�zo��J9�Yjd�������	�\8��W���p�aR�c���~#o��V�P��IbO������� EEr�$���Y���z
���)���BQE^�`$�(����h{H�X�:Z��%�����i���H����k4K�(I.3S����3��B���S�D����egd���l�5F�5�3����K��*N,���]"�	���`F���R�C����@����#qT�Z��]����a,Q�����t���K��{��#�%��<YX\��7���1Q���G���Vni��{�<	p��|I��4-W���Z�p-��'\yl�^�zI6�����b�������XSl��$��o��fl��
���@�����N�"#���Hc���e�R��=�b+���L��C~U(����gKVc'�E.2�n����
�$�"�
,>m��i����OT��;���E���F5�B��T���/��~���.���k�n����[�
>��|�x�a��S��-p��#p!�14h	����v�Pm�
1������J���CZ��������	�C���l�D���@�"�D]�
�fCt��6k<HI�����	��at���Ev�+h��^�'�Z�	������0��#H$���|��,pE�����
o��w��r=�D�d�p��'AH\�/�w�L�my�4��[�S��E��B*w�s�?����(%�kC���fd"����LTBH�R�;�{D=!#��� !]���EJ:eP<L�nWl������-����\��o�����n������`{�2Tfn�3�4������{{7I�������>���9���k,�f��{�xhT��7s�/�ynP�������9i�,�I���4C�G�E?��Do������n�]�l0C._��	\����.��/7Z��rr������7,6��O���./B�Yv�X+���@c������7-����>�F68�H},�z�
��l����N�DE6�u]��)1uZ��a����}�^���l����_����U���'�!y	.��������`
�f���&0�l%q�x����A�U�Q��0���%�Bb?N�3�\�t�s^%?������%!4V���	������_2��uuL�X�>uh�>�-��(4m�((S�g,�������������Pb'�x."�2��=�R�&���x���/?+�=��&�,�����\m��?�T>���Lm�a��7>	�������u��H-�bT�$�.�����y���^n�Zc��Lpz���z$P@	�"sN�P��n����ak�_�B���B>fcF<��7��/�����Q6���7R�ER?��
��E���/n��E��8�����L
c����u:��TQ��{�N���y��^�=12��g
�;j�WgmH4���0{��r��iY6�I����a�T�=�K���W($�$����5yf�/��HyJ������R�,��j�<@�
���d��e**����+b�r�%��������a��
�xJQ�iJ��]���oD�k�'���'��T�]	XA]�����+������������"�����Tq��.��3���	nF�^��*��m����W*���� _��g�10�7���nO4.�YU5:�C�z��v�S�0�
|�����E&66$i���
l.�SL:��~~4Zr�4�l��Y��	lD����7����Bz[n�	Q!�k���M��SC��%�w��%l�
h��<"�2z���r4���*�n	:Y�g7�G9����:��E(�Wd!;$=�/]>�C`������@|�rX
 �$K�	�}����j,J�Y�$gv�v'1�Y����0#��������1 b�S�:���E���~�#��M�O���We2�[�|	�C�3�	�{��'ApL��}�^qD���*b��x8;o��\��,JHD��D��<2L�a��P�@��[�gN�DA}|���������UAf��v�
v���f55"�^�3N�}$�U'��A�8�v�v&/�.��J%b���=�#k*�B��w����?i���r��Y7�&L���"��W�`&��1�J&�w�F<�:d��hl���}���@OZ
��c!�qp�CY_5�@�}@1kb�s>R�L��GI����C��]v��0�;s2(��
*��A��'TM�C~4������1��@`u��/�`P���m�Cw�"5!������ {@�4S�Kb���=H���S?����+�|$��n�$�E�n3~� 8z!6���~|���yh1�:H��������'c	Y�H\l��!7�QU��J�c\oR}i*?�lP���M��B������*����2.q*!6��{������n�^;1��E��Hvqkr�	��1�4��@u����x�K2��1U����V��V����MT���LJT��: ���GL"7�%u�������=6�y<�-������e@`'Q
�TXEei>*�A�L��/���������wB��!I�&�
*�P�`QCO�<�)���0B���"�8�i�r���a�"�(�P�)hI������z��F+�^tt}�AU�y�<��##pf��c��@�����������PK�����\�9|���u�rDB2S��uK�����L���D�<�.�YPb0k�-��"$f�k!��~�^���~y<7t��/��~O-a��]X���-��Kar�Si��t���+�.���~l�d����A
y$�����R���4p�q��#����G� �?Tf/��Q���r��?J�����mE�\T��!�|�UED��c
��{��.���~3�8��jy0+b'�^��D�&���/���")_Jc2��F$����y�I�������M�@���/�k !��B�`��|X�Bq7f������rE_PC)G�
�u��aS�z�q��1(_5K.�y9�z�����t�|Y�&�|.�8���x#����}$\������e�RLc��Q����mpjW�)M���@</��wG(>)�FbT8CU�Zq��-�RBT+��,h��m����I�B��Y�"����)�����#��)t��8|m����6�2>�#����l�^�
�r��|c�������7�$,L�&�����"E��f]�L���"$��E&�����ZQ��a������# ��l�2���
�hC���*9v�{ LGn�yd�(h�D��]	�\�B��������
��}5%�i����m	n���3��k!D��R�x�.����M�;���M�0���	��#�bNo[>@9A�p���&���|�qT�d�;IRB��K^��-�r���\m���Hq��	�2B��h���8�t�����7)�=�B�-!�F�l<�vV���rE��������R7�<������1
�$3/���]����f�%�A%�}xK<2�uvJi��pj�$���D�-�:{���������o���S5��WY�49���T
1b��p��dz
R";5�7^�����A&o ���2�?�=0RCt�;?�,^��fk��7%5�����$MyYH�G {��}�����]�n�D`:�LE4B��\���H?YO��v�YG�c�#������S�������/+����������Zb�}l�#�s��H�k7j�x;�=�y'c���\�:��"�WB\/l������,��VMm�2�d�q�`�n:�e#>�v�tE�����}_/���ZOE�f{�IM�5����
2���Z"��c�o�h��9`��-���\��R�������Lo���BV�Pk���������Hi���fl�=����L�2`�Xh�����39!��R���+]�r�C^����O������z �K��������R*�L�$�"i���T(��A�^�3`J|��6l;#����Zb��@����!��	�	��3�������S���U	b�B�;����iH���t�,D�c
sC�Z�V�V���Q�a.���_��P~�\ob��-m�������N��H�G�����U�������2G~����G��������_��<d��������� :b�2KE�c�+c7J�:������ra����w��,��K���N�p1�t�m���-�q���b���:�g�-�����e	B{�r$4~+HY5�g�(����.q,P����*�e����e$�b�v��B���u�KL�{�#%�%yM���Y
e��������f@v��C�RLG�t��&1t���48��B�{n-���(�v��Z�
	��I�����y!�&C�
E���V�K���1D�[;?u��"H0&�y��
�B����0*e���g�qB*W��0Y��6�n)�}X3w�6��`�S����,��}D����'`0.b������0/p��3���Ob�)#��_�m�S�������8� P��F���b�_i�M�"��0�lF^�H 'K{*���}�Y�D�7�A���(��e�����Z��
���F*Nr���z��w=/��2��F�1����;��AsE�6�����*O�u�@���^����	��*���kc�Z�Q�������G��l�
�-S�K����Z^�w$Qx8�� hnx�EF��FF��Uf�����������.�tLL�P>�Q�Q��cI�@.G�~�We�uI#�HO�0��\0�����@O%��e��
����<"�bj7����.�o������]����AH	�H/�(���C����$�N����s$�o����4&�J
B%m��7A"�]����6���Mz�Tz~K�U��l�����a�x�o��5*B��� �	���O�r���E��U��c�.�}��n3iH�7����h����@�*�Em�����7�syu��2uV�q1��������41:�f��g��5�*c��b��@�Z��-k8L�}9EHqQ����dL]�.�x���8�"���Rj���.�<��5�/�y�U{�o�'���~����:������+!���n�;��c0#��{����rSL=]�]�K�38i����[2Eq!%�7m�X��"��������(q��m��4��@��=G6��(��R '�P��{l�S#"�>6�A�F5�����#�IZ� �mB���D�{��|��1����}����oy��<�����!�R�T��N��7����r9�����i���q?aE��������������D�tk�$����Z���(�a��?��d�C#!���GMTD�0�����[�*"��pY����������S�����������t�#����P7;�����L3_������"�"���J!,�n�:
[
v#���9=���c78S��s?��L�����!S��0�[�46d���%������K<�lI��P ��Ic�z��.f��C�;��C��QFGrR�4��M]��xRE#��������>Zmx	�#��j����=��1fL����Y�(M� O�
=~��p	U���g�3X]Xy+�C��+P�����O�b��5#��<x�m���e��E|�N��(���Z?T�`�4�k���S���B�5��fK�F[qy���e���Y����Z_�8q�0�����.�k�H������~���#��������FD��m	DI��KJ#O����39���n}�E+���'e��LnW�;
�����@Kf*C��]���0�����t���v?{�s�QlD�A�O��8�k����;�Y�`F����y)�0A����4��=-�^�@��|S>�\�&�������C�5\�(F��Ons����x��L:�� �~@���v����$<��\�lO]PF�"N ����\J�L�L$d�R�3</�� ������oN�L<FH����_���.��]���b�V�g���@��k��I��8��p]z�[��U�����[��ye�����"3���Um?�t�q�a�	�����>����?�����L(����������������Y�WI�,��B�I������E�c��.����
�=\�����-�bPU���e%��������Oo����R�x�U��e-/���l��ac��z�gK\$�c��{]��?��Z
��`r��g��v-��AF~Y����~1��S���.�>�����_�������vt�V��%y����C�j��,����T����O����m����l�C�������W�S�0�.�����PPOLq�O������{^h����nwxD.t��@��������q��#W����-���{k���J>���DZR��p������@-�������a-9�a���������������R����DX#��B�����JJFf%�zY��?��Z"!~@1���/����`!(��������X��g�.R�������Z����O���d����B�#2�x�u�P[��
v�(��[�Q�_S�/������Q_�P?���1��?3A��?������/��������>P�����m���������
Ry�n?=q���3XEB\z�<�~6����k�>�E�����i���3&0Ec �����T����K��'j�~�e��.c�8!'������1l�9�D��0���[�r6
|�36lC����F|Gq����|h��?	�a�M� ��O�����d�v��HO��V<{��)�%�.G61�H�wR5�Q?��?������V�g���~i�����|XT�r�h`����q.B��d��C�1Dv�k������T�[���9�)��y�;����hN_�����
�+�#�K���A����Y%Be�`�%2O���
E�@����i��E��+%f������x]I���f��t��������/��qC��}K[8��N��h�{|0������9;�R�`.?��}�j�����W�g�b7)��6�tDk�m�����Qd^��O�~��(s����2�����9H��$QbduV���x��
�W���XY�����Y�#��$c:����r[>jj�`��T%�fh8a�����Z�:�4a`i����	 d�MB�`�V��l��}a�B�zB?C������3����>����0���l�X�U�m�z��X�A����t����>�)LG0Z`�H���0/{�0��XN0���'����_�2I�k<��@>�@o�NE�M�Zp)+��Yn�x�%���2j�i�d����`��v<��X�	�l��3����}:�n.��;o"��t���]�yYp� oObk�#��2v��3�\����?W�W��/7�	�:v������o��I���xV���Jl��(����W�m�J�7��$������4�ls�����t�}^B&�@=Z��������4B��U~F��0���K�}�"���1A'�#����pTK"�c��r�6m�x\�,��W`���j{��Q$iODI>�HY����0,�&Xl�����H��`����;
� rNUAD�~
��[�z����m�'�"��K��*Z��� ��^���_��	��+	j������z���|������G��%1�	=�%2�Jd�����A'�r��"���{��n����G���6(�q[�'�t�G`��H����6+��#�*1����j�oc�$)��a�U*�9�!�B��i�!j#���1��$	��t�����Y:��������%�F���`�giq��� �g����������C���}f��A"g�"y��OD�	�Y������:k����	�$G`a��y<?'����d����0��m�.�p��-����K^��j���}�~�A�*�'3���n�?HL�����Z;��)L�g?������Jt�
��C�K���h6)�s�*��(E_��x��I�bN�����*
D0�N����kr����I1H?��	��o��	��d{P�_��T��"0b�y��Z���	P}��Z��������_��*�Nd�/�&R$����RI �����/�c�y��#vlt�D=�b&bz}��������!X���5X���*.#����Hc�"B�t���V���JS�Rh(>�QA�-��!���F���ak�O)%eZ�m�������p�I����d�W��:��I��&-2�\q�����$��ajrS
�ar����-*1*�����"C<�0�������#(`+���Dd��:2[�����1��z	�Hg�l���(�(�b���?o:}�!�
(�l�W�|�Rq��]5��S�?l�.1�D�jZ�&���B���������7]��������*c����0~�~m��q�����Yc���������^���+�������4���5/$��4��B'%�p�Q����F������=����F���� $�H�d�c4�hN���\q�����"��c�Qm
S�q����������K�F���Rx
��u�x������S�,�Y�l�@�:�cJ���������R�B���b@W ����;
J�j��)��[��i@�C��N�K�n"�0
D����w�57a��~<5R���?��.��/��S:[v@��&Cs�9C��x;6�r�����������KV�x����A�/6��E�B�������D�kh��,�l��3�B���R�=Y	�)���^(4��������=�I8�6`��'>
�9>��oA2�v�QF���W��}�� ����5�3�I2��w�i�Q�G�aR�l�I<�����U�v�y�4���Db���9�k���!�*/��
2����������?G���M����:*�3�E<�� `�g��oOe.Q����A��7���v�h2��Q(��;P���5���;�^"���>�Zt�����7�Nq����`������`"����*L��9<�����m�M� s@@s�eK)����>������]��zi������-*��J�!��UE@�A�+S�Bw��D<[���"���mCNRfu����������OV�(Rt�}��D������BLx���0%}�@��Cm��� ��J��	z9���*�����*s_NL�����p'�������(�7�sN0�6|I�T��F����sx�����s�ul1F�7~q��o��Ya��D"Di=�<�>\:F"F�7D������j���[YC�$#a��I�7�B�F��|<n'02���Dz�7����C�H��}��e�n��PN
	�f��������p�	+���;�/���(�I���"���'8�����<�v������I�VW�?n���U����sS�AqT��7��d�z��%�(��	w�nB7�;���a�FG~�p��=���I,?'
f��H"���>�
Ot�B�Q�B��&�^�1��;q JT\����/b��Bv�WF���H�vT?�k"73	2�U�=^�E�����P�kY~"�z3��A�\l���9���D�7d:�S�S#����~-Y���d���R"6�\����u�(�c�����&�)�N
�����V6����-������O�Gg���+2s�
QE�Y���iU��������c�GE8~��������i����oP�7	8����w�J��w����e#g''���22��l�
��2����!&��5C��*9b��G(�����[�j���}f(;8��p������?:�
F��`�%�{}���m8����o�[*���J���h��F\����|��,t�^�����T���O�vM��q��#L�9����L�9�S��+"\q�e1t�9���;7���K��*�c��Q|m��/X�4{�A�9��k�f�)t���_��{<�hJq�a��++Ps���n�� ��s���
���?��

K_{gZ��K�'���vg��D��B�������yb�a�W^�����D���9�+�$������
�n��XLx��	�e�&�X�rHsR%�v�4����'E�
{�&pj%�������LY��#� �1?gJ#�v�dG7q9��_ ����3� �`���:��u_��?!.���w�~��=m�gc�1��0K<`@6w�l:�\Q�v� ��VG�{�|���4#�����K$m�\�UN���a�FH� �>6�'UG��2������E�L"w��E=�"��/��`Ylw_�%��@1��������Bj�1Xh_��K��6���Tg��\�p��&�R�jCE�v0��N�Y0�t��������Wlc�G�Sg��.��az��P@��
����,���h_�cC)�����Q��:*pDkz~~u��f5��+�|��?��x������7>����P4kU&E��n���&�o"^i;�CvO��:v�y5q�����O3��J�zO;��Q?���B���h1/��m)tY�c���C���73e�TE@�����g��C�EV�>2��g���|l��y��
Q�\�R��~���0y/�L���"K��D"��EU;�#!9.�`�o���V �z#BN������rRC�r���~FM3 ����$���q�Um���2��$U��?��e��"r�2GO�r�����iH����*���	�0Q�FDN���j<�������`���X��������E�]��I�qhb�=������+<a&f%�iHc�R�EC[b��1v�F�6���/��(�����e��PQV�E�}e�?q��kVm'�3^����QA�!Y
�p���TY�`��2��,�2�(��hK3����#D���l(��+������Q�6H���1%>�6����E��!A��%]�(����q�k��?D�7}����B��i��	Q_�u.����'
�����XU�s���ja���;���`�l�4:� Hh�J�5I�R�.�����
it�����+����g��L�S��Iv%�11��WN��8�:G�~�r���f�������7${�����"�e��7��B��ZK,�TtxL!6RNBl;�H6A����T�7������a�L]<d��<����!PW�1����e�dNR��/���P��H��b|�����7VTq�?	ABp�����l�����%-,
�c�������n!-N���',��~��>R�{T@������,*��]�������B�����(I����CN��J�7�Y��h���u��T�W��u�`���4��u�P;I,������i.��x�DZ:2o�m�l�,�����-��X/Xb���%A�
02��i��v'��aQz��(()��7�J�����R>Y�/}��*I�Hiq����US���|#9��^�Q���S;i�����L�<�N-)��"J���H2+,3~�f8����Q;�� [������<$����P�M�^��UU���l�)
�=�b{�Ew�<�c#<�mML�P�E��0�c�nOpV��`��yQ���Lw��]���CSPK��*�A'�? ���$4�]�| 
�]��������������d��Gu��~gL���V�\�����$�s�N����P�I�(>������m���mh�ht=����B�M��������[��e�g��\��S��*�����n���G�dv�rO���Y�{���X��1��A��3"�]�|��	|<�l}cY6Ax���F?���;.�)��H!���T
g�i�G������I�E�l%W��<I�@�9�M��Iq��
�0./���Rf�3��&pI�-k���`�a����2�$�����.x�v��{�1�`�k��i[nBI��e���l��C�
X.��+�����f���*���v|�p,<�5J��/_�D"�_&*��~��������G���]G�-t�26�6��8�J�X�t�	���g8�}�-7���mf�Rw��WCT�>��j-��}����$���{�0y@W��e����F���7a���Jx6����X��(�"*��>�Djn��IU�P�pk��5NAN���kl�b���/��B��������V!
rz�Y<��G����D�8��4��Ct����@��Y�!�R�������'Ih���=P7�Y#���4���B�E@�=^�4~w��dL����~aC�p�T2Z8��%{N7�
��&l[��2=v�^����������
���0�
�3�#���0hI�S()��xCFE�=����!��^���!L�l����(B<�k(���y)��-O$��|{���~�O)1�����]�
�\��(%,]@�4bUb�
�x�Q��98����e�&���]U,�4'����-�%a���/q�7LI:��X���%��;����S�C���}�C@��Z9�3��j��,���6Y�F���=��������,*6����_NjE}9�"��}��v=�����o� ����$��)vM�Yl������i�S)aaae �f�dk�t�m�(���b]p\�����M�%}���"<#�@~��X�e�35���M���n�����!�8��e��h��zG�P*S��g�UA��DI���
]���<�[�H����F�iq�l���@���3F����BV&�]4?�>����3��h��[�wm:�5�@�K]�k�>���R�t���;����R�����?�������O��i~�V0Jl2?-�!�)�mS ���U���[Y6�O����q�b��<B�zL=`����� P��B��X��[�]�Ar����Q������&V��n������8+r0������E��W�'$��\�E��agZE�@�����L�.��(Vn���_'��V���fT0�U����hHtK�P9j\��S�q!���p��J��3$	i���t�����
��E7�s��gklOp���CW�>m����qRf�~���@_Ap����C�Z��>���{�Pq9S�2��e�zbX�$�&8���f����4��g��M��6m����`����~��|j2��<O�t�������<��R��bu�L�WA �%�r|�~+�@�@��^>����^v�8@�.:H���=Ya��!�*���������i����w24�Yo�ok�= v����)��ZB��^���C�d}z<��>n�����}�����������L��gY�����*���D��u�$�T�0���K�����fm�G:hw�FL��`�;.���d?OK�zJ�JQ�E���'u�6����RU������pO��"��<�(�Yr�]Iu��G�.������a�8.rTZ(R;�i[�w<}�n$�"�_}��|����t�SF��������W�_<�_��
?Z�6���d�Q������V`��]��0��E�OR��X��o�W3W�� �
[���uYX/���}���T�c&M��S�8�UR�B��o)�Mh���5��{�AD,�C�3�v��*)�e#�G
F����!�(3�	�b0�i���kNA�!�����S���8��4��fv��1�`=mj�Y�����hl��B�����o;a�Ry�cS]9�������C��1���
�.��yB��j�(n�2N�ka��vL���`>�#�bgw���d���Q �8"�&���c����
����=�`���x��V��w����x��k����8���Da�<���1��'�V�\C���j�']����fP]NR$�T����*��C=��.��a�34��Cp<	���!�l!CU<�2�[,?=������.���6A$v%�2�����������;�])>Pq&�0��b��;zB#���
�������Y�
2�����"�C��d�/�4�F%@�F��d�1������O����������M�J�|b�e��s;�C�Wa��EL��m��^,���?��#<t<���hK��
�'l�����Q](-��+V!���#��^7����W
D��}2���h1(V _L<J#�Bd0C�����c����#�K����m:����\9`����~K����MM����%��aI�
������G�J�k��lE��F5��`Y�M�c1N*� -�c[�Dx��A-��F�xB���F;�5	w��R7_o����i����f��P��D���ue���T/�8�p�@g
4Ul��1����|H������M+�����H�����mH����6�X�lU ��+_�����O��n��q%�dc@1p��"jkt������(��g��`������|�|(����!����	`��+y�����NgZ�@�e�o�)pf�id\*V���������D�i��^5n��#������r�!���"��9]��E�/M�)H�#�M�H�!�-*��5�V".��'��yl�0��mO���4'PUcf5�

����G"d�
XR�yy��O!�'N�SM���/I�!��G��5�'������Q<k?��d��/����X�D��������a������]��
��K1N�X���O �px��yq�F�����=[�e�m�����|��(��, �N�dD9E?�����Xae��*n�x��@����~l�Z���e4�;�������K�X<)_��".���P�3�D����Z���+�2�|�}�Yt�F��1�d/�F�*v6R��+�Fu�Un��!f�M7@�Uf��86N��#�Br�,
	x��c�@�[!�5���f�pN%�3$��4��Q(����;(�
��b�p>;����`�D\&Ht!��^��������>E=��P�6t��*�iP~�z�$�O��@L�A�'!���
��0��L[dS��������
 -��F�O���1W�.�'�J�����h����'���"\"�F�D)T";�o�lq�����3�<8j�{V�c��A�E ��K�M�t���x���j,��H���!����,�}	�C2�q���[��f����s���z�������`_���`���s4���&1�w������A"�W�S��/��.(/�:��%�� /&��#Q�}��������X	��Nc��v{9FH�#\��GD�}hq���Z����7��
/�L������F�
�����<���@E����
F
e"S��E	t#B���-��eb��o���*(����/��}J@�`�M����4 ^nD��1���3vkHA����<0������=�tkQ���v��~�YTZ�F�O��R��������XY����%�g�/����������&��S�r���^
�������o������?�������?p.�����~{r�����g���/�O]Ko��������K�c���i�"[�-��u�����-J�����Q���Yo�����+�dUB����K�DXu�q�������@�E���K'8��������v-��J���t�
D=R���|���/B.���w.]i[��o��/���,����[���������\����_��S�/���t�����t.���&���wi�!���U�/�K�����o���}i�m�_���/}Y�w�������-�Mi��������x�~_�LL�/�/]L_�����e5��1}Y���~_�����������r����e9��L_��{7�������K������r�`h�}9�
G�6Q���/-Mm��oy��!w����nA�������?����i��h�������z*��@u���,�^GCr�	x�����G��!|K^p��t��O�T-Y���![�@���]&��Q����~�"�[�.0#5�`)4K�Wp�HR<N���a��{EE��f���1�B�S}��^>�����'��N�'?��_�1��0bCG��#1�+Ox���'D|�M$a�%��~�X_�c��*bY�Eh�
�=���G����499��H��B^H�����������'���%Q���b�S�Ld�8�������f�����"n���}�X���]�n���s���`W��
��M�����Js_yV>��<qr��6l�C~�g�b4��A��9f�A�S��K����|Xcy����;��r��]dv5�l2�����>g��Gg)/J�f�3����-d!(t�j�A���h��u-���������?�^�cu32~IL`�]��{3�D�&�
��8�*_���~�F��n��P���������2=.��}�*L�K�&�s�G��=jw������W�A��0ji���S�*%����$��C���7*m���0��an���?Z�h��%����&����:4%�(����F����x[��q����K��D�bWn��m	�b��NiU�*���I-w������O�C���jl���&��&��N�4���Zw���*LE���~�O���o(���o������M��#7��������s#t����������<��#��nBwi����MK�aDm����pu%��c�	�n�k�lY�\c���8�k��x����!�n8xB��rtp����=�-�R������W\��]+t�����K�
���&��x���v�'�:>��|���H;6k�{���>��`��,Y��~�A��\;���r���E������W~i63��v
T5���1W~r���YP�F^H���#��n(��hL��(	.��.�oC-���P	r~�rL���o���o3
���q������B?��O��|���nD��@w�-�V�[���| d'����G����~�$��=�	����m��s�F�..	j|�3&��GT\D"��=����(|�z�f�/���:�3)e>�uo�;���.�
k$s��G����xn`2�%�
��$i��1L��n�
�����X�)���W�q��}�L����s�
H()sJ9x��no��$ ��k-I�F]��>�HY;r"�&��xF�HZ6i#�g��Up8���$����7c��8����T]d���c��`:��^�U�M��X�b����Q��a,;��8�0����|d����O�R,*X�
P��53��b��a��������S<r��>�s�~�`_��l�����V�Q�N�2Q�@=*���3���t#��rP��U�/�1��� �5u+"$)/G ��=����C6��B�a	E6�!3P@g�v�w�=���
���G�
������6�T
^��J���,��B���p����8�]_lP�dY��l/��J����un_���*6g�?T�@M(0��J���������%	������/j`�?k����f`,�!�pC�C�s���|I������bc�|r��$*�$g�-�l#0H��1��:�b��>|���Z��G|��<y���(����h�4�{�p:�>�Ek<����mG�/�Jpms��{�P@3�
�_J\`���+H@sp*�=�=(��qLV�7Gt����H��������C���
E0U���k�{\���h��G!��6�a]��H�)n8E��I�W�c�z�x3��k����
��p�`���T��f]��R�������@x�$ix�;a0���rY@���v*jy=���)�8�|�@�P��M�8#?���������m��=�����L��B�l�Y��0�<�9�;a�Mt���xE�Y�QA����66$b�L�K���d���b~�O�*��:���ko�!G���8&/C��Qt�'i�=�D]�q7W�$N������n���;rgE��&����|�HD�u6�Bi���T-�����}Q����?22{~7���B�9���~�__�
��h
��A��e��!�3A��HG9����m���0���� m������lk�N��yK6����[��P$G&��Y��f��J&�AS>�r��].�������d+�s����4�������4N��
|�l���_��N��'FB��L"�z-r�O�����I�3$L���������@������F&*�]���M��rok
�6��2����E��"Q��D�r{�m��|��Z��*2������<�mA���.,W
���)��x}NL��r���j�2��j�m�����j���mOd�WkUQE.yL���|n���/[���K����s G��!9��f�W}��=�Pt-"F4�n������O��3(����cK�fb�(�UCs�!�0V�P/����H�$�_�d/�4$��>1H�l�hKU���B���}i�T�x���8&��ui%6G4����L�Sv��h�w��^+��th|��}��
����=��uL�1#M%�����������A�e��(���)N��w�������#<W�wt@�j?�z��]��x5r�-��Zo��!��l��D�4����b�>���?��8�L	p�*��`�px^2��E
�^��f�����g�bK6i�rIXB�wW�����83�����NVm�JC,��p:v�.(�����"G�j$��
�	Z�o7�����W��;w���PE�EL��agD�d�!ET�vF���5�/�A���{�,�>�f��t
}�a]��8�w(D�_!jY)O�����rC�U��qe�������j�%�g���}<z�[����V�S���*G9K9
e�8,$�����9���I��dm)�����PJiLE��M��Od����)>�!_q�FZJ��}�������a�]���w���/�4��M�H
I%������1(���Iu]k�g7r8h<�au��P�/���~��r���!����"{�����4r�4�����-�������)d��*�����Kn��O��`B
�~��A��4>rO_oPETI�Cs�$���>L!��R��dV�����N����$-���>�D��)^�'^�kJ��~?�� �Iw���O���-Bv�*��)I�PfD��w#V���"���_D���Z�k����	
����)g,���n�W��3AZ�'�Ux���qY���}��A�xqP�@K������g!�_�E��+��D���G�X�$�(O�p���*k���Zr.)��^Z�jmk�N������Q��|�������Yz����yLEh��"~��[���;�i.���D��*E��/�A5��[G23��e��o���������s�
�h���p�Q�U�$������t��O�[h�g��z����j��O"a��!��*���.b���6F%]�B
�+g�_���E�
t����(&��&SP��� ��������B���E�*�
�nMZ�����N2�r���M?�d#����fQ!V�[Rf-�)�"��Oe(=�*���gFL��0[(��=��+5���1�-���%2A�����/�l���:�0L4|��x�`?H���B����PM(n�����PD�Zn��@�G�}\�D���+%)�
��	��Qg�+�%w�����y�=�F�!������4W���1�a�r�1����
c��z��
�VS���b���t	�����2,�^1G���T��
7��/�"��Tiw�Ts�S��e'���{@��5�f���������!���p������8K��d)3�Dw����U~������u��Qx"o����<�w�`S���J�I��������WQv�m��cUQ����GLB,7��&E3�0�@=�������+:hu+G���O��6�;&U�:|�	��vSO���4���E��}���M'��+?�������C��^@0�"�!)wzd��}n�%{S����W�V���+��K���|�9�:�M�_$�d
��&���?�-���,��`���A�rBF��{��w1.	0#D�,����-T�$����X
�v����AjX�����I��s�A�~�!��51�-
P6SB�~`�������|��������[�I��b��p+�L�}�n��E����R5Q��2�M��C9i��]VA�.5~�J
?m�'s�����?
O�G��4Ln�|�kH�l��5f����p��KV\��2���E[�m��:��d�]�#��=	�#"X��n"��~~�J���8�eU��h82&���#�����9����&���K��������pmJ�uH���7�JY�H{��"�_�O�"c���fG�Ai�_�S
���i��%�d�!643�&&f��Y�[��*�~Q>�i�E�P���q�&\O��6���2������%�~GP7���P���e�����ut?	@�n��Q�p�m�E�Oco����,8���JC�L[x��*]�d������m!����{�qo�@�2z����1�e�D�J�����>��\xO�{d�3<Cv��L���F��H[l��Rj�C���D�dW2�d�XN^�P�������M����P�^��>�`#��RI�fz��v��R�oj����}����#a,���vQ�e�����)PV�w�m�	������(���
��9���
U�(�P�1oo���t��hi�|��-��ZHE8� }���Q��i�x��(�h��-f[S�o���a�3�Os��L�[��f!���-v7x��I���H�L6X-��x<�I4>����MV��r^ ��VqD*|��:����2�Kb�P#�Q�J����M�=bWBi0����������C�(�cg��q��%?�$��*K��I����VEQ���p�]��2�r���������'��x���O�V7b�cu�es���}����D�TH��|�y=8:n�z�Ft@�����;k����_`.Y5�g���A�h�=<M���Y�{`�`�U.t�B��'O�;"�������|�8q�|�C*��z�li�L)��~4vI#��o�:�OG5!����a1G��H�2�o�!�@:E��G�����B�I�S�E��Gf�U�L}� ��Gt����!�4u�������MX�MY&"���	��:��I���}������Y� g�2���#>�q
�[p&�A��-�i�����I�mD�>y2 6`D9�/�-J��O��x��\�*E����		�����%�>���'vH��l�>!�a������.D����X4m>eo�ft]�N�l����QKQ
�p�}x�b�Dc��F~������-�O����^���O��`Gq��E���(�*��Q�H��77R�-��`F��BP��q#���|����&�Bx���w��k�����M���9z$I����1�����q�PS��#��\��R�@ .�����4P���T��� ��/7�Q���4yHc����:��{�?9�g�v�K���k�wm�E���"�� ��<%��j����bz���r�V��-@C_��2Q@
82,�
���A�M�)�Y��c2pPxo���*�7H?K�{vL�p��{	�7��$�n�\6ru�20��W��#T�Zr�m5j���UC���oE��7F�%�J��W�&pj�RQ�:�A'
��f�O�3��n�7'��D����h��"`.M[{Uz�|��I�G���Ou���@4�E���U}������P�h���m���E�R�����7��D���w���%w@g	_/�c���-�;ur����`�w������Be�Ov��:��r*|M\�y*vZ���2��p�6��X���l��M���%u��3&�~�,���m~��������h���IC=R}j�'a^��t�tC��j�X8�����8�H e\�}_�%�,TB��EB��x�5%��)v�E>���
��
�#C�%����#tqx
�kt�a� �����Ot���JvFv2�S��r�>��,[������J�3@����[��������e'�����~����&fS�	u��0���k!����e
w��|�&V�]N�#q����*fm�]�����(�Q�r�B���^$���������|��Z6�c���m=��L��]���OaQG�	���[���|Z&�/51���o :bk�����"ya����p��O��_�m	��83�s��]� Np��:��:�m��_��hN�t#��y^C��q���D���|�l)*�yMJ)���%�����������o�5�k<��)���N������Y�����d'x#N(���&������>��N�%���k�A��bL�Y�_v�N=��<4@)�	E�K�<c��&���d���{{q���=c��"y�������.��6�!O�����%K�����p
^.�����Y_M�:h^I�l���q-�{�T�����a���X3���&��x�R!�s��u����#+��W�1D%@�A�1��2�#�O��~0I l���:({���o��D����A5�xQ���V��93'�I���+�<�-��w��FR#���f7oMO��)g.�F�e��Qh��L�9�f�~(���|���`�����B�`j���^nsbX��h�}������K��5n���AE!���[� /�n�N�C���W���l���:��>�Aw�����@�T���l7��8��T��H!������bc
hG��k]�����M1����Pm�������H'Z� �J�X�d�������@���%�K���s9n�.�����=%��K���X\lr�(jc2��d���r%�0�7B����*�uH�F}����.���/����8����L������b����#�HC���&������N$jJ:���B��oL`FH��Lj�<.5�8|��8����J���f9�T����K�A�6������|d�-���,���^E�'{���p����/e��������:�G��P1!IE}kYC
�.�Z���%� �$	]k��X�H,�`��6���+#����)[�Z�gHB�$�����yPS*V��N<��k|?������E��:i ,;W��fc������l!>����!|�a��X\�h�L����o\���B>����,��eR��RP�\��_r�e���H�����B�cO
�7�4-���Z�i�O�H:������{�j`\�i��S��37Hm��|��h~��\�3]�D1�� �H�tq��Fd��:�6!~p��G�uC�����+��G
C�:v�d�����;�|$*`@*��.G5��K���k��}�����
��S���Qa�O�w{@�<,[�������v1�A=�r�����1I<�J�3P$t�F*U�&*t�`��|��I5���H��?s��Uq'!�2�r�6/kze5�Q���k�%�$�p|(�Uz����]��f��+�J�-W4���{S�J$�����fs
�\d1�����uB��&�U�/$�tt�L`�z���v��E(`�#��O�la!kI�ou0��.}������%}����5������v�~J��o��I��d;�f�X~Uo6�f�������p��;��'[j�m��Fd��E�(����,Xp�9���0�R���d�E��/Ji�����Z��'R�f'��`�b�o?E�y Ch_�C��.��zP��D���'a���KS�����;�@j�E���D�
���r:&�{��`rIPiC�/���3����w��t�T#����-��Y�I��
�(�����1���I�]_C��x���eT�i6�Ea��%%Vg Y����
�[������������P��<�7����4n���1J\C.9u�H�w��.MR8?"���"�jT�k�xR�����/T3�1�|���I#�k{F����
e_Fn��6W���A�,�^����'��[��3�-P��0�~0(?����-�r[��f9

���{�W����]/%�S���*Pe����C$�Z��?(�f���A<i8m��$��6���(I����eq`#�~n%���a��cEB�rJh�*}[��x�F�h�bj���c/����/�Xg����
E$�czo9����
����L|���r�	�YU��H��������,���\�1�F��j��D����
<c�)���9�|!�.$���4���
�����or��R�4�
�1�P�)O����s�@$�����R�K��#W��1a<��������x���d��&���vL�����e�?}Q�������M6���T������jBn�'�j�����H#�hV��?p�Np[#���*#�,��m}-�]rr��*�K����X�]�Q�e�L�r0aQ@R':2z8�xT��.ls�%�
��)�]z������"���%��uA�Uf�SD� �Q��n��?��cO����k�=M��������v\��F}�G����d8;;�z.T�L�p�����PfO�/`��("Z�XKmE���u������&�IQ��<��x�
d�v �t �����V�HD��r����v���"R��QX�k�C�k;�����g����U���P�P�A�
5�wnrB��jL���'���.�H�����=Q��,����u����mK�u|Tq�y����b�1��jY��
��T������}�5��CT�Rq�
�C��i/���-sF?�G�N�9�4��@���.k�����'�����7i	����@*�
.��! ���H�K����=�&e��AT?����L0H|F`H�o9
O�GSC�� \��3�5^�:�@E�ri���
���:�Id�=�BB�v�fw���F����Q���y+5;U��������=x�����e'fcgS�K����	K�}��j	V/H����`��O�NF�F	�1������������W�!�����./�;�3ti�X��"B� �(��������@D��^�w}`fx��'B���'
S������YoK5�r�Q�m�8�f�/G-ns�&��(���s�������)S�z�HaLu�0>Gj���m%�h�2��HH��$����*�����89�������9�?q�~����������;v-j�2��_������Y�l\��s�P'��z}v����}�E����m
/�[[��D��o\�#-��o���6����.���Zl��5����D��Y����a1sqM���^���L]�rx[����zr�Zd�m�
�k���r���?,gU����;~��^�z�;/������,���M��?�U�������z�B�S�����A��������j`�3�H�%�o�A#������V)��������7��}_���-�O��[�������Z�������Q�!����_�����������r����e9���_V�[�����������_����/�/��_�����e9�7�~Y����4����/�������0��3��K���������?H+����[�n��W����P����)�Z�W�4��iyi��Ow6����~t��k���R�um��	(Nz�_>+� �kI
7$�S~6N�W!��Jc��y�?����F���&to<�\~����z��H14�J:akt�Q�*@��1Rea�;����V�G�0q��Ei�V��v�A?��%���x�S��}
Q��,kg���e?��o�E,�������Af=e��[������l�L�{{�"���D���xF�^���m�:����[/_}L�]�<G���m��u-
�����Y��g�y���Q(^�V�1�j�K?�W����/�x�,�Fa�IM�<N�H�����cc2F�"T�O!�}�2�k[V�_Zx����1"@�7���f`����*�2$�r���PlH��qy!!)�a��)�(:�r�
�R���b�*���[
�h�#)qy�L��F:�(���o���`K`
h;�9���A����*��T�B�Y�� �D/�}�i�X�V3�>��q2��N�v3#S[����|������0����p�����|��A�
�]o���M�1V�6)v2�G?��G�����6/^������h!�A!��-l�
�$tGg���E�H6@HU>dL���Y��U�?�07i���#��~_E����B�g��`�������d�������K�S�4���"5*nY�-&� ���7���<��TA3��/��R����8��:��xN�d��9��^���"��L\kR������!���p��G�C
���`���&r��s�`�=�@T1n�9U�PT�?!��>�������,�~P�'p��i��6��,daF7$Am�����%�`�tD_�,���uB'�>���?l2(���|���O��$4�N>d`����O���_w�;������O��g�N{��+	 Jz������y>z�b�n�QO��_�~dL��C��e�`��m����,����a<j�ER<�[2^&���3����	k�?��1_.���+(d�H�.��1bSN�&F�(����S���d�W�TQ�N����+��J}��c-i�%�j��L�7JD��N�I�gPd�%�Q����&�R$�Cl���l"�k/���92h��t��l�zJ�qY��"��v!�b�^��"��
(c\���K�UkJ��Sv��r���gx�U0��~��pMx�80
���};p�������k
]��cd�����
�{[�����,�"�kSe[�=,�(M:��8������!N����aot��C\ q�O���m�T���eK>{K�,�LzH���G������l�F�*L���c.%�S;1����0�T�{o�(���qr�	�@=�4�x���n����5�����8�]�.�q�
��TG����,b/t%\�QK,����4N�5�<L�Gp�>jEf\�~:`����&q��q)���q"s���7���r�S����{��`U���5,���h�����E�l@�t0"88����Fn����\�|�!,�T;
������A���AB��l����O"+��C�q�B H�EH��2A�b+
��/��Z���[��>��|d4��'
��<��[�U��[��8E��z9��^�2_����2�K�\��}PPQ��Q�x���I�/����D�p7#���M���[YT��c!�����[r�{Eb
B8sD}���nw�'�%(����s��Kn!����N���]�7=q$@u�E��I#Q�:*�4���v���DN��\�g^�}
}%�gU���,�}m1'�
��O��/�ElN�7S��FDg3�����S���[N����5:7�K��=�s���~]_��T0��������v$-�I=�e�������J}����Y��I����
n 6����A���s��������P�t-�����p��#oNW$�}��?��'$�����7�w�2��OJ��tB�yX_je�����8��Qr:9���\.�a���R���N��m�-����#�0�����R��(�,:�{�"V>��|ro������+z������*��K���=-t7T�����gt�i����o!����?������B!��fq�R����@�b���}��}`��w�wd�w+�!(��8���f�]�j���$�P�6a@~��
��:� ��Ty�_���	V�R_Q��b��{uY�T���j�QL�a�_�E��6B���oa>m���f������x?�t q3�;6J���#���"�G�I.�g�1��-G��^�}w�SG!�e9���A t4���$���V��<�sF��9�e�Ku�
Tg�%lp�9cDd�S��x��Om�=��%hE �0UE��/uQ@�)A�
��t���@���<���C�I	PUn��Wg�=�Nc���4�R(c�*�N�P��vw�;.�L/��F���Q�[����+n����Vl��T�(��?%5�v
M��`��
=k���#��h���C�c��N����3�$1y��<�oEY����!�5(�e�f$t��y<@�u��i'T��hD���zI�X���O;)�@�v�vr�����]���S�9)���e���xF�����<���T>�f(wI;������)G	���z�����;N�������o�m��(�h����ofIgc�
����,0~6vj���k�<���T|�8!C5N�]h�Y`�*���m�BR)�^4�[����^�8u"��z$B(�/i���f=2e���:.�	��C4����I���c���z��a~�V�j���(��$)
���L�w���lG�}^��4��B�D�P��~W�e���.wJ��.���rf�r0�8�l�	V?���J�bBZ$����/T�,�&���R�q�eBI�yi$��)��C�G�h�)��jNB�m(<�@*nH�T�(���1|h������P%Wp{IR��-��2�,�;{�v\"^!���Ob�����	�D��j@����"��<:�5��^0/������z
Rc�#F?1��v�R���	v�;��}�K,���r���Q����h��O/��\*�L�O���wy?J��|2�l�<*��!v�v7?��"w��N�1���/�!��N
G(f!goue�;2GLhg�#�z��>������4�>M0�P�������������PX�l\>�)��!�S�b�U���������"$�4N6 ?%Z2-�!o=����	�H:�*� i�������`����������K����h������=��I�m�{�1��ReZ���GD�;d���B��m���F�W�������{gr�H��e�����j$b����7�N�Ol��u)�<�LC:i���L�/�ud�.�w�����OO��Y"��b�����H`�,��JS�2�D{b��N��=��}�q���x�,e���. 8I����>��<�!O�j�"Sk�'�m��H���FW�c�.�	�prV����c�[��ABc��EEd�����F�{j,���|����-
�#��`P��������DW�WGCN���l��;�q��j�q`�%�"
�����D���4�������:s�o5	����L�C�aP������QAS����|�@��FE�b�F���*&?h�(@���O��!��%������4�"�&�M�j��27��2TO����!�G
��I�����ou0l���D�1+�%x)m���;�,s����IK��;}��_`����q'����0����&�C���f�6��Lf����JD�(�0�����[l��;�V��A-1j�u�)@�L�J2��1q;��c����d�(j�K/�p�J"�����D���nRS��{0���)����l,;Zzd-�7
�,��l��/C��tI�
?]�GQ��q.io�����+lD���J��g�����I���jl��l��B���C�/l^�����Ak{h�u4OQwcJ$@��VF*�Q���YVR����F��9�
���#A1.�m�=��R,I:b� �g������KMS��L�&c&������1���aK��y�[�SH�'E6��V~��������5j�:�CF?������fJB������z���I)qg�����K��'����(�����RB��5�.�1U����.�tl�f+��Q\�1lZgU������c��&��7��O=��
�i*�"|`Z�k�������q�4�5�����
V��1�����6��r[�.����B�mu��LH�^EU�hJ����x
������*���>����4��Q}4�����)�u|b�r��qZA���
�����*���$mTYvI��R�l��R����������"_��@*Z	o'��mm��
@��nL�[6Q�^Ih���ZO��*7M�er�q������|q����:��
�|�F���D���C9(�u��:�4���(�`�|����3����w�|�����b2�k2	�=�$����D�!�[�=�e;�p���X!��.�����)��O }?�Z�h��JRU��U)���`�>�� �����*��f�=�*��h��z6*a�Au�J���R�����m;QY���tn6c������5��kI]�	����� �IS���o����.25G\�IK5�7v�#]H�u
��e�����*������x��ND����Y�M/�
�,W����J�sm��wq�C.�:�6�����*.����q�qM�m�Bo���\b��	�lJ�!]aTx�/���|���tA�['7��o^�2�W�Zn��	[,I���6�DPa������f�����4",�lw��/E���Pg��������+�������GN���|h�X�����4(E?I�N{Iw�n�!�9��*�!�7��K��#F++G�v�rz�z6���R�����P�e=Y	����i-���g�[<g�����_B��h�-E��R��9G���[z�}c\9M� ?�QH�.��18-5�.xv���JD�.?_�h�*[��x���+A��+q��-�f=��Qoa�JAy���lRF��.Q��1���S����>nSS�$�PD�Q�V>n��W$�8�?	v���
���(8:d�6�B>.5%o��8c�E�0��3���9���J��^v$zL��)�TRZ.]�@b�qJ���b]O
���vF�}OE�iIY�1����������	�cjz��JH�&�j������Z����io�����6Jw�M�x��p���$��y|���o�|�7���Y ����w&�+-�#o
�;c�w9?�R:5Q<=	L��	A)7�y�����E�}�Fd���rH�������tK��D��o')c�y���:M����d1����������-	h�g+�ct:�;���������~S�f`�g�]i�"7�$%������������@��=�\�e�OL&}�x'4cd��7�u�T/�d������Oc�1<$�]��'�z��G=e{�6���h*s�T���Z�N�^��c�;?�����6&�4j�'�~QZ��|�����fF��/mA��KB�u7�������4iCa��5������J4�	f�����<|���������X�'�����`�d>	@����WQ���,h���ib����S!x_��/�b	9P�n!���b�E�\���A�BW93���G����z�t����)^��.���^����A�7����K��z�)�{i`e�uqb���Z���t=�H�2gN�_����~�T�������m.6�aKb���9�V���{�W�������&�I/M��RE(B��<�����o����@���[mI��1?&�����43{a��{��� �v�����cs�

��IH��w8��A�=~P\�E��F�k�zT���j���T��7��)>%Ds���
hN�QC�f`����R���5k;����B�6�4�����M��)��=�IH�<#EC~���1���A(��.j�8;�h����@
������#YM�<�%K��+�U��%��Wg����"����.D���>�<K���IO��h�/A�q�lH�_��J�Q���3��a�C��������:w9j�)
Z� �|wS���R���7�O/^����IU%�����������5p���r��UP�Ba�Jd�>``�6)�YB���o�$�PyC��A�P��	�w���Y4�I(@<��`?�p5�������z���X���m&
Q�3(i������N�]���S� ��|� G{��>��Lh�*�(\�E�sg��j�q2��W=)�G�C���o�������C�	n\#�:��������M�Gl00���g�I�%��~��*�e{�"�G���W�X��c
�t���A�>�����4���hA���^D���������w�U%"�B5���nKy����x5���Q��|�t.�T3W�����EG���@]e�!vJR�z}����>����j��+3
���sV$5.�H��Q��#�CJ��v�����5��\�.�$a�9�4"y\O���v@��!4~0M�l�B0V��������������+��bR	���gw�����I7��H`��]FR���%���r��dO`�!��s�P>��R1����0N��^0h��)�y
��h��&bL�!0���%vU��Ax�1!r92 ����E���K��3�������}8Ee�|�PU���x4��R���v�����-��xY��/G-��Y�Z��q�]50>J�r���dP:B1>�;��np,��zu]�_ E��JW;
tP;e_��^������V�a����e��^b `9s�+����G�3�Q���V36��Md6[��� +n*���������.;������� $rg1nI.&��K}�LtB��[ZSAZ���o�o�,�x��t�,D�V�I��
'���*���w^B�LRM{���K9:�\�j�Oc�����R$�����7�Q��\b����������@a��5��)�8TKa%4O2Ax����Q�8D�*^n�^|�=�V�&����E��u;H�2�1"#C7S��X�E^"r�8��29�~����=��qL���[�KO)�<I����$�2�R��i�5i.J�������;66;�*�6�b^��AH���)T��"�]��HZ�A���
�`�?R��)��Ek��&��]t��X�@�����*s$���!Q��������ohKa��~�}�M�;X	����^J��!�9m����)��|�$&.r��}��T	��1���K�?�c1��,/'@5�q���1pZ.Qs���C�6���f���_�^��bT�	��e����W[��'E�Qz���:��#��������^�^]����&�47�q��7RT��[��b�J]�`��-��jIju�T�����E~�Hi���y:��{������������c��Q(������P�6�Q'���K���m4�y%Qf{�@j��j��$���������f��L�b/�r��TR,�������J��Ht���O1�����@ldqpD����\/~��v*�S��]�����+�H�21�C����d,�C_�R��Mfvl89�j�����|���"Y	��`2hbI_�-�{���v��@5#�K_Pn���=�ud=X)'O�@��m�^���@�0�f?Y�������L��@kc9�=������p���8���X@h��Z�B�q��Z���(I�\W�i�0�dy��w�@)�0s����tIp��
g����k��&�	�4x�)������e:��ZJg:?g����p�����?�d������+K#J�J�EsK�u,2�~T��`��Z�2N��,z9m�������O��k�[��#�V��"
���Jl����]M�[���m'��/X����g�MjF��+ ��s~��\���9B\"������pi�`�
KQ�c &�/@�8�S���Y�P4��Wg��DZ<����������������+G����<�U�qHy^���N9��?K������
�@�<�
���rE1R*2����m���E5S�V���vPa��������=����y����,]��������Jb�
���������+;����yFJ9Ac`���AvD�H?0��F������I
�X��1�7��A���dC�-���9�l����\c6>��v�9�x����S�����_y5A��������`��?������������_���"H�=���#9{D1������O��O��^��U������Z?�s��!v��`������������-�����V�D���/��b"�9���;�!�o�y�X��X���!���rg���������D>�Z	�?�C��)���w^�����$;�@��!��~I�������>��?�C\�D�Q!�E�������
�����Sv�Q�>�~�l��]+������������L_���+�����17��:\�������������1���z���[#�����eE0G|Y�?tG|]�{��}�����f���������"�eE��#�uE_M_W��K�����M�k���'�eE0J|Y��)1��<x�l����+��$��,��\��wK��H�'��"=�]b������C�����2w����}�ju��v����[?)�/���3�\	@#��pw��H��5T�l�
�����1_�1����E���, �[D���@�<�`��7�+�d
����������u��E�@���NQ��`������
���G~�����uy��7����rq����@O���O�+�y��=cQ���5� ��T��,"�E�Xm
(�����`<�XC>c��Sm��A�LeL\NW$���{���@������������]4+6��q>�*hv���KI,n,tD�-?[t�ObF��mH�^��>}b���1�:��q���7�������@M������aQ�|��;�&���3P26��$
8���B}�����:�t���F�U>��{�H��*�x������<<n~���X4��8�;�u�M��}6�����_Hg|r_��tQ*.b@d�p�w}��1������P��Z����U+���e�?[�8���%
$Vf���!��*���[��J5�t��Y��@_���@?�d/��Cb
��s�-�Hf��"V�j^�6�Gs��(�+��J���Bf`??��o/!�����H�@:��-�-M�
N����u_E��q&��Rp��["m9"
�k&�?�H���0YGm���f��ob�y�C	H�O��{�B���`
����������\`�< ^a���R���O*��s1�a���~��r�R�#*1�L����E���])�V�I*��`���<�>`M�B�;��x����D	|�876JdY�U� M>)�7;L;�8�U;,��ub��V]�~��A�/"g��Q���O�
������Z���.o��s�C%]��m������D>l��s)8�R������2����M���c�_�=S "��|����?��'�%!���cy�R��Ia~?�R7�f
����;����A!"���
x��U�E��y'g��09�?�{u��qL�&��YA=;�Q�i9���;e�a�'	��.��H����>E����?���=-�@0�:Y������A��6�����eKJ��D�8��^�W�Q��9�> @V����x�q�N`�
1k�_-��-G��l�����"V�]~�Z�������LfI5v��?|M�'����1�j��`o������62���#B��\�S�`9J��"�J{nTPuc
��	�>���oK~����$S��~�������*v�;?Q�J�l��6N��GH!��������xL,L)�*���B�t9���:�����������w�$�'Y���A�6���?A&��D���!G���f�s�u��V�^������x��&�J����_�_e�������(�.'i��]�iEIo@��#�,��	@�*.���1�~�0��@���.�iUa�U� ���"n]�U��R��7�w���c�YB���6
1qv��)V���GA-���<(������e
w�����Xf�x���z���(�b;n����m�<2C$P���B�1��%K��{��9��<a���Z�Jzi!�g_>*H�a��S�{�q���k��~��(Ea`�ic�r�C�k\i��F���c�*��|��n��[i��������&����OC%F�'��<�2�^A��!�'��gfU���9�m�o��������)��@	����b$��m�hF�h�����G������*���������O"9%�V7���}N�d
��lOO
���.Y/"8[KK4*N�$r������x\2&7E�l�9���HqQ.��.-M�{�Yp��b��Y8i.�E��T���qR�I$�`/��~�M
I<�9~i~���&�)���P�h�iP@�/z��t�M���_aJ��`$�6���@{qe����D�����J���v^�4��x6F�����k�v�����z�?�x���
�NV=k��(=�k,1D�1�2B���55��q!�Rz������@�����8H�5$.
K�?�]����(�Z�Q���UC����G"M��K �P�|E��K�����x�Q=Fxr����zb���O�K���~����!U�M�U���PU<����Y+�)��W�Y�IY����R��KGK���P�AB]F�^|v�z��}�+������Yi�8��o7'Z
� �"(���3S�]�8�S�N~C�Af~\�,z�����:���V���D��]_=��5��WR�ND���� ���	U�"3�+M�n����B$��
=6��
X?O�7_o
i'��1}D���K��9)��,��v*�8��{(C�!^���	6���G���#u�H5~��.Q<�z�N!���,�m������8u��j�����[�c��a���W���
99<��8�~W�D�h�$yP&���^sD����	��w��G�����\�j�g���4��K�4�t��u���������h��_��D�<u�W�G�z�3:A����;,�~vv�^M�����������B`5�9�
;�8��l�60�_�`�]��|����|��EVKi��n0��>��H,$d��+����xG�4��mI�3A��~����r#���l�+������`����Iu��x��I���2�Ov}��$]�]��!����0����Qf#w|=�5��C�&������/c�u8���;���X�1���"��	|���!���������md�_��~�%
��y�
�����a����Yo(*���c���Mg��%�������$k�[_<B�6�_p���-��Y�q�����@��K�G����=M����{�lm"��_[L$���*pm�3�e�vB�ka*�h6Y�H�i4���{*'hL�1�@��*��>P����T�u,D�����a�G-�,���N\�@^����@Yk�	��.wFf��|p8q��h/Y��8h���K����08�K��{���:0����s)�4mj�~>|���|@u�a�O�����>"�8O_�E��\�0%v�cx�v��������K.�)n<���73�M	��\��H�O��D���N��}i��J,��2Z�JJ.h�a�H�XBB�`����m�!��)Ga�Q4�Th�����G"���s`���6���|Ny0g��"��l�@�A,8kjl��+�=�b�f�G�x��d�X���a%��)�_N0��AS;�CQ�^�C�B��2������wY;8f�������x;C���NdR��r�+���W?����g��KZt������".G�AK; �>]"_w����y����1M>i�B
S���=�?�I_�e�����y+����@�A2�ym���h��^�.�c�4����8�`���R2�=iG\R�H�������)��j���_N�9�+*�w���4"�s<����axF����j���a��`TWH�m��w@�qc����8�8��P�+�����7v�^[(��H���
�mS�
�a�e�v�dq�L>�!�~i:�B��|X�H�}0�Y��	%����vN�S�&���Q_/�oH{�V��646O?���8��������@I>�L���&9�=��b�����
��c���||
y�}�`�c��������gw��Jy��"n�Rfm�v;����T�/*�g���1��	X��A&Q2�n���������@��e�������(�&��9T.!�~,��=R��g�p��D.:��J���X�CT\��'!��,�46�8NC�7�
����3+�����`����������y�F�$��eZ�x���g�`"�����.�������6�oYJ�(��5�l������t���r��4B3�S��;WAG���L6��7�"U�q����v!���m��?��?3J��u��d�����F��H3��|�m��E3�eA��8o��l��Y�2����!�,;�L�n�l��	|�/���K�b����22p��M�,�r��A��}+]O���o�e���I+0T����%ZdC������D�y�k��E�8�	eVXf���(�]��N)i�B[�!?�[��j<������_4���s`��e�\ �W4kC� ��")������|��>U��J�80d�6m����I���`#[���!�����g��b=��1?(��=�)��)Xh�
x��LO�
[��[����d����]F��>��1�a��������*V��*�/��B��6�d Tb��r�nk: ��:07\�(�/�c�eN+��D.����@���yd�"O�7�2j��7������v�>���I��0ot�K��;�_S}���/m��p@B��2��oK��z�������V1�zn��.p���j^����
M���fN���U��F:���S"�����h^vJ�\&f6��j�kF��������}�*/ �)�/������h���	�Gr#��m{�U�9v�T� U�|]��K�t#��F�6�Cm-�.�A�b��,vi
;�vgfRA�������oA^c8�S�5w����)
�@�!�LT���H�5l��FZ�>���Gg1Z�W�a����,�+��"�VB�(t�I1��3�t����q�S���U�mo���J�`�c�V�W��v�v������FI����t�����s��[�g{ �q6��?!�xI���^��#`����xW";�D���#%$�1^�f�����Q9��8eF8/�;�d�&�.X.	����/a��%��&'U���-9�����A�b�����Ty������<�b
���P��#H?W��P%9�.G���{���y/�!x��G���$h������^Rp�am���]�P�
=�@��vpkq�#�����w�n`��=OzL��p����]�?���������R�D#�Bat�S��6E
[����`����8�N5f28���3"�N��C_I�QF�#�,��l�=K?�Rn��!����s	4����q�ID���{����t�m�9�U(�������)@f�c�������y�E'Fs���*�$L5,�����T�YB�F������`DKE�~p�(�s���#��s��H�a2iZ���]F���"aW����6��bZX}^��=Z�?>�@@�t�>gF�W�"	A�a:Y����=��C�MUS!�����Ol����������"��kl8v����'C�x�K�4U�06_�m��g� 1������y��i �I�$.���kiG�
�g�)�o���$m�K���eYcW����G�<��z�F��P��R�����7�Y���M�Pg|Z��U%�'��(� @E�u��=�~�|�a�����Kh��a��u�!��������+�}.����b�~Yw�p(��l���D$�������V,8:RK�����+� �M����Hg��M���}�{��vP�}6�0�7�O%����������B��C�i{�1��j}j+�q#=�������%�(QH9|������9l��vJ��O.��R`|��tp�S���.���������"�T��\�O	�����u$�t?�ZA��{`)pO�I9O�%/t�k����#u	F��r8{����j�k�n��K��n�J4��Pk��7�E�[�V	���,�>R�Hl�B��:Hx������1���w�c���oA�����}S��� 2
"��-�y!<����db:���8�����U]|�B��Ja�����k�����V����8�
b�����1��Z�[d�Kt�#3�������x���QK����o�>2��:1�#DW{�7&�t( ��]�������
�Q1�r�/=�/����Y�V9�`�������8xE���]��8b+iyU�=QR����A��q<����T�	7�`��$�O"�=5�������/^�s����3<����/��j���O�[s���Z4�����|���.2�]l�w�[$"u
�����_4�l
�bL�F7�&_B�o����z�J�"���F���J[jS��F�>lQvd��T����
���+D�wU�
q\��uz�$>��M})���3�<���yT,Q9N_�������!;�3A/�Y\����#A'���������u�:$��\�������=�L����
�$�Z��KsK���)?��d�����^�U
p�[����%�����dU��T�3�.d���*�c�R�	dKt�M(;�zt#@�S%{����~�� ���<���8�h"�h�fN��~�=��Q��ic��1���!�I�
���1�����a��&�Y���EI��Y�{�+G�����V�(�`b�A�5�L��t!��N��9����~	��.Jx���@��/y���	��(��P����$�6����.;�^l����'
�`�-Y �1C���������{i�
�@G�����W���h���u*:#�<�y���N�&(������;R�4g�-&�O##�!�G^_5���T��+����!d^��@Z&K~iJ`������P$���T�y�tD@q�����������^�S:�	��� A�}�U������DXn��S�D`/�;@C@qH
��G���w��������zh����i����
��	*�f[��X��[e�"�.4e�99]�CJC|�.�����yC8���"�HM��\�����K��(�.(�"�p	�N��L���R]��` �O�>������V���S���E1Q>�C�1U��C�E��z����+5���W��fq_����w9b~b)=�,g�uX����SM2<7Q}�mO_#U����pY�Tq�u����!"�-�a��k-����tFT����u����o��2b7��~Z�W�c���9c=�~����]�#�<9�����]��K�I1�$����Z��*��^�Y����%E���]0@[��[� 81����m�c`���q�������&���v���}�����B��X\���/?�v�����Qw*��'��7_�*����I����� ��
p4H?��Hc����
�Q���
��t����xU������o�@2f������z���s?�#m"�t��I"
�������
�S���)H�i�C$�G�yu��D�9��FWd�l|�����&��$�4������K,�@��C(���%
+N��g�4��(,�n��Y?���n�c����X$��I�k4����,������Bp�i�F
Ppn�D@K�=Z�I�i�������)!����j\(S!��.d�7��.��Ec��<
�9!$��9@��BtqK.4�m=��Bz�:R���D�	�%�/5���������1��4M-
��������6W�1a��=���L������/�$)����,l��@�|�����:�����/�g��"I�,�����(��'�}���U��d����nEP�#�{�Q��(t�q�U��<!(&)�bZ���������j^�3�S��d��@�b�k{���3�s������4R��|o"~h4��	��?~��uD�:���,��)M*��f���q��p�<�kQ���pER�+7��Kt�h�(9�����Q�M�?��n��2��|��l�4��1����|����Z`�W��h E�m?�q>r�����%�E?
����bofy���t��rQ� �m�<X���:����,�m6IPa_��pcG�+�T����f$qk"y4���v�t���U>���,m��lRyez�G������&
�'�����o�I��i��#�����
��L�&��~�}�����MA��4�&���BX���{���f���wk3k������v�z�;o�f��K27k0��+-�?��E2������$��� ���������������G}��1&����C^����f���g�Bu�z��c�[�'����4���Y�9b�DO��*^���el���D��WWr�3��,|_��?�v%Qw�%�������R�
P���p0_�����f3���JNfu1�����%����|��o���<+�_~K���f��R�������_���b�\���j��!\I$*����������\#	���{��?
�!��v�����g:���������R�Qw���wC��?��,�n�
�����BS9�����~�.�C�I���/l7�1��x"G]�i���S_V���R9�,��O�� �H���^��q��!��2F������u_������gH�y�����BfBj�����/���l��'���o8�}Y�����u!�����D�'o��}C�_Y	Q�:/����/d�:��o�~��>d_�_T����,���a!+��qi�����8!�G�~�F���50�x��H���cR���=m����}�1��n�9�������?�f���o	$"hA�	�W�N�4��9�9������.�"���R������vR��{`e ��������0 2��/��d�_W�}�=��f4`ZB�p?J�`����k_u����~;_E�q`��R��v�D��.�P�R��d&6���5�?=*�)��6�f�$}������i�����u��9=}]K���B��NQw!�����O/B;m�9���N�vV?m�_����7�U���!u������i	_���	�
P�{>�x�������9��W�T=�</������v�pX\����5?~���|Y��"	�!�NgB4�j���%@�6f��H��E�O8^AT�M����]V�+���sd�$���{�R��V1�4P/K�"�-C2���?�*&��{�W�b�;]�#�lB����]S�H���LD�b��v1\#MA�Qj2�jV�����_a����u_�����&�$�Y������t�4��W~p�J3�PF�{�O��R��gPJE8N\�����|��t�V�|$���%�����L���}���#���iK�t~�k_�[j�����G(�����#6�&U��I%�3��-��!��$[H(����88�*!�
���������4qC�CN[8��
j
�o{��^6�q���3�����	����xpS�%d���Y[���R���wT���e��Kr�##A4��~���w����.#W�bVkB�+%LP�D__#!%����0=��XS�������/�a�cF����n�����)�"����X��zC�q����q��A����q37�b�~��6���?�:��+��59��i>&�Ip���L?�Fq�;

t!�����`�v�����D%X�a|o&n��*@%3\Q�%vy ���M�{+��Z>��o� ��7�v?��yz�/`� ��8�#�u�6R�~
?���wX�����V�d��� ��2�M�lKq�������Sx�a���]0��@J�q��V�O���|G�~ ���y��%��~����t��2"&������-h+l�DA���>e��C�J+r:������i;���|J�_���dT{e,������?UU��1|O�E��`��~y����
J���6�P��s�mR'�Ce�����`���M���L������z���15+������I�x��Z��L��]Y�Ff���O%���d����"	8�E�/
�:n��#ezH��Tp������CK���g�&<����vI��p���=�M���_oU1����p�_��@@,Z�~"�d��PS�	�����4��{OI#gX�Oi�#�+���&?��(��zZmv\�;%�YH����"X���W
��� l���b�ET���F�Vu~��a����d�$l���EGH�����cWu�PHP����[�����H�`x��n������t��N�������DQ� �����h�O�����rd��$jw{��fKP�
�W,�_Ev�����P��
8J*p;im���E7h�`#�����)�����n����vm��|&��q'[����)��-rc��~�E������w{�UI�������h�E2��c��"����s%M�V��cf6:��<�m�����������<
{�d�
\���w��d�����G��H���h~&n��v��#����u�3J��|�~��9b��*�1nO��O�oG<J�����yIV��E��cB+v$���Z��� +��������L�t]D-�"�SH����n@����O9m������P�����2r_��/�^� y�^�LW�����n�'�C�-a<2��zWy�3���&P�$U�d6����`�� ,��Pq�*bF^��5@`Gj��T��^���2����h�����x���*�u�j�Lbl��~�=w1���`s\��at�b����!��8G{�����Z��u�E,��{�u)�5����r(��	���C�}�QW��
����Q����|���*������~�d+�;5���������AY7�#�J�9
�w��
��|���p����)������+����y��j+����m��GD��O��6&��n��)"D���|�=�U�\�S�.A��I���s�s:B���QbA���vd�����m���f����O�������m&��^ZU�y����5N�D<}���E���|��x�����H������������fD���T+,A���]S���Dl����H�z���F�wF([J�x4��9C��i�DJ����������NqaoT��*�-������3)�P��
��;h8�v|���~�4����56!��l��`q����:�o���~j��E	Q���GA)����D	 �6;��t��Gt��a��Gz�i���Q�Ma�}�����$��8���Q><X�s��`R����x�$� i��� W�m�F����q����b�w�F}�}�zk�g�7�P��	�5�v�"l��/�w1r�����ueH���cvk6���s���]?�U���/c^
:��h9�o3.��n�h*Z���G��R�����>���b�~��I@�1���	C��i�~=qY[��Rb��l����u4���EDC>��
�+$*6n��4����\>��HF@S�_��\�����>9�,Xt�);#�w����������/_'�wYa���l
��}y~qm�|��\���LR����s���'�H�6���d�Pm�� @�xw_��w�f7����P8:��(�#��_�=%
�5���Tq�I�1N�z9��m���T"lPl����.��4k\��}Sy�7�Z0�����W'�	�9t���Q,@�������m{�\�#����=v[)!��'DQ��8����Dd��41�RG�\���:���kR1�S��vzc�XO���>����h)�r�������
��v����rRPc�8]�7�%��"�^��|�e��R�U
��@���I$��E��p��^��K.�����:�h��������Y-�1�O�����3b�8�P��<��~i0F���Yw�����{�ub����W�1K=�x,�	@�XjPT����#?�q���]|�}��a�W����&���Y�t������@m~��b�,V9������8���4\��w��WKWF^�y�:���#�>K��c�p���������$�s��`������r0��K�g��R�V�*1n	?��]�C�)�X�/��l��IRC�d�3BY��6>hzC�or�u��"G��]X���A!���� �����JJ\M.|�KDx��������,��������d�N-b��?������zi\�M0�w�����^�d�O��h	�>��Y�t3��'k�($.�3T�&�[��tD����ii�Y�:-qaMF�MOP�@b`(�� ��R����u�f9�PK��KpC����S�;z��9�-!�w�VM���.m���!�M�y���>�-� ��m����m�rrg�{�I��0���9�4�d)�W��D.��C�+Nqy�y.�a��"�����x����g�o���:;SY��	���f��0*�d�#����~�G,��iIgQ��s����}`8ac��/���Mf*���^{��^�v�����C6���=�@6��:n|�q;����e6	�7T(��Z�����BkJ��aa�z|���P�p�"0����
��vv?�'�2����B�!J�vd;6������Hl�������g��b���������B2���|�I?rnQ�����v0hBm����]���B�)[����2=�C���E���4�r�E����'��A82;��>c�2�����e�BB'k|F'N}5Dk�-�(J>k����k�S��iXL�S�n���� ����(q#���1��?�o����� aF�g���j���� ��f���O�*�]�z��!��<������O�yO=	��dw���f�F��i��P?�%���S���
��VTf�%?z���tWi�����E�-��H�+�=�5V����+<����#�G^�N���s�b
.~H|�0T�qL�����m��H�8�F������13�Z�L`��������L��!��I
�����5�@P�"��q�D�S9��	q0Q�/�{|�s>p�l�CU��I�v'�[��"��2��@>e��E�.��x�2�C����"^�A3���l���l!o�$��|#l+,-����-Tf.}�=��B`�;���� �7�����.Y��i������|��a�����P����*P;�3)����q^��Rm�04n����v����0��XL���86E�h
���FR_�vXD��O@���i�"���K����2�&��o�2��x��?��:
�*�<2{D���d$��Q�\!`-I|���0��g�����EI7����[e�0>��c�9��}����$y_t_Z����Y�h<�!����p���x��E:G�*�=����V0)	������\~��Sq��_i�z~���
]�	am�-Z�t��{��_��O.2>�v�������V��E~N��w�B�dV]��o�P�b,R����{����B(|�R=��K�(*�>~��|YI0��_��"Du!;mp�O�Yp�<d�I�K8�n���T���)V�O%�����@��E!@.'l��9P8�d��q�2����������
��P��J������f<���(���|mDI�$0���h�q�=b���@�8���T��z�2G������~z������3�T�H)U7�NJnF�Jg�1�L�:�}��,�"�l7���E�8p7@]�8�����._�J_4N��Of�-z��h,Zin�����b�c���!0��D9a/���b^c�L��I��zx/�L�I���'���>��.��I�������5#V��V���mS(�t��@�[�����(�Vh��>6��0K*�w
��K3�G���LC,��W�����8����Aa
�"R�|$woEt��#KJ���fvDg��u��@.���FL���[�\��������{����$���)��L�\���#�<�I7.�6naG�17_��lp���\���\����Se��Z1��i���\�A�<����h��CxA�D�S�q�d�HZ
4���2P����J	��y���F����sQ%#�-����i���Cj���I���2D��,����'n�yo^`i�t��c83_A�D����b[6���O��n�b���#���r|Q�a��n\(:���9�Mx{~FJ�4=��Q�GB�=
-P������c�p��I�I�*�g��/�@@��O����Iw����M�c!�9.*;H{3��A[������aB0�G"U�),�W�C,�{1-�����v�8�QJ,���Z<��S��#<�����N�)�Yhkl�Tdm����^���R'�[���8&0I��[�0�s�,��e#�i5�H��6|��mwf�`�>���X*�d!�Ef�i�,�^=%�ok{$�xQ]���xZAM�'��s�+��#���f(�d=	��~���w����0�
�=�LM����t�s�t
]K�����
J�)��EA-��>�T��K��dE��8���}`P��BY.��Od��.}S=et_$�K���sU��C��}KG^|�����HX�����'L�&-����wBU"��l r�����F��������G=�f�XE����Q5��%�.r����{��&�&�zg�.I�|A������������9&q8�QQB��y��B�I�Y�]lB��j� �����,P<V�xy����^x�h7���i�4��O��"�����U�G~bO���9�����t������R��D�O�X�j���DZ{0�����r����`�'K��D8yX�V��('Cm6�%������AnqJ"���F"0����>�`}�Z	#A��'����e��������/F����m���%+�R=	L���6��8�k�<a�B�;��&H�
L�Ly*�����$^#?�?�sr�����U�c�jO@/���������8��fn��
p�q�4Q��*���uEV��g�S������|&�
�}"�"��)8��3/����$���������M���$�Q8q	�����R�z|1�������DAD�c�J������5g�B�W�-�;����FR	����j4J��zb>;����Uf��HP�|�����������4�-`eaR�������JYnC���� ���������|ML:�,�_�F��v��~@<X���@a���S��� ������ ��%�cKn����mEz�0�/��t8z����J�g*F��&������i���)���Dv����*��;�-��(�M �^�D	pF<|�LD�!B����60����*��C��*`JM?+�=���.�D4���#��r���<X=��h�D�;�.�(w���`�r%��x��go�]g|[/�
���/���0
_����e��.��s��-��Z�(��N�{H����'6��gx�:�-FU����k��e���yB�nT]G��|8�L��K�����{f������Qc�^G���_:�����&��
�(@S$I�[6��~�}0��j���/lf �]C�l���Ff�i[�DW����!��f�(�\E��NY����j��9YG���nm��&��*A��������L��e9��(E���9���A���d��?e`��K
8�%q�]������8���|i��G��Xm����z���-2E�3S�p�V	e
�a[S�K�IqPPb�U�%��������p�f�F�72b<4�WHj�{�YMk_:�]��z0���r$����=�c����?pP�3�ciQb��|����<0`�J��%����,���/�)�;��
���u����3��Y���Y�8�)E��0�+/%����e�I*Yv�B��9�HmH���FF��S*?�����5D9�'�#�������S� s��=����P}������1�m?Q]�!o��8{q#��q.V*�[��R%��*���f�O� ~%t�b`z����E��=���@�Ss�,�9�U����E�()���z�Y���,�DXy����+bn�v�4��8�/��~n*� :Mk��W�5���dK��-a�]�Q���'��6�b
����������|-�!����X����e���H�`�jq�u	oH�����\Z�����_�"D(\��Z�[w�����,����!�����?t�2�
`V�
_\�n��=��7�����
������v<^sp��3�fz�=��G��@kn0���<�zZ����.y�,��dG��yGX=/`E��>*��M��?f��������P�YJ/��
�{�Qq��e{�G\����	G,��+a��/��q�w�.>D����
Q�o4���G[)
`
^Ib����I��!'{b	��#��.#�@\.{	ED�;�X��� ` �eoR81�>#
I�HyG���uJ#��x����q�������!�
:T�B6��=��8���8��������;-�����g��}#�2��W��+��!b����[�{
�#F��`������P��D�!�P@Je�r9���|���-�Z������[��Z3��7!���m��Z�����o����[�b�vD����0�js�X*Z�(�y�)d��'!vvN��*k��3N�^�.j���K>�\H�y�N�iA��K��e!���`�O���n���Y��"��d�t���]W0-�#��g�E�o���6��f��S�@Oe�SB��;@���NC��R�Cy^�F����<��f�~����r93�k�(��LJ�	R�b���`�.��Au�w=��QBc�����I���%D6t���+vLQ���@	V���'4��:���6|�#P��k�87pW�	���r�<���_=s$(Y�V���� �M������c$�Y��B&^�!]Fa~���VF��&����l_U*��>�D}��]R[.�(���2��O�U��p��+�������Q�mx��]>�����$!YQ�D0���+*��VS��%�m�D�������@���Md�e��uD�A�]�(B�Q���4h�7�I��gSal��������#M���0��x�OQ��G6)��D'�)\�{pJ�3��bJG�e���
��T~ �x�����z�.�R>���$:����1h��
��		���`���D��0�i�	o����/��[��i��>���X@��s!����]��'R���GA�g�1�~)t���@�
��w�)V#����}�
�=�KI$V3�+Y��lg��m��;c�I���X��"#���0vOF�Rh|Dn���5��d����!��p���d�Q���� v�K���&xSi�!��������
�����JD��dXA��^i����'
���� b:��*v�$�9�������%#����l��\���\���-�",e�I@BK���h<O�����e[�g!
�a�E�Ug�B��
�r����6%i~K����W�U��y��N�B�L�@�4n�b$��:P�)�15b��4X3����K�5���C��.)B�G�D�5b�D;�5��f���7R��������'2�1�%v��{�#�A��lG�A�����E(6H��[�B�r��,8$/\�����Q����&�H�	�HIl��L�vpvT x�Ow�LDN��q�&0O���8��[_�1��#��![��M������]��.7��
K�=������nZ�u���i���+�p�*�S1B.��$8��Mr��YE�K���0@�:��1Mtywr'�����3�V��:P�g6q8r5z�����N�<k�H|����t��t�A�f/���'�&���"�'3l�:���b~?��W������*Et��<�Z�F� ����Jf$��vu��#���2����/=V
�8Dy��{�&����6���Q�x���^�`9c4\t�N�b�1�b��$w�QAz%�o��^���$��*���w��G�Q!�����1��\0�H�64o26q<�vI6��/[�������"&I
��"w�R�d#"F	��|b����R����B�B�L`�zq��j����d����}�K�����F��m4���/�B�M���Wu|y��������f�0� EM�n�}��bF�m��F��y,�]3X�s�8���9�U�cRV��������u �E�^Aj���4���6��'���4��{�Y��*=�N����}Q�jU�w��u���<�� #��jj@I=�Bh�z���UE�\���o`��w�Y6�|!�"&���-��C\�
f�koN�Ci�\c�F�u�)��{�(������M�|��:p�bk>��������4�����AZ���.����z�MM�VLll���Q��&�_�|:����n�
�����8�j���oEk���t�����@"�!����8�pJf�����dH��$/B1�f������F���H~?���,�JB�C�Ly�np�$o���!s��	3����|��\�t����4�`wm[����Q�HM��gF)�=<?&����2%C�k�Xy2�3J�P�d���������mvE6�u'�d�+��\2D,���n��61���B��Z�&�G��@��
2$Y��x$�U�
`��Mx2�+�^N���=�F�z�Hz#os���*�t����~���Rg<����.�P���V��ML3��z��v�SE����Q�����,1�0V��(���f(���	_��'?
����{�/��$���30�.x~�'p^�1]58���*�A=�]�x<�,������o�<��b����l�C{{I�J�Y���R��?����H�U4#$�y�Z��u�A`�o��$g�(��4��*��DK-n�d,<h�
_�P/3����"�qsi�7�@���{����5K(����^�����pA!���������u[n�.��
bo���CFi���V�>��Z�@K��B�?y�@TB4�#a|+U��5����3��4A�u�,pQ�f�!/�`���"1�FTE	g{'>������@�@{�D��-��-�d���<g)	F�W������jO����%.5L^�����a.�6���c��+�4
�{���D�o�t��o���V���@(c���]
���s��@��Cw�����{�=\�������X����4�>�{���]�i,�#vhDQ(���:��Br�����~���V3O��dy`�����-3*����V�=E"$�.P�[�F!EJ���0E(�p$����v���3&i6)���I��5�R7e1�E�����i$s���p��E�3�5�>PUbmi����/kP�R��X�rP�QJ�g�a
���y�
�H>�����A��������F�^�JF����%�g����I)�7��d��|�Je����lZ���F�	_O`L>`�M��MW��GR����	�����+	MU�}�C�-.	S�c��F4�O\��b����E��{�����:o"o-`Y�@�<���3J���|�N��_u\�$���3�d;WO
%�w9���+�{A�����c��^�~��1�����)�"{j�t���K�����ty���������,��t�0N�6x��#�2L�Y��0�\�n�t�{����M5wv�b��0`�4����R��������_6*h�v"�F^���b��C��W�H���/�rr�\��X1�m��+X������2��w�|{���|�	��\SD�n���������`G	m��B�f��(�t��7����	�B�a��'�N>�g�~�����^_n���j8�k�\D���w�7]��a<�N
St]f��u.�fT4-���@��:��v�(�t91��p�6ESO�H#^��Ls@_4���AI�����.������ ��b
E�=�3����[�m�w,0t�������Kb���Qe�3����]���^
F��
�do|�N�4�x���]���`��I=�����_�Aq��Z/�<{��c<U"�a�(�������r���$����m�XI�W����&5�y_����p����B����,n�$7`z�x"B�N}+�5D��bG��cP�fH6�)�o��}$�K����� _u�6�>�������@�����}���+A��R%��?*�%�S�7��&y��6Tdn�;s��T�X{����[w�����`�*��a���V��*�|Y�i��%�i3Q�bPpY$����=��PnD��s�h�4D�d�'ri�)7�'��_������teEaa���g1���}d<0�3����'�tjv�����3���I�C�����8AW����P0�a�����[=���X��;+@��]�bdk���11k��G�7�{��xc���������)��vL<4��X��u����!7r!�>rH�z���7F��S��m,��+�j��mv���_�p?��NAL�sp���b��0A�
>���c�g
��zF�d/�L�R�t�>�R��o�
���?�!|k�{�Z+nZ�.9F���'����dnP�������	LO�g��+M�Jx3uaL	v���>&����
�(���\��
��YL4�Y�w}nN�/J���b�(���U���y�-�c�3S�f��B�*�����~	���Im��"�i�vRl�:^)�m�,k
:m��b�9������{�q@�	�0����{(G���w$����_L�7m���.$�T�)�*�&�w����\�I��9�^vR�N��c6G�-
��6��XY�
s3U�a12{��[^������$��$#
�7n�l�o�;��Q��?'�-Bs��@K
��9�t+.BTIn�	��y�y�E_8���n]}��\�uz#g�3!S�����V!���f�'��B����P�z_.�L����Q���|�P_��
${��2��~�fLn�C+�Y�Q�=.���x�6�/R���}��#�)�H`��Y0�/J�;%�av�w�q��6y"��/�� �����)�-rwD�}������k9�~I(;�5Aq�4��8I�}1��v��3<�Tj_�d�� 6{�����J�l��:�0D����On�v������_I0�����������w>����G���J�i�������Kdxz���B,y[l�"���7�0��d�������:F�:��br	Z��0��Y���0W��U�X�gn`���!MC���'[��t�\y7�@V;�� b94�
�������/
�	:�ex4�]$P�G>B�C_�sD~��i��%Qy�%��1��4#�Y��J>�B����'�i�"�):�Mh#�6��O��tQ�|��^�"�1�{e@dQ�>��.��� AF��U�Q��	���i�:������kO�PY4����q/��hp����D��(���N�q���mh�f�h8&�@�h4U�j�@:BF�7��5����|Lq�����0'M��<�b��
Z�0�03�����\Z$@D0P�q/��/�� <��lR6t(��
��.�	�{��}%�0�gF����	��+�6���5���E��[�j��P}z�_c�W��W��4���Y��P���4G�}���^n�0{��������<WS��P$��z�<�
<�=���g��
�PX�Pg�;�C\�����s��}��!��M�Y����)�!@�X�NF�k3_�Mx��{��0��KgzI���6f�Q�V���If]��a�|Y��{��EP�[N��p6���u��g�����`��6b�&<��Y?l,��hR�r�D����o,�m�����������=A7%[�e9����%����^�Z--o���&����Ui,z��S����{�q��������i�AI�/����l�4`����z����%u�>[�c�CD���$�+Fk��A��YY���8
�{MgR���;�����P�$�F�g��(��/�K�LC"j���R�E�G�����I��Rz!����1���r}�c@iV'����eS ��Q�8��N].�>`��� �����������}t��"=-�R:dM4~�3��'�6����d�k��{~��U:�����{
��[w�����:�c�7�}���2'��w����c;����������[)�����2�'3y/Me�*��q�� =
Z���C(w�����b!�;	h{��`��S*6m��Lq�HpH����_�IXRjJ[�k )�V�T����39����*!��LS�*e>�\���"�x	t�]$+}������nq����Sh��;�-�wT���������-5e���������K!������+vv�-/�
$��D�H������j�b��$g��x���o"dc�2q��Po���.~.
��[�
q(�q����R�B���e����d�l�p��8����P	���)o�+R��D������$~�d���'���9���3#zr���k�/��i��b!�
�'AS�-���l(�H�i@fgt)_����|�T����AY��w�1��4	��.
fD���P������%y4A���*���x�����[��xG�5�;�H�s(6Ga���{��!-�|��`p�(z�B����D���[�"|\�~UK�2x��X��uU��*��:��!Fq�*���� @�j�6���y�����it���B�2�o#T�4T9��h#`�?��M�uq�F��m�7%�����
��-�E����o��e������z���L�����4�L���6�")�"u&�����S���+���l	}�OgE���}Y/G�(N�8�r#'����h�d�U�3RX7��� vh�
[\���'�B���
L�"p\R��O#�
�h�mT�����E�W�-���/�D���*~Wj;/��	�v?��/� ��H�#^W1i^j�=O� "'�h6�f�)�ju(��JC�_���H}m��5WQ����;L5��Dq�7�W��K�"��
���i�Bttqvb�(*B���e�)�J}�{�,���G�$U��"������O�h��o�z��e?��q���^��[-q���~F�5L���w�D,�,���2��a�H��B�=��ejx���2�H�x��"�C����9H�����_�F{�Hm/JF����7�%n�����|*�������Sb��y�'�7�����6�\!X�G6�v�0�N��!�����g�?av��~���]������q���;~����!���?n�����J3E��Jpl����,�=�m�)O��5����/z��@qU�ZZ�����g�_�W2����2���V/��i��c�#�0Q�x)��"��qi�biC��G�T���������Ok\�4~����q�g����L����( �c7�R��,��+z+zA��m����������R�6����\�%�=f�������P����Q��sy��*4	���|�E\C���6�+!�����
h��[Zd'C�������@xG���Z�L!O�����'����������d�s��\���B�&N0��(���%{uc��[\�q<����b��!�>dD&[a�l@�\��3�Bo��^(�mL�#=��U�j��������M����B�%�d�8r|sh+��z�+��)C��d�	p������TS���~\gS��M�|����+u������p8�W/H��I� mwz��2>��32=$ V:@�2���-�+��X:Z��6
-!h1/_�D���=gm1�I G ���N�r(].��N�kX.���Y��h��a:<���r9^� �S�9K�5������0_#C�|�v�5�<��[���R���q��K�a4�2�"�gk�b�B��s��'�J�1����a�Q�S��=��d��O�SS��}��|������U(�y���������i���l�Y!@Wi3��4VE�oG��9��S��
p7����_x<���a[�xdL��Ev�n��� 7M�'e�i��M+��>����JX]��1>��}��hy��)
��q}���l���?�Ti���BQ"h����!���#�������2���������I
LL�L��c����
�_?��LY���$�&pD���r�Y����qY��T��8|���t���c�
A5b6��2�2��j�r]<�
�M�=b[�{�.xp@���g�'2N�2D��	�k��Ra���&������W$�C�.qB=��t�eq}^P9<`�K0��X����i����I%�v������'/Y��KA�I����t� 9F�Y�2�~�^�����m3 @��d��[��q���Upc�1�F
������f@���f�4
�r0�F^�L�����i�����}��%H1�n'K�
�V@l��F����K*o'�l�Q��g�	g�L�U������V���=	Z�)�S<"�'�pA�G���KZ�����DX����@������	8`�����@��Y�����$���dL� !�q��0��O��C���q;�v������_�ee_�[1��!����6�`��}1�t,a��&��"�u���&�/� XW��?��N��,������I	�����A]�/.E���=GF�SCsO������i\V��M{7P@;�j�i����,�a �����a�����������&V%~��
5�W����#9/��R���$�����6���%��hMl���'sk���fj�!��yBW2�xlq�Ua�X�(�����hY�5@����6#S���Pl��V��%�P��������8���<aE�D~*���DK[�8��J� ����'��B@�98
,��ZNB�i�e�� ��]�D��	���A�(�ZKq'���������OowTh�Ex+Tt&Iy&/0� ������K�����������/y���.�V��d�RH�c��0{)�f�;�����a�^Fd%.,�*�9�D����|���CY��&�``Z�.�b8�%��������, ������Q_�����>�,���?�4��(nq<��\1�Kl���/R����3��4������_-�H4)���E�\D���N_3��U�p'�iA�m���^��3s�%�1c�&��g�kt���
��R,`��oodi����D��7�c���F�C/C���_
,N<8C�WJd	^<�JWR���|���`�2��o�m��$M���.��t@��t���\�"�������Z�� �
��������Rl4�B�Z8d����|h��S�w�a� �!M(Tc����0���o�����*���T{�'
d���t�T��%3#�*���n?�pQ���b�D�z�^��$C���8�������V��T�'��;�V��ul(�xA<�v��wR�H���EX����>�CR���<Ja$z���R�d�l��I���*���c���E�`��d�%�� %>�����E�D���3�x��g)O	�b��On|=!Z��P�mp�����\�����rq����/���P-�nc���!���w��4.�����L'6*J�l��	�����m�����{	�N�+xJ��omMRt�)+!��()K���9�������D�y�(�O%6F�I��Z�����{�o�����9��}�
|+���sP��#���y^K���c�
2�?=C6X�����6&����6�:�cA�.�f���!�		������� D	
�U������`��aE���t�x�ni8k��E���O�����o~6��|E�2�\K�e/�
,#���Z����9d	9t@�E����m�����k<���$>�������]���A4
����<Y+���������G�#i"z�/���cV[�����<(�������E ��,�8�b��@������zwa|C)�9Q����U��zK��F"N��BA58"��l�2��E��A�COkU�\:�PG��C�Y�(���,�x���{�%��8U$�tU���
#u`��A]����%I�FF���F�~!hI�Q���Q�_*�s���(M��-�D����J"����>_m��b:0���u��X2^������!�S$y���|�}�j�C�(�5��TZT���\�P�3�W����N�vkM��@�`�  �`������A�/4�Egtc�h7N��?|��$_����GN�-��sk��!5�Y0����'�Hc���~��������
E��t��,��	{���w_��G��H������������I��}��'��*&2g�)}�,�)��gm	t��ntQ��:*���-�������0B����:�������E�#a8�����xQ{�/���<�1�DO/O�,�\J�~��2�$�$��$w��7O���&�)�L�a��N���Mn.��C�DRPbW�V Q������:�3v��8 ����S6�7�H�*j�������&�����e]���R�sc�2m��,��b�O����m ��7���!�b}�IQ�r�Kh���C������TP�Hq�Vud�����x�m�ms�NE8S�����d��������5p���������"���A���o5���e�G:�F��4cW���3p�"r��.�`'
k(,�����D�-2�A��q�S�yb6�`�������m�+��@��J?^'�A��S;n<�)FM9\��������J�
���Q�/��%^�������m�o$����}^$�/�^�@�TP1�?����V��\��-���<���k������&�������w��y��Y?�)���05|{+��}8t%J1�W� �����('7�_�]����
���}[��&��@�#������
��A�8}K���h�01��� �'< ��1�L�Pe�G9���06�[��z��E2��K���
��|�����������D-��� �hm�����83�A��^�@��?:�Pc��
	^�5�\������TC)�'�����zd�{A&���*&+�4����`LUbo������B�����7���A���^�Zb7
���"��} &{	t�xrBD/�L���M�S�Fb��
dO=;�����������i��t��,,�\��P@q�>:����%m5T6P�!L��
�����cC�>��<#D�����2z�H@<�,<����-�V ���#�F#ny{-41��
���Rw-7�H�}���;&`;��w�����Lu@��;{�LgcH;�Al`�}���{�8���i@��������/[�RG��tq��E��IZ��|�d�Hx��qf���0�Zl����������k�rl6�X���2 �$o��8�3��#���DJ�AA�8CZ�~��MA��vh%������Q����f%�+��(��=���_�vQ9��$���xF-R��t�)
��9i���-�'q����AB����;H�yC���+tD��! �����d�������%�?G\�@�4Ly��i������	�R� 7���}��4���i�_���|����2���q=���#�C%^������"^=��-���8j"�}���O����O������7j���=���|����o��W�|�����x�dd0����Ax���?��Tf���������)v>t�������?��p�������Q_��~���S���������SO�Yo-"�����������������������s��o?}��O�������������<������n�d<����~��o~��O�������w���'�����������������?����_������o�����?{�_�~�O������������������W|������S�d3����=�7���?���O�q�/������������w�%J~^�/�I�������\-��Kj8��xz�����x.O�����)nB�Yqw�_��?��:�4:QT����Y� `��~-o���K�{��/G4E��'.�~�Y�l/`��Zx�������IRg���(���\I?<�w���DEN�������b���AH���������6r�m~�j��YU�&q�����q5K�(�'��j�Ldz����n-o���k�G��H��'����y��#��;���������������;+�1�1����6V��Z��v`:�����*z���"�{��7�V����~�/�I\��7Z�]�&����_���e��po����d�����c����F�u#Q�n)o��+k����K�e��/T�YK�I�'rj��������=e�X%�������2[b����?��Z��E(C��;L�Y�J�E�����?��Z�x%�~i->L�]KG2wa��~-?�����HU{�����A�����6Q�E�~�82����R`��o�������?���("���#K_xp(�=}����x��R�H��w������Z�j�������������y���~�����W���������KB��fO�u4���{�0��{��by�e��������
(��
mN5����|���t�y��i�'x���K���>
�q�[���~�*2������������>�(��A�~���4��}q�� �E8�}�����x
�E ((i�������>��g~�����|�{tY���hF�����^	�$��[b�Ev�}}n`�_��R4�7��MX�Uh���%�����/"������j$5�� N(�u>��������k.�q�U������x��:n9��y��Q�����LiR�w	e�5^���^�t���l 1{`�j�I�Nj��������`�����K#	�����P0�'Y���%�}��x�E�/��W���c�-j&;���_U�?�&��4���G��-S_L7&(M
�$��_a�~�:����S�_��$C�[��r�jH;��FU�� ���Sr�|��H�`s}�����.Kv����G��6��p���q��Gti�����B��Vj�0�A,hPB��y��a������G�C���/�!���S�������'�@�yd0�@*�rD;�Z���L�LL��Z"��l����U7Q������:����+�Gyu��;#�+������06��M7�+1�k�#�������o� �5p� G�ni��������D�j��8�kk����C?�L����\p�����)��p?��!��
�yu�4`�;���3�
<�/��W���/#�)e���I�h������lHA�.L9K�Wi���(j�����x�-u�:9A�r1�������)t� ��IW�{�t����rAMa�k��a���|9����?>���S0N�a�������}j�s+rHJ&��H��5#����Q�A��{�^��av'�����a��~8<�U5����-W�|Ujy�pK�@��A��
�+���!a��9r���D�<�md`�F��si��^�D�5�G{�c�	�#�]>�Hw��@Qf
Mj�is�,�A}M�|R���nW�B����t���#��StZr��E�Aa�9�"��W������z�w����X�LQ[�C��CWc��coq�D���=�<���3<�C��M�?��9�j,eIh7^�������>0��q.��,`LRE�_b��,p����I j?�(����m7.B����d���	���C ~�d�zX�H�Z�)�Q@�u3�&���V!TM�0�C��A�yq����yN����~����%���l:�
�[�&���H�`
>")�{�>�������l��t��`A����#
Eb��m����G�_	�-�e���������
y���vp0����r��6�<�:Tf�*%C.�ItHJw�O��VC��B��RZ���7���6����F��"�A�	�#'#_�BJ���c������|A+a$�e"|��gC�����W��X�F{��k���)�vi���f�3�p�zx�v	%����s�*�;<z�g �MD�j���#q!@���p�!���G����)�{�H�F���&��9��?x�����JF�On��aX��+�$�BO%�����g�l�!:s�ND��M���b(�E|���a�?C� 5v:<h}�=
�Y�r�{�O���H��2�C@a�!
kNhg����������Q[9������Uz��nU6�/~X�P��7D}8��#���`2���<����v����@�q��BPk]�p��@m�{=(�-]{X��A�-��I`���:�X�u�Q�Rt�����<zB)t�d�^��u���.qT�O��f����x(t������_� e� ?�$d
8�d=�iXc��x��,j�����sI�e�r��{RMR����{'�>
;��8�N�f�>by�\mAZP(�[.�*H�l�n��eOx(����z���.%*z����U�,�����K�P�s��I������m�=�4u����>���#���h+�{l����e��(x�;�t����n!Tb����p'~PF�:X���
H���$iA�r�BPlv)	#:��S���:�,vqkt��g?����bc�XY�uOP_����,�e���&�w�!��d]��w^&�<�5J�$�;����G��x#���$���F���dt�v�Z����I7�����;Uh���
0�6��?6��1lC>W�0�VG��T�p`�H�L6!nz�A]�]*~=~N�G�,�~�^�����e��l$��E&o6��q1Eh��]�+�,0|���+>9x�E�=���A94��b��5���_�
����fZc����b1r!#iRFF�,o�1T":>�Y>u��]r���"uZ�$��ec6���} �>
��n�����%��s�C�<)�ldTn�y�k���-��/��O��M@��2���g�Z��Eg�8\y�Yxl���0��$k(�P�s��nQt[�0�p��;D�5V��FC��f�aNR`�d�J� �W�;$��4��p"�u�qv���S6eq>��[L]B#L%!�-I��{+�z��!W_��X�|�PM#C���}d�.�qd������_*s������{ ��;�h�u��S���"��['�I�0 kJ8�2��;W|����+4�����3x��f�5�b9�_f�?Z��H##�����\����S� %����R����L?
��1�b���t�J^����4\n���XS����D?��D��O�+f&������?z?�R���1.?���0�v�K��!�C��r5�����%@�%^�h��T�5��m�1J����(��h�6��4������\k�e;��/��hRQ���#Z�`�]�t�	 ��QY�{I<�,����i�-:w�w(wH���AB*���M�:[�N>:�
��.�m�:J�����/	���s�pUh����K?�m�#��$.���f�5"���a
�e�P�V�1�6��(�p��A���dt�2<���(�-	(�H�I�x�����m#��1� �!@������6��*�f{�|I�%$!���;�xj�J~I�rI���k�%(�\J��>;BW|����i'BbI>k�nN�S^"v%<^�:J1%lo�qRV�J��m#�C���e��6���6"���f��p������L�J�������t�)��4����D�O���[�����_�,�^	YY[L�mi$f~KU�������e�����y'K�
����3�@�H�8F0vp^I��w?}5�ahg���tt�,����Y4����I�`�F�c��
C;��p���PC�,����u]
jJ�X�f&X_�$I���I��"cW�wy&��Kz�(SJ��.��FA��y<&J��,�&���P=�W�$������{���8������]
i4�1V��Z�s���F�#�x�T�R�k�����]=����H�&���!=�|�;U�����(�R�������t|�k��[���" �k����HI!.�����������F�op"}m��v'��2��	�!��v�]����m��]�$�|r�E�W��x�C�'���N�#����r)2d���|Dz�H��#�w�|�����<X�/v�,��l����A�c���5G:�����Q0FyT�gH��=f.~�E�&}H��-�����9���V>.g�8��|��V�=�����w�0V\&M������JG��Z��t\���xN��<?9Ice����qC���w:���ul�����L[�������{��j�)�g��
�V)�^��a�b����)�P}BC#7?/��.��K�  _�y4�]���Y�R>�u���ALf+%a�q:7���v(�HK�g�x�2Nzu����.�{���!�)�EmX��������>��P���F���-v�L�t���UZ.���_ �����g`�K��h�Us���q�.CS��\vgm����k���K\P�����
��~����N�����j�zQ�%B���]��5.���S�>G�j��_���""����6�m)r�.��~�<��vn=H�c���=�Oj���HF�
:��c��4�����+Z6j6y�Li�46z�L����#y@(P��Q[�4)�2@B
���J���	�;"�v!���=|��
B���O�Lz��F<)�l*�eF��y����\c8��D:��2X�?W.]f8���y"�!Kz�y|�������P�bF��
�|�vt!��o�os[���6�Y���n���+�hF�s�@����;�(\	3Mz�����"��E�N���\F�'����,Dx�$�
\V{�����\h�����gf#?X��(oBvlzf�]������gk�#��?/uw��rIE6z4�b��h� 0hA��Y*��T�v������6a@�.�M��`�.?
��2����"�B�?�e?g�d_����\�	�L�}��6Z�Y�H�QD�R�9�w�x����EW������R����,x��D�B[��V�u���',�3�*$�*��Y�]��xH(�����H�
&_�"�����S�EBY������7B���kp|(��� ��"tb='�H�|�c�2X���\HBd�Fl��q"vd�����G�.l,OM���gd��-\�q�Y�2d�^w��%4���+��8��d��&���NUB��}��@UQN�s���B�����D��)�gB�|\��uB��=hj��C�RT,��j"�y���{�R�r��~b�����p�k~�@�'k��tK`r��%���EzY�����E���������\���#��b(]��gd�>����xCC��B��-��b;�����Pd
�t�}��xv#��i�����~��pX�n����A�\ ��Q��u���7Y��B�sM
t	iG���$�F�P37�Hk�Zn:�9fp$F���@n!�]z��AyLu��"�c*d'����8�H����&f� ��O(P<>�"*�������{<�9�&���..*ZD>0���v�]�Q�3���xO�yK?�%C���C� �,�%�
�7�k,��2a:��y&_�@"@�*���l�ylOk��G
N�%�u_�?����lC���F?���)
l�o���+n)�K�LG��"�N&6]������^h,r�DE�0_��m	F���@�qb�W+�1{S0-��f��;����$����Xt
��y$��1��#S�g5X��x�����{,1�����6�����$�9�
����2������n���_nk��<3a�0�C����&G�t�X��c��2�e,]�.������8J�2��$�k��k2%�Y(M�F�B���Q�P�!��MY�T "�^�x~RL��M�H�G��1\�'L�Hs�����~�y����w�TGp&}��j��Q�#�(�o?�0Q�;1�~�j�rJ��)���l����:���P��B�����^��V3�D��"n|�7��|�Ejw�p$�Bt����vF�����pT�D#�]�����U�8��[�����>��<}�����6�����\�+�;T=�D^������r���z���LGs^��L��C��V��������j�+V<��{lX{�����Fd���p����U��G�/X�����"�e�iau���Y��t4�[�.|�b�4
=�f�S�>���?g�s���8z
Xq�3\b.@���)�O���"���Q.W��e�
�/-8����#�� �r�6�E���vln+��U���3�R�L�����v�a����1������R�����c��Af��!r����T�v�ha;F��q^��b�)u�����oa2P����}o]�K��cd�U �����I�yRC�:�5��\�>�S�1Nr���1<j��

:_�[�)LZ�)Y;V���%�d��Hj���/�e~#�U��I��l��%����aVC��x�]B��k+
���O��
�ja �L�.��<���5�������v\��u(wN�@.]�=D<��������2�9�V7%J���f���H��il��I�]��KE�&��+�����\qU�n����]�H�����r���q����
`s����:��iZ����O�1f��UN2���"ha���������V�o�-~����e!�="��7*���/�������y��I��:���������m���q&|�K,v
���B#�����v����I����W���e)D�~I|������F'[`��O��2���h�����af�UW��x�=B���-8T1K��I���^i]J�w�p��*��Kt������-�l.�Q��q�T�F���%�`
�������Y��O���#����v�y������&8� {~�p+�8Z.��^�Q���e��'��+�H���:2��Qe�d�)�z<?��l(���n85r�1��}��S��q��9~W�m	��B/���|��������l���v�"����[�,�g�����xN;��B5�A���dP{��>��D]W���3^��g�xW��0���?�	���O?��0V�;=>m����x�gO�| ��H���Hr��?c|�Uk���sx�}t���)�"LV��	��X��$~3�!+B�H��\Em�B��20$��m�{���v��B��_qQy��	��.�O	�OF�]���G?H���t����8�>�r��/��D��*k���p�����Z�X�.:����;��$�@�=>���8J�&�e������^��6E���6�o[�T,7�|�+D$i1��u}���,�x�����WY���E>��1�gY�-�
?���V"�su�&z���e�PN&���OIS�3��"WI#�T�yXy$8k��F?���w�����|����M��:�
��^GZg���
"
W`�gL�SM��VP�������7���5��\F�M�@�O��8?��Xg3a��-\fx)���i�r�1��8O��(T?N�p��q>��?/�`\��4-�[y!�wi��qg�vZ�`����@9g�}o��0�`�
'O�,[H��cp.��!#�!����I��k��m����(5E�H��u����<Y��Kb��1�
[h�E�dx��,�4�`�d6�OG�] &�r+]7`b���]�������wm����*/����@#������s�,�C��2%zi�n��+��<-Jjx�\�"�ay��I�"�g�^����K�S���F{�k������l![�x�x�^"� 2�.�m�Fi]�Cpq�����/@���:6�B�nH|����<�	+��$9�}V��6�r���������Z���/��.,���QAJ�i�K��+.�Ge����Y�b2����-�c�����0��Y�>�'���Q���	��R�B@���1���q�5���S���s� �6�pL1������*�/#���3=���H��z�a��u+a/�S���+���>NK������0��S�gs�����lo<�:~���DM;.�.�M�v��3�[Cj����A@��>.2d�H���8�����0C*���������q/|���^��������<�5���d����)!�x��o����D�VM(�j2,e�Q���K-z��Q��H��U�C�kH����������)?e�&�^�y��@

����d�&�Q�8u��q�e����;��v\V�k$���a���V��&E�Ke8>����r��(i.�2�[b�gf8���WpH�,����u�Iv	��s��<�;���o�m���D����R��k�<q^`��-|g�l���B��
k���\��mF[�a�5����p0�ttS.�����B}>��I8���)3���'��w�N���XHW�%�(	5
�����/��'#�$�P5k�����P�?���_�]�)�.�r����W���`U���� d��o��[H�*RH����-m$��e�*M��O���Ah-�#Y2������O�g���m\~=$��
�52$��K�
�V#�f���:���b�v���Yp�&_`�:9G����EE�]�
P������")�~���Y;S��D�(�c7�}��;�8���������C�����$���	CC`Z�V-jv+���V���)�-x(��9]L�m��"fA���:��$1��t�BLR�5%Aiw2y/C�=�T������ ->D���#���4�n�6����j��aN���U�R�-�F�&K<:����V:�6�+�@�(*0�$��6|��
EK-@�K�XBDl��2����/���� �n!��W
�TGp�!��`��_�t������]�G���B����H�����N�c�
�����O������.���GJu����dxk�#��S}�^����yo!4��|�K��+�������RQ�O���������FIXl���O��M
�K��2��O�g�0ir�X��8wi��X��J����/�"����*A2�v�3�E�Z���8s3�����T �V96�������B��Tn�u�����K��Z�@�����L��G�[��������-�j���n�j�B��u'�����m6����'�ph����D��k
����r#U#���S�qD�x{�_8oas��<	��G��7"�#�&�C���X�]p��hE������U�m�����r���?���]���L^_�C�����:�L���:�����a��8X�|y��j��E�!�pctjr������6���7�m�1���2�L��q7�^��R�HT��(,��#���$)
�W�-�����UOn�5�-.�T�������^��K��!�!��%@����)��$*?m(7w?�T���������W��2@�I��mg�maHj?����MA������JWY�q�B�-}�5�LE�2N�+uw��9�^�����_<�W�k�:�H�f[��BbK$��h ��R����!���5��N��RpbX�d^�?�f�1b"
<��V����������*b��I���v���]3b"��c�1���
6s�<��,pc�QO�Y)�K���(&�r6I6m�xyU���Wp�S���.���$��a��D�qiY����a.������^
���;'��(-o5��_�����FV��|�o|8B)�sj��]��sQ��7-!�X>�DL���,76�Cbu"'��
�9e`��EL���"sU�}�A�����[�V~9���u�U��$o�-���0��m��;"O{��D�4��x�6I����,FC����P/>��� �[p�������
_�V�fy��GM"������9�������MQ�������q��7�L�(6�-��	XYd]6E�7��_�
�B�{z��h$c��"�S+^F���\X�bp����K�x`���
���&��^��2NtF����7uZ�Zi���/?Mv�4$��%A�)o���n0�\2k��M���^S��=`n�,G|(7����6�n���Dv�!�B����32M �[��H/�f�>�l��P2$J���(��d�����H`�4b�����y9zE+!�bs�&x�F�I���,5ym���G0D)�-��|�c)����+�,>����4n�Q?��������xq�Y��4"�%�X�>����G�����K���G��.�D,l�*�oR�&n��������&��\+���E4@p�a�V�72�����$p�Q���DB�=�����"AvL)h���V��@X;%�>����z����3I��x+D
���/7|��l�8Mg������Z7`��K���D�|��E���K[1Q��|A�rBO9��d�1O+�� �,����������Q�%<&^�{��G!#���G��Q�����u����P.)�s�u���=41�bK��� ���~�"���n���/��?���dq��K����M��(�����eLs"J�#���,v)������%t��w`T�����n��?���l�/���F�)��*�e'"g������	���-�E�$&�w!�%'LD��;��X�-��{���Ge�[���\���($^�&
@�g�����ylJF�<��d������?��/��q<������dp��2�	�0��0D������D�b���&iN��%&��M�v`����^9J�`@!�k������q<`+Hs	\����-Y2�w�0�{q5�{*�l��4�0g�S�������Q�#M��V���5�A����
?�>������s,
�'��%��[2��'&+��G��]��J�T�[�
=��-G�M_�5?BtI�U��~�?"��QO��>�\��2��b�,�YqGQ���z�"u��������������V)$
L�����l���)�����BE���r���H	���V����[��P�>�	"��E��%�t�����:��h���X,,�`��\`�?/�Ut�}\���`������~��^V�@Tg����9w�Y�&Cx��+�J��8� �6������
��?�~��_��uM�\p�j^8��c�J���=�n�=�%,�������Ef��T�$�����G6���->I@��iDjJ�� ���;2����O���8��.���j����4D)�����7�2#�8u	H��"^���5�isl�����6��<�o`�����A���#�+���G��n�����:�������Rwg9�\��0�G���q�#D:�a2G�E��8r���.\p���w�F8Z6�/=���Tc���,��������8��.`w0����~Wit��$��j�q5��V>6��E�oM:��B��b�K�z�V2�AV�2��Hez�����OW�2�8�r�go<���9i%�@�~�\:��9�O��3���-A%1��'�R��e����R����h�~.�/�%���:���XV��9O�"J���.g�.0@������;�\��(�>)���{��*hh��35�n����p~�0jz����|�����x8���^�P\�W�|Q\~:^)>Ej�z$�V�z�������[�����e".�L������,�m��<".N�G4�u��m���]�F�	6�;p�.����{�)�M�lFG�
��)��\��e�W��S�5�E��m�R�x���^�>�?��W��R;X7 E=���!1�l�}��wB!��&Z7�i����O1��Xba�-�c����l����\2���;��#��
��B�E��J�~l#��������F��tiQ���y�:S-lf�������2�;�"���T�Z���)��}q��PEo��ro�k��D�#�����pTxn�����DkE)����o�8��GV�X&�jrOy�������JQ8����t���0�r��D�����`�t��j����o�`$0C���x�s�[�$[]�	5�����E����n�g�� 5Y���o0���V�o��_>"ij��[���[���/���U-OmI����E"{yr�����Ag��������GIm�ts~c4�Y�:;;���6)e��I'$�����ei�����y����������z��^%J��P�H���7AenO��0f�T�c\a�����C������GP�I1���y����v����s�����aiZ���>�OK>�U�[b�	Tj�LW����b���<��B�}"��}=b��t������!����	�������oo�X�vR��z��j�w�::f��'.m��)"��W����Q;Uj�K=e�h��@���M�������B�\FsiR��<���U<�C�4H^�\V!
*U�������d�>�H;8��((^r"s?.N!��Kk�E^�1���������~�!����Pg�`;��c���J����������6�6p�V�l��
�����/���;*['��*�:RO��l�������mkEjO��D��Z[�I�&)y]l�H����������sP7Hb�%�%IZ�6D<��S
��<��k&^I�s�D��T�]
����M;��W/e+��s��Cd������-Y������ng�3�6�
B(����
xG���*����rC��Km��eJ���%S%�J�B���E��������_"A��o���A���^$iq�l
���!�GPJ��H��[�m�"vy9Z'�����Q�O�0�4�� �.��55~2n�q�!���\�{l��>K�����yTP�diG����W��\�����$y���2���Q*��V�	��[H���*������*M���J�*��C�$����Do�V�E���i�����3���}���;���R`-�xUrD(�����p=�4������N_�A���[���b#�$|�B�;~A)L4�G��Y�tH��K]k���o��e�V[l�=���J��caX�aC�^0����4�Y��%��j�#�G� \D���g�G�����3VD�6���`�)�D��,��"M����K�L���K�^��]8l(E�Ou��2��.~Xh���hD�g�1pH�Oo@��,^r��l��rXe�`�|��n��	�������jo�����r��=���:���{���� �/��uZ�+}���"��r�����*�3���$��)\���s�Q"�qrn7���x�)r�c��{no��>����zi�#�1O�����T[�o���8�W��
�G����:�BpJ��~�tV�V���[o���h������m��"��v���h���Q�[��45	�G�i��2�p,Z�g�1$>t��`F��*F��E���*����h�Jz��F������������;MLb�:���#,Q-���?�w�=H{���2%c��C^EO@��[.����Y��
$y�z������|��v�
{�$��J
����Tp������C&@|j���2�1��DC�
��.d��������fq�]�GPj�,��B��+�	���b�F��+�y
��R���$.������u�����/�HL,
l�	��mY��|���C�H���#���A��p�AOg��(�0����0������t���_��H�jJ���@Sz�C��n�}Ie�ss�������L��p�$9� �����o����}����]�voL`4r���/i��$�}�C�{�Z$0}�`��6�����I>���t(���n(���U�"UD:&��C�%����Gl���8�O\87~��]C"=j�+��_��	��)���&�;���R<3�mT���N���Mlw�0C��]�����T���Rl{aN����0����+�pAa�
R���!��&t���d@ER/��'#���E[�����t��8�`�aj��iPAlw�����Y�
�0D����rI�JZ2;�p����o3e*PP�H������(K����N�.Z���p*<�Zc+l$R��'��}]��vl%��w}a� �O�����[��R�C�*!A.,���GF������x�W����m�$V���0'�C��_��EN^.�/&>~Bn��t������=���Uo�c��f�h7�k�����C�����):��+pMx�}&�������R�d�������=�x��`��j�TebP.zm�m����*�����8o�K���~l��C���R>���mfv��[��)�m�>�w�����L�����/��:�n�f�`�8J<2���}w	���_���,�[�[��u�6akq���������Gm><H��?OCRNY���,�F��b��A��=��$>f�d����5;z��tE!� ���et�},�1cB����f�x����MT,���L��t��D"����PDnn!�E����������]k���\�����D��F"�.N@K}?d,\�|�Sl� �M`���`�HBv3��m4Z�i5�'/���L8-���OC$�&9�e
�k$y��X��F��k����#��v���oC����X��=����|��/�o�c���pwK�|����j,un�dp�k�����	��&�����_N����C����DV�`��Of��-��B�=S|����Zt�}�^����#U�����#�)@a�#>5�/(	���p�B_��U,�V�������n�/G��gc7j��E��w�=��N���l����Xq�9
��7�^�����&��������1IB������Q��H_D}��m�U�v��M>��H�K�'�]�T��YZ��_��6V��R��u�a��w��������@s�|��8OA$��y#�A���������kf�+�!'�X4������T�!�)���X��q���m|���"D
?�>��m8e�6(c���6����=��!��p�N���	����)�U|����4L �z������a�1]~vf�l(����m#z3���NSk���g'WxZa�x����&����E�l4���6��(0	r��3@�V�5�&�9M[�=p�Q��:��,k�,�o�$��=��y'���oE�RL+G�#UQ��������B���F�c�c��>�d./�@E���� lT�
/QH���#&&KKL�.eSQ��q����q����>A���������9>++����c��D4(��(�HxJ�lA��I�������������P'������:^r���imH<��?�|�P�t�����8���I1TZ=
A����e����dv_�D����y������������������eV�����K��>p����8�����s���=��yT�	���U���^$��)5 ������<�(b:��Y�Q� g�-�!k/����!\��cl����E���R�A��m��D�F���(d��^-m5���&��L
�uC�5�(�(����\� �r��q7�j��m^W�l������7���Pw�di��%����	�+�;A�Xq�=P��)�B�lL������5�O��]�ZHG�Z���b�zX$�4�0��=\T���x��N��� ����@�dF���P�K��0��*�9ls���@���n���.����
��g��i�B�v-,*.X��������6�`eo9N&V#�#v��B���)��	���@8w�}��c��Q�I�G���]�M���(�P$I��|�XrE V���^���t���)��&����}I"��?��!�E����A����
R���@N�3����F���~���b��2�~�0����k]nv�����Y1v�������gJ?���k0^��m�k0���$g8,�zu�Q���#��PBRW�!Gk���W��8���\��W���:�J��^�wKNb��9�;�������IfD����g�`#i����F�No�/��:���7���tu$�^_/.��_ZG�RG<Q�4OV�ro�����	�k�e�I"�GQ�
��D!��x��x,��q��Z�����Z/(EN<�������itf����7�q��uv))���T)np� �����)Z�xt`9��
,xQ�g0�������
/��IR�E2�x�x��t�����l�N�������/�!:Jvz3��Oj!��$.���e�U
��H
�x�Ty@_{*�C�C�YU�i ���;��d�u1"_����"�L�5u�`�����H�����N6�JI��d���i3�������E<:�b��!�����#@u��.yJ��tzM�� ���+�����oBI��Tax����u��#u����Wzp�T,E����M:I*2��8����"X��iv�+����bTD{��c�D�%�U�;����[�XR���[�.����Hl�!�	YV��Sw8��������w�z�4���p6xR.��}p���v�����m�
��2��,;az{^��������j����H!�
z��t�y�*.��UtE�=pj�$w��(��b�'7'�����W�fo��M��q����D��)��a�0��C�[Z�;�h_T�3A���5�2ZU��|7�n
\�7x�
�Rki�S.�/K���9�9�P���s��(b�`�'������,'8����Q��8q�|���i^t
yOC�V�A�G��aU����*�Z$I��s3c\2�
i�4��K��/t�|c-
���A���]�z�Ee����2
V!�b*��6*Vg4I��qf��IB(R=O���,]�.�����c���P����>��M�����|�i	nC�3b��4�����i������^Q�!�JA���mG:�<�z'�m�����O��.m�,'h|~m
���0FA��B��~P8%��i�`CqEE��c���E�~�B�b����,c��d
�1��d�TLi������a�4�ZJ�D�����I(h���������3�
��;"��L�b��\F'�n�>r�&,��-���U��~������rn�p	��6��kc)8�����u�q��K�����IW��Wl�g�1���j��������xY<P�s��F������8q4�~���
fj�p�����/�"�ZOuS$�i���z��fY�eI���:�rkb�<IH����H�!{��wWR�#�/x_�`�����IlK}[�_l�#6Oc8o�[�������2����4�������o�v���<T�2��t�b�[�F!|B!C��
f��7L����o���7`:�Z�XWD�L���h��"����iq�An��E�T`�%�V�~s-"���@��)Kq������G�����Ia�t�b�������q�����
����`�N�Cv�nYq9*)�}E/tyO��|"������&���B�?6���aJ=��HL�������� *~� Fd�T,,u�uDG��Y�xKb����U���9���rr�4�.c-p`�C����l^`D�#B���}��B�?�wC��*8��}��\t\vP�Uh
CP�O���-4X9��y���`12��<����t��[F�U�*�=4@�����v��I���5�t��DU0�T��B3��&b<������<
�BC
FI�M/�r>��h���z�	04K�h���H�B03�~-]�{����7��G�-NPB��2j�qn=�����KX��������.(���/�����\����p��dW� �DZ���*+�X������Z*��B��Y0�(
wl�(�.��RJbsp��������F��[=�uB���!��<"��E�0�6Q�(��8�%u)�\�Ja���\C\�g�o��ri�V<���W����K���SI\;���D��N�92���+~(M����*$[�VL�ha@k���rp)C�y��t����A04lR �O�:����`�b���R
c*S�r}d��q�9�-LG�M��mo�	�S��� ����Q�l�%��!�7�������v�W&��yP��@�=b
-6(�A^gjiW5�:#]8u$��m��{`���"��E�O"��xQO����<�s��n>���T�����q�o+��S�����3<-�C8O�:w����ET��%�C0p�6����q��IQ�A�������J�=���2-W+��,���Uw��N67{G���qGEV�t�q�����[��iA<����Dt����	���<����ls���b�G��!��y�7�Qa�5��>=��T�m�;����)(��^����(�%�c�]$�#�&���z�g��H�KB���7W��'.{xa�*N�ES_���FV��G
��`/��5>�?��oReLY)d�o6�4�Z��kl��#e �L;��8.k&?R�E�:�W���rp�����S���G�t["���-`��U
�3�5,����s����*XAc�<�������x�8�x�^"l�m���s��� Bm�2�&���,��~B��H�
�� ���"3:9���B�
W�}��@%��tIN�oxF�_x�����Uzs:b���t��r^�Bc}UvZB��C�E��6���������-`
��On�y����pe�����y��!HL��r����d��	ox7�ra�$9J�a����sqA�I���X����g'����'Y�
�	�>� �2((�������.�6C>f���������E*+JlU�J�T}n.�h��E�����>��A�@$c��������k^�+�0����[l/	��xyG�B#��3t����HoKd��h2��]*�3ru!�3��bl�Z|�(����))��"r}�}YFY��0���	�>���XXG�/�yPS�����{s��DQ@�_����=�����#�B���9��`�2�6�3*���c2�t<t����f� ������DU���3����������Qc�����wo���@2/��H&*���uA�xa��&N<&c�\����@T�G�
�������FzL����?=��\�H���(��M�xl��2
�T������X��x�[������Ey���aj�C$���o�[BRu���hA����u���
��cJZU�q����-�.�'� �j�I����9m�:+"
����8��
�K)��}����s90���'2�t�&P�Y!�&l����I�l�.et}��Q�h��^p2l��
�4���-����;�#���>>=��_��R��(�e�r�(�s�o���[��W��o-�j�0��%`��d����a��O���fW�b��IFZ��g���\�b����'R�K~s��Gtt_H��D���4e���S��������].z���avF����,d*�>Ltv���V\�Pj�yj {�mi��Bzv�
�B��2�]�uh`.pA=�yw����:x��b\1A�YTSu�d�c#4���I\&�D��v���-A1DD�^IP
s���V�yG}���o�r��<�jk$""lx�J|�3��8h&�\q�q�����1�:)���u��p�IG��N�q�����n,w�����T���b�����n>ly�HiO�k��-����n�����n7|��d�ia��	b�?
��D���KG�]Q�)��^��y@f�~����w���1w_���5���U"i*gS�%l;W$��F��������(?��3���y�������i"�GPe�GY
��V��&k
-���`M��������L���M���%�6���)����X�|�;6� Q6Ba����/^�����r�!u�2�@��)�52�C����������E�	��-����Q�I8���f��Q��&4�E�9��!
�i��V���$o��/��
�_9��QC��qI����M[��p����0��U��
�����y�8~DI�e���I�T���N��-���AW� ;n��.��C�d
2qY�v�1C�z�JL�x�E�tl����1F��%�2��q�_N���T���R{��xM�Td4�%���m��R)�$#�*�.���/RHf�x@�4HF�`j��!�.'A!Q:@8��p��������!���C��,w7\\+�c���@u&I�g��|1��B��2�y��|{��8�*X��������p��7�i=��^��X��SBH�F.|��������#J����������?���?��o�qO{�������7����~����?���K���C<�z��q��0�����>��O�$������>~����#>~��O������w�0�-��o�����z�	u0$)��g�����?����~���YO���O<�_������������O���O��������0H���<��������������������������IG/���������������?����_������o������gO��������u����c~�������������>E��<����xD�w�����{@o~��?���O�(,���;;�%�o+x�� 	>��_�C���G)$�����-Y2�4�?������O�|�>?��SN )��������JV!���+$����H��z6�z.����������h�������0�����.��z���//(�$*a����OE����>������zb�`�A�4~��*���Q����������:�����Da�S��PM*��j�/������8��&�O~a�?��G_J�t>,�����rj�U@�F��?uA���-0;fT�O�&�U��������~������}�s�&�P=�8�e}y�!�YB��	���~	o��.a�W�_���~�i�]���B6���������2:P�����"
j$������$����G��R���W��{������/��kOer�D��ky��_[K<�x��Kk����Z:$<�n����e-Q	RND=������%�m����w�������$��ol�/�����k�y���?���?��ZPb���:����(D�^`|!(rG��	�17������������}����m|"�	6N���.\'��w�>���?+���.~Gf��u��Zdo�s���I~L��?���'�L�������|��_���w�3��%.���&j���s_-���V>x���):6�}�CI���e��Yl�'��`s��X�����^yew\���]�k�V����wR��&�������P�Q1r���d�Z1��:��"'����<b��~�fK��������Vi�g��F����a�&$���b��p�aAd�z��2^�%���yg4���<����.��ff�@��]�\l_(�"��k�������/�Cb�b���
>b9��t��HN	�Y�h��]?��>�{�#���qG}�j}x�(�6���}��,�,�V��nA�G���������P����.�������/MM(�q�K��#6��~��Zd{���D�"���hC�:������J7����h�V&8�0
�bj\�������G�Q����eD}�e�	g��6��$��������Y~�T�ir����N
�"/f�����������1�!5�[��g�Tj���a!�#�6�Q�Q�q��g��rK��,�<��|<���b�Ik?����~��*��Q�g�:3�kQ���)���Zf^[�z�l��c�,�N�s�K�|�9�8�D2��]��f�?���PE��<k�����G��B�| ���AM��������t?�s�u~�U���_���d�:�r���jL%;!&~������R3+b���62�n� ���X4��A=W����PO���������@/������4�#g���=�-+��������)��d2����W������2��OBE�4��k_��(�����c����9������l\�u�����W����E�$z�R�G)��� �h��%���.��K~�`h!�
�
������-��R��_��
���P����8��MT�>�@>�l����]��JB���L`K7�C��!}|���&5Y�"����_v���,�p��E�|P��
��T.��\�y�
���G�����ob�,�}��v���W{��?�S��.�T@����_;Z�8MW�V�Y���+��^;"|_C�������2#�<f=P}�]�
PXR���������zV-������j�B1����.�<�K[���d T����G���2�Ge�����`90o����D�*����+F�*�W0���J
�-5a�������<gh�~2�Qx��9ldQ<�H.�IO����G�8��	?J`;5���Ak�uI&9a9��I�"9�y��%����"�c�B��������������_v,z�O�!�j�>��G~��"�I�I�k���tE�Q/J��_�?�5\4����=��#l�44���QS���nt�4��>�x��%�<�0�s��5��d#9Os�kY�D@�\'���1P�	�`�>
3��}J.x��7�E!�e[�/����U8j���"`��E�j
$�H�����'���G��i��@����9jK �����x��I�!����y� Z������	��~$���'>�8�E�A�wc�<�9t��������S���&.��p��AH�b8�@�&�K��\rT�w6f��h�!����B]���\r���-_� �S���{�`q�P�,��D�L"����|.ip�M�=��(�_��>����hc�9�~��t6N\��������h���f(�}���,�����E�%���������uI���0��OYF��T}�Ji�m��"�!��"��g/
�
'-��v@��-KG2n
t���d>M�H��8���/�1���CS�����&r�Q
x��'��e��9�}y��UL�������)xSr���m���s��ENb�*0�����G<�Z*"pA�%�R�$�h�p'k��-�D�G�U]H05�f��e���3*W��#�7r+O�*������i���~����;��D�>_�V?����t�u�&�`�>��7�.	������Q\�A,�b-��U]��J��.�o�.4����Zg������,�W��Q�#���=v}���1U��6Px�u�����	����Q�L��N>�4�f��bS/�Y�4Y��%���,:q��2��a`����3������F�T��*�����D��l��Iq�|]����t��
5�5��J���J���#��/@c���^v�HN�:�(Z��q	��)(��F����
�V;=��'&�z2�W�'�� ��7�4bn�#�����P)���a���e��o����V�S5�����Z�kG����Cb=��F���r+�I�!tH�1n��a���Gq�E�C����6W�����T��"����=�-���1x�u������S�b���%�i��c��	��|����D�q[<��^�����g��B�8��9�~q;��8�P;PPU�n�,��'i[�JG�eD����l�z�`�������
e��0��[��SK�vi��Yu�3����Fn�K}9h�g*% 9!|�/�1�	�i���dn�C~%(#EH��J"4�
��2�j����4�"�������RG�����q$y3���a���������w�����(h�(����3h
�	�v0�zp��\�E���u���l���������NCi#7yk8�WD�����%��|IT�#��ig�c�r]�y=E�AF�p&���$��������%R0����V������uK��������;v��5��_L����\v��!���F����\w����N��5��,
�K�|���%�x�+P�4���&��8h��k-�W����bz��^���s,&���UN="��1K
�����KE~�
����*�5K���j�����=�<"�Q�7�?�{6%B2[�	��!��'L��vz$��N�����/��D�����wi��{��n����'YFK�����(��I�db�p�	�H0��%�f�A� �����8��V��B������q�!N��xH,F^��>�AR����p�50W����+�������6�;�Z'���+�N`�+�.q�X��d!@T�qNLg$mF�S%�q^�l���n�D�v���;C�����g�A"2T�y-N���%������<d8����y~�_����k�WM;*�&j4<x$fr�DA2���&���J������r���d�[�������"f�n���K*Ljwu���&��C�k����i9�!�nqS���fs��@�
��S���~_�x��7��t���u���.��K���4��l�K%5�Y�7A�N����S��c�h�I��atH�j����(V�g�Q9��p��"Zbt��U��(o"�����i�)2q�E�qd� D����	bVug5+d�@���n�������T�D��\E���v�RK������12DPg4��*���}�a
.����:o������l<��K��]!L�G��y������m������"�hK������sh!�"��N�<�}EV��Y�=p��C����=��fF���Q�}��^e�"�60;z*r:H�CT��<	��R��>	�q��c#&������1�4M-M��� Am��'r�|�PP��Q�n�LQ��h.���4�8l�AF�������s*��>11���������'����fh!��I��CJ��&w�qc�I���T��;>��
�iR���*��g�����	km	����4F��E���4���F�L$�$�HJ)���)��72eoTR`"l����4��&�ay!=d(�����YpD`G������4�I*1+z8�����4�!j-T��9f2���5x6��d)3����h�s�b��F\m���/��[�zlEH�~��W����������jr$u7�W�d�n @3�����PX2
]`r�}�JO�q;C&���03��8�$�z4���G6�;�T��F�����l$0�R�s!�"��Q�I�CiJ�T�F!���q!m�����*�TZ����R��h�3�c���Hx�8v���qc��5?o<�G����P=������D"��(�Qv��
}S�X]��#�7�<�\"�4�%��(�{
�?�� �d��f�� ��K��O��%{7o�m!&*�����9������E�iN�+������@W�.�/����Yk�&��c=��}��hl��)���	Q'�_<��i�i�"��!H]h�^�!�+5D��{�~�`��5~6�j\<|����[w��=d�U��d����������7�[�&;����
���r�}���A	k��m7J�Ej`�b*�'b����W����	
#iU� ��b���4�F�k����	�zX��v@Qall�����<j�lx���$���!�	+K��3h&�������(��@�������-�pkfF�r�;��M!�J��#k���y$u�gn5���t+p0�������g�����Q�F�v3�W�����H�7A�>i�5 ���n�6��$�>`'��k��x58��0*�*w=����:8~,ni��^N�zq`l��qu�������k \1`������P0;B\:�tB1��0�&����S�,r�3��OV0�>s�6+�=���=)p��N"J(������"I������
�����~q����04��H�xY1�*/��v�L��+f&������Kw3�F�n�}�&�`[������{-���c1����t���#����u?*y ���~���F�
�.�����0
�C���$����O_��&|�x`���%�E�}�:~#�{�#k���Hp�4P�.���/�v�
>T72"�}0���(�#�
����r`2m�h�/0������+����H
�C]3��!$exoY���v�q�u��5BH!^����8#i��/����n,a�:n&>U���;�2�;�6%NC�(R����$�v��8�}*Li�N��|0��<��8@�D`@�-�1�?<���#q���4��$���r>z��-�|��Ex�-26����cd����i`o�o��Gy!MN�;�����������[���[��M���fd�iJWX�\�=����� ��[7��R:-��D�RLCP*��*]D$$�0�\.����%-�u:A![<���J4�A�?d�%_��z���^B`Gxpk���1^,�ihb�=�r\0�~F��H�=��������M���"	�U��_����=.�H-�0vA��j��8}�~���BY&CD<OS3��+�}}^3Qj7�W�:&�/��+j�Ob((�#��!^��v��?D
G�Sm�^r��aM����o���"����'��-�;	�i�S��6
k�qLFwr���8N6�+	�$MVT?)�
�(@�����HV��'_(�s#G���
@"�)X�Q����5��C�4a���#C,2�@��u5���)f`�/�Pj^U5�;K��h@�a�6l�1�=�TH)���Q`��������_
�G�?����&yG�XG$�e�.@�O����_N- $J����t����2AR���.1N�j�����9�~����sHw�K�
$	}����ON1�.w���[���y(r���[u<��
�D�c�2�@]���S��i�|L4@;��P
��Ns��)�0:���D7Gg��D{X�Z��d^j0������������O����e��oT����$�T�'b����ojL�*�b������d�x���7�����H6���{��43�����-p�g�)��'����-��	�a�9c&��8����jt2SF���,�
�8���m�k}�u��/L�I���x>���������o5[HM������q�KB�Y�0ihT-�V@3�e�KX�����)	�K���k>#n�M������@��_A�#���FM���L��p������"g�{���}*g��h5�H��0&�K��T�t�����;������J�N�k`�R(2�M���PQ	�����a��J�
��m���pVZ^���R��fT�o�O3�<��h�+%��&Z4�-�H	3�Z���c�E��[�����8�?�d�z�Dd��M��d�~_��&��Rv.J��O���Q����Vf..�j���pmw��Zd5V����
��6~z��5��"�����
�=\��Q����~gI3;�
@G�;����K-�H��QT"�6���{AXF�.���H ,�q�=�(�7@�~s����P�v���{j�p�x!g�Jb�:#T��EG��\�"����;��&b��h5�������m��zbN��-<)"�V$�O
_G�O���w|6D(1��wtM������}���F���t������f^�) CIuxpw��!�3���Q��Xe��l�LYS��&����aD��N�������f�E�,T��}�����
=|�����ZI�m�j���\��+�4
e�4����dB�����;3faG�x���5���:��)��,�&�����LA����h�i���*��m�g���-Y�go�"0��~��`�%�`��g������S�
�#!�i��w�U�w�������F�cG�[
�������P���8.%#UO9u���uvi�n�F�R�������+2�P(�A��x�[���fM�D�C�GF�D�����/8�|�z�H6d�l�B������	n����I_(*#{cNZ
L��w.C���,�M��e�|JpR���9s��F;�l-cc��\�� ��h���i�����)na��U�n���x�	�����
�2�n�}���#�l����[�zx�~����?������
��/�q?�"�>�Z�{�����$g�3������@%��0���`�f�7D ��B���wA��k��e���������_w�v�7^�vm�
&k�_$�5���:�����Fb�������P�-��Y3���3D�c�Z���+1~�?/�*�
W�Q��oN:�d��C0���v�����_j�
H��Y�������:@J}8U�S�&�L��q��yO,t��!]��d�����@�=c���4�����8�$��x�$D��W�@�W�<(���f6����A���{��K#*�J.)Q�����\�Ci��Q0G��5�T������AS����������h�E��g*�AXl��&3��}��n�?��6�g�lh<b3�I0�d�S�����@��	��2�b"��Ib����v���@�����E&�5�5h�;�EPz��?���E>�|P��l���9��u�[
YE'x��������������nO���a����nBrP�
jl��*���:f?-��P��:���$*Y�����:C
7[V����ce��zpkvIv^�L��"u������FT�)QC��e���g�������B\V��	��Zv<��*?�=���F��g�F2�.
��D~s��������w#�/Y���%�T��JrR�*6�I����?@4�_'qN�WHL�1���=���������/X���:�':V�fQ�C�k@�����/6W��DK��n��)��*�Ft4rr��6�@+������eX`��g���@2�����Bk�WQ�6&RVE���	�����VqD"�K����	��B���Q��i5�j�=,����G|�*t{���@S�VwDK;���pG	hh�y�G�H��*�^5s��,���Td"��m��Q���A=�m��:������A�P�{~��������Ai�����[�V�~������K��E���h��6k�x�Q�A��o6�B�b�Q��_$����G��=@u�'�b��d������n�O?�0���,{/�����UQ�0����1oh�����jF���x�	"[�5K���k���S�n�e |������F�i������|&e�U9��������k �Y��k�?���h�*�@���5]>���p�Q���.����V��=�����g�US��������3��R��rx��?��t�P4d�J��n�R;D�&JFT�h��;�qqu��U��C$-K�
�lG �Y�@]����U���8G�����*c���)nl���M�����>�"\�P�h;����9�{.�����X`!4��j*YG��>E�����$
l�����"��'��y����t��������Lf��
��{�5�h`�5�>h����E?d�����`�#����H��06�STX���tW�v��G���c��:���)���g�"�������;�0'��m��!���vf\�0�#�g��V�w����������$�p)��-�������O��d��A�.���x�;9~;<���B�(G*���V�T�#�1�&�(�&\:��M|��R���-����%�h2@�1j����,�YA��n��kgU@'B�s�wV���1�EU���/7���tL�]z�19�tPY!���].�"]��+�bF��Y5��y������7�I"?f��@�fpc�x<�tFz��b[����";�
s~!�G���j^���1�%���8�6P��06`�A�-z�&=��������in
oSt�oq�,��D��9��:���A��Z��M�u.h[�B@���e�95�����'pD�	Bc	�	b?�f�4����3TO�hE�XS�x ���J)�����$���������8�q#w�
��hk��(m	�#K����N]��=
��o����(�'d5�'F�������1SAd����/D����]�v��t��7�A�@H�����
�*��~�t��1Mq�E����r�/q+�UEA��d��O�����X��m��M��t�!Pn��l�s��/������D����N�#��d7�}:�L���d[��	�&3���^��`����G�����������������O�
h��o���6S�|�/��d��lQ:�3��q?^�ZQ��������=��@N5���X�CWa�����Q�CN��D�D�t�3"�FCE��J��Z-�I������%Pu���iF�g������j5zhx�V�C"]������i~n��/����+���'K��k����\1�"��,���.��R2J�"h��.�{D=�g8�q�5����#��<9A��"�`�;AYM����h�a��#sL4�Z ���?fi#�\��������M(�������,�T}SHO��a�&���UQ����L(��V����j� �iS������b�
������=����U'�����mV����ym��m�	� ���EW���2���i@��M�x�����
r`avR���p�:wC����G���%�������|�j1Z�L�`oc1��;Z.�W���~!�9�SPC����[<D����wZ�8�G�D��3�;��{u{��z#�w�~T����:�X�.{b�oV@���������8��n�F#�_��F�����);�F����_�`�����go5'I+?.��j�,����R��t�����Xe����<t�/dw�_0K+}7���b7��J����Sq���<�d0NB��c6�/:�Dd���}��zO^2�a���.�����!�t1�X!n���p;��B���@9y���S��-Pp�>�q���1���`�n��%�k�B�1'<<�x�Gk�!������B� �0�=4^���'�H���Jg��h�����2�Zy�g����e��OWF�G �#��`?L-���=#���d3s>%�Q���S1T�;E�`� ��Y�!8�5v�j��� 3UMrn�"�/MhFy��r�3��<6�tLs�i���M�m��C���&fl�$��(5��A��V��%�����'��MD	�H�����bA��((`u�a�����@<9�a+���a�vjx��-���A����4�_��.�<�
n"�h�/i��`P�(�=:A��f�h���'�A{[aR!u���
a���X)	-�a��1�c�s~��E��3lQ���cjVx����}&��}�&ML�o&���4��A3�GC��=��~�a�\�/�k]W��S��-�v��"
�"M0��
��Cs��];�^�n\m�3�FH�H��n�o�lZ��8���L�O��jGj�(T�u���!}�1�@:Rl��l���Y\��_�T�'�>���p��X��;;Tl�wt\N�.���4V
����\��F+�����A(O���v "*�H�k��T�*~ ��I?h�	�3I���U���fF\O�x����'��W�~�f�;�zXSx� Ry�N^2:�����������#)M�����4��Ap�.�/�I�s������pL��1��bF��`�iArP����l����H�����
u���l@����q�oW�RR��VO������C�$��D����2b������N��N�O�R��������^�G�f��P���U�x�Y��Ulp���Vup��-���a7'�%�!@D?�;F�q�������*'o��f2����852��n\��oHB]������d�!�*7VsJ{��0A��M�l@WM��gZ�SA��W�/Aa�z��0�e0p�`�X5�M���5��@�$��� 3����O��)O
�(B��(��y�y��63�t^Q�qi����0I�@�y�`�B��Q��H*��ZA|���y��
Z^������[�5
T����8��8��!)��}.��c?%��U�4r5Bz�x����r���h���u�.A�Q�`IH�KC�6���j��C'D������G�A�mB���}��}��I�Sn��i�
�Y����]]Cvv��b��eT�7�^T��:�wc_"u�2����	��}���i��	����y	�;�XE� �������N0�<:Nw�n�Th���Zg��E��F^�4Zt�tj�X��~)l��������c�m�'���s���?\�F��K����UNJ�4�a!�����x��q���4��rE��C#���0IB0�E��z��0�7�i�JW�#u�V�S1�P�'�Us |������E��Er@tnLO��=�
����Uc�N���\��������u��ZGd�`�}���Q�P��3����R9oTx���
]��b�q�v�j�D������v)
`mdTf�����+v���# ���
�����r�h��
k
�5��y�H�
�ji�,��~!Fq��S����x���I��F7e�YS����W�@�M5xY���?!u7���AB1I�e7�D�������x���y7";��d�>�\0"Ilm��Q�vp�9�������|��sc$Z��#iih#m����c�������Z���(9����s����	zTxe�cL<���$A�3�]������<"������} �:�Pq�P�l�'��Hd]do���Bx`����>
��$J�6�}[��i���J����`%��n�����z�r�]`�8&��9��r��J(��*s���s�-����(�j���*�
$nTb5R;cF�b0Gq��}�6d\h�BI�������,9		�%����N2M���x32�{�T
�Bl#��e�0R���3��M������f�}��xS2��A
F����,��w�	��G�������.E���@2����o�|���_k�vW�&s��]Tt5*����CC��^a$v!.�f:{F��J��L��mO*�m�~*�)a:F�9�_[���ym���LnK�	��� �!x)���x�J�h��|�M��[;���W�v����yHD���k�����t;s���
���"��������@��q����M��Sx�=v�sQ}�3����������[���H���9�v�!{��.����2���|\!�8��}�].w�%;	�x"�'��-���O����e����b�=���f�v���q���8��.u�p8��-r�������	R��|�
�e4���n�[$3�L�%f�Dq�d�3[�LF<�n��R��t������W�z:i���d�b�)(��`�oI�f��g�Dwcg��j�����N=S������Q�Tp���l`�C
�G����q�`���v�l�Ll�5vj&#T��2N' S������)]@@�*��X�.�
W�����}r!�eQ�v7������5ed�eX1�IY���p&F�!�I5OE��n�HSl:	��������5EH���1��=9��(G��
r�a �&�=3dAA�2g��&F�}���5���TX�����%J,�G�+[�'������������,]�Nxg��#����P[�HG�z�px(��������mG���Vv�5�^O��~q����p��
�+-����D��={f��/b*���������g��-v�0�'��(Fbaf�ER���3����C7�~�������kR(��9� j&R���'��xv�4���tG��RP����6b����

�-nr����[�}�|�����	��O���(��T�z����Nms����������H��O#�K4+�.l3��Wd��
d��iLV��s<�M�	�X�CnQ�H����!�����L�%����|��K<��Z�+��IZ$��m��s1��i��b�A'��#gO#�Q-�|�vDM��#qfPH������$�t$���g�No��o�6����{�$���M�����>Bb��&f�F�V�
�.yd�h�Lj}��������G)� M)?[Yz
�Y����H�����a�{ �`M0��V�)�D����}�xG��5��/p��s���B.w# �O)���V��z�+c����rP��c.h,�����b_l��H{#�AJ���#�\K����Af�dH��8���	�&.�c�����lLX�Cm�,��_����xgU�8�}�{�.xL��"�~�,��h�\�#6�p�O�$��u���1�CmC#o������c��FN�����-�y(
L�Z�'V?=P�>��O�-2��������@*�!j;�x��4��";-VC���R	0����8P������n	�����6�����*����A���c�|j)��	��b�-H,�TJ� �t#�E�4#���M��*��R��`��:��jj<�H����
�m��K���(kl���^�<�2M���L�q �vs��i$*%b��&3����bP��H�-�/h�U�K;)�d��������I|���C�
8��E����I�����u#��u�S����Z�H���Xd��e��:��{[�}h��h��(E�KBe�]��}c����H���BH��Y	e�<H'�@)�kP,w�?�Uh��:%��7�Y��x�W������(�|u!'j�H#�)�Q"E��2������l�D�/!>���@:mN����I���t��^�,a��%�;� N�`�5Ct|���a\�T��gDm��p�����5�z�:u����J�,oi�N����+��
u*2z�f�����FP�E�>���������[�I<���\����$�O���Fs\��\�`��U:��bTN�8�t�5jF��oI�On!;��ay`�f�p� `�a��|4�*���1R���6�^jK5eSI�E���O�Xb��[5:.:����������'�>����4g�P=���Ci;>���JiZK�@��R�3�?Y���L��Q,�K�Tx�	/i���(jX�N�9�	���n���a��h"�8/L��N�/��&"��%����9��7��^jR���Y��2��������|@����2�)��1k��XD3j9�s��Iv��I�Q���p���E�$Wf$�e�1/�i=�h��k��Y{����kyH6�~�C�W����q���sG���Q����7;��Q�����2���rG(�Bh��SRs������1��X�U�p�k
o�
��fA�9�Lx�Ze�*5:,�k����B:�-3.����Yo�GC���{zDD2�;����[
�4('��fU:O0��<�]�-��f)�wu��
9�L>5(�c�7l$���2�jS
'rq�u���9��fT�C�we��������iq�N��}/����t��m���Wf��D1I���������
B)�����(3
>��"�J�,��)����L�p����\x�VO�_Jrj�3\��U?t&p��k!����P�s#��i+���o��������/����*���bT��-��	W;������2��� ����U�n����l��452��hHu,e�!v!"�����"�����f�����"S�}'+�c�o������[r�2�4�}�4N;Y��47kZ���~���m�+���e��Y
������8�@_�q��B�
oI�s-�"L��T�� 8F��*Ru�z����O��mO���Y�B
e5�Q�����I_�����R���l	K����k�������.�b�}&����tM�a0`�U@Dh]c�|�x�F@�=��u�e��������+��R1/��^��<��Bx�q����Zz�B��|�t�s�7{�
!��x���B�����@���WH""U�24�Y�<�8t������du�����X��HY��Z�N��X��?�����2u^V�;����<�,2����t��QN<�YiX7����{����=��>�W:5u}TG(*X\�CzF0�z��L��"@f�?����/����w�L�b?pT��e�|n��q�BmGd���S����zD����A
�U��Qa�����^s�"	���X��woG`��[��X��D[��5�@(�Y�tC�2J#��:*��C�3D���;e]#��������c�n�a1�E"�1��2�3�DELO���������q��VM�$1�������	i�#C���y����`.�U��q"O��	nv�J������P-�
$�4W�j"&M�^��#N�k2�WWe|i����V7�9�7������x��&]hS� ���Rp��� T��K���5;�{�z���l5��i����\��=WE��a�;� f�U����j����r�00�ain���+��R���f����3�H��'���:Z�+6#T��+�<\&��`����{��P(>����ixlt��H����qd�R#J�O5����&�����,�I�\�ck������� m��������U����aT
i�2�mG�����)�����O���q��IQg��
�)J��M����=�/���_�Z�ZNn�+	@���]�K%�<�]nO/j�!/�b�=��%6���)1�9�]B�js
"n.<i �&kx	����@=dT�$~+������-#
�:���E������O�Z~���!x	��A'T����^�#�&6V�#I	�|��Gd3#MC���p���pX�$3HT6�p(�xM"���Z"u�u�����A�?���n�7�������/
���q ���c-���]�|raR�jE>����"A��CV����A�R��������l=},l�44[���[
�hQs��8�!)D��eB!�f����S:������I��b"��Gz�T���f��X��!,�8"JhMv��pY�M����0p�H�Ya�����b�^&��9]t�����	�����'
�����bj|XUnc���w�E8z�r�g.+3�(4������������]|K��	~t`�Lp2�}�ht��������:��>��Y	��� ����!�tM�9`������*r�`����
���r����>�~�/����O�i���8:?����=D��"�`N^�H�"�6l�pT�D�F���� �qc�&��@���|Y	6�mry��A�;�#?���2L�DH_����hm�9�����T�����D�Y�'�e=��E}�0E��^Z��l�A���f���W�Bl
/��
Nw�e9���a�.1��Gg�+�_)��Fc��M���TEq@��h�|v.kJ�E�������>x�W���y�u6��.B�TO7�lSC`���	2b����-y�� m&�M�u��q��zx!	�����zC��t8�PI!�f���U��!C����BR�]���D$9sF(CcED��Lh
��j��"Ip�#����-��C�-�p6��N$�`U����zg�]2�i��ea����0d4lU15�����?q���Fd�����z.?<��GPB��r�kZ%������� =��<%i}�>8i!�/bf��������/J*���NS�W
��nu��S��E�<�DS���W�b���n�����c��Ssd�H&1M��a.��[�h�5����*T�lL=��eF��k����)]x���Ai�!4�-)n�xH����%2�x�|L��&���V���.�o����2�!h�����2��RD>�0����&Y�K�y�i\��|\�X}����CR�A�y�Y��p
�
v��,T�{J��!�vV��7|)��K9�X���fk�]3	21Y)%
��K���^�|��<'���x��p��l��zm��fY9����h?��c�-��0R�����M��|Sw�/a��ER��p����s�*\��4��[��`;Q��M '�	��I%�8��RC�j"O���X4V�����>5�"�z���
A`G0��y�2�������B�G�1����K���$������q�|C���kxX��S����V�r=�Z!_��E@5�z�p� /V$)q�J�R<K-��Q���"f��G�x!_`t1�`�K����t�����L��S�7Z��U�!1a�x�1b�(T�1��Y�����
�
�"���AV!<�am�G����>�Ro����d_d������on�^h������t��6�N���}�<�-Lcf�Z��)v�<(Z��� ltqI�d��r�X�}.�@Y���5Va�g�}'2q���{w��	 ��AH��!�*;${�_���� �0t���r;
����:�e�?����$�u���(�&~-��7�6]t�l�Bb	BpEBNnM2����m������Gx3~�*��hZ��"J�z�PgP� C�q�P���b�`���r�&�Ny}���
 ��;�M�Hx�@����9I��:i##�L<n!�/���R^1�����>H�i�`*��M�Q�s�=�J�K����������U'R��uoz�SWe��*5����m�W�
2��MP��~����'P��]	T�M�.�	7Z�X9�F������bI����P">)�JhLt�"nPR�w�����-����U3*&;v��	�H?�y�u��#��H�P���{�!��dj����e
Y�j����p���d�#�C�?��/�f��#Yg��VeM�G@��I�p���S�`�
NV�~x] *�?A7$BBw�U��Z�	PcG��}P�����]zfQl����
�<���U����+H�3;��\]�t����F�4�l��5,S�M��p}��\�_o��@��\y������!��3��!��S��M�=�Q�1���4qW�d�c;9=�"/�������?P�Gz�:�t�����MDE�f�$���q�����������s`�B}��Q"a����aKjNN�����y�Y�2Z%�W�����c����#���g#/Q�$p[�@~�)&�}[R�j��������5������=M�#k"�b:���j�F����p�H��jTed�7���Sm7���?[q��;��:�3��r��v8�[
^��c|X�����3o��]��d���o*���#�/U������Bx4�aa8�����A��$j
�2�P0�3�:������[�~p �d�h��-���q�[F�q�
�D4���X���VZl�Su��6����37S���B��`\6��L���
�Q.�%�wT�P;7`,�I����$��I?"!���ym~�9f��
�E�'��,x")r���YA3V#��0[f�N������#��+��X��&+�r���/�3�<��L��e���7WC�4Q{.�<|��k�3Rh
U���QP�_�O �4#d������*�ag#��K�Sb��`K'�W��4�q!������:
dNx��SV�H�L����J�1H��0�y��z�L��(�#������f3Q��`J8sQB ��IE�Od$���)!X�9"|&���;�q��l`@�M�Y��?-:��2�wf!��Y�(b�@.73.bh[G�J���4�����E'${XE@+���}}���^|���'��OP��4b�;��c����i4uHf���������3amOPNB��X[��P��� *d����L�s`����#���:J��f��
��)f�d���^*���V:x43���8���9$l��q,7���#~�LR@8>�j�A2�	��[.k�j���H�_��S*�����Zg�w��T��w$i]��M�\�I:h�e(qK����H�T����f�B��}�B_�0��W�a�S�8U���D)�^M�e�������Zq��R���2����%>�&�	�p�C�%\'�#�oL�!F�DE+�@����)�#�q�Cj���@6�����6��L��2~|�0~�����1�tk��>����tlY�E���1��Z�$�9����JH���#0�Z$�B�iQ��L1����)�x��gu��x����8i��:���:����m��`[�X�����z��t�Y(��(���>k����:B�Q��k��x�
WG��m�{�w��fp�4>(�!XeJsz��N&m(5]p@�#��x�J���=$7��A�	����x����p��1��8��=�;�h+3@<?��z��qX�
���,F���dqQC!�$�m���)v!�A��q����{�7q���j��j��_gG�:�q�Z��D��c�8;����*@�o��v��h����
���M	���!��"�
x:�!�������2�t ���:�
/B<DJ����;�JE�0�dQ��S���ipK�j$����X��>�^��02���bH8�L���v��3����;������eM\���6��h� ~C�."�s	�%��`f��p�X�.D���,����`
��	m^Qg�|B#(��*�M����YSV39��v���bv�&IY ^����v:��q:cG����P�~�=H��ww [E=;E������3�")"����
UW��Yx��,��1S����������E����0.�k
#�$����%��a��-���~���_����_������gv���^~�_~�?���������?~�"�JHQ�<�������}���[q*����K��Y�\�������_q���W}�+o~���J���M<���������y��5���q�������/������7�G^~�_x����/_���_������~������_����?���!���y��~������?��?�1~�O�����%e:M��_���?����~��_���?�6������������/�_~��/���/����e����U~��c��9oJ��k>�o[�����"�G�n��O������E����|��XBa	_��,,������� |}���'��w��u�n���%���������x�)�����%}�=^C��q�����,e�^H������������q��������?_M$4q�,H�a����~�-'�s����~��w����v<��������JGH��y���g�����'.��PDy�c���y��/(�A9��% �O]��	E����������,�O�$p��S��g=��v�����|���62�Q�������|�m��F3B�/�q#`%����w�������7�$�����A���ss1jE��?��,$�LP���_��?�/�l���[�b]��N��co����X����{�����'���P��gk1A��b��1��j������c���������ao��>� ��/��|w9��(`�?[��`o���e��a9���{��m����8�'������Bv��������-g����2v�g�1���r�?6��>��7�����e��������u
h���L*��'c-D\��,\�����������������EL���c��40�k�����������"���)e����j���/~J��1���Y������3�p~��o�������������,2������m�<���,~��if��S�[Q��Z�&�����[�]f���5,������P�������������Ul4JZ?�%�������o1.���LN���[�����LM�����4yS�hX�Y���������6�V���of��R$�DK����l��~
|\#���t�*�CqJ��=��T��z�7|���`��YE�
�^x4H��_��H<��������gk<C�O�?����O�	Z��y��/�=x4oM��&|�zr���a,^_X����(�HB<|������8CM��.��f! @��$��*C�z}���$x|�:B��a&~�+d��
(a<L�PK���f�@L[Np�4<�As	_�b�H���v��t�z�.�s�5��e�*���>vL���MhM\��0�!��Z�BI�I|�����CyG�d�`�������"���	M��c���7���-�Wo{��S,0t�m+Y���O	F�u����0
�A��h�J1��dcoM�=�������F��d���_�h�n�u�c�t	(�8�s^�bA�]��!E^?��~?<B�B��$r�
�#��W�����"y������0/��������r}&��B�vo�)4����g�T�+s3�~�7�*�~x=YW�]�Z�#Xr]���P����T����
h��Fk�u�p��o�B�I;�tXuX����~�3�GT����`"�����y��1�a�U����1A�F}�I�����VE��br���$1��o?$h�tl�t�@����}���N�`�YT���C��G�k�n�+D����H���N�G������)2.)�&H6�0"m���������fTf��s\������O��������RW������e�i��f���O�1r������4�5����/(����pV	�������@���o�}�P��1M���&�8 ��:�ms7���I���+��Q��F�;��Q�B���~=���0���(\��%s���.�"K��
c6P��
4��6.��x��A�s{	����������H�,FB<��#�ewC�	����
��w�3��=y��<z�����@V�$���n@�j`���~R�MX�msG�6K��8��x�o�'7}GG�G���1n�E��� 8;Zk�=�{zJ�"o��ThD�(�F���;���f�����c�������eQ*�������������|~����E�
���U�o�=Oy%��<��aZ8+Q��"6�l�{��&�.<7������	�~�Bc#��xN/
��M$��b'V�G��_�����~�+��
�A����qD��?(L�0�4��R�u�2H�NvnG1�����h����O���J���N���.���<D�K��=w ���I9�[���]C	!���@��
��c��r"V�����~�	sd��!J�!^#&Ah��R!�-2������V����W����-c����&i����<3eHh��Xu��3����=�`X0�xL�p&����BW�'=x���vqM����t�x9��i�.�����'���'�1�%���/��bD
�L������<�`���������/B��`�������S#U���=�0l�����R5�3�l��7>�����6�#���J��\��>���*IA�#�l���QV;�I�b��3�97�y-.	Y���GID���%�1f�r��5�p��DW�KG����������>�{l�2��	H;'hG[R�^�tGh�,R��@s1=R&�~��^��$��Q9����t����/i��(�5�32�qO�P(tG�	^��u�@���-�����$�J��������P~)��"]w�AC-8�x���XH����8���h���������{(�8�Pz�����4�#�#�6@$�/�
*���D%~�{uN�i��U7�3�$@qC�����)`"�@�����_4���������\yJ���fneD�bsm]+��H��W��9����:d���+SIe
���r ���Pv������\������=R��47o=
��z�7>^��-���9�Y��b�"� E��T�k����R���,T���5�5G;~-]<�l@Hl��5)cIk�nd��{����0�ZsC
#��{7H�!U�f�H<K���~����)[zj�4��{b�0���uu�R���5Z�NnM���������hq���~�|(#����>�C�B<7M=�364��@��N�������a��Rn�F��T�O5h8�^���Kk��TvT����7r�h`\�~5@�R���xH\�t�b��v���> #UT�-�A;�%uk������J^@m��W\��c2Y��.�dn��>:d�jLA-L���aM
7�M��[���,�,�.�LQ>H��)\����4���#sY�]����\��EI$�)�Q��
6x���7&��\�U��)Ue��t'�0e�2�o�x�U�(��k�� �R�C
_m���z�{�A�B�Hd�s~K�P�B�Gm������U�VT�gK�YS�<�#�W5���"1-���m�y|/$8��00r����W �!�*�p�e��Z0D�f���US�+��K��x��D�jD,��*�Z��IU��M)�� ��[�<L������*c#MMCK����B��tP�P}1��[�,|�����M�H�s�_�R^�7����������������\��
���1�q��	M����#>�{X��IF#������>[�v����a�X�2%����p6\���4�z/�4M�b�d�7f"2<p�$9���+�l}�f�-n�
���E��8����
9k�C�d������D,�`��
�/��)�3lh8uu����{�KKetI��*����,���T�I+��J�J�!%P��MTX�"�n��I ��yv�]B�Tp��2�N�n�H@����i���� ��)���]eT_�q�W/��@���b�(��>��,����Qb�D�2�������]W@�
�`�H���U�Fq��i2r/P3M��&�f�B$�	����tM�'`�0G�M���i�E�\��
A�����
W��gNJ#�T�2��5!M�4�u����:h�v�I�{���^\o.�����.j�����?����%�1s�FGu%���^�64T����"!E)BXf�������2/m�*�`�i�=�L���(�7o��e�=�>4��f���A+���ImKb���U������6QC�������Q3N4�A�h���@��kL��< �@�$����T���A��u?�=�-������q1�-$Z!Q_���E�k���)0�
Gw �x^�	Fie������L�G#��		%Yr���cusS� �#m�z���&��w5Ug�*�<2����R�
��B�2���Q��N��hd��xL�	6rg@�l���$4�j�G�B��k�K4X������������"3�3N$q]/�3di�T�,�`��@��4���#oz�B����G���m�P�4A��7}G4���A{�	]�u��a�����q	~>��;P1�?�&H�J�d�3�X�����/Y����B�������lI���lu|�(�)R�(��(���a���D����<i����Q.��>~	����.�����9�V(�	i�������X��-<�=�B���vQ��I^��^�T�f��85��!����Z������BO)'��T�,l�"�\G(�S�}�����x�H!<��1�3�������y��\",f`?%H�� �Z��1��V��)I�-�a�w��#���l����y�I���5c0�P���F�B������uc��dh��������p��DI1o!Qa�AR�U��%xT����u�$}���>YN��4���/R �����n��S��k�v���l�]4����kr��)�fn�P�A��� y���8p��:Q���2�^�|���yh>	Q>��0 �8�(Jg���X����'9���?M��l
�G��W��:&��5i|f�~�$C�T��{�]Q��
������0%.R;I���a���� 1*�B�x���&a�����P5�8��e��ot@����J����
�s�'b�����������.*|c����8����VP�K
Z��e��������d6j��M��������FN���F,e�BZ����qm��������ECN�����?+����D���(7�@�$�LK����U��f�b�hR��������f �&�2Z������YD�It��C��H��Z���J�u &��CF4�
�x`q)����������$(�W�?�pSMxB����R������z��Eq�?
T2�d/}����	�T�PE�;�\��
0��K����Z���v>fHh�-�A��63	�kD��7;H�#k\���!��,�'����z�}�@�"���h+�2�;�+"q��S�>��L���^ �7��7s��:E_���	�����$����������R��z����l/%����Op��:�]��t�ZW��F=�{��-���]?�mMn�;o`�]�1�V�
G���8�:���q��,�����*p��4:��D��-�,�������^"z��Dj��``up^��Xy(�-d�M���O���@L���Z=��@,vG��$�4�wh�P����E�����5���������o�UI�������D -��/2������m7I���'���}���DL
����>��a���������I�WcI���j�����=�p��a�����!}�)dlN�vfg�:a�e��$���*��������S���
D0��hDUU��d���e�(FO�X��f�-bc��H:�� ���O �H�����xQ��wI���w-�l�����8��:W.��Z5h�m����0�^��C�9m�$��E��<�M��7V��G�_���f���LI\��]�"������6Mq���q#���Y�[��p�L��
4��^t�(THf�u��^B��88�EJiw7�����]$�c����3���v�MF��#�w2#�kjM��49p�����I"���5������	:����WB�;#�i<������z�k�����LT�0������8�_~���!=j��A�����4P
���TyL��-k�]|��������U������#��'~I�~QI,�{@���tT��"����c����r��I�i\��!�����Kq������WlVZn���	��l�e���H&��0O�s�R#���������)��4I�MlN'���oF������{P��L�T$�^�����"*����r���eW���[����t���'�C��	�lG+����
c'�bF�L����9��5�T��$�3Q�bXm���2�������M�a&���������K��Tsh7��`������k2Z�jt�H{;U	��+�Qp���!���f�SDM�	�?�1�����93�j�����<��
�B�Q�q����J�2<��C����
�S�QG;}���1��W~�T�=6���kT��BC;!��Zk�h����!+:.��K�m��s�O�mO��X�8r����I�c��7��S�h�,�Ll����R
G�a�
���k�t��K�H�#;NU��}\��C�?J�-�^L���[
@Q�������^������#�;[�;���-=�:�����F��S
��^��������P�&����w�wt�t�2^��!P�����Tu���-��O����]iBt���?�A[��,������3N�mgU��W\��V�p)7H������
3�K�
"S>}��/�o�h�Ol�i�����D�T-$���
k�*N�6�j��;��U4�� ��`�B�{������WE&��OK��[t����#@f��&�E\�@5�8f�^`����a����4��;�"�#dPP�������	���������8p�Y�����o'smo�^��h���D�m�����*��R����qoHt��k�]JA�s���s�� _8�I����������MP���Bn��y�>�����q�%�v��_���j�>J����V�[�	P�s��r�kDl��D�X(U��9�~A9��~��QXGOCEC�6��|av��U#Z�kwE��"J��"AJc�f���*�Htb�g���v�G�����	���HG|\t=n;������8�L|�e�p�#�!��0Djr�:���]K�T�_��x������ARe�r}�����EA;������b���b�����z��+��5���	�����I�G�� ��N�8����OT�AQOm���-�j�tQ���ob���=s�\&-���K^�v�
5��S���A��z�S����:�]�+��aK��@.��T^�I7�A,V9+�.�_Q���������^�eZ}+31��1m$�W��9n�e�A|�;�eE���q��~����
f@
)���
�����`�f	@��N�b�
L(���wl!@ev���a$��$>�q8�g����}���[���)�@.�����~DE���r@�n�U���1H;e�feIg���O5A�1{%\������"r����0�>I^i���2D!�f���"���X������~���<w_w������1������1���p{!'G������#n���/f�q@%���b��{'8���hW��d�T��}Xv$Y�K	�/r1�3*;�?9��������A��h�F:(j������"1��']s�_�<��"��_�9�AU�M�K���CS�z;����u��"3E���,�HX���u"��^C�1���/��t��P������w�*C����P;�Q��*�{���~\M�EDR�FUu��3��+��B�i�q���|��>L��_�����iw���/�A<��U�{3� pD�a�����ys�6v�l��8X%83P��
�/q����I��o�G�T���%�1X�LT{�������6��w��q�����*��6����\MmZtuUG	A-E\�H�,��QW���/�T�&��,i�$=�l��|&����6.4�����m������������!��i5mm��8�*)�h�P��O�O-����f�������r��B���'�y3�ld��q��H�whNz�7"�]�L�c��\��a����1�K&	%vU1�O�(����MR�A�JY�,�?PV����mH�F"ER!���jQ�h���</0�x��1�X���Xn;)�����4��c�L@#���7`�x'`#L��	��8~���z���m��d���wU�"�(���<"�q��c�1Vvm	&� f�z�7����}?��gt�n;�C�8�����H[l��)��C��)�,*��R����&���GH*k2J��2gGw�n�O9�M������p!)��+��8r��!9�R��n!�����&��N��6&}�A���)F�k���O��R�K[v0���k�^K��v(s���=�cA^`+
�h��jHh
X9�:�:�.F�n����n�$�u�s\���x*�U,`�1D��L�D[cC�g1�e���H��/��
T�h��Z���$%c/����t	�����r�����d���"�L1������y����Xd�2�3��j0�6Mf7�'�3��~B3	F�@��Od"kk�
=����~�GG!�N�~���j�B��)~�����
[�	����j![�->�39+�|���[t|E����G).��������K5�3�N��C���{X��-�k���y�����6����>R���7�&����K�����'��������GH)bXDS����Z���S�"H�u����
N��F�I6G��1h0b����\�����+�J�4����S�p��)&���%c�ajm�vqSi��Ou'w�cq_+g[WMD����'�	&>���p���l�)�%>�+6��2�v���	�����y���$j�7]��!>�l5+^��a�2<�UZ���{<J�_��2K7���!�'7�e�+s�R4qsH"<#	�3R	C�����Hf��<�2V%T�;���$����uC�q*�8��]�ak�U��
��}�;���*���! �R���t��62S����f�������ZZ�<>a�l�2�����r�.\f�B��L{a�z"�����K�N}N���_�����;P���L'M����������U��\��)���+��4��%E7"���``�i���l6�P�F�w:��D�5�|��p�
��U���s�I���x�pJ�/���/��S:%�I���E�nL�����{��6��;)?���l�<k����\7Q�3��}<$�������Fd�CH�@_T"�}[\��d:���2��
.���A��V����^���a���� @
F�.�(r*&E���O���tV�����p�9 �
&��0�!��Xy�:ZQ{SZ�C��e�N���:����q��X,#I��E^jG3Y+"��+��j;#������#�B������#��J?%`:�!b9���y�77Hm��������J��w�l;I-c��m
?M�'#���y?���X@]���~�7d����������g%���{��!��,����|�m��
6'�#��D+	K�a����`U�|K��b6'�T�?�";�R����D!�@�kI�a�XZ@E�_��	���S|2�x�G>��hC[�O����O6�:�������,�M��t���
��<: -���|DB����;�3U���-�)&5�E�"����o�k�n�1�	����m�q�I�6�u�����n�+�D��Vv"��������������<��g#����A��M��L�9��v���}�r��sp�y������������~4��*��;X�n�P
�_���v�C�T�|�Q�,�����P�&F�
!~I_a���&"�I*74Ld8�2[H�Hx��}GP�������M]���G���9�5����|w��H�����"��j`����w:�y����e�A9t��2�\�W3-��_�W7Dh�
^�2L�H�A�A�Bd%*��y_�:�w-g4e���b|����t���*�[e�Ry@���~Y�Dl.�U�c����@u�)��e@�G�J�@������3ZJ�>��vE	{����t�b���op��d~��'�����L5J$���*��%�p�;);B���2PI���b����SB��(�G��)�M<�r��\5
0�kD
�I����*�6�hr!D��i��4����.I�v�/�Q���-�����<-�+�8��u�F	B��;"��M|Qd$��P�j���a�+��mp��z���dP���K�b*R���W
�������C��>��5#�<�,�>��+�0$�bZ�4@��{��&������iGO6cB��`F�J���->8D� ��K����\��(���I�L_���R;������-�~<�2	��kDhU�Kp�{�,YRtJ����#s�	�"��K��s��S�4
��<G�H�;dT���u�.)u���o�-�w�mf���=�� ���(
�B
����q`
��h�X��]�VB,l��`i�����x_����mC0L���!��B2@�al�x1k��=�d��`�bnG���K
�W@�;e����A~�*��5!1g��}�����X���u�d��48� ���4�(����_m�(�h|�4��C����1|Qd�d�K��`��
����8��f��;�O������V@v��D�<}mH.x��o�^�Q���r1~nA6_^$4�a�o�Vs�(t�J��-�)�:��w���4g���5����g�1��K�(�DB�6�������;p,��!�7$�-P
���[;�K���)Jq�m�����e��:�:
���&���8���[I1���M�
i!���$���4���:w���a_�\�b���c�2�-���\�C"P"wE�L?��E+j���`��.�u���D�%�u�p���c8��D�����g��|_G�������;��Nd|�����P��6V�~���p.2���U��=9�cG�c�*u8���V�DV�
��d�VAPoXw��n�D�1hg3Gr�}�N�(>ta���M^\)���sO}�B��?cp���y�F��a������9v|a]����d�4������x��ar}4�;��2`c@0�M�F��jpk�X5M�s���+!�&k-����\i�HK�������z��H)��`?�t��Up�t<���.�uF�����c���fb#Ob(8�4JI(�/c<4@��h�>S�xG����sM�xB���9R�6�VW����<�K`)~�'%������\x��������@������j���9��Np��WO��q���
2N����^������dE8���t@e��������������-�#�����)xH�|��(�;3,$�����Y���X���a�a���^����K������OR�*jQ�!� �JE����+��|T`�(�9��}��T$'�
N�&��9���/�����bf1\�GZ�{J�Q�&w��p{G?-������O��\�T
�z����a���]0���_%t��HCh�/�8���������NM�^�19�U�,�����2����cP'�C, ����"�da�a�;��U��u"��&*O�2j����>��N��3]?�AM�O�$�z��X�r��|��U�P=1]F�UB#�d����1��;i���	`���hX=a�z��>k��j<&����D�v���������������j?�	�q]{hW��)�[�76����|������}��D��f�d�������4x�D�{;YBaw�Y��u�;�t$D�����h1Z4��|Ed!'�8bL21o���
���ZW������Uo)�*�`�j�]H����}#��e�=;L��N�	�����<0O-���p���C&�{12�@K��9Ou���(V:�����a��|Uz��mb.���=G*@mm�,q����b$��vL`�p��A�d�4�q�Pq��d�dN3��e$�d���4�d;^
`<g9��a%~E)4pW�a��eO#��a��0Hw��I�?R(}XS�<+�/ I�r����g9#�����g���9l�����U/q��w��pHt���xVj�L{�kW��A��(� u���M"
��l�g ���IAD)�=r;L�M�n����i���XE�|$@�}.�O����Oa��E��l�������R��c��D%�c9�b��G�����w*����t���|`|����+�2V�M�5�	���|Z;R&C����E=����7�`�p�`�l�.�{{+bC~d���F����8;�%;��:��5��0�F3)l+B3�����-]��Ra����[yp�
�P�pP����;w�Y�vz*�}��IC�����
!�h��
�'Vd]��d*����}C���^f��)R�(�x�Q�������&C�
���	�	���s����H�|�x_]
;��e�F@g<�w����F.6�h��(�R�;�?Y�uhm���*��"e��eS��z�
$�:����V}+^��E�BS�9t�n$8�R&$q����������U�IV���	���+$cZm������'*����"��2M����n�QQ����,J���q<����,�R����o�A�w�,����Q���YH��h�+��>����x�
��!�T��#���]<n3��|F>���"�e���G%w]�'�h����L����vZP{W�����Lju�7��I3�f��[������j�Z�N��;.e?�1~�x�iX;����x�&3D=!��#u�����^0Y e��)�hA���yl�*��c�>�����	�~�����
�����*�����d��D���`B�'��%�x��s� peE()�Nm���-��az
Fy�I�;�DaU��4�kQ��k���b��M�x1;���Z������Afy+W��l\z��	�Q��tUt.�4i���
tE�������S���m	d�����0�����0�L�B��k5�e��R_\x4L������vE���6��������e=�V��)>l�������!���qqS"Z7�lO!���17
c �j���AT�L���c�.��t���F���;�#���cyHX��S	� �^3���rC�S|�E?�d���t�y���dP|����$��	k>UU:�����������pr�G�/�p��������6c�
<QDdA?���7����p>sD^�41L��r��<�<�w�`�3��qy��i���D��Jpc/2�t��zD��'K�0��D�����bYX��9�!x�� )T�P���I���R]2���Z!0�c����lgV[�"���&5�YF�N^�ca�u&�����n%��qs���������H��k#��l���[�o�?�fc"��4�0'�IQ�������q��U�[��L�F2^�	[��X���uH����Y8A���������D���$��A�S��<7�f����a&��j��d�~\��3����a�pv��Zw�����0�0#Vu�d$��h���(�����?CN��F�p�����F|�����o=
&��i�=�_�������EE��a1"V(���@����
��}���E��H��i�
H�LG~~�lV���t�t�����T�H�=����%�2�&4��\���}��D�j������g��Yax(���T�m��u��GqC^��
_fR��P�B�Ep
�II�����2�6%<�%x������+1DQ7���i�����tD�t��h&v?�sK���"H�G�}��{,qX�S�r`G�����SW<o�|���������&7m,]�LZ�����������0"�K�87$��\�dz0�5�`MX�� m���4� ������dw�l�@��Bd��pa1!e����#K��h��<(9��yqx��X���|���Z1����=�1Og 6
�������M$�s��WO�
1��7F.������B��-�o!���e,Y�����n�|��s��
��NE���7����]ek��+����+�%��B+�sU%�|o(���q��?r��-I==�J/~���|�9�<h����o[�;.�N����3���S�b[�]����l���#3��P��^������]��3���1����7n�P&���l1�(���)B������4��^\��t2����~h=!��em�����"�D~d�/4-,D�?R�dDv��AC��K���x��FdA�YPF)[S�d�\xR[����Q���+��ez���mx��	/����`���������6�q���)��x�E�o��A�@�������������@�U�n?���"L����vfp��^K����|��`�
�����ej��#��%c�B��������*�B�AY�,@����o�8�d�������K2��m����W5��i�V�Os�&y�v��-s5����u�u	#�b����J:H�������%N�2cu�8��n^����n���\�
Z�T�N�d
V����l�$���,���I�9��#$,s��X����D5��e��~���DA�W��5X��{}���,���vr�����c�J����}�f�~�N��G
]�{��
Vm�c:���;��1��6�������y�Q��"��~���	�}xB����37h�F��������$x:"��{r
�������(����qW)j������w�x��8�_����Ix�J	j$�[X�)���?j$��x�S�2n�NIuJd����!�v�s��3�J����iW~:����.9�0@��7o�`������!��J�Nv!Bf��/��P����:C�����!Q��3��8j���l��	���L�XdSm��n������4:X�w��W���<�k_���X������2��SEDR8v2fa�t#�����V��0�#�y4t|ukDu���E�Es��;������v��I:_4Hd��W����Gb�6��3�0����0�	��H��8;�]�1��#J�{�O(�h8X�J�6T�������
������p��*Fi�#��U���aE�
L��j������Q��;t�o�%{q�R��(�y��2���RS���i�����ay��������/���(51,�{m��\�Xq0Y��n<Y:�D��r��q�N�y��gT��tN�z�HM�!(0Y�����X�Sm2|InpA�i �'�,�%"�b���L�P�7�u���_^lmBm5a�N8��e����l���=}'.����'���D���.�t���&���=a`q�=;�k�X1�p��;�'TJ�:��7o��8;��z�E�k���h
:�UF�
��4�N�(n���e�� �u4����+C����������l���f`*�CM��w��*�)g�} ��p�B�"J����f��l;�0S9����i)E���z	����C�!P�!��Y|)��5��nT����jD����i�������cn�h�k��}�����hh�
s�8	��$$��w���6wG-n�+��v������G��)�\�,�>5��}����`�(�D�i��,%�������L�}�!��{���hC%KT�=���<{������6�4��jnwX���er1$���#^s9!�)M���-��Rgs5�PD�C�������K��.-6;��U;/)�B����.�.z
%K���������V2����f�$ai�2ys��F�����l�w;q�3�U� ��A�5b<�C`���������C��I���'��3<�p��?B��D�naz`��~<%ED��,��S�[�D���� ����*�F�DZT�(�������x����H`W�������s��b���� DE�8���
N���ACu=�����6��\�6b���>�^/���X��Pu-g�d�V�&3�Il�V���������D��T�������V�i�Q�2�������E�F�?��u�$�o;^6_�X��N"taV�xh��
<�t�x��!�K���pQn5;#�-�������H�/
SY�>A�d�4��	��^d�{)(����lS
2Bjf!�.%m���X�@16��e:��sx�G���I���`G���"�����qs�&w��K��K��l������u�C�^,����������P�-I%g$��B^��Gp��:���6Oo�;�X��QI��<��t���:����&�yb{�G���U4$Y��A����_a��o�[4��sF�%J�#���$=t�h��0
�_rR��c�D{@<9�����;���1h.M����F����v�b��Sd��<��cdG�j��Xs��� 7���/`�mlL��Y,^���V�L������5���+w�������S���Dk���p���3MuZ�5!������X(
��h���j��MaF��>�����g���
p8���2s������Y��h
�K��H(��L�9��0��vj���W���]3�Q���bL:����[�D���}�?�<r�]�����G}K�'�Vw}�:�@�_|	���jt�h��N-���
�tSD�g\�S~��`9��fX���Yg��$��1rf�4:�9���X:���P���0��������]C���@��M��`����8���$�{oV=����*���<���o����i�
������$
���������k�V�:%���{��f������\;q���Hu�C5RL��ke�}0�F� v��j�����A}������o&���U��Tr���4F=#Oq}�������QA�GN����d��o�&������ 4��b�D��,�[�AHhoEU.I����J18^"�@�i7��c�H�@������z.��!~��d@��������
.�S}4�,D�����b#20�����������Sm����;�����W����ZLu��i��T�~�H]NIqY"��C)	uc��h=�1� ��D�{��kB2�&U��zP���M&FE��&�x��G�9�� ���@���*e
��}OM��)�������P��\0�@qqI���;�x����r�E�pj72�[>�I���@Am.��Y0.@����,l����<�S���e�r�n��w����$���
���m������3�u h���2
i���0�s���h��w?H8t����f)4��:�������c��X[dJ�ZNh���1��T�����l�Qr4#�
KyRY��e%j����/Gh��1K�yc��%T��M]���L��Lp���^�7'��U�0V�G86w��}�0�B��d��H��n`���w>fSH��i����K�p�1z?>1�����d� ��3�
��lC�����~�}o�5��q���M�����2��81��h����\�DP����/����62�%t�#^S���w�y��)%4��Kaa�% ������|��	gH!Qo�ECgn���._�z�Sl����:s�>�c!������(pr@��7��b���In������5Y�|�:Px��W�����
���R����Wp��|���9	����I���3����y���;p�1c�o��	F�.w=�:���]6�ke�0��f��A����
)�A��q�I�"k���)�Yf)}��br����o�e��	E@:���ef=�g�W&�k$.��?��d�Y��E�F��^;�15��K=?����%��$��1Q��st��~��.
S;3���\���m/�T�{����YJ�����]���`7B�A���a?�f��&$0��#��#��Oo*i��S4��
XS#�H2XOM2����R�_-R���
+�hE=� ���,�)�t�]z��*'�� ��:�_9�b���_���xG4t�V�	��D�E����M����>��<Q���i����;���,q+�H'�������4��,���2Jh�(��4Ur����1�~��'s�ZE]�������1���h|�:�8�e��s�$�����2t4Db��9:>b?1��x@{J��������B���m�l6Fn
�8%���w�����>j�h*��[C�*j��t�{;2�j9~��%�N����<��8��I�0�n��AE`1X4l,�h.<�g�
R#����9���M8�n)��*>� ����gT7�"�D[3�e�|�*=������M�I��Y@����C�������MXF�_��_l`��n�&�
�?����6���m�'��;�$J\27��U��80�(]�z`\��Y��p���7�;�>��
-����^jp-s�!\�������|,]RS�"�����S5S2)��#�;�
�]
��G(}!4m'j
��s_�JN�PT��F����H��b��DaX�\��`� �������!g1��*�����t�/�;k1��j�[N��o�����e�a�/I���67�v�=*PF��}d"��3�v�����6zE����dh�(��������G���I]?��:�F�kGB���T5�
�w������-Gk]�������SLE��`<��+!�F�l9�'9��x���7������d���w��oq� '�6#����a&�|a�?���<�E+B���lT����,I����[gB����\�������&�DEE��
6�$F<����s���}x����D������HT.�k�P��JI��l0����QE��}���z����y%����}��slP��Z����2 �LNO_7��Xw��J����#��?K�-��N��`Lj�[�����T���A�m���<T��F��C[�����k�K�~Vf���d����vg��&��1I���������GB�����?p,��m�&8�-�|X�s��yp,t�LE�!~�k�C���y9���e�%������K���l#��f
x^e�������q����V01*��2
��	@L�����MFc.W�9��^$+�0�U�SS���L��l?_��j����"�����C���b� *�I/u6�~<{��v;�6�����@�
��52uB�a�(/EA~Bmq*;�,>��| C��#<���c�F���[��H~�������5i:��G�T�@ s7�_����l1Lo�1�`����|��2��E�XF,]K�]�\�O�N�w�ZP�o�I�	Tz*��Ku�t���,n���2������LiVT.���
�!��}~Z�};��"&�COn'"��i",�}l.�\Dv����M��.��<�P0hO<4Y%s3�LtI��uD"7L��ar�Y��YW���e��l����L��a����3���0���x=�A��/e�1KUGJ�|4h�2J���Pj�N����d�J��p����!g�*��@�B<q����Q��0;'{R3�� }�G�k~lGd'�wsdA���?mH�T����W
�N���~PV#�	�(B)(�~RFn���`����Nid���dqH�
��!�~��
�^|W0��KH1���*���&�=���P�;E=�_+*��[fv��L�	h�b_��t5�G]�W�Q�<+���)�.���e[=e��a�'�43mQ����D�%�S�����]ktk�tU���	��[�O�!(	�[j�P���H���c��|%e�f���.p����-����L��,yn����f���������F������EAQ�4(~\�G]�{����b}��2�-lrq��Y����g�u�O�����(u�T�am������]������s0�G 5h��$���p}2��G�6���f����
K�7��o
�*r&�e*Exp�����^t��[�h�Q=O&�(�E���aP��6h�U��1Gj�E�Z�F��E�V�pm���@����V�������@;��
j�n��v�R����������������tXi=��Q�*OZ$	��"���p��q�������E��[�~��#��t4o&W�u!��x��U*��%3��b3�%MkT��$�[�B9
��Q�������%��8�25 ��Q�G�!r\���|g>&�P���P-K:m�bb{(����O�i�� QTO�R	*\
3��C�xa���5+���b�� ��n�P�(��rL��HL�B�@/��.��	�����/F�\�d^]��K�BT��P����{G����+/����-�]p��tQ�r��n_8=���5#�V�u�nrI-
�-+qyEH���hk;& �����j�u��Bt�`�0�+g�Nd�r���M�C�����8�},6h�s�J�E4����A��,T��d�����6�u���kh��{���P�8&�%9(���kL4'���>�G�r��q;���(n�	��_:k�Y.
��-��r�@���`m;k�M����y,�d����Y���j�u�IP���.�/#dY��w)�,�����yA���w�4��t����M0�"]���b�������2��R���A*�~�v�$-y��)X�^_P��,��qo��vr#kx/H}������]z���E�M��m�����h��.dA�Q .�#�W)�t��^.F���>��*�Z6��#������(�|�&�x�8Q)�����nU(�����Y��x�Y]?vb�w���`�f���j�����>gr
����~ll8^<�G����I���-u��p�?�qR�(��,:�p\� �_Sn����z�5��$)i��8Yf����L�`��~(|��J�d�+��@�K+����T����)�-������_~���{+o��9Zo��������������������w_�U~R,��W�����|�����slm���������������?�?���~��|�~��9I�������������ozhm��$���K�����%x|��_~����������C���|��?���_�����7��������������{��_����~�������������w���������(������������������u��_��o��?��O?i�������������_/�����w���;�K��s���%��)�?v,�
����i.���W���^����O��_��m�������F�G���?��?d����_�,��||�
�-O���.�>>���Q��N�0��>-�#1���$�����?~�s�����
z���6}������+�
�]@0w��r��!��y�Q>,���~��$������|}q�H@��O�x���."�%�fHg����r}Q���$���*>���W��Q�T�@��U\�E�$��}\���~wo�(D�6���G�>�F���}:�������4��1���Q�ykUC�[��'���N��������^~�k����������oMf��������g/��F~���z�W 
-���Q/�7�S��}	�E�S4�q
��z�i��)��}�H����.�|X��O�)^���`!KN�U���]��H�/��[����_H�������������OL(������?XH<:,�����?x>����@��tH�����tl���|o!&��/$�@^��|Z���`!zfBub��.��������&4�Rt��M/�������������H�/(�M:���v\�3������������J�#	�_.�K�fM���<}����}J�"���[�/���D.)��m$�_���W��O_���P��2�]#�0�e��y�
��%��|1!Tr��>��*�EC~05E���37�|��$�(Y�y�����ko�\���t!kB%I�O`��jc�y����8���L��x ���u��Ql8�0��?Wt�X��[]�{o����s��BV���t��1G8puF=��d�g���x~��T�NG/�k�~��"YlP��������K}��=���e�/5P���]�x������
t�uE�o�@p��Q����o�G<�g�Y��Mg>{�uI���j
�%iRT�����@Q�IH4�r��"VK}����-��Du����'����\'$�*��,|�r���EXP��E��3���FW3�i��D��wl����5P|���/�_�w�0'�o^J�3�%���yU0w���h�2U���3���:4 ����+���g5�_�����H���d?>��~^Ld
����j����$v�������-�`�ds^{��
������}5�+�������"�_�9(t�h����	���n��y���[��@���
}m��6������-;�����N����J$��-�`�e��p�
&�5���
6�����=�7B�2����@��z�7tgQ��`���Ge�|�A�I2FDL.���o�R�����
��N��f3�>��0�-��H�})�hV���f������3���<����Z�L���e���MB�8.-@�|u]���ua���;�����]�
0<�
�H���_����LJ*���&����R�htq�5|������f�3�67��U�B�z'�FnX�1�e����0t���&m���8�~�7	q�y|Nc� ������O(�T��o��8E�\���[�3���	Y������<F"�('�T���z��������L���}� N|��C�����J��)��kU�Q)�:������(�w1���������6���&zBs���~�K�����P`������~��f����R0����zM=��G"�t#�������`l#����l��m���[���	���%U+��|������'	�RD�`�O���q�����'�)�vG_��Sr)�}��#�|�X�R!OdY����IV�'L�&���dKd�X���(��B		�����W#���&��U&��	4iYB��F2
 (Da�Sq�>a�g �;w��P��'2��l��;�	���a��P�������9B�d,g���E���� s�e�����{5sj)�������1��iC-�N�!� ���B	��|��������W�2�yi��*���;�fn(��C3�21��l��(�4�q�������7��"C�~V,)�������"��84k2\j����?d	$e�@�p���F�)��Tw#�QN��m7%~�k��J��8�j�]���K����x^Xy��.��9�f��N��u�4����j|<n�4�h�" ���
�c���r�f,xP9\����Z�u��P��{�����@������qH��\.�O,�����G�~Bq?i�t�S�#��A��B�\����
R����?��C���ci�����V�I��B{������{(�++wi�B��vK��\c�=h�/�!����������g�vIs]�>��J�r��x@�ur����RD\�z�����q<~��&�P���(g��:<��r��O��m��A��{�}��,�����59�����o}W��6P4���(��
� �s�������!h������(��C��~��(��%����Z@X5JI�F��{�L�UL9P -L�Z�]C��.G(���������e���M��M�z	)|s��d-�l�������
#=���9����U}\�����GTD���|�u��/��,�Pig��{v5��u��6�u�B]#Ve��	Y��4z�	��2���^G�$���3h�5�50)�o@���6;��-�5��������G� �uM�&"=�B)G���nbJR�T��`{u�x<Gr��]��DS��A�5�5���(����EX,XGi.[J����.��w
o4U$����0�~�4���1pv���:C�� �-��������Q:,�t7���>!!�w}y�Ef���a����5h$�#G�����(����K����{�+�%k)XEB�g%)x����YqR����\$���Gz�:hPX�O�����5���$D�����{P��#�%j� p�����g`&s(����w��7���CL�!X[E�fc����OI���M�������.\�=(�j�F�����B���E����7K�\F�@�F��f���3Y^d2��&
��+�F�i���E�):��wO�X���%B��2�}&�4c��9��P�n,�Q���8si���u��4+���
����5����<HtlA�W ����O=�����6&��{�^�D�#���\J���9Z��oR���1�X�Kdr����,�W�����]�?b+5Q%-}���N�q��bJ�6����a�n�GL�`�t����,w&��w���S�E���S�	��'����$�$��������l�qaq�&�h�N���?g��B�Z?�)�{-���AeC��a<����dm�.��N��f���`��Jx����t$�2�~����K"���!j"�%����w��wW���?�6�3)�{�a����1i�h�0]���>�A��h+n�n��*=8��9U�XE��M����!6,����F2����k����:������MS�J.%*u�j��|B���wf���Y9#���V�Oh2�%�E�u��JY�����-?���rS�n��i��P�Q�x��&�b�+��
�<�;�>�'�hG��>Z��[��|����}�T0�J<�.�H�pK{wQ����4�t�G���\!�gw�lqyGAqR��J�������_A��R+�$����h��qN:��\���S����x�����=
$b$��|��~�&���$��`0�?`o��>�6�!}�.������`x"Qso��aZ�;�Ip
���������Q,k�U�FI�������]������t�x`3����y���%����.Q45�C�z������t���x����a��&��;n��B��wO���@Ucb��Y�������0*��~p����� %hv�q�a/�����'}:��[:}��l���O���l^4V�b����:��:���u����P�&�O������{�6����0�A����vt~+-J�G9�Im.U����;PM����|�����]��7fAT9	OX��.�#�����X*���1iAWd����`�'�.�d���yF��/F��d���%��z�!+����v�)��p�����z�.��H���&8�U�4F��@�e�����x��t�L��
��?���F"��.n����:�SE�*	m�7�9$t%f����h�l�m
hteh�e�SR+f����o�n���)f�����:{A�,.������3�H�a�����[�
d�e���N����d�)b�Q��k(��}O���M.���ke���Q�yk����
�b'���\@�
3p��/���M�G�'�v06�.�$@����3:G�#��V�����5�(�@����2����[2����10��o��v�_��X�� G��pN�j����ul��- 3���0q�3�Y"����@C��i�����eC}:��F�5���N�K;&�^�B��V���!LF�_3��}#�>(�������������A��|�;��;��^Cp\�0�_�9��V�GT���q��r�����Q�B!�p`��o�(`1�FuB������5���j\���(�o�"������'����8��}�
j�@a��l��p�������CJ����= f�ql3��j���!�	����PgL-6�2�[Eq�#�[�\gR��R+��H�nNfC#	N|A��^N	���D��PLh���GY��#R3�L�'ab�t�Y���3�3_�?L�)!�lz�X1�s�'���U5��(���T&��M�T0�� �d�
p�����h�6Qwv=�8&�9+���.��4��E!�q��O� �)$���q&��p�C�� �i�0
�� O�n�d���/T$��bcEx��V�+�R�!?��'������]��&6�^
\k�S�{b/�.�����;����r�+B���u���=R����eH�i�I��9�p�T��	�T�:^w�B�����W@E��(�����]a�,����uf��9���j �@r�+������H�o@��a~izj�����%22��R������E-#��xq�������%����|��n\x��r�g7zK���9��B�������0C�#��W|��u�Nr��Y�6��d@Rr�K�#���f:�����O���~�#O>v�}�����������c���q-c�$��*���(*�"uJ���`Oy�����i���������c_C\k��5s=T����A�>�+;����d+��Q�%w�m���8NXJ[��=��\{n����'��9|��RZH��x��;���1�X����?_V��
SQ>�;7��KiL�����������"�#��Lr"��������j+M�����/��eS�VZ����E����t�S[��Mq�O/����Wj��u�S�������b >hn�I�����t���R�����#����u�B���i��K����� -~66��b��)LH������7:�;��Wa��B�����O�����o��F>Wwr�#An'�����1�U�$k�|�����v���G}&�!_p#2��Fea���IK^�U�d��n�`��vfT�����#�Q�
D���-+�����B�LB�}R��k�}�0��~P�&�O���������r���G�i�7Y�Db�8�N��
�V�At��R�
f������N��j��s�5�����KvIBQ����F��Ziv-�<���!�(.�����@�ti�gv�w��;<`��)�tQ�tS�::f1�-�-��u/)��
�h������z�u��4�(V��
�����������4�
]��,/q�����$���I,������z L�"Eg(��Q���2*r�-��R����tR�D���E�F�{,enxI��I����s1�N��K����&2�����2�1-X�P�� !�T}����w�+�������B�!���
P�f�}
�gI/�`m�;�E6�{ca���s�������,�}�+�|��u�A:��FV]�|���##+��(��
�j����`�UqO�Od�8*=7@	���@
g��Kb�'�%!D���);�5�
W�0x�F���n�M�-����
����'x��?�B�;~�S�nL�]s*�/�0q/d��S}4C���\�"�GKAm�wuXJ�HQ�*`_�n����q/���R�`��������d���.D{0Y��]�C��b�YOyC�4�HahbA[SEH�����RH�:B��J	�Q��rRG	JE}c��{�5����M��[H�h]�F,��?6ic�1��	P���q� �T��]*i���fh�G*��.�w������L4�K.��T���#�a��5��+	�L�6�M�}�d<�RI��R��\�'��fZ�Zz�Oi��,x�\	|�d���!B���`�`�0$���K��<��(lc+���aVb�}��*�[����)�e���*=A��}�EU����K6u#�X<���	�e��\`����*�Y��M�vo��t�G�_�Q���h��m[��Kv����BU��\��cM�I�T,� 2���"O!�����n��jA)1�k2�������6t{BG|�)��JRR�����^Jj:@��f�O+Iw�*�s������p���A6'K��,�t-�L<.���(9�f���ivza��T���[�&!��t�����s�P�n(�I��(�"�bg�{��8o��wZ~��������P�V;��%����m����?���F�s��q����:S�
���5`�Nmh(��Fd���oS:=>an�D��sH����U&�vG"�.�����A��^
?�]�qe�{H#�������ED5����C�)<;�H
k�2�����-�b6e\����e�1Pto����8P����>�'�u�����g�8�����[��u�0��/}m&���N��R;=�'{� ��b�cC6�=���$�"�GBdy]�����t1"d�HK�7-��������~���U�����hGn'r�^�u8��F��#*�s���W�[�[�{>�sj����X������6����!��N������p�>D5
��n�
�b@�A����+~�)�8��H4b_-�
4�����=<����2�NKn����2E0�������! ��
�^O��~�{H!K�;�l����WD�}l��4�����@�S��������J�pp`���&t}���Ygj���E��Ep�%[7R������k����il,�8����"<]����\�D]���@T��os]
����E�.j�����x 2j����w���x�@��o�Q�R�?i�-���E����D�LJ��(���)�
��`	�-�47�]�F58qd����
OPrDk����v0�E���~����0�0bf�1�M���=)0#�i��������������a'l�e�
�m��9�������.,�w�
c�V|c���H�@e������%9V/�gru���p4���*���X6��E�J�.x�N��,��T���Usw��=��T���#����t����h����2S�P�S�bP��IB��J��F�4��n!������V���,�f c]J"�2d>�I��U3�9d��R%)�1>?���f�rn���d\���������)����,M����r����1��0������S��{Gv�������l���A /i��+@nm
�J�p�|�n�r-��d]Q�25�?�������(Q$+�e�

�x�xw�����p2��{�(����o����L\��C�1+��]����:�4gQ�B��T#��R�L����#�x�Z%���	J�0r�f�hUX�����(|�}F������
����=���k�f~��X�-���SZ��}��?(��
����2��tB+m�tt�I�z�� \.W=��d�����Lx3�����06����#��{��$?]�I�,����A����U���C��[2�������^qG15���So���Z1��%�/�!A�eG��f�|*��w�3�uP��|�(y"i��k�a5e}+��Qk5�2~�	�PL�@43��#x��4�t�0gu�1������?��Yu���0�k��AW�k^L�otA\���B	�

�u������0���|��~I>~^Mq�E�MCJ������1����Z�h �e����
`�[j����u&D����\�w\|������$]3b�
�x_EaG�DL�L1��t�-��x���\A��,���6}��B���Ck�hr�=�PzM�Y�!�V���F*nB��^D1@����n n��
�n�����(Me�������Z���:
��M���A�t���8L%��7T�����4��G���D�R�L��@;�����a<�i��������t����z�-�XY�={ox��8����h��\kQ�[Pd9cJTt��z"��D}}��\b�0bh���>�H�W`!����ZA?f��O��`>=�	M�(�(�����2�G�|��Xcd]=��Su���G�Q���R2�[��)e9���������r�V�^h������St�)S�����
���]!u��j�6�k
�
��������'�+��f9�md��|N����zd�,Mp�s�pc��,	�xZ������M�����q����
}�D�/�5T�Y��47���H�`.C�\��3>����W��$3(��zN�v����K�����tR���l���R;��q�v��������(q�l��:*�`�"	f ���gS3��Q:.�i��Ix
|f�J�8�(������C���6�+������ ��j`ObE����*Oa�>���)���A�f��<y���S��e�[#g���E�;J��I��+V�K�Dz+Y���q�eU3�joJ\��Ho���vq�g\����E~]�v����}P��u��q�#���;�n�xk'+�
���;XB��A�(2���&p���k	�S_�s ����
1
��r�;�;w���H��z�[����S�?�4E����E�����O]p��m��h�f��iW�|��CY��f4��+�R���?h��6����
���c��0�������X��u0.�S$U�����p�
�R�#���FK&����:3 I��%n~����Ksw��!:
��L���"�^r'�A�u����e���������uI
tF�x�SY�U�b�5�"��mV�j3�k���������&��J��aM��Ze�F���!}���J�z��~�q27%m@�<
r��(T�t���m�>�bg���:,��5����%B�bP��gA$�&��cz,�q3��RV�q����x=LSvGRr8��������$H��Y������oH$��F}@�g��6��E��HF$"&����������""gq�%���0�:�?��sJ-W���-3����Che6)t`�}�<:P>�}���(���Z�	�hE����KL0/T)��fyk��I�dJ����.qvT(�,�r\��t0��*�4�R�8��� �L�}q����m���&Y
�7"g�f�$�CqN������u$������9�m,Yp����H L0(M�E�-�~U$q���>1��Ce��$NH�#��6�@N�����H�2�e��Y���{x�� u�������W�V�d������ ���G#�?��#$v��F�� ��;M�;�#���������-�	b���	Fb�������%�Ql6|�l�EeNn)��Fb�9&d���WT~q
����q���k���H����Ag�d���U��m��Eai����r:�������,�SP�j�lf����[w���P0~�J��s��qN�Y	R2,4JZ8��)�b`�
=P<���$��j�U(�A�����a8uZ���zdF�
�/"��t�qz�p*Px�.
!k�(\-i�V����F�:t���ew���0��.�)D�]����l�����\�#?�����<�f$XC�;Bjw�,��rJ���L�=��71G��	W\q���|��}��Gq?Z�l#�J/�P��1�����=��K���FS2R�7J8�}�E��
�������kG6">J#��p�������q$x��@���4
>����
d8�CvR)<�d+�XxnQ����X�V��c����d;W>�*�4��$r��L�t�I���)m�^))�pE����/���[t��cQ�u����0U�t���ep�?�v�b�wZ�^�ZK+^���I]D�v�Kn#�o7�
L�K�3]��Y������������������&���$�i��MW��{��q#!nfRI���<�J%#C*��|9!-�a4,��)�!��D�7}�e��7P�&��:��%e�q���i�!��	5��������&T���32��3�$s�@a�(�S�7?1�����J!�B4��<�m������m�7��U������p��D6M��M��q���eH�C�EYBaX��x��1jb���P0h���U�MVwbV�E�{�JP��HG%��[1�5��I�w��7����!�lR��_-��Akl����s����JQ�ag���W����B)j�7:�0I�H���M��!�P����&xF��><��{����e3��3	�1��;�|���q.'6?���2RU���(��&�op1�7*�E����:�>�	O".�	(��(�a�t]������G��z�}���������`�<�G���G]J���i��*��JX8\�|��a_�$����L����)M��j���-P���>�,��a�A��X�������,m!0��0w����pm+��H(����2�(��5�����#��z��8�rV��8yJ�
��^�1���U|-E�M�S���8m���J���6UYi���q�#�`n�*�TXBo8_�~^�	�O��I
���u�y��ml���:�i&F����Y����Hg�8o���P-7Q�����:�at���*�`Re�-���s�Q�4�}$��)�%�n������2�f�HeC>y6q8�2d�q���]AsJc������+(yda�,�-kc 8�����?�����a��.$�/%	S��k�����T&�}}b�d��P1!^	|U
{\�4���&�qp�M�W������N1P���\u"d����4�>F	}_�!������e#������8��P�R��l��[�\���hS%"u�=�#"���(@��"�3X��)��_d.
�����J��C��%������N�k�Z��4�]�z��u��
���S D$n��%<���]!�AO�Z1|����1"�If{�B��vM��7�Y����j~�`O�p�0�WN����V����������8�BoqC��L�PA�;G�S�yT1��r���-�cg�+�K�����0�F��z�����G�MwQ_��
y���-�2�.��)�������0xH0
O�	��t���?]��"��P��S��f3�h���q���i���6B^�y�`�I��%~+������q���������� E��f ���PR�cjJ����z��C���h6@�5��q�t�&8�J�����v�'7� �Q�[�i�g)���:1!�OT���Z�4����E$�8	����e�&	��{e�?< @����F�r���E1���O��(� ��d
%Q�Q�a��2})h��v���L?���r�A#"����u�E�PH�����6��T���'���+sN�y&�S�����E�[�AG>�x��W���O?���p�l�GU.�|!ys���Y�/���"uc(fRy���`��]���`R�GN������
��h�h���&�#T��)��\Q�"������,�b��2Q�s��*���h�iV�����M�����r7[�'zK�����������3�8S���]����;Y��"yYO���Nw������X��X�D����$9M=^��F���v�K�LqLv�2�����;(\E�'��,����U����*.C��'�����9Kh�KM	=�*�r�	����UjZj�d��#��cHg�����cJ�H���LJ���V!t�K�I�������`	�0U��&�Zw���Q����^����B�$��)�m��?�[��~�>N�sbHj$2�}�M$������t42pC�Y�Xvp��e5���9��^
Rb�l�2#��Y&�Q���`�E��S�1���� E��\�'\��Q�����R��	�gD�����dK����T��t��b.����2����Su-MO&��J�4	����9��A�d����\D���l����Dd���a~������Je�
�z���#	�����@uB���{�i|BT�[��#�WiEB�$���_QE�(>���Si��p���Z��u�������KR��5
	3;�1�i���� U�9:���5W-���.��������>�����L��������?Kuk�0W1\�JZ��/@������
%��Tu�vrq��;2���t��1#gn�f�U�b%ZT��Q8B���i�uU^C��;����]�������=�'L��F��mo�]������KB�����M���B��L���8%]�G�-h��L0�H6���n��i*G��Y�@
z;*��RP}��-��1K����Yc�<*����y�#�j\��5���#a�����<f$.�����G��"��bi'��k��&�����_�7�����P�#	�eJ�Z�$CP�2 �T.�x�MHBw�C��4e268R�?�@�Ny�W�7����pwH&����`��]�yWr�W��QF�$W
�!S���%���@�E���<�p�6j���1^��8?�c��/f��!� �H�Q�
�~_���jrY�����O&>�6�>cg�!�fd|.�I��� �]��
\��M�]C���A4�-�[�Z4D��(�CL����������.%�t�RD{�	|�
w�R���o����rt�j	���1��2���j)�p�8����t�b���5�
�� rf!�v���+7�RQA�����K���\I�Ty��:�
>��K#=����������~���p���4Hb����"�M���������)��������?�r�,R���O���%=D��(���>��(\p��v��qw�>i��\V(o�Xi��;�"i^����7s�xY�Q�����yJ����3,��'��+ox�$)����C����.be����i�F�C[�;a��aY� %*��"��i������<fz9GSh�=����V$����������� 
�<����-�N|A0B	p�>��k����;������������g�fe�����	�cqp2s�R���6�3>�n���i,����
��d������P����mR5RT���G�����#.alqz� �[�C5F�0�n�*���e�D
z
�v���G���i�
�@Y���mP��T����%�p��gc*���G�d�z�0@��9'�<����j[����}�/r�2��Bi��a�!h�����;4�h[�nE������N���W��i��F�C�z4�vP�z��E�>v"XG��"���xEE���;�Ra%���=O�	$�"A&��k8_o
�}�1y*��} ���������#�z8;}�XV�~$��/����0K
-B?H��!��8xt�]�r/���)b��ap��"qWP�[����������#�Gr1�6]���%�4�+Z���M��G0cZ*dc�uPoWKP�a���V�3�D[C���evc�m
�[`��8�<��+w����|�a���Ql��UV
��R�>��F���(Dykf�.��
;�..��[S��o��k��y�4'�yDn��m@~��:����V2�D�O-����hI�d�i�+����9X-��,�>��I����T��X
#�J�HQ������!�4��Ge/q�8�f$��v��^�����&2��F��HFQ�B�7������/�"%$�Jf����~<�w(����T��C.��S>�4���,�e��!�f"��9!u���: "��wt��?��7��T�F�R�il.:�;T+5J
����&��A5��:� �!M6�.G��N�
�!c���3�5$���o@iAQh
�����M����Pw���)�,.�����0@;$������vS-��_��odL��H�q�=�����	��z2J�H�a)(�;l�����wO�/t�+��9�*�>���x.E���l�����'�@	$���`�9l�TJq2X���Zd�Fw�b�z��ou+	�I)S��<�a��e���;����`����2X1%������&'[��"����<i6n�N��g�qy�!aC�\�Hj�����u���/���B-fAU
T�"��p����:%"��}0��F!����KA�oU����"_/I)�.
C�f�"���V�����?��\�[P�@�G\
$���/�n��3�Qs'o#����bz^�B�2g� �X��2�_(�J
�j�n� �q'{2%���Y��!�q�����$���z�����eL�U�"�
q��jZ�`aZn�fJ
R��e��/iN$�����a&^e!+�4��iH�Qk�K�	�
UD�FqF{��[�&�W�{/���d������Dw�R6cj���xpT��;:T�0�p�,v����.��u*����[��t�N[w��\O���|M���"�����<��Z�z���=�]�=��~���HU4�f�5��
��
+~����[q�8�O(�8�h�&�?[������GQ���Z���$�&]�\b�����if9����d����x9--���g2�5	
���@/2�3��������/>K��]C�/O�����9k���2��5�G&��z���8������O�H��yp����D=5
a�i�F�EG�TS+���K�%��5aP|�M.����{���
���������9�3FU�0���� ��]���^��y��`�2T��Q��s�'=-�k l4�h�������O!�r�
|/s��y���^���x�,~��B�o����BdE�y�K��8r�1Ng	�&���0�|-1�%�-m��_S�	��Z�Q����kwg����#����4��&!��1Cb�����E���d��y�������`L�6��� -@�iK���}�?#�C�Z$��?��,�%���;�����(���~I�;P$�mK�m��7i�@	�Q�@+�����<9\t������-��k
<�Qv��bQb*��-�TH����j�!���Cc�ko@$��@���j�#w��=��q�$8��v����{H�a=Q�
4�r����6�&g��,�mf4�H�����15X�	�hc���+���v���;��O0�c*�E�?M��6#R����]Ip����1&���+Q4��C&�u:����EC�?[���N|D�=\]x�\?
�BP*���+e��	��@�2�J�H��qb��F���R�����C�>��#���������GXI��p�)�MB��q�%��,��c�Rh0����t�i���Q���Z���c	�y����>;�;�������O����:���f���4#}�]S�L��
�z�V���6����&����e�;�����p���=�)���L��]Js��17U�\7�c���q0�$�+���7���V���^��
B�]���MmX$�]��U�34Jvf�� ��@����+��d�,A��u��DmG�1��d�������L���	V�E�:��Cs��y��a���zjT�T�h2� �'� 6I��F��rF��r�6�h�B7Pq4K�2Fi.�:=�V��H��<��9��}�z�c��%��(i��f�Zb�F�N�
��c�����b����dF;6�2�
_Tp8�a5*5V������r,aC��|�����_�r��&A����\H�D<;K;�u���J�����L����5p��8@�6	�)�J��U���u�d;2�X�&�$��c����m@-i���|�4u�F'7�
�ty�$
%7����.�7����$(i�;[0���h\?L������[�,�%�Q���I�*��u�J&���ln1��(����l�)�O��4��F��Sg�����?B2Dq�(��K�rx��do�dD+M�8E`c�����,	��g_,�!�}]���I��@y#�E����}� C'}�0=�>�"�����	��2�_���"����!��z����u{E������/�VWx:�/G�%,t�����_�5�|������Jz���<��6�T�1��-��4�;�^����a�`2
��JWm��5��e�1xg�.^�v�cc�����
n�v�������_�1�D���E�q,��Hw|k�SI>{�J��u���vi����z\�q������}��/>��&��4�m3����:SI$+�5+�s�i�J1�Z���MC*�y(n�"�h$�h0�+6*�?��yT�e��}�f#���2��i��}11���� �+F�J���� �JJ����;�,�bW"����M�)��>F�x��~�#C���:*��%��P���,]�5*w*"�5t�"�P�_m`p=�/��nY+'���_��u�q���:b��p1D��\�4M�,���`v�?�,@�������+ �W����hD�r�Sh@��+�^�A�@�g�qP�R�p2�1Wp'0������8i���!����6s��T#�T����������
��5�C�� L��UM��r��h.#:�IYa*��rsG�_�e����;�F$����A�<����I�D�Q��YJn�t�~�-�p��(lf�QX��{o��5����Kc
	Y2��-��e��������Z�[��]H����-�l;��.��6z�~������&C��H%3���W�nd���H�~p#r����p��|�%�c��*Z:�����mM��U(��^H�,L�&�V�	���8�h*�UD���t[�?�#���`�}��e��i�<.��_�pkx�dW��-�D�}=L&�g8O�9��i���:�i�"��m��"� ��@W
��w���6��*��%�rrq�0p`H�I�s��
5z��Y��X%uk��p��	��,H@Tt�\>��Dm��S���:$&������pd�`7PC��y����J@��E���n��I�[�l�xISt@���[��Zd��/$�WVRO��a��q�����HA�h�cM��Q��n�in��\TbH��������/������1b*��E"����lX9O�f9y����$>�!���[�K�o	V�^I�	�'��"��.}�n�7����"���2�n��� j�B�cx�, ���J��c�D�c�o�on9�;��%�k��-�`CKOZ$�jj�.x�A�ih:%+���d��44���iE�����&��<��O��r����mJ�;��}�\�p����
�8-�������Bur����VdR�r�N�Vp\������q������n�
o�����b3@�:�J��%�i���b�������	/�����|�4��N���.	Gh�U���;}IN!�$C6\���r|��+2�	8���sq�H��F�
SFI����_A�bv����������L���i��;p���;�v��)F�
��K���
�=�F��a��;�2MC���C`�>���G�\��	����-BHxJ���@"d"e?Dq(%t#���r,v�n�,��nX�����d&�I^�cQ�UH�F�	=)�'��@��
�4�N���M���k���<�����2�0�.�E��a	[��a;#���
,�eT�U�����oL��e�<��Q�TO5�:�e�)z�4��><d7��1r�2wcA����
�&���x�O������}�%"�SS}���:H���	z/��jh�m�h�'i$�V���#(�v�d(F�[��-d9��$�R�7A��@J
��q(��p�%������I���B�(4W<�d���q�C�
;#����FE�y<$�	����1M������:i�)2�1La���(������|4�@2�hC6MD"���N�������$����:��n��-���#����`���m�2@������F�.)+$&@����}�4i	]5�P�o�J3W�z��%P��a���3�,��
���Z;����=��V�)��O�>Sb	��99��N�-B�]D��4�7����������W�S0��f��$B'�+����mQ�����El�9�a�uY�c)e��A����0=������S95i�S���	���-�\�s�#�e ��/����}Ma�7�&��
�Xs��0<�#�G-��-���!��������;z�����	�E�SHz�0;`�MF��Hf?4����;RXD�[~��L���i���V��)H��te�0��)�+����J&C�N��~.70b�|���>��.m ��pJ�nW�	L�e	BX�HPl*:O\�re�=���p;9��k�	Q"�R����������Aq��m���+�����:.��CF�0.W���3����-���xB�����S��U��i�5��
���������r%�m/��
G���$�#MD+�'����Mi���b=�u"n�����a�x���ra9*�H%��Yt26q�26�;T<j���5&Q�6�p�j�9�[��,0uy��Y�$�������V���-��$��|_��[w$�K�h�����a��p��[�v1s,������y��S�HW��C��"�"�H@�����q������j��1j�o~M���N���,1�hk������P�"[VS�/�q�u������*���	K���d�J�=_U���K��[�#�e]��b	QuY	5
�6��TQ������{"5e�/Z����m�J�	E���B�� �oSUT)��*r�%��G2�<4�{�J��p��5��	@��6��L����cR$���!�IG�0�r��T-S�D5y�\�2B�,�@_#��W��1���K�][��)�VH��0c�2Qb������������R��]t�`��<�"��_K.i���5������t���������	��j�w�4��6���a�(K��G#j�I:�ly�@;�������������jeK��8h����"+�1�%Rb����3on��x�p�e�u���Dv�����v����*��I��$���;0�-"3�"=7��!cl��7$d#}�y��`B���v|I������
�_����Qa����P�����F���b��_,R���8�S��G�&~���)3��=U�8�/i��f�n0�qZ�5�D��`B�"��	X�4��F>�3uV�� [�^���u��A���v8OD������6�H�8m��
�n-0�����D�x��I�r���{OR*��#�R�����Rn�<E��� U�t����]�D���?�`�=�����I��U��<\�{<��(�%�V�S��������q�����o
� L�����xg�1r���z��&���������h2Cp����7p)���C��-�`���������ZJ�N�!ZK�A�����&���_
�WX��L��������H�S����HvOKh��<��� g@X���S"�4����K�
Fv?��3A��UQIGE�=�W�V<��:*�ce�'�,������IG�V,y	u�>�����
W�����Q��3MuX6a���X�I-���s=Ed;������d�i��
@�f6�������^eM}&@�h�[xO��I�t�]@*�I�u@�H+���`�����%����u���{$�M�r���M0�H9��sr�����r!�J������_a��E�A&���2��:��k�=eW;�B}��Z�LO}P"tZ�	�Mq�h,-VP��'�#M��x
`*Kq0P_d�?���I��:�����!���3��`V�ox �
�0�]�������z��g��]�;�y2W��}�} �T��C�bx�=v�I��[���6gA qiE
]q��:Rk��8]��	$�,=�xh-4�+�J�@�g%8��Q��
zM[G(���E��������@Y��g�e���B3�����9i��������^�T���[���@5I�.h�1��,��>��#o��n0oj���=�L��MPs��#xu2�]�l8K�k�Gt����x�[g�UPcG��QcW�$1�h{��#(4��1������?�q���V�RX�����9u����7>As	�j���I6��z#��g���l
#9�|C�cF��=�=�m��a����C�'��:BV3������5�Y�'��DA��+�^�dF��=�-A�� |2KP:��-��,�'�P.cn���h����(0�� Ez�L.J���xRQ���aW����7a!cG]�e���84��[!�F�
����n�j�l���o,��kD���8:�r�7
�'�o�����*)s��Z��d��U�7>�ziv��T(\F��Y����*LEG���T���3����T,�I��	�`p��p�5D�pD�`���nj&H�M~|<�M3!�>�]<m��-����2�D5�t0����d�.e2
e��\z�5������C�+����w��!�t\��4-�Z��6��a����������� ����A���� '	m88�W����N^��-� �4��[���<
`=�����-��|��)�dNw���	~��!�Tk��"������"��a��O�<��$
��i��
���v>oIJ�T�17�1���&�W>�!���H"�Dw+�x���i�#����4��j��9��ZN�CX���BoO��hk������o.�����_������g�������o�����_D_C��^9�
b�<|�B-��2�///�����q�������������������OO���`��O�?���_��gt�!M���������|������������_x�_�����]~������7_����~{�����=����g������u��?����?W�4���>|��/.����/�b����������_\��?����_�����ao��_��������-�W|���iV5����6�]�O���7������_^~o���K?>����<3��>|�J���=}n�������Ff���������=�d����Yh/}J_�����������R�<�zr1�t�U|\��7�]�H[���3��%���a�c�P�,�����B����"������7O����.b�n�������(������A{�'���*`�1�)���V�>�Ua$1�~\��w�]����`��~���$,� If������������\�?iOO����!I�R��OG0$�I�|��?>|��� ��[{��{��9�Aw<�������_/�/���������vN{�pRW��%�/���Ud+"��Y=�f�w��@h��|A���`d��|o)~�y\��*��)?�����Z�b"�q%J�>?�<^;V��g�O�����XK��P��W���Bo�@�y�b��Z^����@����Y����P�xhn96��c���O�*h}������!�q-�J�����ky����bO0���*���G�������+-��d��8H>�zO?�o_���?~����#U�BSC	 �%VI"#
2�������U�u�u�����;`�P���m��nj�������/����2��,�|9���_=|��"N�W�3L~����W0q};1�F4H pT
���}�.�� �_iD�V����z�9�����&�<���D�]�X�����^��o�r:������
hKXJ?���.&CJ4�)�3Xq]����;��N�qJY^���iq?�61��!DK,��V�����]"�1i�K��})l��+c���7)�a����q����c�bN�v�`��vw��+��2�h�]7Q.-��w0
nT�QU�p��aM�o�I�PKh�s\*>
��lc$w�]���j���fb/rO{id�M��
��dQ+��F�����.�2e�{���	�|D��� �}v��k�:����);�{m{��S~0yx:���!����>��s��p��Q�n�	����	NA��7��SI�C���J��o��8(9�;'#�ciVC���P7����������	c��'mi�]�o-afi�������bp`�3������\�����Y�E;Sm���}v,TG �!Dl��B{`��GA(G�b����\8\�0�Lc�0
8q
�P������}V,(Q���*�����[&e�����V-��<��%	nj�B������i,����9�Hp�^{�w���������L����qo�����b�� ���,I�V��*u��AZ����w�>��8�--�	7���Z�M�����9��t�S����H3�h�8�R.
|R�#-���ca�� (��d��������_D:F=��%���.�*UL|v�p���eZ_���9V��I4�6e������]�h�����u���e�%�X�M�6eOG�	�����c{������!k�!AZ$��F��)��"6#!x��+��p��Y�`�h�2C;@c�I��Y������Q�f��u1���z��P���J�r�Ow�R<�W\�������"�)�(0�q��F�s`���i`p�����}�9|g�$�F���-�G����F�v	�3�f:v[~\"c�v5��#t-�M�/2�������|&w����0#�M��m���NO����n����IlRBbw��JQ�+$����3�q�4D�J�����kf=���a�%��=�A%?��X������e��
�}?�!i`��	\rx�QU�����
(���M��.���xV�O��4H�����?�
Q	������������fC�l�gv����f.�=���n���@�Y�v��J)\��(\����M^�0&^�40v���V�J�G��!=Y��l;����Y����������,����]��m����VQ?��gM����I��otm��;&�
�5�9(����o
*)<�)���'X�����`c
G��qO1?��\����W����heXlr�f�(t�+.��I�Y������s��x�r�nhh�%G���hV������dC�GH���HR���z��<��>�`�fd{8d��<I�%� �����G�	�:�����k����U
��b�Z:�g�k��Te5&4��VA��B��nJ��DG���t0���U�g���{��|���eC?�}>Gj���{Bx�iW��a7:�2�1e����e&R���j��/ Z�D��/�8���H���-aA��)�K��|i�������bW������7����,d��QD������S 'i��'�R^�c�����Jt"�/�Z@ZVI@��P�*k"xBr�fG��KxN4��$����Np���6I@j�@PS�b��|�yzB�T�QSe�|������!7���(\>�.m�|M��/:���qU
�b/d�[���>��$�5�tXmbW���<`5�

�QS��i������ ����I��o�pg��]�g�rp��4���
b�C��B��.?���ng���>0*�}Ju+[�xB6g�n\�,<�%<?$�:��&94a�A���4�:��(�+�$��.��*���q������%��_��F�E�<���7j�h!��HP.��M�*k�8^�?��QU���
��tz���V��h���[v��	N���~,vX��� 1Z�Y��cf�����kp(V����ZN�����G����[�?$���veo�������/Fu�%�@E��.K$9f��N(����X�AX�	�T�4�Y�u#75K�,'�|^ �
M�����H�H��hJ�(�h�%��V���L�A���D�"^&�D/9Ey#uU�L�[=(���W*�����,�?]�0��T�����b�nq�u�"�S��o�T��v�a���qKZ�l��%��W�0
�3�C������ �������
������������/l��ES:�
�i�~�B��-8�A�F��+FHyC��c��}r���OI�X4��0��,u���Z�#�PGad��]����i�����k���X7�(������������������89�Z�j[�s2�������3h��H�[��F��	w1[�4N��7
tQr\�B�Ts"��.f'�C��bO0�\�)�*�����D2��2��G���?�F������ ����^���@��
!�o]�`d��2��_b2w[r6
���z������������D�w+��A-J�km�q�V@q8v���;O1����{�����R����^�H���&��8|��v5!�����z���Eb�������@L,h
�������(��9o�?�(.R����gXGEdH�\>�$���������ck��!�GzB	�D'�����1�����c���:����W����QX@��t�BOv�]�%,����|��+x*��'�������A�qniB�G�o��_Z����@�E�f0���;�6a#�����;�������kW�3�������3�*P���0H{�9�����r��L���~���D]"��d�ii�
�S�M��L�����4,�:qFF1����m	�=�p d���_dU����6U�6�CRa��������zl[5.�q����
��g�r���'�"4�P��_���~\4���L�!V��L���������P,�X�K��
.(c'MFo�����@*D�V"(�(,N����R����.�-���\��3V�
7���2�n�a��X�/���F�)(B��-?C��A��w����G����qPX�����bF������#�-h���
�&�������S#EC���RE���`�Q�]�U�������*�
v4�2���f3�L�e�k�Vt����$�&���i��x������(|#��8/}Go	�!��%������E���jf�����&*�����"dCD(���R*�h@4e\V�Y��?m�C;n�����iJ��M��NY;���z��*��"Hv4�#R��U�JPh!!8*KPu�3x�j����R;Dr6���SL'���x��8anu,�0���3:q�z�8q������R�1�Z�~���m����0�1>
���[����������c����vf��4p�[G\�!���I������eb�����@7+b�6�'=��\��)�.(������k��t�z�h�nYWOp3���(���4�+���+,�FdS;o#o�A���P����`x��$�ntQQ��H%��@5��wHF_�6j���}������A�F���T��u�/o�f$&�Ic�z�������gd\������"jT�\��M����yeh$0"���!X���@���gk���4�1HdN�Q���?�"w�C/[�V��X8L�wa�+Y4P�S
>z�U���hz����G)@���&�����I��&�&����9+�AR�=�n�����+����b��C���E*J��Q� ^��e<�z��"#SD,��0�����gs��w�"+���.X�~)pU���.M���=>�#�0`��$e��(�
c����eJ4/����h>��\W��we���B<!�����T<)u���]�`���k��D�4��KZ1l��4��|m��8�G�Z\_��2�~X5���-^U���F)��v��`(����
6�y}vU3X��������8���7���5�q�>>�3��^1�K���|�7F��K��\��	/�����A�77C�F�^p�bQ�8���w�r6@D��l����x{z0�A��L�Qh����
��HV� �Dd[b3��:d�>�;������7jR�B���dJ�/�"�v���N\�����*���#
��d�>!c-��X�����M�������7�3�Q���y����M���	���@@3J���Y&D��kyX&��.����� D!�u��~?V85�C����V�4x�p���R�c`�<�Z}%�@@���B_�m#��QOn8��]d
��{�=�*����������,���yX��3����
2*�U3��R�N����x:p�"_���G�'
��T���K��>���!�>;���h��{&z�|Q��L�aT[��*����D�-�f��-�og!C������$�j�/`���J�U$rKy$�5x�[�������W4��X��,��a������C�g���?�]���+�J`���7J*��t/��-(H?��Y��3��
��"Q����7�K�	��b�$�l�O!��L&��!7f%�`�Mt������ET�-.\�7�����H���x��v�<Q�=�
�0��8T�h�x��(����!5R=`�)>�]~��.�\�R
��T!|���\D}x6:������#Z�$��w���*_�I���_����Y��BL'E����%�<�$���������K/R��G�����f��]�0Af��=�L��0�2���)x��`���m�;,H����h"�SA�/�BW$$��7�A[�W���e$�RrB9n� ���D��yp?c-�n��;����F�"�J����4��oT
�c;=��l�R�[33� M�Hj�WD����$�va�3z�SY8V�8Yr3���3�iR�$QdY������0Pa�@4����	`P-� e.?|�h�sf���*[��I���Q����X������-����~��Tb�g�}�����i|'�^Z�G��&��.�p&	k���_��H�.|HlSWe����&�� �p��q(� "��z@�$��k�]O���kY)�����4��~^2���r����[D���@��#��u��(s���a�YS�������$2 f�����
	���/������VO��:U����>#4����g�w��2#~������8���!��B��,��UU����>���aK^�9�����M���t��6�-&�_��k���������X�2wD���H���}4�U�������Y�-���������*:5^b��#�d%���A�U��S@����� ������Q!�s3+��0�$���=��r��8FeE0m��`���NB�M%�88�� ��������b��4����^��2 X
����l�Y*,�B��q����ci��(BK�J�=���"�za*�����W�`JG�=��P��~��*K�Z����EO��A&>C��}���w��o�q��_D��`����N<$2d��tC�E�=Z6�����-��Q�"'�Y��r��
+�Z�b�ha��[8c��w0xI�mh���� c��5���~��H!NL���5�*����%J�av`����)B�@����P��
$�����2����m�����3��;]���)]j��n��f�=�a�$a���;�#8.�,X���y��A$�0u������l�w(���#���\�(K��,�X��P9����Z6m�:fNA�_L����,;>��V�@�&����h�R����n���y$�b~R����!�����y��M�1"l�7s�.m���-

�aWSd��Q��)�NFS�R�Q��~2�4V�(�`�c�)�(���9��D���g������O�W�� %�i���k6��(�m,�- �@#E���b|&�g�t���U1����Q��a�"��i���2"��� g�$��w\��
9�y�3!��?e�����1���-y�%�O0�{s�.G��� DX��)��8�KZ	���:�XS[�	8��	�)WQ;&��&�+������$9�=�I��������:eM�q�f�l�Y!�	��N�JQNj�\�&��iw;�i
�?��6L:[�S�L=�Q�p\^8�S�8��<��A1*;^1[)ZR���$!���>�S����&_�U�O*w��,���W}m�����)e)�����+,t^7X�h���y�����Y8�Di
����	.���Q�5�e8�ry������@;�������C��x��(1G
7[]��+���+x������-v�T����,Zb�~&�0��fL,V-�@�R���zP�'���*��]���Aq�I�	��&������B�%}����������zS�J'=p�>�7#s��6 g*[���qg�
���UHu�_�����d�O�����o/��L��4��,fw��
)�1�`0=��+|@u1�F-#�k	�4�9�)'P#�8�t(t������,5��?=I~;U5`�h��L�yW������Y����n+��J�"�$���������L���UJKQ'.�jU��p��`�
C*N��h;Zh��F����]�XO��Bx&4&@�t��
�(o����K�;2$Xra�����)�4+*�rI@�FTr��ip1���b3e�-�1�.���%}���Z�r���-S���n�U��]�(�^@@����������q#j���jhf,X���{�B����E�>��o|[����	�j��1�)�W����F�"��5S��7��<���`�
�'���(h�a�]�]��Mt4=l{YT��Og����82�A��-����+;��M%.Y�[(ld1�T�����<��-�H��Eg����4}l_C�/%��Ee^��2���!J�0�}��q9����O���Z�m�iYTj5�(_�x�* � � �������g��0m���-(�M��`yK)�g $g'��Y
����C� �!whO�B��K�'W+�-�/��nL����I/����.�O�a�Zhk_�OJ\2�A<��\��P�L��>�8��;��h/j��g+��$�!��"��}��&B�\
��;nt�;�"-�����������q^vV��d���`1��*�i�2��_���U��������g
�b	�WA��x@5Y���A�B�[�������I����^H��>9������TN=�?�	?0�E��1��h<�d����Gp]��X��[r~��A�"����%�r�&
+2P�f1�*��a��~��=�UR�.j�	���a��g=�KCs�)S��W,$dR�;Y$z^���@3�@�OK�������jgC��F��,�h����!��K\�������QY��F�V������GoE���x����F�Cf�U���)#������i�N��)��o�����1���@:����j��fg�$�Q�>���Pr;���.�Zn����wBD�;��7H��"�
�?����c)r�>����������W��ta�����������Fu4��$n��#n�$~��	G;����������=F�����3�9Ngz~�R_�2ey���q8��?P*�1��P&��p�$��:L�t��;��#z�%�Q�&����UWEn��F���/��A!5������Ppc�w����lF*U�6
�� ]�c����o�d�j��5R�Va�(G�8 G$���Zh�[-f��*B�Akzc�f�Z$��A-�
U6r+X$Hz�a��1��m'Y����Uf^1����Y���T$��p���B&Rkqxt���Gz��I~C+#C=Q�N
��,�������!��f����
v*��z)����7�w�����C�6�}���z\�Mt���X)79T�F0|A~'�Q���h$l���<?i>��i������A����z2�x�h�X�����r
0;����?h(�?���@�$k�v=Y
�3Ecf>Pt(�L����p$k����Z���5�g�;V5lWO�A6��E���e�F)Q�$Ri�i�#@�-A��}*�N;&nwMf��,]kPg��G�.����rz��Vt��4�9�[��6���LT�2H"w�LG���E��h��X���qf�`���J����������D�@����.���<�S[T�E�l�{D�a`�5�&�
A���W%��h����uZ�����Tbs���������S�ZX��z�D��������1���`��a�L�m_�d��4�2�JJL;^Z9��0�"����44uOSEa��by��CL�I�z���"#�W���F��B,��
��X�ZAl���vD�{c���8�&�lZ���(c���X^�=�@~P�,�Z9iSj`zV���PV��B5F�Ak6�D<��ei���[EB�H�Q���D�����t�kx���:�Q����3��|r���^�'�Lg	��������
���=�*��E6�`#�m\� p���X�d[b�Sf���V�������l0�����e����kS���(�|����i�`�8oC���I��|07��F5���H��������5+�x'	G�G����&Fq��X9��}U0����&"qq��	�Z�X��@��b��\�A9
U�zzL2�t��4����D�!����&�d]���R�Z�:"��`��x�0�*��[����d�-(KI����0?-&ucf�t+m��+A��C8{�n[&	p{���S�'���`�\���Y�F-7;������ ~�E��
;������{�ao���P��e��R��b��y�Sd!�_Yg��%,����	'kvW4���"nV-�ijcz�l�4��3�	�j��Ey'\�&���f�]'*��o��aXFQ�u���hL�e&��
��~���Wa��s��~=u��,�a�
9��*�d�lL �c�1������R$=x4����M`�����Z�	������q� RP��}�!`b'B�e�`�V@#Vdh<�q�� �2�H��&l�*��i����&���F��<���MI\�Nf��E[���~�|����#��'��P������D��rm������X
�+lL�a�J�^��;��Nu���~\6V?��������Kg(��)���MnUAg�0S�xq�Kt�s0������2i�Z;����AP�j����@R��C��HY��d���H���{���9?z�i���M���
(2�9����z�8u��U��k�
���;�W���yD�����}��:4t��L�rVp�#�f;��(u��vQP�D)���u����Aa�s��H"�@t�����Q���4y��Q1�6����@,���P�� ���w8�=P�0-G�?x��t�3�_�.r�=%����Q�a[yi�!tV��u��2l��
��H�<L�O@��}�j8!�:F�J�5����0��%�A�%e\��
=F�i�{�~#�����Q�/Q'��������Te�}#bggo���}uyv��i���
����^����A o����Ng�/j,�T���=�!���L�h4�5l�eX�j*@L^�P���Nx��8C�&��j�i��]h�Q�o������>#V��f�S��,f��� �$C�fH������[L�*����X��1�0�W�5���r���qF���@�NE�]�@r�9����U�ZQ��|�/C��$~�I����rU�<�(4�JF��)m��1����dD�����������m��-���*/�+��G���IHH�r�~����)
a	I?~Dz����.JMH��a�?%��@9����9������6��*�'�*c��M|s�J�����2z��AB��@��20�7�������93:Eh��y������t��j�M���
>h�r�[J6�^��Q��\�����[�/�o����IM����3��V����H2�%
�j�K�U{EM_XrP�����f����G�d ���AEU<R2%z��
pCV	�U�cA��V���`�����A���,��I�_�`�)�D����3#KE���&��2���Z=P��$�	�W� Z��a�R�!J�W�)b13����O��J{��(������s���S���]xnt����\0B2\Z��*��ai������vUQ�Y��g$nX�b���I��=h|q��q=����}�yT(��eh(�B*&��&-�����x<�ZI��g@�.�dB��]�$�]�R�A�kB];I��@=x�a����;p"��q��L"�&I
uK�R�Wk��e�bm��$(������J�t�iAc
	�7��V+���(�:6�T[:���N��S�����`I�T�Tt����6I�	
,QSaAA,���"��&����;���1�p�a�E�`T)p��f�G��u��d�pH�F��#!�lAt�`nG���!�-asi�G5��(���B������I09�Xkq�����U��9X��sw�~��&�����G�AQ�L���
�)j�@~x�E!�����\K�S�(\�8��w�xo�SYZfs�G���P�����1�"q��>�-�����*�
me�^u��33�Bd��o��o�h{�$�B��a&����Zb���io�s0+!BjQx������Vk�(������yT�1���O�{3���I��;�u�|6zX�!y��,��d�I������x�i�uR��V���S�d$���XV1u�b��|}hy�l�h�_q����[(��gm�c�HM���	x*���Q�e�
%e��#H\��wl�F/g��	P3f��!'�@�#R��1��mdz>2}�]{`�
X��9-:D�+�V����I�F�n�R��SJ��fyl��
:~p���h�r�v�F�p�+T<���^��*�XD	1j�h� �H�F���:�qtO6�����=�k<w�"/�����&����s�`��u��H1WVY����h���t(�<�(���`m��L��������$Op�=��Xe3�;.��3HQ�&{��x������\�<��Ir8�|�����b�����`+�/P�����*�������b�Q����
��qj�����j0A�q7��
����~e���R����v�a�o$c21���O�*s��
�V���R1���-:���x�j>i�;�GY168�k�m��������@m��$���a1�}����Z��dX��`+�^��?*�8h��6	�� �!�rq����g��A���%z���>���Ws�?[����T��K����ja����t�1�������>�b���,�dR� B����9 �^9T�q���p
H
0'5-�/�:oh�H]&��$��	V,�R���_�'��3YdR�HCe�(W0�����;|�,S�1����������i;���(3x�H\��F��<��)�3'�AL�k��;�mP���#0'q��G���V��Ml����Y���m�
���0��
�[��fI|�4M�j]�3eRk���>`�"����+}�zWAmM1(��0����>S/�-aSm�����ca7�l�-%�nj�[�����&��_JP��i�
dr�R�����$����`")�bTk����L@��]��m.�
����vL}1,u,����a�f9a(}+��oK_��cQ�^��r��6M��d��H��lW������#AIL/���bY��h�����ln�<�����b�g�n]��tb��L�^M����U�%�U���[rH�#���lL�I!�-��k�3���M5�(A5��}~���`+I�0��)U4+x��t��uF����b�
7�;^3�A�]C48��%{��{T9��=0M���`������F�A���9�:����-�Zb�G�l8>V������u���^Tl@F������=�%�H���������.$`��/*�����.��v�U��J�R���U��#{�>u�����a4��i$���L���;��S�z5MD��E:����-N-�R"��&) ��r),Q�����bV�#I����
��`�Q*�K(q���h%Ux�Md��$'8��AeZ���?��@�U�\ �A�(A��L�A��=:p��>X�Y��a7U`�_�����-��n�>����U������[���Sz����4|+�������d�G9��J���H)���=3�Y�CZ�	�)��+U��g���4Q�V�FZ,��Io���~b�J����i}/�y�������y�Lr ��#B��*����e��D��
�o�S�o��VT&py�����.8�HO$�>�x��u@H2g8Rc�p�r;<�	����j�0��>�P����U9�]^	e��0
P�IES��..z�������Zt4�1�DG��--��=z"Mb�c	6d�B�H�l�g�y�PQq��>�6�R��������"���<���0O
�j0j�7�6���+�wT!�bL���uX��X`��a���As���ZWE4�L���.c9�����'��1C�!�CO�[�1���]�����r��XIPQ�K1�1��#s����J(?5[L]&/~-+Z
j�H�D�nKN�C4N=ZdW��������a=\���
��E�"t-"�H�z��S���B5�;D�X�\�Jc���-�A��.5�b���` �.���bj�&ai���)�	I|�|����I;�	1�c���dK�&�+sX�V{Pr�0�A;|y4�z��+��r��+��8n2�'�x(��F�]2�A�����
A�Q�t����j���y<kD��t��QrJ�ka�����s��
���2�eRM���0����B��c������fK4�)��#�N�d�BDb��#� ������M�;#i	��b29�w��4D������H��Htl}��"K���wH���S	M�Y����	t���iCbS/���8�D����G6oR�)�*Rq^;
��	�B��@�	�j��W(3����U��8,p��u7�E��>�+�B���m.�3~�eo)[I{�=cfE&������!��@%������V��"K��B(�ho�����EA~����'���oP�e�AN
�>�����eFx�
��V���q���l��;����>i�5"���z;c\r��4��������[�w5����m)���0�H�F��b�����T-�0�b}Y� -0V,��)"L����H`���Ec1������`*������Pjnp5%��S�u]��������M\�Eg����+@��K=
�n���-+8H����=Z@9���	D&f�c�j�^|4�@2��|��F���#d�����Z� t`��a���mq��	jy&�"S�uW���?	:��972�l��e[>�f�.��:���2��AOL*T��<
U�"��D
U�.���;"�>k U$��������;p`��(^�d��t��Zs���F1e���sbl4;���:���m�B�0��Z��m#�]��X���Da��%)��#Y�`���P�,�ejd��t��B����U��`v������; ������v�b��!O2Y�Y���������1�@��[d��0F%�f�M��#�q
L����aJ�h�_"b��-842��uA���V��_�����y/�������	q��A��_�;�T�����rYj��(AJ�o��r 2�����]7M:�q���O[Q�(���@[2>�A�}ys����_PO|���	8N��)3C�@��
� |������	T�0P�����M���N?�3���qe�(
���m S#��4C��'3�%&�4o�6�o�k���
],��DCI�����@���O���}�N�a,\Z��xC��1�A����#NqsF\P�`���������[�{����x�i(�j;�	�p�{��Jcm�(a�����[g���o��u~������1eTK����o�
�<�4���"N$�S�/�m"H�h1b�������7����p�@��_��[��
��z�������0h�r�#H���Z)�A��M/6�#�����
��DA��	c�9�`���g�n��m�C��JlQ�3zG�xEOE:M�9Ue���w��-KD�Eq��; 1��q�`���$%;��'&O��*}zKA��O��)2;V�)l;k�	���1"3"�B,wi�	9�`�)q���2|��G7�&(jR(�el�G5cM�:��&�\�/�� t!p��dYTXN��z*������tx�-1�P:�H(jT�G�(\����n�������}��������I�:D�l7�h.b����A����#f4i.����*-F����Db�KaJ�h`m�a-������z���Ud
9�%�
�������o�:�N1�`\^u�'3��t�)���
�uDZj�����~WX-���H����l�&,�=���M��V2rQ�P�_��� �A6��K0	%��GO��[����a���j�=s��� ��$��|��w�t|u�j�6|n��qe��,���G����y����g4�#k��(SV$d���<}R@7+�nEz�]B��?��07��h-���
��p����(�|�??�+�����E�Vi��� ������7,b� {e^,��Q�"MJ����e������������HD�v���yQ&������*�Jf�PC�
%�l7�_�����dt��&�	�Q�E`��~���t�#���,���+g�����h<��w��&�C]0�vd|	�/(U)�u,$��q"JVQ6�z����V�Q��q�1
th�d�a�T����s��K�FN�0��������}��Z��#)���t?]%.�bN:p�!��@�i��z��M��FZ��+P��?��u�3�L
�)���N{����W��fQ�`�Y�8%�nI����d��CY�|>�d9����:1O�Ijf���p������Q�l��{�����{o���V��q�@�>�M [�P�;H1��v�_<(-�,Y����d����?8���!�^+M���|J���U'H��Q�k�����F�������&*�`��|T 3���AP���\�#������]N���C&�����,hRK�Md'�'A�b�3=�I�
;V-hs!k�������C�������pY��H�ar�L�Q��^D~x���^Q��&��������n6G� >i���E]P�$Q?|��P�i�P>��jP3��^c�������������b��v���"��h����$
��\"�O��
W���H���#�=
�����d��%��$b����o�T��
��)�g�s�	����������}��q{�R3���&��#�b�Q�\���/OY�u:x�j��{P2YW�������d4-��[�M'���P��Y�8.|?�a�1�3���b���7{��>A8���74f����feug��|nYh����kX�������a�����
X6��gU�b$j�����7bM�g����Hk4��~C����������Kj0"��(���}����-�Z����@*�f�89H���X����Wx�i$�!�2��7������]����
joa1����UL��%��R�fu+��/�D+������5&V6�#=�uT�L
���t��D�*@e4Z��`E���T�Om��

W�NQ<m�������������=�	��jW�i�P���ve���$~�c�C����|��g����\���HC��$�A���"�.;����m�R�3�������n&w`x���-H"JW~���!������	�_�8��2��I1&D(������C9K������e��8�"���2~|�j�l)�����T(f�������h"5CU����d��bGR����7����=<����j%;������URed�[�i{F	���u�$����&Nj7�������p|aUO��1|"	�S�%|R����Vh�;b���f,�D�� �5�$�P�[���jz:UC���O�nh�L�PA�3:��d�@O	>y_�����O��I���{�������	3�f��U��u],��2m�*������a��q�js�y��`�m��L�s��/E�K��$�L�*�~� �-�4����>F������ �
�\�2zG�F���`�k�#�V+��{$@h
��y�����Jp�0�'��02b���
��n�vj�U-��p�LM�+M�(").�D��q��9��.���c�"�����+�f1b�s�0��@�FtLP���:^�#�xf�2����0-�������������6�]Q#^�Qt@W*2���|��m�wK&r'�
�x�
`��������}<��"JWH���!Z��l=1�����B��0�o"�$�}-�X��~��a�S����H�X��-
����`,`'[V�UU��/BH�����VA���Hs.A������
05��Z`9��v���-�QZ����O����S��,�!����f�Ldh��1����#?�`S�|�7c���"2���<-�1E�l�d�)��`�t��E���}5�q�����x��]��I����_�^V�[�A0�^9�R��-��D�3@_��j�.4�������/#�B�6�82���� ����C5BXG��"��(�GHTTZ��%���@�#�	�eq4�A�6���_?o�.����V�����\s�P[E-�� 7pC�Aa�P�1��lYQn8���� {��x���( ���|�\ QF�1�:1@F=X���~uP�n��X+�5z]�����7`����<����1����D�W�$Tt}pi2�ff6o�Fr�h@E���������;	
<�{�8[��^��,������L�v���T��a�J�#�K7��� D���18���CEir|���{6�;3�k�2QL�6�\[��eI�Y�J���	����@�?�/2����I��Rfj���S�&L=��C`>C>��H�EQ8��VA�������
����V����Yj{�5jB���&�S,��8�V��eUi!gu�I�D
����������2�����7F�h����+X���w%;��t ����f_ ����r����]ot{P��H��%Z�A���p�={��������
-O��`�����f?���J����Qb2	��jB>��'��
����6J����'9�� �����r�C�����g���n�F�uh"E�
�v�\�2Vt/&�i�������Nc��K3TOm�7^8��c��*FbQr�iv���{����=D7�t�u�h���FM|k�H���v}�������8�R����pp�K���%m�^E	G�1������z�p�Y����:O<���]7"U���>���r*��w���
ePfo�b�F��(�f�{���L�@(�}����u������������
�Ao�Kb����B�yTY����8�paj���hv`����I$��b��������"&�[tJ�����p��)�9NhB��_q'�H�4�%W,o|c��p(���"�g;��t�Qd|�������TDg_ta���b U�����������%S��B�
F�$�p�'d�����YZe��}����7�����#A���o�:��������{>�fv?�w����v�n�� �9B�	tA����]��{{���!:qeP<-�(�VT:Q�\��a����oG6�����y�EI'�2d)a���?p�������ShU��0���P���C{�d��a~UR�EE������	k%��c�,f?��'v
��7i4}�e��6)��pg<���B�[t
������kYV�H\9WJ0���z���"6������rz���(c��+c"�d�b ���Z�C��&�e��3�%��F��Ai�h�b;>t�,2r�A P�M`�4dR[��
K ���r��}��j@����t�@���S�#{�����?����k��N�C]��e���C���79�Mh)�=����4m+���WU�eW��.*��4����V2A-c%[i�-;�V2c@��"��`) �O�p�K%]�h�����N���Z�h�����c���$��K������w4���{�����
2��*?pV��oh�������
_v���A"
T��)P�m�|��5~�S��
��?%���r��Zr�y�m	i7h�|:�1YR���%��H��s���vR$=B[&r�B7��V�������81�9��&���D��l��S�/�Va�Y`���`01���^�������8���Mf/p~S�	�'������el�#���n���L���
�J
��~�Ps�F��D�#��,\c[3"�BZ���uJ;&+���u"�l�&���c�H�6��#[���v�cQ"�.5{�"��b%��sP� ~�A
5MB%~;�~�>�XR`�BcwZ>\��N[�j�T�G1�a��h/���9����_�����<�j
��W�z0Cl���:�~�a����������n�;������~���~&�RVJD�M]l����&���J�J5��54
���-��2�������3�6%|�R����&�}!��O�l�Z��L����#�rt%A��������W �C�v8�9d;'h��4l��9��Y�� �}j8��4I,d=���e�V� �~#jcy'_�FY8>�x_��>}�XL:�)Ha��'�d@��q�%��������4 2��9u�j:F���hi]�quG���@e6t��m�]�\
��Y�t�6�&�N�:2�@
.�����
����&�q��EI����25���I��L�v)���a���h�Zv�L��X�8��� !�5�<�pQn��h�$���8d�����!3���e�����Q�@/��	��l�2���� ��4�������*Kk;.(����$�27B:6uh��OwUG�E��N�3����2K&�F?c\w���X9��n�nr��/�"c��uU�VP�Kg��.H�}(a��N��Q��	�w~=gx�n���C�=��:J9�r,i0/�X����q����J��Hb����b���H��t�E����|AMe�N�="�L[�#f��
����NmL`���y��<����.D~e�4��(�D���,7T��Ht�xJ��K �O�6��
�S�����P�2|�m>�&:q��z0@�@��D��h��%�K��ZNLB
��������{Y�
�0���_���1~R
�6����*��DN����Y"�<{���A�U����q�Z4�����v���pksPi�y$�zY3�������<w����m���H�
����-�DE��<�k+�6��jM�5�H���`�u6��4K����o�	-��a�w=)�;����tT7��Ml���#ub���M-(2��T������~�%~Me
��vE�
���F;S�Bu�#�c�n�>t�!>#m�@7��x�;�SG

��h�R
#���Y�F�f�� @�����h,�[�g������B"���=�A��A1-p�E(�!��V�@*�e��n�0
�WB�n��a�H���4���F
�����#k!�

�����@o�1k ��}
+��>�1^�����Uc5����vu�,4���;�S^\�M��B(�h#h��$���d�>�F���=��@��)#�yE��
�|�JJP�m}�z���!1�7��������EwJ]��c<�����
z8�-2��\���%7bN<�>,l��32	�-���$W`�X�ru���/�N��8A��0����1���x�g��������x5��l{��I��m�6u�(P����#�<�=��0e�B�S�k���\V5������b��\����8��_���%�����|:����o�,�5y2e�G c|����stPWK�"nf���wy
�c�����w�~�hk��a;������������K������(�.��|�o����>��W�_����K����p)��~��]{�7��q�����l������<��������?%��I��1����������h�<�.�!�F^�����|���g����|����{y���}��|��������^>�|�sa����w���/����?��o����qw��-����w����������/����o����~�������~���/~���_���������m�8�CK�_��l���o���Gd��${}b�}�h~�������������s;{�_�����w��||_��������~����G��8x���q��N�L.�����m�
>L_o���o��;��j����*,+���q����|X����*��F%����
���e�>�����:���B��V�����I��@��i�]���?��%��U������X�Y@,���x����;�7���j?i!��1��o���O,d-$���~����� �<�Po�����������?�������5O��WB���~�G}����������(
a>���n���t0p���-�y��{1��R����~���E
�"+KA��Y�_�?�`�l�u�7�x����a +�"�*6����A�q-kZjk�i-����Z���l(��X�@�xa `x}z=���Z��t�No�_�EonE��s��w���O�e�I�x�*��p�xb��^@������b-d� �qw�����I�k�vOM���]���?����6�1�Ka�t��V��N�Sf�VV������������~��������(_p[���?������U)w�u���Z-�6��_=e�����S���r>�e=�_R���%�/�?�����_����vG�=��Lw�q����X����M!m��0��*,�����jQ��2L������
>��8�&3;�2L��4��-��<�a�E@y��T��|�ei��J���H))���x�v)���e�PA��`N�����;�a�k�d5v~��y��5OG�]�	(�H�e��v���s9�	���W~h����_G���9���5�@r�c�$����).j���������*�&������q��v5�
�V����9��jO
�-��%;Da0���`��2o�2<B���*3��o�Ak:���Z'���b�����U�3W��~r��^�Q��b!�=i��W��U0��?]����N����d���>����`����3A�o{s���u���*t�:�?�#XLL����� ��0�����wk���vq���7�y��8����d��
����Z�}�h�Ui��Q9�h+�������,@(��	6��:w'�&� ��jr��Ep�����O�v�b��N�I��WR��O���E2kk��^��~J�V�tK�������[LG����d���Q�3��3��T��9���O�!�ZQW��V��?������V5
G��Qw-�^^OGy
`#HWJ�tf��s���S&��V4�7Y0�-��9yX+b?&��j��"���Z��	L�2Gv3���
>�������F��]7C�
!��9��	���t"��
�BJv3�y
��������_��	������Z&,bR
�[K�89X}K|
g7�����2,��i(��.�~nw��X$A��6�E�ue$��Y0��T�j��h�(�� �#q�����^�'�-� ��@'2<s�!��?:(���l�A��fpt���a��L�
P��'U��Y�r�kA3&���=��.�%|�/�=�8���!Q<���a���{{�r}�$���'�Yn����_"]�2��,�v�#`8j���z��1}�LN�z{�DxN�,%<e{�Lig
��Z2���]N>�
]��I�.�����s�v5�D��U��i1������/��������[V�+��"_����}D�C��l@���2����E�t�c
�&��GCI�lTc��63�R���
q�?�fx@����.)��si���1��o�Qi�;;�BR�L�ra���c���S&�!�,�W���u2S������2�LQ~��]���0�����L�u���c�!����?R�!��+7���{s����,��Y���s��*����[}(��D�s$�E�A�/,L�XC�b�����=K��L�7���������)��S#��IA��
�@���I����b���!�����_����/�/� S�7��hN����uI\u}A�dq���Y��f�Q�.�h����l�� #��
(2�'C�R V����������\z�Eh��G&?-�E���yH�$/kK9��P��$�E���L��zR�����BkAZIF�w�Zd
��b2��^DFVBKc����uo�� 6�"�B������k}gd�(!NV����Ad�^j1�����|I`���n���hD��io(~"�X�jU�b+��F�wmF{�T
�i6��5���$��C��Mpo%���`u���P���d�@C��mzD,���m�e&��
z��h��*6��7��b�#�8
�i�%��v�A�J�$'W�(��py7�g����P�����H����?8��-c�[��G'��[�U��EL�P�C���ur����4,�\���.������)�7P� ��[T����sK�/6zb��$��{�&vi

X�LP�#�3tq�_�jAU!�{���oSE����M.P=mK��?Xb��N��T�������P:?R_u��T
�p���Ii�H3(���v:,��e��vw�WA��_��4�����|����h�x7!j���
�E8��.2�J���Y&TD�;`��6�L�;��,R���*�dk��N����K9�V~��qG$������4sa�������1�f��:��zu	���^���v<`.|9��*�WN4B��|�T�#!\������6�e�_luv�X�G��2�L��iX�v����v�D[~�M��C!��k_�q�.�q� +#�b�I�l?9�����>O���b�~G1��I�@?X����r�=@�^'^9��:����R���k������)iJ1}�~�(�U��!zb�,�j[nP�q8������G4k�9�K�t���z/ts�s����K�N�WFG2f�A�������_F�H�%t�bK�ef����������93�b6IY�9Na��7�"�Gd0`C6(�o�c|��iK=r���U3�
��<�A�������mk�P�}zZ���W����L�����ev�C��V���A4(�h	>��?�h����-�,$2��x!�U?��=-��-P�P�q�t�G���K������~��q7��,E���O^��q��Y�f	W�a3"�ci���h0�V���`��'�	3��a7�� �8p���t[�O�����LK�����L�|���k��)��L{�i.gP������!!��1�X�������+��]��am�
�t�r#�G�$/
Y��{`�>gM�����Q�Z��A���F^�m�w90>������}��!��`R���Q��`i�_�w��x�
x+e�R�Wc���R��
qf5���kU��in���%�A��YlA
D�zl��!���&2���$/�]�{�~5��<*��-K��lL�����hJ���v�4A��5u\��c����%�S;fL��
�YDL�KU�X�x�u*��QXK�_�80�k�U����c�+XN���R��*Gg�I$�[��Q��58;u���������C�����Q�>���h5�
	�0��,J����/Hv��f��	�O��R�'�\�X�`,P��c-����;�|@@x�B��uh�	��.��jd��tS����q��x������H��\�^��;l��iUT������{���������iQ�F�k'�k������m��,�]�R:C���wT� dE}�*��,O���?j��dj1�x7��n�I�C�I���\�A���?�$��5j��e���8
6�N�����W�{�U�r�h�c�g���O0��9�*�	1)�Y1�
60���u�0�����3��h�*�=�k�{�g��YN�N��J��t�O��1��k*�����F��b>��"�oO�z�7*�P,����0���"`���]���v�~���:���4�R{@�Q�K�or�*��$����`����k �X��5Cb�Q�	� jkR<�(��)���H�9�H�p�S�e*�h��i:����sP���o���@���Cd`��x������|��D�3��q��2�b�����{�f'��h�J��<��8[
JC&���v�����*���c�n�<u��*k+��%��~�%m&��6#�'�]W��L�!��bK���l�|��
��k]����)�YgG���
YD�*Q^���>�=��y,[����E�����rG�"�S�h��S�1�`1���Y��{��$��D�������-Jx3����Xzt�m.���{����*�[������<i3"���(�z�%���+�1	�"&eq�6g������%�����O�|� e��
NV��\�b#�mA�� �P��1�`���9	:�N�fe{E�������D�j���MB� �o�),�+��+j����%#PK�M���6z������F���].��T��HX�
�xjAhQ�nY,��(���]xv��T�����>����S%W��!�x��Q��5H30^�������d+�w66�v��������;�+O���wl����.����`��.s�n��r�w|�p,�A�T�
�Anp-Y�N�l+��g�%������L�4�KPHeTa�j�~�;S9���~�o)��.)/nL���y����0�6L�Ayj�XYK�W�9�H���F���Z��Q&	��Qa��"H��3TI*K&��`ke�1x9gWN����^5�F���bqU�K�5���5�q�����	�;k]��0��#�z�?u����C\$�OFx�"��>�p�#h<sU��GV,�F{�Y���4���cV//�5���J�V2�2
F��� ���"c���Dv)��K#�.
��5�������
sQ`�I���':&:��me�@�#��.�>�)R��������7��(�l�g�Xt��@���	�SH'�'��U���;8	4yq��~@�Z:	g}�7����T���O��
�`h��b���%s��/�m���0�Q��q��A.�����x�)������%f�lk�C�X���\�����������'P�J)��0 �����K�Lh�W	�#�������	Q[_h0P���b�@S_�ak �������R��lp�����V4��
-���W{W~\���s��:*�tp�^���8�&B��f�q<����"J�kI*h�����I��9�<*���e��S"� ��L����
>��a������gD�C���:�D���+������|��`E�&��E��	nS45
�r���arW4��{����P����B�`+�v
+�30�JwRx�}�R\Z-����k����������{4������[���u\�<f��A3��F���71$�T0Ta��
�g������Fx�:�^�os���(�rc���Y��B�J8�m?����K�blZ���{�4]�����GU�7��&���.ab���D�CMc�+�h����d�'}S{��DIJ(!�#>^8Wh��31�"|*�a�1F�&X�7U�JfY�`�������|��Z0��?�������l0����������
��q�a1����U$L�1D[����������~���Tg�2����i��R[�`V i!�e���7����N5.�v?�>�N��bL�eX�/�q�U��~~��d�P��t��V,�
]��K�����k��(4a��/�d�`�����aJ�<Ed`�%&�d�
B%<&��sPbb�v��d@�6�8��H�i	������p�4�aa���(�#{P�Vi"2��cR?�r�+�u��E������J7�G[@i�e `��������������.�OQ�(kB���H��>^��&�L���6��
��� �-<���L���hH\l����9����~���/VAF^d+�N�M�(��H�(C����,�&{��/��f�9+���/��L<x1���(�r���)�KKsS�l�j�|I`�
���d<`J��c��9E2����>T���n��.#}@T���f�(-CV��t���C��
�I��M�Q(�kYb�--��dd������;^�hp��&tN����������@
vXF��r�~2F���!�)Sp�tP>�G}���s��Q�Q��0����w�%L��{�/,jA9��)r��+=T%'P1�>���al���H����:0�;��x���d����sG^��*�~xM�A�S�������������sFl
���
���+���'�5������m#�(A����LK9b��[��G
�K-e��`�+SCF�Z���tFg���"����=�����T��Vc����?�d��g��wP*���wq��h�P��u���+�C0"u�E0j�$���QK��:un�E\.�J�w^3�!����S�����@2w�
0s��v��>d*������z�S��t �82����r�H��hhnjD�����x-�f-�W��i�Ga�A.
����me���1W�����sv&K�&�u��S��\D���;�$��;R0�B�El�@�
�������������`��QY��~�g�h
��:���f��qe������M{�N,�1^g~��F��j�1��J���7f�`����D���(C�k.o��N$�;�9�_?�U�t&p��C�?�e����pM�A�Z�%)3��.�L��Ch�;l�8eK�m����@\�}�@
7	��L��%.����D��q>���RI�%b��Pg��B'�:����Q�f�"IBW6�5��NsEZ���&�#$5�2�kzi��{c_K���OK �a?�a���S��#+q�������������D����8&}�8P��+����eA����)J�E/����J8��y� \�;��v	��G��A~���aw$��2��h�CR����d�()�4���4LW�`V���N�$*�X�_��$�g4�	�N����F.-[Ja%�3�Gy��
5W��C,#�����_�[�h�l�}c���b��z�0�����p��"���Ap�(����.BoA��\�}?�2���J]��>TI���0Z����oR�<S-Qw���cH;�X�S4�3�(���J*�c���*"�'��KW�.h�0Hd[����(�C�����d�x
VU����S�jfTu��;c��9f�����i��L��	�Z�������a�i;�����C|�����@�^!�x9�	U���T2�i�$�HE����C�O��h�Z��N�-n�� ���-Bj\�F,�M����\A��������,XbY[�+Fz��v����2�����}1��Mm�D��a�J&-B')�������QA)5�����-3�Og^�$P�@�����L
��D:����|�{�Yv+���]Z�$����G�D�I?A�%�2�P!�5�R=�zG�I=6%��@aV��uf�E�jg�)6�6���"Ri�E��T
tv�(h�n8�����}FQ�!iNq�*L'��f�����IKY����.�&:���A�[���/�DD?����
@iNv���D�����c��;3�GF4�A��q
���-�e*Q�0	��QL��
���������9�O|GW�0�'H�D� 1���E��B-�U���u�������5��d%��A��4�!B����}����Ln���u�"D�HU'���Kb�=�������'v��j�E]�N���jC�;��HY1!���Id�5�g�y'A���F��&[V�VkE`!i�����}RF��i����%��m��j���;vB��>��	����z1dm�%vi|9����[���N<��i���d��0-4/�q`�O�H�h������v
�
_w���i��h������AS��H07.�L��"�i����>]n���u��z���e@Q���zDh�Q�H���I�j0Z*#R���;@�-F �,���AH<��: 
�A0Q�P��\���A+A��=<�:X��f4�su�����T�7M��#����� 9�t�F���u>��NP����z��Y�+��-�>�����tH���.2�/�U�|������+����j�3����
�Er����� sE�z�0	T@��97�X^L�����Q3�y��y���[l������F�BW�����th@����ds�v^a�B�v�F���E�JA"}�O��l0U�E4�@�$
];�M��g���%�a�>4�A������v�.�W1��mG��-�4�2��G�>Wz��������v����{���U��s�%���Y�O�V��'1#��B���!t��&���������M]��m�FE������2��$w�����4}�l���$Y&gG�J�54^Zs�i�:� zF�CC���77�Z.j��!c�����3!���[0&T�����`5����4]8��)4�.o��	$YC��$3g*	���E��a5`\T.�4"�^�Jl���D|C���WD���7�'"p@�D�#�G�4����y
Z�>���I7��/��r���q�������n�z���&Iw�B���*��S��;�JB9��$�������E�GQ"�5��u0eoz�SAl�3$�[��G��#j���R�g����	��]�EL1���.���^`�#�j������
��t�h]��I�z�)U0�6��w?���I���C�#=�+���CJ�%yA��w�`
ekV��G���$Q�2���*�W����\���eIdG�&TH��n��a7��4�
8
�����U�)�^"�"�.Mi�\�c�H��Q�Q*���eG��$)���PT��J�"E�5N>��E����L��u�\A�p��io./���d�T(Br������B�3�H�d�����G`k O��3E�@�
�|�L�K�B8K0=�D�	�0\0��3�����H���"~7���d���i���%������]*�� 8�1G������x`�3���@:w=�V|'��F5`A���Y�z)��� ��[��
o+<��ym����'�6�����J���<�p�o;��m����'IeO�Y]�')@X���<��Q��v�F��,�7����������Bqj��m����s���(�������4z���(%S�����\�[�`�,�+���<��5�7����80Zd����A���f]%8h����k�	3��� �n"��L�"���XT�4X�����,&ICA�-�34��\�/YI�Kne��k�`�vQ�AS��{��122H����
�0'	g�p��
n�����}!
���0�DI���3�V����uL��<<�sK�2�\�=��u��H���^��M�K�~���m"�$@�om"Z00s����*��8��s�EB�N��� ;3�d$]#$�JC�W!�;y���&�D��N!�/\�dI����l�Y�
��\.����c_�&���S��3lx�������7�+�DK��4�0y@G������)��h���#�@GI-�J}+�MlI��An���\&`5���� �]Q���,
=^+��[U�GA�����c�#V?EB�#��������,r	�����2s��:����x����gTQQ��S<�."�-x��(X�>��Jf%���<�����#���3�s�0��Q���Q�*8�wQn����j�2I���#$����R�]�+�4�?I�S��������f�O:h�[�@�&�C�����;H�0�j2n��6.��j?��@��7��V�(����#$p�w�^�R7d+{�����a�JW����Ks���Xh�h8����=
7����	F[3P��~��!Re&u1qF��!�5�NA}��|A����4W�2�z��u��\��@^~ap�7���#������HRN(�/��m�3�!Ac&�[�� _��69k��5����XZ%\�3Pa:�y�	�!���4r����O���X����"�������]��V�=%5"R>)�Df�$-��c�Q�E�>��8��w
A,p����G���n�z$/�*��u`��FLk����5�i��.[�r]}���6�����IH*#����>�<�����%qKf�qGHYY|Iph���9������J��J+X�D�<��D���
�C
$%�"	aH�j<tUbTu)�+9���|&�]�R�������^-�����f��j�#b��I���BY�?:L����rB�s�(�i�t��0�*���l��@�E��
	�F,)���IT����K���T
�z����T������G�a�|40����9'��������u"�����c�n�oF�C����D,����.~���%:@|A�����V�����|��cv����b���� 7���3�S��	���r!b�dU���.9 ����#����_]T�up5w#���v����
��$�����O"^=d����H�F����4M���?���7)�:��I�krFDd%������M������|�z�����`��<��:��f!�>��%F��T�T�����������!�0�$�����$;<��D���b�/u5kgP
8���y�Z�EZU���
��ae��D�� PG,##�o���"����x�����
��Py��;e	xG�����;��������M��"���g���A�	��	Lm�����n��E�7���?��1j�3�<���6m����B��"4�wST�W� o�+�r�����f3�����6�YR�Vx�
f��8j�&D+�<��"�"b������MP���f��@�������Y���@	Nc�R. �7��(��Zs�EC��y�~el��Ig��cW�4-��U�X�ScQ�dO��3�|����M�����%�8�v�}�.�P"c;���xlS$�7c���7e��
�r�Y.�7��a��"<�j���V�rq0�S��Hy-���
�N��qt9��x�<�q����,���^A!s�flyM����4����B�����2�0��	��E�0)��&Sh�yQnv��bOtX�|^�l�m�F~���JN��V��#Y��A�r
��W�0��, ���h��w�p�����NeKA#+��)D��gyp��n������z���A�L������dO�\M���Q�BuC9yk�D�8Hj�>4���b1Cey��W���(q�������d����D�������a`��w�3��7��hX�:������UT/c�����5,���*�j��z�p����E�]Q�W�����e}J�f)�Fv��� ��	����8V����Z����(��8��S��@�h��i$�H��p���bSK�4ff!`U�\�S!�b���b��"?@�����+M���U��;���^��*���Cd�uO����hA�B�o8���H�Px�)TW�k:��q���y�����)"����`�Ccn1<
�I
��)��ih�x�&�j��oOFGs�/�~�?����i���4=2���#�c*
��&[$�9/�h��'���aZB�MO�+H�*K�����8/��](Y"���B�y�B��vw3��Ql:����+����\�fad>F��L��_$��zv���?�[�|:�F��K�1d�j� ��T�������b1�peo��[�H\��7+�B#���^` ��5#�W���?���a0��j{�\���R:p}�s,����'j�:��)��)O��+e��)4B�����X�]
�Qm��$�U�����!�7�|�����
��c{���(fZ�]������^y]�8(&B(��b���c����&���7�������i!+tG�]?���@�)�g��{�#���I�[�U���8�FS
���"v*j��X�`f9��t7��1����������R��y"�D�/3);#$��f��L\"���Y�~$E{|K�+��}����=��Y�V�Pqz���G�v4?t�N��f�O�U0�3�WIm��v}	B��#L�;�VZ����5b���#�������9}A�18&29?��4Ls�����z 	[�[wC��������g���n�\��z�"8�O����^���;�"�Q�@%gSo�=!1P8u�W�u$�l�rb+x^�E�(k�y)I~�q�C��o?.�5��[�D�fx$]2����18J��,��?&l�)52lf��A�;����&��V@�L��z��]>���#����S����Z��W1�Z�������<�|���!B���H�.3�	�@���#������4k����������u<��
`�!��=4<{�(��-��ZsH[B8����O=�9�x�T���'����];�$sRI�D��
b��}!�}_A�����f�R�O�]�d���e�R���*I�	Z{H�~���P
�RZ$>��d�5*��.��8<0���-�xj�y����l��nV9k3��'e]\1n&�n�@3�*���+0�����������N�OcQ�1T.�b�t��x��uW�>��sw���n�2E�L�[���0���;Hz���P��.=�*F��%X�%�d�����)2�A���`�Q������U�|�����,�����Z5�]��02f-qI/J�"H3*�@�%
�t����{�hR\���5V�9��Z'��p�(L�Ivz�a��]�63���C����qhcD����� p�#���d��t��d���)��H�`�����:2����V���@b����n��N������.O�@��S5��,U|�MCY���i����q���H^�I����0p�����pT}
���������E�,j��H����9l��kO��+��Q1/���'��
Y�"d`$uH�����l-��.�����i%1J2�&���.@��d �*����U��D!�����Ii
���^a���&�ZO��#���L����?�-2a���+��}T��WU\sk�
�����%W�<�:����E����mu��Z��fZ3p]���K7�t68������E��<*=��\����j�vn��*��D��1G"����*R��-/��H��{"��u����q_7`�����<����h�c����*���B������R� �I����P?C�����\M�pN>1i��^8z�FG_�B\v��4ot��v�<���]��	���� ��(����0Xk��{�CS�E�z��z������Qj��j���#�;�L�l��S����b��pl������8������d���sj����OGqY�7�x�.c���@��>�O�R����b�����=*�&.��*�*bKG����v��|}p�6�*P94U<
�E�����2��E~NI��0���3p�;�P�3�Q��-k@x����"iwsx+�����ldj�[����%/�3�^�����GT��td�f��V�T���H�`/���i1�x+�Ip6	:<g_+,�z���#��L2PdE'�| l�blD*&�]H]H]Gl����D��`Eu��i��������
���m��s�!�F�m$��'�s|�U����	
dS���y#��lp�$r�M�d�4��8��g�u�������'�/��VA`P>�����e-�V���u��(����������6��HkK,�[�������iC�H��Asq�M`"��h`�"��^��B�$����K:�"��l��;��"m�f8�D?F-t�T�S�c!o^���XK�vL<��	;�I��20���\��6H������D�duW7tV�^�~�<b�z�1�]�f8���T��.M�2��<Gd��kG0�����)�C
 X[�/��x�0�Nszrq�3b�f�M,�2����"�������n��<_������k~�����AMD"z]����[r���$8��g}�>$a����"Qq�St���{��[��TE�@%�����T� M�3
������t6NAl@�*^�Uw�UG�
�o���1FS6!#/l���'���J��7�cP5��n�,��A��y���`N�e0CCv���#�Z4����j�H��v2f�r>�4~7f!�����g1�>B:��G�������P��`�3��HZ7�We�)����N/���	�Di=d��Rm��"9��I	�������7K:G�
������4���� ����p���L�n��H����0��?q�v��P�l�3�G�T���������zc.)��q#|����D����D��\��d�7|��cw�}���QO�1a%I(�g&�������Y�'�hZ�
�e�#�)u��^\u�C
����������gr��%A	%�'�����!#��HY^u<�x�t����f�����kM��P)�;���(��"���RE�$����Dr�j��A�o1���s��<�(�����P�6�#�Q����
M������'�FP�a�j$�1Ze&�A�E�����}$�A���2*���X������&�`�ZL�_����g���+���Z��?;��D�0���~	��d�P��y���IF�����g$H]�h�:�����������.��=�
�|�kR�B9���Ec�]6<PZ�V&�}
6b��������Q�t"�t^��+�r���J:��?��6M��d�=���\���
�@���J3[E}���e����y��z*�|���m�i�� ���,L�I#�Yy�'�ue4�Q�z�kB�c*2%��w��J���D�ES"�`���	HpTQ�`����
e���b�)]S���L�������h���e��w�2��������k)m���A5nNE�&T��n����7��f2���8Q�/���a��|4y�;J9W�D�W��!VdN���W�!Q��A�2q����$�*rI�"����1���'�	�7�[v:�R�En_E����^�#�-��7���8hQQ�T����u?4����\�������o
?jwp���M��w�Ax��C)\x?�o���A,ju��N&!
L�hHSM��F����u1�����(����!0��F�����0�5D�
���%���6�V�x�{	0�.���#����p:N6��1�F���T���s���t#��k��F��'J���]N��:����V���3p�"�����Bf��5��t�iL�����F_��}�����vd�q���_��Y��}�RABCa��!R*��I�����!f�'|�v��U�K���)�R��|��x%��F2S"�(~��3��:��O�E�����95�/����(bm��Cs���t���#���Jxc��VwdW7��x1������XZ��
Z����fE�D��=����\�A��2�}�������g�t|���2�N��q�E7���Yq��3�r�)��2�2��y�����}��kJ��,	�:�����!��&�3u��q Y�0��Pc���)�h\Q��)�m���Z�e��������X��kg��S��0��ws�|��``����m;-��xv�@l&O(o�����y-G���~�t���LL6�d
�-A>M5A�/�9�2sw]��}�$��$���v*]�dI���5*���V�A���^L�vdk�C*e0�Q��_A%;#�I��R'�|�'a�&p]�|�8�p���k H���5������/����������Y�������0���K��u��]��"h�G��s�QH}f�~����``����/NT7��Y���61�t�1R������v� qw�P&k�~���g��"	"�x9'ff�[i?�\���&J�v�%��4�@	3r��Xhh����a���j��*�8j�e:O�u:�8!������_��u��g��y����9R>�����Eo4�3�Vw��I��c/�1�2�G��n��+��P|�7�
�R���&p�;�k���i�^�����#b
hcCj�v�JoOM���A�Z�q9a�&���^�4���MA;��A%�b9�k��)�(�����q�j���G���P�d�{�6���z����P�8]����� �u�:�5�����)���B���������BJ��T����(��C�j�[H�B+�Y������V�����	BI5u���QR�m����1:2$�
������fHn�;�����d�����$0v��x��/r��2f��[�����vs63tSq6P
��>����V%]Rb�w�������w)���2uz �cD��
�o��n�<C2��%��=�(���v]����6��i`��-�o���SJ+I���w���5rtaO"���hxX�'ME����1��gG�.�M�/�9�����IP��cQ�����31�F�5@v���4l��b�o	�A�2��:�ZGE�P�z�����`?HY%0��{�6]a�����f�*n&���O<�F��hD�_&�U������%�G+���"W:�?�F�%E5��G|�'�m��!��(��2Pr-�����vMK�����M�n��S��:}e���)=���C�w
�X��l:R��=�wl�������D���a��[]�2��>�������+��&3�F�2h��><&�!�H+'�4�;�����q�M�3�����3y�@���@�xD��bb����kk�o���4R����U��(�x/3T���������
�N���N�"!Dw}���K4��nHJ��#�^K��
X�O�R������GC��X5�����bKX���0iB�^$��[���wEZ�#S>�����g$�FmQ�w��4`h(��B�	w
�y=���3��^�0�Vw/B*�����p�	�j��~.y��g���y]�(��@�on��I��M|m�����2���J�r���dsCK�z
V�� ���h.��H�k��|��w����:$�����*����@sB�j��f�rUm��
���?�q]����O����/IR������9%�q�R� ����[�LE����b�;���b:�b��1B7��K�Zf
��B��H�Th��.���)��`�l��_�5�L����������K�XpE�	����
^1K�/8Yv$�8�Q�.t�;�4����#u�GuqeT� yt#g%��(��r|�D"�6]1����pF�	�/]�����B)Q�u�~V�n���R_�,R�����W�1�+�.4���Q�unX�;�`s�nq�Dp�&�Fn��	��9�RA4C~��1Y�V��1����������[�E�$�(�t���D�BM]��RG!��zn�:�t�2^y���K�(����=.Q8
���pi�:?�@M���j���2��gJ5���c��Z�[�����1���%|������f3g.�h���FoJ��X;��:��,�"i�������l%��'�l�����W%�#����L=4;�ux�l�7���An""3:8���XIBkZ�I�!��51;
	|T����f�}-����"�fIF��B���2IB�_�i��0��LA��]4i��I7���8>����p{��I�z�f6�5������`h�T��:��X�I ~S����X$:#�MT]����z��rD�](��&�F�eJ�QF�[�~���&u����H��8"?G�1�V���\lH���5	�x��3�#����m������� w'V���E)
^q7��wq�u��$�A�3#�b`c��X7�������
��!�B}+2t��� (����,x���������^@5\
�d��l��O�kE���
q�F�����CF,�Ee�T�m�!K#}�����.�Nj$�e8I��-�R���Q��LM'\:�5�����n��Q��4
�<@��D���9Q����a�i�o�!M4�����d�"T;�q�1�9�5Wg�p_
Yi�>�	�s���.Z�k�T�P�����O=a��&i>GMPR����GV�Nea����f� �_��r��/�����T��|������)(
IB��n�4�)Y �M�\��tk��i�;����|c�8�f�(L2��)4�wz����>9������Dp����'#�k�$pv)d��g��)Gk�nP�B�2��w���Y�R�{"��C�@�+Pb#9���f��Q)q�s�4��uB�-g�*��),�v����g>.2'�Q�d����#��cI�$<};���Wq`�9��8�_�h�e!��Q�8��z�"R�x���vK��
MZ
x���o���O��F"�8���k�� K����18�F]�������x��'��yc)��&���l�+�H��'pRE���=F���A�8$��828��(�T*X� ��z�,'�W����U�C����A<���9��%2���.Y���h�p9rO'��	<�0�����!G��t�1��}�u����?e�M�g���ck�?L|�����
��qB��Ms������ADY��I�!�S�c�KA����;_�/�K�\n�xa��m�@����J(��U�m�����Q���������J6����/q�����j���;X�b������`l��r�<N�6�h> Q)��/���5'D?����x�����;�?�e��*&��K����QN	?r�#���i_��qd�g����L[�s�d#�E4������W5�'3k�l$����q
 9E��l�
Q���A���MO�J�tR$|:N#���$��n�,D�6�,9���m�4R���G��`����](�CT��,��|a��*��T�x���%��j�|G��eG���g���=b(�G�Kv�����	������ {} S�
"KZ�/2u�m���lYQ#������L�ygi�C��HK
�����gF��R����V���TTJ3�8p�#��(d��3����}�#�����DW�Y�RT�����fF��1q�UG� IZ�6K�+\����~+Gr
��\
o���u��g3����6�@��s���XN�+dL�U�?�6:�H]�PG)gd��
�^�Yz)�3\���G�)~R�,]N"�R�����
��=	j6��,S�3��� 81�����&���g��u-���
�H�1.d�c �;` ���2[Bd�,���^�3�&rw���o��qGbW��*�4<=V�	L�	����_����:Ni������Q c�@�Pp,�`����8d=��������*�H���e�J��A�;-I8�dfhY�c��]H�H�x��i���S�,���[L������@.j�����4������0Oq��q6I4�����	r����*��V�P���\!k�=�=����I�[;~	���p�������WJ�^�iA-�����0H����}��^��m\@�,������sn��5HMBV��K����(G�A�a]���U>��X��a��O!x����1���s����i�AN�,��x��h�����'�������� 0�������*\r�D��\����`&1,$�C����2
�Z��
�eL�O@�k��.!��#��E-�0a7��a��8IhE3}a��z��4a���~�����
�F����\a���bO���{D�Q���N���E ��)�=��$Z��4V�����f�0��������	����-���^k6��(�
m��21�����L��[�Ha i�f '��}�0�Q���i��!DH���vG�����������E0���FY���g�_=H�����IJ�5[)��5���=�6$&�d%�eS!d@��>�th�l-Q����>Q6�BDs�����M1������@n��"naM�nw��*Qg��M<`�����gq�d�6G"�� �������5r����/\z~��T:R�d��E�DN�����������0��10�&�?�7��L!����G�f���A>�zTT���i��m�+T*�ZlS�`f���	R����m���Q�!M��K���r���E�X�@&�C�^��'��Ed�K,n�� \����	m
�O��(��,����R89�QC���'��$[9.l`�\�I�76�4��+�9�N.THT�,���%�i�D*�����N��p�����n�Mk�=^ +�V|]N�e���(�2��)N�	t��xR��+����<�nK.�;x��$�B���?���GAo2�%h�\�mc������&�e��T.v<F�FV�._�#�g��_��Bt�!@��iF�Bw#( ���n���s TF;X{;����\3w�Y�^���5���sW6bR6��N�?ba�0�3�7n�D/�.}%W�[q��n
�M�BG<��QZ��W����M4R�6g@X{B_��8S��������������`3LN:���e ���|�Z19L��TF�&�����"���X�T' `���q����lQ���T�#Q5�/Ix��+�b�Q�L8�l;���|���f7
����a���B�g�*���`��4K!�Z$HI#������)MJ5i"b�!h6��l\f���i`4�K(Ol O�)K���#c��aQIq%���w���x
;�����%'��v'�df�v�fLc��mcC_r���/K�����o��V��&����|���/������������o��������~��1������96�o����~Bn�I����w�����
�_����~�W������x*���'������z��&�R�xL�?����/�����������'����������?����������o�x��/�}�?���/�������?���?��_a3~�������Wo������w��.��o���������_����_����_������x;������?�{^��+~�_�#0B;���S{���{�O�x:�����>}����������t�����7��x�����6�m	cW�.����3O��y<������|�"[������?��6r�l&�����������W�b?����""��j���sV[������<��w�x�������1J����w���#�>26������������a�7!����������g�b!����	�S
��y�E�sr"��hw�r!���7����"���������c2�>d|��__F��06`k?����������N� Q
�&h������������������|�
X'7G|{����e����,!"'����������X��D�b:��?/�[��"y�+y�/�R*������\i�?3 �_��?##����/���x��)$���|���
�@)�r9������	��v���gF�/nJ�XQ~|Y���7�e�i����3c��c���j�����T�L�`�r4���X�~9@����>,�����r�A&d��$~u9�%b�����A����E]m�����������o���x�I��1�������"	������~�����������+&���E�������������~�����I��������_������*i|-�<q_1t��_�I�0�����h�	�|��,�zd��P��N����>��E=������=���w��"a���;��~��Z48@�" �������ZM}-@�2�G��|���+4W�'�J*?!�|2$<+�&���F"��^~b��gh)A1*C� '�
�^~xU���~�c��D���0B���~P��x�s��Z$��_:�@��M��������L��o�O�Y�Oq=%��(*�Ym���+�q�S�@�����-9�����-��1���3o���e=����!��V�s�~���\h�#���g�z������ve��3?+c���@�#\!�f2���@
�L���i�gin-�� �.@,����)����7�@��d��]�\a�w!��S�����>��
z�B�J,�1�~�������-�0����|����qD�D^�h� t<�����
�{k�6������\����L�"�Z�<�/����Zi�]��k t���r�@`�e���q�`�5��q��gw��g�/=9I1�s�����%&L�f�
���Q�!����
 \{zv���u���1^QL��~L�jF�n������,�u}|�N1�A��d������mc}���������u!�c���x���K��o�u��_	�x�f�h�_���kD�'�b: f%{��-i��V�y0�������Q�k#�@���3)�I]�S�!<��=�gX������;||V��r�5I��d���r����)�LyeB�cM��b-GFu��U�l�_^#D��	�7����t)��y�A4K��Y��h����Q����K����=i�-7�@�EN�`�7�!��%
��cb�g��K`�jB���XZ��@3���2��8� s�����d�7�(�-)��R�(~j��@ND�U(��=x�c����q
Y��^���z
#��S��yW<��+w�&�DE*m�G�����S!/-����ERQ���P���8sLD�D�4��m�I]d�������x�"vqO[&���vYO�i���?��J"�IX
�#[���������r��Y��8QM��3�|�p�TH�;�J�� V�a!	��a���e^"=���&�D��48�7����������������{��5�4!}T�o�j��+=i1=���&�T�����a�V�	�4��p����JM��Wn������ 2"/�8�0,	���^L�}�?iFA
mi�DF3��okpC
�.km ����H\�B"GvnL��/�������*n�^�����@�AO�H�Q�7�h��J����$�j��l�����<�=l����-3P�Veq�_�^hke��n�����X+�X�����]���Yi\���p��L�3^�q����\�S�/&.���������b�����&�p��%k�`�Y������Z�`%�J�;��//w��(D0�F�@D������r��A��k���v��:����7���J�F��S#N��)-�����L���<�S�"P����^�
���!`�F
��w���~S<.l���=�����(�D�k�B#������.X�U3s_�����#(	�,�������&�riV��f�@%}�����EF��*p����QSE�i���(54�G#�}4�H��]���Q2,yX���.��b�xl��z���|��o��XU�+�������U�	R&���=U��Hd��
"��������gj��ip�G��$vq����^�#�����;�'����H�/��c��Vn�Yv��{�U�a9�rK�)��H�{�~8�zR�bl���g��*��HD ����`���g���V��k\kAq�^���Az�� �'u�y����-#�Ua�0���{���8�?R	f��M~�p��	~�~fc����3U�/�Y�Dh���$�Q�����(�f��d/����r����(����dD���\��C�Q�3����'6�����w���iCk���<�mj�5�:��6b��$���������
��r�N�M?i1��:3�L�pZKd�X/�����q��������,�V1��O&	!5�W@��H�����}>BgU.���������p��?o�:h�\L����t\��9��H���'P8K���������%�����n�l��>Vy����G�tE�/\0;�[+�U��*7�l�[���� Q�8l��@�!(v��/��a
����f#�h���$�������6/t�
z��Nl��7��/�"'n�oE�<f�w
L942�F�[�dz�����]C��24������~9e�����L�gT�02��Z�q?��G�Xp<%����|���� O�T����=��2�?(�,��-��{���������t���Yoh�^j����i������X)�����:��>~c���{`��_"�@d�g^��E�� &���0^�_�t1l�A����r���}'��DPA������5c����f1
c����'F�F
@*����{��h��1��Tp�3(^���I
����3s���7�}:��0������r�m�Z�@k�R�nBK���������4���I��L��������&����*L%���/!)���V&��i��R��8��8���*�PsH���
�(��|� ��4Q��G�� ���
��9��	�]_��t����2�^D�c����rPK�rD���\�B��F���<O:L� T��hDv3^U-��;�i��$Ie,"@uLK
��N��M����%J��Qu�-�5Rm:�����g������iG��]�����a�u���o�z��H�Nz;R��#=����)f$���J4U\�"&��!E@R�5�,������a��S����98���������D��c���3]%z[��T�B�����Y�,��q�6)�`�(
y&�2Q�S��qyn"{����V��E�1�t�*��<I8����g�g������5183�����l	�1���|K�=�z#
cu_ �(/���c<�,��7w4t��N#��mYqd�pY�����f���p�,>!��������_�9)�|	�Pz�����/���P��J�T������I)�%{�F����	FL�v�%Q)�����&
h�Y�_�\�����c�-yfr.�h���8j�%P�����@���()�����M��L�����2�4�����*S�qdXF�v[B
�"o�����u%\9���V�h�&�c��,M_'�m�E]-(*�]�������=�&�V^����8I�J����\��w���qQSp��������|B8�\j�A���^	�wnYCjs�l�E#�$cY� �������+F����
��q���q��+�6��D�zo(�+�+3#��=���;W3(D�w���$��!��f���/����6X��!k��D(��������k��p3��me���bRq�D��(.F��1����8�=Af�8tLs,p�.��f�p&�G�8�{?L�V���A�c<O�-�&�v�-
����������31D��-7�Sr�g�fx.��������>2�}N��"i�pW^���#��)��(� Q�U�#���d�����M��Njv�*�x������{L���(Tp���� ���u�A��2�
�� E���1Q�_�Ah?" ��{>7g�E�ZnlRH�&��8��DW
�U�}ZC�B�J��	��)����<l���^����4�_�E}��
��{��p;��e�E[��8���Dj<�trq3�Xk���T��B
�o�cKQ�tQ�Zq�R� q���&�I��XA�$�a���J�)�����$�n�EB�`�d�h�Z�Rr�����Nv.�D����jh�0%����P�����6%ef������q���%B]���{����
HJ�bI�x�gu��{%�.��4�[���}!���Q�E �����C�����������t��^Yc�4���E�qp�qW�Z������]
�Q���*aQ	A��$���#U���m�A\��Y	�\5�T�����)
zCcfh�C��{���:�� ��%�}���[��Ly�CcwP��F'F��Z�r0N��6���_�8%�X�OU�2P�Q�:<�����%�����qc��#��2�I���}���y'���V�X&���2�B5Z����b]�,	>&0
���������mN{�����s��>
w���+i�"�c!/x��+�xfx��AB"�����7�e��6$�w$9�=�D!�EX�D�0������^�0"�����1�,sI��l�t�����
0Ew�m����%`�#l�on"o�����8c�
F~l����e�xM��r������r7�u����^��-?#���7�i��xo��YT���duL��,��{��0�6)&�4��xt�OP��J����v"E��zhs0�d���j�q�C��u��H����$\���#�F�3^9���>��X����UF�Ag��C�������w�rI��4��G6�C����?���)
�Y�����#��
-��K�����)����b�]�����cb��W��:!v�6xeKU�<�8o���"S��M����,�%�4�L+�������f�c�c
���%l�P�y�dm`L�S@��d������#��4]�Q	o]��3��;�i��|������+��$�eQ�M�!��J/>�vP�c��NJd<�����{�M���A���������Ffh�{!k�8�>��L7�v�B:N#���bp�wt�uMY��SM�n��<�
�T����&]@��+.�<����1�+��u�R�]�IMoL������@��8z8��������Ycw��~j�$=;&
X3Eb:&%�?�!'��nH)����A�h/�T>B	�e��V!dW�|��k>�G��bY8$5w��r2�e��L��t��g�s��E���8EE�L��m��B��
��{1�
��u�i��iV��LwM*���b�3�x.>����qm3k��c��������0����q\����!6t�3�m�g���C3�����mcx��{G���f3F�7p&�~x����L��������&��j�Ju*_���Bl������/]���]eFw��3bt���@K���M������Y�nj��W
Z E���/�[57
�&��X�ddM)��<|?�P�7�����v+8�����@,&���L���oN~�@d��#�<���A�E5!#�1H2�c����U�ed����s��q#�h�2�}�����LxC}r�|�%���o��a���kE����3�GD=^K��~�/���|���8��Q[�H4�(�� �Ol�,�b�fK��F���FC����cd3�L��]���$��N�E��4��q���7^C"jf�d�+���l�������M�Vam���/_{"ha�C~������kPNHn/Z���m��i�_
��-���Q�^pI�%�*��*e�����oil7�Yg"SA�A��vW*ngqE��:������F3Mz{�*��j�&�t>q�T4 ��{�R�=c[�c�A�����s��e�RZ���w3Y��	q`d��,�#�P�%�y�_�A<�y��~����
���c(��I����OGe���-�&�
dX�C��%s1���`��D��x0�^����]{�D`�D&�1���
�'�W]�5f�E@��u�zx�������;r@�X��1�a2Mhi�A�@��4~`i�{����}_4`a�D[Lw�K{� M'���(#��n�*���D�Lr���`����P�8?��lg�.�UL��+�dH��m8��U������b(�P�����gD#@%Z�����K��x�IQ���w����k��h���lji�En��Qi�!�|t����?���!0	��p��K[�.b>�@�������������[��v�0�:���>��<������J�������~�@�:�w\_:���8F.5K$n�rdi�&B��vbS�����a����TI���6�\ ��l&�X'��TQ���*M�YN��u�I�\��0�����ACl�1h�9�9N�EM�b����k����=��w��
"�@c�d�
�)�q*c�����J���})�u@6�;JR�"2����2���yL��H�`o#m�6,0�D�_�]y�����?�c����������V��1u��i�#�������Q���w�����������q}j�{�9���@������h�t�i<���g����'G+��V��2��\J6`�r�sOF�	�A]p�'��y�G�hj��K�L�a�Ob$����lOP4���`X�P�����������%�9e�b5��i����L����I(����,T�UM���]�u���C_����'l��g�.��A�T96b���0C������W����44w��t�0�4��#K���`�L�q�����:��dU�U^���	�Z*k��
A0h�B�C�DNr�n�F�<�c������9<0J�j��"u�=��%��I�Ti����C����H<A8����f;b~����||���iMg�B&��������i:�T+�P���~�,H@����}��Wb�
���_���L��������n,�������U�����`Wa�D��j+*���Dn���$M,����
O����d�t�c�(���5�`�:7����]pl<�j8,8�`�9@�Jn�\�������E]9�<5	n������O�!Sq��#Q��
bm����Tq�++���q+���c���23���^�p�Z�Is�n���!I�K��������/��P��y��8�r ��D�D= �o�j|B`v���&!�������K_p�8=3&�.�`9G?W1$b}F&�t���c�LYE�q��y����+�
�
�
}���}��ep��l��~���
N�%�;J�!�uT�N�F�b�_9r��r��I�p! q/7&����x{�
�F�lG�;]B-����@������2Oof��1����]�.k����9u�$��Dm��?�G��k�>+��8�8]knF|�G�c[�����QH����h��K�������CP�����k��y���d����T���;����4�z%22�5M��],8���&,�K��C�u�	�#��!E�6I������v���=�B�S����\�D�eH�0Q�N��&%�I��:F����a:e\��:�P���M�	�G�1xVt�7V���L�8���a"�B}���zr��(��})��nda�!�����W@~�s�n�(1g�-1
w��i��%��5���g���S�u6/��$�c��J*'�]�7r�M�U��$
��/Z�	���n:��������\��n��y7���N�X}n�>�JGj�M^H�a�YK�W����@�b#g8���m����.�-	������K����u�Q-$������	��+ER��YR1I$Ih�_�d���4:a�m$�4
"3OK��4�ji��[`0�w��������PL�l2�D��v�z�����R3�c$��	5�=�MZ�E�h���d=R�;��7X���#0�/1�8#��a@���
Q�KQ$�e0��M�T��������i�1�QD~4���Bw��E��%��A��b�p=*T���"c�C�m ���q
D�G��E���	��E�~�>s�y���EF�4;TTL�����B�����9>X�����VA��yR3�_�B�]o��t|t;�ro��G���3��a�����|���B��b'�hKN�=L~m[�aA�}�r�����s� 8��F��8|Z{R��hg������C�����5�B�����(+�sx7�7������:z����6]��R�����k��4�7��+�Jx>�d��q'����8E2��X���F�07I���rKCh"7��*��;����x� [�C�����(�=�#pL��S9 h����W��0��|$3��b"��q���/��� �c{�[v�,(h�����9-�%��w5�"��^�u1R��}X�Z�����FT�������F��j�M`(�Z���j�+l�n����A�����^q���C���(�� J������6N�3@
��$s����4	���>-
�44�\� ������m|���#i��R�j���*2%��`��$ ��	�PG�i�c{�My���1f�������C��Sb+��`�J���c�,����V
�b?o?L
>�:�B�����P2��86�%�`�q�V_�F$6���"��-	Z�y<z�]E��~c�wD��F`7�@�aQI!Gc�z/���]H{"��l����
��r���$1=����}) ki�1t�d��T�TM���$f�Cu)�����s���}�6|��w60�E�m�i8m@}E~ OH���H�`����:����%<�H�#R�1�������FE��)r�
�!�|/>v^[]�BP�bT�]G�{8C��d#�\��6�yx�@��3�p�G�UQ��#���:-���g��H��a9�.��O1���oi��'B���R�F7t�l��'�a�*����K�`H��QD�A���6eq~��&/HK��p5����yo���H��_��m�.'��0��>2J8w�$�2n*�T`QK��Q�,���W#��J*Kb^>M��HR�v24j���?����]�H6
�)
8}�x��JA�p6c	��.�!-�r[�l�j��iD�`��\
q&�^N/	��������	s�
1y���FP�v � ��Q(�Y�7N����z�.b�h�����H��W|��,�i����� �D`!��"���\{�p���T��!P)6{{���tPHk�(�W
��r�p�7�3s�3Z��w
����Qr���@�!+
�aq4�^m��WM�����~�������^��S�[�����)��bHt��B�~#�g>��7�D
����4��)CdX��s�j�Ri9
�y����H-<��;^KBgn�(I�]C[>\�-}`^=~.����
E�c��'Bsf�����<fYL���"�Dbp�����Y!iD)�B�>M��;����b��yO���Fz�-$��k�Tmcg����I���B���e���hpT�"�9��l6��{������O:7P������:a��h�����8�i!�x
;R�FM<�"A�i�	�X��������4��(�V>�hD}r0����%�,�9�~'h!�!(���������^���o�>����#
%@x��S��j\��t�#e��K�T��<�����%g���N����}�Yic{�p����?�������v�Pa��j'>�S��.
?����hX�8������e�0�qvk�����Y�f�5j'�M��L��E��h����dJ�>[���V����B;XUL��U�.�=�JM6�`�`I��sB��C�{�P\}������8O����h����B�L-��A�1���7W��ib�k�4h
0���%-C����D�uX�VK���� E�rC���2t}��]������5L�x~%��B5:<c?�9���
��k��'7|�Jj�/��;�]g���N��|�	�[O]�����xN���,�q���E�#�����7��Ab��;��(Z�����y��.��:g���!6"~��G��B��Y�:)�O3���	�=�)eJ0��Y����b��U(mIe&&N����Jz�t0�Y���|�0!�r����8O��]��.��q^��V	13#n�X��v2���g�M������+���C��g
N���Z?���F]i@����8<N�6b�tP�Cq�_��A��-3Wd���[2O�>���k-ieq����nB�GQ�SdZ�Xk��}n�P����wR�)S�cd���\�c$l$���H��
��o6���0�WZ`@�`�>����O��-�7(
PN3�q��Q,J�<����]Y(�%V����I?dU�8V��Q��:���0"��S�}�8(���DDg�Du|�4!�%��
o8P�)� �u�����?�PIXzpz�a}��"kB^>2.��s$j��H��`d��fgY����o
7kx���vWP�/2�S���=��<M\�x�+�+�h��(v�8�v��?386s~{B��	�]h��J2�}5DA<��J	��(��DBmC]Z����!�E5�$���t:>��x�EhNd����]M7/"$'�f^mL5�������2�����-�*��e��\2�!���~*����S�B��{�8#[��}����*t�z�!#�i�.;�HYjG�#��#Y���<%�oS�1.3,Nh��lyi�{��������HjK�����Z^J��"���WJN���w	�:�])�|��������x�a�v�h��!�AJ����iOq�#��r�3�6��S:a�|�����4E(�"hLK>�����1��d|����X�=�����i\.����,�R	Bf�t&S�E���*m�(�X�L��\Qu�j���ah� ��z�lF��^��� #1p�5�AA�2�}cI�5#����Ze�9�
Tu������iE�0}0����2G9�q8�}�LN5+NH8�$������M���nf3��.��'����if�Uh?WA�����J}�x�t#|l���� $�P��:!���7�w�+�du`}�j��&��;��--Af���Nb\��t�33��P[~R�2�>0M>���X���D�3M������3]���b��o���ixO�	w�%+8�9
��I�Q���Z�/XPtM+Pqd���H�R�/������ M��w8��@�+��"�^l�)���$�2�\R�������H�2�)���!\����8;�u���B�,��H
�4T�~������I���t�up:��
F����$�Q��A~Bv=/mC��\�T~h�g�����[Bx3��~�c�V�
�
\���>&��0��{"�mD�y�{��o�St�����Q���	� v�K3>P��a��T������w��6j��a�����{���%�����6���Wbi6*�&(�W9]m^bWN�
@�i�Y��C�= �����T���4L��u����
�Y����gI��u��$Q�G�J~J�-�����]�Q4�D5��/��+M�wb�P����;�k�mC1�x��;��'W>|���Z���s��o�� �@�����PX��F<��0+��4�O�zB�uO&$U�{��@��\�L[����x���s��}���7,����E�9�~<��QC��l4\M6��P��Y@r�n�vq�f �H�
5�$bHr���`��"���xe>��c�f�`��T=�a�[�.�!(�Kn)~'����
E��B9�6��U����#�<�����gyN��^O�
��"m�4���#�����o�Y�b��F���*#'".�p��W��EtW@�e� {�vZG��s�QTNC��|�:��t���tmH�6�p%�/�I�`���B��������,!I�gD���`�t
�����Q��fRE�C-V{
���b�-A#9$��K"A�(l������P	]	"�t(���["����|����'�}��V���g��(xYS���r���< ?�F2Q�v(�����[���E�<�S�Uj�7q`�q����0�S�u�����Uf�oA�c���7�VBJ`3���.����VQ��FY;!
+���|�U��S��������V������A���bcCOv�mIY@P�U:b�G�\H$��Z������Y���������O��+�dH���?!pkqI�a5�w�L�b�����}�4#{
�����Rp��qp�����|qE�1.���n�	�y"�f����*��Z�����&t&s������h��H(�b;mP���N?�aBc��~�(�>b�gL�x\�������$�:�]6<��R���C;�~�`��h����b%�H�@PB&���O��������~�}K��c���,��-O��d[��nxO�D�e���.��a���@oI�t#1�1�*���/������:�������s�A���iC����S�W�k��&4�e������8�cL�M5#Hl�t?�yk�p�a��/xT���5'`��h$��l��NC
���s!��$Cd���
�� Z1����`��eJ�;_G��t:�v�� b���e�hQ�p��Y.64��}�3��$��h{�������6�!�l�7��T���)���oB6�>b'�r�u B�AE��DE��U�
�+-$��]�!m�}n��C����\�=��Hy������g+f����&�!* �*L4�Vs�f�R�z����>	F���1�������^&�"t�0����5'���:���q8����-��M��%2��~x� �-
r��������V�)�a9�a@����������n@�-�a���N��f=�~��Dm�s��j��6�kJB'��z����K�,����U5#oGO�q9P�A���
��:nR������@b'������ e>��{�d�f7���0m�5�e���V��j����,�q
�E��&9�������F��N!)���.c2X�qT�I`5i�7�_VdH���*��{����e�$�����p�<����������9
t8M0�\�M,�:��8"�� C �;���>����VnF���E����v<��3�1�a�hvl���O�c���
I�q���7��0����E1��#�<�4�w_PT���$$�����$]�YW;7PG8==������$�H$I�.��2��,�A�����G��H0���QR����y�p������"��yW����L�R,H��Z�8�S���0"��;n�0
��S��� ��7�$�Q��(wx��Z��FN���D�QMd���3����t��;�Wy�7��+��E�[��|~Y������	M\�*�+ �z$��M����wL��=���b{��7~QGD��X�U�"�tx1�u+�N
J��
�E5�UP�LI&UmL�@!��x�S���Z�Mb����������w5x�,3���I�<7������n��!���[����P7S�2
������`
)�2��3<>�A�=��8��~F�Z��M�����]/�;�
�Ir�G��Rk9���#y�T�������������pZ��-�}�H����]�?�("t��to�D��5��F�U09����Hd2R����06����g�z6"��NJD���4#na/�<�2
Eo���$�q��b�MP�"�c�B,���u�(�����%�
�z����I�!P������q�������8J�F�@��('b�rYN��P�[9��RO�G�RitcT�E�5��Oi���	��F�'"�5t���/@��������|"'[��A8��Gu���)V�u
�����g;Cl�ZhR�(����n.����.���\O1`�� Uw�;���s"�4��h7#)c���n��=���K�J%]DZ!��
�VU��i#��
g���������=R�93�uj�;���-���<��Z�Fq��d�"������#��b<�u������~)���Di�n�$@��d�����@�iID���&n!`'�#`g�~�����T�Y�U}�$�}!��!���]����{�&�,A�i.'w��"bI���j@�\Nl����5������f\��h'�s�(��h�S���!�8b0���_7l�%@;�����uO/��pn���N2�B����M��DQ^�]���-A����J���.a�{�u��;"mZm�b(}`?%G��� �>��R4��
�w�j�
�m����As1D��������v&��W��_QKXT���`��w2-Z���f�F�����"d��@���YY�7�u?N�->*SBCd�e	Z.�A��9��8���e������X� ����	)��/��4��	{I2_��qV����Y_�6�-��6A�,�2
M�V�����S5T����/y'�C3E�-����8b�/�=�����T����r2�n��'�����=�{��1F(,�'�|-��3���HP�}�����.��9xTy�S��54�L��X�c	0|n$��,x /D�l����(���veR�g6&r0�`���\��L�E"��t����M���������SW<�y[+/������9��m���LWA��O[���q�0�|d��f41���r��r��b���iG;�b������?6����tjz��N,U
6E�@��,�	X����������1
e�1]���H7��,c��t��;P�ic�i�����>0���jV5���?�@�D���kT%m�M!DY�:�
O"*m�	��i�C�7��L��������T�E��9��>��[�7�"����a�������.5�)�h�p��D7�P���[������oM��dv�t��b���L�DT1���/p��e��]�I$��N�a�g�@}*!z�E7�kl���b�XY���xk8�]�����~�9�re����LnO�!�,����{��2�U�%{�#�waK����N�����gt3���l`�b�A��Pe�����G��W��V��/�|(���~����Fq�z� ����8�o[g���*���n/�b�X�z���`�J������&�*+��d�$�����}���|��v��4��(f*n�5���R�)C�w�- m�<��RN��9��+'�!CAr��u����U@>{�b�8�E<���O��� YQ��z���c���7��KRJ���FU���bc�����~��cMd,F*��}�Aob���P��$�`EQ�(m�����_fzr�
�Q�-�.���a��=�U�
�n��@���P��E�.I+v��_�od|������/�W��P����+��C�����v&�����]	K�]��r������2���)}��9X����z�RD�����D����.�2�ye��������5yq&r�/�������yx@�\S ]C���cI
,$*6B��%��M�����|�������[%36�{��}��.�:~��1�bSX���A���v�>udt�
Q�8��u*mz�]����N���� c��4������nW�������@�O�(���0���#�a����#�	��c���PQ\��x��K'�5h����66�X�����t��"t`�=/�Y���A�7�$a7��#6d���JsW�������ZQ�uf���NK��7��hre��������"����=�����r>9`c`��S=%T��ki������A�QT��&�M�L��c3�#���-�������bc�f�!9�i��������������U��9\
�kn��PWc�����WGe#��y<*F�l�E��cd8�k�	V����91q��Q������G��}/t�����8
��T�=�M�|B�eh�I�y/v_wTe�W~�Nn��b��M�0�;���w3�
�Q:uuiQ-��Y���)�DuA��� �)�����p:��������t4�j�6.3,w+�'�>���=��*$&(L%�����c|0CJ wX_�2�q���b��@{�>�kPt2�S��S���M�X��A���{q���j�B8�#���m�� �����L�ibC9�aq1�v|��
����5����UCw��\��PA:M������K���r�H�;q��_�"�p����\�$7�(��������0F��q��L�P"w���u��
J��-#U��^�HH�A�F�;����G��I�Ks�KBE�#4w')#5����:^��Gwz��W���������*
3� [�(��jl%<�`��������Z�'�y��UF�/_�X)U�4Lp�����]���UQ���b��f��[�~I�,^��9L��$YL#,���K2'��&%m��A ���/U�S�a��_���;^(:�����i�$8�iK�a�����.o�$��|8���pM7����x�uFeD��� �c�H3J��`��d5a6�����}�� �q����{>�:"z�C�]�((��b�Oe*<�K��������F�!�%d���T_��)(�����X������������]���[��Ks��l2�
�TF�t;@f��f��h��v��h������K��"E��#zQ�31k������9~ �#
��5~~���L��p}��.ON4U1v��A���7�
���a<G�@�l��<�:)6��
#�l*Z�=�n�����dH=���b���o�9:�#9�����pQ���1�
B���R��.$� ���y
b���G'j����D��
�Z�����@��'�Y!+g3�3k�7��b�rN������?�{AoL+Yq��RR��	�`$:�B�cY,�Y��W����s��5�L$������q���MA�V�s���.k�.=�c_�� x*��;��E&hT��I��rI��WIG�DA��h���>����l��Z6l�x��H�|?#�]Wjs��j-����'
G>��������o�iX^��9wns���6������0Pn�cE;6�=�F�]�[n�oe�l%�p��
a�!����1r4%��P�;��D&�����A�-�$�'x%�����C���@�pU�=�����Y0��Ms�jZpL��������������3_-D�:��j�=9s����r~��T.�j|��
�quY7��Z�l"E��t�L�*����d�~r!�:�rN,��F�m�����jCh����,�h�`6&J�F?~\��)m�R��"T9T|]�|YRK�~����
��f���%e�CQWN!�xf(���/�|���:��FD�$�30��,�0� o���*��E�m����LS�y�	
�:������<D��7����uVd�=��f��������! �z%���j��qp����[��F�������A��]�Q��H5���~�y�������	���3Q���F-��x}+�h(�����6��&� ���G������q-t�]��T��9hd2�����S7�$�����Ox�v\�]�����hN]��	�����C~�5����� 0dS1A�+�~�}��0�A��8X[��`w��G��}t���C�<�z'���]"�������*��i��<mDk@�;���A���5�S0[����aR�
]�x���pS�>.�#��L����`��=>%�(�;:��f^?N 
�%�OF�/����l�����->?����|,L9�h��(��.;�q�"���C�*���3�\���c�����L��\�[�,�T1����"WTNNLqR.&��#Z�������8�0�@]�Z/i&p^����Q4����AZ�����v1~d�*
Z!�H��4��������;M��5�-(a\3��m,1����6S����g��$�����)?��cD<-j�"Y	���e�U�N�0��c#vy�lx���+�\~�s�D��L��(k��o��T[IZ����h�d(�lx���Tdp����D��RS���*V�x;v��
l�^x2��<�%��"�$(�N]N
���9[)��f�����$�g��e]��}�+-t6�z��R_���9�+���zZ�(��E2�����6��!�,�j�'%�9gI�pfx�9���;�e(cz�1Hp0��@�4(�3#8�cbH,wvg�x��h&����32��B �
�����x�*LY0ME@���>���S�����[������q6���G���k���&�A�h���T�]z�.����<��{��a$%��sm�������sg�F��s�{�u��s�S�b���9�wc$�=5$������o5W��j����0���S�A�T�3^�}��~6���b��
�W"�����E$CE�x�?{�"N5�h����P1v��@R<��vp?�����+�����.��6�!J�G�������?��XY� ������'3M5��w�7���f�9��|i���U��!�g�}�����5��o�M;�<�"`v�$"���W��+%�&�qk��Yh{;��,*����W{wD�p���@���0�#�I�Z��w5�	��Y92g�`�����iH����n#���$���D7_� J�hfB���!���C���}����c���A�����n������C�������d�8���1��	DD�Q3�4t.$�sL**8�3[q��K��5{�h�����j��h��;�h���8��m+ ]�QFS0f�-$�mMrq4�v\N���c~3e�7.?d�<���h�3�E���������x��Q���\fu�?�#�\�(	�0������_g~{>kq�����9���������+���R�S�B�9�0���p�	���#�7F�-yQ�l�
1��l5#q"b��]�b�]&�	�8fV�����L���������
�C�.%���3����HQ�2�e����f��g�r)�$KY�4���C���Q65�R�@���P��5��x���D��((��;���tS�����������l�J�B�d~>�����G���\�L��I��.{dVz�f�K�C8�������h ����k���.���I"������=L�_@���,��.MS6J��l����{7��}�+�,+��J�G�e��Sx������A�e6[\�"|0!��&g668i��j������������^��4jS2�� '���c��Eq����s�{Z�s��
��]KC�x(8��y|��i 
���f�Bw��x��JH���z� ���S�g��XB�������2������0)"�.�Q���k�p�a��i�����C' �a&�*�3��12-�[��B��s������^�3
��x-��KH��l��\�c`T%D��ln�b�����I^p��&����z���A=>���Ne�},��45Q�)�ta��c�xE8
"2�]1�^������?k��7b&%��y~�	U�j��z�Z�r���s�U)F���Z�+������-���76C���vf�x���Q��3�T�q�I[w������2.� 8�.%u�5qhod����H1'
O
��,�85r��Ci�4��Q.�b��:� ���3r.�;�����Y�,�f����fkj�R7�|Bq���J����;h���.�JR,o�w
A�A���d� ��K�B���LS+�sP�c�S4HZ�,�VuW!��9N�d��PA�Frg���l���3��Q�W��w�����t���|`������9��axE-�)�
:2�G5-Cv�T*+��������H-��B$!�T
�:�`��Ec|?�������%����(��L>�1�1"����m�u�H�Pq�_���$|pLi�K��3u@2��I�1��u���%���c
� ;�����P��wF��/Q{�f��
� nD�a���H��Z3��[U!��4��e�s�3)�?J�8��������v��?��u�2��F-���	Y>��8��"*P*3J?�j�U�O9�,x�X}������jl���$s����E���b����]-�f.�%0T,.�ql�������uT^��%1hi�_�q����yf��+�$AIS+�(3���(m�R�L_�e8��Q���ez�8c����4v{dg���Fq��O��5}|U@��/a�TP�ZF{�A	�5����c����!���`�V�������I��BYD����F���m�Y�C��]�6�g<�T8��0;���hR%��r�]Fq��48��^�]����.vm��^]��2sPw9�����#���Wb��+h��@\����G�Z������v[\��!���a@������25��#;�j�Dsn�q�TX�@������������'��n��q��/h��~�}��W����W��G�O�>��{@`�#�(�4�����%i	-�����_�0�?���_�����_��w~��~�g��7�������5_����??}��u���u��������O�Q�������H����O���==����7�~��W/_x�����7�_�v��s{����^�;���~������ �N����7o?�}������_������|����~�a�E����������O|_��.3
Ee(FQ�:1V�J�~w����t�q�\��(^z\������m����_��������
endstream
endobj
12 0 obj
241738
endobj
10 0 obj
[ ]
endobj
33 0 obj
<< /Length 264 /Filter /FlateDecode >>
stream
x�=R��1��
��_R=��q`���=;11KA�nQ9?m%����egI����m������ s�q�b���$-e&�g���q
j��3�!I�rR�"�������_7��tlPzK���T��r�;��]�������3����������N��#,���HE!����,����~�]��XO�<�i�VzK���Lm;���Yc�T	��!�Z��:�������4Uy"�R���=�5\�K��I�������m�phg�
endstream
endobj
34 0 obj
<< /Length 307 /Filter /FlateDecode >>
stream
x�=�Kn1C�>�.������(����'%���Ej��LYS�4����p���;l�ff�Z�������b��|��F]Y'���f:��Q96M���,��.x�&�[�?����5.	7tW�e)4c���{��2�jL]lR�{<^DU��G�"c���A	�J�hZ��wEA����{	���j�����;)f��tR.n�!�������kB���+%�H��3r'�h���������K��h!���n�.`�S:EbdNr�i�UN�P�����lEC)s���_��k�lxJ���&KV���N��<���Z�t
endstream
endobj
35 0 obj
<< /Length 244 /Filter /FlateDecode >>
stream
x�E�Mr!����/���W=��RYL��
��$+Z���G�C���2|/�2|�2;�:��pO�n\�e�3a[�;*�;^Cw�R?����9�.R5ted�z������Yt+�u@���R�l[��J�'��4���w�k|uO���T�!Z����lxA��$�
�'�s!Q���:.`�%������f|zRI0�|��h�6���g��KE�W4��;I5�������6q����w��+}�>K�]
endstream
endobj
36 0 obj
<< /Length 232 /Filter /FlateDecode >>
stream
x�5QIn�0�������'������R�@%��%bc#/1�9����5�&~grW�,O�G���I���^v���e?3��V�����E6=<2�%:0�u�f���!��#R�F�����*�S����m��s��m��Nv{�I������e���X=Q�K1}��l�'��(��l>j�D�(g����(����g�U!h]��mc�FJ���
MM��D	g�4�������N!T
endstream
endobj
37 0 obj
<< /Length 73 /Filter /FlateDecode >>
stream
x�366W0P04�FF
�@V�!H���D!�$b��Y@�8�&�+�i��� ��-��*,�lW���
endstream
endobj
38 0 obj
<< /Length 231 /Filter /FlateDecode >>
stream
x�5O9�!�y�>0U�@����6�����N��!���x�##�f��Zd f�SL�������"��a��p���n���v��X�6��Y^��L�Wg.�ci��9�n�]��u��SXG0��t��� sT����2��8�'�����,v9~�6�!��*z�6���y�rA�]��E��% 	�Qb����_�vt�(sB�A.!��*��P����RQp�>�����_\-
endstream
endobj
39 0 obj
<< /Length 249 /Filter /FlateDecode >>
stream
x�=P;�D!�9�/�$�#pF�-f����)PL~�3$��G1���%������B�n���� �CR �z�t��6�:�3?a7c��E1��t�=&9��
�se�VH'��"��3�)�*{�x,��6['�=� �RR������?m��
:f�,��dM8��IR��2��v"}�<��:�dM��#���O���p�_�dN��t������9����6M�����i*/R�Z�~u����g�d����Z"
endstream
endobj
40 0 obj
<< /Length 395 /Filter /FlateDecode >>
stream
x�=RKn�@��\�����yRU���okCR�*��1�0}����K]q���^�[<�|.[Z�y����%>����!�]t.�8G�2�*D������B���N���}9��/����
��=2A�$�)B�nQ�Aa����P�Y��Q���2jo��c�	�BmH��@D��T���g$��gb`����TD�{��������D�>OM�(�L-V�nS_����|t*�4����U��X�y�9�H���l!�:n����3�2�`K9`���G��Yu����t���pL��~��O�t�Z�u�r�@�MA���F���2>��)z�,���F3�a�����r�4�k"�X"��bD��ls=��L��9���l�����33*!����j�@v���p��?3��m
endstream
endobj
41 0 obj
<< /Length 249 /Filter /FlateDecode >>
stream
x�MQI�0���@!^���C�C�����9	�����X1�,=��!s7�~���Yz������"SQ�R�.bB]����=�kY���9,��s���3�c}I2����!NuZ���kb��Z�<��n�Ffe&�
�dB��� ��,�662Y��
�
Z`��Q��+��	t�V�������v7C-���}��hV�`��K�Xx_�>���v��Bz�M;"�
�2;-+�{��n��?�R��������\�
endstream
endobj
42 0 obj
<< /Length 164 /Filter /FlateDecode >>
stream
x�E��q1C��%0�
����������AzBbO��\Wqat���-3
G���2c��X '�������v�����b���\/:"����@#|:�����3�t^�!��**�na.��@�R����Q����*+kj�W�]J�>.�2N��Z����=��?v:�
endstream
endobj
43 0 obj
<< /Length 72 /Filter /FlateDecode >>
stream
x�32�P0P�4�&
�f
)�\@����B.H�����%���g�� m� D���D����J%��
endstream
endobj
44 0 obj
<< /Length 83 /Filter /FlateDecode >>
stream
x�=�9�0��S�#��"�q�x�V0��z�!8�����`��t�S����	�xJM��z�����h����K��?�����
endstream
endobj
45 0 obj
<< /Length 47 /Filter /FlateDecode >>
stream
x�32�P0P�4�&
�f
)�\�V.L,���p
"����g
'
endstream
endobj
46 0 obj
<< /Length 258 /Filter /FlateDecode >>
stream
x�E�Kr D���#���<�Je1��6
�d6v����J#�,�y0}���d��w9V;E(��U���;S��k�j�ce���;��]9�dq��uTu*pL���Q��vY�}Ge
��sl��m�'F����� O'SG�� ��'�}��+p�l��K0�B���@����S�����v��`oyH���!�v�\������q�;�����w��v�_b�s��)��k.Z�:��3�������`���L��?����)f�
endstream
endobj
47 0 obj
<< /Length 163 /Filter /FlateDecode >>
stream
x�E�;!C{N�#�#>�f2)6�oc�lR��X �����������%���gc��6n5�u�V��h�R}��i�t�h6s+�fz���:����r����Cp�_��b�9�������S��6;����������~+�UaiYK�	���f@	�S9��=?
:�
endstream
endobj
48 0 obj
<< /Length 218 /Filter /FlateDecode >>
stream
x�=P��1�]�X�z��g�K���H��"�ER*5��)/u�%YS�:|��y��nd6%*E/��%��
�}�������C4�h9~3*��K6�p*����3�
mtV��[ ��`�� r����"JM��r��^�>��C���5�X��s
�S�'�no��^�����#]X�.i5AM��Z-���^��#�@���q�R���kp��/�'S�
endstream
endobj
49 0 obj
<< /Length 83 /Filter /FlateDecode >>
stream
x�E��
�0D{�`~&�>Q����
%n�'�=\	�)n3�C�,�]q���0\GP����a������R���������Bf
endstream
endobj
50 0 obj
<< /Length 239 /Filter /FlateDecode >>
stream
x�MP�m1��
50����<��C�	��hK����[��e�#9o���C�N�i�n������v�PT�%�J�\�n�4I/��8��k����{�Y�x����)��=2�f��90�=��N�����;�$����B�
��%��+��R�N-����{|�=��������F�-��j�80S��q����CgGW4���zB5��9����p`������R�e�]�:�4J����(�����^7
endstream
endobj
51 0 obj
<< /Length 160 /Filter /FlateDecode >>
stream
x�E�91s��'H\����������G��4�M�zh>��F���k�,J�D��P�c�;(HLHc�H��#�X�]��T*�R��i����Z��D�p����T�O�\��M���1�T�;��I�^E�Z1��D0��	oE&�������`���
�8��
L�7�
endstream
endobj
52 0 obj
<< /Length 334 /Filter /FlateDecode >>
stream
x�-RKr� �s
]�3��<�t�x�����EF`�1���J|Y �������@�������H��:������-�{D,�1�<�����������/�w+���e!���a�a�X�u!�{xS���$����>�s--|F��_�������i��m��z�L;���lOs^&_Zg�:�����R���3�s�(�VF�v6Hj\lo��XJ��n\F�#���"<����&
���r*a���trUq���5���3If��H���y]8��Sf�y'�r�����gK��9����Yht������NON�W3�!9	�bZW�i�b	�_SQS�z�����;~�,s|s
endstream
endobj
53 0 obj
<< /Length 54 /Filter /FlateDecode >>
stream
x�366W0B]K#c ���R!���������	�pY�U�p@i����4��
endstream
endobj
54 0 obj
<< /Length 18 /Filter /FlateDecode >>
stream
x�36�P0��C�4�R
endstream
endobj
55 0 obj
<< /Length 133 /Filter /FlateDecode >>
stream
x�E�K!D�������q2��s����nc=�T����=.k�!������EY>TzRV������!��,��I*�!P���-en���6
���S�����0���l_�["u�?��*/������������1	
endstream
endobj
56 0 obj
<< /Length 340 /Filter /FlateDecode >>
stream
x�5R9n1��
} �n��� H���
��qtR�;ZTv���T��t����7�we��	���R�H��V!���2��5g�R�����q��?�����������X#�D�2�������f[~�i��x��+�-�XR�8����y-������
V�~A��G�}�TX ��Ip��P��v��H9{,vQ�3(1��E�A�%��9��t���������7�:*�[ZYc�>���,2�zX�t����4�����4e�����9���QVx�C�
�1�!���	J�<��%���
�_���6���?m���^��Jk���L�������������
endstream
endobj
57 0 obj
<< /Length 251 /Filter /FlateDecode >>
stream
x�-QIrA��+��f��c�+�����
�@tZ���� ,W����h��31���~+�mX�@T IcP5�v�z��q�	����f���)����1g��e��]�=�A��\�%L�a#g?�2.�s=7 �FX�a�nV3�4�H!�����A��F�6r��/�t�U��1�s-m_�M8k��X����]q.'/���6Qi��@H��n�s���xK����{����T`���n@6�������������_`[�
endstream
endobj
58 0 obj
<< /Length 174 /Filter /FlateDecode >>
stream
x�M�IC!C�����3��<���h���Cu��� p<<�q$.td���+���� c��8���>�1A��-X�v���s�21�F��<���\d��� "]��V�Y����;����f_=������W�����K��^���*%c����"R6;��T�r�����+p���C���#<�
endstream
endobj
59 0 obj
<< /Length 89 /Filter /FlateDecode >>
stream
x�5��
�0D{O����!
���Ipc���^R�@�:���'A��^ ��VE�QI��M��ES����M'3��u���z�Z(m��p}��
endstream
endobj
60 0 obj
<< /Length 141 /Filter /FlateDecode >>
stream
x�=���0C��
�@��)�|O�j����#K�zc��������`����%Tk��@%7��`���G�zb8\��������f}��B�%h�{�Si��q�5�)�������g�4��4��s�
�{�S��������w.�
endstream
endobj
61 0 obj
<< /Length 215 /Filter /FlateDecode >>
stream
x�5Q9!���@$�/xO�(������V�\���!��R��!�S>z�.�����j4���-s����/����f���i���<C���QC���S(��>��n�c����!�� b(,A��Em�'�5�^������S����V8�����=O&�t2��5�	E"<�����Z4�2���j�;�0Nq�d�J����o���W���GT�
endstream
endobj
31 0 obj
<< /Type /Font /BaseFont /BMQQDV+DejaVuSans /FirstChar 0 /LastChar 255
/FontDescriptor 30 0 R /Subtype /Type3 /Name /BMQQDV+DejaVuSans
/FontBBox [ -1021 -463 1794 1233 ] /FontMatrix [ 0.001 0 0 0.001 0 0 ]
/CharProcs 32 0 R
/Encoding << /Type /Encoding
/Differences [ 32 /space 47 /slash /zero /one /two /three 53 /five 56 /eight 58 /colon
66 /B 97 /a /b /c /d /e 104 /h /i 107 /k /l /m /n /o /p 114 /r /s /t /u 119
/w 121 /y ]
>>
/Widths 29 0 R >>
endobj
30 0 obj
<< /Type /FontDescriptor /FontName /BMQQDV+DejaVuSans /Flags 32
/FontBBox [ -1021 -463 1794 1233 ] /Ascent 929 /Descent -236 /CapHeight 0
/XHeight 0 /ItalicAngle 0 /StemV 0 /MaxWidth 1342 >>
endobj
29 0 obj
[ 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600
600 600 600 600 600 600 600 600 600 600 600 600 600 600 318 401 460 838 636
950 780 275 390 390 500 838 318 361 318 337 636 636 636 636 636 636 636 636
636 636 337 337 838 838 838 531 1000 684 686 698 770 632 575 775 752 295
295 656 557 863 748 787 603 787 695 635 611 732 684 989 685 611 685 390 337
390 838 500 500 613 635 550 635 615 352 635 634 278 278 579 278 974 634 612
635 635 411 521 392 634 592 818 592 592 525 636 337 636 838 600 636 600 318
352 518 1000 500 500 500 1342 635 400 1070 600 685 600 600 318 318 518 518
590 500 1000 500 1000 521 400 1023 600 525 611 318 401 636 636 636 636 337
500 500 1000 471 612 838 361 1000 500 500 838 401 401 500 636 636 318 500
401 471 612 969 969 969 531 684 684 684 684 684 684 974 698 632 632 632 632
295 295 295 295 775 748 787 787 787 787 787 838 787 732 732 732 732 611 605
630 613 613 613 613 613 613 982 550 615 615 615 615 278 278 278 278 612 634
612 612 612 612 612 838 612 634 634 634 634 592 635 592 ]
endobj
32 0 obj
<< /B 33 0 R /a 34 0 R /b 35 0 R /c 36 0 R /colon 37 0 R /d 38 0 R
/e 39 0 R /eight 40 0 R /five 41 0 R /h 42 0 R /i 43 0 R /k 44 0 R
/l 45 0 R /m 46 0 R /n 47 0 R /o 48 0 R /one 49 0 R /p 50 0 R /r 51 0 R
/s 52 0 R /slash 53 0 R /space 54 0 R /t 55 0 R /three 56 0 R /two 57 0 R
/u 58 0 R /w 59 0 R /y 60 0 R /zero 61 0 R >>
endobj
3 0 obj
<< /F1 31 0 R >>
endobj
4 0 obj
<< /A1 << /Type /ExtGState /CA 0 /ca 1 >>
/A2 << /Type /ExtGState /CA 1 /ca 1 >>
/A3 << /Type /ExtGState /CA 0.5019607843 /ca 0.5019607843 >> >>
endobj
5 0 obj
<< >>
endobj
6 0 obj
<< >>
endobj
7 0 obj
<< /M0 13 0 R /M1 14 0 R /M2 15 0 R /M3 16 0 R /M4 17 0 R /M5 18 0 R
/M6 19 0 R /M7 20 0 R /M8 21 0 R /M9 22 0 R /M10 23 0 R /M11 24 0 R
/M12 25 0 R /M13 26 0 R /M14 27 0 R /M15 28 0 R >>
endobj
13 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
14 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
15 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
16 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
17 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
18 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
19 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
20 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
21 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
22 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
23 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
24 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
25 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
26 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
27 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
28 0 obj
<< /Type /XObject /Subtype /Form /BBox [ -6.5 -6.5 6.5 6.5 ] /Length 133
/Filter /FlateDecode >>
stream
x�m�9!E{��|d�C;e�AE���C�����E���=�c >������=f�s	Y�������)i�;�f
�]���j}
���hi:oqWe�nD���90"X0�pl�al���K���_�/}��I7��H�
endstream
endobj
2 0 obj
<< /Type /Pages /Kids [ 11 0 R ] /Count 1 >>
endobj
62 0 obj
<< /Creator (Matplotlib v3.8.3, https://matplotlib.org)
/Producer (Matplotlib pdf backend v3.8.3)
/CreationDate (D:20240329155726+02'00') >>
endobj
xref
0 63
0000000000 65535 f 
0000000016 00000 n 
0000256505 00000 n 
0000251844 00000 n 
0000251876 00000 n 
0000252036 00000 n 
0000252057 00000 n 
0000252078 00000 n 
0000000065 00000 n 
0000000332 00000 n 
0000242168 00000 n 
0000000208 00000 n 
0000242145 00000 n 
0000252281 00000 n 
0000252545 00000 n 
0000252809 00000 n 
0000253073 00000 n 
0000253337 00000 n 
0000253601 00000 n 
0000253865 00000 n 
0000254129 00000 n 
0000254393 00000 n 
0000254657 00000 n 
0000254921 00000 n 
0000255185 00000 n 
0000255449 00000 n 
0000255713 00000 n 
0000255977 00000 n 
0000256241 00000 n 
0000250449 00000 n 
0000250242 00000 n 
0000249777 00000 n 
0000251502 00000 n 
0000242188 00000 n 
0000242525 00000 n 
0000242905 00000 n 
0000243222 00000 n 
0000243527 00000 n 
0000243672 00000 n 
0000243976 00000 n 
0000244298 00000 n 
0000244766 00000 n 
0000245088 00000 n 
0000245325 00000 n 
0000245469 00000 n 
0000245624 00000 n 
0000245743 00000 n 
0000246074 00000 n 
0000246310 00000 n 
0000246601 00000 n 
0000246756 00000 n 
0000247068 00000 n 
0000247301 00000 n 
0000247708 00000 n 
0000247834 00000 n 
0000247924 00000 n 
0000248130 00000 n 
0000248543 00000 n 
0000248867 00000 n 
0000249114 00000 n 
0000249275 00000 n 
0000249489 00000 n 
0000256565 00000 n 
trailer
<< /Size 63 /Root 1 0 R /Info 62 0 R >>
startxref
256722
%%EOF
results.txttext/plain; charset=UTF-8; name=results.txtDownload
#89Thomas Munro
thomas.munro@gmail.com
In reply to: Tomas Vondra (#88)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 30, 2024 at 4:53 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Two observations:

* The combine limit seems to have negligible impact. There's no visible
difference between combine_limit=8kB and 128kB.

* Parallel queries seem to work about the same as master (especially for
optimal cases, but even for not optimal ones).

The optimal plans with kernel readahead (two charts in the first row)
look fairly good. There are a couple regressed cases, but a bunch of
faster ones too.

Thanks for doing this!

The optimal plans without kernel read ahead (two charts in the second
row) perform pretty poorly - there are massive regressions. But I think
the obvious reason is that the streaming read API skips prefetches for
sequential access patterns, relying on kernel to do the readahead. But
if the kernel readahead is disabled for the device, that obviously can't
happen ...

Right, it does seem that this whole concept is sensitive on the
'borderline' between sequential and random, and this patch changes
that a bit and we lose some. It's becoming much clearer to me that
master is already exposing weird kinks, and the streaming version is
mostly better, certainly on low IOPS systems. I suspect that there
must be queries in the wild that would run much faster with eic=0 than
eic=1 today due to that, and while the streaming version also loses in
some cases, it seems that it mostly loses because of not triggering
RA, which can at least be improved by increasing the RA window. On
the flip side, master is more prone to running out of IOPS and there
is no way to tune your way out of that.

I think the question is how much we can (want to) rely on the readahead
to be done by the kernel. ...

We already rely on it everywhere, for basic things like sequential scan.

... Maybe there should be some flag to force
issuing fadvise even for sequential patterns, perhaps at the tablespace
level? ...

Yeah, I've wondered about trying harder to "second guess" the Linux
RA. At the moment, read_stream.c detects *exactly* sequential reads
(see seq_blocknum) to suppress advice, but if we knew/guessed the RA
window size, we could (1) detect it with the same window that Linux
will use to detect it, and (2) [new realisation from yesterday's
testing] we could even "tickle" it to wake it up in certain cases
where it otherwise wouldn't, by temporarily using a smaller
io_combine_limit if certain patterns come along. I think that sounds
like madness (I suspect that any place where the latter would help is
a place where you could turn RA up a bit higher for the same effect
without weird kludges), or another way to put it would be to call it
"overfitting" to the pre-existing quirks; but maybe it's a future
research idea...

I don't recall seeing a system with disabled readahead, but I'm
sure there are cases where it may not really work - it clearly can't
work with direct I/O, ...

Right, for direct I/O everything is slow right now including seq scan.
We need to start asynchronous reads in the background (imagine
literally just a bunch of background "I/O workers" running preadv() on
your behalf to get your future buffers ready for you, or equivalently
Linux io_uring). That's the real goal of this project: restructuring
so we have the information we need to do that, ie teach every part of
PostgreSQL to predict the future in a standard and centralised way.
Should work out better than RA heuristics, because we're not just
driving in a straight line, we can turn corners too.

... but I've also not been very successful with
prefetching on ZFS.

posix_favise() did not do anything in OpenZFS before 2.2, maybe you
have an older version?

I certainly admit the data sets are synthetic and perhaps adversarial.
My intent was to cover a wide range of data sets, to trigger even less
common cases. It's certainly up to debate how serious the regressions on
those data sets are in practice, I'm not suggesting "this strange data
set makes it slower than master, so we can't commit this".

Right, yeah. Thanks! Your initial results seemed discouraging, but
looking closer I'm starting to feel a lot more positive about
streaming BHS.

#90Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#89)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 30, 2024 at 10:39 AM Thomas Munro <thomas.munro@gmail.com> wrote:

On Sat, Mar 30, 2024 at 4:53 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

... Maybe there should be some flag to force
issuing fadvise even for sequential patterns, perhaps at the tablespace
level? ...

Yeah, I've wondered about trying harder to "second guess" the Linux
RA. At the moment, read_stream.c detects *exactly* sequential reads
(see seq_blocknum) to suppress advice, but if we knew/guessed the RA
window size, we could (1) detect it with the same window that Linux
will use to detect it, and (2) [new realisation from yesterday's
testing] we could even "tickle" it to wake it up in certain cases
where it otherwise wouldn't, by temporarily using a smaller
io_combine_limit if certain patterns come along. I think that sounds
like madness (I suspect that any place where the latter would help is
a place where you could turn RA up a bit higher for the same effect
without weird kludges), or another way to put it would be to call it
"overfitting" to the pre-existing quirks; but maybe it's a future
research idea...

I guess I missed a step when responding that suggestion: I don't think
we could have an "issue advice always" flag, because it doesn't seem
to work out as well as letting the kernel do it, and a global flag
like that would affect everything else including sequential scans
(once the streaming seq scan patch goes in). But suppose we could do
that, maybe even just for BHS. In my little test yesterday had to
issue a lot of them, patched eic=4, to beat the kernel's RA with
unpatched eic=0:

eic unpatched patched
0 4172 9572
1 30846 10376
2 18435 5562
4 18980 3503

So if we forced fadvise to be issued with a GUC, it still wouldn't be
good enough in this case. So we might need to try to understand what
exactly is waking the RA up for unpatched but not patched, and try to
tickle it by doing a little less I/O combining (for example just
setting io_combine_limit=1 gives the same number for eic=0, a major
clue), but that seems to be going down a weird path, and tuning such a
copying algorithm seems too hard.

#91Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Thomas Munro (#90)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/29/24 23:03, Thomas Munro wrote:

On Sat, Mar 30, 2024 at 10:39 AM Thomas Munro <thomas.munro@gmail.com> wrote:

On Sat, Mar 30, 2024 at 4:53 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

... Maybe there should be some flag to force
issuing fadvise even for sequential patterns, perhaps at the tablespace
level? ...

Yeah, I've wondered about trying harder to "second guess" the Linux
RA. At the moment, read_stream.c detects *exactly* sequential reads
(see seq_blocknum) to suppress advice, but if we knew/guessed the RA
window size, we could (1) detect it with the same window that Linux
will use to detect it, and (2) [new realisation from yesterday's
testing] we could even "tickle" it to wake it up in certain cases
where it otherwise wouldn't, by temporarily using a smaller
io_combine_limit if certain patterns come along. I think that sounds
like madness (I suspect that any place where the latter would help is
a place where you could turn RA up a bit higher for the same effect
without weird kludges), or another way to put it would be to call it
"overfitting" to the pre-existing quirks; but maybe it's a future
research idea...

I don't know if I'd call this overfitting - yes, we certainly don't want
to tailor this code to only work with the linux RA, but OTOH it's the RA
is what most systems do. And if we plan to rely on that, we probably
have to "respect" how it works ...

Moving to a "clean" approach that however triggers regressions does not
seem like a great thing for users. I'm not saying the goal has to be "no
regressions", that would be rather impossible. At this point I still try
to understand what's causing this.

BTW are you suggesting that increasing the RA distance could maybe fix
the regressions? I can give it a try, but I was assuming that 128kB
readahead would be enough for combine_limit=8kB.

I guess I missed a step when responding that suggestion: I don't think
we could have an "issue advice always" flag, because it doesn't seem
to work out as well as letting the kernel do it, and a global flag
like that would affect everything else including sequential scans
(once the streaming seq scan patch goes in). But suppose we could do
that, maybe even just for BHS. In my little test yesterday had to
issue a lot of them, patched eic=4, to beat the kernel's RA with
unpatched eic=0:

eic unpatched patched
0 4172 9572
1 30846 10376
2 18435 5562
4 18980 3503

So if we forced fadvise to be issued with a GUC, it still wouldn't be
good enough in this case. So we might need to try to understand what
exactly is waking the RA up for unpatched but not patched, and try to
tickle it by doing a little less I/O combining (for example just
setting io_combine_limit=1 gives the same number for eic=0, a major
clue), but that seems to be going down a weird path, and tuning such a
copying algorithm seems too hard.

Hmmm. I admit I didn't think about the "always prefetch" flag too much,
but I did imagine it'd only affect some places (e.g. BHS, but not for
sequential scans). If it could be done by lowering the combine limit,
that could work too - in fact, I was wondering if we should have combine
limit as a tablespace parameter too.

But I think adding such knobs should be only the last resort - I myself
don't know how to set these parameters, how could we expect users to
pick good values? Better to have something that "just works".

I admit I never 100% understood when exactly the kernel RA kicks in, but
I always thought it's enough for the patterns to be only "close enough"
to sequential. Isn't the problem that this only skips fadvise for 100%
sequential patterns, but keeps prefetching for cases the RA would deal
on it's own? So maybe we should either relax the conditions when to skip
fadvise, or combine even pages that are not perfectly sequential (I'm
not sure if that's possible only for fadvise), though.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#92Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Thomas Munro (#89)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 3/29/24 22:39, Thomas Munro wrote:

...

I don't recall seeing a system with disabled readahead, but I'm
sure there are cases where it may not really work - it clearly can't
work with direct I/O, ...

Right, for direct I/O everything is slow right now including seq scan.
We need to start asynchronous reads in the background (imagine
literally just a bunch of background "I/O workers" running preadv() on
your behalf to get your future buffers ready for you, or equivalently
Linux io_uring). That's the real goal of this project: restructuring
so we have the information we need to do that, ie teach every part of
PostgreSQL to predict the future in a standard and centralised way.
Should work out better than RA heuristics, because we're not just
driving in a straight line, we can turn corners too.

... but I've also not been very successful with
prefetching on ZFS.

posix_favise() did not do anything in OpenZFS before 2.2, maybe you
have an older version?

Sorry, I meant the prefetch (readahead) built into ZFS. I may be wrong
but I don't think the regular RA (in linux kernel) works for ZFS, right?

I was wondering if we could use this (posix_fadvise) to improve that,
essentially by issuing fadvise even for sequential patterns. But now
that I think about that, if posix_fadvise works since 2.2, maybe RA
works too now?)

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#93Thomas Munro
thomas.munro@gmail.com
In reply to: Tomas Vondra (#92)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 30, 2024 at 12:40 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Sorry, I meant the prefetch (readahead) built into ZFS. I may be wrong
but I don't think the regular RA (in linux kernel) works for ZFS, right?

Right, it separate page cache ("ARC") and prefetch settings:

https://openzfs.github.io/openzfs-docs/Performance%20and%20Tuning/Module%20Parameters.html

That's probably why Linux posix_fadvise didn't affect it, well that
and the fact, at a wild guess, that Solaris didn't have that system
call...

I was wondering if we could use this (posix_fadvise) to improve that,
essentially by issuing fadvise even for sequential patterns. But now
that I think about that, if posix_fadvise works since 2.2, maybe RA
works too now?)

It should work fine. I am planning to look into this a bit some day
soon -- I think there may be some interesting interactions between
systems with big pages/records like ZFS/BTRFS/... and io_combine_limit
that might offer interesting optimisation tweak opportunities, but
first things first...

#94Thomas Munro
thomas.munro@gmail.com
In reply to: Tomas Vondra (#91)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 30, 2024 at 12:34 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Hmmm. I admit I didn't think about the "always prefetch" flag too much,
but I did imagine it'd only affect some places (e.g. BHS, but not for
sequential scans). If it could be done by lowering the combine limit,
that could work too - in fact, I was wondering if we should have combine
limit as a tablespace parameter too.

Good idea! Will add. Planning to commit the basic patch very soon,
I'm just thinking about what to do with Heikki's recent optimisation
feedback (ie can it be done as follow-up, he thinks so, I'm thinking
about that today as time is running short).

But I think adding such knobs should be only the last resort - I myself
don't know how to set these parameters, how could we expect users to
pick good values? Better to have something that "just works".

Agreed.

I admit I never 100% understood when exactly the kernel RA kicks in, but
I always thought it's enough for the patterns to be only "close enough"
to sequential. Isn't the problem that this only skips fadvise for 100%
sequential patterns, but keeps prefetching for cases the RA would deal
on it's own? So maybe we should either relax the conditions when to skip
fadvise, or combine even pages that are not perfectly sequential (I'm
not sure if that's possible only for fadvise), though.

Yes that might be worth considering, if we know/guess what the OS RA
window size is for a tablespace. I will post a patch for that for
consideration/testing as a potential follow-up as it's super easy,
just for experimentation. I just fear that it's getting into the
realms of "hard to explain/understand" but on the other hand I guess
we already have the mechanism and have to explain it.

#95Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#85)
17 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Mar 29, 2024 at 12:05:15PM +0100, Tomas Vondra wrote:

On 3/29/24 02:12, Thomas Munro wrote:

On Fri, Mar 29, 2024 at 10:43 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

Thanks for the repro. I can't seem to reproduce it (still trying) but
I assume this is with Melanie's v11 patch set which had
v11-0016-v10-Read-Stream-API.patch.

Would you mind removing that commit and instead applying the v13
stream_read.c patches[1]? v10 stream_read.c was a little confused
about random I/O combining, which I fixed with a small adjustment to
the conditions for the "if" statement right at the end of
read_stream_look_ahead(). Sorry about that. The fixed version, with
eic=4, with your test query using WHERE a < a, ends its scan with:

I'll give that a try. Unfortunately unfortunately the v11 still has the
problem I reported about a week ago:

ERROR: prefetch and main iterators are out of sync

So I can't run the full benchmarks :-( but master vs. streaming read API
should work, I think.

Odd, I didn't notice you reporting this ERROR popping up. Now that I
take a look, v11 (at least, maybe also v10) had this very sill mistake:

  if (scan->bm_parallel == NULL &&
      scan->rs_pf_bhs_iterator &&
      hscan->pfblockno > hscan->rs_base.blockno)
       elog(ERROR, "prefetch and main iterators are out of sync");

It errors out if the prefetch block is ahead of the current block --
which is the opposite of what we want. I've fixed this in attached v12.

This version also has v13 of the streaming read API. I noticed one
mistake in my bitmapheap scan streaming read user -- it freed the
streaming read object at the wrong time. I don't know if this was
causing any other issues, but it at least is fixed in this version.

- Melanie

Attachments:

v12-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From d406f48e2de3cf1627b2947ceae741113e9bf454 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v12 01/17] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 805d222cebc..b0f61c65f36 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aabe..93fdcd226bf 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v12-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 07b5447bc106b9aebeeac1e1143b57cff218bcf0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v12 02/17] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 93fdcd226bf..c64530674bd 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -742,16 +752,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v12-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From 415995a3fcd92e5055b30d0cf9213894f78deeb9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v12 03/17] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b661d9811eb..27e9d05f14b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -948,6 +948,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1036,6 +1038,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1055,6 +1063,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 41a4bb0981d..4c5fe8f090d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -28,6 +28,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2209,6 +2210,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2321,6 +2340,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c64530674bd..83d9db8f39b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,11 +185,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	node->ss.ps.state->es_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	extra_flags);
 		}
 
 		node->initialized = true;
@@ -207,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -228,37 +232,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -301,52 +282,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +531,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +601,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +610,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +654,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -740,8 +697,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +707,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 32a3fbce961..49f212eb9a6 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -72,6 +72,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index cf76fc29d4b..e8d04b4dec6 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -63,6 +63,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -959,9 +966,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e7ff8e4992f..4880f346bf1 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,10 +1794,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1817,9 +1814,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v12-0004-BitmapPrefetch-use-prefetch-block-recheck-for-sk.patchtext/x-diff; charset=us-asciiDownload
From c7f5e03f51ea387a20a22b2ecb969d58eca3b5fc Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v12 04/17] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 83d9db8f39b..5df3b5ca46d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -474,14 +474,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -532,7 +527,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v12-0005-Update-BitmapAdjustPrefetchIterator-parameter-ty.patchtext/x-diff; charset=us-asciiDownload
From 48d53f4a2204e35991e7ee8dad115252aace37d2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v12 05/17] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5df3b5ca46d..404de0595ec 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -230,7 +230,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -341,7 +341,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -360,7 +360,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v12-0006-table_scan_bitmap_next_block-returns-lossy-or-ex.patchtext/x-diff; charset=us-asciiDownload
From 7a3992b21b174a3a644a3eb82d982c77a64be7dd Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v12 06/17] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 4c5fe8f090d..973734e9ffa 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2199,7 +2199,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2327,6 +2328,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 404de0595ec..c95e3412da8 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
+		bool		valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -232,12 +232,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e8d04b4dec6..19e99c81092 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -811,6 +811,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -826,7 +829,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -2013,14 +2017,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2031,7 +2037,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.40.1

v12-0007-Reduce-scope-of-BitmapHeapScan-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From bf96c0a51ad2d88d2077418740d1e57696534625 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v12 07/17] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c95e3412da8..49938c9ed41 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +202,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -221,9 +219,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v12-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From 6bb0d8733eee92db27152ea40fab632759d34ba5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v12 08/17] Remove table_scan_bitmap_next_tuple parameter
 tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 973734e9ffa..2cb5fb18675 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2335,7 +2335,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 49938c9ed41..282dcb97919 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -286,7 +286,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 19e99c81092..ff3e8bcdd6f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -802,10 +802,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -836,15 +833,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2050,7 +2042,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2062,7 +2053,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v12-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 521548fd0b97f1d7356e225984cfb12b2dc05bde Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v12 09/17] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 195 insertions(+), 149 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2cb5fb18675..916d7a6e2e8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2199,18 +2199,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2229,16 +2262,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2330,7 +2354,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 282dcb97919..90cb10bc819 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +109,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +161,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -202,55 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool		valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -272,45 +232,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,13 +311,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -356,14 +335,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -388,7 +370,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -466,6 +451,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -523,6 +509,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -584,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -597,13 +581,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -634,28 +618,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -688,8 +668,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -697,9 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ff3e8bcdd6f..ad1805b55ed 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -795,19 +796,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -826,8 +822,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -964,9 +960,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1013,6 +1013,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1023,6 +1038,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -2006,19 +2036,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2028,8 +2056,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 4880f346bf1..8e344155679 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v12-0010-Unify-parallel-and-serial-BitmapHeapScan-iterato.patchtext/x-diff; charset=us-asciiDownload
From 551cdba973c43816ad40a17b23451d280c8db19e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 25 Mar 2024 11:05:51 -0400
Subject: [PATCH v12 10/17] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to both
TBMIterator and TBMSharedIterators. This encapsulates the parallel and serial
iterators and their access and makes the bitmap heap scan code a bit cleaner.
This naturally lends itself to a bit of reorganization of the
!node->initialized path in BitmapHeapNext(). Now, on the first scan, the the
iterator is created after the scan descriptor is created.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 163 ++++++++++++----------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  29 +---
 src/include/executor/nodeBitmapHeapscan.h |  10 ++
 src/include/nodes/execnodes.h             |   8 +-
 src/tools/pgindent/typedefs.list          |   1 +
 7 files changed, 116 insertions(+), 107 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 916d7a6e2e8..38c4fd5011c 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2218,10 +2218,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		tbmres = bhs_iterate(scan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 90cb10bc819..8b6f22bc3b6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -56,6 +56,56 @@ static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
+static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
+											 dsa_pointer shared_area,
+											 dsa_area *personal_area);
+
+BitmapHeapIterator *
+bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_area)
+{
+	BitmapHeapIterator *result = palloc(sizeof(BitmapHeapIterator));
+
+	result->serial = NULL;
+	result->parallel = NULL;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(shared_area))
+		result->parallel = tbm_attach_shared_iterate(personal_area, shared_area);
+	else
+		result->serial = tbm_begin_iterate(tbm);
+
+	return result;
+}
+
+TBMIterateResult *
+bhs_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		return tbm_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
+
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+	{
+		tbm_end_iterate(iterator->serial);
+		iterator->serial = NULL;
+	}
+	else
+	{
+		tbm_end_shared_iterate(iterator->parallel);
+		iterator->parallel = NULL;
+	}
+
+	pfree(iterator);
+}
 
 
 /* ----------------------------------------------------------------
@@ -97,43 +147,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate)
+		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
+			if (init_shared_state)
 			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
@@ -154,21 +184,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
 			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -198,8 +216,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  dsa);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			node->pf_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
+												  dsa);
+			/* Only used for serial BHS */
+			node->prefetch_pages = 0;
+			node->prefetch_target = -1;
+		}
+#endif							/* USE_PREFETCH */
 
 		node->initialized = true;
 
@@ -280,7 +311,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			node->pf_iterator &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -321,12 +352,11 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
@@ -335,7 +365,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = bhs_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -348,8 +378,6 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -371,7 +399,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -431,23 +459,22 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 				node->prefetch_pages++;
@@ -475,8 +502,6 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (1)
@@ -500,12 +525,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 
@@ -572,18 +597,17 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	if (node->pf_iterator)
+	{
+		bhs_end_iterate(node->pf_iterator);
+		node->pf_iterator = NULL;
+	}
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -628,12 +652,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+	if (node->pf_iterator)
+		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -671,11 +693,10 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
+	scanstate->pf_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc7..fb22f305bf6 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,12 +20,12 @@
 #include "storage/buf.h"
 #include "storage/spin.h"
 #include "utils/relcache.h"
+#include "executor/nodeBitmapHeapscan.h"
 
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
-struct TBMSharedIterator;
+struct BitmapHeapIterator;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -44,8 +44,7 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	struct BitmapHeapIterator *rs_bhs_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ad1805b55ed..592a8421bdf 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -964,8 +964,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
+	result->rs_bhs_iterator = NULL;
 	return result;
 }
 
@@ -1015,17 +1014,8 @@ table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1040,17 +1030,8 @@ table_rescan(TableScanDesc scan,
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index ea003a9caae..cb56d20dc6f 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -28,5 +28,15 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 										  ParallelContext *pcxt);
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+} BitmapHeapIterator;
+
+extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
+
 
 #endif							/* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8e344155679..cf8b4995f0d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1787,6 +1787,8 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
+struct BitmapHeapIterator;
+
 /* ----------------
  *	 BitmapHeapScanState information
  *
@@ -1795,12 +1797,11 @@ typedef struct ParallelBitmapHeapState
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
+ *		pf_iterator        for prefetching ahead of current page
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1815,12 +1816,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index a8d7bed411f..0fb2dad2053 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.40.1

v12-0011-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From 2ee3891dc6362dc484bbb4ea6778a268bd345469 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 17:09:12 -0400
Subject: [PATCH v12 11/17] table_scan_bitmap_next_block counts lossy and exact
 pages

Now that the table_scan_bitmap_next_block() callback only returns false
when the bitmap is exhausted, it is simpler to move the management of
the lossy and exact page counters into it. We will eventually remove
this callback and table_scan_bitmap_next_tuple() will update those
counters when a new block is read in.
---
 src/backend/access/heap/heapam_handler.c  |  8 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c |  9 ++-------
 src/include/access/tableam.h              | 21 +++++++++++++--------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 38c4fd5011c..46f1a374252 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2199,7 +2199,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+							  bool *recheck, BlockNumber *blockno,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block;
@@ -2349,7 +2350,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 8b6f22bc3b6..fb79f57d7a6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -119,7 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	bool		lossy;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -298,14 +297,10 @@ new_page:
 
 		BitmapAdjustPrefetchIterator(node);
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+										  &node->lossy_pages, &node->exact_pages))
 			break;
 
-		if (lossy)
-			node->lossy_pages++;
-		else
-			node->exact_pages++;
-
 		/*
 		 * If serial, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 592a8421bdf..a06ed271eb6 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -804,8 +804,8 @@ typedef struct TableAmRoutine
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * lossy indicates whether or not the block's representation in the bitmap
-	 * is lossy or exact.
+	 * lossy_pages is incremented if the block's representation in the bitmap
+	 * is lossy, otherwise, exact_pages is incremented.
 	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
@@ -822,8 +822,10 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+										   bool *recheck,
+										   BlockNumber *blockno,
+										   long *lossy_pages,
+										   long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -2019,15 +2021,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap table scan.
  * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy is set to true
- * if bitmap is lossy for the selected block and false otherwise.
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented if bitmap is lossy for the selected block and exact_pages is
+ * incremented otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+							 bool *recheck, BlockNumber *blockno,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -2038,7 +2042,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+														   blockno, lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v12-0012-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From 393fa25bbff39b997f9f21d68ec9dd24c0add612 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v12 12/17] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 33 +++++++--------------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 28 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..1dc4c99bf99 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1463,12 +1449,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	TBMSharedIterator *iterator;
 	TBMSharedIteratorState *istate;
 
-	/*
-	 * Create the TBMSharedIterator struct, with enough trailing space to
-	 * serve the needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..432fae52962 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.40.1

v12-0013-Separate-TBM-Shared-Iterator-and-TBMIterateResul.patchtext/x-diff; charset=us-asciiDownload
From 82b1fab2acccba1cdb9295f1e2b8897b12d33860 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v12 13/17] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 30 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 47 ++++++++-------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/executor/nodeBitmapHeapscan.h |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 8 files changed, 113 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3aa457a29e1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..033d5253394 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 46f1a374252..bd630e38fa8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2207,7 +2207,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2219,9 +2219,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = bhs_iterate(scan->rs_bhs_iterator);
+		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2236,11 +2236,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2248,19 +2248,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2289,7 +2289,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2298,9 +2298,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2350,7 +2350,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fb79f57d7a6..d61965a2761 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -77,15 +77,16 @@ bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_ar
 	return result;
 }
 
-TBMIterateResult *
-bhs_iterate(BitmapHeapIterator *iterator)
+void
+bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result)
 {
 	Assert(iterator);
+	Assert(result);
 
 	if (iterator->serial)
-		return tbm_iterate(iterator->serial);
+		tbm_iterate(iterator->serial, result);
 	else
-		return tbm_shared_iterate(iterator->parallel);
+		tbm_shared_iterate(iterator->parallel, result);
 }
 
 void
@@ -348,7 +349,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
 	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -360,8 +361,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = bhs_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -394,8 +395,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = bhs_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -462,10 +463,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -473,7 +476,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -482,13 +485,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -501,7 +504,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -520,8 +523,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = bhs_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -529,17 +532,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1dc4c99bf99..309a44bdb84 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..3b432263bb0 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index cb56d20dc6f..3c330f86e62 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -34,7 +34,7 @@ typedef struct BitmapHeapIterator
 	struct TBMSharedIterator *parallel;
 } BitmapHeapIterator;
 
-extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+extern void bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result);
 
 extern void bhs_end_iterate(BitmapHeapIterator *iterator);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae52962..f000c1af28f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.40.1

v12-0014-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchtext/x-diff; charset=us-asciiDownload
From 1bc468541c8c3de890c5c4acc374f8cb33ac1764 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 09:42:23 -0400
Subject: [PATCH v12 14/17] Push BitmapHeapScan prefetch code into heapam.c

In preparation for transitioning to using the streaming read API for
prefetching [1], move all of the BitmapHeapScanState members related to
prefetching and the functions for accessing them into the
HeapScanDescData and TableScanDescData. Members that still need to be
accessed in BitmapHeapNext() could not be moved into heap AM-specific
code. Specifically, parallel iterator setup requires several components
which seem odd to pass to the table AM API.

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  26 ++
 src/backend/access/heap/heapam_handler.c  | 262 +++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 341 ++--------------------
 src/include/access/heapam.h               |  17 ++
 src/include/access/relscan.h              |   8 +
 src/include/access/tableam.h              |  26 +-
 src/include/nodes/execnodes.h             |  14 -
 7 files changed, 355 insertions(+), 339 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 27e9d05f14b..086dae59668 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -948,8 +948,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+
+	scan->rs_base.blockno = InvalidBlockNumber;
+
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
+	scan->pvmbuffer = InvalidBuffer;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1032,6 +1040,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
+	scan->rs_base.blockno = InvalidBlockNumber;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	/*
 	 * unpin scan buffers
 	 */
@@ -1044,6 +1058,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1069,6 +1089,12 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bd630e38fa8..36c6fb021c3 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -61,6 +61,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
+static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2197,6 +2200,73 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+static inline void
+BitmapAdjustPrefetchIterator(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	TBMIterateResult tbmpre;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			scan->prefetch_pages--;
+		}
+		else if (prefetch_iterator)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblockno = tbmpre.blockno;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (scan->rs_base.prefetch_maximum > 0)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (prefetch_iterator)
+			{
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblockno = tbmpre.blockno;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  bool *recheck, BlockNumber *blockno,
@@ -2215,6 +2285,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(hscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2355,6 +2427,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->bm_parallel == NULL &&
+		scan->rs_pf_bhs_iterator &&
+		hscan->pfblockno < hscan->rs_base.blockno)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(hscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2365,6 +2449,154 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
+		else
+			scan->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+
+	if (pstate == NULL)
+	{
+		if (prefetch_iterator)
+		{
+			while (scan->prefetch_pages < scan->prefetch_target)
+			{
+				TBMIterateResult tbmpre;
+				bool		skip_fetch;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre.blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		if (prefetch_iterator)
+		{
+			while (1)
+			{
+				TBMIterateResult tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+
+				scan->pfblockno = tbmpre.blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
@@ -2390,6 +2622,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!scan->bm_parallel)
+	{
+		if (hscan->prefetch_target < scan->prefetch_maximum)
+			hscan->prefetch_target++;
+	}
+	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&scan->bm_parallel->mutex);
+		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+			scan->bm_parallel->prefetch_target++;
+		SpinLockRelease(&scan->bm_parallel->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(hscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d61965a2761..187b288e688 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
 											 dsa_pointer shared_area,
@@ -122,7 +118,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
@@ -142,7 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
 	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
 	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
 	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
@@ -154,7 +149,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate || init_shared_state)
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		int			pf_maximum = 0;
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
+#endif
+
+		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
@@ -169,23 +173,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * dsa_pointer of the iterator state which will be used by
 				 * multiple processes to iterate jointly.
 				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
-					pstate->prefetch_iterator =
+					node->pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
 				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
+				BitmapDoneInitializingSharedState(node->pstate);
 			}
 		}
 
@@ -216,19 +213,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		scan->prefetch_maximum = pf_maximum;
+		scan->bm_parallel = node->pstate;
+
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
 #ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
+		if (scan->prefetch_maximum > 0)
 		{
-			node->pf_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
-												  dsa);
-			/* Only used for serial BHS */
-			node->prefetch_pages = 0;
-			node->prefetch_target = -1;
+			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
+														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
+														 dsa);
 		}
 #endif							/* USE_PREFETCH */
 
@@ -243,36 +240,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
 
 			/*
 			 * If we are using lossy info, we have to recheck the qual
@@ -296,23 +263,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			node->pf_iterator &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,219 +289,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -594,22 +334,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->pf_iterator)
-	{
-		bhs_end_iterate(node->pf_iterator);
-		node->pf_iterator = NULL;
-	}
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -648,14 +378,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->pf_iterator)
-		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -688,17 +414,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->pf_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -738,13 +458,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -828,7 +541,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 49f212eb9a6..accbc1749cd 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -82,6 +82,23 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
+	/*
+	 * These fields only used for prefetching in bitmap table scans
+	 */
+
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
+
+	/*
+	 * These fields only used in serial BHS
+	 */
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block  */
+	BlockNumber pfblockno;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index fb22f305bf6..7938b741d66 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -26,6 +26,7 @@
 struct ParallelTableScanDescData;
 
 struct BitmapHeapIterator;
+struct ParallelBitmapHeapState;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -45,6 +46,13 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
+	struct BitmapHeapIterator *rs_pf_bhs_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+	struct ParallelBitmapHeapState *bm_parallel;
+	/* used to validate BHS prefetch and current block stay in sync */
+	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a06ed271eb6..a30c0412901 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -807,17 +807,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the block's representation in the bitmap
 	 * is lossy, otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -967,6 +956,9 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
+	result->rs_pf_bhs_iterator = NULL;
+	result->prefetch_maximum = 0;
+	result->bm_parallel = NULL;
 	return result;
 }
 
@@ -1018,6 +1010,12 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1034,6 +1032,12 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index cf8b4995f0d..592215d5ee7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,18 +1794,11 @@ struct BitmapHeapIterator;
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		pf_iterator        for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1813,18 +1806,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v12-0015-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From 441e94149ab349bc7008575e16f8cae5556f092a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 15:43:10 -0400
Subject: [PATCH v12 15/17] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block(). Heap AM's implementation of
table_scan_bitmap_next_tuple() now calls the original
heapam_scan_bitmap_next_block() function, but it is no longer an
implementation of a table AM callback but instead a helper for
heapam_scan_bitmap_next_tuple()
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 48 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 45 ++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 75 +++++------------------
 6 files changed, 63 insertions(+), 111 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 086dae59668..8dc1eab5348 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -319,6 +319,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 36c6fb021c3..717bcd08175 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2194,12 +2194,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
- */
-
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
  *
@@ -2233,8 +2227,8 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
@@ -2597,30 +2591,43 @@ BitmapPrefetch(HeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
-		return true;
-	}
+		if (hscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			hscan->rs_empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -3002,7 +3009,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index d9e23ef3175..1e89e3dfffa 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 187b288e688..2f9387e51a2 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -230,44 +230,35 @@ BitmapHeapNext(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 
 		node->initialized = true;
-
-		goto new_page;
 	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346f..cf56cc572fe 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a30c0412901..8665e90fbc7 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -795,36 +795,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the block's representation in the bitmap
-	 * is lossy, otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   BlockNumber *blockno,
-										   long *lossy_pages,
-										   long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -2023,44 +2007,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented if bitmap is lossy for the selected block and exact_pages is
- * incremented otherwise.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno,
-							 long *lossy_pages, long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   blockno, lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2071,7 +2024,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v12-0016-v13-Streaming-Read-API.patchtext/x-diff; charset=us-asciiDownload
From 5235e68513f32ffef2a896037296199d9d90039c Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 26 Feb 2024 23:48:31 +1300
Subject: [PATCH v12 16/17] v13 Streaming Read API

Part 1:

Provide vectored variant of ReadBuffer().

Break ReadBuffer() up into two steps: StartReadBuffers() and
WaitReadBuffers().  This has two advantages:

1.  Multiple consecutive blocks can be read with one system call.
2.  Advice (hints of future reads) can optionally be issued to the kernel.

The traditional ReadBuffer() function is now implemented in terms of
those functions, to avoid duplication.  For now we still only read a
block at a time so there is no change to generated system calls yet, but
later commits will provide infrastructure to help build up larger calls.

Callers should respect the new GUC io_combine_limit, and the limit on
per-backend pins which is now exposed as a public interface.

With some more infrastructure in later work, StartReadBuffers() could
be extended to start real asynchronous I/O instead of advice.

Part 2:

Provide API for streaming relation data.

Introduce an abstraction where relation data can be accessed as a
stream of buffers, with an implementation that is more efficient than
the equivalent sequence of ReadBuffer() calls.

Client code supplies a callback that can say which block number is
wanted next, and then consumes individual buffers one at a time from the
stream.  This division allows read_stream.c to build up large calls to
StartReadBuffers() up to io_combine_limit, and issue posix_fadvise()
advice ahead of time in a systematic way when random access is detected.

This API is based on an idea from Andres Freund to pave the way for
asynchronous I/O in future work as required to support direct I/O.  The
goal is to have an abstraction that insulates client code from future
changes to the I/O subsystem that would benefit from information about
future needs.

An extended API may be necessary in future for more complicated cases
(for example recovery, whose LsnReadQueue device in xlogprefetcher.c is
a distant cousin of this code and should eventually be replaced by
this), but this basic API is sufficient for many common usage patterns
involving predictable access to a single relation fork.
---
 doc/src/sgml/config.sgml                      |  14 +
 src/backend/storage/Makefile                  |   2 +-
 src/backend/storage/aio/Makefile              |  14 +
 src/backend/storage/aio/meson.build           |   5 +
 src/backend/storage/aio/read_stream.c         | 750 ++++++++++++++++++
 src/backend/storage/buffer/bufmgr.c           | 701 +++++++++++-----
 src/backend/storage/buffer/localbuf.c         |  14 +-
 src/backend/storage/meson.build               |   1 +
 src/backend/utils/misc/guc_tables.c           |  14 +
 src/backend/utils/misc/postgresql.conf.sample |   1 +
 src/include/storage/bufmgr.h                  |  41 +-
 src/include/storage/read_stream.h             |  63 ++
 src/tools/pgindent/typedefs.list              |   3 +
 13 files changed, 1400 insertions(+), 223 deletions(-)
 create mode 100644 src/backend/storage/aio/Makefile
 create mode 100644 src/backend/storage/aio/meson.build
 create mode 100644 src/backend/storage/aio/read_stream.c
 create mode 100644 src/include/storage/read_stream.h

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index f65c17e5ae4..241a6079688 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2720,6 +2720,20 @@ include_dir 'conf.d'
        </listitem>
       </varlistentry>
 
+      <varlistentry id="guc-io-combine-limit" xreflabel="io_combine_limit">
+       <term><varname>io_combine_limit</varname> (<type>integer</type>)
+       <indexterm>
+        <primary><varname>io_combine_limit</varname> configuration parameter</primary>
+       </indexterm>
+       </term>
+       <listitem>
+        <para>
+         Controls the largest I/O size in operations that combine I/O.
+         The default is 128kB.
+        </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry id="guc-max-worker-processes" xreflabel="max_worker_processes">
        <term><varname>max_worker_processes</varname> (<type>integer</type>)
        <indexterm>
diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile
index 8376cdfca20..eec03f6f2b4 100644
--- a/src/backend/storage/Makefile
+++ b/src/backend/storage/Makefile
@@ -8,6 +8,6 @@ subdir = src/backend/storage
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS     = buffer file freespace ipc large_object lmgr page smgr sync
+SUBDIRS     = aio buffer file freespace ipc large_object lmgr page smgr sync
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
new file mode 100644
index 00000000000..2f29a9ec4d1
--- /dev/null
+++ b/src/backend/storage/aio/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for storage/aio
+#
+# src/backend/storage/aio/Makefile
+#
+
+subdir = src/backend/storage/aio
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	read_stream.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
new file mode 100644
index 00000000000..10e1aa3b20b
--- /dev/null
+++ b/src/backend/storage/aio/meson.build
@@ -0,0 +1,5 @@
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+backend_sources += files(
+  'read_stream.c',
+)
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
new file mode 100644
index 00000000000..6b4b97372c7
--- /dev/null
+++ b/src/backend/storage/aio/read_stream.c
@@ -0,0 +1,750 @@
+/*-------------------------------------------------------------------------
+ *
+ * read_stream.c
+ *	  Mechanism for accessing buffered relation data with look-ahead
+ *
+ * Code that needs to access relation data typically pins blocks one at a
+ * time, often in a predictable order that might be sequential or data-driven.
+ * Calling the simple ReadBuffer() function for each block is inefficient,
+ * because blocks that are not yet in the buffer pool require I/O operations
+ * that are small and might stall waiting for storage.  This mechanism looks
+ * into the future and calls StartReadBuffers() and WaitReadBuffers() to read
+ * neighboring blocks together and ahead of time, with an adaptive look-ahead
+ * distance.
+ *
+ * A user-provided callback generates a stream of block numbers that is used
+ * to form reads of up to io_combine_limit, by attempting to merge them with a
+ * pending read.  When that isn't possible, the existing pending read is sent
+ * to StartReadBuffers() so that a new one can begin to form.
+ *
+ * The algorithm for controlling the look-ahead distance tries to classify the
+ * stream into three ideal behaviors:
+ *
+ * A) No I/O is necessary, because the requested blocks are fully cached
+ * already.  There is no benefit to looking ahead more than one block, so
+ * distance is 1.  This is the default initial assumption.
+ *
+ * B) I/O is necessary, but fadvise is undesirable because the access is
+ * sequential, or impossible because direct I/O is enabled or the system
+ * doesn't support advice.  There is no benefit in looking ahead more than
+ * io_combine_limit, because in this case only goal is larger read system
+ * calls.  Looking further ahead would pin many buffers and perform
+ * speculative work looking ahead for no benefit.
+ *
+ * C) I/O is necesssary, it appears random, and this system supports fadvise.
+ * We'll look further ahead in order to reach the configured level of I/O
+ * concurrency.
+ *
+ * The distance increases rapidly and decays slowly, so that it moves towards
+ * those levels as different I/O patterns are discovered.  For example, a
+ * sequential scan of fully cached data doesn't bother looking ahead, but a
+ * sequential scan that hits a region of uncached blocks will start issuing
+ * increasingly wide read calls until it plateaus at io_combine_limit.
+ *
+ * The main data structure is a circular queue of buffers of size
+ * max_pinned_buffers plus some extra space for technical reasons, ready to be
+ * returned by read_stream_next_buffer().  Each buffer also has an optional
+ * variable sized object that is passed from the callback to the consumer of
+ * buffers.
+ *
+ * Parallel to the queue of buffers, there is a circular queue of in-progress
+ * I/Os that have been started with StartReadBuffers(), and for which
+ * WaitReadBuffers() must be called before returning the buffer.
+ *
+ * For example, if the callback return block numbers 10, 42, 43, 60 in
+ * successive calls, then these data structures might appear as follows:
+ *
+ *                          buffers buf/data       ios
+ *
+ *                          +----+  +-----+       +--------+
+ *                          |    |  |     |  +----+ 42..44 | <- oldest_io_index
+ *                          +----+  +-----+  |    +--------+
+ *   oldest_buffer_index -> | 10 |  |  ?  |  | +--+ 60..60 |
+ *                          +----+  +-----+  | |  +--------+
+ *                          | 42 |  |  ?  |<-+ |  |        | <- next_io_index
+ *                          +----+  +-----+    |  +--------+
+ *                          | 43 |  |  ?  |    |  |        |
+ *                          +----+  +-----+    |  +--------+
+ *                          | 44 |  |  ?  |    |  |        |
+ *                          +----+  +-----+    |  +--------+
+ *                          | 60 |  |  ?  |<---+
+ *                          +----+  +-----+
+ *     next_buffer_index -> |    |  |     |
+ *                          +----+  +-----+
+ *
+ * In the example, 5 buffers are pinned, and the next buffer to be streamed to
+ * the client is block 10.  Block 10 was a hit and has no associated I/O, but
+ * the range 42..44 requires an I/O wait before its buffers are returned, as
+ * does block 60.
+ *
+ *
+ * Portions Copyright (c) 2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  src/backend/storage/aio/read_stream.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/pg_tablespace.h"
+#include "miscadmin.h"
+#include "storage/fd.h"
+#include "storage/smgr.h"
+#include "storage/read_stream.h"
+#include "utils/memdebug.h"
+#include "utils/rel.h"
+#include "utils/spccache.h"
+
+typedef struct InProgressIO
+{
+	int16		buffer_index;
+	ReadBuffersOperation op;
+} InProgressIO;
+
+/*
+ * State for managing a stream of reads.
+ */
+struct ReadStream
+{
+	int16		max_ios;
+	int16		ios_in_progress;
+	int16		queue_size;
+	int16		max_pinned_buffers;
+	int16		pinned_buffers;
+	int16		distance;
+	bool		advice_enabled;
+
+	/*
+	 * Sometimes we need to be able to 'unget' a block number to resolve a
+	 * flow control problem when I/Os are split.
+	 */
+	BlockNumber unget_blocknum;
+	bool		have_unget_blocknum;
+
+	/*
+	 * The callback that will tell us which block numbers to read, and an
+	 * opaque pointer that will be pass to it for its own purposes.
+	 */
+	ReadStreamBlockNumberCB callback;
+	void	   *callback_private_data;
+
+	/* Next expected block, for detecting sequential access. */
+	BlockNumber seq_blocknum;
+
+	/* The read operation we are currently preparing. */
+	BlockNumber pending_read_blocknum;
+	int16		pending_read_nblocks;
+
+	/* Space for buffers and optional per-buffer private data. */
+	size_t		per_buffer_data_size;
+	void	   *per_buffer_data;
+
+	/* Read operations that have been started but not waited for yet. */
+	InProgressIO *ios;
+	int16		oldest_io_index;
+	int16		next_io_index;
+
+	/* Circular queue of buffers. */
+	int16		oldest_buffer_index;	/* Next pinned buffer to return */
+	int16		next_buffer_index;	/* Index of next buffer to pin */
+	Buffer		buffers[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/*
+ * Return a pointer to the per-buffer data by index.
+ */
+static inline void *
+get_per_buffer_data(ReadStream *stream, int16 buffer_index)
+{
+	return (char *) stream->per_buffer_data +
+		stream->per_buffer_data_size * buffer_index;
+}
+
+/*
+ * Ask the callback which block it would like us to read next, with a small
+ * buffer in front to allow read_stream_unget_block() to work.
+ */
+static inline BlockNumber
+read_stream_get_block(ReadStream *stream, void *per_buffer_data)
+{
+	if (!stream->have_unget_blocknum)
+		return stream->callback(stream,
+								stream->callback_private_data,
+								per_buffer_data);
+
+	/*
+	 * You can only unget one block, and next_buffer_index can't change across
+	 * a get, unget, get sequence, so the callback's per_buffer_data, if any,
+	 * is still present in the correct slot.  We just have to return the
+	 * previous block number.
+	 */
+	stream->have_unget_blocknum = false;
+	return stream->unget_blocknum;
+}
+
+/*
+ * In order to deal with short reads in StartReadBuffers(), we sometimes need
+ * to defer handling of a block until later.
+ */
+static inline void
+read_stream_unget_block(ReadStream *stream, BlockNumber blocknum)
+{
+	Assert(!stream->have_unget_blocknum);
+	stream->have_unget_blocknum = true;
+	stream->unget_blocknum = blocknum;
+}
+
+static void
+read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
+{
+	bool		need_wait;
+	int			nblocks;
+	int			flags;
+	int16		io_index;
+	int16		overflow;
+	int16		buffer_index;
+
+	/* This should only be called with a pending read. */
+	Assert(stream->pending_read_nblocks > 0);
+	Assert(stream->pending_read_nblocks <= io_combine_limit);
+
+	/* We had better not exceed the pin limit by starting this read. */
+	Assert(stream->pinned_buffers + stream->pending_read_nblocks <=
+		   stream->max_pinned_buffers);
+
+	/* We had better not be overwriting an existing pinned buffer. */
+	if (stream->pinned_buffers > 0)
+		Assert(stream->next_buffer_index != stream->oldest_buffer_index);
+	else
+		Assert(stream->next_buffer_index == stream->oldest_buffer_index);
+
+	/*
+	 * If advice hasn't been suppressed, this system supports it, and this
+	 * isn't a strictly sequential pattern, then we'll issue advice.
+	 */
+	if (!suppress_advice &&
+		stream->advice_enabled &&
+		stream->pending_read_blocknum != stream->seq_blocknum)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else
+		flags = 0;
+
+	/* We say how many blocks we want to read, but may be smaller on return. */
+	buffer_index = stream->next_buffer_index;
+	io_index = stream->next_io_index;
+	nblocks = stream->pending_read_nblocks;
+	need_wait = StartReadBuffers(&stream->ios[io_index].op,
+								 &stream->buffers[buffer_index],
+								 stream->pending_read_blocknum,
+								 &nblocks,
+								 flags);
+	stream->pinned_buffers += nblocks;
+
+	/* Remember whether we need to wait before returning this buffer. */
+	if (!need_wait)
+	{
+		/* Look-ahead distance decays, no I/O necessary (behavior A). */
+		if (stream->distance > 1)
+			stream->distance--;
+	}
+	else
+	{
+		/*
+		 * Remember to call WaitReadBuffers() before returning head buffer.
+		 * Look-ahead distance will be adjusted after waiting.
+		 */
+		stream->ios[io_index].buffer_index = buffer_index;
+		if (++stream->next_io_index == stream->max_ios)
+			stream->next_io_index = 0;
+		Assert(stream->ios_in_progress < stream->max_ios);
+		stream->ios_in_progress++;
+		stream->seq_blocknum = stream->pending_read_blocknum + nblocks;
+	}
+
+	/*
+	 * We gave a contiguous range of buffer space to StartReadBuffers(), but
+	 * we want it to wrap around at queue_size.  Slide overflowing buffers to
+	 * the front of the array.
+	 */
+	overflow = (buffer_index + nblocks) - stream->queue_size;
+	if (overflow > 0)
+		memmove(&stream->buffers[0],
+				&stream->buffers[stream->queue_size],
+				sizeof(stream->buffers[0]) * overflow);
+
+	/* Compute location of start of next read, without using % operator. */
+	buffer_index += nblocks;
+	if (buffer_index >= stream->queue_size)
+		buffer_index -= stream->queue_size;
+	Assert(buffer_index >= 0 && buffer_index < stream->queue_size);
+	stream->next_buffer_index = buffer_index;
+
+	/* Adjust the pending read to cover the remaining portion, if any. */
+	stream->pending_read_blocknum += nblocks;
+	stream->pending_read_nblocks -= nblocks;
+}
+
+static void
+read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
+{
+	while (stream->ios_in_progress < stream->max_ios &&
+		   stream->pinned_buffers + stream->pending_read_nblocks < stream->distance)
+	{
+		BlockNumber blocknum;
+		int16		buffer_index;
+		void	   *per_buffer_data;
+
+		if (stream->pending_read_nblocks == io_combine_limit)
+		{
+			read_stream_start_pending_read(stream, suppress_advice);
+			suppress_advice = false;
+			continue;
+		}
+
+		/*
+		 * See which block the callback wants next in the stream.  We need to
+		 * compute the index of the Nth block of the pending read including
+		 * wrap-around, but we don't want to use the expensive % operator.
+		 */
+		buffer_index = stream->next_buffer_index + stream->pending_read_nblocks;
+		if (buffer_index >= stream->queue_size)
+			buffer_index -= stream->queue_size;
+		Assert(buffer_index >= 0 && buffer_index < stream->queue_size);
+		per_buffer_data = get_per_buffer_data(stream, buffer_index);
+		blocknum = read_stream_get_block(stream, per_buffer_data);
+		if (blocknum == InvalidBlockNumber)
+		{
+			/* End of stream. */
+			stream->distance = 0;
+			break;
+		}
+
+		/* Can we merge it with the pending read? */
+		if (stream->pending_read_nblocks > 0 &&
+			stream->pending_read_blocknum + stream->pending_read_nblocks == blocknum)
+		{
+			stream->pending_read_nblocks++;
+			continue;
+		}
+
+		/* We have to start the pending read before we can build another. */
+		if (stream->pending_read_nblocks > 0)
+		{
+			read_stream_start_pending_read(stream, suppress_advice);
+			suppress_advice = false;
+			if (stream->ios_in_progress == stream->max_ios)
+			{
+				/* And we've hit the limit.  Rewind, and stop here. */
+				read_stream_unget_block(stream, blocknum);
+				return;
+			}
+		}
+
+		/* This is the start of a new pending read. */
+		stream->pending_read_blocknum = blocknum;
+		stream->pending_read_nblocks = 1;
+	}
+
+	/*
+	 * We don't start the pending read just because we've hit the distance
+	 * limit, preferring to give it another chance to grow to full
+	 * io_combine_limit size once more buffers have been consumed.  However,
+	 * if we've already reached io_combine_limit, or we've reached the
+	 * distance limit and there isn't anything pinned yet, or the callback has
+	 * signaled end-of-stream, we start the read immediately.
+	 */
+	if (stream->pending_read_nblocks > 0 &&
+		(stream->pending_read_nblocks == io_combine_limit ||
+		 (stream->pending_read_nblocks == stream->distance &&
+		  stream->pinned_buffers == 0) ||
+		 stream->distance == 0) &&
+		stream->ios_in_progress < stream->max_ios)
+		read_stream_start_pending_read(stream, suppress_advice);
+}
+
+/*
+ * Create a new read stream object that can be used to perform the equivalent
+ * of a series of ReadBuffer() calls for one fork of one relation.
+ * Internally, it generates larger vectored reads where possible by looking
+ * ahead.  The callback should return block numbers or InvalidBlockNumber to
+ * signal end-of-stream, and if per_buffer_data_size is non-zero, it may also
+ * write extra data for each block into the space provided to it.  It will
+ * also receive callback_private_data for its own purposes.
+ */
+ReadStream *
+read_stream_begin_relation(int flags,
+						   BufferAccessStrategy strategy,
+						   BufferManagerRelation bmr,
+						   ForkNumber forknum,
+						   ReadStreamBlockNumberCB callback,
+						   void *callback_private_data,
+						   size_t per_buffer_data_size)
+{
+	ReadStream *stream;
+	size_t		size;
+	int16		queue_size;
+	int16		max_ios;
+	uint32		max_pinned_buffers;
+	Oid			tablespace_id;
+
+	/* Make sure our bmr's smgr and persistent are populated. */
+	if (bmr.smgr == NULL)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+
+	/*
+	 * Decide how many I/Os we will allow to run at the same time.  That
+	 * currently means advice to the kernel to tell it that we will soon read.
+	 * This number also affects how far we look ahead for opportunities to
+	 * start more I/Os.
+	 */
+	tablespace_id = bmr.smgr->smgr_rlocator.locator.spcOid;
+	if (!OidIsValid(MyDatabaseId) ||
+		(bmr.rel && IsCatalogRelation(bmr.rel)) ||
+		IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
+	{
+		/*
+		 * Avoid circularity while trying to look up tablespace settings or
+		 * before spccache.c is ready.
+		 */
+		max_ios = effective_io_concurrency;
+	}
+	else if (flags & READ_STREAM_MAINTENANCE)
+		max_ios = get_tablespace_maintenance_io_concurrency(tablespace_id);
+	else
+		max_ios = get_tablespace_io_concurrency(tablespace_id);
+	max_ios = Min(max_ios, PG_INT16_MAX);
+
+	/*
+	 * Choose the maximum number of buffers we're prepared to pin.  We try to
+	 * pin fewer if we can, though.  We clamp it to at least io_combine_limit
+	 * so that we can have a chance to build up a full io_combine_limit sized
+	 * read, even when max_ios is zero.  Be careful not to allow int16 to
+	 * overflow (even though that's not possible with the current GUC range
+	 * limits), allowing also for the spare entry and the overflow space.
+	 */
+	max_pinned_buffers = Max(max_ios * 4, io_combine_limit);
+	max_pinned_buffers = Min(max_pinned_buffers,
+							 PG_INT16_MAX - io_combine_limit - 1);
+
+	/* Don't allow this backend to pin more than its share of buffers. */
+	if (SmgrIsTemp(bmr.smgr))
+		LimitAdditionalLocalPins(&max_pinned_buffers);
+	else
+		LimitAdditionalPins(&max_pinned_buffers);
+	Assert(max_pinned_buffers > 0);
+
+	/*
+	 * We need one extra entry for buffers and per-buffer data, because users
+	 * of per-buffer data have access to the object until the next call to
+	 * read_stream_next_buffer(), so we need a gap between the head and tail
+	 * of the queue so that we don't clobber it.
+	 */
+	queue_size = max_pinned_buffers + 1;
+
+	/*
+	 * Allocate the object, the buffers, the ios and per_data_data space in
+	 * one big chunk.  Though we have queue_size buffers, we want to be able
+	 * to assume that all the buffers for a single read are contiguous (i.e.
+	 * don't wrap around halfway through), so we allow temporary overflows of
+	 * up to the maximum possible read size by allocating an extra
+	 * io_combine_limit - 1 elements.
+	 */
+	size = offsetof(ReadStream, buffers);
+	size += sizeof(Buffer) * (queue_size + io_combine_limit - 1);
+	size += sizeof(InProgressIO) * Max(1, max_ios);
+	size += per_buffer_data_size * queue_size;
+	size += MAXIMUM_ALIGNOF * 2;
+	stream = (ReadStream *) palloc(size);
+	memset(stream, 0, offsetof(ReadStream, buffers));
+	stream->ios = (InProgressIO *)
+		MAXALIGN(&stream->buffers[queue_size + io_combine_limit - 1]);
+	if (per_buffer_data_size > 0)
+		stream->per_buffer_data = (void *)
+			MAXALIGN(&stream->ios[Max(1, max_ios)]);
+
+#ifdef USE_PREFETCH
+
+	/*
+	 * This system supports prefetching advice.  We can use it as long as
+	 * direct I/O isn't enabled, the caller hasn't promised sequential access
+	 * (overriding our detection heuristics), and max_ios hasn't been set to
+	 * zero.
+	 */
+	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
+		(flags & READ_STREAM_SEQUENTIAL) == 0 &&
+		max_ios > 0)
+		stream->advice_enabled = true;
+#endif
+
+	/*
+	 * For now, max_ios = 0 is interpreted as max_ios = 1 with advice disabled
+	 * above.  If we had real asynchronous I/O we might need a slightly
+	 * different definition.
+	 */
+	if (max_ios == 0)
+		max_ios = 1;
+
+	stream->max_ios = max_ios;
+	stream->per_buffer_data_size = per_buffer_data_size;
+	stream->max_pinned_buffers = max_pinned_buffers;
+	stream->queue_size = queue_size;
+
+	if (!bmr.smgr)
+	{
+		bmr.smgr = RelationGetSmgr(bmr.rel);
+		bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+	}
+	stream->callback = callback;
+	stream->callback_private_data = callback_private_data;
+
+	/*
+	 * Skip the initial ramp-up phase if the caller says we're going to be
+	 * reading the whole relation.  This way we start out assuming we'll be
+	 * doing full io_combine_limit sized reads (behavior B).
+	 */
+	if (flags & READ_STREAM_FULL)
+		stream->distance = Min(max_pinned_buffers, io_combine_limit);
+	else
+		stream->distance = 1;
+
+	/*
+	 * Since we always currently always access the same relation, we can
+	 * initialize parts of the ReadBuffersOperation objects and leave them
+	 * that way, to avoid wasting CPU cycles writing to them for each read.
+	 */
+	for (int i = 0; i < max_ios; ++i)
+	{
+		stream->ios[i].op.bmr = bmr;
+		stream->ios[i].op.forknum = forknum;
+		stream->ios[i].op.strategy = strategy;
+	}
+
+	return stream;
+}
+
+/*
+ * Pull one pinned buffer out of a stream.  Each call returns successive
+ * blocks in the order specified by the callback.  If per_buffer_data_size was
+ * set to a non-zero size, *per_buffer_data receives a pointer to the extra
+ * per-buffer data that the callback had a chance to populate, which remains
+ * valid until the next call to read_stream_next_buffer().  When the stream
+ * runs out of data, InvalidBuffer is returned.  The caller may decide to end
+ * the stream early at any time by calling read_stream_end().
+ */
+Buffer
+read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
+{
+	Buffer		buffer;
+	int16		oldest_buffer_index;
+
+	/*
+	 * A fast path for all-cached scans (behavior A).  This is the same as the
+	 * usual algorithm, but it is specialized for no I/O and no per-buffer
+	 * data, so we can skip the queue management code, stay in the same buffer
+	 * slot and use singular StartReadBuffer().
+	 */
+	if (likely(per_buffer_data == NULL &&
+			   stream->ios_in_progress == 0 &&
+			   stream->pinned_buffers == 1 &&
+			   stream->distance == 1))
+	{
+		BlockNumber next_blocknum;
+
+		/*
+		 * We have a pinned buffer that we need to serve up, but we also want
+		 * to probe the next one before we return, just in case we need to
+		 * start an I/O.  We can re-use the same buffer slot, and an arbitrary
+		 * I/O slot since they're all free.
+		 */
+		oldest_buffer_index = stream->oldest_buffer_index;
+		Assert((oldest_buffer_index + 1) % stream->queue_size ==
+			   stream->next_buffer_index);
+		buffer = stream->buffers[oldest_buffer_index];
+		Assert(buffer != InvalidBuffer);
+		Assert(stream->pending_read_nblocks <= 1);
+		if (unlikely(stream->pending_read_nblocks == 1))
+		{
+			next_blocknum = stream->pending_read_blocknum;
+			stream->pending_read_nblocks = 0;
+		}
+		else
+			next_blocknum = read_stream_get_block(stream, NULL);
+		if (unlikely(next_blocknum == InvalidBlockNumber))
+		{
+			/* End of stream. */
+			stream->distance = 0;
+			stream->next_buffer_index = oldest_buffer_index;
+			/* Pin transferred to caller. */
+			stream->pinned_buffers = 0;
+			return buffer;
+		}
+		/* Call the special single block version, which is marginally faster. */
+		if (unlikely(StartReadBuffer(&stream->ios[0].op,
+									 &stream->buffers[oldest_buffer_index],
+									 next_blocknum,
+									 stream->advice_enabled ?
+									 READ_BUFFERS_ISSUE_ADVICE : 0)))
+		{
+			/* I/O needed.  We'll take the general path next time. */
+			stream->oldest_io_index = 0;
+			stream->next_io_index = stream->max_ios > 1 ? 1 : 0;
+			stream->ios_in_progress = 1;
+			stream->ios[0].buffer_index = oldest_buffer_index;
+			stream->seq_blocknum = next_blocknum + 1;
+			/* Increase look ahead distance (move towards behavior B/C). */
+			stream->distance = Min(2, stream->max_pinned_buffers);
+		}
+		/* Pin transferred to caller, got another one, no net change. */
+		Assert(stream->pinned_buffers == 1);
+		return buffer;
+	}
+
+	if (stream->pinned_buffers == 0)
+	{
+		Assert(stream->oldest_buffer_index == stream->next_buffer_index);
+
+		/* End of stream reached?  */
+		if (stream->distance == 0)
+			return InvalidBuffer;
+
+		/*
+		 * The usual order of operations is that we look ahead at the bottom
+		 * of this function after potentially finishing an I/O and making
+		 * space for more, but if we're just starting up we'll need to crank
+		 * the handle to get started.
+		 */
+		read_stream_look_ahead(stream, true);
+
+		/* End of stream reached? */
+		if (stream->pinned_buffers == 0)
+		{
+			Assert(stream->distance == 0);
+			return InvalidBuffer;
+		}
+	}
+
+	/* Grab the oldest pinned buffer and associated per-buffer data. */
+	Assert(stream->pinned_buffers > 0);
+	oldest_buffer_index = stream->oldest_buffer_index;
+	Assert(oldest_buffer_index >= 0 &&
+		   oldest_buffer_index < stream->queue_size);
+	buffer = stream->buffers[oldest_buffer_index];
+	if (per_buffer_data)
+		*per_buffer_data = get_per_buffer_data(stream, oldest_buffer_index);
+
+	Assert(BufferIsValid(buffer));
+
+	/* Do we have to wait for an associated I/O first? */
+	if (stream->ios_in_progress > 0 &&
+		stream->ios[stream->oldest_io_index].buffer_index == oldest_buffer_index)
+	{
+		int16		io_index = stream->oldest_io_index;
+		int16		distance;
+
+		/* Sanity check that we still agree on the buffers. */
+		Assert(stream->ios[io_index].op.buffers ==
+			   &stream->buffers[oldest_buffer_index]);
+
+		WaitReadBuffers(&stream->ios[io_index].op);
+
+		Assert(stream->ios_in_progress > 0);
+		stream->ios_in_progress--;
+		if (++stream->oldest_io_index == stream->max_ios)
+			stream->oldest_io_index = 0;
+
+		if (stream->ios[io_index].op.flags & READ_BUFFERS_ISSUE_ADVICE)
+		{
+			/* Distance ramps up fast (behavior C). */
+			distance = stream->distance * 2;
+			distance = Min(distance, stream->max_pinned_buffers);
+			stream->distance = distance;
+		}
+		else
+		{
+			/* No advice; move towards io_combine_limit (behavior B). */
+			if (stream->distance > io_combine_limit)
+			{
+				stream->distance--;
+			}
+			else
+			{
+				distance = stream->distance * 2;
+				distance = Min(distance, io_combine_limit);
+				distance = Min(distance, stream->max_pinned_buffers);
+				stream->distance = distance;
+			}
+		}
+	}
+
+#ifdef CLOBBER_FREED_MEMORY
+	/* Clobber old buffer and per-buffer data for debugging purposes. */
+	stream->buffers[oldest_buffer_index] = InvalidBuffer;
+
+	/*
+	 * The caller will get access to the per-buffer data, until the next call.
+	 * We wipe the one before, which is never occupied because queue_size
+	 * allowed one extra element.  This will hopefully trip up client code
+	 * that is holding a dangling pointer to it.
+	 */
+	if (stream->per_buffer_data)
+		wipe_mem(get_per_buffer_data(stream,
+									 oldest_buffer_index == 0 ?
+									 stream->queue_size - 1 :
+									 oldest_buffer_index - 1),
+				 stream->per_buffer_data_size);
+#endif
+
+	/* Pin transferred to caller. */
+	Assert(stream->pinned_buffers > 0);
+	stream->pinned_buffers--;
+
+	/* Advance oldest buffer, with wrap-around. */
+	stream->oldest_buffer_index++;
+	if (stream->oldest_buffer_index == stream->queue_size)
+		stream->oldest_buffer_index = 0;
+
+	/* Prepare for the next call. */
+	read_stream_look_ahead(stream, false);
+
+	return buffer;
+}
+
+/*
+ * Reset a read stream by releasing any queued up buffers, allowing the stream
+ * to be used again for different blocks.  This can be used to clear an
+ * end-of-stream condition and start again, or to throw away blocks that were
+ * speculatively read and read some different blocks instead.
+ */
+void
+read_stream_reset(ReadStream *stream)
+{
+	Buffer		buffer;
+
+	/* Stop looking ahead. */
+	stream->distance = 0;
+
+	/* Unpin anything that wasn't consumed. */
+	while ((buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer)
+		ReleaseBuffer(buffer);
+
+	Assert(stream->pinned_buffers == 0);
+	Assert(stream->ios_in_progress == 0);
+
+	/* Start off assuming data is cached. */
+	stream->distance = 1;
+}
+
+/*
+ * Release and free a read stream.
+ */
+void
+read_stream_end(ReadStream *stream)
+{
+	read_stream_reset(stream);
+	pfree(stream);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f0f8d4259c5..7123cbbaa2a 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -19,6 +19,11 @@
  *		and pin it so that no one can destroy it while this process
  *		is using it.
  *
+ * StartReadBuffers() -- as above, but for multiple contiguous blocks in
+ *		two steps.
+ *
+ * WaitReadBuffers() -- second step of StartReadBuffers().
+ *
  * ReleaseBuffer() -- unpin a buffer
  *
  * MarkBufferDirty() -- mark a pinned buffer's contents as "dirty".
@@ -160,6 +165,9 @@ int			checkpoint_flush_after = DEFAULT_CHECKPOINT_FLUSH_AFTER;
 int			bgwriter_flush_after = DEFAULT_BGWRITER_FLUSH_AFTER;
 int			backend_flush_after = DEFAULT_BACKEND_FLUSH_AFTER;
 
+/* Limit on how many blocks should be handled in single I/O operations. */
+int			io_combine_limit = DEFAULT_IO_COMBINE_LIMIT;
+
 /* local state for LockBufferForCleanup */
 static BufferDesc *PinCountWaitBuf = NULL;
 
@@ -471,10 +479,9 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
 )
 
 
-static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
+static Buffer ReadBuffer_common(BufferManagerRelation bmr,
 								ForkNumber forkNum, BlockNumber blockNum,
-								ReadBufferMode mode, BufferAccessStrategy strategy,
-								bool *hit);
+								ReadBufferMode mode, BufferAccessStrategy strategy);
 static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
 										   ForkNumber fork,
 										   BufferAccessStrategy strategy,
@@ -500,7 +507,7 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
 						  WritebackContext *wb_context);
 static void WaitIO(BufferDesc *buf);
-static bool StartBufferIO(BufferDesc *buf, bool forInput);
+static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
 static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty,
 							  uint32 set_flag_bits, bool forget_owner);
 static void AbortBufferIO(Buffer buffer);
@@ -781,7 +788,6 @@ Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
-	bool		hit;
 	Buffer		buf;
 
 	/*
@@ -794,15 +800,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot access temporary tables of other sessions")));
 
-	/*
-	 * Read the buffer, and update pgstat counters to reflect a cache hit or
-	 * miss.
-	 */
-	pgstat_count_buffer_read(reln);
-	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
-							forkNum, blockNum, mode, strategy, &hit);
-	if (hit)
-		pgstat_count_buffer_hit(reln);
+	buf = ReadBuffer_common(BMR_REL(reln),
+							forkNum, blockNum, mode, strategy);
+
 	return buf;
 }
 
@@ -822,13 +822,12 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
 						  BlockNumber blockNum, ReadBufferMode mode,
 						  BufferAccessStrategy strategy, bool permanent)
 {
-	bool		hit;
-
 	SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
 
-	return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
-							 RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
-							 mode, strategy, &hit);
+	return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
+									  RELPERSISTENCE_UNLOGGED),
+							 forkNum, blockNum,
+							 mode, strategy);
 }
 
 /*
@@ -994,35 +993,146 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
 	 */
 	if (buffer == InvalidBuffer)
 	{
-		bool		hit;
-
 		Assert(extended_by == 0);
-		buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
-								   fork, extend_to - 1, mode, strategy,
-								   &hit);
+		buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
 	}
 
 	return buffer;
 }
 
 /*
- * ReadBuffer_common -- common logic for all ReadBuffer variants
- *
- * *hit is set to true if the request was satisfied from shared buffer cache.
+ * Zero a buffer and lock it, as part of the implementation of
+ * RBM_ZERO_AND_LOCK or RBM_ZERO_AND_CLEANUP_LOCK.  The buffer must be already
+ * pinned.  It does not have to be valid, but it is valid and locked on
+ * return.
  */
-static Buffer
-ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
-				  BlockNumber blockNum, ReadBufferMode mode,
-				  BufferAccessStrategy strategy, bool *hit)
+static void
+ZeroBuffer(Buffer buffer, ReadBufferMode mode)
 {
 	BufferDesc *bufHdr;
-	Block		bufBlock;
-	bool		found;
+	uint32		buf_state;
+
+	Assert(mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
+
+	if (BufferIsLocal(buffer))
+		bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+	else
+	{
+		bufHdr = GetBufferDescriptor(buffer - 1);
+		if (mode == RBM_ZERO_AND_LOCK)
+			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+		else
+			LockBufferForCleanup(buffer);
+	}
+
+	memset(BufferGetPage(buffer), 0, BLCKSZ);
+
+	if (BufferIsLocal(buffer))
+	{
+		buf_state = pg_atomic_read_u32(&bufHdr->state);
+		buf_state |= BM_VALID;
+		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+	}
+	else
+	{
+		buf_state = LockBufHdr(bufHdr);
+		buf_state |= BM_VALID;
+		UnlockBufHdr(bufHdr, buf_state);
+	}
+}
+
+/*
+ * Pin a buffer for a given block.  *foundPtr is set to true if the block was
+ * already present, or false if more work is required to either read it in or
+ * zero it.
+ */
+static inline Buffer
+PinBufferForBlock(BufferManagerRelation bmr,
+				  ForkNumber forkNum,
+				  BlockNumber blockNum,
+				  BufferAccessStrategy strategy,
+				  bool *foundPtr)
+{
+	BufferDesc *bufHdr;
+	bool		isLocalBuf;
 	IOContext	io_context;
 	IOObject	io_object;
-	bool		isLocalBuf = SmgrIsTemp(smgr);
 
-	*hit = false;
+	Assert(blockNum != P_NEW);
+
+	Assert(bmr.smgr);
+
+	isLocalBuf = bmr.relpersistence == RELPERSISTENCE_TEMP;
+	if (isLocalBuf)
+	{
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
+	}
+	else
+	{
+		io_context = IOContextForStrategy(strategy);
+		io_object = IOOBJECT_RELATION;
+	}
+
+	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
+									   bmr.smgr->smgr_rlocator.locator.spcOid,
+									   bmr.smgr->smgr_rlocator.locator.dbOid,
+									   bmr.smgr->smgr_rlocator.locator.relNumber,
+									   bmr.smgr->smgr_rlocator.backend);
+
+	if (isLocalBuf)
+	{
+		bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+		if (*foundPtr)
+			pgBufferUsage.local_blks_hit++;
+	}
+	else
+	{
+		bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
+							 strategy, foundPtr, io_context);
+		if (*foundPtr)
+			pgBufferUsage.shared_blks_hit++;
+	}
+	if (bmr.rel)
+	{
+		/*
+		 * While pgBufferUsage's "read" counter isn't bumped unless we reach
+		 * WaitReadBuffers() (so, not for hits, and not for buffers that are
+		 * zeroed instead), the per-relation stats always count them.
+		 */
+		pgstat_count_buffer_read(bmr.rel);
+		if (*foundPtr)
+			pgstat_count_buffer_hit(bmr.rel);
+	}
+	if (*foundPtr)
+	{
+		VacuumPageHit++;
+		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageHit;
+
+		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
+										  bmr.smgr->smgr_rlocator.locator.spcOid,
+										  bmr.smgr->smgr_rlocator.locator.dbOid,
+										  bmr.smgr->smgr_rlocator.locator.relNumber,
+										  bmr.smgr->smgr_rlocator.backend,
+										  true);
+	}
+
+	return BufferDescriptorGetBuffer(bufHdr);
+}
+
+/*
+ * ReadBuffer_common -- common logic for all ReadBuffer variants
+ */
+static inline Buffer
+ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
+				  BlockNumber blockNum, ReadBufferMode mode,
+				  BufferAccessStrategy strategy)
+{
+	ReadBuffersOperation operation;
+	Buffer		buffer;
+	int			flags;
 
 	/*
 	 * Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1041,181 +1151,359 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
 			flags |= EB_LOCK_FIRST;
 
-		return ExtendBufferedRel(BMR_SMGR(smgr, relpersistence),
-								 forkNum, strategy, flags);
+		return ExtendBufferedRel(bmr, forkNum, strategy, flags);
 	}
 
-	TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
-									   smgr->smgr_rlocator.locator.spcOid,
-									   smgr->smgr_rlocator.locator.dbOid,
-									   smgr->smgr_rlocator.locator.relNumber,
-									   smgr->smgr_rlocator.backend);
-
-	if (isLocalBuf)
+	if (unlikely(mode == RBM_ZERO_AND_CLEANUP_LOCK ||
+				 mode == RBM_ZERO_AND_LOCK))
 	{
-		/*
-		 * We do not use a BufferAccessStrategy for I/O of temporary tables.
-		 * However, in some cases, the "strategy" may not be NULL, so we can't
-		 * rely on IOContextForStrategy() to set the right IOContext for us.
-		 * This may happen in cases like CREATE TEMPORARY TABLE AS...
-		 */
-		io_context = IOCONTEXT_NORMAL;
-		io_object = IOOBJECT_TEMP_RELATION;
-		bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
-		if (found)
-			pgBufferUsage.local_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.local_blks_read++;
+		bool		found;
+
+		if (bmr.smgr == NULL)
+		{
+			bmr.smgr = RelationGetSmgr(bmr.rel);
+			bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
+		}
+
+		buffer = PinBufferForBlock(bmr, forkNum, blockNum, strategy, &found);
+		ZeroBuffer(buffer, mode);
+		return buffer;
 	}
+
+	if (mode == RBM_ZERO_ON_ERROR)
+		flags = READ_BUFFERS_ZERO_ON_ERROR;
 	else
+		flags = 0;
+	operation.bmr = bmr;
+	operation.forknum = forkNum;
+	operation.strategy = strategy;
+	if (StartReadBuffer(&operation,
+						&buffer,
+						blockNum,
+						flags))
+		WaitReadBuffers(&operation);
+
+	return buffer;
+}
+
+/*
+ * Single block version of the StartReadBuffers().  This might save a few
+ * instructions when called from another translation unit, if the compiler
+ * inlines the code and specializes for nblocks == 1.
+ */
+bool
+StartReadBuffer(ReadBuffersOperation *operation,
+				Buffer *buffer,
+				BlockNumber blocknum,
+				int flags)
+{
+	int			nblocks = 1;
+	bool		result;
+
+	result = StartReadBuffers(operation, buffer, blocknum, &nblocks, flags);
+	Assert(nblocks == 1);		/* single block can't be short */
+
+	return result;
+}
+
+/*
+ * Begin reading a range of blocks beginning at blockNum and extending for
+ * *nblocks.  On return, up to *nblocks pinned buffers holding those blocks
+ * are written into the buffers array, and *nblocks is updated to contain the
+ * actual number, which may be fewer than requested.  Caller sets some of the
+ * members of operation; see struct definition.
+ *
+ * If false is returned, no I/O is necessary.  If true is returned, one I/O
+ * has been started, and WaitReadBuffers() must be called with the same
+ * operation object before the buffers are accessed.  Along with the operation
+ * object, the caller-supplied array of buffers must remain valid until
+ * WaitReadBuffers() is called.
+ *
+ * Currently the I/O is only started with optional operating system advice,
+ * and the real I/O happens in WaitReadBuffers().  In future work, true I/O
+ * could be initiated here.
+ */
+inline bool
+StartReadBuffers(ReadBuffersOperation *operation,
+				 Buffer *buffers,
+				 BlockNumber blockNum,
+				 int *nblocks,
+				 int flags)
+{
+	int			actual_nblocks = *nblocks;
+	int			io_buffers_len = 0;
+
+	Assert(*nblocks > 0);
+	Assert(*nblocks <= MAX_IO_COMBINE_LIMIT);
+
+	if (!operation->bmr.smgr)
 	{
-		/*
-		 * lookup the buffer.  IO_IN_PROGRESS is set if the requested block is
-		 * not currently in memory.
-		 */
-		io_context = IOContextForStrategy(strategy);
-		io_object = IOOBJECT_RELATION;
-		bufHdr = BufferAlloc(smgr, relpersistence, forkNum, blockNum,
-							 strategy, &found, io_context);
-		if (found)
-			pgBufferUsage.shared_blks_hit++;
-		else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-				 mode == RBM_ZERO_ON_ERROR)
-			pgBufferUsage.shared_blks_read++;
+		operation->bmr.smgr = RelationGetSmgr(operation->bmr.rel);
+		operation->bmr.relpersistence = operation->bmr.rel->rd_rel->relpersistence;
 	}
 
-	/* At this point we do NOT hold any locks. */
-
-	/* if it was already in the buffer pool, we're done */
-	if (found)
+	for (int i = 0; i < actual_nblocks; ++i)
 	{
-		/* Just need to update stats before we exit */
-		*hit = true;
-		VacuumPageHit++;
-		pgstat_count_io_op(io_object, io_context, IOOP_HIT);
+		bool		found;
 
-		if (VacuumCostActive)
-			VacuumCostBalance += VacuumCostPageHit;
+		buffers[i] = PinBufferForBlock(operation->bmr,
+									   operation->forknum,
+									   blockNum + i,
+									   operation->strategy,
+									   &found);
 
-		TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-										  smgr->smgr_rlocator.locator.spcOid,
-										  smgr->smgr_rlocator.locator.dbOid,
-										  smgr->smgr_rlocator.locator.relNumber,
-										  smgr->smgr_rlocator.backend,
-										  found);
+		if (found)
+		{
+			/*
+			 * Terminate the read as soon as we get a hit.  It could be a
+			 * single buffer hit, or it could be a hit that follows a readable
+			 * range.  We don't want to create more than one readable range,
+			 * so we stop here.
+			 */
+			actual_nblocks = i + 1;
+			break;
+		}
+		else
+		{
+			/* Extend the readable range to cover this block. */
+			io_buffers_len++;
+		}
+	}
+	*nblocks = actual_nblocks;
 
-		/*
-		 * In RBM_ZERO_AND_LOCK mode the caller expects the page to be locked
-		 * on return.
-		 */
-		if (!isLocalBuf)
+	if (io_buffers_len > 0)
+	{
+		/* Populate information needed for I/O. */
+		operation->buffers = buffers;
+		operation->blocknum = blockNum;
+		operation->flags = flags;
+		operation->nblocks = actual_nblocks;
+		operation->io_buffers_len = io_buffers_len;
+
+		if (flags & READ_BUFFERS_ISSUE_ADVICE)
 		{
-			if (mode == RBM_ZERO_AND_LOCK)
-				LWLockAcquire(BufferDescriptorGetContentLock(bufHdr),
-							  LW_EXCLUSIVE);
-			else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
-				LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
+			/*
+			 * In theory we should only do this if PinBufferForBlock() had to
+			 * allocate new buffers above.  That way, if two calls to
+			 * StartReadBuffers() were made for the same blocks before
+			 * WaitReadBuffers(), only the first would issue the advice.
+			 * That'd be a better simulation of true asynchronous I/O, which
+			 * would only start the I/O once, but isn't done here for
+			 * simplicity.  Note also that the following call might actually
+			 * issue two advice calls if we cross a segment boundary; in a
+			 * true asynchronous version we might choose to process only one
+			 * real I/O at a time in that case.
+			 */
+			smgrprefetch(operation->bmr.smgr,
+						 operation->forknum,
+						 blockNum,
+						 operation->io_buffers_len);
 		}
 
-		return BufferDescriptorGetBuffer(bufHdr);
+		/* Indicate that WaitReadBuffers() should be called. */
+		return true;
+	}
+	else
+	{
+		return false;
 	}
+}
+
+static inline bool
+WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
+{
+	if (BufferIsLocal(buffer))
+	{
+		BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1);
+
+		return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0;
+	}
+	else
+		return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait);
+}
+
+void
+WaitReadBuffers(ReadBuffersOperation *operation)
+{
+	Buffer	   *buffers;
+	int			nblocks;
+	BlockNumber blocknum;
+	ForkNumber	forknum;
+	bool		isLocalBuf;
+	IOContext	io_context;
+	IOObject	io_object;
 
 	/*
-	 * if we have gotten to this point, we have allocated a buffer for the
-	 * page but its contents are not yet valid.  IO_IN_PROGRESS is set for it,
-	 * if it's a shared buffer.
+	 * Currently operations are only allowed to include a read of some range,
+	 * with an optional extra buffer that is already pinned at the end.  So
+	 * nblocks can be at most one more than io_buffers_len.
 	 */
-	Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID));	/* spinlock not needed */
+	Assert((operation->nblocks == operation->io_buffers_len) ||
+		   (operation->nblocks == operation->io_buffers_len + 1));
 
-	bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
+	/* Find the range of the physical read we need to perform. */
+	nblocks = operation->io_buffers_len;
+	if (nblocks == 0)
+		return;					/* nothing to do */
+
+	buffers = &operation->buffers[0];
+	blocknum = operation->blocknum;
+	forknum = operation->forknum;
+
+	isLocalBuf = operation->bmr.relpersistence == RELPERSISTENCE_TEMP;
+	if (isLocalBuf)
+	{
+		io_context = IOCONTEXT_NORMAL;
+		io_object = IOOBJECT_TEMP_RELATION;
+	}
+	else
+	{
+		io_context = IOContextForStrategy(operation->strategy);
+		io_object = IOOBJECT_RELATION;
+	}
 
 	/*
-	 * Read in the page, unless the caller intends to overwrite it and just
-	 * wants us to allocate a buffer.
+	 * We count all these blocks as read by this backend.  This is traditional
+	 * behavior, but might turn out to be not true if we find that someone
+	 * else has beaten us and completed the read of some of these blocks.  In
+	 * that case the system globally double-counts, but we traditionally don't
+	 * count this as a "hit", and we don't have a separate counter for "miss,
+	 * but another backend completed the read".
 	 */
-	if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
-		MemSet((char *) bufBlock, 0, BLCKSZ);
+	if (isLocalBuf)
+		pgBufferUsage.local_blks_read += nblocks;
 	else
+		pgBufferUsage.shared_blks_read += nblocks;
+
+	for (int i = 0; i < nblocks; ++i)
 	{
-		instr_time	io_start = pgstat_prepare_io_time(track_io_timing);
+		int			io_buffers_len;
+		Buffer		io_buffers[MAX_IO_COMBINE_LIMIT];
+		void	   *io_pages[MAX_IO_COMBINE_LIMIT];
+		instr_time	io_start;
+		BlockNumber io_first_block;
+
+		/*
+		 * Skip this block if someone else has already completed it.  If an
+		 * I/O is already in progress in another backend, this will wait for
+		 * the outcome: either done, or something went wrong and we will
+		 * retry.
+		 */
+		if (!WaitReadBuffersCanStartIO(buffers[i], false))
+		{
+			/*
+			 * Report this as a 'hit' for this backend, even though it must
+			 * have started out as a miss in PinBufferForBlock().
+			 */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
+											  operation->bmr.smgr->smgr_rlocator.locator.spcOid,
+											  operation->bmr.smgr->smgr_rlocator.locator.dbOid,
+											  operation->bmr.smgr->smgr_rlocator.locator.relNumber,
+											  operation->bmr.smgr->smgr_rlocator.backend,
+											  true);
+			continue;
+		}
+
+		/* We found a buffer that we need to read in. */
+		io_buffers[0] = buffers[i];
+		io_pages[0] = BufferGetBlock(buffers[i]);
+		io_first_block = blocknum + i;
+		io_buffers_len = 1;
 
-		smgrread(smgr, forkNum, blockNum, bufBlock);
+		/*
+		 * How many neighboring-on-disk blocks can we can scatter-read into
+		 * other buffers at the same time?  In this case we don't wait if we
+		 * see an I/O already in progress.  We already hold BM_IO_IN_PROGRESS
+		 * for the head block, so we should get on with that I/O as soon as
+		 * possible.  We'll come back to this block again, above.
+		 */
+		while ((i + 1) < nblocks &&
+			   WaitReadBuffersCanStartIO(buffers[i + 1], true))
+		{
+			/* Must be consecutive block numbers. */
+			Assert(BufferGetBlockNumber(buffers[i + 1]) ==
+				   BufferGetBlockNumber(buffers[i]) + 1);
+
+			io_buffers[io_buffers_len] = buffers[++i];
+			io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
+		}
 
-		pgstat_count_io_op_time(io_object, io_context,
-								IOOP_READ, io_start, 1);
+		io_start = pgstat_prepare_io_time(track_io_timing);
+		smgrreadv(operation->bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
+		pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
+								io_buffers_len);
 
-		/* check for garbage data */
-		if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
-									PIV_LOG_WARNING | PIV_REPORT_STAT))
+		/* Verify each block we read, and terminate the I/O. */
+		for (int j = 0; j < io_buffers_len; ++j)
 		{
-			if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages)
+			BufferDesc *bufHdr;
+			Block		bufBlock;
+
+			if (isLocalBuf)
 			{
-				ereport(WARNING,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s; zeroing out page",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-				MemSet((char *) bufBlock, 0, BLCKSZ);
+				bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
+				bufBlock = LocalBufHdrGetBlock(bufHdr);
 			}
 			else
-				ereport(ERROR,
-						(errcode(ERRCODE_DATA_CORRUPTED),
-						 errmsg("invalid page in block %u of relation %s",
-								blockNum,
-								relpath(smgr->smgr_rlocator, forkNum))));
-		}
-	}
-
-	/*
-	 * In RBM_ZERO_AND_LOCK / RBM_ZERO_AND_CLEANUP_LOCK mode, grab the buffer
-	 * content lock before marking the page as valid, to make sure that no
-	 * other backend sees the zeroed page before the caller has had a chance
-	 * to initialize it.
-	 *
-	 * Since no-one else can be looking at the page contents yet, there is no
-	 * difference between an exclusive lock and a cleanup-strength lock. (Note
-	 * that we cannot use LockBuffer() or LockBufferForCleanup() here, because
-	 * they assert that the buffer is already valid.)
-	 */
-	if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
-		!isLocalBuf)
-	{
-		LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE);
-	}
+			{
+				bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
+				bufBlock = BufHdrGetBlock(bufHdr);
+			}
 
-	if (isLocalBuf)
-	{
-		/* Only need to adjust flags */
-		uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
+			/* check for garbage data */
+			if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
+										PIV_LOG_WARNING | PIV_REPORT_STAT))
+			{
+				if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
+				{
+					ereport(WARNING,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s; zeroing out page",
+									io_first_block + j,
+									relpath(operation->bmr.smgr->smgr_rlocator, forknum))));
+					memset(bufBlock, 0, BLCKSZ);
+				}
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_DATA_CORRUPTED),
+							 errmsg("invalid page in block %u of relation %s",
+									io_first_block + j,
+									relpath(operation->bmr.smgr->smgr_rlocator, forknum))));
+			}
 
-		buf_state |= BM_VALID;
-		pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
-	}
-	else
-	{
-		/* Set BM_VALID, terminate IO, and wake up any waiters */
-		TerminateBufferIO(bufHdr, false, BM_VALID, true);
-	}
+			/* Terminate I/O and set BM_VALID. */
+			if (isLocalBuf)
+			{
+				uint32		buf_state = pg_atomic_read_u32(&bufHdr->state);
 
-	VacuumPageMiss++;
-	if (VacuumCostActive)
-		VacuumCostBalance += VacuumCostPageMiss;
+				buf_state |= BM_VALID;
+				pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
+			}
+			else
+			{
+				/* Set BM_VALID, terminate IO, and wake up any waiters */
+				TerminateBufferIO(bufHdr, false, BM_VALID, true);
+			}
 
-	TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
-									  smgr->smgr_rlocator.locator.spcOid,
-									  smgr->smgr_rlocator.locator.dbOid,
-									  smgr->smgr_rlocator.locator.relNumber,
-									  smgr->smgr_rlocator.backend,
-									  found);
+			/* Report I/Os as completing individually. */
+			TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
+											  operation->bmr.smgr->smgr_rlocator.locator.spcOid,
+											  operation->bmr.smgr->smgr_rlocator.locator.dbOid,
+											  operation->bmr.smgr->smgr_rlocator.locator.relNumber,
+											  operation->bmr.smgr->smgr_rlocator.backend,
+											  false);
+		}
 
-	return BufferDescriptorGetBuffer(bufHdr);
+		VacuumPageMiss += io_buffers_len;
+		if (VacuumCostActive)
+			VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
+	}
 }
 
 /*
- * BufferAlloc -- subroutine for ReadBuffer.  Handles lookup of a shared
- *		buffer.  If no buffer exists already, selects a replacement
- *		victim and evicts the old page, but does NOT read in new page.
+ * BufferAlloc -- subroutine for PinBufferForBlock.  Handles lookup of a shared
+ *		buffer.  If no buffer exists already, selects a replacement victim and
+ *		evicts the old page, but does NOT read in new page.
  *
  * "strategy" can be a buffer replacement strategy object, or NULL for
  * the default strategy.  The selected buffer's usage_count is advanced when
@@ -1223,11 +1511,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
  *
  * The returned buffer is pinned and is already marked as holding the
  * desired page.  If it already did have the desired page, *foundPtr is
- * set true.  Otherwise, *foundPtr is set false and the buffer is marked
- * as IO_IN_PROGRESS; ReadBuffer will now need to do I/O to fill it.
- *
- * *foundPtr is actually redundant with the buffer's BM_VALID flag, but
- * we keep it for simplicity in ReadBuffer.
+ * set true.  Otherwise, *foundPtr is set false.
  *
  * io_context is passed as an output parameter to avoid calling
  * IOContextForStrategy() when there is a shared buffers hit and no IO
@@ -1286,19 +1570,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(buf, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return buf;
@@ -1363,19 +1638,10 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		{
 			/*
 			 * We can only get here if (a) someone else is still reading in
-			 * the page, or (b) a previous read attempt failed.  We have to
-			 * wait for any active read attempt to finish, and then set up our
-			 * own read attempt if the page is still not BM_VALID.
-			 * StartBufferIO does it all.
+			 * the page, (b) a previous read attempt failed, or (c) someone
+			 * called StartReadBuffers() but not yet WaitReadBuffers().
 			 */
-			if (StartBufferIO(existing_buf_hdr, true))
-			{
-				/*
-				 * If we get here, previous attempts to read the buffer must
-				 * have failed ... but we shall bravely try again.
-				 */
-				*foundPtr = false;
-			}
+			*foundPtr = false;
 		}
 
 		return existing_buf_hdr;
@@ -1407,15 +1673,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	LWLockRelease(newPartitionLock);
 
 	/*
-	 * Buffer contents are currently invalid.  Try to obtain the right to
-	 * start I/O.  If StartBufferIO returns false, then someone else managed
-	 * to read it before we did, so there's nothing left for BufferAlloc() to
-	 * do.
+	 * Buffer contents are currently invalid.
 	 */
-	if (StartBufferIO(victim_buf_hdr, true))
-		*foundPtr = false;
-	else
-		*foundPtr = true;
+	*foundPtr = false;
 
 	return victim_buf_hdr;
 }
@@ -1769,7 +2029,7 @@ again:
  * pessimistic, but outside of toy-sized shared_buffers it should allow
  * sufficient pins.
  */
-static void
+void
 LimitAdditionalPins(uint32 *additional_pins)
 {
 	uint32		max_backends;
@@ -2034,7 +2294,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 
 				buf_state &= ~BM_VALID;
 				UnlockBufHdr(existing_hdr, buf_state);
-			} while (!StartBufferIO(existing_hdr, true));
+			} while (!StartBufferIO(existing_hdr, true, false));
 		}
 		else
 		{
@@ -2057,7 +2317,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 			LWLockRelease(partition_lock);
 
 			/* XXX: could combine the locked operations in it with the above */
-			StartBufferIO(victim_buf_hdr, true);
+			StartBufferIO(victim_buf_hdr, true, false);
 		}
 	}
 
@@ -2372,7 +2632,12 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	else
 	{
 		/*
-		 * If we previously pinned the buffer, it must surely be valid.
+		 * If we previously pinned the buffer, it is likely to be valid, but
+		 * it may not be if StartReadBuffers() was called and
+		 * WaitReadBuffers() hasn't been called yet.  We'll check by loading
+		 * the flags without locking.  This is racy, but it's OK to return
+		 * false spuriously: when WaitReadBuffers() calls StartBufferIO(),
+		 * it'll see that it's now valid.
 		 *
 		 * Note: We deliberately avoid a Valgrind client request here.
 		 * Individual access methods can optionally superimpose buffer page
@@ -2381,7 +2646,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 		 * that the buffer page is legitimately non-accessible here.  We
 		 * cannot meddle with that.
 		 */
-		result = true;
+		result = (pg_atomic_read_u32(&buf->state) & BM_VALID) != 0;
 	}
 
 	ref->refcount++;
@@ -3449,7 +3714,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
 	 * someone else flushed the buffer before we could, so we need not do
 	 * anything.
 	 */
-	if (!StartBufferIO(buf, false))
+	if (!StartBufferIO(buf, false, false))
 		return;
 
 	/* Setup error traceback support for ereport() */
@@ -5184,9 +5449,15 @@ WaitIO(BufferDesc *buf)
  *
  * Returns true if we successfully marked the buffer as I/O busy,
  * false if someone else already did the work.
+ *
+ * If nowait is true, then we don't wait for an I/O to be finished by another
+ * backend.  In that case, false indicates either that the I/O was already
+ * finished, or is still in progress.  This is useful for callers that want to
+ * find out if they can perform the I/O as part of a larger operation, without
+ * waiting for the answer or distinguishing the reasons why not.
  */
 static bool
-StartBufferIO(BufferDesc *buf, bool forInput)
+StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
 {
 	uint32		buf_state;
 
@@ -5199,6 +5470,8 @@ StartBufferIO(BufferDesc *buf, bool forInput)
 		if (!(buf_state & BM_IO_IN_PROGRESS))
 			break;
 		UnlockBufHdr(buf, buf_state);
+		if (nowait)
+			return false;
 		WaitIO(buf);
 	}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index fcfac335a57..985a2c7049c 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -108,10 +108,9 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
  * LocalBufferAlloc -
  *	  Find or create a local buffer for the given page of the given relation.
  *
- * API is similar to bufmgr.c's BufferAlloc, except that we do not need
- * to do any locking since this is all local.   Also, IO_IN_PROGRESS
- * does not get set.  Lastly, we support only default access strategy
- * (hence, usage_count is always advanced).
+ * API is similar to bufmgr.c's BufferAlloc, except that we do not need to do
+ * any locking since this is all local.  We support only default access
+ * strategy (hence, usage_count is always advanced).
  */
 BufferDesc *
 LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
@@ -287,7 +286,7 @@ GetLocalVictimBuffer(void)
 }
 
 /* see LimitAdditionalPins() */
-static void
+void
 LimitAdditionalLocalPins(uint32 *additional_pins)
 {
 	uint32		max_pins;
@@ -297,9 +296,10 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
 
 	/*
 	 * In contrast to LimitAdditionalPins() other backends don't play a role
-	 * here. We can allow up to NLocBuffer pins in total.
+	 * here. We can allow up to NLocBuffer pins in total, but it might not be
+	 * initialized yet so read num_temp_buffers.
 	 */
-	max_pins = (NLocBuffer - NLocalPinnedBuffers);
+	max_pins = (num_temp_buffers - NLocalPinnedBuffers);
 
 	if (*additional_pins >= max_pins)
 		*additional_pins = max_pins;
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
index 40345bdca27..739d13293fb 100644
--- a/src/backend/storage/meson.build
+++ b/src/backend/storage/meson.build
@@ -1,5 +1,6 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
+subdir('aio')
 subdir('buffer')
 subdir('file')
 subdir('freespace')
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 92fcd5fa4d5..c12784cbec8 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3129,6 +3129,20 @@ struct config_int ConfigureNamesInt[] =
 		NULL
 	},
 
+	{
+		{"io_combine_limit",
+			PGC_USERSET,
+			RESOURCES_ASYNCHRONOUS,
+			gettext_noop("Limit on the size of data reads and writes."),
+			NULL,
+			GUC_UNIT_BLOCKS
+		},
+		&io_combine_limit,
+		DEFAULT_IO_COMBINE_LIMIT,
+		1, MAX_IO_COMBINE_LIMIT,
+		NULL, NULL, NULL
+	},
+
 	{
 		{"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index adcc0257f91..baecde28410 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -203,6 +203,7 @@
 #backend_flush_after = 0		# measured in pages, 0 disables
 #effective_io_concurrency = 1		# 1-1000; 0 disables prefetching
 #maintenance_io_concurrency = 10	# 1-1000; 0 disables prefetching
+#io_combine_limit = 128kB		# usually 1-32 blocks (depends on OS)
 #max_worker_processes = 8		# (change requires restart)
 #max_parallel_workers_per_gather = 2	# limited by max_parallel_workers
 #max_parallel_maintenance_workers = 2	# limited by max_parallel_workers
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d51d46d3353..241f68c45e1 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
+#include "port/pg_iovec.h"
 #include "storage/block.h"
 #include "storage/buf.h"
 #include "storage/bufpage.h"
@@ -133,6 +134,10 @@ extern PGDLLIMPORT bool track_io_timing;
 extern PGDLLIMPORT int effective_io_concurrency;
 extern PGDLLIMPORT int maintenance_io_concurrency;
 
+#define MAX_IO_COMBINE_LIMIT PG_IOV_MAX
+#define DEFAULT_IO_COMBINE_LIMIT Min(MAX_IO_COMBINE_LIMIT, (128 * 1024) / BLCKSZ)
+extern PGDLLIMPORT int io_combine_limit;
+
 extern PGDLLIMPORT int checkpoint_flush_after;
 extern PGDLLIMPORT int backend_flush_after;
 extern PGDLLIMPORT int bgwriter_flush_after;
@@ -158,7 +163,6 @@ extern PGDLLIMPORT int32 *LocalRefCount;
 #define BUFFER_LOCK_SHARE		1
 #define BUFFER_LOCK_EXCLUSIVE	2
 
-
 /*
  * prototypes for functions in bufmgr.c
  */
@@ -177,6 +181,38 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
 										ForkNumber forkNum, BlockNumber blockNum,
 										ReadBufferMode mode, BufferAccessStrategy strategy,
 										bool permanent);
+
+#define READ_BUFFERS_ZERO_ON_ERROR 0x01
+#define READ_BUFFERS_ISSUE_ADVICE 0x02
+
+struct ReadBuffersOperation
+{
+	/* The following members should be set by the caller. */
+	BufferManagerRelation bmr;
+	ForkNumber	forknum;
+	BufferAccessStrategy strategy;
+
+	/* The following private members should not be accessed directly. */
+	Buffer	   *buffers;
+	BlockNumber blocknum;
+	int			flags;
+	int16		nblocks;
+	int16		io_buffers_len;
+};
+
+typedef struct ReadBuffersOperation ReadBuffersOperation;
+
+extern bool StartReadBuffer(ReadBuffersOperation *operation,
+							Buffer *buffer,
+							BlockNumber blocknum,
+							int flags);
+extern bool StartReadBuffers(ReadBuffersOperation *operation,
+							 Buffer *buffers,
+							 BlockNumber blocknum,
+							 int *nblocks,
+							 int flags);
+extern void WaitReadBuffers(ReadBuffersOperation *operation);
+
 extern void ReleaseBuffer(Buffer buffer);
 extern void UnlockReleaseBuffer(Buffer buffer);
 extern bool BufferIsExclusiveLocked(Buffer buffer);
@@ -250,6 +286,9 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern void LimitAdditionalPins(uint32 *additional_pins);
+extern void LimitAdditionalLocalPins(uint32 *additional_pins);
+
 /* in buf_init.c */
 extern void InitBufferPool(void);
 extern Size BufferShmemSize(void);
diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h
new file mode 100644
index 00000000000..f5dbc087b0b
--- /dev/null
+++ b/src/include/storage/read_stream.h
@@ -0,0 +1,63 @@
+/*-------------------------------------------------------------------------
+ *
+ * read_stream.h
+ *	  Mechanism for accessing buffered relation data with look-ahead
+ *
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/read_stream.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef READ_STREAM_H
+#define READ_STREAM_H
+
+#include "storage/bufmgr.h"
+
+/* Default tuning, reasonable for many users. */
+#define READ_STREAM_DEFAULT 0x00
+
+/*
+ * I/O streams that are performing maintenance work on behalf of potentially
+ * many users, and thus should be governed by maintenance_io_concurrency
+ * instead of effective_io_concurrency.  For example, VACUUM or CREATE INDEX.
+ */
+#define READ_STREAM_MAINTENANCE 0x01
+
+/*
+ * We usually avoid issuing prefetch advice automatically when sequential
+ * access is detected, but this flag explicitly disables it, for cases that
+ * might not be correctly detected.  Explicit advice is known to perform worse
+ * than letting the kernel (at least Linux) detect sequential access.
+ */
+#define READ_STREAM_SEQUENTIAL 0x02
+
+/*
+ * We usually ramp up from smaller reads to larger ones, to support users who
+ * don't know if it's worth reading lots of buffers yet.  This flag disables
+ * that, declaring ahead of time that we'll be reading all available buffers.
+ */
+#define READ_STREAM_FULL 0x04
+
+struct ReadStream;
+typedef struct ReadStream ReadStream;
+
+/* Callback that returns the next block number to read. */
+typedef BlockNumber (*ReadStreamBlockNumberCB) (ReadStream *stream,
+												void *callback_private_data,
+												void *per_buffer_data);
+
+extern ReadStream *read_stream_begin_relation(int flags,
+											  BufferAccessStrategy strategy,
+											  BufferManagerRelation bmr,
+											  ForkNumber forknum,
+											  ReadStreamBlockNumberCB callback,
+											  void *callback_private_data,
+											  size_t per_buffer_data_size);
+extern Buffer read_stream_next_buffer(ReadStream *stream, void **per_buffer_private);
+extern void read_stream_reset(ReadStream *stream);
+extern void read_stream_end(ReadStream *stream);
+
+#endif							/* READ_STREAM_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 0fb2dad2053..e652b5b8141 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1215,6 +1215,7 @@ InjectionPointCacheEntry
 InjectionPointEntry
 InjectionPointSharedState
 InlineCodeBlock
+InProgressIO
 InsertStmt
 Instrumentation
 Int128AggState
@@ -2288,11 +2289,13 @@ ReInitializeDSMForeignScan_function
 ReScanForeignScan_function
 ReadBufPtrType
 ReadBufferMode
+ReadBuffersOperation
 ReadBytePtrType
 ReadExtraTocPtrType
 ReadFunc
 ReadLocalXLogPageNoWaitPrivate
 ReadReplicationSlotCmd
+ReadStream
 ReassignOwnedStmt
 RecheckForeignScan_function
 RecordCacheArrayEntry
-- 
2.40.1

v12-0017-BitmapHeapScan-uses-read-stream-API.patchtext/x-diff; charset=us-asciiDownload
From 8f207aa0d17355228fb8bf4df5c1c82c3be935bf Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 16:51:40 -0400
Subject: [PATCH v12 17/17] BitmapHeapScan uses read stream API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the read stream API prefetching. Heap table AM implements a read
stream callback which uses the iterator to get the next valid block that
needs to be fetched for the read stream API.
---
 src/backend/access/heap/heapam.c          |  99 ++++--
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  43 +--
 src/include/access/heapam.h               |  21 +-
 src/include/access/relscan.h              |   6 -
 src/include/access/tableam.h              |  14 -
 src/include/nodes/execnodes.h             |   9 +-
 7 files changed, 121 insertions(+), 418 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 8dc1eab5348..2a9547249a0 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -108,6 +108,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_stream_read_next(ReadStream *pgsr, void *pgsr_private,
+											   void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -324,6 +326,23 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
+	/*
+	 * Make the read stream object for BitmapHeapScan. If this is a rescan, we
+	 * expect that the previous read stream was ended in heap_rescan() before
+	 * invoking initscan(). Do not create the read stream until after creating
+	 * the BufferAccessStrategy object.
+	 */
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  BMR_REL(scan->rs_base.rs_rd),
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
+
 	/*
 	 * copy the scan key, if appropriate
 	 */
@@ -950,16 +969,9 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-
-	scan->rs_base.blockno = InvalidBlockNumber;
-
+	scan->rs_read_stream = NULL;
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
-	scan->pvmbuffer = InvalidBuffer;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1042,12 +1054,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
-	scan->rs_base.blockno = InvalidBlockNumber;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
-
 	/*
 	 * unpin scan buffers
 	 */
@@ -1060,10 +1066,13 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
+	/* Free the old read stream before reinitializing the scan descriptor */
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
+		if (scan->rs_read_stream)
+			read_stream_end(scan->rs_read_stream);
+
+		scan->rs_read_stream = NULL;
 	}
 
 	/*
@@ -1091,11 +1100,9 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
+	/* We must free the read stream before the BufferAccessStrategy object */
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_read_stream)
+		read_stream_end(scan->rs_read_stream);
 
 	/*
 	 * decrement relation reference count and free scan descriptor storage
@@ -10132,3 +10139,51 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) private_data;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		bhs_iterate(hdesc->rs_base.rs_bhs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(hdesc->rs_base.rs_flags & SO_NEED_TUPLE) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 717bcd08175..859bc4603d0 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -61,9 +61,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
-static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
-static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
-static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2194,147 +2191,68 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
-	 * parallel workers.
-	 */
-	if (scan->rs_base.prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno,
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *per_buffer_data;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(hscan);
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2355,7 +2273,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2364,9 +2282,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2416,23 +2334,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->bm_parallel == NULL &&
-		scan->rs_pf_bhs_iterator &&
-		hscan->pfblockno < hscan->rs_base.blockno)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(hscan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2443,153 +2349,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= prefetch_maximum / 2)
-			scan->prefetch_target = prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= prefetch_maximum / 2)
-			pstate->prefetch_target = prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-
-				scan->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
@@ -2624,41 +2383,11 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 			return true;
 		}
 
-		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
 										   lossy_pages, exact_pages))
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!scan->bm_parallel)
-	{
-		if (hscan->prefetch_target < scan->prefetch_maximum)
-			hscan->prefetch_target++;
-	}
-	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&scan->bm_parallel->mutex);
-		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-			scan->bm_parallel->prefetch_target++;
-		SpinLockRelease(&scan->bm_parallel->mutex);
-	}
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(hscan);
-#endif							/* USE_PREFETCH */
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2f9387e51a2..f2662ea542c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -131,14 +131,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -149,15 +141,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-		int			pf_maximum = 0;
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
-#endif
-
 		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -174,13 +157,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					node->pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
+
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(node->pstate);
 			}
@@ -213,22 +190,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
 												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
-#ifdef USE_PREFETCH
-		if (scan->prefetch_maximum > 0)
-		{
-			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
-														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
-														 dsa);
-		}
-#endif							/* USE_PREFETCH */
-
 		node->initialized = true;
 	}
 
@@ -525,14 +492,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -563,11 +526,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index accbc1749cd..c4943af9e4d 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/read_stream.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	ReadStream *rs_read_stream;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -82,23 +86,6 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
-	/*
-	 * These fields only used for prefetching in bitmap table scans
-	 */
-
-	/* buffer for visibility-map lookups of prefetched pages */
-	Buffer		pvmbuffer;
-
-	/*
-	 * These fields only used in serial BHS
-	 */
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
-	/* used to validate prefetch block stays ahead of current block  */
-	BlockNumber pfblockno;
-
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 7938b741d66..02893bf99bc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -46,13 +46,7 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
-	struct BitmapHeapIterator *rs_pf_bhs_iterator;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
-	/* used to validate BHS prefetch and current block stay in sync */
-	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8665e90fbc7..559ea9c248d 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -940,8 +940,6 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
-	result->rs_pf_bhs_iterator = NULL;
-	result->prefetch_maximum = 0;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -994,12 +992,6 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1016,12 +1008,6 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 592215d5ee7..8d86b900a0b 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1767,11 +1767,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1779,10 +1775,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.40.1

#96Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#95)
16 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

On Fri, Mar 29, 2024 at 12:05:15PM +0100, Tomas Vondra wrote:

On 3/29/24 02:12, Thomas Munro wrote:

On Fri, Mar 29, 2024 at 10:43 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

Thanks for the repro. I can't seem to reproduce it (still trying) but
I assume this is with Melanie's v11 patch set which had
v11-0016-v10-Read-Stream-API.patch.

Would you mind removing that commit and instead applying the v13
stream_read.c patches[1]? v10 stream_read.c was a little confused
about random I/O combining, which I fixed with a small adjustment to
the conditions for the "if" statement right at the end of
read_stream_look_ahead(). Sorry about that. The fixed version, with
eic=4, with your test query using WHERE a < a, ends its scan with:

I'll give that a try. Unfortunately unfortunately the v11 still has the
problem I reported about a week ago:

ERROR: prefetch and main iterators are out of sync

So I can't run the full benchmarks :-( but master vs. streaming read API
should work, I think.

Odd, I didn't notice you reporting this ERROR popping up. Now that I
take a look, v11 (at least, maybe also v10) had this very sill mistake:

  if (scan->bm_parallel == NULL &&
      scan->rs_pf_bhs_iterator &&
      hscan->pfblockno > hscan->rs_base.blockno)
       elog(ERROR, "prefetch and main iterators are out of sync");

It errors out if the prefetch block is ahead of the current block --
which is the opposite of what we want. I've fixed this in attached v12.

This version also has v13 of the streaming read API. I noticed one
mistake in my bitmapheap scan streaming read user -- it freed the
streaming read object at the wrong time. I don't know if this was
causing any other issues, but it at least is fixed in this version.

Attached v13 is rebased over master (which includes the streaming read
API now). I also reset the streaming read object on rescan instead of
creating a new one each time.

I don't know how much chance any of this has of going in to 17 now, but
I thought I would start looking into the regression repro Tomas provided
in [1]/messages/by-id/5d5954ed-6f43-4f1a-8e19-ece75b2b7362@enterprisedb.com.

I'm also not sure if I should try and group the commits into fewer
commits now or wait until I have some idea of whether or not the
approach in 0013 and 0014 is worth pursuing.

- Melanie

[1]: /messages/by-id/5d5954ed-6f43-4f1a-8e19-ece75b2b7362@enterprisedb.com

Attachments:

v13-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 8244da026228e82333eb501d0d9f96540d2282be Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v13 02/16] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 93fdcd226b..c64530674b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -742,16 +752,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v13-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From 3a3cffe2adb8b43ae0298bb23633856cc4045299 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v13 01/16] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 805d222ceb..b0f61c65f3 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aab..93fdcd226b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v13-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From 378bf4147ec506c32d01fa94335299804db42f18 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 20:15:05 -0500
Subject: [PATCH v13 03/16] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a9d5b109a5..50b4bc1475 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -948,6 +948,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1036,6 +1038,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1055,6 +1063,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 0952d4a98e..ae894a7573 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2198,6 +2199,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2310,6 +2329,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c64530674b..83d9db8f39 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,11 +185,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
 																	node->ss.ss_currentRelation,
 																	node->ss.ps.state->es_snapshot,
 																	0,
-																	NULL);
+																	NULL,
+																	extra_flags);
 		}
 
 		node->initialized = true;
@@ -207,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -228,37 +232,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -301,52 +282,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -518,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -569,7 +531,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -639,8 +601,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -650,7 +610,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -695,8 +654,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -740,8 +697,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -752,7 +707,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index a307fb5f24..a527e1b99f 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,6 +76,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e7eeb75409..55f1139757 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -63,6 +63,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -937,9 +944,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e7ff8e4992..4880f346bf 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,10 +1794,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1817,9 +1814,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v13-0004-BitmapPrefetch-use-prefetch-block-recheck-for-sk.patchtext/x-diff; charset=us-asciiDownload
From c2fd41ee5afbd8bd643bc6cd3c8529f912e83219 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v13 04/16] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 83d9db8f39..5df3b5ca46 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -474,14 +474,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -532,7 +527,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v13-0005-Update-BitmapAdjustPrefetchIterator-parameter-ty.patchtext/x-diff; charset=us-asciiDownload
From 48d65097497466d8c23a1bfe38b74c2942900f24 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v13 05/16] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5df3b5ca46..404de0595e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -230,7 +230,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -341,7 +341,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -360,7 +360,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v13-0006-table_scan_bitmap_next_block-returns-lossy-or-ex.patchtext/x-diff; charset=us-asciiDownload
From 34ca369410bf7c1161cf34b5eafb74099a8d3811 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v13 06/16] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ae894a7573..48b8359786 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2316,6 +2317,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 404de0595e..c95e3412da 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,7 +211,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
+		bool		valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -232,12 +232,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 55f1139757..75c5ee956d 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,6 +789,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -804,7 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1971,14 +1975,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1989,7 +1995,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.40.1

v13-0007-Reduce-scope-of-BitmapHeapScan-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From fe6ac36bbd1dadebc9c2e7a2958c7009029f20b1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v13 07/16] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c95e3412da..49938c9ed4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -206,6 +202,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -221,9 +219,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v13-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From 39c219ddccb054e5fbcd3cec9e4f3356847af8bd Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v13 08/16] Remove table_scan_bitmap_next_tuple parameter
 tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 48b8359786..265f33f000 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2324,7 +2324,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 49938c9ed4..282dcb9791 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -286,7 +286,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 75c5ee956d..1b545f2b67 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,10 +780,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -814,15 +811,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2008,7 +2000,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2020,7 +2011,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v13-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 5ff565b545d1ff1e08aaa9c610fff3d8c7d0d7b5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v13 09/16] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 195 insertions(+), 149 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 265f33f000..8a9d2a9c34 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,18 +2188,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2218,16 +2251,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2319,7 +2343,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 282dcb9791..90cb10bc81 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +109,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +161,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -202,55 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool		valid, lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -272,45 +232,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,13 +311,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -356,14 +335,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -388,7 +370,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -466,6 +451,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -523,6 +509,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -584,12 +572,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -597,13 +581,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -634,28 +618,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -688,8 +668,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -697,9 +675,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304a..92b829cebc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1b545f2b67..74ddd5d66d 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -773,19 +774,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -804,8 +800,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -942,9 +938,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -991,6 +991,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1001,6 +1016,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1964,19 +1994,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1986,8 +2014,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 4880f346bf..8e34415567 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v13-0010-Unify-parallel-and-serial-BitmapHeapScan-iterato.patchtext/x-diff; charset=us-asciiDownload
From 89f594870e40601de33778f7157c8ee3c1b7b370 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 25 Mar 2024 11:05:51 -0400
Subject: [PATCH v13 10/16] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to both
TBMIterator and TBMSharedIterators. This encapsulates the parallel and serial
iterators and their access and makes the bitmap heap scan code a bit cleaner.
This naturally lends itself to a bit of reorganization of the
!node->initialized path in BitmapHeapNext(). Now, on the first scan, the the
iterator is created after the scan descriptor is created.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 163 ++++++++++++----------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  29 +---
 src/include/executor/nodeBitmapHeapscan.h |  10 ++
 src/include/nodes/execnodes.h             |   8 +-
 src/tools/pgindent/typedefs.list          |   1 +
 7 files changed, 116 insertions(+), 107 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 8a9d2a9c34..b2e52e3fc1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2207,10 +2207,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		tbmres = bhs_iterate(scan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 90cb10bc81..8b6f22bc3b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -56,6 +56,56 @@ static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
+static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
+											 dsa_pointer shared_area,
+											 dsa_area *personal_area);
+
+BitmapHeapIterator *
+bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_area)
+{
+	BitmapHeapIterator *result = palloc(sizeof(BitmapHeapIterator));
+
+	result->serial = NULL;
+	result->parallel = NULL;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(shared_area))
+		result->parallel = tbm_attach_shared_iterate(personal_area, shared_area);
+	else
+		result->serial = tbm_begin_iterate(tbm);
+
+	return result;
+}
+
+TBMIterateResult *
+bhs_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		return tbm_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
+
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+	{
+		tbm_end_iterate(iterator->serial);
+		iterator->serial = NULL;
+	}
+	else
+	{
+		tbm_end_shared_iterate(iterator->parallel);
+		iterator->parallel = NULL;
+	}
+
+	pfree(iterator);
+}
 
 
 /* ----------------------------------------------------------------
@@ -97,43 +147,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate)
+		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
+			if (init_shared_state)
 			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
@@ -154,21 +184,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
 			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -198,8 +216,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  dsa);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			node->pf_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
+												  dsa);
+			/* Only used for serial BHS */
+			node->prefetch_pages = 0;
+			node->prefetch_target = -1;
+		}
+#endif							/* USE_PREFETCH */
 
 		node->initialized = true;
 
@@ -280,7 +311,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			node->pf_iterator &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -321,12 +352,11 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
@@ -335,7 +365,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = bhs_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -348,8 +378,6 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -371,7 +399,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -431,23 +459,22 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 				node->prefetch_pages++;
@@ -475,8 +502,6 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (1)
@@ -500,12 +525,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 
@@ -572,18 +597,17 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	if (node->pf_iterator)
+	{
+		bhs_end_iterate(node->pf_iterator);
+		node->pf_iterator = NULL;
+	}
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -628,12 +652,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+	if (node->pf_iterator)
+		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -671,11 +693,10 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
+	scanstate->pf_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc..fb22f305bf 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,12 +20,12 @@
 #include "storage/buf.h"
 #include "storage/spin.h"
 #include "utils/relcache.h"
+#include "executor/nodeBitmapHeapscan.h"
 
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
-struct TBMSharedIterator;
+struct BitmapHeapIterator;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -44,8 +44,7 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	struct BitmapHeapIterator *rs_bhs_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 74ddd5d66d..d4fbf0d889 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -942,8 +942,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
+	result->rs_bhs_iterator = NULL;
 	return result;
 }
 
@@ -993,17 +992,8 @@ table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1018,17 +1008,8 @@ table_rescan(TableScanDesc scan,
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index ea003a9caa..cb56d20dc6 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -28,5 +28,15 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 										  ParallelContext *pcxt);
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+} BitmapHeapIterator;
+
+extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
+
 
 #endif							/* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8e34415567..cf8b4995f0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1787,6 +1787,8 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
+struct BitmapHeapIterator;
+
 /* ----------------
  *	 BitmapHeapScanState information
  *
@@ -1795,12 +1797,11 @@ typedef struct ParallelBitmapHeapState
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
+ *		pf_iterator        for prefetching ahead of current page
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1815,12 +1816,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 8d08386d65..825454c90c 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.40.1

v13-0011-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From 63f90ed6dcac0c65c56b292a8c78ad87561c1550 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 17:09:12 -0400
Subject: [PATCH v13 11/16] table_scan_bitmap_next_block counts lossy and exact
 pages

Now that the table_scan_bitmap_next_block() callback only returns false
when the bitmap is exhausted, it is simpler to move the management of
the lossy and exact page counters into it. We will eventually remove
this callback and table_scan_bitmap_next_tuple() will update those
counters when a new block is read in.
---
 src/backend/access/heap/heapam_handler.c  |  8 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c |  9 ++-------
 src/include/access/tableam.h              | 21 +++++++++++++--------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b2e52e3fc1..b08837efd0 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+							  bool *recheck, BlockNumber *blockno,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block;
@@ -2338,7 +2339,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 8b6f22bc3b..fb79f57d7a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -119,7 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	bool		lossy;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -298,14 +297,10 @@ new_page:
 
 		BitmapAdjustPrefetchIterator(node);
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+										  &node->lossy_pages, &node->exact_pages))
 			break;
 
-		if (lossy)
-			node->lossy_pages++;
-		else
-			node->exact_pages++;
-
 		/*
 		 * If serial, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d4fbf0d889..70e538b76b 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -782,8 +782,8 @@ typedef struct TableAmRoutine
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * lossy indicates whether or not the block's representation in the bitmap
-	 * is lossy or exact.
+	 * lossy_pages is incremented if the block's representation in the bitmap
+	 * is lossy, otherwise, exact_pages is incremented.
 	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
@@ -800,8 +800,10 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+										   bool *recheck,
+										   BlockNumber *blockno,
+										   long *lossy_pages,
+										   long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1977,15 +1979,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap table scan.
  * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy is set to true
- * if bitmap is lossy for the selected block and false otherwise.
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented if bitmap is lossy for the selected block and exact_pages is
+ * incremented otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+							 bool *recheck, BlockNumber *blockno,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1996,7 +2000,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+														   blockno, lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v13-0012-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-diff; charset=us-asciiDownload
From 27eb60345e14bba33420198c55bf3c2041592097 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v13 12/16] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 33 +++++++--------------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 28 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fc..1dc4c99bf9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1463,12 +1449,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	TBMSharedIterator *iterator;
 	TBMSharedIteratorState *istate;
 
-	/*
-	 * Create the TBMSharedIterator struct, with enough trailing space to
-	 * serve the needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639b..432fae5296 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.40.1

v13-0013-Separate-TBM-Shared-Iterator-and-TBMIterateResul.patchtext/x-diff; charset=us-asciiDownload
From 05f7e86cb1276a6141d0213d40bcd7252e8af31e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v13 13/16] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 30 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 47 ++++++++-------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/executor/nodeBitmapHeapscan.h |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 8 files changed, 113 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb..3aa457a29e 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544..033d525339 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b08837efd0..d9ceb4b848 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2196,7 +2196,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2208,9 +2208,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = bhs_iterate(scan->rs_bhs_iterator);
+		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2225,11 +2225,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2237,19 +2237,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2278,7 +2278,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2287,9 +2287,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2339,7 +2339,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fb79f57d7a..d61965a276 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -77,15 +77,16 @@ bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_ar
 	return result;
 }
 
-TBMIterateResult *
-bhs_iterate(BitmapHeapIterator *iterator)
+void
+bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result)
 {
 	Assert(iterator);
+	Assert(result);
 
 	if (iterator->serial)
-		return tbm_iterate(iterator->serial);
+		tbm_iterate(iterator->serial, result);
 	else
-		return tbm_shared_iterate(iterator->parallel);
+		tbm_shared_iterate(iterator->parallel, result);
 }
 
 void
@@ -348,7 +349,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
 	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -360,8 +361,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = bhs_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -394,8 +395,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = bhs_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -462,10 +463,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -473,7 +476,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -482,13 +485,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -501,7 +504,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -520,8 +523,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = bhs_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -529,17 +532,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1dc4c99bf9..309a44bdb8 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae..3b432263bb 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index cb56d20dc6..3c330f86e6 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -34,7 +34,7 @@ typedef struct BitmapHeapIterator
 	struct TBMSharedIterator *parallel;
 } BitmapHeapIterator;
 
-extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+extern void bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result);
 
 extern void bhs_end_iterate(BitmapHeapIterator *iterator);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae5296..f000c1af28 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.40.1

v13-0014-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchtext/x-diff; charset=us-asciiDownload
From e1a29efe65346205cc324178d72b01c8c9325d12 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 09:42:23 -0400
Subject: [PATCH v13 14/16] Push BitmapHeapScan prefetch code into heapam.c

In preparation for transitioning to using the streaming read API for
prefetching [1], move all of the BitmapHeapScanState members related to
prefetching and the functions for accessing them into the
HeapScanDescData and TableScanDescData. Members that still need to be
accessed in BitmapHeapNext() could not be moved into heap AM-specific
code. Specifically, parallel iterator setup requires several components
which seem odd to pass to the table AM API.

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  26 ++
 src/backend/access/heap/heapam_handler.c  | 262 +++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 341 ++--------------------
 src/include/access/heapam.h               |  17 ++
 src/include/access/relscan.h              |   8 +
 src/include/access/tableam.h              |  26 +-
 src/include/nodes/execnodes.h             |  14 -
 7 files changed, 355 insertions(+), 339 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 50b4bc1475..263c728543 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -948,8 +948,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+
+	scan->rs_base.blockno = InvalidBlockNumber;
+
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
+	scan->pvmbuffer = InvalidBuffer;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1032,6 +1040,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
+	scan->rs_base.blockno = InvalidBlockNumber;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	/*
 	 * unpin scan buffers
 	 */
@@ -1044,6 +1058,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1069,6 +1089,12 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d9ceb4b848..42d5b749de 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -60,6 +60,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
+static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2186,6 +2189,73 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+static inline void
+BitmapAdjustPrefetchIterator(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	TBMIterateResult tbmpre;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			scan->prefetch_pages--;
+		}
+		else if (prefetch_iterator)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblockno = tbmpre.blockno;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (scan->rs_base.prefetch_maximum > 0)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (prefetch_iterator)
+			{
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblockno = tbmpre.blockno;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  bool *recheck, BlockNumber *blockno,
@@ -2204,6 +2274,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(hscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2344,6 +2416,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->bm_parallel == NULL &&
+		scan->rs_pf_bhs_iterator &&
+		hscan->pfblockno < hscan->rs_base.blockno)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(hscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2354,6 +2438,154 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
+		else
+			scan->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+
+	if (pstate == NULL)
+	{
+		if (prefetch_iterator)
+		{
+			while (scan->prefetch_pages < scan->prefetch_target)
+			{
+				TBMIterateResult tbmpre;
+				bool		skip_fetch;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre.blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		if (prefetch_iterator)
+		{
+			while (1)
+			{
+				TBMIterateResult tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+
+				scan->pfblockno = tbmpre.blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
@@ -2379,6 +2611,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!scan->bm_parallel)
+	{
+		if (hscan->prefetch_target < scan->prefetch_maximum)
+			hscan->prefetch_target++;
+	}
+	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&scan->bm_parallel->mutex);
+		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+			scan->bm_parallel->prefetch_target++;
+		SpinLockRelease(&scan->bm_parallel->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(hscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d61965a276..187b288e68 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
 											 dsa_pointer shared_area,
@@ -122,7 +118,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
@@ -142,7 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
 	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
 	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
 	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
@@ -154,7 +149,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate || init_shared_state)
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		int			pf_maximum = 0;
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
+#endif
+
+		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
@@ -169,23 +173,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * dsa_pointer of the iterator state which will be used by
 				 * multiple processes to iterate jointly.
 				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
-					pstate->prefetch_iterator =
+					node->pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
 				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
+				BitmapDoneInitializingSharedState(node->pstate);
 			}
 		}
 
@@ -216,19 +213,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
+		scan->prefetch_maximum = pf_maximum;
+		scan->bm_parallel = node->pstate;
+
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
 #ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
+		if (scan->prefetch_maximum > 0)
 		{
-			node->pf_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
-												  dsa);
-			/* Only used for serial BHS */
-			node->prefetch_pages = 0;
-			node->prefetch_target = -1;
+			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
+														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
+														 dsa);
 		}
 #endif							/* USE_PREFETCH */
 
@@ -243,36 +240,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
 
 			/*
 			 * If we are using lossy info, we have to recheck the qual
@@ -296,23 +263,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			node->pf_iterator &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -336,219 +289,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -594,22 +334,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->pf_iterator)
-	{
-		bhs_end_iterate(node->pf_iterator);
-		node->pf_iterator = NULL;
-	}
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -648,14 +378,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->pf_iterator)
-		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -688,17 +414,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->pf_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -738,13 +458,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -828,7 +541,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index a527e1b99f..bf212f577f 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -86,6 +86,23 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
+	/*
+	 * These fields only used for prefetching in bitmap table scans
+	 */
+
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
+
+	/*
+	 * These fields only used in serial BHS
+	 */
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block  */
+	BlockNumber pfblockno;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index fb22f305bf..7938b741d6 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -26,6 +26,7 @@
 struct ParallelTableScanDescData;
 
 struct BitmapHeapIterator;
+struct ParallelBitmapHeapState;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -45,6 +46,13 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
+	struct BitmapHeapIterator *rs_pf_bhs_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+	struct ParallelBitmapHeapState *bm_parallel;
+	/* used to validate BHS prefetch and current block stay in sync */
+	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 70e538b76b..a2b229fb87 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -785,17 +785,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the block's representation in the bitmap
 	 * is lossy, otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -945,6 +934,9 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
+	result->rs_pf_bhs_iterator = NULL;
+	result->prefetch_maximum = 0;
+	result->bm_parallel = NULL;
 	return result;
 }
 
@@ -996,6 +988,12 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1012,6 +1010,12 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index cf8b4995f0..592215d5ee 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,18 +1794,11 @@ struct BitmapHeapIterator;
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		pf_iterator        for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1813,18 +1806,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v13-0015-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From 8b0607dbdfbc6d9f05153f9ada673cd11526c9aa Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 15:43:10 -0400
Subject: [PATCH v13 15/16] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block(). Heap AM's implementation of
table_scan_bitmap_next_tuple() now calls the original
heapam_scan_bitmap_next_block() function, but it is no longer an
implementation of a table AM callback but instead a helper for
heapam_scan_bitmap_next_tuple()
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 48 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 45 ++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 75 +++++------------------
 6 files changed, 63 insertions(+), 111 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 263c728543..92f050272b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -319,6 +319,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 42d5b749de..a04774c7dd 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2183,12 +2183,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
- */
-
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
  *
@@ -2222,8 +2216,8 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
@@ -2586,30 +2580,43 @@ BitmapPrefetch(HeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
-		return true;
-	}
+		if (hscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			hscan->rs_empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2990,7 +2997,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 55b8caeadf..0b87530a9c 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -90,8 +90,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 187b288e68..2f9387e51a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -230,44 +230,35 @@ BitmapHeapNext(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 
 		node->initialized = true;
-
-		goto new_page;
 	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346..cf56cc572f 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a2b229fb87..79689ec377 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -773,36 +773,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the block's representation in the bitmap
-	 * is lossy, otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   BlockNumber *blockno,
-										   long *lossy_pages,
-										   long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1981,44 +1965,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented if bitmap is lossy for the selected block and exact_pages is
- * incremented otherwise.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno,
-							 long *lossy_pages, long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   blockno, lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2029,7 +1982,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v13-0016-BitmapHeapScan-uses-read-stream-API.patchtext/x-diff; charset=us-asciiDownload
From b44830bbc4e60ea867b09fa009e2e476e989773f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 16:51:40 -0400
Subject: [PATCH v13 16/16] BitmapHeapScan uses read stream API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the read stream API prefetching. Heap table AM implements a read
stream callback which uses the iterator to get the next valid block that
needs to be fetched for the read stream API.
---
 src/backend/access/heap/heapam.c          |  95 ++++--
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  43 +--
 src/include/access/heapam.h               |  21 +-
 src/include/access/relscan.h              |   6 -
 src/include/access/tableam.h              |  14 -
 src/include/nodes/execnodes.h             |   9 +-
 7 files changed, 115 insertions(+), 420 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 92f050272b..4a74398e54 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -108,6 +108,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_stream_read_next(ReadStream *pgsr, void *pgsr_private,
+											   void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -950,16 +952,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-
-	scan->rs_base.blockno = InvalidBlockNumber;
-
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
-	scan->pvmbuffer = InvalidBuffer;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1014,6 +1008,23 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 
 	initscan(scan, key, false);
 
+	/*
+	 * Make the read stream object for BitmapHeapScan. BitmapHeapScan does not
+	 * use a BufferAccessStrategy, so we could do this before initscan(), but
+	 * wait until after so the scan descriptor is fully set up. On rescan, the
+	 * stream will be reset.
+	 */
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
+
 	return (TableScanDesc) scan;
 }
 
@@ -1042,12 +1053,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
-	scan->rs_base.blockno = InvalidBlockNumber;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
-
 	/*
 	 * unpin scan buffers
 	 */
@@ -1060,11 +1065,8 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_read_stream)
+		read_stream_reset(scan->rs_read_stream);
 
 	/*
 	 * reinitialize scan descriptor
@@ -1091,11 +1093,8 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_read_stream)
+		read_stream_end(scan->rs_read_stream);
 
 	/*
 	 * decrement relation reference count and free scan descriptor storage
@@ -10111,3 +10110,51 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) private_data;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		bhs_iterate(hdesc->rs_base.rs_bhs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(hdesc->rs_base.rs_flags & SO_NEED_TUPLE) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a04774c7dd..77ce10327a 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -60,9 +60,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
-static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
-static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
-static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2183,147 +2180,68 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
-	 * parallel workers.
-	 */
-	if (scan->rs_base.prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno,
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *per_buffer_data;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(hscan);
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2344,7 +2262,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2353,9 +2271,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2405,23 +2323,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->bm_parallel == NULL &&
-		scan->rs_pf_bhs_iterator &&
-		hscan->pfblockno < hscan->rs_base.blockno)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(hscan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2432,153 +2338,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= prefetch_maximum / 2)
-			scan->prefetch_target = prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= prefetch_maximum / 2)
-			pstate->prefetch_target = prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-
-				scan->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
@@ -2613,41 +2372,11 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 			return true;
 		}
 
-		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
 										   lossy_pages, exact_pages))
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!scan->bm_parallel)
-	{
-		if (hscan->prefetch_target < scan->prefetch_maximum)
-			hscan->prefetch_target++;
-	}
-	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&scan->bm_parallel->mutex);
-		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-			scan->bm_parallel->prefetch_target++;
-		SpinLockRelease(&scan->bm_parallel->mutex);
-	}
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(hscan);
-#endif							/* USE_PREFETCH */
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2f9387e51a..f2662ea542 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -131,14 +131,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -149,15 +141,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-		int			pf_maximum = 0;
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
-#endif
-
 		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -174,13 +157,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					node->pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
+
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(node->pstate);
 			}
@@ -213,22 +190,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 																	extra_flags);
 		}
 
-		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
 												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
-#ifdef USE_PREFETCH
-		if (scan->prefetch_maximum > 0)
-		{
-			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
-														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
-														 dsa);
-		}
-#endif							/* USE_PREFETCH */
-
 		node->initialized = true;
 	}
 
@@ -525,14 +492,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -563,11 +526,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index bf212f577f..deccd5c237 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/read_stream.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -76,6 +77,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	ReadStream *rs_read_stream;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -86,23 +90,6 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
-	/*
-	 * These fields only used for prefetching in bitmap table scans
-	 */
-
-	/* buffer for visibility-map lookups of prefetched pages */
-	Buffer		pvmbuffer;
-
-	/*
-	 * These fields only used in serial BHS
-	 */
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
-	/* used to validate prefetch block stays ahead of current block  */
-	BlockNumber pfblockno;
-
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 7938b741d6..02893bf99b 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -46,13 +46,7 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
-	struct BitmapHeapIterator *rs_pf_bhs_iterator;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
-	/* used to validate BHS prefetch and current block stay in sync */
-	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 79689ec377..aead772e6f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -918,8 +918,6 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
-	result->rs_pf_bhs_iterator = NULL;
-	result->prefetch_maximum = 0;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -972,12 +970,6 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -994,12 +986,6 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 592215d5ee..8d86b900a0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1767,11 +1767,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1779,10 +1775,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.40.1

#97Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#96)
19 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/4/24 00:57, Melanie Plageman wrote:

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

On Fri, Mar 29, 2024 at 12:05:15PM +0100, Tomas Vondra wrote:

On 3/29/24 02:12, Thomas Munro wrote:

On Fri, Mar 29, 2024 at 10:43 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

Thanks for the repro. I can't seem to reproduce it (still trying) but
I assume this is with Melanie's v11 patch set which had
v11-0016-v10-Read-Stream-API.patch.

Would you mind removing that commit and instead applying the v13
stream_read.c patches[1]? v10 stream_read.c was a little confused
about random I/O combining, which I fixed with a small adjustment to
the conditions for the "if" statement right at the end of
read_stream_look_ahead(). Sorry about that. The fixed version, with
eic=4, with your test query using WHERE a < a, ends its scan with:

I'll give that a try. Unfortunately unfortunately the v11 still has the
problem I reported about a week ago:

ERROR: prefetch and main iterators are out of sync

So I can't run the full benchmarks :-( but master vs. streaming read API
should work, I think.

Odd, I didn't notice you reporting this ERROR popping up. Now that I
take a look, v11 (at least, maybe also v10) had this very sill mistake:

  if (scan->bm_parallel == NULL &&
      scan->rs_pf_bhs_iterator &&
      hscan->pfblockno > hscan->rs_base.blockno)
       elog(ERROR, "prefetch and main iterators are out of sync");

It errors out if the prefetch block is ahead of the current block --
which is the opposite of what we want. I've fixed this in attached v12.

This version also has v13 of the streaming read API. I noticed one
mistake in my bitmapheap scan streaming read user -- it freed the
streaming read object at the wrong time. I don't know if this was
causing any other issues, but it at least is fixed in this version.

Attached v13 is rebased over master (which includes the streaming read
API now). I also reset the streaming read object on rescan instead of
creating a new one each time.

I don't know how much chance any of this has of going in to 17 now, but
I thought I would start looking into the regression repro Tomas provided
in [1].

My personal opinion is that we should try to get in as many of the the
refactoring patches as possible, but I think it's probably too late for
the actual switch to the streaming API.

If someone else feels like committing that part, I won't stand in the
way, but I'm not quite convinced it won't cause regressions. Maybe it's
OK but I'd need more time to do more tests, collect data, and so on. And
I don't think we have that, especially considering we'd still need to
commit the other parts first.

I'm also not sure if I should try and group the commits into fewer
commits now or wait until I have some idea of whether or not the
approach in 0013 and 0014 is worth pursuing.

You mean whether to pursue the approach in general, or for v17? I think
it looks like the right approach, but for v17 see above :-(

As for merging, I wouldn't do that. I looked at the commits and while
some of them seem somewhat "trivial", I really like how you organized
the commits, and kept those that just "move" code around, and those that
actually change stuff. It's much easier to understand, IMO.

I went through the first ~10 commits, and added some review - either as
a separate commit, when possible, in the code as XXX comment, and also
in the commit message. The code tweaks are utterly trivial (whitespace
or indentation to make the line shorter). It shouldn't take much time to
deal with those, I think.

I think the main focus should be updating the commit messages. If it was
only a single patch, I'd probably try to write the messages myself, but
with this many patches it'd be great if you could update those and I'll
review that before commit.

I always struggle with writing commit messages myself, and it takes me
ages to write a good one (well, I think the message is good, but who
knows ...). But I think a good message should be concise enough to
explain what and why it's done. It may reference a thread for all the
gory details, but the basic reasoning should be in the commit message.
For example the message for "BitmapPrefetch use prefetch block recheck
for skip fetch" now says that it "makes more sense to do X" but does not
really say why that's the case. The linked message does, but it'd be
good to have that in the message (because how would I know how much of
the thread to read?).

Also, it'd be very helpful if you could update the author & reviewed-by
fields. I'll review those before commit, ofc, but I admit I lost track
of who reviewed which part.

I'd focus on the first ~8-9 commits or so for now, we can commit more if
things go reasonably well.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

v14-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-patch; charset=UTF-8; name=v14-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchDownload
From 8d42c0e61cda5f7a8b574fc6a775bec84370ba26 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v14 01/19] BitmapHeapScan begin scan after bitmap creation

There is no reason for a BitmapHeapScan to begin the scan of the
underlying table in ExecInitBitmapHeapScan(). Instead, do so after
completing the index scan and building the bitmap.
---
 src/backend/access/table/tableam.c        |  1 -
 src/backend/executor/nodeBitmapHeapscan.c | 26 +++++++++++++++++------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 805d222cebc..b0f61c65f36 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,7 +120,6 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
-
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aabe..93fdcd226bf 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
+																	node->ss.ss_currentRelation,
+																	node->ss.ps.state->es_snapshot,
+																	0,
+																	NULL);
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +615,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +693,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +800,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.44.0

v14-0002-review.patchtext/x-patch; charset=UTF-8; name=v14-0002-review.patchDownload
From d2160a9958f8185ab4803e9e778b370a6a6dde32 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:15:18 +0200
Subject: [PATCH v14 02/19] review

so is this an optimization, bugfix, or what? what difference does
it make in practice? or is it just cosmetic change?

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/table/tableam.c        |  1 +
 src/backend/executor/nodeBitmapHeapscan.c | 11 ++++++-----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index b0f61c65f36..805d222cebc 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -120,6 +120,7 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 											NULL, flags);
 }
 
+
 /* ----------------------------------------------------------------------------
  * Parallel table scan related functions.
  * ----------------------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 93fdcd226bf..c8c466e3c5c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -185,11 +185,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
-			scan = node->ss.ss_currentScanDesc = table_beginscan_bm(
-																	node->ss.ss_currentRelation,
-																	node->ss.ps.state->es_snapshot,
-																	0,
-																	NULL);
+			scan = table_beginscan_bm(node->ss.ss_currentRelation,
+									  node->ss.ps.state->es_snapshot,
+									  0,
+									  NULL);
+
+			node->ss.ss_currentScanDesc = scan;
 		}
 
 		node->initialized = true;
-- 
2.44.0

v14-0003-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-patch; charset=UTF-8; name=v14-0003-BitmapHeapScan-set-can_skip_fetch-later.patchDownload
From ee72a2b5c846408ba9549d9d4c8b6d419fe3c311 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v14 03/19] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() when
!BitmapHeapScanState->initialized instead of in
ExecInitBitmapHeapScan(). This is a preliminary step to removing
can_skip_fetch from BitmapHeapScanState and setting it in table AM
specific code.

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c8c466e3c5c..2148a21531a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -743,16 +753,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.44.0

v14-0004-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-patch; charset=UTF-8; name=v14-0004-Push-BitmapHeapScan-skip-fetch-optimization-into.patchDownload
From ee62f42859a69cab1039155e2f15d0239a3f3dc1 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:34:25 +0200
Subject: [PATCH v14 04/19] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block and implement it for the heap
table AM by moving the vmbuffer and other fields needed for the
optimization from the BitmapHeapScanState into the HeapScanDescData.
heapam_scan_bitmap_next_block() now decides whether or not to skip
fetching the block before reading it in and
heapam_scan_bitmap_next_tuple() returns NULL-filled tuples for skipped
blocks.

The layering violation is still present in BitmapHeapScans's prefetching
code. However, this will be eliminated when prefetching is implemented
using the upcoming streaming read API discussed in [1].

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index dada2ecd1e3..10f2faaa60b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -967,6 +967,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1055,6 +1057,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1074,6 +1082,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3e7a6b5548b..929b2cf8e71 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2198,6 +2199,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2310,6 +2329,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2148a21531a..a8bc5dec53d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,10 +185,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
 									  0,
-									  NULL);
+									  NULL,
+									  extra_flags);
 
 			node->ss.ss_currentScanDesc = scan;
 		}
@@ -208,7 +212,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -229,37 +233,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -302,52 +283,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -519,7 +481,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -570,7 +532,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -640,8 +602,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -651,7 +611,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -696,8 +655,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -741,8 +698,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -753,7 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2765efc4e5e..750ea30852e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,6 +76,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e7eeb754098..55f11397576 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -63,6 +63,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -937,9 +944,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e7ff8e4992f..4880f346bf1 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,10 +1794,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1817,9 +1814,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.44.0

v14-0005-BitmapPrefetch-use-prefetch-block-recheck-for-sk.patchtext/x-patch; charset=UTF-8; name=v14-0005-BitmapPrefetch-use-prefetch-block-recheck-for-sk.patchDownload
From e3fa2f25b5631bb9a5e27515be8161ef89418c40 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v14 05/19] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. It makes more sense for it to use the
recheck flag from the TBMIterateResult for the prefetch block instead.
See this [1] thread on hackers reporting the issue.

XXX I think this commit message should "distill" the reasoning from [1]
to justify why this "makes more sense". The details can be left to the
thread, but the basics should be in this message I think.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a8bc5dec53d..2e2cec8b3b5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -475,14 +475,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -533,7 +528,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.44.0

v14-0006-Update-BitmapAdjustPrefetchIterator-parameter-ty.patchtext/x-patch; charset=UTF-8; name=v14-0006-Update-BitmapAdjustPrefetchIterator-parameter-ty.patchDownload
From 9b66215da19d8b6dc1e135204d9b427eb47c99d5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v14 06/19] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.

Author: Melanie Plageman
Reviewed-by: ???????
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2e2cec8b3b5..795a893035d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -231,7 +231,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -342,7 +342,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -361,7 +361,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.44.0

v14-0007-table_scan_bitmap_next_block-returns-lossy-or-ex.patchtext/x-patch; charset=UTF-8; name=v14-0007-table_scan_bitmap_next_block-returns-lossy-or-ex.patchDownload
From 742490b1d4ef3b41eaece6b9fc0475d52b60ca39 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v14 07/19] table_scan_bitmap_next_block() returns lossy or
 exact

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So, the table AM must inform
BitmapHeapNext() whether or not the current block is lossy or exact for
the purposes of the counters used in EXPLAIN.
---
 src/backend/access/heap/heapam_handler.c  |  5 ++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/include/access/tableam.h              | 14 ++++++++++----
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 929b2cf8e71..a511bbfa88d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  bool *lossy)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2316,6 +2317,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	*lossy = tbmres->ntuples < 0;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 795a893035d..56943b211fa 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,7 +212,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
+		bool		valid, lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -233,12 +233,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
+			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
 
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
+			if (lossy)
 				node->lossy_pages++;
+			else
+				node->exact_pages++;
 
 			if (!valid)
 			{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 55f11397576..75c5ee956db 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,6 +789,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy indicates whether or not the block's representation in the bitmap
+	 * is lossy or exact.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -804,7 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   bool *lossy);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1971,14 +1975,16 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
  * a bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy is set to true if bitmap is lossy for the
+ * selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 bool *lossy)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1989,7 +1995,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres, lossy);
 }
 
 /*
-- 
2.44.0

v14-0008-review.patchtext/x-patch; charset=UTF-8; name=v14-0008-review.patchDownload
From ae9308ef69e04e1231bfd718c59482320cc9dde3 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:51:03 +0200
Subject: [PATCH v14 08/19] review

I wonder if returning "exact" instead of lossy would be better, for the
silly reason that the if branching in BitmapHeapNext would be the same.
---
 src/backend/executor/nodeBitmapHeapscan.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 56943b211fa..9b2034c2f83 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,7 +212,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid, lossy;
+		bool		valid,
+					lossy;
 
 		CHECK_FOR_INTERRUPTS();
 
-- 
2.44.0

v14-0009-Reduce-scope-of-BitmapHeapScan-tbmiterator-local.patchtext/x-patch; charset=UTF-8; name=v14-0009-Reduce-scope-of-BitmapHeapScan-tbmiterator-local.patchDownload
From 597254156f86cb57bb0340b68d52e8a3aa7d981e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v14 09/19] Reduce scope of BitmapHeapScan tbmiterator local
 variables

To simplify the diff of a future commit which will move the TBMIterators
into the scan descriptor, define them in a narrower scope now.
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 9b2034c2f83..cf778f61d52 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -207,6 +203,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -223,9 +221,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.44.0

v14-0010-review.patchtext/x-patch; charset=UTF-8; name=v14-0010-review.patchDownload
From 7e4e7dfcc334198b83ccc86d15dc6aa6f8189a36 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:58:57 +0200
Subject: [PATCH v14 10/19] review

---
 src/backend/executor/nodeBitmapHeapscan.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cf778f61d52..6787547b9ff 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -99,6 +99,10 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * XXX why don't we assign directly to the node-> fields? Then we
+		 * would not need these local variables at all.
+		 */
 		TBMIterator *tbmiterator = NULL;
 		TBMSharedIterator *shared_tbmiterator = NULL;
 
-- 
2.44.0

v14-0011-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-patch; charset=UTF-8; name=v14-0011-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchDownload
From 3fb2c24d79f8cdc8e33007697db362ad5b50b4fc Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v14 11/19] Remove table_scan_bitmap_next_tuple parameter
 tbmres

With the addition of the proposed streaming read API [1],
table_scan_bitmap_next_block() will no longer take a TBMIterateResult as
an input. Instead table AMs will be responsible for implementing a
callback for the streaming read API which specifies which blocks should
be prefetched and read.

Thus, it no longer makes sense to use the TBMIterateResult as a means of
communication between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

XXX Does it make sense to merge this without the switch to the new API?
Imagine an AM chose to do the work in table_scan_bitmap_next_tuple. Now
it would have to do that in the other callback. Is that OK, or would it
make it harder/less efficient? Ultimately the AM will have to do that
anyway, so maybe it doesn't mattter.

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a511bbfa88d..02bab2e93f4 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2324,7 +2324,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6787547b9ff..14a5af30087 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -292,7 +292,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 75c5ee956db..1b545f2b678 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,10 +780,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -814,15 +811,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2008,7 +2000,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2020,7 +2011,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.44.0

v14-0012-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-patch; charset=UTF-8; name=v14-0012-Make-table_scan_bitmap_next_block-async-friendly.patchDownload
From 7dff0fdde3016536244a78efe0803ddcb9fdb8ee Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 16:05:04 +0200
Subject: [PATCH v14 12/19] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to
the table AM.

These changes will enable bitmapheapscan to use the future streaming
read API [1]. Table AMs will implement a streaming read API callback
returning the next block to fetch. In heap AM's case, the callback will
use the iterator to identify the next block to fetch. Since choosing the
next block will no longer the responsibility of BitmapHeapNext(), the
streaming read control flow requires these changes to
table_scan_bitmap_next_block().

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  59 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 199 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 195 insertions(+), 150 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 02bab2e93f4..eea3b7f149e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,18 +2188,51 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
-							  bool *lossy)
+							  bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2218,16 +2251,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2319,7 +2343,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 	*lossy = tbmres->ntuples < 0;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 14a5af30087..5f987b40ede 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -70,8 +69,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
+	bool		lossy;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +82,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -115,7 +113,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -168,7 +165,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -207,56 +203,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		bool		valid,
-					lossy;
-
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			valid = table_scan_bitmap_next_block(scan, tbmres, &lossy);
-
-			if (lossy)
-				node->lossy_pages++;
-			else
-				node->exact_pages++;
-
-			if (!valid)
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -278,45 +237,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+			break;
+
+		if (lossy)
+			node->lossy_pages++;
+		else
+			node->exact_pages++;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -342,13 +316,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -362,14 +340,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -394,7 +375,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -472,6 +456,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -529,6 +514,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -590,12 +577,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -603,13 +586,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -640,28 +623,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -694,8 +673,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -703,9 +680,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1b545f2b678..74ddd5d66d3 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -773,19 +774,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy indicates whether or not the block's representation in the bitmap
 	 * is lossy or exact.
 	 *
@@ -804,8 +800,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
-										   bool *lossy);
+										   bool *recheck, bool *lossy,
+										   BlockNumber *blockno);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -942,9 +938,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -991,6 +991,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1001,6 +1016,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1964,19 +1994,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy is set to true if bitmap is lossy for the
- * selected block and false otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy is set to true
+ * if bitmap is lossy for the selected block and false otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
-							 bool *lossy)
+							 bool *recheck, bool *lossy, BlockNumber *blockno)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1986,8 +2014,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres, lossy);
+	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
+														   lossy, blockno);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 4880f346bf1..8e344155679 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.44.0

v14-0013-Unify-parallel-and-serial-BitmapHeapScan-iterato.patchtext/x-patch; charset=UTF-8; name=v14-0013-Unify-parallel-and-serial-BitmapHeapScan-iterato.patchDownload
From 53362e02e069747a413aa11cf25df918a94b1cc1 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 16:05:53 +0200
Subject: [PATCH v14 13/19] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to both
TBMIterator and TBMSharedIterators. This encapsulates the parallel and serial
iterators and their access and makes the bitmap heap scan code a bit cleaner.
This naturally lends itself to a bit of reorganization of the
!node->initialized path in BitmapHeapNext(). Now, on the first scan, the the
iterator is created after the scan descriptor is created.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 163 ++++++++++++----------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  29 +---
 src/include/executor/nodeBitmapHeapscan.h |  10 ++
 src/include/nodes/execnodes.h             |   8 +-
 src/tools/pgindent/typedefs.list          |   1 +
 7 files changed, 114 insertions(+), 109 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index eea3b7f149e..e086cbd2cfd 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2207,10 +2207,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		tbmres = bhs_iterate(scan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5f987b40ede..a1f9acc2cfb 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -56,6 +56,56 @@ static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
+static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
+											 dsa_pointer shared_area,
+											 dsa_area *personal_area);
+
+BitmapHeapIterator *
+bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_area)
+{
+	BitmapHeapIterator *result = palloc(sizeof(BitmapHeapIterator));
+
+	result->serial = NULL;
+	result->parallel = NULL;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(shared_area))
+		result->parallel = tbm_attach_shared_iterate(personal_area, shared_area);
+	else
+		result->serial = tbm_begin_iterate(tbm);
+
+	return result;
+}
+
+TBMIterateResult *
+bhs_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		return tbm_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
+
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+	{
+		tbm_end_iterate(iterator->serial);
+		iterator->serial = NULL;
+	}
+	else
+	{
+		tbm_end_shared_iterate(iterator->parallel);
+		iterator->parallel = NULL;
+	}
+
+	pfree(iterator);
+}
 
 
 /* ----------------------------------------------------------------
@@ -98,46 +148,22 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	if (!node->initialized)
 	{
 		/*
-		 * XXX why don't we assign directly to the node-> fields? Then we
-		 * would not need these local variables at all.
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
 		 */
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate)
+		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
+			if (init_shared_state)
 			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
@@ -158,21 +184,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
 			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -203,8 +217,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  dsa);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			node->pf_iterator = bhs_begin_iterate(tbm,
+												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
+												  dsa);
+			/* Only used for serial BHS */
+			node->prefetch_pages = 0;
+			node->prefetch_target = -1;
+		}
+#endif							/* USE_PREFETCH */
 
 		node->initialized = true;
 
@@ -285,7 +312,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			node->pf_iterator &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -326,12 +353,11 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
@@ -340,7 +366,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = bhs_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -353,8 +379,6 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -376,7 +400,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -436,23 +460,22 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 				node->prefetch_pages++;
@@ -480,8 +503,6 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		if (prefetch_iterator)
 		{
 			while (1)
@@ -505,12 +526,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
+					node->pf_iterator = NULL;
 					break;
 				}
 
@@ -577,18 +598,17 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	if (node->pf_iterator)
+	{
+		bhs_end_iterate(node->pf_iterator);
+		node->pf_iterator = NULL;
+	}
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -633,12 +653,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+	if (node->pf_iterator)
+		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -676,11 +694,10 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
+	scanstate->pf_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc7..fb22f305bf6 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,12 +20,12 @@
 #include "storage/buf.h"
 #include "storage/spin.h"
 #include "utils/relcache.h"
+#include "executor/nodeBitmapHeapscan.h"
 
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
-struct TBMSharedIterator;
+struct BitmapHeapIterator;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -44,8 +44,7 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	struct BitmapHeapIterator *rs_bhs_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 74ddd5d66d3..d4fbf0d889b 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -942,8 +942,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
+	result->rs_bhs_iterator = NULL;
 	return result;
 }
 
@@ -993,17 +992,8 @@ table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1018,17 +1008,8 @@ table_rescan(TableScanDesc scan,
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		bhs_end_iterate(scan->rs_bhs_iterator);
+		scan->rs_bhs_iterator = NULL;
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index ea003a9caae..cb56d20dc6f 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -28,5 +28,15 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 										  ParallelContext *pcxt);
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+} BitmapHeapIterator;
+
+extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
+
 
 #endif							/* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8e344155679..cf8b4995f0d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1787,6 +1787,8 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
+struct BitmapHeapIterator;
+
 /* ----------------
  *	 BitmapHeapScanState information
  *
@@ -1795,12 +1797,11 @@ typedef struct ParallelBitmapHeapState
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
+ *		pf_iterator        for prefetching ahead of current page
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1815,12 +1816,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index b98e330e3ed..bcee567b65b 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.44.0

v14-0014-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-patch; charset=UTF-8; name=v14-0014-table_scan_bitmap_next_block-counts-lossy-and-ex.patchDownload
From f1290c0c5127abc0755a5ead9d1d77549bd01cc7 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 17:09:12 -0400
Subject: [PATCH v14 14/19] table_scan_bitmap_next_block counts lossy and exact
 pages

Now that the table_scan_bitmap_next_block() callback only returns false
when the bitmap is exhausted, it is simpler to move the management of
the lossy and exact page counters into it. We will eventually remove
this callback and table_scan_bitmap_next_tuple() will update those
counters when a new block is read in.
---
 src/backend/access/heap/heapam_handler.c  |  8 ++++++--
 src/backend/executor/nodeBitmapHeapscan.c |  9 ++-------
 src/include/access/tableam.h              | 21 +++++++++++++--------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e086cbd2cfd..fe31b0efee4 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, bool *lossy, BlockNumber *blockno)
+							  bool *recheck, BlockNumber *blockno,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block;
@@ -2338,7 +2339,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	*lossy = tbmres->ntuples < 0;
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a1f9acc2cfb..261e00849a7 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -119,7 +119,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	bool		lossy;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -299,14 +298,10 @@ new_page:
 
 		BitmapAdjustPrefetchIterator(node);
 
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &lossy, &node->blockno))
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+										  &node->lossy_pages, &node->exact_pages))
 			break;
 
-		if (lossy)
-			node->lossy_pages++;
-		else
-			node->exact_pages++;
-
 		/*
 		 * If serial, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d4fbf0d889b..70e538b76ba 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -782,8 +782,8 @@ typedef struct TableAmRoutine
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * lossy indicates whether or not the block's representation in the bitmap
-	 * is lossy or exact.
+	 * lossy_pages is incremented if the block's representation in the bitmap
+	 * is lossy, otherwise, exact_pages is incremented.
 	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
@@ -800,8 +800,10 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck, bool *lossy,
-										   BlockNumber *blockno);
+										   bool *recheck,
+										   BlockNumber *blockno,
+										   long *lossy_pages,
+										   long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1977,15 +1979,17 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap table scan.
  * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy is set to true
- * if bitmap is lossy for the selected block and false otherwise.
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented if bitmap is lossy for the selected block and exact_pages is
+ * incremented otherwise.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, bool *lossy, BlockNumber *blockno)
+							 bool *recheck, BlockNumber *blockno,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1996,7 +2000,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   lossy, blockno);
+														   blockno, lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.44.0

v14-0015-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-patch; charset=UTF-8; name=v14-0015-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From 0e379ec9ce12ecc1fc1b9b0d93ea99a174a63966 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 20:13:43 -0500
Subject: [PATCH v14 15/19] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 33 +++++++--------------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 28 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..1dc4c99bf99 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -692,12 +683,7 @@ tbm_begin_iterate(TIDBitmap *tbm)
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
-	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1463,12 +1449,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	TBMSharedIterator *iterator;
 	TBMSharedIteratorState *istate;
 
-	/*
-	 * Create the TBMSharedIterator struct, with enough trailing space to
-	 * serve the needs of the TBMIterateResult sub-struct.
-	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..432fae52962 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.44.0

v14-0016-Separate-TBM-Shared-Iterator-and-TBMIterateResul.patchtext/x-patch; charset=UTF-8; name=v14-0016-Separate-TBM-Shared-Iterator-and-TBMIterateResul.patchDownload
From 99f4982bc9f861f080b2aa71caf92169b5c21334 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 15 Feb 2024 21:23:41 -0500
Subject: [PATCH v14 16/19] Separate TBM[Shared]Iterator and TBMIterateResult

Remove the TBMIterateResult from the TBMIterator and TBMSharedIterator
and have tbm_[shared_]iterate() take a TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching, for example.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 48 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 30 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 47 ++++++++-------
 src/backend/nodes/tidbitmap.c             | 73 ++++++++++++-----------
 src/include/access/gin_private.h          |  2 +-
 src/include/executor/nodeBitmapHeapscan.h |  2 +-
 src/include/nodes/tidbitmap.h             |  4 +-
 8 files changed, 113 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..3aa457a29e1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +836,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_iterate() sets matchResult->blockno to
+			 * InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				tbm_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_iterate(entry->matchIterator);
@@ -858,10 +872,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +889,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..033d5253394 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index fe31b0efee4..ec16d8c5e3c 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2196,7 +2196,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
@@ -2208,9 +2208,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = bhs_iterate(scan->rs_bhs_iterator);
+		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 		{
 			/* no more entries in the bitmap */
 			Assert(hscan->rs_empty_tuples_pending == 0);
@@ -2225,11 +2225,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2237,19 +2237,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(hscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2278,7 +2278,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2287,9 +2287,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2339,7 +2339,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 261e00849a7..1086e20234b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -77,15 +77,16 @@ bhs_begin_iterate(TIDBitmap *tbm, dsa_pointer shared_area, dsa_area *personal_ar
 	return result;
 }
 
-TBMIterateResult *
-bhs_iterate(BitmapHeapIterator *iterator)
+void
+bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result)
 {
 	Assert(iterator);
+	Assert(result);
 
 	if (iterator->serial)
-		return tbm_iterate(iterator->serial);
+		tbm_iterate(iterator->serial, result);
 	else
-		return tbm_shared_iterate(iterator->parallel);
+		tbm_shared_iterate(iterator->parallel, result);
 }
 
 void
@@ -349,7 +350,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
 	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -361,8 +362,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = bhs_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			node->pfblockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -395,8 +396,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (prefetch_iterator)
 			{
-				tbmpre = bhs_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				node->pfblockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -463,10 +464,12 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -474,7 +477,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -483,13 +486,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -502,7 +505,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -521,8 +524,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = bhs_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					bhs_end_iterate(prefetch_iterator);
@@ -530,17 +533,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				node->pfblockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1dc4c99bf99..309a44bdb84 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -944,20 +942,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -985,6 +984,7 @@ tbm_iterate(TBMIterator *iterator)
 	 * If both chunk and per-page data remain, must output the numerically
 	 * earlier page.
 	 */
+	Assert(tbmres);
 	if (iterator->schunkptr < tbm->nchunks)
 	{
 		PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
@@ -995,11 +995,11 @@ tbm_iterate(TBMIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1015,16 +1015,17 @@ tbm_iterate(TBMIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
@@ -1034,10 +1035,9 @@ tbm_iterate(TBMIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1088,13 +1088,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1104,21 +1104,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return;
 }
 
 /*
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..3b432263bb0 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index cb56d20dc6f..3c330f86e62 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -34,7 +34,7 @@ typedef struct BitmapHeapIterator
 	struct TBMSharedIterator *parallel;
 } BitmapHeapIterator;
 
-extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+extern void bhs_iterate(BitmapHeapIterator *iterator, TBMIterateResult *result);
 
 extern void bhs_end_iterate(BitmapHeapIterator *iterator);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 432fae52962..f000c1af28f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -72,8 +72,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_iterate(TBMIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
-- 
2.44.0

v14-0017-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchtext/x-patch; charset=UTF-8; name=v14-0017-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchDownload
From 8f271b04d9108b2c36b30141d807ef4976d59526 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 09:42:23 -0400
Subject: [PATCH v14 17/19] Push BitmapHeapScan prefetch code into heapam.c

In preparation for transitioning to using the streaming read API for
prefetching [1], move all of the BitmapHeapScanState members related to
prefetching and the functions for accessing them into the
HeapScanDescData and TableScanDescData. Members that still need to be
accessed in BitmapHeapNext() could not be moved into heap AM-specific
code. Specifically, parallel iterator setup requires several components
which seem odd to pass to the table AM API.

[1] https://www.postgresql.org/message-id/flat/CA%2BhUKGJkOiOCa%2Bmag4BF%2BzHo7qo%3Do9CFheB8%3Dg6uT5TUm2gkvA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  26 ++
 src/backend/access/heap/heapam_handler.c  | 262 +++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 341 ++--------------------
 src/include/access/heapam.h               |  17 ++
 src/include/access/relscan.h              |   8 +
 src/include/access/tableam.h              |  26 +-
 src/include/nodes/execnodes.h             |  14 -
 7 files changed, 355 insertions(+), 339 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 10f2faaa60b..bda6abb8d0c 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -967,8 +967,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+
+	scan->rs_base.blockno = InvalidBlockNumber;
+
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
+	scan->pvmbuffer = InvalidBuffer;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1051,6 +1059,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
+	scan->rs_base.blockno = InvalidBlockNumber;
+
+	scan->pfblockno = InvalidBlockNumber;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	/*
 	 * unpin scan buffers
 	 */
@@ -1063,6 +1077,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1088,6 +1108,12 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ec16d8c5e3c..0138a23e9d4 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -60,6 +60,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
+static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2186,6 +2189,73 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+static inline void
+BitmapAdjustPrefetchIterator(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	TBMIterateResult tbmpre;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			scan->prefetch_pages--;
+		}
+		else if (prefetch_iterator)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			bhs_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblockno = tbmpre.blockno;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (scan->rs_base.prefetch_maximum > 0)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (prefetch_iterator)
+			{
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblockno = tbmpre.blockno;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  bool *recheck, BlockNumber *blockno,
@@ -2204,6 +2274,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(hscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2344,6 +2416,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->bm_parallel == NULL &&
+		scan->rs_pf_bhs_iterator &&
+		hscan->pfblockno < hscan->rs_base.blockno)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(hscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2354,6 +2438,154 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
+		else
+			scan->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
+	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
+
+	if (pstate == NULL)
+	{
+		if (prefetch_iterator)
+		{
+			while (scan->prefetch_pages < scan->prefetch_target)
+			{
+				TBMIterateResult tbmpre;
+				bool		skip_fetch;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre.blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		if (prefetch_iterator)
+		{
+			while (1)
+			{
+				TBMIterateResult tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				bhs_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					scan->rs_base.rs_pf_bhs_iterator = NULL;
+					break;
+				}
+
+				scan->pfblockno = tbmpre.blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre.recheck &&
+							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
+											 tbmpre.blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
@@ -2379,6 +2611,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!scan->bm_parallel)
+	{
+		if (hscan->prefetch_target < scan->prefetch_maximum)
+			hscan->prefetch_target++;
+	}
+	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&scan->bm_parallel->mutex);
+		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
+			scan->bm_parallel->prefetch_target++;
+		SpinLockRelease(&scan->bm_parallel->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(hscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 1086e20234b..ea309cf93e3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 static BitmapHeapIterator *bhs_begin_iterate(TIDBitmap *tbm,
 											 dsa_pointer shared_area,
@@ -122,7 +118,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
@@ -142,7 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
 	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
 	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
 	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
@@ -154,7 +149,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate || init_shared_state)
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		int			pf_maximum = 0;
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
+#endif
+
+		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
@@ -169,23 +173,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * dsa_pointer of the iterator state which will be used by
 				 * multiple processes to iterate jointly.
 				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
-					pstate->prefetch_iterator =
+					node->pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
 				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
+				BitmapDoneInitializingSharedState(node->pstate);
 			}
 		}
 
@@ -217,19 +214,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		scan->prefetch_maximum = pf_maximum;
+		scan->bm_parallel = node->pstate;
+
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->tbmiterator : InvalidDsaPointer,
+												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
 #ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
+		if (scan->prefetch_maximum > 0)
 		{
-			node->pf_iterator = bhs_begin_iterate(tbm,
-												  pstate ? pstate->prefetch_iterator : InvalidDsaPointer,
-												  dsa);
-			/* Only used for serial BHS */
-			node->prefetch_pages = 0;
-			node->prefetch_target = -1;
+			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
+														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
+														 dsa);
 		}
 #endif							/* USE_PREFETCH */
 
@@ -244,36 +241,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
 
 			/*
 			 * If we are using lossy info, we have to recheck the qual
@@ -297,23 +264,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			node->pf_iterator &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -337,219 +290,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			node->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				node->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = node->pf_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					node->pf_iterator = NULL;
-					break;
-				}
-
-				node->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -595,22 +335,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->pf_iterator)
-	{
-		bhs_end_iterate(node->pf_iterator);
-		node->pf_iterator = NULL;
-	}
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -649,14 +379,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (node->pf_iterator)
-		bhs_end_iterate(node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -689,17 +415,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->pf_iterator = NULL;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -739,13 +459,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -829,7 +542,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 750ea30852e..2e262bf4354 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -86,6 +86,23 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
+	/*
+	 * These fields only used for prefetching in bitmap table scans
+	 */
+
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
+
+	/*
+	 * These fields only used in serial BHS
+	 */
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block  */
+	BlockNumber pfblockno;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index fb22f305bf6..7938b741d66 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -26,6 +26,7 @@
 struct ParallelTableScanDescData;
 
 struct BitmapHeapIterator;
+struct ParallelBitmapHeapState;
 
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
@@ -45,6 +46,13 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
+	struct BitmapHeapIterator *rs_pf_bhs_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+	struct ParallelBitmapHeapState *bm_parallel;
+	/* used to validate BHS prefetch and current block stay in sync */
+	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 70e538b76ba..a2b229fb877 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -785,17 +785,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the block's representation in the bitmap
 	 * is lossy, otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -945,6 +934,9 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
+	result->rs_pf_bhs_iterator = NULL;
+	result->prefetch_maximum = 0;
+	result->bm_parallel = NULL;
 	return result;
 }
 
@@ -996,6 +988,12 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1012,6 +1010,12 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
+
+		if (scan->rs_pf_bhs_iterator)
+		{
+			bhs_end_iterate(scan->rs_pf_bhs_iterator);
+			scan->rs_pf_bhs_iterator = NULL;
+		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index cf8b4995f0d..592215d5ee7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,18 +1794,11 @@ struct BitmapHeapIterator;
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		pf_iterator        for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1813,18 +1806,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	struct BitmapHeapIterator *pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.44.0

v14-0018-Remove-table_scan_bitmap_next_block.patchtext/x-patch; charset=UTF-8; name=v14-0018-Remove-table_scan_bitmap_next_block.patchDownload
From 8076d43ea02fa6d5bc137ce3721846a3dc492b72 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 15:43:10 -0400
Subject: [PATCH v14 18/19] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block(). Heap AM's implementation of
table_scan_bitmap_next_tuple() now calls the original
heapam_scan_bitmap_next_block() function, but it is no longer an
implementation of a table AM callback but instead a helper for
heapam_scan_bitmap_next_tuple()
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 48 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 45 ++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 75 +++++------------------
 6 files changed, 63 insertions(+), 111 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index bda6abb8d0c..6c575ffc168 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -324,6 +324,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 0138a23e9d4..3e92725a821 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2183,12 +2183,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
- */
-
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
  *
@@ -2222,8 +2216,8 @@ BitmapAdjustPrefetchIterator(HeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->rs_base.prefetch_maximum > 0)
 	{
@@ -2586,30 +2580,43 @@ BitmapPrefetch(HeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
-		return true;
-	}
+		if (hscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			hscan->rs_empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -3006,7 +3013,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 55b8caeadf2..0b87530a9c4 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -90,8 +90,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index ea309cf93e3..7f651004113 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -231,44 +231,35 @@ BitmapHeapNext(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 
 		node->initialized = true;
-
-		goto new_page;
 	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck, &scan->blockno,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346f..cf56cc572fe 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a2b229fb877..79689ec3773 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -773,36 +773,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the block's representation in the bitmap
-	 * is lossy, otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   BlockNumber *blockno,
-										   long *lossy_pages,
-										   long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1981,44 +1965,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented if bitmap is lossy for the selected block and exact_pages is
- * incremented otherwise.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck, BlockNumber *blockno,
-							 long *lossy_pages, long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, recheck,
-														   blockno, lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2029,7 +1982,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.44.0

v14-0019-BitmapHeapScan-uses-read-stream-API.patchtext/x-patch; charset=UTF-8; name=v14-0019-BitmapHeapScan-uses-read-stream-API.patchDownload
From 9a98aa4c74d301500d5d3ce9b0ddf46360167a41 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 16:51:40 -0400
Subject: [PATCH v14 19/19] BitmapHeapScan uses read stream API

Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the read stream API prefetching. Heap table AM implements a read
stream callback which uses the iterator to get the next valid block that
needs to be fetched for the read stream API.
---
 src/backend/access/heap/heapam.c          |  95 ++++--
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  43 +--
 src/include/access/heapam.h               |  21 +-
 src/include/access/relscan.h              |   6 -
 src/include/access/tableam.h              |  14 -
 src/include/nodes/execnodes.h             |   9 +-
 7 files changed, 115 insertions(+), 420 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 6c575ffc168..b0af15eb9c0 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -113,6 +113,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
 static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
 										bool *copy);
 
+static BlockNumber bitmapheap_stream_read_next(ReadStream *pgsr, void *pgsr_private,
+											   void *per_buffer_data);
 
 /*
  * Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -969,16 +971,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-
-	scan->rs_base.blockno = InvalidBlockNumber;
-
 	scan->rs_vmbuffer = InvalidBuffer;
 	scan->rs_empty_tuples_pending = 0;
-	scan->pvmbuffer = InvalidBuffer;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1033,6 +1027,23 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 
 	initscan(scan, key, false);
 
+	/*
+	 * Make the read stream object for BitmapHeapScan. BitmapHeapScan does not
+	 * use a BufferAccessStrategy, so we could do this before initscan(), but
+	 * wait until after so the scan descriptor is fully set up. On rescan, the
+	 * stream will be reset.
+	 */
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
+
 	return (TableScanDesc) scan;
 }
 
@@ -1061,12 +1072,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
 	}
 
-	scan->rs_base.blockno = InvalidBlockNumber;
-
-	scan->pfblockno = InvalidBlockNumber;
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
-
 	/*
 	 * unpin scan buffers
 	 */
@@ -1079,11 +1084,8 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_read_stream)
+		read_stream_reset(scan->rs_read_stream);
 
 	/*
 	 * reinitialize scan descriptor
@@ -1110,11 +1112,8 @@ heap_endscan(TableScanDesc sscan)
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->pvmbuffer))
-	{
-		ReleaseBuffer(scan->pvmbuffer);
-		scan->pvmbuffer = InvalidBuffer;
-	}
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_read_stream)
+		read_stream_end(scan->rs_read_stream);
 
 	/*
 	 * decrement relation reference count and free scan descriptor storage
@@ -10130,3 +10129,51 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
 
 	CheckForSerializableConflictOut(relation, xid, snapshot);
 }
+
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	HeapScanDesc hdesc = (HeapScanDesc) private_data;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		bhs_iterate(hdesc->rs_base.rs_bhs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(hdesc->rs_base.rs_flags & SO_NEED_TUPLE) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+		{
+			hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3e92725a821..cc6289b6343 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -60,9 +60,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
-static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
-static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
-static inline void BitmapPrefetch(HeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2183,147 +2180,68 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (prefetch_iterator)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			bhs_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
-	 * parallel workers.
-	 */
-	if (scan->rs_base.prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (prefetch_iterator)
-			{
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck, BlockNumber *blockno,
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	void	   *per_buffer_data;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(hscan);
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		bhs_iterate(scan->rs_bhs_iterator, &tbmres);
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(hscan->rs_vmbuffer))
 		{
-			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
-			return false;
+			ReleaseBuffer(hscan->rs_vmbuffer);
+			hscan->rs_vmbuffer = InvalidBuffer;
 		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return hscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		hscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2344,7 +2262,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2353,9 +2271,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2405,23 +2323,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->bm_parallel == NULL &&
-		scan->rs_pf_bhs_iterator &&
-		hscan->pfblockno < hscan->rs_base.blockno)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(hscan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2432,153 +2338,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	int			prefetch_maximum = scan->rs_base.prefetch_maximum;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= prefetch_maximum / 2)
-			scan->prefetch_target = prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= prefetch_maximum / 2)
-			pstate->prefetch_target = prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-	BitmapHeapIterator *prefetch_iterator = scan->rs_base.rs_pf_bhs_iterator;
-
-	if (pstate == NULL)
-	{
-		if (prefetch_iterator)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (prefetch_iterator)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				bhs_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					scan->rs_base.rs_pf_bhs_iterator = NULL;
-					break;
-				}
-
-				scan->pfblockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->rs_base.rs_rd,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
@@ -2613,41 +2372,11 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 			return true;
 		}
 
-		if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
 										   lossy_pages, exact_pages))
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!scan->bm_parallel)
-	{
-		if (hscan->prefetch_target < scan->prefetch_maximum)
-			hscan->prefetch_target++;
-	}
-	else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&scan->bm_parallel->mutex);
-		if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
-			scan->bm_parallel->prefetch_target++;
-		SpinLockRelease(&scan->bm_parallel->mutex);
-	}
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(hscan);
-#endif							/* USE_PREFETCH */
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 7f651004113..38a6262e3c4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -131,14 +131,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
@@ -149,15 +141,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-		int			pf_maximum = 0;
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
-#endif
-
 		if (!node->pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -174,13 +157,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * multiple processes to iterate jointly.
 				 */
 				node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					node->pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
+
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(node->pstate);
 			}
@@ -214,22 +191,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->prefetch_maximum = pf_maximum;
 		scan->bm_parallel = node->pstate;
 
 		scan->rs_bhs_iterator = bhs_begin_iterate(tbm,
 												  scan->bm_parallel ? scan->bm_parallel->tbmiterator : InvalidDsaPointer,
 												  dsa);
 
-#ifdef USE_PREFETCH
-		if (scan->prefetch_maximum > 0)
-		{
-			scan->rs_pf_bhs_iterator = bhs_begin_iterate(tbm,
-														 scan->bm_parallel ? scan->bm_parallel->prefetch_iterator : InvalidDsaPointer,
-														 dsa);
-		}
-#endif							/* USE_PREFETCH */
-
 		node->initialized = true;
 	}
 
@@ -526,14 +493,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -564,11 +527,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2e262bf4354..8702a20741b 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
 #include "storage/dsm.h"
 #include "storage/lockdefs.h"
 #include "storage/shm_toc.h"
+#include "storage/read_stream.h"
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
@@ -76,6 +77,9 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* Streaming read control object for scans supporting it */
+	ReadStream *rs_read_stream;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -86,23 +90,6 @@ typedef struct HeapScanDescData
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
 
-	/*
-	 * These fields only used for prefetching in bitmap table scans
-	 */
-
-	/* buffer for visibility-map lookups of prefetched pages */
-	Buffer		pvmbuffer;
-
-	/*
-	 * These fields only used in serial BHS
-	 */
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
-	/* used to validate prefetch block stays ahead of current block  */
-	BlockNumber pfblockno;
-
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 7938b741d66..02893bf99bc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -46,13 +46,7 @@ typedef struct TableScanDescData
 
 	/* Only used for Bitmap table scans */
 	struct BitmapHeapIterator *rs_bhs_iterator;
-	struct BitmapHeapIterator *rs_pf_bhs_iterator;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
 	struct ParallelBitmapHeapState *bm_parallel;
-	/* used to validate BHS prefetch and current block stay in sync */
-	BlockNumber blockno;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 79689ec3773..aead772e6fd 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -918,8 +918,6 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 
 	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 	result->rs_bhs_iterator = NULL;
-	result->rs_pf_bhs_iterator = NULL;
-	result->prefetch_maximum = 0;
 	result->bm_parallel = NULL;
 	return result;
 }
@@ -972,12 +970,6 @@ table_endscan(TableScanDesc scan)
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
@@ -994,12 +986,6 @@ table_rescan(TableScanDesc scan,
 	{
 		bhs_end_iterate(scan->rs_bhs_iterator);
 		scan->rs_bhs_iterator = NULL;
-
-		if (scan->rs_pf_bhs_iterator)
-		{
-			bhs_end_iterate(scan->rs_pf_bhs_iterator);
-			scan->rs_pf_bhs_iterator = NULL;
-		}
 	}
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 592215d5ee7..8d86b900a0b 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1767,11 +1767,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1779,10 +1775,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.44.0

#98Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#97)
13 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Apr 04, 2024 at 04:35:45PM +0200, Tomas Vondra wrote:

On 4/4/24 00:57, Melanie Plageman wrote:

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

On Fri, Mar 29, 2024 at 12:05:15PM +0100, Tomas Vondra wrote:

On 3/29/24 02:12, Thomas Munro wrote:

On Fri, Mar 29, 2024 at 10:43 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

Thanks for the repro. I can't seem to reproduce it (still trying) but
I assume this is with Melanie's v11 patch set which had
v11-0016-v10-Read-Stream-API.patch.

Would you mind removing that commit and instead applying the v13
stream_read.c patches[1]? v10 stream_read.c was a little confused
about random I/O combining, which I fixed with a small adjustment to
the conditions for the "if" statement right at the end of
read_stream_look_ahead(). Sorry about that. The fixed version, with
eic=4, with your test query using WHERE a < a, ends its scan with:

I'll give that a try. Unfortunately unfortunately the v11 still has the
problem I reported about a week ago:

ERROR: prefetch and main iterators are out of sync

So I can't run the full benchmarks :-( but master vs. streaming read API
should work, I think.

Odd, I didn't notice you reporting this ERROR popping up. Now that I
take a look, v11 (at least, maybe also v10) had this very sill mistake:

  if (scan->bm_parallel == NULL &&
      scan->rs_pf_bhs_iterator &&
      hscan->pfblockno > hscan->rs_base.blockno)
       elog(ERROR, "prefetch and main iterators are out of sync");

It errors out if the prefetch block is ahead of the current block --
which is the opposite of what we want. I've fixed this in attached v12.

This version also has v13 of the streaming read API. I noticed one
mistake in my bitmapheap scan streaming read user -- it freed the
streaming read object at the wrong time. I don't know if this was
causing any other issues, but it at least is fixed in this version.

Attached v13 is rebased over master (which includes the streaming read
API now). I also reset the streaming read object on rescan instead of
creating a new one each time.

I don't know how much chance any of this has of going in to 17 now, but
I thought I would start looking into the regression repro Tomas provided
in [1].

My personal opinion is that we should try to get in as many of the the
refactoring patches as possible, but I think it's probably too late for
the actual switch to the streaming API.

Cool. In the attached v15, I have dropped all commits that are related
to the streaming read API and included *only* commits that are
beneficial to master. A few of the commits are merged or reordered as
well.

While going through the commits with this new goal in mind (forget about
the streaming read API for now), I realized that it doesn't make much
sense to just eliminate the layering violation for the current block and
leave it there for the prefetch block. I had de-prioritized solving this
when I thought we would just delete the prefetch code and replace it
with the streaming read.

Now that we aren't doing that, I've spent the day trying to resolve the
issues with pushing the prefetch code into heapam.c that I cited in [1]/messages/by-id/20240323002211.on5vb5ulk6lsdb2u@liskov.
0010 - 0013 are the result of this. They are not very polished yet and
need more cleanup and review (especially 0011, which is probably too
large), but I am happy with the solution I came up with.

Basically, there are too many members needed for bitmap heap scan to put
them all in the HeapScanDescData (don't want to bloat it). So, I've made
a new BitmapHeapScanDescData and associated begin/rescan/end() functions

In the end, with all patches applied, BitmapHeapNext() loops invoking
table_scan_bitmap_next_tuple() and table AMs can implement that however
they choose.

I'm also not sure if I should try and group the commits into fewer
commits now or wait until I have some idea of whether or not the
approach in 0013 and 0014 is worth pursuing.

You mean whether to pursue the approach in general, or for v17? I think
it looks like the right approach, but for v17 see above :-(

As for merging, I wouldn't do that. I looked at the commits and while
some of them seem somewhat "trivial", I really like how you organized
the commits, and kept those that just "move" code around, and those that
actually change stuff. It's much easier to understand, IMO.

I went through the first ~10 commits, and added some review - either as
a separate commit, when possible, in the code as XXX comment, and also
in the commit message. The code tweaks are utterly trivial (whitespace
or indentation to make the line shorter). It shouldn't take much time to
deal with those, I think.

Attached v15 incorporates your v14-0002-review.

For your v14-0008-review, I actually ended up removing that commit
because once I removed everything that was for streaming read API, it
became redundant with another commit.

For your v14-0010-review, we actually can't easily get rid of those
local variables because we make the iterators before we make the scan
descriptors and the commit following that commit moves the iterators
from the BitmapHeapScanState to the scan descriptor.

I think the main focus should be updating the commit messages. If it was
only a single patch, I'd probably try to write the messages myself, but
with this many patches it'd be great if you could update those and I'll
review that before commit.

I did my best to update the commit messages to be less specific and more
focused on "why should I care". I found myself wanting to explain why I
implemented something the way I did and then getting back into the
implementation details again. I'm not sure if I suceeded in having less
details and more substance.

I always struggle with writing commit messages myself, and it takes me
ages to write a good one (well, I think the message is good, but who
knows ...). But I think a good message should be concise enough to
explain what and why it's done. It may reference a thread for all the
gory details, but the basic reasoning should be in the commit message.
For example the message for "BitmapPrefetch use prefetch block recheck
for skip fetch" now says that it "makes more sense to do X" but does not
really say why that's the case. The linked message does, but it'd be
good to have that in the message (because how would I know how much of
the thread to read?).

I fixed that particular one. I tried to take that feedback and apply it
to other commit messages. I don't know how successful I was...

Also, it'd be very helpful if you could update the author & reviewed-by
fields. I'll review those before commit, ofc, but I admit I lost track
of who reviewed which part.

I have updated reviewers. I didn't add reviewers on the ones that
haven't really been reviewed yet.

I'd focus on the first ~8-9 commits or so for now, we can commit more if
things go reasonably well.

Sounds good. I will spend cleanup time on 0010-0013 tomorrow but would
love to know if you agree with the direction before I spend more time.

- Melanie

[1]: /messages/by-id/20240323002211.on5vb5ulk6lsdb2u@liskov

Attachments:

v15-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From adae81352723f22ba2528dc4bf5f2216c7641428 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v15 01/13] BitmapHeapScan begin scan after bitmap creation

It makes more sense for BitmapHeapScan to scan the index, build the
bitmap, and then begin the scan on the underlying table.

This is primarily a cosmetic change for now, but later commits will pass
parameters to table_beginscan_bm() that are unavailable in
ExecInitBitmapHeapScan().

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 27 +++++++++++++++++------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aab..c8c466e3c5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = table_beginscan_bm(node->ss.ss_currentRelation,
+									  node->ss.ps.state->es_snapshot,
+									  0,
+									  NULL);
+
+			node->ss.ss_currentScanDesc = scan;
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +616,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +694,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +801,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v15-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 6957ee25cf85784906a1315d148180858aedaad2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v15 02/13] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() instead of
in ExecInitBitmapHeapScan(). This is a preliminary step to pushing the
skip fetch optimization into heap AM code.

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c8c466e3c5..2148a21531 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -743,16 +753,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v15-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From 7566751f0ce9d68154e1f5616f7585334f497716 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:34:25 +0200
Subject: [PATCH v15 03/13] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM-specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block. The layering violation is
still present in BitmapHeapScans's prefetching code, which uses the
visibility map to decide whether or not to prefetch a block. However,
this will be fixed in an upcoming commit.

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index dada2ecd1e..10f2faaa60 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -967,6 +967,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1055,6 +1057,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1074,6 +1082,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3e7a6b5548..929b2cf8e7 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2198,6 +2199,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2310,6 +2329,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2148a21531..a8bc5dec53 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,10 +185,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
 									  0,
-									  NULL);
+									  NULL,
+									  extra_flags);
 
 			node->ss.ss_currentScanDesc = scan;
 		}
@@ -208,7 +212,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -229,37 +233,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -302,52 +283,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -519,7 +481,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -570,7 +532,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -640,8 +602,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -651,7 +611,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -696,8 +655,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -741,8 +698,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -753,7 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2765efc4e5..750ea30852 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,6 +76,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e7eeb75409..55f1139757 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -63,6 +63,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -937,9 +944,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e57ebd7288..fa2f70b7a4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,10 +1794,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1817,9 +1814,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v15-0004-BitmapPrefetch-use-prefetch-block-recheck-for-sk.patchtext/x-diff; charset=us-asciiDownload
From 9d18888d6e80bc7e2bb676b2803a463f5ee4b04c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v15 04/13] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. This doesn't seem right. We should use the
prefetch block's recheck flag to determine whether or not to prefetch
it. The current block's recheck flag has no relationship to the prefetch
block's recheck flag. See this [1] thread on hackers reporting the
issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a8bc5dec53..2e2cec8b3b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -475,14 +475,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -533,7 +528,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v15-0005-Update-BitmapAdjustPrefetchIterator-parameter-ty.patchtext/x-diff; charset=us-asciiDownload
From 200f5b4e4e79d9cd9e0d8f02df574d616a3569eb Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v15 05/13] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2e2cec8b3b..795a893035 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -231,7 +231,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -342,7 +342,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -361,7 +361,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v15-0006-Reduce-scope-of-BitmapHeapScan-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From 001b361b38b294b8cbf7d7c4487804d56f0929e1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v15 06/13] Reduce scope of BitmapHeapScan tbmiterator local
 variables

A future patch will change where tbmiterators are initialized and saved.
To simplify that diff, move them into a tighter scope.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 795a893035..8403be84f3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -207,6 +203,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -222,9 +220,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v15-0007-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From b865213848634d95f22ce50aa701eb1ac4722c5c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v15 07/13] table_scan_bitmap_next_block counts lossy and exact
 pages

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So the table AM must keep
track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap for the purposes of EXPLAIN counters.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 13 +++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 929b2cf8e7..b5ab104ec2 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2316,6 +2317,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 8403be84f3..68f9ded168 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -210,8 +210,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -231,19 +229,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
 			}
 
+
 			/* Adjust the prefetch target */
 			BitmapAdjustPrefetchTarget(node);
 		}
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 55f1139757..e2ad8d0728 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,6 +789,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy_pages is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, exact_pages is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -804,7 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1968,17 +1972,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy_pages is incremented is the block's
+ * representation in the bitmap is lossy; otherwise, exact_pages is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1989,7 +1997,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v15-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From c4098d4d1ec206b837711b03f5dfc322346be497 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v15 08/13] Remove table_scan_bitmap_next_tuple parameter
 tbmres

Future commits will push all of the logic for choosing the next block
into the table AM specific code. The table AM will be responsible for
iterating and reading in the right blocks.

Thus, it no longer makes sense to use the TBMIterateResult (which
contains a block number) as a means of communication between
table_scan_bitmap_next_tuple() and table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b5ab104ec2..efd1a66a09 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2327,7 +2327,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 68f9ded168..951a98c101 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -280,7 +280,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e2ad8d0728..2efa97f602 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,10 +780,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -814,15 +811,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2012,7 +2004,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2024,7 +2015,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v15-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 520acaf3df90cec9db518f6fda660ae9bb81fba0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v15 09/13] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to the
table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  58 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 186 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 190 insertions(+), 141 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index efd1a66a09..9d3e7c7fda 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,18 +2188,52 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2218,16 +2252,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2322,7 +2347,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 951a98c101..e1b13ddaa6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,7 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +160,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -203,48 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -266,45 +232,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -330,13 +307,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -350,14 +331,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -382,7 +366,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -460,6 +447,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -517,6 +505,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -578,12 +568,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -591,13 +577,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -628,28 +614,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -682,8 +664,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -691,9 +671,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304a..92b829cebc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2efa97f602..42c67a128e 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -773,19 +774,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
@@ -804,7 +800,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -942,9 +938,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -991,6 +991,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1001,6 +1016,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1964,19 +1994,18 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy_pages is incremented is the block's
- * representation in the bitmap is lossy; otherwise, exact_pages is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented is the block's representation in the bitmap is lossy; otherwise,
+ * exact_pages is incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1989,9 +2018,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fa2f70b7a4..d96703b04d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v15-0010-Unify-parallel-and-serial-BitmapHeapScan-iterato.patchtext/x-diff; charset=us-asciiDownload
From dcdfa8174ef7927f64bfb07f29bf0e9c2a45fde7 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 25 Mar 2024 11:05:51 -0400
Subject: [PATCH v15 10/13] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to both
TBMIterator and TBMSharedIterators. This encapsulates the parallel and serial
iterators and their access and makes the bitmap heap scan code a bit cleaner.
This naturally lends itself to a bit of reorganization of the
!node->initialized path in BitmapHeapNext().

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 172 ++++++++++++----------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  40 +----
 src/include/executor/nodeBitmapHeapscan.h |   7 +
 src/include/nodes/execnodes.h             |  13 +-
 src/tools/pgindent/typedefs.list          |   1 +
 7 files changed, 124 insertions(+), 121 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 9d3e7c7fda..5e57d19d91 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2208,10 +2208,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		tbmres = bhs_iterate(&scan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e1b13ddaa6..70b560b8ee 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -57,6 +57,61 @@ static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
+/*
+ * Start iteration on a shared or non-shared bitmap iterator. Note that tbm
+ * will only be provided by serial BitmapHeapScan callers. dsa and dsp will
+ * only be provided by parallel BitmapHeapScan callers.
+ */
+void
+bhs_begin_iterate(BitmapHeapIterator *iterator, TIDBitmap *tbm,
+				  dsa_area *dsa, dsa_pointer dsp)
+{
+	Assert(iterator);
+
+	iterator->serial = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = false;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+		iterator->parallel = tbm_attach_shared_iterate(dsa, dsp);
+	else
+		iterator->serial = tbm_begin_iterate(tbm);
+}
+
+/*
+ * Get the next TBMIterateResult from the bitmap iterator.
+ */
+TBMIterateResult *
+bhs_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+	Assert(!iterator->exhausted);
+
+	if (iterator->serial)
+		return tbm_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
+
+/*
+ * Clean up the bitmap iterator.
+ */
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		tbm_end_iterate(iterator->serial);
+	else if (iterator->parallel)
+		tbm_end_shared_iterate(iterator->parallel);
+
+	iterator->serial = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = true;
+}
+
 
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
@@ -96,43 +151,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate)
+		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (init_shared_state)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
@@ -153,21 +188,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
 			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -198,8 +221,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		bhs_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
+						  pstate ?
+						  pstate->tbmiterator :
+						  InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			bhs_begin_iterate(&node->pf_iterator, tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+			/* Only used for serial BHS */
+			node->prefetch_pages = 0;
+			node->prefetch_target = -1;
+		}
+#endif							/* USE_PREFETCH */
 
 		node->initialized = true;
 
@@ -276,7 +314,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!node->pf_iterator.exhausted &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -317,21 +355,20 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = bhs_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -344,8 +381,6 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -365,9 +400,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -427,23 +462,21 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -471,9 +504,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (1)
 			{
@@ -496,12 +527,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -568,18 +598,14 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	if (node->pf_iterator.exhausted)
+		bhs_end_iterate(&node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -624,12 +650,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+	if (!node->pf_iterator.exhausted)
+		bhs_end_iterate(&node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -667,11 +691,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc..e520186b41 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,13 +20,11 @@
 #include "storage/buf.h"
 #include "storage/spin.h"
 #include "utils/relcache.h"
+#include "executor/nodeBitmapHeapscan.h"
 
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -44,8 +42,7 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	BitmapHeapIterator rs_bhs_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 42c67a128e..618ab2b449 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -938,13 +938,9 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
 /*
@@ -991,20 +987,9 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
+		!scan->rs_bhs_iterator.exhausted)
+		bhs_end_iterate(&scan->rs_bhs_iterator);
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
@@ -1016,20 +1001,9 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
+		!scan->rs_bhs_iterator.exhausted)
+		bhs_end_iterate(&scan->rs_bhs_iterator);
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index ea003a9caa..7064f54686 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -29,4 +29,11 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
 
+extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+extern void bhs_begin_iterate(BitmapHeapIterator *iterator, TIDBitmap *tbm,
+							  dsa_area *dsa, dsa_pointer dsp);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
+
+
 #endif							/* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d96703b04d..714eb3e534 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1787,6 +1787,13 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+	bool		exhausted;
+} BitmapHeapIterator;
+
 /* ----------------
  *	 BitmapHeapScanState information
  *
@@ -1795,12 +1802,11 @@ typedef struct ParallelBitmapHeapState
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
+ *		pf_iterator        for prefetching ahead of current page
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1815,12 +1821,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	BitmapHeapIterator pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index f3b8641d76..2348a8793e 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.40.1

v15-0011-Push-BitmapHeapScan-prefetch-code-into-heapam.c.patchtext/x-diff; charset=us-asciiDownload
From d141ad447470458de47c6c9b54c97491bb9f168c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 09:42:23 -0400
Subject: [PATCH v15 11/13] Push BitmapHeapScan prefetch code into heapam.c

7566751f0ce9 eliminated a table AM layering violation for the current
block in a BitmapHeapScan but left the violation in BitmapHeapScan
prefetching code.

To resolve this, move the BitmapHeapScan prefetching logic entirely into
heap AM code. There is a fair amount of setup that is specific to
BitmapHeapScan and once the state associated with that lives in the scan
descriptor, it made more sense to make dedicated
begin_scan()/rescan()/endscan() routines for BitmapHeapScan.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          | 129 ++++++-
 src/backend/access/heap/heapam_handler.c  | 306 ++++++++++++++--
 src/backend/executor/nodeBitmapHeapscan.c | 410 +++-------------------
 src/include/access/heapam.h               |  62 +++-
 src/include/access/relscan.h              |   3 -
 src/include/access/tableam.h              |  74 ++--
 src/include/executor/nodeBitmapHeapscan.h |   6 +
 src/include/nodes/execnodes.h             |  21 --
 src/tools/pgindent/typedefs.list          |   1 +
 9 files changed, 553 insertions(+), 459 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 10f2faaa60..a21ec92d71 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -938,6 +938,48 @@ continue_page:
  * ----------------------------------------------------------------
  */
 
+TableScanDesc
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+{
+	BitmapHeapScanDesc scan;
+
+	/*
+	 * increment relation ref count while scanning relation
+	 *
+	 * This is just to make really sure the relcache entry won't go away while
+	 * the scan has a pointer to it.  Caller should be holding the rel open
+	 * anyway, so this is redundant in all normal scenarios...
+	 */
+	RelationIncrementReferenceCount(relation);
+	scan = (BitmapHeapScanDesc) palloc(sizeof(BitmapHeapScanDescData));
+
+	scan->heap_common.rs_base.rs_rd = relation;
+	scan->heap_common.rs_base.rs_snapshot = snapshot;
+	scan->heap_common.rs_base.rs_nkeys = 0;
+	scan->heap_common.rs_base.rs_flags = flags;
+	scan->heap_common.rs_base.rs_parallel = NULL;
+	scan->heap_common.rs_strategy = NULL;
+
+	Assert(snapshot && IsMVCCSnapshot(snapshot));
+
+	/* we only need to set this up once */
+	scan->heap_common.rs_ctup.t_tableOid = RelationGetRelid(relation);
+
+	scan->heap_common.rs_parallelworkerdata = NULL;
+	scan->heap_common.rs_base.rs_key = NULL;
+
+	initscan(&scan->heap_common, NULL, false);
+
+	scan->iterator.serial = NULL;
+	scan->iterator.parallel = NULL;
+	scan->vmbuffer = InvalidBuffer;
+	scan->pf_iterator.serial = NULL;
+	scan->pf_iterator.parallel = NULL;
+	scan->pvmbuffer = InvalidBuffer;
+
+	return (TableScanDesc) scan;
+}
+
 
 TableScanDesc
 heap_beginscan(Relation relation, Snapshot snapshot,
@@ -967,8 +1009,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1026,6 +1066,35 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	return (TableScanDesc) scan;
 }
 
+/*
+ * Cleanup BitmapHeapScan table state
+ */
+void
+heap_endscan_bm(TableScanDesc sscan)
+{
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+
+	if (BufferIsValid(scan->heap_common.rs_cbuf))
+		ReleaseBuffer(scan->heap_common.rs_cbuf);
+
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+
+	bhs_end_iterate(&scan->pf_iterator);
+	bhs_end_iterate(&scan->iterator);
+
+	/*
+	 * decrement relation reference count and free scan descriptor storage
+	 */
+	RelationDecrementReferenceCount(scan->heap_common.rs_base.rs_rd);
+
+	pfree(scan);
+}
+
+
 void
 heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			bool allow_strat, bool allow_sync, bool allow_pagemode)
@@ -1057,12 +1126,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1082,12 +1145,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
@@ -1334,6 +1391,50 @@ heap_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction,
 	return true;
 }
 
+void
+heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
+			   ParallelBitmapHeapState *pstate, dsa_area *dsa, int pf_maximum)
+{
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+	scan->vmbuffer = InvalidBuffer;
+
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+	scan->pvmbuffer = InvalidBuffer;
+
+	bhs_end_iterate(&scan->pf_iterator);
+	bhs_end_iterate(&scan->iterator);
+
+	scan->prefetch_maximum = 0;
+	scan->empty_tuples_pending = 0;
+	scan->pstate = NULL;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+	scan->pfblockno = InvalidBlockNumber;
+
+	bhs_begin_iterate(&scan->iterator,
+					  tbm, dsa,
+					  pstate ?
+					  pstate->tbmiterator :
+					  InvalidDsaPointer);
+#ifdef USE_PREFETCH
+	if (pf_maximum > 0)
+	{
+		bhs_begin_iterate(&scan->pf_iterator, tbm, dsa,
+						  pstate ?
+						  pstate->prefetch_iterator :
+						  InvalidDsaPointer);
+	}
+#endif							/* USE_PREFETCH */
+
+	scan->pstate = pstate;
+	scan->prefetch_maximum = pf_maximum;
+}
+
+
 /*
  *	heap_fetch		- retrieve tuple with given tid
  *
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 5e57d19d91..c513cbd2da 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -60,6 +60,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc scan);
+static inline void BitmapPrefetch(BitmapHeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2186,12 +2189,80 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	BitmapHeapIterator *prefetch_iterator = &scan->pf_iterator;
+	ParallelBitmapHeapState *pstate = scan->pstate;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			scan->prefetch_pages--;
+		}
+		else if (!prefetch_iterator->exhausted)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbmpre = bhs_iterate(prefetch_iterator);
+			scan->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (scan->prefetch_maximum > 0)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!prefetch_iterator->exhausted)
+			{
+				tbmpre = bhs_iterate(prefetch_iterator);
+				scan->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+heapam_scan_bitmap_next_block(TableScanDesc sscan,
+							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+	HeapScanDesc hscan = &scan->heap_common;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2201,19 +2272,21 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(scan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = bhs_iterate(&scan->rs_bhs_iterator);
+		Assert(!scan->iterator.exhausted);
+		tbmres = bhs_iterate(&scan->iterator);
 
 		if (tbmres == NULL)
 		{
 			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
+			Assert(scan->empty_tuples_pending == 0);
 			return false;
 		}
 
@@ -2228,7 +2301,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2236,15 +2308,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+	if (!(hscan->rs_base.rs_flags & SO_NEED_TUPLE) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(hscan->rs_base.rs_rd, tbmres->blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(scan->empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2255,18 +2327,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
 	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
+										  hscan->rs_base.rs_rd,
 										  block);
 	hscan->rs_cblock = block;
 	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
+	snapshot = hscan->rs_base.rs_snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
+	heap_page_prune_opt(hscan->rs_base.rs_rd, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2294,7 +2366,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, hscan->rs_base.rs_rd, buffer, snapshot,
 									   &heapTuple, NULL, true))
 				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
@@ -2320,16 +2392,16 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
+			loctup.t_tableOid = hscan->rs_base.rs_rd->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
 				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+				PredicateLockTID(hscan->rs_base.rs_rd, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+			HeapCheckForSerializableConflictOut(valid, hscan->rs_base.rs_rd, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2344,6 +2416,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->pstate == NULL &&
+		!scan->pf_iterator.exhausted &&
+		scan->pfblockno < block)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(scan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2354,22 +2438,168 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	return true;
 }
 
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->pstate;
+	int			prefetch_maximum = scan->prefetch_maximum;
+
+	if (pstate == NULL)
+	{
+		if (scan->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
+		else
+			scan->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(BitmapHeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->pstate;
+	BitmapHeapIterator *prefetch_iterator = &scan->pf_iterator;
+	Relation	rel = scan->heap_common.rs_base.rs_rd;
+
+	if (pstate == NULL)
+	{
+		if (!prefetch_iterator->exhausted)
+		{
+			while (scan->prefetch_pages < scan->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					break;
+				}
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->heap_common.rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(rel,
+											 tbmpre->blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		if (!prefetch_iterator->exhausted)
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = bhs_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				scan->pfblockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->heap_common.rs_base.rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(rel,
+											 tbmpre->blockno,
+											 &scan->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = &bscan->heap_common;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (bscan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		bscan->empty_tuples_pending--;
 		return true;
 	}
 
@@ -2379,6 +2609,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!bscan->pstate)
+	{
+		if (bscan->prefetch_target < bscan->prefetch_maximum)
+			bscan->prefetch_target++;
+	}
+	else if (bscan->pstate->prefetch_target < bscan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&bscan->pstate->mutex);
+		if (bscan->pstate->prefetch_target < bscan->prefetch_maximum)
+			bscan->pstate->prefetch_target++;
+		SpinLockRelease(&bscan->pstate->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(bscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2704,6 +2964,10 @@ static const TableAmRoutine heapam_methods = {
 	.scan_set_tidrange = heap_set_tidrange,
 	.scan_getnextslot_tidrange = heap_getnextslot_tidrange,
 
+	.scan_rescan_bm = heap_rescan_bm,
+	.scan_begin_bm = heap_beginscan_bm,
+	.scan_end_bm = heap_endscan_bm,
+
 	.parallelscan_estimate = table_block_parallelscan_estimate,
 	.parallelscan_initialize = table_block_parallelscan_initialize,
 	.parallelscan_reinitialize = table_block_parallelscan_reinitialize,
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 70b560b8ee..d22a433f06 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 /*
@@ -122,20 +118,9 @@ bhs_end_iterate(BitmapHeapIterator *iterator)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TIDBitmap  *tbm;
-	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
-	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
+	TableScanDesc scan = node->ss.ss_currentScanDesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -146,25 +131,37 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
 	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
 	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
 	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
+		Relation	rel = node->ss.ss_currentRelation;
+		bool		pf_maximum = 0;
+		bool		init_shared_state = false;
+		uint32		extra_flags = 0;
+
 		/*
 		 * The leader will immediately come out of the function, but others
 		 * will be blocked until leader populates the TBM and wakes them up.
 		 */
-		bool		init_shared_state = node->pstate ?
+		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate || init_shared_state)
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
+		if (!node->pstate || init_shared_state)
 		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
-			if (!tbm || !IsA(tbm, TIDBitmap))
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-			node->tbm = tbm;
 
 			if (init_shared_state)
 			{
@@ -173,113 +170,52 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 * dsa_pointer of the iterator state which will be used by
 				 * multiple processes to iterate jointly.
 				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+				node->pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
+					node->pstate->prefetch_iterator =
+						tbm_prepare_shared_iterate(node->tbm);
 				}
 #endif
 				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
+				BitmapDoneInitializingSharedState(node->pstate);
 			}
 		}
 
 		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
 		 */
-		if (!scan)
-		{
-			uint32		extra_flags = 0;
-
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
-				extra_flags |= SO_NEED_TUPLE;
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
-									  extra_flags);
-
-			node->ss.ss_currentScanDesc = scan;
-		}
-
-		bhs_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
-						  pstate ?
-						  pstate->tbmiterator :
-						  InvalidDsaPointer);
-
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			bhs_begin_iterate(&node->pf_iterator, tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-			/* Only used for serial BHS */
-			node->prefetch_pages = 0;
-			node->prefetch_target = -1;
-		}
-#endif							/* USE_PREFETCH */
-
+		if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+			extra_flags |= SO_NEED_TUPLE;
+
+		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
+								  rel,
+								  node->ss.ps.state->es_snapshot,
+								  extra_flags,
+								  pf_maximum,
+								  node->tbm,
+								  node->pstate,
+								  node->ss.ps.state->es_query_dsa);
+
+		node->ss.ss_currentScanDesc = scan;
 		node->initialized = true;
 
 		goto new_page;
 	}
 
+
 	for (;;)
 	{
 		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
 
 			/*
 			 * If we are using lossy info, we have to recheck the qual
@@ -303,23 +239,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!node->pf_iterator.exhausted &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -343,215 +265,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = bhs_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbmpre = bhs_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
-
-	if (pstate == NULL)
-	{
-		if (!prefetch_iterator->exhausted)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = bhs_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->pfblockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -597,19 +310,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->ss.ss_currentScanDesc)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
-	/* release bitmaps and buffers if any */
-	if (node->pf_iterator.exhausted)
-		bhs_end_iterate(&node->pf_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -648,14 +354,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (!node->pf_iterator.exhausted)
-		bhs_end_iterate(&node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -688,16 +390,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -737,13 +434,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -827,7 +517,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 750ea30852..73690d15c5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,22 +76,60 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDescData
+{
+	/* All the non-BitmapHeapScan specific members */
+	HeapScanDescData heap_common;
+
+	/*
+	 * Members common to Parallel and Serial BitmapHeapScan
+	 */
+	struct BitmapHeapIterator iterator;
+	struct BitmapHeapIterator pf_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
-	Buffer		rs_vmbuffer;
-	int			rs_empty_tuples_pending;
+	Buffer		vmbuffer;
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
+	int			empty_tuples_pending;
+
+	/*
+	 * Parallel-only members
+	 */
+
+	struct ParallelBitmapHeapState *pstate;
+
+	/*
+	 * Serial-only members
+	 */
+
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block  */
+	BlockNumber pfblockno;
+}			BitmapHeapScanDescData;
+
+typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc;
 
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
@@ -289,6 +327,12 @@ extern void heap_set_tidrange(TableScanDesc sscan, ItemPointer mintid,
 extern bool heap_getnextslot_tidrange(TableScanDesc sscan,
 									  ScanDirection direction,
 									  TupleTableSlot *slot);
+extern TableScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags);
+
+extern void heap_endscan_bm(TableScanDesc scan);
+extern void heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
+						   ParallelBitmapHeapState *pstate, dsa_area *dsa, int pf_maximum);
+
 extern bool heap_fetch(Relation relation, Snapshot snapshot,
 					   HeapTuple tuple, Buffer *userbuf, bool keep_buf);
 extern bool heap_hot_search_buffer(ItemPointer tid, Relation relation,
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index e520186b41..855b9558bf 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -41,9 +41,6 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
-	/* Only used for Bitmap table scans */
-	BitmapHeapIterator rs_bhs_iterator;
-
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 618ab2b449..138bf5f6ed 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -391,6 +391,23 @@ typedef struct TableAmRoutine
 											  ScanDirection direction,
 											  TupleTableSlot *slot);
 
+	/*
+	 * TODO: add comment
+	 */
+	TableScanDesc (*scan_begin_bm) (Relation rel,
+									Snapshot snapshot,
+									uint32 flags);
+
+	void		(*scan_rescan_bm) (TableScanDesc scan, TIDBitmap *tbm,
+								   ParallelBitmapHeapState *pstate, dsa_area *dsa,
+								   int pf_maximum);
+
+	/*
+	 * Release resources and deallocate scan. If TableScanDesc.temp_snap,
+	 * TableScanDesc.rs_snapshot needs to be unregistered.
+	 */
+	void		(*scan_end_bm) (TableScanDesc scan);
+
 	/* ------------------------------------------------------------------------
 	 * Parallel table scan related functions.
 	 * ------------------------------------------------------------------------
@@ -774,9 +791,9 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
+	 * Prepare to fetch / check / return tuples as part of a bitmap table
+	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
+	 * bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
@@ -785,22 +802,11 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno, bool *recheck,
+										   bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -929,18 +935,26 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 }
 
 /*
- * table_beginscan_bm is an alternative entry point for setting up a
- * TableScanDesc for a bitmap heap scan.  Although that scan technology is
- * really quite unlike a standard seqscan, there is just enough commonality to
- * make it worth using the same data structure.
+ * table_beginscan_bm is the entry point for setting up a TableScanDesc for a
+ * bitmap heap scan.
  */
 static inline TableScanDesc
-table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
+table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
+				   uint32 extra_flags, int pf_maximum, TIDBitmap *tbm,
+				   ParallelBitmapHeapState *pstate, dsa_area *dsa)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!scan)
+		scan = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
+
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa, pf_maximum);
+
+	return scan;
 }
 
 /*
@@ -987,9 +1001,11 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
-		!scan->rs_bhs_iterator.exhausted)
-		bhs_end_iterate(&scan->rs_bhs_iterator);
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_rd->rd_tableam->scan_end_bm(scan);
+		return;
+	}
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
@@ -1001,10 +1017,6 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
-		!scan->rs_bhs_iterator.exhausted)
-		bhs_end_iterate(&scan->rs_bhs_iterator);
-
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1979,7 +1991,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno, bool *recheck,
+							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1992,7 +2004,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages, exact_pages);
 }
 
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index 7064f54686..f3c92f7a8a 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -28,6 +28,12 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 										  ParallelContext *pcxt);
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+	bool		exhausted;
+} BitmapHeapIterator;
 
 extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
 extern void bhs_begin_iterate(BitmapHeapIterator *iterator, TIDBitmap *tbm,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 714eb3e534..49ce4ff9a7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1787,30 +1787,16 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
-typedef struct BitmapHeapIterator
-{
-	struct TBMIterator *serial;
-	struct TBMSharedIterator *parallel;
-	bool		exhausted;
-} BitmapHeapIterator;
-
 /* ----------------
  *	 BitmapHeapScanState information
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		pf_iterator        for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1818,18 +1804,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	BitmapHeapIterator pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 2348a8793e..443b01c053 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -263,6 +263,7 @@ BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
+BitmapHeapScanDesc
 BitmapIndexScan
 BitmapIndexScanState
 BitmapOr
-- 
2.40.1

v15-0012-Move-BitmapHeapScan-initialization-to-helper.patchtext/x-diff; charset=us-asciiDownload
From c1c9537f045ba7293416711347c7113fa8ec33f9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 02:50:42 -0400
Subject: [PATCH v15 12/13] Move BitmapHeapScan initialization to helper

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 170 ++++++++++++----------
 1 file changed, 92 insertions(+), 78 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d22a433f06..aaeece6697 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -109,6 +109,94 @@ bhs_end_iterate(BitmapHeapIterator *iterator)
 }
 
 
+ /*
+  * If we haven't yet performed the underlying index scan, do it, and begin
+  * the iteration over the bitmap.
+  *
+  * For prefetching, we use *two* iterators, one for the pages we are actually
+  * scanning and another that runs ahead of the first for prefetching.
+  * node->prefetch_pages tracks exactly how many pages ahead the prefetch
+  * iterator is.  Also, node->prefetch_target tracks the desired prefetch
+  * distance, which starts small and increases up to the
+  * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
+  * scan that stops after a few tuples because of a LIMIT.
+  */
+static void
+BitmapHeapInitialize(BitmapHeapScanState *node)
+{
+	Relation	rel = node->ss.ss_currentRelation;
+	bool		pf_maximum = 0;
+	bool		init_shared_state = false;
+	uint32		extra_flags = 0;
+
+	Assert(!node->initialized);
+
+	/*
+	 * The leader will immediately come out of the function, but others will
+	 * be blocked until leader populates the TBM and wakes them up.
+	 */
+	init_shared_state = node->pstate ?
+		BitmapShouldInitializeSharedState(node->pstate) : false;
+
+	/*
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
+	 */
+#ifdef USE_PREFETCH
+	pf_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
+	if (!node->pstate || init_shared_state)
+	{
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+
+		if (init_shared_state)
+		{
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			node->pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+
+#ifdef USE_PREFETCH
+			if (pf_maximum > 0)
+			{
+				node->pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(node->tbm);
+			}
+#endif
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(node->pstate);
+		}
+	}
+
+	/*
+	 * We can potentially skip fetching heap pages if we do not need any
+	 * columns of the table, either for checking non-indexable quals or for
+	 * returning data.  This test is a bit simplistic, as it checks the
+	 * stronger condition that there's no qual or return tlist at all. But in
+	 * most cases it's probably not worth working harder than that.
+	 */
+	if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+		extra_flags |= SO_NEED_TUPLE;
+
+	node->ss.ss_currentScanDesc = table_beginscan_bm(node->ss.ss_currentScanDesc,
+													 rel,
+													 node->ss.ps.state->es_snapshot,
+													 extra_flags,
+													 pf_maximum,
+													 node->tbm,
+													 node->pstate,
+													 node->ss.ps.state->es_query_dsa);
+
+	node->initialized = true;
+}
+
+
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -124,88 +212,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
+	 * the iteration over the bitmap. This happens on rescan as well.
 	 */
 	if (!node->initialized)
 	{
-		Relation	rel = node->ss.ss_currentRelation;
-		bool		pf_maximum = 0;
-		bool		init_shared_state = false;
-		uint32		extra_flags = 0;
-
-		/*
-		 * The leader will immediately come out of the function, but others
-		 * will be blocked until leader populates the TBM and wakes them up.
-		 */
-		init_shared_state = node->pstate ?
-			BitmapShouldInitializeSharedState(node->pstate) : false;
-
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-#endif
-
-		if (!node->pstate || init_shared_state)
-		{
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-
-			if (init_shared_state)
-			{
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				node->pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
-
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					node->pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(node->tbm);
-				}
-#endif
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(node->pstate);
-			}
-		}
-
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
-			extra_flags |= SO_NEED_TUPLE;
-
-		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
-								  rel,
-								  node->ss.ps.state->es_snapshot,
-								  extra_flags,
-								  pf_maximum,
-								  node->tbm,
-								  node->pstate,
-								  node->ss.ps.state->es_query_dsa);
-
-		node->ss.ss_currentScanDesc = scan;
-		node->initialized = true;
+		BitmapHeapInitialize(node);
 
+		/* We may have a new scan descriptor */
+		scan = node->ss.ss_currentScanDesc;
 		goto new_page;
 	}
 
-- 
2.40.1

v15-0013-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From 869023793654571cba6af0ccfd2fac9950ccc635 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 22 Mar 2024 15:43:10 -0400
Subject: [PATCH v15 13/13] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block().

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 48 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 61 +++++++++----------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 74 +++++------------------
 6 files changed, 73 insertions(+), 116 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a21ec92d71..9c98109a16 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -324,6 +324,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c513cbd2da..d7f3bb960f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2183,12 +2183,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
- */
-
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
  *
@@ -2222,8 +2216,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->prefetch_maximum > 0)
 	{
@@ -2583,9 +2577,15 @@ BitmapPrefetch(BitmapHeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = &bscan->heap_common;
@@ -2593,21 +2593,28 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
-	if (bscan->empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->empty_tuples_pending--;
-		return true;
-	}
+		if (bscan->empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -3008,7 +3015,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 55b8caeadf..0b87530a9c 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -90,8 +90,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index aaeece6697..48086aae1d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -206,58 +206,53 @@ BitmapHeapInitialize(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext = node->ss.ps.ps_ExprContext;
-	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
-	TableScanDesc scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext;
+	TupleTableSlot *slot;
+	TableScanDesc scan;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap. This happens on rescan as well.
 	 */
 	if (!node->initialized)
-	{
 		BitmapHeapInitialize(node);
 
-		/* We may have a new scan descriptor */
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
+	/*
+	 * BitmapHeapInitialize() may make the scan descriptor so don't get it
+	 * from the node until after calling it.
+	 */
+	econtext = node->ss.ps.ps_ExprContext;
+	slot = node->ss.ss_ScanTupleSlot;
+	scan = node->ss.ss_currentScanDesc;
 
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346..cf56cc572f 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 138bf5f6ed..e4d0c4b0ed 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -790,34 +790,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples as part of a bitmap table
-	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
-	 * bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the bitmap is lossy for the selected
-	 * block; otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   long *lossy_pages, long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1980,45 +1966,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented is the block's representation in the bitmap is lossy; otherwise,
- * exact_pages is incremented.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 bool *recheck,
-							 long *lossy_pages,
-							 long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages, exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2029,7 +1983,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

#99Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#98)
18 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Apr 05, 2024 at 04:06:34AM -0400, Melanie Plageman wrote:

On Thu, Apr 04, 2024 at 04:35:45PM +0200, Tomas Vondra wrote:

On 4/4/24 00:57, Melanie Plageman wrote:

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

On Fri, Mar 29, 2024 at 12:05:15PM +0100, Tomas Vondra wrote:

On 3/29/24 02:12, Thomas Munro wrote:

On Fri, Mar 29, 2024 at 10:43 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

Thanks for the repro. I can't seem to reproduce it (still trying) but
I assume this is with Melanie's v11 patch set which had
v11-0016-v10-Read-Stream-API.patch.

Would you mind removing that commit and instead applying the v13
stream_read.c patches[1]? v10 stream_read.c was a little confused
about random I/O combining, which I fixed with a small adjustment to
the conditions for the "if" statement right at the end of
read_stream_look_ahead(). Sorry about that. The fixed version, with
eic=4, with your test query using WHERE a < a, ends its scan with:

I'll give that a try. Unfortunately unfortunately the v11 still has the
problem I reported about a week ago:

ERROR: prefetch and main iterators are out of sync

So I can't run the full benchmarks :-( but master vs. streaming read API
should work, I think.

Odd, I didn't notice you reporting this ERROR popping up. Now that I
take a look, v11 (at least, maybe also v10) had this very sill mistake:

  if (scan->bm_parallel == NULL &&
      scan->rs_pf_bhs_iterator &&
      hscan->pfblockno > hscan->rs_base.blockno)
       elog(ERROR, "prefetch and main iterators are out of sync");

It errors out if the prefetch block is ahead of the current block --
which is the opposite of what we want. I've fixed this in attached v12.

This version also has v13 of the streaming read API. I noticed one
mistake in my bitmapheap scan streaming read user -- it freed the
streaming read object at the wrong time. I don't know if this was
causing any other issues, but it at least is fixed in this version.

Attached v13 is rebased over master (which includes the streaming read
API now). I also reset the streaming read object on rescan instead of
creating a new one each time.

I don't know how much chance any of this has of going in to 17 now, but
I thought I would start looking into the regression repro Tomas provided
in [1].

My personal opinion is that we should try to get in as many of the the
refactoring patches as possible, but I think it's probably too late for
the actual switch to the streaming API.

Cool. In the attached v15, I have dropped all commits that are related
to the streaming read API and included *only* commits that are
beneficial to master. A few of the commits are merged or reordered as
well.

While going through the commits with this new goal in mind (forget about
the streaming read API for now), I realized that it doesn't make much
sense to just eliminate the layering violation for the current block and
leave it there for the prefetch block. I had de-prioritized solving this
when I thought we would just delete the prefetch code and replace it
with the streaming read.

Now that we aren't doing that, I've spent the day trying to resolve the
issues with pushing the prefetch code into heapam.c that I cited in [1].
0010 - 0013 are the result of this. They are not very polished yet and
need more cleanup and review (especially 0011, which is probably too
large), but I am happy with the solution I came up with.

Basically, there are too many members needed for bitmap heap scan to put
them all in the HeapScanDescData (don't want to bloat it). So, I've made
a new BitmapHeapScanDescData and associated begin/rescan/end() functions

In the end, with all patches applied, BitmapHeapNext() loops invoking
table_scan_bitmap_next_tuple() and table AMs can implement that however
they choose.

I'm also not sure if I should try and group the commits into fewer
commits now or wait until I have some idea of whether or not the
approach in 0013 and 0014 is worth pursuing.

You mean whether to pursue the approach in general, or for v17? I think
it looks like the right approach, but for v17 see above :-(

As for merging, I wouldn't do that. I looked at the commits and while
some of them seem somewhat "trivial", I really like how you organized
the commits, and kept those that just "move" code around, and those that
actually change stuff. It's much easier to understand, IMO.

I went through the first ~10 commits, and added some review - either as
a separate commit, when possible, in the code as XXX comment, and also
in the commit message. The code tweaks are utterly trivial (whitespace
or indentation to make the line shorter). It shouldn't take much time to
deal with those, I think.

Attached v15 incorporates your v14-0002-review.

For your v14-0008-review, I actually ended up removing that commit
because once I removed everything that was for streaming read API, it
became redundant with another commit.

For your v14-0010-review, we actually can't easily get rid of those
local variables because we make the iterators before we make the scan
descriptors and the commit following that commit moves the iterators
from the BitmapHeapScanState to the scan descriptor.

I think the main focus should be updating the commit messages. If it was
only a single patch, I'd probably try to write the messages myself, but
with this many patches it'd be great if you could update those and I'll
review that before commit.

I did my best to update the commit messages to be less specific and more
focused on "why should I care". I found myself wanting to explain why I
implemented something the way I did and then getting back into the
implementation details again. I'm not sure if I suceeded in having less
details and more substance.

I always struggle with writing commit messages myself, and it takes me
ages to write a good one (well, I think the message is good, but who
knows ...). But I think a good message should be concise enough to
explain what and why it's done. It may reference a thread for all the
gory details, but the basic reasoning should be in the commit message.
For example the message for "BitmapPrefetch use prefetch block recheck
for skip fetch" now says that it "makes more sense to do X" but does not
really say why that's the case. The linked message does, but it'd be
good to have that in the message (because how would I know how much of
the thread to read?).

I fixed that particular one. I tried to take that feedback and apply it
to other commit messages. I don't know how successful I was...

Also, it'd be very helpful if you could update the author & reviewed-by
fields. I'll review those before commit, ofc, but I admit I lost track
of who reviewed which part.

I have updated reviewers. I didn't add reviewers on the ones that
haven't really been reviewed yet.

I'd focus on the first ~8-9 commits or so for now, we can commit more if
things go reasonably well.

Sounds good. I will spend cleanup time on 0010-0013 tomorrow but would
love to know if you agree with the direction before I spend more time.

In attached v16, I've split out 0010-0013 into 0011-0017. I think it is
much easier to understand.

While I was doing that, I realized that I should remove the call to
table_rescan() from ExecReScanBitmapHeapScan() and just rely on the new
table_rescan_bm() invoked from BitmapHeapNext(). That is done in the
attached.

0010-0018 still need comments updated but I focused on getting the split
out, reviewable version of them ready. I'll add comments (especially to
0011 table AM functions) tomorrow. I also have to double-check if I
should add any asserts for table AMs about having implemented all of the
new begin/re/endscan() functions.

- Melanie

Attachments:

v16-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From c6ebe66dcf5ff961ef3d2c66a26b21d2246a499b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v16 01/18] BitmapHeapScan begin scan after bitmap creation

It makes more sense for BitmapHeapScan to scan the index, build the
bitmap, and then begin the scan on the underlying table.

This is primarily a cosmetic change for now, but later commits will pass
parameters to table_beginscan_bm() that are unavailable in
ExecInitBitmapHeapScan().

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 27 +++++++++++++++++------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aab..c8c466e3c5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = table_beginscan_bm(node->ss.ss_currentRelation,
+									  node->ss.ps.state->es_snapshot,
+									  0,
+									  NULL);
+
+			node->ss.ss_currentScanDesc = scan;
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +616,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +694,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +801,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v16-0002-BitmapHeapScan-set-can_skip_fetch-later.patchtext/x-diff; charset=us-asciiDownload
From 770bf2e20dfd3c29c5fc4937d78ec2e26d3f78d4 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v16 02/18] BitmapHeapScan set can_skip_fetch later

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() instead of
in ExecInitBitmapHeapScan(). This is a preliminary step to pushing the
skip fetch optimization into heap AM code.

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c8c466e3c5..2148a21531 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -743,16 +753,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v16-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From c5d36fc7f201d8e01f68a00b235872165fd0ec94 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:34:25 +0200
Subject: [PATCH v16 03/18] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM-specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block. The layering violation is
still present in BitmapHeapScans's prefetching code, which uses the
visibility map to decide whether or not to prefetch a block. However,
this will be fixed in an upcoming commit.

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  14 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 102 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index dada2ecd1e..10f2faaa60 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -967,6 +967,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1055,6 +1057,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1074,6 +1082,12 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3e7a6b5548..929b2cf8e7 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2198,6 +2199,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2310,6 +2329,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2148a21531..a8bc5dec53 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,10 +185,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			uint32		extra_flags = 0;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+				extra_flags |= SO_NEED_TUPLE;
+
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
 									  0,
-									  NULL);
+									  NULL,
+									  extra_flags);
 
 			node->ss.ss_currentScanDesc = scan;
 		}
@@ -208,7 +212,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -229,37 +233,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -302,52 +283,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -519,7 +481,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -570,7 +532,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -640,8 +602,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -651,7 +611,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -696,8 +655,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -741,8 +698,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -753,7 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2765efc4e5..750ea30852 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,6 +76,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e7eeb75409..55f1139757 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -63,6 +63,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -937,9 +944,9 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e57ebd7288..fa2f70b7a4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,10 +1794,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1817,9 +1814,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v16-0004-BitmapPrefetch-use-prefetch-block-recheck-for-sk.patchtext/x-diff; charset=us-asciiDownload
From 796e139454a8863c12235d248d76f313da6ef002 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v16 04/18] BitmapPrefetch use prefetch block recheck for skip
 fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it could skip prefetching
the proposed prefetch block. This doesn't seem right. We should use the
prefetch block's recheck flag to determine whether or not to prefetch
it. The current block's recheck flag has no relationship to the prefetch
block's recheck flag. See this [1] thread on hackers reporting the
issue.

[1] https://www.postgresql.org/message-id/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a8bc5dec53..2e2cec8b3b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -475,14 +475,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -533,7 +528,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v16-0005-Update-BitmapAdjustPrefetchIterator-parameter-ty.patchtext/x-diff; charset=us-asciiDownload
From 2f9abb4c09528925060b7613fe7d3e52d04d8bea Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v16 05/18] Update BitmapAdjustPrefetchIterator parameter type
 to BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only. This will
allow us to move away from using the TBMIterateResult outside of table
AM specific code.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2e2cec8b3b..795a893035 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -231,7 +231,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -342,7 +342,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -361,7 +361,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v16-0006-Reduce-scope-of-BitmapHeapScan-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From d5b31a8d8e73fc332748856e3bcb52654d3b134e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v16 06/18] Reduce scope of BitmapHeapScan tbmiterator local
 variables

A future patch will change where tbmiterators are initialized and saved.
To simplify that diff, move them into a tighter scope.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 795a893035..8403be84f3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -207,6 +203,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -222,9 +220,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v16-0007-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From b0043ddcc0a4d18746f80aa90c3b6dc32304b92f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 26 Feb 2024 20:34:07 -0500
Subject: [PATCH v16 07/18] table_scan_bitmap_next_block counts lossy and exact
 pages

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So the table AM must keep
track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap for the purposes of EXPLAIN counters.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 13 +++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 929b2cf8e7..b5ab104ec2 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2316,6 +2317,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 8403be84f3..68f9ded168 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -210,8 +210,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -231,19 +229,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
 			}
 
+
 			/* Adjust the prefetch target */
 			BitmapAdjustPrefetchTarget(node);
 		}
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 55f1139757..e2ad8d0728 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,6 +789,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy_pages is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, exact_pages is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -804,7 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1968,17 +1972,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy_pages is incremented is the block's
+ * representation in the bitmap is lossy; otherwise, exact_pages is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1989,7 +1997,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v16-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From faa5a08e645c7635a38e3e31a58c0aed10418c6b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v16 08/18] Remove table_scan_bitmap_next_tuple parameter
 tbmres

Future commits will push all of the logic for choosing the next block
into the table AM specific code. The table AM will be responsible for
iterating and reading in the right blocks.

Thus, it no longer makes sense to use the TBMIterateResult (which
contains a block number) as a means of communication between
table_scan_bitmap_next_tuple() and table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b5ab104ec2..efd1a66a09 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2327,7 +2327,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 68f9ded168..951a98c101 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -280,7 +280,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e2ad8d0728..2efa97f602 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,10 +780,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -814,15 +811,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2012,7 +2004,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2024,7 +2015,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v16-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From f22e1320d1746afad905f169dcf4002a9f164f7e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 14 Mar 2024 12:39:28 -0400
Subject: [PATCH v16 09/18] Make table_scan_bitmap_next_block() async friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on the tuples on the page.
This could happen when there were no visible tuples on the page or, due
to concurrent activity on the table, the block returned by the iterator
is past the end of the table recorded when the scan started.

This forced the caller to be responsible for determining if additional
blocks should be fetched and then for invoking
table_scan_bitmap_next_block() for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
time that the scan began) and for table_scan_bitmap_next_tuple() to
return false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to the
table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  58 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 186 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 190 insertions(+), 141 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index efd1a66a09..9d3e7c7fda 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,18 +2188,52 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2218,16 +2252,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2322,7 +2347,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 951a98c101..e1b13ddaa6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,7 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +160,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -203,48 +198,19 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
+
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+			CHECK_FOR_INTERRUPTS();
 
 #ifdef USE_PREFETCH
 
@@ -266,45 +232,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -330,13 +307,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -350,14 +331,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -382,7 +366,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -460,6 +447,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -517,6 +505,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -578,12 +568,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -591,13 +577,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -628,28 +614,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -682,8 +664,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -691,9 +671,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304a..92b829cebc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2efa97f602..42c67a128e 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -773,19 +774,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
@@ -804,7 +800,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -942,9 +938,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -991,6 +991,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1001,6 +1016,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1964,19 +1994,18 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy_pages is incremented is the block's
- * representation in the bitmap is lossy; otherwise, exact_pages is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented is the block's representation in the bitmap is lossy; otherwise,
+ * exact_pages is incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1989,9 +2018,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fa2f70b7a4..d96703b04d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v16-0010-Unify-parallel-and-serial-BitmapHeapScan-iterato.patchtext/x-diff; charset=us-asciiDownload
From afb28afbf45efbdd9fa4992a3dc1f1fe7f07afd3 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 25 Mar 2024 11:05:51 -0400
Subject: [PATCH v16 10/18] Unify parallel and serial BitmapHeapScan iterator
 interfaces

Introduce a new type, BitmapHeapIterator, which allows unified access to both
TBMIterator and TBMSharedIterators. This encapsulates the parallel and serial
iterators and their access and makes the bitmap heap scan code a bit cleaner.
This naturally lends itself to a bit of reorganization of the
!node->initialized path in BitmapHeapNext().

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 172 ++++++++++++----------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  40 +----
 src/include/executor/nodeBitmapHeapscan.h |   7 +
 src/include/nodes/execnodes.h             |  13 +-
 src/tools/pgindent/typedefs.list          |   1 +
 7 files changed, 124 insertions(+), 121 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 9d3e7c7fda..5e57d19d91 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2208,10 +2208,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		tbmres = bhs_iterate(&scan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e1b13ddaa6..70b560b8ee 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -57,6 +57,61 @@ static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
+/*
+ * Start iteration on a shared or non-shared bitmap iterator. Note that tbm
+ * will only be provided by serial BitmapHeapScan callers. dsa and dsp will
+ * only be provided by parallel BitmapHeapScan callers.
+ */
+void
+bhs_begin_iterate(BitmapHeapIterator *iterator, TIDBitmap *tbm,
+				  dsa_area *dsa, dsa_pointer dsp)
+{
+	Assert(iterator);
+
+	iterator->serial = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = false;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+		iterator->parallel = tbm_attach_shared_iterate(dsa, dsp);
+	else
+		iterator->serial = tbm_begin_iterate(tbm);
+}
+
+/*
+ * Get the next TBMIterateResult from the bitmap iterator.
+ */
+TBMIterateResult *
+bhs_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+	Assert(!iterator->exhausted);
+
+	if (iterator->serial)
+		return tbm_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
+
+/*
+ * Clean up the bitmap iterator.
+ */
+void
+bhs_end_iterate(BitmapHeapIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		tbm_end_iterate(iterator->serial);
+	else if (iterator->parallel)
+		tbm_end_shared_iterate(iterator->parallel);
+
+	iterator->serial = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = true;
+}
+
 
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
@@ -96,43 +151,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate)
+		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (init_shared_state)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
@@ -153,21 +188,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 					pstate->prefetch_target = -1;
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
 			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -198,8 +221,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		bhs_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
+						  pstate ?
+						  pstate->tbmiterator :
+						  InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			bhs_begin_iterate(&node->pf_iterator, tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+			/* Only used for serial BHS */
+			node->prefetch_pages = 0;
+			node->prefetch_target = -1;
+		}
+#endif							/* USE_PREFETCH */
 
 		node->initialized = true;
 
@@ -276,7 +314,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!node->pf_iterator.exhausted &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -317,21 +355,20 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = bhs_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -344,8 +381,6 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -365,9 +400,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -427,23 +462,21 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -471,9 +504,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (1)
 			{
@@ -496,12 +527,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = bhs_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					bhs_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -568,18 +598,14 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	if (node->pf_iterator.exhausted)
+		bhs_end_iterate(&node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -624,12 +650,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+	if (!node->pf_iterator.exhausted)
+		bhs_end_iterate(&node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -667,11 +691,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc..e520186b41 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,13 +20,11 @@
 #include "storage/buf.h"
 #include "storage/spin.h"
 #include "utils/relcache.h"
+#include "executor/nodeBitmapHeapscan.h"
 
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -44,8 +42,7 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	BitmapHeapIterator rs_bhs_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 42c67a128e..618ab2b449 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -938,13 +938,9 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
 /*
@@ -991,20 +987,9 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
+		!scan->rs_bhs_iterator.exhausted)
+		bhs_end_iterate(&scan->rs_bhs_iterator);
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
@@ -1016,20 +1001,9 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
+		!scan->rs_bhs_iterator.exhausted)
+		bhs_end_iterate(&scan->rs_bhs_iterator);
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index ea003a9caa..7064f54686 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -29,4 +29,11 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
 
+extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
+extern void bhs_begin_iterate(BitmapHeapIterator *iterator, TIDBitmap *tbm,
+							  dsa_area *dsa, dsa_pointer dsp);
+
+extern void bhs_end_iterate(BitmapHeapIterator *iterator);
+
+
 #endif							/* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d96703b04d..714eb3e534 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1787,6 +1787,13 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+	bool		exhausted;
+} BitmapHeapIterator;
+
 /* ----------------
  *	 BitmapHeapScanState information
  *
@@ -1795,12 +1802,11 @@ typedef struct ParallelBitmapHeapState
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
+ *		pf_iterator        for prefetching ahead of current page
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1815,12 +1821,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	BitmapHeapIterator pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 01845ee71d..848ce9b30c 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -259,6 +259,7 @@ BitString
 BitmapAnd
 BitmapAndPath
 BitmapAndState
+BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
-- 
2.40.1

v16-0011-Add-BitmapHeapScanDesc-and-scan-functions.patchtext/x-diff; charset=us-asciiDownload
From eac4e11efc7c19091b8076f6193b90aa3989b19e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 19:30:43 -0400
Subject: [PATCH v16 11/18] Add BitmapHeapScanDesc and scan functions

Future commits will push all prefetching related code into the heap AM
to eliminate a layering violation. Move all of the members used to
manage prefetching for bitmap heap scan from the BitmapHeapScanState
into a new scan descriptor BitmapHeapScanDesc.

With this new scan descriptor, add all of the relevant functions for
beginning, rescanning, and ending a bitmap heap scan. There is a lot of
bitmap-specific logic to do there now, so it makes sense for bitmap heap
scan to have its own.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          | 98 +++++++++++++++++++----
 src/backend/access/heap/heapam_handler.c  | 42 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 47 +++++------
 src/include/access/heapam.h               | 36 ++++++---
 src/include/access/tableam.h              | 45 +++++++++--
 src/tools/pgindent/typedefs.list          |  1 +
 6 files changed, 193 insertions(+), 76 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 10f2faaa60..82faf447e9 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -13,8 +13,11 @@
  *
  * INTERFACE ROUTINES
  *		heap_beginscan	- begin relation scan
+ *		heap_beginscan_bm - begin bitmap heap scan
  *		heap_rescan		- restart a relation scan
+ *		heap_rescan_bm  - restart a bitmap heap scan
  *		heap_endscan	- end relation scan
+ *		heap_endscan_bm - end a bitmap heap scan
  *		heap_getnext	- retrieve next tuple in scan
  *		heap_fetch		- retrieve tuple with given tid
  *		heap_insert		- insert tuple into a relation
@@ -938,6 +941,43 @@ continue_page:
  * ----------------------------------------------------------------
  */
 
+TableScanDesc
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+{
+	BitmapHeapScanDesc scan;
+
+	/*
+	 * increment relation ref count while scanning relation
+	 *
+	 * This is just to make really sure the relcache entry won't go away while
+	 * the scan has a pointer to it.  Caller should be holding the rel open
+	 * anyway, so this is redundant in all normal scenarios...
+	 */
+	RelationIncrementReferenceCount(relation);
+	scan = (BitmapHeapScanDesc) palloc(sizeof(BitmapHeapScanDescData));
+
+	scan->heap_common.rs_base.rs_rd = relation;
+	scan->heap_common.rs_base.rs_snapshot = snapshot;
+	scan->heap_common.rs_base.rs_nkeys = 0;
+	scan->heap_common.rs_base.rs_flags = flags;
+	scan->heap_common.rs_base.rs_parallel = NULL;
+	scan->heap_common.rs_strategy = NULL;
+
+	Assert(snapshot && IsMVCCSnapshot(snapshot));
+
+	/* we only need to set this up once */
+	scan->heap_common.rs_ctup.t_tableOid = RelationGetRelid(relation);
+
+	scan->heap_common.rs_parallelworkerdata = NULL;
+	scan->heap_common.rs_base.rs_key = NULL;
+
+	initscan(&scan->heap_common, NULL, false);
+
+	scan->vmbuffer = InvalidBuffer;
+
+	return (TableScanDesc) scan;
+}
+
 
 TableScanDesc
 heap_beginscan(Relation relation, Snapshot snapshot,
@@ -967,8 +1007,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1026,6 +1064,29 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	return (TableScanDesc) scan;
 }
 
+/*
+ * Cleanup BitmapHeapScan table state
+ */
+void
+heap_endscan_bm(TableScanDesc sscan)
+{
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+
+	if (BufferIsValid(scan->heap_common.rs_cbuf))
+		ReleaseBuffer(scan->heap_common.rs_cbuf);
+
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+
+	/*
+	 * decrement relation reference count and free scan descriptor storage
+	 */
+	RelationDecrementReferenceCount(scan->heap_common.rs_base.rs_rd);
+
+	pfree(scan);
+}
+
+
 void
 heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			bool allow_strat, bool allow_sync, bool allow_pagemode)
@@ -1057,12 +1118,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1082,12 +1137,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
@@ -1334,6 +1383,27 @@ heap_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction,
 	return true;
 }
 
+void
+heap_rescan_bm(TableScanDesc sscan)
+{
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+
+	if (BufferIsValid(scan->heap_common.rs_cbuf))
+		ReleaseBuffer(scan->heap_common.rs_cbuf);
+
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+	scan->vmbuffer = InvalidBuffer;
+
+	scan->empty_tuples_pending = 0;
+
+	/*
+	 * reinitialize heap scan descriptor
+	 */
+	initscan(&scan->heap_common, NULL, true);
+}
+
+
 /*
  *	heap_fetch		- retrieve tuple with given tid
  *
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 5e57d19d91..43721cbd42 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2187,11 +2187,12 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_block(TableScanDesc sscan,
 							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+	HeapScanDesc hscan = &scan->heap_common;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2208,12 +2209,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = bhs_iterate(&scan->rs_bhs_iterator);
+		tbmres = bhs_iterate(&sscan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
 			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
+			Assert(scan->empty_tuples_pending == 0);
 			return false;
 		}
 
@@ -2236,15 +2237,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+	if (!(hscan->rs_base.rs_flags & SO_NEED_TUPLE) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(hscan->rs_base.rs_rd, tbmres->blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(scan->empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2255,18 +2256,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
 	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
+										  hscan->rs_base.rs_rd,
 										  block);
 	hscan->rs_cblock = block;
 	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
+	snapshot = hscan->rs_base.rs_snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
+	heap_page_prune_opt(hscan->rs_base.rs_rd, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2294,7 +2295,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, hscan->rs_base.rs_rd, buffer, snapshot,
 									   &heapTuple, NULL, true))
 				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
@@ -2320,16 +2321,16 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
+			loctup.t_tableOid = hscan->rs_base.rs_rd->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
 				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+				PredicateLockTID(hscan->rs_base.rs_rd, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+			HeapCheckForSerializableConflictOut(valid, hscan->rs_base.rs_rd, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2358,18 +2359,19 @@ static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = &bscan->heap_common;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (bscan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		bscan->empty_tuples_pending--;
 		return true;
 	}
 
@@ -2704,6 +2706,10 @@ static const TableAmRoutine heapam_methods = {
 	.scan_set_tidrange = heap_set_tidrange,
 	.scan_getnextslot_tidrange = heap_getnextslot_tidrange,
 
+	.scan_rescan_bm = heap_rescan_bm,
+	.scan_begin_bm = heap_beginscan_bm,
+	.scan_end_bm = heap_endscan_bm,
+
 	.parallelscan_estimate = table_block_parallelscan_estimate,
 	.parallelscan_initialize = table_block_parallelscan_initialize,
 	.parallelscan_reinitialize = table_block_parallelscan_reinitialize,
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 70b560b8ee..0b28c46d08 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -151,6 +151,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		uint32		extra_flags = 0;
+
 		/*
 		 * The leader will immediately come out of the function, but others
 		 * will be blocked until leader populates the TBM and wakes them up.
@@ -193,33 +195,26 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 		}
 
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+			extra_flags |= SO_NEED_TUPLE;
+
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
 		 */
-		if (!scan)
-		{
-			uint32		extra_flags = 0;
+		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
+								  node->ss.ss_currentRelation,
+								  node->ss.ps.state->es_snapshot,
+								  extra_flags);
 
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
-				extra_flags |= SO_NEED_TUPLE;
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
-									  extra_flags);
-
-			node->ss.ss_currentScanDesc = scan;
-		}
+		node->ss.ss_currentScanDesc = scan;
 
 		bhs_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
 						  pstate ?
@@ -593,10 +588,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* rescan to release any page pin */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
-
 	/* release bitmaps and buffers if any */
 	if (node->pf_iterator.exhausted)
 		bhs_end_iterate(&node->pf_iterator);
@@ -642,10 +633,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 
 
 	/*
-	 * close heap scan
+	 * close bitmapheap scan
 	 */
 	if (scanDesc)
-		table_endscan(scanDesc);
+		table_endscan_bm(scanDesc);
 
 	/*
 	 * release bitmaps and buffers if any
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 750ea30852..545760aab5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,22 +76,35 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+
+typedef struct BitmapHeapScanDescData
+{
+	/* All the non-BitmapHeapScan specific members */
+	HeapScanDescData heap_common;
+
+	/*
+	 * Members common to Parallel and Serial BitmapHeapScan
+	 */
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
-	Buffer		rs_vmbuffer;
-	int			rs_empty_tuples_pending;
+	Buffer		vmbuffer;
+	int			empty_tuples_pending;
+}			BitmapHeapScanDescData;
 
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
@@ -289,6 +302,11 @@ extern void heap_set_tidrange(TableScanDesc sscan, ItemPointer mintid,
 extern bool heap_getnextslot_tidrange(TableScanDesc sscan,
 									  ScanDirection direction,
 									  TupleTableSlot *slot);
+extern TableScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags);
+
+extern void heap_endscan_bm(TableScanDesc scan);
+extern void heap_rescan_bm(TableScanDesc sscan);
+
 extern bool heap_fetch(Relation relation, Snapshot snapshot,
 					   HeapTuple tuple, Buffer *userbuf, bool keep_buf);
 extern bool heap_hot_search_buffer(ItemPointer tid, Relation relation,
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 618ab2b449..3b0fa0610b 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -391,6 +391,21 @@ typedef struct TableAmRoutine
 											  ScanDirection direction,
 											  TupleTableSlot *slot);
 
+	/*
+	 * TODO: add comment
+	 */
+	TableScanDesc (*scan_begin_bm) (Relation rel,
+									Snapshot snapshot,
+									uint32 flags);
+
+	void		(*scan_rescan_bm) (TableScanDesc scan);
+
+	/*
+	 * Release resources and deallocate scan. If TableScanDesc.temp_snap,
+	 * TableScanDesc.rs_snapshot needs to be unregistered.
+	 */
+	void		(*scan_end_bm) (TableScanDesc scan);
+
 	/* ------------------------------------------------------------------------
 	 * Parallel table scan related functions.
 	 * ------------------------------------------------------------------------
@@ -929,18 +944,34 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 }
 
 /*
- * table_beginscan_bm is an alternative entry point for setting up a
- * TableScanDesc for a bitmap heap scan.  Although that scan technology is
- * really quite unlike a standard seqscan, there is just enough commonality to
- * make it worth using the same data structure.
+ * table_beginscan_bm is the entry point for setting up a TableScanDesc for a
+ * bitmap heap scan.
  */
 static inline TableScanDesc
-table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, uint32 extra_flags)
+table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
+				   uint32 extra_flags)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!scan)
+		scan = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
+
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+
+	return scan;
+}
+
+/*
+ * End Bitmap Table Scan
+ */
+static inline void
+table_endscan_bm(TableScanDesc scan)
+{
+	scan->rs_rd->rd_tableam->scan_end_bm(scan);
 }
 
 /*
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 848ce9b30c..8369c15a82 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -263,6 +263,7 @@ BitmapHeapIterator
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanState
+BitmapHeapScanDesc
 BitmapIndexScan
 BitmapIndexScanState
 BitmapOr
-- 
2.40.1

v16-0012-BitmapHeapScan-initialize-some-prefetch-state-el.patchtext/x-diff; charset=us-asciiDownload
From ad2395adba28db8d1bbf0f87c64bf619367d48b9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 17:38:36 -0400
Subject: [PATCH v16 12/18] BitmapHeapScan initialize some prefetch state
 elsewhere

These members can be initialized elsewhere. This makes the diff more
straightforward for moving those members from BitmapHeapScanState to
BitmapHeapScanDesc.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 0b28c46d08..4f7138bbd9 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -181,13 +181,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				{
 					pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
 				/* We have initialized the shared state so wake up others. */
@@ -228,9 +221,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 							  pstate ?
 							  pstate->prefetch_iterator :
 							  InvalidDsaPointer);
-			/* Only used for serial BHS */
-			node->prefetch_pages = 0;
-			node->prefetch_target = -1;
 		}
 #endif							/* USE_PREFETCH */
 
@@ -601,6 +591,9 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
 	node->pfblockno = InvalidBlockNumber;
+	/* Only used for serial BHS */
+	node->prefetch_pages = 0;
+	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -683,7 +676,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
 	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
+	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
@@ -818,7 +811,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
-- 
2.40.1

v16-0013-BitmapHeapScan-begin-iteration-in-rescan.patchtext/x-diff; charset=us-asciiDownload
From d16551c7330822ccd0132565773ceab7569aa6b5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 17:48:08 -0400
Subject: [PATCH v16 13/18] BitmapHeapScan begin iteration in rescan

Now that BitmapHeapScan has its own dedicated rescan function, it is
easy to begin iteration there instead. Doing this in heap AM code will
allow us to move the current block iterator from the TableScanDesc to
the BitmapHeapScanDesc.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 ++++------
 src/include/access/heapam.h               |  3 ++-
 src/include/access/tableam.h              |  8 +++++---
 4 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 82faf447e9..a876a34b74 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1384,7 +1384,8 @@ heap_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction,
 }
 
 void
-heap_rescan_bm(TableScanDesc sscan)
+heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
+			   ParallelBitmapHeapState *pstate, dsa_area *dsa)
 {
 	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
 
@@ -1401,6 +1402,11 @@ heap_rescan_bm(TableScanDesc sscan)
 	 * reinitialize heap scan descriptor
 	 */
 	initscan(&scan->heap_common, NULL, true);
+
+	bhs_begin_iterate(&scan->heap_common.rs_base.rs_bhs_iterator, tbm, dsa,
+					  pstate ?
+					  pstate->tbmiterator :
+					  InvalidDsaPointer);
 }
 
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 4f7138bbd9..f8627991d0 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -205,15 +205,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
 								  node->ss.ss_currentRelation,
 								  node->ss.ps.state->es_snapshot,
-								  extra_flags);
+								  extra_flags,
+								  node->tbm,
+								  node->pstate,
+								  node->ss.ps.state->es_query_dsa);
 
 		node->ss.ss_currentScanDesc = scan;
 
-		bhs_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
-						  pstate ?
-						  pstate->tbmiterator :
-						  InvalidDsaPointer);
-
 #ifdef USE_PREFETCH
 		if (node->prefetch_maximum > 0)
 		{
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 545760aab5..7b44c94d29 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -305,7 +305,8 @@ extern bool heap_getnextslot_tidrange(TableScanDesc sscan,
 extern TableScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags);
 
 extern void heap_endscan_bm(TableScanDesc scan);
-extern void heap_rescan_bm(TableScanDesc sscan);
+extern void heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
+						   ParallelBitmapHeapState *pstate, dsa_area *dsa);
 
 extern bool heap_fetch(Relation relation, Snapshot snapshot,
 					   HeapTuple tuple, Buffer *userbuf, bool keep_buf);
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 3b0fa0610b..d02f5055b0 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -398,7 +398,8 @@ typedef struct TableAmRoutine
 									Snapshot snapshot,
 									uint32 flags);
 
-	void		(*scan_rescan_bm) (TableScanDesc scan);
+	void		(*scan_rescan_bm) (TableScanDesc scan, TIDBitmap *tbm,
+								   ParallelBitmapHeapState *pstate, dsa_area *dsa);
 
 	/*
 	 * Release resources and deallocate scan. If TableScanDesc.temp_snap,
@@ -949,7 +950,8 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
-				   uint32 extra_flags)
+				   uint32 extra_flags, TIDBitmap *tbm,
+				   ParallelBitmapHeapState *pstate, dsa_area *dsa)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
 
@@ -960,7 +962,7 @@ table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
 	if (!scan)
 		scan = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 
-	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa);
 
 	return scan;
 }
-- 
2.40.1

v16-0014-Move-BitmapHeapScan-current-block-iterator-to-Bi.patchtext/x-diff; charset=us-asciiDownload
From 91b04fc00567fe4395c9820eb95e7ee3e10af2ae Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 18:05:02 -0400
Subject: [PATCH v16 14/18] Move BitmapHeapScan current block iterator to
 BitmapHeapScanDesc

After beginning iteration in heap AM code, we can move the current block
iterator into the BitmapHeapScanDesc and take it out of the generic
TableScanDesc.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c         | 9 ++++++++-
 src/backend/access/heap/heapam_handler.c | 2 +-
 src/include/access/heapam.h              | 1 +
 src/include/access/relscan.h             | 3 ---
 src/include/access/tableam.h             | 8 --------
 5 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a876a34b74..c35dc3c4e7 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -973,6 +973,9 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 
 	initscan(&scan->heap_common, NULL, false);
 
+	scan->iterator.serial = NULL;
+	scan->iterator.parallel = NULL;
+
 	scan->vmbuffer = InvalidBuffer;
 
 	return (TableScanDesc) scan;
@@ -1078,6 +1081,8 @@ heap_endscan_bm(TableScanDesc sscan)
 	if (BufferIsValid(scan->vmbuffer))
 		ReleaseBuffer(scan->vmbuffer);
 
+	bhs_end_iterate(&scan->iterator);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
@@ -1396,6 +1401,8 @@ heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
 		ReleaseBuffer(scan->vmbuffer);
 	scan->vmbuffer = InvalidBuffer;
 
+	bhs_end_iterate(&scan->iterator);
+
 	scan->empty_tuples_pending = 0;
 
 	/*
@@ -1403,7 +1410,7 @@ heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
 	 */
 	initscan(&scan->heap_common, NULL, true);
 
-	bhs_begin_iterate(&scan->heap_common.rs_base.rs_bhs_iterator, tbm, dsa,
+	bhs_begin_iterate(&scan->iterator, tbm, dsa,
 					  pstate ?
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 43721cbd42..cc32d77100 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2209,7 +2209,7 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = bhs_iterate(&sscan->rs_bhs_iterator);
+		tbmres = bhs_iterate(&scan->iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 7b44c94d29..e33e4433a7 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -92,6 +92,7 @@ typedef struct BitmapHeapScanDescData
 	/*
 	 * Members common to Parallel and Serial BitmapHeapScan
 	 */
+	BitmapHeapIterator iterator;
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index e520186b41..855b9558bf 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -41,9 +41,6 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
-	/* Only used for Bitmap table scans */
-	BitmapHeapIterator rs_bhs_iterator;
-
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d02f5055b0..f344d97f1f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -1020,10 +1020,6 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
-		!scan->rs_bhs_iterator.exhausted)
-		bhs_end_iterate(&scan->rs_bhs_iterator);
-
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1034,10 +1030,6 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
-		!scan->rs_bhs_iterator.exhausted)
-		bhs_end_iterate(&scan->rs_bhs_iterator);
-
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
-- 
2.40.1

v16-0015-Lift-and-shift-BitmapHeapScan-prefetch-funcs-to-.patchtext/x-diff; charset=us-asciiDownload
From 86012b83948098f0c0f512676a275bf5595a1294 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 16:59:31 -0400
Subject: [PATCH v16 15/18] Lift and shift BitmapHeapScan prefetch funcs to
 heap AM

We will soon move all the members for managing prefetching from the
BitmapHeapScanState to the BitmapHeapScanDesc. First move the prefetch
functions as-is to heapam_handler.c

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  | 211 +++++++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 214 +---------------------
 src/include/access/heapam.h               |   4 +
 3 files changed, 216 insertions(+), 213 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index cc32d77100..ebaba33406 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2180,6 +2180,217 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			node->prefetch_pages--;
+		}
+		else if (!prefetch_iterator->exhausted)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbmpre = bhs_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
+	if (node->prefetch_maximum > 0)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!prefetch_iterator->exhausted)
+			{
+				tbmpre = bhs_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (node->prefetch_target >= node->prefetch_maximum / 2)
+			node->prefetch_target = node->prefetch_maximum;
+		else if (node->prefetch_target > 0)
+			node->prefetch_target *= 2;
+		else
+			node->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < node->prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+void
+BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
+
+	if (pstate == NULL)
+	{
+		if (!prefetch_iterator->exhausted)
+		{
+			while (node->prefetch_pages < node->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					break;
+				}
+				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		if (!prefetch_iterator->exhausted)
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = bhs_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					bhs_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				node->pfblockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index f8627991d0..6f1afd427d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -40,6 +40,7 @@
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
+#include "access/heapam.h"
 #include "executor/executor.h"
 #include "executor/nodeBitmapHeapscan.h"
 #include "miscadmin.h"
@@ -51,10 +52,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 /*
@@ -326,215 +323,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = bhs_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbmpre = bhs_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
-
-	if (pstate == NULL)
-	{
-		if (!prefetch_iterator->exhausted)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = bhs_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					bhs_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->pfblockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index e33e4433a7..f81a295685 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -426,6 +426,10 @@ extern bool heapam_scan_analyze_next_tuple(TableScanDesc scan,
 										   double *liverows, double *deadrows,
 										   TupleTableSlot *slot);
 
+extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
+extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+extern void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan);
+
 /*
  * To avoid leaking too much knowledge about reorderbuffer implementation
  * details this is implemented in reorderbuffer.c not heapam_visibility.c
-- 
2.40.1

v16-0016-Push-BitmapHeapScan-prefetch-code-into-heap-AM.patchtext/x-diff; charset=us-asciiDownload
From 7da12cdb96ae5255c815d657048f7a812094fcfa Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 18:48:27 -0400
Subject: [PATCH v16 16/18] Push BitmapHeapScan prefetch code into heap AM

An earlier commit eliminated a table AM layering violation for the
current block in a BitmapHeapScan but left the violation in
BitmapHeapScan prefetching code.

To resolve this, move and manage all state used for prefetching entirely
into the heap AM.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  33 +++++-
 src/backend/access/heap/heapam_handler.c  | 125 +++++++++++++++-------
 src/backend/executor/nodeBitmapHeapscan.c |  98 +++--------------
 src/include/access/heapam.h               |  29 ++++-
 src/include/access/tableam.h              |  18 +---
 src/include/executor/nodeBitmapHeapscan.h |   7 ++
 src/include/nodes/execnodes.h             |  19 ----
 7 files changed, 168 insertions(+), 161 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index c35dc3c4e7..5728b2ea8a 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -975,8 +975,10 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 
 	scan->iterator.serial = NULL;
 	scan->iterator.parallel = NULL;
-
 	scan->vmbuffer = InvalidBuffer;
+	scan->pf_iterator.serial = NULL;
+	scan->pf_iterator.parallel = NULL;
+	scan->pvmbuffer = InvalidBuffer;
 
 	return (TableScanDesc) scan;
 }
@@ -1081,6 +1083,10 @@ heap_endscan_bm(TableScanDesc sscan)
 	if (BufferIsValid(scan->vmbuffer))
 		ReleaseBuffer(scan->vmbuffer);
 
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+
+	bhs_end_iterate(&scan->pf_iterator);
 	bhs_end_iterate(&scan->iterator);
 
 	/*
@@ -1390,7 +1396,7 @@ heap_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction,
 
 void
 heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
-			   ParallelBitmapHeapState *pstate, dsa_area *dsa)
+			   ParallelBitmapHeapState *pstate, dsa_area *dsa, int pf_maximum)
 {
 	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
 
@@ -1401,9 +1407,19 @@ heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
 		ReleaseBuffer(scan->vmbuffer);
 	scan->vmbuffer = InvalidBuffer;
 
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+	scan->pvmbuffer = InvalidBuffer;
+
+	bhs_end_iterate(&scan->pf_iterator);
 	bhs_end_iterate(&scan->iterator);
 
+	scan->prefetch_maximum = 0;
 	scan->empty_tuples_pending = 0;
+	scan->pstate = NULL;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+	scan->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * reinitialize heap scan descriptor
@@ -1414,6 +1430,19 @@ heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
 					  pstate ?
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+	if (pf_maximum > 0)
+	{
+		bhs_begin_iterate(&scan->pf_iterator, tbm, dsa,
+						  pstate ?
+						  pstate->prefetch_iterator :
+						  InvalidDsaPointer);
+	}
+#endif							/* USE_PREFETCH */
+
+	scan->pstate = pstate;
+	scan->prefetch_maximum = pf_maximum;
 }
 
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ebaba33406..fca9c7233e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -60,6 +60,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc scan);
+static inline void BitmapPrefetch(BitmapHeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2187,26 +2190,26 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  *	iterator in prefetch_pages. For each block the main iterator returns, we
  *	decrement prefetch_pages.
  */
-void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
+	BitmapHeapIterator *prefetch_iterator = &scan->pf_iterator;
+	ParallelBitmapHeapState *pstate = scan->pstate;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_pages > 0)
+		if (scan->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
+			scan->prefetch_pages--;
 		}
 		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
 			tbmpre = bhs_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			scan->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
@@ -2216,7 +2219,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
 	 * the parallel workers.
 	 */
-	if (node->prefetch_maximum > 0)
+	if (scan->prefetch_maximum > 0)
 	{
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -2240,7 +2243,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			if (!prefetch_iterator->exhausted)
 			{
 				tbmpre = bhs_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				scan->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
 	}
@@ -2256,33 +2259,34 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
  * page/tuple, then to one after the second tuple is fetched, then
  * it doubles as later pages are fetched.
  */
-void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->pstate;
+	int			prefetch_maximum = scan->prefetch_maximum;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_target >= node->prefetch_maximum)
+		if (scan->prefetch_target >= prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
+		else if (scan->prefetch_target >= prefetch_maximum / 2)
+			scan->prefetch_target = prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
 		else
-			node->prefetch_target++;
+			scan->prefetch_target++;
 		return;
 	}
 
 	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
+	if (pstate->prefetch_target < prefetch_maximum)
 	{
 		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
+		if (pstate->prefetch_target >= prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target >= prefetch_maximum / 2)
+			pstate->prefetch_target = prefetch_maximum;
 		else if (pstate->prefetch_target > 0)
 			pstate->prefetch_target *= 2;
 		else
@@ -2295,18 +2299,19 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
 /*
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
-void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+static inline void
+BitmapPrefetch(BitmapHeapScanDesc scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	BitmapHeapIterator *prefetch_iterator = &node->pf_iterator;
+	ParallelBitmapHeapState *pstate = scan->pstate;
+	BitmapHeapIterator *prefetch_iterator = &scan->pf_iterator;
+	Relation	rel = scan->heap_common.rs_base.rs_rd;
 
 	if (pstate == NULL)
 	{
 		if (!prefetch_iterator->exhausted)
 		{
-			while (node->prefetch_pages < node->prefetch_target)
+			while (scan->prefetch_pages < scan->prefetch_target)
 			{
 				TBMIterateResult *tbmpre = bhs_iterate(prefetch_iterator);
 				bool		skip_fetch;
@@ -2317,8 +2322,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					bhs_end_iterate(prefetch_iterator);
 					break;
 				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2326,14 +2331,14 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
+				skip_fetch = (!(scan->heap_common.rs_base.rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -2373,17 +2378,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				scan->pfblockno = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
+				skip_fetch = (!(scan->heap_common.rs_base.rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -2416,6 +2421,8 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(scan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2556,6 +2563,18 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->pstate == NULL &&
+		!scan->pf_iterator.exhausted &&
+		scan->pfblockno < block)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(scan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2592,6 +2611,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!bscan->pstate)
+	{
+		if (bscan->prefetch_target < bscan->prefetch_maximum)
+			bscan->prefetch_target++;
+	}
+	else if (bscan->pstate->prefetch_target < bscan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&bscan->pstate->mutex);
+		if (bscan->pstate->prefetch_target < bscan->prefetch_maximum)
+			bscan->pstate->prefetch_target++;
+		SpinLockRelease(&bscan->pstate->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(bscan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6f1afd427d..ae36dfd773 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -124,7 +124,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
-	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
 	 * extract necessary information from index scan node
@@ -148,7 +147,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		Relation	rel = node->ss.ss_currentRelation;
 		uint32		extra_flags = 0;
+		bool		pf_maximum = 0;
 
 		/*
 		 * The leader will immediately come out of the function, but others
@@ -157,6 +158,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+#ifdef USE_PREFETCH
+		pf_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
+
 		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -174,7 +184,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (pf_maximum > 0)
 				{
 					pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
@@ -200,25 +210,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * scan descriptor and begin the scan.
 		 */
 		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
-								  node->ss.ss_currentRelation,
+								  rel,
 								  node->ss.ps.state->es_snapshot,
 								  extra_flags,
+								  pf_maximum,
 								  node->tbm,
 								  node->pstate,
 								  node->ss.ps.state->es_query_dsa);
 
 		node->ss.ss_currentScanDesc = scan;
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			bhs_begin_iterate(&node->pf_iterator, tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-		}
-#endif							/* USE_PREFETCH */
-
 		node->initialized = true;
 
 		goto new_page;
@@ -230,37 +231,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -283,23 +253,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!node->pf_iterator.exhausted &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -365,21 +321,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* release bitmaps and buffers if any */
-	if (node->pf_iterator.exhausted)
-		bhs_end_iterate(&node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
-	/* Only used for serial BHS */
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -418,14 +365,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan_bm(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (!node->pf_iterator.exhausted)
-		bhs_end_iterate(&node->pf_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -458,16 +401,12 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -507,13 +446,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index f81a295685..499e739da7 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -93,6 +93,10 @@ typedef struct BitmapHeapScanDescData
 	 * Members common to Parallel and Serial BitmapHeapScan
 	 */
 	BitmapHeapIterator iterator;
+	BitmapHeapIterator pf_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -102,7 +106,26 @@ typedef struct BitmapHeapScanDescData
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
 	Buffer		vmbuffer;
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
 	int			empty_tuples_pending;
+
+	/*
+	 * Parallel-only members
+	 */
+
+	struct ParallelBitmapHeapState *pstate;
+
+	/*
+	 * Serial-only members
+	 */
+
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block  */
+	BlockNumber pfblockno;
 }			BitmapHeapScanDescData;
 
 typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc;
@@ -307,7 +330,7 @@ extern TableScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, uin
 
 extern void heap_endscan_bm(TableScanDesc scan);
 extern void heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
-						   ParallelBitmapHeapState *pstate, dsa_area *dsa);
+						   ParallelBitmapHeapState *pstate, dsa_area *dsa, int pf_maximum);
 
 extern bool heap_fetch(Relation relation, Snapshot snapshot,
 					   HeapTuple tuple, Buffer *userbuf, bool keep_buf);
@@ -426,10 +449,6 @@ extern bool heapam_scan_analyze_next_tuple(TableScanDesc scan,
 										   double *liverows, double *deadrows,
 										   TupleTableSlot *slot);
 
-extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-extern void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan);
-
 /*
  * To avoid leaking too much knowledge about reorderbuffer implementation
  * details this is implemented in reorderbuffer.c not heapam_visibility.c
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index f344d97f1f..9ec0a1da2b 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -399,7 +399,8 @@ typedef struct TableAmRoutine
 									uint32 flags);
 
 	void		(*scan_rescan_bm) (TableScanDesc scan, TIDBitmap *tbm,
-								   ParallelBitmapHeapState *pstate, dsa_area *dsa);
+								   ParallelBitmapHeapState *pstate, dsa_area *dsa,
+								   int pf_maximum);
 
 	/*
 	 * Release resources and deallocate scan. If TableScanDesc.temp_snap,
@@ -801,17 +802,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -950,7 +940,7 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
-				   uint32 extra_flags, TIDBitmap *tbm,
+				   uint32 extra_flags, int pf_maximum, TIDBitmap *tbm,
 				   ParallelBitmapHeapState *pstate, dsa_area *dsa)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE | extra_flags;
@@ -962,7 +952,7 @@ table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
 	if (!scan)
 		scan = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 
-	scan->rs_rd->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa);
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa, pf_maximum);
 
 	return scan;
 }
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index 7064f54686..028081db32 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -29,6 +29,13 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
 										   ParallelWorkerContext *pwcxt);
 
+typedef struct BitmapHeapIterator
+{
+	struct TBMIterator *serial;
+	struct TBMSharedIterator *parallel;
+	bool		exhausted;
+} BitmapHeapIterator;
+
 extern TBMIterateResult *bhs_iterate(BitmapHeapIterator *iterator);
 extern void bhs_begin_iterate(BitmapHeapIterator *iterator, TIDBitmap *tbm,
 							  dsa_area *dsa, dsa_pointer dsp);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 714eb3e534..713de7d50f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1787,30 +1787,17 @@ typedef struct ParallelBitmapHeapState
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
 
-typedef struct BitmapHeapIterator
-{
-	struct TBMIterator *serial;
-	struct TBMSharedIterator *parallel;
-	bool		exhausted;
-} BitmapHeapIterator;
-
 /* ----------------
  *	 BitmapHeapScanState information
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		pf_iterator        for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1818,18 +1805,12 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	BitmapHeapIterator pf_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v16-0017-Move-BitmapHeapScan-initialization-to-helper.patchtext/x-diff; charset=us-asciiDownload
From d66c526696f6bcb9d6aa0a8b234d51c58866a6ff Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 19:02:38 -0400
Subject: [PATCH v16 17/18] Move BitmapHeapScan initialization to helper

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 182 +++++++++++-----------
 src/include/access/tableam.h              |   6 +-
 2 files changed, 98 insertions(+), 90 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index ae36dfd773..ce47cd51bd 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -109,6 +109,97 @@ bhs_end_iterate(BitmapHeapIterator *iterator)
 	iterator->exhausted = true;
 }
 
+ /*
+  * If we haven't yet performed the underlying index scan, do it, and begin
+  * the iteration over the bitmap.
+  *
+  * For prefetching, we use *two* iterators, one for the pages we are actually
+  * scanning and another that runs ahead of the first for prefetching.
+  * node->prefetch_pages tracks exactly how many pages ahead the prefetch
+  * iterator is.  Also, node->prefetch_target tracks the desired prefetch
+  * distance, which starts small and increases up to the
+  * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
+  * scan that stops after a few tuples because of a LIMIT.
+  */
+static void
+BitmapHeapInitialize(BitmapHeapScanState *node)
+{
+	TIDBitmap  *tbm;
+	ParallelBitmapHeapState *pstate = node->pstate;
+	Relation	rel = node->ss.ss_currentRelation;
+	uint32		extra_flags = 0;
+	bool		pf_maximum = 0;
+
+	/*
+	 * The leader will immediately come out of the function, but others will
+	 * be blocked until leader populates the TBM and wakes them up.
+	 */
+	bool		init_shared_state = node->pstate ?
+		BitmapShouldInitializeSharedState(node->pstate) : false;
+
+	/*
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
+	 */
+#ifdef USE_PREFETCH
+	pf_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
+
+	if (!pstate || init_shared_state)
+	{
+		tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+
+		if (!tbm || !IsA(tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+		node->tbm = tbm;
+
+		if (init_shared_state)
+		{
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+#ifdef USE_PREFETCH
+			if (pf_maximum > 0)
+			{
+				pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(tbm);
+			}
+#endif
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(pstate);
+		}
+	}
+
+	/*
+	 * We can potentially skip fetching heap pages if we do not need any
+	 * columns of the table, either for checking non-indexable quals or for
+	 * returning data.  This test is a bit simplistic, as it checks the
+	 * stronger condition that there's no qual or return tlist at all. But in
+	 * most cases it's probably not worth working harder than that.
+	 */
+	if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
+		extra_flags |= SO_NEED_TUPLE;
+
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	node->ss.ss_currentScanDesc = table_beginscan_bm(node->ss.ss_currentScanDesc,
+													 rel,
+													 node->ss.ps.state->es_snapshot,
+													 extra_flags,
+													 pf_maximum,
+													 node->tbm,
+													 node->pstate,
+													 node->ss.ps.state->es_query_dsa);
+
+
+	node->initialized = true;
+}
 
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
@@ -121,9 +212,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 
 	/*
 	 * extract necessary information from index scan node
@@ -131,97 +220,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
+	 * the iteration over the bitmap. This happens on rescan as well.
 	 */
 	if (!node->initialized)
 	{
-		Relation	rel = node->ss.ss_currentRelation;
-		uint32		extra_flags = 0;
-		bool		pf_maximum = 0;
-
-		/*
-		 * The leader will immediately come out of the function, but others
-		 * will be blocked until leader populates the TBM and wakes them up.
-		 */
-		bool		init_shared_state = node->pstate ?
-			BitmapShouldInitializeSharedState(node->pstate) : false;
-
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-#ifdef USE_PREFETCH
-		pf_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-#endif
-
-
-		if (!pstate || init_shared_state)
-		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-			node->tbm = tbm;
-
-			if (init_shared_state)
-			{
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (pf_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
-		}
-
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		if (node->ss.ps.plan->qual != NIL || node->ss.ps.plan->targetlist != NIL)
-			extra_flags |= SO_NEED_TUPLE;
-
-		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
-		 */
-		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
-								  rel,
-								  node->ss.ps.state->es_snapshot,
-								  extra_flags,
-								  pf_maximum,
-								  node->tbm,
-								  node->pstate,
-								  node->ss.ps.state->es_query_dsa);
-
-		node->ss.ss_currentScanDesc = scan;
-
-		node->initialized = true;
-
+		BitmapHeapInitialize(node);
+		/* We may have a new scan descriptor */
+		scan = node->ss.ss_currentScanDesc;
 		goto new_page;
 	}
 
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9ec0a1da2b..eea7b7ff20 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -791,9 +791,9 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
+	 * Prepare to fetch / check / return tuples as part of a bitmap table
+	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
+	 * bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-- 
2.40.1

v16-0018-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From 6a2a8b7d147e3c5343512bcf4d1d8389ff71bbe8 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 5 Apr 2024 18:56:45 -0400
Subject: [PATCH v16 18/18] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block().

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 53 +++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 69 +++++++++------------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 73 +++++------------------
 src/include/nodes/execnodes.h             |  2 -
 7 files changed, 78 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 5728b2ea8a..3ee4d75f17 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -327,6 +327,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index fca9c7233e..a6d75cfaa8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2216,8 +2216,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc scan)
 
 	/*
 	 * Adjusting the prefetch iterator before invoking
-	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
-	 * the parallel workers.
+	 * heapam_bitmap_next_block() keeps prefetch distance higher across the
+	 * parallel workers.
 	 */
 	if (scan->prefetch_maximum > 0)
 	{
@@ -2397,14 +2397,12 @@ BitmapPrefetch(BitmapHeapScanDesc scan)
 
 
 
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
+/*
+ * Helper for heapam_scan_bitmap_next_tuple()
  */
-
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc sscan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
@@ -2418,7 +2416,6 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
 	BitmapAdjustPrefetchIterator(scan);
@@ -2447,7 +2444,6 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2585,9 +2581,16 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	return true;
 }
 
+
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = &bscan->heap_common;
@@ -2595,21 +2598,28 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
-	if (bscan->empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->empty_tuples_pending--;
-		return true;
-	}
+		if (bscan->empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -3010,7 +3020,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 55b8caeadf..0b87530a9c 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -90,8 +90,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index ce47cd51bd..3ce24156dd 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -211,61 +211,52 @@ static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
-	TableScanDesc scan;
 	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	TableScanDesc scan;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap. This happens on rescan as well.
 	 */
 	if (!node->initialized)
-	{
 		BitmapHeapInitialize(node);
-		/* We may have a new scan descriptor */
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	/*
+	 * BitmapHeapInitialize() may make the scan descriptor so don't get it
+	 * from the node until after calling it.
+	 */
+	econtext = node->ss.ps.ps_ExprContext;
+	slot = node->ss.ss_ScanTupleSlot;
+	scan = node->ss.ss_currentScanDesc;
+
+
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
+
 	/*
 	 * if we get here it means we are at the end of the scan..
 	 */
@@ -334,7 +325,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->tbm = NULL;
 	node->initialized = false;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -414,7 +404,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346..cf56cc572f 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -313,7 +313,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index eea7b7ff20..b2f0a61751 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -790,34 +790,21 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples as part of a bitmap table
-	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
-	 * bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the bitmap is lossy for the selected
-	 * block; otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno, bool *recheck,
-										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1983,45 +1970,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented is the block's representation in the bitmap is lossy; otherwise,
- * exact_pages is incremented.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno, bool *recheck,
-							 long *lossy_pages,
-							 long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
-														   lossy_pages, exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2032,7 +1987,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 713de7d50f..49ce4ff9a7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1797,7 +1797,6 @@ typedef struct ParallelBitmapHeapState
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1810,7 +1809,6 @@ typedef struct BitmapHeapScanState
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

#100Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#99)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/6/24 01:53, Melanie Plageman wrote:

On Fri, Apr 05, 2024 at 04:06:34AM -0400, Melanie Plageman wrote:

On Thu, Apr 04, 2024 at 04:35:45PM +0200, Tomas Vondra wrote:

On 4/4/24 00:57, Melanie Plageman wrote:

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

On Fri, Mar 29, 2024 at 12:05:15PM +0100, Tomas Vondra wrote:

On 3/29/24 02:12, Thomas Munro wrote:

On Fri, Mar 29, 2024 at 10:43 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I think there's some sort of bug, triggering this assert in heapam

Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);

Thanks for the repro. I can't seem to reproduce it (still trying) but
I assume this is with Melanie's v11 patch set which had
v11-0016-v10-Read-Stream-API.patch.

Would you mind removing that commit and instead applying the v13
stream_read.c patches[1]? v10 stream_read.c was a little confused
about random I/O combining, which I fixed with a small adjustment to
the conditions for the "if" statement right at the end of
read_stream_look_ahead(). Sorry about that. The fixed version, with
eic=4, with your test query using WHERE a < a, ends its scan with:

I'll give that a try. Unfortunately unfortunately the v11 still has the
problem I reported about a week ago:

ERROR: prefetch and main iterators are out of sync

So I can't run the full benchmarks :-( but master vs. streaming read API
should work, I think.

Odd, I didn't notice you reporting this ERROR popping up. Now that I
take a look, v11 (at least, maybe also v10) had this very sill mistake:

  if (scan->bm_parallel == NULL &&
      scan->rs_pf_bhs_iterator &&
      hscan->pfblockno > hscan->rs_base.blockno)
       elog(ERROR, "prefetch and main iterators are out of sync");

It errors out if the prefetch block is ahead of the current block --
which is the opposite of what we want. I've fixed this in attached v12.

This version also has v13 of the streaming read API. I noticed one
mistake in my bitmapheap scan streaming read user -- it freed the
streaming read object at the wrong time. I don't know if this was
causing any other issues, but it at least is fixed in this version.

Attached v13 is rebased over master (which includes the streaming read
API now). I also reset the streaming read object on rescan instead of
creating a new one each time.

I don't know how much chance any of this has of going in to 17 now, but
I thought I would start looking into the regression repro Tomas provided
in [1].

My personal opinion is that we should try to get in as many of the the
refactoring patches as possible, but I think it's probably too late for
the actual switch to the streaming API.

Cool. In the attached v15, I have dropped all commits that are related
to the streaming read API and included *only* commits that are
beneficial to master. A few of the commits are merged or reordered as
well.

While going through the commits with this new goal in mind (forget about
the streaming read API for now), I realized that it doesn't make much
sense to just eliminate the layering violation for the current block and
leave it there for the prefetch block. I had de-prioritized solving this
when I thought we would just delete the prefetch code and replace it
with the streaming read.

Now that we aren't doing that, I've spent the day trying to resolve the
issues with pushing the prefetch code into heapam.c that I cited in [1].
0010 - 0013 are the result of this. They are not very polished yet and
need more cleanup and review (especially 0011, which is probably too
large), but I am happy with the solution I came up with.

Basically, there are too many members needed for bitmap heap scan to put
them all in the HeapScanDescData (don't want to bloat it). So, I've made
a new BitmapHeapScanDescData and associated begin/rescan/end() functions

In the end, with all patches applied, BitmapHeapNext() loops invoking
table_scan_bitmap_next_tuple() and table AMs can implement that however
they choose.

I'm also not sure if I should try and group the commits into fewer
commits now or wait until I have some idea of whether or not the
approach in 0013 and 0014 is worth pursuing.

You mean whether to pursue the approach in general, or for v17? I think
it looks like the right approach, but for v17 see above :-(

As for merging, I wouldn't do that. I looked at the commits and while
some of them seem somewhat "trivial", I really like how you organized
the commits, and kept those that just "move" code around, and those that
actually change stuff. It's much easier to understand, IMO.

I went through the first ~10 commits, and added some review - either as
a separate commit, when possible, in the code as XXX comment, and also
in the commit message. The code tweaks are utterly trivial (whitespace
or indentation to make the line shorter). It shouldn't take much time to
deal with those, I think.

Attached v15 incorporates your v14-0002-review.

For your v14-0008-review, I actually ended up removing that commit
because once I removed everything that was for streaming read API, it
became redundant with another commit.

For your v14-0010-review, we actually can't easily get rid of those
local variables because we make the iterators before we make the scan
descriptors and the commit following that commit moves the iterators
from the BitmapHeapScanState to the scan descriptor.

I think the main focus should be updating the commit messages. If it was
only a single patch, I'd probably try to write the messages myself, but
with this many patches it'd be great if you could update those and I'll
review that before commit.

I did my best to update the commit messages to be less specific and more
focused on "why should I care". I found myself wanting to explain why I
implemented something the way I did and then getting back into the
implementation details again. I'm not sure if I suceeded in having less
details and more substance.

I always struggle with writing commit messages myself, and it takes me
ages to write a good one (well, I think the message is good, but who
knows ...). But I think a good message should be concise enough to
explain what and why it's done. It may reference a thread for all the
gory details, but the basic reasoning should be in the commit message.
For example the message for "BitmapPrefetch use prefetch block recheck
for skip fetch" now says that it "makes more sense to do X" but does not
really say why that's the case. The linked message does, but it'd be
good to have that in the message (because how would I know how much of
the thread to read?).

I fixed that particular one. I tried to take that feedback and apply it
to other commit messages. I don't know how successful I was...

Also, it'd be very helpful if you could update the author & reviewed-by
fields. I'll review those before commit, ofc, but I admit I lost track
of who reviewed which part.

I have updated reviewers. I didn't add reviewers on the ones that
haven't really been reviewed yet.

I'd focus on the first ~8-9 commits or so for now, we can commit more if
things go reasonably well.

Sounds good. I will spend cleanup time on 0010-0013 tomorrow but would
love to know if you agree with the direction before I spend more time.

In attached v16, I've split out 0010-0013 into 0011-0017. I think it is
much easier to understand.

Damn it, I went through the whole patch series, adding a couple review
comments and tweaks, and was just about to share my version, but you bet
me to it ;-)

Anyway, I've attached it as .tgz in order to not confuse cfbot. All the
review comments are marked with XXX, so grep for that in the patches.
There's two separate patches - the first one suggests a code change, so
it was better to not merge that with your code. The second has just a
couple XXX comments, I'm not sure why I kept it separate.

A couple review comments:

* I think 0001-0009 are 99% ready to. I reworded some of the commit
messages a bit - I realize it's a bit bold, considering you're native
speaker and I'm not. If you could check I didn't make it worse, that
would be great.

* I'm not sure extra_flags is the right way to pass the flag in 0003.
The "extra_" name is a bit weird, and no other table AM functions do it
this way and pass explicit bool flags instead. So my first "review"
commit does it like that. Do you agree it's better that way?

* The one question I'm somewhat unsure about is why Tom chose to use the
"wrong" recheck flag in the 2017 commit, when the correct recheck flag
is readily available. Surely that had a reason, right? But I can't think
of one ...

While I was doing that, I realized that I should remove the call to
table_rescan() from ExecReScanBitmapHeapScan() and just rely on the new
table_rescan_bm() invoked from BitmapHeapNext(). That is done in the
attached.

0010-0018 still need comments updated but I focused on getting the split
out, reviewable version of them ready. I'll add comments (especially to
0011 table AM functions) tomorrow. I also have to double-check if I
should add any asserts for table AMs about having implemented all of the
new begin/re/endscan() functions.

I added a couple more comments for those patches (10-12). Chances are
the split in v16 clarifies some of my questions, but it'll have to wait
till the morning ...

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

v15-review.tgzapplication/x-compressed-tar; name=v15-review.tgzDownload
#101Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#100)
9 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Apr 06, 2024 at 02:51:45AM +0200, Tomas Vondra wrote:

On 4/6/24 01:53, Melanie Plageman wrote:

On Fri, Apr 05, 2024 at 04:06:34AM -0400, Melanie Plageman wrote:

On Thu, Apr 04, 2024 at 04:35:45PM +0200, Tomas Vondra wrote:

On 4/4/24 00:57, Melanie Plageman wrote:

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

I'd focus on the first ~8-9 commits or so for now, we can commit more if
things go reasonably well.

Sounds good. I will spend cleanup time on 0010-0013 tomorrow but would
love to know if you agree with the direction before I spend more time.

In attached v16, I've split out 0010-0013 into 0011-0017. I think it is
much easier to understand.

Anyway, I've attached it as .tgz in order to not confuse cfbot. All the
review comments are marked with XXX, so grep for that in the patches.
There's two separate patches - the first one suggests a code change, so
it was better to not merge that with your code. The second has just a
couple XXX comments, I'm not sure why I kept it separate.

A couple review comments:

* I think 0001-0009 are 99% ready to. I reworded some of the commit
messages a bit - I realize it's a bit bold, considering you're native
speaker and I'm not. If you could check I didn't make it worse, that
would be great.

Attached v17 has *only* patches 0001-0009 with these changes. I will
work on applying the remaining patches, addressing feedback, and adding
comments next.

I have reviewed and incorporated all of your feedback on these patches.
Attached v17 is your exact patches with 1 or 2 *very* slight tweaks to
commit messages (comma splice removal and single word adjustments) as
well as the changes listed below:

I have changed the following:

- 0003 added an assert that rs_empty_tuples_pending is 0 on rescan and
endscan

- 0004 (your 0005)-- I followed up with Tom, but for now I have just
removed the XXX and also reworded the message a bit

- 0006 (your 0007) fixed up the variable name (you changed valid ->
valid_block but it had gotten changed back)

I have open questions on the following:

- 0003: should it be SO_NEED_TUPLES and need_tuples (instead of
SO_NEED_TUPLE and need_tuple)?

- 0009 (your 0010)
- Should I mention in the commit message that we added blockno and
pfblockno in the BitmapHeapScanState only for validation or is that
too specific?

- Should I mention that a future (imminent) commit will remove the
iterators from TableScanDescData and put them in HeapScanDescData? I
imagine folks don't want those there, but it is easier for the
progression of commits to put them there first and then move them

- I'm worried this comment is vague and or potentially not totally
correct. Should we remove it? I don't think we have conclusive proof
that this is true.
/*
* Adjusting the prefetch iterator before invoking
* table_scan_bitmap_next_block() keeps prefetch distance higher across
* the parallel workers.
*/

* I'm not sure extra_flags is the right way to pass the flag in 0003.
The "extra_" name is a bit weird, and no other table AM functions do it
this way and pass explicit bool flags instead. So my first "review"
commit does it like that. Do you agree it's better that way?

Yes.

* The one question I'm somewhat unsure about is why Tom chose to use the
"wrong" recheck flag in the 2017 commit, when the correct recheck flag
is readily available. Surely that had a reason, right? But I can't think
of one ...

See above.

While I was doing that, I realized that I should remove the call to
table_rescan() from ExecReScanBitmapHeapScan() and just rely on the new
table_rescan_bm() invoked from BitmapHeapNext(). That is done in the
attached.

0010-0018 still need comments updated but I focused on getting the split
out, reviewable version of them ready. I'll add comments (especially to
0011 table AM functions) tomorrow. I also have to double-check if I
should add any asserts for table AMs about having implemented all of the
new begin/re/endscan() functions.

I added a couple more comments for those patches (10-12). Chances are
the split in v16 clarifies some of my questions, but it'll have to wait
till the morning ...

Will address this in next mail.

- Melanie

Attachments:

v17-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From e65a9baa52c99c93a9a9a281aebacd38b8299721 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v17 1/9] BitmapHeapScan: begin scan after bitmap creation

It makes more sense for BitmapHeapScan to scan the index, build the
bitmap, and only then begin the scan on the underlying table.

This is mostly a cosmetic change for now, but later commits will need
to pass parameters to table_beginscan_bm() that are unavailable in
ExecInitBitmapHeapScan().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 27 +++++++++++++++++------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aabe..c8c466e3c5c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = table_beginscan_bm(node->ss.ss_currentRelation,
+									  node->ss.ps.state->es_snapshot,
+									  0,
+									  NULL);
+
+			node->ss.ss_currentScanDesc = scan;
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +616,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +694,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +801,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v17-0002-BitmapHeapScan-postpone-setting-can_skip_fetch.patchtext/x-diff; charset=us-asciiDownload
From d232ecdd32157b97e95619916fc889fa1fe56845 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v17 2/9] BitmapHeapScan: postpone setting can_skip_fetch

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() instead of
in ExecInitBitmapHeapScan(). This is a preliminary step to pushing the
skip fetch optimization into heap AM code.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c8c466e3c5c..2148a21531a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -743,16 +753,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v17-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From a8b6a13bd2472451e1ce9d904b5ba2eeb1e83c76 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:34:25 +0200
Subject: [PATCH v17 3/9] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM-specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block. The layering violation is
still present in BitmapHeapScans's prefetching code, which uses the
visibility map to decide whether or not to prefetch a block. However,
this will be fixed in an upcoming commit.

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  15 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  12 ++-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 105 insertions(+), 93 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index dada2ecd1e3..01bb2f4cc16 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -967,6 +967,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1055,6 +1057,14 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
+	Assert(scan->rs_empty_tuples_pending == 0);
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1074,6 +1084,11 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+		ReleaseBuffer(scan->rs_vmbuffer);
+
+	Assert(scan->rs_empty_tuples_pending == 0);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3e7a6b5548b..929b2cf8e71 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2198,6 +2199,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLE) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2310,6 +2329,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2148a21531a..920d99c0330 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,10 +185,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			bool		need_tuple = false;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			need_tuple = (node->ss.ps.plan->qual != NIL ||
+						  node->ss.ps.plan->targetlist != NIL);
+
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
 									  0,
-									  NULL);
+									  NULL,
+									  need_tuple);
 
 			node->ss.ss_currentScanDesc = scan;
 		}
@@ -208,7 +212,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid_block;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -229,37 +233,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid_block = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid_block)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -302,52 +283,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -519,7 +481,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -570,7 +532,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -640,8 +602,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -651,7 +611,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -696,8 +655,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -741,8 +698,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -753,7 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2765efc4e5e..750ea30852e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,6 +76,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e7eeb754098..d05f7cd2398 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -63,6 +63,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLE.
+	 */
+	SO_NEED_TUPLE = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -937,10 +944,13 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
+	if (need_tuple)
+		flags |= SO_NEED_TUPLE;
+
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e57ebd72887..fa2f70b7a48 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,10 +1794,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1817,9 +1814,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v17-0004-Use-prefetch-block-recheck-value-to-determine-sk.patchtext/x-diff; charset=us-asciiDownload
From 33c92948e822fcae0587818584011b3f6871d6b4 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v17 4/9] Use prefetch block recheck value to determine
 skip_fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it should skip prefetching
the proposed prefetch block. As explained in the comment, this assumed
the index AM will report the same recheck value for the future page as
it did for the current page - but there's no guarantee.

This only affects prefetching - we may prefetch blocks unecessarily and
not prefetch blocks that will be needed. But we don't need to rely on
that assumption - we know the recheck flag for the block we're
considering prefetching.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
Discussion: https://postgr.es/m/CAAKRu_bxrXeZ2rCnY8LyeC2Ls88KpjWrQ%2BopUrXDRXdcfwFZGA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 920d99c0330..3e3c976ff6f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -475,14 +475,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -533,7 +528,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v17-0005-Change-BitmapAdjustPrefetchIterator-to-accept-Bl.patchtext/x-diff; charset=us-asciiDownload
From 4e4da48d4da2626f3f3fcd397a92997308fad517 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v17 5/9] Change BitmapAdjustPrefetchIterator to accept
 BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only, so that we
can move away from using the TBMIterateResult outside of table AM
specific code.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3e3c976ff6f..12b59d417d6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -231,7 +231,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid_block = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -342,7 +342,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -361,7 +361,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v17-0006-BitmapHeapScan-Reduce-scope-of-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From 0fd0fe20348ef715c8083007acbd4da025a11491 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v17 6/9] BitmapHeapScan: Reduce scope of tbmiterator local
 variables

A future patch will change where tbmiterators are initialized and saved.
To keep that diff easier to understand, move them into a tighter scope.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 12b59d417d6..4692c7ecc91 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -207,6 +203,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -222,9 +220,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v17-0007-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From 8cb393423bab817feff803ad48a4f80088d546d3 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v17 7/9] table_scan_bitmap_next_block counts lossy and exact
 pages

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So the table AM must keep
track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap for the purposes of EXPLAIN counters.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 929b2cf8e71..b5ab104ec25 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2316,6 +2317,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 4692c7ecc91..bf05e7b652d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -210,8 +210,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -231,14 +229,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d05f7cd2398..e263ad2ca16 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,6 +789,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy_pages is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, exact_pages is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -804,7 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1971,17 +1975,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy_pages is incremented is the block's
+ * representation in the bitmap is lossy; otherwise, exact_pages is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1992,7 +2000,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v17-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From 05c1d34c58396b56bff0a8fccafa3c62399a68f3 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v17 8/9] Remove table_scan_bitmap_next_tuple parameter tbmres

Future commits will push all of the logic for choosing the next block
into the table AM specific code. The table AM will be responsible for
iterating and reading in the right blocks.

Thus, it no longer makes sense to use the TBMIterateResult (which
contains a block number) as a means of communication between
table_scan_bitmap_next_tuple() and table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b5ab104ec25..efd1a66a092 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2327,7 +2327,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index bf05e7b652d..265ea8bd818 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -279,7 +279,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e263ad2ca16..b8256116c98 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,10 +780,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -814,15 +811,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2015,7 +2007,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2027,7 +2018,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v17-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From c75ea2495f849a98de560dc76f56764570841b39 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 09:04:01 -0400
Subject: [PATCH v17 9/9] Make table_scan_bitmap_next_block() async-friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on tuples on the page. This
could happen when there were no visible tuples on the page or, due to
concurrent activity on the table, the block returned by the iterator is
past the end of the table recorded when the scan started.

That forced the caller to be responsible for determining if additional
blocks should be fetched and for invoking table_scan_bitmap_next_block()
for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
beginning of the scan) and for table_scan_bitmap_next_tuple() to return
false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to the
table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  58 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 182 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 190 insertions(+), 137 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index efd1a66a092..9d3e7c7fdae 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,18 +2188,52 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2218,16 +2252,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2322,7 +2347,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 265ea8bd818..cea2a56d499 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,7 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +160,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -203,48 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -265,45 +235,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -329,13 +310,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -349,14 +334,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * Adjusting the prefetch iterator before invoking
+	 * table_scan_bitmap_next_block() keeps prefetch distance higher across
+	 * the parallel workers.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -381,7 +369,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -459,6 +450,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -516,6 +508,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLE) &&
 							  !tbmpre->recheck &&
@@ -577,12 +571,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -590,13 +580,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -627,28 +617,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -681,8 +667,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -690,9 +674,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b8256116c98..693c95027cd 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -773,19 +774,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
@@ -804,7 +800,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -942,12 +938,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLE;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -994,6 +994,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1004,6 +1019,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1967,19 +1997,18 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy_pages is incremented is the block's
- * representation in the bitmap is lossy; otherwise, exact_pages is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented is the block's representation in the bitmap is lossy; otherwise,
+ * exact_pages is incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1992,9 +2021,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fa2f70b7a48..d96703b04d4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

#102Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Tomas Vondra (#100)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/6/24 02:51, Tomas Vondra wrote:

* The one question I'm somewhat unsure about is why Tom chose to use the
"wrong" recheck flag in the 2017 commit, when the correct recheck flag
is readily available. Surely that had a reason, right? But I can't think
of one ...

I've been wondering about this a bit more, so I decided to experiment
and try to construct a case for which the current code prefetches the
wrong blocks, and the patch fixes that. But I haven't been very
successful so far :-(

My understanding was that the current code should do the wrong thing if
I alternate all-visible and not-all-visible pages. This understanding is
not correct, as I learned, because the thing that needs to change is the
recheck flag, not visibility :-( I'm still posting what I tried, perhaps
you will have an idea how to alter it to demonstrate the incorrect
behavior with current master.

The test was very simple:

create table t (a int, b int) with (fillfactor=10);
insert into t select mod((i/22),2), (i/22)
from generate_series(0,1000) s(i);
create index on t (a);

which creates a table with 46 pages, 22 rows per page, column "a"
alternates between 0/1 on pages, column "b" increments on each page (so
"b" identifies page).

and then

delete from t where mod(b,8) = 0;

which deletes tuples on pages 0, 8, 16, 24, 32, 40, so these pages will
need to be prefetched as not-all-visible by this query

explain analyze select count(1) from t where a = 0

when forced to do bitmap heap scan. The other even-numbered pages remain
all-visible. I added a bit of logging into BitmapPrefetch(), but even
with master I get this:

LOG: prefetching block 8 0 current block 6 0
LOG: prefetching block 16 0 current block 14 0
LOG: prefetching block 24 0 current block 22 0
LOG: prefetching block 32 0 current block 30 0
LOG: prefetching block 40 0 current block 38 0

So it prefetches the correct pages (the other value is the recheck flag
for that block from the iterator result).

Turns out (and I realize the comment about the assumption actually
states that, I just failed to understand it) the thing that would have
to differ for the blocks is the recheck flag.

But that can't actually happen because that's set by the AM/opclass and
the built-in ones do essentially this:

.../hash.c: scan->xs_recheck = true;
.../nbtree.c: scan->xs_recheck = false;

gist opclasses (e.g. btree_gist):

/* All cases served by this function are exact */
*recheck = false;

spgist opclasses (e.g. geo_spgist):

/* All tests are exact. */
out->recheck = false;

If there's an opclass that alters the recheck flag, it's well hidden and
I missed it.

Anyway, after this exercise and learning more about the recheck flag, I
think I agree the assumption is unnecessary. It's pretty harmless
because none of the built-in opclasses alters the recheck flag, but the
correct recheck flag is readily available. I'm still a bit puzzled why
the 2017 commit even relied on this assumption, though.

regards
--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#103Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#101)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/6/24 15:40, Melanie Plageman wrote:

On Sat, Apr 06, 2024 at 02:51:45AM +0200, Tomas Vondra wrote:

On 4/6/24 01:53, Melanie Plageman wrote:

On Fri, Apr 05, 2024 at 04:06:34AM -0400, Melanie Plageman wrote:

On Thu, Apr 04, 2024 at 04:35:45PM +0200, Tomas Vondra wrote:

On 4/4/24 00:57, Melanie Plageman wrote:

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

I'd focus on the first ~8-9 commits or so for now, we can commit more if
things go reasonably well.

Sounds good. I will spend cleanup time on 0010-0013 tomorrow but would
love to know if you agree with the direction before I spend more time.

In attached v16, I've split out 0010-0013 into 0011-0017. I think it is
much easier to understand.

Anyway, I've attached it as .tgz in order to not confuse cfbot. All the
review comments are marked with XXX, so grep for that in the patches.
There's two separate patches - the first one suggests a code change, so
it was better to not merge that with your code. The second has just a
couple XXX comments, I'm not sure why I kept it separate.

A couple review comments:

* I think 0001-0009 are 99% ready to. I reworded some of the commit
messages a bit - I realize it's a bit bold, considering you're native
speaker and I'm not. If you could check I didn't make it worse, that
would be great.

Attached v17 has *only* patches 0001-0009 with these changes. I will
work on applying the remaining patches, addressing feedback, and adding
comments next.

I have reviewed and incorporated all of your feedback on these patches.
Attached v17 is your exact patches with 1 or 2 *very* slight tweaks to
commit messages (comma splice removal and single word adjustments) as
well as the changes listed below:

I have changed the following:

- 0003 added an assert that rs_empty_tuples_pending is 0 on rescan and
endscan

OK

- 0004 (your 0005)-- I followed up with Tom, but for now I have just
removed the XXX and also reworded the message a bit

After the exercise I described a couple minutes ago, I think I'm
convinced the assumption is unnecessary and we should use the correct
recheck. Not that it'd make any difference in practice, considering none
of the opclasses ever changes the recheck.

Maybe the most prudent thing would be to skip this commit and maybe
leave this for later, but I'm not forcing you to do that if it would
mean a lot of disruption for the following patches.

- 0006 (your 0007) fixed up the variable name (you changed valid ->
valid_block but it had gotten changed back)

OK

I have open questions on the following:

- 0003: should it be SO_NEED_TUPLES and need_tuples (instead of
SO_NEED_TUPLE and need_tuple)?

I think SO_NEED_TUPLES is more accurate, as we need all tuples from the
block. But either would work.

- 0009 (your 0010)
- Should I mention in the commit message that we added blockno and
pfblockno in the BitmapHeapScanState only for validation or is that
too specific?

For the commit message I'd say it's too specific, I'd put it in the
comment before the struct.

- Should I mention that a future (imminent) commit will remove the
iterators from TableScanDescData and put them in HeapScanDescData? I
imagine folks don't want those there, but it is easier for the
progression of commits to put them there first and then move them

I'd try not to mention future commits as justification too often, if we
don't know that the future commit lands shortly after.

- I'm worried this comment is vague and or potentially not totally
correct. Should we remove it? I don't think we have conclusive proof
that this is true.
/*
* Adjusting the prefetch iterator before invoking
* table_scan_bitmap_next_block() keeps prefetch distance higher across
* the parallel workers.
*/

TBH it's not clear to me what "higher across parallel workers" means.
But it sure shouldn't claim things that we think may not be correct. I
don't have a good idea how to reword it, though.

* I'm not sure extra_flags is the right way to pass the flag in 0003.
The "extra_" name is a bit weird, and no other table AM functions do it
this way and pass explicit bool flags instead. So my first "review"
commit does it like that. Do you agree it's better that way?

Yes.

Cool

* The one question I'm somewhat unsure about is why Tom chose to use the
"wrong" recheck flag in the 2017 commit, when the correct recheck flag
is readily available. Surely that had a reason, right? But I can't think
of one ...

See above.

While I was doing that, I realized that I should remove the call to
table_rescan() from ExecReScanBitmapHeapScan() and just rely on the new
table_rescan_bm() invoked from BitmapHeapNext(). That is done in the
attached.

0010-0018 still need comments updated but I focused on getting the split
out, reviewable version of them ready. I'll add comments (especially to
0011 table AM functions) tomorrow. I also have to double-check if I
should add any asserts for table AMs about having implemented all of the
new begin/re/endscan() functions.

I added a couple more comments for those patches (10-12). Chances are
the split in v16 clarifies some of my questions, but it'll have to wait
till the morning ...

Will address this in next mail.

OK, thanks. If think 0001-0008 are ready to go, with some minor tweaks
per above (tuple vs. tuples etc.), and the question about the recheck
flag. If you can do these tweaks, I'll get that committed today and we
can try to get a couple more patches in tomorrow.

Sounds reasonable?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#104Tom Lane
tgl@sss.pgh.pa.us
In reply to: Melanie Plageman (#101)
Re: BitmapHeapScan streaming read user and prelim refactoring

Melanie Plageman <melanieplageman@gmail.com> writes:

On Sat, Apr 06, 2024 at 02:51:45AM +0200, Tomas Vondra wrote:

* The one question I'm somewhat unsure about is why Tom chose to use the
"wrong" recheck flag in the 2017 commit, when the correct recheck flag
is readily available. Surely that had a reason, right? But I can't think
of one ...

See above.

Hi, I hadn't been paying attention to this thread, but Melanie pinged
me off-list about this question. I think it's just a flat-out
oversight in 7c70996eb. Looking at the mailing list thread
(particularly [1]/messages/by-id/a6434d5c-ed8d-b09c-a7c3-b2d1677e35b3@postgrespro.ru[2]/messages/by-id/5974.1509573988@sss.pgh.pa.us), it seems that Alexander hadn't really addressed
the question of when to prefetch at all, but just skipped prefetch if
the current page was skippable:

+		/*
+		 * If we did not need to fetch the current page,
+		 * we probably will not need to fetch the next.
+		 */
+		return;

It looks like I noticed that we could check the appropriate VM bits,
but failed to notice that we could easily check the appropriate
recheck flag as well. Feel free to change it.

regards, tom lane

[1]: /messages/by-id/a6434d5c-ed8d-b09c-a7c3-b2d1677e35b3@postgrespro.ru
[2]: /messages/by-id/5974.1509573988@sss.pgh.pa.us

#105Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#103)
9 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Apr 06, 2024 at 04:57:51PM +0200, Tomas Vondra wrote:

On 4/6/24 15:40, Melanie Plageman wrote:

On Sat, Apr 06, 2024 at 02:51:45AM +0200, Tomas Vondra wrote:

On 4/6/24 01:53, Melanie Plageman wrote:

On Fri, Apr 05, 2024 at 04:06:34AM -0400, Melanie Plageman wrote:

On Thu, Apr 04, 2024 at 04:35:45PM +0200, Tomas Vondra wrote:

On 4/4/24 00:57, Melanie Plageman wrote:

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

I'd focus on the first ~8-9 commits or so for now, we can commit more if
things go reasonably well.

Sounds good. I will spend cleanup time on 0010-0013 tomorrow but would
love to know if you agree with the direction before I spend more time.

In attached v16, I've split out 0010-0013 into 0011-0017. I think it is
much easier to understand.

Anyway, I've attached it as .tgz in order to not confuse cfbot. All the
review comments are marked with XXX, so grep for that in the patches.
There's two separate patches - the first one suggests a code change, so
it was better to not merge that with your code. The second has just a
couple XXX comments, I'm not sure why I kept it separate.

A couple review comments:

* I think 0001-0009 are 99% ready to. I reworded some of the commit
messages a bit - I realize it's a bit bold, considering you're native
speaker and I'm not. If you could check I didn't make it worse, that
would be great.

Attached v17 has *only* patches 0001-0009 with these changes. I will
work on applying the remaining patches, addressing feedback, and adding
comments next.

I have reviewed and incorporated all of your feedback on these patches.
Attached v17 is your exact patches with 1 or 2 *very* slight tweaks to
commit messages (comma splice removal and single word adjustments) as
well as the changes listed below:

I have open questions on the following:

- 0003: should it be SO_NEED_TUPLES and need_tuples (instead of
SO_NEED_TUPLE and need_tuple)?

I think SO_NEED_TUPLES is more accurate, as we need all tuples from the
block. But either would work.

Attached v18 changes it to TUPLES/tuples

- 0009 (your 0010)
- Should I mention in the commit message that we added blockno and
pfblockno in the BitmapHeapScanState only for validation or is that
too specific?

For the commit message I'd say it's too specific, I'd put it in the
comment before the struct.

It is in the comment for the struct

- I'm worried this comment is vague and or potentially not totally
correct. Should we remove it? I don't think we have conclusive proof
that this is true.
/*
* Adjusting the prefetch iterator before invoking
* table_scan_bitmap_next_block() keeps prefetch distance higher across
* the parallel workers.
*/

TBH it's not clear to me what "higher across parallel workers" means.
But it sure shouldn't claim things that we think may not be correct. I
don't have a good idea how to reword it, though.

I realized it makes more sense to add a FIXME (I used XXX. I'm not when
to use what) with a link to the message where Andres describes why he
thinks it is a bug. If we plan on fixing it, it is good to have a record
of that. And it makes it easier to put a clear and accurate comment.
Done in 0009.

OK, thanks. If think 0001-0008 are ready to go, with some minor tweaks
per above (tuple vs. tuples etc.), and the question about the recheck
flag. If you can do these tweaks, I'll get that committed today and we
can try to get a couple more patches in tomorrow.

Sounds good.

- Melanie

Attachments:

v18-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From 3e80ba8914dd5876ab921ca39540be3b639236f7 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v18 01/10] BitmapHeapScan: begin scan after bitmap creation

It makes more sense for BitmapHeapScan to scan the index, build the
bitmap, and only then begin the scan on the underlying table.

This is mostly a cosmetic change for now, but later commits will need
to pass parameters to table_beginscan_bm() that are unavailable in
ExecInitBitmapHeapScan().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 27 +++++++++++++++++------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aabe..c8c466e3c5c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = table_beginscan_bm(node->ss.ss_currentRelation,
+									  node->ss.ps.state->es_snapshot,
+									  0,
+									  NULL);
+
+			node->ss.ss_currentScanDesc = scan;
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +616,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +694,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +801,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v18-0002-BitmapHeapScan-postpone-setting-can_skip_fetch.patchtext/x-diff; charset=us-asciiDownload
From 60e75bbf91bf06832402daa5d3c30bc99401c2f2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v18 02/10] BitmapHeapScan: postpone setting can_skip_fetch

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() instead of
in ExecInitBitmapHeapScan(). This is a preliminary step to pushing the
skip fetch optimization into heap AM code.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c8c466e3c5c..2148a21531a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -743,16 +753,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v18-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From 6af2d6cbbbe53e94f09fdb78fdfaf1f410359114 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:34:25 +0200
Subject: [PATCH v18 03/10] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM-specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block. The layering violation is
still present in BitmapHeapScans's prefetching code, which uses the
visibility map to decide whether or not to prefetch a block. However,
this can be addressed independently.

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  15 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  12 ++-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 105 insertions(+), 93 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index dada2ecd1e3..01bb2f4cc16 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -967,6 +967,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1055,6 +1057,14 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
+	Assert(scan->rs_empty_tuples_pending == 0);
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1074,6 +1084,11 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+		ReleaseBuffer(scan->rs_vmbuffer);
+
+	Assert(scan->rs_empty_tuples_pending == 0);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3e7a6b5548b..58de2c82a70 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2198,6 +2199,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2310,6 +2329,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2148a21531a..5f768701a5e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,10 +185,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			bool		need_tuples = false;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			need_tuples = (node->ss.ps.plan->qual != NIL ||
+						   node->ss.ps.plan->targetlist != NIL);
+
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
 									  0,
-									  NULL);
+									  NULL,
+									  need_tuples);
 
 			node->ss.ss_currentScanDesc = scan;
 		}
@@ -208,7 +212,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid_block;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -229,37 +233,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid_block = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid_block)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -302,52 +283,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -519,7 +481,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -570,7 +532,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -640,8 +602,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -651,7 +611,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -696,8 +655,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -741,8 +698,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -753,7 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2765efc4e5e..750ea30852e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,6 +76,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e7eeb754098..be198fa3158 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -63,6 +63,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLES.
+	 */
+	SO_NEED_TUPLES = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -937,10 +944,13 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
+	if (need_tuple)
+		flags |= SO_NEED_TUPLES;
+
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e57ebd72887..fa2f70b7a48 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,10 +1794,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1817,9 +1814,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v18-0004-Use-prefetch-block-recheck-value-to-determine-sk.patchtext/x-diff; charset=us-asciiDownload
From 08af70f3becef4bd1de9aac3943b0b2a8b15e788 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v18 04/10] Use prefetch block recheck value to determine
 skip_fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it should skip prefetching
the proposed prefetch block. As explained in the comment, this assumed
the index AM will report the same recheck value for the future page as
it did for the current page - but there's no guarantee.

This only affects prefetching - we may prefetch blocks unecessarily and
not prefetch blocks that will be needed. But we don't need to rely on
that assumption - we know the recheck flag for the block we're
considering prefetching.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Tom Lane
Discussion: https://postgr.es/m/1939305.1712415547%40sss.pgh.pa.us
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5f768701a5e..6f843908032 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -475,14 +475,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -533,7 +528,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v18-0005-Change-BitmapAdjustPrefetchIterator-to-accept-Bl.patchtext/x-diff; charset=us-asciiDownload
From 391747a1235b1a29bd8beed127418bbd584ba10d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v18 05/10] Change BitmapAdjustPrefetchIterator to accept
 BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only, so that we
can move away from using the TBMIterateResult outside of table AM
specific code.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6f843908032..6b48a6d8350 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -231,7 +231,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid_block = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -342,7 +342,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -361,7 +361,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v18-0006-BitmapHeapScan-Reduce-scope-of-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From 8bd31f41e00ec958cfc8c309509cdd2e93020f0b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v18 06/10] BitmapHeapScan: Reduce scope of tbmiterator local
 variables

A future patch will change where tbmiterators are initialized and saved.
To keep that diff easier to understand, move them into a tighter scope.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6b48a6d8350..fcbc8664508 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -207,6 +203,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -222,9 +220,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v18-0007-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From e35e6e050e79028f978f3e59c5728c6d85c0becb Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v18 07/10] table_scan_bitmap_next_block counts lossy and exact
 pages

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So the table AM must keep
track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap for the purposes of EXPLAIN counters.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 58de2c82a70..eb56dfe4e93 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2316,6 +2317,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fcbc8664508..da201a14385 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -210,8 +210,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -231,14 +229,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index be198fa3158..8c75a4c038c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,6 +789,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy_pages is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, exact_pages is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -804,7 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1971,17 +1975,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy_pages is incremented is the block's
+ * representation in the bitmap is lossy; otherwise, exact_pages is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1992,7 +2000,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v18-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From 426c2e04782242589d67f6a87fb9327c0fc1eaa9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v18 08/10] Remove table_scan_bitmap_next_tuple parameter
 tbmres

Future commits will push all of the logic for choosing the next block
into the table AM specific code. The table AM will be responsible for
iterating and reading in the right blocks.

Thus, it no longer makes sense to use the TBMIterateResult (which
contains a block number) as a means of communication between
table_scan_bitmap_next_tuple() and table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index eb56dfe4e93..f99e6efd757 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2327,7 +2327,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index da201a14385..306bca801d7 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -279,7 +279,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8c75a4c038c..697b5488b10 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,10 +780,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -814,15 +811,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2015,7 +2007,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2027,7 +2018,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v18-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From d19f6290f0cc783979c0c2556f0ac908b9c0adb2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 09:04:01 -0400
Subject: [PATCH v18 09/10] Make table_scan_bitmap_next_block() async-friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on tuples on the page. This
could happen when there were no visible tuples on the page or, due to
concurrent activity on the table, the block returned by the iterator is
past the end of the table recorded when the scan started.

That forced the caller to be responsible for determining if additional
blocks should be fetched and for invoking table_scan_bitmap_next_block()
for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
beginning of the scan) and for table_scan_bitmap_next_tuple() to return
false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to the
table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  58 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 186 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 194 insertions(+), 137 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f99e6efd757..903cb80157e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,18 +2188,52 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2218,16 +2252,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2322,7 +2347,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 306bca801d7..01703bd4865 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,7 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +160,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -203,48 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -265,45 +235,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -329,13 +310,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -349,14 +334,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmapheapscans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -381,7 +373,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -459,6 +454,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -516,6 +512,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -577,12 +575,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -590,13 +584,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -627,28 +621,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -681,8 +671,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -690,9 +678,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 697b5488b10..68a479496d7 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -773,19 +774,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
@@ -804,7 +800,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -942,12 +938,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -994,6 +994,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1004,6 +1019,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1967,19 +1997,18 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy_pages is incremented is the block's
- * representation in the bitmap is lossy; otherwise, exact_pages is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented is the block's representation in the bitmap is lossy; otherwise,
+ * exact_pages is incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1992,9 +2021,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fa2f70b7a48..d96703b04d4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

#106Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#105)
21 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Apr 06, 2024 at 12:04:23PM -0400, Melanie Plageman wrote:

On Sat, Apr 06, 2024 at 04:57:51PM +0200, Tomas Vondra wrote:

On 4/6/24 15:40, Melanie Plageman wrote:

On Sat, Apr 06, 2024 at 02:51:45AM +0200, Tomas Vondra wrote:

On 4/6/24 01:53, Melanie Plageman wrote:

On Fri, Apr 05, 2024 at 04:06:34AM -0400, Melanie Plageman wrote:

On Thu, Apr 04, 2024 at 04:35:45PM +0200, Tomas Vondra wrote:

On 4/4/24 00:57, Melanie Plageman wrote:

On Sun, Mar 31, 2024 at 11:45:51AM -0400, Melanie Plageman wrote:

I'd focus on the first ~8-9 commits or so for now, we can commit more if
things go reasonably well.

Sounds good. I will spend cleanup time on 0010-0013 tomorrow but would
love to know if you agree with the direction before I spend more time.

In attached v16, I've split out 0010-0013 into 0011-0017. I think it is
much easier to understand.

Anyway, I've attached it as .tgz in order to not confuse cfbot. All the
review comments are marked with XXX, so grep for that in the patches.
There's two separate patches - the first one suggests a code change, so
it was better to not merge that with your code. The second has just a
couple XXX comments, I'm not sure why I kept it separate.

A couple review comments:

* I think 0001-0009 are 99% ready to. I reworded some of the commit
messages a bit - I realize it's a bit bold, considering you're native
speaker and I'm not. If you could check I didn't make it worse, that
would be great.

Attached v17 has *only* patches 0001-0009 with these changes. I will
work on applying the remaining patches, addressing feedback, and adding
comments next.

I have reviewed and incorporated all of your feedback on these patches.
Attached v17 is your exact patches with 1 or 2 *very* slight tweaks to
commit messages (comma splice removal and single word adjustments) as
well as the changes listed below:

I have open questions on the following:

- 0003: should it be SO_NEED_TUPLES and need_tuples (instead of
SO_NEED_TUPLE and need_tuple)?

I think SO_NEED_TUPLES is more accurate, as we need all tuples from the
block. But either would work.

Attached v18 changes it to TUPLES/tuples

- 0009 (your 0010)
- Should I mention in the commit message that we added blockno and
pfblockno in the BitmapHeapScanState only for validation or is that
too specific?

For the commit message I'd say it's too specific, I'd put it in the
comment before the struct.

It is in the comment for the struct

- I'm worried this comment is vague and or potentially not totally
correct. Should we remove it? I don't think we have conclusive proof
that this is true.
/*
* Adjusting the prefetch iterator before invoking
* table_scan_bitmap_next_block() keeps prefetch distance higher across
* the parallel workers.
*/

TBH it's not clear to me what "higher across parallel workers" means.
But it sure shouldn't claim things that we think may not be correct. I
don't have a good idea how to reword it, though.

I realized it makes more sense to add a FIXME (I used XXX. I'm not when
to use what) with a link to the message where Andres describes why he
thinks it is a bug. If we plan on fixing it, it is good to have a record
of that. And it makes it easier to put a clear and accurate comment.
Done in 0009.

OK, thanks. If think 0001-0008 are ready to go, with some minor tweaks
per above (tuple vs. tuples etc.), and the question about the recheck
flag. If you can do these tweaks, I'll get that committed today and we
can try to get a couple more patches in tomorrow.

Attached v19 rebases the rest of the commits from v17 over the first
nine patches from v18. All patches 0001-0009 are unchanged from v18. I
have made updates and done cleanup on 0010-0021.

- Melanie

Attachments:

v19-0006-BitmapHeapScan-Reduce-scope-of-tbmiterator-local.patchtext/x-diff; charset=us-asciiDownload
From 3259c5a3d469d597d6cec7321999803baef5ab73 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v19 06/21] BitmapHeapScan: Reduce scope of tbmiterator local
 variables

A future patch will change where tbmiterators are initialized and saved.
To keep that diff easier to understand, move them into a tighter scope.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6b48a6d8350..fcbc8664508 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -71,8 +71,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
 	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -85,10 +83,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
 	tbmres = node->tbmres;
 
 	/*
@@ -105,6 +99,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,7 +110,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_iterate(tbm);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -166,8 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
@@ -207,6 +203,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		node->tbmiterator = tbmiterator;
+		node->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
 	}
 
@@ -222,9 +220,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		if (tbmres == NULL)
 		{
 			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
+				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
 			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
+				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
 			if (tbmres == NULL)
 			{
 				/* no more entries in the bitmap */
-- 
2.40.1

v19-0004-Use-prefetch-block-recheck-value-to-determine-sk.patchtext/x-diff; charset=us-asciiDownload
From b257f9c4804e73d9d1790108d94d62a81cecdccc Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:03:24 -0500
Subject: [PATCH v19 04/21] Use prefetch block recheck value to determine
 skip_fetch

As of 7c70996ebf0949b142a9, BitmapPrefetch() used the recheck flag for
the current block to determine whether or not it should skip prefetching
the proposed prefetch block. As explained in the comment, this assumed
the index AM will report the same recheck value for the future page as
it did for the current page - but there's no guarantee.

This only affects prefetching - we may prefetch blocks unecessarily and
not prefetch blocks that will be needed. But we don't need to rely on
that assumption - we know the recheck flag for the block we're
considering prefetching.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Tom Lane
Discussion: https://postgr.es/m/1939305.1712415547%40sss.pgh.pa.us
---
 src/backend/executor/nodeBitmapHeapscan.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5f768701a5e..6f843908032 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -475,14 +475,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * skip this prefetch call, but continue to run the prefetch
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
-				 *
-				 * This depends on the assumption that the index AM will
-				 * report the same recheck flag for this future heap page as
-				 * it did for the current heap page; which is not a certainty
-				 * but is true in many cases.
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
@@ -533,7 +528,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  (node->tbmres ? !node->tbmres->recheck : false) &&
+							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
-- 
2.40.1

v19-0005-Change-BitmapAdjustPrefetchIterator-to-accept-Bl.patchtext/x-diff; charset=us-asciiDownload
From 0a96e606398c6dd370ccc93246f0edcbfda10c79 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 19:04:48 -0500
Subject: [PATCH v19 05/21] Change BitmapAdjustPrefetchIterator to accept
 BlockNumber

BitmapAdjustPrefetchIterator() only used the blockno member of the
passed in TBMIterateResult to ensure that the prefetch iterator and
regular iterator stay in sync. Pass it the BlockNumber only, so that we
can move away from using the TBMIterateResult outside of table AM
specific code.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6f843908032..6b48a6d8350 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -52,7 +52,7 @@
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												TBMIterateResult *tbmres);
+												BlockNumber blockno);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -231,7 +231,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				break;
 			}
 
-			BitmapAdjustPrefetchIterator(node, tbmres);
+			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
 			valid_block = table_scan_bitmap_next_block(scan, tbmres);
 
@@ -342,7 +342,7 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
  */
 static inline void
 BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 TBMIterateResult *tbmres)
+							 BlockNumber blockno)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -361,7 +361,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			/* Do not let the prefetch iterator get behind the main one */
 			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 
-			if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+			if (tbmpre == NULL || tbmpre->blockno != blockno)
 				elog(ERROR, "prefetch and main iterators are out of sync");
 		}
 		return;
-- 
2.40.1

v19-0001-BitmapHeapScan-begin-scan-after-bitmap-creation.patchtext/x-diff; charset=us-asciiDownload
From 3e80ba8914dd5876ab921ca39540be3b639236f7 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:50:29 -0500
Subject: [PATCH v19 01/21] BitmapHeapScan: begin scan after bitmap creation

It makes more sense for BitmapHeapScan to scan the index, build the
bitmap, and only then begin the scan on the underlying table.

This is mostly a cosmetic change for now, but later commits will need
to pass parameters to table_beginscan_bm() that are unavailable in
ExecInitBitmapHeapScan().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 27 +++++++++++++++++------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cee7f45aabe..c8c466e3c5c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -178,6 +178,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 #endif							/* USE_PREFETCH */
 		}
+
+		/*
+		 * If this is the first scan of the underlying table, create the table
+		 * scan descriptor and begin the scan.
+		 */
+		if (!scan)
+		{
+			scan = table_beginscan_bm(node->ss.ss_currentRelation,
+									  node->ss.ps.state->es_snapshot,
+									  0,
+									  NULL);
+
+			node->ss.ss_currentScanDesc = scan;
+		}
+
 		node->initialized = true;
 	}
 
@@ -601,7 +616,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss.ss_currentScanDesc)
+		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	if (node->tbmiterator)
@@ -678,7 +694,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * close heap scan
 	 */
-	table_endscan(scanDesc);
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 }
 
 /* ----------------------------------------------------------------
@@ -783,11 +801,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 
 	scanstate->ss.ss_currentRelation = currentRelation;
 
-	scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
-														  estate->es_snapshot,
-														  0,
-														  NULL);
-
 	/*
 	 * all done.
 	 */
-- 
2.40.1

v19-0002-BitmapHeapScan-postpone-setting-can_skip_fetch.patchtext/x-diff; charset=us-asciiDownload
From 60e75bbf91bf06832402daa5d3c30bc99401c2f2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 14:38:41 -0500
Subject: [PATCH v19 02/21] BitmapHeapScan: postpone setting can_skip_fetch

Set BitmapHeapScanState->can_skip_fetch in BitmapHeapNext() instead of
in ExecInitBitmapHeapScan(). This is a preliminary step to pushing the
skip fetch optimization into heap AM code.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c8c466e3c5c..2148a21531a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,6 +105,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
+								node->ss.ps.plan->targetlist == NIL);
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -743,16 +753,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-
-	/*
-	 * We can potentially skip fetching heap pages if we do not need any
-	 * columns of the table, either for checking non-indexable quals or for
-	 * returning data.  This test is a bit simplistic, as it checks the
-	 * stronger condition that there's no qual or return tlist at all.  But in
-	 * most cases it's probably not worth working harder than that.
-	 */
-	scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
-								 node->scan.plan.targetlist == NIL);
+	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
-- 
2.40.1

v19-0003-Push-BitmapHeapScan-skip-fetch-optimization-into.patchtext/x-diff; charset=us-asciiDownload
From d52013ee0a11bf0f006df2270c7de2af48598a27 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Thu, 4 Apr 2024 15:34:25 +0200
Subject: [PATCH v19 03/21] Push BitmapHeapScan skip fetch optimization into
 table AM

7c70996ebf0949b142 introduced an optimization to allow bitmap table
scans to skip fetching a block from the heap if none of the underlying
data was needed and the block is marked all visible in the visibility
map. With the addition of table AMs, a FIXME was added to this code
indicating that it should be pushed into table AM-specific code, as not
all table AMs may use a visibility map in the same way.

Resolve this FIXME for the current block. The layering violation is
still present in BitmapHeapScans's prefetching code, which uses the
visibility map to decide whether or not to prefetch a block. However,
this can be addressed independently.

Author: Melanie Plageman
Reviewed-by: Andres Freund, Heikki Linnakangas, Tomas Vondra, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  15 +++
 src/backend/access/heap/heapam_handler.c  |  29 +++++
 src/backend/executor/nodeBitmapHeapscan.c | 124 +++++++---------------
 src/include/access/heapam.h               |  10 ++
 src/include/access/tableam.h              |  12 ++-
 src/include/nodes/execnodes.h             |   8 +-
 6 files changed, 105 insertions(+), 93 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index dada2ecd1e3..9be3a4b1afb 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -967,6 +967,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1055,6 +1057,14 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
+	scan->rs_empty_tuples_pending = 0;
+
 	/*
 	 * reinitialize scan descriptor
 	 */
@@ -1074,6 +1084,11 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
+	if (BufferIsValid(scan->rs_vmbuffer))
+		ReleaseBuffer(scan->rs_vmbuffer);
+
+	scan->rs_empty_tuples_pending = 0;
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3e7a6b5548b..58de2c82a70 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -27,6 +27,7 @@
 #include "access/syncscan.h"
 #include "access/tableam.h"
 #include "access/tsmapi.h"
+#include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
@@ -2198,6 +2199,24 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(hscan->rs_empty_tuples_pending >= 0);
+
+		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
 	/*
 	 * Ignore any claimed entries past what we think is the end of the
 	 * relation. It may have been extended after the start of our scan (we
@@ -2310,6 +2329,16 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	Page		page;
 	ItemId		lp;
 
+	if (hscan->rs_empty_tuples_pending > 0)
+	{
+		/*
+		 * If we don't have to fetch the tuple, just return nulls.
+		 */
+		ExecStoreAllNullTuple(slot);
+		hscan->rs_empty_tuples_pending--;
+		return true;
+	}
+
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2148a21531a..5f768701a5e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -105,16 +105,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		node->can_skip_fetch = (node->ss.ps.plan->qual == NIL &&
-								node->ss.ps.plan->targetlist == NIL);
-
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -195,10 +185,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 */
 		if (!scan)
 		{
+			bool		need_tuples = false;
+
+			/*
+			 * We can potentially skip fetching heap pages if we do not need
+			 * any columns of the table, either for checking non-indexable
+			 * quals or for returning data.  This test is a bit simplistic, as
+			 * it checks the stronger condition that there's no qual or return
+			 * tlist at all. But in most cases it's probably not worth working
+			 * harder than that.
+			 */
+			need_tuples = (node->ss.ps.plan->qual != NIL ||
+						   node->ss.ps.plan->targetlist != NIL);
+
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
 									  0,
-									  NULL);
+									  NULL,
+									  need_tuples);
 
 			node->ss.ss_currentScanDesc = scan;
 		}
@@ -208,7 +212,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		skip_fetch;
+		bool		valid_block;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -229,37 +233,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres);
 
+			valid_block = table_scan_bitmap_next_block(scan, tbmres);
+
 			if (tbmres->ntuples >= 0)
 				node->exact_pages++;
 			else
 				node->lossy_pages++;
 
-			/*
-			 * We can skip fetching the heap page if we don't need any fields
-			 * from the heap, and the bitmap entries don't need rechecking,
-			 * and all tuples on the page are visible to our transaction.
-			 *
-			 * XXX: It's a layering violation that we do these checks above
-			 * tableam, they should probably moved below it at some point.
-			 */
-			skip_fetch = (node->can_skip_fetch &&
-						  !tbmres->recheck &&
-						  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-										 tbmres->blockno,
-										 &node->vmbuffer));
-
-			if (skip_fetch)
-			{
-				/* can't be lossy in the skip_fetch case */
-				Assert(tbmres->ntuples >= 0);
-
-				/*
-				 * The number of tuples on this page is put into
-				 * node->return_empty_tuples.
-				 */
-				node->return_empty_tuples = tbmres->ntuples;
-			}
-			else if (!table_scan_bitmap_next_block(scan, tbmres))
+			if (!valid_block)
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
@@ -302,52 +283,33 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * should happen only when we have determined there is still something
 		 * to do on the current page, else we may uselessly prefetch the same
 		 * page we are just about to request for real.
-		 *
-		 * XXX: It's a layering violation that we do these checks above
-		 * tableam, they should probably moved below it at some point.
 		 */
 		BitmapPrefetch(node, scan);
 
-		if (node->return_empty_tuples > 0)
+		/*
+		 * Attempt to fetch tuple from AM.
+		 */
+		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
 		{
-			/*
-			 * If we don't have to fetch the tuple, just return nulls.
-			 */
-			ExecStoreAllNullTuple(slot);
-
-			if (--node->return_empty_tuples == 0)
-			{
-				/* no more tuples to return in the next round */
-				node->tbmres = tbmres = NULL;
-			}
+			/* nothing more to look at on this page */
+			node->tbmres = tbmres = NULL;
+			continue;
 		}
-		else
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (tbmres->recheck)
 		{
-			/*
-			 * Attempt to fetch tuple from AM.
-			 */
-			if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				/* nothing more to look at on this page */
-				node->tbmres = tbmres = NULL;
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
 				continue;
 			}
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (tbmres->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
 		}
 
 		/* OK to return this tuple */
@@ -519,7 +481,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * it did for the current heap page; which is not a certainty
 				 * but is true in many cases.
 				 */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -570,7 +532,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				}
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (node->can_skip_fetch &&
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  (node->tbmres ? !node->tbmres->recheck : false) &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
@@ -640,8 +602,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
@@ -651,7 +611,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->initialized = false;
 	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
-	node->vmbuffer = InvalidBuffer;
 	node->pvmbuffer = InvalidBuffer;
 
 	ExecScanReScan(&node->ss);
@@ -696,8 +655,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
-	if (node->vmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->vmbuffer);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 
@@ -741,8 +698,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->tbm = NULL;
 	scanstate->tbmiterator = NULL;
 	scanstate->tbmres = NULL;
-	scanstate->return_empty_tuples = 0;
-	scanstate->vmbuffer = InvalidBuffer;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -753,7 +708,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
-	scanstate->can_skip_fetch = false;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2765efc4e5e..750ea30852e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,6 +76,16 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/*
+	 * These fields are only used for bitmap scans for the "skip fetch"
+	 * optimization. Bitmap scans needing no fields from the heap may skip
+	 * fetching an all visible block, instead using the number of tuples per
+	 * block reported by the bitmap to determine how many NULL-filled tuples
+	 * to return.
+	 */
+	Buffer		rs_vmbuffer;
+	int			rs_empty_tuples_pending;
+
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
 	int			rs_ntuples;		/* number of visible tuples on page */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e7eeb754098..be198fa3158 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -63,6 +63,13 @@ typedef enum ScanOptions
 
 	/* unregister snapshot at scan end? */
 	SO_TEMP_SNAPSHOT = 1 << 9,
+
+	/*
+	 * At the discretion of the table AM, bitmap table scans may be able to
+	 * skip fetching a block from the table if none of the table data is
+	 * needed. If table data may be needed, set SO_NEED_TUPLES.
+	 */
+	SO_NEED_TUPLES = 1 << 10,
 }			ScanOptions;
 
 /*
@@ -937,10 +944,13 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key)
+				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
+	if (need_tuple)
+		flags |= SO_NEED_TUPLES;
+
 	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e57ebd72887..fa2f70b7a48 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1794,10 +1794,7 @@ typedef struct ParallelBitmapHeapState
  *		tbm				   bitmap obtained from child index scan(s)
  *		tbmiterator		   iterator for scanning current pages
  *		tbmres			   current-page data
- *		can_skip_fetch	   can we potentially skip tuple fetches in this scan?
- *		return_empty_tuples number of empty tuples to return
- *		vmbuffer		   buffer for visibility-map lookups
- *		pvmbuffer		   ditto, for prefetched pages
+ *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1817,9 +1814,6 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	TBMIterator *tbmiterator;
 	TBMIterateResult *tbmres;
-	bool		can_skip_fetch;
-	int			return_empty_tuples;
-	Buffer		vmbuffer;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-- 
2.40.1

v19-0007-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From 2b48a84efa072ff91c80a8a844c09ed8e403578f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v19 07/21] table_scan_bitmap_next_block counts lossy and exact
 pages

Future commits will remove the TBMIterateResult from BitmapHeapNext() --
pushing it into the table AM-specific code. So the table AM must keep
track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap for the purposes of EXPLAIN counters.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 58de2c82a70..eb56dfe4e93 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2316,6 +2317,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fcbc8664508..da201a14385 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -210,8 +210,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -231,14 +229,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index be198fa3158..8c75a4c038c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,6 +789,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy_pages is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, exact_pages is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -804,7 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1971,17 +1975,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy_pages is incremented is the block's
+ * representation in the bitmap is lossy; otherwise, exact_pages is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1992,7 +2000,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v19-0008-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From c7cc646b2715934158bc0f6a499ddc1f60d43e01 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v19 08/21] Remove table_scan_bitmap_next_tuple parameter
 tbmres

Future commits will push all of the logic for choosing the next block
into the table AM specific code. The table AM will be responsible for
iterating and reading in the right blocks.

Thus, it no longer makes sense to use the TBMIterateResult (which
contains a block number) as a means of communication between
table_scan_bitmap_next_tuple() and table_scan_bitmap_next_block().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index eb56dfe4e93..f99e6efd757 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2327,7 +2327,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index da201a14385..306bca801d7 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -279,7 +279,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8c75a4c038c..697b5488b10 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,10 +780,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -814,15 +811,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2015,7 +2007,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2027,7 +2018,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v19-0009-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 7604cb907fc5c056fe24d7c6881e1a731b25d54d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 09:04:01 -0400
Subject: [PATCH v19 09/21] Make table_scan_bitmap_next_block() async-friendly

table_scan_bitmap_next_block() previously returned false if we did not
wish to call table_scan_bitmap_next_tuple() on tuples on the page. This
could happen when there were no visible tuples on the page or, due to
concurrent activity on the table, the block returned by the iterator is
past the end of the table recorded when the scan started.

That forced the caller to be responsible for determining if additional
blocks should be fetched and for invoking table_scan_bitmap_next_block()
for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
beginning of the scan) and for table_scan_bitmap_next_tuple() to return
false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to the
table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  58 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 186 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 194 insertions(+), 137 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f99e6efd757..903cb80157e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,18 +2188,52 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2218,16 +2252,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2322,7 +2347,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 306bca801d7..01703bd4865 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,7 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -83,7 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -111,7 +108,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			node->tbm = tbm;
 			tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -164,7 +160,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			/* Allocate a private iterator and attach the shared state to it */
 			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -203,48 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		node->tbmiterator = tbmiterator;
-		node->shared_tbmiterator = shared_tbmiterator;
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(node->tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(node->shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -265,45 +235,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -329,13 +310,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -349,14 +334,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmapheapscans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -381,7 +373,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -459,6 +454,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -516,6 +512,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -577,12 +575,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -590,13 +584,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -627,28 +621,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -681,8 +671,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -690,9 +678,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..92b829cebc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,6 +43,10 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
+	/* Only used for Bitmap table scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 697b5488b10..68a479496d7 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -773,19 +774,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
@@ -804,7 +800,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -942,12 +938,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -994,6 +994,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1004,6 +1019,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1967,19 +1997,18 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy_pages is incremented is the block's
- * representation in the bitmap is lossy; otherwise, exact_pages is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented is the block's representation in the bitmap is lossy; otherwise,
+ * exact_pages is incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1992,9 +2021,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fa2f70b7a48..d96703b04d4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v19-0010-Add-UnifiedTBMIterator-common-interface-for-TBMI.patchtext/x-diff; charset=us-asciiDownload
From 154e570a6cc0d1950b0b327a445f7f3c12e00892 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:41:05 -0400
Subject: [PATCH v19 10/21] Add UnifiedTBMIterator: common interface for
 TBMIterators

Add a new struct, UnifiedTBMIterator, which encapsulates the serial and
parallel TID Bitmap iterator interfaces. This simplifies call sites for
callers supporting both parallel and serial TID bitmap access.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/nodes/tidbitmap.c    | 55 ++++++++++++++++++++++++++++++++
 src/include/nodes/tidbitmap.h    | 17 ++++++++++
 src/tools/pgindent/typedefs.list |  1 +
 3 files changed, 73 insertions(+)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..c0628fa8a56 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -1556,3 +1556,58 @@ tbm_calculate_entries(double maxbytes)
 
 	return nbuckets;
 }
+
+/*
+ * Start iteration on a shared or non-shared bitmap iterator. Note that tbm
+ * will only be provided by serial BitmapHeapScan callers. dsa and dsp will
+ * only be provided by parallel BitmapHeapScan callers.
+ */
+void
+unified_tbm_begin_iterate(UnifiedTBMIterator *iterator, TIDBitmap *tbm,
+						  dsa_area *dsa, dsa_pointer dsp)
+{
+	Assert(iterator);
+
+	iterator->serial = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = false;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+		iterator->parallel = tbm_attach_shared_iterate(dsa, dsp);
+	else
+		iterator->serial = tbm_begin_iterate(tbm);
+}
+
+/*
+ * Clean up shared or non-shared bitmap iterator.
+ */
+void
+unified_tbm_end_iterate(UnifiedTBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		tbm_end_iterate(iterator->serial);
+	else if (iterator->parallel)
+		tbm_end_shared_iterate(iterator->parallel);
+
+	iterator->serial = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = true;
+}
+
+/*
+ * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
+ */
+TBMIterateResult *
+unified_tbm_iterate(UnifiedTBMIterator *iterator)
+{
+	Assert(iterator);
+	Assert(!iterator->exhausted);
+
+	if (iterator->serial)
+		return tbm_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..40dbcf7d3d8 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -46,6 +46,17 @@ typedef struct TBMIterateResult
 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
 } TBMIterateResult;
 
+/*
+ * Callers with both serial and parallel implementations can use this unified
+ * API.
+ */
+typedef struct UnifiedTBMIterator
+{
+	TBMIterator *serial;
+	TBMSharedIterator *parallel;
+	bool		exhausted;
+} UnifiedTBMIterator;
+
 /* function prototypes in nodes/tidbitmap.c */
 
 extern TIDBitmap *tbm_create(long maxbytes, dsa_area *dsa);
@@ -72,4 +83,10 @@ extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
 													dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+extern void unified_tbm_begin_iterate(UnifiedTBMIterator *iterator, TIDBitmap *tbm,
+									  dsa_area *dsa, dsa_pointer dsp);
+extern void unified_tbm_end_iterate(UnifiedTBMIterator *iterator);
+extern TBMIterateResult *unified_tbm_iterate(UnifiedTBMIterator *iterator);
+
+
 #endif							/* TIDBITMAP_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index f87e8b80ec0..71686e79abb 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2996,6 +2996,7 @@ UV
 UVersionInfo
 UnicodeNormalizationForm
 UnicodeNormalizationQC
+UnifiedTBMIterator
 Unique
 UniquePath
 UniquePathMethod
-- 
2.40.1

v19-0011-BitmapHeapScan-initialize-some-prefetch-state-el.patchtext/x-diff; charset=us-asciiDownload
From 22e1988956d6e32d8012b1478842f6af10928c1f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:51:11 -0400
Subject: [PATCH v19 11/21] BitmapHeapScan initialize some prefetch state
 elsewhere

These members can be initialized elsewhere. This makes it more
straightforward to use the recently committed UnifiedTBMIterator API in
BitmapHeapScan.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 01703bd4865..23b21247dea 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -111,11 +111,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
-			{
 				node->prefetch_iterator = tbm_begin_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
 #endif							/* USE_PREFETCH */
 		}
 		else
@@ -144,13 +140,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				{
 					pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
 				}
 #endif
 
@@ -591,6 +580,9 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
 	node->pfblockno = InvalidBlockNumber;
+	/* Only used for serial BHS */
+	node->prefetch_pages = 0;
+	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -676,7 +668,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->lossy_pages = 0;
 	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
+	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
@@ -812,7 +804,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -839,6 +831,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
+	pstate->prefetch_pages = 0;
+	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-- 
2.40.1

v19-0012-BitmapHeapScan-Use-UnifiedTBMIterator.patchtext/x-diff; charset=us-asciiDownload
From 455604a6fb9fcfd5d87a48ddbcc6dd90f3ea0192 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:57:10 -0400
Subject: [PATCH v19 12/21] BitmapHeapScan: Use UnifiedTBMIterator

BitmapHeapScan can be simplified by using the recently introduced
UnifiedTBMIterator interface for accessing shared or non-shared
TBMIterators.

This required a bit of reorganization of the !node->initialized path in
BitmapHeapNext().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 116 +++++++++-------------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  40 ++------
 src/include/nodes/execnodes.h             |   6 +-
 5 files changed, 57 insertions(+), 117 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 903cb80157e..ec6128e1d65 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2208,10 +2208,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+		tbmres = unified_tbm_iterate(&scan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 23b21247dea..cd76d5e46ad 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,39 +96,28 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 * Serial bitmap table scan will simply build the bitmap.
+		 */
+		bool		init_shared_state = node->pstate ?
+			BitmapShouldInitializeSharedState(node->pstate) : false;
 
-		if (!pstate)
+		/*
+		 * Only serial bitmap table scans and the parallel leader in a
+		 * parallel bitmap table scan should build the bitmap.
+		 */
+		if (!pstate || init_shared_state)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
 			if (!tbm || !IsA(tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
 
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
-#endif							/* USE_PREFETCH */
-		}
-		else
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			if (BitmapShouldInitializeSharedState(pstate))
+			if (init_shared_state)
 			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
 				/*
 				 * Prepare to iterate over the TBM. This will return the
 				 * dsa_pointer of the iterator state which will be used by
@@ -142,21 +131,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 						tbm_prepare_shared_iterate(tbm);
 				}
 #endif
-
 				/* We have initialized the shared state so wake up others. */
 				BitmapDoneInitializingSharedState(pstate);
 			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
-			}
-#endif							/* USE_PREFETCH */
 		}
 
 		/*
@@ -187,8 +164,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		unified_tbm_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
+								  pstate ?
+								  pstate->tbmiterator :
+								  InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			unified_tbm_begin_iterate(&node->prefetch_iterator, tbm, dsa,
+									  pstate ?
+									  pstate->prefetch_iterator :
+									  InvalidDsaPointer);
+		}
+#endif							/* USE_PREFETCH */
+
 		node->initialized = true;
 
 		goto new_page;
@@ -268,7 +258,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!node->prefetch_iterator.exhausted &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -309,21 +299,20 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	UnifiedTBMIterator *prefetch_iterator = &node->prefetch_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = unified_tbm_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -340,8 +329,6 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
 		{
@@ -361,9 +348,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = unified_tbm_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -423,23 +410,21 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	UnifiedTBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
-
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = unified_tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					unified_tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -467,9 +452,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
-
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (1)
 			{
@@ -492,12 +475,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = unified_tbm_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					unified_tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -564,18 +546,14 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	if (node->prefetch_iterator.exhausted)
+		unified_tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -623,12 +601,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+	if (!node->prefetch_iterator.exhausted)
+		unified_tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -666,11 +642,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 92b829cebc7..7fec4ff8acb 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,13 +20,11 @@
 #include "storage/buf.h"
 #include "storage/spin.h"
 #include "utils/relcache.h"
+#include "nodes/tidbitmap.h"
 
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -44,8 +42,7 @@ typedef struct TableScanDescData
 	ItemPointerData rs_maxtid;
 
 	/* Only used for Bitmap table scans */
-	struct TBMIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	UnifiedTBMIterator rs_bhs_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 68a479496d7..b4b7fa13948 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -938,16 +938,12 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
 /*
@@ -994,20 +990,9 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
+		!scan->rs_bhs_iterator.exhausted)
+		unified_tbm_end_iterate(&scan->rs_bhs_iterator);
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
@@ -1019,20 +1004,9 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
+		!scan->rs_bhs_iterator.exhausted)
+		unified_tbm_end_iterate(&scan->rs_bhs_iterator);
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d96703b04d4..6693cf66c77 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1795,12 +1795,11 @@ typedef struct ParallelBitmapHeapState
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
+ *		prefetch_iterator  for prefetching ahead of current page
  *		prefetch_pages	   # pages prefetch iterator is ahead of current
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1815,12 +1814,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	UnifiedTBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
-- 
2.40.1

v19-0013-BitmapHeapScan-rescan-in-BitmapHeapNext.patchtext/x-diff; charset=us-asciiDownload
From 4ba6b8cda0bce3a68f68c39f45864a6fcb148b45 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 14:43:04 -0400
Subject: [PATCH v19 13/21] BitmapHeapScan: rescan in BitmapHeapNext

Instead of rescanning in ExecReScanBitmapHeapScan(), do so in
BitmapHeapNext(). This has no functional impact, but it is a step toward
creating the iterators in the table rescan function itself.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cd76d5e46ad..1fe50348c6f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -164,6 +164,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		/* rescan to release any page pin */
+		table_rescan(scan, NULL);
 		unified_tbm_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
 								  pstate ?
 								  pstate->tbmiterator :
@@ -541,10 +543,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* rescan to release any page pin */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
-
 	/* release bitmaps and buffers if any */
 	if (node->prefetch_iterator.exhausted)
 		unified_tbm_end_iterate(&node->prefetch_iterator);
-- 
2.40.1

v19-0014-Add-table-AM-callbacks-for-Bitmap-Table-Scans.patchtext/x-diff; charset=us-asciiDownload
From e4c54efb9aa77ada072c472de6bd5d0cdbf34b6c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 14:49:45 -0400
Subject: [PATCH v19 14/21] Add table AM callbacks for Bitmap Table Scans

Add specialized functions for starting, restarting, and ending a Bitmap
Table Scan.
---
 src/include/access/tableam.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b4b7fa13948..15f3db4113a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -355,6 +355,24 @@ typedef struct TableAmRoutine
 								bool set_params, bool allow_strat,
 								bool allow_sync, bool allow_pagemode);
 
+	/*
+	 * Functions to begin, restart, and end a scan of the underlying table of
+	 * a bitmap table scan.
+	 *
+	 * `rel`, `flags`, and `snapshot` serve the same purposes as in the
+	 * standard relation scan_[begin|rescan|end] functions documented above.
+	 */
+	TableScanDesc (*scan_begin_bm) (Relation rel,
+									Snapshot snapshot,
+									uint32 flags);
+
+	void		(*scan_rescan_bm) (TableScanDesc scan);
+
+	/*
+	 * Release resources and deallocate scan.
+	 */
+	void		(*scan_end_bm) (TableScanDesc scan);
+
 	/*
 	 * Return next tuple from `scan`, store in slot.
 	 */
-- 
2.40.1

v19-0015-Add-BitmapHeapScanDesc-and-scan-functions.patchtext/x-diff; charset=us-asciiDownload
From b568e7512e10d49742509315ea18dde4185445ad Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 14:51:35 -0400
Subject: [PATCH v19 15/21] Add BitmapHeapScanDesc and scan functions

Bitmap Heap Scans are specialized enough that it makes sense to create a
separate "sub-class" of the HeapScanDescData with Bitmap Heap
Scan-specific members.

This creates a convenient location for other Bitmap Heap Scan-specific
members to be added in the future. For example, the VM buffer used for
avoiding prefetching heap table blocks when no data is needed for
the query (the skip fetch optimization). This is a table AM layering
violation and should be moved out of the BitmapHeapScanState.

Along with the BitmapHeapScanDesc structure, add heap implementations of
the table AM functions for beginning, restarting, and ending a Bitmap
Table Scan.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          | 101 ++++++++++++++++++----
 src/backend/access/heap/heapam_handler.c  |  48 +++++-----
 src/backend/executor/nodeBitmapHeapscan.c |  46 +++++-----
 src/include/access/heapam.h               |  33 +++++--
 src/include/access/tableam.h              |  28 ++++--
 src/tools/pgindent/typedefs.list          |   1 +
 6 files changed, 180 insertions(+), 77 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 9be3a4b1afb..bcb9e4390d4 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -13,8 +13,11 @@
  *
  * INTERFACE ROUTINES
  *		heap_beginscan	- begin relation scan
+ *		heap_beginscan_bm - begin bitmap heap scan
  *		heap_rescan		- restart a relation scan
+ *		heap_rescan_bm  - restart a bitmap heap scan
  *		heap_endscan	- end relation scan
+ *		heap_endscan_bm - end a bitmap heap scan
  *		heap_getnext	- retrieve next tuple in scan
  *		heap_fetch		- retrieve tuple with given tid
  *		heap_insert		- insert tuple into a relation
@@ -967,8 +970,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1026,6 +1027,45 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	return (TableScanDesc) scan;
 }
 
+TableScanDesc
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+{
+	BitmapHeapScanDesc scan;
+
+	/*
+	 * increment relation ref count while scanning relation
+	 *
+	 * This is just to make really sure the relcache entry won't go away while
+	 * the scan has a pointer to it.  Caller should be holding the rel open
+	 * anyway, so this is redundant in all normal scenarios...
+	 */
+	RelationIncrementReferenceCount(relation);
+	scan = (BitmapHeapScanDesc) palloc(sizeof(BitmapHeapScanDescData));
+
+	scan->heap_common.rs_base.rs_rd = relation;
+	scan->heap_common.rs_base.rs_snapshot = snapshot;
+	scan->heap_common.rs_base.rs_nkeys = 0;
+	scan->heap_common.rs_base.rs_flags = flags;
+	scan->heap_common.rs_base.rs_parallel = NULL;
+	scan->heap_common.rs_strategy = NULL;
+
+	Assert(snapshot && IsMVCCSnapshot(snapshot));
+
+	/* we only need to set this up once */
+	scan->heap_common.rs_ctup.t_tableOid = RelationGetRelid(relation);
+
+	scan->heap_common.rs_parallelworkerdata = NULL;
+	scan->heap_common.rs_base.rs_key = NULL;
+
+	initscan(&scan->heap_common, NULL, false);
+
+	scan->vmbuffer = InvalidBuffer;
+	scan->empty_tuples_pending = 0;
+
+	return (TableScanDesc) scan;
+}
+
+
 void
 heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			bool allow_strat, bool allow_sync, bool allow_pagemode)
@@ -1057,20 +1097,33 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
-	scan->rs_empty_tuples_pending = 0;
-
 	/*
 	 * reinitialize scan descriptor
 	 */
 	initscan(scan, key, true);
 }
 
+void
+heap_rescan_bm(TableScanDesc sscan)
+{
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+
+	if (BufferIsValid(scan->heap_common.rs_cbuf))
+		ReleaseBuffer(scan->heap_common.rs_cbuf);
+
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+	scan->vmbuffer = InvalidBuffer;
+
+	scan->empty_tuples_pending = 0;
+
+	/*
+	 * reinitialize heap scan descriptor
+	 */
+	initscan(&scan->heap_common, NULL, true);
+}
+
+
 void
 heap_endscan(TableScanDesc sscan)
 {
@@ -1084,11 +1137,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
-
-	scan->rs_empty_tuples_pending = 0;
-
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
@@ -1109,6 +1157,29 @@ heap_endscan(TableScanDesc sscan)
 	pfree(scan);
 }
 
+/*
+ * Cleanup BitmapHeapScan table state
+ */
+void
+heap_endscan_bm(TableScanDesc sscan)
+{
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+
+	if (BufferIsValid(scan->heap_common.rs_cbuf))
+		ReleaseBuffer(scan->heap_common.rs_cbuf);
+
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
+
+	/*
+	 * decrement relation reference count and free scan descriptor storage
+	 */
+	RelationDecrementReferenceCount(scan->heap_common.rs_base.rs_rd);
+
+	pfree(scan);
+}
+
+
 HeapTuple
 heap_getnext(TableScanDesc sscan, ScanDirection direction)
 {
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ec6128e1d65..a2cbd7a24d6 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2187,11 +2187,12 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_block(TableScanDesc sscan,
 							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+	HeapScanDesc hscan = &scan->heap_common;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2208,12 +2209,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = unified_tbm_iterate(&scan->rs_bhs_iterator);
+		tbmres = unified_tbm_iterate(&sscan->rs_bhs_iterator);
 
 		if (tbmres == NULL)
 		{
 			/* no more entries in the bitmap */
-			Assert(hscan->rs_empty_tuples_pending == 0);
+			Assert(scan->empty_tuples_pending == 0);
 			return false;
 		}
 
@@ -2236,15 +2237,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+	if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(scan->empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2255,18 +2256,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
 	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
+										  sscan->rs_rd,
 										  block);
 	hscan->rs_cblock = block;
 	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
+	snapshot = sscan->rs_snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
+	heap_page_prune_opt(sscan->rs_rd, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2294,7 +2295,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, sscan->rs_rd, buffer, snapshot,
 									   &heapTuple, NULL, true))
 				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
@@ -2320,16 +2321,16 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
+			loctup.t_tableOid = sscan->rs_rd->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
 				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+				PredicateLockTID(sscan->rs_rd, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+			HeapCheckForSerializableConflictOut(valid, sscan->rs_rd, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2355,21 +2356,22 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc sscan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
+	HeapScanDesc hscan = &scan->heap_common;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (scan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		scan->empty_tuples_pending--;
 		return true;
 	}
 
@@ -2386,10 +2388,10 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 
 	hscan->rs_ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 	hscan->rs_ctup.t_len = ItemIdGetLength(lp);
-	hscan->rs_ctup.t_tableOid = scan->rs_rd->rd_id;
+	hscan->rs_ctup.t_tableOid = sscan->rs_rd->rd_id;
 	ItemPointerSet(&hscan->rs_ctup.t_self, hscan->rs_cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rs_rd);
+	pgstat_count_heap_fetch(sscan->rs_rd);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
@@ -2701,6 +2703,10 @@ static const TableAmRoutine heapam_methods = {
 	.scan_rescan = heap_rescan,
 	.scan_getnextslot = heap_getnextslot,
 
+	.scan_rescan_bm = heap_rescan_bm,
+	.scan_begin_bm = heap_beginscan_bm,
+	.scan_end_bm = heap_endscan_bm,
+
 	.scan_set_tidrange = heap_set_tidrange,
 	.scan_getnextslot_tidrange = heap_getnextslot_tidrange,
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 1fe50348c6f..bb9a11aa51d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,6 +96,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		bool		need_tuples = false;
+
 		/*
 		 * The leader will immediately come out of the function, but others
 		 * will be blocked until leader populates the TBM and wakes them up.
@@ -136,36 +138,28 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 		}
 
+
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
 		 */
-		if (!scan)
-		{
-			bool		need_tuples = false;
+		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
+								  node->ss.ss_currentRelation,
+								  node->ss.ps.state->es_snapshot,
+								  need_tuples);
 
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
-									  need_tuples);
-
-			node->ss.ss_currentScanDesc = scan;
-		}
+		node->ss.ss_currentScanDesc = scan;
 
-		/* rescan to release any page pin */
-		table_rescan(scan, NULL);
 		unified_tbm_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
 								  pstate ?
 								  pstate->tbmiterator :
@@ -591,10 +585,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 
 
 	/*
-	 * close heap scan
+	 * close bitmap heap scan
 	 */
 	if (scanDesc)
-		table_endscan(scanDesc);
+		table_endscan_bm(scanDesc);
 
 	/*
 	 * release bitmaps and buffers if any
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 750ea30852e..1ee5195a8d5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -76,22 +76,34 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDescData
+{
+	/* All the non-BitmapHeapScan specific members */
+	HeapScanDescData heap_common;
+
+	/*
+	 * Members common to Parallel and Serial BitmapHeapScan
+	 */
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
-	Buffer		rs_vmbuffer;
-	int			rs_empty_tuples_pending;
+	Buffer		vmbuffer;
+	int			empty_tuples_pending;
+}			BitmapHeapScanDescData;
+typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc;
 
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
@@ -289,6 +301,9 @@ extern void heap_set_tidrange(TableScanDesc sscan, ItemPointer mintid,
 extern bool heap_getnextslot_tidrange(TableScanDesc sscan,
 									  ScanDirection direction,
 									  TupleTableSlot *slot);
+extern TableScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags);
+extern void heap_endscan_bm(TableScanDesc scan);
+extern void heap_rescan_bm(TableScanDesc sscan);
 extern bool heap_fetch(Relation relation, Snapshot snapshot,
 					   HeapTuple tuple, Buffer *userbuf, bool keep_buf);
 extern bool heap_hot_search_buffer(ItemPointer tid, Relation relation,
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 15f3db4113a..0763ab9847c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -948,20 +948,27 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 
 /*
  * table_beginscan_bm is an alternative entry point for setting up a
- * TableScanDesc for a bitmap heap scan.  Although that scan technology is
- * really quite unlike a standard seqscan, there is just enough commonality to
- * make it worth using the same data structure.
+ * TableScanDesc for a bitmap table scan.
  */
 static inline TableScanDesc
-table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, bool need_tuple)
+table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
+				   bool need_tuple)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!scan)
+		scan = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
+
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+
+	return scan;
 }
 
 /*
@@ -1015,6 +1022,15 @@ table_endscan(TableScanDesc scan)
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
+/*
+* End Bitmap Table Scan
+ */
+static inline void
+table_endscan_bm(TableScanDesc scan)
+{
+	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+}
+
 /*
  * Restart a relation scan.
  */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 71686e79abb..b74338fea83 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -263,6 +263,7 @@ BitmapAndPath
 BitmapAndState
 BitmapHeapPath
 BitmapHeapScan
+BitmapHeapScanDesc
 BitmapHeapScanState
 BitmapIndexScan
 BitmapIndexScanState
-- 
2.40.1

v19-0016-BitmapHeapScan-manage-iteration-in-heap-BM-funct.patchtext/x-diff; charset=us-asciiDownload
From 2252c038424ec683311d08a0a868d83ffc10d616 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 15:08:11 -0400
Subject: [PATCH v19 16/21] BitmapHeapScan manage iteration in heap BM
 functions

Now that therea are dedicated heap AM BitmapHeapScan functions to begin,
restart, and end Bitmap Heap Scans, it is easy to initialize and cleanup
the UnifiedTBMIterator there instead. Doing this in heap AM code will
allow us to move the current block iterator from the TableScanDesc to
the BitmapHeapScanDesc.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          | 15 ++++++++++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 10 ++++------
 src/include/access/heapam.h               |  3 ++-
 src/include/access/tableam.h              | 21 ++++++++++-----------
 4 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index bcb9e4390d4..4fa4c29f90f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1049,6 +1049,9 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	scan->heap_common.rs_base.rs_parallel = NULL;
 	scan->heap_common.rs_strategy = NULL;
 
+	scan->heap_common.rs_base.rs_bhs_iterator.serial = NULL;
+	scan->heap_common.rs_base.rs_bhs_iterator.parallel = NULL;
+
 	Assert(snapshot && IsMVCCSnapshot(snapshot));
 
 	/* we only need to set this up once */
@@ -1104,7 +1107,8 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 }
 
 void
-heap_rescan_bm(TableScanDesc sscan)
+heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
+			   ParallelBitmapHeapState *pstate, dsa_area *dsa)
 {
 	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
 
@@ -1117,10 +1121,17 @@ heap_rescan_bm(TableScanDesc sscan)
 
 	scan->empty_tuples_pending = 0;
 
+	unified_tbm_end_iterate(&scan->heap_common.rs_base.rs_bhs_iterator);
+
 	/*
 	 * reinitialize heap scan descriptor
 	 */
 	initscan(&scan->heap_common, NULL, true);
+
+	unified_tbm_begin_iterate(&scan->heap_common.rs_base.rs_bhs_iterator, tbm, dsa,
+							  pstate ?
+							  pstate->tbmiterator :
+							  InvalidDsaPointer);
 }
 
 
@@ -1171,6 +1182,8 @@ heap_endscan_bm(TableScanDesc sscan)
 	if (BufferIsValid(scan->vmbuffer))
 		ReleaseBuffer(scan->vmbuffer);
 
+	unified_tbm_end_iterate(&scan->heap_common.rs_base.rs_bhs_iterator);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index bb9a11aa51d..012cba2c125 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -156,15 +156,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
 								  node->ss.ss_currentRelation,
 								  node->ss.ps.state->es_snapshot,
-								  need_tuples);
+								  need_tuples,
+								  node->tbm,
+								  node->pstate,
+								  node->ss.ps.state->es_query_dsa);
 
 		node->ss.ss_currentScanDesc = scan;
 
-		unified_tbm_begin_iterate(&scan->rs_bhs_iterator, tbm, dsa,
-								  pstate ?
-								  pstate->tbmiterator :
-								  InvalidDsaPointer);
-
 #ifdef USE_PREFETCH
 		if (node->prefetch_maximum > 0)
 		{
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 1ee5195a8d5..700205b9149 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -303,7 +303,8 @@ extern bool heap_getnextslot_tidrange(TableScanDesc sscan,
 									  TupleTableSlot *slot);
 extern TableScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags);
 extern void heap_endscan_bm(TableScanDesc scan);
-extern void heap_rescan_bm(TableScanDesc sscan);
+extern void heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
+						   ParallelBitmapHeapState *pstate, dsa_area *dsa);
 extern bool heap_fetch(Relation relation, Snapshot snapshot,
 					   HeapTuple tuple, Buffer *userbuf, bool keep_buf);
 extern bool heap_hot_search_buffer(ItemPointer tid, Relation relation,
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 0763ab9847c..e1df701c9a1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/execnodes.h"
 #include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
@@ -366,7 +367,8 @@ typedef struct TableAmRoutine
 									Snapshot snapshot,
 									uint32 flags);
 
-	void		(*scan_rescan_bm) (TableScanDesc scan);
+	void		(*scan_rescan_bm) (TableScanDesc scan, TIDBitmap *tbm,
+								   ParallelBitmapHeapState *pstate, dsa_area *dsa);
 
 	/*
 	 * Release resources and deallocate scan.
@@ -952,7 +954,8 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
-				   bool need_tuple)
+				   bool need_tuple, TIDBitmap *tbm,
+				   ParallelBitmapHeapState *pstate, dsa_area *dsa)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
@@ -964,9 +967,13 @@ table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
 	 * scan descriptor and begin the scan.
 	 */
 	if (!scan)
+	{
 		scan = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
+		scan->rs_bhs_iterator.serial = NULL;
+		scan->rs_bhs_iterator.parallel = NULL;
+	}
 
-	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa);
 
 	return scan;
 }
@@ -1015,10 +1022,6 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
-		!scan->rs_bhs_iterator.exhausted)
-		unified_tbm_end_iterate(&scan->rs_bhs_iterator);
-
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1038,10 +1041,6 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN &&
-		!scan->rs_bhs_iterator.exhausted)
-		unified_tbm_end_iterate(&scan->rs_bhs_iterator);
-
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
-- 
2.40.1

v19-0017-Move-BitmapHeapScan-current-block-iterator-to-Bi.patchtext/x-diff; charset=us-asciiDownload
From bf4777672024963eaf7582d23a7274f2261cd76b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 15:18:57 -0400
Subject: [PATCH v19 17/21] Move BitmapHeapScan current block iterator to
 BitmapHeapScanDesc

After beginning iteration in heap AM code, we can move the current block
iterator into the BitmapHeapScanDesc and take it out of the generic
TableScanDesc.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c         | 13 ++++++-------
 src/backend/access/heap/heapam_handler.c |  2 +-
 src/include/access/heapam.h              |  1 +
 src/include/access/relscan.h             |  3 ---
 src/include/access/tableam.h             |  4 ----
 5 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4fa4c29f90f..a45fdb50285 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1049,9 +1049,6 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	scan->heap_common.rs_base.rs_parallel = NULL;
 	scan->heap_common.rs_strategy = NULL;
 
-	scan->heap_common.rs_base.rs_bhs_iterator.serial = NULL;
-	scan->heap_common.rs_base.rs_bhs_iterator.parallel = NULL;
-
 	Assert(snapshot && IsMVCCSnapshot(snapshot));
 
 	/* we only need to set this up once */
@@ -1062,6 +1059,9 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 
 	initscan(&scan->heap_common, NULL, false);
 
+	scan->iterator.serial = NULL;
+	scan->iterator.parallel = NULL;
+
 	scan->vmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
@@ -1120,15 +1120,14 @@ heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
 	scan->vmbuffer = InvalidBuffer;
 
 	scan->empty_tuples_pending = 0;
-
-	unified_tbm_end_iterate(&scan->heap_common.rs_base.rs_bhs_iterator);
+	unified_tbm_end_iterate(&scan->iterator);
 
 	/*
 	 * reinitialize heap scan descriptor
 	 */
 	initscan(&scan->heap_common, NULL, true);
 
-	unified_tbm_begin_iterate(&scan->heap_common.rs_base.rs_bhs_iterator, tbm, dsa,
+	unified_tbm_begin_iterate(&scan->iterator, tbm, dsa,
 							  pstate ?
 							  pstate->tbmiterator :
 							  InvalidDsaPointer);
@@ -1182,7 +1181,7 @@ heap_endscan_bm(TableScanDesc sscan)
 	if (BufferIsValid(scan->vmbuffer))
 		ReleaseBuffer(scan->vmbuffer);
 
-	unified_tbm_end_iterate(&scan->heap_common.rs_base.rs_bhs_iterator);
+	unified_tbm_end_iterate(&scan->iterator);
 
 	/*
 	 * decrement relation reference count and free scan descriptor storage
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a2cbd7a24d6..15fc58f4fb7 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2209,7 +2209,7 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = unified_tbm_iterate(&sscan->rs_bhs_iterator);
+		tbmres = unified_tbm_iterate(&scan->iterator);
 
 		if (tbmres == NULL)
 		{
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 700205b9149..853a042c418 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -91,6 +91,7 @@ typedef struct BitmapHeapScanDescData
 	/*
 	 * Members common to Parallel and Serial BitmapHeapScan
 	 */
+	UnifiedTBMIterator iterator;
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 7fec4ff8acb..149b0c1cdda 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -41,9 +41,6 @@ typedef struct TableScanDescData
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
 
-	/* Only used for Bitmap table scans */
-	UnifiedTBMIterator rs_bhs_iterator;
-
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index e1df701c9a1..aebcecad30d 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -967,11 +967,7 @@ table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
 	 * scan descriptor and begin the scan.
 	 */
 	if (!scan)
-	{
 		scan = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
-		scan->rs_bhs_iterator.serial = NULL;
-		scan->rs_bhs_iterator.parallel = NULL;
-	}
 
 	scan->rs_rd->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa);
 
-- 
2.40.1

v19-0018-Lift-and-shift-BitmapHeapScan-prefetch-funcs-to-.patchtext/x-diff; charset=us-asciiDownload
From f1540b476ba02ae962f8d44fce53317219543697 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 15:46:05 -0400
Subject: [PATCH v19 18/21] Lift and shift BitmapHeapScan prefetch funcs to
 heap AM

We will soon move all the members for managing prefetching from the
BitmapHeapScanState to the BitmapHeapScanDesc. First move the prefetch
functions as-is to heapam_handler.c

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  | 214 +++++++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 218 +---------------------
 src/include/access/heapam.h               |   3 +
 3 files changed, 218 insertions(+), 217 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 15fc58f4fb7..85564fef2e0 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2180,6 +2180,220 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	UnifiedTBMIterator *prefetch_iterator = &node->prefetch_iterator;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			node->prefetch_pages--;
+		}
+		else if (!prefetch_iterator->exhausted)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbmpre = unified_tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmapheapscans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
+	if (node->prefetch_maximum > 0)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!prefetch_iterator->exhausted)
+			{
+				tbmpre = unified_tbm_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (node->prefetch_target >= node->prefetch_maximum / 2)
+			node->prefetch_target = node->prefetch_maximum;
+		else if (node->prefetch_target > 0)
+			node->prefetch_target *= 2;
+		else
+			node->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < node->prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+void
+BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	UnifiedTBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+	if (pstate == NULL)
+	{
+		if (!prefetch_iterator->exhausted)
+		{
+			while (node->prefetch_pages < node->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = unified_tbm_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					unified_tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		if (!prefetch_iterator->exhausted)
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = unified_tbm_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					unified_tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				node->pfblockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 012cba2c125..fda5645e4ae 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -40,6 +40,7 @@
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
+#include "access/heapam.h"
 #include "executor/executor.h"
 #include "executor/nodeBitmapHeapscan.h"
 #include "miscadmin.h"
@@ -51,10 +52,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -281,219 +278,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	UnifiedTBMIterator *prefetch_iterator = &node->prefetch_iterator;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = unified_tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmapheapscans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbmpre = unified_tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	UnifiedTBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-	if (pstate == NULL)
-	{
-		if (!prefetch_iterator->exhausted)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = unified_tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					unified_tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = unified_tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					unified_tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->pfblockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 853a042c418..f0cd0041460 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -422,6 +422,9 @@ extern bool heapam_scan_analyze_next_tuple(TableScanDesc scan,
 										   TransactionId OldestXmin,
 										   double *liverows, double *deadrows,
 										   TupleTableSlot *slot);
+extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
+extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+extern void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan);
 
 /*
  * To avoid leaking too much knowledge about reorderbuffer implementation
-- 
2.40.1

v19-0019-Push-BitmapHeapScan-prefetch-code-into-heap-AM.patchtext/x-diff; charset=us-asciiDownload
From 2148abc16c11a3c7eb23ee973d925455f22ba823 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 16:21:04 -0400
Subject: [PATCH v19 19/21] Push BitmapHeapScan prefetch code into heap AM

An earlier commit eliminated a table AM layering violation for the
current block in a BitmapHeapScan but left the violation in
BitmapHeapScan prefetching code.

To resolve this, move and manage all state used for prefetching entirely
into the heap AM.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |  38 ++++++-
 src/backend/access/heap/heapam_handler.c  | 125 +++++++++++++++-------
 src/backend/executor/nodeBitmapHeapscan.c |  97 +++--------------
 src/include/access/heapam.h               |  29 ++++-
 src/include/access/tableam.h              |  18 +---
 src/include/nodes/execnodes.h             |  12 ---
 6 files changed, 167 insertions(+), 152 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a45fdb50285..71f93bfbb1d 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1065,6 +1065,14 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	scan->vmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
+	/*
+	 * The rest of the BitmapHeapScanDesc members related to prefetching will
+	 * be initialized in heap_rescan_bm().
+	 */
+	scan->pvmbuffer = InvalidBuffer;
+	scan->prefetch_iterator.serial = NULL;
+	scan->prefetch_iterator.parallel = NULL;
+
 	return (TableScanDesc) scan;
 }
 
@@ -1108,7 +1116,8 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 
 void
 heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
-			   ParallelBitmapHeapState *pstate, dsa_area *dsa)
+			   ParallelBitmapHeapState *pstate, dsa_area *dsa,
+			   int prefetch_maximum)
 {
 	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
 
@@ -1122,6 +1131,17 @@ heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
 	scan->empty_tuples_pending = 0;
 	unified_tbm_end_iterate(&scan->iterator);
 
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+
+	unified_tbm_end_iterate(&scan->prefetch_iterator);
+
+	scan->prefetch_maximum = prefetch_maximum;
+	scan->pstate = pstate;
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+	scan->pfblockno = InvalidBlockNumber;
+
 	/*
 	 * reinitialize heap scan descriptor
 	 */
@@ -1131,6 +1151,17 @@ heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
 							  pstate ?
 							  pstate->tbmiterator :
 							  InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+	if (prefetch_maximum > 0)
+	{
+		unified_tbm_begin_iterate(&scan->prefetch_iterator, tbm, dsa,
+								  pstate ?
+								  pstate->prefetch_iterator :
+								  InvalidDsaPointer);
+	}
+#endif							/* USE_PREFETCH */
+
 }
 
 
@@ -1183,6 +1214,11 @@ heap_endscan_bm(TableScanDesc sscan)
 
 	unified_tbm_end_iterate(&scan->iterator);
 
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+
+	unified_tbm_end_iterate(&scan->prefetch_iterator);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 85564fef2e0..77888cdc90d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -60,6 +60,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   OffsetNumber tupoffset);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc scan);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc scan);
+static inline void BitmapPrefetch(BitmapHeapScanDesc scan);
 
 static const TableAmRoutine heapam_methods;
 
@@ -2187,26 +2190,26 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  *	iterator in prefetch_pages. For each block the main iterator returns, we
  *	decrement prefetch_pages.
  */
-void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	UnifiedTBMIterator *prefetch_iterator = &node->prefetch_iterator;
+	ParallelBitmapHeapState *pstate = scan->pstate;
+	UnifiedTBMIterator *prefetch_iterator = &scan->prefetch_iterator;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_pages > 0)
+		if (scan->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
+			scan->prefetch_pages--;
 		}
 		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
 			tbmpre = unified_tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			scan->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
@@ -2220,7 +2223,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
 	 * exacerbates the effects of this bug.
 	 */
-	if (node->prefetch_maximum > 0)
+	if (scan->prefetch_maximum > 0)
 	{
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -2244,7 +2247,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			if (!prefetch_iterator->exhausted)
 			{
 				tbmpre = unified_tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				scan->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
 	}
@@ -2259,33 +2262,33 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
  * page/tuple, then to one after the second tuple is fetched, then
  * it doubles as later pages are fetched.
  */
-void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->pstate;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_target >= node->prefetch_maximum)
+		if (scan->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
+		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
+			scan->prefetch_target = scan->prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
 		else
-			node->prefetch_target++;
+			scan->prefetch_target++;
 		return;
 	}
 
 	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
+	if (pstate->prefetch_target < scan->prefetch_maximum)
 	{
 		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
+		if (pstate->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
+			pstate->prefetch_target = scan->prefetch_maximum;
 		else if (pstate->prefetch_target > 0)
 			pstate->prefetch_target *= 2;
 		else
@@ -2298,18 +2301,19 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
 /*
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
-void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+static inline void
+BitmapPrefetch(BitmapHeapScanDesc scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	UnifiedTBMIterator *prefetch_iterator = &node->prefetch_iterator;
+	ParallelBitmapHeapState *pstate = scan->pstate;
+	Relation	rel = scan->heap_common.rs_base.rs_rd;
+	UnifiedTBMIterator *prefetch_iterator = &scan->prefetch_iterator;
 
 	if (pstate == NULL)
 	{
 		if (!prefetch_iterator->exhausted)
 		{
-			while (node->prefetch_pages < node->prefetch_target)
+			while (scan->prefetch_pages < scan->prefetch_target)
 			{
 				TBMIterateResult *tbmpre = unified_tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
@@ -2320,8 +2324,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					unified_tbm_end_iterate(prefetch_iterator);
 					break;
 				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				scan->prefetch_pages++;
+				scan->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2329,14 +2333,14 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->heap_common.rs_base.rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -2376,17 +2380,17 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				scan->pfblockno = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->heap_common.rs_base.rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -2419,6 +2423,8 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(scan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
@@ -2559,6 +2565,19 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	else
 		(*exact_pages)++;
 
+
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->pstate == NULL &&
+		!scan->prefetch_iterator.exhausted &&
+		scan->pfblockno < block)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(scan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2595,6 +2614,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc sscan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!scan->pstate)
+	{
+		if (scan->prefetch_target < scan->prefetch_maximum)
+			scan->prefetch_target++;
+	}
+	else if (scan->pstate->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&scan->pstate->mutex);
+		if (scan->pstate->prefetch_target < scan->prefetch_maximum)
+			scan->pstate->prefetch_target++;
+		SpinLockRelease(&scan->pstate->mutex);
+	}
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(scan);
+#endif							/* USE_PREFETCH */
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fda5645e4ae..11945ab9c42 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -69,7 +69,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
-	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
 	 * extract necessary information from index scan node
@@ -93,7 +92,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		Relation	rel = node->ss.ss_currentRelation;
 		bool		need_tuples = false;
+		int			prefetch_maximum = 0;
 
 		/*
 		 * The leader will immediately come out of the function, but others
@@ -103,6 +104,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		bool		init_shared_state = node->pstate ?
 			BitmapShouldInitializeSharedState(node->pstate) : false;
 
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+#ifdef USE_PREFETCH
+		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
 		/*
 		 * Only serial bitmap table scans and the parallel leader in a
 		 * parallel bitmap table scan should build the bitmap.
@@ -124,7 +133,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				 */
 				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 #ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
+				if (prefetch_maximum > 0)
 				{
 					pstate->prefetch_iterator =
 						tbm_prepare_shared_iterate(tbm);
@@ -154,22 +163,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 								  node->ss.ss_currentRelation,
 								  node->ss.ps.state->es_snapshot,
 								  need_tuples,
+								  prefetch_maximum,
 								  node->tbm,
 								  node->pstate,
 								  node->ss.ps.state->es_query_dsa);
 
 		node->ss.ss_currentScanDesc = scan;
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			unified_tbm_begin_iterate(&node->prefetch_iterator, tbm, dsa,
-									  pstate ?
-									  pstate->prefetch_iterator :
-									  InvalidDsaPointer);
-		}
-#endif							/* USE_PREFETCH */
-
 		node->initialized = true;
 
 		goto new_page;
@@ -185,37 +185,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -238,23 +207,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!node->prefetch_iterator.exhausted &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -319,22 +274,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator.exhausted)
-		unified_tbm_end_iterate(&node->prefetch_iterator);
+	/* release bitmaps if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
-	/* Only used for serial BHS */
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -373,14 +319,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan_bm(scanDesc);
 
 	/*
-	 * release bitmaps and buffers if any
+	 * release bitmaps if any
 	 */
-	if (!node->prefetch_iterator.exhausted)
-		unified_tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -413,16 +355,12 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -462,13 +400,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index f0cd0041460..b17f0e8b4e6 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -92,6 +92,10 @@ typedef struct BitmapHeapScanDescData
 	 * Members common to Parallel and Serial BitmapHeapScan
 	 */
 	UnifiedTBMIterator iterator;
+	UnifiedTBMIterator prefetch_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -101,7 +105,26 @@ typedef struct BitmapHeapScanDescData
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
 	Buffer		vmbuffer;
+	/* buffer for visibility-map lookups of prefetched pages */
+	Buffer		pvmbuffer;
 	int			empty_tuples_pending;
+
+	/*
+	 * Parallel-only members
+	 */
+
+	struct ParallelBitmapHeapState *pstate;
+
+	/*
+	 * Serial-only members
+	 */
+
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+	/* used to validate prefetch block stays ahead of current block  */
+	BlockNumber pfblockno;
 }			BitmapHeapScanDescData;
 typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc;
 
@@ -305,7 +328,8 @@ extern bool heap_getnextslot_tidrange(TableScanDesc sscan,
 extern TableScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags);
 extern void heap_endscan_bm(TableScanDesc scan);
 extern void heap_rescan_bm(TableScanDesc sscan, TIDBitmap *tbm,
-						   ParallelBitmapHeapState *pstate, dsa_area *dsa);
+						   ParallelBitmapHeapState *pstate, dsa_area *dsa,
+						   int prefetch_maximum);
 extern bool heap_fetch(Relation relation, Snapshot snapshot,
 					   HeapTuple tuple, Buffer *userbuf, bool keep_buf);
 extern bool heap_hot_search_buffer(ItemPointer tid, Relation relation,
@@ -422,9 +446,6 @@ extern bool heapam_scan_analyze_next_tuple(TableScanDesc scan,
 										   TransactionId OldestXmin,
 										   double *liverows, double *deadrows,
 										   TupleTableSlot *slot);
-extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-extern void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan);
 
 /*
  * To avoid leaking too much knowledge about reorderbuffer implementation
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index aebcecad30d..06530536897 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -368,7 +368,8 @@ typedef struct TableAmRoutine
 									uint32 flags);
 
 	void		(*scan_rescan_bm) (TableScanDesc scan, TIDBitmap *tbm,
-								   ParallelBitmapHeapState *pstate, dsa_area *dsa);
+								   ParallelBitmapHeapState *pstate, dsa_area *dsa,
+								   int prefetch_maximum);
 
 	/*
 	 * Release resources and deallocate scan.
@@ -805,17 +806,6 @@ typedef struct TableAmRoutine
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
@@ -954,7 +944,7 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
-				   bool need_tuple, TIDBitmap *tbm,
+				   bool need_tuple, int prefetch_maximum, TIDBitmap *tbm,
 				   ParallelBitmapHeapState *pstate, dsa_area *dsa)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
@@ -969,7 +959,7 @@ table_beginscan_bm(TableScanDesc scan, Relation rel, Snapshot snapshot,
 	if (!scan)
 		scan = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 
-	scan->rs_rd->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa);
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa, prefetch_maximum);
 
 	return scan;
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6693cf66c77..713de7d50f6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,18 +1792,12 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1811,18 +1805,12 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
-	UnifiedTBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

v19-0020-Move-BitmapHeapScan-initialization-to-helper.patchtext/x-diff; charset=us-asciiDownload
From ae6834ff0f5d929bbe49cad3d325639153b76e27 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 16:25:45 -0400
Subject: [PATCH v19 20/21] Move BitmapHeapScan initialization to helper

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 193 +++++++++++-----------
 1 file changed, 101 insertions(+), 92 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 11945ab9c42..46832535d20 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -55,6 +55,103 @@ static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *ps
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
+ /*
+  * If we haven't yet performed the underlying index scan, do it, and begin
+  * the iteration over the bitmap.
+  *
+  * For prefetching, we use *two* iterators, one for the pages we are actually
+  * scanning and another that runs ahead of the first for prefetching.
+  * node->prefetch_pages tracks exactly how many pages ahead the prefetch
+  * iterator is.  Also, node->prefetch_target tracks the desired prefetch
+  * distance, which starts small and increases up to the
+  * scan->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
+  * scan that stops after a few tuples because of a LIMIT.
+  */
+static void
+BitmapHeapInitialize(BitmapHeapScanState *node)
+{
+	TIDBitmap  *tbm;
+	ParallelBitmapHeapState *pstate = node->pstate;
+	Relation	rel = node->ss.ss_currentRelation;
+	bool		need_tuples = false;
+	int			prefetch_maximum = 0;
+
+	/*
+	 * The leader will immediately come out of the function, but others will
+	 * be blocked until leader populates the TBM and wakes them up. Serial
+	 * bitmap table scan will simply build the bitmap.
+	 */
+	bool		init_shared_state = node->pstate ?
+		BitmapShouldInitializeSharedState(node->pstate) : false;
+
+	/*
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
+	 */
+#ifdef USE_PREFETCH
+	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
+	/*
+	 * Only serial bitmap table scans and the parallel leader in a parallel
+	 * bitmap table scan should build the bitmap.
+	 */
+	if (!pstate || init_shared_state)
+	{
+		tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+
+		if (!tbm || !IsA(tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+		node->tbm = tbm;
+
+		if (init_shared_state)
+		{
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+#ifdef USE_PREFETCH
+			if (prefetch_maximum > 0)
+			{
+				pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(tbm);
+			}
+#endif
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(pstate);
+		}
+	}
+
+
+	/*
+	 * We can potentially skip fetching heap pages if we do not need any
+	 * columns of the table, either for checking non-indexable quals or for
+	 * returning data.  This test is a bit simplistic, as it checks the
+	 * stronger condition that there's no qual or return tlist at all. But in
+	 * most cases it's probably not worth working harder than that.
+	 */
+	need_tuples = (node->ss.ps.plan->qual != NIL ||
+				   node->ss.ps.plan->targetlist != NIL);
+
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	node->ss.ss_currentScanDesc = table_beginscan_bm(node->ss.ss_currentScanDesc,
+													 node->ss.ss_currentRelation,
+													 node->ss.ps.state->es_snapshot,
+													 need_tuples,
+													 prefetch_maximum,
+													 node->tbm,
+													 node->pstate,
+													 node->ss.ps.state->es_query_dsa);
+
+	node->initialized = true;
+}
+
+
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -66,9 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 
 	/*
 	 * extract necessary information from index scan node
@@ -76,102 +171,16 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
+	 * the iteration over the bitmap. This happens on rescan as well.
 	 */
 	if (!node->initialized)
 	{
-		Relation	rel = node->ss.ss_currentRelation;
-		bool		need_tuples = false;
-		int			prefetch_maximum = 0;
-
-		/*
-		 * The leader will immediately come out of the function, but others
-		 * will be blocked until leader populates the TBM and wakes them up.
-		 * Serial bitmap table scan will simply build the bitmap.
-		 */
-		bool		init_shared_state = node->pstate ?
-			BitmapShouldInitializeSharedState(node->pstate) : false;
-
-		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 */
-#ifdef USE_PREFETCH
-		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-#endif
-
-		/*
-		 * Only serial bitmap table scans and the parallel leader in a
-		 * parallel bitmap table scan should build the bitmap.
-		 */
-		if (!pstate || init_shared_state)
-		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-			node->tbm = tbm;
-
-			if (init_shared_state)
-			{
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-				}
-#endif
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
-		}
-
-
-		/*
-		 * We can potentially skip fetching heap pages if we do not need any
-		 * columns of the table, either for checking non-indexable quals or
-		 * for returning data.  This test is a bit simplistic, as it checks
-		 * the stronger condition that there's no qual or return tlist at all.
-		 * But in most cases it's probably not worth working harder than that.
-		 */
-		need_tuples = (node->ss.ps.plan->qual != NIL ||
-					   node->ss.ps.plan->targetlist != NIL);
-
-		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
-		 */
-		scan = table_beginscan_bm(node->ss.ss_currentScanDesc,
-								  node->ss.ss_currentRelation,
-								  node->ss.ps.state->es_snapshot,
-								  need_tuples,
-								  prefetch_maximum,
-								  node->tbm,
-								  node->pstate,
-								  node->ss.ps.state->es_query_dsa);
-
-		node->ss.ss_currentScanDesc = scan;
-
-		node->initialized = true;
-
+		BitmapHeapInitialize(node);
+		/* We may have a new scan descriptor */
+		scan = node->ss.ss_currentScanDesc;
 		goto new_page;
 	}
 
-- 
2.40.1

v19-0021-Remove-table_scan_bitmap_next_block.patchtext/x-diff; charset=us-asciiDownload
From fe9e990176d52d5b73fb65cc955c41689612c2b8 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 16:38:06 -0400
Subject: [PATCH v19 21/21] Remove table_scan_bitmap_next_block()

With several of the changes to the control flow of BitmapHeapNext() in
recent commits, table_scan_bitmap_next_tuple() can be responsible for
getting the next block. Do this and remove the table AM API function
table_scan_bitmap_next_block().

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  2 +
 src/backend/access/heap/heapam_handler.c  | 50 ++++++++-------
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 69 ++++++++-------------
 src/backend/optimizer/util/plancat.c      |  3 +-
 src/include/access/tableam.h              | 74 +++++------------------
 src/include/nodes/execnodes.h             |  2 -
 7 files changed, 72 insertions(+), 130 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 71f93bfbb1d..f0943802c7c 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -327,6 +327,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 77888cdc90d..818cea5aed0 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2397,16 +2397,12 @@ BitmapPrefetch(BitmapHeapScanDesc scan)
 #endif							/* USE_PREFETCH */
 }
 
-
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
+/*
+ * Helper for heapam_scan_bitmap_next_tuple()
  */
-
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc sscan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
@@ -2420,7 +2416,6 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
 	BitmapAdjustPrefetchIterator(scan);
@@ -2449,7 +2444,6 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2588,9 +2582,15 @@ heapam_scan_bitmap_next_block(TableScanDesc sscan,
 	return true;
 }
 
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc sscan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc scan = (BitmapHeapScanDesc) sscan;
 	HeapScanDesc hscan = &scan->heap_common;
@@ -2598,21 +2598,28 @@ heapam_scan_bitmap_next_tuple(TableScanDesc sscan,
 	Page		page;
 	ItemId		lp;
 
-	if (scan->empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		scan->empty_tuples_pending--;
-		return true;
-	}
+		if (scan->empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			scan->empty_tuples_pending--;
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(sscan, recheck,
+										   lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -3013,7 +3020,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 55b8caeadf2..0b87530a9c4 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -90,8 +90,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 46832535d20..798876ee954 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -162,63 +162,48 @@ static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
-	TableScanDesc scan;
 	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	TableScanDesc scan;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap. This happens on rescan as well.
 	 */
 	if (!node->initialized)
-	{
 		BitmapHeapInitialize(node);
-		/* We may have a new scan descriptor */
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	/*
+	 * BitmapHeapInitialize() may make the scan descriptor so don't get it
+	 * from the node until after calling it.
+	 */
+	econtext = node->ss.ps.ps_ExprContext;
+	slot = node->ss.ss_ScanTupleSlot;
+	scan = node->ss.ss_currentScanDesc;
+
+	while (table_scan_bitmap_next_tuple(scan, slot, &node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+		CHECK_FOR_INTERRUPTS();
 
-			CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
@@ -289,7 +274,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->tbm = NULL;
 	node->initialized = false;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -369,7 +353,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6bb53e4346f..a9d6c6a037d 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -312,8 +312,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amsearchnulls = amroutine->amsearchnulls;
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
-				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+				info->amhasgetbitmap = amroutine->amgetbitmap != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 06530536897..e8c28766e2f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -794,34 +794,20 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * lossy_pages is incremented if the bitmap is lossy for the selected
-	 * block; otherwise, exact_pages is incremented.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno, bool *recheck,
-										   long *lossy_pages, long *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * recheck is set if recheck is required.
+	 *
+	 * The table AM is responsible for reading in blocks and counting (for
+	 * EXPLAIN) which of those blocks were represented lossily in the bitmap
+	 * using the lossy_pages and exact_pages counters.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1990,45 +1976,13 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. lossy_pages is
- * incremented is the block's representation in the bitmap is lossy; otherwise,
- * exact_pages is incremented.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
- */
-static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno, bool *recheck,
-							 long *lossy_pages,
-							 long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
-														   lossy_pages, exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if a
+ * visible tuple was found, false otherwise.
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
+							 TupleTableSlot *slot, bool *recheck,
+							 long *lossy_pages, long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2039,7 +1993,9 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot, recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 713de7d50f6..49ce4ff9a71 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1797,7 +1797,6 @@ typedef struct ParallelBitmapHeapState
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1810,7 +1809,6 @@ typedef struct BitmapHeapScanState
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

#107Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#106)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/6/24 23:34, Melanie Plageman wrote:

...

I realized it makes more sense to add a FIXME (I used XXX. I'm not when
to use what) with a link to the message where Andres describes why he
thinks it is a bug. If we plan on fixing it, it is good to have a record
of that. And it makes it easier to put a clear and accurate comment.
Done in 0009.

OK, thanks. If think 0001-0008 are ready to go, with some minor tweaks
per above (tuple vs. tuples etc.), and the question about the recheck
flag. If you can do these tweaks, I'll get that committed today and we
can try to get a couple more patches in tomorrow.

Attached v19 rebases the rest of the commits from v17 over the first
nine patches from v18. All patches 0001-0009 are unchanged from v18. I
have made updates and done cleanup on 0010-0021.

I've pushed 0001-0005, I'll get back to this tomorrow and see how much
more we can get in for v17.

What bothers me on 0006-0008 is that the justification in the commit
messages is "future commit will do something". I think it's fine to have
a separate "prepareatory" patches (I really like how you structured the
patches this way), but it'd be good to have them right before that
"future" commit - I'd like not to have one in v17 and then the "future
commit" in v18, because that's annoying complication for backpatching,
(and probably also when implementing the AM?) etc.

AFAICS for v19, the "future commit" for all three patches (0006-0008) is
0012, which introduces the unified iterator. Is that correct?

Also, for 0008 I'm not sure we could even split it between v17 and v18,
because even if heapam did not use the iterator, what if some other AM
uses it? Without 0012 it'd be a problem for the AM, no?

Would it make sense to move 0009 before these three patches? That seems
like a meaningful change on it's own, right?

FWIW I don't think it's very likely I'll commit the UnifiedTBMIterator
stuff. I do agree with the idea in general, but I think I'd need more
time to think about the details. Sorry about that ...

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#108Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#107)
3 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Apr 07, 2024 at 02:27:43AM +0200, Tomas Vondra wrote:

On 4/6/24 23:34, Melanie Plageman wrote:

...

I realized it makes more sense to add a FIXME (I used XXX. I'm not when
to use what) with a link to the message where Andres describes why he
thinks it is a bug. If we plan on fixing it, it is good to have a record
of that. And it makes it easier to put a clear and accurate comment.
Done in 0009.

OK, thanks. If think 0001-0008 are ready to go, with some minor tweaks
per above (tuple vs. tuples etc.), and the question about the recheck
flag. If you can do these tweaks, I'll get that committed today and we
can try to get a couple more patches in tomorrow.

Attached v19 rebases the rest of the commits from v17 over the first
nine patches from v18. All patches 0001-0009 are unchanged from v18. I
have made updates and done cleanup on 0010-0021.

I've pushed 0001-0005, I'll get back to this tomorrow and see how much
more we can get in for v17.

Thanks! I thought about it a bit more, and I got worried about the

Assert(scan->rs_empty_tuples_pending == 0);

in heap_rescan() and heap_endscan().

I was worried if we don't complete the scan it could end up tripping
incorrectly.

I tried to come up with a query which didn't end up emitting all of the
tuples on the page (using a LIMIT clause), but I struggled to come up
with an example that qualified for the skip fetch optimization and also
returned before completing the scan.

I could work a bit harder tomorrow to try and come up with something.
However, I think it might be safer to just change these to:

scan->rs_empty_tuples_pending = 0

What bothers me on 0006-0008 is that the justification in the commit
messages is "future commit will do something". I think it's fine to have
a separate "prepareatory" patches (I really like how you structured the
patches this way), but it'd be good to have them right before that
"future" commit - I'd like not to have one in v17 and then the "future
commit" in v18, because that's annoying complication for backpatching,
(and probably also when implementing the AM?) etc.

Yes, I was thinking about this also.

AFAICS for v19, the "future commit" for all three patches (0006-0008) is
0012, which introduces the unified iterator. Is that correct?

Actually, those patches (v19 0006-0008) were required for v19 0009,
which is why I put them directly before it. 0009 eliminates use of the
TBMIterateResult for control flow in BitmapHeapNext().

I've rephrased the commit messages to not mention future commits and
instead focus on what the changes in the commit are enabling.

v19-0006 actually squashed very easily with v19-0009 and is actually
probably better that way. It is still easy to understand IMO.

In v20, I've attached just the functionality from v19 0006-0009 but in
three patches instead of four.

Also, for 0008 I'm not sure we could even split it between v17 and v18,
because even if heapam did not use the iterator, what if some other AM
uses it? Without 0012 it'd be a problem for the AM, no?

The iterators in the TableScanDescData were introduced in v19-0009. It
is okay for other AMs to use it. In fact, they will want to use it. It
is still initialized and set up in BitmapHeapNext(). They would just
need to call tbm_iterate()/tbm_shared_iterate() on it.

As for how table AMs will cope without the TBMIterateResult passed to
table_scan_bitmap_next_tuple() (which is what v19 0008 did): they can
save the location of the tuples to be scanned somewhere in their scan
descriptor. Heap AM already did this and actually didn't use the
TBMIterateResult at all.

Would it make sense to move 0009 before these three patches? That seems
like a meaningful change on it's own, right?

Since v19 0009 requires these patches, I don't think we could do that.
I think up to and including 0009 would be an improvement in clarity and
function.

As for all the patches after 0009, I've dropped them from this version.
We are out of time, and they need more thought.

After we decided not to pursue streaming bitmapheapscan for 17, I wanted
to make sure we removed the prefetch code table AM violation -- since we
weren't deleting that code. So what started out as me looking for a way
to clean up one commit ended up becoming a much larger project. Sorry
about that last minute code explosion! I do think there is a way to do
it right and make it nice. Also that violation would be gone if we
figure out how to get streaming bitmapheapscan behaving correctly.

So, there's just more motivation to make streaming bitmapheapscan
awesome for 18!

Given all that, I've only included the three patches I think we are
considering (former v19 0006-0008). They are largely the same as you saw
them last except for squashing the two commits I mentioned above and
updating all of the commit messages.

FWIW I don't think it's very likely I'll commit the UnifiedTBMIterator
stuff. I do agree with the idea in general, but I think I'd need more
time to think about the details. Sorry about that ...

Yes, that makes total sense. I 100% agree.

I do think the UnifiedTBMIterator (maybe the name is not good, though)
is a good way to simplify the BitmapHeapScan code and is applicable to
any future TIDBitmap user with both a parallel and serial
implementation. So, there's a nice, small patch I can register for July.

Thanks again for taking time to work on this!

- Melanie

Attachments:

v20-0001-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-diff; charset=us-asciiDownload
From 3ca97f7a8ef11876b1ed0c089bed19d057314067 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v20 1/3] table_scan_bitmap_next_block counts lossy and exact
 pages

Keep track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap in table AM-specific code. These
counters are used for EXPLAIN.

This is a step toward removing TBMIterateResults as a flow control
mechanism in BitmapHeapNext(), which is required for a more asynchronous
design. It also is more table AM agnostic.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 58de2c82a70..eb56dfe4e93 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,7 +2188,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2316,6 +2317,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6b48a6d8350..de7a293de8e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,8 +212,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -233,14 +231,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index be198fa3158..8c75a4c038c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -789,6 +789,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * lossy_pages is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, exact_pages is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -804,7 +807,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1971,17 +1975,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. lossy_pages is incremented is the block's
+ * representation in the bitmap is lossy; otherwise, exact_pages is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1992,7 +2000,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.40.1

v20-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-diff; charset=us-asciiDownload
From 37086ebd78348b359c84cfff7b3ca40712bc8f25 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v20 2/3] Remove table_scan_bitmap_next_tuple parameter tbmres

In order to remove TBMIterateResults as a flow control mechanism in
BitmapHeapNext(), they can no longer be used as a means of communication
between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Remove the TBMIterateResult parameter from
table_scan_bitmap_next_tuple().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index eb56dfe4e93..f99e6efd757 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2327,7 +2327,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index de7a293de8e..e63f6f0429a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -281,7 +281,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8c75a4c038c..697b5488b10 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,10 +780,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -814,15 +811,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2015,7 +2007,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2027,7 +2018,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.40.1

v20-0003-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-diff; charset=us-asciiDownload
From 5ccc64748fc60e10fdceebf4430b826bac81731a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v20 3/3] Make table_scan_bitmap_next_block() async-friendly

table_scan_bitmap_next_block() previously returned false when
table_scan_bitmap_next_tuple() should not be called for the tuples on
the page. This could happen when there were no visible tuples on the
page or when, due to concurrent activity on the table, the block
returned by the iterator is past the end of the table (as recorded when
the scan started).

That forced the caller to be responsible for determining if additional
blocks should be fetched and for invoking table_scan_bitmap_next_block()
for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
beginning of the scan) and for table_scan_bitmap_next_tuple() to return
false if there are no visible tuples on the page.

This also allows us to move responsibility for the iterator to table AM
specific code. This means handling invalid blocks is entirely up to the
table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  58 +++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  68 +++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 199 insertions(+), 144 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f99e6efd757..903cb80157e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2188,18 +2188,52 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+		{
+			/* no more entries in the bitmap */
+			Assert(hscan->rs_empty_tuples_pending == 0);
+			return false;
+		}
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2218,16 +2252,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2322,7 +2347,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e63f6f0429a..01703bd4865 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,9 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -85,11 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -105,6 +96,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,8 +107,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
+			tbmiterator = tbm_begin_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -166,9 +159,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -207,46 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -267,45 +235,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -331,13 +310,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -351,14 +334,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmapheapscans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -383,7 +373,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -461,6 +454,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -518,6 +512,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -579,12 +575,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -592,13 +584,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -629,28 +621,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -683,8 +671,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -692,9 +678,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..024dc08c420 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -36,6 +39,10 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
+	/* Iterators for Bitmap Table Scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 697b5488b10..68a479496d7 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
 
@@ -773,19 +774,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * lossy_pages is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, exact_pages is incremented.
 	 *
@@ -804,7 +800,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -942,12 +938,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -994,6 +994,21 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1004,6 +1019,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1967,19 +1997,18 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. lossy_pages is incremented is the block's
- * representation in the bitmap is lossy; otherwise, exact_pages is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. lossy_pages is
+ * incremented is the block's representation in the bitmap is lossy; otherwise,
+ * exact_pages is incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1992,9 +2021,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fa2f70b7a48..d96703b04d4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1792,8 +1792,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1802,9 +1800,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1812,8 +1812,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1822,9 +1820,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.40.1

#109Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#108)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/7/24 06:17, Melanie Plageman wrote:

On Sun, Apr 07, 2024 at 02:27:43AM +0200, Tomas Vondra wrote:

On 4/6/24 23:34, Melanie Plageman wrote:

...

I realized it makes more sense to add a FIXME (I used XXX. I'm not when
to use what) with a link to the message where Andres describes why he
thinks it is a bug. If we plan on fixing it, it is good to have a record
of that. And it makes it easier to put a clear and accurate comment.
Done in 0009.

OK, thanks. If think 0001-0008 are ready to go, with some minor tweaks
per above (tuple vs. tuples etc.), and the question about the recheck
flag. If you can do these tweaks, I'll get that committed today and we
can try to get a couple more patches in tomorrow.

Attached v19 rebases the rest of the commits from v17 over the first
nine patches from v18. All patches 0001-0009 are unchanged from v18. I
have made updates and done cleanup on 0010-0021.

I've pushed 0001-0005, I'll get back to this tomorrow and see how much
more we can get in for v17.

Thanks! I thought about it a bit more, and I got worried about the

Assert(scan->rs_empty_tuples_pending == 0);

in heap_rescan() and heap_endscan().

I was worried if we don't complete the scan it could end up tripping
incorrectly.

I tried to come up with a query which didn't end up emitting all of the
tuples on the page (using a LIMIT clause), but I struggled to come up
with an example that qualified for the skip fetch optimization and also
returned before completing the scan.

I could work a bit harder tomorrow to try and come up with something.
However, I think it might be safer to just change these to:

scan->rs_empty_tuples_pending = 0

Hmmm, good point. I haven't tried, but wouldn't something like "SELECT 1
FROM t WHERE column = X LIMIT 1" do the trick? Probably in a join, as a
correlated subquery?

It seemed OK to me and the buildfarm did not turn red, so I'd leave this
until after the code freeze.

What bothers me on 0006-0008 is that the justification in the commit
messages is "future commit will do something". I think it's fine to have
a separate "prepareatory" patches (I really like how you structured the
patches this way), but it'd be good to have them right before that
"future" commit - I'd like not to have one in v17 and then the "future
commit" in v18, because that's annoying complication for backpatching,
(and probably also when implementing the AM?) etc.

Yes, I was thinking about this also.

Good we're on the same page.

AFAICS for v19, the "future commit" for all three patches (0006-0008) is
0012, which introduces the unified iterator. Is that correct?

Actually, those patches (v19 0006-0008) were required for v19 0009,
which is why I put them directly before it. 0009 eliminates use of the
TBMIterateResult for control flow in BitmapHeapNext().

Ah, OK. Thanks for the clarification.

I've rephrased the commit messages to not mention future commits and
instead focus on what the changes in the commit are enabling.

v19-0006 actually squashed very easily with v19-0009 and is actually
probably better that way. It is still easy to understand IMO.

In v20, I've attached just the functionality from v19 0006-0009 but in
three patches instead of four.

Good. I'll take a look today.

Also, for 0008 I'm not sure we could even split it between v17 and v18,
because even if heapam did not use the iterator, what if some other AM
uses it? Without 0012 it'd be a problem for the AM, no?

The iterators in the TableScanDescData were introduced in v19-0009. It
is okay for other AMs to use it. In fact, they will want to use it. It
is still initialized and set up in BitmapHeapNext(). They would just
need to call tbm_iterate()/tbm_shared_iterate() on it.

As for how table AMs will cope without the TBMIterateResult passed to
table_scan_bitmap_next_tuple() (which is what v19 0008 did): they can
save the location of the tuples to be scanned somewhere in their scan
descriptor. Heap AM already did this and actually didn't use the
TBMIterateResult at all.

The reason I feel a bit uneasy about putting this in TableScanDescData
is I see that struct as a "description of the scan" (~input parameters
defining what the scan should do), while for runtime state we have
ScanState in execnodes.h. But maybe I'm wrong - I see we have similar
runtime state in the other scan descriptors (like xs_itup/xs_hitup, kill
prior tuple in index scans etc.).

Would it make sense to move 0009 before these three patches? That seems
like a meaningful change on it's own, right?

Since v19 0009 requires these patches, I don't think we could do that.
I think up to and including 0009 would be an improvement in clarity and
function.

Right, thanks for the correction.

As for all the patches after 0009, I've dropped them from this version.
We are out of time, and they need more thought.

+1

After we decided not to pursue streaming bitmapheapscan for 17, I wanted
to make sure we removed the prefetch code table AM violation -- since we
weren't deleting that code. So what started out as me looking for a way
to clean up one commit ended up becoming a much larger project. Sorry
about that last minute code explosion! I do think there is a way to do
it right and make it nice. Also that violation would be gone if we
figure out how to get streaming bitmapheapscan behaving correctly.

So, there's just more motivation to make streaming bitmapheapscan
awesome for 18!

Given all that, I've only included the three patches I think we are
considering (former v19 0006-0008). They are largely the same as you saw
them last except for squashing the two commits I mentioned above and
updating all of the commit messages.

Right. I do think the patches make sensible changes in principle, but
the later parts need more refinement so let's not rush it.

FWIW I don't think it's very likely I'll commit the UnifiedTBMIterator
stuff. I do agree with the idea in general, but I think I'd need more
time to think about the details. Sorry about that ...

Yes, that makes total sense. I 100% agree.

I do think the UnifiedTBMIterator (maybe the name is not good, though)
is a good way to simplify the BitmapHeapScan code and is applicable to
any future TIDBitmap user with both a parallel and serial
implementation. So, there's a nice, small patch I can register for July.

Thanks again for taking time to work on this!

Yeah, The name seems a bit awkward ... but I don't have a better idea. I
like how it "isolates" the complexity and makes the BHS code simpler and
easier to understand.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#110Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#109)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Apr 7, 2024 at 7:38 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/7/24 06:17, Melanie Plageman wrote:

What bothers me on 0006-0008 is that the justification in the commit
messages is "future commit will do something". I think it's fine to have
a separate "prepareatory" patches (I really like how you structured the
patches this way), but it'd be good to have them right before that
"future" commit - I'd like not to have one in v17 and then the "future
commit" in v18, because that's annoying complication for backpatching,
(and probably also when implementing the AM?) etc.

Yes, I was thinking about this also.

Good we're on the same page.

Having thought about this some more I think we need to stop here for
17. v20-0001 and v20-0002 both make changes to the table AM API that
seem bizarre and unjustifiable without the other changes. Like, here
we changed all your parameters because someday we are going to do
something! You're welcome!

Also, the iterators in the TableScanDescData might be something I
could live with in the source code for a couple months before we make
the rest of the changes in July+. But, adding them does push the
TableScanDescData->rs_parallel member into the second cacheline, which
will be true in versions of Postgres people are using for years. I
didn't perf test, but seems bad.

So, yes, unfortunately, I think we should pick up on the BHS saga in a
few months. Or, actually, we should start focusing on that parallel
BHS + 0 readahead bug and whether or not we are going to fix it.

Sorry for the about-face.

- Melanie

#111Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#110)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/7/24 15:11, Melanie Plageman wrote:

On Sun, Apr 7, 2024 at 7:38 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/7/24 06:17, Melanie Plageman wrote:

What bothers me on 0006-0008 is that the justification in the commit
messages is "future commit will do something". I think it's fine to have
a separate "prepareatory" patches (I really like how you structured the
patches this way), but it'd be good to have them right before that
"future" commit - I'd like not to have one in v17 and then the "future
commit" in v18, because that's annoying complication for backpatching,
(and probably also when implementing the AM?) etc.

Yes, I was thinking about this also.

Good we're on the same page.

Having thought about this some more I think we need to stop here for
17. v20-0001 and v20-0002 both make changes to the table AM API that
seem bizarre and unjustifiable without the other changes. Like, here
we changed all your parameters because someday we are going to do
something! You're welcome!

OK, I think that's essentially the "temporary breakage" that should not
span multiple releases, I mentioned ~yesterday. I appreciate you're
careful about this.

Also, the iterators in the TableScanDescData might be something I
could live with in the source code for a couple months before we make
the rest of the changes in July+. But, adding them does push the
TableScanDescData->rs_parallel member into the second cacheline, which
will be true in versions of Postgres people are using for years. I
didn't perf test, but seems bad.

I haven't though about how it affects cachelines, TBH. I'd expect it to
have minimal impact, because while it makes this struct larger it should
make some other struct (used in essentially the same places) smaller. So
I'd guess this to be a zero sum game, but perhaps I'm wrong.

For me the main question was "Is this the right place for this, even if
it's only temporary?"

So, yes, unfortunately, I think we should pick up on the BHS saga in a
few months. Or, actually, we should start focusing on that parallel
BHS + 0 readahead bug and whether or not we are going to fix it.

Yes, the July CF is a good time to focus on this, early in the cycle.

Sorry for the about-face.

No problem. I very much prefer this over something that may not be quite
ready yet.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#112Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#109)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Apr 7, 2024 at 7:38 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/7/24 06:17, Melanie Plageman wrote:

On Sun, Apr 07, 2024 at 02:27:43AM +0200, Tomas Vondra wrote:

On 4/6/24 23:34, Melanie Plageman wrote:

...

I realized it makes more sense to add a FIXME (I used XXX. I'm not when
to use what) with a link to the message where Andres describes why he
thinks it is a bug. If we plan on fixing it, it is good to have a record
of that. And it makes it easier to put a clear and accurate comment.
Done in 0009.

OK, thanks. If think 0001-0008 are ready to go, with some minor tweaks
per above (tuple vs. tuples etc.), and the question about the recheck
flag. If you can do these tweaks, I'll get that committed today and we
can try to get a couple more patches in tomorrow.

Attached v19 rebases the rest of the commits from v17 over the first
nine patches from v18. All patches 0001-0009 are unchanged from v18. I
have made updates and done cleanup on 0010-0021.

I've pushed 0001-0005, I'll get back to this tomorrow and see how much
more we can get in for v17.

Thanks! I thought about it a bit more, and I got worried about the

Assert(scan->rs_empty_tuples_pending == 0);

in heap_rescan() and heap_endscan().

I was worried if we don't complete the scan it could end up tripping
incorrectly.

I tried to come up with a query which didn't end up emitting all of the
tuples on the page (using a LIMIT clause), but I struggled to come up
with an example that qualified for the skip fetch optimization and also
returned before completing the scan.

I could work a bit harder tomorrow to try and come up with something.
However, I think it might be safer to just change these to:

scan->rs_empty_tuples_pending = 0

Hmmm, good point. I haven't tried, but wouldn't something like "SELECT 1
FROM t WHERE column = X LIMIT 1" do the trick? Probably in a join, as a
correlated subquery?

Unfortunately (or fortunately, I guess) that exact thing won't work
because even constant values in the target list disqualify it for the
skip fetch optimization.

Being a bit too lazy to look at planner code this morning, I removed
the target list requirement like this:

-           need_tuples = (node->ss.ps.plan->qual != NIL ||
-                          node->ss.ps.plan->targetlist != NIL);
+           need_tuples = (node->ss.ps.plan->qual != NIL);

And can easily trip the assert with this:

create table foo (a int);
insert into foo select i from generate_series(1,10)i;
create index on foo(a);
vacuum foo;
select 1 from (select 2 from foo limit 3);

Anyway, I don't know if we could find a query that does actually hit
this. The only bitmap heap scan queries in the regress suite that meet
the
BitmapHeapScanState->ss.ps.plan->targetlist == NIL
condition are aggregates (all are count(*)).

I'll dig a bit more later, but do you think this is worth adding an
open item for? Even though I don't have a repro yet?

- Melanie

#113Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#111)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Apr 7, 2024 at 10:10 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/7/24 15:11, Melanie Plageman wrote:

Also, the iterators in the TableScanDescData might be something I
could live with in the source code for a couple months before we make
the rest of the changes in July+. But, adding them does push the
TableScanDescData->rs_parallel member into the second cacheline, which
will be true in versions of Postgres people are using for years. I
didn't perf test, but seems bad.

I haven't though about how it affects cachelines, TBH. I'd expect it to
have minimal impact, because while it makes this struct larger it should
make some other struct (used in essentially the same places) smaller. So
I'd guess this to be a zero sum game, but perhaps I'm wrong.

Yea, to be honest, I didn't do extensive analysis. I just ran `pahole
-C TableScanDescData` with the patch and on master and further
convinced myself the whole thing was a bad idea.

For me the main question was "Is this the right place for this, even if
it's only temporary?"

Yep.

So, yes, unfortunately, I think we should pick up on the BHS saga in a
few months. Or, actually, we should start focusing on that parallel
BHS + 0 readahead bug and whether or not we are going to fix it.

Yes, the July CF is a good time to focus on this, early in the cycle.

I've pushed the entry to the next CF. Even though some of the patches
were committed, I think it makes more sense to leave the CF item open
until at least the prefetch table AM violation is removed. Then we
could make a new CF entry for the streaming read user.

When I get a chance, I'll post a full set of the outstanding patches
to this thread -- including the streaming read-related refactoring and
user.

Oh, and, side note, in my previous email [1]/messages/by-id/CAAKRu_Zg8Bj66OZD46Jd-ksh02OGrPR8z0JLPQqEZNEHASi6uw@mail.gmail.com about the
empty_tuples_pending assert, I should mention that you need
set enable_seqscan = off
set enable_indexscan = off
to force bitmpaheapscan and get the plan for my fake repro.

- Melanie

[1]: /messages/by-id/CAAKRu_Zg8Bj66OZD46Jd-ksh02OGrPR8z0JLPQqEZNEHASi6uw@mail.gmail.com

#114Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#112)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/7/24 16:24, Melanie Plageman wrote:

On Sun, Apr 7, 2024 at 7:38 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/7/24 06:17, Melanie Plageman wrote:

On Sun, Apr 07, 2024 at 02:27:43AM +0200, Tomas Vondra wrote:

On 4/6/24 23:34, Melanie Plageman wrote:

...

I realized it makes more sense to add a FIXME (I used XXX. I'm not when
to use what) with a link to the message where Andres describes why he
thinks it is a bug. If we plan on fixing it, it is good to have a record
of that. And it makes it easier to put a clear and accurate comment.
Done in 0009.

OK, thanks. If think 0001-0008 are ready to go, with some minor tweaks
per above (tuple vs. tuples etc.), and the question about the recheck
flag. If you can do these tweaks, I'll get that committed today and we
can try to get a couple more patches in tomorrow.

Attached v19 rebases the rest of the commits from v17 over the first
nine patches from v18. All patches 0001-0009 are unchanged from v18. I
have made updates and done cleanup on 0010-0021.

I've pushed 0001-0005, I'll get back to this tomorrow and see how much
more we can get in for v17.

Thanks! I thought about it a bit more, and I got worried about the

Assert(scan->rs_empty_tuples_pending == 0);

in heap_rescan() and heap_endscan().

I was worried if we don't complete the scan it could end up tripping
incorrectly.

I tried to come up with a query which didn't end up emitting all of the
tuples on the page (using a LIMIT clause), but I struggled to come up
with an example that qualified for the skip fetch optimization and also
returned before completing the scan.

I could work a bit harder tomorrow to try and come up with something.
However, I think it might be safer to just change these to:

scan->rs_empty_tuples_pending = 0

Hmmm, good point. I haven't tried, but wouldn't something like "SELECT 1
FROM t WHERE column = X LIMIT 1" do the trick? Probably in a join, as a
correlated subquery?

Unfortunately (or fortunately, I guess) that exact thing won't work
because even constant values in the target list disqualify it for the
skip fetch optimization.

Being a bit too lazy to look at planner code this morning, I removed
the target list requirement like this:

-           need_tuples = (node->ss.ps.plan->qual != NIL ||
-                          node->ss.ps.plan->targetlist != NIL);
+           need_tuples = (node->ss.ps.plan->qual != NIL);

And can easily trip the assert with this:

create table foo (a int);
insert into foo select i from generate_series(1,10)i;
create index on foo(a);
vacuum foo;
select 1 from (select 2 from foo limit 3);

Anyway, I don't know if we could find a query that does actually hit
this. The only bitmap heap scan queries in the regress suite that meet
the
BitmapHeapScanState->ss.ps.plan->targetlist == NIL
condition are aggregates (all are count(*)).

I'll dig a bit more later, but do you think this is worth adding an
open item for? Even though I don't have a repro yet?

Try this:

create table t (a int, b int) with (fillfactor=10);
insert into t select mod((i/22),2), (i/22) from generate_series(0,1000)
S(i);
create index on t(a);
vacuum analyze t;

set enable_indexonlyscan = off;
set enable_seqscan = off;
explain (analyze, verbose) select 1 from (values (1)) s(x) where exists
(select * from t where a = x);

KABOOM!

#2 0x000078a16ac5fafe in __GI_raise (sig=sig@entry=6) at
../sysdeps/posix/raise.c:26
#3 0x000078a16ac4887f in __GI_abort () at abort.c:79
#4 0x0000000000bb2c5a in ExceptionalCondition (conditionName=0xc42ba8
"scan->rs_empty_tuples_pending == 0", fileName=0xc429c8 "heapam.c",
lineNumber=1090) at assert.c:66
#5 0x00000000004f68bb in heap_endscan (sscan=0x19af3a0) at heapam.c:1090
#6 0x000000000077a94c in table_endscan (scan=0x19af3a0) at
../../../src/include/access/tableam.h:1001

So yeah, this assert is not quite correct. It's not breaking anything at
the moment, so we can fix it now or add it as an open item.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#115Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#114)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Apr 7, 2024 at 10:42 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/7/24 16:24, Melanie Plageman wrote:

Thanks! I thought about it a bit more, and I got worried about the

Assert(scan->rs_empty_tuples_pending == 0);

in heap_rescan() and heap_endscan().

I was worried if we don't complete the scan it could end up tripping
incorrectly.

I tried to come up with a query which didn't end up emitting all of the
tuples on the page (using a LIMIT clause), but I struggled to come up
with an example that qualified for the skip fetch optimization and also
returned before completing the scan.

I could work a bit harder tomorrow to try and come up with something.
However, I think it might be safer to just change these to:

scan->rs_empty_tuples_pending = 0

Hmmm, good point. I haven't tried, but wouldn't something like "SELECT 1
FROM t WHERE column = X LIMIT 1" do the trick? Probably in a join, as a
correlated subquery?

Unfortunately (or fortunately, I guess) that exact thing won't work
because even constant values in the target list disqualify it for the
skip fetch optimization.

Being a bit too lazy to look at planner code this morning, I removed
the target list requirement like this:

-           need_tuples = (node->ss.ps.plan->qual != NIL ||
-                          node->ss.ps.plan->targetlist != NIL);
+           need_tuples = (node->ss.ps.plan->qual != NIL);

And can easily trip the assert with this:

create table foo (a int);
insert into foo select i from generate_series(1,10)i;
create index on foo(a);
vacuum foo;
select 1 from (select 2 from foo limit 3);

Anyway, I don't know if we could find a query that does actually hit
this. The only bitmap heap scan queries in the regress suite that meet
the
BitmapHeapScanState->ss.ps.plan->targetlist == NIL
condition are aggregates (all are count(*)).

I'll dig a bit more later, but do you think this is worth adding an
open item for? Even though I don't have a repro yet?

Try this:

create table t (a int, b int) with (fillfactor=10);
insert into t select mod((i/22),2), (i/22) from generate_series(0,1000)
S(i);
create index on t(a);
vacuum analyze t;

set enable_indexonlyscan = off;
set enable_seqscan = off;
explain (analyze, verbose) select 1 from (values (1)) s(x) where exists
(select * from t where a = x);

KABOOM!

Ooo fancy query! Good job.

#2 0x000078a16ac5fafe in __GI_raise (sig=sig@entry=6) at
../sysdeps/posix/raise.c:26
#3 0x000078a16ac4887f in __GI_abort () at abort.c:79
#4 0x0000000000bb2c5a in ExceptionalCondition (conditionName=0xc42ba8
"scan->rs_empty_tuples_pending == 0", fileName=0xc429c8 "heapam.c",
lineNumber=1090) at assert.c:66
#5 0x00000000004f68bb in heap_endscan (sscan=0x19af3a0) at heapam.c:1090
#6 0x000000000077a94c in table_endscan (scan=0x19af3a0) at
../../../src/include/access/tableam.h:1001

So yeah, this assert is not quite correct. It's not breaking anything at
the moment, so we can fix it now or add it as an open item.

I've added an open item [1]https://wiki.postgresql.org/wiki/PostgreSQL_17_Open_Items#Open_Issues, because what's one open item when you can
have two? (me)

- Melanie

[1]: https://wiki.postgresql.org/wiki/PostgreSQL_17_Open_Items#Open_Issues

#116Richard Guo
guofenglinux@gmail.com
In reply to: Tomas Vondra (#114)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Apr 7, 2024 at 10:42 PM Tomas Vondra <tomas.vondra@enterprisedb.com>
wrote:

create table t (a int, b int) with (fillfactor=10);
insert into t select mod((i/22),2), (i/22) from generate_series(0,1000)
S(i);
create index on t(a);
vacuum analyze t;

set enable_indexonlyscan = off;
set enable_seqscan = off;
explain (analyze, verbose) select 1 from (values (1)) s(x) where exists
(select * from t where a = x);

KABOOM!

FWIW, it seems to me that this assert could be triggered in cases where,
during a join, not all inner tuples need to be scanned before skipping to
next outer tuple. This can happen for 'single_match' or anti-join.

The query provided by Tomas is an example of 'single_match' case. Here
is a query for anti-join that can also trigger this assert.

explain (analyze, verbose)
select t1.a from t t1 left join t t2 on t2.a = 1 where t2.a is null;
server closed the connection unexpectedly

Thanks
Richard

#117Michael Paquier
michael@paquier.xyz
In reply to: Melanie Plageman (#115)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Apr 07, 2024 at 10:54:56AM -0400, Melanie Plageman wrote:

I've added an open item [1], because what's one open item when you can
have two? (me)

And this is still an open item as of today. What's the plan to move
forward here?
--
Michael

#118Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Michael Paquier (#117)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/18/24 09:10, Michael Paquier wrote:

On Sun, Apr 07, 2024 at 10:54:56AM -0400, Melanie Plageman wrote:

I've added an open item [1], because what's one open item when you can
have two? (me)

And this is still an open item as of today. What's the plan to move
forward here?

AFAIK the plan is to replace the asserts with actually resetting the
rs_empty_tuples_pending field to 0, as suggested by Melanie a week ago.
I assume she was busy with the post-freeze AM reworks last week, so this
was on a back burner.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#119Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#118)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Apr 18, 2024 at 5:39 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/18/24 09:10, Michael Paquier wrote:

On Sun, Apr 07, 2024 at 10:54:56AM -0400, Melanie Plageman wrote:

I've added an open item [1], because what's one open item when you can
have two? (me)

And this is still an open item as of today. What's the plan to move
forward here?

AFAIK the plan is to replace the asserts with actually resetting the
rs_empty_tuples_pending field to 0, as suggested by Melanie a week ago.
I assume she was busy with the post-freeze AM reworks last week, so this
was on a back burner.

yep, sorry. Also I took a few days off. I'm just catching up today. I
want to pop in one of Richard or Tomas' examples as a test, since it
seems like it would add some coverage. I will have a patch soon.

- Melanie

#120Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#119)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Apr 22, 2024 at 1:01 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Apr 18, 2024 at 5:39 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/18/24 09:10, Michael Paquier wrote:

On Sun, Apr 07, 2024 at 10:54:56AM -0400, Melanie Plageman wrote:

I've added an open item [1], because what's one open item when you can
have two? (me)

And this is still an open item as of today. What's the plan to move
forward here?

AFAIK the plan is to replace the asserts with actually resetting the
rs_empty_tuples_pending field to 0, as suggested by Melanie a week ago.
I assume she was busy with the post-freeze AM reworks last week, so this
was on a back burner.

yep, sorry. Also I took a few days off. I'm just catching up today. I
want to pop in one of Richard or Tomas' examples as a test, since it
seems like it would add some coverage. I will have a patch soon.

The patch with a fix is attached. I put the test in
src/test/regress/sql/join.sql. It isn't the perfect location because
it is testing something exercisable with a join but not directly
related to the fact that it is a join. I also considered
src/test/regress/sql/select.sql, but it also isn't directly related to
the query being a SELECT query. If there is a better place for a test
of a bitmap heap scan edge case, let me know.

One other note: there is some concurrency effect in the parallel
schedule group containing "join" where you won't trip the assert if
all the tests in that group in the parallel schedule are run. But, if
you would like to verify that the test exercises the correct code,
just reduce the group containing "join".

- Melanie

Attachments:

v1-0001-BitmapHeapScan-Remove-incorrect-assert.patchtext/x-patch; charset=US-ASCII; name=v1-0001-BitmapHeapScan-Remove-incorrect-assert.patchDownload
From 6ad777979c335f6cc16d3936defb634176a44995 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 23 Apr 2024 11:45:37 -0400
Subject: [PATCH v1] BitmapHeapScan: Remove incorrect assert

04e72ed617be pushed the skip fetch optimization (allowing bitmap heap
scans to operate like index-only scans if none of the underlying data is
needed) into heap AM-specific bitmap heap scan code.

04e72ed617be added an assert that all tuples in blocks eligible for the
optimization had been NULL-filled and emitted by the end of the scan.
This assert is incorrect when not all tuples need be scanned to execute
the query; for example: a join in which not all inner tuples need to be
scanned before skipping to the next outer tuple.

Author: Melanie Plageman
Reviewed-by: Richard Guo, Tomas Vondra
Discussion: https://postgr.es/m/CAMbWs48orzZVXa7-vP9Nt7vQWLTE04Qy4PePaLQYsVNQgo6qRg%40mail.gmail.com
---
 src/backend/access/heap/heapam.c   |  4 ++--
 src/test/regress/expected/join.out | 36 ++++++++++++++++++++++++++++++
 src/test/regress/sql/join.sql      | 24 ++++++++++++++++++++
 3 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4a4cf76269d..8906f161320 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1184,7 +1184,7 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1216,7 +1216,7 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_vmbuffer))
 		ReleaseBuffer(scan->rs_vmbuffer);
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 8b640c2fc2f..ce73939c267 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -8956,3 +8956,39 @@ where exists (select 1 from j3
 (13 rows)
 
 drop table j3;
+-- Check the case when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed.
+CREATE TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM GENERATE_SERIES(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+                       QUERY PLAN                        
+---------------------------------------------------------
+ Nested Loop Anti Join
+   ->  Seq Scan on skip_fetch t1
+   ->  Materialize
+         ->  Bitmap Heap Scan on skip_fetch t2
+               Recheck Cond: (a = 1)
+               ->  Bitmap Index Scan on skip_fetch_a_idx
+                     Index Cond: (a = 1)
+(7 rows)
+
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ a 
+---
+(0 rows)
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
+DROP TABLE skip_fetch;
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index c4c6c7b8ba2..700631cd938 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -3374,3 +3374,27 @@ where exists (select 1 from j3
       and t1.unique1 < 1;
 
 drop table j3;
+
+-- Check the case when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed.
+CREATE TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM GENERATE_SERIES(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+
+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
+DROP TABLE skip_fetch;
-- 
2.40.1

#121Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#120)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/23/24 18:05, Melanie Plageman wrote:

On Mon, Apr 22, 2024 at 1:01 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Apr 18, 2024 at 5:39 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/18/24 09:10, Michael Paquier wrote:

On Sun, Apr 07, 2024 at 10:54:56AM -0400, Melanie Plageman wrote:

I've added an open item [1], because what's one open item when you can
have two? (me)

And this is still an open item as of today. What's the plan to move
forward here?

AFAIK the plan is to replace the asserts with actually resetting the
rs_empty_tuples_pending field to 0, as suggested by Melanie a week ago.
I assume she was busy with the post-freeze AM reworks last week, so this
was on a back burner.

yep, sorry. Also I took a few days off. I'm just catching up today. I
want to pop in one of Richard or Tomas' examples as a test, since it
seems like it would add some coverage. I will have a patch soon.

The patch with a fix is attached. I put the test in
src/test/regress/sql/join.sql. It isn't the perfect location because
it is testing something exercisable with a join but not directly
related to the fact that it is a join. I also considered
src/test/regress/sql/select.sql, but it also isn't directly related to
the query being a SELECT query. If there is a better place for a test
of a bitmap heap scan edge case, let me know.

I don't see a problem with adding this to join.sql - why wouldn't this
count as something related to a join? Sure, it's not like this code
matters only for joins, but if you look at join.sql that applies to a
number of other tests (e.g. there are a couple btree tests).

That being said, it'd be good to explain in the comment why we're
testing this particular plan, not just what the plan looks like.

One other note: there is some concurrency effect in the parallel
schedule group containing "join" where you won't trip the assert if
all the tests in that group in the parallel schedule are run. But, if
you would like to verify that the test exercises the correct code,
just reduce the group containing "join".

That is ... interesting. Doesn't that mean that most test runs won't
actually detect the problem? That would make the test a bit useless.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#122Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#121)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, Apr 23, 2024 at 6:43 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/23/24 18:05, Melanie Plageman wrote:

The patch with a fix is attached. I put the test in
src/test/regress/sql/join.sql. It isn't the perfect location because
it is testing something exercisable with a join but not directly
related to the fact that it is a join. I also considered
src/test/regress/sql/select.sql, but it also isn't directly related to
the query being a SELECT query. If there is a better place for a test
of a bitmap heap scan edge case, let me know.

I don't see a problem with adding this to join.sql - why wouldn't this
count as something related to a join? Sure, it's not like this code
matters only for joins, but if you look at join.sql that applies to a
number of other tests (e.g. there are a couple btree tests).

I suppose it's true that other tests in this file use joins to test
other code. I guess if we limited join.sql to containing tests of join
implementation, it would be rather small. I just imagined it would be
nice if tests were grouped by what they were testing -- not how they
were testing it.

That being said, it'd be good to explain in the comment why we're
testing this particular plan, not just what the plan looks like.

You mean I should explain in the test comment why I included the
EXPLAIN plan output? (because it needs to contain a bitmapheapscan to
actually be testing anything)

I do have a detailed explanation in my test comment of why this
particular query exercises the code we want to test.

One other note: there is some concurrency effect in the parallel
schedule group containing "join" where you won't trip the assert if
all the tests in that group in the parallel schedule are run. But, if
you would like to verify that the test exercises the correct code,
just reduce the group containing "join".

That is ... interesting. Doesn't that mean that most test runs won't
actually detect the problem? That would make the test a bit useless.

Yes, I should really have thought about it more. After further
investigation, I found that the reason it doesn't trip the assert when
the join test is run concurrently with other tests is that the SELECT
query doesn't use the skip fetch optimization because the VACUUM
doesn't set the pages all visible in the VM. In this case, it's
because the tuples' xmins are not before VacuumCutoffs->OldestXmin
(which is derived from GetOldestNonRemovableTransactionId()).

After thinking about it more, I suppose we can't add a test that
relies on the relation being all visible in the VM in a group in the
parallel schedule. I'm not sure this edge case is important enough to
merit its own group or an isolation test. What do you think?

- Melanie

#123Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#122)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Apr 24, 2024 at 4:46 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Tue, Apr 23, 2024 at 6:43 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/23/24 18:05, Melanie Plageman wrote:

One other note: there is some concurrency effect in the parallel
schedule group containing "join" where you won't trip the assert if
all the tests in that group in the parallel schedule are run. But, if
you would like to verify that the test exercises the correct code,
just reduce the group containing "join".

That is ... interesting. Doesn't that mean that most test runs won't
actually detect the problem? That would make the test a bit useless.

Yes, I should really have thought about it more. After further
investigation, I found that the reason it doesn't trip the assert when
the join test is run concurrently with other tests is that the SELECT
query doesn't use the skip fetch optimization because the VACUUM
doesn't set the pages all visible in the VM. In this case, it's
because the tuples' xmins are not before VacuumCutoffs->OldestXmin
(which is derived from GetOldestNonRemovableTransactionId()).

After thinking about it more, I suppose we can't add a test that
relies on the relation being all visible in the VM in a group in the
parallel schedule. I'm not sure this edge case is important enough to
merit its own group or an isolation test. What do you think?

Andres rightly pointed out to me off-list that if I just used a temp
table, the table would only be visible to the testing backend anyway.
I've done that in the attached v2. Now the test is deterministic.

- Melanie

Attachments:

v2-0001-BitmapHeapScan-Remove-incorrect-assert.patchtext/x-patch; charset=US-ASCII; name=v2-0001-BitmapHeapScan-Remove-incorrect-assert.patchDownload
From c5f28d12f75f5af84ede0db563fc5c0b53295c65 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 25 Apr 2024 18:50:14 -0400
Subject: [PATCH v2] BitmapHeapScan: Remove incorrect assert

04e72ed617be pushed the skip fetch optimization (allowing bitmap heap
scans to operate like index-only scans if none of the underlying data is
needed) into heap AM-specific bitmap heap scan code.

04e72ed617be added an assert that all tuples in blocks eligible for the
optimization had been NULL-filled and emitted by the end of the scan.
This assert is incorrect when not all tuples need be scanned to execute
the query; for example: a join in which not all inner tuples need to be
scanned before skipping to the next outer tuple.

Author: Melanie Plageman
Reviewed-by: Richard Guo, Tomas Vondra
Discussion: https://postgr.es/m/CAMbWs48orzZVXa7-vP9Nt7vQWLTE04Qy4PePaLQYsVNQgo6qRg%40mail.gmail.com
---
 src/backend/access/heap/heapam.c   |  4 ++--
 src/test/regress/expected/join.out | 37 ++++++++++++++++++++++++++++++
 src/test/regress/sql/join.sql      | 25 ++++++++++++++++++++
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4a4cf76269d..8906f161320 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1184,7 +1184,7 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1216,7 +1216,7 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_vmbuffer))
 		ReleaseBuffer(scan->rs_vmbuffer);
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 8b640c2fc2f..4f0292c7285 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -8956,3 +8956,40 @@ where exists (select 1 from j3
 (13 rows)
 
 drop table j3;
+-- Check the case when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+                       QUERY PLAN                        
+---------------------------------------------------------
+ Nested Loop Anti Join
+   ->  Seq Scan on skip_fetch t1
+   ->  Materialize
+         ->  Bitmap Heap Scan on skip_fetch t2
+               Recheck Cond: (a = 1)
+               ->  Bitmap Index Scan on skip_fetch_a_idx
+                     Index Cond: (a = 1)
+(7 rows)
+
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ a 
+---
+(0 rows)
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index c4c6c7b8ba2..25743ec972a 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -3374,3 +3374,28 @@ where exists (select 1 from j3
       and t1.unique1 < 1;
 
 drop table j3;
+
+-- Check the case when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+
+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
-- 
2.40.1

#124Tom Lane
tgl@sss.pgh.pa.us
In reply to: Melanie Plageman (#123)
Re: BitmapHeapScan streaming read user and prelim refactoring

Melanie Plageman <melanieplageman@gmail.com> writes:

On Wed, Apr 24, 2024 at 4:46 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

After thinking about it more, I suppose we can't add a test that
relies on the relation being all visible in the VM in a group in the
parallel schedule. I'm not sure this edge case is important enough to
merit its own group or an isolation test. What do you think?

Andres rightly pointed out to me off-list that if I just used a temp
table, the table would only be visible to the testing backend anyway.
I've done that in the attached v2. Now the test is deterministic.

Hmm, is that actually true? There's no more reason to think a tuple
in a temp table is old enough to be visible to all other sessions
than one in any other table. It could be all right if we had a
special-case rule for setting all-visible in temp tables. Which
indeed I thought we had, but I can't find any evidence of that in
vacuumlazy.c, nor did a trawl of the commit log turn up anything
promising. Am I just looking in the wrong place?

regards, tom lane

#125Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#124)
Re: BitmapHeapScan streaming read user and prelim refactoring

I wrote:

Hmm, is that actually true? There's no more reason to think a tuple
in a temp table is old enough to be visible to all other sessions
than one in any other table. It could be all right if we had a
special-case rule for setting all-visible in temp tables. Which
indeed I thought we had, but I can't find any evidence of that in
vacuumlazy.c, nor did a trawl of the commit log turn up anything
promising. Am I just looking in the wrong place?

Ah, never mind that --- I must be looking in the wrong place.
Direct experimentation proves that VACUUM will set all-visible bits
for temp tables even in the presence of concurrent transactions.

regards, tom lane

#126Melanie Plageman
melanieplageman@gmail.com
In reply to: Tom Lane (#125)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Apr 25, 2024 at 7:57 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

I wrote:

Hmm, is that actually true? There's no more reason to think a tuple
in a temp table is old enough to be visible to all other sessions
than one in any other table. It could be all right if we had a
special-case rule for setting all-visible in temp tables. Which
indeed I thought we had, but I can't find any evidence of that in
vacuumlazy.c, nor did a trawl of the commit log turn up anything
promising. Am I just looking in the wrong place?

Ah, never mind that --- I must be looking in the wrong place.
Direct experimentation proves that VACUUM will set all-visible bits
for temp tables even in the presence of concurrent transactions.

If this seems correct to you, are you okay with the rest of the fix
and test? We could close this open item once the patch is acceptable.

- Melanie

#127Daniel Gustafsson
daniel@yesql.se
In reply to: Melanie Plageman (#126)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 26 Apr 2024, at 15:04, Melanie Plageman <melanieplageman@gmail.com> wrote:

If this seems correct to you, are you okay with the rest of the fix
and test? We could close this open item once the patch is acceptable.

From reading the discussion and the patch this seems like the right fix to me.
Does the test added here aptly cover 04e72ed617be in terms its functionality?

--
Daniel Gustafsson

#128Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Daniel Gustafsson (#127)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/30/24 14:07, Daniel Gustafsson wrote:

On 26 Apr 2024, at 15:04, Melanie Plageman <melanieplageman@gmail.com> wrote:

If this seems correct to you, are you okay with the rest of the fix
and test? We could close this open item once the patch is acceptable.

From reading the discussion and the patch this seems like the right fix to me.

I agree.

Does the test added here aptly cover 04e72ed617be in terms its functionality?

AFAIK the test fails without the fix and works with it, so I believe it
does cover the relevant functionality.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#129Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#122)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 4/24/24 22:46, Melanie Plageman wrote:

On Tue, Apr 23, 2024 at 6:43 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/23/24 18:05, Melanie Plageman wrote:

The patch with a fix is attached. I put the test in
src/test/regress/sql/join.sql. It isn't the perfect location because
it is testing something exercisable with a join but not directly
related to the fact that it is a join. I also considered
src/test/regress/sql/select.sql, but it also isn't directly related to
the query being a SELECT query. If there is a better place for a test
of a bitmap heap scan edge case, let me know.

I don't see a problem with adding this to join.sql - why wouldn't this
count as something related to a join? Sure, it's not like this code
matters only for joins, but if you look at join.sql that applies to a
number of other tests (e.g. there are a couple btree tests).

I suppose it's true that other tests in this file use joins to test
other code. I guess if we limited join.sql to containing tests of join
implementation, it would be rather small. I just imagined it would be
nice if tests were grouped by what they were testing -- not how they
were testing it.

That being said, it'd be good to explain in the comment why we're
testing this particular plan, not just what the plan looks like.

You mean I should explain in the test comment why I included the
EXPLAIN plan output? (because it needs to contain a bitmapheapscan to
actually be testing anything)

No, I meant that the comment before the test describes a couple
requirements the plan needs to meet (no need to process all inner
tuples, bitmapscan eligible for skip_fetch on outer side, ...), but it
does not explain why we're testing that plan.

I could get to that by doing git-blame to see what commit added this
code, and then read the linked discussion. Perhaps that's enough, but
maybe the comment could say something like "verify we properly discard
tuples on rescans" or something like that?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#130Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#129)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, May 2, 2024 at 5:37 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/24/24 22:46, Melanie Plageman wrote:

On Tue, Apr 23, 2024 at 6:43 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/23/24 18:05, Melanie Plageman wrote:

The patch with a fix is attached. I put the test in
src/test/regress/sql/join.sql. It isn't the perfect location because
it is testing something exercisable with a join but not directly
related to the fact that it is a join. I also considered
src/test/regress/sql/select.sql, but it also isn't directly related to
the query being a SELECT query. If there is a better place for a test
of a bitmap heap scan edge case, let me know.

I don't see a problem with adding this to join.sql - why wouldn't this
count as something related to a join? Sure, it's not like this code
matters only for joins, but if you look at join.sql that applies to a
number of other tests (e.g. there are a couple btree tests).

I suppose it's true that other tests in this file use joins to test
other code. I guess if we limited join.sql to containing tests of join
implementation, it would be rather small. I just imagined it would be
nice if tests were grouped by what they were testing -- not how they
were testing it.

That being said, it'd be good to explain in the comment why we're
testing this particular plan, not just what the plan looks like.

You mean I should explain in the test comment why I included the
EXPLAIN plan output? (because it needs to contain a bitmapheapscan to
actually be testing anything)

No, I meant that the comment before the test describes a couple
requirements the plan needs to meet (no need to process all inner
tuples, bitmapscan eligible for skip_fetch on outer side, ...), but it
does not explain why we're testing that plan.

I could get to that by doing git-blame to see what commit added this
code, and then read the linked discussion. Perhaps that's enough, but
maybe the comment could say something like "verify we properly discard
tuples on rescans" or something like that?

Attached is v3. I didn't use your exact language because the test
wouldn't actually verify that we properly discard the tuples. Whether
or not the empty tuples are all emitted, it just resets the counter to
0. I decided to go with "exercise" instead.

- Melanie

Attachments:

v3-0001-BitmapHeapScan-Remove-incorrect-assert.patchtext/x-patch; charset=US-ASCII; name=v3-0001-BitmapHeapScan-Remove-incorrect-assert.patchDownload
From 0f10d304fc7dcce99622f348183f36a8062e70c6 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 10 May 2024 14:52:34 -0400
Subject: [PATCH v3] BitmapHeapScan: Remove incorrect assert

04e72ed617be pushed the skip fetch optimization (allowing bitmap heap
scans to operate like index-only scans if none of the underlying data is
needed) into heap AM-specific bitmap heap scan code.

04e72ed617be added an assert that all tuples in blocks eligible for the
optimization had been NULL-filled and emitted by the end of the scan.
This assert is incorrect when not all tuples need be scanned to execute
the query; for example: a join in which not all inner tuples need to be
scanned before skipping to the next outer tuple.

Author: Melanie Plageman
Reviewed-by: Richard Guo, Tomas Vondra
Discussion: https://postgr.es/m/CAMbWs48orzZVXa7-vP9Nt7vQWLTE04Qy4PePaLQYsVNQgo6qRg%40mail.gmail.com
---
 src/backend/access/heap/heapam.c   |  4 ++--
 src/test/regress/expected/join.out | 38 ++++++++++++++++++++++++++++++
 src/test/regress/sql/join.sql      | 26 ++++++++++++++++++++
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4be0dee4de..8600c22515 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1184,7 +1184,7 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1216,7 +1216,7 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_vmbuffer))
 		ReleaseBuffer(scan->rs_vmbuffer);
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 0246d56aea..8829bd76e7 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -7924,3 +7924,41 @@ where exists (select 1 from j3
 (13 rows)
 
 drop table j3;
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+                       QUERY PLAN                        
+---------------------------------------------------------
+ Nested Loop Anti Join
+   ->  Seq Scan on skip_fetch t1
+   ->  Materialize
+         ->  Bitmap Heap Scan on skip_fetch t2
+               Recheck Cond: (a = 1)
+               ->  Bitmap Index Scan on skip_fetch_a_idx
+                     Index Cond: (a = 1)
+(7 rows)
+
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ a 
+---
+(0 rows)
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 923e7c5549..b73ce67bd2 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -2904,3 +2904,29 @@ where exists (select 1 from j3
       and t1.unique1 < 1;
 
 drop table j3;
+
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+
+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
-- 
2.34.1

#131Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#130)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 5/10/24 21:48, Melanie Plageman wrote:

On Thu, May 2, 2024 at 5:37 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/24/24 22:46, Melanie Plageman wrote:

On Tue, Apr 23, 2024 at 6:43 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 4/23/24 18:05, Melanie Plageman wrote:

The patch with a fix is attached. I put the test in
src/test/regress/sql/join.sql. It isn't the perfect location because
it is testing something exercisable with a join but not directly
related to the fact that it is a join. I also considered
src/test/regress/sql/select.sql, but it also isn't directly related to
the query being a SELECT query. If there is a better place for a test
of a bitmap heap scan edge case, let me know.

I don't see a problem with adding this to join.sql - why wouldn't this
count as something related to a join? Sure, it's not like this code
matters only for joins, but if you look at join.sql that applies to a
number of other tests (e.g. there are a couple btree tests).

I suppose it's true that other tests in this file use joins to test
other code. I guess if we limited join.sql to containing tests of join
implementation, it would be rather small. I just imagined it would be
nice if tests were grouped by what they were testing -- not how they
were testing it.

That being said, it'd be good to explain in the comment why we're
testing this particular plan, not just what the plan looks like.

You mean I should explain in the test comment why I included the
EXPLAIN plan output? (because it needs to contain a bitmapheapscan to
actually be testing anything)

No, I meant that the comment before the test describes a couple
requirements the plan needs to meet (no need to process all inner
tuples, bitmapscan eligible for skip_fetch on outer side, ...), but it
does not explain why we're testing that plan.

I could get to that by doing git-blame to see what commit added this
code, and then read the linked discussion. Perhaps that's enough, but
maybe the comment could say something like "verify we properly discard
tuples on rescans" or something like that?

Attached is v3. I didn't use your exact language because the test
wouldn't actually verify that we properly discard the tuples. Whether
or not the empty tuples are all emitted, it just resets the counter to
0. I decided to go with "exercise" instead.

I did go over the v3 patch, did a bunch of tests, and I think it's fine
and ready to go. The one thing that might need some minor tweaks is the
commit message.

1) Isn't the subject "Remove incorrect assert" a bit misleading, as the
patch does not simply remove an assert, but replaces it with a reset of
the field the assert used to check? (The commit message does not mention
this either, at least not explicitly.)

2) The "heap AM-specific bitmap heap scan code" sounds a bit strange to
me, isn't the first "heap" unnecessary?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#132Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#131)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, May 11, 2024 at 3:18 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 5/10/24 21:48, Melanie Plageman wrote:

Attached is v3. I didn't use your exact language because the test
wouldn't actually verify that we properly discard the tuples. Whether
or not the empty tuples are all emitted, it just resets the counter to
0. I decided to go with "exercise" instead.

I did go over the v3 patch, did a bunch of tests, and I think it's fine
and ready to go. The one thing that might need some minor tweaks is the
commit message.

1) Isn't the subject "Remove incorrect assert" a bit misleading, as the
patch does not simply remove an assert, but replaces it with a reset of
the field the assert used to check? (The commit message does not mention
this either, at least not explicitly.)

I've updated the commit message.

2) The "heap AM-specific bitmap heap scan code" sounds a bit strange to
me, isn't the first "heap" unnecessary?

bitmap heap scan has been used to refer to bitmap table scans, as the
name wasn't changed from heap when the table AM API was added (e.g.
BitmapHeapNext() is used by all table AMs doing bitmap table scans).
04e72ed617be specifically pushed the skip fetch optimization into heap
implementations of bitmap table scan callbacks, so it was important to
make this distinction. I've changed the commit message to say heap AM
implementations of bitmap table scan callbacks.

While looking at the patch again, I wondered if I should set
enable_material=false in the test. It doesn't matter from the
perspective of exercising the correct code; however, I wasn't sure if
disabling materialization would make the test more resilient against
future planner changes which could cause it to incorrectly fail.

- Melanie

Attachments:

v4-0001-BitmapHeapScan-Replace-incorrect-assert-with-rein.patchtext/x-patch; charset=US-ASCII; name=v4-0001-BitmapHeapScan-Replace-incorrect-assert-with-rein.patchDownload
From d3628d8d36b2be54b64c18402bdda80e1c8a436f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 10 May 2024 14:52:34 -0400
Subject: [PATCH v4] BitmapHeapScan: Replace incorrect assert with
 reinitialization

04e72ed617be pushed the skip fetch optimization (allowing bitmap heap
scans to operate like index-only scans if none of the underlying data is
needed) into heap AM implementations of bitmap table scan callbacks.

04e72ed617be added an assert that all tuples in blocks eligible for the
optimization had been NULL-filled and emitted by the end of the scan.
This assert is incorrect when not all tuples need be scanned to execute
the query; for example: a join in which not all inner tuples need to be
scanned before skipping to the next outer tuple.

Remove the assert and reset the field on which it previously asserted to
avoid incorrectly emitting NULL-filled tuples from a previous scan on
rescan.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Reported-by: Melanie Plageman
Reproduced-by: Tomas Vondra, Richard Guo
Discussion: https://postgr.es/m/CAMbWs48orzZVXa7-vP9Nt7vQWLTE04Qy4PePaLQYsVNQgo6qRg%40mail.gmail.com
---
 src/backend/access/heap/heapam.c   |  4 ++--
 src/test/regress/expected/join.out | 38 ++++++++++++++++++++++++++++++
 src/test/regress/sql/join.sql      | 26 ++++++++++++++++++++
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4be0dee4de..8600c22515 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1184,7 +1184,7 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1216,7 +1216,7 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_vmbuffer))
 		ReleaseBuffer(scan->rs_vmbuffer);
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 0246d56aea..8829bd76e7 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -7924,3 +7924,41 @@ where exists (select 1 from j3
 (13 rows)
 
 drop table j3;
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+                       QUERY PLAN                        
+---------------------------------------------------------
+ Nested Loop Anti Join
+   ->  Seq Scan on skip_fetch t1
+   ->  Materialize
+         ->  Bitmap Heap Scan on skip_fetch t2
+               Recheck Cond: (a = 1)
+               ->  Bitmap Index Scan on skip_fetch_a_idx
+                     Index Cond: (a = 1)
+(7 rows)
+
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ a 
+---
+(0 rows)
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 923e7c5549..b73ce67bd2 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -2904,3 +2904,29 @@ where exists (select 1 from j3
       and t1.unique1 < 1;
 
 drop table j3;
+
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+
+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
-- 
2.34.1

#133Michael Paquier
michael@paquier.xyz
In reply to: Melanie Plageman (#132)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, May 13, 2024 at 10:05:03AM -0400, Melanie Plageman wrote:

Remove the assert and reset the field on which it previously asserted to
avoid incorrectly emitting NULL-filled tuples from a previous scan on
rescan.

-	Assert(scan->rs_empty_tuples_pending == 0);
+	scan->rs_empty_tuples_pending = 0;

Perhaps this should document the reason why the reset is done in these
two paths rather than let the reader guess it? And this is about
avoiding emitting some tuples from a previous scan.

+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;

Nit: adjusting the casing of the second SET here.
--
Michael

#134Melanie Plageman
melanieplageman@gmail.com
In reply to: Michael Paquier (#133)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, May 14, 2024 at 2:18 AM Michael Paquier <michael@paquier.xyz> wrote:

On Mon, May 13, 2024 at 10:05:03AM -0400, Melanie Plageman wrote:

Remove the assert and reset the field on which it previously asserted to
avoid incorrectly emitting NULL-filled tuples from a previous scan on
rescan.

-     Assert(scan->rs_empty_tuples_pending == 0);
+     scan->rs_empty_tuples_pending = 0;

Perhaps this should document the reason why the reset is done in these
two paths rather than let the reader guess it? And this is about
avoiding emitting some tuples from a previous scan.

I've added a comment to heap_rescan() in the attached v5. Doing so
made me realize that we shouldn't bother resetting it in
heap_endscan(). Doing so is perhaps more confusing, because it implies
that field may somehow be used later. I've removed the reset of
rs_empty_tuples_pending from heap_endscan().

+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;

Nit: adjusting the casing of the second SET here.

I've fixed this. I've also set enable_material off as I mentioned I
might in my earlier mail.

- Melanie

Attachments:

v5-0001-BitmapHeapScan-Remove-incorrect-assert-and-reset-.patchtext/x-patch; charset=US-ASCII; name=v5-0001-BitmapHeapScan-Remove-incorrect-assert-and-reset-.patchDownload
From d44679397e3aaa043afad2108ec904f68b7052b3 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 14 May 2024 13:36:42 -0400
Subject: [PATCH v5] BitmapHeapScan: Remove incorrect assert and reset field

04e72ed617be pushed the skip fetch optimization (allowing bitmap heap
scans to operate like index-only scans if none of the underlying data is
needed) into heap AM implementations of bitmap table scan callbacks.

04e72ed617be added an assert that all tuples in blocks eligible for the
optimization had been NULL-filled and emitted by the end of the scan.
This assert is incorrect when not all tuples need be scanned to execute
the query; for example: a join in which not all inner tuples need to be
scanned before skipping to the next outer tuple.

Remove the assert and reset the field on which it previously asserted to
avoid incorrectly emitting NULL-filled tuples from a previous scan on
rescan.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Michael Paquier
Reported-by: Melanie Plageman
Reproduced-by: Tomas Vondra, Richard Guo
Discussion: https://postgr.es/m/CAMbWs48orzZVXa7-vP9Nt7vQWLTE04Qy4PePaLQYsVNQgo6qRg%40mail.gmail.com
---
 src/backend/access/heap/heapam.c   |  9 ++++---
 src/test/regress/expected/join.out | 39 ++++++++++++++++++++++++++++++
 src/test/regress/sql/join.sql      | 28 +++++++++++++++++++++
 3 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4be0dee4de..82bb9cb33b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1184,7 +1184,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	/*
+	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
+	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
+	 * on rescan.
+	 */
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1216,8 +1221,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_vmbuffer))
 		ReleaseBuffer(scan->rs_vmbuffer);
 
-	Assert(scan->rs_empty_tuples_pending == 0);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 0246d56aea..466be7b439 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -7924,3 +7924,42 @@ where exists (select 1 from j3
 (13 rows)
 
 drop table j3;
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+SET enable_indexonlyscan = off;
+SET enable_indexscan = off;
+SET enable_material = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+                    QUERY PLAN                     
+---------------------------------------------------
+ Nested Loop Anti Join
+   ->  Seq Scan on skip_fetch t1
+   ->  Bitmap Heap Scan on skip_fetch t2
+         Recheck Cond: (a = 1)
+         ->  Bitmap Index Scan on skip_fetch_a_idx
+               Index Cond: (a = 1)
+(6 rows)
+
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ a 
+---
+(0 rows)
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_material;
+RESET enable_seqscan;
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 923e7c5549..1bd4ed8d29 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -2904,3 +2904,31 @@ where exists (select 1 from j3
       and t1.unique1 < 1;
 
 drop table j3;
+
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+
+SET enable_indexonlyscan = off;
+SET enable_indexscan = off;
+SET enable_material = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_material;
+RESET enable_seqscan;
-- 
2.34.1

#135Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#134)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 5/14/24 19:42, Melanie Plageman wrote:

On Tue, May 14, 2024 at 2:18 AM Michael Paquier <michael@paquier.xyz> wrote:

On Mon, May 13, 2024 at 10:05:03AM -0400, Melanie Plageman wrote:

Remove the assert and reset the field on which it previously asserted to
avoid incorrectly emitting NULL-filled tuples from a previous scan on
rescan.

-     Assert(scan->rs_empty_tuples_pending == 0);
+     scan->rs_empty_tuples_pending = 0;

Perhaps this should document the reason why the reset is done in these
two paths rather than let the reader guess it? And this is about
avoiding emitting some tuples from a previous scan.

I've added a comment to heap_rescan() in the attached v5. Doing so
made me realize that we shouldn't bother resetting it in
heap_endscan(). Doing so is perhaps more confusing, because it implies
that field may somehow be used later. I've removed the reset of
rs_empty_tuples_pending from heap_endscan().

+1

+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;

Nit: adjusting the casing of the second SET here.

I've fixed this. I've also set enable_material off as I mentioned I
might in my earlier mail.

I'm not sure this (setting more and more GUCs to prevent hypothetical
plan changes) is a good practice. Because how do you know the plan does
not change for some other unexpected reason, possibly in the future?

IMHO if the test requires a specific plan, it's better to do an actual
"explain (rows off, costs off)" to check that.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#136Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#135)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, May 14, 2024 at 2:33 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 5/14/24 19:42, Melanie Plageman wrote:

I've fixed this. I've also set enable_material off as I mentioned I
might in my earlier mail.

I'm not sure this (setting more and more GUCs to prevent hypothetical
plan changes) is a good practice. Because how do you know the plan does
not change for some other unexpected reason, possibly in the future?

Sure. So, you think it is better not to have enable_material = false?

IMHO if the test requires a specific plan, it's better to do an actual
"explain (rows off, costs off)" to check that.

When you say "rows off", do you mean do something to ensure that it
doesn't return tuples? Because I don't see a ROWS option for EXPLAIN
in the docs.

- Melanie

#137Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#136)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 5/14/24 20:40, Melanie Plageman wrote:

On Tue, May 14, 2024 at 2:33 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 5/14/24 19:42, Melanie Plageman wrote:

I've fixed this. I've also set enable_material off as I mentioned I
might in my earlier mail.

I'm not sure this (setting more and more GUCs to prevent hypothetical
plan changes) is a good practice. Because how do you know the plan does
not change for some other unexpected reason, possibly in the future?

Sure. So, you think it is better not to have enable_material = false?

Right. Unless it's actually needed to force the necessary plan.

IMHO if the test requires a specific plan, it's better to do an actual
"explain (rows off, costs off)" to check that.

When you say "rows off", do you mean do something to ensure that it
doesn't return tuples? Because I don't see a ROWS option for EXPLAIN
in the docs.

Sorry, I meant to hide the cardinality estimates in the explain, but I
got confused. "COSTS OFF" is enough.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#138Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#137)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, May 14, 2024 at 2:44 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 5/14/24 20:40, Melanie Plageman wrote:

On Tue, May 14, 2024 at 2:33 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 5/14/24 19:42, Melanie Plageman wrote:

I've fixed this. I've also set enable_material off as I mentioned I
might in my earlier mail.

I'm not sure this (setting more and more GUCs to prevent hypothetical
plan changes) is a good practice. Because how do you know the plan does
not change for some other unexpected reason, possibly in the future?

Sure. So, you think it is better not to have enable_material = false?

Right. Unless it's actually needed to force the necessary plan.

Attached v6 does not use enable_material = false (as it is not needed).

- Melanie

Attachments:

v6-0001-BitmapHeapScan-Remove-incorrect-assert-and-reset-.patchtext/x-patch; charset=US-ASCII; name=v6-0001-BitmapHeapScan-Remove-incorrect-assert-and-reset-.patchDownload
From 6dc674fff206dc62c64d348ff0042b1d20798511 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 14 May 2024 13:36:42 -0400
Subject: [PATCH v6] BitmapHeapScan: Remove incorrect assert and reset field

04e72ed617be pushed the skip fetch optimization (allowing bitmap heap
scans to operate like index-only scans if none of the underlying data is
needed) into heap AM implementations of bitmap table scan callbacks.

04e72ed617be added an assert that all tuples in blocks eligible for the
optimization had been NULL-filled and emitted by the end of the scan.
This assert is incorrect when not all tuples need be scanned to execute
the query; for example: a join in which not all inner tuples need to be
scanned before skipping to the next outer tuple.

Remove the assert and reset the field on which it previously asserted to
avoid incorrectly emitting NULL-filled tuples from a previous scan on
rescan.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Michael Paquier
Reported-by: Melanie Plageman
Reproduced-by: Tomas Vondra, Richard Guo
Discussion: https://postgr.es/m/CAMbWs48orzZVXa7-vP9Nt7vQWLTE04Qy4PePaLQYsVNQgo6qRg%40mail.gmail.com
---
 src/backend/access/heap/heapam.c   |  9 ++++---
 src/test/regress/expected/join.out | 38 ++++++++++++++++++++++++++++++
 src/test/regress/sql/join.sql      | 26 ++++++++++++++++++++
 3 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4be0dee4de..82bb9cb33b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1184,7 +1184,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	/*
+	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
+	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
+	 * on rescan.
+	 */
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1216,8 +1221,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_vmbuffer))
 		ReleaseBuffer(scan->rs_vmbuffer);
 
-	Assert(scan->rs_empty_tuples_pending == 0);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 0246d56aea..df358f7605 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -7924,3 +7924,41 @@ where exists (select 1 from j3
 (13 rows)
 
 drop table j3;
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+SET enable_indexonlyscan = off;
+SET enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+                       QUERY PLAN                        
+---------------------------------------------------------
+ Nested Loop Anti Join
+   ->  Seq Scan on skip_fetch t1
+   ->  Materialize
+         ->  Bitmap Heap Scan on skip_fetch t2
+               Recheck Cond: (a = 1)
+               ->  Bitmap Index Scan on skip_fetch_a_idx
+                     Index Cond: (a = 1)
+(7 rows)
+
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ a 
+---
+(0 rows)
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 923e7c5549..d9199dfcad 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -2904,3 +2904,29 @@ where exists (select 1 from j3
       and t1.unique1 < 1;
 
 drop table j3;
+
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+
+SET enable_indexonlyscan = off;
+SET enable_indexscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+
+RESET enable_indexonlyscan;
+RESET enable_indexscan;
+RESET enable_seqscan;
-- 
2.34.1

#139Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Tomas Vondra (#135)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2024-May-14, Tomas Vondra wrote:

On 5/14/24 19:42, Melanie Plageman wrote:

+SET enable_indexonlyscan = off;
+set enable_indexscan = off;
+SET enable_seqscan = off;

Nit: adjusting the casing of the second SET here.

I've fixed this. I've also set enable_material off as I mentioned I
might in my earlier mail.

I'm not sure this (setting more and more GUCs to prevent hypothetical
plan changes) is a good practice. Because how do you know the plan does
not change for some other unexpected reason, possibly in the future?

I wonder why it resets enable_indexscan at all. I see that this query
first tries a seqscan, then if you disable that it tries an index only
scan, and if you disable that you get the expected bitmap indexscan.
But an indexscan doesn't seem to be in the cards.

IMHO if the test requires a specific plan, it's better to do an actual
"explain (rows off, costs off)" to check that.

That's already in the patch, right?

I do wonder how do we _know_ that the test is testing what it wants to
test:
QUERY PLAN
─────────────────────────────────────────────────────────
Nested Loop Anti Join
-> Seq Scan on skip_fetch t1
-> Materialize
-> Bitmap Heap Scan on skip_fetch t2
Recheck Cond: (a = 1)
-> Bitmap Index Scan on skip_fetch_a_idx
Index Cond: (a = 1)

Is it because of the shape of the index condition? Maybe it's worth
explaining in the comments for the tests.

BTW, I was running the explain while desultorily enabling and disabling
these GUCs and hit this assertion failure:

#4 0x000055e6c72afe28 in ExceptionalCondition (conditionName=conditionName@entry=0x55e6c731a928 "scan->rs_empty_tuples_pending == 0",
fileName=fileName@entry=0x55e6c731a3b0 "../../../../../../../../../pgsql/source/master/src/backend/access/heap/heapam.c", lineNumber=lineNumber@entry=1219)
at ../../../../../../../../../pgsql/source/master/src/backend/utils/error/assert.c:66
#5 0x000055e6c6e2e0c7 in heap_endscan (sscan=0x55e6c7b63e28) at ../../../../../../../../../pgsql/source/master/src/backend/access/heap/heapam.c:1219
#6 0x000055e6c6fb35a7 in ExecEndPlan (estate=0x55e6c7a7e9d0, planstate=<optimized out>) at ../../../../../../../../pgsql/source/master/src/backend/executor/execMain.c:1485
#7 standard_ExecutorEnd (queryDesc=0x55e6c7a736b8) at ../../../../../../../../pgsql/source/master/src/backend/executor/execMain.c:501
#8 0x000055e6c6f4d9aa in ExplainOnePlan (plannedstmt=plannedstmt@entry=0x55e6c7a735a8, into=into@entry=0x0, es=es@entry=0x55e6c7a448b8,
queryString=queryString@entry=0x55e6c796c210 "EXPLAIN (analyze, verbose, COSTS OFF) SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;", params=params@entry=0x0,
queryEnv=queryEnv@entry=0x0, planduration=0x7ffe8a291848, bufusage=0x0, mem_counters=0x0) at ../../../../../../../../pgsql/source/master/src/backend/commands/explain.c:770
#9 0x000055e6c6f4e257 in standard_ExplainOneQuery (query=<optimized out>, cursorOptions=2048, into=0x0, es=0x55e6c7a448b8,
queryString=0x55e6c796c210 "EXPLAIN (analyze, verbose, COSTS OFF) SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;", params=0x0, queryEnv=0x0)
at ../../../../../../../../pgsql/source/master/src/backend/commands/explain.c:502

I couldn't reproduce it again, though -- and for sure I don't know what
it means. All three GUCs are set false in the core.

--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
"Here's a general engineering tip: if the non-fun part is too complex for you
to figure out, that might indicate the fun part is too ambitious." (John Naylor)
/messages/by-id/CAFBsxsG4OWHBbSDM=sSeXrQGOtkPiOEOuME4yD7Ce41NtaAD9g@mail.gmail.com

#140Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Alvaro Herrera (#139)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2024-May-14, Alvaro Herrera wrote:

BTW, I was running the explain while desultorily enabling and disabling
these GUCs and hit this assertion failure:

#4 0x000055e6c72afe28 in ExceptionalCondition (conditionName=conditionName@entry=0x55e6c731a928 "scan->rs_empty_tuples_pending == 0",
fileName=fileName@entry=0x55e6c731a3b0 "../../../../../../../../../pgsql/source/master/src/backend/access/heap/heapam.c", lineNumber=lineNumber@entry=1219)
at ../../../../../../../../../pgsql/source/master/src/backend/utils/error/assert.c:66

Ah, I see now that this is precisely the assertion that this patch
removes. Nevermind ...

--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
"This is what I like so much about PostgreSQL. Most of the surprises
are of the "oh wow! That's cool" Not the "oh shit!" kind. :)"
Scott Marlowe, http://archives.postgresql.org/pgsql-admin/2008-10/msg00152.php

#141Melanie Plageman
melanieplageman@gmail.com
In reply to: Alvaro Herrera (#139)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, May 14, 2024 at 4:05 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:

On 2024-May-14, Tomas Vondra wrote:

I wonder why it resets enable_indexscan at all. I see that this query
first tries a seqscan, then if you disable that it tries an index only
scan, and if you disable that you get the expected bitmap indexscan.
But an indexscan doesn't seem to be in the cards.

Ah, yes. That is true. I think I added that when, in an older version
of the test, I had a query that did try an index scan before bitmap
heap scan. I've removed that guc from the attached v7.

IMHO if the test requires a specific plan, it's better to do an actual
"explain (rows off, costs off)" to check that.

That's already in the patch, right?

Yep.

I do wonder how do we _know_ that the test is testing what it wants to
test:
QUERY PLAN
─────────────────────────────────────────────────────────
Nested Loop Anti Join
-> Seq Scan on skip_fetch t1
-> Materialize
-> Bitmap Heap Scan on skip_fetch t2
Recheck Cond: (a = 1)
-> Bitmap Index Scan on skip_fetch_a_idx
Index Cond: (a = 1)

Is it because of the shape of the index condition? Maybe it's worth
explaining in the comments for the tests.

There is a comment in the test that explains what it is exercising and
how. We include the explain output (the plan) to ensure it is still
using a bitmap heap scan. The test exercises the skip fetch
optimization in bitmap heap scan when not all of the inner tuples are
emitted.

Without the patch, the test fails, so it is protection against someone
adding back that assert in the future. It is not protection against
someone deleting the line
scan->rs_empty_tuples_pending = 0
That is, it doesn't verify that the empty unused tuples count is
discarded. Do you think that is necessary?

- Melanie

Attachments:

v7-0001-BitmapHeapScan-Remove-incorrect-assert-and-reset-.patchtext/x-patch; charset=US-ASCII; name=v7-0001-BitmapHeapScan-Remove-incorrect-assert-and-reset-.patchDownload
From 031012be9d77d5f5888b306d546322e6176e527e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 14 May 2024 13:36:42 -0400
Subject: [PATCH v7] BitmapHeapScan: Remove incorrect assert and reset field

04e72ed617be pushed the skip fetch optimization (allowing bitmap heap
scans to operate like index-only scans if none of the underlying data is
needed) into heap AM implementations of bitmap table scan callbacks.

04e72ed617be added an assert that all tuples in blocks eligible for the
optimization had been NULL-filled and emitted by the end of the scan.
This assert is incorrect when not all tuples need be scanned to execute
the query; for example: a join in which not all inner tuples need to be
scanned before skipping to the next outer tuple.

Remove the assert and reset the field on which it previously asserted to
avoid incorrectly emitting NULL-filled tuples from a previous scan on
rescan.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Michael Paquier, Alvaro Herrera
Reported-by: Melanie Plageman
Reproduced-by: Tomas Vondra, Richard Guo
Discussion: https://postgr.es/m/CAMbWs48orzZVXa7-vP9Nt7vQWLTE04Qy4PePaLQYsVNQgo6qRg%40mail.gmail.com
---
 src/backend/access/heap/heapam.c   |  9 +++++---
 src/test/regress/expected/join.out | 36 ++++++++++++++++++++++++++++++
 src/test/regress/sql/join.sql      | 24 ++++++++++++++++++++
 3 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4be0dee4de..82bb9cb33b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1184,7 +1184,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 		scan->rs_vmbuffer = InvalidBuffer;
 	}
 
-	Assert(scan->rs_empty_tuples_pending == 0);
+	/*
+	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
+	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
+	 * on rescan.
+	 */
+	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1216,8 +1221,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_vmbuffer))
 		ReleaseBuffer(scan->rs_vmbuffer);
 
-	Assert(scan->rs_empty_tuples_pending == 0);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 0246d56aea..6b16c3a676 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -7924,3 +7924,39 @@ where exists (select 1 from j3
 (13 rows)
 
 drop table j3;
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+SET enable_indexonlyscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+                       QUERY PLAN                        
+---------------------------------------------------------
+ Nested Loop Anti Join
+   ->  Seq Scan on skip_fetch t1
+   ->  Materialize
+         ->  Bitmap Heap Scan on skip_fetch t2
+               Recheck Cond: (a = 1)
+               ->  Bitmap Index Scan on skip_fetch_a_idx
+                     Index Cond: (a = 1)
+(7 rows)
+
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ a 
+---
+(0 rows)
+
+RESET enable_indexonlyscan;
+RESET enable_seqscan;
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 923e7c5549..8bfe3b7ba6 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -2904,3 +2904,27 @@ where exists (select 1 from j3
       and t1.unique1 < 1;
 
 drop table j3;
+
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+--   1. A join doesn't require all inner tuples to be scanned for each outer
+--      tuple, and
+--   2. The inner side is scanned using a bitmap heap scan, and
+--   3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+--      This optimization is usable when no data from the underlying table is
+--      needed. Use a temp table so it is only visible to this backend and
+--      vacuum may reliably mark all blocks in the table all visible in the
+--      visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+
+SET enable_indexonlyscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+
+RESET enable_indexonlyscan;
+RESET enable_seqscan;
-- 
2.34.1

#142Robert Haas
robertmhaas@gmail.com
In reply to: Melanie Plageman (#141)
Re: BitmapHeapScan streaming read user and prelim refactoring

Procedural comment:

It's better to get this patch committed with an imperfect test case
than to have it miss beta1.

...Robert

#143Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Melanie Plageman (#141)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2024-May-14, Melanie Plageman wrote:

On Tue, May 14, 2024 at 4:05 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:

I do wonder how do we _know_ that the test is testing what it wants to
test:

We include the explain output (the plan) to ensure it is still
using a bitmap heap scan. The test exercises the skip fetch
optimization in bitmap heap scan when not all of the inner tuples are
emitted.

I meant -- the query returns an empty resultset, so how do we know it's
the empty resultset that we want and not a different empty resultset
that happens to be identical? (This is probably not a critical point
anyhow.)

Without the patch, the test fails, so it is protection against someone
adding back that assert in the future. It is not protection against
someone deleting the line
scan->rs_empty_tuples_pending = 0
That is, it doesn't verify that the empty unused tuples count is
discarded. Do you think that is necessary?

I don't think that's absolutely necessary. I suspect there are
thousands of lines that you could delete that would break things, with
no test directly raising red flags.

At this point I would go with the RMT's recommendation of pushing this
now to make sure the bug is fixed for beta1, even if the test is
imperfect. You can always polish the test afterwards if you feel like
it ...

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/
"No necesitamos banderas
No reconocemos fronteras" (Jorge González)

#144Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#108)
20 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Apr 7, 2024 at 12:17 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

After we decided not to pursue streaming bitmapheapscan for 17, I wanted
to make sure we removed the prefetch code table AM violation -- since we
weren't deleting that code. So what started out as me looking for a way
to clean up one commit ended up becoming a much larger project. Sorry
about that last minute code explosion! I do think there is a way to do
it right and make it nice. Also that violation would be gone if we
figure out how to get streaming bitmapheapscan behaving correctly.

So, there's just more motivation to make streaming bitmapheapscan
awesome for 18!

Attached v21 is the rest of the patches to make bitmap heap scan use
the read stream API.
Don't be alarmed by the 20 patches in the set. I tried to keep the
individual patches as small and easy to review as possible.

Patches 0001-0003 implement the async-friendly behavior needed both to
push down the VM lookups for prefetching and eventually to use the
read stream API.

Patches 0004-0006 add and make use of a common interface for the
shared and private (parallel and serial) bitmap iterator per Heikki's
suggestion in [1]/messages/by-id/5a172d1e-d69c-409a-b1fa-6521214c81c2@iki.fi.

Patches 0008 - 0012 make new scan descriptors for bitmap table scans
and the heap AM implementation. It is not possible to remove the
layering violations mentioned for bitmap table scans in tableam.h
without passing more bitmap-specific parameters to
table_begin/end/rescan(). Because bitmap heap scans use a fairly
reduced set of the members in the HeapScanDescData, it made sense to
enable specialized scan descriptors for bitmap table scans.

0013 pushes the primary iterator setup down into heap code.

0014 and 0015 push all of the prefetch code down into heap AM code as
suggested by Heikki in [1]/messages/by-id/5a172d1e-d69c-409a-b1fa-6521214c81c2@iki.fi.

0017 removes scan_bitmap_next_block() per Heikki's suggestion in [1]/messages/by-id/5a172d1e-d69c-409a-b1fa-6521214c81c2@iki.fi.

After all of these patches, we've removed the layering violations
mentioned previously in tableam.h. There is no use of the visibility
map anymore in generic bitmap table scan code. Almost all
block-specific logic is gone. The table AMs own the iterator almost
completely.

The one relic of iterator ownership is that for parallel bitmap heap
scan, a single process must scan the index, construct the bitmap, and
call tbm_prepare_shared_iterate() to set up the iterator for all the
processes. I didn't see a way to push this down (because to build the
bitmap we have to scan the index and call ExecProcNode()). I wonder if
this creates an odd split of responsibilities. I could use some other
synchronization mechanism to communicate which process built the
bitmap in the generic bitmap table scan code and thus should set up
the iterator in the heap implementation, but that sounds like a pretty
bad idea. Also, I'm not sure how a non-block-based table AM would use
TBMIterators (or even TIDBitmap) anyway.

As a side note, I've started naming all new structs in the bitmap
table scan code with the `BitmapTableScan` convention. It seems like
it might be a good time to rename the executor node from
BitmapHeapScanState to BitmapTableScanState. I didn't because I
wondered if I also needed to rename the file (nodeBitmapHeapscan.c ->
nodeBitmapTablescan.c) and update all other places using the
`BitmapHeapScan` convention.

Patches 0018 and 0019 make some changes to the TIDBitmap API to
support having multiple TBMIterateResults at the same time instead of
reusing the same one when iterating. With async execution we may have
more than one TBMIterateResult at a time.

There is one MTODO in the whole patch set -- in 0019 -- related to
resetting state in the TBMIterateResult. See that patch for the full
question.

And, finally, 0020 uses the read stream API and removes all the
bespoke prefetching code from bitmap heap scan.

Assuming we all get to a happy place with the code up until 0020, the
next step is to go back and investigate the performance regression
with bitmap heap scan and the read stream API first reported by Tomas
Vondra in [2]/messages/by-id/5d5954ed-6f43-4f1a-8e19-ece75b2b7362@enterprisedb.com.

I'd be very happy for code review on any of the patches, answers to my
questions above, or help investigating the regression Tomas found.

- Melanie

[1]: /messages/by-id/5a172d1e-d69c-409a-b1fa-6521214c81c2@iki.fi
[2]: /messages/by-id/5d5954ed-6f43-4f1a-8e19-ece75b2b7362@enterprisedb.com

Attachments:

v21-0001-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-patch; charset=US-ASCII; name=v21-0001-table_scan_bitmap_next_block-counts-lossy-and-ex.patchDownload
From 1b7f9e5c83ccfae0a3829f8fb86c7c88ea698af0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v21 01/20] table_scan_bitmap_next_block counts lossy and exact
 pages

Keep track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap in table AM-specific code. These
counters are used for EXPLAIN.

This is a step toward removing TBMIterateResults as a flow control
mechanism in BitmapHeapNext(), which is required for a more asynchronous
design. It also is more table AM agnostic.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6f8b1b79298..72ba9ed4dcf 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,7 +2120,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2248,6 +2249,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6b48a6d8350..de7a293de8e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,8 +212,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -233,14 +231,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8e583b45cd5..ad3339196af 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -806,6 +806,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, `exact_pages` is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -821,7 +824,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1959,17 +1963,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. `lossy_pages` is incremented if the block's
+ * representation in the bitmap is lossy; otherwise, `exact_pages` is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1980,7 +1988,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

v21-0003-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-patch; charset=US-ASCII; name=v21-0003-Make-table_scan_bitmap_next_block-async-friendly.patchDownload
From 54c5df1e6ba542184fa9143aeb82dd5111db4fa2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v21 03/20] Make table_scan_bitmap_next_block() async-friendly

table_scan_bitmap_next_block() previously returned false when
table_scan_bitmap_next_tuple() should not be called for the tuples on
the page. This could happen when there were no visible tuples on the
page or when, due to concurrent activity on the table, the block
returned by the iterator is past the end of the table (as recorded when
the scan started).

That forced the caller to be responsible for determining if additional
blocks should be fetched and for invoking table_scan_bitmap_next_block()
for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
beginning of the scan) and for table_scan_bitmap_next_tuple() to return
false if there are no visible tuples on the page.

This also allows us to move responsibility for advancing the iterator to
table AM specific code. This means handling invalid blocks is entirely
up to the table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  54 ++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  77 ++++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 203 insertions(+), 145 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b303dc49430..3110f97473f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,18 +2120,48 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+			return false;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2150,16 +2180,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2254,7 +2275,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e63f6f0429a..e8b4a754434 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,9 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -85,11 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -105,6 +96,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,8 +107,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
+			tbmiterator = tbm_begin_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -166,9 +159,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -207,46 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -267,45 +235,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -331,13 +310,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -351,14 +334,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -383,7 +373,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -461,6 +454,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -518,6 +512,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -579,12 +575,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -592,13 +584,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -629,28 +621,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -683,8 +671,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -692,9 +678,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..024dc08c420 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -36,6 +39,10 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
+	/* Iterators for Bitmap Table Scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9f11cf3729a..2f4e221870e 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "storage/read_stream.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
@@ -36,7 +37,6 @@ extern PGDLLIMPORT bool synchronize_seqscans;
 struct BulkInsertStateData;
 struct IndexInfo;
 struct SampleScanState;
-struct TBMIterateResult;
 struct VacuumParams;
 struct ValidateIndexState;
 
@@ -790,19 +790,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, `exact_pages` is incremented.
 	 *
@@ -821,7 +816,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -959,12 +954,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1024,6 +1023,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1034,6 +1048,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1955,19 +1984,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. `lossy_pages` is incremented if the block's
- * representation in the bitmap is lossy; otherwise, `exact_pages` is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set by the table AM to indicate whether or not the tuples
+ * from this block should be rechecked. Tuples from lossy pages will always
+ * need to be rechecked, but some non-lossy pages' tuples may also require
+ * recheck.
+ *
+ * `blockno` is only used in bitmap table scan code to validate that the
+ * prefetch block is staying ahead of the current block.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1980,9 +2016,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8bc421e7c05..0af7906a184 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1795,8 +1795,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1805,9 +1803,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1815,8 +1815,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1825,9 +1823,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v21-0004-Add-common-interface-for-TBMIterators.patchtext/x-patch; charset=US-ASCII; name=v21-0004-Add-common-interface-for-TBMIterators.patchDownload
From 9f31c6fc35414cfb1e52d8476e1f490c2b329c6d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:41:05 -0400
Subject: [PATCH v21 04/20] Add common interface for TBMIterators

Add and use TBMSerialIterator, which replaces the current TBMIterator
for serial use cases, and repurpose TBMIterator to be a unified
interface for both the serial and parallel TID Bitmap iterator
interfaces. This encapsulation simplifies call sites for callers
supporting both parallel and serial TID Bitmap access. TBMIterator is
not yet used in this commit.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/gin/ginget.c           |   8 +-
 src/backend/access/gin/ginscan.c          |   2 +-
 src/backend/access/heap/heapam_handler.c  |   2 +-
 src/backend/executor/nodeBitmapHeapscan.c |  20 ++---
 src/backend/nodes/tidbitmap.c             | 102 +++++++++++++++++-----
 src/include/access/gin_private.h          |   2 +-
 src/include/access/relscan.h              |   4 +-
 src/include/access/tableam.h              |   4 +-
 src/include/nodes/execnodes.h             |   2 +-
 src/include/nodes/tidbitmap.h             |  27 ++++--
 src/tools/pgindent/typedefs.list          |   1 +
 11 files changed, 125 insertions(+), 49 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..0d66381df1e 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,7 @@ restartScanEntry:
 			if (entry->matchBitmap)
 			{
 				if (entry->matchIterator)
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_serial_iterate(entry->matchIterator);
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -385,7 +385,7 @@ restartScanEntry:
 
 		if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
 		{
-			entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+			entry->matchIterator = tbm_begin_serial_iterate(entry->matchBitmap);
 			entry->isFinished = false;
 		}
 	}
@@ -832,12 +832,12 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				entry->matchResult = tbm_serial_iterate(entry->matchIterator);
 
 				if (entry->matchResult == NULL)
 				{
 					ItemPointerSetInvalid(&entry->curItem);
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_serial_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
 					entry->isFinished = true;
 					break;
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..46dde99514d 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -246,7 +246,7 @@ ginFreeScanKeys(GinScanOpaque so)
 		if (entry->list)
 			pfree(entry->list);
 		if (entry->matchIterator)
-			tbm_end_iterate(entry->matchIterator);
+			tbm_end_serial_iterate(entry->matchIterator);
 		if (entry->matchBitmap)
 			tbm_free(entry->matchBitmap);
 	}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3110f97473f..ff46ad8f330 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2143,7 +2143,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (scan->shared_tbmiterator)
 			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbmres = tbm_serial_iterate(scan->tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e8b4a754434..f6e066a0cb3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,7 +96,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
+		TBMSerialIterator *tbmiterator = NULL;
 		TBMSharedIterator *shared_tbmiterator = NULL;
 
 		if (!pstate)
@@ -107,12 +107,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_serial_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
+				node->prefetch_iterator = tbm_begin_serial_iterate(tbm);
 				node->prefetch_pages = 0;
 				node->prefetch_target = -1;
 			}
@@ -324,7 +324,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMSerialIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
@@ -334,7 +334,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = tbm_serial_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -437,19 +437,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMSerialIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_serial_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
+					tbm_end_serial_iterate(prefetch_iterator);
 					node->prefetch_iterator = NULL;
 					break;
 				}
@@ -576,7 +576,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 	/* release bitmaps and buffers if any */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_serial_iterate(node->prefetch_iterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -632,7 +632,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * release bitmaps and buffers if any
 	 */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_serial_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->shared_prefetch_iterator)
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..429cb8bd7c9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -170,12 +170,12 @@ struct TIDBitmap
 };
 
 /*
- * When iterating over a bitmap in sorted order, a TBMIterator is used to
- * track our progress.  There can be several iterators scanning the same
- * bitmap concurrently.  Note that the bitmap becomes read-only as soon as
- * any iterator is created.
+ * When iterating over a backend-local bitmap in sorted order, a
+ * TBMSerialIterator is used to track our progress.  There can be several
+ * iterators scanning the same bitmap concurrently.  Note that the bitmap
+ * becomes read-only as soon as any iterator is created.
  */
-struct TBMIterator
+struct TBMSerialIterator
 {
 	TIDBitmap  *tbm;			/* TIDBitmap we're iterating over */
 	int			spageptr;		/* next spages index */
@@ -213,8 +213,8 @@ typedef struct PTIterationArray
 } PTIterationArray;
 
 /*
- * same as TBMIterator, but it is used for joint iteration, therefore this
- * also holds a reference to the shared state.
+ * same as TBMSerialIterator, but it is used for joint iteration, therefore
+ * this also holds a reference to the shared state.
  */
 struct TBMSharedIterator
 {
@@ -673,31 +673,31 @@ tbm_is_empty(const TIDBitmap *tbm)
 }
 
 /*
- * tbm_begin_iterate - prepare to iterate through a TIDBitmap
+ * tbm_begin_serial_iterate - prepare to iterate through a TIDBitmap
  *
- * The TBMIterator struct is created in the caller's memory context.
- * For a clean shutdown of the iteration, call tbm_end_iterate; but it's
- * okay to just allow the memory context to be released, too.  It is caller's
- * responsibility not to touch the TBMIterator anymore once the TIDBitmap
+ * The TBMSerialIterator struct is created in the caller's memory context. For
+ * a clean shutdown of the iteration, call tbm_end_iterate; but it's okay to
+ * just allow the memory context to be released, too.  It is caller's
+ * responsibility not to touch the TBMSerialIterator anymore once the TIDBitmap
  * is freed.
  *
  * NB: after this is called, it is no longer allowed to modify the contents
  * of the bitmap.  However, you can call this multiple times to scan the
  * contents repeatedly, including parallel scans.
  */
-TBMIterator *
-tbm_begin_iterate(TIDBitmap *tbm)
+TBMSerialIterator *
+tbm_begin_serial_iterate(TIDBitmap *tbm)
 {
-	TBMIterator *iterator;
+	TBMSerialIterator *iterator;
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
 	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
+	 * Create the TBMSerialIterator struct, with enough trailing space to
+	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSerialIterator *) palloc(sizeof(TBMSerialIterator) +
+											MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
 	iterator->tbm = tbm;
 
 	/*
@@ -956,7 +956,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 }
 
 /*
- * tbm_iterate - scan through next page of a TIDBitmap
+ * tbm_serial_iterate - scan through next page of a TIDBitmap
  *
  * Returns a TBMIterateResult representing one page, or NULL if there are
  * no more pages to scan.  Pages are guaranteed to be delivered in numerical
@@ -968,7 +968,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  * testing, recheck is always set true when ntuples < 0.)
  */
 TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+tbm_serial_iterate(TBMSerialIterator *iterator)
 {
 	TIDBitmap  *tbm = iterator->tbm;
 	TBMIterateResult *output = &(iterator->output);
@@ -1143,7 +1143,7 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
  * bitmap to return to read/write status when there are no more iterators.)
  */
 void
-tbm_end_iterate(TBMIterator *iterator)
+tbm_end_serial_iterate(TBMSerialIterator *iterator)
 {
 	pfree(iterator);
 }
@@ -1556,3 +1556,61 @@ tbm_calculate_entries(double maxbytes)
 
 	return nbuckets;
 }
+
+/*
+ * Start iteration on a shared or non-shared bitmap iterator. Note that tbm
+ * will only be provided by serial BitmapHeapScan callers. dsa and dsp will
+ * only be provided by parallel BitmapHeapScan callers. For shared callers, one
+ * process must already have called tbm_prepare_shared_iterate() to create and
+ * set up the TBMSharedIteratorState. The TBMIterator is passed by reference to
+ * accommodate callers who would like to allocate it inside an existing struct.
+ */
+void
+tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+				  dsa_area *dsa, dsa_pointer dsp)
+{
+	Assert(iterator);
+
+	iterator->serial = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = false;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+		iterator->parallel = tbm_attach_shared_iterate(dsa, dsp);
+	else
+		iterator->serial = tbm_begin_serial_iterate(tbm);
+}
+
+/*
+ * Clean up shared or non-shared bitmap iterator.
+ */
+void
+tbm_end_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->serial)
+		tbm_end_serial_iterate(iterator->serial);
+	else if (iterator->parallel)
+		tbm_end_shared_iterate(iterator->parallel);
+
+	iterator->serial = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = true;
+}
+
+/*
+ * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
+ */
+TBMIterateResult *
+tbm_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+	Assert(!iterator->exhausted);
+
+	if (iterator->serial)
+		return tbm_serial_iterate(iterator->serial);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..cfac6ca3923 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
-	TBMIterator *matchIterator;
+	TBMSerialIterator *matchIterator;
 	TBMIterateResult *matchResult;
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 024dc08c420..74562a1a155 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,7 +24,7 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
+struct TBMSerialIterator;
 struct TBMSharedIterator;
 
 /*
@@ -40,7 +40,7 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Iterators for Bitmap Table Scans */
-	struct TBMIterator *tbmiterator;
+	struct TBMSerialIterator *tbmiterator;
 	struct TBMSharedIterator *shared_tbmiterator;
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2f4e221870e..6829f542621 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -1033,7 +1033,7 @@ table_endscan(TableScanDesc scan)
 
 		if (scan->tbmiterator)
 		{
-			tbm_end_iterate(scan->tbmiterator);
+			tbm_end_serial_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
 	}
@@ -1058,7 +1058,7 @@ table_rescan(TableScanDesc scan,
 
 		if (scan->tbmiterator)
 		{
-			tbm_end_iterate(scan->tbmiterator);
+			tbm_end_serial_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
 	}
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0af7906a184..d1ed606fb71 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1818,7 +1818,7 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
+	TBMSerialIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..7fc2c4a464c 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -32,8 +32,8 @@
  */
 typedef struct TIDBitmap TIDBitmap;
 
-/* Likewise, TBMIterator is private */
-typedef struct TBMIterator TBMIterator;
+/* Likewise, TBMSerialIterator is private */
+typedef struct TBMSerialIterator TBMSerialIterator;
 typedef struct TBMSharedIterator TBMSharedIterator;
 
 /* Result structure for tbm_iterate */
@@ -46,6 +46,17 @@ typedef struct TBMIterateResult
 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
 } TBMIterateResult;
 
+/*
+ * Callers with both serial and parallel implementations can use this unified
+ * API.
+ */
+typedef struct TBMIterator
+{
+	TBMSerialIterator *serial;
+	TBMSharedIterator *parallel;
+	bool		exhausted;
+} TBMIterator;
+
 /* function prototypes in nodes/tidbitmap.c */
 
 extern TIDBitmap *tbm_create(long maxbytes, dsa_area *dsa);
@@ -62,14 +73,20 @@ extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
-extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern TBMSerialIterator *tbm_begin_serial_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_serial_iterate(TBMSerialIterator *iterator);
 extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
-extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_serial_iterate(TBMSerialIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
 													dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+extern void tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+							  dsa_area *dsa, dsa_pointer dsp);
+extern void tbm_end_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+
+
 #endif							/* TIDBITMAP_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 61ad417cde6..910fbdd880c 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2795,6 +2795,7 @@ TAR_MEMBER
 TBMIterateResult
 TBMIteratingState
 TBMIterator
+TBMSerialIterator
 TBMSharedIterator
 TBMSharedIteratorState
 TBMStatus
-- 
2.34.1

v21-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-patch; charset=US-ASCII; name=v21-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchDownload
From 2d53228d2aa18ff9f0f60b4adb0752adade3213f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v21 02/20] Remove table_scan_bitmap_next_tuple parameter
 tbmres

In order to remove TBMIterateResults as a flow control mechanism in
BitmapHeapNext(), they can no longer be used as a means of communication
between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Remove the TBMIterateResult parameter from
table_scan_bitmap_next_tuple().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 72ba9ed4dcf..b303dc49430 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2259,7 +2259,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index de7a293de8e..e63f6f0429a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -281,7 +281,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ad3339196af..9f11cf3729a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,10 +797,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -831,15 +828,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2003,7 +1995,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2015,7 +2006,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.34.1

v21-0005-BitmapHeapScan-initialize-some-prefetch-state-el.patchtext/x-patch; charset=US-ASCII; name=v21-0005-BitmapHeapScan-initialize-some-prefetch-state-el.patchDownload
From 3f5829e150ec3dbbccee6e5ecc378db6025694c3 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:51:11 -0400
Subject: [PATCH v21 05/20] BitmapHeapScan initialize some prefetch state
 elsewhere

The prefetch_target and prefetch_pages members can be initialized in the
scan and rescan functions. This makes it more straightforward to use the
unified TBMIterator API for BitmapHeapScan.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index f6e066a0cb3..b885bfeabd3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -111,11 +111,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
-			{
 				node->prefetch_iterator = tbm_begin_serial_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
 #endif							/* USE_PREFETCH */
 		}
 		else
@@ -591,6 +587,9 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
 	node->pfblockno = InvalidBlockNumber;
+	/* Only used for serial BHS */
+	node->prefetch_pages = 0;
+	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -676,7 +675,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->lossy_pages = 0;
 	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
+	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
@@ -812,7 +811,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -839,6 +838,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
+	pstate->prefetch_pages = 0;
+	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-- 
2.34.1

v21-0006-BitmapHeapScan-uses-unified-iterator.patchtext/x-patch; charset=US-ASCII; name=v21-0006-BitmapHeapScan-uses-unified-iterator.patchDownload
From b41e1a026f7d76f773ec6fa25744502b7d445f50 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:39:04 -0400
Subject: [PATCH v21 06/20] BitmapHeapScan uses unified iterator

With the repurposing of TBMIterator as an interface for both parallel
and serial iteration through TIDBitmaps, BitmapHeapScan may now use it
since it has both parallel and serial iteration.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 132 ++++++++--------------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  34 +-----
 src/include/nodes/execnodes.h             |   4 +-
 5 files changed, 54 insertions(+), 128 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ff46ad8f330..c3788918777 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2140,10 +2140,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_serial_iterate(scan->tbmiterator);
+		tbmres = tbm_iterate(&scan->tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b885bfeabd3..90fa5585312 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -69,7 +69,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -80,7 +79,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -96,76 +94,49 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMSerialIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
-
 		if (!pstate)
 		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
-			if (!tbm || !IsA(tbm, TIDBitmap))
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
-			node->tbm = tbm;
-			tbmiterator = tbm_begin_serial_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-				node->prefetch_iterator = tbm_begin_serial_iterate(tbm);
-#endif							/* USE_PREFETCH */
 		}
-		else
+		else if (BitmapShouldInitializeSharedState(pstate))
 		{
 			/*
 			 * The leader will immediately come out of the function, but
 			 * others will be blocked until leader populates the TBM and wakes
 			 * them up.
 			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
-
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+				elog(ERROR, "unrecognized result from subplan");
 
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+				pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(node->tbm);
 			}
-#endif							/* USE_PREFETCH */
+#endif
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(pstate);
 		}
 
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+			tbm_begin_iterate(&node->prefetch_iterator, node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -194,8 +165,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
+						  pstate ?
+						  pstate->tbmiterator :
+						  InvalidDsaPointer);
+
 		node->initialized = true;
 
 		goto new_page;
@@ -275,7 +249,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!node->prefetch_iterator.exhausted &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -320,17 +294,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMSerialIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_serial_iterate(prefetch_iterator);
+			tbmpre = tbm_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -347,7 +321,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -368,9 +342,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -433,20 +407,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMSerialIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_serial_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_serial_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -474,9 +447,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (1)
 			{
@@ -499,12 +472,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -571,18 +543,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_serial_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -630,12 +597,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_serial_iterate(node->prefetch_iterator);
+	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -673,11 +637,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 74562a1a155..b4511677b1d 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/itup.h"
+#include "nodes/tidbitmap.h"
 #include "port/atomics.h"
 #include "storage/buf.h"
 #include "storage/spin.h"
@@ -24,9 +25,6 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMSerialIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,8 +38,7 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Iterators for Bitmap Table Scans */
-	struct TBMSerialIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	TBMIterator tbmiterator;
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 6829f542621..7034b79c2de 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -954,16 +954,12 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
 /*
@@ -1024,19 +1020,7 @@ static inline void
 table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_serial_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+		tbm_end_iterate(&scan->tbmiterator);
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
@@ -1049,19 +1033,7 @@ table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_serial_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+		tbm_end_iterate(&scan->tbmiterator);
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d1ed606fb71..1f262db776c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1803,7 +1803,6 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1818,12 +1817,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMSerialIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
-- 
2.34.1

v21-0007-BitmapHeapScan-Make-prefetch-sync-error-more-det.patchtext/x-patch; charset=US-ASCII; name=v21-0007-BitmapHeapScan-Make-prefetch-sync-error-more-det.patchDownload
From dae58dd92f24a0535129167989249c48e4d69b9f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Jun 2024 12:40:58 -0400
Subject: [PATCH v21 07/20] BitmapHeapScan: Make prefetch sync error more
 detailed

Add the prefetch and current block numbers to the error message emitted
when the prefetch iterator gets out of sync with the main iterator in
serial bitmap table scan.
---
 src/backend/executor/nodeBitmapHeapscan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 90fa5585312..5134ab86020 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -251,7 +251,7 @@ new_page:
 		if (node->pstate == NULL &&
 			!node->prefetch_iterator.exhausted &&
 			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
+			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
 
 		/* Adjust the prefetch target */
 		BitmapAdjustPrefetchTarget(node);
-- 
2.34.1

v21-0008-Push-current-scan-descriptor-into-specialized-sc.patchtext/x-patch; charset=US-ASCII; name=v21-0008-Push-current-scan-descriptor-into-specialized-sc.patchDownload
From 4f5f67b03c3e05a90809ba55f3061efe9e2fe42f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:41:49 -0400
Subject: [PATCH v21 08/20] Push current scan descriptor into specialized scan
 states

To allow Bitmap Table Scans to use a forthcoming bitmap table-specific
scan descriptor in table AM-agnostic code, move the current scan
descriptor out of the generic ScanState node.

This adds a bit of duplication, but a few of the scan types don't use
the current scan descriptor anyway. Additionally, for many scan types,
the scan descriptor is initialized later in execution than the other
members of the generic ScanState.
---
 src/backend/executor/nodeBitmapHeapscan.c  | 10 +++++-----
 src/backend/executor/nodeBitmapIndexscan.c |  1 -
 src/backend/executor/nodeIndexonlyscan.c   |  1 -
 src/backend/executor/nodeIndexscan.c       |  1 -
 src/backend/executor/nodeSamplescan.c      | 14 +++++++-------
 src/backend/executor/nodeSeqscan.c         | 14 +++++++-------
 src/backend/executor/nodeTidrangescan.c    |  8 ++++----
 src/backend/executor/nodeTidscan.c         | 18 +++++++++---------
 src/include/nodes/execnodes.h              | 10 ++++++++--
 9 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5134ab86020..281eaf114c1 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -78,7 +78,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -162,7 +162,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  NULL,
 									  need_tuples);
 
-			node->ss.ss_currentScanDesc = scan;
+			node->ss_currentScanDesc = scan;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -539,8 +539,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss_currentScanDesc)
+		table_rescan(node->ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	tbm_end_iterate(&node->prefetch_iterator);
@@ -580,7 +580,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * extract information from the node
 	 */
-	scanDesc = node->ss.ss_currentScanDesc;
+	scanDesc = node->ss_currentScanDesc;
 
 	/*
 	 * close down subplans
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index 6df8e17ec84..b4af2f17ed4 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -225,7 +225,6 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
 	 */
 
 	indexstate->ss.ss_currentRelation = NULL;
-	indexstate->ss.ss_currentScanDesc = NULL;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index b49194c0167..194c544c167 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -534,7 +534,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	indexstate->ss.ss_currentRelation = currentRelation;
-	indexstate->ss.ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * Build the scan tuple type using the indextlist generated by the
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 8000feff4c9..8260cb0954d 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -910,7 +910,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	indexstate->ss.ss_currentRelation = currentRelation;
-	indexstate->ss.ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 714b076e646..d15bf249d31 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -123,7 +123,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 							 eflags);
 
 	/* we won't set up the HeapScanDesc till later */
-	scanstate->ss.ss_currentScanDesc = NULL;
+	scanstate->ss_currentScanDesc = NULL;
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
@@ -187,8 +187,8 @@ ExecEndSampleScan(SampleScanState *node)
 	/*
 	 * close heap scan
 	 */
-	if (node->ss.ss_currentScanDesc)
-		table_endscan(node->ss.ss_currentScanDesc);
+	if (node->ss_currentScanDesc)
+		table_endscan(node->ss_currentScanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -289,9 +289,9 @@ tablesample_init(SampleScanState *scanstate)
 	allow_sync = (tsm->NextSampleBlock == NULL);
 
 	/* Now we can create or reset the HeapScanDesc */
-	if (scanstate->ss.ss_currentScanDesc == NULL)
+	if (scanstate->ss_currentScanDesc == NULL)
 	{
-		scanstate->ss.ss_currentScanDesc =
+		scanstate->ss_currentScanDesc =
 			table_beginscan_sampling(scanstate->ss.ss_currentRelation,
 									 scanstate->ss.ps.state->es_snapshot,
 									 0, NULL,
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
 	}
 	else
 	{
-		table_rescan_set_params(scanstate->ss.ss_currentScanDesc, NULL,
+		table_rescan_set_params(scanstate->ss_currentScanDesc, NULL,
 								scanstate->use_bulkread,
 								allow_sync,
 								scanstate->use_pagemode);
@@ -319,7 +319,7 @@ tablesample_init(SampleScanState *scanstate)
 static TupleTableSlot *
 tablesample_getnext(SampleScanState *scanstate)
 {
-	TableScanDesc scan = scanstate->ss.ss_currentScanDesc;
+	TableScanDesc scan = scanstate->ss_currentScanDesc;
 	TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
 
 	ExecClearTuple(slot);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 7cb12a11c2d..89f5e8c80da 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -57,7 +57,7 @@ SeqNext(SeqScanState *node)
 	/*
 	 * get information from the estate and scan state
 	 */
-	scandesc = node->ss.ss_currentScanDesc;
+	scandesc = node->ss_currentScanDesc;
 	estate = node->ss.ps.state;
 	direction = estate->es_direction;
 	slot = node->ss.ss_ScanTupleSlot;
@@ -71,7 +71,7 @@ SeqNext(SeqScanState *node)
 		scandesc = table_beginscan(node->ss.ss_currentRelation,
 								   estate->es_snapshot,
 								   0, NULL);
-		node->ss.ss_currentScanDesc = scandesc;
+		node->ss_currentScanDesc = scandesc;
 	}
 
 	/*
@@ -188,7 +188,7 @@ ExecEndSeqScan(SeqScanState *node)
 	/*
 	 * get information from node
 	 */
-	scanDesc = node->ss.ss_currentScanDesc;
+	scanDesc = node->ss_currentScanDesc;
 
 	/*
 	 * close heap scan
@@ -213,7 +213,7 @@ ExecReScanSeqScan(SeqScanState *node)
 {
 	TableScanDesc scan;
 
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 
 	if (scan != NULL)
 		table_rescan(scan,		/* scan desc */
@@ -264,7 +264,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 								  pscan,
 								  estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss.ss_currentScanDesc =
+	node->ss_currentScanDesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
 
@@ -280,7 +280,7 @@ ExecSeqScanReInitializeDSM(SeqScanState *node,
 {
 	ParallelTableScanDesc pscan;
 
-	pscan = node->ss.ss_currentScanDesc->rs_parallel;
+	pscan = node->ss_currentScanDesc->rs_parallel;
 	table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
 }
 
@@ -297,6 +297,6 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
 	ParallelTableScanDesc pscan;
 
 	pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
-	node->ss.ss_currentScanDesc =
+	node->ss_currentScanDesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index 9aa7683d7e3..bc523a5d773 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -227,7 +227,7 @@ TidRangeNext(TidRangeScanState *node)
 	/*
 	 * extract necessary information from TID scan node
 	 */
-	scandesc = node->ss.ss_currentScanDesc;
+	scandesc = node->ss_currentScanDesc;
 	estate = node->ss.ps.state;
 	slot = node->ss.ss_ScanTupleSlot;
 	direction = estate->es_direction;
@@ -244,7 +244,7 @@ TidRangeNext(TidRangeScanState *node)
 												estate->es_snapshot,
 												&node->trss_mintid,
 												&node->trss_maxtid);
-			node->ss.ss_currentScanDesc = scandesc;
+			node->ss_currentScanDesc = scandesc;
 		}
 		else
 		{
@@ -326,7 +326,7 @@ ExecReScanTidRangeScan(TidRangeScanState *node)
 void
 ExecEndTidRangeScan(TidRangeScanState *node)
 {
-	TableScanDesc scan = node->ss.ss_currentScanDesc;
+	TableScanDesc scan = node->ss_currentScanDesc;
 
 	if (scan != NULL)
 		table_endscan(scan);
@@ -375,7 +375,7 @@ ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidrangestate->ss.ss_currentRelation = currentRelation;
-	tidrangestate->ss.ss_currentScanDesc = NULL;	/* no table scan here */
+	tidrangestate->ss_currentScanDesc = NULL;	/* no table scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 864a9013b62..f08bc7daa89 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -145,11 +145,11 @@ TidListEval(TidScanState *tidstate)
 	 * the size of the table), so it makes sense to delay that until needed -
 	 * the node might never get executed.
 	 */
-	if (tidstate->ss.ss_currentScanDesc == NULL)
-		tidstate->ss.ss_currentScanDesc =
+	if (tidstate->ss_currentScanDesc == NULL)
+		tidstate->ss_currentScanDesc =
 			table_beginscan_tid(tidstate->ss.ss_currentRelation,
 								tidstate->ss.ps.state->es_snapshot);
-	scan = tidstate->ss.ss_currentScanDesc;
+	scan = tidstate->ss_currentScanDesc;
 
 	/*
 	 * We initialize the array with enough slots for the case that all quals
@@ -336,7 +336,7 @@ TidNext(TidScanState *node)
 	if (node->tss_TidList == NULL)
 		TidListEval(node);
 
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 	tidList = node->tss_TidList;
 	numTids = node->tss_NumTids;
 
@@ -453,8 +453,8 @@ ExecReScanTidScan(TidScanState *node)
 	node->tss_TidPtr = -1;
 
 	/* not really necessary, but seems good form */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss_currentScanDesc)
+		table_rescan(node->ss_currentScanDesc, NULL);
 
 	ExecScanReScan(&node->ss);
 }
@@ -469,8 +469,8 @@ ExecReScanTidScan(TidScanState *node)
 void
 ExecEndTidScan(TidScanState *node)
 {
-	if (node->ss.ss_currentScanDesc)
-		table_endscan(node->ss.ss_currentScanDesc);
+	if (node->ss_currentScanDesc)
+		table_endscan(node->ss_currentScanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -518,7 +518,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidstate->ss.ss_currentRelation = currentRelation;
-	tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
+	tidstate->ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 1f262db776c..62bc883bc28 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1555,7 +1555,6 @@ typedef struct BitmapOrState
  *		retrieved from the subplan.
  *
  *		currentRelation    relation being scanned (NULL if none)
- *		currentScanDesc    current scan descriptor for scan (NULL if none)
  *		ScanTupleSlot	   pointer to slot in tuple table holding scan tuple
  * ----------------
  */
@@ -1563,7 +1562,6 @@ typedef struct ScanState
 {
 	PlanState	ps;				/* its first field is NodeTag */
 	Relation	ss_currentRelation;
-	struct TableScanDescData *ss_currentScanDesc;
 	TupleTableSlot *ss_ScanTupleSlot;
 } ScanState;
 
@@ -1574,6 +1572,7 @@ typedef struct ScanState
 typedef struct SeqScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
 	Size		pscan_len;		/* size of parallel heap scan descriptor */
 } SeqScanState;
 
@@ -1584,6 +1583,7 @@ typedef struct SeqScanState
 typedef struct SampleScanState
 {
 	ScanState	ss;
+	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
 	List	   *args;			/* expr states for TABLESAMPLE params */
 	ExprState  *repeatable;		/* expr state for REPEATABLE expr */
 	/* use struct pointer to avoid including tsmapi.h here */
@@ -1793,6 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1812,6 +1813,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
@@ -1831,6 +1833,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1841,6 +1844,7 @@ typedef struct BitmapHeapScanState
 typedef struct TidScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	List	   *tss_tidexprs;
 	bool		tss_isCurrentOf;
 	int			tss_NumTids;
@@ -1851,6 +1855,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
@@ -1860,6 +1865,7 @@ typedef struct TidScanState
 typedef struct TidRangeScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	List	   *trss_tidexprs;
 	ItemPointerData trss_mintid;
 	ItemPointerData trss_maxtid;
-- 
2.34.1

v21-0012-Update-variable-names-in-bitmap-scan-descriptors.patchtext/x-patch; charset=US-ASCII; name=v21-0012-Update-variable-names-in-bitmap-scan-descriptors.patchDownload
From aca32df57af1b91d2b5569a434c342d472ceb3ef Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 09:59:23 -0400
Subject: [PATCH v21 12/20] Update variable names in bitmap scan descriptors

The previous commit which added BitmapTableScanDesc and
BitmapHeapScanDesc used the existing member names from TableScanDescData
and HeapScanDescData for diff clarity. This commit renames the members
-- in many cases by removing the rs_ prefix which is not relevant or
needed here.
---
 src/backend/access/heap/heapam.c          | 64 ++++++++++-----------
 src/backend/access/heap/heapam_handler.c  | 70 +++++++++++------------
 src/backend/executor/nodeBitmapHeapscan.c | 14 ++---
 src/include/access/heapam.h               | 22 +++----
 src/include/access/relscan.h              |  8 +--
 src/include/access/tableam.h              | 14 ++---
 6 files changed, 96 insertions(+), 96 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 0d8239d2f15..88da737d149 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1244,27 +1244,27 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	RelationIncrementReferenceCount(relation);
 	scan = (BitmapHeapScanDesc *) palloc(sizeof(BitmapHeapScanDesc));
 
-	scan->rs_base.rs_rd = relation;
-	scan->rs_base.rs_snapshot = snapshot;
-	scan->rs_base.rs_flags = flags;
+	scan->base.rel = relation;
+	scan->base.snapshot = snapshot;
+	scan->base.flags = flags;
 
 	Assert(snapshot && IsMVCCSnapshot(snapshot));
 
 	/* we only need to set this up once */
-	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
+	scan->ctup.t_tableOid = RelationGetRelid(relation);
 
-	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+	scan->nblocks = RelationGetNumberOfBlocks(scan->base.rel);
 
-	scan->rs_ctup.t_data = NULL;
-	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
-	scan->rs_cbuf = InvalidBuffer;
-	scan->rs_cblock = InvalidBlockNumber;
+	scan->ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->ctup.t_self);
+	scan->cbuf = InvalidBuffer;
+	scan->cblock = InvalidBlockNumber;
 
-	scan->rs_cindex = 0;
-	scan->rs_ntuples = 0;
+	scan->vis_idx = 0;
+	scan->vis_ntuples = 0;
 
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
+	scan->vmbuffer = InvalidBuffer;
+	scan->empty_tuples_pending = 0;
 
 	return (BitmapTableScanDesc *) scan;
 }
@@ -1274,31 +1274,31 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
-	if (BufferIsValid(scan->rs_cbuf))
+	if (BufferIsValid(scan->cbuf))
 	{
-		ReleaseBuffer(scan->rs_cbuf);
-		scan->rs_cbuf = InvalidBuffer;
+		ReleaseBuffer(scan->cbuf);
+		scan->cbuf = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->rs_vmbuffer))
+	if (BufferIsValid(scan->vmbuffer))
 	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
+		ReleaseBuffer(scan->vmbuffer);
+		scan->vmbuffer = InvalidBuffer;
 	}
 
-	scan->rs_cblock = InvalidBlockNumber;
+	scan->cblock = InvalidBlockNumber;
 
 	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
+	 * Reset empty_tuples_pending, a field only used by bitmap heap scan, to
+	 * avoid incorrectly emitting NULL-filled tuples from a previous scan on
+	 * rescan.
 	 */
-	scan->rs_empty_tuples_pending = 0;
+	scan->empty_tuples_pending = 0;
 
-	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+	scan->nblocks = RelationGetNumberOfBlocks(scan->base.rel);
 
-	scan->rs_ctup.t_data = NULL;
-	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+	scan->ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->ctup.t_self);
 }
 
 void
@@ -1306,16 +1306,16 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
-	if (BufferIsValid(scan->rs_cbuf))
-		ReleaseBuffer(scan->rs_cbuf);
+	if (BufferIsValid(scan->cbuf))
+		ReleaseBuffer(scan->cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
 
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
-	RelationDecrementReferenceCount(scan->rs_base.rs_rd);
+	RelationDecrementReferenceCount(scan->base.rel);
 
 	pfree(scan);
 }
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 82f216952b1..4057d0cf22b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2130,8 +2130,8 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	int			ntup;
 	TBMIterateResult *tbmres;
 
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
+	hscan->vis_idx = 0;
+	hscan->vis_ntuples = 0;
 
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
@@ -2140,7 +2140,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->tbmiterator);
+		tbmres = tbm_iterate(&scan->iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2153,7 +2153,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->nblocks);
 
 	/* Got a valid block */
 	*blockno = tbmres->blockno;
@@ -2164,15 +2164,15 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+	if (!(scan->flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(scan->rel, tbmres->blockno, &hscan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(hscan->empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2182,19 +2182,19 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
+	hscan->cbuf = ReleaseAndReadBuffer(hscan->cbuf,
+									   scan->rel,
+									   block);
+	hscan->cblock = block;
+	buffer = hscan->cbuf;
+	snapshot = scan->snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
+	heap_page_prune_opt(scan->rel, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2222,9 +2222,9 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, scan->rel, buffer, snapshot,
 									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+				hscan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
 	}
 	else
@@ -2248,16 +2248,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
+			loctup.t_tableOid = scan->rel->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+				hscan->vis_tuples[ntup++] = offnum;
+				PredicateLockTID(scan->rel, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+			HeapCheckForSerializableConflictOut(valid, scan->rel, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2265,7 +2265,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
+	hscan->vis_ntuples = ntup;
 
 	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
@@ -2291,43 +2291,43 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (hscan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		hscan->empty_tuples_pending--;
 		return true;
 	}
 
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
+	if (hscan->vis_idx < 0 || hscan->vis_idx >= hscan->vis_ntuples)
 		return false;
 
-	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
-	page = BufferGetPage(hscan->rs_cbuf);
+	targoffset = hscan->vis_tuples[hscan->vis_idx];
+	page = BufferGetPage(hscan->cbuf);
 	lp = PageGetItemId(page, targoffset);
 	Assert(ItemIdIsNormal(lp));
 
-	hscan->rs_ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-	hscan->rs_ctup.t_len = ItemIdGetLength(lp);
-	hscan->rs_ctup.t_tableOid = scan->rs_rd->rd_id;
-	ItemPointerSet(&hscan->rs_ctup.t_self, hscan->rs_cblock, targoffset);
+	hscan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+	hscan->ctup.t_len = ItemIdGetLength(lp);
+	hscan->ctup.t_tableOid = scan->rel->rd_id;
+	ItemPointerSet(&hscan->ctup.t_self, hscan->cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rs_rd);
+	pgstat_count_heap_fetch(scan->rel);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
 	 * acquires a pin on the buffer.
 	 */
-	ExecStoreBufferHeapTuple(&hscan->rs_ctup,
+	ExecStoreBufferHeapTuple(&hscan->ctup,
 							 slot,
-							 hscan->rs_cbuf);
+							 hscan->cbuf);
 
-	hscan->rs_cindex++;
+	hscan->vis_idx++;
 
 	return true;
 }
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 84c720bdc76..5f625c1f3e6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -166,11 +166,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		else
 		{
 			/* rescan to release any page pin */
-			tbm_end_iterate(&scan->tbmiterator);
+			tbm_end_iterate(&scan->iterator);
 			table_rescan_bm(scan, dsa, node->prefetch_maximum);
 		}
 
-		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
+		tbm_begin_iterate(&scan->iterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
 						  InvalidDsaPointer);
@@ -436,14 +436,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -488,14 +488,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				node->pfblockno = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -594,7 +594,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	if (scanDesc)
 	{
-		tbm_end_iterate(&scanDesc->tbmiterator);
+		tbm_end_iterate(&scanDesc->iterator);
 		table_endscan_bm(scanDesc);
 	}
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3cac199dd36..1d5583cac22 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -100,19 +100,19 @@ typedef struct HeapScanDescData *HeapScanDesc;
 
 typedef struct BitmapHeapScanDesc
 {
-	BitmapTableScanDesc rs_base;
+	BitmapTableScanDesc base;
 
-	BlockNumber rs_nblocks;		/* total number of blocks in rel */
+	BlockNumber nblocks;		/* total number of blocks in rel */
 
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+	int			vis_idx;		/* current tuple's index in vistuples */
+	int			vis_ntuples;	/* number of visible tuples on page */
+	OffsetNumber vis_tuples[MaxHeapTuplesPerPage];	/* their offsets */
 
-	Buffer		rs_cbuf;		/* current buffer in scan, if any */
-	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
-	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
+	Buffer		cbuf;			/* current buffer in scan, if any */
+	/* NB: if cbuf is not InvalidBuffer, we hold a pin on that buffer */
+	HeapTupleData ctup;			/* current tuple in scan, if any */
 
-	BlockNumber rs_cblock;		/* current block # in scan, if any */
+	BlockNumber cblock;			/* current block # in scan, if any */
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -121,8 +121,8 @@ typedef struct BitmapHeapScanDesc
 	 * block reported by the bitmap to determine how many NULL-filled tuples
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
-	Buffer		rs_vmbuffer;
-	int			rs_empty_tuples_pending;
+	Buffer		vmbuffer;
+	int			empty_tuples_pending;
 } BitmapHeapScanDesc;
 
 /*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 036ef29e7d5..086fce35a8b 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -54,19 +54,19 @@ typedef struct TableScanDescData *TableScanDesc;
 
 typedef struct BitmapTableScanDesc
 {
-	Relation	rs_rd;			/* heap relation descriptor */
-	struct SnapshotData *rs_snapshot;	/* snapshot to see */
+	Relation	rel;			/* heap relation descriptor */
+	struct SnapshotData *snapshot;	/* snapshot to see */
 
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
-	TBMIterator tbmiterator;
+	TBMIterator iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
 	 */
-	uint32		rs_flags;
+	uint32		flags;
 } BitmapTableScanDesc;
 
 /*
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5110fa2b443..69ccdaee8c4 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -988,7 +988,7 @@ table_rescan_bm(BitmapTableScanDesc *scan,
 				dsa_area *dsa,
 				int prefetch_maximum)
 {
-	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+	scan->rel->rd_tableam->scan_rescan_bm(scan);
 }
 
 /*
@@ -997,7 +997,7 @@ table_rescan_bm(BitmapTableScanDesc *scan,
 static inline void
 table_endscan_bm(BitmapTableScanDesc *scan)
 {
-	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+	scan->rel->rd_tableam->scan_end_bm(scan);
 }
 
 
@@ -2020,9 +2020,9 @@ table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
-														   lossy_pages, exact_pages);
+	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
+														 blockno, recheck,
+														 lossy_pages, exact_pages);
 }
 
 /*
@@ -2045,8 +2045,8 @@ table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+	return scan->rel->rd_tableam->scan_bitmap_next_tuple(scan,
+														 slot);
 }
 
 /*
-- 
2.34.1

v21-0009-Remove-ss_current-prefix-from-ss_currentScanDesc.patchtext/x-patch; charset=US-ASCII; name=v21-0009-Remove-ss_current-prefix-from-ss_currentScanDesc.patchDownload
From 9406d6d8957e2cc555432a987556789ae89f6863 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:44:50 -0400
Subject: [PATCH v21 09/20] Remove ss_current prefix from ss_currentScanDesc in
 nodes

A previous commit pushed down the current scan descriptor from the
generic ScanState into the specialized scan states. The naming
convention was left as is to make the diff easier to understand. Rename
it, as the ss_ prefix is no longer correct once this member is in the
other node structs.
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/backend/executor/nodeSamplescan.c     | 14 +++++++-------
 src/backend/executor/nodeSeqscan.c        | 14 +++++++-------
 src/backend/executor/nodeTidrangescan.c   |  8 ++++----
 src/backend/executor/nodeTidscan.c        | 18 +++++++++---------
 src/include/nodes/execnodes.h             | 16 ++++++++--------
 6 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 281eaf114c1..2e9cd4eda7f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -78,7 +78,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -162,7 +162,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  NULL,
 									  need_tuples);
 
-			node->ss_currentScanDesc = scan;
+			node->scandesc = scan;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -539,8 +539,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	if (node->ss_currentScanDesc)
-		table_rescan(node->ss_currentScanDesc, NULL);
+	if (node->scandesc)
+		table_rescan(node->scandesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	tbm_end_iterate(&node->prefetch_iterator);
@@ -580,7 +580,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * extract information from the node
 	 */
-	scanDesc = node->ss_currentScanDesc;
+	scanDesc = node->scandesc;
 
 	/*
 	 * close down subplans
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index d15bf249d31..581bd3ed3b1 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -123,7 +123,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 							 eflags);
 
 	/* we won't set up the HeapScanDesc till later */
-	scanstate->ss_currentScanDesc = NULL;
+	scanstate->scandesc = NULL;
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
@@ -187,8 +187,8 @@ ExecEndSampleScan(SampleScanState *node)
 	/*
 	 * close heap scan
 	 */
-	if (node->ss_currentScanDesc)
-		table_endscan(node->ss_currentScanDesc);
+	if (node->scandesc)
+		table_endscan(node->scandesc);
 }
 
 /* ----------------------------------------------------------------
@@ -289,9 +289,9 @@ tablesample_init(SampleScanState *scanstate)
 	allow_sync = (tsm->NextSampleBlock == NULL);
 
 	/* Now we can create or reset the HeapScanDesc */
-	if (scanstate->ss_currentScanDesc == NULL)
+	if (scanstate->scandesc == NULL)
 	{
-		scanstate->ss_currentScanDesc =
+		scanstate->scandesc =
 			table_beginscan_sampling(scanstate->ss.ss_currentRelation,
 									 scanstate->ss.ps.state->es_snapshot,
 									 0, NULL,
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
 	}
 	else
 	{
-		table_rescan_set_params(scanstate->ss_currentScanDesc, NULL,
+		table_rescan_set_params(scanstate->scandesc, NULL,
 								scanstate->use_bulkread,
 								allow_sync,
 								scanstate->use_pagemode);
@@ -319,7 +319,7 @@ tablesample_init(SampleScanState *scanstate)
 static TupleTableSlot *
 tablesample_getnext(SampleScanState *scanstate)
 {
-	TableScanDesc scan = scanstate->ss_currentScanDesc;
+	TableScanDesc scan = scanstate->scandesc;
 	TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
 
 	ExecClearTuple(slot);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 89f5e8c80da..5aaad645950 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -57,7 +57,7 @@ SeqNext(SeqScanState *node)
 	/*
 	 * get information from the estate and scan state
 	 */
-	scandesc = node->ss_currentScanDesc;
+	scandesc = node->scandesc;
 	estate = node->ss.ps.state;
 	direction = estate->es_direction;
 	slot = node->ss.ss_ScanTupleSlot;
@@ -71,7 +71,7 @@ SeqNext(SeqScanState *node)
 		scandesc = table_beginscan(node->ss.ss_currentRelation,
 								   estate->es_snapshot,
 								   0, NULL);
-		node->ss_currentScanDesc = scandesc;
+		node->scandesc = scandesc;
 	}
 
 	/*
@@ -188,7 +188,7 @@ ExecEndSeqScan(SeqScanState *node)
 	/*
 	 * get information from node
 	 */
-	scanDesc = node->ss_currentScanDesc;
+	scanDesc = node->scandesc;
 
 	/*
 	 * close heap scan
@@ -213,7 +213,7 @@ ExecReScanSeqScan(SeqScanState *node)
 {
 	TableScanDesc scan;
 
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 
 	if (scan != NULL)
 		table_rescan(scan,		/* scan desc */
@@ -264,7 +264,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 								  pscan,
 								  estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss_currentScanDesc =
+	node->scandesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
 
@@ -280,7 +280,7 @@ ExecSeqScanReInitializeDSM(SeqScanState *node,
 {
 	ParallelTableScanDesc pscan;
 
-	pscan = node->ss_currentScanDesc->rs_parallel;
+	pscan = node->scandesc->rs_parallel;
 	table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
 }
 
@@ -297,6 +297,6 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
 	ParallelTableScanDesc pscan;
 
 	pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
-	node->ss_currentScanDesc =
+	node->scandesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index bc523a5d773..3a2ba169e9d 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -227,7 +227,7 @@ TidRangeNext(TidRangeScanState *node)
 	/*
 	 * extract necessary information from TID scan node
 	 */
-	scandesc = node->ss_currentScanDesc;
+	scandesc = node->scandesc;
 	estate = node->ss.ps.state;
 	slot = node->ss.ss_ScanTupleSlot;
 	direction = estate->es_direction;
@@ -244,7 +244,7 @@ TidRangeNext(TidRangeScanState *node)
 												estate->es_snapshot,
 												&node->trss_mintid,
 												&node->trss_maxtid);
-			node->ss_currentScanDesc = scandesc;
+			node->scandesc = scandesc;
 		}
 		else
 		{
@@ -326,7 +326,7 @@ ExecReScanTidRangeScan(TidRangeScanState *node)
 void
 ExecEndTidRangeScan(TidRangeScanState *node)
 {
-	TableScanDesc scan = node->ss_currentScanDesc;
+	TableScanDesc scan = node->scandesc;
 
 	if (scan != NULL)
 		table_endscan(scan);
@@ -375,7 +375,7 @@ ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidrangestate->ss.ss_currentRelation = currentRelation;
-	tidrangestate->ss_currentScanDesc = NULL;	/* no table scan here */
+	tidrangestate->scandesc = NULL; /* no table scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index f08bc7daa89..becf0274678 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -145,11 +145,11 @@ TidListEval(TidScanState *tidstate)
 	 * the size of the table), so it makes sense to delay that until needed -
 	 * the node might never get executed.
 	 */
-	if (tidstate->ss_currentScanDesc == NULL)
-		tidstate->ss_currentScanDesc =
+	if (tidstate->scandesc == NULL)
+		tidstate->scandesc =
 			table_beginscan_tid(tidstate->ss.ss_currentRelation,
 								tidstate->ss.ps.state->es_snapshot);
-	scan = tidstate->ss_currentScanDesc;
+	scan = tidstate->scandesc;
 
 	/*
 	 * We initialize the array with enough slots for the case that all quals
@@ -336,7 +336,7 @@ TidNext(TidScanState *node)
 	if (node->tss_TidList == NULL)
 		TidListEval(node);
 
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 	tidList = node->tss_TidList;
 	numTids = node->tss_NumTids;
 
@@ -453,8 +453,8 @@ ExecReScanTidScan(TidScanState *node)
 	node->tss_TidPtr = -1;
 
 	/* not really necessary, but seems good form */
-	if (node->ss_currentScanDesc)
-		table_rescan(node->ss_currentScanDesc, NULL);
+	if (node->scandesc)
+		table_rescan(node->scandesc, NULL);
 
 	ExecScanReScan(&node->ss);
 }
@@ -469,8 +469,8 @@ ExecReScanTidScan(TidScanState *node)
 void
 ExecEndTidScan(TidScanState *node)
 {
-	if (node->ss_currentScanDesc)
-		table_endscan(node->ss_currentScanDesc);
+	if (node->scandesc)
+		table_endscan(node->scandesc);
 }
 
 /* ----------------------------------------------------------------
@@ -518,7 +518,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidstate->ss.ss_currentRelation = currentRelation;
-	tidstate->ss_currentScanDesc = NULL;	/* no heap scan here */
+	tidstate->scandesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 62bc883bc28..ebba73d9b8b 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1572,7 +1572,7 @@ typedef struct ScanState
 typedef struct SeqScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
+	struct TableScanDescData *scandesc; /* current scan descriptor */
 	Size		pscan_len;		/* size of parallel heap scan descriptor */
 } SeqScanState;
 
@@ -1583,7 +1583,7 @@ typedef struct SeqScanState
 typedef struct SampleScanState
 {
 	ScanState	ss;
-	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
+	struct TableScanDescData *scandesc; /* current scan descriptor */
 	List	   *args;			/* expr states for TABLESAMPLE params */
 	ExprState  *repeatable;		/* expr state for REPEATABLE expr */
 	/* use struct pointer to avoid including tsmapi.h here */
@@ -1793,7 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *      scandesc		   current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1813,7 +1813,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
@@ -1833,7 +1833,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *      scandesc	   current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1844,7 +1844,7 @@ typedef struct BitmapHeapScanState
 typedef struct TidScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	List	   *tss_tidexprs;
 	bool		tss_isCurrentOf;
 	int			tss_NumTids;
@@ -1855,7 +1855,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *      scandesc			current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
@@ -1865,7 +1865,7 @@ typedef struct TidScanState
 typedef struct TidRangeScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	List	   *trss_tidexprs;
 	ItemPointerData trss_mintid;
 	ItemPointerData trss_maxtid;
-- 
2.34.1

v21-0010-Add-scan_in_progress-to-BitmapHeapScanState.patchtext/x-patch; charset=US-ASCII; name=v21-0010-Add-scan_in_progress-to-BitmapHeapScanState.patchDownload
From 384ce8ab456879fd2b585db5af75393a7595899c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 13 Jun 2024 13:38:46 -0400
Subject: [PATCH v21 10/20] Add scan_in_progress to BitmapHeapScanState

Instead of checking that the scan descriptor hasn't been allocated yet,
use a dedicated variable, scan_in_progress. This feels cleaner and also
allows us to more easily extract the per scan setup into a separate
function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 4 +++-
 src/include/nodes/execnodes.h             | 2 ++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2e9cd4eda7f..3c9e7f00b56 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -141,7 +141,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
 		 */
-		if (!scan)
+		if (!node->scan_in_progress)
 		{
 			bool		need_tuples = false;
 
@@ -163,6 +163,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  need_tuples);
 
 			node->scandesc = scan;
+			node->scan_in_progress = true;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -640,6 +641,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
+	scanstate->scan_in_progress = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index ebba73d9b8b..5a9a187771a 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1804,6 +1804,7 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
+ *		scan_in_progress   is this a rescan
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1823,6 +1824,7 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
+	bool		scan_in_progress;
 	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-- 
2.34.1

v21-0011-Make-new-bitmap-table-scan-and-bitmap-heap-scan-.patchtext/x-patch; charset=US-ASCII; name=v21-0011-Make-new-bitmap-table-scan-and-bitmap-heap-scan-.patchDownload
From 7272b43ec90a2879952befd41b776ff0949c5da0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:51:05 -0400
Subject: [PATCH v21 11/20] Make new bitmap table scan and bitmap heap scan
 descriptors

The number of fields from the TableScanDescData required for bitmap
table scans is few. Create a new BitmapTableScanDesc with only those
members needed for bitmap table scans and remove the bitmap table
scan-only fields from the generic TableScanDescData.

Also add a BitmapHeapScanDesc structure for the heap AM implementation
of bitmap table scans. Add table AM callbacks for starting, restarting,
and ending these scans.

While reducing the size of the scan descriptor (and the amount of code
executed in the table_begin/end/rescan() functions) was a benefit,
creating a new BitmapTableScanDesc and associated table AM functions to
begin/end/rescan was actually motivated by work to remove all
heap-specific code from the generic bitmap table scan code path. Pushing
this code down into the heap AM layer would have required adding quite a
few bitmap-specific parameters to heap_begin/end/rescan()
---
 src/backend/access/heap/heapam.c          | 110 ++++++++++++++++++----
 src/backend/access/heap/heapam_handler.c  |  12 ++-
 src/backend/executor/nodeBitmapHeapscan.c |  29 +++---
 src/include/access/heapam.h               |  39 ++++++--
 src/include/access/relscan.h              |  20 +++-
 src/include/access/tableam.h              |  83 +++++++++++-----
 src/include/nodes/execnodes.h             |   2 +-
 src/tools/pgindent/typedefs.list          |   2 +
 8 files changed, 225 insertions(+), 72 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 82bb9cb33b6..0d8239d2f15 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1061,8 +1061,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1178,19 +1176,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
-	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
-	 */
-	scan->rs_empty_tuples_pending = 0;
-
 	/*
 	 * The read stream is reset on rescan. This must be done before
 	 * initscan(), as some state referred to by read_stream_reset() is reset
@@ -1218,9 +1203,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
@@ -1247,6 +1229,98 @@ heap_endscan(TableScanDesc sscan)
 	pfree(scan);
 }
 
+BitmapTableScanDesc *
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+{
+	BitmapHeapScanDesc *scan;
+
+	/*
+	 * increment relation ref count while scanning relation
+	 *
+	 * This is just to make really sure the relcache entry won't go away while
+	 * the scan has a pointer to it.  Caller should be holding the rel open
+	 * anyway, so this is redundant in all normal scenarios...
+	 */
+	RelationIncrementReferenceCount(relation);
+	scan = (BitmapHeapScanDesc *) palloc(sizeof(BitmapHeapScanDesc));
+
+	scan->rs_base.rs_rd = relation;
+	scan->rs_base.rs_snapshot = snapshot;
+	scan->rs_base.rs_flags = flags;
+
+	Assert(snapshot && IsMVCCSnapshot(snapshot));
+
+	/* we only need to set this up once */
+	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
+
+	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+
+	scan->rs_ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+	scan->rs_cbuf = InvalidBuffer;
+	scan->rs_cblock = InvalidBlockNumber;
+
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
+
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
+
+	return (BitmapTableScanDesc *) scan;
+}
+
+void
+heap_rescan_bm(BitmapTableScanDesc *sscan)
+{
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+
+	if (BufferIsValid(scan->rs_cbuf))
+	{
+		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
+
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
+	scan->rs_cblock = InvalidBlockNumber;
+
+	/*
+	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
+	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
+	 * on rescan.
+	 */
+	scan->rs_empty_tuples_pending = 0;
+
+	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+
+	scan->rs_ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+}
+
+void
+heap_endscan_bm(BitmapTableScanDesc *sscan)
+{
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+
+	if (BufferIsValid(scan->rs_cbuf))
+		ReleaseBuffer(scan->rs_cbuf);
+
+	if (BufferIsValid(scan->rs_vmbuffer))
+		ReleaseBuffer(scan->rs_vmbuffer);
+
+	/*
+	 * decrement relation reference count and free scan descriptor storage
+	 */
+	RelationDecrementReferenceCount(scan->rs_base.rs_rd);
+
+	pfree(scan);
+}
+
+
 HeapTuple
 heap_getnext(TableScanDesc sscan, ScanDirection direction)
 {
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c3788918777..82f216952b1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,11 +2119,11 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2283,10 +2283,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
@@ -2629,6 +2629,10 @@ static const TableAmRoutine heapam_methods = {
 	.scan_rescan = heap_rescan,
 	.scan_getnextslot = heap_getnextslot,
 
+	.scan_begin_bm = heap_beginscan_bm,
+	.scan_rescan_bm = heap_rescan_bm,
+	.scan_end_bm = heap_endscan_bm,
+
 	.scan_set_tidrange = heap_set_tidrange,
 	.scan_getnextslot_tidrange = heap_getnextslot_tidrange,
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3c9e7f00b56..84c720bdc76 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -54,7 +54,7 @@ static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *ps
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
+								  BitmapTableScanDesc *scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -68,7 +68,7 @@ static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
-	TableScanDesc scan;
+	BitmapTableScanDesc *scan;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -158,13 +158,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
-									  need_tuples);
-
+									  dsa,
+									  need_tuples, node->prefetch_maximum);
 			node->scandesc = scan;
 			node->scan_in_progress = true;
 		}
+		else
+		{
+			/* rescan to release any page pin */
+			tbm_end_iterate(&scan->tbmiterator);
+			table_rescan_bm(scan, dsa, node->prefetch_maximum);
+		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
 						  pstate ?
@@ -401,7 +405,7 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
 static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -539,10 +543,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* rescan to release any page pin */
-	if (node->scandesc)
-		table_rescan(node->scandesc, NULL);
-
 	/* release bitmaps and buffers if any */
 	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
@@ -576,7 +576,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 void
 ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 {
-	TableScanDesc scanDesc;
+	BitmapTableScanDesc *scanDesc;
 
 	/*
 	 * extract information from the node
@@ -593,7 +593,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * close heap scan
 	 */
 	if (scanDesc)
-		table_endscan(scanDesc);
+	{
+		tbm_end_iterate(&scanDesc->tbmiterator);
+		table_endscan_bm(scanDesc);
+	}
 
 	/*
 	 * release bitmaps and buffers if any
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 9e9aec88a62..3cac199dd36 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -91,22 +91,39 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDesc
+{
+	BitmapTableScanDesc rs_base;
+
+	BlockNumber rs_nblocks;		/* total number of blocks in rel */
+
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+
+	Buffer		rs_cbuf;		/* current buffer in scan, if any */
+	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
+	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
+
+	BlockNumber rs_cblock;		/* current block # in scan, if any */
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+} BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
@@ -296,6 +313,12 @@ extern void heap_prepare_pagescan(TableScanDesc sscan);
 extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 						bool allow_strat, bool allow_sync, bool allow_pagemode);
 extern void heap_endscan(TableScanDesc sscan);
+
+extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
+											  Snapshot snapshot, uint32 flags);
+extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
+void		heap_endscan_bm(BitmapTableScanDesc *sscan);
+
 extern HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction);
 extern bool heap_getnextslot(TableScanDesc sscan,
 							 ScanDirection direction, struct TupleTableSlot *slot);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b4511677b1d..036ef29e7d5 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -37,9 +37,6 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
-	/* Iterators for Bitmap Table Scans */
-	TBMIterator tbmiterator;
-
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
@@ -55,6 +52,23 @@ typedef struct TableScanDescData
 } TableScanDescData;
 typedef struct TableScanDescData *TableScanDesc;
 
+typedef struct BitmapTableScanDesc
+{
+	Relation	rs_rd;			/* heap relation descriptor */
+	struct SnapshotData *rs_snapshot;	/* snapshot to see */
+
+	/*
+	 * Members common to Parallel and Serial BitmapTableScans
+	 */
+	TBMIterator tbmiterator;
+
+	/*
+	 * Information about type and behaviour of the scan, a bitmask of members
+	 * of the ScanOptions enum (see tableam.h).
+	 */
+	uint32		rs_flags;
+} BitmapTableScanDesc;
+
 /*
  * Shared state for parallel table scan.
  *
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 7034b79c2de..5110fa2b443 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -345,6 +345,24 @@ typedef struct TableAmRoutine
 								bool set_params, bool allow_strat,
 								bool allow_sync, bool allow_pagemode);
 
+	/*
+	 * Functions to begin, restart, and end a scan of the underlying table of
+	 * a bitmap table scan.
+	 *
+	 * `rel`, `flags`, and `snapshot` serve the same purposes as in the
+	 * standard relation scan_[begin|rescan|end] functions documented above.
+	 */
+	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
+										   Snapshot snapshot,
+										   uint32 flags);
+
+	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
+
+	/*
+	 * Release resources and deallocate scan.
+	 */
+	void		(*scan_end_bm) (BitmapTableScanDesc *scan);
+
 	/*
 	 * Return next tuple from `scan`, store in slot.
 	 */
@@ -815,7 +833,7 @@ typedef struct TableAmRoutine
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
 										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
@@ -826,7 +844,7 @@ typedef struct TableAmRoutine
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (BitmapTableScanDesc *scan,
 										   TupleTableSlot *slot);
 
 	/*
@@ -851,8 +869,8 @@ typedef struct TableAmRoutine
 	 * is obviously OK.
 	 *
 	 * Currently it is required to implement this interface, as there's no
-	 * alternative way (contrary e.g. to bitmap scans) to implement sample
-	 * scans. If infeasible to implement, the AM may raise an error.
+	 * alternative way to implement sample scans. If infeasible to implement,
+	 * the AM may raise an error.
 	 */
 	bool		(*scan_sample_next_block) (TableScanDesc scan,
 										   struct SampleScanState *scanstate);
@@ -945,29 +963,50 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 }
 
 /*
- * table_beginscan_bm is an alternative entry point for setting up a
- * TableScanDesc for a bitmap heap scan.  Although that scan technology is
- * really quite unlike a standard seqscan, there is just enough commonality to
- * make it worth using the same data structure.
+ * table_beginscan_bm is an entry point for setting up a BitmapTableScanDesc
+ * for a bitmap table scan.
  */
-static inline TableScanDesc
+static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, bool need_tuple)
+				   dsa_area *dsa,
+				   bool need_tuple,
+				   int prefetch_maximum)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 }
 
+/*
+ * Restart a bitmap table scan.
+ */
+static inline void
+table_rescan_bm(BitmapTableScanDesc *scan,
+				dsa_area *dsa,
+				int prefetch_maximum)
+{
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+}
+
+/*
+ * End a bitmap table scan.
+ */
+static inline void
+table_endscan_bm(BitmapTableScanDesc *scan)
+{
+	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+}
+
+
 /*
  * table_beginscan_sampling is an alternative entry point for setting up a
- * TableScanDesc for a TABLESAMPLE scan.  As with bitmap scans, it's worth
- * using the same data structure although the behavior is rather different.
- * In addition to the options offered by table_beginscan_strat, this call
- * also allows control of whether page-mode visibility checking is used.
+ * TableScanDesc for a TABLESAMPLE scan.  It's worth using the same data
+ * structure although the behavior is rather different. In addition to the
+ * options offered by table_beginscan_strat, this call also allows control of
+ * whether page-mode visibility checking is used.
  */
 static inline TableScanDesc
 table_beginscan_sampling(Relation rel, Snapshot snapshot,
@@ -989,7 +1028,7 @@ table_beginscan_sampling(Relation rel, Snapshot snapshot,
 
 /*
  * table_beginscan_tid is an alternative entry point for setting up a
- * TableScanDesc for a Tid scan. As with bitmap scans, it's worth using
+ * TableScanDesc for a Tid scan. As with sample scans, it's worth using
  * the same data structure although the behavior is rather different.
  */
 static inline TableScanDesc
@@ -1002,7 +1041,7 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 
 /*
  * table_beginscan_analyze is an alternative entry point for setting up a
- * TableScanDesc for an ANALYZE scan.  As with bitmap scans, it's worth using
+ * TableScanDesc for an ANALYZE scan.  As with sample scans, it's worth using
  * the same data structure although the behavior is rather different.
  */
 static inline TableScanDesc
@@ -1019,9 +1058,6 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-		tbm_end_iterate(&scan->tbmiterator);
-
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1032,9 +1068,6 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-		tbm_end_iterate(&scan->tbmiterator);
-
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1974,7 +2007,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
@@ -2001,7 +2034,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  * returned false.
  */
 static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
+table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 							 TupleTableSlot *slot)
 {
 	/*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 5a9a187771a..0f34bac4baf 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1814,7 +1814,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *scandesc;
+	struct BitmapTableScanDesc *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 910fbdd880c..49941d62251 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -261,12 +261,14 @@ BitmapAndPath
 BitmapAndState
 BitmapHeapPath
 BitmapHeapScan
+BitmapHeapScanDesc
 BitmapHeapScanState
 BitmapIndexScan
 BitmapIndexScanState
 BitmapOr
 BitmapOrPath
 BitmapOrState
+BitmapTableScanDesc
 Bitmapset
 Block
 BlockId
-- 
2.34.1

v21-0013-BitmapHeapScan-Push-primary-iterator-setup-into-.patchtext/x-patch; charset=US-ASCII; name=v21-0013-BitmapHeapScan-Push-primary-iterator-setup-into-.patchDownload
From a7bd2889b76d702ef39430de64522f2b882fc134 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 13 Jun 2024 17:24:44 -0400
Subject: [PATCH v21 13/20] BitmapHeapScan: Push primary iterator setup into
 Heap AM

Now that the table AM's are responsible for advancing the iterator for
bitmap table scans, it makes sense to also delegate most of the iterator
management tasks to them as well. This commit only pushes down the
primary iterator which yields the current block. The prefetch iterator
will be pushed down in a future commit.
---
 src/backend/access/heap/heapam.c          | 22 ++++++++++++++++++++--
 src/backend/access/heap/heapam_handler.c  |  2 +-
 src/backend/executor/nodeBitmapHeapscan.c | 13 +++----------
 src/include/access/heapam.h               | 12 ++++++++++--
 src/include/access/relscan.h              |  5 -----
 src/include/access/tableam.h              | 19 +++++++++++++++----
 6 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 88da737d149..c99ed440a0e 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1230,7 +1230,9 @@ heap_endscan(TableScanDesc sscan)
 }
 
 BitmapTableScanDesc *
-heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
+				  TIDBitmap *tbm, ParallelBitmapHeapState *pstate,
+				  dsa_area *dsa)
 {
 	BitmapHeapScanDesc *scan;
 
@@ -1266,14 +1268,23 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	scan->vmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
+	tbm_begin_iterate(&scan->iterator, tbm, dsa,
+					  pstate ?
+					  pstate->tbmiterator :
+					  InvalidDsaPointer);
+
 	return (BitmapTableScanDesc *) scan;
 }
 
 void
-heap_rescan_bm(BitmapTableScanDesc *sscan)
+heap_rescan_bm(BitmapTableScanDesc *sscan, TIDBitmap *tbm,
+			   ParallelBitmapHeapState *pstate,
+			   dsa_area *dsa)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	tbm_end_iterate(&scan->iterator);
+
 	if (BufferIsValid(scan->cbuf))
 	{
 		ReleaseBuffer(scan->cbuf);
@@ -1299,6 +1310,11 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->ctup.t_data = NULL;
 	ItemPointerSetInvalid(&scan->ctup.t_self);
+
+	tbm_begin_iterate(&scan->iterator, tbm, dsa,
+					  pstate ?
+					  pstate->tbmiterator :
+					  InvalidDsaPointer);
 }
 
 void
@@ -1306,6 +1322,8 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	tbm_end_iterate(&scan->iterator);
+
 	if (BufferIsValid(scan->cbuf))
 		ReleaseBuffer(scan->cbuf);
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 4057d0cf22b..936a34dcaa6 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2140,7 +2140,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->iterator);
+		tbmres = tbm_iterate(&hscan->iterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5f625c1f3e6..22df6314f3f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -158,6 +158,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
+									  node->tbm,
+									  node->pstate,
 									  dsa,
 									  need_tuples, node->prefetch_maximum);
 			node->scandesc = scan;
@@ -166,15 +168,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		else
 		{
 			/* rescan to release any page pin */
-			tbm_end_iterate(&scan->iterator);
-			table_rescan_bm(scan, dsa, node->prefetch_maximum);
+			table_rescan_bm(scan, node->tbm, pstate, dsa, node->prefetch_maximum);
 		}
 
-		tbm_begin_iterate(&scan->iterator, node->tbm, dsa,
-						  pstate ?
-						  pstate->tbmiterator :
-						  InvalidDsaPointer);
-
 		node->initialized = true;
 
 		goto new_page;
@@ -593,10 +589,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * close heap scan
 	 */
 	if (scanDesc)
-	{
-		tbm_end_iterate(&scanDesc->iterator);
 		table_endscan_bm(scanDesc);
-	}
 
 	/*
 	 * release bitmaps and buffers if any
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 1d5583cac22..824092c1d63 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -20,6 +20,7 @@
 #include "access/skey.h"
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
+#include "nodes/execnodes.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -113,6 +114,7 @@ typedef struct BitmapHeapScanDesc
 	HeapTupleData ctup;			/* current tuple in scan, if any */
 
 	BlockNumber cblock;			/* current block # in scan, if any */
+	TBMIterator iterator;
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -315,8 +317,14 @@ extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 extern void heap_endscan(TableScanDesc sscan);
 
 extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
-											  Snapshot snapshot, uint32 flags);
-extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
+											  Snapshot snapshot, uint32 flags,
+											  TIDBitmap *tbm,
+											  ParallelBitmapHeapState *pstate,
+											  dsa_area *dsa);
+extern void heap_rescan_bm(BitmapTableScanDesc *sscan,
+						   TIDBitmap *tbm,
+						   ParallelBitmapHeapState *pstate,
+						   dsa_area *dsa);
 void		heap_endscan_bm(BitmapTableScanDesc *sscan);
 
 extern HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 086fce35a8b..2c4c57bb983 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -57,11 +57,6 @@ typedef struct BitmapTableScanDesc
 	Relation	rel;			/* heap relation descriptor */
 	struct SnapshotData *snapshot;	/* snapshot to see */
 
-	/*
-	 * Members common to Parallel and Serial BitmapTableScans
-	 */
-	TBMIterator iterator;
-
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 69ccdaee8c4..afb8a9f3d6c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -36,6 +36,7 @@ extern PGDLLIMPORT bool synchronize_seqscans;
 
 struct BulkInsertStateData;
 struct IndexInfo;
+struct ParallelBitmapHeapState;
 struct SampleScanState;
 struct VacuumParams;
 struct ValidateIndexState;
@@ -354,9 +355,15 @@ typedef struct TableAmRoutine
 	 */
 	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
 										   Snapshot snapshot,
-										   uint32 flags);
+										   uint32 flags,
+										   TIDBitmap *tbm,
+										   struct ParallelBitmapHeapState *pstate,
+										   dsa_area *dsa);
 
-	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
+	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan,
+								   TIDBitmap *tbm,
+								   struct ParallelBitmapHeapState *pstate,
+								   dsa_area *dsa);
 
 	/*
 	 * Release resources and deallocate scan.
@@ -968,6 +975,8 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
+				   TIDBitmap *tbm,
+				   struct ParallelBitmapHeapState *pstate,
 				   dsa_area *dsa,
 				   bool need_tuple,
 				   int prefetch_maximum)
@@ -977,7 +986,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, tbm, pstate, dsa);
 }
 
 /*
@@ -985,10 +994,12 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
  */
 static inline void
 table_rescan_bm(BitmapTableScanDesc *scan,
+				TIDBitmap *tbm,
+				struct ParallelBitmapHeapState *pstate,
 				dsa_area *dsa,
 				int prefetch_maximum)
 {
-	scan->rel->rd_tableam->scan_rescan_bm(scan);
+	scan->rel->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa);
 }
 
 /*
-- 
2.34.1

v21-0014-BitmapHeapScan-lift-and-shift-prefetch-functions.patchtext/x-patch; charset=US-ASCII; name=v21-0014-BitmapHeapScan-lift-and-shift-prefetch-functions.patchDownload
From 2e58b0e93a0000f6c9fc162e0b986a9d04209bd5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 12:14:28 -0400
Subject: [PATCH v21 14/20] BitmapHeapScan: lift and shift prefetch functions

This is a temporary commit. For ease of review, move the BitmapHeapScan
prefetch functions into heapam_handler.c without modifying them. The
next commit will push the prefetching code into heap specific code.
Separating the commit which moves to the functions to heapam_handler.c
and the one which modifies them and their callers to contain bitmap
prefetch code in heap AM-specific code makes it easier to see what has
changed. Doing so requires including heap code in nodeBitmapHeapscan.c,
which is not okay for the final code that is committed.
---
 src/backend/access/heap/heapam_handler.c  | 218 +++++++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 225 +---------------------
 src/include/access/heapam.h               |   8 +
 3 files changed, 228 insertions(+), 223 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 936a34dcaa6..bf6a67467b3 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,6 +2112,224 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+void
+BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!prefetch_iterator->exhausted)
+		{
+			while (node->prefetch_pages < node->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!prefetch_iterator->exhausted)
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = tbm_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				node->pfblockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (node->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			node->prefetch_pages--;
+		}
+		else if (!prefetch_iterator->exhausted)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
+	if (node->prefetch_maximum > 0)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!prefetch_iterator->exhausted)
+			{
+				tbmpre = tbm_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (node->prefetch_target >= node->prefetch_maximum / 2)
+			node->prefetch_target = node->prefetch_maximum;
+		else if (node->prefetch_target > 0)
+			node->prefetch_target *= 2;
+		else
+			node->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < node->prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 22df6314f3f..c3a6336f5d9 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,6 +37,8 @@
 
 #include <math.h>
 
+/* XXX: temporary include only for review purposes */
+#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -51,10 +53,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  BitmapTableScanDesc *scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -279,225 +277,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->pfblockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 824092c1d63..9a455deba48 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -394,6 +394,14 @@ extern void simple_heap_update(Relation relation, ItemPointer otid,
 extern TransactionId heap_index_delete_tuples(Relation rel,
 											  TM_IndexDeleteOp *delstate);
 
+/* in heapam_handler.c */
+extern void BitmapPrefetch(BitmapHeapScanState *node,
+						   BitmapTableScanDesc *scan);
+
+extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
+
+extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+
 /* in heap/pruneheap.c */
 struct GlobalVisState;
 extern void heap_page_prune_opt(Relation relation, Buffer buffer);
-- 
2.34.1

v21-0016-BitmapHeapScan-move-per-scan-setup-into-a-helper.patchtext/x-patch; charset=US-ASCII; name=v21-0016-BitmapHeapScan-move-per-scan-setup-into-a-helper.patchDownload
From f0f3ec44f87b3dd4f7ec3e96e1057bef512cb00a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:21:08 -0400
Subject: [PATCH v21 16/20] BitmapHeapScan: move per scan setup into a helper

Add BitmapTableScanSetup() which contains all of the code that must be
done on every scan of the table in a bitmap table scan.
This includes scanning the index, building the bitmap, and setting up
the scan descriptors.

Much of BitmapHeapNext() code was this setup, so it made sense to put it
in a helper function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 188 +++++++++++-----------
 1 file changed, 96 insertions(+), 92 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 12dc75d0d2a..03ef9d7bde7 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,122 +53,126 @@ static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
-
-/* ----------------------------------------------------------------
- *		BitmapHeapNext
- *
- *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
- * ----------------------------------------------------------------
+/*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
  */
-static TupleTableSlot *
-BitmapHeapNext(BitmapHeapScanState *node)
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	BitmapTableScanDesc *scan;
-	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
+	int			prefetch_maximum = 0;
 
 	/*
-	 * extract necessary information from index scan node
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
 	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->scandesc;
+#ifdef USE_PREFETCH
+	Relation	rel = node->ss.ss_currentRelation;
+
+	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
 
 	/*
-	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
+	 * Scan the index, build the bitmap, and set up shared state for parallel.
 	 */
-	if (!node->initialized)
+	if (!pstate)
 	{
-		int			prefetch_maximum = 0;
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+	}
+	else if (BitmapShouldInitializeSharedState(pstate))
+	{
 		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
 		 */
-#ifdef USE_PREFETCH
-		Relation	rel = node->ss.ss_currentRelation;
-		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-#endif
-
-		if (!pstate)
-		{
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-		}
-		else if (BitmapShouldInitializeSharedState(pstate))
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
 
-			/*
-			 * Two iterators are used -- one for the pages being scanned and
-			 * one for the blocks being prefetched.
-			 */
+		/*
+		 * Two iterators are used -- one for the pages being scanned and one
+		 * for the blocks being prefetched.
+		 */
 
-			/*
-			 * Prepare to iterate over the TBM. This will return the
-			 * dsa_pointer of the iterator state which will be used by
-			 * multiple processes to iterate jointly.
-			 */
-			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+		/*
+		 * Prepare to iterate over the TBM. This will return the dsa_pointer
+		 * of the iterator state which will be used by multiple processes to
+		 * iterate jointly.
+		 */
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
-			if (prefetch_maximum > 0)
-			{
-				pstate->prefetch_iterator =
-					tbm_prepare_shared_iterate(node->tbm);
-			}
-#endif
-			/* We have initialized the shared state so wake up others. */
-			BitmapDoneInitializingSharedState(pstate);
+		if (prefetch_maximum > 0)
+		{
+			pstate->prefetch_iterator =
+				tbm_prepare_shared_iterate(node->tbm);
 		}
+#endif
+		/* We have initialized the shared state so wake up others. */
+		BitmapDoneInitializingSharedState(pstate);
+	}
+
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!node->scan_in_progress)
+	{
+		bool		need_tuples = false;
 
 		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
 		 */
-		if (!node->scan_in_progress)
-		{
-			bool		need_tuples = false;
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
+		node->scandesc = table_beginscan_bm(node->ss.ss_currentRelation,
+											node->ss.ps.state->es_snapshot,
+											node->tbm,
+											pstate,
+											dsa,
+											need_tuples, prefetch_maximum);
+		node->scan_in_progress = true;
+	}
+	else
+	{
+		/* rescan to release any page pin */
+		table_rescan_bm(node->scandesc, node->tbm, pstate, dsa);
+	}
 
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  node->tbm,
-									  node->pstate,
-									  dsa,
-									  need_tuples, prefetch_maximum);
-			node->scandesc = scan;
-			node->scan_in_progress = true;
-		}
-		else
-		{
-			/* rescan to release any page pin */
-			table_rescan_bm(scan, node->tbm, pstate, dsa);
-		}
+	node->initialized = true;
+}
 
-		node->initialized = true;
+/* ----------------------------------------------------------------
+ *		BitmapHeapNext
+ *
+ *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+BitmapHeapNext(BitmapHeapScanState *node)
+{
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
+	BitmapTableScanDesc *scan = node->scandesc;
 
+	/*
+	 * If we haven't yet performed the underlying index scan, do it, and begin
+	 * the iteration over the bitmap.
+	 */
+	if (!node->initialized)
+	{
+		BitmapTableScanSetup(node);
+		scan = node->scandesc;
 		goto new_page;
 	}
 
-- 
2.34.1

v21-0015-BitmapHeapScan-Push-prefetch-code-into-heap-AM.patchtext/x-patch; charset=US-ASCII; name=v21-0015-BitmapHeapScan-Push-prefetch-code-into-heap-AM.patchDownload
From 234b7d18a25a266310b640ff4a497232131acf00 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 10:30:28 -0400
Subject: [PATCH v21 15/20] BitmapHeapScan: Push prefetch code into heap AM

In order to completely remove the layering violation in bitmap table
scan code, we must avoid using the VM for skipping prefetches as well.

To accomplish this, push prefetch code down into the heap implementation
fo the bitmap table scan AM functions. This fixes another layering
violation related to prefetching mentioned in tableam.h.

This commit moves prefetch-related members from the BitmapHeapScanState
to the BitmapHeapScanDesc and localizes the prefetch functions to heap
AM code.

heapam_scan_bitmap_next_block() no longer needs to take blockno as a
parameter because it was only being used in generic bitmap table scan
code to check if the prefetch block was falling behind the current
block.
---
 src/backend/access/heap/heapam.c          |  53 +++++-
 src/backend/access/heap/heapam_handler.c  | 217 +++++++++++++---------
 src/backend/executor/nodeBitmapHeapscan.c | 111 ++---------
 src/include/access/heapam.h               |  30 ++-
 src/include/access/tableam.h              |  40 ++--
 src/include/nodes/execnodes.h             |  14 --
 6 files changed, 242 insertions(+), 223 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index c99ed440a0e..373553bcd3b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1232,7 +1232,7 @@ heap_endscan(TableScanDesc sscan)
 BitmapTableScanDesc *
 heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
 				  TIDBitmap *tbm, ParallelBitmapHeapState *pstate,
-				  dsa_area *dsa)
+				  dsa_area *dsa, int prefetch_maximum)
 {
 	BitmapHeapScanDesc *scan;
 
@@ -1266,13 +1266,38 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
 	scan->vis_ntuples = 0;
 
 	scan->vmbuffer = InvalidBuffer;
+	scan->pvmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
+	scan->pstate = pstate;
+
+	scan->prefetch_maximum = prefetch_maximum;
+	/* Only used for serial BHS */
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
+	/*
+	 * We use *two* iterators, one for the pages we are actually scanning and
+	 * another that runs ahead of the first for prefetching.
+	 * scan->prefetch_pages tracks exactly how many pages ahead the prefetch
+	 * iterator is.  Also, scan->prefetch_target tracks the desired prefetch
+	 * distance, which starts small and increases up to the prefetch_maximum.
+	 * This is to avoid doing a lot of prefetching in a scan that stops after
+	 * a few tuples because of a LIMIT.
+	 */
 	tbm_begin_iterate(&scan->iterator, tbm, dsa,
 					  pstate ?
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
 
+#ifdef USE_PREFETCH
+	if (prefetch_maximum > 0)
+		tbm_begin_iterate(&scan->prefetch_iterator, tbm, dsa,
+						  pstate ?
+						  pstate->prefetch_iterator :
+						  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 	return (BitmapTableScanDesc *) scan;
 }
 
@@ -1284,6 +1309,7 @@ heap_rescan_bm(BitmapTableScanDesc *sscan, TIDBitmap *tbm,
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
 	tbm_end_iterate(&scan->iterator);
+	tbm_end_iterate(&scan->prefetch_iterator);
 
 	if (BufferIsValid(scan->cbuf))
 	{
@@ -1299,6 +1325,12 @@ heap_rescan_bm(BitmapTableScanDesc *sscan, TIDBitmap *tbm,
 
 	scan->cblock = InvalidBlockNumber;
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * Reset empty_tuples_pending, a field only used by bitmap heap scan, to
 	 * avoid incorrectly emitting NULL-filled tuples from a previous scan on
@@ -1311,10 +1343,25 @@ heap_rescan_bm(BitmapTableScanDesc *sscan, TIDBitmap *tbm,
 	scan->ctup.t_data = NULL;
 	ItemPointerSetInvalid(&scan->ctup.t_self);
 
+	scan->pstate = pstate;
+
+	/* Only used for serial BHS */
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	tbm_begin_iterate(&scan->iterator, tbm, dsa,
 					  pstate ?
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+	if (scan->prefetch_maximum > 0)
+		tbm_begin_iterate(&scan->prefetch_iterator, tbm, dsa,
+						  pstate ?
+						  pstate->prefetch_iterator :
+						  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 }
 
 void
@@ -1323,6 +1370,7 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
 	tbm_end_iterate(&scan->iterator);
+	tbm_end_iterate(&scan->prefetch_iterator);
 
 	if (BufferIsValid(scan->cbuf))
 		ReleaseBuffer(scan->cbuf);
@@ -1330,6 +1378,9 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 	if (BufferIsValid(scan->vmbuffer))
 		ReleaseBuffer(scan->vmbuffer);
 
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bf6a67467b3..77b78ac5a36 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,6 +54,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
+static inline void BitmapPrefetch(BitmapHeapScanDesc *scan);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan);
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 static const TableAmRoutine heapam_methods;
@@ -2115,19 +2118,19 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 /*
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
-void
-BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
+static inline void
+BitmapPrefetch(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->pstate;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->prefetch_iterator;
 
 		if (!prefetch_iterator->exhausted)
 		{
-			while (node->prefetch_pages < node->prefetch_target)
+			while (scan->prefetch_pages < scan->prefetch_target)
 			{
 				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
@@ -2138,8 +2141,8 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				scan->prefetch_pages++;
+				scan->pfblock = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2147,14 +2150,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->base.rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -2163,7 +2166,7 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->prefetch_iterator;
 
 		if (!prefetch_iterator->exhausted)
 		{
@@ -2196,17 +2199,17 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				scan->pfblock = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->base.rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -2220,27 +2223,27 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
  *	iterator in prefetch_pages. For each block the main iterator returns, we
  *	decrement prefetch_pages.
  */
-void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->pstate;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->prefetch_iterator;
 
-		if (node->prefetch_pages > 0)
+		if (scan->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
+			scan->prefetch_pages--;
 		}
 		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
 			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
@@ -2254,9 +2257,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
 	 * exacerbates the effects of this bug.
 	 */
-	if (node->prefetch_maximum > 0)
+	if (scan->prefetch_maximum > 0)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -2280,7 +2283,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			if (!prefetch_iterator->exhausted)
 			{
 				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
 	}
@@ -2295,33 +2298,33 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
  * page/tuple, then to one after the second tuple is fetched, then
  * it doubles as later pages are fetched.
  */
-void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->pstate;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_target >= node->prefetch_maximum)
+		if (scan->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
+		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
+			scan->prefetch_target = scan->prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
 		else
-			node->prefetch_target++;
+			scan->prefetch_target++;
 		return;
 	}
 
 	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
+	if (pstate->prefetch_target < scan->prefetch_maximum)
 	{
 		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
+		if (pstate->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
+			pstate->prefetch_target = scan->prefetch_maximum;
 		else if (pstate->prefetch_target > 0)
 			pstate->prefetch_target *= 2;
 		else
@@ -2331,34 +2334,36 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 }
 
+
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
  * ------------------------------------------------------------------------
  */
 
 static bool
-heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
-							  BlockNumber *blockno, bool *recheck,
+heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
+							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
 
-	hscan->vis_idx = 0;
-	hscan->vis_ntuples = 0;
+	scan->vis_idx = 0;
+	scan->vis_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(scan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&hscan->iterator);
+		tbmres = tbm_iterate(&scan->iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2371,10 +2376,10 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->nblocks);
+	} while (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
+	block = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2382,37 +2387,35 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->flags & SO_NEED_TUPLES) &&
+	if (!(scan->base.flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rel, tbmres->blockno, &hscan->vmbuffer))
+		VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->empty_tuples_pending >= 0);
+		Assert(scan->empty_tuples_pending >= 0);
 
-		hscan->empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
-
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
-	hscan->cbuf = ReleaseAndReadBuffer(hscan->cbuf,
-									   scan->rel,
-									   block);
-	hscan->cblock = block;
-	buffer = hscan->cbuf;
-	snapshot = scan->snapshot;
+	scan->cbuf = ReleaseAndReadBuffer(scan->cbuf,
+									  scan->base.rel,
+									  block);
+	scan->cblock = block;
+	buffer = scan->cbuf;
+	snapshot = scan->base.snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rel, buffer);
+	heap_page_prune_opt(scan->base.rel, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2440,9 +2443,9 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rel, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, scan->base.rel, buffer, snapshot,
 									   &heapTuple, NULL, true))
-				hscan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+				scan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
 	}
 	else
@@ -2466,16 +2469,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rel->rd_id;
+			loctup.t_tableOid = scan->base.rel->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
-				hscan->vis_tuples[ntup++] = offnum;
-				PredicateLockTID(scan->rel, &loctup.t_self, snapshot,
+				scan->vis_tuples[ntup++] = offnum;
+				PredicateLockTID(scan->base.rel, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rel, &loctup,
+			HeapCheckForSerializableConflictOut(valid, scan->base.rel, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2483,17 +2486,29 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->vis_ntuples = ntup;
+	scan->vis_ntuples = ntup;
 
 	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->pstate == NULL &&
+		!scan->prefetch_iterator.exhausted &&
+		scan->pfblock < block)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(scan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * scan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
 	 * return false returning control to this function to advance to the next
 	 * block in the bitmap.
 	 */
@@ -2501,51 +2516,83 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
+heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 							  TupleTableSlot *slot)
 {
-	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+	ParallelBitmapHeapState *pstate = scan->pstate;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->empty_tuples_pending > 0)
+	if (scan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->empty_tuples_pending--;
+		scan->empty_tuples_pending--;
+		BitmapPrefetch(scan);
 		return true;
 	}
 
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->vis_idx < 0 || hscan->vis_idx >= hscan->vis_ntuples)
+	if (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
 		return false;
 
-	targoffset = hscan->vis_tuples[hscan->vis_idx];
-	page = BufferGetPage(hscan->cbuf);
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!pstate)
+	{
+		if (scan->prefetch_target < scan->prefetch_maximum)
+			scan->prefetch_target++;
+	}
+	else if (pstate->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target < scan->prefetch_maximum)
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(scan);
+
+	targoffset = scan->vis_tuples[scan->vis_idx];
+	page = BufferGetPage(scan->cbuf);
 	lp = PageGetItemId(page, targoffset);
 	Assert(ItemIdIsNormal(lp));
 
-	hscan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-	hscan->ctup.t_len = ItemIdGetLength(lp);
-	hscan->ctup.t_tableOid = scan->rel->rd_id;
-	ItemPointerSet(&hscan->ctup.t_self, hscan->cblock, targoffset);
+	scan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+	scan->ctup.t_len = ItemIdGetLength(lp);
+	scan->ctup.t_tableOid = sscan->rel->rd_id;
+	ItemPointerSet(&scan->ctup.t_self, scan->cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rel);
+	pgstat_count_heap_fetch(sscan->rel);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
 	 * acquires a pin on the buffer.
 	 */
-	ExecStoreBufferHeapTuple(&hscan->ctup,
+	ExecStoreBufferHeapTuple(&scan->ctup,
 							 slot,
-							 hscan->cbuf);
+							 scan->cbuf);
 
-	hscan->vis_idx++;
+	scan->vis_idx++;
 
 	return true;
 }
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c3a6336f5d9..12dc75d0d2a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,8 +37,6 @@
 
 #include <math.h>
 
-/* XXX: temporary include only for review purposes */
-#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -81,17 +79,20 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
+		int			prefetch_maximum = 0;
+
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+#ifdef USE_PREFETCH
+		Relation	rel = node->ss.ss_currentRelation;
+		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
 		if (!pstate)
 		{
 			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -110,6 +111,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
 
+			/*
+			 * Two iterators are used -- one for the pages being scanned and
+			 * one for the blocks being prefetched.
+			 */
+
 			/*
 			 * Prepare to iterate over the TBM. This will return the
 			 * dsa_pointer of the iterator state which will be used by
@@ -117,7 +123,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			 */
 			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (prefetch_maximum > 0)
 			{
 				pstate->prefetch_iterator =
 					tbm_prepare_shared_iterate(node->tbm);
@@ -127,14 +133,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			BitmapDoneInitializingSharedState(pstate);
 		}
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-			tbm_begin_iterate(&node->prefetch_iterator, node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -159,14 +157,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  node->tbm,
 									  node->pstate,
 									  dsa,
-									  need_tuples, node->prefetch_maximum);
+									  need_tuples, prefetch_maximum);
 			node->scandesc = scan;
 			node->scan_in_progress = true;
 		}
 		else
 		{
 			/* rescan to release any page pin */
-			table_rescan_bm(scan, node->tbm, pstate, dsa, node->prefetch_maximum);
+			table_rescan_bm(scan, node->tbm, pstate, dsa);
 		}
 
 		node->initialized = true;
@@ -184,37 +182,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -237,23 +204,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!node->prefetch_iterator.exhausted &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -319,20 +272,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* release bitmaps and buffers if any */
-	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
-	/* Only used for serial BHS */
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -373,11 +317,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -410,17 +351,12 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->scan_in_progress = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -460,13 +396,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 9a455deba48..78601b40904 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -116,6 +116,22 @@ typedef struct BitmapHeapScanDesc
 	BlockNumber cblock;			/* current block # in scan, if any */
 	TBMIterator iterator;
 
+	/* used to validate pf stays ahead of current block */
+	BlockNumber pfblock;
+
+	/* iterator for prefetching ahead of current page */
+	TBMIterator prefetch_iterator;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+
+	struct ParallelBitmapHeapState *pstate;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -123,7 +139,11 @@ typedef struct BitmapHeapScanDesc
 	 * block reported by the bitmap to determine how many NULL-filled tuples
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
+
+	/* page of VM containing info for current block */
 	Buffer		vmbuffer;
+	/* page of VM containing info for prefetch block */
+	Buffer		pvmbuffer;
 	int			empty_tuples_pending;
 } BitmapHeapScanDesc;
 
@@ -320,7 +340,7 @@ extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
 											  Snapshot snapshot, uint32 flags,
 											  TIDBitmap *tbm,
 											  ParallelBitmapHeapState *pstate,
-											  dsa_area *dsa);
+											  dsa_area *dsa, int prefetch_maximum);
 extern void heap_rescan_bm(BitmapTableScanDesc *sscan,
 						   TIDBitmap *tbm,
 						   ParallelBitmapHeapState *pstate,
@@ -394,14 +414,6 @@ extern void simple_heap_update(Relation relation, ItemPointer otid,
 extern TransactionId heap_index_delete_tuples(Relation rel,
 											  TM_IndexDeleteOp *delstate);
 
-/* in heapam_handler.c */
-extern void BitmapPrefetch(BitmapHeapScanState *node,
-						   BitmapTableScanDesc *scan);
-
-extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-
-extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-
 /* in heap/pruneheap.c */
 struct GlobalVisState;
 extern void heap_page_prune_opt(Relation relation, Buffer buffer);
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index afb8a9f3d6c..78eecfef930 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -358,7 +358,8 @@ typedef struct TableAmRoutine
 										   uint32 flags,
 										   TIDBitmap *tbm,
 										   struct ParallelBitmapHeapState *pstate,
-										   dsa_area *dsa);
+										   dsa_area *dsa,
+										   int prefetch_maximum);
 
 	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan,
 								   TIDBitmap *tbm,
@@ -815,33 +816,26 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
+	 * Prepare to fetch / check / return tuples from as part of a bitmap table
+	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
+	 * bitmap is exhausted and true otherwise.
 	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
+	 * This will typically read and pin a block, and do the necessary work to
+	 * allow scan_bitmap_next_tuple() to return tuples (e.g. depending on the
+	 * table AM, it might make sense to perform tuple visibility checks at
+	 * this time).
 	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, `exact_pages` is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching future blocks indicated in the bitmap is left to the table
+	 * AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
-										   BlockNumber *blockno, bool *recheck,
+										   bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -986,7 +980,8 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, tbm, pstate, dsa);
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, tbm, pstate, dsa,
+										  prefetch_maximum);
 }
 
 /*
@@ -996,8 +991,7 @@ static inline void
 table_rescan_bm(BitmapTableScanDesc *scan,
 				TIDBitmap *tbm,
 				struct ParallelBitmapHeapState *pstate,
-				dsa_area *dsa,
-				int prefetch_maximum)
+				dsa_area *dsa)
 {
 	scan->rel->rd_tableam->scan_rescan_bm(scan, tbm, pstate, dsa);
 }
@@ -2019,7 +2013,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 static inline bool
 table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
-							 BlockNumber *blockno, bool *recheck,
+							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -2032,7 +2026,7 @@ table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
-														 blockno, recheck,
+														 recheck,
 														 lossy_pages, exact_pages);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0f34bac4baf..6b1c3bbe6fd 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1796,19 +1796,12 @@ typedef struct ParallelBitmapHeapState
  *      scandesc		   current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		scan_in_progress   is this a rescan
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1817,19 +1810,12 @@ typedef struct BitmapHeapScanState
 	struct BitmapTableScanDesc *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	bool		scan_in_progress;
-	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v21-0018-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-patch; charset=US-ASCII; name=v21-0018-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From df5fef912e606deaac1f9843397b35860a053156 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 16:25:14 -0400
Subject: [PATCH v21 18/20] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 25 +++++++------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 429cb8bd7c9..8af2193b7ec 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMSerialIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,8 +687,7 @@ tbm_begin_serial_iterate(TIDBitmap *tbm)
 	 * Create the TBMSerialIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSerialIterator *) palloc(sizeof(TBMSerialIterator) +
-											MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMSerialIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1467,8 +1457,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 7fc2c4a464c..78e612b58cc 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /*
-- 
2.34.1

v21-0017-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v21-0017-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 109dbd15e49d10742c689f370b2290c2b564c823 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 18:02:38 -0400
Subject: [PATCH v21 17/20] Remove table AM callback scan_bitmap_next_block

Non block-based table AMs might find implementing bitmap table scan
somewhat easier by removing table_scan_bitmap_next_block(). Now bitmap
table scan code only calls table_scan_bitmap_next_tuple().

This commit turns the heap AM implementation of scan_bitmap_next_block()
into a local helper in heapam_handler.c.
---
 src/backend/access/heap/heapam_handler.c  | 58 +++++++++------
 src/backend/access/table/tableamapi.c     |  3 -
 src/backend/executor/nodeBitmapHeapscan.c | 63 ++++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 88 ++++++-----------------
 5 files changed, 88 insertions(+), 126 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 77b78ac5a36..973eaf6d713 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2334,18 +2334,22 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
 #endif							/* USE_PREFETCH */
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
+/*
+ * Prepare to fetch / check / return tuples as part of a bitmap heap scan.
+ * `scan` needs to have been started via heap_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set to indicate whether or not the tuples from this block
+ * should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  */
-
 static bool
-heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
+heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2515,9 +2519,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
 	return true;
 }
 
+
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	ParallelBitmapHeapState *pstate = scan->pstate;
@@ -2525,22 +2536,28 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 	Page		page;
 	ItemId		lp;
 
-	if (scan->empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		scan->empty_tuples_pending--;
-		BitmapPrefetch(scan);
-		return true;
-	}
+		if (scan->empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			scan->empty_tuples_pending--;
+			BitmapPrefetch(scan);
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2941,7 +2958,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index e9b598256fb..a47527d490a 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 03ef9d7bde7..1bb36b38949 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -161,56 +161,49 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext = node->ss.ps.ps_ExprContext;
-	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
-	BitmapTableScanDesc *scan = node->scandesc;
+	ExprContext *econtext;
+	TupleTableSlot *slot;
+	BitmapTableScanDesc *scan;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->scandesc;
-		goto new_page;
-	}
 
-	for (;;)
+	scan = node->scandesc;
+	econtext = node->ss.ps.ps_ExprContext;
+	slot = node->ss.ss_ScanTupleSlot;
+
+	while (table_scan_bitmap_next_tuple(scan, slot,
+										&node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+		/*
+		 * Continuing in previously obtained page.
+		 */
 
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 775955363ef..c11ff3a1bae 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -324,7 +324,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 78eecfef930..19aeb388617 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -816,37 +816,20 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from as part of a bitmap table
-	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
-	 * bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin a block, and do the necessary work to
-	 * allow scan_bitmap_next_tuple() to return tuples (e.g. depending on the
-	 * table AM, it might make sense to perform tuple visibility checks at
-	 * this time).
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
-	 * block; otherwise, `exact_pages` is incremented.
-	 *
-	 * Prefetching future blocks indicated in the bitmap is left to the table
-	 * AM.
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
-										   bool *recheck,
-										   long *lossy_pages, long *exact_pages);
-
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
 	bool		(*scan_bitmap_next_tuple) (BitmapTableScanDesc *scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot, bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1993,54 +1976,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * ----------------------------------------------------------------------------
  */
 
+
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
- * incremented if the block's representation in the bitmap is lossy; otherwise,
- * `exact_pages` is incremented.
- *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked. Tuples from lossy pages will always
- * need to be rechecked, but some non-lossy pages' tuples may also require
- * recheck.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `blockno` is only used in bitmap table scan code to validate that the
- * prefetch block is staying ahead of the current block.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
+table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
-														 recheck,
-														 lossy_pages, exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2051,7 +2006,8 @@ table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rel->rd_tableam->scan_bitmap_next_tuple(scan,
-														 slot);
+														 slot, recheck,
+														 lossy_pages, exact_pages);
 }
 
 /*
-- 
2.34.1

v21-0019-Separate-TBMIterator-and-TBMIterateResult.patchtext/x-patch; charset=US-ASCII; name=v21-0019-Separate-TBMIterator-and-TBMIterateResult.patchDownload
From 417e286dce29aafed6de08784da3cb32db205844 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 17:09:50 -0400
Subject: [PATCH v21 19/20] Separate TBMIterator and TBMIterateResult

Remove the TBMIterateResult from the TBMSerialIterator and
TBMSharedIterator and have tbm_[shared_]iterate() take a
TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c          | 49 +++++++++------
 src/backend/access/gin/ginscan.c         |  2 +-
 src/backend/access/heap/heapam_handler.c | 66 ++++++++++----------
 src/backend/nodes/tidbitmap.c            | 77 ++++++++++++------------
 src/include/access/gin_private.h         |  2 +-
 src/include/nodes/tidbitmap.h            |  6 +-
 6 files changed, 108 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0d66381df1e..235a465362d 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,7 +332,20 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -374,6 +387,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_serial_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +837,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_serial_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_serial_iterate(entry->matchIterator);
+				tbm_serial_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_serial_iterate(entry->matchIterator);
@@ -858,10 +873,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +890,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 46dde99514d..43bb6c7ac4b 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 973eaf6d713..aa862348672 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2132,17 +2132,19 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 		{
 			while (scan->prefetch_pages < scan->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				scan->prefetch_pages++;
-				scan->pfblock = tbmpre->blockno;
+				scan->pfblock = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2151,13 +2153,13 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -2172,7 +2174,7 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -2191,25 +2193,25 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				scan->pfblock = tbmpre->blockno;
+				scan->pfblock = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
@@ -2228,7 +2230,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = scan->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -2242,8 +2244,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblock = tbmpre.blockno;
 		}
 		return;
 	}
@@ -2282,8 +2284,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 			 */
 			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblock = tbmpre.blockno;
 			}
 		}
 	}
@@ -2354,7 +2356,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	scan->vis_idx = 0;
 	scan->vis_ntuples = 0;
@@ -2367,9 +2369,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->iterator);
+		tbm_iterate(&scan->iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
 		/*
@@ -2380,11 +2382,11 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= scan->nblocks);
 
 	/* Got a valid block */
-	block = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	block = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2392,14 +2394,14 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->base.flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->base.rel, tbmres.blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(scan->empty_tuples_pending >= 0);
 
-		scan->empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
@@ -2431,7 +2433,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2440,9 +2442,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2492,7 +2494,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	scan->vis_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 8af2193b7ec..653c0133455 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMSerialIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -948,22 +946,22 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_serial_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  If result->ntuples
+ * < 0, then the bitmap is "lossy" and failed to remember the exact tuples to
+ * look at on this page --- the caller must examine all tuples on the page and
+ * check if they meet the intended condition.  If result->recheck is true, only
+ * the indicated tuples need be examined, but the condition must be rechecked
+ * anyway.  (For ease of testing, recheck is always set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_serial_iterate(TBMSerialIterator *iterator)
+void
+tbm_serial_iterate(TBMSerialIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
+	Assert(tbmres);
 
 	/*
 	 * If lossy chunk pages remain, make sure we've advanced schunkptr/
@@ -999,11 +997,11 @@ tbm_serial_iterate(TBMSerialIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1019,16 +1017,16 @@ tbm_serial_iterate(TBMSerialIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1038,10 +1036,9 @@ tbm_serial_iterate(TBMSerialIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1092,13 +1089,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1108,21 +1105,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1592,14 +1589,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
 	Assert(!iterator->exhausted);
 
 	if (iterator->serial)
-		return tbm_serial_iterate(iterator->serial);
+		tbm_serial_iterate(iterator->serial, tbmres);
 	else
-		return tbm_shared_iterate(iterator->parallel);
+		tbm_shared_iterate(iterator->parallel, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index cfac6ca3923..d8a460d2e2f 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMSerialIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 78e612b58cc..60c6eb41738 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -83,8 +83,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMSerialIterator *tbm_begin_serial_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_serial_iterate(TBMSerialIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_serial_iterate(TBMSerialIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_serial_iterate(TBMSerialIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -94,7 +94,7 @@ extern long tbm_calculate_entries(double maxbytes);
 extern void tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
 							  dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 
 #endif							/* TIDBITMAP_H */
-- 
2.34.1

v21-0020-Use-streaming-I-O-in-Bitmap-Heap-Scans.patchtext/x-patch; charset=US-ASCII; name=v21-0020-Use-streaming-I-O-in-Bitmap-Heap-Scans.patchDownload
From 17c60f8dc226053738e8ab9b2f8c8171dc16bbb0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 18:11:57 -0400
Subject: [PATCH v21 20/20] Use streaming I/O in Bitmap Heap Scans

Instead of calling ReadBuffer() for each block, bitmap heap scans now
use the streaming API introduced in b5a9b18cd0.

The read stream API prefetches blocks from the bitmap, so this commit
removes all of the bespoke bitmap heap scan prefetch code.
---
 src/backend/access/heap/heapam.c          | 103 ++++---
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  24 +-
 src/include/access/heapam.h               |  14 +-
 src/include/nodes/execnodes.h             |   6 -
 5 files changed, 103 insertions(+), 391 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 373553bcd3b..b75a5eace00 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -285,6 +285,59 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+static BlockNumber
+heap_bitmap_scan_stream_read_next(ReadStream *stream,
+								  void *callback_private_data,
+								  void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) callback_private_data;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&scan->iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(scan->base.flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
+		{
+			/* can't be lossy in the skip_fetch case */
+			Assert(tbmres->ntuples >= 0);
+			Assert(scan->empty_tuples_pending >= 0);
+
+			scan->empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1271,33 +1324,19 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
 
 	scan->pstate = pstate;
 
-	scan->prefetch_maximum = prefetch_maximum;
-	/* Only used for serial BHS */
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
+	scan->read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+												   NULL,
+												   scan->base.rel,
+												   MAIN_FORKNUM,
+												   heap_bitmap_scan_stream_read_next,
+												   scan,
+												   sizeof(TBMIterateResult));
 
-	/*
-	 * We use *two* iterators, one for the pages we are actually scanning and
-	 * another that runs ahead of the first for prefetching.
-	 * scan->prefetch_pages tracks exactly how many pages ahead the prefetch
-	 * iterator is.  Also, scan->prefetch_target tracks the desired prefetch
-	 * distance, which starts small and increases up to the prefetch_maximum.
-	 * This is to avoid doing a lot of prefetching in a scan that stops after
-	 * a few tuples because of a LIMIT.
-	 */
 	tbm_begin_iterate(&scan->iterator, tbm, dsa,
 					  pstate ?
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (prefetch_maximum > 0)
-		tbm_begin_iterate(&scan->prefetch_iterator, tbm, dsa,
-						  pstate ?
-						  pstate->prefetch_iterator :
-						  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	return (BitmapTableScanDesc *) scan;
 }
 
@@ -1308,8 +1347,11 @@ heap_rescan_bm(BitmapTableScanDesc *sscan, TIDBitmap *tbm,
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	/* Reset the read stream on rescan. */
+	if (scan->read_stream)
+		read_stream_reset(scan->read_stream);
+
 	tbm_end_iterate(&scan->iterator);
-	tbm_end_iterate(&scan->prefetch_iterator);
 
 	if (BufferIsValid(scan->cbuf))
 	{
@@ -1345,23 +1387,10 @@ heap_rescan_bm(BitmapTableScanDesc *sscan, TIDBitmap *tbm,
 
 	scan->pstate = pstate;
 
-	/* Only used for serial BHS */
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
-
 	tbm_begin_iterate(&scan->iterator, tbm, dsa,
 					  pstate ?
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
-
-#ifdef USE_PREFETCH
-	if (scan->prefetch_maximum > 0)
-		tbm_begin_iterate(&scan->prefetch_iterator, tbm, dsa,
-						  pstate ?
-						  pstate->prefetch_iterator :
-						  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 }
 
 void
@@ -1369,8 +1398,10 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	if (scan->read_stream)
+		read_stream_end(scan->read_stream);
+
 	tbm_end_iterate(&scan->iterator);
-	tbm_end_iterate(&scan->prefetch_iterator);
 
 	if (BufferIsValid(scan->cbuf))
 		ReleaseBuffer(scan->cbuf);
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index aa862348672..93c630a0fbe 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,9 +54,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
-static inline void BitmapPrefetch(BitmapHeapScanDesc *scan);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan);
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 static const TableAmRoutine heapam_methods;
@@ -2115,227 +2112,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &scan->prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblock = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &scan->prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				scan->pfblock = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &scan->prefetch_iterator;
-
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblock = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (scan->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &scan->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblock = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->pstate;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= scan->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
-			scan->prefetch_target = scan->prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < scan->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= scan->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
-			pstate->prefetch_target = scan->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap heap scan.
  * `scan` needs to have been started via heap_beginscan_bm(). Returns false if
@@ -2356,63 +2132,52 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+	void	   *per_buffer_data;
+
+	Assert(scan->read_stream);
 
 	scan->vis_idx = 0;
 	scan->vis_ntuples = 0;
 
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(scan);
-
-	do
+	if (BufferIsValid(scan->cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		tbm_iterate(&scan->iterator, &tbmres);
+		ReleaseBuffer(scan->cbuf);
+		scan->cbuf = InvalidBuffer;
+	}
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	scan->cbuf = read_stream_next_buffer(scan->read_stream, &per_buffer_data);
 
+	if (BufferIsInvalid(scan->cbuf))
+	{
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= scan->nblocks);
+		*recheck = false;
+		return scan->empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	block = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->base.flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->base.rel, tbmres.blockno, &scan->vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(scan->empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		scan->empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(scan->cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	/* Got a valid block */
+	block = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
+	scan->cblock = tbmres->blockno;
+	scan->vis_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	scan->cbuf = ReleaseAndReadBuffer(scan->cbuf,
-									  scan->base.rel,
-									  block);
-	scan->cblock = block;
 	buffer = scan->cbuf;
 	snapshot = scan->base.snapshot;
 
@@ -2433,7 +2198,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2442,9 +2207,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2494,23 +2259,11 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	scan->vis_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->pstate == NULL &&
-		!scan->prefetch_iterator.exhausted &&
-		scan->pfblock < block)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(scan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2533,7 +2286,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
-	ParallelBitmapHeapState *pstate = scan->pstate;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
@@ -2553,7 +2305,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 			 */
 			ExecStoreAllNullTuple(slot);
 			scan->empty_tuples_pending--;
-			BitmapPrefetch(scan);
 			return true;
 		}
 
@@ -2561,36 +2312,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!pstate)
-	{
-		if (scan->prefetch_target < scan->prefetch_maximum)
-			scan->prefetch_target++;
-	}
-	else if (pstate->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target < scan->prefetch_maximum)
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(scan);
-
 	targoffset = scan->vis_tuples[scan->vis_idx];
 	page = BufferGetPage(scan->cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 1bb36b38949..99b634e77cd 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -95,24 +95,13 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 			elog(ERROR, "unrecognized result from subplan");
 
-		/*
-		 * Two iterators are used -- one for the pages being scanned and one
-		 * for the blocks being prefetched.
-		 */
-
 		/*
 		 * Prepare to iterate over the TBM. This will return the dsa_pointer
 		 * of the iterator state which will be used by multiple processes to
 		 * iterate jointly.
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
-#ifdef USE_PREFETCH
-		if (prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif
+
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -471,12 +460,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -503,17 +489,9 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
-	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 78601b40904..e05fd5b9ee8 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -116,19 +116,7 @@ typedef struct BitmapHeapScanDesc
 	BlockNumber cblock;			/* current block # in scan, if any */
 	TBMIterator iterator;
 
-	/* used to validate pf stays ahead of current block */
-	BlockNumber pfblock;
-
-	/* iterator for prefetching ahead of current page */
-	TBMIterator prefetch_iterator;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
-
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
+	ReadStream *read_stream;
 
 	struct ParallelBitmapHeapState *pstate;
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6b1c3bbe6fd..776ca6cea13 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1770,11 +1770,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1782,10 +1779,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.34.1

#145Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#144)
19 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Jun 14, 2024 at 7:56 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Attached v21 is the rest of the patches to make bitmap heap scan use
the read stream API.

---snip---

The one relic of iterator ownership is that for parallel bitmap heap
scan, a single process must scan the index, construct the bitmap, and
call tbm_prepare_shared_iterate() to set up the iterator for all the
processes. I didn't see a way to push this down (because to build the
bitmap we have to scan the index and call ExecProcNode()). I wonder if
this creates an odd split of responsibilities. I could use some other
synchronization mechanism to communicate which process built the
bitmap in the generic bitmap table scan code and thus should set up
the iterator in the heap implementation, but that sounds like a pretty
bad idea. Also, I'm not sure how a non-block-based table AM would use
TBMIterators (or even TIDBitmap) anyway.

I tinkered around with this some more and actually came up with a
solution to my primary concern with the code structure. Attached is
v22. It still needs the performance regression investigation mentioned
in my previous email, but I feel more confident in the layering of the
iterator ownership I ended up with.

Because the patch numbers have changed, below is a summary of the
contents with the new patch numbers:

Patches 0001-0003 implement the async-friendly behavior needed both to
push down the VM lookups for prefetching and eventually to use the
read stream API.

Patches 0004-0006 add and make use of a common interface for the
shared and private bitmap iterators per Heikki's
suggestion in [1]/messages/by-id/5a172d1e-d69c-409a-b1fa-6521214c81c2@iki.fi.

Patches 0008 - 0012 make new scan descriptors for bitmap table scans
and the heap AM implementation.

0013 and 0014 push all of the prefetch code down into heap AM code as
suggested by Heikki in [1]/messages/by-id/5a172d1e-d69c-409a-b1fa-6521214c81c2@iki.fi.

0016 removes scan_bitmap_next_block() per Heikki's suggestion in [1]/messages/by-id/5a172d1e-d69c-409a-b1fa-6521214c81c2@iki.fi.

Patches 0017 and 0018 make some changes to the TIDBitmap API to
support having multiple TBMIterateResults at the same time instead of
reusing the same one when iterating.

0019 uses the read stream API and removes all the bespoke prefetching
code from bitmap heap scan.

- Melanie

[1]: /messages/by-id/5a172d1e-d69c-409a-b1fa-6521214c81c2@iki.fi

Attachments:

v22-0013-BitmapHeapScan-lift-and-shift-prefetch-functions.patchtext/x-patch; charset=US-ASCII; name=v22-0013-BitmapHeapScan-lift-and-shift-prefetch-functions.patchDownload
From f4db48d29f0e9128278da53e0dbb34e82ca929ae Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 12:14:28 -0400
Subject: [PATCH v22 13/19] BitmapHeapScan: lift and shift prefetch functions

This is a temporary commit. For ease of review, move the BitmapHeapScan
prefetch functions into heapam_handler.c without modifying them. The
next commit will push the prefetching code into heap specific code.
Separating the commit which moves to the functions to heapam_handler.c
and the one which modifies them and their callers to contain bitmap
prefetch code in heap AM-specific code makes it easier to see what has
changed. Doing so requires including heap code in nodeBitmapHeapscan.c,
which is not okay for the final code that is committed.
---
 src/backend/access/heap/heapam_handler.c  | 218 +++++++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 225 +---------------------
 src/include/access/heapam.h               |  10 +
 3 files changed, 230 insertions(+), 223 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 4057d0cf22b..51aaff6c6de 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,6 +2112,224 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+void
+BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!prefetch_iterator->exhausted)
+		{
+			while (node->prefetch_pages < node->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!prefetch_iterator->exhausted)
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = tbm_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				node->pfblockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (node->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			node->prefetch_pages--;
+		}
+		else if (!prefetch_iterator->exhausted)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
+	if (node->prefetch_maximum > 0)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!prefetch_iterator->exhausted)
+			{
+				tbmpre = tbm_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (node->prefetch_target >= node->prefetch_maximum / 2)
+			node->prefetch_target = node->prefetch_maximum;
+		else if (node->prefetch_target > 0)
+			node->prefetch_target *= 2;
+		else
+			node->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < node->prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 4dfc031c125..b7b03a767cb 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,6 +37,8 @@
 
 #include <math.h>
 
+/* XXX: temporary include only for review purposes */
+#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -51,10 +53,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  BitmapTableScanDesc *scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -283,225 +281,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->pfblockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 1d5583cac22..92f7dd7390c 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -20,6 +20,8 @@
 #include "access/skey.h"
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
+/* XXX: temporary include so lift and shift works */
+#include "nodes/execnodes.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -386,6 +388,14 @@ extern void simple_heap_update(Relation relation, ItemPointer otid,
 extern TransactionId heap_index_delete_tuples(Relation rel,
 											  TM_IndexDeleteOp *delstate);
 
+/* in heapam_handler.c */
+extern void BitmapPrefetch(BitmapHeapScanState *node,
+						   BitmapTableScanDesc *scan);
+
+extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
+
+extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+
 /* in heap/pruneheap.c */
 struct GlobalVisState;
 extern void heap_page_prune_opt(Relation relation, Buffer buffer);
-- 
2.34.1

v22-0014-BitmapHeapScan-Push-prefetch-code-into-heap-AM.patchtext/x-patch; charset=US-ASCII; name=v22-0014-BitmapHeapScan-Push-prefetch-code-into-heap-AM.patchDownload
From 5be0a1763837c29e605d751b259d8a5f9336bf85 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 10:30:28 -0400
Subject: [PATCH v22 14/19] BitmapHeapScan: Push prefetch code into heap AM

In order to completely remove the layering violation in bitmap table
scan code, we must avoid using the VM for skipping prefetches as well.

To accomplish this, push prefetch code down into the heap implementation
fo the bitmap table scan AM functions. This fixes another layering
violation related to prefetching mentioned in tableam.h.

This commit moves prefetch-related members from the BitmapHeapScanState
to the BitmapHeapScanDesc and localizes the prefetch functions to heap
AM code.

heapam_scan_bitmap_next_block() no longer needs to take blockno as a
parameter because it was only being used in generic bitmap table scan
code to check if the prefetch block was falling behind the current
block.
---
 src/backend/access/heap/heapam.c          |  23 ++-
 src/backend/access/heap/heapam_handler.c  | 217 +++++++++++++---------
 src/backend/executor/nodeBitmapHeapscan.c | 130 ++++---------
 src/include/access/heapam.h               |  28 +--
 src/include/access/relscan.h              |   4 +
 src/include/access/tableam.h              |  42 ++---
 src/include/nodes/execnodes.h             |  14 --
 7 files changed, 235 insertions(+), 223 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 88da737d149..9847ce2c3aa 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1230,7 +1230,8 @@ heap_endscan(TableScanDesc sscan)
 }
 
 BitmapTableScanDesc *
-heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
+				  int prefetch_maximum)
 {
 	BitmapHeapScanDesc *scan;
 
@@ -1264,8 +1265,15 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	scan->vis_ntuples = 0;
 
 	scan->vmbuffer = InvalidBuffer;
+	scan->pvmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
+	scan->prefetch_maximum = prefetch_maximum;
+
+	/* Only used for serial BHS */
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	return (BitmapTableScanDesc *) scan;
 }
 
@@ -1288,6 +1296,12 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->cblock = InvalidBlockNumber;
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * Reset empty_tuples_pending, a field only used by bitmap heap scan, to
 	 * avoid incorrectly emitting NULL-filled tuples from a previous scan on
@@ -1299,6 +1313,10 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->ctup.t_data = NULL;
 	ItemPointerSetInvalid(&scan->ctup.t_self);
+
+	/* Only used for serial BHS */
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 }
 
 void
@@ -1312,6 +1330,9 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 	if (BufferIsValid(scan->vmbuffer))
 		ReleaseBuffer(scan->vmbuffer);
 
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 51aaff6c6de..e06054369d2 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,6 +54,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
+static inline void BitmapPrefetch(BitmapHeapScanDesc *scan);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan);
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 static const TableAmRoutine heapam_methods;
@@ -2115,19 +2118,19 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 /*
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
-void
-BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
+static inline void
+BitmapPrefetch(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		if (!prefetch_iterator->exhausted)
 		{
-			while (node->prefetch_pages < node->prefetch_target)
+			while (scan->prefetch_pages < scan->prefetch_target)
 			{
 				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
@@ -2138,8 +2141,8 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				scan->prefetch_pages++;
+				scan->pfblock = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2147,14 +2150,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->base.rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -2163,7 +2166,7 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		if (!prefetch_iterator->exhausted)
 		{
@@ -2196,17 +2199,17 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				scan->pfblock = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->base.rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -2220,27 +2223,27 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
  *	iterator in prefetch_pages. For each block the main iterator returns, we
  *	decrement prefetch_pages.
  */
-void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
-		if (node->prefetch_pages > 0)
+		if (scan->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
+			scan->prefetch_pages--;
 		}
 		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
 			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
@@ -2254,9 +2257,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
 	 * exacerbates the effects of this bug.
 	 */
-	if (node->prefetch_maximum > 0)
+	if (scan->prefetch_maximum > 0)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -2280,7 +2283,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			if (!prefetch_iterator->exhausted)
 			{
 				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
 	}
@@ -2295,33 +2298,33 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
  * page/tuple, then to one after the second tuple is fetched, then
  * it doubles as later pages are fetched.
  */
-void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_target >= node->prefetch_maximum)
+		if (scan->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
+		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
+			scan->prefetch_target = scan->prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
 		else
-			node->prefetch_target++;
+			scan->prefetch_target++;
 		return;
 	}
 
 	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
+	if (pstate->prefetch_target < scan->prefetch_maximum)
 	{
 		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
+		if (pstate->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
+			pstate->prefetch_target = scan->prefetch_maximum;
 		else if (pstate->prefetch_target > 0)
 			pstate->prefetch_target *= 2;
 		else
@@ -2331,34 +2334,36 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 }
 
+
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
  * ------------------------------------------------------------------------
  */
 
 static bool
-heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
-							  BlockNumber *blockno, bool *recheck,
+heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
+							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
 
-	hscan->vis_idx = 0;
-	hscan->vis_ntuples = 0;
+	scan->vis_idx = 0;
+	scan->vis_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(scan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->iterator);
+		tbmres = tbm_iterate(&scan->base.iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2371,10 +2376,10 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->nblocks);
+	} while (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
+	block = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2382,37 +2387,35 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->flags & SO_NEED_TUPLES) &&
+	if (!(scan->base.flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rel, tbmres->blockno, &hscan->vmbuffer))
+		VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->empty_tuples_pending >= 0);
+		Assert(scan->empty_tuples_pending >= 0);
 
-		hscan->empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
-
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
-	hscan->cbuf = ReleaseAndReadBuffer(hscan->cbuf,
-									   scan->rel,
-									   block);
-	hscan->cblock = block;
-	buffer = hscan->cbuf;
-	snapshot = scan->snapshot;
+	scan->cbuf = ReleaseAndReadBuffer(scan->cbuf,
+									  scan->base.rel,
+									  block);
+	scan->cblock = block;
+	buffer = scan->cbuf;
+	snapshot = scan->base.snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rel, buffer);
+	heap_page_prune_opt(scan->base.rel, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2440,9 +2443,9 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rel, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, scan->base.rel, buffer, snapshot,
 									   &heapTuple, NULL, true))
-				hscan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+				scan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
 	}
 	else
@@ -2466,16 +2469,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rel->rd_id;
+			loctup.t_tableOid = scan->base.rel->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
-				hscan->vis_tuples[ntup++] = offnum;
-				PredicateLockTID(scan->rel, &loctup.t_self, snapshot,
+				scan->vis_tuples[ntup++] = offnum;
+				PredicateLockTID(scan->base.rel, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rel, &loctup,
+			HeapCheckForSerializableConflictOut(valid, scan->base.rel, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2483,17 +2486,29 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->vis_ntuples = ntup;
+	scan->vis_ntuples = ntup;
 
 	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->base.pstate == NULL &&
+		!scan->base.prefetch_iterator.exhausted &&
+		scan->pfblock < block)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(scan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * scan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
 	 * return false returning control to this function to advance to the next
 	 * block in the bitmap.
 	 */
@@ -2501,51 +2516,83 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
+heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 							  TupleTableSlot *slot)
 {
-	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+	ParallelBitmapHeapState *pstate = sscan->pstate;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->empty_tuples_pending > 0)
+	if (scan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->empty_tuples_pending--;
+		scan->empty_tuples_pending--;
+		BitmapPrefetch(scan);
 		return true;
 	}
 
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->vis_idx < 0 || hscan->vis_idx >= hscan->vis_ntuples)
+	if (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
 		return false;
 
-	targoffset = hscan->vis_tuples[hscan->vis_idx];
-	page = BufferGetPage(hscan->cbuf);
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!pstate)
+	{
+		if (scan->prefetch_target < scan->prefetch_maximum)
+			scan->prefetch_target++;
+	}
+	else if (pstate->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target < scan->prefetch_maximum)
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(scan);
+
+	targoffset = scan->vis_tuples[scan->vis_idx];
+	page = BufferGetPage(scan->cbuf);
 	lp = PageGetItemId(page, targoffset);
 	Assert(ItemIdIsNormal(lp));
 
-	hscan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-	hscan->ctup.t_len = ItemIdGetLength(lp);
-	hscan->ctup.t_tableOid = scan->rel->rd_id;
-	ItemPointerSet(&hscan->ctup.t_self, hscan->cblock, targoffset);
+	scan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+	scan->ctup.t_len = ItemIdGetLength(lp);
+	scan->ctup.t_tableOid = sscan->rel->rd_id;
+	ItemPointerSet(&scan->ctup.t_self, scan->cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rel);
+	pgstat_count_heap_fetch(sscan->rel);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
 	 * acquires a pin on the buffer.
 	 */
-	ExecStoreBufferHeapTuple(&hscan->ctup,
+	ExecStoreBufferHeapTuple(&scan->ctup,
 							 slot,
-							 hscan->cbuf);
+							 scan->cbuf);
 
-	hscan->vis_idx++;
+	scan->vis_idx++;
 
 	return true;
 }
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b7b03a767cb..e3b8e8baa6a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,8 +37,6 @@
 
 #include <math.h>
 
-/* XXX: temporary include only for review purposes */
-#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -81,17 +79,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
+		int			prefetch_maximum = 0;
+
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+#ifdef USE_PREFETCH
+		Relation	rel = node->ss.ss_currentRelation;
+
+		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
 		if (!pstate)
 		{
 			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -110,6 +112,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
 
+			/*
+			 * Two iterators are used -- one for the pages being scanned and
+			 * one for the blocks being prefetched.
+			 */
+
 			/*
 			 * Prepare to iterate over the TBM. This will return the
 			 * dsa_pointer of the iterator state which will be used by
@@ -117,7 +124,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			 */
 			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (prefetch_maximum > 0)
 			{
 				pstate->prefetch_iterator =
 					tbm_prepare_shared_iterate(node->tbm);
@@ -127,14 +134,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			BitmapDoneInitializingSharedState(pstate);
 		}
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-			tbm_begin_iterate(&node->prefetch_iterator, node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -156,7 +155,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
-									  need_tuples);
+									  pstate,
+									  need_tuples,
+									  prefetch_maximum);
 			node->scandesc = scan;
 			node->scan_in_progress = true;
 		}
@@ -173,6 +174,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 						  pstate->tbmiterator :
 						  InvalidDsaPointer);
 
+		/*
+		 * We use *two* iterators, one for the pages we are actually scanning
+		 * and another that runs ahead of the first for prefetching.
+		 * scan->prefetch_pages tracks exactly how many pages ahead the
+		 * prefetch iterator is.  Also, scan->prefetch_target tracks the
+		 * desired prefetch distance, which starts small and increases up to
+		 * the prefetch_maximum. This is to avoid doing a lot of prefetching
+		 * in a scan that stops after a few tuples because of a LIMIT.
+		 */
+#ifdef USE_PREFETCH
+		if (prefetch_maximum > 0)
+			tbm_begin_iterate(&scan->prefetch_iterator, node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		node->initialized = true;
 
 		goto new_page;
@@ -188,37 +206,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -241,23 +228,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
-		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If private, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!node->prefetch_iterator.exhausted &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -323,20 +296,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* release bitmaps and buffers if any */
-	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
-	/* Only used for serial BHS */
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -374,17 +338,15 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	if (scanDesc)
 	{
 		tbm_end_iterate(&scanDesc->iterator);
+		tbm_end_iterate(&scanDesc->prefetch_iterator);
 		table_endscan_bm(scanDesc);
 	}
 
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -417,17 +379,12 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->scan_in_progress = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -467,13 +424,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 92f7dd7390c..285c46db54a 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -20,8 +20,6 @@
 #include "access/skey.h"
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
-/* XXX: temporary include so lift and shift works */
-#include "nodes/execnodes.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -116,6 +114,17 @@ typedef struct BitmapHeapScanDesc
 
 	BlockNumber cblock;			/* current block # in scan, if any */
 
+	/* used to validate pf stays ahead of current block */
+	BlockNumber pfblock;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -123,7 +132,11 @@ typedef struct BitmapHeapScanDesc
 	 * block reported by the bitmap to determine how many NULL-filled tuples
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
+
+	/* page of VM containing info for current block */
 	Buffer		vmbuffer;
+	/* page of VM containing info for prefetch block */
+	Buffer		pvmbuffer;
 	int			empty_tuples_pending;
 } BitmapHeapScanDesc;
 
@@ -317,7 +330,8 @@ extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 extern void heap_endscan(TableScanDesc sscan);
 
 extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
-											  Snapshot snapshot, uint32 flags);
+											  Snapshot snapshot, uint32 flags,
+											  int prefetch_maximum);
 extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
 void		heap_endscan_bm(BitmapTableScanDesc *sscan);
 
@@ -388,14 +402,6 @@ extern void simple_heap_update(Relation relation, ItemPointer otid,
 extern TransactionId heap_index_delete_tuples(Relation rel,
 											  TM_IndexDeleteOp *delstate);
 
-/* in heapam_handler.c */
-extern void BitmapPrefetch(BitmapHeapScanState *node,
-						   BitmapTableScanDesc *scan);
-
-extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-
-extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-
 /* in heap/pruneheap.c */
 struct GlobalVisState;
 extern void heap_page_prune_opt(Relation relation, Buffer buffer);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 086fce35a8b..079bce61da8 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -57,10 +57,14 @@ typedef struct BitmapTableScanDesc
 	Relation	rel;			/* heap relation descriptor */
 	struct SnapshotData *snapshot;	/* snapshot to see */
 
+	struct ParallelBitmapHeapState *pstate;
+
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
 	TBMIterator iterator;
+	/* iterator for prefetching ahead of current page */
+	TBMIterator prefetch_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index f7f099b6449..a00b9bd296a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -354,7 +354,7 @@ typedef struct TableAmRoutine
 	 */
 	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
 										   Snapshot snapshot,
-										   uint32 flags);
+										   uint32 flags, int prefetch_maximum);
 
 	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
 
@@ -808,33 +808,26 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
+	 * Prepare to fetch / check / return tuples from as part of a bitmap table
+	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
+	 * bitmap is exhausted and true otherwise.
 	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
+	 * This will typically read and pin a block, and do the necessary work to
+	 * allow scan_bitmap_next_tuple() to return tuples (e.g. depending on the
+	 * table AM, it might make sense to perform tuple visibility checks at
+	 * this time).
 	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, `exact_pages` is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching future blocks indicated in the bitmap is left to the table
+	 * AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
-										   BlockNumber *blockno, bool *recheck,
+										   bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -968,14 +961,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   bool need_tuple)
+				   struct ParallelBitmapHeapState *pstate,
+				   bool need_tuple,
+				   int prefetch_maximum)
 {
+	BitmapTableScanDesc *result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
+	result = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, prefetch_maximum);
+	result->pstate = pstate;
+	return result;
 }
 
 /*
@@ -2004,7 +2002,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 static inline bool
 table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
-							 BlockNumber *blockno, bool *recheck,
+							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -2017,7 +2015,7 @@ table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
-														 blockno, recheck,
+														 recheck,
 														 lossy_pages, exact_pages);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0f34bac4baf..6b1c3bbe6fd 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1796,19 +1796,12 @@ typedef struct ParallelBitmapHeapState
  *      scandesc		   current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		scan_in_progress   is this a rescan
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1817,19 +1810,12 @@ typedef struct BitmapHeapScanState
 	struct BitmapTableScanDesc *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	bool		scan_in_progress;
-	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v22-0015-BitmapHeapScan-move-per-scan-setup-into-a-helper.patchtext/x-patch; charset=US-ASCII; name=v22-0015-BitmapHeapScan-move-per-scan-setup-into-a-helper.patchDownload
From 031afb1a17b21e076c506581eb2c0ee7f5b50aed Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:21:08 -0400
Subject: [PATCH v22 15/19] BitmapHeapScan: move per scan setup into a helper

Add BitmapTableScanSetup() which contains all of the code that must be
done on every scan of the table in a bitmap table scan.
This includes scanning the index, building the bitmap, and setting up
the scan descriptors.

Much of BitmapHeapNext() code was this setup, so it made sense to put it
in a helper function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 226 +++++++++++-----------
 1 file changed, 115 insertions(+), 111 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e3b8e8baa6a..e581e727f7e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,146 +53,150 @@ static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
-
-/* ----------------------------------------------------------------
- *		BitmapHeapNext
- *
- *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
- * ----------------------------------------------------------------
+/*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
  */
-static TupleTableSlot *
-BitmapHeapNext(BitmapHeapScanState *node)
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	BitmapTableScanDesc *scan;
-	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
+	int			prefetch_maximum = 0;
 
 	/*
-	 * extract necessary information from index scan node
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
 	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->scandesc;
+#ifdef USE_PREFETCH
+	Relation	rel = node->ss.ss_currentRelation;
+
+	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
 
 	/*
-	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
+	 * Scan the index, build the bitmap, and set up shared state for parallel.
 	 */
-	if (!node->initialized)
+	if (!pstate)
 	{
-		int			prefetch_maximum = 0;
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+	}
+	else if (BitmapShouldInitializeSharedState(pstate))
+	{
 		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
 		 */
-#ifdef USE_PREFETCH
-		Relation	rel = node->ss.ss_currentRelation;
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
 
-		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-#endif
+		/*
+		 * Two iterators are used -- one for the pages being scanned and one
+		 * for the blocks being prefetched.
+		 */
 
-		if (!pstate)
+		/*
+		 * Prepare to iterate over the TBM. This will return the dsa_pointer
+		 * of the iterator state which will be used by multiple processes to
+		 * iterate jointly.
+		 */
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+#ifdef USE_PREFETCH
+		if (prefetch_maximum > 0)
 		{
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
+			pstate->prefetch_iterator =
+				tbm_prepare_shared_iterate(node->tbm);
 		}
-		else if (BitmapShouldInitializeSharedState(pstate))
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-
-			/*
-			 * Two iterators are used -- one for the pages being scanned and
-			 * one for the blocks being prefetched.
-			 */
-
-			/*
-			 * Prepare to iterate over the TBM. This will return the
-			 * dsa_pointer of the iterator state which will be used by
-			 * multiple processes to iterate jointly.
-			 */
-			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
-#ifdef USE_PREFETCH
-			if (prefetch_maximum > 0)
-			{
-				pstate->prefetch_iterator =
-					tbm_prepare_shared_iterate(node->tbm);
-			}
 #endif
-			/* We have initialized the shared state so wake up others. */
-			BitmapDoneInitializingSharedState(pstate);
-		}
+		/* We have initialized the shared state so wake up others. */
+		BitmapDoneInitializingSharedState(pstate);
+	}
+
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!node->scan_in_progress)
+	{
+		bool		need_tuples = false;
 
 		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
 		 */
-		if (!node->scan_in_progress)
-		{
-			bool		need_tuples = false;
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
+		node->scandesc = table_beginscan_bm(node->ss.ss_currentRelation,
+											node->ss.ps.state->es_snapshot,
+											pstate,
+											need_tuples,
+											prefetch_maximum);
+		node->scan_in_progress = true;
+	}
+	else
+	{
+		Assert(node->scandesc);
+		tbm_end_iterate(&node->scandesc->iterator);
+		/* rescan to release any page pin */
+		table_rescan_bm(node->scandesc);
+	}
 
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  pstate,
-									  need_tuples,
-									  prefetch_maximum);
-			node->scandesc = scan;
-			node->scan_in_progress = true;
-		}
-		else
-		{
-			Assert(scan);
-			/* rescan to release any page pin */
-			tbm_end_iterate(&scan->iterator);
-			table_rescan_bm(scan);
-		}
+	tbm_begin_iterate(&node->scandesc->iterator, node->tbm, dsa,
+					  pstate ?
+					  pstate->tbmiterator :
+					  InvalidDsaPointer);
 
-		tbm_begin_iterate(&scan->iterator, node->tbm, dsa,
+	/*
+	 * We use *two* iterators, one for the pages we are actually scanning and
+	 * another that runs ahead of the first for prefetching.
+	 * scan->prefetch_pages tracks exactly how many pages ahead the prefetch
+	 * iterator is.  Also, scan->prefetch_target tracks the desired prefetch
+	 * distance, which starts small and increases up to the prefetch_maximum.
+	 * This is to avoid doing a lot of prefetching in a scan that stops after
+	 * a few tuples because of a LIMIT.
+	 */
+#ifdef USE_PREFETCH
+	if (prefetch_maximum > 0)
+		tbm_begin_iterate(&node->scandesc->prefetch_iterator, node->tbm, dsa,
 						  pstate ?
-						  pstate->tbmiterator :
+						  pstate->prefetch_iterator :
 						  InvalidDsaPointer);
-
-		/*
-		 * We use *two* iterators, one for the pages we are actually scanning
-		 * and another that runs ahead of the first for prefetching.
-		 * scan->prefetch_pages tracks exactly how many pages ahead the
-		 * prefetch iterator is.  Also, scan->prefetch_target tracks the
-		 * desired prefetch distance, which starts small and increases up to
-		 * the prefetch_maximum. This is to avoid doing a lot of prefetching
-		 * in a scan that stops after a few tuples because of a LIMIT.
-		 */
-#ifdef USE_PREFETCH
-		if (prefetch_maximum > 0)
-			tbm_begin_iterate(&scan->prefetch_iterator, node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 
-		node->initialized = true;
 
+	node->initialized = true;
+}
+
+/* ----------------------------------------------------------------
+ *		BitmapHeapNext
+ *
+ *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+BitmapHeapNext(BitmapHeapScanState *node)
+{
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
+	BitmapTableScanDesc *scan = node->scandesc;
+
+	/*
+	 * If we haven't yet performed the underlying index scan, do it, and begin
+	 * the iteration over the bitmap.
+	 */
+	if (!node->initialized)
+	{
+		BitmapTableScanSetup(node);
+		scan = node->scandesc;
 		goto new_page;
 	}
 
-- 
2.34.1

v22-0016-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v22-0016-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 52629bc9e45a7ba13e5714c381fc0c55b68ed025 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 18:02:38 -0400
Subject: [PATCH v22 16/19] Remove table AM callback scan_bitmap_next_block

Non block-based table AMs might find implementing bitmap table scan
somewhat easier by removing table_scan_bitmap_next_block(). Now bitmap
table scan code only calls table_scan_bitmap_next_tuple().

This commit turns the heap AM implementation of scan_bitmap_next_block()
into a local helper in heapam_handler.c.
---
 src/backend/access/heap/heapam_handler.c  | 58 +++++++++------
 src/backend/access/table/tableamapi.c     |  3 -
 src/backend/executor/nodeBitmapHeapscan.c | 63 ++++++++--------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 88 ++++++-----------------
 5 files changed, 88 insertions(+), 126 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e06054369d2..a97d835c815 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2334,18 +2334,22 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
 #endif							/* USE_PREFETCH */
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
+/*
+ * Prepare to fetch / check / return tuples as part of a bitmap heap scan.
+ * `scan` needs to have been started via heap_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set to indicate whether or not the tuples from this block
+ * should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  */
-
 static bool
-heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
+heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2515,9 +2519,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
 	return true;
 }
 
+
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	ParallelBitmapHeapState *pstate = sscan->pstate;
@@ -2525,22 +2536,28 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 	Page		page;
 	ItemId		lp;
 
-	if (scan->empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		scan->empty_tuples_pending--;
-		BitmapPrefetch(scan);
-		return true;
-	}
+		if (scan->empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			scan->empty_tuples_pending--;
+			BitmapPrefetch(scan);
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2941,7 +2958,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index e9b598256fb..a47527d490a 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e581e727f7e..badc4b98dc5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -185,56 +185,49 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext = node->ss.ps.ps_ExprContext;
-	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
-	BitmapTableScanDesc *scan = node->scandesc;
+	ExprContext *econtext;
+	TupleTableSlot *slot;
+	BitmapTableScanDesc *scan;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->scandesc;
-		goto new_page;
-	}
 
-	for (;;)
+	scan = node->scandesc;
+	econtext = node->ss.ps.ps_ExprContext;
+	slot = node->ss.ss_ScanTupleSlot;
+
+	while (table_scan_bitmap_next_tuple(scan, slot,
+										&node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+		/*
+		 * Continuing in previously obtained page.
+		 */
 
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		if (!table_scan_bitmap_next_block(scan, &node->recheck,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 775955363ef..c11ff3a1bae 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -324,7 +324,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a00b9bd296a..d496d68f1c2 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -808,37 +808,20 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from as part of a bitmap table
-	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
-	 * bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin a block, and do the necessary work to
-	 * allow scan_bitmap_next_tuple() to return tuples (e.g. depending on the
-	 * table AM, it might make sense to perform tuple visibility checks at
-	 * this time).
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
-	 * block; otherwise, `exact_pages` is incremented.
-	 *
-	 * Prefetching future blocks indicated in the bitmap is left to the table
-	 * AM.
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
-										   bool *recheck,
-										   long *lossy_pages, long *exact_pages);
-
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
 	bool		(*scan_bitmap_next_tuple) (BitmapTableScanDesc *scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot, bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1982,54 +1965,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * ----------------------------------------------------------------------------
  */
 
+
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
- * incremented if the block's representation in the bitmap is lossy; otherwise,
- * `exact_pages` is incremented.
- *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked. Tuples from lossy pages will always
- * need to be rechecked, but some non-lossy pages' tuples may also require
- * recheck.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `blockno` is only used in bitmap table scan code to validate that the
- * prefetch block is staying ahead of the current block.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
+table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
-														 recheck,
-														 lossy_pages, exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2040,7 +1995,8 @@ table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rel->rd_tableam->scan_bitmap_next_tuple(scan,
-														 slot);
+														 slot, recheck,
+														 lossy_pages, exact_pages);
 }
 
 /*
-- 
2.34.1

v22-0018-Separate-TBMIterator-and-TBMIterateResult.patchtext/x-patch; charset=US-ASCII; name=v22-0018-Separate-TBMIterator-and-TBMIterateResult.patchDownload
From 67aefde0849262e6229d16f52b68274996798039 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 17:09:50 -0400
Subject: [PATCH v22 18/19] Separate TBMIterator and TBMIterateResult

Remove the TBMIterateResult from the TBMSerialIterator and
TBMSharedIterator and have tbm_[shared_]iterate() take a
TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c          | 49 +++++++++------
 src/backend/access/gin/ginscan.c         |  2 +-
 src/backend/access/heap/heapam_handler.c | 66 ++++++++++----------
 src/backend/nodes/tidbitmap.c            | 77 ++++++++++++------------
 src/include/access/gin_private.h         |  2 +-
 src/include/nodes/tidbitmap.h            |  6 +-
 6 files changed, 108 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 9c53ca19f06..33226603407 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,7 +332,20 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -374,6 +387,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_private_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +837,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_serial_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -858,10 +873,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +890,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 5b9a0eaea73..09e1586c4ac 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a97d835c815..7b9a9999ec7 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2132,17 +2132,19 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 		{
 			while (scan->prefetch_pages < scan->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				scan->prefetch_pages++;
-				scan->pfblock = tbmpre->blockno;
+				scan->pfblock = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2151,13 +2153,13 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -2172,7 +2174,7 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -2191,25 +2193,25 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				scan->pfblock = tbmpre->blockno;
+				scan->pfblock = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
@@ -2228,7 +2230,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = scan->base.pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -2242,8 +2244,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblock = tbmpre.blockno;
 		}
 		return;
 	}
@@ -2282,8 +2284,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 			 */
 			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblock = tbmpre.blockno;
 			}
 		}
 	}
@@ -2354,7 +2356,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	scan->vis_idx = 0;
 	scan->vis_ntuples = 0;
@@ -2367,9 +2369,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->base.iterator);
+		tbm_iterate(&scan->base.iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
 		/*
@@ -2380,11 +2382,11 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= scan->nblocks);
 
 	/* Got a valid block */
-	block = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	block = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2392,14 +2394,14 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->base.flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->base.rel, tbmres.blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(scan->empty_tuples_pending >= 0);
 
-		scan->empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
@@ -2431,7 +2433,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2440,9 +2442,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2492,7 +2494,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	scan->vis_ntuples = ntup;
 
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 011d0353a1a..ccee2e1937d 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -948,22 +946,22 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  If result->ntuples
+ * < 0, then the bitmap is "lossy" and failed to remember the exact tuples to
+ * look at on this page --- the caller must examine all tuples on the page and
+ * check if they meet the intended condition.  If result->recheck is true, only
+ * the indicated tuples need be examined, but the condition must be rechecked
+ * anyway.  (For ease of testing, recheck is always set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
+	Assert(tbmres);
 
 	/*
 	 * If lossy chunk pages remain, make sure we've advanced schunkptr/
@@ -999,11 +997,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1019,16 +1017,16 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1038,10 +1036,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1092,13 +1089,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1108,21 +1105,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1592,14 +1589,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
 	Assert(!iterator->exhausted);
 
 	if (iterator->private)
-		return tbm_private_iterate(iterator->private);
+		tbm_private_iterate(iterator->private, tbmres);
 	else
-		return tbm_shared_iterate(iterator->parallel);
+		tbm_shared_iterate(iterator->parallel, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 78800509367..b528ab715f1 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 7efb5ac4ca8..59981a99586 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -83,8 +83,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -94,7 +94,7 @@ extern long tbm_calculate_entries(double maxbytes);
 extern void tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
 							  dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 
 #endif							/* TIDBITMAP_H */
-- 
2.34.1

v22-0017-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-patch; charset=US-ASCII; name=v22-0017-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From 06e19ed23305e36355ed1878fccd2380a54fa2f7 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 16:25:14 -0400
Subject: [PATCH v22 17/19] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 25 +++++++------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 6d1fbcb03e9..011d0353a1a 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,8 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1467,8 +1457,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 472c0b444bf..7efb5ac4ca8 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /*
-- 
2.34.1

v22-0019-Use-streaming-I-O-in-Bitmap-Heap-Scans.patchtext/x-patch; charset=US-ASCII; name=v22-0019-Use-streaming-I-O-in-Bitmap-Heap-Scans.patchDownload
From bb03c690016244bac013ecef943dfad9ec33d8ee Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 18:11:57 -0400
Subject: [PATCH v22 19/19] Use streaming I/O in Bitmap Heap Scans

Instead of calling ReadBuffer() for each block, bitmap heap scans now
use the streaming API introduced in b5a9b18cd0.

The read stream API prefetches blocks from the bitmap, so this commit
removes all of the bespoke bitmap heap scan prefetch code.

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  79 ++++-
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  70 +----
 src/include/access/heapam.h               |  14 +-
 src/include/access/relscan.h              |   4 -
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   6 -
 7 files changed, 115 insertions(+), 416 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 9847ce2c3aa..211233cd147 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -285,6 +285,59 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+static BlockNumber
+heap_bitmap_scan_stream_read_next(ReadStream *stream,
+								  void *callback_private_data,
+								  void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc *scan = callback_private_data;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&scan->base.iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(scan->base.flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
+		{
+			/* can't be lossy in the skip_fetch case */
+			Assert(tbmres->ntuples >= 0);
+			Assert(scan->empty_tuples_pending >= 0);
+
+			scan->empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1230,8 +1283,7 @@ heap_endscan(TableScanDesc sscan)
 }
 
 BitmapTableScanDesc *
-heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
-				  int prefetch_maximum)
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 {
 	BitmapHeapScanDesc *scan;
 
@@ -1268,11 +1320,13 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
 	scan->pvmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
-	scan->prefetch_maximum = prefetch_maximum;
-
-	/* Only used for serial BHS */
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
+	scan->read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+												   NULL,
+												   scan->base.rel,
+												   MAIN_FORKNUM,
+												   heap_bitmap_scan_stream_read_next,
+												   scan,
+												   sizeof(TBMIterateResult));
 
 	return (BitmapTableScanDesc *) scan;
 }
@@ -1282,6 +1336,10 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	/* Reset the read stream on rescan. */
+	if (scan->read_stream)
+		read_stream_reset(scan->read_stream);
+
 	if (BufferIsValid(scan->cbuf))
 	{
 		ReleaseBuffer(scan->cbuf);
@@ -1313,10 +1371,6 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->ctup.t_data = NULL;
 	ItemPointerSetInvalid(&scan->ctup.t_self);
-
-	/* Only used for serial BHS */
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 }
 
 void
@@ -1324,6 +1378,9 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	if (scan->read_stream)
+		read_stream_end(scan->read_stream);
+
 	if (BufferIsValid(scan->cbuf))
 		ReleaseBuffer(scan->cbuf);
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7b9a9999ec7..93c630a0fbe 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,9 +54,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
-static inline void BitmapPrefetch(BitmapHeapScanDesc *scan);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan);
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 static const TableAmRoutine heapam_methods;
@@ -2115,227 +2112,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblock = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				scan->pfblock = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblock = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (scan->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblock = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= scan->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
-			scan->prefetch_target = scan->prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < scan->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= scan->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
-			pstate->prefetch_target = scan->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap heap scan.
  * `scan` needs to have been started via heap_beginscan_bm(). Returns false if
@@ -2356,63 +2132,52 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+	void	   *per_buffer_data;
+
+	Assert(scan->read_stream);
 
 	scan->vis_idx = 0;
 	scan->vis_ntuples = 0;
 
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(scan);
-
-	do
+	if (BufferIsValid(scan->cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		tbm_iterate(&scan->base.iterator, &tbmres);
+		ReleaseBuffer(scan->cbuf);
+		scan->cbuf = InvalidBuffer;
+	}
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	scan->cbuf = read_stream_next_buffer(scan->read_stream, &per_buffer_data);
 
+	if (BufferIsInvalid(scan->cbuf))
+	{
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= scan->nblocks);
+		*recheck = false;
+		return scan->empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	block = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->base.flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->base.rel, tbmres.blockno, &scan->vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(scan->empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		scan->empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(scan->cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	/* Got a valid block */
+	block = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
+	scan->cblock = tbmres->blockno;
+	scan->vis_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	scan->cbuf = ReleaseAndReadBuffer(scan->cbuf,
-									  scan->base.rel,
-									  block);
-	scan->cblock = block;
 	buffer = scan->cbuf;
 	snapshot = scan->base.snapshot;
 
@@ -2433,7 +2198,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2442,9 +2207,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2494,23 +2259,11 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	scan->vis_ntuples = ntup;
 
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->base.pstate == NULL &&
-		!scan->base.prefetch_iterator.exhausted &&
-		scan->pfblock < block)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(scan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2533,7 +2286,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
-	ParallelBitmapHeapState *pstate = sscan->pstate;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
@@ -2553,7 +2305,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 			 */
 			ExecStoreAllNullTuple(slot);
 			scan->empty_tuples_pending--;
-			BitmapPrefetch(scan);
 			return true;
 		}
 
@@ -2561,36 +2312,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!pstate)
-	{
-		if (scan->prefetch_target < scan->prefetch_maximum)
-			scan->prefetch_target++;
-	}
-	else if (pstate->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target < scan->prefetch_maximum)
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(scan);
-
 	targoffset = scan->vis_tuples[scan->vis_idx];
 	page = BufferGetPage(scan->cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index badc4b98dc5..85ec9b8e9db 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -63,17 +63,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 {
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
-	int			prefetch_maximum = 0;
-
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-#ifdef USE_PREFETCH
-	Relation	rel = node->ss.ss_currentRelation;
-
-	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-#endif
 
 	/*
 	 * Scan the index, build the bitmap, and set up shared state for parallel.
@@ -95,24 +84,13 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 			elog(ERROR, "unrecognized result from subplan");
 
-		/*
-		 * Two iterators are used -- one for the pages being scanned and one
-		 * for the blocks being prefetched.
-		 */
-
 		/*
 		 * Prepare to iterate over the TBM. This will return the dsa_pointer
 		 * of the iterator state which will be used by multiple processes to
 		 * iterate jointly.
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
-#ifdef USE_PREFETCH
-		if (prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif
+
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -137,9 +115,7 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 
 		node->scandesc = table_beginscan_bm(node->ss.ss_currentRelation,
 											node->ss.ps.state->es_snapshot,
-											pstate,
-											need_tuples,
-											prefetch_maximum);
+											need_tuples);
 		node->scan_in_progress = true;
 	}
 	else
@@ -155,24 +131,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
 
-	/*
-	 * We use *two* iterators, one for the pages we are actually scanning and
-	 * another that runs ahead of the first for prefetching.
-	 * scan->prefetch_pages tracks exactly how many pages ahead the prefetch
-	 * iterator is.  Also, scan->prefetch_target tracks the desired prefetch
-	 * distance, which starts small and increases up to the prefetch_maximum.
-	 * This is to avoid doing a lot of prefetching in a scan that stops after
-	 * a few tuples because of a LIMIT.
-	 */
-#ifdef USE_PREFETCH
-	if (prefetch_maximum > 0)
-		tbm_begin_iterate(&node->scandesc->prefetch_iterator, node->tbm, dsa,
-						  pstate ?
-						  pstate->prefetch_iterator :
-						  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
-
 	node->initialized = true;
 }
 
@@ -323,22 +281,21 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	scanDesc = node->scandesc;
 
-	/*
-	 * close down subplans
-	 */
-	ExecEndNode(outerPlanState(node));
-
-
 	/*
 	 * close heap scan
 	 */
 	if (scanDesc)
 	{
 		tbm_end_iterate(&scanDesc->iterator);
-		tbm_end_iterate(&scanDesc->prefetch_iterator);
 		table_endscan_bm(scanDesc);
 	}
 
+	/*
+	 * close down subplans
+	 */
+	ExecEndNode(outerPlanState(node));
+
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
@@ -499,12 +456,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -531,17 +485,9 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
-	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 285c46db54a..b78781d05c9 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -114,16 +114,7 @@ typedef struct BitmapHeapScanDesc
 
 	BlockNumber cblock;			/* current block # in scan, if any */
 
-	/* used to validate pf stays ahead of current block */
-	BlockNumber pfblock;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
-
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
+	ReadStream *read_stream;
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -330,8 +321,7 @@ extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 extern void heap_endscan(TableScanDesc sscan);
 
 extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
-											  Snapshot snapshot, uint32 flags,
-											  int prefetch_maximum);
+											  Snapshot snapshot, uint32 flags);
 extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
 void		heap_endscan_bm(BitmapTableScanDesc *sscan);
 
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 079bce61da8..086fce35a8b 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -57,14 +57,10 @@ typedef struct BitmapTableScanDesc
 	Relation	rel;			/* heap relation descriptor */
 	struct SnapshotData *snapshot;	/* snapshot to see */
 
-	struct ParallelBitmapHeapState *pstate;
-
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
 	TBMIterator iterator;
-	/* iterator for prefetching ahead of current page */
-	TBMIterator prefetch_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d496d68f1c2..632a07c7a0c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -354,7 +354,7 @@ typedef struct TableAmRoutine
 	 */
 	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
 										   Snapshot snapshot,
-										   uint32 flags, int prefetch_maximum);
+										   uint32 flags);
 
 	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
 
@@ -944,19 +944,14 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   struct ParallelBitmapHeapState *pstate,
-				   bool need_tuple,
-				   int prefetch_maximum)
+				   bool need_tuple)
 {
-	BitmapTableScanDesc *result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, prefetch_maximum);
-	result->pstate = pstate;
-	return result;
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6b1c3bbe6fd..776ca6cea13 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1770,11 +1770,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1782,10 +1779,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.34.1

v22-0008-Push-current-scan-descriptor-into-specialized-sc.patchtext/x-patch; charset=US-ASCII; name=v22-0008-Push-current-scan-descriptor-into-specialized-sc.patchDownload
From 6c6703e9a1fda3d57f813918b63bd992caa34f21 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:41:49 -0400
Subject: [PATCH v22 08/19] Push current scan descriptor into specialized scan
 states

To allow Bitmap Table Scans to use a forthcoming bitmap table-specific
scan descriptor in table AM-agnostic code, move the current scan
descriptor out of the generic ScanState node.

This adds a bit of duplication, but a few of the scan types don't use
the current scan descriptor anyway. Additionally, for many scan types,
the scan descriptor is initialized later in execution than the other
members of the generic ScanState.
---
 src/backend/executor/nodeBitmapHeapscan.c  | 10 +++++-----
 src/backend/executor/nodeBitmapIndexscan.c |  1 -
 src/backend/executor/nodeIndexonlyscan.c   |  1 -
 src/backend/executor/nodeIndexscan.c       |  1 -
 src/backend/executor/nodeSamplescan.c      | 14 +++++++-------
 src/backend/executor/nodeSeqscan.c         | 14 +++++++-------
 src/backend/executor/nodeTidrangescan.c    |  8 ++++----
 src/backend/executor/nodeTidscan.c         | 18 +++++++++---------
 src/include/nodes/execnodes.h              | 10 ++++++++--
 9 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 33e4ef13bd6..b841eee58b4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -78,7 +78,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -162,7 +162,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  NULL,
 									  need_tuples);
 
-			node->ss.ss_currentScanDesc = scan;
+			node->ss_currentScanDesc = scan;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -539,8 +539,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss_currentScanDesc)
+		table_rescan(node->ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	tbm_end_iterate(&node->prefetch_iterator);
@@ -580,7 +580,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * extract information from the node
 	 */
-	scanDesc = node->ss.ss_currentScanDesc;
+	scanDesc = node->ss_currentScanDesc;
 
 	/*
 	 * close down subplans
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index 6df8e17ec84..b4af2f17ed4 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -225,7 +225,6 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
 	 */
 
 	indexstate->ss.ss_currentRelation = NULL;
-	indexstate->ss.ss_currentScanDesc = NULL;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index b49194c0167..194c544c167 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -534,7 +534,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	indexstate->ss.ss_currentRelation = currentRelation;
-	indexstate->ss.ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * Build the scan tuple type using the indextlist generated by the
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 8000feff4c9..8260cb0954d 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -910,7 +910,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	indexstate->ss.ss_currentRelation = currentRelation;
-	indexstate->ss.ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 714b076e646..d15bf249d31 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -123,7 +123,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 							 eflags);
 
 	/* we won't set up the HeapScanDesc till later */
-	scanstate->ss.ss_currentScanDesc = NULL;
+	scanstate->ss_currentScanDesc = NULL;
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
@@ -187,8 +187,8 @@ ExecEndSampleScan(SampleScanState *node)
 	/*
 	 * close heap scan
 	 */
-	if (node->ss.ss_currentScanDesc)
-		table_endscan(node->ss.ss_currentScanDesc);
+	if (node->ss_currentScanDesc)
+		table_endscan(node->ss_currentScanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -289,9 +289,9 @@ tablesample_init(SampleScanState *scanstate)
 	allow_sync = (tsm->NextSampleBlock == NULL);
 
 	/* Now we can create or reset the HeapScanDesc */
-	if (scanstate->ss.ss_currentScanDesc == NULL)
+	if (scanstate->ss_currentScanDesc == NULL)
 	{
-		scanstate->ss.ss_currentScanDesc =
+		scanstate->ss_currentScanDesc =
 			table_beginscan_sampling(scanstate->ss.ss_currentRelation,
 									 scanstate->ss.ps.state->es_snapshot,
 									 0, NULL,
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
 	}
 	else
 	{
-		table_rescan_set_params(scanstate->ss.ss_currentScanDesc, NULL,
+		table_rescan_set_params(scanstate->ss_currentScanDesc, NULL,
 								scanstate->use_bulkread,
 								allow_sync,
 								scanstate->use_pagemode);
@@ -319,7 +319,7 @@ tablesample_init(SampleScanState *scanstate)
 static TupleTableSlot *
 tablesample_getnext(SampleScanState *scanstate)
 {
-	TableScanDesc scan = scanstate->ss.ss_currentScanDesc;
+	TableScanDesc scan = scanstate->ss_currentScanDesc;
 	TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
 
 	ExecClearTuple(slot);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 7cb12a11c2d..89f5e8c80da 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -57,7 +57,7 @@ SeqNext(SeqScanState *node)
 	/*
 	 * get information from the estate and scan state
 	 */
-	scandesc = node->ss.ss_currentScanDesc;
+	scandesc = node->ss_currentScanDesc;
 	estate = node->ss.ps.state;
 	direction = estate->es_direction;
 	slot = node->ss.ss_ScanTupleSlot;
@@ -71,7 +71,7 @@ SeqNext(SeqScanState *node)
 		scandesc = table_beginscan(node->ss.ss_currentRelation,
 								   estate->es_snapshot,
 								   0, NULL);
-		node->ss.ss_currentScanDesc = scandesc;
+		node->ss_currentScanDesc = scandesc;
 	}
 
 	/*
@@ -188,7 +188,7 @@ ExecEndSeqScan(SeqScanState *node)
 	/*
 	 * get information from node
 	 */
-	scanDesc = node->ss.ss_currentScanDesc;
+	scanDesc = node->ss_currentScanDesc;
 
 	/*
 	 * close heap scan
@@ -213,7 +213,7 @@ ExecReScanSeqScan(SeqScanState *node)
 {
 	TableScanDesc scan;
 
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 
 	if (scan != NULL)
 		table_rescan(scan,		/* scan desc */
@@ -264,7 +264,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 								  pscan,
 								  estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss.ss_currentScanDesc =
+	node->ss_currentScanDesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
 
@@ -280,7 +280,7 @@ ExecSeqScanReInitializeDSM(SeqScanState *node,
 {
 	ParallelTableScanDesc pscan;
 
-	pscan = node->ss.ss_currentScanDesc->rs_parallel;
+	pscan = node->ss_currentScanDesc->rs_parallel;
 	table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
 }
 
@@ -297,6 +297,6 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
 	ParallelTableScanDesc pscan;
 
 	pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
-	node->ss.ss_currentScanDesc =
+	node->ss_currentScanDesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index 9aa7683d7e3..bc523a5d773 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -227,7 +227,7 @@ TidRangeNext(TidRangeScanState *node)
 	/*
 	 * extract necessary information from TID scan node
 	 */
-	scandesc = node->ss.ss_currentScanDesc;
+	scandesc = node->ss_currentScanDesc;
 	estate = node->ss.ps.state;
 	slot = node->ss.ss_ScanTupleSlot;
 	direction = estate->es_direction;
@@ -244,7 +244,7 @@ TidRangeNext(TidRangeScanState *node)
 												estate->es_snapshot,
 												&node->trss_mintid,
 												&node->trss_maxtid);
-			node->ss.ss_currentScanDesc = scandesc;
+			node->ss_currentScanDesc = scandesc;
 		}
 		else
 		{
@@ -326,7 +326,7 @@ ExecReScanTidRangeScan(TidRangeScanState *node)
 void
 ExecEndTidRangeScan(TidRangeScanState *node)
 {
-	TableScanDesc scan = node->ss.ss_currentScanDesc;
+	TableScanDesc scan = node->ss_currentScanDesc;
 
 	if (scan != NULL)
 		table_endscan(scan);
@@ -375,7 +375,7 @@ ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidrangestate->ss.ss_currentRelation = currentRelation;
-	tidrangestate->ss.ss_currentScanDesc = NULL;	/* no table scan here */
+	tidrangestate->ss_currentScanDesc = NULL;	/* no table scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 864a9013b62..f08bc7daa89 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -145,11 +145,11 @@ TidListEval(TidScanState *tidstate)
 	 * the size of the table), so it makes sense to delay that until needed -
 	 * the node might never get executed.
 	 */
-	if (tidstate->ss.ss_currentScanDesc == NULL)
-		tidstate->ss.ss_currentScanDesc =
+	if (tidstate->ss_currentScanDesc == NULL)
+		tidstate->ss_currentScanDesc =
 			table_beginscan_tid(tidstate->ss.ss_currentRelation,
 								tidstate->ss.ps.state->es_snapshot);
-	scan = tidstate->ss.ss_currentScanDesc;
+	scan = tidstate->ss_currentScanDesc;
 
 	/*
 	 * We initialize the array with enough slots for the case that all quals
@@ -336,7 +336,7 @@ TidNext(TidScanState *node)
 	if (node->tss_TidList == NULL)
 		TidListEval(node);
 
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 	tidList = node->tss_TidList;
 	numTids = node->tss_NumTids;
 
@@ -453,8 +453,8 @@ ExecReScanTidScan(TidScanState *node)
 	node->tss_TidPtr = -1;
 
 	/* not really necessary, but seems good form */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss_currentScanDesc)
+		table_rescan(node->ss_currentScanDesc, NULL);
 
 	ExecScanReScan(&node->ss);
 }
@@ -469,8 +469,8 @@ ExecReScanTidScan(TidScanState *node)
 void
 ExecEndTidScan(TidScanState *node)
 {
-	if (node->ss.ss_currentScanDesc)
-		table_endscan(node->ss.ss_currentScanDesc);
+	if (node->ss_currentScanDesc)
+		table_endscan(node->ss_currentScanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -518,7 +518,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidstate->ss.ss_currentRelation = currentRelation;
-	tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
+	tidstate->ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 1f262db776c..62bc883bc28 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1555,7 +1555,6 @@ typedef struct BitmapOrState
  *		retrieved from the subplan.
  *
  *		currentRelation    relation being scanned (NULL if none)
- *		currentScanDesc    current scan descriptor for scan (NULL if none)
  *		ScanTupleSlot	   pointer to slot in tuple table holding scan tuple
  * ----------------
  */
@@ -1563,7 +1562,6 @@ typedef struct ScanState
 {
 	PlanState	ps;				/* its first field is NodeTag */
 	Relation	ss_currentRelation;
-	struct TableScanDescData *ss_currentScanDesc;
 	TupleTableSlot *ss_ScanTupleSlot;
 } ScanState;
 
@@ -1574,6 +1572,7 @@ typedef struct ScanState
 typedef struct SeqScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
 	Size		pscan_len;		/* size of parallel heap scan descriptor */
 } SeqScanState;
 
@@ -1584,6 +1583,7 @@ typedef struct SeqScanState
 typedef struct SampleScanState
 {
 	ScanState	ss;
+	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
 	List	   *args;			/* expr states for TABLESAMPLE params */
 	ExprState  *repeatable;		/* expr state for REPEATABLE expr */
 	/* use struct pointer to avoid including tsmapi.h here */
@@ -1793,6 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1812,6 +1813,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
@@ -1831,6 +1833,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1841,6 +1844,7 @@ typedef struct BitmapHeapScanState
 typedef struct TidScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	List	   *tss_tidexprs;
 	bool		tss_isCurrentOf;
 	int			tss_NumTids;
@@ -1851,6 +1855,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
@@ -1860,6 +1865,7 @@ typedef struct TidScanState
 typedef struct TidRangeScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	List	   *trss_tidexprs;
 	ItemPointerData trss_mintid;
 	ItemPointerData trss_maxtid;
-- 
2.34.1

v22-0009-Remove-ss_current-prefix-from-ss_currentScanDesc.patchtext/x-patch; charset=US-ASCII; name=v22-0009-Remove-ss_current-prefix-from-ss_currentScanDesc.patchDownload
From 2aa0b7482e93487771919d200957c4faa0f7e037 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:44:50 -0400
Subject: [PATCH v22 09/19] Remove ss_current prefix from ss_currentScanDesc in
 nodes

A previous commit pushed down the current scan descriptor from the
generic ScanState into the specialized scan states. The naming
convention was left as is to make the diff easier to understand. Rename
it, as the ss_ prefix is no longer correct once this member is in the
other node structs.
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/backend/executor/nodeSamplescan.c     | 14 +++++++-------
 src/backend/executor/nodeSeqscan.c        | 14 +++++++-------
 src/backend/executor/nodeTidrangescan.c   |  8 ++++----
 src/backend/executor/nodeTidscan.c        | 18 +++++++++---------
 src/include/nodes/execnodes.h             | 16 ++++++++--------
 6 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b841eee58b4..84ad3a92585 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -78,7 +78,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -162,7 +162,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  NULL,
 									  need_tuples);
 
-			node->ss_currentScanDesc = scan;
+			node->scandesc = scan;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -539,8 +539,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	if (node->ss_currentScanDesc)
-		table_rescan(node->ss_currentScanDesc, NULL);
+	if (node->scandesc)
+		table_rescan(node->scandesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	tbm_end_iterate(&node->prefetch_iterator);
@@ -580,7 +580,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * extract information from the node
 	 */
-	scanDesc = node->ss_currentScanDesc;
+	scanDesc = node->scandesc;
 
 	/*
 	 * close down subplans
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index d15bf249d31..581bd3ed3b1 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -123,7 +123,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 							 eflags);
 
 	/* we won't set up the HeapScanDesc till later */
-	scanstate->ss_currentScanDesc = NULL;
+	scanstate->scandesc = NULL;
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
@@ -187,8 +187,8 @@ ExecEndSampleScan(SampleScanState *node)
 	/*
 	 * close heap scan
 	 */
-	if (node->ss_currentScanDesc)
-		table_endscan(node->ss_currentScanDesc);
+	if (node->scandesc)
+		table_endscan(node->scandesc);
 }
 
 /* ----------------------------------------------------------------
@@ -289,9 +289,9 @@ tablesample_init(SampleScanState *scanstate)
 	allow_sync = (tsm->NextSampleBlock == NULL);
 
 	/* Now we can create or reset the HeapScanDesc */
-	if (scanstate->ss_currentScanDesc == NULL)
+	if (scanstate->scandesc == NULL)
 	{
-		scanstate->ss_currentScanDesc =
+		scanstate->scandesc =
 			table_beginscan_sampling(scanstate->ss.ss_currentRelation,
 									 scanstate->ss.ps.state->es_snapshot,
 									 0, NULL,
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
 	}
 	else
 	{
-		table_rescan_set_params(scanstate->ss_currentScanDesc, NULL,
+		table_rescan_set_params(scanstate->scandesc, NULL,
 								scanstate->use_bulkread,
 								allow_sync,
 								scanstate->use_pagemode);
@@ -319,7 +319,7 @@ tablesample_init(SampleScanState *scanstate)
 static TupleTableSlot *
 tablesample_getnext(SampleScanState *scanstate)
 {
-	TableScanDesc scan = scanstate->ss_currentScanDesc;
+	TableScanDesc scan = scanstate->scandesc;
 	TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
 
 	ExecClearTuple(slot);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 89f5e8c80da..5aaad645950 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -57,7 +57,7 @@ SeqNext(SeqScanState *node)
 	/*
 	 * get information from the estate and scan state
 	 */
-	scandesc = node->ss_currentScanDesc;
+	scandesc = node->scandesc;
 	estate = node->ss.ps.state;
 	direction = estate->es_direction;
 	slot = node->ss.ss_ScanTupleSlot;
@@ -71,7 +71,7 @@ SeqNext(SeqScanState *node)
 		scandesc = table_beginscan(node->ss.ss_currentRelation,
 								   estate->es_snapshot,
 								   0, NULL);
-		node->ss_currentScanDesc = scandesc;
+		node->scandesc = scandesc;
 	}
 
 	/*
@@ -188,7 +188,7 @@ ExecEndSeqScan(SeqScanState *node)
 	/*
 	 * get information from node
 	 */
-	scanDesc = node->ss_currentScanDesc;
+	scanDesc = node->scandesc;
 
 	/*
 	 * close heap scan
@@ -213,7 +213,7 @@ ExecReScanSeqScan(SeqScanState *node)
 {
 	TableScanDesc scan;
 
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 
 	if (scan != NULL)
 		table_rescan(scan,		/* scan desc */
@@ -264,7 +264,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 								  pscan,
 								  estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss_currentScanDesc =
+	node->scandesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
 
@@ -280,7 +280,7 @@ ExecSeqScanReInitializeDSM(SeqScanState *node,
 {
 	ParallelTableScanDesc pscan;
 
-	pscan = node->ss_currentScanDesc->rs_parallel;
+	pscan = node->scandesc->rs_parallel;
 	table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
 }
 
@@ -297,6 +297,6 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
 	ParallelTableScanDesc pscan;
 
 	pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
-	node->ss_currentScanDesc =
+	node->scandesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index bc523a5d773..3a2ba169e9d 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -227,7 +227,7 @@ TidRangeNext(TidRangeScanState *node)
 	/*
 	 * extract necessary information from TID scan node
 	 */
-	scandesc = node->ss_currentScanDesc;
+	scandesc = node->scandesc;
 	estate = node->ss.ps.state;
 	slot = node->ss.ss_ScanTupleSlot;
 	direction = estate->es_direction;
@@ -244,7 +244,7 @@ TidRangeNext(TidRangeScanState *node)
 												estate->es_snapshot,
 												&node->trss_mintid,
 												&node->trss_maxtid);
-			node->ss_currentScanDesc = scandesc;
+			node->scandesc = scandesc;
 		}
 		else
 		{
@@ -326,7 +326,7 @@ ExecReScanTidRangeScan(TidRangeScanState *node)
 void
 ExecEndTidRangeScan(TidRangeScanState *node)
 {
-	TableScanDesc scan = node->ss_currentScanDesc;
+	TableScanDesc scan = node->scandesc;
 
 	if (scan != NULL)
 		table_endscan(scan);
@@ -375,7 +375,7 @@ ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidrangestate->ss.ss_currentRelation = currentRelation;
-	tidrangestate->ss_currentScanDesc = NULL;	/* no table scan here */
+	tidrangestate->scandesc = NULL; /* no table scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index f08bc7daa89..becf0274678 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -145,11 +145,11 @@ TidListEval(TidScanState *tidstate)
 	 * the size of the table), so it makes sense to delay that until needed -
 	 * the node might never get executed.
 	 */
-	if (tidstate->ss_currentScanDesc == NULL)
-		tidstate->ss_currentScanDesc =
+	if (tidstate->scandesc == NULL)
+		tidstate->scandesc =
 			table_beginscan_tid(tidstate->ss.ss_currentRelation,
 								tidstate->ss.ps.state->es_snapshot);
-	scan = tidstate->ss_currentScanDesc;
+	scan = tidstate->scandesc;
 
 	/*
 	 * We initialize the array with enough slots for the case that all quals
@@ -336,7 +336,7 @@ TidNext(TidScanState *node)
 	if (node->tss_TidList == NULL)
 		TidListEval(node);
 
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 	tidList = node->tss_TidList;
 	numTids = node->tss_NumTids;
 
@@ -453,8 +453,8 @@ ExecReScanTidScan(TidScanState *node)
 	node->tss_TidPtr = -1;
 
 	/* not really necessary, but seems good form */
-	if (node->ss_currentScanDesc)
-		table_rescan(node->ss_currentScanDesc, NULL);
+	if (node->scandesc)
+		table_rescan(node->scandesc, NULL);
 
 	ExecScanReScan(&node->ss);
 }
@@ -469,8 +469,8 @@ ExecReScanTidScan(TidScanState *node)
 void
 ExecEndTidScan(TidScanState *node)
 {
-	if (node->ss_currentScanDesc)
-		table_endscan(node->ss_currentScanDesc);
+	if (node->scandesc)
+		table_endscan(node->scandesc);
 }
 
 /* ----------------------------------------------------------------
@@ -518,7 +518,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidstate->ss.ss_currentRelation = currentRelation;
-	tidstate->ss_currentScanDesc = NULL;	/* no heap scan here */
+	tidstate->scandesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 62bc883bc28..ebba73d9b8b 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1572,7 +1572,7 @@ typedef struct ScanState
 typedef struct SeqScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
+	struct TableScanDescData *scandesc; /* current scan descriptor */
 	Size		pscan_len;		/* size of parallel heap scan descriptor */
 } SeqScanState;
 
@@ -1583,7 +1583,7 @@ typedef struct SeqScanState
 typedef struct SampleScanState
 {
 	ScanState	ss;
-	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
+	struct TableScanDescData *scandesc; /* current scan descriptor */
 	List	   *args;			/* expr states for TABLESAMPLE params */
 	ExprState  *repeatable;		/* expr state for REPEATABLE expr */
 	/* use struct pointer to avoid including tsmapi.h here */
@@ -1793,7 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *      scandesc		   current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1813,7 +1813,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
@@ -1833,7 +1833,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *      scandesc	   current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1844,7 +1844,7 @@ typedef struct BitmapHeapScanState
 typedef struct TidScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	List	   *tss_tidexprs;
 	bool		tss_isCurrentOf;
 	int			tss_NumTids;
@@ -1855,7 +1855,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *      scandesc			current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
@@ -1865,7 +1865,7 @@ typedef struct TidScanState
 typedef struct TidRangeScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	List	   *trss_tidexprs;
 	ItemPointerData trss_mintid;
 	ItemPointerData trss_maxtid;
-- 
2.34.1

v22-0010-Add-scan_in_progress-to-BitmapHeapScanState.patchtext/x-patch; charset=US-ASCII; name=v22-0010-Add-scan_in_progress-to-BitmapHeapScanState.patchDownload
From d6ae56bbbc060835c2d3a4606fcf788b72ee154d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 13 Jun 2024 13:38:46 -0400
Subject: [PATCH v22 10/19] Add scan_in_progress to BitmapHeapScanState

Instead of checking that the scan descriptor hasn't been allocated yet,
use a dedicated variable, scan_in_progress. This feels cleaner and also
allows us to more easily extract the per scan setup into a separate
function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 5 ++++-
 src/include/nodes/execnodes.h             | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 84ad3a92585..3774379cc69 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -141,7 +141,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
 		 */
-		if (!scan)
+		if (!node->scan_in_progress)
 		{
 			bool		need_tuples = false;
 
@@ -163,8 +163,10 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  need_tuples);
 
 			node->scandesc = scan;
+			node->scan_in_progress = true;
 		}
 
+		Assert(scan);
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
@@ -640,6 +642,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
+	scanstate->scan_in_progress = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index ebba73d9b8b..5a9a187771a 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1804,6 +1804,7 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
+ *		scan_in_progress   is this a rescan
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1823,6 +1824,7 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
+	bool		scan_in_progress;
 	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-- 
2.34.1

v22-0012-Update-variable-names-in-bitmap-scan-descriptors.patchtext/x-patch; charset=US-ASCII; name=v22-0012-Update-variable-names-in-bitmap-scan-descriptors.patchDownload
From 8fe0e440f6109532de42fb3e11a4f234cae0066f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 09:59:23 -0400
Subject: [PATCH v22 12/19] Update variable names in bitmap scan descriptors

The previous commit which added BitmapTableScanDesc and
BitmapHeapScanDesc used the existing member names from TableScanDescData
and HeapScanDescData for diff clarity. This commit renames the members
-- in many cases by removing the rs_ prefix which is not relevant or
needed here.
---
 src/backend/access/heap/heapam.c          | 64 ++++++++++-----------
 src/backend/access/heap/heapam_handler.c  | 70 +++++++++++------------
 src/backend/executor/nodeBitmapHeapscan.c | 14 ++---
 src/include/access/heapam.h               | 22 +++----
 src/include/access/relscan.h              |  8 +--
 src/include/access/tableam.h              | 14 ++---
 6 files changed, 96 insertions(+), 96 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 0d8239d2f15..88da737d149 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1244,27 +1244,27 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	RelationIncrementReferenceCount(relation);
 	scan = (BitmapHeapScanDesc *) palloc(sizeof(BitmapHeapScanDesc));
 
-	scan->rs_base.rs_rd = relation;
-	scan->rs_base.rs_snapshot = snapshot;
-	scan->rs_base.rs_flags = flags;
+	scan->base.rel = relation;
+	scan->base.snapshot = snapshot;
+	scan->base.flags = flags;
 
 	Assert(snapshot && IsMVCCSnapshot(snapshot));
 
 	/* we only need to set this up once */
-	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
+	scan->ctup.t_tableOid = RelationGetRelid(relation);
 
-	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+	scan->nblocks = RelationGetNumberOfBlocks(scan->base.rel);
 
-	scan->rs_ctup.t_data = NULL;
-	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
-	scan->rs_cbuf = InvalidBuffer;
-	scan->rs_cblock = InvalidBlockNumber;
+	scan->ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->ctup.t_self);
+	scan->cbuf = InvalidBuffer;
+	scan->cblock = InvalidBlockNumber;
 
-	scan->rs_cindex = 0;
-	scan->rs_ntuples = 0;
+	scan->vis_idx = 0;
+	scan->vis_ntuples = 0;
 
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
+	scan->vmbuffer = InvalidBuffer;
+	scan->empty_tuples_pending = 0;
 
 	return (BitmapTableScanDesc *) scan;
 }
@@ -1274,31 +1274,31 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
-	if (BufferIsValid(scan->rs_cbuf))
+	if (BufferIsValid(scan->cbuf))
 	{
-		ReleaseBuffer(scan->rs_cbuf);
-		scan->rs_cbuf = InvalidBuffer;
+		ReleaseBuffer(scan->cbuf);
+		scan->cbuf = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->rs_vmbuffer))
+	if (BufferIsValid(scan->vmbuffer))
 	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
+		ReleaseBuffer(scan->vmbuffer);
+		scan->vmbuffer = InvalidBuffer;
 	}
 
-	scan->rs_cblock = InvalidBlockNumber;
+	scan->cblock = InvalidBlockNumber;
 
 	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
+	 * Reset empty_tuples_pending, a field only used by bitmap heap scan, to
+	 * avoid incorrectly emitting NULL-filled tuples from a previous scan on
+	 * rescan.
 	 */
-	scan->rs_empty_tuples_pending = 0;
+	scan->empty_tuples_pending = 0;
 
-	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+	scan->nblocks = RelationGetNumberOfBlocks(scan->base.rel);
 
-	scan->rs_ctup.t_data = NULL;
-	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+	scan->ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->ctup.t_self);
 }
 
 void
@@ -1306,16 +1306,16 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
-	if (BufferIsValid(scan->rs_cbuf))
-		ReleaseBuffer(scan->rs_cbuf);
+	if (BufferIsValid(scan->cbuf))
+		ReleaseBuffer(scan->cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
 
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
-	RelationDecrementReferenceCount(scan->rs_base.rs_rd);
+	RelationDecrementReferenceCount(scan->base.rel);
 
 	pfree(scan);
 }
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 82f216952b1..4057d0cf22b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2130,8 +2130,8 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	int			ntup;
 	TBMIterateResult *tbmres;
 
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
+	hscan->vis_idx = 0;
+	hscan->vis_ntuples = 0;
 
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
@@ -2140,7 +2140,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->tbmiterator);
+		tbmres = tbm_iterate(&scan->iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2153,7 +2153,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->nblocks);
 
 	/* Got a valid block */
 	*blockno = tbmres->blockno;
@@ -2164,15 +2164,15 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+	if (!(scan->flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(scan->rel, tbmres->blockno, &hscan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(hscan->empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2182,19 +2182,19 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
+	hscan->cbuf = ReleaseAndReadBuffer(hscan->cbuf,
+									   scan->rel,
+									   block);
+	hscan->cblock = block;
+	buffer = hscan->cbuf;
+	snapshot = scan->snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
+	heap_page_prune_opt(scan->rel, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2222,9 +2222,9 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, scan->rel, buffer, snapshot,
 									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+				hscan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
 	}
 	else
@@ -2248,16 +2248,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
+			loctup.t_tableOid = scan->rel->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+				hscan->vis_tuples[ntup++] = offnum;
+				PredicateLockTID(scan->rel, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+			HeapCheckForSerializableConflictOut(valid, scan->rel, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2265,7 +2265,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
+	hscan->vis_ntuples = ntup;
 
 	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
@@ -2291,43 +2291,43 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (hscan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		hscan->empty_tuples_pending--;
 		return true;
 	}
 
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
+	if (hscan->vis_idx < 0 || hscan->vis_idx >= hscan->vis_ntuples)
 		return false;
 
-	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
-	page = BufferGetPage(hscan->rs_cbuf);
+	targoffset = hscan->vis_tuples[hscan->vis_idx];
+	page = BufferGetPage(hscan->cbuf);
 	lp = PageGetItemId(page, targoffset);
 	Assert(ItemIdIsNormal(lp));
 
-	hscan->rs_ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-	hscan->rs_ctup.t_len = ItemIdGetLength(lp);
-	hscan->rs_ctup.t_tableOid = scan->rs_rd->rd_id;
-	ItemPointerSet(&hscan->rs_ctup.t_self, hscan->rs_cblock, targoffset);
+	hscan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+	hscan->ctup.t_len = ItemIdGetLength(lp);
+	hscan->ctup.t_tableOid = scan->rel->rd_id;
+	ItemPointerSet(&hscan->ctup.t_self, hscan->cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rs_rd);
+	pgstat_count_heap_fetch(scan->rel);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
 	 * acquires a pin on the buffer.
 	 */
-	ExecStoreBufferHeapTuple(&hscan->rs_ctup,
+	ExecStoreBufferHeapTuple(&hscan->ctup,
 							 slot,
-							 hscan->rs_cbuf);
+							 hscan->cbuf);
 
-	hscan->rs_cindex++;
+	hscan->vis_idx++;
 
 	return true;
 }
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fe5e19ac6dc..4dfc031c125 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -166,11 +166,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			Assert(scan);
 			/* rescan to release any page pin */
-			tbm_end_iterate(&scan->tbmiterator);
+			tbm_end_iterate(&scan->iterator);
 			table_rescan_bm(scan);
 		}
 
-		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
+		tbm_begin_iterate(&scan->iterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
 						  InvalidDsaPointer);
@@ -436,14 +436,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -488,14 +488,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				node->pfblockno = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -594,7 +594,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	if (scanDesc)
 	{
-		tbm_end_iterate(&scanDesc->tbmiterator);
+		tbm_end_iterate(&scanDesc->iterator);
 		table_endscan_bm(scanDesc);
 	}
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3cac199dd36..1d5583cac22 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -100,19 +100,19 @@ typedef struct HeapScanDescData *HeapScanDesc;
 
 typedef struct BitmapHeapScanDesc
 {
-	BitmapTableScanDesc rs_base;
+	BitmapTableScanDesc base;
 
-	BlockNumber rs_nblocks;		/* total number of blocks in rel */
+	BlockNumber nblocks;		/* total number of blocks in rel */
 
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+	int			vis_idx;		/* current tuple's index in vistuples */
+	int			vis_ntuples;	/* number of visible tuples on page */
+	OffsetNumber vis_tuples[MaxHeapTuplesPerPage];	/* their offsets */
 
-	Buffer		rs_cbuf;		/* current buffer in scan, if any */
-	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
-	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
+	Buffer		cbuf;			/* current buffer in scan, if any */
+	/* NB: if cbuf is not InvalidBuffer, we hold a pin on that buffer */
+	HeapTupleData ctup;			/* current tuple in scan, if any */
 
-	BlockNumber rs_cblock;		/* current block # in scan, if any */
+	BlockNumber cblock;			/* current block # in scan, if any */
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -121,8 +121,8 @@ typedef struct BitmapHeapScanDesc
 	 * block reported by the bitmap to determine how many NULL-filled tuples
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
-	Buffer		rs_vmbuffer;
-	int			rs_empty_tuples_pending;
+	Buffer		vmbuffer;
+	int			empty_tuples_pending;
 } BitmapHeapScanDesc;
 
 /*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 036ef29e7d5..086fce35a8b 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -54,19 +54,19 @@ typedef struct TableScanDescData *TableScanDesc;
 
 typedef struct BitmapTableScanDesc
 {
-	Relation	rs_rd;			/* heap relation descriptor */
-	struct SnapshotData *rs_snapshot;	/* snapshot to see */
+	Relation	rel;			/* heap relation descriptor */
+	struct SnapshotData *snapshot;	/* snapshot to see */
 
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
-	TBMIterator tbmiterator;
+	TBMIterator iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
 	 */
-	uint32		rs_flags;
+	uint32		flags;
 } BitmapTableScanDesc;
 
 /*
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 57bc06f77e0..f7f099b6449 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -984,7 +984,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 static inline void
 table_rescan_bm(BitmapTableScanDesc *scan)
 {
-	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+	scan->rel->rd_tableam->scan_rescan_bm(scan);
 }
 
 /*
@@ -993,7 +993,7 @@ table_rescan_bm(BitmapTableScanDesc *scan)
 static inline void
 table_endscan_bm(BitmapTableScanDesc *scan)
 {
-	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+	scan->rel->rd_tableam->scan_end_bm(scan);
 }
 
 
@@ -2016,9 +2016,9 @@ table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
-														   lossy_pages, exact_pages);
+	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
+														 blockno, recheck,
+														 lossy_pages, exact_pages);
 }
 
 /*
@@ -2041,8 +2041,8 @@ table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+	return scan->rel->rd_tableam->scan_bitmap_next_tuple(scan,
+														 slot);
 }
 
 /*
-- 
2.34.1

v22-0011-Make-new-bitmap-table-scan-and-bitmap-heap-scan-.patchtext/x-patch; charset=US-ASCII; name=v22-0011-Make-new-bitmap-table-scan-and-bitmap-heap-scan-.patchDownload
From 7c44a303f0e0005aecc535912f67a2f75b01247a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:51:05 -0400
Subject: [PATCH v22 11/19] Make new bitmap table scan and bitmap heap scan
 descriptors

The number of fields from the TableScanDescData required for bitmap
table scans is few. Create a new BitmapTableScanDesc with only those
members needed for bitmap table scans and remove the bitmap table
scan-only fields from the generic TableScanDescData.

Also add a BitmapHeapScanDesc structure for the heap AM implementation
of bitmap table scans. Add table AM callbacks for starting, restarting,
and ending these scans.

While reducing the size of the scan descriptor (and the amount of code
executed in the table_begin/end/rescan() functions) was a benefit,
creating a new BitmapTableScanDesc and associated table AM functions to
begin/end/rescan was actually motivated by work to remove all
heap-specific code from the generic bitmap table scan code path. Pushing
this code down into the heap AM layer would have required adding quite a
few bitmap-specific parameters to heap_begin/end/rescan()
---
 src/backend/access/heap/heapam.c          | 110 ++++++++++++++++++----
 src/backend/access/heap/heapam_handler.c  |  12 ++-
 src/backend/executor/nodeBitmapHeapscan.c |  28 +++---
 src/include/access/heapam.h               |  39 ++++++--
 src/include/access/relscan.h              |  20 +++-
 src/include/access/tableam.h              |  79 +++++++++++-----
 src/include/nodes/execnodes.h             |   2 +-
 src/tools/pgindent/typedefs.list          |   2 +
 8 files changed, 220 insertions(+), 72 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 82bb9cb33b6..0d8239d2f15 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1061,8 +1061,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1178,19 +1176,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
-	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
-	 */
-	scan->rs_empty_tuples_pending = 0;
-
 	/*
 	 * The read stream is reset on rescan. This must be done before
 	 * initscan(), as some state referred to by read_stream_reset() is reset
@@ -1218,9 +1203,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
@@ -1247,6 +1229,98 @@ heap_endscan(TableScanDesc sscan)
 	pfree(scan);
 }
 
+BitmapTableScanDesc *
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+{
+	BitmapHeapScanDesc *scan;
+
+	/*
+	 * increment relation ref count while scanning relation
+	 *
+	 * This is just to make really sure the relcache entry won't go away while
+	 * the scan has a pointer to it.  Caller should be holding the rel open
+	 * anyway, so this is redundant in all normal scenarios...
+	 */
+	RelationIncrementReferenceCount(relation);
+	scan = (BitmapHeapScanDesc *) palloc(sizeof(BitmapHeapScanDesc));
+
+	scan->rs_base.rs_rd = relation;
+	scan->rs_base.rs_snapshot = snapshot;
+	scan->rs_base.rs_flags = flags;
+
+	Assert(snapshot && IsMVCCSnapshot(snapshot));
+
+	/* we only need to set this up once */
+	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
+
+	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+
+	scan->rs_ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+	scan->rs_cbuf = InvalidBuffer;
+	scan->rs_cblock = InvalidBlockNumber;
+
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
+
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
+
+	return (BitmapTableScanDesc *) scan;
+}
+
+void
+heap_rescan_bm(BitmapTableScanDesc *sscan)
+{
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+
+	if (BufferIsValid(scan->rs_cbuf))
+	{
+		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
+
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
+	scan->rs_cblock = InvalidBlockNumber;
+
+	/*
+	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
+	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
+	 * on rescan.
+	 */
+	scan->rs_empty_tuples_pending = 0;
+
+	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+
+	scan->rs_ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+}
+
+void
+heap_endscan_bm(BitmapTableScanDesc *sscan)
+{
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+
+	if (BufferIsValid(scan->rs_cbuf))
+		ReleaseBuffer(scan->rs_cbuf);
+
+	if (BufferIsValid(scan->rs_vmbuffer))
+		ReleaseBuffer(scan->rs_vmbuffer);
+
+	/*
+	 * decrement relation reference count and free scan descriptor storage
+	 */
+	RelationDecrementReferenceCount(scan->rs_base.rs_rd);
+
+	pfree(scan);
+}
+
+
 HeapTuple
 heap_getnext(TableScanDesc sscan, ScanDirection direction)
 {
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c3788918777..82f216952b1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,11 +2119,11 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2283,10 +2283,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
@@ -2629,6 +2629,10 @@ static const TableAmRoutine heapam_methods = {
 	.scan_rescan = heap_rescan,
 	.scan_getnextslot = heap_getnextslot,
 
+	.scan_begin_bm = heap_beginscan_bm,
+	.scan_rescan_bm = heap_rescan_bm,
+	.scan_end_bm = heap_endscan_bm,
+
 	.scan_set_tidrange = heap_set_tidrange,
 	.scan_getnextslot_tidrange = heap_getnextslot_tidrange,
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3774379cc69..fe5e19ac6dc 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -54,7 +54,7 @@ static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *ps
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
+								  BitmapTableScanDesc *scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -68,7 +68,7 @@ static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
-	TableScanDesc scan;
+	BitmapTableScanDesc *scan;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -158,15 +158,18 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
 									  need_tuples);
-
 			node->scandesc = scan;
 			node->scan_in_progress = true;
 		}
+		else
+		{
+			Assert(scan);
+			/* rescan to release any page pin */
+			tbm_end_iterate(&scan->tbmiterator);
+			table_rescan_bm(scan);
+		}
 
-		Assert(scan);
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
@@ -402,7 +405,7 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
 static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -540,10 +543,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* rescan to release any page pin */
-	if (node->scandesc)
-		table_rescan(node->scandesc, NULL);
-
 	/* release bitmaps and buffers if any */
 	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
@@ -577,7 +576,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 void
 ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 {
-	TableScanDesc scanDesc;
+	BitmapTableScanDesc *scanDesc;
 
 	/*
 	 * extract information from the node
@@ -594,7 +593,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * close heap scan
 	 */
 	if (scanDesc)
-		table_endscan(scanDesc);
+	{
+		tbm_end_iterate(&scanDesc->tbmiterator);
+		table_endscan_bm(scanDesc);
+	}
 
 	/*
 	 * release bitmaps and buffers if any
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 9e9aec88a62..3cac199dd36 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -91,22 +91,39 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDesc
+{
+	BitmapTableScanDesc rs_base;
+
+	BlockNumber rs_nblocks;		/* total number of blocks in rel */
+
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+
+	Buffer		rs_cbuf;		/* current buffer in scan, if any */
+	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
+	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
+
+	BlockNumber rs_cblock;		/* current block # in scan, if any */
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+} BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
@@ -296,6 +313,12 @@ extern void heap_prepare_pagescan(TableScanDesc sscan);
 extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 						bool allow_strat, bool allow_sync, bool allow_pagemode);
 extern void heap_endscan(TableScanDesc sscan);
+
+extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
+											  Snapshot snapshot, uint32 flags);
+extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
+void		heap_endscan_bm(BitmapTableScanDesc *sscan);
+
 extern HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction);
 extern bool heap_getnextslot(TableScanDesc sscan,
 							 ScanDirection direction, struct TupleTableSlot *slot);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b4511677b1d..036ef29e7d5 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -37,9 +37,6 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
-	/* Iterators for Bitmap Table Scans */
-	TBMIterator tbmiterator;
-
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
@@ -55,6 +52,23 @@ typedef struct TableScanDescData
 } TableScanDescData;
 typedef struct TableScanDescData *TableScanDesc;
 
+typedef struct BitmapTableScanDesc
+{
+	Relation	rs_rd;			/* heap relation descriptor */
+	struct SnapshotData *rs_snapshot;	/* snapshot to see */
+
+	/*
+	 * Members common to Parallel and Serial BitmapTableScans
+	 */
+	TBMIterator tbmiterator;
+
+	/*
+	 * Information about type and behaviour of the scan, a bitmask of members
+	 * of the ScanOptions enum (see tableam.h).
+	 */
+	uint32		rs_flags;
+} BitmapTableScanDesc;
+
 /*
  * Shared state for parallel table scan.
  *
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 7034b79c2de..57bc06f77e0 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -345,6 +345,24 @@ typedef struct TableAmRoutine
 								bool set_params, bool allow_strat,
 								bool allow_sync, bool allow_pagemode);
 
+	/*
+	 * Functions to begin, restart, and end a scan of the underlying table of
+	 * a bitmap table scan.
+	 *
+	 * `rel`, `flags`, and `snapshot` serve the same purposes as in the
+	 * standard relation scan_[begin|rescan|end] functions documented above.
+	 */
+	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
+										   Snapshot snapshot,
+										   uint32 flags);
+
+	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
+
+	/*
+	 * Release resources and deallocate scan.
+	 */
+	void		(*scan_end_bm) (BitmapTableScanDesc *scan);
+
 	/*
 	 * Return next tuple from `scan`, store in slot.
 	 */
@@ -815,7 +833,7 @@ typedef struct TableAmRoutine
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
 										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
@@ -826,7 +844,7 @@ typedef struct TableAmRoutine
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (BitmapTableScanDesc *scan,
 										   TupleTableSlot *slot);
 
 	/*
@@ -851,8 +869,8 @@ typedef struct TableAmRoutine
 	 * is obviously OK.
 	 *
 	 * Currently it is required to implement this interface, as there's no
-	 * alternative way (contrary e.g. to bitmap scans) to implement sample
-	 * scans. If infeasible to implement, the AM may raise an error.
+	 * alternative way to implement sample scans. If infeasible to implement,
+	 * the AM may raise an error.
 	 */
 	bool		(*scan_sample_next_block) (TableScanDesc scan,
 										   struct SampleScanState *scanstate);
@@ -945,29 +963,46 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 }
 
 /*
- * table_beginscan_bm is an alternative entry point for setting up a
- * TableScanDesc for a bitmap heap scan.  Although that scan technology is
- * really quite unlike a standard seqscan, there is just enough commonality to
- * make it worth using the same data structure.
+ * table_beginscan_bm is an entry point for setting up a BitmapTableScanDesc
+ * for a bitmap table scan.
  */
-static inline TableScanDesc
+static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, bool need_tuple)
+				   bool need_tuple)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 }
 
+/*
+ * Restart a bitmap table scan.
+ */
+static inline void
+table_rescan_bm(BitmapTableScanDesc *scan)
+{
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+}
+
+/*
+ * End a bitmap table scan.
+ */
+static inline void
+table_endscan_bm(BitmapTableScanDesc *scan)
+{
+	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+}
+
+
 /*
  * table_beginscan_sampling is an alternative entry point for setting up a
- * TableScanDesc for a TABLESAMPLE scan.  As with bitmap scans, it's worth
- * using the same data structure although the behavior is rather different.
- * In addition to the options offered by table_beginscan_strat, this call
- * also allows control of whether page-mode visibility checking is used.
+ * TableScanDesc for a TABLESAMPLE scan.  It's worth using the same data
+ * structure although the behavior is rather different. In addition to the
+ * options offered by table_beginscan_strat, this call also allows control of
+ * whether page-mode visibility checking is used.
  */
 static inline TableScanDesc
 table_beginscan_sampling(Relation rel, Snapshot snapshot,
@@ -989,7 +1024,7 @@ table_beginscan_sampling(Relation rel, Snapshot snapshot,
 
 /*
  * table_beginscan_tid is an alternative entry point for setting up a
- * TableScanDesc for a Tid scan. As with bitmap scans, it's worth using
+ * TableScanDesc for a Tid scan. As with sample scans, it's worth using
  * the same data structure although the behavior is rather different.
  */
 static inline TableScanDesc
@@ -1002,7 +1037,7 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 
 /*
  * table_beginscan_analyze is an alternative entry point for setting up a
- * TableScanDesc for an ANALYZE scan.  As with bitmap scans, it's worth using
+ * TableScanDesc for an ANALYZE scan.  As with sample scans, it's worth using
  * the same data structure although the behavior is rather different.
  */
 static inline TableScanDesc
@@ -1019,9 +1054,6 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-		tbm_end_iterate(&scan->tbmiterator);
-
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1032,9 +1064,6 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-		tbm_end_iterate(&scan->tbmiterator);
-
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1974,7 +2003,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
@@ -2001,7 +2030,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  * returned false.
  */
 static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
+table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 							 TupleTableSlot *slot)
 {
 	/*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 5a9a187771a..0f34bac4baf 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1814,7 +1814,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *scandesc;
+	struct BitmapTableScanDesc *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 757a9a3a41e..90f7fd882dc 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -261,12 +261,14 @@ BitmapAndPath
 BitmapAndState
 BitmapHeapPath
 BitmapHeapScan
+BitmapHeapScanDesc
 BitmapHeapScanState
 BitmapIndexScan
 BitmapIndexScanState
 BitmapOr
 BitmapOrPath
 BitmapOrState
+BitmapTableScanDesc
 Bitmapset
 Block
 BlockId
-- 
2.34.1

v22-0005-BitmapHeapScan-initialize-some-prefetch-state-el.patchtext/x-patch; charset=US-ASCII; name=v22-0005-BitmapHeapScan-initialize-some-prefetch-state-el.patchDownload
From 5242d841a5d4cad1d60959618ca9b4d2ec132778 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:51:11 -0400
Subject: [PATCH v22 05/19] BitmapHeapScan initialize some prefetch state
 elsewhere

The prefetch_target and prefetch_pages members can be initialized in the
scan and rescan functions. This makes it more straightforward to use the
unified TBMIterator API for BitmapHeapScan.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d1ef3a44e18..5eb54f62f20 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -111,11 +111,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
-			{
 				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
 #endif							/* USE_PREFETCH */
 		}
 		else
@@ -591,6 +587,9 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
 	node->pfblockno = InvalidBlockNumber;
+	/* Only used for serial BHS */
+	node->prefetch_pages = 0;
+	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -676,7 +675,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->lossy_pages = 0;
 	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
+	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
@@ -812,7 +811,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -839,6 +838,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
+	pstate->prefetch_pages = 0;
+	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-- 
2.34.1

v22-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-patch; charset=US-ASCII; name=v22-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchDownload
From 8e0781124f0ba4ab240964170b41791237e98348 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v22 02/19] Remove table_scan_bitmap_next_tuple parameter
 tbmres

In order to remove TBMIterateResults as a flow control mechanism in
BitmapHeapNext(), they can no longer be used as a means of communication
between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Remove the TBMIterateResult parameter from
table_scan_bitmap_next_tuple().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 72ba9ed4dcf..b303dc49430 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2259,7 +2259,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index de7a293de8e..e63f6f0429a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -281,7 +281,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ad3339196af..9f11cf3729a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,10 +797,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -831,15 +828,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2003,7 +1995,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2015,7 +2006,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.34.1

v22-0003-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-patch; charset=US-ASCII; name=v22-0003-Make-table_scan_bitmap_next_block-async-friendly.patchDownload
From df97f24b5fe1f4f0041157b28bdafbfaa5737c64 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v22 03/19] Make table_scan_bitmap_next_block() async-friendly

table_scan_bitmap_next_block() previously returned false when
table_scan_bitmap_next_tuple() should not be called for the tuples on
the page. This could happen when there were no visible tuples on the
page or when, due to concurrent activity on the table, the block
returned by the iterator is past the end of the table (as recorded when
the scan started).

That forced the caller to be responsible for determining if additional
blocks should be fetched and for invoking table_scan_bitmap_next_block()
for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
beginning of the scan) and for table_scan_bitmap_next_tuple() to return
false if there are no visible tuples on the page.

This also allows us to move responsibility for advancing the iterator to
table AM specific code. This means handling invalid blocks is entirely
up to the table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  54 ++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  77 ++++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 203 insertions(+), 145 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b303dc49430..3110f97473f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,18 +2120,48 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+			return false;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2150,16 +2180,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2254,7 +2275,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e63f6f0429a..e8b4a754434 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,9 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -85,11 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -105,6 +96,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,8 +107,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
+			tbmiterator = tbm_begin_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -166,9 +159,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -207,46 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -267,45 +235,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -331,13 +310,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -351,14 +334,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -383,7 +373,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -461,6 +454,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -518,6 +512,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -579,12 +575,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -592,13 +584,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -629,28 +621,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -683,8 +671,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -692,9 +678,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..024dc08c420 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -36,6 +39,10 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
+	/* Iterators for Bitmap Table Scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9f11cf3729a..2f4e221870e 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "storage/read_stream.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
@@ -36,7 +37,6 @@ extern PGDLLIMPORT bool synchronize_seqscans;
 struct BulkInsertStateData;
 struct IndexInfo;
 struct SampleScanState;
-struct TBMIterateResult;
 struct VacuumParams;
 struct ValidateIndexState;
 
@@ -790,19 +790,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, `exact_pages` is incremented.
 	 *
@@ -821,7 +816,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -959,12 +954,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1024,6 +1023,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1034,6 +1048,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1955,19 +1984,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. `lossy_pages` is incremented if the block's
- * representation in the bitmap is lossy; otherwise, `exact_pages` is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set by the table AM to indicate whether or not the tuples
+ * from this block should be rechecked. Tuples from lossy pages will always
+ * need to be rechecked, but some non-lossy pages' tuples may also require
+ * recheck.
+ *
+ * `blockno` is only used in bitmap table scan code to validate that the
+ * prefetch block is staying ahead of the current block.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1980,9 +2016,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8bc421e7c05..0af7906a184 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1795,8 +1795,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1805,9 +1803,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1815,8 +1815,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1825,9 +1823,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v22-0001-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-patch; charset=US-ASCII; name=v22-0001-table_scan_bitmap_next_block-counts-lossy-and-ex.patchDownload
From 164700a6b45df7362b2432d9d880cd78d183e37a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v22 01/19] table_scan_bitmap_next_block counts lossy and exact
 pages

Keep track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap in table AM-specific code. These
counters are used for EXPLAIN.

This is a step toward removing TBMIterateResults as a flow control
mechanism in BitmapHeapNext(), which is required for a more asynchronous
design. It also is more table AM agnostic.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6f8b1b79298..72ba9ed4dcf 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,7 +2120,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2248,6 +2249,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6b48a6d8350..de7a293de8e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,8 +212,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -233,14 +231,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8e583b45cd5..ad3339196af 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -806,6 +806,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, `exact_pages` is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -821,7 +824,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1959,17 +1963,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. `lossy_pages` is incremented if the block's
+ * representation in the bitmap is lossy; otherwise, `exact_pages` is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1980,7 +1988,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

v22-0004-Add-common-interface-for-TBMIterators.patchtext/x-patch; charset=US-ASCII; name=v22-0004-Add-common-interface-for-TBMIterators.patchDownload
From 76b9c9af813dadd87fc6a6cfa1cc3b2eaf107b1e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:41:05 -0400
Subject: [PATCH v22 04/19] Add common interface for TBMIterators

Add and use TBMSerialIterator, which replaces the current TBMIterator
for serial use cases, and repurpose TBMIterator to be a unified
interface for both the serial and parallel TID Bitmap iterator
interfaces. This encapsulation simplifies call sites for callers
supporting both parallel and serial TID Bitmap access. TBMIterator is
not yet used in this commit.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/gin/ginget.c           |   8 +-
 src/backend/access/gin/ginscan.c          |   2 +-
 src/backend/access/heap/heapam_handler.c  |   2 +-
 src/backend/executor/nodeBitmapHeapscan.c |  22 ++---
 src/backend/nodes/tidbitmap.c             | 102 +++++++++++++++++-----
 src/include/access/gin_private.h          |   2 +-
 src/include/access/relscan.h              |   4 +-
 src/include/access/tableam.h              |   4 +-
 src/include/nodes/execnodes.h             |   2 +-
 src/include/nodes/tidbitmap.h             |  27 ++++--
 src/tools/pgindent/typedefs.list          |   1 +
 11 files changed, 126 insertions(+), 50 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..9c53ca19f06 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,7 @@ restartScanEntry:
 			if (entry->matchBitmap)
 			{
 				if (entry->matchIterator)
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -385,7 +385,7 @@ restartScanEntry:
 
 		if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
 		{
-			entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+			entry->matchIterator = tbm_begin_private_iterate(entry->matchBitmap);
 			entry->isFinished = false;
 		}
 	}
@@ -832,12 +832,12 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				entry->matchResult = tbm_private_iterate(entry->matchIterator);
 
 				if (entry->matchResult == NULL)
 				{
 					ItemPointerSetInvalid(&entry->curItem);
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
 					entry->isFinished = true;
 					break;
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..5b9a0eaea73 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -246,7 +246,7 @@ ginFreeScanKeys(GinScanOpaque so)
 		if (entry->list)
 			pfree(entry->list);
 		if (entry->matchIterator)
-			tbm_end_iterate(entry->matchIterator);
+			tbm_end_private_iterate(entry->matchIterator);
 		if (entry->matchBitmap)
 			tbm_free(entry->matchBitmap);
 	}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3110f97473f..b6ddf600a0a 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2143,7 +2143,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (scan->shared_tbmiterator)
 			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbmres = tbm_private_iterate(scan->tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e8b4a754434..d1ef3a44e18 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,7 +96,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
+		TBMPrivateIterator *tbmiterator = NULL;
 		TBMSharedIterator *shared_tbmiterator = NULL;
 
 		if (!pstate)
@@ -107,12 +107,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_private_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
+				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
 				node->prefetch_pages = 0;
 				node->prefetch_target = -1;
 			}
@@ -275,7 +275,7 @@ new_page:
 			break;
 
 		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * If private, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
@@ -324,7 +324,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
@@ -334,7 +334,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = tbm_private_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -437,19 +437,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_private_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
+					tbm_end_private_iterate(prefetch_iterator);
 					node->prefetch_iterator = NULL;
 					break;
 				}
@@ -576,7 +576,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 	/* release bitmaps and buffers if any */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -632,7 +632,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * release bitmaps and buffers if any
 	 */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->shared_prefetch_iterator)
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..6d1fbcb03e9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -170,12 +170,12 @@ struct TIDBitmap
 };
 
 /*
- * When iterating over a bitmap in sorted order, a TBMIterator is used to
- * track our progress.  There can be several iterators scanning the same
- * bitmap concurrently.  Note that the bitmap becomes read-only as soon as
- * any iterator is created.
+ * When iterating over a backend-local bitmap in sorted order, a
+ * TBMPrivateIterator is used to track our progress.  There can be several
+ * iterators scanning the same bitmap concurrently.  Note that the bitmap
+ * becomes read-only as soon as any iterator is created.
  */
-struct TBMIterator
+struct TBMPrivateIterator
 {
 	TIDBitmap  *tbm;			/* TIDBitmap we're iterating over */
 	int			spageptr;		/* next spages index */
@@ -213,8 +213,8 @@ typedef struct PTIterationArray
 } PTIterationArray;
 
 /*
- * same as TBMIterator, but it is used for joint iteration, therefore this
- * also holds a reference to the shared state.
+ * same as TBMPrivateIterator, but it is used for joint iteration, therefore
+ * this also holds a reference to the shared state.
  */
 struct TBMSharedIterator
 {
@@ -673,31 +673,31 @@ tbm_is_empty(const TIDBitmap *tbm)
 }
 
 /*
- * tbm_begin_iterate - prepare to iterate through a TIDBitmap
+ * tbm_begin_private_iterate - prepare to iterate through a TIDBitmap
  *
- * The TBMIterator struct is created in the caller's memory context.
- * For a clean shutdown of the iteration, call tbm_end_iterate; but it's
- * okay to just allow the memory context to be released, too.  It is caller's
- * responsibility not to touch the TBMIterator anymore once the TIDBitmap
+ * The TBMPrivateIterator struct is created in the caller's memory context. For
+ * a clean shutdown of the iteration, call tbm_end_iterate; but it's okay to
+ * just allow the memory context to be released, too.  It is caller's
+ * responsibility not to touch the TBMPrivateIterator anymore once the TIDBitmap
  * is freed.
  *
  * NB: after this is called, it is no longer allowed to modify the contents
  * of the bitmap.  However, you can call this multiple times to scan the
  * contents repeatedly, including parallel scans.
  */
-TBMIterator *
-tbm_begin_iterate(TIDBitmap *tbm)
+TBMPrivateIterator *
+tbm_begin_private_iterate(TIDBitmap *tbm)
 {
-	TBMIterator *iterator;
+	TBMPrivateIterator *iterator;
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
 	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
+	 * Create the TBMPrivateIterator struct, with enough trailing space to
+	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
+											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
 	iterator->tbm = tbm;
 
 	/*
@@ -956,7 +956,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 }
 
 /*
- * tbm_iterate - scan through next page of a TIDBitmap
+ * tbm_private_iterate - scan through next page of a TIDBitmap
  *
  * Returns a TBMIterateResult representing one page, or NULL if there are
  * no more pages to scan.  Pages are guaranteed to be delivered in numerical
@@ -968,7 +968,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  * testing, recheck is always set true when ntuples < 0.)
  */
 TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+tbm_private_iterate(TBMPrivateIterator *iterator)
 {
 	TIDBitmap  *tbm = iterator->tbm;
 	TBMIterateResult *output = &(iterator->output);
@@ -1143,7 +1143,7 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
  * bitmap to return to read/write status when there are no more iterators.)
  */
 void
-tbm_end_iterate(TBMIterator *iterator)
+tbm_end_private_iterate(TBMPrivateIterator *iterator)
 {
 	pfree(iterator);
 }
@@ -1556,3 +1556,61 @@ tbm_calculate_entries(double maxbytes)
 
 	return nbuckets;
 }
+
+/*
+ * Start iteration on a shared or non-shared bitmap iterator. Note that tbm
+ * will only be provided by private BitmapHeapScan callers. dsa and dsp will
+ * only be provided by parallel BitmapHeapScan callers. For shared callers, one
+ * process must already have called tbm_prepare_shared_iterate() to create and
+ * set up the TBMSharedIteratorState. The TBMIterator is passed by reference to
+ * accommodate callers who would like to allocate it inside an existing struct.
+ */
+void
+tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+				  dsa_area *dsa, dsa_pointer dsp)
+{
+	Assert(iterator);
+
+	iterator->private = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = false;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+		iterator->parallel = tbm_attach_shared_iterate(dsa, dsp);
+	else
+		iterator->private = tbm_begin_private_iterate(tbm);
+}
+
+/*
+ * Clean up shared or non-shared bitmap iterator.
+ */
+void
+tbm_end_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->private)
+		tbm_end_private_iterate(iterator->private);
+	else if (iterator->parallel)
+		tbm_end_shared_iterate(iterator->parallel);
+
+	iterator->private = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = true;
+}
+
+/*
+ * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
+ */
+TBMIterateResult *
+tbm_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+	Assert(!iterator->exhausted);
+
+	if (iterator->private)
+		return tbm_private_iterate(iterator->private);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..78800509367 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
-	TBMIterator *matchIterator;
+	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 024dc08c420..159921ffb50 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,7 +24,7 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
+struct TBMPrivateIterator;
 struct TBMSharedIterator;
 
 /*
@@ -40,7 +40,7 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Iterators for Bitmap Table Scans */
-	struct TBMIterator *tbmiterator;
+	struct TBMPrivateIterator *tbmiterator;
 	struct TBMSharedIterator *shared_tbmiterator;
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2f4e221870e..9802d42df9d 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -1033,7 +1033,7 @@ table_endscan(TableScanDesc scan)
 
 		if (scan->tbmiterator)
 		{
-			tbm_end_iterate(scan->tbmiterator);
+			tbm_end_private_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
 	}
@@ -1058,7 +1058,7 @@ table_rescan(TableScanDesc scan,
 
 		if (scan->tbmiterator)
 		{
-			tbm_end_iterate(scan->tbmiterator);
+			tbm_end_private_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
 	}
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0af7906a184..81447fea8c5 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1818,7 +1818,7 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
+	TBMPrivateIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..472c0b444bf 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -32,8 +32,8 @@
  */
 typedef struct TIDBitmap TIDBitmap;
 
-/* Likewise, TBMIterator is private */
-typedef struct TBMIterator TBMIterator;
+/* Likewise, TBMPrivateIterator is private */
+typedef struct TBMPrivateIterator TBMPrivateIterator;
 typedef struct TBMSharedIterator TBMSharedIterator;
 
 /* Result structure for tbm_iterate */
@@ -46,6 +46,17 @@ typedef struct TBMIterateResult
 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
 } TBMIterateResult;
 
+/*
+ * Callers with both private and parallel implementations can use this unified
+ * API.
+ */
+typedef struct TBMIterator
+{
+	TBMPrivateIterator *private;
+	TBMSharedIterator *parallel;
+	bool		exhausted;
+} TBMIterator;
+
 /* function prototypes in nodes/tidbitmap.c */
 
 extern TIDBitmap *tbm_create(long maxbytes, dsa_area *dsa);
@@ -62,14 +73,20 @@ extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
-extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
 extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
-extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
 													dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+extern void tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+							  dsa_area *dsa, dsa_pointer dsp);
+extern void tbm_end_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+
+
 #endif							/* TIDBITMAP_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 61ad417cde6..757a9a3a41e 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2795,6 +2795,7 @@ TAR_MEMBER
 TBMIterateResult
 TBMIteratingState
 TBMIterator
+TBMPrivateIterator
 TBMSharedIterator
 TBMSharedIteratorState
 TBMStatus
-- 
2.34.1

v22-0006-BitmapHeapScan-uses-unified-iterator.patchtext/x-patch; charset=US-ASCII; name=v22-0006-BitmapHeapScan-uses-unified-iterator.patchDownload
From faf85685fdd454d88e962e621f1b22ea686a8db2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:39:04 -0400
Subject: [PATCH v22 06/19] BitmapHeapScan uses unified iterator

With the repurposing of TBMIterator as an interface for both parallel
and serial iteration through TIDBitmaps, BitmapHeapScan may now use it
since it has both parallel and serial iteration.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 132 ++++++++--------------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  34 +-----
 src/include/nodes/execnodes.h             |   4 +-
 5 files changed, 54 insertions(+), 128 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b6ddf600a0a..c3788918777 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2140,10 +2140,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_private_iterate(scan->tbmiterator);
+		tbmres = tbm_iterate(&scan->tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5eb54f62f20..9c156787770 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -69,7 +69,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -80,7 +79,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -96,76 +94,49 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMPrivateIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
-
 		if (!pstate)
 		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
-			if (!tbm || !IsA(tbm, TIDBitmap))
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
-			node->tbm = tbm;
-			tbmiterator = tbm_begin_private_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
-#endif							/* USE_PREFETCH */
 		}
-		else
+		else if (BitmapShouldInitializeSharedState(pstate))
 		{
 			/*
 			 * The leader will immediately come out of the function, but
 			 * others will be blocked until leader populates the TBM and wakes
 			 * them up.
 			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
-
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+				elog(ERROR, "unrecognized result from subplan");
 
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+				pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(node->tbm);
 			}
-#endif							/* USE_PREFETCH */
+#endif
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(pstate);
 		}
 
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+			tbm_begin_iterate(&node->prefetch_iterator, node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -194,8 +165,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
+						  pstate ?
+						  pstate->tbmiterator :
+						  InvalidDsaPointer);
+
 		node->initialized = true;
 
 		goto new_page;
@@ -275,7 +249,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!node->prefetch_iterator.exhausted &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -320,17 +294,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_private_iterate(prefetch_iterator);
+			tbmpre = tbm_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -347,7 +321,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -368,9 +342,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -433,20 +407,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_private_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_private_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -474,9 +447,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (1)
 			{
@@ -499,12 +472,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -571,18 +543,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -630,12 +597,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
+	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -673,11 +637,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 159921ffb50..b4511677b1d 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/itup.h"
+#include "nodes/tidbitmap.h"
 #include "port/atomics.h"
 #include "storage/buf.h"
 #include "storage/spin.h"
@@ -24,9 +25,6 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMPrivateIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,8 +38,7 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Iterators for Bitmap Table Scans */
-	struct TBMPrivateIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	TBMIterator tbmiterator;
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9802d42df9d..7034b79c2de 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -954,16 +954,12 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
 /*
@@ -1024,19 +1020,7 @@ static inline void
 table_endscan(TableScanDesc scan)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_private_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+		tbm_end_iterate(&scan->tbmiterator);
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
@@ -1049,19 +1033,7 @@ table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_private_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+		tbm_end_iterate(&scan->tbmiterator);
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 81447fea8c5..1f262db776c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1803,7 +1803,6 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1818,12 +1817,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMPrivateIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
-- 
2.34.1

v22-0007-BitmapHeapScan-Make-prefetch-sync-error-more-det.patchtext/x-patch; charset=US-ASCII; name=v22-0007-BitmapHeapScan-Make-prefetch-sync-error-more-det.patchDownload
From ea44146463a724f54c03bf2a27cc42983572c8a0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Jun 2024 12:40:58 -0400
Subject: [PATCH v22 07/19] BitmapHeapScan: Make prefetch sync error more
 detailed

Add the prefetch and current block numbers to the error message emitted
when the prefetch iterator gets out of sync with the main iterator in
serial bitmap table scan.
---
 src/backend/executor/nodeBitmapHeapscan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 9c156787770..33e4ef13bd6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -251,7 +251,7 @@ new_page:
 		if (node->pstate == NULL &&
 			!node->prefetch_iterator.exhausted &&
 			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
+			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
 
 		/* Adjust the prefetch target */
 		BitmapAdjustPrefetchTarget(node);
-- 
2.34.1

#146Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#145)
29 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

I went through v22 to remind myself of what the patches do and do some
basic review - I have some simple questions / comments for now, nothing
major. I've kept the comments in separate 'review' patches, it does not
seem worth copying here.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

v22b-0001-table_scan_bitmap_next_block-counts-lossy-and-e.patchtext/x-patch; charset=UTF-8; name=v22b-0001-table_scan_bitmap_next_block-counts-lossy-and-e.patchDownload
From 9e5c44314f78754c7c30d550ca6f2cedc05d21e1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v22b 01/29] table_scan_bitmap_next_block counts lossy and
 exact pages

Keep track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap in table AM-specific code. These
counters are used for EXPLAIN.

This is a step toward removing TBMIterateResults as a flow control
mechanism in BitmapHeapNext(), which is required for a more asynchronous
design. It also is more table AM agnostic.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6f8b1b79298..72ba9ed4dcf 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,7 +2120,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2248,6 +2249,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples < 0)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6b48a6d8350..de7a293de8e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,8 +212,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -233,14 +231,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8e583b45cd5..ad3339196af 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -806,6 +806,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, `exact_pages` is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -821,7 +824,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1959,17 +1963,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. `lossy_pages` is incremented if the block's
+ * representation in the bitmap is lossy; otherwise, `exact_pages` is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1980,7 +1988,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.45.2

v22b-0002-review.patchtext/x-patch; charset=UTF-8; name=v22b-0002-review.patchDownload
From 58ebda69284ab9c61c0b9855978fbb5a9cf007c4 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 20:42:24 +0200
Subject: [PATCH v22b 02/29] review

---
 src/backend/access/heap/heapam_handler.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 72ba9ed4dcf..6f744f727d0 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2249,6 +2249,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	/* XXX why inverted condition, compared to the original one in BitmapHeapNext? */
 	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
-- 
2.45.2

v22b-0003-Remove-table_scan_bitmap_next_tuple-parameter-t.patchtext/x-patch; charset=UTF-8; name=v22b-0003-Remove-table_scan_bitmap_next_tuple-parameter-t.patchDownload
From b5a006e59fd287a97a971460beee63bd9732f5bd Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v22b 03/29] Remove table_scan_bitmap_next_tuple parameter
 tbmres

In order to remove TBMIterateResults as a flow control mechanism in
BitmapHeapNext(), they can no longer be used as a means of communication
between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Remove the TBMIterateResult parameter from
table_scan_bitmap_next_tuple().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6f744f727d0..f98ffe51759 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2260,7 +2260,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index de7a293de8e..e63f6f0429a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -281,7 +281,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ad3339196af..9f11cf3729a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,10 +797,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -831,15 +828,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2003,7 +1995,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2015,7 +2006,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.45.2

v22b-0004-Make-table_scan_bitmap_next_block-async-friendl.patchtext/x-patch; charset=UTF-8; name=v22b-0004-Make-table_scan_bitmap_next_block-async-friendl.patchDownload
From f4f5223abbe4d3e9550d4fdd85d6289988bc9e44 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v22b 04/29] Make table_scan_bitmap_next_block() async-friendly

table_scan_bitmap_next_block() previously returned false when
table_scan_bitmap_next_tuple() should not be called for the tuples on
the page. This could happen when there were no visible tuples on the
page or when, due to concurrent activity on the table, the block
returned by the iterator is past the end of the table (as recorded when
the scan started).

That forced the caller to be responsible for determining if additional
blocks should be fetched and for invoking table_scan_bitmap_next_block()
for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
beginning of the scan) and for table_scan_bitmap_next_tuple() to return
false if there are no visible tuples on the page.

This also allows us to move responsibility for advancing the iterator to
table AM specific code. This means handling invalid blocks is entirely
up to the table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  54 ++++--
 src/backend/executor/nodeBitmapHeapscan.c | 198 ++++++++++------------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  77 ++++++---
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 203 insertions(+), 145 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f98ffe51759..e92c44d9049 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,18 +2120,48 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+			return false;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2150,16 +2180,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2255,7 +2276,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*exact_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e63f6f0429a..e8b4a754434 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,9 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -85,11 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -105,6 +96,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,8 +107,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
+			tbmiterator = tbm_begin_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -166,9 +159,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -207,46 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -267,45 +235,56 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
-		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
 
-		/*
-		 * Attempt to fetch tuple from AM.
-		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
+
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
+
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -331,13 +310,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -351,14 +334,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -383,7 +373,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -461,6 +454,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -518,6 +512,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -579,12 +575,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -592,13 +584,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -629,28 +621,24 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+
+	/*
+	 * close heap scan
+	 */
+	if (scanDesc)
+		table_endscan(scanDesc);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -683,8 +671,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -692,9 +678,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304ab..024dc08c420 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -36,6 +39,10 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
+	/* Iterators for Bitmap Table Scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9f11cf3729a..2f4e221870e 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "storage/read_stream.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
@@ -36,7 +37,6 @@ extern PGDLLIMPORT bool synchronize_seqscans;
 struct BulkInsertStateData;
 struct IndexInfo;
 struct SampleScanState;
-struct TBMIterateResult;
 struct VacuumParams;
 struct ValidateIndexState;
 
@@ -790,19 +790,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, `exact_pages` is incremented.
 	 *
@@ -821,7 +816,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -959,12 +954,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1024,6 +1023,21 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1034,6 +1048,21 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+	}
+
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1955,19 +1984,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. `lossy_pages` is incremented if the block's
- * representation in the bitmap is lossy; otherwise, `exact_pages` is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set by the table AM to indicate whether or not the tuples
+ * from this block should be rechecked. Tuples from lossy pages will always
+ * need to be rechecked, but some non-lossy pages' tuples may also require
+ * recheck.
+ *
+ * `blockno` is only used in bitmap table scan code to validate that the
+ * prefetch block is staying ahead of the current block.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1980,9 +2016,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8bc421e7c05..0af7906a184 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1795,8 +1795,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1805,9 +1803,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1815,8 +1815,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1825,9 +1823,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.45.2

v22b-0005-review.patchtext/x-patch; charset=UTF-8; name=v22b-0005-review.patchDownload
From 3382c9290f3c01389134156d95a9c92531748e48 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 21:03:49 +0200
Subject: [PATCH v22b 05/29] review

---
 src/backend/executor/nodeBitmapHeapscan.c | 14 ++++++++++++++
 src/include/access/tableam.h              |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e8b4a754434..6d7ef9ced19 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -270,6 +270,20 @@ new_page:
 
 		BitmapAdjustPrefetchIterator(node);
 
+		/*
+		 * XXX maybe add comment explaining what "false" means here?
+		 *
+		 * XXX I'm a bit unsure if this needs to be handled using goto. Wouldn't
+		 * it be simpler / easier to understand to have two nested loops?
+		 *
+		 * while (true)
+		 *		if (!table_scan_bitmap_next_block(...)) { break; }
+		 *		while (table_scan_bitmap_next_tuple(...)) {
+		 *			... process tuples ...
+		 *		}
+		 *
+		 * But I haven't tried implementing this.
+		 */
 		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2f4e221870e..c6a9fb34bd6 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -1023,6 +1023,7 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
+	/* XXX worth a comment? */
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
 		if (scan->shared_tbmiterator)
@@ -1048,6 +1049,7 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
+	/* XXX worth a comment? */
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
 	{
 		if (scan->shared_tbmiterator)
-- 
2.45.2

v22b-0006-Add-common-interface-for-TBMIterators.patchtext/x-patch; charset=UTF-8; name=v22b-0006-Add-common-interface-for-TBMIterators.patchDownload
From 90551a3422285d9c1207256e8f90dd5e8d753d29 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:41:05 -0400
Subject: [PATCH v22b 06/29] Add common interface for TBMIterators

Add and use TBMSerialIterator, which replaces the current TBMIterator
for serial use cases, and repurpose TBMIterator to be a unified
interface for both the serial and parallel TID Bitmap iterator
interfaces. This encapsulation simplifies call sites for callers
supporting both parallel and serial TID Bitmap access. TBMIterator is
not yet used in this commit.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/gin/ginget.c           |   8 +-
 src/backend/access/gin/ginscan.c          |   2 +-
 src/backend/access/heap/heapam_handler.c  |   2 +-
 src/backend/executor/nodeBitmapHeapscan.c |  22 ++---
 src/backend/nodes/tidbitmap.c             | 102 +++++++++++++++++-----
 src/include/access/gin_private.h          |   2 +-
 src/include/access/relscan.h              |   4 +-
 src/include/access/tableam.h              |   4 +-
 src/include/nodes/execnodes.h             |   2 +-
 src/include/nodes/tidbitmap.h             |  27 ++++--
 src/tools/pgindent/typedefs.list          |   1 +
 11 files changed, 126 insertions(+), 50 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..9c53ca19f06 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,7 @@ restartScanEntry:
 			if (entry->matchBitmap)
 			{
 				if (entry->matchIterator)
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -385,7 +385,7 @@ restartScanEntry:
 
 		if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
 		{
-			entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+			entry->matchIterator = tbm_begin_private_iterate(entry->matchBitmap);
 			entry->isFinished = false;
 		}
 	}
@@ -832,12 +832,12 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				entry->matchResult = tbm_private_iterate(entry->matchIterator);
 
 				if (entry->matchResult == NULL)
 				{
 					ItemPointerSetInvalid(&entry->curItem);
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
 					entry->isFinished = true;
 					break;
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544e..5b9a0eaea73 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -246,7 +246,7 @@ ginFreeScanKeys(GinScanOpaque so)
 		if (entry->list)
 			pfree(entry->list);
 		if (entry->matchIterator)
-			tbm_end_iterate(entry->matchIterator);
+			tbm_end_private_iterate(entry->matchIterator);
 		if (entry->matchBitmap)
 			tbm_free(entry->matchBitmap);
 	}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e92c44d9049..9a097f1ce76 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2143,7 +2143,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (scan->shared_tbmiterator)
 			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbmres = tbm_private_iterate(scan->tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6d7ef9ced19..12a85f0e72f 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,7 +96,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
+		TBMPrivateIterator *tbmiterator = NULL;
 		TBMSharedIterator *shared_tbmiterator = NULL;
 
 		if (!pstate)
@@ -107,12 +107,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_private_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
+				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
 				node->prefetch_pages = 0;
 				node->prefetch_target = -1;
 			}
@@ -289,7 +289,7 @@ new_page:
 			break;
 
 		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * If private, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
@@ -338,7 +338,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
@@ -348,7 +348,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = tbm_private_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -451,19 +451,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_private_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
+					tbm_end_private_iterate(prefetch_iterator);
 					node->prefetch_iterator = NULL;
 					break;
 				}
@@ -590,7 +590,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 	/* release bitmaps and buffers if any */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -646,7 +646,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * release bitmaps and buffers if any
 	 */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->shared_prefetch_iterator)
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..6d1fbcb03e9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -170,12 +170,12 @@ struct TIDBitmap
 };
 
 /*
- * When iterating over a bitmap in sorted order, a TBMIterator is used to
- * track our progress.  There can be several iterators scanning the same
- * bitmap concurrently.  Note that the bitmap becomes read-only as soon as
- * any iterator is created.
+ * When iterating over a backend-local bitmap in sorted order, a
+ * TBMPrivateIterator is used to track our progress.  There can be several
+ * iterators scanning the same bitmap concurrently.  Note that the bitmap
+ * becomes read-only as soon as any iterator is created.
  */
-struct TBMIterator
+struct TBMPrivateIterator
 {
 	TIDBitmap  *tbm;			/* TIDBitmap we're iterating over */
 	int			spageptr;		/* next spages index */
@@ -213,8 +213,8 @@ typedef struct PTIterationArray
 } PTIterationArray;
 
 /*
- * same as TBMIterator, but it is used for joint iteration, therefore this
- * also holds a reference to the shared state.
+ * same as TBMPrivateIterator, but it is used for joint iteration, therefore
+ * this also holds a reference to the shared state.
  */
 struct TBMSharedIterator
 {
@@ -673,31 +673,31 @@ tbm_is_empty(const TIDBitmap *tbm)
 }
 
 /*
- * tbm_begin_iterate - prepare to iterate through a TIDBitmap
+ * tbm_begin_private_iterate - prepare to iterate through a TIDBitmap
  *
- * The TBMIterator struct is created in the caller's memory context.
- * For a clean shutdown of the iteration, call tbm_end_iterate; but it's
- * okay to just allow the memory context to be released, too.  It is caller's
- * responsibility not to touch the TBMIterator anymore once the TIDBitmap
+ * The TBMPrivateIterator struct is created in the caller's memory context. For
+ * a clean shutdown of the iteration, call tbm_end_iterate; but it's okay to
+ * just allow the memory context to be released, too.  It is caller's
+ * responsibility not to touch the TBMPrivateIterator anymore once the TIDBitmap
  * is freed.
  *
  * NB: after this is called, it is no longer allowed to modify the contents
  * of the bitmap.  However, you can call this multiple times to scan the
  * contents repeatedly, including parallel scans.
  */
-TBMIterator *
-tbm_begin_iterate(TIDBitmap *tbm)
+TBMPrivateIterator *
+tbm_begin_private_iterate(TIDBitmap *tbm)
 {
-	TBMIterator *iterator;
+	TBMPrivateIterator *iterator;
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
 	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
+	 * Create the TBMPrivateIterator struct, with enough trailing space to
+	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
+											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
 	iterator->tbm = tbm;
 
 	/*
@@ -956,7 +956,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 }
 
 /*
- * tbm_iterate - scan through next page of a TIDBitmap
+ * tbm_private_iterate - scan through next page of a TIDBitmap
  *
  * Returns a TBMIterateResult representing one page, or NULL if there are
  * no more pages to scan.  Pages are guaranteed to be delivered in numerical
@@ -968,7 +968,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  * testing, recheck is always set true when ntuples < 0.)
  */
 TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+tbm_private_iterate(TBMPrivateIterator *iterator)
 {
 	TIDBitmap  *tbm = iterator->tbm;
 	TBMIterateResult *output = &(iterator->output);
@@ -1143,7 +1143,7 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
  * bitmap to return to read/write status when there are no more iterators.)
  */
 void
-tbm_end_iterate(TBMIterator *iterator)
+tbm_end_private_iterate(TBMPrivateIterator *iterator)
 {
 	pfree(iterator);
 }
@@ -1556,3 +1556,61 @@ tbm_calculate_entries(double maxbytes)
 
 	return nbuckets;
 }
+
+/*
+ * Start iteration on a shared or non-shared bitmap iterator. Note that tbm
+ * will only be provided by private BitmapHeapScan callers. dsa and dsp will
+ * only be provided by parallel BitmapHeapScan callers. For shared callers, one
+ * process must already have called tbm_prepare_shared_iterate() to create and
+ * set up the TBMSharedIteratorState. The TBMIterator is passed by reference to
+ * accommodate callers who would like to allocate it inside an existing struct.
+ */
+void
+tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+				  dsa_area *dsa, dsa_pointer dsp)
+{
+	Assert(iterator);
+
+	iterator->private = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = false;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+		iterator->parallel = tbm_attach_shared_iterate(dsa, dsp);
+	else
+		iterator->private = tbm_begin_private_iterate(tbm);
+}
+
+/*
+ * Clean up shared or non-shared bitmap iterator.
+ */
+void
+tbm_end_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->private)
+		tbm_end_private_iterate(iterator->private);
+	else if (iterator->parallel)
+		tbm_end_shared_iterate(iterator->parallel);
+
+	iterator->private = NULL;
+	iterator->parallel = NULL;
+	iterator->exhausted = true;
+}
+
+/*
+ * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
+ */
+TBMIterateResult *
+tbm_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+	Assert(!iterator->exhausted);
+
+	if (iterator->private)
+		return tbm_private_iterate(iterator->private);
+	else
+		return tbm_shared_iterate(iterator->parallel);
+}
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..78800509367 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
-	TBMIterator *matchIterator;
+	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 024dc08c420..159921ffb50 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,7 +24,7 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
+struct TBMPrivateIterator;
 struct TBMSharedIterator;
 
 /*
@@ -40,7 +40,7 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Iterators for Bitmap Table Scans */
-	struct TBMIterator *tbmiterator;
+	struct TBMPrivateIterator *tbmiterator;
 	struct TBMSharedIterator *shared_tbmiterator;
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index c6a9fb34bd6..5dc39f85925 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -1034,7 +1034,7 @@ table_endscan(TableScanDesc scan)
 
 		if (scan->tbmiterator)
 		{
-			tbm_end_iterate(scan->tbmiterator);
+			tbm_end_private_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
 	}
@@ -1060,7 +1060,7 @@ table_rescan(TableScanDesc scan,
 
 		if (scan->tbmiterator)
 		{
-			tbm_end_iterate(scan->tbmiterator);
+			tbm_end_private_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
 	}
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0af7906a184..81447fea8c5 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1818,7 +1818,7 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
+	TBMPrivateIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..472c0b444bf 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -32,8 +32,8 @@
  */
 typedef struct TIDBitmap TIDBitmap;
 
-/* Likewise, TBMIterator is private */
-typedef struct TBMIterator TBMIterator;
+/* Likewise, TBMPrivateIterator is private */
+typedef struct TBMPrivateIterator TBMPrivateIterator;
 typedef struct TBMSharedIterator TBMSharedIterator;
 
 /* Result structure for tbm_iterate */
@@ -46,6 +46,17 @@ typedef struct TBMIterateResult
 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
 } TBMIterateResult;
 
+/*
+ * Callers with both private and parallel implementations can use this unified
+ * API.
+ */
+typedef struct TBMIterator
+{
+	TBMPrivateIterator *private;
+	TBMSharedIterator *parallel;
+	bool		exhausted;
+} TBMIterator;
+
 /* function prototypes in nodes/tidbitmap.c */
 
 extern TIDBitmap *tbm_create(long maxbytes, dsa_area *dsa);
@@ -62,14 +73,20 @@ extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
-extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
 extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
-extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
 													dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+extern void tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+							  dsa_area *dsa, dsa_pointer dsp);
+extern void tbm_end_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+
+
 #endif							/* TIDBITMAP_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 61ad417cde6..757a9a3a41e 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2795,6 +2795,7 @@ TAR_MEMBER
 TBMIterateResult
 TBMIteratingState
 TBMIterator
+TBMPrivateIterator
 TBMSharedIterator
 TBMSharedIteratorState
 TBMStatus
-- 
2.45.2

v22b-0007-review.patchtext/x-patch; charset=UTF-8; name=v22b-0007-review.patchDownload
From ef1f05c22d39e393d233b17fc95775a1d50a1ba6 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 21:27:34 +0200
Subject: [PATCH v22b 07/29] review

---
 src/backend/nodes/tidbitmap.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 6d1fbcb03e9..eeef413b7f5 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -174,6 +174,9 @@ struct TIDBitmap
  * TBMPrivateIterator is used to track our progress.  There can be several
  * iterators scanning the same bitmap concurrently.  Note that the bitmap
  * becomes read-only as soon as any iterator is created.
+ *
+ * XXX Doesn't the commit message call this TBMSerialIterator? I'm not sure
+ * which of those two options is better. Maybe the "private" is better.
  */
 struct TBMPrivateIterator
 {
@@ -1564,6 +1567,8 @@ tbm_calculate_entries(double maxbytes)
  * process must already have called tbm_prepare_shared_iterate() to create and
  * set up the TBMSharedIteratorState. The TBMIterator is passed by reference to
  * accommodate callers who would like to allocate it inside an existing struct.
+ *
+ * XXX Maybe don't say "non-shared" but "private"? Seems a bit confusing.
  */
 void
 tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
-- 
2.45.2

v22b-0008-BitmapHeapScan-initialize-some-prefetch-state-e.patchtext/x-patch; charset=UTF-8; name=v22b-0008-BitmapHeapScan-initialize-some-prefetch-state-e.patchDownload
From 2a42990c588a395afa824185e308713a57527a6b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:51:11 -0400
Subject: [PATCH v22b 08/29] BitmapHeapScan initialize some prefetch state
 elsewhere

The prefetch_target and prefetch_pages members can be initialized in the
scan and rescan functions. This makes it more straightforward to use the
unified TBMIterator API for BitmapHeapScan.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 12a85f0e72f..71c5a880a6d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -111,11 +111,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
-			{
 				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
 #endif							/* USE_PREFETCH */
 		}
 		else
@@ -605,6 +601,9 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
 	node->pfblockno = InvalidBlockNumber;
+	/* Only used for serial BHS */
+	node->prefetch_pages = 0;
+	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -690,7 +689,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->lossy_pages = 0;
 	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
+	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
@@ -826,7 +825,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -853,6 +852,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
+	pstate->prefetch_pages = 0;
+	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-- 
2.45.2

v22b-0009-BitmapHeapScan-uses-unified-iterator.patchtext/x-patch; charset=UTF-8; name=v22b-0009-BitmapHeapScan-uses-unified-iterator.patchDownload
From 45113a98b461bb8e61f6c716cf8ca381f3dc6c9e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:39:04 -0400
Subject: [PATCH v22b 09/29] BitmapHeapScan uses unified iterator

With the repurposing of TBMIterator as an interface for both parallel
and serial iteration through TIDBitmaps, BitmapHeapScan may now use it
since it has both parallel and serial iteration.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 132 ++++++++--------------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |  34 +-----
 src/include/nodes/execnodes.h             |   4 +-
 5 files changed, 54 insertions(+), 128 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 9a097f1ce76..94aa814bfa5 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2140,10 +2140,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_private_iterate(scan->tbmiterator);
+		tbmres = tbm_iterate(&scan->tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 71c5a880a6d..43297783ab3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -69,7 +69,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -80,7 +79,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -96,76 +94,49 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMPrivateIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
-
 		if (!pstate)
 		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
-			if (!tbm || !IsA(tbm, TIDBitmap))
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
-			node->tbm = tbm;
-			tbmiterator = tbm_begin_private_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
-#endif							/* USE_PREFETCH */
 		}
-		else
+		else if (BitmapShouldInitializeSharedState(pstate))
 		{
 			/*
 			 * The leader will immediately come out of the function, but
 			 * others will be blocked until leader populates the TBM and wakes
 			 * them up.
 			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
-
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+				elog(ERROR, "unrecognized result from subplan");
 
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+				pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(node->tbm);
 			}
-#endif							/* USE_PREFETCH */
+#endif
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(pstate);
 		}
 
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+			tbm_begin_iterate(&node->prefetch_iterator, node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -194,8 +165,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
+						  pstate ?
+						  pstate->tbmiterator :
+						  InvalidDsaPointer);
+
 		node->initialized = true;
 
 		goto new_page;
@@ -289,7 +263,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!node->prefetch_iterator.exhausted &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -334,17 +308,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_private_iterate(prefetch_iterator);
+			tbmpre = tbm_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -361,7 +335,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -382,9 +356,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -447,20 +421,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_private_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_private_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -488,9 +461,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!prefetch_iterator->exhausted)
 		{
 			while (1)
 			{
@@ -513,12 +486,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -585,18 +557,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
+	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -644,12 +611,9 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
+	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -687,11 +651,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 159921ffb50..b4511677b1d 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/itup.h"
+#include "nodes/tidbitmap.h"
 #include "port/atomics.h"
 #include "storage/buf.h"
 #include "storage/spin.h"
@@ -24,9 +25,6 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMPrivateIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,8 +38,7 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Iterators for Bitmap Table Scans */
-	struct TBMPrivateIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	TBMIterator tbmiterator;
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5dc39f85925..422b90b17f0 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -954,16 +954,12 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
 /*
@@ -1025,19 +1021,7 @@ table_endscan(TableScanDesc scan)
 {
 	/* XXX worth a comment? */
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_private_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+		tbm_end_iterate(&scan->tbmiterator);
 
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
@@ -1051,19 +1035,7 @@ table_rescan(TableScanDesc scan,
 {
 	/* XXX worth a comment? */
 	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-	{
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_private_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
-	}
+		tbm_end_iterate(&scan->tbmiterator);
 
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 81447fea8c5..1f262db776c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1803,7 +1803,6 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1818,12 +1817,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMPrivateIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
+	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
-- 
2.45.2

v22b-0010-review.patchtext/x-patch; charset=UTF-8; name=v22b-0010-review.patchDownload
From b1ec31d645fea52f7c71bc9717ef182bf8f8cd18 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 22:03:15 +0200
Subject: [PATCH v22b 10/29] review

---
 src/backend/executor/nodeBitmapHeapscan.c | 5 +++++
 src/include/nodes/execnodes.h             | 1 +
 2 files changed, 6 insertions(+)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 43297783ab3..7ca986ae5b2 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -263,6 +263,8 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
+			/* XXX shouldn't we have a function instead of checking the
+			 * field directly? */
 			!node->prefetch_iterator.exhausted &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
@@ -557,6 +559,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
+	/* XXX seems it should not be right after the comment, also shouldn't
+	 * we still reset the prefetch_iterator field to NULL? */
 	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
@@ -611,6 +615,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * release bitmaps and buffers if any
 	 */
+	/* XXX misleading place, not a bitmap or a buffer */
 	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 1f262db776c..f47e6c75b7c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1821,6 +1821,7 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
+	/* XXX probably should be kept in the order per comment */
 	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-- 
2.45.2

v22b-0011-BitmapHeapScan-Make-prefetch-sync-error-more-de.patchtext/x-patch; charset=UTF-8; name=v22b-0011-BitmapHeapScan-Make-prefetch-sync-error-more-de.patchDownload
From ebc5e04f83bd0dbb1735ca7571c71859b15fca7e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Jun 2024 12:40:58 -0400
Subject: [PATCH v22b 11/29] BitmapHeapScan: Make prefetch sync error more
 detailed

Add the prefetch and current block numbers to the error message emitted
when the prefetch iterator gets out of sync with the main iterator in
serial bitmap table scan.
---
 src/backend/executor/nodeBitmapHeapscan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 7ca986ae5b2..d638b73b7d2 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -267,7 +267,7 @@ new_page:
 			 * field directly? */
 			!node->prefetch_iterator.exhausted &&
 			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
+			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
 
 		/* Adjust the prefetch target */
 		BitmapAdjustPrefetchTarget(node);
-- 
2.45.2

v22b-0012-Push-current-scan-descriptor-into-specialized-s.patchtext/x-patch; charset=UTF-8; name=v22b-0012-Push-current-scan-descriptor-into-specialized-s.patchDownload
From 96d21a4c65e552e4dab962bb9237f3dd4d02c0bd Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:41:49 -0400
Subject: [PATCH v22b 12/29] Push current scan descriptor into specialized scan
 states

To allow Bitmap Table Scans to use a forthcoming bitmap table-specific
scan descriptor in table AM-agnostic code, move the current scan
descriptor out of the generic ScanState node.

This adds a bit of duplication, but a few of the scan types don't use
the current scan descriptor anyway. Additionally, for many scan types,
the scan descriptor is initialized later in execution than the other
members of the generic ScanState.
---
 src/backend/executor/nodeBitmapHeapscan.c  | 10 +++++-----
 src/backend/executor/nodeBitmapIndexscan.c |  1 -
 src/backend/executor/nodeIndexonlyscan.c   |  1 -
 src/backend/executor/nodeIndexscan.c       |  1 -
 src/backend/executor/nodeSamplescan.c      | 14 +++++++-------
 src/backend/executor/nodeSeqscan.c         | 14 +++++++-------
 src/backend/executor/nodeTidrangescan.c    |  8 ++++----
 src/backend/executor/nodeTidscan.c         | 18 +++++++++---------
 src/include/nodes/execnodes.h              | 10 ++++++++--
 9 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d638b73b7d2..37decac7acb 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -78,7 +78,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -162,7 +162,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  NULL,
 									  need_tuples);
 
-			node->ss.ss_currentScanDesc = scan;
+			node->ss_currentScanDesc = scan;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -555,8 +555,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss_currentScanDesc)
+		table_rescan(node->ss_currentScanDesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	/* XXX seems it should not be right after the comment, also shouldn't
@@ -598,7 +598,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * extract information from the node
 	 */
-	scanDesc = node->ss.ss_currentScanDesc;
+	scanDesc = node->ss_currentScanDesc;
 
 	/*
 	 * close down subplans
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index 6df8e17ec84..b4af2f17ed4 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -225,7 +225,6 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
 	 */
 
 	indexstate->ss.ss_currentRelation = NULL;
-	indexstate->ss.ss_currentScanDesc = NULL;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index b49194c0167..194c544c167 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -534,7 +534,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	indexstate->ss.ss_currentRelation = currentRelation;
-	indexstate->ss.ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * Build the scan tuple type using the indextlist generated by the
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 8000feff4c9..8260cb0954d 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -910,7 +910,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	indexstate->ss.ss_currentRelation = currentRelation;
-	indexstate->ss.ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 714b076e646..d15bf249d31 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -123,7 +123,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 							 eflags);
 
 	/* we won't set up the HeapScanDesc till later */
-	scanstate->ss.ss_currentScanDesc = NULL;
+	scanstate->ss_currentScanDesc = NULL;
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
@@ -187,8 +187,8 @@ ExecEndSampleScan(SampleScanState *node)
 	/*
 	 * close heap scan
 	 */
-	if (node->ss.ss_currentScanDesc)
-		table_endscan(node->ss.ss_currentScanDesc);
+	if (node->ss_currentScanDesc)
+		table_endscan(node->ss_currentScanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -289,9 +289,9 @@ tablesample_init(SampleScanState *scanstate)
 	allow_sync = (tsm->NextSampleBlock == NULL);
 
 	/* Now we can create or reset the HeapScanDesc */
-	if (scanstate->ss.ss_currentScanDesc == NULL)
+	if (scanstate->ss_currentScanDesc == NULL)
 	{
-		scanstate->ss.ss_currentScanDesc =
+		scanstate->ss_currentScanDesc =
 			table_beginscan_sampling(scanstate->ss.ss_currentRelation,
 									 scanstate->ss.ps.state->es_snapshot,
 									 0, NULL,
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
 	}
 	else
 	{
-		table_rescan_set_params(scanstate->ss.ss_currentScanDesc, NULL,
+		table_rescan_set_params(scanstate->ss_currentScanDesc, NULL,
 								scanstate->use_bulkread,
 								allow_sync,
 								scanstate->use_pagemode);
@@ -319,7 +319,7 @@ tablesample_init(SampleScanState *scanstate)
 static TupleTableSlot *
 tablesample_getnext(SampleScanState *scanstate)
 {
-	TableScanDesc scan = scanstate->ss.ss_currentScanDesc;
+	TableScanDesc scan = scanstate->ss_currentScanDesc;
 	TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
 
 	ExecClearTuple(slot);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 7cb12a11c2d..89f5e8c80da 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -57,7 +57,7 @@ SeqNext(SeqScanState *node)
 	/*
 	 * get information from the estate and scan state
 	 */
-	scandesc = node->ss.ss_currentScanDesc;
+	scandesc = node->ss_currentScanDesc;
 	estate = node->ss.ps.state;
 	direction = estate->es_direction;
 	slot = node->ss.ss_ScanTupleSlot;
@@ -71,7 +71,7 @@ SeqNext(SeqScanState *node)
 		scandesc = table_beginscan(node->ss.ss_currentRelation,
 								   estate->es_snapshot,
 								   0, NULL);
-		node->ss.ss_currentScanDesc = scandesc;
+		node->ss_currentScanDesc = scandesc;
 	}
 
 	/*
@@ -188,7 +188,7 @@ ExecEndSeqScan(SeqScanState *node)
 	/*
 	 * get information from node
 	 */
-	scanDesc = node->ss.ss_currentScanDesc;
+	scanDesc = node->ss_currentScanDesc;
 
 	/*
 	 * close heap scan
@@ -213,7 +213,7 @@ ExecReScanSeqScan(SeqScanState *node)
 {
 	TableScanDesc scan;
 
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 
 	if (scan != NULL)
 		table_rescan(scan,		/* scan desc */
@@ -264,7 +264,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 								  pscan,
 								  estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss.ss_currentScanDesc =
+	node->ss_currentScanDesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
 
@@ -280,7 +280,7 @@ ExecSeqScanReInitializeDSM(SeqScanState *node,
 {
 	ParallelTableScanDesc pscan;
 
-	pscan = node->ss.ss_currentScanDesc->rs_parallel;
+	pscan = node->ss_currentScanDesc->rs_parallel;
 	table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
 }
 
@@ -297,6 +297,6 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
 	ParallelTableScanDesc pscan;
 
 	pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
-	node->ss.ss_currentScanDesc =
+	node->ss_currentScanDesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index 9aa7683d7e3..bc523a5d773 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -227,7 +227,7 @@ TidRangeNext(TidRangeScanState *node)
 	/*
 	 * extract necessary information from TID scan node
 	 */
-	scandesc = node->ss.ss_currentScanDesc;
+	scandesc = node->ss_currentScanDesc;
 	estate = node->ss.ps.state;
 	slot = node->ss.ss_ScanTupleSlot;
 	direction = estate->es_direction;
@@ -244,7 +244,7 @@ TidRangeNext(TidRangeScanState *node)
 												estate->es_snapshot,
 												&node->trss_mintid,
 												&node->trss_maxtid);
-			node->ss.ss_currentScanDesc = scandesc;
+			node->ss_currentScanDesc = scandesc;
 		}
 		else
 		{
@@ -326,7 +326,7 @@ ExecReScanTidRangeScan(TidRangeScanState *node)
 void
 ExecEndTidRangeScan(TidRangeScanState *node)
 {
-	TableScanDesc scan = node->ss.ss_currentScanDesc;
+	TableScanDesc scan = node->ss_currentScanDesc;
 
 	if (scan != NULL)
 		table_endscan(scan);
@@ -375,7 +375,7 @@ ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidrangestate->ss.ss_currentRelation = currentRelation;
-	tidrangestate->ss.ss_currentScanDesc = NULL;	/* no table scan here */
+	tidrangestate->ss_currentScanDesc = NULL;	/* no table scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 864a9013b62..f08bc7daa89 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -145,11 +145,11 @@ TidListEval(TidScanState *tidstate)
 	 * the size of the table), so it makes sense to delay that until needed -
 	 * the node might never get executed.
 	 */
-	if (tidstate->ss.ss_currentScanDesc == NULL)
-		tidstate->ss.ss_currentScanDesc =
+	if (tidstate->ss_currentScanDesc == NULL)
+		tidstate->ss_currentScanDesc =
 			table_beginscan_tid(tidstate->ss.ss_currentRelation,
 								tidstate->ss.ps.state->es_snapshot);
-	scan = tidstate->ss.ss_currentScanDesc;
+	scan = tidstate->ss_currentScanDesc;
 
 	/*
 	 * We initialize the array with enough slots for the case that all quals
@@ -336,7 +336,7 @@ TidNext(TidScanState *node)
 	if (node->tss_TidList == NULL)
 		TidListEval(node);
 
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 	tidList = node->tss_TidList;
 	numTids = node->tss_NumTids;
 
@@ -453,8 +453,8 @@ ExecReScanTidScan(TidScanState *node)
 	node->tss_TidPtr = -1;
 
 	/* not really necessary, but seems good form */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss_currentScanDesc)
+		table_rescan(node->ss_currentScanDesc, NULL);
 
 	ExecScanReScan(&node->ss);
 }
@@ -469,8 +469,8 @@ ExecReScanTidScan(TidScanState *node)
 void
 ExecEndTidScan(TidScanState *node)
 {
-	if (node->ss.ss_currentScanDesc)
-		table_endscan(node->ss.ss_currentScanDesc);
+	if (node->ss_currentScanDesc)
+		table_endscan(node->ss_currentScanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -518,7 +518,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidstate->ss.ss_currentRelation = currentRelation;
-	tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
+	tidstate->ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index f47e6c75b7c..d1b1a9e0d79 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1555,7 +1555,6 @@ typedef struct BitmapOrState
  *		retrieved from the subplan.
  *
  *		currentRelation    relation being scanned (NULL if none)
- *		currentScanDesc    current scan descriptor for scan (NULL if none)
  *		ScanTupleSlot	   pointer to slot in tuple table holding scan tuple
  * ----------------
  */
@@ -1563,7 +1562,6 @@ typedef struct ScanState
 {
 	PlanState	ps;				/* its first field is NodeTag */
 	Relation	ss_currentRelation;
-	struct TableScanDescData *ss_currentScanDesc;
 	TupleTableSlot *ss_ScanTupleSlot;
 } ScanState;
 
@@ -1574,6 +1572,7 @@ typedef struct ScanState
 typedef struct SeqScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
 	Size		pscan_len;		/* size of parallel heap scan descriptor */
 } SeqScanState;
 
@@ -1584,6 +1583,7 @@ typedef struct SeqScanState
 typedef struct SampleScanState
 {
 	ScanState	ss;
+	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
 	List	   *args;			/* expr states for TABLESAMPLE params */
 	ExprState  *repeatable;		/* expr state for REPEATABLE expr */
 	/* use struct pointer to avoid including tsmapi.h here */
@@ -1793,6 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1812,6 +1813,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
@@ -1832,6 +1834,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1842,6 +1845,7 @@ typedef struct BitmapHeapScanState
 typedef struct TidScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	List	   *tss_tidexprs;
 	bool		tss_isCurrentOf;
 	int			tss_NumTids;
@@ -1852,6 +1856,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
+ *      currentScanDesc    current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
@@ -1861,6 +1866,7 @@ typedef struct TidScanState
 typedef struct TidRangeScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	List	   *trss_tidexprs;
 	ItemPointerData trss_mintid;
 	ItemPointerData trss_maxtid;
-- 
2.45.2

v22b-0013-review.patchtext/x-patch; charset=UTF-8; name=v22b-0013-review.patchDownload
From 4aedd8875f6f5edd8fcd28dd63c15ae4002cd43f Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 22:33:04 +0200
Subject: [PATCH v22b 13/29] review

---
 src/include/nodes/execnodes.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d1b1a9e0d79..34891afd0b2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1793,7 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *		currentScanDesc    current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1834,7 +1834,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *		currentScanDesc    current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1856,7 +1856,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
- *      currentScanDesc    current scan descriptor for scan (NULL if none)
+ *		currentScanDesc    current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
-- 
2.45.2

v22b-0014-Remove-ss_current-prefix-from-ss_currentScanDes.patchtext/x-patch; charset=UTF-8; name=v22b-0014-Remove-ss_current-prefix-from-ss_currentScanDes.patchDownload
From ca4cd39029fb694e032089d95e1db9238225abce Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 22:33:56 +0200
Subject: [PATCH v22b 14/29] Remove ss_current prefix from ss_currentScanDesc
 in nodes

A previous commit pushed down the current scan descriptor from the
generic ScanState into the specialized scan states. The naming
convention was left as is to make the diff easier to understand. Rename
it, as the ss_ prefix is no longer correct once this member is in the
other node structs.
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/backend/executor/nodeSamplescan.c     | 14 +++++++-------
 src/backend/executor/nodeSeqscan.c        | 14 +++++++-------
 src/backend/executor/nodeTidrangescan.c   |  8 ++++----
 src/backend/executor/nodeTidscan.c        | 18 +++++++++---------
 src/include/nodes/execnodes.h             | 16 ++++++++--------
 6 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 37decac7acb..fd58b202c5d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -78,7 +78,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -162,7 +162,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  NULL,
 									  need_tuples);
 
-			node->ss_currentScanDesc = scan;
+			node->scandesc = scan;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -555,8 +555,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* rescan to release any page pin */
-	if (node->ss_currentScanDesc)
-		table_rescan(node->ss_currentScanDesc, NULL);
+	if (node->scandesc)
+		table_rescan(node->scandesc, NULL);
 
 	/* release bitmaps and buffers if any */
 	/* XXX seems it should not be right after the comment, also shouldn't
@@ -598,7 +598,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * extract information from the node
 	 */
-	scanDesc = node->ss_currentScanDesc;
+	scanDesc = node->scandesc;
 
 	/*
 	 * close down subplans
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index d15bf249d31..581bd3ed3b1 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -123,7 +123,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 							 eflags);
 
 	/* we won't set up the HeapScanDesc till later */
-	scanstate->ss_currentScanDesc = NULL;
+	scanstate->scandesc = NULL;
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
@@ -187,8 +187,8 @@ ExecEndSampleScan(SampleScanState *node)
 	/*
 	 * close heap scan
 	 */
-	if (node->ss_currentScanDesc)
-		table_endscan(node->ss_currentScanDesc);
+	if (node->scandesc)
+		table_endscan(node->scandesc);
 }
 
 /* ----------------------------------------------------------------
@@ -289,9 +289,9 @@ tablesample_init(SampleScanState *scanstate)
 	allow_sync = (tsm->NextSampleBlock == NULL);
 
 	/* Now we can create or reset the HeapScanDesc */
-	if (scanstate->ss_currentScanDesc == NULL)
+	if (scanstate->scandesc == NULL)
 	{
-		scanstate->ss_currentScanDesc =
+		scanstate->scandesc =
 			table_beginscan_sampling(scanstate->ss.ss_currentRelation,
 									 scanstate->ss.ps.state->es_snapshot,
 									 0, NULL,
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
 	}
 	else
 	{
-		table_rescan_set_params(scanstate->ss_currentScanDesc, NULL,
+		table_rescan_set_params(scanstate->scandesc, NULL,
 								scanstate->use_bulkread,
 								allow_sync,
 								scanstate->use_pagemode);
@@ -319,7 +319,7 @@ tablesample_init(SampleScanState *scanstate)
 static TupleTableSlot *
 tablesample_getnext(SampleScanState *scanstate)
 {
-	TableScanDesc scan = scanstate->ss_currentScanDesc;
+	TableScanDesc scan = scanstate->scandesc;
 	TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
 
 	ExecClearTuple(slot);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 89f5e8c80da..5aaad645950 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -57,7 +57,7 @@ SeqNext(SeqScanState *node)
 	/*
 	 * get information from the estate and scan state
 	 */
-	scandesc = node->ss_currentScanDesc;
+	scandesc = node->scandesc;
 	estate = node->ss.ps.state;
 	direction = estate->es_direction;
 	slot = node->ss.ss_ScanTupleSlot;
@@ -71,7 +71,7 @@ SeqNext(SeqScanState *node)
 		scandesc = table_beginscan(node->ss.ss_currentRelation,
 								   estate->es_snapshot,
 								   0, NULL);
-		node->ss_currentScanDesc = scandesc;
+		node->scandesc = scandesc;
 	}
 
 	/*
@@ -188,7 +188,7 @@ ExecEndSeqScan(SeqScanState *node)
 	/*
 	 * get information from node
 	 */
-	scanDesc = node->ss_currentScanDesc;
+	scanDesc = node->scandesc;
 
 	/*
 	 * close heap scan
@@ -213,7 +213,7 @@ ExecReScanSeqScan(SeqScanState *node)
 {
 	TableScanDesc scan;
 
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 
 	if (scan != NULL)
 		table_rescan(scan,		/* scan desc */
@@ -264,7 +264,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 								  pscan,
 								  estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss_currentScanDesc =
+	node->scandesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
 
@@ -280,7 +280,7 @@ ExecSeqScanReInitializeDSM(SeqScanState *node,
 {
 	ParallelTableScanDesc pscan;
 
-	pscan = node->ss_currentScanDesc->rs_parallel;
+	pscan = node->scandesc->rs_parallel;
 	table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
 }
 
@@ -297,6 +297,6 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
 	ParallelTableScanDesc pscan;
 
 	pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
-	node->ss_currentScanDesc =
+	node->scandesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index bc523a5d773..3a2ba169e9d 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -227,7 +227,7 @@ TidRangeNext(TidRangeScanState *node)
 	/*
 	 * extract necessary information from TID scan node
 	 */
-	scandesc = node->ss_currentScanDesc;
+	scandesc = node->scandesc;
 	estate = node->ss.ps.state;
 	slot = node->ss.ss_ScanTupleSlot;
 	direction = estate->es_direction;
@@ -244,7 +244,7 @@ TidRangeNext(TidRangeScanState *node)
 												estate->es_snapshot,
 												&node->trss_mintid,
 												&node->trss_maxtid);
-			node->ss_currentScanDesc = scandesc;
+			node->scandesc = scandesc;
 		}
 		else
 		{
@@ -326,7 +326,7 @@ ExecReScanTidRangeScan(TidRangeScanState *node)
 void
 ExecEndTidRangeScan(TidRangeScanState *node)
 {
-	TableScanDesc scan = node->ss_currentScanDesc;
+	TableScanDesc scan = node->scandesc;
 
 	if (scan != NULL)
 		table_endscan(scan);
@@ -375,7 +375,7 @@ ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidrangestate->ss.ss_currentRelation = currentRelation;
-	tidrangestate->ss_currentScanDesc = NULL;	/* no table scan here */
+	tidrangestate->scandesc = NULL; /* no table scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index f08bc7daa89..becf0274678 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -145,11 +145,11 @@ TidListEval(TidScanState *tidstate)
 	 * the size of the table), so it makes sense to delay that until needed -
 	 * the node might never get executed.
 	 */
-	if (tidstate->ss_currentScanDesc == NULL)
-		tidstate->ss_currentScanDesc =
+	if (tidstate->scandesc == NULL)
+		tidstate->scandesc =
 			table_beginscan_tid(tidstate->ss.ss_currentRelation,
 								tidstate->ss.ps.state->es_snapshot);
-	scan = tidstate->ss_currentScanDesc;
+	scan = tidstate->scandesc;
 
 	/*
 	 * We initialize the array with enough slots for the case that all quals
@@ -336,7 +336,7 @@ TidNext(TidScanState *node)
 	if (node->tss_TidList == NULL)
 		TidListEval(node);
 
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 	tidList = node->tss_TidList;
 	numTids = node->tss_NumTids;
 
@@ -453,8 +453,8 @@ ExecReScanTidScan(TidScanState *node)
 	node->tss_TidPtr = -1;
 
 	/* not really necessary, but seems good form */
-	if (node->ss_currentScanDesc)
-		table_rescan(node->ss_currentScanDesc, NULL);
+	if (node->scandesc)
+		table_rescan(node->scandesc, NULL);
 
 	ExecScanReScan(&node->ss);
 }
@@ -469,8 +469,8 @@ ExecReScanTidScan(TidScanState *node)
 void
 ExecEndTidScan(TidScanState *node)
 {
-	if (node->ss_currentScanDesc)
-		table_endscan(node->ss_currentScanDesc);
+	if (node->scandesc)
+		table_endscan(node->scandesc);
 }
 
 /* ----------------------------------------------------------------
@@ -518,7 +518,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidstate->ss.ss_currentRelation = currentRelation;
-	tidstate->ss_currentScanDesc = NULL;	/* no heap scan here */
+	tidstate->scandesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 34891afd0b2..c8cc9f4295e 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1572,7 +1572,7 @@ typedef struct ScanState
 typedef struct SeqScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
+	struct TableScanDescData *scandesc; /* current scan descriptor */
 	Size		pscan_len;		/* size of parallel heap scan descriptor */
 } SeqScanState;
 
@@ -1583,7 +1583,7 @@ typedef struct SeqScanState
 typedef struct SampleScanState
 {
 	ScanState	ss;
-	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
+	struct TableScanDescData *scandesc; /* current scan descriptor */
 	List	   *args;			/* expr states for TABLESAMPLE params */
 	ExprState  *repeatable;		/* expr state for REPEATABLE expr */
 	/* use struct pointer to avoid including tsmapi.h here */
@@ -1793,7 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
- *		currentScanDesc    current scan descriptor for scan (NULL if none)
+ *		scandesc		   current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1813,7 +1813,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
@@ -1834,7 +1834,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
- *		currentScanDesc    current scan descriptor for scan (NULL if none)
+ *		scandesc	   current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1845,7 +1845,7 @@ typedef struct BitmapHeapScanState
 typedef struct TidScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	List	   *tss_tidexprs;
 	bool		tss_isCurrentOf;
 	int			tss_NumTids;
@@ -1856,7 +1856,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
- *		currentScanDesc    current scan descriptor for scan (NULL if none)
+ *		scandesc			current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
@@ -1866,7 +1866,7 @@ typedef struct TidScanState
 typedef struct TidRangeScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	List	   *trss_tidexprs;
 	ItemPointerData trss_mintid;
 	ItemPointerData trss_maxtid;
-- 
2.45.2

v22b-0015-Add-scan_in_progress-to-BitmapHeapScanState.patchtext/x-patch; charset=UTF-8; name=v22b-0015-Add-scan_in_progress-to-BitmapHeapScanState.patchDownload
From c8a9b5a0db622323a7a928376e8f5ef528991522 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 13 Jun 2024 13:38:46 -0400
Subject: [PATCH v22b 15/29] Add scan_in_progress to BitmapHeapScanState

Instead of checking that the scan descriptor hasn't been allocated yet,
use a dedicated variable, scan_in_progress. This feels cleaner and also
allows us to more easily extract the per scan setup into a separate
function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 5 ++++-
 src/include/nodes/execnodes.h             | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fd58b202c5d..d9c6f252138 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -141,7 +141,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
 		 */
-		if (!scan)
+		if (!node->scan_in_progress)
 		{
 			bool		need_tuples = false;
 
@@ -163,8 +163,10 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  need_tuples);
 
 			node->scandesc = scan;
+			node->scan_in_progress = true;
 		}
 
+		Assert(scan);
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
@@ -659,6 +661,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
+	scanstate->scan_in_progress = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index c8cc9f4295e..4c0c5c14f64 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1804,6 +1804,7 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
+ *		scan_in_progress   is this a rescan
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1823,6 +1824,7 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
+	bool		scan_in_progress;
 	/* XXX probably should be kept in the order per comment */
 	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
-- 
2.45.2

v22b-0016-Make-new-bitmap-table-scan-and-bitmap-heap-scan.patchtext/x-patch; charset=UTF-8; name=v22b-0016-Make-new-bitmap-table-scan-and-bitmap-heap-scan.patchDownload
From 0502feef8477eaa4b2f67399010663e033eaa6df Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:51:05 -0400
Subject: [PATCH v22b 16/29] Make new bitmap table scan and bitmap heap scan
 descriptors

The number of fields from the TableScanDescData required for bitmap
table scans is few. Create a new BitmapTableScanDesc with only those
members needed for bitmap table scans and remove the bitmap table
scan-only fields from the generic TableScanDescData.

Also add a BitmapHeapScanDesc structure for the heap AM implementation
of bitmap table scans. Add table AM callbacks for starting, restarting,
and ending these scans.

While reducing the size of the scan descriptor (and the amount of code
executed in the table_begin/end/rescan() functions) was a benefit,
creating a new BitmapTableScanDesc and associated table AM functions to
begin/end/rescan was actually motivated by work to remove all
heap-specific code from the generic bitmap table scan code path. Pushing
this code down into the heap AM layer would have required adding quite a
few bitmap-specific parameters to heap_begin/end/rescan()
---
 src/backend/access/heap/heapam.c          | 110 ++++++++++++++++++----
 src/backend/access/heap/heapam_handler.c  |  12 ++-
 src/backend/executor/nodeBitmapHeapscan.c |  28 +++---
 src/include/access/heapam.h               |  39 ++++++--
 src/include/access/relscan.h              |  20 +++-
 src/include/access/tableam.h              |  81 ++++++++++------
 src/include/nodes/execnodes.h             |   2 +-
 src/tools/pgindent/typedefs.list          |   2 +
 8 files changed, 220 insertions(+), 74 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 82bb9cb33b6..0d8239d2f15 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1061,8 +1061,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1178,19 +1176,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
-	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
-	 */
-	scan->rs_empty_tuples_pending = 0;
-
 	/*
 	 * The read stream is reset on rescan. This must be done before
 	 * initscan(), as some state referred to by read_stream_reset() is reset
@@ -1218,9 +1203,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
@@ -1247,6 +1229,98 @@ heap_endscan(TableScanDesc sscan)
 	pfree(scan);
 }
 
+BitmapTableScanDesc *
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+{
+	BitmapHeapScanDesc *scan;
+
+	/*
+	 * increment relation ref count while scanning relation
+	 *
+	 * This is just to make really sure the relcache entry won't go away while
+	 * the scan has a pointer to it.  Caller should be holding the rel open
+	 * anyway, so this is redundant in all normal scenarios...
+	 */
+	RelationIncrementReferenceCount(relation);
+	scan = (BitmapHeapScanDesc *) palloc(sizeof(BitmapHeapScanDesc));
+
+	scan->rs_base.rs_rd = relation;
+	scan->rs_base.rs_snapshot = snapshot;
+	scan->rs_base.rs_flags = flags;
+
+	Assert(snapshot && IsMVCCSnapshot(snapshot));
+
+	/* we only need to set this up once */
+	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
+
+	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+
+	scan->rs_ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+	scan->rs_cbuf = InvalidBuffer;
+	scan->rs_cblock = InvalidBlockNumber;
+
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
+
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
+
+	return (BitmapTableScanDesc *) scan;
+}
+
+void
+heap_rescan_bm(BitmapTableScanDesc *sscan)
+{
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+
+	if (BufferIsValid(scan->rs_cbuf))
+	{
+		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
+
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
+	scan->rs_cblock = InvalidBlockNumber;
+
+	/*
+	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
+	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
+	 * on rescan.
+	 */
+	scan->rs_empty_tuples_pending = 0;
+
+	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+
+	scan->rs_ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+}
+
+void
+heap_endscan_bm(BitmapTableScanDesc *sscan)
+{
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+
+	if (BufferIsValid(scan->rs_cbuf))
+		ReleaseBuffer(scan->rs_cbuf);
+
+	if (BufferIsValid(scan->rs_vmbuffer))
+		ReleaseBuffer(scan->rs_vmbuffer);
+
+	/*
+	 * decrement relation reference count and free scan descriptor storage
+	 */
+	RelationDecrementReferenceCount(scan->rs_base.rs_rd);
+
+	pfree(scan);
+}
+
+
 HeapTuple
 heap_getnext(TableScanDesc sscan, ScanDirection direction)
 {
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 94aa814bfa5..2223a6c8b6c 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,11 +2119,11 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2284,10 +2284,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
@@ -2630,6 +2630,10 @@ static const TableAmRoutine heapam_methods = {
 	.scan_rescan = heap_rescan,
 	.scan_getnextslot = heap_getnextslot,
 
+	.scan_begin_bm = heap_beginscan_bm,
+	.scan_rescan_bm = heap_rescan_bm,
+	.scan_end_bm = heap_endscan_bm,
+
 	.scan_set_tidrange = heap_set_tidrange,
 	.scan_getnextslot_tidrange = heap_getnextslot_tidrange,
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d9c6f252138..1f615006fbd 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -54,7 +54,7 @@ static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *ps
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
+								  BitmapTableScanDesc *scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -68,7 +68,7 @@ static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
-	TableScanDesc scan;
+	BitmapTableScanDesc *scan;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -158,15 +158,18 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
 									  need_tuples);
-
 			node->scandesc = scan;
 			node->scan_in_progress = true;
 		}
+		else
+		{
+			Assert(scan);
+			/* rescan to release any page pin */
+			tbm_end_iterate(&scan->tbmiterator);
+			table_rescan_bm(scan);
+		}
 
-		Assert(scan);
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
@@ -418,7 +421,7 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
 static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -556,10 +559,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* rescan to release any page pin */
-	if (node->scandesc)
-		table_rescan(node->scandesc, NULL);
-
 	/* release bitmaps and buffers if any */
 	/* XXX seems it should not be right after the comment, also shouldn't
 	 * we still reset the prefetch_iterator field to NULL? */
@@ -595,7 +594,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 void
 ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 {
-	TableScanDesc scanDesc;
+	BitmapTableScanDesc *scanDesc;
 
 	/*
 	 * extract information from the node
@@ -612,7 +611,10 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * close heap scan
 	 */
 	if (scanDesc)
-		table_endscan(scanDesc);
+	{
+		tbm_end_iterate(&scanDesc->tbmiterator);
+		table_endscan_bm(scanDesc);
+	}
 
 	/*
 	 * release bitmaps and buffers if any
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 9e9aec88a62..3cac199dd36 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -91,22 +91,39 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDesc
+{
+	BitmapTableScanDesc rs_base;
+
+	BlockNumber rs_nblocks;		/* total number of blocks in rel */
+
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+
+	Buffer		rs_cbuf;		/* current buffer in scan, if any */
+	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
+	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
+
+	BlockNumber rs_cblock;		/* current block # in scan, if any */
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+} BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
@@ -296,6 +313,12 @@ extern void heap_prepare_pagescan(TableScanDesc sscan);
 extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 						bool allow_strat, bool allow_sync, bool allow_pagemode);
 extern void heap_endscan(TableScanDesc sscan);
+
+extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
+											  Snapshot snapshot, uint32 flags);
+extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
+void		heap_endscan_bm(BitmapTableScanDesc *sscan);
+
 extern HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction);
 extern bool heap_getnextslot(TableScanDesc sscan,
 							 ScanDirection direction, struct TupleTableSlot *slot);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b4511677b1d..036ef29e7d5 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -37,9 +37,6 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
-	/* Iterators for Bitmap Table Scans */
-	TBMIterator tbmiterator;
-
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
@@ -55,6 +52,23 @@ typedef struct TableScanDescData
 } TableScanDescData;
 typedef struct TableScanDescData *TableScanDesc;
 
+typedef struct BitmapTableScanDesc
+{
+	Relation	rs_rd;			/* heap relation descriptor */
+	struct SnapshotData *rs_snapshot;	/* snapshot to see */
+
+	/*
+	 * Members common to Parallel and Serial BitmapTableScans
+	 */
+	TBMIterator tbmiterator;
+
+	/*
+	 * Information about type and behaviour of the scan, a bitmask of members
+	 * of the ScanOptions enum (see tableam.h).
+	 */
+	uint32		rs_flags;
+} BitmapTableScanDesc;
+
 /*
  * Shared state for parallel table scan.
  *
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 422b90b17f0..57bc06f77e0 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -345,6 +345,24 @@ typedef struct TableAmRoutine
 								bool set_params, bool allow_strat,
 								bool allow_sync, bool allow_pagemode);
 
+	/*
+	 * Functions to begin, restart, and end a scan of the underlying table of
+	 * a bitmap table scan.
+	 *
+	 * `rel`, `flags`, and `snapshot` serve the same purposes as in the
+	 * standard relation scan_[begin|rescan|end] functions documented above.
+	 */
+	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
+										   Snapshot snapshot,
+										   uint32 flags);
+
+	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
+
+	/*
+	 * Release resources and deallocate scan.
+	 */
+	void		(*scan_end_bm) (BitmapTableScanDesc *scan);
+
 	/*
 	 * Return next tuple from `scan`, store in slot.
 	 */
@@ -815,7 +833,7 @@ typedef struct TableAmRoutine
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
 										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
@@ -826,7 +844,7 @@ typedef struct TableAmRoutine
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (BitmapTableScanDesc *scan,
 										   TupleTableSlot *slot);
 
 	/*
@@ -851,8 +869,8 @@ typedef struct TableAmRoutine
 	 * is obviously OK.
 	 *
 	 * Currently it is required to implement this interface, as there's no
-	 * alternative way (contrary e.g. to bitmap scans) to implement sample
-	 * scans. If infeasible to implement, the AM may raise an error.
+	 * alternative way to implement sample scans. If infeasible to implement,
+	 * the AM may raise an error.
 	 */
 	bool		(*scan_sample_next_block) (TableScanDesc scan,
 										   struct SampleScanState *scanstate);
@@ -945,29 +963,46 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 }
 
 /*
- * table_beginscan_bm is an alternative entry point for setting up a
- * TableScanDesc for a bitmap heap scan.  Although that scan technology is
- * really quite unlike a standard seqscan, there is just enough commonality to
- * make it worth using the same data structure.
+ * table_beginscan_bm is an entry point for setting up a BitmapTableScanDesc
+ * for a bitmap table scan.
  */
-static inline TableScanDesc
+static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, bool need_tuple)
+				   bool need_tuple)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 }
 
+/*
+ * Restart a bitmap table scan.
+ */
+static inline void
+table_rescan_bm(BitmapTableScanDesc *scan)
+{
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+}
+
+/*
+ * End a bitmap table scan.
+ */
+static inline void
+table_endscan_bm(BitmapTableScanDesc *scan)
+{
+	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+}
+
+
 /*
  * table_beginscan_sampling is an alternative entry point for setting up a
- * TableScanDesc for a TABLESAMPLE scan.  As with bitmap scans, it's worth
- * using the same data structure although the behavior is rather different.
- * In addition to the options offered by table_beginscan_strat, this call
- * also allows control of whether page-mode visibility checking is used.
+ * TableScanDesc for a TABLESAMPLE scan.  It's worth using the same data
+ * structure although the behavior is rather different. In addition to the
+ * options offered by table_beginscan_strat, this call also allows control of
+ * whether page-mode visibility checking is used.
  */
 static inline TableScanDesc
 table_beginscan_sampling(Relation rel, Snapshot snapshot,
@@ -989,7 +1024,7 @@ table_beginscan_sampling(Relation rel, Snapshot snapshot,
 
 /*
  * table_beginscan_tid is an alternative entry point for setting up a
- * TableScanDesc for a Tid scan. As with bitmap scans, it's worth using
+ * TableScanDesc for a Tid scan. As with sample scans, it's worth using
  * the same data structure although the behavior is rather different.
  */
 static inline TableScanDesc
@@ -1002,7 +1037,7 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 
 /*
  * table_beginscan_analyze is an alternative entry point for setting up a
- * TableScanDesc for an ANALYZE scan.  As with bitmap scans, it's worth using
+ * TableScanDesc for an ANALYZE scan.  As with sample scans, it's worth using
  * the same data structure although the behavior is rather different.
  */
 static inline TableScanDesc
@@ -1019,10 +1054,6 @@ table_beginscan_analyze(Relation rel)
 static inline void
 table_endscan(TableScanDesc scan)
 {
-	/* XXX worth a comment? */
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-		tbm_end_iterate(&scan->tbmiterator);
-
 	scan->rs_rd->rd_tableam->scan_end(scan);
 }
 
@@ -1033,10 +1064,6 @@ static inline void
 table_rescan(TableScanDesc scan,
 			 struct ScanKeyData *key)
 {
-	/* XXX worth a comment? */
-	if (scan->rs_flags & SO_TYPE_BITMAPSCAN)
-		tbm_end_iterate(&scan->tbmiterator);
-
 	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
 }
 
@@ -1976,7 +2003,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
@@ -2003,7 +2030,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  * returned false.
  */
 static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
+table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 							 TupleTableSlot *slot)
 {
 	/*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 4c0c5c14f64..d37fa6ac946 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1814,7 +1814,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *scandesc;
+	struct BitmapTableScanDesc *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 757a9a3a41e..90f7fd882dc 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -261,12 +261,14 @@ BitmapAndPath
 BitmapAndState
 BitmapHeapPath
 BitmapHeapScan
+BitmapHeapScanDesc
 BitmapHeapScanState
 BitmapIndexScan
 BitmapIndexScanState
 BitmapOr
 BitmapOrPath
 BitmapOrState
+BitmapTableScanDesc
 Bitmapset
 Block
 BlockId
-- 
2.45.2

v22b-0017-review.patchtext/x-patch; charset=UTF-8; name=v22b-0017-review.patchDownload
From b974ff18088d296f7efa72cfc58abdb507356a39 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 23:06:55 +0200
Subject: [PATCH v22b 17/29] review

---
 src/include/access/relscan.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 036ef29e7d5..9c711ce0eb0 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -52,6 +52,13 @@ typedef struct TableScanDescData
 } TableScanDescData;
 typedef struct TableScanDescData *TableScanDesc;
 
+/*
+ * XXX I don't understand why we should have this special node if we
+ * don't have special nodes for other scan types.
+ *
+ * XXX Also, maybe this should do the naming convention with Data at
+ * the end (mostly for consistency).
+ */
 typedef struct BitmapTableScanDesc
 {
 	Relation	rs_rd;			/* heap relation descriptor */
-- 
2.45.2

v22b-0018-Update-variable-names-in-bitmap-scan-descriptor.patchtext/x-patch; charset=UTF-8; name=v22b-0018-Update-variable-names-in-bitmap-scan-descriptor.patchDownload
From 685d2107491019768324cb82230ee57e95587ee4 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 09:59:23 -0400
Subject: [PATCH v22b 18/29] Update variable names in bitmap scan descriptors

The previous commit which added BitmapTableScanDesc and
BitmapHeapScanDesc used the existing member names from TableScanDescData
and HeapScanDescData for diff clarity. This commit renames the members
-- in many cases by removing the rs_ prefix which is not relevant or
needed here.
---
 src/backend/access/heap/heapam.c          | 64 ++++++++++-----------
 src/backend/access/heap/heapam_handler.c  | 70 +++++++++++------------
 src/backend/executor/nodeBitmapHeapscan.c | 14 ++---
 src/include/access/heapam.h               | 22 +++----
 src/include/access/relscan.h              |  8 +--
 src/include/access/tableam.h              | 14 ++---
 6 files changed, 96 insertions(+), 96 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 0d8239d2f15..88da737d149 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1244,27 +1244,27 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	RelationIncrementReferenceCount(relation);
 	scan = (BitmapHeapScanDesc *) palloc(sizeof(BitmapHeapScanDesc));
 
-	scan->rs_base.rs_rd = relation;
-	scan->rs_base.rs_snapshot = snapshot;
-	scan->rs_base.rs_flags = flags;
+	scan->base.rel = relation;
+	scan->base.snapshot = snapshot;
+	scan->base.flags = flags;
 
 	Assert(snapshot && IsMVCCSnapshot(snapshot));
 
 	/* we only need to set this up once */
-	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
+	scan->ctup.t_tableOid = RelationGetRelid(relation);
 
-	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+	scan->nblocks = RelationGetNumberOfBlocks(scan->base.rel);
 
-	scan->rs_ctup.t_data = NULL;
-	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
-	scan->rs_cbuf = InvalidBuffer;
-	scan->rs_cblock = InvalidBlockNumber;
+	scan->ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->ctup.t_self);
+	scan->cbuf = InvalidBuffer;
+	scan->cblock = InvalidBlockNumber;
 
-	scan->rs_cindex = 0;
-	scan->rs_ntuples = 0;
+	scan->vis_idx = 0;
+	scan->vis_ntuples = 0;
 
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
+	scan->vmbuffer = InvalidBuffer;
+	scan->empty_tuples_pending = 0;
 
 	return (BitmapTableScanDesc *) scan;
 }
@@ -1274,31 +1274,31 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
-	if (BufferIsValid(scan->rs_cbuf))
+	if (BufferIsValid(scan->cbuf))
 	{
-		ReleaseBuffer(scan->rs_cbuf);
-		scan->rs_cbuf = InvalidBuffer;
+		ReleaseBuffer(scan->cbuf);
+		scan->cbuf = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->rs_vmbuffer))
+	if (BufferIsValid(scan->vmbuffer))
 	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
+		ReleaseBuffer(scan->vmbuffer);
+		scan->vmbuffer = InvalidBuffer;
 	}
 
-	scan->rs_cblock = InvalidBlockNumber;
+	scan->cblock = InvalidBlockNumber;
 
 	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
+	 * Reset empty_tuples_pending, a field only used by bitmap heap scan, to
+	 * avoid incorrectly emitting NULL-filled tuples from a previous scan on
+	 * rescan.
 	 */
-	scan->rs_empty_tuples_pending = 0;
+	scan->empty_tuples_pending = 0;
 
-	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+	scan->nblocks = RelationGetNumberOfBlocks(scan->base.rel);
 
-	scan->rs_ctup.t_data = NULL;
-	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+	scan->ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->ctup.t_self);
 }
 
 void
@@ -1306,16 +1306,16 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
-	if (BufferIsValid(scan->rs_cbuf))
-		ReleaseBuffer(scan->rs_cbuf);
+	if (BufferIsValid(scan->cbuf))
+		ReleaseBuffer(scan->cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
 
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
-	RelationDecrementReferenceCount(scan->rs_base.rs_rd);
+	RelationDecrementReferenceCount(scan->base.rel);
 
 	pfree(scan);
 }
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2223a6c8b6c..55c2e57b5f5 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2130,8 +2130,8 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	int			ntup;
 	TBMIterateResult *tbmres;
 
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
+	hscan->vis_idx = 0;
+	hscan->vis_ntuples = 0;
 
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
@@ -2140,7 +2140,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->tbmiterator);
+		tbmres = tbm_iterate(&scan->iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2153,7 +2153,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->nblocks);
 
 	/* Got a valid block */
 	*blockno = tbmres->blockno;
@@ -2164,15 +2164,15 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+	if (!(scan->flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(scan->rel, tbmres->blockno, &hscan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(hscan->empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2182,19 +2182,19 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
+	hscan->cbuf = ReleaseAndReadBuffer(hscan->cbuf,
+									   scan->rel,
+									   block);
+	hscan->cblock = block;
+	buffer = hscan->cbuf;
+	snapshot = scan->snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
+	heap_page_prune_opt(scan->rel, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2222,9 +2222,9 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, scan->rel, buffer, snapshot,
 									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+				hscan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
 	}
 	else
@@ -2248,16 +2248,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
+			loctup.t_tableOid = scan->rel->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+				hscan->vis_tuples[ntup++] = offnum;
+				PredicateLockTID(scan->rel, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+			HeapCheckForSerializableConflictOut(valid, scan->rel, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2265,7 +2265,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
+	hscan->vis_ntuples = ntup;
 
 	/* XXX why inverted condition, compared to the original one in BitmapHeapNext? */
 	if (tbmres->ntuples < 0)
@@ -2292,43 +2292,43 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (hscan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		hscan->empty_tuples_pending--;
 		return true;
 	}
 
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
+	if (hscan->vis_idx < 0 || hscan->vis_idx >= hscan->vis_ntuples)
 		return false;
 
-	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
-	page = BufferGetPage(hscan->rs_cbuf);
+	targoffset = hscan->vis_tuples[hscan->vis_idx];
+	page = BufferGetPage(hscan->cbuf);
 	lp = PageGetItemId(page, targoffset);
 	Assert(ItemIdIsNormal(lp));
 
-	hscan->rs_ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-	hscan->rs_ctup.t_len = ItemIdGetLength(lp);
-	hscan->rs_ctup.t_tableOid = scan->rs_rd->rd_id;
-	ItemPointerSet(&hscan->rs_ctup.t_self, hscan->rs_cblock, targoffset);
+	hscan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+	hscan->ctup.t_len = ItemIdGetLength(lp);
+	hscan->ctup.t_tableOid = scan->rel->rd_id;
+	ItemPointerSet(&hscan->ctup.t_self, hscan->cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rs_rd);
+	pgstat_count_heap_fetch(scan->rel);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
 	 * acquires a pin on the buffer.
 	 */
-	ExecStoreBufferHeapTuple(&hscan->rs_ctup,
+	ExecStoreBufferHeapTuple(&hscan->ctup,
 							 slot,
-							 hscan->rs_cbuf);
+							 hscan->cbuf);
 
-	hscan->rs_cindex++;
+	hscan->vis_idx++;
 
 	return true;
 }
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 1f615006fbd..0f00e0d42d5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -166,11 +166,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			Assert(scan);
 			/* rescan to release any page pin */
-			tbm_end_iterate(&scan->tbmiterator);
+			tbm_end_iterate(&scan->iterator);
 			table_rescan_bm(scan);
 		}
 
-		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
+		tbm_begin_iterate(&scan->iterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
 						  InvalidDsaPointer);
@@ -452,14 +452,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -504,14 +504,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				node->pfblockno = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -612,7 +612,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	if (scanDesc)
 	{
-		tbm_end_iterate(&scanDesc->tbmiterator);
+		tbm_end_iterate(&scanDesc->iterator);
 		table_endscan_bm(scanDesc);
 	}
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3cac199dd36..1d5583cac22 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -100,19 +100,19 @@ typedef struct HeapScanDescData *HeapScanDesc;
 
 typedef struct BitmapHeapScanDesc
 {
-	BitmapTableScanDesc rs_base;
+	BitmapTableScanDesc base;
 
-	BlockNumber rs_nblocks;		/* total number of blocks in rel */
+	BlockNumber nblocks;		/* total number of blocks in rel */
 
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+	int			vis_idx;		/* current tuple's index in vistuples */
+	int			vis_ntuples;	/* number of visible tuples on page */
+	OffsetNumber vis_tuples[MaxHeapTuplesPerPage];	/* their offsets */
 
-	Buffer		rs_cbuf;		/* current buffer in scan, if any */
-	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
-	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
+	Buffer		cbuf;			/* current buffer in scan, if any */
+	/* NB: if cbuf is not InvalidBuffer, we hold a pin on that buffer */
+	HeapTupleData ctup;			/* current tuple in scan, if any */
 
-	BlockNumber rs_cblock;		/* current block # in scan, if any */
+	BlockNumber cblock;			/* current block # in scan, if any */
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -121,8 +121,8 @@ typedef struct BitmapHeapScanDesc
 	 * block reported by the bitmap to determine how many NULL-filled tuples
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
-	Buffer		rs_vmbuffer;
-	int			rs_empty_tuples_pending;
+	Buffer		vmbuffer;
+	int			empty_tuples_pending;
 } BitmapHeapScanDesc;
 
 /*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 9c711ce0eb0..0fe0b8c8b4f 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -61,19 +61,19 @@ typedef struct TableScanDescData *TableScanDesc;
  */
 typedef struct BitmapTableScanDesc
 {
-	Relation	rs_rd;			/* heap relation descriptor */
-	struct SnapshotData *rs_snapshot;	/* snapshot to see */
+	Relation	rel;			/* heap relation descriptor */
+	struct SnapshotData *snapshot;	/* snapshot to see */
 
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
-	TBMIterator tbmiterator;
+	TBMIterator iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
 	 */
-	uint32		rs_flags;
+	uint32		flags;
 } BitmapTableScanDesc;
 
 /*
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 57bc06f77e0..f7f099b6449 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -984,7 +984,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 static inline void
 table_rescan_bm(BitmapTableScanDesc *scan)
 {
-	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+	scan->rel->rd_tableam->scan_rescan_bm(scan);
 }
 
 /*
@@ -993,7 +993,7 @@ table_rescan_bm(BitmapTableScanDesc *scan)
 static inline void
 table_endscan_bm(BitmapTableScanDesc *scan)
 {
-	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+	scan->rel->rd_tableam->scan_end_bm(scan);
 }
 
 
@@ -2016,9 +2016,9 @@ table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
-														   lossy_pages, exact_pages);
+	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
+														 blockno, recheck,
+														 lossy_pages, exact_pages);
 }
 
 /*
@@ -2041,8 +2041,8 @@ table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+	return scan->rel->rd_tableam->scan_bitmap_next_tuple(scan,
+														 slot);
 }
 
 /*
-- 
2.45.2

v22b-0019-review.patchtext/x-patch; charset=UTF-8; name=v22b-0019-review.patchDownload
From 5014e06aaaea574eb33835667bac7ac91cb2de36 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 23:13:12 +0200
Subject: [PATCH v22b 19/29] review

---
 src/include/access/heapam.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 1d5583cac22..ce69f5a023e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -104,7 +104,7 @@ typedef struct BitmapHeapScanDesc
 
 	BlockNumber nblocks;		/* total number of blocks in rel */
 
-	int			vis_idx;		/* current tuple's index in vistuples */
+	int			vis_idx;		/* current tuple's index in vis_tuples */
 	int			vis_ntuples;	/* number of visible tuples on page */
 	OffsetNumber vis_tuples[MaxHeapTuplesPerPage];	/* their offsets */
 
-- 
2.45.2

v22b-0020-BitmapHeapScan-lift-and-shift-prefetch-function.patchtext/x-patch; charset=UTF-8; name=v22b-0020-BitmapHeapScan-lift-and-shift-prefetch-function.patchDownload
From 58cde3cbd841c3395eaf1af85cc3320586379941 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 12:14:28 -0400
Subject: [PATCH v22b 20/29] BitmapHeapScan: lift and shift prefetch functions

This is a temporary commit. For ease of review, move the BitmapHeapScan
prefetch functions into heapam_handler.c without modifying them. The
next commit will push the prefetching code into heap specific code.
Separating the commit which moves to the functions to heapam_handler.c
and the one which modifies them and their callers to contain bitmap
prefetch code in heap AM-specific code makes it easier to see what has
changed. Doing so requires including heap code in nodeBitmapHeapscan.c,
which is not okay for the final code that is committed.
---
 src/backend/access/heap/heapam_handler.c  | 218 +++++++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 225 +---------------------
 src/include/access/heapam.h               |  10 +
 3 files changed, 230 insertions(+), 223 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 55c2e57b5f5..9a5ebe6d138 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,6 +2112,224 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+void
+BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!prefetch_iterator->exhausted)
+		{
+			while (node->prefetch_pages < node->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!prefetch_iterator->exhausted)
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = tbm_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				node->pfblockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (node->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			node->prefetch_pages--;
+		}
+		else if (!prefetch_iterator->exhausted)
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
+	if (node->prefetch_maximum > 0)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!prefetch_iterator->exhausted)
+			{
+				tbmpre = tbm_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (node->prefetch_target >= node->prefetch_maximum / 2)
+			node->prefetch_target = node->prefetch_maximum;
+		else if (node->prefetch_target > 0)
+			node->prefetch_target *= 2;
+		else
+			node->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < node->prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 0f00e0d42d5..a06964613b6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,6 +37,8 @@
 
 #include <math.h>
 
+/* XXX: temporary include only for review purposes */
+#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -51,10 +53,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  BitmapTableScanDesc *scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -299,225 +297,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->pfblockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index ce69f5a023e..a393151e061 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -20,6 +20,8 @@
 #include "access/skey.h"
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
+/* XXX: temporary include so lift and shift works */
+#include "nodes/execnodes.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -386,6 +388,14 @@ extern void simple_heap_update(Relation relation, ItemPointer otid,
 extern TransactionId heap_index_delete_tuples(Relation rel,
 											  TM_IndexDeleteOp *delstate);
 
+/* in heapam_handler.c */
+extern void BitmapPrefetch(BitmapHeapScanState *node,
+						   BitmapTableScanDesc *scan);
+
+extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
+
+extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+
 /* in heap/pruneheap.c */
 struct GlobalVisState;
 extern void heap_page_prune_opt(Relation relation, Buffer buffer);
-- 
2.45.2

v22b-0021-BitmapHeapScan-Push-prefetch-code-into-heap-AM.patchtext/x-patch; charset=UTF-8; name=v22b-0021-BitmapHeapScan-Push-prefetch-code-into-heap-AM.patchDownload
From f5e0b96325fa228b59d42d9572efb9fefb03f2c4 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 10:30:28 -0400
Subject: [PATCH v22b 21/29] BitmapHeapScan: Push prefetch code into heap AM

In order to completely remove the layering violation in bitmap table
scan code, we must avoid using the VM for skipping prefetches as well.

To accomplish this, push prefetch code down into the heap implementation
fo the bitmap table scan AM functions. This fixes another layering
violation related to prefetching mentioned in tableam.h.

This commit moves prefetch-related members from the BitmapHeapScanState
to the BitmapHeapScanDesc and localizes the prefetch functions to heap
AM code.

heapam_scan_bitmap_next_block() no longer needs to take blockno as a
parameter because it was only being used in generic bitmap table scan
code to check if the prefetch block was falling behind the current
block.
---
 src/backend/access/heap/heapam.c          |  23 ++-
 src/backend/access/heap/heapam_handler.c  | 217 +++++++++++++---------
 src/backend/executor/nodeBitmapHeapscan.c | 135 ++++----------
 src/include/access/heapam.h               |  28 +--
 src/include/access/relscan.h              |   4 +
 src/include/access/tableam.h              |  42 ++---
 src/include/nodes/execnodes.h             |  15 --
 7 files changed, 235 insertions(+), 229 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 88da737d149..9847ce2c3aa 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1230,7 +1230,8 @@ heap_endscan(TableScanDesc sscan)
 }
 
 BitmapTableScanDesc *
-heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
+				  int prefetch_maximum)
 {
 	BitmapHeapScanDesc *scan;
 
@@ -1264,8 +1265,15 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	scan->vis_ntuples = 0;
 
 	scan->vmbuffer = InvalidBuffer;
+	scan->pvmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
+	scan->prefetch_maximum = prefetch_maximum;
+
+	/* Only used for serial BHS */
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	return (BitmapTableScanDesc *) scan;
 }
 
@@ -1288,6 +1296,12 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->cblock = InvalidBlockNumber;
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * Reset empty_tuples_pending, a field only used by bitmap heap scan, to
 	 * avoid incorrectly emitting NULL-filled tuples from a previous scan on
@@ -1299,6 +1313,10 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->ctup.t_data = NULL;
 	ItemPointerSetInvalid(&scan->ctup.t_self);
+
+	/* Only used for serial BHS */
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 }
 
 void
@@ -1312,6 +1330,9 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 	if (BufferIsValid(scan->vmbuffer))
 		ReleaseBuffer(scan->vmbuffer);
 
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 9a5ebe6d138..166a84b909e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,6 +54,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
+static inline void BitmapPrefetch(BitmapHeapScanDesc *scan);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan);
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 static const TableAmRoutine heapam_methods;
@@ -2115,19 +2118,19 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 /*
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
-void
-BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
+static inline void
+BitmapPrefetch(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		if (!prefetch_iterator->exhausted)
 		{
-			while (node->prefetch_pages < node->prefetch_target)
+			while (scan->prefetch_pages < scan->prefetch_target)
 			{
 				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
@@ -2138,8 +2141,8 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				scan->prefetch_pages++;
+				scan->pfblock = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2147,14 +2150,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->base.rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -2163,7 +2166,7 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		if (!prefetch_iterator->exhausted)
 		{
@@ -2196,17 +2199,17 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				scan->pfblock = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->base.rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -2220,27 +2223,27 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
  *	iterator in prefetch_pages. For each block the main iterator returns, we
  *	decrement prefetch_pages.
  */
-void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
-		if (node->prefetch_pages > 0)
+		if (scan->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
+			scan->prefetch_pages--;
 		}
 		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
 			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
@@ -2254,9 +2257,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
 	 * exacerbates the effects of this bug.
 	 */
-	if (node->prefetch_maximum > 0)
+	if (scan->prefetch_maximum > 0)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -2280,7 +2283,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			if (!prefetch_iterator->exhausted)
 			{
 				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
 	}
@@ -2295,33 +2298,33 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
  * page/tuple, then to one after the second tuple is fetched, then
  * it doubles as later pages are fetched.
  */
-void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_target >= node->prefetch_maximum)
+		if (scan->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
+		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
+			scan->prefetch_target = scan->prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
 		else
-			node->prefetch_target++;
+			scan->prefetch_target++;
 		return;
 	}
 
 	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
+	if (pstate->prefetch_target < scan->prefetch_maximum)
 	{
 		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
+		if (pstate->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
+			pstate->prefetch_target = scan->prefetch_maximum;
 		else if (pstate->prefetch_target > 0)
 			pstate->prefetch_target *= 2;
 		else
@@ -2331,34 +2334,36 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 }
 
+
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
  * ------------------------------------------------------------------------
  */
 
 static bool
-heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
-							  BlockNumber *blockno, bool *recheck,
+heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
+							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
 
-	hscan->vis_idx = 0;
-	hscan->vis_ntuples = 0;
+	scan->vis_idx = 0;
+	scan->vis_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(scan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->iterator);
+		tbmres = tbm_iterate(&scan->base.iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2371,10 +2376,10 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->nblocks);
+	} while (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
+	block = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2382,37 +2387,35 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->flags & SO_NEED_TUPLES) &&
+	if (!(scan->base.flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rel, tbmres->blockno, &hscan->vmbuffer))
+		VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->empty_tuples_pending >= 0);
+		Assert(scan->empty_tuples_pending >= 0);
 
-		hscan->empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
-
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
-	hscan->cbuf = ReleaseAndReadBuffer(hscan->cbuf,
-									   scan->rel,
-									   block);
-	hscan->cblock = block;
-	buffer = hscan->cbuf;
-	snapshot = scan->snapshot;
+	scan->cbuf = ReleaseAndReadBuffer(scan->cbuf,
+									  scan->base.rel,
+									  block);
+	scan->cblock = block;
+	buffer = scan->cbuf;
+	snapshot = scan->base.snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rel, buffer);
+	heap_page_prune_opt(scan->base.rel, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2440,9 +2443,9 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rel, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, scan->base.rel, buffer, snapshot,
 									   &heapTuple, NULL, true))
-				hscan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+				scan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
 	}
 	else
@@ -2466,16 +2469,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rel->rd_id;
+			loctup.t_tableOid = scan->base.rel->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
-				hscan->vis_tuples[ntup++] = offnum;
-				PredicateLockTID(scan->rel, &loctup.t_self, snapshot,
+				scan->vis_tuples[ntup++] = offnum;
+				PredicateLockTID(scan->base.rel, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rel, &loctup,
+			HeapCheckForSerializableConflictOut(valid, scan->base.rel, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2483,7 +2486,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->vis_ntuples = ntup;
+	scan->vis_ntuples = ntup;
 
 	/* XXX why inverted condition, compared to the original one in BitmapHeapNext? */
 	if (tbmres->ntuples < 0)
@@ -2491,10 +2494,22 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	else
 		(*exact_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->base.pstate == NULL &&
+		!scan->base.prefetch_iterator.exhausted &&
+		scan->pfblock < block)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(scan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * scan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
 	 * return false returning control to this function to advance to the next
 	 * block in the bitmap.
 	 */
@@ -2502,51 +2517,83 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
+heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 							  TupleTableSlot *slot)
 {
-	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+	ParallelBitmapHeapState *pstate = sscan->pstate;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->empty_tuples_pending > 0)
+	if (scan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->empty_tuples_pending--;
+		scan->empty_tuples_pending--;
+		BitmapPrefetch(scan);
 		return true;
 	}
 
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->vis_idx < 0 || hscan->vis_idx >= hscan->vis_ntuples)
+	if (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
 		return false;
 
-	targoffset = hscan->vis_tuples[hscan->vis_idx];
-	page = BufferGetPage(hscan->cbuf);
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!pstate)
+	{
+		if (scan->prefetch_target < scan->prefetch_maximum)
+			scan->prefetch_target++;
+	}
+	else if (pstate->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target < scan->prefetch_maximum)
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(scan);
+
+	targoffset = scan->vis_tuples[scan->vis_idx];
+	page = BufferGetPage(scan->cbuf);
 	lp = PageGetItemId(page, targoffset);
 	Assert(ItemIdIsNormal(lp));
 
-	hscan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-	hscan->ctup.t_len = ItemIdGetLength(lp);
-	hscan->ctup.t_tableOid = scan->rel->rd_id;
-	ItemPointerSet(&hscan->ctup.t_self, hscan->cblock, targoffset);
+	scan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+	scan->ctup.t_len = ItemIdGetLength(lp);
+	scan->ctup.t_tableOid = sscan->rel->rd_id;
+	ItemPointerSet(&scan->ctup.t_self, scan->cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rel);
+	pgstat_count_heap_fetch(sscan->rel);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
 	 * acquires a pin on the buffer.
 	 */
-	ExecStoreBufferHeapTuple(&hscan->ctup,
+	ExecStoreBufferHeapTuple(&scan->ctup,
 							 slot,
-							 hscan->cbuf);
+							 scan->cbuf);
 
-	hscan->vis_idx++;
+	scan->vis_idx++;
 
 	return true;
 }
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a06964613b6..ed86e4bac11 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,8 +37,6 @@
 
 #include <math.h>
 
-/* XXX: temporary include only for review purposes */
-#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -81,17 +79,21 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
+		int			prefetch_maximum = 0;
+
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+#ifdef USE_PREFETCH
+		Relation	rel = node->ss.ss_currentRelation;
+
+		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
+
 		if (!pstate)
 		{
 			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -110,6 +112,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
 
+			/*
+			 * Two iterators are used -- one for the pages being scanned and
+			 * one for the blocks being prefetched.
+			 */
+
 			/*
 			 * Prepare to iterate over the TBM. This will return the
 			 * dsa_pointer of the iterator state which will be used by
@@ -117,7 +124,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			 */
 			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (prefetch_maximum > 0)
 			{
 				pstate->prefetch_iterator =
 					tbm_prepare_shared_iterate(node->tbm);
@@ -127,14 +134,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			BitmapDoneInitializingSharedState(pstate);
 		}
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-			tbm_begin_iterate(&node->prefetch_iterator, node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -156,7 +155,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
-									  need_tuples);
+									  pstate,
+									  need_tuples,
+									  prefetch_maximum);
 			node->scandesc = scan;
 			node->scan_in_progress = true;
 		}
@@ -173,6 +174,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 						  pstate->tbmiterator :
 						  InvalidDsaPointer);
 
+		/*
+		 * We use *two* iterators, one for the pages we are actually scanning
+		 * and another that runs ahead of the first for prefetching.
+		 * scan->prefetch_pages tracks exactly how many pages ahead the
+		 * prefetch iterator is.  Also, scan->prefetch_target tracks the
+		 * desired prefetch distance, which starts small and increases up to
+		 * the prefetch_maximum. This is to avoid doing a lot of prefetching
+		 * in a scan that stops after a few tuples because of a LIMIT.
+		 */
+#ifdef USE_PREFETCH
+		if (prefetch_maximum > 0)
+			tbm_begin_iterate(&scan->prefetch_iterator, node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		node->initialized = true;
 
 		goto new_page;
@@ -188,37 +206,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -241,8 +228,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * XXX maybe add comment explaining what "false" means here?
 		 *
@@ -257,23 +242,9 @@ new_page:
 		 *
 		 * But I haven't tried implementing this.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If private, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			/* XXX shouldn't we have a function instead of checking the
-			 * field directly? */
-			!node->prefetch_iterator.exhausted &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -339,22 +310,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	/* release bitmaps and buffers if any */
-	/* XXX seems it should not be right after the comment, also shouldn't
-	 * we still reset the prefetch_iterator field to NULL? */
-	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
-	/* Only used for serial BHS */
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -392,18 +352,15 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	if (scanDesc)
 	{
 		tbm_end_iterate(&scanDesc->iterator);
+		tbm_end_iterate(&scanDesc->prefetch_iterator);
 		table_endscan_bm(scanDesc);
 	}
 
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	/* XXX misleading place, not a bitmap or a buffer */
-	tbm_end_iterate(&node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -436,17 +393,12 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->scan_in_progress = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -486,13 +438,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index a393151e061..5d73bb361e3 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -20,8 +20,6 @@
 #include "access/skey.h"
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
-/* XXX: temporary include so lift and shift works */
-#include "nodes/execnodes.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -116,6 +114,17 @@ typedef struct BitmapHeapScanDesc
 
 	BlockNumber cblock;			/* current block # in scan, if any */
 
+	/* used to validate pf stays ahead of current block */
+	BlockNumber pfblock;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -123,7 +132,11 @@ typedef struct BitmapHeapScanDesc
 	 * block reported by the bitmap to determine how many NULL-filled tuples
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
+
+	/* page of VM containing info for current block */
 	Buffer		vmbuffer;
+	/* page of VM containing info for prefetch block */
+	Buffer		pvmbuffer;
 	int			empty_tuples_pending;
 } BitmapHeapScanDesc;
 
@@ -317,7 +330,8 @@ extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 extern void heap_endscan(TableScanDesc sscan);
 
 extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
-											  Snapshot snapshot, uint32 flags);
+											  Snapshot snapshot, uint32 flags,
+											  int prefetch_maximum);
 extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
 void		heap_endscan_bm(BitmapTableScanDesc *sscan);
 
@@ -388,14 +402,6 @@ extern void simple_heap_update(Relation relation, ItemPointer otid,
 extern TransactionId heap_index_delete_tuples(Relation rel,
 											  TM_IndexDeleteOp *delstate);
 
-/* in heapam_handler.c */
-extern void BitmapPrefetch(BitmapHeapScanState *node,
-						   BitmapTableScanDesc *scan);
-
-extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-
-extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-
 /* in heap/pruneheap.c */
 struct GlobalVisState;
 extern void heap_page_prune_opt(Relation relation, Buffer buffer);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 0fe0b8c8b4f..a1207c22b3c 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -64,10 +64,14 @@ typedef struct BitmapTableScanDesc
 	Relation	rel;			/* heap relation descriptor */
 	struct SnapshotData *snapshot;	/* snapshot to see */
 
+	struct ParallelBitmapHeapState *pstate;
+
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
 	TBMIterator iterator;
+	/* iterator for prefetching ahead of current page */
+	TBMIterator prefetch_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index f7f099b6449..a00b9bd296a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -354,7 +354,7 @@ typedef struct TableAmRoutine
 	 */
 	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
 										   Snapshot snapshot,
-										   uint32 flags);
+										   uint32 flags, int prefetch_maximum);
 
 	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
 
@@ -808,33 +808,26 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
+	 * Prepare to fetch / check / return tuples from as part of a bitmap table
+	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
+	 * bitmap is exhausted and true otherwise.
 	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
+	 * This will typically read and pin a block, and do the necessary work to
+	 * allow scan_bitmap_next_tuple() to return tuples (e.g. depending on the
+	 * table AM, it might make sense to perform tuple visibility checks at
+	 * this time).
 	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, `exact_pages` is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching future blocks indicated in the bitmap is left to the table
+	 * AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
-										   BlockNumber *blockno, bool *recheck,
+										   bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -968,14 +961,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   bool need_tuple)
+				   struct ParallelBitmapHeapState *pstate,
+				   bool need_tuple,
+				   int prefetch_maximum)
 {
+	BitmapTableScanDesc *result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
+	result = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, prefetch_maximum);
+	result->pstate = pstate;
+	return result;
 }
 
 /*
@@ -2004,7 +2002,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 static inline bool
 table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
-							 BlockNumber *blockno, bool *recheck,
+							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -2017,7 +2015,7 @@ table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
-														 blockno, recheck,
+														 recheck,
 														 lossy_pages, exact_pages);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d37fa6ac946..28fc6e7221f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1796,19 +1796,12 @@ typedef struct ParallelBitmapHeapState
  *		scandesc		   current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		scan_in_progress   is this a rescan
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1817,20 +1810,12 @@ typedef struct BitmapHeapScanState
 	struct BitmapTableScanDesc *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	bool		scan_in_progress;
-	/* XXX probably should be kept in the order per comment */
-	TBMIterator prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.45.2

v22b-0022-review.patchtext/x-patch; charset=UTF-8; name=v22b-0022-review.patchDownload
From 01d7ddb54fc8a523bc3c0787fb1a1d055b579a38 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 23:37:24 +0200
Subject: [PATCH v22b 22/29] review

---
 src/backend/executor/nodeBitmapHeapscan.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index ed86e4bac11..79229f9f538 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -87,6 +87,10 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Maximum number of prefetches for the tablespace if configured,
 		 * otherwise the current value of the effective_io_concurrency GUC.
+		 *
+		 * XXX Why do we protect this with the ifdef? The prefetches are
+		 * still protected by the same ifdef anyway, and we didn't do that
+		 * before this patch.
 		 */
 #ifdef USE_PREFETCH
 		Relation	rel = node->ss.ss_currentRelation;
@@ -115,6 +119,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Two iterators are used -- one for the pages being scanned and
 			 * one for the blocks being prefetched.
+			 *
+			 * XXX Is this comment needed? The one a bit further down says
+			 * about the same thing, no?
 			 */
 
 			/*
-- 
2.45.2

v22b-0023-BitmapHeapScan-move-per-scan-setup-into-a-helpe.patchtext/x-patch; charset=UTF-8; name=v22b-0023-BitmapHeapScan-move-per-scan-setup-into-a-helpe.patchDownload
From 868457ce9d1b227e2bc16b47ed268b63e2fbbf71 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 23:39:17 +0200
Subject: [PATCH v22b 23/29] BitmapHeapScan: move per scan setup into a helper

Add BitmapTableScanSetup() which contains all of the code that must be
done on every scan of the table in a bitmap table scan.
This includes scanning the index, building the bitmap, and setting up
the scan descriptors.

Much of BitmapHeapNext() code was this setup, so it made sense to put it
in a helper function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 233 +++++++++++-----------
 1 file changed, 115 insertions(+), 118 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 79229f9f538..317cbda857a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,153 +53,150 @@ static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
-
-/* ----------------------------------------------------------------
- *		BitmapHeapNext
- *
- *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
- * ----------------------------------------------------------------
+/*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
  */
-static TupleTableSlot *
-BitmapHeapNext(BitmapHeapScanState *node)
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	BitmapTableScanDesc *scan;
-	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
+	int			prefetch_maximum = 0;
 
 	/*
-	 * extract necessary information from index scan node
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
 	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->scandesc;
+#ifdef USE_PREFETCH
+	Relation	rel = node->ss.ss_currentRelation;
+
+	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+#endif
 
 	/*
-	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
+	 * Scan the index, build the bitmap, and set up shared state for parallel.
 	 */
-	if (!node->initialized)
+	if (!pstate)
 	{
-		int			prefetch_maximum = 0;
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+	}
+	else if (BitmapShouldInitializeSharedState(pstate))
+	{
 		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
-		 *
-		 * XXX Why do we protect this with the ifdef? The prefetches are
-		 * still protected by the same ifdef anyway, and we didn't do that
-		 * before this patch.
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
 		 */
-#ifdef USE_PREFETCH
-		Relation	rel = node->ss.ss_currentRelation;
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
 
-		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-#endif
+		/*
+		 * Two iterators are used -- one for the pages being scanned and one
+		 * for the blocks being prefetched.
+		 */
 
-		if (!pstate)
+		/*
+		 * Prepare to iterate over the TBM. This will return the dsa_pointer
+		 * of the iterator state which will be used by multiple processes to
+		 * iterate jointly.
+		 */
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+#ifdef USE_PREFETCH
+		if (prefetch_maximum > 0)
 		{
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
+			pstate->prefetch_iterator =
+				tbm_prepare_shared_iterate(node->tbm);
 		}
-		else if (BitmapShouldInitializeSharedState(pstate))
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-
-			/*
-			 * Two iterators are used -- one for the pages being scanned and
-			 * one for the blocks being prefetched.
-			 *
-			 * XXX Is this comment needed? The one a bit further down says
-			 * about the same thing, no?
-			 */
-
-			/*
-			 * Prepare to iterate over the TBM. This will return the
-			 * dsa_pointer of the iterator state which will be used by
-			 * multiple processes to iterate jointly.
-			 */
-			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
-#ifdef USE_PREFETCH
-			if (prefetch_maximum > 0)
-			{
-				pstate->prefetch_iterator =
-					tbm_prepare_shared_iterate(node->tbm);
-			}
 #endif
-			/* We have initialized the shared state so wake up others. */
-			BitmapDoneInitializingSharedState(pstate);
-		}
+		/* We have initialized the shared state so wake up others. */
+		BitmapDoneInitializingSharedState(pstate);
+	}
+
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!node->scan_in_progress)
+	{
+		bool		need_tuples = false;
 
 		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
 		 */
-		if (!node->scan_in_progress)
-		{
-			bool		need_tuples = false;
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
+		node->scandesc = table_beginscan_bm(node->ss.ss_currentRelation,
+											node->ss.ps.state->es_snapshot,
+											pstate,
+											need_tuples,
+											prefetch_maximum);
+		node->scan_in_progress = true;
+	}
+	else
+	{
+		Assert(node->scandesc);
+		tbm_end_iterate(&node->scandesc->iterator);
+		/* rescan to release any page pin */
+		table_rescan_bm(node->scandesc);
+	}
 
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  pstate,
-									  need_tuples,
-									  prefetch_maximum);
-			node->scandesc = scan;
-			node->scan_in_progress = true;
-		}
-		else
-		{
-			Assert(scan);
-			/* rescan to release any page pin */
-			tbm_end_iterate(&scan->iterator);
-			table_rescan_bm(scan);
-		}
+	tbm_begin_iterate(&node->scandesc->iterator, node->tbm, dsa,
+					  pstate ?
+					  pstate->tbmiterator :
+					  InvalidDsaPointer);
 
-		tbm_begin_iterate(&scan->iterator, node->tbm, dsa,
+	/*
+	 * We use *two* iterators, one for the pages we are actually scanning and
+	 * another that runs ahead of the first for prefetching.
+	 * scan->prefetch_pages tracks exactly how many pages ahead the prefetch
+	 * iterator is.  Also, scan->prefetch_target tracks the desired prefetch
+	 * distance, which starts small and increases up to the prefetch_maximum.
+	 * This is to avoid doing a lot of prefetching in a scan that stops after
+	 * a few tuples because of a LIMIT.
+	 */
+#ifdef USE_PREFETCH
+	if (prefetch_maximum > 0)
+		tbm_begin_iterate(&node->scandesc->prefetch_iterator, node->tbm, dsa,
 						  pstate ?
-						  pstate->tbmiterator :
+						  pstate->prefetch_iterator :
 						  InvalidDsaPointer);
-
-		/*
-		 * We use *two* iterators, one for the pages we are actually scanning
-		 * and another that runs ahead of the first for prefetching.
-		 * scan->prefetch_pages tracks exactly how many pages ahead the
-		 * prefetch iterator is.  Also, scan->prefetch_target tracks the
-		 * desired prefetch distance, which starts small and increases up to
-		 * the prefetch_maximum. This is to avoid doing a lot of prefetching
-		 * in a scan that stops after a few tuples because of a LIMIT.
-		 */
-#ifdef USE_PREFETCH
-		if (prefetch_maximum > 0)
-			tbm_begin_iterate(&scan->prefetch_iterator, node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 
-		node->initialized = true;
 
+	node->initialized = true;
+}
+
+/* ----------------------------------------------------------------
+ *		BitmapHeapNext
+ *
+ *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+BitmapHeapNext(BitmapHeapScanState *node)
+{
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
+	BitmapTableScanDesc *scan = node->scandesc;
+
+	/*
+	 * If we haven't yet performed the underlying index scan, do it, and begin
+	 * the iteration over the bitmap.
+	 */
+	if (!node->initialized)
+	{
+		BitmapTableScanSetup(node);
+		scan = node->scandesc;
 		goto new_page;
 	}
 
-- 
2.45.2

v22b-0024-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=UTF-8; name=v22b-0024-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From afba4ebb7113716d9cd4d34321f2a634d44c28b1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 18:02:38 -0400
Subject: [PATCH v22b 24/29] Remove table AM callback scan_bitmap_next_block

Non block-based table AMs might find implementing bitmap table scan
somewhat easier by removing table_scan_bitmap_next_block(). Now bitmap
table scan code only calls table_scan_bitmap_next_tuple().

This commit turns the heap AM implementation of scan_bitmap_next_block()
into a local helper in heapam_handler.c.
---
 src/backend/access/heap/heapam_handler.c  | 58 +++++++++------
 src/backend/access/table/tableamapi.c     |  3 -
 src/backend/executor/nodeBitmapHeapscan.c | 77 ++++++++------------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 88 ++++++-----------------
 5 files changed, 88 insertions(+), 140 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 166a84b909e..71c74fa12c6 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2334,18 +2334,22 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
 #endif							/* USE_PREFETCH */
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
+/*
+ * Prepare to fetch / check / return tuples as part of a bitmap heap scan.
+ * `scan` needs to have been started via heap_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set to indicate whether or not the tuples from this block
+ * should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  */
-
 static bool
-heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
+heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2516,9 +2520,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
 	return true;
 }
 
+
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	ParallelBitmapHeapState *pstate = sscan->pstate;
@@ -2526,22 +2537,28 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 	Page		page;
 	ItemId		lp;
 
-	if (scan->empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		scan->empty_tuples_pending--;
-		BitmapPrefetch(scan);
-		return true;
-	}
+		if (scan->empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			scan->empty_tuples_pending--;
+			BitmapPrefetch(scan);
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
-		return false;
+		if (!heapam_scan_bitmap_next_block(scan, recheck, lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2942,7 +2959,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index e9b598256fb..a47527d490a 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 317cbda857a..badc4b98dc5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -185,70 +185,49 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext = node->ss.ps.ps_ExprContext;
-	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
-	BitmapTableScanDesc *scan = node->scandesc;
+	ExprContext *econtext;
+	TupleTableSlot *slot;
+	BitmapTableScanDesc *scan;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->scandesc;
-		goto new_page;
-	}
 
-	for (;;)
+	scan = node->scandesc;
+	econtext = node->ss.ps.ps_ExprContext;
+	slot = node->ss.ss_ScanTupleSlot;
+
+	while (table_scan_bitmap_next_tuple(scan, slot,
+										&node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+		/*
+		 * Continuing in previously obtained page.
+		 */
 
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * XXX maybe add comment explaining what "false" means here?
-		 *
-		 * XXX I'm a bit unsure if this needs to be handled using goto. Wouldn't
-		 * it be simpler / easier to understand to have two nested loops?
-		 *
-		 * while (true)
-		 *		if (!table_scan_bitmap_next_block(...)) { break; }
-		 *		while (table_scan_bitmap_next_tuple(...)) {
-		 *			... process tuples ...
-		 *		}
-		 *
-		 * But I haven't tried implementing this.
-		 */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 775955363ef..c11ff3a1bae 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -324,7 +324,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a00b9bd296a..d496d68f1c2 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -808,37 +808,20 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from as part of a bitmap table
-	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
-	 * bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin a block, and do the necessary work to
-	 * allow scan_bitmap_next_tuple() to return tuples (e.g. depending on the
-	 * table AM, it might make sense to perform tuple visibility checks at
-	 * this time).
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
-	 * block; otherwise, `exact_pages` is incremented.
-	 *
-	 * Prefetching future blocks indicated in the bitmap is left to the table
-	 * AM.
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
-										   bool *recheck,
-										   long *lossy_pages, long *exact_pages);
-
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
 	bool		(*scan_bitmap_next_tuple) (BitmapTableScanDesc *scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot, bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1982,54 +1965,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * ----------------------------------------------------------------------------
  */
 
+
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
- * incremented if the block's representation in the bitmap is lossy; otherwise,
- * `exact_pages` is incremented.
- *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked. Tuples from lossy pages will always
- * need to be rechecked, but some non-lossy pages' tuples may also require
- * recheck.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `blockno` is only used in bitmap table scan code to validate that the
- * prefetch block is staying ahead of the current block.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
+table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
-														 recheck,
-														 lossy_pages, exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2040,7 +1995,8 @@ table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rel->rd_tableam->scan_bitmap_next_tuple(scan,
-														 slot);
+														 slot, recheck,
+														 lossy_pages, exact_pages);
 }
 
 /*
-- 
2.45.2

v22b-0025-review.patchtext/x-patch; charset=UTF-8; name=v22b-0025-review.patchDownload
From 4b9efb3a9d7af472574586a3c6cedb94ddc53264 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 23:51:25 +0200
Subject: [PATCH v22b 25/29] review

---
 src/backend/access/table/tableamapi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index a47527d490a..379b7df619e 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,6 +91,9 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
+	/* XXX shouldn't this check that _block is not set without _tuple?
+	 * Also, the commit message says _block is "local helper" but then
+	 * why would it be part of TableAmRoutine? */
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
-- 
2.45.2

v22b-0026-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-patch; charset=UTF-8; name=v22b-0026-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From 9b16d92591b612ec7be09adb0cf829172545d94d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 16:25:14 -0400
Subject: [PATCH v22b 26/29] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 25 +++++++------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index eeef413b7f5..ca7c4f4eaa1 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -184,7 +175,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -225,7 +216,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -393,7 +384,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -699,8 +690,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1470,8 +1460,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 472c0b444bf..7efb5ac4ca8 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -41,9 +42,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /*
-- 
2.45.2

v22b-0027-review.patchtext/x-patch; charset=UTF-8; name=v22b-0027-review.patchDownload
From 8a4d7ea0bc7d6d0851c7c352d2181e51ec3d1102 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tv@fuzzy.cz>
Date: Tue, 18 Jun 2024 23:55:48 +0200
Subject: [PATCH v22b 27/29] review

---
 src/include/nodes/tidbitmap.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 7efb5ac4ca8..76d97ced9f5 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -50,6 +50,8 @@ typedef struct TBMIterateResult
 	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
 	 * the per-page bitmaps variable size.  We just legislate that the size is
 	 * this:
+	 *
+	 * XXX Doesn't this make it tied to heap too much?
 	 */
 	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
-- 
2.45.2

v22b-0028-Separate-TBMIterator-and-TBMIterateResult.patchtext/x-patch; charset=UTF-8; name=v22b-0028-Separate-TBMIterator-and-TBMIterateResult.patchDownload
From b76c6107782cc0133fd0f0a913c41ba7ef8d1491 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 17:09:50 -0400
Subject: [PATCH v22b 28/29] Separate TBMIterator and TBMIterateResult

Remove the TBMIterateResult from the TBMSerialIterator and
TBMSharedIterator and have tbm_[shared_]iterate() take a
TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c          | 49 +++++++++------
 src/backend/access/gin/ginscan.c         |  2 +-
 src/backend/access/heap/heapam_handler.c | 66 ++++++++++----------
 src/backend/nodes/tidbitmap.c            | 77 ++++++++++++------------
 src/include/access/gin_private.h         |  2 +-
 src/include/nodes/tidbitmap.h            |  6 +-
 6 files changed, 108 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 9c53ca19f06..33226603407 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,7 +332,20 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -374,6 +387,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_private_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +837,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_serial_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -858,10 +873,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +890,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 5b9a0eaea73..09e1586c4ac 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 71c74fa12c6..7c9c11af513 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2132,17 +2132,19 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 		{
 			while (scan->prefetch_pages < scan->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				scan->prefetch_pages++;
-				scan->pfblock = tbmpre->blockno;
+				scan->pfblock = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2151,13 +2153,13 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -2172,7 +2174,7 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -2191,25 +2193,25 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				scan->pfblock = tbmpre->blockno;
+				scan->pfblock = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
@@ -2228,7 +2230,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = scan->base.pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -2242,8 +2244,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 		else if (!prefetch_iterator->exhausted)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblock = tbmpre.blockno;
 		}
 		return;
 	}
@@ -2282,8 +2284,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 			 */
 			if (!prefetch_iterator->exhausted)
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblock = tbmpre.blockno;
 			}
 		}
 	}
@@ -2354,7 +2356,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	scan->vis_idx = 0;
 	scan->vis_ntuples = 0;
@@ -2367,9 +2369,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->base.iterator);
+		tbm_iterate(&scan->base.iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
 		/*
@@ -2380,11 +2382,11 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= scan->nblocks);
 
 	/* Got a valid block */
-	block = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	block = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2392,14 +2394,14 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->base.flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->base.rel, tbmres.blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(scan->empty_tuples_pending >= 0);
 
-		scan->empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
@@ -2431,7 +2433,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2440,9 +2442,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2493,7 +2495,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	scan->vis_ntuples = ntup;
 
 	/* XXX why inverted condition, compared to the original one in BitmapHeapNext? */
-	if (tbmres->ntuples < 0)
+	if (tbmres.ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index ca7c4f4eaa1..c663998fac1 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -175,7 +175,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -216,7 +215,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -951,22 +949,22 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  If result->ntuples
+ * < 0, then the bitmap is "lossy" and failed to remember the exact tuples to
+ * look at on this page --- the caller must examine all tuples on the page and
+ * check if they meet the intended condition.  If result->recheck is true, only
+ * the indicated tuples need be examined, but the condition must be rechecked
+ * anyway.  (For ease of testing, recheck is always set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
+	Assert(tbmres);
 
 	/*
 	 * If lossy chunk pages remain, make sure we've advanced schunkptr/
@@ -1002,11 +1000,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1022,16 +1020,16 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1041,10 +1039,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1095,13 +1092,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1111,21 +1108,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1597,14 +1594,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
 	Assert(!iterator->exhausted);
 
 	if (iterator->private)
-		return tbm_private_iterate(iterator->private);
+		tbm_private_iterate(iterator->private, tbmres);
 	else
-		return tbm_shared_iterate(iterator->parallel);
+		tbm_shared_iterate(iterator->parallel, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 78800509367..b528ab715f1 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 76d97ced9f5..871b5fdd2c4 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -85,8 +85,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -96,7 +96,7 @@ extern long tbm_calculate_entries(double maxbytes);
 extern void tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
 							  dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 
 #endif							/* TIDBITMAP_H */
-- 
2.45.2

v22b-0029-Use-streaming-I-O-in-Bitmap-Heap-Scans.patchtext/x-patch; charset=UTF-8; name=v22b-0029-Use-streaming-I-O-in-Bitmap-Heap-Scans.patchDownload
From 54f1a881954a9ce29ade437715a369f009e4646b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 18:11:57 -0400
Subject: [PATCH v22b 29/29] Use streaming I/O in Bitmap Heap Scans

Instead of calling ReadBuffer() for each block, bitmap heap scans now
use the streaming API introduced in b5a9b18cd0.

The read stream API prefetches blocks from the bitmap, so this commit
removes all of the bespoke bitmap heap scan prefetch code.

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  79 ++++-
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  70 +----
 src/include/access/heapam.h               |  14 +-
 src/include/access/relscan.h              |   4 -
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   6 -
 7 files changed, 115 insertions(+), 416 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 9847ce2c3aa..211233cd147 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -285,6 +285,59 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+static BlockNumber
+heap_bitmap_scan_stream_read_next(ReadStream *stream,
+								  void *callback_private_data,
+								  void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc *scan = callback_private_data;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&scan->base.iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(scan->base.flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
+		{
+			/* can't be lossy in the skip_fetch case */
+			Assert(tbmres->ntuples >= 0);
+			Assert(scan->empty_tuples_pending >= 0);
+
+			scan->empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1230,8 +1283,7 @@ heap_endscan(TableScanDesc sscan)
 }
 
 BitmapTableScanDesc *
-heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
-				  int prefetch_maximum)
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 {
 	BitmapHeapScanDesc *scan;
 
@@ -1268,11 +1320,13 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
 	scan->pvmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
-	scan->prefetch_maximum = prefetch_maximum;
-
-	/* Only used for serial BHS */
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
+	scan->read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+												   NULL,
+												   scan->base.rel,
+												   MAIN_FORKNUM,
+												   heap_bitmap_scan_stream_read_next,
+												   scan,
+												   sizeof(TBMIterateResult));
 
 	return (BitmapTableScanDesc *) scan;
 }
@@ -1282,6 +1336,10 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	/* Reset the read stream on rescan. */
+	if (scan->read_stream)
+		read_stream_reset(scan->read_stream);
+
 	if (BufferIsValid(scan->cbuf))
 	{
 		ReleaseBuffer(scan->cbuf);
@@ -1313,10 +1371,6 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->ctup.t_data = NULL;
 	ItemPointerSetInvalid(&scan->ctup.t_self);
-
-	/* Only used for serial BHS */
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 }
 
 void
@@ -1324,6 +1378,9 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	if (scan->read_stream)
+		read_stream_end(scan->read_stream);
+
 	if (BufferIsValid(scan->cbuf))
 		ReleaseBuffer(scan->cbuf);
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7c9c11af513..8d22cb9aecf 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,9 +54,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
-static inline void BitmapPrefetch(BitmapHeapScanDesc *scan);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan);
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 static const TableAmRoutine heapam_methods;
@@ -2115,227 +2112,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblock = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (!prefetch_iterator->exhausted)
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				scan->pfblock = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (!prefetch_iterator->exhausted)
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblock = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (scan->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!prefetch_iterator->exhausted)
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblock = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= scan->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
-			scan->prefetch_target = scan->prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < scan->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= scan->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
-			pstate->prefetch_target = scan->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap heap scan.
  * `scan` needs to have been started via heap_beginscan_bm(). Returns false if
@@ -2356,63 +2132,52 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+	void	   *per_buffer_data;
+
+	Assert(scan->read_stream);
 
 	scan->vis_idx = 0;
 	scan->vis_ntuples = 0;
 
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(scan);
-
-	do
+	if (BufferIsValid(scan->cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		tbm_iterate(&scan->base.iterator, &tbmres);
+		ReleaseBuffer(scan->cbuf);
+		scan->cbuf = InvalidBuffer;
+	}
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	scan->cbuf = read_stream_next_buffer(scan->read_stream, &per_buffer_data);
 
+	if (BufferIsInvalid(scan->cbuf))
+	{
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= scan->nblocks);
+		*recheck = false;
+		return scan->empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	block = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->base.flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->base.rel, tbmres.blockno, &scan->vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(scan->empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		scan->empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(scan->cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	/* Got a valid block */
+	block = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
+	scan->cblock = tbmres->blockno;
+	scan->vis_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	scan->cbuf = ReleaseAndReadBuffer(scan->cbuf,
-									  scan->base.rel,
-									  block);
-	scan->cblock = block;
 	buffer = scan->cbuf;
 	snapshot = scan->base.snapshot;
 
@@ -2433,7 +2198,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2442,9 +2207,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2495,23 +2260,11 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	scan->vis_ntuples = ntup;
 
 	/* XXX why inverted condition, compared to the original one in BitmapHeapNext? */
-	if (tbmres.ntuples < 0)
+	if (tbmres->ntuples < 0)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->base.pstate == NULL &&
-		!scan->base.prefetch_iterator.exhausted &&
-		scan->pfblock < block)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(scan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2534,7 +2287,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
-	ParallelBitmapHeapState *pstate = sscan->pstate;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
@@ -2554,7 +2306,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 			 */
 			ExecStoreAllNullTuple(slot);
 			scan->empty_tuples_pending--;
-			BitmapPrefetch(scan);
 			return true;
 		}
 
@@ -2562,36 +2313,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!pstate)
-	{
-		if (scan->prefetch_target < scan->prefetch_maximum)
-			scan->prefetch_target++;
-	}
-	else if (pstate->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target < scan->prefetch_maximum)
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(scan);
-
 	targoffset = scan->vis_tuples[scan->vis_idx];
 	page = BufferGetPage(scan->cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index badc4b98dc5..85ec9b8e9db 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -63,17 +63,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 {
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
-	int			prefetch_maximum = 0;
-
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-#ifdef USE_PREFETCH
-	Relation	rel = node->ss.ss_currentRelation;
-
-	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-#endif
 
 	/*
 	 * Scan the index, build the bitmap, and set up shared state for parallel.
@@ -95,24 +84,13 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 			elog(ERROR, "unrecognized result from subplan");
 
-		/*
-		 * Two iterators are used -- one for the pages being scanned and one
-		 * for the blocks being prefetched.
-		 */
-
 		/*
 		 * Prepare to iterate over the TBM. This will return the dsa_pointer
 		 * of the iterator state which will be used by multiple processes to
 		 * iterate jointly.
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
-#ifdef USE_PREFETCH
-		if (prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif
+
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -137,9 +115,7 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 
 		node->scandesc = table_beginscan_bm(node->ss.ss_currentRelation,
 											node->ss.ps.state->es_snapshot,
-											pstate,
-											need_tuples,
-											prefetch_maximum);
+											need_tuples);
 		node->scan_in_progress = true;
 	}
 	else
@@ -155,24 +131,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
 
-	/*
-	 * We use *two* iterators, one for the pages we are actually scanning and
-	 * another that runs ahead of the first for prefetching.
-	 * scan->prefetch_pages tracks exactly how many pages ahead the prefetch
-	 * iterator is.  Also, scan->prefetch_target tracks the desired prefetch
-	 * distance, which starts small and increases up to the prefetch_maximum.
-	 * This is to avoid doing a lot of prefetching in a scan that stops after
-	 * a few tuples because of a LIMIT.
-	 */
-#ifdef USE_PREFETCH
-	if (prefetch_maximum > 0)
-		tbm_begin_iterate(&node->scandesc->prefetch_iterator, node->tbm, dsa,
-						  pstate ?
-						  pstate->prefetch_iterator :
-						  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
-
 	node->initialized = true;
 }
 
@@ -323,22 +281,21 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	scanDesc = node->scandesc;
 
-	/*
-	 * close down subplans
-	 */
-	ExecEndNode(outerPlanState(node));
-
-
 	/*
 	 * close heap scan
 	 */
 	if (scanDesc)
 	{
 		tbm_end_iterate(&scanDesc->iterator);
-		tbm_end_iterate(&scanDesc->prefetch_iterator);
 		table_endscan_bm(scanDesc);
 	}
 
+	/*
+	 * close down subplans
+	 */
+	ExecEndNode(outerPlanState(node));
+
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
@@ -499,12 +456,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -531,17 +485,9 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
-	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 5d73bb361e3..c9d91b72b1a 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -114,16 +114,7 @@ typedef struct BitmapHeapScanDesc
 
 	BlockNumber cblock;			/* current block # in scan, if any */
 
-	/* used to validate pf stays ahead of current block */
-	BlockNumber pfblock;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
-
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
+	ReadStream *read_stream;
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -330,8 +321,7 @@ extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 extern void heap_endscan(TableScanDesc sscan);
 
 extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
-											  Snapshot snapshot, uint32 flags,
-											  int prefetch_maximum);
+											  Snapshot snapshot, uint32 flags);
 extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
 void		heap_endscan_bm(BitmapTableScanDesc *sscan);
 
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index a1207c22b3c..0fe0b8c8b4f 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -64,14 +64,10 @@ typedef struct BitmapTableScanDesc
 	Relation	rel;			/* heap relation descriptor */
 	struct SnapshotData *snapshot;	/* snapshot to see */
 
-	struct ParallelBitmapHeapState *pstate;
-
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
 	TBMIterator iterator;
-	/* iterator for prefetching ahead of current page */
-	TBMIterator prefetch_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d496d68f1c2..632a07c7a0c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -354,7 +354,7 @@ typedef struct TableAmRoutine
 	 */
 	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
 										   Snapshot snapshot,
-										   uint32 flags, int prefetch_maximum);
+										   uint32 flags);
 
 	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
 
@@ -944,19 +944,14 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   struct ParallelBitmapHeapState *pstate,
-				   bool need_tuple,
-				   int prefetch_maximum)
+				   bool need_tuple)
 {
-	BitmapTableScanDesc *result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, prefetch_maximum);
-	result->pstate = pstate;
-	return result;
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 28fc6e7221f..20459b6bfbb 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1770,11 +1770,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1782,10 +1779,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.45.2

#147Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#146)
19 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, Jun 18, 2024 at 6:02 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I went through v22 to remind myself of what the patches do and do some
basic review - I have some simple questions / comments for now, nothing
major. I've kept the comments in separate 'review' patches, it does not
seem worth copying here.

Thanks so much for the review!

I've implemented your feedback in attached v23 except for what I
mention below. I have not gone through each patch in the new set very
carefully after making the changes because I think we should resolve
the question of adding the new table scan descriptor before I do that.
A change there will require a big rebase. Then I can go through each
patch very carefully.

From your v22b-0005-review.patch:

src/backend/executor/nodeBitmapHeapscan.c | 14 ++++++++++++++
src/include/access/tableam.h | 2 ++
2 files changed, 16 insertions(+)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c
b/src/backend/executor/nodeBitmapHeapscan.c
index e8b4a754434..6d7ef9ced19 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -270,6 +270,20 @@ new_page:

BitmapAdjustPrefetchIterator(node);

+        /*
+         * XXX I'm a bit unsure if this needs to be handled using
goto. Wouldn't
+         * it be simpler / easier to understand to have two nested loops?
+         *
+         * while (true)
+         *        if (!table_scan_bitmap_next_block(...)) { break; }
+         *        while (table_scan_bitmap_next_tuple(...)) {
+         *            ... process tuples ...
+         *        }
+         *
+         * But I haven't tried implementing this.
+         */
         if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
                                           &node->lossy_pages,
&node->exact_pages))
             break;

We need to call table_scan_bimtap_next_block() the first time we call
BitmapHeapNext() on each scan but all subsequent invocations of
BitmapHeapNext() must call table_scan_bitmap_next_tuple() first each
-- because we return from BitmapHeapNext() to yield a tuple even when
there are more tuples on the page. I tried refactoring this a few
different ways and personally found the goto most clear.

From your v22b-0010-review.patch:

@@ -557,6 +559,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
table_rescan(node->ss.ss_currentScanDesc, NULL);

     /* release bitmaps and buffers if any */
+    /* XXX seems it should not be right after the comment, also shouldn't
+     * we still reset the prefetch_iterator field to NULL? */
     tbm_end_iterate(&node->prefetch_iterator);
     if (node->tbm)
         tbm_free(node->tbm);

prefetch_iterator is a TBMIterator which is stored in the struct (as
opposed to having a pointer to it stored in the struct).
tbm_end_iterate() sets the actual private and shared iterator pointers
to NULL.

From your v22b-0017-review.patch

diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 036ef29e7d5..9c711ce0eb0 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -52,6 +52,13 @@ typedef struct TableScanDescData
 } TableScanDescData;
 typedef struct TableScanDescData *TableScanDesc;
+/*
+ * XXX I don't understand why we should have this special node if we
+ * don't have special nodes for other scan types.

In this case, up until the final commit (using the read stream
interface), there are six fields required by bitmap heap scan that are
not needed by any other user of HeapScanDescData. There are also
several members of HeapScanDescData that are not needed by bitmap heap
scans and all of the setup in initscan() for those fields is not
required for bitmap heap scans.

Also, because the BitmapHeapScanDesc needs information like the
ParallelBitmapHeapState and prefetch_maximum (for use in prefetching),
the scan_begin() callback would have to take those as parameters. I
thought adding so much bitmap table scan-specific information to the
generic table scan callbacks was a bad idea.

Once we add the read stream API code, the number of fields required
for bitmap heap scan that are in the scan descriptor goes down to
three. So, perhaps we could justify having that many bitmap heap
scan-specific fields in the HeapScanDescData.

Though, I actually think we could start moving toward having
specialized scan descriptors if the requirements for that scan type
are appreciably different. I can't think of new code that would be
added to the HeapScanDescData that would have to be duplicated over to
specialized scan descriptors.

With the final read stream state, I can see the argument for bloating
the HeapScanDescData with three extra members and avoiding making new
scan descriptors. But, for the intermediate patches which have all of
the bitmap prefetch members pushed down into the HeapScanDescData, I
think it is really not okay. Six members only for bitmap heap scans
and two bitmap-specific members to begin_scan() seems bad.

What I thought we plan to do is commit the refactoring patches
sometime after the branch for 18 is cut and leave the final read
stream patch uncommitted so we can do performance testing on it. If
you think it is okay to have the six member bloated HeapScanDescData
in master until we push the read stream code, I am okay with removing
the BitmapTableScanDesc and BitmapHeapScanDesc.

+ * XXX Also, maybe this should do the naming convention with Data at
+ * the end (mostly for consistency).
+ */
 typedef struct BitmapTableScanDesc
 {
     Relation    rs_rd;            /* heap relation descriptor */

I really want to move away from these Data typedefs. I find them so
confusing as a developer, but it's hard to justify ripping out the
existing ones because of code churn. If we add new scan descriptors, I
had really hoped to start using a different pattern.

From your v22b-0025-review.patch

diff --git a/src/backend/access/table/tableamapi.c
b/src/backend/access/table/tableamapi.c
index a47527d490a..379b7df619e 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,6 +91,9 @@ GetTableAmRoutine(Oid amhandler)

Assert(routine->relation_estimate_size != NULL);

+    /* XXX shouldn't this check that _block is not set without _tuple?
+     * Also, the commit message says _block is "local helper" but then
+     * why would it be part of TableAmRoutine? */
     Assert(routine->scan_sample_next_block != NULL);
     Assert(routine->scan_sample_next_tuple != NULL);

scan_bitmap_next_block() is removed as a table AM callback here, so we
don't check if it is set. We do still check if scan_bitmap_next_tuple
is set if amgetbitmap is not NULL. heapam_scan_bitmap_next_block() is
now a local helper for heapam_scan_bitmap_next_tuple(). Perhaps I
should change the name to something like heap_scan_bitmap_next_block()
to make it clear it is not an implementation of a table AM callback?

- Melanie

Attachments:

v23-0005-BitmapHeapScan-initialize-some-prefetch-state-el.patchtext/x-patch; charset=US-ASCII; name=v23-0005-BitmapHeapScan-initialize-some-prefetch-state-el.patchDownload
From 7064e561230698dd0ecb8866b8eaff1975fe20ec Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:51:11 -0400
Subject: [PATCH v23 05/19] BitmapHeapScan initialize some prefetch state
 elsewhere

The prefetch_target and prefetch_pages members can be initialized in the
scan and rescan functions. This makes it more straightforward to use the
unified TBMIterator API for BitmapHeapScan.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/executor/nodeBitmapHeapscan.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 19716e42a6..f43b7b2c44 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -111,11 +111,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
-			{
 				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
 #endif							/* USE_PREFETCH */
 		}
 		else
@@ -614,6 +610,9 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
 	node->pfblockno = InvalidBlockNumber;
+	/* Only used for serial BHS */
+	node->prefetch_pages = 0;
+	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -715,7 +714,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->lossy_pages = 0;
 	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
+	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
@@ -851,7 +850,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -878,6 +877,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
+	pstate->prefetch_pages = 0;
+	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-- 
2.34.1

v23-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchtext/x-patch; charset=US-ASCII; name=v23-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchDownload
From 4177cc60ac7c25ca6a271f54974570348e9f969f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v23 02/19] Remove table_scan_bitmap_next_tuple parameter
 tbmres

In order to remove TBMIterateResults as a flow control mechanism in
BitmapHeapNext(), they can no longer be used as a means of communication
between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Remove the TBMIterateResult parameter from
table_scan_bitmap_next_tuple().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Mark Dilger
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index acc6d60156..0fb5818d4c 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2259,7 +2259,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index de7a293de8..e63f6f0429 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -281,7 +281,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ad3339196a..9f11cf3729 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,10 +797,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -831,15 +828,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -2003,7 +1995,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2015,7 +2006,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.34.1

v23-0003-Make-table_scan_bitmap_next_block-async-friendly.patchtext/x-patch; charset=US-ASCII; name=v23-0003-Make-table_scan_bitmap_next_block-async-friendly.patchDownload
From feaea9be73d18531c43e122732c1cad60f06cbd6 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v23 03/19] Make table_scan_bitmap_next_block() async-friendly

table_scan_bitmap_next_block() previously returned false when
table_scan_bitmap_next_tuple() should not be called for the tuples on
the page. This could happen when there were no visible tuples on the
page or when, due to concurrent activity on the table, the block
returned by the iterator is past the end of the table (as recorded when
the scan started).

That forced the caller to be responsible for determining if additional
blocks should be fetched and for invoking table_scan_bitmap_next_block()
for these blocks.

It makes more sense for table_scan_bitmap_next_block() to be responsible
for finding a block that is not past the end of the table (as of the
beginning of the scan) and for table_scan_bitmap_next_tuple() to return
false if there are no visible tuples on the page.

This also allows us to move responsibility for advancing the iterator to
table AM specific code. This means handling invalid blocks is entirely
up to the table AM.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  54 +++--
 src/backend/executor/nodeBitmapHeapscan.c | 237 ++++++++++++----------
 src/include/access/relscan.h              |   7 +
 src/include/access/tableam.h              |  47 +++--
 src/include/nodes/execnodes.h             |  12 +-
 5 files changed, 212 insertions(+), 145 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 0fb5818d4c..d0757b8e50 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,18 +2120,48 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->tbmiterator);
+
+		if (tbmres == NULL)
+			return false;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2150,16 +2180,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2254,7 +2275,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*lossy_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index e63f6f0429..1c9a931a78 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,9 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -85,11 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -105,6 +96,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,8 +107,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
+			tbmiterator = tbm_begin_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -166,9 +159,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -207,46 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		scan->tbmiterator = tbmiterator;
+		scan->shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->lossy_pages, &node->exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -267,45 +235,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
+
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
+
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
 
 		/*
-		 * Attempt to fetch tuple from AM.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
-		}
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->lossy_pages, &node->exact_pages))
+			break;
 
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -331,13 +314,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -351,14 +338,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -383,7 +377,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -461,6 +458,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -518,6 +516,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -574,17 +574,32 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* rescan to release any page pin */
-	if (node->ss.ss_currentScanDesc)
+	TableScanDesc scan = node->ss.ss_currentScanDesc;
+
+	if (scan)
+	{
+		/*
+		 * End iteration on iterators saved in scan descriptor.
+		 */
+		if (scan->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->shared_tbmiterator);
+			scan->shared_tbmiterator = NULL;
+		}
+
+		if (scan->tbmiterator)
+		{
+			tbm_end_iterate(scan->tbmiterator);
+			scan->tbmiterator = NULL;
+		}
+
+		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	}
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -592,13 +607,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -629,28 +644,40 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+	if (scanDesc)
+	{
+		/*
+		 * End iteration on iterators saved in scan descriptor.
+		 */
+		if (scanDesc->shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scanDesc->shared_tbmiterator);
+			scanDesc->shared_tbmiterator = NULL;
+		}
+
+		if (scanDesc->tbmiterator)
+		{
+			tbm_end_iterate(scanDesc->tbmiterator);
+			scanDesc->tbmiterator = NULL;
+		}
+
+		/*
+		 * close table scan
+		 */
+		table_endscan(scanDesc);
+	}
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -683,8 +710,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
@@ -692,9 +717,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 521043304a..024dc08c42 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,6 +24,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -36,6 +39,10 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
+	/* Iterators for Bitmap Table Scans */
+	struct TBMIterator *tbmiterator;
+	struct TBMSharedIterator *shared_tbmiterator;
+
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 9f11cf3729..1ae1487797 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "storage/read_stream.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
@@ -36,7 +37,6 @@ extern PGDLLIMPORT bool synchronize_seqscans;
 struct BulkInsertStateData;
 struct IndexInfo;
 struct SampleScanState;
-struct TBMIterateResult;
 struct VacuumParams;
 struct ValidateIndexState;
 
@@ -790,19 +790,14 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, `exact_pages` is incremented.
 	 *
@@ -821,7 +816,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -959,12 +954,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->shared_tbmiterator = NULL;
+	result->tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1955,19 +1954,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. `lossy_pages` is incremented if the block's
- * representation in the bitmap is lossy; otherwise, `exact_pages` is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set by the table AM to indicate whether or not the tuples
+ * from this block should be rechecked. Tuples from lossy pages will always
+ * need to be rechecked, but some non-lossy pages' tuples may also require
+ * recheck.
+ *
+ * `blockno` is only used in bitmap table scan code to validate that the
+ * prefetch block is staying ahead of the current block.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -1980,9 +1986,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8bc421e7c0..0af7906a18 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1795,8 +1795,6 @@ typedef struct ParallelBitmapHeapState
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
@@ -1805,9 +1803,11 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1815,8 +1815,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
@@ -1825,9 +1823,11 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v23-0001-table_scan_bitmap_next_block-counts-lossy-and-ex.patchtext/x-patch; charset=US-ASCII; name=v23-0001-table_scan_bitmap_next_block-counts-lossy-and-ex.patchDownload
From d6de748aab15b116b60210f01f55b5a2d763deb9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v23 01/19] table_scan_bitmap_next_block counts lossy and exact
 pages

Keep track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap in table AM-specific code. These
counters are used for EXPLAIN.

This is a step toward removing TBMIterateResults as a flow control
mechanism in BitmapHeapNext(), which is required for a more asynchronous
design. It also is more table AM agnostic.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6f8b1b7929..acc6d60156 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,7 +2120,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  long *lossy_pages, long *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2248,6 +2249,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6b48a6d835..de7a293de8 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,8 +212,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -233,14 +231,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->exact_pages++;
-			else
-				node->lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->lossy_pages, &node->exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8e583b45cd..ad3339196a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -806,6 +806,9 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * block; otherwise, `exact_pages` is incremented.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -821,7 +824,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1959,17 +1963,21 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * the page, true otherwise. `lossy_pages` is incremented if the block's
+ * representation in the bitmap is lossy; otherwise, `exact_pages` is
+ * incremented.
  *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 long *lossy_pages,
+							 long *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1980,7 +1988,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

v23-0004-Add-common-interface-for-TBMIterators.patchtext/x-patch; charset=US-ASCII; name=v23-0004-Add-common-interface-for-TBMIterators.patchDownload
From 62f1be941ed0cbcd70699fe6dd8dcc93bafe49c9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:41:05 -0400
Subject: [PATCH v23 04/19] Add common interface for TBMIterators

Add and use TBMPrivateIterator, which replaces the current TBMIterator
for serial use cases, and repurpose TBMIterator to be a unified
interface for both the serial and parallel TID Bitmap iterator
interfaces. This encapsulation simplifies call sites for callers
supporting both parallel and serial TID Bitmap access. TBMIterator is
not yet used in this commit.

Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/gin/ginget.c           |   8 +-
 src/backend/access/gin/ginscan.c          |   2 +-
 src/backend/access/heap/heapam_handler.c  |   2 +-
 src/backend/executor/nodeBitmapHeapscan.c |  26 +++---
 src/backend/nodes/tidbitmap.c             | 104 +++++++++++++++++-----
 src/include/access/gin_private.h          |   2 +-
 src/include/access/relscan.h              |   4 +-
 src/include/nodes/execnodes.h             |   2 +-
 src/include/nodes/tidbitmap.h             |  33 +++++--
 src/tools/pgindent/typedefs.list          |   1 +
 10 files changed, 133 insertions(+), 51 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb..9c53ca19f0 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,7 @@ restartScanEntry:
 			if (entry->matchBitmap)
 			{
 				if (entry->matchIterator)
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -385,7 +385,7 @@ restartScanEntry:
 
 		if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
 		{
-			entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+			entry->matchIterator = tbm_begin_private_iterate(entry->matchBitmap);
 			entry->isFinished = false;
 		}
 	}
@@ -832,12 +832,12 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				entry->matchResult = tbm_private_iterate(entry->matchIterator);
 
 				if (entry->matchResult == NULL)
 				{
 					ItemPointerSetInvalid(&entry->curItem);
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
 					entry->isFinished = true;
 					break;
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index af24d38544..5b9a0eaea7 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -246,7 +246,7 @@ ginFreeScanKeys(GinScanOpaque so)
 		if (entry->list)
 			pfree(entry->list);
 		if (entry->matchIterator)
-			tbm_end_iterate(entry->matchIterator);
+			tbm_end_private_iterate(entry->matchIterator);
 		if (entry->matchBitmap)
 			tbm_free(entry->matchBitmap);
 	}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d0757b8e50..84f8ead382 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2143,7 +2143,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (scan->shared_tbmiterator)
 			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
 		else
-			tbmres = tbm_iterate(scan->tbmiterator);
+			tbmres = tbm_private_iterate(scan->tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 1c9a931a78..19716e42a6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,7 +96,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
+		TBMPrivateIterator *tbmiterator = NULL;
 		TBMSharedIterator *shared_tbmiterator = NULL;
 
 		if (!pstate)
@@ -107,12 +107,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_private_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
+				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
 				node->prefetch_pages = 0;
 				node->prefetch_target = -1;
 			}
@@ -279,7 +279,7 @@ new_page:
 			break;
 
 		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * If private, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
@@ -328,7 +328,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
@@ -338,7 +338,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = tbm_private_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -441,19 +441,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_private_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
+					tbm_end_private_iterate(prefetch_iterator);
 					node->prefetch_iterator = NULL;
 					break;
 				}
@@ -589,7 +589,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 		if (scan->tbmiterator)
 		{
-			tbm_end_iterate(scan->tbmiterator);
+			tbm_end_private_iterate(scan->tbmiterator);
 			scan->tbmiterator = NULL;
 		}
 
@@ -599,7 +599,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 	/* release bitmaps and buffers if any */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -657,7 +657,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 
 		if (scanDesc->tbmiterator)
 		{
-			tbm_end_iterate(scanDesc->tbmiterator);
+			tbm_end_private_iterate(scanDesc->tbmiterator);
 			scanDesc->tbmiterator = NULL;
 		}
 
@@ -671,7 +671,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * release bitmaps and buffers if any
 	 */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->shared_prefetch_iterator)
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fc..d035de7f95 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -170,12 +170,12 @@ struct TIDBitmap
 };
 
 /*
- * When iterating over a bitmap in sorted order, a TBMIterator is used to
- * track our progress.  There can be several iterators scanning the same
- * bitmap concurrently.  Note that the bitmap becomes read-only as soon as
- * any iterator is created.
+ * When iterating over a backend-local bitmap in sorted order, a
+ * TBMPrivateIterator is used to track our progress.  There can be several
+ * iterators scanning the same bitmap concurrently.  Note that the bitmap
+ * becomes read-only as soon as any iterator is created.
  */
-struct TBMIterator
+struct TBMPrivateIterator
 {
 	TIDBitmap  *tbm;			/* TIDBitmap we're iterating over */
 	int			spageptr;		/* next spages index */
@@ -213,8 +213,8 @@ typedef struct PTIterationArray
 } PTIterationArray;
 
 /*
- * same as TBMIterator, but it is used for joint iteration, therefore this
- * also holds a reference to the shared state.
+ * same as TBMPrivateIterator, but it is used for joint iteration, therefore
+ * this also holds a reference to the shared state.
  */
 struct TBMSharedIterator
 {
@@ -673,31 +673,31 @@ tbm_is_empty(const TIDBitmap *tbm)
 }
 
 /*
- * tbm_begin_iterate - prepare to iterate through a TIDBitmap
+ * tbm_begin_private_iterate - prepare to iterate through a TIDBitmap
  *
- * The TBMIterator struct is created in the caller's memory context.
- * For a clean shutdown of the iteration, call tbm_end_iterate; but it's
- * okay to just allow the memory context to be released, too.  It is caller's
- * responsibility not to touch the TBMIterator anymore once the TIDBitmap
+ * The TBMPrivateIterator struct is created in the caller's memory context. For
+ * a clean shutdown of the iteration, call tbm_end_iterate; but it's okay to
+ * just allow the memory context to be released, too.  It is caller's
+ * responsibility not to touch the TBMPrivateIterator anymore once the TIDBitmap
  * is freed.
  *
  * NB: after this is called, it is no longer allowed to modify the contents
  * of the bitmap.  However, you can call this multiple times to scan the
  * contents repeatedly, including parallel scans.
  */
-TBMIterator *
-tbm_begin_iterate(TIDBitmap *tbm)
+TBMPrivateIterator *
+tbm_begin_private_iterate(TIDBitmap *tbm)
 {
-	TBMIterator *iterator;
+	TBMPrivateIterator *iterator;
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
 	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
+	 * Create the TBMPrivateIterator struct, with enough trailing space to
+	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
+											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
 	iterator->tbm = tbm;
 
 	/*
@@ -956,7 +956,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 }
 
 /*
- * tbm_iterate - scan through next page of a TIDBitmap
+ * tbm_private_iterate - scan through next page of a TIDBitmap
  *
  * Returns a TBMIterateResult representing one page, or NULL if there are
  * no more pages to scan.  Pages are guaranteed to be delivered in numerical
@@ -968,7 +968,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  * testing, recheck is always set true when ntuples < 0.)
  */
 TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+tbm_private_iterate(TBMPrivateIterator *iterator)
 {
 	TIDBitmap  *tbm = iterator->tbm;
 	TBMIterateResult *output = &(iterator->output);
@@ -1136,14 +1136,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 }
 
 /*
- * tbm_end_iterate - finish an iteration over a TIDBitmap
+ * tbm_end_private_iterate - finish an iteration over a TIDBitmap
  *
  * Currently this is just a pfree, but it might do more someday.  (For
  * instance, it could be useful to count open iterators and allow the
  * bitmap to return to read/write status when there are no more iterators.)
  */
 void
-tbm_end_iterate(TBMIterator *iterator)
+tbm_end_private_iterate(TBMPrivateIterator *iterator)
 {
 	pfree(iterator);
 }
@@ -1556,3 +1556,61 @@ tbm_calculate_entries(double maxbytes)
 
 	return nbuckets;
 }
+
+/*
+ * Start iteration on a shared or private bitmap iterator. Note that tbm will
+ * only be provided by private BitmapHeapScan callers. dsa and dsp will only be
+ * provided by parallel BitmapHeapScan callers. For shared callers, one process
+ * must already have called tbm_prepare_shared_iterate() to create and set up
+ * the TBMSharedIteratorState. The TBMIterator is passed by reference to
+ * accommodate callers who would like to allocate it inside an existing struct.
+ */
+void
+tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+				  dsa_area *dsa, dsa_pointer dsp)
+{
+	Assert(iterator);
+
+	iterator->private_iterator = NULL;
+	iterator->shared_iterator = NULL;
+	iterator->exhausted = false;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+		iterator->shared_iterator = tbm_attach_shared_iterate(dsa, dsp);
+	else
+		iterator->private_iterator = tbm_begin_private_iterate(tbm);
+}
+
+/*
+ * Clean up shared or non-shared bitmap iterator.
+ */
+void
+tbm_end_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->private_iterator)
+		tbm_end_private_iterate(iterator->private_iterator);
+	else if (iterator->shared_iterator)
+		tbm_end_shared_iterate(iterator->shared_iterator);
+
+	iterator->private_iterator = NULL;
+	iterator->shared_iterator = NULL;
+	iterator->exhausted = true;
+}
+
+/*
+ * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
+ */
+TBMIterateResult *
+tbm_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+	Assert(!iterator->exhausted);
+
+	if (iterator->private_iterator)
+		return tbm_private_iterate(iterator->private_iterator);
+	else
+		return tbm_shared_iterate(iterator->shared_iterator);
+}
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae..7880050936 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
-	TBMIterator *matchIterator;
+	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 024dc08c42..159921ffb5 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -24,7 +24,7 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
+struct TBMPrivateIterator;
 struct TBMSharedIterator;
 
 /*
@@ -40,7 +40,7 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Iterators for Bitmap Table Scans */
-	struct TBMIterator *tbmiterator;
+	struct TBMPrivateIterator *tbmiterator;
 	struct TBMSharedIterator *shared_tbmiterator;
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0af7906a18..81447fea8c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1818,7 +1818,7 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator *prefetch_iterator;
+	TBMPrivateIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639b..9dbc7bab7a 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -32,10 +32,21 @@
  */
 typedef struct TIDBitmap TIDBitmap;
 
-/* Likewise, TBMIterator is private */
-typedef struct TBMIterator TBMIterator;
+/* Likewise, TBMPrivateIterator is private */
+typedef struct TBMPrivateIterator TBMPrivateIterator;
 typedef struct TBMSharedIterator TBMSharedIterator;
 
+/*
+ * Callers with both private and parallel implementations can use this unified
+ * API.
+ */
+typedef struct TBMIterator
+{
+	TBMPrivateIterator *private_iterator;
+	TBMSharedIterator *shared_iterator;
+	bool		exhausted;
+} TBMIterator;
+
 /* Result structure for tbm_iterate */
 typedef struct TBMIterateResult
 {
@@ -62,14 +73,26 @@ extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
-extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
 extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
-extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
 													dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+extern void tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+							  dsa_area *dsa, dsa_pointer dsp);
+extern void tbm_end_iterate(TBMIterator *iterator);
+
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+
+static inline bool
+tbm_exhausted(TBMIterator *iterator)
+{
+	return iterator->exhausted;
+}
+
 #endif							/* TIDBITMAP_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 61ad417cde..757a9a3a41 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2795,6 +2795,7 @@ TAR_MEMBER
 TBMIterateResult
 TBMIteratingState
 TBMIterator
+TBMPrivateIterator
 TBMSharedIterator
 TBMSharedIteratorState
 TBMStatus
-- 
2.34.1

v23-0006-BitmapHeapScan-uses-unified-iterator.patchtext/x-patch; charset=US-ASCII; name=v23-0006-BitmapHeapScan-uses-unified-iterator.patchDownload
From b39554e9dcf4e99a1b4fe8f04f28b0669e1de5f5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:39:04 -0400
Subject: [PATCH v23 06/19] BitmapHeapScan uses unified iterator

With the repurposing of TBMIterator as an interface for both parallel
and serial iteration through TIDBitmaps, BitmapHeapScan may now use it
since it has both parallel and serial iteration.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 160 +++++++---------------
 src/include/access/relscan.h              |   7 +-
 src/include/access/tableam.h              |   6 +-
 src/include/nodes/execnodes.h             |   4 +-
 5 files changed, 58 insertions(+), 124 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 84f8ead382..b105ec9437 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2140,10 +2140,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->shared_tbmiterator);
-		else
-			tbmres = tbm_private_iterate(scan->tbmiterator);
+		tbmres = tbm_iterate(&scan->tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index f43b7b2c44..aca3c1d620 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -69,7 +69,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -80,7 +79,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -96,76 +94,49 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMPrivateIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
-
 		if (!pstate)
 		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
-			if (!tbm || !IsA(tbm, TIDBitmap))
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 				elog(ERROR, "unrecognized result from subplan");
-
-			node->tbm = tbm;
-			tbmiterator = tbm_begin_private_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
-#endif							/* USE_PREFETCH */
 		}
-		else
+		else if (BitmapShouldInitializeSharedState(pstate))
 		{
 			/*
 			 * The leader will immediately come out of the function, but
 			 * others will be blocked until leader populates the TBM and wakes
 			 * them up.
 			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
-
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
-
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+				elog(ERROR, "unrecognized result from subplan");
 
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+				pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(node->tbm);
 			}
-#endif							/* USE_PREFETCH */
+#endif
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(pstate);
 		}
 
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+			tbm_begin_iterate(&node->prefetch_iterator, node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -194,8 +165,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->tbmiterator = tbmiterator;
-		scan->shared_tbmiterator = shared_tbmiterator;
+		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
+						  pstate ?
+						  pstate->tbmiterator :
+						  InvalidDsaPointer);
+
 		node->initialized = true;
 
 		goto new_page;
@@ -279,7 +253,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!tbm_exhausted(&node->prefetch_iterator) &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -324,17 +298,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!tbm_exhausted(prefetch_iterator))
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_private_iterate(prefetch_iterator);
+			tbmpre = tbm_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -351,7 +325,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -372,9 +346,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -437,20 +411,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!tbm_exhausted(prefetch_iterator))
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_private_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_private_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -478,9 +451,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!tbm_exhausted(prefetch_iterator))
 		{
 			while (1)
 			{
@@ -503,12 +476,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -577,35 +549,22 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		if (scan->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->shared_tbmiterator);
-			scan->shared_tbmiterator = NULL;
-		}
-
-		if (scan->tbmiterator)
-		{
-			tbm_end_private_iterate(scan->tbmiterator);
-			scan->tbmiterator = NULL;
-		}
+		tbm_end_iterate(&scan->tbmiterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
+	/* End iteration on iterators saved in the node . */
+	tbm_end_iterate(&node->prefetch_iterator);
+
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
@@ -648,17 +607,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		if (scanDesc->shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scanDesc->shared_tbmiterator);
-			scanDesc->shared_tbmiterator = NULL;
-		}
-
-		if (scanDesc->tbmiterator)
-		{
-			tbm_end_private_iterate(scanDesc->tbmiterator);
-			scanDesc->tbmiterator = NULL;
-		}
+		tbm_end_iterate(&scanDesc->tbmiterator);
 
 		/*
 		 * close table scan
@@ -666,15 +615,14 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
+	/* End iteration on iterators saved in the node . */
+	tbm_end_iterate(&node->prefetch_iterator);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -712,11 +660,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 159921ffb5..b4511677b1 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/itup.h"
+#include "nodes/tidbitmap.h"
 #include "port/atomics.h"
 #include "storage/buf.h"
 #include "storage/spin.h"
@@ -24,9 +25,6 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMPrivateIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -40,8 +38,7 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Iterators for Bitmap Table Scans */
-	struct TBMPrivateIterator *tbmiterator;
-	struct TBMSharedIterator *shared_tbmiterator;
+	TBMIterator tbmiterator;
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1ae1487797..4fca5eb9b6 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -954,16 +954,12 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->shared_tbmiterator = NULL;
-	result->tbmiterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 81447fea8c..fd11f7db03 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1803,7 +1803,6 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1818,12 +1817,11 @@ typedef struct BitmapHeapScanState
 	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMPrivateIterator *prefetch_iterator;
+	TBMIterator prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
-- 
2.34.1

v23-0009-Remove-ss_current-prefix-from-ss_currentScanDesc.patchtext/x-patch; charset=US-ASCII; name=v23-0009-Remove-ss_current-prefix-from-ss_currentScanDesc.patchDownload
From 6f721fa4f6f2c25ae145ad417c79b20f5219ea27 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:44:50 -0400
Subject: [PATCH v23 09/19] Remove ss_current prefix from ss_currentScanDesc in
 nodes

A previous commit pushed down the current scan descriptor from the
generic ScanState into the specialized scan states. The naming
convention was left as is to make the diff easier to understand. Rename
it, as the ss_ prefix is no longer correct once this member is in the
other node structs.
---
 src/backend/executor/nodeBitmapHeapscan.c | 10 +++++-----
 src/backend/executor/nodeSamplescan.c     | 14 +++++++-------
 src/backend/executor/nodeSeqscan.c        | 14 +++++++-------
 src/backend/executor/nodeTidrangescan.c   |  8 ++++----
 src/backend/executor/nodeTidscan.c        | 18 +++++++++---------
 src/include/nodes/execnodes.h             | 16 ++++++++--------
 6 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 9a4a050a7d..d5e8557397 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -78,7 +78,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -162,7 +162,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  NULL,
 									  need_tuples);
 
-			node->ss_currentScanDesc = scan;
+			node->scandesc = scan;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -542,7 +542,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	TableScanDesc scan = node->ss_currentScanDesc;
+	TableScanDesc scan = node->scandesc;
 
 	if (scan)
 	{
@@ -552,7 +552,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_iterate(&scan->tbmiterator);
 
 		/* rescan to release any page pin */
-		table_rescan(node->ss_currentScanDesc, NULL);
+		table_rescan(node->scandesc, NULL);
 	}
 
 	/* End iteration on iterators saved in the node . */
@@ -595,7 +595,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * extract information from the node
 	 */
-	scanDesc = node->ss_currentScanDesc;
+	scanDesc = node->scandesc;
 
 	/*
 	 * close down subplans
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index d15bf249d3..581bd3ed3b 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -123,7 +123,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 							 eflags);
 
 	/* we won't set up the HeapScanDesc till later */
-	scanstate->ss_currentScanDesc = NULL;
+	scanstate->scandesc = NULL;
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
@@ -187,8 +187,8 @@ ExecEndSampleScan(SampleScanState *node)
 	/*
 	 * close heap scan
 	 */
-	if (node->ss_currentScanDesc)
-		table_endscan(node->ss_currentScanDesc);
+	if (node->scandesc)
+		table_endscan(node->scandesc);
 }
 
 /* ----------------------------------------------------------------
@@ -289,9 +289,9 @@ tablesample_init(SampleScanState *scanstate)
 	allow_sync = (tsm->NextSampleBlock == NULL);
 
 	/* Now we can create or reset the HeapScanDesc */
-	if (scanstate->ss_currentScanDesc == NULL)
+	if (scanstate->scandesc == NULL)
 	{
-		scanstate->ss_currentScanDesc =
+		scanstate->scandesc =
 			table_beginscan_sampling(scanstate->ss.ss_currentRelation,
 									 scanstate->ss.ps.state->es_snapshot,
 									 0, NULL,
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
 	}
 	else
 	{
-		table_rescan_set_params(scanstate->ss_currentScanDesc, NULL,
+		table_rescan_set_params(scanstate->scandesc, NULL,
 								scanstate->use_bulkread,
 								allow_sync,
 								scanstate->use_pagemode);
@@ -319,7 +319,7 @@ tablesample_init(SampleScanState *scanstate)
 static TupleTableSlot *
 tablesample_getnext(SampleScanState *scanstate)
 {
-	TableScanDesc scan = scanstate->ss_currentScanDesc;
+	TableScanDesc scan = scanstate->scandesc;
 	TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
 
 	ExecClearTuple(slot);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 89f5e8c80d..5aaad64595 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -57,7 +57,7 @@ SeqNext(SeqScanState *node)
 	/*
 	 * get information from the estate and scan state
 	 */
-	scandesc = node->ss_currentScanDesc;
+	scandesc = node->scandesc;
 	estate = node->ss.ps.state;
 	direction = estate->es_direction;
 	slot = node->ss.ss_ScanTupleSlot;
@@ -71,7 +71,7 @@ SeqNext(SeqScanState *node)
 		scandesc = table_beginscan(node->ss.ss_currentRelation,
 								   estate->es_snapshot,
 								   0, NULL);
-		node->ss_currentScanDesc = scandesc;
+		node->scandesc = scandesc;
 	}
 
 	/*
@@ -188,7 +188,7 @@ ExecEndSeqScan(SeqScanState *node)
 	/*
 	 * get information from node
 	 */
-	scanDesc = node->ss_currentScanDesc;
+	scanDesc = node->scandesc;
 
 	/*
 	 * close heap scan
@@ -213,7 +213,7 @@ ExecReScanSeqScan(SeqScanState *node)
 {
 	TableScanDesc scan;
 
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 
 	if (scan != NULL)
 		table_rescan(scan,		/* scan desc */
@@ -264,7 +264,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 								  pscan,
 								  estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss_currentScanDesc =
+	node->scandesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
 
@@ -280,7 +280,7 @@ ExecSeqScanReInitializeDSM(SeqScanState *node,
 {
 	ParallelTableScanDesc pscan;
 
-	pscan = node->ss_currentScanDesc->rs_parallel;
+	pscan = node->scandesc->rs_parallel;
 	table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
 }
 
@@ -297,6 +297,6 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
 	ParallelTableScanDesc pscan;
 
 	pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
-	node->ss_currentScanDesc =
+	node->scandesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index bc523a5d77..3a2ba169e9 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -227,7 +227,7 @@ TidRangeNext(TidRangeScanState *node)
 	/*
 	 * extract necessary information from TID scan node
 	 */
-	scandesc = node->ss_currentScanDesc;
+	scandesc = node->scandesc;
 	estate = node->ss.ps.state;
 	slot = node->ss.ss_ScanTupleSlot;
 	direction = estate->es_direction;
@@ -244,7 +244,7 @@ TidRangeNext(TidRangeScanState *node)
 												estate->es_snapshot,
 												&node->trss_mintid,
 												&node->trss_maxtid);
-			node->ss_currentScanDesc = scandesc;
+			node->scandesc = scandesc;
 		}
 		else
 		{
@@ -326,7 +326,7 @@ ExecReScanTidRangeScan(TidRangeScanState *node)
 void
 ExecEndTidRangeScan(TidRangeScanState *node)
 {
-	TableScanDesc scan = node->ss_currentScanDesc;
+	TableScanDesc scan = node->scandesc;
 
 	if (scan != NULL)
 		table_endscan(scan);
@@ -375,7 +375,7 @@ ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidrangestate->ss.ss_currentRelation = currentRelation;
-	tidrangestate->ss_currentScanDesc = NULL;	/* no table scan here */
+	tidrangestate->scandesc = NULL; /* no table scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index f08bc7daa8..becf027467 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -145,11 +145,11 @@ TidListEval(TidScanState *tidstate)
 	 * the size of the table), so it makes sense to delay that until needed -
 	 * the node might never get executed.
 	 */
-	if (tidstate->ss_currentScanDesc == NULL)
-		tidstate->ss_currentScanDesc =
+	if (tidstate->scandesc == NULL)
+		tidstate->scandesc =
 			table_beginscan_tid(tidstate->ss.ss_currentRelation,
 								tidstate->ss.ps.state->es_snapshot);
-	scan = tidstate->ss_currentScanDesc;
+	scan = tidstate->scandesc;
 
 	/*
 	 * We initialize the array with enough slots for the case that all quals
@@ -336,7 +336,7 @@ TidNext(TidScanState *node)
 	if (node->tss_TidList == NULL)
 		TidListEval(node);
 
-	scan = node->ss_currentScanDesc;
+	scan = node->scandesc;
 	tidList = node->tss_TidList;
 	numTids = node->tss_NumTids;
 
@@ -453,8 +453,8 @@ ExecReScanTidScan(TidScanState *node)
 	node->tss_TidPtr = -1;
 
 	/* not really necessary, but seems good form */
-	if (node->ss_currentScanDesc)
-		table_rescan(node->ss_currentScanDesc, NULL);
+	if (node->scandesc)
+		table_rescan(node->scandesc, NULL);
 
 	ExecScanReScan(&node->ss);
 }
@@ -469,8 +469,8 @@ ExecReScanTidScan(TidScanState *node)
 void
 ExecEndTidScan(TidScanState *node)
 {
-	if (node->ss_currentScanDesc)
-		table_endscan(node->ss_currentScanDesc);
+	if (node->scandesc)
+		table_endscan(node->scandesc);
 }
 
 /* ----------------------------------------------------------------
@@ -518,7 +518,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidstate->ss.ss_currentRelation = currentRelation;
-	tidstate->ss_currentScanDesc = NULL;	/* no heap scan here */
+	tidstate->scandesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index c4907d624d..672dd9f717 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1572,7 +1572,7 @@ typedef struct ScanState
 typedef struct SeqScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
+	struct TableScanDescData *scandesc; /* current scan descriptor */
 	Size		pscan_len;		/* size of parallel heap scan descriptor */
 } SeqScanState;
 
@@ -1583,7 +1583,7 @@ typedef struct SeqScanState
 typedef struct SampleScanState
 {
 	ScanState	ss;
-	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
+	struct TableScanDescData *scandesc; /* current scan descriptor */
 	List	   *args;			/* expr states for TABLESAMPLE params */
 	ExprState  *repeatable;		/* expr state for REPEATABLE expr */
 	/* use struct pointer to avoid including tsmapi.h here */
@@ -1793,7 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
- *		currentScanDesc    current scan descriptor for scan (NULL if none)
+ *		scandesc		   current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1813,7 +1813,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
@@ -1833,7 +1833,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
- *		currentScanDesc	current scan descriptor for scan (NULL if none)
+ *		scandesc	   current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1844,7 +1844,7 @@ typedef struct BitmapHeapScanState
 typedef struct TidScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	List	   *tss_tidexprs;
 	bool		tss_isCurrentOf;
 	int			tss_NumTids;
@@ -1855,7 +1855,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
- *		currentScanDesc		current scan descriptor for scan (NULL if none)
+ *		scandesc			current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
@@ -1865,7 +1865,7 @@ typedef struct TidScanState
 typedef struct TidRangeScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *ss_currentScanDesc;
+	struct TableScanDescData *scandesc;
 	List	   *trss_tidexprs;
 	ItemPointerData trss_mintid;
 	ItemPointerData trss_maxtid;
-- 
2.34.1

v23-0007-BitmapHeapScan-Make-prefetch-sync-error-more-det.patchtext/x-patch; charset=US-ASCII; name=v23-0007-BitmapHeapScan-Make-prefetch-sync-error-more-det.patchDownload
From 6244d196ddb2852b6fba69205abeaa265bdef294 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Jun 2024 12:40:58 -0400
Subject: [PATCH v23 07/19] BitmapHeapScan: Make prefetch sync error more
 detailed

Add the prefetch and current block numbers to the error message emitted
when the prefetch iterator gets out of sync with the main iterator in
serial bitmap table scan.
---
 src/backend/executor/nodeBitmapHeapscan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index aca3c1d620..b7bf877594 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -255,7 +255,7 @@ new_page:
 		if (node->pstate == NULL &&
 			!tbm_exhausted(&node->prefetch_iterator) &&
 			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
+			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
 
 		/* Adjust the prefetch target */
 		BitmapAdjustPrefetchTarget(node);
-- 
2.34.1

v23-0010-Add-scan_in_progress-to-BitmapHeapScanState.patchtext/x-patch; charset=US-ASCII; name=v23-0010-Add-scan_in_progress-to-BitmapHeapScanState.patchDownload
From eecfd22a91a9f973b3e118a7942f8d134fc4bf23 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 13 Jun 2024 13:38:46 -0400
Subject: [PATCH v23 10/19] Add scan_in_progress to BitmapHeapScanState

Instead of checking that the scan descriptor hasn't been allocated yet,
use a dedicated variable, scan_in_progress. This feels cleaner and also
allows us to more easily extract the per scan setup into a separate
function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 5 ++++-
 src/include/nodes/execnodes.h             | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d5e8557397..3d8dce25ed 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -141,7 +141,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
 		 */
-		if (!scan)
+		if (!node->scan_in_progress)
 		{
 			bool		need_tuples = false;
 
@@ -163,8 +163,10 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  need_tuples);
 
 			node->scandesc = scan;
+			node->scan_in_progress = true;
 		}
 
+		Assert(scan);
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
@@ -663,6 +665,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
+	scanstate->scan_in_progress = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 672dd9f717..50c5b1ad8e 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1804,6 +1804,7 @@ typedef struct ParallelBitmapHeapState
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
+ *		scan_in_progress   is this a rescan
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
  *		blockno			   used to validate pf and current block in sync
@@ -1824,6 +1825,7 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
+	bool		scan_in_progress;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
 	BlockNumber blockno;
-- 
2.34.1

v23-0008-Push-current-scan-descriptor-into-specialized-sc.patchtext/x-patch; charset=US-ASCII; name=v23-0008-Push-current-scan-descriptor-into-specialized-sc.patchDownload
From c5ce0fa996cb268cfaac4dbc6a19425c510c790c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:41:49 -0400
Subject: [PATCH v23 08/19] Push current scan descriptor into specialized scan
 states

To allow Bitmap Table Scans to use a forthcoming bitmap table-specific
scan descriptor in table AM-agnostic code, move the current scan
descriptor out of the generic ScanState node.

This adds a bit of duplication, but a few of the scan types don't use
the current scan descriptor anyway. Additionally, for many scan types,
the scan descriptor is initialized later in execution than the other
members of the generic ScanState.
---
 src/backend/executor/nodeBitmapHeapscan.c  | 10 +++++-----
 src/backend/executor/nodeBitmapIndexscan.c |  1 -
 src/backend/executor/nodeIndexonlyscan.c   |  1 -
 src/backend/executor/nodeIndexscan.c       |  1 -
 src/backend/executor/nodeSamplescan.c      | 14 +++++++-------
 src/backend/executor/nodeSeqscan.c         | 14 +++++++-------
 src/backend/executor/nodeTidrangescan.c    |  8 ++++----
 src/backend/executor/nodeTidscan.c         | 18 +++++++++---------
 src/include/nodes/execnodes.h              | 10 ++++++++--
 9 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b7bf877594..9a4a050a7d 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -78,7 +78,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -162,7 +162,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 									  NULL,
 									  need_tuples);
 
-			node->ss.ss_currentScanDesc = scan;
+			node->ss_currentScanDesc = scan;
 		}
 
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
@@ -542,7 +542,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	TableScanDesc scan = node->ss.ss_currentScanDesc;
+	TableScanDesc scan = node->ss_currentScanDesc;
 
 	if (scan)
 	{
@@ -552,7 +552,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		tbm_end_iterate(&scan->tbmiterator);
 
 		/* rescan to release any page pin */
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
+		table_rescan(node->ss_currentScanDesc, NULL);
 	}
 
 	/* End iteration on iterators saved in the node . */
@@ -595,7 +595,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	/*
 	 * extract information from the node
 	 */
-	scanDesc = node->ss.ss_currentScanDesc;
+	scanDesc = node->ss_currentScanDesc;
 
 	/*
 	 * close down subplans
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index 6df8e17ec8..b4af2f17ed 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -225,7 +225,6 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
 	 */
 
 	indexstate->ss.ss_currentRelation = NULL;
-	indexstate->ss.ss_currentScanDesc = NULL;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index b49194c016..194c544c16 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -534,7 +534,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	indexstate->ss.ss_currentRelation = currentRelation;
-	indexstate->ss.ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * Build the scan tuple type using the indextlist generated by the
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 8000feff4c..8260cb0954 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -910,7 +910,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	indexstate->ss.ss_currentRelation = currentRelation;
-	indexstate->ss.ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 714b076e64..d15bf249d3 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -123,7 +123,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 							 eflags);
 
 	/* we won't set up the HeapScanDesc till later */
-	scanstate->ss.ss_currentScanDesc = NULL;
+	scanstate->ss_currentScanDesc = NULL;
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
@@ -187,8 +187,8 @@ ExecEndSampleScan(SampleScanState *node)
 	/*
 	 * close heap scan
 	 */
-	if (node->ss.ss_currentScanDesc)
-		table_endscan(node->ss.ss_currentScanDesc);
+	if (node->ss_currentScanDesc)
+		table_endscan(node->ss_currentScanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -289,9 +289,9 @@ tablesample_init(SampleScanState *scanstate)
 	allow_sync = (tsm->NextSampleBlock == NULL);
 
 	/* Now we can create or reset the HeapScanDesc */
-	if (scanstate->ss.ss_currentScanDesc == NULL)
+	if (scanstate->ss_currentScanDesc == NULL)
 	{
-		scanstate->ss.ss_currentScanDesc =
+		scanstate->ss_currentScanDesc =
 			table_beginscan_sampling(scanstate->ss.ss_currentRelation,
 									 scanstate->ss.ps.state->es_snapshot,
 									 0, NULL,
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
 	}
 	else
 	{
-		table_rescan_set_params(scanstate->ss.ss_currentScanDesc, NULL,
+		table_rescan_set_params(scanstate->ss_currentScanDesc, NULL,
 								scanstate->use_bulkread,
 								allow_sync,
 								scanstate->use_pagemode);
@@ -319,7 +319,7 @@ tablesample_init(SampleScanState *scanstate)
 static TupleTableSlot *
 tablesample_getnext(SampleScanState *scanstate)
 {
-	TableScanDesc scan = scanstate->ss.ss_currentScanDesc;
+	TableScanDesc scan = scanstate->ss_currentScanDesc;
 	TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
 
 	ExecClearTuple(slot);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 7cb12a11c2..89f5e8c80d 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -57,7 +57,7 @@ SeqNext(SeqScanState *node)
 	/*
 	 * get information from the estate and scan state
 	 */
-	scandesc = node->ss.ss_currentScanDesc;
+	scandesc = node->ss_currentScanDesc;
 	estate = node->ss.ps.state;
 	direction = estate->es_direction;
 	slot = node->ss.ss_ScanTupleSlot;
@@ -71,7 +71,7 @@ SeqNext(SeqScanState *node)
 		scandesc = table_beginscan(node->ss.ss_currentRelation,
 								   estate->es_snapshot,
 								   0, NULL);
-		node->ss.ss_currentScanDesc = scandesc;
+		node->ss_currentScanDesc = scandesc;
 	}
 
 	/*
@@ -188,7 +188,7 @@ ExecEndSeqScan(SeqScanState *node)
 	/*
 	 * get information from node
 	 */
-	scanDesc = node->ss.ss_currentScanDesc;
+	scanDesc = node->ss_currentScanDesc;
 
 	/*
 	 * close heap scan
@@ -213,7 +213,7 @@ ExecReScanSeqScan(SeqScanState *node)
 {
 	TableScanDesc scan;
 
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 
 	if (scan != NULL)
 		table_rescan(scan,		/* scan desc */
@@ -264,7 +264,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 								  pscan,
 								  estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss.ss_currentScanDesc =
+	node->ss_currentScanDesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
 
@@ -280,7 +280,7 @@ ExecSeqScanReInitializeDSM(SeqScanState *node,
 {
 	ParallelTableScanDesc pscan;
 
-	pscan = node->ss.ss_currentScanDesc->rs_parallel;
+	pscan = node->ss_currentScanDesc->rs_parallel;
 	table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
 }
 
@@ -297,6 +297,6 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
 	ParallelTableScanDesc pscan;
 
 	pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
-	node->ss.ss_currentScanDesc =
+	node->ss_currentScanDesc =
 		table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
 }
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index 9aa7683d7e..bc523a5d77 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -227,7 +227,7 @@ TidRangeNext(TidRangeScanState *node)
 	/*
 	 * extract necessary information from TID scan node
 	 */
-	scandesc = node->ss.ss_currentScanDesc;
+	scandesc = node->ss_currentScanDesc;
 	estate = node->ss.ps.state;
 	slot = node->ss.ss_ScanTupleSlot;
 	direction = estate->es_direction;
@@ -244,7 +244,7 @@ TidRangeNext(TidRangeScanState *node)
 												estate->es_snapshot,
 												&node->trss_mintid,
 												&node->trss_maxtid);
-			node->ss.ss_currentScanDesc = scandesc;
+			node->ss_currentScanDesc = scandesc;
 		}
 		else
 		{
@@ -326,7 +326,7 @@ ExecReScanTidRangeScan(TidRangeScanState *node)
 void
 ExecEndTidRangeScan(TidRangeScanState *node)
 {
-	TableScanDesc scan = node->ss.ss_currentScanDesc;
+	TableScanDesc scan = node->ss_currentScanDesc;
 
 	if (scan != NULL)
 		table_endscan(scan);
@@ -375,7 +375,7 @@ ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidrangestate->ss.ss_currentRelation = currentRelation;
-	tidrangestate->ss.ss_currentScanDesc = NULL;	/* no table scan here */
+	tidrangestate->ss_currentScanDesc = NULL;	/* no table scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 864a9013b6..f08bc7daa8 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -145,11 +145,11 @@ TidListEval(TidScanState *tidstate)
 	 * the size of the table), so it makes sense to delay that until needed -
 	 * the node might never get executed.
 	 */
-	if (tidstate->ss.ss_currentScanDesc == NULL)
-		tidstate->ss.ss_currentScanDesc =
+	if (tidstate->ss_currentScanDesc == NULL)
+		tidstate->ss_currentScanDesc =
 			table_beginscan_tid(tidstate->ss.ss_currentRelation,
 								tidstate->ss.ps.state->es_snapshot);
-	scan = tidstate->ss.ss_currentScanDesc;
+	scan = tidstate->ss_currentScanDesc;
 
 	/*
 	 * We initialize the array with enough slots for the case that all quals
@@ -336,7 +336,7 @@ TidNext(TidScanState *node)
 	if (node->tss_TidList == NULL)
 		TidListEval(node);
 
-	scan = node->ss.ss_currentScanDesc;
+	scan = node->ss_currentScanDesc;
 	tidList = node->tss_TidList;
 	numTids = node->tss_NumTids;
 
@@ -453,8 +453,8 @@ ExecReScanTidScan(TidScanState *node)
 	node->tss_TidPtr = -1;
 
 	/* not really necessary, but seems good form */
-	if (node->ss.ss_currentScanDesc)
-		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	if (node->ss_currentScanDesc)
+		table_rescan(node->ss_currentScanDesc, NULL);
 
 	ExecScanReScan(&node->ss);
 }
@@ -469,8 +469,8 @@ ExecReScanTidScan(TidScanState *node)
 void
 ExecEndTidScan(TidScanState *node)
 {
-	if (node->ss.ss_currentScanDesc)
-		table_endscan(node->ss.ss_currentScanDesc);
+	if (node->ss_currentScanDesc)
+		table_endscan(node->ss_currentScanDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -518,7 +518,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
 
 	tidstate->ss.ss_currentRelation = currentRelation;
-	tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
+	tidstate->ss_currentScanDesc = NULL;	/* no heap scan here */
 
 	/*
 	 * get the scan type from the relation descriptor.
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fd11f7db03..c4907d624d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1555,7 +1555,6 @@ typedef struct BitmapOrState
  *		retrieved from the subplan.
  *
  *		currentRelation    relation being scanned (NULL if none)
- *		currentScanDesc    current scan descriptor for scan (NULL if none)
  *		ScanTupleSlot	   pointer to slot in tuple table holding scan tuple
  * ----------------
  */
@@ -1563,7 +1562,6 @@ typedef struct ScanState
 {
 	PlanState	ps;				/* its first field is NodeTag */
 	Relation	ss_currentRelation;
-	struct TableScanDescData *ss_currentScanDesc;
 	TupleTableSlot *ss_ScanTupleSlot;
 } ScanState;
 
@@ -1574,6 +1572,7 @@ typedef struct ScanState
 typedef struct SeqScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
 	Size		pscan_len;		/* size of parallel heap scan descriptor */
 } SeqScanState;
 
@@ -1584,6 +1583,7 @@ typedef struct SeqScanState
 typedef struct SampleScanState
 {
 	ScanState	ss;
+	struct TableScanDescData *ss_currentScanDesc;	/* current scan descriptor */
 	List	   *args;			/* expr states for TABLESAMPLE params */
 	ExprState  *repeatable;		/* expr state for REPEATABLE expr */
 	/* use struct pointer to avoid including tsmapi.h here */
@@ -1793,6 +1793,7 @@ typedef struct ParallelBitmapHeapState
 /* ----------------
  *	 BitmapHeapScanState information
  *
+ *		currentScanDesc    current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
@@ -1812,6 +1813,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
@@ -1831,6 +1833,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *	 TidScanState information
  *
+ *		currentScanDesc	current scan descriptor for scan (NULL if none)
  *		tidexprs	   list of TidExpr structs (see nodeTidscan.c)
  *		isCurrentOf    scan has a CurrentOfExpr qual
  *		NumTids		   number of tids in this scan
@@ -1841,6 +1844,7 @@ typedef struct BitmapHeapScanState
 typedef struct TidScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	List	   *tss_tidexprs;
 	bool		tss_isCurrentOf;
 	int			tss_NumTids;
@@ -1851,6 +1855,7 @@ typedef struct TidScanState
 /* ----------------
  *	 TidRangeScanState information
  *
+ *		currentScanDesc		current scan descriptor for scan (NULL if none)
  *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
  *		trss_mintid			the lowest TID in the scan range
  *		trss_maxtid			the highest TID in the scan range
@@ -1860,6 +1865,7 @@ typedef struct TidScanState
 typedef struct TidRangeScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	struct TableScanDescData *ss_currentScanDesc;
 	List	   *trss_tidexprs;
 	ItemPointerData trss_mintid;
 	ItemPointerData trss_maxtid;
-- 
2.34.1

v23-0011-Make-new-bitmap-table-scan-and-bitmap-heap-scan-.patchtext/x-patch; charset=US-ASCII; name=v23-0011-Make-new-bitmap-table-scan-and-bitmap-heap-scan-.patchDownload
From 35381b224a2a4b4f2d31ef2c2a69947d5706350e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 08:51:05 -0400
Subject: [PATCH v23 11/19] Make new bitmap table scan and bitmap heap scan
 descriptors

The number of fields from the TableScanDescData required for bitmap
table scans is few. Create a new BitmapTableScanDesc with only those
members needed for bitmap table scans and remove the bitmap table
scan-only fields from the generic TableScanDescData.

Also add a BitmapHeapScanDesc structure for the heap AM implementation
of bitmap table scans. Add table AM callbacks for starting, restarting,
and ending these scans.

While reducing the size of the scan descriptor (and the amount of code
executed in the table_begin/end/rescan() functions) was a benefit,
creating a new BitmapTableScanDesc and associated table AM functions to
begin/end/rescan was actually motivated by work to remove all
heap-specific code from the generic bitmap table scan code path. Pushing
this code down into the heap AM layer would have required adding quite a
few bitmap-specific parameters to heap_begin/end/rescan()
---
 src/backend/access/heap/heapam.c          | 110 ++++++++++++++++++----
 src/backend/access/heap/heapam_handler.c  |  12 ++-
 src/backend/executor/nodeBitmapHeapscan.c |  34 +++----
 src/include/access/heapam.h               |  39 ++++++--
 src/include/access/relscan.h              |  20 +++-
 src/include/access/tableam.h              |  73 ++++++++++----
 src/include/nodes/execnodes.h             |   2 +-
 src/tools/pgindent/typedefs.list          |   2 +
 8 files changed, 217 insertions(+), 75 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 82bb9cb33b..0d8239d2f1 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1061,8 +1061,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1178,19 +1176,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
-	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
-	 */
-	scan->rs_empty_tuples_pending = 0;
-
 	/*
 	 * The read stream is reset on rescan. This must be done before
 	 * initscan(), as some state referred to by read_stream_reset() is reset
@@ -1218,9 +1203,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
@@ -1247,6 +1229,98 @@ heap_endscan(TableScanDesc sscan)
 	pfree(scan);
 }
 
+BitmapTableScanDesc *
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+{
+	BitmapHeapScanDesc *scan;
+
+	/*
+	 * increment relation ref count while scanning relation
+	 *
+	 * This is just to make really sure the relcache entry won't go away while
+	 * the scan has a pointer to it.  Caller should be holding the rel open
+	 * anyway, so this is redundant in all normal scenarios...
+	 */
+	RelationIncrementReferenceCount(relation);
+	scan = (BitmapHeapScanDesc *) palloc(sizeof(BitmapHeapScanDesc));
+
+	scan->rs_base.rs_rd = relation;
+	scan->rs_base.rs_snapshot = snapshot;
+	scan->rs_base.rs_flags = flags;
+
+	Assert(snapshot && IsMVCCSnapshot(snapshot));
+
+	/* we only need to set this up once */
+	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
+
+	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+
+	scan->rs_ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+	scan->rs_cbuf = InvalidBuffer;
+	scan->rs_cblock = InvalidBlockNumber;
+
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
+
+	scan->rs_vmbuffer = InvalidBuffer;
+	scan->rs_empty_tuples_pending = 0;
+
+	return (BitmapTableScanDesc *) scan;
+}
+
+void
+heap_rescan_bm(BitmapTableScanDesc *sscan)
+{
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+
+	if (BufferIsValid(scan->rs_cbuf))
+	{
+		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
+
+	if (BufferIsValid(scan->rs_vmbuffer))
+	{
+		ReleaseBuffer(scan->rs_vmbuffer);
+		scan->rs_vmbuffer = InvalidBuffer;
+	}
+
+	scan->rs_cblock = InvalidBlockNumber;
+
+	/*
+	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
+	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
+	 * on rescan.
+	 */
+	scan->rs_empty_tuples_pending = 0;
+
+	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+
+	scan->rs_ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+}
+
+void
+heap_endscan_bm(BitmapTableScanDesc *sscan)
+{
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+
+	if (BufferIsValid(scan->rs_cbuf))
+		ReleaseBuffer(scan->rs_cbuf);
+
+	if (BufferIsValid(scan->rs_vmbuffer))
+		ReleaseBuffer(scan->rs_vmbuffer);
+
+	/*
+	 * decrement relation reference count and free scan descriptor storage
+	 */
+	RelationDecrementReferenceCount(scan->rs_base.rs_rd);
+
+	pfree(scan);
+}
+
+
 HeapTuple
 heap_getnext(TableScanDesc sscan, ScanDirection direction)
 {
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b105ec9437..3457a3e516 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,11 +2119,11 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 							  BlockNumber *blockno, bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2283,10 +2283,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
@@ -2629,6 +2629,10 @@ static const TableAmRoutine heapam_methods = {
 	.scan_rescan = heap_rescan,
 	.scan_getnextslot = heap_getnextslot,
 
+	.scan_begin_bm = heap_beginscan_bm,
+	.scan_rescan_bm = heap_rescan_bm,
+	.scan_end_bm = heap_endscan_bm,
+
 	.scan_set_tidrange = heap_set_tidrange,
 	.scan_getnextslot_tidrange = heap_getnextslot_tidrange,
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3d8dce25ed..a7cbb980cb 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -54,7 +54,7 @@ static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *ps
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
+								  BitmapTableScanDesc *scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -68,7 +68,7 @@ static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
-	TableScanDesc scan;
+	BitmapTableScanDesc *scan;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -158,15 +158,18 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
 									  need_tuples);
-
 			node->scandesc = scan;
 			node->scan_in_progress = true;
 		}
+		else
+		{
+			Assert(scan);
+			/* rescan to release any page pin */
+			tbm_end_iterate(&scan->tbmiterator);
+			table_rescan_bm(scan);
+		}
 
-		Assert(scan);
 		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
@@ -406,7 +409,7 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
 static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
@@ -544,19 +547,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	TableScanDesc scan = node->scandesc;
-
-	if (scan)
-	{
-		/*
-		 * End iteration on iterators saved in scan descriptor.
-		 */
-		tbm_end_iterate(&scan->tbmiterator);
-
-		/* rescan to release any page pin */
-		table_rescan(node->scandesc, NULL);
-	}
-
 	/* End iteration on iterators saved in the node . */
 	tbm_end_iterate(&node->prefetch_iterator);
 
@@ -592,7 +582,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 void
 ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 {
-	TableScanDesc scanDesc;
+	BitmapTableScanDesc *scanDesc;
 
 	/*
 	 * extract information from the node
@@ -614,7 +604,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * close table scan
 		 */
-		table_endscan(scanDesc);
+		table_endscan_bm(scanDesc);
 	}
 
 	/* End iteration on iterators saved in the node . */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 9e9aec88a6..3cac199dd3 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -91,22 +91,39 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDesc
+{
+	BitmapTableScanDesc rs_base;
+
+	BlockNumber rs_nblocks;		/* total number of blocks in rel */
+
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+
+	Buffer		rs_cbuf;		/* current buffer in scan, if any */
+	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
+	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
+
+	BlockNumber rs_cblock;		/* current block # in scan, if any */
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+} BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
@@ -296,6 +313,12 @@ extern void heap_prepare_pagescan(TableScanDesc sscan);
 extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 						bool allow_strat, bool allow_sync, bool allow_pagemode);
 extern void heap_endscan(TableScanDesc sscan);
+
+extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
+											  Snapshot snapshot, uint32 flags);
+extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
+void		heap_endscan_bm(BitmapTableScanDesc *sscan);
+
 extern HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction);
 extern bool heap_getnextslot(TableScanDesc sscan,
 							 ScanDirection direction, struct TupleTableSlot *slot);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index b4511677b1..036ef29e7d 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -37,9 +37,6 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
-	/* Iterators for Bitmap Table Scans */
-	TBMIterator tbmiterator;
-
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
 	ItemPointerData rs_mintid;
 	ItemPointerData rs_maxtid;
@@ -55,6 +52,23 @@ typedef struct TableScanDescData
 } TableScanDescData;
 typedef struct TableScanDescData *TableScanDesc;
 
+typedef struct BitmapTableScanDesc
+{
+	Relation	rs_rd;			/* heap relation descriptor */
+	struct SnapshotData *rs_snapshot;	/* snapshot to see */
+
+	/*
+	 * Members common to Parallel and Serial BitmapTableScans
+	 */
+	TBMIterator tbmiterator;
+
+	/*
+	 * Information about type and behaviour of the scan, a bitmask of members
+	 * of the ScanOptions enum (see tableam.h).
+	 */
+	uint32		rs_flags;
+} BitmapTableScanDesc;
+
 /*
  * Shared state for parallel table scan.
  *
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 4fca5eb9b6..57bc06f77e 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -345,6 +345,24 @@ typedef struct TableAmRoutine
 								bool set_params, bool allow_strat,
 								bool allow_sync, bool allow_pagemode);
 
+	/*
+	 * Functions to begin, restart, and end a scan of the underlying table of
+	 * a bitmap table scan.
+	 *
+	 * `rel`, `flags`, and `snapshot` serve the same purposes as in the
+	 * standard relation scan_[begin|rescan|end] functions documented above.
+	 */
+	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
+										   Snapshot snapshot,
+										   uint32 flags);
+
+	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
+
+	/*
+	 * Release resources and deallocate scan.
+	 */
+	void		(*scan_end_bm) (BitmapTableScanDesc *scan);
+
 	/*
 	 * Return next tuple from `scan`, store in slot.
 	 */
@@ -815,7 +833,7 @@ typedef struct TableAmRoutine
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
 										   BlockNumber *blockno, bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
@@ -826,7 +844,7 @@ typedef struct TableAmRoutine
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (BitmapTableScanDesc *scan,
 										   TupleTableSlot *slot);
 
 	/*
@@ -851,8 +869,8 @@ typedef struct TableAmRoutine
 	 * is obviously OK.
 	 *
 	 * Currently it is required to implement this interface, as there's no
-	 * alternative way (contrary e.g. to bitmap scans) to implement sample
-	 * scans. If infeasible to implement, the AM may raise an error.
+	 * alternative way to implement sample scans. If infeasible to implement,
+	 * the AM may raise an error.
 	 */
 	bool		(*scan_sample_next_block) (TableScanDesc scan,
 										   struct SampleScanState *scanstate);
@@ -945,29 +963,46 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 }
 
 /*
- * table_beginscan_bm is an alternative entry point for setting up a
- * TableScanDesc for a bitmap heap scan.  Although that scan technology is
- * really quite unlike a standard seqscan, there is just enough commonality to
- * make it worth using the same data structure.
+ * table_beginscan_bm is an entry point for setting up a BitmapTableScanDesc
+ * for a bitmap table scan.
  */
-static inline TableScanDesc
+static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, bool need_tuple)
+				   bool need_tuple)
 {
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 }
 
+/*
+ * Restart a bitmap table scan.
+ */
+static inline void
+table_rescan_bm(BitmapTableScanDesc *scan)
+{
+	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+}
+
+/*
+ * End a bitmap table scan.
+ */
+static inline void
+table_endscan_bm(BitmapTableScanDesc *scan)
+{
+	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+}
+
+
 /*
  * table_beginscan_sampling is an alternative entry point for setting up a
- * TableScanDesc for a TABLESAMPLE scan.  As with bitmap scans, it's worth
- * using the same data structure although the behavior is rather different.
- * In addition to the options offered by table_beginscan_strat, this call
- * also allows control of whether page-mode visibility checking is used.
+ * TableScanDesc for a TABLESAMPLE scan.  It's worth using the same data
+ * structure although the behavior is rather different. In addition to the
+ * options offered by table_beginscan_strat, this call also allows control of
+ * whether page-mode visibility checking is used.
  */
 static inline TableScanDesc
 table_beginscan_sampling(Relation rel, Snapshot snapshot,
@@ -989,7 +1024,7 @@ table_beginscan_sampling(Relation rel, Snapshot snapshot,
 
 /*
  * table_beginscan_tid is an alternative entry point for setting up a
- * TableScanDesc for a Tid scan. As with bitmap scans, it's worth using
+ * TableScanDesc for a Tid scan. As with sample scans, it's worth using
  * the same data structure although the behavior is rather different.
  */
 static inline TableScanDesc
@@ -1002,7 +1037,7 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 
 /*
  * table_beginscan_analyze is an alternative entry point for setting up a
- * TableScanDesc for an ANALYZE scan.  As with bitmap scans, it's worth using
+ * TableScanDesc for an ANALYZE scan.  As with sample scans, it's worth using
  * the same data structure although the behavior is rather different.
  */
 static inline TableScanDesc
@@ -1968,7 +2003,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 							 BlockNumber *blockno, bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
@@ -1995,7 +2030,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  * returned false.
  */
 static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
+table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 							 TupleTableSlot *slot)
 {
 	/*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 50c5b1ad8e..7471ca128e 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1814,7 +1814,7 @@ typedef struct ParallelBitmapHeapState
 typedef struct BitmapHeapScanState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	struct TableScanDescData *scandesc;
+	struct BitmapTableScanDesc *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 757a9a3a41..90f7fd882d 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -261,12 +261,14 @@ BitmapAndPath
 BitmapAndState
 BitmapHeapPath
 BitmapHeapScan
+BitmapHeapScanDesc
 BitmapHeapScanState
 BitmapIndexScan
 BitmapIndexScanState
 BitmapOr
 BitmapOrPath
 BitmapOrState
+BitmapTableScanDesc
 Bitmapset
 Block
 BlockId
-- 
2.34.1

v23-0012-Update-variable-names-in-bitmap-scan-descriptors.patchtext/x-patch; charset=US-ASCII; name=v23-0012-Update-variable-names-in-bitmap-scan-descriptors.patchDownload
From 69590853430a49e866777b256205302298fcc73c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 09:59:23 -0400
Subject: [PATCH v23 12/19] Update variable names in bitmap scan descriptors

The previous commit which added BitmapTableScanDesc and
BitmapHeapScanDesc used the existing member names from TableScanDescData
and HeapScanDescData for diff clarity. This commit renames the members
-- in many cases by removing the rs_ prefix which is not relevant or
needed here.
---
 src/backend/access/heap/heapam.c          | 64 ++++++++++-----------
 src/backend/access/heap/heapam_handler.c  | 70 +++++++++++------------
 src/backend/executor/nodeBitmapHeapscan.c | 14 ++---
 src/include/access/heapam.h               | 22 +++----
 src/include/access/relscan.h              |  8 +--
 src/include/access/tableam.h              | 14 ++---
 6 files changed, 96 insertions(+), 96 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 0d8239d2f1..88da737d14 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1244,27 +1244,27 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	RelationIncrementReferenceCount(relation);
 	scan = (BitmapHeapScanDesc *) palloc(sizeof(BitmapHeapScanDesc));
 
-	scan->rs_base.rs_rd = relation;
-	scan->rs_base.rs_snapshot = snapshot;
-	scan->rs_base.rs_flags = flags;
+	scan->base.rel = relation;
+	scan->base.snapshot = snapshot;
+	scan->base.flags = flags;
 
 	Assert(snapshot && IsMVCCSnapshot(snapshot));
 
 	/* we only need to set this up once */
-	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
+	scan->ctup.t_tableOid = RelationGetRelid(relation);
 
-	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+	scan->nblocks = RelationGetNumberOfBlocks(scan->base.rel);
 
-	scan->rs_ctup.t_data = NULL;
-	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
-	scan->rs_cbuf = InvalidBuffer;
-	scan->rs_cblock = InvalidBlockNumber;
+	scan->ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->ctup.t_self);
+	scan->cbuf = InvalidBuffer;
+	scan->cblock = InvalidBlockNumber;
 
-	scan->rs_cindex = 0;
-	scan->rs_ntuples = 0;
+	scan->vis_idx = 0;
+	scan->vis_ntuples = 0;
 
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
+	scan->vmbuffer = InvalidBuffer;
+	scan->empty_tuples_pending = 0;
 
 	return (BitmapTableScanDesc *) scan;
 }
@@ -1274,31 +1274,31 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
-	if (BufferIsValid(scan->rs_cbuf))
+	if (BufferIsValid(scan->cbuf))
 	{
-		ReleaseBuffer(scan->rs_cbuf);
-		scan->rs_cbuf = InvalidBuffer;
+		ReleaseBuffer(scan->cbuf);
+		scan->cbuf = InvalidBuffer;
 	}
 
-	if (BufferIsValid(scan->rs_vmbuffer))
+	if (BufferIsValid(scan->vmbuffer))
 	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
+		ReleaseBuffer(scan->vmbuffer);
+		scan->vmbuffer = InvalidBuffer;
 	}
 
-	scan->rs_cblock = InvalidBlockNumber;
+	scan->cblock = InvalidBlockNumber;
 
 	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
+	 * Reset empty_tuples_pending, a field only used by bitmap heap scan, to
+	 * avoid incorrectly emitting NULL-filled tuples from a previous scan on
+	 * rescan.
 	 */
-	scan->rs_empty_tuples_pending = 0;
+	scan->empty_tuples_pending = 0;
 
-	scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_base.rs_rd);
+	scan->nblocks = RelationGetNumberOfBlocks(scan->base.rel);
 
-	scan->rs_ctup.t_data = NULL;
-	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
+	scan->ctup.t_data = NULL;
+	ItemPointerSetInvalid(&scan->ctup.t_self);
 }
 
 void
@@ -1306,16 +1306,16 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
-	if (BufferIsValid(scan->rs_cbuf))
-		ReleaseBuffer(scan->rs_cbuf);
+	if (BufferIsValid(scan->cbuf))
+		ReleaseBuffer(scan->cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
+	if (BufferIsValid(scan->vmbuffer))
+		ReleaseBuffer(scan->vmbuffer);
 
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
-	RelationDecrementReferenceCount(scan->rs_base.rs_rd);
+	RelationDecrementReferenceCount(scan->base.rel);
 
 	pfree(scan);
 }
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3457a3e516..8b8e4e9c78 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2130,8 +2130,8 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	int			ntup;
 	TBMIterateResult *tbmres;
 
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
+	hscan->vis_idx = 0;
+	hscan->vis_ntuples = 0;
 
 	*blockno = InvalidBlockNumber;
 	*recheck = true;
@@ -2140,7 +2140,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->tbmiterator);
+		tbmres = tbm_iterate(&scan->iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2153,7 +2153,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->nblocks);
 
 	/* Got a valid block */
 	*blockno = tbmres->blockno;
@@ -2164,15 +2164,15 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+	if (!(scan->flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(scan->rel, tbmres->blockno, &hscan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(hscan->empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		hscan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2182,19 +2182,19 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
+	hscan->cbuf = ReleaseAndReadBuffer(hscan->cbuf,
+									   scan->rel,
+									   block);
+	hscan->cblock = block;
+	buffer = hscan->cbuf;
+	snapshot = scan->snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
+	heap_page_prune_opt(scan->rel, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2222,9 +2222,9 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, scan->rel, buffer, snapshot,
 									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+				hscan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
 	}
 	else
@@ -2248,16 +2248,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
+			loctup.t_tableOid = scan->rel->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+				hscan->vis_tuples[ntup++] = offnum;
+				PredicateLockTID(scan->rel, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+			HeapCheckForSerializableConflictOut(valid, scan->rel, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2265,7 +2265,7 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
+	hscan->vis_ntuples = ntup;
 
 	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
@@ -2291,43 +2291,43 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (hscan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		hscan->empty_tuples_pending--;
 		return true;
 	}
 
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
+	if (hscan->vis_idx < 0 || hscan->vis_idx >= hscan->vis_ntuples)
 		return false;
 
-	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
-	page = BufferGetPage(hscan->rs_cbuf);
+	targoffset = hscan->vis_tuples[hscan->vis_idx];
+	page = BufferGetPage(hscan->cbuf);
 	lp = PageGetItemId(page, targoffset);
 	Assert(ItemIdIsNormal(lp));
 
-	hscan->rs_ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-	hscan->rs_ctup.t_len = ItemIdGetLength(lp);
-	hscan->rs_ctup.t_tableOid = scan->rs_rd->rd_id;
-	ItemPointerSet(&hscan->rs_ctup.t_self, hscan->rs_cblock, targoffset);
+	hscan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+	hscan->ctup.t_len = ItemIdGetLength(lp);
+	hscan->ctup.t_tableOid = scan->rel->rd_id;
+	ItemPointerSet(&hscan->ctup.t_self, hscan->cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rs_rd);
+	pgstat_count_heap_fetch(scan->rel);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
 	 * acquires a pin on the buffer.
 	 */
-	ExecStoreBufferHeapTuple(&hscan->rs_ctup,
+	ExecStoreBufferHeapTuple(&hscan->ctup,
 							 slot,
-							 hscan->rs_cbuf);
+							 hscan->cbuf);
 
-	hscan->rs_cindex++;
+	hscan->vis_idx++;
 
 	return true;
 }
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a7cbb980cb..7f88452a62 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -166,11 +166,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			Assert(scan);
 			/* rescan to release any page pin */
-			tbm_end_iterate(&scan->tbmiterator);
+			tbm_end_iterate(&scan->iterator);
 			table_rescan_bm(scan);
 		}
 
-		tbm_begin_iterate(&scan->tbmiterator, node->tbm, dsa,
+		tbm_begin_iterate(&scan->iterator, node->tbm, dsa,
 						  pstate ?
 						  pstate->tbmiterator :
 						  InvalidDsaPointer);
@@ -440,14 +440,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -492,14 +492,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				node->pfblockno = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
 											 tbmpre->blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -599,7 +599,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		tbm_end_iterate(&scanDesc->tbmiterator);
+		tbm_end_iterate(&scanDesc->iterator);
 
 		/*
 		 * close table scan
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3cac199dd3..ce69f5a023 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -100,19 +100,19 @@ typedef struct HeapScanDescData *HeapScanDesc;
 
 typedef struct BitmapHeapScanDesc
 {
-	BitmapTableScanDesc rs_base;
+	BitmapTableScanDesc base;
 
-	BlockNumber rs_nblocks;		/* total number of blocks in rel */
+	BlockNumber nblocks;		/* total number of blocks in rel */
 
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+	int			vis_idx;		/* current tuple's index in vis_tuples */
+	int			vis_ntuples;	/* number of visible tuples on page */
+	OffsetNumber vis_tuples[MaxHeapTuplesPerPage];	/* their offsets */
 
-	Buffer		rs_cbuf;		/* current buffer in scan, if any */
-	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
-	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
+	Buffer		cbuf;			/* current buffer in scan, if any */
+	/* NB: if cbuf is not InvalidBuffer, we hold a pin on that buffer */
+	HeapTupleData ctup;			/* current tuple in scan, if any */
 
-	BlockNumber rs_cblock;		/* current block # in scan, if any */
+	BlockNumber cblock;			/* current block # in scan, if any */
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -121,8 +121,8 @@ typedef struct BitmapHeapScanDesc
 	 * block reported by the bitmap to determine how many NULL-filled tuples
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
-	Buffer		rs_vmbuffer;
-	int			rs_empty_tuples_pending;
+	Buffer		vmbuffer;
+	int			empty_tuples_pending;
 } BitmapHeapScanDesc;
 
 /*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 036ef29e7d..086fce35a8 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -54,19 +54,19 @@ typedef struct TableScanDescData *TableScanDesc;
 
 typedef struct BitmapTableScanDesc
 {
-	Relation	rs_rd;			/* heap relation descriptor */
-	struct SnapshotData *rs_snapshot;	/* snapshot to see */
+	Relation	rel;			/* heap relation descriptor */
+	struct SnapshotData *snapshot;	/* snapshot to see */
 
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
-	TBMIterator tbmiterator;
+	TBMIterator iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
 	 * of the ScanOptions enum (see tableam.h).
 	 */
-	uint32		rs_flags;
+	uint32		flags;
 } BitmapTableScanDesc;
 
 /*
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 57bc06f77e..f7f099b644 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -984,7 +984,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
 static inline void
 table_rescan_bm(BitmapTableScanDesc *scan)
 {
-	scan->rs_rd->rd_tableam->scan_rescan_bm(scan);
+	scan->rel->rd_tableam->scan_rescan_bm(scan);
 }
 
 /*
@@ -993,7 +993,7 @@ table_rescan_bm(BitmapTableScanDesc *scan)
 static inline void
 table_endscan_bm(BitmapTableScanDesc *scan)
 {
-	scan->rs_rd->rd_tableam->scan_end_bm(scan);
+	scan->rel->rd_tableam->scan_end_bm(scan);
 }
 
 
@@ -2016,9 +2016,9 @@ table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
-														   lossy_pages, exact_pages);
+	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
+														 blockno, recheck,
+														 lossy_pages, exact_pages);
 }
 
 /*
@@ -2041,8 +2041,8 @@ table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+	return scan->rel->rd_tableam->scan_bitmap_next_tuple(scan,
+														 slot);
 }
 
 /*
-- 
2.34.1

v23-0015-BitmapHeapScan-move-per-scan-setup-into-a-helper.patchtext/x-patch; charset=US-ASCII; name=v23-0015-BitmapHeapScan-move-per-scan-setup-into-a-helper.patchDownload
From 00a62d1264b52a2c691e94edd1fc3fbdcde64e1e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:21:08 -0400
Subject: [PATCH v23 15/19] BitmapHeapScan: move per scan setup into a helper

Add BitmapTableScanSetup() which contains all of the code that must be
done on every scan of the table in a bitmap table scan.
This includes scanning the index, building the bitmap, and setting up
the scan descriptors.

Much of BitmapHeapNext() code was this setup, so it made sense to put it
in a helper function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 214 +++++++++++-----------
 1 file changed, 110 insertions(+), 104 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 45095d800b..fdccc84205 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -53,138 +53,144 @@ static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
-
-/* ----------------------------------------------------------------
- *		BitmapHeapNext
- *
- *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
- * ----------------------------------------------------------------
+/*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
  */
-static TupleTableSlot *
-BitmapHeapNext(BitmapHeapScanState *node)
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	BitmapTableScanDesc *scan;
-	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
+	int			prefetch_maximum = 0;
+	Relation	rel = node->ss.ss_currentRelation;
 
 	/*
-	 * extract necessary information from index scan node
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
 	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->scandesc;
+	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
 
 	/*
-	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
+	 * Scan the index, build the bitmap, and set up shared state for parallel.
 	 */
-	if (!node->initialized)
+	if (!pstate)
+	{
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+	}
+	else if (BitmapShouldInitializeSharedState(pstate))
 	{
-		int			prefetch_maximum = 0;
-		Relation	rel = node->ss.ss_currentRelation;
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
 
 		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
+		 * We use *two* iterators, one for the pages we are actually scanning
+		 * and another that runs ahead of the first for prefetching.
+		 * scan->prefetch_pages tracks exactly how many pages ahead the
+		 * prefetch iterator is.  Also, scan->prefetch_target tracks the
+		 * desired prefetch distance, which starts small and increases up to
+		 * the prefetch_maximum. This is to avoid doing a lot of prefetching
+		 * in a scan that stops after a few tuples because of a LIMIT.
 		 */
-		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
 
-		if (!pstate)
+		/*
+		 * Prepare to iterate over the TBM. This will return the dsa_pointer
+		 * of the iterator state which will be used by multiple processes to
+		 * iterate jointly.
+		 */
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+#ifdef USE_PREFETCH
+		if (prefetch_maximum > 0)
 		{
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
+			pstate->prefetch_iterator =
+				tbm_prepare_shared_iterate(node->tbm);
 		}
-		else if (BitmapShouldInitializeSharedState(pstate))
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-			if (!node->tbm || !IsA(node->tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-
-			/*
-			 * Prepare to iterate over the TBM. This will return the
-			 * dsa_pointer of the iterator state which will be used by
-			 * multiple processes to iterate jointly.
-			 */
-			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
-#ifdef USE_PREFETCH
-			if (prefetch_maximum > 0)
-			{
-				pstate->prefetch_iterator =
-					tbm_prepare_shared_iterate(node->tbm);
-			}
 #endif
-			/* We have initialized the shared state so wake up others. */
-			BitmapDoneInitializingSharedState(pstate);
-		}
+		/* We have initialized the shared state so wake up others. */
+		BitmapDoneInitializingSharedState(pstate);
+	}
+
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!node->scan_in_progress)
+	{
+		bool		need_tuples = false;
 
 		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
 		 */
-		if (!node->scan_in_progress)
-		{
-			bool		need_tuples = false;
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
+		node->scandesc = table_beginscan_bm(node->ss.ss_currentRelation,
+											node->ss.ps.state->es_snapshot,
+											pstate,
+											need_tuples,
+											prefetch_maximum);
+		node->scan_in_progress = true;
+	}
+	else
+	{
+		Assert(node->scandesc);
+		tbm_end_iterate(&node->scandesc->iterator);
+		tbm_end_iterate(&node->scandesc->prefetch_iterator);
+		/* rescan to release any page pin */
+		table_rescan_bm(node->scandesc);
+	}
 
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  pstate,
-									  need_tuples,
-									  prefetch_maximum);
-			node->scandesc = scan;
-			node->scan_in_progress = true;
-		}
-		else
-		{
-			Assert(scan);
-			/* rescan to release any page pin */
-			tbm_end_iterate(&scan->prefetch_iterator);
-			tbm_end_iterate(&scan->iterator);
-			table_rescan_bm(scan);
-		}
+	tbm_begin_iterate(&node->scandesc->iterator, node->tbm, dsa,
+					  pstate ?
+					  pstate->tbmiterator :
+					  InvalidDsaPointer);
 
-		tbm_begin_iterate(&scan->iterator, node->tbm, dsa,
+#ifdef USE_PREFETCH
+	if (prefetch_maximum > 0)
+		tbm_begin_iterate(&node->scandesc->prefetch_iterator, node->tbm, dsa,
 						  pstate ?
-						  pstate->tbmiterator :
+						  pstate->prefetch_iterator :
 						  InvalidDsaPointer);
-
-#ifdef USE_PREFETCH
-		if (prefetch_maximum > 0)
-			tbm_begin_iterate(&scan->prefetch_iterator, node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 
-		node->initialized = true;
 
+	node->initialized = true;
+}
+
+/* ----------------------------------------------------------------
+ *		BitmapHeapNext
+ *
+ *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+BitmapHeapNext(BitmapHeapScanState *node)
+{
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
+	BitmapTableScanDesc *scan = node->scandesc;
+
+	/*
+	 * If we haven't yet performed the underlying index scan, do it, and begin
+	 * the iteration over the bitmap.
+	 */
+	if (!node->initialized)
+	{
+		BitmapTableScanSetup(node);
+		scan = node->scandesc;
 		goto new_page;
 	}
 
-- 
2.34.1

v23-0013-BitmapHeapScan-lift-and-shift-prefetch-functions.patchtext/x-patch; charset=US-ASCII; name=v23-0013-BitmapHeapScan-lift-and-shift-prefetch-functions.patchDownload
From f7a076204f6c7c901bef4f6189dd5ecc6e241bca Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 11 Jun 2024 12:14:28 -0400
Subject: [PATCH v23 13/19] BitmapHeapScan: lift and shift prefetch functions

This is a temporary commit. For ease of review, move the BitmapHeapScan
prefetch functions into heapam_handler.c without modifying them. The
next commit will push the prefetching code into heap specific code.
Separating the commit which moves to the functions to heapam_handler.c
and the one which modifies them and their callers to contain bitmap
prefetch code in heap AM-specific code makes it easier to see what has
changed. Doing so requires including heap code in nodeBitmapHeapscan.c,
which is not okay for the final code that is committed.
---
 src/backend/access/heap/heapam_handler.c  | 218 +++++++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 225 +---------------------
 src/include/access/heapam.h               |  10 +
 3 files changed, 230 insertions(+), 223 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 8b8e4e9c78..34c593c2f4 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2112,6 +2112,224 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+void
+BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!tbm_exhausted(prefetch_iterator))
+		{
+			while (node->prefetch_pages < node->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!tbm_exhausted(prefetch_iterator))
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = tbm_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				node->pfblockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (node->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			node->prefetch_pages--;
+		}
+		else if (!tbm_exhausted(prefetch_iterator))
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
+	if (node->prefetch_maximum > 0)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!tbm_exhausted(prefetch_iterator))
+			{
+				tbmpre = tbm_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (node->prefetch_target >= node->prefetch_maximum / 2)
+			node->prefetch_target = node->prefetch_maximum;
+		else if (node->prefetch_target > 0)
+			node->prefetch_target *= 2;
+		else
+			node->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < node->prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
 
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 7f88452a62..feac0a4d0e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,6 +37,8 @@
 
 #include <math.h>
 
+/* XXX: temporary include only for review purposes */
+#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -51,10 +53,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  BitmapTableScanDesc *scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -287,225 +285,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->pfblockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index ce69f5a023..a393151e06 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -20,6 +20,8 @@
 #include "access/skey.h"
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
+/* XXX: temporary include so lift and shift works */
+#include "nodes/execnodes.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -386,6 +388,14 @@ extern void simple_heap_update(Relation relation, ItemPointer otid,
 extern TransactionId heap_index_delete_tuples(Relation rel,
 											  TM_IndexDeleteOp *delstate);
 
+/* in heapam_handler.c */
+extern void BitmapPrefetch(BitmapHeapScanState *node,
+						   BitmapTableScanDesc *scan);
+
+extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
+
+extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+
 /* in heap/pruneheap.c */
 struct GlobalVisState;
 extern void heap_page_prune_opt(Relation relation, Buffer buffer);
-- 
2.34.1

v23-0016-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v23-0016-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 8a2bcf7675c923962e319f578661b5222edce1d0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 18:02:38 -0400
Subject: [PATCH v23 16/19] Remove table AM callback scan_bitmap_next_block

Non block-based table AMs might find implementing bitmap table scan
somewhat easier by removing table_scan_bitmap_next_block(). Now bitmap
table scan code only calls table_scan_bitmap_next_tuple().

This commit turns the heap AM implementation of scan_bitmap_next_block()
into a local helper in heapam_handler.c.
---
 src/backend/access/heap/heapam_handler.c  | 62 ++++++++++------
 src/backend/access/table/tableamapi.c     |  3 -
 src/backend/executor/nodeBitmapHeapscan.c | 67 ++++++++---------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 88 ++++++-----------------
 5 files changed, 92 insertions(+), 130 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ae5fa4657b..e99ca30616 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2334,18 +2334,22 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
 #endif							/* USE_PREFETCH */
 }
 
-
-/* ------------------------------------------------------------------------
- * Executor related callbacks for the heap AM
- * ------------------------------------------------------------------------
+/*
+ * Prepare to fetch / check / return tuples as part of a bitmap heap scan.
+ * `scan` needs to have been started via heap_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set to indicate whether or not the tuples from this block
+ * should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  */
-
 static bool
-heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
+heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2515,9 +2519,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
 	return true;
 }
 
+
+/* ------------------------------------------------------------------------
+ * Executor related callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
 static bool
 heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot, bool *recheck,
+							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	ParallelBitmapHeapState *pstate = sscan->pstate;
@@ -2525,22 +2536,32 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 	Page		page;
 	ItemId		lp;
 
-	if (scan->empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		scan->empty_tuples_pending--;
-		BitmapPrefetch(scan);
-		return true;
-	}
+		if (scan->empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			scan->empty_tuples_pending--;
+			BitmapPrefetch(scan);
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
-		return false;
+		/*
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
+		 */
+		if (!heapam_scan_bitmap_next_block(scan, recheck, lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2941,7 +2962,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index e9b598256f..a47527d490 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fdccc84205..3dd5fa5353 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -179,60 +179,49 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext = node->ss.ps.ps_ExprContext;
-	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
-	BitmapTableScanDesc *scan = node->scandesc;
+	ExprContext *econtext;
+	TupleTableSlot *slot;
+	BitmapTableScanDesc *scan;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->scandesc;
-		goto new_page;
-	}
 
-	for (;;)
+	scan = node->scandesc;
+	econtext = node->ss.ps.ps_ExprContext;
+	slot = node->ss.ss_ScanTupleSlot;
+
+	while (table_scan_bitmap_next_tuple(scan, slot,
+										&node->recheck,
+										&node->lossy_pages, &node->exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
+		/*
+		 * Continuing in previously obtained page.
+		 */
 
-			CHECK_FOR_INTERRUPTS();
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck,
-										  &node->lossy_pages, &node->exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 775955363e..c11ff3a1ba 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -324,7 +324,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a00b9bd296..d496d68f1c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -808,37 +808,20 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from as part of a bitmap table
-	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
-	 * bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin a block, and do the necessary work to
-	 * allow scan_bitmap_next_tuple() to return tuples (e.g. depending on the
-	 * table AM, it might make sense to perform tuple visibility checks at
-	 * this time).
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
-	 * block; otherwise, `exact_pages` is incremented.
-	 *
-	 * Prefetching future blocks indicated in the bitmap is left to the table
-	 * AM.
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
-										   bool *recheck,
-										   long *lossy_pages, long *exact_pages);
-
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
 	bool		(*scan_bitmap_next_tuple) (BitmapTableScanDesc *scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot, bool *recheck,
+										   long *lossy_pages, long *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1982,54 +1965,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * ----------------------------------------------------------------------------
  */
 
+
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
- * incremented if the block's representation in the bitmap is lossy; otherwise,
- * `exact_pages` is incremented.
- *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked. Tuples from lossy pages will always
- * need to be rechecked, but some non-lossy pages' tuples may also require
- * recheck.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `blockno` is only used in bitmap table scan code to validate that the
- * prefetch block is staying ahead of the current block.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
+table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
-														 recheck,
-														 lossy_pages, exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2040,7 +1995,8 @@ table_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rel->rd_tableam->scan_bitmap_next_tuple(scan,
-														 slot);
+														 slot, recheck,
+														 lossy_pages, exact_pages);
 }
 
 /*
-- 
2.34.1

v23-0017-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-patch; charset=US-ASCII; name=v23-0017-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From e691bf84f837d0875cc98e6d2af9852e8a4a346f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 19 Jun 2024 11:42:12 -0400
Subject: [PATCH v23 17/19] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MAX_TUPLES_PER_PAGE OffsetNumbers. Creating
a fixed-size aray of size MAX_TUPLES_PER_PAGE is more clear for the API
user.
---
 src/backend/nodes/tidbitmap.c | 19 ++++---------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index d035de7f95..4dd49fd48a 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -696,8 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1467,8 +1457,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 9dbc7bab7a..c108e4f3d5 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,9 +22,17 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
+/*
+ * The maximum number of tuples per page is not large (typically 256 with
+ * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+ * the per-page bitmaps variable size.  We just legislate that the size
+ * is this:
+ */
+#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
 
 /*
  * Actual bitmap representation is private to tidbitmap.c.  Callers can
@@ -52,9 +60,9 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+	OffsetNumber offsets[MAX_TUPLES_PER_PAGE];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.34.1

v23-0019-Use-streaming-I-O-in-Bitmap-Heap-Scans.patchtext/x-patch; charset=US-ASCII; name=v23-0019-Use-streaming-I-O-in-Bitmap-Heap-Scans.patchDownload
From 8661e3cdf7e54c365965bdd19436e1367914b952 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 18:11:57 -0400
Subject: [PATCH v23 19/19] Use streaming I/O in Bitmap Heap Scans

Instead of calling ReadBuffer() for each block, bitmap heap scans now
use the streaming API introduced in b5a9b18cd0.

The read stream API prefetches blocks from the bitmap, so this commit
removes all of the bespoke bitmap heap scan prefetch code.

ci-os-only:
---
 src/backend/access/heap/heapam.c          |  79 ++++-
 src/backend/access/heap/heapam_handler.c  | 347 +++-------------------
 src/backend/executor/nodeBitmapHeapscan.c |  52 +---
 src/include/access/heapam.h               |  14 +-
 src/include/access/relscan.h              |   4 -
 src/include/access/tableam.h              |  11 +-
 src/include/nodes/execnodes.h             |   6 -
 7 files changed, 109 insertions(+), 404 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 9847ce2c3a..211233cd14 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -285,6 +285,59 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+static BlockNumber
+heap_bitmap_scan_stream_read_next(ReadStream *stream,
+								  void *callback_private_data,
+								  void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc *scan = callback_private_data;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&scan->base.iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(scan->base.flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
+		{
+			/* can't be lossy in the skip_fetch case */
+			Assert(tbmres->ntuples >= 0);
+			Assert(scan->empty_tuples_pending >= 0);
+
+			scan->empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1230,8 +1283,7 @@ heap_endscan(TableScanDesc sscan)
 }
 
 BitmapTableScanDesc *
-heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
-				  int prefetch_maximum)
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 {
 	BitmapHeapScanDesc *scan;
 
@@ -1268,11 +1320,13 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
 	scan->pvmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
-	scan->prefetch_maximum = prefetch_maximum;
-
-	/* Only used for serial BHS */
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
+	scan->read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+												   NULL,
+												   scan->base.rel,
+												   MAIN_FORKNUM,
+												   heap_bitmap_scan_stream_read_next,
+												   scan,
+												   sizeof(TBMIterateResult));
 
 	return (BitmapTableScanDesc *) scan;
 }
@@ -1282,6 +1336,10 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	/* Reset the read stream on rescan. */
+	if (scan->read_stream)
+		read_stream_reset(scan->read_stream);
+
 	if (BufferIsValid(scan->cbuf))
 	{
 		ReleaseBuffer(scan->cbuf);
@@ -1313,10 +1371,6 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->ctup.t_data = NULL;
 	ItemPointerSetInvalid(&scan->ctup.t_self);
-
-	/* Only used for serial BHS */
-	scan->prefetch_target = -1;
-	scan->prefetch_pages = 0;
 }
 
 void
@@ -1324,6 +1378,9 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 
+	if (scan->read_stream)
+		read_stream_end(scan->read_stream);
+
 	if (BufferIsValid(scan->cbuf))
 		ReleaseBuffer(scan->cbuf);
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 1050f59e56..b11aafc9de 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,9 +54,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
-static inline void BitmapPrefetch(BitmapHeapScanDesc *scan);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan);
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 static const TableAmRoutine heapam_methods;
@@ -2115,227 +2112,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 									   HEAP_USABLE_BYTES_PER_PAGE);
 }
 
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (scan->prefetch_pages < scan->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				scan->prefetch_pages++;
-				scan->pfblock = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				scan->pfblock = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre.blockno,
-											 &scan->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		if (scan->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			scan->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			scan->pfblock = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (scan->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				scan->pfblock = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = scan->base.pstate;
-
-	if (pstate == NULL)
-	{
-		if (scan->prefetch_target >= scan->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
-			scan->prefetch_target = scan->prefetch_maximum;
-		else if (scan->prefetch_target > 0)
-			scan->prefetch_target *= 2;
-		else
-			scan->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < scan->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= scan->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
-			pstate->prefetch_target = scan->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * Prepare to fetch / check / return tuples as part of a bitmap heap scan.
  * `scan` needs to have been started via heap_beginscan_bm(). Returns false if
@@ -2356,63 +2132,52 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
+	void	   *per_buffer_data;
+
+	Assert(scan->read_stream);
 
 	scan->vis_idx = 0;
 	scan->vis_ntuples = 0;
 
 	*recheck = true;
 
-	BitmapAdjustPrefetchIterator(scan);
-
-	do
+	if (BufferIsValid(scan->cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		tbm_iterate(&scan->base.iterator, &tbmres);
+		ReleaseBuffer(scan->cbuf);
+		scan->cbuf = InvalidBuffer;
+	}
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	scan->cbuf = read_stream_next_buffer(scan->read_stream, &per_buffer_data);
 
+	if (BufferIsInvalid(scan->cbuf))
+	{
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() && tbmres.blockno >= scan->nblocks);
+		*recheck = false;
+		return scan->empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	block = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->base.flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->base.rel, tbmres.blockno, &scan->vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(scan->empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		scan->empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(scan->cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	/* Got a valid block */
+	block = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
+	scan->cblock = tbmres->blockno;
+	scan->vis_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	scan->cbuf = ReleaseAndReadBuffer(scan->cbuf,
-									  scan->base.rel,
-									  block);
-	scan->cblock = block;
 	buffer = scan->cbuf;
 	snapshot = scan->base.snapshot;
 
@@ -2433,7 +2198,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2442,9 +2207,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2494,23 +2259,11 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	scan->vis_ntuples = ntup;
 
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
 
-	/*
-	 * If serial, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->base.pstate == NULL &&
-		!tbm_exhausted(&scan->base.prefetch_iterator) &&
-		scan->pfblock < block)
-		elog(ERROR, "prefetch and main iterators are out of sync");
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(scan);
-
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2533,7 +2286,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 							  long *lossy_pages, long *exact_pages)
 {
 	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
-	ParallelBitmapHeapState *pstate = sscan->pstate;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
@@ -2553,7 +2305,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 			 */
 			ExecStoreAllNullTuple(slot);
 			scan->empty_tuples_pending--;
-			BitmapPrefetch(scan);
 			return true;
 		}
 
@@ -2565,36 +2316,6 @@ heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 			return false;
 	}
 
-#ifdef USE_PREFETCH
-
-	/*
-	 * Try to prefetch at least a few pages even before we get to the second
-	 * page if we don't stop reading after the first tuple.
-	 */
-	if (!pstate)
-	{
-		if (scan->prefetch_target < scan->prefetch_maximum)
-			scan->prefetch_target++;
-	}
-	else if (pstate->prefetch_target < scan->prefetch_maximum)
-	{
-		/* take spinlock while updating shared state */
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target < scan->prefetch_maximum)
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-
-	/*
-	 * We issue prefetch requests *after* fetching the current page to try to
-	 * avoid having prefetching interfere with the main I/O. Also, this should
-	 * happen only when we have determined there is still something to do on
-	 * the current page, else we may uselessly prefetch the same page we are
-	 * just about to request for real.
-	 */
-	BitmapPrefetch(scan);
-
 	targoffset = scan->vis_tuples[scan->vis_idx];
 	page = BufferGetPage(scan->cbuf);
 	lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3dd5fa5353..c5f3f2fd1a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -63,14 +63,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 {
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
-	int			prefetch_maximum = 0;
-	Relation	rel = node->ss.ss_currentRelation;
-
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
 
 	/*
 	 * Scan the index, build the bitmap, and set up shared state for parallel.
@@ -92,29 +84,13 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 			elog(ERROR, "unrecognized result from subplan");
 
-		/*
-		 * We use *two* iterators, one for the pages we are actually scanning
-		 * and another that runs ahead of the first for prefetching.
-		 * scan->prefetch_pages tracks exactly how many pages ahead the
-		 * prefetch iterator is.  Also, scan->prefetch_target tracks the
-		 * desired prefetch distance, which starts small and increases up to
-		 * the prefetch_maximum. This is to avoid doing a lot of prefetching
-		 * in a scan that stops after a few tuples because of a LIMIT.
-		 */
-
 		/*
 		 * Prepare to iterate over the TBM. This will return the dsa_pointer
 		 * of the iterator state which will be used by multiple processes to
 		 * iterate jointly.
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
-#ifdef USE_PREFETCH
-		if (prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif
+
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -139,16 +115,13 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 
 		node->scandesc = table_beginscan_bm(node->ss.ss_currentRelation,
 											node->ss.ps.state->es_snapshot,
-											pstate,
-											need_tuples,
-											prefetch_maximum);
+											need_tuples);
 		node->scan_in_progress = true;
 	}
 	else
 	{
 		Assert(node->scandesc);
 		tbm_end_iterate(&node->scandesc->iterator);
-		tbm_end_iterate(&node->scandesc->prefetch_iterator);
 		/* rescan to release any page pin */
 		table_rescan_bm(node->scandesc);
 	}
@@ -158,15 +131,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 					  pstate->tbmiterator :
 					  InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (prefetch_maximum > 0)
-		tbm_begin_iterate(&node->scandesc->prefetch_iterator, node->tbm, dsa,
-						  pstate ?
-						  pstate->prefetch_iterator :
-						  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
-
 	node->initialized = true;
 }
 
@@ -328,7 +292,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor.
 		 */
 		tbm_end_iterate(&scanDesc->iterator);
-		tbm_end_iterate(&scanDesc->prefetch_iterator);
 
 		/*
 		 * close table scan
@@ -496,12 +459,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -528,17 +488,9 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
-
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
-	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 5d73bb361e..c9d91b72b1 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -114,16 +114,7 @@ typedef struct BitmapHeapScanDesc
 
 	BlockNumber cblock;			/* current block # in scan, if any */
 
-	/* used to validate pf stays ahead of current block */
-	BlockNumber pfblock;
-
-	/* maximum value for prefetch_target */
-	int			prefetch_maximum;
-
-	/* Current target for prefetch distance */
-	int			prefetch_target;
-	/* # pages prefetch iterator is ahead of current */
-	int			prefetch_pages;
+	ReadStream *read_stream;
 
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
@@ -330,8 +321,7 @@ extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 extern void heap_endscan(TableScanDesc sscan);
 
 extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
-											  Snapshot snapshot, uint32 flags,
-											  int prefetch_maximum);
+											  Snapshot snapshot, uint32 flags);
 extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
 void		heap_endscan_bm(BitmapTableScanDesc *sscan);
 
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 079bce61da..086fce35a8 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -57,14 +57,10 @@ typedef struct BitmapTableScanDesc
 	Relation	rel;			/* heap relation descriptor */
 	struct SnapshotData *snapshot;	/* snapshot to see */
 
-	struct ParallelBitmapHeapState *pstate;
-
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
 	TBMIterator iterator;
-	/* iterator for prefetching ahead of current page */
-	TBMIterator prefetch_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d496d68f1c..632a07c7a0 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -354,7 +354,7 @@ typedef struct TableAmRoutine
 	 */
 	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
 										   Snapshot snapshot,
-										   uint32 flags, int prefetch_maximum);
+										   uint32 flags);
 
 	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
 
@@ -944,19 +944,14 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   struct ParallelBitmapHeapState *pstate,
-				   bool need_tuple,
-				   int prefetch_maximum)
+				   bool need_tuple)
 {
-	BitmapTableScanDesc *result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, prefetch_maximum);
-	result->pstate = pstate;
-	return result;
+	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 28fc6e7221..20459b6bfb 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1770,11 +1770,8 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
  *		mutex					mutual exclusion for the prefetching variable
  *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1782,10 +1779,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
-- 
2.34.1

v23-0018-Separate-TBMIterator-and-TBMIterateResult.patchtext/x-patch; charset=US-ASCII; name=v23-0018-Separate-TBMIterator-and-TBMIterateResult.patchDownload
From 1d031bfe66e0d71e1c1257e0e2c2c679f17b46a9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 17:09:50 -0400
Subject: [PATCH v23 18/19] Separate TBMIterator and TBMIterateResult

Remove the TBMIterateResult from the TBMSerialIterator and
TBMSharedIterator and have tbm_[shared_]iterate() take a
TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently
allowing asynchronous use of the TIDBitmap for prefetching.

tbm_[shared]_iterate() now sets blockno to InvalidBlockNumber when the
bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, inline the matchResult
in the GinScanEntry to avoid having to separately manage memory for the
TBMIterateResult.
---
 src/backend/access/gin/ginget.c          | 49 +++++++++------
 src/backend/access/gin/ginscan.c         |  2 +-
 src/backend/access/heap/heapam_handler.c | 66 ++++++++++----------
 src/backend/nodes/tidbitmap.c            | 77 ++++++++++++------------
 src/include/access/gin_private.h         |  2 +-
 src/include/nodes/tidbitmap.h            |  6 +-
 6 files changed, 108 insertions(+), 94 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 9c53ca19f0..3322660340 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,7 +332,20 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -374,6 +387,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_private_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -823,18 +837,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_serial_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -858,10 +873,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -875,27 +890,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 5b9a0eaea7..09e1586c4a 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e99ca30616..1050f59e56 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2132,17 +2132,19 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 		{
 			while (scan->prefetch_pages < scan->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				scan->prefetch_pages++;
-				scan->pfblock = tbmpre->blockno;
+				scan->pfblock = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2151,13 +2153,13 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -2172,7 +2174,7 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -2191,25 +2193,25 @@ BitmapPrefetch(BitmapHeapScanDesc *scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				scan->pfblock = tbmpre->blockno;
+				scan->pfblock = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(scan->base.rel,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
@@ -2228,7 +2230,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = scan->base.pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -2242,8 +2244,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			scan->pfblock = tbmpre.blockno;
 		}
 		return;
 	}
@@ -2282,8 +2284,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				scan->pfblock = tbmpre.blockno;
 			}
 		}
 	}
@@ -2354,7 +2356,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	scan->vis_idx = 0;
 	scan->vis_ntuples = 0;
@@ -2367,9 +2369,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->base.iterator);
+		tbm_iterate(&scan->base.iterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
 		/*
@@ -2380,11 +2382,11 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks);
+	} while (!IsolationIsSerializable() && tbmres.blockno >= scan->nblocks);
 
 	/* Got a valid block */
-	block = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	block = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2392,14 +2394,14 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->base.flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->base.rel, tbmres.blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(scan->empty_tuples_pending >= 0);
 
-		scan->empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
@@ -2431,7 +2433,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2440,9 +2442,9 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2492,7 +2494,7 @@ heapam_scan_bitmap_next_block(BitmapHeapScanDesc *scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	scan->vis_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 4dd49fd48a..5a4161cf71 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -948,22 +946,22 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  If result->ntuples
+ * < 0, then the bitmap is "lossy" and failed to remember the exact tuples to
+ * look at on this page --- the caller must examine all tuples on the page and
+ * check if they meet the intended condition.  If result->recheck is true, only
+ * the indicated tuples need be examined, but the condition must be rechecked
+ * anyway.  (For ease of testing, recheck is always set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
+	Assert(tbmres);
 
 	/*
 	 * If lossy chunk pages remain, make sure we've advanced schunkptr/
@@ -999,11 +997,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1019,16 +1017,16 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1038,10 +1036,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1092,13 +1089,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1108,21 +1105,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1592,14 +1589,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or non-shared bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
 	Assert(!iterator->exhausted);
 
 	if (iterator->private_iterator)
-		return tbm_private_iterate(iterator->private_iterator);
+		tbm_private_iterate(iterator->private_iterator, tbmres);
 	else
-		return tbm_shared_iterate(iterator->shared_iterator);
+		tbm_shared_iterate(iterator->shared_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 7880050936..b528ab715f 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index c108e4f3d5..3f929f2271 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -83,8 +83,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -95,7 +95,7 @@ extern void tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
 							  dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v23-0014-BitmapHeapScan-Push-prefetch-code-into-heap-AM.patchtext/x-patch; charset=US-ASCII; name=v23-0014-BitmapHeapScan-Push-prefetch-code-into-heap-AM.patchDownload
From 13a6850c19a81925d9af538d24928828867f8cd7 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 14 Jun 2024 10:30:28 -0400
Subject: [PATCH v23 14/19] BitmapHeapScan: Push prefetch code into heap AM

In order to completely remove the layering violation in bitmap table
scan code, we must avoid using the VM for skipping prefetches as well.

To accomplish this, push prefetch code down into the heap implementation
fo the bitmap table scan AM functions. This fixes another layering
violation related to prefetching mentioned in tableam.h.

This commit moves prefetch-related members from the BitmapHeapScanState
to the BitmapHeapScanDesc and localizes the prefetch functions to heap
AM code.

heapam_scan_bitmap_next_block() no longer needs to take blockno as a
parameter because it was only being used in generic bitmap table scan
code to check if the prefetch block was falling behind the current
block.
---
 src/backend/access/heap/heapam.c          |  23 ++-
 src/backend/access/heap/heapam_handler.c  | 217 +++++++++++++---------
 src/backend/executor/nodeBitmapHeapscan.c | 110 +++--------
 src/include/access/heapam.h               |  28 +--
 src/include/access/relscan.h              |   4 +
 src/include/access/tableam.h              |  42 ++---
 src/include/nodes/execnodes.h             |  14 --
 7 files changed, 219 insertions(+), 219 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 88da737d14..9847ce2c3a 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1230,7 +1230,8 @@ heap_endscan(TableScanDesc sscan)
 }
 
 BitmapTableScanDesc *
-heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
+heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags,
+				  int prefetch_maximum)
 {
 	BitmapHeapScanDesc *scan;
 
@@ -1264,8 +1265,15 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot, uint32 flags)
 	scan->vis_ntuples = 0;
 
 	scan->vmbuffer = InvalidBuffer;
+	scan->pvmbuffer = InvalidBuffer;
 	scan->empty_tuples_pending = 0;
 
+	scan->prefetch_maximum = prefetch_maximum;
+
+	/* Only used for serial BHS */
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
+
 	return (BitmapTableScanDesc *) scan;
 }
 
@@ -1288,6 +1296,12 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->cblock = InvalidBlockNumber;
 
+	if (BufferIsValid(scan->pvmbuffer))
+	{
+		ReleaseBuffer(scan->pvmbuffer);
+		scan->pvmbuffer = InvalidBuffer;
+	}
+
 	/*
 	 * Reset empty_tuples_pending, a field only used by bitmap heap scan, to
 	 * avoid incorrectly emitting NULL-filled tuples from a previous scan on
@@ -1299,6 +1313,10 @@ heap_rescan_bm(BitmapTableScanDesc *sscan)
 
 	scan->ctup.t_data = NULL;
 	ItemPointerSetInvalid(&scan->ctup.t_self);
+
+	/* Only used for serial BHS */
+	scan->prefetch_target = -1;
+	scan->prefetch_pages = 0;
 }
 
 void
@@ -1312,6 +1330,9 @@ heap_endscan_bm(BitmapTableScanDesc *sscan)
 	if (BufferIsValid(scan->vmbuffer))
 		ReleaseBuffer(scan->vmbuffer);
 
+	if (BufferIsValid(scan->pvmbuffer))
+		ReleaseBuffer(scan->pvmbuffer);
+
 	/*
 	 * decrement relation reference count and free scan descriptor storage
 	 */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 34c593c2f4..ae5fa4657b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,6 +54,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
+static inline void BitmapPrefetch(BitmapHeapScanDesc *scan);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan);
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 static const TableAmRoutine heapam_methods;
@@ -2115,19 +2118,19 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 /*
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
-void
-BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
+static inline void
+BitmapPrefetch(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		if (!tbm_exhausted(prefetch_iterator))
 		{
-			while (node->prefetch_pages < node->prefetch_target)
+			while (scan->prefetch_pages < scan->prefetch_target)
 			{
 				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
@@ -2138,8 +2141,8 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				scan->prefetch_pages++;
+				scan->pfblock = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2147,14 +2150,14 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 				 * logic normally.  (Would it be better not to increment
 				 * prefetch_pages?)
 				 */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->base.rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 
@@ -2163,7 +2166,7 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		if (!tbm_exhausted(prefetch_iterator))
 		{
@@ -2196,17 +2199,17 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				scan->pfblock = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->flags & SO_NEED_TUPLES) &&
+				skip_fetch = (!(scan->base.flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->base.rel,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &scan->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rel, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->base.rel, MAIN_FORKNUM, tbmpre->blockno);
 			}
 		}
 	}
@@ -2220,27 +2223,27 @@ BitmapPrefetch(BitmapHeapScanState *node, BitmapTableScanDesc *scan)
  *	iterator in prefetch_pages. For each block the main iterator returns, we
  *	decrement prefetch_pages.
  */
-void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
-		if (node->prefetch_pages > 0)
+		if (scan->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
+			scan->prefetch_pages--;
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
 			/* Do not let the prefetch iterator get behind the main one */
 			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
@@ -2254,9 +2257,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
 	 * exacerbates the effects of this bug.
 	 */
-	if (node->prefetch_maximum > 0)
+	if (scan->prefetch_maximum > 0)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->base.prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -2280,7 +2283,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			if (!tbm_exhausted(prefetch_iterator))
 			{
 				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				scan->pfblock = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
 	}
@@ -2295,33 +2298,33 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
  * page/tuple, then to one after the second tuple is fetched, then
  * it doubles as later pages are fetched.
  */
-void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *scan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	ParallelBitmapHeapState *pstate = scan->base.pstate;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_target >= node->prefetch_maximum)
+		if (scan->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
+		else if (scan->prefetch_target >= scan->prefetch_maximum / 2)
+			scan->prefetch_target = scan->prefetch_maximum;
+		else if (scan->prefetch_target > 0)
+			scan->prefetch_target *= 2;
 		else
-			node->prefetch_target++;
+			scan->prefetch_target++;
 		return;
 	}
 
 	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
+	if (pstate->prefetch_target < scan->prefetch_maximum)
 	{
 		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
+		if (pstate->prefetch_target >= scan->prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target >= scan->prefetch_maximum / 2)
+			pstate->prefetch_target = scan->prefetch_maximum;
 		else if (pstate->prefetch_target > 0)
 			pstate->prefetch_target *= 2;
 		else
@@ -2331,34 +2334,36 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
 #endif							/* USE_PREFETCH */
 }
 
+
 /* ------------------------------------------------------------------------
  * Executor related callbacks for the heap AM
  * ------------------------------------------------------------------------
  */
 
 static bool
-heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
-							  BlockNumber *blockno, bool *recheck,
+heapam_scan_bitmap_next_block(BitmapTableScanDesc *sscan,
+							  bool *recheck,
 							  long *lossy_pages, long *exact_pages)
 {
-	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
 
-	hscan->vis_idx = 0;
-	hscan->vis_ntuples = 0;
+	scan->vis_idx = 0;
+	scan->vis_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(scan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->iterator);
+		tbmres = tbm_iterate(&scan->base.iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2371,10 +2376,10 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		 * isolation though, as we need to examine all invisible tuples
 		 * reachable by the index.
 		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->nblocks);
+	} while (!IsolationIsSerializable() && tbmres->blockno >= scan->nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
+	block = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2382,37 +2387,35 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
 	 * page are visible to our transaction.
 	 */
-	if (!(scan->flags & SO_NEED_TUPLES) &&
+	if (!(scan->base.flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rel, tbmres->blockno, &hscan->vmbuffer))
+		VM_ALL_VISIBLE(scan->base.rel, tbmres->blockno, &scan->vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->empty_tuples_pending >= 0);
+		Assert(scan->empty_tuples_pending >= 0);
 
-		hscan->empty_tuples_pending += tbmres->ntuples;
+		scan->empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
-
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
-	hscan->cbuf = ReleaseAndReadBuffer(hscan->cbuf,
-									   scan->rel,
-									   block);
-	hscan->cblock = block;
-	buffer = hscan->cbuf;
-	snapshot = scan->snapshot;
+	scan->cbuf = ReleaseAndReadBuffer(scan->cbuf,
+									  scan->base.rel,
+									  block);
+	scan->cblock = block;
+	buffer = scan->cbuf;
+	snapshot = scan->base.snapshot;
 
 	ntup = 0;
 
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	heap_page_prune_opt(scan->rel, buffer);
+	heap_page_prune_opt(scan->base.rel, buffer);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -2440,9 +2443,9 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 			HeapTupleData heapTuple;
 
 			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rel, buffer, snapshot,
+			if (heap_hot_search_buffer(&tid, scan->base.rel, buffer, snapshot,
 									   &heapTuple, NULL, true))
-				hscan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+				scan->vis_tuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
 		}
 	}
 	else
@@ -2466,16 +2469,16 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rel->rd_id;
+			loctup.t_tableOid = scan->base.rel->rd_id;
 			ItemPointerSet(&loctup.t_self, block, offnum);
 			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
 			if (valid)
 			{
-				hscan->vis_tuples[ntup++] = offnum;
-				PredicateLockTID(scan->rel, &loctup.t_self, snapshot,
+				scan->vis_tuples[ntup++] = offnum;
+				PredicateLockTID(scan->base.rel, &loctup.t_self, snapshot,
 								 HeapTupleHeaderGetXmin(loctup.t_data));
 			}
-			HeapCheckForSerializableConflictOut(valid, scan->rel, &loctup,
+			HeapCheckForSerializableConflictOut(valid, scan->base.rel, &loctup,
 												buffer, snapshot);
 		}
 	}
@@ -2483,17 +2486,29 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->vis_ntuples = ntup;
+	scan->vis_ntuples = ntup;
 
 	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
 
+	/*
+	 * If serial, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->base.pstate == NULL &&
+		!tbm_exhausted(&scan->base.prefetch_iterator) &&
+		scan->pfblock < block)
+		elog(ERROR, "prefetch and main iterators are out of sync");
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(scan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * scan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
 	 * return false returning control to this function to advance to the next
 	 * block in the bitmap.
 	 */
@@ -2501,51 +2516,83 @@ heapam_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 }
 
 static bool
-heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *scan,
+heapam_scan_bitmap_next_tuple(BitmapTableScanDesc *sscan,
 							  TupleTableSlot *slot)
 {
-	BitmapHeapScanDesc *hscan = (BitmapHeapScanDesc *) scan;
+	BitmapHeapScanDesc *scan = (BitmapHeapScanDesc *) sscan;
+	ParallelBitmapHeapState *pstate = sscan->pstate;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->empty_tuples_pending > 0)
+	if (scan->empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->empty_tuples_pending--;
+		scan->empty_tuples_pending--;
+		BitmapPrefetch(scan);
 		return true;
 	}
 
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->vis_idx < 0 || hscan->vis_idx >= hscan->vis_ntuples)
+	if (scan->vis_idx < 0 || scan->vis_idx >= scan->vis_ntuples)
 		return false;
 
-	targoffset = hscan->vis_tuples[hscan->vis_idx];
-	page = BufferGetPage(hscan->cbuf);
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!pstate)
+	{
+		if (scan->prefetch_target < scan->prefetch_maximum)
+			scan->prefetch_target++;
+	}
+	else if (pstate->prefetch_target < scan->prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target < scan->prefetch_maximum)
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(scan);
+
+	targoffset = scan->vis_tuples[scan->vis_idx];
+	page = BufferGetPage(scan->cbuf);
 	lp = PageGetItemId(page, targoffset);
 	Assert(ItemIdIsNormal(lp));
 
-	hscan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-	hscan->ctup.t_len = ItemIdGetLength(lp);
-	hscan->ctup.t_tableOid = scan->rel->rd_id;
-	ItemPointerSet(&hscan->ctup.t_self, hscan->cblock, targoffset);
+	scan->ctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+	scan->ctup.t_len = ItemIdGetLength(lp);
+	scan->ctup.t_tableOid = sscan->rel->rd_id;
+	ItemPointerSet(&scan->ctup.t_self, scan->cblock, targoffset);
 
-	pgstat_count_heap_fetch(scan->rel);
+	pgstat_count_heap_fetch(sscan->rel);
 
 	/*
 	 * Set up the result slot to point to this tuple.  Note that the slot
 	 * acquires a pin on the buffer.
 	 */
-	ExecStoreBufferHeapTuple(&hscan->ctup,
+	ExecStoreBufferHeapTuple(&scan->ctup,
 							 slot,
-							 hscan->cbuf);
+							 scan->cbuf);
 
-	hscan->vis_idx++;
+	scan->vis_idx++;
 
 	return true;
 }
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index feac0a4d0e..45095d800b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,8 +37,6 @@
 
 #include <math.h>
 
-/* XXX: temporary include only for review purposes */
-#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -92,6 +90,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		int			prefetch_maximum = 0;
+		Relation	rel = node->ss.ss_currentRelation;
+
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+
 		if (!pstate)
 		{
 			node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -117,7 +124,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			 */
 			pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 #ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (prefetch_maximum > 0)
 			{
 				pstate->prefetch_iterator =
 					tbm_prepare_shared_iterate(node->tbm);
@@ -127,14 +134,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			BitmapDoneInitializingSharedState(pstate);
 		}
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-			tbm_begin_iterate(&node->prefetch_iterator, node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -156,7 +155,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
-									  need_tuples);
+									  pstate,
+									  need_tuples,
+									  prefetch_maximum);
 			node->scandesc = scan;
 			node->scan_in_progress = true;
 		}
@@ -164,6 +165,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		{
 			Assert(scan);
 			/* rescan to release any page pin */
+			tbm_end_iterate(&scan->prefetch_iterator);
 			tbm_end_iterate(&scan->iterator);
 			table_rescan_bm(scan);
 		}
@@ -173,6 +175,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 						  pstate->tbmiterator :
 						  InvalidDsaPointer);
 
+#ifdef USE_PREFETCH
+		if (prefetch_maximum > 0)
+			tbm_begin_iterate(&scan->prefetch_iterator, node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		node->initialized = true;
 
 		goto new_page;
@@ -188,37 +198,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -241,27 +220,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck,
 										  &node->lossy_pages, &node->exact_pages))
 			break;
-
-		/*
-		 * If private, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -326,23 +291,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* End iteration on iterators saved in the node . */
-	tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
-	/* Only used for serial BHS */
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -379,6 +333,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor.
 		 */
 		tbm_end_iterate(&scanDesc->iterator);
+		tbm_end_iterate(&scanDesc->prefetch_iterator);
 
 		/*
 		 * close table scan
@@ -386,16 +341,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan_bm(scanDesc);
 	}
 
-	/* End iteration on iterators saved in the node . */
-	tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -428,17 +378,12 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 	scanstate->exact_pages = 0;
 	scanstate->lossy_pages = 0;
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->scan_in_progress = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -478,13 +423,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index a393151e06..5d73bb361e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -20,8 +20,6 @@
 #include "access/skey.h"
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
-/* XXX: temporary include so lift and shift works */
-#include "nodes/execnodes.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -116,6 +114,17 @@ typedef struct BitmapHeapScanDesc
 
 	BlockNumber cblock;			/* current block # in scan, if any */
 
+	/* used to validate pf stays ahead of current block */
+	BlockNumber pfblock;
+
+	/* maximum value for prefetch_target */
+	int			prefetch_maximum;
+
+	/* Current target for prefetch distance */
+	int			prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			prefetch_pages;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -123,7 +132,11 @@ typedef struct BitmapHeapScanDesc
 	 * block reported by the bitmap to determine how many NULL-filled tuples
 	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
+
+	/* page of VM containing info for current block */
 	Buffer		vmbuffer;
+	/* page of VM containing info for prefetch block */
+	Buffer		pvmbuffer;
 	int			empty_tuples_pending;
 } BitmapHeapScanDesc;
 
@@ -317,7 +330,8 @@ extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 extern void heap_endscan(TableScanDesc sscan);
 
 extern BitmapTableScanDesc *heap_beginscan_bm(Relation relation,
-											  Snapshot snapshot, uint32 flags);
+											  Snapshot snapshot, uint32 flags,
+											  int prefetch_maximum);
 extern void heap_rescan_bm(BitmapTableScanDesc *sscan);
 void		heap_endscan_bm(BitmapTableScanDesc *sscan);
 
@@ -388,14 +402,6 @@ extern void simple_heap_update(Relation relation, ItemPointer otid,
 extern TransactionId heap_index_delete_tuples(Relation rel,
 											  TM_IndexDeleteOp *delstate);
 
-/* in heapam_handler.c */
-extern void BitmapPrefetch(BitmapHeapScanState *node,
-						   BitmapTableScanDesc *scan);
-
-extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-
-extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-
 /* in heap/pruneheap.c */
 struct GlobalVisState;
 extern void heap_page_prune_opt(Relation relation, Buffer buffer);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 086fce35a8..079bce61da 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -57,10 +57,14 @@ typedef struct BitmapTableScanDesc
 	Relation	rel;			/* heap relation descriptor */
 	struct SnapshotData *snapshot;	/* snapshot to see */
 
+	struct ParallelBitmapHeapState *pstate;
+
 	/*
 	 * Members common to Parallel and Serial BitmapTableScans
 	 */
 	TBMIterator iterator;
+	/* iterator for prefetching ahead of current page */
+	TBMIterator prefetch_iterator;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index f7f099b644..a00b9bd296 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -354,7 +354,7 @@ typedef struct TableAmRoutine
 	 */
 	BitmapTableScanDesc *(*scan_begin_bm) (Relation rel,
 										   Snapshot snapshot,
-										   uint32 flags);
+										   uint32 flags, int prefetch_maximum);
 
 	void		(*scan_rescan_bm) (BitmapTableScanDesc *scan);
 
@@ -808,33 +808,26 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
+	 * Prepare to fetch / check / return tuples from as part of a bitmap table
+	 * scan. `scan` was started via table_beginscan_bm(). Return false if the
+	 * bitmap is exhausted and true otherwise.
 	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
+	 * This will typically read and pin a block, and do the necessary work to
+	 * allow scan_bitmap_next_tuple() to return tuples (e.g. depending on the
+	 * table AM, it might make sense to perform tuple visibility checks at
+	 * this time).
 	 *
 	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
 	 * block; otherwise, `exact_pages` is incremented.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching future blocks indicated in the bitmap is left to the table
+	 * AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (BitmapTableScanDesc *scan,
-										   BlockNumber *blockno, bool *recheck,
+										   bool *recheck,
 										   long *lossy_pages, long *exact_pages);
 
 	/*
@@ -968,14 +961,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline BitmapTableScanDesc *
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   bool need_tuple)
+				   struct ParallelBitmapHeapState *pstate,
+				   bool need_tuple,
+				   int prefetch_maximum)
 {
+	BitmapTableScanDesc *result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin_bm(rel, snapshot, flags);
+	result = rel->rd_tableam->scan_begin_bm(rel, snapshot, flags, prefetch_maximum);
+	result->pstate = pstate;
+	return result;
 }
 
 /*
@@ -2004,7 +2002,7 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 static inline bool
 table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
-							 BlockNumber *blockno, bool *recheck,
+							 bool *recheck,
 							 long *lossy_pages,
 							 long *exact_pages)
 {
@@ -2017,7 +2015,7 @@ table_scan_bitmap_next_block(BitmapTableScanDesc *scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rel->rd_tableam->scan_bitmap_next_block(scan,
-														 blockno, recheck,
+														 recheck,
 														 lossy_pages, exact_pages);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 7471ca128e..28fc6e7221 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1796,19 +1796,12 @@ typedef struct ParallelBitmapHeapState
  *		scandesc		   current scan descriptor for scan (NULL if none)
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		exact_pages		   total number of exact pages retrieved
  *		lossy_pages		   total number of lossy pages retrieved
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		scan_in_progress   is this a rescan
  *		pstate			   shared state for parallel bitmap scan
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1817,19 +1810,12 @@ typedef struct BitmapHeapScanState
 	struct BitmapTableScanDesc *scandesc;
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	long		exact_pages;
 	long		lossy_pages;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	bool		scan_in_progress;
 	ParallelBitmapHeapState *pstate;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

#148Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Melanie Plageman (#147)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 6/19/24 17:55, Melanie Plageman wrote:

On Tue, Jun 18, 2024 at 6:02 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I went through v22 to remind myself of what the patches do and do some
basic review - I have some simple questions / comments for now, nothing
major. I've kept the comments in separate 'review' patches, it does not
seem worth copying here.

Thanks so much for the review!

I've implemented your feedback in attached v23 except for what I
mention below. I have not gone through each patch in the new set very
carefully after making the changes because I think we should resolve
the question of adding the new table scan descriptor before I do that.
A change there will require a big rebase. Then I can go through each
patch very carefully.

From your v22b-0005-review.patch:

src/backend/executor/nodeBitmapHeapscan.c | 14 ++++++++++++++
src/include/access/tableam.h | 2 ++
2 files changed, 16 insertions(+)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c
b/src/backend/executor/nodeBitmapHeapscan.c
index e8b4a754434..6d7ef9ced19 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -270,6 +270,20 @@ new_page:

BitmapAdjustPrefetchIterator(node);

+        /*
+         * XXX I'm a bit unsure if this needs to be handled using
goto. Wouldn't
+         * it be simpler / easier to understand to have two nested loops?
+         *
+         * while (true)
+         *        if (!table_scan_bitmap_next_block(...)) { break; }
+         *        while (table_scan_bitmap_next_tuple(...)) {
+         *            ... process tuples ...
+         *        }
+         *
+         * But I haven't tried implementing this.
+         */
if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
&node->lossy_pages,
&node->exact_pages))
break;

We need to call table_scan_bimtap_next_block() the first time we call
BitmapHeapNext() on each scan but all subsequent invocations of
BitmapHeapNext() must call table_scan_bitmap_next_tuple() first each
-- because we return from BitmapHeapNext() to yield a tuple even when
there are more tuples on the page. I tried refactoring this a few
different ways and personally found the goto most clear.

OK, I haven't tried refactoring this myself, so you're probably right.

From your v22b-0010-review.patch:

@@ -557,6 +559,8 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
table_rescan(node->ss.ss_currentScanDesc, NULL);

/* release bitmaps and buffers if any */
+    /* XXX seems it should not be right after the comment, also shouldn't
+     * we still reset the prefetch_iterator field to NULL? */
tbm_end_iterate(&node->prefetch_iterator);
if (node->tbm)
tbm_free(node->tbm);

prefetch_iterator is a TBMIterator which is stored in the struct (as
opposed to having a pointer to it stored in the struct).
tbm_end_iterate() sets the actual private and shared iterator pointers
to NULL.

Ah, right.

From your v22b-0017-review.patch

diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 036ef29e7d5..9c711ce0eb0 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -52,6 +52,13 @@ typedef struct TableScanDescData
} TableScanDescData;
typedef struct TableScanDescData *TableScanDesc;
+/*
+ * XXX I don't understand why we should have this special node if we
+ * don't have special nodes for other scan types.

In this case, up until the final commit (using the read stream
interface), there are six fields required by bitmap heap scan that are
not needed by any other user of HeapScanDescData. There are also
several members of HeapScanDescData that are not needed by bitmap heap
scans and all of the setup in initscan() for those fields is not
required for bitmap heap scans.

Also, because the BitmapHeapScanDesc needs information like the
ParallelBitmapHeapState and prefetch_maximum (for use in prefetching),
the scan_begin() callback would have to take those as parameters. I
thought adding so much bitmap table scan-specific information to the
generic table scan callbacks was a bad idea.

Once we add the read stream API code, the number of fields required
for bitmap heap scan that are in the scan descriptor goes down to
three. So, perhaps we could justify having that many bitmap heap
scan-specific fields in the HeapScanDescData.

Though, I actually think we could start moving toward having
specialized scan descriptors if the requirements for that scan type
are appreciably different. I can't think of new code that would be
added to the HeapScanDescData that would have to be duplicated over to
specialized scan descriptors.

With the final read stream state, I can see the argument for bloating
the HeapScanDescData with three extra members and avoiding making new
scan descriptors. But, for the intermediate patches which have all of
the bitmap prefetch members pushed down into the HeapScanDescData, I
think it is really not okay. Six members only for bitmap heap scans
and two bitmap-specific members to begin_scan() seems bad.

What I thought we plan to do is commit the refactoring patches
sometime after the branch for 18 is cut and leave the final read
stream patch uncommitted so we can do performance testing on it. If
you think it is okay to have the six member bloated HeapScanDescData
in master until we push the read stream code, I am okay with removing
the BitmapTableScanDesc and BitmapHeapScanDesc.

I admit I don't have a very good idea what the ideal / desired state
look like. My comment is motivated solely by the feeling that it seems
strange to have one struct serving most scan types, and then a special
struct for one particular scan type ...

+ * XXX Also, maybe this should do the naming convention with Data at
+ * the end (mostly for consistency).
+ */
typedef struct BitmapTableScanDesc
{
Relation    rs_rd;            /* heap relation descriptor */

I really want to move away from these Data typedefs. I find them so
confusing as a developer, but it's hard to justify ripping out the
existing ones because of code churn. If we add new scan descriptors, I
had really hoped to start using a different pattern.

Perhaps, I understand that. I'm not a huge fan of Data structs myself,
but I'm not sure it's a great idea to do both things in the same area of
code. That's guaranteed to be confusing for everyone ...

If we want to move away from that, I'd rather rename the nearby structs
and accept the code churn.

From your v22b-0025-review.patch

diff --git a/src/backend/access/table/tableamapi.c
b/src/backend/access/table/tableamapi.c
index a47527d490a..379b7df619e 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,6 +91,9 @@ GetTableAmRoutine(Oid amhandler)

Assert(routine->relation_estimate_size != NULL);

+    /* XXX shouldn't this check that _block is not set without _tuple?
+     * Also, the commit message says _block is "local helper" but then
+     * why would it be part of TableAmRoutine? */
Assert(routine->scan_sample_next_block != NULL);
Assert(routine->scan_sample_next_tuple != NULL);

scan_bitmap_next_block() is removed as a table AM callback here, so we
don't check if it is set. We do still check if scan_bitmap_next_tuple
is set if amgetbitmap is not NULL. heapam_scan_bitmap_next_block() is
now a local helper for heapam_scan_bitmap_next_tuple(). Perhaps I
should change the name to something like heap_scan_bitmap_next_block()
to make it clear it is not an implementation of a table AM callback?

I'm quite confused by this. How could it not be am AM callback when it's
in the AM routine?

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#149Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Melanie Plageman (#144)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2024-Jun-14, Melanie Plageman wrote:

Subject: [PATCH v21 12/20] Update variable names in bitmap scan descriptors

The previous commit which added BitmapTableScanDesc and
BitmapHeapScanDesc used the existing member names from TableScanDescData
and HeapScanDescData for diff clarity. This commit renames the members
-- in many cases by removing the rs_ prefix which is not relevant or
needed here.

*Cough* Why? It makes grepping for struct members useless. I'd rather
keep these prefixes, as they allow easier code exploration. (Sometimes
when I need to search for uses of some field with a name that's too
common, I add a prefix to the name and let the compiler guide me to
them. But that's a waste of time ...)

Thanks,

--
Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/
"Cuando mañana llegue pelearemos segun lo que mañana exija" (Mowgli)

#150Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#148)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Jun 19, 2024 at 12:38 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 6/19/24 17:55, Melanie Plageman wrote:

On Tue, Jun 18, 2024 at 6:02 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

From your v22b-0017-review.patch

diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 036ef29e7d5..9c711ce0eb0 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -52,6 +52,13 @@ typedef struct TableScanDescData
} TableScanDescData;
typedef struct TableScanDescData *TableScanDesc;
+/*
+ * XXX I don't understand why we should have this special node if we
+ * don't have special nodes for other scan types.

In this case, up until the final commit (using the read stream
interface), there are six fields required by bitmap heap scan that are
not needed by any other user of HeapScanDescData. There are also
several members of HeapScanDescData that are not needed by bitmap heap
scans and all of the setup in initscan() for those fields is not
required for bitmap heap scans.

Also, because the BitmapHeapScanDesc needs information like the
ParallelBitmapHeapState and prefetch_maximum (for use in prefetching),
the scan_begin() callback would have to take those as parameters. I
thought adding so much bitmap table scan-specific information to the
generic table scan callbacks was a bad idea.

Once we add the read stream API code, the number of fields required
for bitmap heap scan that are in the scan descriptor goes down to
three. So, perhaps we could justify having that many bitmap heap
scan-specific fields in the HeapScanDescData.

Though, I actually think we could start moving toward having
specialized scan descriptors if the requirements for that scan type
are appreciably different. I can't think of new code that would be
added to the HeapScanDescData that would have to be duplicated over to
specialized scan descriptors.

With the final read stream state, I can see the argument for bloating
the HeapScanDescData with three extra members and avoiding making new
scan descriptors. But, for the intermediate patches which have all of
the bitmap prefetch members pushed down into the HeapScanDescData, I
think it is really not okay. Six members only for bitmap heap scans
and two bitmap-specific members to begin_scan() seems bad.

What I thought we plan to do is commit the refactoring patches
sometime after the branch for 18 is cut and leave the final read
stream patch uncommitted so we can do performance testing on it. If
you think it is okay to have the six member bloated HeapScanDescData
in master until we push the read stream code, I am okay with removing
the BitmapTableScanDesc and BitmapHeapScanDesc.

I admit I don't have a very good idea what the ideal / desired state
look like. My comment is motivated solely by the feeling that it seems
strange to have one struct serving most scan types, and then a special
struct for one particular scan type ...

I see what you are saying. We could make BitmapTableScanDesc inherit
from TableScanDescData which would be similar to what we do with other
things like the executor scan nodes themselves. We would waste space
and LOC with initializing the unneeded members, but it might seem less
weird.

Whether we want the specialized scan descriptors at all is probably
the bigger question, though.

The top level BitmapTableScanDesc is motivated by wanting fewer bitmap
table scan specific members passed to scan_begin(). And the
BitmapHeapScanDesc is motivated by this plus wanting to avoid bloating
the HeapScanDescData.

If you look at at HEAD~1 (with my patches applied) and think you would
be okay with
1) the contents of the BitmapHeapScanDesc being in the HeapScanDescData and
2) the extra bitmap table scan-specific parameters in scan_begin_bm()
being passed to scan_begin()

then I will remove the specialized scan descriptors.

The final state (with the read stream) will still have three bitmap
heap scan-specific members in the HeapScanDescData.

Would it help if I do a version like this so you can see what it is like?

+ * XXX Also, maybe this should do the naming convention with Data at
+ * the end (mostly for consistency).
+ */
typedef struct BitmapTableScanDesc
{
Relation    rs_rd;            /* heap relation descriptor */

I really want to move away from these Data typedefs. I find them so
confusing as a developer, but it's hard to justify ripping out the
existing ones because of code churn. If we add new scan descriptors, I
had really hoped to start using a different pattern.

Perhaps, I understand that. I'm not a huge fan of Data structs myself,
but I'm not sure it's a great idea to do both things in the same area of
code. That's guaranteed to be confusing for everyone ...

If we want to move away from that, I'd rather rename the nearby structs
and accept the code churn.

Makes sense. I'll do a patch to get rid of the typedefs and rename
TableScanDescData -> TableScanDesc (also for the heap scan desc) if we
end up keeping the specialized scan descriptors.

From your v22b-0025-review.patch

diff --git a/src/backend/access/table/tableamapi.c
b/src/backend/access/table/tableamapi.c
index a47527d490a..379b7df619e 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,6 +91,9 @@ GetTableAmRoutine(Oid amhandler)

Assert(routine->relation_estimate_size != NULL);

+    /* XXX shouldn't this check that _block is not set without _tuple?
+     * Also, the commit message says _block is "local helper" but then
+     * why would it be part of TableAmRoutine? */
Assert(routine->scan_sample_next_block != NULL);
Assert(routine->scan_sample_next_tuple != NULL);

scan_bitmap_next_block() is removed as a table AM callback here, so we
don't check if it is set. We do still check if scan_bitmap_next_tuple
is set if amgetbitmap is not NULL. heapam_scan_bitmap_next_block() is
now a local helper for heapam_scan_bitmap_next_tuple(). Perhaps I
should change the name to something like heap_scan_bitmap_next_block()
to make it clear it is not an implementation of a table AM callback?

I'm quite confused by this. How could it not be am AM callback when it's
in the AM routine?

I removed the callback for getting the next block. Now,
BitmapHeapNext() just calls table_scan_bitmap_next_tuple() and the
table AM is responsible for advancing to the next block when the
current block is out of tuples. In the new code structure, there isn't
much point in having a separate table_scan_bitmap_next_block()
callback. Advancing the iterator to get the next block assignment is
already pushed into the table AM itself. So, getting the next block
can be an internal detail of how the table AM gets the next tuple.
Heikki actually originally suggested it, and I thought it made sense.

- Melanie

#151Melanie Plageman
melanieplageman@gmail.com
In reply to: Alvaro Herrera (#149)
Re: BitmapHeapScan streaming read user and prelim refactoring

Thanks for taking a look at my patches, Álvaro!

On Wed, Jun 19, 2024 at 12:51 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:

On 2024-Jun-14, Melanie Plageman wrote:

Subject: [PATCH v21 12/20] Update variable names in bitmap scan descriptors

The previous commit which added BitmapTableScanDesc and
BitmapHeapScanDesc used the existing member names from TableScanDescData
and HeapScanDescData for diff clarity. This commit renames the members
-- in many cases by removing the rs_ prefix which is not relevant or
needed here.

*Cough* Why? It makes grepping for struct members useless. I'd rather
keep these prefixes, as they allow easier code exploration. (Sometimes
when I need to search for uses of some field with a name that's too
common, I add a prefix to the name and let the compiler guide me to
them. But that's a waste of time ...)

If we want to make it possible to use no tools and only manually grep
for struct members, that means we can never reuse struct member names.
Across a project of our size, that seems like a very serious
restriction. Adding prefixes in struct members makes it harder to read
code -- both because it makes the names longer and because people are
more prone to abbreviate the meaningful parts of the struct member
name to make the whole name shorter.

While I understand we as a project want to make it possible to hack on
Postgres without an IDE or a set of vim plugins a mile long, I also
think we have to make some compromises for readability. Most commonly
used text editors have LSP (language server protocol) support and
should allow for meaningful identification of the usages of a struct
member even if it has the same name as a member of another struct.

That being said, I'm not unreasonable. If we have decided we can not
reuse struct member names, I will change my patch.

- Melanie

#152Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Melanie Plageman (#147)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 19/06/2024 18:55, Melanie Plageman wrote:

On Tue, Jun 18, 2024 at 6:02 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

I went through v22 to remind myself of what the patches do and do some
basic review - I have some simple questions / comments for now, nothing
major. I've kept the comments in separate 'review' patches, it does not
seem worth copying here.

Thanks so much for the review!

I've implemented your feedback in attached v23 except for what I
mention below. I have not gone through each patch in the new set very
carefully after making the changes because I think we should resolve
the question of adding the new table scan descriptor before I do that.
A change there will require a big rebase. Then I can go through each
patch very carefully.

Had a quick look at this after a long pause. I only looked at the first
few, hoping that reviewing them would allow you to commit at least some
of them, making the rest easier.

v23-0001-table_scan_bitmap_next_block-counts-lossy-and-ex.patch

Looks good to me. (I'm not sure if this would be a net positive change
on its own, but it's needed by the later patch so OK)

v23-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patch

LGTM

v23-0003-Make-table_scan_bitmap_next_block-async-friendly.patch

@@ -1955,19 +1954,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
*/

/*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise. `lossy_pages` is incremented if the block's
- * representation in the bitmap is lossy; otherwise, `exact_pages` is
- * incremented.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise. `lossy_pages` is
+ * incremented if the block's representation in the bitmap is lossy; otherwise,
+ * `exact_pages` is incremented.
+ *
+ * `recheck` is set by the table AM to indicate whether or not the tuples
+ * from this block should be rechecked. Tuples from lossy pages will always
+ * need to be rechecked, but some non-lossy pages' tuples may also require
+ * recheck.
+ *
+ * `blockno` is only used in bitmap table scan code to validate that the
+ * prefetch block is staying ahead of the current block.
*
* Note, this is an optionally implemented function, therefore should only be
* used after verifying the presence (at plan time or such).
*/
static inline bool
table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
long *lossy_pages,
long *exact_pages)
{

The new comment doesn't really explain what *blockno means. Is it an
input or output parameter? How is it used with the prefetching?

v23-0004-Add-common-interface-for-TBMIterators.patch

+/*
+ * Start iteration on a shared or private bitmap iterator. Note that tbm will
+ * only be provided by private BitmapHeapScan callers. dsa and dsp will only be
+ * provided by parallel BitmapHeapScan callers. For shared callers, one process
+ * must already have called tbm_prepare_shared_iterate() to create and set up
+ * the TBMSharedIteratorState. The TBMIterator is passed by reference to
+ * accommodate callers who would like to allocate it inside an existing struct.
+ */
+void
+tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+				  dsa_area *dsa, dsa_pointer dsp)
+{
+	Assert(iterator);
+
+	iterator->private_iterator = NULL;
+	iterator->shared_iterator = NULL;
+	iterator->exhausted = false;
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+		iterator->shared_iterator = tbm_attach_shared_iterate(dsa, dsp);
+	else
+		iterator->private_iterator = tbm_begin_private_iterate(tbm);
+}

Hmm, I haven't looked at how this is used the later patches, but a
function signature where some parameters are used or not depending on
the situation seems a bit awkward. Perhaps it would be better to let the
caller call tbm_attach_shared_iterate(dsa, dsp) or
tbm_begin_private_iterate(tbm), and provide a function to turn that into
a TBMIterator? Something like:

TBMIterator *tbm_iterator_from_shared_iterator(TBMSharedIterator *);
TBMIterator *tbm_iterator_from_private_iterator(TBMPrivateIterator *);

Does tbm_iterator() really need the 'exhausted' flag? The private and
shared variants work without one.

+1 on this patch in general, and I have no objections to its current
form either, the above are just suggestions to consider.

v23-0006-BitmapHeapScan-uses-unified-iterator.patch

Makes sense. (Might be better to squash this with the previous patch)

v23-0007-BitmapHeapScan-Make-prefetch-sync-error-more-det.patch

LGTM

v23-0008-Push-current-scan-descriptor-into-specialized-sc.patch
v23-0009-Remove-ss_current-prefix-from-ss_currentScanDesc.patch

LGTM. I would squash these together.

v23-0010-Add-scan_in_progress-to-BitmapHeapScanState.patch

--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1804,6 +1804,7 @@ typedef struct ParallelBitmapHeapState
*		prefetch_target    current target prefetch distance
*		prefetch_maximum   maximum value for prefetch_target
*		initialized		   is node is ready to iterate
+ *		scan_in_progress   is this a rescan
*		pstate			   shared state for parallel bitmap scan
*		recheck			   do current page's tuples need recheck
*		blockno			   used to validate pf and current block in sync
@@ -1824,6 +1825,7 @@ typedef struct BitmapHeapScanState
int			prefetch_target;
int			prefetch_maximum;
bool		initialized;
+	bool		scan_in_progress;
ParallelBitmapHeapState *pstate;
bool		recheck;
BlockNumber blockno;

Hmm, the "is this a rescan" comment sounds inaccurate, because it is set
as soon as the scan is started, not only when rescanning. Other than
that, LGTM.

--
Heikki Linnakangas
Neon (https://neon.tech)

#153Robert Haas
robertmhaas@gmail.com
In reply to: Melanie Plageman (#151)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Jun 19, 2024 at 2:21 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

If we want to make it possible to use no tools and only manually grep
for struct members, that means we can never reuse struct member names.
Across a project of our size, that seems like a very serious
restriction. Adding prefixes in struct members makes it harder to read
code -- both because it makes the names longer and because people are
more prone to abbreviate the meaningful parts of the struct member
name to make the whole name shorter.

I don't think we should go so far as to never reuse a structure member
name. But I also do use 'git grep' a lot to find stuff, and I don't
appreciate it when somebody names a key piece of machinery 'x' or 'n'
or something, especially when references to that thing could
reasonably occur almost anywhere in the source code. So if somebody is
creating a struct whose names are fairly generic and reasonably short,
I like the idea of using a prefix for those names. If the structure
members are things like that_thing_i_stored_behind_the_fridge (which
is long) or cytokine (which is non-generic) then they're greppable
anyway and it doesn't really matter. But surely changing something
like rs_flags to just flags is just making everyone's life harder:

[robert.haas pgsql]$ git grep rs_flags | wc -l
38
[robert.haas pgsql]$ git grep flags | wc -l
6348

--
Robert Haas
EDB: http://www.enterprisedb.com

#154Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#153)
Re: BitmapHeapScan streaming read user and prelim refactoring

Robert Haas <robertmhaas@gmail.com> writes:

On Wed, Jun 19, 2024 at 2:21 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

If we want to make it possible to use no tools and only manually grep
for struct members, that means we can never reuse struct member names.
Across a project of our size, that seems like a very serious
restriction. Adding prefixes in struct members makes it harder to read
code -- both because it makes the names longer and because people are
more prone to abbreviate the meaningful parts of the struct member
name to make the whole name shorter.

I don't think we should go so far as to never reuse a structure member
name. But I also do use 'git grep' a lot to find stuff, and I don't
appreciate it when somebody names a key piece of machinery 'x' or 'n'
or something, especially when references to that thing could
reasonably occur almost anywhere in the source code. So if somebody is
creating a struct whose names are fairly generic and reasonably short,
I like the idea of using a prefix for those names. If the structure
members are things like that_thing_i_stored_behind_the_fridge (which
is long) or cytokine (which is non-generic) then they're greppable
anyway and it doesn't really matter. But surely changing something
like rs_flags to just flags is just making everyone's life harder:

I'm with Robert here: I care quite a lot about the greppability of
field names. I'm not arguing for prefixes everywhere, but I don't
think we should strip out prefixes we've already created, especially
if the result will be to have extremely generic field names.

regards, tom lane

#155Melanie Plageman
melanieplageman@gmail.com
In reply to: Tom Lane (#154)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Aug 26, 2024 at 10:49 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Robert Haas <robertmhaas@gmail.com> writes:

On Wed, Jun 19, 2024 at 2:21 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

If we want to make it possible to use no tools and only manually grep
for struct members, that means we can never reuse struct member names.
Across a project of our size, that seems like a very serious
restriction. Adding prefixes in struct members makes it harder to read
code -- both because it makes the names longer and because people are
more prone to abbreviate the meaningful parts of the struct member
name to make the whole name shorter.

I don't think we should go so far as to never reuse a structure member
name. But I also do use 'git grep' a lot to find stuff, and I don't
appreciate it when somebody names a key piece of machinery 'x' or 'n'
or something, especially when references to that thing could
reasonably occur almost anywhere in the source code. So if somebody is
creating a struct whose names are fairly generic and reasonably short,
I like the idea of using a prefix for those names. If the structure
members are things like that_thing_i_stored_behind_the_fridge (which
is long) or cytokine (which is non-generic) then they're greppable
anyway and it doesn't really matter. But surely changing something
like rs_flags to just flags is just making everyone's life harder:

I'm with Robert here: I care quite a lot about the greppability of
field names. I'm not arguing for prefixes everywhere, but I don't
think we should strip out prefixes we've already created, especially
if the result will be to have extremely generic field names.

Okay, got it -- folks like the prefixes.
I'm picking this patch set back up again after a long pause and I will
restore all prefixes.

What does the rs_* in the HeapScanDescData stand for, though?

- Melanie

#156Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#150)
2 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Jun 19, 2024 at 2:13 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Wed, Jun 19, 2024 at 12:38 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

+ * XXX I don't understand why we should have this special node if we
+ * don't have special nodes for other scan types.

In this case, up until the final commit (using the read stream
interface), there are six fields required by bitmap heap scan that are
not needed by any other user of HeapScanDescData. There are also
several members of HeapScanDescData that are not needed by bitmap heap
scans and all of the setup in initscan() for those fields is not
required for bitmap heap scans.

Also, because the BitmapHeapScanDesc needs information like the
ParallelBitmapHeapState and prefetch_maximum (for use in prefetching),
the scan_begin() callback would have to take those as parameters. I
thought adding so much bitmap table scan-specific information to the
generic table scan callbacks was a bad idea.

Once we add the read stream API code, the number of fields required
for bitmap heap scan that are in the scan descriptor goes down to
three. So, perhaps we could justify having that many bitmap heap
scan-specific fields in the HeapScanDescData.

Though, I actually think we could start moving toward having
specialized scan descriptors if the requirements for that scan type
are appreciably different. I can't think of new code that would be
added to the HeapScanDescData that would have to be duplicated over to
specialized scan descriptors.

With the final read stream state, I can see the argument for bloating
the HeapScanDescData with three extra members and avoiding making new
scan descriptors. But, for the intermediate patches which have all of
the bitmap prefetch members pushed down into the HeapScanDescData, I
think it is really not okay. Six members only for bitmap heap scans
and two bitmap-specific members to begin_scan() seems bad.

What I thought we plan to do is commit the refactoring patches
sometime after the branch for 18 is cut and leave the final read
stream patch uncommitted so we can do performance testing on it. If
you think it is okay to have the six member bloated HeapScanDescData
in master until we push the read stream code, I am okay with removing
the BitmapTableScanDesc and BitmapHeapScanDesc.

I admit I don't have a very good idea what the ideal / desired state
look like. My comment is motivated solely by the feeling that it seems
strange to have one struct serving most scan types, and then a special
struct for one particular scan type ...

I see what you are saying. We could make BitmapTableScanDesc inherit
from TableScanDescData which would be similar to what we do with other
things like the executor scan nodes themselves. We would waste space
and LOC with initializing the unneeded members, but it might seem less
weird.

Whether we want the specialized scan descriptors at all is probably
the bigger question, though.

The top level BitmapTableScanDesc is motivated by wanting fewer bitmap
table scan specific members passed to scan_begin(). And the
BitmapHeapScanDesc is motivated by this plus wanting to avoid bloating
the HeapScanDescData.

If you look at at HEAD~1 (with my patches applied) and think you would
be okay with
1) the contents of the BitmapHeapScanDesc being in the HeapScanDescData and
2) the extra bitmap table scan-specific parameters in scan_begin_bm()
being passed to scan_begin()

then I will remove the specialized scan descriptors.

The final state (with the read stream) will still have three bitmap
heap scan-specific members in the HeapScanDescData.

Would it help if I do a version like this so you can see what it is like?

I revisited this issue (how to keep from bloating the Heap and Table
scan descriptors and adding many parameters to the scan_begin() table
AM callback) and am trying to find a less noisy way to address it than
my previous proposal.

I've attached a prototype of what I think might work applied on top of
master instead of on top of my patchset.

For the top-level TableScanDescData, I suggest we use a union with the
members of each scan type in it in anonymous structs (see 0001). This
will avoid too much bloat because there are other scan types (like TID
Range scans) whose members we can move into the union. It isn't great,
but it avoids a new top-level scan descriptor and changes to the
generic scanstate node.

We will still have to pass the parameters needed to set up the
parallel bitmap iterators to scan_begin() in the intermediate patches,
but if we think that we can actually get the streaming read version of
bitmapheapscan in in the same release, then I think it should be okay
because the final version of these table AM callbacks do not need any
bitmap-specific members.

To address the bloat in the HeapScanDescData, I've kept the
BitmapHeapScanDesc but made it inherit from the HeapScanDescData with
a "suffix" of bitmap scan-specific members which were moved out of the
HeapScanDescData and into the BitmapHeapScanDesc (in 0002).

It's probably better to temporarily increase the parameters to
scan_begin() than to introduce new table AM callbacks and then rip
them out in a later commit.

- Melanie

Attachments:

0002-Move-BitmapHeapScan-specific-members-into-suffix.patchapplication/x-patch; name=0002-Move-BitmapHeapScan-specific-members-into-suffix.patchDownload
From 880a70639504cabf00d7d60d665f4025df3d64ef Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 25 Sep 2024 18:39:47 -0400
Subject: [PATCH 2/2] Move BitmapHeapScan-specific members into suffix

Make a new scan descriptor, BitmapHeapScanDesc, which inherits from
HeapScanDescData but has a few extra members that are specific to
BitmapHeapScans. These were in the generic HeapScanDescData but they
don't need to be. This saves space and sets the precedent that future
scan type-specific members shouldn't be put in the generic
HeapScanDescData.
---
 src/backend/access/heap/heapam.c         | 35 ++++++++++++++++--------
 src/backend/access/heap/heapam_handler.c | 12 ++++----
 src/include/access/heapam.h              | 19 ++++++++-----
 3 files changed, 42 insertions(+), 24 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index f167107257..61cb3350bd 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1036,7 +1036,15 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	/*
 	 * allocate and initialize scan descriptor
 	 */
-	scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
+	if (flags & SO_TYPE_BITMAPSCAN)
+	{
+		BitmapHeapScanDesc *bscan = palloc(sizeof(BitmapHeapScanDesc));
+		bscan->rs_vmbuffer = InvalidBuffer;
+		bscan->rs_empty_tuples_pending = 0;
+		scan = &bscan->heap;
+	}
+	else
+		scan = palloc(sizeof(HeapScanDescData));
 
 	scan->rs_base.rs_rd = relation;
 	scan->rs_base.rs_snapshot = snapshot;
@@ -1044,8 +1052,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1161,18 +1167,20 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
 	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
 	 * on rescan.
 	 */
-	scan->rs_empty_tuples_pending = 0;
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		((BitmapHeapScanDesc *) scan)->rs_empty_tuples_pending = 0;
+		if (BufferIsValid(((BitmapHeapScanDesc *) scan)->rs_vmbuffer))
+		{
+			ReleaseBuffer(((BitmapHeapScanDesc *) scan)->rs_vmbuffer);
+			((BitmapHeapScanDesc *) scan)->rs_vmbuffer = InvalidBuffer;
+		}
+	}
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1201,8 +1209,11 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (BufferIsValid(((BitmapHeapScanDesc *) scan)->rs_vmbuffer))
+			ReleaseBuffer(((BitmapHeapScanDesc *) scan)->rs_vmbuffer);
+	}
 
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 1c6da286d4..6fa1fec8f3 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,6 +2119,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  TBMIterateResult *tbmres)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) hscan;
 	BlockNumber block = tbmres->blockno;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2134,13 +2135,13 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		((BitmapHeapScanDesc *) hscan)->rs_empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2253,17 +2254,18 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) hscan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (bscan->rs_empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		bscan->rs_empty_tuples_pending--;
 		return true;
 	}
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index b92eb506ec..752bf40c5e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -92,6 +92,17 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDesc {
+	HeapScanDescData heap;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -101,13 +112,7 @@ typedef struct HeapScanDescData
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+} BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
-- 
2.45.2

0001-Example-use-of-union-in-TableScanDescData.patchapplication/x-patch; name=0001-Example-use-of-union-in-TableScanDescData.patchDownload
From ae02bbecfcdae29b80eda106b350d97048bc9dca Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 27 Sep 2024 15:51:07 -0400
Subject: [PATCH 1/2] Example use of union in TableScanDescData

For scan type-specific members of the TableScanDescData, we could store
them like this to reduce overhead.

This is just an example since bitmap table scan on master doesn't yet
need the TBMIterator
---
 src/include/access/relscan.h | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 114a85dc47..eacdf44d80 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/itup.h"
+#include "nodes/tidbitmap.h"
 #include "port/atomics.h"
 #include "storage/buf.h"
 #include "storage/relfilelocator.h"
@@ -38,8 +39,14 @@ typedef struct TableScanDescData
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
 	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
-	ItemPointerData rs_mintid;
-	ItemPointerData rs_maxtid;
+	union {
+		struct {
+			ItemPointerData rs_mintid;
+			ItemPointerData rs_maxtid;
+		};
+
+		TBMIterator *iterator;
+	};
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
-- 
2.45.2

#157Thomas Munro
thomas.munro@gmail.com
In reply to: Melanie Plageman (#156)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Sep 28, 2024 at 8:13 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

For the top-level TableScanDescData, I suggest we use a union with the
members of each scan type in it in anonymous structs (see 0001).

Just by the way, you can't use anonymous structs or unions in C99
(that was added to C11), but most compilers accept them silently
unless you use eg -std=c99. Some buildfarm animal or other would
bleat about that (ask me how I know), but out CI doesn't pick it up
:-( Maybe we should fix that. That's why you see a lot of code
around that accesses unions through a member with a name like "u",
because the author was shaking her fist at the god of standards and
steadfastly refusing to think of a name. It's a shame in cases where
you want to retrofit a union into existing code without having to
adjust the code that accesses one of the members...

#158Melanie Plageman
melanieplageman@gmail.com
In reply to: Thomas Munro (#157)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, Oct 8, 2024 at 4:56 PM Thomas Munro <thomas.munro@gmail.com> wrote:

Just by the way, you can't use anonymous structs or unions in C99
(that was added to C11), but most compilers accept them silently
unless you use eg -std=c99. Some buildfarm animal or other would
bleat about that (ask me how I know), but out CI doesn't pick it up
:-( Maybe we should fix that. That's why you see a lot of code
around that accesses unions through a member with a name like "u",
because the author was shaking her fist at the god of standards and
steadfastly refusing to think of a name. It's a shame in cases where
you want to retrofit a union into existing code without having to
adjust the code that accesses one of the members...

Wow, that is terrible news. I fact-checked this with ast-grep, and you
are right -- we don't use anonymous unions or structs.

Perhaps this isn't the time or place but 1) I was under the impression
we sometimes did things not allowed in C99 if they were really useful
2) remind me what we are waiting for to die so that we can use
features from C11?

- Melanie

#159Melanie Plageman
melanieplageman@gmail.com
In reply to: Heikki Linnakangas (#152)
12 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Aug 26, 2024 at 9:37 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

v23-0003-Make-table_scan_bitmap_next_block-async-friendly.patch

@@ -1955,19 +1954,26 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths

+ * `blockno` is only used in bitmap table scan code to validate that the
+ * prefetch block is staying ahead of the current block.
*
* Note, this is an optionally implemented function, therefore should only be
* used after verifying the presence (at plan time or such).
*/
static inline bool
table_scan_bitmap_next_block(TableScanDesc scan,
-                                                      struct TBMIterateResult *tbmres,
+                                                      BlockNumber *blockno, bool *recheck,
long *lossy_pages,
long *exact_pages)
{

The new comment doesn't really explain what *blockno means. Is it an
input or output parameter? How is it used with the prefetching?

I've updated this comment.

v23-0004-Add-common-interface-for-TBMIterators.patch

+void
+tbm_begin_iterate(TBMIterator *iterator, TIDBitmap *tbm,
+                               dsa_area *dsa, dsa_pointer dsp)
+{
+     Assert(iterator);
+
+     iterator->private_iterator = NULL;
+     iterator->shared_iterator = NULL;
+     iterator->exhausted = false;
+
+     /* Allocate a private iterator and attach the shared state to it */
+     if (DsaPointerIsValid(dsp))
+             iterator->shared_iterator = tbm_attach_shared_iterate(dsa, dsp);
+     else
+             iterator->private_iterator = tbm_begin_private_iterate(tbm);
+}

Hmm, I haven't looked at how this is used the later patches, but a
function signature where some parameters are used or not depending on
the situation seems a bit awkward. Perhaps it would be better to let the
caller call tbm_attach_shared_iterate(dsa, dsp) or
tbm_begin_private_iterate(tbm), and provide a function to turn that into
a TBMIterator? Something like:

TBMIterator *tbm_iterator_from_shared_iterator(TBMSharedIterator *);
TBMIterator *tbm_iterator_from_private_iterator(TBMPrivateIterator *);

I thought about this a lot. I've changed the struct a bit but have
left the tbm_begin_iterate() interface mostly the same. I actually
think having some parameters that are used only for parallel and some
only for serial is better than exposing the private/shared versions of
the iterators only for tbm_begin_iterate() (which I would have to do
if the caller calls
tbm_attach_shared_iterate()/tbm_begin_private_iterate() directly).

Does tbm_iterator() really need the 'exhausted' flag? The private and
shared variants work without one.

I got rid of this.

v23-0006-BitmapHeapScan-uses-unified-iterator.patch

Makes sense. (Might be better to squash this with the previous patch)

Done.

v23-0008-Push-current-scan-descriptor-into-specialized-sc.patch
v23-0009-Remove-ss_current-prefix-from-ss_currentScanDesc.patch

LGTM. I would squash these together.

I wanted to make a change that was lower impact than a new top level
scan descriptor. So, I made a few changes to the design to allow that.
Those rendered v23-0008 and v23-0009 moot.

See v24-0003 and v24-0007 for the new design. I could use input on
whether or not this strategy seems acceptable.

v23-0010-Add-scan_in_progress-to-BitmapHeapScanState.patch

--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1804,6 +1804,7 @@ typedef struct ParallelBitmapHeapState
*           prefetch_target    current target prefetch distance
*           prefetch_maximum   maximum value for prefetch_target
*           initialized                is node is ready to iterate
+ *           scan_in_progress   is this a rescan
*           pstate                     shared state for parallel bitmap scan
*           recheck                    do current page's tuples need recheck
*           blockno                    used to validate pf and current block in sync
@@ -1824,6 +1825,7 @@ typedef struct BitmapHeapScanState
int                     prefetch_target;
int                     prefetch_maximum;
bool            initialized;
+     bool            scan_in_progress;
ParallelBitmapHeapState *pstate;
bool            recheck;
BlockNumber blockno;

Hmm, the "is this a rescan" comment sounds inaccurate, because it is set
as soon as the scan is started, not only when rescanning. Other than
that, LGTM.

It turns out I didn't need scan_in_progress once I rearranged some
things anyway.

- Melanie

Attachments:

v24-0003-Make-table_scan_bitmap_next_block-async-friendly.patchapplication/octet-stream; name=v24-0003-Make-table_scan_bitmap_next_block-async-friendly.patchDownload
From 1720a0eeeb00b2b722c9cdd5a8681bd95bda0f0a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 13 Feb 2024 10:17:47 -0500
Subject: [PATCH v24 03/12] Make table_scan_bitmap_next_block() async-friendly

Move all responsibility for indicating a block is exhuasted into
table_scan_bitmap_next_tuple().

Previously, table_scan_bitmap_next_block() returned false to indicate
table_scan_bitmap_next_tuple() should not be called for the tuples on
the page. This happened when both when 1) there were no visible tuples
on the page and 2) when the block returned by the iterator was past the
end of the table. Generic bitmap table scan code handled the case when
the bitmap was exhausted.

It makes more sense for table_scan_bitmap_next_tuple() to return false
when there are no visible tuples on the page and
table_scan_bitmap_next_block() to return false when the bitmap is
exhausted or there are no more blocks in the table.

This also allows us to move responsibility for advancing the main
iterator to table-AM specific code which is a step toward using the read
stream API.

Note that the prefetch iterator is still saved in the
BitmapHeapScanState node and advanced in generic bitmap table scan code.
This is because 1) it was not necessary to change the prefetch iterator
location to change the flow control in BitmapHeapNext() 2) modifying
prefetch iterator management requires several more steps better split
over multiple commits and 3) the prefetch iterator will be removed once
the read stream API is used.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas
Discussion: https://postgr.es/m/CAAKRu_ZwCwWFeL_H3ia26bP2e7HiKLWt0ZmGXPVwPO6uXq0vaA%40mail.gmail.com
---
 src/backend/access/heap/heapam.c          |   8 +-
 src/backend/access/heap/heapam_handler.c  |  54 +++--
 src/backend/executor/nodeBitmapHeapscan.c | 237 ++++++++++++----------
 src/include/access/relscan.h              |  28 ++-
 src/include/access/tableam.h              |  53 +++--
 src/include/nodes/execnodes.h             |  12 +-
 6 files changed, 242 insertions(+), 150 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index da5e656a08..3577396507 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1387,8 +1387,8 @@ heap_set_tidrange(TableScanDesc sscan, ItemPointer mintid,
 	heap_setscanlimits(sscan, startBlk, numBlks);
 
 	/* Finally, set the TID range in sscan */
-	ItemPointerCopy(&lowestItem, &sscan->rs_mintid);
-	ItemPointerCopy(&highestItem, &sscan->rs_maxtid);
+	ItemPointerCopy(&lowestItem, &sscan->st.tidr.rs_mintid);
+	ItemPointerCopy(&highestItem, &sscan->st.tidr.rs_maxtid);
 }
 
 bool
@@ -1396,8 +1396,8 @@ heap_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction,
 						  TupleTableSlot *slot)
 {
 	HeapScanDesc scan = (HeapScanDesc) sscan;
-	ItemPointer mintid = &sscan->rs_mintid;
-	ItemPointer maxtid = &sscan->rs_maxtid;
+	ItemPointer mintid = &sscan->st.tidr.rs_mintid;
+	ItemPointer maxtid = &sscan->st.tidr.rs_maxtid;
 
 	/* Note: no locking manipulations needed */
 	for (;;)
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d4180d05b7..37845cda24 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2116,18 +2116,48 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->st.bts.shared_tbmiterator)
+			tbmres = tbm_shared_iterate(scan->st.bts.shared_tbmiterator);
+		else
+			tbmres = tbm_iterate(scan->st.bts.tbmiterator);
+
+		if (tbmres == NULL)
+			return false;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2146,16 +2176,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2250,7 +2271,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*lossy_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 1d3c92eafe..5d979a981a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,9 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -85,11 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -105,6 +96,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,8 +107,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
+			tbmiterator = tbm_begin_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -166,9 +159,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
+			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -207,46 +198,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		scan->st.bts.tbmiterator = tbmiterator;
+		scan->st.bts.shared_tbmiterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->stats.lossy_pages, &node->stats.exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -267,45 +235,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
+
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
+
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
 
 		/*
-		 * Attempt to fetch tuple from AM.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
-		}
+		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+										  &node->stats.lossy_pages, &node->stats.exact_pages))
+			break;
 
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->pfblockno < node->blockno)
+			elog(ERROR, "prefetch and main iterators are out of sync");
 
-		/* OK to return this tuple */
-		return slot;
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -331,13 +314,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -351,14 +338,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -383,7 +377,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -461,6 +458,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -518,6 +516,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->pfblockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -574,17 +574,32 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* rescan to release any page pin */
-	if (node->ss.ss_currentScanDesc)
+	TableScanDesc scan = node->ss.ss_currentScanDesc;
+
+	if (scan)
+	{
+		/*
+		 * End iteration on iterators saved in scan descriptor.
+		 */
+		if (scan->st.bts.shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scan->st.bts.shared_tbmiterator);
+			scan->st.bts.shared_tbmiterator = NULL;
+		}
+
+		if (scan->st.bts.tbmiterator)
+		{
+			tbm_end_iterate(scan->st.bts.tbmiterator);
+			scan->st.bts.tbmiterator = NULL;
+		}
+
+		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	}
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -592,13 +607,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->pfblockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -652,28 +667,40 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+	if (scanDesc)
+	{
+		/*
+		 * End iteration on iterators saved in scan descriptor.
+		 */
+		if (scanDesc->st.bts.shared_tbmiterator)
+		{
+			tbm_end_shared_iterate(scanDesc->st.bts.shared_tbmiterator);
+			scanDesc->st.bts.shared_tbmiterator = NULL;
+		}
+
+		if (scanDesc->st.bts.tbmiterator)
+		{
+			tbm_end_iterate(scanDesc->st.bts.tbmiterator);
+			scanDesc->st.bts.tbmiterator = NULL;
+		}
+
+		/*
+		 * close table scan
+		 */
+		table_endscan(scanDesc);
+	}
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -706,8 +733,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
@@ -717,9 +742,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 114a85dc47..28cfc59a86 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -25,6 +25,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -37,9 +40,28 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
-	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
-	ItemPointerData rs_mintid;
-	ItemPointerData rs_maxtid;
+	/*
+	 * Scan type-specific members
+	 */
+	union
+	{
+		/* Iterators for Bitmap Table Scans */
+		struct
+		{
+			struct TBMIterator *tbmiterator;
+			struct TBMSharedIterator *shared_tbmiterator;
+		}			bts;
+
+		/*
+		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
+		 * scan.
+		 */
+		struct
+		{
+			ItemPointerData rs_mintid;
+			ItemPointerData rs_maxtid;
+		}			tidr;
+	}			st;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d212ebd432..47cc49e1de 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "storage/read_stream.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
@@ -36,7 +37,6 @@ extern PGDLLIMPORT bool synchronize_seqscans;
 struct BulkInsertStateData;
 struct IndexInfo;
 struct SampleScanState;
-struct TBMIterateResult;
 struct VacuumParams;
 struct ValidateIndexState;
 
@@ -780,23 +780,29 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
 	 * make sense to perform tuple visibility checks at this time).
 	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
-	 *
 	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
 	 * incremented by the table AM to indicate whether or not the block's
 	 * representation in the bitmap is lossy.
 	 *
+	 * `recheck` is set by the table AM to indicate whether or not the tuples
+	 * from this block should be rechecked. Tuples from lossy pages will
+	 * always need to be rechecked, but some non-lossy pages' tuples may also
+	 * require recheck.
+	 *
+	 * `blockno` is the current block and is set by the table AM. The table AM
+	 * is responsible for advancing the main iterator, but the bitmap table
+	 * scan code still advances the prefetch iterator. `blockno` is used by
+	 * bitmap table scan code to validate that the prefetch block stays ahead
+	 * of the current block.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -812,7 +818,7 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno, bool *recheck,
 										   uint64 *lossy_pages, uint64 *exact_pages);
 
 	/*
@@ -950,12 +956,16 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result->st.bts.shared_tbmiterator = NULL;
+	result->st.bts.tbmiterator = NULL;
+	return result;
 }
 
 /*
@@ -1946,21 +1956,27 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
- * bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false if
+ * there are no more blocks in the bitmap, true otherwise.
  *
  * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be incremented
  * by the table AM to indicate whether or not the block's representation in the
  * bitmap is lossy.
  *
+ * `recheck` is set by the table AM to indicate whether or not the tuples
+ * from this block should be rechecked.
+ *
+ * `blockno` is the current block and is set by the table AM and is used by
+ * bitmap table scan code to validate that the prefetch block stays ahead of
+ * the current block.
+ *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno, bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
 {
@@ -1973,9 +1989,8 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
-														   lossy_pages,
-														   exact_pages);
+														   blockno, recheck,
+														   lossy_pages, exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e4698a28c4..c7a6ad31a7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1833,8 +1833,6 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1842,10 +1840,12 @@ typedef struct SharedBitmapHeapInstrumentation
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block in sync
+ *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1853,8 +1853,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
 	TBMIterator *prefetch_iterator;
@@ -1862,10 +1860,12 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.45.2

v24-0001-table_scan_bitmap_next_block-implementations-cou.patchapplication/octet-stream; name=v24-0001-table_scan_bitmap_next_block-implementations-cou.patchDownload
From df2655612a0a32d33fa144f3e48d0a2c63505e62 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v24 01/12] table_scan_bitmap_next_block implementations count
 lossy and exact pages

Keep track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap in table AM-specific code. These
counters are used for EXPLAIN.

This is a step toward removing TBMIterateResults as a flow control
mechanism in BitmapHeapNext(), which is required for a more asynchronous
design. It also is more table AM-agnostic.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Heikki Linnakangas
Discussion: https://postgr.es/m/063e4eb4-32d9-439e-a0b1-75565a9835a8%40iki.fi
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 12 ++----------
 src/include/access/tableam.h              | 23 ++++++++++++++++++-----
 3 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 1c6da286d4..0ab3526d95 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2116,7 +2116,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2244,6 +2245,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3c63bdd93d..988fac261e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,8 +212,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -233,14 +231,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->stats.exact_pages++;
-			else
-				node->stats.lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->stats.lossy_pages, &node->stats.exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index da661289c1..f87688c480 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -796,6 +796,10 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
+	 * incremented by the table AM to indicate whether or not the block's
+	 * representation in the bitmap is lossy.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -811,7 +815,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   uint64 *lossy_pages, uint64 *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1949,17 +1954,23 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of a
+ * bitmap table scan. `scan` needs to have been started via
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
  * the page, true otherwise.
  *
+ * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be incremented
+ * by the table AM to indicate whether or not the block's representation in the
+ * bitmap is lossy.
+ *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 uint64 *lossy_pages,
+							 uint64 *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1970,7 +1981,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.45.2

v24-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchapplication/octet-stream; name=v24-0002-Remove-table_scan_bitmap_next_tuple-parameter-tb.patchDownload
From 581cf63f6803b25eaa60807c17736752e08be9a6 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v24 02/12] Remove table_scan_bitmap_next_tuple parameter
 tbmres

In order to remove TBMIterateResults as a flow control mechanism in
BitmapHeapNext(), they can no longer be used as a means of communication
between table_scan_bitmap_next_tuple() and
table_scan_bitmap_next_block().

Remove the TBMIterateResult parameter from
table_scan_bitmap_next_tuple().

Note that this parameter was unused by heap AM's implementation of
table_scan_bitmap_next_tuple().

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Mark Dilger, Heikki Linnakangas
Discussion: https://postgr.es/m/063e4eb4-32d9-439e-a0b1-75565a9835a8%40iki.fi
---
 src/backend/access/heap/heapam_handler.c  |  1 -
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/include/access/tableam.h              | 12 +-----------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 0ab3526d95..d4180d05b7 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2255,7 +2255,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 988fac261e..1d3c92eafe 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -281,7 +281,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 		/*
 		 * Attempt to fetch tuple from AM.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
+		if (!table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/* nothing more to look at on this page */
 			node->tbmres = tbmres = NULL;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index f87688c480..d212ebd432 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -787,10 +787,7 @@ typedef struct TableAmRoutine
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
 	 * on the page have to be returned, otherwise the tuples at offsets in
@@ -822,15 +819,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -1996,7 +1988,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2008,7 +1999,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
-- 
2.45.2

v24-0004-Add-common-interface-for-TBMIterators.patchapplication/octet-stream; name=v24-0004-Add-common-interface-for-TBMIterators.patchDownload
From 66e86eea838b39f31ad1d7166d75a883c8201490 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:41:05 -0400
Subject: [PATCH v24 04/12] Add common interface for TBMIterators

Add and use TBMPrivateIterator, which replaces the current TBMIterator
for serial use cases, and repurpose TBMIterator to be a unified
interface for both the serial ("private") and parallel ("shared") TID
Bitmap iterator interfaces. This encapsulation simplifies call sites for
callers supporting both parallel and serial TID Bitmap access.
TBMIterator is not yet used in this commit.

Author: Melanie Plageman
Reviewed-by: Heikki Linnakangas
Discussion: https://postgr.es/m/063e4eb4-32d9-439e-a0b1-75565a9835a8%40iki.fi
---
 src/backend/access/gin/ginget.c           |   8 +-
 src/backend/access/gin/ginscan.c          |   2 +-
 src/backend/access/heap/heapam_handler.c  |   2 +-
 src/backend/executor/nodeBitmapHeapscan.c |  26 +++---
 src/backend/nodes/tidbitmap.c             | 109 +++++++++++++++++-----
 src/include/access/gin_private.h          |   2 +-
 src/include/access/relscan.h              |   4 +-
 src/include/nodes/execnodes.h             |   2 +-
 src/include/nodes/tidbitmap.h             |  30 +++++-
 src/tools/pgindent/typedefs.list          |   1 +
 10 files changed, 135 insertions(+), 51 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb..9c53ca19f0 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,7 @@ restartScanEntry:
 			if (entry->matchBitmap)
 			{
 				if (entry->matchIterator)
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -385,7 +385,7 @@ restartScanEntry:
 
 		if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
 		{
-			entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+			entry->matchIterator = tbm_begin_private_iterate(entry->matchBitmap);
 			entry->isFinished = false;
 		}
 	}
@@ -832,12 +832,12 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				entry->matchResult = tbm_private_iterate(entry->matchIterator);
 
 				if (entry->matchResult == NULL)
 				{
 					ItemPointerSetInvalid(&entry->curItem);
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
 					entry->isFinished = true;
 					break;
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index f2fd62afbb..2c6631c914 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -246,7 +246,7 @@ ginFreeScanKeys(GinScanOpaque so)
 		if (entry->list)
 			pfree(entry->list);
 		if (entry->matchIterator)
-			tbm_end_iterate(entry->matchIterator);
+			tbm_end_private_iterate(entry->matchIterator);
 		if (entry->matchBitmap)
 			tbm_free(entry->matchBitmap);
 	}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 37845cda24..d8df699abf 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2139,7 +2139,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (scan->st.bts.shared_tbmiterator)
 			tbmres = tbm_shared_iterate(scan->st.bts.shared_tbmiterator);
 		else
-			tbmres = tbm_iterate(scan->st.bts.tbmiterator);
+			tbmres = tbm_private_iterate(scan->st.bts.tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5d979a981a..319da4c45c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,7 +96,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
+		TBMPrivateIterator *tbmiterator = NULL;
 		TBMSharedIterator *shared_tbmiterator = NULL;
 
 		if (!pstate)
@@ -107,12 +107,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_private_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
+				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
 				node->prefetch_pages = 0;
 				node->prefetch_target = -1;
 			}
@@ -279,7 +279,7 @@ new_page:
 			break;
 
 		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * If private, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
@@ -328,7 +328,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
@@ -338,7 +338,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		else if (prefetch_iterator)
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = tbm_private_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -441,19 +441,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_private_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
+					tbm_end_private_iterate(prefetch_iterator);
 					node->prefetch_iterator = NULL;
 					break;
 				}
@@ -589,7 +589,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 		if (scan->st.bts.tbmiterator)
 		{
-			tbm_end_iterate(scan->st.bts.tbmiterator);
+			tbm_end_private_iterate(scan->st.bts.tbmiterator);
 			scan->st.bts.tbmiterator = NULL;
 		}
 
@@ -599,7 +599,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 	/* release bitmaps and buffers if any */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -680,7 +680,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 
 		if (scanDesc->st.bts.tbmiterator)
 		{
-			tbm_end_iterate(scanDesc->st.bts.tbmiterator);
+			tbm_end_private_iterate(scanDesc->st.bts.tbmiterator);
 			scanDesc->st.bts.tbmiterator = NULL;
 		}
 
@@ -694,7 +694,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * release bitmaps and buffers if any
 	 */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->shared_prefetch_iterator)
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fc..ab10d13137 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -170,12 +170,12 @@ struct TIDBitmap
 };
 
 /*
- * When iterating over a bitmap in sorted order, a TBMIterator is used to
- * track our progress.  There can be several iterators scanning the same
- * bitmap concurrently.  Note that the bitmap becomes read-only as soon as
- * any iterator is created.
+ * When iterating over a backend-local bitmap in sorted order, a
+ * TBMPrivateIterator is used to track our progress.  There can be several
+ * iterators scanning the same bitmap concurrently.  Note that the bitmap
+ * becomes read-only as soon as any iterator is created.
  */
-struct TBMIterator
+struct TBMPrivateIterator
 {
 	TIDBitmap  *tbm;			/* TIDBitmap we're iterating over */
 	int			spageptr;		/* next spages index */
@@ -213,8 +213,8 @@ typedef struct PTIterationArray
 } PTIterationArray;
 
 /*
- * same as TBMIterator, but it is used for joint iteration, therefore this
- * also holds a reference to the shared state.
+ * same as TBMPrivateIterator, but it is used for joint iteration, therefore
+ * this also holds a reference to the shared state.
  */
 struct TBMSharedIterator
 {
@@ -673,31 +673,31 @@ tbm_is_empty(const TIDBitmap *tbm)
 }
 
 /*
- * tbm_begin_iterate - prepare to iterate through a TIDBitmap
+ * tbm_begin_private_iterate - prepare to iterate through a TIDBitmap
  *
- * The TBMIterator struct is created in the caller's memory context.
- * For a clean shutdown of the iteration, call tbm_end_iterate; but it's
- * okay to just allow the memory context to be released, too.  It is caller's
- * responsibility not to touch the TBMIterator anymore once the TIDBitmap
+ * The TBMPrivateIterator struct is created in the caller's memory context. For
+ * a clean shutdown of the iteration, call tbm_end_iterate; but it's okay to
+ * just allow the memory context to be released, too.  It is caller's
+ * responsibility not to touch the TBMPrivateIterator anymore once the TIDBitmap
  * is freed.
  *
  * NB: after this is called, it is no longer allowed to modify the contents
  * of the bitmap.  However, you can call this multiple times to scan the
  * contents repeatedly, including parallel scans.
  */
-TBMIterator *
-tbm_begin_iterate(TIDBitmap *tbm)
+TBMPrivateIterator *
+tbm_begin_private_iterate(TIDBitmap *tbm)
 {
-	TBMIterator *iterator;
+	TBMPrivateIterator *iterator;
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
 	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
+	 * Create the TBMPrivateIterator struct, with enough trailing space to
+	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
+											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
 	iterator->tbm = tbm;
 
 	/*
@@ -956,7 +956,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 }
 
 /*
- * tbm_iterate - scan through next page of a TIDBitmap
+ * tbm_private_iterate - scan through next page of a TIDBitmap
  *
  * Returns a TBMIterateResult representing one page, or NULL if there are
  * no more pages to scan.  Pages are guaranteed to be delivered in numerical
@@ -968,7 +968,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  * testing, recheck is always set true when ntuples < 0.)
  */
 TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+tbm_private_iterate(TBMPrivateIterator *iterator)
 {
 	TIDBitmap  *tbm = iterator->tbm;
 	TBMIterateResult *output = &(iterator->output);
@@ -1136,14 +1136,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 }
 
 /*
- * tbm_end_iterate - finish an iteration over a TIDBitmap
+ * tbm_end_private_iterate - finish an iteration over a TIDBitmap
  *
  * Currently this is just a pfree, but it might do more someday.  (For
  * instance, it could be useful to count open iterators and allow the
  * bitmap to return to read/write status when there are no more iterators.)
  */
 void
-tbm_end_iterate(TBMIterator *iterator)
+tbm_end_private_iterate(TBMPrivateIterator *iterator)
 {
 	pfree(iterator);
 }
@@ -1556,3 +1556,66 @@ tbm_calculate_entries(double maxbytes)
 
 	return nbuckets;
 }
+
+/*
+ * Create a shared or private bitmap iterator and start iteration.
+ *
+ * `tbm` is only used to create the private iterator and dsa and dsp are only
+ * used to create the shared iterator.
+ *
+ * Before invoking tbm_begin_iterate() to create a shared iterator, one process
+ * must already have invoked tbm_prepare_shared_iterate() to create and set up
+ * the TBMSharedIteratorState.
+ */
+TBMIterator
+tbm_begin_iterate(TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp)
+{
+	TBMIterator iterator = {0};
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+	{
+		iterator.shared = true;
+		iterator.shared_iterator = tbm_attach_shared_iterate(dsa, dsp);
+	}
+	else
+	{
+		iterator.shared = false;
+		iterator.private_iterator = tbm_begin_private_iterate(tbm);
+	}
+
+	return iterator;
+}
+
+/*
+ * Clean up shared or private bitmap iterator.
+ */
+void
+tbm_end_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->shared)
+		tbm_end_shared_iterate(iterator->shared_iterator);
+	else
+		tbm_end_private_iterate(iterator->private_iterator);
+
+	*iterator = (TBMIterator)
+	{
+		0
+	};
+}
+
+/*
+ * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ */
+TBMIterateResult *
+tbm_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->shared)
+		return tbm_shared_iterate(iterator->shared_iterator);
+	else
+		return tbm_private_iterate(iterator->private_iterator);
+}
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae..7880050936 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
-	TBMIterator *matchIterator;
+	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 28cfc59a86..63b775cd06 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -25,7 +25,7 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
+struct TBMPrivateIterator;
 struct TBMSharedIterator;
 
 /*
@@ -48,7 +48,7 @@ typedef struct TableScanDescData
 		/* Iterators for Bitmap Table Scans */
 		struct
 		{
-			struct TBMIterator *tbmiterator;
+			struct TBMPrivateIterator *tbmiterator;
 			struct TBMSharedIterator *shared_tbmiterator;
 		}			bts;
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index c7a6ad31a7..0905827bb1 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1855,7 +1855,7 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator *prefetch_iterator;
+	TBMPrivateIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639b..65ecc5ba04 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -32,10 +32,24 @@
  */
 typedef struct TIDBitmap TIDBitmap;
 
-/* Likewise, TBMIterator is private */
-typedef struct TBMIterator TBMIterator;
+/* Likewise, TBMPrivateIterator is private */
+typedef struct TBMPrivateIterator TBMPrivateIterator;
 typedef struct TBMSharedIterator TBMSharedIterator;
 
+/*
+ * Callers with both private and shared implementations can use this unified
+ * API.
+ */
+typedef struct TBMIterator
+{
+	bool		shared;
+	union
+	{
+		TBMPrivateIterator *private_iterator;
+		TBMSharedIterator *shared_iterator;
+	};
+} TBMIterator;
+
 /* Result structure for tbm_iterate */
 typedef struct TBMIterateResult
 {
@@ -62,14 +76,20 @@ extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
-extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
 extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
-extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
 													dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
+									 dsa_area *dsa, dsa_pointer dsp);
+extern void tbm_end_iterate(TBMIterator *iterator);
+
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+
 #endif							/* TIDBITMAP_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 57de1acff3..f219e806c8 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2806,6 +2806,7 @@ TAR_MEMBER
 TBMIterateResult
 TBMIteratingState
 TBMIterator
+TBMPrivateIterator
 TBMSharedIterator
 TBMSharedIteratorState
 TBMStatus
-- 
2.45.2

v24-0005-Bitmap-Table-Scans-use-unified-TBMIterator.patchapplication/octet-stream; name=v24-0005-Bitmap-Table-Scans-use-unified-TBMIterator.patchDownload
From 0b19ef0b6822c6ac849dde7f03ea536cf75417e9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:39:04 -0400
Subject: [PATCH v24 05/12] Bitmap Table Scans use unified TBMIterator

With the repurposing of TBMIterator as an interface for both parallel
and serial iteration through TIDBitmaps in commit [XXX: put commit
here], bitmap table scans may now use it.

Modify bitmap table scan code to use the TBMIterator. This requires
moving around a bit of code, so a few variables are initialized
elsewhere.
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 166 +++++++++-------------
 src/include/access/relscan.h              |  12 +-
 src/include/access/tableam.h              |   6 +-
 src/include/nodes/execnodes.h             |   4 +-
 src/include/nodes/tidbitmap.h             |  10 ++
 6 files changed, 83 insertions(+), 120 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d8df699abf..2d4143ca70 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2136,10 +2136,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->st.bts.shared_tbmiterator)
-			tbmres = tbm_shared_iterate(scan->st.bts.shared_tbmiterator);
-		else
-			tbmres = tbm_private_iterate(scan->st.bts.tbmiterator);
+		tbmres = tbm_iterate(&scan->st.tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 319da4c45c..fb747cb9e2 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,8 +96,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMPrivateIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		TBMIterator tbmiterator;
 
 		if (!pstate)
 		{
@@ -107,69 +106,60 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_private_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
+				node->prefetch_iterator = tbm_begin_iterate(node->tbm, dsa,
+															pstate ?
+															pstate->prefetch_iterator :
+															InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 		}
-		else
+		else if (BitmapShouldInitializeSharedState(pstate))
 		{
 			/*
 			 * The leader will immediately come out of the function, but
 			 * others will be blocked until leader populates the TBM and wakes
 			 * them up.
 			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
+			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			if (!tbm || !IsA(tbm, TIDBitmap))
+				elog(ERROR, "unrecognized result from subplan");
 
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
+			node->tbm = tbm;
 
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator = tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+				pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(tbm);
 			}
 #endif							/* USE_PREFETCH */
+
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(pstate);
 		}
 
+		tbmiterator = tbm_begin_iterate(tbm, dsa,
+										pstate ?
+										pstate->tbmiterator :
+										InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+			node->prefetch_iterator = tbm_begin_iterate(tbm, dsa,
+														pstate ?
+														pstate->prefetch_iterator :
+														InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -198,8 +188,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->st.bts.tbmiterator = tbmiterator;
-		scan->st.bts.shared_tbmiterator = shared_tbmiterator;
+		scan->st.tbmiterator = tbmiterator;
 		node->initialized = true;
 
 		goto new_page;
@@ -283,7 +272,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!tbm_exhausted(&node->prefetch_iterator) &&
 			node->pfblockno < node->blockno)
 			elog(ERROR, "prefetch and main iterators are out of sync");
 
@@ -328,17 +317,17 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!tbm_exhausted(prefetch_iterator))
 		{
 			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_private_iterate(prefetch_iterator);
+			tbmpre = tbm_iterate(prefetch_iterator);
 			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
@@ -355,7 +344,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -376,9 +365,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
@@ -441,20 +430,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!tbm_exhausted(prefetch_iterator))
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_private_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_private_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -482,9 +470,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!tbm_exhausted(prefetch_iterator))
 		{
 			while (1)
 			{
@@ -507,12 +495,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -581,39 +568,30 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		if (scan->st.bts.shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scan->st.bts.shared_tbmiterator);
-			scan->st.bts.shared_tbmiterator = NULL;
-		}
-
-		if (scan->st.bts.tbmiterator)
-		{
-			tbm_end_private_iterate(scan->st.bts.tbmiterator);
-			scan->st.bts.tbmiterator = NULL;
-		}
+		tbm_end_iterate(&scan->st.tbmiterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
+	/* If we did not already clean up the prefetch iterator, do so now. */
+	if (!tbm_exhausted(&node->prefetch_iterator))
+		tbm_end_iterate(&node->prefetch_iterator);
+
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
 	node->blockno = InvalidBlockNumber;
 	node->pfblockno = InvalidBlockNumber;
+	/* Only used for serial BHS */
+	node->prefetch_pages = 0;
+	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -672,17 +650,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		if (scanDesc->st.bts.shared_tbmiterator)
-		{
-			tbm_end_shared_iterate(scanDesc->st.bts.shared_tbmiterator);
-			scanDesc->st.bts.shared_tbmiterator = NULL;
-		}
-
-		if (scanDesc->st.bts.tbmiterator)
-		{
-			tbm_end_private_iterate(scanDesc->st.bts.tbmiterator);
-			scanDesc->st.bts.tbmiterator = NULL;
-		}
+		tbm_end_iterate(&scanDesc->st.tbmiterator);
 
 		/*
 		 * close table scan
@@ -690,15 +658,15 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
+	/* If we did not already clean up the prefetch iterator, do so now. */
+	if (!tbm_exhausted(&node->prefetch_iterator))
+		tbm_end_iterate(&node->prefetch_iterator);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -738,11 +706,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
+	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
@@ -901,7 +867,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -938,6 +904,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
+	pstate->prefetch_pages = 0;
+	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 63b775cd06..e014abcdc7 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/itup.h"
+#include "nodes/tidbitmap.h"
 #include "port/atomics.h"
 #include "storage/buf.h"
 #include "storage/relfilelocator.h"
@@ -25,9 +26,6 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMPrivateIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -45,12 +43,8 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterators for Bitmap Table Scans */
-		struct
-		{
-			struct TBMPrivateIterator *tbmiterator;
-			struct TBMSharedIterator *shared_tbmiterator;
-		}			bts;
+		/* Iterator for Bitmap Table Scans */
+		TBMIterator tbmiterator;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 47cc49e1de..b0f1a79623 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -956,16 +956,12 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
-	result->st.bts.shared_tbmiterator = NULL;
-	result->st.bts.tbmiterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0905827bb1..2def5895fe 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1840,7 +1840,6 @@ typedef struct SharedBitmapHeapInstrumentation
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
@@ -1855,12 +1854,11 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMPrivateIterator *prefetch_iterator;
+	TBMIterator prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 65ecc5ba04..db678d541f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -92,4 +92,14 @@ extern void tbm_end_iterate(TBMIterator *iterator);
 
 extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
 
+static inline bool
+tbm_exhausted(TBMIterator *iterator)
+{
+	/*
+	 * It doesn't matter if we check the private or shared iterator here. If
+	 * tbm_end_iterate() was called, they will be NULL
+	 */
+	return !iterator->private_iterator;
+}
+
 #endif							/* TIDBITMAP_H */
-- 
2.45.2

v24-0008-Lift-and-Shift-Bitmap-Table-Scan-prefetch-functi.patchapplication/octet-stream; name=v24-0008-Lift-and-Shift-Bitmap-Table-Scan-prefetch-functi.patchDownload
From b7171f2cbb1dd6842c3155401327f1f2e601a391 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 9 Oct 2024 07:55:47 -0400
Subject: [PATCH v24 08/12] Lift and Shift Bitmap Table Scan prefetch functions

This is a temporary commit. For ease of review, move the Bitmap Table
Scan prefetch functions into heapam_handler.c without modifying them.
The next commit will push the prefetching code into heap-specific code.
Separating the commit which moves to the functions to heapam_handler.c
and the one which modifies them and their callers to contain bitmap
prefetch code in heap AM-specific code makes it easier to see what has
changed. Doing so requires including heap code in nodeBitmapHeapscan.c,
which is not okay for the final code that is committed.
---
 src/backend/access/heap/heapam_handler.c  | 219 +++++++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 225 +---------------------
 src/include/access/heapam.h               |   7 +
 3 files changed, 228 insertions(+), 223 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6b943bf5c6..04f8adc71e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2611,6 +2611,225 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (node->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			node->prefetch_pages--;
+		}
+		else if (!tbm_exhausted(prefetch_iterator))
+		{
+			/* Do not let the prefetch iterator get behind the main one */
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
+	if (node->prefetch_maximum > 0)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!tbm_exhausted(prefetch_iterator))
+			{
+				tbmpre = tbm_iterate(prefetch_iterator);
+				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (node->prefetch_target >= node->prefetch_maximum / 2)
+			node->prefetch_target = node->prefetch_maximum;
+		else if (node->prefetch_target > 0)
+			node->prefetch_target *= 2;
+		else
+			node->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < node->prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+void
+BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!tbm_exhausted(prefetch_iterator))
+		{
+			while (node->prefetch_pages < node->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+				node->prefetch_pages++;
+				node->pfblockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!tbm_exhausted(prefetch_iterator))
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = tbm_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				node->pfblockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d7944eccd5..4eae377d91 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,6 +37,8 @@
 
 #include <math.h>
 
+/* XXX: temporary include so prefetch lift and shift works */
+#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -51,10 +53,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -301,225 +299,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			/* Do not let the prefetch iterator get behind the main one */
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->pfblockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 13e9986e86..d5f8cd5eef 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -22,6 +22,8 @@
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
 #include "nodes/lockoptions.h"
+/* XXX: temporary include so prefetch lift and shift works */
+#include "nodes/execnodes.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
 #include "storage/dsm.h"
@@ -423,6 +425,11 @@ extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
 extern bool HeapTupleIsSurelyDead(HeapTuple htup,
 								  struct GlobalVisState *vistest);
 
+/* in heapam_handler.c */
+extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
+extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+extern void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan);
+
 /*
  * To avoid leaking too much knowledge about reorderbuffer implementation
  * details this is implemented in reorderbuffer.c not heapam_visibility.c
-- 
2.45.2

v24-0007-Add-and-use-BitmapHeapScanDesc-struct.patchapplication/octet-stream; name=v24-0007-Add-and-use-BitmapHeapScanDesc-struct.patchDownload
From 13b5ea14ac9167503b22883d6aba1a3d607cdfb5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 8 Oct 2024 18:56:40 -0400
Subject: [PATCH v24 07/12] Add and use BitmapHeapScanDesc struct

Move the several members of HeapScanDesc which are specific to Bitmap
Heap Scans into a new struct BitmapHeapScanDesc which inherits from
HeapScanDesc.

This reduces the size of the HeapScanDesc for other types of scans and
will allow us to add additional bitmap heap scan-specific members in
the future without fear of bloating the HeapScanDesc.
---
 src/backend/access/heap/heapam.c         | 50 ++++++++++++++++--------
 src/backend/access/heap/heapam_handler.c | 16 ++++----
 src/include/access/heapam.h              | 23 +++++++----
 src/tools/pgindent/typedefs.list         |  1 +
 4 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 3577396507..3452634040 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1045,7 +1045,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	/*
 	 * allocate and initialize scan descriptor
 	 */
-	scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
+	if (flags & SO_TYPE_BITMAPSCAN)
+	{
+		BitmapHeapScanDesc *bscan = palloc(sizeof(BitmapHeapScanDesc));
+
+		bscan->rs_vmbuffer = InvalidBuffer;
+		bscan->rs_empty_tuples_pending = 0;
+		scan = &bscan->rs_heap_base;
+	}
+	else
+		scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
 
 	scan->rs_base.rs_rd = relation;
 	scan->rs_base.rs_snapshot = snapshot;
@@ -1053,8 +1062,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1170,18 +1177,23 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
+		BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
 
-	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
-	 */
-	scan->rs_empty_tuples_pending = 0;
+		/*
+		 * Reset empty_tuples_pending, a field only used by bitmap heap scan,
+		 * to avoid incorrectly emitting NULL-filled tuples from a previous
+		 * scan on rescan.
+		 */
+		bscan->rs_empty_tuples_pending = 0;
+
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+	}
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1210,9 +1222,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
@@ -1236,6 +1245,15 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) sscan;
+
+		bscan->rs_empty_tuples_pending = 0;
+		if (BufferIsValid(bscan->rs_vmbuffer))
+			ReleaseBuffer(bscan->rs_vmbuffer);
+	}
+
 	pfree(scan);
 }
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2d4143ca70..6b943bf5c6 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,7 +2119,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  BlockNumber *blockno, bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
+	HeapScanDesc hscan = &bscan->rs_heap_base;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2162,13 +2163,13 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2282,18 +2283,19 @@ static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
+	HeapScanDesc hscan = &bscan->rs_heap_base;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (bscan->rs_empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		bscan->rs_empty_tuples_pending--;
 		return true;
 	}
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index b951466ced..13e9986e86 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -92,22 +92,29 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDesc
+{
+	HeapScanDescData rs_heap_base;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
+
+	/* page of VM containing info for current block */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+} BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index f219e806c8..8804525276 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -263,6 +263,7 @@ BitmapAndState
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanInstrumentation
+BitmapHeapScanDesc
 BitmapHeapScanState
 BitmapIndexScan
 BitmapIndexScanState
-- 
2.45.2

v24-0010-Move-BitmapTableScan-per-scan-setup-into-a-helpe.patchapplication/octet-stream; name=v24-0010-Move-BitmapTableScan-per-scan-setup-into-a-helpe.patchDownload
From 5c392b74794065b57adfc02afad0863be849a392 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 9 Oct 2024 15:25:03 -0400
Subject: [PATCH v24 10/12] Move BitmapTableScan per-scan setup into a helper

Add BitmapTableScanSetup() which contains all of the code that must be
done on every scan of the table in a bitmap table scan.
This includes scanning the index, building the bitmap, and setting up
the scan descriptors.

Much of BitmapHeapNext() code was this setup, so it made sense to put it
in a helper function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 220 +++++++++++-----------
 1 file changed, 106 insertions(+), 114 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 21ceff5310..ca22cd4196 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -54,150 +54,142 @@ static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *ps
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
-/* ----------------------------------------------------------------
- *		BitmapHeapNext
- *
- *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
- * ----------------------------------------------------------------
+/*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
  */
-static TupleTableSlot *
-BitmapHeapNext(BitmapHeapScanState *node)
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TIDBitmap  *tbm;
-	TupleTableSlot *slot;
+	TBMIterator tbmiterator = {0};
+	TBMIterator prefetch_iterator = {0};
+	int			prefetch_maximum;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
+	Relation	rel = node->ss.ss_currentRelation;
 
 	/*
-	 * extract necessary information from index scan node
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
 	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
+	prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
 
-	/*
-	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
-	 */
-	if (!node->initialized)
+	if (!pstate)
 	{
-		TBMIterator tbmiterator;
-		int			prefetch_maximum;
-		Relation	rel = node->ss.ss_currentRelation;
-#ifdef USE_PREFETCH
-		TBMIterator prefetch_iterator = {0};
-#endif							/* USE_PREFETCH */
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+	}
+	else if (BitmapShouldInitializeSharedState(pstate))
+	{
 		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
 		 */
-		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
 
-		if (!pstate)
-		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		/*
+		 * Prepare to iterate over the TBM. This will return the dsa_pointer
+		 * of the iterator state which will be used by multiple processes to
+		 * iterate jointly.
+		 */
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
+		/*
+		 * For prefetching, we use *two* iterators, one for the pages we are
+		 * actually scanning and another that runs ahead of the first for
+		 * prefetching.  node->prefetch_pages tracks exactly how many pages
+		 * ahead the prefetch iterator is.  Also, node->prefetch_target tracks
+		 * the desired prefetch distance, which starts small and increases up
+		 * to the node->prefetch_maximum.  This is to avoid doing a lot of
+		 * prefetching in a scan that stops after a few tuples because of a
+		 * LIMIT.
+		 */
+#ifdef USE_PREFETCH
+		if (prefetch_maximum > 0)
+			pstate->prefetch_iterator =
+				tbm_prepare_shared_iterate(node->tbm);
+#endif
 
-			node->tbm = tbm;
-		}
-		else if (BitmapShouldInitializeSharedState(pstate))
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
+		/* We have initialized the shared state so wake up others. */
+		BitmapDoneInitializingSharedState(pstate);
+	}
 
-			node->tbm = tbm;
-
-			/*
-			 * Prepare to iterate over the TBM. This will return the
-			 * dsa_pointer of the iterator state which will be used by
-			 * multiple processes to iterate jointly.
-			 */
-			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+	tbmiterator = tbm_begin_iterate(node->tbm, dsa,
+									pstate ?
+									pstate->tbmiterator :
+									InvalidDsaPointer);
 
 #ifdef USE_PREFETCH
-			if (prefetch_maximum > 0)
-			{
-				pstate->prefetch_iterator =
-					tbm_prepare_shared_iterate(tbm);
-			}
+	if (prefetch_maximum > 0)
+		prefetch_iterator = tbm_begin_iterate(node->tbm, dsa,
+											  pstate ?
+											  pstate->prefetch_iterator :
+											  InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 
-			/* We have initialized the shared state so wake up others. */
-			BitmapDoneInitializingSharedState(pstate);
-		}
-
-		tbmiterator = tbm_begin_iterate(tbm, dsa,
-										pstate ?
-										pstate->tbmiterator :
-										InvalidDsaPointer);
-#ifdef USE_PREFETCH
-		if (prefetch_maximum > 0)
-			prefetch_iterator = tbm_begin_iterate(tbm, dsa,
-												  pstate ?
-												  pstate->prefetch_iterator :
-												  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!node->ss.ss_currentScanDesc)
+	{
+		bool		need_tuples = false;
 
 		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
 		 */
-		if (!scan)
-		{
-			bool		need_tuples = false;
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
+		node->ss.ss_currentScanDesc = table_beginscan_bm(node->ss.ss_currentRelation,
+														 node->ss.ps.state->es_snapshot,
+														 pstate,
+														 0,
+														 NULL,
+														 need_tuples,
+														 prefetch_maximum);
+	}
 
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  pstate,
-									  0,
-									  NULL,
-									  need_tuples,
-									  prefetch_maximum);
-
-			node->ss.ss_currentScanDesc = scan;
-		}
+	node->ss.ss_currentScanDesc->st.bts.tbmiterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bts.prefetch_iterator = prefetch_iterator;
+	node->initialized = true;
+}
 
-		scan->st.bts.tbmiterator = tbmiterator;
-		scan->st.bts.prefetch_iterator = prefetch_iterator;
-		node->initialized = true;
+/* ----------------------------------------------------------------
+ *		BitmapHeapNext
+ *
+ *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+BitmapHeapNext(BitmapHeapScanState *node)
+{
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
+	/*
+	 * If we haven't yet performed the underlying index scan, do it, and begin
+	 * the iteration over the bitmap.
+	 */
+	if (!node->initialized)
+	{
+		/* BitmapTableScanSetup sets node->ss.ss_currentScanDesc */
+		BitmapTableScanSetup(node);
 		goto new_page;
 	}
 
 	for (;;)
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
+		while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
@@ -231,7 +223,7 @@ new_page:
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck,
+		if (!table_scan_bitmap_next_block(node->ss.ss_currentScanDesc, &node->recheck,
 										  &node->stats.lossy_pages, &node->stats.exact_pages))
 			break;
 	}
-- 
2.45.2

v24-0009-Push-Bitmap-Table-Scan-prefetch-code-into-heap-A.patchapplication/octet-stream; name=v24-0009-Push-Bitmap-Table-Scan-prefetch-code-into-heap-A.patchDownload
From 5b9d1b8cfd11b8f7c8defc718c0e670375e1eed2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 9 Oct 2024 14:54:24 -0400
Subject: [PATCH v24 09/12] Push Bitmap Table Scan prefetch code into heap AM

In order to completely remove the layering violation in bitmap table
scan code, we must avoid using the VM for skipping prefetches as well.

To accomplish this, push prefetch code down into the heap implementation
fo the bitmap table scan AM functions. This fixes another layering
violation related to prefetching mentioned in tableam.h.

This commit moves prefetch-related members from the BitmapHeapScanState
to the BitmapHeapScanDesc and localizes the prefetch functions to heap
AM code.

heapam_scan_bitmap_next_block() no longer needs to take blockno as a
parameter because it was only being used in generic bitmap table scan
code to check if the prefetch block was falling behind the current
block.
---
 src/backend/access/heap/heapam.c          |  25 +++-
 src/backend/access/heap/heapam_handler.c  | 136 +++++++++++++++-------
 src/backend/access/table/tableam.c        |   4 +-
 src/backend/executor/nodeBitmapHeapscan.c | 130 ++++++---------------
 src/include/access/heapam.h               |  21 ++--
 src/include/access/relscan.h              |   9 +-
 src/include/access/tableam.h              |  63 +++++-----
 src/include/nodes/execnodes.h             |  10 --
 8 files changed, 201 insertions(+), 197 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 3452634040..4ea8933c44 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1029,7 +1029,8 @@ TableScanDesc
 heap_beginscan(Relation relation, Snapshot snapshot,
 			   int nkeys, ScanKey key,
 			   ParallelTableScanDesc parallel_scan,
-			   uint32 flags)
+			   uint32 flags,
+			   int prefetch_maximum)
 {
 	HeapScanDesc scan;
 
@@ -1049,8 +1050,17 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	{
 		BitmapHeapScanDesc *bscan = palloc(sizeof(BitmapHeapScanDesc));
 
+		bscan->rs_pfblockno = InvalidBlockNumber;
 		bscan->rs_vmbuffer = InvalidBuffer;
+		bscan->rs_pvmbuffer = InvalidBuffer;
 		bscan->rs_empty_tuples_pending = 0;
+
+		/* Only used for serial BHS */
+		bscan->rs_prefetch_pages = 0;
+		bscan->rs_prefetch_target = -1;
+
+		bscan->rs_prefetch_maximum = prefetch_maximum;
+
 		scan = &bscan->rs_heap_base;
 	}
 	else
@@ -1181,6 +1191,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	{
 		BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
 
+		bscan->rs_pfblockno = InvalidBlockNumber;
+
+		/* Only used for serial BHS */
+		bscan->rs_prefetch_pages = 0;
+		bscan->rs_prefetch_target = -1;
+
 		/*
 		 * Reset empty_tuples_pending, a field only used by bitmap heap scan,
 		 * to avoid incorrectly emitting NULL-filled tuples from a previous
@@ -1193,6 +1209,11 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			ReleaseBuffer(bscan->rs_vmbuffer);
 			bscan->rs_vmbuffer = InvalidBuffer;
 		}
+		if (BufferIsValid(bscan->rs_pvmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_pvmbuffer);
+			bscan->rs_pvmbuffer = InvalidBuffer;
+		}
 	}
 
 	/*
@@ -1252,6 +1273,8 @@ heap_endscan(TableScanDesc sscan)
 		bscan->rs_empty_tuples_pending = 0;
 		if (BufferIsValid(bscan->rs_vmbuffer))
 			ReleaseBuffer(bscan->rs_vmbuffer);
+		if (BufferIsValid(bscan->rs_pvmbuffer))
+			ReleaseBuffer(bscan->rs_pvmbuffer);
 	}
 
 	pfree(scan);
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 04f8adc71e..78193b1248 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,6 +54,10 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
+static void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *bscan);
+static void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *bscan);
+static void BitmapPrefetch(BitmapHeapScanDesc *bscan);
+
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 
@@ -2116,7 +2120,7 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
@@ -2130,14 +2134,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(bscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.tbmiterator);
+		tbmres = tbm_iterate(&scan->st.bts.tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2153,7 +2158,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
+	block = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2174,8 +2179,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	block = tbmres->blockno;
-
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
@@ -2269,6 +2272,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*lossy_pages)++;
 
+	/*
+	 * If private, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->st.bts.pstate == NULL &&
+		!tbm_exhausted(&scan->st.bts.prefetch_iterator) &&
+		bscan->rs_pfblockno < block)
+		elog(ERROR, "prefetch and main iterators are out of sync. :fblockno: %d. block: %d", bscan->rs_pfblockno, block);
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(bscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2288,6 +2303,9 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->st.bts.pstate;
+#endif							/* USE_PREFETCH */
 
 	if (bscan->rs_empty_tuples_pending > 0)
 	{
@@ -2296,6 +2314,7 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 		 */
 		ExecStoreAllNullTuple(slot);
 		bscan->rs_empty_tuples_pending--;
+		BitmapPrefetch(bscan);
 		return true;
 	}
 
@@ -2305,6 +2324,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!pstate)
+	{
+		if (bscan->rs_prefetch_target < bscan->rs_prefetch_maximum)
+			bscan->rs_prefetch_target++;
+	}
+	else if (pstate->prefetch_target < bscan->rs_prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target < bscan->rs_prefetch_maximum)
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(bscan);
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2618,27 +2667,28 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
  *	iterator in prefetch_pages. For each block the main iterator returns, we
  *	decrement prefetch_pages.
  */
-void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+static void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *bscan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	TableScanDesc scan = &(&bscan->rs_heap_base)->rs_base;
+	ParallelBitmapHeapState *pstate = scan->st.bts.pstate;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->st.bts.prefetch_iterator;
 
-		if (node->prefetch_pages > 0)
+		if (bscan->rs_prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
+			bscan->rs_prefetch_pages--;
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
 			/* Do not let the prefetch iterator get behind the main one */
 			tbmpre = tbm_iterate(prefetch_iterator);
-			node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+			bscan->rs_pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 		}
 		return;
 	}
@@ -2652,9 +2702,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
 	 * exacerbates the effects of this bug.
 	 */
-	if (node->prefetch_maximum > 0)
+	if (bscan->rs_prefetch_maximum > 0)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->st.bts.prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -2678,7 +2728,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			if (!tbm_exhausted(prefetch_iterator))
 			{
 				tbmpre = tbm_iterate(prefetch_iterator);
-				node->pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
+				bscan->rs_pfblockno = tbmpre ? tbmpre->blockno : InvalidBlockNumber;
 			}
 		}
 	}
@@ -2693,33 +2743,34 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
  * page/tuple, then to one after the second tuple is fetched, then
  * it doubles as later pages are fetched.
  */
-void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+static void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *bscan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	TableScanDesc scan = &(&bscan->rs_heap_base)->rs_base;
+	ParallelBitmapHeapState *pstate = scan->st.bts.pstate;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_target >= node->prefetch_maximum)
+		if (bscan->rs_prefetch_target >= bscan->rs_prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
+		else if (bscan->rs_prefetch_target >= bscan->rs_prefetch_maximum / 2)
+			bscan->rs_prefetch_target = bscan->rs_prefetch_maximum;
+		else if (bscan->rs_prefetch_target > 0)
+			bscan->rs_prefetch_target *= 2;
 		else
-			node->prefetch_target++;
+			bscan->rs_prefetch_target++;
 		return;
 	}
 
 	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
+	if (pstate->prefetch_target < bscan->rs_prefetch_maximum)
 	{
 		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
+		if (pstate->prefetch_target >= bscan->rs_prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target >= bscan->rs_prefetch_maximum / 2)
+			pstate->prefetch_target = bscan->rs_prefetch_maximum;
 		else if (pstate->prefetch_target > 0)
 			pstate->prefetch_target *= 2;
 		else
@@ -2732,19 +2783,20 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
 /*
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
-void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+static void
+BitmapPrefetch(BitmapHeapScanDesc *bscan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	TableScanDesc scan = &(&bscan->rs_heap_base)->rs_base;
+	ParallelBitmapHeapState *pstate = scan->st.bts.pstate;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->st.bts.prefetch_iterator;
 
 		if (!tbm_exhausted(prefetch_iterator))
 		{
-			while (node->prefetch_pages < node->prefetch_target)
+			while (bscan->rs_prefetch_pages < bscan->rs_prefetch_target)
 			{
 				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
@@ -2755,8 +2807,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
-				node->prefetch_pages++;
-				node->pfblockno = tbmpre->blockno;
+				bscan->rs_prefetch_pages++;
+				bscan->rs_pfblockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2766,9 +2818,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->rs_rd,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &bscan->rs_pvmbuffer));
 
 				if (!skip_fetch)
 					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
@@ -2780,7 +2832,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &scan->st.bts.prefetch_iterator;
 
 		if (!tbm_exhausted(prefetch_iterator))
 		{
@@ -2813,14 +2865,14 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->pfblockno = tbmpre->blockno;
+				bscan->rs_pfblockno = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->rs_rd,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &bscan->rs_pvmbuffer));
 
 				if (!skip_fetch)
 					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index bd8715b679..3dafcea964 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -117,7 +117,7 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 	Snapshot	snapshot = RegisterSnapshot(GetCatalogSnapshot(relid));
 
 	return relation->rd_tableam->scan_begin(relation, snapshot, nkeys, key,
-											NULL, flags);
+											NULL, flags, 0);
 }
 
 
@@ -184,7 +184,7 @@ table_beginscan_parallel(Relation relation, ParallelTableScanDesc pscan)
 	}
 
 	return relation->rd_tableam->scan_begin(relation, snapshot, 0, NULL,
-											pscan, flags);
+											pscan, flags, 0);
 }
 
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 4eae377d91..21ceff5310 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,8 +37,6 @@
 
 #include <math.h>
 
-/* XXX: temporary include so prefetch lift and shift works */
-#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -95,6 +93,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	if (!node->initialized)
 	{
 		TBMIterator tbmiterator;
+		int			prefetch_maximum;
+		Relation	rel = node->ss.ss_currentRelation;
+#ifdef USE_PREFETCH
+		TBMIterator prefetch_iterator = {0};
+#endif							/* USE_PREFETCH */
+
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		prefetch_maximum = get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
 
 		if (!pstate)
 		{
@@ -104,14 +113,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-				node->prefetch_iterator = tbm_begin_iterate(node->tbm, dsa,
-															pstate ?
-															pstate->prefetch_iterator :
-															InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
 		}
 		else if (BitmapShouldInitializeSharedState(pstate))
 		{
@@ -134,7 +135,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 
 #ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (prefetch_maximum > 0)
 			{
 				pstate->prefetch_iterator =
 					tbm_prepare_shared_iterate(tbm);
@@ -149,13 +150,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 										pstate ?
 										pstate->tbmiterator :
 										InvalidDsaPointer);
-
 #ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-			node->prefetch_iterator = tbm_begin_iterate(tbm, dsa,
-														pstate ?
-														pstate->prefetch_iterator :
-														InvalidDsaPointer);
+		if (prefetch_maximum > 0)
+			prefetch_iterator = tbm_begin_iterate(tbm, dsa,
+												  pstate ?
+												  pstate->prefetch_iterator :
+												  InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 
 		/*
@@ -179,14 +179,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
+									  pstate,
 									  0,
 									  NULL,
-									  need_tuples);
+									  need_tuples,
+									  prefetch_maximum);
 
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->st.tbmiterator = tbmiterator;
+		scan->st.bts.tbmiterator = tbmiterator;
+		scan->st.bts.prefetch_iterator = prefetch_iterator;
 		node->initialized = true;
 
 		goto new_page;
@@ -202,37 +205,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -255,27 +227,13 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno, &node->recheck,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck,
 										  &node->stats.lossy_pages, &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If private, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -347,30 +305,22 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		tbm_end_iterate(&scan->st.tbmiterator);
+		tbm_end_iterate(&scan->st.bts.tbmiterator);
+
+		/* If we did not already clean up the prefetch iterator, do so now. */
+		if (!tbm_exhausted(&scan->st.bts.prefetch_iterator))
+			tbm_end_iterate(&scan->st.bts.prefetch_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	node->blockno = InvalidBlockNumber;
-	node->pfblockno = InvalidBlockNumber;
-	/* Only used for serial BHS */
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -429,7 +379,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		tbm_end_iterate(&scanDesc->st.tbmiterator);
+		tbm_end_iterate(&scanDesc->st.bts.tbmiterator);
+
+		/* If we did not already clean up the prefetch iterator, do so now. */
+		if (!tbm_exhausted(&scanDesc->st.bts.prefetch_iterator))
+			tbm_end_iterate(&scanDesc->st.bts.prefetch_iterator);
 
 		/*
 		 * close table scan
@@ -437,17 +391,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -480,18 +428,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->pfblockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -531,13 +474,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index d5f8cd5eef..0ddef490c7 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -22,8 +22,6 @@
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
 #include "nodes/lockoptions.h"
-/* XXX: temporary include so prefetch lift and shift works */
-#include "nodes/execnodes.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
 #include "storage/dsm.h"
@@ -105,6 +103,15 @@ typedef struct BitmapHeapScanDesc
 {
 	HeapScanDescData rs_heap_base;
 
+	/* used to validate pf stays ahead of current block */
+	BlockNumber rs_pfblockno;
+	/* maximum value for prefetch_target */
+	int			rs_prefetch_maximum;
+	/* Current target for prefetch distance */
+	int			rs_prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			rs_prefetch_pages;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -115,6 +122,8 @@ typedef struct BitmapHeapScanDesc
 
 	/* page of VM containing info for current block */
 	Buffer		rs_vmbuffer;
+	/* page of VM containing info for prefetch block */
+	Buffer		rs_pvmbuffer;
 	int			rs_empty_tuples_pending;
 } BitmapHeapScanDesc;
 
@@ -299,7 +308,8 @@ typedef enum
 extern TableScanDesc heap_beginscan(Relation relation, Snapshot snapshot,
 									int nkeys, ScanKey key,
 									ParallelTableScanDesc parallel_scan,
-									uint32 flags);
+									uint32 flags,
+									int prefetch_maximum);
 extern void heap_setscanlimits(TableScanDesc sscan, BlockNumber startBlk,
 							   BlockNumber numBlks);
 extern void heap_prepare_pagescan(TableScanDesc sscan);
@@ -425,11 +435,6 @@ extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
 extern bool HeapTupleIsSurelyDead(HeapTuple htup,
 								  struct GlobalVisState *vistest);
 
-/* in heapam_handler.c */
-extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-extern void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan);
-
 /*
  * To avoid leaking too much knowledge about reorderbuffer implementation
  * details this is implemented in reorderbuffer.c not heapam_visibility.c
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index e014abcdc7..f02176692d 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,13 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *pstate;
+			TBMIterator tbmiterator;
+			TBMIterator prefetch_iterator;
+		}			bts;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b0f1a79623..0b4cacb631 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -324,12 +324,16 @@ typedef struct TableAmRoutine
 	 * the scan's behaviour (ScanOptions's SO_ALLOW_*, several may be
 	 * specified, an AM may ignore unsupported ones) and whether the snapshot
 	 * needs to be deallocated at scan_end (ScanOptions's SO_TEMP_SNAPSHOT).
+	 *
+	 * `prefetch_maximum` is the maximum prefetch distance for use by bitmap
+	 * table scans as needed.
 	 */
 	TableScanDesc (*scan_begin) (Relation rel,
 								 Snapshot snapshot,
 								 int nkeys, struct ScanKeyData *key,
 								 ParallelTableScanDesc pscan,
-								 uint32 flags);
+								 uint32 flags,
+								 int prefetch_maximum);
 
 	/*
 	 * Release resources and deallocate scan. If TableScanDesc.temp_snap,
@@ -780,9 +784,10 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
+	 * Prepare to fetch / check / return tuples from the next block yielded by
+	 * the iterator as part of a bitmap table scan. `scan` was started via
+	 * table_beginscan_bm(). Return false if the bitmap is exhausted and true
+	 * otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
@@ -797,28 +802,14 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching future blocks indicated in the bitmap is left to the table
+	 * AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno, bool *recheck,
+										   bool *recheck,
 										   uint64 *lossy_pages, uint64 *exact_pages);
 
 	/*
@@ -914,7 +905,7 @@ table_beginscan(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_SEQSCAN |
 		SO_ALLOW_STRAT | SO_ALLOW_SYNC | SO_ALLOW_PAGEMODE;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags, 0);
 }
 
 /*
@@ -943,7 +934,7 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 	if (allow_sync)
 		flags |= SO_ALLOW_SYNC;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags, 0);
 }
 
 /*
@@ -954,14 +945,20 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, bool need_tuple)
+				   struct ParallelBitmapHeapState *pstate,
+				   int nkeys, struct ScanKeyData *key, bool need_tuple,
+				   int prefetch_maximum)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags,
+										 prefetch_maximum);
+	result->st.bts.pstate = pstate;
+	return result;
 }
 
 /*
@@ -986,7 +983,7 @@ table_beginscan_sampling(Relation rel, Snapshot snapshot,
 	if (allow_pagemode)
 		flags |= SO_ALLOW_PAGEMODE;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags, 0);
 }
 
 /*
@@ -999,7 +996,7 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 {
 	uint32		flags = SO_TYPE_TIDSCAN;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL, NULL, flags, 0);
 }
 
 /*
@@ -1012,7 +1009,7 @@ table_beginscan_analyze(Relation rel)
 {
 	uint32		flags = SO_TYPE_ANALYZE;
 
-	return rel->rd_tableam->scan_begin(rel, NULL, 0, NULL, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, NULL, 0, NULL, NULL, flags, 0);
 }
 
 /*
@@ -1091,7 +1088,7 @@ table_beginscan_tidrange(Relation rel, Snapshot snapshot,
 	TableScanDesc sscan;
 	uint32		flags = SO_TYPE_TIDRANGESCAN | SO_ALLOW_PAGEMODE;
 
-	sscan = rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL, NULL, flags);
+	sscan = rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL, NULL, flags, 0);
 
 	/* Set the range of TIDs to scan */
 	sscan->rs_rd->rd_tableam->scan_set_tidrange(sscan, mintid, maxtid);
@@ -1963,16 +1960,12 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno, bool *recheck,
+							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
 {
@@ -1985,7 +1978,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages, exact_pages);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 2def5895fe..d5bca3ac73 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1833,18 +1833,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block in sync
- *		pfblockno		   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1852,7 +1845,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
 	TBMIterator prefetch_iterator;
 	int			prefetch_pages;
@@ -1862,8 +1854,6 @@ typedef struct BitmapHeapScanState
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber pfblockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.45.2

v24-0011-Remove-table-AM-callback-scan_bitmap_next_block.patchapplication/octet-stream; name=v24-0011-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 60f37859c7108e912980a3884d0c7b767f0a959b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 9 Oct 2024 16:47:33 -0400
Subject: [PATCH v24 11/12] Remove table AM callback scan_bitmap_next_block

Remove table AM callback scan_bitmap_next_block(). This makes
implementing bitmap table scans easier for non block-based table AMs and
makes BitmapHeapNext() control flow similar to SeqNext().

Now bitmap table scan code only calls table_scan_bitmap_next_tuple().
The heap AM implementation of scan_bitmap_next_block() is now a local
helper in heapam_handler.c.
---
 src/backend/access/heap/heapam.c          |  7 ++
 src/backend/access/heap/heapam_handler.c  | 57 +++++++++-----
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 57 +++++---------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 96 ++++++-----------------
 src/include/nodes/execnodes.h             |  4 -
 7 files changed, 92 insertions(+), 133 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4ea8933c44..c673457889 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -378,6 +378,9 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
+
 
 	/*
 	 * Initialize to ForwardScanDirection because it is most common and
@@ -1072,6 +1075,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1185,7 +1189,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 78193b1248..6fc779e1d0 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -57,6 +57,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 static void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc *bscan);
 static void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc *bscan);
 static void BitmapPrefetch(BitmapHeapScanDesc *bscan);
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
@@ -2118,10 +2121,15 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when the
+ * bitmap and or relation are exhausted.
+ */
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
 	HeapScanDesc hscan = &bscan->rs_heap_base;
@@ -2288,15 +2296,17 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
 	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
+	 * invoke this function again.
 	 */
 	return true;
 }
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot,
+							  bool *recheck,
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
 	HeapScanDesc hscan = &bscan->rs_heap_base;
@@ -2307,22 +2317,32 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	ParallelBitmapHeapState *pstate = scan->st.bts.pstate;
 #endif							/* USE_PREFETCH */
 
-	if (bscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		BitmapPrefetch(bscan);
-		return true;
-	}
+		if (bscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			BitmapPrefetch(bscan);
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		/*
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
+		 */
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2941,7 +2961,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index e9b598256f..912495bdaa 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index ca22cd4196..25cfc1647a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -181,51 +181,34 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
-		/* BitmapTableScanSetup sets node->ss.ss_currentScanDesc */
 		BitmapTableScanSetup(node);
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc, slot, &node->recheck,
+										&node->stats.lossy_pages, &node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-
-			CHECK_FOR_INTERRUPTS();
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(node->ss.ss_currentScanDesc, &node->recheck,
-										  &node->stats.lossy_pages, &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index b913f91ff0..29f5036e9b 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 0b4cacb631..3339043a8a 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -783,44 +783,23 @@ typedef struct TableAmRoutine
 	 * ------------------------------------------------------------------------
 	 */
 
-	/*
-	 * Prepare to fetch / check / return tuples from the next block yielded by
-	 * the iterator as part of a bitmap table scan. `scan` was started via
-	 * table_beginscan_bm(). Return false if the bitmap is exhausted and true
-	 * otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
-	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
-	 *
-	 * Prefetching future blocks indicated in the bitmap is left to the table
-	 * AM.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   bool *recheck,
-										   uint64 *lossy_pages, uint64 *exact_pages);
-
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
+	 *
+	 * Prefetching additional data from the bitmap is left to the table AM.
+	 *
+	 * This is an optional callback.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
+										   TupleTableSlot *slot,
+										   bool *recheck,
+										   uint64 *lossy_pages,
+										   uint64 *exact_pages);
 
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
@@ -1949,50 +1928,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false if
- * there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be incremented
- * by the table AM to indicate whether or not the block's representation in the
- * bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages, exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2003,7 +1956,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d5bca3ac73..53fcb9d33a 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1846,10 +1846,6 @@ typedef struct BitmapHeapScanState
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
-- 
2.45.2

v24-0012-Move-BitmapHeapScanNextBlock-next-to-other-helpe.patchapplication/octet-stream; name=v24-0012-Move-BitmapHeapScanNextBlock-next-to-other-helpe.patchDownload
From e0ab52f8ad2d0c321644c09c558988e85cdc7090 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 14 Oct 2024 16:10:59 -0400
Subject: [PATCH v24 12/12] Move BitmapHeapScanNextBlock() next to other
 helpers

A previous commit turned heapam_scan_bitmap_next_block() into a helper
for heapam_scan_bitmap_next_tuple(). Move it down in heapam_handler.c
next to the other helpers. This is its own commit to make the diff more
readable.
---
 src/backend/access/heap/heapam_handler.c | 360 +++++++++++------------
 1 file changed, 180 insertions(+), 180 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6fc779e1d0..6c5a7d3f4e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2121,186 +2121,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
-/*
- * Helper function get the next block of a bitmap heap scan. Returns true when
- * it got the next block and saved it in the scan descriptor and false when the
- * bitmap and or relation are exhausted.
- */
-static bool
-BitmapHeapScanNextBlock(TableScanDesc scan,
-						bool *recheck,
-						uint64 *lossy_pages, uint64 *exact_pages)
-{
-	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
-	HeapScanDesc hscan = &bscan->rs_heap_base;
-	BlockNumber block;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	*recheck = true;
-
-	BitmapAdjustPrefetchIterator(bscan);
-
-	do
-	{
-		CHECK_FOR_INTERRUPTS();
-
-		tbmres = tbm_iterate(&scan->st.bts.tbmiterator);
-
-		if (tbmres == NULL)
-			return false;
-
-		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
-		 */
-	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
-
-	/* Got a valid block */
-	block = tbmres->blockno;
-	*recheck = tbmres->recheck;
-
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
-
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
-
-		return true;
-	}
-
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
-
-	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
-	 */
-	if (tbmres->ntuples >= 0)
-	{
-		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
-		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
-		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
-		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
-		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
-
-	/*
-	 * If private, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->st.bts.pstate == NULL &&
-		!tbm_exhausted(&scan->st.bts.prefetch_iterator) &&
-		bscan->rs_pfblockno < block)
-		elog(ERROR, "prefetch and main iterators are out of sync. :fblockno: %d. block: %d", bscan->rs_pfblockno, block);
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(bscan);
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * invoke this function again.
-	 */
-	return true;
-}
-
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot,
@@ -2902,6 +2722,186 @@ BitmapPrefetch(BitmapHeapScanDesc *bscan)
 #endif							/* USE_PREFETCH */
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when the
+ * bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;
+	HeapScanDesc hscan = &bscan->rs_heap_base;
+	BlockNumber block;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	*recheck = true;
+
+	BitmapAdjustPrefetchIterator(bscan);
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbmres = tbm_iterate(&scan->st.bts.tbmiterator);
+
+		if (tbmres == NULL)
+			return false;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() && tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	block = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(bscan->rs_empty_tuples_pending >= 0);
+
+		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
+	/*
+	 * Acquire pin on the target heap page, trading in any pin we held before.
+	 */
+	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
+										  scan->rs_rd,
+										  block);
+	hscan->rs_cblock = block;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = tbmres->offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * If private, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->st.bts.pstate == NULL &&
+		!tbm_exhausted(&scan->st.bts.prefetch_iterator) &&
+		bscan->rs_pfblockno < block)
+		elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. block: %d", bscan->rs_pfblockno, block);
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(bscan);
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * invoke this function again.
+	 */
+	return true;
+}
+
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
-- 
2.45.2

v24-0006-Make-Bitmap-Table-Scan-prefetch-sync-error-more-.patchapplication/octet-stream; name=v24-0006-Make-Bitmap-Table-Scan-prefetch-sync-error-more-.patchDownload
From 9760486fabdccd58b5763a1a4cbc3e88a6b59ffb Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Jun 2024 12:40:58 -0400
Subject: [PATCH v24 06/12] Make Bitmap Table Scan prefetch sync error more
 detailed

Add the prefetch and current block numbers to the error message emitted
when the prefetch iterator gets out of sync with the main iterator in
serial bitmap table scan.
---
 src/backend/executor/nodeBitmapHeapscan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fb747cb9e2..d7944eccd5 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -274,7 +274,7 @@ new_page:
 		if (node->pstate == NULL &&
 			!tbm_exhausted(&node->prefetch_iterator) &&
 			node->pfblockno < node->blockno)
-			elog(ERROR, "prefetch and main iterators are out of sync");
+			elog(ERROR, "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d", node->pfblockno, node->blockno);
 
 		/* Adjust the prefetch target */
 		BitmapAdjustPrefetchTarget(node);
-- 
2.45.2

#160Tomas Vondra
tomas@vondra.me
In reply to: Melanie Plageman (#159)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

I took a quick look on the first couple parts of this series, up to
0007. I only have a couple minor review comments:

1) 0001

I find it a bit weird that we use ntuples to determine if it's exact or
lossy. Not an issue caused by this patch, of course, but maybe we could
improve that somehow? I mean this:

if (tbmres->ntuples >= 0)
(*exact_pages)++;
else
(*lossy_pages)++;

Also, maybe consider manually wrapping long lines - I haven't tried, but
I guess pgindent did not wrap this. I mean this line, for example:

... whitespace ... &node->stats.lossy_pages, &node->stats.exact_pages))

2) 0003

The "tidr" name is not particularly clear, IMO. Maybe just "range" would
be better?

+  struct
+  {
+      ItemPointerData rs_mintid;
+      ItemPointerData rs_maxtid;
+  }   tidr;

Isn't it a bit strange that this patch remove tmbres from
heapam_scan_bitmap_next_block, when it was already removed from
table_scan_bitmap_next_tuple in the previous commit? Does it make sense
to separate it like this? (Maybe it does, not sure.)

I find this not very clear:

+ *    recheck     do current page's tuples need recheck
+ *    blockno     used to validate pf and current block in sync
+ *    pfblockno   used to validate pf stays ahead of current block

The "blockno" sounds weird - shouldn't it say "are in sync"? Also, not
clear what "pf" stands for without context (sure, it's "prefetch"). But
Why not to not write "prefetch_blockno" or something like that?

3) 0006

Seems unnecessary to keep this as separate commit, it's just log
message improvement. I'd merge it to the earlier patch.

4) 0007

Seems fine to me in principle. This adds "subclass" similar to what we
do for plan nodes, except that states are not derived from Node. But
it's the same approach.

Why not to do

scan = (HeapScanDesc *) bscan;

instead of

scan = &bscan->rs_heap_base;

I think the simple cast is what we do for the plan nodes, and we even do
it this way in the opposite direction in a couple places:

BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;

BTW would it be a good idea for heapam_scan_bitmap_next_block to check
the passed "scan" has SO_TYPE_BITMAPSCAN? We haven't been checking that
so far I think, but we only had a single struct ...

regards

--
Tomas Vondra

#161Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#160)
11 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Oct 16, 2024 at 11:09 AM Tomas Vondra <tomas@vondra.me> wrote:

Thanks for the review!

1) 0001

I find it a bit weird that we use ntuples to determine if it's exact or
lossy. Not an issue caused by this patch, of course, but maybe we could
improve that somehow? I mean this:

if (tbmres->ntuples >= 0)
(*exact_pages)++;
else
(*lossy_pages)++;

I agree. The most straightforward solution would be to add a boolean
`lossy` to TBMIterateResult.

In some ways, I think it would make it a bit more clear because the
situation with TBMIterateResult->recheck is already a bit confusing.
It recheck is true if either 1: the Bitmap is lossy and we cannot use
TBMIterateResult->offsets for this page or 2: the original query has a
qual requiring recheck

In the body of BitmapHeapNext() it says "if we are using lossy info,
we have to recheck the qual conditions at every tuple". And in
heapam_bitmap_next_block(), when the bitmap is lossy it says "bitmap
is lossy, so we must examine each line pointer on the page. But we can
ignore HOT chains, since we'll check each tuple anyway"

I must admit I don't quite understand the connection between a lossy
bitmap and needing to recheck the qual condition. Once we've gone to
the underlying data, why do we need to recheck each tuple unless the
qual requires it? It seems like PageTableEntry->recheck is usually
passed as true for hash indexes and false for btree indexes. So maybe
it has something to do with the index type?

Anyway, adding a `lossy` member can be another patch. I just wanted to
check if that was the solution you were thinking of.

On a somewhat related note, I included a patch to alter the test at
the top of heapam_bitmap_next_tuple()

if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)

I don't really see how rs_cindex could ever be < 0 for bitmap heap
scans. But, I'm not confident enough about this to commit the patch
really (obviously tests pass with the Assertion I added -- but still).

Also, maybe consider manually wrapping long lines - I haven't tried, but
I guess pgindent did not wrap this. I mean this line, for example:

... whitespace ... &node->stats.lossy_pages, &node->stats.exact_pages))

Ah, yes. pgindent indeed does not help with this. I have now gone
through every commit and used

git diff origin/master | grep -E '^(\+|diff)' | sed 's/^+//' | expand
-t4 | awk "length > 78 || /^diff/"

from the committing wiki :)

2) 0003

The "tidr" name is not particularly clear, IMO. Maybe just "range" would
be better?

I've updated this.

+  struct
+  {
+      ItemPointerData rs_mintid;
+      ItemPointerData rs_maxtid;
+  }   tidr;

Isn't it a bit strange that this patch remove tmbres from
heapam_scan_bitmap_next_block, when it was already removed from
table_scan_bitmap_next_tuple in the previous commit? Does it make sense
to separate it like this? (Maybe it does, not sure.)

I've combined them.

I find this not very clear:

+ *    recheck     do current page's tuples need recheck
+ *    blockno     used to validate pf and current block in sync
+ *    pfblockno   used to validate pf stays ahead of current block

The "blockno" sounds weird - shouldn't it say "are in sync"? Also, not
clear what "pf" stands for without context (sure, it's "prefetch"). But
Why not to not write "prefetch_blockno" or something like that?

Fixed.

3) 0006

Seems unnecessary to keep this as separate commit, it's just log
message improvement. I'd merge it to the earlier patch.

Done.

4) 0007

Seems fine to me in principle. This adds "subclass" similar to what we
do for plan nodes, except that states are not derived from Node. But
it's the same approach.

Why not to do

scan = (HeapScanDesc *) bscan;

instead of

scan = &bscan->rs_heap_base;

I think the simple cast is what we do for the plan nodes, and we even do
it this way in the opposite direction in a couple places:

BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;

Yea, in the reverse case, there is no way to refer to a specific
member (because we are casting something of the parent type to the
child type). But when we are casting from the child type to the parent
type and can actually refer to a member, it seems preferable to
explicitly refer to the member in case anyone ever inserts a member
above rs_heap_base. However, for consistency with other places in the
code, I've changed it as you suggested.

Additionally, I've gone through an made a number of stylistic changes
to conform more closely to existing styles (adding back more rs_
prefixes and typedef'ing BitmapHeapScanDescData * as
BitmapHeapScanDesc [despite how sad it makes me]).

BTW would it be a good idea for heapam_scan_bitmap_next_block to check
the passed "scan" has SO_TYPE_BITMAPSCAN? We haven't been checking that
so far I think, but we only had a single struct ...

Good point. I've done this.

I plan to commit 0002 and 0003 next week. I'm interested if you think
0001 is correct.
I may also commit 0004-0006 as I feel they are ready too.

0007-0011 need a bit more work, I think.

- Melanie

Attachments:

v25-0011-Move-BitmapHeapScanNextBlock-next-to-other-helpe.patchapplication/octet-stream; name=v25-0011-Move-BitmapHeapScanNextBlock-next-to-other-helpe.patchDownload
From b9e6d08eb14ce6626ae95718682448f73a797aa4 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 14 Oct 2024 16:10:59 -0400
Subject: [PATCH v25 11/11] Move BitmapHeapScanNextBlock() next to other
 helpers

A previous commit turned heapam_scan_bitmap_next_block() into a helper
for heapam_scan_bitmap_next_tuple(). Move it down in heapam_handler.c
next to the other helpers. This is its own commit to make the diff more
readable.

ci-os-only:
---
 src/backend/access/heap/heapam_handler.c | 371 ++++++++++++-----------
 1 file changed, 186 insertions(+), 185 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7bd8a17099d..eae85f81dbc 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2120,191 +2120,6 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
-/*
- * Helper function get the next block of a bitmap heap scan. Returns true when
- * it got the next block and saved it in the scan descriptor and false when
- * the bitmap and or relation are exhausted.
- */
-static bool
-BitmapHeapScanNextBlock(TableScanDesc scan,
-						bool *recheck,
-						uint64 *lossy_pages, uint64 *exact_pages)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	*recheck = true;
-
-	BitmapAdjustPrefetchIterator(bscan);
-
-	do
-	{
-		CHECK_FOR_INTERRUPTS();
-
-		tbmres = tbm_iterate(&scan->st.bitmap.rs_iterator);
-
-		if (tbmres == NULL)
-			return false;
-
-		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
-		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
-
-	/* Got a valid block */
-	block = tbmres->blockno;
-	*recheck = tbmres->recheck;
-
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
-
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
-
-		return true;
-	}
-
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
-
-	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
-	 */
-	if (tbmres->ntuples >= 0)
-	{
-		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
-		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
-		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
-		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
-		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
-
-	/*
-	 * If private, we can error out if the the prefetch block doesn't stay
-	 * ahead of the current block.
-	 */
-	if (scan->st.bitmap.rs_pstate == NULL &&
-		!tbm_exhausted(&scan->st.bitmap.rs_prefetch_iterator) &&
-		bscan->rs_prefetch_blockno < block)
-		elog(ERROR,
-			 "prefetch and main iterators are out of sync. pblockno: %d. block: %d",
-			 bscan->rs_prefetch_blockno, block);
-
-	/* Adjust the prefetch target */
-	BitmapAdjustPrefetchTarget(bscan);
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * invoke this function again.
-	 */
-	return true;
-}
-
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot,
@@ -2914,6 +2729,192 @@ BitmapPrefetch(BitmapHeapScanDesc bscan)
 }
 
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	*recheck = true;
+
+	BitmapAdjustPrefetchIterator(bscan);
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbmres = tbm_iterate(&scan->st.bitmap.rs_iterator);
+
+		if (tbmres == NULL)
+			return false;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() &&
+			 tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	block = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
+	/*
+	 * We can skip fetching the heap page if we don't need any fields from the
+	 * heap, the bitmap entries don't need rechecking, and all tuples on the
+	 * page are visible to our transaction.
+	 */
+	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
+		!tbmres->recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+	{
+		/* can't be lossy in the skip_fetch case */
+		Assert(tbmres->ntuples >= 0);
+		Assert(bscan->rs_empty_tuples_pending >= 0);
+
+		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+
+		return true;
+	}
+
+	/*
+	 * Acquire pin on the target heap page, trading in any pin we held before.
+	 */
+	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
+										  scan->rs_rd,
+										  block);
+	hscan->rs_cblock = block;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = tbmres->offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * If private, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->st.bitmap.rs_pstate == NULL &&
+		!tbm_exhausted(&scan->st.bitmap.rs_prefetch_iterator) &&
+		bscan->rs_prefetch_blockno < block)
+		elog(ERROR,
+			 "prefetch and main iterators are out of sync. pblockno: %d. block: %d",
+			 bscan->rs_prefetch_blockno, block);
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(bscan);
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * invoke this function again.
+	 */
+	return true;
+}
+
+
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
  * ------------------------------------------------------------------------
-- 
2.45.2

v25-0001-Remove-unused-rs_cindex-condition-in-heap-AM-bit.patchapplication/octet-stream; name=v25-0001-Remove-unused-rs_cindex-condition-in-heap-AM-bit.patchDownload
From d7b6fe50c4af123051d7ba48a0a0b6eda208a1bb Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 17 Oct 2024 15:51:24 -0400
Subject: [PATCH v25 01/11] Remove unused rs_cindex condition in heap AM bitmap
 callback

HeapScanDescData.rs_cindex can't be less than 0 for bitmap heap scans.
Remove this test from heapam_scan_bitmap_next_tuple() and add an
assertion to ensure this stays true.

Also initialize HeapScanDescData.rs_cindex to 0 in initscan().

Author: Melanie Plageman
---
 src/backend/access/heap/heapam.c         | 1 +
 src/backend/access/heap/heapam_handler.c | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index da5e656a08d..cbc5f62aff6 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -378,6 +378,7 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_cindex = 0;
 
 	/*
 	 * Initialize to ForwardScanDirection because it is most common and
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 8c59b77b64f..bdb7599684b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2269,7 +2269,8 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	/*
 	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)
+	Assert(hscan->rs_cindex >= 0);
+	if (hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
-- 
2.45.2

v25-0003-Make-table_scan_bitmap_next_block-async-friendly.patchapplication/octet-stream; name=v25-0003-Make-table_scan_bitmap_next_block-async-friendly.patchDownload
From 3b2587d69b6a826a6cbe4856dc854354931a646a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 12 Feb 2024 18:13:41 -0500
Subject: [PATCH v25 03/11] Make table_scan_bitmap_next_block() async-friendly

Move all responsibility for indicating a block is exhuasted into
table_scan_bitmap_next_tuple() and advance the main iterator in
heap-specific code. This flow control makes more sense and is a step
toward using the read stream API for bitmap heap scans.

Previously, table_scan_bitmap_next_block() returned false to indicate
table_scan_bitmap_next_tuple() should not be called for the tuples on
the page. This happened when both when 1) there were no visible tuples
on the page and 2) when the block returned by the iterator was past the
end of the table. Generic bitmap table scan code handled the case when
the bitmap was exhausted.

It makes more sense for table_scan_bitmap_next_tuple() to return false
when there are no visible tuples on the page and
table_scan_bitmap_next_block() to return false when the bitmap is
exhausted or there are no more blocks in the table.

As part of this new design, TBMIterateResults are no longer used as a
flow control mechanism in BitmapHeapNext(), so we removed
table_scan_bitmap_next_tuple's TBMIterateResult parameter.

Note that the prefetch iterator is still saved in the
BitmapHeapScanState node and advanced in generic bitmap table scan code.
This is because 1) it was not necessary to change the prefetch iterator
location to change the flow control in BitmapHeapNext() 2) modifying
prefetch iterator management requires several more steps better split
over multiple commits and 3) the prefetch iterator will be removed once
the read stream API is used.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Andres Freund, Heikki Linnakangas, Mark Dilger
Discussion: https://postgr.es/m/063e4eb4-32d9-439e-a0b1-75565a9835a8%40iki.fi
---
 src/backend/access/heap/heapam.c          |   8 +-
 src/backend/access/heap/heapam_handler.c  |  56 +++--
 src/backend/executor/nodeBitmapHeapscan.c | 246 ++++++++++++----------
 src/include/access/relscan.h              |  28 ++-
 src/include/access/tableam.h              |  65 +++---
 src/include/nodes/execnodes.h             |  12 +-
 6 files changed, 253 insertions(+), 162 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index cbc5f62aff6..f9e3be1e846 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1388,8 +1388,8 @@ heap_set_tidrange(TableScanDesc sscan, ItemPointer mintid,
 	heap_setscanlimits(sscan, startBlk, numBlks);
 
 	/* Finally, set the TID range in sscan */
-	ItemPointerCopy(&lowestItem, &sscan->rs_mintid);
-	ItemPointerCopy(&highestItem, &sscan->rs_maxtid);
+	ItemPointerCopy(&lowestItem, &sscan->st.tidrange.rs_mintid);
+	ItemPointerCopy(&highestItem, &sscan->st.tidrange.rs_maxtid);
 }
 
 bool
@@ -1397,8 +1397,8 @@ heap_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction,
 						  TupleTableSlot *slot)
 {
 	HeapScanDesc scan = (HeapScanDesc) sscan;
-	ItemPointer mintid = &sscan->rs_mintid;
-	ItemPointer maxtid = &sscan->rs_maxtid;
+	ItemPointer mintid = &sscan->st.tidrange.rs_mintid;
+	ItemPointer maxtid = &sscan->st.tidrange.rs_maxtid;
 
 	/* Note: no locking manipulations needed */
 	for (;;)
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 753d0384ead..1536fa9f2d9 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2115,18 +2115,49 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
+							  BlockNumber *blockno, bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
-	BlockNumber block = tbmres->blockno;
+	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
+	TBMIterateResult *tbmres;
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
+	*blockno = InvalidBlockNumber;
+	*recheck = true;
+
+	do
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		if (scan->st.bitmap.rs_shared_iterator)
+			tbmres = tbm_shared_iterate(scan->st.bitmap.rs_shared_iterator);
+		else
+			tbmres = tbm_iterate(scan->st.bitmap.rs_iterator);
+
+		if (tbmres == NULL)
+			return false;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+	} while (!IsolationIsSerializable() &&
+			 tbmres->blockno >= hscan->rs_nblocks);
+
+	/* Got a valid block */
+	*blockno = tbmres->blockno;
+	*recheck = tbmres->recheck;
+
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
 	 * heap, the bitmap entries don't need rechecking, and all tuples on the
@@ -2145,16 +2176,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	/*
-	 * Ignore any claimed entries past what we think is the end of the
-	 * relation. It may have been extended after the start of our scan (we
-	 * only hold an AccessShareLock, and it could be inserts from this
-	 * backend).  We don't take this optimization in SERIALIZABLE isolation
-	 * though, as we need to examine all invisible tuples reachable by the
-	 * index.
-	 */
-	if (!IsolationIsSerializable() && block >= hscan->rs_nblocks)
-		return false;
+	block = tbmres->blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2249,12 +2271,18 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*lossy_pages)++;
 
-	return ntup > 0;
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
 }
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TBMIterateResult *tbmres,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index f4690a20bb1..89a16f142b7 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,8 +51,7 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-												BlockNumber blockno);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
 static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
 static inline void BitmapPrefetch(BitmapHeapScanState *node,
 								  TableScanDesc scan);
@@ -71,9 +70,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator = NULL;
-	TBMSharedIterator *shared_tbmiterator = NULL;
-	TBMIterateResult *tbmres;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
@@ -85,11 +81,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
 	tbm = node->tbm;
-	if (pstate == NULL)
-		tbmiterator = node->tbmiterator;
-	else
-		shared_tbmiterator = node->shared_tbmiterator;
-	tbmres = node->tbmres;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
@@ -105,6 +96,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
+		TBMIterator *tbmiterator = NULL;
+		TBMSharedIterator *shared_tbmiterator = NULL;
+
 		if (!pstate)
 		{
 			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -113,8 +107,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
-			node->tbmres = tbmres = NULL;
+			tbmiterator = tbm_begin_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -166,9 +159,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			}
 
 			/* Allocate a private iterator and attach the shared state to it */
-			node->shared_tbmiterator = shared_tbmiterator =
+			shared_tbmiterator =
 				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
-			node->tbmres = tbmres = NULL;
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
@@ -207,47 +199,23 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
+		scan->st.bitmap.rs_iterator = tbmiterator;
+		scan->st.bitmap.rs_shared_iterator = shared_tbmiterator;
 		node->initialized = true;
+
+		goto new_page;
 	}
 
 	for (;;)
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		/*
-		 * Get next page of results if needed
-		 */
-		if (tbmres == NULL)
-		{
-			if (!pstate)
-				node->tbmres = tbmres = tbm_iterate(tbmiterator);
-			else
-				node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
-			if (tbmres == NULL)
-			{
-				/* no more entries in the bitmap */
-				break;
-			}
-
-			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
-
-			if (!table_scan_bitmap_next_block(scan, tbmres,
-											  &node->stats.lossy_pages,
-											  &node->stats.exact_pages))
-			{
-				/* AM doesn't think this block is valid, skip */
-				continue;
-			}
-
-			/* Adjust the prefetch target */
-			BitmapAdjustPrefetchTarget(node);
-		}
-		else
+		while (table_scan_bitmap_next_tuple(scan, slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
 			 */
 
+			CHECK_FOR_INTERRUPTS();
+
 #ifdef USE_PREFETCH
 
 			/*
@@ -268,45 +236,64 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				SpinLockRelease(&pstate->mutex);
 			}
 #endif							/* USE_PREFETCH */
+
+			/*
+			 * We issue prefetch requests *after* fetching the current page to
+			 * try to avoid having prefetching interfere with the main I/O.
+			 * Also, this should happen only when we have determined there is
+			 * still something to do on the current page, else we may
+			 * uselessly prefetch the same page we are just about to request
+			 * for real.
+			 */
+			BitmapPrefetch(node, scan);
+
+			/*
+			 * If we are using lossy info, we have to recheck the qual
+			 * conditions at every tuple.
+			 */
+			if (node->recheck)
+			{
+				econtext->ecxt_scantuple = slot;
+				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+				{
+					/* Fails recheck, so drop it and loop back for another */
+					InstrCountFiltered2(node, 1);
+					ExecClearTuple(slot);
+					continue;
+				}
+			}
+
+			/* OK to return this tuple */
+			return slot;
 		}
 
-		/*
-		 * We issue prefetch requests *after* fetching the current page to try
-		 * to avoid having prefetching interfere with the main I/O. Also, this
-		 * should happen only when we have determined there is still something
-		 * to do on the current page, else we may uselessly prefetch the same
-		 * page we are just about to request for real.
-		 */
-		BitmapPrefetch(node, scan);
+new_page:
+
+		BitmapAdjustPrefetchIterator(node);
 
 		/*
-		 * Attempt to fetch tuple from AM.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
-		{
-			/* nothing more to look at on this page */
-			node->tbmres = tbmres = NULL;
-			continue;
-		}
+		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+										  &node->recheck,
+										  &node->stats.lossy_pages,
+										  &node->stats.exact_pages))
+			break;
 
 		/*
-		 * If we are using lossy info, we have to recheck the qual conditions
-		 * at every tuple.
+		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * ahead of the current block.
 		 */
-		if (tbmres->recheck)
-		{
-			econtext->ecxt_scantuple = slot;
-			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-			{
-				/* Fails recheck, so drop it and loop back for another */
-				InstrCountFiltered2(node, 1);
-				ExecClearTuple(slot);
-				continue;
-			}
-		}
-
-		/* OK to return this tuple */
-		return slot;
+		if (node->pstate == NULL &&
+			node->prefetch_iterator &&
+			node->prefetch_blockno < node->blockno)
+			elog(ERROR,
+				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
+				 node->prefetch_blockno, node->blockno);
+
+		/* Adjust the prefetch target */
+		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -332,13 +319,17 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 
 /*
  *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
  */
 static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
-							 BlockNumber blockno)
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -351,15 +342,22 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 		}
 		else if (prefetch_iterator)
 		{
-			/* Do not let the prefetch iterator get behind the main one */
-			TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-			if (tbmpre == NULL || tbmpre->blockno != blockno)
-				elog(ERROR, "prefetch and main iterators are out of sync");
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
+				InvalidBlockNumber;
 		}
 		return;
 	}
 
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
 	if (node->prefetch_maximum > 0)
 	{
 		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
@@ -384,7 +382,11 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
 			 * case.
 			 */
 			if (prefetch_iterator)
-				tbm_shared_iterate(prefetch_iterator);
+			{
+				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
+					InvalidBlockNumber;
+			}
 		}
 	}
 #endif							/* USE_PREFETCH */
@@ -462,6 +464,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 				node->prefetch_pages++;
+				node->prefetch_blockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -519,6 +522,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
+				node->prefetch_blockno = tbmpre->blockno;
+
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
@@ -575,17 +580,32 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 {
 	PlanState  *outerPlan = outerPlanState(node);
 
-	/* rescan to release any page pin */
-	if (node->ss.ss_currentScanDesc)
+	TableScanDesc scan = node->ss.ss_currentScanDesc;
+
+	if (scan)
+	{
+		/*
+		 * End iteration on iterators saved in scan descriptor.
+		 */
+		if (scan->st.bitmap.rs_shared_iterator)
+		{
+			tbm_end_shared_iterate(scan->st.bitmap.rs_shared_iterator);
+			scan->st.bitmap.rs_shared_iterator = NULL;
+		}
+
+		if (scan->st.bitmap.rs_iterator)
+		{
+			tbm_end_iterate(scan->st.bitmap.rs_iterator);
+			scan->st.bitmap.rs_iterator = NULL;
+		}
+
+		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
+	}
 
 	/* release bitmaps and buffers if any */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -593,13 +613,13 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->tbmiterator = NULL;
-	node->tbmres = NULL;
 	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_tbmiterator = NULL;
 	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
+	node->recheck = true;
+	node->blockno = InvalidBlockNumber;
+	node->prefetch_blockno = InvalidBlockNumber;
 
 	ExecScanReScan(&node->ss);
 
@@ -653,28 +673,40 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 */
 	ExecEndNode(outerPlanState(node));
 
+	if (scanDesc)
+	{
+		/*
+		 * End iteration on iterators saved in scan descriptor.
+		 */
+		if (scanDesc->st.bitmap.rs_shared_iterator)
+		{
+			tbm_end_shared_iterate(scanDesc->st.bitmap.rs_shared_iterator);
+			scanDesc->st.bitmap.rs_shared_iterator = NULL;
+		}
+
+		if (scanDesc->st.bitmap.rs_iterator)
+		{
+			tbm_end_iterate(scanDesc->st.bitmap.rs_iterator);
+			scanDesc->st.bitmap.rs_iterator = NULL;
+		}
+
+		/*
+		 * close table scan
+		 */
+		table_endscan(scanDesc);
+	}
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->tbmiterator)
-		tbm_end_iterate(node->tbmiterator);
 	if (node->prefetch_iterator)
 		tbm_end_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_tbmiterator)
-		tbm_end_shared_iterate(node->shared_tbmiterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
-
-	/*
-	 * close heap scan
-	 */
-	if (scanDesc)
-		table_endscan(scanDesc);
-
 }
 
 /* ----------------------------------------------------------------
@@ -707,8 +739,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->tbmiterator = NULL;
-	scanstate->tbmres = NULL;
 	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
@@ -718,9 +748,11 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->prefetch_pages = 0;
 	scanstate->prefetch_target = 0;
 	scanstate->initialized = false;
-	scanstate->shared_tbmiterator = NULL;
 	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
+	scanstate->recheck = true;
+	scanstate->blockno = InvalidBlockNumber;
+	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 114a85dc47c..e1884acf493 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -25,6 +25,9 @@
 
 struct ParallelTableScanDescData;
 
+struct TBMIterator;
+struct TBMSharedIterator;
+
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -37,9 +40,28 @@ typedef struct TableScanDescData
 	int			rs_nkeys;		/* number of scan keys */
 	struct ScanKeyData *rs_key; /* array of scan key descriptors */
 
-	/* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */
-	ItemPointerData rs_mintid;
-	ItemPointerData rs_maxtid;
+	/*
+	 * Scan type-specific members
+	 */
+	union
+	{
+		/* Iterators for Bitmap Table Scans */
+		struct
+		{
+			struct TBMIterator *rs_iterator;
+			struct TBMSharedIterator *rs_shared_iterator;
+		}			bitmap;
+
+		/*
+		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
+		 * scan.
+		 */
+		struct
+		{
+			ItemPointerData rs_mintid;
+			ItemPointerData rs_maxtid;
+		}			tidrange;
+	}			st;
 
 	/*
 	 * Information about type and behaviour of the scan, a bitmask of members
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index be09d180d45..ea4c21114ad 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,6 +21,7 @@
 #include "access/sdir.h"
 #include "access/xact.h"
 #include "executor/tuptable.h"
+#include "nodes/tidbitmap.h"
 #include "storage/read_stream.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
@@ -36,7 +37,6 @@ extern PGDLLIMPORT bool synchronize_seqscans;
 struct BulkInsertStateData;
 struct IndexInfo;
 struct SampleScanState;
-struct TBMIterateResult;
 struct VacuumParams;
 struct ValidateIndexState;
 
@@ -780,26 +780,29 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
-	 * of a bitmap table scan. `scan` was started via table_beginscan_bm().
-	 * Return false if there are no tuples to be found on the page, true
-	 * otherwise.
+	 * Prepare to fetch / check / return tuples from `blockno` as part of a
+	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
+	 * false if the bitmap is exhausted and true otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time). For some
-	 * AMs it will make more sense to do all the work referencing `tbmres`
-	 * contents here, for others it might be better to defer more work to
-	 * scan_bitmap_next_tuple.
-	 *
-	 * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
-	 * on the page have to be returned, otherwise the tuples at offsets in
-	 * `tbmres->offsets` need to be returned.
+	 * make sense to perform tuple visibility checks at this time).
 	 *
 	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
 	 * incremented by the table AM to indicate whether or not the block's
 	 * representation in the bitmap is lossy.
 	 *
+	 * `recheck` is set by the table AM to indicate whether or not the tuples
+	 * from this block should be rechecked. Tuples from lossy pages will
+	 * always need to be rechecked, but some non-lossy pages' tuples may also
+	 * require recheck.
+	 *
+	 * `blockno` is the current block and is set by the table AM. The table AM
+	 * is responsible for advancing the main iterator, but the bitmap table
+	 * scan code still advances the prefetch iterator. `blockno` is used by
+	 * bitmap table scan code to validate that the prefetch block stays ahead
+	 * of the current block.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -815,7 +818,8 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
+										   BlockNumber *blockno,
+										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
@@ -823,15 +827,10 @@ typedef struct TableAmRoutine
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
 	 * if a visible tuple was found, false otherwise.
 	 *
-	 * For some AMs it will make more sense to do all the work referencing
-	 * `tbmres` contents in scan_bitmap_next_block, for others it might be
-	 * better to defer more work to this callback.
-	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres,
 										   TupleTableSlot *slot);
 
 	/*
@@ -959,12 +958,17 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
+										 NULL, flags);
+	result->st.bitmap.rs_shared_iterator = NULL;
+	result->st.bitmap.rs_iterator = NULL;
+	return result;
 }
 
 /*
@@ -1955,21 +1959,28 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
- * a bitmap table scan. `scan` needs to have been started via
- * table_beginscan_bm(). Returns false if there are no tuples to be found on
- * the page, true otherwise.
+ * Prepare to fetch / check / return tuples as part of a bitmap table scan.
+ * `scan` needs to have been started via table_beginscan_bm(). Returns false
+ * if there are no more blocks in the bitmap, true otherwise.
  *
  * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
  * incremented by the table AM to indicate whether or not the block's
  * representation in the bitmap is lossy.
  *
+ * `recheck` is set by the table AM to indicate whether or not the tuples
+ * from this block should be rechecked.
+ *
+ * `blockno` is the current block and is set by the table AM and is used by
+ * bitmap table scan code to validate that the prefetch block stays ahead of
+ * the current block.
+ *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
+							 BlockNumber *blockno,
+							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
 {
@@ -1982,7 +1993,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres,
+														   blockno, recheck,
 														   lossy_pages,
 														   exact_pages);
 }
@@ -1997,7 +2008,6 @@ table_scan_bitmap_next_block(TableScanDesc scan,
  */
 static inline bool
 table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres,
 							 TupleTableSlot *slot)
 {
 	/*
@@ -2009,7 +2019,6 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   tbmres,
 														   slot);
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e4698a28c4f..b67d5186a2d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1833,8 +1833,6 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		tbmiterator		   iterator for scanning current pages
- *		tbmres			   current-page data
  *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
  *		prefetch_iterator  iterator for prefetching ahead of current page
@@ -1842,10 +1840,12 @@ typedef struct SharedBitmapHeapInstrumentation
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_tbmiterator	   shared iterator
  *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
+ *		recheck			   do current page's tuples need recheck
+ *		blockno			   used to validate pf and current block stay in sync
+ *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1853,8 +1853,6 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	TBMIterator *tbmiterator;
-	TBMIterateResult *tbmres;
 	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
 	TBMIterator *prefetch_iterator;
@@ -1862,10 +1860,12 @@ typedef struct BitmapHeapScanState
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_tbmiterator;
 	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
+	bool		recheck;
+	BlockNumber blockno;
+	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.45.2

v25-0004-Add-common-interface-for-TBMIterators.patchapplication/octet-stream; name=v25-0004-Add-common-interface-for-TBMIterators.patchDownload
From b4192670c95b40f8ca4f6214b9ead76e2b3cbf6c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 12:41:05 -0400
Subject: [PATCH v25 04/11] Add common interface for TBMIterators

Add and use TBMPrivateIterator, which replaces the current TBMIterator
for serial use cases, and repurpose TBMIterator to be a unified
interface for both the serial ("private") and parallel ("shared") TID
Bitmap iterator interfaces. This encapsulation simplifies call sites for
callers supporting both parallel and serial TID Bitmap access.
TBMIterator is not yet used in this commit.

Author: Melanie Plageman
Reviewed-by: Heikki Linnakangas
Discussion: https://postgr.es/m/063e4eb4-32d9-439e-a0b1-75565a9835a8%40iki.fi
---
 src/backend/access/gin/ginget.c           |  10 +-
 src/backend/access/gin/ginscan.c          |   2 +-
 src/backend/access/heap/heapam_handler.c  |   2 +-
 src/backend/executor/nodeBitmapHeapscan.c |  27 +++---
 src/backend/nodes/tidbitmap.c             | 112 +++++++++++++++++-----
 src/include/access/gin_private.h          |   2 +-
 src/include/access/relscan.h              |   4 +-
 src/include/nodes/execnodes.h             |   2 +-
 src/include/nodes/tidbitmap.h             |  30 +++++-
 src/tools/pgindent/typedefs.list          |   1 +
 10 files changed, 140 insertions(+), 52 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0b4f2ebadb6..e8e0eab6552 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -373,7 +373,7 @@ restartScanEntry:
 			if (entry->matchBitmap)
 			{
 				if (entry->matchIterator)
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -385,7 +385,8 @@ restartScanEntry:
 
 		if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
 		{
-			entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+			entry->matchIterator =
+				tbm_begin_private_iterate(entry->matchBitmap);
 			entry->isFinished = false;
 		}
 	}
@@ -832,12 +833,13 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
 			{
-				entry->matchResult = tbm_iterate(entry->matchIterator);
+				entry->matchResult =
+					tbm_private_iterate(entry->matchIterator);
 
 				if (entry->matchResult == NULL)
 				{
 					ItemPointerSetInvalid(&entry->curItem);
-					tbm_end_iterate(entry->matchIterator);
+					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
 					entry->isFinished = true;
 					break;
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index f2fd62afbbf..2c6631c914d 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -246,7 +246,7 @@ ginFreeScanKeys(GinScanOpaque so)
 		if (entry->list)
 			pfree(entry->list);
 		if (entry->matchIterator)
-			tbm_end_iterate(entry->matchIterator);
+			tbm_end_private_iterate(entry->matchIterator);
 		if (entry->matchBitmap)
 			tbm_free(entry->matchBitmap);
 	}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 1536fa9f2d9..a85edd60d78 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2138,7 +2138,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (scan->st.bitmap.rs_shared_iterator)
 			tbmres = tbm_shared_iterate(scan->st.bitmap.rs_shared_iterator);
 		else
-			tbmres = tbm_iterate(scan->st.bitmap.rs_iterator);
+			tbmres = tbm_private_iterate(scan->st.bitmap.rs_iterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 89a16f142b7..5fdbe1315b8 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,7 +96,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator *tbmiterator = NULL;
+		TBMPrivateIterator *tbmiterator = NULL;
 		TBMSharedIterator *shared_tbmiterator = NULL;
 
 		if (!pstate)
@@ -107,12 +107,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_iterate(tbm);
+			tbmiterator = tbm_begin_private_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->prefetch_iterator = tbm_begin_iterate(tbm);
+				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
 				node->prefetch_pages = 0;
 				node->prefetch_target = -1;
 			}
@@ -282,7 +282,7 @@ new_page:
 			break;
 
 		/*
-		 * If serial, we can error out if the the prefetch block doesn't stay
+		 * If private, we can error out if the the prefetch block doesn't stay
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
@@ -333,7 +333,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
@@ -342,7 +342,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (prefetch_iterator)
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
+			tbmpre = tbm_private_iterate(prefetch_iterator);
 			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
 				InvalidBlockNumber;
 		}
@@ -447,19 +447,20 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
 		if (prefetch_iterator)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult *tbmpre;
 				bool		skip_fetch;
 
+				tbmpre = tbm_private_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
+					tbm_end_private_iterate(prefetch_iterator);
 					node->prefetch_iterator = NULL;
 					break;
 				}
@@ -595,7 +596,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 		if (scan->st.bitmap.rs_iterator)
 		{
-			tbm_end_iterate(scan->st.bitmap.rs_iterator);
+			tbm_end_private_iterate(scan->st.bitmap.rs_iterator);
 			scan->st.bitmap.rs_iterator = NULL;
 		}
 
@@ -605,7 +606,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
 	/* release bitmaps and buffers if any */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->shared_prefetch_iterator)
 		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
@@ -686,7 +687,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 
 		if (scanDesc->st.bitmap.rs_iterator)
 		{
-			tbm_end_iterate(scanDesc->st.bitmap.rs_iterator);
+			tbm_end_private_iterate(scanDesc->st.bitmap.rs_iterator);
 			scanDesc->st.bitmap.rs_iterator = NULL;
 		}
 
@@ -700,7 +701,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 	 * release bitmaps and buffers if any
 	 */
 	if (node->prefetch_iterator)
-		tbm_end_iterate(node->prefetch_iterator);
+		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->shared_prefetch_iterator)
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index e8ab5d78fcc..c1ecf2a41a9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -170,12 +170,12 @@ struct TIDBitmap
 };
 
 /*
- * When iterating over a bitmap in sorted order, a TBMIterator is used to
- * track our progress.  There can be several iterators scanning the same
- * bitmap concurrently.  Note that the bitmap becomes read-only as soon as
- * any iterator is created.
+ * When iterating over a backend-local bitmap in sorted order, a
+ * TBMPrivateIterator is used to track our progress.  There can be several
+ * iterators scanning the same bitmap concurrently.  Note that the bitmap
+ * becomes read-only as soon as any iterator is created.
  */
-struct TBMIterator
+struct TBMPrivateIterator
 {
 	TIDBitmap  *tbm;			/* TIDBitmap we're iterating over */
 	int			spageptr;		/* next spages index */
@@ -213,8 +213,8 @@ typedef struct PTIterationArray
 } PTIterationArray;
 
 /*
- * same as TBMIterator, but it is used for joint iteration, therefore this
- * also holds a reference to the shared state.
+ * same as TBMPrivateIterator, but it is used for joint iteration, therefore
+ * this also holds a reference to the shared state.
  */
 struct TBMSharedIterator
 {
@@ -673,31 +673,32 @@ tbm_is_empty(const TIDBitmap *tbm)
 }
 
 /*
- * tbm_begin_iterate - prepare to iterate through a TIDBitmap
+ * tbm_begin_private_iterate - prepare to iterate through a TIDBitmap
  *
- * The TBMIterator struct is created in the caller's memory context.
- * For a clean shutdown of the iteration, call tbm_end_iterate; but it's
- * okay to just allow the memory context to be released, too.  It is caller's
- * responsibility not to touch the TBMIterator anymore once the TIDBitmap
- * is freed.
+ * The TBMPrivateIterator struct is created in the caller's memory context.
+ * For a clean shutdown of the iteration, call tbm_end_iterate; but it's okay
+ * to just allow the memory context to be released, too.  It is caller's
+ * responsibility not to touch the TBMPrivateIterator anymore once the
+ * TIDBitmap is freed.
  *
  * NB: after this is called, it is no longer allowed to modify the contents
  * of the bitmap.  However, you can call this multiple times to scan the
  * contents repeatedly, including parallel scans.
  */
-TBMIterator *
-tbm_begin_iterate(TIDBitmap *tbm)
+TBMPrivateIterator *
+tbm_begin_private_iterate(TIDBitmap *tbm)
 {
-	TBMIterator *iterator;
+	TBMPrivateIterator *iterator;
 
 	Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
 	/*
-	 * Create the TBMIterator struct, with enough trailing space to serve the
-	 * needs of the TBMIterateResult sub-struct.
+	 * Create the TBMPrivateIterator struct, with enough trailing space to
+	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-									  MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
+											 MAX_TUPLES_PER_PAGE *
+											 sizeof(OffsetNumber));
 	iterator->tbm = tbm;
 
 	/*
@@ -956,7 +957,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 }
 
 /*
- * tbm_iterate - scan through next page of a TIDBitmap
+ * tbm_private_iterate - scan through next page of a TIDBitmap
  *
  * Returns a TBMIterateResult representing one page, or NULL if there are
  * no more pages to scan.  Pages are guaranteed to be delivered in numerical
@@ -968,7 +969,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  * testing, recheck is always set true when ntuples < 0.)
  */
 TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+tbm_private_iterate(TBMPrivateIterator *iterator)
 {
 	TIDBitmap  *tbm = iterator->tbm;
 	TBMIterateResult *output = &(iterator->output);
@@ -1136,14 +1137,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 }
 
 /*
- * tbm_end_iterate - finish an iteration over a TIDBitmap
+ * tbm_end_private_iterate - finish an iteration over a TIDBitmap
  *
  * Currently this is just a pfree, but it might do more someday.  (For
  * instance, it could be useful to count open iterators and allow the
  * bitmap to return to read/write status when there are no more iterators.)
  */
 void
-tbm_end_iterate(TBMIterator *iterator)
+tbm_end_private_iterate(TBMPrivateIterator *iterator)
 {
 	pfree(iterator);
 }
@@ -1556,3 +1557,66 @@ tbm_calculate_entries(double maxbytes)
 
 	return nbuckets;
 }
+
+/*
+ * Create a shared or private bitmap iterator and start iteration.
+ *
+ * `tbm` is only used to create the private iterator and dsa and dsp are only
+ * used to create the shared iterator.
+ *
+ * Before invoking tbm_begin_iterate() to create a shared iterator, one
+ * process must already have invoked tbm_prepare_shared_iterate() to create
+ * and set up the TBMSharedIteratorState.
+ */
+TBMIterator
+tbm_begin_iterate(TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp)
+{
+	TBMIterator iterator = {0};
+
+	/* Allocate a private iterator and attach the shared state to it */
+	if (DsaPointerIsValid(dsp))
+	{
+		iterator.shared = true;
+		iterator.shared_iterator = tbm_attach_shared_iterate(dsa, dsp);
+	}
+	else
+	{
+		iterator.shared = false;
+		iterator.private_iterator = tbm_begin_private_iterate(tbm);
+	}
+
+	return iterator;
+}
+
+/*
+ * Clean up shared or private bitmap iterator.
+ */
+void
+tbm_end_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->shared)
+		tbm_end_shared_iterate(iterator->shared_iterator);
+	else
+		tbm_end_private_iterate(iterator->private_iterator);
+
+	*iterator = (TBMIterator)
+	{
+		0
+	};
+}
+
+/*
+ * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ */
+TBMIterateResult *
+tbm_iterate(TBMIterator *iterator)
+{
+	Assert(iterator);
+
+	if (iterator->shared)
+		return tbm_shared_iterate(iterator->shared_iterator);
+	else
+		return tbm_private_iterate(iterator->private_iterator);
+}
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 3013a44bae1..78800509367 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
-	TBMIterator *matchIterator;
+	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index e1884acf493..153561addc0 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -25,7 +25,7 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
+struct TBMPrivateIterator;
 struct TBMSharedIterator;
 
 /*
@@ -48,7 +48,7 @@ typedef struct TableScanDescData
 		/* Iterators for Bitmap Table Scans */
 		struct
 		{
-			struct TBMIterator *rs_iterator;
+			struct TBMPrivateIterator *rs_iterator;
 			struct TBMSharedIterator *rs_shared_iterator;
 		}			bitmap;
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index b67d5186a2d..73266920f3a 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1855,7 +1855,7 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator *prefetch_iterator;
+	TBMPrivateIterator *prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1945f0639bf..65ecc5ba045 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -32,10 +32,24 @@
  */
 typedef struct TIDBitmap TIDBitmap;
 
-/* Likewise, TBMIterator is private */
-typedef struct TBMIterator TBMIterator;
+/* Likewise, TBMPrivateIterator is private */
+typedef struct TBMPrivateIterator TBMPrivateIterator;
 typedef struct TBMSharedIterator TBMSharedIterator;
 
+/*
+ * Callers with both private and shared implementations can use this unified
+ * API.
+ */
+typedef struct TBMIterator
+{
+	bool		shared;
+	union
+	{
+		TBMPrivateIterator *private_iterator;
+		TBMSharedIterator *shared_iterator;
+	};
+} TBMIterator;
+
 /* Result structure for tbm_iterate */
 typedef struct TBMIterateResult
 {
@@ -62,14 +76,20 @@ extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
-extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
 extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
-extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
 													dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
+									 dsa_area *dsa, dsa_pointer dsp);
+extern void tbm_end_iterate(TBMIterator *iterator);
+
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+
 #endif							/* TIDBITMAP_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 57de1acff3a..f219e806c8b 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2806,6 +2806,7 @@ TAR_MEMBER
 TBMIterateResult
 TBMIteratingState
 TBMIterator
+TBMPrivateIterator
 TBMSharedIterator
 TBMSharedIteratorState
 TBMStatus
-- 
2.45.2

v25-0005-Bitmap-Table-Scans-use-unified-TBMIterator.patchapplication/octet-stream; name=v25-0005-Bitmap-Table-Scans-use-unified-TBMIterator.patchDownload
From 0f5446c886e2750b8c1a4f99ca5f4203ee56a830 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 May 2024 13:39:04 -0400
Subject: [PATCH v25 05/11] Bitmap Table Scans use unified TBMIterator

With the repurposing of TBMIterator as an interface for both parallel
and serial iteration through TIDBitmaps in commit [XXX: put commit
here], bitmap table scans may now use it.

Modify bitmap table scan code to use the TBMIterator. This requires
moving around a bit of code, so a few variables are initialized
elsewhere.

Author: Melanie Plageman
---
 src/backend/access/heap/heapam_handler.c  |   5 +-
 src/backend/executor/nodeBitmapHeapscan.c | 170 +++++++++-------------
 src/include/access/relscan.h              |  12 +-
 src/include/access/tableam.h              |   8 +-
 src/include/nodes/execnodes.h             |   4 +-
 src/include/nodes/tidbitmap.h             |  10 ++
 6 files changed, 86 insertions(+), 123 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a85edd60d78..c51f5e921f1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2135,10 +2135,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		if (scan->st.bitmap.rs_shared_iterator)
-			tbmres = tbm_shared_iterate(scan->st.bitmap.rs_shared_iterator);
-		else
-			tbmres = tbm_private_iterate(scan->st.bitmap.rs_iterator);
+		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
 
 		if (tbmres == NULL)
 			return false;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5fdbe1315b8..b35d09c2ef3 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -96,8 +96,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 */
 	if (!node->initialized)
 	{
-		TBMPrivateIterator *tbmiterator = NULL;
-		TBMSharedIterator *shared_tbmiterator = NULL;
+		TBMIterator tbmiterator;
 
 		if (!pstate)
 		{
@@ -107,70 +106,62 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-			tbmiterator = tbm_begin_private_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
-			{
-				node->prefetch_iterator = tbm_begin_private_iterate(tbm);
-				node->prefetch_pages = 0;
-				node->prefetch_target = -1;
-			}
+				node->prefetch_iterator =
+					tbm_begin_iterate(node->tbm, dsa,
+									  pstate ?
+									  pstate->prefetch_iterator :
+									  InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 		}
-		else
+		else if (BitmapShouldInitializeSharedState(pstate))
 		{
 			/*
 			 * The leader will immediately come out of the function, but
 			 * others will be blocked until leader populates the TBM and wakes
 			 * them up.
 			 */
-			if (BitmapShouldInitializeSharedState(pstate))
-			{
-				tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-				if (!tbm || !IsA(tbm, TIDBitmap))
-					elog(ERROR, "unrecognized result from subplan");
-
-				node->tbm = tbm;
-
-				/*
-				 * Prepare to iterate over the TBM. This will return the
-				 * dsa_pointer of the iterator state which will be used by
-				 * multiple processes to iterate jointly.
-				 */
-				pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
-				if (node->prefetch_maximum > 0)
-				{
-					pstate->prefetch_iterator =
-						tbm_prepare_shared_iterate(tbm);
-
-					/*
-					 * We don't need the mutex here as we haven't yet woke up
-					 * others.
-					 */
-					pstate->prefetch_pages = 0;
-					pstate->prefetch_target = -1;
-				}
-#endif
+			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+			if (!tbm || !IsA(tbm, TIDBitmap))
+				elog(ERROR, "unrecognized result from subplan");
 
-				/* We have initialized the shared state so wake up others. */
-				BitmapDoneInitializingSharedState(pstate);
-			}
+			node->tbm = tbm;
 
-			/* Allocate a private iterator and attach the shared state to it */
-			shared_tbmiterator =
-				tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+			/*
+			 * Prepare to iterate over the TBM. This will return the
+			 * dsa_pointer of the iterator state which will be used by
+			 * multiple processes to iterate jointly.
+			 */
+			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 
 #ifdef USE_PREFETCH
 			if (node->prefetch_maximum > 0)
 			{
-				node->shared_prefetch_iterator =
-					tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+				pstate->prefetch_iterator =
+					tbm_prepare_shared_iterate(tbm);
 			}
 #endif							/* USE_PREFETCH */
+
+			/* We have initialized the shared state so wake up others. */
+			BitmapDoneInitializingSharedState(pstate);
 		}
 
+		tbmiterator = tbm_begin_iterate(tbm, dsa,
+										pstate ?
+										pstate->tbmiterator :
+										InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+			node->prefetch_iterator =
+				tbm_begin_iterate(tbm, dsa,
+								  pstate ?
+								  pstate->prefetch_iterator :
+								  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
 		/*
 		 * If this is the first scan of the underlying table, create the table
 		 * scan descriptor and begin the scan.
@@ -199,8 +190,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->st.bitmap.rs_iterator = tbmiterator;
-		scan->st.bitmap.rs_shared_iterator = shared_tbmiterator;
+		scan->st.rs_tbmiterator = tbmiterator;
 		node->initialized = true;
 
 		goto new_page;
@@ -286,7 +276,7 @@ new_page:
 		 * ahead of the current block.
 		 */
 		if (node->pstate == NULL &&
-			node->prefetch_iterator &&
+			!tbm_exhausted(&node->prefetch_iterator) &&
 			node->prefetch_blockno < node->blockno)
 			elog(ERROR,
 				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
@@ -333,16 +323,16 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		if (node->prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
 			node->prefetch_pages--;
 		}
-		else if (prefetch_iterator)
+		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_private_iterate(prefetch_iterator);
+			tbmpre = tbm_iterate(prefetch_iterator);
 			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
 				InvalidBlockNumber;
 		}
@@ -360,7 +350,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 */
 	if (node->prefetch_maximum > 0)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -381,9 +371,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 * we don't validate the blockno here as we do in non-parallel
 			 * case.
 			 */
-			if (prefetch_iterator)
+			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
 					InvalidBlockNumber;
 			}
@@ -447,21 +437,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate == NULL)
 	{
-		TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!tbm_exhausted(prefetch_iterator))
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
 
-				tbmpre = tbm_private_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_private_iterate(prefetch_iterator);
-					node->prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
@@ -489,9 +477,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
 
-		if (prefetch_iterator)
+		if (!tbm_exhausted(prefetch_iterator))
 		{
 			while (1)
 			{
@@ -514,12 +502,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_shared_iterate(prefetch_iterator);
+				tbmpre = tbm_iterate(prefetch_iterator);
 				if (tbmpre == NULL)
 				{
 					/* No more pages to prefetch */
-					tbm_end_shared_iterate(prefetch_iterator);
-					node->shared_prefetch_iterator = NULL;
+					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
@@ -588,39 +575,30 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		if (scan->st.bitmap.rs_shared_iterator)
-		{
-			tbm_end_shared_iterate(scan->st.bitmap.rs_shared_iterator);
-			scan->st.bitmap.rs_shared_iterator = NULL;
-		}
-
-		if (scan->st.bitmap.rs_iterator)
-		{
-			tbm_end_private_iterate(scan->st.bitmap.rs_iterator);
-			scan->st.bitmap.rs_iterator = NULL;
-		}
+		tbm_end_iterate(&scan->st.rs_tbmiterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
+	/* If we did not already clean up the prefetch iterator, do so now. */
+	if (!tbm_exhausted(&node->prefetch_iterator))
+		tbm_end_iterate(&node->prefetch_iterator);
+
 	/* release bitmaps and buffers if any */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
-	node->prefetch_iterator = NULL;
 	node->initialized = false;
-	node->shared_prefetch_iterator = NULL;
 	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
+	/* Only used for serial BHS */
 	node->blockno = InvalidBlockNumber;
 	node->prefetch_blockno = InvalidBlockNumber;
+	node->prefetch_pages = 0;
+	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -679,17 +657,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		if (scanDesc->st.bitmap.rs_shared_iterator)
-		{
-			tbm_end_shared_iterate(scanDesc->st.bitmap.rs_shared_iterator);
-			scanDesc->st.bitmap.rs_shared_iterator = NULL;
-		}
-
-		if (scanDesc->st.bitmap.rs_iterator)
-		{
-			tbm_end_private_iterate(scanDesc->st.bitmap.rs_iterator);
-			scanDesc->st.bitmap.rs_iterator = NULL;
-		}
+		tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
 
 		/*
 		 * close table scan
@@ -697,15 +665,15 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
+	/* If we did not already clean up the prefetch iterator, do so now. */
+	if (!tbm_exhausted(&node->prefetch_iterator))
+		tbm_end_iterate(&node->prefetch_iterator);
+
 	/*
 	 * release bitmaps and buffers if any
 	 */
-	if (node->prefetch_iterator)
-		tbm_end_private_iterate(node->prefetch_iterator);
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->shared_prefetch_iterator)
-		tbm_end_shared_iterate(node->shared_prefetch_iterator);
 	if (node->pvmbuffer != InvalidBuffer)
 		ReleaseBuffer(node->pvmbuffer);
 }
@@ -745,11 +713,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_iterator = NULL;
 	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = 0;
+	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
-	scanstate->shared_prefetch_iterator = NULL;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
 	scanstate->blockno = InvalidBlockNumber;
@@ -908,7 +874,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
 	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = 0;
+	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -945,6 +911,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
+	pstate->prefetch_pages = 0;
+	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 153561addc0..8ca8f789617 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/itup.h"
+#include "nodes/tidbitmap.h"
 #include "port/atomics.h"
 #include "storage/buf.h"
 #include "storage/relfilelocator.h"
@@ -25,9 +26,6 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMPrivateIterator;
-struct TBMSharedIterator;
-
 /*
  * Generic descriptor for table scans. This is the base-class for table scans,
  * which needs to be embedded in the scans of individual AMs.
@@ -45,12 +43,8 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterators for Bitmap Table Scans */
-		struct
-		{
-			struct TBMPrivateIterator *rs_iterator;
-			struct TBMSharedIterator *rs_shared_iterator;
-		}			bitmap;
+		/* Iterator for Bitmap Table Scans */
+		TBMIterator rs_tbmiterator;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ea4c21114ad..dbcea659fbc 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -958,17 +958,13 @@ static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
-	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-										 NULL, flags);
-	result->st.bitmap.rs_shared_iterator = NULL;
-	result->st.bitmap.rs_iterator = NULL;
-	return result;
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
+									   NULL, flags);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 73266920f3a..7cd4b57509e 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1840,7 +1840,6 @@ typedef struct SharedBitmapHeapInstrumentation
  *		prefetch_target    current target prefetch distance
  *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
- *		shared_prefetch_iterator shared iterator for prefetching
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
@@ -1855,12 +1854,11 @@ typedef struct BitmapHeapScanState
 	TIDBitmap  *tbm;
 	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMPrivateIterator *prefetch_iterator;
+	TBMIterator prefetch_iterator;
 	int			prefetch_pages;
 	int			prefetch_target;
 	int			prefetch_maximum;
 	bool		initialized;
-	TBMSharedIterator *shared_prefetch_iterator;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 65ecc5ba045..db678d541fc 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -92,4 +92,14 @@ extern void tbm_end_iterate(TBMIterator *iterator);
 
 extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
 
+static inline bool
+tbm_exhausted(TBMIterator *iterator)
+{
+	/*
+	 * It doesn't matter if we check the private or shared iterator here. If
+	 * tbm_end_iterate() was called, they will be NULL
+	 */
+	return !iterator->private_iterator;
+}
+
 #endif							/* TIDBITMAP_H */
-- 
2.45.2

v25-0002-table_scan_bitmap_next_block-implementations-cou.patchapplication/octet-stream; name=v25-0002-table_scan_bitmap_next_block-implementations-cou.patchDownload
From abb7cbcc8761f2a43792763d99d69cc1f1b6ed0f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Apr 2024 08:51:40 -0400
Subject: [PATCH v25 02/11] table_scan_bitmap_next_block implementations count
 lossy and exact pages

Keep track of whether or not individual TBMIterateResult's blocks were
represented lossily in the bitmap in table AM-specific code. These
counters are used for EXPLAIN.

This is a step toward removing TBMIterateResults as a flow control
mechanism in BitmapHeapNext(), which is required for the more
asynchronous design required to use the read stream API. It also is more
table AM-agnostic.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra, Heikki Linnakangas
Discussion: https://postgr.es/m/063e4eb4-32d9-439e-a0b1-75565a9835a8%40iki.fi
---
 src/backend/access/heap/heapam_handler.c  |  8 +++++++-
 src/backend/executor/nodeBitmapHeapscan.c | 13 +++----------
 src/include/access/tableam.h              | 20 +++++++++++++++++---
 3 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bdb7599684b..753d0384ead 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2115,7 +2115,8 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  TBMIterateResult *tbmres)
+							  TBMIterateResult *tbmres,
+							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
 	BlockNumber block = tbmres->blockno;
@@ -2243,6 +2244,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
 	return ntup > 0;
 }
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3c63bdd93df..f4690a20bb1 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -212,8 +212,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 	for (;;)
 	{
-		bool		valid_block;
-
 		CHECK_FOR_INTERRUPTS();
 
 		/*
@@ -233,14 +231,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			BitmapAdjustPrefetchIterator(node, tbmres->blockno);
 
-			valid_block = table_scan_bitmap_next_block(scan, tbmres);
-
-			if (tbmres->ntuples >= 0)
-				node->stats.exact_pages++;
-			else
-				node->stats.lossy_pages++;
-
-			if (!valid_block)
+			if (!table_scan_bitmap_next_block(scan, tbmres,
+											  &node->stats.lossy_pages,
+											  &node->stats.exact_pages))
 			{
 				/* AM doesn't think this block is valid, skip */
 				continue;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index da661289c1f..be09d180d45 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -796,6 +796,10 @@ typedef struct TableAmRoutine
 	 * on the page have to be returned, otherwise the tuples at offsets in
 	 * `tbmres->offsets` need to be returned.
 	 *
+	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
+	 * incremented by the table AM to indicate whether or not the block's
+	 * representation in the bitmap is lossy.
+	 *
 	 * XXX: Currently this may only be implemented if the AM uses md.c as its
 	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
 	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
@@ -811,7 +815,9 @@ typedef struct TableAmRoutine
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   struct TBMIterateResult *tbmres);
+										   struct TBMIterateResult *tbmres,
+										   uint64 *lossy_pages,
+										   uint64 *exact_pages);
 
 	/*
 	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
@@ -1954,12 +1960,18 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * table_beginscan_bm(). Returns false if there are no tuples to be found on
  * the page, true otherwise.
  *
+ * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
+ * incremented by the table AM to indicate whether or not the block's
+ * representation in the bitmap is lossy.
+ *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 struct TBMIterateResult *tbmres)
+							 struct TBMIterateResult *tbmres,
+							 uint64 *lossy_pages,
+							 uint64 *exact_pages)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
@@ -1970,7 +1982,9 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   tbmres);
+														   tbmres,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.45.2

v25-0006-Add-and-use-BitmapHeapScanDesc-struct.patchapplication/octet-stream; name=v25-0006-Add-and-use-BitmapHeapScanDesc-struct.patchDownload
From 18fbbdeb912be86c17dd994c9d7c2812f28820d6 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 8 Oct 2024 18:56:40 -0400
Subject: [PATCH v25 06/11] Add and use BitmapHeapScanDesc struct

Move the several members of HeapScanDesc which are specific to Bitmap
Heap Scans into a new struct BitmapHeapScanDesc which inherits from
HeapScanDesc.

This reduces the size of the HeapScanDesc for other types of scans and
will allow us to add additional bitmap heap scan-specific members in
the future without fear of bloating the HeapScanDesc.

Author: Melanie Plageman
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/c736f6aa-8b35-4e20-9621-62c7c82e2168%40vondra.me
---
 src/backend/access/heap/heapam.c         | 50 ++++++++++++++++--------
 src/backend/access/heap/heapam_handler.c | 18 +++++----
 src/include/access/heapam.h              | 24 ++++++++----
 src/tools/pgindent/typedefs.list         |  1 +
 4 files changed, 62 insertions(+), 31 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index f9e3be1e846..90f6816922c 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1046,7 +1046,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	/*
 	 * allocate and initialize scan descriptor
 	 */
-	scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
+	if (flags & SO_TYPE_BITMAPSCAN)
+	{
+		BitmapHeapScanDesc bscan = palloc(sizeof(BitmapHeapScanDescData));
+
+		bscan->rs_vmbuffer = InvalidBuffer;
+		bscan->rs_empty_tuples_pending = 0;
+		scan = (HeapScanDesc) bscan;
+	}
+	else
+		scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
 
 	scan->rs_base.rs_rd = relation;
 	scan->rs_base.rs_snapshot = snapshot;
@@ -1054,8 +1063,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1171,18 +1178,23 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
+		BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 
-	/*
-	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
-	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
-	 * on rescan.
-	 */
-	scan->rs_empty_tuples_pending = 0;
+		/*
+		 * Reset empty_tuples_pending, a field only used by bitmap heap scan,
+		 * to avoid incorrectly emitting NULL-filled tuples from a previous
+		 * scan on rescan.
+		 */
+		bscan->rs_empty_tuples_pending = 0;
+
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+	}
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1211,9 +1223,6 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
-
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
 	 */
@@ -1237,6 +1246,15 @@ heap_endscan(TableScanDesc sscan)
 	if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
 		UnregisterSnapshot(scan->rs_base.rs_snapshot);
 
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) sscan;
+
+		bscan->rs_empty_tuples_pending = 0;
+		if (BufferIsValid(bscan->rs_vmbuffer))
+			ReleaseBuffer(bscan->rs_vmbuffer);
+	}
+
 	pfree(scan);
 }
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c51f5e921f1..192a326a019 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2118,13 +2118,16 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  BlockNumber *blockno, bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
 
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
@@ -2162,13 +2165,13 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2282,18 +2285,19 @@ static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
 {
-	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (bscan->rs_empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		bscan->rs_empty_tuples_pending--;
 		return true;
 	}
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index b951466ced2..a789c608f1d 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -92,22 +92,30 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDescData
+{
+	HeapScanDescData rs_heap_base;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
 	 * fetching an all visible block, instead using the number of tuples per
 	 * block reported by the bitmap to determine how many NULL-filled tuples
-	 * to return.
+	 * to return. They are common to parallel and serial BitmapHeapScans
 	 */
+
+	/* page of VM containing info for current block */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+}			BitmapHeapScanDescData;
+typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index f219e806c8b..88045252768 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -263,6 +263,7 @@ BitmapAndState
 BitmapHeapPath
 BitmapHeapScan
 BitmapHeapScanInstrumentation
+BitmapHeapScanDesc
 BitmapHeapScanState
 BitmapIndexScan
 BitmapIndexScanState
-- 
2.45.2

v25-0010-Remove-table-AM-callback-scan_bitmap_next_block.patchapplication/octet-stream; name=v25-0010-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 7560f29cece7bfa4c75d3e9a0d8495543edbf5e5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 9 Oct 2024 16:47:33 -0400
Subject: [PATCH v25 10/11] Remove table AM callback scan_bitmap_next_block

Remove table AM callback scan_bitmap_next_block(). This makes
implementing bitmap table scans easier for non block-based table AMs and
makes BitmapHeapNext() control flow similar to SeqNext().

Now bitmap table scan code only calls table_scan_bitmap_next_tuple().
The heap AM implementation of scan_bitmap_next_block() is now a local
helper in heapam_handler.c.
---
 src/backend/access/heap/heapam.c          |  6 ++
 src/backend/access/heap/heapam_handler.c  | 58 +++++++++-----
 src/backend/access/table/tableamapi.c     |  2 -
 src/backend/executor/nodeBitmapHeapscan.c | 63 ++++++---------
 src/backend/optimizer/util/plancat.c      |  2 +-
 src/include/access/tableam.h              | 94 ++++++-----------------
 6 files changed, 91 insertions(+), 134 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b8d8d0452aa..9b3878aff37 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -379,6 +379,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
 	scan->rs_cindex = 0;
+	scan->rs_ntuples = 0;
+
 
 	/*
 	 * Initialize to ForwardScanDirection because it is most common and
@@ -1073,6 +1075,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1186,7 +1189,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index dc4faa0643e..7bd8a17099d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -57,6 +57,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 static void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc bscan);
 static void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc bscan);
 static void BitmapPrefetch(BitmapHeapScanDesc bscan);
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
@@ -2117,10 +2120,15 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  * ------------------------------------------------------------------------
  */
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
@@ -2292,15 +2300,17 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
 	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
+	 * invoke this function again.
 	 */
 	return true;
 }
 
 static bool
 heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
+							  TupleTableSlot *slot,
+							  bool *recheck,
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
@@ -2311,23 +2321,32 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	ParallelBitmapHeapState *pstate = scan->st.bitmap.rs_pstate;
 #endif							/* USE_PREFETCH */
 
-	if (bscan->rs_empty_tuples_pending > 0)
+	/*
+	 * Out of range?  If so, nothing more to look at on this page
+	 */
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		BitmapPrefetch(bscan);
-		return true;
-	}
+		if (bscan->rs_empty_tuples_pending > 0)
+		{
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			BitmapPrefetch(bscan);
+			return true;
+		}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	Assert(hscan->rs_cindex >= 0);
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
+		/*
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
+		 */
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
+	}
 
 #ifdef USE_PREFETCH
 
@@ -2953,7 +2972,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index e9b598256fb..912495bdaa1 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index f522ba4959a..86b27ec62b8 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -189,55 +189,36 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
-		/* BitmapTableScanSetup sets node->ss.ss_currentScanDesc */
 		BitmapTableScanSetup(node);
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(
-											node->ss.ss_currentScanDesc,
-											slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-
-			CHECK_FOR_INTERRUPTS();
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(node->ss.ss_currentScanDesc,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index b913f91ff03..29f5036e9b0 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index df7b02be9ca..52c6c4818cb 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -784,45 +784,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from the next block yielded by
-	 * the iterator as part of a bitmap table scan. `scan` was started via
-	 * table_beginscan_bm(). Return false if the bitmap is exhausted and true
-	 * otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
-	 * Prefetching future blocks indicated in the bitmap is left to the table
-	 * AM.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1956,51 +1934,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2011,7 +1962,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.45.2

v25-0008-Push-Bitmap-Table-Scan-prefetch-code-into-heap-A.patchapplication/octet-stream; name=v25-0008-Push-Bitmap-Table-Scan-prefetch-code-into-heap-A.patchDownload
From b563d330ae16ce60ed3e71f2540cdfceeece7108 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 9 Oct 2024 14:54:24 -0400
Subject: [PATCH v25 08/11] Push Bitmap Table Scan prefetch code into heap AM

In order to completely remove the layering violation in bitmap table
scan code, we must avoid using the VM for skipping prefetches as well.

To accomplish this, push prefetch code down into the heap implementation
fo the bitmap table scan AM functions. This fixes another layering
violation related to prefetching mentioned in tableam.h.

This commit moves prefetch-related members from the BitmapHeapScanState
to the BitmapHeapScanDesc and localizes the prefetch functions to heap
AM code.

heapam_scan_bitmap_next_block() no longer needs to take blockno as a
parameter because it was only being used in generic bitmap table scan
code to check if the prefetch block was falling behind the current
block.
---
 src/backend/access/heap/heapam.c          |  25 +++-
 src/backend/access/heap/heapam_handler.c  | 142 ++++++++++++++-------
 src/backend/access/table/tableam.c        |   4 +-
 src/backend/executor/nodeBitmapHeapscan.c | 147 ++++++----------------
 src/include/access/heapam.h               |  31 +++--
 src/include/access/relscan.h              |   9 +-
 src/include/access/tableam.h              |  68 +++++-----
 src/include/nodes/execnodes.h             |  14 ---
 8 files changed, 226 insertions(+), 214 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 90f6816922c..b8d8d0452aa 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1030,7 +1030,8 @@ TableScanDesc
 heap_beginscan(Relation relation, Snapshot snapshot,
 			   int nkeys, ScanKey key,
 			   ParallelTableScanDesc parallel_scan,
-			   uint32 flags)
+			   uint32 flags,
+			   int prefetch_maximum)
 {
 	HeapScanDesc scan;
 
@@ -1050,8 +1051,17 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	{
 		BitmapHeapScanDesc bscan = palloc(sizeof(BitmapHeapScanDescData));
 
+		bscan->rs_prefetch_blockno = InvalidBlockNumber;
 		bscan->rs_vmbuffer = InvalidBuffer;
+		bscan->rs_pvmbuffer = InvalidBuffer;
 		bscan->rs_empty_tuples_pending = 0;
+
+		/* Only used for serial BHS */
+		bscan->rs_prefetch_pages = 0;
+		bscan->rs_prefetch_target = -1;
+
+		bscan->rs_prefetch_maximum = prefetch_maximum;
+
 		scan = (HeapScanDesc) bscan;
 	}
 	else
@@ -1182,6 +1192,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	{
 		BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 
+		bscan->rs_prefetch_blockno = InvalidBlockNumber;
+
+		/* Only used for serial BHS */
+		bscan->rs_prefetch_pages = 0;
+		bscan->rs_prefetch_target = -1;
+
 		/*
 		 * Reset empty_tuples_pending, a field only used by bitmap heap scan,
 		 * to avoid incorrectly emitting NULL-filled tuples from a previous
@@ -1194,6 +1210,11 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 			ReleaseBuffer(bscan->rs_vmbuffer);
 			bscan->rs_vmbuffer = InvalidBuffer;
 		}
+		if (BufferIsValid(bscan->rs_pvmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_pvmbuffer);
+			bscan->rs_pvmbuffer = InvalidBuffer;
+		}
 	}
 
 	/*
@@ -1253,6 +1274,8 @@ heap_endscan(TableScanDesc sscan)
 		bscan->rs_empty_tuples_pending = 0;
 		if (BufferIsValid(bscan->rs_vmbuffer))
 			ReleaseBuffer(bscan->rs_vmbuffer);
+		if (BufferIsValid(bscan->rs_pvmbuffer))
+			ReleaseBuffer(bscan->rs_pvmbuffer);
 	}
 
 	pfree(scan);
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index b4a51153d7a..dc4faa0643e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -54,6 +54,10 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 								   HeapTuple tuple,
 								   OffsetNumber tupoffset);
 
+static void BitmapAdjustPrefetchIterator(BitmapHeapScanDesc bscan);
+static void BitmapAdjustPrefetchTarget(BitmapHeapScanDesc bscan);
+static void BitmapPrefetch(BitmapHeapScanDesc bscan);
+
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
 
@@ -2115,7 +2119,7 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
@@ -2131,14 +2135,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
 	*recheck = true;
 
+	BitmapAdjustPrefetchIterator(bscan);
+
 	do
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
+		tbmres = tbm_iterate(&scan->st.bitmap.rs_iterator);
 
 		if (tbmres == NULL)
 			return false;
@@ -2155,7 +2160,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 			 tbmres->blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
+	block = tbmres->blockno;
 	*recheck = tbmres->recheck;
 
 	/*
@@ -2176,8 +2181,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	block = tbmres->blockno;
-
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
 	 */
@@ -2271,6 +2274,20 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	else
 		(*lossy_pages)++;
 
+	/*
+	 * If private, we can error out if the the prefetch block doesn't stay
+	 * ahead of the current block.
+	 */
+	if (scan->st.bitmap.rs_pstate == NULL &&
+		!tbm_exhausted(&scan->st.bitmap.rs_prefetch_iterator) &&
+		bscan->rs_prefetch_blockno < block)
+		elog(ERROR,
+			 "prefetch and main iterators are out of sync. pblockno: %d. block: %d",
+			 bscan->rs_prefetch_blockno, block);
+
+	/* Adjust the prefetch target */
+	BitmapAdjustPrefetchTarget(bscan);
+
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
 	 * not exhausted. If there are no visible tuples on this page,
@@ -2290,6 +2307,9 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = scan->st.bitmap.rs_pstate;
+#endif							/* USE_PREFETCH */
 
 	if (bscan->rs_empty_tuples_pending > 0)
 	{
@@ -2298,6 +2318,7 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 		 */
 		ExecStoreAllNullTuple(slot);
 		bscan->rs_empty_tuples_pending--;
+		BitmapPrefetch(bscan);
 		return true;
 	}
 
@@ -2308,6 +2329,36 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 	if (hscan->rs_cindex >= hscan->rs_ntuples)
 		return false;
 
+#ifdef USE_PREFETCH
+
+	/*
+	 * Try to prefetch at least a few pages even before we get to the second
+	 * page if we don't stop reading after the first tuple.
+	 */
+	if (!pstate)
+	{
+		if (bscan->rs_prefetch_target < bscan->rs_prefetch_maximum)
+			bscan->rs_prefetch_target++;
+	}
+	else if (pstate->prefetch_target < bscan->rs_prefetch_maximum)
+	{
+		/* take spinlock while updating shared state */
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target < bscan->rs_prefetch_maximum)
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+
+	/*
+	 * We issue prefetch requests *after* fetching the current page to try to
+	 * avoid having prefetching interfere with the main I/O. Also, this should
+	 * happen only when we have determined there is still something to do on
+	 * the current page, else we may uselessly prefetch the same page we are
+	 * just about to request for real.
+	 */
+	BitmapPrefetch(bscan);
+
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2621,26 +2672,28 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
  *	iterator in prefetch_pages. For each block the main iterator returns, we
  *	decrement prefetch_pages.
  */
-void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+static void
+BitmapAdjustPrefetchIterator(BitmapHeapScanDesc bscan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	TableScanDesc scan = &(&bscan->rs_heap_base)->rs_base;
+	ParallelBitmapHeapState *pstate = scan->st.bitmap.rs_pstate;
 	TBMIterateResult *tbmpre;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator =
+			&scan->st.bitmap.rs_prefetch_iterator;
 
-		if (node->prefetch_pages > 0)
+		if (bscan->rs_prefetch_pages > 0)
 		{
 			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
+			bscan->rs_prefetch_pages--;
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
 			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
+			bscan->rs_prefetch_blockno = tbmpre ? tbmpre->blockno :
 				InvalidBlockNumber;
 		}
 		return;
@@ -2655,9 +2708,10 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
 	 * exacerbates the effects of this bug.
 	 */
-	if (node->prefetch_maximum > 0)
+	if (bscan->rs_prefetch_maximum > 0)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator =
+			&scan->st.bitmap.rs_prefetch_iterator;
 
 		SpinLockAcquire(&pstate->mutex);
 		if (pstate->prefetch_pages > 0)
@@ -2681,7 +2735,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			if (!tbm_exhausted(prefetch_iterator))
 			{
 				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
+				bscan->rs_prefetch_blockno = tbmpre ? tbmpre->blockno :
 					InvalidBlockNumber;
 			}
 		}
@@ -2697,33 +2751,34 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
  * page/tuple, then to one after the second tuple is fetched, then
  * it doubles as later pages are fetched.
  */
-void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+static void
+BitmapAdjustPrefetchTarget(BitmapHeapScanDesc bscan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	TableScanDesc scan = &(&bscan->rs_heap_base)->rs_base;
+	ParallelBitmapHeapState *pstate = scan->st.bitmap.rs_pstate;
 
 	if (pstate == NULL)
 	{
-		if (node->prefetch_target >= node->prefetch_maximum)
+		if (bscan->rs_prefetch_target >= bscan->rs_prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
+		else if (bscan->rs_prefetch_target >= bscan->rs_prefetch_maximum / 2)
+			bscan->rs_prefetch_target = bscan->rs_prefetch_maximum;
+		else if (bscan->rs_prefetch_target > 0)
+			bscan->rs_prefetch_target *= 2;
 		else
-			node->prefetch_target++;
+			bscan->rs_prefetch_target++;
 		return;
 	}
 
 	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
+	if (pstate->prefetch_target < bscan->rs_prefetch_maximum)
 	{
 		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
+		if (pstate->prefetch_target >= bscan->rs_prefetch_maximum)
 			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target >= bscan->rs_prefetch_maximum / 2)
+			pstate->prefetch_target = bscan->rs_prefetch_maximum;
 		else if (pstate->prefetch_target > 0)
 			pstate->prefetch_target *= 2;
 		else
@@ -2736,19 +2791,21 @@ BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
 /*
  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
  */
-void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+static void
+BitmapPrefetch(BitmapHeapScanDesc bscan)
 {
 #ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
+	TableScanDesc scan = &(&bscan->rs_heap_base)->rs_base;
+	ParallelBitmapHeapState *pstate = scan->st.bitmap.rs_pstate;
 
 	if (pstate == NULL)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator =
+			&scan->st.bitmap.rs_prefetch_iterator;
 
 		if (!tbm_exhausted(prefetch_iterator))
 		{
-			while (node->prefetch_pages < node->prefetch_target)
+			while (bscan->rs_prefetch_pages < bscan->rs_prefetch_target)
 			{
 				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
 				bool		skip_fetch;
@@ -2759,8 +2816,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				bscan->rs_prefetch_pages++;
+				bscan->rs_prefetch_blockno = tbmpre->blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -2770,9 +2827,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->rs_rd,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &bscan->rs_pvmbuffer));
 
 				if (!skip_fetch)
 					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM,
@@ -2785,7 +2842,8 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
 	if (pstate->prefetch_pages < pstate->prefetch_target)
 	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+		TBMIterator *prefetch_iterator =
+			&scan->st.bitmap.rs_prefetch_iterator;
 
 		if (!tbm_exhausted(prefetch_iterator))
 		{
@@ -2818,14 +2876,14 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				bscan->rs_prefetch_blockno = tbmpre->blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
 							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+							  VM_ALL_VISIBLE(scan->rs_rd,
 											 tbmpre->blockno,
-											 &node->pvmbuffer));
+											 &bscan->rs_pvmbuffer));
 
 				if (!skip_fetch)
 					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM,
diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index bd8715b6797..3dafcea9649 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -117,7 +117,7 @@ table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
 	Snapshot	snapshot = RegisterSnapshot(GetCatalogSnapshot(relid));
 
 	return relation->rd_tableam->scan_begin(relation, snapshot, nkeys, key,
-											NULL, flags);
+											NULL, flags, 0);
 }
 
 
@@ -184,7 +184,7 @@ table_beginscan_parallel(Relation relation, ParallelTableScanDesc pscan)
 	}
 
 	return relation->rd_tableam->scan_begin(relation, snapshot, 0, NULL,
-											pscan, flags);
+											pscan, flags, 0);
 }
 
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index a3381a08790..fcdbbb821ab 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,8 +37,6 @@
 
 #include <math.h>
 
-/* XXX: temporary include so prefetch lift and shift works */
-#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -84,17 +82,26 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
+	 * While prefetching is the responsibility of the table AM, the prefetch
+	 * iterator is set up here along with the main iterator. Two iterators are
+	 * used -- one for the pages actually being scanned now and the other to
+	 * run ahead and inform the storage layer what blocks to prefetch.
 	 */
 	if (!node->initialized)
 	{
 		TBMIterator tbmiterator;
+		int			prefetch_max;
+		Relation	rel = node->ss.ss_currentRelation;
+#ifdef USE_PREFETCH
+		TBMIterator prefetch_iterator = {0};
+#endif							/* USE_PREFETCH */
+
+		/*
+		 * Maximum number of prefetches for the tablespace if configured,
+		 * otherwise the current value of the effective_io_concurrency GUC.
+		 */
+		prefetch_max =
+			get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
 
 		if (!pstate)
 		{
@@ -104,15 +111,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 				elog(ERROR, "unrecognized result from subplan");
 
 			node->tbm = tbm;
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-				node->prefetch_iterator =
-					tbm_begin_iterate(node->tbm, dsa,
-									  pstate ?
-									  pstate->prefetch_iterator :
-									  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
 		}
 		else if (BitmapShouldInitializeSharedState(pstate))
 		{
@@ -135,7 +133,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
 
 #ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
+			if (prefetch_max > 0)
 			{
 				pstate->prefetch_iterator =
 					tbm_prepare_shared_iterate(tbm);
@@ -150,14 +148,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
 										pstate ?
 										pstate->tbmiterator :
 										InvalidDsaPointer);
-
 #ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-			node->prefetch_iterator =
-				tbm_begin_iterate(tbm, dsa,
-								  pstate ?
-								  pstate->prefetch_iterator :
-								  InvalidDsaPointer);
+		if (prefetch_max > 0)
+			prefetch_iterator = tbm_begin_iterate(tbm, dsa,
+												  pstate ?
+												  pstate->prefetch_iterator :
+												  InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 
 		/*
@@ -181,14 +177,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			scan = table_beginscan_bm(node->ss.ss_currentRelation,
 									  node->ss.ps.state->es_snapshot,
+									  pstate,
 									  0,
 									  NULL,
-									  need_tuples);
+									  need_tuples,
+									  prefetch_max);
 
 			node->ss.ss_currentScanDesc = scan;
 		}
 
-		scan->st.rs_tbmiterator = tbmiterator;
+		scan->st.bitmap.rs_iterator = tbmiterator;
+		scan->st.bitmap.rs_prefetch_iterator = prefetch_iterator;
 		node->initialized = true;
 
 		goto new_page;
@@ -204,37 +203,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -257,31 +225,14 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
-										  &node->recheck,
+		if (!table_scan_bitmap_next_block(scan, &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If private, we can error out if the the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -353,30 +304,22 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		tbm_end_iterate(&scan->st.rs_tbmiterator);
+		tbm_end_iterate(&scan->st.bitmap.rs_iterator);
+
+		/* If we did not already clean up the prefetch iterator, do so now. */
+		if (!tbm_exhausted(&scan->st.bitmap.rs_prefetch_iterator))
+			tbm_end_iterate(&scan->st.bitmap.rs_prefetch_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -435,7 +378,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		/*
 		 * End iteration on iterators saved in scan descriptor.
 		 */
-		tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
+		tbm_end_iterate(&scanDesc->st.bitmap.rs_iterator);
+
+		/* If we did not already clean up the prefetch iterator, do so now. */
+		if (!tbm_exhausted(&scanDesc->st.bitmap.rs_prefetch_iterator))
+			tbm_end_iterate(&scanDesc->st.bitmap.rs_prefetch_iterator);
 
 		/*
 		 * close table scan
@@ -443,17 +390,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -486,18 +427,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -537,13 +473,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 232f80821a0..cbda064c612 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -22,8 +22,6 @@
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
 #include "nodes/lockoptions.h"
-/* XXX: temporary include so prefetch lift and shift works */
-#include "nodes/execnodes.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
 #include "storage/dsm.h"
@@ -101,10 +99,29 @@ typedef struct HeapScanDescData
 }			HeapScanDescData;
 typedef struct HeapScanDescData *HeapScanDesc;
 
+
+/*
+* For prefetching, we use *two* iterators, one for the pages we are
+* actually scanning and another that runs ahead of the first for
+* prefetching. prefetch_pages tracks exactly how many pages ahead
+* the prefetch iterator is.  Also, prefetch_target tracks the
+* desired prefetch distance, which starts small and increases up to the
+* prefetch_maximum.  This is to avoid doing a lot of prefetching in
+* a scan that stops after a few tuples because of a LIMIT.
+*/
 typedef struct BitmapHeapScanDescData
 {
 	HeapScanDescData rs_heap_base;
 
+	/* used to validate prefetch block stays ahead of current block */
+	BlockNumber rs_prefetch_blockno;
+	/* maximum value for prefetch_target */
+	int			rs_prefetch_maximum;
+	/* Current target for prefetch distance */
+	int			rs_prefetch_target;
+	/* # pages prefetch iterator is ahead of current */
+	int			rs_prefetch_pages;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -115,6 +132,8 @@ typedef struct BitmapHeapScanDescData
 
 	/* page of VM containing info for current block */
 	Buffer		rs_vmbuffer;
+	/* page of VM containing info for prefetch block */
+	Buffer		rs_pvmbuffer;
 	int			rs_empty_tuples_pending;
 }			BitmapHeapScanDescData;
 typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc;
@@ -300,7 +319,8 @@ typedef enum
 extern TableScanDesc heap_beginscan(Relation relation, Snapshot snapshot,
 									int nkeys, ScanKey key,
 									ParallelTableScanDesc parallel_scan,
-									uint32 flags);
+									uint32 flags,
+									int prefetch_maximum);
 extern void heap_setscanlimits(TableScanDesc sscan, BlockNumber startBlk,
 							   BlockNumber numBlks);
 extern void heap_prepare_pagescan(TableScanDesc sscan);
@@ -426,11 +446,6 @@ extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
 extern bool HeapTupleIsSurelyDead(HeapTuple htup,
 								  struct GlobalVisState *vistest);
 
-/* in heapam_handler.c */
-extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-extern void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan);
-
 /*
  * To avoid leaking too much knowledge about reorderbuffer implementation
  * details this is implemented in reorderbuffer.c not heapam_visibility.c
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 8ca8f789617..f14db173660 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,13 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator rs_tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *rs_pstate;
+			TBMIterator rs_iterator;
+			TBMIterator rs_prefetch_iterator;
+		}			bitmap;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index dbcea659fbc..df7b02be9ca 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -324,12 +324,16 @@ typedef struct TableAmRoutine
 	 * the scan's behaviour (ScanOptions's SO_ALLOW_*, several may be
 	 * specified, an AM may ignore unsupported ones) and whether the snapshot
 	 * needs to be deallocated at scan_end (ScanOptions's SO_TEMP_SNAPSHOT).
+	 *
+	 * `prefetch_maximum` is the maximum prefetch distance for use by bitmap
+	 * table scans as needed.
 	 */
 	TableScanDesc (*scan_begin) (Relation rel,
 								 Snapshot snapshot,
 								 int nkeys, struct ScanKeyData *key,
 								 ParallelTableScanDesc pscan,
-								 uint32 flags);
+								 uint32 flags,
+								 int prefetch_maximum);
 
 	/*
 	 * Release resources and deallocate scan. If TableScanDesc.temp_snap,
@@ -780,9 +784,10 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
+	 * Prepare to fetch / check / return tuples from the next block yielded by
+	 * the iterator as part of a bitmap table scan. `scan` was started via
+	 * table_beginscan_bm(). Return false if the bitmap is exhausted and true
+	 * otherwise.
 	 *
 	 * This will typically read and pin the target block, and do the necessary
 	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
@@ -797,28 +802,13 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching future blocks indicated in the bitmap is left to the table
+	 * AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -916,7 +906,8 @@ table_beginscan(Relation rel, Snapshot snapshot,
 	uint32		flags = SO_TYPE_SEQSCAN |
 		SO_ALLOW_STRAT | SO_ALLOW_SYNC | SO_ALLOW_PAGEMODE;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
+									   NULL, flags, 0);
 }
 
 /*
@@ -945,7 +936,8 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
 	if (allow_sync)
 		flags |= SO_ALLOW_SYNC;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
+									   NULL, flags, 0);
 }
 
 /*
@@ -956,15 +948,21 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
-				   int nkeys, struct ScanKeyData *key, bool need_tuple)
+				   struct ParallelBitmapHeapState *pstate,
+				   int nkeys, struct ScanKeyData *key, bool need_tuple,
+				   int prefetch_maximum)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-									   NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys,
+										 key, NULL, flags,
+										 prefetch_maximum);
+	result->st.bitmap.rs_pstate = pstate;
+	return result;
 }
 
 /*
@@ -989,7 +987,8 @@ table_beginscan_sampling(Relation rel, Snapshot snapshot,
 	if (allow_pagemode)
 		flags |= SO_ALLOW_PAGEMODE;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
+									   NULL, flags, 0);
 }
 
 /*
@@ -1002,7 +1001,8 @@ table_beginscan_tid(Relation rel, Snapshot snapshot)
 {
 	uint32		flags = SO_TYPE_TIDSCAN;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL,
+									   NULL, flags, 0);
 }
 
 /*
@@ -1015,7 +1015,7 @@ table_beginscan_analyze(Relation rel)
 {
 	uint32		flags = SO_TYPE_ANALYZE;
 
-	return rel->rd_tableam->scan_begin(rel, NULL, 0, NULL, NULL, flags);
+	return rel->rd_tableam->scan_begin(rel, NULL, 0, NULL, NULL, flags, 0);
 }
 
 /*
@@ -1094,7 +1094,8 @@ table_beginscan_tidrange(Relation rel, Snapshot snapshot,
 	TableScanDesc sscan;
 	uint32		flags = SO_TYPE_TIDRANGESCAN | SO_ALLOW_PAGEMODE;
 
-	sscan = rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL, NULL, flags);
+	sscan = rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL,
+										NULL, flags, 0);
 
 	/* Set the range of TIDs to scan */
 	sscan->rs_rd->rd_tableam->scan_set_tidrange(sscan, mintid, maxtid);
@@ -1966,16 +1967,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1985,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 7cd4b57509e..53fcb9d33a4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1833,18 +1833,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1852,18 +1845,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.45.2

v25-0009-Move-BitmapTableScan-per-scan-setup-into-a-helpe.patchapplication/octet-stream; name=v25-0009-Move-BitmapTableScan-per-scan-setup-into-a-helpe.patchDownload
From 68350a7a21de67e97664fb669ec11ed0d7009f36 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 9 Oct 2024 15:25:03 -0400
Subject: [PATCH v25 09/11] Move BitmapTableScan per-scan setup into a helper

Add BitmapTableScanSetup() which contains all of the code that must be
done on every scan of the table in a bitmap table scan.
This includes scanning the index, building the bitmap, and setting up
the scan descriptors.

Much of BitmapHeapNext() code was this setup, so it made sense to put it
in a helper function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 227 +++++++++++-----------
 1 file changed, 116 insertions(+), 111 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fcdbbb821ab..f522ba4959a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -54,148 +54,152 @@ static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *ps
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
-/* ----------------------------------------------------------------
- *		BitmapHeapNext
+/*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
  *
- *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
- * ----------------------------------------------------------------
+ * While prefetching is the responsibility of the table AM, the prefetch
+ * iterator is set up here along with the main iterator. Two iterators are
+ * used -- one for the pages actually being scanned now and the other to
+ * run ahead and inform the storage layer what blocks to prefetch.
  */
-static TupleTableSlot *
-BitmapHeapNext(BitmapHeapScanState *node)
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TIDBitmap  *tbm;
-	TupleTableSlot *slot;
+	TBMIterator tbmiterator = {0};
+	TBMIterator prefetch_iterator = {0};
+	int			prefetch_max;
 	ParallelBitmapHeapState *pstate = node->pstate;
 	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
+	Relation	rel = node->ss.ss_currentRelation;
 
 	/*
-	 * extract necessary information from index scan node
+	 * Maximum number of prefetches for the tablespace if configured,
+	 * otherwise the current value of the effective_io_concurrency GUC.
 	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
+	prefetch_max =
+		get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
 
-	/*
-	 * If we haven't yet performed the underlying index scan, do it, and begin
-	 * the iteration over the bitmap.
-	 *
-	 * While prefetching is the responsibility of the table AM, the prefetch
-	 * iterator is set up here along with the main iterator. Two iterators are
-	 * used -- one for the pages actually being scanned now and the other to
-	 * run ahead and inform the storage layer what blocks to prefetch.
-	 */
-	if (!node->initialized)
+	if (!pstate)
 	{
-		TBMIterator tbmiterator;
-		int			prefetch_max;
-		Relation	rel = node->ss.ss_currentRelation;
-#ifdef USE_PREFETCH
-		TBMIterator prefetch_iterator = {0};
-#endif							/* USE_PREFETCH */
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
 
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+	}
+	else if (BitmapShouldInitializeSharedState(pstate))
+	{
 		/*
-		 * Maximum number of prefetches for the tablespace if configured,
-		 * otherwise the current value of the effective_io_concurrency GUC.
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
 		 */
-		prefetch_max =
-			get_tablespace_io_concurrency(rel->rd_rel->reltablespace);
-
-		if (!pstate)
-		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
 
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
+		/*
+		 * Prepare to iterate over the TBM. This will return the dsa_pointer
+		 * of the iterator state which will be used by multiple processes to
+		 * iterate jointly.
+		 */
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-			node->tbm = tbm;
-		}
-		else if (BitmapShouldInitializeSharedState(pstate))
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
+		/*
+		 * For prefetching, we use *two* iterators, one for the pages we are
+		 * actually scanning and another that runs ahead of the first for
+		 * prefetching.  node->prefetch_pages tracks exactly how many pages
+		 * ahead the prefetch iterator is.  Also, node->prefetch_target tracks
+		 * the desired prefetch distance, which starts small and increases up
+		 * to the node->prefetch_maximum.  This is to avoid doing a lot of
+		 * prefetching in a scan that stops after a few tuples because of a
+		 * LIMIT.
+		 */
+#ifdef USE_PREFETCH
+		if (prefetch_max > 0)
+			pstate->prefetch_iterator =
+				tbm_prepare_shared_iterate(node->tbm);
+#endif
 
-			node->tbm = tbm;
+		/* We have initialized the shared state so wake up others. */
+		BitmapDoneInitializingSharedState(pstate);
+	}
 
-			/*
-			 * Prepare to iterate over the TBM. This will return the
-			 * dsa_pointer of the iterator state which will be used by
-			 * multiple processes to iterate jointly.
-			 */
-			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
+	tbmiterator = tbm_begin_iterate(node->tbm, dsa,
+									pstate ?
+									pstate->tbmiterator :
+									InvalidDsaPointer);
 
 #ifdef USE_PREFETCH
-			if (prefetch_max > 0)
-			{
-				pstate->prefetch_iterator =
-					tbm_prepare_shared_iterate(tbm);
-			}
+	if (prefetch_max > 0)
+		prefetch_iterator = tbm_begin_iterate(node->tbm, dsa,
+											  pstate ?
+											  pstate->prefetch_iterator :
+											  InvalidDsaPointer);
 #endif							/* USE_PREFETCH */
 
-			/* We have initialized the shared state so wake up others. */
-			BitmapDoneInitializingSharedState(pstate);
-		}
-
-		tbmiterator = tbm_begin_iterate(tbm, dsa,
-										pstate ?
-										pstate->tbmiterator :
-										InvalidDsaPointer);
-#ifdef USE_PREFETCH
-		if (prefetch_max > 0)
-			prefetch_iterator = tbm_begin_iterate(tbm, dsa,
-												  pstate ?
-												  pstate->prefetch_iterator :
-												  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!node->ss.ss_currentScanDesc)
+	{
+		bool		need_tuples = false;
 
 		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
 		 */
-		if (!scan)
-		{
-			bool		need_tuples = false;
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
+		node->ss.ss_currentScanDesc =
+			table_beginscan_bm(node->ss.ss_currentRelation,
+							   node->ss.ps.state->es_snapshot,
+							   pstate,
+							   0,
+							   NULL,
+							   need_tuples,
+							   prefetch_max);
+	}
 
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  pstate,
-									  0,
-									  NULL,
-									  need_tuples,
-									  prefetch_max);
-
-			node->ss.ss_currentScanDesc = scan;
-		}
+	node->ss.ss_currentScanDesc->st.bitmap.rs_iterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bitmap.rs_prefetch_iterator =
+		prefetch_iterator;
+	node->initialized = true;
+}
 
-		scan->st.bitmap.rs_iterator = tbmiterator;
-		scan->st.bitmap.rs_prefetch_iterator = prefetch_iterator;
-		node->initialized = true;
+/* ----------------------------------------------------------------
+ *		BitmapHeapNext
+ *
+ *		Retrieve next tuple from the BitmapHeapScan node's currentRelation
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+BitmapHeapNext(BitmapHeapScanState *node)
+{
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
+	/*
+	 * If we haven't yet performed the underlying index scan, do it, and begin
+	 * the iteration over the bitmap.
+	 */
+	if (!node->initialized)
+	{
+		/* BitmapTableScanSetup sets node->ss.ss_currentScanDesc */
+		BitmapTableScanSetup(node);
 		goto new_page;
 	}
 
 	for (;;)
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
+		while (table_scan_bitmap_next_tuple(
+											node->ss.ss_currentScanDesc,
+											slot))
 		{
 			/*
 			 * Continuing in previously obtained page.
@@ -229,7 +233,8 @@ new_page:
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->recheck,
+		if (!table_scan_bitmap_next_block(node->ss.ss_currentScanDesc,
+										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-- 
2.45.2

v25-0007-Lift-and-Shift-Bitmap-Table-Scan-prefetch-functi.patchapplication/octet-stream; name=v25-0007-Lift-and-Shift-Bitmap-Table-Scan-prefetch-functi.patchDownload
From 0c72a0819756adf8e212ebf7a0f91e87b9b598c2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 9 Oct 2024 07:55:47 -0400
Subject: [PATCH v25 07/11] Lift and Shift Bitmap Table Scan prefetch functions

This is a temporary commit. For ease of review, move the Bitmap Table
Scan prefetch functions into heapam_handler.c without modifying them.
The next commit will push the prefetching code into heap-specific code.
Separating the commit which moves to the functions to heapam_handler.c
and the one which modifies them and their callers to contain bitmap
prefetch code in heap AM-specific code makes it easier to see what has
changed. Doing so requires including heap code in nodeBitmapHeapscan.c,
which is not okay for the final code that is committed.
---
 src/backend/access/heap/heapam_handler.c  | 222 +++++++++++++++++++++
 src/backend/executor/nodeBitmapHeapscan.c | 226 +---------------------
 src/include/access/heapam.h               |   7 +
 3 files changed, 231 insertions(+), 224 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 192a326a019..b4a51153d7a 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2614,6 +2614,228 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ *
+ *	We keep track of how far the prefetch iterator is ahead of the main
+ *	iterator in prefetch_pages. For each block the main iterator returns, we
+ *	decrement prefetch_pages.
+ */
+void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+	TBMIterateResult *tbmpre;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (node->prefetch_pages > 0)
+		{
+			/* The main iterator has closed the distance by one page */
+			node->prefetch_pages--;
+		}
+		else if (!tbm_exhausted(prefetch_iterator))
+		{
+			tbmpre = tbm_iterate(prefetch_iterator);
+			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
+				InvalidBlockNumber;
+		}
+		return;
+	}
+
+	/*
+	 * XXX: There is a known issue with keeping the prefetch and current block
+	 * iterators in sync for parallel bitmap table scans. This can lead to
+	 * prefetching blocks that have already been read. See the discussion
+	 * here:
+	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
+	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
+	 * exacerbates the effects of this bug.
+	 */
+	if (node->prefetch_maximum > 0)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_pages > 0)
+		{
+			pstate->prefetch_pages--;
+			SpinLockRelease(&pstate->mutex);
+		}
+		else
+		{
+			/* Release the mutex before iterating */
+			SpinLockRelease(&pstate->mutex);
+
+			/*
+			 * In case of shared mode, we can not ensure that the current
+			 * blockno of the main iterator and that of the prefetch iterator
+			 * are same.  It's possible that whatever blockno we are
+			 * prefetching will be processed by another process.  Therefore,
+			 * we don't validate the blockno here as we do in non-parallel
+			 * case.
+			 */
+			if (!tbm_exhausted(prefetch_iterator))
+			{
+				tbmpre = tbm_iterate(prefetch_iterator);
+				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
+					InvalidBlockNumber;
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		if (node->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (node->prefetch_target >= node->prefetch_maximum / 2)
+			node->prefetch_target = node->prefetch_maximum;
+		else if (node->prefetch_target > 0)
+			node->prefetch_target *= 2;
+		else
+			node->prefetch_target++;
+		return;
+	}
+
+	/* Do an unlocked check first to save spinlock acquisitions. */
+	if (pstate->prefetch_target < node->prefetch_maximum)
+	{
+		SpinLockAcquire(&pstate->mutex);
+		if (pstate->prefetch_target >= node->prefetch_maximum)
+			 /* don't increase any further */ ;
+		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
+			pstate->prefetch_target = node->prefetch_maximum;
+		else if (pstate->prefetch_target > 0)
+			pstate->prefetch_target *= 2;
+		else
+			pstate->prefetch_target++;
+		SpinLockRelease(&pstate->mutex);
+	}
+#endif							/* USE_PREFETCH */
+}
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+void
+BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
+{
+#ifdef USE_PREFETCH
+	ParallelBitmapHeapState *pstate = node->pstate;
+
+	if (pstate == NULL)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!tbm_exhausted(prefetch_iterator))
+		{
+			while (node->prefetch_pages < node->prefetch_target)
+			{
+				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				bool		skip_fetch;
+
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+				node->prefetch_pages++;
+				node->prefetch_blockno = tbmpre->blockno;
+
+				/*
+				 * If we expect not to have to actually read this heap page,
+				 * skip this prefetch call, but continue to run the prefetch
+				 * logic normally.  (Would it be better not to increment
+				 * prefetch_pages?)
+				 */
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM,
+								   tbmpre->blockno);
+			}
+		}
+
+		return;
+	}
+
+	if (pstate->prefetch_pages < pstate->prefetch_target)
+	{
+		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
+
+		if (!tbm_exhausted(prefetch_iterator))
+		{
+			while (1)
+			{
+				TBMIterateResult *tbmpre;
+				bool		do_prefetch = false;
+				bool		skip_fetch;
+
+				/*
+				 * Recheck under the mutex. If some other process has already
+				 * done enough prefetching then we need not to do anything.
+				 */
+				SpinLockAcquire(&pstate->mutex);
+				if (pstate->prefetch_pages < pstate->prefetch_target)
+				{
+					pstate->prefetch_pages++;
+					do_prefetch = true;
+				}
+				SpinLockRelease(&pstate->mutex);
+
+				if (!do_prefetch)
+					return;
+
+				tbmpre = tbm_iterate(prefetch_iterator);
+				if (tbmpre == NULL)
+				{
+					/* No more pages to prefetch */
+					tbm_end_iterate(prefetch_iterator);
+					break;
+				}
+
+				node->prefetch_blockno = tbmpre->blockno;
+
+				/* As above, skip prefetch if we expect not to need page */
+				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
+							  !tbmpre->recheck &&
+							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
+											 tbmpre->blockno,
+											 &node->pvmbuffer));
+
+				if (!skip_fetch)
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM,
+								   tbmpre->blockno);
+			}
+		}
+	}
+#endif							/* USE_PREFETCH */
+}
+
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index b35d09c2ef3..a3381a08790 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -37,6 +37,8 @@
 
 #include <math.h>
 
+/* XXX: temporary include so prefetch lift and shift works */
+#include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "access/visibilitymap.h"
@@ -51,10 +53,6 @@
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -307,226 +305,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index a789c608f1d..232f80821a0 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -22,6 +22,8 @@
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
 #include "nodes/lockoptions.h"
+/* XXX: temporary include so prefetch lift and shift works */
+#include "nodes/execnodes.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
 #include "storage/dsm.h"
@@ -424,6 +426,11 @@ extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
 extern bool HeapTupleIsSurelyDead(HeapTuple htup,
 								  struct GlobalVisState *vistest);
 
+/* in heapam_handler.c */
+extern void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
+extern void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+extern void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan);
+
 /*
  * To avoid leaking too much knowledge about reorderbuffer implementation
  * details this is implemented in reorderbuffer.c not heapam_visibility.c
-- 
2.45.2

#162Dilip Kumar
dilipbalaut@gmail.com
In reply to: Melanie Plageman (#161)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Oct 19, 2024 at 2:18 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Wed, Oct 16, 2024 at 11:09 AM Tomas Vondra <tomas@vondra.me> wrote:

Thanks for the review!

1) 0001

I find it a bit weird that we use ntuples to determine if it's exact or
lossy. Not an issue caused by this patch, of course, but maybe we could
improve that somehow? I mean this:

if (tbmres->ntuples >= 0)
(*exact_pages)++;
else
(*lossy_pages)++;

I agree. The most straightforward solution would be to add a boolean
`lossy` to TBMIterateResult.

In some ways, I think it would make it a bit more clear because the
situation with TBMIterateResult->recheck is already a bit confusing.
It recheck is true if either 1: the Bitmap is lossy and we cannot use
TBMIterateResult->offsets for this page or 2: the original query has a
qual requiring recheck

In the body of BitmapHeapNext() it says "if we are using lossy info,
we have to recheck the qual conditions at every tuple". And in
heapam_bitmap_next_block(), when the bitmap is lossy it says "bitmap
is lossy, so we must examine each line pointer on the page. But we can
ignore HOT chains, since we'll check each tuple anyway"

I must admit I don't quite understand the connection between a lossy
bitmap and needing to recheck the qual condition. Once we've gone to
the underlying data, why do we need to recheck each tuple unless the
qual requires it? It seems like PageTableEntry->recheck is usually
passed as true for hash indexes and false for btree indexes. So maybe
it has something to do with the index type?

Anyway, adding a `lossy` member can be another patch. I just wanted to
check if that was the solution you were thinking of.

On a somewhat related note, I included a patch to alter the test at
the top of heapam_bitmap_next_tuple()

if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples)

I don't really see how rs_cindex could ever be < 0 for bitmap heap
scans. But, I'm not confident enough about this to commit the patch
really (obviously tests pass with the Assertion I added -- but still).

Also, maybe consider manually wrapping long lines - I haven't tried, but
I guess pgindent did not wrap this. I mean this line, for example:

... whitespace ... &node->stats.lossy_pages, &node->stats.exact_pages))

Ah, yes. pgindent indeed does not help with this. I have now gone
through every commit and used

git diff origin/master | grep -E '^(\+|diff)' | sed 's/^+//' | expand
-t4 | awk "length > 78 || /^diff/"

from the committing wiki :)

2) 0003

The "tidr" name is not particularly clear, IMO. Maybe just "range" would
be better?

I've updated this.

+  struct
+  {
+      ItemPointerData rs_mintid;
+      ItemPointerData rs_maxtid;
+  }   tidr;

Isn't it a bit strange that this patch remove tmbres from
heapam_scan_bitmap_next_block, when it was already removed from
table_scan_bitmap_next_tuple in the previous commit? Does it make sense
to separate it like this? (Maybe it does, not sure.)

I've combined them.

I find this not very clear:

+ *    recheck     do current page's tuples need recheck
+ *    blockno     used to validate pf and current block in sync
+ *    pfblockno   used to validate pf stays ahead of current block

The "blockno" sounds weird - shouldn't it say "are in sync"? Also, not
clear what "pf" stands for without context (sure, it's "prefetch"). But
Why not to not write "prefetch_blockno" or something like that?

Fixed.

3) 0006

Seems unnecessary to keep this as separate commit, it's just log
message improvement. I'd merge it to the earlier patch.

Done.

4) 0007

Seems fine to me in principle. This adds "subclass" similar to what we
do for plan nodes, except that states are not derived from Node. But
it's the same approach.

Why not to do

scan = (HeapScanDesc *) bscan;

instead of

scan = &bscan->rs_heap_base;

I think the simple cast is what we do for the plan nodes, and we even do
it this way in the opposite direction in a couple places:

BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) scan;

Yea, in the reverse case, there is no way to refer to a specific
member (because we are casting something of the parent type to the
child type). But when we are casting from the child type to the parent
type and can actually refer to a member, it seems preferable to
explicitly refer to the member in case anyone ever inserts a member
above rs_heap_base. However, for consistency with other places in the
code, I've changed it as you suggested.

Additionally, I've gone through an made a number of stylistic changes
to conform more closely to existing styles (adding back more rs_
prefixes and typedef'ing BitmapHeapScanDescData * as
BitmapHeapScanDesc [despite how sad it makes me]).

BTW would it be a good idea for heapam_scan_bitmap_next_block to check
the passed "scan" has SO_TYPE_BITMAPSCAN? We haven't been checking that
so far I think, but we only had a single struct ...

Good point. I've done this.

I plan to commit 0002 and 0003 next week. I'm interested if you think
0001 is correct.
I may also commit 0004-0006 as I feel they are ready too.

Are we planning to commit this refactoring? I think this refactoring
makes the overall code of BitmapHeapNext() quite clean and readable.
I haven't read all patches but 0001-0006 including 0009 makes this
code quite clean and readable. I like the refactoring of merging of
the shared iterator and the private iterator also.

--
Regards,
Dilip Kumar
EnterpriseDB: http://www.enterprisedb.com

#163Richard Guo
guofenglinux@gmail.com
In reply to: Melanie Plageman (#161)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Oct 19, 2024 at 5:48 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I plan to commit 0002 and 0003 next week. I'm interested if you think
0001 is correct.
I may also commit 0004-0006 as I feel they are ready too.

I noticed an oversight on master, which I think was introduced by the
0005 patch. In ExecReScanBitmapHeapScan:

-      if (scan->st.bitmap.rs_shared_iterator)
-      {
-              tbm_end_shared_iterate(scan->st.bitmap.rs_shared_iterator);
-              scan->st.bitmap.rs_shared_iterator = NULL;
-      }
-
-      if (scan->st.bitmap.rs_iterator)
-      {
-              tbm_end_private_iterate(scan->st.bitmap.rs_iterator);
-              scan->st.bitmap.rs_iterator = NULL;
-      }
+      tbm_end_iterate(&scan->st.rs_tbmiterator);

I don't think it's safe to call tbm_end_iterate directly on
scan->st.rs_tbmiterator, as it may have already been cleaned up by
this point.

Here is a query that triggers a SIGSEGV fault on master.

create table t (a int);
insert into t values (1), (2);
create index on t (a);

set enable_seqscan to off;
set enable_indexscan to off;

select * from t t1 left join t t2 on t1.a in (select a from t t3 where
t2.a > 1);

I think we need to check whether rs_tbmiterator is NULL before calling
tbm_end_iterate on it, like below.

--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -572,9 +572,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
    if (scan)
    {
        /*
-        * End iteration on iterators saved in scan descriptor.
+        * End iteration on iterators saved in scan descriptor, if they
+        * haven't already been cleaned up.
         */
-       tbm_end_iterate(&scan->st.rs_tbmiterator);
+       if (!tbm_exhausted(&scan->st.rs_tbmiterator))
+           tbm_end_iterate(&scan->st.rs_tbmiterator);

/* rescan to release any page pin */
table_rescan(node->ss.ss_currentScanDesc, NULL);

Thanks
Richard

#164Richard Guo
guofenglinux@gmail.com
In reply to: Richard Guo (#163)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Dec 19, 2024 at 6:15 PM Richard Guo <guofenglinux@gmail.com> wrote:

I think we need to check whether rs_tbmiterator is NULL before calling
tbm_end_iterate on it, like below.

--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -572,9 +572,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
if (scan)
{
/*
-        * End iteration on iterators saved in scan descriptor.
+        * End iteration on iterators saved in scan descriptor, if they
+        * haven't already been cleaned up.
*/
-       tbm_end_iterate(&scan->st.rs_tbmiterator);
+       if (!tbm_exhausted(&scan->st.rs_tbmiterator))
+           tbm_end_iterate(&scan->st.rs_tbmiterator);

/* rescan to release any page pin */
table_rescan(node->ss.ss_currentScanDesc, NULL);

This change may also be needed in ExecEndBitmapHeapScan().

Thanks
Richard

#165Melanie Plageman
melanieplageman@gmail.com
In reply to: Richard Guo (#164)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Dec 19, 2024 at 10:12 AM Richard Guo <guofenglinux@gmail.com> wrote:

On Thu, Dec 19, 2024 at 6:15 PM Richard Guo <guofenglinux@gmail.com> wrote:

I think we need to check whether rs_tbmiterator is NULL before calling
tbm_end_iterate on it, like below.

--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -572,9 +572,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
if (scan)
{
/*
-        * End iteration on iterators saved in scan descriptor.
+        * End iteration on iterators saved in scan descriptor, if they
+        * haven't already been cleaned up.
*/
-       tbm_end_iterate(&scan->st.rs_tbmiterator);
+       if (!tbm_exhausted(&scan->st.rs_tbmiterator))
+           tbm_end_iterate(&scan->st.rs_tbmiterator);

/* rescan to release any page pin */
table_rescan(node->ss.ss_currentScanDesc, NULL);

This change may also be needed in ExecEndBitmapHeapScan().

Thanks, Richard! I'm working on the fix and adding the test case you found.

- Melanie

#166Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#165)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Dec 19, 2024 at 10:23 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Dec 19, 2024 at 10:12 AM Richard Guo <guofenglinux@gmail.com> wrote:

On Thu, Dec 19, 2024 at 6:15 PM Richard Guo <guofenglinux@gmail.com> wrote:

I think we need to check whether rs_tbmiterator is NULL before calling
tbm_end_iterate on it, like below.

--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -572,9 +572,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
if (scan)
{
/*
-        * End iteration on iterators saved in scan descriptor.
+        * End iteration on iterators saved in scan descriptor, if they
+        * haven't already been cleaned up.
*/
-       tbm_end_iterate(&scan->st.rs_tbmiterator);
+       if (!tbm_exhausted(&scan->st.rs_tbmiterator))
+           tbm_end_iterate(&scan->st.rs_tbmiterator);

/* rescan to release any page pin */
table_rescan(node->ss.ss_currentScanDesc, NULL);

This change may also be needed in ExecEndBitmapHeapScan().

Thanks, Richard! I'm working on the fix and adding the test case you found.

Okay, pushed. Thanks so much, Richard. I also noticed another
oversight and fixed it.

- Melanie

#167Melanie Plageman
melanieplageman@gmail.com
In reply to: Dilip Kumar (#162)
5 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Dec 9, 2024 at 1:22 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:

Are we planning to commit this refactoring? I think this refactoring
makes the overall code of BitmapHeapNext() quite clean and readable.
I haven't read all patches but 0001-0006 including 0009 makes this
code quite clean and readable. I like the refactoring of merging of
the shared iterator and the private iterator also.

Thanks for the feedback, Dilip. I've pushed the patches through 0006.

I've reorganized the remaining patches in attached v26.

0001 is just the refactoring to push the setup into a helper.
0002-0003 are required refactoring of the TBMIterateResult and
TBMIterator to support the read stream API.
0004 implements using the read stream API and removing the old prefetching code.
0005 removes the table_scan_bitmap_next_block() callback, as it is not
really used anymore in BitmapHeapNext() to get the next block.

I could use review feedback on all of them. 0001 should be ready to
push once I get some review.

0002 and 0003 shouldn't be committed without committing the read
stream commit because they are not improvements on their own. However,
I have an outstanding question in 0003 that I could use input on.

0004 needs another round of benchmarking.

0005 needs review once the others are dealt with.

- Melanie

Attachments:

v26-0001-Move-BitmapTableScan-per-scan-setup-into-a-helpe.patchtext/x-patch; charset=US-ASCII; name=v26-0001-Move-BitmapTableScan-per-scan-setup-into-a-helpe.patchDownload
From 7c73e5e868781904730cc4ea0fa62266c4fe8f4b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 Jan 2025 17:36:50 -0500
Subject: [PATCH v26 1/5] Move BitmapTableScan per-scan setup into a helper

Add BitmapTableScanSetup(), a helper which contains all of the code that
must be done on every scan of the table in a bitmap table scan. This
includes scanning the index, building the bitmap, and setting up the
scan descriptors.

Much of BitmapHeapNext() code was this setup, so it made sense to put it
in a helper function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 205 +++++++++++-----------
 1 file changed, 106 insertions(+), 99 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be616683f98..92a199c1e87 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -48,6 +48,7 @@
 #include "utils/rel.h"
 #include "utils/spccache.h"
 
+static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
@@ -57,6 +58,109 @@ static inline void BitmapPrefetch(BitmapHeapScanState *node,
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
+/*
+*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
+ *
+* For prefetching, we use *two* iterators, one for the pages we are
+* actually scanning and another that runs ahead of the first for
+* prefetching.  node->prefetch_pages tracks exactly how many pages ahead
+* the prefetch iterator is.  Also, node->prefetch_target tracks the
+* desired prefetch distance, which starts small and increases up to the
+* node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
+* a scan that stops after a few tuples because of a LIMIT.
+*/
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
+{
+	TBMIterator tbmiterator = {0};
+	ParallelBitmapHeapState *pstate = node->pstate;
+	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
+
+
+	if (!pstate)
+	{
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+	}
+	else if (BitmapShouldInitializeSharedState(pstate))
+	{
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+
+		/*
+		 * Prepare to iterate over the TBM. This will return the dsa_pointer
+		 * of the iterator state which will be used by multiple processes to
+		 * iterate jointly.
+		 */
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			pstate->prefetch_iterator =
+				tbm_prepare_shared_iterate(node->tbm);
+		}
+#endif							/* USE_PREFETCH */
+
+		/* We have initialized the shared state so wake up others. */
+		BitmapDoneInitializingSharedState(pstate);
+	}
+
+	tbmiterator = tbm_begin_iterate(node->tbm, dsa,
+									pstate ?
+									pstate->tbmiterator :
+									InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+	if (node->prefetch_maximum > 0)
+		node->prefetch_iterator =
+			tbm_begin_iterate(node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!node->ss.ss_currentScanDesc)
+	{
+		bool		need_tuples = false;
+
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
+		node->ss.ss_currentScanDesc =
+			table_beginscan_bm(node->ss.ss_currentRelation,
+							   node->ss.ps.state->es_snapshot,
+							   0,
+							   NULL,
+							   need_tuples);
+	}
+
+	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->initialized = true;
+}
+
+
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -68,10 +172,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
-	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
 	 * extract necessary information from index scan node
@@ -79,110 +181,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator tbmiterator;
-
-		if (!pstate)
-		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-
-			node->tbm = tbm;
-		}
-		else if (BitmapShouldInitializeSharedState(pstate))
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-
-			node->tbm = tbm;
-
-			/*
-			 * Prepare to iterate over the TBM. This will return the
-			 * dsa_pointer of the iterator state which will be used by
-			 * multiple processes to iterate jointly.
-			 */
-			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				pstate->prefetch_iterator =
-					tbm_prepare_shared_iterate(tbm);
-			}
-#endif							/* USE_PREFETCH */
-
-			/* We have initialized the shared state so wake up others. */
-			BitmapDoneInitializingSharedState(pstate);
-		}
-
-		tbmiterator = tbm_begin_iterate(tbm, dsa,
-										pstate ?
-										pstate->tbmiterator :
-										InvalidDsaPointer);
-
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-			node->prefetch_iterator =
-				tbm_begin_iterate(tbm, dsa,
-								  pstate ?
-								  pstate->prefetch_iterator :
-								  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
-		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
-		 */
-		if (!scan)
-		{
-			bool		need_tuples = false;
-
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
-									  need_tuples);
-
-			node->ss.ss_currentScanDesc = scan;
-		}
-
-		scan->st.rs_tbmiterator = tbmiterator;
-		node->initialized = true;
-
+		BitmapTableScanSetup(node);
+		scan = node->ss.ss_currentScanDesc;
 		goto new_page;
 	}
 
-- 
2.34.1

v26-0004-BitmapHeapScan-uses-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v26-0004-BitmapHeapScan-uses-read-stream-API.patchDownload
From 19cdf4706e0ad1842ad3eb14a5c81fa16e88f976 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:00:12 -0500
Subject: [PATCH v26 4/5] BitmapHeapScan uses read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.
---
 src/backend/access/heap/heapam.c          |  70 +++++
 src/backend/access/heap/heapam_handler.c  |  86 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 355 +---------------------
 src/include/access/relscan.h              |   8 +-
 src/include/access/tableam.h              |  33 +-
 src/include/nodes/execnodes.h             |  23 +-
 6 files changed, 131 insertions(+), 444 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b6349950294..fc4e3f807d6 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -277,6 +277,62 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&sscan->st.bitmap.rs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			bscan->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1065,6 +1121,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1144,6 +1201,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1178,7 +1245,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bd567760f2d..eac51f5eb51 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2115,76 +2115,66 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		bscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2205,7 +2195,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2214,9 +2204,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2266,7 +2256,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index da3c76f4744..5b368a3dccc 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,27 +51,14 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
 /*
-*
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
-* For prefetching, we use *two* iterators, one for the pages we are
-* actually scanning and another that runs ahead of the first for
-* prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-* the prefetch iterator is.  Also, node->prefetch_target tracks the
-* desired prefetch distance, which starts small and increases up to the
-* node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-* a scan that stops after a few tuples because of a LIMIT.
-*/
+ */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
 {
@@ -104,14 +91,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -121,15 +100,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -151,16 +121,16 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		node->ss.ss_currentScanDesc =
 			table_beginscan_bm(node->ss.ss_currentRelation,
 							   node->ss.ps.state->es_snapshot,
+							   pstate,
 							   0,
 							   NULL,
 							   need_tuples);
 	}
 
-	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bitmap.rs_iterator = tbmiterator;
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -173,7 +143,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 
 	/*
 	 * extract necessary information from index scan node
@@ -200,40 +169,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Continuing in previously obtained page.
 			 */
-
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -253,34 +190,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/* OK to return this tuple */
 			return slot;
 		}
-
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -304,226 +224,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -573,31 +273,19 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scan->st.rs_tbmiterator))
-			tbm_end_iterate(&scan->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scan->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scan->st.bitmap.rs_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -657,8 +345,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
-			tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scanDesc->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scanDesc->st.bitmap.rs_iterator);
 
 		/*
 		 * close table scan
@@ -666,17 +354,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -709,18 +391,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -760,13 +437,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -870,12 +540,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -912,17 +579,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index dc6e0184284..934b667ad78 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,12 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator rs_tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *rs_pstate;
+			TBMIterator rs_iterator;
+		}			bitmap;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 09b9b394e0e..6a8ba3b8657 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -796,28 +796,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -955,15 +939,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
+				   struct ParallelBitmapHeapState *pstate,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-									   NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys,
+										 key, NULL, flags);
+	result->st.bitmap.rs_pstate = pstate;
+	return result;
 }
 
 /*
@@ -1965,16 +1953,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1988,7 +1971,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d0f2dca5928..3000a1ce756 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1807,11 +1807,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1819,10 +1815,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1846,18 +1839,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1865,18 +1851,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v26-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v26-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From cadf9b662830ac19e71b40a9a8689feee83178a2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 17:20:28 -0500
Subject: [PATCH v26 3/5] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently,
allowing asynchronous use of the TIDBitmap for prefetching.

tbm_[shared|private]_iterate() now sets blockno to InvalidBlockNumber
when the bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, we inline the
matchResult in the GinScanEntry to avoid having to separately manage
memory for the TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 51 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 30 ++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 40 ++++++------
 src/backend/nodes/tidbitmap.c             | 79 +++++++++++------------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 111 insertions(+), 99 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 330805626ee..7cf3dd2a4b9 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_private_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -824,19 +837,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -847,7 +860,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -860,10 +873,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -877,27 +890,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..625140fdf25 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a4003cf59e1..bd567760f2d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2124,7 +2124,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
 
@@ -2138,9 +2138,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
+		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
 		/*
@@ -2152,11 +2152,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2164,19 +2164,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2205,7 +2205,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2214,9 +2214,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2266,7 +2266,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 92a199c1e87..da3c76f4744 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -316,7 +316,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -329,9 +329,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -370,9 +369,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -440,17 +438,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -459,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -480,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -499,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3d38cc04cc5..40d7b9f7505 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -948,20 +946,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -999,11 +998,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1019,16 +1018,16 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1038,10 +1037,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1092,13 +1090,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1108,21 +1106,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1598,13 +1596,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or private bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..a7071c4cbdc 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index b2e322508a2..f3956d5171e 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -86,8 +86,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -98,7 +98,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v26-0002-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-patch; charset=US-ASCII; name=v26-0002-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From 9fa10cd0ee89626e048adb4ce0c8d25a309a2d11 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 16:42:25 -0500
Subject: [PATCH v26 2/5] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 26 +++++++-------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index af6ac64b3fc..3d38cc04cc5 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,9 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1468,8 +1457,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index fedbf69eb53..b2e322508a2 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -55,9 +56,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.34.1

v26-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v26-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From ad5a7de323d3bea2509dce52c37415cc22be7281 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:35:17 -0500
Subject: [PATCH v26 5/5] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator usage into table-AM specific code (as
part of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer set the current blockno.

BitmapHeapNext() doesn't use the block number for anything, so there is
no reason to have a separte scan_bitmap_next_block() callback.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple().

The heap AM implementation of scan_bitmap_next_block() is now a local
helper in heapam_handler.c.
---
 src/backend/access/heap/heapam_handler.c  | 354 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   2 -
 src/backend/executor/nodeBitmapHeapscan.c |  71 ++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 235 insertions(+), 284 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index eac51f5eb51..f449272a2ea 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,11 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2114,189 +2119,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	*recheck = tbmres->recheck;
-
-	hscan->rs_cblock = tbmres->blockno;
-	hscan->rs_ntuples = tbmres->ntuples;
-
-	block = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (tbmres->ntuples >= 0)
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
-		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
 
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2603,6 +2463,167 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = tbmres->offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * invoke this function again.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2662,7 +2683,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..56378007a81 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5b368a3dccc..f32a9da8efe 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -140,67 +140,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-			CHECK_FOR_INTERRUPTS();
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
-new_page:
 
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 6a8ba3b8657..afdc93d1acf 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -779,43 +779,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1942,51 +1922,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1997,7 +1950,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

#168Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#167)
5 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Jan 22, 2025 at 4:24 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Mon, Dec 9, 2024 at 1:22 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:

Are we planning to commit this refactoring? I think this refactoring
makes the overall code of BitmapHeapNext() quite clean and readable.
I haven't read all patches but 0001-0006 including 0009 makes this
code quite clean and readable. I like the refactoring of merging of
the shared iterator and the private iterator also.

Thanks for the feedback, Dilip. I've pushed the patches through 0006.

I've reorganized the remaining patches in attached v26.

0001 is just the refactoring to push the setup into a helper.
0002-0003 are required refactoring of the TBMIterateResult and
TBMIterator to support the read stream API.
0004 implements using the read stream API and removing the old prefetching code.
0005 removes the table_scan_bitmap_next_block() callback, as it is not
really used anymore in BitmapHeapNext() to get the next block.

I could use review feedback on all of them. 0001 should be ready to
push once I get some review.

Bilal mentioned offlist that 0001 had some indentation issues in one
of the comments. v27 attached.

- Melanie

Attachments:

v27-0004-BitmapHeapScan-uses-read-stream-API.patchapplication/octet-stream; name=v27-0004-BitmapHeapScan-uses-read-stream-API.patchDownload
From c9bc705e9df6a04ef2df1db277d8f97dd89b1e91 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:00:12 -0500
Subject: [PATCH v27 4/5] BitmapHeapScan uses read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.
---
 src/backend/access/heap/heapam.c          |  70 +++++
 src/backend/access/heap/heapam_handler.c  |  86 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 352 +---------------------
 src/include/access/relscan.h              |   8 +-
 src/include/access/tableam.h              |  33 +-
 src/include/nodes/execnodes.h             |  23 +-
 6 files changed, 130 insertions(+), 442 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index ea0a12b39af..45f419f849f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,62 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&sscan->st.bitmap.rs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			bscan->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1123,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1203,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1247,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bd567760f2d..eac51f5eb51 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2115,76 +2115,66 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		bscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2205,7 +2195,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2214,9 +2204,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2266,7 +2256,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5a55d6e2bdf..46721e091ab 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -149,16 +120,16 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		node->ss.ss_currentScanDesc =
 			table_beginscan_bm(node->ss.ss_currentRelation,
 							   node->ss.ps.state->es_snapshot,
+							   pstate,
 							   0,
 							   NULL,
 							   need_tuples);
 	}
 
-	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bitmap.rs_iterator = tbmiterator;
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -171,7 +142,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	ExprContext *econtext;
 	TableScanDesc scan;
 	TupleTableSlot *slot;
-	ParallelBitmapHeapState *pstate = node->pstate;
 
 	/*
 	 * extract necessary information from index scan node
@@ -198,40 +168,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Continuing in previously obtained page.
 			 */
-
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -251,34 +189,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/* OK to return this tuple */
 			return slot;
 		}
-
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -302,226 +223,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -571,31 +272,19 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scan->st.rs_tbmiterator))
-			tbm_end_iterate(&scan->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scan->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scan->st.bitmap.rs_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -655,8 +344,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
-			tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scanDesc->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scanDesc->st.bitmap.rs_iterator);
 
 		/*
 		 * close table scan
@@ -664,17 +353,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -707,18 +390,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -758,13 +436,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -868,12 +539,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -910,17 +578,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index dc6e0184284..934b667ad78 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,12 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator rs_tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *rs_pstate;
+			TBMIterator rs_iterator;
+		}			bitmap;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..b5675b47dcc 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -956,15 +940,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
+				   struct ParallelBitmapHeapState *pstate,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-									   NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys,
+										 key, NULL, flags);
+	result->st.bitmap.rs_pstate = pstate;
+	return result;
 }
 
 /*
@@ -1966,16 +1954,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1972,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d0f2dca5928..3000a1ce756 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1807,11 +1807,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1819,10 +1815,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1846,18 +1839,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1865,18 +1851,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.45.2

v27-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchapplication/octet-stream; name=v27-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From fcca47b8b755892359a7435ab7a5857317139b29 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 17:20:28 -0500
Subject: [PATCH v27 3/5] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently,
allowing asynchronous use of the TIDBitmap for prefetching.

tbm_[shared|private]_iterate() now sets blockno to InvalidBlockNumber
when the bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, we inline the
matchResult in the GinScanEntry to avoid having to separately manage
memory for the TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 51 +++++++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 30 ++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 40 ++++++------
 src/backend/nodes/tidbitmap.c             | 79 +++++++++++------------
 src/include/access/gin_private.h          |  2 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 111 insertions(+), 99 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 330805626ee..7cf3dd2a4b9 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,22 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+	/*
+	 * MTODO: is it enough to set blockno to InvalidBlockNumber? In all the
+	 * places were we previously set matchResult to NULL, I just set blockno
+	 * to InvalidBlockNumber. It seems like this should be okay because that
+	 * is usually what we check before using the matchResult members. But it
+	 * might be safer to zero out the offsets array. But that is expensive.
+	 */
+	entry->matchResult.blockno = InvalidBlockNumber;
+	entry->matchResult.ntuples = 0;
+	entry->matchResult.recheck = true;
+	memset(entry->matchResult.offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -374,6 +386,7 @@ restartScanEntry:
 			{
 				if (entry->matchIterator)
 					tbm_end_private_iterate(entry->matchIterator);
+				entry->matchResult.blockno = InvalidBlockNumber;
 				entry->matchIterator = NULL;
 				tbm_free(entry->matchBitmap);
 				entry->matchBitmap = NULL;
@@ -824,19 +837,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -847,7 +860,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -860,10 +873,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -877,27 +890,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..625140fdf25 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a4003cf59e1..bd567760f2d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2124,7 +2124,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
 
@@ -2138,9 +2138,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
+		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
 		/*
@@ -2152,11 +2152,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2164,19 +2164,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2205,7 +2205,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2214,9 +2214,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2266,7 +2266,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 7b1fd24b419..5a55d6e2bdf 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -314,7 +314,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -327,9 +327,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -368,9 +367,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -438,17 +436,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -457,13 +457,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -478,7 +478,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -497,25 +497,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3d38cc04cc5..40d7b9f7505 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -948,20 +946,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -999,11 +998,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1019,16 +1018,16 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1038,10 +1037,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1092,13 +1090,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1108,21 +1106,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1598,13 +1596,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or private bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..a7071c4cbdc 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,7 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index b2e322508a2..f3956d5171e 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -86,8 +86,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -98,7 +98,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.45.2

v27-0002-Hard-code-TBMIterateResult-offsets-array-size.patchapplication/octet-stream; name=v27-0002-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From f558a88a21a4e8d6754325d94cb126c0d9826eb9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 16:42:25 -0500
Subject: [PATCH v27 2/5] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.
Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the API user.
---
 src/backend/nodes/tidbitmap.c | 26 +++++++-------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index af6ac64b3fc..3d38cc04cc5 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,9 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1468,8 +1457,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index fedbf69eb53..b2e322508a2 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -55,9 +56,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.45.2

v27-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchapplication/octet-stream; name=v27-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 5c121b664c28429d2e7925794ccee64409c883a5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:35:17 -0500
Subject: [PATCH v27 5/5] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator usage into table-AM specific code (as
part of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer set the current blockno.

BitmapHeapNext() doesn't use the block number for anything, so there is
no reason to have a separte scan_bitmap_next_block() callback.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple().

The heap AM implementation of scan_bitmap_next_block() is now a local
helper in heapam_handler.c.
---
 src/backend/access/heap/heapam_handler.c  | 354 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   2 -
 src/backend/executor/nodeBitmapHeapscan.c |  71 ++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 235 insertions(+), 284 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index eac51f5eb51..f449272a2ea 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,11 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2114,189 +2119,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	*recheck = tbmres->recheck;
-
-	hscan->rs_cblock = tbmres->blockno;
-	hscan->rs_ntuples = tbmres->ntuples;
-
-	block = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (tbmres->ntuples >= 0)
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
-		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
 
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2603,6 +2463,167 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = tbmres->offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * invoke this function again.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2662,7 +2683,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..56378007a81 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 46721e091ab..68499e3aa45 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -139,67 +139,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-			CHECK_FOR_INTERRUPTS();
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
-new_page:
 
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b5675b47dcc..4206a6d0ab1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1943,51 +1923,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1998,7 +1951,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.45.2

v27-0001-Move-BitmapTableScan-per-scan-setup-into-a-helpe.patchapplication/octet-stream; name=v27-0001-Move-BitmapTableScan-per-scan-setup-into-a-helpe.patchDownload
From f607a4b9994e622d2c5f15054dce24f2f99ca255 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 21 Jan 2025 17:36:50 -0500
Subject: [PATCH v27 1/5] Move BitmapTableScan per-scan setup into a helper

Add BitmapTableScanSetup(), a helper which contains all of the code that
must be done on every scan of the table in a bitmap table scan. This
includes scanning the index, building the bitmap, and setting up the
scan descriptors.

Much of BitmapHeapNext() code was this setup, so it made sense to put it
in a helper function.
---
 src/backend/executor/nodeBitmapHeapscan.c | 203 +++++++++++-----------
 1 file changed, 104 insertions(+), 99 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be616683f98..7b1fd24b419 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -48,6 +48,7 @@
 #include "utils/rel.h"
 #include "utils/spccache.h"
 
+static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
 static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
@@ -57,6 +58,107 @@ static inline void BitmapPrefetch(BitmapHeapScanState *node,
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
+/*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
+ *
+ * For prefetching, we use *two* iterators, one for the pages we are actually
+ * scanning and another that runs ahead of the first for prefetching.
+ * node->prefetch_pages tracks exactly how many pages ahead the prefetch
+ * iterator is.  Also, node->prefetch_target tracks the desired prefetch
+ * distance, which starts small and increases up to the
+ * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
+ * scan that stops after a few tuples because of a LIMIT.
+ */
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
+{
+	TBMIterator tbmiterator = {0};
+	ParallelBitmapHeapState *pstate = node->pstate;
+	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
+
+	if (!pstate)
+	{
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+	}
+	else if (BitmapShouldInitializeSharedState(pstate))
+	{
+		/*
+		 * The leader will immediately come out of the function, but others
+		 * will be blocked until leader populates the TBM and wakes them up.
+		 */
+		node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+			elog(ERROR, "unrecognized result from subplan");
+
+		/*
+		 * Prepare to iterate over the TBM. This will return the dsa_pointer
+		 * of the iterator state which will be used by multiple processes to
+		 * iterate jointly.
+		 */
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+
+#ifdef USE_PREFETCH
+		if (node->prefetch_maximum > 0)
+		{
+			pstate->prefetch_iterator =
+				tbm_prepare_shared_iterate(node->tbm);
+		}
+#endif							/* USE_PREFETCH */
+
+		/* We have initialized the shared state so wake up others. */
+		BitmapDoneInitializingSharedState(pstate);
+	}
+
+	tbmiterator = tbm_begin_iterate(node->tbm, dsa,
+									pstate ?
+									pstate->tbmiterator :
+									InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+	if (node->prefetch_maximum > 0)
+		node->prefetch_iterator =
+			tbm_begin_iterate(node->tbm, dsa,
+							  pstate ?
+							  pstate->prefetch_iterator :
+							  InvalidDsaPointer);
+#endif							/* USE_PREFETCH */
+
+	/*
+	 * If this is the first scan of the underlying table, create the table
+	 * scan descriptor and begin the scan.
+	 */
+	if (!node->ss.ss_currentScanDesc)
+	{
+		bool		need_tuples = false;
+
+		/*
+		 * We can potentially skip fetching heap pages if we do not need any
+		 * columns of the table, either for checking non-indexable quals or
+		 * for returning data.  This test is a bit simplistic, as it checks
+		 * the stronger condition that there's no qual or return tlist at all.
+		 * But in most cases it's probably not worth working harder than that.
+		 */
+		need_tuples = (node->ss.ps.plan->qual != NIL ||
+					   node->ss.ps.plan->targetlist != NIL);
+
+		node->ss.ss_currentScanDesc =
+			table_beginscan_bm(node->ss.ss_currentRelation,
+							   node->ss.ps.state->es_snapshot,
+							   0,
+							   NULL,
+							   need_tuples);
+	}
+
+	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->initialized = true;
+}
+
+
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -68,10 +170,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 {
 	ExprContext *econtext;
 	TableScanDesc scan;
-	TIDBitmap  *tbm;
 	TupleTableSlot *slot;
 	ParallelBitmapHeapState *pstate = node->pstate;
-	dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
 
 	/*
 	 * extract necessary information from index scan node
@@ -79,110 +179,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	econtext = node->ss.ps.ps_ExprContext;
 	slot = node->ss.ss_ScanTupleSlot;
 	scan = node->ss.ss_currentScanDesc;
-	tbm = node->tbm;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
-	 *
-	 * For prefetching, we use *two* iterators, one for the pages we are
-	 * actually scanning and another that runs ahead of the first for
-	 * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
-	 * the prefetch iterator is.  Also, node->prefetch_target tracks the
-	 * desired prefetch distance, which starts small and increases up to the
-	 * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
-	 * a scan that stops after a few tuples because of a LIMIT.
 	 */
 	if (!node->initialized)
 	{
-		TBMIterator tbmiterator;
-
-		if (!pstate)
-		{
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-
-			node->tbm = tbm;
-		}
-		else if (BitmapShouldInitializeSharedState(pstate))
-		{
-			/*
-			 * The leader will immediately come out of the function, but
-			 * others will be blocked until leader populates the TBM and wakes
-			 * them up.
-			 */
-			tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-			if (!tbm || !IsA(tbm, TIDBitmap))
-				elog(ERROR, "unrecognized result from subplan");
-
-			node->tbm = tbm;
-
-			/*
-			 * Prepare to iterate over the TBM. This will return the
-			 * dsa_pointer of the iterator state which will be used by
-			 * multiple processes to iterate jointly.
-			 */
-			pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-
-#ifdef USE_PREFETCH
-			if (node->prefetch_maximum > 0)
-			{
-				pstate->prefetch_iterator =
-					tbm_prepare_shared_iterate(tbm);
-			}
-#endif							/* USE_PREFETCH */
-
-			/* We have initialized the shared state so wake up others. */
-			BitmapDoneInitializingSharedState(pstate);
-		}
-
-		tbmiterator = tbm_begin_iterate(tbm, dsa,
-										pstate ?
-										pstate->tbmiterator :
-										InvalidDsaPointer);
-
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-			node->prefetch_iterator =
-				tbm_begin_iterate(tbm, dsa,
-								  pstate ?
-								  pstate->prefetch_iterator :
-								  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
-		/*
-		 * If this is the first scan of the underlying table, create the table
-		 * scan descriptor and begin the scan.
-		 */
-		if (!scan)
-		{
-			bool		need_tuples = false;
-
-			/*
-			 * We can potentially skip fetching heap pages if we do not need
-			 * any columns of the table, either for checking non-indexable
-			 * quals or for returning data.  This test is a bit simplistic, as
-			 * it checks the stronger condition that there's no qual or return
-			 * tlist at all. But in most cases it's probably not worth working
-			 * harder than that.
-			 */
-			need_tuples = (node->ss.ps.plan->qual != NIL ||
-						   node->ss.ps.plan->targetlist != NIL);
-
-			scan = table_beginscan_bm(node->ss.ss_currentRelation,
-									  node->ss.ps.state->es_snapshot,
-									  0,
-									  NULL,
-									  need_tuples);
-
-			node->ss.ss_currentScanDesc = scan;
-		}
-
-		scan->st.rs_tbmiterator = tbmiterator;
-		node->initialized = true;
-
+		BitmapTableScanSetup(node);
+		scan = node->ss.ss_currentScanDesc;
 		goto new_page;
 	}
 
-- 
2.45.2

#169Nazir Bilal Yavuz
byavuz81@gmail.com
In reply to: Melanie Plageman (#168)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On Thu, 30 Jan 2025 at 00:38, Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Wed, Jan 22, 2025 at 4:24 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

0001 is just the refactoring to push the setup into a helper.
0002-0003 are required refactoring of the TBMIterateResult and
TBMIterator to support the read stream API.
0004 implements using the read stream API and removing the old prefetching code.
0005 removes the table_scan_bitmap_next_block() callback, as it is not
really used anymore in BitmapHeapNext() to get the next block.

I could use review feedback on all of them. 0001 should be ready to
push once I get some review.

Bilal mentioned offlist that 0001 had some indentation issues in one
of the comments. v27 attached.

I have no other comments, 0001 LGTM.

--
Regards,
Nazir Bilal Yavuz
Microsoft

#170Melanie Plageman
melanieplageman@gmail.com
In reply to: Nazir Bilal Yavuz (#169)
4 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Jan 30, 2025 at 3:02 AM Nazir Bilal Yavuz <byavuz81@gmail.com> wrote:

On Thu, 30 Jan 2025 at 00:38, Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Wed, Jan 22, 2025 at 4:24 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

0001 is just the refactoring to push the setup into a helper.
0002-0003 are required refactoring of the TBMIterateResult and
TBMIterator to support the read stream API.
0004 implements using the read stream API and removing the old prefetching code.
0005 removes the table_scan_bitmap_next_block() callback, as it is not
really used anymore in BitmapHeapNext() to get the next block.

I could use review feedback on all of them. 0001 should be ready to
push once I get some review.

Bilal mentioned offlist that 0001 had some indentation issues in one
of the comments. v27 attached.

I have no other comments, 0001 LGTM.

Cool, thanks!

I pushed v27-0001.

Attached v28 is rebased and has a few updates/cleanup. All patches in
the set need review and I need to do some benchmarking of v28-0003.

- Melanie

Attachments:

v28-0003-BitmapHeapScan-uses-read-stream-API.patchapplication/octet-stream; name=v28-0003-BitmapHeapScan-uses-read-stream-API.patchDownload
From b232efe88b364153d3515bdc64c59746e1e7977c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:00:12 -0500
Subject: [PATCH v28 3/4] BitmapHeapScan uses read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.
---
 src/backend/access/heap/heapam.c          |  70 +++++
 src/backend/access/heap/heapam_handler.c  |  86 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 355 +---------------------
 src/include/access/relscan.h              |   8 +-
 src/include/access/tableam.h              |  33 +-
 src/include/nodes/execnodes.h             |  23 +-
 6 files changed, 130 insertions(+), 445 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index ea0a12b39af..45f419f849f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,62 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&sscan->st.bitmap.rs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			bscan->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1123,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1203,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1247,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bd567760f2d..eac51f5eb51 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2115,76 +2115,66 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		bscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2205,7 +2195,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2214,9 +2204,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2266,7 +2256,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 32dea13cb86..46721e091ab 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -149,16 +120,16 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		node->ss.ss_currentScanDesc =
 			table_beginscan_bm(node->ss.ss_currentRelation,
 							   node->ss.ps.state->es_snapshot,
+							   pstate,
 							   0,
 							   NULL,
 							   need_tuples);
 	}
 
-	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bitmap.rs_iterator = tbmiterator;
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +143,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -201,40 +168,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Continuing in previously obtained page.
 			 */
-
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -254,34 +189,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/* OK to return this tuple */
 			return slot;
 		}
-
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,226 +223,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -574,31 +272,19 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scan->st.rs_tbmiterator))
-			tbm_end_iterate(&scan->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scan->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scan->st.bitmap.rs_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -658,8 +344,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
-			tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scanDesc->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scanDesc->st.bitmap.rs_iterator);
 
 		/*
 		 * close table scan
@@ -667,17 +353,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -710,18 +390,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -761,13 +436,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -871,12 +539,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -913,17 +578,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index dc6e0184284..934b667ad78 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,12 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator rs_tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *rs_pstate;
+			TBMIterator rs_iterator;
+		}			bitmap;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..b5675b47dcc 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -956,15 +940,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
+				   struct ParallelBitmapHeapState *pstate,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-									   NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys,
+										 key, NULL, flags);
+	result->st.bitmap.rs_pstate = pstate;
+	return result;
 }
 
 /*
@@ -1966,16 +1954,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1972,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8ce4430af04..9c557d2002d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1808,11 +1808,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1820,10 +1816,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1847,18 +1840,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1866,18 +1852,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.45.2

v28-0001-Hard-code-TBMIterateResult-offsets-array-size.patchapplication/octet-stream; name=v28-0001-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From 87b910b9ad2b4e4d6a78f6c10a6ad3cf5a54063d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 16:42:25 -0500
Subject: [PATCH v28 1/4] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.

Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the tidbitmap API user. Doing so also allows us to nest inline
TBMIterateResults in other structs.
---
 src/backend/nodes/tidbitmap.c | 26 +++++++-------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index af6ac64b3fc..3d38cc04cc5 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,9 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1468,8 +1457,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index fedbf69eb53..b2e322508a2 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -55,9 +56,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.45.2

v28-0002-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchapplication/octet-stream; name=v28-0002-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From fbf0772603f00d4230f1382ae5d2d7640d62ed49 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 17:20:28 -0500
Subject: [PATCH v28 2/4] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This will allow multiple TBMIterateResults to exist concurrently,
allowing asynchronous use of the TIDBitmap for prefetching.

tbm_[shared|private]_iterate() now sets blockno to InvalidBlockNumber
when the bitmap is exhausted instead of returning NULL.

BitmapHeapScan callers of tbm_iterate make a TBMIterateResult locally
and pass it in.

Because GIN only needs a single TBMIterateResult, we inline the
matchResult in the GinScanEntry to avoid having to separately manage
memory for the TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 40 ++++++------
 src/backend/access/gin/ginscan.c          |  3 +-
 src/backend/access/heap/heapam_handler.c  | 30 ++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 40 ++++++------
 src/backend/nodes/tidbitmap.c             | 79 +++++++++++------------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 106 insertions(+), 99 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 330805626ee..ddf9976ae12 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,12 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+	entry->matchResult = (TBMIterateResult) {0};
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -824,19 +826,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -847,7 +849,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -860,10 +862,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -877,27 +879,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..5e6dd514cc4 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,8 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult = (TBMIterateResult) {0};
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index a4003cf59e1..bd567760f2d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2124,7 +2124,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
 
@@ -2138,9 +2138,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
+		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
 		/*
@@ -2152,11 +2152,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2164,19 +2164,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2205,7 +2205,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2214,9 +2214,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2266,7 +2266,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..32dea13cb86 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +460,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +481,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +500,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3d38cc04cc5..40d7b9f7505 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -948,20 +946,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -999,11 +998,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1019,16 +1018,16 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1038,10 +1037,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1092,13 +1090,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1108,21 +1106,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1598,13 +1596,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or private bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..478e2a8a377 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index b2e322508a2..f3956d5171e 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -86,8 +86,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -98,7 +98,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.45.2

v28-0004-Remove-table-AM-callback-scan_bitmap_next_block.patchapplication/octet-stream; name=v28-0004-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 3d992c9b46e065f6e3081e8e1167660ac1d460aa Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:35:17 -0500
Subject: [PATCH v28 4/4] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator usage into table-AM specific code (as
part of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer set the current blockno.

BitmapHeapNext() doesn't use the block number for anything, so there is
no reason to have a separte scan_bitmap_next_block() callback.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple().

The heap AM implementation of scan_bitmap_next_block() is now a local
helper in heapam_handler.c.
---
 src/backend/access/heap/heapam_handler.c  | 354 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   2 -
 src/backend/executor/nodeBitmapHeapscan.c |  71 ++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 235 insertions(+), 284 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index eac51f5eb51..f449272a2ea 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,11 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2114,189 +2119,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	*recheck = tbmres->recheck;
-
-	hscan->rs_cblock = tbmres->blockno;
-	hscan->rs_ntuples = tbmres->ntuples;
-
-	block = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (tbmres->ntuples >= 0)
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
-		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
 
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2603,6 +2463,167 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = tbmres->offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * invoke this function again.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2662,7 +2683,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..56378007a81 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 46721e091ab..68499e3aa45 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -139,67 +139,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-			CHECK_FOR_INTERRUPTS();
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
-new_page:
 
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b5675b47dcc..4206a6d0ab1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1943,51 +1923,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1998,7 +1951,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.45.2

#171Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#67)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, Mar 19, 2024 at 4:34 PM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

On 3/18/24 16:55, Tomas Vondra wrote:

...

OK, I've restarted the tests for only 0012 and 0014 patches, and I'll
wait for these to complete - I don't want to be looking for patterns
until we have enough data to smooth this out.

I now have results for 1M and 10M runs on the two builds (0012 and
0014), attached is a chart for relative performance plotting

(0014 timing) / (0012 timing)

for "optimal' runs that would pick bitmapscan on their own. There's
nothing special about the config - I reduced the random_page_cost to
1.5-2.0 to reflect both machines have flash storage, etc.

Overall, the chart is pretty consistent with what I shared on Sunday.
Most of the results are fine (0014 is close to 0012 or faster), but
there's a bunch of cases that are much slower. Interestingly enough,
almost all of them are on the i5 machine, almost none of the xeon. My
guess is this is about the SSD type (SATA vs. NVMe).

Attached if table of ~50 worst regressions (by the metric above), and
it's interesting the worst regressions are with eic=0 and eic=1.

I decided to look at the first case (eic=0), and the timings are quite
stable - there are three runs for each build, with timings close to the
average (see below the table).

Attached is a script that reproduces this on both machines, but the
difference is much more significant on i5 (~5x) compared to xeon (~2x).

I haven't investigated what exactly is happening and why, hopefully the
script will allow you to reproduce this independently. I plan to take a
look, but I don't know when I'll have time for this.

FWIW if the script does not reproduce this on your machines, I might be
able to give you access to the i5 machine. Let me know.

I had this particular email on this thread bookmarked so I could go
back and investigate the regression. The patch set has changed since
these benchmarks were run. And, I honestly no longer remember what
0014 and 0012 were. There are four remaining patches in the set I
posted earlier today in [1]/messages/by-id/CAAKRu_as499kHb9B4B4=+c+4p+OF_Bibd4KEdoqyBgjEaEUdgA@mail.gmail.com. All of them are directly related to
bitmap heap scan using the streaming read interface (i.e. not useful
on their own). Therefore, it is time to investigate if we should merge
streaming read bitmap heap scan.

I ran the query included in the reproducer in this mail a dozen times
on master and with the patches in [1]/messages/by-id/CAAKRu_as499kHb9B4B4=+c+4p+OF_Bibd4KEdoqyBgjEaEUdgA@mail.gmail.com and the average speedup with my
patch is 12%. So, at least for this query, I don't see a regression.

What do you think about rerunning these old benchmarks to see what
they look like now?

- Melanie

[1]: /messages/by-id/CAAKRu_as499kHb9B4B4=+c+4p+OF_Bibd4KEdoqyBgjEaEUdgA@mail.gmail.com

#172Tomas Vondra
tomas@vondra.me
In reply to: Melanie Plageman (#170)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 1/30/25 21:36, Melanie Plageman wrote:

...

Attached v28 is rebased and has a few updates/cleanup. All patches in
the set need review and I need to do some benchmarking of v28-0003.

- Melanie

Hi,

I've been re-running the benchmarks on v28 on Melanie's request. The
tests are still running, but here's what I have so far. The results are
pretty large, I've pushed them here:

https://github.com/tvondra/bitmapscan-tests

I've decommissioned the small "i5" machine and replaced it with a new
ryzen 9900x one. I kept the "old" storage (SSD SATA RAID), but other
than that it's much more capable. That might explain some of the
differences in benchmark results.

So now I have these two machines:

xeon: 2x E5-2699v4
- nvme: WD Ultrastar DC SN640 960GB

ryzen: Ryzen 9 9900X
- data: Samsung SSD 990 PRO 1TB (NVME)
- raid-nvme: 4x Samsung SSD 990 PRO 1TB (RAID0, NVME)
- raid-sata: 4x Intel DC S3700 (RAID0)

See the PDFs for the usual "colored pivot table" visualization, or the
raw CSV files. The pivot table shows results for various combinations of
parameters, the columns are for different patches and values of the
effective_io_concurrency GUC.

The columns on the right compare results to the previous patch, i.e. it
shows how the query duration changes after applying the patch.

I didn't have time to do a particularly detailed analysis yet, or try to
investigate the regressions. But some basic observations.

1) xeon
-------

This machine only has a single type of storage (NVMe SSD), and the
results looks really good. Most of the chart is "green" i.e. the patch
makes queries faster, and the regressions are random, for the very short
queries, and it seems random / no pattern. Which means this is likely
random noise, nothing to worry about.

There's one minor issue that I failed to test the 0004 patch due to a
bug in the script, so the PDF only compares master, 0001, 0002 and 0003.
But that should not matter too much, because 0003 is the main change.

There are "gaps" for tests on the 100M data set that are still running,
but I think I'll abort those, it'd take many days to complete and it
doesn't seem we'd learn very much.

2) ryzen
--------

This "new" machine has multiple types of storage. The cached results (be
it in shared buffers or in page cache) are not very interesting. 0003
helps a bit (~15%), but other than that it's just random noise.

The "uncached" results starting on page 23 are much more interesting. In
general 0001, 0002 and 0004 have little impact, it seems just random
noise. So in the rest I'll focus on 0003.

For the single nvme device (device: data), it seems mostly fine. It's
green, even though there are a couple "localized regressions" for eic=0.
I haven't looked into those yet.

For the nvme RAID (device: raid-nvme), it's looks almost exactly the
same, except that with parallel query (page 27) there's a clear area of
regression with eic=1 (look for "column" of red cells). That's a bit
unfortunate, because eic=1 is the default value.

For the SATA SSD RAID (device: raid-sata), it's similar - a couple
regressions for eic=0, just like for NVMe. But then there's also a
couple regressions for higher eic values, usually for queries with
selective conditions.

Overall, I think this looks good. It might be a good idea to look into
some of the regressions, but ultimately the read stream relies on a
heuristic to determine how far ahead to read etc. And each heuristics
has counter examples. So the presence of regressions is guaranteed, it
should not be a reason to reject a patch on its own.

There's one more thing to consider when looking at those results - the
script *forces* the use of bitmap index scan, even if the planner would
not pick it on it's own. The ryzen-filtered.pdf shows only results when
that would be the case (i.e. the optimizer would pick bitmapscan). Most
of the regressions are gone, simply because it'd do index scan, seqscan.

Of course, this is not perfect - planning mistakes happen, and it would
be nice to not regress more than before. The plan choice depends also on
the cost parameters, and maybe with different values we'd pick bitmap
scans more often.

Anyway, the results look sensible. It might be good to investigate some
of the regressions, and I'll try doing that if I find the time. But I
don't think that's necessarily a blocker - every patch of this type will
have a hardware where the heuristics doesn't quite do the right thing by
default. Which is why we have GUCs to tune it if appropriate.

regards

--
Tomas Vondra

#173Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#172)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Feb 9, 2025 at 9:27 AM Tomas Vondra <tomas@vondra.me> wrote:

2) ryzen
--------

This "new" machine has multiple types of storage. The cached results (be
it in shared buffers or in page cache) are not very interesting. 0003
helps a bit (~15%), but other than that it's just random noise.

The "uncached" results starting on page 23 are much more interesting. In
general 0001, 0002 and 0004 have little impact, it seems just random
noise. So in the rest I'll focus on 0003.

For the single nvme device (device: data), it seems mostly fine. It's
green, even though there are a couple "localized regressions" for eic=0.
I haven't looked into those yet.

For the nvme RAID (device: raid-nvme), it's looks almost exactly the
same, except that with parallel query (page 27) there's a clear area of
regression with eic=1 (look for "column" of red cells). That's a bit
unfortunate, because eic=1 is the default value.

It'll be hard to look into all of these, so I think I'll focus on
trying to reproduce something with eic=1 that I can reproduce on my
machine. So far, I can reproduce a regression with the following and
the data file attached.

# initdb and get set up with shared_buffers 1GB
psql -c "create table bitmap_scan_test (a bigint, b bigint, c text)
with (fillfactor = 25)"
psql -c "copy bitmap_scan_test from '/tmp/bitmap_scan_test.data'"
psql -c "create index on bitmap_scan_test (a)"
psql -c "vacuum analyze"
psql -c "checkpoint"

pg_ctl stop
echo 3 | sudo tee /proc/sys/vm/drop_caches
pg_ctl start
psql -c "SET max_parallel_workers_per_gather = 4;" \
-c "SET effective_io_concurrency = 1;" \
-c "SET parallel_setup_cost = 0;" \
-c "SET parallel_tuple_cost = 0;" \
-c "SET enable_seqscan = off;" \
-c "SET enable_indexscan = off;" \
-c "SET work_mem = 65536;"

psql -c "EXPLAIN SELECT * FROM bitmap_scan_test WHERE (a BETWEEN -33
AND 10015) OFFSET 1000000;"
psql -c "SELECT * FROM bitmap_scan_test WHERE (a BETWEEN -33 AND
10015) OFFSET 1000000;"

It's not a huge regression and planner doesn't naturally pick parallel
bitmap heap scan for this, but I don't have a SATA drive right now, so
I focused on something I could reproduce.

One thing I noticed when I was playing around with the script is that
depending on the values chosen by random(), there were differences in
timing. From your script, it looks like the $from and $to won't be the
same for master and the patch each time (they are set in the inner
most nesting level, below where $build is set). Am I understanding
correctly?

Anyway, the results look sensible. It might be good to investigate some
of the regressions, and I'll try doing that if I find the time. But I
don't think that's necessarily a blocker - every patch of this type will
have a hardware where the heuristics doesn't quite do the right thing by
default. Which is why we have GUCs to tune it if appropriate.

Yea, I definitely won't be able to look into all of the regressions.
So, I guess we have to ask if we are willing to make the tradeoff.

- Melanie

#174Tomas Vondra
tomas@vondra.me
In reply to: Melanie Plageman (#173)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/10/25 19:02, Melanie Plageman wrote:

On Sun, Feb 9, 2025 at 9:27 AM Tomas Vondra <tomas@vondra.me> wrote:

2) ryzen
--------

This "new" machine has multiple types of storage. The cached results (be
it in shared buffers or in page cache) are not very interesting. 0003
helps a bit (~15%), but other than that it's just random noise.

The "uncached" results starting on page 23 are much more interesting. In
general 0001, 0002 and 0004 have little impact, it seems just random
noise. So in the rest I'll focus on 0003.

For the single nvme device (device: data), it seems mostly fine. It's
green, even though there are a couple "localized regressions" for eic=0.
I haven't looked into those yet.

For the nvme RAID (device: raid-nvme), it's looks almost exactly the
same, except that with parallel query (page 27) there's a clear area of
regression with eic=1 (look for "column" of red cells). That's a bit
unfortunate, because eic=1 is the default value.

It'll be hard to look into all of these, so I think I'll focus on
trying to reproduce something with eic=1 that I can reproduce on my
machine. So far, I can reproduce a regression with the following and
the data file attached.

Yes, that approach makes perfect sense. I don't think anyone can
investigate all the regressions, it's enough to investigate one specimen
for each of the main "patterns".

# initdb and get set up with shared_buffers 1GB
psql -c "create table bitmap_scan_test (a bigint, b bigint, c text)
with (fillfactor = 25)"
psql -c "copy bitmap_scan_test from '/tmp/bitmap_scan_test.data'"
psql -c "create index on bitmap_scan_test (a)"
psql -c "vacuum analyze"
psql -c "checkpoint"

pg_ctl stop
echo 3 | sudo tee /proc/sys/vm/drop_caches
pg_ctl start
psql -c "SET max_parallel_workers_per_gather = 4;" \
-c "SET effective_io_concurrency = 1;" \
-c "SET parallel_setup_cost = 0;" \
-c "SET parallel_tuple_cost = 0;" \
-c "SET enable_seqscan = off;" \
-c "SET enable_indexscan = off;" \
-c "SET work_mem = 65536;"

psql -c "EXPLAIN SELECT * FROM bitmap_scan_test WHERE (a BETWEEN -33
AND 10015) OFFSET 1000000;"
psql -c "SELECT * FROM bitmap_scan_test WHERE (a BETWEEN -33 AND
10015) OFFSET 1000000;"

It's not a huge regression and planner doesn't naturally pick parallel
bitmap heap scan for this, but I don't have a SATA drive right now, so
I focused on something I could reproduce.

One thing I noticed when I was playing around with the script is that
depending on the values chosen by random(), there were differences in
timing. From your script, it looks like the $from and $to won't be the
same for master and the patch each time (they are set in the inner
most nesting level, below where $build is set). Am I understanding
correctly?

Yes. The values for the WHERE conditions are generated randomly, and the
idea is that it evens out for multiple runs. Maybe not with only 3 runs
per query, but it should be good enough to show patterns (e.g. when the
runs with eic=1 show regression).

Anyway, the results look sensible. It might be good to investigate some
of the regressions, and I'll try doing that if I find the time. But I
don't think that's necessarily a blocker - every patch of this type will
have a hardware where the heuristics doesn't quite do the right thing by
default. Which is why we have GUCs to tune it if appropriate.

Yea, I definitely won't be able to look into all of the regressions.
So, I guess we have to ask if we are willing to make the tradeoff.

I'm at peace with that.

Certainly for the "localized" regressions, and cases when bitmapheapscan
would not be picked. The eic=1 case makes me a bit more nervous, because
it's default and affects NVMe storage. Would be good to know why is
that, or perhaps consider bumping up eic default. Not sure.

regards

--
Tomas Vondra

#175Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#173)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Feb 10, 2025 at 1:02 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

It'll be hard to look into all of these, so I think I'll focus on
trying to reproduce something with eic=1 that I can reproduce on my
machine. So far, I can reproduce a regression with the following and
the data file attached.

# initdb and get set up with shared_buffers 1GB
psql -c "create table bitmap_scan_test (a bigint, b bigint, c text)
with (fillfactor = 25)"
psql -c "copy bitmap_scan_test from '/tmp/bitmap_scan_test.data'"
psql -c "create index on bitmap_scan_test (a)"
psql -c "vacuum analyze"
psql -c "checkpoint"

pg_ctl stop
echo 3 | sudo tee /proc/sys/vm/drop_caches
pg_ctl start
psql -c "SET max_parallel_workers_per_gather = 4;" \
-c "SET effective_io_concurrency = 1;" \
-c "SET parallel_setup_cost = 0;" \
-c "SET parallel_tuple_cost = 0;" \
-c "SET enable_seqscan = off;" \
-c "SET enable_indexscan = off;" \
-c "SET work_mem = 65536;"

psql -c "EXPLAIN SELECT * FROM bitmap_scan_test WHERE (a BETWEEN -33
AND 10015) OFFSET 1000000;"
psql -c "SELECT * FROM bitmap_scan_test WHERE (a BETWEEN -33 AND
10015) OFFSET 1000000;"

I think I figured out why there is a regression. On master, parallel
bitmap heap scans seem to end up cheating effective_io_concurrency.

What you expect to see with effective_io_concurrency == 1 is a single
pread followed by a single fadvise. We can prefetch up to one block
before reading the next block. This is what you see on both the patch
and master with a serial bitmap heap scan. This is also what you see
with the patch if you strace a participating parallel bitmap heap scan
process. On master, however, you do not see this 1-1 interleaving for
parallel bitmap heap scan.

On master we typically issue many fadvises in a row followed by a few
preads in a row.
For example:
fadvise64
fadvise64
fadvise64
fadvise64
pread64
fadvise64
fadvise64
pread64
pread64
fadvise64

On master, while executing this query, the leader did more than 2000
runs of > 1 fadvise or pread in a row. With the patch, there are
essentially none.

On master, parallel bitmap heap scans' prefetching behavior is
controlled by some shared pstate members, prefetch_target and
prefetch_pages. Prefetching is supposed to be allowed only up to
prefetch_target -- which is capped at effective_io_concurrency.
Incrementing and decrementing these variables is not based on whether
or not the process actually did a read or a prefetch -- only on the
values of those shared memory variables. I think what is happening
due to quirks of CPU scheduling is that some of the processes are
actually issuing more consecutive reads and prefetches and another
process is incrementing and decrementing those values in a way that
makes this possible.

This effectively increases effective_io_concurrency for parallel
bitmap heap scans on master. The patch can't really compete because it
is interleaving every read with an fadvise -- preventing readahead.

I don't really know what to do about this. The behavior of master
parallel bitmap heap scan can be emulated with the patch by increasing
effective_io_concurrency. But, IIRC we didn't want to do that for some
reason?
Not only does effective_io_concurrency == 1 negatively affect read
ahead, but it also prevents read combining regardless of the
io_combine_limit.

- Melanie

#176Robert Haas
robertmhaas@gmail.com
In reply to: Tomas Vondra (#174)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Feb 10, 2025 at 1:11 PM Tomas Vondra <tomas@vondra.me> wrote:

Certainly for the "localized" regressions, and cases when bitmapheapscan
would not be picked. The eic=1 case makes me a bit more nervous, because
it's default and affects NVMe storage. Would be good to know why is
that, or perhaps consider bumping up eic default. Not sure.

I'm relatively upset by the fact that effective_io_concurrency is
measured in units that are, AFAIUI, completely stupid. The original
idea was that you would set it to the number of spindles you have. But
from what I have heard, that didn't actually work: you needed to set
it to a significantly higher number. But in 2025, you probably don't
even have spindles any more, because you're probably on SSD or some
other modern storage medium rather than a rotating hard drive. And if
you do have spindles, do you know how many you have? Is that even a
meaningful concept?

I am not saying that it's this patch's job to replace
effective_io_concurrency with something better. I think adopting the
streaming read interface is pretty important, and if it works out that
we should also change the default effective_io_concurrency from 1 to 2
or 17 or 42715 in the same release, fine. But I think that in the
slightly longer term, it would be a really good idea for someone to
propose a more sensible model. It's hard to think of a clearer case of
a parameter being rendered meaningless by the march of technology. The
closest analogue that comes to mind is our sorting implementation used
to have a hard coded number of tape drives, when the underlying
implementation was a bunch of files all on the same filesystem, but
that wasn't a user-settable parameter.

--
Robert Haas
EDB: http://www.enterprisedb.com

#177Melanie Plageman
melanieplageman@gmail.com
In reply to: Robert Haas (#176)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Feb 10, 2025 at 4:24 PM Robert Haas <robertmhaas@gmail.com> wrote:

On Mon, Feb 10, 2025 at 1:11 PM Tomas Vondra <tomas@vondra.me> wrote:

Certainly for the "localized" regressions, and cases when bitmapheapscan
would not be picked. The eic=1 case makes me a bit more nervous, because
it's default and affects NVMe storage. Would be good to know why is
that, or perhaps consider bumping up eic default. Not sure.

I'm relatively upset by the fact that effective_io_concurrency is
measured in units that are, AFAIUI, completely stupid. The original
idea was that you would set it to the number of spindles you have. But
from what I have heard, that didn't actually work: you needed to set
it to a significantly higher number. But in 2025, you probably don't
even have spindles any more, because you're probably on SSD or some
other modern storage medium rather than a rotating hard drive. And if
you do have spindles, do you know how many you have? Is that even a
meaningful concept?

I had taken to thinking of it as "queue depth". But I think that's not
really accurate. Do you know why we set it to 1 as the default? I
thought it was because the default should be just prefetch one block
ahead. But if it was meant to be spindles, was it that most people had
one spindle (I don't really know what a spindle is)?

I am not saying that it's this patch's job to replace
effective_io_concurrency with something better. I think adopting the
streaming read interface is pretty important, and if it works out that
we should also change the default effective_io_concurrency from 1 to 2
or 17 or 42715 in the same release, fine.

Yes, I think we should probably change it to be higher.

However, this exercise today made me realize that it is going to be
pretty difficult to completely emulate the IO behavior of parallel
bitmap heap scans on master with this patch. The way the different
processes and the two iterators happened to interact had all sorts of
random side effects. (See, for example, this [1]/messages/by-id/20240315211449.en2jcmdqxv5o6tlz@alap3.anarazel.de bug we discovered and
didn't end up fixing because it would be hard and we figured we would
replace this all with the read stream API).

But I think that in the
slightly longer term, it would be a really good idea for someone to
propose a more sensible model. It's hard to think of a clearer case of
a parameter being rendered meaningless by the march of technology. The
closest analogue that comes to mind is our sorting implementation used
to have a hard coded number of tape drives, when the underlying
implementation was a bunch of files all on the same filesystem, but
that wasn't a user-settable parameter.

I imagine if I said that we should start calling it prefetch_distance,
you would say that no one would know what to configure it to and that
would be just as bad.

- Melanie

[1]: /messages/by-id/20240315211449.en2jcmdqxv5o6tlz@alap3.anarazel.de

#178Andres Freund
andres@anarazel.de
In reply to: Robert Haas (#176)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-02-10 16:24:25 -0500, Robert Haas wrote:

On Mon, Feb 10, 2025 at 1:11 PM Tomas Vondra <tomas@vondra.me> wrote:

Certainly for the "localized" regressions, and cases when bitmapheapscan
would not be picked. The eic=1 case makes me a bit more nervous, because
it's default and affects NVMe storage. Would be good to know why is
that, or perhaps consider bumping up eic default. Not sure.

I'm relatively upset by the fact that effective_io_concurrency is
measured in units that are, AFAIUI, completely stupid. The original
idea was that you would set it to the number of spindles you have. But
from what I have heard, that didn't actually work: you needed to set
it to a significantly higher number.

Which isn't too surprising. I think there are a few main reasons #spindles
was way too low:

1) Decent interfaces to rotating media benefit very substantially from having
multiple requests in flight, for each spindle. The disk can reorder the
actual disk access so they each can be executed without needing on average
half a rotation for each request. Similar reordering can also happen on
the OS level, even if not quite to the same degree of benefit.

2) Even if each spindle could only execute one IO request, you still want to
start those requests substantially earlier than allowed by
effective_io_concurrency=#spindles, to allow for the IOs to complete. With
e.g. bitmap heap scans, there often are sequences of blocks that can be
read together in one IO.

3) A single spindle commonly had multiple platters and a disk could read from
multiple platters within a single rotation.

However, I'm not so sure that the unit of effective_io_concurrency is really
the main issue. It IMO makes sense to limit the max number of requests one
scan can trigger, to prevent one scan from completely swamping the IO request
queue for the next several seconds (trivially possible without a limit on
smaller cloud storage disks with low iops).

It's plausible that we would want to separately control the "distance" from
the currently "consumed" position position and the
maximum-io-requests-in-flight. But I think we might be able to come up with a
tuning algorithm that can tune the distance based on the observed latency and
"consumption" speed.

I think what we eventually should get rid of is the "effective_" prefix. My
understanding is that basically there to denote that we don't really have an
idea what concurrency is achieved, as posix_fadvise() neither tells us if IO
was necessary in the first place, nor whether multiple blocks could be read in
one IO, nor when IO has completed.

The read_stream implementation already has redefined effective_io_concurrency
to only count one IO for a multi-block read.

Of course that doesn't mean we shouldn't change the default (we very clearly
should) or the documentation for the GUC.

Greetings,

Andres Freund

#179Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#175)
4 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Feb 10, 2025 at 4:22 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I don't really know what to do about this. The behavior of master
parallel bitmap heap scan can be emulated with the patch by increasing
effective_io_concurrency. But, IIRC we didn't want to do that for some
reason?
Not only does effective_io_concurrency == 1 negatively affect read
ahead, but it also prevents read combining regardless of the
io_combine_limit.

Would a sensible default be something like 4?

I did some self-review on the patches and cleaned up the commit
messages etc. Attached is v29.

- Melanie

Attachments:

v29-0002-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v29-0002-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From f98a2255fdb1441ac6b4a6c8df42eced771c5125 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 17:20:28 -0500
Subject: [PATCH v29 2/4] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This allows tidbitmap API users to manage multiple TBMIterateResults per
scan, instead of only one per iterator. This is required for
asynchronous I/O to use the TIDBitmap -- as there may be multiple I/Os
in flight at once.

Because GIN only needs a single TBMIterateResult, we inline the
matchResult in the GinScanEntry to avoid having to separately manage
memory for the TBMIterateResult.
---
 src/backend/access/gin/ginget.c           | 39 +++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 30 ++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 40 ++++++------
 src/backend/nodes/tidbitmap.c             | 79 +++++++++++------------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 104 insertions(+), 99 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 63dd1f3679f..ac1b749ed98 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,11 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -824,19 +825,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -847,7 +848,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -860,10 +861,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -877,27 +878,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..625140fdf25 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c0bec014154..39d10849c65 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
 
@@ -2140,9 +2140,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
+		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
 		/*
@@ -2154,11 +2154,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2166,19 +2166,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2207,7 +2207,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2216,9 +2216,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = tbmres.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2268,7 +2268,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..32dea13cb86 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +460,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +481,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +500,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index c573086453e..b7e4b4d9e1c 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -948,20 +946,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -999,11 +998,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1019,16 +1018,16 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1038,10 +1037,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1092,13 +1090,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1108,21 +1106,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1598,13 +1596,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or private bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..478e2a8a377 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 661a52b4fe3..bc4adca3809 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -86,8 +86,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -98,7 +98,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v29-0001-Hard-code-TBMIterateResult-offsets-array-size.patchtext/x-patch; charset=US-ASCII; name=v29-0001-Hard-code-TBMIterateResult-offsets-array-size.patchDownload
From 084ad01eb4456385ca193a3a3a0feb12c9d1f7bf Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 16:42:25 -0500
Subject: [PATCH v29 1/4] Hard-code TBMIterateResult offsets array size

TIDBitmap's TBMIterateResult had a flexible sized array of tuple offsets
but the API always allocated MaxHeapTuplesPerPage OffsetNumbers.

Creating a fixed-size aray of size MaxHeapTuplesPerPage is more clear
for the tidbitmap API user. Doing so also allows us to nest inline
TBMIterateResults in other structs.
---
 src/backend/nodes/tidbitmap.c | 26 +++++++-------------------
 src/include/nodes/tidbitmap.h | 12 ++++++++++--
 2 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 66b3c387d53..c573086453e 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,9 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -1468,8 +1457,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index a6ffeac90be..661a52b4fe3 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -55,9 +56,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
-- 
2.34.1

v29-0004-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v29-0004-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 20f02a1780ee8a135e360c455651372b92e926d2 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:35:17 -0500
Subject: [PATCH v29 4/4] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator into table-AM specific code (as part
of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer returns the current block number.
Since scan_bitmap_next_block() isn't returning any relevant information
to bitmap table scan code, it makes more sense to get rid of it.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple(),
and the heap AM implementation of scan_bitmap_next_block() is a local
helper in heapam_handler.c.
---
 src/backend/access/heap/heapam_handler.c  | 354 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   2 -
 src/backend/executor/nodeBitmapHeapscan.c |  71 ++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 235 insertions(+), 284 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index dcebac66534..f6387f60e3e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,11 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,189 +2121,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	*recheck = tbmres->recheck;
-
-	hscan->rs_cblock = tbmres->blockno;
-	hscan->rs_ntuples = tbmres->ntuples;
-
-	block = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (tbmres->ntuples >= 0)
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
-		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
 
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2605,6 +2465,167 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = tbmres->offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * invoke this function again.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2664,7 +2685,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..56378007a81 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 46721e091ab..68499e3aa45 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -139,67 +139,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-			CHECK_FOR_INTERRUPTS();
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
-new_page:
 
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b5675b47dcc..4206a6d0ab1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1943,51 +1923,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1998,7 +1951,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

v29-0003-BitmapHeapScan-uses-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v29-0003-BitmapHeapScan-uses-read-stream-API.patchDownload
From 71efb544d59ce8a11b71b447d96b6d8a9b4bbcb5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:00:12 -0500
Subject: [PATCH v29 3/4] BitmapHeapScan uses read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.
---
 src/backend/access/heap/heapam.c          |  70 +++++
 src/backend/access/heap/heapam_handler.c  |  86 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 355 +---------------------
 src/include/access/relscan.h              |   8 +-
 src/include/access/tableam.h              |  33 +-
 src/include/nodes/execnodes.h             |  23 +-
 6 files changed, 130 insertions(+), 445 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index ea0a12b39af..45f419f849f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,62 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&sscan->st.bitmap.rs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			bscan->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1123,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1203,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1247,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 39d10849c65..dcebac66534 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2117,76 +2117,66 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
+	tbmres = per_buffer_data;
 
-		bscan->rs_empty_tuples_pending += tbmres.ntuples;
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	*recheck = tbmres->recheck;
 
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2207,7 +2197,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2216,9 +2206,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres.offsets[curslot];
+			OffsetNumber offnum = tbmres->offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
@@ -2268,7 +2258,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 32dea13cb86..46721e091ab 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -149,16 +120,16 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		node->ss.ss_currentScanDesc =
 			table_beginscan_bm(node->ss.ss_currentRelation,
 							   node->ss.ps.state->es_snapshot,
+							   pstate,
 							   0,
 							   NULL,
 							   need_tuples);
 	}
 
-	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bitmap.rs_iterator = tbmiterator;
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +143,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -201,40 +168,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Continuing in previously obtained page.
 			 */
-
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -254,34 +189,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/* OK to return this tuple */
 			return slot;
 		}
-
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,226 +223,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -574,31 +272,19 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scan->st.rs_tbmiterator))
-			tbm_end_iterate(&scan->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scan->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scan->st.bitmap.rs_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -658,8 +344,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
-			tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scanDesc->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scanDesc->st.bitmap.rs_iterator);
 
 		/*
 		 * close table scan
@@ -667,17 +353,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -710,18 +390,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -761,13 +436,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -871,12 +539,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -913,17 +578,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index dc6e0184284..934b667ad78 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,12 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator rs_tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *rs_pstate;
+			TBMIterator rs_iterator;
+		}			bitmap;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..b5675b47dcc 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -956,15 +940,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
+				   struct ParallelBitmapHeapState *pstate,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-									   NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys,
+										 key, NULL, flags);
+	result->st.bitmap.rs_pstate = pstate;
+	return result;
 }
 
 /*
@@ -1966,16 +1954,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1972,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e2d1dc1e067..c08fa33ad83 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1822,11 +1822,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1834,10 +1830,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1861,18 +1854,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1880,18 +1866,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

#180Robert Haas
robertmhaas@gmail.com
In reply to: Melanie Plageman (#177)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Feb 10, 2025 at 4:41 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I had taken to thinking of it as "queue depth". But I think that's not
really accurate. Do you know why we set it to 1 as the default? I
thought it was because the default should be just prefetch one block
ahead. But if it was meant to be spindles, was it that most people had
one spindle (I don't really know what a spindle is)?

AFAIK, we're imagining that people are running PostgreSQL on a hard
drive like the one my desktop machine had when I was in college, which
indeed only had one spindle. There were one or possibly several
magnetic platters rotating around a single point. But today, nobody
has that, certainly not on a production machine. For instance if you
are using RAID or LVM you have several drives hooked up together, so
that would be multiple spindles even if all of them were HDDs, but
probably they are all SSDs which don't have spindles anyway. If you
are on a virtual machine you have a slice of the underlying machine's
I/O and whatever that is it's probably something more complicated than
a single spindle.

To be fair, I guess the concept of effective_io_concurrency isn't
completely meaningless if you think about it as the number of
simultaneous I/O requests that can be in flight at a time. But I still
think it's true that it's hard to make any reasonable guess as to how
you should set this value to get good performance. Maybe people who
work as consultants and configure lots of systems have good intuition
here, but anybody else is probably either not going to know about this
parameter or flail around trying to figure out how to set it.

It might be interesting to try some experiments on a real small VM
from some cloud provider and see what value is optimal there these
days. Then we could set the default to that value or perhaps somewhat
more.

--
Robert Haas
EDB: http://www.enterprisedb.com

#181Tomas Vondra
tomas@vondra.me
In reply to: Robert Haas (#180)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/12/25 20:08, Robert Haas wrote:

On Mon, Feb 10, 2025 at 4:41 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I had taken to thinking of it as "queue depth". But I think that's not
really accurate. Do you know why we set it to 1 as the default? I
thought it was because the default should be just prefetch one block
ahead. But if it was meant to be spindles, was it that most people had
one spindle (I don't really know what a spindle is)?

AFAIK, we're imagining that people are running PostgreSQL on a hard
drive like the one my desktop machine had when I was in college, which
indeed only had one spindle. There were one or possibly several
magnetic platters rotating around a single point. But today, nobody
has that, certainly not on a production machine. For instance if you
are using RAID or LVM you have several drives hooked up together, so
that would be multiple spindles even if all of them were HDDs, but
probably they are all SSDs which don't have spindles anyway. If you
are on a virtual machine you have a slice of the underlying machine's
I/O and whatever that is it's probably something more complicated than
a single spindle.

I think we've abandoned the idea that effective_io_concurrency has
anything to do with the number of spindles - it was always a bit wrong
because even spinning rust had TCQ/NCQ (i.e. ability to optimize head
movement for a queue of requests). But it completely lost the meaning
with flash storage. And in PG13 we even stopped "recalculating" the
prefetch distance, and use raw effective_io_concurrency.

To be fair, I guess the concept of effective_io_concurrency isn't
completely meaningless if you think about it as the number of
simultaneous I/O requests that can be in flight at a time. But I still
think it's true that it's hard to make any reasonable guess as to how
you should set this value to get good performance. Maybe people who
work as consultants and configure lots of systems have good intuition
here, but anybody else is probably either not going to know about this
parameter or flail around trying to figure out how to set it.

Yes, the "queue depth" interpretation seems to be much more accurate
than "number of spindles".

It might be interesting to try some experiments on a real small VM
from some cloud provider and see what value is optimal there these
days. Then we could set the default to that value or perhaps somewhat
more.

AFAICS the "1" value is simply one of the many "defensive" defaults in
our sample config. It's much more likely to help than cause harm, even
on smaller/older systems, but for many systems a higher value would be
more appropriate. There's usually a huge initial benefit (say, going to
16 or 32), and then the benefits diminish fairly quickly.

regards

--
Tomas Vondra

#182Robert Haas
robertmhaas@gmail.com
In reply to: Tomas Vondra (#181)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Feb 12, 2025 at 3:07 PM Tomas Vondra <tomas@vondra.me> wrote:

AFAICS the "1" value is simply one of the many "defensive" defaults in
our sample config. It's much more likely to help than cause harm, even
on smaller/older systems, but for many systems a higher value would be
more appropriate. There's usually a huge initial benefit (say, going to
16 or 32), and then the benefits diminish fairly quickly.

I'm happy to see us change the value to something that is likely to be
good for most people. I think it's OK if people on very tiny systems
need to change a few defaults for optimum performance. We should keep
in mind that people do sometimes run PostgreSQL on fairly small VMs
and not go crazy with it, but there's no reason to pretend that the
typical database runs on a Raspberry Pi.

--
Robert Haas
EDB: http://www.enterprisedb.com

#183Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#172)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Feb 9, 2025 at 9:27 AM Tomas Vondra <tomas@vondra.me> wrote:

For the nvme RAID (device: raid-nvme), it's looks almost exactly the
same, except that with parallel query (page 27) there's a clear area of
regression with eic=1 (look for "column" of red cells). That's a bit
unfortunate, because eic=1 is the default value.

So, I feel pretty confident after even more analysis today with Thomas
Munro that all of the parallel cases with effective_io_concurrency ==
1 are because master cheats effective_io_concurrency. Therefore, I'm
not too worried about those for now. We probably will have to increase
effective_io_concurrency before merging this patch, though.

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

For the SATA SSD RAID (device: raid-sata), it's similar - a couple
regressions for eic=0, just like for NVMe. But then there's also a
couple regressions for higher eic values, usually for queries with
selective conditions.

I started trying to reproduce the regressions you saw on your SATA
devices for higher eic values. I was focusing just on serial bitmap
heap scan -- since that doesn't have the problems mentioned above. I
don't have a SATA drive, but I used dmsetup to add a 10ms delay to my
nvme drive. Unfortunately, that did the opposite of reproduce the
issue. With dm delay 10ms, the patch is 5 times faster than master.

- Melanie

#184Thomas Munro
thomas.munro@gmail.com
In reply to: Melanie Plageman (#183)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 13, 2025 at 1:40 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Sun, Feb 9, 2025 at 9:27 AM Tomas Vondra <tomas@vondra.me> wrote:

For the nvme RAID (device: raid-nvme), it's looks almost exactly the
same, except that with parallel query (page 27) there's a clear area of
regression with eic=1 (look for "column" of red cells). That's a bit
unfortunate, because eic=1 is the default value.

So, I feel pretty confident after even more analysis today with Thomas
Munro that all of the parallel cases with effective_io_concurrency ==
1 are because master cheats effective_io_concurrency. Therefore, I'm
not too worried about those for now. We probably will have to increase
effective_io_concurrency before merging this patch, though.

Yeah. Not only did we see it issuing up to 20 or so unauthorised
overlapping POSIX_FADV_WILLNEED calls, but in the case we studied they
didn't really do anything at all because it was *postfetching* (!), ie
issuing advice for blocks it had already read. The I/O was sequential
(reading all or most blocks in order), so the misdirected advice at
least kept out of the kernel's way, and it did some really effective
readahead. Meanwhile the stream version played by the rules and
respected eic=1, staying only one block ahead. We know that advice for
sequential blocks blocks readahead, so that seems to explain the red
for that parameter/test permutation. (Hypothesis based on some
quick reading: I guess kernel pages faulted in that way don't get
marked with the internal "readahead was here" flag, which would
normally cause the following pread() to trigger more asynchronous
readahead with ever larger physical size). But that code
in master is also *trying* to do exactly what we're doing, it's just
failing because of some combination of bugs in the parallel scan code
(?). It would be absurd to call it the winner: we're setting out
with the same goal, but for that particular set of parameters and test
setup, apparently two (?) bugs make a right. Melanie mentioned that
some other losing cases also involved unauthorised amounts of
overlapping advice, except there it was random and beneficial and the
iterators didn't get out of sync with each other, so again it beat us
in a few red patches, seemingly with a different accidental behaviour.
Meanwhile we obediently trundled along with just 1 concurrent I/O or
whatever, and lost.

On top of that, read_stream.c is also *trying* to avoid issuing advice
for access patterns that look sequential, and *trying* to do I/O
combining, which all works OK in serial BHS, but it breaks down in
parallel because:

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

+    /*
+     * The maximum number of tuples per page is not large (typically 256 with
+     * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+     * the per-page bitmaps variable size.  We just legislate that the size is
+     * this:
+     */
+    OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;

Seems to be 291? So sizeof(TBMIterateResult) must be somewhere
around 588 bytes? There's one of those for every buffer, and we'll
support queues of up to effective_io_concurrency (1-1000) *
io_combine_limit (1-128?), which would require ~75MB of
per-buffer-data with maximum settings That's a lot of memory to have
to touch as you whizz around the circular queue even when you don't
really need it. With more typical numbers like 10 * 32 it's ~90kB,
which I guess is OK. I wonder if it would be worth trying to put a
small object in there instead that could be expanded to the results
later, cf f6bef362 for TIDStore, but I'm not sure if it's a blocker,
just an observation.

#185Tomas Vondra
tomas@vondra.me
In reply to: Melanie Plageman (#183)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/13/25 01:40, Melanie Plageman wrote:

On Sun, Feb 9, 2025 at 9:27 AM Tomas Vondra <tomas@vondra.me> wrote:

For the nvme RAID (device: raid-nvme), it's looks almost exactly the
same, except that with parallel query (page 27) there's a clear area of
regression with eic=1 (look for "column" of red cells). That's a bit
unfortunate, because eic=1 is the default value.

So, I feel pretty confident after even more analysis today with Thomas
Munro that all of the parallel cases with effective_io_concurrency ==
1 are because master cheats effective_io_concurrency. Therefore, I'm
not too worried about those for now. We probably will have to increase
effective_io_concurrency before merging this patch, though.

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

Agreed. If this is due to master doing something wrong (and either
prefetching more, or failing to prefetch), that's not the fault of this
patch. People might perceive this as a regression, but increasing the
default eic value would fix that.

BTW I recall we ran into issues with prefetching and parallel workers
about a year ago [1]/messages/by-id/20240315211449.en2jcmdqxv5o6tlz@alap3.anarazel.de. Is this the same issue, or something new?

[1]: /messages/by-id/20240315211449.en2jcmdqxv5o6tlz@alap3.anarazel.de
/messages/by-id/20240315211449.en2jcmdqxv5o6tlz@alap3.anarazel.de

For the SATA SSD RAID (device: raid-sata), it's similar - a couple
regressions for eic=0, just like for NVMe. But then there's also a
couple regressions for higher eic values, usually for queries with
selective conditions.

I started trying to reproduce the regressions you saw on your SATA
devices for higher eic values. I was focusing just on serial bitmap
heap scan -- since that doesn't have the problems mentioned above. I
don't have a SATA drive, but I used dmsetup to add a 10ms delay to my
nvme drive. Unfortunately, that did the opposite of reproduce the
issue. With dm delay 10ms, the patch is 5 times faster than master.

I'm not quite sure at which point does dm-setup add the delay. Does it
affect the fadvise call too, or just the I/O if the page is not already
in page cache?

regards

--
Tomas Vondra

#186Tomas Vondra
tomas@vondra.me
In reply to: Thomas Munro (#184)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/13/25 05:15, Thomas Munro wrote:

On Thu, Feb 13, 2025 at 1:40 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Sun, Feb 9, 2025 at 9:27 AM Tomas Vondra <tomas@vondra.me> wrote:

For the nvme RAID (device: raid-nvme), it's looks almost exactly the
same, except that with parallel query (page 27) there's a clear area of
regression with eic=1 (look for "column" of red cells). That's a bit
unfortunate, because eic=1 is the default value.

So, I feel pretty confident after even more analysis today with Thomas
Munro that all of the parallel cases with effective_io_concurrency ==
1 are because master cheats effective_io_concurrency. Therefore, I'm
not too worried about those for now. We probably will have to increase
effective_io_concurrency before merging this patch, though.

Yeah. Not only did we see it issuing up to 20 or so unauthorised
overlapping POSIX_FADV_WILLNEED calls, but in the case we studied they
didn't really do anything at all because it was *postfetching* (!), ie
issuing advice for blocks it had already read. The I/O was sequential
(reading all or most blocks in order), so the misdirected advice at
least kept out of the kernel's way, and it did some really effective
readahead. Meanwhile the stream version played by the rules and
respected eic=1, staying only one block ahead. We know that advice for
sequential blocks blocks readahead, so that seems to explain the red
for that parameter/test permutation. (Hypothesis based on some
quick reading: I guess kernel pages faulted in that way don't get
marked with the internal "readahead was here" flag, which would
normally cause the following pread() to trigger more asynchronous
readahead with ever larger physical size). But that code
in master is also *trying* to do exactly what we're doing, it's just
failing because of some combination of bugs in the parallel scan code
(?). It would be absurd to call it the winner: we're setting out
with the same goal, but for that particular set of parameters and test
setup, apparently two (?) bugs make a right. Melanie mentioned that
some other losing cases also involved unauthorised amounts of
overlapping advice, except there it was random and beneficial and the
iterators didn't get out of sync with each other, so again it beat us
in a few red patches, seemingly with a different accidental behaviour.
Meanwhile we obediently trundled along with just 1 concurrent I/O or
whatever, and lost.

Makes sense, likely explains the differences. And I agree we should not
hold this against this patch series, it's master that's doing something
wrong. And in most of these cases we'd not even do bitmap scan anyway, I
think, it only happens because we forced the plan.

BTW how are you investigating those I/O requests? strace? iosnoop? perf?
Something else?

On top of that, read_stream.c is also *trying* to avoid issuing advice
for access patterns that look sequential, and *trying* to do I/O
combining, which all works OK in serial BHS, but it breaks down in
parallel because:

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

+    /*
+     * The maximum number of tuples per page is not large (typically 256 with
+     * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+     * the per-page bitmaps variable size.  We just legislate that the size is
+     * this:
+     */
+    OffsetNumber offsets[MaxHeapTuplesPerPage];
} TBMIterateResult;

Seems to be 291? So sizeof(TBMIterateResult) must be somewhere
around 588 bytes? There's one of those for every buffer, and we'll
support queues of up to effective_io_concurrency (1-1000) *
io_combine_limit (1-128?), which would require ~75MB of
per-buffer-data with maximum settings That's a lot of memory to have
to touch as you whizz around the circular queue even when you don't
really need it. With more typical numbers like 10 * 32 it's ~90kB,
which I guess is OK. I wonder if it would be worth trying to put a
small object in there instead that could be expanded to the results
later, cf f6bef362 for TIDStore, but I'm not sure if it's a blocker,
just an observation.

Not sure I follow. Doesn't f6bef362 do quite the opposite, i.e. removing
the repalloc() calls and replacing that with a local on-stack buffer
sized for MaxOffsetNumber items? Which I think is 2048 for 8kB pages?

Note: Is it correct to use MaxHeapTuplesPerPage for TBMIterateResult, or
should it not be tied to heap?

I don't have a clear opinion on sizing the offsets buffer - whether it
should be static (like above) or dynamic (expanded using repalloc). But
I'd probably be more worried about efficiency for "normal" configs than
about memory usage when everything is maxed out. The 75MB is not
negligible, but it's also not terrible for machines that would need such
values for these GUCs. Saving memory is nice, but if it meant "normal"
configs spend much more time on resizing the buffers, that doesn't seem
like a good tradeoff to me.

The one thing I'd be worried about is if the allocations get too large
and can no longer be cached by the memory context (and doing malloc
every time). But I don't think that's the case here, it'd need to be
larger than 8kB.

regards

--
Tomas Vondra

#187Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#185)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 13, 2025 at 7:08 AM Tomas Vondra <tomas@vondra.me> wrote:

On 2/13/25 01:40, Melanie Plageman wrote:

On Sun, Feb 9, 2025 at 9:27 AM Tomas Vondra <tomas@vondra.me> wrote:

For the nvme RAID (device: raid-nvme), it's looks almost exactly the
same, except that with parallel query (page 27) there's a clear area of
regression with eic=1 (look for "column" of red cells). That's a bit
unfortunate, because eic=1 is the default value.

So, I feel pretty confident after even more analysis today with Thomas
Munro that all of the parallel cases with effective_io_concurrency ==
1 are because master cheats effective_io_concurrency. Therefore, I'm
not too worried about those for now. We probably will have to increase
effective_io_concurrency before merging this patch, though.

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

Agreed. If this is due to master doing something wrong (and either
prefetching more, or failing to prefetch), that's not the fault of this
patch. People might perceive this as a regression, but increasing the
default eic value would fix that.

BTW I recall we ran into issues with prefetching and parallel workers
about a year ago [1]. Is this the same issue, or something new?

[1]
/messages/by-id/20240315211449.en2jcmdqxv5o6tlz@alap3.anarazel.de

Th postfetching is the same issue as you linked in [1].

For the SATA SSD RAID (device: raid-sata), it's similar - a couple
regressions for eic=0, just like for NVMe. But then there's also a
couple regressions for higher eic values, usually for queries with
selective conditions.

I started trying to reproduce the regressions you saw on your SATA
devices for higher eic values. I was focusing just on serial bitmap
heap scan -- since that doesn't have the problems mentioned above. I
don't have a SATA drive, but I used dmsetup to add a 10ms delay to my
nvme drive. Unfortunately, that did the opposite of reproduce the
issue. With dm delay 10ms, the patch is 5 times faster than master.

I'm not quite sure at which point does dm-setup add the delay. Does it
affect the fadvise call too, or just the I/O if the page is not already
in page cache?

So dmsetup adds the delay only when the page is not found in kernel
buffer cache -- actually below the filesystem before issuing it to the
block device. reads, writes, and flushes can be delayed (I delayed all
three by 10ms). fadvises can't since they are above that level.

- Melanie

#188Tomas Vondra
tomas@vondra.me
In reply to: Melanie Plageman (#179)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/10/25 23:31, Melanie Plageman wrote:

On Mon, Feb 10, 2025 at 4:22 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I don't really know what to do about this. The behavior of master
parallel bitmap heap scan can be emulated with the patch by increasing
effective_io_concurrency. But, IIRC we didn't want to do that for some
reason?
Not only does effective_io_concurrency == 1 negatively affect read
ahead, but it also prevents read combining regardless of the
io_combine_limit.

Would a sensible default be something like 4?

Could be. It would perform much better for most systems I think, but
it's still a fairly conservative value so unlikely to cause regressions.

If we wanted to validate the value, what tests do you think would be
appropriate? What about just running the same tests with different eic
values, and pick a reasonable value based on that? One that helps, but
before it stats causing regressions.

FWIW I don't think we need to do this before pushing the patches, as
long as we do both. AFAIK there'll be an "apparent regression" no matter
the order of changes.

I did some self-review on the patches and cleaned up the commit
messages etc. Attached is v29.

I reviewed v29 today, and I think it's pretty much ready to go.

The one part where I don't quite get is 0001, which replaces a
FLEXIBLE_ARRAY_MEMBER array with a fixed-length array. It's not wrong,
but I don't quite see the benefits / clarity. And I think Thomas might
be right we may want to make this dynamic, to save memory.

Not a blocker, but I'd probably skip 0001 (unless it's required by the
later parts, I haven't checked/tried).

Other than that, I think this is ready.

regards

--
Tomas Vondra

#189Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#188)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 13, 2025 at 10:46 AM Tomas Vondra <tomas@vondra.me> wrote:

I reviewed v29 today, and I think it's pretty much ready to go.

The one part where I don't quite get is 0001, which replaces a
FLEXIBLE_ARRAY_MEMBER array with a fixed-length array. It's not wrong,
but I don't quite see the benefits / clarity. And I think Thomas might
be right we may want to make this dynamic, to save memory.

Not a blocker, but I'd probably skip 0001 (unless it's required by the
later parts, I haven't checked/tried).

So, on master, it already pallocs an array of size MAX_TUPLES_PER_PAGE
(which is hard-coded in the tidbitmap API to MaxHeapTuplesPerPage) --
see tbm_begin_private_iterate().

So we always palloc the same amount of memory. The reason I changed it
from a flexible sized array to a fixed size is that we weren't using
the flexibility and having a flexible sized array in the
TBMIterateResult meant it couldn't be nested in another struct. Since
I have to separate the TBMIterateResult and TBMIterator to implement
the read stream API for BHS, once I separate them, I nest the
TBMIterateResult in the GinScanEntry. If the array of offsets is
flexible sized, then I would have to manage that memory separately in
GIN code for the TBMIterateResult..

So, 0001 isn't a change in the amount of memory allocated.

With the read stream API, these TBMIterateResults are palloc'd just
like we palloc'd one in master. However, we have to have more than one
at a time.

- Melanie

#190Tomas Vondra
tomas@vondra.me
In reply to: Melanie Plageman (#189)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/13/25 17:01, Melanie Plageman wrote:

On Thu, Feb 13, 2025 at 10:46 AM Tomas Vondra <tomas@vondra.me> wrote:

I reviewed v29 today, and I think it's pretty much ready to go.

The one part where I don't quite get is 0001, which replaces a
FLEXIBLE_ARRAY_MEMBER array with a fixed-length array. It's not wrong,
but I don't quite see the benefits / clarity. And I think Thomas might
be right we may want to make this dynamic, to save memory.

Not a blocker, but I'd probably skip 0001 (unless it's required by the
later parts, I haven't checked/tried).

So, on master, it already pallocs an array of size MAX_TUPLES_PER_PAGE
(which is hard-coded in the tidbitmap API to MaxHeapTuplesPerPage) --
see tbm_begin_private_iterate().

So we always palloc the same amount of memory. The reason I changed it
from a flexible sized array to a fixed size is that we weren't using
the flexibility and having a flexible sized array in the
TBMIterateResult meant it couldn't be nested in another struct. Since
I have to separate the TBMIterateResult and TBMIterator to implement
the read stream API for BHS, once I separate them, I nest the
TBMIterateResult in the GinScanEntry. If the array of offsets is
flexible sized, then I would have to manage that memory separately in
GIN code for the TBMIterateResult..

So, 0001 isn't a change in the amount of memory allocated.

With the read stream API, these TBMIterateResults are palloc'd just
like we palloc'd one in master. However, we have to have more than one
at a time.

I know it's not changing how much memory we allocate (compared to
master). I haven't thought about the GinScanEntry - yes, flexible array
member would make this a bit more complex.

I don't want to bikeshed this - I'll leave the decision about 0001 to
you. I'm OK with both options.

regards

--
Tomas Vondra

#191Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#190)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 13, 2025 at 11:28 AM Tomas Vondra <tomas@vondra.me> wrote:

On 2/13/25 17:01, Melanie Plageman wrote:

On Thu, Feb 13, 2025 at 10:46 AM Tomas Vondra <tomas@vondra.me> wrote:

I reviewed v29 today, and I think it's pretty much ready to go.

The one part where I don't quite get is 0001, which replaces a
FLEXIBLE_ARRAY_MEMBER array with a fixed-length array. It's not wrong,
but I don't quite see the benefits / clarity. And I think Thomas might
be right we may want to make this dynamic, to save memory.

Not a blocker, but I'd probably skip 0001 (unless it's required by the
later parts, I haven't checked/tried).

So, on master, it already pallocs an array of size MAX_TUPLES_PER_PAGE
(which is hard-coded in the tidbitmap API to MaxHeapTuplesPerPage) --
see tbm_begin_private_iterate().

So we always palloc the same amount of memory. The reason I changed it
from a flexible sized array to a fixed size is that we weren't using
the flexibility and having a flexible sized array in the
TBMIterateResult meant it couldn't be nested in another struct. Since
I have to separate the TBMIterateResult and TBMIterator to implement
the read stream API for BHS, once I separate them, I nest the
TBMIterateResult in the GinScanEntry. If the array of offsets is
flexible sized, then I would have to manage that memory separately in
GIN code for the TBMIterateResult..

So, 0001 isn't a change in the amount of memory allocated.

With the read stream API, these TBMIterateResults are palloc'd just
like we palloc'd one in master. However, we have to have more than one
at a time.

I know it's not changing how much memory we allocate (compared to
master). I haven't thought about the GinScanEntry - yes, flexible array
member would make this a bit more complex.

Oh, I see. I didn't understand Thomas' proposal. I don't know how hard
it would be to make tidbitmap allocate the offsets on-demand. I'd need
to investigate more. But probably not worth it for this patch.

- Melanie

#192Andres Freund
andres@anarazel.de
In reply to: Melanie Plageman (#179)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

Thomas, there's a bit relevant to you at the bottom.

Melanie chatted with me about the performance regressions in Tomas' benchmarks
of the patch. I experimented some and I think I found a few interesting
pieces.

I looked solely at cyclic, wm=4096, matches=8, eic=16 as I wanted to
narrow down what I was looking at as much as possible, and as that seemed a
significant regression.

I was able to reproduce the regression with the patch, although the noise was
very high.

My first attempt at reducing the noise was using MAP_POPULATE, as I was seeing
a lot of time spent in page fault related code, and that help stabilize the
output some.

After I couldn't really make sense of the different perf characteristics
looking at the explain analyze or iostat, so I switched to profiling. As part
of my profiling steps, I:

- bind postgres to a single core
- set the cpu governor to performance
- disable CPU idle just for that core (disabling it for all cores sometimes
leads to slowness due to less clock boost headroom)
- try both with turbo boost on/off

With all of those applied, the performance difference almost vanished. Weird,
huh!

Normally CPUs only clock down when idle. That includes waiting for IO if that
wait period is long enough.

That made me look more at strace. Which shows this interesting difference
between master and the patch:

The chosen excerpts are randomly picked, but the pattern is similar
throughout execution of the query:

master:

pread64(52, "\0\0\0\0\260\7|\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 8192, 339271680) = 8192 <0.000010>
fadvise64(52, 339402752, 8192, POSIX_FADV_WILLNEED) = 0 <0.000008>
pread64(52, "\0\0\0\0h\10|\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 8192, 339279872) = 8192 <0.000011>
fadvise64(52, 339410944, 8192, POSIX_FADV_WILLNEED) = 0 <0.000008>
pread64(52, "\0\0\0\0 \t|\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 8192, 339288064) = 8192 <0.000011>
fadvise64(52, 339419136, 8192, POSIX_FADV_WILLNEED) = 0 <0.000011>
pread64(52, "\0\0\0\0\330\t|\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 8192, 339296256) = 8192 <0.000011>
fadvise64(52, 339427328, 8192, POSIX_FADV_WILLNEED) = 0 <0.000008>

With the patch:

fadvise64(52, 332365824, 131072, POSIX_FADV_WILLNEED) = 0 <0.000021>
pread64(52, "\0\0\0\0(\223x\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 131072, 329220096) = 131072 <0.000161>
pread64(52, "\0\0\0\0\250\236x\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 131072, 329351168) = 131072 <0.000401>
pread64(52, "\0\0\0\0@\252x\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 65536, 329482240) = 65536 <0.000044>
pread64(52, "\0\0\0\0\0\250y\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 131072, 332365824) = 131072 <0.000079>
pread64(52, "\0\0\0\0\200\263y\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 131072, 332496896) = 131072 <0.000336>
fadvise64(52, 335781888, 131072, POSIX_FADV_WILLNEED) = 0 <0.000021>
pread64(52, "\0\0\0\0\0\277y\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 131072, 332627968) = 131072 <0.000091>
pread64(52, "\0\0\0\0\230\312y\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 131072, 332759040) = 131072 <0.000399>
pread64(52, "\0\0\0\0\30\326y\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 65536, 332890112) = 65536 <0.000046>
pread64(52, "\0\0\0\0\220\324z\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 131072, 335781888) = 131072 <0.000081>
pread64(52, "\0\0\0\0(\340z\17\0\0\4\0x\0\200\30\0 \4 \0\0\0\0\260\237\222\0`\237\222\0"..., 131072, 335912960) = 131072 <0.000335>
fadvise64(52, 339197952, 131072, POSIX_FADV_WILLNEED) = 0 <0.000021>

There are a few interesting observations here:
- The patch does allow us to make larger reads, nice!

- With the patch we do *not* fadvise some of the blocks, the read stream
sequentialness logic prevents it.

- With the patch there are occasional IOs that are *much* slower. E.g. the
last pread64 is a lot slower than the two preceding ones.

Which I think explains what's happening. Because we don't fadvise all the
time, we have to synchronously wait for some IOs. Because of those slower IOs,
the CPU has time to go into an idle state. Slowing the whole query down.

If I disable that:

diff --git i/src/backend/storage/aio/read_stream.c w/src/backend/storage/aio/read_stream.c
index e4414b2e915..e58585c4e02 100644
--- i/src/backend/storage/aio/read_stream.c
+++ w/src/backend/storage/aio/read_stream.c
@@ -242,8 +242,9 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
      * isn't a strictly sequential pattern, then we'll issue advice.
      */
     if (!suppress_advice &&
-        stream->advice_enabled &&
-        stream->pending_read_blocknum != stream->seq_blocknum)
+        stream->advice_enabled
+        // && stream->pending_read_blocknum != stream->seq_blocknum
+        )
         flags = READ_BUFFERS_ISSUE_ADVICE;
     else
         flags = 0;

I see *much* improved times.

Without cpu idle tuning:

master: 111ms
patch: 128ms
patch, with disabled seq detection: 68ms

Suddenly making the patch a huge win.

ISTM that disabling posix_fadvise() just because of a single sequential IO is
too aggressive. A pattern of two sequential reads, gap of more than a few
blocks, two sequential reads, ... will afaict never do useful readahead in
linux, because it needs a page cache access nearby already read data to start
doing readahead. But that means we encounter ynchronous-blocking-read.

Thomas, what lead to disabling advice this aggressively? Particularly because
heapam.c disables advice alltogether, it isn't entirely obvious why that's
good?

I suspect this might also affect the behaviour in the vacuum read stream case.

I think we'll need to add some logic in read stream that only disables advice
after a longer sequential sequence. Writing logic for that shouldn't be too
hard, I think? Determining the concrete cutoffs is probably harder, although I
think even fairly simplistic logic will be "good enough".

Greetings,

Andres Freund

#193Thomas Munro
thomas.munro@gmail.com
In reply to: Melanie Plageman (#191)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Feb 14, 2025 at 5:52 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Feb 13, 2025 at 11:28 AM Tomas Vondra <tomas@vondra.me> wrote:

On 2/13/25 17:01, Melanie Plageman wrote:
I know it's not changing how much memory we allocate (compared to
master). I haven't thought about the GinScanEntry - yes, flexible array
member would make this a bit more complex.

Oh, I see. I didn't understand Thomas' proposal. I don't know how hard
it would be to make tidbitmap allocate the offsets on-demand. I'd need
to investigate more. But probably not worth it for this patch.

No, what I meant was: It would be nice to try to hold only one
uncompressed result set in memory at a time, like we achieved in the
vacuum patches. The consumer expands them from a tiny object when the
associated buffer pops out the other end. That should be possible
here too, right, because the bitmap is immutable and long lived, so
you should be able to stream (essentially) pointers into its internal
guts. The current patch streams the uncompressed data itself, and
thus has to reserve space for the maximum possible amount of it, and
also forces you to think about fixed sizes.

I think if you want "consumer does the expanding" and also "dynamic
size" and also "consumer provides memory to avoid palloc churn", then
you might need two new functions: "how much memory would I need to
expand this thing?" and a "please expand it right here, it has the
amount of space you told me!". Then I guess the consumer could keep
recycling the same piece of memory, and repalloc() if it's not big
enough. Or something like that.

Yeah I guess you could in theory also stream pointers to individual
uncompressed result objects allocated with palloc(), that is point a
point in the per-buffer-data and make the consumer free it, but that
has other problems (less locality, allocator churn, need
cleanup/destructor mechanism for when the streams is reset or
destroyed early, still has lots of uncompressed copies of data in
memory *sometimes*) and is not what I was imagining.

#194Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#193)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Feb 14, 2025 at 11:50 AM Thomas Munro <thomas.munro@gmail.com> wrote:

Yeah I guess you could in theory also stream pointers to individual
uncompressed result objects allocated with palloc(), that is point a
point in the per-buffer-data and make the consumer free it, but that
has other problems (less locality, allocator churn, need

Sorry, typing too fast, I meant to write: "that is, put a pointer in
the per-buffer-data and make the consumer free it".

#195Jakub Wartak
jakub.wartak@enterprisedb.com
In reply to: Robert Haas (#182)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Feb 12, 2025 at 9:57 PM Robert Haas <robertmhaas@gmail.com> wrote:

On Wed, Feb 12, 2025 at 3:07 PM Tomas Vondra <tomas@vondra.me> wrote:

AFAICS the "1" value is simply one of the many "defensive" defaults in
our sample config. It's much more likely to help than cause harm, even
on smaller/older systems, but for many systems a higher value would be
more appropriate. There's usually a huge initial benefit (say, going to
16 or 32), and then the benefits diminish fairly quickly.

I'm happy to see us change the value to something that is likely to be
good for most people. I think it's OK if people on very tiny systems
need to change a few defaults for optimum performance. We should keep
in mind that people do sometimes run PostgreSQL on fairly small VMs
and not go crazy with it, but there's no reason to pretend that the
typical database runs on a Raspberry Pi.

Is there any reason we couldn't have new pg_test_iorates (similiar to
other pg_test_* proggies), that would literally do this and calibrate
best e_io_c during initdb and put the result into postgresql.auto.conf
(pg_test_iorates --adjust-auto-conf) , that way we would avoid user
questions on how to come with optimal value?

root@jw-test3:/nvme# ./pg_test_iorates
File size: 16.00 GB, Block size: 8192 bytes
buffered sequential read: 1573.33 MB/s
direct sequential read: 289.46 MB/s
random read performance with different prefetch distances:
using prefetch distance 1: 173.58 MB/s
using prefetch distance 2: 243.05 MB/s
using prefetch distance 4: 376.78 MB/s
using prefetch distance 8: 590.66 MB/s
using prefetch distance 16: 824.49 MB/s
using prefetch distance 32: 861.45 MB/s
using prefetch distance 64: 830.36 MB/s

Attached, compile naive way via: gcc pg_test_iorates.c -o
pg_test_iorates -I /git/postgres/build/src/include -I
/git/postgres/src/include -L /git/postgres/build/src/common
-L/git/postgres/build/src/port -lpgcommon -lpgport -lm

-J.

Attachments:

pg_test_iorates.ctext/plain; charset=US-ASCII; name=pg_test_iorates.cDownload
#196Andres Freund
andres@anarazel.de
In reply to: Jakub Wartak (#195)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-02-14 10:04:41 +0100, Jakub Wartak wrote:

Is there any reason we couldn't have new pg_test_iorates (similiar to
other pg_test_* proggies), that would literally do this and calibrate
best e_io_c during initdb and put the result into postgresql.auto.conf
(pg_test_iorates --adjust-auto-conf) , that way we would avoid user
questions on how to come with optimal value?

Unfortunately I think this is a lot easier said than done:

- The optimal depth depends a lot on your IO patterns, there's a lot of things
between fully sequential and fully random.

You'd really need to test different IO sizes and different patterns. The
test matrix for that gets pretty big.

- The performance characteristics of storage heavily changes over time.

This is particularly true in cloud environments, where disk/VM combinations
will be "burstable", allowing higher throughput for a while, but then not
anymore. Measureing during either of those states will not be great for the
other state.

- e_io_c is per-query-node, but impacts the whole system. If you set
e_io_c=1000 on a disk with a metered IOPS of say 1k/s you might get a
slightly higher throughput for a bitmap heap scan, but also your commit
latency in concurrent will go through the roof, because your fdatasync()
will be behind a queue of 1k reads that all are throttled.

Greetings,

Andres Freund

#197Tomas Vondra
tomas@vondra.me
In reply to: Melanie Plageman (#179)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

Based on off-list discussion with Melanie, I ran a modified version of
the benchmark, with these changes:

- only: uncached runs on the raid-SATA device (4x SSD)
- only: work_mem=4MB
- only: pached-0004 branch
- all datasets, ndistinct/nmatches combinations, 1M and 10M rows, ...

and then two new parameters:

- io_combine_limit 1, 16, 32
- read-ahead, 16, 256, 4096

The complete logs are pushed to github, as usual:

https://github.com/tvondra/bitmapscan-tests/tree/main/20250212-221123

There's also a .sh with the benchmarking script.

I'm attaching a PDF with the comparison, the columns are for

- io_combine_limit (16, 256, 4096)
- effective_io_concurrency (0, 1, 16)

And as usual, the colored columns are comparing patched-0004
(green=good, red=bad).

One way to look at the PDF is that there are 9 squares (in 3x3 layout),
for combinations of io_combine_limit and read-ahead values. The central
square is for the default values (ioc=16, ra=256), and you can compare
this to the surrounding squares.

Of course, this shows "behavior relative to master", a square being
"more green" does not mean the absolute performance improves, just that
it's "more better" relative to master.

I hope this explanation makes sense ...

FWIW this does not change anything in the detection of sequential access
patterns, discussed nearby, because the benchmarks started before Andres
looked into that. If needed, I can easily rerun these tests, I just need
a patch to apply.

But if there really is some sort of issue, it'd make sense why it's much
worse on the older SATA SSDs, while NVMe devices perform somewhat
better. Because AFAICS the NVMe devices are better at handling random
I/O with shorter queues.

regards

--
Tomas Vondra

Attachments:

results.pdfapplication/pdf; name=results.pdfDownload
%PDF-1.4
%��������
2 0 obj
<</Length 3 0 R/Filter/FlateDecode>>
stream
x���A�����	��S�q
T�,�6�H`{��@�^w=h���5P�j����~�I)|�~�}�y��{v:(2���`��}7N���?����r��\������y�������e>������?��?���?���������������o���O�e�����e8u�������������SwZ�?����_���1����c������������8�{�����������__�������������?&���)�?�g�S�h|�t�����_�����?��?a�x��e�����]������Oi��?�������R���t��O������z�O�q�����[����3���y����iZ��<�9_.�2����S7��?����������
�>�O�p^�s?��������5_��4���u��}w�\�������l����y����������e�^�?�����6}7�I/Y��[��e��k?\����\���Z>e���������8����yM�����N��g�/����xz�x���v��|J�{	zJxj����x��%l��>�u�+������N�4NB�61���k-^�n�P
;�Cx��,�����w����#�������z��?=�=�h��h�o���
I_���n������� L��l��tj��5�w�<�i�?�qC���/������n�K����H��k�����yn�]�QO-���u-���d���_���(�~��eo{Qx(1�3_��kv���E��3����+�y���������5�o��}a���sw�,R���l�}�Z8����o����-#L�	�u��-��,�����w2�m���.������	'C���`8�v����;'c-������\���h����H������!����%_Z�"Bbb��h�?�mN�w���x������z��y�����|#m��%����=�P�����������7'��}~�������H���lh1%��'�����{gC������9 ��
�}��E��k�����/�������w������_��?��~�~�������j�;-�
A���P�������G�vZ�q�������'�A�����iY���|�_��o<N����9_�a�7�^\�q����7����������H���?������<�{)�����>������OS)�~G�\�n����`��s�d����p���r���_)�,�����������.���i<�������~��SO8A�����6�n�=��<P���M�~o�\����pm?����G��;�3���6N�w�Y���N����k��R���s�&z��x^�����A����=dnNH�5g�m��i��$�9�l��w��3�Y�J��4k�wx��������p1-�4��V���?���@ex���G�����|_���d������^�U���C��������	u�I��^���s��><��6/$Q���d���+L*j�J�/�re���3��/����{�M�p=����h<����e���l��x$�3�o�v6�u.���,|{��$�vy�C�6���QX�����|��{�;]�~8%;�,����0����]�%�w����qH������K����T���2����;�#�w^�Sw����J�%�
���_�P�[(���k�M�o�A�����������4��c�%u���P�h�77#��@��l��f�m��j�����������c��x�fiY��/�P��orv��{!(��`��Os�#�`G{��^�7�]�3�M���ti��FV{Q��N���akj�6�i��~�>�ST�A������� �H�#Ja��wUR�<�ys�}xH�"�V�:��1�M�e�7�:M������wat�?�!a�'	���G�
~z�n�D��s�������;A�r�=���3��$����hZ%;��97�!:�	�N���7�aM:ds<>��~�+:,�u�wS���Gf�
�N��%4���~y>LN@aU�v�Ll�_������|���s�i�(kx�����R�H�i$�����a����h6���g���9��w��<��[	7a���
iJ���6�|�I�����pI2���d�\;�}[����%A���_�_��J�A�Kja�$=�[+�%�����q�|�1����V���HX���:\s��G��8�uw8:N����t��n\Td��@hB����7)��8�~��c|&u����m�ol����m�;��;�uT���}|��'�:��������Q@%n�?�/���
6��Ia�;�}�F��7�C	��G5��*r?9�p���?f�m&%\��(����{]���&��y>���.P��G�h�u�.�J�,V������U�4w�D�9�hl����wj��W�D�]�|D�ed���Q-t3��V���$6s��8\��
������m����s�m?��Ssx���)����Ip�u��P����{�i<���N�*^��2�f�!�:<�(�^��$�\Sm�8gs7��y9w'�����f�O�v��I�����u�$a
����a����h3���\�P4���l���te+���&
�X�����Yl���YtoE#���6���K����aO�p��a�P���O�Y](��r�*e
�
O���i��d����fZs�/a�*��K�377��W0����wf�G��|�����nJ���m�M-����?&4�
��}3��a�7	����"�C�=-/@��pt���i��me�{!�C��2�d�J�x���R�W��y��'�	��7^�e7^(��*�Ws��@����(��|J����zdes5��7/$3?��CaK���|��u�����o�`���u'���p8),��pCR����D�>�rz�A��w��z��pCT�vc��!�`�,��!YY��q7do�k��ey����:'	k�P}�7E��#��pS�����i�fo�>����S���6����A�����O������e��,"N���G���-�[!bsc.	�����$	�0�?-6���<��vh�<��l8N��=���#�s��Z�R��Y���#��~��7�,Z�&f���6w4wF)+<�v�#]]���O��y>u������HX1_~�;VMo�Ca����<65w����l�D�Z���r_
k��;A������0���F��Y�0����m�(�2Mw?�i�
��I��?�^���
�$��X���h]������7i��nT)����[g��<�����DV��OaS�D���Y��]��$�y����#�V�~�'�����g
������@���w��q���?��I�b$`�C������'�q�?�XNKw^T�i�~-�H�u�.�e�����9%�#IX�+�=5���$�����62���En�pG�\���!��m���^�g9��<����C�JaI�����Ny�
�$�>=.��O�%��}2bkeSI������de�-|������M�Kw!{U�.�oj	E�w*m�{)���tZ�;)���II���\��M����~cep/E3��J�R4��3N�Y���9u�E�S�:�unN��rg�R-�	0C����d��������g�,�/�/"#�qL����d}�$�>$�\�kw�7c���F�����H��.���3;�/�7����)W��c�<U�~�3IXuc	�D3�U���_*v�{s����S�)kj��h�����)�*� l~JV~�����~|���e�(,k��J�/�7O%���-�T)�6�n������=A� 5,�� ��]T��bc�|��2�H8MHC����oqp�>�r4�S/�'|��?w�I�h?�p$aM+T��G�������I,r��G�t�%aU�lwY�2p��x�?ae�,Z�����T{.:wYT�������21���.��u����, Jh
l�c��O�$���c���f��~>Y��X4�)�������������Kw��R���%�i(��aA�_�y|��[�BW4�U�JtDaU�w��JwH����l�~h+S�;��!y�+���:u��_���P
��x�MP���'�V�u�a
�*�9�o�����=o��7��I�2��HP��P���HY:_����<?%R�����H)���-_���.	�>�oV���y$�*�
mIFV/��7��"�D�&8�[��|Y����4\K�"!���p,���_��j��+�qO�AL��Wd���;$������� ���/Cw�"������hjCf����'��>6�'�am�����
�lNJ�5�m�G/E3�9��� ���6+����|�����%a�KD��D3�Y-,�pG%uj�lQ5~����S��t�$a&��b���p�S7]���pOV�����4����/&Q���U8*��gY�,�X��9*����&������������W�k&�pN�55Q$h���I������eL���Ny��9����\��s���f�<����W��cs���'����iL�)�v������@V�
�m>>/��/~X��Y��	�l�>�������7}�m*�Te?7��������>HM��c(Ga����DQ�#���0�1��:����C�q�����G"�ir?�yz�K���j����������a��2�U�E�^�F�!���=���)������	�P����e�i�q>����;���~�7����~�A�p<�U�r��)X����0	���|���,`�jR���pm�w�G/0�}+�.�p�d����I�q��oN�[g�/Ba����(���w?Bm��'
����2�{Rb[�9qD����������|
���%����m�*c�'����n�y�Vt�C�:�!��xwk���?�F����X@�N��|�,�V7����77����L�|��yx��H5<J�N�.�������jo���o�e(����e$��a�s8����4w� #U��C<����%[���9����_2��6�
��2��[�,A���[����i�������4l���$�����3�qwU�:V[�������Y8�5�q��3�?����6b��S-M
�a�Q3i��O;������_�~:�����v>zp56����L��{h�����6���v��Q,l�UN��	I��������in��S�y6���E��U��IY���4��dU�(���l��G�5��%!d}����VF����O�<���-2���L���A�pB-�o'�W�����&pj�L�����h���
'$e�&���B<�AU�B�)�
�������E�&h�nU ��v� ��|�>�1�{i�&��)w6���H�
/���k�m�s�
%7�$���r6�ae*�pN��ZQ�G�i�fC
O�P����}��8J���*����%QB���'�V�r�������q>0hn��f�h+0����&�������6�X�sw��H�~f�ja��_S{�tO�|�+�m+�X������%?D�>d�f��<���l5�4�D��{}�u9<A����CJa��]��������Z�����#�����ui��������2D�M:0��lN���!N���3�_��0�a���au*S��5wd�>D���Bo]T�	������pwG�U&�1wDam��&|����;��U���3O�iT%���ox�6�q�^�[��LP�lY�&Z�+\���e���	��Cw�� ����I���I��l�
;���
�Nc���		�)�n���{Z��m�7(|����N�����.�&��]�e)Z��S<��J�p���\T�I`���,���(e�S���,-1jcD� �4����;���4�M�Q;�M0:<�}��9�v�t'�Y*�	M��)�)��l��d8�~lCG�yjB=�wZ�5G7*hB���4�Q��Ti��MT�0=�d�������2K���\������t��B�����9-�9���b���+���q�E����������&��?�����A
qL�oc����:*'�]���%�L��O"�S�S��L
{�=�_������:�v�a�����v��91�I�;�'��1��p������S&�
c��������������\�^��$Y��rZF�S�����M�#��������6���WY&�q�fZ�������5�rDc�+�!5������_����dU�A7?a�/��C�rf�_N�i_[yx����?���m�J�&���tmm;Z6m_��v��,+�1����',�5G�S�N��$��w}�\��T�kjY_��7��h�~i�tx=���A�p�����u�?�,�6�o�v�1��V�<2�L,k����p��;��34y����i<��������d�vXYI	���u���vG��lY��#��}J:�V��|oV6������\�pMX���<t�b�t�<)���y ���EVe	/$+�������-����	IX1��9!YYDwBv,��q����*��v�bm��f?r����	�S�����$�C�4��&�����:��2d}��@���3��x�r~�i���o.�������!���/���XX5����1��L�����&
��	�Uy��7q�?��;]�	��"N���0��l>��eQ�9)Y����$�����Y���e?���]��U���jQG��n\�E���#AX��h��B��HV�1�a�2��f:��8
��m~F��������KJ�f�����)ao� ������b�Z��9)l�$x^��kx)�)�����}�e��������:��Gw.-���B��g!
���L��H�������l�g����R�d��Z��9<����}���[����f�/
��C���=���f�*	��s����s7[�����p~^����~��������}��$,��r�C}>�>�YKV����x�N���@�������io�p����f����"0�����Q���
W%�>
}��O�-I����OL��j��*�������	��J����vvO$aS�hS^�+'�D���Xn����:
c	D��I���p\�������<��q��;��
��oI	���| �S��F�p>VM�����Sd�������!+����bUB�p��4��!�o���j��L�pI�\s�����]�U7��%i�
���xk$3�m�K��Mw���?��c�v�.�d��T���jE��qOda�u�#��~���L�DV���'�0]&�Oq57da:�Rd[���Yp:pG��CN��u��3�H�TJ`���F>��5_UP��9)�t�DaD�zT���>tR���~ulc�����;�O�����@ra�K�����(}���e��u��{�o���}������7IX�,���f~b3���=/���GA�z���[N�*5c�'+���?IXK��w�pT2�S�'ae��pT2S����pT2�
G%3?{��bd�]�|}^��NA���<r|m�d�S2�I���H��%���8U�=.o�V~��h���?2���swx���O����J8���JQ�;�U��
��s������nN������]Mq�f����i�����#b������R�_!p|p�#h�8�U�?�|��h�o��p5��}�FNM��>�����`w<��B��iY��L�+�1��iaCKW��]I�T�)�C�i��wH6�w����#vO�r_�$6����{�h�)��������^M��L���t��)�^�}��};��J	)Pm�2>�>6����}h����pA3?��Aa�4Ow?��
*��g�f�������>�%��)���
����}�!a�"�=�������IX9hj���sN�
�n�Er�_n(�F���9�E��� �CBY�U�@�C��r�_x$MYnm��������|B�>���3��!�kw����`�X�vo��}�aQ���Y���M��&�9Lg�j����������r?6sTT��L��4w�LS�}o~
���6��[xG���-=�~�DY�|�z�<s�����nNH�>�t$a����mN8t�!�x�>�E�w�Q����@m�deD��ZZ�BZ���s���O�����gK�}l��~��9��B�����[�a�q�#a��@�������X���#��`w<VFT��lv�+������m��S���l~x��AG����O�����%�<NJxo��������"Y���hZ�Yj�DJ t�=9R�D��
��y��I�&��������x����8G�
YB� 4��n�%����YVs{���l���lXs_��K�N�>H��M���[f.H�|Z�z�n�9��������=������6o#aM��mb�7����;���o��m����rX2<mk������q(�����k���knF��L��i�V*�ba�}�:����<4����/�����_n�nFYKs-��.?7����x��+�{h�q���<9��D������%�9������2�p$l�o���fi�^��x�����M�k������-oE����� ��H�O{Z�����yR�2��,#	��&[����
�UWes8���\��/�9���z����DA�������]����4�����*#����{(����o����{��R����9i�1�&�������rz�:c����f:>3�i�3�G"��s8�����Igy5M�J���H�������7Y���8L�����@�q?�I�����p���d	�a��|x��[|x�^�q�����q�����Z�������PV����	E����Y(l�w<i���}w����^��g��E��+�V����n��]?��L�!t���%�����s�w(��o��>l��F���9<��*"|�&�zA>�������	�|��U+s�����Q�Ix�!��g���a�����Q�C �E�6[�QX��;��U��lnFsV�c7a���e4cU�[w���-�����-	7D	on���x��
��6PXGID������}���D��v�	�#a�^��|�/�^O�e�N�iRo��������w�������d��7�Ym����(s���=���=���p=��O������oq����O������
�>5������B�������}o-S�_��������d5TI:O:��d��3r�����<c�z!	[�_Z�����P�1�OOl�f
�#	��'[o>���j�ix��.���
�i�����e��s��>=R��*N��-���R>L����?o��o,k����.�CP�� �����0�+r�$e�M��/AV9;��
�����<^��7���yPe����p?)kx������hS�a���d>��i����$��"^��w[8���#Mo��y�T�D�p��UJ��N(e
���-�#��i�r/<���GL'D���7N�pB�@u��dO������d{���G=ey�>L9�s��UMt1o��P�JV*���)�(��iE���B�
���	/D�Z��}c����0Y�fg=Jh����<w���2�ZC���_����R��|���7�������i
L�_�7f�pC6
j�
��K,��Z`sH6��vi?Q�!�������-'���\79E�|�pB-k�H�G4�[awB�f��A���hY��<�01M�_���N�$����W�IV5�1�����L���4i���q��A�yk�6����	�|Z��>����4�
����}Jt��4B�p��} \�����M�v������#�����N�t��$���m2	+���a�}��M?9�Ga����B6��� ��+�d[�do�S���������#�-+�q�d�a�������	�d}�� ����Z���h7�*^	�+�Z�'Is���fk���;/*y���<Z����dr����|��hYs�UqP�����y(��m.
��u�0����_=o^z�9s����x��Iv���Z�l?V�7IX���U���%������U:�C��:��!	;��A�e�!	�7�
���Za���Sweg�}@T�ln��$]��$�J�~JV�~^��E���S���%	��IV�<��T���
l����n�U�is�h�>G,�(����~��e���h����?a[8'	��IX5�)������L�|���p��y���BZ�������S)��O�/I����$����
����>G�
�ouH��Y���%�qx>�8��e���1\Kx#����%IX�~2\�m����A���t�!��W��Qt��Q�T2I�CN�t��BTm��}��6K��Q��H�Y��&�%�=�%4�����r�c	��v���M2�{T:*kO������?v~�����0�Wc7�_Q��3���=������b�m����@����m��=<M��a��?������12���EV��9�KU����z�z�j\�����������4g
k-�O����aM��|��,�(���Se�����G��
B���Ym/�f��m�Q[#�%����_��4��&��\�`d�l%�%�]�����<\�i���S����mk>nt��o�n����w�;�?`Z�����*���� \��}za��[k�3��K�mEjqwN6���;����y��!��*���fbY��3\��4��;�����C���%R
�l�$�����esHVmi�y$��c��G�mU��pI�����.	��}b�9�n8���}`��J�Qu���o�&����mn�V�R���<��c+���;��@V���M������L�������d�5���k�}��t�AD(��1��?z�/QPX�����s	k�������l��[��
��s����X #���S����s��kC���hR1���21-O��3.y�������r:��$a�F������54�TuN�O�NIf~�pdee
��dZ����v���+Xl��IXM�r?].�tA�����'���?$���~��eqzwN��!9����8���U�e�;IX9����p�
0m��2�����?b���S7���]���C�M�U]��E������ rxf/�X�U���D�����])�{�a�d���#ru��D_�G���pf�/���'t%�����r��@Xs��V��h�f�7o�P�����Mk��@)+cS	�L�|�LY�A����<w�Q�G��6U����0��d���K�#�K�#�K��b16��4	��i��lZ���������a�Ee�}�� L�_S>*EU�6���x�D�`���T�\�Q��(��l��Z/m���� �TZ3�My���a:w���RYtt�M�4$�}�*r�KQV���^�6�A��&s��dm������R[�du>��L��T�u�nX�6�<�j(��#��ox��8���H��*��=	����������@T5Gfs@��rI��@�O������N�~�X�����=5hNLC�vw$u��$�Ms9��EaM :;�7�i�&0������Ax$.[�~!<�mk�������c�������P[nHZ"Q�m�-�>a���l������<4�SoW�qd�q�����p8�Ue��C���:o\�p���	��g.����
���~�&*}S8�Uf�_�)h�w������f;k	X���p5�U��<�kJ����p4���)��q��+(�A����7O���������O;�&��\��T�lhZ����
m�m`��-�
b���6�;���g�j�gv�h�$�;��m��m�3QN?C�\��N��!������o�3�M�<��@�O{�
�����mT��%�y������P�[�O�Z�n<
��mR��i�F�����v]��H�����Iz��F�>$�n9�p_�OKxw8���[���b����p�t��� �
���<n�F����y��W$���������d}����nR�a~y�N��F������/$a��	�����c�����nH������X�=��������G4�����H.Tj55�s7\�^�q�����k��*����$�a^k+�O�$�Z��&i��C����wh&~x�O�:��|�G>�>��l�'��w����?1m�� �x�C������e�`�v�PC�Uq;V��^�N�7���O�*����;��jso�N���s�^�,�M�U��6�$Y��a���T+��/QV�O���dUk��-��r;�5��k��7���(�V�OjQ�?wI����EM{tn��CB������D���g�&�����iyKK�\��qV�{����[���_P��C���CGAu>�i��454u�T$���-�o�������>�P�������?T��3�$���� ����#�^nYZV�i^��wIIU�����].�*���iY��--��{*���i2�v)?;OCY�����G7l�����<5s/R�z�q�"Ye�isD6l�"?��j��=q��E��C"��R����O�7�{"(�i���0�D4��\���
�D2x\��WIV���&���y��3��X����ox��M������'e%���}���
�H��_�6q����������J�4<���]��������f�;e�������5������i��P1��iQk��n��4���RN$4�#Y�&�d�%����Y�{hV�J�&��z�U�����Y���pby�����E��J,n(e
o�rx����I�=�li���������-�-�ay)S�����a�Gq���~���}�W�qc~��o���S��rJQ�{�qyP�CV2J��k?)�	�(`sU���y�F�T�c�H3������� ����*�����'e
��6��I��5�� V#�
d�d��{ hrn��I�=d�"Y�>��7#���h�m��a�5���*~��>{�����=I��lOv?d���|dM���6<=
6�����"����d�#����WSk����i�>��{��9m�|�d%��7�6��q��hZ5a��dM�����n_/���6B��#�
���El��6V�[�������8
�u�}�?tF�UuF����z���L�0��d�]pv�������4|dUy����>K�:���Z�G�?���q��E5��~L5�����������k����i�V;Q����7���M�<�M���� ��������������������_���{6h<]�\�k7��������������SC/������������tv�N����[��m��!v}�(w��0w�8�qc?wg�oU2�������q���q����������'f��=O��X�"����O�f��\��/Ol_�']��'��F���[�a7��������vIVO=_��2/�9�q���q�������]?��u�?��w�u���?�������eH������0�K2�t���~���d�������������:]�/������_v�R��e~y�n������o��/��y����g�qS?<y�v��/����E��g�qO���0�C�c������e������
�n�^��/b�r����:���O�a���q����[��
���|���/zw���y�^�h�8�K��y\^�p����d�t�t��~����s���a�~��%{�0>d����d��<=�u���������}3���<p<����7���
��;�U����>��������q����j7�������_�6^���.���N����_����9�9u��������cN��_��_��_������s��_���=��/�O�^G)��������pR���q��~�b��M^^��[?����c7���c�/����["���i�h�����y�>�v����n�FOX�\����j���~��e�F�������X���OP���7�>qm���������j����o�}���r�F]{[��S����]��O��������NO�|�����������e�g?����R���,~��^�a|�P�	����[�_�����+Q�Sw^�4��M�tg9�o�WN���l/����B~�}R�{���z��b[�P����j������
�Ke#�T���Sy�B������fv�:?T�4.�Or���n���@���?��<t����=]�n>��Z�����'�����NCw����
�>Uv�v�&j�3�o�e?U��,�)��/���o��p�Ce��3���6��._�\���k7����?��W2��H�|;�+	����j�m�Gi{��6^uT�yK�\���}y������3��i�_��N0a��~���+E����L�cx��q��q����p��q<����w����2c\��������i���'i;�K���;=g`����q�(���}��|-�p�V��g�<Y����8*ON��_���S�i~�[��9����������
�y<
���s7�Nx{i0����x��|ip���s7_`"����8vm����\��y�F+�rG=�<t�Ao/�8N���i��~���8
w=�<u����G�\�3��7x���;�}�����MW=��<.z�8?� H��|�<;��z���E�j��7w��r�ub\?���D1��?%��%��Q�?���G�9���M�W�������}dl�?ZB������{v�.���+���y������)E��g�����xm��=����x9���?�7\�
����}�����>�8���w�Ps���������o���@��'���v�'�j����[�Q,����@��l�;P-w	�ji��������������g|��<A*��B��F�@���~���[��a~�n��f�_����
�/���C����%��^����w�
�\�
�����]�{7�E x����<k���g�O��g&���"�������M�qzz&���iR���PH |���
�%bz���P����{Dc��J��y���2�qx
��;�������h(�[BCi��t��h�����+������;��M��x�m��A!��L����'������)��P�p���	����\����7�Ae�d1'9������k���c��<�������1P/�/}��WV����t�/��X����E��c��x}�@��O������4�[H#E=)�M����~�������+�)7,��C$/��x������z� �hPw8���t�\:z9��'9�2��C�R�Q�x��n�$?������������?J��@N����m��EU������w�v8y�
����l�W[�u���-�C��,�d� K;���L/�>/�i;^���O�z� �
������x�#��.�O����? C(�O�\����S�
9�Is������c�s�����O�jC��$���j]m������G����6(�����p�':
W.�A����O�
�PT���2`Q+^8�-������[�p��J<������� ���g����Ez8*!7{��2n|�D�q�����Kwz���yM��kAH2f=����rY����e�I�B.���0J��v��c����%������R"���������-��	yy�O�rAW
M G��R�n7����E�_�
��ZD���*���>^����R{������b�J������R�i����?*�F5���P)�jT���P	�V9=j�P��.\*�������Ky����C��������J!���k�(���Z������Jm�]����k%���})$�R�&�@�7����0:�@�ly~vfx����z]TJ�e�AB2k%y�kV�P��?0���|���!�L�"���"J(u�����@)D,k��GP������U*+P*���.�#�F�!Id�I���ix��^�I5���r�
1Vm6��6�T���NJ�ap���z��v������aH*�I1t���D](��������I�����aZ�N��lKR��8	�Xv���'���w���	����v�;�
'iaf�\O�������F�I��w��B'A��q����$j������YH�N
'���q�������f���O�I5��g�3���$�����@���������	L@5���&�N��wL����8��^ �8��.�'a��q�+�'i;Jqr���a���}��R~&��Hy��R����)��<�-�]�B %�����R����MJ�
���L�Kc)A�W-d�R��5'H��nH�fM�GJ�c�S����HNu�D!�J��D�fd�3vz�"~�t3}(
��"^���R�����(���R����u����Z�k=����^���CI3^�!��r�T��#�l@)��);z,d�P���P��������J�ZX����"=�NV��%@
����q���.r�}D���H�J?,N+��kD��V���$�]A#fN��d!0��{u��*D�w.�<�����5?9�JV��[)��
D�]�y���D+�^����i�Ng��6p�����'����(�TS`_3z�4R
0n9�^)�q}�4Zyi$���0J#������A��8��U�hp+/%���������[`�����3�����t�`������z���s7.G5(��,Y5����I!@O��M"jzJ��.H��H�C��:��v�LaO.����y��d1 ��GV��S����e]����`F��{~l��������?��'O2��O��B�������J��!!P��%B 
z @�r����@�a�@jO7��j���8��R|*TC���q����*�N!��g;����r�*x����n����,tO9�Kx�������X�����N�pO���I�"Ta��}E�������}���D��L ���6�|O��%�5�{Z���7���;H��,�
:��7�G[������pl���Qg�x�U�T/X�R��OlHI���{��9s�a�x�RB=a8��\��:����t�u�T�N}z�u9���*A������@��}!��tyv�?��OPO�|X&9Hp�S"nk�3���-���14�!�o���!���iu$������T�aH���q�Hv<j�d�/��9
j?F�"E8�w��� $=�;�����@kq7�ay�s,LDP��z�Hf�,���k"O��|9*�P�=��$��yu�]Ke�����y<u�n��	��(U�0�|�z@��-�W�z��}:�!Q!���,�A���a��:n�A�2��EZ��Fi�o�8�A�4d��z�����Q��7�p8th;z��h�J����]��Ac��J�rE&���A��F�����E�F<�&�jC�$��A�a�E��9e���UC:4��5h���#m�C#��'�h��E���$U[
]�n�����|�xc����80��k�.@���
	��4c����B�-�,5k�#�����p���W����,b�Fe��d����#�J�;���
zGm��^�[CmIoC��cH�TI��n�����l������	���rE�5�E��8���rp�"�����tx����Q�d�T��oh���j������7zo�(��n ��{*���d�_~����������O��zdo� I��`�_��.*!��~,E8.JK�#��.�)Iy�"�2r.��"����t��SC�6�q���w>pQ[r�s�<�9.�k��9.j?��Lf�8.jk)�9.���|�r\������.��<�
"�PY^O��(X�,�z��F���6g�����~v	����
�zt������z{-��g��j���
0�u>�|J�Q��^�[��x,a%GN��6`j�+!���������f@ff�6%N8����M������4uP+�������S�`�~n�(-��J�F=I��
a>o�+�Q�`��� �Qia1�e����E���������A�=iE��pK�"��e/$���5\T�^�m�(�p\�zn���^Tr3���R�.���7���;�DO���W�}�_�q��E,+5��2`�",��v�J�h7����w��o(��1�!�Q*K?���m<���Y���"-������4�3v�TC^g��Hs���=�g=�{�@EX��<P����0��Xh����ELv
�t�P{��U��%���\�
A��+������p�E�z~^����E��P�(W��������R��p��A���x��jx��_��*��8����74�J[C��R�^���F��H���>�R��F$�B^��F@�S�0����u �T����lD����U��?CNtT��w8k*���z���`/|���@w>jf����Z�����hf���A�X��AT=���D
��>8r��/��G�����BxVj]���jx[��g�/������/*����Z��:@O���Pu�S"��:Mr%3��ef@�.�=6����X���=�"ia��V@��>�����q�V���@jwk+��dI�_.���'�x S@�a��=p�*~��)���n�w�e�1i
�����s���U��V��ow�z����f|sT��^\�z)�9��S���rPh���qQ9�o,6"��z+
��F.m���e5�`F�����&���a
�d 8@����-@PZ������S3�zo �3M�6L&�+��e�@D,�**"�ZDo^��J�+Xa�]�aP(�j����j4�P	(A�L5�J��0{��/(�zC�4��������r0����k<���=���.�a�H��F�������q��C�bR�o�9%�6d�,��53���/&��L�P����EiGok�vM�������)�#
X����e���E������S7X������t)�hz4O��B���;�U��RD���bR��5��aZ�c��Y�P�K�p��|+����z� 5�pe@���b�4J��s������(U/��X�K�L��%I����g���B��Jf�quh�Z8@CW(�F2�j%�4jC���C#b�_}W��F������.�H��
����U$�4$�d��0��q:�R�D��r?��|Q�2u�F��^"���!t�3hD#s���1�L�Y��Q�w��(�_ii%��#Sd������y��J��\�qx^��U/0�������u|mhG��G���]��<��>@�z1�Q����6Q[b��@Hgu�)?��nG0�G��GX�,����@C~��
��;b������U�d�T�S:8�|����5���j2�4�����#2��<�-��A��5���0�=&l����R)�S����t��}o�<�*��_i��5�5%�:0�v��y���`�Z��`�r�F�
����F�����cwp�XTB~_l��dEV��a�L�'������2$�6`��P4��
�h����P���
yX  �fK�[4e������a������E�����6(�������+���iE��=��PCg?4�
o�����z���v���q��T�������PQk��x|��c�V;o������OL?���0�xd���30QH��S/������y�<+p��%���e���g����eW�h
�@`��dI�������`�]=�w������:O&��$"��ZP&n`"�&?\��Z��a!01�N��a"���&j-�:�	VQ�	��7L�^��AW���b0��0��`
��=�����qV$�����\�Bq����;/��g)%��n�/��zQ��)��:���0J-"cE�_/�!�� `�"<	j�����g]�QD����(�0�j]��d)v�@7��iM�H&P<�8��!��d�O�z�D��c�b6��	*P1yERJp+QH���z�������z
��z6����N���B��Q
��94~�l��o�,�Q�������s��m��� 1�:t�4�8&0.92a����<rl����f���( ���VZ���O�r�'L�/g��'�1'Fk=�6��
����#����
('�z�d1�1���1��E�m������u�s��`�J��]9	@���V�I�	g� 41����	�b��P�	��_���]8
���9r�4P������;
��Ri4��F�X��|�v��LB�Cw:�b��������N��p=w}?�x�n�w��=�al<��<����
��6����7�#��=���d��0������>F����H�����P���v��_�u�����Y�������p����^=��x�7O�� �n��������W��m�~J�.�'M��8����6=�p�)��@o'�VB�b,6kX�B�@556g��:�E��r���s�5.d��5�t���qhS"~�@����LG:��&g:1&��
��]_�g������Dd���sh��f,;�e3	m��L��� ������x���L��d���\Dz�S"��W[DsI��Qt�E<0e��OIxXc���4����?N�g�\�J����W�O���2�g~��C�W������e�.���f9��4���R��T���oj�I��
Yb�	 ���k���!��PvLCfk�g��vd�#SC4E�����.3����b���9�Pka�8��2d����c��8#<G3����0�	���x��X����M%�k'�*p(�]���p(����h�~����oL8Tj���+'���1�C5�f�}�
8�"�cO�K��?}8-����C=K��pH���.�p��A�c�CZ��Za���rq!��pH�0#n�a�����zAz+���}���W$o��51���(q��"���I���h�t0cmy��	5D������]BD�8�)y��w�(�W�p�����_
vP��V����n���x2P#g/{���$�����c/�7�T�@Qka`�R�h��K{Ei�� ���p6�n���(�P;�)+jqcr�EX���q�!wk�Kq7P�Z�\�,E��$@Q�d�(J-�::E0�u��Q�H3"�]j	|kh�0����D5�B"������J�
��Z�o�@�F�D��^���O��-% �/�8��v3�2��$}��uEa�������Z�jK�85�<!3&
l����T}P�K7����=���e����n���\c2����"6'#����-��x�]���F!�f@ 7_���,Lo	�����;��c$i�����9H��_
V)F��$�������6c����A�8�������b&�$������[��7������Q�v��(�N*/����g��b���A��};Lj��U��=�Ie��f�P�a�l�I�PL�1��>k������&�I�����������n&qa^;��������4`R��"��,`�����H85�$!�U��0����xd�.c�O�eN�}J�����]��2���*�)�i,�0��J��������JQV�}������h:�T~�d�J=�P_��������;7���K9��*"��\���q�=�V,���� �����%��t)���L����t������KZ�W���,�	�\�KX��,�����0c�%33�X
!�k/b"
�$Ix�6�!s�L����A����R��6<�O�
,��%�wK!�����G��T���J�+`)^�X��%��fl��r�J��~r�>����RmK'8=���M�B�[!P����k����������?,Pb�VD)�t��2He��J{Q�3x��� )��BHZb��K�������j+���J��gX]�6D>���S�R�����R�����I�j��(����+�(�T��2��R��/�F��X>�j�w�����:H1���������`�&�T�����7*;�~���)l���t�N�Q�H�k���QU�4��~%�i�tb��������:�I��^��M��#s[b�N�qd�U��$���U����l���{]�)����m�
D��&-�3�^���k������M
H������h��-Nj0��@�����QZ�~'��?���l�!D��gW
�;\ �#�����%��o������N���K��n��Uf��b\�C���r$�������u���H�e%nL>������d|lF^��,^C��.�X5��V�j\���Dkb%��b��i9�)c��)��CW�#�aTp�h(�x��.:��2�G�v�@m��y�q���H��Z�z�T=�T���:��T����!P+^8���*@�V;�`��:~U��F>�
T�rm (E����q���JdC���Ct&]�2&�P������������xp��0�	[Z@!2!���`H�����,�J��F=�YF��r��?<���%9G��6�����m�#ip($�vx?j#�>����
�j�LHh(O�.�h�A��qzp@�2��R�]�B�v������Q\�j�eUP%�C�q3���
�\�@�4d\�s*82�3)7(��r����XSR2���CmP��������OHjP��	�%�(��DE�@C�reG�@CeHO����;�Bg��Z����Nf��z=��@Ce��F�i�4�-��3���58�'�D��!(^9�=����j
�"��*�7�/'F�n��f�(GZ���ADT"f+�/�6
/�q��#"ba9�E��d����3C�������$����/����������^��p{�@Dm��=��U��rA�#I ���5G�`�����S����mA���D�����3W�!?I�K9�f����J�	�~~)�T={��W�r0a���1:v���W��R�JH���	D�q9.6�Q�|�% �Q��	x�7D"#�� �4d�[����i���D�����Y ��0oV����
���X�HL���Y�"��p5����"^E!?I��#���Oy��^�W�5�ZTZX��]"�E
-$�"JC��g�#�0��J��#��P+���H�;m�#�~�����PQ��L�����9��?GE�v����������dQm(l��~-����#�����<wt����d�lY���< J�c<�vO����)�A��E2�'m���,��X:�,p���Y/������q�Kia��M�(�����%s�T"&K.�C�,��9���J�c=9b����2�(�O��yU��
)�!�	�}������zQn���E=�����_/~�u���1,qp���A�+�$���� y�.����z�������&������v������=�!�Lm���7����k�s.7�T������`Lo{���0���L��Y3V��'`m��U;`�n�d���2f�z���1�LXj�0I>�\ l0)�<���H&������D��I0��d�9LJC��!���C���R��\AI��%��UHI���p�T�k@���P~�XP*��������[��X�@�������~96)�W���F��xl���r��V�u��[�6��eq]2"���j0����V����+�VF$gM+�dw���B�,P,v�~&f	�B�g�~+�#�NY��#3xHf����� �o�-�G[`����7�p�pj�����Xt��Q;_;��G�����|�\`g�Nk�[P;����������|�o4�����:���������<��=i����`Doy����Z�F�p�P`�4�S
�&"�i��lv{t�������b�B�p��=4B7w	�S/����%zB�)K�
��Z�}y��'<���
��	�g���$o�2
���VxV�e(T�k�)=5@O>�*7�SS�w��sJrp���R;=����\t8��^*�7��������Wg�;���������'Dx���:�)��������34w��|��;�s�`1z��=�b=(��=Zb�	���`2���#���/�l
���IP�nWYW����@'P�X?D��d�V��O�\=y�x S����H��y�U��H�1,u����A=��80�vf�d�p���oH(��(��
�YG��O-X��MZ}�';^��:��L������P�E���/�����4%�AC~9]�������n#����������1����7�� ��H�h���x���[H0����[H���:Ee)�h�O�c��&���c��	c�&�S�Dm�J���1QI�Y+q����^�J�o�;(��-�\B�u������z��T�AQ+�s���;H�vN�3_��|��@��
a�����q����@k�h�!��I����k�|
���ZE�#��Ee�%=��A���;�E�Y	3��� 7�S�(
����
�![��`��/i-1G������`11Dw5�`11�-;,K���4`
�P���������H�ONY���z�C��s<TO.$���<���2��K7��K�P�|�Z�������>f�8*-��-
�5��R���������M2bj��af�~t<;��w�Cm����u3������_��n�t�	�m�!��nSn\v��C�E����[xH+2���+�S`�f�TBJi3��7@T���������HV�I�1Q
�����y���;&�v�b����\5�����P��b2g���hA.w��D!by%#�L`�4�'y�6L�����3�!��"����!������U`�������0a�
�!Nn��h��"q�D0�)�7L�+�q�&
-���|&*A:'x����W[h��vL:����ka�>�&3�Di@���������'W QM[��[%���)�����U#_�
&�]>*�1�xd����7J	�K�)���@Q�}�7q:g���d��
p��F4eLzm�(M���F�E!�M�u��U���d}��!��VS3l���:^����4Otd�3���l2�{!2���`�#�*���c��cI^�
����1q��;V:*-�J
�~b�(�P����o���7��[����'u a8`\�z*i�i(����VH����e��y��R}��n:��|�c�G��c�8�S~���H�wC�����c���W��r5�;!�F������Q[a��#���Wq~^:�+e�(
���yO�����Hu�)�D���}�#"h���@D�pG�
<�w|N
��Z����K�@"U�B���P(4�$�@B9oX5�@��5��%�z�B=r*�2N�;K�H����C�L���q��O?�a/����*d���U�R>z�y���b�
�p��uv=4g'Pc�/�L��� �7k+�h���Y��',����6�*��h�q�h�����m��!�p+� �5'V�zF�
[�"���>��2�_0����'�*g�hS�������T�6����wm
k)t��M-��E���$��������)>��#a�'�j(�-�$��E���P02�2�������A>;���=����V�X��g��Q�K��j\���2:D��<t:J�-����B3����D<���� �C@������<C�d1�-��3��S�#`*"�?�\k9
W">YC@%`
H�{�@@%`I����J�%C�fC@��,�2���'����XC@�����T�c��g_C@�R�!�������d)���(��B��|�����&C��q>��h�UZ��UG@���m�3 �a�C�R3����X  ��dg(U�+��HV$��@@iE�W���l�9�[��w<PG�X��-�	H�mD"z��{�X����9������6"|�X(�������z*��4��
����k$GCa��S��X��@Ci���p�����z0(>]�%[/`�5<�.��rX�������"��DT��w��������/&����Gv�tL�����!#SGCnL�`�Hrc2GEXe�Y���r�q12��d�E����p5\F#�Y\
�\<����I���8.��-�Gs�.j-��q/s|�c;�"��Um��$�`�+��W��j�o*��	c�H/T
�`6�Y��tM���/�w��8u����6�.#_��#��m�(D���9m���$|�0*C�E��{��Q��6���`H�<E/��
C�l0����
��l0jC�W���`�"~�(M�M��<�F5��\g90j�������Q��w^N�S��_������,:r;0J�G���`��(�?*7��b�7��X:����"���4��0�h.�O�����z����}7O�qX.5t-.~�`P�bY�ZF��Ef�G!�f�z�6\Z�����`=������
 �1I'Ao��c�P���m1o����LV����6\�-�.^�B������N�rAW�y�`^��_�_k
���HqLc�Z��Ic�ri���p��"�1K�����n'�R�i
*��G�-�~�+�
*�pB
�J9u��F�*�Umv!���.(��2�g��q��(��g���]����R�X��%I:5�TB~�Df�8P�-����u&c,���cP�1k���?u���Y9���@I3���9PJ[�e��\�D'��(�S�LVJr��>��"���2�v��"�^2���[
u
�J���.�Z��j�#�R�e���J��%���1Z�@���9V�@����������6�l�/R�L)�������s���[p�<�*��M��&�E�n��GJ+����J$�!�os���1RY����7f�Hm�/��n�-��x��� �!��.�9�!wKi��9�o%=E7t��q���iB0D�a�z������b>��td���G��'f��N�����$��`O"������i�U�v�h���x<��r���[�Xyj3����J�U��8T����r�I�p<w����@q�x�?v���VqD���(9����/�uuH$[~�N��$��F�:]�@Q3e<>�����
�>I��j
�s#�b�Vd���������2=7�17���Dy���FY�5qlT3��y�-�')�t�^�A��f��<��e�D���u1�
�Z�#i��r2���R���.#j���zKRI=�P�Hfd�]����`J��DX4��[�G�Z���j�	��"�`5�2���F��	h���DO��9���u���N��yA���.�H��d�
J��
=+H�pV��{��b��	�	"?��7r�tK�9A�dj��(�T"~-UV&Xy��#�F����F�`����(�(��SX����$|��S���R�J�7�U���+{���![��������Z�B�/��{�j�
��k7�_	�q}4ZHP��^$��c(�_/��N�P�a$��x�f��G������c�aG@���
�V������)i{"�����ZDof�H�N���q��L�@!��L�U�c�������X�@) q��@-`FpT���3���0�@5xA�v�@��7��@�l�i���P�C�v�	�\
�z�4|�����>��x�|-���q��A	$
{I
LJ�9�<� P�a���fL�
$3���!P/��kQ��d14�����2"������wN�
�Z0��B�i�d�~Q��c��k��r�k�����q�< ��nP(���9��B����P^�P6�P:�T�������R��E���K�+�������E!���\�a�����$�P#VE��\68"n��j(��R���.�-�������H &������C�J��Di��}\����:++�)����$@���c�"8����� ����
��n��nE���=2�����T��(������3�������x,���K��"lSD�c,�z8^:.~������L6w����1��(VS��������_����v%AF=��j%Sd"��~��o
���\JC,y�pd��L�(ij+������ ���!��&����d������dH_#��k:��'9�haG��x�Dp�0��Yo������g����Z��j����L���6d�f�
u���PI(��������Q?�����^L<x0j��������)k��R�
��VN�����~���q���H�]�%B�M�mx�E!�fk�
#pQ�����N�d�������S�j���������@�m�Fi�o��(-��_L9��v���e�H*�gV���_#��	5�����l�(E���FR�;������Ig�F)�a�iZ��������r�)�B�W�Q	�j���_�2�-���Bo�

d�.%�|����������HV\��?I#�E%���f�na�(����l���qQZ2Y�,d�.&����`��k	��I_a�aC^��V.���K���w�2\$���b&��M.���O
`q.�<�E�"/f�4\�Z,�9�����_s-��ka)4�X������S9�M�g�80J��r���+�i�h��v�B�K��
Il�`��A4)��Q�\����������)��Tc^_�BI�����$u�4J!�v����T2�%�f����K��XTbw�J
������F)�7���F����
���Ig������t�4fHV	Isaq���Qz��ZAM����&F7ph�����a=�#�LW^2�=�R�����_��!�� K��v���Q>�?a?���r���(@��Q�}�]w����Q�XA� �D$\�qfT"��k�"�v�ZxE�NG5X��y�+���b����jw�8��P�Hn�@��@���iA�GE�b��VGE�Y���[�*fo�.Y
TL�2��wTT"�<���$���*���b��z���J����TN���/����=1g+�R��F5��rh���Fe5�)E�t��sX"��
'	��$r�����.r\p�dI?�tV��!Z��Is�]A#��wc0����kC��5Q����V�\�mHF<$^KC`%���i8w�S�N�0v���cKX������5q�L1b9�����kQ$�9
��"�������"��u�����"A�=��|U�h7�d9���J�JQ�^��YTO>�_�YT)>��<=J�+_~:Co�+�,/��sV������7t����ev��\Jn��DX^��������B>Y�,0�J��V�`�d���ADs~����7>��xpzh ��"�,�(�1�RyR�r;��K��v�ZXc���H�;�ED��@��2�&$��&p���*Io�I,�U�	�}uCA��^�m((/e��i�QPn��((��^�
�������
����|N
�������������n���~����dFVA�((���~bm5Tf�F��]P���� -�a
j+F�wq$3�\"�(��g�%�~(��(��H
Fw��j���e<�ZD����I��^Z����F��-��~ �*B5��%���Q��P�]���E�J ��r:sP=o���N[)O�S�O��������lD!��!���Z�,~�Di�d)�9��Y��I0�D��������E���-1�z�d�Q�"�p��E1ce�����\���=�H_�j7��JDJ;���q_�`E6X�"�d���fb�b����f�R�������X{���k����0j|��F9�K0
��X�������\��xTe�����?�����/E��F���=pI��S`S)��Q�V��Fm�h��0j;��{9�Q/��\y0��X�K�'��p"��D$x��"VC��W(bD����hQ��H"z>i90jwk����~'�d��~�80*	I���~����	!"k�T��F�y������A#
/��H��4�9��s�����(����OW���Y�����	R�6
!7�M�90��`��D��b���bi���.�������kN�����d��8�Q��dd���%<�����ZA���<�D�X����6�nG�pj���Z<&ZL)�*���:YZ+��cl&��j����
������t��]3d������z�U�S7]�[����qQ�&Dv������Lw�b���"8���'�W����z�_H�qH<��k��������R�%� j;��3<�P��0X���4���
���r�CmE�.�a�\�����J������SZ�=�� T�Y�C��\��!%'�X�t((�0V��@��Q8eGD=~���~BTN]���b����*%�l�C�u^�!������� �'��\%J����z��-����t��+1��#��;�)	�n���5E�����'m<�-yUPa��#�4��k��d4��������c Y23��� ���S��� rC������<�8H"&��f��w��Z��������P��XH�,��� �r�%�9f�
'�a&�{F���K��HQ
�n���x�T����Z�B����*"D���Lw���]�/�����w��8�F�"�	����"^�@#3s.jC,� ��"�?Y3�l�(
Y�t�Z�",���|D����3���pn��b
�sW�EX���o�"h�'m���(Q(@Dp�����Q�}�b��jn�
��^vPL��"@Q�v�_c��0�rG�K����W�,�w�����yO*xr��
,~1���v�3M��|���:t�4�8fp�5r]�l@�����@?��R��e�}h7k] q�+N����zo�v������A�^q�D��j]���OVL����OV�\-�'���d�����L@x��?��(�x@��P�N�5����!��^s������&,��K)���3��Y���=m���!��XI�P�u*~5���=(�
��4gt9jx������V��������S7G�/%�t;b�Z��u�������[����>�����v����nxF��bJw�#�(��v�j�y9w��7���n@�0rq���	@E�D;l��p�m���8�I~�3�.�r(�b]3�:�	
�:	���w(�;���%I�����_�����xv�U�S��
��`����X�C����$�v�d7�I�Z��r�t���A�J�0 �Y{j����^*B'�:�)�gc�J�{�CV���T\��������l&5�I��+�����V�^����8�y/�	/?e�b��2����4�7�f�8/�����P�0r��\��\�D<��@P[����V����%�[k��\+�c�Wc��HU���\�������R����i���a��V@�|X?�����:�i��Z�{��1p�
!dC �$�=��;a	����0�
�d�k��JG
,dC�qc`a"������$��
A���o�sM+�px,�9��L ������p�E$�8�I�?�rV8��L
�`�A����'���T��P���r"�O.��~58�P��?=
��2�%�F���#�B"Lh(D<��{�$����
C�;=�01x
A�O
yM� �P��~���e����v��d�,T}JC��bCC����������ZM�I@JDoU\p�x(�s�w=�B�$d�k���wA��PI�rx@��p���A�\��o�$�e����D��J�T�]�~��C��t���u��b���$�u�~�����X�3��0 ���:X�d���$kd�8���X�G��BmDr'H�FPq�!,��� �������aPXq��O@��((g���S�^����(���sO��9�s����%����a%2�JK�?)�0"��~���
�[�~3��O��9�}�\�o�:�I��7v�x��R������j�Crzx�$���E6�6,/^=�w�f����w��K��_w�1=�X�K7���IE:��^7��
��;���S��Z��qc!��[���es^3����G����/�y�f=A�Sw>,�7���C���V���]����C�x����Z<���Gi����2�9����
�P
�������I�.RF��+0�W.��9P�n�{�@)����2�aJ��59t�T6�����P��1�����X
eZ?	�X6��@���2Q�%�x0w����a�����%���m��V��S��������c��� W���xu��q�TB����������-<_��2o���S*kW(�[p��J��Mix*�KR�J�}������h����O.@�W�*���X��8�`��v0�R���
,I����<�����5�p�D=~1O~K)�n���d��6�(x��K�c�r�,qB�NhKXn��%�bq9e
��	y0�M���k|��}`I��T~�d!7����R1:x:�X�Fo�y,I�����X�R��c������R����^}58�R�*$����-{�v������bx��Q+^HL�jp��rK'����(z�n��P�+4����'<�����S�Xi(��B����7��D3�W����e!l�>���V�������x$��V����/�<���3�_z���3H��m��f�E*��� g��"���X"�P�#�<�,R�L��e�R��.��HoZ)��X�s�U����g4r�_�)����i��1��ixI�W/9v��9�����
|��G%W1n=h�(s��`C?��Z��CAA�M�V�A d���	V2�9a�@��M��M�X�{�
H�n4�Ht|t�dt��*!���J3�Ny������w��!%�N�����������Ctg��;eA��x'��n0ix!�GY�'��;9uu����q�T������tz����_-�w
�*p7t���<';���.]������|xg������k;��7�|`��6��f��R?��
?<�q����zG>i��������������O��G?�B�*D��I�Z����[�rM\
��7"��w���bF�
��NO����W���B�#�t�h+��C�^����zv��C��&���

�Ku���B��WjJ�������
�a1O� G>�~Tp��"nF����������!V����!0������qA��d8��bw�h��]0	S��@CB4���C~,n��=��eu}��a��@TC%�h����J>��[�������jB�#%���D;&������
��t�hx�����K���b�Z�BT��?J��08 q�.��fp$����`�A�aw���l�D!�a�
91���g��Y@������<$�!D��(����
���� �H������S*�lA���D!�%�#�$���e��H� ^���u�E�2:�B/ Q.�dx$�, ��x@�����{M;!�4�<q�JAR�l�@D1x��F~e����p�L.��7jJ�s8�\��vN�P
\7���[�B��7tp,<���;�#�B��*��	��if��d����R������4"k4(�K���� X�5��`�{�
+�N}�A�P�C$�f4�P����T�C�r[J+����1������H�������OhPB?���qP<�����M��18�O9~��R��7Z��)P������2u�Q�-`p�S#__'D?f�J���x��!�Pc��#e��"�([KO�J��$!|���6$�jt�;^��3k�*
^���a ��*�@@�$����9�(f�f�f�
�+�Q�~� �u�
-<b����jQ-R��Bi�d��:6�"�4��R��2F���W2-E�N[C��B��V��(�� QZM	3���c
�(�.��n<���U�j���E��0JO'OK��
� �U�h��U[Ht�*F2�b������p�bdc�GA
���
�u���#��3��U1�F��U1&^v�,��Ha�bGM8�F
�Q'��Z
#��%���R��B��*0 %PR.m�`�+qUnV����W�T�x��4�Fo�t�gF��(�$R��J�L��J�
(�p�f�����S�j�6�Tj�����Q<�B��L.	�����Z+T
!A��m	�$[zK����P����#�����Y�J\����lY+�+�Ti�7����Ae�d!�������VQ�D�����1����L�dS&�TB�+�O*���	�d@%���\O�P)
Y1r��HI�U���r�c%�b���M)V~�x`�N���J��r�T�KX�����V�:��z�{��3�V�����9Vy_��j�U��6�q����YM�>���Z����+#�j4���i^�FLx���Gi�hMs�~�IF<8��j?x%(E��a%�������L��+������L�����A@����(^���|�9X^*�z7��|�F���Fqi#��(�\L�Y��a�*�S5uT/���>��|���9{��`��h2W�Y	q����O����U��W�j\�RaB�X��W"����zJ����'R��$#F�N�J0������\^�7���,4���`��#�zh�q�ef��&`�B�N8���k<:���S����h
���q��|J�G��:��`������c��C���0;��:.0��X*����M���>��9�
������_	�j�GM�v��\�W!,�����:��q��������h��;���_�>MU��f<��=�|`�+�L�������k�MP��|�bPs��?�JsF��f$��������_	T/��vL#��3�j�D�"I'
"�V:�5vD��)�xH��y�����!K��I���=7"�Z��:
��}	��Dx�((����\CA�	��7_���bx���v���t'+�W#kOCJ�u $=�������c�)J-��(L����!�3�	9e�!�����}d� P�p�,H���]�6$�
D�Z�+�g�����y*Q����'y�sD�3aAib�3D�fX���X�$�-����c�^�J{^��/���(�c��C�[*�P����!Q
.%�~��#��n��
D���aO���C|���N����X�-����Z���gtB������\b��j+~�z&�P���oH(��������-B������~�j+t�
��LB�����V
+l��;:*	N����6T��k��)�
[$�������T���j|��QO`%G<y*0�i����o��V+������)���
�
�s����f�9��|7+�`O<|^�7�L�����/Ao�>%"J��~0���s�C~�$��'�X+��%���K����;����g-���IC�K��na"r���5$9�[b���qy�6�JC��aqCA0dAnCKG�f��M5��Q:TzO}78�PY_�~�Olp(�fl`���[�\?�R���dop(���vpZ���U�����^��������E���{��A0���tr���4��w�pDFV�!Yr������PucF�C�#�v<$;�ZXTbxX!����v��V���|$������R�+2YM�&7<��i�t�����Vd�Q�d��i	
������PO&���)*�1���t�A������3h8����^:!~3i~Y�������+�����IA������](+�W�W��o��_	�}%+�I3`QZ��J ��k���N�)�23�;0
	��� ��Q�0F;M��!�6����'E����Q��M�Yi�Y���rF�5N��d�� P�K�|�V��L�G���c�
��|���742y�"�)��4��Qi�~xQ����k����o����J�To����Gz!
��^�J��T�A��!T�6/:�.]?��@������*�X�Q?�a����9�Qy0'��|���	V�#L������Gm�=��a��$�����&V�&�2�!7���\q�/���\�Gm��������r�����|�EY�cta�Gm��������Z���	�:9>����J������+>J-�JG�����|T�M]��� ��8<���!��@�!��1B.��%���_b���v�������w�F�������K����s7�J	���C7O��8/�i��I������>+�x�Iq�.'0�O�.���-��F��]_�j���x��3�������^a�>������?������n�x�f��
#���=�S7,���(���t�u�y��	�O�?<M�n�&>��e�N�d�!��|�Ng�y:x_�n�����$���n��g��f�V�O���=r0*�`�#�K.����K=�Q������U��1�����}��$�]h!�)�<]�����c:���n���dx�>��.���C�����3���?]�@:�����d�3����:��xF�!w�����I��g<��V���C�����Ow<#��;���<�:8��pH�5<���"��������w�������J�L>����L�>WJE������:�i�K��_=��L
F����8{��|�#�pv<0iF�������
��p�N���'�8�3U.g������&�<����Ec��V����kr8C�u5��.{z<�����
�`�������5��>=�3�C�g0\�n~<�.W�_���|x�t�s<���rl�N��K��+���`�d��\�[!�g��5���H������s���g������f�9T}8�i�u�L`�Vp4����L*���}3��i�!w3`�\M�:����3���Lr�a��5(�	���O���-�s`�d�l��K��������J�E9�/���������tnrh�$�L~�p�'j����K��J�8j
Kw�k=�k21t�[���j�������XN��c��A)u��]���\$/���
�����z�h�������F_����iX��eS����#0�W���tM/(F��y�
c�����%�yXQ/[�e�z6�S����Z#i9m��ej�/v�00�f����Z�B��Z����@�B�0v��ae��'[�Q���
Ip3^n)��F���tO0�zQh&��Nn6@���i���
E�@Ij|�Z�G���`l�l���.n\A`T����w, )�����6Nn�
�`��=�&�m8�i����%�xm�T�Np&i�N$�p�l��8i6�G7����5i4��z"�^�����t� �������������<�8m�D�c:�C�4���A��C�4���uF�1okz�S��U�f�r���CiN�����A��	�
��<1���n�Pv{�%��J�%8�(/�~����T��o�@��U��:_���0�r����mM��~�Fz��yp�zj,�^�����������zb0���M�xE��z�P�x�5���
������p����On/6�~��x�I8n���4��n6��U���@=e��.u�_G=4\�����C@���'����z�5b�
��9����zR�o�g�QOXO���uC=G5G=�6����'�S��
���{���^���{P!�D��%��z�v9�I�\j��-j�}�wV����X�������Gkh�+�����\�J�������F
���F,X����d�\�>iCr^������^�x$�Z���\6���o��{
:��H���TB��@@�Ar�(���
���+�#`2^Z�(������h�����@@0>E@��������S��.t�&:
*��<7e�>�W	LY�]9�/�Bo��
Xg
��3T"V�*3$3Vv��M��X���Q��8@�(�V�r]�q��b0g�� X�s��`nF���n���0������r&�5�	��V�H����G���qP�����J�� ���@��z�J*�f��)(\���X9����Y�0<���c+�O�����~u
Y-`4����a��n9V����|�����m� B
 
�_���4�4)��F�Y�ym���Ma������\���c7���`����y����E��G�����0�,���!���3�#G�5����� ��s��Q��n���hZ�z�
BN������
,���	$TN�0��W�A�|��^d�F=<�F1�c��	Q��"@L�
�M.d���D��x9w�p�����|����J'���dslB^4�?����Q�q_�VP���5��W�6>�::jS~����=MyM��\��|�V%aQs���X��@JS�	=�S�� b%h���Dy>�j(@?u�E/�i2s��������0�D�I���"&Ak�&O^�J���T��LJ����g^0��L�8@*'��Eh��xd��^�C	���s�TfW��0g�="�Y���M.�`���<u�5�<�?�K�����/�m)�g
W����G"��Mm��QZ�c-�d�������y<��fxwv}ph�f��cc�F+��x�E���O��cK�/a"~���(E�L�E�x(����@C����B���93.m1���	�6���pd5�_,K!����\�M�P�S�F���KD���;:���[���M
�;�<at<_��Q���zb�J�c�K�)}��v��c����
�#[<�$�����J
��>�	c^~�=
����Sp��Y��5�:���z@=�!�.s���5�'m0!���� 5`28���HB��Z���S�D%�f��t�!@Q���M�\|�b�	��������|G��$�Q
/�Pax���l�aq��sV8���D%����!�z9RN�yQU8%�/��a�r`%�0���2���B�C�I^"C`����r�h`%c���-�6f�W�
��������d�-��5*D[.����-�F�a%�`j��J%�tF��J1#�ZF�|h��rRW����
+���X)f���Qudz�J)��$�9V�fZ�C$���c���,����y�rx~��j�����y+_x�
���\
��Tkh�����OK���\li���W�~0y��
�Cc����P�n\m8����H�OxF��9�jKt�}W��Dw�]�lX��k��us�����)����L�.v\�l�3��/]��lp8��M�u���Ie��`��I���o�;���bMJ���r0�4t ��k)�U>;o��.����9�(Lx^�ecj#8+�h��;�G-(30S{$�
0��T��`FO����w������``F��3�]_=���9�����`F��#�p�������������Ng������;�}�|��<S_`�>=�
�Pu��v0��9���L
���@3�l:�����n�h����

�7������^hw~ed�x��<oh��Z��������)��8_�oVgZ�
�����!���/����D��3�p��3�x]��x����Py�@<������^��g0�V�`����g�p�������K���f��E�a��N~8�{����g��L)������%8�B�
���L��p&�Slx��oT8������|�.�����Fr�������f���)\��F�������h�p($q@���4[4��m$��K�O|�@�������h<�q6����A�4�]���UOh�z^C/�'%h���_!M��hZ��JM�]
Tj�7��`x�����Ly�?}�O���_��gj���A]
Ox�7@S�s
G(WPh�����E���=
t��eN|h8��	
��#��ny���.k9�(/�.��H�t@#�I[�&�s�>|��v�HTOOh�ek�&/�~�R��V� ���j�+G��2/��LOx��
����9�MO_?�vI���H�8-��'��f����`v<zMWK�@Qw�Y�`���@�eB�s����}�'�2����@w�G2��N�g��Fpv���0��N���z��`��u��a0:C8��h��~g&�����	_(F�O����R�K*�w1�M��v�)�.�dlL�)������[s7���1f�p,��x	k�2��9������i������6S&�i4c�NLX���z9�	��nX&M����y�$���rHL�����!�'�z9��uF�1x�*�k�`��9�p�3xf�,�+���M�����������#��Oy��t��R�9=��ur�s�����9/���g#H��g���<���rR�~8l��v/�c���
���[�T55�^ �p7������	���#���!���
�������&@:| ���b��x���&
�C 3�@M��x(�����apV+��(S�j�B�<9~�&��yj<�N`lF9���$j8f:���������xb�\�l�;o�s�|�T �>-����w.ZO�}5����@<����&�R�h9 �xZ�*�I,�+E<4�+����@<m�v�i
nH|���G�du��- �u��1E������*������.����T��t�h���g���xz�^E�lB����>|@u���W0O���S��Je�^�Be�~r��n>��7\���^�P���P����K���:,\���Xo��=�6b6F
}E��'u`��
�h% =<�����y��h%��#����i|0K�c�T`�l��>T���}����'��,�OX�~Uy�Sy�o�R�'�'�o���,(%�����}��HQ�Q<�O�]>��J%�\/zr�\j�����x�N�Q)P�;�m|��W�)w�������Z����������<�O�J�B�r�02��!"�ND~���! -����giq�f���(1���;9���������W���yTp;[X��n�gla�+�s��������E��i���^la$`*��i	�5��9�K7�����2���x^E'���h~�hFe6�S��� ����W�5��N��K�(F��W�E��m���
������R��E#�!�e�6$�QN��i�u�zAV���+����6���F����f�Z�i!!)�1q���;j�`�
����N��1�N�&w`�"V�T��(D<,��/�7`�"�]O(�I����BW�m����0�������W�Z��i��7P��b�j���j+���:�\@Q����j�jZIXc�3����W���g$GEm�������M�)�I]@��6�g����mf	T8�4����v��&	L#-��u��z2��E�#�����$��M����@��#9��)��J���U�����H�������������0����r����7���xb4h�F��F	2�@�^��y��'4��r=(&L�94�~nZk��t��F!��~���A�Rc��N�+�b��-��4�)k��>�4JS�+xK%	?�K�(
����t'�A#�I��p���nI��
��{FD��<�Jk�FXf���Q�iYUb@��b������q�NGPk�(E,I`��Q�V����Q��t���Q=��]�_-�2��F�[����������jo���w
�2�/G���.�������_�3��D,�D,��A�q�^�RD@�1:��M����n0jC�D�p`T��'�TX,�D��� pQ�ai����qQj1%}�6\�"VD��.�\���q�E�Yk�����0��lc�E���x��$R"�5�@����R��e�.���GF�� ��[��B'W����
�F����5�w�����l���pV��%-��s7.G�)�3_��H
�6%R�SV5�`,�V55}�C����D4�)�j0�����N�kL44��U��S�\c���O���psi\4<\�Z���;�w>t4�5�kz:t��z�/���4�z�����,K[\��C����R���MZV�6�k7.�����)���Ju�P=����uH�����W�.S�j�O]?tL���@n����N=	�����=P
����jbx�y��F���j<�i7��������?P
&�J��k$�����Cp���������?�6T#���9|���j8<;#����gD=y�kr�/a�����Q����iR�R"��
��R��oO?�����0�Q��������M����FO�nG4T����������y"��z�����<C4T������8]��(�����(������L�n��"Z�|�o��'�������h���5��{T�6P>���~��4���78�Jo�3��Q�3N-�@���>[�M��V�f����^�m�&���sw4x:�c@����������TA����o�
��������g�G�������
�h��n��*�F�q�(��4�sT��e���4�w���
6)�1	D;�}6D��~�9�gS��@4�w�A��S��.����`x&'<8�����g}w��T�x��bF��g����
���������ox���x�/L�H��"
u����3R���������j�g0<9�����Xy�<C���l{�o/Y��=���o4����np&�}��k!�~r��A>9���p�����	3F�0~<�zS�0���-'��	w0�,��V�e�gj���n�+��|r���
8����p8!�'��{(4x<\�������I?�5W@@O~
i�;Dzf����	�
�pxil���4H���\ci4�i4\��A����������}���A���4�9&�8�}��c��;/A�z������iR�B�"�p��tL��tX/B����[��� ��&���-�a��D�W��tR
\S�/y�h
���mB�/�<�������l��
(�Gg�7t`M����!k3�
.�`��Yu7ty�2pC��5|v~^S���a�mr��#W`�x2�#�(�.��TA����&t	d��x�7�W��!�����n8���a�[��H
�\iC>5�f��;�T=i����Z���)�_�FTJg�&���e��U���y�aM�?#sU�����p��D�������T�p� 4��l�5��$�����G1~�<�����'����:�^�����];?������7�6�i��qr�
G6�2%��}�r�������7Z;���I����y8lS�� RcW�YL�wT-�/kA$5XI	�V�qM��k�4���1�M�p��e�62���)�In�?m��L��X��(s���@����T ;�9����6.YE
qk�D@�t/yt`v�9�D���s�"$��`@)�D?�p�S�)L�al�)�}���vR�BJ$MwN7���x_(���<#5��#k@$G�|��y+A�~��0�������3���3c�����$��pOal����p������F�	�i Q9��;A=�#��4��������k��u��,�6�K^(n3��� C>i��T~Xi@�AN(-�5S\��V�B�7z�i���g��z�s0:�6j�������:�����x���=m����?Y���������-�6�f��a�}��.2�L4��_����H�Q��A��X 3���T�x5�O
�����������������K���S�G;�I�����:�fc�C/���?!��I7����
1N�����z?�5��O>���J��?�x�����e>��X�����;K�3�P��]@��
���J�I�_��I���!�M�����cF��3=6�f�����r38���1S���y���"�.����^�`�
	�z�If����f������B�Z+f�5����35Cs�����Jg�H(K�Q
/!�|%r��~y�=0���vrD��� ���!�����[NGM�J��F������W#-����Kn�����sH�z�Z�����N�u����"V�hP�f��I�!\�W�;:�8,&k����d	�,,&
�AK���/+a4j�\�90�\�������gX:4&+B�4�$b�/.��L4������R����"�L����0d�F�@�o�d�����������(�8v�pTq\C�����bR���$��G#3�2
!��,����%Y��@Fi�m=��d �4e^�t���QHx�G5�tdC��^7���
����xpCF��W��_;.+{��� b��^ #/	EoY�L�Z<�lbCFX����������w���b��!�~;
���/0?��c��{�F1�_q�(����Q;����K7�nPlT���<,G%7�>sh"^)8s�/f�(�X�"����d�/��!7�`��hV`�D�@�@�qO�iAF�
\C�q�q�9�q1�N
b:.j�Z�>��,p������0/����3���A�EZ�`5\$����������\�g#�:0jW(���#�7Z,j�e�0Y/](�P�	��-���?
8�^���Z���qS"�i�F���3�#K������M=��A�F���(k��Wt��V�����������O�jPq�%k�kz4\DQ
i�S���us�����)K�w������^����*~�2��h�������~�O���z;#v������j��@�>�
l�(���-���}�?�|r%V<i��;TjM��Y�kw^���2�R�����s�R�{��EO���<���r��:\����*B���W�*�����i�t�b��^E_N]��?���v��t��C��a>]�V�g���b8\�V=+��:;��D�f(�'*��15[�)�N�����I�d��y�"=�l����==NG�S0;h��Y�=9���bfbx������@�`�s�P���p���h�	���CD1�'>=�}�|����3X8�����vyR>���@�f���hp�����]������L&
�/78S��j�������4���np&��n�gR����L���3��-y��4t���*2���F>�9C���o���&����(��GG�op}h����h8�i�=��n��@y�@���'�4=��F���t�������Z���'�dq0�����2��&��hr���
4�z�*Tz\!���g�4iv��^�] ����4�8]d:���n8�rT�S$�&yuhjxR��&��Y*�)��h�;����C3�4�x�j�����e�|���mO������L�~��C4N,<h��B���x�i�I��p�,M/U���g�������?^�9)�i���e�R	8����O�w���T���M+N hcw�Vf�ijd�f`�<�R��R��H���N����`	E �=pM�O�C/�g������:Et�60�r;�'�
�3<1������x*vp�;`�AiF�tJ�����~Y�"^z]���u��p���i��������q��~+�5(���'��.�pb���9N]8�i�)�n�t�rXSA��V�Sc���8%������HA��L� �&P�$9i�1YI�����sl����^�_.wBP6j���U��N
X������t_�w=|��h,�.�������;! ))>4����d|h8��<�#����~���a����~�<�nx:r��
��O]�~pw���S"H-(��'�0u�t��_�i$���O)��a�x��UR �������`����N�w��&$�3�y����*�0�[`�Q`�I�5P6��K��!��1��k�
�h
*$�������_d��vP%�7>��TX���b�Q��&Qq�S����z���W9=9�S�rN
'Z�=a�R��f�T�z��B��4����^�B��w�x��0�y���E�:m=)��
?@�X�U��!'@5������:��	X�����M�
��Ez�	iH�5(�4Y��)�',�bH������{���]y�	+f�,�
��	�K��W#z��4�����z�
��t�����<Z?�W����!�@<ir!��+����yh�_�^�j�����E���f��z��B"������l=�������!Ncl�Dh��c3��������V����{-��V�����$:`���Z���
E��_����>�j�*��.N�"������H�R{�����D����A���af<-���e�C���
�Q�B5���]����A�2�F�N�B��B"�W�
��z�
��|=������k�="N	(LD@���)O����,A�r{l`"���}Yf��:j%��&"t�C��evP�������R���iC��#��@8&J-�5�7�/KD2&
����)�c��'��WJ^f��Z�Di�{�&��,��x<���]�D1���(�����D��&J�� ��M5L������}��W��	�-GD��V
�>�+ *��;ZG��ksBJ>18$	�_�hVX�Ir6�&(I
���0bP�-���	A��*�W ��������������0:$T ����"�9<�k~>��3�k��Y��L��2Z	<����3V�*�B�#�2��jl��j��� �����o�k�'���=}�P��Ii}��%$�x@�0�fMXu=n@����D@_2P����X�S��*��^?}`���W}�t���:,\D������9�	+��^B'b�I�
�B_�Z�t��>a��d�p�C�����r��l5uu���
�����>%�t���y@�\9�>1���}3��O�����~n���������U���R���������f�&m}��������������b�_k	��� O�59����+R�@���l���M�+j�����{~59bCn��l0H�<@�S��ZBo��t>��n��d2z��u(To��f���|��#/���sj0<u����x`�i�C%��6y�����j0����/M���r�5��~b:�k�Di���C��A"�P��/G$�
7?
��H�j�A�2�����L�s�(�t������VR%P���v�C�+(��$�.@�X�s���4]h��������2���(Y�\����hu�I�?6���5��R�(�cL,�A-y���AQ���6K�l��Zx��N�1P�2��/E!�n��5�P�"X�$���`�zf��n�B���6A�@������(^��9Q����7C��*&�s�s�Wc����d��w�a���6Cjl���|���j���M:���A���[������q�O��T�����������x�u�����S�KWz�rH71�4z�~;q�w��i8k�*pe��9�8l�2l�|�q��h}����4_e�k�2�^�������Xg������Q>9M0�C��B���Pk����@�J1)��FF{��b=?k�GU	b�q=^8b���
FC�G,
���X�9d��E����!=���F�io!�r ]5�6�+b������gM
����u���X<Z������
g��x�������9��x1���X,j0��Z#A���:�>�Fi,���XZi��0�Rc���v"Ru����(.k#t<,Iv�:����V�<9�J��b�U������P��w�@*9_Cu���
�:�)R;�)�������Q�����:�* 
C%�!ygFC��wU�����O��<��)5�;"8:�\�85�I=�����[(�#+��Zcl�n�$��!��d�a�%=��1j�t�tX���R#�U���F'�t����b���K�0pB���	�8D
�Hq��`����9@��g]�h�&�p�b�3��gg
Zi���w�BWK�����M���n	����|�
UzG�����_:�X�'����b4��p��V�
�.��JiC���6�"������]�������f�N�T����5����O��,�\�r9fi����1��]�Y4�i/V�r(�v�"�5�9f������0�0�<;Y}��f}���,���+��Y�+���S~J��Yb�B�����k������Oj��������u���'�0[r���o��9h��Wv���Ivc%FZ���L��T���8:���\6`�E����u�����t�d�E���R'�L�j�V��i�c�A��eZ��i�0����K����=�O���
��_(Gq�.Z1h��.����W��5��?��+5�t������r���hE.�t�iA��w
WO�
�-�d��v���U��g���=�4�����%�?�su�d���\C�3�O�_�?�2
K�?�����z��=�p��j��+���U�+u3�uz������+k%O?��[y���s�J��-�.�^�����l�����������078@
���
���a����x4u�	P�fb�����D+��H���'�*.�ddAqP��2?���������D8����1G��&���$�59��_���3��j�|h1��F��h���O>����?P^f���!������|��Z2}Y3tb�vPK�O_�����)m�D���Oa���E�M�pH��8��9k�������S��it��AfVA&��p5��R���5�3��sX��M[�OKw�����v��[������BU�����Rz�����k�?�t��������,^�;�������O�J�5��b�`-�����R�n��2X��������_�*�%�+���}���aM�o��W����*���kS����W:��gW����r����n�VP�c�����B����~�`����"�jZ����4���?=��:4�����%��w���7h;���8 �^��$~�z�x#��	�H��
��k$����_��I&����6a*u�I�A�Ngd�TAm('LXVB�����R����E�kG����$��b��9����:U���a���hH'<uL�Q��A�.@�]
u�s�rjh�$Y\����rD����9���^�������f+�r��"��
tJ��L����%����[t`����
��	�2,0!I�\q,�%9�+��"�b���J,�|w�9����N�r�AA�_)�4�k��Y��'�a��sr~
$�.��^}HUe��rnI����A����rJ���+�I�+,W�
6�zc��!�JY�+������0��ob�o��C)\H$))�����y
endstream
endobj

3 0 obj
49540
endobj

5 0 obj
<</Length 6 0 R/Filter/FlateDecode>>
stream
x���M��L��	��W<�^�)��$ �@DH5@�j&�Yz�]f����H43���}�I��BW�s*�h�n�%w��q������L��z]���N�u��Y�q���?��.�����o��������������������{�����_�4]�a:������8���������_N���������������?N���8��x�������N�>.�q��q��������������������_^���?f���S��?[�r&�����������;R��O����{���~l�m�����6\�Wi��?�?�^�n��J��x��U����?����Y�p�^��2����?n�x�������iY��ty���u8]���2,��?����y���?�������/���{������<�-�a9�X��uy�?]��2.��?�p����%�2��5�|�m<���0W�������%�z�yI��,�9�-�:N,���M���e��S�����e�����9������S�6�9�����%l��iM�t���I�����4��sb�������\��1�b�`��aLd����a�����xL�� �������|�l���Y�x�}����������o�,;�����.������{+���K:�%+{���l����d��.�7��\�r����/���,
�����������7=������y,
;���_�X�y��l���_��+���^��w�Ms�X�LwY6s��eO7�v.������1����p]��]��+��^��k�~e/�f��$������Z�K����pYv�������d��cq�v���K���q{w�����:��{�������~�}���z��|���9~�����pT-���TU�[	�����U�d�C�����%,{������	��a���p������c�q,a����������5�4�j�=�=w�_������9����s-�������:B�������G�ed�������/�k��p8v���?�b�m�t{�~c�����g��w�7��[�����'n=��IYO]������h,<���w����n��/���t�}M��_�k�R5$�����O|�����u��{�9g�� ���s����q��8M������/�p��b�����m��a�]k��Z�6����?�I���>��h�~?p�[��(��l�u�j�n�����7�_�����h����K�����?v.��������rz�����ok��?�����u�n�fm?��%{�h����o��o���<�������d��57��N���
�$������_?5�7������4���G~3����X�x����D
�$��lv�9IV�(��$��gv_��M���v����'A�&ZY<�7E+�g������
��q
�kf~�ee?��;��Yl�����;�����R-k�A�#���yN�E�d�G�������|��YK��������>��w=l�����ot�C&���h��}��=����]w^�<m���m8�������^�_�sw��J���O\�u�������Ip8�_1�����j�{�K������|k�I��m��h[wB�4�a����4������������������������0bx��
�#+���[wN�����:���.V�����2����bb�nc�{����l�6?��s�h�D�����5G��"N�����;��>�U>y	G��Nx_����@��=f�!�V��77Y�-@�B��k��������Mu����K��{���u�u&��Ju�:��;�0���wo�����������7�����u��.����Y1�[j�X�#O\o�;�i�@�G��/��A�K��Ix&�Z����/��}4;�Y��pR),{��5A���*H����\/Q�#z��	�C�# �N��X�����:������@w���+�F�������	����u�����	#m�a�o���&��N�#����dn�i�����r������ k�������7	�o��B���)���7T��oYH��_@-��/ �-{o����9w�{��	�_Y w��6,��;��b]��ewC��}
�?V��[BU��s���+K�;P��/���a��lX��h�n^~v�Ad]�#���#.�y��d'��$��N����qX����s=��Fa�Oy���uk$�z���b�Yb�� m��S��m��[���hf�����k�����MQ�L��4����ek�H)��#����2���vgO�� ����k��1�K���U��S�K�.If���Z�/M8"���vG���b\����o�i����wZ���"b�?�����?���;L$��w��G�����|h��i8�!m~]���h�0�=4m�L���w�#a�pxw�d�
��i��������������&���������,�i�	p��t�{;����	��Y��>����_���e�w;���z��~y���������|�TV�d���<T�_I��������q7�d8M���1�U%��OR���<L�<��^���Js7�������_��n l�������n8��:���v���*������,��WZ��u��i*����0�r���H�o��[OAl���'��@X��#|��H���~�M�������.g��S����I�.��������
�o����lw�������y��� ���&�@���z������@D�=��77(,K3�\.��t���N�>��2��Q��@�o/S���}��~�>�[��2-k����[���UN)o����&}��aE������E�N��w9r��/��z�:.k�������J��s�o�_���/����HX1(��d��W6���B����!��)~�HT���9N������<�.:S|�����	I�o'����]LL��G���]E�����9!�*-
'a����vXiNHS���0��[�
A�e?����UK�^��m��1]���?�n�~��������������wSP��&a�^����U���I��Ue�����V�CZx�~hn6��=����H�o7��t�}���@��nVx�Hx<���N	��w���E l���;D<:FY���p������
TQ�o7���/;��Y
��u ��!{�k�s��[�mG��c�_������!������u&����PX�/7��������'�0�}��G����('�caG%bPX9��|�d��m�#�>~.\o��8�Y��]��N��B)���o{��������0~%w������R�!��-w���|�/��|�u�����.��}du��} Kx���\y��O��#53<NJxN�����;7DKw�5�6S�	AVw��!�W�A4l���Y�_6������r���HX�c�>��f6�Ck*gx�yXgu6Y�I��Ia���J}���v,a/�p����7�a��(�w ���r�����_a�K�Px!���}��{!������a��Ie�:&�P;������
I��Ev�$	{{�����2w�L�I�bMT^��
�J�����H������&��S.�������N��
o���K��n�����������)8<nfm
1S�M��O�#�V���r	CwC�U.in���g����x�:�������C����ll����lZ���eu�C�a�4)
^
�a����LV-/���������pY�/�����B���G-,���?�?=wwC�����o�:%"���:�f�.���H��H�9�}���H���B��f-��<
��1�7��zRV`���oRoZ�N�&���d����M���Q�_��o�:��Uj�ao[�f�`+\�j5	���:��5���R�N��)I�����D�:����c�>��V8�&u���Bw&���s�$a�pXd�'�+��%d.�GN� +�U�6�!���?�����D*ZS�R>���}k�]����.����jZ��� ���������'w4^����t�7�4�~���L�4R�Z�6�m�*�b����~G�6�	�#ao�HXwp^8��V[W���a��S���������C)���C��-V�b��Jl�E[6�a����NV�po�	���cw����+X8�>��y����2��a�Q�
��k�s���8��}����|s?�V�9H��n�e���� ��P����#���q�������e����g�
]!��Q�;,	{�aQV���K��%��aQ���/O��Ft�%ak�37��I��9`���\V���	{7�z<�
0�s��G�[�R�J	��bca�P�����<�����k�G�����=��nl����m|��u��T����A�sO{	���9'K��2�=T�Z��}���q�b�{>���dn�VT��67{CV_����
7���"N�N]�������Xhn&�e�i��H�o7������?q(���W�<@��p>Pg�\���tX�m�u&
�C���m}�{s��U�b<ua;e�����*�o���l��T(b�������S+���*�4���^Y����Bxx��N�B��Z�<�B��p|�\������i��� Z*u�@�	�����=���_�t��������p<���P;�n�]���W�.���:l�����!Z�I�O�ME�[B5/Y���}O�>g>����.���+�\�S��������N��9��6����� ��kh����������2\F���������$l�����e�8(�]P���oY�*<�m�}��)���v�����<�
�>��g`8���;�V���DUK4=�UQa�5�������pQV
�	��0L��%V�&n~	�~5\��s�/��_�����d���r����;��o���Q������iU��x��7�H���IF��8��_��}m�/Qw��7�
_D���m��h\w��hf������|����.�8��S$�w��� ��U
Kv�;?4��*?�V,1���m�N6��h��������m�9��j^�;'�z���|�Qd��$|DU3��5Ae���
'%{'�/�pR2�Z+:�T
���m�N�];����>J��a��������(O����I��
�RV.q�n��eg���h[W]v��;E����U���s���5u3��S4��������Q��7��,�4����?������M��b�!���u/`��8�������a��whX�����/�^�v�A��|N���+��r)�EF���
-&f�������L-���w���B6�2O]���
���A^�?/����A,�a%V���+����mo~IX928����{3�r�QX��w��Z�l��Ag��6\�#���YwN-���$	{�=(��u�������&sZ�s"B���������(��������	Su��'��Q�\
��YT�����u����]��������.��ON<�3	��������Y�b9����~'��jx ��
���Zv�� ����������T�AX ���w�U���b�]sD����\�JN�2]���b+���1cw��wB-�O'�����;!
�&����f�(�XZ!\�*������aT0����Kp�
�������izF	��"�5�<��������"��8�?����w��3������B��X��9N�{�PX�GV��S%��t}���p�HjxJ��q�o��J��v�#ao�sBY��M�Z	����N,��L�/ ���IV�C�������y8a�f���a���N��������$�vB��ot�
'a�z{T�.��.���1�S��
���z�;(�z3��D����3�C��u����OY�o���{Fu���<��6pIX5I�9!���6'�)��m���_�/Ym��s*[�qnW�Ie���P�/��[��
�#a�I�*���<��X��	Rg��s
�y���m���@�Q$w2M����\\���29NJ�����G��w��YX�t:<�U;�6�$�����s���o������M������vy>�_pS���7]��)
{7��U���MQ��?8�D{t*�W4s7ea�%K��� K���P��*&��k�s����Nw��~
��@�_�N�S����Y��C���MT8'��U��$���IV|��S�u]�Ig�Q�a��)���4�3��n�����{b�
���ZVf�;"��^����K����Da����$��IQ���?)2��|��#��z���
���~�$a�q�|$��^�����'#�5+n��
I����f�
AX�T��a�����w�G��L��Y9�^%Y�_�eR�p���EM���Z�.d�O����;�:�Y������[]�a^8f2L�m��Cx	+{��>�m��IX��*TuwCV��q?$at���l��leq��8
�YUs�v{�|����6W���89����1s�Yq(�zPe��g��a��lZ�7����v�M����LtbI�9����]���:��H�y����a�4����o�
���!5����k��������.��/��c���M���>�� +��+�]
�q��hlH�������M�.*��o�%�m�y��x����%��i�r`�."�t)������9Ved8$�Y;9Yo�^%3�^4�����!���Z��v�����c��,���9����������Q<j������t��I���	��|�>�����yY����R�}��Q,>;��+��+j��t������������4�d�:6������N�������� ���
�a���>��@/`u�yN2����h ��;��j�	��}�����?7�-���d��� ��V�xTI�V���9��M6=~��(������JK�G2��.�2}��������
�� ���|���D�>f��#��w�Y���,w������'�e�����N�Wp�#��\�"�2��H/T���@(�\�)\5+V�w��y�}�q�>c����/	+w5s?$a��b��hfq3~H������$��� \�|��$f�X�.�����������������K�Rv�� �X���,��+���������o^���y�����lf�[.Kf���V�V�zu���ex�8�*p��5��[�����G������E+8�8��)�����73�Q��^HFV#��y�7��2\��X�}��u���|�������o��oz����U�)�)w�MR��w�����������O/���n��G2��'a�O`�,	�����ja>KfVS��gA���f���������������]a����+?�>�7��}�tyS�%�%ao�,
�4�}v�)s��+V������1 9�=��~��{��V���E+��XV�����<�VZt��X�j�K������V�����?�h����hf5�!\��,�n������Z�%�����&c��oR8�����_�s���(��1��#��	Im�4dwB�:Su�C���h���G����3���=/�,��9��p9�2�o�Fa�]J��::���^�J]��>�!��)��C�������d[�Z��%�>D�{nx�����y}����[��^�I�z] �^�����a=O��9����n��P��p�!{�o��G����=���DK5�m����k�e���pMZ�7����YAU,������:�2Ba�w�����y)��*�WysM���	�u�<����u�6;B�z&�\����0�d�������!b���0^�l�ZI8&[������~�t�	��}x����7?�(���U�(?�����?�E�I��j���R�M�������i��=��e��X�i�Mw����DK����t8�ia�>VZ5-`��
h����bw��I���i��n8"����.���M�%Ao]�C��B����zV���r���a�AU�x��Q
�������GQG(l���MF��h��
l>H��^���dNW���r�+������/�g���_�}��dw'$Y���~rw��ja�n�T��3�_���a(0��f���6�T�D������D��*$�X��r��G����7�*�����2��Vv��X"T�K�;*����s�E�E���K��&2d��hN4��iSJAA4����p��8x�	Y�lR��fg�@��p9�������A��(�?���Y�@���dRt���8P�zrp��7S��u�������=����d�%a���;%
+��	�$a��4��ZX�k�H�������u�y'�t52 �s�Y������z��9AV9%+���[V�����GP�zM�H�U���g~fX���`��%.�{1>�����/���_��jHv���|�	�u��d����h�/o�I�*-�!�4�<8���L�(�p�y8�2p�k^������ ��R� ��%�I��n����6�ir�����iGH��W��y�
��8��������j�������Q�l��|���=�F���w������6���8q6�������qpY��pC�����x���+�����FKxcJ�yJ��|lPW��?�#��|�7p����mT�p�����M����K�3����,>�������EO�
'���g5��g0	S\m���������&��/���O.��u	���=�����*�B�@�Wi	������'5/� �������c>�����%>���0�>�)��������\x��PN�l>F��i��HXw[�)�����g�{+���PX�w�!����pC��x��9]����C�������%AE�������d�j?r�7QV-6<\�e�K��L��kja�pa��P���k�<,�%+1����i�����������jW�b���HX-�����r�~��Q�+����Y�oh�.�����dfw��}�SQ�����!�t�����a)K�+!���������q�HJx��#�5z�>4��:��X��y	{+�	W���i��/����o��_����^�(��u���:��������.g���}���5�����qP;<-����N�V��������d�^p:
���U�!)e8$<w����� x8$�No	���-�!���-0�9$��������l���������D��sp��M�IV���#��?=��_����HV�X�SR�}�I���{��k����V�YX��n�G����xf;��A,��H�o/��~{fV�/�y���Z������>,7�W&�������y��[����?�[w��?����f�U�kW�r�<��]�\�\�oz�w��p3�Am���r��z���#�y����G��w���m�Y���@�������/w���vs	�!#((���3�
�|��R�������a�������@��a����Q��W��x!<��9��$��/����[v��7VK_o����M��ZI������p��o?��P�/����g��Z�}xV2
p���F���o(�M#Yo�b��	B������S��U"�Z������egPx!	�^��������!��f�[�N����T����H������u8���b�|�]R;�>�:����t�
�
<\����I���A:/�
z�YX�=\����6��xQ������b�F��������%��:���N��9Hh>GW�$|.�X���X����X@����p�]�Ls7B]����k-��J6cBQo������i��|TE����j�*��w%����N�2,��JB�w��y�������������jDrx	{3B�������~CI���8g�V@��$��x�i�t|[ec�N;:u�)�����~�Yt���M�f��Y�
�$a��/(��|��|+��E����e/��b��5Q��3�������,�k��t7c��C�pC�;2����	Q�J`d8!
��=�}G�^(��;�i��������+�!������������n�E6�,T{��e�X���V��
���3�[�~����V8i���zVY��~�E�����:�~r��%/d	��~H��������q7$Y��3%�u-���:��hZ1V+���-�U�t�$Q�3�p�y�O�eW;x|0w���CJa�#@R���	��������6�m�I6��t��I��7�X�������=�+��B��f~�UA��*;��RXv
�	�������.5|�l����"G	��my�6�C�&���Q�y�����}��� ��x���2)�y�2o��HY\����Ty�L�D���XUpEP���6<�d������.0���(N�����i���u�]:�0��f~�������j�P8#�Vh u��RC7��F���������s���t�Y�V��SK2��9Q�+���9QX���3�M�q�$u�%�NV���w�����yg2O�<�������RBs4�'o����}�qxW"A�M	����Pca���p.�Ul����7���tN��Z�=N��,���:w�D���0����	��f}nE�^"!/��I�c�3��i~�qp��K��M�[,B����P��!z�f�N��,���������w8P�����OJ�5/C	���Ex���~ed���1
��6����K���[��] �\^����p#2��<��L��
�@��t�����6�P)w.V�������.��/L�{a2����0M:�P�Pi^��}��?:/�~�����7/Y�P�pHVm�I����Ba���pHV��q�d�|�]�Q]A�sH�#�?���6�#QU6�C� Ae?�u(��.�Dw9U
��<.��<��t;?��3�7;�����������p:P�nT����v$��U����wl��{w�]$�
m+������Z��7�?�������aQ����p=-����8��w^wH�`���G������~}������cl�,��j������P?������jy�.�yG/����6g����k��eoM��S8��u�d�\*�t��@a��e�>kw+N���������P�:�� PE�:�����N��,�
�������5\��
d����@T�R.��l��R��d���B46�x������e���r�}
e��zj�����Q�z�u���Yg1�>|eu�t�����@V�P9��X��h����/9���po$Y����lr�[T�z�NH���,u�L�[�Og�������VuN���'Y�K����4���od����i�F��w��Y������Eoce��}p��E����I���3t��C?��&���A�}�p�� �?6-��M���4/L��U�k���y�JW��\�9��U\���JT1N���B����s���Z������W��AV��9%�]��N	jU�k���0���j-��YW�z����T�RJh���"��5�%g���:�^������iTo��kY��$�Km�����bjS?q?Ca��m�L��_%�c�!QX��W8$
�f��C&�[�p���BT8Q����F5��HV����,2���� p�m�AX����-uQ����X�j6����z��}�T�{�e8_e������VLm�$���=2n2�	}�N�����@V�������G���ZVs��pZ?96j����_}�����z�Fs4V��k����4G#u�v4V,����we�hc��%���6���wYBw�����Kj	�G���j��{$
�~k�9QX�.X8'
�	��W�(�����-�������y.�>^���pH�p�;����������#AX�����HV-�If���Rg?�f�,V��r�d�x�8,�!FE�������v�e�����j���w ��nG6�_�?�6gu���?B	�
2P��=���`�:L7-~�����_.���^]"|�.�;�?������O�t|�����0����UB���b\���z7��4M�x�K��(l�������aQ�����RX�~��9�!u12K���������~j[sM�m���~��g����p��E6�).��	��J�c�������������{��/I����"��Sa��f��W�(\�<�g�%�����U?5�$��L�L��W���������/>K�U�_�gIXu�>KfV_M�Y�������0��'�?����IX572<���������/�/O<
��)�[��hv8"	���;���������uG��������'=��J	�
���^�rX���o��
I��n�����sV��inH��9Z�
�J�������k�=>��/�Da���������%QX�v��);�]�����w��4g�����$���N�~�<�'3����e��J}�d^��q\mNJ���q�e�������e?�K�e~��W������Z%*w;�u�s���j��O��:w�i��U��(�9%�����}����&�|U�2���=5Y�f�U��	_���0E�/P����{�&���z�-��������<��CY�R�0U-�n.�Z7���(�n�N�,�f5/L���y����y8�:Kb�Q@�I����]�5�������7*���������
�z+�)�!�����t1��*���]n��
�� � �zZ���](��]1?�z���7����jA.��d��0|�D=>�k�B1�2�,`�_���c�_R@����*��w�"Q��e�\$��$��CYG��PVuGb~�^����a�?J�v7D�>�d<��j�����]9�C�!U�����������ITB��t���$��C����a~�n��7��k��q3(���Zo)�����X���Kk�&��ql�.$�P'�
��]��\�1y���<��8���������>�����W���]
`
��9�%���a������l�{����Y�fhU!$p��0�����H���]�i�js=�nj&��-�����C��{�.d�J���?]5�@2�Z|is@2����e��I��n	��;�����-i�%���FD�*��!]��\�arw$������t��I���.���/���|��R�*��>$�wU�"Q�^@��d���M��n}7��t��?O��P�{*��fx����e�����=U��6�������g�I��tO��Kv-g{g������r��y'���?+��.K����8��O�>dk�����&v��dI�M��j�"w��p;��i��� �]7Q�v��da�9�� �u�n
����{_�z��x�� �~J6������ �Q��a����7�d�z�w�z������K��h���J����%Q�>Rg�g�����)ZX=B4?E�n��OJ���q�����o��i�:�������N����.�u��so�r�����?�/�|9�������o��5�|������r����Q�gI�i7���G�N�4.�Q�<������0��d��<������Q�MA?��%���X��8�7MO�?����%�.�m�?�����O�a<������[����W��%�������w0��?��v���v����\��*�����_x��������!UtY.�:�����o���8��+�iX�w���/�}��N�\��p^��8������������
��r;������m�M�?��������I8_�a��S���
<M���~����y�
��������u������d��0��s���szZn���������uX�����a~_������3i\��y��?�����r��<���?������}�:}O�������9��$
�O?���8=���2�^_�c�z�>}O����-D<����A>J����4N����*�2<ee�L��b����C/?J��<�V�!��|�:�������q���:MJ������i���r�"���4hq9����qZ�yM�9����Yha��o�)��</���Z�����gI�>�����O�����o���O�����g=����������Z����"_�Q���e�<c��\<_��|��%���i��=��������e�d<}�^�U�����	�7������<�+��/�0O������_�����eZ��e<
'����r:�M�E��4������'�G=�|&^)0yy����L������������5�x,�9���O�|[��������3y~?G-"�(
�/���7&�!������(�x��6��&��<��D�c|���t5&j�|}>����dA�5V��B���;��)�\,�t�!_�E]�\����^�����D��O-N�Z0Q�L�����fL�f�����+u&
jL�dp0QY_b���?��1Q�%&J��&*�a���)/������}���G{[�7���r�H	����zQ&��8���mE�#�"X�x�
����u8����)�}�����(�X�����������/h,��e��^,������'�+�on�!�G�uX�53e}���'��D�z��fc����^���"^��/P���Q
y���-c#�����!��:\o�*�=�_ji7:�!���I��NG�^:~6��(W�����m�Vp��������Df$X����l��j����a��b�������~�=��%��������.����B�����}i:M���"^�l�Z'����I��'��i����ah������*C%����4T�-w�6=���Z�9��"��,�������	X
c�
�����1����s
�h��t
�B�����sz��K��Lh�%�2��J��5XjC��Fj1��k�_9-�4�h���7��r0pc�K~�uC���;�����P)���R�M{��4�O���a^.������!rY/z��Z}���V������l�����:\�`���C@���+2���	4]��B��G]�|n7��m���6o�+��.w��y�o'
������4%O'���i���J�mo�4&���y��������
����p�1^���	����8_n�����>�<��W�I. ��"�����T��C������/3���[������Q5x�}�e���~m�5H����aV����'=�v:
�D��<=�+}���a@��u�����|�|'��)����z��jb����
j0|�_���N`���akP����%����h@
gN�(jb��7���8su���i��p���+����J5��G=����X�>]oj8�2����/�P#����6�r4~����O3h���|�c{���8�I���*�49��r���
�Q
����T�^�ix���w
����O�41���&4x:�/:�����@y&@���~�/�F��4m��,<}��QN|�K�����4x��4�NAh8u��4\w}Q�@C�S�@��]n�h��hj����M|�������Ms���k��S�MG�A3�3`J�L�]8�T��)D��'��g�e9(�:�e��C3Hv<���VJ8����a~����"#&�>���Z���Kk
�N/=��wu�����pr�d�O�sK?Y?���L�.�,r0�a������"=Y�i6C���U4��f�H��\;�����B�������Q����������Ih\�k)�G�lQ�Lj�a�����y��e��qrRJ&5�������a�t����Y�I���� �P��t�Q��\�M�dp���o�B��cCN�pA+t:����`� (����Y�t���*/��[�pz���#�m�����0�������^)�O����j����G���`��+0��W�^d��+�[�Of�Q�^��z������if�e�����=�6��T�o�f�>m���4����!��P{=�q�C��t��3�Tk����?�����O��p��U���^�����@�������<���.�o@��r?�@��:)���SWM9�7|�h����@�j�hJk�p����]���BgZ�B������l���|�����41��w4����-P�:�a�gV�.���}�HS$U&��2��7����S
����4`���q�g��6 	R��
h4���oa���p��i��P�z��+w���e�Zp
��8�>R�q��V_��1�v:�sh`�NO�a6�y%�C�"���j6�`:]m`�D�|"s�I���l����r8_pv�).j�h����dS�_9��hd����&�e��	p��l�&LI���
M���e�\�M��O��6a������=9��������y������4�.�nh�!�mz���@'��/�aa	F�/�!�l�K�ed�j�����e����u?��0`N@q'���������8���u��N��~|�u�N���:;���.��Lq���n����2\��,W���;k������EL:�����h�v��)�:s�	?��*��9���������v���2�vB��UH��4�v���\�]��9s�g��wj�oe�;�G#�4��p��c���y�/#��t�%&�K��4a�D��Y��xmL������bh^��t��?0��1O|Hgzv0O�����+�����[<�8��l�hZo<s
�)�+�;
�U$h������Hv8^>��X:���w,�U�����|B��%XI
�t&�Hv�}�������`�4�#��n&���B?2nw��\���Oh0Y��f�S
����A?�%8�h�C��~������&�1���d�;m�k�p��'m�����O�r%E
���F?�Pi����q~q������SzW.�����~�X�����;D�/��
?t�R�?5����u���O>�y���W^L��X�?m�o=���.3$A���a���(�x	�HQ�v��U���)�f@��#P����pX�hZ
;��e�7
	[EJ*��D��R_[�hX�o;L����Ae��5pj#F�1��n*��aP��r&�vjw�m�aP=OM�����$�	��O��GS�^`��'��T�%0�������yM+����1�<�0x(�;�P`bP�X����B�^+Z[a1n�&P[�����S��[[�hX�$�5���[}��TF,}�Dt���j���7Q�R������Ow���H@�k�]+v)u��;t�b�.���FAi������W�KmC���!���B}��T�2��X,����`q��O��r�v���\���6����+���j�j��]|��]P�x�N�S�nTZ|�f�e���W�1�jSC�f	�����(�,������>V�!���,�A���[�v	�k?����B��VJ�����^�y����I��8
��U���0�C2����C�Z�u(��"����ND�W�m��`�d����R�Y=s1������E5��(i��R] �'��a=eO��x<�u����[
�B�i�t@6mC�����b�D����#�!A�x-bV�,�(M���J�E���-�8��X�(bp�v�n��lG^(H��(D�X�\�����x�W�6�d�^�78���i!��-�;m:�������|%��J������#��<J�*l�`��	<�oezf*?����5�Ep6���l���BaZ��P�y���t�����Q�l]� ��[i
��������A���r<jK��\y�=m���y���������G�$��m��`ML�!>JC��L�Zb���d�<�mf�Qh�����d�Qhq�suiH�1q.��u����Z\���Z��j���G�.��!���fu!9'$������P�A�i�������Tl%���]�A��B��~
�^>S=(	�+;H�9m�o�����:�.��_�t����:�O�t��t�nB���Y�IY�Kv;m�Cj\���[ ��P������Gj|��"���;-���$�(V(G��r�%��';��FA��p+�#}&�a�H�x}��(���O�������8������(m�QH��Ij=E�B���=��J���$~>��4� �v	/�`�F>~�;��P��I��V�TN>����S@�c?�{��
=I>�Rr[�]��Tj��0��4������rb�#�!�('���e��O	��!�r��������l�SN����r�?8���x���C��4(GD�g�r����S
X3}|��F�p�7�N9_A9��b/�F9��b�%���S|-�fX�����i?��������vRM��k����TRM�������\qr����e����<&���K�E�8%���1���I`�!N>?���p�#���e�q��xG����zGy�8^�<����5�����SF;�����8-�����h	���#���q�i�\�����$�����nD��Q��1N{���q��+����yw
�3:�5���X��)���N95c�������f�$��y�l+�K��<wOgR:���5��u���u=8'�][pN��qA�9^��t�����2w?8@�*�s��W5��P)S�. �w
���g�Ru�9@���I-��s5� �gkhQ�
����,��� ���_��Cs_h�D�_���^����`f������1'�Fz+��w�����G������tQ�)�wJ�x�%`���8�����U��LH+��	���h���O��vl���Z9l�����^��t��9��v�y��D����9��y�<�:���R����-#������S��C~�Q�W�GKXh��]�r2�z��s�������/o�1��x���{�n��`����a���e�tj�e��/Mc��}����<!�[��;m��r6�I\�4�'M�Il�S&X@E��I���!)�<eB���1��bB�y,@o�y��-#��S����'�`�����c?�b��<)��
G�P�:�h<��:��x>�t���SQ�`�|�j�S�i���;�
��y0k�M5�:�4�I�������*�7��0��Z;����
��$h�����dNPOi�4Oh��&�\�4����k�8������M;`h�6���LH���pt�D��|��P@����n�����8�^5���5n�^�Gr���_�l��G� �SO���7A=�����;�N���*����O���Sf
���nGi�W�t��w<�����a�E�Pr���nI|p*������t:`e��`:����&P�����MP��	L�c��KL�J;a$�i{F���@���Kq+Z���H�V��P����L��i9�@WBr�����QO	��G��fln�K�J�����AO>}��M=��G��!O�3��ob�A��
r=�G
=0:?������z�^���cj��J�Wc��1�B7 bk[��V6�I�|�����. j����:��oN=�r�3+��s+q�V|#@�h1�5�%����UC�2Z���������A�f�4�F������,lA��/I���mU%��(0���m�`+�|0�;�;���o[�A9`�T_�.�[:����aPP�w�J�M�N��u�d�X���8�F��BT�l�T"V�:�;����p01�9���t�j�lp)F>6j;,< �
Evl��4���z9&��r�r�D����&��N�\D��31������rI��
��7�w*����?I���P+�����B~�R����,�w2��s���\�%���PG`/�4�F�`�!�kJ�g�����J�75�U�rE4
��hj<��nRD�o�Q�Ci���5JC&��,�W������%R��zA,�L�f���q����pAF,����|�.�D$���R�d�Ku8�V�����Mem2P����- ��J�iv�Ja1[ep���K_��H�!I��T-)��;�4��]�|���a#�^ �����K�s�'@a
�Dm2����<��x�
�� y"�u���_�����E!�U#���J�����L���k1z��/48JS�No�H��d��i�u�/76�aA�l��Q������>����@����� b�J~rm��:���y��7������N�gNmtJ��":��))E����,a��u��t���QR�xX�
��9%��m:)�u�d&@G%���()=�C9%�*TihxJI���PR�Y�,U�Y����%���<Ip�l���[����cM�1�
� c���Y�a%�u!�]m&�-�8\����hL�w�@���O�Nrn�cV����
�����/�=�=�����g�NJ�e�N�2�2HI�����S'%��7L�L\u���)�/��S,���c#�4R���[�)�;��H	:ly�IP�rl�������p�R����*���bl%���Yk��k��k��K�
,O����@����_=t�I��@����u��?�)��X�'�>juP�!|��8)-�6aOp������E�EPR[�%�Q�AR/����o��K����
���/+ �@���d@W����U����l�[� ��p<�}�����O�O��%|o�pL��(%l�wu����xV���Ymy,����E��U��c�FE5:?e��V�>��*���S��2�p�(_�<c���H�,Q	x��|��q#�������0$
!������,Dc"��|�1�2�HB��ykP11�23��0w�M���yq�y��`$[���NF�c���hdc��*��Xq���fd�u���DL[�0��:������U��j6~���TL�	"�{n#$����ml�����4�@I5�����I=<��K��m�����J�"�t>��T~�q:��i]���z�eM���b�&�p5�R%�s��ul�J����������%��ByX����)����,I���u�%�i�V�4Y��r$�z8 ���_X�$�:l���&
����;2�5O�����F8,?�H=g���Zmo)���b#*�s
+�-��SI��om���#L��d?�<v�j��[��r������3��B��pB�\_?P�|Q��q�E�e-,���U��-�
sJ�'$:��\�<0'
��1}i�a���)��9^�����/�A`�Dz�/d�8���o��h������0���uq`N
�bY%��a��c`3���dM�
s�����s�����B?�;�h�(��0�[�����r��9����aN��{`���Wb�cNo��2�r��0���8�)��$����f-w���bo`_�7�)���>^5������9��P��R�s���i�C� ����D��x�0'��`M`N
x���pa��9ZHn�S���
sB�'���)�_��|�+������9p���7���<�������y��w�r���b��2���ifZ�M��0��9!�a�4������l����>28������%�O���.��l���p��,@��)1���sR��Dt��������x�%m�MZ��$�pN��s���%�������/qN�"c�sz�+4r�+�9��RX)�@28'���j�sj�i����Z��0���B���cR4*8�&�����h
��s��M��5'�4��/u���rc@��!;;\����5hUas���t�i�$�b��'�;�����E�.Y��|wb�����'K������2�??=�T�����N)_J� ��1���`�
���Z�{Wh�$�|�{6��V������W1�O���;T��I�����o����XXdz���`!��;e�����	�I
�9�1x���o��p�S�#�ZP���1y�<����S�{��4��j@A��;�C��%2����MP��V�M����
y�0a�!O<�6J
yZ�J��T���<�w�����l����1
��/g�`�zr���z~:���f7vb�#�P�����B�
�z��0p��*�vJ�I��r������#�)G�Q'�����N:��R;�������C�!S�0��O�2e�#�w���_������>�z�V,���?Y�]���A��L9��o���7��Of������_��n�`�:��GcrA�M<��/�[�����y=L���0����Ggc����
snR�W�(�t����!�v,��W@m���u�prg����U�#d��@��d�qR@�x/ �����r8bZs�*�us�M5��R���N������uZ�w��<��}gl���8��Y�N<���S��,B��}�x�N��)�;��pz����
x�a=��g����6�������iC����4
�
����#Ko�@L�
�)~�����R�d���t�%F�-w����I�V�J�������4{p��pif���:�8��p;��Z���FJ>�@g���[D1��p�IVIV'�o����f�SSP:��P�~�0����_
��zW�Gz�����0�o��:=cyA�in����^����sW��5���{=$�t�I�1���O
��N
}`��!;
}R��T�5��eL�W����������Y�O
�9
?�GPGg94��I�����5���`�p���`�p����Mc��r����@;��oZ~bx����g�!'
/�OjN9w�?�����E��'��'~j�������}����
�j�4
w���=
�i-���n�Y�iHZZ�!���E�����J	����S�AX��knz�3����D�%1r�>��D���Ix�Y�"��kB�6��������6��H:jxi���(��J�iC��KZ�DX���*mFV�h�J�jxm_���c_x<�����.4�'�+`z�����F1���`<��|=J�(�Q����6�V �(D<���*mZ$��R�7h��t�6������Z��22���F���b���^m����F������t��#9g�O��H"��2��^��Hy�1YT
�q0f���p�J���ki�h`�"��iM���C���$��r5q����}��j}�H��;�O���u�7#3,��=��v[(��XT�`���0��Ig%�����W|��>����?���'y��E�F�%o\��������u�������iF9�.�(%<���^�O��a���
�Jz��<8�"�(L���G84���F44Js�����9�&�(��+�r��(��o���h3i;A_N��{F����h��5B}��S���t�BY�u�������r��������u��x��������������k:/��(��(���`T���*��6�BUz��)�E���1���`��(��F=����j���x�h`��H*q:A;���F=��QX�Q�u��oZ��Dp]���mg�:�'�(E<�%��_`�:�Im���Q�A�A��j0�R2.�'W���<�����.4S��s�E5��E��<Kp<�I�T���x���������NR������R���4�S�1m�C)��OR��;�����w,�#v/��T�EH@m��t��3������Y���gQoA��6�N������%����NE��o��A��\jT"��1	7*J������g$���FE�������ix!�T���?1;�?���Q�=�(J�)�+����mX��6}�z�g����b�$9^'|��������S�s��:�C������h��p[`�����7&���:�B��o�^�3�U���p�������|o5HY}����i�����y���O�'��6L7��v��Q�E�������V-��|������&��*�����=�51����W���m�	���%��B7	�ln�����|���������&w���
6���id�r[���(&���S*>*�o=��8K�
���s4��p��7��U��7�7�x��p;n�EYa��;�n��>�np��S����F{�y��w���i���
�����zg�.��M\?G�T����6X}}���&�����mjp��h��}{�6��y�$9g��@�6����6����T�x~���N�S�?%E��b�aC����f���mJq�hh�����6������k�6�=6t����Mk�MN>7hh#�����
���G�����6�\������������.��|�+��$lX��cSy�����
kB�1�A��F�g
#�������%��[B�n�v���g�`4��v���=n���4�������9���%��6���P�x��3F5��G�er���'	wN5T��jR}���+��{��/��`S�c�M�`���-��
���L[����1�6��6R��e�>�=�F�u��y�X���9��r:cP�w��Y#�O�&5����}��cM*����X��T�F^��v�4�p�N��|���^�����&�?l����F����
����4`b�����` P&�&
X���������cvU���;��p���6��)���p�=����vC)�E��s���
�s�@O���`m��9���+m�|���:�����t��w����
l�/��5�������:,G}�����M��b=��|O��lJ�h��Y�����m�K,�*��	�.��k@,�6m��7�6i@hS�Qr����lEG=�*c�`8��������:�x�tiPC>�?����r9�������-T�����^�Mi�b���M��EJ���u�(RO7>�������O�;�6�b���N�v<���n��V�C_r������.$�62@��mh�|cNQC����K{m����k�$���
p9��6�t�h��{�@>=�m/�W��Q"@5{��D��m�3P#�����U�L�����#�������CN�;�I��E����������EB�U��i�Q$�Lx`n��A�C��������B�sB��������2y�k0�^$�2!�o��&��Jk��&�62XG�@���:i��uX�k0a��jV���9����x���P3:"$�����e��s��'$i{�<��#����>�%����o������}�u��:O�����A����T���[����Z���j5������.�{�w�Xf���s���NZ0�m�g��3��v�Ix��#��sX��31���:��:�"��9�x<���@G��5�sN�$���� �Rp��x��9�p< ���o�q8\�Nx_)�M�~^�L���t����������o(�9�t%�M.s!�Di]3YO�:�L����}�Hy����Q�� ����is�8iD�z�Ss��#4&rd�op��J<MI1+��j��
�t�I#�8�"H'<8��Q��b��������zk�h�P-�i�����-/i��,;��������
�`��=�~}�6
i����&��4@*����Y�����[�o�A�B��h�����o��z��U��]Zi1)�{(A0��O��M�}��)�K������6H���������p��V����Y]��j����fdM�{%���Xh?���,����cy��D����
�x�~��SY?^D�Z��S*�k��	�5����'����G>�;5�t��������i��e9�x��P�R$G���NoX�E���|'+@���)�{mM0dL�
����ma���(
��
�4d���-D?4���;V�Q����!b�5Q�7w�����+�Q����>*�YmM2���
�V[3�N(�l�5�y$�|[mM1rh���f��,��$�}[`Q�xiX��E����_�E5�R�K�]n�%������w0���v=��(�Q�mK��p�����O/���dB��
�t2jK���:���1�)K�6�)_��q6����.i����R�[���o���#y���xi2���p$-&��t8&Z@���c6 ������K�c�[P�����k+��AIN�w8��ZIJ�yL������L�;E����hh�D�@#Mw���G�;������y��W��NEj������gW��3�k~44
!?������$���Q�r�t44JS�'�"��&|�h�5����Y?0d������%��NC#�Hz��3�T^C�1Z)R}��hCF��hCt��F�������Qh��f�\���(������G�b0}�c�H�����
�R��q��L)FT�]B��h�e	�%8���
Z����*��9�<�x,���'�k���\�����q2JC,#�4�I=k?P���+��*,��i��
Y�MP�1YS�jAW�n`��L����;�c��%X#�����
�0?8Fp/5+��YiV���
�p&�o��p?z�
�
�����r�i��l:R]���� :~0���g���K��>I������
rw9�&Ij8T�Izh�A��%��qVTR�Yz�`��:��j�
V]%���O1xr����V�jm��z��D���w�gF�
���%�N��D�P���X^��-�H�:�i����#�@���sK�@����aF���O���p���w�@�^���T��o�j8v��-��{!::���B�zxr�4X�\���<���i8����x���s���'qG�o���I�7���$��&�[��n�<�9�P���M=E��H{}��`#��F��5�����k����������A�ns����qlZq[��a��FO�$� �����^;~����Z@�K-����r���RH�Jc��@�zK+$�����%�{���@c�e���8��g_SW ����|�&5��=�t��,����a�������gz�w��a<#�46��D�^�������O]8��x%$�jP���+�S����5|>�/����`Sx�������~��&g�`
n��)U&U��[5=�P�M=a��N>�B8�v���^�<�u:���]aV�M��>1�����A~�=�_��4
�IFN���	���9w<>)�8������9������U��6�N��sd������9�
�l��>������0��'�Y����k���t$�[��5���=�N�8�n��Rm�:�@X�;P��4ub�7���u�7o�����w9�>1:`��b;�N�b��Y�	��H��Hkp+�����N	�|Hz�������;6�!���6����;^8�t�if�ym�����xh�\��9�x��x����$3'^�imR�!���[3'��$A<! ���{;x<&e�h�
G��(���p:�t�����=�PO���_�B7��*�(�+
pO�0w����������<!�n�
:��'�Yf^�L�)h��&�`8_��&��]q�WA��4�I�s��A/<��t��
���
xr
��K	�$��`q�i����+��X@���C�&��	��Rzz!�D�Dc���>#)���R�6��i��0���'��-}dt O,v	y�a<��P�%���c�&:���'x��zJ�-}:?��&�YL��2a+_��TV�-=��&����A�L�@���4���8=2���z8PR��'���J��"$�7��b��C�H��k��_�����G�\���
@e��������~:��5���w�_��'��_�|�'���<�s��4��J��R�����q.7��� O��2���!O=��"�S�)���X O�����<m��;�@�6����:�x 5���� O�y�>�I����<@eV
y�'�a����\o��9��G/�����_��tN O���8C*@}��dS���V�yz8R�����y�|����F�f
���~���F6z���4��a��WL����9)?��G0���w,����SlgB�.,��&Pun��@A=4R&�z(���p���S�4�JA=\�g9����@P�_�������qA=a��r�����`���P{��V�����%:����}
/t���W������r���p-��<���W��+�<��z���5�K1���y�����UGF���Ya?���M%b��a�^Eu����U���H:K���	�x��L�tPk5dp".m���(TM}
Z�Y��-�������?���1�?�b�^>E|��8����Zg�c23 �����f�5�k
�
�����qT�{C���
�����C��8�Pc�)�Bi4�<
?{���G��v��b���I��KK���vf��.
�B��J��=��T�"�Wrb��2c}��aE-t�VR

�^��f�o{AD�+����cTj=�@���DvN�n%������A/�D�b�zh��D`5�(D���<g"{7+
&�t��Ld+�B����CQ^a��p,���(c��T����E1M�R�
��<��N����m�M�)!,�����H:L+����������n�<�>5���X�B2��"�x3�^��$"�4�	X� "�GX���6��E2�#����B����2�a}P?��Hn�p�c�9>�*�JCF����?c6�T���(E���p��g�Q0��4ev2j	�$wi�����^q+�����[�D���fD^���';���U��
S��p�n��x<�u�������E��&QX6|���1L%��LXT�aD,\�:���
p�3�]�����������s,�_�V"���I������m8�Z`��')b�X�s�m�,}��X�����q�E�"9
,jv��
����5�CT)��a���
��������0�G���^�?yr�Q�o��M#G��i���]��M��0Mz����V<Q��X�&��mpL�R�����l��_��1����y�����:�Hm�VSQ�~���VX�Eo������
l�$,��?���:���-�o�G��uX�51�4��+@)�o��k����p���1��|9����<�3�K!��}����$�>�1U��p�%+�e?R�S�b?�1IS*Q�u�pxS~������g��g�3�p,��v��X����V;g��2L�j�X����������q���eNM!�u��r��S����r;�������AM0&)�����I�1�5��;NHP�f��?�&����?AM6fd~;5��+�5����l�����S�l������������6j�1�������@��FMm����Hz��0�������%aj���\[�l�S]���O�90?����6{���r��(������\l��.O}_)"��o���)"���Ce�"�R�7���0��m<A�����l�M���]�e���<����dV�
�nI��Du�,7�`}[�����-7D��e}������}��x�;����>?k�����P��*H��[�����X�����lK����N�9eC:b����5R��f���GS� ������:\����sj�VVT�
�)�$/0��p�c�
��;�9i@���1�S"�cN��9��9���v��k��T��1����cN�pD�cN
��`���L��������s�|���������zsb8����(/s#?���1_����4{�����KsZ��
��r��Aq8���u<J��0w<�����t��p�w4�����bs��/|����[>iUA�C�`�-�?����o��h����aY��@V�-��9�So�����}��X�%	�q��@na`��R
s�����Rx�+����?��s�����|~��F5�R�M�y�)�\�b�ja�r�sSH�X���^sz��8�^�Q�x����t�x�j��.����!Ni�Q���O���o�����d N��pg� �~p�}Z��S�3��{����T7���a�<U����������u�j�\xZkP�O�D������J1g�Zm4�T��y&_����V�f�Rm�v%�TL�\��O����uXo���?\�f�:�.��H����e|e�����%k��j�c�+<��5m���iZ��M���cMx�����&@�����U����666�7�D��ktK�0���^�b|c�**�&P��NH*��M?�+	���q<�~������P���]h@A�_h@��K)c���j��h���KR���S!�S��PO.4�x��m9HTL{.��v�"_��;!�n��tD��Ni`u��cJ4��wh\���	�����W�R�w���h	�C K=p�&P
����c�w��z|�.�F�$��9\(���Z���e<�����#���$�'x���<�:�vwzx%�������I����[9�����O������r>L"I{.��Y�������h����_��L���&p���4��!OzZ�/����KLH{.%��Zz�
�v(��s�q��@$�A��C�C_�����)(���e�?]zz�$B@OJ8W���
��COx%����/rz��/��k����}�R���y�j�) $���]�?��V���r:l��v]�c��!�u]��PezR�#��H���	KzR�/�}��'<�Sa@O����j�KL��.%&��=��<*����M%)�p)�����U�z�K`g�Y�%w�=9~��j@�X@�O=�Z5�������6?Q<����
y�w�rI�M�
y�a+�������m�nG	Qy�%5��m�F O=|��$k�$5���r���C�w�#O���8�@�jylB�h�W��c ����8R�o�����<��}�x�wY�<����S,V�>��+5x
j6��m�#O�`�R�g�-��U��T���uc�R�T9T;`�2O�=l��xR�JZ�^�B�|i-�|U�
���o���0^D_�����N��
�"�?
1��Q�X��xdx�Pm�'hI�z�P2������!�m5C����z�P����~��]����bP��W%38�$($���{���������X���ok��kh;��{rS�(��v}V(�����AeC��4�}���jX���`�w��r����NKj��eQc������j�����=�8\� �����I���@%b�`@�������v��;���)�
���:=�)�
�T���Yb��:�[�0[
J;&+����&;	�_n��P_�I�5��7��<�r/�������a����E�������CP�����~�B���4cI�j�%Xqzp��(0���v�RA3����{^�CX/J����bx��V��"��DE�v�|~��a=�v�@Q~X}jL<��*����,	�
;2'������q�QY����<�x�X5P
���1S�i�KAAC0bL*�����H��b��'�����>��2�yx��`�CB������u��)t��D:�#8��&tt�������������VBj`g�Z@%M]�_���%���=�*��zW�'�-�J��<�����4
�t���F>9��tXm�;���mg��	-�m%�~�����8������!��iM�j;��z���t����%�.��^wj�J�4JC�|��
-��&�"z��rM�����9�!E�w�PZ������P�$%t	�!_�)��P�a?s��*JY
�������8�Z�H�+P�&�&"A��$�77e��:L�q�F��z�}�!tk!$l���#9�'4(*!?Qb,=#��l�{����@S�a���cQ����u)�
���{���} �![<6�,3.�!��	.��$J������dTB�#�W�G�llM������4lTB�NC��6&/�3���dec6:jC��RZ�E�W)EP.�Q
.�Q.��D����r�bt�&C=2��V�@G�v��[���S�J�$�H�z�R��N)Q�y,���$�<�%�-~��9�Dc���I6�P�_.�mu'^�$������gpR���b�z���^������1����AJa����0� �1o�}��Y�M��2AJ!��C��%;���M_�)��6R�)��)��)�!�6�, H)�����AJ�vTH)�?O��D�FJ1��}$|
��D� �jG���6\��"�DD�$5��*I������<������!���P������1M����y���i���vQ=[em����
����'t�����W�N�A8��0�������0=i��O��2?����9I�����Z����$���0�xHk5��y���gq��pT�GI}���P��WI�W��MM�-���6���{��r�*�:���y�BL�Z�BEm����"������,�mb��g6������������im���WiZ�F����y���3�m0Z^���[��������#;m�;�&OC�^����h#���y8�����%�l���Eb����z����3W+
�����h��x�|<������6�0*��JG$�8�!s���te�(_W�2:����E����d�������p����R�L*<6���wk&��A6�x����&�/�IdS�'m��l�}e�&��x������� ���
�l�;:{��M�@� <�z�l�9@� �x��Ys����%ll��z�A��&��� ��5X�I�:�`�
�rx� TO|!�T
��VZ?JT����N5=�����U��j���W�o��4'�%\SC�-OZNT>�a\��v��|>��t����k����s���0�_����&����M`�'}���'��6Z��dpC��g�7�}"6������6�/3�4C�ttC��O�� �e��K�5|v���B&=�<u����/���es�}��s
�����K^��N��kr�)c1�6
��a���M
M��5��'?��L/$#X��d~LA6e@Rv��M0��#��g@J6i���
�\�ldE.�>Z�F6���eY�
�>i��`�!z4��_L�p����g��M�0X����~5���:���M�N�\A6���N6����j�5���~
?59���R���|��WnpMN7��k(�\�^��X�]���V�%k���{�����?Z�!�iL��J`'�C��Mi��:���s�]��>+c8���vN3�>�]��T�XF��N��2=��]�d0z���2�����f������#�8J�N��U2���G�.M��b��m���t���JS#C�J����,�u^�Sj
c_�0�V[�E�l2�2&�������k|�^�I�$��)FPz`L��V�8?r$(U�A&
9�,HFPA�@���e0\��i0����-[$�<_I5O<j���px�<R$Q����+E�X�g@7=�(t��G�7���oz�
��Zo���	�Y�j�`�A�)��xZ��&m��a:N��H��X7�	VOBS"0'��^'�X�&�{�@�L���t���6�}C�
�=�\���
ud	��
`�����}C��pA�U��H��A�7w_��T@V�:1���9���t9��<4A�����'��'�S���<5��y.�	]c��y��3O}����7�v��	/�����HP\�(�y�uO�5��Ej���"f:������%��4�N���yJ��L�xe�u]��'MH�}�y�
p���S���{�d�����M�sT�3O�wq�I�"��<m��{�y�U�8����n���yZ����`�4!i�������1&�<9�K^��S�DPOH�M�Q�T�k-��z4Vyv�����3�����g�,��5��L.��r�	�s��O���(����t���-3U�T}�"����������4��`�����F��1�'Wb����	F<�[��?4�*��� [�+s�;%���p��>qJo�|/��m�X��)�xt��(1"/MM��u�JZ�
���(���3>�*/*�g�g�=`�Hg��Ax�r*z�	c���n��=���2,���>���AP��I������e:��&[�1)�����'��4�.�ty��4ck.�<2��j��n!� ������Bm�b]��ke�R3���Q�NS(�:�Y���PHx�!+�y) ��Q�����s��Z������B6 �`Dc(T�&]|}?�]���V?�BB�l>��L�dlCk{A9�������������4��s����A��������q+����cOO����e���%�u)��:5�����(��x����Q(
�n?I�"������B����yA�Z���&�J�#����_�!����-6��Y�M\���x��DuZ9�Vl��Qj��B[���6����{�1���I*-�`�2����c��}{��
����u��m���U��gz?��������(���E5z|��� ������pbPpQi�����O��6d�j&Yw0d�-�.f\C,{8�l����[h��\Tv�[���t.��,��-�H����z�E��c��*����,^Jn4��������sQ���cg��w.�_$}���"�5xp�\k����uX-�9=:U:TJP�w�/����(����RhNFps2��LF�3~����F�����P�en�v4���,���tkP���A�c?����Fe�w�)�5�_�-kqvd�������3���W��b;��*��E�3�C��t*kA�n�O��G<m��u��7C�1G"��o�������e�ZX@�It"j;��7�we�w������YO;@����x�N5?�c�(�K����O,n(<]#�GO��Qis�������p�G&���b�c���=H(5��%�;
���~�N���,��n��4��e�Q����6�t�8K������&T�aM�T� "[a�
�B���-o�w?�O[��!���SQ���+���v+�-�Ei���l`S&�����72J-�$+9�H_����J~�����Y��H^�i�_��1�z�r�U���RoJ��
�����0_���_N�8M�q�'�����������VB�K&Y�%9��Z�%Z��$�g9)j��*�d)X�x}S9��g�����W���-��aY�n���N=I>�����P����J�V;\��z.��z2�0q��������!��sQ�&�6�����{�}��W�g������|7�@(��r�S���/'m���K0�� ���>�/?1|9��u�I~[�4�{�+~�8�����/9H7
�a���tb�����:T��3���X���3;���y
����V�R��5�)�y���v��	�I'4���j#9k5���8�7HGh��t�e�A�#����C��N:�@�H
�I+��5��w��@�6X�_<"V����|6�L6�������0�
r�����X���7����PaG.���8��%�b�����2��HD��S.��{��tHD(Q6�N��.�N1��l&�w?�h"F�t{�%[�����pf�����d1��tK6���6�v6��@��-�(�ck-��bZ�\8u�<�$3Cg{�	Z��>�y+�^�;������C^8���q.�'.������d��F��������<<��8c.#�������������R$y#��b�G#"���U�� ��n��R�7��:���!'��Z�����(�x�W<�3��g
��`���(��B�g�JNDXn������\������"�(u���^u"�wn�D�V�K�C�}���#�W�(�s�U$����������r0���[���������-��p�
�x��!A�i/<Hpj�E������o+e#���d����B=�?[t��
�i��
��LB"��DX���
�^��\�(P��H7�J��%^�	&Z�����f�B�����B�#���\B=P��������P[���O�
���zzrZ�$��K	��tVi$�c�%z0l���
v~d��~bsp��<l��/���#����=����J��(�s��B�l��9����JK��;���1Y�uF�U���6J�B��7p1��AX�oLD@G'��U���\9
�k��F�,��P�p��B�v����8
�Vs��B�3($+��CC�z�J(T��v
���03%P��(���B�:� �(������#��rp~::�����h:u��Dc�#K���rK������GO-Q2��wz�5Hx2r�����%_��(2K���#C��0_nh�����c�-�y$g��Y�
�64���� �����V�t�y%V���e|o{Jt\��e�%�z�P�#_O-�2���C�F���&k�!l��u!���}:-2K����L��3G%�������,%��x��R8+�C����rR��[i$,�[h���J�����'.��>G��J����Q�������J��ZNP�V�"���j�:��Gr`j\$c8� ��z|%5�62��|�&]�-��-��06�NF
�� d�G��8�yX�����yv�/�8 ��W���B����w��H='?��Gw�2F�1?v7�B��x�w��(I�<xj��zm9��@I�����R�&��Q��Syg�[���:Ki��\H���+����������%��
`~U����B��ut5')�Le�k���Li�l	zC����y������I0�2���&,�#)?���~�^�lI6�Lt�[\7`����J��4`*M^�����B���5�M��R�K��e�0���$@
�������IgT&��-�rYJ�
�����%iO��K����������*'�i��D���T;o�5^��$�XB��S
�������vJ��������L!�uz�����e����Lm�����>����S�&����f�L^�j���IJ�0��S�:�2m'�&��!~���bR��d�vr\�[��/	��K�2v����rR�����(
XjS�����1X*?[��J��\�J�t��;g�|�0�<X���[K�~��k���2���j���c���q��q�U*}���,�_g$+���-T�5���X�k����R�b�up��c��O}��X�����5�4�u���P���;j���+�����z�Jt���+qB&�[k�!�V"1M��3�H�t���U-��k�����R�X������x@���*7'���X���>����)�����b���9*�����Ki%���F����.D�~dt�Rx�M,�a<��V�����YwW������0�<�|���-K�X�1_�l1���X"�$�����uY�X���D5������I�e�����p����t:��aI�j5�$q�jF,���K9�[#J(���"��LZK]�����WK-b�d����W���:,��*,?���IU8����R����K0�����t�J�G������`9����}U`)�o���|,YF]��TB^��/.wc��z���������������A��2��%����e"cb�,���
V�';,qN's��3X�1������I�7�%��vi	�j��I�~K)b�j�,|;F����9K�i�|�:p	?��3Q������R����2V��4C����J4;��7:g%��7k���N�����qj�<n��;�s�J�q�������mOHUl��J�+���`%�U��������i���ip�R�aG�:A"X	�|+��\�0�)=t�V��L"�+Sc��5V��&5?+aF�j+�A~����D�92X)f�g��K���J)��4�vV����+�Ln+?�����NJ9�vNJ9�BJ18������3��tR~28H)Vk��['��2�'�-��J% >c����2^'[w,��Bv02��YIz<��.�s�JbE���2���r���d=��$��J�aq�����R�b��ge�0��sV�1���,��dW�k�t_�gd�T���D$
�����V"+< g��"�����D��G���� ]I�a��|c��p��~����K=<��[�%�]�Xjnp��`���{��5�z~��!I��_����W��j��D��[�����|,����!�D>{�kLk���o�5����o"'=	S� R��i����x�]��
w[�R�RE��[�����:�������Z��~�����[~���bH����
�D���z�U|�����T�v:�7
��8��
6���ps)m�4O�iN_�3?���X����G��p)�*��.��v�/-���cI|)���=�\R�CtiF������0����&`��N�O�w��P(���d�;�x��A���2X���0����uF�L���	��
P��#
=�
�:�p �3����~�������
�)��w�z�H�r�i��/��
T�jF8R��+�d�cW��	����z�e.�Q����6����!|u��
"F��N��j���6V���d�W��j�f3A��V������6+Z�pH��fEI��f��Lo�YS����V����T�j����������d��&VP.+�
"�	�|4[�<�#uK���fM�o(�c{<2"� ?�� !�����g��j���	?$��S���}�������q��qX��L��{����{
���z����#��C��#�Et����p"���o�!����Z��0�R��PF4p(E$�\�C���iA���?�B�����C��s�!t�7���eu�a"F��A�o<�i8d3����0�"�-����m!
�K��JAV5�>��P�-T��lp�P�����~�d�����	d��J��Z���*@�Ed%��J�w�3� �:�YT!�q�b�BmF���@V���>5��6�l�v�O��l�/�fB<
�J���v�B��Z<B�Z���]�@�c���B��w�� �6���A�V��'�_!
������3��b8��q���6���<s�i���� ���4�����a�l��J��4r]'��P�x$�q�o$) T:��Rk�P��e\������uc���5���@��],e�����j/@(u�[����Ag�z��N���&
����\r5*��7d��b.f;gH7�d������c��IKcm�����~](��r]���
#�s%�@!�`�B�6R��^��R��Q,w��P���p���6ey�*l��I��q�Hz}N�R�m���S-H��z7lLn��`L��S-`a��9|�<�"��/��d���8�Tr�u;"�P�T2f�a����H%�;
�eu�A�/��RZ�VH�,	_"�B��j��2q�;�z��W��J����"F��oK��"lisZ
5Z�	������AK�z��z,�i�����zp!��#���rp�u9�z�l�7���78|��,h��^P�h)����[�
�h)m���R��
Z�1�`]��2�j����FKX����������,�1h	3"�-�����k�R
����y�-���}�!q�R	y&	}
^���:��Eo��$5�/��R*���B�_�K0%��^��%����)��R~��3�|]��	��$��y)Fcw���4�v���v��X�l���AL�x|3��������J��._�3�y)D<�'}Y[���4��KB���R����������)!��`��d���<G%,��t�!SVL�A)d����$���:�������������I)��~z@Ig���*����uD���I��!�%�kN5�`�&����RD����!
���:J�����Q��]���+=���\ #x������+�cq��h�	��R�~�L�
��E��{����[�Q���#���E�1mYP��Q���4����L������_F�5�*��c`DCF��hdL�r��>R{�rh��}���%����� ����A���T�"���<a��E�&�����Ij�J"�\���Q��;"K~;��|�H/|NF�|L�4j�+9�RqJ�w4�7�p)����1�~��R���,}������iO�-^����x�k�6�u@�Q<|�k��rgAG��=��t"��X)�F�x����zF�_�AGX�d�t��,�!�t�kb?7�h)�Zw�s�F�d2@D�������R��Jt�j�:J�b�Mp�l�Z$�����D@B���HV .C���;���~�b��������WzT���k�3�&�����v���HzY�j�*'�jp�G�~q
;�u�v�*�Q�v8B�i�JV�Y�_�������lT"&�����
Y�$� #��5��G�FFR���"�D�V>����[�4��Dl����F����:������������d��:I��X��u���	F-b�����1�:�:��.�����B�N�k��+��7��x�hh$�hT�Kh�h��Q��l��a��{������Q9AW�ohT"��p�h"&+��/�������ok����b%�r6�h�vX�T��kj���84���\�<�����IY�F�b���g;fs;�@#h����F!bM��74J�|�]3�����x�4U����S����^[�)8\t2~`v##�]!�Z5,��d��+dVW�jL���&�T�(G[�8T�q2j��KG�I���t2*���7�Z�V�Xs2�����&��62j	?�O�H�\�9aA�7I�i�5M"^��`��lKOSaM�z���Q���  ��j<��g�	q�AF%b�Ri�)-"�N#���]�J�6�JB�4U~'*�����vS��P[����*�~�w�Q.Z�R�\����y8�U�
���������EP&E�Q�������Q��,��)��;H�L�\��\�
74&v@DQ����]|C#�������In��R��d�74�!w>
4�t���
��3�h$.�h�
����Z�D�1������MV%��x�*94��k�px�Q������=������G�r�#U=���&m�@U�/u�
��Q�����Sjx������R�����e	�e�`��i�9q�� Zvhf<h��Z���������vW��O�����'+�e)����@��e��ux�2@��D��@*�-;��B��������e���vD��d�����C�xV�����`W��V�$��
���t��:hi8��BHy�z�J�fz�*��y��i��A�f��J������k�CT��i'pB_��|��i��vb���U�'7�����
���%I�N;9+�^h��?w��tHW��������vB���������<�f3h+�c��7m�}�h��w8OzT���������iO/�_};vUW:v�G�U�o+��i����Ik��H�`�i��G	"����������8q�"��S��C���8o��yS������`M�H��
>����T�F��`�"�I�9;k��|p����&n�<g��j�K	�Y���[�������Wa"����Y����1k��g=��
}-4
Q���9
��&�)��4c|��P���:�r?��
�V��B��x��0�%�N�F>^�Yh� ��b���'@��Hj�`�5k�{7!��r!!�(!Y�r|������l
�Z�73w�|? ����S)	wK�O�T���HS�7;@�'b��B2�sY��7�j�l ���*���t���p��]I��� x����t�h,���4���
����e�'S,<�|��1oP%Gn���_�X(�c���UJ��(�o6J�"6oP�gbN��8�Gr���R�i_-b�#e}��,�V$�c��z1��}�)���/x��X�������_���X"��q��y\�6.�3��z��3�B-��wRJ+F>au��U����T9�
�'�uS�X�Q�P
�D���P�'@(C<l�P��w����:\��$��4���.�Iq*�p!��pJS���A����B�����-��P����&B\���������A/F��
-F�� �"�x-\�Y$����J�;Jc!�V���4DlqUk��J{���g���8r�"��Y#X1�&�X(5���p�����^h���T�B��d,����08/����B�&��n���������i(�Z���X����<�n]�a��gh!FH� JK�-�C��J��)_[8��l	h���.Ei�vd��[)84d�l��P*���s�b�&�X��S�6�S�� ��������K��[3�en�RQ�OV���4`]V�����[q�cB��V.�,�]Zj���?Y/J�$�h^I\:�k��~��`��2����Bs�[�T�i�i����.�0����I�xa�8��A���rL���V@[;j`R==h�>�aR�Gt�I%"�IX&�)[(����bR�bA-Id
��hhSL�!;��r�qM8
�aR��������X��p�4 )E|�!RD@R2�J�r��I-����qH������:��!	�|��j�k��j�i
����%
C���Y����P�H9�y6��?�F:#����|�H1���J��tj��7:���W��Rq}&�����i=H��nT�H1�����
tF*	����T�JJ�H0�����[�C��J��*��}&��d������zF_7tF��X
k]g3I��p�Gg�^��.SFjSF�G�58�������X�\,���8!��_�I� �6ek��/���R�����!���C!�e�����*X����2���-��q�I���3��Q�k^G�������?x�hx�F��p@�<�O�R��	g���6���v��/��B��;���)!�C��gP� ��5h���x����6%�
��������UMN9�rMf��24�V3�HmJVk.��g�����6�q�Ed���+��E��!|`���/�W|&�,nh?�=�7�J��;�`��w2�/D��
����0��9������t&���d��b�O��x�\��A�T���]����Q�Z�����B��=�k�8����*bq����wz�PZq���I]8R�KpG(O�
��&+�$�_�As
�.�����` HH�_9�'���y�� H�?�?��o���/�@'k���/��EX�r��/�LkK���y��}'9���\����'pJ��f6�w��A&i�����*^�fD�j���R#����6���4j-�OVc ���!Ai�����o����C�� ��b�f������/�FB0���P����������!,j��8h�h�SvaE&���x��e:�����c��8�($����pJWt**�+A�����qA��oX�����Z���
�]���d����p�VK���h�)�O��R�u���+�&���.�fh$Cx�h$C��X��Qb's�X��HJ|����1����h���v)I�6�4���x�h����TG#i��I���D2��H"�-G�QrO��s-�Cq*@_&8������gc���Q=��]�_�)���H�a��h�D�@��4�@44���M�v��a�&��x<z���PG�8�Wg�Fi��0X@�6�j0g����%9�kh���ufvv
�iPJOi*&N�4*;��[h����U��
�jh��y.�,~�54�+R��s�c\�������B��|E�cT��+��*�gs�oG�xv
�Z�B*����\�z�����Xpl.�&~2����Zv��
��G�y�Q:AF-"����x,��(�umd-F��	2*Wh�dT��ob�{�dd;
�OSP�%�v<�jg�fs�"�AFp���|��R����^8��)1�"�,n##�E��
�Xl�+�;��/<v2��b��������T�^�S��?{v�?������
����%��~������sZ�a=t�T���U�^��U��J����
���[��I{+9�nM��s��NUG��ZW�����)�g�[�0�^�~$������r5k�+���
?��w������~� ���h�n��
?�	�m�5�HP���#q!?�5���'W���#Yh�l
?>||���}#V��M��e"���������K9�n+�������zS��m�������N����i�OG�����m�]��i��I~�6�	
����SN>�7�Q���S���uN9����9���;�`���z�Nq�%��SN
��F9X]��Q�V���*Y���W�D�r�6L�$�-!	�i��=('�������*��*�i+;XR��������~�z�L�b����7���W��n���&v����M� �#v��������V�U�H
���.�a��0Y2��GD�V-��~�K��pD���_IU+��V@��&>E'�~�K"��[�������\R!����\��/L?����Z@������4Ns���3e���V�9g!Q�QG�;>���,��3����:fM����G;
���m�`p����G������T�����M��
�Z�����J�v)�f�h
,/K�4(�mx$Q?A�A��
��3��@'|A@2A�L6j
�����%P���O���i9�m��)�3�'%$%�x�B�:���O���
�)F����<��0��/a����(���zS|�#O�L���x��������w�`m����r��o�e=H#IW��V~L�B�i���gM��o�����h�t��E�����@�y�����A������S/��/{��,9��:l��iG��������$x���qX�B�Wg�~-��O�����m�t1r�_�Hu��L�m�>���/�>\

I�#�zzvj����Z0P�^p�f�}�`p!'Rk]���0�8���;hy���#_��8G�qP�x$�+��9���8�����[?-b;
�����1Y�=yo�����
���z1��juJ+�4�qP�`��ADpf"�$�1����B��z9����Y9
A�7W���#	�n(��X�P`��9
�
�C�g�z9+=ix�T�n�Y(�oy=U�:Zr|48X(���8���`V=X#<Xx��a�%���\�i���b����x��q�� �3�\)���+�L���I�3��.?$���*�cEc�"rd���'�X��|�e�$�VSl���f��|h[&� �!��aI�k�?sCD�`�b��i%���%����sh=���<l{��������.r?��,�(J��1����^z���6iI��v�-O��.�%%\�D������9.�����R\��s%�C�V��O�\J�1�z��l��tN������R�s7y��^=*����8��Z���l�,�0��HB�
L^S��I�V:.����;.ia~�xk��C�bu�G��R���}O)��qIBYU��<�Wp�qk����L-��ZbAp�S
y�a�6�&L��/I#�&�aMXt!&�HR*�������e��J��I��,�S��c�jx���Gc�b0v�
`~�d�\���j�9
��ABF���;Y%�����D��$#`I�+���������d���#
�������W�����~�J"�h�A���3W�������5A�A�O
��C	j?sM<���U�0�A��@�0��h/i���+��M���D�����(���,*	I]V=�KQhb�SC�<�PqO��lx��|���|�l�7�pt�Qi^h�q��*2W����&��G���$����:�(���X�\}��I���
�o��dc�9(�!�9���dc&�_��$�H��8(������Lm�����d!3���B�sem��%��1�%����������<^����{I6��3-|/������AS�b
=��t�,3�p�cS���6?|�c����M5��s�vR�]�����M�w��x��y������>�~ts�e@S����3�c!�=��Y�M��;�4�c���/�h�1[g�����	h�-�F�f���lh��,���)���
]�Ia�&,�#9`o�!w�����M���F����R�M�W�AS�V=:��)�b��6;4�������NS
�{�8|���~����%�+���O&����\��!�.���a�r:��XK1|��
}������<�Rb�
�K��v�
uZ,Q��TtsX&�@s��e�0�&������c6|��4���*�X�1I������T���%s�4�4��$�,���kcC��`)��#Hz[��|�Y{r,+M���43R�)�F:+?��K����y���+���X)M��R~���J���a���a<�����rV��c���P�J�1[���c�B^��	�������}�����P<��R���P�g%�����,��0���0I�������9/�J-��&��T�R�-�VU�����;(����Y�F��J%�aA�P��Y���:���:+����o���X�MY��z�lY+Q:���P�q�^�v;�K5����c�TF����R�\����U�ZJ����i���]j�<n�,W�x\J���A�����c�>�P����l�X�4s��12���948p����K�%��j�[�l��e���Kq��:qPn�R���z�w\�sV%5p�B�����K!�n5�R�K���j�7\�/����*����R�R ,
/\^��p!V
.�����K�@�����J�U=�����6\�.�rQ�9����_����e�ds��R�x6��A�����eIHf+Y�7)9*3K��tI���J�H�m:'��;w�0L�3��$w�����*?~�����H��}��F�7D����R��[5�����X,�ZFY��g�/<j;��k�����K�H���Z���\R��2~4����.�����w��5*J�������s�6�i��[Z�G�a[�5�nU4��Vz��_����s+o��O�o���`������( ���>q�kk�!�[�@}������������X^������}�7���;k(o����O�s#hk���}���<G����8w���{{�K�O���}�������.��c[K���O14�*�L���������<�R����WP,-T������_o��|�����R��i���P���I^��21����;�
e������(K���2*�����25���@��2=~N�V7�I�q�ez��^�2�O�e�8�%�(�O��(!C��{;6����������L����1C����(���7��������bQ)NvG�'cm7�������1=�j��8��<{c*���\��v�NK��U'@��QP���h	_�Q������Z���Di����U�Y����dEk���2@ ��I�'���+���8�0h`�����2@��V�\��$�f�	p|iH��D�lEXa^���>T�
�^ ����+���z�������Q��A�o#���sKi���p����;5�p)��s
w0��_�m�'v����Q�)5�a��u�Z�N=�n8`����:����p�m�D�w��-�O��wR�;���.1��9�@��Owhd	8���V����
_���p'l��@K��2����'����������;�D.	��Yx�Xd�������x<�O����wv�;9��3*��{Oi��������`���O�����I�f�v�m��(3#+'F������`��)����b�a����W8�2	:��i�m��m��������������&X��>��h���+��d�Kf��vJ����+":��k�c7�:�e��6a�����4rAw���p��HH
N��	�|�d����L
�2�����%��h�(m��C�8�p����-=�p���[;96��|^���K�K��d�BSa)`�}]�bQ���F�B����R_���}��S<��F9�x�6��s�)�[��.�����2��8�I=� ��������W/v�p����J���A8)�:S�B3��9�����ot�[1��0��E�������7������M�.��T.����`����kj(��9���@&��Z�<�D*��^��8'���z��C����@"���1���2����/����m3�i�hIV���%�}������S��"�Rz�������������R��!�e/�%��;����'pYo(���e/@.�e/��e����mw�W�!-��g�g/h[�,���^����=���Hf�ht�B5z+S��P�f�l4�C��Prl!
�#�
�zl���s���z����J����8��[)����q��Y�n2d�n4Y���y���`���K	�D�dN*U9���T������`�������D%���z�Dqk������9���G�#O�"��MQ
E��[U%��w(�%?����H�$W	E���fI�nZT�n�b4v
$J��/����-������d���z[��,~��c��
�����c(v|2,��v6������'����"����-����h�E�I��Y��c���������0&�_���D�[�3H�r$�V2 ��v�^U�4�h4�C.�=���D����CZ�19I��Qz?f.�f0�ZX_h]8�aHv<���vLJ�1a=�
�`E�Rj(�������|e�B���v���������������x�<��*���-�����D����q#`D-�aDh�(2~�_���w�!�cD��r�����P[b�����d��&D2d�}��?�%�s�N�!2Z�tI"� �%3��:�e�zdL�i��J�duj)�s��K��p��B��u��U���P��$Mi|k��a�	+�����*?/�p��PL�R8-��O�����R�D1�!��0����T?P��xN��o�y����+=K���(E�5"Es:�e�b$��V ��{��`(Y���3S�����h��eiI�RW��HC4�HDCjE�pI�F}��H��)�B������+�&�p$�7==�
$��X�;;-�vx}P��5$���wR1��n�wiRSPi<!_	<+5 jJ7��4��4���R8'�:����9���� ����I��<�uJ�������Ex�B����Tb1�!��:�bj����������s�%�,�h�!��U0
�`���d15d�wa�0KB��"��d�-;H0*-~�l�!����3Y3&%�ayZ��P~+��6�^1���g�Wd������MeR�Cr+��3*g��P�jJ��h��kC���i�&��o0�d��Z�4�t�^��\���}��w�0�"��dP�d��2^�c�yH�0DC���0$K�Ivs���7k$A�<jm��%��=�!,���-�`�h���!Xb
 ������dM/��r.���-
/e;�$}�`(d<����t��X�b$k�����C_����<���e�++8c�X(�X����B�����I)�Gy145�:���Tp(�R����9����r�Z���`���<8����-Yu��PX����t�B��n'�Y�4��WTBe���?i
��m!
�hE�$a+F���
���j3�W	�
6
3����B��v}�6�'#�DP����k�G���?!�g�M�3f��4�g�@�~���|A��'���>94'�|r���,��:9������tx�AO�q!k^*����.i�
endstream
endobj

6 0 obj
49895
endobj

8 0 obj
<</Length 9 0 R/Filter/FlateDecode>>
stream
x���M��N����Oq����=3�B��f�v^���
�@�f���I)���c(��
���tEFPq��m��������/��:��v]s��_��6c{�56�4��������������������?������������S��~~]��i���?�����/������?����{����������������uo�\�������^�_���-�{����������1���b?�?rz�����������v�����v��f��������2��o�e�J������u�����Roh�f�^���w�����������r�n������8�Mw]�������_�16}�������������z������o����G�tm��ca�y���g�g|�M�u�/����v��a���^�,����������E.2�C�����65s���!���6����vmW�>������[2U����>�t���>������f���:{�"#�{��c�G�"l���2$��
��u{S}M�e��qj�D�y���v��������9,<T
�L�����G��(�V,]�C8%4����A��{�����������������X��u_*�����+6��I-���{�#m�G�_?��r���.�K�^;!��e{�>��eC�����@��B��}�����:{�
;�%��^b�~��4�=��7�3tq������9Y3��w�
g0�dYz��v��o��������)�*����q�/����w��l�G��(a�O�TBb����c���pM�gsA���M%�o���i��I��!����$�]�!y��I+]���zm�q�b�7d	�?�?�n�%��L����*����~��K~=;����u���)�?��/����Gb���������@���	�6������an�G��(���v{�ZB�����0~��Y?�[�G���CC8'	�\J�t.������������(�����k���$%�~�m^H����o���?Q�~;�����zs7�e�>��}m�����T���@X���F����z$�<~�}5��25��,�������R�w@�����m���,���B����O� �5>
7Da��_���o{��m�~G�}�������Iz������:�q�c��[.��k.����[����6�8�&�}����S���I�yl��^<������|����K�.x	��l��g�+6�"+d��r�$�:�n6_�Od�/}z����yr3�)3Y��D��ia�+�~�H(������A�^��^�X�T�{8���Mw��4�Q������#���g�yhu~��^m��EM�/��.�6��\z#hU��R��vK�L����'�X`^x���l���O�2��H�l���:���J�N���Tv��$gMw>6��L�~p^�J����	�~�����,��H����W\��j��6�����V~��U�#�v���M;����z���8H�&����v����/��MV}c�)�e/q�&�3������������c�9�M��8�o�(|�O�����T�e��������2>�a�]R
�����,A�#��A�������
������#K�!���� ��{7Y��{��������\�`�{*�w��$lt���"S�R�������Aed-�:��$��;��1$�}�U�:�s������M�9Q���7�������,��X~6)�d����.%�m�2:�)�u?�����d<8w�&�3�����0v��*�'�����hS����i��L�)�%�?���~���o�f��[���E��nF��" ��K>s�K�a�s��������}��m�J-�q
wGc�!��H��a�ah.7r.�ee�vs4�����o�7���@�yG�y�������"��?����������4�nH�u���_D����N�^k&}���v��c�z$��������{o��}��D�v;���R�z���L_D�wF��i{��)8<z�������},����`�,�ws��fU�����(�����o����O���N������@�~�~���X��7��y��]������d�������q�Y�����F�ZZ�z$�����~�|�q���X�t��@���C�������=��l���{P(o���8Q�_�| �P��O����T����uss��=��K��XJ��q��_x	�O��Ag*��=��U�x����~���}�t8�����^Q��������P_��;��SvxT����������(�/�����B�����S2J/,R��A�y/ae8���	/a��eAx!�l�E`#����p����,p�e��]�^�Q�i������;J��d��|�+�NF�N����D�p2v��p�j�g�d$l.>H�o���������

�c��2t3_w{�|=��P�O?��������A����������AX���]���������}�{,�����nH3v�
��U����O�t�|���\�[��RO��k�	s�5Q�k���Z���
����G�m!���.n�����_!s��65�^$�>�~[��R#����\���]��~����vY�?l;*�Ll�~ �|�)��� ������P�N=������������o�u�����muZV�3=��Dn���9�A��A��(��k�6�����G>�Q��DU�7������G*��F�p'#}���)���+�.��������a�i&I��h�>���3��E��"�s)�C
�{#	�nS���YY���Q�y�����i�]R
�R;�%A��z��N����af���w�::�w�pM�T[�	�����>�g�����rmn�
������IV���;&
;�he���;&jV��>J�fq�\��nJ���H�OY�"�"��������H����Q����\��Z�q�,
;W������03\�4;�Fa�����jI�y,)VLY���������K�L�,W�e�,����\�U�����g�5�$�\�]����]���eA��
��$�Hq��);���s�����WY�{����El�wDz���PV�(�MsGp?D�j���qR+���I�P$��y��L��C��8(Q|��������t���"X����H*v���jV�.�Hc�<��$�e�T�#������c>$I�)f�����%\����(8<���o�I%�d�����2�w��������p<�U�
'������A2���S���d�[](&v��2���Hv�R.�+�2p0O����44��R9�o��J���	e���W�a�������@�A$A�L������gEx ��������R��@����2��-g���[3�*�s_W���H�y�AX�C�m;
 �&m�{P��VD������=M�k�#/����#I��woM��I�N����Ur[WT@�7�����|�
{�.{��"�`�M)�2�"�m_P�;_���	��}���I
��l��E�<��OH��P|8$�Y�� �����=E��H��_�
��5�D���m^����������a���<����u����_?�F��P�&�V���R��i�<�_�t�h����an.��
>��$��;*|P��]�/	������a;��i.��w�e�-�!�&[V�*�m;����V�%}3�"��7����pGV8�$#��z�����(|���	�����n������g�e���K��3q���]�I�k3�"���|�o�C*l�UY�NJ���t'�F����������C�G������u`��h��\>���X���+��4��U��
�c�x�� \P���6�N	�bo$Y�7&��iY��Q���u�6�#Y�U�t`#���p�+ ��5��L��<�/��"�Cv���YyA���,����3IX�mw�&kv�`���^��s���$����f'#@���(��=��2��} ��N
��R�Q=?
�/-Ux�0s�HV���G�������GN���u�8A�e��(%��~�N�����73��e�[�~h�Y�Ca�z���j�'w?����������kV���*	+��~��a 5;�������w�DV��y�Q��n<����K}wD-��}���8�l����2������l�=��Wyc�*�v)lsx^u&�{����'L�ks�Fd��'�(��+���
�����*���^s
V��S�0w
V���tu�d����t����������FrC(�����ZLGa���h��YG��6G#������W�o�}�x����������a��G+N�;����v
v�8�f�U���+���s�}����'�/�#Y�0��Gz������7`,���5AD����=��v�p;xj5��y�����5���^��;6����B�rq

��;2�,d����$I���df��R���}kf�
7a'�]�b'w�����"��+N���qe��Hv��:
�e��D3k�[�G��g=�,���_{�b�C�������(����[m�V�������)�yv�$a�'�l����=��N�'Y���S��Q{�\O���������I�����IV-yUx'Zy�;I�P����SVrm�9�O=h��S�y.ed�n������}�/��SV������
������^��_Zwt�����'MUm%S�'�y����<��dU���;��������d�<
+O�Z�
��M����� ��K���^JV��R���i�{)N���47s��I��/�6Q|m�!�:����I������ZsLG3�:"�y�����#��������!�*�v���
��Z�y'���� �x�Im<��`�Y�
�(����N���.(��%�������8�
:�1I����yz3kV1����J�]�&�g(�|.�m��
�>���|��Nd�#��G���[%	;����E����t��HVe�\��L�K;Vn�Eg��<���n���kQ�>���$�aYq�;*�s:7m+vK(�pG����N���D������P1L���WAo]x�aQ
��8������v-|O
�����r-T��^���E����������t���,2�dX-�
���uMS��"R[B��
+�;��/�%�i8\�����7����3|�9����U8���y)|�`�(\��1������D��@���L�f$h
�w7C�N`��Zt%uN������p��6���h�I��e���9�O��r�}���9�PVu��pNR�d��x��9A��v��h[�y~sN�����Z`������&Yv6��]�Y�j���s���>N��ZXeS�LB�#T���=2Q���0� �
� It�����H76c�W+���@Xu�p2)�����7��g������X��p&�P�����p&2���F�N�Z���[I�X������HB�"~[_���;�"�����8[m�u�p8�mO;zP>.�&�w�;(q�6����U�9���n�h(������g�����q��������-��m
G#u*���x��k�"�s�o$�`u��yt�#Y������s��|�S���Q�I��z�������@��v��<���%5T�����"�Wx,��6��y�-��a{V^�\���2���K3�2XY����M�%����o�������.C���d���<���g���{~�DU^�������%��l��74C/#C��G����n���l���������@��p7P��F��2FDx�jc5�o � 3���]h����~���[��2�ML��P����e���bP��&��$q�Ca�w���$������2E����!	�N3?�);�����^u3�=V��Q����oc����(���A��M��U�3���~�R���#�H����!	����wC��Z6�p�O�'������?
/?�P��Ct���u��A�(���O�d��*���d�B�5����^�A��27�$���^u������\������]$l���#���pp�"Yg{�0��������TDh��[�`$�\b\��\�o�A�N�a��#�q�-T�l�(�v�vb[Q1��G�{�N%3��zd������-�����=�'��D;_�V��9t���T�*�jY�e���wC��l&����p�����m�v���Nq?���(���(�wbA�t`��^4��i���Cs��X�6�'�u?�q_���{(�2������w�:�E�S[$�9�M
�Y����$U������i�}Y,Y�&�>�e%a��A����>�M�m�����V�#u4�L��$�:g���d}������&u0�M�G����,�9�=���������A�Y�9�{D�� �:�3�����C�,����k:�*w��@�YFBv���<{*a�*�j�!A�|���h�#�:{a�N�����q�����9�� �:���H�js&�����Lz�
D�����$��+�����"A�l�+JQ�P=��������� ��6/�����Y�Y�f3�>���%f��U����%��n�NJz�9����<������t�����X�����^s�:�ee��{)iSY�N�����E c.�f�IQ��oV���$����5+��R�����)NY-�T�����
�V��n~*�u?/@�		:�>|���-A	�ds�������|����H��S��s�N�usy8rGm�f��C��2A��o��h ��� |N
����u�N�ks6��$I9�����W����m9��� �����"��]������Se�ox��2��grZq���������GU�;ZV(�s�m��	��}d�@������"���9w�?`Yx#Zv�4�X����7v��C�-�m�f;_���Zn�����9�m��d[8$�V���h�e���X��H�m��[+O,$c��oQ;���D�u�S��|�}��uE%���vy��>I�j?��'���[B6m��Ms����K&�AI���X�pM�����G����1c74�,��]q���.��pIVK*��$;�������us�?`���R�6�D��5�z7�$�j/"�M������67���7�h��$���:\S���8���b�v�����M���sLl�C�{$�V���G�m�h�����5��\���X�B5�6E����'��F�����K#">\8YQY:�9XQ���������T�p������.]��>7v���<������8b��X:|d��*D+������11|��,H�)6\S����H,������3q���|�|���z��^���|�I��GYX��d���,�dr+�)��G��(hu����i�Y���y,���v�e3�N8�w�u��i/�1���O~$��`O*���A�Y>BR>�
��{d�0�6��.A}�&V���M �:�nE��u����f�h�_������%���WTj�w�����N�Ca�����C�f��a��E����G3rh���v�	�a�wD��,$�3�gAXR�����k��*�76Oa'��A�oG��rk�;��O�F�?n��E�"����v/P����w�h���������������>��Y��LM	7��qU�c+�f�������j�5\Q�:{M�Z���N��>����v�����}��C��PX]Q�����Y'��6����{U+����9vv�#3�:��p��yn.��a�]�'��x���~-��O�H��}�5;�=������'��f�;�fc$�w���wn>$�����N~���Zv��{H���
;�5�fV���IQ��"�t��u�!�$aEz_Y8R�;����b��h��Y����$,���{�uE�gYKy��ia�5*���z�s��<�ol����%�aE�YQ�})}9����al�Gf��������P�8Ya��� ���H��b0�����a�5�ke�X��w��z����]s�������9��44��=�����!�����>�����9������e�\m|!|�%��+���M/�����@��B����u9�q3B�b�x������F'��hf-/��_����u�,9���E"��7�U��h���1�Q��&�oO;#�x����fN��J���8\�~�����I����s�Q�YgD3�~��Z�5�F��h�^����'�����6���*���ah��uUGa�4O������a_;S&	����'�Lvz�D+K7�������g? ��s}5��������r�"���cI�Y�%Y��6�d������3u����*�Y�~c��G�?<ul&��u�s����@a���kQ<.�'��a'b��Ew���zO
�y,YYK%KV��X)���_��}��"\�M����Y�V~���c?a��T���fu,=��JY�����~F�2���[$���s���#��i	?�+~����2u���;�����AD�Q�������������$a'c�_)<�kn�����H)�>>�y$+[��]P������pNPg�m�(���'���)^,�$D���X��$O5pk�#��f���lq]"DAo�>I��"'���:��G�jk��%��l�u�$uj7w�?1����i�mD����ig9���2�����,�&�7AX�ctw;�iu������*)m2	5	����L��"Ca�>�9'�y�<�'�t��o���V������M��oG����QJ�U{;`n
���sST����M�<f��f��V����l�9�LL;�o���iG-�s���w����5AV5�w���}�C��j�C�Ag#��:����PJ���4>�g�
T8�g�e��<s-Sx��)������0��
7e�?���X�7������}�Y��Gs������:7s����k$����}M��x�
���H��{]w�D����/�P�h�t���QU��7�w~�C(���v�(GJ����<����66|M�EfU�jS[D����IV���y�����Vx
(�?��}�r�p�I�+������{,��q��%<O��o���j�M����"p�����P���|�
����qlR��]�[��%��������:J�-z����o$�l��,����G��8r�o�0����B!|�A6��<��9������_y�\�ZV��+Q��H���|k.��A�]6�vw#?�M����q���Yw6�E����}
��R��i`��bS���s����a���x��9�����������@��O�����:8-��.��������&{��p���~�Z"��k<���8�l�F�U��6o#�������i�L�e�o(�&�1wM������~�B^F~z��mZ*�9���HL�E�u8�-N�?������s���f��w�mE�C1;�]���<�~�4�E�ej
%�p4��z���86��3�vV|����<��;�
J�)��7��Y�=��d��}p��eo��(���*�:������:��
|5nG~:��m�6�9��c���
�i����q�Me����h��p�P,\�U�����4��w�xm�A&��V��ewC	?�M����:����m5������H�~�����p��y��gw86��?!��p4M?�������X��l����H�O�������\�����;	�N'
/a��Tp�����h�j;�������{w3��������\����5�i�O/���|�ws�|�U��q����;9��Da��?��d���������Bv~�a'��%�S�;��<�\I���?�����>��GT/$k���{����
N�y ����&IW6vK'Y�X�}T��h�&5_qC�\fQ�����6%��4��o\
�������(�*��o$��2J�;�Y�);��$����=����\i�Qf���`�@s'C	?�L��D�"w26�����Qfo2����E��v-���{	��xUqV Y��"����J~t�
�#	?�O���|������?�HX��I?�D�| ����
PX��u�J�?�9;�G��~����
w��ke ��������%��C��/�$�,����"@wC���7r�!	���u7$as�����K�37�u�	���i�������1�����Q�.v�	��N��*�����������[���������������`4ag���$���]
����>(�����������pB�u�	i���(H�Y/�e����s3�:���v%�p2��/N$,�	p�"����s�"a�~�-���N���aB�����]��[��F|<a�����M���?���h��,�)�%L�U�!�	�Q����$����I�!�s�T�m�c���M��������P@��#+�\��]�V5_)�5I�����$������3�#kj�h�w�5e{��	R��g�{����>��Lu3�������U�G��������� ���}=���p:)l1���/�P6�u
������ ���,<�M�[���(�������Z���|�v�5���:I��8�>x�5�Lv.RY���e�s���d����
B14h�o�����w������� �w��+�������L���$��V!�mj�I�>��������� ����]�(<�������^���@�j��p8��Dw��6��q��6���nP�����OIa]��J��J�W5�9��B�Q%�h�[S��U>�k�6��c��S�Y��@X�e��Z �:m����Us'������)���ZX������V�l������<��)0�,�-+��%IXu�*wI�l��T�m.��<m.�r��F)ee/Hxd"!��#{����T�L}|�����2
/Y�^�$/$��y��$�AV5��;�|m����uH�UMY�������(/t/%Yg�8X1�C1���GS8*�8{��
���B}��ZVe�b7�M���y�,
��mkY�Ax$V��I.��lWe,/�Q��W�Vg}�a	�j9��)A��n��o+�t�'���]�����V��6��r1k���;AX�����R�cm�I����5����dW�G�'���A�� �l 
��g������CNSs�U�fY���U�(�;$	+B�e����Gja�m��l���5����!���U#�{'	��+���e���&�����">^$�k���}-^��5�f��t�E��k���h{�&	��/%3+�l^J��F�KAXm^A8)�:���z���Q��O����K�K3\U,����^J�n�w?�+�IYVe�wR�������f��pRVv�(���(�QXm�\�)	;���S����I���t����0��$��h��,+v�Ro>�fV�G�,�y�IXu
H�,����|�4�����;�5�
��6�������,	;sBa�[�{,Zy������K�js\�cI��?&����Mtx,jV0���1�P��\z�.. ��%\�U������=��[�|��,N�y�kV����,;�"a�>C��gQ3IM��(�����6	
����}�~�%Tj������kx��U��NJz���,:�Q�pQ-�6�~�P�����D�V���s���c�m�`�H"No�(��@*\����'d��vuE��������J���^H���7P��9D������(��u��}�^T|������6�\R
[�x��q�����]����0��!�
%��]s<N@Jf��^,��Y�(g�b&�_���;�6��/�n���N�~z���w7-����L��p	w#u�^�x���m�(��l[q{R�l��:'�gXXm��=�m+*�~�(�G��u��ph�AV�`�0�MK&7?u~�S����Q��
�ln��%?����<9��Ey�	�#����>�^~���%�l�N��xlLq�W"���[3����>�y�@D�q�n�Dm�h�	���.��l�����MZ��V���zl�n-�8���T�v5?dY�q�p���n"���In$�:�7�T
�M$"u����7����������V�c����� �8
��?E	wM6�"��~fP��S[���B��!A����"������v��G4�����#�V[[���������HP.���d[�����G�������L"���[I^��o��i����Y���o���vi��X�E�Y6���$�h��#�(|0�����=��,��������f��W�2���7���&�S��N�M%�2�
��##	�*op����L����)so����)<A�Yr���T~]����L
����"����&��$�����%��������`��hcm,�<m��7/=���8by�77EN��	f:�jAO���M���V����4�B�;*H���}V8����M�;��}����nu����w����I6Ehr��9����M�M4�\6���\�bG�
TXD�N�U��g��e%����G3�$Y������a:�d.���{����Cq�>�'V���D�v���g���#����;%����>	���^�=���{�U�Y��\���'�X������26��e�+�0?��*�G��G��A���*�
�Y}q
���� ���s�D�������;'�Xw��$+��7���-&|WQ�f��g�)%U��e�qN��YTv�s����ksN6��s����S����������Hg|��6���ph�V��jw�pC��)s�3G�9~(eU~U�a���;V�����]�]�U�R�K��s�Qg���k����$�:�1���[VsM���g�}U�Z��d^e,�=�;��d^��������K��t)�g�9$��N��R���kC���"�u�AR-9�;#x�q����vy]�����;-=���W���:�JQ��dhA�WT8Y _���\UM��n�L7����]������>��J���@W�L\)�z$�������e�v����n�����D�=5������������X9s�d��+�����kn��	A���!
(��o
��4�{�����D��e��Q��U����p>�k������Gvi��"�0�����q8�"=|�4��/����iYe�wi�����2�e��)6Q�>�U�YP��>6�`G��O+�>Tf��P�h�:�}���4�5osQ�c�>�ei#���o��%��m�_��W�����~����Ks�/����������.�x�~�?������2pv��ks��v��<��6�����?��[����e�Q�g"��a��d�04����!���.��_�q���i���������dt�e��$��������_x��uM;���I�Ms�M�U��$��v�C����/�������tl����d.=,��{�^���>{��wO�C��4]�������O������������������K3
�_��o�x�g��%y���v,�_���<7�e�
������������.�*w��/��[�0�o�/���o��h�{���~M��9����_�������n��%8\?I����������o�q�������y��/��~l���?�������n��%y��9[��������>��~
�/��~��bB�?�(o���(��vn����������K�kh�������������{��?���{�������M�^�����������������]*�i��}R���~��������O?�I��������WB�k3����~��~�J���7��.�<��{j�����!ra���L=��=���V*2��h��t�eN_R��S��j�d���o%��6�8���.��^6���O3������*��F��"����SZ%�24��a���I�}�aR�M����c;5�NO�����u����]���W����>��aj`z�s��\����&�u�/j�<6�o��?r�en�^�����ks��tqF5xj���������o�e�L��O�)�nz��������'OKE��=��,���}�u��������~N|��L,��P{�G@��6�Ow��
�^�j�n����MK�fj���a	a��[�kX�4�53���J��7]3��]_
�nMK�-������4���$
_�~�.���[@B_;.G4@��Cwi������Z��7�\w�yk�o	��\P���\0�����Aj����ZZ�e
���R�������������������Wpz�5�+����
����`���=l��el�	����
�i��
r��B�������Y�`V<{$���F������hW���.�Wc����c�C�x�>�@�,��K����m�T���Z����H��O�.Y��Fz:��y:������:~~�k�5��xW���c��7�����@�r�����?���t���U�D@�50��wX����k.����qN��)���o?�M���l
��r_��GIpy�W����lkiGIxr�
�|�L���������K��MM��OJ��c"�}��#k�	�����:@�>���0�\��e&&��.M7�d�{�<�^>Ul�$�Ow���KD�����M��|��9tS3��b����Up������$��q"��xi�U���C�������]����B9�/��������\$~R���3��t�O�.��z�@������s�Pn�2@D4PPT��7��nM�;��@4�P>�(���7 T�	E���V�S�C��������O�P�|��=r0_��J�����BC2cZ�L��.�����NC6C�;��+@�������/>~9�b����$��-��PI�`�<�:�L."&m��a�R����"���X
:�i`HfL�yp�������'�ow�#GC��>a���&
�p<��������j�����rp��P��/��S���W_�����F�~1�P=�s�[v�
��%�
��%@#Q�!��^��dh(�x ��3OD�![��

i1(h���{/�/h(�Xq��
�%�b�����R��"2�h"���h�o��xlh(uXR� :����]�vN��6���Rc~4T���2����`���}��P:"�� �f������6��w�'������Zz�	��S�tt�!��\|~�~e�5��XD?}��1��!����*!$�P��/;_��P�����QdCB!b�J��u$�*�*7��nH(�H�?	���$EJO�@�A�5�T����R�60�����`(s�3��$t0T�a��2_3�P�a9Ii��fb����PZ�.��d�J
�%����N��@C�L�gQ��r���X������7O4���q*���R;^��G���c����r���N���O~��|;{]��&�S!������-�Ud�k�\�Y=�6b�G}E�0(l�lu�r�B4��^/��&��E��@
�:���&��[�4��n��m+C�C�
��gdP�C���b��\�i�y��/��m���J/���}J�j��:�K/������^�L�d������x`�W����d�(s<t���c���cc���%�($i�w��H�0�<1d��v������"�R ��N���@/}3]��y�;A5�ep��������v��[`�RcM��|n��'D<��"����\5�'gtZ���n��OJX���O��e��+�/YJu�����y���qmK����<cy�(CA!��:F�#p�x����q$�/��|`nX����\�(h�	�O,�C0���@(���f��|M*������*	�x�h��(F#H8�Wj"�
x��,��@~�x@�Rp�Ar�6�|P�1��	H���KF��Ig��{+5�=�1�,���e`�6�#��e�6�a�yR�#�6d�y���Iv,A�<H��xeY'�dG�G#H��;�*:@�!�s�u��Rk�JJN#L
�X�Vj�aRxE��4-��Qi�	�<�H"��Zw���@)��L2`�f��Uv�xmh��S>�Z�/������AC�+N�r�	����A3���d�:2j��?�ql�������F1�����������z�$L	pB��eQ�R[2�aEf��R�b��$$�Q�b���%��9� iM�
��!������ke����AT2�ne�������fB��<����^�%�2�O��H�����NF��2��>��d�#)�r����k��@�c�(�c����<�$�|�v`$m�	oB���=�1R��I3�Fs���C7�r�F���O�*�T�7?���B�$���K,�E^�9F�)������c�6eM3o� ���r*�+Fm���l`�6���#��7^mFjS�Q��^5*!\��d���^SR�o�My-����_���5�#����):	+0l���/�H0$�S�+�FE�U�7�kH�g3
���zrH��5V�*Tb|��C$��9D~�w@��\����GD������J@���.Y'3�DYpz����H���E�DJS�����R���	p����@Ln�zM��j�"�!���f�HK���2�4 R�����E��B��"�P�.��Gu��Ui��u��C��R#�MsR����^��DJS��N!Rj1g�~�T�����bpB�M�a!����@Hx���R�	56Z�
����J�F�@�����:��=~���!��%�b�9B����{�w�������@Hm�3_i=!Stu@ $�	E�!��5X�Z�!�.���)-�xF��!�)��63R�CdB&�@�i �4��3u����JCH��!�6��D%�x �4����5��Z�V�+�3�I�Q���)t�H�l�H��$�!P 	�+����P��J��H��s^�oq~�/��,v
J��K���g�����./��yE%��U�kC%�%�%��:J�)��K�QR���U��Z�%�k��h�;�9J����:>�(I��4�t�Eo�X����t4��
�C��S��F�5yEiHz��z�iq5	;���w�D'�HmJke[�E
#���*��O��9Dj����T�?��� RO^U�'�q���B�9R�8=�R/WE��7j@M+B�Uy<������R=?R������P��O����I�
t�v��?:�8j;�k��#��L?
��z5��UM�c�:��#:������:#`<����W9.J;����z=z��OO����@Q��XW�(�x��	p���(t�y��S#�D����+ZL�'���������xjxo�|��TA��KG�����������i������oKi)��w����}���|6�����|�V�|5.i�e�������\���fe4b�r
��(�Q"&�����R�h~���!/��@^F��x���	KC,eG���������(��v��� ���Av����??��^F��<s�
�!���<?������$1`:���hk��.w��-�nymi�Z�e�R��^/��D�H�}���$zn_ �KVp���m
3;�d���N_V_*�	���������zW�kD��b'�������f��*c�8�-.�i-�#��2���JO���F��fX:B�-��-��~2�B���|�#��B�#4��a����S[�~  l�<P������^���7�>��|EW��z%�PYjoG�!��R�X�� _9�R���B�d�
(�����>J-����^%�eMz2#x�&���V{]��R�'�qRZ���j��I���"p��qR/y~b��]��dh��v�c3E���k��Q[�����BF��.���d���`�+f�{m(�m1=��9P��[�
����VD'.P�y���i;]��(��.xu-��$��2R�������I $P�����wC��z�"���5�"&���'ADB�()f�iI��yCI-b-��"%A�w]����:�T�"���b�����G:GI1�%����(����;^itM�t{�1G�~n��aH]�H'��O�Koa=��d�I%���U��=U{m��E������RJk���'ftRjs�k�,El����vqc�T���aF�JX��G}����4��{������Y�q���@K�2@���%	y���dFp�?���1/�
$�2������v��+S`��K������Tk��$$=Csp7k����Y(V���`Ox{kZE�;5>�zx�����
��YCN#O5�]�,Z]C�'/��)xv�m:���Q�������BO@����� ����
<��%1��)�c&Zcy2�B�lf<�l�	��I�
<�9���y�����>�4x�5o.	���X�,}���'�pk���Q��u����rN�(�M+Sqb�BM~x��GB;���b���
�$!�����<A��cKs��������4��N�cFT`���s�c������l����S�$rv*��4�S,6q�;vv��2���]�����IiC��us�(�Q
��/H\���Ty8�5�?�K �� ��<��dPk�K�2����
$+�s3�zm�V"+$�0��<�������@�)����'4��Xm"���ss��Z���������v��G�Sj�8�g��N/��;�J!��q����Q�����RUB�c�Mq�Db���j!/��j_;��5�����(T
���� �Y��T;�e%��;��'�k�X�����J���g74Sw�p�F��.��GZ����f��@��.���9T��P�Z���;��I�4���f����I����c�6i-&&�
K�I�o%�R}��O�*X������@S��e������)��d�����&�h1 h
�<�z����rfZ�e�C� �.2 Vh*�X�D�74B�u���R���4	4!��k��TzUHW���4�k�T�@S5yUh*�����z2�Ymh�L�9�J��M�[���[�fh*��L�V4��[��JL��A��,�h��3&��8��I��9��������>�9��IV;�����JN�
��+��E��;�:��"-LP�bh�~������������/��(f���tWGS53����2����2Z;O0���=JE4%d^>T��A�hJBz�G��������54��_�����y��� ���BSc����TBK���~�*�T�\��j���N����*�sr<�W&���B:��x*����Pm��c1�	��NxJ&y��8��i�|��C�l�x�M2�n���W��,�O�"}��M9����H���z3����
O����w������o����jf�imMWQb(�0��r�fK7�Y��
!�g����B<S��8���Y�92�Tn�ux*��mx*�������rx��������X�:<�/y
����x����i����g�o;�\C� �����������4����QG#�_������!�,�D��1���Z�9-H��/A�����"����Yy���j��D$�^��4���[y�sn�r&���rF{�Z���^9�EL�W��o�cX��v�g��`L�d���W�/�g�1����H�
0�B��`��n�[�����%R���T�v"����;��f������L�K������Z�pQ����)9"Y���Z��r7�[udDS���gEF\����)��Z�Q��p�[�����qhT">y8+[nJ��"�d�����da�F������D�Fw�s�Vh�E���]
�/Z�a��(���v�'���1'i�F������������m�F��y�N�Q�Fc��y^U*�\��0��e7�]�������HIX(V`��50
5��^sz�%�����)S���Sg#����Fi����Z�����p���c@��S0j�Z�z4�0�d��b)�1��2����Y��F���.ECZ����Qx�����7`T"��b��u`/t�F��UgF9�����![�k�QT�E�7��;,���
X��A^/*������z���a��l�>��^��;6*��Fw��X�	%E��y��R/��LV��5/sZk�
��v������^/�,N�h I��$�5v�,��OnV/������Z/��.�k�h2�O�7���\"5��O-d9��s���x�]��w�`N�A��s?B%*v�	B����7^/��$����JB�@NP�����4<��~�y`�w�v�)�*hoa���N��
��t�;.*J�S]���1pi�y,����A���NPd��/���R�
32�0��C���vjs�����`Nk��	�-ZcG���N�����P�l�"	6��0%���c�N-���!\���@)��E!��`0%*b7I�n�)���:�vj!��?_`�2gia��O��N��u�)4��N5UI��x~��z�cI��S��{� r ����<Yv�����|P�CL��b�Jmn/LB�'�/g�'8rjE��NG��d�������h���!UGN2�i��n��hZGNm���������YKK�������6��s�$!S�����f�XRGN-���A�] '��k-�J+X���AM�� ����sf�!GNb}2vbp�����Qy��g�"`K��`�C�|a+���=��s+��U��W�8���j�����h��:������vE	�K�9��l�)�<-�`;�A�nR�v^���t2
��^���JPGOiPom9t"����=K%��6������0e�K<�?)6��U���8~js,�9���d����{x�OZcK���~j!F���)�d�����~�����@H���?��W]xJ���vL��A�z��b��_h���Zo��^���X9�#=�����K���C9x��*��6�<���^�,/5Y��3�pr*k��!^���H]�u�Zm��
�ljkF�#����1���M�4�Y�^������k���F���T���"�P&S��6*�lY�Kz���$�����>�T
�<�1/1�q,���Z"
e�Vj�5$�_p�m�&F+��:�T�����:J
����
1*.5���0�u���Sc�7���������b����6_�9��Z�W��@�IGI��+���)Ad��\�N�AN|�Q#�A/+/�H�I����	Tj{���M3��K���<��q�a���4yQyF#������TB&�����M�F���kZ�v�J�l�K5CZ��*���!kJ.p7�S�}�S
�`�~�l�Ne~M�VO]�S?����g�"�V
�*3���N�0�}s=���v@Q��A��D�cJ9�vb��tJ)�i��u�.R{O��s�U��!/�tf�`Hz2��2�S����$%��`6[/o;�{Ob���$�C�������-R���>�Q��E��r:��E�X[������\��0�-z{z[#O��^��E�V���}�z���iy����bxw�~��E�&���5p�4�h����p�I�^�����v$:)Nz�n4]���w�M�Q�{�]�0��f)	K^�u������^������,����,#0��Tt���Fm���K�)���:�*AO0���F����iM\2��Hk2q��l2taq�#�`�GXTi��#�H�G�!��xJ��jI	Y�m��'~?8jo����Bi��8��y$R���X���/f����IU���}��wN���Y���[?;�ql����%#EP���b���%���)����I�0jK��[���)��E7���Q��f�Ro2F���p�0JCF�8���0�!�I)#�K[50���I�a��90J/k��#���������W��gRA�#��Eu`T�`Ne0*��;5��o�7
`�)afF�x��Q�F>�F�:�������Q���Zq�:,�M?v?��[F1����0
	/���,����<��Nk��l���f�F0��~����S���A�CppT�X R�L8�)I�n�z��x+����SY��N�:�����1(����bm�	�N�ZDrZ��Q�m:�%e����H��W<J����A���G��9��Q#����L}L6x�������n�b�g:�<J����(�(B���
>�qn��;�5�]nG���B����5�H+P�"+�r��7�5�a��i:Fjs�����s
�3�m]�H��X~rV�	�xeO�hMR��A�j+w7�2�� ��wB�g�A,���N<9�'c���T*F�� ��m�u)gY�7p�A��+I��� ����R���*�VjP�T�?j"���AZ���'�M����w�U��_*��|�x g�\{�U �����+�D��������T�����6�k^	������p(����lE�9r���Q����1��X9aq�=���9SW���)�cbCN�H�>6�!ok-������wn����X�@
�r�������&=�r*!k�1�L�C��QuY	*T@��7��T+7����o���Si]��C�
��N�6p���Bq���L�d
)n�\��^�����J����z~9p
)O?���X�&X�V����+R������|A�K��+������+G���M��)�i��o9j���=�D^M���@H�1&����TA c2�}si��2ZL�$I;�^
����`��K)���\�ih	z�I>���t�*���+�R�%��8d��a5��B�@J�4��Pj�	�'��V���Zl%�f���m*`�x���_��*pRYC:s�XhJa����<�����`���F�����O�l�2�O+��>�X�
M���%,�g�B�S�%-�U"���d�;#r
�!�uR�B1A�+a�� ��g=��l<'=Ol�&z���-g"!OKNyi��;�n�������
���q��&l�)�)S������_�
��B�
<a�+b���
>�P����5�(z����#YA,M���R�T�Y���Y	�#(�mRG���;�:�j���W| (�0��A�����!�J�L�I#Oi��h�y\�OKB��@*"1%������I����R~=����rGP��3�Aqb�&CA���z��]6
A������
����N�����5�A��������h�_i��)�(������O����[����k���qL���j8d�:����-�����v-2�� ������nQ:#�w.���(ha�)L�m!;d��!o$:����HQv�Z&e���lA�=1Xk���v=18�  ��`0���f��!�������I����L�C�d9Ybpb�\=1D$�9�6�����hy4��Mw����n��W���������r� A)���'����g����s�\;�e�(�=�W�6Dw�~
D"^+���Y�9�!"�H����:"&�.�� ��G�@DmGcvD-�/���R�q7���#�2�J3��������;�l�(D���N'cm�Z�o��DX��
��2��	����RB$�������r@���rl
 *t����J�D5�&�����������"y���d1p���l���2��I�EuPTL�
�����;�<��Y6�
����G��x%������L|�rp$[���sJ�V��1�D����$��y��&����1	y�
�J�{%�'�Z�k@A�WD����LY��6eJR�"l���������*���/�N~����Wc'��8������;N*�_]������r�
�C�;�g��2���U��2�.]��a%h���zT
�$slJ���@w�
-�&V��������o^�nEk,��&,�&kP�/iJ,J�6g����.1��}C���!A7��muR!d���P63�j|6��B��-9ZjSV����~����$_�L^�����:Z��U�����Latd�'�@�7�2��5��^�v<Nn� S
}X�+���I2F�e$O��J����?�2I��:U��	B�0���2#s����C&jb��5��
�<%���^�	��d��Yq�<P9d��w�o�)�Y�\J�I�cMx�9�$�m�B2=CI	Y�yK�M+c�&����3�@��j>*M!��|HM�����@��\��<�!����?jzg�'W@�W�2��ys������/����������L���� 6 �X���}.�i�l��5!)m��^�t`� �y[�Iz���1�����d�����& �y��I��j���L2g-��I�9K[4��JO��&��F��d���}����v�{l9��)5�>���d�9w��L{�Is�/�s6��T�5��)�a��RN1�
8���_�
��O��op��9o�=�n�|���sn��"��.b�����b21kx5��JCf/,�(Q�w�x�B��E����`"%CPm��jR�yn�V/�����c�R�Z�p)�&�0�>t]s�L����t'���\2���YV`*�<<g��ss��E�Zd��X*�w��u����R�����q,%M��D�8�����?�"���i�����X�x\���7,���������g��Ceh
o���h�k���w�
M��Uh:5�����M��.!�q�����
MQ��EW��0d�!����.�t�5$b������6)�<��hJ��%_J��M���g��l�Z	T�����d<���:����GF
(�<
�M�$c}����k�EZ>��M����ql��v�7�s�c,V���]���5Z��.zGTe���`���CGT�J�~7<U�85�S��������
�k����<�fp��T;
�N�nIU=Xg"mpD��_�fCl)��sxH�	D=�����
Q��`f *�yX�e�
D�&Mu�/�@T�e\���vD�E-�IJ	D��uX��tDe���XsQ����I�yz[�*D��|��K�Z������8���B�k��pC�
Qarg�����
QI�3w��^)f��0�����R���
D/N�E�\����
DU�T����5����@T�6�P�Qa�����o���SA��T�V��
R9�y}48x�a�mD�k�2Z�h��Y�
R0�:Fj��
R4$���B4$�p\+HiA��KW���h��z�L� Z� EC��I��d�5��8��S�U��;=Y��.�Y+H�\�G]*B���4���ZZ��]�G�K���^�M���
`WMyU�@[{�0m����*�����='����bz�R VO��~t��,	�;��&�_��2�gTP��W��uM�P<����0!6�P�xy�6��;JCF/O���`����Pbq5y�v<;V�v<;�|�x23)N�!x��kF�!v��Iq6<"�����"�P�Z�����7<���iWB���H��r!~{GD��F}���"&��O�5�W�a�)��TK�a��nY��+S��
�������7<�\�������;����px�6�Q�=��`p���k�4���]%a�Y�!��x��X�eH�<K�V'K�S���2d�"JS,�+?!JKV�r���]\������H�5�k��D���d�|����Lv������`vPT"&�����/B��6��h������<4�vX����$Oy�[T�����
���]�*qV��|�YQ�P��n�%�O���~�����p:t8J�!�|G�\�(��[�M�q��f,#Q�C�Mp��4R�x/���N�/@�
o��^Zy[co�N(r�s����/?����_+oI'�>r����V3���'ZS���y��O��.����.��X��+����\�[`F^V����6�����L!�a
�����q��H���A�K�K�A�)��)�PK����1j��jp�YR
�9K~���b��.9��Up����J��l��rX��U��P���Z��K!���p
�B�VY����Z��5�����E8s�sVM �)�R�c���v�kVp���Km�q<!���RZ���V-$�R����jX����dA�0��X���"0L2'��
0��|�#	l�	<��hZ��	#�����L����vE�-v��S(P�bp`J�����7���eNf&�-�A��� �NR�����0gO�#}���g�B��t�X�����M�H�r�S&��S�[��CI:T�-����mybI�%��F`�'qY^�V0)M���{�z,��������e)��k��d<�c��q\�H�.wo=���
=����@�kk�����u���X�a��Yi���Y�\�0R��:S���#�Z�
[5��@)U��G�T�������/�9�Q��>�4v�<�$Hpl�C_v��2�����T��(���N����
�5k�'X��#�c�Ku$9R�����$.�q����H��ii�)'Y�Za�<|HJkL%�J*s����L�`�X���k����O��R��H��8P�9�U��Hr �0�s���Vx��-��Xjg���B�rm`)��v_(Z*U
Rpx������3�L�Y���N�
7��:��(T���sj�S��+�K3v+��S}��&E���6��f+@C����<���IJ>���?����p�
��[i�m2�pKG�@i�z��B�l��y�=%!~J�[���j����Q���f�P�AT�2/�Om�aS	�"�J7�K�&���y�� ��,��{���^��o4�y�&��z	��,1XF�*U�_w��Q�rpE��|�j���h:��j�+0T�]��R���=�P��@���6�I�R�i1�%���;���c1vHYS\SR!4)}�6$E�v��#�4�?S���S �*M+�\J*�=-��c).R�(X*�����i�R0�m���]X*t�R�����YYn9f�;��9Y7�
K���	���mX*���UhB�X
��g��-K�A��oKn�B<��.
�~58�TNe
�J���/���TLz�a��H��5@*� u�������E5w���^�}��f�j�+��4}��z��37������+�9D^�"E���k�Z������m�;�Lze-��$G�'�aU�����-���Fa,HVP���d�E�.��$GYyV�'����j"����B�}����(i�f�	wbTzf���p�eE���aXN���hq���h�F� �����z�+�X/��;�XO9�jg��*��{�3��cs��R!2D����nT����A���
�q��#"��F"�!/�n��b�@D��+
s����;e-�S;jQ.��4��Q�r��En �����4�=����`��f<	W�h�D^'�:&JC��cg`"�"y�6�a���l*D,���|~U�W=��;��g$J�k Q�*�S�d�S?�~�v "�z)"��4~A�����7B���9FB�2~�zy�	HB>o��A7H��������b�Ed�d�;9(�)I�QEX�7gJYjb�	�!+�v�tT�kb����)F����zF-�� (=v���"~Sz��
���a����Q��8u�n��)��
����fi�F��L�`q��2��
���WO�<"=��?�A�Z��<������wz6��5�
D���%V='-UVtT�^�m�}���6�mi�oh�m��m�n`:���Q�zqP���'��:B���J�6�$Sz;�����v�)���������U��1��S��J���Om�c$����$���wB8��<<��c���J�3z��)���)p��b�6�eE2I�kp����rE�0 ��P�����K�&i8�6&�p
NL�I����$�]�Z��Ve����ey���.d�m���p�X�c�9�4�
&�e�y�F�-�b�4i�
��6�L}�t������L���������Y�
��X�
y��tY���S��)I�RJ
�^�|�3e�I=,
�y<(�E1m0)����r!P�P�B���'C$�%OKH�8�����N����0�{O�#����5�� ���x�h�H�s�R�[�R�W��v���������F�v�E�_���p�RhC���;i"�b���\�*�:+�Q	y-A���o�����������&��`�QSC��$����I��2��H\��O�8�5�����Q���h���������oT&aq��^���:���4�4�5q� p������XjsF�%����9�q$J��c��A��M������PS=�Ap��)�\��dup����O9���5��n�;��5�94����p
��C���YE���/a����<��y��z�M��`�=�Km�)���%r�;x�9/�)$�3]�����yY� =_�5w��5'�8	u\���d\�<�jO�����r��Uc��4��rT:��S���n�;�
<�&kr����
<iu��-Sq<�9�J�����)�������R�Q��B�G���V���@N\%v��U���(�	z� ������������N3�L��J���9���\������I�)��m�AS�;����.��
�N)��v-�{�i�v����i=�5P��[o��������m��Y�J�����l��������M��q���8�jM^�>�|�R�GDBj%�dPo�Z����
z{�����)9���#�8�*�)�4n5�"���(
����oF���M��+�~9�aT��0:5�q9�@p �?�v���#���`Mvc�
H����F��Iyj� N����[���X��Z�2�� �T����5 {Z��)�`��(�Sbw���t4���h���A�WW�~�����f����Lz���sMq���R��B������J!�}���C�6h�Z�3K@���G��P.�JE���y�	,��N��~�x`)�J��R�jTa)<;/������R�R�������uM���\�������.��_��o�M��|�nZ�zo]3���018��8�$zhN����_ ��v���U!d�^|#cw��(=^�:-��F������h��U0%iU%:�)�^���U�NeQ��L��sl^���JN�������������(�oH"	Yo�}�I���D+��t��*�.��x*R��k(��^�J"^z_s������������K���7f ��V��9�����,I"���k�����NG�]�w��_����E�
��vn.����#���Q�5vO���E���^i)��ARY
��"�����kb2f-����d��s�&��A4��zI�c����7�����Ud�z%ZB�I�������HB��8)gd�Z"�p��"������^�WR;8)w
�I�8�E��C!)����5=��5�"������j�k	��@��CN�%,_�0k5�:j�/�
(���d?�+�+
u���.G�`S�<hwt\�0)d���+d&�N�R��g�����{p-�l*�Im�U��
�xaZN
s���y����l��L���MB f0	�r>jn�
&�Y%
��I1#��E�am0)E����:Z�rO����1�'�<�Lj	���$�����r&���QR�#�io()���X���^��blJJ�1`(��#�}p����@I��������9��I9��9��aI�����Ff
�_m�������`�d���5)��S��}/��n�t*5����]D�W�����q����3�j��-iq�x6�
-qJ�(�1�$!YO��pN��ZZ�Co����K��z!/�.��^�^ku)�jy�,d-�My�Q��>�%#�a�R���f>v�+W����&�	�M\�+v��5�)�����S]q���MU��c��m��+�P���z������F����v
!���(+xk>�|����`����J��Nm����X\�wR?�	��}b�29�gZb��
������^�
;��X5��;A#�J^qN���I9v���R�r����}�c��
;�&�QG����(���V��Z�70���JumK��� 'O� u�)�W��[�0k��O�p9�6�"GJ��S^�:^o��?�G�:����7�{iE1�O�@�d�]��*���Q����n-�g�*���W���~c�P0h�c�|�H]���A?���i�Pm�hM�`nB���nO�E�5�aH�kTD�tc�7y��5�.q�GP;�������[���P)dI�n�'�)	-���[�B^kk>�F����]Q���)	y')�z�k�9����R � �;�����k@��2g��;��'��n�`T��0���`�F���7\Ma�x�Q�N	����h1+ve7��B�s��7�Z	$�&-w�3��Z��4��<=��I���c)�d8�^Kw�E�����*��4�X�M���5X���w�Kvj]�hJo�r������n�y�@�7#�\�@S�JZ�oh*�<��af�
M�����M����?sp�C�j��
�j�)=6�TahtS9ML�������<eH>�L��5gR�E��a��F���V�����h����IH1��:r�K��0d�H219�*�Dv���N�LZ�I��L��������)����15gy�)Yd��9�!Z��?�u0��FY	�3� ��d}�����\(�t`*f��9�J.70�Bz�����bAQ��aS!d^n�G��
L��(x���
LA��t���T��U`���E�L���/��T���"S9g5`*7b��u0�&��rp
�^.M?�&�08U��������RB��|�?�:��l*�'�������)���r�
���s��;��w	N��19���IOgJ��,j�@_~ 8�j��h���N���������,������S�_oZ�������Jt8�B��'�q9���g,MR��`���5����RD�dLv8�B�h�'s�,�����H�N���S5��W���zx�Uc��"�T�@U�W�Vx
3���t�S�d/C���m�u���2�����j��N�{8�=����DD�&�0Y���eK:	�M�����]ka|����+e�Z
�Z��D��!.�?s2���&���y�M�u��!)�#"Z������[<����fPD���u38~Sz����V$�#�E��H��n�x&!��n&{������v���I/6Ku(��f����K���A��/����Xn)y���p,�L_�����G�F	(�q���n���R������>5PQ��F����P,1(��YKYS����q\S��>�.�%=[b�J�!z
`���F>�Y�K������D���c&N��Z�5�$_��?�����R��D�����2�-�(*u��Qx�WF�����{
iR`��n+�������7z,���D}��#6�1XT�����O�Y>+>�G��3X���
�p,KX���8�2����M����ai6@���M��E~\�����S���$�}������D��E^ ��`���+6X�e���
�N 
	X�� ����M���
�\L�R���g<��
{�R����C�Z�$���������W���g���k�ER=�J�+���U�(�o�9/�g�-�N�-�m3|���F.9��6���b�KPP�n�Y�p�a�l����mI�PY���`K�|�G�(�x$�G��^�5�������[�D�(�b
^���<kfIF�O���!�]��D=&���w�����Q��N��U��!�g��E
���E��a|pE������(%�;R*u�����6N�'�������H�tNmK�UQ*��*�m��T����0��q���������XQEn��B��K�L[��"��I:�R!k��#��5�D$��W�
+P�I�c�I�&�Iu����s��%NI7��)�/��}
Yy�o+yN�|�`IB��Q��?�9�|�sFYR�Zf�u�$!N��5G!v��51�T2*!S
����gC�?[���.Rk^q��N�@N��P)f@����"P���l9u�m:����y<t)��[���H=�_�O��R�����Ek���f��`�3
�m�	�X�Jx�9L��O
<��x����g�1I{���Y�q�Z�q=�T�
<��^�D�����=vtOt����<A��J��J�k	��\��)�����x�� �e=r�&�BFe`V;H
x~�l?q�6o��@i<�S��N�d�l��S�xE��7Ov�/�e8*���S
�����Q�"�s�3����c����v�v�����^��d'���������L{��
�tUYkS����,��y�Q�E�3!e<hr��8�9~��%����O2��~y�U)��+!�Nr��9yXbtJ���<�`�3�n�	B�E��]��Z�;�a~j���O�����T�)��:z~3����=��+�45U;��U�)}���v��;*��@O1t2
?����y,d%�4�x��T�,��7�D��bG
�@
�T-/�l�������4��S�P����	����ie'���V�)
nj�z�Uv�����B��@O��{v��IN�����zb�9AO��2/|#~ m�)��,=J7���4y%)=��W�n�p��t���2�y����Z��TzW�����jck����?�[��D��A���VfJ2�<��������Z���#�=I���kMA���%oT���A��Jz�$�Vb���+����I��oY�6�F0%���NJ$��|gMA����?!��T���JvA��6�rSV�X��rtUB�������J!���Z�$C(��z��U�O5�I�=~K��`�U�;��E����)��3V�T�?j8�yrp"S�^;��a�V5��A��X������p�j�B���qG��(t�Zx-��[��6d�C�<:+�6d�r*�2m��n�2VZ���:+��c�����%����\hAz�E�K2D��U.�4{���[7!��W����ti�*0���5)�U�h-���%!��\���ne5M�R�:Xl;#��]���T���-���@K�CR������A?���O������-2n��T'<��|CX��rc�\�/��8@�D$%!��!�!�Tc��[;
d��X��DFOBS��#A>�Q��]�:6��$L���� ���GX���t�#�I�1�GA���hiT��"�%3�l��EXy��"�Q���:]��Q�x)��""@G�L�%:\%��f6l����(�O�8q �|/�|4�Q�1�L�����hd�������~n�#���0�u�F��c�p���,
%&��`uT�f���t�"��%��j
�e���tH��x0��!���b������H
����A��[�:�G�L�`(%8mpzPT�NY	(d�	����R��?8
�
Ok
�v���PP����N1�Ys�����&�@�t�e�J�i�kB��h��Z�uE�m�7cX�#c�~b��`5�v����Z�ROfo�+Nm�c�d�������\���1��y������nh�1�����8�M	��47(_}w�a!����;kh3:�llpx,��AF�!lAD����z.�^g�:"
-F4]��A��/C��c���H�2nw��XF�(��������B��x���7hTzc�c���M����i<����n�k���S�H�RC[/��GH%c�w����#���<L��$�kR�!d_Y��#sZ;"Is<��i3NB�I�8�Y���&��{F��	@���������hJ�v�OPXHr]�	@,���"W8��	@�������X��<�X�\b� �dm�H��k5w�r8G:�`Jg	�$�s^�o���F��N���g�W�;tj��C@���Q*����k����8�S<�S~�N�6����r[n�	�<����$�S�c|��4v�����N0��Q��Vi�sJTA'Z�����C'Z3�yy�N��'�kt�������H�;����5I��:S!� ������j@'�X7�!�}��7���+b�Z��`����<qV��s�}����_h���z2_fn��|{Z��p��5���7�P+���,JO���~�J�������q��C'4%fQz-��'�~xj��+�]Q:x�AO&a���g��@�������O���
>��������UH�z��O������<'++kJ���F���O0�nQ�����de��q��O�� �����������^��j0�]����3z��
� �w�������J�+Z���{��B�A��.�2m��iCP!����	y�6fLK%���6����7"s�T�M���wCPe�rS=c����B��C<h��{���r�&�?��@P��'�]A��u���$4y%�.���q:���4'I[�
AaN&�=�M�AI�v��xb�����������]Q��W"�N]QA��WMO����=GP�7��:�������B�@��zQ��c��^�"�[�J
��<a�
C��,����+'@ ��T��>C��.1�S���A�ZYq
���jh�6tE{���Z��C�=o;UC#��PX�g�J�a(ye��j!V�W�����es[6��h���/�
CQ�v�0&v2>A�6��BZL8�~_�:$���J�k���VC��'�7TjM����_M����(��t_>u�_���t��Z�[�Lc��7�h�pH�5��R.��	���|�2��S.�&�
��
�L�b�"k�f�hH�-���
y ��%�����(��!G/���K�9\a�DP������X�02%�
�-�O+����L$�{�0loc��m�Kd>,sD�f7%3��!�?�]2�i������_=����%5�hy�4xr^R��`P;M}n}s�u����x��
�'���RD���op����&��8L����C-��K�t'�C0d��7��]��<P�
�&��CX�� �!w,���P���1�)8ZL��O��C-b�4���CaH��YP���C0dFP��y�t:J3V^*�
8T8����}*��]��`5�o� ��9��O�����@�j��r@�^��(��������}��N��A�Q,�8"
�'#7�!����)�,��9��`��Ke-v�[�o�,��W����%��4N�����d0�~������h�f�b�d�����k�eX�O��B�+���P1��cM-�YB)&/�\�mBX�v��y"���*T��w��V��C�bl�������*<����rlN��u�������m�����M���eX9
����*���L��^����i�"��{.�Ues������C�B�(#���;�dqf���Gr���%�SM��8��T��v�����������T��5@��L(y,d��{2�P�$��2�Z�8	B�I���R��XC�j%1R��8RJ���J�����W��nM?�7&�L�b8�&7����}�
�j�r����6�pXQ��#���H;���� c�Z�h
!�e/��������g!��A����<�m���6����hN�p��I2V��MZ�eDZ�����m�4qJ�^������M�,�7��4@��
��d^)d)E���Y'P4�{f��������Z"�s���$�7��c�w�;��/_�9v��U�o�p*������8����j��@�����1h�j�����[�ay-���SY�w�*C��I�<�����!��:�?0�m�CyP4g	��8p��$���8����6I��ERS���Y�%t�<�S���zg�D8�&/�j���N��G��*�S��.���f���OC1�'	y�mz
����e������*��r�������8����j��~�����S?��������e�����[�j������"��I�V_�O^��������Y[Ws>e�w�x�B���7�	8V�b��3�6E��\����^`�^��%�@��iq��P�,�K}��5�Of[d����07�KnR�|vCR!�	*�&m����C�0���a�&y������K���J���O1����wcu�l����}�F��������6t�Rbyvs<�nx��xqFdfp<�������������o�x*WD��5x:_��r����T5��
�9
OY��j���Oe��d:p<9��t��H���)����r�����iN]�S���D�O3)�^q<�EJ�s�&~gW�:K����z�	��O���B�����������$d�C�<%;�*1��������.� �oeOY�Z^1Y�Sm�������V�
O��x�^������g;�J��AT��*D�O�8�~5�U�]�������S���p����� f��n��a����c%K��0�t�n�S�Yn����T0)K��0W��9�;�Yk��L��p�;��.o�"��&k��fk��B�3�������rCB��SQ�l�)�E�����P�y�T�%.�sL�5r"o�O
L�&��7���T�J�~7<0U�8UgT5�*��;�7P�	�6P�B�
T��P�jC��P�nM7�����'H���`5��F�8�J�%�Q5*D8ix
����1�M��Qm�Z!�^5�
�/��77���Z�(��Dr�j��H�5�B��x!tT���$��^5J���p����4~Q5�DXIQ9x�(���w����9�	YT�jC����������v��%3^�����vIH�u4�M6Gc5#��v4��+��jl���v����'d!�q7K>!���y��46��4���=�5�_�J����^���P��g�}CCe����SF!m��bu]�c�����7
���5k �6�������/�8�V�-��c�P
�����Z��cf�$����@m�h6<��]�t�;sC@��O>O*+�D~�(c�'l�����W`�3
!�~��4]��n�w<�e�
W�B��� �����gP9�GP��V�u����G�meH��u�@c��N���2������'l���h��*2�l]6f��
c�Z�����d,���K�Xg��5l15��/���8!���C���1�jS��fSJ7�����<�:5`Qy�)p��(��im��Fih�=�xwlT��Z�����v��!xg��P�5u��fp �W�o)�W�h�����rU��j�����8/�~G�aP��q����9P*K����_{j^Q���(�5k�fj�bP��Y.�f\y�9N��<
,�k�2�5}R	���8���hpI��L���K^�0�B>��su2�����Ds&��
�L�������������e�:d�1��M���dJS�Z��yR[Ru���S
�:R��@V��IVW �^u�)������8Wj���h��7�q3��T}x�:�b
���:i��)���s4th�S[c
]@H &��0�0���I�$}7�T�����bjk�H�����e��@Lr5�@��|�8+�p�zr��.��S9���4B3��I��6�<��{�}�	�u��0S�d0#����1
c��\����/�j
��5���hE�@���g�>6 Si]�
���L�=��9\�v<*��!S�}}@t�T2&kmUU�"�,G!�O��=�d�+��I���r&=d�9�u��:���X�,��jkZ�o����8I��C&����7�3�
K�u���X�(vbs�TBO�����I�L�|d�*M�����	K����s�n���������Z�	���ZFUeG�aSO4 u���k�h��:�S�@r���#���
��o�r��?,���S5�Q8(r
}T���_ �2{������6�U �6��_��&��p�r�9+����	�<�J�
9�5�N�3\9�5�9��N����8}�aSY����\(%��s�d���l�)��,���9�9��]s���
9���+
�~rjs�RB�mm�)��	O��*e�9��)�����I~���_q�TF����
��F�N�vp��fn�h�s��C�M	��^�)�,=�N��/;��� nd��N0�x����9��e�&�5
=��5��p=i������9��u�����1��
�[�g��s�7�ge���A�.����!�@P%d�88�����l����JN%f�g_�� +�T/�h�6�
��8�����Nx������o]C�*U��p�P�5�W�}�x��N!��Qmu��
���)���q���~�[r=x!��,��A�y9s&� J��,��6�%��$+"�S2i�f�����4�e�1:&����/��s���)�����Q/Q�),�����O�F�%���68E�&+z�'���9(�5�T��R�2��:��9I��
N����+@��
N�2�����`Pk|�p�p*
zX��^��pJ�s���T�e
��_e�o���T�����T�O�~�v �T����wM'z�i���D�k���A{����D����%�XY��T�R9���O����*�?�����E[���)���w����OmDF�E/`D���^�����R��+��5���]eE���$����I;g�D��9Hr3xY;	{^�"�x�SJ�����$I���QW�����V����}
��WO��]@5A`i0��1|go@�F������m:(����8��T�@>!��� }#�Ok�Dy����1����4��)�k�G���k;���"����.�)�\�B���� /���K��p$CZN�r$C��m�aPi�:D^�I���t���������9��5(�������j���!=Z�xD�;���C��c����������
�(����21Pd�(������V�l�G�!��E����#�[qXKF���D"2��+d,9�Q�b�>R���d��_*�C�
yY�4td���'N �^���\��?Dk��2����|#��l��b�3}B��!6����
����U�k�
��Y}#o_z���z>*C��l"�s6eHUlmB�YQ�=>��P�����^������f�6pj��c{m�����7�G1r��3l������y�/9�v
G���mY��4;X�6�e$��k��7�1/�lg)m�|����$0�7�hJ��-@R��#�,q�'��H`cp�Tz�k������$�.L� 	��}Ju�������vJ&K���Ir��,L��HjC������E���[L5
"�T�~����O&�#�H�s#�����o�����7`����;��l���}G������}���pR�xX�4�qN
!���!i��y�`M��N���9NH7���`����=���f<Km���������sk��eW���J��4��=����R��&��`���<��B�s�6�����[@�����=s�0O��1�Ky���F�R���0e��*Y�U[R�������b��K�������0�6�T���4<Zl~�^lJ��+R��i��U� ��K
v�l��B�s��k9o5`SY���<�M�f%����Me�RG��z��Mm����W@�&���f�)lJk&k�9���8�X�T�|���r���v_�H�i�aS��'����6�Ds�N�������Nz��Y������Xg�hj�
8����&i�Nm��/������Ij;���;K�WP�j�+8��Ue�K^�9������7prJ��"���Q��t&AN5t�w��^g�,�)�Gt&'A�B�%��o��h�#��	CN0�m���!���Yy{5��#'���!��eENZ����CN��e����sE�����9�&�����������n#r����WR��"�^�������Sj�|'��e�I�HN�����x�!'�A�Ft=vjU�N�e�����l��;Q��
2�����shnWrC�>q4�
>������u�<��T����%_�7�K�!��oJ!K�����+|CP!f)�^c����J���L
zp-i`�6(���gbP��Fk�&��\?��Y����g��
�j��\a'�r�
M^�NlN�(,�h%D�:���7r��@Q������N/���%0������8]��l8*
z����H�8*U��Q�gcE�V>��1�
�A�j�@Q�bT�(�x��h��
��t~�^���ZSU�?��R��\��Q���k5��G�{���J�Q2���G��{�Re�fl�8J=���<��=/c������d��W~E�[��&&pTi�/����/8�4y���8����I�����:�5W��G�&~����Q0�|�B�q�f����8�uq^��5��T�������z����[�Iax
��W��OIIu�Z��F��\��.�����*C�{zn{o�nl��U{����x����f;5*a_0�1����A���������ah��4�E2��vm��SL��[7�������6�I�g-�Cs���j���tkZ��w&���M�����O�[��������n���u��5}���}d���;�2������wBr�0��0�l�u����m
��f���y�L�mo�8�w�����
���57��Z�����7��j������&0����x�rS��+��>�j����������{Y��X�������i�*���������I
l!�h8l��N0
����9B�pM<�b�.��R_��8���[fR��@�`X���q�
��[�+|:��b���>�������P�Zs:n�p�]�]�aO�y��K�V�_z�y�������&�/����xEj8���i�
����`0��:�i��E<��|T�����@�����gb���7<���G�(���g�<� 3<��:8�t����32]���gZy��	<������g8\^J��p
H�g�p�)x��n�3���6<��:�jx��K��w�v<S��L9�grx���gJwF��31�
<���L��7<�fs���L=��l���2�L�e3<;��m����E8�M([7DON�b��p~G6D��L?M+���h�;�����:��!�I��h��<f���:0��N�	�`8D����t%���������p}�3D#��
�
�u���e����-�%r�4��r)���8:d9��G#�I��������I���4�xE��<7C�D3�C�)}H
@S�'�9�I��,:
���P45|�|?4�BOh����4@���]��&^�E���:�(
m�C�����:M��|8�����2N1C4zz��p4�
�34�l�������������/��r@���Ge6�T�����Q�M��������V���8~V�=���wh]��BR#[k�#��.M�� �6��M��$�^���0�r?�M���d ��qM�O�����N��K��g����l ���4��z��c��o�8o������N p������r����\��v>^���}WWM8���i��v��q|o+�lj��I����GERM����mMR
�z�@8etM�(��������E�qz�85�e�����a��^AJ��u}��#k��n�rh5�r��&XM�.��4�';Y��W5t�*H�w�������m���^��P��5u,@��ur�2�s:��8���j'4�]���Eh�n���o�1["Ik/�tO^)k��
yb�uL�g�K3��?���WD)��� O�}S
:oy��ij�h����!��!O
F�r/lPVSIg����(
��nxb��B>���OX�� ^���>�)��@�ox���O�x��7����(�4��	�X��'M�*�
����p������KO��@���O��|��#
 9i<!`�����{��6!���'��AO��K�������zb���I����;F����$Oj���Z��4:���^�j2~���	Y�a1�����4PO<�O���k#<8bY��`J����+l��aY@��k2����<�/.%s�S�)WW��]1�%�5R�S�$$�*�#�E��	����b��<9����yr�:��_I��<�7����xU�p'��*��F���V�'���eP;G�t0a�`:1��@�����sb����n��~P}*���r�{e�~��RX+��k!Su�������@;0��q�P��F�yX���f�y�b�������8�/`OZ�=_7�c3H�>�J�[8�iI��}b&�N��}j*��}�d���'f��~��=-��uz����;��Vq���)}d�@1��\U�(����AP���m�o��[��"��*����A���8�5mw�����������u��
^N�����������xCBe�uZ�9*C�{�;��h���<��zA�
aA��1Y��2V���Yc�i�h�����4g��!�����:#��Xx(��25���w]�<��%�6����-MK�&��e"�^���]Q�7s~;0J	u�(��40�w��ax
�bl0��[40J��F�Us`�k���\D�8bs�P5|�0��n`��4"b���F���+�u;7(��[��N~1t������@Gi�ct�
��������������;�$��L��T��VW��������	AYSLj?]{T��:L&����Z����C��J�53���I���P+L����X<9L��RC�"���P�2-t���.����FR�jp��Q.Z
L���0�7���o���rT��0��D�b�u@z%}k?'%��|���&'�S$�e}�?��O����X�{(h���X����	����6������fa�A0�R����A-�C%�b���NN8!�_*Q�G�?�P)�<-%g�
w�J%b���Tj-�Vs�9T
��]'_3:TJ��D�4�P)�k^�HO
��^^u�(�/��9T����5zxT���G�J1�=�]@�~�*�R�\�r7�96�k3L��K��tX*k3�S",���G��G6ZNhK�����dM�������+���d�+a~���<�<�5?��yq����k�t	�O��W���IS�&�����Lr���������&$y�Cb���s��M���M�B���>��1��"V���Q+pjF�d��z*�B�rxp��/l������)]�����C�V��#����FW@�\�����%��5yO�y,���i9}:��)d����yut
K��*o,!��S[c�e`�	�T�,"F>&tJsz�N�P�A�4g\���
���y�-p���g\���NM�jw��(��zJ�����"�N�W���t�9Y��33nt��D~Ntj!��8\�F�&%��yZe�D>����k����O	��^�2:�*�*U��S�C����5=ix
�b��:�������;Tza#�4��6S
���������@�f���	�{[u�c�����k�I���J��!1E}��k�+Y�eX�A(0t����`
D�A�aU�����+ltOI�V����b]���Q��
(�~�k.�%.��'��ss��Z��.���c�\���-I���g�mq";�����Sx�,��\L�����=�+t0UB^6�H(�`J�<�J�����H�Lh��4)�zx�����X�����U��Rmr�aT
~V�tS3�Dqe�X��f��a#�K1k�@�)�T�y._%c��p�&�n�� L&��i@�L�.�
P���}������0YdR�?��`�W5�����Ojq��y�T���SSRRq~�$x�A�x�%��
�J!�}��5s@�\��z+B��B�cA�'VTm����@�R��r�����������E��m����)
O1UN^
�
o����*�\������������9�����cKV�d�D�?��*���m�g��M?0U�3.����R�9�j���.7��0�L�=ryS��)c�L�����iS�EK0d�<�J��f2d����w�S!h�Jb����SAL�,�S��L�.Od%�0U	Y6���50Uj2����d�T!d^�#�uS��W�����
Bf+��J;��Wb*l1_5��Dp������[U���"5W�V�����s�\�����g�0�U�����l����>PUj�L���V�
1�K\�CGU0i��x�T�b�����bU�$���@��J&=-8	��Uq�<OV�8��E^�w����wKl�.�Uqb�C@��6���D�U��,�'#.R���2����QUyXa+u6TUB��s���
T�BF� C.��*	imu�u����,�PU���U�_�^�������@ZXCU5����QU�V�
3����������=4�x��Xa���|x=������f����y�,�h��E�,�y�,x�5|���>����f��Y�<4���"�p ���Y4��m����N�h���et��f����gm�p��R������m��T����p]�]E�m���4��S������b8&���������o@*�W�����u�0��Bsl.�y�����9��S`����7��i���/��Bgr`��qgr�CJg�t��w8���@`pF�CJ��>���p�����,�xy38C��J��,Q^��Z����xdp����+�%.��5��v��Dy}\\���.i����q����I�����2<S��J����D�x��:��L�~b�u�3�<�S���S���L�*�d}�x�����B�g����
�����-�Lo9o'�L��n�������g�p������3�����xO����g�5�<xFN�Q�3zzz<�r�7<C�5�������<C��X�����_��g����x&�S��
�����:�����h&�NU��7���
�s���
����<�+��m��a������&����fC41��D:�h����h�<������lc���*�
�`8��8�i��L>
��������hd{p��C{�@4R��p�4%�#<P%
�WMy�">[��h�FS8���1��x��NXhr�n��M'���4a6U�l�������9aL:���U�k!���t�a�Hv���b@@�������!��N�ij��r���#g[���I@tH#�)�� 
'�8����!���H�4�C����F����!��N���������e�o���|. �=^�,���F�K�f�i���L���O�4�d��5'V��/������iZux:����6K�����"�H�C���;6�����2C����yC5R?�Q�?�|�qM?��6\;n�&�1�z5��S�C M>�i:����\���x��
��>U�l�<t�rd��z
d��:B�!�5������l��Y��,��:��y�+�,��-�;�}�z ��3-���=8��G��\�F�:���O��G����'��}Z��fJ,�kb���>�a�z3���V�K�^3�����&������2���`���>#������M�o�>�.���g���l�u��0��pa����>�]�Q�_Vq�=���c���1y}t�:0f��i���z�o&
��G��&f3x���4t�����MU��m�=�o�����kJ��,���TJ�5wjr������>�24Sw�_���X� �I�jB��W�j���
�����&M���������lR�����p^:������
�h agC�d����-q�:�����
��
��E�!Nh�^SSx�=�����h��0(�D@u���D�a��p<m`����qxJ�{PE&	=�X���Q��
���_�z��T���7"6�9���k
���PO=������j�;�2���QO��O@�������8��*T��	�5��y%�zl�Z:�i\���P�C=v��v�����zZ����e&H�p�S^I7�@=-���OC==�e<�D;rE�$l�zs3�z����xz0����U�`^��5�r�DZ;�����W��k�nj��(����x���Y^W�[�`�x����>�I���" O
�z!o�F�|5��tH�>6�z;+f��3#�����4���J��d��II���*��{�V
8��E}��p
���=!�I����=@QM�=�3��G[��8����t���aE	��9�)�	���=�db���O����O����� *r��Vwm���G���8�����K[k-�C6}c������0$��s�S�XU�`k����_��6�H�$�{�@i�c����h��yH��g\������m3�� �X�=5����qx[�_|Ez&������k�Lm�5�M_T}��� bm��w��!���~r�a���J���cK����)����x21Zn��-�(��z�**�k�X���� lE9*��T���8��<�0�S�����2\�%�(D�-+��G]Og���xX.�&�6T�"Z��E��J�sq{�sT$CZ�.pT�a6�@E� /K��H��Hv$wX��$bay�QYGE-��4NCEr���E9*f+	;���s��t�b6�UTT"�k��7���ngu�tAE�aM�M+����
s�]b����z�z��tX�Nq�E���M��5aR��T�-������"l�9,����']8������=/4����t#T����.
!^���.JsV]g}����������g�����R��4a���&������k���K,Us4������gd\�����]���"^���o���o���s�F%bm���+4�<����!�Q*@=���U�~(�90�y�n��0�gsuaK��Q�����B�xm���Yk�7��� �bw����Q�x/��O����
��+�:}r���(�������a$���@ik���Uo
�A����
J\���7k k��3������xk
�Q��T�y�{�Wk9������&6����X
�4��4����P���tt~-�/;:l*�y<�/�)�rz�H� ���N	,�0�9l~3�aSj]����;h��S���R�Q8h���y�S�1�K���1�x�R����2EX����41���U����RF�����k���/�Z��5g��x-����Z��&�1�T�<JL�
�T��v0�ITjS��F��=�R�x.�����ZFo�a��0pR�bMw�U��Z��j��J�|��i/#%��� ��2�2� \�{������>=�h�o$���������������[���X�� �T&
4���*oy��gE�� �s+������f@
���'��}�R)�/-�f�����<�y.#����F�Hjs�k����0CI2�[m����$��&������f�.0WP�"��0�\���t�����5��q�$s�,��`��������X^�p�%�c��u�����^�!r7�L��$����B��.>2�K\��rBk@S?���C�=��R�A�]�7Zp�'x �|�j�S?9?[���N�S5vX��>��o�+�,\��(w��O�Kk��T����1#���%����'S��j]�i~�TK</�&I���D�i�=m�d��P��g��. ������zR,x�J��o	%��J��[����Pi���>�1*5yz2��:��9��G�e�����1^dM�
BF����h��*Q�9>k\_>;PT�&5+Uz�Dh��+"��������BQ�d�v�h��a�l-�
K�i���i?���B�ft���2]&PT�2-��7p������cCQ0�e�0t%����C��E���?E�=�	rd��@Qm������
E�=Q6��l����{����t��R�����1�����iV{���R�{i`�]E��<>_�k�E`�(y����(YS��lQ�?VD�`b�����5Q��WD��Up��+*,��)��A�\u����D�K��sjkAT�X��'��� Q����7��4=H���8���A���� �
�|�M�K���x	�.�e��.�@����H��8��=�m����(��b
}�(hb�/�\� J�v7��D��i91���ZHo!�� d����VQ%d���'���(	��"$��j!����aGQ��UGQ5�Y�~��g;�*�k8z���0|�`�Q9c55�j���[��'w]����}s��/����!�P���^��!���v�����<��
�������z�N�������[���
��u����I��V�<�i*T��W��k�:x��^4.=�W�<vZ���.zu��I�~�< ;�9O{u�&W�����������*�J9��=�vk���}	q�E+z�g�9�FTd{
��y��YoD��M�Mj�����R����7�Q�p8p�������}j0�Njj4�j�;4JvP�����A�M�\�j�<�;���5����i�j�M]��OwPc���vj����"����}�4jlye��9�1M~�4�8f���P=�&OV�]CZ��~���|��a^J�������L��\�P���8%&�hv<��L�P:������h&���v������f�<�9���u���f0�y�`�tJ��f�<��9�����hF���S���'�@3r:�St4���64�N��:�}5u�f�si;EV]>��h��u��j��j�p�g�k�
��k2o����"�L���w~:�k������T<k��?�HM�ZO9������Of�@4=�6D��W���o�
�����S�)G4���A0
��@4�=:�p���!.\t�����@4|����#
�1KC��,�
���&7)l?�&�W]��gS�oC���\Q��&��9eC4=g��4�wE{`�8@q�(�7�h��=nh�^���Hx&���n�hxO��|�3p�x�������u��V�3�=�3�x}�<SO�,�����-����X�g�t�4����-�������2=
�x�$�Y����<��"��W.���gjpU�����7h�����E��G�zc^������L+�)zg��������K:R0;j�h:��:$�'�vJ�$�gJ��Y���x��3�uO`4��	3#6@#�����=��H����!
���%7H���4�!�<�M��p��H��F��pH����i_=�!��y� 
�=���>[��^
���
����`�V�N+�iR��Z�7��8���W4��f�7L�����n�f�rAV�����9��'���VC���4������'_��I���
J����Z���0���[��P{�$�y����4�^�6D��v4�ZM��x�&&V�3z6��������Znd���=Y���p�����K{Lc����0��9����&]��&'���L��������D;|���������A#�7��[_5��n��G��K�_��@V���R=�I���E�?q`J+i�G20���a����<������L`�=\��={y��+�AY� K�^~8��]o2ek�^u���7q]H�_{��x�$[�O�d/]z�G�Df������L�lg��5�X�d`s�r�^�����I��8��T�}1�g�����8SV8C�F
J�
���{�����V8S���Ig�?�\�L����g���fk'���7@S��	�������sh�����z���a�49<��6Hc���i��Y�y�_7�pH�^_�b�>�=_�Z/�����$M`M�}�g��y�5��v�3��9����@M�\Ai��4;�i����9M����M���������}����UW>|��'XrX;������5i��n�NW[0���;1`S$;S[bA�H����!7�6�������&����
�
m�xM��&������������������C�4����sh#��I��MxvMph��_~Tc��Ol���H���i!�(�&'�����7�s��ym������(n�����-�����{������JBk<���?�M��bt����{1�=��7���ph����:��F���JV�Sj9�G6P��C�����q��P������C��>~qr�=�|k��2\q9������C>.�81���R�n�	^���t���=����P: N*M�n����J;�}����Sm �Y��a�Cd�Z{����5!�	dsBB�1��A�9��k��D�sJ�����V�S<-�
Pm0G6�{D����k��h!�\�e8GF<���p.[�sk�w��;g�H�
����������n����3	�<�h�s�[=z��l��B�iV�����*d����(xj,�e��J�����p������V9o���4;�}3�v}��r}vk�(���������xO��d�����X�����������^$x�=i��2c-���������������z��u���2f�H���\���s�t!�H����a?�C�����hn������:��N
���X��r������P�,c�t<��U��kj�����x	^��7`��2�;�o��y}����!�����)����K��k;)�85|�DE�^rJ�g�{������$�6��&aL��6����C�!Yb��Z��"H-�6+��!�� C�+�i;&����`G�V���+��kY���[1��b��=�afRC������H�����{$���|�S���!_������>�����]�����hc��O���?�K2�Fej�D��@���v�Z�084���@I�����K{�wR����0/A{~A�
��y�7��Ae�71��<��k�-��%k�5����\�);5*;���#�48�/�$�N~�ZwLE
d�����A��7��;�/��0���;j+�
}�L^sb�2��|b�� ��3
���p���zt���`p��#����o� �B�BP:���Jk�/�6 �nK������Vub����nu2,T*�K���Dj2,Tj|��'�O���aiR��$�r����~q������`���t���td��
�ub��rY������e�������CS,..Oe��.�R�qY��{��hb}�X��I��-�X��CR�w�#=��I+���d�mNe|�z�im�.������9����Q�zt�jl����k��oTv��Fe��j����t6��:���~8��X������h������U�X�c��4l��<��*�#���������d���)J�u����	�������2�vLt�KW4f�Z`���Ks_
���q��gl���4!+s*
'AF[�������4y�8�z��q�� �e��S�[fk%c��� cL^��I-c����u��"��1pR���I1��0IZ�m�Q:�R*]��b{CG�otv��:�d,S�t��]h-R�_v�������J���/�U����RX2m�@�`4�����Ew�	���,���RGJ�&a�
���3JmCJ0�ni�@[�H	��R��H�9�p���}f��)qRG&�q�=�d�C�����I_�@J����L)S�G!�d�
����!%��}&�����N�rtR*�+�7������)��y������tv��BgC�qnn�a�b[��J�{�O?����g+��+����dN.C+sk���a����p+L�cX	��aN��a�����&�\�����U�4%�����3u��J0��WW�:V�����+�E�5��q���myUa%��6[�����d��l)�J��1I2v�d=FnngX�z<jz�kg��>�J�5Z�R��8U~��a����V��Fi�J�#�`�W:Vj�����I��������
I�u���U�]���y���04��#�����@��%�'l�k�$MYD�]�F�D��l�1][%�����6�P��U���>�}�h�3m���K2�m~��b#/��YO�������^��it�M����o�hn��c�Vhu�@r��Mw��;I������[��G��%^����� ���6���V����3�6Z�G��3\���SYb�Zr�����pj�%�X��xEj������
nE+���
�������
g=�I���L6l�T0j8
���N�)���P
fZ�H�����8X��| 
���_G(��[�]�x0��0p�:Otj5l���21r��LC&��\Q�/���HcL
������?��a�
endstream
endobj

9 0 obj
52172
endobj

11 0 obj
<</Length 12 0 R/Filter/FlateDecode>>
stream
x������L�������4�%��G�x7v^�����60���"#�L�+�����~�O#2C�����6��������_��u�u���:����m���kl�i������o�������W�����_�x�����?}�S��~~]��i���������?�_C3��������m��n�g����g;����v�W�����u�g;���g{Y���������������,���_����-�?�������q����������H���������6�<m��o���Wk.�UZ}�����[�]���zC�5��*��{�����j��xk���^���������y��i���e��C�qn�����N��]u������������/��?���n���[d�o	����.������xK����z%	m3�9�����������W�\���k�u�~�X�n��i1O�b����>3m��S�Lq�������^��tK�)&�����J����m�nN���_c�a�?w�e6��|2��M��?���i��^�5���v���~x/N������g������-��]�<���z����C��yU���y5�S���@�P8��v*��p(����>����:���C�m���b�����[�Oh���l���{�rs�X~(7��_�����]n���vr��?����%���6���w�������m��
������m����y[2
�������a��o��B����a����o+�����-�l�������js�����3S��c>��p7���n�o�f��m�����Px��|�����|.������h��P�Z�M��*����?��2{���T:�v�8M���;hS~�����8�^�p��������}���>M�m�������������?�nu�5��[��P����H�=Cw�Nm3��F���{���L���������b�^���L{�K�����?
w��������(��$|���������uc�z��
�M�����m�����p��r�=��n�L������a����h��.V�[�Ca���T~Z��7��B�����M�NJ�������u�I��7������D.�w�x�K@ac���}���R�C��e��| ���v_�C���|4g���b
�a���x�_��h8�N�W����.Ss���E�~H�
������]��������[�iGEa{��6����QI��w�����ApGE�������t��������{��������)_����%/�������wJ	��L]�o��;A�m��^������;I����!��J�w���/��N�l�#�p��!���(l�.���pO6�����l*Oq�QI1�<v����_r��Z��c�������
��'
+��V|^���1��s�d��~}��c��-I�����-��:wKT���s�Al��Oj����3^&���������W��G�)��}'��jY�~x�_��-i�+������V%ksA����"PI����2����G��a��Z�����W�&�U$��������H�����_B�c�f���sx�{�����[&sC����pl���������|�U|8�+W:���p�/�/�p4��h�7�p4�����hR��>����Oj%����+�?���>NI�/���p>�U���G�N��@�y�C3����Ca'��������k������s3N�C���O�x
��j��Y��� 	;���x���'<�[a���f��D-�w�����3���������j�?�R���������fgq��m�C���)�w��M�]�������@�f'������h$��
5;�Bca'��f�tIT��` |vh.7�X��T�D-�P�g����.�o�����8f��w�AE8���M������d��K���J�����[����D�qs5�\%�S������f����j�pRVW��}�����2���y ��v���h�&���U\eD���8�
�Cc�^�t������<~1���(�/�c���fq|����-�:v
����0�p:R�8A�wnx
�����m�l~_�G�x�N�'��� ��h~_���,�m+���@�pC2m�U�����%���9�\`n|<'��KJa������>�\%P�O�!T��q���P�!��='�����(\��M?�\�����Z���xy���8��uss�U�f�
�C���qw��0�.��t��A
�C�N���b�;��AV��H����x������~�g�;w���yf�\Z�Y�H�)~��kJaIX���,��_)?�#��T{�����K�:E�R������G?a��
�9�g�� ������&_I�����3R��}V^�z������[�Ar$]��x��D�>^����;��1�l���"%+�����$����F��!������{#	�=7poL��;�<l������1J�� �:�)�����E a�_%��RV������l8'hS���a������]�I�g���~�����m��*:���Ja�Q{x!<�t�Zq6�������
A�����}���pCV����!�?�}v�����������mj��z�;�w?Da��R��h������3+����(l(����"��|���%�o�Y6s�)Wz��c�]6���5��,���O�o]#O�j#\�M�����ZV�]c8)�x�v�d��M���tU��7k#`�A���������*����������4��$���?\���w��ja�'��"=�v�����$���������Z�;��Ei�^0��+N94��OC��#A������H2j�:Q
����=A���I�'`�o������2(#������}�[�'��Gh�|�6���p����.�e�Z��3Fw>4����~H���q��/���Vjj^i���'�;"�Y[��Q��L��/cs��1=��$a�/G�QV��7��a����?�7H�'�Y\6Tl{���G3����u��|��ijx"��D�Q������_Zw��!a���4U��[�Ay�:�V�vD���#JYYZ���<7��;��$��?�(w"�;p�Uw�^�W�t/%a���<��D3�~X��'����xl����5�����/�
�%a��e��>�"\��<{jD���,Yy��k��'��h����c/tpc�w��]v�4\(�=d�~��������z)�:��d�Y%��(�x��*EU�������:�����R
���L$�X?����`Pu�cx#�Sd�|��)�����A��~T]6Qg����I��/�������J���`5t�}A��e���k�iS�^�����2t���	/d��}l�\�>��(�^�H�|w=�0�'�"p�c/�9���*����9<N
��������@����(l���ACG	�i���)�!���VE^A��9$.������^�{oK�����4V��|O
���kY�t�=P����D������i���|�L;Y8�m��f�	��6���%�������[�an.������0��G-+��$mN�����}��Tj���U��o��"l���g����Vn��������b��P��'�\�y��iT��u�.����b�*J�����O��{���oD4�����d������9���de�^����,�������~�_������w]�'�zZ������O��C,�T��N�;��]4��p,���K��}��������<[��"+�H�p7E3k���&�������}�>���I�S��m?�9��U�.�����k���j}|:�3��A��,/(���?�h�4����`�>���s�H	q����=(q��n��&�u��w/C1_��$�� e8��]��[�m���CyX�~���v�$a����K������'C�������O�f�������SV�a?���
���:�zT�����2k�(Y�'���h2O�Kh�M2�x��me�&�v�\��u�8�����X�8D+|d������o����`x���}��k�i��$�*?`6�$a�ET67a�^�������W\{���d���`�F>>�$Y�MY�7I��/P-,9`�$u�W�����(2�I(���s��J���Z�=�l���A��$�ae
���������R�Q�9��@���p8v��l[�M$�����
bbq�D�j����M�ks��3�� Pq�R�(���0�a{x���Va|fa�����Fg�j��kf�����&�v�53e����66��{�o���}���?[��GV���(�e�G�#A��mix$�V��#<�mS�����s�h�����5��2�v?Ze�o����t�oJa�'C�]�esH0��+���y/~k���d��������]��S{����5S����fw���~�>�?�{���g�+�Gb����sn��������k��d�cQ������d7�Yg�(�lS����u�Nu�}��������KV�������E�����Y��\�K���+����H��=	;�{Z�oY����}��9��K������� Q01���_>/�CwLT��h\�f�����u�~�����L��4�MJ��
_#Y'+N%�Q�l��sv?��isA�U{F�>������[��:�bx�YB�w���c�B-���~��(��������~����px!�*��7���X��N�#����^NX�������N�q�N����i��*��g��n�CW���3���w_	G��(
*������ ��}~I��V�
�$a��������L��7i�xS�8����3%��
$	���������o�G�j������s���H3Hh9�4
����|�d������T|(Ns3�Z���P����sqB�G�IXm�;!*VD]���^��pBV���A�sE�N��~3�8yt�c�����q�g�9�v���7�P���+C�^-�zJ�����N��`�2�+O���	�����&��l���?����l���*m<<-$�d��+������T���k�]tdi^Q��{����)�Ba��5���y(h]f-�[�:�����cQ9 �
��_�)E}Gw,V��������Z4O������t�o1����[$�����V��o���+��o���@Fm���\ ���h���f�24}s.6�c��������d��i�55VD����(������������q��/��L���(�l�,����.���"����8���bw?VT�(�;��j�>���"��}S3u�x��8o���H�����m��(���y�r�
�a��������J��} ����
���4g:���-H����T���]�f�:tM��.E����%|:����L��������-���~Qo���#A��@Xm���|4g��N�| �6�3���d�Ti��
��e���%|�����K�pC�u�H���2����q7$a��>��!4�.�^�3v��
����"��L�3/d���������t����(���:����<��v?^�E���<V�D���+.���@Xu.Ox�N��9�-���>� �m�����������/��^��~��J��=�����H�G��]Q���](�����Z�?+./���]��U��t�#ae+����=����������;<����O����������#ag�iI���N�i�atS�����o �g���Q��)e����H�����}��������F�wxQA�>�Ze
���@X�W�t���<g�Q��| l����=���3v2�rj��v�������Qj��%|����/����>�#aT�p�A�N�q�jSq�
IXe�wC�����{����o?(�G>}O���.$�lrV]+|���=�����p=�U��}�fB��H<�.��z������0^�%�n{�+�AD�a�
;��(����+�X�����cd�n��N~����ph��S�7���������:���W�e�u�)���~y�qD��������7���Z��o��"����<g���y�����K��@���E
������)*N	���s<���|��{�����L>��ea'��a�#)��w��,����H-`s���^!9[o���H����~�Q$L�:�!�Q$��u(^P�}�YX�	����H�i�aT��`S�yNViu����Go�����O��Y
���j�������}����j��W\�{da]����`�������
��z��'q.Y\������p���~�>��f��`��wo�zenx�����T���)tf��`��r�{�VD4����O1�6����,��JO&�Q�Y�[���:�*�<�n���du�>��P��Q5C	{�F�0�R�wp�i���y(��7$���#��u� YV�<�N�j�)����ie���;�pH-��,m��i��%TT�e�*C��!ud!wBR���-�O�e�G���$�v�l��LR�^w��M��/�h:N(�%;��	Y���	���R���,8�*��!AX���8-���C�0
"��lI��J�fe� �H����p���WR�;��	du���������Mu���)�v���q����BY�uw�KIVm�[x)*V�����,ex����������d�mn
��,���|���6'Yue6Qg�QX��Vn���N���>7N]�}�@[�Ox��m��A������d������Xme��Avg����Bv�A���>����������t����DQ���� �����5wX)���dV�'��(�����2E�SA��AD�E}�"��t�CW�����c��c8��,���jKOmH�j�������(�U;$�C-���
�a��6�7I�����P�<����>��K~��e;jwNR�l�[���%*v2_����������������l)���J���M?�C��3+�����$��c���Py�)�v�M����s�U\�Pg�);�=G�N~t�����
7m�V�
����������M���*��'S���i�(�6�:<d���oI���V�#+�����k�������X.��ia�	�{�S����h���S��d�
��1Mey�")������kV�a���!N�������)��Q���'a�G���$��	ZY|�.{�g��-�.��e��pYV[8=<�o(�+e�^Qv�f����2�f_����\�}��:�]��9I����\�d�����7q���&	+�A�IS�t�D� ��h?�Sv�C��n���R8'J����	���WjGa������z'�K����s���*��FV�q�k���J���A�\*�g����J�������$��?+C��#-y����@ w<�����������k�������!��,s��]��D8��\�?-��'���mUT%�^�u�
�a���#��9Of����9���x�h%q���j�+���2�g'���� ��W�	w���M���O��E�$>��7"a�O��^����yN�p���������lM���6��j��uED�����g~�81�|�������E���s�ct'Ca�A,�c5F���s+�y�c(��l�H�8�d��j��6���"N%��.�����U��**�����A�����zu������Ne�f8!��.^H�}z!Q�z�B�bs�9�AV��bx���\U�Z�?-��T����(k��|������s/������F��i�/qwC�m?Q{��2y���m�������pM�l�5Z�����]���L�AY�����C3�L��+r�����	�j�o�M)����G�i�&�V��Wp�M��d����}"m	��M�l�v����o�&�Z�%|
��w�����W�Ok*�x��C����&��Z���Y���a���^�+��N�#[V�#|�Fw�D��!�wH����9$��!����xU�����R��-�n)$u����sg2��Kj�N;$�t���%����-��������IAg���?��������;V�5�'���W(;�n�G�U.���h[eX� �V��1Z��h���<���m�9���hZ�K�ssQ!c�!M���u�KjaYR��$�vvG��mEh��df�J�v�D�����Erx1����3�C&��8d�L�:K<�fVYp�G)+��$�*Wm�GV����������m�G\��S���7�?�ay��a��?N�v�R��iE�4wH-�����0������7l�$�,n4��K+�����*v����OY�(�p���kE��y�a�e|������;������&�����"�i����MH�jE7�$#+Y�y�WF��3y�*<s�5��:R=��$�,�����"�V{������z��5�4��O����_X5�Guz�=N�����,�� ��G��&���GuP���^��Vn^JV�&���+7����#�kI�e�c��d��/J-��3jQgsS���(�s7OT�������|�6�#��8���������nX(,(��w;���F-�:�{ZV������_��a��M��e�r$�������[�sL���W��5�C�^ZC�v)��u�>�[|���$uN���0�V}����U�bYE+e�\asR�U[(���U�����g�kz5���r���e����H�P����}SK����I��f���8|P���r$��}��PV�������r�pc3��BJ%�#	e86��Gvg�~//�6�"a�y�3Aau�7'Yg��b�^�SV���^����
��=��{����+A�����o?�M�_��qPXqYS��"AaEl�G������0s�CV��as��a��!�:��n~��U�������"��=R��#����0�#Q�>��#N�H�q�$a�q����Y�'-����eO#wD4n��)!���������kn]]c��g�q��v�g���������]	W5
?a��~FfV��l~�f�U{�<�����q�Y�O��K3�tr<�����?��?X���B��r7DYE@���7�i(�qe���=R��������{ |m�����(������:Y�fh�f��emNY��������|�����8�"gO\HV��_����M^x�j����@Xq�BM���h��������nM?���i���%�XB�}��'���P4�=�VAa'�e�u�d����Ea'�Ny�N���MM;B@���7����a����	�T��ag��R��������pI���._����E�>� ��}h���n���@�u�}�h��������=$�,�c��C���l�X4����6#a���������;:����un��O��IX�9�8^�-��f��wI6S������$��Z��,jVY�>|�o�>�f���Y�����o:V��pT��CR�b�?��S��2t,��
��EE���k	?%�N��_0s�S2�\2��YLw����4��wN�������TfwTv����*'���
�E+���sGE�j�
�QQX������pPv���W�?�tx���/QVT���g��~������~�������V�����(������<w���*S���\��������HwS�����6�WA���T���[U�
�#�O"]��}K>O���knn#���-	;M�o�{;�zC�j���w�v�zC3����u�h]������(�\��UF���a�������P��/))lsR��������L�����S�?��>NA�N��P���0v�}X���a,��g�y�=�eu������~}s����������G�������,�dPkb��v~YB:�&�����pHV��nsH��n<�z�����fdw���{�����Cm�^H��)��i��)��ZX���$�,��3T���A�/r������S���������<`�%|D-��=����B�7���mnH��o�R�Q� ������U�����~����?m�'�8=X��K@�����|���@�y�#3k�x����}�G1���n��������q�E'_|��(YS��>j~.���!������T�$��6�!����?u����V���U;���hUYrW��lwj����U����5�YESVV2
g���/���`(����(��	���p�}���p}=(�B�����p|*��m��~kmp,����>*����e5q����?lUN��u�)"��%P�;wC4���*�0Q����;��)"�j~$���m��d�
I��p�t�t��p��zu�XyE����U�7d	��H�7����PP���(��tCZ��d�^���|x!�S�#��i%����\�����t�8��_�e�{���=R�>7�E���c2�"h�9��$�l�nV|�|d���{�$a����5Q�b�X�fnk��, p-�q|����V�e
�$a���O����'$�2
p�S�5}��W[�)y2>���yw���d������I����O�����B_�q�Cv:�����C����+�pD)l+O~FF�~|�����u?k�f����=��A�C�DY�JG��'���U���C����t�d3O^+����w��Z����m����
8%a����$�p�.}sD2�l?	�MW���,�����K�;��h�YG$3O�:���#��vmZav.��d]����E���F�NF��,`vq%f��&���e��=��%Zx2`-<�������
���C�������R������W����JF�vU6�Q��d���h����Y��s<�;��{�5����Gag=e������'=��������,�
�_�l�I���'_�����8�uj��/e����{&�u�s�[+�]������'�Ll���$����*�����]�
�$n
�N�XI��O��bdx)+����JF�~�������<�^��~��w���uz:��H��C��=��!<+��;�<=y�$���)	y�����I�D3O�6Y�s���K�����.<�%�M�G[��M)��n���$�L(.�{��N���.I���da�]�m�1��,@5�����x�'U���������-v�/K��������p1�Q6MfN����-����������p6��Z�5�K����q�^W{/^����Q���������,��6%��w�Z)��6g��j��o������������������p����F�a��6�(�:�}�&��?��M���J�Zmk�p%�u�}�1����m�B��Y���������1�0d�2E+�n��k/N��������&U�AZ��m�J���p�p%�E1~G�_k��B#j���O�0�DP~��K�
'N�5��Mk�����~cs26��g��������%�`�
?�g����5����p4�1eo8Y��h���?|���e���d��WG8���y����f��>�E�������s�#Y:��#J�}N+g�c����"����Z����e�J	'�YPS�����U�(\��}�(v��M�����|��C��u]�u��pH6�_������RXU*[V���[h(w���d����#���bCbX����H����(C�����L;W7$1�&�f�6�Q��?���U�w���$��-�\��G�����-+B�?��!���`�[+�k�!����C���m�al.�>�+jnf���bm>�����}�GV�E����	wx$�C���Dx$�VyE�9'�Vl�����d������d6�����Tb[������{xv����e4�CjYg�AhY��!�qER�lLl��.��y 	(v3��m3Y�/���V�l�V?7�M�be1�pEV��-|���-�
���}���n����(����	zB�����C\���G��o��<^�o�H��.�2�ADv�����_8�q��$�l���6]�.��,;��<����a���4�I�M�_�E��~���\��*��3	����d�i������B��#{��8��7���oh������OB�U������p�
IX����� ��G�f�w���RXF��S�����W�\�i����.ZR��QI���$	���cjka���{'�s���:����r�D�N�:q�����S���4{>\��	���� �pC�P��H��~I�:N�p�D�
�#�+��������n����]����{���Ia[wx�-.�g���_p �l����
��m'�[�*�Z���L*q_.����k���/2-�7��?��a�V����U�����'%�����r��M�������V�@R����X����<>�#'��kvQEVy��Qq�I�c(�����Z��3P�������/N����tD����i�E������N��j��QV���<0�$�Q����T�7��%��+��&�L�2|au94�x|�a��r���U2ZT��qG��~�;�>R�2�?��d�<6����>R���:��d�����0��qG��y����\�z�e��ee/Rs?������}-+~�e��Q)��2�:���1��1(��<�V]A�����g	L�v���#���u�"Y'�hYV���~)��
e�+�(�9[}��i���+^c]3������}^���c�����(�u��c��I���-+������x|�<_�1���_ZV�������2����^(�����7��*S���>���Cnf���X��������84m���Px
��|������CY�~��F�jk�����"0Rn���HTmE�:�U�b���]�N��a�i������|(W�R�?���DU���#�:YU�<W&�����k���C
�E���&k��Q��X���y��O�s���@�.H���s-.���H�>��W�AVZX��FZUCw#YET[�#(����@����i){���c�	�p=��E�����;c�=�U[,|�dq���92�0����n�r�L��-��������`u?�L��/�T���>�E��S��]��o)�Gy�$k*.z�/������U�4m��&VV
0��&�s�ZE������������������u�/��~�2xj�����k��2�W��\ ��|~�V�F��&��[�L+}��d��O���I:�����/����px�p�O�D��P���L3�CY�m)��3��(~��k��H�~�K*J{���(k�=Q����'w8�U|���<D-����O��o���m��������u���?�Ks�/�����������0\����������O��a�����r����Q�wU�~7���G���o��(���'�������f���HF�?��a�/���q�4��������s�����$��������������v�?��%7�M7�W��%���k���U�_~�������������������/<��Z���i��*:M�f��s���7���������pi.�����k�K2p~?f�v�_����u���[��n��K���vy�a�
��v�����@�1p�5�~�5��m��8�����47������|W��o�n����mn�b)�b������m�Ji�f�_��������~
�0]�������������w�_pr`�����Oj���\��4�.����|E��m?t?���_�������}���Cs��I�^��j�tk�1�]���M�����^�~�5]O_�M����M7���s�T�����*���U���������%!9�]>}�a������_n�p���ww5�6.�18������Y3%>������U-��T��;��k����tzx��sQ��~������^���4����C�^��X��S�5���~�~���k���}�N��~j�>����k��z������^P<p�7]7�Vo�
h�C�����uo@O~�����7���/|�m@�_@���s?g@�_zt
t�����k&��R~z�|z�l�4��p�)�M���`���.�F����p��:Y��@�n�xk�0o��3��hrxKH
�)���M���M<���D�f��A4�7=;����A4���hD��.����oV�$#�����O���D�����%��hZ��-*?�]�M�o�d�F���9�P�^���L��(�x�����F����o����{����xiF=w1^}8����Bd�T������gP���kd��R5�j�m�~�,c����L����a�hL�S�I�g`�3
�n���4�w���0c�4R<��]nC3_�#�*/{w���zd��������m�w���<j�����/M{M
��Z�t�%7 ������w[������'��]�~�_�
od��cwi�!]}�.qAy������;��<�~�cH���OG���7�����e�����d�w�p��:�i��^��_��n���<;'�FN����W�'��fN������+w}{���sF����Sc��Q/�@��Z���z���M;��}�;���4����9i�r"���L?�oto��;}(i�c�*�x������6e��I�c*�r(6�N:�dX�a��U�h
��Zi���L-,�*��s��'����^��
��ng�������'�yO���Ho������h`O?������I�cO;p��SfW��h�>�=m�6:��?��mz�]�?�~�o����������o=1�g=v��uJ�c����[@Oio���N�'��I
z��	�+6�I�}n���U�G�A@O����'��9�p������.���V*�����%�o�5�'� 9���}��E�{}���e�
g�=)`\^:������v�����;a+�'�?h�������
����as�	��	A==k�����G�����V�08��5�L����w���|]�����'��=��)�������y���M��/����P6���X��7��wQ�a���
}�z7��BtO����f����o���A��"`�8N�;�D���q
��|���F@t}w��@��F@!��n<!<�	H�Q��%�K�w�e�
6���#�
J�1h3(�����g����`6��7��'�h��S&�V7�'��HS��en������Sck,<uNM��p�����
x���2���������6�;�EX���=�2��/|������uj��/
W���SN������+�������YoC!�����i���T���a��)����>]l�����L���N�����jJ�7���m�cN��(sl�Y������{��5�*��ihS#�@��v<Og�X�B_���`�:���y���o��Q�Jw�7j M�~�6`|�5-��~�a����E����6��t���n������8�45�
�m�z���3�����r���p����Z������:���b�v`��b{�
Y��/8�t�I-&����E��_z��D�,��qH��{�g��;s:�@��g�A?iE�''q�'��hg�Mb@P<��R��n����Ba4�4��+�8�`"xQ�����#q�6�|�b�~�����D1����MI�yR����q��De�����k�D���(q$���t$�!�G"(���@��!�D�x`HLD�����&\y��	o������E���D���mP �D<1-m�-e�!K�o���!t��P�Dh������]r���J�**��WQQ=�.���Zq8�4*~5��H�H������_
v*��P
���R������r]*q��Kh��{��mh�g,c��� �������Y��k���I?\��}HBV�Bjtc�����wB=�k0�%�_�f�IF�FHi������fnA��0v3))�k3�s&d=���
J�_�la%:�dx�����iW�C~��\.]&����;)���rMD5��vh�S���5�C���ks�%+s_�X -b��4�i9M2�#h)�����<�
Z�K8���-���=�2�IZ~����7���Rm=�i9���M�'`O���T^��O�������A�^����?~��v#&[��=���Yq���U,aN�Jtf�9�$5pef��pl}�6��-�]��A�fj
�vqj�����pV:�|���j�r�s����D�7I��
#��B�A!�}���d=�,��IB�eZ��7���EK�4)�{��������m�Z��\�jp�6S�����^���Jk�W��J�*pN��=��|-:�F2�)<������g�N�qO7p
!�86�4'Yc�u�N0���,/��k�8�9v��Q���y���P����<�WM���-�Tg_88A������Q���2�r���WNr���4	p����nn��������~=O�KG'i���7tj!�U��"�{��/_�05��nx�S�_�Ne<m�o����!Y���
%5�N�x
=���jW��k��ag-=��iIB��vJ���zjA�c!o��_�X'���5y��1�m�'�-�DG�8=��v���',��^�)=��i���z�5��uz�&}��$s�$��0��z��=��-���RH��<�so��0�}��fE�H�����	��z����8tr����JZD<��Z'���:�����������\sj������UT���'>��|J�s|����C�5>�fx��g�zH	@]3�n�K��tg�2g	Yy}��b������fz��eb�O�(�d���2����e6]^V�[N��k��8��5w;e)Y4Y%}���;ve�X	�������d���1��X���S�S5/�ry3c�V��X(2li�����F��W�)ir�`�t7�����'�8<��X
�O�=������S5
�#����g�����U5�
���H�J��BU���C��$W3�p�]qM����C�T�����e��e��O�@%{f�F 5	��=�����R��e�m�AS��O��S\d+����9���c���n��������N%�����5�q����u��y'9�.]�?�%��+�������������]�����"�����Wg�0fh U�L^�N��U��a���A�c��M�C��'C��!�xt���bQ���7c���:��I�����`��Z�j��m����@(�Y#p ��*�,����^��A�uY�V�ESP������hRvX�E���H�EZ38�G���-����@)�2ZqZhq�,e�Zk}���L��5V�CP���0���<�]q�Bl�
Lv�*1k�4��@����@4H�
��I�%���%�J��F��(���U���������Su[�W��~�x`UzS�����zpY�����o�E������j��:��������Fa�]=^��VW��I=kuE��%������m�����Sj��`8u��~ �p�v�VW4����������;���{�.�6oL��K��yc2uY�FG������yo��.�������-�����Enr=�EO��[� 5x��r���/�v�-��V��*���z��9V����^�\X6p*W������@k��v��M\�T��:����������1�4P^�6���:.���Mh4�y�F/h�<���`��'l@�u���=]�0��.���b�u= �cX��d����7n��]�C5;mD;�E|�h����J���<c'�v�<�z��$����������<����,��~n���y�31�NS$�gj���A9����f
���!�?xF�S���3�9(Z�<��u�<#�ue��N<\=�h��L����S'b�O���j<c���:�3v:]��x���4�]�~�<C�uP����=��;�h�%9��n��V��~6�;��gW���zC�U��v��p<hu�I��g���zy�5��0�FW�s���/����&�?8�1�������h�<��
�����t
uOwh������F��������h0�D�u�b�N4\�������h0��A4�:���D�9\��F��H
�}��q�(����*�&��S4�~|�������q�I�a�H��n���4^�Vl&���+�h�����[�-���S�@�nu4�M�T��?i�|�I�RyC=\7��p]1>��t��@M<Dv:�Hy�9eH������.�I�4~zz��'���4~�N�0�}�u�4�8��oH��r����-7xr�)��6��4xv�&M=�������������z�����
�C��V�v�������;�%���������m�u#�R��t�h8������>���i�x��L����F���i/�T���]XP�+�����%��j0\o�7��p��TC���4��j�p:	���uT�F5t��j�g��I�y�i�T��������������k��mM)�l���gS���k_-�s�}���&!`��5��WK�P�6%`M��k��5h1��/M{E�@&��&�(�h������<�
p���&�=��z��'�	����4��9C��.�S;�����0Hk��o�����I*�@76�	kQ��h������E�C
�����i?��S�W��Hw�������{9�hnl�#��t������g�T����z2��������@D�O��B�:"��'<����qs��J��8�z#�4aNj�8���$�����@I�N<e�Z����	�P�Nm��G�k��"��x�G���CO��N<��r�.�tOn��n���	���y4>��yj<Fl���d��'�������bpO�%Ro��3Fa�A<�l�	��gS���x���� ^�\����N��x�c��P:q#�x��|XB�� ��`�K
�N<i���e6�I���F<2�6�A<2�:c��	}���&���F<���
�I/��t��@ f/qD�����s8i
�x�D�8����U1��'N<)��N�N<9��sA(��k6y�x����c�@�R�"K@�]�������<1�����\n�m O���
y�mn�Q�6���n�L���N�
���A�3	�p�)V}n��S0�13;�S0�1a�J��1a���YA���Opf����X����+��qk�`2��&�V�V�'c L�����3V�u
J/;��(F�\����B��[��A�����
}��O�������[��O(Z��������&@��_��3�+��������|�q�@9�N���nT"��!��X�X�����S�!)���$gM����U�����^����9�'V�
8�C�T	���� !,H�h���!��:#�m3������Y8C��9px,��e�
0c;5�n����wuD����09
+f����PXlD��#�LIo�`,Lf�������NE�6(J��HN����V;O�����WeJ���CQ�����qgP"��v-�����x��������5�[Ci��O��YE0���I����z�"-�o4�� =�(:������ ����PTZ���r�z.^��(�H�5&{�����b���n�"9����X��<��(��QHfd���QT: ��zp~C(��U`Q&�:i�*��Wvl�E�x�^���,j������N8<l���1a`Q����Yg_%a��&Dj�E!��z�B������e��t���/!�r�C���dLL��T'#���J�-	��;[�F6�U64��LX��&�pO�
�B�#�K�p�������!���9�F8��;�w6<JS^�y�$4e�
6�R�o��USIW��`:�)��H=�E����)�/���
�J��������Y?K�|y!h|I��?t�d�������V:$����"�^��:�f���J2Rjs^�7W�|�����y_4�au�u���K^�{�x����|��j�I�LI�o Sy>X�i���1tC��C���������<��jpd���5
tl�1��3�.����I�?o���ts�v��S�U9��4G;tE�^i4F�86��5��_����jW�+/����4���=
��i��T2����=�)��[�=���EulJk���,�`N�\m�s^��[:6aqz���$k�h�
�hMR�9�I�c=���h������%����x&e6p�9Y�L/^���98�o}�o(��B��%v���:8�?���z����I�=����f�����]T*�6�jp6��4K�+�7l��e6��5��Z���X�:��f�Gaz����G����y
��"��M����r0�P��A���Y�NS��Y��`8�I�<1L�e���[��%-k�������Ajw�T��V�b_��a-�#m�<�����V��U2�{��<TC
R�xx�e*��.�f�C$�5Tz�m�\�:@)���o���a]�j_�y�@��Kdul���26jA�8)�
��c)C0�e��x��Z�L*���7AI5�5�:W0r�4]w�YI�n�G��JF���8��1��,akz�\'i:L��DV�
]u�E������9G%�3����H����yZ�=uX�5K�a-�5O�mC��%���IFu��B�r�=f7�L9'�o��2AL2g��R��#S���ZXc��yy0S/�k�8�d���v��r���QS�3Z���i���2�6���
pj?�����kn4��
v��U��wUJ�o�;�)���g�\��7���Dw�o���J���Z���
�B���[�~8�V��~}�g����^�Wu��6h=5��s@Vh�8"
��q}�@�%}�
�����l`�M����
z�
��0q��e^���[�
�B����)�������
( b^��h�7@�y�
��f�Z��A��o�7�J��v%�_+$�&x���AR�5$U�+������T�#��:���]��jW�t�.�3���T�X|��:��X��x.Q�|�,U�L~�H{Zg)dA
#�tK� �a�9��R2hJ�*����-.�}�_�W�FS\"K8�*�N�t��"���|n�r ���Dk%5�Q:M�.�������rV�;vE����y�OH���T�y�=�z[�[��^�����a�����:�8h�
zxp���mL�����5��v��#]=���Y8U��p
��T�wN�����o�E����9���\���j���u�`]H�ZW�G������X)om��O�q����C�"k]��C������[��x(������i���#Q^'��M>����&�np��6�H�N��]�|���cSo����-Z�|��!w�y����Vk����Y�~�>ov��K.o���/��Y%<xvM;FD�P"�9�K�Zx�h�C��Q��J����.3,x�m����lJ41����`8���p�&���i3�Dy�������j?N4x8�������T�������u;'�����p����kt��
N��p�}�������N4|���q��pM4?l�1e�<�yiM)���m(�]Q�\�����L�M��
gr8����yI0��������9w��s�vG9����$�5x��'��g�t���<C��s��L
rH��N��3���:�h�+xF��m����<�����=���g��)��S>x�n#S>V����<�wE�!)G/�D)����:�����SM=��V�[���~bF�]�����<����gc�\�;q��tN41�������w���SXH
����A4P^q���:lp#��+�oD���7���!�!�&�/)���C>~����h�py�D��K�y��q����X8qYy�DC���R�����F41���h��m����ygM��i+LsVS,G�]Q,G+���	����R�G������0����X����������h:�t���uj$�GSa��:�������XA1t�t[v�8�`�W�#g� #�wv;��[�;3x���6|������G����O�B9������K�����/�vn�� ��N�y�3K��*�%'��W��
\
�0�Qq�W�C������G�O^��t���YJu>h�����[#����m.�+���t&i]�!v"�����x�'?�X�t0�@�`0�5a`����1��z^8�p������n��: ��� K"�R=[U��P;H&�~�DPj��D�Y&��[��dWDPj������t�a�G
�����A�(�z������Zy�G�)	Si�K'�����c�+�q'N�����obt_p��i@#{`z]F��������\���v�����e<\76\�����k���Wu�5�l5�}���rM*�}}-�Q�X(������i�f���lr�k�i_��d�jW�+�cs��=�����c[k��mB���F��������$�����OL�Jh7i����9��	/��V��	�c��0��c��������g5om|���7����*���>�j�x�����9����v��}��~�<^f�]���������X����C�q���/����2�,2����wRqj	�)�+R�����;��p�f�;k�����J`�;��#����S&d���w���dg�N������*����h(�/x�L�����
��2B�P���=���gt(�F�D��#
(:>�GP�X/Y��C/O�%�
�r��FK��5<1O=c�'�
{%9���5<�wE�z=�5��b�7�I��
^77�Ue�m��<5���5�������!Y@O�����	���F�0�.:�&F���3�)#������2#t�1k���xZ�[b�S"~�,O�3�i#�L4o���h�>L�>��5�������64�)�0��x
}J�Z[N%}��t!�>��K�����
~h����~P�m
���9i��?e
^q���8������I���.�~r���nMl#�a������|���M?�������O��I87����'����D�v>m|��.���O����������x�/���S�q�����r5~�"N'	X�]Z�>���D3�hg0t9X��TX<Jn$���w���X���b�)x,�zRf�SP	���9��5jj��
�N����9�`�,�3O�6�z0������T�2��Jq�����

��E�S��6�x������&�q������X>9��WpPi������������$�3������ ���c`h�d���IQvXC	�4���������y�C������SWk���iz2��O�O�a���-����2���g+9mNEm�3iQf-��'���@�P�)�,	��E���;4.�'�����������L�/v�����4����Qk�o��a{�R��G/��3~�{�#%a=�m����F!�g}C���FmI�	'z�)���:�Dq:&���@AG��c7:
���C�Ndp:&vP��#������iy�`�����"6Z����I*�xo#����E�;�����n�N:L�����������c�����JH%b��Q�Tl���d�i���P�i�����InT�H1��v����U���$�I��B*�����}�~�&��qA������5X�s���`3���M�AR�b}����C���[�����7��a.��u��v���L�Ib�x!1���NJ��i��Y/@����ca� c��s��;+qYZ��3VJ+�f�Bm�=Z������$S��\��+������ve��4�����J��������"-++a
����6R����i��0�yl)=���++Q�<�Fk^���nY��k���x�{�R�d^k��z]�\)d�O�c�������6@:�vc�6f=��6�Ji�c=�Z��J�.����-���eL�,6V��,Q��N�R�2����3X��x������ERH�
��0h����2��B���9s��������(&�i��v�,9�S� �h)
�[��$����B����RN@
.���)Z
���|=�KP<�X������^z�:������c������~&-j��B�O������\~�3��Z?��n?������RO'�6�>����u�M���\Mi���dy�y�����������`�����t���	���M����]rs�\�,��V��G;w���<-��k_?4� sxJs&�)I���&/�x�*���hV�x4�)�g~�G�`;�?��Wm8���f�	�Wl8��<�4��p��~:�GX�P!`=G\n����3T)1.{��|C��y�<'�r��5O���4w�js&�.u��9�$J3
�,U����1��
s;C�5��9�����8I}�`(8�D��Ug�����p���P6�'imdU��K4����9C�&����yZ�������3��jig\�d�d'}���P)��3����@T=��~�[��4�b��WA�;��4:�����@�o.�a>x-D���Ox������5zk��b�1�SRx�(�h��Qz�y6("�^�h�hEv�&0H����Y:��=�9�$�t?J��i��T�c���>cc���%#l�d��d���L����o|�������,�*3K�&O;�1lK��z��{�y4h���.l��T�bQOp�;R�);R5x��U���TNaLax,$��t�R��)�����\8L/�fR]�*q�D��a|8�z�� �:N���S�����R2���Nab���'T�S6���n�S2����vM+N��q�c�D��)�s��~���p��������_��z�
�8U�<#�C�iNyy������Y��U�8��,�<		�Z�dgT�Rd��zGC�If��TO�s���������
�J����S�~����*��p��q��_F���TNI��<+�����������E|�m�m�������n������&d]�)	7)K:��[��qI�h�7��zZ
�N���\�
�����!!)�'�-4�x�?�r���!�����Zk>���nL:�u-������	������~|v�nU�x�U��H�:��2l���`�O���m�~����x����^��=�������d������?�<���%oN��Clz�Q$U�t7|y��!axM&�^S�V��kH�5hY��T_=�
<|gt|&|180�6��(�*������T��0'���0'L|�������h �.0�C�t`N,�Ov��C�!*)0�
�(����&��9�8�]k���[�S�s��R�3�#o\��SS��������L��x
7�����9'W��sz8n��sj8�����tL��c��������z2�����b��r�����4O�Q	�,��x���0���xp�@�l����d�#�[d�SXP�<}���Z���	4`����sr	���ky	��sNN`�"V��f��|8���W����S?����(Q�'���	�k�>� J�t�I��@$ '��y3�V����\��|��|F;����.�z��v�z�� �����
����l�c+6prl�4w�<Y���FZ�7H��|��5?z&;����
�f
���xi����h���Is�y�Z���o�@��"��l)���r�{��������wB�O�����z&_�;�MJ��|$����Z������P2��\,���"��=�'�hy�i[<��l���T�P��+����K�E�@9�"W
�0�����T�k�;�`��� ��?��d���i5��pJ�P����sM���6jB������[!��][�hL����h9��A�Y��b�Bi����i�B2���AD�U���6�(���Z�.���h,�?�;8p�O<���F�;�
��vj
�
$��\��I�u���AB5����z,��I(W���'W��+�����$��=�h��{AB1�e�e�@#��\�Zh$���p�� !�A��ABeFd�[Bi��{�>#!X���� !,�N�H(�1b#!��m77J3� N�g#��"���$"Z�]���6j��L�m$"I��FB0����	���ZAFBe��+L\�u$<��iwJo|`K'�x�L��NB9m{Bz�$�F� �7j	%
4F�����]�Y����P�}��]��D��B�b,"������,3�EE�B��WR��X���B�B��3�u����&")��,D+ �5X��T��L�qG��0�	J{q������^�r2=�5%�\�e�Is�*Y�����e*��z|�i�V�������Q��K]�A�qP�(���<�wS�_OE/��U��������4��e>H/
������ �~����O����"������`��eT���u$$3�%hE�M$TV���n����C�������0b��� �����P�h��jNB!b�!�l��k�"�
��b=�;v��B)��7J=���$���s��'���r�+�8�W��P�r�B1�3cO(�5���=RCBer	��T���m3���S�[��x�RV�27
q$\{vIm4��Y��Pa�`���9��]`��)"/�vX������^K��:v���q���0�,�Q<"�j.lh6J-�,o?x���~���Z���f��VU=�,���9�a���sRQwc�^VkC��TD#r*����q��|E�5w�zx~g(X0�w�_���E�F�8+�?����j�OE"��b�n'������U�;�O�g	�r'�������pR0�/�*��d��b:3C ������6�AFmG��d$;���r2���I>��Q�x��H-���ER���sa�����a�Mp��d�"f�}njd��<��U��83:����hm�a��
��\K��HT����r��Q�	#����L����Q=�j��M��CTjS�fp�oDK<��c�p����r���3�x,a^{�R���0�$�0�X�)��!QXa����KQ[�b�j)�v����RLk��
�X��i���~�0�.����`�����&1YL��j	O�J���c={�
Kh��;�X�0�$�Ig������P
�����)�cc������9��|o(�V���/�?�q�r�O�[Q�U��6����\o�s������$����B�����f P��L���Z��Ly$e������A��`�e��%��/�])
�zUA��a�*�#��W����^~��p��(����g��EZ����9����FR2�;�O��D<��u�r6�����Q	��(b[D�{��"j��8Q�#Ma���JQ;@�Q�*�k���$\H�k�N�`��
J�|9l}��/(y<|i��R�
������%$;KzLJ;��/f����r��d�����,�5�$��A)����TxP���q��]�������A��f#%,�d�=�B�<!���H	��
�K�9)�����n!����*R*+���U�R���������R��[�d�<�B���^^����	9*����B�J9<�K��|��������gg��Ji2@:P)�Td�w�f�d��X*��j��C��J�s�}�$�����zr�m���fy���O0p����c���w�@s�us
LX��� [�^���Nu�~�� k��cT
��j?��2i��I
�@&i�������C�������z�I����5�~xo��m�au�B��u7r�oo:���[���� ��t����dT���&�~q5����g��O��sM�7�5;M�56�2|���i��5;�njz�_��C���aZ�j8i�2��[A�L�SZr_#��R@�����w�I�Sh�c��X�4�)������3��/wJ���O�8c����k<L9�q��XD��>iJ���
�Z��B������."��7�	B^�Og�'yZ\��4zk,%�}b�����1�4��	Dn�B�<�'PeM%@�d`*c�e5���h5��2S�.*j���WT�\�#_��]���A���tn����|����5�j�
5z����|*Ty����&���� �]l�h�
���%R��G�Q0�M�^�����^��,�6����1
�Q�i�f�����������)�����/9��r�d����5c�\������f/�ff�_�LA��&?0�Z�E����
�B���OhN6�J!^���b�Z���V�S���i���|��0�`���),E
S�50�7`S���� ir�nT�9�m��r;��[	S!`������j���4���y���D��)p��I��9�����h�5���_'*�d�\�B'*����D��k��h��0�n!�*-z�PY3}�kL%���e���3�'�k!H1�T�X�t�r����{E���Z�Jx�����WpLUB�������T2Z�!�Uv�j!Ok�
�m%R���P"�!tPHU��+��zx�T9w5��z�*���\�?�&W��j���0���.��k�z,`����D�lHb�41o�$h�����,�xH��5���o�`���t�#MZ��J.R�I����[R�E�~n���R�E/�]*m�H������
k=�a-�RA�{�
��k U�����Z�T)dZ[�PX U
��6��_�!U����oH�B��t�HUB��v��M��_u�K��b0Urk�`�������LU��������J�+rX���K��vm�I�
�QU�x���Q�J��T1�%��{ ���P�n�E�W��I�f�k;U��.W�/�,���W��IS�`���QMzD�	����H�������Hk�,�Z��Y��N�p�����*sFU-f�ezX	���zf�|��*	�wN;C:UQ�3�b�T�B���:1UA��C �Q�,�4������]B����)�'�?�"�A��U9�At2����P�g~��3�AU����o�E���dk45x��|���8�������k�,?41���O���Z��������MZ���{�K�^����k��sb�
������/�y,.r_�9��/�Qm�����Z?����p������4oM�Sh��:�t���b���n-_���f�`
����j���tc�j(f��L#81:l�X�XzwV0V��ms0V�>�m������#��(���AY�^�
+X�������[�^�PN���~��������8������8����`Pj�(�
�00�)��+*(��'����	�xU�-��s��A��zD�[g9���
�E�s��c�-�aNH���9�I��aN����9���^v�}�#�ZX��&]��xc������MPN={���������;��`��t�}5x�63��fR����K{�����������F9%`�����MI�{I��/��V`@��s��YxbIzoI:<��7`G�@[���\~�x?�d`Ofu�p������o��*x_����%;�
xJ@��mHx��c Oh�^,�u��'Mh���\�,�[;g������!����-Qd9���R��w@�����xmN=98����z��}
w��URo�)#�#4*��������icJ)�er����=+��fp\��>2��G����b�N�*�i�M7o��,�%��K(�����,��������X�M��v��@`���<��o-
D"�R���Z�b�/��h�{I 4���!Z���R������:q�0(S���;t`P�p�B�WT��3Vs�����A5_yu��ri����A�A5��.��"0�D��
���cP�x$���dF����`F��d3���0�Y�L�3k+��l���
~m�;7�o���HSx}u��B�B� ��}�^#(��Z8	������A�D8�	������H�VPZ#��#E��b���~Tx�77�~�mM�f9��fK������t�+�.pj��NC98O�/C���MP�?1����T�P<��^YAP��B�����[B%�K������������B�??���z-�6��B6��+
q- �"P����Wu���0[N�:
A��b]�P�xY�P��Dx��("I���B����K���	M����������b���F&��8
��t�(��WT��2��:
a���
�xM��~���/������=���0c���.�0TY"5��9�cVQ�#`�Y3LG�2�4C~��P��Ypj#����P�Do{!�f�P�+�0<���|x������@���`��a��j3f���n�{�a' �3�<����B��V���/�1�I�
Q�I
���?��Q�~-���h�a?e��/"���}��kNE�
��O+^���\
�����D+���sQ5�+2�^2���c����c��}/Hf<8M2���cpI�f�M����Y�QP[�&4��XC�dli1�,�7�ZDkU�t��m�����o���Z
AD��>�B���!A(�t+�(F�q�B�@r[�Ar���P5��[.`
����PiN�)���q
	����P�]G�/�$l������]^7k�'���8x,���P)��:j��)}����J��l�V?����J+��"J&1B'ld#t����J��vaAA)��:$;�z8Rvc������^�$@M� ���Lv��7+�Ih0�<~/d��6��kKt��a�;>&�9�NP?>����Q���>5�^��1r���?�t������K�;�d�	������o����."�Sh;������h`O�x��Y�I��C����� �6�_����K���>)��Y��������f$������D��9��D����$�i�V$����"�$�9H~���q'���ezi�(�H����#A@k���.�JDR�h��_��Wm��C+^q(*���~�`G�\�D�*����O����b����v����7�FE9��	���N�c�@������*j-,'9�J^L�$�(
����AE0d��YN�dA�d\P���h��"�1a����l�f*JzUAE��]]P����"^�K*Jk�=j��T"Z����FA�E�RQ	X?t ��OH���X�����Exv^�T�0q��X�zWl��k�(S���E�v���~V�xi.�A��ci�����O;����E!b���|��X�6�}��(�c�y��t`Q��q���,jCV�`��v$wu�Em��N�J�����8�!��
�f���IJ�c~vR��&sA��X��DYq��HZ<��~`Q�xY�*,���!��E-`L��c����"�PO#m�f��Kc���5TON�X��Ro�,Z
<�1���l:�.��0��:��*.����,]��C5z�N�p��4xT���%�cH�J�����p0&�����6e)�l}������;Dm��C����c�&w��l5����Q�����A�a���D��,]2�(E�-�D��q6�!p]��Q��U�������3v�uc��B���D@c���'�Yd��b������2:�����
�\�Y���.��4CG��SR�Wm��+�8�����'�f����{�����8u�����F��}0P�5���?��t��s��fc=0H����H���f��H�����p�@I��v-�u�bk�L����*�`�*�������S�[��J�|����B���I����/hN~���������Z�M!di���Z���B�q�@�{v�*��Kem�o*��
n*��Z�����yH���fS����S
��F'�~=�����y#�aj��aW�����Sxy�&x�9�e,{���W������v��M�S	�vK������9��`���y}Y�mNN)dZs�0_��)�->*�9�K��c�d:9��9^������dA
��vrj7�tZiN�g��z���M�z9��_�o8zF)!��^o�I�(4�)��V����Y�(-����,a��p{*���Sh��l�w�'W��K��/r�S�]����jUO��9�%����O��w��u:lZK�c�~b-�A-��B�~����6z�"S���B�V��d=�9wK��c����d9{����S�I���!=FOX���&IE��`�	%���zq�Yp���)������7���~9=��Z����)������AO)�e���A�FO!d-
��~���BF����D=AO3�1�AO��X1��)�n%���<9�)��l���*
�j�+�d�'����S��.4���D�~n�����<�D�I�i�/2�X��B\���)5yE"]����x�O����5K��1��4xJM�h��S�Hk6x�bZ���q�N2&��4t���$�����"O��1tp����a�����n^����ul*q�p�s���2F���vM1kd������(c���@���Xzks\�_tJg�
�U
���'W�N�H{U��T����7�uX�_Q�NSyK
*�xn��o�^�[�C�0-g�\�dc��K�����
�R�1�%_��R�d`<�����	^�.=��0���k���NL���m��@�^ ��DI$�L�q��9�M�7a��4�	�3���TB�8����7����Bo|�R���s&�Sr
!�r?�e���X�t���X�*���M�~�I�T���m7�zr�S�����5��>���M��:���U��<��]��=Ljk!*D,rv����Z�g���Q�CT��\����C�X�/]�* �
z,���< J�oi�v���*p��=-\������������V2"�bW��l���u�����Z�}�S/*�(	y%9Q-��1�!�CT	�#VO�DIH�mb�R��]>����@��WmA�pl��{�/��U������8�����Q9c5U�tN��O����o�E��
���!=s������F����%H.$��������_Y�V�����\�S�H�����k�s�{o���I�[���c������lo�h��T�	���vl�Y/��*��]����G���j:z���C���!�|�M����S���.�<��f�`
[�5����Iq +��3@�f��\d�w�j�b�Z)�����j8�5�(�T���fW�~58(+W��������,�q����'����D�����P%��d5��q����<0�i#k`��������`O��:����o��lt�1�@�L�� ��[�LK;��%�cG��
�c�,�<:����RE@N�=��f��C�~�P��!��s��AN�?�s���/lj���������V��O��mM�����#��W8Kv�}380�N�>����a�qS��m�����D3!`Y,������^S��	I�h�&P�P�N���'1X'Mx`�dt�&p��F;���NL�q��#A�X����i~$q�#��A�N	�]q�K/���;iBRm5xG�{C����9Z���M�N��;^@:��p:�������$�y%���Sz�;r=M<�	z0�y��`t0O:�~r0�k��0CG��3������&X�h�8��
�	/����{�{��$�������h#�2���Y�)#��5��F�'L��WZh��I��`�0Y=P�c��$�!�X�����i�Y���vtn��?�M|A5��<��R=�*�d+��C�A[S�N
��8�u�����r�����+�	(�Xq�	(�n��A�oJ��~�8�.M���d��I��P
x-�1��(E<�
@��AG�8�K����+��
�J������xp8�P��6�#�|Xj�i|%�?���x8�����V# ��c���K�9s3R��,����7���{*K<^@�? ��+�
��nO�=WD����?�HzWT8��*n��R<�7��A.��9��g�0|���n��J���SPq��
����0�@�?\ (uHbi�`D���(Wb�2�@�/��?��43��\s��?��hD�U2�Xs9:D�	�����)�"�>���"�H�OY����R��O.���I������3G�����d���9���U����y�x{������n�.���j�ki�c5��a�P���w,��HB���OZ���nN>i�Z��G��:��@FpOZ�r[���T<]����@��CO�!�q�I~���������xj��p���{��t�G�WD��������}j�g�	e�<���r��j '_}�����"N>�� �\Q���oz�*J�k���M5�'���c3�^����[}�Ir�[��X��j����2"y�l�#^|��SFX��,Q!Y	��� F<���F92��9��J<�l28��@��:�@] ���7�P'<9a1X�s��+$���F;%`=����x�r2x'�0���O�+� ����9<�Uq�)GW����&��]�=�x�	������m��(�
.�|�c�BL����'���
�J��TR���0��'D�u�*�5�������3^Y���4#i������6���u�������?�T-&n�#�$x8�P����?�V����4���d|�m��$U�r�u��<�������,�rx
��Qsd��|����rt�������Gu��U����4ao��M����fN@1:�[T����>W
J, �������3,]�v�B�dM@���?�k����K�  ���,4'�6��-H��Z�������L��j~���A@- ��q�G��� ����m5��,�����:6�J@M)op�
��QEP'�����������O���P��+>���`�\n�_KRv�'F�e��c{�0{�B�\wJY�� ��
�`FR<��M(��:�o�2c��'v��W����{���T�����&��@%����>)��f��	�6��7J��d@i���i!R�����������t�P>��'�]s��������S<(��}'�|i��a�L,�vm���G[.�2��B����u�uj^v���A���&4$yk�!/���n�!�mF%�/m3������v����V20������nj���r$����Z� ��,�����I��Hv�"���*p[��a)��6�%���*�������xO���nX[��'�?50j	U`�IH��S#�#(^�5��kb��;�HzW�;|���Q+^F����![��0�^Z�0C�$J	��?r�c�Q1�i�S���������)�!mR�,��L��y�C46�%�vf}�5��PW��$)�pK���G)���tH��Qk����R���b��Js����+�Y�0:�G�u8���p�������(�Ku���]���Z�GP<�J����R�8j�	��/&|���p�nM7��#}��xT�}�@}�V<*	�e�gn�g�(������: �-/���"�d�=�^�^dL����+"���3WD�)?v)��6�.?���� i]^X+. �EX�C�Y�d&�"J
�$���I���G�$�H*$I�c�$�$a~�$y8�uHj������i
I�u��$�sH~�w@����w���W�;$����$��v��tnrF�N���E �X��$�����<���l�'�v ��
mPv4�(,y����X��;�%Vw���!�
�C
�jE�l�]�����%��2�F�"?��"���"��0j	KU������L��6,J��\�4:��5�W��E)!��oL�VLx��H�<8���x����F9�����P�BZ�m�����J{�l�V��q����8x^��`�\��^�u����b���kFc�P��kE����R��f���t)�ai_��d�������1
"*s�X���e�y!��'���O"�"�EX�������uab���-k]�B������<��*�X�B�|�����01�~��0�
�`� o]��I�������bP��0����l��RF6��n��u�HP�b���:��WMn>��W�N���T<�87��h'XP!��
X�6b���XY�Cm3�n(��k��������q9�(yo�%IG�@q��A��LNQX�e�1imL�,����=?X�58�{��K���,��9JB����(/��{f8GQH��Es,JY��GY��������@��s��d�/?�Y`�~_��U��E�����k�|��f�(�����7ZE�����W�;E�Q<(�7���UG�ct�cX�FQ!��n}Xlv�����Wc5�t3'��6h-IZE����3E�A�r�k��(�P��=:E�;*�Q�Ei���eN����AQ�%vEA��v�R��(��%�VP5�9~*(�s�H�;ESM`#%!Y+��h��Ta�)�����rx�nT�_EQ�^�����WP��7��tW�A�f�7�~��St�6�(�s*9�D���4��8G�/����@�9*�,wH/J9
��"K��d���eA��s��[�����B��dl�q���������9J��Y>�s���U�����n������%�1�ev��$����G�;��QA�Q��b���|b�J�s�&$����*�j**���5���x�x)G����$�n����Lx�T+���/�4���xh��Q��w��.�z'lv}3�/��ph�8���������������S������k�d-���������1Lr���*J,h8��&g :������^Gg�Zm|<]�[�dX�$���nN@��GUm���yU���dU����7��n��E�'Q�^TAxr�ml����q��>RX���������91�=J
��IM��[2�;���*K�~U�G�F� �7c��r0T$�X'=�b������jpEM�����Q���qj�����d�qB@\��j��8�v��i^�g�4��:�U��85~b��q������,��+�80���8� *����ZNm��Aj|kU8�	�CN�v���r�7��^r������~��w�9-����9�!����W���{5��p��:������`mz^A�kJ�}5�)'�TGP��N9=8�����UG��[�Z����~��p��xt����v!Z�,��I'5���B�N	�o���oZ�d�ex`���vrF,��B2�,2��/�Hc!O,^�^F��3��%e���yR@���jyz���w���zJ������%�{;���>�A=�DU�S���A=9������^qj�S,�SO���'�\Q,���z]��d�������2y��VlV�Jw�Kxe�<�l������mX^�t���6Xa�{���3C�c�m�C���S��J����R��
���7���M9�^�/-��%�'XZ#].�9��M��Jy�&�0�<�����;^F.���S�s�cG�z�X	�����xbhMyX1�T�p�T��"�Vd~�������t�"���S#_k�48�	�I�M�ka��L�hf���4�1Y
]��'���;��xE,����u������ZA
��zd���d,�m�uk�Y�D�v�w���Jk�]�:�����H��w�%���3���L��9 ���
'������?��Zu�bT�(p�(�����	���e�A=�"PG������2&�eU������7�T"��g�5`�R�����P���o TfXW
}�������	B9�wk��v�+�P���SZa��:'�A��T^�N�Dk�0z� TZX^
\�������S��P������S�x$��A�g^�L$}g������d�]�i
��V����6'�~�a1'�x�\CB5m5��>�I(�����W�bG����������6������_�,$I!9g�aq�t�g,$�\0�Y�D��N!�����z4f3	E����z�z�P[������D�CtjmR�!X�O���e,�?��}(�|ca&.��j=���+����8�����
T2j���i�I�	���i$���Ss�S��x0�5s?��t,�����@m4;��S�M;L��GQ�B1�3��9��P?��$��7��Z	��
��;^%m4T�D�\)"hx,�����i�V���FC�NQ�� �-�d�x��|P<?x���P���1mH�P���|���4������P�U"��P�����Rn�<�'+������:�`���!�Q�C9<�yPc�3��E���{=��4�bcH����m����3�������^Z���P�x-q��<#`(D�v���C0�^�5"�����6Yd��*HF*��R�`�P/HR�a�a� �vg��6d�(�	�5m�9�.YZ�����C9��9��c�PO���?
����f�n��=���#�8*�:���{vg�TXCM���oA��-".e�D��x�D�h_�K�OvZ�D��UL�o�&��������Ncb{k/Rit��QQ�~���N%r*���B�QlxXV]�ED-^�i`TD��7�JE4d��?�bf��:I�A�6VN�����lR��Q1uN�cTC^��-
1*f���-J�������7�J�u\��b��933�s���b��f@�e�S���7R��N]�����6*�Gc�9��|4��Z��o�6.��pi\�J��b���Hw�[������E�U7.jk�'�\�6�����Ipy��gp��cx�"B����� Tq<��v����E�#��.�FQl\L�"��"Z�1�3�7.�!pl�q11D����x,���CvBpQ���7Y�)�-^+I,+�����^����x<~
**�1�����o������([�Q/\�]�I�������Wj;��f���bY7���c�S�]�"����~�;���_X��5d���R,�!���bQ2f-�����"��'e�� I��c1Y���"������;��kI�"�D�+YeqG�!���E�>�0j-�,V}�`L���������8�~cNF-���bx�`J��3�����E=��P$B�P�O���W&;�O7�2��(����.�3~<x�����@�+]�Fj	k`6��-���j�.�����<w�f�(�+#o@�f0F��8M�������$��9}/pHVP��G�HZOXq��W"�1�wl2��x>��z����xX��N�p���Rhe��A���2ge�A�3I�ua/��q
jZ@
G�C�x�Vl
���!�i�7�>�Y�4Y>�}��	��������{d�,g�������x[l���2<iO�z
��i��
C��I�����8�J��d�]�@��������8%��L~ZXo����q$�5I�M�"������[��jni�Gv���6���N�SB��VV-��HzX�nD�$!���� �M�<�t�����~��W�/*�k�����i?G���`�^EM�x����`'�V;�^���e	!5�������9a>n�S�����uv
!��i��`'Z3s�L�35G�7l�sI_�����l� tg*c'��C�
v�5V� �K���d�n�!�,s$�)�i-76���h�_�;A��*�d����C�����J����U���;�9���N���Th�=�����t�)��m6�����w�����7|*�T���'>��|J�+��m3�Y s5>��i��`�c�d<�R���c!��5����#j��n��w������
���v9����O��������O�����6|�����V��$k�J>��g�%d���9���k�>A�i����z����@�9	|
s����Z�5���� ��6Al��S�g��%�)����V�Q�O1��+��8p?6�_
�*�w�z�j6�����sA������SJ����+B��Z��+��,&N+�F�1�����X�f����f�j!f�h�u�E��#9�wWY����'�����[����d=,���]��Ez$���`�����f�\��-��+=t���\2���3��*1���������\�l�������5��n�������(���Pm�kn��p�����?����_^�3��V�A��F���hO~���p����8 ����)XU��6��(X��+�����j�t�ai-V��=�^�������yb��
���78fk��+8VYK�'��U��H�M`U�d���au��z�8VI�}(����U���D�lXMt��c`'�����*���Y����at��6�t7�����X�{U%f��1��y�*�2Y-X���.M�'k4Yv�n5��U�4y+N]���*U��w����SV�����jlPU]�Y�O���~58�*����ti��qZ-W��w���StA;�*������W�YD�I���j�K�w���L��>W����SR��*�������1���s�,zZ�����������,�bR�	��������suY�AY?+WA�r`3rF�sU�y.��^+W����:e9WQ�Z�����J���=���Z�*�~9���~8|�j\U�k���X��2�����\�j�sU���]����C3�Y/Xv��;�X
^Oy����\W�W��]�>R��������3kv���3�����g��f~����ff��Y?����I���<������@�g;6��@���K3�����7�\�i����`�5�
����z?f0�����3h���c3v0���"{��W^����}2|k�Q�@����o?����V�p�j]������@�zvE��������w[�����S�`x�xm���U�}o�xtG�P�xX$T�3`��?q�qg�?q��#N��t}#���k�8�@y�Eu�I�_X�0�����!]V��FS5�n�8p��l���`8��]V����I�m��w��r���/�;u���O��k��O��XS/�l��T���fjr��������&�\�TD=�6�4�4U��-�7cfJ��j���y7�o)865�p��RW�3��q^e;'������Rk����"���?Z��iAsIQ�NK�`7��@����
��o��$��X3-���7���cU�t��������Y��u�������N8@"�����n�6�I
��~��A�K2�@g{�t���T?�zIm�S���r�������N�������x��I���<������5mw\�@Ro-v�G>�q�J����+�'D��z���:<��^��0�I-�}�+�)����c���vA+zG�C��2w�OQ�g�|��&���c	��~�*X����qG"�����R-�*z�;Z���.���a���~�Vp}���I
�.�/����A�s�j�1��+
�K�N��A1��Rk�4��5�j�}$��"��,����[O'z���Zjb����j��2� ���F�$3F..�d3t�)�`�:q"0�-��:3+�	�c�����A)����s�������5YI�c����  "+K�$�?n�n
�	i&~0�I�V�Z��#���P
�+Z*���R�#M��sW�ERk^4���%��7��z;����a���A���.��CY�,5���j�{m���� x�a(���zyC0���6J3����I���!X�rFc�P/���u�s���bm����	^`/m�L�`�w���(b��x�B)�i�����Q�DD5�������*���Q(����aI�@��$
��5T��mQO����U�`/JQ(W�W�B1g��qC!�]�&K/xE?�=������J�J��Xk��[�
��_�
��B�������\�v�.8�k���J#,�U�
-�E��#>�����h
9�J<x/��F$�=�E�I�����f,���Z@��@�k�'��@=	w�J��A%`�c�����_9��
��Z�n��(iP�p�����nk�D��e������w������70��������H�76�p���(l3���G3�k#�z��Y��fP���
���� �1s��`���$lc�4#����`jE�$_���
���	����(�1�]���Zl�A2�g
���C�������i(L��N������u,c�����w,����X�P�0��%Yix�T�S�{A�708H(}�"4TN8=9H���=N������$�n���bl\��� ����(��M���|
�n��d����8���}�B�fo�E�����4���]����c�SEo��,����Z�cD2�ykj�k���x���"��C��'S�yH��r��w����w~@
+��`�`�z���^�?T���=�G����Q5�@"���C �&?��F�@�\��d	5�js���H�O�G���o"A^���h����XE!�[*B��������w�f�`�������!���AI���J�hV&o�R����!�����`�oP��8�!�(
Y]B���"���E6�j��&Q��@"�]H�fd��qh���!���($<��4�(�����b�J�����#��i��D�B���b����FD1�.�6"~�vQ��AD|�.;L|�C�DQ�~Z3}��Q��[�iD�6x��4��I��C�{k#"RCDiGk�]]��v$AD����� ",���9��P��(D�k=��m�����Dt]6'"�rq� ��;����ADxO�m�F����E�H+�@cP�T�~58�(U��<V���F�
��WXD1�OMg|�%u���R���������wrt?6"������Q�AD����,'��
�t>qQr�J�9��N	"&����dM+��1FD���;'"���W��y���!k�.I3"*/��j�ND=�e��q�d��A��T�h����:&JC,CBGL�k��]3qi���x%U��������`��\E9���hP�e���M��%j�+��j�+�84�x����j1�D1�_�����������M:!lPB~�S�PK����'2���
�<�
,JS<W#K� K������d�T��"�I���7.JK���>h�^�hJR�r#��c^OO�N�Q��V��Z������pc�����l���0z�)m���N���!vk��?�JTe�K����r�Xt<��y��o���(f�I�����T�j�k������������O������k'K���H)����3��`�%��@{����Yk>R=m�$�sO��x4gL�z����'�Xa�����k�X���5k~�X���`�e���J�[@R0�[���!�;� Af�iw�tdJ!���[ko|��;%U��2���^���M�^�Y	��&]#��\M��fD����rx��R+^Q��~�)7A�
n���%k�=���R�3��u��qS�x,g����qSyg���-$�I�$q 7����F��:7��vM����4�a[3����Dk^lMpSY��p������8���J!�Me�;v��At���e��.%��|�FN9'?���ANm��bm6rY�_���FNt�;��9am����oVrJS��|v+E��~78�)����T-'������Y���k�)�;�p��1g�������R�#z���1yy8��y,d��hWt�'X�\{,T�����3�������pP�������;8qq������Y���B���\m���y����J{ks���)
p
!���e�ryN2��;���:-JM�@p����N��c�Y��S�s����.�`�����>|�)e���J;��)'���jp���+�7~��E��SZ��g�|��S����:7�,rH����Vm�����J���������J����}q����Y5�9�%s���$����I�X���8���n<��8����5����?iq^��Q������,X��C��B��"�U���8?��xg��u~�9~M��S��z[_�y���K�Z�_��V��Vg������Om�{,�&�����b���`��v�
|��5��W�O5�
�����w�S�]�������k�)<=N��u�p�I!k������A�����l� �w�`���_������h��@-��u��A-�������Z��j�]�f��jmZ��[����9AQ���4����\��8������B�9�N�NpT������^��@v�B��G����8@����r��5b�*�u�����yz1�|'*
��zH`���V��
T�kJ�k��T
�����z����:�J�k8����Q�vZ���\��q�[
���H�/1�/H*�<�=�H���C���t�I����������Q���nv��!���J��\��n��>te(��9��P0�M����ri�������B��W������%����P5'������V~�-^�Q���SHyK�Y�5���r}_�����O��uk����SY�|��k��������\
N�y�+=�b���N1����qrl~1�AM�3l>�����f��;��ah.�E7f��Z`[H�y0Kyu9��(����u�I^����	����Xiu�|�N�;\���@�K?������%[U�������m&�;I��t3/
���`��xEu0�������oz
-YQ7�\�����7ZN@w����L����Z����
�Z*/���5�N�����W- ���.����k��pj��!V�q��5�c�R�ZH��L����00;^�9[���w~��(��������������\pN	���.8����O��0��sN�O2]�s��#�q����s�@`����zpN����@&�C������?:�xq�!���m��NN^����:�+@��B�@�$���
.;��t0�����F��Ss��-C`l^V�x*j��[�y�sZ����������i/�/I�,5�J�� ��r��^f-k�,5h�o��sBk�
��sl���MB����s�N�`�orO�S&,����"�U�����t����*�$%;��g��:�Z���;) ��l��������;���86��	Ph`�m��t:m�N��G��b��;1���ReU���m^��/'��5��&��h��`�T<����������F<���H���2�^����q���sO�Xk3CY���2"k�l�������SF$)��k&CV����4.�'Wb����}�N�M��'�y2z���
�����=0��������	��OzS�:x��a��V�.���
[���@�AU�
�rj�+Zc��Q�	(4�ZxA@1������6��xE��x��������-����� ��Z3���P�x$����������H�=A@i�U��:8��{UaW0bL���G�Z��	�p�w' ��]6��J�}UT8G��! 7�N@��l�f3(u�n
Q' �h9�����c��PO$mH�����y����\�?������7�Jo�����/\�9����l��\q�9���u!Mo�����u�XZ�z�X��J{�`�����4��=G����j��9��=4�'u��[��?!��������W����r%�f#�?@:�8BZ��S	x�i�������z�Q5s���a���M ��%�7_A?)��Z�%�`&��)���l�����5��j�L��`�}��&��}��K�s�}��mM��Flx�}_(���M���e�~j�����O% �"��~B���nWF?m�r[q�F?0"�:t�I#��)��6���O��t�p����r��J�C������������F?%�a�.�CawR���]�}������i�
wR@R����Hj�xP��C���M�S����pR��S����.����O�:���	�>�����{�/>�3�}Z��N�w��G'��7�J�8
}N�A,����<=y/���)��� YPq����&xGk��6�	,E7�r��xhl��#'���������z��:5~-l��������S���m���Tb�1����y�������=9��9rz�s���R�[ N����������������NOj�-v�
��2dJ,
����Q/E����������1�?��ze�Hg�6���9%��������3Z����t�i38z?HGf�)�w��W#���S�d��r����.S@��9����v����ew�������'��5���4��<0P���,��]��#VqO���������A�Zo���O��)���G����=�xEQ�o&<����s�
��� ����l^QxI����$?w#��+��m���5C�����	m���4�
���jn������d��v,3R�@���;���@�Q��7��������.�T:X}�4m�	>N�r��/
��B�#����jz
���z9Rt��P*_��'��^��8�T���ch�)�e~7��r�7*�+��������;P(@x<������
����5�������#TJ	
3���o�P�1e0�f� ��Z��T�Bi���n d3(�1@(W�����2c�Wc�k�R�R-�8���9�?@(�b���U57
�$�g�\�;��#����P���Bl�	�bC(Q���g?0��9(���V����5P�#��n1��H�!L&H(�9	�K��4�Ri��ioztae����c'@��i�P��pQ�c�OM�.��NCiH���d�+�yiO;��Y�Cm������C�#!j75�\� P���(D,E�&L���R����}�yp�SV�������P�Z��v\o-�3Yh�d$Cf���O3,7���%T�U>E���F�����vV���G^sU(�5���:E���+�N��Z���v�7��A���CH�n����.p�������A�tB~���J���O�����Oh���|�#�2s^����'��Y�>iC�K>,V�@jC��4$�	�H
@J��'= ������S$,	�����^���bG6DJ=��ll��_<5*�FO�;������$�/+��6yR�Q��I
��S�H�<�Mn���M�T
F�p�\0R�:H�3N��f|������TzWl�k3��=k+���j���"�g���Z�F~�{c
m��J�Q��Ql�:)%�1[�Dj})�/V�����uy���9I����������Mi���I�m�|y�����;9)���B�J6378+Sh?�����Ui�|g����	*V&�|��V��-�����X�
Y�����o(��"s��)���BZ���x�i�wv,����Vzv~���h�����c3����I7'�����+�=��h�<�O.����[�m�7\�-/�6�����]���t\*c���o�����C���Li�s@��Mi����K�.�d���R���Z�A��wpRB�����2��:0�1mZy���1+$��L������r`�4em���v�v����Z(0�!iu��^��X��Q
`�	�lv9��y&�Wc����T���WSNJX��{Ix
��l��?��Z�@XX�q�$ "`)d����v.,����������zH���!d4p���?:�u\js��,�%���d�l�C��a���Lk� ��1��'���s0[��D�`�t���@�3Si�4��s��=s�9�D����50�h|�5yZ
$�W����"�s^c�S����XNu���GR�!�f�&UG���3
x
��"{��P ��r��
0�)�5{������p�U�W�5��i���TX�T�dU���UJ�KP��
���J������TY�.��������{\A��#(��f�0NP\��K�A�5m�G)����AiqF��A���-��A��>��� (-�=�d����X{TS�'���q�N�� (�&���Js�O��Y��`���tM'����A��U��(�y�i����� ^q���W1�;���_j���W�B�����jz,`9)�����k��MYcg�,�/0*��,�a�/�a�Y���=�07�;�Z��z.E �����R2h�YH��}dJ4-Q��
�`Ooo|�({�z��J���fB�6�JMz;8�A).������k������z�(U�,�m%Jqu��b�.M�'��[T�.���Td]A�z�Z���\�g��b��x6�5�h���AS^�s��W���gE�%�]q�+�����K3]d�K
L����6)��,�Z���5h ;�R���uF�'#)Y�~��E����yY��~�;G����^_F�5Kl���++E����MR�A��yX�l]q|e(-���<W����>�a_v���x.��'W2������,��uY�<��������,��tz�-Y-X�'Y3�y�nn���������0tjEj����&ES=�f����M��A���bJONSP`pE=V�+���5C7��������tc���vl��z\��7%B���-����$-���y�hh9�e�����/����~j��R��V�r�ux�Y:Cs�&=�kk�X{��.�z��eK����z����Y�Z|8m��?3O��q�����O��h�G�Je�p<�z����r����<���
���t�������������d�jy�����K<O�7~I�h��~��9�Z��FS���%��jE�
���`����"hX��6\��Y��r�+����i�63�|1�����2��fj��}�����fb��m����L�����,�^?�h�����D��p��1�����b�������p�5�f�=T�3���DC�iO�eO���+��z��0���������^�9������h�S���f��Y�J3]Q�V)���,.I�����dz(��v����Y�Pc�WO^Y��L;�h��kg�����%9/b�UV�
���$��$��$��r]�����e��	P�{��,�d��$rH�"	-�.ys6�8-��&q���V2!����{�Iy9!R`J�Y�jB�*�d%����]3Y��#�Y!����k���M�"�.��
?��j�m�`�*2X������:��R:`'�U�
v�`;r��o=�]����Q��zr��IBg:�;!��+p�%p�!��������w ��SE������t�]jB�:���������;�D
&r�i	V�X^�����.1��.
w a-������7��;p�;�kw�SM��ldau����YM1��m�w���EH������~V)��(�����^�����J=Vo��x������*O
|��V��x��V�E��8��YX�J<���%��x`��m
V��2�I	��x$��;#H�z�F<��;�9��Y���+���
u�i����/�$(�g��6������qGF�l!�I�M�����I���4S=;95��h*�n����j��'������/�l��f�|�GON�%��|��xfU���-��|��c��!xw,`\�@j�8���-�r��v���~�Y�d)�o��u��\,4P�<���I��=������s���@����b�x�cV����4q�Y��0���GU�qz��8���'f;�����7W��N�=�1���R��������R������\?��f�C����4=Oi��|m����e����>���V/@�XZ4���j���!��R3H�����j��%/���z� �2-��x��NG�,UPD����iI���d�/��c)����zw�q�2�>]�W�	�+�
���E�6����<4�ZK��s�I��5�X7�z�heH�hYP����t�[�1g,�jBWh4�;_y�GS/`�������P���#��@L�d��[����F���v,�����s,���N�O���i�+��{N����E���:G����vM��@r,�%k�*8lu,&��s����������$b�(�q,jC�������K�����E���`�X2��|��|NVt�X�2Fs
(;�X���������c�x�A�N�7,���hd�b~$�G�BBRh��(�^w�G?p�hTTzS��QQ��6QOp��(���}Z��6�~���q�-/������r"��8����Ex-���B��	SV���'����d����eD��X���DK��X�n%"��
aI�`0�����vZI.]VHB��}eI���bL���������/�V/����Z3Y�>ja�O�
r4���+����x$���D�C
�G`��1Q���(����.#�DirE���'9h�)�ae�W:��A���rH%�������F/�d�%�S��7��$�2!_�V�FKyX�7}G��]3^IF����9��J��=��f%n���J�77sK���=���Z��\d�uV���y��hPv�e����,T�`���r!{���,i�a)�<���;��2d���[���R�X�/0\�
��yYQ]����[z+��m!��	�k���|U��t����3���2S�~-{���b�6�3S+�����H�r~��u���3S���#��������$�	���E���BJ�@�[C�5��R�x{��`O��+b�c��'�A��3S�����j�83��9iI��s�V
>$���<�$���	��G{^����Iq�B�
g��������K�Mss�����5�����/��@�2#���SS���Z���������~��M�Ur-��X�+l]����q��E����T�S���3��}�K���*�)�z��m��EU����:�'���l���66��mFN5��������r�J�s�P]�q�r�B�z�l���(v%'���U$%���lO�m������5`����d��:�����S���k�J���<��G��dw{Xj�<�4rj)��w�]s��������Q�7WvJ)���=�,���e�,\����W����%Wv�&kP-�77v���n3������b6�����)���&C_*���3r��?X��S�J�=�|l9�R�����FN�����/'F[���������jo�"����)�<���#����LK���$s9�=�R���#����fn���{Z����ii}��
b����</����K�9?v�C|��d����7�AN�<ws8��7rJ]��sw��B��g 9����n=g�89���KL�����5Y���k���Y/�1�����Y+'sf��S*REN�f�8���\^�F�~T�S���/�";D>�"VO<��)��^��9\�I�Z?�T��)�����u���R�}�\����y,d�����:v�&��P��wl�1O���;Jjc�y"�7h��$�&��`��<�~�`�ug���+1���J�d�TBV2�I�n���R������M9#w�Nc��i������"�C.U���B����`i�RDx�u�j�Ts��������R�k�e�`j������K�)��T#�5�+"�m�@�)���~y������"�-U
endstream
endobj

12 0 obj
51250
endobj

14 0 obj
<</Length 15 0 R/Filter/FlateDecode>>
stream
x���O��L����Oq����f�N��60�����n�h��7��
I$C:W���zoP�{:�"#�x�m��������o��>��w]s��_��6c{�56�4�����������������?��?������������S��~~���i���?�����/������?����{�����������x����uo��������������~������������_���E�����ENo\���������]��������L�|��G��o�������������]�j��?+���k��]�{?����fu���q����?�������q���6���S3u�_]�
��������������F�����}��{i?��i����R��m��;��m��{���>���6��vZ^�;<�n��s�
�M?N,l���~���/M�~��Va������=B��]���������[��,��4n�������m�U������m�nN�l�nQoV,�1V��7�m`Y��������U����q6NM��:����N�5����p�9�|�������.N8���9�6h��8:!�C��>������@���G�\��3�X����s;�������]/|�z�-���qk�{'�-:����������o�s��{���i�q(������q��s�C;�������
��c������;x����)��.��f������&�[h�s��a�\�o�)��������H�O�����r ���@��L??����a�����\\� ,\��������$n���@��.�S�r�{3��t��������P������r$l����}�)���{$�����}<������|�O��=�5�i}?>t��������c3������k)<R
��[������N��V�SVg�����)����c�=:'v�����.�����F�\�tu�$�:4?�@�.�|
O��������Y�����?~(%|�Z����6\�m��3�N�!HX�sp3R��,�2�c��<��-2��M��>K	;B�������n����{V"������P?��;%��G���P��px���PX�4���j]��O(V|�kn���;�.���B�pX�������R�a��))��	�����`�D�*�(�%Y=�?���a���
t�;�|k�o��6V��Z����[�=���CT�S�&���P������������a��^��]0�K����o�A.y	}�p$�~X��i��������n ���:�U�V���6�e��H�������[���G2xz4]'7Y�>[�+����?���-Q���u\��_���>���Q�)�=��E�o����da�����>�{)�:�K8��M�j��il�����x�#Q��3h<�G���"���q%�����z��#	��p-�H����ofv��IX��yQ�a��	�`���z�v��m��z(������qp>)�m����)�~p��=���| [v�����n�q�8]�����q�.g��#�j9|�������
g�,�v���9��8]��
�D	?�L�o�&���s�s/��{?Da�{��W���������~�q��wC��?1�ae������@����S=���l�p4�~�17L<�b�p\����Q���E���7���k�����!����	�#a�����q�.��m�X!�m���`�q�G�_��/��u`.��x�2�����#��;zr��.�e��r��f�cs��������{�0+����p96���aO�����q��0����m�I�/���i����W�-��;�#�~~�
Cs{��=�n�yz<xz�,)l�](���
%��UA�4�W���7�)��o �����p��7C�A���4��L�[q4����g l�2��{�W�3������L*48	Xr��"�%������3����^�tx��������q%���@���2\d�q8����@�u���������4v�����a?��#�8����J)��-A�*�U�[�i�^���b>�|�_�b�F��y��t'a��_��?���)u�����5��b���s>_~ha�~
��F��t�QA��oXg������f��������W2�QA��i�s��8#��B�g��Svs�����������Pka������t�D�>�<Q�OC\I���'a��|��p�d��-��-kr�����on��b��nS��RX��:��R���gFT������H�~��2��P!=3�9�ep�l�����>��VKkR�S�$Y�o��$*��Kb��UI���;�P�5�hb$Q���qu��/�~�[a5q��8-�d	��Z�����:�]+^H�����K���O�a�������;I@�Vx\����v��L	�#a�w�������#���Q�PJ(�������@�����i���<������;�V](������{/"�������#��7@��~�&�:�����m^��T���Ce��w��,���bTSu�UP��k�N�t��9H��3|����[�����Y�L�H�cQ/W�/���a�p+W
���c>�p9�o�����������m����%:���}MK�<���}����*�B���*v�bw���5���QK7����t����H��B��(�'%|�
nH�j�*�
Q�g�tYW���G���$��X��t�����s���<&���d��,��C;����Z�?da�����(�S?Da�f���=e}x8�����9g�O��t���m�tc<<%t{����R�����$�r�/eU^��$a���V�}�#�?�����?�/���m��w��L�<�p�����;t�1V%\d.����,0,�s.�"<�l�0����	S|��U����
�����s���0z��@��>��m��.�|:������c(v������}��~|���s�xl�~H����K9ZF���P�>��qr;�`����|r5�}��T��=Mn{f�q��IaK������p��H��o��@��a*8dK=��Ca�`���G��/�E���P|��O���q���-���;0��n�:��S�!��.����@�!;���]g������;���I������r����p5�@�����d�]GN�FI���x�����l�"����������a?�'�#�������W�Y�*��?Fo��i8�n����i�������������$�cRG���"T�����<h���y|4c/v*��$|����[�dU�y
w$Y��?�7�����}�<�O>D�G��o������n�c���1������s��T������U�Vw7���.$�?�@`�S)��D����7���o���o��O3�%V��i+�k�	+�7�y�9.����^��<�L/Y�{)�8�<�^���?`f�X4�� :<���s�����W��e���7	����jaS9��G������$�:���O����w���s��A��nB	d�>�5q�>��1}3�"X��Y�d}�� �
�����Q2���,|�Y���?�<���'2��L�t��7C/v4����>��J�>]/����Khd��Z8�02����YQ�����r/�h����m�7#�K�2�AD_��Pw��P�C�g)���gq���dP�����*T>����.�I���?�2���])����jZ���-Q$�����w�B�?
gMTW[��WI�����N���w�����2���K�q')��,�p<���JlKS������:����GY|3mj�|]3N5p����+��%�A�|d��Q�(��`����(VT����IWk���]�'���5��W+���iae����!=����f����E���#|^�Ua�#x�9�����i!V���,�p�x��Y��u������g��N"�gHX����.���Kl(�6L���t�����7�\��#h~�H8$	9��t?	��xcaVB�z�k��DwI���o���:���������U4J�����2���oR��>�r�����;#�o$���Cq=V���x��,��e}Vd0s���mz,[�p<q"a����-�����Q�9�t��>�F����A��kVB��;���+���	?�o���t���=dA2�c�[�F)�����'Lp_Y�`����.>��`��g�~(��0��d������J�t��[36�^]�8�*^#�6��(������Ex��u�6������c���>Dr����Ia�3H�r����t:���Nu����[���s/��=pcDy�=�jEZ����^�&���������D7���>����~:���?���QF\
�}��<q��a>|�s<T��������s��������x�j�Q1����g���G	�S�p�s��8��a�Ybd�b�������7c3?��L�}v��f���*R�:q��i�����f�'?n��?�:8�4n�����
�u��k����^��Q���U�3�����0��^��|���G�:�����<=_x�����JP��x��Y�{���=��a?.���q��X��t�p3�e�O�![]8Y;����}�=����%$���XV��d}�e(��L�(����;$jV{����*3��C������[w���!k|(��o��,��e�p���]L�~��V]�(�4��{�Q��/����{����#�����Gx�'��|>�����two��U��vw@�k���X�g'�l����(��G����5��2�J	���y6�L��&%\8&Fa��(.I�}s��>l��K����a]�����a�8�=�dA0��<��sx4�����>��,��{I��Q�<
|�=��i�0����^��pT�v�in��P�S���L�L�Vy<^$�e���E���l���.(�v3\�}x�}��N
�,+u�|�8tM���m2qI)������7�YX�J��[�+�;G�g�����:��>��%���3�����#�*<*��p�:��%�X��V�o]�!JK��;��PX���+�a<_�/u�����'�u?���=��aL���-\m�($�G�)����j��W��\�Y�s�}	l�2O����C%��%|\A�e�.m��������n��>�zKL��E�[�'\ol���}��z(a�m���V�}}��p<�U���w$��F`� 	��D\|��U^����W�Q�����m����I$��0�������P_�������S,�v�!���@B���7R���|�$(���V����O8��y�O�����O%i8�����H�>.��4�����s��u7D�j'Q�C���	��N}�>�q7��~���Yv�����?��y�#A�Y������Z�C�	3�!A��w�Q����fB���H)��k���[��G�s�f��q[��i�����6�F�w���RO�] ���h|��Q�lE���9O��<���y���9>�f�O�^������}1�����
�U���Ia'~�R?�V?��(~�'�p?"#>�������L�G��)����sf�p$�������K��������e��$�L�w��#�����Gx$��Y�����jY�}�������j�`x$;Dr=�,�'��.��'��a�~c�G��~��x$G��u����)7��2�!��O�Z��&���w���B����U�:T18�l���:��5��$��HSqV-k:���h�5W?��C���6�;*hUy�~z��q�����$���Kv��;��:�-`3?\�0�:s��$k�����5�	����0&�����h�Gz?<�o�A����cA��NYX������{,�x~%a����e���������3n�>;���<�Bx���ODa�����d}�����o��#���m�����a2���a2�y(k�����N����:�0/��I��H��
���L$�l��� �G4�����p�ddN��[�d��3���qz,������;���|u�g��P,�x�u���#�o%��-�q���5�X���Eapb|�4?�N������a�����RXe�fV����NV'YM$�;V\��,n+����H���pCQW�{]��8�/���l2�c	�.�p,����XB#���)u�.IC2	��=~��]w�qn�vM�b}����?��#|��P�zw!���KCZVx�[�YF���<��������c�_����P�a5y;J��.��}��*���H��3V2ni�4H�
�DO��e;��,<Y�������L�� >��01�bK�����-\�l���G�0K��N66��s<��B8J�����|�����t���e$�PDK��������)��Uf6#Y�%Od}�H ���/��mZU�����8K��=O���}.�������~q=V��Gf~M���ijbP�����38���{�f�{���AjwwC��"e}��G���e��f�i��Q��9�Q���>������	�H���v�S���J	�C�����G��KYX�o�:��&�H�d��*cx$������6���8��K^6������.I�>����swI��3��T�N���^�q��C��;P�����,\gh�Y����R\�U������='��o��=���:?2�g����?]T}V�D>�i�H{o*n��x�p$�1�q$��T ,����H�}��c��1��}/�F��q��$���H����f��=rln�������q7�<��~������pC��sF7��}�!���@u���A�����6`>u��c~�f�=���VQ�!����~������}Z/�eg��������H��TNT�q8R����L�t+ox��"������;�;������OI�~K���
$A����2ur��:�F��m�9\���7<��������d��Cp?z�-V<�}����#�pIP��:8���)~[\�t���zm�8w������Og3�5j���a��f�����T�x6K����2	:�0�

��5�Y��������?���m�_��W�����~����[s�o����������X�
��������_����k6�����kfH����}��f�����k�v�5�?$���3��q����04��o��!k6��tlg���f��}C�K����y����%k8O���?���4��i���/Y�in�i?��������{�������w/3����I�{h���%i����U����tk�~����?���W��n�{3vwk�����a{o���7������y�����7];���_�N�������%i8���v��_t���f�1��~����'�zd����|q����s3����_��_�_C3L�_����w���O�w?�������?o���h)��}wm?u�~�^}��<�fx<��M�������V���{3t��������E��K	��5��L�����~�{�3�07S?�I��to?����~Z@�;x5i\���M��bN0��(���*��&��f��������{��J���L3
R?/=������aH��]�Rb������m����~X�Rb���w��}��x���J�t_n��Xu����~RBnCs�u$�������5���{����hqp�����;w����������cF!��/o�2�c���	Y4���o%d|4wz�w�o���7�\�]�U6���}���	I6����i��K6^2�u`���t�nhF0{�@u�%�d�'��������~�W����5��n�L.�q0�o�n8q�j��Xg�u>Y`('��T!�����5�W/`a�0g\�����TmRL��|S���e\W��gB0U��N���4W0LZX��_>)S��u��	�0U[�O]�v���T��g��b�e���Xw��e�c
S��y{��S.S�*{�]���	�d��R��40S���j}i���e�8E�S���W�yA�Oa*���}��z�u�����HU���T U4���#U7��*�>�m U�Y
R�[U�T���H��%H�=n��1�n�T�T%`���~[���bG*�Y?��sTb��*�WpL,��J&����H�x7�&&���t��MZ�X��@s�����&i]6��E�f�5�
�8H�u���CC*�h���r�T���j���!5���V��2��m�R�M2������4,��	Ra�f��^�H�B�m;}�T2�;a�ZWjbH%!�;}7�2U�q�2��R��*��������<e�l[�T��5L����2U7�/ g�l�
�L��6��\��s���-`;�0U��Z���5��U�
s�u2x�B$9����~Zw�hn+L�&-������la*�4���w�
S����&G�fg����%����������MXx��E�}�;�������R/
��J��qjF=�e���E������L��k��d�2Uj�m'zn(LBV�S��_��g4/�j!�G����o����+�*��^da�h�Z��s���Lm�D�`��S��Y�T�����q
S��f�ng#��RU�������)7V��Z�����v'��B���~;���U���%\?l�Z*�J&��a8;U��m���z���*uY���Zg�*X���3�D;Uq��%�S���v�s���m�t�&]�����e��T�=���������v�j!�W��,�� �^$��TUB�u�{<�	�j!�*�>���j|��=�m�*�U�dYEU��������vJU�<��j���I������~�*�������tP{	��W����gO��K�DR���n�:6�TW�W��]��i����x��x��5m�'@���G7i�����g��N?�M�C�ooz���M�����K���c��#�����~��WM���ts2�����P1��C�7p���>���@>��s��V�N�o�fjiV�����16c]������5��<x�&����O��QGQ
���M����������q�v���K�BX�x���k�?M?C���] ��
���:m�f�	�]W9e/�YP�k�+���YF9��;]�:����c�rB���S��9�P��w4(�����P8��I-o������)��C�
����M������N9)`F���A90�
K�z@[A9i@�D�:���S('���I��u1�s�����9�:��W��-,���{x��a!�k%ul�����b�xo�d�*vioss�H�3{_��V�9��{LM7t$`������v���1�O���O?��!�vl�~�����S������
��o��m���Y��O���i,���M��\����g�u-���8_�rZ
o�����y�v�<���;�����K�?��:���$����Pxa��\��&5s�A�8������^����~�+�Ki�IG��77����Yp�S52��F�����sa���v��/�>�6��7���j^�5������M(�`|A��M��B������a[Fj����o���\���')�& ���>f*�����H�t����:O>^
�I	����M�T�1��/y3�q]A���v�����e��=0���u����N/�(u<=;�J��O6ok�
/����:����9�'���P��$���4Xx���������9��n��l�,�k�FC%���lh
��5�N_�p���KNC��Wrxg4�fl���FC���c�a�FC�v]��U���Xn�e4L{Ro0:
i<G6�h(�XQ4uf�C���t�4��\u�;�F���9
I�7~ 9
������T�+������5�����L�qx��8����5�mx^|����ae���l�	<�n<�&�{����k(���EJ�����C!bL6�
�d	Yk��R�v��<$3�.{�P[�N<z�^xV<9�N�����C���q1�C�	��
	[F�1_�[�T��S?���b��4}��<���9
���(<��i�R�����'V�P�o�<�����yK��������?����������
/�mk�kkC�����%-�t�	�/g��4���z���c��14K��x[��&�R_r +��+��k�&*�4l�po�l�7��NS�?pH<�_'����2s=�mC	���z������w�vI�=�-���7�����������7�8�?����f��!����X��o`��xz��4�
���%mK�-�V����v�����4@q��l�(�f�����Z���
�~���^j���	�"E�~6�g.e[�F�������/�������I�rjn���f�w���{{Ytd]�R�X����-X)��<���qVJ_v��+�C68@���ycF��J0�i���������Q��`%�����I=X	}j����j�:��sV
!�]���V��L����+A����+e����5�����[�5H����2VjS,�nvOQI�\]R���G�|�|�qy�|u���-A+p)W��\�:p)�������������Z��+�T���#�R����2Y\��2�����%���9H&p	��,.=��2�2{�!d�R3�k)������l;��1-p)�6�!�����E���%z��0�C3������v������p����Bz|i
0���-���T�����r����!�n�SZ��[<_`��5����z��S��X���"���q��C�5�80��������s�������d�S�@����V�^���!1�e��-YO������>,�T9�K[�i�����<�d����vU=UN�I:���������=UY�m�8i�����!�{�*G������"'��Z�bf|��B��Wf]��'���#���"Q�����k����R0g9�K����.�T!s��&��AosO�y�T5s�u�����n[�_�}�"��%����1��yz��������Fg�.8=o���B�$cK��������_i!/i���Z������/��r�j{^�.u	��K������4���drC����[0(m!F����J��`�6�S������&����:��3�T���N2�Lss�����p���u
�<kl������6��������1m�T�EMF�s�y
����=��+R����������2O T)�[�v������Uk�N��i�.��T��mi1j���:��S=9/�������}�N�o��W}�i�T��U�;�2�Tb^����pN�1�~eo���
�'�dw"��T��z�E9A�$��jv�I������E_^Q��CT[�Z�n���%�F�w1�Q-��&�m�8���j1�z'-��(�b��e����xr]�
������t�hJ}��:���I��B���<��5�E����"=�V����o,bH����Hc�~i+r��G�PU��n��X��W,J��y�06s'���"q.*�/3�v�/�1"����[��T�*t�bo
�q~8���iw
�'~��2�bDgN}P�Y��l��0Bv�T���l�}$���d�����;$%�k-�G�K��T�H�)�e������������������T�������c�B�y=fy��2P*u�Z�QN�WP�MZ�l���J�B���Q�n��E���,��5�S�
�u�j�+�q�K��i���8K��o�a�����R���"���6����������iz.�\~��X���b��m�w��T���(���T���������C6I��A��4�����v?\�Ma�z;v���
M��x��)��&uR
M�����aASm��
C�����V��Zu�}����9M��~�,��[qP���7��k�B�f��>/$U}��*+AR9=��T4�
������8]9�aG����[�Z����j�]s�E��5���u��h?7���<.��e��d�6�S�G�����Jb8G�./�b�q��AV�A�F�J��W(��u/� �����Q2�;����d�+�2t�9Jd����P�����������y���L��G��i����9���j�3�G�9_VeUg�
�*!���_�%!v98!�Wf|sW	�����D��W�
�Z�|9�{�"�H?�"�H]Q�2��CT>�������tVY��B�
���]!��.�JUQ����:!8 �
Z�x8 J���UD��UHG���^s�������%{���L�vi��Y���b���
D�9�q����
!����c�Q���)B���������rByZ���Z ��DXGDA���TeI���W-FU����(=����|L8��]W��+\EQ�cU��5%��X��n�m8�?3�RT	��(�;E�[��,QKZ.Z���`LX.9E���H��]2�2�B���(�f(v�j!/K�F�l��DNQ����!��=9��S4�MC��AQ)d��I��)*��ULR��)����<�W��Wy]����ST	������B�������(	���KY���U�*Td*�gW�}W��Y��A�X��W�^PFWQT5�:�O����L�i��Z�
�z����.E��l��vPE	���R�������E�����/�E�A�5��,%��}�BQ����,���)��%���J�5B���=���q[yf`PTw����F���,%oPT��w�=�PT����CN����|���;���B�����hIPT�NfjF���c�
]����:�J;j(
����������E���(*����h\��O��h���7�+9*Dlk�J'/�8G����m���`�.��N_�lr��K�(����.[pT���`���Z�k�QK]k%{F�[Hw��%����)�(���s�4i�k+�Q�
�$�J���m&���}�&��g�(��������sT	��e~�����R�o���JpTkb��`zs�j���G��W��^|�sT�_�Q�����������U�c��f^������e�ahnK=�|�^����B���5��&�m�����=nM��$`���}74��T��:��������M5�M�C���F��2~4-
=E�z�Y�x�F�!K��_�Wh���ts2zd�n�0�l����7�
\����7Vwa;�}3��C����Z�1)�26c]�������Nlu$�����O�A}�<�f���������5��h��tEAY�����B��9g���Y��GC�� �|vE�K�{m3R�b��6���VF��vv�[O3�t���I��B:���u$
��G����D������
�d�����N:�nF������N�I����a��#����P�?'���(� ��8
��H���!��� ��WQ�O�Fc9)NK��67c��!��9�8�"�x^k^H�Y��'5F[��kcV��������cn�����D�Z�S����I�E<A���xO�N�mE<33(/���{"-������x�
i�����_O/�I����E<S3`�dE<+|*)�	��������mtf���'�d�!aE<��`���x�#&��"��x���"��z���>9����m����5��y��T�i�������a��X�v�I�.
���.>;`��U1NZ��U��h���E�K+8=_8	J-&�)8L��4�C�D��7��s�*��*O�����c��C�$p�l��8�=aZ�K%�C)��)l����BG|qe��!�rrOR��a"B�m�4�3p[��V�6T�q�Qh����C��|v

/�]h(��W���i�.D�a�5`]�9�0����<��>��`([��E��� "���0T"<g��v5j����aH:p4f�P�x��v�!�`it������#������q�C|���aH=����C)!��0$+ZNN�0�^.��v�`�D�Cx3�DVnr:����a�/�Q����H���zz�R��n�V�����#�K�u��:�nLC�0��dg!��^�����5}$h,<o���B��P��.���Da�1��+WT�B���D����,�f�|��,����NWa!X�D%
�
�qTX:pM��B=��Q/D���>�5,�*��K����W�i��Pj���aa����.X�{�����g�t�-FR]S�ou���y
e�7����Pzb�
^\�KJ�@�Kz���<;`�N����Gs�O/��p�����0�Mi%�Q�����V�������5���TJ$YIj�N���$5��cL��Azl�������-�|��JRgC�t��L���o���1��d��i�^}o��Pvy�������.o���CT/=� 5����������(d�'!�f)H����-
u�GmBMD)�@���T����lX�91��Y,u����5�-��ia��6�>��_h)�<9��ZJFK�'jAK��{�
!��i	�<-�N������qN��:-���-Ji��I�-���R\�M����%)�Th)E�[}H�\
Z��>1�i����eN���Y��T����
-�����������]h���*]B��BK�J
9-��m�#I\'%d'��Kh�W$����r��p�>/7
m��;�1��8.��+����\J��x�[��i���0h)��{�\@$`�DL���bV��X��lC(G�4d���h�BJ����R�*�(�%�����`���,u�I=$o����AI=$RT �
��,	��J�����'�[>%��L���`�|��Yn:-��R�}���?��HH���e������a5`u�����UW�K*g�q8��5l<o�U���x�y#�����M�����m~)����E�����n��G��[�u�6��.���k��'����9�C|H��������FA�������+������N���k����9h����H��B����Ol@l�s{�Y��������9-�������H!��4b����2�i-5�\�&c�Y������"&^�Z��(o�������S�K�&��Ln�x�4'[�;<��5J"�U������^��y�V�U���V�NP����������w�����������e�����Xi�X��BH����g��E�����8q8LpT�&�9('8
��C�*���Y�K&��Y�2=��Qm���o���(Pk�"#5���q~�/����e��[���s!������u����O�m)g�7��.���(����0����m�.�_V8�
�"���u+
b�k^��J�^V�\{k���)�N_����5����X�*���"�q�u��zL�(0���E�t_wqN�Z�G�0U���d�3`�B��e��U����O��LA�f�#A�)�5�����T��B���h���z�`�e�q��9L���%f���<@_x�0�B�[�z*��0e!-�I�T	i��Q;��`��|{A��"#`��.�����)����|��L���
��r��I�/��L��V�TB+�-�l�]��GO�L4C�~Y5��R��,<���C�K�;J�����il���\lI�
J���!F���SP*��l�}�]�@�0eZS�WU�b�l�Y.����-K���Q*
j��d`
�*���E�(���_��^A)�k�ri���K���=��Q��6=�9JA�l����js���r:U��]%dA����!�R%�|��%����>�|W�E�BHk_)O�*�zn��
��P��yzp1g�CT�r�H!�Q������fsW?�%De����ec�j	��M?��'�^/&���J�{��X��`Ti������\��b�/�un����Qm���X�J!_~w����`�8�;��Q��k�*�i�z��
^�,����Fa�F�4��;��em`��$�wF������(������Q�XY�JG�|`!�yt��M�@�<-����������4���Q�?�;8
�����5,����8#5CT]W������v��s�vg�6+�uI���/E��v{o,�0+����J[29��n��?�(dw
��aPT��R��bT���c8i5�j{�5��zEa����r�Ei���;(�B6W�B��$����4���lq��"�)Jc�Z�qV�+��W�AQ��.����7nE��g�ik�~_EQ��@����P���NQ�wE��wE� 5C`���%���W�;(�5���p�=��$�J'�UBZ���#�E�1���"��d�S��E�A�u����t��4�VpnV(*
������d��$�Cva���P�J����nlP:��2�edP]eJB��� d6��)
B�-DNEA� �!���}�IEI�-�
��8E+:6=U[u.�5���Q�!j�]��y��|�k��]�� �Bg�^Q;*��/�K=��c�:����f���VT�X�C-�O_�~
K���V)�M����4d�k^i6��'X��V��Ni�}��9��S�|�x�#�%NNm���A:'9��Hz3d�����M-��A�i�&�h5������=�h��	2�R������1Q����80S����|�)����/Ukb��R)_CK�r!v�TV^P9�>��+���h����u�rh���FL-*���O��6��BH�]�X�l��p�R3F�r�����2|�d�e�����
zm�( *�I#���b�=��=G��`�h[��b����� ���n����s<l�&/�.�L����N0��t�''h�����E��lt��e��^d�D%�`�������W�S�_�O5��Tv�A/h��KZA�����3�4�xZ�������M����v��e���B�-lz���A�\��AQm���N:��`�]����d�����u'
�d��c�e��y�S��s��=�|�P�E���X��(	���A�\o�����AQ4����=N�(�N�d"��;�bM��hj�R8E��WQT�P�g+��e���sT��Y�^�;8�f�*�^����V[s��$Z[���y�g�E�G��<���2i�7��Y�9\!����N�M��?�������u��n�v/+
&���5m���	CM�nhKU��H����Nd�|���z���M�:���ia���[oo	��0����_��pt����n�X������gR.�o���+�M����s��}3���#��������o(i�cl����G���]�������&���1�d��K�~+�cZ��<HsgE��������ExQPj^��PvF5�>3=�b�Y?���/_(�����^;��{[�@0���\@�R`'LI���4�7	�P��p���z9R`'�J��;����q'`�4�UL��e]��R`��F.���Gr���?v�B�B���:�
v���`�����U%[���4��N7'���9,�v��.�t�����,�c-+�=��M����A;��Ni77�������V�S���o��'��"�Q�S�xsx�W���H���U?I������'���V�3Qo�X��l0�~V����6Q�3�)8����-�z�O�*h{�OR�+I�kU?�#f��U?������`@�"����P8��~���}��tA�������:�9�NG���L�]]�����R^��Xxm�bcW��g�����O��Vg�h�6?����B)��d�z��,�"8�Q���Y��D�|�$X(E�����P�`W��g!F���`!�,s�o._,�<�B)���=���
��!X���NH]XHf�d���X�G)��'^=
�j�,��(��M��/�	��Y���,��yl����oI��MP�l�/�=�a���v<���&C��i�u:�-`H"�s7����F�'���7�0�}�:eGj-�Xa�a�XA�Z� "�Q0�"�6M�0�Bi������Cv)?0L]*_�K�|y�a��h9��t�,W�D�D|Y8�����C��2��h^Cz6lt:/6�}�k��X+�K����q�=�+���Cs�O�x��`�y�5�K�'2�� b����P���nzE,�:XB��q�3g�J3Z�.�,dj6I�#���DY�PZ�{�������.�_�2}�X($��&k�zr����B����<��PwD%a0�8i]�0y���f��^�Q�CC9�����H��X�G��c��!<�/5/0��q�W�4��i����hfYM��$���n�;V��d����3��`����������z]GGz	k�����h��k�����T�Nf��-�=��5���;������>�|�;#���5n��AHo������d�����,�o��qd�UY��S��-�4�,�wI����u�d�����DT!���2d�����A�4���I;VD���k�6^^/�J��xsj���e��Q�)o������
�����NL��;�r	b�-��`!&3Zq}���)5ye��AL0�/���'&L��[AL=0��8�U����/��B,��2�1���G`�i��S���&]
b��)Ky��W����BL�#I�\��=�v'&��]M�)���"*�)��)�����a81��t���)���__B��a8�/��m�Kxr��:=��7���!�����>>ZLi��T
�%���Po-�"\�t��l�-!����c�Yhh�R�m������6��C^�%�g�BK���[�AKiKk'�p
��imJ�rH!k����=��/��-��^x)���#9�?+��}���!���=�n��W��$d[��&/�)/��D����D�b�|W�W���=8����-G�:0U�*`J��"��v�
��X90���������qd���ur��G&�x����O��v|�Fy���dk��c@37��,���U��]��&jb�\:)��M�����x����������N�����TB��&��:6s=��x`3wW�!"�)��N�tx��e�L��,����6���K��%������y�����~E���(����(�b� �����Y���(�Zc'����}sNk�~��� �y�uKe���:����d�>SV����:���Sk�����5�	�����_'s�r�tJT��|�89��o� �Dkz�<P�	��v"=�Ds��K��T�����*	v��e	v����ue<
�����MZ~u������L�C�<
���$����
�^k��+��\}v�R�BP��I��vS����[�W[D/h�������X���!*��k�g���!J2���R����s�B%i�(i��O�4&�l�	]Q4g���>�(k���3���l�������0Q��e����!J]2%w�������f���_���!�
��d��2g������N�(w���,��(D��~l9D��*�^l�U��+�Z^}�C�Z���j���mr������W4���I����p����f�n��z���5��`���b��[�T�����:�G�w�x!fRrB�����D����$�k� �vn�Vr���D����I���-;&�Je�����
Cf��]j���v�0��b�
1��"�����47�)�9��p����C�
W���z�����m�<��`�#�	�5m�c��N\�+��M�T
�G�l�����Z�`�����wW�l����U4�,P/>��z�u�Uj�w��m��N��|���	��U
x�1�O�bQ��b��sN�s1�7��T�
WA������]Q��%��D��Io+V��J���Kv.�
R^�N� 
�J���8
]��� �b�bu���mQ���R�����b��BW�e�A�`NW�V�(tb��i#�h-tE���6m�+��JJ�*�<���]�*ut��<�*^�W�u�WT��6�*�~�D]z�����yN�vU��9K��JK�TE�v=�|�i��;2���o��"gkG������L;�NT��M�oPQ�]M�y
��6�����4��������y������')F,EMfK�&�8JQ�d������TH��7E�:H�&�Vvr�oO��	�M�B�{]��E�&�����_�(HyZ�P.c��'n���8G�T����Z;@��2�-��h[��+M��%p�����Ky����-�;:����A�������s5:��/�w�Y��b�sS}���S�3�m{�-^���<���<j|���9����$K�&@Q�-�
�19A���Tl����P�/�x
�&~����1����3T%�;.�B�l`�w��,���q��x ;`�T�Y��^I��Z��N���b�$������`�2i�J��8���T�����N��3b@��T4����ATa�w9R��+�������T[?��:-y�Nn�L�T��x���b�J�*�����y8U�9�k�$
n��.�����{�kZ��R4�����F�L���Te)������}c*��*;����w�&c
�b�QU���>���PA��]6���1+ �TUb��i�"�*���,��cAU��G�^FPU���4� ���U�����NU���.���^{�sU=������d\�O������U�v^e���o�.�Ts�\�:1��;(��e1V������)r�B�npt��=�%*\E1[��s\E���R����L
mWQ��d�7|��>)_U���|��������|�$�*�|��I���.�F���D�7��
1�5!������Z��>�W�WQ��v�u�����I������T�����W��Suz*g������AU�JIt��9.5�J��$���y�O����\�"b~����*��t6��c+�$��s5����?��,f�iuO��d�+�\E]��C�l�U�2[:Z���\��9{����Z������-����Zq��,U����{�"��.��C����,�m�~���sU�y�3'
��.�%��q��U7�u�2���=Zr�,�V����;W��S�U������:W�������\���sU�t����yU{ln�8��k�ahn�M7�nOA�\p]=^��w�roM�{���l��5m�'�������MZ�s]����������E��������I}��O���o��%`o�y�����������Z���E��t3���n�0�p��0��p��OHv�h�t!��s��3z�����n���#������;��'V�[3���_�����y��� ���h�1�lK�f?*����aA	/>= +^�����mM�^����8de��8�5��������m���2~9���N�7`���^��9%�O0rd �I-o�:�@��
���a�: G ?F����o*����h>�JO.�rh�@��h�C�|
9|��L@����:t���J�38�����,�j���W���8'o�ls��'5��:J�)���n�����WG��[!�ztEn�E���z�tk�O��T^>Fu�V�DX��^�X�OQW�uhqU�e?IDv���~&f��=+��Vpn6/��w�5��~����3�����7�������\V��~&Vh�����[C�/��
]�����K�����D^\9��~�`$U���gf�f�-��#S����Cr��f��{��mE	3��8hI.6�%�V����J�a��zy	�Z�8U) ���[��*	o�(D��YPPIh����dp��M�9�p PK�9�lPvW��P�$��`���Q�����2uB�OK�y�}J�7����(�'����WR[��G�����{j2�*��+��\k�;m]��)�B�h@O*��I�y��<o4�U������=����g�Q�4o��j�������z��V�	�8��o�4��#3�p��%"H'��&G{�H����
�h��[?-�U��3�����L�2��������$��qf/�3�`�|���D8��`pvf� ��y�U�JRs8�sBsLU`���t���^�=�xM� ����uE*=�������o'eTu�H �����9�
���v#�:,�(D�d"YHT:D��<�$J3F��LwD�\�*�*$	q�<p�S�(�xs�@"���7�
A���L�BBo���} \j����D���l Q�u(HL������#�����wT�tP�&���
Q�*f����(�<��k.E^���
4���K��
�K����I�=�q:���o�E��x�/���^��e�XV*�Tk+,w����'�-���+������D�j0&9��z'h����{�z'd�����V��li�(�W;!=^�M��v�2��F�M%�m��?������z��*CF��'����f��@�9�t�z$Uu��	
o�D=[����W�"^�
R?�/e1u�5��T�:�O/���$�+xyIo��%�}7���vS���A��AL������x� &���5�>KtbJ!/[��5�H����E/���7{K2��v1��7����D�R��j�[�2���S*��l�]� &�k��2qb��f�C��B��i��mSv��v�B��:	�����Z�F�+���=�,����b��vKF��1�)Io����Py�����m S5_?rd�7���L�������L�����lL���K�����;��Ar����j
���7�0`*��2�y4���DP�LS��o�05�Sc�� m\S��0`��i-&
�:0�-����a�`�3I]��'{�-:�F�������]�-�.�)_�w$w����L)����PZ�@���-���
2��u�
d��J����)My%'��L9�u�������:��=8V�����@����L�5]�pd�'o}OV7�v���=�(�e�T�_���6��J���=b�~��;"M�Z5h�5_v�Ag�3h�9[�]�)����|o�4��d��.d�L���V����Yl�88��dsZ���+M!d�9���������
2�6����v�cS��B��zd��k2������b����,�R�C�Z����=c�j�M7%�����Y��&c����;������k���zk�5�f����:"�PS4_���Z$����U}�/1��v��z���k�-�V/����OUa�NM4��e
5��>I]�Dkx�5���F� N��:�j�9OE�����]����jpS�c�:p�9�	�<�^h�sN����J289�9>�zS���Fg�e����9|�(�I2*�y�y�<=���C�k���/��5��+�@�����t|��a:���Fr�����U6�4��]�PC���V�xeu�
�`���$T��5����C
��Y��nQ0��U���O��m%����Q����,�+��y������=='�1��Av:a��e���c���Tj�5�Y�-)���S��F�k�-M;Hs�9��G'��e es��G�1�&�A���
��y�2"�E���yM�P<��sUo�%��c���Zk!������v%(�<u\����~h��
K���uo�����R0�mQz:h���I�1���I3�c*4%������b	��A��SVh-z[�$G�4���<!zb�����`['����f�'�*��~�Bf.��CO�i1�U������gK��#���-�t��I[<(vTE��X� �JUP�Z���p��Q�-@rP��������V�A��U��T���S��h�������A�U-`�}�zLz�j\�b^��n�,��U!f�R]�����h�M�s��I�4�YpL�j{T�JL�r`��3�*[�e;�YaL�o�_���,�2�C@�q�L��J�:�\U&��_�)���J��)�6��9��2N�����T�u+Ur�~�@��b��z2AUm�{
[��A�*�t��O�x��*��;S�_���KZPU��(3�U���nQF��v�j�+x:5����f]�.)�5������T�yE:%Pxz.f�z���+-�S2����T�)�d���"��T���L:���Gi��$�)���H�}���2!��� }'��`���Q�����0i^�1q>������v�9���S4gJ���
1�����5���B�s���@��4�[��t��T����bW������E�x�^��5*�U��Z�*�`Z!�)�O�S�6��O��)O������yz.��DMVYA�u�J1�T�Ed�&i�T�3��Ds��<%�������<�^~=n�8O����t�{q��I/K���Li��V��K�=�
��E_��e�����j9x�^��:���t��~i-��^�9O����Ej<b���ER�9x*�d��&�C��T�^���is����x�@��-H�j�]k8U�Q�S�Vy�~�*�*��U�	��AT���� �R����[��ge~k�*��V��$A[#��Z������U����g� �J&�^�I����&Yj�Z��I-79Qy��,�G_����}[a-�w'*Zd'�Yii���b_t� *���j������L�no%�e��U����r�����l�h��+T%��E��vU��h�B�3�D�m[��;
�j��KP���*�0����WUzF
Q�uK���YJT��U���^�����+*^��y��mh���Vj-Q��\m�)pO��*�����AD�Lk�/��(D��-w)���j����.]��IIu�BT������D�A��z�D�AjyAD�A�J	P(O��,e�f�I�g�@��&�~Y���}]g������Vn9=CUb6�ra�BT9�_A��
Q��w4DU��������KW��+g�*�����d�T�W����.H���*�fu U�w�@�N�5������v�Z�j+T�pMW�6�j1�5[�F�T��u�~Y��4��LZn��|��Pe�����$�ku��(YV]��oPE�,�0d�p��E��h8���db`���
&����e�2i^��f��PUB����
�l����hU%f����a��a~[�@�j�*��2Lp���*
������������K����++�*���.i@U�^Tmr�0���V������=6s��=�ahn�M7��X8��	�\Z�,w�T;�����m{`��:��<�	��B���i�h����c�t=����MKC���z�Y�����~H@���M7�����5��y��f��������h����,G��7�LlAL���[3�8=�8c3v�����h�f�g�c�7��BP����L#8�V.����_~�������B�S�o�_��TK���<%����_��B[��p���Z
=��,?/�[Zf��f8���v����~��v����K���������u�tZ���zX ;�@y�1�#���60������i���r��I�`�����<WA��BA�H{�mYGnO)u�o���VS�?]�1�������7�|���l;o�$������x]3����b�y����o|�����h��X�����\�+��,E����in��Y������jgL_�^�D|YE���5�xsv:����������`U=3 ��V�UH��ZUO��u�U�$���U=�!&.�eU=S���$��'�EEU��
�Y��zf��l�K�mU=A���zUO4c��������V�L_���wO��Fq#���.��R�������^R�v����u2����z�P6&�������v�c:O���P�|{Yx(��8�"�Ih8�"�|b8�f$g'� b����!����C�IN�_p����<�dM��C�����-�&8�^��/p�XA�J�0/t��C4J�3��f����I���[�z~�b���HACx6��������Ch)���y�e�q���^�x�p�xkn��]���eD0�v�Q>�J!V��o^�9���f�t}���+_��j@�����{��
 ����("�`5�%�d����R�z��C-�0I��"uc���nV13��Dz���;"�����@T�3 ��bsG�n������uDR�����C���'�
���"e������qh���*��@<o�^z���?D)��TFD!b���hD)��� ���(�����R��d���p.@���+��V����� �����:��VHL��8�hL���Q$�L��q��0���Vx�D��o�oS��/�+q&J+��.F*q�Hg�A�l��(S�U���]2�����0�����z<��<?>�����i1�8j)V��	������[�j�"���ah�����7��	��2K/�J�d�%W���V<���Z��.�V�m����*U��pp/��l9$`��O�S9�ZpR	y��������}��S��w�����z�M�7fQ��h�}K!^���ybt�Vp�=��@�Q�L�U����N��5�Hu:f����*�m�(��$�+��_�;�95���B,��1E��6�_�Y�0-���?�,�)�x>7��tbj[���|)����")AL0��S"1������$[�yN����>��m��7����!����BL!���@r� �|����:��,��B�D��*���j�{sbJ=z���Y�	=2nEx ��FL�����JB�������C S5����������*S������j\SL?�xiA9�qE�����e��'QV�s\��k�.r��2��V>�c
.��,+2;,��9�K%���T��c���%��P��K2�&2���p	�x�g�KmKr��Nf{np�!p);�� ������vMf��d0�����YS
yE]N��
`�>��/i�2�i�:
�S����S���nI:0����TR������fU��)zp�u�S���jL{��+Z0��p���j����fV��P���)Z�5�^�80���V&NyFm������`�k��o��--� y*�%����[��|��K2e�|��{e�PFS�%zX�C�[<s���ok�s�mr��I)-�}�vP�%_v���-����y[Wi��%���DKZ,~`��v<�4�(2F��Wq��ZkO�#��b=	���Q5���#����R>�a�Wtv2J��7P��o���j�vE#=�T��[�F��h<��.f�m�V.����W$
���x���������W��G0�m[��d��13���`�Vw��!ipl��n�Jk�DhmRT���C�?lE�4Y��o������:V������l��U�����I��4g�WsAKzu�&�~�p)D��,Rk���ZD��%vf0��y�n����=�+fj���Q=����O-��xa��<�����=�F�d�sx���`�^�9<��������6Om���Su�����//d?7x�9_��;�w��dg�O4g��b�$k�k���5c�y�W�J=�<�9V����J��T�z~	G�Ozs�U�����y[��4=��d���p�;���|���s,

�\=9+��L(����ZF�}JeGUvV��o��5~���_���9���1�!�������;B��y�O�p��-�6��7_� �*��\	i��]+b%�b���"U�M2h 4E�s4(O�M
�s��(�e��.�����im�W�9IS{���BRm�v�G��<��6�k=
���H�T�Y?��_Z����"����4>�[�)]�*1��o�IwmyF�M�Hu�m���AS0hJj�M����Q�+n�MEc*�Xh
����R�BS�j@����>�^�<hzAs�i�hn������~z���%|�4�^�O�k�+l�w
1kP��n��7P��6;4u��A�����"���Z��u�J��Pg���<%{&?��W�8@I�p��������A_[(��q�*1kYo��\�)�e�:Th�i����u�jM^^�%�)��LJ�O��~K*OK\���e\���������t�j����S�>m�N��+�FS��;)�������3�����S�yN����z^YE.�������S�9N��v[�d����b�	�{�����2(����b���s�}8�Y�
�N��1)C8{^i���S�g��6]��=��4�Hi����&S��|m�����������L���_���>�
�JM�Fd�	��9oK��7z��nI�S����E�j;`*=�����9�B}:�+0�]X�7�c:u��|3j`
�W�ZW��S�v����w��az.���'��
L��m)��fiqKe�T�D5���u���%�g{?0�z���^`���]:�����(��
L��-�
Uq��=o<H.0��)[vM�����e�T����y��f��K�O���C��&O��@���4:V�$-jI���"B��T����M�����jU��M������g3M-RW{8<9X
VW�e�/4����}�k�UX*5OY:<nM��z�,UlW��;]�R)�]������Uc)������Y��%��y6��A�[<s�kc)�No��3��A�'&6�X�����;�X��&)i��8@��F��Tj����I�Yc���e�B��,M����@4��w�gfS��@����� �������������������^7��*5,��8�R���m^T<���h��^����lZ�n`��]q��i������jaz.�J���R`*�l��\hr��
c��
|cz�Sm�v��4	�j������`zh
L��g�Fh��}�&���/�B���)�g��9����u��1���T��e���������d	�����MD���`����uv�;[j�
�Vx��Q0E���P�S��m[��L�*u0U�3���u0�k`�������z5�8������4��:h*_j��N��}��|����B��h�4�Z��n":L��l,��l�WZ���z�Z�.k����^";I����E�����^�aEcf[k�kRm�v���l���|��$Q�G���/�8C�����2;Ba`�$Q�T���y���P��z�%��u~���z4rs��)����zLD�������,q��ZJ::���,C��5������	�+���m��&<9=��y���W��?����
endstream
endobj

15 0 obj
28984
endobj

17 0 obj
<</Length 18 0 R/Filter/FlateDecode/Length1 16124>>
stream
x��{{xSe��Z���������4���hZ��$���J�
m�FK���Rn
Egq�Q�����8��x��3����8TG��8pg��������s��}}[�t�����z��[�-!��2
��
�#�o>��p
M
��<]�^.�P����<q��@q��uMS�n�h� {K4�X�x\@A7Lhi�F���+
�9-���Ft����	O��"S?~��UX�<rk�fzP$�����h���,��)���������,����=3���|����@Nz�h��JU�Z���
FS��b��Gd9�#G�xw�'��;z�X���aO���vX`
��0�����Jo�?S��F�����0�&�w��a��������1�,LS;a7���z7�����^=�k��pN���~xnIK?�7�n
?�7���$�?�p��n���R��������{1����bX���@�W�����Y������Q�[`;���`O�����/���3hS��E�O���i�n������:NQ}?��������F_�=���~�uL���%��6�6�p��}�n������5����
��q���fV^_Q>c�������N�<����J��������d�]v����i�*��c�B��E�/i/o��x�=���<���2#?��SQ/�^���\Oe%ay""_�����a���/6]��5���h����������O����^�6���/=��L.y�������<�D%E����Z:��g��a�:c�gz4#?�2��=���y ��$�p�T$5�|RJ��V����F14��|������u�D��I��.*�I>&�[�����{N`Y�O��i��T+��p~^']��y�h��c=3���}b��+��y���O�Z5o�O�e�(�^����
D��|qv8'��p^�W �"5]�y�n�qTx*�;;+<|Eg}g�d�2o�tvi4���z^�P������mu���EC}N
��^1�J����V��|KD��"�
x��8��A��w�ATL9)�n����'��,?�-v����yX�8�B_X��%I���R#I:$���=������N���l���������L�#7K�1��:��N��/+]^��3c������jh����t������/�"�k4�e��P�S�)�O����.v,����J����bp_.#�+�**,��G�E��� �)z��3mpt���c���I��h�.B}C��XXN��/���!� ����}���]%���J <CR�N�������&�U�h��&����a#aOm4,��c��:8�+�k��=Us�^�DH�o�f<����zE�W��R:,2^��z�
��z�M���*E�� r2W��)|-:`@[�+����3�z��0������8�U����w�-?�y��x��c��*��V�h//2^�Hy�W��K�z����=-��J}��C��N�yz��{���<�U�_�d�>����������+�3�|��SU�)��
�Hyg� A8x��A���=o�+����
�bn�$��l��T�N!�U�j�p�&�2AV�����E��.n������j�5�������^?-������>�	���Sz������#���;�
t)C���$�)x
')�g��GA���$#K��4�T���#OH)f�AeP�PZ����T>�*��������>��ObG�*��5:@�A9��5�]�,�=�-:�g8�&=�y��O������P~n��K�V����E�L��L�B�����4Q��&�? �9���L���yb�HM�(!`q��c��7��/��
���:
������:�A����X��UJ�f���;��MXVf����2�Fw��m|��^�3�~�]��Z�������9��I�3vd��y=�rj����g���zV��-
+h��g"��u+ �MPf/�
����������Q����3��.����H�������&��A��o����]��Sh�;Mb�����H����B�T�z��PF�Wa�
���[��
���C�	�T*<?D�O�;T8���V�O���)n�_NO��B��-��c�C���e&]|���I��7����2h��2h�FE�9����F
�kp�gh���Y��{5xZ��jp�w���e�,*���e��	�1�����_���h������,�A�o+P!
j��A��bI]]]��:���\�������o	�� ���&��A�_���?�j`�����Z��w�5���|������U��@�����H�F�+T���6�R
+
�9�������vL����!;���}����(O6e4��MtI�'������	��o�������>{a�O����G�R�R��>C7�����G�o�������<��������9Z�Y����j��J6V�U��UA��2������ur(Y�,]R���?��b),/��.5zJ����c���H����Ko}�
 g�����
_~������N���9���C)h��Yfi4���*NVa�
/��m>��=*����*����)R�^��gT�.)��*���"{W��I�%�(H���Ua�0u9��
{H=vYH��D�C�� �e~P��

*�+���B�'���Ui@^��������!(&3q|J�V��B��"�d�b>��`>}�!y~\����Epop?v�Ba��hZo�b�����
���`T��V(���^�QjZ�3����9�0X��q_1�(��bLc}1����0�T�S���.�[a4���-��@��f�sKK&���W1��.�Zd�X8Ov�h�GO�kQ��,f+>��������k��?/���~5nr�{����9���������P��|h���8f���y����|W� 4W�0�?h�{�O��U�8��^��F�6�S`�'�bu:����e�����--dX(����/��b��./�{����^�Gfp��W��!�)X��'3��L(5��f�*����T����)%�4w�a�����^���o��{�*���p�km�����u�-�RgS������{�M@���dZ�K�X������YY��b�	],�Y<?D���,�a��4�!�A����(���ERW;����)����L0V+2��b�F�0��,�z���hfF�P���PXoP�������n�s�v80��z�X��Wb���K����a0��u)�m�[�,M~�h]��������F<I=y��������w��a7�_?�����~�Q�������g?9�[���?J�����@�%��X`�#��H���n��9���_O����'s#d�'h�234f���00z�@ ���L�~c�h��B�a�\��*_�)��3%�����y���)�������">������*��)
.��th���i�i��
;�:#V�VCB����<����<���@��0&8�K���xxJIuN���	�%��X@��L�[m
�Z�y�F��������{�mG��������p�o�:�[�#�
m�%��<����c����M�\���ee�����������7TL��������M�g���I�K��MJ�G�G8&����V���}���(:�<��wb�����p^F1An��T:d#h4�=�j��)��y���[j�I�n
��u�;�M�S]s�1fR��[V�y�.=��86�lN����k@x�����/hf����Cs��a��<U����et|���mdK�~���6�^��������?���}�TWR�sL�P{��n�J�b�1F#���
�z[�Yg���f��
����-r�p��/�w�P,���"�)��"�S������P_������%��H�SR�/��#58P�e��0�H�L#�7��4�",���%&�9��@��1c�OE*��7��1���Z�d�/���@�d~���P�y���5+S�vdU���O��P�t�1�S1����R���o|1�F�_n|�������,�<g�,�V��s:�{������v8q#�G�g8�����N�@�������8�(��8��">���D"�s���O��!ve������l�q��O���[�!����U
���Olu8�J�A'H���q,��M��6�W�����t5P.���d"�@J��1�q���D�����S;�Jm��M3/�j��S�U���>�����KA��`[��K��u�
'�=j����������9�X!���No��\��d��i��'��,i��#9����������T��� {�xtKp��v,�WySB��%��}1E����?�z����6�y�e��NMX�l
�t1��Cr&����3�{�My�����Y	N1�T����p��@&-�V�����e��a�����#�GZCFQ6��X-F�����4����������B@X�=�*4��F����^|�BD����!D:z�-�����'���07�X�3�o�V�y�R��|���P�i��ba���F�V����U>���C��>���g|�����>���qN&R�o���o�a"^���>��C�/��i<�����Q`|x���^��[|XBDz�]$��}���L�U�����~�,u�=>��I�>��"
�����>�<s�����C
���o P<0�e���(��1�*8��g@N���p��4,&�j�}���f����Y�X��z�'���.#DX�����G��+�$���������o17�h
�����)�Z:�a���.�Z�v�3c6<��:���c�3p������*��22�P8��r���"�/�zr�����������~����������}�������*�?zZZ5=�.�D#�=�[t�/����Bf$3l�#����2*�*P�z��������Ae��.rqG.&r�������������?}`wg��X�2d������o��1�idX���uo���m�nY������������,��f|Sfc]�B���_^�����z��������;�'[�F�RaR����M
�
�iCOvg�����g�f� s_&���r�f�T�Q������o4s
�v��w�O<3��f��c�H������$���K������Rw^�>(��e<�.P�
��&N�G��BX��-B���w&��c��������_ ����y������z)�7u�c��7�~�������2�v�t�3t��D�O3��`��5Q�Y�4cd���hD5��R
�C����F�.,�C��M�8��Bmz����D�z`���@�%�C�4�^z5�$���
f������vY�BA�H#�Q����1f��V��fZ��	a�f���`5*�_N���	h����&�,��|�"W"��)��<G|���/!�%��}���#�+���u��{~z������T
��<l����\�R��/^z�����h��=�	�nL�a4���i��d{
N�;�k4
�����~������F4�F#�p��B���UBX!��?p�`J��|����!V7Y�}X:�l+F��4s
�(dF��������A��=]O4-����
��y�����?`��"nz���^0~s�Fa�C��Wl�-�{������b�GH��
�F�� ��^ii����N����&���������a���t*{E�:T�P��4�����9���kO��~��O�v�Z�<�:�v���~����w�0x��g�=���%T�g�>���.��`?�Q�i�::S����Y�0���T�Zi�u��R�#����b��[�����cE�+^�������Xq�wY���D�lE���Z�c+����V<N�6Z1IT�Z�,'�vs1+.0�Y�+�O\���V�b�v+b=��C���q�*��A�TY����V�HD�$��"�����z�V<O�m�c��F"
X�2X�d�^���r�o����Dk�|����7�I��_g4���[R����C��!-�!O��gJ��_����}�'��#'9��_z����H��?�W�L�s����^�7�[�,��N�fO����*�Pe0�V+h��j\����>�j���^+�k�l�6X���^�������h�3Z������-���^�y�JA�"�Q�Y`,��E�V�K�%���nE��)6�M��dI@�
���7;��65�_�Z���������M-�/1�����3�z�)C���&�nSf�3mF��P?��z;&��h�yv�f�;���dG�����c���x����8T�}+�o��?����m0TE;���N;n���o��������������������?��\��T�T�9T�

�;v|��c�
�9x-�s�U�<�WlK�~���"�4���CW�����Vq��9��`�:���s�\fLUw��f�_�"U?=�-�P}7���)�;��G�kT����:PM��������E�o���L
���L�7W�����^��S:Z��-���u��@y����qp�Xf /3�bS&�t��.���s*2���_=�K��	'�d�����'����/_}h��]�:n�k6�a���m[�8D�Q�h92���/����w�x����]��x'|4��4��Y S)/~���|���w�!���bw���B�	�8�6+��iUi9�h�U�=&{���>3��l�`p�t�������W_eKK&L,-@��/���%���C����x����~�������z����J�����o�n�r��M���my��hny�����s3�8���o����c6��,�=w��5kW�]��i���I9��uw�a\��dXT*�hA��J�38�C���)�x|fP����R7���#����>5�(s.u<����
��������u��%�RS��f6C���gj��3rT�^ge�f�-6sx�hU������ �
�a�tHMeR"q4�K�d�-nZJ)32����}�/;{�����yg@,��}+����>�������M�&R����n�`af��4�
���?,�:!���5�1�#Fdj�p�%�������������Z��u<L�N.����t&|����w�5�P�/���^���Cv�Ci��#?�w���|q����\<����?��A�n���s�,��w���EKB����#���G~r����N����������=�������'���G�}��'I�����o��[���!EYc�f�C���C�LN����6�����������������mgl�l��Km/�(YF�m�������+m��y����Vo��6�[����h_B~A���mI]��<�G���$J���~��������*���O�-}��L����v��lQV��@�T
@?�L.^�8"�)uG3t(��Q!�����_U�15�W�N5nTcR��j����K�����FP�5������C��Q#��O��#jWS3�����~b��(1���h�KYA���F��%o;��Pc���_�.�o�D�\���:
\�;I��45X�m����^�
}�P�:w��K�*
@���g���K�S���[�7��~p�w���r��S���T�����a���W�������a���K��(Pe����?A#�BF���K���������(c������;OJ6Sa1'�����2�
Zndhf���t2�w��Se�<#@� �0O1fRe0�	��-po���*�:NW����f�$��&�}�5
�"����3��U��3��������E�'5Oj3t��{t��V}�~��7t��32J����p��b�!�Q�6����9D���4M���4
Y�<M3����4Z���9���iZ�AW�V�}iZ:�����4�'u|�_P�I�Z(�b�A]
4 ����9ia���)�1�4MC	36M30��K�,d1��i���iZ��4��1�ciZN��4�A���[�V�5����nR�#Mk�f�@l:(Q=;#�K�n�6���d�o�'����[�����|q��"��x��5�O��'���d,�V�gL�R���m�+#�<~f[C�������WG��y���������h[c�����P��uA�]�������eWh�>�'�#�����[�x����hsLHF���|���)�.�C�d�-�G����
�45����mOFbm|<�m�o^�c
�7�`0�!��NFWE���d2*���E�h#o��k�-����[b
-����7F�Xs[��_�����|������WE��U�<�=��Zbm��ix!�kJ���-������d{�!����o�/OD��e�Q~u,�"y��,����MM�v��-O��W������h��o�F#�b�����%�iHF�cB2� �d$[�|"��_��=��F��������Q9�B�uUT �m�h� 
DctU�5������H]i����c����!�6����������� �������!J����E����'Z#��x�r��%�LL*,\�zuA$=*
��DAC|y����k��P�KV����5D��Q[I�V�D��Y��D�����%��B?�����.���X")���x{s���Y0b�1HBn�(4��$D���C�@;�j�$��e����C�p=�!��
Q�a:���3B���
��"�~{����t��}�0��
`�`D�Y��"�i�+�"���
�6h$-x�������D"����C�^������<�q�H����o����y����U��$�e��]PM�B����$��F��_��h�&���]�l �%,������t6o��dh$��&@�UruTT��V��	_z�lD@H�K��u��r��\��������F�Z�V[��2XCF����������A�aU:J�M^:�M�S ~��x�c��H������'����c��d���#�
�$B���C"�uY��V��l�{Z��dd/�BFKS�<�&����r����H�GIT!��b�J��q�LD��F�#�$�
C�!��'K��	����3���YW�(gk("��h%�
Cl��h	/>�YI�5�I�q+�n�&�29{��Z�w����&��'5Bcz�eD��V�Q��H�p�[�������dJ�cYN����.��
a5����oh�4�+� s����W�dphU���Z��$[���C�v`$�a&�9��4����WX�j��yr<�'��BFc$�D�
H���@��������u�kw�T������N� ����a\�����IP���_�C�����^d����!�a����_��Bc\_V�q�W�8��
�k����(��9����~��9V��'�\������WX]�V���=�{����'T�V�]�������l��5�C�������TB�������gj� ]��k�����]��\�Q�#���Q����B��K�\��1���,�N&Nv��O�w�O��+\''����X{b���'���8���x��������A��h����t��C�D�[��������������z��
Q{��{Rsl?@�x�@���=9�����w������w�\����kwn����-�/x�q&�wl�vl���=��9�,�'~}WE�k�&��a�+)\B(�o��j�(ue��f��^���5�������r]7U�w-^T�ZT1��Yl�a��a���V5�z�J��f���6���sK������x7�3+xWeE����R��
<Sq����@k�����C���B�A@�K�/���3z}�~�>���?���+���sz:8��kX<�;��W�|U'���DEh���Eo����H�6�P�hqm���M�����Ubqu�X?2\%6V��A����
#��0-,$��J���L@���B��'��>����|�K��'$Q� $�BR�%��� �|����?h)��-|�["$e��D!�����8�c
endstream
endobj

18 0 obj
10076
endobj

19 0 obj
<</Type/FontDescriptor/FontName/BAAAAA+LiberationSans
/Flags 4
/FontBBox[-543 -303 1301 980]/ItalicAngle 0
/Ascent 905
/Descent -211
/CapHeight 979
/StemV 80
/FontFile2 17 0 R
>>
endobj

20 0 obj
<</Length 407/Filter/FlateDecode>>
stream
x�]��n�@���sl�'�FBH	i$�[-�pR�f@��!o���V��c���nMS������c"��{�I��2e��>-'���nVY���-��	��,U��.�-��~�
���U�+�p�Ou����>�_t���QU�:�����?�+eR�j
iL��G�~'�?f�N�*�4�m�z�]��*��ty<V������Rr:��]T���.���J��	�[f/\��k����������}$��|��;��f��7�5j���%����`��F�s��`������}����'9�������,��.���0��K�^�����,������o��?{:��{f�<s/�����������8�;�e����_�d���k�{�w�t��B��������y��J�?;l�
endstream
endobj

21 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/BAAAAA+LiberationSans
/FirstChar 0
/LastChar 41
/Widths[0 666 222 500 556 277 277 610 556 556 222 556 556 333 500 556
556 556 833 556 556 333 833 500 556 556 556 556 556 556 556 722
500 500 556 277 556 556 556 889 277 500 ]
/FontDescriptor 19 0 R
/ToUnicode 20 0 R
>>
endobj

22 0 obj
<</F1 21 0 R
>>
endobj

23 0 obj
<<
/Font 22 0 R
/ProcSet[/PDF/Text]
>>
endobj

1 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 2 0 R>>
endobj

4 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 5 0 R>>
endobj

7 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 8 0 R>>
endobj

10 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 11 0 R>>
endobj

13 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 14 0 R>>
endobj

16 0 obj
<</Type/Pages
/Resources 23 0 R
/Kids[ 1 0 R 4 0 R 7 0 R 10 0 R 13 0 R ]
/Count 5>>
endobj

24 0 obj
<</Type/Catalog/Pages 16 0 R
/OpenAction[4 0 R /XYZ null null 0]
/ViewerPreferences<</DisplayDocTitle true
>>
/Lang(en-US)
>>
endobj

25 0 obj
<</Title<FEFF0072006500730075006C00740073002E006300730076>
/Creator<FEFF004C0069006200720065004F00660066006900630065002000320034002E0038002E0034002E0032>
/Producer<FEFF004C0069006200720065004F00660066006900630065002000320034002E0038002E0034002E0032>
/CreationDate(D:20250214173029+01'00')>>
endobj

xref
0 26
0000000000 65535 f 
0000243603 00000 n 
0000000019 00000 n 
0000049630 00000 n 
0000243712 00000 n 
0000049652 00000 n 
0000099618 00000 n 
0000243821 00000 n 
0000099640 00000 n 
0000151883 00000 n 
0000243930 00000 n 
0000151905 00000 n 
0000203228 00000 n 
0000244041 00000 n 
0000203251 00000 n 
0000232308 00000 n 
0000244152 00000 n 
0000232331 00000 n 
0000242494 00000 n 
0000242517 00000 n 
0000242713 00000 n 
0000243190 00000 n 
0000243514 00000 n 
0000243547 00000 n 
0000244253 00000 n 
0000244396 00000 n 
trailer
<</Size 26/Root 24 0 R
/Info 25 0 R
/ID [ <F4DB6785570551BDBE74C146569C86F0>
<F4DB6785570551BDBE74C146569C86F0> ]
/DocChecksum /95E855BF23F4F88F0B35E8A6E3A3D12F
>>
startxref
244704
%%EOF
#198Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#197)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

io_combine_limit 1, effective_io_concurrency 16, read ahead kb 16

On Fri, Feb 14, 2025 at 12:18 PM Tomas Vondra <tomas@vondra.me> wrote:

Based on off-list discussion with Melanie, I ran a modified version of
the benchmark, with these changes:

Thanks! It looks like the worst offender is io_combine_limit 1 (128
kB), effective_io_concurrency 16, read_ahead_kb 16. This is a
combination that people shouldn't run in practice I think -- an
io_combine_limit larger than read ahead.

But we do still see regressions with io_combine_limit 1,
effective_io_concurrency 16 at other read_ahead_kb values. Therefore
I'd be interested to see that subset (ioc 1, eic 16, diff read ahead
values) with the attached patch.

FWIW this does not change anything in the detection of sequential access
patterns, discussed nearby, because the benchmarks started before Andres
looked into that. If needed, I can easily rerun these tests, I just need
a patch to apply.

Attached a patch that has all the commits squashed + removes
sequential detection.

- Melanie

Attachments:

0001-Streaming-BHS.patchtext/x-patch; charset=US-ASCII; name=0001-Streaming-BHS.patchDownload
From 0617aebfdd635ba75f3cc7bc44cc9e72431aa9c5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 17 Jan 2025 16:42:25 -0500
Subject: [PATCH] Streaming BHS

---
 src/backend/access/gin/ginget.c           |  39 +-
 src/backend/access/gin/ginscan.c          |   2 +-
 src/backend/access/heap/heapam.c          |  70 ++++
 src/backend/access/heap/heapam_handler.c  | 366 ++++++++++---------
 src/backend/access/table/tableamapi.c     |   2 -
 src/backend/executor/nodeBitmapHeapscan.c | 424 ++--------------------
 src/backend/nodes/tidbitmap.c             | 101 +++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/backend/storage/aio/read_stream.c     |   4 +-
 src/include/access/gin_private.h          |   7 +-
 src/include/access/relscan.h              |   8 +-
 src/include/access/tableam.h              | 121 ++----
 src/include/nodes/execnodes.h             |  23 +-
 src/include/nodes/tidbitmap.h             |  18 +-
 14 files changed, 411 insertions(+), 776 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 63dd1f3679f..ac1b749ed98 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,10 +332,11 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
+
 	/*
 	 * we should find entry, and begin scan of posting tree or just store
 	 * posting list in memory
@@ -824,19 +825,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult->blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -847,7 +848,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -860,10 +861,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -877,27 +878,27 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchResult.offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchResult.offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchResult.blockno,
+						   entry->matchResult.offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..625140fdf25 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index ea0a12b39af..45f419f849f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,62 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&sscan->st.bitmap.rs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			bscan->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1123,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1203,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1247,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c0bec014154..f6387f60e3e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,11 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,199 +2121,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
+							  bool *recheck,
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
-	{
-		CHECK_FOR_INTERRUPTS();
-
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
-
-		if (tbmres == NULL)
-			return false;
-
-		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
-		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
-
-	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
-
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
-
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
-
-		return true;
-	}
-
-	block = tbmres->blockno;
-
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (tbmres->ntuples >= 0)
-	{
-		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
-		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
 
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2615,6 +2465,167 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = tbmres->offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * invoke this function again.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2674,7 +2685,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..56378007a81 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..68499e3aa45 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -149,16 +120,16 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		node->ss.ss_currentScanDesc =
 			table_beginscan_bm(node->ss.ss_currentRelation,
 							   node->ss.ps.state->es_snapshot,
+							   pstate,
 							   0,
 							   NULL,
 							   need_tuples);
 	}
 
-	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bitmap.rs_iterator = tbmiterator;
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -168,120 +139,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-
-			CHECK_FOR_INTERRUPTS();
-
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
-			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
-			}
-
-			/* OK to return this tuple */
-			return slot;
-		}
-
-new_page:
-
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
+		 * Continuing in previously obtained page.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		CHECK_FOR_INTERRUPTS();
 
 		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
 		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
+			{
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
+			}
+		}
+
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
@@ -305,226 +200,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-				bool		skip_fetch;
-
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult *tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre->blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -574,31 +249,19 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scan->st.rs_tbmiterator))
-			tbm_end_iterate(&scan->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scan->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scan->st.bitmap.rs_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -658,8 +321,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
-			tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scanDesc->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scanDesc->st.bitmap.rs_iterator);
 
 		/*
 		 * close table scan
@@ -667,17 +330,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -710,18 +367,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -761,13 +413,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -871,12 +516,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -913,17 +555,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 66b3c387d53..b7e4b4d9e1c 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as MaxHeapTuplesPerPage, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((MaxHeapTuplesPerPage - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
 };
 
 /*
@@ -222,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
 };
 
 /* Local function prototypes */
@@ -390,7 +379,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > MaxHeapTuplesPerPage)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,9 +685,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -959,20 +946,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -1010,11 +998,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1030,16 +1018,16 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			page = tbm->spages[iterator->spageptr];
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1049,10 +1037,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1103,13 +1090,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1119,21 +1106,21 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		int			ntuples;
 
 		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
-		output->blockno = page->blockno;
-		output->ntuples = ntuples;
-		output->recheck = page->recheck;
+		ntuples = tbm_extract_page_tuple(page, tbmres);
+		tbmres->blockno = page->blockno;
+		tbmres->ntuples = ntuples;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1468,8 +1455,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
@@ -1610,13 +1596,14 @@ tbm_end_iterate(TBMIterator *iterator)
 /*
  * Get the next TBMIterateResult from the shared or private bitmap iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index e4414b2e915..4dd58e96bf4 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -241,9 +241,7 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 	 * If advice hasn't been suppressed, this system supports it, and this
 	 * isn't a strictly sequential pattern, then we'll issue advice.
 	 */
-	if (!suppress_advice &&
-		stream->advice_enabled &&
-		stream->pending_read_blocknum != stream->seq_blocknum)
+	if (!suppress_advice && stream->advice_enabled)
 		flags = READ_BUFFERS_ISSUE_ADVICE;
 	else
 		flags = 0;
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..478e2a8a377 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index dc6e0184284..934b667ad78 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,12 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator rs_tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *rs_pstate;
+			TBMIterator rs_iterator;
+		}			bitmap;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..4206a6d0ab1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,59 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
-	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
-	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -956,15 +920,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
+				   struct ParallelBitmapHeapState *pstate,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-									   NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys,
+										 key, NULL, flags);
+	result->st.bitmap.rs_pstate = pstate;
+	return result;
 }
 
 /*
@@ -1955,56 +1923,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -2015,7 +1951,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e2d1dc1e067..c08fa33ad83 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1822,11 +1822,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1834,10 +1830,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1861,18 +1854,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1880,18 +1866,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index a6ffeac90be..bc4adca3809 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,6 +22,7 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
@@ -55,9 +56,16 @@ typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	bool		recheck;		/* should the tuples be rechecked? */
+
+	/*
+	 * The maximum number of tuples per page is not large (typically 256 with
+	 * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+	 * the per-page bitmaps variable size.  We just legislate that the size is
+	 * this:
+	 */
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
@@ -78,8 +86,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -90,7 +98,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

#199Tomas Vondra
tomas@vondra.me
In reply to: Andres Freund (#196)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/14/25 18:14, Andres Freund wrote:

Hi,

On 2025-02-14 10:04:41 +0100, Jakub Wartak wrote:

Is there any reason we couldn't have new pg_test_iorates (similiar to
other pg_test_* proggies), that would literally do this and calibrate
best e_io_c during initdb and put the result into postgresql.auto.conf
(pg_test_iorates --adjust-auto-conf) , that way we would avoid user
questions on how to come with optimal value?

Unfortunately I think this is a lot easier said than done:

- The optimal depth depends a lot on your IO patterns, there's a lot of things
between fully sequential and fully random.

You'd really need to test different IO sizes and different patterns. The
test matrix for that gets pretty big.

- The performance characteristics of storage heavily changes over time.

This is particularly true in cloud environments, where disk/VM combinations
will be "burstable", allowing higher throughput for a while, but then not
anymore. Measureing during either of those states will not be great for the
other state.

- e_io_c is per-query-node, but impacts the whole system. If you set
e_io_c=1000 on a disk with a metered IOPS of say 1k/s you might get a
slightly higher throughput for a bitmap heap scan, but also your commit
latency in concurrent will go through the roof, because your fdatasync()
will be behind a queue of 1k reads that all are throttled.

All of this is true, ofc, but maybe it's better to have a tool providing
at least some advice? I'd imagine pg_test_fsync is affected by many of
those issues too (considering both are about I/O).

I'd definitely not want initdb to do this automatically, though. Getting
good numbers is fairly expensive (in time and I/O), can be flaky, etc.

But maybe having a tool that gives you a bunch of numbers, as input for
manual tuning, would be good enough?

As you say, it's not just about the hardware (and how that changes over
time because of "burst" credits etc.), but also about the workload.
Would it be possible to track something, and adjust this dynamically
over time? And then adjust the prefetch distance in some adaptive way?

Perhaps it's a bit naive, but say we know what % of requests is handled
from cache, how long it took, etc. We opportunistically increase the
prefetch distance, and check the cache hit ratio after a while. Did it
help (% increased, consumed less time), maybe try another step. If not,
maybe try prefetching less?

regards

--
Tomas Vondra

#200Tomas Vondra
tomas@vondra.me
In reply to: Melanie Plageman (#198)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/14/25 18:31, Melanie Plageman wrote:

io_combine_limit 1, effective_io_concurrency 16, read ahead kb 16

On Fri, Feb 14, 2025 at 12:18 PM Tomas Vondra <tomas@vondra.me> wrote:

Based on off-list discussion with Melanie, I ran a modified version of
the benchmark, with these changes:

Thanks! It looks like the worst offender is io_combine_limit 1 (128
kB), effective_io_concurrency 16, read_ahead_kb 16. This is a
combination that people shouldn't run in practice I think -- an
io_combine_limit larger than read ahead.

But we do still see regressions with io_combine_limit 1,
effective_io_concurrency 16 at other read_ahead_kb values. Therefore
I'd be interested to see that subset (ioc 1, eic 16, diff read ahead
values) with the attached patch.

FWIW this does not change anything in the detection of sequential access
patterns, discussed nearby, because the benchmarks started before Andres
looked into that. If needed, I can easily rerun these tests, I just need
a patch to apply.

Attached a patch that has all the commits squashed + removes
sequential detection.

OK, it's running.

I didn't limit the benchmarks any further, it seems useful to have
"full" comparison with the last run. I expect to have the results in ~48
hours, i.e. by Monday.

regards

--
Tomas Vondra

#201Andres Freund
andres@anarazel.de
In reply to: Tomas Vondra (#199)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-02-14 18:36:37 +0100, Tomas Vondra wrote:

All of this is true, ofc, but maybe it's better to have a tool providing
at least some advice

I agree, a tool like that would be useful!

One difficulty is that the relevant parameter space is really large, making it
hard to keep the runtime in a reasonable range...

? I'd imagine pg_test_fsync is affected by many of
those issues too (considering both are about I/O).

I think pg_test_fsync is a bit less affected, because it doens't have a high
queue depth, so it doesn't reach limits quite as quickly as something doing
higher queue depth IO.

Orthogonal aside: pg_test_fsync's numbers are not particularly helpful:

- It e.g. tests O_SYNC, O_DSYNC with O_DIRECT, while testing fsync/fdatasync
with buffered IO. But all the sync methods apply for both buffered and
direct IO. And of course it'd be helpful to note what's being used, since
postgres can do either...

- Only tests O_SYNC, not O_DSYNC with larger write sizes, even though that
information is a lot more relevant for O_DSYNC (since O_SYNC is useless)

- Only tests write sizes of up to 16kB, even though larger writes are
extremely common and performance critical...

There's more, but it's already a long enough aside.

I'd definitely not want initdb to do this automatically, though. Getting
good numbers is fairly expensive (in time and I/O), can be flaky, etc.

Yea.

But maybe having a tool that gives you a bunch of numbers, as input for
manual tuning, would be good enough?

I think it'd be useful. I'd perhaps make it an SQL callable tool though, so
it can be run in cloud environments.

As you say, it's not just about the hardware (and how that changes over
time because of "burst" credits etc.), but also about the workload.
Would it be possible to track something, and adjust this dynamically
over time? And then adjust the prefetch distance in some adaptive way?

Yes, I do think so! It's not trivial, but I think we eventually do want it.

Melanie has worked on this a fair bit, fwiw.

My current thinking is that we'd want something very roughly like TCP
BBR. Basically, it predicts the currently available bandwidth not just via
lost packets - the traditional approach - but also by building a continually
updated model of "bytes in flight" and latency and uses that to predict what
the achievable bandwidth is.

There are two snags on the way there:

1) Timestamps aren't cheap, so we probably can't do this for every IO.

Modern NICs can associate timestamps with packets on a hardware level, we
don't have that luxury.

2) It's not always easy to know an accurate completion timestamp.

E.g. if a backend fired off a bunch of reads via io_uring and then is busy
doing CPU bound work, we don't know how long ago the requests already
completed.

We probably can approximate that though. Or we could use a background
process or timer interrupt to add a timestamp to IOs.

Perhaps it's a bit naive, but say we know what % of requests is handled
from cache, how long it took, etc. We opportunistically increase the
prefetch distance, and check the cache hit ratio after a while. Did it
help (% increased, consumed less time), maybe try another step. If not,
maybe try prefetching less?

I don't immediately understand how you can use cache hit ratio here? We only
will read data if it was a cache miss, after all? And we keep buffers pinned,
so they can't be thrown out.

Greetings,

Andres Freund

#202Andres Freund
andres@anarazel.de
In reply to: Tomas Vondra (#197)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-02-14 18:18:47 +0100, Tomas Vondra wrote:

FWIW this does not change anything in the detection of sequential access
patterns, discussed nearby, because the benchmarks started before Andres
looked into that. If needed, I can easily rerun these tests, I just need
a patch to apply.

But if there really is some sort of issue, it'd make sense why it's much
worse on the older SATA SSDs, while NVMe devices perform somewhat
better. Because AFAICS the NVMe devices are better at handling random
I/O with shorter queues.

I think the results are complicated because there are two counteracting
factors influencing performance:

1) read stream doing larger reads -> considerably faster
2) read stream not doing prefetching -> more IO stalls

1) will be a a bigger boon on disks where you're not bottlenecked as much by
interface limits. Whereas SATA is limited to ~500MB/s, NVMe started out at
3GB/s. So this gain will matter more on NVMes.

At least on my machine 2) is what causes CPU idle states to kick in, which is
what causes a good bit of the slowdown. How expensive the idle states are,
how quickly they kick in, etc seems to depend a lot on CPU model, bios
settings and "platform settings" (mainboard manufacturer settings).

The worse a disk is at random IO, the longer the stalls are (adding time), the
deeper idle state can be reached (further increasing latency). I.e. SATA will
be worse.

It might be interesting to run the benchmark with cpu idle stats disabled, at
least on the subset of cores you run the test on. E.g.
cpupower -c 13 idle-set -D1
will disable idle states that have a transition time worse than 1us for core
13.

Sometimes disabling idle states for all cores will have deliterious effects,
due to reducing the thermal budget for turbo boost. E.g. on my older
workstation a core can boost to 3.4GHz if the whole system is at -E and only
3GHz at -D0.

Instead of disabling idle states, you could also just monitor them (cpupower
monitor <benchmark> or turbostat --quiet <benchmark>).

Greetings,

Andres Freund

#203Tomas Vondra
tomas@vondra.me
In reply to: Tomas Vondra (#200)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/14/25 18:50, Tomas Vondra wrote:

On 2/14/25 18:31, Melanie Plageman wrote:

io_combine_limit 1, effective_io_concurrency 16, read ahead kb 16

On Fri, Feb 14, 2025 at 12:18 PM Tomas Vondra <tomas@vondra.me> wrote:

Based on off-list discussion with Melanie, I ran a modified version of
the benchmark, with these changes:

Thanks! It looks like the worst offender is io_combine_limit 1 (128
kB), effective_io_concurrency 16, read_ahead_kb 16. This is a
combination that people shouldn't run in practice I think -- an
io_combine_limit larger than read ahead.

But we do still see regressions with io_combine_limit 1,
effective_io_concurrency 16 at other read_ahead_kb values. Therefore
I'd be interested to see that subset (ioc 1, eic 16, diff read ahead
values) with the attached patch.

FWIW this does not change anything in the detection of sequential access
patterns, discussed nearby, because the benchmarks started before Andres
looked into that. If needed, I can easily rerun these tests, I just need
a patch to apply.

Attached a patch that has all the commits squashed + removes
sequential detection.

OK, it's running.

I didn't limit the benchmarks any further, it seems useful to have
"full" comparison with the last run. I expect to have the results in ~48
hours, i.e. by Monday.

OK, I've uploaded the results to the github repository as usual

https://github.com/tvondra/bitmapscan-tests/tree/main/20250214-184807

and I've generated the same PDF reports, with the colored comparison.

If you compare the pivot tables (I opened the "same" PDF from the two
runs and flip between them using alt-tab, which makes the interesting
regions easy to spot), the change is very clear.

Disabling the sequential detection greatly reduces the scope of
regressions. That looks pretty great, IMO.

It also seems to lose some speedups, especially with io_combine_limit=1
and eic=1. I'm not sure why, if that's expected, etc.

There still remain areas of regression, but most of them are for cases
that'd use index scan (tiny fraction of rows scanned), or with
read-ahead=4096 (and not for the lower settings).

The read-ahead dependence is actually somewhat interesting, because I
realized the RAID array has this set to 8192 by default, i.e. even
higher than 4096 where it regresses. I suppose mdadm does that, or
something, I don't know how the default is calculated. But I assume it
depends on the number of devices, so larger arrays might have even
higher read-ahead values.

I'm running the benchmarks with ra=8192, shouldn't take more than a
couple hours.

regards

--
Tomas Vondra

Attachments:

results.pdfapplication/pdf; name=results.pdfDownload
%PDF-1.4
%��������
2 0 obj
<</Length 3 0 R/Filter/FlateDecode>>
stream
x���M�#���	����u/��M���@J��w5s�Yz�]������������#��N ;�O�QF3�#�<��q�������z���Cw���.s������-�����?����_~����?~�������������������:v�4��S���������~M��,���_�?��������O���[?�s����s��~���o����u����������������?g���D�����%g�?n�t������;������+���eY�V�6v���k�u�t�Z_����0l�m�_���~���U|����j����O�q�,����k���e��i/�k�</�������[���0n�1w�x��?��_����k�����_�?^�.��2
$lx
��a]�����%a�������/���������v�����������m+q��������u�.�m~I�c
7a�K��#[m*����/�|����o���kw��5}�n�x[��~^�)���	�n����e�e�5_r��~�l�Z��
����GY�����p��q��s0��?�'%����"��`� �rX���Z��"��~x�c��^{l�}�������w��eG�Y��W�����
�z4>��������no}ws�o�#s�la�}7�e[o��m+U
�]�q:a�0���){}?K���f*e��?�����8�����Ys;C���a�G�2��-v�#aG�x?F��Uo�nd���Hg�q�������Kw�.	�����O>?i:����m����m����`r$���e_��p�C�p2��������B�8QK�k����_����q�0����U&�����������W����i}j����#M�pNoia�,�8���8�����w��'���6	2�0�e�o�bk}=�$�Z�����
�h� lz_���?.����&i��V^��v_��n����Hy�
�����.����V��M>��B-����
��M����~/��r>X&	+^��2I�:�@��$a��^h�kv�L��0HT��������$�C�����I���^��*��d��3���b���#�Z��}���:�&�z7���y�]���'������`�Z��7��h���uS9�ra�Z���n�dQZ���
��'����A@����M�G��~��@��I�����~t��9�
�}h�$k|�r�won:l`�(	������������5�_?n��qff�h�������Fm��V��0S�����B�o��B�U�
�����l���4D�����a��C�j�B�r����Wu�B�Rk�Q��
'L���U�&�~�'%���
���98�i���=t|����n� kz����8
����G���i�N��tl��w�C`&l��|?!|��M�&M�s:���S7����Sq^��r�s�����n����x�C�����q�p{��H��~~���1n}$ly�]��67���
�#a��e��r���n}$lz_���|9�B��H���/��q37��e�vwK|����k����\�$����v��.���z��v��C�/��:�;�oPq�f��w� ���!/���������
p���]?�x
��������u��G���<�Q��H�����;��]��O��
���c�M�fC!�C �M���ks<��qP3>�����4u�M�9)0x�����(#
{�q���!��d]�-�x;���}l��d����#����������O�������n��������u�u���6*|��$��
t��wKY��������$	���<�����p�z��Q��O_d@�*.*�H��E^�i��7C�o�8 Q��=__�v�a�����P,��(��tp��7��Fv���uw���.s��%�=���o6o(}8=�
�����9t�,�KG[�'L��}z�Da��(���!a��%��_O�Q���vx���la� ���[,��&����N~�e1,�m�[Y�ZX�!�^��V�e
?���s���,�N���=����PX����X��>���[�_������[3����lYy�������7t=j�t.���~g�
d}��M��C��{<��=�`{�e1�m�=R���6�Z�����tH�
+dcx�{��j�m��W��/�vZ�L�
��6	���I
����WI�>M'Y�C��|�=���3�I����x��d��39w��E��4�G��;&���3N$(t9z	��[�� A�����.�o�q�C����C���av��9|���0>2�O��}����r ��/�kv�B��I�����#yva$Y�6/��0!��|_����a��
o��s�]���sps�	<��q�079����Oc��TH39����g!�d!�ar�����#4�t�������}L�l������r:U,��$�G:�����|�!Y�
��5Tj����d��S�1~��'���b�@��_������E}���u}Z���e��m��A�#	������������x����)�vt>�i:��Q�{��{<	_g��%.�u���<jf&���Ow ,�����tj/v,��`a\�<:��������(�GU�!����	C�m;H;d�����vQ��C��p�>�0I6NY�I�(������Z���������_�2�T�J�Ua���6a��O�������w�e��u���AX�i:��:���$�f��	������m��|��������������N_������?�g�������0;T��!���y������������h�E���/������K���4�O�kY^����]��"��%�� ���O�V���m����g������7f6�7�,l����f�Z�o���2v�
���F
$���w���m�!+'����j4!��������YY@�\-l�[	+�B��WU�H-u���r����z���w���o����MD�������0'�����w,�<F���h��c���d����H�j���T� �v�n�?�7<?�HX1!~7/����E���
a� lz_������n�4�b�s�FV����7�t��r�O�����cR����m�T�-�d�_u�"���3����'����������|������pb�z����v�������~�y��wv�Y��
+���A��!G)��/h��!	��I�X�*�/�k�"j��!'�m�+c�B��1���O�����g��	���E5�7]���
��MK�.)����W��V�I�>�AY�fL��U?y��<28�<>n�����O�#���%\f�hd���Lcw�e��gts(��N��8���l7YV���m����uA5���������4�7�S�M���n� ����J��3d��4�i6��*	#�C=��*	��w�����X��*	#��S������_�1}�m�,������=t���'<����'c�NS�}�A������jQ���fz`�3� V�e�����j}X���X�����*������}n����������CU�������OT��S��M�����x�>qk%a��7W-,y	#�+�����W��N/��������v;ao���������&������CVvO�Adr��I����[$i��O6Tb�\���/:[�rDJ	�E:����NV%��m�}�jM����a� k}��Y�C�����jY��m����Ln�����WaS7S-�^��VJ�e��c-�)���5"a���������VJ�>rV�C+E5��n�e��L��?�q��i	���J�O#�$�J��*��4%a�8Q�*c{*�Y}
C%5k$�a�_����v���k3�D��"����"A����"QX�� Q����e���
����U��<���<��6�DY�B/�����GOc�(��d6�E�3����0d�Z������������PZtV�l�g9��f�e�M�&v|�M���u%�I��=���"�n� �S'���2$����rFO�,+���%5����di3�������JX�y^�n�*:M��&)|�������x�'�	�Y�F�H������n��������%An��c���H:~nJL�p�������>AX�.J3;��TW���K����n�(�������=%}�f����[%w�+�,������C�4u�AB��?���}J(��>t�Q����3;��GC=��pC�-����C���u�#������:u�F5c�������On3��=��S��0>��z�#a���5�:ib�A�������x���h��%|�������n��n�7�C&��&M��Xg6xw���������p+�f�@�fv������QK�<���	�b	�_�YM7�3���A�Y����D1����W���-�X�$?L�����0a�$������wk&��0Lv�E�d����r�9��f����|<�D|�����>���JY����e��^���^� ���m��U��&Q��>�6I�>$GY�&�a�,�3� �!�xfZ��	lSg+�m*V�4�,x=9}GY5��.���`�y��uC��3ZI�u�7YU�.��Q�h^�0D���#���|��5��u�����6�%|��nt$����VG�>lX�J��M�r~�DY������,�}�?E}n��������HIX�~�
��D������Q����J���`A����?��utn�RD��f�u�L����Aa��Cae�H�NV���I�(u��4���j�;�������I����x��$a��+7T6�m�Kw>�8�Aa�:D$�����,[m5rs�IsX�4���(�����`AX��z7X���@����%X���x�q���p���OVV
�V
��o�1�VJ����a� l|���x:�C*+��Ca��e|z��k��J:�6��>
���=��&��o�fI���}G���e�M�d-��Y?N��P	��)�k�t�]��R������An����b�?��f�ZT�V:��	k^=��R{D��A/��<Ve��M�}�������;���@���M�i��b-nY���Yg�6J��,��%���������=��j'��'�1���b�m�dU���p���XJ�4�Jl��n���4LS
�mO��0)�R�g&L
�)�v���:����M
�Q��c
����1�D@���n����<�
Ga�zZXv`�E�t���X�	��	��>5L�u����t����O?��Fa���h���5������]u-����	�t+�8����G�.�����Xb�G�(�s��Z~��C�>f������_��"��e��F�q��O�\xf����0�j�
�NIX��1��
G�#UA*�f���
��I��D=�����
�NAX���S�4�Da<�.�q��bKO7N�M����LEU�&n�<�C��{�i�:5��ep�M�4�8M	�?����R�O_Qp���cY�'YX��r�M�aO��#b��9�X�a��Z��[7�_����� �z@j	a[�#����z(�s5�=,
�}H0�-�!0w<z��p:�������5w�+����$��n3R�!B��T?b)���x|�8��}������/Fa�C�u��A�r(�>��}����P��@��L�����R�nr�_�,�:V���������@�A��Ud���N�*����iYU��0:-�L�6{X�t�[�n���b�	at����N�A�/mnl$�Sw6�
@=���s�[y<�/�nf_��W"������W1�0))���]L���af���wd����@��of����#�.��S}���v�5���-��An[�����G9EK-l�a�����nf$�������iv�e�� �_�M�X�[���r7#���4��[o_$��[!	���L���?l��ql�����`�
�d��k�n�0�r7�0N���<tx?&��u�j���^�/�<��j	_������!M��*��e�������I�~$9qgI�(����,�����\���y_����D�g,��g
v�s*�:	�8x��e^A*��a6>
[�G��uCe��l��2tg��?���������n����pd
�~�v��g3#�foG�|�����l*V�4����;����1�-k^�����	���y�&��������#Y��E#�*n�4�b6u�%����u�,M��R�y_���n@�>%���U��ZQ�bd)����O�^if��a��f�d���������U�����r�o��:��:i�'������������579���)�,�CmV�7���Us����n\�Xe����2~N�Cae�C#a�%	�aY���D���>5
{���,meUy0��v�w�w	{a}R�1��>V�
������O{'3��IX��{��/�<����m�����]��0P��'eF��3�U�������z$�jOSpf�/ ��i;;�������>fg8�O�w^����&�>Ff�Y���%a��6l�����Y���6K��>�n����6+e�~6��
�g��'��q(�uC#a���

�}jh$��<��'����0��>�?�����D33-���7L�����OGD��z��n� ����Ka�S=��M����l��&�<����}�Z�����n�`E�w�n�o�'{%hp���Ij	�Ni�/�I�>��Fa��7HT�=���q���H�>%�`%��wf�d?����u�K-�PX��<�����9�����$a�	�%���8$�G��!A�,������Z~�����r�v����V�)#��g@��M$v;%5?�SV�����O��'j����PI��eZ���r���*e
�~�����t[���~�6c�	>o������n��jy�g3��Y}�c��Y$
+���E��j;'�HV�����SX����W��a�R�ta� �?�d��M�}z^��O;M��r`X'�����jV;
�u~���?]��
Ih�$����NI���O�i�r6�_��"�2�������0c���iv��i�qN�2�81������A���z�]�R	��O��(�s+a�����q����[a������+��8<(��+%	���I��Uq�$a��CYeB�H���m�Z����,��XY������29����+���}����Sk��l����r��>)*a��MNJ����^���������^S</����HA~�y<f���V�=~J+�{_���t�P��@���"(��@8ky��<�����f�P��e��b�"��C����xZ�Bv((�����������I�[��������|���c���!mV���u+�����������e�K|�(l~d���)���Kf-?�SV����Cz�;%5?�5����������������T�)!a���a�$�c���AV��I�[!�*^M�Y�o�CI�A�W5�9�t���O�'�^A���X<�b�l7X�i��M��/t����}�Q�U�U��hn����<B����]�P~�/�n�ZB�P�&�����e}X$��>~>��}���m`�6Q7h�r��3��z6�A^��R���4��y�d}|Xf��l�0C����o�
�k�n�����fH�U?17C�����<tP�,�aoJ�!��b��=��M�*7�sc�t^fX������U��5T�r��b>C'sI���i���+nM�?-�7�7o��� 	���
�K������n��[�FF�����n�������G��0���"?��~�Q�������V�����ED��c���jb�5�az0��~0�������i7=��C��H���uE����n���k1l���e
?����:az4�*�Z�	+w�u�c�9�zQ�b��������j����B�B��{���
���3������'�>+5����������s�jv��������n���nw +{�sc��
�4E;P����-(�'�k�p@���d����:e�nr ,����*2���Y��j�X�w9��V�$��K��ar0��c�����?{]pC���+�"M���5��U�6�"���'�q2��17H�j�O�X$�]��4�C�)RS��7t����J����0.)���������`�+��@T5x��)Y��3Y���nf���=������ �B!����r��I��7�1��w�	e_?��d���9�����[#��R��5��*�U�#	���3S�Q�0���U��������X��I���\a� ����)���;�����da� l|??�<�Y�$�� ��'iw���7x�n�:����=���E��S3>�Pggq�Ca��'�#�{vD��r��Y
;���Gs�CQ�{n���y:-6a%��GG��T3d��z�A��b��n����e(�������j�D�+��L��
��������C���-�w��X6�c��2e:}$f5��q���M������JY�R���:�Ufe��t�S)k�>���*|?���J����5Za} ����������dzw�v�#%�'��w���=R�}�~0r��G������]�n��z�w�#	?������}��7"�w�#a����N@�-��}�%�
�w�;
^�����cx����eU#3=��i	�x�I'��� QX��bA��7KvyW�d� ���(l8g�����u�������n�RV1�f\����B����a�V7S6�0H'a��+��LIX��"��d}���c��kX)	+w:4+���V:��=�b��o�1B�a��eI�va�W� ����A-���������Eq�Cx��L�������p�u��6�p#���_?l~<��a������.���Y��z���1�d�����-���J���yTa��A���B��Zgu��r�.�W�������8O�&�3�{���u�?J�O/�<���t~��t���i"���	�o�x�U;Pp������d����]�>����n�Ye&�#�n{(�p�8��n{<�Cp�=)���"��n{8�����c�
�:������	�[���r��YgS.w���]���a�'�O~>q?�0>�N��w;$a���a������#��v��>�C��<�C���Aa���!���?�L��|������B?����8),K����T���8V}��-�u�2��8����'����w$V�C�^��vQ����&9_�e����n�ZX���b{�.�o���I��j��[$�S������}X�J~j��e�F��41���<w�	��� �%�������PJ��� ��]��4�t��d���2��@F5��[M��<<~��pL�>���_�QR_4�%��a���i&�����z���>��sr���a� �P�{��:�$�-���n�nB���W�:�
CQ��7���}gEn�,����Q����g�����E��j��$�����E������H�V��[$�*�j�E��@���
$|��	��M�,�	�.�Qs���(����dU	A�DI�,�&J:���O`pe�:�0i��0�����[�m�Uc�n�$���)L�d]��;?�GOVH��6�J�������\H\D%��~���Ee�)a�S7��fFJ�>M�!a�~��EQ��Y
[���h���{9�[���������B>
;Rd��9��*���gj����p��^��s�:��y�L6��I��8������n�(�C�V�X����0���
��_���0N�i
;�=���$�L<v
�����SV��
;a��;��}���e�����&�������QX��
3-~t~���6M�S�FYE����X5��	����Banm�e����;���]�t��Gq�D�_n�,a����;-�7��wG�}wLz?�n�o�,�pw�rR�`����1��v�,�^��[-��M���rd	x���
n��Q�e
�ap(hhv�C	�L*�M����U�N��Tr:����xI%J�C������������~S���T3��v�z���j=������aN�M���'�4V���pc�������R,�6#K4y�d.�O��X�����1Y*Llz��}�	���&����Os P�r���M���V�
��u*>A���=$�Q�Ct�r��V�Ft`e;���^o�E&r�M����e�q3��T���IX�3�T�I�n�$����2���u���q��������/����w���W��2)��z�l�������PX��f78��{<���|�"����'�C�n� �s�aU�0S�U�e3�a����a�,��0N)����0NV
���	�����m�-w�a�0r�����]<8�6I�b.z���t��O�:����jx�-�}XN���w��Q2p��bQX�J�e��e�����(+cK6�ds:��i������������ YB�h�I�7�0=)���v7=����j�k��fS}����T��K,5��q{X��������
��[�����
q:�[�$	�>5�A��O
�<tS��c�&	��tx�;^�6Q�"|�q~o
a�s7~���|���L��0G=���C�>����)>?��e��oz�p;�ob��n�ZO�_����������o�'C�U�L������Nf��"�0�!�9���cka�����$��w�HjV�v��d������]Ghl��r��/VMgt�$a�6�n�(�X����z^������F��_��$�����e��C��;a�$��d������(���N�W��K$5?�ca���0D)��48��t������H�����a�����������A�����&	��C����j�N������
}�IT1t����
��Cu�k��QB��	$�[�
����!l�Gu����;��!�{��
a���0ET����X;H��Y��0]���E����6�$;��2��H��6Fcda5��0F�����o-����t�QX�t�
�U�S����9w�����+��%���f(%��w3aG��C	����u������3$�=^��hVM>��u;<���j��l>,��W���tX����0G=�C�����?�Q���X��Hj�V�"(Vl���E�#�a���a��5�n��t���oP���n��	�����%�h�|8��oa�$L����8e�i~��@T�P�������HF��u�c���X�)�d������]��i��C)l��3S�X�v�)Sa������:U��$I�wa����a� �p[(�:�����x���1�;����v��_*�aY��m��S$0�$Y%_3�$Ae����0IX5��v�*�<*�5n����������/��[��3$�!���a� �P����;9�n� ��v��I��
j�c|/l����p�@���I��1$���� ��X����<!-�O��z��>V
�����*�zX	�q��=�=W����e�:���g�������Y^N������]���{g�����m��j~�n�$�xd�m���}��{���6����q��R�y�M�5����C�[$���w����"�����-������#P��0$������=6�	3��}Z)������>�7���a^�0��-�z�I������vF�M��fP,�3{"Y��	]���+�W��ssBYU�l�;��]���������>,
���,���n�ZT1�4�&U�{t3%��K�V�EMo8~h)?=T�Q���9(����GxVy%%e+f��k7�,���U�����i��,�@5�$Y��3��y���6Y�g�'�����(���T�V�s7��q��f��y��y�y��O�d��y�8���o��I*�u���Z��tG3�\o��������e
?o�����&Ye\�!�6�>K�d���������js��#e�Y������������[����8�F����B�R-�sRx�%i����^���
��S��*�=���Z��{�t0����u��j�u��
�	�anr8������@V�R?�
�:��OGss�u=4�:M�%e�����p2y��H����n#�J����T��% �dVF����ff<��=���?��,[�X�f��Y���W�YY�K�M,S��Gs;�����������I�1��x�������*�0.P����l9u1����
�����b���&G^����E31��zD���-iu�;�(������L��LN�UAP�9�Yiw�3=������y�r����]��j���X�v��IaV�_j��mL��:8�?��)�nX ��&$���?r��b���h^����2�Q����7�]��WH�O*���ni,>7D)�s��E���h�"��fe�!���!��p�5r$I�����2Q��k�:S'��'����=�T������J���:&��.�������U,�[�������8&���_�.����
Jx��
�>|l#Q��n��b�e�-d}���:��a����/��c5��,U��-UfZ���6�-Q����zcUna�Gz��q��N��������2�a�yU=m��P�C�c
�In>����������c��������W���5����x�t�n��������k��u��_����_��/j�uY�x��_�������6n��
�p�e�G��a�W�����?\�a��qc�V��M2������5���?��sY^8�oS�?�3_�B���}'�_��i�~j3����y��K��C����/��h%/��[��m���7-�`�qK������^���8�_�����������m]������o��(���
��_�F���}���6������n����?$�^�q�����c�L�m�m��_�O�������-%��\6�}g�qn��8�K2��t�e}g�qs?t�u|�I�]����m�����p�ryf�ml�_o�s�,�����d��[n����1p�u���rt���m��!��e~]����?d���[o��8��>������w�>�����e\�������d�|�v���@���|y�R��q�����{hIN���b�
����N����a��%��q��u|W���
�n��w���k����'jH~�:����b��?���������n|�3�K7M�������~M�t������a������u��e��K��a��a������?�����n����������I	���Y�yX��WG�~]��{?�����n���c�������?����>-W-��_�������a�����G�����>��%����'s|��6���Z�q���
���,�:L=�1d���t_07��o��B�e�}3���9������l�|3�R^��7���w�M��.��������C��f	o����e����������b7-�?�����b�<n�+�2�E}��z������w�___���V���[��Vc��������x�Z��J!e�?��'~.dTF�'��uy6�����!��';N�{,��xy�/`/�����^_�����-�4~������d�q��{�����/��h�qZ:�u�.�;]�����Z��';�|�������[��VvG�O'{�u~&j�++�gL6P����^�eZ �������dw��p���4���}E�/O.C����/������W2�q������h/$�_v�W���'�{��T^uT�uK�\�U��a�n�n��y���8�����&><��&c�h��V����/����8��ubx/]�������M�*3�/e��V��
8�v�������!e�E]�^y�S|E�e��\��}G`�m_�q��1��dz�&�~[�i����(\�e������������s��y�%�X���6�|X�����`3i;}
�Vfq���iI��2<G�Y������q�Dh#�_A��6�&`���8������g��6t��:�nL�2^��e�h=������\����P9�z�V�6�q\��K?tl�c���a�fP{�i�xy%Q}9�����[<���TH��{�x���z2���Lt�__��� c;�_�����`�����)<�y����,��Q	���2�$$�Q)���>��L�8AHj�^>$��Vu���I�m�%�>&F� �
|L6�>�ZH�#Z������(D,fc�^��G���^��G�������W��z�M�Y���(b�5����9oI`�q�z���\�y���8�S ��&)��
@�m�w��� H��p��R~6z� ���{��X5�������g;B�cvt���"�2uu���QL�����`�t��H�d;?��A����k�xy=��m�w=�@F��gSD���&�G{}2JM��2�}��11/:�wd�m�5� ��v�^�W4��e���JL�����[��v__���B������(T�i[Q}�����^��{s����@
�ZH�
�y8�3�vU_���08�]����{����o�L:�o�8�y�����Q���(��4\p=����������t����<���^�-v%#���B�v~6EBJ��a����j$���x>�u[����"��/��c[
��������:��F��gA�0d�Z4�s�#�������S��vQIQ��6���x8u��6c3�~\t�=�sO�,�KJ����&���C���18(�������P���.l��MEB��-�2�W��T$N�m����a�����[���r	+1T��T�A���8#s�;:�9����o����X����bka����r=I���^;��}9b�(_�L�|B����-��s,���vZn@����f3����?,ju�v�j�@Vg����S��y;zz&��J�-���pt�.o������@C�M���_x������EGDP�a����u7Q~r��]�U%�E��h����@F�No1Tm$;6��nky�������l>o�]`!����!���)J�s���b�w_@J=����&(��h)���\�����xh &|9f�i�/j�#!��k7-�������K7��$1�y-Ia\�1�J��n7�oJ��&�xO�����l�0O��7/�rRi�l�y�r.��]^^�����/#���*�����[z-�<���y��>m��T@i����ed},�	���t�z!u����\�D��������,���B����lm�k�C�Z��?t�2�rE�Q^�B����k���P��)+�Lq���(�J����jJ���~��j,�(:�jK,������l
*�
��@�������4��|��g�FH�p�SI�������r�����)a"�����<�E;|j�6~h��'��a�����R�]rf������>���%V�����fA��0�(�Q�p]!z�P����i�K���h����2��������
B&��*D�M��J!��P!dm�����Z�qjB^�R��D� ���eE�^,����O�
���|W:Is��{W�@��]�@��U��z�:�����*���~{~��-�e�OJ6u�TR�lD�c����bi���S:|����e�.a)~�BV]2B=���V��Tza�.
1��������$�)5�6x�'Uy#pTk����N(	%���Sy (l��LO�#(�������Z��_��c:-b��x����P5�u[N�B�-���*%K*�!C90T���n�+E�C�L
q\��JJ��m�XqU�� W�0T��uU�.a����C�~s����z����V_:w���W��Ag]~�q\3�XS&8����b�-E��+H�\,��{�)�Y��&}�,�Ug����$��26G'�P�`���T+3�-*y[����!�b(ms���������Dfmr;�
!��D31U_�������E�L^�Rw��MC�j.w�Ab<8PT�I�����QT�$|s����\^�F�p�QsF���R1��rl!}H�|!}V~�F U�&�;�TX_:'�e��ROo�)+�\aE�?��YU��n�[�c��$gm�OOz!��9}C[�zU���U��g��[U�� �,�]Y��D8X�&[\R�!�WR��������"����IOX��l>	E�����+kUZ����H�U�������&�"!z�-��X[����S����@t��xq- m��YR%�RO8)	Q�a8e��_+��*\���7u8c1G(�X�0�6���VN����_�X��8������$�(�
�,�������n�(���T���t^�d����vXe�����EV�'��d�t[�E���6�3�%�92&��b�-�6�%{�cc�15ulTB���]Fw^ic��"���Q-�b�����j�Et��CG%��@-��=Y����zG�,�k�HRpX����v��������>�m+�}�/���S��*��������g/72�k%/��Zj]��@��h�z�W�c�������FO�9;<jE�������R�V0C�����)��*E��GN�������<`Qiq�<]����j���Sv�d?��Ld�*�s�e���p�����C�svH<�dt����S���?�O��d��()��A���y.��0������R��w��Kw�w��n����k�T�p)x+���+
Mg>����v0������������v,@��(dl��'
����)u�O���@���w ����)�=��{&�`rs�����T�i��8_R^��Xam3m(PI��B��^"=��b~#D�$���4u�PRy��iWUk2YP@�~'a���?��V2����{�������v�4`� �DJO�_w��#� �`��1���^2��w��q�n��6�|��M�Q�o���9��2|�������b6�el��d�vi6�D��7�>���R����r)p*u���q�N��b�T�8p������u���3�\J��
���Y�[4�eOLmK��
\8���$pju������<o��#8�:�y�/O5e�U3�-�Kg-��)�i���&I���z��_r8��x�>9p���w�8����>���lE��h�P����M9kB��M�
�&���@�>��t��8�aS}4w.��n+�4��x�P�)�2zo�s����J���d[R��������2�����Y0VoPo}U���+o�����������"���i[�=NK�%uF#;(De3c��Nij����e"�S�z/���4[�&����yz��)����57	��k�����S�c����i�LJ-N��%������,[=���O���������)/�,[m7�=���s|u�;���Sm�
3��v
!�M=[k���Tb��UYb��a�Rh���BHv��
mI���:vj��mU/n��RHs(����/��y&����A��J�5�3��x��d�[�g�'����)���g��d@����1�����S�M�b��M)e��kr�
��Z������P���_M����]p=�"2��_X�1A.t��7�Omz0m�O2�>��v9/5K�S]����z
!����>�\���g��>�ZX�����|�B��f��@��Th�����v�� W�����+K��Z���D�������\����?�
����:<W���/��H�Z��Tg�?��Zu;��������w�B��B�rH��W��Q��IP|qC�<
�Cz0$|���'�o|
k����O5�RT���}�������!3��sX�u:-H#�P1�e�7�$%��~���2Z�|�pH.���m����?z�������H
q���2W�fz��4.�6��I2����;3;y������\I�%!i�K�����s��Z�d��Tcb��2��
����J�j��s�fHY�����V�}(���I3�����7�L*4C|����/�;v�a����Vu�`���N���z0uYY�'*Z�B��7?	��]�6�h:K�>TX���%AMy��2��h�Y;a
y�^�"�o^�>2"�5�BMi���)K�V��nz5��Uk�Z_��yO�	��hE��^�q�^X��H�Q:���T	�NT��S�$�o��B����J�3��xR�^���S�����\����Bp7��Vc���V����i�sx����Y�A�A�~Z�(��F:Ysh�Oc9e ���R��f���v!I
�0��b���',	�����c��6���a�\TBZ)�H��&]�,����+�� Q���U>\��nL� t�z��BH���B��;�z���I��ITN��2-�J�N,(c�N���R�c�n:�<R������5�%�n5�:�9 R�h
�DD�O���m)7���\ix�s�����kC����#m����OaR�2��:L�=/������l�_��zV$����@�Z���L
[�+y����Yk�4)]������iI������� )Uiy�P� 	�������-V��{��-[��$�.�����w���I9 $icZ6h
�`ew���r'��<,>����2kS5oV�F�W���?t�(�V������P��+��d���Rj��B�K�	�|�/;`��
j�%�����P��
P*�������oT��u9+b����g��q%��\����	�m<�J��!�P�R��;+��V��q�a2�?�f����C&l�?(��)7������GA���i����S�4A�>�CGb��^V��������R�6���C����T���G%���N!�a���P	��3�\H�@�w�E �Jb����),h��W���X=8O-RcK���`��:v�=�	z;�W]`S�+7�\nK���Ua	r����=g�EJ����m|3����}�+t�m��<����	�����BPTg�<�,�H��0|K�M�Skct+�!r�6SBu���j��aCN��vK��������fA"�!'}t
~���S�3�
�r��8^-�4���i3y�������Z����N
E�ra+5-��&��~�������rl�NA*]�!�+V�!�� �����-�q�����9r������B��E
�=:�e�g���c$jf�<�B�h����9x�B�����V��M��<A�>��[Mi�y��i��5���'X�jm�4x��Tg{k�#I�g�N�$T+ThT�����l>#6Q��K�[��~���S
i���;|���fx-��S/��^����I���fV�\F���_�z@�]�kAs�!���������j���r�v���� T����b$	����7���1�J!��{���Z��y�ZV��iQ_���B�B�F�
:A�B�s
�����X��;y����>V
��]C���G%`�c(��#*TuZ�a()t7�U��c�V�iM�r^"��N��������CI�����*�#��\�C�:vM����	�R������yy�6
r�B�a����`bV0�%���J�Jq(�`B_�?��J!�|�v�T]h^����9���(*������(*��5z-�
�p����U��B���i��E�B�p��K��Q7h5� ��
��x�M��!`��(l�Q�O�(lP��%PTZ���u���[A�3Zg���$�V���o|Z���:�(�N�V��1�@Q��5��,��ze=��(�����4<M���+08g(�������
��:�Z�[�.��[9���)�
��2�G��uB�S�O�"���8]84�P�2��c�A���n�-9�P������vb���9������i�L)��jd�|j�=��x��:#t�v�B�F&wA���2�<I��c����5y�k�������fb$�iCO}"�?�������f<�����C����X��+��7���So7r�S�~5��u��>����{�C��
�e`s2��N	�F����trl~G���;~���Ok�V��5�.�i�T��
Q������>eJ���D�����Y��L�����	+�~?@]����D�J���AbeL\��2L�`�p@�Jo�-^�����-�[�s�}��T��U�����U1[+�P��qX
.��g]5���.���/
�+i�|�'�~��� ���I5k����v������Mg�Xj�u��{��0��)~/�0
0��xlO%��9Qi�1��������/k"a�@ "h��b���Fr��b��������������&��\m�7BI�����Fl�
)!�\��B�L1�\��J@�{��JBkN}t���&o��~d
#�a?!�BZ:Z���t���@��]a%�����p���������b�2G�/���)���w�`�!O�-$1�9k�u�[�n�`iP�����w	+2R�P	�[�h\�.!�c�*E�2!����O�2[)oFe��b���;��&� �J]��|9w3����2�0S�����J�3_�3���a-�l=�����uTTB��#&"'��P^�y��vf4�+Mh�v|t^�����C��O��L�`��SB����<M�����j�X`2���!��)�]������c�������%AFk!�s��qU��j�zz�t�fbu�Y��D��<���+S������k���e`M�&im�V�N`e�MO�}���:�?%�2�VX�+ac�>X�
�<��J���O�yno:�s=	�������H�*�m9�4��Zs%ax��T
'
�.����R=�P[��~��fp)W�RM;o��\���s��R��������2��Y��J'��(�n%����`�#v��(L���	q]`f�,$���Ii�0is��L53�f���h%!-�/���HJ��qn�^�r9/���&�D;�4���x<x�s��yX]xJ'B�^��R+b���
.���xax%���O\B��|�_�u���Qxr��\�.�����6�wq����rV{�uY�#gK���X�%X
��	�B�n[�4o�t�'�c;V*!�9S5�R��A9-��E�+�%�)�)���F'y ���hF��B�bKQ%�jk��=C�$3i��*��d"�R��T���@�;V�y<���]�'�������#��Q��*=J�X��D����e[�����;d��L�u���@�\��/���w�t��T{�K7�^����[���X�(���IMbM@�P�z����w��D�S
�V9Jbz����TrZU���tK�7��w5������n����Ajd��3��C�n��s���"����GkfZ%��=���,���4�5	��Z�(
1e�9K����H��ve�o�J[�W�=/me2x������V��u����'�F��bx)T������fl��,*@*������o��@:/]?|H�`@*�����}�,fn�_9�*Ef���! �T�����
���f�JV_��((d�� %�a4���]��6���&V�5,����Q��bo�:)�HXLc!�F�J�����\���5�[�8;t@��H!�N��t
FQ������a������6�p[
 ��l�&�l-�$�S�=z~9��T
'&�@Ry�������j��(�W��H��TN����n-$X*?���������j���+��r7�h���V;�#�k8�����o���=	^�HJ
E%\Ff�k4S3�@R�+v$E�������H�*M	����B��JNfA�H
si��O�S�B�`Rfz%�ap��Ma.k����w4E1�k\4(��JOcJK���wTC������w��M��V�D��
��Y��T�r!����@�/�	��������`Hc+	�g����a�������)G�R�*l��f���H�E5f�B
������(��z�KZ�jL��l��p�E�j�RgP/%5Zw�,X�XU+�zd���2w�$W�{�f�4���3��q0[�9k���s�HJ��/�QKF�:4��1}Y�31���F;�
���+~�N�B��bh��@}{��f��r��U�[p^����������%xR4��1(�R|��s-3�;�IE�.�R��6���==�=�Ft�����GZ`m`���h�������Zv��j8����</�h��)�	5z��2�3�&1�J(�	�C������"�����rs��pG@Rd+c����r?��q��D�U���%}58 P^��o�@i��t1���������	�	��L�P(��@$��&:��a>iG�2"��{=3���Ldl	�����2��z7��X�����)`Q+�d$�0+��Wx�	�����p
3]4ED���<z�w��|�������a�ST��E+r�p������mO�K�JH��;$DD�Sc�K0�y���'<��R�xH��IE*��zp$����5$Om��4O��YB���5�~��=RO���j0��B��m��A
}��0�C�2�b�P��up*Yr%�LF�\����A�:���8I�,j
�X�4�f�P��x�LT��;H�.s�<�SR������a�\H��XL���ee�S0)�y��\&�2y���W��X�����<�^��A�5�	�Jm��2�"�jx)�VM���R�
R�Yct3�R����m�P���*�n��R�TC[z�L*�e�����}N-�&�4&j�mPJ]Z����v����l]Y��C��L+�z���d���.�Rk�Tz"���
&��h�����-���������L��8�a��R~r�]C@��KPgLvg�K!d����^�
^,_LsC�x	�f�9^*]��9%`W��t�T�Q�K��k%�G�b/�����\���_&��K���~,�<���������v)^��A�A�(
/������{���BH�U.P����Y�,!8��Y�`a f�5H5���i�G�IK�,�"%T�KP������K��Q���634j�p��y������'�j&��G���\�:��
dJ�2����)[�]��Vg�7}�`��XZ<WZ�,���d���fB%���z%�T���f����Ry��n���3/8�z�!��C�r�*,�r��>�����yq]��j�����pS��6��� "��M!dm�v��<B���������
���^�N�4S!��d��)=�������X�Xw7A� �qS*3Yi|��D���S�+���k��N����)U��l�3�,z����\��r{[��;u�
���4���7���\�O�TW-���h�&���4�B��Z�������/�����(!���B�+�N9b�9G�����i���\S5�-1O��X����r�US��s�Jv�3�P��1&�A��MRi���c����71I�P%����J6q���n���Q�������L�vZi�X�i�aX����16oo�NH��J�b��4��Oh��)!�>����J��5zx�4{�&����	����T(�k�dYml��M>!SU�]����(}a)�*�)� J����7{ ���s�D��:~�z �����t��r��t���i,�F�yFA����!�&`T��f��%;��J�e������@�a4Z�*TF�FZ����|���DWW:��J�����L�J���L�`*���OAH�=@�3�xL0b�f�s�e�Vg5f
@�S8����ZB-�c�iB�R�D�G�ZR1�^�;�����F�H��k@
�^�r��L9m�;m����[���Q��s��C��@�MX����j���z�F�J!AOO���<^����O�����c�C���gk��.�*��8��f��
p��;k�GOku.��V�)=;�u��E?)F�Z��!�r����90�Z(|���k/��jAG��e��a5�!�U��"F����f�#�1l��HN":(MYp8t�\��r�Sc���r�(��Y�4�x
����.fz�p	qD�n���0m�����n���$��j���s$u�n�E��n�pv��(����=��*)"Y}�V��}��"�� ���RQ�>cF��T)�U�/D+�H�la���U{����=+Mve���;8�y,�T'��G1��Q3$����6�d��`�,�'�Q��X]�|�h���X�E��n�Hjp��<UP#/���y��\iV&S�����������QM��t��z��(�
��������N��|`{@K�����d�2�2
!w��{ �������i�3je<�	o���J�i��Yhc,�D�n���6'Z�R�#o0���Ff����3�2d&xB��D]ga]�G�����(�F�V��$����)@J��%�O�����gF�"��� ����F:�oIq�U�X�:+������>���"P:'��������b�\��iW0RM��<^��v9���2$���x� !��R�5�V� 
:D[��!�f������$!~�g9E�:�0HI�3��\X�"����w�T��<'��L�V$���fI��B�Q�.�.�zV�T�J-��$Lt�q�T��Z�;�����;�JX5�F�%�g[����R�V�EIDl�f��RG�/�;Z���T\�<���S	�8�j8R�:`��#�;`j��)��g�^�c�N_�$��O�=y"�������?�J=��(����1��^�.�2��J>.A��0W�T�%l�b�e�*��L��+�J�!��/A�)�����Y�6��3	������R���i��6>�
��@L!$���>�Z�`��];f���I��LTe��70S�m���W<L5�
S�<���zl!aH��0`~3��o��)��%\�kw9kt�%���3��>nk���������������b��@
�x��X3H|��$U<�_��^ju&;��u���1�2�/��{TB�K��%��:^�6�
�
>���G�T�Ki&�L��w�������i�<`k-9@��e��y��M�5EI�y@G���T��o�~�l�*�L� 2j!9�J���A)�>��$&����(��?�`~5�F-D�]���j�����`vr���y>tC��J,�Z��S��@-�����2?&}������BN��R��+��f��w�	[���:"k��t���������dL�����>!m��[
�rc����#Lm"��iQ������"L�Nk�v'^��L1�>�I�51\LRg�FC_���H���������)`����)�'n�L1���/5����)6�)��
f��T�LX�
f�o9��}��g�0�<�
 ����L!�o�J�+e��B����Q�xT�hm���S(������^��u�,�5�:s��j%�������i��h}f�x�:��9cV!a�����xAT5�S��n��y?���t��9Q�G�~�#���=�?���S��:8��9Q!/M���;�R�g������~*E���?�o37����,L����0@0T~T�9u�+XbBJ�����P5�B��r�N��"�@T��&�+|�����^��X�
t.e{�����������OB.GQ��U�#u��<�|���c���-Xs<I��4v~�;��X Oon����7&�O0���DS6�����8S�s��'k�=��i�)uy��A)I��j�D���N�d���N 'i�
�u��3��!6�-c�U�[!��Z���b��<VM�������Y1�B��j;\��e�_Lz�u��]b�e>)�\�aX���a.����������gq��$�m�.���%T���T��]gq�C,jl~���}��6���s��y�����'O��o^SL���B+b�1���*��0n���,�c.������krH��F�?�t?���h�F�f�q������Z^/,��i�%�KV���%y�9��z����Vlcw��L[XM����[�g7/Ye#dMX$��@R@�(�J�8x�����G�5�����~�X���B&N��J!�P������N���/k7�����Q��Z�J4�-�
2�_���0v�<�|N�|i�%K!��@���Sd��LYWqG�L$*6d�6�^|ySV�;2&�l>s�"EB�F��"#*�
3dT"{�� �##�(�6���j<2E�c���l���[F0����22������`i��(Ji�4����1#���������-7����
dzp�GSx��L���U��x>p�N��2X�����FGF���d�����aTx��"���b�F�J�u7
l�]�Z���dS�i�F�e������1�������L����x`#o$�GLZ��>gp�=
�Dw����T�u����t��<�2���P$�OX�%��x�]��rEk(	�+()�_CI��:=��@*��w���e"U�QR
�����-�^�m�kw��V���b�V�?��Zw��T2Fs6�>��p���|;��'�p�h�����Ww$u �#^pSe
��ReV�G
.I���>qI���iP��s��|��M�S�_q3uV����l-R��u��"�=:=|�3�V&�s��� S+�hB k!�Z�F����{k���&-F0����0��=,m�P�*?.zMu�T���o���g�7$������?a�����#p� )�n����G'��k����=��R�1�C����Tfv������8t�
&U�	����in0':\
	�`����g�K���m[�&=%�p�1�R��g�A3��KP��S$���7H��m�:��(��MaL�N��{�`���|�i��^�%����'�N�m�DHJF����M��u4���M��y4V��r�w�?\�of����h�;@��.������������1/����x��!=a�N����l����&��3����B���V<�S*d<���J�����Ikd���A�>�>�h�7RK��3N��-��K
����J��%rGQ��#�6GQ!d6go�����Uy%��H�
F�X��C�������
��,�,������J�Z^I�Q��%?��Z�C�X���1TYb����u%VK�c�L��������o9������X�
}�������K�O%��m}s�tg3�PRimw�CA�`{�$&�P�P0`P^�a((dl
#�qx�*i4�z��Z��t�L�@Q��a�\�Mj��:��J��%�J���h�[��(��L�w�Nx���2��k�,I	Y���x<t�Wd2:^M�k�UY�5x��^/*Q%���`wC�}��P5kG
B�$�!�l9�P�m
:�j���N�P=���s���iD��z:r{oY�����z.����Xm�y�����!��]?��C���c{*o�M!�'`S�a�+�:j�}Y�X�zx��q���;f�m1�)��L�N�B�-Yo����s���c/������Z���;m�ro����u����X��q#��)fr�� (Y�S@^d���j�+4�8��RvO��P��C���c���5��:P�5#�
�TcYA�x�[v��� y>v.�:�kw��N�����X�1��$	i��X#�0)�le~����0�����R�y��/�B�����q&)��C%�b�5��B�Vk4�R�
f�F�U�w�&���2�R{�$�r�2�k!�U��M�ow���Is��L�z�@��@N�17t���h��!4�S����E��j��Xyi_
�Z����L���4U?\*���X�*?�Ji�V���r��&�l	��-�I��'�_�\�K�?����QK��9���ex�����H
���m��rFx��g��xme/���<^��Q��a��z1�!{��^P���L���.�Q��
L�mi1T��V���q�,����*w�).D/	"�����!�>���i�W�f�Y��.����Lv��wY������������m��3�e����X,;	X�K`m�X+V*��.0&�n�|�� ��RY����Q����OHj�Lye��G2��"ysR�IKS�T�=eI3e�O
"A�CM�C$�2Q[l�H�e��M!2�2
�DJe���2D3�T"&��"�'���]�H��,��"�����N���"f�NN�����D�m ����0�B�����3���%$�:D���)W��h�S�����
�n<���B�����S4/ R�0*��EN���J��R7�~�Z�n��H��eKQ%��J��Y+;D&C�N�ZK����H��9�i-(��t�y+�lcF"��_�$�������`b����#r��kC?
�%)Ti>��RX=����4*n@(�j!��f�������'���+i��j������F~180RZ@��T+V���YW��jp�76��J4]?��O��	j�3����p�\F�S��x!�:�[��Oj�}�b�*�@JPgL���>��C.��������]����h!mw�GQR��``R���*�_��R#"�:N��N�^h�
��� P�;V�5i��O�F�Q�����bx�R����i�5:D�gG\|����W=ke/����R�X)�H&�4�{�x��~�D��~��J��7
��f����"�/�[���������1�Po.����B��q��M��q�TyF��va1�6�3
���Vg������S�3��nR���1�C`�s���F�d�%hc��)5���{<�I��a��ic�~1diw#�J�H��:Yk������\[e0t@�T�������IG�s/��|d���L;{��i}�^3I��zIJ�X�=c,��pw4�AT�{��k%��]r4��+lC�(c�yP�������7_NAS}!����BH+T�#Qw��qS��+�^���6A*��J)��sqA!�p��&�S*4����)s�#��e}��2i�N�AFM����Y]R^�I��Qb�f�����`��������u����J�=� �9�S�����c��������";~��8����O�N��k���2�Z���T�	�]������i�O�(�`��@O1��R��m���#?���o�]���!eBCO5ts�'k������Z[v���r��s�Sd�GO��9Y(�d���FjaqG��I�NP�,~����OoM�!��B��AY4������V�����������s��O������d�J!S�+�#�2��GA��o�	��&{5��
AA��y�������z[
���#(�v��x�d
����v>'�C��O�A�n8mW@P1tq��m��j�[�)~vs��}�����	��B�t:�*��C�IA�@P�����u�;��'v�6%}�,��#(oP��LT�c�b��4����+�Y���@O��M��)7��h�h5��7�?�+�)fb���������x]�X���,�ld�K���r���9v�u-T�|;�=���S�9v�y�%�zp!�~9O�%�+`���s&��z�n�yb��bpP���$�d,^�����Si�9wzht�TB&k�$�{��3��Mj5�I�:Z��,I�fb�@���<is�(#��Gm��'�:I�`�-{��%12b��i�I3���5Nik[R��2��
8��;F�-D:8�LV��}B�n��Z����������������g����5���+���Z��5�~���/���o�n\����e��jx����	�_D{����[�w��0_/���n��#v5|(�(����}�������~f����h�+�5
=}��(������x�IOs/EZY�A��.�#�D
���<���V���.������J=��%U���yi(���'��`/�R��n�@�o�� �����P��6�V�����t"���������U���1��<@��������l$�u���G��o&`4�V�K���?\h�������������+@q���Y����=��a��G���e����y/Or+
���vji����1:H����2e�u���TI�s���m��*�G�I�X����;�{�Z[p����myX��N>r�DeF�
�yX!c�b����C@���������B��}�p]���[h5L�5���U\�N�'����GiT5|���F0�>*K&�/�Q��k���e�D
|�^�G����B��v��u���k[AF��J��XFV�����4�-�RjI��=���^Rf����w��L��RtI��!���!�.������#�4-����#d������2F�����zc�{WZ��	�����"b�u�>����i��G�W�c��-�c�z{�BmCJid�S��W)��
9.�C	)��^^�J2�+�OW
Bi��-r�#�����Kx9u�����4�l|du�<����}B��#��������	��
1%Rb*e�,����^GAg�����oM�Q&�2�jy���y�	�<���:i�:K���)E�:x��13�3�n
��B<�h��eT��/��^�g��<�y$cez��f���>����q�B�� 9p�p����"e��R�����6�Ocfk���i����)�
�>`S��'S.x��\��u</�@S���,%�U2�����xR�����_U��&,���n��)���Q��qG��y4g$s4ak,��UN��%�x��	����G!5�
K�c[�������x��9�9�)p*u�����_g��f���o��wS�c9pwj!�����n������[���a:���^/��>���<����Lj%�s�T?]�9��$Or���B<����s��������C7�����������H�?�v�l�4��\���2u!v���B��@)�;�������h`��!�ZRD�g!}f�����@Q����M�O���q��
�Y���j��5GU
y*��3�������8*����8�|@#�	���������B��[8}�T3)�n�����}�����s~x9�T*�[�8���+ *?I@�Q9q���}7}��p>���gNu��z.�=��Y|���B�U�������%���e0�S����+d9xJ]r?8�S�L�1:��6�O�\w�T��^e���NT�F��)�i��v����H�%�j*C{z��Y4�?��Xk"��<�1Z��	��w��;��i�<~�V���w��l���;��R����B�Vng-���K}��X)�����06p�|l�;A�Z�:��t��u���}$���J���f�����x1
�r:p�+�B��R�,�B�k\�\h]�hI
����r�%���5jw���6h���9`�>�����������!������9fj����Lq_MRh5�GM}�U�j{�4\*��T������#���EYFK'R�\�@N����S��p5�L���"��;r��y���;r�u+�j���b�d�9a<L����[.d]��v��?A
~�RY��S��T�;��~��^W�y���O9��)@����$KRTO�Z�� �j�N������#������S������g 'h�A]F�.	u��q31�8h;nJ!������M�ra7aM��k�3F��������6��
��WK"��1q6�Y��������M9�����&����	0�J���x7�Z4�M���p~����V��k��n�>(��
�e`�-8[�N���� ���������4g�
�AO|4�]S�h�A{���]� �.S��K���2
T-�e&z���V�a�P�c��1������d�a2���D���P���� �*Y��d_ ���
J���<R��W�j��9i�V#���;�:�V�F��N� EX�4�i7��?��,���Y!�U�����}@�L�D����Z5�|�@�_�����*��i��N��]���5�:t�;����t~�p�t�4�(��)�����'�q��+*�l)�J��4��<d�;��xI���=�^/��}q$b��I�.��x"����I��k;{�a��of��*E�6��Y�n^h9��C7"uD=��ocw��bz����d%�V���1���S8�D�� (%���5����������
*<���ap��\h<����[7����JlT~b\�2h�t�0�p����C5��I��R���`�:��o�/F�7��������Ik?��M%�� ���y�c�;��&�u�0��m�ch����m��G�i�Q�Qc21�5����q\������<��H�c�O���6x����O�#�I�r����>bD�T�+O�_�u�T���s���\!b��.���i2��K��g�`s5t��NR�d"c�S��Y�������&3it�)Rj!�n������XE)�s=�J�,�0=%c���AK��������j�����=S
Y=�0���';AtzLP�����h�j���Pf����`��?��w�MJ!�e&%/���.p�:\*3�U�~9<�R���;\
����G��&�#����W�/d����Ri�(4���z���A�2F;>��$���P���W
�F�]� �y4�2�/AHk�XH�%e�V���q�RN����%�->��`��B�4;X�L<�,�D�n�����1n���%�K�d���R	i��#6J��$�NoO�D���g�2��i�0�����M�'E6/����zF�2J�	S���X���aSF���L9��e*A�"�L����fp`��v��n9}2O!S��-��HB1AD�P���)dx���,1a�����L)c���x���%��^j]��
0a9<�&u.A+)��xA��E1�Xl�#0
X���Z�>-�E?OZ��Gk���*	-��2�3����.Dl��z���,�@I��i}e�[� 	������w��D~7�R�&��H�||�C�(���<R~���rl���8v�xZ%��q��W������z�X�(���Ib��!R(��=����������O�J�\��4�&�z��R�d���#eY���l*Y>*pZ�{
]�.Y�-�2���3��l�c�m��*�i���lWY6K
J�����_b4����@.P�:�Cw�&{�,��sX�~C
8���S;vJ��F���<q*i����R����RT��_��fl���.**���rpB��s������*���v@Z�p[����
9v*��MM ;iO���C��N-�i�DK�	*Y�e;ywZ�^T�lfs������IY�jB�n}����N��bf�*L}N���d#���Q�b�>v��P�n���t��J���L��Y�(�e1�\���(
b�k}�
�&>Z�v	]�n�QTN���~9�qT
'���Qy�������Y?���q��Y;����9m���V�zb��=xc(hle�/�B���7��s1����s<Us��x�+��:��JK����)���5Eg9���>�6Rs��f;�=v�mZ@#^O��)n���t���T2_�rO�J�������x�3g+cx
B���K	�����|�O�\6v�M��:��g���T������J�+%������w��O��V������Y��T�rO���_*�Mx����[�u��A
�#��P�~t�6�1��1Z
)���T/]�����\�B/RR�a	����U�.4Y��b�r:~l��R��XB�/�|�z,��$�3���Yr�`S�'����rz1�q7�YsZ1�0f��"�W�a�uru��
o�
RN)���R�$��:b����X����`hx���!e��c���L�z���JeS;(�i*^��pV-��/��.���3x���J����c�����Y,��s#�"=<
����������Dx%H$=���f	���W����}d�hU�,C������W|C�����iP��#5'��"P�C%�����"�P(�4��
8��p�[)"�P�X���&�_�E�i��)X��_
�~9�T�?���X��b�[rP%0P�5�l7�B9�������#�C7�g�l��x>��m�i7Q-���!���B�=�i�E��U�*?3e(�b����*�Be*i��*+T)y�hbM�!5\E����uvW�uiOz�����t#GG!��q��E,rc����$$;���d%gRB�H�zkw���������i����\ezR	��@4�RoFp-�H.B%�H
��];<�#��=��/f����
*e+���a����i<��NY����
�i���A}���o��Z�6�-��������� ��"n��:To����N+zA�ITg���6�$m�Z/����i��	P�6K�����yd�5
(���;�xJ��L�(��A�6WR*39�~�lE,Z��y@�����su�u�KPeI(�
.A�Np�'ix��^��R�	F��#��sz9�Qp)�`l�b�)��S�L�v�R�����y��3�P�*�WS��s�T��
3�D����'>��L9��j$um���J�5<�)�80S�c�3�hfjuZ�4F\
3�6
d���13�Y�-��n��b�2���%Ie�)s�D�3�'gQd�P��	�d���*�)�,���J�)�������c�V�����a�TeIK��ro+IB���_!��c�R�@�9�rl��?1S��\�i�i�1X���y����?yDM�R�t��E�K!b6��N�5�U2���J���(�)_��4Y2�YJ���=bNj]�?�&mo0)U���N���M�-��:�����7EI��yb��9H��R��40R�����	&�6>��%�*]<5n�b��H��h��-��t��8�Wz&-��Hl���75���_y�T��
w5kz����Y@��%�R�9�uxT�T`��s���L�����;�����-fI'q���1Y%$���TBVkfH�;D������3Z%�lo�3,�E@���L�JK����
���PX���T�B�v��o�;I��pr�U�$�dDU�Ub[��B=�*���qn�������R��d���w���8Cm�f	�H�>��i=�)[��J��s��nx`�4��>����$s�1S~y�+!P5�lr��b���}7Ng%/)#���A��k@Z%��}p^J"_<�"���QX%'�d3U�|�J��Y>-�Uj	%Y'�����P��>FoO���B��9�X��U�lsV�=�C��zc�����o�
�V���R�@Q!di@<�q��,��(*�<�Q�f���4�����)�Up��4���g�QP����D�(	i��>_�?rp�9��*E�/f���X�%�*�����r���L9��TdZ��Nk���pT���-G���@8��BL{����d8J*�t��P-�d�c���B��V�QR�i���N��(�����FcGR������@�\���IQ��4@94��J��xt0��H��,���!
I��I����T�y�T��H*����DQ�H

E�wh��H��%S#��p�B�.))���*0�B&^������N}R"�z�
h*�
8�l�oq��6���������� �Jo}@�����i[�'L{�Z����}+��~`V�	��rI�[��"H��s��jU,�$�BM�V��U��"V�����%���b�5�=�o"�W��Z����D�U���^�)E������Z��1�����GR���?�����J7��3�[�����h�V��QIt��
72^����s�?
12��W�o!N�W�`�y���v��2]�o�����Q��bl^��K@�����\Bt��VA�>��Q�D��Q @�C�V����$]����SZ��V��U�HXrpDU6�6��Owe%X2j�������b83B��j
���B�##kA����r5��x�o�"zO��>U�f����P�a#�Q�FZ����`-p��!��~�Sd��&W��Q�9Q#,�e�6~��Q�[��e����Sh<�]a��$+c�2�yo%���F!�/�@8��u1�1`%p���Y���2��r��Q*�M>��tL������/H�����eN�<�*�����yTB�"<�KK:[�s����r��>H
yZ��f��a�q��l��,S�Y(I�����:){%^H����Lx���:��+z����j`GI1����j���N;�L�[7LgEJ9C���I�4�aR������:<=� ��L�����L�	�Y(I��e�d@	�p�N�H���~���?�&[��������XIKba�+���G�O��N�yx���uD<�"��qR)2:�a�P$���y�r�S��T��i�pR�b��:�J�I)%�W^@��W8�*����S
*��R2�R����?��k�]��o�P9w����)�G>[g
l�@y*"X���qRMc5P���x��7�����Z�V�J^�e
i���-�wt�:l�;eR98jU��;kGF��[BWZ�	�1[����31-D5�����"������4�~
�Q�����s��D�t��&�?d2�]�fF���KI\t�QH��vGEe�(����R��fM����� �������2����^�J|UM��[{���?�E\����[9���Nc���gkD�����r"��`�N�A�{R��c�R���:iG������ZK)�Shs��Iy�hs��(�	RB��~�1v�iC���4�?�sh5-OK��(�,Q��{�`ek{PU"<�V��57�J:���%�I4R+c����	�R����X;N���h�8W��R�WjQ����=�&^I���w�	A�8Q�b~7��L9��?�4/[�����)�n]�����c���������GI%d��p��h�.� ��e�����u�������������C9"��R�W�;b�6�����R��5�a"�s�R�chET;��r]
����q��i�	�L�V�:-�z�8r���&��;9�������Z������r�:�%���E^���
/������t������:��Q�~3q��/������eo���c"8t�
F�0+�8�������~�%�����0|�O������u��V��j�����R����-����:=�z	'mO#�y���%��=�������z')t���C�g3:_�����5���o�dm�zh��Y9K*���L������o��X���h3e�29���%
R��O���|�yN�I��z��:5��z����'���z~3o������YMR!�����<�'�3xFG{prA�'��><��i�j������N�@s����+�\GP���L������[��#����z�s%{�'��A+��T���m?r~�B�>
���������������;Kx~)��I��6�@P�6����GGP�ck&���BA!'nL���Tj^('GQ5�^�;-������(��?���vCL�����-y���9����U_<M�u��"���~���_{u������� )nCw�=.a_p�1�2}��A��������:i��;�7�����o qu�~�k�r|�M��v�U[�`!]
���
#.}V��Z��
����-�U@r������L
�Gw��,f��)�}�'`0�����P�����4%t�xZ���'[���s7��g�����Z���Q��y��L�}}��v��
f�`�,������2���g��T}?�z5)��[F��JKn9�N��~C�F����-���y�[��g
$�]��Xb �������]C;�ut��`�1#�����x������."��
�X�v��X�	6��f �DG;�`6�#
���7-c7/��;_������l'3���f��:�P�����4p���7���zT�T�x���4?S����
��X�5��kN��wr��
��;���W�l����O��C�JC���U����'Xc*�b�'d]�w��*H���*P?mG<T����
Ol���*L^�T�6�;��
���tCbG�M~����������
��jv(���i����w$��F�v4X�;��}��E����W�N�W�N�v���6VHp��U�j���p�y���N/'2��xw:0�����|�h����������G��vr�[
G����5c�C����*[�`�	
���Cg��`��M+`�������_�/t����h������������-�@'��0'���QN�&6�9=�g!����t�����}5:N��8:�M�=��o�C$�����,[5i����9�
��������mX�����%�C[~-�����m�����[�
M"k�F
�����*l�u:�������g������W6�7P`�X��%���v��Ht$/Sw�����9����D�����Z����h�'�Eux#9��l��41l8\C|G����,`����Z��y�Nk�{p�����%��;�i�)xpr�����t�����iT�B�\85��SN
h�d����_���.�F"J�s��	u���{r�0�x���]>w�x#���F@.�Sh%f�@�/uF��X������&�@�s����@>!`J:rSHM��
�^�{�S�`%���D�j���B&�q���+U j8eY��u/$��5����u��N�2U�F���6���^�.�h����Z-5�a�� �{�(��.zHN=�5��^!�~BDk������N*���9:mD�(!�0����
����c�x����O��pD���r`�VdnE�����LC����j��sU��H����T�mX��	�{��C��Fz�-��sM����X�I�C��D���N�"��c�#���!��Q���@GD��H����?B*�4DT�\BD5�^0�n������<CD1���,���a$��������e>��MGC��dU���o�T��P
��!�AW��C��Rw<�z�22]���������7x(f1;A�"cB2��!n��w<$H5����:���f����+����0���k���P�0'�����[Z������,,��i��F�B���> jx	
��P�l�_a%�@������v�Byx�I-}���m� 1���|�� ���]7�N�|#���p��1er�3H%������P�c����s�T�x�8��x(UyZ`,���4��[� 1���"�T��p���(UY���@DA=�vD����	5"��ZP/��D���D��\�k1�se�a��-N�e��shx�:G�$�j�"�a����(��(c�5pQ��Jw\���6pQ�2%�.����e�S�eY��#�Wk+Lai���|���8#<�8B�.����S�Y�@��zu�\>��,��J��TY�0>�8�4�<�4�L4���i��2Zj��_1�DkD��i�A$��d�����_D��/I��C�\�{x�� �A���jM��F�ZKxf��z��H'���"�%��7�7"���<��+�#le�6x��g�9
�g\����YY��Sx�e:-��������{����3�����Z-D�f�rRHo��������<�>R��X?7�'k�,V�-�$Y��z%i"�mNkH����f6�>k��4��(�A��*�!���XqcZ�x�3:9�z�%e�4�_�u��S�f���3�f�=� 8���:�E�'�����$,���[.�v�)I,�p�F��������8<�9d�O+o�%)^2|r�T���r@��v�F���8��J2�n��r��N��������
��Px���<�����a��O�i-� |��	
m��\x6I������	
YB	�G6���������/��[_�j��0<�B��B���g�5q�TB�����d�@����.G
��3q�RJ�qOS�Vz��������V\	��[8�fayu	����R��&Z����*���,ViJ��9�S�z��J��z�s�9�^��4W��������,o_'�6s%dl5��1�;�=�

����&���6��C�1��*O/hI[2�*}���,���M��;d�
u��_�u���K`��eL
Kv�����V��4�rP�[������B�gp�Ke-�zD�V���Xy.��UM�MtG���x��N��"Z����i�r�I�}{u��G8�z�=�H�����,J!Y5����TC�X�s��#-��%����U@QL�����X������y-5H����l�,��0@Q�i9'-�]���K����+�dP�F��3BJ�u�R��]���1GP��v����#+�-���eH��1����E�m�� IV7y�������P���I���J5�{xb:%<�R/���iTV	[�|���e��R�c?,l@�^���Zh��M����	��{����{	��$��Si����)?�BlV�0��:�J��8�z�����v���O)��������
[�w��);�*1-������i�q$��&���5K��!~��z�@S��e���h
s�����rZ����A,�����B�������-K�p2��� 9
����fsR��R���8"���j�E���Z���K�LV{WDz��R%d
\��f���m���@S!���iM	�mM����T�f
M�oW�Q9�����=g�<����6�x��Xl*���S�����i}�5����M����q��G����)-���o�����r���g��Q�8 ��#��%x0t:;T��X8�O��������@7:;��R���	�V6n��t>n�:�rN;�C�J6f��d6�1�$�AcO*b��N�2py�(	�U���p�Y<A�GQ�u�)Z������r�����N������m�oS�|G[1��8�L���������N��y���f2����_
�f�8�%
��v(`��<��}Vo��Gk���Pjt����@p����3p�c����4x@����%�%�y(��,J�k��%Cu��	!�7@�U�|"=�����S}J:;�un�l�'�3�:�����g��_���1O���8����3��	�����N/0o����8 ������#]����
�@�<����
=�GV������I������,<�g��P;��
L�>��=p�p�{�S_���M�u�P'?�6�u��������u$�2q���-��uNg������q@1U��������_���ur8��:�}��uBql�P'�����]�p���S/8x�jy_���{=o����#�I�������y��x0�����x$�^�m%��A�f��Z=��`��G*����#��$|<V�:��
OJ�5��	����GV,�0�SI�"��f0Q�B>���5�T���|�L��OYA�U��u�{�+�a�y����z���w`��y����f�4�������,g�I�;��"�VJ�����h3=���
P���*��;��l��-���WX��V)�0��{;��y�������T)��V�����H�'f�&�;��8�����^���&
��M�o�%O�@�6��'~��x��G�O�v�O�~	�`�w���w ��mdR���w��_�������j�4�\k���[n��8��l
i\�||#���_e
Vz�t�#
p��#
��`�����=���X�Xh2�V��0�.��]�����o�`G����ub[��q����t�12�q2@hQ�0�����Z��?���ANm}
�������>�Z����\�BF�R��'�����<TnR�0>��n�D�����m��Y�))��n�h5�z�&����A��AN)�J����9�EV������@:���b����A-����xP��S���h�>�ujf��H��S������m���(m�'=!����r��l���I'N���0����i���H�6A	���w=Z�Nu,�_/����#���J*��K%�����D1��v~���
]?��I���Xc�i������`cI�l�Y�(������P�"�	 ��9(���?�����4�Wo
TL6j�qwJ�	T�
���@E��b"�C��"Z��;*����G��>GE)b1D�9�F(�D����JD4��zQ%k1�,i�W?e�^��(��6vX��X�{H���{�U�\�J�
\����5X�����[��`����X��
�JD�F5R	��������b9,�E�6�G�X��<"��	�
y�M�����Y����v]�������46�v�}������5�!���*	0������M��M*�T��pGL{�7q�<�94���a�9��O�������1S5u�CC��%4���6�z0��:�y����v�$NcwYEU	��9��n�_���d���g�"(�@����6��1m��'��;��2%���)�*��AQJX��K�gl�3��A�B*�"O��	TT"����6���d6tN�O�y������h���:�E�P�f�������;:��G"%n�#�����T�G5������r��T(����,�������
�B�[_`�Q�<���;GG������M��"�R*5��fmt#v�T2��R�-���Dfb��� k�B&+��RtI�N#�j]�$HU�cZ�j%zih!{@4���7gw>%=��
�4!�uj$!�b�v� [�:��
m�W�WK'i�/�	�� <�BZ�'�Ev�6)��[��Y�������s��:���Y����q")�� A,��d1���Q.$���3�w�j,�At�T+V�N9�
t�iZQ�i��1��
�I����C��pon�A�.,4�Sp6��:t��<���%.J!�R�j���6TJ��\;�"v�uz��I�P��i3����Z���]�v�T���+�	�69&m������9����S���YZ�u��Q�3YU���}�z� {M{O�	����S����R���]};�S�1��M��1���<��Zi9bJ=x^;b����^C.4�P����[CL�=�S��R�(�]	������p�n�i%d	1��������Sj-�1%]d4�\V�R�P�����z7n9�r&NN
=�e+�M��5<��M�C�d���6[��t�6b$����A�����S��XU��858(�2���c�����e������sjC���6'Wk�0����@P-�a�s}]�e���5�3���?�{�f�92������������m����
��4����Y)�N����e���[n'��Y�*�Q1�X��o����B����u>�����B�=^Xq[)d����|:��B�J��8*�2�����-�����7d���Q�A�p��9�>SF�(��i��ia������L� k{{Z<���Q�&���nG���{nbd�Q%$:chR�G���3�N�u�3�"�4v+
�VH��P�����gO=|:GP��UZU����f\���BA���#������a����B����/2e�k�%��� �i������2YC���E�V�d�S�H�,9���=��>���P�b�[���B�RF �2�Iln�@A��+"tF�:WR�f ��_�*��ow�K[�%@�	m�����B���S�d5uF ���S	i�B�c���\Z�&����7pS*3�+c���z]K�'nK��r9�����o�n\���oq��^
������	���}�%��!oN�����V�����������Tj|Fk��%��uZ;p���`�H]4?4��<:��C����T�x����f��th'����Y��(���t %�A(���,lH:��T?h����~����B^H��B�d
���A0��
�c�k:y��yG�����Ba�h����`J52�����\��*�������O��9�0����u���nk?u�|�O2#��ZR+��a�Pi����e�=-��T�`����
�P:`��=����������{�P��'x����L�A�p�Z2Q8��@�m��%���
�8c�������`�Jd�y��^I;��_'Wm�<5���Q�$��<�x�A��i|���u+P����v���]���v���Y�7C��]��q��'<���!/�`�A	�Bw2j�G*l����A�`%
#0G�x�q�9�e{�O{<��v�Cf���/[A(�l�����x���i��������*L@�~ ��z��#Q�����}�C=�~%���2d�	<��r,����G�+h���9I�y�M�0��v�ns����(3�#�vZ�Z�kw]')��<��b`��}���c(���i���9�y�����*���hG=Pa���z������h�O��]H���5��e��)���w��[�*mE;��
Bb`�4�
��XHi�GK@?�y�+���p*(��Di���9��i.�����x��z�����<�{x'wk��x}7]O����<=�����r���X�'h��3@.�@<0S��@<Pa���[�'����pt��w��t���a��3H����`
?�4����,!`Mxx�q���i��e���}�u��k^V�8�8�e�q������ ��N���8�7Y�\S����^�w���o�������8=oL�q���xur��N�6>:�]�nXNkM��;52������{�����a�n�E�a��:�rZ���1��72�D���8S �8�9���40"�D�������U���q�CK��7c&�� �5�NM�u��9����p�>�>j�n���^���A^2�<�	�a�K��
M����/�!��S���sn��;�I�-T��.$��r�Nnv�B~9�`��k>���vU�vb�rYY���N�:Q��Va�}�,~G<�������
�F�����Bu!{���;�j�F_hD�j����'�X��,iE�h�o�������V������B���3P���_��{�,c���Q��*�������U v8�@����<�~^eSO�`�rrU��HM(�����J#9�n
�������ni{*5�8=m8���D$��j��qAd�8�Y���7�+g�8��3��1t��5��=�?�����.����a�
�I,�z��w)��^-i���~B��j�K����9�%��8w��t��G�wj��z�����/��O�RN�&�b*���������v/P�����0�<aS)L���xb����������i�)56>/
7;���_�[^��<!��_iOa=��y
������3l��EvJ=Z�W���a�U���S{a	���{��W��F<�(2����Vdi�Y�?���������@�4�O~����l�?1���':w��|�����r1��}�!�����@�}�?�����
���px���Fk��jp	������	M���C��z�?�����ZA�H6�p��%z�I?�QQid�[R��:5TDM6oZ��1��*�����JU�4G��d���	7zR$��������T�&��W��Z�diL�Y�	b���y��:��l����Xh�<>�TY����}���"z��z9��J������-1�O��OT`6H�m�����;�������]���.���e�z�)!��\�~=��A6{(�����84�_w~�'5�06)��;��=��
�&��W�Z@�V��������JJO��H{����R��~���q��*�����(uy$=jwx3n/�����*3�L�4��U����Z���[�@m�kZ{�{RJ�$~�#<�8_)��:t�h�]Ce��k&�
�A�ro�x��JVx�p��:X���F�08���r�v�������\���	N3\�/)FOv5�<R�s	���l,(�E.S�vS2��7)u���J�# S*�XgCx��T�X�:+9c���YB�+GM� ���<���zk�K'�l���6*@�T�X��*kv�Kk�����K+��=3�LA��B���B���Fb���C`�����2���J����R�>���2��zk
��z87��������Ga�Oc��@Nu�U�/�k��S�v ��x��x�,�2��y,�}��}������:f�oM� Q�O!fs������a.������:f�B�������p�e�2��l���A�1��������d]����Q�6(es%�{Z�^�k�j{��`x}t%uZ��}t�q�|��,PT	yl����Y�FTg�����v�Z6�v�-P��y�l��[�H���3-�P����o;��)�����e�������X�e�Z����������5=���[�:�o;�*![�v's��V �s���T��

��k(	�
m�����w#(��+1�@P!�i��4Aa�Z3��
d�[��7�rf���*�z�"$9�����>��`q��~����g<[��H�
ck���];���4=EP�L�r.�{�R�f��g��whS�9%���d`�7�C�*�V�6�/�R�g�wm�i����C�}���
�1YC����_!\��$%X�BHkzl9�Y�c���v�� .�cHQ�ju��'1�O�I���w�����
�*�R�z��Z�O��9�J�9�RD�\�!���3��y<��.u>3!����'�3g$����H�m�I��Vh<��I��H�itV��,SNEt@
:���JJ�o?
-�q�i�c=�
x�u/$���������Vk��of��_��K��{�v��<�a����\����j-���Z�+5<#���z��V)����UH,u:<���e��]����������^�V5�����g�^+J�>kP�%����	�`;���'���z�(��6������20�A������[$��xJ�^�:Q9/�>�-��B���M�������+G?+4xj���P1��H�@e�_2�WN�@� ��X����������Y�V�hb�u�%�iJ@�CJ�c����"�@
g@�fG5VA���pN�5\�=�> l �V�����>��H�BcG��z��������
@
�x��� �4�{��f�0Gft�	8��S�6����`�99�-z���ml�hH'�X9��%�t%���~��N+
��h��w����.������x�u��	;�wB��c�T��� ���s<PSr�h0�T�n�;�i���x���j<�HXu��M��UF�J���'��$zu����w��T������l����p<����St����$�:�����M5�{����	�x��GLr���.Tr���4���($MC7���X���l����C�`���s�sJJ�
*��giw�D���C����@�-b@�Va3��;1�@^�y��v�2���%�	��f�j�AOx$��;�������T��4�A�f@�Ez<��	+�7�����J,S���������P���2��C���������y���4 OO�P�9��p�"-}�#�	�N�S��5�N,�n�E���
He9����B,PzV������u&��;��)��`�
T�V��S�&;V!��@���M�j�u����vJ�j��r
�2d����S���=�M���@��3�N[Q��S�Wd������y���~�����]x�����C;=�����8z��vcw����H�k�jdoa�b��R�w��;5���������P���jc�t�#���,jBsG>9��d3E>R�y8�i�%I$��>`�<H]����������	�'��~Z�V��]=���L�R�;���<��'�2w�
XK�4g5���O� �����S��C�4a���O����>�j��t!��g]p��/��=���|�v�rZF������Q`Ew�S"�V7
�t|Z��h5e4�jX!��0��j�][_"��U��g"����x�����p;���sq+TV�h�v�]b�F���@�]���]Q��`�C��Q��U4j^��I[��\��C���xuP�I��U��/]��46Vc%N+�	�V1���!�~����v�����I��j�R�D}�R9�`����8w�|V�Phl%�6�Q|��!Q��B;xnsBs�A{p��NET�*vPT��D��Jc����J�HM[\���p��A��h41)(JE�I4nE�!��6��(�"xAPL�rw��G{��N��BDk5�(&"�i������$
���V��R�h	�
EeS� h�rp�K�F�S�����%������9$�_.���K�`n��q<�1�w�Rc�	<�K��RD���(D������i/��<��E@��D�F��K �f�"wt�z��t;r@D����,1Y�@<aMF��� 
w�r�Y�S�a��R8z��Q�C9�Fe@	�����N�k5|g��Zs���!�0�� 3QXs��O����D��s@�f��rp����6��b�t��r&_��F=4���
��b��SB�KAkF�k���t��c�|g�����������Bu������R�2�r�����8@����r����6���d5��U�;H*e�<{�Yn�<(���
�����*���[��.8n�yLT�7�l�jp�UyXf�$�3��s��t��R
/��2J|�3��c����R�z��W�v�����<��~���i�N�N_�F�t.��U!M��SB�
]�"]H�q�m�K]&�����<Sg�0�f�s�t�p)3u �3S+cay�b��l	H9b�zlM8u��1�Ie�e}%�
��3�#�G�:f&Bf��v�<-��/0�a��t�C`�b�(�f
weO]L��
f~7<0S�������BJ����L1k|��T�\�$�jp`�<���������Z�T�W*�J�D7L��C���$�V��q��yX3�;Ps8\f��b��������A%�h��IIT����By1�D��5(���8����mHI�bD�i���3���'aM���&��� Ng�:�����i��6��y��B��$�������<G&u2��J	�^�]q*��������������_���Q�9o�|{�k�Z����7�k��+ut94*���
�F!clmo7��Y:���ju�	th�2��	���H�.Von���^S�S��M�dg�A/����p���#oK�(��#�X���.G��<Zo�Vw������	H;8���z��'NG��u���A{�����g�ABDeO���S���V���������+��>w�������(?�2��- �7c���!���
�I�e��j����F?Coh��>V,e����J�}{�`V�q���e���S�l�m�P'�I!R��0n(�\�n����L<��Y7�d!��9IPfpwZ{�C�N���M ��ZX������r�vT_���/#��z�}��l���F�����e`�2�*)Ok^<��~�nW��-�������G��M�d	�)[��#�%�%L�(��Ve��U��s[��]���X�)W�R�.���_�5��s�	n�sw�m�rGR����\.`�����s)["��|I�����*Q{�J>�6���F:T�L&gL��qk����-�,AO3�c%���d�V�&~�(�.�!eO�6��dhi�oCK-c�m��Y�d%�i�oH�mW����!������*��K������9Z���9�_�v��/[���~�S�t	1��S�n�^~5gG�/��
��}���m��Hk��[F��V������Q����^/��@��}>#����^`%Z�	��C������6�x�~��������v�5����a4t�����Y��zFz4�O����������������/����n�������;<���6�^zxD5$U�����F[a���I�h�Ps$����F;����h����-4U�.p�~�`�i���zV���&�y�H�m���?3:o�4���������.k6��h�B�l�F��PuD��T���F�'�4�9�?���F����fr��Y�^��k�����d�R��dt
gd�w����%��.�l9��wH�������gb��GuZ1�\�
�o���Pr���Y4U�;�
�j��U^i�y���9�j,��0<�K}��s^'��ag����/���p��`�}����3�������[6B����G��q(����8��VBxd����4k�+`2-� �f[xv��\Ak1\�����i�!LB�@0XsH&
�-���_���&�<2���{��KmZ�����B��:RsoL�d�7�.5�;���b�V9���4��#���3
\�]?���&����g����K�7�6��6�����Hw�`<�Dz��_�Ep�n]���$/�:0�z�������f��.�/��Bf[��o��c��#��;�������������?��A�?�^�O*$60c��������t*������:�zcj0�B2H�'<8��r��mr����}7o�������^��@k�2��&�g�ekj��Zj�W��lq`���Wh~��.�m�?��+j��geu2�������uG6\}x�rd��_����M�����i�
���\45~5d��6���8���P����3�#Z���ud�_��T?^�OH�L-�
����#��x@G6��d�J�@61�����3d������N��������\-�"U?����"m����zH���
��.p��x�Q��
�u�� ������~��bX�n���{��G���G�=�xG���K�!m��������k��F�:�������dm�i<�8�������e"����?����;J��2����~��
~9o�+��p�,�������8��fEK��s�c�^�i9S�����d�������Xy�y��m�b�s��9n�B[#y���C��N`}^�K�
��������
J����`U�}�N��fN�q���m�W�%�pO�>R��'m	�B�u1��"�^]�~o�}Y�	-�9�@��U��^yY��@���M��s���y_�v��+]��,��=6gUc+-���9�����g����:&��w.!�� ����$8�����UG+��SZx�Rx�3��9P��������t���K���J�V�Dv���f�j��%����`��C�P�_���j��*{�S��@�X|j|���>�
wct����g�����������3����w���h
F�	��B-�;W\=5��{r�y�����mn^��|^J������5,A=5����~���$8U��YS�0b&�c���T�0�u ��c�-|�9$��uX,�'�(�P�F��@���\y����b�j����r	�xgjjhx'���<��S���#�
���NK�;��Xf��N���xkh�t���f���-��R+�1����2��5�SS��P������7��8�M4
i���#(B�Y�$�BI��ed�R��B��
�xw.c�����Uh�I�V`h��Y�Gz`���t��,�p9��$5f+aL�����F�B���)�(U2Mf`Yw�Oi�zo�4��$,��4�@g#�Lkcu���zL�x�Y��D����9!pzN��u^^{�S"v�������g@(��tcj��1��4�v������yO�v�?E����r��X���4�9]��i�q�n�I�CB)a����iL�hU�[6���S�4�j��%�A����"w� ��9��l���V���b���Rc�zX�"dd&z� E�3L���"�Uj�p�j)b6�(o7_0�,`j������ �wU���\,��qT�W���W���*<��g{��;Y 3���bp�����P�&��b����bh�T>x�����1
endstream
endobj

3 0 obj
52009
endobj

5 0 obj
<</Length 6 0 R/Filter/FlateDecode>>
stream
x���M�����	�����@���2��xg�
����A�gU.��n����o���R�h�H�96`���LRA��b������_����v����}��m�s��n���n�M���������������������?��������������������>L]?.����������M���?������������������[?��0�[�������������������������|n����g�����_�������q��������og�n��_������-��f?�������n������/�6��M�E�7�C7��B��
����f
��������y��u�s�o�m���M��������?�����_}�x,�z��a����-�v�n�����1����������O�����o��M��w�����W���[�����[r���~����n�o����8���<��LS�	{���Y���m�+����y���v���q{������.��V����o�����&l��iX23c������6c��Mc���?d�|�z�5�E��CG���8��N~(��������[|����nO����~���3�x
!�����n���!Yy�
�L��_�� ,���x��O��
I����o�>�������$������/���V�)
[�|n���t�tTV�sT6}*��Q�u~���~�V�)�[��m������O�J�:���?e+��~�����f�uP�����c���/�pN)�:������|�+��Y}pNV~��9A���C�)��5���w������s��Q�R�������y�����L��������
Y��kx��O�c	����v|������[?���{��=?s�K�
<�����������[d��g���@����\+��s����?���'���l��q.}������%����M�z���MR�{�
'�����x������o���9�	%����	�Y�^�z�9l��
���>����x
�y������cvH��;����=��o��������g�����9�{��������qCun���������i��o#s�{�V�����.���~��j�7����?>]m�u��"%��G�������������?��g����y�F�~}�G�w����I���c���:>���G��x�'r�?.1�S�rx��rh��w��q?�7�?j�Q�y�>+w�c	�G}�]	�����@�r@�O�]�3���h��V�O#U��
���I�S3������y�|��-;��Q�B2��p/\��
z/�s�����)���O�L$����y��B2��~|��;!ic_��p�����r���2����\�u��}� ���K=k�&zN7_��K(�=\I	��e�~���G��]I���wW����������������+��H���l�����|`������A�k�2��Z��������R�x"|~���rp@��Nf�E	�g�y��M�� Z�)�x���	����� �O�Y���}�E��p���n7������p�n����_���Y0"~w�U=�"��v�X����S���S�u����t~�@�n���/�G���q��/���|��?���{(a����-��p(A9�����N&������mo�{������1�UN����CX?���x,�c�i��Yt�x�������������1��5/�|������/���YZ�;b�L�.�QT8�S��K$@���GM����v�{���}�:��	�K�G�:����Od8��n�c���d]�~���k:�vx��4-�}��yH/�OS&$����� ��������0=\r�gH����s����}hD����i/�y�����������|Z��&$�\����������	+��{'?�#^�����,a=i���hP�r�<�y���S�>tn���3w����HP�c�p8Vn���@�_uw� -��=>�x��C��I��?W�-������l���f���i���7�{�������p2�U>��	������t��t���,E���A�0��#(~T����N6~��t�!F����M�,v�x����KH��'�|T�������Q���V+���d-���1�}\�-IX�Rq�Kv��T?����+*I�n3��f�*��w'%a���#��"<�U�������@��������� �^@I{8,�Z>�~]��VL����M���Yf���f���7\����1��}�}��	?���b.wNR�r�������'>=�v�hv�$at�ZUE�n���������?f���O�7��OG%a�2��g��p6GM�Rn��c��:3����,!�w�������\�C�������>�j�G��~���N�C�HVBU�g���� l>l������{�Gv��8VG�v_�]	���i0�|~�\�����$�\4�I������C���v$Y�<�;$	�6S�?��Q � ����I��x�y�v�vD��K��Q!sCtH�V?�s7."i������V��%�]1��(���{;]�%>�N�����@��Y$�A��z��5�u���#��^���C������s7	���~�5�2�^����y�p?6}^B���� ��	&�����~���.$k���J�V~���-��G������H����M���u��Gu���'H��i�{��b���e-�g��pH~����,�Xg������o�C�!�2~��|�|��wJv1�����C�DH�G�� �P	���P��y���~�B-k9D�/Y������X�N�e�������_�$��+jQW+"���M��z���jaY��{(�3}"D���$���t%a�v�c/�Y"�?#�C1�t�&p'E+?��P3�N�F�>�R��jqA���
��EV��pS),cT7u��)+�m������N���)���h�i���YGg��,��{�t�0��	�Q
�$�2��0H@������������Q���W8�7LGa��h$�����A�~>�c��X�a^�xV�_��['Y'y������w��@��;�������U�����	xZ�����������[k�>2��=��'E)����n���[�������� ������H������� ����������h�'����c����w~q�����-�&�v7M$@{����p=)D�E�p9��I���7�?��_��g�}ld�e�/G�#�U���]���R~��I�/�pC���p>)�zw3
;�S��.������q6|�l+�I���O����������(kd��{�\~���U9�����	R�W�����p������h�A��10p�#�>�_�Q�)%v�0;&7��T������M�2��$fx"	�r��+���w��E���e�X�-��W����������n)�5(��0=�h�%�V��
�Y���zLZ���3��c��iw�2?�y�Y�������\=���/wG�u�[����4	�$a����1���O��h����tT��f=,O�z2�:�������n��n�GXX5U�)������Q
7<|�� �P��~P��4��>s(�_aM�Y�b���
��u�I������^�3H�OJ	Z��'I�!�:|����0hp9nPX�1vwS�U�������VL�u�33���8l��n]d�Rb�P�W7�1��}��[�:&l`x�$aW/�IV���;T�3���2wL��X�l���p���
e���6�~��77(����{��%I�KA��^
��N�,/I���O��/%+�^m�f����i��x�������Kv���e�������R!v��������:�y�V;���b�������8w�^��*e����~�p�{������jY��^�r�d]��Q�*��?-�v��toc��X�>u���E�����?t�)g�	�u�O~��a�������#M�ixC�����at�Ca����J��M����CJ���W������9�e��-���-+���S�$���������#����:��]��EY���pCv(5��;��cAG�;��VD�>Wo��N��C7�T��A�c���W"	+����09*Ix+��C���� �*Z��j�o�+Yy�e11�
����9��~��	J/s���72�����e<
kH�_�)O�XD��-��]LY����)*v�N
��8.d�����v�[8�V� Cu����w�:�\�h#u�;'	�zt&�}����M�$�s���$q�)���n}�]�IsH��������J?�!QX5����� 7p���<�C�t�@vDm�F��t8E������{{�f�=r�n+�jj�pC)�z��c���p������
�����y����;�P���m���������E*���M�
���p1��	�g�����/��5)������(q�5�uh��U���pwoC���q�A2�H
�� �V$�t�M��\n��tq����q�u�����8�����uR�u��u�E��:��c�p9��ZH���o�q�_y���>tYnX
^�����$�oa���h���R@������w[�kh\n���\mDa���>�&��~�nl|����k�����������.v�0>{�!I��df(�:�&�-;�v�+��\eFa��5�$���Z8���w���
$\OZ��h?u��������7+�m�o�_3��A���r�A����p�?j�y�y���������������7�����������p7������C���'��*������c���
m+���%�A�Sx���g�����?���/,�bg ��:�`5��]������Ez�K�!�s�������KbX!�]�������2����t��y�xx�s�~e�{��������iUJ��7v��]��V��m��^N����
������;�P��*BV��
?�GR����\��C����&�s1�|�	����S�?P�����v��T��������u��;�V�rL�U�r���w���
��G�~��+ja=�okz��E
;�u�&�i��3���D�_�����wld����.��B&p�����R�������.�������pRv�B����� �*�<[y-P���Lw�������Z
�����u^�e{�2	����������y>�	���6�C6�0���PM������s�0�K�)$��[w�!�Ov5x&a����AX1[�E����!��������(L��[�%A��r�p{������'�n|��6�pI�u5n!a��#���;"���6D��${�O���!��V�3��'�{�N9�]�B�z���~�-�o�n��ur��?��Ca��B�	�8x(�������Z�Y���|�Q�X!��H�u��aW-M��n���p��d#��n8�����]+����������Z?C���k��������j�p��A'r.Y��A����N��|�;'	���!Y��_]�2ewNvu%[y�R�<j�(Wd�O��<��P�'����K(l����{��b�lwO�u�K���
�w���3PXqrnx)����MJ�
}7�*�MDb�pX)��d��L���~�3��RFZg�8$��Q��R�Px^
�����Y��z�pSv��������u�e�����]7�,�(�w`�����O�����.�BV��7DaW/I��ywW������W�?Q�������G�-��Y����=��$�Zp������;�"0�=��"Yy���:��d����3h<��w,x�y��X�mZ�LQ
�RP�G�f�F�H�����m�����>���=W�����uE�K��b�����f���K&nv�'q~L�4~���*%�BvGa�C8*	�^��������O����
kVD��QIX��pw��Lw������������	���p�D��u�$m.{$	���#Q�����p�f~jv���Y �7�)<r����[=�	�������������<#{@a������QQX-1�;*������>���D���
���G�i�xwB-�|������.�e]?*A��'���{i^����}��g]���S���4H�����]�,DaWA��M�<�G����c�b�6V�	'D+/z!*V����t��Igs>�L�A����D�r�i�,����y��C�Z�?�a�������N�����	�9]k��v]2��-��W4(�S=(�"%'�6������wH���?]�p��H���dg�}J��9qd��
�d��k'��)9u���:��
Y��	������'%\�@��W��.�[��<��P��B�G�}��c�Q�!sO3���x��^���x�HK	9�\&!/��$�L�=-��Xhv�D:�����*�r�!	�J��}F��&����0��B�{�u�M�e�'��9/L�#�����G��G�:W�\H��Fiv��e�+��9A��i6R���5��}��!o=�oC7�2��Qa�j�pS),;��7A���� i�w�YW��PX��8\d]��z}~
�B������F������mCuEY��cPV����dU�W�YA�U�'�U�B��J&^��j	=|�x�����<��U���c	���	�o8����s#Q�5fl��W�7�m���3p����T���;���eb�t�������pV$c/$Y���pS��J��nJ�����X�r:��]�o���/�����v�/���q�	��������H�ph�Ga����OAV��?a�gp��9t��~J��H�nJV^-/C+?
+�H�b'L�S���XI$	���������0��p�X)�HF��\wS���P�dka���hf�Y$�4y��[��s�u���6r�s��2W�{'	����1��A���?Im���u��R��r�D3����h�g�yh ��)�O~��~���������
�h�S�����W+�I�t �9��Yey�p��9��`+�z,Y���*�����6�yX�}G�$��M��Cj���J����>��$�rE	����Q��I��)}wO���{�������S7,	�m8���Cn��#���AX�A�uGa�gq���<
?Y�r�pD����#��54p?$��������{�2�b������iao��Oq�y O�\�RGa���pR4�80����$'����U��T6�7�~�<n7w�����~;|MJ����9������c��
�U3:�W�D�������hd���6��5N���x��A�_��o�#���
�/��DY����1z�����1��Vn����V<�����
��������O��������l�������:�.u%��;$
+����m�L����+����o�zsCu�@�u�v��
��~����,��A�)�
�����5��Ej)�ux����|M;d�~���o�i����]���$��������vwY�x1�a�P�O�]��1
e;�vda�� G2��Y���&+��H��IE��eC�Q�e����7S���-�L�\<�P��i!)�
�[�V���N�{�Hv��61M^��t���Q5-�
�6�23,�������G��A��?�v(���L��0�p�oZ�	��ja�� �����T@8!�v�l����nH�Tc�pC�����t�u%bx���i�CXu����'�_8w�����p@�����E]L?���/�P��p?���Shw3�[U����Z<�Y����i}o���'aIrX��}/ ,{��@�r�zxZ�6x����i�$�$/�)SV�xw�\�n��Dh�q��(�:�*�3������T����%����p�D�N=���A�:���e�3��fcw�uV�p�xd	7����*����h�����K��!�s�V7{��[|wC����v7${���������������9���%|�{$�*�lfL�t�#u��#���1�'���*���ab�>3����~x���	g�����������{wI)��M���J3	��h�B0��	H��_����k�l��+V�b��4?��]'�/G�v���GR��W`�:D��{�������L����HH
6�J��*����������S0�!zxK�3@w��Z��;z$�W�2<���YIT����2R�z����69��4����Z��,Hx�:��1s�	��bl�F��0-�}"������
T|
�U�B]���=jZ�qJ��y��^H�����C)L�>#�S�w�l��K��x���I�A�{S�x����*�2u��3���I	�4Y�EriV�p3V��
7#a�;����P1<�����H�!�w��d�	��������Ypx��Y�X���X,L���	+���fW������(�����o]�7������8��{
ha��~R���w�l<�>���mUj�pTV��Jfg��������i�[Y��?%YU�?�x������JaY�]�)�AG���S�'�>,����������K��jaR�)i�����D��X7%a�������K��{�^�Ly
�~C����j���+���(p�%aW���	+�a��pC���&����"��4�c�>����e�S8�s�|���n�z���@��������3'P����{9?����{�u�5����q:����K��E���.��O��-���l��/:�HX�f5|����>��������A��)
?�S_(��,��Y������]-q�|���S7C	Y��MK�@�	�������
�Y|��.I"�m��� k84|F��1h
�aW�P��2��{$y�ER������4���R�i	�D�K���{
+v�������p^?[6��0�>v��eUG������G8���g�!Y�7���n
�kQv/%Y��c����j�N
��;)YeG
/a�d����a]}�R������?��b���� ���	���P��O���pH���	�����YW�>�}��>�+v/��-E� ����,�Fa����g^���dUG������"Z��:�IwCv�\$Y���p���t��!��r�s��B9H�^S����
��R��sl>���������p4V'��am����]���[^lvrG�������gq��5Y�3�u�333M4��:��nxd�4C����gn�=�+�7��75��{�F;�~��:��H��U;���{������C����C��j%�����{Y����*��JY���������j�� ����]�LBYE�*�JU+v��'�W1����
��4Q
+;�:����IX��!|1�MW��3�:���������d���?~N��m��$����������:��u�s�:�c��1�	�$a�����&=�j�`�))V������]��fjZ����e]������H���f�{�s������'�{$	����K����a,�P�u([;t�K��O���.��>��>���tw�Hr�R��x���o���]kNa�5x8'�s�ZeR|�����^�
�Zl�!��R�C�m��Y���k��q�w��7��#���3�'����7�S�i<���R��'�;	��p���i�WB�i���X6�a�e$�T��S9���������XB�~DK�N)����9"��w�Y�3%\�����qx�� !��M��F�r�����b���B"<����H>�����e���CN��@Xq���{$��
1��}>��
�e<7��d#5=����=�v���u'�n��`�3�����(����v��y)�t!���c�~^����:�K�K_X�'�]�u)|�MC�.���$�
�~�N�%ww@T��vu�t9���*?p8!����>H�>�h�ZN�r��6���Zf3��U�x�5Q�g]&5��kja��������k��b�V�&��r#�2���Q�_]��8u��E~�4�Ea{X��+-l������u.�(����m9!��}��������-������^f��u���j���To��QX���%�A�>��%�u�c��~����%u�F�����p���&��_��~�
9�DB��	������]��CaU�	?��S��:p[rr}��]���91������B)��Fa����M�-g��$Ayx!T,����������0v�<eU���K�K7�:�C�]RK�"ZAaW��ZX�\b>���j/�!$u��gY�ot�CaU�1�9�u�#��q���ZYX�f:�d��!��C�.(~��N'�������cI�����1;+�e4�����Ez��q���j�5�����$��v9z���0�U+�r�D����(�"��*���[��k|�(�b�qxL���	���R�_�j�������^��*�:g��7aa�a���l���=�8���o�y�wx��A����������:.���n����%��m���?x���:?�;��I�g\1"����V�����K��d/��u���M�Z5+�m)
�~{���:���: �X��{Nn��9d����@4v�9�s@X���D]�%���
���N��.~�iaIt�BPg�D��<K�[ c9;��>��������w�YW��PX�p�����X$3�K�T��b�
;_����0/<�S�*&�Y�"3[�)	�>�����y���C/������jz������R��:��q$��)*V��7����$o�7���o�_:j�ae���S�
.��9����y �;F�dm �Iz��:����!q�.�^�{7�_���Cj	h��������51,�>T��P�wb����0��j��p��Hs<T�����P������1�p�����@���u)����`�U�$��1��������Z�t�?O����q�$�]K���L#�?�=A�$�~�;�vr,���7���G�f���3�������T�d
�#'��5x�u�Q%����ZX�����
��U��db���!�S$�p�DY�>�p����*.PH��n��:��QX�#!R����v����]�Y���� iS�A
Da5��}���r�;���7o��Mw��.J�����L)�p����]��ca��������f�����Fs��} �p��E�YK��g	�Da��B�3��K����3����K��jxx'	�X����b3���|}��9����t!,L"�i�
�*f��eQX�v�]�U�a�e�5��I ����&?�c�'���u�*gn*%\g�Da�"�C������$���+��M����H�))Ver
7E+e���B)���,Fi��$����/Du��[R�K��/�d%s�v��"��*Ua$^��Lx&�v���m�F
��>K�h����?�	������$/�H[j�	��@��"�Ax 	�:2�L7��5�}k�i�6�y(�=$�O/�+�^6v��C��O>�=`��fR�_�����o�p#6}~���/�|��7������b����]?��������V��kw����k��(����s�\Y>m����O���O$l:�Q~:�|�w���Nl��X��DN��c�T��p��[&9b����N ��������7V��a���P�"����$���������������t�y�X����zl{sG$a���],a a�Ar������O���wv9Xe3�y�����������M�Ga�b��QI�j$�J���K�� �<�+�����OIV��=����_������W��;��r{ZB�wr�B�u��DaW�KV.�;!�*p��de1iNHF~v�n��wB��"l?�n���a�Z@=+b>J������(�����$�j`�zK[�?�(�:V�,~9���9]�'�3%m���������$�g �x�n�����e �Z@�N�������6����~��W����{7�J5���"�u�>X���`��P���(���n���q�K��23s3T�Zq��u!�#����u������]N
�NN����Q��@V��8�����;�u�/QF�7���.���Gw�E�.�6�#�H;���2tM���������+��x���*V���%�������;��v���o�d��IY	cZx"(s������{"(�/�;=���F�����?���ns���\��V���<�"�k)@�u���d���|^L�#�^�����hc��qO%�D��	�=�D}f
Ij4�x�b�*%e�<��e���#7z,���o�I��v=�����w���|a�����EZ��(K���d�Y���"k��E�%&^����N�O�pd���2������t�e��U�q �jUb�������nF�}^�J���h:s��Ip�/��o��R������T]�%d@�������"��������N�7}������.W������\F���������2��SI������c��a2ox�*�I���6��
�)����aT����O�`.���tG����=w���w�'���Am��G�RRV8
�Z�c�}dM<>�C���:��=��~�����:7���l<�>��}6�S���v���?]�U�bt$YP��yR����je�y*�x1�G���H��$k>�x[{H�����CA�g4�A����h��-��������ZR�����1$�0�=���K�PVq�T8_��-�����������[ �|���E6����
��hZ���w���HVu����: ���0W��m��y@��O�U�1G����^����$T�������P���Dm����������,������O���3������������
�������v�:��������n��c�|���c���Z�����x�c��������W
�1|������n�>��HV������_�u�{����������F��m�I�-���������������I���n�}���K�_��&��t0��������Cv�?��%s�i�9����/��},�>���!U�v[�e�|��/����������eZm�c������>���M���:����e��u�X���-��n}��_����=���mz���?���$?8�K7�����%[8��*����/�L���-����I~p�/�t�|4�/��q�������g:��}�|4�/�>��6}>��X���?�������~��i���������n�������q�q��������]��7����~�����qUBS7�Z�:��<����Kc��a�B�����6����RB��bo?�e�
��g�����M�����q~�%��A�L6s^o!oaJ�:v�0������*��w�P7S����%�q�nKa_����L��~f/{y��|��x��yAc����~���y��;�K?N�'2���t�����L�/�x��&+!���+l��y�m��8*!�����������t�����M;���q���,]m���A�����_�����=&}m����~\�9���k_�^�~�����u�|�|]�y�g�3�z������.�K.��C7�+��B�v����~�����NB�_���^<�����E/���i�.�v���
�t�Q5�T��~;Y��G�3���
[�p.d\��
�p(��)D���>�~x`S?���������7�o���������
��<.6���f;E��.:����m���D�%�	��|\�vJk^����q"�<��a���Sh�j�9n��,��u��q�$zk�����'��n��J�qS��~y���&�3;njg�>H8H�w��������5�1��
��XB��������QS//��<��j�'��)��PSh�$��TZ�PS�]AM�v���c}�d��z9j��q�i�C7=R��k�Dp8rJ]V��}G&R�!'�_���Kwg6h��Y��R�����D�a'���p@���[n�=o^��N�7��u��4�${�3��0p��[��A��B��R�s��w(���X�	��n&t�O���/P�����c(��^�-���g��i�j�Y��)�a��1��y;Xz��r�b^����e���������r8B�Q2�P�`|#>�h���n\���I��Q@R��<��H��v9���?[I�nY��K�n��(���/xwv4Ub���l����fG�s1-���?|��M�<��8����S4i�v�h�x
&��J(\�n��m^6D�t�#jj������E�;`��:�����^�it�1U�d��'�PvL&�������S���G������-������)�
!��.���4���y��6���1����#�D;�*�,6}�A-6MN�T�[�*��@UzV���k+����I?�
�#�T;�M���c����?�����t
��V�e�����G����*����X�w��@��]�n��
�V�'\�%�5l�]Ox���{<�����ok7�?>Q�7�$��h��y��w���e��n|d;���$*��4�N�����Mk�:������	��}���2Q�Na�G�>�i��sC��F-���_��O��u����`���g~3��o��zv��|��K�!�����F�c�7�����qF�wGY���t�9�2��l_|g��q�c�}��H�T�(j����{�e.���~���~��������Qo`x�B�h�~�Q�����{�x��$����FX���I_�:����������kG;��}�Ct�pG;0�U�4w��<�I�X�>�j��C�uX5�kw��-X��c��K�`}� �xH����-c��8���<|G��c�Z��9����O�<XNq�c,��w`�X����c������y_=���`h��U��40o������3�;_g��o*w���T��i
(<���
���1X��l�<���i��	@r`��/M�15���g��U�_��4�����<�!�8D�;��8�w��q��N?�c��'�C��;������*u��@��x'�su��N��������r�����@;���7��v����i�)6
���P����Dx�����L����{�G�.�1�;]��Z���Et'}������t�����)�9���<�r��;�a�~�3�������������?��G7���m�uL��U�`��M?���YG6�\'4���mi[	��i��w��D�w�G���v	��h�����g���X44��v���nr1�����q���{�B��������=�0�q����w�J�v��?�HM��7�k�n�����&N����^���u.`�D��N�/��Z�` �	��;�	����q�CLc5|��#�%�X�@���'�����$�h�~~������E��8���@�jb�hr��a�l4����5��V�������2���T	�b����>+�7���5N��6c�����rJo����`����P2�N*�|v�[����v�dWqb����k ]v���O�VM�wZ��*����x��R2�K��x�p&�O�<l��;�k�OLxR���GFPy:����|�}0��5�m��E?���!�|��fq���-�1/q$h��%��d��2a1O���
�H���=����U(���;�{���%,/Tz�W�����E�R�x�J��~o
���Z@��
�Y�	$�������+v�^��
�r}7�GOh�{{c�|%��>�e�9���.f�f�����%����dZ�xZ)DX�&d�!P��j5��z�����4�f������"}� HN�%�%���������SQ�����?��1���,����{_�6�8�^i6�s8�`���@X^����)�~���j����[�s�F������Am����6��Px{��N����N�m����
(	���&1��P��6X�r����=��6iH;�3 d#z�-]�n��0�#!n��6GBm��2�B�[7/�f,�]�X�7��IuG�a!nH#7�X��jC�<��P��-������~1�e����[��[�E�:<4D���i�x�@@o�>��!*���d�����H���9�Y�j1�88 ~���R�Q���j�n���4!���
�7��\�5��6����M���h}��C��4�N�H$CZSJ)���!�\@�7����E!�gA������J\���CmHBZ��f��,wH��97:X}��Hfl�o��������)�SNpw��!�����C�b�/-������E�z���B�������F��&��Cl�d3Z��B6#���J�JA�B���[���`��A*�����������\�Q���]gD�ET%��=D)����<�Q��� ���D%bKVSU@"��U-�K���T;�e�gl�sL��L�h2�D�T]j���`��)t�(�s5�0MQ��"����>#��LY��w�F!��/�N�)���������]�@_CGi�FP=�,j�4��
�E}��������.A�zzU��)^���M"�YO��'[���.\'����N��#���`9�Ll�
�����N�������4l���6t�����j��6i���_TjP)dl�-���i�J�//���{�kdJo��R��d�@�]���AV�8T*&�q��Z�J���V���K-�J�<�SJ�0��x�(�!-Q�����D�P�UeC&�a���
��>r�`��H��T;(�_+l�p����T��T8�u7�������!��8)5/�V���O�eJ����J����U��j���&��x5���M��(��M����Qzn�e���1RY2[J���
���M�;u�<7e�~	jy#��X���9�w�^0�,BJi�h�������J�f�F�)mqVRm�u�m��R�����sP7�;R��p�|MP�efIPJ;�)AP��=�s0��BJ-�Q�sR@�@y��2"Co!t����UI����HJ��%��Q�5�p��P��6?���4��NxT�{�B�I��Z��>L!�s�B��6��;cj�1����%���J��'T���LJs,��c�'�9-u�������rs�>�0#��'�z�l�O���R���#u�lH�R��jS1621i�c%y���;^K����x	C���51Vs�J
�����8���_������HM4�&�l��/�&�?����+��zS����+��k�e�`SiM���3��5���������)��[����x�/�����AW�x
&�@:QSa����d$�����-�I5{;xJsV�2�cLm�d����9��^�(���P2b��6'D��>�=>3�k,���x
	tk�2�'&1��K�P!�i!N@(���Rl���y�����S��vg�<y�#0��(n���;�js�2\�e����J�"��������X,���7�P�#�96F���PT�]A����!���B@\A�S���Zl��^��^h
1���f��|��R6����T)2h�1ZL��6(�T	0�C>�1���w0��x+,T��J{+��L���g�����;�
�����]]���Se��z��
L��=M'JiMZU��;�������pJ�s2�,��jug0/���pD����),��J�S�����T�g)�K�@�.M�r&���a)���V�~���������t���tp���q����������������$d������%gK=��6z]2��'c��D��S����T,�>������:�'�"�j*���H?��i��6cJx���X�m6aJR��X[�['#���7c�ts���f,0�%X�`3��<������*4c�?09Z�����o�l���L���2`������.���D��X~�xNf���v�z�{�H����H��U�|���~����'B����2��}C��Pq��2	��F.��J��p'<��v�p$!�13�u�9I��4b��u�t��R�#����U�`����i6:N��~l�g�Z1���?��u��Kr���A~�N/*�
�����~R�d.����7�2�2'�Gfl�����I���C+4sL$��NJ;���H�n!�W��'#+�c�ZK9��>�x���W�2HD�\������oX�u:�����:��N�"
�������I��eU����!\#���6c�������@Jx�?�
$�	��"�dBm�oF��)�}������6����L���R���c�	6��"~��)�O�����2����?)������Om�l�C?�����b=����0/G@��H�`(�V�c�#����j�JZ;j��_[����Sw���V>�|,�����}"B�c`���V�vTF���4*���B���� 7a��L�i7��X�z�QPn�A1�-]?i�h��"`�0$�L���R��
���|�^v(�E���b�g���R{��b�����	w�A���Bk��
1��{];l$�p~�J��6����9�S���T���k��\��_��@@��y�?��q�'�]��V���������Qh�CJD�?�*2P01����!��iBCA4dk��T�
���t.��oN;�V�h��#!���5��.CBm����8&�A���P�x�z��.P��$u	�������A�Co���m�1�z*+�#2#�%#
���!Jt����]�m���Z�
,TZ���P�u!�~����N������v���O��b����t�B��O;-�J5�P���
h�!���-;�!4�����k�Jbp;���Ai�!=Y`!Y�e���.�B��	�;&�y��B�Wk��;J-G����B�����ct������0�'��h(7�7����Vk��L�E�������xvT9gG-:��`��!-� �|'�a^��'h	D?�s���Vy�_��j �X\���}w_��_��{jm��	U�ED��&
-^qA���l�I`�2�uP�m��j+Z�L����d��(�"m��V�Q����}GE4�E= ��rCV��L�����;G��Y@��(�{�n0	���R���t��QQ�?v��3�������/��"��1�$J	� Q�O0� ����BqL=:$��b��D��T4C;�C�R��!$��F���-�i���� Q�uf;�QpH�?���p�!n�(E<��F���`H�����
��=���D0���
���w�����D���%������i�����J�28��(��'"~�A��P>�1�3�������t8OKe#.�Y��W�2}�ab�np(%��p9U�4@D���^:��<F��(�� hIQ>��@$��g���c'?����@-�>����h�@�'D ������G]�Lh����5$)��[[-Vc��B�Y���������������1�m�`�o����3�jjH���2�����S/���-H��v�O�itD:�����r���s26?�g��&����=$�rf��o=`R�"\�9L����0�.�b��0)_��r_�&��nT��0���R-������J���Z����R�Xc�e�%�b-��T1��1"2`Ww�dcV�S
��zL����JJ�e4?������yt:T���-G����~F���zc�����R�X�8�Ig�#��2#=R�J%�'
���ay��p�c����~���[&�>���`��rK>�S���F�d��X
�;X�w�f
,���$wI���Kt�V!�S����F!X
�v����byR�v�8�d����f�.w�.�9szw��xdNdms�����w�!1�zs�9����LS���	������Yls�����Rs(���x$d��n��M���\����5�~J@87i�A#MH	����+�3�Y��������l��FXL�����/J��t�
v���+�����8�Nu0T�������>�u9m%a�\��}/'��ljZ���������3:z*Uv�����Q�Gr��T�Oi��Q�
G�H��)
�`��`kY����k�LY��!�����Y@���%{�2M�����\$�[J���`N�����LiM#�F+�S;�hCJ@���~[�w!*GO����4}
��;A��Fe����L���a;�6����-zJ?�������/3���.3�k�YZ����W��z��vH��V�	u��gA��][���y�����m�B�������AD�2��S��`�(B�7�S����b��%9;��0�nh<�I-����<i����4zv�����@�PmQ���"�@��VWF�N��~g��&�0
��'�;��s��K�F����Y)$`Ty�9����Q��J!6��&��@
/�e�t��oA�?/8��7��*�AD�#��7@T�dDr?�AT,���t��U�.D�C7�e��<=]��:z6�:Y��s)}|F������<��Dv���B��]bE����LlR6j3����S������lZm��9�*s�7n?���A6��R;|��R@oL����r���J�1b@������K�QO����\���2o	�t������6��p��hIX��T�2���:��p���n�LF�����@�s�K�y����Uk�%% S��9b
+��|�����v� �i���Z��#�������B������hm�s��],h���aS�i������i��\ 	r���k��O��,��0`��3��
!���6��z�)��$��CK��v�ACo�����LN�6z��9������Si���)�n��Si�c�]Vm���t���	X�P���F�����������]���B��Z^iIQf�����Y\}~�@���T-�,���Z�������&M��%�j�O���w��%��?m�9���Ie�/�H�����F�-u��P�}m�NuEo(���f�7�7c�� #��������$[� �I���tB��W�jZC�%m��lC��WoD+{��v���E,D�`,zRD���iT����t���y��.z7����8�������E�U	������r�6��K���j��,^���6���U�����(� x�o��}���_(@P�x�-$��s�3�xZJ1���fx�
�F���V���z
q'Z.P"��#��pJ]b�F��
3�!�/����N�X+�����
<����	L�D� bj���\�Fm��@+'����T�,b��	���v4�\A�A	�\��\��D�HgR���.�	��)�1���_�@�xa�A~
z���v6�2���uCo�,����B�3���8Pj��t�u\�������d�4����j�8�|���&�>������%P����i��DD�N<a/v��b"z��@� ��H���B��
wN����M}�1�Xh6���&��:+[A��ay�
H������n�����c�M].f�X@8��V(����b����)�)Q�^�s���"RDK��mPPH-��"���,�����4JD+���k�
b�f�
��0����j3,'����$�bGB���	$���n��eH�wc+���A|7�nGB�b��4�,	�����IK��s "��C�Ib8bA��b��dg��vI����y�b,�@(�~:bK���*�P�M�VoX� O�]�A��yO��t�p�����Z�[A>�9*{=�<���]�gcEX�v/��C�!�!i6h252����H�xb]G !��Z������BSGB4��	������PC��������"�P�p��NKC���|20�V�!Ce�����dB��@�|N���������T!c`�Vcu�����������R��v���g��|&Yv3�V�^���"�����.�����(��"V��C�4�i��M
����zI,*�~��D*XH��5bf�D;�J~��j�^��B4�8�
�k`afH:cK�x�}2�u��s����"�O"����|�}��h(%�t���z��~�JU�u*5
8������y��<�+��F�U�W���50�+7����O�u4K_A��&H�%�('��q,T�[{�.���PY�xyh"�c���oB`�PHOr�-K�M��=@(���t4�8�[�n��G�� [LK����� ��A���*0PZa_��q]�[���]@�����w�?HR�OaM�0�����FW�lL��{0(p������0�����"��E�Z�B (~���*~��|�w����O�n��N��~T{S7-��^�-�6fi	����Q�h�Y�d�=��	���H�F��#�2�z=t)�}h��}h�R?���zeFkA7�;�I�\��)�7���!A� 
Y�n^�q�h1��������afl;*���F���Vk��p=
d%�1�J���9�������JQe7�����A!�D9�_�����%4����G7���,�~��P�}����Qgj�u��Q�a�=y��a#�)���d�e��p�M��C�0�K���yxZ8��
�C"�1�D������!-��A:Y����������	W�)?^v	���J��F��9,j��N����Y4|'.�j���M;	�-
��,(�^L�QFR</��'�#�_
���qN�#�)0~���s�E�'������I�v�H�0�_7��m�z�"UJL69�o|�=���H��1��V�Fi�h�9	l�JB��/��119�<^���-{�7���6�K8�)�]ui�8Gr�
����~QZZ8����V����;<
!?���
)��'�������������bL�@�9@J� ��F{�����M������B�R���te����}������,����|������#5Z8c(���yJU��W��()��,���#���yEZgJ�lWzL�mq�<���G�������de{���T����u�@Cj0�%���!�0��`cb�X���u�&���T�
 �:?���l���L8��,�;�41c�����B�v^s�7�e5�[������b�Jk5��%zr������.�c���|��t����#�e�)��o���2%jS:�6�R4�����ASi��a���6�i9>=�=@S�1�!w�>YR�L���G��S[����|�$l�"@|��I�8�L���$�Yk��W����6�Y���	�����H������*M^�j�N-���d
�����FB:pJMl���G8����BN�A�V�W�M�zn���|���DR._�
��T�rQ����U������5�<_�Dv#��V*�6���������X��R���9�#�2����#�����P�ci�D!�J�����<���i�$0��S�J�hM}�f�PGb�	�d7k��4f�zP �
�T/���`�e��l��1	����*�{uNy�X��� 8�91�-��P�L�kL��6�AX�M�x6��/���YZ
@�x��'�M��y�c����T6��e�)������|���U�X�:��#�2e����/4���#$���`i�\��$Z\i��;���G�Z�jl��
����gJ+e>�#E��!�;��y�j�cmO�QzRo�C(d�c�^5���)sB�K<����UBF���|K@���^%�8��w�X��*5i����A��UBJI[�f���Z��~�!T/�Kd�K%�b2�Pz�RU&�"O:WR���('�V@�\�6��e4)��b�'��
�z���'u,�
!���#����-��r>A��B�xmPx��r8,mK�XGM>+}$����g�$0l���D��#=�N����	��BfC=�>_�N�h���X�ObV��f���;tJ!S�@�yXt����dO�eM�/v��'A�JH/.���(���~��
�n\����<�S,���\L!�������J��%�}"����5�K7�L,�|(����u����A/��9��wm�F��\�I����{����0}��y�	cr����	�������%����x���n6�zD�G7��1���}�H���j�o��h5�zg'[@CFm/q����:����)�2�j����j�u$�Y�J"b!�����V������6�Dwr��DG]:�3(��Sn�+d
r��t���k�KA+�6��0�:�3�=n��8�h���5��uk����������j2@O�����	��K�2��\a�tjw����������5`�����M�1Lq��MoL;�IOZab6�#Q�v�;E
h\nH
d�� b6��UC�|�]n����[����@>6j����|���`@��l-��B-[+����sS��������~b1���7��~r�+����~���W���O�[
�2�s% F_+]����_�����@B�=�##6���Y�������|�+�;�C���"�$w�4j �2">�t&�P�����z����{�wv�6X�05��	��@��:��4bJ�������9�l����=��6����_��`yN\.��v�?a�X 9��t���4{.��h��VP\�������Ngmj���j�O2�������%�di����7s8��	�3�'M�w���D#����O	XmB�n�A���S��hLIY�����jw2:8`�kH[1!{� ��������*#Z50�� ���@m�Q}��������s*�������Ok���
����������@��O������w,x5��=��v��gXa�18KZ�z���:��k�����X���t������+���|J��`� ;J#|��N:&fhfW@2>dv�����3���h��{?!��~R�����q2V��,*
F,E�:������<h�6��F\�>0E@��4�UYC���Jc���=��W��4��~������P��T_��#���2P�6�m�������N����b�%)�������5�������;���!�����l��@�BG��d���Il6	�/���@bs�K2�:Po���I]��/��Sc��c@���&:A,m�;`����k@�����ZD7	�=�`c7�w�!X����z/����8�����0(�=�>NC���
���0��9��m��yk�;���n��6 F��@(����M���{�T6��g3'
�!��>�,��QjaT2p{�����.�xP�1��*P�C��������r#�n�]��ab�2��v+"L�Q�x���l���V
yQG��h�D���f���R'f�f8"�p���QZ�s�|�<PQ/�D���x��%PQ�4��8*J���n��P����j���w�z:e5�%��6�F����(D������g��&���Ei�3�>\T��l�;��eI�!��"c�u��
���B��{�����Di��Hf4c�c"�E!K*� U�8&&.���� ���Da������ng�K�$�����1Q>NO��r�������$�����"&~�<0��
��*��\*�K�D�Q]��!��P���)��m�u��v4����K�S:�/����l��T�������`(�������������&,�De���V��n<rZ�%c�om����
V�/�if�(d�E�����	������I�9 �n�vl��[�
��+�	��B��.������^���'�B�$��%��5(T6X1����r���K���*��R�6�IN���i�)�B�R�u�`N�����f�e��Y�u����mhl�j"$�
L��JA�\�Q2N�M�QP24("^>��z��)�OS��->�s�,2$KS$�v�����B�-J��X���D��)�u�H���i4i#�4e�+��RT�(?-����4�Qj
���'�������]��-4N�B5)�P�$�����:�t:.���p��s/���3�@�T��J�W����"�c��-bG�z�dis�d��"D�����ub�f:�}�B>�BI!����v��_��Gi�F`�q�jh2�72���+BJ[�K(,V�����j�%��|CS,]M��z_F\�
�"'��'�F��:��,3��S��ola�#|��IO-��l����K8~��N�����16�;%{��T�t�o�n�\��T�z>�J�t)���/��J6Uq�hR*^���M���tn$�1�W�w�
�/1����f1�>v	�)U����0��c&�3�&2������j:�*��
�u[��&o�v�%#��M��md��-�x�ht��2'�:��q�����6�&��
��
�:}����^��6j��:�&/+=&�u�J����XS?�9Hgd����1:)���������',/���!��)V�Tx����e$�
���b�j�������{�O�*T�r�X��;����1O����@T�iFF���D���J	�m^�}V=}8��A>�H&�F� ��o������2&v�=1�Q��ij��M�Hj(w������E@)��4�~@�~����O%
UB�[��69�OO�xJ�9V�4A%y@�4����d��n�Q�6S9F�����$���+M��I���s��zf�������q��G�n]NnD��WV�#Voi��y$�P!�G��C- �B��T�
�B�1�G>&vh��&�dI�4g�D�.M����0��@�5����P��mV��P�=�%��"��&��.����Z�
w�dP�x��-����+0�x��2��,��)_���_�<���P��yjS+r��&�%8�*�S(��i7�r1vMZ�V�r~jw.p���%���y��)��8@��4��6�����Sxm���A���R�]i-�Y�����Bk���4��lG*1���)��y�RIs��R����h�T�k�[��JfC���m1~;�����f�&�QW����u�5�����[�t��-}����i�.�D�	B�/A�U�&<��C�a3���6�X~8l�K�6����+�M�}�l��r(��)Whw����#uK�M����B��Bj9
�Z�%��?�g3���=��6���c�t-���^}��\Z�������v�+��Xy�gQ5�E�v�����so)��������F�fl�1]em�d�LTEV
%U�y���1��y?��s��nX���[�4dePh�vW'�_�#���s/���7�F��=r���l���1z�0�����mV�f�^��f,�!��e|{�=�2���H
�����K��S���j1v�X����,��-#m�@����o���b�+v�WOl�'8v�s������lHy��z�3�Y�s	?����}`����BR�jE�)�,�0�3p�#zM�'$U<$)}��6aK��������O�{�)�S���R�;_m���)a����[lW�:O��6`m�x(�(j��	8���N�~�TO������ZU�r��W�^�$�.��k�K��N�L5Q�s_�0w]gG�q����I�I�'�����/�N��fv��q���'��uh�������DI-���)���@3�d+�J'�No�3i�
���xBQY�]�QP%�����K>T��U�<���"�A{���"$��u�S"��S��{h�v}�z,��R�|j3l���2���f���
�}���x�h�'�Vk�������j1��C�Wj;�7�PR4N��� �x�������4���W�M�c����n����0Hf��1��c�w 3*)v L�H�>��t8�@V �^!����4v�
m>���aP�G����7�
�����Q7�v���-�O�K�k�;J#6Z�w:'�@��b�lYU-md�[��SiR@�0~,����.��h���e@ ��9�_.���Yr����������O����*���@��@%"�!e(���t�$�����Ah�ES�<�c�2�Am����G�1S0�0�~������lE1��~�S���"����@C-�'Rh(DDR����R��?KRFu4c������X*
�J@�aA%"��8�o6�����&��x���������K��Z�|��p���)�m�X��!���p(~�i�!m��S��T��%
1��4"�fl1�H�p�"��T���!m�����y���0���#kC4d���^�������Y���P�x�o$b���E��w�p�DX�t�@Vk�wW�<�: �l��p,,H	<�����a���@Cy��ly�t��G���B����"��K\yj�1m�����i��2<kl G��P����	x����r����4���e`��]jC���5
����H�#����B����h�D�-������q;F�]
DL6@5Q�(�Y ���C���Q���9"���.D^;"*C�z\?GD�����@D�!Z��^\ ���#�"��O
��m�Q]J�����(~��O)�.��K�>TT��b�Q��UO[$��S2�|8"*6��3GDiH���!�#JC��C�&JC|���T
�K2�10Q��$�����lCyC��.0�7d��W�D6��+P�D����W�.���h�'s>�Y����Vt�D-���pL�/��j%j^���b�v�B�T�~R����+u4������NQ���5�8��n�(���9�@?v��t�%
�2Tkg��+i���8�%�5�1Z������)�����6�O/������� b�@D��2�;"J;��pGD�����Y�t�x.�cFH:tKj�DP:�Dl����-e��n�u&fGD��l])g����>�qDTf�P���FI(��|����VQ,����6Q���kD�� *�+a�T;����n����0��Hw`�jp����t�dX;�-XTB���4K��A[���)wRc�
��Q���~ �p���C�XCH|"3R9B&�B|J��S�1(�4���y������5��al;���8�u���vP���e����m-P��v���`%��vH��& ���LY�A�
-�,����
-����7��7,-���9Z�S'������F@����+�-�nP�	s�:���F�l�(t����Ta2bf�euRHo����/�2�.�/���U�����1���v���4fh�1����l��D#��6g ��4��J7���H���I�`s��/`31������\�^���c�����x-c6��,�Pkj�I�l��t����`S//T�h��9j1&�6�Y�)_��.~9'���A&������1����`S-_m����=2S@��)�l�>��
����&hb�!(�q���A"r�M0���a����d��)]���I2^6�L�p�L��"���-�(�4ik&K�gu�������tSGkp�LI�X���{$��U��[���e�����@�p)���TkSD����@�k�)e�@��J���3d6^WT=�w�;PM�r��������sv7�v^�:�o�����
h�/�.�f#:����+����A���B�����f&z�@�3��d|c��%s,�"&�����1A����;S�b�j��a�&l��g!��`���~X��^�g�e�����������7�3af �0��s7��9��3���9�?�t(��E��<IsFrJ>tiG��B��9gC'�����(��|���_<�8�P;�s������d���t�m���[{+� ��7Q����R�B~��
N��b�4iy/��9�$f��o�y���"��]j�AS]t������ieEp��HFg7��[7� {�,���h���Hh����I0RQS�(h���@�����R��Q!�FBoP(C�~�w�}czI��v����� ��c�6���t��c�R�����(T�44�+�T8h%q����R�u-��\��o�*�P�������0��0�H��$m�%���S
#O����q������I�gs�YLL������dR���m��tKO���d��"�v���P��6�,��x#�-Z�UOW
����MZ��1U��~��K�nKw�%������e/���B'����j���=������Kk���JF���(�r2z [�*�d-��P�Q���Uay�:T-/���E+���ZGU�u	U�/PU/.dv����65k^��������Yrqqn��q�����������d������6kQ"��W�
f��Y-k	��s�
��6���>et��h��f@"�k{y/^pk�c�p/�D��Z��^�<6�Y��lb0X���sr��b������f���7���]edA��w0Mw��`��T>��V"��.P<��Z�/W�m�y��s�LV.&���	fc�L��X�,����Bh����x�4���Xgt�D�0�D<-b���aP��	�)�,�aCihj�� $3�:�u��f�?����l���O����3>u��f0>�l3��"�3��J6yQ��� ��b ��b8(�j�<���
�>?R��� ?	��8�V�>s�C�8������P�=^w:���3�`P��Z�A��Id
A�q�w�;J�aq���-�Y�a�����Wb�A!b��0������ H����b4`P�a�f3\�:j36��v$+�{u�A�Y���`�������/
�SB�@(���z��fXqjm�������co��6Ztx60NaP�fc�b!�A�a����A�'���[U�R�����yJVy�HL{�b1���@���;J�+@�N�
��t��eH�zG����s	�SD���������Aa��<
�
�\ �m����1M����@e�b����I2a) ��V��Q�
[y�����@�~�6P��~�EL&R��wn�l%��l��������\���B���������P�=�*�<e�=�"A���m ���;�����yZ�e
T�]��!jm-�^��������1��-�Z��y�S�x9��N�9������Y�e���20Ob�����I���e�"����Cu;k7��iz�gJ��XA%2}�[��b�6cN8 ���
A�"@����J>lNk�(D�"��{T����-��j�z'�%��5�-IFT:F��O���~�P�*����+T���9�3(�F��X�WHa���(�����v��]��6��
����i�v4�Z�))��!��Gf���!���c1��ab��9	4$	��a���e�8�D��0[2�,���C��-)�s���l]��gM�M�����~Y�VF�:)����RDkbN���c��
��%���������r���KA��/=,�N��Cy��S���YZr�R!�S�+�C�/CP�p8��:��)���������Y�a{�Ou@�XFT���!}����
q������
f
Q�V!�V�����'D��R������4�z#���1�,jkt@dC�D;��vN�m�!�C�~��	ms@�aM�$�'1Z�=�D�kVi���'0�sD���R�D�|ej(�����8��Q�]�"���_����9����6������Z�5�����B��U�@�3Qi1fU�;"�![�@zI(
���n��
��h 7�]W �/�S6.9���r�)W]�YD����BL�#b�!P���xQ�:"��hl���������|�[|�%L����b�C�(Wc���
���?�:T�����BA�	-L�N�E�Bk%L�!E�����AQ�]�B��\(����8�l���Rkc�o�hF���D��%�
/����AQb�y7!2���Ei�q����~Bi��PH1Q�a�[(^qLD3���f�3L�p�1Q��uV��1Qia�K�
�1Q�]���8��J���,FTf����cDCE|���	i�����zS�� l�������ha����<�=�p��_�t�2h
e����
(���q�4�C�v�Q;�����"�N����r@�yN:�UXm ,pq*��������Z����UA��=�����k�=��hc~lb���6�V������6C�Eg����,yY���:�d.1�]7�����m
�
���A�"N0�y��xw�B����$�)�K$����]����J��h���������f<?]�jyi��R|���ZA�
C�|������B>UoWa��V;�6������
�@m.�M��*L���Z*���q_SP�m1R=�p�Ji��D(�-0��
a*s�%�c�o�,���^O�����<yxE�������46���l;"Rfsi��[�
q����w2�}���	���,���s!m�@|7�l���j���M��X�3�h�)8�sM!�j4�gTZ���Zp)�������*U���J�J������7j;h�K��Va�0S��f��s�"V���B��2Z�����s'�)V%����;>p`���%j�S��m1*�.��l� x1����-�����i��<}DK\&���\cKa�+Fp�F`%l�lI`�~5�3:��gU��x\Z��fv3�����z@��2�e��?V������I-���
�R���^~CJ���~���bi�ZU�|#��T|�)u.��Ko��x�����8�B��-����3�<��:��U��XT������n�k�����K�KIi�KB�3���h��)>��8C��:5�����Pf��J��#- R[c�?PK)���S�I������ubGI�L�.�v��N�s�M>��zD����})��;LJc�OB�]�qR����l���4"<�s��RiRJ�j
jP)�B*V)����h@�@K�5A��J�J��Wj`*����s�wc/�D
�����}:�c��24���:��T��3�d��{\)��+h����{y���|�Gb�6~"O2�u�C[�
���Y	�>�=,/p#�	��
�f��h�q&���J���Y��,T?��&(o=�����=�Tb^�a����!T���4t��82hncI��&@T�nKXK�D���@�)��>
 J{�� �_�P5U�\
:���F��F|'��0#��f�7�@������*8��
1
,2�(���]Bz@)4���q(M�R,&d�=-7��Lq�~��uL�E����,��gW�t���Q4�������0hl%0\�`*���[O���q����`*�������i[�dCd��z<
Yx�9;��9�u�fL<|H�X����R�����~U�R����B�R@J�^��R�
�~�vL����n9�[�����l,�^����=Sj������"���R�����m��0����`���$=i�F`a��*������^�c�F���J�(�%#z��]�i�;�'��Nm��pg;,y�L$�^�+_Ek`�~ o��"Z�L�v<%��q�zm�>Q�$����-��i����
��a������#WX�Z�����!��A�|�*t��������ADn_�x�O+�������^������\]W��w. &����~B����kv?-`�p���?4b��|?����w����rv��F�����P��;Q?i�ls�����w��'��9�)m�3��~��Nfz�n�QE��6bI����
��J
Y<�N0���dquBX�?��b��[!��\)��[_h�T�\�D�j8��R�~����
+�?�n5B�<�;`��V$Dw�S�'�b;�i#��
R��?i���4H0bk ��>�`�]#;�I#F���K��x_���NRiD>���l`F����J�
��
�@��'D�@>�_	]/���2�>����a{�,�A��@=��2	�������,�c��|����>���9��gV���jW��K��L�����0F?��x�u�����i+���L+�������`�?49����O��RkhK��R����;�i#,��0�##��0��u��\q;���]hw�����7���P�y{���h/D6�a�Yf�',�2��Wr�
}��a��A��X��g
�_�|���O����(��]����c�|�#Jx�S��O?���������#|��?��^4�><���G����_�%;�	>qO��c����eP`�2�R�9�9�����!��~���j6��K���	�h��������y��K�����$����������H�J���B���#`PX�)dS?��5cdu�6���))���@�+�7Zy�p�N�����kT��3����R�g	��y�O�'��k�i�!��=E!��~�.���#@PH��O���(lh�Gh�p�6����@�� �s�6ld3i�G����J�q�C����l�)q�����P���l��0�F�p���2vz�a�fHmAoU3��+e�d_b2ki/Z���H�{s���C���=���'=��y��Wk����Sgw��O��t�gX���u�q��=	:y��>w����\�������C;�	F:�����/Kwg�x�\�� m����`+�Nm��e;R�j��E:���qG<4cBZ��Y"z�=�Q�j�3;B>6�R��U����~��'���O2��L�>p,�A�P�1��JG@2a� ��@�*$?iy!�������t��X���	����'=�|�����@�����{���i{O:�J���CU�/�xx.b�pj�9i
Ti�4r* @�9`����J�����A_;&*ClVt���V`Go�#� m�}�CJ�"�1�
V�"y�����4dNx�vP$C�\�!p��(^��'5����w���$����!(���*�P�F��a���f��Pl�e{5�6ta(��9/M9(���"�<���x�X����%��<�K��L��p+��#hg�[A���s�e���VE5����wS���J�%�]
HdC�-� ���t��A������"�!�0���(
��?-
M6d�@���i�9���8�
Y C���l52�>�@�_S�������No������3���QK�q�%���RD�j9�j��/���08�k��|x���@z���8� �u8�F����[b0'��r@�[A:
�7^U���H��z,0�\�~�E�c����N`f�1�kS�9{��oGEi�j-n�W�P��� o���'c��H�x�"�s�wX�{2gYG#�A��
5���0e�:*��	`���	$9�*��T:)�*8���d}������ 3v<����mI������R/��Q��B
�h����S
��Ix'����Mk��-�H�w:�jZ����6k"�a�Z�cl�z��c����vS�7)�7�����%�-6/x`%�1����z�[f1���2�Q��jNJSbH����2���#%��")��L>B:,��6�����N&�+����������M_��$+!��n3Hb�c%�B5?Qg��BE?-��f,vvdl�RDe���#%�ir��P����:.�r�L���_�-iu���5�������,���������
u��S����v�O`
E��;�������5�5����.6\��2��%�i	�kZ�O��d��1Jk���T��A&�\�8����thJslr�%:h
Ml��F� �G*���"�����#|}�O����Y��G�1���J�"������[�����i��x�O�	6�|j
����S,���k����,O��*v��Q6v�c��;x��6/��=�a:m+��Z�E3V��E�BF5�.�t.��S	���'�D���YZ��q�N0���u�)r����� S�P��������F�9v�-���i"�Np3+K�v
�N���z7*�;�&���������H����������d�MF#n/���@�������7��~;��8�G��j�7Z^i���q<�3���������S-b��ei��y���*�:�����������J��i�����P2|\H��K�N!��)aws��`Mo�u:�lC:����3u�a����T��'Z�}��T�6����
m`�V��6fn�B
���yY���0�IW���<�>Zw�<����Ki���[�)��l�9hg,�LE��J�d%��[�Q'��SI��W`�������J_p��{�2��r�To���d-<�B���U��]��x���?j��26�R����$����^����#M��TZl�&�eY�h�\L���JZ3���*}��`���M�[�&�50J�
���j7�={������K�k2�9�=6�	B��Ni��>'f T�� e���In�l
��h�bkN���hL�OV�N������liw�B]G{�`Pc�Oh�O6�0cYnoe<$�d�by�����D�R}GQ�����y��/�}�����w�e^���W���0������5�}WK>�9��1t�y����Z6�K-'rX����r��/�Zg��0���R��,�������42�R�NZ[��A3�C!Xi�j�����
����m��
����hi�
�z��)m������&��M+8��9���D�&��������qM/��F�h��T]l�|`��_��L[����"zQ�I�\0�+�^���A	�fR�D�����;Q�H.|;�rJ���w���X�F������-�y����c7����8����:���DsGB%����\/�Ph?��f�s$$36���������t�����j���� ����P[�� �}��!�d$b���f,�XV qS`!mF���b���e#.S�v�JG;����:*�F3��������[��eJ��J(��G4��[��4��+�o��-#�}�g���D���aV���tw8��]?��
f�h�p�����P�K�[�T���*��	Q���I��X���'b�E��'m���ez����Vx��Xm��N�#m��v��fKA'�}��=����D��	h�2r�H@��6��=e^�����1�p��lg(�����U��o�����]�C&=�B��P��U�/f�2��d~�x����dF��s��n�0�3<s���y�`
�b��*�g8�23P��C�bLjG:d��`��?%�!k;Dr�?�D�2G��	u�(2��v��v�D[��6bJ��*�%<xv�DltS)X��Dg`�������=���,�1��:K��b��:��%=�/L�����J�B
*a9u�Z���L���X�s���p�bjK��`���Z���X�������(9>��?��+����ri�O��SS.\-�Z8snx!�J�zj q�$-^�}+��tk"���"�)���7���E�
"���\9�����u}��`�H��'^ZELI����0��a�e���O�aR�gv�@��� �*�u[��6�)��m���~�kpi�0�=L&������R�86E)�!��$�6N
3���������H�8��WF�����o�W`��&��UX����K�<Tv{$)e4r�-����>R	YZ�FN�@�x'e��x��~�w�B��#����#=$y[6I�,��M~U:�z���A�/��I)�����0)}l�Rf��~E	�����$����>���-!P9HJ=V���7�x�BZYz���4eM���rG{)U�:J����er�(�l'�p��W3GI�~%��:P^�%�����t�L�k��Jci�(i-3����kB��1#5Y�[��a�wk�r�ct��=q?���0���2]T.��'�c��:Y�
3��@�(��2���s��[�5,�=���jGL�g��	��h*5����UoKw����6Oh%��M-ei�T�VS)��M�V����~s���8%^y�������B���HJ��t�.v���TF�����V�K�q�����/��<_J��w�Tk�g3��H	�������b-|�8`K����c��u��w�Q.�d���M�C�t�.PS�yw�:6Y+U��J�M�N���&����(�t�SqF��i���6I����`��/$B:����&EG��k�;=&%���E?If���o�~����@��xu(����O|7��X�P�e�Y����b�����2Y}��m�A�B@��T�P*����C�o�2Q��r���F(t�Jk����v �j��
����� Q]Hz���������B�6!���S�L �2��hM�$�&-��B�2��`R�Q�N=��IN�#)��%��S�q`Ah�I�����J����@G` ���-M��Ow$�YOOE<��r�&��#Q��V`��4v��T	���9��#)<�g2�}GR�el�
��@R�4m�A��Qi�5�����/<�*�q��MJ!���x
�H��b�X�/{O�Yx�����_���i�n����/=
Q�������DUb������)m��U~�+X��f��M��C2�GT2i��`����d�UA��!*�R;�f��f��-z���[�|��j��c
R�~
9E4���A�SQ����r�+!�O���8�S�*�1S�>O�&�=�L'�Q�L��MS"AiP0��4i��T���NJ�c��,:�S��*0��h
^������2Z[�0!�����4����u���~�����K|���r��8*��T����%8���hz.fK��6�)�O�I[�kI.�v4%������*�,[��*�T�Rk��*^S4�-�_�C��Mz�H����������#�LzYOa�~,����(!��#!���4�����	���B�������T
��|F�y��2�B�V����x*?~�
�h��l	Ma9*���PAS����)<�����+S��M��Qcg��z
+}��g#��S��rC��%�R,!��t����������f�R�Kem�i�>���TK�I�(��K`)����nb1,R�d��)`������ou�R|�/�R��HK��^������I��:b������[S+;RB&+�!��c���4Qh�,UB��m���MK�9V��4y�ZWm��
��5����k8��r����J�W-/��rm%.�������*��h�� �X<�bC������H,���R�������cXJb��1��f�R%fK��.E���j]67��"U�R|2�U`@���T�d�qfy[�>��Q�$3b��LJkwi��>�g
I�����CR���/`R���q�v��`����2y�(�G���M�j�d$h8
B&{"�_j8���Y@4��cR}�����]�q�R)����.7,��,���t�a)����|��p�X��.P�K�+a��-�i�M
K��7l�H9�X
b|�Z~c*��<�I����J��\���J�z`)��'��w,���BGN`)��tR�K��aAz��Rm���A2�uY��&�JQL�<xR�E���Z�a"/;M�}��K;�J�76"h*���V|����G�38�&��q4��i����jQ)��4����TJH:RIayI�[H*���T�-���s� �<�����T�]AR�q$���<��%,U^��`o�D��t#]H����H����^,3���I�2Sl�@
bZ��&Li#_�L��UO��&q��
`K6h4�[�XH�=�����HI�W���kH���A����h���nH�>/V���Ui�&�P=K�JMV�k\�����e!,���XBj�<,UO��)�D�k]1�I���K�����[*�2�zmK���`�|5+Q�69'.�[�w�6���@x�c
�6�L,-1S?�V��-bU�J�*gT�,0`v. �H��-��#�,;����vtL�[���zp����wI�&yh�Z������;_gd ��1-��{N�EmCZ@��������c���Zx)��,��F\$��
g�x�N6�wp�R}�8%���oG����U�z~b�\8ni@�c�P:�>R++Y�/���6��^�!'��������=N��IL��r�u����I6��v���%e����>aS	dS���O��c�����ul��:	�}���D&n�tx#�A15h���S�@"9�h	�c&bqr��"�,Pv�S",K'��>�U������w�+�/��t�S*s9a1��:�)��iY��9��M-�m
�]&���FO?M�YG@�| �
��u9�G�9�Vu��g�]�����	�'��������X
�d�hD�(dj/���
�B3�B�9(�����P!��������'M�2R����/
�'b��^cf��t/������X�UF���M s���J@�������+Lv�4��&��ixH��vOy����6�;�����w����+�o�-�zq%��Y�te������t��^j��^P><���G-���X)N*v�=u�8	:<�����Z��B��w���gB��#%����G���'�0R�-�<%�V:R�-�
���Q�qG@�H)�iwrR��}YJ=)S!:O�#���1����GsUb{��B��LVI��U(��JT&���xp�Q%�6D�U~����j-NVq��zX����)��y�WV;R.K7�'3>��cz�q���?*��[�}a�b��F��	Vm�dQ��[�J-bv��B0���x���*��g�*���l�m���J��J[<L��,�=�
��'LjC�l��$���?K!��y�6��&�����������^M|"��~&U�l�>&�5>>�@)�J�]����]���zC0�0������sF>X�3���3��$B���� SK�r��V�J�u;B5��BH#�%���)�-s\#��Wm�U%�]��4fi0@i�@�7�x�����R�b�����R	�)$T5����d+�jDDI����e�JeJ���T�W�n��op�J)���h�I@���1�*�O���(�w�p�X&�G�iC|y�{U*�I�����]�A�1�%�2i��~
w�z�r"x<Pr��W8�����O���2k����b��	S�yq����H1�}K���;�l:�z��3�5~x&�dDEp���#�KS�N��7��MjN?��#�Ik�_��#`Q�����=B&�ZHS �M�1�%	FBz3i%n��?B�n��G��5p�T��Axc����I�~F^[�c�9:���J��
�\���byi��\<
^������zqQ��B��Wj;���������,�=i��2�x;�Z�;�*lI���Q�J1��y�lGTeR�?����"�MZ�[B��vD�V;�����K-E����h��MD�ZB���,q������O�A�PB�@���u���o9O�A?����������k��g�U���X�����.6�O8���y����M�7;?B6XTaz�O���`�m�b�
"�sz��*O��3�wZ�~'�7U)^I�J�7����O��<��r�b�dC����hz.��Gz�h����0�L���l������7��H�����t�d�(X3�s�����U��V�����1;iLNi �i�\����@@aPi��!%�GakR
�O�h?6���=I�}�@^�S����&�=��X���t����@���	�:��rv�������tQ�L?�Y�x)����a\�h)~���X����������)o�8��o�1dF& Vo��$���z������(��=4���RY�U��T�9����:��JeP����A �t��;O����[[u�\JUf##�a)����y���J!��L��������t���oA�������T������}���J����`��QS	������=���l���P\��)u�x.T:�h,do�\����=�����#V�:�
�=K�^��R�B�V�����q�~8���KQ����������}o���'�T���7r�
!�9���"�2��m[�k�����5����I��9���r�l��A�m�T��C�����D�C����Q�7�2����Qi�hL	�-
!}6�-pT�_:�U�qTh�I�$(vBF�JXG=�T�`����@�&������-��(<�BG'-���^^BQy������E���-�\\)��{N&��_�Q����t����d��E�j���Hx�<��y"�r�L��nd�����L
���4*p�9?yK���6gv�U5f��5yz'����5}B��	B�0���5�r_��$7YZ(��z�s.a�Y����l�Jw5�����8r*!��8?P�����*�[�6�����3�c�u�7�N��(�����]��&,��N�M������EFv�"�Z�Si\Q�����5�����R�
t��m	�B*������zJ��:���)d��O�S��LDO�������/ ���O��V�<��O��c��%Q�6%������`MZ�	�8���aq����i*T��qg�9=�;zJ�u�J���)�x���zJ!��z��wJs����;~jM,�����gb��S�Q�f��.t�h���T�= 
Q������O����>����[��9��x���iP	>�r�h��o�O-#fg����U������LV/�R���i!�T�%!>�:eJ�����K@���h
��@��a�q�G�Z�N��jM��Je���&-~����6/eL���'�;+T	Y��tWZ��
t:IL��[���ZB����( $�z�5t���	�tH�r�sE�2����zp��S?�z��T>��S�]>�3��7�s��I`�����-�l����n�)e��
H�w�TB,(��s>�S��6�1�Oi�b�����O�L���?A��fT������V����9}2�x�Op�4��s��^��';��q�&o��W,1
�w��N��O�T"�h����;�+vAy�<��2��N�	�i�7�Y�i���'��9p���Ps�dp��WN����8����\\N�w��V=3N�6<��p�3����t1=L,�����l��Z��j%�h��Z��2Sl�V���� D#��'���hS�z{t=[A\�6HL�~EF5I6J�������l�����1��}%���w�`����3�:�
��P,E��s�����M�����;�(�������I��V��Up��c�����)��i��W
���b\�n>���;������_��P+��V���@�[�<N�L���.������IFK����B�9�@
D3F�!pP��Z�	�>e��xR�����d��J�PZ�X�����B!b�$�

y3h��4v����B�'$v
i'��)�0qj(O �[1f�Q>vL?}�C!9�H�av(�"&����D�z3�s5E�S(���
G<-/p&����V=:f��h�������A��9��,�Q}�$D��|��-K���[��*�z��P	�A&�y����	����n��-4b��nSZ�U�Q��C�m�!)WB�/D����\��:��b���a����L
�![�y�L�-A~��l�����k�����e?�lgJ����*U���1�B�~��gb��(��<7�[��j���S���y
��MM����[��]O��q����R�`���{�(����m��~����71CK��e�J�m~�)��
�#;�R*�/r�-�I��k����Y�T�����Cz����(h���h��z��R��4JbG\fz`^��2��Jz4��@�XI������AEY�8+���B>mO!=�*N�����D��R�V�)4	6�R�H�YVj�<��R�v�:H..�"|�����0#|��(�b@YO���yuP?u�|2��0{L,��G��.�J��F�PIl@�TdL.<w�LlY(KP)�i��H�P�4���|�������*�1��	O#K������zc�`�k��J�11AUWTJ[^x%�C�|�<}��������T&���
;Tjc"�������i�����
��B��V
�S��ZL��J�x�rJ�u!����;LJ���~^�[H�l��6���>�vf��`��,�U1�T2�2�������v)�X#�NzH��@'�I-��O�7:HJ!N����-v���_����(jI���_����>C���$m������+lL+�V�����J��j�y}��(�MI�F%3=6��:6AH�}C���PveM��%��b�I(�	�A�I�m`Z0��S���{M`1D���p(�����wj[���_����?���c��b�����]�6�=��fZm��)�(����������;��chN����X�	��Z��0�A?>�39��cl:F�^�gI�qw�����

"�F�����*{�	�j�����AHo�V?��Q�����Z�	�	jt�9i�P��^"�74�Z6�����M4����;L%���	��	)��jpt$p �W&���|B
�
�n@�7����y������~���3�J��g�6 $�Ti��X���u�6`_��T��)��	0���qv0��lV���lc�A���`
���*4���$����'z���5�Z�h��6hJ�v0B��f��4A9��)Ym2OL�s������.[��}!�`
b��BbS6i�mJF�hU�7�A���������O���t����c�]�L�g
�O������w<�/���t�TF���mj��d�R����MF��JC,��R��Td��xJm��c��%���-�n��)�����A7��`�� ��gs���VL�&�CO�.���m�����9��9�c'w��O����;]c�*=����4I�������|(��R�}��;��IF�O��I�I�#M�I�*X��H
�-��������*����� �>�*�T�S���N�I��1����:T-��G+�R)d���[������s1�Y��hK�Av_E�T�VT	yz+L�js�Fy@�Z�����ub�3 ���tp�a)�M�����7��5�})�R��O���hp@��R�K����0���5�n�_R(���C�4J%{w�Y�9��A9�����%�3���JH��H/�nN�$��L�����L��J�P��c%��~��,Fr�R��5�~�����v�I%Rm�^��)=�w�������^L��s>4d��4��A���&��
��J���{q����Q�������+!(�r"���ni3xiJ��v���������2��H���.Z	������)�&=V�DR���F�).^K$dl��%H	v4�I=_'*�`__�����
�Go&��d$�+��S#����V�B��S�M�0
 �A���Q*
a���|Xt�k�{��Q:IJs0�Sw���
8�/�c����I�����&
�A��#[�5rd])Z���Y$i��W�� �����8B�i��P<)mY[k
�6*����@@�4�!���;F����#�J��F#5L���7����Qe��]��2���JH�6�x�5�B+�%c�f��)}��y ���)�3^Z��W��*^)�s'���,�v��V�]���Fq�������d�Xc���-��wrj	v��B[Y���3^P��I�L�.�]5�S���+�9�%��[�&K2+�q��]
0��q��0�G=�$GK)i9���g���V�
���M������X�MbCV����1X����<}n�&mz����(3�6:�N�����A�R���
 � �5���)�������7�<�S..0��v`������R�)�o�lk���T2����bg�Oi����[��O���%��y�O0g��W��)�i]88`��3�"���H����-��Lw`�2��H�0v��p[c`'�c}��=�$!�Qd<{�5������m��#>�@��� ��1�fB ���3sV������������Wq4X�������qS,/�h��SFZm6AW����
h�_.T�����S>n���~�j_)�^Q��{6AF��U��y.d{���J���=bl�y�4�R�+���Q����r���@���9����#S����&���9A��tU��	��.Z��_j��m�m���d�S$�S9A�l��@UQ�~"���7%;rfB���Q'l��J+tSJ����R�^W���B}:�w���<�9�r�n��)U�������B��`x>�SkOm}�
<���[������1t�y�u<��������k#����H3�^�4�����=��O~&4�z���M�(x�	��(����]�(1� �l���>�5�[@�Vle�2�n�\��8v��(�����������fZD�	�4NA��s�C@�����~n�\��Z/�a�\����<t�:����]��l�u6���o/�����_..Lr�c�bv��U��Z�������pR������7����ad���s������Y�|rI+��-8zw$[�����8(�������B��S�`7pP����O���qP������J��I~�A�O�
+�,!pP�`���O�X�k8�{L��r3Fk�L
���+-{S�A0�I����Ck��8�Fl'/�L����I���^��J��'��B��tm�A�`P�@p��O�0��f{:��.���^H����{7��BK@P�k����k���3&	cR��R�����`b	U{��D,YP���l����g���>-��lq�-H&�h��\1��c[��+N7:�B)1�q���el�+N�AN�h�!i�#���2���utd�37{7��L�v����R�����+�&�	4���EX^��Q�aR�-�-|���z1��n)bz`�V�o~:P��������U��Y��76�R���� ��sF�J�B�X�Z�ZO���TZ����f�2�G��;JJ-�2t
$�����-A��!R��fiBjK��@�%=����������k��%RF�#8W�K��_V�cc��S��A#�$3$�=~�*�����J������2����v��/~6 ������9WQ�p!u:=�u9�I�I��R����6Ja���D!��*-.`K�^K�G2���i��@E4��Y&�T���:(���d-��tT��Xi�>7��aW�-%�ma�i��#�~�Z!)�i@#	�i�c�6�O�8fz<�G�������9���� z{��D�n�Z�q��?c�7���] P�z�c�^������;��Lv�������}��-�+K7h���&�����
3X��)fi�4�R��m����Im�a>0��	��4z�����
)[z�����l��R6NR��Ym$��{G2�^���qMY��(pR�j��Yjh��Gx_=zKQR��X�\��6�N��v�S�����2�O�()7����L(����.�+��������HRk]W�w�p�����%
(9t�x�(����nz����[���4J�����^S>eEk3
.$��&���z�
y�F��O��0�l���6x;��
4' j��h��X�P��,d�jC:5}���S�E��H�AiK&9����,d�dE/R�OZ�Bz�:�&��6��i�����-��D�I���.C~��h�����0)���l%��z�Kp��o���sN�����"W
[��%8�jR�Z���r\��l��,38��G+�Y����T�q�i���S�yn�oD 4���<4�j ��pJ�mz�9�J�l��<9��.�#�������A���)l�
h���S������+��X���7N��K0j.?�S%���xV{�	�J!F'��'�U������Pkp�Y*Z���,�m5p�:����q����O���6�4m���2T�'����\���p=��_v@�����U�]����~?iQ)�,S�'k������� ��= �������g��&>�)��'!���0d��!��%MVcm�8�r�$�y}s%���<���	`��{J!���		A���<������g���'	����_A��;b�Edu3�_*�~��v�b�4��'`��i�~��-�XT=�&_��S,|�|�O����BF���o[����B�����:��e��H�2��R�|�p�X%�R�S�S^����`�4���h�q�����ImL%��:��IVw#�<.�]�,���R�h��P�;�j�����,���EsRiq)��ZS�"%�0#P<.e�k�7�-.�wz���U%fk�MX�".��{q)�
��VQ��IF�
i^�V8,+���r�V�|��N����vl�ny`�|A*s@��m��/W;��W;c6��<�~��sl��k5:�vl�b���k[���;�!Os�h����g`+����ti�c+��N9�XlMw�E���� e��G`�lU����b��V�$f4�c+�����[�I�=]�c+8���	.
[A��"���S�����:�J]"u[�c+����4n������V�J��V�������~��TG���_���^[H�*������![�	_��R�����Q�n�D�
��/�8eg�<��R��4U�%����F0��,�5��B��S|,>t$M��I�
���tY��]�p��Ek��p�-���S��_�Qxp�{���VN��8|NA��:��K���d��;�
11$��+����j�Js^��g�aP���/8��P�T)���-0���4�TnDL��?�����L��~z�v����L������%�L��>:�^p�9�������T!dC���t/��)i2�.��`��v�j�=Si���
\g��EV3F��
L���5���`J����&V00Mu�f��y_~0����.RSe��:s��2S��]�b���)
��H��v0Ub^�;�]�d����54r����8�j1N�����]����ea���ksKayK�
4F���;+X���Ti�����_^*�����4�v����q��S����[��U��_�,��bZ�
U��
c��+W�S��i'R�(&cF��T����8�]-1�[L
NQ����8�mU��u���s8-��I�(fN�c�Sa�;��m���ep8U��&�������Q��Vb|��T�q8���(��K9�OIL�����T��>nH��Jw)��_.L��@w�T��%L�k+�*�&p�1U�S!>�jW�e��������V9�5U�~�l�������b�J��e��-��A_	���e4��S~&��=YQRb
,��&/��Y+
KQ���N��O�l4�	��[3��k�����d
2���uJo_;���[��~J�Y������PC^�������\O��#uR�TR��!�C.�����9au��T����r�l~��PS?���H�n������Zg@L�\�x�����.Sk����O�e��^-{Z+�.�k��#HX(Jh���pS���ZW45�z���v��8�I-`���#��/�&L������,�q&�Z���d���#'K���%�mF�����m��U\I���&tc�
hat���Q�F��mL?��#j	_z�W�n�`�zJ��w�V���`�ZB:X��ya����^W��,��7�:�~��@������W5�K&�Y�m���%�l�T��n�/R��@���� *�G�%L	�������% �p���r,����@����^�%nD��n$vc��	4Z�A�`�)����/>iZ��y1�9�e����r�6/��h �/,o �~�Vj�~�2���_�&X�S�J�1�����t��X�3��W��<���*%W����lt�N�6^�n�Uy;eB� El'}V�1�mP_�!�i1�0%gT -�,S��'e<y�q)dv�0���@��z,���j3l�����Z��g�c��0��t�������?�6�����>!y�5\����B�4�:!��bNgN���J>�.����8��:�(�����T1@��y��7z;��9a��J�:��gq�WZ�L��~����������1Zn����![��J�6�@O������y����(�3�-��P�c��-�##��<���J��x��@�h�r���GD�c5f�l��V���Q[b|P�������`GDt-���������!"�k6�m��m�O���2@u<<_]������2�C��0BE��s�}cr��\�3}gp��7;�F�����z�w�����������1f�C-b���0<2��g�S�C-�_�)1���U���W�C��3��JV�K�����-����C�D�w�p�e�%:^w8$K&����jKV���#�
���d����48d������0b�aO�\)��vl�r}K�*JXK����Q������a)�����)�����ol��A�� ~���,�f�����'|�4���>�j+���PIxy�3�N"l�|�
b"#5z*3�C�{&
�E�o��H�-.�f����Ka���y��@�����4,�.e�;��(`}�M
�P�6�]���
���q�]�a�aPo�����03��jl,���1����i�	��+-��C
�k��w��lf��-���y��-)���"<�pJ����~>o�M�2��������} ec;��Nyu\[������(���z�%���������d}���vIG��5��$��/�����:���9�:�I��kp$g[-0����g�ASR���2�)���m�,�n����R���zw�~�v��	����:c��3��V�����E��&��%;���aV�����ria�W?kp��Z�K�s�]�7e�Y��~6��2�K�
���3a��
|��fD;J��Mt}g�"ds+���Y���d�qf#��5�*3IO9\��xif� ���!"����|�HF�C��1(Y^
:\���v<fA������`ptK��h�����R����m:X�-�	�Q�����X3���R����K��hS*m�����(V'�2[�~xte�`)W�{)�y�W�a$��.��yBUj�W��[.�/Ky�W�K��}�y?6�\lp���f�����4��a���E�`�5I�����K���"C�K���.yk��i3K�f[����eb��������}ADg�V�f�41�T������T������y��vV����a���5Y�O%�,����jSiof����J���S��3���&��/W\���E�������wZ;^�����o��f�/�6��J����w���Y�M��������e��J)1���f
)6�j�<�2���4�6	��-�${�����8jj{�@�����?��]� ��i���u�slf��egmD��t�4�[���Gw))��6�o*���x���� �mY��*�BWR^���NH�l;��M�Wb���l��7�5>�:���;�_]��`S��Z���ZC?���WZl����:lJ��\��&�o��Bi�����i��9�z��$b��M%e��[�/�R��X���k{��C��&Zc\(9hJk^���4�=
47N����K
�6��'� 	w����*�L����R��C��f��P�;d
M~�&��O�LmK���H���Lu4Gk~d�����+�!�����'��T�PSZ��JY}s��&8Z!��w����)
S�����G�_��U�l	0�� `������:^J�����t�����6~K����*(wmx)�|\�A0da��d��B
�1�������e{ZbU��4�kZ�]2qw�z)K��1����f�1-����$xI[���7��^��42$hx)_�vi�]e
�J�������8�$[�|H����bC��3D��lx��a��������x1`B��%Y���{���������p�}"�K�6����`�K��<���v���G���%�7:;\���{��Kp)V�������RJ���n�.�������6+�a{Z���a�%Z�XV�C�<����K��J��Yh�%oN��s0�9���L0���x���S�c�'O�bu����g�i0�3�/�'�L��1a�R^����J��e�����djk�r����V?��^��n2�\�x)O��hG�b�����N��L����q�QZjm%��Fg�����Nl+�y��>�����6�(!1�g!�RK�
3fS�|�����6���BK0�*~��i��������L�1�	�����A�|
GImI�
�������Ps�5�$S��-�)�1�
h{�B��1���|�
 ���6����B��]��Q����)��pR���/�����-DO������#b?+�#�	�QzQJ;�����B_J`:$JSsj�p~EYR���L��
endstream
endobj

6 0 obj
52374
endobj

8 0 obj
<</Length 9 0 R/Filter/FlateDecode>>
stream
x���M�$A����W�Z�{P(�FD���LZ�I-���{��?3������������5�F�����}7������_���n���0t�e���}7��_s�.��������~�������?���������O�����O�m��i�u���_��?~���y�5u����������������������
�?��_�?��_�?����[����?�������}����������"������3�?�?�����_�-��_~����[��k��cw��_������������P����J����v�9<����f��}[��_n���_�����u�����O�������
����/�2�~
c�������������?�"a���<
����%,�n���w��������m���>���
�i����7��)��2��M��a������C�����/oa��[���M�����s���OoaK�u����9���(�Vf��qy����"c��iX3�b�s���o�E�4v�6%���+�Uu������_6/]����9���u7���C7���?]�t�/�d	����pv���?�~��M�����'upJv�����nG�$a�m?���98�_�l�����v�a7��"���~y�-���o�;?�~;��7������������B�[<�;�����]~�|������h����:��������^��v_���n���0��������s�>��v���^��?�gG8���j�D���x�-<������$�?~��������_?���\D	�f�G�_<��v�p$��YG���%OT���������v�������Y(l����v���,����NF�$\�������������������p��������k�<����{�����q��u�O8-���h�Cv�IX�a���7$Y��D8$�����vdb��!I�FL����I��f�Y��'|���~9��;����SxEar��X��{$�����H����q[��Nx
k<���HXu�e�'��} ����qP��|z��V~|"�nKw���g��Z������}��>��������A/����(l�����l���%��1���i�be���P��}9����������4bN����q�0�~G�Zc�pL)l�|�������/���b��X
'a�g�o��Gxan��oh�of�
������_����������{��5�%������#c9
s7#a�>�~���?���H�����|���1������$	}���
���pO.��l��M:|9�����nJ���>P�����OL��
u�C�W���_��i�b���w���e5���������������o��y&��~Z�zr�Z��0�L�!Ot�q���n������������^$�9LvWc�������H���W\E�}�%���:� '>��D*����>7�>�h��.sw��L��E�o���zR���^����}m;}�W!|��>���z��\������X�!V?�`�����`���u|�~�k�A�����sTf]���Cl�{���w��/���^�y�����X��6=�
o���+�����	k��o#3�w��`dx��v�r�q���gX���O����w�������%�4�������\�KC��Y�C,��Yqr<���W2m���w-�L!�|�i	}��KYN��,��'����$w�c� 
�m.�Y���^��i��i�z�|��~b|z!k1�{�t��ak�����]	�>�o��e9���p$l���G��f�������p>4���:��!�	�#a�g�����/��R(���|�������-^7u�]&�/V�ha�_F�O�����/�����@�:|@���7r��a����38�@���������������������-�{�y8�?�E���q
�7��E9��!xt�����2�BP��<'Y����3�� j���Y�����5�w���?�| �-������������9�Z!��u�K7�:W�W���/*�HXk���� r@��q�Pv�x�:�� Y���s����k������p���|Xw�=x)�>c���\wSt�������f��;_�S�Px.+�5��:����MAVk�<��d�5�i�	?;�_�y��d-����D�n��I�����C1��+���[�������Gyi�x0�����e�$�5��J��C�J����'(�3F����$k��$?�_�,��-�������*�l}�O��k�����'I�pC���/N-�= �}�-�������;!����$k��M�Nx��
'$#E9V�������l,
/dgh���o�*�m�]��(�j�	���$l�<���dQ�u��D��M��J�Rx��h���O�a�����	���qUY�����{��~��G������G�p�[�a���''	?3Y���7��%��c��3b?���d����e������O������|s�Ia����,��y����C���] �r����>�����������I�����v�"�.����@s���t�QWS���o�H�p�<�����E�_^�����v����X���}���!(����e��0x�>���P�!I�g�y�[������Y��87�P��
^�O��8<P��~�����X�����ZT�6�jYW��:��
��@�~�uy������wZ���7�X����f����e]��Q�&�����$l�La�>qy=���3Q���g�M�l�>���t�������]:�PJ�5�������<�eY�U7Y��a�s��q�� �GTuHj>U�
��C��'J���>�[w_Te�1�����(���!������Q���n�������(I�x��X�Yt��?���G��f��m��B5SJ��1IX�'A8&��ADY����c�����pM2��y�����^|�k|��5��~$k��]�r��J)����5wa���Zw�����7����o �����s#���������m]�Q�51
fN:-�k1������3�<�~������p=�z����f~Zv<7O���f�'�9nf+l�w�]�I>���!
���ZXmw��@����:GH>y��vGa����Z5��M:�E��w�-��EN��f��sL}��O�e��sG\�N�^��aY�!������x��2����\��[��h��4b��DP�j�7�������:�G����C~%\r��Y%������ ���
	Od	@��5q��H��0��h�����\
�I���Z�����|��Q6�_+\`a/�AX�J�G�4w���������=��v���<���H����(�"SR�m
�</��j�.ja�G`"!��A�.��(���m�Kc�CPg���i�C��Zr;���^e~{�����
���p�����&aW�$�r4�<����M��hZc��#m��zZ�m�����wM-��5I��T}��h:����	
��z�s8��goH��}h���a��i�:��2���&��3i����;v��HX[��o�Ls������i�yLw86
����[7�I�������b��=�����G�Z�i�	k6�=��q���!Z�VK^�F�����C4�j��8w@V��(4��>�E5s����,�n:����ZV+Y�����e�sw���CA������+A��-z�p�n���M��J��I��`�]d���_?z�#z���B�5n�|(�1;���2	��Z\&�k���O+N��@XkU����U�#a���� ���gw������$���������t��n>;t��X
���:'
�\����;\�]wI��"O�����h�m��o�8}QVzz"���D�_kvz"��F_v�#a�g���K����z ��F�w?E+?/-�O���r��T������UUX�J	_��$�r�!
�z
���c%+���Ja�s�����_~��r�u��4���r�yPX��j�C��K��]t	������v2�+�������e��t��o��]���� 
�������ka�
7#+��L�:q��3<o7�r!n����V>�~���7�����[���/����,��?�����e����U�{���p������y������iE�(D;�#Y��w9g�Ch�U%��({T^����V->)%���S��������AEqpJ���p:����+���h��
�a�)��;2��Y��*�6)�<R���w/��n���%
�`���b��z�I�h�%Vb��/A6}^��a�����������}/y��Y4���<|���i>���?����o��
�a�&M�MP�����g���>��'������m|�����}���cw������z�e�w��������I��}�������$���N6�\��X������L��o;�9]������,��.�=	;J�/�O���e����� ��|(6�P�
�/�c����;Zy�����O������~�� �����A����]�Bzb��cO�������de�H�������!��[{ ����$aWs�u�!I�8v�D+u��i��y���KD���������^ �w��Z�j���e]�o@}o���E[�;�����H6^���y���[7l_���~0�����Y3]�p�a�~�Y��J�����������|(�j��;3Ok���b�KN���o>/�����"�� �� swC0�77�n�l7$+Y�pC�~�nHf^+d�.�o.���T}��j	L�v��~H���?�*�q.d�52���%����],WeaW����$G�.{��-Ao�N)���$	kf��d��11��i��;'��������il�=�L���!m~~(NC7�u���B�8�=�M��	�g%$�j�qf����"��
��*�m����%�}~�?9����kQI�L^���[�o�c�����/r7$�r�Yb���pCR�u0d�!��}�~m[�!�v�
�����8����e@E)%|�$�r���&O��GPf�L����2
ga"A���NH5~U��29��2���=)8�����/��D��V�D�J�pdP���p�D]�H�h���=���������G`����<�e��I	�l����:P��|��������G\���V������'��I���1��
d]�+�}7�X��{�����z�����G��!�^� Y�Y���#�:��$~��G�r���pM6��?X�OS�$��9�GCwO�����K�t��i�c8���������|p8	k����P������:|a}<����H��y�������:�������-��������M)��[�iMJ��	�Zg���I��:'�?�Q���y-7	[>Y����d�6�jn�p7%��x0���Mqw�~�,a��6����_�����r,�uT��,
?o�s;9k��|~��}6��5WHVWY������M���v�{"	kM��'���Z��A�U2uv�A�����4�Fa�'����z>;<����|��R���x�wC�}��'_8	kM����0�x<�,��PX#{���?3Z�o��vv�����ym�"�:q����t����YB����
�����<�,��0E6~�G�;-�Ga?��O�1�%N�O�co�+����G�y����6E%Z������h9����)7���sZ�W����Ns�$k9v�~z��}w50���N�����mk7/J��N�������f���H�"�\���O$a�l���$��y�V��}~)������<|��,4����;��c7N���;��
��������
�:2��4�C�@x';���}��w�;A���5���C�Iu��d^o]O$:i�u*!Gl-!|N����5�j
���H�����p�x;���������������Ow#Y���a��v�w���7|l������������bx	�H����++�II��6�j��n
� H9�tD����u��"~��{�l_�0��i	_�gu�J�]��i.#s�Ca����7=�Yw5��|��a��3%a�r�o����M��g��-\.��.���{�r �r.��6
�a���7o�Ga0��<�f~ZF�q����x�j��(!\�%4|���c��o��7PX�U��q ����������;w8�u9�����o>K���qg�����I��u�$�����
�$�m�U�'��:���4���lb8��~k�R����fjP���N(l�|�l��Ta������Vp'%3/^��b�E���

'�t{3G���I�1����H��#�}��������H����5D�zhek9��*v��8�����qUG`C8�xDaWCh-,k	�u.�$�Zj11��E��/].��I��7g:�����>+w�{�R1�
~����C�9�
����Aa�
���7����sZx����O�3���d],mM,������t���������9��[�
�����B�u�\01M7���:�+H�U7$�~&
��=��!2N
kv8��[�v��g��G��fp��C��9/!��c��!.>���p ��1��w
.��
��]��'�B-����D���R������Q�g#�2�tt~H�,�A���m������S7����)���h��:�� �����e5�\����	�<�9A��3���<D�.���i
�H���V��4�[L���S4��m�!��|��?B���U�p$�������x����1Zv1
�X�PI���6�dNF���o�$	?����^?�P��#��5������7wh�Uo��|o+��gv�������������ke��@X�x�p>�����{RV�a�;Y�x��{��1����]�+���������|$\�bEaW�ha�<)��(l�\���^��f���}<�s�QYX���;*
����DD������c�o�y�����\��
�a����_Z��������5��>�O�BX�e�A3'���HY���t���,�������k�fW�7-,��~��d�D�k�Y�E��������O�jv��[��	L���'������DX�K~����f����]�C4�3����gC����w����<��x���3�QX���;"
���$��&���Y�����#�6,�����J�C-����m�N�����G���IQ�O:u���(8�n������VW�8%j�P��������Yos�,m����o<�]�-)l����^C�7�7�����g�y�Ljp
w�u�6]w1 a�%�f�Xk�������3$���k��*H��m�S8$�����GjY'9v��G7-��o5v��Ca���]>Y����������}h�s}�0�r��=��/�$������dc��b�����8�]���x��8������f~�?�E�U\���x��*L��
}R�N&���v�g/��f �r�@��g������
�����~hfk����o<w����n_%��Q��M���$,!_�$����MG��K��I��A��{����l�j	������g�Nr���������"*���3�P��S��>�3��������G�<�/�5��C��Wq������]������.�7U��LY��T��~hjYd�(�9r����~�;(�x�?�����}r��q�K�(��������������'��l����������h��~NKJ����(Z�:G��T�j��������3�P��%U$���o��I�u/a�������d��;a���6����x��;V���|Q|@�Z�7��H�e<&a�S ����c��;�y���+s\AT�i7�����~�v�o�qCv��#Y���$�y�dx!Yy��c3/�.�y����#6����R����}SJ���&YWyP����n�a��L���GV�o���0� <�d]>���kE��Xk���pX�wv�?v/�������5��m�k��I�\N��m��C
���-yPm�x'����lH2&=o9�����	��Z��/���w��C_c�$�|���pIP�5I�����K��G�iv���F\t8~�
������?��.�
�����2�]9�
�p�m�er�#u����6�����2}���e3�hY+p�CN��j��N@-��T!	�JC��&���A���4�bpf�>�w���;&���/����+������}$\O�����m���Cp�^��\
��c\s����
��������Xe�/]?��������������B��@tn����i���;���������1%�ydP�[������������r�#<OJ��GDu~pd��N��P��N�+��+�hw��������tok��:yx D>�Q�;i	�2������e�e�F�\v�D�
N�H��N�}��48!ks(��b����n��i�����RX�N��s��^��1n�#�t����
���7�H���a���� ��}�F���.�A��[�q�u�*33��l��a,�3:�c��x���H����(�u�b�������=��h��s����v!����g����|�8�L�8����!����O7-l��t?����@�����H�g���w/D������Xx��:�XX��q�!�v�O�c���!
h��{��i��{���HPJ������V���A4��v�I�.H������w$�q��{Z�t9��D�ie��[�e�|�m�I��Ia�U/�vu�����ws9d<�A��8+���l�����%.H�2�������d[�d���m�q�;$h9�n��2�pC),�7
7u�O�+�w����@F��������^��'���B��D2��'��������R�8<�e��Mft.�'kL���������<9�������	���(�@u}�
=~g�������|�#���,	kd��%Y��5�������8F�������#�lz&k�L
�a��������Tyx,k��a�����I���n8,�Z>�<>Fh��<��<����'V�j������6A��jaYg��&���Q�$a0������$��o�����9�V���*��-���1�:�=�o�#;dQ>k�������3����<w����	
���w�!]����������V�?�,����$l���o�!�t�����'v�L�������1���
P��w���������]���������r��1#�B��KA��h}<O�IA���������<�y��nz:x��l�u�~*e5�������&s�����Y�(��Y��8�E����Q��V�6����W���s�o�A�a�O�$Yx���y�8
���)�e���}����:�!������meAp�2
�a�����z,���q*�W�]��f3�	�~z��u���u���ZX�'$�3
�)�O7$a|���"Z/���������5Z�|�?(w�d���q��1!�?��;���7�~�7�"$�1j�=
dQ����@������5�8z)1S_hB.w.�u9;>�����YG��,���	�>����3����$��' *v�>�5�����'���O���	���~��?Ly������=��5V8�G���I��y�Hql��$Y����#�������jL$4D+Z'��w��V���L��=���$+��;jvt�C���7����� �rCK�v��2����'�i�)��������;vg���������
	�|����Y�{g3/~�f����c7�����- �S
~��~�o�w�:W'F�m����X���J}�sTg	
m�h�U~&.��
Q�����n���h�������v��p���^'u?��^" �����2���	qh������a�-��.y.���]�,i�m����O����������w��v���4��y�I��������p �:w�C�������>�0�p.Cv�CeI�����u���i�k�{����V�w;-��>��P���(���U5�vlYC�V�lR�#sZK���X��O!�01o���/%AXvb���:��PXkW��zh��3��y����s�n����p>4����c��;��n���o���/��ba�	��C�{8O�A��F-���=�
N;fXXc���� j�u���RXR���7��u[������QQX����ja����I�4��w��C|8>Fp|z'	���'�7I����NT�=O���c��������6�c����1�v����oNvY���RN?'Q1Y�x�!�����;���vE#?�
�H�Qv��^qXo��I
�F4u/Eao�a���],�@Y�g6Y���(�j.�r'E?�8�H.�5���Z�o-�#v��������j>��IA���C�����E�^��
�;��CAT�mG8��U���(��x��s*I�o��������g��=D���) 9
N��2u�R�	��'�:��J�u�;���/��F�_$#'o�(����c��)~ kvw$_8���k�o����t�Q�rsv�LBC�%4��$Y��Bx&��zH�,��q$����~-�[&��Sk!�9$y����a�UV������G�����[/��9}w=Pg�t]�����Z����HXc�Zx!Yy���l���^H�]��H6���u��n�����<��[�#�m�=
�~9
��.�{(K�x�O��H��V}Z��X�*�Z�d�����NGY
��
���Vja������i������,�b5k�

?a?x�a�gG���h���\��F�u7�n�}�b.���
��Ba�V�����Y4��(L���G:(����aI}����aQ�O���*}F���ZVk�r��m��vk����
�����Q8���ka����{X���[w8v���v�����xl�
h�1%�����
d]��BY��B��j�pE-�jK5����'~�������6?��mP�U�Fa�l���$��f:\��]�Qv1�V6�_���bc-+��
?�~��$K8����#3�!�?�k'v7Du��C�Dx��>5�Q��F�>�$xg�0��=�R?=
I����u��m��=�p��Q{�����G��7i	?k
�-�:��It>T-�p�P���?%�DV����CP���P�@�
�0u�t�����V��,�Szw2R�b$A��K������;�|�
���e�}G����f��B��f=���7|���n�5gW{
�������9�$p�����$�bStb��=��5��!i�:*��-�3�����b���� {Pc�r���
w�����������vLc�;�:W��H��	�m��������a��8�C��d[W���l�gE����H��k;���&���6,A~}�N(�_(�	'am����^�������sl�u.'^�W�}�@�9�}��E�0���]"�`s<�c�����z$�+��13��3����p���g[�-�}��O��TN�2��\,�5v����_��[JTV����V���iQ\��Kso��A�3jI��z�VL��N1_�.v��n�E~yV%���h�1$Y�LB��(�s9��?fO9�TRf�����HV� ����]y��6wC��s��I���A���s�N	�Z��)I��6�u��Z}tie�
�Y����y����S��qG������!������Kxw9����0�K����sh��>�K�������������o�����Qw>)�zQK��	�������	���fB#�CzH����d�E�9��V��>��Q~
�<_O&����>I�.�������'���f�_wO��u��'�x���m�R��W��<u�����L-��{���L9$�b ��Z��7�{'�x
��D�N9��K<
p�]r���/u����zl�N)��D"�����u�G��Vx���y���A�)�����3_n����1��)f��/��z �ji>�������;u��
��v���2w��j?/��iY�n�k��$�m�J��hY#v�����7qh�v���-���sy�KX]��&\U-+~�uN��j�w5z
�D��j��^����j$�Z�}�)������Y�����v�u���QJ|�3���~����m�
w�#Y����!�qJ$�`�;Z�z��s�
�o�k\�Q���>�����<�+��IQ���?�|��H]�w�Es�Y��v�zh���p=�2�p�K�P�pH��5�I�~�l�G��t2#���:s�i���6
��iQ������I��H��Iw8�uHK�(����w�c����s>��y�Vi��5�&p�c�1�rv���z�������/�}?��~����_�����q�n������e���������������RN���������*�^��]?V�?�����������W
�1|������n�>��HV�?����_�u�;�e�\g�����]f3|n��K�n]�{��{�/�n���>��%Y����|���K�_��J��`�/�������t�?��%s���"~�t�^�>�O��H]��[��g���7���R����{��u�}���(���e�����������_�������B��d���]�M�_��������:�����u�/�.���a��_����
�a���>Co��k������_������c��K�p�u�r�\h���t��������_���������%[8��a/�������n��2���������i�_�����~��C��������������������������������_��~M���~����s����q�����?���_���T�b0����q^J�}������1N�2���-������Q���)�2nC?nJ�8t�M�&
�q���u��ng4i��~\��~*1��CA?�b���e��Q	Y�n��m������&��n]6���Z���[�d����C>����6Mh��^����K��n���q~���^�-���[o�Io�{�T���������)��;<���
�F�V5C����G<������u��&s?u�E?��c}�D�6��]�����d������e�����*'�R���,C�
�6h����ci�B���m�fz�q��o�n�m\G��K?t�>��i���a�f2�	Z/����%����O�o�jY��0x�����7x�E�����(��Iz�;.�J�|������.�K���f��i�����p���]�,E�zz)`�����-o��6����KF\��q��q��_�����(�l���GY��������c0+�7dK�^��F[a"&
i���w�,�����a���6��A�x(����a?�y�f� �K��^��+�����K
��tk�TA�����Q]�)�����������R��;���RE�'�;����m��{�;�;��
���[p������R�9�`��00X.�����190X,~;J�����-���1�u%x�/����Jc�1����9AA��%�
��rdMZ�� ����[������7��VL�xKI	�����Ad(HV�=�(�����1C���t�c(�.5�?���a+_E�T���n)-4���Hl�[A�c`���c <������0PJX���*����E�2�v���R{�@������8I��Q���v��������n��^-88u�����L���E�ZX��8*Ds����2����(Ad���t�I!���B@7��E��J&I�ro�T`@?K�7\��a�T�1�y1��52����wP$aq���e<-PS�w�8g�L��0���zQ���L��[��=u*�N�T�y���@�1tg���L�� �9u�6���b$��8�KgP�+#Ex���D��j�������-tV_p��t�����GK|o5Z�]���pX)C�8�R-&�+���Hw�n��kAKiw3~��b���c�����v�k�-��W9J9��h	2,C�����RK�2j�u��"����@u��R/��9ZjM�P��dGK0�`J�D��<�G�"
,���;
,3Sf8M#�L��}-�A���i��B�|�Jbh)�*�J*AH}_�������:�+P��X���;�����y��m�I����Y�P��������!��1W`)SdXs���pQ�H�������WJ�:Rj��JP�������M��e�<_�>9�i�>�2�T?o/�J��R*R�9�yV��d)=�J��B�N*C���?;NJJ1L���4j�X���h�J�8���_�,2��R�R+W���RkR�����z�U�g�=NqR��k7�G�qR?���y1��%��'YH�QN�8�������B���'p��5b����)+���\9P����:0�QR�(��/{<������{w��\6�[������o�rnPd�dX�A8�c�2�(��/�xR�b�1T�D<	���<�y�'����><��~���1]kZ�5���P�����(��]�BYJ��,��(qc�� {H)_������U��*��r�F
Q;TJc�7@���j�@H@%<��3h�3�T��������R(�`]@�w�*�������P)�6\Tj�!sP)7�^�������u�P����|�T�/}X��\��;������a���(���
,%����}�k��nmF97��j���&��
�O����;Ra�����6d�6}��=&zS��J�B*K^v}�C��zS^v��+wjg	x�Z3���������������������i�U"M�"k������@����0��=%��A��iF��)��G����Y�E�Y�j)�,Z+<B�^okw��n&�0X<�y���j)E�Sw�i�+��B�*; ����8��&z���H����Xo]���5(]��d��R��>d{�~h���j�vp�j[!������.�4����Q���{F���B�I��^*��&����E����IY���Ek�%x�lM'i0���*�;\-\��7&0�Syx�ld*]�u�v
i�M�'�)�w4��Cy�6�b��q������=ih����K�)��	@���!T*�7b~����z����
>��D�-�u5~�Z����������<�
T`1�����l����%s��;�"
>�9���G���)a�[��1��Ji����������%�T��JP�i�2���>m�m�!��d��U��t�$W{Y!��s���#����2O*��D�6��������yc����`31�}hM9�&T	k�X�A}���s������^
�����y<���i--p�������s7���&��T�_�"d��/�P�C�
��E�H�
1����Uh��6� Em��A�I����8�
Z!}����4h.;���BC��
`e�J�=�HA�b@)�S3���W�0T�*�\�
:��M%��'T�P
����7�"cv��<���E�U;���I�v(��+�P
�����x��&& :Z[�J�oo�V�P
�z���
q�|/0��M���X���,�/�v ]��|���3���^>��/�JH��h/I�T�)�+�r��{�RiPE�r��s�A}��,����T���6��v�A�
H����Rb=������@JW{	�-��T��j�N��J�A�e�g�
p(�����AkP
�����JMJ�&O'��R�?�a �8���P/��E@�6�e����V"$i�3��p��X��?($�!���Lv$�7��JH-�\��C�����=��R�y�w�,����w��Xz�<���9;�
!u�6;Od�X*L��&��K�A�=B��������_P �2�����H
�����u$��c��x^��V�����<�K�6�J�����5~�R�������$$q+�8�2��\�qT�c}1]��JM�V�
1\���K�=���~y�M@I��8*5��m�G�*E�Jm�����Q����V:'���j�j��6������
W�Rs��u}��t>qT,�s��)���qT��%�A�W�����T�Z`�	�������8bRm��\4��H��9�w�!&����5q$��<�wAi�Hk��=�5��c)��u��X�
�|(�;�
�FKe�T�X�y�U,�h�T
|a�*M,&}By���p"��o��XJ'�]l$��Z�1)�
UJ�� h�ZV��L8j�]R�!�K�s�Y��s���_�5F��l�\���M��V��o?���X��<%��6�T	���GL�:�*Sf/(�FMR0��<P}@J����s����9����iV�����ni�I�Hi{J�%��8m�o
�6���$D�������G�%D�9S������9���\j���ATk2����.Q���z+@�^�&%i��Z�-.��9�R���.-o�$U�����-���:�����M!�w�{HJ�7�v��
!�<u��h����V�SB0)#�T��
_���J�\��])k������������R\�&v�51��Fyop����YM(�
�[c�������4fr�E��u�[�9�+L6q=�f�yy�*���:���T�b7�=���T�1Z�/�8q�T2��mFt���B/�}5������O(��,���!��
��b5uLF2W8%6�pJ�[�D���B1$��D�c�V�!���~\������{����l\�|/#���m����~�������R�����-���%s�l��6?��O.�NQkS�Ce��S#����H�pb������DZ`M�������FLP�7�J��c:`i|��9�3��_(�9^S�(��I[��hC��6��0?�y������|m3���6���+�o%�:�8�`3��������HcC1f`���-�&�p����DF�S��"�7�}��t���I�����~��=m"�������W���r�,���`�u��~�ylp��u[����Y��:\\-4Z�z�������Z0\oUe�������-���M�%�+������_��R��y�Um����q^ZM[���(�������>Z�-�Q
r<��M��1ve�p����B�f�=�q�3W��[^��
B�6�g������[�C@������w���6KSlX�nv�T.�$���B��Dg��o~�}����S9RK���f2�O�e
�����?��
�S�M��Y�)~�/�7�����l�O!�/1WW���F'���-��:��}I?�A%q��Y8~�A}TI�
��MF##�?i�j��>w��F��������� ��?�������4i�sQ�Wl�O6	��?�h����m�riN�0�)��&[4���J�G�A�=�S�1Y��m�A�1�O�KI����a(��c��m�C�r��C�&����w�	C��M�r�P��-|��U�/��������h(*����>2�i�4x�e���k7�����:�����+f6���3�&Um�~\�nYW4���t��l�wifu��MqN�D�������T�Q����Q��qT���'�I�Cw�[P��1��t2b���>���b�R&.Z��K'#Ux*)�����hj���`�po����X?�����Zl���_q������g��$�!��[����4�u��S��a�ZK����r1�c�t��	��ym-E[jq��}9��������K�o�eO��m�T���N���B��
1�����e�ma�)��	TbJ{�G�
����yY�:�U�Q�����RGU�QV�����v�7j����2�q��*mZ��������Z���vd�^^"����Z��Qq��"�z�Ko_Eu�%��~*/�}Di��[�I>�����*���].l$&����S�����z�*���zW�;)�U?�Z���R�C���v
�.Z�j���3|C9�[�M'-Mz�G@�XZ.��61M�{�J���O�!�t
Z����/�v'��M
Z�����1��U��LvO7��`���?!#eG�S�<$�J�T�y=�6p`%�V���S��Mv5�+�X�(��E�	V���e)����U�)U�O��HBV�BG������?G�|�a���S>:��E���>�z���Z��C����kZX��6�"��n6G���Z��r"V��%fU���U{����9�K�nN&�hj�X������{�ce���J7�:�
1��-:'LG����n�YJaU���"+,k
X�&��������I[m�$�V����a�{+l�5��u��}o�(]���J�g�)����`�h�������:�bx{�xU�����Oy��7�Z�O �K�����N���/��)�����5�,����,���=X��-w�j9V�8�J�n�T���8�����iuj����o�vL���x?x�a�Xj=��#d����65yE���Te�Z��^��V���~_Sx��bzp���6�7���bo�S2�J4����3%j���)�d<�nOq���b:��i1JW���I~���*1s���A��T��u�AV��x��l1��</�T-�1��qM�e����\0��*u�o���_J:L��h�_}�R��bT��
1�R�O��k��Q?�����%F���T����K��N{[at] �X\hZ���Q����T>6y�z.��D<�.SO�uD�FE�"psx�JF��h��F�N\��JF�DL=��pU9���s����*mZ�����w\����B�`F�JF�FN��{��.@3�����:��~(da�A�Y��h�)�U��f�s�&Z��q\�bl��n�"�KFm6���Jm&���n/��JL���^L����shU��&h����dI�p��7�!T�j��K�)Tu����n�������0G���n�j����%�Q 1��n�-����q����u=Y������*a��#�1��)�h����^��O������M�N��1rc����;dMe���GAA�6etP�9N^�r_�_5O/g�3�=kz���z�Z��sc�9F��>�����Wx�����3��*�K�����)���<F�����#>_����
	��pY�~zk���7Gh�_���)Vj���;8����uu~�^g=:��W��x�1����5�I�S�2�S4)c�&mI��a
��Y5�O���Y���qonOI/e�dOy�Ob�7��B�8!�j1�6���1����z�F�M���f�Ni�#xu���)�8gu����������R2���\/��[63O����[~/K��0������{G�n�/���K�7�r��T.^2�x�e
j����>�n���N�N�0H�t(�c���R���06�2
���c�7������
��k�	��a
i_L��GQ��rw�VR
!��'l�l�}����k���������T�a����A4;i����h������6'4��a�Oe�]���<��f\�O`���ShR��j���_?�&S�����#�9v�����g�A�;|J7k)k�vy��^�g�qs����>�[��F���bz�S������"��Kc��C�JL�a�I�_��66�������#V�RD(��z�QX���(i����^���9x]30�m�w�%Z��pH���E�~	�6��gN�Fy��V��F�vh��5l�B�M�M d���Je��B��ycV�/a�p�����e���f+��i��]����j�'(w���4dvQ	��n�]�-Ha������ju�!,��a���o��j1&�Y�/������E�-O)���u��Ki��S���Be���YA�e��� f2�)�
FM�����Q����fe�$$F��^�@Vi�jd=t���J��vd1���_;�f�T����#��f��;3e�Yq�g���_����~x��
���I���}23`�V)f��:�y��UelJ���c�6��mg��
l�R�������r�f�q�O!w`������^���B���.^���I�
���u�w�z��c�Z:����[[���y����[�6%j}�xwy�;�j����6�����r�Z��)��1>��%����jTM9K7����N=5�:��A�>(�sh�j�-��y��6�g=4G��Y�-�9����
��Z�6��j#���L���X��:Tr�T���=x��>*����Qo�O�S����x���a����a��V�O7��zq�*��"�aU�[C2X��w����-�Y]���[��3&W-&`�\�MF_��PB���*1K�-�}�*M�/z���U0��q�7@Lr�[�T�Q�����&�l��V��qj�Fc�)����mZ����:	��9�Rd��)p&�#+Uk�p�!�|�+E�e�k�I���.(pU�R�a������g�a���:rH�_*�\U.�V�D�VX�����LXGV}66 ��BY�K7!�R�>Y���?Y�n:�����w 6[���1�q�TJ�%��<Z���8�2W�pC��wX���F
�C!PU�b7K%2�AUZdi���f�T�E����f��A-a] *9���{2�C�����x���i��:�����h5�+�[�h*^���~�%����R�u�u��L,����R6+T�lN2�`z.e5����)�T�R���P��*gi�q���%@���E�/7���?���Uk��) T��A�����7��u���K���F_����pC�O�Xh��������%1O��[C�QiT9�';�e�����M\���J$��f}�;�6XD����M�����%��m��v����(����Tj�S�y`���*1�"��,��1�f9�*M�VV�����������`T�G��-���<���bP�	7\��r�1�_����z���*������J�&`��f����9�����`#�X����
�����2B-(#���2B.|�,u�N��?���I�M�j�������uGZS��T�W	������b/�[
 ��TZ�B�h����1�	gX���tX:n�����W���fe4��9�I�7��9F���rs����iek��#�|��
�����W��1��<�,��Y��qGoq���y��6grv1{��2��-
���`<���bX���B��|�Z��������p���@m�~
��x^������8CN���5�d�M��JH?x7�H�@����v��dV�`P������S��>i!�d���M	�������\2Z�%B9s�cW�~"�S�c��-�d��J����\�n�AF45������K��8|*!��y��C~�8|*!/�h�����m��O�J�2�T"�����_O��}POd)d�z�N���^����/�;~��<�����I.��s���f��k�k��P�����2w�r����F������p/	!���f���7�S�2����M�S�-�
]���	��"k�TUl}7iUJ`����'c��t'���;����v���@����6(&B�������&>� �Pi�����@MKs*S�]��'=�)q��?�qP/s��s�P!d����S�SS�+�UD�)5���O����O��<
��S/�NO�O�3���jq~j_n�O�~
��t@���w�t6i�#A��GLn�'���B��������U�aJ��e��$M2����C�I>���y6��L�Y 30�q�4����	��TnR	N������M��]7�!�P
~���}:=�����H�nb��`��0�MZ��[w�8�JM&���ZxL���@��Wv0B�{��{d����R`\Y���� �7&�:"&�RZ���S�����
4��8�UO�_6�0�a�����6<����U�o]��v��]�Z�g���-U���}mSDU��z��D��&2j����L��m�y��Qu6@�����d�Z�������c�����*�T��zjT�
'��zA
���d��j70y��.&R"&i������W�]���/��p����QEw +�T'(Qk�#�6��O(����MZ�5�x9Y��0�k���������vl�n�c�Z�T7,�`+��)��W�[���]�<t������H,-M����"��O6}y���)�
1c��-���$#������J��3	�W���
2��;pw�i���/Y4�t&��6_����d����V�=��o��W������m8�Q>�F�TdU����T��Y�.���:��9�j����4%�k�x�d,Brl�FM�q�����U��T;���@W��a.:x|~��]��I����`t�����<�T��u�����"[�WZ����c�[���D�;l�B���iIN�@V�h�4����-*�X��2\E{|r�N��=��J��8d�}(4�� ���9���A5O�K@*Z�YS����
[�:EI:���&��r>�S�
��L2N�&�B�][�����THy
�t�h���z�1?�F��Ey��v�����T���b��PTzFS��W7P�������CA�~����Sp�@�nZO[�r=_Z;,7��wb�k|Ik�
C�h���pQm��N-IlT��H ��$6j�
�G��WZ~@
y������,��S/`����i�y2 ��n�AL�u��
U����RU��(n���c��T��>���Z�H*�����f���h����#%�Th��&��U%��KJL�g�@����h*���p���
�S�9����6L��!8P���U�����T<����
��[�����Z��1�-%J�AM�mT���3=����#L�)=���j��t�{�#@�F��p�vGV2��*kC��m7p���
6��zff��U"����R����{�_��G����Q0��d�g�am�W��g�8���_�����k�-�Wm������'_�Q�����j�
FYN�b�W�4����
����������Z�����[��c��)#����U������������e�����S��C�(S��i��*�r�9v�
����B���"��6�z��D'�6	���OHZP����>j�I��q�'�I���	����m�-�3s6�mW��d���YJRA�l����T$nR3�2���g_��p��`�W���`�c��D2G5zl!��C����tJ!���	;^y�3Q��7�����:8�-��#���@/G�c�6���g�6����m����6�}��
����6�����i���}����K�)�B��)_�:�mh	2�ZX���B����=��4�Rj��H���)y$%����-�9ipGK�����;Zj6��lM	��i���p��)�����x)���F2�g8^j_3M�;�R
����. %�����w�D���p���	��v���Zj����8��lJm�����M�Z*��Q�RI�������&��F��M��6��
�9��|;��|v	,���h;_���Y�O'�
;��Gm�)<�i�u�Z�|��q6C(.v�T;3��s���D5?�9&d�j�bF9�J�j�f����u����������O{����pT�4Z��E����]�S8�k����b��=�Tb^v��G��fM�d&W$�I����0<I����E�R�J�~���T�m
�i��-X��6`�������_��c�^�����X:v�z����)M�����,7��;3�kz��
y�<�����6���G���Iv��&�6c6-M�}2^}hbr<%�,�~�K6=�x�0}��,nZ��F9'n�
1�js���
��u�1kD���JB��'e�Pm���w����p}F�K�J1/��|���i����G��t��6��w�O�r�����~;U<:D�@T��m�*�Q�Y�����������Z��HY,-Y������$�XFg��@TeH�K}@Z�C�F=���	L%�*�!�&��d���wr�'�fu�QI���������7��d���x.WQ���M�)�(�RF�>��)1k�-�ljZ�b*�)��0�T�����G�~�Sz�\�
<�bF.�B�(M��~�S�.�a���S�r�T�Q��p�z�w���*dU�0
����
�����R��q�����"-���X:G0����TA�
���T���D@���3@UkS��J��/MT���%�4��Q�kD�j�*U
���QV���E6����;��6������h�N��SS1%S�g?44y�Jn�9CR�����)�����J��Y\�&��kh�y�������n�
e6j�
�^��6x�ny��X���9����Z�*�&���U�r�~�8���
[���[���e��������a�z"��4��Vi��Qg�s[Y��;��>%b���!+��7d��S�U�e��0IIR�I5[���=�����Ol��X�*OG�������YCU)��4R���j�0���Y*��<9C93T���Z�A1��*iKz���*���mlL�~�QN�Y�tU��P�����ryK"����������5i�Vp�Z�����+�Z�n���,5@��Rckz�-b�(��o&�
Cfo$)�d�5��yb�X�bfd�y��Jd��B�o
Z3�|��M����������T{|Sh%{���>�����	��Va�X�7���Z��n��!�2h%!�A��Z��W%��R��Z�=~z��
Fm������z�.0���U)���-h�[V}�7���T|V��%���;���y���n����Q�
�*?K���fC21^��B���J�X��(�ZA���5��$�f����;�J����e5;��I���������%�N�8�A����+��i����*?EUa�V��1)�^�&Za4ME��I�TFQ�\S��W���M���/���q��{����X*��'b�r,Uj4b�w�K�rb���T�gC�����B�6 ���H�� �Bm'�X���r:Y�Z;U�\�@�X��
�}���	�������i����}�Z�J.X���i��%&z�91;K�e��;�E@���c)f2��BDn)f�%������X@t��w��5[����]��5���X"���T�fx���O��p����"
��a�:RH4��E�a����3��s�qgz�K��t���{�u���K3:@����!��4�������-_��rb��D�����Z�<����6}�!nq�Q�kXy.��0G,�Bj�P��e�X�����:o�X	�l��rm����i����6g5�
��ch��)��e ��-����@KeMmA���)Z&�<(�;/�2��Z��5LeQ�|��^y�nGK�iN����jX
�����^�
��i`������V	�G�Wks|�����V�h!5�vy��|9C����%C��d��4\�j�a@m��X����f�����l��&�0�T���`^V-�������7�N%��?��u��a!�6��%�C�
�9�>�9�� sF�Ok�&��dJ`�k��n�������R&CNi�!����;r�19!���0���Mj��HS�b��n�<XCO%d�[\�''��I.!�S�y�-�?�S�c��8���X�A�1��x�j�	��6bN�p
1�4�-)���Kv���9���w�|��O��c�IoD
�z����>��<���B/-_k��*����	w:q��
�6��:e�z57����@
FU������,��y�e�Yv�JFm5�$��`%��j����F�N��p<��<4��j��"�Ixz.�\�N�h[�\�O�im��Qa��ZEE��
�l�U}/%�Z���Z�)|���sy����x���x�w<B��Tzk���mx*��!�N�O��6<U�7�~��j�S���O����t�r%��Y��V��xz.��7�3�o�����e=�����)�>i��	�4�KF�v�VK��ODt�h�-2��Fy�MjQ�U��V��d�iH0�
F�V
(�uKJ���j�N����������m���Dp��B�lL�T��Q������uKS���*��Y�h�
������)����T,�1;�
���aI�m�`i�R�i�8���K�P��t]�3�D����]��������C��y��xH�����(*����?����j����OeOIfS�"�z;�����SY��2�6ew�z�*��d:i���	�99�
y�Y\��MF-�Q��PaO%S�u7��� S�Q�D�/�a��(XS	�4�D����:yjJ6oL�{\�\p�N$v��:�y�&��-UZ���(!Q�lyv����
7�Sh�B�G���~�u�����It��i@�/�)@Szm�C����<��O+�����?���d�W�r�b����!������So>5�
u�:��QV��0#�*G��eL��Q�g���F�im��(l����s��Z�>�u=b���m�z����M��72K�[#Pi�N��")�
��%������Q�v���
�vH�FY��o��������(:�xTKi�Gay���m�*��t��+
�(�!9�J�����v�*��u���|Z`��z��J�z��lb|���
f�RL9Ob|�E�V6jN�c[�(�

2��d�4�I�E��Q������E�z�`��!+Y�Z�2�Ssd��fOT�����SiRLUz>M�d��n��J��fj����;Tk~(5�������z��K��F��������d������Tm�M1B��T�����JS� U?�H�������nJ����R�R�!U��v@����YwS��X\�.9�����e5�:<q"��B�9fOT�3���|W�Qy����h�����UZ�^��cT6g��*���HJ6Y]�f)��T���Tn�I��Y������Q�(��:^�S��h[�T�O��1������)������7x*��*�I-Nn�S���!�L�x
F�V�������Rq���i��N�O�m��T,@����v�<����;���m�
n�C���C�T ���[w��I�S�� �-\j��rk��}�|���-�]��'����#���������<�Mc���hb�B�k�>����y!�U��5������\rKz>�p8��'�����u��m-�3Z7�na��Z�����B�
�<m�{}
�u-��'s��A	Ym�"q�[y���#�_oa��&x�5d�6e��
O(���������&�Ce|��w�Z��k�}��Y�����!������s��g)b��V��&�@�s�����t���)�<�B��@Lm����bjsrM�D��eN� �������L��^�6�$�5/c����K7��\��v���1�1�L�U;b
!��i������l��| f�i#��zI������?&0S�S/�yT�c����>���Ga0�c�T�p3�\u4�7I
�X�Sh`}���R��V�	6��a��'�Lk7��������)n��2C��n�������B*�O����0v�<k1F��M����gj��&2f5��1�����Q��	���������,���N���E0��S�ct���l1�3[�i�/�4�����2K!���0-S��f��p�)�81'�r���w���i����A3��|J�������w����2�D9|���!G�����x|��T���O<�S���R��������?�}0KUJo|+�I����_�-OT�~��mx��L�	u��y�`�6���.|W��+�d����v%�^���(
[���0�4n^���
zO�J��W�s;��I[�M�}6Z����C��#���a=azER2����0�%��oC��V�Qm�j����q������j�����M<UB�pT�|����R��oC�S<pT-o����`�Q��G��
%����O�L����>h2{�QD�������H�
]j�mm�LG�i{jN��F�k��=}ml)9���	�y#{�����;Y���4����
w�=m
<y��\�^��@Qa�G�6Q<8�
]
���SI������O�AT���*�f�8D4*��A��t���Y��@QmO���7?@T�S9����@�7���jB�W7<��@��z�O�%�Sw��������\L�����������{��(T,��J�7�i\%�P�Z1p�x ���FU������d��\]l��`T�s�A���r���!�w�G��a(o�h}J��6y����H�JeHJN�0�|�������S�6���iy�Ja�,}�$����z��Z��fQ�u�������T��C@�,3Koe�Q#r��&U�{M�J��4�aU>���T�{S](N��*���*�owd�Ro�V�w�N������BS����v�A�k���`*9��e��4��y�`��L�U������Tm������?�������1�
;�����6�f��4\.�l�����J�� ��kSi�������Fi�,bo��������,����'����B��Z�K��_���'�f;��]�����CvtU&������^�jm��Z�������m�*oW�xK�������Z�~�y�+����n^���K�����E��Xr%��'7��������<���~�f�
F9��\:��Q���U���5F�.:��Q��m�$��+oT-�� �W�(#H�!2���R�R{5��T��6�U'���(K��h����<0nS$�6��dRO��Z��1�<�V��W�����h�U��,7V0)Bz]c�a�T��@VXN������Ad]��{��;��r(�ulU�������D`X��:��;�j�s��a���y�
�j���>�6�]���W�x�Z����r@V~��8]�(��n�T2��x)0�9p����
�
��j�
6���#�p�+l�q^z�J6=�->�L��*t
^�����1��2�;���M)	��dRo��:��c�����P%��a)�8��:"<EYm��M�!��Q��Je�Xa9����b9��:�~�z�,���e����T�A5���i(��������)>t�p�}���������6,�������!dm}7���,�q����X�PU8��2����B.m`�Pk�o���8�5�y��zhNiN��(�R�<k�Qe��i�'.��G��W�96�&���3��9B��D`�Ch]�dM���:Z��5�:��
-�S�J���I5�oW�����RH���9�I�k^0-�����j��oW	����I�����_�|�����Dy�]{��~&O�@c	��K�c�������v{"���~�p�}���dRm��s�p�kd�j-5��h���w�Zk���B�n��>������m����7��R���;��������H�:�[��9����.��w��&Mya=�T{/V��F�.��'�)��K/�����I����B���E�R/�(�D���h�M�r���r���b���X������\����-����e�7;����z�
U�<*�h=2����I�8y�������/�;����h�(�m8*w���Ho���Z���.�Q:bR��P�t�����������?y=�v;�
1}�bi$I:7�8����J��8J&y	�8
&�~��G��`���g��� ��8�-
BgG�E�p��(Xdt�4M'p6���7�T�qT��=��qT��N��,#.�)���d`���B��s!{��/��N*!sm#l�����m���2_V�y���J\���ZDR�G��R08
���GJ-G2
�Q����zq���~9pT:pC
�t�G������$I������C��i�A%nG}:+OR���;��a)eQ�
q�c�6�d���<k�%��<��E��w���bqsES���Uri/�d�-p����YbO�([&j�[f����JH��[fz-�;�%�RH�$0b(f�e�J��
��I�z�&g57���6������o�Ag�|Q��b+>�[��r���1������Y�ZbTvd�������2��ym
w�r1M�
d���|8`vG����z��P��#���QgwXG���:�
1/2T���:ZIhJ�����:"(k4d�F9$AT +��eGi��!����F���Yi��R�pd�V����7�6���Pso�T���(����d�{��9V�/t$Fj�
\b�z/n�b���qU����;�J������f5���{������U�h�pU�0y�x=������qU�'y�,n�U�i�7��*��F���U��f�:����}<m�LqU,5������K
�Rt�J��W�����[��H'��Q^��v�Q���\��*5�����r�~��7\��s3����Qk�Y8���.��f�FY}������2]�y��U������Y�+]j�jM �i9����6�r��cDGV-����3*��)���h�#+��u����U�^�����[��6`+=�[���[UX����_Xm��]�[���I��t[:@7�������Z�Q��:�*1���(3�l��(h6&3N����*_>�Sd�<����@Vi��T4� �L��BS�1d�6���g���M�����;���MF?��8��QOKB�5���,OF��J���V��Y�]�������9�U���1���.�U�)�o�F���S�2���#EV��E����*}�
Ya9�<��VZ�p�*�7a���l�w$�V���-���b�[nZA�tZ�|{�kg�p��|ie��w:�o�[����[B�������U"7�Q�Q[Mb5������V���7�`�QB�
���Q����Zhp�f��b+l�f��@���}�RH��[��"��QQ�6Y��	lb������,jU&����Tnz��t�
��81�U��,_RJRlU�?�y����2�S��l�O����7�[�[�*�7a�X��U�7���uo�V��[��y��m��^e��
�����p��l������������
��g������)TO�wGT)f��!�J�Q����5�����z��~Z�6�Ix��6�Tm�j��cK�J��9����J~7�iM�����};���3�g���j�� 9+�a��e��<	[G`�3�)�"��Q��P���
��h����J1��j�J�4@���R���kV�����7A�~� U�
�R���F,1oS���=�j��\�@-�X��u�ZXil��V#��2VaG�P��GZ`�<��8�=K!A��[F,����]����2'����������?,.���Z�&��n�cl�J,�n�J��F,����Ob���n��s
2��\�n)_5�5��Z~C������T*���_|�ci!���Q�v�{	���O�^`�a�.>@����X��h^��ha�����r����
p-V?��J�g��t�����������Jh����As�u���H�Jh���/�J���RG������)���8�9p��
���}�u:
�m�M6
��"s��=^E���`�]b9vf�4���A�;������$�zk,�=�Y�<�����g�G��b�4��:���Y�4
��S�a|�H:2OK������:
r�)MA��->��/�;n~��q����pS-^q����~�r	P;��RZ���#�����3S�O�����9�DkoJ]�w�����B���Q1D��d�l����c�j����7�(l��d4d�)>?A���!��)5`���!S;��7�A�`7��'��g5�wgVKKc���Hv������u�������"E���7���}#���x�=.[�	������������ol������FH�gJ-l*�m�p����}7}��V�i%�W_;p�K)��3��v�*u�f�0��]��z��G��,z������]�j]�4��<�s)��#��8~�A��
:x���2�<�>�p�-2VF�;
�N��#!������$�m+X�����8X�x�mk���R���&mu
m`�:Nz�����'����\��%���c {��*����

�6r;���CO��y�V,n<���j`a0�����k��S�.l����v��5�ZZ&\�����������ZX�R`��h�^PgJb��{�������4�l�kc����� Jbj�Ic�E���eR'����uE��p	F�:����z��}h���*�I�	�0�<�����G���H*_��_k�`���-)1u�\)K��G/[�yY�H��P����wpA����|�v�j)M�
�[R��<'��/1�O7X�w%�U���nIi��`GVyn���jt��l���/�!,����uRj�tI�U)�l�:'���u1z��MI��������;O�j�^1�+m`�&m5u�c��:L2�&�rT�����h��������M�)52 �b"0ioiIUo����<4����<x�m�B�����BL���i��%vLb�1���w nG�Qu�R[!0�<z�Q����Z\������G�����1U�n�T��ah���6L�o$�S��y{��u�t�.���ji-�&ep�b#��!�--6J@=��F0�S0���	�mD���y�gB�5�pU��*��2�w����Z��6�l����E>p��T���'"�
6`Rq�T%�V'��lh�z�L�l��lD%&�O�����Z�<"�K`��e,��T"ax������;���2f��Z��$��T�0mw�J&04D��n������jo����kH�����x����`������[���<K�r��� *�Yb�	�,g0A�QUj3������%���`T�H7Q�<t�]��#�i`Z����N�B�,?O�����3�,F�-���j�*P��JU��4j"`DUF��k��4kGT0����(�zZ�������aC���FF���l�k����S���/0'���*��� L��H��61����W>������
�T��������$I;@[����)H��A�U�v������$i�w��t:p@8������7������i<���Xm�/p��S��1�Cj��4�x�6,���^z����g�J&���Yim�7����C+Y4Z�d>a5Sj�Rh�m���YB����6���V')!���R��$���8�&��:9�*=��m�b�U�����uPs�M��T�6�7
+����LC��������7��zEn���7[J}��M��\�R��_�\�j7ALK�o���%$� ����
B�M�r���
g}BE�SA(�WK��~yk�T�:��1>Zs2k^���w�dN�Ef�e��;=�`���k�9`��g��`H���,���J�,J\��-���H!~q+��Q�=]�6�S�����9r�^�fVeN!1�-�Z����{ot��E�������U�va����rJ�,���y���^	���(��E����������O��kwj���b�g���
|��_6��D�&}&�s���|����)f��1?U��{|.$n6k%��K����9�Q�&d�u�&�j����z<���6����}d�>I!�x�Y��`O
����V��OF���	4%\={��W���

g��yc��y����
!s|U@�<T<�g�����*s,/A/���B�G�d,��2U�X��A�W���Q�J��\*�e�Jo���;����8a�1T��0�I��P��S���[�H�3�6wu�l
=�Q��}�
m5U�lh=q���T �1��`�����;GOm�MG�i�O�7V���@;�11+��:��W����f���N��
yp��)��.��t|����M�#��U����r��k�
4�~��H��-�<6����rW�Nq����K!�1���|+*���^����P���9WO�bU�J����n�u�M�R�m�������(��p�Kmf�@/���BH%?�j�\^�$����$/�I{��.
��&��NOQ��2�IFa^��6��l�I���"k��%��m+[4�H?M��	~7e����I�K�G^��&MIna�O�I�J@E��������n��kB�S�����ZQ��2�F?�z��8#N���g�aFHi�<�\`���@Sx?:����!���M�������+/l*V�����p���|���T�bRKK���+twJ��Sr��\�9�*mj{~oAt����(KCA���*5��_C��6�g�?��8�J��Zd��i�U%�a��RL7����MvJE�^�
A�����QO���q��*�4��In�$����F���,��$
Y�[P��,-��u����~��V8�b�1 9�j�,7T��'�
�CK�J�������Ta�BC��Twd�oJC��^L���t"7 �<�[�X��
�C��,�"���J�g����gGV��4���
���]%�z_R���$O4S���M2��J,w\�&c��� �&�z����\GV�&o��y;��MO;'�fV���aUN���g5������^����t+e9�4j�/��n(�Q$���./�T�Rt�3b��<��~_*���c>�V�K�f�[~�F���3-�7_-��U?����o~;�U�t����x����nV�9
!�V<�����v�B�u��r�mV�����B	�kh�7�(���gKj
}�T2���Z�jsj3�\����Q�l��JF�~!�����6�8�R����{���T���
�84 ���!�9�
Fy�*�:��FI]�VH����/�i�C����3�+9v�������I!U>���n���L�����!B�L[�R���~�%L�����|��MGU��@���Jz�rGU�x���������8kr��U����}�o)��S�h_�^��0d�	W"��Q�QI��`T�k��7�F���{���]�QF}���Y����`H�<���@WmSmw(�����l
n�<`��I�(yvt�z#:�]�W����U��FX�_��3���s���`�=�NCK+mV���6��B�6�n_�����
������ �W�a����U.n�[��;V�|CBX+���C7�g->-�j��r�&�&;�jJY��\���b*]�U�@�j`�6�Ra�F��T���F�D�+��$�\�+m��=�+mz��k(U
���zZ�'����l�
�i;�
1��liWy:j��W��hp�x.�3c��h��J3�j�p%�FKW���a�Is�<�z�a�I�gk����I�iDXX��~�J�"�
��-tL����7�U�0"\��WOlGW�8-tU��g��w�x�5��n�/4���n�X�|FW��SM�QU��9U�\�e���[9���f��(T��-�[em�
��)Ak5�������r��@sJ
���Z�Pj�H��V������T�
|$�o����4D�Xy�>���������Vh��G6�����M[m�����4yY�3�Y�-	1Hjf�X�3�
������A��j��%���������w�9S�Gf�	|���	�.�����Y�L��������������K�_n�H����>�R;`s�n��1z[�\��[����n�b\�tu�����A����z�4��L��7W�'4g���b&?�����`���f�-F�����L���C`f�g�3������C�����(73����&���LaN_{�5J��Z�z_�	;fJ!�udCr`&�S9�t�i`������-���0S<��������B�g��u���������R������g�$c-��:]#��{nQ���H8l
f� ����&k-N�AJM����,�T�X������fM�C)�]���[R�Q��}6�R�dNe#�.2�P�=sF���)�m�2�[v�'�.4v���$cb�,7���b$��{=5M���L�1Iy�����;�=�����
:�"MIiX��bun
�l	5�Y��)T&�	�����T|��!S���
����t\ �T8h��%/d���X�D���eca��g�����@N����u}XD�l��i.��f�e:A�����.v�?��+^��f����?�6���s;���oh��#���R�������T�Pt^�5���n�fm���{�PX|�/�6��o�(��jM��]:�h���g�d�A�r�F���@T,oCQa<������?%�K�b��a�:(���,4Uj��>�������,��RK��vJ&��}'IY�e8+��V���a%4Y��b���7�P3���+�b�j�+M<U����O&���MN����S�����2<E���z���d�_V����J����2����\t��G����������T��,-���u��%sz�0�
���l�15��Q�2�~Q6���]n��~�<0U,'��S��-����;�*�A&E�T�x�~�80��S����s~�S��9�rL%)�E,q�1U	)�AAv�1�ty�uJ�� ��PG�RvL�F�F� ��#�T�����0�l���(c}J6�aw�Y#-j3���|,,�)u�SLbJ,VKg��rL��x�N�SSu8�����#
��R�2Ogq*hc�Z/ ��{Rc���64�Y�t��������_.w\U���$pU=�&\�N��U��)V��7��W�W��-�:t��l�s��/-	���5�lU�~ILM�9�
C���m���)jcsW�u��(f���Z�Q�4��,)�&;�#C@k�h�pJ�m�8����a��^���IATR-O�*�<��MF#��~�-x���V�gm�U!�P���'�:��6��0��U�/S�����U��T���6�����V��
X�9fw�_�
TUoH�~����rq�������u��7�ZZ����4����x!D����9:��hq��k7,�2���pJV���u��d�<Vi����l����?�Rk�i���)�4�o�'�:^���������Id��L��3��6��Nr�,"�0T%��#�q�F*jS�.)16�
�����r#S��AR�U*��_.w@U��2���o���:�*��
S�������v@�j��@�?��gs*
X��i����,&%J��^!�2#���pS3]�����*>�Z�As��4��'�R��n��+u�=����>OL��
��b��P�s��56�6���;��S�Q�1���Rz�����M��\1�2(�1>EU!���G�������.�2���0���O�9�\��d<U�4��w�O��6<.�����
<Z7���[������Jm
P�b�w�t�-�},� ��"�����U,��I��_�*[���S
�C�
�D���'R�����
�����Q^�8�T:������/9�����w�c���Y��
�5N���@d���KR/*����u��wR��m����uK�#4���?��1�H^=<����)V�������G��	����'iNR�5���G�RP��p�j9�T�g8�\�~�x��v���'�x�Z��j����e��'��)	��:s\Y3�<�i�k*9�x����O<;b
S����v������G�b�p`�����g>��1����4@���+!���)1��*�-�c�������z������;P��a_���-����eSb�-�M~�������WuK����:��A��'�-[p{I[&��@()W7��ro���������D~���������j����|mS0�tn�
/}��g����Xh���=Sz�*���tJ�*w�f��p�E^�Lzy��F���F|2n0>S�S�S��8I�T�&
��&K^��X)�y����,3��<�F�<*���)���vyh��<K�LP�`7��i6���8f
1/c���M��uFiw
��iw
d\4P:�����%����N��-�T����_)���X���,���/�v��'N�@������f�*1����9!7��J���M���P�a�����4-[���Yv�z���A�vZ�U�zB%���T)�/Y6����%+m�Mm��U6����U!����.�t{�]�j��RXu���[���������2�"KL����F{(
T���>[��t
��jbf�T��4����T��&P�L/X���V������_�f�~��#�7j���x:�1/W�K}E��
1���Xh �6/g�)���R���kDI����`T		1��55jj)�JM~�	N�j�&�����'6U�)`�
D�����UUY��w�DT+[R�����HK���Y�+���K�J���r
T�J���;����z��7�Z
T�&�F2LwGUe��6�{�Q�R�RwP�^��by�lh�~����dhn���P|n����v��
X���t����{0�U�4�T(6\Ubj��F��T�BL�D����t\�F���'M1w\�F�{{M:��Z#���D���S�7Hq��*l�Z#���*�T��'U�:��FY
��XW��zcA@t\UF�b����*=VU�����D4��nM��6k%���J�jn�f�����V��HHkR��V2��;�l�:e$lT��1���C�^ay���M�*�cK��w��JWh�W:}RxU���U{p�N�m<�&��U--�1sr���*�L�J��,A�h�������Fe�e;��Qs�����6���/%��'�8��Q���g��
6�6HTW���
6Y�*eM^��JJ�����E�FM����;��)/�j��@;�*��j�L�5��v)����9�U���9����\�I�{�V9�7WeTI�Z>�M��Uy����T����U,o�V���@�W����^�&h� ��pl��
ov���[�3r���E.����c	`B���VGtPw��))1����$���g������L�)��l0��u�����
�������*n�E���~�l}l@��J��4�f9�Q+������!�6���.#�`0��3�g�43`e����X��W��+���u`����d��H`�J������Z��:��h�E�R����/�;��'������;�Z��'��C�T�Z�a��j��A@��M�o�!��:���y�Wg�W���>�j�x��%��*D	�Sm���������)��A�Q*�1+dQLwpE��V^�M��6�g�WeS!N����0d�4!��h�j���%�2gtV��2)��~*S��RM�U0��m������8���y�+H�z'
�[�4T�I�|V�%Y7
�\K��.��by�j�J�����Uh����B9�~�v �T��!��N��{�����C?�X�����j)�R�4$��^Wa��@CW���6�d"���)���k�u[F�:��m���-sK�����\�crj��4�e>�������q%o���b�w`t��n����g>�t���l9w��
,I�����iA�
���.���V�/���	si�+���-im��e��J�p���q�t�~�:��|uS]�x|�Q��]@�dV��0�Ui�R�$-n�e�s�1��}9k���Q.h�^CG%c68�0��Q+����{A�1�Hm�\����)Rk�L����L�D����9qK�N5�����A��%7�q
���V���)���ik�`�PI['S���ce�;+	q�T���\��������\]�pI�N��/�9��"iM�jXi�T5�5hBL����+�3I��T���!����a��7��
����m�Y�S
�b�w�_�R�B�U&ZQ��;�.���!M�c�4��^M�d�am�����l����>���lGOe���q�Y��d�A�.er��dX�O�?��j�	�-1L7�Cww��uvj-9N<��	x�]+�@�Q���7J���";��/�6�x"X#Q:����e���""5���-������iy������P�m
�C^6 T,o����#E��M�_/�~��ch���lf-pD�����Q#��~I�����Z�D�w��x'�F����`R�^	�G����|J�T�bX|�I��1���!)Zd��k~��-zY�P���t3hS2�/�yH�
�z���I�&k�,-c)��6���m��$%sf{&�If����i��}?5*�"Q��j"��I�+���a������i��!�t�6$��t7�H��7�o��H��d7dRI���B�ow$�n�I��
��������!��:�rM�v,=S[.g]��c���V������hTM�pC�QF�D����`�j�����Kl���f=�`�O�GxJ�������`��n���S�Q���[����R���e$i+m�W�kq\%��3���*1�!�D���h�w�a�2�&0��c��&i��!�����UB����O��T���fI+�p7
��Q@��������U�@��9���_h��w���������9�Q��Ub�����S*C%��!���������T@���������8�MZ[k��I��PJ��PUo�=�}��6�����V��FwT�*��O)���UhS��|���]rh���T��j������"X����cx3��+�N��I�����&���M�d5�d�j��F{�*}����\��W����x�MI`���W�����x��W�����;E���V��?(AW����{�K
&/���#��R�VC�,�j��F�B�F]���b�����������*_�(��v���`SoC17�<w|MlZ�'K��T|����u\g����R$�H��_�6e�]e�����6���&j#*�
&Ya^�8�J]j��6��pr�W4�^C�����|�:���	��Q�-�C�������t�a����\�eJkwpS1�m��C���~K`k�����jn����C�Ng=?
{��*G�����RLo~_�5f��R�������Q0�Q��4��`�
�$���X0�a3Fs�CmT�\>��' �6�g����d��i<7�!�6��f`@�4��\��G��5�3��/%6��+e�����l��
�
`�X���$�4Z& �|/�/���Xm��/`~�!�Z}����je��"h9�����BX���T����+�?	$c�R=0V�`��<����������Z�
����Gtx�h�cq�bl2Y�
u�%�FoC�4��,��dJD��(F}���`�(oU�Z/CY��'�A
V�6Y1yJs�Y�()9�j���9�DA`�2i,�Bc2�)0����'���@`� �v|�z<-CE�p����?�>7
a����Gb��d��>``6���j��BXiJ[��7����
�J��U-o
a����/z��7���n�����^d��G?s��o�r�����.�K����-	OW%��wq��j���B-�?����z�r��z��NAdU[��#,/����a��Y?,c8��T[��Hy����n����7]-�u����me���]�GG�\[7.m�>�~������e�a����;U8Ms7���Y���T�����@�L�u��	��{�i������$������0�WM~l�r#_���y�U�q��)�����:�2����w�s���T�&�y��e�N��k���wW���4����[G�!��/��Fck�K�k�u�]�F	=��y�u��)�	f�u���@-%���
�Ep�x�����M��ZG.��r��/x
�������e�z�` ��7��P�06�����td�7���i����X�HF{�
8���k*x�X�k��n�y��+P����k�&�@��^����l0:�n���������*�!N�8��@N����s����,6�S�-P'�n;���t�����g�{�����t
�pG�t&�N���E���2��<0S)�r������v�uU��v(�����rc1hP
�%���P�r���	:�u���a��`1�z��dL )O���HcxG�i����
��jq�:��"9���XN�6�v�Sk����N��"�	����3�bH�I��������oLFfu�++�)4��P'�Xe�TuBw�h�'}@���^��:0a��uuh��:KK����@�O4�4�����t�CD�@G>D��Yv{`����;!�i�)9��i��	�@���������	�p08�	�;���~;�N�?��8���~�
���<�_
dF��T�`��/�I�[*����������m��7X��8�!�N-^-*��#�T�p&�}#���=�N	��~\��ZL(���,&�0����M�v��]�����L��3��va��I�;�`����N)0&|�wJ@�������D���Jf��	������
�(��n�D�;���r���IM���~�9���n�;�;g��!(u���Sd�x�����?���x�w�]��
����p_�a@D��q��������0.�H��^������c#f(t�l����������=	h�L������a�}��?c�K���{.���	x�
�����?��\@A���Y���)	�v������| ;��	��Y��>�����,��~���G�q��c�zCbS=<�Fs��n��U;^��.��<w�Sj7��������������5���u��`�pO	xYV����mb��rK�>4�v?f��
��Pv�t�=���K� ��<��!������6�0ZbDwL�)�#�y#9j;z�Nk�-wp��������P��(V��
I)~r �����rk�������t(�����,$��\���	B���P�	��������M������j1�<	��kC��2u�z�����=Tk�5������"
?f��*�L��8�!�N���Sb@��l���H��H�����DVHHv�lJF��� ��H��A�4�y����
z�C�r�V'�	d�n������U��h�e�"z��G�u��a����Fl��#iY����`���*��fE����-L_�r����GC�&�L�Rk,:	4����P�����J��b����g�{$��L��r��H�h�������F4GC!a�c��av��&��P�aW p��p(����>�$���f�F�r?j��>�i?
�p6`��c6��l�4�U�������0�C)�f�ap�c�z;#K,%8�g���U�B��R�+����PZ��,=$� !�0��0��C������^�0�L��P,��b�b��pP���%=*=%��)�m��'1HT��;����N��j;J����nP���(���a�S����f8�	(�L��:�9R��fI5�I�d����zh�Be��g�|����=)��i��� 5
�{M��'��@D)�g��\�1�IS��Fb*
!{0�9`Q�x&\�;.J����Z��Q��R�n
d��������/=�Q,oBG�}��K���rF��-mr�fu���9t�p�.��
`@�����_� V��w�Q���z�0���RH����uyGJi�fQq�;R*s���tT>:���n5�G��S�o�j��K�9����M������;6g�FL`��)�W�)�
�Ds��a}�e�L�{2@S��N���C��&u�wA^�2_�]�Bf��y�u�;�Nk =k�@����S66i�O����Qy:�x���S�b�x��@mOp�<����S���|��n�#�����V���&k��k�O��\�=�I��w�T�<���f���g��~%�������8�`���4���t�@�_7�*k��� TIy��������`�%O���Ua������CBD��r��h�D���Z5{���v[O���z��~�G��
W��J��_�@j"@��� ��S?X��3�Z�z��4����P��!��C	�C����{J���S��-��^�����C�z^E��Z�<���n��:�p�������M���J�*Wbzo[��5W���0f�	$w�&�����%�;S9���(�[G�IV1�0
M��A�p�S�,2��z��,��I)�j��t��q�r����k ls$�����J ���aG��Q���/��H=e�Q����_����2Y� 
E���%��8*�lu�]l���t���j�BS�?�vKW�&:��G�0���GRr�;�p�)_d�h����M����������B@�'d�c��:�T�QJ~�Y�>�C��g=��J�J���A�R2�����c�U�K�My����������%_�6����#*nT����j�������O� ���q��jS?����Tj���+�.s�LC�W=����.�B�j!�e�����~�A�Y
�YGV��j����jU��U?�d��nAV��%BUk����U/n�+�og�
��eZ�������s7Lb�%v���(�ZFO���Y���\M�h �0�Ux
^V���.Y�Q5���s���F�%aE��;��Ik��*M�,~_��(pUo�5@>��g�Um���Lt�������7�������'|����mTy!e�����++�������*�}�����j���5G6QK�����	l�Fm������Z`T�d���@W)��
��T�~�<�U��
�*����\������������[��9��p���I�����B���{����W��T��V>�R�)5.6��(�	�+O�&���U���;=E���`RdA��+�S����X��J����<mtf:��i��P]�d��6�4Dh�t|�U���Q>-L��zZwb:�R���+�V|�/u���g�>�����]�|(r|%1k���o��Wm�f�O1�J������_��5E���0z����;�J��U�m�]��[�U-n�
k�bW�X'�[�n����6l=P>p�l�����+1���7���P��E`����)WC�(�Q53�,vT�&���-;��9�_����)
��,PU�T62��6=�i�;��F�A��F�l�\�t��*���0#[��U	YK%Zoi���*���
�e�#��5�B��:�
��)���#2��{s�m��+(1M�
_-��U�}S���7�<�Z�U.n�nU���U��
m3zqN7;�!���+��`>.��M}�
�W������0�U�k����W�-����UmR����")��Q[6:pU����2aH\����M��B�T��VqK�~���M[��@e�������b����Q����B�F��*��^C�bU�.����^���7PU�R�J���U�{23�
	TUGTI��!���U��1����~�-T
������X����V��1������uo��_n�/�v`��n\�|�&hU"^�)g�j`�V��B��W��a]��-�U4����,0�S�H���p��e1�c_9��Q��m����U�&�Z�TyB��#+��9��N�zk*{\_3��I�u�9�j���V��S\�b��j��z�s�UmR����k���pU������:A!��*������U2j�6b���������U�UR�!��h������jyK�*%TU�7������~����V�X��[��S���cV�w�����X\���'Cu�����*|��KM1I$��m�{��|�:V7�(2w���K�o���Qd$���(F��@�"F��3uV�(2!`4w�&�(2v"���n������������cA'ja���P�*=��n�j�s�]~|���Q,���b���2tS�������{b�oS6: V�M��6�L�������o����w���plC�U�#7����6���3��u���(|������ �J2���A@7�u$��
R�A]b��5p��L��c�ng� �3�����
:|���>z
xQ lP�&�P�����D\���n���������g�P�H�5�����cw�������$-�zK���3�a���Z�k[�N�]Z�2����3���yfX�%`����Y�t�u��j�Bw�����+���>#�
��J��F������s�����G��c�(7ma]��z�����5�v�2�����u�X�e�5��Hw,�p��
�,��7��y$��d��	O�����u�z�<u�5t��"f���C��i�:eo��O��M�<���	��S#�
��;��w��#dp��n�����1=����B�D��m���nT�!O�~-�O!
�I��iJ[S����hr	�#��&7�2��@!j ��B��x`�H��x��H���x����M8��&S���/
��`4�:�4����w���NN0�,�)=���9���.Ul���>���]g��|��)x��	5v��[O,GZ�<�����w[�a=m�I����r��p`G�������<�{B��&Tz���j�0��b�!�'V`�<%`��7i�G[����x��S@lA)��IU�<R�'�t�����X<�S6�@�
3�c
`������v�i@���t��9�d��5�S�'�I�<��-=��-YM����L��X$c�'�0-ie2���N�6vu8�i���1�n���y�W�wre>�:�����k�!i0S�D����<��H�����g�M0������O����L6a{�=0�E|;{z'
;�D-��:�������|�+�C��O<�)������c>0�S��>ND�n�*e�|�
8���&-�����4�8On�������@1pOj��{�_�<���8o����^'�������2��W��Hq�M�F
��j�n|�H	�d@��b����[�c�s|�aa�1�}�4���������a�������b1������|"f�P2i1��Q�8�)	�Zd�w�����p?����k9��oD��t�:�5xQ��w{����z-��}�95FX�S�n��bd�q�&�
�/�����U�����7�_��n�;��:���;���xh0�xO��Pt!��:p��^b�K|���k�#����t��A����~�@��������e�E�i�T�@?z�;-�?i�de!:�s�CC��n���t����F���<h)���[�� �X����P>���3�"���|(�
�W �y������n��Q<�P���|/xn��_����C��8�$���w�	�n@������^��g@�������!���.KQ��J���v��������B�q;
���=CD�c#BRGD��3�^sD�6�$����U�|GD����"&;�'�������i��#��JS*
��W���ACD}��,��W���l���U���������@��s@��x��i<U�W����v@����K�or
��4H<_m��X���mq	�rTjT2����aP4u�RC���!�b��j8*�G1[<���B�F�X��c���g,JKj����e�)���������E�d;0��3�����n@��C��#�4���Q��:L`T/Ze
$�F�`����Y6P��
��^������C��-C;���6�e��F���0�_�;��/3�N�)�?l�nayo�I��������.�13Zq���@��lTGjL�������h�����������Xs��cJ�5V����nYis����85
��yp�H���Q\+��
������u�U�5e���#�^��:I4%[(	��a���JfB0�������~Q�!��I�&F��R��"�$����9��s<�7���)S�����R�4��v�����J��S���I;��[��Y�=F��b����V�S7���J�����j�R�����-�����[����4�,B^�O0�BT`�q�s�U?XO%�a�g�-����%����S��[�@7�t��dr>�
=�e���'�c�0y�)�]�r��V�J��MS{Pe���R	�k�{��%vm�U���+M��I�P�Xg��'y\/���
37��T�b������S.n�9��e�M
_���j1}+n��<����Y�;n�//�����j��C"��}��L�:�.u�
�w��c3��$����AV��%R�J����������#�9Qi�sk���i�-�L��|"�Z��f��\�SJ��I	���������� �j��^��~R�&zx���2��D�P��S�~B7����_i�[��R�r��Tw�=��7�l�
��o��\�9[�<��c��#�<���T942�:���
��T�a�2�M���n8�Wg�M	^��8�n�0Ub^��i�L�D���#��q��l���CP�Qm�j\�~�!�IY���`��r����h��!��
�@eVFO-%��0�<
Q��F�JGB�6U�S��
S�d��.�}��B���Jr����BL�]��9�*!�E�O�$�`P������Y���r�U�J�7<��&���.��TwdU���H����T/n�M��ZZI�/�� �7��9MN��e��U>�	7����R�������
]���A��"����@�#;�j�V�%�{QGUi��3�+�����	Q��uL��[�r�'��j�����w�u $mQ��Wb�	H���=����E��0j#UI�J�_�`5�Z��^�:��F�N��*%���y�����Rf��H��S�=}dtUQW����.P�L����0Uk[�Ti�2���_=�a��Q��aL�^�@C�_����C�t������C���|��I�v��3�_��MQTjS���0��� �(j��J�ZN��\��k����J��J
6���K�a��
F�����t�8J��2VRRmS����yp*=o�-��AB1�7��h>�H��Q�����T���q��Du�R!�P)=�k�N����� �Zp�O��F��I�`���|�h��S}VA��oN���>�[ju�Q�1U�������\�Ro�$;������E�r��2�O�N���*l5M��_��z.f�3�7h���X���e�+����h��RL�[Po������^�;��&k��<<%1�5���5/>B�JU�e���J���������OOyM/@�J]Xa4H!U���\�U�/��=�4��vtPU�s���PeiR�Y^F��PQ����Dy�j��ZW�,��B�8���:�3����4�:��r�O����z$�Z�����qU.n��o��K���|�s���=���?�W���&�e�&8���)����1
�*����;W�oS-�+��Se�&s��j�
��P�[�(+�c�M����"���i�jg����Eun�H����R�f�R3�<��
F����)�]�I���_GW�y�	���z�k�TE�<��������eGW!f,��U�k1�����th������*
�9�J��;U�WX�P����U>���U�4�p;���-���T+�]o���Fm��q�1-EX��"
�XM6B������$a��+OK],���9��U���l49��[����I'���5�]�Y�J"z#C�����d�\s�T;����<��MO�2d15~�+�H'��H�a+�W���bU�)�zK������E������f��t�*������*���s=��W+�Q�
��[�6[��-�02=m�J�4�+)%�H����|�\����7[X��k�U��W�+��������a������n�P������/�O������l����Z���A@)����6cE=:���mLJ�Mt��b�0q\��^���Ux`���C���8f���@��UH�. b������*�
F��*�C��<�"���|�"�s4�
��tLV�]|���MVa�f��A�)fQ,,o�b����6�~=�
Vg ���\1���\1�����Z���R�'�����7��[��6���:{S4'Y`(_���H�P	�KL�1/3A3��T1������{����q�LXi�����c�p���"��Ls7���#�1�V�DV��G��:0�o�&����cot�:����=���ds4�z�25���-7�r9O�v��_�cLuz���5��?�5��y��'�����6
tw�����+�a���l�pz����\_��'d��;�i
�ai=�����&�Ma�<��H�@�K�	���0+@4��+��=���z���@Ca�����G�U��i*gX
|�0E��&@��8w��@����\���t����4;Z?�Y�,�*��H������N��w��U����#<��H�`'7���O4��8��+H������V-�����)b��W�-�N�~���h����	����4��aG;0Ary���a�����L�:��\��������L�{�?@(������_����r��Q������t��0)�#<�����#xR9���:����1����<>�7�N�6t�8����9a�vR�W��0�7"m��R�)���=6T��k��N�Ko��J�$N3�B����O�q������4��A;X^��%�8�)�l^��k�v����C;6*G���[�C;�QJ������P0<%`�Yxl���
�S�����	8����	#��4�#
&"�3���8�<:(��&J����@=��~���7��x�~�$�;��a�>8�N*N �x�C(x7t���G%��+���
Pm����>��4�����9�i#����b���z`�Dan�A��#1���o��##V*?�0��	@+P�M��	M��s��3�s7M ��	�t���6����(Of��/�3�w�!|h��b@���Uh�%o�.|
��O�a�vS��'O�� O�az�q��7\��3#�
��������
��[�lg�2�U�SK6$As�V�S�_6Zm��V����bM��B��
���47@��Hlh�\�}�`� m(�J�hr�J�*��,�
��h-m��l�3�Pn���&����g�AeA$Bz�>�����"Y0�����������+�I#z}v�m�M@�^E�/W��j�j�
�vZ�)��:�v�����T�PO�2��uGh��2����Ofb��#�Xj�����m^��Y�'����jo!ZP��2�C6`3��6�,�+%���
+=�<i���!	���������l+���AOZ�%�m����bU��Y�m9N�>N�NM�^�,5�~N���������i��E|�9>j��aO�����|�ZR�rmC�<��U�u:�R�p�����a*�7+�N�m��,u�YW����L�������Z/;P;��7�L�Pa1��0���n�u��V�������u���-Z���I+j�EM}���w���j��p�O�M��|�"�_�U��6Xr�h*��;UF���
��@O������yJ���&��1�_�'T�x����#�VQO��V/;�io���z[:hu�{��m��~��X*������}���4�����9�m���.F�A���'��E��f��sT���2�s6�pv�?i����N-NvXA��D;
3�|���������j#|�!K����QA�����#'�@����f�%+tL8�fP��C mF�9)!���vx���.�[�����n��6��t�w}J��sp��cC�����[*�^�s�|��P=��5��ZKRT�Ja��XK�]��[����P��x���%n@��(~�Y�l%v����QV2�:J	?��!��\�����%[�����������S,�01�*:+j+� F��7�Q�e�E`w}��Z/��10��jLl`rf�D\�����SGA����O�!�S�b)XJ:*K*�6���{�%6zm�#Y2�}�L�J5Z�GiuCL��j����i/�����P�0��"(�������(�R������e;m�Bj4��������pQ)0��]`Y`��xK/��**-&�J�k`(����X+������F�M[b�'�-����)+!�5h��8�*��X��7�R/�r"Gp.�	7r��)k��g��R�)v�eE��M� q�9��J��
���f�G~Uh_�o�V�D���%>�>Y<c�-��c�5����!CG>utTFc��������o�c���!`���
��d�	w�:���x��|���0n�.�"
8��$���0*p,��y�����3��VN�f��Fe�j�t�92�)����J�
�?:��(7� ��q����d��"�����r�e���
��kR�;�d�zM����� 
��jrmE�#=�L<�`��3V�$J#��G<Z�(�hi�?�T���wFT��M��b%r�8
��@��P���y*�.�P�Pp�u�|�E���:B���_����#)���O�~�Cl"����'�;"�=c9,��� Q���o$�aOd�%�,j{�2�.���	:�pW�G�WK�"Y��x'M�d�[���:���.�u��Q[3[q.u��P���0V6��0�Rj^3�!�4br�W6E�fOH[l_�;N�-�Cg���JFK���h	auXJ�sJP��.��8���w;dj�����:�A�N��l��q��X_*mz�"���BF��W�v������aS
4�=k'Ep��)�m���4����s�T�����{MeN!�y$s
4����V9(i{�J7�(����>�R*RkHI��&%��jk�:E�>*h���cP)t���&%��1�ta�)���jet����M�1�3������-/-�T�%��_nH�~���S,~P��S�mH�~��9���7$j�S�\��D:
r[���6��e�Y���XKR{��b���JJ9���Y��u�0�c��4���S�3G�:�b�)�)G�_����A$��^����R�PT�A66��JL�6�\n>V)��SoQ�=��R����Ec�t�Y����@���+����=�Yj����UZ������:��ly��nYr����y-��=A�5�m�R(m���}(6��S>
A�PX�U=5��z�d6����T�m`+��Q;�J�!s
@������-ZDZBO���FW��f�)e���_��MVR�y�|�=
@�.c�����E1�U�0���X���n>�=v"�t)k�	dsr)�w��
�A8����Ie:���3H)5�4����m�iN���Jlxl�|��z���;d=�T��"����N�plvy�3��p$��(
l���%�V��K�[��i����-���j�N��$��S��k�S���j-&�;����s����r�5�<__����������P���$N8z
[�8V{�_���-�
%��q�<t�]K�1�ZGNeKI�����`�T�'����7��]u��!'T��6��w{�����������?�E%U��U:~���Y
��?�K�����R�:N�������'�$������3I��,zX��.�p������:������v���O��C�/7`���u�:��2���#��[PTIx���TX T-}%Z�W����� T�(y
�C(������ep���*�i�)XT?P�����-zZ�Q�� %���d*H�AO��Y�y��������Hy����j+�*)���!}��@���lw�24/@���\�s�%S~^�*)cT���u�@J���.�M�j��h��W�d���:ZJR�,M��J<U�
�!� 
Z� *=���@T)�- VA����Zk�5�F����r�5����w'��C��)�q?�0v�2������n{�j��I>��d����:J����Z��
a�$IZ_�]���[w_��S��b�5'�OQ���h��6w�����6@�V����'p'^`��I���@<T����>�����y=���f�k����N���h���QjU1�Y�_u�4����W��Uo��
�Vk8f�	�j��9�UK[$k��
���/�
���Z~%�:�$O�n9��hv��9X ��`F��r��L/��������
J������#�
e`{�7��G�����~��c<���#�����!���n���{^1XK���`�F)Z�0��n�
���?��i�����7�96��gJ+W�������<���K�k-��w��O���{j�%V�l�-��9���%79��|��Ty<,��
y��
endstream
endobj

9 0 obj
53970
endobj

11 0 obj
<</Length 12 0 R/Filter/FlateDecode>>
stream
x���A�����������RJ���:3��]���;�
4<to��� )�-=?������[u+����Gd���L�����_e������0t����6����M�|���������������_����?������?����*���q�u��/�������~��8����_��������}����~�������a�g����~�W�g���������������}��������?D�����#��_��t������9St����+�.��6�_��(�}��*�n��������mUV����M����R����f���>�����������>�e����x+�i����������u���k(�oL])�_�����_���E.`:��#�v�n��I������������;I���������{_E���e����
��]�n,��>��1�����������6��_>��������/����L�5��VE��*���8�,�Qn��#�c����4�Q��������6�����G�t�z�q<7�������<B�?���.�~pH)�c��Wg9�	��F��]s>X����{tH����9{W_6����q;����d[�{}Yw��?��C��y�h���#x�=�M��1���Hr���<����\��`����0[�w��vN�n���}s���m���Q�b�`��y���8"w>��a���;����c�s�n��������������g���?&;x��}������Z����}���07fv�|��9�������88'�3�<eo�s��S����|~q�F�#���`�������\������q�9v�o�}o��}�|�7�����#79���3���p��?���NQw�D�r���w4-����a���|��������]l���w�|�m��~�����+{�$Ye��>?����I�m��~�����?�����o����s���{&��������$�j;o8x&Kh�L)�������M�S;�&�}|�x�����k������~��5�M���/�����a�6�a��|<,�lsN2��>j��{'�����e����g_E�wJau�����u���q���-��	���wY�w��e�<���N��w��rp����O��9��}����1��o�����-����C����=��vp����!u�$a����'��I�f{�;�������.p��:D��$,��
�D����"�pP~T�
�y���P6��`���v���U�����<q�����P�qmx"��q?<�4�F�Z���Dpp8��AX�G�����t�c�I�v����>q�9$�;��b���<R�~���g���K�Ati�B�o����t�{!	���(��es/$a�����?������U7�g�?X��~�f6�l���Dm�=��(�&�
pzX�,J���>�Vc,>
�.���5�����L������d5���{������wmt�T�Z��������$�N�3�����������C���������n�#{D�Z��}�[3��n8!��
��-{7u�����p8v�@�R�c*!<����V�� �2j��mW�G���O��#�����R�:q�O�!rP�H	�.;$*��C��R��f�{W�u�|�Ia�����o�_|g�~Z���3��t����C���'+v�y��p���������;
����V^�t��N��S�w����G��/�d]��/��C!	��f��U7�R�V������*v��n�w����rI��Ctw���k~���P��Z,����_1��;��������^c�<t��p�p^�)�s����j��J������r��!����,G�	/L���x��GA��������?�k��@��<a�[yt7�l��z���I�8�Vjx����������w�}���"lW���6T���nw
ge�qt��|0��/Y8<�������:�W����9����{^�Wn�8�:��]�o[�h(����4)�BqCxk�>�C����������m�w��������s��;��P/s;Jp�CTF�7t���L*�%
�w88����V���@UBG������eR�_�������h����w��������4rH�!\��Q����v�pf���z����������-����7�����D��N�H����Yd��U���vx�s�����{�����x���d�[z�jl���<N
�|>���i����d�~4��e�
I��O�����y$���'���7A������������{��'l���� 2����p�DB�����G��������������9��;!������n���Q��������W�p l�|0��	��2�$��+
-��|�$���pG0�r	[�C)�y'
;@���=~�n	�n�xo�?:F�!I���:k����ym��]?�B�k=�,��3�P
�27���N+jm^��O��B&��}����i������pC6��C�������w0/}���^dee[N����;\;&D�����(�P����g��37e#[?��MQ���(�R�Ig]�l��:��R�(�����
���:�����ZVs`��e� �S���`ck�Lx��5R�����C8������
6��� m�v����?=Z������DwP-����
<���%a�V���{��/I����pL4��s���#
k��pM4s��4���&�u��a�����IK<H����2%���q�Y���o����'	���p�Cz�)�y�M�����pS2��<��/(~������T������Z������$��.G��3>%�u�:��qz��hec��n�V^�<d+�m<$I�M3��C�e��Q7�������7�&#�����s�m����wt���tJ��V�v������g$����:����z5V��~�����p8�o�0�������Vz���@X��Mx$k>'�#��}��i�6�$+/;$Y�z��G����9�]Q�m?=R��/Bv�I�e�$a��H��������#����f^�gr�&&�y.]��������+��5�����~�.&�����C>������l�5��+��=��t��;���_� �j&D]��A�e_$�������x���_����']O	����(��7��iI7_���� ,��9��������������������C��=p���{�R9�_c����M�O�o	��x��%\0����5F�{l��,�O�{��}�����FwCR�)h��X�i_�����X��5����k�����Z�-�L�jd�L$�khO�=Mxjs�{�9�j����E�.�d���bx��O���j'��n0���E'�q)��%-��$���`�z �5��|m��q���#��p��������������|H������;�:���s���&R���%@w>-��?����{x�l3�tSc�������imuQ�zl��sa�����e������6�BV�/d	ym7H��������G
�����pDv�I���y�t�����QE�wc��������9��;"
k���'Q�����]=I}-��������c7���7���],�FY�}i�'�}���h��XrHz��N]F����7���'�~M��������F��<Q?X�y��-�z��l
�����,����~��c��s�nxt�����Ea�+��ZXcG�s��]e�����~<������LsN�A��y��E&����p��C����w��.O�?���k�6'{����	AX+�����S�o����y���?��w�s�����!o������7\OJ�����]��Nl;�:�����������miI�}����
A���a��~dQk��{b�te�Y����p�k.�r��}��v��G�\nXI�9��y���Ci�����
�VZ��=���]�����Z�]S$���5\m���p>Pg<\74��m�}$���o�6?$��u���];o�{�<����G���9���G���P���z�������L}��&h���!t�8�;{~8u�E�^���!d������:?&?$���n�_w3��>��C�oax�v�L�Mk����5��:@�'%\BPXs�V�$������U,NlkK�m.���{��%���.I�]=�s7��K���)\�/I�i�_�u�����"+�e�v,`���h�E�M~����C������)�+H���X��b	
XK]�*P�k���Xu�oD�_u�d#�����tK�����|q�����+V�!o�Ih���~E�ZQ%/�
�?����V�s�D�<�r[�n�C�+�g�G��8)��E����P�9kf&?$a�E��df#Sb�!)���G��C�VV�CJQ�q��+�_�����X�6���=�u���o��[b�U�p��p8��X����X	@��D@^�|�o]?��_+�Z8!	k-La4b}�C�0h9���$l_�����$l�<x�,9�p�7I���xWzu�i�������Mr�F�������jPE�����Mx&�j��y&
�V����?s4����!I��m�,������7�$����p �s�C�wos7��M������#�0��:�}CY��r��$��������@J�����r,�>���hf+w�9���%1�MK7�����KA��:U�uh��7im:kT'Q�������x�����)�\�L����������������#�/m<��q���6��a�K��,�b�*
k$�
g%Y�����>J"�v�*�NJ��>�p`��N�P��gU(,�j1��"~��i����1�H�;�A��oz�i�Q��e�<
��vm>G�K�6�ae�wp���(�v�.��O�}�l�i��g�q8�Bn��n��/���;��������j�����>y��~G�Z�)��HV����_��<��Ff4�<#�@a����Z�=�����4��t8K���p=)��Xm�<�u��
3*PXc���z ����&�#+�������#\�5���z ��.|s���OY��M���<7uZ��6?a��w����P���);�1��������?���*�u���Sw�N����~��=4��w�C]
V���K2��O��?�~H�Zk��I�e?$a��g��Pa�YE5���.?~#F$��H��q�{$:���R>��'�K"!�g	�w��s��y��[��Y�!���� ��;��E�$�9K�If�?y~|���>��?�G����dr�����q����Ny�Q��&d[u�u�F^uHv�)��C���LA>
e]�s�n*����������MA���N�]ksS�u1�&Ye�����<�WGa�1�?�)�%��d���L�,��w
}W�?P����|��:����������]
�HX�g�M���pG%���-�������\����[�w�'����~��������R�pY�\H�.��Z#	wYv�eQ3}sp��(���4���Irn���hU��8�2��]�'a�����6�OG%a�=� a��]�@3�����JY��?�c�\#4%����w�?���(�5�����z
�	��J���?�)����k��������Rx���Ee�4���1��.�7Y���X�}Vl���,�������6���$<�����#�������(�S$��$�8��
!����v4��V��Ww
v^��8_���i��=���6��usV��[��PTkyk���������p(��|�%@cg���p���52�n�I�~S����e4�y�O��}�������e56�O����������%��(���T�aj�G-�P���=?����e��~��>��-��6r��)�������7_�O�p�?6,<q�����}L�h��?���������{�$u.�"���P�W���i{mN�H6l�h�a��$�X_�`��*l/�+�W}���R�Ou�����u_^��4�;�:�5��?�����1�v�<��v�X��~��d��
I�Tl.I�5���K�\,���{��JN��I����Z�����$�G��>cq�t	�$aW�PXs��{'	�i�����"�s&�4��c�<�� $\�<aa�	���e�(�bm.�j���\������r���
t���l��w7�=>������M���
�,����������p`�?��?%a��0��$���s�(�����F3���Qy31���7��n�����~k���\�����w[����e<(+���#���3�c��{����e���_Z�����n�k�"@�����%b�p=P��W�Q{��~�0��Y�9!���P�����}�wb
w�i����1m�~G�.�8�,x��I����u���d�V0��;(�x��!���m�V��Ee���������P�]�P�Z.
�~P���G���GI�E'Y����� �5��y)Y�Z�n*ee�|������_��sf��-����/vH��3�|��t7D��d]��BaW�b����:��W3�����)as8��X��s��$a���H'a�1��5~������d�����o�J�]�Y�w�����d�)�_h��de��pHP��Zn�G�u�IXOIx#����4y#�u�#}��hq�,��^t����QK�"������I�U����s7Ea�����(�b
�F�����oe*�G�?��$	?�@��bZ\������.^���F�
/a4��0� ��4k�lp/��l�r�
���B�Ih�k��/�lH�����x_�G�;'	��(�1^r��V�s�b�q/[�	�9�n�a��nn�d	9�H�`P8'	k
�9�6-a�HR��}��/������Z<���������{����9Jv�
�8���;'	�����>ti�o�b����&
k���^�F���CTy���z���a��_����M����N�2�4����3CZ���c:%�O%�B�pM0�u����$l�)v���!��|m;����oT'�BG�
o�h
G��j�r����o<&|NJ�P��G�����?�`��Yu�/H������I���r+6�"+���H����C��J:<�����1���������]�0����r�g-^(����|��������1�
����c�n�)1��(]�|�6K$��q"�P�|NU���7a��6������FV~x�!q;^�����r~(�jc�x_���Ql<���X�8����P~�xh���:m�P�Uf���=�O�HRf:������A�;$��>��#��5���y��=�c^(%\�-I�9����6/u~�{8�\���^������q0��W�����c�2��y����M�_�S�~�$�{�j������To�.q�F6�������H����3vq�AbZ�����������/�5R����*��ARs�S8���?�����������K�S_������|S�$f2���d�k
���z�!����x �*bf������l�X���]+��L�KY�y�(�j�����Yg����!�s��>�Z�7�
���������A�f^�����t�I�j�]�����9\R
k;I���L���ae���#�v����z��G6
���o�n,:Yw��=��w'����d��A������QvqHAf�F�pC4�mflx!Z�Z�c^�p5x����S�x��$�*f���L%(���ssSv5|��lsYvh1m88�����e��������b�s?�$��I<�����-~��������(���'�(v9F�'�X�k������OK�6�BaO>-�������I'������
��#�����67$3����^5���5��������p--�2d���#ps,���".���m��
d]��&^����3I�?�I���.�YQ��P�����~a�������9\H����ZV��N����W��hZc������T*�t���O�?�M��,��uZ��7�$���7�$Y�U��o��@�}H��������.7����;'h�a�{�<��B�=R���#I�f�v�H��@��|���
;D���(r�ep��b��(��{���e]��+Sw����$|Q�E����{��}	��Jr��pO��DNOL�l���@,��t������S
��m�X����=�
^�r2c���n��9��9~��%��H����[���s$l�G���9� ks$���[�=
D\��a�>8�w�����G���/�(���q��>����kMw������n�T�ZJd.��q5���1�D���@Xv����:��t�� ���sT�|;�Jf����Q��������^��J�������/������;��H�7�c�e�-6�,�I���+�9��I�E�9�U������?rG$a0�����]�>����~�&U�v�E�J�7A�q'��cIM�&���/,N��$�jY�*�cq�[|L��m���pH�E���I��Hv��.�<]�����<����?<�?�~��=�����0 Y;N4�Ca�e5:����".����c����u��%b���paw8����'J	����>�q�"8�@��@����DXc�/|�������p�����rx������apQuz�~��H�h|$�� l�����8�T�+�mI����p��f������.�7����}���OZ�AB�U|�!�����/�!	k�
?D������)�+k��������C?�tB��<���,��t�y���g����m~���$�Q�UGa��4k=��QXc-P8"��O58�����
�-���!	k��7�V��������������B��b�z����'�*�^]��e�\C���Nx$����X������pY�z����b�N+�m~H���0i���~�7v��p~t�J�����g ��Z�����3��|*��E)+<�4�x����u�n��"��`��^?�H�e`��6����YBz��9�|c*s�v��y�y)����fCWTA�on&��7��gR��g�{�������(�j��f^<�|����t�r�z	�����!a������;	��hl�E,da46����E��Y��7�����%I��r��Sv�a�A�|�^
'$���7'��t(�?�"CeZ������3����:*etg�,���=s�w���H3�#X��5���_���]���_��{]�F�<�G��eamT���(��9�|4���O�i����Z�3>$v�����6|�S��*~Jf6����4������$�8=��+����S���*��+wSz`K���w���9K��,!/�	���	���2��k���b0>\��lmM
�$��S�5�j�&	���V^u����g��rZ�@����b��1A���]$j�/?L�<4��S�Q���c��;"��/��-���,sB������C��_�`�����85�p(�����rRB�M���}����*����y�i�@���v��nG���4��;p<2�Z�>�j>r�
����?-5t���~/N���OS>$���E4�t�#a�t�I��?��+~���ji��Mf�����QE���E�'Q�>���:�~�����1_,���Nv��;�fH��A�~������k�;��;�8�$�C�n���s�P�dl8����		$m~���^eFa��P}��u+����u�����k����1��;L����G\����>h�=v�+;�V��wbRC�i1���G��a�ux"=���!d5�H�#��{

*	wG$��v����O�/�{��VZ��=A�rP����������zMH�Z[�6��Gvm�6�
0������|�����p!��~�����Z�7wB����^H�.{!	���hf�l%wC4�jU�y�O���?-])���]�u�POS>ZV+��6����}�K��=���L�;��R���5�h�a���K�����Y��tx���O�Z�u�$YDitF�E��VY���')����;�f>-cd���l�z
ON������1~>�����=AX35z�'��g� ����Y���3�d�5�/���HV^r��������n������8#I����u�{�]>%����fwS4�"�'f�}����g�(���n�a.����5
k����d]�FAa��,��0D+/����wnFf^;
��_K
����a�o�9�@����!A��s�]`�Hf��=��ks+��#�P�.s�N��{��|��G�Z�V��H�e�#a�g�q6��)�����}l�%���2���������p-r�����l~J�Zy<�OI����Sv���e#*�9I�V&�pNzP����l��!���3
�|��Eg�����PK�9����}��������f�����(���m?�����������o��%]Gdw�����7���f��M��@�|Q6/U�96'Y�wR��Z��Z��{���PV[{�����6�Z�����^�Zh�������'���t�����6_���}I���������3�L l_�ux�����r6g!�pds�q���c�Kp������:���v���o�������P��"�[	���PXk���T��R���-���1�J6�!��
�,�/6����<�B	����������P`q(�?�W�������pd�O�##��;$>��g+�&o����@�rhr���n�7q6j(�Ca��A��ZX2�-�������O����9���]��JL������}��9�_�3�~������sNt���	��
3����^ a�3��e���l~&%\}~����4Be��}g�����m������]E]�����h��{L�K���}�����~�%Y�CQ�q�R�$�s��e�2n�G&�J3��#�����]j�|�!�7N�Rt��3���R�uj�L��V=[�y!J8$F~�����AW��{$mN8[�?L���4��/X����?���>}3��C?��:5�N	�����9H;��C4�7�N[s��d5����a���#WS�v�����s<��+H����%\����G��>���683�I���L�E��j:�5���c~g����xSN�0����WS����/`�������~�|9�9��@���_���$��,��}��8r3\�j-�u�bm|kX��M��BR�}KK���K��B��Dt[���A���H��Q8�m�� ��mk�\5�C����
�ne���]~�,'�����be��
'L$�|8!t5� YWi]S�t�L��_0�]���r����W
��%|k����z�m/��:W�3u�f��%�MR�t-���j-!7�u�C�jt(������	�����A�G��"(|�h�Haw�w�=V����5h�=2��K����
���L�?���/j�I��y6�m-��\�L���c	:�9�Z����������-7]��(�=-��a�(���%��6o#k�:[����t_K@���[s)� ]~t�=J���7%T���$5V��&�Q�;jo�����r��rO;�����"?8^����;.�4�����r�p#|�<��c���i��38���������0��6wb���Z���Z��V���x)�q���W��euZV�bpO#e.��(��h�=-1L����2�n���2��,@��{��?���Gw�K4��� �<N�r�����S
�m=���e���������m���Rt?J�-]�����r���]��HY�u��L���{+�v�R�L���E�Z[�����uv`}�c�h��43��4�$�p��.s������>�u��:yFp���2�6|Hm�V�}�w��m��7���������4���4F�~�����c
�����p��+y�p�K��l,2�.���_7�c��i�����2����h$��i���!5F���$���'�����pJ�u->M� �����������$�"s�jm?w�$����o����swM2������j��p����F�an)%5�������dpwK)+;��A��LO$j���4�eA�Ig�_�0�����^YwG�o�8�$�6
s�����[�}Z �����Q��m���?&~t7������pP�^�_��z$+��w�#�Z���H�V2pw:4m�gG���s���3���O�:�A���o��i��9A�����Ci�9���/���|<;��P/=��p���Z�'�����P���;XxhV5�C����H�e�����=���RV�s�2��9?
���wI��o�_%�~���yy����������������=p�NY��F=�X�n��lz�58.����?}bnG~@���}W�,���c:�V$YW�_�,j�>I>���wh�����T�5�9
�����j��������q j������������~�?��_������GY��������6�_�_��q��e����������q�j�w���[e�����e����W=�����*�^5|��7��&Y7��4����HV}�����o�u�����_g��J�)�~��o�u��{������u�0t���=��d�m���~�o�������������9@�~���7�K�+����������p����E����ts�?S�������b���q���h��=�&Y8~f�������>�n�G��n��M���c�Tk���d���i���F,���L��q��~����I~����>=v�o��6��Qv�o��>��v�
��X�tJ��������q,�������c�5v��������e�����?���_w��,�
�r�e.�Z��<����mx�R��2���&-�/���IZ�����3���V��{<����P�������=���Y���,�+���A�����
�{}����3��q�(ez%`X�qL��H���K�s��#����	?��K?��|:b��_���t�OuYPJ/�p\�<a��"*�~�n�%��`*�������|��5S`x�I��
��A�X�j�\��p���z�2u��C?<����[���4�r���A��e.�^;�\�����}+��~���
�=���*�����{7�~-�[.�+�0�gf?3�;_Y���a����?U�J@������Nh�yKz��q�;$��n���"���;P�]&��6�����Dy|*76A-���/�sg���}�9P���#��,x~�����h�������s!�N��R�
�����Z@������J����"���Gw��T������g���	������PN:�QN��,�����4�����9PN���~9PNnv��6�[����������s1-���%IT'�O5�KaN��yE)(��.1`�q�A��B��J�:6Bc�:2�������F-`�T�>��������.�������L���F�\���sz����)
���e}xo���=����F
�92�U=�C��1��z�=�:�2��1.����-o���x����C1��M`vi�ah
mX.�lX������n^�3�U��p�\2��}=d0�y��-��R�xR����O�Rn��q��(����w��df���v=0�#@��K����w��H��u���)vp.
�GV��=��i���f��|d�ek��6<��U��|R�9
�*`�q�3m(Y��0a���H�P+P
x��4�B�f�,����~��<��oS�������z�7�t��X�j�?a�B����3����M��44�K���j���U_Z�#��^��?x�}7|������A�a �^"H-<����"����S��1i��O�Q.�1�(���g���c�wS������'E�� �U^y���d ���y?�Y��{��S�3�_����#
��:�1��n���j�5y�X�S�M~m[�/9�����~�8\�s4��!��������!-�)��C�2@hdx��>1�i��zfS���h����1�}�tio�[���[W�����{��b���n�<�6,<�~�}�� {X�,X���.���z�����xP2���4������yCf���CeG
��;~�C�c�����Y�e�F��}�!r��t�>���`N�C~���@D�~�5:��p-��"j��	��
��i�X@L��Lv�o+&�o�������"�����zy(��/6E�:��\��x������/c����t�����t��]b��������V&T�d�5pQh0��o�7\"J��/�R>�Z��+�z9��DGFi�Z2�I���(MY�������w2�V�B=����R�����Q�b�k��u`*:��UqF�H������'e)3\Nk=Z��[�[������(��*)u�z�F)�k�u���Q�>���9
�v��C�|=0��������C��`�=L�Q�mFa4�0�_~�0*�	��������/��0�����<<���p�^���CC�S��]odM�c����i6(+�w���L�X_��������U���f�0q�n%{���4J��� �0�:�_��/�n�f��f�c�s3+Q���MQ>~���{���[��!b�Z8��xy[����o�����z�!#����z7���DT#���4�@P�n
����Tt��"�����P�*]��)}�����|)�V:�)}����
	R�F���v?m��!���^={ic�x,am��g}���h!���P[�$h�iM�+S7�m�����T�I?=��L�5�[?�u�����}^D<��T��6��XK�N�nP��`���!��GG�c7�io���tF�D��TS�h(��e��S����R���6`L����
A�%b�{}
��s�����-�x���#!��-)n�%����R�5�cR~����j1}Z~����|������s�E���N��jT
2AF-����L!dm�zP�2S�L��$����H����f
�$s��^/ 3y�xy�H2&�(M13�f����cf��\t�`f�ku�;f*s�Vz�P&�1Sj�v^�����1��e�u��?������5M�YUCM�I����I���:�6g��1�#�V�X�B~tJIv�.a9!���ZN%������^�w��%o�B�_n��;xj��s�����k�������h���u��Ac���#��dy���<k���J��BB�5_��sw��I��~@C������G�I���K&F���}�cr{^��e{��_F|��-�[8�e��7��nH�;]�O���H*^�R�`�V�����~���� ���5�rO�p`�������f��������C=��K�v��[�Ag�7<�&���"M�JU�BQ�&M��|iM��A�b�p�x������~QHx��/����	x��������<����@T%�]�ck��<�QA���i}������i���*`-b�bW�T4����Z���,f���Q��6��I�z�@�<ws������wT%�j���dy|��m*��WI��ze�����d�d���B�
1k~���a:�����A����YI�����
dU{*/��	d%]��CGVS�c�,���Lz%��U:o[�R�	Y�o7!+(�������~�)R����������R�d�uK��Y�����'z�����Ut��'zAF��#��Ua�;r��v�M��
��
�K�$��# X�F��!�6�d��e��*>������B�*�T������U��7
�4����5Ot���q���x���]��8��.�e�!�7X!�.����*���7rS�6��/���~iQ-	���i�*��~�	��P�����y�������7�p����S�-Mp*�N�������8���Y�g
��
S
=�fTI��8!4Lb��^^,$�90���'TA�dC2��J&[��
QA��:�tP�JR���Q�M����@Tt�9�%D1��R��#���u�����&t�=D�`x
"j	�W�'���;��F����/�-P�����m[���D���Z����3�R�~��
~Fx��4us~�<�U,o�V��������B��$���l�fq`�R��RuZ�2�v�4b�P��`:0l��,3���2g�]�m������h��},7JH;��I�dp����Y�t;�V�R.��V��J��-���2�Ys�Y
8��z�.��J����ggD�����~�������XBz��iGWe��X��]�����L�����Z������Q�KW��������rGW��	]�92t�j���|CZ���_vt%�I���]��?K@�������2�NI��d�3��UX2�j���@w�#+�Rc���_�b����'�c�Z�A�����+5l24 y��*�������LJ�P����
hzn������:eL�&ks���X
2��V�oPz.���(�u$�Ov��'�O%)^z���
�*�SM����J�F�ju����6�z�~�4�\�6��w?���:7���}� r��}kt�E��p��dx���Q%k>���X������l���ce��#S�v<�0T5��t}���o�G���d�E�GSo����l��n8oI[�:NJ3��,�Re�l=�����
�������Gqy���
����y��&x����`��4BW����	?K�������IR�64�r���Z����E[�����J�&H������Jm�o�����W��nN����v�euU�����<����uu\&�r����P6I�<�n����r���=n��nt�����|DBy����PN�D���b'�#�{w�>O�M��X�#�&|����D������B��Is�E $�i*$����D��40�����NG�4��%V�Z@���?^�4qx�Z8D5�P0���CZ��Qo��0�4�D��8���=���D��A�R�aJ4�N�z}7>��$���L�p�W�<���$��3���P1�3A@�!NQ�������P�����zhT���.@A���J�<D}i6�SW&x�o��	��_D����
�xh�fi����x(����@���Ct�'�0���'����t�|�<O>#�#��i�!�z�
����
����8��������5�%A�Xg%7@/���5O	���3<0�����,<�`}�eF��b!N�@�+x�p	�a:���0�M����Y0f9����w��G�{3��e�|ez�*���=����:��zJ��T�4H1PO._�IS���4=���`��0�S?M���yZ�&j?�w��L��)���]�f��{����2�+�6�O��8����=�bC=��'J�z`��o��M���)��	/���PM�f�@=��4l�G&`��:�x�G�����<������<w��	�X�
�@���7�#/�r��<mB���0��
c��1��F��[�'��i'�;����	�����8O��P���_���� �t��nO;f�u�������=<����e���'����I������<%`N����8����51����.`n7/1!��C'��D�x���B^�	i���u�C��q���!�4�� y�	�(������@j�;Z��{�p�6��|�C�-�����;�)�[�g��K7qw��y��!�S��-�M��%����6����Wy5�+W�z����y��{�R���3)��y`B)�
��	��9f��	+�yz�����c�	����>,�����1���a�	��{�K�Vv�=0l��������{B��P;l�G�����	�I�}�6�\L��S
P��;zq�TK�������<��=�`T�0��X�����w]�k����|�s����t��>�|��]��p�f=+���K�X�=���[W�[bF����gs���(�9Oc�ef��.}7����
�Y��v*���l�7K�p��9�����
�S��=iL�d-������{3D3���g-��� �A^R�Q�A�`(D�����F:����|K6�ED@����'-��B��/��\hyN��V?[�(��#�9(��XP���/-��Z�P�u���e�(,�k��J�9$�X�(��.=k�k�"���t�h,@Q�qP�9(�!�(�v��.K���Ii?u��=K�7�{��}
�,�0�
��:�s��4�P>�1���P�pD�r���-���g��"�Q2%�����Hg��Z6* �rj)t@��)5����D����QD�2an5Q-n����e��V;O��}w�O�+(|�(Q�-A�������~�Qn1 QjQ�&��$*��@��)Rm��S@��Y �
@D+&J�F����5���YRm�T�RPL�
�������p�HZT*��1{��PTo���i��"�����(J�+�.@���cE�a-�L�D!���\���G�]�z1Mzv@��7�M�A��(c��(C�6Q�
��(��3����$�Nt�A"�6�e%��?���������4�S;��yFK����)��#����1��A����Dc�W�D�!����P$������.{jf��:CM�1�FJc��L1R���n�
d�����'S%�
K��%7��P�F;��,��p�I0d�}��l<s����e����6x���x��Z%��-�=�������v~�j�o���������{'H���RL��<v�:�R_�����@�B��@Jx�u}I�
���x/��g�(g2�����I�J��Z�������@k�Q�f������h�7�o���Xh���l�$�S�C �����B��[%eK��Y3�����\H���#�$b��X��>�M�n`�t��}/��0�Le��0��*r����I2����SY�����G~z<Vf���s��_
�Rq��j����>j��d�|�w����r5�r���]���J��t��_�u�B��Dj�^~B�S��������2����3�F��������&�3&���s������Q����[�gjf��P�I{Sj��a
5�9}HYld�)���wO�K;j�����J�XK�5�1�'�u.�Q�������$ao��U?�@N�D���2� �N��I����Jq
7;�S<��:�N�x����vvj�S*����A9��Z9-�Ue`�\��aL�����PB�/�q�t�p;�Q���Y�8�8�S����3��A��)uK��2���\fP�C/��xn�z���a�=3o������g�p�3���@P!�UoujZ�T>��6�n3?L�h�\�wi���b1uH�R��&o }8�84����:�
1��������r��J�
I��`T>���_�*���~e����h�Q�x���M!�V;����-�i�s/y�i�9H��/��<�T�yW`����
�m��*��
�@�&�z�Pf�S2��+�O��4*z_4��4j��&��5HE�l7���l�?t�Yt�M�Y9%>;�j���@[N@��.���u��O��^��� �yW~�J%���8�*1�gmR��C:h���p���+�T��{�%
x�&�FU��=HU�B���G���MA����NT�������R��;�o�*���ZkY�����W(`�A:���z.��Y���8&�V�����eD�P�����R��V2�nH����Ue#���r�Vi����+MevK�6M��Q��VQ��T��$���[��s�Y�W��~8Y�(��N��z��c]�Q�.���|��2VP��j�7/j�	@b��s�S=�J�>9�zc�/6@�z+w�D��*�����.om-^�;������@T��
Q��3����-��~Q�r\p��aS.nU8-SP�����S����i����R���A����!���5��v=hZ@�����j2�%I�V�-������+���8r4�{���0d��T���
�9��0Un��~G���(U;�\����lA���"Z����E��>t�#�-�+t)+Q\�P��x���&��H*)>��	�"�n�����#GSi�
�kr%!	�X:��#<=���+T�A��H�Z��\�6 �F�
G��7����l�d���D���:/�0���&�����t���J�h�SS��Pf)f�+�B3����a@�Qi�z����8J&M���2��Mrm��/l�w�|��$�Z!�4[^S3�����H��R4)�9w,b���3��=��|2+zMV���V<%��o9���2��C1m���P�Uo��z�&�tT�>-��y�1YS��*��h��+�:Hi�T�r�#�Z����i�M�N�W����U)�j�i�W�v�������jXP[7&������������6h>W���������z�q"�LC7<�3��V���gR��U�;k*=����C�;����)�S�����{Saw&�	�A��h�l	�4>U��D�eE44�
1SLl|$��Io�I�'�*���X�\�1Um�
�%o�a*��t�Z�ly��a�]�����iK���&L�/P�*#�����0U,o�X��h�TuX4a�T;���}��?q��U��5/2��%��Z���:�*=����Oz�U����r����l�T9����U����c���Tz�	f{�J6y�	3@`���&s�Z�X�(��� �SE�*��h/�W�K1�[���5x�.<�<�4WxE��k�frxUb�7n�(����W��+�U����
Fy�6R�>d����Fwfu��6����r�W��	^��rx�N��W��	^��rx�GE�j�^�����S7�����c���z�����_�B�f\ix���w��,��,$���K�z��r�7|x7J�� /������H�;u��!���w�?��4t���lK�D2��d��i���a��G����a�GH=N6�%�B�]�9,�#��L�#��*���$&�c���j��30G[���w^/O�LWVAZ���J�@�x�B?���b�B�_���Ru0������#' ���x6�7���u�d�O�
����q�<�A���Wg��	#�#Oc�x�g�s�S�����2�@���7@�����g{�B��B�6dw�r��1���s�<u���o4��!���#t+x��l�yu�8��B������5��_o�0����
yx���vb-���I�qFKD���G�2���7a�\N���u����Y|�ub���*��kX�x�}�u��D���u���L^
����*v�#
����4c+�vD�&`�R��0��C<���#{2�x�GF��4��Z�4�#�.��	����N�sT*��j"���N*?�\1��S' f4���k�*�����7��i��gx��qD��vZ�|�4)��wC��q~����A��#���|pH h�T���Z�"�0�����#h��A�x�f���]X��gC<2�x]����[�#<2��� �-��K�>te�'��O�X���(�(M|����4�#�����w>6Lam�9�����r��b��]�Bw�k�B&�N�t�����	���dt�(�������+���B�
��8�v���l^#�����5
�yk
�`=���@��h}�P����;X�����~���� �>��cYOi@���u,N��������q��4��#:���f�x����j7�8rH��i�W��D�����s8�}�����w���[��&�27��<!��
�n�]~��#�����������8���H`��g �X�����q6��>I]"C �T��H�I&m��������Dl��F��l��}�	;�s���'Na�(0��G`&F`��C�Pa��:�:�a�?�~	6X�����;�k�K��F���
���:���9��+�����RgO��-h���ry����I��T���n������Nn7�m��q��W�0���V��>��(�%��,/���#�}�yI�W6���N�0*6���i3�]�i.�G�aG+����lR��IV��H�&��,�?���:��FL������?�;�nPF�P�`.	�����Q�Ij>��������`D�i��;b�����?x����e��~�-yM�~�1P�_���k`p��`C���XC��ZLe'�������S�(�dYp�W'?����Aq�����A�AeA:���[W�[fBq�`b�N4��g���Q���B��h_�:��X�f`��c!��y������X(����H����l���I��Vk��.gq4�>Q�
Jj|���b����9�l��z��!u��>m����&|�#|'FP���!JO���[�(U��B�v!0
@zs�5-���w@��m��sC��eO���,������;!��C����J���1 Q���o��sHT���U������h�Qi�a�����r`���iL3�9"
VV��LJ�Q "n1��d; ��a"m�6n�(
)�F���1����
��i�>�#"D�E�1���"�{^�rgCDi�W��<������cDi��E��<�e��W�����k=�j��A��{�#F�F7�����������Mw����e������ys��bi�c�&�$
9*6�����/+��6�,�����DiJ�-��������!�/w�����*�C��3�WKq<��81���kFo��A����XR��@Di���Pc��iS�aL�8Q��Y��ozB�S�iW�v����V\�Z�6q3�Ez[!����>/��2�������vVm��eH����6y�#������������.��te>f
��0����W*|=Wr�>����c�s�b>�������H'����S���2f������^l6�6�Nz��f��R�b�h�XG]iS|t5:��4�B�:jJ��;X*[��:�!cj���ZY��|��-EI����#%��2Y�&d�%��j�-v��r;��^�S��6�F~�CIi����NGGI��q����^����!�y�Q~�a�~+�1CI��z6��o�`��P��PR�t�g�(���~:�cF��������O�L�7(�
�M��NyJ���b�7]�����`�<�����:Ctq}@�6���ao����<xsJB��h)�#� ��@K���9g��}�n��#�5�h_��F�UoN��'-K=���CSOZ�!Vd����B8������8���0S��gX�1s��iW0�^*d�9z_z�#L�"�Y��I�O�9��j��;n�oC��q�z9n���m���m��]���}�F�@��������I /$9��;���U���6�J	��M`�1U��0e��Q��%<�Ao����,�Sh2���k�B�g���Ykbq���e%��f�����q��Ai���v��#M�N�7>yT�)d�hyU��
�b^6��fpo�	o���n8�3[�8L���bj����?�������5Z�H�He-f���,�'A`),o@�����H�O�Jqf�	U/F�
�V����:9�J��������b�����IV�Q%`�{'=r�R���"K��c�����Z�)�T�$GH_�h
��
6�)���&9��'c��6��8*:�xJU�C�k�E6�w�����-����)y�
*����Tj2���	*�O3���XO�%zF~_O��w�A{��"�2���!*����)��A/�9*CT0ht�zM�c��4�%2�7�;'+���-]����..�G��GH��)>������P�&�Lo�[7>Nzm^��*�s�/ZtBgU�E%i�
T��:�o��P��:�J��5�@r�U!�X����}���$�5 �i���%����
U�Iks?�8m�
�T''RM����w���y�U�I����,K���.���)X���<&��1`�j����*V!f�����:��9�ZI%"�J��5���{�U�����E~��.���������U,oC��Td��9-`L������U�;�(BlLquXKWO�[�p�\@-�u�W��ge2�R���T��i��!���$��_d�O�
W���I�P�5pM�
0��@�.��4���U�T�:U�h@VmS�)���Y����z�#gs �0�����?Y�.��=vU #p��MZ��m���5��*=o\�'k��Z�H��6�Yf>w��"M����6�Tm(Q�s �������@XiS���
���(�9����+d�W��S9����a$(�&�a�qRG��z;�~�������)�J��f��s;V�1��k�z��E�J�:�h�n����1��9�c�6�JG1%�L���Q8510���F3+N"�����@X��]����6�����J�[���|Ow��*m���ks:k�������uU����G���0V��)��^Y}eK��L��c���O���Z��j����R�0��Cz�1V-o�b��)�v�%����5i���D-Tq�4�.��
8[�eLm8{.��`}��@�pV�����R�b�u$|B���,5��8KF�
����p��m��B�pVem&4>�c��&c\��V�4��5	��^iS�#2��e�Q��k���Y�*��Y�M~��Y0��pwj8Yq2T�o8�t�J��#B&yg���1
��g�QkQF�H���6���K^���i�YX�����i�Y��M8�7d���6������j�/����8�����|���J�{�J+���c�i�&��j��2�b�|htr�-�O�t�E��Z[i���H ��1UcQj�t�����z�����h8�i����m,XTy�&��Ym�ke��%=R�YePYO���I��h��
C�^q�L��:�j]��I5Q���l�w=Q�:��Q��G[�jm^V8��"=�Y�L��/<wne��&��Ru�YX����M8K���,��/�Y�9�/u��9��������?�e��g����<��(���'!k�p�<������J�)�%}�C��O�^,�����-�+����/�NRE����:�t")-�&E��W5O���h�@�gr^9�b�$&xc��h�D���a����9���RH%V,�L�i3l$,��Z��d����77C���GW�6����I1`/��.������'S$#���	1����]� �e������r+�-�c�����Qk����@+�gb��l�r-�6���\�p������������������l��D�u��\g9��X�$%�a�������Le��Z�e�10P���sk�}��L��VD�����s6q
���@4�M,����S����Wf(t)d���3`���
�
�U+�����i�ws�T���k�)��$b-o��k@z�iP��)-�����qy���U����l����FI�������>m�*�������C6	���nM5eC`��0'_��',$K��%T�?&
�5v�=�N%�V<!�pL���Tb0v�#�l������
���P�!P�Q�����H����������ST�-����FO�m�	1���@P�����>�B�l����! ��9��~� ~�T2�)��s��O�MC
Y��$���T���
����S���N1o�����B��Z?�\��r�������H����w�����cm���L6&r�F�D�8�x�1Dx��dL�3�e+.&[�{��Y,�����������S^�D�8}������fX���Y-a�Ze=$!����$�1}R������)����08�@����)k���W��*���P����o~;0R,�q$�ZHqJ��3�����C����U�����O^���'�I��]���f�8�eL97��I����%�LGI����/4��Q21�6�d()M	B������5CI��jX U�����J������C�.���1�����I���J������u1��$��P �8�_�
.�9N���/�8IBFk3gb}6���F*���Z ��e,,�^T�I�8V3�T?���j1b���WZ;L��
M���09v�?��J��j��roY#�����R�cIm�d��r�K����QR�����G��H�Jjc<x2K������$�)���� ����$a_��o0@�n��F������"��N��m
��B�>k"v��H��}UB!p@$�v�D�)=|D�M��]�H���]#�v�0o����8H�Wv�1@Rj
��I�vKg�7j;HN��q]])��Z�D�S��R�X��k�{~�(�����gJ�u=��x�)s!P��H����^�GJ�cLZ�<��2����YW�Ji��Q
�A%�2���f�7�$/{�H�s���A��xR�nN7	�[K)���-i�USL�d|���v����t��J�4�NP��R�xZ�H=����h�q���J~��QR�pOg(�7?g����a��~[*R��������3���-���\�����Z���]�	��[��l)�<b(��+�
"�%���&�DJc������
"�1����# R����t$�b� �;D�/��o�
$���idx�$y�-����5#u�H�'b�����AR>�����x��R��:����,�JDH�)���I@�d)�mS%DZ,�.��K�r���h��i~��z5(.s�T��a�<���.1������%�J���d���������X�vH��]�a3�2<���e�J!���`D���_'p�TJ!�M����`�����
,ak�u��9X����n�����S�ic���,T�`�7�n����&������R���w!��B���
Y��)��?�T"+r�"Fo�ai@�2�S�S�7�*�s���
��L�Dd��H������d*�n����0�T�0�^� S0
	X�ve���<���6��o��4�r�<\�J&��T0�n<���^�a%,t����y�7|�`����
��I�T|]�� `�U�d�6e��Y���	�8+M�����It��x1p���1�g@����\-��hh�#�b�\W��t�6��b��KK-�~<�t�QS��{.M�X�-7���9i9��r�q�"�������U9�7!�����j7 �ZL����;
�ntzwy�z���1��#p�\�R�3�U
����9����2�r�#��7L�-X��)-�n�x=�������4�T�L����[7�n���JaB�l��[�f��7\V:Pj^�Sl8)dD}QCe�����Sh4	�<����=1n �dT~*m�0R=S#��;��Hi�%����o,��������&����@G�)8�W���U���R���h�|�:7da��y�,��q:r	���V,�Q�u^���tlTJ�v���wp���s�[���|V��,���A4H	��
z[z������yK��&�����{���.��qy�e�z\h�t���
�BGL���
����$d���4��,��h�G���G����UBb��<��^2YImr�
�>(����1��&�iE>_��#&=�2�5`���&��;9`GM�v���7jn����M�]g6��K��������*�o\�+1}�r�]�t
c����)@7��+���kNO&-���)���$?th��`���S=����E�_v��?�q��4�D�l�u:���Ioj
�9#��&p�r��&A��J
/M��
kqVs*-�*�{��RH�A]�5!�E�J�,�:;�
�TG����T[���)y�I�J���&k�-�rq��g�9�J�k��j�u2�Qtxt�MtL��3<pT�����H|�5�Tj�j\D%���iK\{��o���`Q��� *
Z����XO33��h�YD�A���T���r��(X�]��$���R����H�6�~2���R2�m����)+�y/KXo�OY�/���V�t���u���f}����+�U`:e�Xe�|�1e�)o<�Z���B������\��/��+?�\�\��J'm�j-8���
W�jq���k�\��p��z�����4�LXK0�:"HUz<�.k�b�
_�������@���d�d�"��)1�z ��S���1�x4��c,��������dS�S��@X�u�P5o�	�a�.kC4.j
=GX�&2�0���O?3#��w{v��lZ�����/�,��U���V�?I(
|���:�5�������Y_�6��:����������S/n�B������oWyH7P!��-�����[S�~7��j7�����i�L+��X�y��N�DJ�U����<+�|�o�*��9����,�U�I�yH���4���vp�F�VjT���v*j�uG��`S-���q�W���8���.�W�(�3$x��T���z8sp��J�$Z[�*�,��:��r�W�\>�Vgf�1p��S��b��y�������p�s���z.����"�.��K_4m����	Z�Y�*�
Z��yRX�T�n��Z����U�r���7j;��s�<N� 7B��"�ly�Ez|@�c=���:�*1�u��WB��A+5��j �5h�F�lr`
hE�l�0`�Ck�SF��@+oT���o��M6<�M��Z�����yn7�G���amT��s*�up�b��Z�E�l�VI��s-0��2�U	Y?1m����	p1��4�!bWyZm�c�����-����`���u���)v��%���rI�WK�J���^��jq�����7j������m�z.������������@kFK����9�h�������+�
^�Q������Sx�F9�(���J�����=^q��
7�W��p~*���*d��������r�)�����:���B�T����3m��&�NE����.�����I�28�J1����
Z�IU~��R����6�H�����c���a5�vC�Z���bm���-���EoBW��
�V��i^xz���&����U�x[Qo�,�V�������D	�*!u����lJW�h��s��b]5����j��	��Iso�A�C+�4���.5h�M�V���^3h%�j(��g�h�bw�������whzKW�<#j�sp1%zJ��vM
�;��sgq��e��T�
_W3�����d\�eZ���rYF��R��8��BQtWT&/��
}��.7x��r�z3�]��o�Wx�sx�a��+���P�yU{�1�Qw��c���*��^���]��ZWy}�:#]+0��fmk1#F���QS"l,1���m�a����m��xO����f�0�T~�,��W����=>&yo*����X!u������5V�R"��p|��Z����`�;��CRm�6������(�mJ���G������&�Z�+?��R%���V�dT�`8����ypk���c��>���Y�|yl,;�������o���/��A�����](��&�mH���@P����>7�����+�r�,�*�a@���i�A@0aM�gP���xaN�����@@����KG@�FD	L�����)�

�
(8��h����]l��p�d=��0P;�J�	�]��`�}���O���I����q�@�2�8���5J���FI?S8hq�Z�h� �C�����:��/�3^�Zx�����'cTm�k5��tT�n1���k=jFu�*-F��,,�"��:����-F� ����Z�����}��M?L�u#(��H�+,�!�����h{%��p���#���sI���["�P�0Y�D�������5�$���;�t�k�����,�F_�L`F
�uS��K��!<���,��T��K�P��y�.,�<�Z�3�r<�[���N��M�����Zp�~:&sA���H
�$ Qy[r(���x�5��_s�1���aQS,��W��:�y%U�R���I���#o��j3������%3f�I�F�1k�����o|��<#!�fsA��,�t���(��������H��,
��J�R�C�����D�R��S�������a��������)���9��,]��Y2�TK}�_S�)������8�R�6t��#%�b�@���#�H���4�F^��8I�b�4BV��mqb�Do8����H�8�m�)r���$c^F���'c�'�1O��G����()_������P��x�J��������I}z�Qf|�rc���o��|��w�?�[��}�lP��-��r1M���=�����]����K�o������i���q�V7++������_��O�7���OV���f"�Fw="�1��(�L��V'��QH�T�kzS�����'8e`�G���k�v�d{�4����3�y�we��������C��4�,��B�����y �p��W6�vf�L�
q$c=�>*C�;�NxY2���9��w���)g��M�ehAH��!��7�Aj��/;B���^N���7�Jq��m����s�T��#
��J*5f�X`
XY��>�%O��t�6d�h�#��J��`d�#D�`	�Xzf�8F�!/8��&R[R��x�@HeJ�s���F����������F�)�%�*��Z��&:�#u|Tz,�!�K��>R���
D=~����%�������@�o%:�y�p��r��z��������Jt�4����YZO����DG-F\wx�N�N6����|N���tx<_��L����� ��JUY
�J��E�vL�<�c���g����!$��{�L�Z�l�mJp���:zSf��Ko#i[j$L ���w^�m$nLm���H2���K6�TB�����6�Bj :C�xCI�<&9�3.J�)KZ�ZQR�L&�J��NJ��Fs�-���HC;�d��b-r�F�S�1R9NK��n���j7tr�}7��q�����<_k�k�<K�4H�����nF|v�V�^�OH�c�V-���N��Xi�kN/�����Nj��w��2K���F�I�-���a[lZ�1%_�L�myW���.������d[��
%�k���2,��C�����o�d�$�X�Uj���N��JF	jR�v�Eie��0�>�g��e��LIVGG�
<�a��OQ#�m@����t���tn��Bg����
��
�w��z�T��\�:VlT2�r�j�YG�H=2���V�F��C���Z�/p|��iH2g������IA�C�T$&�4��$��t~H������@I���9��$�9>�Fk�%;J��JJ�^�z��Lr�����8��Xq����`��L��4��>�����Z��\L��YW�
$���IZd��4o*�Q?�S�_nj��j7��R����m����=�ql�)�k{!���2�-Gv����6�;���
��t7�s�6�,����s&YvJ!��;6;�5v!���fIX�f���
9�����������:� �����+�@N0�d�6��B��K�Wn�)Dl�WS^����6*g��������P@�<��R����CM�%M%�zq>Q�oCNX����������BN�������n)��j��9-�2����B0�)�����B3�T*��+��0��������v����c}����S�c�y=�A��%��p�;n�1��&�9���J`a����`�S���CN���.@S�#'x�E�
�����;��M����9��������jzh�
�T�XPm���S��*3��;�O~���Z���=���_d*m���e
|<��-�����\�v���S������R:�vK�V���cw���Vz���O���t����M���QG_���
=�.O�S��@�h!���K���L���Q����R�:�quJy1�)��:��&�9~j{,}N?as��Ew�Oi�d�����<��=�~D:GP0(��!���i^#e�+��4g�-��#�0�R�N~/RB�{�
����#c������S�a��8���S?W�?�
Mi[���������#[.;�����~������-�Q��s|t�!{`t+��h��������J��8��g���%R���s��M6���q�uPG���({j���1��%
�@��K`��0=i��%�QV���F�����F���N���@��a*5I1���.!m��k��6��^�W��
�+�j]��R����B�����Dd���>�/�['���a�e�"Mxr���~��M�D�+�Y�\��*�'t4dU?����rq�*��M �U-n��6�%��������������J�����Y����Oq��t�5h3[��H�e +U"u'A(�U5;�n�
F�����,��M�!�CVm����4s-�5�	�@V�(�&���)��F�v�Ao +U!�nmY��5���k�_��U�������2��`J��d�c:�S�@����w�*O+��]��6Lk3�E����J)��i�������������a���V�����jq �T��{V�r���[}��iCX!��/�b����V��7Z��>%�y�Wk�X�5���*!����K�q��$�[�_���xO����`T
��T����m��'��������/d7|�G���*��
|��gW��*#�W2������i�F��L�6l�������Yg�[�����qhA�a+�����[�����j[�6k�����x`���8q��4�jwm`��N�@W��-~��[�U���7"GW�v��e�fq����������a��R;4G�lL�U����Z$�U�(f���j{�+"��
���4v��^*�R��b�
���7�Ta�^v��a��"�|�M�!-�k�<b�-��i����r�f+'"�Q�k�~8�VO'e8�
)�����?�TK1z'"�8�-u4=�����y��T���B�&�>�gm��������p�D�����r-������*W���n*bPg�
�t��A���Z�3x��.O����S�o�0
F�6y�!,�ZO�b35t��)5���I���d���6���`Li`����}�cS�Q�u M���`�w�����S0j1Rw0��R�%:+�Q������6m,M+]��^�"Z�U%�^���(\rT��U��s4� ���S��T|�
����\�~�����I6�/��&���U-n�d�����������c�{W��>��k���B��b��z������e�����Wk�2�aA�?��+VT���T�!,d����v��]�o!�o���T�#� ��l�'�8�
a���&�Wa����J�a�6�"�j����,<uVV�U�����J���C�z,hJ5��b�J������ZGX2�mCe�G�Vj�C�g�A��E[r���
�A���S�*��BX��!��JmGX���J7�jW����
4��c���z��m�/�x!A6���Z����@��-EX�"�L3*_��xVt�h3�k9����`�VE7�K7��aF���]Y�3��b���q}�Q��Kc_�����������t�q�����n=m�}i���i�&���'M3�K7��s����E��y��n�s��4������b��J����0�L����f
@���c%��!��\m(s��-|�_��xt�����6�\`����Ju�&��Kh1��S�]�G��^�$((�9�4�
��^�sFl
*�K����
w���QP��J��r{t=XQ� �A/����7���+n�	�9:�o��/�k�*C;�@-�~�@��A X���5Z��~�}� �"�����t�I?���MG�h2���A~o��0H.E���J�Z��^L hw�r1������Z$��� I/nB�A������p���N�}�V�4�d����Z;1B����1Z[ 0�yNW���#"�w�S��c�ef�4��r9!Rfp
;��,D	�a�T�����I���j�A!���������k#pP>��_$���y$�1�R��"y!5���	������,�����:�I����Y�F`=��R��:��h��)a/��ny��4�,�6^��
�=�+��C���q��=�n,g=J�|3���Z'�'�D������Q �A!��m����F��t32�iIQM�kIQi��1I����R[O!��0��4��X����P���&���`H-�"<��fzC#����(�Hk��Dx�y(JSj�*��9��b�k���x
����uq~W�%0�eJayK���md�d��V�����J��
���M�(�����h|,����He��z�w�e�R��Fi�L�XQ	�9�/8�<VK*��R�\2�v8����%�������L���������6$�^�b�
� ���	.jS !h5xdC��e6�Sja�^�������x����^2�G��i���)-(��|'�������j	J�lk�[0�|�GX�wt�C>�8���4���S�46e<�)���)n��������OG�%��r�v���i������(
�*�
��	y��)1R%�Ge�
�B�G�FqP��T�G)�v�4:�
��i�G�����?���,80�|Ht�	J�<~T"��x���AO
�>���'�]��J�3Bu��`���&S��cr�,�*E JY	�ke-�J����1v!-w�g8)�l��T���FJ���#5��y�����&	H������#�oDyQ+��V����)c?�GeD}[i���#X1��0�yk�(��S6a�������M����
�)L���XHY�)��,j+�~�eq/z�uP�|�)�����4Vg�"tHZ,��{-k�����O6yIh�T}���
&[�P�_�;q`@���),R�ki�����u���C����(Q>n�Y@��S��Pg��N�u���Mb�cv�(����/����[m���Q���N�
�%��Mz��4�X���v��MYC+}`�y�V�4�J��[��<���LF����$�o���\�5[�X(M�3zw���"<���/�!N�O@����4�=��*C���=:��X)��R�kC��X�z@"�g���N��E8�r\�����kAF�?D6��(�~��O�3CHp�i�Y�c�����c���@�����E=���RB-���8�����~��	��h���6|"�ky�
,�l����%�;F�=�S�����S�����u��b'�����E� N
����V�EY�:Z,u����"d�������'�^�MST'��N�'2��Iyj���As8NJS����'��v��~���h�)h�gM��0�]2%f����R.��p@�7��P���@)=?�h\�������Q��r��;*������_�����l�	����R7.�nH�Y�b���$���^������@Y6U�P���\`dndD=��v��]�s��
���lgnTgJ*!�!��(�D���	��c��}w
�<���Y������8�,L�����1��"
+�L�JZ���Jo
*�c�`��������+�����x.�X�����C�<N�w���.�s�m�p����J!a�k~*E	��F� ���[�\=�Ji�l!�@�ebL���V�-<��v��T&@��13K(q����Nb�)��"H������jM��!��d�fC��Kw�G����w�����}���
-�!��u�Z�!���gCK0f�l2TS�hb�����a����x	�������/�O7�O��C���o����L8��t���s2!�[�])z�v��q�2�
��MJ�Ki�:"���h��������4��AS�c-�/��t�L������{7-�ts��x�J�PSoN����SNm��Z��(�q�������:�Nm��B+���kK�{&�����y�;t*=�T��Si�6�)-�d��>i�<jOm�*�_�����kOiM�DjZ������
����;x�=h��)�)1Kf�L:�xCy�7Vx�??�����x�/_�����$�B�*kzn��Q�L�0��f��6�R��(2���r����Y+nd�P�'���b+I:��4����S�SIVQ2�*�y�C�{@#HO6�3�isl���js�:;<a�����tl8*�/��O�
G�96�zZ�
G�9��0KA��2'z95+I��rB�������o7�(,�CP�y���fJtGQ��E��
�1���`w�=�a<oj��@�
^�y�l������|Z���^��^�������IV����K�.k����^hR�&���.���C�6i�����w�27�N�Rm���Fh�q(c�`��I(��Fx�
%NiF#�����d#p]�*M��@�+C�Si��-��IG�M�l��
is��<����e�4-o�5��7�~������&0U?�TTKzC(�`�o�����3����=De?�r,=]�r�R�
J�e,kq��NBF�����wE����@*���5Prj�Qe�Yn�I�&Lm�g�RU���/�����l�:�[Gv�)>?�w�*W�-���
B�=�u�����`����l>`���{�e���xy�l����o�mP���Wr��Bp�O�l�j�uV��SF/k�^0�[gti{Fo�!VoK�4uj�����J�[�_�_��K�n.-��$s�2xN�B��R�<�{���?�6�R	����r�@S�C��c->4zr(r
�b�z��2:j��Y�_�Q��Da��)��������M�C�Qkc[Vd�/��W��}R��>�m��T�4��b:h}�%o�����@Se��t������p
�7�g��|�eb����(R���~�FR�c���]]�I�����|JT��j�*�VF��#�X�Q�QV-�Bm�*���H>�����.��T/����-���[l�G�z���+�c�R��Ov�WX9��iY!`�A{z�d�R�]�87/@V�y��vY}mj �FM�\/;b�j�M
�d�b����!L��T]���<e��I�{
b�M�:x��X��$����Mo�c�~�X�(�M��\�X2j���V��������@�7�C���N|�%9��>��Nq����c����b��R�3�x{�W���__�M�+�v�e�w�a��� �W�=��Ro�X���0V+����5��
c�X�l�=]��+��vO'��+���?N�l�F-V��&���$)PV5�{���[���QO�!u�U6U��������`�5����@Ym���)0�bCY����VS����BV�u�,lTo�c���|�Wr�b���T�QV�Y�&�	U��IV�
_��J����s��:PV���5)���|�nYay����=Q�������T�\��j�
��R;0V.�������y�O+�*ogp_�^�lj(�5Y[*�*7CY!�F46y������F`�s�m1	��c�I���O�L#Y2i1����lZ���?�ca��D����a,��Q�[�c,5Zgn��J�se�{em�~���C�a�����u�X�*VbJ�L��a������ �Vi3������:f��Z���M�Ya��$���*%Z�S���$GW��9�j�'r�F�!�a�q�p8|����T>����E�{9���Cw[aL��^��t��cD,�A���-������/��2"D����&u��
�5�dr�|���D$�FV��q���ND���y����u�FQ!�x�������ZqY��t�����E><F��d��>[��	�����}�]���*X94D�uwb��1T�� 
���u�N����F�N�#;T�n��rX-ob�c5
�i9�.;�K����\K��/�!�V�i���Rm�^�����5�n9�G7�g�	�uKM�B�d�a�Z2P���E e6���O�@~��J�"�XO��"_�0�D
}��t��D�"j]K
��IZM�.�2��Ve-��!��Xhd�A �Do�N�6�/M�k�E�v3�oO���U"3�S�i��9�>D#�b
��g�G�P�@Q�>����W�#����9�!P����+�n���j�C�~b
7�z1 �C mu~��3:	�M����<��Bm((~}tnn�8����J���CS��k&=����_>4M�Nj��a'�c���SE-*���d]%>2�����u��JFl;N]����Qv�3����mp��q��93aR "-��X�������Z,@���������umj�f8��CvX�j�n��"MkWl���k�i�rX�� �E����
��o(�p:�-�&T+��:m"!�<��:4tP<����6	#�������2 QZ�%�
�(,��	s��%%9w��v�V��!l	�unp��`_cp����t�D�dla"�Z�+�@yj�(i�������FtM�u��%Oc�����I`����u`;pRF�L�%���H�dP�h��������n�A�����&��E,H��B������:;s���4��N8�����Z�	��p(%X7���:������7�/�,�\'��x�TS;4
 JS�y.9�mJ����%3�:&�����i[��D���S0���i��Mq����Ai<�-��$d���i�(����)0f�LD*��(�l5y��B#��NHY��28Z&U/n�������X$k�(���Jk�������Z�|���O�J���m?Y����LP�-��2f�t�n��He�5�5�*k��>5jc���	%��@aCIm�E|:Jj[� ���k��@I�d>��H-v��yY����q���L��!��[F%�P�(�%��b��B�::>=��������RD�|��4c�b��������V)�����?��F�?I���7(@RP
!������+�$��a$�{w�(���Q-~k�Nc��D��GK����.���J���{��k������8L�1k�eL�-���I�
�����H[*Qa>%
��B�t�v�)�"yS�0�&BI��Ca�S�$��%�,���2f��:I�<��*���G�u���0�T"�1�N
�@R��e�-m�K�r���v��(G�@K0);�N�7���S�]Z�t��������8�s���
'�����N��IP�7�V����B���I�0��`�lU2���+�W^)JJSF;;�`L�"�7��m�]3p���dbq�{0�m�#�z��H)�qz�'�HI����@J�G-���H���0�v
�B��}���y����R����xP{��*5&��*�8����+r����'�����B���FRzON����R�%�*]�a�K�w�����AS��M������s�����=pR������`K�����6�8����G��1��+�
+yk���4����������(�2�����-asj�O��l�v�iP������'@�x)�<�x�</���e���G��R��)��>���-�)���d�L�$�L�@d��n
-�oSx��)!�!�~�
2���Jm�
�� �<>��j���R.��9��M2*�;���m��Xx�?6SMh������i�I�X�`��&nMi����x��|���5���d!ff�'/���N�u��Pk�T2�&�p�bIZ������������/�A�6!+�I�������`�;�W������QJ�����Xn���[������	����\���&�MD!?�����PS��s��������\���P�|�T�l����5�g>����)�3[�4X�B�LH~���4���ZH�@E
�;dj	������)6L]�vw�>R(3�"��a�G���,{���!f�b��������!�2���&��xY�f�u�cz(��1�d����S�mK��T�#L�K��mx�����_-��R,5���f�3��r�T<�����L��\$�s���X�d��&�0>L�p�0S	Y�&���L��xR
q���yQb�!33g
�4�&c���a-��$�����,X�z���7-�$W�{jYy���k!�u�TB�N��P���L���i
;IH�H���N
���Orj-��	��9��)%y���{�p�6
����ZFS���r�O��������v��ny��~��M�C�����7��V[W�z���H_��s�����K\�Z5P8��bc5V�<O��j����NP�z���6+�;=�h���������k�*S�F���2����J��?���@Sn�M��q)�`�]�J��4�(�����$q�<5��1b��!)�������aF�����>�J��f���n�xU��5���(d��e�o�pyn�����:/�[��o���@�S���k�y�����>�.nCG�����o�2
�s\\���|��s����R	X�c�J���G6����0�������!cZ�5�x[�
C��������+#l��l�5����e����&��MU�������h�p�����r
16��,~C!�a'���K�c
B
|�~*���~�@P����=�
x�Ib�ud��
�h=-�]�-��r���Z�!g-	��#�;�~�x�ZN��Z�P�j���T�X�n���{'�)k����%��uhUb�>�������������uc��`TM��`�� f�Obb�����^�������h7�)���Z-S�6p�6y5)`��}FO
m��Z��2'\��b��~�"R����.��y�d� �2(>���W!f��*MR
���^��uz�QA�d~j�4���4i��x0*�V�t���V�!VU�����Nq���J�
]�sA�+lZ���,t�B�@���M��1��*Lu�_��fGW-�zC�t��*��u�����D����l<��������l$��N2��<&(����v�4�2\CWx4/D tE���������������y��2����b�U*�B��v�h������|�^/�����&��#���&��6����Y���8~�fw�Q��#�t ����~�<0V,oa�sla�R|Y��-������7�d��
 ;��X�&����0�����4��l&���� ��Y�1I�0@��q�V]|d �b��
�FYm�lU���� �e���L��,K��>�!� e��O*Wu�emf�������l�J��7j
�����,kc�����Y����d���=���0j ����=zM�,�����0�@��zY
�n�r�Eer��r���Z����k���ZGX��� �W����bGX�b7 l��^��lC�s6�a���������1]��+�Y��
����hSIud�9�����G���`�s�@�U ,U�s��v����adRJ �����
M��e�,M�V.�gt�T�����"�h������J��E�t���"Vb�k��G�
]�.�������I��0�a��U������,I,�iD������m��N���;�7���V*��~�8V��������v��E�j��F�-b�b���g��<&M�6�emF�G2�e1�5�i.@�X2����n�!���+' L�p�E���@G��`��{�)�������`���>@��8)��5qR���,��+��6^�W/�����t�W%f%�Q(^����RS�y��Bj���_
\����u���U*��_.wpU���U9hK���ZGV�u��_n@���vd�j���W��n�Uo�Z<�����X\�d�/Cv��j]�&���LW���m-���i.L��I?<+���S���fL�:��,i�(�%���n�����\�	��"��t�&���lr#:�}�4D��"��3	��O��tV%��P}X��Q�����f�fh~�q%�zB���/��NO�R�j��/�G���6�^��Tl�x:���MDJJ����r�LH��~�Ho������p4@X��	���@XZ���G7���e��}�>����,���(~v�oL�9�		������4�&���>���s~hT�����$I0-��O�P�����@>0��<�|�N�I	��P�9�)_NF���m�5F
��KXiU���1u��c�2��W	��G�p �|NN�K�*��3d�7U(0�����~��J�N�rK�)����l�ZL=��B���o�:��M�*c9�VoQ`��+���S���@O���H�o8'EL6
#�"�>bE�3�XG�������"r-l^�_�x��"��'�xfg���O����a�7/�J7.���l{mNK�YE��}��r�e�t�S"��]�pF@m�;i�� Pj�X+��RDC���Z����7E-��j����*�Ax9s �g�"����M}�S���[�P����_�r�����9a���4��t�TgJ5����F1]�������g^��2�[��:`bL�D������ |��l�5��

���2�h�HIsqc>gy�d��Bc���6�J�����f����z��TD��Z���1������^���7��@�,V�+l+L�)���jD��"�F~�rr��e���hlP=e&�N9��rq������O�2at �6;R�s����I��V���kX&���5�,T��0)��	&����1�����O�1q�����P#�0)��I��34f�f�8����aR�R��&�`��R�z2��6fAn�I6��8Ljc�5,C.	��Dfs(�;���v}h@)����Z��%�Wp��4�� ���jk��R���}\���[���v�T?������~�b��'����R�vT~�x@e�n�i?��SK{��88Z
/�}#F�
-�
�����=�
��@�+�)^9
��V����@X�n4b:V�����~��m���4�6�oCP�)5�!��d����������M�I�<��
�|Z��R�O��aCIi�M��
%Y�Z
��+JJC��������PlC��O~����O
@�^KD��[@�J��|�'(�(�P�������:�dTY�n�Z���^�o�*���@#��%�v_���S�gPY}*�K��`L%�#��
m�R3|����������"�o�Z�i����l�E!���wD����U(r�L�+&������
$��Z�B�[#�T�,v�����bR?����l69/�a�]M*�=���"���+�H��#�\�9W���]!�n'���9Wz�R|T���gS|��a<�CKe��uUk��Q���@H��v�S����
!^7��\���2�7�#<�����q$�R[�8���Z[GZ�N�/�>�+�G��lL�Sy	S�$����hUo��)H*Kj��J!��q,���^M*!OC|@�I�4�zGWSm )��_�� )
Y���I=����i�$�x�p��=�#�����(Y()�{���2zj��T�R;P�%C���=�H���Y�U,^	=����J��H�f�o���H�h�A���7��;X�9�A��Y����'w��%�cP�k1%YS��KR��#g�����18i\���,[t�z q�yn43_{����Iqx�4�0�<J�h*���oH�jS�AHM��l
��ao����[n)a9��8h���rKI���W	-����i�Z���>X�������R����n~�7xB[��r�t��%�B��RB���R�$Dl�5c2Tp�M0g��.9ljs�}��6�����VJk���K_�&lNI��7�������[/`31g�NO�
!����h�'R�������&x�h��i:VS��I����RS�
�=��&�6+�Rrk�M�~�M8
bM>Ls����r��Xe<��)�l�����i5-�T�bG�T��r�P��t���d�M��e�$�7����f�	d����h�Rq�M�0F+i�_�n�9�%��~�������x���Pl�-��e����3�5�/��h����>UBM6����p����|&/k����n�9������Bl�\��J�M}�=���p�����������^�M��M���M���o���2����7�T����d��������j�L�w^��/]�OG�R�a`�Z���3�3�����i�,�.�1S	yY�H����`��h�)�1S�S�f��Y�!�X���3���H��4�.���6����\1T/9j�5��W�fbM�f�P6�X�u�������E
������l���k�U���&���x��
-���r�}��9njsl�6"�lN0�>|��F����~�A�xi�	O!O�8^x~ct��v���Z���Z��u�vv�]?���>��"v�������A�.��/���T�e���M�"�:O0g�0@
q�u2���Zn8����X�Jf�=��
��_���&px&����@O(�u���3�x����FL$u	��c����~�O!d2~���Uv�t��9�S�y�\��.?�&/���RgW��1sD��o�
����}��	A�!mB�a6����������xK�V-���Q�F4�����Bm��q����%�Q-`=G��0*���M��}f	�����2�6�$1���
��Q1
z#mf	5��=�.��2�X
&�VS�����o�MF:�3>7���n�r\M��P\�T\Ubb��R�>vL*>���Y��:��w��UT|r'1��X0��)��2lE���5_z�V0�]�����l�
n�N��l��W}e����%:��<54���9���
�:us����s`U������z.d�L�Y	T���*ty�����Ut1��|&�����
�*&B��U2�&xAt�J�duI02�a��7vk�/X�mZ�AS�������DL�<k2�+riZ�M�����C7+�
`U�fM>���d Xn������RL���aV�����4;�^&���z]*��6����u���&JZ�@�u���6L����U����1&�U�x�<�XHa����i+M��M-`���l���
1Sp���`��J�U��8T{�UiR�V���<^�&Uz�O�	w��`RE�B�|+�������*mz���	p+�4��`E���^5���6�`�uA����w���u])�
]J�\p8�Q���T#3
�s���U�)����X������
�|���u�&����M��^>����UhC���*#V��
]�cL������U�A���C�{�A�T;����
�Y�N+�J�q����G2hUb�jW�[���J�R4jb:�Y�S����u)��+��4������f�=j�
;5XLE_/�d�bY{b\0p��k�9\����F����=�����,jbj��S�P�d����l��'��Q+�S��=y:X���G�
)�E�6h���+:�j����Kt�j��
���"p��UKi����rGW��	]�+��~�x�|A�����*X�=y����C��D�\�J�����zV���u��@��*�<����$,��E����i�k�I��buKdT�y��U�d)��6��E�v�V���k����d��i>�M2��<lU����B����2��	��Mg;
��B@�*�5/���h��Uo�d���o���	x�:pU����L����J�F\�ny��|�-����!j��GC���n)`�w�T�Q;@��T��[�k�ZQUI(����T�/���d�a���5�1Zx���B`4�f�u���)Z��O
��j{l���@��4��i�N��
�9��Ao�wn�Z�
��S���EA��k�,L��&m-Q��TH�D������`�A!�t��B�Z=Xk&p2������
k��2:J-C7?`��T.
O�-�m+�K06����9��j�P��	B�K�*�6�P�)�^���7:;zJ�<�����cwNv���q���E���Y�������LN��*U��E�u��e�g���Vv`%��`@��h�%>���������]�X�o5�R�w��tV�����?��V�B&��ZM
Qy�������w��6�h�U����FP��O}�'�Ni�=�v����--�1u�0'��I�p0y�3������*��������l=�1pW���{��L��i|���r1����������)!<ts�m�'������a�
�O�n~$ ��p~t�q�	��Z����l�"&�d�G��1e�:�K~�h���6���%��|4���Y��V�R�@�� ����=f����Z)���9����t��������,��W
�Z��KP���Nv"�:�� .��@����K^�:j����
����� P�o�=iy>T��� ��LA���D���^�p+����������x����))@����tm��BD�����37(V�1Rqi@�2����o�����jC��
������YZAe�����h3�`C*���#TZ8���jCl��Fs��M<�P�8�P�"/K
��!GC���N���Amx(�x'���q�I�B���!�A=2^������IQ����5��rq~��O��t�^�6���
�/����K��_�N�,k�V��*��KL�md` H ������
rDT�X`Z���zD�)A��'Boa!����(w��mtnt��Kwd�p$ Q�a�7`�X@��4%�#$�*�r�2�<3-�������E-�Y�SP����:H�RZ�b����r�8�PHm�������w�]���O�
��QzG�u����m8��_V�#���6x�����t���H�&c��-y��y<������� ���}��t�H!�����<-� �)����#�FiJtdA����54}�C$2%a|@���b��� � R?��M0CS���	f��^�4$����c��W�/0"	�����-�.�1�c�5U9Lf�����`��l �����MQ��)*�`�I�0�� �~{A�u�T?�2�S/��@R��/$�7��JqI��T� Y�i8o��@R���w�:H*	�{��Q� ��q�ss���L��pCW��n`Cj�H_+:<�]�2�<�G�
��(��c$'����Q2&��<J=�FG�f:<����x$S�8	��V"��<l�(�0<Y�q���(�x%���~�nwp������[�T`d3��9�Q*�Tl���h#�vC��7�Fn0�GGAX���`��p�N�7�0Jl��q�w����8�������
�R�q{>�@whB*q��)�&X�662'�S"���p@�)��5��{�'�������(v����"\&H�����(O����4!���M��M}���M�m�����|OkY�$9<*C�h*v�wT"�E�z
P�>p�w	�?+@*O#�a���!TW�(Sr�/�b*F5t��a��v
9�C�{KGG���n�v�����L������<%��>��//�L/�o�V�NO�����
�!Vz���)V4�C�sF�Id�j?�:l3
�
��eH+f����Tr*��}��bj��
����/���)�M�Xk��b����x�'��~��P���O��F[�;���\�5c-Q@����v��i��w���{S&�������G9�l��p���A�5E���Qb���-�I7�B%4�jm�x$������K�JH�������0��<�Bm��lu%-c����q8����t��!�R*�,0��ab�)81PQ	y�����J\�q'���s�&x����CF�����#��HQi19e�91l��X�[^��MY�@Az�s��f���L�:>j���cE��
�"�Z��Z�l����!����n�H
V
 �������c1fUW��\?�\�#�r���6��'L��PR��B�w���%��X�L���+q#SzB'�H�'�u%��FjS�P\���l
�{6U	1R5�()���T�����z�������Gi�PIq4#����mY|�t5:J
S�(�&dJ�)8}C��*�s�T���k-��t�5�r�r�r0)}��u&�o�������R��LP�H	�C-�8���j�P�����C7�S*'����|��Y �`)~���cX*#�����4M�*[�!�e���4frVT�\JcjH����j_�0#��KiJ��)��L�e�BJ�/u����,��bi���
#���F��"j��K��8YZ���e���\
=&k�o���|	T����>������4������JiH���k�Q��byZ��n�G
MM�Z��k!���r����w��w��e���yt�H�S3��5�bG��p�d<m@���+�G	y�{���c�q��xDu�����m�]��%�b�)0��M����lA����RZSi��r;���yS���4Bt�f�QS)f������'
3���=��x��������Y��dN��Z�������M����a�i�	��~gN����N��k���H$F�@O�,�R�t��Rq�}�N���������
]+N�;��7�����Y����c�]��Gg��kfe���1�K��w�#�Tb���H������3+$������uY��qCP0hI��6��S'A�;:�S��S�*���b�
C�y:0*�
z�f|ld�PT�9>j��i�hbjRY����}�U���R��&����
E�<X���)#��p41h�����R���-,o!�����YJ�
���r��R���PK�~��La5��~����p����5�fO�PTX&��K��*%��2�t�����������HYdT0��v�=0>ZMr�=��e�
&��lRY4�()���a��V���=
T��g����Mzy�&��:�*]��1��(���1m��6��TC���Z��h�5��A*��;�\H%cb�^�S"5��<�t�68���4�K-o��~���),o��U����~;�S2�b��o48��i:��H�tYt*��������T�Bf�
8b�k�`��M_�:�*���s����BH�!P=��J���\��g�S�G��S���x���M�9^S���O�o.�Tn����{�Se���,���&u)���;�O�n�S0i�����.m�	��J��3�t�<m���i`�#s���i<�O��H��M����<����<�Z�������7�idi���#+�(�R�@�/�4��RN[[�^
+\�|�o�*�<W�*�u-���T!&��	�}�4e�/8V��TA��;��Iu��B��>��M*Yy���z��C�@;���M�]Y�h�`�M��<�x�x&g����S`����m��d��dT����V0��� ��)�R���C�����&-�|��4}z���Z�,�����F������*���61U���^����%�MU�;sc��k�M�o~S���3��G�@��5�Q����l,����B�
��u�Q�Z��J��[�@��X%���P� {��,������]�kq+����qp��,���gda�l���*�d�M�����Al2�&J�Yt�(t�M0����*{�Tq�U���3�����Q���
����i��4 @V�	���h����i2���fw����f|��, �U��S��X'�d����:��r(rpU��B�/Uwx��
7�����_���
7�_j���5�S���-����Vx=`1������*1�5Lu�D��B�s�uS���
a��Z�
��@X0j�G7��F��6��������6)��tYv�+ZT|�U��`�;e
���l
Jo]��*��tQc��R|�R���s�7|E�3�d��a��M�^+LK!��J�����3
bi��������Q���;��Yi�w{O
A�T����^���W����V�	gay���Ma,=�<���
�L�hn8�X��"z���VIx[�v�y�g�k����k��
�BJ�����5CYiQm��2��Ek�VI&1,�3[�ab����k�+~EX2�e$4��������
.WKrJW8�j�^�����&��,*�l�����d����Q�{�V��[����U;���������;����T�n~�}��"L#j�y[||�R�&4��9��Z���_�mP
�����T�nR�;�QR;���F���������������c��R���u,���Q�>���A<�,��J7�&�����c���^Y����CH����5�b�MOl�����j	��[�9�������a�fz�SX(^���l��+�E�4��8o|kO�]Z	��mHi������$��Rm�R�h��h�&��b�Q$f
�b������6QN�#��6�&��"2nD��tA��n~�&������Zg>	3�|��8��8����+c��
���8�t����<����,��R�����6�������.���n��+���u�M�1�MB���`��3e*�i	�FM�w�Am�M���r]�%6d�Z�������P�kp�<�2ue�����emHm��
Ke��xS�LX����oR����wx,��x�
�z���9T6��
�����W�C���OY�V%�F�~�� O��Q9������W!k�������o����=���Tr���lw���������QYP�kC�����P���y`��
�2�zp?[���H��M;�EomH	�a*�F��5����7m}�
)�.�MP#SJ�_)�-�|�5��N��Q���f2F�9�~I����V�A�
:�]v#�4�&/;|�zk�:��3��rm�tQz~����_��c�\
��c!(M�L����!�[c�����~��dp�w������P�|[y�g�V�A"��&Q�X������0.�|tY2Za�&[2H��X�
�$&Z��C���:���8=� �a2!�D0d��8��C"[�\z��%-}��\O�;J!1�1��g@"�&4K= 1q����:$�%��!�(����tLL:&��f<�+�����)hM�d��~I���1j���
��v*PV�������k(AE�����L��B�z	XK�!�3T�2��
"��0�p�����-���);&j;^�O�01���`2�C"�FT����!3��&������&&�`��c��$�@8&&�����Z&�K��g�CjI���Y��-�a"�I���!i��D���)+&*��	��#Y�����8Z������	���)��f�P-P��yy�T�(7D��Y;"����@fl�����,1�x�$,v�A����\�-��������<�4DL��;
3��>�� v0,TV�6�U�*+^VY�%L�6����PoF��2!�A�S}R�0(����!,�+Cm����C�@����Q�G��i���;���dv(�C�,������k��Ph���!�XJR�A�2��zR
��
�B�Q��
��4��]?�Q�Y��\[���R�����2��X��Ocq����v����L��N�R��F�b��`O�f������=J�+Es,��
�&c�
�����rBn�['�����v��e����d�dw�k���$�f�am8!��K�/
��O\��N��.��4�y��zk}����������<v�o��JQ�����R�>7p�`V7\*J�)�Y1��4�3�cE����"=�|���a�:n���|h���	�k_���vE���Z� ���R�M������v:n�=.%'�'{k� �q��Q!��c��4���k�9�z
�������9UCNmNe$_k3�y����k9�=�\OYQGN��ES��h�)e���L=8�������t�M����SKY�.o�'CNxy��K�~�@S��"��e�v8���S�2��p��T�ZS��`�q6��Bj�bM��y��7�d�y{�����.4l�PS�]�P'�L����2�hO
���BJ�Z��1��dv&!85�}� ���jj{*��L�_K���D������	�cu�����`���Bu�e_�/l��>CL�������9-Z��:n�s�Sk�v>G�,��I2^��f�Ikl^�J�1AcS��
GL�2}2T���-5,����D�!�2��%kj�����j��wr��m���k�0S��_I~����~�������&;}���!�Zm	�R3�bj>Hea�F�J���.k �E��� �4�"�?�6j ��N3_��2�=�h���*��hPUT1j 4(2gY���\e��:v�E~����[4�����y.����&��Y�S��
����������udZ���.p�~�S��]M���{`����#(��
*
�c�/�1T���_p��3�o��rm^��U���P��
�����Q9��0������>T7�����)��5.k���Z�V��S�����e��N8�)��,
�?}�i�)��<��*�@O��:��jx
=��W��%;z��FR���A�`(�J���,�-��2��Av���y�n�XU-���l��&�9f�'ZK�m�}VK��U��u�D{��Bg�!���x 
ez
1���0����/W;f����<_�������:f~��c�7:;f��:/m�9}�1LH��V��t�>�,�M%�e���	�
7�+!n������&������q�,zq�����)-���r��\m�M�h�1=E�7� ����N���E�Z
7����/�v�n���W%O�h��w:��M�Eol�=��W�$>�j�;��x���:�D��s7����*cv���W����D&��myY_&��5�����P�r��&�n�5��g�Y�Qb���6���kji���pS��^��Y�����>2=_+V�%~��H�
�����W��Mg�)����FT0��1S�2�8J@;�Lm�3�c-�a��(&��TU`&����H�5���~�fji�l<9��;f�A���ZY�-��O�]�M���.�%z;n
M|���Q1n*��rt��7�5�0����G.������9-36�zj)+�G�_�<m����u�=�;v�G���h���/� �2�9��<�TJ7!��-��:r��y=��9�����&�74�8t��5%�'�<�TB�����H�1�<�������2w�
�Y�>��Mm�
�#���`����;f�!Co�Lf�5�2^�p����'�<}�v��9�������W�����/��i�����$a�|kkM�X+��z,+����0+��B��]M��h�9uD�5 g	Z!����G�V�"y����a%,��R,~tT���G�'(��&�������L�p������������
endstream
endobj

12 0 obj
53285
endobj

14 0 obj
<</Length 15 0 R/Filter/FlateDecode>>
stream
x���M���s���Oq�^�|g�Gs����L�xg��06 m���,�[�/������`Df0�{�����������v[~����-��e�������u�~������O������/��������?���?�����������6L]?����o���?��nZ�_�����~�s�������?����?�������~�s�G����������~�U��G���?g��?�H���l}�����C�����|b���_~����[�������m����m�MJ}�s��0n+��bo��n���������w��<
�6.���qX��:n��s�e���k�<�����n��-���0�g��8�~�����������7
��[��(�8X����K��El�������~�E��n[��_^������b������&������Z�_}��o�Tv��/���	���/b~/6��}������rgbc�^�'��_}7��������}7
+[���&W�_�
x��n��LL������(����ZG�<jF��:t��.�����u���v�Y"vZg����uo�Y ���������X�,��,[���M[���}3*�����UeI����l�w��fT���|�^��~�6]���JZ�uhz�����
S�LO�����������=����Foj���w���gG}��w5Db'�i�UC���n��nN����<���L��!��w���qP��{q��Z&{�6Db�/5�3�������j��8��o�8���5����+�Q�z����7=<*u�!�y�YL����w=l�"������C�&�F�#E����hDl����}w�p�3�uZ��������^z�w�A�.Jy��C�P�w�no������b�:�C��:��s7�s��G���������2�w��@hW=I����{��r��G��?"��E���5Z����������ws�v{9�e>(��f[$3����)4�nB�`0hWCI��W!������?�G����z	7��|��F�|������CR'��m[��m� Y������������0ag����ZH�4��k!���g��d3X	���
�J��]���~��d������3�>���s������H
�w�*T��������E����$���i�������~/��8��f+|����}h!��na���]B\%��{}q��������Zo�NMl�m��Z�*��5n��$;0s���� ����>�\;B��N>�6��i��p�V
E���������2OO�&0������0��hIM8�U�(�:{������*Z�vWO�Um�w����������*���I����]�8T9n�+]w4�P��������n������{�����O�Pb�=�u��}����h5���fD����B�
�B����I�����Z���([Jt����H��-B�!�#������g�a��W���5%Z��*�C�����n��������c/�A���;���|����}�i����n^���R5������7�o{��]���{�Hl?�w=Cb{�`^�w=c��0�7�<~��f?�c�fH�=Nv�=�M�4�C�^�s��u�2db���RI,�4�j;�{��+s��I�����'^����M$���]�����w���@b�y�Ho�\W��P#������v�]����~���~����i
�c�Dk}�No�	F�~��
���+�?_|? Z����_p��;�f�F�����mwp��Q�M��i�����t�7I�����|\e/�y;�����
��m��)�bfz?����1	4��$kM�p}Z��{�(Z��3�<I�w���6��B��[������p����IzH*����"�:`�mOR����?hm"��w�=��M���{��M���`��}���>$v��:|�9b�{>�!�������)�@l�=x������[��A�~�wW><���7t��9���~���o��v�[@k;|�������71t���-"�{r���$&����[����A�����":�=SO�6tK������upT���{W."vZ����s�E�P�w{��.�zW.�L+���h�E���]c��?�_��v����V? �|��~��s��9~���]#&���<8�[��8;ihhZ����^��G�q��?�Pw����;
�D��������yZ��S���q2G���q��>�PYIl��b��ff�)��([�)�CyY��,�{a��?���k$k��	�����g���8������K�P>��P>I�D�/�����O(R8�g�>�]�H ]��<�w�1? �����l����z_��%�:�ez���2����3��v2��Y��9�tK&{����������N��5E/�s���g�k�31���#x�M�����y�����l��3��E�V�K��ZSO]�p������u��<�Y��Zq��N�dseDv��f�@��k#rs�d�C������G�(4r����V�F"�s�5;��fZ�Y�rJb{QZ�!
��Jj�g����Uh$�j���Fn�������o��/tL�?�cH���	Cb�7�+!K���P#�J��Z���Ps�j������&������'I��������C�Jhk�	�B1/��."��k�+J����[jH�N�\��+mG�B6��p�&b������,�]O�����7mxG�zz����.��|/0��8��	�]1BO�����P��3z�j���H���Y�)�/I�Y�SY�u�t�$v9�����[�������#n�B5Y�����-@������B�ho�y�����]�	O���A��]����v��E��@�-�������?5!�<�%b�z���y&&+��F
�d�.['v��W�u��O��]���g;>����
"���'�9����D9B��n���(k�;�Q8��{��@g��������x���P<�m{�V��q�G`�l=�v.�����J��n�Z��oOx�\�Z�jF^�%���j�������&��f�%G�nl�b+�]�Ghw�#Z��o����I���t#%d�����������������������J��7���p���]�������;��{��z�v��!]��)T�%����	*@����f�5t��6�����VB���M�+!I�
���(�{�c��j}W�i��
���[���2eo��f�v5$b�����D��s����l�r�������!�y���Y	��t=D)�F���[f�^(#^��r���PS ���L3���y5b����<��(fc�rh)Jy
��j�mo�4��Jr���������������G�N�kn����b�~�M��R�� �Vs;�P���Np-Z��Kb�}iv�S��V��	�Z�TC/Q.�:������#��i��������^���p�w��~��0�=��
���������Nj�:����sW�l���%��C�/d�dMG�d��%o��l����T�[�u���<g>�	1�n�����T ��JF��M�bb�e?�o,�����vuwB��@��o�yQy|��BC���Y��&�����-�����$����}��k�_�bv�M�E��M8��n��7
��t��Z/����]�.
����������Y@��Q��	�Lbkv-��^&J�Zh�$��Ph�5v>;R���� $v�M����w�H@b����~?����r�u��oV����Z��O��bb'[�p=��f��������dL��s����-���%�5&�0;���rt��qD�x��C����Z&��@�$k��B;/�������d������7�Jb�z���/���R��2������R�n}�qg���w-�kK�w%$R'����v��S�z��1��A u����7�5h���c��O�@��o�P���������{��R�|�*3t�kyU�R�B����������#���5!�J����?�{rG?��H�?���#;�k�O����G���m���5p��������h�\%H���ib�h���W���b�Xb�#���5A�J��)�#$���	�M�|k�����w�5jxnh����%�M���������J ���O��g�N��z�����?r��C��o���;?s"v6������p�!b��"�����|�w�a1���]&v'�&����Q9�����g5q���'<�*)�����$;�rb����N�S�|�i�F����Fb�-?44����\����z�2_�E�����t��3 v����v=��M����	jB���w�oqj!��	s�f$�;�CN��'����	���e����\~�^�zF�N��&zF����V�N�0��
�oK��!����P4�P����|,�7Ek������>@h��E���]y4���#9��Ok������{j(�:�ue|���]�
"s�Q�~����
�����6�'�s�Bm��i�;M$b����2gg���5��e,��w�71���|5��������\���{WSI�DS��S �O����5&���-���)6�t���$v3�w�v������C�+�t�6�t{��+_��zD�l_���I3S�-��)��O�����P�_�B
��
]wW��[����"b';_1�����!$v�� �T$�7����F��~�!�w���&�m��P����B�F2��5��j�;��oOd���� a(rv�G{��G-;�p���v���u�&���5db���Xc�6�s6���C
\9yw��{";�������������q|5�r��q��	\�v���?���-"��
��;{"����w:���\���+l�wt+�_��P�����qH�����Q]�4�������#���tS)Mk������SuN](ktQ�N�F5�u����"�NIb�N��NV�%��a$�����wc��
P�*')4�C�UhZ������_��%v�Cbo=��)��&Iy6��������"t��;��Kw����4�B"��S$9;��Eb'k<Y�w�>��<�xt�D�ZA�5��\���_<���)��B��+m�-���q���w��B��V�<��="v�DE)�Y�2����Y[/�]�P����(ec{���2}��[����K�@�p�2����
�L����]E��/������T�DL���V��+��0�k��M���u������X�Y�z*��#��M�M�h�M�52�bW����u��������Vt5�?io��jD���!�q;d�����;$6���OhOi~�3"����T���-Y���(���Q��vosw�a����R��������om�?U�#��.;$v�>#b�A��j����=#1[]B�~BL�3�����������x���F=�T������d�h���J�iM��EG5��=m���M���PQ��dz:�x�������m��%�z����>N(t��m����H�Nk#��@a��#[��������_WG��d��������r��?ycnc7N�|<������0$�T������	5Z������-{��0G�H�)�y2l�b6/��^�,�����YO�B���%;8
��h��"��k���<w=XH�=8(fk��k!�yJI��Y��f,�N�v��#�w5������?�������L�������fd�r(!��)������\��%����z���
�����	:�~����y�M[zd(^�
����7�f��}��>n\�&4�(|w&O�2S,>���j���M��T�Y����> ��s��	=�l�����k�U)v=�,��0
�������]@��l���<��9�;��C�.��GW3�v2����u���B%������*'�A���$p����u%c0f�u�	>p���zuU��%����S��l�!Z�<���SC�$��pvU#v�f �����;"v�/��p��#;i�&G��nB;��+��CL��w;�B����CQ�XkI�+*�y.�/��d���5j�����X.9Os7�?��
��; ;��B;I��	�(������6w��{D���1T7�1�U/9��p������B��N4�}b���w}#b���B!I�w)�.�C��PHb�d�s&�8� 4��{"��t����(q5$b'�3c'��)O�f���9���'�=�	�B�XS>Ph���{���h���X�oI����`6�C�X="��r�����Y���s^�H����c������j��\����nm==���;�#�f;����������{���@����L�~d�C��nX���YSx���}X��_2�����]�N��9H����@�s�2�����1�M����@�|��������U���B�4��Q��Z�����:(JD�C�����+Q�N�%�!�+t.[9���P���&�[9���8������s����T9?�Q����j��U�7�E�����"�N�O���U���A�N �$TKR8�^[����n%���h�[�:���- ���j���>Vw�C1O^f?��+�t_�W������>S>�p>���
�f���e����-b�Z����l�J�l�.���}V���7��}����2�O-���2��w(�}6W�5�^�l,Y���%���u=/���t���Oh��i
�5,��a�;�������5@��o��2��+������C�~������?����������_���c��������n�_�����7���������������l�u�������,�����o�������������,^�1���NS7O����e��-�u��l��t���/��$��������-\����?���,������'�_����
��a�_2U��n��+��������ug���C�/�~O��M��_����ayWU�C���l�:�����g�������v�u�p�������n\�����p�w�q����n���u�������������,����n��������-S=�u���_~bi��?��_���v�u��n��_��_����_S7-�_��?�����k\��������~_��%�Zx_���<.�c����M��&�������x�zAf��n�If\�q�
/�q��8�� j��q���EP���ng��7��8��k��e��u%����
GEf}
����'�
�q������n]�����qg-�}��{zPS�_If�n�a�_2=�y|�:�i\�mKD�_���F*�4�m�o���U�/��^}��L����n�M�������*7�����g������H��=�7}J��:��2��If��~��4N/Ql���5Oc��pN�k[_�]^'�5�d�m
~i�M-^�n����:�^/��nYPc_����[�������6u�q_�S��n&���Q/~e�,����������/��"�����c7����g�����������L�6J	���E�����rXj,���j�(2�p2}�^#t@�g�������ZQ��~/_ZW����U�t���R���m���l�}{�K��t:E_��n�U���JB�J2}���\j��m��@
�W�N1U^_�'�MJ1U����A_;��8��y0LU��>�'�K�S�����d�i\��Q��a�#��;�.;���>�sD��y�J�����m8+C�����������@1��X��g�����z[�$�O�Q�8/�y���K#�!*	U^�jk*��d�d�}��ZzYf��JB$[���$c��BM��{q#��M�[������Kj��D�c��&����U��k	�&�W���Isc���W��%���U�y�F�����$�
B�F�+������K��4	�������/v�@��Q����T���_"����{�d��Y�x(��zu���\����}`l����*��9�j�,U�v�N�����+�����yM��{�UE������"#M��U!�Z������6Y�*5b�K�W��A� ���Z(C����Nj�U�������Rz��+eZ���uP��|�u��w�Z����4�j��r�����J�g������
������` c�W�=��[\����3�>]��{�u�Aop��L�-Dd�D���OI��VP���S�y������Wu����!_53���di��k�_��ys_�a�v+������N�_�M�*����v��e��"�"�"Q}��%}j2����X�XS�R�d
��\���6����D&r�:��4�W���Z�4ku����^phq,�������J]1�u|���F+�T����+�VM"
!��vf�or�\���������f������J��"��pU�l��{��"����"���:�j��_.�����*2����>a�Wb��|������r�W��^�a6��z��U��
�z�m�W�����������������/�W��V�U,�]���]=^���2R���%iPlw��i sM����0v��7��=%}E�������5t�}7.pN�R��R��bl�P4n}7����K
���m�����a��n�~�������_�e^�y���9;��3����a�,�A��4o��7���J�k�-wT������tk�rA��i#�c���*�������;i&�t$��������?���������0�;���������B����^���)����WJ����b�)��#�\0H|����[�#x`���*�~��?��y���c�"1�����X(I��
�^
,Dd������i`!���;�a���i#j�>�B�Jf,j
,�������B)��6%	�BT�/�
��x=�,�����:��nV<0��~�6Xn�EO@X(��Q������P=�}x��$0���C��?���B��������n�*�	P��[G8��h�#��M_�/���a��G�-s ���k?��TS~^6���3��k�n�$����F��
}7l�&QKq ;�~�	����'�0���s��t�]���[�-6��R�������5�HS��	i����~3JQ�i%�:�dK�Vzoo�:��Qc=
�.�a��a��=-�n�@_����n��n���<g8��^���N�� p0�*an���*��yZ������
�|�������p���oZ=���s	B����ZJ�������<�
z����w����n�}.zLaO,}Z��H�4
����(�Xn�4|����I��n��2}��Z��
(E��5���|,%WT�����r�����aeY!x�dO_�U�t(�
��5Y���c5D���z�^�ZN�
EA�g>�!_���6��8u�������RzaGV��kgi�F<�|O������ ZN�RG����=`����)���yxM�0���<4G�%�*5�yu����i�X7$���b��&��K1�$�:thv�$b_�}t���`
$��<<����\s�p���� an��\t���R��d/�F��R��#��+����9k��ce.�3+Y�J2l��	5�)�J b�%:�.�O�E}+3>(�.\�D�Q�����InF*-���<���������6?��G�9yE���KOv����av������e-2�0�y�����)��LJs��Hs
�DJ��b��O�I-�hu:�&`RY�	�6v�T�T��
k����Y�c�A��u��%��K;P*.j���-�|Pj"�B�{9PJa��T���Z��7Z���#��E
�R�������@	�Zw
<��Lv�l�Je���*	2�v����<��n���u�R?�������B�P��X����x��(�W����g?�.��K��z'�o��.2�X�za�������E��Y�Wo"/Q�!��KL�L�����y���+m�e@<��!/Vp@�V`�T�T��D"�
/.����E���M�����@�n��Y�:������vf����~�l��2�6I�G�B�KxsGK��?^X�"�/�'d�����'���,9je�G�Ya���X�����x��
~V��Kk�G{��@T�lEG�K�����x`��m���p�+	L�����t _���@f��
��z�TA��w>s`*��eI�iG cU�#l��� R��B���T��	�>wL*�URk\���HT7(EU��/��I?��D��rPU�To�Q=��*yY������&b�7U�T��P9��8O�(�1��%5�sL�V�������H�7����T�~���*�
�R�Z2�D�n����u���D�O�� ,/�T J���S�������������T\slk���d�qAm�-mKw�j����t�g��Z���LA��Z��H��(��uW���2@�uS�h2��Nr0�ZW��j_
�pH���L�H��!���<k�-�-�`�_���&j�����E?��)p2y�bHr0�]��WDVL�	"�������c��EG�F4%��+�]M��)(�T.��l������R?�@S��y����*Ua�����),/W���jO��jI��B-
i2��#���a�fB�MoI�X>!8}��e����#8�7S
+2+��A��+9����e�@���*��j���B�x3th?�}����}�SO]GVA�b
���f���L����z_!)R
5XV6�EsS�9��(GW����i�>��������{��f�jY�Z5t����U�WC������Bz1������vt�������]����7��$2��*-��yu_��@9L��X_����K��*�x�f��T)K��N�{����V�P#��S)�9�FJ�
8�����5Q�yVwD
�J��[B3�@R}<6ijtv %����P�� Q�Jq�aTK���fS���dG��zU�S@�\rGP��%+���9�J*��C��w�������ws���&�T�n�tm����yS���K�!�O���*A�����u��Z�w�n�m~_[n4
�by�x���T�@�O��}�*1�jX��*%q�����R�z�C�k�(	U�7�a����|@�����`P�p �c�z�IY��8	����3�y���e�(*��A?��N��-�>��+9;����k�gv���g}�WJ������;���jC?p������)�)�[����A�W��X���0S��6X���<J���"����w@��x �����������+��]
�k���������~�S��U��l�^j�fj��P�������� ������U)T�Sg�'~��<�/k��B��{{�Le��e�������ifY �>�������$�@�� ����R^0���T-�T�'_@2�E��!�d(\����_�.�9�JnJB�e6H����P%:���g���~^��_��&|����Wxz��Hn`��n��6|U|;'�Wy��hQ`\�q_�n��R-tP(��@��70mGX�Gm�[7\	�����=�f���H�mk>��u�W����P5�
"mnn�	�tN����
��1
��0���2YH����'CDv�U�_R;��8����E4��\���C.���Y�[�1EV��V����.$
d2������n�*��E�fvK2%����u�x��f�%����eh��g{$U>�[��5�)��
�E/-d"����*��Y_���Oa���g�@I/���z�T��u��Z�J�}��4+������4�
��~�R���2X��TA �	J}�TA���Z.���F���/����A�dz�!���D2��7��
��2z(����4��?)�>�U��=Y�tGI��Z��'tN���*^��2�.�
�
db�)8cZ��\�<"�Y�
�JV���p���g�����Z�>6�h�l�V��WK��^6�C�<�h�������/��B� P��S��>���=)�X�T|�CX��0���[%��z���M`+�3�`j��
lM���[��8�4=������[&��	lU�x��Z��b���#�[�:��P[��L+�����g���*��~T^����j�zON���@Vy/<lz��;�*2�m�r��N��z�@��h��l6��l����&lY`�X`�����-h1[�~R��V�7��[���U��p��d��a���Ci��b��T�l�����Q�}�Y���bT���)��<��DA[O&��:W+�V�bo����U��(^���)3[�D�0-�'�L�8e"��*�R;-��&
�=�3k��
!�1U���(��oRP����i��T�KqMX�
B3L%2� Q>��P}-6����T��f����^
S��SayKN�����jZ0U�gC�B�w���
AV
m
AV��L��e�4'�T���5<�0U	���������@=�V���Z��P���`�j�R70e��]�Oao�pg�� S$v���J���F"VyP+o~������2AZ�� Tq/�i
���\���z!IL4`����eo$/^d�x���u���V5�����Z�����^LaUqS^&�
��8�3-�
���������V�v6d+������*��`U>9����n�,��[����Q��������9yR�AZj�Jn�w����9�j����a;��PV����Z���W4a*0��~�_

Q&KW�c���`Z9��A�;�f�:��P�u�M�o��b��WEf���8��0V��������x��'U�����e���V`��P��jF�I������{����iCYb�e��P��rGY�-(����!��nB�K�e5�
a�d2^��[�K����NS�u���������� ��lV�ir�/�0
D�&{@p�'���+��a�����B<l5�UC��$�y1��[7�z3=�Uc�
���h:[���$�,������6"o��t����!r��������z�[7��0�L�Y�n��Z�,�i����2)V��8v���D�W�)�P����CG�y�:��L
H&���@�`q�[sV�����X��Ks"b[KXg~b�ZZ���������������>�}w[?U
e`�y���������t�Z�&�p������R@��~��������t�����0��������d�O�v�c���� &��q��(��:9�`������ J�����A�B���0�o�6�wD�~B����]}�Q5�R4�x�AA�
�p�������0x��;�����E*Yo��7�|���p������������&�����+>7m����y!��F��49�&���T����Q3"����,'0�d���
�*k�l��O��X����P�o����u d����$�5�Nl4j�eO��c�QQ���LW��������F���(�!e�e��65}�)��FMT�x��u�L��[ZN������}[Z���������q�i�x�/n�%<P��E<-m�T��^��lz����X�U�3$����Dz���c�"aS����+5�HOC^+%�����V�z��d#�J����M��e�Z�F����� X	|X� ��:V����-|+�`0Cn��D�6��X	;b�I`S:V&�@���O7���v�L���������FfZ*M���@�nH���8���B�g�8\J������<M��K_���������v������H�^i��!��R������$���[�Z��@��8R�(���Qw��0}�92��
-�&iw�LT!��:N�r�q$9N����a�8�hX�'�#����cX68I/��>,u�#�IP���}�'Y�/0��~�����;Bb~`d��8��z_�]����J��\ Z�0yMr��a$��6����I�����|����^/�Y����|���w2�R,-um_zJJC��j
�o � �Z���)�,��������l���6�f��
X	��5%6kiOc�I�{V����C����J�e�I[�MIci�P��XIZV�sR��J��W�V&D�X�Z����nS�v��v��'c�l4P������0�Lq6z`/.�x�����U���`�Z��t�����W���W���Gb^Z�����m�X�;�x��^\[[��e}�z�
��������D�����$R?Yq�����H����Y'���|�m�6D^����uYu
P����p���X��=m2��V{m
�q�*�2k�"�+�;�L����?���2����x�����E� ��u)��
�}�<�Ka�3?���-�i�n���D�;����	Wi94t\��7��;/J��`:���T�RQ��~�^[�Z��?6n:���6S,��uT�<L6@��*n�����QD�m��]UQ����/�U�H����;�J"6���sI_��v8h�F��tH+�/��
G4Y�S���1��VDQ��ThL����*7w�������������t��T��,m�T����YG�D�:P����������UE��X��
���>=@��r����-�k|��*�nH���K�#�W�L����C�!U�������:)h���H��v@�H�4���,���*yf���dZ�%�S=�����T�b�OOa�Ry6�t	J�G�(��'=�w�T�c��uI���J��~�������M�nh�K��'��;�����c������J����&�Pu:>�����W���0�~�v��4��k�-�����a�=�gN�������W���y�J���xl��Kk1/�����������_��u��A���d��������:��	<�!��p�[����4��AS�)����n��P���Z�P����I��"rno���AU��a��H�jn� �C���c��AI������5B�6k{�&�B�f�����5�^g�e���H�=�(�s�(�4G�I6���2Q�4��C,��iA��U��t�6`��g{���������6t���
�+tn
���
bGW�8�F����a�:S R�����u�����VpQ]v[�����X)�d��7�� T�}�����P���Zk3=�`
��Bm6�����}J2=m�90+�T��jA�b��&�&MG�$�7[F��<�����`�0V�R'�����]	R���,
�W%L��P��A:��+�3�?^'�����|*T��j���Y�n�|����L^X�@��<�U�yCK��z�fl'��*�|R��k|�^a<�U-n0_�[I��pEac?�W��\�������y%�b(_��*I��}&�W���*Y�i��<=���+e��
��W��f]@q��+���h���Z���<[��H�fu�/�W���C�[W�>�_3pU��5���6Wy�w�fg�������)����|Y05MOB2u�
@sg0e�z�q��������������+<�\�e��o
\��7��s��b��o�GK1),���
��s7/S6������/��a�*23�c��_�0�2���)��P���A���W)�X�+������UU�u�r|�<��q|��"� �_�L%��R\�4�U�4VgE����+h�X?>�'�����6+�8V	U�������"Rs�K��V�4�K�:�R�Ul�Xc�����2K�\��	�����5R�����&��>�&�c+@Yxz:\�_K�U=���.(���7=|>F3��!^�n�>Nw��>�f�W�Ro�����Ul�N������("�����J����	Hc�&�\�c�P�!z.���pLV���X}L���@?�c��Vk��X����q2
�<��{p�;�*q�=�Hc��� �j��i�9����~�Y�8�Wb� �'���/��9�O��dmh��#� ���#�| ���6dEQ���~6��^zv��R����r�&�\zGU��-�*�C�Qu^�~�P��h��&	<����U��&E�:ck�:X�b*�Vl�S�X�POk�>��PV-����#<+X�LCW�|N}���a���<pw{b0S��i0[�*I���90�p%�&k�U-���W�2�,
he��a'f���}���zV����L���ii���e[<�Uo�j.�u�
BYS��
`�9,��-�zq���<_0�_��
�*O��nU|����U-n�W���>�W�|����V|�L�"H�R{�WA��P���i��g�u6��?M�"=#=
rl]A�u����� �`��6�U�S���2X�W)�����W:�9���fk*S��"��^��R�d�
 =�El|%������Zq�U�����a��,�m^n�:�/������@X��\r�<�=�n"�j��'$!�*�i�d��8&�VoE^��c��W���t��U�M�^�:�U��z���������9\������k~�@]C���>�
Y�Q�+�V�� �#���qW)�3z�6�5i���d�2R�V�h�!i�B8���]K�.���n���@�����H��"�TA���Yk�|
�R"�dh��!�z�K��3k���*��^2U��i�B}B{Vx��b�bp�);�*y���ds�Da�*mH�W����XpT�E��`T�u����M *Yn��+<;�J��U:u���`�B?(��h�N���������LAT��:Z�/�E�P6������J���5��� ��#Tyh������v6�j�.V�v0U2�N����M�Ln�LT%p�*�fR���� �U,0�j�;-�+�[��d
Q��{��R��|#lY�����{6,��V�P�
��fn;�j��zl%n<�*����R�0�hGV��Z%���J:���xp�^��^�-�����;��as[!V��/�j��R�NJ�'��
2%���dy�����*��/ V�t����;�J�"�5Av@,e��_�M�2Y�)�r;��AE>
���ee�T�`Q����������>�`I��el����7d�����"3�H���+v`Y�zJ��!VqS�Du���+��G�PW'�\����Y/.w���H�����0�Vs�Dr�U|7a�Z�d�J�):������W����8w��S�Xw��@�Z�e����e�>/�����m�QK��/���vj��f�k�p��$J�&���������Q>,�8,�C���V���
�>sB���!�G��l}i�-e��Vrk/�T���m���~����IK��l�a���"�B��n��uxX������./d,�}��r�9�!uw��n}�"��B���s7����������n��������B�������V�Z>����^E��� }�7�0���:���
�N(y���hy��:}b
#��=;P�����3��. �r����O�p:GA����b<lf�Do[��-kI�P9�=������q����88w����v�O�� j���8P���+_����6�������F�HNk�e��(6�v7;�F��Q�n��JplR+�4���_����--q��{j-���Z����d�:���c����G��j�;p��a�a�����������P��ZKVK5��@(�X��47����g�R%��h%Q&�w�`h3Z��:2�lFk����DjG�|�9�J���bs�����JD���g}D+��T?8f|4t�OHT;E��
hE+~^�.����_!�1�&��Y	6�5;��5�$I`���$�&��
���rGJumc�����+_T7�~�+�?����tb������q�X��� Z��i~��-
�B&�~�3�5�g��7�d�Q��K ��
��R���Q���������J�,A��T����L����Kd�2%��L�p0�yu�CL���;`&oLzsk�H�&��<s~]�/�0���Th�Q�V3"�\��",������P,G�,LJ���-�E�*/-���746��u��������������Y�:vh)�zzgm���%���ChL�h)�x}(������6�d�lHI�Q���P��,����J�9V�\���>���|U��6Q�m��K:$i3|�X
�Z��@�����FM����!��dv%��w=�;��e$�4�29�B$�+A�jd���U3R�hd�W���H�����MsX+iy�{t���)/-v����nU^��q��������8=���KK�~oFT���4VO��8)��a��V%�2�+�@
�"��!��ja��`B�L2����0Z��f�2[.�,_i��Y����.�b
��D��B{�t0Iy�&k{�,�88`ja�,N<N)�����%p�U?��q��%���^uG_�K|_t(�vn8�hyeq���{�F�������J����;V��4������AyId�����v�����j<]V����:!��Wk�)�_90���BQ����"V����x�����0��5�F�$Rd���Z��d�������)��9�����D�Z`�h]o!��_���&���P sf���~���J0��T���x�����S�S����k_���]���D�1)���3(�wK+-��Z���W�mx
�N��_�����vD�gSl�=��
|/���t��S��Z;���u��la�l��0YO��l��T�M/�1 DZmL�����J"y:��!RY$���!U�du3���O���$�w/H��Auc�pH��
�Xi�*RT�B$U�O��wP����t<4P"6�2p���ZW'f�����l��PMS��:��U��,�RRI�m��Z��������g����zI�N�b���
��9��_
�P|�����~rO�Z\��j��xr5���� 9�JFj��F�@
�<l�z�J�f�[���o����@C\iR-R5�K2H�����:�4e5��z1�_��$������tH�:=N"Y�<��@*_��[������<����:�Z�����T�R"�<�i�N��U�B��SyF����0��F�u*$iS��&0�^�������� t>\������+�%�L_��E�����a�������&���)��^@�~��G(L�'�2���_��U�Lg0Z��	e��ft���'�g���jz�%�D��u=b�blI6^&Q'�5l 3C��@VA������"+�R3P��51QI �L9���Z����'��7����dE�"�N7�7d���
��1d%���>�.�]� EV�����"���qt������vx�"w���^�n�>Nn���^?/��������
d�p�J	xU��W?E�vxnfmA���WjN�"8��PV����n������pxM���4)�U�������+�������P���J��,��VP
U

H��`�Pp^����T���c�Q�=���I��Y���x��e�ec�Y(���vVH�� ��7��[16���z����;�*��_}�EX/�������v���#�I���Z���j8�+*p�������9�ja���`�7k�
SIgqoj�^�jq�E���8+qS	#\������k�a�)�������{���2���1cZ+c(+�X)go���/��YY)tb((��V�ZGY%R��j�7t�O^�9�i�E�3��v���P��
�������;����e/>�Q���@Y���y����m({q����e�R������������b����fs��L���&;�
2_����j%�Yn�PY�eQ���)Q�� �m� ,s�&�y��L���lRj"�j��Z������j��D(����� S=)�]����2�D(��&(��S��!PV�)N6o�Q����W2�R��DJ���c� ������iV���6���<0V\��]
������K�w����Dc�=�1��������]�}����S�w����)���Hf�d�4_X���E�I��E^6�3��lBf��:��(�����&�4�i���}FO�1&�l�����L�m`l�{��yn�
��Z�ds�R�1qSR�����,���	s�d�6I������eI�h��
PMv�a�u������!W���Y�L#�^[8+��X��*Em
�^c|GY��AE1��t���^Z+��!v]�O�	������r�Z��l�R�UhLu+�3�����z*;q�E�F��L��l�H��+H�����httMv�����v������a�d����8,��hT���4�L��L�YN��h����[5�1q�dTA����px*y)�NK�J������u������=��?�`�Xi��k�J�j�]H*���O�����()���6t���T��G[��[���V3�*A�"����Be"��p��a%�\�Gk���������Q���n��	�%��7 ��s�ov0�i��&SLJ�Y��J�Y�������
�d=���Nv�"��:�_�Z��J+%D�ST
���>�}��������(_5W��n�OL�e����Z�<z��=;p*6�����N��
;��6�������k��>��jX/-Ul�={��5
�C���!�m����@y�Wj���I�@�����|Yu
�r���������m�t�&LP���NKn��jwdh�h^�R����wD������
n�6�
���i��9!�R����g,��}2�$Q��`����f�fD6�u�x��<��j�Q���Mo��aV�w� 2k����"��n��iU�����;���4�;"��������	U��-������QU.�)������������2�V�� PG�~�8u�����y-�V!�\�9+�	lnVk?
�n�f{���8�7�;�����&c|�56�z������ ��a��k@R����4�#e�1���x*��J��hm�$��u�����MW��T��
������n��#��#R� ����Lf���i6�j�yp�]F`�b�K�-,���r�T��
�������k��I���B\ZHz�mG����o�Jyj��,�$��u�!8���Tl\��l@*����V:H��
H����[�T_���j���>�'�27�G]��gT�`$�Z!
����3��%Y[��Lf�q/���D��cE��@%n���L
i"��O����"S�Xw�T���D�hFk�*��xGC�D�d��*p
T%3m�zq���Z��j��g;�*%o�U��&X�On��Kl;�J��ji�n-l���~��C'�i����bq=��_�����\&��uK~������Hlu��F�a���� a}5|/���O���}��8���������
��Jl�����,X���d�����Mz��n��Q��8X�
����w�4����aL�nY�����g�
lv*+u�!���Nm !�l�M"�,�����x�B�tnjr�#��L�n��f�NI��������!X]�Ns�^)���Z�x�����`�S������G����6.�����e�Tv����uVC>BZ������u��{�~�5�s
2�;�aP�0�H�a�H��v�� �j�N�P��� IQ���<�<`P��,�`�Mc7m���w� x���VJ�K{90�����&��"A���
J�d������#uD�1�BV��*����W=|j�B�����`@����7m��k����x
 �$�������k��w���K�fH5u���1x�<�d�P�����M���bF���q�H���g�P3a����6��5�n�!���P7�e�A��&{Z��Jgn���!��6����l��h��JcY=k���V�+����$'C�^�G�Q������e��P��&�b^� ��f4�>4 ��~�S/����Kk.i�*F�������V.n�Nc'��P�y��Bt+�Mr��$<-V�[���P3%afh��d3��.u��\���m��#I��"Q�bx�"CHM��m�rt�Tb<�;�6�Z|Yk�4���%�|tt$Iz��pd����0!I����H��R���E|Q�+��|_P��<-�8�I��x*��.�����W������' ��c��3��'U�m�vem�����bm�[w�,�I������m����H�@���B�#�$�=�a��A������%���!_6�I���������q���-B���T`���jd0��%�4��� :��f�H�4�^� 2pDa�-�5���n8��_���Z��%;K`q��_��1yajS��p�������FEm7����j�j���R@���i��-�VzzC���=w?�E�+�lz�������������XY�?����!�����#��z�QY�L]��E����
��Df/��]�R���vp�$���C��1����dcN���4�u����}��D����;NJaz�{�P�Vd"z9v��Zf���o %�04%-I�^��t�y�I~a�w�������(	J�%���Mq1c��6�����K����N����F�^��G$����B�����E��P�N���Eg��� cc�����7���|��Q�'(R���<�����A^�a�D��W����x��
���J��y���u' �u~����|H+�8��"2��3H�#*>�����:�@��ZsBy��.���N��.��-�K��)��d�d�a� ���t�L|�����X�������X�c^Z����D.n�8���1������;0u���#H��$0U,~��J��S��
dz�:����L�5
��QQ 7z�V�zS'��O�QA�G2��3aI"�ge`
����{�9�����
/�Di�@'��p��D���
8�"=��=x_N���fg���@$f:��Q�S)P�C���)�j}z��N%�f��H#����NhL>lL�V0����by[�^�����h�W�^YP*EnH��8�t���S�!����Wwa|��R�C����Y�Y��S����w���%�F���)�Z" e9�J^j�UV�i*y�l�x�i�IT�es4������@S}D�Me���h
"M�Wa��>$�����-��D���^"3Z�����h���v3N<s4��<��uji�@d�cEe�x
"U���[�
�x��7�����}\k�Z,�DU��[�*�np�j��������_��.kg�Igj�c��S!�a�"S���61!�#�c���S��**chZq�*	��V8�2/��PS�����9��L��]mh#��:���Y,��[A��� H\ul��Z-`�;�
2{Kx(`l��L�%��`�R�S�q�����*2P�$�H8"�&/.���Oh��{��|	��8=�r8�����������op���h����-_�u�^��1�����e�����-�Z���wL�_�U#�=�2��#A���_A���T%I�0�m�{|A�������j��[���L������B�D�5���P���e���������M����)����Xp�Z�>�K-q�-(�s&E�y�K}#$�Zq	U;�i����%�j���c�������!��������x��/x�V�������6���`li�+�'L���k���*o�����b����w@��;�:�o��|�'L]NZ���i�j�*�(I�v5A�Vs�0c������$R<Zc�	�6��l��E��W�K�o
[�s������d�\�!�a+�d�Y��n�*�d]���*���e��{]%7�v�&��M$7�>�H)�*��f�N
wt��[�,��n�V+��o��+��%����KBY��r_�+"��Dq3|�[��I+��~e�zQn�W����:�^b���*����w`��s7|����{;+-U���l��RtUD���6���LI�k�@}m��J"Y�:�x��PC����Z(����Y���������i3`�O��A�j;�:���hJ��h���
�{k�8(��1U��SA��*���3Q,z�
q���,#�vS�@�������TT���Y���� ����L�:�����������q�`�%�wL��H�
���7�0�����vL��������*zlqX���X����,��>��\��C�� �z��t����UEf�,%��{7��P}q�����U���(�[���
�p���U�@� +�T��(����dA~�#��5
Z�*q��g�^�����%��x��EFRY�Z�R�U�yV�^%i�9���~�wXO�M�Wj�-����_�PO���f����u9�^\����5�ZA�r��E�_��GC�Qm��<�W�v�.���V�6%M�\��*��jz��/�N����3��<�vD�~+�c���X�8���r��Y�T/�s��V7�3`�#zX�8��� �j����w`E�jjd�Z��T�/���*Dz��{O�`W��Wq|��(�W�����j�\�gq�X�sn�;SR�}�M�BU~�Z��/�gI��\�$�)��\�-pUJBc^\A��<&y�-yL3-�*�(�
�l��Y/���B���3d5w� `�b���lUD*����l��f�<��vtE�|���@W��J���JB"#��	tE��-G]�
]Y�D���e-��+���O�"ne�f�����Pc	�=��?;�����]_S�U�T^����� S������
|U�L��V���W)�3����W)�#&j'C�+�^�������_-�a��_��6|\��+(Q���m�_;�J��d�m������V�U��Wo�s�|oCXI��q>:)CX-��B�T�5�$T���Y;��H�&0��H^P=y_���������LN�|�c���y:��e�hi1:��P����U	U�ml�6T�z�U���p.�4t�S�E����"I�%t���h��GV�*gt;�j��%���]�
]A�(b�	y��|A��zq���Z����_)���M���&�
t�J���AdG�+l�N]?���&�U0t}T�c���H����Z��B���c���^I$kG@�?]A�-R:R���Z�7��Bvt�s�Hgf�f2��u�J�������+Tm�A�]Q�G������|��!�L�zUd�f���Y�0�P��6e�8�LQ��1F~_�����
b��[I����������W������5������rG[�U�}����
/��Up���Rd�v|�l������s�������
h�[�WI��5YM\^��9yX9U�D9� ���l��[�$��ryR
��O4/�� �}�OD��O��}�-m��2��&�W:$���������i�x�����,u ��*�F���	��wX�Y��T;b���$�h�4�h�zGH2�}x�6;]�a����D{���'q��
"Y��
�t��xA��
�[�U-oBW���#�/2��7�����&��	`5��������[������mE_?/<T��2��/(�:�:5G���|����H�dMh�hCs`��N����Bb�V���s�����B�k���U��6&�]�C_%l/�T^z$��&L���w����^��M���+�m�������b�NF�����xOr�l�\�M=U�Z
 �&�����-sr��?�[��p#��8�xb��m�K�
T��ZG��%L;���|%i�������[#�����$��`�^Zk���o
�N���[Sf��Z
&r��\?: ���O��!��eu	vV�H!���N;�}�a���:��Gl4h&�OQ��*�=5�dX�
j��@e+;���������;B�C�KH[,�dh��4o��7�3�%~�	���b��|��+����O��$�����cxPO�q��1�`���0h)@�3��X���������[�N�d��9�����S�=�������������Z�#�w��
���Y�T,z��=�|�Zj�[Y'dH��j��:�S�T2.��<BHv�K����:*5G�z��L��f��Td��0��<�,+�7�9!���9F�L*��Jm��lTjv0M�RS[�:�Q��IE6��6�0���I4���O-=R����������J��%��kN�*?&�0�Q�W�;T��\q\N�h.�m���E�0���9t��sw�3����1K��
�c�#u�LE$&���"�L�c�]���G"�
��QOGM)����Vg��$�[�S��r"V�������H4A+-u��efQ2�T6jD�Vd&
p�����`�(0����������`ux���{����������cof &,of����(���������K�G��i�"v@��G�'U?:7-������2P��%�������%����q)��3
H
(I���/�R����N���Z�>��>j���3�2=\�Fq���)�
Y������^��$-�m��tdX���|@���K:K��2QCK��-
nGK#�����u�-��u����'4�2��l�"�Ku,������	�[�)�qJ��������S�{�/i����E�4��[���-��j�4?/-�/6�+MIc�)]0F����H-~��n��@����\;d�(�9�R�R���l�2��X�<��u��vd,!����������%��Z���f�x)wc��� �c�K>jfx	|�5�������u����;^����(i�^���\"�m������/�\fx)���dYX������\%>�if_��
�(z1d��uy���+{�����v����+K�c	t�B��eGU�
\~Q�Bdj��/J��B-�WT~�m���{��}�Y�g�3���(������V��"����SQ�J����
O�|�Q�Bm��=��E�a.�"cL�C�;�P����b#����X���z
d-zJ<I�>���E(H&��yk(R�@����^��Z�&P���AU�����T�b�EU��a���'��yE�������Sw���b�#� {0�vHUd�P�8����C���i�#x]R�HV����r�T-�Mg�j�RA��"�9��)Y�+%�:��Du��H��<l*����D��:�������9�j����A���p��+}%�j"�A�" ;���T
!u��!xc��4RQ$OM�aRA�������F��
��0���S?//{�b�ZK��^�kb��*�
�U�0�*wL������m���;�~^\��=�*�m.wT�<|���H�������i�J�*���7-�DU�H%�j��qT���vaC�O��"����'�����;��
�d�y�8$�#��d�*�d}&�{C�*�4��via��W�!��0L�yI�/R`����5t���<c���p��H��|vD�Y�8�h�"*,oH����@T��kC��Z��h�J����^������|2%����y�q�V�Ng������W��
f��
*�zY�k��$�
Wk�� �f���t8���k%'�w �E�\HTr8�����a� ��z�������"�2�M�G���F��D�����K?S)�S[B�R%�����������
o�J�:����05-�}���t����Kzbc�h"�F�n0
o ���}
0���s5�9~��B�g]�8T�
���=�������y�P�R�G���X^�VO�������;�(='T	SGan�Y��FR����6k���P�"(��"Y��'Nx��#)Z*��#CP-QM�(����<�O��-R�<k�:A��DI(�X�0�T	U��������KB�V�k�KA�������SAf���D`w4���3a�)��Cb�]j������hpwH%*�eJ��P�B�SZ�B�7'��������^zv��{����;��n�?�-�.~��by��{���I/����j�N�f�AGGX-���|@Zq���P#�t��,T�X�]�cY(kB��(����\���$��?�����R��fb���h��������QCGY�+�V�%CY�M���T�:��P�"�����|N�qJ"�����FV�Zs��^'��nHQ�l�)p�,�4�`��I���J[�������Jh(-��lG�k�e�2`���,<���n@Y�yU�����]���byid�������� S}GS
~@��� �e������XGY��1k2��$T�����Y��<��,5�i}����������a��@Y���Rg#GY<(o����P_u�&������C��w���l�=��V�P(=�3&�H������c�8Q�s�v�Eqf��M1V�
:��J`�����zyK�ueo��1���cayCk@��P7z��K���{�s����m����R[����@)!�J}B�Z���x�on�+��;�R����!VJT�+�H��$�h����$���>h]���d�T�Z!d�eP57�X��pz�I-�,�j���b�P�j4�\6�X%T����8��w��jit���!"��<��aV��WX+��l��0K����Bh��0K/�d��
0��y�C�����Kf�`��C<�aV-����Yw����l0��?0k0K��a�V7����������YrMc��g�(�S����"S3��$pG��d��4Z���zV)T�����4�	��j*E
�����*M�@Z-Tt������Mx_�`�Z�0�c�gP�K'd�S
v���<j�3��;�
��B}�i�C,�yc�x�B,��4�P��R����/K0?-hE��ui@,�I�UR7LU�jAI�,Y�6b�r*�
���0��!�������J�lZ v�bA���.W8��i�P��5C�go&�f�%+�TK��ZLC�J�����?-n�|�"����H�uLC�$�j��P��
���$!(�uKV�TR�z���l&~3�0K2�}f�P5
��Y�0+�k�jC��,�W�j�"�@�-v���<+��9���8�����8t�����F';��8_����c%mIO��"��by���[$o�a��6���z����87���[7�b�j�*o7���e���dj���,�, �<���y
cI(K�����(��~Y@��R<���0�O���t����(��m��b���k
�B
^��F�������y�f�ET�R��|��Y����P[1��im�
I�Z%�"��+p��Lj�����R�;�9�n���Bk-�M ��Q�Zw�Lh��4��i9&�+��L�j���;�V.g��%;�7x�
���N#��������x����@E����� ���T�SRx����K�g^�P%�����.bjzB��
B�Q����tRo����b��L�*�YGl��U�+p���A�������<��f�@X!�~��IT6���t�9���Z�R���P�c%/�:=a{}�[rG�O��xEq����� ��u���Q����Fd���wX.o1^���z��[���<�����j��	t�����������������0��g�����������u�F�����$��~����
�6!p����D=��T�4�'���[��yZ�u�k;�ja���x��pA�
V)�����U�u�P���P{+�0�C)��d�4U*�`��|l<#��Tr���n�<���>��g4�O/o�D=-3*��yb&8�
L#M�VZ�`���MH
OnR�	
59ju�j�P�;�J�����p$I�
endstream
endobj

15 0 obj
29587
endobj

17 0 obj
<</Length 18 0 R/Filter/FlateDecode/Length1 16372>>
stream
x��{{|SU��Z���y�y����i�#}��H"�
!P

Xhh�6R��@t��R("8"�@G���B�q���cgD��p�������8#4�~g'--�s������N�^k���^{����'�ZW�@m@��nY0���|
'�P�2��f`/��!����c�^`�d]���������?k
�������qMM���u2��s���,v�1��'
tp�9R,:~���_@�������2
��|KpY�Qwg@a1�ra4"�vBw?���=���7��q��"=�G����h��drE�R��huzC��d�XG���Gf�yG�3��=j��������`O�]�Z0�j��0���������k�<��^�C�1��	��ba�x�!�n��#b_�Ih��{��6X[at
���m�~�8<�����ai�z���(�������~
�`)�������Rs���=���f����mX�p!,�uI� �����vx���+(vm��A}�����
vB��'@{9��k(f���)x���S�<O���+�F�F����h� ����7��7��n-�F�=)��?����p�����nZ� P]5�r�l�������y������N�|��;����O(�n������������]Y�L��j����2E!�q,CS9���e"����Ag�38-7�/�6M��)s���|��kE&�9mA9�"_���A�A��� /6\��Kp�9Q�O���
'/���������N^�:����|��l�POu���X%Y����+���j���`�2e�sJ(%7:S�S�S��9 �vF;q�$$5�lB'r��V�]e�z�?��l�����L5���S�H��"��H>,�[��������`I�[U���Z-��@nN;]��~��w�c�S�1w���������2�-I��3����JY����"�:�:7Lb8���@��"��j����������N����=x��m���9�;U��hY-/��Z������������	'�C/�S!��^X-R�r�)(�.�vy���l� ���� �����a�Cr���>X����fW'�<,�_�; R��{�b��(m����NGnNEeu�����;���oKPl["�����q�D�?lg�A���//����a^d�EN�5���dK]�u���G��W�v����R'_�/�)s��&�_�d����9�4w"�V���|��&g��� ��Y��6<�L�����F������*WV�.�n�q��u�^b~�+���vj�I�sv�����,�mG<P���yJ�Hg��W�7��Z[���6��6���8�C)��:qL��G������Jg����%
I$q���*1�j[B���D�K�WS6: 2.����r�q9'O�(s�E�K'r	���'��h�nqL�8�/MM�I�aBY)��L��IMk�L�9����C���O*Y�\r����E�%)��i%��*=_�9�&^�����I�!^N:��<9Ws���8+7GG�����L��m�\�&�lN��<}��������pgR ��k�R�����Z %��<��u|y"��;}>)��&HB�������	w����lwH�P�s'��tR0����fw�pS���t�����)���Ntf����/�>��$������$��>L�	��@�2A�u�N>�C�;N%p���l���g�7u��	\���$��RX�����(5e�D	u���_D�����FM�C����S��%8�@���������ZP}Dj��w �,=�9e�&g������R��$��^��
�"�)���"�����S�����9Y�{%�7��$��9YD3���m"5�/��N����ck�}%�T������<(8	��k��}j�ci�V�Y��'�O�
XZ���=���#U���dB�v��O�k�[��\�0��
�`�`�B
�a����,��Zfq@�ee2����f
|*��X��^����|��I�C��;��n�<�E�Ro|�+�������o������������?�@}�)b�f��=A����F�d�0r�eL��~�*���(*p��U�]���CH
���Y�T�<��>�u������{�)��h�G����������p�-@���b&@
���'�H�)�K��*����[�TX���*��B^�F2*�U�)������`hL����������m��[����*Z��
'x�g��|����0_�:�
e�jjjj��g����G��'�0�^���7�%4���=�f�S=T��������s���+��>��7W��^
���cF23!�0���'j��5��\G���a��Vl�b���V�[���g��1��y���@����:G��.�vfr&��S4������?��/o����[zl�?���
��������~��r�{�j,�F(�e��F�V�`�I��Y@�U��V��Z��P�63�$LI;�xQ����`4If�8gf��Y��1yLN�d�xjl��?��Pr��o{�YS��o�������}U3���yL�dX��R%�r`Xfq���p�+x��xI��)�%�V��Q ���L��
l<���I2mS`��H��x��_��|$���^F�;����+���c���O=D�v�:��)�W�N��Le �k	�K�ZE2 �����C	C���`0��(�Z%���x:s��%����&�������	N(��}��1cd2�F�G�ZSST8�:;0���^6fv@&��W�ZMDC)i�F�W�zd�`�.��"�^�mE-��"�aA��D�����xQ�r��4?����H�D���%���XB�W6��(2�c������U4	o@��2����}�����W�(��N�f��i��7�/���c�	��f}�b���Owq��Z�,�c�K��<�lYT�����?�0TA�����6H���8��7>��h�VPC���S&��0���b�R��.��p��.������.�vabf��S:d!	���d�d�q%z��(�LB���o��q%�������;N������l��]�VS�}���kR��g��n�nZ?���7z>���w�'�}h�o6
�2`��b/�gX�fQdq/�m,FY���e��R��Y��b?��C�����s�����
���w�'�+�=+30V��S��l�J%���4�z��hdF�Ph�f@�S�����c�nv�p�
�l�a�
�6,����c�����$�aa&m��_�[(��X<��4*�xC�#;Vl�'���K��_�n�w�.�}��E�r�30
U���������%�S����L{�K���SP,0/��z$����������#��&����	������T����Rt�L��z=�!��G_<�c6����H\����w�!��51�����~���!���W��N�����L��z�D�iJ��l&�q��3i����[ut�? ��������9����9������$����Gr�g0����d����+)���<��x���l����h��������i�^����k��������=�A�c��-w�
=����������[��g�����e�����c��[��n��"o�XW�
7�1n�?G�L�4X��� �+q�rD����Y�lV���I��t��y��co:";�1�~%�I�
.�C
A�112)G-�<JZ����%z�0�����]��h������O0��,]Y|x%\~���lN��hM�	����(�%���gd��T�Cs�c�Bb��z<��ha����gK\���(6�_�[����������u��W�����L��{}��Bag��z=m����������:����A���T2`� _���X��	�?S��8�;
���P[�
���E�������+ZTSCrp K��a�"y3)�����$a���)7����:�83fO�$��:�����zTS���~��;'��y��y�;2m}e��+�Um����-�b6^�\S�hC;�����q.���~k�+��{��Z�K$?��(v-���y+����4M��N��hi�i�a{:n �Q��S��8�t4��E@o��>�K��t�Kt���c�YB�J���'���b:�"�
C�&�&$n!]��t6�"+!H9 ��A�.���Ym�HE�~_:z���>Xq,��"�{����_�GZ��%Y���s2tb�4N�3�2	��G��S����'��:�����.N�Q`�������.���-��/�e�^����������~�&Q3���`�L��+	���i�,���P�r9O��4�|����,�ga�fawVr)�a���!������qT2��$�c$���l�x����(��;H���x����������hD+5n���������t�����Sg~��;����3� ��hP(R -%��n0Y�tjm
�����J��Z}2��Ni��,d1��t��W-�9�f�m�+��Y}���{�YTh���@3,�K���>R���5�����0-������+�df����o�P8x�\�+�c�]�@�������)���S�+��u���v7j������%7>��-n���7^O�J7����#�C�����8��67^r�y�y�a�
���q�E7����K�XLHZ7�^"����Az������DAB�>bW�j#B{�Hu����X+Y�Sb������9���?I�kP�w`o����^9��,���k��`88�4��
�I�����wnK����|�C��EW������b��,Y����{}���/����u~�9�]f&��_����L����l:�?`7�1n3�12F�N�sQ����z98WK��\'S���B�)f��0^O~������n�f�(;0u�����������������4��mmT��45�}���z�|X���_%���|f$sX K���`���
Pd����J��*��Fe��?���=��h���l�����W�'���QN��������R�7�e����a��=k�~��;6.]�����;��/���,��8��!��&~1����-xe����I��~i�aO�j}���z�\f��HK�
2��h]Ov������?
{�p�������RJ���+5��x�FN�7Lx�.�����V����%Cz�mu�~#ENk�X|�o{"~�
�R���f&Y�������z�HZGg9u6�N�����:��3�/�,|?�,�N`�B�������,l���,�f��,�!��k����M!Y�8���LrN��������G��ge]5n����|��{v���fj��P�����.��c��.�&}p�������sM����N2f��=R���%G;��i����V(4B@����RX�BF�B����+��!�1q/>U�-�d�dCO�#���o�����K�<��������v�s��_��n�<����-�)���`������/~����>�s�����FC��T���M�*�L�.����u�uz],�����EoM�[�z��z=m���B�.�B@&��3pa`H���{���f���X2�E�F%����L�����?������M�;�jX�����W=�z���k��|x�7����/���g����������<������3�a2�FF�������A���F����yy��`P
�!�j���4�ak��d{���iP�05z|lo��M�����������;~+l����Yq����d��X�]����~��9�=v`�����g�������A/�TZ
��P�z�(��h��Q)7��TZ�E����V����s�Xn�qf�2����/���f|�������;�x��T�i4#g��?���O��-3%|�#�C%r�q;����
���x���G���7����XKtf���HT�Ad�=f, d�/R�$�W�w���H/6��������E�o T�)��L���?x7����Z���j���c�G��E5zO��`)�nD=�u���A:q_<>��*����}9K��BO����������r���H�����W�L�sX���^�7�W[�4����%l�5���Ha@����V��^5%�����V����R��r��Zu��C���Q�g��D��N]��%���j��BY
#�����^K).��������b�H�1�\8PF��(�.��tCW�� >�[_�����������9���%X`��h�T��u�B+2�te���}�A���=E�������W�������|����;�W�{��a+��R�-���.,DC���{�S�/0��|�23�x���*��
)
�50V�<U�j�+���`���Y1f�z+���d+[1��+RV�h��V��_�b��Yq(��!�f�������;��P~��a�V�0��`���o��Vd�x���V<e�7��#���V��$� � � ����<�@X�{�����V������"���N����2x����G{$��d=<tWL�Ub�y=���z��^��(;��%�xe�YV3�.��W��)�����{�o�LI���?���:/����JR/�0�������������b�=#�z=*9���*�|�����&��^�.4�e�E��@_�������bu��q:���W�{}�����U����s7�
�������s}ygUp���rhB@��k)
���&�M��~k�ab�����t���P���SdH%�6��3)"&!c����vw|�f�k�_����_~��������6��[��������&"�������}�}�����#GnJ����^��0�g�3,
���HQ�)c��Wt��STX�)���3�������p�����OI?������w���
7����n8
4X|)4��^������=��^?}Z:��?���;adA>T����]���H5+�WPhVd���"���T.3����Wt2:w��uk��������q�K�0qs�,_�b�@��,7u��qL�?��i��;����^���w���������5��n���yp;n~�����K#c�Z����xju��1�@����j��}��o�vW�������ok!�J�V���2���0�r���4�HK��FK,`���i��Y��l��JQ��0�uG�%��T�`
Tk�T��AKCfF�������������}�������o�m�s=��{g��������q_�x���7.�,L����b���`�Q�����t��4Z�ztj���j-\I���h@g>�P�>�1ZmP��h�����h�N���<����85l�<Eft��Ef)���g�!0w��=�������]�~7���/�����={�>����p��Y��\�0c�"����������������/��U���_����3�]G~���3O<E�%>����O<M�d$5�}L����NE)����9E�����rZ4�-��Y���5�m����������b9c9o�]�����J�h�%�r��Y�o^�4�oT�4�R`���>�,w�k��."���$��I�%
�D2����^���7���1a��g?[wOEq��l������c����N�Y^~kp=S%�3��w��d�4'g�)����E�ts
�SJ|C�]J���J������8W�>%+�W�Q����J�U�)%v��T���DF�g�v��k�	����;a�>"��01D� i��CBS��b�H�mWbT�~b8(�~^�o����#��C|Tv4��9i�4��TI���I�����t������%�
����������{���o�����oq�?���N�'����$d��3a��Ov�����9���<x
�#�<��T)��1�g�������	u61����p�i�/#�&�,�<�/#��IZ#�LF�F���}�~F�*@>#@-#@�*���sd#a:U
#�b��	����B�PG�r� }�Y��d�f����]'3�b������YQ�x.�KiK�T�W�Q�Q�z�f��C�i�igj�u�G�������������Vj�C��2����~D���$L��0
i�,	3��{�0j���9���IXw@g���IX�&��-IX	������G�.	����Mit	�����g%a��/	S�alI��bfLf ��I�,�1w&a�����.2�IX��'�����I8����$����/%a�*�{V�m��4P�xaj�1������ _��n
76���uc������H��9�O��F#��X8����L��������c9������%�3_l��W4[o�B-��V>�������P� �Ey�y%WhWq�>��Z���e���|�a�
|k�1,�B��z>��W�U���`,���-�������u!������>k
����h
��:I��7h�WT�B+C�-�X,$DZ&�P=i�ol
/������uM�������pcK��_����
|����DVc����5����-��lx!�nH��cM��4�e�Xk�.������,�c�%�!~U8�$i6�KX�GB�^m��$��
u��P�
�������|]S�5X���X�N ��5��h�%�lEk$
���o�q��B	G
���!�p��B��4�����HTR��,���i�W��cM�C�m���>�����!A��#u+�IS������F��6c
��eB^S,����j���`rV�"���������VGC��h��,k���H���L�4���3�Y�P_i��I�~ &�
�*���p4&�	���Hkc���0��a�A�������:�@VC+�j����!���
�x�	"�Fh��0"�
Q��h�<�!��~\^�0'i�4�?x�-Py0��B�$�P	Ah��k��Ah�A�:A��<��o$�8u���"��B���k��q�a�'>��d�2b�R�!
?�Z�X%)1";�&�� *	����|#�Z��kh�
�a��+�uD�	��AS����
2���~c ���vTT�V����m2AH�+����e!�XMDo�������[-��K`5����'����-��I+�>9I7��@��@#� $��'�J�5\eO<$�O��2�9�lB34�L[���%�\ZE2�ip�Ahvd�����D�4$c�'�(��1\�^.����J��$��@����M$&�dFC��k�!����X,I/#� ew(���p�������F�4��^a��bm=�E=+q5'5%F�L������@�,��z"-���@|Kj����>9����@� ����D���� �o$�/JV�X��e$+�H�Ea�C>�"�����+u�L�K�����'�%����,�f�:%����!Y;0�0���,"O�������$H�r�:YH����HDc���y����!fA9��j����e�y�cx�R
��P���'��`��v�����	P���G��e����{/2�������0e�%�/�7�����G���|��B��������������o;�<���l���O���O��i���Io����3��{i_�g\yo�������_�_��M����"���_�R�_�����o���3Ug����
t���v���)���k������=���?���_���������m����������r�1��Y�"���{��1��(Fw�����y�G��(��9�n���(v�="��{��xV|��~��Y*��� ���>�s����~*d�+���3�����wcd'��w���?��b����X�c���l����0��m�}vo��F��o�}���{���{7���������l{�e���������k��CWqt����m_����Z^h_�`�}Ay�=��P�"]��U�4�������	�������M�f�\W���]������i�%���K����L��r���E�*=j�tE�*
�
�v�W�X�F�h���Y��v����_+�j�h�k��,�>]�x�w��t�+����T�2�B7��J����@�6�P�`au'����[����bQe�X;2P!�WV�>	h��u#;�09 ���
��`���-�R�����$~!&��[�[�� �@������!& nA@7��
�;)PR��^$���H�%T�"AP��:�"�?��J
endstream
endobj

18 0 obj
10234
endobj

19 0 obj
<</Type/FontDescriptor/FontName/BAAAAA+LiberationSans
/Flags 4
/FontBBox[-543 -303 1301 980]/ItalicAngle 0
/Ascent 905
/Descent -211
/CapHeight 979
/StemV 80
/FontFile2 17 0 R
>>
endobj

20 0 obj
<</Length 412/Filter/FlateDecode>>
stream
x�]��n�0��y��CE���J����a?�Pp;�5�4=��'��&��bl�Kd���5~��k���>�~x���G}����=�}L+~��nVY����%�����,U�����M�m����*{	�����G���������GmTU��*�����;c�U�f@�x[|��_��mF
����O^��������J��}����-AJ����4���1+S��s�&v�EN����x%�%q�\[H�?H�%^�F�&�
��k���;������x/L��0;�o�?/���#��|l�$�����?����t.������}����X�w\+���m�g7����*!�S������3�����;�������
������s�'OH��44"4�?���k�#:�M����_������F�`
endstream
endobj

21 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/BAAAAA+LiberationSans
/FirstChar 0
/LastChar 42
/Widths[0 666 222 500 556 277 277 610 556 556 222 556 556 333 500 556
556 556 833 556 556 333 833 500 556 556 556 556 556 556 722 500
556 500 556 556 556 277 556 556 889 277 500 ]
/FontDescriptor 19 0 R
/ToUnicode 20 0 R
>>
endobj

22 0 obj
<</F1 21 0 R
>>
endobj

23 0 obj
<<
/Font 22 0 R
/ProcSet[/PDF/Text]
>>
endobj

1 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 2 0 R>>
endobj

4 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 5 0 R>>
endobj

7 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 8 0 R>>
endobj

10 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 11 0 R>>
endobj

13 0 obj
<</Type/Page/Parent 16 0 R/Resources 23 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 14 0 R>>
endobj

16 0 obj
<</Type/Pages
/Resources 23 0 R
/Kids[ 1 0 R 4 0 R 7 0 R 10 0 R 13 0 R ]
/Count 5>>
endobj

24 0 obj
<</Type/Catalog/Pages 16 0 R
/OpenAction[4 0 R /XYZ null null 0]
/ViewerPreferences<</DisplayDocTitle true
>>
/Lang(en-US)
>>
endobj

25 0 obj
<</Title<FEFF0072006500730075006C00740073002E006F00640073>
/Creator<FEFF004C0069006200720065004F00660066006900630065002000320034002E0038002E0034002E0032>
/Producer<FEFF004C0069006200720065004F00660066006900630065002000320034002E0038002E0034002E0032>
/CreationDate(D:20250216013112+01'00')>>
endobj

xref
0 26
0000000000 65535 f 
0000253154 00000 n 
0000000019 00000 n 
0000052099 00000 n 
0000253263 00000 n 
0000052121 00000 n 
0000104566 00000 n 
0000253372 00000 n 
0000104588 00000 n 
0000158629 00000 n 
0000253481 00000 n 
0000158651 00000 n 
0000212009 00000 n 
0000253592 00000 n 
0000212032 00000 n 
0000241692 00000 n 
0000253703 00000 n 
0000241715 00000 n 
0000252036 00000 n 
0000252059 00000 n 
0000252255 00000 n 
0000252737 00000 n 
0000253065 00000 n 
0000253098 00000 n 
0000253804 00000 n 
0000253947 00000 n 
trailer
<</Size 26/Root 24 0 R
/Info 25 0 R
/ID [ <E71AE2A2FBCA1E404CC14C8B73990B48>
<E71AE2A2FBCA1E404CC14C8B73990B48> ]
/DocChecksum /07996D085EA5FE1D230346314BC7AFF6
>>
startxref
254255
%%EOF
#204Tomas Vondra
tomas@vondra.me
In reply to: Tomas Vondra (#203)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On 2/16/25 02:15, Tomas Vondra wrote:

...

OK, I've uploaded the results to the github repository as usual

https://github.com/tvondra/bitmapscan-tests/tree/main/20250214-184807

and I've generated the same PDF reports, with the colored comparison.

If you compare the pivot tables (I opened the "same" PDF from the two
runs and flip between them using alt-tab, which makes the interesting
regions easy to spot), the change is very clear.

Disabling the sequential detection greatly reduces the scope of
regressions. That looks pretty great, IMO.

It also seems to lose some speedups, especially with io_combine_limit=1
and eic=1. I'm not sure why, if that's expected, etc.

There still remain areas of regression, but most of them are for cases
that'd use index scan (tiny fraction of rows scanned), or with
read-ahead=4096 (and not for the lower settings).

The read-ahead dependence is actually somewhat interesting, because I
realized the RAID array has this set to 8192 by default, i.e. even
higher than 4096 where it regresses. I suppose mdadm does that, or
something, I don't know how the default is calculated. But I assume it
depends on the number of devices, so larger arrays might have even
higher read-ahead values.

I'm running the benchmarks with ra=8192, shouldn't take more than a
couple hours.

And done, uploaded to

https://github.com/tvondra/bitmapscan-tests/tree/main/20250216-014254

The PDFs combine the results with the previous run for other read-ahead
values.

Overall, it seems about the same as for read-ahead 4096. The regressions
are a bit stronger, but nothing surprising.

regards

--
Tomas Vondra

Attachments:

results.pdfapplication/pdf; name=results.pdfDownload
%PDF-1.4
%��������
2 0 obj
<</Length 3 0 R/Filter/FlateDecode>>
stream
x���M�$=����_�������H$P�=k���L���?���]����H����C�����72D'%��D���e^�����_�~��������m�.���k������/����_��_���������/_�������������|��_��r�.����_�������u������u���_���N������i���\��Nk�����e�����_������y����2��������o�r���^�����/E�#��:�:�������_��?���������x2�e��_����'@L������kU�L����t�,���6��,�.���<��m������m����.�e�o�{��,��������z��^���z���������oy��������-j�]��]����������t;��{�m����TYo��k�����-����E������D�xL���k�������������Q��e]p�vScz�m��^�*�E=��z}���6�2�f���������n���N8W����e��\�o)e~�Z��o�?��6?.�����9����<��W>����kb����b2n'E����vt6)�,b���������V�>�M��>G�?�n�9}MJZ>?���_n�w���iQ�}M�����{M����8������+��zY���L6E�)�R��}�Q�pF���s��[���W
I���Om���{�����kR�Z���T� ����r;`@�5-���[�q3
_��h>�L{�aW9�j�/�������S@V��������N��.5e�lJ��V����iQ������p[l��}O���a����}�s���N���v��\����H�	>}�'���'���=��|��[���7�K�-�x�
_��Ge��(�O��sN�7���]PJ���~lh�M����R���u�NA��G����I�?��vu,=����p��3������<P�w�5>>��'�4������m������>���)����'���O�Z>��<Q�V�Q�=��#jI����#{�5���|���E�!9����R�]�b�>=<`����^��O9�)Q���UY�����l����~Z�v��6����Q��t������jI�=v��������������G�������WJQt�����+���z����_������J)j�����c�z�pJ)i;\>w����)���N)%��_��y�Z���R��}���(�����R�7�_����Q��J�
go����oW���.~t%�J=��C�t�o�w:�4���tZ���}�{��
�hI��Y����!^N��;��|p�}:��?�~����6_6C�'�p�����������|���}Fk�(�Jhn�-�Z/GI��R��0����{������q��p��J�>7�o����6\P�t��R��ex yP������N;\L����8,��c���D���S����L�Z?��o�����L��>Co�����g�;�u����gLek��OO�����9�ho�3D��u��G"����C����p���`dx���'�=<P�(7���*�����,����IQ�!����a~>/�;����:)j�4	B���h�g��/W��UW{��z��a�/��A���� *�M����!���M��>���y�<��6g�~���a�l&5�H����y��i�q[;����Q�s���L�C�������F�@�������[����t�t�#�5d��9-����yc���>-i�<5��?7�p>-����h���S����y��u��p����#�>
�O��?�ZuH�9��a��)��rn�X��p�k��|�-<�C�r.s���1��(E�}���v��2�kv����:w�>������>����$>�Em����K�,��C���&{8�jQ���:uo��O��n��������9�{�����>R���i���W��P-���Dn�GQ����}����{�ED������C�|l*%
�5��S.���;��p}\�����?���:�[�'�p:%��= |�{��d�����C�+<
D
:m�Y�h�~��O�'���U�~��.�[7�
{e?��D]�~�X�r����+e�/)�t6���>c$O�W��
�5W��!kI���|�9�5����<7~;,�+^�����L����au�"��D�p@i���>Iu�����Z����$�������	�Z�������f��
J���]=���#��	I�i~4�p�;>���I;n���:7G��=)�4��I����
���|��>����o����<d
��i9{r���#�hv���/�:�\�������%�[��w���N/M�a�Q��z=m���-4W\5��/n����p+��x�0_������n�����C��yH���^d��3�_��z���2�:�Y���As��iX��M��lu0�["��)�K�?
Q�U����*(�	�����7�c��*�i�������,L�:������v0��"��'�[��(��9�����C��x��E�y�>���ax�T�d�$}&B��^��m��2�����R��3���V���*co_$|�P�����C��*1w+-�dp$}+"9dn&�W�Va�l���E�^�(������JQ�a��%��$��:<d�/j�=���0�W��}��BR0j�H�5�4�K��=��H]����?~[r�S����=�c���N�2�
�����=f}��uZ��k)�w��������O��������w������I����z����"�pE��pP-|Q�-�n����|1�z��E)i������npD-����M����a^���b�'�L6z�W��F/���B��{��~@���R���fv������R��Dd)�9���QF��a0��n��T0zj�w��5�e�_�������C�z��<�(�"��A$s�������#�8&o�Z�p��;��7�h�l�|JH�_���H�
<�4o����HQ'��hS���{��=�_R�1%�pX��d�
�5�����������
w;%*�d�5Re0��n�E
�G����^��O�����"g�L��W8$d�����'8M������*c������9-������oe��:�^�?���iN	�>�R�<T�MC	��~(X�P!j4|+4�#g9�7��C��������n�5H:�zB�w�c�����&E����`7<�E�
kI�C���}��_�t���GE�!��]Q��.�����-���E8%jr��vks@��������:��HF}lz�"���*����iU���8�}: X�y�>�U����du���+}D�����5z���k�5UpsF)j�h�9�5�Z�|���kn����,��}��v�����K������wgSa�a!�N����;��{����/��_>�	�<F�;�LT��i�g0���;��u;��	u��^�!Ok$�����:)�E�����~`6�����V�E�x���jG��pQ!��"�m~���@sN�$��������5\��n�F�7�vZ���ie1��d���w8�,
g4��I�1������=#�[�K���iJ�p�l8Z_R��K���ER��m&�HJ�����@�e�r��7��p/��Q���&P��;iQ�7��<)j���oDw�L���j���9�5�	��c���h����u�l�k�����w��Z��#�;�n���[��g�
D������O��1��
�:{Q��+r�!L��wV��1��������IJ:�M j0~'E����c���iQ��N�wM��A��mz��=8��9���N�%��Pu���(�}���@����$���;����N�u��'#�Z��6�?����II'��A�Y����(���}�O��������M���x������5������*E�>�1d��C��Q"�������0p4y9\T�*;�b<nD�gJQ����3�V�!P���c����LED���I�L5�4��I����3A��.* ������u�m��A>wQ�~F�k`��d��}�u����7��-%<S�$hk�)%��9�!�3S�7
/��R�`C�K=S'	�p��e�/�����Z������C>���O-j�2��SK:�q�}'/= j�T�[��C��;�5����De	3��nU�%����|����N�]���<��n'E�q�j7�D
�������kEs;)
Rc	M�u�����p@m���68�P���>������?��@����i��F���*Ig�{��A����J��y�>�uv��`��[
7Cm.�U��wg������7����M��Z����P]|���7jI�o1Z���Y|�DyH's���N�1x�%���V�����i���+�PV��`�����Q�m1�_JQ��I-��!l5����(�_j?[��as�����v���<���_>P�?Q7��E������t�+�����C��?��$y-x��>x|Zt��N ������-����\ ��<�k4�w22N��LBx�6��\��!����x.���7�ZG������3f��P)j�N�P)��M��P
��F3]��JQ�
k�C�������z��_���c
	��7��Q��K�m���?�lkQ�c��Z������^����������#�,a	$����`������9��������pK)j�Hn���^��.I:{���F/��+�V����+G
����o����������wa�����I��R�:��D��ukQ���:���~y`�r���f��v���Uk$	��
A��b�pm����?i-�l�'[U��kR���j���=���iQg�������Z���5w��]L%V���s�(p_�Ot�uW���O��d�����\�n(�8g$5��=Ow�cE�����>u�Vs����������0�OU	'����N�0���,��^$%���IL�l���~`T�f6�=�-�J���{�����!U/�L�?�p'E
W:��IQg)�����b�?m�X4�y"�w�!r���J�������]~�g�G��Z��S�o���{��I������|C���I��F�����}������x�t	QE�P-�Y�/A��-�n��>��#C���E�
QkI��o��D�_�}'��`Gp�;J	��h��B���\P��E�7���m���h{o�w5��1��iQ����P�(u8�C�X�:�
�E���Q�D�jn_�"�7�&�^	Z�='^��Z�z7�������C����(�fs+�EX��[0W���VZ���5��c����>��Y�Ax���Ju��'Z���HQ��w �l�X����aO����+������gy������]\%���Qe5��Az�Z���m
�>���5��I��4��j���]�uv��_]�-�X���_b�B�Z��X1Zux0=���*g}`���p�����R	�k��MLo����5�[��D]�����C�;����&�������~�,�a�C��zH6qGQ��~�hlt�5W#�N�Z5FR��n�����?)i������Fk��R��?XM�'���HGsI��/���a.��Hi�hU8d_� )�����&o�$��8���IQ���p>-
��'
���F�����$bn��;��s|� �l�@��_�o�Hv�{uCzr��L9�E-
����I$j�%����D-C���Z�1}������ ���~�w��y��B���?Z��8��E~+`�����&����4)j��!<MJ%�
G��
6�
?����]��-�QG~��hF�
$�v��.��F�=�'A�����S��p���FK��=����I�iL>���jQ��S�����F�~�$&�����DN^N@���]8�5�f&�Q��>����z��o�������;j?����������3G���R�(�T�K��sOm�>���OsQ-��%F��@h.*EQT)����Z�l���(�)���y�F3��JQPi���
QYa�;��
�$�4/wJuv�������)����C���� j��-�R��?�:�.Gp���Fk��/��o-�V_�g��m��T�A�����|F�(�.*E����u;�Ux���}>}����-j�<oNK�"Sux���=�A�}���.k��?�������.{!�������hj�	f_w4-j�s�{�u���CF�g7��si�#�Z�� w��H�����bs�������{������3��xi�Q������b�DK:��Z�X��9�4��.$��s����� X������<�?����D����������v���F;]����[��^]���(���	R�FC�8~�o�%H��>z�$��}@��v�p@�
PK��;8�u�
:[Y�vR��p�;��{�U �P��h0�;���
#�G��/!�p*1�!9`�_R����O�cYR��5�����;Y!	�N������������Ww��]J�O!Q#Qg0H�s�@���%�� j�CL��u8|+L;$7�_jQ�i��Z����Y�������J�������?���5�������/JQ��V���� ����(�������R��	�y����Py�o�G�y��W��]h��d-�?5��Z��ei���4-	Z�$�#���gA5����E�o�W����Z��x�g@�����X8���Nwx��\����O�o�?p��{�2�m����N6��i;D��js��h;�p��`8�����m."�Br�n."���6�#0j	�a�����&���`6w��F���;IQ��-�����O&{?8Fs,)�l�����%R��T����_��Du�������iI�����kZ�h�Nw5-i���]M�:����IL��`�F�����uC?������@<T��w���x�
�R�N_6�$��PJ��pi9����p�-]s">����2��j"�TW�O����*��`�G�	������N4�U�e��KiUF_���`U>!��0���U	WZ/������������4���UR���;<��	!���(����?=��y�T���>�TR4m��u�|J/�Y������q:-j4�^)De$���R��11-�,�[���+JU�[6�/j��3�W�c�f8#Y�#�����!�;�����~����2�����$�r����������o���X/SD
w�6$O���c���U7�E�{�'Q'@���&�hu6F+Eeg��Km��r�N~��V�K�*� _���C����e>L����1\��%��Q!%]}�9>��W�M�W���t=^u��P��������xu��`uF������kA�)��"���4��$)�[��3���Qg{��}'��@��^zd�a�o��Fe �ly�r�~���H�!��(�s��g�O���t���,���Z�s$ iw�Cp���R�yO��(�{�[W�������~�8WF-E
f���C!��]�P�2LB��EA#�^�H:I�F���p�����M���[���_�����WX%��}:����IU���A��;,Y��,�*gzA��1��d���t��t��?z�p���~������A��}���&��?w>)���������I5�CB���>���wRR��Fv��>\l��.��6���=I����T������1�IJ=l�;iI'Q��6��QR���4�'�V������1��~��!��������Q�����dvh8�����p���)L�r;<M��=/�q��"Z�����M�S
6,m�(Dey#��Z���]-j4m(|QK:���m��$d������R-i8�)�R�:[���t��z��knF:��|! j�<�����9(h5X�*D]���70��V}:�����@�J)��y�F�J==��R��-Z�|gz�����l��A}�"��$�+jQ���� j0�,�R�}/
��I$�/���=0�dY!9�h�I�����,�W?��E�m�NZ��-�����pQ)j�9\Tku��������s5XD.��6�K��]���^=r�8E����t�h�D������q�O�V��AG����@�������c��V�o~��R�r��5���WZ��T�JQ��Y����pp<���4)��vt�n�YK��m~�:K������e7r��<�p6)j����E�l��F�����Vg�N���n�#T*�v�������������3=�SIA�GG�)�t��&%�Z��t����%i���u�j���f�u:��r�^O�toZ�it%�����Z����)E�^'�{j�N��5x�j�
<��B����]�	i�_������A�+-jx�r�Qg�J�:�L��:�V �P�y<�u�l���m�*%i4����b"��	�p:)��f�#Q��:�N��v���*�Nku��@��A0�N8���n3I���e$:�����t(�ck�?H:��D
�6���}>^8~���~R�Y�_2o�	Fs?����tz��S����aJKw?-��'�,�������5���E}c�:<�v��>8�uo�`��p�5H��L��?�������K�%M����c�pKm�i�����K�[JQ�u�a���kb�Km������r;�5�������������xW�����D�?�ZD
�C�/�Qy4����F��A�gLs@2��������;��8P��F-/� �JQgwC5��'�Q��w
g�����������9�O����cR�$C�G9~��1�RJ:{vQ�y��R��y8������pKm��\����-�K���-{:q�Ss���{���y��V��k���	A�i���N��`����?��p��i��f��r�j�%�>JI������u����$-�g��J�{J�0�o��6n�p�y�4zT�������1��zA;��'�2����gCm���p�G����iQY�����p�����/)|
=�p=&������&�B��7b��g��K��t��������s��[IIg9�A���3�w��sH��5{��p��1��&��x�U8�u�����:-j�4��N��-|�<��_���H9������vz���}��A���5����ws��zz9����X>�Z���t�"K��uK)j4��R�:t�&b�pKm��`x.�E���N�]��d ���>���������M�GD�N�%�(Hx9$���II�'��s`�����\N+5���>y�����au�T��:Y�N��F�������-���OP�dP)j�����T�%M�`]��/(p�_��;v7W��N�?��� ��chu2K�m��U�����3U���w���IS����1g-��V�F�|5�:���H3Xi����{��
�����:�������7RUD9��Ha�-����`R�0�B8Z����*�L[5zW#��5���[.��f\����6��gw,
����������[�p9!���i{PT��|�E��1 ������j?Y��h���di�������yE6'/JT�����n�O+2�.$P�����N�:fAJzU�$�$�2�>{��d~X�H�1Y�=��n��'�-���?��i�(E����V�����jQ�s*EQ�p�1D�:��]�1������%�����5�4 <TH�5���K�q�n�E�>�7FK��A���J��lPZ�:�����������N&����T��J��)A�������q�AW�pJ1����g*j��$�����D���R��+�����}�<��-��g��`��5�
Z�v����SH�@�i4��u�%Igc�Z��-��A�
��F�������YZ4�'�����(�"^�J5�|���t�v�D��J-�t��ov��s�-���pK�%�����Rq���$7|Q��.�o1��
�J�x.H�@���;��y��V��G���*n�V�|�������w��
���{������a������-�����w;��i�#���b�U��51��,�
�Cg���p�w�����y����������#�5�=����IQg�=�*�^�9�T����L:y���:��9����Q���\��=��;R���#���,�olV�rz�!�z,shn����A)i4�9N[t����-:�L�1����L+BM��`a���^��J?��7�s��c����/27�<LJ�6Es1�d�
���:rA�l�8Y5�0�nF��Y����\�:<����8>Vd=����f��v���me<��t�#����1��$}&�67���K�����C��x"	7�V���57���:��.���;��8~���z��+IE��<��{�c9~�5{x��=%�c�1���~�52���2�R�FFn���r6��z_�����������*�ag���n����wR�p�p@�J�*���"�������Sv�k�&�}k�G2H���?����Z6����/����KZ������{x�pO���3�����1���*-i0�6�
�;�����F�.���?x]�[�i���j��/����p�'����������@�hq8��4��><�����|R�(��>)j����W?��]��|9�k���pD-j�
)|R���	���F��SJQ�g���R���}83�Go�F���7j��R��3
I�e�_���Etr���?NV��E-���o���
P�fgsg����������3��@�t��Cm�����k���u�7hw9p8���������J��Z���)�S�Nf������?~�w�pO)j�Q%T���q��r|,
��$}�k#�<T��Vq8��9�E��A����!�h>����*�RI
g�?5Bt�{�z��p6-j���M�:��D]?�%�����~��I�?]����j`����X6�I����=��W�,����t�������z[������������
p�N�$b\�|��T>�$]|��.��k�>T�h`�	B����)IgG���?����A����N�����C�)E��*7������a�%���A�������b��O!j�������D��sum(j0���R����X����x��t���FY�)�����}���n@��SjQ����	���N�D
;��i�UM�����u6,��xxV8����IQ�G��rR��[��	�����-�"L��z����o��������.4���wJ%���[��7�rO���h��$��O�����+�����G�����{��(w�{�5�K^GFd��g���#��.�:"�����h0�|>�~2�����o����(�'>R���b�ooZ�>�f��U���<�xp40�@Q�-P��5,�k��#
/o�]��`��Hp���j������jb��R������*C{������6��=R��ss0��C�z�)W�2\��6�+{N?Pt�vJ�����_UN���������{�@h�����i���:|�@?��E����U�l�caKx���m~W�����>�)QYB8�Ve��	�������*�D
�V���Q�g|��`�Ps0��p���1�:Y�}��{N�����5��iU��CI��%����Q~Iw@��A*��E-�lb;�w����Jo�J\�������G��p?>���!��y\����8%����f��A��g(���t���{)����]R��]��E�1UJ:�!p}��Tt.��g4~ -����i!?���B��II:9����&����G����;m����x�����D�~6��4�n�~7�K�~���������;5�[��[����E����	��Q�v7Icy���`�`�M�!(u�V}u�H�@�0�Rx��\H����'��)�����!����n��i����RJ:�&�%
��6�������'�u"��m�o.I~���wM���:���F����Z�`OxwG-��d����{���Nz#�vX����OD�3��6�i������~�]�]q����:����t2�EK�n���y-��){�DZ��yA�n��s��`���,�IcL���B��{r���|���]�$����j���
T���iE�f�iI�-1��@�I
�n����T:�6���r���������t2$���������4�"��(%��������$�F)�dL��$S%i����;���?p6�4�s��I���+<L*rfA�`�p0��K���"#���)�B����]��Jy(������o:�����������qZ����[���zK���~�Y�q��C���1���l���%��Wi=���*�C���� ���c���
�����A�Tb�����T���vp9��S�*��p)i�8{����������y)u��9�{Qd�����FK�s"1������PR�����	�9DR�&�N0Z���7I��+������{-&�T�#���*�c����5�~%%�}������ZU�c�����g��9Ik�%�:������j`���};w_#o�����|����ai����Lw6��hV�;��4zwgC����;�n���%���I�����r_�r�`
F�e�V�^����m�����g�zOZ�0����yE����z��O���p��Z�Y���	��A�h��;��y�7wA1�D����4�r��F_�����pA)	��$Z���
>��@m�`��{���OU�y�� i4�k~	�N&�kI�'�~+����I��D�K%h�F��8Iv�e$����7��4�YWxh�D$w;�?K�pxs�/��qZ������FAww1���C[�����{H�G��,��
���kBRIq_���b�������p;)���i�����(%��9�?��=P7����p���w	��_���r�l��wZ��I�y�?�|32�����%}c�����R��q���mR���?������Y������_��_��������_n���}z\�y��?��.�e���������'5���~���eZ�_���`�.�e����4|�;^��#�O����e/��1����0�cK����Ma��|�u�<��s���oc����k�����'C35�s��m�}�N�=t���z{���?������\/��:����m]?���6��^���1���7c�`�o�S�x��������=t�_��^��v-�_� ���~�������������6�� ���'��#�O���t����P��|���?����/�rY���^l��p��y�o\�����}�s��I:�?�6��$�n����?��������P��t�a���H��t����s����n��k�m�[��bY�O�^��r�k������1mc�O�c�n��m�.�}�j2����2o����'���������#��F�j�[��\�����s}�O��]��!b�k20v�]�����'���~/������k�����r�j2�����nP���y��!����'c��e����I����t���>�'��^��r|:��I>����OG�?�����o���_��e~gmM�e�~��?���v��\������^����L�t���v�M�t���6���z��?��_����$�Q�v����1��4O�z]���vy����yZ���>)n�����i�C�����=~��m�O�n������7)�>���u�>�Sz�]�i����O_���m���������&�����o�'5)��e�����x{��r���M�YU�X|+����.������Y]���qZ�u�.���y}C��v��������������5���OW
���b5�����8��t"�����R���uz]����H-���6k	�My��Z�X����������{�w%iy'ro0s���[�.��M<:��z_���v9���������~[��=�qz+�=�������oz���u���v��=����r��05���_~�g�!�����Q�����\/���tA���Oj�]/�Y r�~����O4
8��:����F��>.�.g4m�sR��5��5�v�L�O>��r'5���!�},���(�@������c9���h��G;�c�t���������"��z����n�xW��]����y��E���[��G^���(��Z�.[�+��:��u������J��u���_E�:���v�_����k��3���m���
��e�����6��������v�b��)gq���:�,�S��]���e����_��T�?�E�B]�E��L{y5�ux���v��ZO_�>�O	���t����,�(A�6_�]�0���s���y��sY�E����N��9\�����?���H/��2�K��z�^�YW8~��Y��o�m�/��~���e�\g��Tf�>�Y�X��U�`2��,h;��w��\����|�#_�|����]�o1��t���>����'8j��i��k�c�~��Un
�i�LW9f�<o�.����~����m����*���k������n����]�����g@��v��S�7�(AB��5H8P*����;Pj
l��J�{�����@�l������f�
S�>n8Pj�<j(���jf@���>.P&��%��J�%��:P���y���(q��g��R�@=��]1�R��������(q���;P��������]��(IF9�-9P�u4�.�����Dl��r�J�1��5�:Pj��y� �@	2�eB�@�2�y������<���7|
X���z]�DS���{�bq-�CT*	[9�>�?4�������>�4��6�ux
@������`��+�S�:����JiC����u@����g�/5�d_�u�J�s�G�
*�
�Nw��Ts����
w������p}�{���>��o�</���r�ILR���<:����w�����rd����Qj��o��y�������rOd���5�T�P��}�3������x'��,���I�
��2��S�*s��z���!h�d�w&-�R �����m�����Cf�[�w��
`���$���A�a�n��=J�r���O���a+3x�c\����Y�A����~��r&}�}o�l�Z��#����1_n�$$��Xm�`R��Ut���e+�r�Qk�H�u�^��4p9t*	��(� ��>]�W9����2��V<�QNg<���]$����������a>�?8|�wy[�g"c�
������}n����\��K��;�'�P���s�%[���7�f���U��Yh���:����c�;!���?�������SH(����������B(�����������SY��c���|�C���b-���8|
+�a�]9|J+
l�P{�OeE=�<5t|����-��S[�,� o}���*>u�cq�����������,"�!�S�_u�v�������-�SXq}����|�g2��
>�Z�K�\�_^�>A���@%�9|jS��j���2�[���&HX��l�a�O)�������x�l�O�}q�D[�����m����v��\/�]�����8�����e�nZ��jA,  TX�����H$!����%[qmzY���r��%P��T���-����7�"�I	��S��o�w�0R�D������ey$�f2�"�O��.�B��H�j8��%0�����(���q���[�|�p43���M�<�O���r�����M��U�I����E�a�4%����8����\�'d�9�jv������t9��`J�4�F��d�\��2OA��s����S����R<�]��_P558�
|oU��I���]�l��L�"�l��������/;��m@�2��1���*3
Cfn�4c*g8U8���x����h���*+,�Vo�
D�bL�mC��g�*����RA����!�������C��][}�����gJ�������@U��r��9�����J�O�U�Xo�����R�d�|QU��QqW#MCM9k<!i�)�(��:l�)���\��m@�6����$�z�n�����AfwdM�)���[f�e��H���A\a�^-�5PS[R�����`,��	������X2���NiI	 �{�#�0�Drg�'t*C^G�;v`�6��<�7��Kb��'������'d�|*	b���\��vxL@< ���V����
C���z�0@Tl5���+������c�~�hw��
�I�z�����B)�Q^,������D2�MXg�5,����L?�70��T4����Z�����	E��VO�r�hx
��\�<�{�/o��^P5�T1�U~}�+ �d\�����Q�N<H�ZX@RrRA�f<�UT[b��2���
Z�v��RQ��R�!�ez��Qp���XK(rH�e�4o��C*8���<�B�b�L%���#�::'�
-�r����C����N�P���*g���M�!U���4�+t������A�\�r�,�=r.RI�KI������O8'�������T��U"y:�;0d�S�&�TS���L�N���kY�?�m�������
b�C��]���e[W5�����,2�������Q��Q�[�R��|�����*�YM��2p��J�@����v�`e4P��	M`�W��VF#
���2�����%
h<�	�hC'�"i��1��7�6���T�7t�/���~y����T�>ScD�)��Q<���^v���}'R��2��-\����PO5� a��Y�x;"�*2k�r���R 3��9�2�-_�%x{S�k:��.�%[��g��>.���<"��r������_3!��q��YGH���������r�����Hm�1����h@���f��_j&a�l�I�!'f�uX��;�2]�����L���B���Yp����7�%�J�A9o�.�R����^�a���}��R��6�+PanO�d%s �M�X�r-D�+�(�8:�6�d�����h5`OU����V��)*.�����Y@�������h`y���{J
��q%��/�
,��� }^
,���v����������+��``	6\X
l��a��z^���������,�=�
,y�^`���F�/m��:�k	Iz,'�Y
��(=�+5��B��$%L�+�C���,�W)2���(��A�Z�
�O��i�Iz����vIj�����j������!S�(��^�d�t���4�2��������~�4)	\�WE���f���V����fWB)�"]Z��*�=�4g�UVXBP+l���l1p�Z�p����3���O���0�lT�t���Q���A~v�����=jK��<��g�����?�E�,xJ
�X O�
5�i�l*W�f�AJ�g���g�L�
>I�^/j|��
)|j5�(�>�������5nv��'�������W|j{a��A���e��#
�3��_��"�N>�
9��i����eY���
K��|Z�OeEe��W@�Oi��1;|�Z�X��)�b�����k�	k���v�g�Q������@�<
>��
�����5!��V�vw�iq�w$t�,$8�J+�
ZG�@�j&d�j-"�K����c��|P����:�&2f('qE[e�d��|�M0T��%-�&���S��(����yG c�������T�|&������p���O!��������w��Pa�%kB���;�0�S3(;�hD�zL�-&���fD�1������e\^!E����`�l�
iIi�V`G��r�:�@08���uc�|�p�?���D���Q���B1��Q5��@�O������M��h_���P]������T�m4%=�F5�Q1���j��6��$p�d,H��pT�R��t�����1����&dv7�u��w����Y3#���q�/�x�WNu2��V�	�0����B���������$l������Mc�JB�|`�P�Q4������z9,�R��6e3��8�n�3�;��O~Gt���v�{G��������	�<��B���SZ�����/{(�7Z�QiEM�p"ug����:��6}E=�z�OpE���4�H���6�,��]�
M�j�E���|��\��K�V�(�zl��$%7��.AQ58��G��-;p�K���>2�(��b-Ebx�3`�uS�������(��X�����r=�����`Fy��(�fT���O��0#���J;��$���J;,�������f/VO��0�3"�j8��b�e��8*%�����H��W���J��<��h_B�k����(�x#:T���U������vI�2j�����(c/�i��a/�)�.��V�,����T����:��!��%�B�����
����R���Rr%�f���s3����
O�]T�P�$�X�a�2"c�
���q2������~�'h
|�'@?N�&�)W������B�R���n���]��Goz5�6+�����B�Q��=>0S��fdJ
8��+�]���i&�@&���(b�+����PS^t�DCK����i����J�ro%���� b�,�)T*C
���hH�ZP;� ^�n]B��T������!�16�^��iS��q�h"���Q��5Y��S/��%:�,�9���2��'W���4`��������e2����:�s:0'K�A/�I,��l���]�������Y+;���3����Z=���y����zP/��[����,�[a<q&Q'�Ce��2��`EeP�.�;,k�����.�k��i�`&[�K7'82'�LpV
h_%���$
!�.�RJ��W��0��0RI�Jbv
#�j��G lX9�(���A&Pl�n1v�M�!%_�6$E-
(����(�+���eo�2'�R���
*�
Y��������``��`�����������q%��?�����i��?!�CK�%p�`K���S2�r����aN�@z��F;�$�Y���`�M��+T�XJs��%�R�Q��_����Y,�{�R
z�x�	���]���z�?��B�{@��PH��q*�R��&����k�-�*�
v�M/���'��8T�:l����a���C%�D�*�
��q@%��GT�:����/}a[����,<1:`)l�7[�,��^i�f}��i�d��:i�S�GIQY�����"������7Wx	�$=�Z��=��)���/L0�\@��S����#�I�-WkN��.���V���~�GmQ�6��VE���f�+��4���d�j�x#U�G����HZ�X�c�F��0������
�q5��k���
8�ZiA^;�����S/���tj+&�*������s��Ua#oE�$D�#y��R������}	OK�����O����`���\�u	�}������@��]w��@(�Q�4����pVz�%mBz
@���`'�.�SZ{SP��\�������t�)�N]���9r2r0I5��P��'l,������\������VPe�6sbgPm���
@���$����Z�C�:T[��������=��$p�J+��k��_T�`x�t�[1���!����L�j-f��O��I	�h��Z�k�
@�3���v����Fu]BP�c���L��j[e���� _H�����
ojm�m����^��Z�jA��\~{l�y���!'_#}��/wQ&�R��A����D	���g����]���������C���(�1�}����N��^C�f�t%���:�����L
G3;��QiG���qT���5J>
G�\NV��]D��/���.�r��7�N0����BvU:D�6G�W�E�*3GQF����w5jW�Ga:��R���(M�:��[�	=.���m:t��c(�0
o�#�v�kl����z���`hwd�U��4�K����cC�2��:V"G`�����6���=#``���;{`����j�l!�P��)��J3����P�VfF�����Y�j`���g�a����4�j��4G��`TI�m.��(Y�bX�a��`��J$C�v"J{�(	���xC�WxQ�M`(����)k9��*e�,��%k%�O��<��7�����jCn�*8�e��T?����2�=��G�#�6�����BB�2��t��� 
2EG����E�5�L�OG��mX����R	���(.�����Q�����E3���^j�����H"�����vKA�E�zA�1[8��w$vlQ��"����7�t$U[L-����#�����-]�\V��B��t@�F���>KC>�QEj�F�_J�ol��h�Q�aE+��d@(v����~.$c��25(`t�<��KN���z�������`P�������_2EK�Q��S�g��Z�l�&����r��w�Q�3_g�U�b����6�$�����h������<�
A��m�Z�eA�������~�<Pi�'��N�k�)u0j��&�����&����u�/�G�V2����p|�^����jl}xEK*n�
EK�7�!(������(�(
]R>���.QN���������^�`�c����1���R7a��
�������5���T����jV� �n�����@�O �����N�3R{�1�$B���Ya�V��L54�b��efB��:�'�ZS*�3�y��������R�����7+(M��W/+����X�(���L���p��.T��,����#���-V+���YSR-��$MT�c������_2c�]�2�E3�)Y;2��n�����N����g}e)���`_��@)Ia_�g�d��d���(
��@C1����lX�5 Q��4L�u��-~g�6��Oh{�����F���"};��|�N����jy�YR�E\����������#�������u���]��-Zof@���
��B�� k�Fj��Ob���2fk�����]�JJ	�1~���ZF�H��NjK���!�;����v���!�[�JO�/�0P
	FU0�K�e_w�]M��
v����2�(�
��4��6lL�@�mHZ�P*�	�T6x�h�)��R�0'4�
(a��v��`��b��R��.��oC�@0�J��\!��Jj�1\.�:$X�B�l�O���6����2{���I2�����4�nQ�*'S���J�<�H�(YD�� d�7Z��7�����a�.�	��sZr�2��r�z�"���u�H/$�4��[�]Tj?J���x&
�6�p������
�a�:p�Z�5�TViDV-Jk�#WR@'���Y��z-��,{��H��<�V���0:x�y�i�:e;�Sh�����s����[�h�`T���I��X�C9��\�4 �2j�@s���"Q�����k�4��+<��tk�g��ZF�P�m�N��i}Tdb�c'�2�NV�g �d,��;-}��{��$�)#_���]��P91��a��a��d��J�l��"e��=h	������!�S�����������z��)�0R�����X��<�S���dg5��k�qK��N%a���<�HX1[F0�{N����3bVR���j�]��z*	���9Ej&�S����S�Cd��l�'�(�+)9�Z�v��*SP�F�T�4�P��f��s�2��@R���$��=7�2'�
@���`n�a���,�N�@�#��s�yu��`ZCdEJ��D���C���V��U�`�l��������B������@��V�B�a|�)�&fO���4cNj���%����j;,S�G��6<�
	_v����#pTJx%y���j�	2�G����,pT��7�e�#�Xj��G�gM4Y5e5��X���a�-0����Z	���qTOG�'��%=*����(�2�T�Go����E��������
G����rI`����/������g����������tFpT�Q�M�;8*��/�i�(�1%���J3�SyZ%�nE���Q�c�e����	�n�h�����#��
	su*���j�zb�����`��o�� ���4�u6S��2p�d����}4�c�������>�@�8*e�t�������J��2�eS�)W�Q-c�7��m��p������2O=j�G�#��>��%T����'p��e>D�Uv��)�
;J�?�����4U����������8��c������xb�s�Q�V�)!g[ �JX��*�Z�u�r�H�l���FU!����o����Z�@Re���W�@R��Li�PGRa��q�g��O���B���Q�0�v��n�Q��n�1�?
�.'��JE�(��Nf��#VI����h�WC����9�jk�o����~�^{�.Tb���p�gQ)a��X;��%����yC���o��,
�q�V<�!-k}�ux%��YTI�p�ET�E��30@�L�v�R-�y��1/�3��up�3�yy~v
����x&�0@��0c;�O�b"�	F��^C�O6�?��_��C��#� m�
Z�d��o���$P����
I��lJ=�g�:q�2P���d�,�������N�[��4�N�����m��j$[���;�GS�3;��#�bl~J���!�vJP�f�	Q��tl���qF�6�ZZ��6!T��
�X�����yT��
����l�v���$=y��@�N� ������C��'����.���~��B��U�_1#�tHj''���G���B�2�nO�	j��t�����������ZF�� �c�ki������'�&�� ��yo!����dJ.�.y�&0$1n�������vj9�/=���v��g@��������> �x�rp$�!�)�p�)��q�W?qZ��"N?��;�O�:/�����>[&
�'+�����b��%���D�h��R�o�����:
�����?��R��������3��{2��j�8�'�%��S��d�H���>���S�>�����E�Q�D2XD[(�����������aqX�����a���/c~Mh����F��F�/<
�+��13 �L���Y@������7F6B��]�7�>_G4Y��%��dX���6t�
xe��H�����G�+0��3�Q�pql�cw�����/�,��6J[�$yL��KZ`�F@����RD-���d
3-P�D����!�xk'���cd����QKX����^���������������?��V��4����a$J���xz�V�'h�N�#@�Y�!�%��CT�P�5��%?�2�YK�}���@���.��z�C�lC����1���_ &�(������0�snsf]-��^�2IF}uM�\A��05�D[j��5AFy����l�-3��7����4���Y�&����Ji�)�Y?a@=�M�������ZBI��Me��=7+��q�����q���7+t�V�&H���4�WX1Y�Hp�T:D��4eIK�y��a9���:}��	<�7�SJ�9��d�)m���)�S��g�@���d��y V�a�X��x�����������2�%R�:Q��f�e��2�Z��A'Z��%�r�s�Hi��A�\�����tJ	�eCN�$$��(%tj+F�SHp����Vd}Z:�L�|	��y�!���
�j���Hb��Z��d�8tv%�FK�L��S���:t����l_a�dG]���S����/�SK�0����p_���D`���#b���3�S���4�v�$5v�C|�)�����`J-������v�
@AF-9����e,f{��8
������W����e�(c������
W!�{�/�eg-��.���S�1��UR�d����z�k2�&�x�)N���:�*C���Z��e���6���S���L"�S!�Y���\�>.�\�k��
�L^}J2�!�d�*d��,ZC�|yl8����T�c,v+�s��v�����Q/r�r.���aT���P�PESJ�j��2��>��)��{&@��4�i
�('�����D�����D<����x���
RI��Tv�}V�"���J�����yl�J�p������Aj�&�Ok��/k���
�����;�h���-�������� =4 U+�E}J�2����Aj_�?P��C*Xb��d�u�/��g���SNUaI�N&������GJd���kO�ZD�AK�PP���W����6�jC�Y|5�mY�d��Dv���-k��O1u��!����[/��Q�PdX
{�.�/��t<�;X����4��U��	�s�jK����P,10J/��!��lm����\_L��J�����j��-�I	��Z��R�sT�g4T��pD��r���bK&��*�H(�U�%/|i�����R��@�D!��j����=Z:�J�v����e�K�
4�<
S��rf#��������x�+���k�VRDK���;{�.L� w��/�� ��.���(n��qi�7^k�������3J��N/�J�t�K-[�Q<#-x1c������G��h��3h���Ga)Y�!e{�M��z<'XZ��}��TXPS�����4�f������r�KKQ�
��R5�>��vF����r�s�->/�)��+����QS������ �����������]my�)M��d��Z�w]��F����i��8��b��0�8����4������B��J�g]	��� ~���%�8
�g8��P��j�3���FR_?�5hT�3eEp.���|
��O)��Z����V
�} q:�Q�oM����~?�<`�	���3Cc���G����Y�B��F-c+�*,5`�"��%5G�d�RUI�L)��>�7`�2�r�h4��R>QME�\�U���<�����2�(���jkya��c"�����/����Im���������l�&X�/h`a=M�_o��,���A$���GO�%
���?&��t�&�g��6Xz���sxR��l%u8��RIxI�oP�����*YE)YP/.XJi|���n��,c��w	X����e��.��K�O����2�k��%�(�M�K�c�t�)C����1���R�@��������"fw��l�.�Sp����T��J
�`�5��0�R�'&@:����	��&#*�&X�5#aHL����	T�p)MX�g��4a������Hj��H�'T��"Ri�����PG��^�)���`�VN���:���6`�F����L����\V=�E����a�R���;@�{��� ���V�/�;�e�G=E�6��#-�P��������}���#g\�#k��B�*S�xq|:��4b�����jUR��V��?f�������)F�/n�� ��H�3%�����`����[��d����=�t��-	���������!�p�+f�[GK!aO��.�Z�~�����0�
V��,��(�����(�`f~�[}J���$b/����M�k6n�ZF� �X#=
;��;t����4��<��m��G)x�.��;oC�� G:���n	��KX�:�\"]S�l�������Om��Vx&V��d�����������
�����bM�g4�d��������vG������S�D`E	8�#���*+&������9ydh�����<��� z�:8Y���j�J�H�/�Z��o����B=O�0~�����>�!5�&�$-V����-�K�8�z�-��?���e�u�ER�#=���;��/�>����*	�����]�Oi�U2f���
n���S[��|*+#�I�`��:|J+�P}�Om��4�TV,����gWB�S/Li����eL������X-}F��8|�u��H8���\������z�{u����X"����P/)��$�d�7x�%+j*�4��jN��g3.�ZFa��OJ���-Pzj=V�TI��dK	��hK9����������2P1�.�Px��Qfqc�>GP!�+*���f-K,���|�2P�d5�HQ,I.�V��X.EB��Kb��rBH�!Y���rK[T}�"P����Y�C��b��@"gp(v#[���^���2���dX3*�q0v��M�g�
PZ�g�SC�����#h:��v���_��YL�'V����9��[���"
�gAO8S���/�V�����l����Z�������\��*J���t��/�u�q���
r��M:t�T�S��O?�CU��iWF��,�p�-y��_7�t8��T=��7�T[�a�K�S�$M�58��lV�''4�Tb!v	C����0�MT���E3:]e�e=i����V�H���LE��/�e�I�
����X.4����_�F���P�I����
;.�2�*����9��w�%	f#=U�)k9�0�o����W�Q����A�d *�Q����)�Q����@T�e�$+gU�m���i���}] ��
b�u�WA��x��{��!e���RH��c����#��V8*-��3��d�dmA���1h�Z�(0@~���}QCP�����y�h�k���*��8+�n�?�Q�����	�E�.�O��^#�_�����8��-oI���/.K�=�e n�2�3�.k��8*��TZ�S��v����@7��f�c�8F��dKm��?��-�MZ��h���!��2����g����4���YA��1+hx	��+���Y52 (�V��a3H��_[��)ym��
J���$u��,�]+�)�
��:��Ri�,��_�����?�?R���5�T��X��Ry��d~���?�!��G�(��B����Io� ��@B��#�Q�aF�L�I���R2��%�l�+�J�|\vp�����'�
6|�^�����cw�u���>|�;��`��H���ea:�W��4��:��HiC�l )l0r��F��������4��u��<�������J�/A�e_B�z������i$}i6/�Rv��KxY���X�p��`��u�����H����D�f?�V�	�%8o�B2f�K����[)d�`�)k}fJS�0"t�L�G=������Lp�k�	�R�������~�^{L")����P����$Xkx.��S�}�*`S�PY��� ��!�M�
x�
���X�:wgk�����4��:+4GS@'�����t�%C0Dq:�^�B��P9�V�)l���rj%�@)x���T6�����Ozc9@�����3����C����x��*R-�\xw8�t����(ti��M���);YR{��5�l�X/ZR�z�X�m�t��i
L��
X������y��B��h�r���?�������&�j�D#GL�
��MS��0F�%��A�����ZJ6.:���������0a�N��<�R~�$����+`O8�T�
������`�n3
(�]��p�����C�Y���-dD��Q��v�AR+Q�I{F�uU���Q3Z������!O���tVh�HF��x�@���/��w�����HK^�L��G����3����a���4+$X�Jz�s�+��  RZa%!���0R�E���yp�����@IX�����`����'�Z���J������RJ��-V���j�J�"W�P9���������I�}������!2p�I�W��"�4�L�C�

p�i-
	�{���|��y��^!���
�u z���eb�Du1~��E��l#�N��P��D�z�/=�<�#xr���g��g��������:��
�n�[7�TVX���O�B?V4��k1q5M����i���,X�p@5�SZaA�<�Zx���^A��]t���d- u(�SY��{J� t����9x�%D����(�.t
TOm��E4~�:|����~R�[e&�8b�O�G�����O0��<CN�_:����P�My�>-��&.�RT�_(�����h�N�}���hw��_�d^*$L�Ew�\�����/k���B���^
v��
T��	
D�k��j������-BuO��2cM��4��1sq�����$���
��&��(��k��x&O�
I�����������"JA��W����T��%?K��'�lt,��r���>r�[�vO����z��"K��yK�5�
�
KI��|��3g&����-��!��.[��
	M�����AM���C����/����h*���!�3�����*!��h*�x��7GS�dr&M���g�����^�wR�I��@Sp���>S�ya�\,"�g;�$��T����cG�UZ���|3V`���H����b�:A;������M8�%�U�#��Z�w&}Y�,���1C6^�)�(m�s�y0�YD:�A�����N��lI��2,M,���"��h��&����V���Q+��)���x��c6��JgK�&/�Q���D�VPsn��i�X0s�����6j�	^D�����C^��[JP+��{�-I�UX�V��X���`6&��p�C�����|%\�V8*�$�(U���7M��[�~7d���_t�dV:TH\�����d,��H�Y���v	��k�GZF���QY�P�d`*��Kv\k>�����Uc�r���=�-�ul��}���v����K:����z����C�P��c�}�������rt��H���"�;4J&N��-//�T��"�������wYX�5!	4R�H�����V
��/��b���/;��
F�����W9~2/����(-X������`��P��X�]a��<���j�vA@	C��� `O��qeM���R��d����j�H��<��Q�e�����U���^  ��q�����W���]��QI��B�j���|i�W�P�����6$%���`��F*��0n��
T��(I��+�J�u({$���!_�,$����������6lI0%r���(kX���J�gVJ
����@����7�@�UO�����c��$Q�Rn���)��+�QJA"v�_��L6e�Ps&�r���4}dr<Hl��>0kYG
J0iY&t���b�J!�?�e/���dj	/����R�����R��1����� ��J��iw4�C������bN�����`*��Z�/7
8�j&���]	�8��I
��_�'�����
���dDj%�J��8�
������2�y�5S�P3Ug�������#u/ c��S�{��F�3��E���2���)e�T�	��tj=�Z�%���,��t�-�8#
�^7�[������L��:���N��R���:�N:�A��"�F���X���:y-����S[Q��z&:�Y��N�"��:t�G����s����
6=q�L<j�aA[1O\���)$�	�e�'x$�8x�?q�Oe���M�����;��#�m"c�eH�JU��t*��"I`{p�LdL�2#�S�b����-8�[	��Fh���,
h����l�)H�J8�.���Bd9Un���g_����C�g_���@�d���9I���Zu<��pJ+�2���������Zp�eN^ �
��Vd�
�r-�B?M��:l�O6�������
8��"m"*$���9�SZQ� ����'�H��V$�
<�+��R�O�Q"	i�Vxe�[�yO)���Ljx�����S��,y��e��v�&���lG-�H���0��:�{��h�l�;��j�8���XA\r7���9���MaB��c����0��5����M��6�1S�B���)W�"�i�V�`e9�~���Va���ES���q�;\�5x:so�#T;���,�*|%��+�Lq�L�R�_)�*�,���PJ�"�����(w�4KV�P��E�D��R����ZL�S-�PD�"�3;Hj;�����*���@s�%C���Pj�)�hUqD.]R�>��������Q*$�(A���p�/��:i���K��4��vXcH�
�D;�-���\�%�]�j(,�?D��D��J�����j9f;w�|
��W��l�@������P6�K��V
v<�o@�r�z���N�y�E5*@��X�L������s�������@�2eI�S(5�9�j=���e���dJ�l��AdJ�@�9PT�Q�&G����!�qZ�QZ��`I�N��<�!K��a��x������W-��-��~�*"����T������T�ahJBM���.�Y�V�(���<���\�hJfXV(���hJfp���i��u�h��x�k4��*;fk���������m�!������lT�reh
��5fY�z=j�(����v��'GS��n;����c�����z��a+��Y(�U�}41��WfX�M�N����d��f���D �N:��X��X'��nmy��
���o�u	���z�����~��������������J�<���m��*����5.�>d	�9����'�m������������sG-�����Cz��!m0��9��&^��bm����q�����!�p7�0����y2��a�aN.�5�����ZN2�@�V���y��<h��WO.K���sf�B��k�b(	�V����A���PB�8Z��B�/�_��:����tc�R�����u�^��>�������r�*^I�Z.T���+�������B�(�;�aWt��U_�S��^�[��$���k�O'��R�q�����Bw�����Z�i���B�� �l`F��l�ZH�:P��A��!Nl��l�����  	6Cb�d�n��:�� 	��!�X�������V���&���2?�AR���

$�!1H�kI�%N);"����o�Z�\�;�%����@)%�t�	&����,�i.P��	��P�����MN
����m��^"����31�Q���f�G�J�����R��O=P�
��@)mH��(af~Ov�L����
(����@	����NJ�����;P�:�]P��1Bz�HH�+��{�M��H
j����)����L���Y���E����QF�C�����s"=0A�f)'i�e���AFm�B-a2A���'���2j�UZ��K[n�i���0��=���B�,ot��h�%����_�}��
�D+
u+���~3+�f� !�S[�
A���H���Ni��s�d�������V��q�g_����(�SH��o�p�7_i�du�Y�����Hh�����$�x��{���!K@V��!UD�P5�V:P����9T�jSJXu �dl��T�'4�2J
�^\��-_��V
� ��wd�:$cOJ�@��e���B�SD��Q&�#�B�w
y_rU��F���*�X��!�wj+<��hbPe8�J+����B�~��'3VX/P��B��r-�I�`3��������UY1�P'Q:�J+���T��^Wg���y���isTiE�,_V���M�|Y�N����h�S����Q&t�
;��(�I����G�O��Y���?�$d�\�����$a����s�]�G�RQB�z��r��������JF��R����oA�X����~y,;Yb:y#����%�s4U���B�����%I*��KC����aE�!��<��z�C&���dX��b�H�-�|������Fh���#i_�j�@}NoH���g��#+I�k�X��T�C<�j�%GRe�nFi,WzU�.��WQaG#\�w���$�2JDw,�"���K��/����(��V���r	m�=�u=�_EA��,��>4<�2JIEdO��y����iwd}B��'����e&�f���/����*x�-���������z�O�%Q�SkO�%Vh��x�
�"���G���	p+u<��T� b`r<�%��r?�TZRs�S�B���S�ox��P�yRS���}	s��f�J�f��C��j+�I�y���kh<�/����v3M����s���i,�"�}����@�Wy�H�_n�v+�����z���GiL�f�Z9�j�����m�t(��[�@�;�j��5g`h_�T���E�Ch_����r�fT���PaF}��*R�Oa�5�����z5�m^4
=�b\�W���qMR>;��l�t�1����9u��S.FR����a���:�k��j-�Oi�M���f1a����������aS�,_I�y���`���������<�����f��V�	9�� �DX�V3ZBq���l ��1Q-��?I�^J��T"-�ex�I�ln��?�j�j�����K�1����?�U�0��!�������W�(�V��5��ZXk�Y��S����	��=����}�(��-�<K-�OZ����*C�Z�2������3�:1 �4+^q�K�u�
D��5k�(*>�Y�JO���~���0
G�.�j@�>������Q1��3��uht�PuX�2j|:S���(y��RD�q���Z����������`�i��e�j_��N���0f�7Q��|��<�)n��ct>j��2��C��w%�[B��MK�����1���e4J�,��LJ#A�������uX���a�%3��o������,<M����lz�Hefl^�L��Ble4��5Id�zS1�������?��  �Kh���l�����|n�	^o*��p��|��TU�h����E���$�^�S�D��\�'W1����3=F�d���5M^�jGu����%��Lh
����������E�t�������t��R���+[��q��JBV��`R��Q"L

jX���Lj�8�0	60��:,|;
��6X�?�I�nt����7��I�%��L
j�`�6u���_�Uh0�������u�������L���
��Er<��L
��]8�E�`G����L�N)m0	2*�������k!y
�Z�\�)LJ	�)f*M	����������8���"�|NP��@r��k�3%���8�C�p�d_��2Z�{(@R�~��gIe��g���
�Q����{O+K�u
$�
v�-�$�6�	IaIi�5�v��uZ�Ie�������te��H=R��:�s����YO��$FjP��4��R�dD�)%}�@T��R��Q2 ���e_����?�(�$�e�G����R�Q���.��R�(��@5�[�7��e�P��)9�� �\��v�n=����A�|�������%�� ��S�}��e���F����	V�c�0�x�`o2�������`��M�4�GeYC���hD�uM%+��ni���"�:l�y��zo�Si��Q�8�O�����'���/�rozY����.w�m~������ew"�`N��s'6N2�~ y-)���������e�P,e��{).���q�[�����>A�^����|�m��lP1�����3=|v%��O��|�uxE�Y�v)��������Z�I�
�TV,�S���������SZ�4h�)�0:���H��W�������d9|j��Js>���n���b��7���0Yy T��_�>��>�D�l�)��v�) ��`<D�"
2��~~�dU�@�NQok�r��E/�Z�VR�GT�(�R3�P���}��C� c��_2�)T�X����6t�_��wR"d0�#�~P<��/���\U*��A��qUvXf!$y�������/��5��D�s��d��hF�k�(�����K(�W3E�.���3��[1O��\����[!au��G�L<-�~��(��g8
�0�NYa��!
����#�7�	V��z������}
EY
�
;�j%�E����$�f ��Z��Z-L��� c6j�4md���wE��r�q��(�i��h�l(��Px�k�]�UZ�V���HS/���������9�
UvL�$&�(���>��]���h(*�HV
E���M�u����>PT~X���mTHX��
	�I�����}	V%N���j=�V�9�*+���C��+=��7�������bGAcJ��AQ����t8�����r���@Q��!�`CQmIeS���PT��.
z��s�4$B���%D"G�����	���}	�pX�Ss*#��j�L�J43P%t�
;���QE�W���PT�G�����Q��rx��(.<�5f��I]GQ�VK

Uvx�e�I$����h�2R�Nns8���n�DM8*$D����To1�'��e���a7�H���\Z4��fGA�\����AX���O"��� c����uTJ(�T��5 %�!�6=.+l��N(_3�_f��g^�
'�5���I����@�?�Z�
��J	�&2�j2����
	��E�|U:X�'��:��L�c�C��%����H��?��$��3�0�
�a�w�@O�aB*�@O�Q��b�)���*�V�+����B����!1��SJ���?EO�mmv�Nc�R����S>#9��t%}ZDB��t�d=jIarMD�T	���e�W4z�u���Q�K)����$�Z��.8�L�'�h�^^x%�9	�<����r�HY���C$�������J����7��B�����fF�m�,������f�����+s��R?���\F��'W��Eo��P�(���f/���'���~y\�����
���T?�{�L>6^�:����zV��1VF��[u��d+�Q�O���E�����>NQC�������!��>O�j�
��,���& X�(yZ�������~[���X��$H��Z��o}�h��DT�J�^6��"��Gz����K�0������(��q^h�8�$��!�������d^i���qt&��!����dr����a��H@��!��
Ld���������:<��G��?��lxbc�G��nI�)����e=�t�G1��:�H�q|�����R����U1���������#GI@GI�����TDhJ�w�����<�����R����T��H	zl�Z�>������������^��t������4J�����.��o`���2
��:X�u_-�6�#��W`�mX������aI��9XJj[�����Z�A�q���!��`�6����R����,�:�[
�68�H^2�%����2)l���Gw�[�b�]��N��C���,�7 �?�!���d�y�Y��~l��2��5 D��@�p��p6���c�]��
`�a�4�Z����X��(��\^�����e5LNNA]��,��/#����@�����21a���*��2����`��,u�TV��aV�VdT������h�k1B�V������x������9���D�
�ip��<*o3*%x.���VL�����A>��I+&���mF���4�y�r���`�D��q�$���{:j
��W��r�5S&(���&���(��>��2�+"�xj[���<�����e\�/��,5�*�hN�.����9Y{�4��/��7�M	����v�yR����#}�TVD*iJ�V<�H�T�E���T�E�`-TZa��������viNSr����{�z-��+��b��MD���a�y��]4VX���@�<|Y�9�����fr�
W�����4��F�u�'�P����@35�#RP-c+y��)*e�[<������p�k�m���!M)k���7���.���B�����-B���P����6�~n����Z����-`��[d�8@T�a���^�X�
D���j~u����^���s�j3��0J[p9��`�������{S6vxJ��!
���Z��� ���4,���&$���
�v��r�Q�I�4�����������\f��D���jG�sW���B6�l�j���2�G�)k	$ko8
�6*��z�ui�O�e�#�����^�cHKqT�,�t�7O�Q%���?4U2��6<�QiGT�g%�d�f���e��.����Iu��(/GB�o8���MKD3�&h8
v����G���;�j�ze!a�Q�i.�y��G���:t��;�QZ�	���z������d8*������d8�=��;!?�pe��0�Qe�c��x���� ;��5��S����]�
M)wQ���d��XG"������0qdJ����-��Kx��,���=����
C������20���Z^)�f#0T�a}�C���V�5�vL��*���$�Z�=k<*��4���'�1�
C���:#+�v�5s9����y��v+�������Yw0��
����Ud�Q�b,�=��J+���'P�/��F�OI�(�(�������������Y����EF�2���C�L�Q����Eo~e[��g��$c5�����r���������j��Q)�2(t[ i_���;q ��aMF�a��a��j+�v5��f2�����d-(��aTY���L\�b�� {������O���Q)a������ETK���<�|p+�X���f�0J8R��7�D�T������C��6�(��%�E�[!�3 �Ly�'%Z9��){-@� ���e��lKM��0���R�62�j\��v���J�v�1�:����ftRck������x�S����aK�1�e�bIY�iA$�J���m�����tA/A����l�u������y����H�N�k��a'�7�5��S��//U3�e��V/�g`aV'+/����W^^*�'y^+#�?!�t��~5�t�u���A�0 �k`Af:�8.K%�(.kC��I��^�A��,
����m��e<k�N��������h�x�t���+mgT!����
{�� ��������/(��Y�@E�}���0Qk�#D�
��~��3��=6~q@���N��WAV���b��4�Y1��u���Q_������5����+	 ���J���
���Qj����io�Zd�z�j�_7/���@���������E�<��i��� ���+����I�1])�iY�IXtf�CzvKh�3�}�\��I{�qe���,�'%|��2�>���)���Z��U�e.d�������9�u�L�V� �$X4Xw�
I�!�R�J0q(��`��Q�
���p(gqO��"�+$?	��(
�9���D�R��E�0��D�j?2���E���AP��)th��� ������ ����X���)S�L����d��C�[����7�s��t0I�Q�����K��w�����W��et
BB��@��x�T�[	$ X
+�i*1,�����h+�����Z,X���RY�JR����xr1�y��ka=w����
xp�T�'�;
2�<��*��4 �?�}�i�����A������:0e��zgz%�r"�*u0�<�������F���*QBm\��U�W�RO����ViR"�a�B�v�dK	�	B@��e6��4�d���	�9:���1�G�|!1�U_L�����/�r/")i@��a�$#R�,��u;tJ+v�g��VP��C'��<����X�+-���b��N��4:�4�
@���K��R���f@������5����%��C��03Z��v������os����H��C�D��~��s}U4�9��5�'��j\'kw*q���J8F�5@������o(NiIN@��Zu��V� c-
}(i�^���d9��YR����+B���1�� ��������c1�u�Ri�+��4����������^����u��0c����GhfF�#T����Y�mm�����A��t+;�����Rc�tB��}���������������1sw��Q��Xf�@���g2�*=�#�F��]CQ����� ����h2�]�\��k��Q��hH���d-V`:,�@���j=*�������/��n�e_{�'9�vG����O\
E���3=��q����DD�(����~p�%;�0��PT�q�z��tE��=C,�QT�Q��F����d"��[�������/�e���%��W�(�����E��h��\��C���%����L��j5VC��K^n0i#����
�a��P������.
J`:����3	9����~_eJ5���~j%�6�!����!(M�Tv�4�s���d�j����>e�m�l��I���������
	�tv����-�2j���(y�C$
�#������{�KI���'CP0c3��A�����������C����r��'�@P���i����V	���(���".����
;���DSC�3���}`��b�P�;�J+j�J��MTH�H���EIF�N`/p�kj����PM��1iDW�x?�L��.�2�0U5�m���L )�����@R��Z�x�v{�/����2@� ��Bx<�J	/+&�7�@������I����q�QTZ1��B��G���9���������L�bfJ��Qa���-����cA��'��8y5@T�CB� ��b��4WYI\�A��bgV��P=�3���J,�,�' T���O�
B�>����T���������gQsH4p���}JA��b��G�]d�Jv��p�Ov���Y����'�4�-����=.�w��z���x���q�f=j��E:��)������16=!Hm_	/\�������9J�������aat������l�/�A��C��
���a�`��>�s�
7���@�1~6��A_+�8�A�:	�1�������jU��'f|G���b��W{W9c
z���4
���R'���w��bq68q�4���2Ja��
��D�%�?��r8
�P����Q��9�G-�OY	��R�LlYq&@[����A�zY��@h�#6�jR�g���R<���{��dw|��&�`5�����`�r�<��������"m�F�>D��G�N���):�����Ig4���<���\n����u&�c_�����2;0�����4���:0����0T������?~M�0��)���}��jU����j���dl�V�J���Z[�����l����e��a��/�j�2,I$F������e��Cw��2�$
�B�����kOl�G���Y!�������7 �����4`����;�`Jt��6n�l�����D�cW�y@P��?c�X����^��������0����#���^���c����u&hxD�;t�~�fH
������
J+��XY��kl?�E����R:2c�bNr��6���B:����]���c�dbdcMO�1������*�ZP0}|e�j!�QK�R�4
X[a����W�bGZ���d��%k1@��z���1��6W���/���`�#%��13�Ce"A'ZV
���"�<��-����"�R�P�9y
����e�>�<�3�!,���(W����
2���fg��L�N�~�5�\'�n��"H�I8IF���z8r��<�z���r�z�'��dd�l�m�A����86��koTt���:���A����tj+V,�h��t����v��9���X	��Z.�o����Sd������AO!��P�M����S���)u0r�>�<��}8��%���lL�JB%b�({*�e�P���?5-~�"P-�f��p(���-�L��N-�r �6����!��d��
>��m�d~�w������6}
�	IP��SH���HD��	:������0g�P>+������"����y����O���h>��/�|&��9�}	%�����O����2����`	�PC��)��,�*�>�v�M+g��6�
�+�������`wGL�q�Ld�H�O15�j�%	|j5^K
�>3=��L)��)I��X�?����[u�qE[�B@����K�~
t�\w9��q��>��[�&���AX��y�������%�]F�d���U?H�%Fl(����=���$��*Q�e5K�h
�L��z���ZT�1qk���������T�>.�\������1�QA�d���F*dx=�� _����tN^;/Au��n��sFM�`UYR�3�
���3���X%{�iI��ZF}��<^/�Il�{m�*Jx�r�^���#T�/�M�~��y�K@����d�RPd�z}t�����0�?�f{��r��$�Q^�S�k�����a*h���/T��J�SHC�Tm�iv$�T\��[}��dXqmJs��L����c6��(ce�����(�%��Z�y���S���I%�c����J��;���eE�&1��ZF�h���V���S���*-����SS:G,0U8�?�~�vU�"�5�^�TQFU����)e�m/�����&el����*�RirX��������U�}��Sj�J2^����Qb�S
�
-,W��X�%�=��U�d�f��4�����5Y���#m�E1t�5VZ�/��
`K��?�
K6�P���+������e�I>]����F1�V����+^+�`�����%i���U9W�/�|��2���p.�3:�k]�a5� "��d�%��V��g��s�P���
XY�OF
X��r_�$gc�^{]�� ��1����n�7W�S��[)a�J���A�_���6�!-���2�5h����V�P����J��xB���H��f<��:,���m�:T��;��
:�e�b�Wv���S5�wf	��*��w�[	�Vv�o-��(��N�x����_K��?a����*��X�jeLD�M���6{�Y�)��Pi����@�w��Q3:�a�4�2�*�4��e�����odK9n�m2��}"��<�lb���9���f������9ec���c*K�1�������7���������;�OI��8�@��l�=����p����aQ��������i/�E5�j�$,;,
�'+������}�0X��w� ����7��4$,�[8��]��*l��H�`[���=h@�5B�����Dy��0��j)�X����K+�R����U#��W���.�QJ��W�L��J	��_��c_�W���7Hm�Q2�E��
�����db����!�A0�l����o�l���
���4��K���<�Wi���rn^��������$�\���h�e���p�VLaAF����[*�
��EW��R���%TxTj	s�;��"#	d���4����l���eX��Rj=j�\�)��P�!%�R3�3�����Sk�
j�����2��
�!VG������P�9Z��s�����p�dJV,��oxIV$���`EJ�W�K+�be�IV������xb��SH�+]
1�{�Fqbf+�m��l�8��HF�`�>�P�1S�d�;�1S�����/��k�6���2J���a����
�R��D_ID��~}�N4e�M��K&�QAr�:I�W�H�B'��bq`��j�����S
��>�V�N�Zj
T�p���{�;b�fW��?���R�}���*� ��������y`�2���)d**��
� ���������	i:<�H��o������#2:�����{�4��
�+X��d�"Z��9V*lw����;7%�Kh��O5�R�(���E�d�c�e�>�`����LR��j
T�F*����"����XB�!k�����HmH��I)q��U�l�)F�S d_�j�}�o����V�V,I�������m%�3�v5��V$m-N*+,��r0�Zp�eCJ�QuO@����eY�5!!����3�R����Zj���Y�5e����b�������r��k�
K���?��%+�8�
6�:�*��n*-�%T'Y5��z�2�v����{�L��g��z��Y�,7��	8iQ�oCNM�N��d�S@O���t3���]$"`0�#�J���)$,V^��7��B�V/�|��S��'sH���,B������~�kR&j��W##���,hF��JkY�� 1"��9�j�,lc�
����sb
B��/����X�P�8Vn"�*gbI\; T��n$�����9E��`E�P}8
�n����A@(�`
"�P1��Z�Y�D�e��%q�IP��jy��X�b���Y[Rz��,�%���2t�/���;iCN� F^kU��y]��Qb[\��p�o�j[�>+{](Xb��<;�,���4^�<���u��&YBL`�4��� {9��/���2��B����RGnM��&��h�_��Z�!C)��/a�xLu6V��H^�d�����O�sn���1�z�+%��j;��q�`�=+��K����"��@T-c+x>D�"���_h��)���%��BY�{p�T��Z�wt����d��������`K���$F���c����lr����������'8hpT��(�	":��%N�&#���hI�|���-��P�i�
���]'�VTC�$�&P��USCt�g�*Yb�Y����d6���;���G�����k��n�f�*d��w�QU������QU�����GUi�l�i�W��=T���*���s������M�p�vTSJ�"����)�����)O{	�7DGU��p�C�;P���3��R����W6�Z���r_~�kx������-����5Vcy�!U�F������y�o-������je���=i�m���������h8u�
I�kr��Y0��Az���% ��ZJ�K4��(N43�����T�j��j�WB����r�u�������!�\�c�
l�2(��VL���Z{���8
��<�f�
�		l&���QFy���6�����<������Z�\�QS$���rl�2�
U��6k�ea��)���9]
!�������Y��?�jdx0����-��@�xfm;�	V�4Zt�i�5���H�+R������uM������"r
!�����k�@�`t�E����}
^���"d��K��wYGH�!�Q���$2�0�,�����;0R����S~n`$�H����,������b�����9/�X�
�����S�[�coJ�����?@�-kM��r�.��C��d�����~!.�J�=�c��`�w�c�m��Nv�6�JJ�'.PR��{lZ
�6`���$���;N&�@�Iv��6cDZ;*$<-�F���/���6xn�����������O���h	|q��3��xX	�$����R�g^`�w����2�z"�0�z��"���FIZ�h�^�R��2��@/j&�Q;)�Kzf��� �d[�!��F������II�H�����Tj�>P������e��z�����M�.��r
V,H��`S�P@�X�6�O�B�gS^",�L<j8�<p���]	A���I
��Z��+%T�a�~�g��9���+Y{H�vN��:�:p
���u].��})
�J�o�B-�.��{��<�r"�����?
.��Z�S_\J�bRp.��NG���d�^����#��,��.o����N^1�� F�j�9\�%��~���:���w�p)%x�yz�+vf�w��V���2��f@���`3�\�ZL��p	k�2���e�Qw�a$t�w[��:`J+V��J0�	�F���[f�]�l�f�9`�J����)m���i��~!�	�<QF)I��H�V����YR�P�����M�k�n�ZF}u���O����PO����0|"�d��cy�����S)6�����~�=�tvy����)4�'b�m
��&$�J7�&�����Me�]t%bj*����r��>h�
��� �+��/�Z@ �X���vS�"�A���W���B�n��f�#m�-D6n_���m�dW�.��������~��+L��Di?����F\I�B�>��J�Eyp�����R�a�U���05��e���O?74�-j�����e_�)�8��'3*F�~y�.��K��bdwdi����-
$���X�^��w��K�l{�[Q�d��g�|�DE��z+�0@��x���$V@Bp@���n�@{X)�pj�,�G��,���VXA��K1��V��x���Lm��]b�u�LPd��{�&��������)�X�1�C���P���� 6AF-���3�\�Bm%��Q�����I���?i�����}��C�N��r����	B�
?���d�Jt}���C&�hd�6����A�����a���P!�+@X��C��c�$?M#o�����������������Hg�ZPX�W�(���>0����(�A��^	
v|���������~J0G��`�JPp+��K�TiaYE�
��������r�K;X����?��R�Qz3C��e�
��wP���jv�F���y�1���\�l)�	MAH�u�"���z���-3�y���r�z"D��@�k_t}n@�~�e�`�@�������
H�5��=�`�1�H �vX����S������6c�N�@��������T���2�*;��
��};����H����ZR�{rl@*�� G����0
H�z'4t� �v$d�
H���C�D����";@�'<���l�D���N�XJ�L�4��c�6�Y��4�M�e��}/��y�f�(+\��J���R��N��N-��8T&��:�B�u�PA�M	�����G$Y��p�*(�-�����s����(2X����W�	O;���J� 
X��d0��S�e0r	x
�P�,�HH���(��sy�vn�rQ1�+�N���j�<1!��%I����N� V`K�Q,���$����kd��Y#�"3�0.���'V ��q����A�/b 3��+��/�ZF�YR�������sq�AF}+����f��w��h�\s��(������Ic�*��-��Sy �
�S/�x�r���Z'T�$U/�dq��������N�@k@�h!�	)��h�<�
m��PAY�,j)B�5x%����J�� �T�F(��L�^�sSp���w�	�Tp�vCI�@_J��_�&��	�$kyyK����R�IiU����u�����</R#PR���k����Z�^6����8_�1-�������9?.����ad���AuA�#���#��E
&��#�y��
E0����!��:P����Q���@)4�������ET�uX�?G@���Z�d��:��I;�RHxZ&R��*}i�<	l��,�R�#�U.�
FW��!%6���������v��i�9hR�p)���K��r�[-�d�K��3�@7n4e/�*Mq��2JyZ.A��umK�dK�R�$D c��o]m�y��k�6$�T#� :�tQ�V��������9�$�ac>�M95z�W��+��l����9`S[��
��)�T:4�d���������/����?5�T����8�Gf���}j��k��fq�"U����m��������q���P�����Hy����t��Z�-��s�CJ�.4;
���(1�<�H��~:|��S�Q�z�l���l��dN'�R2��h�|����9Gb���~@�MgWBm:����J��BIiPV[���pj+�����g���4��V�cdD�������b�M7���4�TV��t��:xc������1+{@'��B��<#6���$&��N��k~�NaC2�
:��?�3
���RE���%HKo���Fi-�'�&���
o�E����E-����B'�X�N�N��Z �=��{��h�\�?2���q@���e���`��)$Xe?��8t*+j�+��9t���xr:tj+��#o���
+����NeEJ�	Vl|���jo��p�b����N�a��U�N�.H�N�^�#KW�0U=�Tt����
CO�Qe���st�����B�Od�s�TZ��6�������>����(����QR0��-�R���I ��(�@�:�Y[t�-��-A���K��h�w�?2�l�������%i�Y>�6O��Oe���g4�VD�h��Vp}y�OiE�w	�.���);�|j+v��>�Z��x�]��S���Ni���"�k��.����������Om?e4�TVx�O�u��V����T���X
� ������b.�Xt�����Q�����\���N0�xjC�u��_<�K�M��(�����I���a_��:|N����Bw�ou�Gp%�KE�J����=�"�j���s�TF�Q[�Fn�/n�������4KHa�x��J��0e�W6���#�\�8�BTyS��Oq���\sp�d#�P��C���}�����e-uS�m���xm�6�'R�	nj#8�)��K�xy���&�����n�L�CM�H�+�7��)����F�p�O�!�&2C!���K�P
�`��+������J!Wc��Y�}CL�����
�]2��A�ED
3�FE���
4�,�������r�������*7�3<�8��S�Qy���'�S�1[��:�rX�4��u��/�l����0������x�A�>�#�^����y�a����I���������y���\P���PT��5!Tdc,E�������D���K�Ea.
����R�#���Q�e��5�]0�~,dKyH������K#�k��h��i����t��dl������ ������r�\R�S>��hJv.5r���G�>t��:7�]��Z.�w4R����t��n�B�
k���u������~�g=_Y����\��y�G,��c�Y���zY�r�,"���e���y�����t�n8k��e�]��}M+������5B���^:k���L�E����vg_����~��<k�l�:_�-�B!�x�,zMf��@���'�a
/��E�(�{�*�!A6�<a_�vH�2V�K�vy��59�!A�Q�O���	��SiS��<�����_{��-�=1.�����F����`�~b�{��T4k��v������J
�=�5=�`��\sV�C���o����v��9����Hs�w�����������a[����6\,
�x��W�c��m����������6y�P��3������K��^���Jn�	�$�b�N2���|������
��9���B�Y��z�*Ok<�e�q�����^w�%��l����g��z���H����������QOkN\��zZs���POk�@=�sy�
����PTC=��x���pU���
!�@=9��z��:)�QO�6��������QO�&�G=�bSm�^�@F-���Z
���������j\���p0�(�'��:�<�u,)+ e[��,�E��<�"���s��������Ks.��G�g]�x'F��\x'�����;�9vy1�#�ux��4�tc�;�\�����4w�#�5b9���)����gkx�5��Q�;
ml���'`���TG�x��R�h���w���	� ������]BY�T�dw<-��PsL<��F�\��,"�Q�tn[��*-4]Q�2����V���K�
�%��������}F��EO��������G��.�'�fb�=�9\0����d��#����V
�������
:����9��5�f�^����=9�����Go�74@O�9������O��Y��>@f-}�S��$�.�{$c)�q�E�^�������'�P�#���a��Qaw u�
Y+�o�yZ��u<�r~����X���B����hC��K!e*��D���2d�l���m��R�D����uSp�v��:x����]��3�����j�������}��2���Hu�4���@M�c�������
u5�c`������z�u����0Z�����n����f����o;�F�j������'����d���G�)%A}#���$_�P�� LhIZ���A��\!i5@P��U����9G-p��l��v�n=N
�Uwc��Z����W=]��K��I�������U����������i�9��B��}+��?�8��XjT��>z8��@�9�P��2=�����*��K����w,���R ��
�]�����K�:��n%z<���=$Y:,�_/����(�.����DT���,D*��d|9O��ZF
������B1���@E�c+Uh���2���$�y���m����;��b�W���n}�ce��P=I�h���O�����U����@ERn���J}&aj��S�1P����<%,���J��j4T����@E�����$1�$V���V@8.�� ���E����'����%��Z(9Q��@��y��'����e�.Y[a/[l�Z��5qH��`�ZF��6p�z>kd�sp�z��3�[8�-��%}-�������m�u�?4x�u���c��w�O��?|��k@i�U��������)7�C�P�.|Y#�������qr�C������F-��C�m�J�'�X���l�H���pQ}t/�e����=�LQCE1���2PT�3�C`"�:��9$*����U78"�����g���������h	5�c����jc�<sFka����-�eaK�u,CJ�nN���7H
g���e��8�����?�eMku*�3����+�[��RH(��H:��m�8���^�
u�16`�o���.*�����^�6�
�h��Q���
����|����
 �
;| $�������wL�l���/���L���o	�mCI����WG���}7����4�QS�J�Q�T���3�;TJ��C��
+�[���z�����GU��W!��d�K���9�QU����#�����e���'6���~����`�����O����'��S&L��`J+j�T�;`
+�auN	��{���VP���L\��5�:m�j����Y�`�uMe�l5�:�Z��h-^��Q�i	[�������zM:S����������S}L�Z�Lf
���N[1Y�����P��WY�$4�+���v���B��������\@�Vc+tmB�oj=
������4t4�Y�
��H���-)N�R�������0����.G�,+[�ZD��/�@��� *$��)�g�����u�v��P0��(�e��q;�=��]/�c%;,
��H�G�,��i��i�vYo3���2J�SR$P���c�R!�e-��1�T�%��P�R����!P�P*%L��"�T��j�����A�����2(U>���t(EOL�(%���O�R���T�E�t8�j���~�����FJ�J2���6��l�V2�4��c/`$f�����;_�� ��G{
�8���Q���
N�2��$I�	8%Kvl.�,�d�5�JY����6%UZm\��#`Hy���m �6d�4�@T�$�w!jeR'K&{v�z�*K^V5�u����������P����0�?O��u�c��P��GS�<L��"mI:p��aj_�V
9��2�rV���j�,����*�&�j%��z�_�j=�
I�@�d�=c��yTm�lS����-��������;��l���GW�\#eIU��I.�X�*�X�KM�������t�R���>os�������i�T�d��bT\��+^P�!L���\��,inUT�$�5@���UT��W\�4�����%y�@�{��T%�(��U���i�Ti�R�b�%�xy�GZ/��h�����}*��2�������s�Q��H�-��%t���������)���sm�]D��t[�������g�.����8���?�U�Y
O���n���:�ve% "r�)Xb������T���szA��d)���Z��H��F_,b���
Y���|u<��L�t����������&��<���r-�����e��@����^�Kr ��PB���[}��c�������1���*�pL�x\RY��C�4$1���3u�p\�"�1g'r���r���q'��E���Q[S�����
S���r�dwTX���uiT��Y��������N���������-��X���������I���dC��Y�,����6�==��N4��l�`����������2�!f�,{4�y�yK0�h��aF��3���K��)�h=��0����F�a�N�e�������	����d������VB�}65_7gSj@��r���u:-�m5ry�N&��Y<1��������������
��h����h�����P���G���g{J.�{�nx
�#�s��9���[t�i�=��I���Pz�s���{�b)�����{z�~�n�Gv��{����z���d�<S4�J,|����<dR�a��(�A������B-a�=t��C�����L50�=����I=����jC������;�B�8�?.i]�`O���W{���9����� `Ok>�.[�8�i��s)`Ok���
�h��v�0rk�����������$?��d�+����=9C�{?��{�����G���^O�{c�,���%|i�+�L5��j���A�(/!i
L�ZJ*@F����i}�S>��*�� _=��t��V"�d�s��t@��_n�����_��+ �;8k���'(���`b>0��j�#����e�Or����6;�i�����f[��C��"�V[GA��/k���9=������c�!�`b"t�#��i-�q?���8=a����_g#(���{��*�z�pb#��B� a���XK?C��n��E�t3($uiG�+������6������#sIn�f�Y��8�m����� =��HL�h��miv�}~������=�������'5���5���8�9d����9���hBG9�9p���Y��I�9�<��%~{��b�t��)����C�W��v4�i����U'��[�]_'� v����X�t���;x@@w~�	�\Y��!h�\�R�#K��u����a����'m1z]��w}�Y���;9�j���U�<4}�p��?�$�|���Z�V��u�,"}0q����������;��������\&^�yO����:
����}���1�a���qm��|+s���F<���-"�o{��B2�P�^��S�S�g�������j���)�w�2�)j3�h:��)�?����f�@���T>����v���R��)j��A��,�����WrrW��	���A�u������.�����V �>�G���t�te���Z����p���se��d���*�[��U��&��x+�����*}�A���'�r4`���4����-AF�]���F���g��ZD�[L��d�Z�4�E�(�dz5`D5����Uh�����\"�90^Y�@�,56�:`��� u�#���F���J��>
��'�YF���hy�S�s�}�>�������;�`$��[������F5~Gh
�s1�I!t���Q��z\4��=����:0������|�J������R�$��n�����Z���<��F=[����O-��e�l���X+u|^���l�HP�lL������7�t��	�
�X���Y�+6���G�>�6���[�~34lT�'w`���K�c#N��6�p��:6��K������F ��r�����}���������������{1�96��G�)����b�+��6����������Q��?�m�D��k��*��$���O5dK�R�R��������B ��QB��%��d�V�@>������-
��-[-�L�q�I�2���;���Q����__
���R���<��/��
����,X0��$X��5�j�6�+K���"��o)���2���R��D�� I�ul��$9���j ���T�
:H�g�+	@���D�cV�I����B���{X��|\ �
�f*��-j�\�f
"���9�3[9��]���Q��(Q4pR�Q(j���p�l�G�'��a�{e=��k�U�<Y+:���8)<��<�|����8i}����
�u��
�����E����M�`u^�k�%�qR�J�
sv�7�7X�9�M�Y  )7�G�p�w~7X�������o�hZ���*����Q�)��
�4��&5�,M&�Km�%�fL�`���Rjp3�0��`�E��J�^��S&�JQ�s���}�����G�4��T��p�%Q�������%f�wa�H4��IF��k��&��e�����`����NHM����}
������!���x��XB��]��o�#�6�oR��j�P��)M�8!�	���$:Bj�k����b�=R��s��#�2a����Ax���YGH�A}���LGH%�i'%yr�T&���:�/`�;5T?8B*���\)��'�Q�/GHa �p����v��EDl��F����Qj�W��H�!(��|2��3ewI������1u�l�.W����R�"=�3��_�J����T�u��G"0�8T
�Y$��y8�J�,���]?LX����4n+ox���h��+ikeh�l�L�@�f�����<��W�KiDB�x����������6��?Oc^J�K%��4��������`J��/�'��}*��p��"�w����y����2�%��("o���Z���_���ZD>�H�%�����GJ4db.��A-&�
5��o}��!��������}%i|��W���������R	("�]��%��%���R�P�����\����@-���r��wK��B^�-�
K��mh���k9p�oJx�
-�7�,��.�,��
�~��R��g�PY	��rw5�of�WGK�A��IU)O0���>

<e�5���"�Y�)�)I�
S��QJ���E�Z��:V���YN�}AC�� ����(iIz�����:Y*���$@���o�~�y��R����������.S��U�?��"�w���7��;D����S]k�U���>����:���Q���8�"�r��)�.1hT�g���c�(�g�������o���#cW�����|���?�����b���3X��v	�;��_noD3hW�it��g���?N��(`�sr��2���7��q8T:8���Ft4	��_b�]������$�t(�s
��Xj��	n��Y�?�:�XJ�����R���`f=����������������Zk�/C�F���_������L����Cj������lg��h��}�����=��m��
�@��:j�:C�H��A�3b����/���@�g���5��Iv�D��P�8�������%L�Z23����xG��LX�r*{�����%�D���������������R����Y�h�����kz0$�:���d���y�(T[����C����f�a
���'�5������CK���e�U������5���L�9��C�LaM�����[�=2�
�_Xx��[R���e{e�b��%�W�Eu`�S��d�S��������l��N)�R:e
x�O��f���O%�[�(����d�
h�N�������Q��6�6d{��_�$mz0$�8�i��Y6��'����������+�
&L_4�h�3�p�9�������M�
��m0��mz����y�]���M+?�S�&H"*Qv�&(6R��!�C���%��M�Q:T��C�^O��M�!5sw�2�������r}��	��Jho*��[7���/C���
��)�nZm8�9���5p#������
�5n��@�f�F��Q��
g[^��������
S�~71�9��'L��Tp#��{�����
m�{��d��3l�n(�}e��R7�m�>�!�M7����iO-��P���������pp��(E���@�Z^����
���}��f��\��7�L���@L�p��NJ)��_m7=�n���@���������h��C�����7�%Am�	p�uN��G6;�������[0�����I��/C
���Lqn}��ytH]�o�u��_����(�irsC%ju\
nRD-���n<�<�������f��d�_�2p�Z��/��8�����;KC���?����.�Gkn�~put?�T*�I�o����JQq���o���_��
&�Q��C�{C8�4��dG�����4Q<ko(~{e�7�8�8�
���� �`����a��{XT����@g'p��6���uuO`�uR�,�Q��&A���e�n,�2m$"��.�^�H�z	M�IPD!EK�����pp�r�#��&[���m�<��6s2���m�1�?�e�d:����J�'G9�9ej:���y�
�pJw������s�:fMV�QT�<�����H�T��~��`U�D�:P��*�����T(��;�@%<!:��7�ul������RT���,�A)��`����;��������DX�/�E+��5~�xR�77J�DA�J����CCJ�^��D���@����E���?E��}���_`�K�j�EY#��h����C�<�w�r�m�]W�8�I�7�uC=TnX�z������Nd;�zR�:����bh����{�z4�D5j���2M4���VN�oy�S[�����<d���]��9��__1�o{b�=�c�������Lp	���Z��E4Q���
*�
�����A/��~(�&���C?���fI�i�~0[yw����~ b-!fh���w��k�Bc�S��)��x��K��W����@?�{�,N��_wz*yqr��[D7��D���;���7����M<$xo	T^����;W�9*�7,@	$�!��P}k����3#
w���J�����
���~`��=��Qzw����vuQ��xY�Ux/����D��J:�����,�����YE:�h�d64�?2d/��Y*�z�l?����Jzl:9����8�������@�i�)nh�,Jwkz�vX�'�B��7�8Y�����������o�~B���H��EO;��������\&o!?�9)_p������Ygi���Y;^5o3Y�����hQO5o1�������7�j���=.w�S�N�7���_
�F��BK�EYQ�_0�q�@;�a��KvR�\�J_{�����~��)}n
����b]����;��N�����L�����i����.��RO`���j\d`@VE^P��)
���s�V�����v^���J��]�}�AL��dd�@Jm�'=h�\@���Gj�3.2e���A*�� ~���e\d��|�p220�3��(5�X����C1���2zh�@1��y3�L�D����eQP�D�C�R�EQ���k OEe�L�DT�x�����s��d����?�;�x
endstream
endobj

3 0 obj
55741
endobj

5 0 obj
<</Length 6 0 R/Filter/FlateDecode>>
stream
x���A��@��	��W����-���;�����U��f��`v��@a���M�����4��v>�n�K�"2H�ft�<�.�������3������~������<���:����?����������T��?��|�������/��j���}�s�.������������?��:�������t�����}������>-��o��������?�m��i��{����v�������R������^��o�)��?����������K��N�������3����+1�/�}��b<��4���e/�X�����_��DseS&.����[_��__�����]�L��c����\�������uY.�i�s�n��m�s�^���z��������?��-����������^o��?Jz�<��y����c�|�m�m��n�e��l�����v���?����e��d�m��{�����L�m�����OuM������L���>�����*��m��N�E�c���.����;u�n�u��.����������m������_�;��?y/��Sou��ZE���,��m[<���C�]/�6�C�?"P��&��c������m=F�Vu����x�!������s�#���U���*���;����1i������8D�4�V
���m����6���Cj�b-��
��<��~�����Y7.I�!~�7�T����}��se����m��C�������V��Z~����+<r�]������<R���e7]�����;�)���r�w����v|U��jJ�29�w�s�����H�k��x�5�Pz4���0T�����?j=By!xtX�$������`�K7Z����z�����������RU?<>��m$��`?���M�rx�����8�����f�t%�L����������j��#S�����j �c�vY���~��o�0��}�����`B~������%��k$BMk���������P����C�IS�������f��Eg�o?�]A�|Z>-���!�`�>?���-���e�����'U�#?Y����l������*"Q�j�%���|����������~�E|�������"L��<zH=���`���3DnG�0��Y�}����������A�T]�/���O�H��|D��O��R�$�i?�q��#�{��S����>C>�<��+	�o+�V%�L�8�|?�D�A�~�(=��[��S}����/�o��8t�:��}D�8l8P��~O=}��v���wB�:���_u���u�����9]�u:�d����������C����3���eZ���Ux�)U�^�2���C���Y��O���U�~�y��S���O�����=�}�h �����u0�:r�pN���!���cU�cH6D���gV��;1"��?_?�������?����;������_R�!A�8$Y��C�IU�Y�����Y�H�N����5��G�����Sm�J}���{?��,>�)��fx���X����N�<�������o���(4\�v>�p�Ai��p���`q�zx]E4JU��+��W��xw�^��|�eE�����$������Ru������x���@�V�>��t��-�;�i4������P��}B��������yk���|�p�H�H9�����M��&M��:�������(�����^Km����R����3!�$���i�&};�L���C�%�M�6�-�~�J�$����.����o�"�@��/�#S��~O����6e��0�Qk�>�/�+�BFD�S�w�N����",x%������5���"�F���GZ����BUr����u�K��te�f���V���[R�x�m�)��e��:YRBa��~>&4�n��*������-��?8|���G��To��}��t>�h?a�_���H>��/��t���]�I������K��-W��T���=�*N>D��c�}��W'?����
��Ep��|u?�����Z���	7J����yr:��(�����;$��;BL��}}��&#��������J>�������u�j���E�_oP�:��3d)��Q7�/�Y���B����������������J/����Rf�@\�����WD�t����a?��Um����#��9��=�����
�v�����z��~E��
U��P��GE�IS�����qX8���<�T��Z��W�g�~=~;F���)-����(�����������������XU�.�<�P�������S�����e�Vu�T<������g��gu�������=���c��!�gv���$�����L-���{7��].:"P�����?i�h����Tu��|:�b�X"��W� �3����-���C-����gaV?r�������������M�N4��#���;%?]�����{����iU��;��Qt�a��#�g�~�8��MU
+��nlR�h;M��r����V[r<{/��9���yFS"uB����"�c[��4d��b�4�v�'����k�"����%z�i�%o�����~/�Pj:���dk�B����!������oD��o�t0w|JUv�1(MY>M9�������4tl!(�0��"�����A�����������j0�����<�L�y�q�f=FOvI�`���!hZ>��pn^������d
2i:�/;�ICEP5��!i�t�@��>mPu�t(����*��M��E��0�o�&U��'#��&�J<~�E�IU�!���1�~���������]�-W�+�'�G����������P5kW�U�Y)��oBQ�.a�X��_��R��)�����A�����XUc���R������O��@m�������(����S�3s�����r�����������/��-�QF
&�"���&������!����@���IF^\J�_\������T"�@�������?g�eTC���CZ�!�j����M;������!#��U���C����U�GP#t�e���Q�2�P�op�<B��������H
F�d�AUc��P�O����JUV�Q���������NG�o���7I�`&3�R�����*�^��/����Mr�����\-*�����>�[���J�j��+��������N��T/�.��Qg����kQ������,���������������W<*�������>� N�}���w�d�����v��$�we��Q���-h��F��|�6��V��-�@����V�q%������Z��!�@U�����P�1N�>cT�W�%�����T���|^�-�����W�������/R�h��@#y]]�a������A�[�"����e�r3\���<�?��[�������L9�m}+z������>��o�w����x@��~���D�F�y��2�N��S�����?��B�}�������Zt���]�����Vn��*�%T
r��<��#��+�D�Y �T$�[�ZPI�O�>%+���#��>(<��w;��}I?���y6v6
�<��)g);�����o���;���F>pNt�<A�I�1�����[IW�B��8�"��]A� ���#���v��D����`�i��Tu8�����TRDJcZXIU�OD�VKw�����V}~1PQ��T�����GhD���R���1���Cy��x*���(�j?��/�.��,��gD�Uc��Z�p�k������D,JU���=*hU�S�[v."T;8VC�TjZ>W�Xd�% ��_�-@������-@���@�~(��#�� �<B�w���e�=B����bZ��G�xV8��{����Z��K1pp�s5"<{W�yE�*U?kX�w���?��8�C��Rt�l�9 ��w�!��G�z�z�r��>�8�n����4�Z�0A�������[�G��=_����e��K����a���+���W�-�� "����zR�p}}�Tu�P���?p�l����-������~��n��{I������o������V5:d��Nk:uZ�����F8x����mn������]�B��BGX
�C	#,���<H��Tu��N�:������5�b��$���yJ;�t��9� ���8���~q�������Z��O>��tA�V�|���c��Ug�����H�o��cQ���O��W.��Q��R�o��5���f_B�GJuk������?�
������te0��"�,�\^-|@������CP]�����:�/��-��u�F�yb�8j��KFj�HV����d����y0���!xhSr�=vy�q�XL�*PBib��G���-��������s/^�4��E����._'����]>l��W��Z��)��E����R����vOul7>ViGlIU�>�8C�!%--h�%U��Jb�������0�����������6<�P����4��?��
�F'yD��W����M �N6r���[�:�	�+#����=�����tO[B���l������'�N��-�>���1'-����/��@8�mNM������P����w�������u�����F�] ��: 0��?? Bk:[��5QmY?��wc��Z�)Egm�����}��k��A����&��c������>��O)��G+����8��S���vL�{�����?6k�����a�`�BD�����?�1���<�F����F��"�R�#��3G��Z|i��~�kU��U�����U4��_zUqL��v�����F��'v���&���)��S�_N���W��@y;<�CJkN�{H���*�����8�BXp�������N'�m[����f��-u��?��1��|��<�i#��+g�����h�E{��-���o�jPu��k{������Q/^XB�}��"8��wsZ���K9��GRL?�$��p��]��x7���;n��s�����GF��^kJ�|��:�D��W]?��U�n[#�5t8F��~|e�n����*����F��iT6?�$���?�F|��p3A%��Vg&��ZPIUg�+�Wk�5�UZ����x��U���"���y���������J�~Y{��W������)K??����lf����|�dN�~E|����_����o�~^������$yy�"
�/�#�v#!���$4��������:�����-�hO4T�)i������<��ws��;�.?�5��K���\��}_IM�TLg����A��;��u��4<���
��@q����]���H�Q>����GX	�o�-����S�U��������F�[p�WP�������nH���j�?�����!���y[��?1�2L�?����Q-��)�E�`����V���=����W��%�����"�����HU��<���#�����vEO$����!�K-�dHjyL�����Rd����S���S!���7r�������<�|H�G���D�����9�_�*��com��4�vx����~��x�x�s>�[��V
�V_�m!W��Q�N2\IU�o/m�� ��Z�pG��:�[��`7W��{H�~>��u��TS�'�7�L(U��g�#����K�G�����jSh�p�X���N������v���n�x��]�MDJUg{����F&0e�a3"P�:�6��R������F�����)�FK�=,�wk����{XjU���J�ha$�CT{(jO���'�������;���H^�����Gm�X�~��� f"����_�-�������2�w����#BN:r��<�\���d��)B�DLF�i�~��u���+`����8�=�����{Q�����M�+80��^Q���b����@� O�����H���4eS�#��X������89 ��/~�E7�Jr���6�;�
���F��b9����b-����J�c�:�!&]:�l>=�-���h7y������X��y��5�i��qN�8��4��(�CIn����W�	Z��'b�!��''�WhN2T��
.<t�]����>[>4AzD�Vu�����	�:m
Q��v����G z�[F"���ell�����3a7������R7�D�IC�����:��,�<cG�IM��-����)cPu�?�� Z$�HF1���E�`m�$�:�%�����>�j�;2T}��3��!�Z���@S@F|jM�g���n�G�Z��y�v�J�j�Q	p��U������?�R��C����<�B"��������;�
T����h��n����V�HE�������G\JUg'|p@}o��#P�H�)X+����-�����R-������~�����~R��y�;��n���:[`���7r�6y���}q���N{�iM��(Z��a��Oknf�����F#���Y@����~���U�>����`��`?����D��1uPU�Mn�����<	�r�_K��9�cR��!Z�*������������xC�%5���M��7\�M������C��f?Y�I�N�H����X��vZ��!��6��
�����i�<8����(��Q�������"� �����]o�6�����}��~��J�(%|D�R48����T4�Vq�4�����:&a��o4����D��t��K�3x���XTb�?=�P�������rh�|{��tD�V5�
��U�]3tZ�0���Vu��N�:�Z��J�wP�����^��T�]BD\JS�O@�K��K�j8�q)Up���=�/�4�J�t�a�ZXj�k�"*�{���:�Fi?"*�mEE]��R����#*�)��R��"�����B�Vu>,���h
�P����������~?0F��������NC�V���&h�����������M}9�����t�� !�U
�����PH;��{�E'����k�Y�cM��v��I���!M��lR����a��x���n�>�Z�i�>+Z�	M�k�cm~� ���l����q����NG�VuvA���a�J��tTjU�������8�#-F���w� ������vD%�C;Z���?����}mp��(5��b�i�|�}����X�{�7�Z�0�A ���@kQ�nFR�7�(�u$Y��5!��TN=��7���4�
�"n�1���O�������/��c���<:=\�#MI����:�:m�����]��Z��N�(AG^����=����o����x��A^������������{w �U
1�Oj����4�������R�zZ��Q�
S�E�5]������h��E�R�}�3���cC{D���X����N��4�bL�������<��P�a���kU����~UD�iU�cO�:�E���q!?����
���+�[��!�I'[����w�Z�h�&�Q��8�q�`
�
��R��r�`��o�z�eM���=�
���:0�S�X�,���:y��������B��L��Vu8�0�K���!�U�p�j�Z�`�-�Rj:���Pj:�i��$���c�wo��jI��J< ���c��L9�h�$A�BPu�B4���%��������������8��?������Y��Z;yB�'�c|�K"(��,1A)M9�RU�t���	���f���u0Yu21��X��,��������U'�������R�r�xT�-�U�l������2��B	FyX�����}�.g_�J��Q����(�F�IU��[:Ru�r4
�D�IU���G��E�i��n![���9����'�o��H�k�|W��t�����c|�H��N�x��X���!������k��C��p*�������6���_^l�.y��������v1�m.��o��N�:9�4���G���C���w���c�z����t�64}
�����q���Y6�K��zZ���KD�V��a��)5�+����R�Y�M�U�-<�������W~O�}��g����/c�W��������o?��9Dj�QC�mT��%����G���e����Hm��J-��Q����U��
��#���'2ep�zC0��|�76�)��P�:�>D��8���S����>�}{����m�������������r�V@Q���V5�����U�q�p��H��9�.���?m�h�)"��������+"o���
������Ki��?�1��C���5�-�����G]��-������-���>����P�����dX��������="��?��{�F����o|ZB�H�~�p,�k�%5�x���4��:����r��AR�r��1��r��7��aId�?�x���@�%������6tPu�]�:�~��g���R��3�j���
�*/�Z�w��%;x����~&����]����:p�GtIU��E-��'�/j�%M9����g�Fx�W�������������T�lf�������
9�k��gz��O��|�`�Yf
��d'zE�[������P���
�)�#��)�=|<MG�iUg�+�+����N�r��	;���Mzx������B��{7 ��������'�^Ru�v�u�����ctnA"�h5�����@u�1���+vm�ENA=����4��R??���n�h:���4�4�x�����^-H������R������d�+r2�A
D��r�v���G��<O����-��)go����o��,rj$��S���\R�Y�3�ux��:����{H���k���~"(<�d��:]1�F[�<��R�,4;m��4��d�#�������1�.	�� bM����@������"P�2<E0"P�:{D��g�����'S�j���E�/�&������-�BU�m'���w�6�$yh:[�9X��"M��	�nA?rD-������g�e�����od8�>�N������ Z��������w6&���t����#��4�q�L����#&������w��b>[P
M�}:(��~���k��g���[��%�;����Q%
��#��[r(w�@��2Z�m17?�
=*��HI�����j����T���,�@��������]-��^:�r�AG�z�-�ukt���2t+�_�,}�i ?}.���%������q��<��#��*]���,#���6��*Pu6c���D#���])Et�<��Et	�oU��{�!A�z�`�k�@���\����9�"�S���a����,P/�(oK xu�
�W�����K�Q^@Pu��U�
�9�:K�����=����1��r��}�����Vu�#1�a�"��{�8��
@������Ad�aI�������4�������w�.}�MYl����5����|�%9\�E���>�5�w��.Y�;����(?��]7%�#���[���2��	i�&��""|:�%&��1?������;���5NzK!��s?�)@�'M9�g�N������s?���J��?�Z�i��-�h��������-@Pu�<T��������cQ��}.�@�5�:;H�����D��\
h:[�I�?�yAy���"����������-�����b�
���9�4�j�o�E�v�$-9x��� /�����9yO�����KU�Q'z�T�T����^�-��)�!y���H�N
�T�P��������p���GH��L�h�!h�����d�h:I���;p�������Q�)?����z�m�{��+	-���D���
Q)9��le�:WyB�A"���A%U���#�����'�9����#'���#:%��T}.����4��t���5������S#���}�v"��H^������'�H|����U!"Q����U���F{�=^hU�s*Z�����Z���.`?����n��	���������F,
E����3z���@��I>�[�ii����<������\��<U4�HSu�-����A2�
V7?�.�e��d�s,���lO�.������Z���$���65x��*]�~ ������@�A�B��!��y�:�5���UI�D�IG���x��N*8��H�^���a���j�����18���T��@����~�U��D����:[�U���%�(�#�@�U���4x��H���G��-h�rB�K>�D�	���D��v;�6"���o����C�Y��T5H���Kj�3�"M/�IFPu��	T��\����U=�7dy8�D
���K?O�k?��U�M�hM����(���(U��B������NQ������-�����w#��y�CP���,E�Z>7h$�����F���W�V5����5���?��Q�:4����J���dz�w�P�?Zk�)T�V�iS�O�8�2���4��F��:}������5�-(���3Y�-�q�NQ)U��W����P:[4:���db>�w���� �_N��������N�����U'@��+�@���/�����R��)vPt�42�{��I,�K������=�gx�U��V5Z1�'UG���(bO�:��;;�����zU7�G�i��m�F��������z��U�F�)M���~��Q6��>�I#�8�OiZ>w�PZ~;��D�I��)Z�IM���-�~��aAD���s���v�����x��'- A��q�"�T�^ZH���3��O�k����:YBJ���<*�zX&��r]\3��������X$K�4PZr>����z���tjU���P;�i�!o������~��(���A��7�#Xu�x�����R�:�b�{#.I�`���%8��p����TJM�a�fwju�_�(=�����_auZ���*�N�:�6���
��K`�X��S6�����\)��o;�����:�Z��9Z���1��3����o0P5x�Q���:�j��)��Fwii���9���X������>����g���C���h�.��n�%i1'-.�����s��7ZN�0��[��IRu�!M��"N���0�v��8>r�D�IMgo��O�o��?p�Cz`^yur�;zE��m�bT.�Q��r��I��+4%��!��4��)��
�A�Y��dI>�U���h��g��0}�v�l�@�����)������-p]��h$����!�z<iD�	���>����s�������i�-��������C����iQG�6p(�=�������@��@�*��SN�e����	@�Ir=�4\����U���%�������AE���n�z��������D�i��&b��){�G*C��^2/a#
���c����	�-���G0�t�E�h�
�{�S����������XU�z8H�I�GP5Z��BS�:;�T���Epj�%�G�zd�����!>���I�����+�:����@������y~@�����(�����g��z�[l9�����Vu�N���[���Z BM�������F�ZTj�F��#*�����t,�8���������z�F6����-����]�-Jq�����X}Vu������F��<,���_���V�|~��=�����T�cR<*���eV���K#�`�h�fD���I�:����F{.">����U	g��BUV1Q)M9������K��AZ�Kpp����%��n%�X|����jD��)�(U����������p��h�����:~S��G��h�B��v��HxhsY�Y�GX���=�[����$"S�:�Z�D ��
����U��)������QeP��d���)���%Xu�a�:���~�5��������V�s��1�(5�����������(U���E4j�NG���t4�j�������i�iI��Cr�{�o�=������N��V�|�^�GRr;�i�"��|�G��Co�;0��B8����v����:EXJMgk���K�O]���Zr�
Zk:3�
�9�n���r����5�h� ����H]��s��n������6S�&����+�#�`��T5�Si!�Wb������dV�K��(����Ndz�%�_3�-u(���R�~�����v���?�CJ=���5���FH�J��WxH�cfRZ�`�O���a��7���w��"O���-���	d��#S��`��{P�|��O�:;.�:�,��bZ��z����^������u8�n����w����X(���z�D���=�������$����oET�l����!���s��<:Yl.n=�LYA��7(}�����O�)�F�����������@��aU�R�7�
}#G�HM'���G����7�E���T�/��M��������t��(�w�N2JL�q�5�$"%�$�����&>�>��9�����U�E:�_�o���`�!p���JSV���F�����Z�CM�1Z>������F���uBx�ICFO�l�%=�����[�0�_�7��'�c&%L��x�x�IM��?�����Nk:�����M8�C���\]�l���Oe���:a�1���1�������bjM'�R����JS�c�p��s�Z\
�$?x���^6pH���y���kg�E�8q��G�?)�
�Vg�Cw�G��x�!������J$�:L�M��������L����?���E�KB��M�Ttv��shg9�fy�I3N�d����c3���;e�����������R���ZR�Y�Ot��J]�	m����8p4����4����F.����v�l������lW}�p�t;yx�	��������(��["��g�dR��Ye��\/8w�l:Y6y����p�pZ�:%~>��!�>��b8V[�i�u��J��*�Q����=�p���o4A�q��K�����;�{O�4e�A�#�{T�.���q=Z��@
,j��cA?�k���N��C\��iY���_]�xX)���b`���G?��[������KZ
�]$��{,�G�e�G���	��d���=@����O�c=����
��[{1i����a=X���Rz�G�"L���
�m\���AD�6����n�5�G����Vk��:	�&���"�!
��/�#Lr������1�i?�q�^-��]Kj3����>���(�<�D������%B$����"�L�f%~�����9�2W��N�}"����C���h:SU��� ������[)gO��FK�<�������?���K!�4���?����������_����}z\�y�����X��mY��������_��2O��!��/�z���H���>_?�/R������&h�
^�������E�2�S��&���{�OQ��\t�^���]��IE��zy����������e�>w��&]����>���&]��|����\�]�q^�������~���e���{\�C���H���m����I�����Q�S���_)���l��g,�e�M��X�o�W���7D����S��&����a�������y{|������u�<��C������'�}��>%�/��������Q��\v��w�C��f@��;]�OY��to��z���a��?��"�_?���f@�z�,�U����������EH������xSmM���]���?��?����Y.���?�����<�����?��?��?
�/��U	/�2��_������]���u����	�t�L�E)x���k��������:�����?���^��M;��W`����~��W���Yl�I)����S)���n�In���/�U-�����5��O����r{�z�A]�y
�i��tA[������E���4o�E�W�`�.�M.�;���m^�.,���GT,���>.�8x�����������*���O��SZ�e]d����\������^�����<�M\��r����Su@+X��u�=x�H��Bj'��r� oe+7���v�L�J��2��X���/�b�.��o�'�����>_������QJT��\���8��~���o�v���B���?J��~�&���J<}���K�����Q��N���D�T�|�m��K��vy\�Rz�u}�UxOS��h���z�(8��1o%�n����p}\�M���W�
+��m�6�Kr)o9���}?�y)VL2,^�~��H��.�|n���T)d���'{[��l�����[��t����B~5�TaU�w���������j��?�����Y�D@g_��
>���c����b+�!�+�SE�f��*�~*/�%*w@�y��;7EP�Qd�{p�=.�Y.E���U���
<�^�@P�����/N���-�.�G��[�K��(�gy����^�w|�}Q/�����V�Tm�������~����TH_��tTr ���rV(�����U�
���������}8�����Q�6R��f'W���Tix��Q���v�b��	�QN
��@
�Q L��H�ygP
��?H)��JH4 U?�����0 U�r�}�����4����%R�����^�9�@*���=�rH�?~�?� e��(��������>
2�f�<����t� �{k,�w^�s(���Ky����c)�2���Z�R�Q6W�hX�^��.S#h��E�5������L$��v5�������K�
���?vO��	�4$U^���{�!�������%
SI��u ^X
T4 �{Q������RCy��#J&AF�
���RQ�`�5���Q����������`T{�	��:�����`��������P}�h0����_[=�0*u�?U���3���M>��2�'�����#M��4������SeOH6%��
E��"�M�7=�:�������Jzy�nJ�0x���0�//��?.Ky���R���X.���������[y��W���N��������gk���-�$���R����\��U��w��m��
�\'��U}w�j����e�q� �����W�}D��|��+����ey�y��U�Hz[/�W��q�8��LSk�@~_.�;��>i,o~�W
�;�u��� ��_��c
�s����N���+�x�p�������PN���{5%]z���Jp3�K�|���������/����Z����A.���d��F��v�����Jz}��)9��T�����L)@O�<�}�����}��I��~��X���<�:���\s=Zs}�t�����HZ?�A������(Rs����z =���@��5n�J������4��]A/���_��Fc��I�_��5���+k�-�A�t��Fz�%?	/�8i�{9u�<g��(�
��{�����{��z]�4S����W�x�����*j�����$_�{�r(gl����y�{�r�p4���C=m��\s��j�G��g=�1���`��\�^� Z4h�Q�������~v������{�c�]�����=�N�z��dX�^9
�{ZG= �"�{Z�R+"�J���$�!P5����t,<K�����zd��;k-��
�H���o��/r.���*P�}?5/?u��[�=!������t)���
�=x��\�iix����=�h��]��X��&������k.���{h�.�1����~����<�I�C�����~&���{ 
���{hyz�i�(q�i��t�So���Q*�%�:����Z����v�;��|����WOK]I�Zk����b�p�h9��2*�y��m�+�?�=��}H�~����X��?��bOI�O��^W�����<[_�6����)��[��'t=��u������-�����
��'���i��e3@��<�q��_�*����|�#r���,���������E.�����z}�
X�R�%���~��+�I��s%��d+��E,y�-���b�\��<m�Z.���x�<iG�N�m�G���k=}^������c�}&)�i;�]+����G����X��������|y��xl� ����=i6������������:��v8r9�i����q��-Y�'�@����o��'l_��b���cI�@� �m�����9�~�7���[�2��x�}����	����0�����������C��?�!F
[��}x��mG@4c.g��'t�{Bj�qDW�q)��`��1��_�ry�/��5]���!���w�	!� �'Z@p�3�>�v��v�_7�����]��N��0}�����v��'=���W~	�p�e&�w�r��n���C�0�O�N����qN�I
���p���&.�7]9�9��5�S?Sh�Z�����T>{�[�7Q�6�g[���+�O�Wj��n��
ka���
���zbJ\H���6�}�]����0b���rf�������!
������w`�=�H%98�]�+���k���d+
��
���["b���Y�����|(��S�/X�����G@e����
��+�w`�2?������o��J�����JYPB
���/[�e?3�50��?���&�P���-5N���8��(���� ���/������������ZG��������dg�B�`���!���a*
urE�'����e�rW�+���0`�V�4]):����	o�{���|	��86�e-��=��Q<z�����lw�)6
�_���a���s6*��)G�86��/�w���r�g��qlD�u�6��S5�c#�O-p����)6b�6;6�_��6��?�"��F��^rl���`�u`���������Q���(�t6
g������+�!��##���khOqp�:��%r�98�kqF�q9��R
�`�V�}rp��(�
����e��6pvi���~���\��F>}���y�����(�\ d���E��>4�����*F����	[�FA[�[@E���}�9i��T�	��Q���D�$n�N�.���F��CQ~)R�=0�;h�w��=�RCJ�@�@����r����������y1ICJ�Qhj ?�HI�����ftleS�}5�R�0�6`Y�$_�%�9�Q���/H�p�<)��)���/	;<1C#:��d�5�O�O@�I�y��qq�#���$����R�P�k5T9����T�c�r!�5V*�(�C��M�PgL�8Z�6@���%��"�A��6pZ"�R��]'&,w�T?�����O�w��0��\��b�}��.����*�FW�r�j���@M����gbVq��:��l��tT~��JR.g�����9P��
���������V�|1BYK��K����HE_jR<m�Xo�����cH�K�F�l���jt����!g��g���R�%��4����W�_�)��<�D����7��t��v`g�������)7����kj���a����4��}�d�:��/n�wrTL��k���I�vb��\)^u�1�z�hZ�����qK�
=���r��g��F�2��Z�RH��9dD�� :�z��z�I�S�R�.��@O�1����D
���X�G������*b�jV�e+��9z^��7cc���6�(��u(
����?�:����<4���
������uh?|��Ns�j?���lL����}�d�:h;l��n�wnx��k�d\Z�Y�~6����+�DhH��x�	�!��c���~���I 
I���
���f\U�������j%��}�$��x4�����
�9����R����p�,Mt�t�+����K�����i��aX���a),���X
�,���
K��y���������/]~�6=�

��Z0�����\q �c���rpc�X*5�1�8�R�G)H����������oKa;����R�F������>J�R�C�Ka;V�s	,���F�R���4���5,��c������K�
��pIGHJ/l��n&[�����&�O�}���F�t��F#W�z�������%)~j��4AO^�'��*yy���e�u^F:� ��J!�eE6�������v%�_vl�7���Ub��D�������?v�6<
�5~Z.W{��6��^�5���u��+�&�������)��L^�\���W�������|1_k@�^�
�

:��bg"��N^h
��^�c�h|7��VR9tj
3�#�1T��M�a�p���4r���U[Q�������^�V6@������.qe�d����2��
DQ�
E_*	���=.�w��|��G	�����Z�l��\��Z}i���ZJrt���O)��soP�|Z������@�D �������9�ND$�$��DD�j�r�����
X������,������"���w��o�)����l-�#�`��������S���)�,�Z=��DhA������+��N����YK��f�[.�]��X(x/�@���������R��E�0��e��/����6��k��(����%���w}��Ic����>;��%i�-u���p
xk>�wR�r��wz���6���\�x��4�����4���@�xG�����-�#�us��=[�j�t��90���NrN��(�X�F�=~���L��gZ�W;�z��i
+���Q,�
eE�yhw����A��P�H�R�X���Po�R�������l���k�m�/�0��I�8����+����0N%�N�vN����/�v�lj��������fL�����������U��v��NO�--�r���Z��O����qZ�n��M������FZ�V��T)����/�2���r�
;�#!�M��nC3��Nx-�KU�6`M;R�}�j!��w0q�ANn���Dd�v��Yj}�z����4XV��$pM[Nvl`�n�dC��������4���
,qG7Xs�y���k���k�����!k�'���Wq M%>�q`9��:������{����~��]��H�AMJq�����%i�fl�[n�Yt��Y��~�.���<�����_��~������<����:���d��Y0m��u}�R��)���L�� OX��y�r�����im@Y�C����#�������A��~y����y�rx�6��?{��n����N�y��< OZN�����n- OK/@@^_��h�s���sV��NWy��i��x�J����eyRG�����q��������G���8��:6c9Jr�/�JR;0/d����r�;!�����W�a�x�[�'
�K� �A�����a�<3�����S4*�����'&$�@m<�'�����f�;),��������jU�A-=R�"���;< -p�L:6KX�cN7`�,��}�A�l���x�� ��%o
�2ro��FPj0��(e�;��t_u�W��v���JF_��e�a������}�@7v��x�U0I��,������h��������#���J�ylBa~��q(�P�o���i����d>���S;�s�B�P�hC�8W����Og~���Y��dG�T���R>��y_���eP��C��#���R~N������
�|�����AcWG$V�7�A#�Qz����6�&�F&J���J?�z9jo��Qm���xy'MvBD_*�nzH���%	o�S�&jd�V_��Hp��Ac_|�����|E����'�:�Fa���������k-�Q��U�4���L��F0��@��/\��j�7~������
q��95��/_;3�f3��/o�� m�������(�<,9�Q=�e���E�hr4�c�O�_��H:�J��A�Ta�p�h�f�R;]�4������x4j_��G�uh�vlE�@�'��+�(���]��'���d-%�trn��I������� G|>M�2pdy��7p��'���pi��������3Cx����1�?;7
y�Yz�J�R�����Q���KG%?�]jvn��1���#�O32��;&��fT����$K�&�E��A����e!�
���\��H�b�w�z�������id��xR+H`D�}O��:0�'O<C7`�/�k�+�jU�-='i%g�!
�J6|�j�d�Tj<9�P�b<9����}x!#�����}���C>���'����A�#'�%��s��,��3�����T�:C���8���r@����[J��>x2���H?N�>:h*���O�:4���&�(;
}���xr�|Q�v_.�E��f�9�oe�X��J~�<+Ij&~�VCM��0���2��L5���4w�b�����n4��"�PSkHF�8���P>s7��'_�9n���?���/p&�!g��Y���x\�/^��� :vr<P��c'�q��������Q��S��f5?������k(��}
�6��5XS�L :z

_�U{9�����8v�X�9�iZ�V�f��
p�����|\t�D���3v�W��x����V��D6f+�K:A�l������\K�zf:������u��Sj��d:��!�t
*�&�t8t�:����N�������N��<,�A'�Q�t�TW���@�5�z/v������+���Y[��I�^�N�a6��&�(/&�E�\y���a���R�]��>�J���xyowv�T�^dE(�(����j-@'*�q�*
�����v�]��J���=��g`��=�����dU>���b@��r��+�@������0��]�rb[��3�S(�T'u�z��u22��:xj�|9�S*�+�l&�v�&L��Z��������*�7�.$�6q�%PS+�y0��f�w��f�J3�/�t������ydv���0Y���\�TL	�@��VP� �]��U����o��5�2���|����J���6 �[�J�ch��"O�j?�����+�w���$G�:�2CJp���k
(o�}��W���Z/�]J���mh(%��9�x��QO�<Hk�<�����M0��Fi�'�����hO��7����&V0p�0-V16����{�n��6�������8-��-aw��D�(�� �>.���Y;&<�m���-�10QK�xU,����|yl��������~�� >��?��q@U�<��/�"�V�����( ���8f90U��E2y9mbF=
��J:�r������z�w�
W���,7`e;��m����C�����e����	[�B���7pMu�
������y��U[ag�p%Ox�uW�I�B��7p�V,�~K����x��y���Wrdb��W�$�Lh���d�;�C\!�������RGab�;Q�������R����&�u�]W�$����UzR�&���U������n9���Qm!Tp�:
���2��55c��J:�B���q�+�C�N���`G	t�
m����W
\��22X���m�/��'y6r� ,%;:K>[z����B�������tv�4n=x6��I�-�q���������p�5n=�<�����;���<��E:�����H���)���r��4������B��1'�5��C�������,��Zs
�����nv����'Z	�u�RJ��$1�n���VV�:���t�h�;5X����6��e�dx�e��.d���\2)�^_��+x��p�i����ii��
��������0/3O�9�����):�y6	����x�j�,K���#U3o6�i�u��uJY�M~�g�����wR���7��;{�B��Bh^e�p��	^�uj#`�/Y��G�-��B��^|K�1��I~�����p� �5l�Z��U��q!�a]_.�m��/>�8����q8���?<����q��,�����_�y`��~�c�~6���p��)�����\��p��iX�7,�@H�h�S�t��lVKgS�)��@!=���MV��i�*��u<p�v�����+t�@�Z�w:��h���	�<q����,�����"#Nw����)3���v���NyZ:KI�p�@���t6e*0O?�4��4���I����y��|�1[.W-0,�<m�n�j��-�	��y�r}�0�V-cI�8O'+��700O[�����
���I�1����;�<�V��~�3S�;3�����hG%��:l�1��"=Q��������t���*R&�d5JR�{�K��o��{�K�>=p��^�����^��%���"OHs+^�=a5O�#���<����{����<�;�k
�����qO�40�������\��5�����l��o���^_zC�i�G��f���t��6��=���"O�y#�9��-�"�'
�
�;,��b��6/LW�R�o�������$>\������e�]8y��G�	O|�~�^{���^_�*���^�x��6,]�j�'�F�SG>���w%�I����}�}����6�]�vX9G?m;�09�i����]��{=Xw}��G����	��On�B����@����t�T���2P�"���E�
�*j�f�	��������2�Z�v�t'����oN@�Tj]F��Gv����������rv��YV$���2�}��l>�Re]``_<��<��x��w�s�����A�N���������'�����������o����M�j<�R>��8T�o|�s��$z%�8�9����s��
��|,������
�r.��u��r.�g������C�A�����'q�������Qj �\�DO��lh��9@�$��3E�������Z�n�u���2�:�(��W!�����Z���������>�l2�|�]-IyE��tp�������|>�(J�'~�(&�gC#y�u�m�"���I�"���q���������*@Q�zV��t6V!od�d,)o�����aQ������|��	X������&��(mps��s`$��#K���r���Ka-��z�n #�XkG~\$��N�k
dD_V��
dD;
@N���=����XB4�����x�,v��>-��lg���=qo��&�D0:������������?��D�x������CXx�0h�Y�9=!��Ml`a��$y���+>Y�TW�:���� ��H2�n���+�6v�7��N�sO*v��E�T�(}�&�km
O�&'K��Y=@P��|U����� G8_���:��EW6��
�tK@�~�bk}����8}�4��.�j0��P�O�JV���F9�*���`�!����
���!-�T���9����t2U��gRJcl��5�>lYB�c_~�d:��#�{��}
/��4�*wq��s�jlVd6HYix��U:�Jx�.5�cJ�Q��)���a�����R��Z{]���\����Tp���Wo;1�/F'�^0�/��5�,%_
Y�@���	�!�q��
m4��5�p�7�����6��%I�lj/��/�|^|!�N'��_p�;���M{a5��Di��x��%t�g)��Mz1Y�U:�CjX�N���gQp����P���W\���;�!:��o��������X�U���;����t�����M��}T���U�/���*�j&Y���&8�,T3���O�d-�_],�	:*4�;|�/e��>k4����7�����UiP3��g_�V�G�
��j�:aL�|�5`�����:$Wj��^0�h�O�����Wv�O�83|��zr�c����J�s��{1���e6��3a��'�EBu�$���)�Vj���*�j�m*����9�8x1�>.5T�xMk@h��8��]�P��6�
�A��w
�D�G?�&�Lt�����������^i=����{)��/�aE������e����k��������Z���ATh���6\���5�|��D�6@	�;�J/�:��?D�^$�D���IXDa/���� *�x����4����Qa���(dD�:�V�K`
D�b�s^L6�R�V�1Y>G���AThXm	p8�J/6K���P����LD�� J:lHJy*��9�&�i �UTNZ?����S��I�#��:QJ��hp�	EO��g�'����k�k�
nB�t��$����k����V��}+6�^���Q�G���;��}fn��}_sV=�`T�1�%��r�8pr��QY�kP��u���������gb	O��T���jC���%�v��cOJK��%)/hX*���*yr���G2��i_G���}�"�>��"h�<��Z�^�h*�(����M�+k���@S\*)4������Hf�d+���R=��z(N�J�����0��${�aiy�%��V�S��vN�!��iWG���ip|�D�c@T�d�^�@T���Lm���$a���#���a*;BgS���JyzU�'����'
U���Q^��kJY�@CU���5T��x��&f��=-�,<����)e�sT~�U__4TU�e}%�f�������l�@��zz��2rF�*��'��Z�t����i��]yZ�M��v��C'�+G_����)|)�*�f����M�MM���YX}���,,!�R�����\P�ii:	:��X1.�"!�N�N����t����pk4B`9�';�X��N"�k�R��*Z�B�<��E���N!������`K��NG����^��K����t��z^����c.g@�����k�,�d���
�k:~zk9�
P��+����.��JMf�����tt��'1���=Jao���z}�d�c�=-=���i�c�����=
���/<[5��~�a9`,��ci��t�X�s��4���(Z��8`�8��r��u��_IJD�9c:HC�/`OK�cI�=��I�
���S9ck��k!:�3�����=TQ�?�# �+�^XT�GaX)p����)e�G~����
���"�Q�3]R;���.�P6K�]y�����~!��<^%z���A�,���z��lLKK�
�~i����~���tzd9T����5�A=���A�H�E���4��@�w~;����p�@�N+iI��
���{��6�J�����������R +=��+k��~>��EvT���,�n���{�~�l�1��*v9Y��
C��b:K��K��^O����q���T�������x�l�R
��f�'������N�vz�C���&����:i6e@�\0�sC:mv���FeC�s����|N3����� ����_A6	k��[�8��Te�W�ZEm��Q�n����/d��b�8�?�
�,�	t�6T6u��	pS**�5k���6V��9������Fz{'%kJ9��t�����Mg2�7���o���yp�Z�@8�[��C�9p(9����a��7t:����\4`�
�*�9��t��|c">G:!=s��C���<�N[eLv�r��u��6�3fw�{��+5�����E�a�G�����xZGa�{�W�'2��A�'?��|����@�Z�HR���U�"a�U����?)�XB���������k�t62�O��Y�|�th\0:����p�m��x�>i;eq���m�a��~�v�)�A�@�FesE��>��_��Y9�����JI�����H��<���xk���|�xk�������_n���?�P��$�������������TLL��'])��/��}`��C(�I�p���}z[��-���lMKB�}��v�PO��+G����+���_�E���j�'���?m<����@6����$��u�b:�C���#$���'���@i=��B�P�������	4PPGN>�J?�����k��1
��p����v����=���X'A��Z2�0�@C�QF��� 3;v�!GC2��-�����VJ�u�

���I^!��P�X<���!�R�As4�v�6);=	�{i�����WJvr����)#X��2�r<�����`���Q������t$�?0���@���-�M���'E����8(����Fe�������1�3����<
���9~�m��(�_�CbeaE�	���4���/�c����K�MGRQ_�y�\���fJcN:����_�����s$-}A_�zA��#���x���e�;d%���l�x��[�c_���5��c_�i�(��+4���|���)�Ge2����W_����u�,��0��brpT�'i�d?��:8�����
�~$�sp����dLvG
?��p$��=%����~
�~y�
p���Q���-�Q�@�(�:98j;V������������0O
������G��W�g��>�:��T�4j+�r�*������!8
���$��7F��L�z|���(���*�Q�%w�|�f�P�
�d>|���{KEC	���t`����#n ���IU{���R���5�@����,��P��)4��G�l"���8�*y����HJ��.@R��
n�u����Q�U7��s����Dv|D?�:*CH���?�$�����M����R�e	:���0p|�=)�U�ZI���08F�.s���	�#��_6r!��%�^�8?�R�)
S
�%7��'�@Y���
n������9�x������p5�T����O}�X���fip�|`"��j|����q��[���-yp�~/�
��<�jT�K�����+p	L���BRO���<����}y���SKo#e,���)��3%���_��:bJ3j� ]�b��r����;Q��l�\�)��f &lKB�|Ir�
1��y�����z���
3��������}^u.��n<��5�62��5��]����J6N^p�g���l7Tp�t��{a-'���4��z��Sy1[D6�C�P� �7NT���G�U:|
/�Y�c|�5	�^G�C�}�/k�Y���������C���
~g�P�}@���V	�hTF@����V(oEW�����^�+/�vM[;��gip�����������I�?
B��:�5���~�^�����R��}�����P���
C���!����yr��C(x�����Pa�34��P��%)�c�!TyQ��t	���"�Q�q�^����P�3���
����R�Pa�����[�Q	��C��]���)!�H��
��3e/�Y�AT�.J���nD�
�l�QaCC8�9�J+nu`#�}t�v����ED���f^%�V�7�AwyA�<��h����T��`9�^��&��(�Q��������A���W}���o�xv���\U��n��U��|R�t*J��
9�>!>t%]X�7�M����:�C���b\
�>�V�)�"PS��S,4h�i��W6*P���iN�N�&�]��(tb��T�BE=x�H��L�+f!|�v�� �O�1S9������r�?J�],��RXPo�Dp�l�h9�C"�0Vs�%�'�Q�T�O?pj?�\E�Rjp��������e;t>��%:2��P��z�<�A6��S�����c��V�����z����a������&��T�u����7P��������S�a���|;t%{��t��q�8zJ7v����Yi?�u|7��~
?�B��@���p���~L�M*���Fpzv�����R\y�L�����-3q������*.)����@�P*"����K��R����St�Y�j34W*���#8�m��NRf\��������K�����
������t�7p������aVJ>�����b�����P�@ 
M�N�����������)��^'	f'D �uQ�������	B Z���������@���p�t�!��.�	: ��h6��I;
��R:<\5=��H~'�~[\Z�������)�b����t�GWF�����Q������h���
r��[[Yd�6 W���d4h�\��r�7p��.���F!����Y1A:���?1@OJ��b�^_��e5z�w���_���J�����,xh�L��i�����
�����j�����4@O�
��G���!=��o�=��������$���!9�@O{?�*�>o����R�"�A\I�������B�W�N���4����})=C�'u�b�������v���)��eJ9��rI�W���~a}n�<�6����I���@����-�����~6�����3�20��5��������i`r����<`�%�=�1�/0�i��p��_hN�J~��w�j��a~%O�0M�z���^J�z`G�
�76��� �@�=��6��:�)�=\����J�q�����V�=����� i�G��j���}��|���|���_W�f,�������4���I��7�O[L|`y>�
,Hr�j��������tt1=[l4�i��t��K3'c>��t���G����R�|��S�[)���{{��e:���'5�xz��t�##�������7n�RM����+�|:�i;��1���_�/�t�<�Q~ �9�!Y{J�E�������=x64�8�iiV����=��g�Sr��
�{��i�,��=����r 	p�����a,�v��s�S�E�>�:�������r�q��3Fj���nd�p!��=�������J����|��r��5�c�R$>�c��/��r|�sgJ�C�I��c�^�+�RnuB���*������deX�	���N<��i��=e6�~cz����4�+�����y���gF]�m��o|A���]�4���P�����\��~z�5#_C?3�%�t��v��j�'W���i�����������,�G=�u�}/ji��:�
�0���2�"meD3v.�	��o��G� �i{)��������6�w�[�T���8������
'A�60��/[��Ss��W��F�
���iCAi���+e�����)Z��I�O� X������B�����T'H��������� �K�>M�
�w�=�P<=�>������6�������K�7]�sR~����S���dE�������hhH:v�Th��	j�w4�f���u�4�]��l�h��������K�����8
�/�h�Xx�!���+!;9gD��}�r��R�@Ce���R&Ve�LdxH���"�XX�|x� J�W��
@����^�X)z���!��;$��}���&�����B��4��>N>�g�*�����1cr9�Q���o�8(���`[�;�
7���<D;�r��3hc@�6��	a[@#���,�������o��v���zP���|�����e�v���q?i�T��.g�9h��7}v�������Ge��W
�~*�up����
�����YSG%?#3gG�__54p��#v������e�j���E�����gdA��+_�U
p�_�������dXV�#>?o���6�h
8�����*���:�T|�WyV2J~�O=��o�(�(��+T]7d��<�5��m����4���tTz��tl�$�������j`�U_�gp��p����H��|�wK�}����������o;u%�O��a��Z���+��2��"�����0�C�6UG���w�}����)P���/�/U�?s%��"E��x+�<`}3�T4dZ�?@���<���%��H*��W:��E��L!G���&#SJ�!T�M������K�g"��<Sn;�P;��:��p�{���NC�E�9
M��K��}+6<OZ�tB���,��>��������)(*&�s�>gz�>XB0)�a�t�3�K���-��X��������B	FJ@J�9�
!�,v��%��*�^�M�w���H�5��J��Gp\	��l���pRY��U
(��~a����@J�s��ET���"=?j3Jfu�Du��v�e�RN7pe.�,T��_���q�m����j��6
.�����x�>]����VB:�J_�8b��o6�(CLe��|H���!��a��t�����j
�����67j�:�ZASy��L,��3��^8�>V5*xa���'�����i�l=��jlE:���H�Y
:��5�:eL�����VR�<��a�F���'6�	��Sk�Y�A^�:�0��v�TkQL&��[��r[;������_�9��$��,-�z��5A��@�}u��}}���	z�/��5k�(�u���qVJ�v�"�x�gWC%��)
=�6�����k/�k2	1�S���07����l�8������_�O��b���Z\zQ����&�Szat
�����a���<��lp���X��b�����wa��h�!������"
;�Q�*/vc���OGPm���*
^�
�
:�������N��}��@��x��qDAG���{@��:�b����c)�n ������(���A�e�^��O���VB��0 }��P*9{r0��a�U6p��`T�1{^6R����T
�*/��^��h�E~U^�I���������c�����}B�T��90R�xZR@�4 �~�����:����M�(U:�S�y@������<<����9>��T�Q[w���~�F�$�*+*��L�����Z�B�����Z�x$��.�+�H

�v�Y)	����{2�T��� �@
���������m����R�6�	N��`�j����H������"�T�1'5{>�J�����������O������6������T����~_�&n�����]mW�����u�����������cI�D
M�^���)��4b:�J?�v:?�j+�H*�cU;�Y.�u��V�8��v�j;J�U3��+{�j�M�+N��6d�+������5��<��R�z\�!�}y�������(_.����`�_���N_�}z]o�}���c~U��r}���U���q�f)5����b��%��J��tI��9]J>���rv�����OG��y���Zi��r���+.�����Z����|����>�U�W��\���^j���:���J[�2��u����ac�Fh}Z��m�0���L>��E�C��J��-����;'���+��h��5>!��o������	!�������">!���$��9����4|��'����!RG|B���4�f����^�Cr�}B��g��J?!�/�{S����p�d���r����n�5(������P�q��C!���
�����8��z�e7(d���6^���@��P(���+"����_�B r(�NN���J�����P�Zr#�B����
�%�:��������:@v�:jamZi�vl#�,I�V^����P�:�J�$���$%������VX����=�jUE��&O��P�.�����BaW�1�d��P���Q�Ba6��5(�?}�T(����*�P[w��������P����PHK/� ��~
a�f9��g�7��S2�A���b�����<��5(����
R>i�jP�_{��hP���&�
AG!\�����w�P�P����d7=��2�$oI:�Z�0�Z�V~��G}�>.�Lk��j��Z�^*t@���e���()�%�����/��7���u0����.ck��'l
���V���� ��n����!�=����O�8��_��:��K8
8�a��w����P�������7�?���+O�6�[�;��p�|��.�����1
����#�48$_uX
������)���B���^n��������^�]60���-(8m`�����������xkP8�:����n��G��_
����x������a�.�S2�=�m�s����/�
�x:V����@H��o'.B�������,���2~�}� .|J�'����� (�������qDg$�����*��Y��/	��!�z���ZU����n����Z�b=A�4x��e����H�V�U���5��n��:o!%7&��
��V��9�����N����o)��3��^�%����~��D��t����#�����E+�+����'���;5�9���dF��u�:���B����PL ���o(����&*y��m8���u�BcW�����3�P��������f���H?��� ���	��� Q�p�:C�
H$�x>��W�J���=PQ�(lY����r�dH:.�53`C%���p
�
��
�*j{���Yn��c��;�T0F!������%�@��F��Wvg�����MB��[��vF���,�gCW`$���$����l��m�#��KF��w�80��4I��1�_fie����F����0�_������|a`�#�O���|=*>Gr�"���Wb1=+���,;0j�R��$2�qB�?���c-���W��J
���'���p�#�b4�98�����W���	���F�������(8�����LGe����8
��M!Ge��w`��������/<H&��'J�Ge���:�`?�8����$���}�g#��Q�r�> ����O��j���O�A8��p���_?���
�6�E�N�J�d�Z�}Y��VQ��A�����U*���jG�Q��F�����*�5�#
p�KZ�bS�G���Q(����8�W�w<&��������2��`��t��?�^w��a��g�>�N�(�|����#����i��!������9�}�'Q'��}X��'��a$�*K/�������[K�����	�.�|B��R���_�
.��������K�nSRX����.��������RZ�J��H�R�0���1u|�r4��:^esumx�K��������c-��� �r�.�������0��s��u��P���=�����$\A���:S�`/�l�&��[n0����ti�&�03����H��6&�L�	�p�L�	�D2�N��V�	S�o|�s�Z��6�@�ASh����4����2�Yq�"�lJ6&r�{�&�-�)�u�O�4+W��x�n�`S�Q@b���(WWJ3d��+�J������)��U���'L����d�'s����9_n[�ld�b�/]v���d�������r�=�a*{�p���X������5��sz=�E��
�T^����r���0�W=��aSy�8=v
����	h6���E�T�x�����5XJ��;t��e��^8����z\�G������w�����.�C��i�������r�����c-w)����:"kH�j3j��:��t|��4# tT��~�BG�ja[�B�
�N���,������=�
���r��tM�&�s����9��y�ATX1`���X�
5I�8U~�������;1@��v�l���H�NH�~�0l�
0 ?��vYo3�UB�P�����tz
�Q;Lt���TFf��
���YS���9�T���3���R��VR��C�\��6>B1�A�������U1��#��(%�\
XJ��zIV:�j����d��B�C��`G����x@)�x��V�S(E_
e_^+:���6@������#����T(*^X���R��<5������U�<�:�TX��p{���RG;����'�\
�;��'���0�w����h�GS�H�������Zq�N�N�U�HoI�T�%\U�0U�E�YLU?S�������}
�:��a��P~"X^�����LOmC-"����~��:���S�~��.�E`*����T��`����S���Rq�H���c�ca`���*~:w�0U/i��j<l�J�,3�Jm�:	��1L�J�6��a�� 0��c��p�	�0����lAZC`�����������Z�A�����	Q���=y%����zK����a�r�Y�4��c���-a�n�
[bX�;8S�'5�����J�Shh6�T�3��(1rL�k�K����5l~����S�����j/V,Lo��"��-4%0�o��������(�a�TQkhKS�����O��T��5���:wH����%-D�t�����#I�y��_C�*�������:UAGm��&G���m��o����N�0��QU���t�W0PUx���_Ld�J�i��UQE9�k���0a���Lvm��[U����+PU{b�����J�SCA��
)S?�(�������b��q�r\V|�L��C����X5T���������*V�]�%�#�����J�=n��]�'����`U�Q^^t)��
k1W-pT5Nu���R��*hxY�j��%O���+u8�����"�3��Y���C����3���%�[�z*����S��dq��v����{�,�x������Z���]�>@V$,O�C��-�w�Z��:y�.����Se� �;����U�b�=o�qJ8S__��T{QL��9��7�6-a_w�>i:�����T�X�h�U�
��c���]	���GV�4,���>Bk���~��*�4"M�Un��Y���l'G^���Fm������=����r����	���-�t��0��c�x��'�s������1O�%��+����4PO.��0{`<��:�I�_����'���������gAY������1�������~l�>�8��<�����_���~�������H�\�/�>��
^^~��fXcQ��[�6�C+A�Z'��(KZ�4
����K������/%E��*
�.�Q�����z�1;�	q���;+��7��P_�����P���wJ�Bi=U�8��t��PH��o��}��A(T�O��PH�W��z����A!XOi��B%�_A
��_���7�!d�B��V
��$�����+���0(v�5��1*�tX�U�}�]��FPC��V0�=q����ZiJJ������_�/[��I�P�(�3d��G��*g���<��P������MP�����lH���C�|��8w@��g3=
�y��s@T�o4��������<|��@���(���k& �t����7����Da��)���}J�D��3����w��@�O������8 �������b�����[~�t��9�����I^�c-�W0F��t�������|1^��p�vL��1�����J/��d5�)������������g��ta����^U��L��4[*�����H����"��0-9�����`?�����c�p���&0Q��������d/��i�hO���zC����=�PQ=��o���4�u]I�P�t,	���v��pP�9`Q�Q
l6�7��]Yk�2?&�������A�c����������UPZ��BrJ
(��v��������������1`Q���7K�E�|���)���N�h��O�7�d>5`:,R�]�"��X�����h�,��_�a��bW>������!�
��;~������Z�c�{��&W������������dE![M���b.7�9,J�S3��_�n�$�|m@���VMkQ�=��
k�N�����"�j+�D%�J89��O���t�Di�}nf'Ei�Q�Hy�Di�����A".�*$��Pd���?<j���O�����).?�-9$���;sH�����k���&���d�%E���_��h?M6P��SY������������!��Yh��"�x��F�Eve+=�9�Q����A���jj�F�c-?.��shD;
����1hD+
#�>7h\�U>�K�f���������xh�hy�7h�[���Tth$�����H������|'�H����
U��|�
h�����Fa��r���������/�����+�4
y�d�6�������|(0	h����^�X��=�t�c�J`k�#��E
�������
\�Fl	�5\�:��:7\�v������/��Y�z2�������G�|
g{2J�'~6:a��w�V��p����G!o����^����^��'1xT�I��s��/&�w�$pB�$��H/�A����'�$������)<�J
:"���:S���K��� R����U"��+�TF����x���D��#K�Q�Z�����\~Jeze��Cfl�;�+%������`�Z��M?=�/�� �H��|�g7���v���~��(��vV��@���mz|�5��[����['���_Lg8�}�a�I�C�d�8)��|m�p�6��I���o�����/��m8�=����I#� pR���F�2��0�5�TQH�����ZnH)���c���������Je��4����2�kV�����O�4
�$;�:].�Jm�^�&=VJ6�R���<u��A)RjO*�dI�<	:6���g��JZ��r�fZ��K�Hsh�W_v
��lI_���uU�����'���}����"%��/�S�M�B�i�������5`I����Q���O�mj��n^j����.y�5�9�_�a4sr��0K_C:@v{N������e �E���%��������/#���7�������t-Hr4�w�����F�P�<	U+:Q)RSPT�e�~�����P��&B�����~t�^P�nC%_S��uP�����c���t��:��C���&/A]����rcD�j�(5�~��@Qz���D	�����^,�PK��a\34J/��l��Q���>t���#x1��H�(�a	����3������e�aR�.��W��R����x*��W2�5�2�e�[��R�`�hr�s��~+�����
�����A�u�q�	l�+o��$N���L��:tj���k<IG����;O�/ec�++ ����qF���K��g�cD��6K���n��_r�V���[F�1Z3=YJ
F��m0ns����|�!A
H�S2�)j����l�n����:����b��@����r���H�K	hH�A�G
I��b2�����i�1p�H����X���*
��\���%���I��\���}����K�T����*`k��X�Eh������fI�Q�r�9�aIY��h0J:�R�q��/sM��0���	��n��c�q\�h_��B
�F��R,e���th��js��aTi(�E�buU~�����#`T�����:�J
uZ�fq��X����Q�����Q�a�������v�f��	 ?&�@�l�����y�5���p f���R�a�'�����j5����^��1��Th�B����8����<�[ybG��J�T�bW��X�u�#�D�8�����zfX�:����gta=6.Ir$E+�Z��"�z�/}^�1,���w�xO5��u�;���������$���}
�e#����������pTj0Vj]<�8�W���"�^$�5��:!��(���n��(�����z/R�Q�a��n5�3��/3
�F�Vl���F��%�.��-z���h�� �Vlx��������V��n@
:��n�'S�F��b�����/
s�V��J�6�V�qy�������8jgR��L>�Y]��d�R��2�js��m���O��y��Q[B�::kK����w!�M�1O�7�����*�I���z���k���u�O��NHo����btvY�]���.��}��������o�mm�������d�eUA��lO�c;�,�����^u�mC\A�G��"�+H�?y������o�����9�:Yp�_y;����� X�X*!kJ��W��$�4�3�(t2bY���g@��}�8t24��Q��!��X���Of�
�����i_�m�l��J�Bn�C�C`_�.2��Fv�����l���v�@���s
���d;|o���T��p�r�1S�)e��C ==��U���'��@R~��T?��(�@���}�l}:y�������JW:r
�:������\�������.{�y^af�� ��(�u��
�c��2n4��Q}�K�!���|�!5�Pp����,
:��(������>y����dCAi��A�l�����b�QP/;T
�����@A�]�)d2�Xi{���PP�N��� �F��}���X"x``_�kh���}�#pC@a�Q��MG@m;�.������A��:}r���@@��V����R������1�4* �ul������Xkj<?�'�R����'{�`��o�_���7�����N�s��$����zB��DF��l��t�
%����PHo�vd��9�yT�dM���49��Y��Y�@Xy��Q��3������+��jixIJ���b����;fe�ya�c��aU��s�����W�c ��+�g(���<K�B��:*�*]:
����g@0GA�c�F��<�t���l����������l9
�%�.�p}��y��}���;�����]�����z��>h=T����'N�������h}~-���z/	a�ib���p�h4
,�[��q���g�/����t%X��NB����9aKw,�?}A������6Y���-h�=0w#���(�)��VaM�P�X(])
��H�+,�Z���Yd��7
�[�����$+�z��w\���ZYvS�u��?{ii��aO�.9�[��C��>�M^���2��\���8`�t���0P�~��C'J `�tk"I�����_���n�'V�����:0�uM_���a_��/����g$v����B�>����'�y�j��	q{��A�t+E�������9A���N}����)p�������~W?\��!x�.���b �]xV�WM|�'���N�xl��1��tn��]��^P��,���l�\��WV�Y�V��2���������<������|e�|���S������,�OZ������V� t`������8���UgE1I���P!���;;
����j��|.��]����3i{ ���+=(L
(D��8�8��2�c`b�B��~3j���,����W�AQ�R�L^�����V��!`��}��X��u��j144K��y�A���JR4
��O'�H�Q���"
��5+�OV����l ��������H��4��/�q�s\���h_>�l����s�����,a��d�8�_���<)~�Z2�Q�gw8
��+7����!�/bZp$�R �
p$5K*kw�������8J��8�jG�Q�{pO��QjU��.�Q��V�c�H ��|)��y��|W^�����}{��
%o%i��t|��'��+���)?��9���<��!�;S�{�?l��#�#u�\��Ha���>$FZ�������Q�xX%i���QR�%1��B�iW��4���`GI�~;'C%�����~6�()|���x�%IG}��U5�J���{+���}�Q\Y�� @I�Id_('�	V�������Qo#��y<JCs���s���
%���$��P���h!ahT���������B�������e�t���$8U
%��(��y6b�$��Jr�Y*P<��ACI����r���9@����}
_�5A�I��%��~�$�
)�����p]��� ������D�/�)��#�������`F�8���`F�8��y���Q9�!wgI��^@����K�[�S�����&���G��'��e8��.�#t8)�^N���H����	
m��|�;RJv���R�PH��c<���j��r���@�a���2>>>�I\H�~��rff�s����|2�\J@��x��R*V�c��l�2ir�����"����8b��e�u�����/dk������g�(���:���
Q����v�D3v��	��:J��	�j����v9�9XZ�J������(���{[��^�~�:�^s�I�������{#�y�f�����k����
>	��UyQ+����!��b�������{�t������#CAx/��!hX���64�^����O�J�:
���W�v*~������}^V��)N�
{� 7U+�ZysJ���H����W��o&+B�Jx6q�3��`B������7�f�V\��P��>,��%-ES���A�^��|i����'�R2�����U0c��h_����$���4\c�0�9�vu����6���n�� R�d���O@���iJ
H�v�����\p�.�9�*7|H�D�@��
}�� �G��
,��"<,�~�|,U?�-i�oX���,���u,����J���n�����:p�)��8�C�X��~D|^TJ;K��z?���J\�����T��Yhz��u���������%G���
K���d]R"9��\�������ZCX��.I`�G,�y����$�T���Nts,U~Xg�m%���K����c��c�L���t,���x^�a�v��h9��vP)�c������z8�a)l���glI?v��J�>��s�������:�

�M�������'�X�B��c��a��+�vw,�^�v�H�Tz�u��S5�TX�X���Q`)���Y��(�2p%�u�|,*2J:�Q�����#)z�U>�����c+VP�j,W���t�ccX����I�u��U�.���I���E�QH*m(�]���]�a�3�D��Q���k������!����.hx��d�Q����/��QQ	QC$wa7'�Q�Ij�UVK����:�*_:�4�<n3@T���s7����������w���2�h?���`��`���Q�5�l���8 ��(������]�cs%_��u����<��^�M�Eg]|���x�)�j#����ZB�::^K�glzJ��G�mT>���2Vu�d�y�X��tR�k-������8e���r����|��^���I�������4"
8�Y�(�;p:�,�;���Hl�l�w����\��ZJ��DV��O�kE���������GQP�_%m
���=Kk
X��	���=S�+����
�`�_�Q�H�k�Kvf%�l�����fG&�:(��(k�byEL�7����2=!�b�5��'k�����_W��*���9_�4|�3E�>0<c������|}���|�0���4<�H��y��z:J�����N��R�QO�s�W�����5����� O�E�
�������+�o@���N��S�`���:58cD
���f�},�����N)(����@�u�x�%.���9����L
t:(j�l�;?�}���r����>������8����y�E;a{6�9�N��
���t!x�����i�a
T ��������P�<3��q����s(�'�V�%�z�)Y�|���OaO�oLv��_;�=�.����/�9I#�����N��(�
�9O;��� Ls�s��1W����t���&����XK(�H���W�)H��t��������&h	I�������-�7�f��n�4�_I�����>��4j������=X� ��~��/X�8(���A����v]-8�����qP���|�����'9����"t���'�����u�Z��?�r�q'�Z�Aa��7n�3uDsa�����]Gp���LN�A���>,tw+j��>���x�����t'�1K2u�P|G����2]�,)�%�p2]�`_�e0�q�+����v�-���=��#�8 ��18@P.��(Im��l�>����`P�=�	T��\�b�>��:p����@@��������Q8�P�<�pBa�%or �?��3����-7f�@e�1[
o��,��Si�J�~�W�$	�F��S���v������� ���),N�`�V�(R�t���N�|�e���'�B>@KH�� ;
��>��[_�
yo^��ABm<�D
 T����t�[?p���"B��_|w $��������`
q�!��@�k�~(���B!��L�n���v�����gGI��u�R~��g���>�7D=��?Q����N���7��TT�Q+0BeDX����s���L��}".���<��|)W{P���H��:)(D
@\/��O)�^�e�7[@b_xN
�$�
�	;���I�-C������b������Xe,>\S(���{��"Y'������U�"XO��H�C�b����0�qE�V������o8���"�>y(������
������.
���"47HTx�L��d)YQ���!�hF-����`�fy��9�t�v����h_���C� 4T$_�Z���"��������dq���d�d�p�b_��JH��b_��;����Ea�5Z�4��z�^*��rcz��'����|�NE����3�Y^�~���H��KU�$�����o��_��F?�F�F����Y�A#�?��4����o�Fa�}��D�Fe=�������/���H:�r�K�I�^[��Z�f��V�j�U�L�QnJ-.����F�%����u�����m�l��#���l�^�[o�W��
���GGm=8:J�D�5���l��G����������z�?9��d�@H���;�!��&{�D@>gIP��c$���F
�/����
#�|%p��Q�H�����b���Y�#�~j�����?�P)z�j�1=r����dP7�W������Qtl�<�{�%���;��9J��|���!�K�f�������MK���|�m]����ZJ���Xm8����T45�q������8)<HFC5�T��X�.���l��
�TK��4��[�'}���������� �,}�	�qR{��Y,p��@�a�I
"�xb|82���A'�R�5|Uv$�:w��2$j��^#O��X)<�(�+����W�ae?�2u��``%�(�e	��2a!e�Ji���R��J���������RYS��K:�vM�r�L8�c��3R���u�q
������n")����k�(F�JNi��TP�cX)|�,c�3������^�!��a����T)]��-��O�hYY�`/�mH����N��!G��o�@L��]�f4���h�k��09��Q���c��a�}��>LVv�1���i^�Z��x��
&��2jwr��LmE�[���1S�QKD���1����BS]f��~��*0���&d�A����Q����K����V���e�����r��
/F���.���
-��������\8F�*��Y�c�.L���!�r�xS5��f�MOq���_��������3�%RZB
.����t]�c�r�
;����V!�������O�~4����k������8�R���[��R,���4�<GYo��l�0�Nj��&�
������NxBY����TP�@]k�('��)=Q���0���*��I*�
l�u(����2�{l#��Jz����`�>���=�c�Bvu���;�D*+��:������I�G���3�k+����&}��5��n0��S�ga5�6���9q��	��a���7�����d����iT?�B��f_�M�������I�U�N�����n�)��R' |������KY�O�7�>��
�$;�	1M�����O��`AG=f�l3��6���%}�v�I���J5�
J������X��G��bK������u���R�l�����T�(��C������kq,?�d(�q,�~���=�TZ�gK���>+�D����#�Z�Rpc���~Xc��!1,�~�����7
K����G����9['I��B�l�[���T��%K����a�z`
p,�^lF���
A|CB��r%���xj�%��P����� �L:6;
�q �:
���R^�2�D�|H��i�L�����y��r�z
cC���+�Mi���`���Q�BC����WRa���`��'n�����m
U^l�l��:F�
��2���_�
(*�"!�m(*�"h9\���	�C�J&��
C�����a�����
C����f��GAC!n�P��4U��z�Y��50��mh��C���&m#����
>�w���E3gA��:�*EPZ��N�J:�o~�=
A������r}W��k
�?��2��m�Ru#d����4Q���.%9:�K��
6J.a^��S)�2g�������^%��w��y�����n�!eo����2�r���Q��q���0k�os�zr�:E��R�Yki��:a�k[y�����9W]9]��~C��[\�~`l	���������A_>��B$u���v���OB�����%�*
����o����UJ�������Z���^��J��z�v�1,��1w�^R ����D?��P��	q�a_����t�
 T�[���@���|�!'�B!oc�!&�x�� TO��~=�Py�D�
)p��R!=��h�K$�W.�
 �V� ����!��#+�zx�����oy{K��:�Z��V3��Z����*J�D=������"�P��v���1!?�"=����c����k1�p~� ~R7���}�����P��8��D����B2��+���X�@���,������r��L?�@K�����L�@����a�i���xzJ��@(�W�� �_�$B��
{Q��b�W�� ��t$N;B��3#�Y���2�V����+"�L%
���NA�Z8�������i�0�����j`!����6���e_{.)7��|�O�Y+�_6Q$G���q��c�!O����`=1�j�� ��������������P�@C��Pb��T/cRPo����O�b^��hx(qX������k��bM�g�O���W��4?*��'�-
����+MD4T��\C�B���'�@C��\b1i�5���u�j+�2�R�j;
�:��jx�s��ZG)�I���>V~[(%ynm�a_�����cH��h���O�o5������O�`"��������������_�LL������D�NI��>�*��J���v��J�������dezk��>��5T��B����^�&4T�K���<�rlf3��*��g-�I�����SX�5`Q/G!z����E�c���D���f�!aj/��
��
��B��J��]�^�7�}���10�D<�i���X!_�M
�L���k�%������d?M�2P����UEZ~`Pd���C\~�3P������"�T;(Jy��
P����Ki�pO>�3��J����������'������"~���	�����8�*���(�s��ZE��hA�����"�R;)uu�m�/�M��#��8,���9,������y���b��o��W������

�����Q��=f
��L���������2?�mw`�E�||#��9�0��S�E#-?C#���(
���<�55`T�o	��#����Fa:����U��������|`��	7����z��5�����������u|]+l�C�Q��uX���x�!]��T�c�^��������9��G��jd�WW����n:4����a��O�md�(l�/���B���8,
�*������}�B�Ee{�M���l��H��_sD�����D2~�F��X���V��N�?UK���D%�D��B����&<�P=�����������DS'��q��
�APQ�@�`P�QJ�d*�.K���p������L��f��Z������zG���A�h%�J����M���7�Bv��<Y������B~N:�����5�)i H��
D���������|.lj@H�'2YGB�ffv���6�IT�72�����!����o�+��jp���J�gCi?��k�(��&���o-p>
H������8l�(�()�/��/���c��`�s�Q~/�4c
:�J�������p��p|)d��F�����Y��*��x��Q�H�-�����l�lz���P�kP����;����'�AW,4������I���V1g]�UX�33���a�F����=�*�����}6��M)d��'��t����)���}
O���s���GZ0'�A��5X�!GM���D���\�
b)E�����V��RJ��u����F%;J�z�������VjO��]t���<�������~�X���P��Xy}��Vl��NI?���������K���tj��S�R�������H/�"i�0�;������K���4���d�k�i������#f�����d���i��^xU�>aV�����S�L�� �c������f�OL�8fj
�a��`��>���N�B��rNh��:��nC
?���|��<'se&7e{�OV�J����te;�� �a�u�o!u��h��Z��.��n@��[!a�4�0�]
�nh����cB��������J/��;;pj�d�`P�����@�,�qe�U!T��h���e
�p��^@UP���M���������lp��

�:��<����]d\�R�7���QQ�1B���o��� 
fXN��3j!�-�/7����Z�[��u�5�����(/(�q�����|���9~MT
>����{S>���_U�������b�OX&2�/�V+�l����	&d
��^��>�^XKB
����4�|����V����Om��r3�L�ny>�S���O��OiCv��r�r7�	3Q������J�R������S��@����u�\h���'��^T���L\�� �������2����t_���Z�t,��~M}����WA���^�������'���/���������/���W��h�X���/L��/����kP*=�
t��e{�V@*���J����zK^��1�.�mfG�����_y�cx j�'2��m����zO�F�,;��Z������&
T�:|����-����x9+o,�qN��v��t��t�&xb3ut���r��[�k
��a��U
V���c�!`U���,
0qX%u$ZV]K�<m�s���v��X�����~6M|Y��]��d��V!_�w7��o��uX��>��vu����&����"�td=����y�Z�����U��lW�T����Y�25����
��5�`Ph�{�����:�R��|�h��*S��}�z������
k����C+�����*=I�~�3�
��.��Kt��Q
����{S��5p�*��������x*Z�#�� ��~+���A+�XK�e����]gK��u���v���P��
�R������%����\+�����iF>�>w����h�|6l�Zf��/�O���a3�v�����@k�a�u9�7�������������e8n����e�z����l���Y�e���K��Y���q�h��z���V���[]�UF����q�=%��)����h�����a�u��6r�%���|F	��iN���3.,�:�����k-4����+,�\kw3�V�z�	B3`Wc-|���u�/�����BaW��<5�[@a_�����i@a_~l\�6�54�2���
��pQ�P+O��`<�JJ��u������B��
(�K�o�
��@�g@!�����B�k����B�������9��:]P��^.T��aF��,��S��kPH:���<�����4%f'36��4�:*��M�3)�b�0���|)_������|a���~Yg<{}�k�t�P��NI�	��8)!�PXns��Jez��0(M�d�� XN � �=��u��C3�C ���:*�n�p����&�UO�����3�9�����d~��O>�9��M��Y�>i:�]��gW��������k�����*��<�"?*?m^z��^���A��n�}S~���Zy�p!
�QF��nLx���*��z�o�������=OKf=�y}q�6�����O���	����zl}�����{h��!�)�y�dC>m<�;�������}`=|�4������~����'ol}�_���{Zm&��>}����~�����c]���5�9��i�/�E�l=�	5���l�2�E#��G�w������a�;1���O���D�8�u���6�L:6����d��
�m6(�.�����Ba_r�NP���k�	����vNg~Ce��#��#��r]�C%��
�|<Vz���<J�?@)��_�2����~�7
H�����D!o]����!�+�
��3�z�����J~�*���zxz��z��(���oA��JGe�`��DE��`F9Q�F���Q	�&��kmfO	�IG�[��m��ul����E���]f�x�.�G/o��
I�~�
�R��T(�E�����|��,*��{/�~b�H��ZX���8������[>�E���EZ���#���1�`�G��,
���j�����#���Z���3��E������G>������I�2�e����������u����]!�R��Rh�fp����Fp����5��f@�^��S�������P`$+J*@Q4`�/�����^
���@$C���
\���tK��w���	��4*����F��y�*Z�F'�a�GN�����hD��Q�o�������'?1��@}�������/���:4*y�/n����1��Q�B"����z���)!����Y�
������@cZQ
:��c"4h�:��$�����X�7p1�H�T�����4�(���\~�]���R���#G!�eU�d.����Z�|�tpT����l8�O��q���z��4�V�G2�5q�������Z!
���fVf��
���2�����Q�r����R�?.��m����H��%Q�m�H>�u����v�a�MpL\��-�Q�S
�r����hu�UN(V����uh$O��4:O�QR+i:u].��'%���.!������=!�h������T������������Fa������(������B�o��lp%����=90��O�G0��o#O��3�Q�r��]���/�&	��}����F��@�����Q<
�~�'`�?�5N�
^��:��T���w:w:,j#�2�t���)5����gFp����E:��-i��FN*O�~bDO�ZN�c���������^��F���������}
6n��V�P^���a���PK��� ����_	L�+��b
@J�����
>���9�_�:�:X
��y����[�kI@t�p)4XU�>G;\J�������^��7�B������U��aL^�#�p����#���:�wd���Z*�n q9��< \y��G]�����P��C&yb}02��'I�dpy]n�}�����+i#s���
0����3(���Z���>2�v���^�	�J��i/��:M�w�5��{Q;���#�O������ke�����-z�C���'#�]�n.x���S{1��b@gWC�	�A�.Wa3����O�����l�%�����/��[����c���u�������X�Ei��*���,
���Mp�L��2�H��/Wf��]�}��v��]�����i�y�l��x
i�y9m�5l6�����]
u�(�xJ/����{����O��������"����{Q>C��6�S���� <�O�h�������.���'����S������:�ngp6��&z>�/��Mv%^��Lgo/x�uP���n�
@�~��{�@�#���SPm�j�t��R���!�����������`��'��"�O�l��Q����g���.!\DTC��U�F-��}���}s��3��r�kU��]��������e�=�.0Uu������>�S�0'�:���	�
9�Ykg���S�����X��k�]��.�����1���0��U�bu�T.�ygP����\��>��L��M�K��}����2~��*h����T��7�BXj�r��O�J�b���*��
B2�)�x}�@���9cN�#�u�6���e�z�c8��k��~�������-�����t�����krX,�~�]#6;D�q����]�� ��@L����>9$uCGeM���a�T��t��������6,=r
>���j%����>6�~������������8�S���������c���RG`���jm��[b��D\y����C����D�i/`TZQgDL�G��sO�� ��Xj�.ER�����p��km�")nk����<��N9�^��lh�����t���Q��0��i_G�`�i\������.�����������i\�'O�[2L�-���T�T��'��i\���YT%OJ�P�;�
O�Z<Ch��*4���U1�&^GU��U��Lwn���4��������5��;��+�������L�	\��y��Ip+����(��i �����J��x9
}z:�\y���EGT�c-e<�������p:})���������\As�N�q��������n�y\��1FX��`o�Q�����dT�9�����_�M/�a�v]g�O�&�y�.���v��{'���n���	h�v���t�n:��|�.i����A?1S���W���3IVXy�����&���O���^��X��0�|:|�����b��5��_�A��gs&5
�q���,�8Sn�a�4��MdF`0��������AV_�(0�|�_���e-�Y��(x����G�����YG��p���X(����
�4��
��p(���
��i?��=�(O���@AX�|��}M�t����4P�/=e((�m�t:�K�Ly�������t``�����J��y(0P=�����@���b��'0���sP~�����IJ�j3�R:?pS�u�F�Jq9J�%oja_0eu���/�@���T�{H�u
�������}ag1G@e�j��n�P���$G@�]��v'�(m�y��v}9H���!(��1��������^���������>�$e\���O�?\w��t�S�'���v�<�O>�2�`1��������Ry��	�|�3��*��	�}�������g@��� ,�;���{�SN��|)�6���g@��;��'p��6o�c`W��0�!$��/{���y�������6~���l�P��t��k(��^�������N�9P��
���LTT��s>3PP�;�0
j�!((h	�����u �h(���������6s&5P����a�O����ju�c�U�U>���#
#C��w.�Pp��w�v�U�v
��z����My��}4��L�>L��\kmJ�}��<a�e`_0�A����lq��'�},�����'��p"���2=�b��N\�~`���u�C�	�*���.v����}0��4�\uM2���C�x���M\��x6�y8�	��v���oL�j��
8�	a#�+6d'?PQ�)�/� �T������|�;�c�6��SWB+G<Z�B#6<p�Y{T�3:Rj�4}�:R�ZS�����x�[�w]�z���<�C��)�%�m��
����;3�9�)��Q>��M�Ow����^�UG��;20��N�>�w��z���t
�w��:<���~���<f�4}��NG���IW�#�z��C���G�_�>0O=�����>�}�P�c�X��s�^�:x��x9�I��N�y�bp�2������`1�'<�	��
�CJ^��t���
�2�����A>� �/������ �o���)����h� O�n���H�����&���4�I�N`��G��O~'=��wR8�Q����zd|^�"'�|��
��+����3��;���!�O�=e:3)������F)n9A�0�����N�<�A�TX=ar��^��45�8�I#l�U>3�X�qr��z���$c�+��M�(	�GJ��V��w��V>K���o��|}���L�S�O<��w����i�k��A�%d��}�x�7��W�~H�'��1�S�'T�~h���p����&?i���x~d<����D$W�O�����q�S?U{��������|���?8.gs������C*��jt"�X@��6��d�e]��q�����<�kX���Q
�i'l�H��*������v��3�@G?���(�;���nj�~s�Hgd�UW2N/I����u�x��C_Wz��������������])p,�5���C�)P�o�}}���
�k9����3�}@,9��#^��OK�e�=�\y����:��dG;��l����ZGc��d�S��d��S��=NHv�����X:��P��R#H��:�a.��ylE��v�i��a��(G^�sbr�]q0���sB����]tBT���>�d����� q�)�+k	�=�d��|k���5C<i�����d�3T��s=�j�
��z*1����r��8P!v���a�03:���'�����T�����O�
��}����h5]xEAi�k������>������ZEI�l���HHF�!�8
�R@��9���x?�u��0q���
iOKfT�#%��_�����������/��PC�g�V^���
&c���>CD���}iz6CD���%JJ�q�e���6`�,X`��?�{�����M���F*�$���6`�A�r�Nq \v\��Nw�E�Hc�
*\z.����&p������������q	G���*j��9.J+J ���"a���*�69����F�������h��?:*�����d�Dr�^F��8G������!x_��&LxT	\�?}�I���<�j(�\�`LN��)����|�g����cp�	��.w�fA3p.\��Y7b�ta����6������)(Pp�Rpa�VvH��q���q�*��>�?g� �\��~x3=)���&���v8�:L**'���\&�~bJ��r[�k�� ��gG�D9�/t�w��N<kw��@IZ�jG�IE� GIr���7%��r}�v���J��;J��z����$()�6�G�()]�kHAW|EI��M0��e(b6����(�]���lN4�T.�����v�:q
���$+�R�����3�����URAx
4�����4?�������cH�>:#�N��QR�0�QR_4V��l���Q�V�J��FO�q�$�9;����GI�|�GI��L��R��u/��?�6t%�Ir��1�&8��@G��P� �n����t�Kl��6��p�g�pf���
|�&�*l��:Lj'&�@�)���]=:P
',������Q�0���`&;O�+�v�T>�,Iy�����|i6PJ�x�$'��4�����
��������1�T*+���1�N0��O��Nx��F
/�
6h
�X�T)�l~6V9b*7��w���F�uz1�Z�!YQ�.���&�1�	
`j7�������(��������o���Hy]���������R4��_J��JM���O�
�f_E�j~�AMp��!
4���v7���NP���&81��
����t���}p��4�	�;hJ'���
4�sIv`���&�$ s���Nl��6��6��	���+h�N�u��&8Q�u`���&;A
4�V��>J�9h����^��MmE�bL�Y��dD1z�
5��W�}d�X����T��&;R*��l,���:�Qy���B-�u[.����Q�������_G�C	��N��b����GV�}�z5Jp���������Tr�5����6>��(@/8M���4\'9�
�������y��F�p�S3T2R��G<�gIx���U2���	�'f��2��O��4"��j������7��F��g��RE����X�%�T�X�
;�j�c#-����*2"8X������^����,��t�L.:2�ma�v�R��R;���:�p�$ ��wOBz*d��$��=Z�	w7<59�I��f
90<'��-e�Q��+W�V��gkvz9-wr���pe ���uF
����8e0��3�9��dzu�9z6
G0���;_9�i����`N�L��?;�I��l��B����	���QR��%n���s`D!�����VQS&���M�e��8~��d?H�[���T�s�F=��8w���O*���M�m��s����wR�Xy�9i7^M�	�3�4�9m8��8�i����qN����@������zN�9e��0�8�+��0'���u��r}aIH���g�0C9�l���0�(�KqG9�l�/�r�
�y+�-:�)��E``�!YQ*h�����4�$�_	S0b.�0�J'PN��W"pG�(�~������z���������\�t������f�S_��������= @�'m���&mt>�IXm�X����Zw��ueW��q|Vs�v��uz�������s�cX-�r��Z�O"���S���������r�jY8{9�	���30����W���/�W�p{�x&,��;����md��m�����4G2i�fte������v����(E�Q@&m(=��	��Zl���,���.�D�c}A�����C_	������h��YLhy�����8_�)l��<��
L�!
M��H��!��Uk�F�ka�5:�U�4�W������z��s��
�
j���p�,O=�o��32pz�������A�:�I�+�1Ci=��34������+8mD���������+����J�Wp�`5�
������f7?6���!i�
endstream
endobj

6 0 obj
54845
endobj

8 0 obj
<</Length 9 0 R/Filter/FlateDecode>>
stream
x���O������������ d\�P�DD�����-�f���$�{3__w3���~~�����P���-���<t�sl����������_�����u�s[�����g����������������������������O�����W�}�����u�\���?��?����Y.���?���������������v��i�����>�������������������������+����^��o�)��?������/E�W�7u�u����?������������~����7�k�L��g����
���r�����h�lJ�e�^�}�����?���������u����z���?�����uY.�i�s�n��m�s�^���?����������������r�]�����}�����������.������6�E�m����~t��o.���������VRe3E��{�>��?�e�
(��������e���Z$�
��f������m-SD}-����X����hp����o��M��:��L�����^�no�l������������x���*?�����������l;{��t��?�P�{������}���|��������E����1������dvS�8��T�f's[����s�E)jo;���o��OX�"X�p?��O�6��$�����mZ\��'j�'5��tR��N������������\^`�RTQ����N���k���p:0e���u�H������$��	>|��:��?|xhr��\y����F�?|x����o�{����~x���s�������.�_O������O������
t��sJ�a���V�i��$?8�����m��$-����?��y��G��:������R}��W��<�o-j�'-:���m�_���_���%lj�r�������o��?=ro/�O'DU�&���G����||q��iS�O��?e=���������4�/��9������ �td���~��S�;iro_-�?\�vY�������u��p5�~�l��0���C��jR��w|'�����������,�{��>�f���H�5W����� ��|�I����z�����)����M�|�zY�]�r�4m8��X����kGD_����6�k`����e��IU�����m��[@s5���>&8���~�����p5m��w�7K>_K��hS\m�/�u;�pWS��Z��N�Y�^������Ve�����:�j`���}�����Q���o���u`��}�|��=����kF��������28x�X����;������uR�S����N%�^>r�8�a��W�*#��;S�+iS�^�����#��o�p���2-��w}Fdz/2��}��������*�Tw4Z�.�����MY����u__h�����s�f|"�|^��fd��k8�LK:�n@s��7[/_k?l�#��`Y��u=�x\��h=\��~���hz+F�p4�����S��:/��J+=���U���*��pp�w�O�}>�����zs%-��H�
�|��S�Q:�N%�; ������'��O�{v��H�c��wO�m�}��r�%;��<�+p�Q��H�3������!Zw���c'��iw^�TS��;��F�c�l��8�����y��4zx�1R�(�GII�_�PR��[����~�\�ow�9��t(8�t��'TN���{���8���u9E����,d���V�P�ow8�����E�OG?�L��@��>�������wM8�|�����>9�2�~��:����pW�F��Z�C5�a�������������3��^ ��[>��f~�
���8��������cv��^��R�7�xln�E�"Y��;�*@q���-�������Te?�Z$m�����u��������ZP��}�����R�7X���Rk�Y�wx�K��WjQ�i�o�J/��/�$w�e�,�_���)A�������}V~}�����=A�ge�Q�1��E��;x��>w���/�SI
��w���~�6%a�hm�/��8���5%*���_IU�+�����P�8{��]&s�*K����:n������I��q�>�}�����U�:��w�o ��u��~��*>
�j�;��D��]P�N�jQ�!������t��Z������������|~z#��h)�{�5�I�~��4���eZd0Y��3������@-j>������?������������oi�^�AK�������p�i(E��gQ�]���~��/^�._k'���A��tS���Q����lZ��{��%�����3�����M���l�Z%|MK:d�A���kZ�p!|���s:!��j(Q�^)U-�	���>��P���jI�w��I)��Oj�t)���-�R��?����4���?������Y��p}�Q��~Z�gp��(E�~'JI����pk^����?m�he����^��_��(E���L{�lq���p��+�s�P����B�p8)h��NJ:����}^W���?�g�����o;)i��#�m�Y����~��7��#eLj�/
A�hkD��������;��@��6��*Re��T���3m__232��l~%E
~��*c�s�V$i�s������=�:Re0l�����5�:\-U�u�V���p��Jw}CI�/O�~����r�{��V�d�����4�G���i`+�����������:����2_5
!�vBT�+�k�J��5X��������pF��\{)�:|��A:J���_�+����z�}�y����?%j��T�.
�Q�ev�l�����iU>� �U_��~`��/8���~]{�N&���"\�}Q�����R�Y���x_	_��>o;���v!;������jx�Vj�$���5X_��Rx��_���u�-�/�*�������jwus~���L`�jQ�T���o|9�� �dy�:�4j��5M�� ������>+u>�o]����k7�����y�[��s%�R� ��2�`
W��!�o�P��4�����4������X��ku%������e��y�M����P�jn%��[���+���������b���WR�`Ss+0�3��t/`���J���J�+�BKF�e�����'����<�����3w7����[�tn�4w2)h��N&%��;�g�����w�����#�?�p��i�NV9��C�?�n�l[7P���M�����Z�_��
'�����g[�3�$�K���������$����b��@�L�w`�=p���������I��n�"I|�� ��j����;%�:�e�F%ex���x6;YV��f1�U
��xR:!�F��?Te�[��n�;���?!*�������6�U�D/�N�2��n�E��>t�6�#�>>H�]7�tZ�Cm���m>��>�W>�&���O��j	O��>�W1<Q�~�IU�y�����^���`���	O��R����'J=�5{o���t��{'Q'�I����u�����R�M�r����:Z�	���@�jG�w_CUr.�m}�����VE)j���������Q�
�~
�
��p;�j���<�T���p��w������.w;\?N���F����#�O�6D�M���Q_q��
�IT@�A�r``��
�myw��`r�G-��mA���f�"YY��?Z�����������tZ�.�J����R �$��6�{�~1*�=P����D��(+Q�bh6��������.��b���e}�b j�r�]�D��
��wG�_�����R�p5%��hz�FH��y���c� �SZ7V�\S�t| �p���}IIcx�T�$Q�6_/�Me$��j�y�N#o����B5HFn�
�"?��N����A����Z�I6=u6�w�/�&:q�]T�jq�@�/��p/G_q��J�:(}��
�Q�j��v�C�>_���k��@������p52��y�p����|�Yu�4~��z7��C�����a}�
��J���^��))���u!5U����j�w���}���3��gzw�`,�E�������(�_����hQ���(���(��!�q �:��Q��Q�(�-��g�t�y��-8$��G��D��IU�O�+5J����0<�.�M��wwsF)�t��5J���Q�w�~�=�Z$����������Plmu7g�Fc��� W�J)j���#��J^��z�+�RK���WJQ�����n�v�8^���<4��}����H���\�v�~�N�"�f�4�d� c�HV^���@�WdM �`H�-�����7��O�\4���@N���b=u�����|���:�fx��y�/�KJ:��M��B�������gZ���������:��S�?���	\c���&g�K�Q'���:�&A�������pa�|���8�{"x.�z��2�1J"^)E-�g����-���o?�/������'��*z�G�5Z����ISF?~���*y���>�D�`�O8U_������� L\v�wI;F���3)i4�n&���p�.�iN&�}��II��Kw�}���G������"VP�����z�����'����{���������NP`+�B����CJ:�C�F�6�SZ�����V��@���-<]����������v�g���?H�����z.:�G��@���ZI�*g�C����I�I"5z�u��������9J�y}N�%������N%�U`�U9���z#�K5J#��E
����|�������o�p@-�$O
jun�&���^i)5����BTv�_�F�s�'j�d���l�&
Th�n������>���G�L�o���E���P	�'	L���L��:w90��������k������@�g�����^F��u4�������"�lB��3����9@���? �l�O�~���U�y���MxP�t�#?�	}[�m/� >r�Q��~U������5B ��	x��B�O�J���i����A� ��8�/�@�D8��k�t�H�
���z]'$�d�'��	��.�1��&E���!�������uHZ>_�JD>���/JQ��+�����������S��0�#����4<��]QJ�[O����o������s7�r����o�EI��R��T��������-ts�&��8�o��*���c�Q�'0��8�9�Q�&8
�F+��������r���z�G.<����������������d'�my7��@�@M�Z?]�������JQ�_���d�@��:�*�V�-� Q�zG��O���8P�3��V������������"�E-i�����F
�
���w��"X5�M��K����N�
��������]N�E�����#���R�Y~��(������/�p?m�Y0Qg_�d�'�=�@��Z����[s���s�4R� !�rv�Y5�A��h���3�*�sh�A� mm�"�w������v}���]V!�N��'�����:|������q��5��iM��r j������;�4]x�u�Zr}w������|�V�c'���]��iQ�OT��5����Z�h�K�"������@���_�;��n��s9�RK��DS�{ �:Y�/��=D�d�AQ'��@<b]gQ'�Bp�Ov1L����~5��jQ���pQ-j���y��4���<T����FIh�Ce`7�HZ�%x�A����A��/H���b����W���"k1�-I���J6�W�}�n^IJ
s�D�$#�������L�W���^���QLT�������?�'*�<��H���p�G�F�tfYwn�H���@WCs��>���I���q���d�
7��+�����������Q~��q���R��Z���.�!x�|k�U���[?������n��6E�
�W)I?�U�7��-�k����{r�|*�C{xM�8���N������G���S��N1�u�*�G����Cn����q��W?�G�Z������s������n���'~S���yO���=�������5����CJ
^���@�����K�:�UOZ
6Y����@w��w��@���:t��6����v������#�U��u��@�9�|:�a���\����:4�?�z�@��k$x����,Y�6�L�I0���)�/�V����K-�d�5�:0��k�mQ��R���E��Y�t�?��-�}�k��T�~����*�^�������iI�_�$���P�Z>����u������;�7�u���������{�9P�,o3d�rj/�~<DN)%
�U�)��Q����N�[A�A��pJ!��h��|�0C"|�������]G�Y�����e��a j01����J
Q�oP�0u�����/w�N���ko����N�+I'��JRV�.'9��-/��i^�h�i�%9��I���������������������!I�h��;�5�wu����q��N2R�*�L�>��~������$w���������ts��u�#�D��Pu��F{5X�FT��k�� ���A7=|M������*������!(Uq����v0-�\?��@��_p��7��@�����
��B��u ��u>��v��+p���C�����P0�.>�P�CA�g@`$��
�B�A��A�����/���|��WJQg[zH����WjQ��r�mk^�Q�[jQr'EI��O5N�k^)D�������_4�����'^��t�J����UFg���iQ�����C]�q���X���)E�q����R���������Hd������Z�nLE�:���V}��?�|"����'j���J��'\x]�~s*����0���r~�����L�8}|�W8�u����V��IUF�p4_�V�s�b���������~���`�w������<�}}�����qWR��A�o
7&��hQ���{}��r_��n��rdB;�_O������Ui}V��3���|q]�]7g�x�W��Ev����uR�hyJ��4�l�NJ-j��$��>[
n�w�M%�Pd�y�� j<x�4�3G|��=�/��F�q��e��Z���E	�:|���>���������?iQ����PZ�pJ�]
�x��75�g�|-�l��K��>����cA��u��cc���&�Kx�wD-��
�zt��W��n':��on�+�>�?���f�$�X�����@�����F)��9��e<�Ao�����������XH|l�
o�&����`����u�~��~`��|m�������q��r��B&�K��m>H�F_�������{��������S�bq���������<�%Q��kL��Q�U�8��iQ���p:-j���������&�j��Pu��u����
��D��v���d�RT�G�����J�}��JT��@���j����V�v��&S����#iQ���HZ����
��4��p�=<M[5J&��V���p�_�J8�i��>D�?�}n�E�v;-j���y��4���'%
�G���R'���>=�� *\])��[����_S��DZ�}
D�c�"I�^���Fg5�����7�;���g��F���~g`�:}�g��8Y�)E�(��������@�L��	��9-��(:4����6��56����5X�n��cH����L�+�I'�o����O%Q�(IK��	����u�Q,�Z��+}�����jU���8���0����.3�:;M���z�p3���j���o�>��[Y�����K��$�r���+�p{��Z������K����K�K���S�-&K���@���)��*}w:�j��'�N��-���n�����p*��4�H:�_�F>o��r�IUN�y������S�^w�7����,IbU���w�������e#�����9R5���V/eG�W����4W#M��4W���H��������-�{�PW#U�,w���@#��Y?>M�?_�|�"D����EZ���p �l�)��3w��U���k����Q��5��,�&����G;�
G#U>�q}�~���/1�c�����,$�k�F����wC�/h0����C%�P�8���p?C������59�i`��q �5*����^NV���,��U����6����G`��g����J���C�������?���a)\Io�IN5�l^EV
|�/����O������n�\����Fs��kd�j��VE�"��������3�Y��y��hu>Pk��}3�������OiIg��Z�I�QII���)\KK$|
���l��������r��]x7\S��H��!�^��H5�A��Z�I�5XT>)$5W�������'�����;��h���H��Gu��D
^.��@��������I:�E�De>�J\7�p�w��Q���y�]�&t,����Y5������@��C���o�k��6�=��E��e��KK����4�R��>.���oEZi����("QG��j��i�s*���UM�����Z��*:��k��nk��������-�+��o���e�	W���h��K�W�9���@�A�p%p������w�Yk�W�Q��������<z�MY>�oe3�c+���*�'>�<&K�*����
 -�lHv�z���@3������At�%s5u�Z�:�,��w�y�2��^GVAt�RC��0�Y���h���'5Z��L�!9�������Y=@���Dl����J
���w@m��O�j�|��+l����������gx�	�c�&��t�>�c����������+M��p���n�*'��@�o�&���aR�$giu2�;�7�<N�x(�jj������X	����v�U�B�{���U�_�
���x=D������nt�C|���T���q���%��\���!-�,M)��<�����)E��f�"�8p��)��U����%�������p���S�;��>}L�??�Uh��z�D��6��4Su�J���K��*���~������V�`�� ���|�0�Z>W������`R��S�o2	_���i��������N��IQ~��G�#4pp;)��l�-D�y+ln���;����y��@%�Gy��(u8��}���dd�`Z�~��h���N2p��7L�Z?��4�����``����@�{��u��:�&�M�������,qn'U}���IQ�g��[���I��9y�5�%>����nN'%�>��@>��;|_�.y��>�y�B�)OV����>@���y8�5������SJI���r`�\7���R��@vp�6=��u6���p�X|��2�1X��De94wK��hD��RK�gu�I��[�J-j�P���Z�M~ �v���4�?}�����j<wI����@����R�2�(�����������y�p�O�pJ)i�+�P}�u��*>&��^��|��[��/�[���l�q���r��Q�?1c�]M��}*r��#c����t�����Fq��~~�UM��*�!�p:�o��'��?/q��w��_�$�'jI'�xA�y���n�o�����N�#�Q���7!��?��B0�P~0�*$_8W-5���Ho��^�����<�zB��Pyy��?����� ���P�?cI���l9�����i������;gF�v�=������_���7Q���1%*{7�iUn��w�s��BZ�������V��=/������;o�	?���{j�a�V�4E���b�y�@)�y����r��0-���~_�z�� h�������~b������\��u����|�������c�r�S�~�������>���������N�%
��{�uA�Cq�����4v��S�����_������)���T� ��k�A�t���%�qE�=\Q��}���|������=L�S���[���oG���?�/�Z���_<iQ��������:�uR��y����s������|!��o��u��C�����2NG�?�Uw}��������pWQg?�H���
-�t��:�� I~Tv��A���/�6���.�D
���O��S������u�/D�
�iI����C-j0w���;|[~��<�W�J�=f��'}�L�� Q��5�D��q�������Nc/���w�Q�0���%����{�Rc5@�^�I�{��~T�r>������z�P8��&E����c�Swz�.�O��������6}������Vco��k��6�N�����NJ:�BR�oN�9b��\����|RI���%��IF�������CRd t�-9��1v��?�� .f�v��.���y����a��IQe�y�r�ZA�t~��{g��V�.*�=P�l�2��]��Q�-4��~t�����g��]�]�:)*{*��h=L������/��iI�S������Q@8�P�r�:����Q���������L�����Z)*i�
O����������jd���$94��iU�%���#����������o;)j����G0����D�v;�J64����>� Cn��:CN�*�V\���N\��)Q�]T�\�D������\����P���:��`��H������u��l�h�#<Q��D����Pz���9���W	u����C�[7������U�"v���}���
��|	�����|�D��/-j�)(��v2'M���6j4v�EV����m��I�_����iQ�mG�jZ�p-���5�T�jd���^�������y:��+�#�NNV�n��h �{�J��:R�P�����+JU�RX�����o���O�"u�_?fL��IM��V�(b6�U������}�D��������G��������OW����E<
p'[!��CsG��	TY?/������#�����G!�F�|��n2Ou��XI��r�����8K���Ei�K�q��XK:�����]!�tH~t)���YUVx����*�C�JTs$�U��
?�������N� H��o��O�dG�u}7����N�u�JT���N���x�p*m
�!$R�S$i��������R�O�������Q����?m�������
7'#�JT���A���u���*���H�r�F�+�LN*�F-���~`�\��4����y?
X2��NU�-��0<M�r;�`����w�p5��d}X��]���l����_�JT��~��Vg;NI�i_���EY�*g�A���A|4
>`���
�b�Kx�X��FP��������W j�9%�OJ��g�u�����������B�`���3\Q�w���:��f~��"��_��)����SQ���� j�����:��{�-���� >�����~��3�gFx���<?XD���Q�.~'E���2����p7���� ���m���:\����>��t}���P����5���FZ�t75�qw���9����^��;5~
��	0i`x�����E��5#�;�O���)Ig�H��#��)I��O�4:�>|�/�9����?)'���O�]wJx�uv��/����@�����IQ�'e����7���:��Q�@N����R������S��^������E�mm&Qg_oZ��Y��S���������:%*|���W�����M/�(~�����)j�������u���g�;$��{���k�"$����w�J'r��������%����I�!��t�@�����I:x��(��&%��3�[Qzyw&���(0ug��N;���]D�������I�!I�o/�m�g��������e��������dj�x(�|L:��zS����cZ��� -��K�~-�0��[	z�=�;	�`�9�C�s����<P,�=s��[�Y`�m��;�4����_�Go>�_Z��T�_R�p4��K[���,�!7�u}�����w���>��\��~'%�V����u�>����9���R�����>�P�gj�)�3�����_�x�3�]gt�y���������,�s������o�I���L-i�l*<~!��3��Av.�L���g�u��m�<����=SI���~��G�_��_x��D�	��������_�Z�����m
W|�~z����{S����_�o]x��t:d����G�w�sL)�,>KA�w���������-3�����c�.�
�<}���-;yA���|�	A�/�������?���II��^&�}�iIg�L��f�=4���i��z�6np&m���o���5K9�������N�y���n'%�����#�;m�h{�����$��ucU���o���m���v��h1���F����iIg/Z}����u����w`�I�#�N�]�-�V�_�����$h��f�@'�j���+I?b|�'u��z��[i�������@���o��W��N�x�W?7�}������#l�����>Ts6m�7g�?9�`rg��!
s6�4x�qg�N���N'Y8��r�O�q�;�X��K��{��t�^?��e1E�r���~Y�j�NF���>��;:���`�*�����#xZ�0��� ��`��R��3z��;�&`��S.HiT
����hE�}�-�A�lJ>���S���-h�SZ�Yr?��F���"g��`����;����q�4���]
��?�����o��e��4���?����������_����}���������l��������������<M����~Y���B��t�v�����B��t������-��H^�+�y�X��/]���|}.��������s��M�t�^���S��I������.�j�/�������7��e�/��s��o���v������/}���������n�~����6�����}]�����H�������&U��^/�}�\j��\�y���������W�~��i��O�e���k�o����]������&_{���}^>�����i��n�rYn_�K�o��]���w�X�3�vz�7>����W.��e�nK�o�a�/���g��w��c��M���z�L�����X;��y��(��|��?t]?���I������OW����k�����R��g�._��C�����?��������9��8�e�������������r��������1��������������R0��p����q}����!�������y�7�z���:���|��|^.�U��[�y�'�x���2R��k���V���]���|���S-�������v��R�����r������_�eY�oW���y���;r����.w}�����a����2����]_���6_�]��u������Z���y��*��z������_�7m��vY�uUy}l��zy�2���}p�A_��e���]��Oz��^��Ea��i��#����
�W�t}^Z���>��/����u�>����or\P������������&�ZS}��)�n X����^�y?OB�m�.�U���!oo�Wy����2�wX��"d�����~�i/��m�{?�������L�L\�ev�����U�u����Q�)�:j��~~a���u�Y��S�H@���Y^)r}` �?��o ����l�:���B����w/`���
��o�O���_��@B���J�P=6��,�4��������J����\h����op����C����������k��?��E���$d�4�D��U��c����c���;�h�Z�m��/�F�����_j�
�-�5'�Pk�H�l�=�2���h"/v�����]C�{D�>82���]�dT�����N��g9��FVC�D}�T82��pC3dd�������Oo`����k����1S_��t���#�:�Z��
�Z�Wy'���R'	��b}����7p�O��>�p��Wp��Q�_�
��=��Q��bp5p������Z������Xu���Gy��g��D��X�N��#���2�M�Gb��2�_�����������nsp�cy_}g��tp$kyI�G���zY��|35p�����p���^�N��Q���Nk�(�����8*��5��������������Sp�����\8������Q�__M������o����g�~
������#������c��'�8�����pspT����
Q�������V��J� �Z�����Pe/�P	��R���"�[%�Q�X��8jS��R�7�9�[�G�p�c)�_������1��k��_�\<�
���o|�����]�����%E����@������zV���KL��k $�>��B���|4!Q}����/�u�`�A�h� �������/������������@��[�������h���I�����88�4�1����?�3s��.���R���kd��;����0�RYQ^�����z�_��#EJP��~(RjkE(�_�w�,�R2��H8�����6����?;������hI�k��8y�.�t�~
�xu�du���(W�����\�&y�L�=��n��RH��i��2�ndC-L�����^���J-�1�X/[
-�	�r#�����r��nd&�[*���������w���V�]���`*o��1�`1�
��5 S>����OA'�1���|\��r7�H���x����Obj�nJhGLa�!fy��J�������-���=�P���`����.��d=
��R�L8�gyL!x�����%],������z];�3�����zU��f�>Y|u�����Z�j�ux�_?�����mr��j.AH�C�f����H:��p��X����\�Y����
�
:�/�K�d@��b�W�2��A�<����
<�Y�e�y<�K�_������e�!%|*+f+����r��NZzG�Z�����0�� T[�O�:/��;9���.kk �$T���8����Q�83]�D�{QAt.o�,{�E�
#����v���@��2�3������So�dG��'���)|��-����s^~~c���X=�W��)|�%���5.�Y�O!a.)�W|j+�����j���r�����V8|�%
����%U���
���R�OeEy��Y���a��2#wO�C�@��W�'������`��i��O��\�����G����Ox��5 �Ox�lXU�.���M�O�p�L$LpM	�;����_:xj����<�)%F���]�@�����\+ mYJ[��C(�b/��.m)�x�[�A�r�Z�NrjB��K�o����~���MJ(w�`�� ����p�N5�vl�)0/��6k&�U�M8`T�a�L���aT���P�0������XF�
��u�V	�dy������4*b��i_���b ��W���������
R��R%��9���x%%���n�_���u�0��i�'�������f=��8%���,e���1�S�>����E��h�L��8�T������	��-��48e[v(�npJ�<Kw��3������{����/�{��������/�T���Bys@�v�����w��+��Z���iZ��ZT8�	{�}��w8���d�������q<H!��q���D�v<��G^nQ��U{��L �>��e�QCT���M���nN\����$X�����c^oQ�YQ�#�8Q�_Y�r���;y����3]o_��LJ@�S��������T����@E=�,��Jq/������C)��KkA�M,Y�K��&#��o���#�:���:��}Z��UI��.�wCW�|K��.���l]���=}-b1����n�&�������<m��/{���.�������H\���;Kn4e���J�v)��=dQ��S��m�,���T�P�X���$�~�yR��]�]�Y�<odU�?8+��:���Aw����U���i���
}5�t�r.�[���vW��7����Q����A�,���y�,������/��zg� ��ZD��M����Zq����z�k��.���o�a�c�{6m����/T��������U�=ID����t�K%�H��Zg~�d
v�u���i��������^�M��(�n
��x�>OkE�y��[K�#���)@O*O��z��g}6�������=�}�l�{q��|J�6o5���O�n���7w�hO�@?�^cW�_����?A1\��IF���@`���&�,�L"j��6%PM)a^���--�K��%p��xB�q�#��,6,�=��U���`x�/��?��Y�����J�T�O,�J~�/UI���
y�4X��������K���J^����`���q��	g|�=�l�������$��_�I�hPE_��qe�`f"	/yJ|	ZL��m����)'�1L/xJ�Q�����})�'K
*����$���i��x�z���n��(b+W������Vd�;��8d&��BqK@&�(A���&9Z��
�\.����@����<���i��H�/�M!���E2@SX_�{��!@SK��Z8@S���l
4�.n�(��m��f�@�l��d���!��
���L?�I���rk����M}	R��������J�����*a��'~@5�(��5�R�����	�)�e�e|\g�^�!�D��>7�L��"�O�aI��Jx�N��Q~dC��&�c*���4���(�� `��e���6�H	�������+����&h��"$L�@}����q����������R�j����)���B��KO�*v��!�y<xQ`�'��9`j	FX��:H�*>S��f�)`&�@uK��
���A�V��H@����UHY��Iz�zy�����j���>�L�Q*O�:`�Q��[&����<0�z�&t-c�^v����d�.�W���������L^�
2�����_�����~�5��5�T6x��������<��A����+�wL>���7�!S�0[x;
�J	S��
2�/��2��!S>I�m@���"1X�Le�����4���'�L!�H���# S���H
2���j� r��L�������Z�+6��S��:����ga;
�P:^��R����K����� ��H����1ceQC��`}��e��������c�_t���F�D�5#����TGg�����%���<�o,I���7�-�8���^/�{N1��%G5���mH��L��#��x���G�L���w�,���wF���TIX�.3��l����g@�n
����g�����AE�|��`;��f���y$F�FqWo��2��Q�+!P/���(�4���]�����j�Z��\!��g$cO@�+�(@_h�J��c�]��W�#��A��7�HZ�.U�=3`Uk#��eXA���R`2��"��AV�bg~`V�Q_�9�����.��Z{���kV1'����jC�S`��|%�_X�Xgnu`�#yp���0�|C$�u`�2���*7�a5}�2�����������-y&�X�;kMi�X�W��u`EK��u0�c����at��$�LF��l�)��^����k"���dK����_�.��Ls`��}_G|r�������}��k������8��UY�]���o��-��[EVm���������7����H���������DV�\������+X`UG�$
��}%
7M����BF���8�����
�����-��8��U�x&#.�
K��(pX�5u�Rqmk�1���9�k����*�jl�����jsy��OCU)���umYJ�Y6�;�e�����hKm��Pu�k:@������B[1a�P������!1�:��es(DqW�%��9��%[Vo��
�$�K��p&�������WB�������"���pUbP��
������W[b�k��"$�6S���V�c:[bF�:�
-6�M���������6���r�FST�{2�.@UH��&�:���YE���*�����W��J�52������1w\=�7��S>���a ]p\��(�������������bVB�U����Gp�/c*�r\���Q�(	�A������Z�p,�z���WYbW4�G\�gD����pU��&j����i	kM������ioPM����-yY!
��<0��p�/a��?�;�*;�����B�����b��l*T,		K���&;���l�{y32V`�T5�'W�^8����
T�"��'�U����������[RU��:;F~6T�[�9%i��Z�z���U'E8�����3�s�J�$@� �k�n��#7��5�0F�;���<UfE~M�f����iW�T�\����o�e�`Pw`)��_�
J��^c<���S��2�)_<}��~�����~�hW�gc�#80�/�z�0B�&X! �*A���qc
�j�O����D�>�ce��D�����0�zYx�����[�)E<
k
:���E'�8�>�w��(�pJ���P���M�z
�X��m�Srju�R�t�e�h9�kq�TZT�`�p�����h#��*Kb�y
���O#�����+��!oP}$��)����R�ij
2��HC�%��������>TK �(*$,'�aTH�J��g9�J	�n�f��*+�gQ
#�T����A7��
Z�������%r0�|PE�$
Z
K�E��)�����	d<,������~����:@���Q[���8�����^�>� �vWW4�4���@T-cJFn5D�[�xDsQ������rCK����<����{u ����P��J��20{Fb�~i�/j�q	N ��1�PZ����HB *���j���	��*_!���������uJb%
Q�N>�1M��R������3BBp������:g=����BHm@����C�����D
$mx�%<,n�^PAF�o��p *Y��
m�*e�w8�Q�����&������%����1e,H����Q^�{�h�
Z�i/P����e��V�L��%4=�1����a*	�L�,>��SA�W�B��c*l�j�i-��$��Z$y�{R9��A�Xi���b�i�i-��`����*�b7�U�N8�4�:�
Z��@y�<gW���*�(�D��b��M)���zi�����7��*�x��.��\/��N#�hK�e�q�c��RY��3���Kz�
�>&M����~[b�������.-��1jyRa�c���������>;F�����g���0��f����}�����\!��cp����f�$�������<t(f����H��c��3~���>;(��1Z{�<��c��!���c����g���y��X�3[V�S Vo���������z�n�b0�Z"��1oGm�J��e�`;�vX�`2N�����L�K/��K��R�������`(���L�C��^�J�	8�7��i/��!i������@�`��'
E�Zy����ca��!XOp`[�����p�0T�W�i������!�����&i
0������j'�{Q�M�!����9�w�M�[I��V��`H2
c��)o� ��C��:A�_C�����R)���t���p��.���"�&�]'k���a��	6TgM+_��`!����4H��_/IX���z��u��M5�����5��9�������z34K��������v�A����
@=a)Rz�I�n���|)��Mv�����l�IZ��e_���L�AZ�\�������&���y~�����:��m�F���h�y��_���a=�R���$�(_aP=l0�z,�!?���r�v)YR�+m���l@�����0 �u��$G�:Pj
�L�@)%$�f
(�
	�S%�d�P�
��
���#�R��'<�Z��1����(6��l�l@�I�&���#�
��k>�RI����
(��� ���>������%��s��:"��x4��A�(Y�����cK����46�y�����4�$�X�B&��<�#����i�R�d��V�~�2�og-�}	6�k�!S����9��dJ	kB��)m�z[2��g�_d�	6��[���lHn�������C��%���n)m���B��'���)waK��dJ_b���L���ie}��32�d�
9����Q
A��!S�TC���$=jUL�E5J�*|�8d�)s!E��t��@�Q�&����#:h�~T�����2��w#������c������rG��B�}��w���J�|���5K3h*�"2��m�y�j��<c�H�����H��B��������������?�@S�P���R8@S<I�����
4��W��T�4�������d�h���En��&@S�`7�4��[���n�I2�r���	��!���Vc��J�I2�Jw��&m���"��G����UM�c�����9�2��44�]���A��KW{�el�RDe��A3�7�(���
y�:�F�Rmm* bNZ�KE�����&8��n�I�'F���;����alCl���Jf4��f��U'e"��x ��Q����Yt����E8��=�R��Pr�����1����b�)�<�@��������>e�<*�-���
0U��S�_k�g�E"����>�I"��*/��R'���m��&	�j�Nv�$3�E#���o�}�Q��������c�
7�����(p�e<ch��pr
K�g���
:����-;�%L���S�I
P���'�q�M��6d��z��`H��m*-�[PA�����!T�0^D��s���%���j3��[<EA+��o��Q-c�rWx�Q��Z3��R��GN��#��+#�P��.�XJV<yx��T���p�
4�����6m,[��!�
�:�H[J������v�P��d4����
S�����]	%����UTX`��:6����dS����!���e���6�-��]CTa��z�Q�U��5)��6d�AGQ-��]++,
<Uv����S} 	W������M�������7p)%���x���b7�E]@�x��s��4���j��1���TiQ�����]��<��QYD��Gv��c-�"U+1����7i��el�]'�"[��5
Q[Fj�����w���~�m]���f��_mc��
(0U���>���j-������B�nT���#*������i^�Q�v�
����w���X�4,���J���������H�O�V��OC�v,�p(�3���*��5N��9g>h9�
-6�v����J�U�C�������)�`*�X
�S��1�3e�C�/-����m@�K�FX�7�:�����,T��X�e�[!B��k�N�;=I�g��o����G��j����e�{�C���X�]����ai������o
K�Z�FQB��}	K�6�0�I;�i��QK�/���hX�$����n*�����q�
%��$�7��K����0��J;j�`P`��0�4��Re�����ai_����u�X�������'�+��V�l��5�TY��:B��\n���^5��?��g	�S��G$�j������{9V�4,�2�vb���$�Q��2�X�m�l����~]�m)���3-��)��v��,����I����(!���J��H���(�@���B�R��\�TWZ��Z:E����Ho�R�WJ-d��`��4��j	�)�j+l��#j���;��:���	��R���d�*��<|>�LI���� ����[)^F���p�z	���|�UTHp&�'��Ch_F\#��;��KM$�",��A�6���P�C�����h�[*��~��:J�b_�D�h�l)/��2z�]����h� 4�������)����#4����}	�I�v�V�6�--<�;i��:M����aAX8 u���Y1�&
V$e6�Z��47 T�P'���[@(�%HB�O:�e�(�$x���	Uj
64Y�
+�N��7�:�o��7\��B�P@h_�h �E=��Aw%���s ;��(����4 T�Q�o��3�P������-�l)�i�j���B��y����M>sU���E�~@���N�
�2QGAB��5�������h���(H�Fp;����a�9����$�i���O@���
Iq�**��/BQJ��j	+��*���hu�K���r�")aO���*+&k��o�]	��j��E
B�:8��J�=� ����HU�P��FzR%ex�>������[(4�J=J���<
BI�Z�#R�"mK�a�o�v�{����B��r���'�Qg��������Q)a���Q%�n
T�k *$��2T�J+v���F��>$��� ��N�z'������b�����Q��A����8@���������q �|�I��M�ATH���*�+R�J[D��Mn��E��j����D�;.:?s�aG������(���d���!�����J�j8�j=����DQ�Zs���-%�����&
{�Z�Y6�l[��4��p���f������l3�>�m��=��I��8��/>�Eo]|�*����8�~����S�n��|��[��'U�6������>�����l�K�8�8�f��8�u�4�q.r}2������$�q.|�P�j�\���y�����i��|����������C�N�����3(&5j�?-�%a@1o�60�����#a���g���Aa���o0����{�L)�l&����j�%|t��A�P{e�$�BT>��~}�(�&�7(�u@�����H�
��;3;����P�[�C�\���C!n}
��t��B����l�Bi=�D9��R��C�\�`�!�P�=��;����@�~�B�^��QL���d��t��W	����r���168���DUl��b��%��;��N
z�`Nkt��G��Ft������jR#�+��x�;����96�LP"NP���\4^kA����w=��'@=���hL4�\%��m���h�t��`\@7D��p��Eo��3Uo�=x�����	4�hV$?��-@����tP,��}yy�t#&�Ga�UyB.�a#j1�+4j	uz����%�0����H[Q���>P��:C5����xi���x1�P���H�Rd��|�W���F��NcE�F�C2���Z������9ux�������5���H��+�)mx�7F�H�������$���
%�7O8U�����Qp�/O6@"������R�]H�0T�
���aew}��&����
C
-Z��� �Ka��i�m*R����s���x`����nR�F���%�_��7s��Y9�_e�F�������y2e�R�s���
�5�)mX�%�N�V:$�l�r��vNo�p��0���;�>��0�9��N��`J^c���I�pqZ$m������
iI��!��9`��	��L~�zL���,/�]���P,���2*�]VU"�:94��e5��d��nd�0�������)�G��I���{F�.0�4����Q3���%�ki���P�i���!�/����jZ��u���)$XX�|5��Kp�t����d*^W�>o�����V5�T6���!S��M��!S���6�6=�����YtB�2�
	�H�L�`2���Q
E���6�����z��L�%��[����8 �(Y�<$"��z��dYFmH!��t�l�)d�v�+y!��aY�c*AUy�
�$=��#h^��U���l��6&�
x��O��M���oDQ2��,
���A:7���B*%�[Q�����0��+S�;7����$�E3v�?GPi����
��;�{,m�;���y������f��O���3���)���if��bO�S��%K,��vv�%�m������	�.T�Q��%
9�JKj���v�U�(��3�sq@S*'����2�
� ��t��yN�c���R�*���tZ{]�<G<����������*~�@�=�
-�.�J;v�a��k;��(��vdT��]	%���~T}�������x�q4@fx������x%D�
P�q,�:u@�(��I�qT-c��}9����A���$UkQB��Q��e�IeDT�J��*-nV��I �J6�h���d�'t6e[��js�y0��'��jgJ
�J6cG��U��Vk��������my������'��m�_[*�X*���/�Y��kp*,����i78Uvx�����j;
>��N�������Sy���O�VCU��}��J���(p
ne��\3m��c��Qq�e&2��M�:����;M���^���'��B�����jK|"�|��
K�X����J�Z�Q
q�)�0~�MY�>@+��r-���������y
M���T��
M���fE�P�hJ�,ufsz=�2��i���x:m�ih��X������*%��{��b���Q�y��Q���J��	Oo��\D ��c��Q�vU��fCTm�
"�B'GT}�i��c�B%GT)��@GTi�M!����u\5�����,BTa�V�pFY���l��)��q#�J;|4q��B��������d�Wn^r�2�_��P���&}��u<5�+���j�P_x��R�{�~O��i}Bi_��Z�5��Ns�ip��\='����HK��&M�|	���
l"���G���a�,0Lu	,UVTv�����|1���i��<��TXQO��J�Y<�t�����o�R�P����D��a��V5���%���M5�V0=e� �i�����h����;������)f�@�7@e99�J����v��N�w��k���R�Qa�{N�e���������^�K�@�\.���!��u�4~9����� �	��A��`���Z���
j1��[O�=B��2�:��V=�q��><�&���0��t�Y��3Y�|f
�$�?FB��'��P:�)!����@���T�bJ���}�!���x6�A��Ig���>O�����S}���u�^�Sf
�vEKJa��!([�u�����hY�����r������o_���?�`B��-jES�A�,���,
@{b�G>4X�������9��n��7�:��}���� �<v�cL�O
:�	v����))��
�T{`���/���)Oa�Ht����q	�$(+������L����`b�j8	��z���<��!����s�n�hp�����T�')�S�R�;�B�U%vL)��@eTj�R������yx�df�]&V�r�
���J����0��RZ��t��:��I�%+^Ki�n:dtDZ��u�WM-�\� ��x�����ZB&��I:b��8�	ff7p����x���&x������>@��a�%P��f��YA.�aj�Z�9�Oz+����������'�hj-�E�������V�7M��N��g�);��z����4�e���$�I�<��0�5���������f���/���)�Q-a�xL���6u9e[�:X��D�fm *���MJQ:XIoFQ���.�n *���]I��!��@TK���������GQ��w��J+��i �$��W������f���,�I��aQE��O~�x����?Q�Ze�0*e��5�9����u�p���Rf
A��Q0����`�l�
DzEs�zIaT��2� f��n��e���M&xa��2��::�L��f��uO�,]�T�����[�����[����3�]��C�
l���lI���p����0��[Xy}��[x��l`k��c|`�/���-��i��-|v���-�}6�,q[]Dk[��F�q�B-L>(Vo:��A���}
���	�
�I����06$�0qD@1�R[2��)����c�b�u9n%��dL�V"�b�e-9��j���T8h��u5[aC��6��`(���������b�6���i-�b������<N�60�[7q���P+����0a���N�*�q�q���C�^��q`���!�<�s0D����C���P�v��*���]�������J�D�<0�31e�s�e��F)���D����#[*�<=�2�������?���n��Gi������{:�@WJ��r���Os2B�C�����������_=������MvH��@�$����4�����.@.�t� g�`.h�1[�s��H��@�m���Ml����r��@CV�@���C`*
*��d�L�Qz&�!-��j��B��L�&��n~�$�����\��Ub3	��w%����*�|"���������Vi���uY���2�?���P�gA�o�8����!��m0����lX8*��I6P��&���L�A�`J^<M��`bF;L�.}	��:���L���!�$L6�t��R��>;$L8`j��#L~�s��X�����,�]����G�L	����������(�TYh���K���|�r�L������`��r�i�'��^�L^3o��S��6�++q%]3���.���!�����!��M>�/�`C�n����lx���L��.�+��wac���L<�t(��1�����v*���������Iz$a�����-IB4�T��4�fJ
�*"�d�6dC��� ���� �<�C40ep�Q`&���C2�Em�OG��r�@d�9/9A�R;���,�����~�h�-S)��zh���aq)k�m�^��'qE>�L�,�qzU6��J(%��h�%,������-��
��6d
���y���l��� @S���9RB�&�,
4�fL�������b�&�@�KMmC�����2	:��@�o�n=i��~�m��Lhj&�k�)l0��l|�� 
H�?@��C��������^
��&��������.�����}�f��x&F�#&Y�"�bCL����cXn��r�v��������4��V����tt��&%�P�����c+�Hld,�l�����������������QYn�+]
}�S�f8|����5�:�-�����q��%��L5������dX)��D����e���8-1�	��7�[��	C:��"�������EY]�0gh�eXI��0	4.�DG3���

j,��6��o���q@Ee<'�9
P�-Fs^[g2@%=�T*��DsK#������m02�L,}�3����h���h*t�C��(=��/�~�c���T�t��J�3���xqq���a��)���!�%q1Y�X_BE��Vf%o�`������vd�o�D�d9 ���xX\��8�J�dM�O��;�|&f������=�*&�S�����&�v�����D@gW��%@n�!��������)���C����4d���l�
����4���`���3�\����'����2����(��)$<����R���/3�S�R���S�<
9���:������)����<,�;��������GOy59?����U�	��T;�!��*����\u�V��o���B�5�1���&����Z������`�n�\�pm�$����3�����G�%���*��G0�]B��7������s� 7��$l%��?	J�{��72���%k�����QF>�J��t-�T��Q>�L�.EK<k%��/!f~aN�iW��&���*;�*;��BB�	y��
;l��]T���W����TG#}�7��Sy��j4�T�Q�x�}��T�1Oq��7��S}L����	5<�g�������};6o���7���|��`����i:)=�h����}_^M���Vi�<!����'&g��
4e�)9���:3,�*����UEZ�
a
��S�����j=j<Q���j=�:�9o_Y���vX�����j��D��"!�Qy]�fh���#���4�T��j%�����/�~$L�����}�=^�����^_���
+l��@Y���5s�XT���	J��1H4-�M��l^c��s�6�T���uR�v��lz��B����,f�}�0*�N����K���_���V�KS�2
��B<��Z�^[��.�R7c`�
��3���'`T�R	��F�h�XY�x�2�v����e�VC �_]Y���3@$<��i+vc��*�I"7��J+�@W_�B�5�I���CB��
2f!�P8�����16\����j,8�R��W%VL���N�Dq�������!���.N�Z��YR>��C�������P-�D|V�o��u��B���5T�9��)s�\��h��.���(����u�h�
1���$�������2�c� TI�l�_�]	���a"�A��������Pe�kfb�����.*w��SjB�E��V�{@(�@T��Z�+!�s�����- T>����Z�?g�j	�si���O�A�>�'V{5�'�hB�>�7���klw#�\��@`�!�L��d�B����!���dJ���:���
�mo�I�����K�|$e7R���������;h�"
���g����J��D�(X��f�<�-���:d����Y���(X��$�P������a89�����4��h�Q �����$LX���oZ��'�d�TJ�y��"|2��4\�Th��C�@���YP4�������Z&����e�l@�7P>�O��aI@(ZRju�;��
����fb������DQ%�e�>imQ_B�@��YQ��
%��p����u4@TXa� 5[Q����X38�i,
V����;�dJ�Q�gD����D�NZK_JR��������� ��lAO���a�����.w�lF �Uo��~Z��I����T���A���X�([R���D(�I����(�������l��������5��>��Xv��l�^UXx%l���jb��jj��5�>�&���}=�����\�Sc�v#G�O�A�u�bL����
ScH{���ScHyZ�Sc�S�B���h��ScX�|j�Zoau�)`Sc@{�4��1���\��Sc�q("�Sc@{(���1��7���Scp���������������=��"��~�Q���������NOp�8kj����l��{Q
x��2���i�
����-Fzd�q�'2�3�@���^<Sj���%kJ�����(y�6�����8(�^�k=pP����W�;J���S�8���"#�A���X�#���xr��k8�CD�qP�z�XuD���e������A��3W9J���6p��_�A�uB�A|l4z���=��8(V7�#`XX��n�,���<�LJX%$J������D
�@�zL\��@�z<
9Qz��C��ie��*���K��������?��"vf�7r�^%�J>��1�@�9	L��h��������tG�������9z����1h�Q5N�A_���m�x��m��a��
��^�d'��qr�6"��/!�s��3�']������*�����M�3$��e�hHa��o�(c)Q�t�_lhL�Q�K���&�T�R�L��������������Tg�����tL_�%u,��R�~V'�h�~���t��`��B%��6�$m7e����N������S9Nj��j�`��GI�B�����~v6�1\o���BF�2y��.����:>���!%�Xx$Obrt�
d[����#J�d6&J��C#�XKt'-GB�H,F�p;��"������~Z�T\9g�Z�����H	{�;�*$G��+��_�
�
Fe#5l�6�&k�6P;k����_M
�INX|��Q�`{)�Q���B�s�`��I� ����MdO���/�LQR�0x�L4���pRK��8�R�O�iH�_��R	�� QFy�B
��e���D�p:We<�8�0I����R2#���w����hKI��wI��������W�/+�&V�W��8hj	/��DF4��%����)50�`�3���P�`�)m�Jf
4���G3�_��&�^����aKZ�4��w�A�m�����4N���E��eWKeC���.M��F��.4��
;�4�
I�AS���������E� oj��z��ZF]D"jE|^��2�h�)�{(�]`=6�n0��l��0����L�0�y�u4#m�\wX[fAr[�������(����rM$\�����%��G�T�Kl��Z���c�����z��V����g�����/�����xB�t���99�'���.Y����Y�_���c�u��0��q
�VZ]m�d����:`����4���5��;�.ZrMdXX��5)�v%�P��	XU�j�����Jz���X�"������Z�^$m%E��>U����C�*[�����DY���CF
V��������M�U�vv2���^��Y�����������
�$�
V�%k���o���#�����U��n�|	U=I������$
��!64%�2,\�|���7�8��L>?���V���Q����W+C�&��%��`�J2&�tl����Q�:�G��jWB��5
V�%��Z��%$����'P���*M)0�H�U�Q�o���mUo�Z��iR4����5`E��,����J��04���r�~�<��RSk�����#��%d=#�����&|�F�$���8�V�;���Tr���$��XJ�44F-�	�U�'fG
G��3r`�K�\�4�$!��:�
+��"��x5A�{YU�:�J+�����AK��y^��D��>>�N�g{��]���*�r�5*-�:|j�S��6���&]��)��3�D����,��Q:���\��Kp����^�VW�b|��^
2����nD�2vu��S���%F��|AK*_a����\%�����d����K���
K�!�������h��{)Z2%���}^�7l���o�����4=�|����3z��4�N������'���JK�Iq/�����)!
X�2Z�����j�G�EMLy�TRV4�D�5{��{��w���l�V�J����Y��hI	�fM,��uY�"��7��U�n	7��:�j9}�k_F)��{V��r /�+Z�3��+X�#uX�3��0`��D�X�!A)���X�Hv$�`EgAX�%������_`
`),:��g��oAK��"��9�����.�U��f+�K����P���}%/O�2Jc�����F�!���d��	�Iu`S���,V��Y�`2`E�:*5V��Y������.�W�YhX��?���R��dXC�5���X+�:�7`%-&�/`�������da~�V��nm�Y��qwO�4$���J-<a����c}%�|�����Y"��VbK|�+��
��}/;H	{Xl��U�N����'�;��};�Z������J�V�����8��e(F�S���] S����-����AO[e�������7`E[��'��e�~�?d��X�������
X��%e,r`����h�p`�Z�F�������?X�%�h:���$	��!YR�>�dbJk��6`���1����o�\x���U*Q3�`��j��e��g.��Ui��\uD�A���d
���A��d�y�c�V��5��t�h�;F��<�J����3%j�tq�P�2*Q6�L)a?����U���%����d���~
7h[J��2�n���8����%>%a�VaC��k��:�pVI�'�	:��n�P�f`�c*���E!�$!��uDUV�����^��i�/�XCN�fl6�J�M�
�����L��5�;2,��0��i�R���.��|9�T�Xm��cReF�^�����r/T�������+�r������9|��v1�����(���y�����gt5K`��b�]�{�����c\��^.�*�P���f�m)��?=!�������uB0�O
��i&��&d�{dRY�IZ0�@�M���>
8��S��Z��&(+L"	@�NmH�5���	|�6���x� ����%[m���Z�O�����J_P!�Y����/����B�V�L�� #� ����T��	��G�Vk0����u�B�F������hJ�"J��d�%%��P�)5���^��zl���h"a���~eK*'��5���>���'����t4�vt:��m	�u*�Z����&�/Sa�����������-W�T�u��T\O�E�
�������P�eSax�.���0��f��Sa������_�������R{�
��_�F�����3%�T�>�
#��E���M�a�u�����C�O�o�B�Y.�z*��0��+~e0,�p���N�`�D�� ��0�am������e�3 N�c���1����������$��F��uV�K$��b�M��F�*�WL�40�����iz��uB�R{�t0���Dh�!�'BC��0�,���F|���;���o��!<�/60$��G���@?l�!z��Czh��5��>������	��
���������:nE����hK	�� �}��w��xS��R3�_H���[Pq'������e�s����GvT���7��]'����lcoP
�"�A�����R��D��`����J	O����
�
P-��
ZBv�t�^i��g��$�L�m�s����	z��&
�8��O�Yx����j0�r�D��g��?����Z:-��3��,T�h���`V��lh	2
������d�Vz�5\�����S���e�6�3�'�-��)# l1����(�����v�n��t@�Z������C��mKhBD�!S�`,)�=�0s)�C&����:dJ�+"�Lm�I�qU�L����$F�����!x�@@&���:dj�0�����L�%$����%��p���!�i=�7 ��>2�O�r��VT�����!�d���T�kL���:�wc�$b��������sI1��[���'��<r���r�:$.9I�ZDd��4-a�ZA3�J�&03�z��l����GV@��txr50S���a�u�T�`����tH�&3�/Y'L:lXp(A�Le��D�
3�'����%����I�%���R��N�����v�L�
�f�5p���2m�����z��L��Q0"�%��Y3qd������I����o
�$c��)d��<��[z:S��~Y��L���+}d�$2���EVu�� SH�qWydVi�S*s��6L�U�%8d
	�E���i�k��9u�9d�.���e2�/Y_����D�4�x@�����$#B��K�L)��B4��A���g�dj
�l��Mv�����Le�5��<�q���� US(`���Y�(��D� �N�>|LT�V'�QY6���(�-����&�(���"L��U�R�\/����7���O�)�'�h%f�\<���d�`*I�
+�����y�
���d��	���'V���L��'�!F��6��!;��y�
9��HV��6���?oX���L���) r&]����I[����"���D��
+$���R&]�����*%���m���/��Q�3�e�%)��U��K�v`p���y(�Q���!����9��-�J�+�(I�X'M�km0�P�5�U���k�K$d83��k�*-���X�%�����-a������X��7V8�$���Ub_K�}������k	`��u�.�
`�G���v`U'���UXA�1����I_Pl�J�0oVVu���{�S&]y�>`0��"-qB��N�%�'>��ve|�����T����nV�u�&0g7X����,��'[
����`K��9��dK	4������l���V�k���l'�O��X&i�RUe��������K�'Fz�����L�����D���&�;���v��3GT<���#�v0�F����&��O�S0���"����4g��'���-GS�#!o��/������R���^����V��_����������8��!;&K���"�p,�z��~[�&�l#�E�-�����-;M�,���UCc��b�4�i���
1�	��L�"l�����=x�l��fx�(�"�������R}v��.�p�$�H*��&�:��C.|���)�T�u@���o���:�
(=�`�������0����@Q��
#l4��w�)9����*#�y�~��B�?�6�<�f-���*u���G�`~�s����i���)���@��N��	f�;hJ:�FLPa�`�Xr5��t���H����q��7���W����}e���Iv9�����:�h	3�vJK^� ���-��	]��d�
������N~�����
��h[-�TX2{�U��C���a��p�t�vT�E�OQ��W����@Q���&���Qi��~QW�����i�)����zey����4�����S�����t�������e�6�e�(�;���kmNKwA���Y�dK�)7Z�U���Kqu��e#��]m����4\2>�si�TX�z����JK,��W���������>��
g���q\���<4
W�!5XN�x���H�.O���H*�G�U�H���j_�G�k�H�����9�l\�����E��zY�I����>�G�"�pU��!���};H���)��	����e�90�\u�u>�������U�<
z<�����:�j-�
�f���e_��2�4�)B;�x�<[:}	��!L�'#����T%#�H�c��e�@o�vLEKL	��%���R�T�$a�pL%K��!��x$5���z�!	���!O�6�wUm�u��2��Ta�\;4���1U��}��N`*�HF|k�*d�,$40vT��Y�3�
S����;w`���V-jrL���Y���15��x��*�33�F��e��#�T���~dWU��47@�[�*XR������� c��F����2�f��[��oV���6��Wx:�[��P���j�����|<��������%V���"IK��/���%�����4�*Z!��*
��J��8�~��%�^�j���f�����j/��|���v��i��f��W�O�j_����y&U����p�SXE; >�`Uy�A"%2��8E����*��r������Z�2o9��I�x���U[��o�t`��]KRD����bA�D��-�R��*��g���r#�Wg�T!#�]�z���QK���>0,��W�V��X|~�jK���J�LC���#����TmHR
�*
�+LeqL�#)}@����d��$�Ll�����D ���j;j�@��7L��h%Z)�<�����1�`��L�m�*��NX.�0�o�s�T�WU����H�j=*?,�L�j[�7[����Q�(��jK*���Z����l!
`E[
���JdKe���f����]1����g������ij}6;M��XR�:.F.��C6;Mo�������)O��q���!��0���a��m�����@e�b��[RU��$�:.��d�����6.��b#���3������{n��EJ6.����b@{bs0$V���v���X�-+�/�:���k"M)�v���A�1B����������8����U�Q?���40\�tM��4�����H��X���8�����P)��Z��j=���7��9��i�<�������Ry�>`H~�����h�$C�80(<��o��
�![�k���C'S�!����Ce�������;�}����y�k��w���uiC�e8���H�L�09��L��m�4��@��<�������y[@���r3~AL@���K���O��>tK'���AJ���+}�3�^-��xj$���������`�"���7�����l��,=V��6��'����m�O����I��q6�7&��F��6�d��s
����
$a�����f��5��7?���J���������m �#L���*n��������Y�u�(�&���q-������L�am����c+<P��m�Q 3%k�=}�������������>�
$hJ	6zB�9h*	<����XoC�}��������:h*�e�@S�`��4�9<y�k�&���M�A�lh�/�T�M�O�m�)��J���@SJ�`g�p���@Si�[9�N�:hj�f��&���J��5�y���4�PQ&�&d|DK���!�D�G##h@%��%�14o���� Hf�|aKh�j�K�d��������-�MN��+=�O�B4�����x�z�����]<�0��������Q���������5��? ��'cQ��B�����8j����A����G������,��5�Y���4X�(�[ui6QT�S6�_�p}CX��
���(����p�� g��P:���0��������AP
0j����T��@��,�u�Y9
��0�+���cS�#	/�du����u���d��_Y�g��@%��D�`($,^������^��]l��B!!� P��|���?�Cuv�J��R����)$J	O��KA�AX�O�fm,)0*	�E���(m��	�Z�(K�va��/���d�|@���!n��/�����aR���_!Xl@I"*�c���2j"kAaS�:h)�K�Q����P�1�%�I���
lY������yI��a�������M��|"e��bd�v�������#F�d�~�����s�������:��S�?k�	��4�����?����:����r�[�����Z	�SBe��������X��6dK�3N-�%��1�u��%e�9���D�x$�H
P������c�$c�)�P��:Q99�jkICWh�6e��M�$�R�����R������hKy��wP���D����n����c��	h����f�[@P����9\���*d<c���7@�vX��dT�cK��P�14L��*;j������s]v@3�Q]�R�bz)�j;��9)Jn����U(@f���0��f���x��I6RTjQ:�_XD��2&�#�-!�wT��xKoPIF�Y@��*���Dy�6@�O��Q]o��V��Z�v8��)�}��
$`��E���-{�;�jf@A��r_~-��3�����;����T��������l�����e-C<�V�Nyq�"��Si�M@����UVX�AN6�Y������x��J�W��.X��

I��x��'x�k��V[��F�:x�t����i��4�Vp�A(ZAL�}"�E�J������K�P���ed�h�]�sES��L��q�����P�ci<!s
|�=�lN�k:]�UP���Q��e�fPI�R��W���`s�����X�2!m�}�e�}`�u���QRa�sW���c��1�C�n����b�1mH����x*�D3v�_h�Re�
	�dk`i_��K���R�V�Z�Ri�SF��m��������h*�#I��+)���hx���0V���+�#>;Pb+_�����8S<�z��$�OA����k/�ESV��h*
��B�
4�C�>9��n���/��m���@��v�nz�����T�^�*�@S!�`i��bh��Q�d��lt4UvT<&�GSi�T����h*���@S}v%���`�����p4��Q�8���[��h��T�aS�(��h*��-h�������c3��;�#�U���R�gFC�h*�c7$��YGSx�k� ���v��}Q�54UZxC"���)��*�dh*<�G�����T���7��Sm�?���LyZ&c��-�_��u���U��)�Q$�7��|�mv�A,����L�-7,�K�lz����mX���ZK�����K�����F��Ra�}z��L�RmGmI������8,RM\z����:�bK�[-�*X��xZ����T=����T�a���X*������X����7y��>�q�����a#Z��"�Ti�9��X*�����
,�2Jn�2j
K���xo���a)����vX!mZ������r��XV����)��F#}Sox
��@P>�{Y��u����>3<���
nx*$L�8�,��}�"��L�Si�~M��O�W��I���5����SmG��r<�f<�g<���8��i������SmG����G�������u<M�*����cM�}O�v7����)<�\'xJ���Z��n�S���s�*-��~�dx�e\����	�jZt��)�b��2<M��AuT��`��7�S�2,����(����
�-;#�������!�y�x�]��!"�<�K��1�!�x��a���I�a�L���d�j�t9�J;��i�����;TO���i����86&
<e�����Se�3����^a����������{�R<�v�����x�����e�S�VL���T?~�L�y�������m�q<��Eh�:���R�b3|i�\�c"KNI�\C�)�jKl�u^�Dz��$�S��T}�+n�)�R�~�t���^�l���iw��@aX�����+�Ru��=>t�`,����3g�,F������9�`hH�'�� ���m>YZ�+b�0�`T��$��
E�Alv��p#f������� j{(��9�*#j���#�
A���g�B�����fx$�_Q��:|�u�3F����fcPFZKADy���D`g����r�*�$T�Wx�5���x_�����g����J���~�������!5E�a���-������(������������t��X��|�yS���V��p�6s��p���	!�
p��7�U�.�}:��~��}���������:$�B�i1������|�i�I6�%�{]l\�����p�'��|�����~�N�����6X�v��0;���������(���e�4d�5N���)0�e������X*UQ���rM����}���,���:�d�H���u[��`�]^�����Z���bu6�,���I�����[���0T���`��Z=����xCXOL�r���)��Jy��$<�Z{H����{�!��|^�!h��V{�x���}�n��_GQ�Z'bfP��m�#�(c-%�9��?{�B�c�t^�B�Q��F�$����C�|��%�A���k�-�E���fd�]%��9���`��S02���g�9�.��P���'�/��P�cHv���l��l=��m�����9C��P�kd�h�h�������l����>��R�&6���`b�g�rmN��6�o�u��62��e��oT�W
#JH;��%���x�o����'�%`�qf�|�`����e���R��DF���R���|�.G�5�R���J~�5��d�=��
t2�
��N���m����A&J@��L:Hdj
V.�	�~\>��f�	�@!��L���-���Lm�����t��@���2Y��,3�!g������Jd��������v����thb�
_Aq�dHc�@d��	���$=�bO��D��I��B����b*�@���b��u����� _��J�J���
I
�dld����ZMJp�������
��
��6$u_��AS�`�}�V�@���z`4��Lh�'�q���Mi��_������_�AS��<uh�
�(h�9�'h���
G�B�&�(��y�2�A���$��*��T����]+(c���h�-���2�v6M��^����^��M���\j�1�C�P�fWB9��y4���>���7���.lH���`�H}�<���d���������4)����a�R��>f�h���a�V�Me���D����@SI�F'�)��)
�j
�47
Y���	��
4�9l`���B�V�C&I�o
�}+���Sx�!�(_!)q�QG������o�)�Q)L�b/�R���}(
0�Pf�;k�y�\[i>���T93�gt��_Z�(Px[�����6���a�#�~`G���]�L�v��y��vX�����m������S���W�@OiFF��)x<�2�S���Po�m������XkQIe@��{T��-i���-����>��XA��z��<V��r�	��
�68�L�DN�n��Y��N�"l\��N�)����
�d<�3�m[
�����q��
P�hm<]�o���e��N���S@iL����2����R�G2�9UJ�I�)���fP����9�*	v����������2Z��8��U�U���
v<�Z�T��kI6@J2%#^p@%�d�T�NN����5@���O����ju��v*���P���J�������ux�*�L�s�b�L�!uj�H�-l�Z�� ��`
��9�H0%[���<��<+��`�t���&������?��^��!mP*����|t���$h"�*+���S�ymE2u������`U���(/; 6�Vl��8�=j�<��u�Yl��UCQ��sF���])a��S��VXV:��&t�"��N@�����.��?4��V����UE��L����J-*/��� T�Q'��$6�PP���a�L@(���s�A�4���5�4%=�:e<�P>������-6"#�������4��U�G�K�����d��a�J�#?���������TB����i
�Yv��H2��F
f�[�;+��q�k�����[M<��n�����8i
K������Pm�R��N���r��;����j-&td<~Z�l�V����<���Tja��������Y��\G��Q��h����>�
5N�t}�
Ky�%���u�p�8��u�2����&�*����O��)T�����|�6����F�������c~�(���YuA�<�`>��M��^����L��O6�EXk�%i;�	s213���~���\8��� ��o�������q�����\?�h.J��|&|hJ#v�t��)6�������&| b��]h�I:P���?�QZWZ�/������|�##i���j�`�����!%����3R�6��f^�O<�G!����`��L_������+&�������������Wu�U��15L���K��L#YP�b�KN�s�%X&zh�������Mm��M��d����
9��|����'V�Na�ur���;�z0��0)�S���@�Oe�s���F�O���S&TK��Gp�C��#�%@3����@��d)��~>n��
w��P�G����!@lI�E������'�%��y��

G�V��3��n<��!��lyb�q@�}�TbP*V�������Pn=Vh�Q����#�j;j3A���)���]����R�!m����ffP[��)GE�,Jf<�:`���
B�K��T�1�$�t���#��u0�vXy��;�j-�-����uT�U������?�"R'��t5i�p�%u���8�j-J�J��%Cj9�V��Tr�S�����L)M��ahJZQ(�w�CaZ�@S�����.�}�L���cc��j���m�i_B}}�k��i�k�$�@SeGF0��T����+�f�h;&{}���@Sm���JM�q�0�u4���
���[�L_h����{ii��c����y��T��8h��X2,4ZX���j;v�*hh��X��)kw�v<��&+/R'���	�+�r*����U���t�XO��sx
O���NzK�T��,�Q K<�z,��e&��d4�o�h��N���t�_��i��`3��������4(����#j_�O���TGT�cJ����}>g-/dg�Q���7ETi�}\ 9�!*�11��#*���}(�(_���*����J-��	q�#*�a���pD�~1��#j�VprD�v<��n��K��]GT���U��	Q����S��#��,C������RSt�Z *�x_���5L��5��V ��Q��`;Q���&����z���-5��^}��\�X/��G�q��<����R�>_����M�U���u��� ��u�f�j.-����F�I��J��{�~���f�E��=j�����	M�9�������U���w����:<|�i�\V��SR�gac�3:m������>���7��E�E��j�E�Q�d�^�g�����^�K�X8p,[s�E,��^H+b�D���$Xb�V,5
�0��������i��o�^l�*���+H6	G�����Ne�V�"j^����������j�[E�X�1:u��U���~��o�����-��(�����.9i��>]��C�#�s�\w��|�?B�v�W2���/T�o7�7�|�/_�N��]~�����4����Z�
���z����L������<�wV�Q>��N��z��+���q��Gb1�4���P�s`i_�f%V��};�y����}	^(�^���5k�C^�����A��4�TXaS�u�\�R�VP4CQ�����;�K=h��c�T�8�AD`��Q+�`�B`����\�\l�T{��{���]��Q4>�l�Xy���]��O�A74���E����v42*��*M���]�T��T[�
@`lh
�L�K/�TZ�8)v��t&��?GS0dvB�M�!��GSt�#����d�����%t�s4U��}rj����+;����O��1.
D���b����T��X�H�U���bO�O�O8��#��>0f&KOY�Z���V�n�D�x
2e[�3����(B'V�)��2�43
zl5	��N���	�������!�FG���r����1
Q���,����x�������%��a �a*�23�*[�&Dy7���=8�R���I
U��)`���������k����i�-C�T�*�R�+�L�qU���X)d���6�-�ZQ'�b���Nv�O���K��-�f�h�o�R'A��i�c2`vyOS���m��~���DL�:��+6��]�_���y%5���T��*EK�@�dTFD�R|%F���
_������X��-��{##:&k	�@����v��{�=�������W��2!o�������M�W!�e�l�u|%[�%+��26�l F;�j[�|����j[�e���c��_�)�5,�*M�M`�u|���W��y�W���t�8�j�lE�`�W���x�����.��2���
a�-S
��#�|�<-��{aA
��Hk��w8�-H�h�J(�����Cq�e��3|�JX����d<
"A���+�(9I|/���Sp([��8����,�3<�����lv���}���zk��1�'��k������d��������i����]�_J�bJM2p����0�a�m�W
]�)�0����u��)-�T�v�H�U����)�JKv���+���~U�Z�2�Aai��}Amt`�����,��}	���2�Aa��F��~y6`���s����<��j_�������x�L��M����B	cu�2���Q)DJ���D�
���E��-��J	u:�a@�����>�� b�W�P��J���O�nn����
N���v��h:]�{�)�����d	������T<[H����Y0R�R��W~��J{Jl��}��2]����z��(jBd�UiO}���Vm�f�"�K�up7�V�4������'/�J�f��T����^[���}:��Wm�l3�d
�1V�(��r�4@V<���y��ZC����Hd1�0�d�0&x4�U�L5��m���=�R�@����KO�$�����(����Ix`J%]�����������	X��a�nd2�d�����
n���L�,) 1�~};�W�?��J+��*�\!e�����+�����g��={����$\���&�0���FyT:��=�-��i\mO�L�s\��.��ee�K�c��0��w���1���X�P_�p�����fZ,\������E��B�V�tGW��2���i�����L��z\�F|`B���'@�o\��W<MD���K2
U2o�j���\pA�����c\�����x�OC�:;��-���gd����S��;_�S�[*���2!m9k�+��'������A�+����|h9��D�$���j{<c��]�g�A��`�]>��)@Wx����������Z,���AW��fD!:u�@W���>�r���Sn1t��R�������J�.[�~|P�4&`���fw���2jh��v���~�z\��n���o^�����r�����5P
E2
�@�8�Wm�s=��T#f�����:��?�W�Qn#���W�����2�l���|8�R��u��sW,o�>?N�^!��W���`o�b�����D��+��,�q>�.{��(X�Wh+��T���WH+��t�[��sRV���kJ^�����
�S>h�b��[g��Z�,�����	:z��G�A���G(9]�r��)g������st��:��>����s��!���>�d��;������
r.a*��6���F�}�0�`�����2���m7���e�R�-�������
d���P�l������r��;T3)|�u���oPQ]��p�SXg��	Z�T�S�J;��&�\F;���PmG2( T�Q�d����R3�k$0T���q
�K�����UvxJ��'P��J�6����y3E�vX� ��6�Kp6lP���������8��+_���}+�������+��4/P�d�jN.E��^�~���2�R�:PT����@U��5'y�l��I��$�<jt	�2*o�@�y������)��Z�Tqm6�K(nm�!�k(*�X����QT��}�U�QT��[_�~���L�(*��i���E��(G-���qGQiF:�QT��u��c�hj���&n��E�[Ub1��I\e�5�jsZl�c��8*��%dI6:,�T!�QeE0�Kt�8��e%J��?I��-���(����i?�6��n��(�����0�q���;�~�(��� ��@=*-@�������eR�
��� �M������}�����M��Z��%[l���Q�*[^f��9[�cJ�!��d��O�3����Xl�P;z�V�Q1��y��L�i�W�x�A�x-U�L��zK����\�Z�����:8���+����y�4�|cL�
H^%-Y�JK��'i�����a|m����#�`�R�+�����"q(�,~��#�W�����W)#
��$-�x����Wm�Z�� dl%�C)
_Ac�I����K�5�W!V��Y�j���a��w��j=��@�|_��%�-i��mY�A*
_�u$�N�5|�2J$�_�)�Qo��"�W0%�a��U�X��:���XFzj���LK��dWN��g�s����B	����2,V�X��.(mq:'�+M�a�@��w�����*=<';��H2�] ���){-�NV�0�?+���2h�������Z?}4��M[����J�Qy��i���)E���b�lLLT��*d,����_������J[�vA=_�-S�����W�%0����,<���U���@����6��������M��oP����l������J.f�9Y>-;_�_��j��C|P}��j_��g���O��W��������+�������X��L�F���*L�2�u���d�Pv�e��V���r����������	�S��J2���c�^a/��}���@W�c��^�.��W8��WnV�E%�����Q�Y��
�����<,|�S_�5�uJ��FWX��=@��q��tN��f/obj_�����<Md�5���@UCYm�n�H�.���&x��}6����YmL����9����A��k�0��z���`��G���M
p�U�^��2���j���V(�p�B�� ���sbca�c�����$�aK� ���r��2jI0�>�������P��T���]�e*��v��t����c���vEX{�3��qb�G����x���������Z�^/Pl �����U`�4���0��!V����,h��)�������&��p*��^��=��Y�
]�%�=�iV<���&ivl���K�9Z�"6+X���@����X.�D��U(1O��7`�U��)3k,rX�k�W�PqTE-*�d��DG�7I52<�L"*	1�6i����z'
�����t�j�-����#N
����zG3��P��?���+�*M� �T-�i�22��*�)��z�n�U������&�1%S������p�&��l��=�~����@V�&)�
h��t����Q�F���4f���0�=����Vo�,#V���: �qQhkJW����Y�H�"�o���J�
pOE02���|���G�f�W�F�Z�)�X��d P�e�s��p�%Lrh`���� d����xBJ:�(�k�F�FzR.�����X�rQ�u��{�6;����TM*�& ���8��T4)+��J�:�����4���I+6o���n-@�,��x�E!���y��gQC�i�ERe�\�,*��\`�lE��<�=���.Z�.(�4�F%��}�'L���C������4���3��K%+����}�W6�~�Ja��X�$p����D�q�a�i-h������@m-c5V���G[�_v�d��l�$�c�6������x����e���(��r�y �y���0]��D�8~J���W>o�;������ESz�OEP�c���!(��s�P-�B3��(k�3����+�J3lLy^��neN�QQH;��(5DI��L�� ��x�X B������H74,��\�� �$l�����j�vz�l����������@T�qf�O&��{v�ES��.��
EA�:����
EQF-���yE��k-��q�����s)e�B+CQ�Q�%������%���(����K�4P�+�d,�4��(���6������#oY
Uv��;C}E�3O��v�WM���fd3�E�8hlM��>�uhJ���u8PT���0���I��Y���X�q���Mg���d�����1��	���8���D�`��������
G�*~����U@e2�9����M�����QQ4�tZ.�]�VT��D(����a����`hl��>�Zj�os
E�/���(���g��D��b�#�Re�NJ��f3S��'k��6j�����cs��'CRe�����\K��%6�F:�JKVk���TI�������#��c8�G$�z�������AU���%�l��Sy$��%g����9`��i_FL���
	��
/o+}�v�����0K�j��C�!U���V��wH�����WRIF�^�e�T4�\��XP�R��vPMd�4W���`��f����uxS6z�$�v���P�.�V�<�V�h�>��]F��
R�z�j5����'�e�b��y�l��� UiK=@s����l����7XU��M��V�)�QkX��O|,3~!4`��T`��
X��=,�>IS,���wY�����9tY���R�I��V���9M4
=�U�2�7���:�*Svk��\_���a�_����;x��+5����)c�S�Q_c)�J;��X-4h%�&/���%u0�W����l�{'{���5�����%���'���
ah�ux���b������k_�7Vx���my&�=
^�-���L�����G����\[^�)�%7���x,V�����������\�8E��b�����^�T�r���Y�f�=x�����?<)!�U���iG���%*�um���2e��Vg��*S��
����7��Ua������wh����+�0S}u����Y)N~s�2
�np�
^a3��#�W�����*�R>8toD���]��O���yB���;��y���Q�
��z6VHy��c����+�
0�����cV�k��0%z@,X�%@�����L�q���X&�2e�l,`�u��5�����p6{�q�8KGc�/���8����i����Yh_�8X)pV�x]=:��t��-�9���`8���<���-�"`���X����~�����p�6�e��"��jC*�Uv�.����)�[R�!�Y8��c�o��h�V�S��/��'sEN;!V��L�\��;�}S��9c�����F/\�f�5V��4
f����%`����a7`V[�J
x�jk����f�5��
(�f�l6n�
�����O{v�9�+��dB�,��o��������j0��1��O�h0�myZWxFC���S�f�"�CS#��Jo�GLBq�E[M$�YV�������h�N���2j:�n�~�E�:�=��d3�(h?J5]�g����M�����v�r��/}��q 
���^�^0�0���$F.����A��
d�)u�s�Xv�U���&3�Xm�+��+M��h@r����;��q|�S���'������Kl_��Z�0Hk��-��w^�����3��{���1{[6|�*C^vq�o�VaH���E�J;j\�X~�f��N ���I��!F�Y��X��T�v8�JF�����[%�M9'�����
f$#�O��`�	'��zY�s�DWW#���#�jmF8��=K����pBIx��:4��G�n�h�{���"�a��`EFY��>�@����lE��pBZ
��Y1'�{�2<��!�pB���=h��.mE�
U��
v@������
�Q�,��}�f��}S!�l=>�4�	<���VTv�|����sj�S
�J����&=j��Lq;`K5��}:�NjT�tHqdke��S�����G��4��z��+Jw�4��2v+��X���t��f�>���+����Q1%$����	��
��Uv�l�eZ-v���S
v�
D�B���Z)�����5�fd���Pm�UR�VI'��6��	�k��/�`6���(���2�h��(�����h����<B#7a��@�(���el��)PTy��z��7P���*�E�K)��@Q�F)�xG�(�(8l7_iK�������zCg�Y�v����2�)��������0T�������K��~���oBh���9�J;����1T�a��?�C��h'�����5���1�����Wr�
�f�V��6����o����VIw�c���&(F�X�q���XB�(*wsJDE�!g���a�N	kF����&����OD����QTh���O��we=J�6����d���6��@�|GQ�Q7��w�8
�����lF�X�h-���r�z�0)�De%n�@jC��o��n�W�	Y��3J8tF��TYbai�X*,���c�{,��x
M�%��SM�!K6����d�M��;���HCr<�����@E1X��J���Hvs��/ViaCEq�A j_���F�9UH���t'�d��c�-�d����"���Xj�X��w
SI������-q\~��c*�Q�	�Y�F���}`*�x���0�l����nj���[k�"���z�g���;=��Q��jENbe�����������&0U�������U9)[�4�x��-�%J*��-v)"'+s�s�P��R�������Xe�@Qt�9���8��rB����K��Y�XY������x:�V��>"��
c�[�cY>iG�R��n�M��*m�������I��[���
�"%���W��V��_�-5;���QDIl@��9�)51�gOI�r�����dm�i�e�����'�e��%R|]._s��f_�++jM���_��KaxL���e�Q��Wa���q������-�@;��H�cb�\^<j��U����T��*M)�K�B��U�d��r|�C��C�d�j_�)�+�{a�����H�9!�x�+��)�������������4����,6�A~5|U�7�h����}S<+���_+��_�{���U�Feu�b���$c��a��G�~LVo�f����0�b�)�._�����b�v���|ne=���#dL���/��V�P�
k�QJ�����A�:`���9��5���u���,Xc��p��n�f��b��@+�T�	������� �v�5m� ����5F$�e��c�YW��������E�B�g����^�Zi����/��Z���w��I��M5P��#xid���&]�Y'�i��
sHDy�`���b�Q���1�$��)���f<Ko���p�������sw�v��{���O��������%

c�2���2�i�U��:1<6�8�jk�,�+�16L�b��x-6�8�Jk��G�dc�l��Z�c�����=�Xm�tMF�����=!���X���3�c��m	9f�X�����uV����� ���y�D��z�Q��I����mv�g�����|)���Y�G+q��R��`tv����E�C���3fAF`�3(�%��������+i�
��V��S��^�[��f�sB�}��WM4����d�C�����U�J��
k�6��������6��#�ZiM%�z����W�\�l�Ze��l�9S1Z�r�R��&z��"*��/�QA�s���������h@����N��4um_�\�y!GJZ}0N��r+[J��������g����d��������� ������o�5��u�o�ZD!�[)���P�`���j%q^������(�-�yM��h���>����r]�?�y��~�N���]�Y.�y;�����]L��N~!�p_��������]��|!�����B(n���0���+�j;����
��&X�V��h6A?&�y��w�h5�&l��^�~@����	�T[��]'����hx��`?�tQ��,����_UY�d�B�@2��EZ{�:�.�$�`��|�X�_�p�-�^�F�<�) ��V��K����!�����w����#�Gb|�!����g�!��H -���
�����n����gh�@j	�B�%���A�T:X��';F�>�HJ+:���Z�sKLJ	��F.p��F�J��H��}hP����5\�+�G�����RIX�Z�h&+%��L�\�c��`��l-�:��0�y������e��y-,��q5 S�Pc����Hub�3I��Q��Z�l��������,�
�D[J����n�-5��������E������B2JmE�(���<���ij��5ia��i#.���	=��$��W2����+�zA3��Y�c�2������i��k^�����4��
K��	��<(���|�KyPd����N~2^6�:<$�Zl8+B� crJ�N�%5N�q�S�E���S��1bz<&��Z�
:��5��7@e��S=U0�Y��tt&@5����U�Q���h�~�&��7A���-V�+��bCN��Z�l��e��S����=��iS=��0��d<����h���?���X����c�
�$E���S�V���+���s\��e���/�d�w�|��*��:y�V�
2��K~%��
���
��z;�����U�xI���JK2	�}	��3B���<j��k*�U�a�s�S�t/�(e�)u���!
)����,o����
F�e��f)�^�4XD��u���e�9�U����@#���U�|3�Z�+�b��)#������
lY���W���0��j[��J�2q�j�+��#�BW����QP%l���������^S����c�k_�b5�}`C�{g���1�I~w�Dt&��R����|"���ea�� -!&FeR�3�pE5_���6�i�i8��+��W��b47�,�A52����aux�8.��5�i�`�1Y�b�$d�6;s��Z�Z2D<T�R���z?Z��kN�m�������f�����K���a@+��%���V���MLk��2*V2h���c��z=4��U�0�fh��Zea�T�y�K��+����G�J�g���[4�	�]�����������L/�Ul�w�L�i��ET:,(:|e�o�
�<+�a�q�zT���Vy@F�����M/���e�"����T���V��>�hB)[V-(��b������o���0k7�� ��L��5�{��|��|�pg����xs��lA��&����eZ.�w�j�~����������$����<�|��x�K�{����i�����~�sr�n_���
Rf�J=,)Cju��1K)Sfn��	�U��X]��P�e��"7P��~�]��5PW���y�������F�@]mJ��`�B=
gb>m ��������-:R���uW��	��V�!�O��9�\R;@���!W��z
q&����S���v��J_�[mL�*y6�ecLH�����
�t2k�
����1��i����u�}J�,�)c*k���+���n)���-����g��|Z!��+�'�n��yV�[*�|���n��U�Q���[�BEZ��ajd�OJ
��V��T4��
kw[�?W��,t[a ����p�0�x�d�����2bQ�a�%C���M��Z��]���5�b+�$u���]!��dpK ��c��D(�u�!���[�������O�#,��-2EX���Jc�yR����!~���RGXv�'&�a��l��53�;�J=��F������-:��}!��e����iwmL ,	���
�����z�@�+���1��atv��{�#�F�jCX)�;u��q&�>�a��M|�S
���[8ET�a���	sg�r�k�3�Ab�I'���	���kS�XfU�4��zj��?������&��j��	|�P�&@����	��vZ0ae
��V���Y#�6��C�q|`���7�J�����)��g�&Vy��FZ��V&HY[-�w�9��`��)��<���!so��3�9��tB�<�����+����83a����0����(�����sq9(k;������(k-�g����2�)��o���_CV
�8��>9Z�b��4Y�l���u��4p��ad�6!�.2p6�Ig�&���p
; 8*���F�98���i�+8*�i��UpLL�_��B��:%]U��r�h�W�Q;����b!��4)���:F�K�$T�Gy
������+��J���r��������������XG�V���
� a5:C��a����������(�����h�\�	8����We�Nd����r������i%���@��^C�]������+���j��QX�e�n�rXZ`$m�]5pT��e�Hg@s|k�0�#)_2h�`�I;GFi���Y�J��`M�o��6xP�����~�y�Y01}�cW����%p�o�
��j+NRLFiF�I����d������@QIB�>���Pz����qQ�P�fA�a��10�G����l��a�KC�AV��!Mj�E�Bk�x���\)%�ZX�����(D��5by���{�:�����|t,������WR	6h��5��!u�\`+F����fc��@j7�F	���v�?�A�6�(������/�8�q�^m�����[+�K8������������f��_��J0������2��&��5��V�C
�6;�Pnju�XN�J������3��d
:����}���dHi�����hH���](��J`���e�����r��r@c�hWDy���LC�h_�����P2��{@��$���
�-9��))Cb;a������4����@��X��8�jCf�N�*���s,z���(��o�
;l�)�!B�"�������
z��'��O�.��fX�uF� ��fU�
u�/&����p}B�!TJ�(��*�"���>���q�fdHmu�!��k�s��!0��!t*)��Y�B�B{��(( �/�m�4HJ�QI���� TRG�B5�C�0�'dh��L�q�A�0�k[�B� THe���~�p VA�
{�r���B��,V��|B��T����lB�J�Tf6��!T�Q)�����q��{���Qy�NE���
��`s�v����E�ftF@[C�(��U�U���{`����Vb���Y7����E�OfA\2�j�����?G�(R�u�Y3������HPT.|ZE�N�8�
K�
��_��B��Z@���6�G����`����E����e@E�!�����T�1R"=���(H<4������(��e�<�a���;a+����(���(���aH@��(*��j����E�����&��
��q�[�(*���O�j�*�J7��V%C�D2��������(�%�?�����l��g������i(��n���
��\�E��g���Pt.����SU�V2���/���k�&0��
!��c��(��"�w��)6�jQI�)��D0�������zE�)��$�������2�`*=�B�p��NQ<��j�|���u�����}	k` �6Q:�Z������WiZ���Tq��?S��_�D��*�f�
��LD����C�l����(K����;�J-*�b��tC�7c�#���k���(�Q#�
f�*j`vD%C����!*RxB�Qn����hF���bj�����1U���&(�ofIR��#����8�F���HVCU4��
�3TU��`W��`@cV�i��nW�+K�a>���d�PB3y9�j'��3��*�bd)���c������a<Z4��p,yU�F�D9�
!/���+W��Nh4\S&����W�%�f���^W�%�V��#��9a��Z�� ;V������V<�P���m�.�W�T��Z���X*%>�Ci�Cjb���in��k���P�LR�������X�/�e1J
��Rmoy#i�7��Q�%�����!�i����R)`Ix��}Lxq�����)��Z��R������&9���&1*j��L�������3'1
o�G�9
l��`���F� ����:h��V:�\?		y�/�y�<B/B������jr@�"�@Z��@f%&*Br@��xQ�n�`��|0j�
PCjQW�[�{��A5� R	�x\�.��C)���Zf�
�#���/���#����4�{�<j������L�GmBF|`��X�f�<�	V�8<�	/��Gm��;���
����f$�G!�u��Y�G6��GC+������� �	5�M3�*@�S��W��'+��&$�O��qn�S�p�T:Xzu��A$h�i��Q�)�6���ib�H���a�n>����@$�x��~�9D�!��+-RZo�}�����/�e��'@��(���*K�dB�1����2�ewMr_�����f�j^�Ia��R8�Q���%��N�
���8)l0�7���EIh������}�:�ZB)�����\��"�����36!��,����R��}7f��S#`4���2�i�1���h�7���3-��[�P���RjQJz�+s�$;�!{����3{�����Z�!e�{Z��"��/CK0�T�G������*47��eo��3S�,����/��G�������,S6?�B�����&�@-�%J��r��RKiCB�oX�����i3�4��8�;e�kg�I�
[R�H)4X��G��eW��%�h�qRZPc�0z�a�k�������`��|�:H���e����pa���k�!������k��'@R�/R�P�+�/
�_H/�`����e�(�xZ�F�5JGQ���v���t�<VX.&	�������Y��)�)�k��aO���h�B�Z���Y��6������!R2�6�_2�C^���o��DN� "�Sj;�J���`����%NXyV�#Ji��!�f:e]PZ�Fl��"J�]#��)�i�;��k�)D���U�[��um�	fT�Hju��)����Z���<���#:QD��e�E����o+xj	u^�.�a5L|��.W�w?��:KU���&���EhH�$����?�q��
endstream
endobj

9 0 obj
56316
endobj

11 0 obj
<</Length 12 0 R/Filter/FlateDecode>>
stream
x���A�$���	����u�mnfn�$��^5@�j&�Yf�]f����o�DRn���(������x!:)�t$�<�.��������3������~������<���:���������������g*���������?��?�������e�������l����������r��������t�����u���_��:-��/��_���?����_��������^����/�����2����Y������u�������/���"��Ku�������[O��W��O��|�������X.������=b2�V��z�V��M��L���o}��:�����,���.��6��u�.�?�����,�����O������^/���g�\��������/�(�o�c�^�m=��=~�]�����e���6=���������.�t5e���~Y�+�z<��m�o�����_����e���U����9��=�~����tY�3�O���m�����>�aE�c���Zu��K��V���?��?n���N0A�U��~Y�0+�e�M��Q�����R$�����h�O������W����������(w�������o\�g�Nf�����.G��F��9 Yu��9���'Y��-�O��������C�9�K��p�9m��'������s�����>m��m�����|�������;���y��o��LY��n��>�w������X��W���x���/2����wjw�_�J8�r���}�������O������{�j��K������8���\���{*��_|���Z���������VJ� ����~��`��e�?�;�{�?]��EL���b��Y������s0��u�m������s����6y��������v�Z�^��7|��
��_���.n�o�����������S6����}@k.x�:���Jx������V��I��{K��E��'��3�5�I������p.n��m�y�^�i�g��(��RP��M��5lUxZu���u5�Q��������P�f���U��L����j����������	�h����2_��W�:5��D�$~C�A
���Z�^�UY>�y�������ud�O�U�u j���{�q��|��n��|���e����~J
��F7���dTeUF�n��U��Us@�*�x�U��l����m�����&��w����������*�On�U��J+}6t����O��*~����u�|��e��cU!�� ��#H��2"H�E�>��Uz�
���,n�c0^����>��j^�M9/���r�SM��M�v??��?�N���N%E
[nV��]�����IUN��p��Y������?�L�����������������O������]���g�6��O��z|GG�x�����O��:���H�����&?
9�PZ�y��/[��=�,���t�q�=�����"����S���7������||.�v�L��)A��Twx�:�;���q���o��O��*I��W{����a��?*I����{T�P������e��~���?��\j�;v�q����{�5z�u�I�������>�KK:�X���'�O���n������o_������?��/-j4J�l-~�7y��BTW��������������
�����4����/�&t����(E�>��p��>�+��=~��W������No{������z�W���7�pP)j��o�/������o�A��Q_���vy{�4�G��n�������x��������p�=�x�3���1�e�,������@�h
�;�5>
����������n�����:�574��%-���u����=�`���}��a�?�����������O{����������))�~��M�����������\JJ�?�����r��KIQ�]J��y���|���W	Q?�j�_��
]v���������{�"����Em���=���Q��D���E���t�~lN�:{��>��C��c�t5t����y�LK7����&���B�?W����	8��iI�����D5���n������~yp0m_?��6�����KJ����]���(��A���p6�[�O��lZ�M���!�n�E����vZ��m
������ao;^}���������N��w�g	�{����:G�-V�F���^y���(M��_����3��3��oS��R���$�?��3JQ�#�`�?���c|1�Q{���>��
�9����8>Ga5�����#� i����K��,5�c�@��u�<����:x��t��<��c�\x�/��]j����`�}8��4�s7��F�����j0�G-�d�X
:�U�)��?�WJ�E���u:w���B��+���������"N����m��Te8�%�K���=|���l������e���p���
�TA8%2����b}������*8e��%��G}9�|�.�:!Q���a j?��~���C�]
D�>7���i����g���{@����%�
x|~J������<# Q���`R�y��n�����T���|i�%E���n��|��L]>>j}n���������&'yA@��WuXI�1K��Fr�����`�;�#�Wj��B��)�~��)��|�:y���C&��h��{�u������������Z�p}�{%��=wK0��)5�n�0�A���z"�����j�_���?��;�h������	G�
W��No� jp�	O����&��i�N����������2;��w�Q'o�RT�B���U9��iQ�Bzl��7���O��z�
������Ew?�j��������X�/O���w�=.���
��������������^d�����O���3����77-�l
'EQ����7���W)j�z��uq^�:i��;j8��t2O�����p:����u���U��v�������KH�.��������f�[Z��p
Xt�`8���gIEn���o������%%���hx3��E���p���m�(�	��g��*�#��}@�Ah7D��|�p9�J����IUn� ��iN��:�e�����u>������5"�'����E�3v^�I�(���"���?	_���>��#�:���e��-��%=#��i9��3D����f���}������U��_R�(N�{�M9�%�t���l:uC������.�Q-����h��N�������/6,-���%E
sk�sIQg������E����m���ji�?�V�w�V}�k>]I���t_���������U
WS���t��4�RF�^`��~iUs�wN'�L����~�����Jb�/b�Z��[{s&��@��%MU������nGP
g�VvMq�88�u��~yW��T��y�G����2S���V�t��������Yup��?|��Ve=�2��E��o���^��������m����<�<&t�	@+r�j�D�}@�Z2���U�������"h���5��j�Og�7���WF�/�&���U>���NV��M�����V�P�|�a8B�oiI�������a~��!��p���o���yZ�i����"�#������R��x�|�����M
�����+Q��IZ���U������JI����(�P�Qu|P:��J`���Gm�����_����6��p����m5���:�5��*�F�r�DF�=���hI�Sf�����j�L�:{w$Q��jx�u:d�E�~�il�
<���{��d��X+x�5u��U1������e������+jU���(Z�O��pE-�t����g`�,��``s���������(E���#Q��j������aA~��:�:���q?�R� 4����v�wF�C�O|�������	@
w����������$�����F?�}�����I���N~������_�y�5;�=��~E0oQg[��V'7/)��
~kt1��P�s�65H5����}N�mR���-�M�_�����������%�N�fA��Z�v;-���������>�~>�4���Yw�?�O
�w��or����!Qg�N�����\ZRj�W��h��u�E�n���S�~�n������J�����*)��nF��z��Y�Jkuv7S���������-K��������?��S)I�}�/�9����~"u��47���n>���{O��,����N������3w'Pj�����W���u�M2iu�����Nx8�q��)Q����I����K�:�����n'E���H����D5g������~�!�a�����������z�5-�hX?{���)I�SsO��IK��2���6�I�<g700�s�1Rq�W���Y�J�p�U��|?��y��&�J�������UR����E
���v��C�Vh�n�
<{jC1���~���^���n����,�R�J�6w�����|l��S\N��o�����orx#�7v�h���>3C�3J�~���S�9�Z�(��{��t���Fa�kv��
���������Z�0���x����p@��\����]���pK1��SZ�y���No�Z��y\��)��-jI�j�{��������[�/>����������t|Q��R�:\>����2��J�o0��^�E-z���E����7�ne;�wv���s�W*Q����]E���t�_��2Q����5XK:�tR�i����v:m���U�����N����i��K���x���F��OII��UJ���.��;��s�����V�n�{	w�F���v��uo��7�&E������Ac-j��[8����F�N2���I��Z�p�w��y���b�����t���=��������4���X����hZ���
�;��Z�,����
���L�tj�/��Z��\K�
����*�#�`���+�vE�	��������Hp�:'+���U�0�����
vG�����Cx�u�����}x�Te0��Pu.�j�
�F�f���?�_4�g��������r�	�P�/-���q)^���V����K�r6JF}��m�U��Mz'	���F���Q,
�{���������"2�E����V�Z��>�����t�(�M�[vs��5�yj�����ZW>l���Fs91�q9-�tZux�:����IUN_e����gxY5�u����v�Y���bz���2p����������	\��p|��i;��������~>�KC��p�����+o8�2����iQ��S�+`SG����|#�e��U�)��y��Tn�C*kHi���J7����F?��C�:|��~���{����H�$����E�z+�� �x
"�sh������3�'|n���D�\���(p���")0����Z��q]-���r�Q�,\KJ�5��I�>����e4�C�\����]KJ:�k��s�q j4��<Nku�����}N�y���ts�_����}�G+�s�/��'�������[u��D��&�N�z���/	d�`-H�"����gz��a��E1�t�0H:���F�OY��h�Ns@m��ch8 .U�E���z���G��O�#��T�P�?�Qg�nl��jU������p�V����@�j�%�:{��WxAq@1�|��U�g��:?�u������T�#o�)���M9����Fx�}�7�����W���IQ������������^'U9=AU`�
���z/h^�M9�U�_m�M��\�~���W��������JVQ���J�r������@w0\+��$���m
�"�N���Y?�F[�7���R��t8����q,�
���,����z����O[u��������?<P[u�I�O���1��nw{�����������MW��2U���*�����~����U�nsL��>J�Q�1�C��������i��iI�d�|d�w����C��]Y#��U;^������CH�I
>�m�����7���?������Cp�������K>$�d����,�g������}��������������|�R���g���^�U-_7Q����!�����t	�I�v��^5Zx�>GV�G�p:?r>[�56G�^'De��:���.=�����@5��/��:|
�1&�N������T��v
_S��&�n\
|E��	���.���?/a���]��Te����������NJn6^GFA0(�Nu�6}����k���r���.'K��O�i��f��+k�����N���i���*������[���i	�M���`^+Z�����
vw<0������/����C�l���B����
wQ�O��R�N�Y��b��R�p��pQ-����p���=Q�!)����cc�pQ)j��[x���A��-����'��{�����?��p��
�F���Z�h�;��4����E��n��jQ��^��Z�WR�O-��Y7����;^�	Q���4�����������B����jD��#�+JQ��u��pE)��+JQ��r�-���5�Y�����Cp�3k�x�
W���K���]�s>�����2��'������\�p?-I_���g-j�R��/��-��9S���!��O�7�����V U�����;b-wD5Z��>�E
���OjQ���������R����Y�g�OjI������]�c��@1�~z�T�+�����pK%*�p�w9�����Q1��D)i9"�as��?iI�D@��RP?*N�P	�?5:�z.��G8��t�\���}f;���m'�E�@�_���e������N����kZ��p��X����	���~<S��iQg�
�;���}��Hh��E�������p���X�9/&J���O�2�����IQ�L�|M|�m���:�lZ��M)|���<�{��;��/��p+�/����F�����k�5x�k$%Q<��@R��y�>��1-$Hk5�k�y���,z�KR�� ����K�hV���:wtQg/� ����$��S�t��FJ�|%!Q�
��A�^:�����pP!�m���G��zw5�@����T���R�y�J��78���iIc�Ws?�3g������2�����B��3�!c�=Q�m��H��#v�B��$V�VGO<�������/jQg����*�����}�K�'Ee��pK����u��[��/����uz�E��w�_jO�!p�I�����3
Q����o�v��*g���U��3�1�;|�:���}�����`�+�������@����o��jz}yf���
�L���]
����r�y"u�	����Z��
��pN#_��6c�Yy�)2�g0��g�o���~6�#HN���?w�c���21�Dzlx�5��e`SZ4�3�{�4��-�X���9��?�p�2ZZ@+w������1��{�����K����'����CY�����A5E8��I+F����@��4{�.�k��bgzJT�	��iUF]=|L���iNV���v�e�*h@�u9))ySOST=�Z-���C�����!��N�����0����<l��vZ��B"����q��w�;H�`us������cwF%*I�g�'x@��M����3�_jQ�.~)De�i8�Te�5P8�u������g������{��R��sr�EP	��@`8��{R8��zI�I���C1����JT��D��H�GJI�w�o����@PJ��I��%�����+R�@�%����7m^sI��<?oY�L�i� <�S���/�$��SjQ's@�����.�
g*�O�u�G����:������W8��h���q@F���9�u��D
��OJI�oS�)���g��J-i�5!�R��T��N	J
����B���1�X��>���T�p���p��'h��Q�CQO����iU�n�Z�!B{,�ko����'�������Vw�������Q������v����� <�]��bB���(��75~��ksD)i���QJ:�
�$N\	���������=���O��hvt��\�o)���.D�?7|�K�*_�t{��?�2��iR����Bd���5|�_���\���}�'����o$B�tZ��Y�j���.>��n����~���~H�Oe����4�"�LJZ?�?����.�U�{s��s�����\����E��M�XPe�Z)�Q�:[HN���S���cc�I)�O����Y���<�q
8����w%���+�7u6<��s�����?��(�z������|� ��o�O�����}5�7�pP%j4jx}�/�����wu�6�%��kI���JTs0��IVR{�8�E�1�Nz}����j������+�\-�,����[iQ�X�'%���E�����tw��]�$�E��� �,���Qj>wK-j4!8�R�:�� �d�d-���^W���~(��]�$��y���Bn������"�ub��L��:P�g�u������KN����?�nN������tz�����x�I~������{�9��n���#�k
�c�*��N��Y��;����><29�\Gn���D��������c�o'�p��Z�!I��OiU���A�~�SIi��l:����ls.m�`�L�3)j�}�9X����h���������Ly)*{L���^_�|���:)�d.u�L?>P6����6_	��6�X�g��L�:P�7����u��o�)�dtX��~��oM���@��Eg �,G=[u��)?�O�r}���;��X5����F}>����i���H���~���Oh�>,����o�%
f���I�Fz������X���9���"�j0*Y���;<Y�9������]L��[������99�EZ�G��o�<$}�Q�x����L�p��G>/b��������V�6t���#y8����SiUF�O���(�
j�&&*���`���<����py�8K�
vdh���;Yd1o��z���9/��w@-j�d�]D}��S��"Op�Z���Mj m	D
�asD��#�M��������)t$j�f(�Q����3jQ��iJ�-%
���d�y���u6o���i���
/zV����q������������������kd�>n7_�V�+� ����w��iR��5�����3Q��$��OaU�����*�O�^��5���4�����##Qc	4���@��w[�S���{u�����d �8�y35J���R8�Y/�Rx2�
<����p+���]��"wK5�n	�N����)t �lR�?a��+����
��a�������.
:�/��,A�h�rx��3"��l��:��IS1x�j^'E};�d]Y���d��u�Z�.Z��K�a�[+���n"��'���7!�l��t�:"M��7O���	�ig�L���9p�/�$z���������������+$�,z�Y����E�~-��uk!���"�yy��W
Hk����JTs,�[�
L��iQ�+�\L�� �is1�UK^�z��bZ��ltv����:�w����d��;���	�{������,�,��}���]��\�p*P�����������	�zW���������5�Y���?7�����s��'��\4�C�!������{?������):Y����~�>�p���-X�_|b��?D���D]�|k7����
d68|M�K�o�F�������d��rR��K�1\�LR,���h�?��[�;��]Z#Kc�9H���������1r������ir �����&����]`��!���:�-|��q���57O{W��������tB�����?C��?)���FF}���t%<%��`���|�/���*��u�P�\�L9$�u���w��/��]8~��h������O�R��Km�����t%�@�,��h�������v�O��L�'iM�����w�/8���h<�(�S��'��IQ��l�hR���UM�^�E���6���n���CH�����Ep�-���r�3�s8>������Fs��"g�h���H~���4
���07���A���yr��_�lt�L�S���c����&�e��xRTv�0�������ga��vYuI�*�c^�1��<����
w9P�2>z�d� ��;[��n��^�g�d|������&������1���idS~EM��=�Qc����~���h��|D9�tN�N2�HQ�����`�M���4Jk�G�3����
�L�'�}���pE�o�R �rU�,����b��F'���+JU�p�+JIg�i~Nf�}����G�;�p�k��^��L�`r|8��>�S����N�%�&�SiQ�	��T`�'g����ps��N�p��
@�~So&g&��lS
����&8�+JQ��9����N���j��i32�d>������~��'iqH�(�S���#5~�d�t��gB�:�<����w�v�jO����}�v�u��F������,�r���%��E6*���Q'�z���'��9��q��62zE�F�-��(�T���Q|7��I�N5���tsF���5�t���6��3�����_��7����_,@����@� �&�v�����_�Xu��?��p0�*��n7��r��AI�x����-5MI��n~&%��7��0�eR<�6�����A;F6�+<m����%1��xx)2pn������������e��o������r���?�K�~/uO[�%6')��O�RR�%���h�����5H�NGF�E����4�	4]?�U�'����t/��@�����u4��Q����6�T�cK�+e��������;����tT����������^�6���{�i���T��j���<��s`���{;�t�9�3g���wU�
-Cf�;���Kw;5�;���u��iv��:2�Pw���B���KQ����td���]~����@��c}8��VGt�9GN-Ee�X�Rx�?����IQ���B����`�!��m-P[5���'%�>��Q��9��3����v������C_�^�Gwq���}I�	-i�86\N�~#����33��q��~R�Y�a\5Hn��'�$��u~���S
r����i?Pe�����7P�A-�,�+��w1�����a�����<$w1-j��,\���b����b�R���u�x������r��~�W���UK:���E%�VI��5����~����IIgk&@�!\��$����NC��]	����]X8"�pD5~�,���������{�u:6�E�\*�vW�������}�?�jQg�n����v8���#�2������:��/�%e�}��J���;8�����v�D%�l�t-��"��9F*���������3P�qc	���m�S�����y�s���_���]�V8�5�M��:I�I�F�]�%���H���,�k�S4�!��Q�Z>��������B�����]�w��xZe�to�������av���F������X�Y8 �{��,�J���;R�hB���B&�p:�/O�=��IQ��N����������~(�=Fh��i�N{��`�F��6p��j^'�f��*����2���s��'I�s�� ��GjI�����{�O���#H%0o�o�g<���7*I�[��](�w���R�hGVwF!�G<�>�m�&%-�G��������N'��g�����M[7�����KcnuW
�]�����tr���J��<�4����iIgA��;WZ���wd���n��t��|9���%�u;Pi�Y����p&�K'T>��)I�!Z�C������,�$�t��|�8�"R�I�#�N���."���h�G��]DK:y��N���������	w���v-�,x�JR�����D*�s��I:��9wrg�N�a�K�"�M���1K:�!I����/�~��DZ�� �t������i�Fi�����"f9�/����U0�#�Gb�y�=���.G&|.�~pw3����q��A�y��	�8��%��7I5�6��n*���r�M4<�Y�����=J��QK]���@�C����#���"'�/���'�o��=V$���"�/����+�������x�q������[��'�������;��M��>=L�4�*.&%}��>}����I�4��q��`8����ts1~�A��������s%����$��=�����I����WJ����AW=8�Q�9��X�{�9w0����~[ .�����
��?<���%���8 4uG"�/�~�8\�P���J�?��O�����4'�@��|	8��$e>m�����iA���l���m�)6�5�����m��U�@-�l�7��m�������� ���p;�?I���P@S���IA�8�4��&������1/2e;t�`��Gx��]p��p�u��=�l������4�����[A�q�Z@K.�v���8r l8��w���NR��J��v���U�����_��-"D|��$�f���)IY�|M+2
8�kZ�p��|
$���ci�����~���L� ��MK:�(%�y�������������g�����������}���O��>o����v�-�������?�k���4\��e���Hn��}�~��H���g������{��-F���C�w���s��M>�������7���z��?W��&:_��c]>��&z�������7��e�/��s��o���v������}�`�������n��x��s��or�������/����c�?G����������s���?sh�������X.�6���c������~l�m���|�����[���X��|�v�/�i��30v�.�}�k���v��l��2o����7������1��b`�r{�I�j��]�����@�7����i����7��.��2o���30vz;��s��M>v������@�7���)����,����rYn����E�,���������H-��]���������r��\����o�:o�������������r����t����s�]_��D���}�)_�z��m�]��"D����������u�ooAJ�u����u���Y�X��m^��y��b��D���:��|���^_o-�_J�v}���|��y�����`,�<���(	�R��vL�m^����O��Y�1��T��)�b����(C������y���,�e��l����������>.�����u�*_�v�e[�W� ����7��~Y�z6���(�y���<��}���2�R�:���M�f�+&4d�����u�z �.}s]��U�S�����\�u�.�InYU�[��E����.}�=	oC���}�Lj����U&t������t���>��-F�xg�/�7�vw���H��M�e��T��������~�&��UC��y�"���qWsa���K/HC��r�?7������N3�.�p����{�;
�c�����|���!miH*m)�
�	�*[^�����I��`��`1oZ�S�.S&��T.���l���jS^e��5��*S��vU�N�"���7�����YC�����T�g�Tm�RLY��"0U-�W=���6P��Qv)�!e���e�'
�jY�r^zq�W�)��^96�Ml]�7��T�n��V!PU�P&��!��R���Q�UW���������)������jS����h%=�2%jY���rz�^���lyV]t��w�at#�;|�mK�s���2���1]�5o���J��]��_��k�
���j����;M�Q�y�C��y��ZN-��5�r���y_/7��6��>�zNdim��[zi��������.��e~���w��x�^a�Y���E���1�������e{o�74f�i����jM�r��i5���y�#�So���r�j=�5��zl�R*��1q����v������]lQB	�|i�6�U>�XB�
���T�$`�2���R��-��4/�7H[^������k����a���-���7�]/�}�m�`���5��������������+�l�S
iP�kj0TGdl�5����W�[iM�f$6�x8S�~�����i����&�zmj�P!�V[�ew"�U�<�1h��y��5sx	�Wl��-��"l�1S��S�<�Vi�,Eg��BF���Lj���"c+�$�b2�F,�^jc��E��%;�[���%����en�/���;���r3����[��vx8}<n��4��m��5�%-^%��|�o�����L
�hI��������[����g�y/_���]N����0������j��]���,���^����x��� a���|��n��.g����������i������<�]|Y/s�q��6��z��W=�+��%�/�u������~�LW=�O����y���Gu-�Q{	�{I6�:��I

�����O.���%,�e����
��u��w�J����e��1��n��z������4�&/�
-��$��
�q}������W��e��7��F7����x���u�A���}
�dK=�u��/��d�\�G�!( M�g����My�@�%h�-5l�������!�F[
�K�v��o�y��<�g�����M��t�%�����3��w���������)Bt:�
8�t*+��%8t*+,m���`���x�Nm�u���Ni�� C��C'X�r��C��������=��W?�tj+,���s�\��'��E2��Vl������`����u^.�]����=|
+�%��5����0�h2��z�����z|fj@nh�'�(!yp�S�����e�i������e����10�%�����|�^����<������y��%�$L������J�
]�#�����7��v#��fH�k=�CH�T�Qo+:�*$�w��f��V��@P�+�$�J�����4Yf�����(���S�5�}�I1T����������}���#����<]�x,%
?���@g�������#4�����~�U6pTX��:o����������1�R/^G��~�2S4n4����#��4%KvxX�G�lI�vq[��������8����~�K������?�����2�����Q?�U��Y������tU�x�T��c(Y2sZI<��%5�J��E���~�NP�kn��N���X YgN��%�,i[q
G�%����7I�Q��ZnP��R���_9���{ bG��%�Rr���^�P�m�p�<�>(Cj�����>�^�����lY^���u����"eJG@E���4��j�8�������!5�����)�����r����(���r@�p��F���qAk��ry,s��C��%;��S9��]��iW�[w+��
O�z�������N`�n�4��T�b���v�l)��Z��������Ka��y
S�)�f	SYN�����������2���8)=J�`�E���8�������4�N�p@`��X��TS<�	,�0m����%JB�5�U[����jY�NF���$c�w��};Z'���JV'���A+b�-�����`����Rp[j)j�Ml�(\���|A�!�u{�`���T�������c�+����Q^�����U�(�Il/�U�b2�[���eN�#�U�R
0w��m���&�����1W4��A��\l�<�\�-�U�h[\���3QwAy]4p��������M��-�Z=}X��*r*
x�e�Rv	J���}��3�'kS<�;�W%��u�D������g"�m��k���t2�e�%%�;
�K*���f`�U�Fs�N3����
*���.�����t�?��YG���^�[�l(��+b�9z\��
�p�{�Ve���h^����W�s��a�!/K��7pVa�j�8:����#�9����,P��EIr0`��&���d�|^�Tm�UkK(HUvD`&�nZ�b+�*�U��=��^W�!����X]�i��#��@S!���� b��)�v���t6��J	�1�j��1��r��Qi��\�u0�����J3��l9�?*@TR���
���JA�;�N�w��U����m������_P�Rn	�f��b/wU����6�����f6^iM���f����S+wk���P�4L��x\</w����
���]���<����X�_��:���1#��h�f�G)������{q������:n�����r��:g� V����c����4A����jJ���x���Z�J���Y4�r2�WViJ�����P�My�������)l[�z���m�!�p{�/�.]��W��\
n�����<������T>�$7"��)H����f��)&!9��5Y�h����n���p���s���a����S����gp�5O��(�4WX3�����H\2�2SAr��6�*)0���+5yy�9���jG�g�:�Jk�.��0s�/����N����6��g�\eL}T/�o)������lT�k����BS��dJ	�hB��oS��6/U%K��MECe�-Yb�9�����o].����b���}�O�|����>���1?���q��k����6x\�Y���J����c�!���1��f16?������:/9
|�|-��
���BIh��hxl����#eZ�_�c�#�W(��G��2��^����Bc�\m%J��g������c��k��
;v�{H��v���,O�V{A��uD��|�����P���_��.��[b��o��o�^�+���� ��s��F[��~��y< �8$c-1�4�K�v�ZJ3���T�����_`�fQ���dn;8���2���4����iPs<������R�<�z}\��O�
��a0�Wr�*w�N��i)�ee��q;�
�7�R��WeR;�Kv��DS`�4��&/K��PZ��qI�/�R0dG��RmH��+��O�%s��eh�,�9_#�r.v����THX-�[��M�L<�
FKp4U�Dy���@��B'��B'GSi�j~�fz	+��X�M3�9h*7���N��Z�R1��xS�)��*�w4%�����MA�QT��J�,[�T]�h
2����sN��������h��A.��@�����\a�
����{�M�,��v/w4�����$�M�%�3ZR��d/m�����
M�!v;4����s�e��$�d�w���$��44�KX��L��F������_\�x��b��[p	ix����*��d/���A��@���/;���h|G�E *���{v��j6�	Rg��J5J]�4r?�")QI�^�5}��m�qQ��l%0���j�Rd�U �Up�i"
�������?@�E����?K jG��x�VL]������%�*�jeK$rC���Ak[l����U�._�7+�S��23�� S������bv;�1_GVi��l�u�??��m�=����wf�_��p����3��������3h<>K[j�>�X��r�����g�Fm^�T���}B�@X���#uJP�2j��a��:�����ZF����$����{��j���d��)��S�d��Z�C����]��r���rd�������_��6���+d�(��L�������KR ���x��V��(������O��_�,5G�aiY���5�%S�,
��eOX�a���h��/\�������[�p�@���1}|-)�*[����#�����p�=CX9�Sm�E�XGX9N�9f���K�5j�W����i'-������2J`(`aQ�Z�]e2^��6/�)�J{���hK%�J����K�E�e-��Y0i3�A�:�0���K���8���Q��7n�.����Z=��0X��t�k(+���c:�8���M��M��CPw�3���CP��fO���i��W���hV�$�viai��nZ���Z�#��Y�+����	>x��'�iu�xH�d���`��r�q���4X�b=��*7�V����CP�!-�(��iCL�#��jsi�{H���
i��/��M��Q�u`H�V�xY��D�@Z=�����]�m�e����>�Z������sOn^Q����<��'�VH�t3�o�j{J^�����r	��[����J{Z�^���Y�)T���vI���L<=8��=��i�H\����)�ra��ig;��\�g�h4r�o�N�������B���+d���g�[k�JF��e������u��
�Z
KAN�\�e���* e�����d�}J�
r�t|�����Qr���+w	�/�I�y@g`�_�H�^k���GEM�l��J?.C��k��89l�#�����:����/��8i�C��{��}%��l�=�q*����V�����>�V�S9�&l��/c��=l���^|�����l��H��8�J+��'�<m`��	���>	X�m_�Z��I���
+c�"VIK��&[A)�x�*�EQ�"�VL��
){��V����_B�r��qR��P��Ss"2�jY�L7d���T��\�)��[���6r�#7[_���l����R+���
j�
��nP;�������;���e��
j��_��k(xi{BJ�T�{��2�20����%�A�Yi��X)�Jc������U������xc�1�wR��J7�J��ea�����C�p�v���?�UH��wY�WaI��4#wC���Umb:�U�X�]�
a��C������T��)��]e�""M;�MD�w��Y�E,p�
pU,]w[�[�(�7�_eI$uF`�����{,�1��[����J�9{�u�ppu�
1v��B���s��Wh�8(�B�^�����eBB���WnZ��Tj�/���BYa�5%B��9	l{_@����+�Z�V�2W�Z<��_k
����u�
i���9	�VV|a�}��ZT.yp�J[!a3�)x��� �M��o���/K�L���y�o���.�vDf��{�����6�j�P/iU������>�%`�"*%kZ�M�ZP��ya:V�4�f���N/)a�(�@`K`6�bt��;�u���������B_
"��/����H���Sho��6��vX9}�Ev�v��Z�j;&,~i��H@�����$/�!�4���5_�#(�1Pv�]ObG`�^�/�0�0T���%X� C�3���zU��S�~�u���e�f���a����^��X�����*|*���o�2������$0TN�����0dX�O����_�5<�P-�6W��I
C���:��ds��qAO/����}	5�l����Bia���
� �O�}��z�	�Pi�������zT�&}�q3�$��f`��a�v+cOL9*�6�p�r�vdA[���� g��Rv��ffZ����@Q�����a�=������	XG����W�J-�=���UV���R�b'�Q�P6=��pE���2�2�pEF��$���iu������{�������g(JZ����evZU��Q��U#�#�6$��xF��)��+����i��	m���@Se���T���_e�����(��yQ�����M�L1��������V�r��v���
��,�X����S�J+��+d��]v���/����X�?�cL�������K�������a|�t;lU2��<f�-�eTj�]��=�l��
j���:���U�Q+zHF�+�(�>t�t�����#��W8��JzX�P��S��k��B�|��
b
_�2���P���c��.��=�!f�*l�AFl
���H��5|�2���a�N�Q�Z&����+����R�b�a��<����
�!�7���6�J��KkM�����W���w��`"�I���T&d�l�l��f�6��}�
���bi�b �W�!��
u�80���3�2V:-8��?Z�oTV+e�f���dT��<�lY�	S��j�N� -��~�l�!����=��<��� n���j�\i�P�����	������1�j�J�XP-��U����\_�_�-�����`�1HQC�����h���?�����Ab��+.�E��>�`��@l���ev���_���|����w �6|2J��;�gI�J�3Zhi����*>�Tj�F�aG�p|��8��+�(i!�'a���Q�W�;kf�D����jU"W	Kd+��������+�(7��Jm
_I�f�|���+���i���r��d� F
������_B���v�k:Em��})��h ����[:D��;��������Hp�z�5{�*��;hM���5��P��8�jO��
����5������jkv�&L�(hi���@�>Z�� ����R��g�a@��c���:'�����6���VZ���pB��m_�W��P����dl5�"Z��v���7�l�L�@+eX��hk
�(���1KXjN
�z6*}L�F��Q���t��~�L�OFb�0�#WK��m8��/�����D�Z����<���}'����V[S��L��@+5����{h���
�YZ����aNh�5������V����
��h�5���Wr�k��(a� c�����,������u���V���u[_�h���?�B�UZ!c7����V#�8d=y��@'��r�%��/Z�����U��h�^��2��qd�� ��4@��2��-�A-�2��K
�������.���#�!:
���r��xj`�~�i|���-�Vjb��������VXc�sG�l��n���F��gJo��6^`�S�jkf+���6�A����6k�6��Vk�G��yV�X
*��sRhc&#i%'ip��d�J[��
��2��z�i)������Rd�J�4�X+��[�o	�5d�:��^����g�\�[xir��2��>���RFA�u �e���A��-�������=�{��Sl��r��<Qn��S�_G�)����B{ZZ]�����������AJ+�~��.(1��+3�0q��j�4/��i��Y�x���&$t�^$M���^&�\Ec��k6K���LX���*��	�y1�0a+�6D�����#6BhYdE@j���1$�X%����Y�4�������Y�����G��Vx��a�6L"���I�2�Q�<��������pq�jm�7�F�.J��emDM,�k5%��o�}�����(�y+X��Z�T_B<�R�@�H����/Hj;�f@�.����{����R�a/[���PZV`���J������g��{jh��cA��H�B��n1�[�X2� �/a��&x�u��KX���U���xV�B�������h��������#n
+j\��p
��(�M�,��)s���fc~K�N�������������(�\*���hKIJ�P=��w�JAT�XKJ��^/��'�EFA��m�� ��@���R��4����)��F2:��QT�Q��Y���g��E=������QT���G����4#��PT����@Q�qp�(,G��(��x���S�Q�r��]V��� ��������u�Y�Q�_I!�d�zx�"Td��e|�8tz$UZ����:������u7z�
$=Jl`���Ly���I�)�����II�����4{���"�^�JB��I�������H��������4��b�u��B���TH���KB�d��J��������$aS4���s�@�Y�0��jK�����4�j�����`�����s-LN��
K�%����-Y����,F`��O(	�����X���+f��v��B�n	��l�*g��g���"&#��5��R����������9Cb�G��t����������-�D������$������_v���i�&u2<���-&
������R<].��e��xj	Nbdiyd����/�S�y�D��Q9&���Md���$��j[���LU�x�s`���&e�E�n�����u��IN���e��):��M��kF��pU����W��������dU��o�J�G��jO�]��g5��m�{����w�v���	��*����:����[��k���'�\�������,V�a�vy�v�QH�u3:���-�Q}a����A�^�X���Vr��=.�����#ld%�K��a��/�LK�a���:s}�#��%����U�b���rd�,�U����-�1�g���,^�/����h���\a�������Lc+m���,��a�`�f����[��'M��t�z��c�a��_����l1`�����B��e�� �P#�����e,���F��5,g�{�d��:���^��Z�M�^Q��4L�'�YY#2x���l#�:��-_�M,���e~�Lr����,���$�G���Q����2+)� x�pl���H��rXi�svM ����b����={��
X����<����ckN���8�7��!k,��%pVZ���Z���^��J	��G����Y���xz�{�ik8+l�NV������bJK�{�VLG��b/�i�X��W������J����s�-���E�2e�[0���M
�RB�3?��`�,y���f�����-Nr����2O?�+X'�#�&<%�_����z~ed�}V��E���Y�f�Su�Yi��F�kkv����Yi�Q���<`VXS@�&�������ZBy
f�5iV�Yi�Q"y~���f2���@��hgm0+>Zc�\������@��a
��f;F����=��wP"�k#����f��k�J=_QF	y�50��dXF�(��R��O��h�.;,��w��RF��:B�2JM0d-4�[��������~���pN��/�H&����_�aV�5p��K�L�F���k,�'�`��������8�ZiMe����C����)��VZ������Pk���[�V�P�X�b�p�R�J�f������1�s��VLji�\�9���aMH��f�����eP+mY�.:�ZeJ��GJ�f�D��Qj�e������\y���'��07��������Ed����E-a�T��8��S|��m���&�-%Kc�sN��e�{|5]l�t�?�:�:!���b��f$��"x'��~��h��Ij��T=�����zBZ�f�p/�:��Z$/+	5����}BZ�[��l�@z-�3EZQ����@��B��=U��e�b+ 1����]�t�F��
	����=gY}�v���������jXx��zZ)�����VYQ�������-����#�����6I(��i�-"��4��vA���� c�)f)h�%e���a
����u������|������TS)#��yQB�K��P���8e�P��c�>YxJ;��N3���Z�O���������{f��P��R�����
���������2�P&;j�R^K��``3Th�e�����T��F�W��A��H�S�A�_	�d ��`���h�i�C ��I�g��$�o����0Rdz��l���mI��
*P�C�(�T8����Jc�B�5}���Ba>�Jq���BA�Z�cZ,k�2.E����zc��J��#?�����g_u���g�������f������! ���C9%my;�kV����l�{���<q!��\'.�.n&���)�{
7���P�q�R�qca��`=PSL�<'G�����(g�P+1�	{4�S�C`��������"�ET"f�2�/EDy-��Sjp����S�P�@5��5�-M}"C����������>��R�Z(�*'A��M�GZ�����~9<��=�*���'�^4��X�+3�%�S{f��h��M�7��p)h�2�u����ECv�'��
I�7�SZR[�P�q{EKf��n���VB
%-^s���NJkG��J�d��i_9�v0��{v�"&k>9�#,eXf�oI���@�-ZJQ
:R8���ZX�������J��@S�Q��$�a�)�R_�5�>.����&�y�$��`����u���&����p���@���(�0�#����y�p�DTKm��\��@����� 5/L`*��f�������OF��B�W�g|1���4��&��6��hY,-;m��l)2�X�J.V;�h<��&X����S`���U�R���4)=J&���Z���,Fn(wrW��E�>�M�/#�RF���f:�����Fd7�#-�e5J�x��$��������$�����hK��O��i=
�/@G����+H��s�j�o�?�{�b�AC���/�s�Ssa�2��kECXiK�t�������s����#���5���2�go��������zY�J]9��`����xg �Zc9
���zY&�d3���%�,
a��j�T'���0y&LJ
a�-�_�<������+>��*S� �J��B
�� ����$�ne)]b"c�k�#�ZcK$r�@X�F�)@*U ��a�a������0�R�e�7�C[��iY������ ���,�%�M��!�������!���U��8�����Z/��������0X�e�T)�X�Z�Mi����5k�{N]
f�5�WE�Y�4�w�2�<���v�hqmDZeL-�f�~Z��~�C�����YX�6�Z���r�rJW�p�������R��h���N��Md�H�d@�2��e-�H���N{�	��,eJ9���'���lf�H�����&Cz�,�R,Ii��`��a�;��y�g���eL��@0��a���l0`��ruf�5%��n� %`VZ��������`�f�5��S+�S�	e���S�����f2�}��
����Z�&�h0�V�D��jc{TN��G[N�_�$�`�/c���|b�%[6&T
���Q)�5P�l_�6OV�5��$d�!��������0�z�z�$"��>2j+{P#�V�(����-O�����-�]8�N������$��('���3�C��������-c�})�������e����J[eM-}�t�)�X�f/���6��vJ9k�D�Y';�*k�E7�4�jk|F�.�V�M�I�Y����/#4��'[a�u��W���`���Jf�2eV�m_�\LY�b��m���,�V���	t}s����Iq@����`wR>f��_D`��Xk��lI���6��j��-�l��6e�6�i;^��V [������;�-����r]�?�����������zT��Ld�����f��P#G(.����B�������V�UFJw�=�t����:��TNqV��!��+�[��KK��u>���yX9d��F����+��VH��	_,�+����[r��jO��:Tz	5x�����MD���I��V�R�)y
�]�fN�Z#��I��� th�a}��s���������2���B[v���1!��	��8&�%Ot��T���/F�	h�Z���c����$G��O���g�>O�>��SHp"x]v��������)u0��=�y��nGOm����z�L�zj+6fg��V$�1������4��=
�l=��c���N��z&��7��g_��9�������U�`pCO��qd���$���V��\���SI�W�'�0z���4��g.���:��-[���tjV��������Om�����!m�c-����^"ca�`[
�^������9��p�W��s�pvM�F��\�+�*�K���ZC����HK�a�jW�Qi�]!�^@�E�X��?�dL�!fH
�Z��Ygn����l	g�9�*Kfc��&�5z�+b��-zM2j�2���*�`����]�tV*4=�&���+��%��+��'��x/���*������*��|��aQA��(��vm����������@���j�G�HH@�e�C�	�����f����ry�
#�v����|���'g���T����T��x(��S�����a0d7���i�X�= �T�����
���:m����C�9�j�R��0�'���{1y�����9�hp
��\�M�Vl�M*Mn���E9�������o����#M i�-H�z"�EPIj���~7E
��jF������Or�b0�Y�Sv���� b-�����QR,u<1������.�N���e�[�*��O�Q,�4�JY��*0��u%=,C4c� �K���d�U/e����
Xn(
��Ny�/�6���],	o:�����;�S��-S9�,vw0%��2��8�S!c����r
�X�]J*�}t��E�!uDU��Y1/U>�$���e����Q�R6����i��D�j��,���E|������S��"���2Z)��C�#�5��j~\o�}��!
�k�W����U���s�^��k�-&�6p�z<����R�����������O�A!��%�o��M��CnFz���5DzAz,�}���1�IUL�kW���r����P����i����`��-+Sj�����^�V�mX^��WB�fy�d���Of/�Z�����y��TF����#:�8:�J����2
��<��jS�tBqL�W�c�����5�A����`K���}io��e��$� ����T���V��J��/[^$DR&k����
e�V�Z��_4������&F��O,^&�R����i�J{�XR��=.����K|kk�P6+26�%{^��.�r������Q"Y�����2&G%���p|X���%3�u�P-���k�TR�w�Rj����`��z�g����Qy����S���]�y�1�Z@y�
y�j��Vx2
�Ubd��M�+��u������� x�o����"3j� ��{}	HQe_���-eG��j����B��A�u�#��8�	�tC]�R��)���b���@��K����:����J1���Q��|�uqfW�g�S,�{"e��`�v���@]�d����G]^��V,PW�3[�{:���&kmI�8����2��Y�QWHyEu,�q;��&���y�n��UkR�<�����P3B�(	�����]�&������ZF���>t�E5v����M�u���)�B��W�f��eD�Y�`��%�������e�{,CD�����>-�N{{�^��N�������3��~����	S�7��Y��*{VK_�����Z�=���o��w������!�V���)Re{A�!0�����H��e{�&���3/E`/H�s@JG����
��{��nV����� �������^i�i���R��i�=m"����A��}W�;�l���R�sZA�Ne~�dz�jC��9$�5�;3��7�/3
{��"E"�V���e��|V9e�;BY!W�}-��
���[�[�����N,O��!9g���Q���O�cx���"k�B�
+���+�+l&��[�b����
%V@���n���{�[�m�Q�!�����To� ��n�{_Y/�%+&��{�	���J+,��Vte���BZQ%P������V�S������ ���<L�%X�d����~]N&��"���R��m��<�^�6.�^��h�-�;C��7��]�N�t�X!��^��<��lWm,
r���5�/�SX�4cY13�R������:���SZaB���SZ�dK5��k��

<���Oe�bw$�P����e9��
��`ygP����"����[1U&�	r�TV��P�1Vh+*
;02x*+�������p��}�(7^�1���iQ���B�>����+��|j��h��Z0�0<@�n�O��r����������v��Tv�<��y���H������k�2����^V2���$m�@��;�<�Az�2X��*|=w9�N�
D�%_�����dI���3���W��
G�!�zu����-g�E�	<o�,�����}Kfk�T�������@}-�VMaL����q��L��5�S�<m
��������H��i��V�	`���;-�L�gO�vr����}�oAi=P2;-J��6�i�9�j=*��F���l�	�:���PI�z�/�k��%e�P#-c����
��]r!��[i��""��qT[��!�����2��jj��`���@�����Z8�f��m"l�E�;���<��+EV��i�Y�2jYw�z i�\�A%c@�2��;'yV�����mT�e�x�~up��X���2���P_vW�&����8�
->����Y-��U(��F=����W6�.N�`JMa�I�i��z;��x�hEK���>�V��2!����r���,�@��Ke3
X{"jAg�-�p�����n���*
Y��S��uT���K"b�jb��S�!%{�R�����@�_�
P��dO�!�A�����������W����bJcN���i-���E�~c��`*Wt�����B�1[��:9����N�y�S_@K����R�qI��L�F��A��
�kM~
�0��
�f<������J-J��NN
MT�GP0�Y��3�\������b��B���}b2j�v����e�����t#�Pi�6O�W���J[��J���l��k���^/hLqT/K���@J�����I��X�
������T��c���
���:�
5��W��`��<�����S��)5�>�q1U/mH[���k��6�(����QU��>^3�3X�D���:�j���z����X�����)�t[������f�J��eI3����_�f"�%O����kIW�l?)����~��&���/�0��%������yGh[��G��j[��������z�k�h�J�,C|�`JM����Wm�e��ml�����_�-K���|�������9R�p|U��G�W����U.K�1��f�k�����Ri�xiK9+<9I7�U�R�GS�5|U�x�����J��6rJ
�QA%���t��ty��Qr}'��k��e|%���Wm��|r���d���R�%[��0)��-�tK��������##R�g!
c�2���V�P�e`l_�Wyx1�`���g�)��`M��OX�5���ze��x�+$.YQ,��] !8@����
h��=�i:���f��s:
�I�����:��E�q��������m&%��R^�:��FI�V-�n���
�W�jkJP4��p+��������V(������YaM"C��5��;�� ��[)��j�T�`�e,�x'[mJi
8�CA����@��e��C)��-�j;e^\�>=2Q����6=�����m�*\n�&k�Xs�b�P(M��|���.��d�@�Y���y(���=\JMr��l���)���E�y(�����"@��-yY��
{fg;��@�rJ� �MI(����
)/�xF��H��(d5�k�Z���*c�P���AWzZ�����~�eerS���w��(���r[���+1��'`�q?e�V<k��q��Z3��������2��lI9_*���w���7������!�	16���j�y	���qH��
 ���~�=���VZ�e:x	-X1c�KT�$V����*+*C���VZ���@x�[��(��k�����VZ���i����V��������I	����G��R�~�2���H�z�]�������H�RV\����!���[�k��@l�a����s��@��Si������L���L~OKJ'
�7�Kjc�<�
gc�������O�{�y*%�P������SHX
5�&��)uxY�2%��l�I�������;�������G8z&��@��^��%�3�I�����Q�z
	�eDS�C����O;)9z�O������Z��
+&�;�����"�7EO�.�=�[���)t�(b�kz��xf
��z��
r,����5�7�O2��2 �S�V��6�C[J�g���N�v
�e#������	(<����.��/��`����|��X�=����c�H�=WJ��2��UvL�kr������Y����C�S8��0������j9j��N��)p�9i4�0���\�RD<0T�����<A
?�����e��-�Q��������(����������B�=��k8J2����6��i�j����Fi��G��Gq:
�p�6L�����(�����+d�(�R��FylK	���` �����	���H{R�,�����~��'g�C���it�0���-���@Sm��\���-��X������? 3����\�6+
yYYH 
DU��YG�@Te�����6���^�z@��U�1Y����;���\�Q]��l��u�OCT���jt{Q�������kR��L�o�K,�nQIF���l��������R��S�ySDS�c�>��jS���]�[
Q����8p3%[������-5��!�u�2}
N����l�������Z����S�5�7�e�5&[j)'�[�*o����d^����hK�4\qU�����4cZ+�L���)��V�j�*[*?��{����p�M�^j�N�*�U/����L�Gx>wp2v�x�{�.��X�Ym�Q����������v��*$|4C��f�W��I�������,�81�E����D��m,��Cj�,�(y�,Z�`��A+.�����l	�Rh�:w���(�#k��(�dNB�Wy7���(��g�")s
h[�!e��(mY�{�Z���_�Z�-��@]Z���t@��V2e����V0�^��0�p��OM#TB�JP�d����V��N���)��mO$�z����������i�*l���
t+�4b0e��8iR�����?�3yCW�Q�l�]���Q*<����eX�{�����U�USx����7�!fKJ"e�����b����m)�)�t��E
PQt�d��Gr�k��O����@����$�=9
���
y����B�^��X�0$�@`.Y�!����Y�����*�U�cO���*;�&�\����#�)�T�Z<K���TU��r=,9h�}B�a�$D�kQ�3��P�!��:�8�*���>;YSvi���:����>��]�`����@|*�TjQ�t&v)�����DYm����gu���\f���![-aS"<9�y���NK�j�m�?�� �����_������I�H�R��k"�
I�5v��9V�
�XkP��
4��|��9g��&
4u|?J_im��k������5luP�������������KC0�k�k��x����>�!��9V�J�e���m��4q�E�xGK�3��U[�		�N`�n��$4��W7������0��l��������MPy�YPc�yz)��XkvC
����Isn5�e[^��PK2�|���~ee[j�n�����5�7����Mo>���_���ap�k6%�+��5sV�b�K��*5<9��5y�Z\��*����5����
p��W�*����d-V
p�5O"�����f���@x��Gx�6�ec&{��Sb��5yZ�	���R�?�P��.XS6v>��1O;�d��V������o�+���mE�pAsjP71�l�r:pS��J�d���'X�c�����%����6�D'�;����u	����o�lB����M�����x�N���$X����U	��^�#u��[z���J��vj�����J+fk5����}�
�����r-f�/V�Z.����Y�O�������>�\����{�~��K�d@e���Zh��r�d-�X�2�h?��Z�����5�.�\�������5VX;�,kJ��H�@Zm��'6�hK=j>1$th��A<k*�1�]��a%xN�;2/J������x�;2��k�>��z�n��<�8����E
<�V;S2���������=��5�z
��V�f�����<b[T������t������6�����lPxJ�J:�5���]xv%���<���:)�S�����}+&�.�w��j5�����:xJ+jl%mz���-���x�����j�'��}*R���E�xsJca��������H�S��,�4}��G��(�>y>6�6�$[f�;�����������?���4�U�(	��l��a��~�g���I�a|�Pak)Qd�bo��B���>B�[���fD�v��������p��&����r�����h�QT�1��1�:�j��Xv�c�nU?19��B�e3a�;�Q�Ic{��";,�4�����ru���#���i���*��d��=xwv$�����6hH�ET�	j�H��X(���L�D���H�z�3��:��-��a��dK����I���e�{�*��YR8�f�ai��_�ySv�?�J�t�����$�E
4U�X�1]��-�9K,�TZby�	{,�>��������;���������%�7���UhaD&�6�U�1%�����g�Lb��u���Q�/+?�>v;%����X�y�!���������� �JT��'e������.�1D�",�����dJeB�h����NS��k,���I�S�����x����	<������"��P#�H��a�@�����9���B��6�����&�	L����X�g��!\W�E����R��X2�[�f�l
��F��6���9>pU�qo@�xRz8��Y��2�t8�jS��;t�qh2V;}B��g;�%�����t��=�@���U��m��$gW!���@[��*]���>����!��jX��Ri[��Rp��e'K�����l	2#��:�&Oh8��vTv�Yo����%���;�jo��\���/������/��/�YR�w��@VaKI���_�1��U�b����@ViKT�dTd�^�'sd��L����8�)Wn8��U�R��!���w�u6&(�y�����e��H���J��C�d�������Lb����x�te�/�3��
�V-T��y�`�~��J���~��)Ir:\�+���W���2����:����I�d���<#	y��8`=���t�����
9���-Vu����2O=v�^�#��n��q��__,Gm�kB�����H���d��^�z��e>�h1�U��X�bV K����&���� 	�4�U���Z9�JS�IO�4xU.].�}=�5�R��^3S4�i�Wa�q�cS�����������er�5��U-�f0���+nxjj4�	�3Zv�G���t�\����5�cKVj��Jv�<�$���Z�C7W�W���Rb����X
^������������)(�K���+"��
b�"j]V����
p�p���N�{]���%'g ��xG����������jF)�^�=��\�)s��>����Y?^�V�V}�C
��R���A��%v����%�}oP���*��V<z�d��|Y�[
�V+?�B��q
GV��
��{�rs����*qm�"��|�9���+n����qU�0z�4 L3�t�z��O��I��d�R[Xd�
�a������*7D].����3���/�������������A�])e)����*Y�#[yVm�q�S��@Vm��4�l����lYP[�*�)s��]
\am,���+��e{K�����+3_��T��!^'i���@�DCXi���m�4�,a�|
��Kc,":��@VYS:�'�j��rZ�N���_��Fn,��	��T
�H�@+��L�t��1��#�n�Z0����+,����SFE�,K-xI��ly��
�-�$��~����{�����?M�u�����&c{\�������q�f9j.+ �m��?����C������"$������������xWc��t)����M���F���r��0�L����}��5q��m�,W9k���]�D����z�Y�2��v�v�5���N�����S��v�W�584.���g������^y� ��=.���F
��r����7�<����_(�����o<k� 5��E��W�+�1�V�4���&?&�����[vL@=^��39&����H��h�T�p�;9�q��������z��1d����S[�s�A!���������Ia�;�^e������	ib������G�������\���i�!�)`4���'G�S{��o4o��oi��G��k��^11��hy������G_��0;����������{����==z�+���c��i���^M�"��jSF���Yx�^"���	d���I"����'���IJ�q!�w05�V������jhx7]��'����p���+����x���b���hf�mx�G��nx�Cl���fM����R��;�\���w��)�7�N�9<��I��54�N�6��
����rxG�ue��h����;�_��h���r��o�������U�j~�{���.y��J�xZ���
��%�dl���<m����)����%zE��5kKG��"W
�z�v�n=~Ma���0����3�a:�	�_\����CY��h��{�y
{�9��8����)��G���M�H�5�#o���8�itS�&]�=1��<�{��it�~;�=
�I�==z������C^##|�_�^#\��G��Ji{A��d�M�@��G�!��O�R���F*�1Q���J��C���p�Kj��@k�u����,�����Y��\���������={Zs�+�`�?z���{Rs*^	���C���=�s�;��Gs.���=�9�O	��s���i�!C(`������`�?zc��=�<����PZ��5��Z��yJj$~�+>68pD�
��CG��
^\�� zZ���M@=)��e��=@L)�J:P�=��H(����[C�����g����~Y��z���e[W9r�mT���������e=�#�Tss��e��Ty�}����E���,��Ok���v��[��pw��G�����)��=����U/�d����r�M���!O�:�9�Gg���b���#�����k ���� (4�4�A�s�@r�S�~=��O��I��2��5����`����?�l�2l��w>�A��R��� �Q^M�
�� �R�R�rD[j�
	f�kI>�����k��X�e����k�m��9m�{A�:gv:��DnP���8��6]n���))�0$��G0���B����8���D�C��<�} �����')���V`E�&��e�`��N�)���
R5����M5{�kI���1A�|�l�]���c_���R-�v������E�P��3X�"

Q�k)��}�K_�aQ�R2����Z�W9�$|�-��:H1�Ip�A@5`�?�V|�������w���������`����XT��U��"��#����frX���FHuX�a�,����2`��Zv,��������������0,�������j��}n�u����t������+i���H�����MI��wF����$zLt�pp�"�)+���2\�)k�"��!@�h�M�[I��/
���J�{�88��`?#����[���0��(~|�r��x���d��XE`l��I��� yX	�������'/�bF�5x%�3���#��`
V�(:J�A_LGIeAF�()�'$����4���GCI1�OK��,y��r����8JJ��$��P�tr�Td��y�xB���tR��t]!Z���Z
c��u_��2����X�al�����������V�jk��4��P�CJ���Lv�*�9�RXKl������	6��=��#sE&�3W�{7le�n[�0�5`��J����,�j����M4P�o���k~YIe�q���(�[���ZS�.�pY``��1D{�k�~<����ey����C����
!��%I����[�f�C���b�=�����
Jy���xQ���cw����V[�E|]���P
$��0pQ��%��N
XT"
2/�;�3�,�������OE�@����<�`�L����ge���Skt-$��H|���
g���2�����������V�vh�k�k�cD�^���C�r�Xy)��3�%�Zl��F��[GN�bA�����<�����.��
��[�0�C0���	��2=.��f��V�.
��S���:XkJtq�^��7h�Q�^B�Y��a�D�a����j��>A�����?A��R=�J�xc�A���S�'�^����9Kl��]sD���f��� ���i�k��?���\��8�0*��MO��vv��,����YNni_�W�+�W��T�aUy�rNX��-�T���p�_	!�����J@���g�a��T}��e��'L����x#��6�RB����T�d�R��J��)t �G~58����,�R��W��|&�9t(�"�Et������r�Xq�)���w�L��W
��D70�[�v��_���I^�IL�G�pg����it=5�ohdb]������9�TX�ZB��N�%�1>�m�{��%~/�p���-����CYRaB��C�6�������Y��.U;�����K��%[�N�JK^���KGS�_���c��L������0W�w���J	��
$":�j+�W�n
f�*$l�d(=HzDe�{�Dv��N��SY�r����Z�b����T0e�	By�,�����L%[��'�:��-��RG/SA���������c������jw�U��+����uxE�c�^��D��0@D����r]�����m��='m�my3jc�GCVZ����#�2e-�-,��&d�GcRl�eI���*[v�)
O���l���T�X�����^�
�<�{S���wlJk�=f�*	�E�����n���H�����^@2M@���B��Al_�VZW��X���O3p���u�\�����k��$��L���HBZ��Z<�*6������}:����uh��_|�b�^�2�����%+��o��4�~!�B�WiK��`����e���)���m����������:i$�U.��U�I!�U�b�+:����v���"����U��b�:K��5Y���W%"<L[���bKQ��e%�L���M������8�h`
�U�l�ik0m���h
&e3�9�E��S�eOdF�&��������q����n����*g���2^W.4�=��A�������]��c��_�0;_�eW����=��|)Z��RNo3�;�*sY��������z����(���j�5��$t�`M�5�����I=lm�Wz�U����B��4s�j:-��*��S�(� ��V/Mm�<������Av�[-�i0yD���-�dI�j�[5��R������$���S���lF4O�nI��^�5_�^Wj��$��P��%�xs�M��NNv��.p2�%_�we3fo��<)�d���^��>.����3�kQB)K��`����-6������8},���RJ}M�\L�����/���#b<������l�{��{tG�[m�b�y	�����9����g��������]�r��g�a�[`���A��t�����t��_I3�ht�2�g�Wr�k���1�c���`�f2F@WlG�w~��R��+�w\%�A&<9���e �������d��+�(i:_���`W���- �]�Q#�Y�*�(�O����\�#�lj���l�G���g����n���r�R&g�H�]�
[�������W��:�'�W�S������������+�)L�&��P��>��tq�������/��V�*�)�*{�>Ti8�l����+#;2�"VO�B�����]v���	�$z�&�5y|��2lB���
�&�et�%S�.��
'��rYnF/������&�$��
)��wU{�%_���`�$�-^�vA��&L����������2P��o����M�����$~
��R���OUoW�=����$��q�8�@v�{j&�@��S�r�
��W�S<me��^�'��_�N��1�W��%�t
x���K�������J��x�={-@�0`�Q�d��@^eL���VrrJx��l�.u��n�$c���;#�~�z\+�l����1�U�,V_?p�2zWz���c��_5!V�K�_��13���o�`�fYG�Q�}��[����ZZ���B��%Px�v������ez�e\/'i}��r+�ho�4�)�wY}���~�r����K�5�2����kw5�!��V�:�dE�-��B�����<��D��Bk)������Q�|C7����`��F2�w� amd�7�&2����al����!�r���w�}������1����Q�-��i0
K����g�z�g~ju�G�\�
���'�Hx�G6S�o���Rlp�k�Ve�j��9tjWzF���e���/���Y�e�[�~q����6�;����V�@�GCeq@i����4���ps���4�mxtH�Y��5��8�����������h7\o}}4x�9�������zK�r�{���k�Zs�A�v't$����y4�#SJ�8PO9������So�Zk�[�
�w8�s���O[bA(�u�����4�-)@o)6�����g�HYgl
�������?���M��z��L8�@O�6��;���Yg���X=�sy�	���M�Kzz��>@�7��@O��I�
���Da���WF��hy����C�5@F�����d��%�"
���M�JM�o��;p
._��T\�c��*RD ��Qo�T�<0��_|`�g���'i]�3k�8I;����N�q���1w�9�[�PO��I�)��G�w������h�Hs� 5������h�GG�_�y��y��\c��h��4P4��	����,�Q�W��'F?9��QF��F����;��oCV����F;��]���q�;�	��h{	����Z�Zgl>R�	�2��=A���`�|�5� O�\�Z3b]��Tk� S"���Y�%u=_��r_~�e��O����i�n���r��>�5n�
���ta���*��OjNY:|������G'��|z���2�4J?>9��m��������5���Go�y��4�#��G<
�����y'�k�|R�e__��W���@��� ��j�CV���d��#L���M)E������t.����2b��E�w��=m�Q%���������ep
��H�ZO5x��^��O�8�]�uG[�����3�=G>�;5�#�uNi����j�i��D5�O�;U�[��l�s���C�6�O�;����-_�m2��?:!w���C�@?�f����
�g�j��ul���o]:�4 ��d���Y!�X1��a��Qb�_tq�#=j/���el��.��i[�	��@?p�R���~����:�)��]����+�%NjG@1�UL���v���������N3�g��@A���l������s��%3��;���%���L�_g�O���
'��)��C��u���G_k{N���ZX����$��[s������	���='jOi���� �SX���S,��1�1Cq@#�(�Yo=e"��0��j5J}�N���`�Z��t�I�I�����A�Vi�rj����k�m�����X*�(��3Ev5��lU����H?O90�4�j��v��u���_�F���V��0����F�>j���C�vF�����80��P���K����3g{�j5��rh���M�A��?��4��O�
����Nj���Q��I��� �j��=p��j��c����Z��f�KI#�N����V.������m�j�@��~Y���sdc�$���Q_2�qGF����"�T��e���R�'��;2J��	���fv�@FTx���?���1����(��i{MCFt]����/������tHE5d��wd��CF1�RT��Q ��9^������b�4uT��f�+��#��!��W��F�����Q�!4��2���%��ZF����r�#��Vz��b�l�z�I���R���e�wy$ &���;��$P�{�L��.C����}
�x��6���7���=����iR#���k#���Rj���C����@�@Ie������Z[���n��8IN88I�����eJ,�
�)�x[s���H)�W���BGJ�U�A��q����=
)��Z��"e_{])$�r)I���/��$��+i��a|�Y7(c��Z)R���R����UR�<��z,����r���Z�	.R��vy�����'cj�8���+�Y�d�zg=���I����m�~78�*�	�]'$V[���
��rYg9�S���}
,�	I���V��'��2���]N�S��[�e�����/
���e�^�Wh\�/q�b�})'�[th�����PK-k--�`�^�0k�K���	�KK
��\[����E�f6@Zx��S��9\�;�s6��Jl�"0s�"����#\�J��)T�!�|�"�QjD�5��rys�v�gJ��~�4���.��Vd������C`�����:�(���9_��RYQ�*Q������^M����R[ax�{�`
	_���_1���[]8dJ+j���8f�Z�v�	��kv�+2��M�]%���0�:���Ed
8��J�/2���M�A���
i���j&��f��B�Jn��'��va|�)��� �O��Y��@�#-�z (���8 l�� ��K`(��^�NS�/���dS��gK����u<aP.Y
	�v��/�*-j;=����ga3�b6oa	vx���"���E-�� k�\����yef
��r�{hCR�V/�G�JeG	�<9�%�T��06,��H���T|�s=S��������<B��R)�<"��J�~%�o
K����w
K�g�nUE�K�Z8�D���� �����[m��&!�j5j�8��R��g����R�Q["��Q���F��(��@��|���X7$���^�;��$7jO�x*d�
����2�q�����������nD2���1U��[,w�-4��9��v�l��m��m��)V��6�5��R�����ft�g�F�
.6[���V��A�b�Ht�^ZD�}��"�S*�f��K�}����
`�����zI�=���4���*;,Awb������������%��KZ��;4!��r�K
&�/�����+�_I�����L�W�c�-�2|�5)/�����z|qs������6�r|�����M5|��(s[Fp�*���&gn��m����t����=��	|�����K_�|<-t�_L
_�)����s_�)[�h���e�:�_�-�d���
�b��Y/,)��@b7��W�������������
�0������z?w`��e������>Xd�q6H���{��Aw"��{,�(�
�f�-��"�	�k��g�c"ns�Y�Q7���� ���d �|l�,^c\����P��>��\�8+���p�ay���Q:��&1�qV�Q4I�������}d>������}4a1w��9]J*�59���X�N��8�l�5��a
gaY^F:�JS&k/N]Ag�������giY�M��`���B���b�u�4;��e�����>pV�Xj��8���g���@lg8�M�6�pu�j�
������p�e\GjbS���f�ZF���f�����[�,jQ�:-�����P-��~�l�G�f]o}��a���/��-�_��z����zj�V��	��K���5=�5�2J�eK����3X�Y�?���&;��g��-����dMI���+�Z����j�;�y�gmMi7�L��l���sh��Y}6���������t�Nh`�7��N�L7`2��8
l�-SM�@w����<���P��V���n�`�2��<��o��J4� ��4\\jA�V ;�V��R���,����-%�I~�%=�F���k�lp���W�4�h���Q�>��}Wi��R \�2���0[m����U2����4����ru��9W������V[�eW}�/�J�f9XP������zjxp�56����r���
��t����@���m�|R!���/���09������n�����:�\����4%d$$�
pY�����?��$7W�(��HC�D�P�d[��/W��u���\���)g����.]�4
�}	%�R��������0��B���J��a��C���Y�r����+��Yy9kz���U&�w\�1��Nx�5�k���L��\��+I86��2�]v��\^�
�@�d���LL�`�+D����P��7�|6��/)�u���rz����Q�J�=��-�v�_���.�;��JEj�&�X9m�T��&
t�Zx��/�a�$�{c������^qA�����j��)g=��U4)��RvT`�p�E=V��^���x�X
�.��V�������)��%�m��/�y�I��!��b��ql4���o��>�������b`4D��Y��������yP�\�����@
�m�p������yP���M����0V�_}c�(�;m�+��%���.��da���K2J�
��~����J9��G�]2eB��z��\����K���>a����\�i��R��y�4���,!M���.�S�&M���J^�
�`4�h1����){���a�����oC:������&�!u�`�w�;��n��x�u6q�=�A{4R�����?�6�=+���g�������~g���v�v���=���Z�U�a}����^a�M�jnG{j���+_��k�Gz���p
p���x�,(�U����1�����?�����w���������z�a	�w��`�Bo��~>�y��)5�����xr�6xu���!bp���N��_�|�;=�P��X����H�����3�����R�s�fJ$r�����v��w����S	/�@\ws���`!NkQ��Y�)Q�Q���������6��JQ����9��vF��Ex�hZi
������g�����VAG�����Ip���k?�|��M��p�9�:�������oC.S`�
lErZs(]
��9��v����u�����&�at ���P������M`�Mv�Y��v��i(������;�+)����}��'�!�I=J��LaY�<Rc���)�IV��i��iS^��+e0"[V���B�hK�a���v�]�ph�}�2KA2>5H��GW���
�~n9|z4�A�	���&��~;}�c��`&i-��~��|��;�O{���=�3�n�!p���I�|�9\��@s�������|z4����]o�H�1I��L1�V'W���7<Vc-44u�0nJh�������l��G���?�r�#[,�����)�-�����BWA4���4�Y�n���T?;e{x �R��7�I�1�������}Zw��i��I�5���g�����:d��O���X��Dw=>����+7��w�c�b����
�����!��]�G�_��m��~��
����xr��(�OyM���P�f���aL�qu�cSf���RFm�9@�z��5x��/�M���$��[��HG3-v�0G��~y�?�2&���?1�=�������g�����5�������R�Y��3�>�����0`H�S����$�aNC����C��i(��O�J�'jO�[��_y�7���n��iZ���%a�3$��������>��.X[p����h(���q�@4��PsGC�Q���/$��yB���j������$c�4YM�ch��P[GC�b����U5[R�[S��wy�}�I$A�@��Z�u��Y�������������b��K5�O��I`�DT����e�Q���W�A�R?!
H���<!�P�M�~tPT�o�57P$����O����,�/oI�`jwj��V*C�����U4���� k@��������7l��^����0x��:0�E�s0J5Ws����X�k;�����.h
���6����hKi��'���e_;�pfm��k���5�?ml�W�����$�4
�K�i��_;wi|@���^�4�94��3��4���N��>��4�����C���t���>�D+���?�F����P�h�����f)4������j���d��Q��$B�[c����o�W����a��� ���B,���My�r8J%����
AF%��nqk�)� ��A��������6h�2J�r�J4n�e�)�	��h�(F����Z�z�M)��/�z6>9>J���>�d��T���d�C1��%�_�����IvH`�2������)4xf�6��4,�������������T�h�2���8�8),��F�$���8)~����8)~��8
�^�J2Ee��pR���|+�(q�DF���$�H�"'��Z4H�R'QFi��_"��T��V���0�RZ?�R����m��m���ML�4��FG��hk*	�����_�(�@�i%�>`m\`��a�Je�V��5XY�ii�7�LC�l��v��&f�f�L�������'S�^f6H����
���!&�^���4X,�*g��_��!
�f
�=\b���������/��_^n*�8Co�
7AFmP���$26��n���u6��/i�~S�o���QIL�.��&��UP/�I$[Jy4.	��2Vc�����y�_���3��n����^�����N �������!�!���i��@���)tX�������JZJ�����
:�\�Y���v�GO����X
<�N"���r%�
���de?ROX��
P�1]����zu��6�S}�v�v�:��y�~�	��o�Y�O��	�>|*��t���KaC����)���U��"��XJ)^����'���	j����� ���@�]�'MGy��g�O��lW�h����������y[/K���D$������l8c��w��
v�3@��]_�����mS3P��b~kc����I����S���AHyu�$#�|l�+a!<GIGi:�Bd�5����a�#��5Z�J%�Yqj`'y��t�ObKZC;r���t�h��0��f�c��}�	KQ��k�|#����2!IX�[�2�f�� "p��C�A�f�M-��gGM�P��)hJ����@�Q��O2��J�����!��j<��eCv*���.��K�S������c��"��Kxy�t"*������t����-���-�SY��\H���d�6'���������S.���@�`�:���Z�S*TR����d�f���ek�t.kG�3fF�%k��j���C�2 �y��]5�����R�Z/n�l����-��E�J;�>�>
	������$�|�;�G����T4��i��
2J����� �W7�t�4�d:�L2P�,�k#�V��d�R���<�;IO,������>!V���P�Z6c��RY���M�66pUZ���\�Rk�*-���$���%Y3M�UeI��R|�qUR��R�
�X�A~3�%�w��U�$�M����`�d2t�
�Ui�b]8������P?��JT��WJ��3!���UZbUI�Ya��iM�4Y{_�!�qf�,R���@�C�����2�ZIF�_���)��$��j5
�L����e��k|�R��d>���
2�@����l,#u��|�N���v�b�W,��b���*��J0p�����
fY�I��n����5��u���U�bG.|5�V�d�3M�5�����9�����bS
���g�\lN�n��eYJ��j��e��h�u��U���'�X��>=�H�Yc�z��r���j�I�����i(�l�qyL�u�U���%o�����Y�������(2���Ye��B������Q�SS��/�(�Y[�gX\��2�e���\4@�@Y�d��x��;����mE���k��pH��:k���Jhc
g������2�����$.��OlM������iYi�5V�G������K��aM�im��1������;����`����:����8���%����4'
9��O��/z1s�����&���p[�f�)��6T��kS�[0e7Z�n��xOF0��V����.���e��E���p�e��h������y�	YR�P��p2��x(�6�Y
n��c�����mw|%8��]	��}�h����Z+,Yc;����[iM���@i����9{=��>	��������[m�b�nim����[m�jWlM^�p�=����4'�����^��K������?�����^����d�����Mwmp��Q����f5r��-��7��r����9���|Y�~C��Qo�3e������;�}["�L2n�p+e���.�(����'�����L��G=I�Qd�o����&�Gt2�B���*O���F��
r��rp��N����Rr2���\������9�G)n������Gztv�Ek���`M���i�����������B\"�7���Y�J�\!���B���A.~6+?�:��I]�����:�
�G�]z�[^���p�-kZj�����KR@���\�k;�
=�m����rAF}MJ@�\2����l&�\�FM{G2�S6�o��I��-t��E[���4������c��ez�e�.�������e���F�}5��5��KH{��_&���y��a�;��h�&v�{=�r��������/���a6�{���{����l]_��%�9�=��|m��g0:�x�
���u��������\^����<m���X��5O{[��+i����1�$��e\���*`����V�d�KKX�))�=N�RoV)��t|��v��km;��.����
v����K|�k��)�x��l�
���_�������=9�Z���h�
������Y����==��������c������oS����y��~[����jt����8{z4��������C�J��w)4�^��Y-T��O�oh�����H����{*��+�X
{�e�W]M���zp���=-c�D	�{`Kmw�s�_�.S���?��(�mO�N����h>����r����[Q�j�+k������aGk~A�=��H�O�5��i��7M�=�\g�����>�h��:��h(�q��uVR��v{0�,��+yU����zY�3Za^<��^k��u�^���AG�3���~s_c,`�s�����zT��L��wdKy���W�;���^�����g��@G��HNh��m��:9�O�6��������5��V ��m�hp�����xZs���O�94�
���t��xRsbD
����5������?:��@<�����G_h�D�s�����e ^�=���U�/z(c+�+i|S���
�P�m�^�G�	����
��%5qXf��l+�.Ty\�%�e!�K*����7=z�X:y8@O,;�ngm��l=\t��A��e�"�������n	����Y_�h�����mh��`���8�:�i�
�Hm��;������@�+��������H��`prz0��t������C\����<}�| ��
S�#-JVuJ$$%�g3������G����7���jY��6t���J�B�R'
���#-T����\
�n]�)]k���;��3e����z��4gE�]*�R����!)�o����%PN�T
sr��r����N�7���AC`�D2��&�;�e�]��W&�	�����c ^��4
���	R`���o���w\��z���{��n��8�{�kn�?�wBA����M�K)�@1-�*�!��SZ���k?Z�����h���\�1����"�S��k�	6�����I�[ `��+���h�)�1P+O���B{+v�7=k�����
�����Q����	NC��
���\O8������;k��#�,z�)��O�_�b������/#
,�~{�w�T�'^5��G�����wE|�ix���
�;*gi�z�+�D�a�CP�$��m���Q�I7b�	<�z�p�@&'MG�X�SZ��	���\/���e@eG��c�Q�j�4�����pk�	Ep��R����c��{�#�������/���&��>��UHL���
���i0�������R;Ne���}�]�5�D��L��������X�i��_�pi��X��Vh���
����b�����j*��4*��Q�s��_X��r(34���^mhS��
n��4�Q�������1�F�c+��@�]���GzU|���8x6�p������w	p�����C�c��<�7p$��(��Q�o�t��������������PwG5�I�i������8��/z|�����,k��>���(�7����(��,�'�����J����<���Q�����88��P�����1����8���Ky+�L�N��$b�����r8RAg�#�(1:o��#.�[�k��QZs��5��fc���4���i�3S���J�~�MZ��j
�t���c_�u�|q|D�]�zIkvK/�������
��!�;�GXiX��b$.o;F���5�&'�1�(PRY`���%i
���������Y�f�pRX�%�}����.�d�<a�,�
���-y�\�u������C��t�D	KE�'C��TRRc���5�;Nj%Of��S�$N�^��3�D[HN�DK��j5�����>�Sqp���8�]R���j8����u\$��9ZI��I�������5)�
F�	Xm�����C���h��8V�e�,P����d�:v�$W���@KiC���m��J$�R��-^��1��u*jmv�m��&_��1�����@L�A�������ef���j����Rl����Ki����L���r�;���S�L��B����L��V+S�r�Q�����r�e5�l�V�k��T��\��ws@��������QR������1 �;��]��\�����������LeC�s��o��n� S��6d*���: S�0��������ae���LaC��9 S-�q��C&�@�?2�s��L�1��k as�����`<��d�u����A��E��������AA@7 �/�Z�*w��	5�1Q���h�.,���m����Z�z�w���v��2��4���5�T5�$[
����hKB��o���!�aTk-F[Q
��y�J-a��@@���)d|�hW�-tf4j���dGi�8��,�u��B������R@n�������%4����z�J�c1���c��Ek����;�����UP:�
	�s�n��:Y
HY
 :x"x3 UV��r�eSZ��F�:@*�h-'���������V��J,$�q$l��-�Q-������Q���IG��Za"e8��-s�d���}���.�
61kH���@t	$�Kxyg9�,i�;���$�HK�%���a)Xbg:��`�=2�Cc���d�z�8�*CV������$�g��x��dK��O�%�������]-�39"5D�����w��Zx��Z��ve��[>�5L�vX�����S��c�U�o�
U�v,��F7��]�7=A���
�ku�f��![�aU�����#���f$���(�:�&�`�gc�l�J�leL�A�����Mau�_��I���+��j����U?@�+�6wj�S�:��Q�*�R���T
Q�%H�r���0#��� ������/uh��T[Q.�T��h�c����50��a�G����T�1�"�R��UCR�)���4�sdY�+!���M����T��o��=�q�w�9��W�������a�oEd��]7H@�9IK5��� a.H$L�\���22�-�"(�A���YAwJP0�"a��(��t6�\/��!��*)������t��u��6Ge��}�����c=%���	rS��Q�vIH����
sL�()m������T-�Z��)�7�T.K-��:{k'�.����j[H��)��f��R��LL1$��@U��~��9X��}=^�t�'k&���##�9�
[*qZBqn��L��/&��p���@�%T�py�xU���#5q|5,�'-��2
���j2���j@,MG��������*&@�mYF�P��2�;T!�(�_q)i$������m}�$e\�l���>o�}7pV[S_Su��n���J���7�jkj�P�Q4���� ���nkJ��j"����|���

l�5�d���w3Y��`v�
��k����,�V;����
��n9���5����,�/���S+��������&��n�)_F��1�jSjr�>�De�d�A�2��!���zv��I�j[%��j�J�g�����e���.�Rb���� �s��m�����x�����n��)�J���]�Wa�Z�c5`.XS�eV�]0�kv�2y\e���)��W[S_	���W[S�G��\���Vjj|q�����SBs���m3�p�����a
p�������t�,d�A*W��KS�	OS��0��8�J[��m�~+D���=W���r�JT����*Q-�R�p�J��-!�[-���V"�p�Es}������FO��&���p�%b4�t���r�z�,�0��%�f�R��!WjQ����"�nW����p�5��[O5�U����7���*k&�%������3�p��'�5}h�+��}}%F���y�����
p�R��e�&pii���(�?���*`� �/c.��e=l�
9���
[�g���W���pp��9���~�%%	(�-�X�bLu��x�vL��x+���V�Yx�
�*�M~������G��dK���6bl��D/��n�������K�G���?.��Gq��u�L�E��~��t��7m5r�������5M��<�)F/�u�����d��4���q�/5��2�O&��s6}�m�����h4T���9��+�>j��������]�����F����uQ�'�+����������5:Y?�J�N����#n@<}%�����N�2^���wj��2��6*Q�S�6�(
mF�n����H���A��V�����;�����!</J}�O!o�<��K
y�qFB#i��h���u����& �?��7�����!O�MU@y��< �W���9�h@������i��yz4�O8����y�����<=�@��G��f��5��

���s�_+�'�;�Z���S���D)�����%J��0,��{1D��6�#7~�sD�(E��I�'����-��E&4����g����9�$�����q����
���>������:����e��5��o{Zs���P��@s';���C���z���f��C�M�=����S�Y�a4����=�m����h�t�#�!�k�����JbOj��:5`V}*OKP���_�T3��<��)��k�d����:��)O�.I�	��R+�r,���	�o{��W6���u�]��GF�I	��#kb����G�x�n�������|�90@8�����5��j�����|Zs`��#���#���%
q�������5��b|r4$�6���~r�N�=�2�4��[|��r���v����z{��!N��S�o{�T[c%G�k�c��`����2���8��y��t�C�/�M�<�PFH���� �2
����$?��A��e�u�M�G��H�|��]���������kV�HsM���'5B<�x���t������F'Ok�}�!�o��!���.��x��3�@���P�����E8��S:r ����J�xz�~�o��GY�#^tC<������n���3u:��������M���d��i�1h��;4�%+K�Z�U�l�kYY
|Z�;�}��q>�,�Ol|�~�ur���f���mF:�Y�~���a�)���(H�As�0����:�������\���W��^�b���i��4O�`��i�OPkI����������9�q�/x7����;����M:�������z��G�]�����?���Z���V�Z+T��s�/���x'E�;
����a5.2���Nk��Y�9�����f�i�� �#@������Bt���]���`5Z:���{y��&��:�]������0�����������u7��|B}������S�?1�\�y����k��}'M?d8Do9��pY�k5���S_��h��Z�z�u�-�I{���q'�>��"��wz�f�A�����ot
LF���iS����35T�2���P���%Ke�z�J���mo���p�S)#�Q��k�Q��>k��C��eT����BcxJ���T7�W��g�(~�J#��K��i�(�]	y�shT���(�FR��G��?]�q�������!Y�F������[�b�}��xk��y�r����G�?�m8��:�=�Q��d������<�RA�=
��Y����d]��e�2�u�xsv\��\�!uZ�z����'A��x4..���w������O��� r��-G��#�?������q�?~��9��2����+�#��`bR�@Fe���~���-�N����QX`�+�V��(,�H��7s;8�����`�[�#��<�jj��>�/N�x���3�)	xT�9���������R<�������7��,~w6���B�����z�
C�~A��'Z��O�������_a6��eR��C���U����3 l���r��-�� ���^o�D9�j�����X��'V6��J(�:�6��0Ci�����-�J�*fV�:����NfA�i4��u���
-Q�e�>��^�^�m�,�Y��Z������o��J������L�a��	h����h�����J
7��b
���c�`���p�d������a��Y��t�����+�1�7�5����nR�$[^���f��jz�8�4��K�,��:��������f������L�@�~��ZH��}:jj�n��&X��W��_����A������p����o_
V$����V��#'H����7�VV�
�;�ku�	�t:v
	������D}��	I]�c'��C���r%=�����}
������ZF�PO�w�OT�<x��N�Qxq�40�Y����k��AWz�DKJ&O�Z���^��:-�a�����l����O)�:4��gWBI�~��]���a����z���Omo5
>q&IB����&�5�h��|��������|��x%����O��5�O)!i�}�����>T�0�Z��N������]��6��SI��[�'���$�q
���p��/B?P)�>��c3)����]�V;�)V��W����4eH���O�)��-5�*������S����f%G���p�_�=6ID���*D|��/	0V�L�H��� �9'o���/	�Z��q5��fj�t1e+���h�I+���<�T��	E�g1[������<�2��������.���B����hF}:LF�C���\������}�J3��L9J�����C�C8�<���PT�(UP���'k����ltm
f<K�%}V�hb��2�D�S?
���>�Eok�`�������?�U{�C�Q�!7x
��"��Wm�D���	����+1�$�e�;��!?�:��t��~��������^d�D��A80TkQE@e�Pr������]����T
C��'�zr�"�!��0�o�l��D��Z/��c���20T����ni���C�:8���uy�j6)�b����(�P;{���xZ����Z����������|A�Q@�������^�'����s�J5�[j���xE$Y�hB�/c�I!T���
9�Pi�9T�8��!��#�Bi*.�q�v�Ik��P�bbR;�P%b.)���0�d�����i ��X-��I�D�WBg���E,��,mz	:xv_
�Z��$��
3�~x�D�z�@���h_�Q*����am��FsQ�w!*<O;��o��"H���}�+�)Rw>	�5�E�@$0�f`S����'��Q1|�< a0J"��5�Q!b.������!������r��sh�Q2$K�1-�Z��DIB��`0����+�8��[$lu� �[7g
-�"����
F����FAD}���`�f)�x���f�R��+e������k+Ki�P�=�J��	=�I���_�"kH�E$�8C�D	�+�f"���H
v��n��
�X�)YT7��������M��s��+������7�Z]�v
����fI:��i����buK�}�o��+���^� c���!���,�T����<n8�������O4�����Si��)�x��\�+�gI�C����Z
4�;�ve<
�����;��t��L�S%���s4����2{L���9F��B���
�M�P����X�1w$��@JMDj�Q���M��E���^c�e��L��$�dd}C�	�7�5�t�+�`��$��xj+J S��9v��>=� x������'�u���(������0�&isC�O��^����(
q����`L�.��+S�������W|Q2������(N�n_�����
��������o����{��(I���n��|��2���dx*���D��z�g��� ��
h��r�J=&����x�UeKMu�)��J
�����PS��d7T�a
]������P�u
`Y�P����L@�
��km��,����6)!C
��{r��zY��4��J��7b���8B���
�g�B���mg��g�x7p�����]�����^U���qW��!�k8�3R����*�[��*�����x|�,�#@�l��-(!��Y�G�H����p�DxH��:����j�(��;��I��jD?������T
g�-5]�S���mzN3l��D����c�a���7Qb���c+���"��v�7���Y<����^�2dEe��*J3^p��^���X��S���au*�2]n���?�c��.�.~[bym;&�^*�������,j����{����:��}W��5�|m8j[�1�m�[����Y�1R[�I�������	��Uk�B��v�����D�8X�km����Dk��+��+�v�d��gI���I���@��|-�(I���SrT�T�V0�=���\.�2��af��l��*`)5}9�<~
5�$��n������.�������C��cm������M&{�6�m0�R�*��lK�
�Pm]3Z�
g;kM�
����� c|�6P���f;m���*8a���B�������jg-��=�/��
�3K6J�1h�o�Dg�;g�6���J��D�J�=�6��w��_�)��
��!u�K�4LI������U$���R�2�u��m.��]�5h�������I�C[p�Nmz0\�����|wrh���@��0�E�6P[_s�`�u�����D�����:^j�����Rm4X��C��o�mz�K��C����9��/g�6\g]�y��o�vauO�2�����p��	< �B�FC����t��`���
D�w=�'vL�6�*PD��	;n`��ZQd���0�6�)����r�QvhF��jb �Z9��[��nrRQM�2���@m"�������C5Px��P�,	�M���Hm}�2T#'I/l0�:;�Q
~Y}�hp�jb07�qT�_�wkG5t�������j0X#�_��T��1K�q�E�����C��l�4)��c�_�va����5���Z���RRx4�:��!�y��
y��Z����\�O����X���+��%�nBe�9�i�uFp�[����n�R��M�M�tnz���������I��6�m��c��+����5���[0���_�L���v���0�������@�[�<���&�HDi����&ZLD�g����(���fnZD����:7�c+�������Y�2p����x�S�����m�����^��_BG���K	�����G��;tt�:c5���M���/�R���uYa�7�8�����.���Q��S��!�8����`��B�3`a���;PV���D$W1N,���f�'o\�bG^�s�q�v�L���a��e�M�jG"��G?39����_5��a��~���n��&��np*�R�!�
�@D��`]�
?8��t��X
U�q���v���z�����4�h���_��u��?>1+�|�����c!�a�P��$�X[�Dy�6y���ONkq������N2�]W�/�7n������<������>����im���u]�����M���9�qw���
��zW.��Nn���
U�?5���p�q�c��7��D�����G��/���U��@���=�i�n|#�r��"J�,j����ET�H�t�C��Yk�w�l��b�Pp���4�)����\������O�4�����TR�����n
� ��4�":�=�q�A5��SN��z���	/�1�(0�0�!�\�2
��n}�3�v/L��x��h�9N����Y3&��;�9����^Q�@;1��g�/���1��2S�@���1�������t����3$���iX�m�#C�0�5`NJ���!E9��qAdl���g��w�rb�l����'F/v��i(���oH]�@��[��H�I�gNt4����+���:��N�nE��:����}e�1�K�Fg�T��w�N�a�
x����h��N�hy�[3ZS])W1�?�X�tL�AO!o����#{����b�'����Y*��{~�!�X�]�B���L��@�������DX�]z�C3��"�r�����E���t��oj�0
endstream
endobj

12 0 obj
56887
endobj

14 0 obj
<</Length 15 0 R/Filter/FlateDecode>>
stream
x���M�$���	����q���/7s������
5��=hzV�IwA���~��"�n{�z�l�9/�%"C�ET�l����q��?��?���y�����4�����<��6���������������3����������?�����_��y��?�i�e����������?�0���_�?�>N��o�����?�������6��>���������������{�g�������)�����������1��?������/E�#���i����?������������>������X�q^���ao�������OSU�L����8
���������?�X6���c�n�}��������uY��������~[�L���Y�������������������m�!�~����X�"j�
�����m���6>���~����2��Z�����O$i?��V����}I�cXo+�W��8=���B���>��P�v�{u��u��Z��q���R��3���XD=�a�h_5n����\��y��zK���aq��o�����EM���q��OQ��[���w����������w����{N�������|;�������������RT��Vd�����}��^���*E-����zX>T��'��V��~]�\������������g������=�=��n.��m��A��>l��S�����\?�����/G��O�Q�a{�����2_M������f)�T���E2������1��Q�/������H~�����k�Q��F���p�e���������>��C?����8��tx���������~�$]};jI������������(�����n�r;������y������Sx��1�����Q���G�t���Q�:���c{���=8��t8�#�(zGv]��������`���=���>x��N����r��mX�fT�`�	W����"G��9����������.M��Q����(�W�������������&E]~�������'\
����:�ex��e��|�����W�p�/)��+~��_R��/�p@)����9�6��>�v�p'?������i�N���������0O�T���-�*�jI��O����>]������; x����`����5�h	�{�(o��N��_|�iQ���9����vR�u���.�������d�n�
��Z����q�_�����c��������u1f
�._z�����}�����:�N?��z�/���U�[����O?����sx%��xg�x��+��xA�pp@�~�-f�-��MT8 �r%���u�~�$�8��4���ps52���������]�L�}$B����������CL�9�?<+��~s0���)�kR�����j`��m��:�jR��>>���s��uR��T���~�]?�pp*XxX��h_x�m��\?�Z�SJR���S���K,9��pG"Mn��t�;�����;f?�@	6��/�oq=w44�3n���OG��=q)����
������9���]���D���s��o��fJ���_s3m��y�������I�c�{�4	nN��G'�>���C<�������O[�5<*H�Y�����}��������3��eZ��	���Lc�j��:���``�����u�>(��������OG��~8�C�9�Z�G���m�����������tb=8�N��9:�V���><�i~�E]Q-iko�o_K�������5�����!��Kub����>���o�������pA-��{O����������	W��0�`l��:��u����B�Cq�����g5��>�X���P��>�?�mX�S��/�~ ��2����u�4��"H����~Z�YGv��{������.6}>�Z�8�����g$��y����mh������p�yx�_/~���BI�����D!*�2���B]�V��F����O�:��o����~jQ�����E��a;zP8�_����~H�0���0��t���~;�3�����G��7E��Az������@�X�>�-Y>O��Y���>�E_y�����A�������p
G����/������gx>��~����
p?
O��m��N�wxXu@|{=��IU�(�B��V*;�B�{����JGC��IUJ�s_o�tx�6F�q�Cw��1<V�n8�S�/�o7�~�5�(�;���W^��j���
���|��ZZ�J~�_��_d����_�����-�"�'�vj���u���yXE���5��rH��h���v=���Yikn����5AGu��6Ajp9P��"�c�5P����h~��*�+�P��n^��Yj^�M�����r�w��8������ub�/�N*�Aw)��^��QR��%%�M��k�I�{��wpx�6�j��6�l�W��Bi����c�=K���5A�:�L�GVA8�O�rO��s���~d�N4���:�����m{< ��C���r��nV%GQ^��=~Q���)W_z�
$���x��k�w!%C.z(���t�g&�?�����Hb�o�T9�H�>O0��#IU�:-\��V���2Z��.�����m�I�>#��v����q#P�D���_�`�u7���F�3�J?���U'���i�N�����wH�U���D�.�?�E�]��kj��[��Ep��^�;q��b��j�>�������C,��M��*������;4�K�r��#�kQ��2�o@y?�_��	Q%E�Y%�����iU� �pg���>/����d
��N��T�b
���<Vk�k�����*��g`8�6�b�l�:�qxEO��h=�~����������j
�9-�t����g����{X�y�=<F���{��t��)<�L�>�4��8�������U�-Nk��	Q����~��������>�jS�C�g|s?����~iJx�����9-���s���,�Q���y�6����>�u�!�N���]�?Z�����o�ZP�l�f�/��dZ,\��?���&U9{k���>�jU�K��~����{k~O��y9-?�}�:r?�����/����IAg;�������Y-�b�$�t�3��;o���y��~��d�cs;-�P��e�
QYp?|P�r�l$�}����\�Q������_4Q�:�Y�������vnm�w?���;�{p�T��(y�"������6�l�������ck��(�E4J_����FK����}����}�^s|�~��o������3L]�/��,�K��^������o�vx���IQg�~�����um�����p��������7���yX�����6}���������|c8�X!�&U��.?�~�aC�j�����7�JY���l�|�S>��3p'���}�w��
�b��>�J�������E��~t�"�4�GF��:���v�������U�g����~�UY??���A����Q'��;dTgd��������R��`�u������IU�C���uq;Z���:��n�VAg]�?������������R�����/�B���p�S������@w;��pE8����iUN2����QW�dT^(B&��f�CEN�,��u�|��M*�_�*����O�U���.(r�D9�gd�g[�1#�<M�r�T�^�6�dd���(���O���x�iQ�������C��XH^�U���n�l�X
�6��m8Xt��8��!V�p�ww��C������_���.�&��Y������)E���Ig9����Ip�o���&5w�&]����i�o��	>���������
E��������\w9)����U�������j^'U����>l��_S���J���W�*g��hJ�)�
��)�E]��`�N���[>����O�.�_Dz����_@�u�����U�{���n'U�\5V]�t�U�/�.�Yu��I������wK�
�����B:�����z�O=<�kZ�Y��p;u2�n~�'kF��:P��u�DAE/��$5��l�����j��V���x(]�^	��CU������Q�)�_kT�/-�d1f��d
�T��D��{~�H@z��o���:������o�{X��E��z���>��^���Z����.�o��%}��>��HV�\QHJ>��+��?�P�S�;%%���<Q�?��9"H:]�c��������������������8(�D�?r��; ���I���}<�����Xd���[+�N�:[�~'E������t�>�y��t�����y�H�c��O��X�F�,�j�'De�*�����+�m�q�Qg�*�+���t�C�w;�H�+���<���^��:���nI�}b����8&��<Yxn�;=����������Y��P-�"�/�Z���*��ru�t�|�?����/�����o��=�}5���O']��/�(z�z<q *�
i�($�D����0'>i9���W������F)y��
�R���9h�%%��7�w)I�����o'��o)A��7������ui@��=5��c?���)�S�������`�_�/y��n����aZ��Q0�aZ������4-�x2�w 8��k�Q�r�ow�^������!�A��)Z�z�ib�ir��hR���E<�������8�iR���Z<�i���
] ��m;<M�:�������6�^�DeoZ�J�������Z��4�8�KM������
�Mm�������^�y\��~�����pF��b�
y����������.�//�h��u��#�N���vR����1�N�"���J��������^��w�C��5��p�����-��+��;�����h�����5BV�t����S��+�[
�N�i���������kr��[�T���m�����������u=�bs�����H"Q'�+�������E�����wa?����t�(�O�:EW|7�Tx��yux�T�2DkQYPH�����4>*�>Ma��R��q��\�^��w�\I���+��m�_�+&E�}WjU.{�u�"�D]��hQ�gd�0�f9<,������:���[�/���
�|�]&���D����-�t5hx�u:��E���o*E]�P������N>��E������������9Ggn�%]M KI��RJ�>��h�������.�KI�=RJ���:������t6������!�p7�/�������y�IQ�I��|W?����sL��+i��U�30�s8��+�?0��Tx�u5�������n���]���*�����b����1�l�"��;���"�~������%U����>v.> �����!:~!���~���iS�`�'�����C*���:���n�N������4����d����q:\����pE��z�<����c����%\Q���L�`$�|��jQ��C�jI'{[�JQW���w���C�{�{ �?�2T�/@�{�u�O N4�@-�������Pa�����CG�{"�w�t�R;x �u�q�k���{����'U^zZT�u�D��c���;�Q�r��^K�)|]x�|������&$�>6T���PJ������>��_��������'�W�(�[wE�OZx�T�4�]���9��zmlh���z9~��j�)��<P[u2��<P��������
���cw�{ ��!w;��:�,�:���E].���N���3jQ�!�}�eC�:����e%��d�N�����HI���d���R��"g-�j���t�U�y�6OG%�.`��G���>������������T���iI�.�������/�8}�%�:��0�Q�C?��������d2�d���O�$��_�*�u6+�����C�C���|Ni|6S�\NI�X��ema�f��c�����k��>�������c�M����*�r�\@��8���4#|L�|�T���p2)��{M�����l��p��O���S������qtd9��z��:��~�.�(������Z���{u��D},@���J0��<�m����X�'EM�oY��R�����\�Xu�/������R�7n��@�����Z�EL��N�:�[JQW���}'K&�[
QY���r�C�������Y������	H���r�A=�:p�����,C �j7&�w���N�b�p�W�~9{�
_�NV7�*_�Z�1ir���� M��}�6��~����G���K���Z�_{@8���J���'V_��W$E���?���Ws?)���iQ��-���u���S��u�������~�m�����G�I���5���C��v��W������� �b���H~����c�fH������f������*)�j����AI'���TR����Q��TZ���N��������I�
i:�?qQ��	��5���~|��/jQ�qD�ls_�{��A��_}p�g�����G���>?\��\j�;�������C0	���IE�Q�������o6�G�L��9Y�X.x �wg[�c���9�x �~=�Q�JwB-����[m�!S�NJ�}����s��!���W����e�%�N���{O�$�N��7�|7+�s�>���(Q������'�u5Ox�4�4�}x���
up�oS��*��P��d�������i~GGt"o����~1�&\L��P
��U�3�J��a���{�����������L��AZ���z�IZ����������h��;��nj��O�Z��@���������B���}��&���R���H�S��RZ����R�:�.EP���/"��R�>����C�n��J�?����K�:;�������{i�?�Y�;&�����WClZ����u~�#�]�}�D}� �#��)Q��o����N�r�U\��A[>���.q������gD�v����%Q�_�'}����nCRm�����z Ul"��r���*?*�
N�$6�[s^�s5@~���IW�����=���3��y��~f��<���h�
g�J�u&-�j	(�r�;�W�LR��������d�h����-C���/���xs�*g�M�r��$�-�	�#����~wu�y)��������C����w��okGh����_�vx[1'��p�6%�*���D��I��V'i�����I'*5��0��0>�0S�Q5��@��N�r��]�:|U�AU�
����������A�u�6y\v\��"�).&�@��wmx�u����
�Z��:$4���i�.����d�Vs?�
*�����b�!�y�}�����*`Jx�T�r��u�������Nun4fs:m�����t��/����&�Jgch��$�"���� �l��{%��x����{(�:49��E���� ��5z��1����ko���/���	W����#����@��N��IQW/��
L�����k�w��8�p"Q�kJ�O_�?z��E�R�����~+��������:0�"��I�[U������W�?��

g��.c �:��gO��3�������������5��}�Y��]� �@�i���Z����pQ)�t9x��u�|����0ux���T�7��F�}1�[j�N��+�(��sW�7Hc�����PUv������K���P��t<�D���Xr��O������O��b���u�h�9���<8,�_H���iQg�����C@��������-������-���b{�U��R���	����Z��������WI-wJX~�c���pDX�~"��>�O,�G�xK���%�$���9� &����I�m`�5x��<>�l+�7��A^�w&��c]����y2�CIQg�R4���o����`���!I(?�����{�N|���~�%�'���8��^����`�7?R���F�x#K#���Z����\�p#R�dj��H�:M��~��w�l>���yn�J�O��oul�K�R��?�G������H�_�
����pm�w��J��Z���V��V�"M:�5T?���\T�6�t����Ab���C%h��D�����3tx��$E]��
:�}k<	o�V���CMc��uuN	����n�Q��C�y�p���>�����4��:+��Z��VJIn��^xXu�XD�$��Tx�u�_��0��
"X�k�����`�)_����7_����[9e������hH�F��:|,}�G�
��i����~A���
w������y���'���C��~H
�������@����{Y��J�M���N5���M'?����W�#�gx���{N������??������!�K�r��D]d�b����50
����GF��7���
��f�ey��t��?\M��s�\��c��/������gdD��i��eJ�{i��zd�� �2d������/���Q�"�(k>?�z�����uZ��R���M��TD�}�?��E'I����m��a���%%<P�:�����Zi�'M����.w����=m��40�)�_��=iw���#��t��=
�����z�d���_GZ-�*�$�%<��:Ez�F���~jR�����
�1�p:Z��������R�Ejq�t�y
��>���i����@�s���ix�ylwzG��?I��_k����G��uu\���R��z���:��m�����vh�O��?Y��N7�{X~O�%�����p0�[g��`Z��P�p�����`��'�g��s`	N^s����Y�����w���XR�����+!�g?�����p0)�l��9�������U���U�L��#wp5�*`�u���w?�`���uRT��0_U����3�Ur��1g�H���]�/�}���oQ�^\�;W�n��D#���>g����k���
���p@��!�	5���U�Q�P�+Q�~u�p������Ts@-�b;���e4?F��9QV+�_��Q��3�$|x���Y���H�W;BvAm|�}��:[��E]�n������^������r'��y�^�������.�E�E�M��o6w1u�S].�>��Xq�����o�Oe\��XZ�u��U��b3(H:����$���_�������g�,<M	:�����hR����p4)�$�t�H)�bB��b����e���H
)�d��r���R�Z	�c��!�.�E��>	���p��{�+����n	�t1=1���t\�+Q���o-�W�������(�Y>�O��8�$��������j$�N�Zd������f�;)����p;!�d�b�2u�(�}M�:��U�����'�z�e�+jQ����Ty��$]L��������z��U�
�@���t>��<}�n�	�~�m��.��������W��`�����|M���kR�i_�f�b��b�v�_�H�u7�U�L���X��*�xb}s'���z8B{�7D]�oCQ'#l�b���bx���<���
��:sv�}�E�-�	gS�~��P��[��E-���o����/�*D���!��H�/�C��=�_����$AN����%��vR�n'���IQ��#���V���!�u�������'��i??X�uk�xw�Z�����x:��p+�.��[iQ�?��H�E���.�hu��~G�N������1�~�$���������n)E���
���R=~A)��7���������i�/2\���/;0���~�tc�i�;&�p?!���)�.��e��B��wEsK��E�A!�9���3p��]F��?
w�e���T�VG,��/>����,�$�*�jQ�_sd����>j_}y�63��������+�/��������D5g���|��`���h�O������s	��V`���E����9H��^���/�VZ�e�R����o]v+P�*������d���U��6�f������~�-R�elQg/�J���W`�El#Q_Wd������q�wy�����;�����_LjQ�b�c5��>|Nku��6|�G����iEN�777���nn�E
��b]Ru�ty���8��C����������C���S���$}��;u��	7�>�8�w(Ur����
�$Q����K���
���H'>��w��hm8��^�E����J)�P&���)�pK-�l�N��6�$�|�K��������/�D�#fin�%}���'�R���2����#c��������?W�������]8��Z�[�J}�S���{"�w�K�=����D��c���4�}����������������!{,*W��\�'I')c�#�E�:�#�Cx�����W��7��[������48�����}���������j����d��o�����������)I'���i��O��8���EG���"�>�4Xt��\J:�J1g��0?D(�Z�T��Qr����^@�&����!���8��
D�p���D�Y]P%���j��se�U���_���0�
�!��IU>��~�RO�wZ�E6u��;�[��vR�ENC2��c���
������*�u��U�?�p���|+����JZ�.���$�>����}'�z����;d>��=%g�����t��Wx�X�����p5)���tx~�G$c�4=h�|����Co8����_��wR��n������*���i�.65L��oS5��ZL��7�(�+�9�����kQ��Aa�NR���*I�.�������~��������|&����<p'�_�*
���N?��IQ��N���t���WD��������n���n9�������P)�2FkQ'�66��b��d�,x<��pJm�������.�}���oN�����t�+���09{1V���ZQ��8�@���au�e	~~��������%x�eI�����dWJ;��m������ 
>�WJQ�����������[�anT�������e���]�gP�,��{���/B��/B-����7-��G�u�=��M��W��W��<��^�]�[U�t�us(��������JI'	^�K)AW{(���P=p�-����O���}��N����8���q���%��������L�:����<)���L��z����[�G�],=E�.z���s>����z�1�j���SM�:�����E]�5-������$����W����JR�Q������	�c���N���u��1�R��t�#on)E]�)����d��V�,�p���������d���������.�6#5�w�uj�w����pt`�:-�l!Hxhu2��N�hy<�n"�W[uH����N}�k�eM�1��MW�N��4�|w)�������7 4�����y�+��C��xl��pK-�d/Jx�_oUsK������Z��m�K����u��wW���yC�������$���������G8��Y�t��cK]�O�}s�=W4���`G�
8����8v��W��f����qQ�N�B����G+}����D��
J��{������w%<�w����w�������]��|������)���P�}�
���N�s���Q��K��Z���~�:�n�As/�p�8|���M���~����+�4uvj�;����
�����~��0%������-:h���R��~rW�����OR�*D}L	�1��3;��~5�?��}��^�_ys*-~�������S���I�K)I����?�I�g,�8��y�4�P�u�vXJ��R�i�w��.{>?���3��|���r(��6|&|O�r��$��?�#����D��>m�e��V]�9d�9<�=>�%v�����tj�u.tV��|��	������7fw5m���Z��U����������t��k;�����_H�g�^��H=��C��������*a�:7ZO�E���)��:���	��:���29r����U���`��&����GfRDU�/�3��� ���V2	^�|Z�su��y`���+H:Y��.����=t�����n�Q�x?�����U+���5>��#��TR��/4TD��/����S���'K@��H��������p�y�Z~����@!��.�^�+m��b5-���4I�����I�z#������aw��N#��8��&_/$"5��qW��:���&�����]%�d�d�Hx��Z����q�� ����Z~��_K��
�&�E�}M*r�?�GF�u�%<L�q��N�ly�9��C�H_b�����o3T$N��cs�eI��������S�#���a�H�a���=�8�a�.���p�Z~��q���WvkIWg|�I'\L*r���s��:�.��8Y(.F����������������_\�aNE���k>%���R���t���P�jF\��'5�������'r���vp/�O�CiAg������C��[������KK�ug��rw4m���'}\N�NE�
<h�U�L��_��$���w_�������q'���kZ���9�;��u�5-�Z�5�t�"|
$u�?�/JAgK��-o;�.r�7��z�5)rhM�vE5����u��; �[�-=#�$��;�q$v��Js:8���*�td�!����8�u��N�9��c���x?���l������M��S���?����h��������_��y%>.�9�a��i�?�\��m�#����gR��g�O2�������3Z����>���1�>r�7�f�����Sw��W�E���5-�"8X���Z����.];W�II�C��@�.��_Jj�y��0P�D�Vd������Z��&��Pr{�����C�����vH���IIg'�����[���wW	�/�[���5�%Z~`J��<�����[��v�;�3iIg'��/�E��+����%������y�A� P
*����������:���������3��o�������������������
�e��������)�y����}X���B��t�v������"]x��m�/���{�;+�o���8���s��M�������K�o���4L��S��I���:<���@�o�����?����K�q���6���K�m����������3���c�w��>��s��or���vp������c�?W������i����R�����s�������N���X�o���c���c��
�Z�[���W�/��-�����R��|�������&_���a�ok�o�u���?�yY����7�����������k�u����gNv���p��/b����o����F�a������?����2L������y�^����o��O���x�
�i���<��q����w)`z��|��y�q+��0��^~���O�a�����y���:�����-�o�6�2`���6}M_j����7p�m����+�}�%9��9oJ�c�E�@=�y�^b�2��d����������V���r��������y����a���>}���s��o�w��V�U�������Jx�'�%xyl����7�����c���o�}����m�Fy����S��/�0��}�����t�u��Ij0����m���p���"����)�Z��0�},J������}��<�b��i������^��t,'9���o�>�7�:��l�2/J�t�,��vIy�k��N;Q^
o����8�����^�
�����y����Q��Z^,3 �m�&�%�7pf	�z���]�S�������a^��}�;9���,�-%B��x�}���������C����&L���^'�G5��V<��mXnz'�X]^��o�]������Q�S�]�%Z��
/���X4P���c�����Wy�%ff*����^eCMeC������6��si/�
�

4I�^��)jJ4�y�����x�l��p�LY�/��i��My�Oi���q�	���{����.O��}(�	�$[�������s��u���1�#����\�~i�[�rO�O%a����fh�)$L�z5���C�����W��s���X����3�b�S�$+������Om�\>�3����(�l��6�����O:��|�K>�cya�k��S����@������SI(6�|j�����������]��;�5�v�T:8f����B�����f
z�!��i$W%S�zk�"BS
|ewO2�9��&�d8��-����mz�lCr����e�)��	Q������NPi�O�O��ew&����}�)	�K)��O�
@�2����"[
@��3��vo	��p�����*��
��>�����n�|���g�:�j3J�V�O`�v�W���0.�%��^B��g��Q��������C��-��h�^���*�N?M��-�K���C����i,_�}����������U���/���5���_9��t!,U�T����K���,^�Dq����q0���c�X����{���j����%�����_F���kC���2�����-
M�a~��_�w/d9�a�q}Adr���}��e���y\��6�����c�S�w?
�R��gPU�����}�F��<F>o���m��8�/;��)
t�g~�zj6�nE:z��������
]�-/��hT
t��(���8����a&}��%-�/�������������g�M�
�����@�Zs����V[2��.�U�,e/�������K�\�>���`��;�Uja�a��������~l�J�����n���6�Y_���oK�lo	'�l�yc��
�%[^%��^W��0��n\j�/�XX_���/����i��K�����O�C'M
`3[ 2K����N9:�j[J&�xH���g���o8��)+�`�X�����x8^�p�U��p_�:���:l����C�p�q�U�����O8�G���X��X!c-�s,]r���<��,�
�K�Z��o~���������Z����2��$�� �����Av!�7��"��,�2�eSJp[n��a��g�#�wX�����2�����C,Z���n��y���g��4���O�B~��r@l_�:������ClW�����,
b�-�����A�����.�V���;=\���s��=�I	��c)������X,>���j�k����J[*.�-
b����7�L����rP�MoG@l_�/jb�w��]ni	-��r���K7s�.�������:���E��\�������n#$��
=e_t%��z�c�H�}zO�A[�� �B ���b��n�`I���8�Y�������-{y)'m0���z
�}���K���$���^�����B�b��~`eL�aV��<OF�f�Ym�}YC������lr�[�
�Z�Y�%��`VK�j0��Mo��b3f�����������Q�rs�U�Q�uK�)��a%�	��YaJI��N6
���h_���#`V�V�	#
f�)�G��\����K	�f0+��0����Y�G�.���2���G>~g��X��"pLy��Djg������8���%���d���E����������,����1D����^�2����J��s���/����-�H��y�w!����M������j�)�;��5#F����)�F��:��Tk,	���[iM�WH[5��g���L��L�a~��5kv{���n_���9����Q^5r8���
�yY���@m���Rs���� Wo�K���6�'���Q���	�U��?�6N��
E���o�� ���*(�"-M���R�;�S|-��%
�C
t�)O;]	��`K�����K����J����myA�( w{�z���>����6��#@Wj�,=����AWh��L�������"NxXt���2@������>n�f�=��
���-+F�v�������]��^��{9`Ng6�����K�T�#)�B��z�Av��.��a\�]r5KY�"�BJ������]y�����v�5^�����w���uS��� �.	�������,�aW�aw]������v3�����l��v�`�UG����.�2���������P�w]��Un6�qo�a�U�`+���a����Z������{���n�P����2<���r1a�xn�T�Z��e�V��Sm��W������u��6�DF��m{�N������~�NF����q�
�������
���|�7Lb,����������:��?�q�
C��e���� �|/�u�X>��<�[�a�y�7L�sC�����������5����4��������`�c	���r+���M�9�%�6��i��7��uh�����)e��'����1�m*����b[w]�������[ �����b���\w�6|��E��m�;N���k@����c���E:�����@9����
�����9m�N(4���D^�`�u��j	�u���v���}��N2?/%i����%�;���3%���N3S�[�!��Qkj`;����R��q+��n��
��X�<����\z�}xO��n�����M�
����?@~(~�h5�h
���W=����u_A��6�b����j=�9���Hs�3u���[z��x�`�����������n=�\F��Ps]5d��u�}�����;�x�E��~z��c�B��r������KF��:��{�����c�����������1T~��*���a�;��%���_����{�����k���o���=�������j}����
tE�{�n���=��,�{�y�Do����=�9��;��yK�
���PE���_��W�=����=?��!���5����{��d5;O�
k�2�����{$�����=��N�����>-�V���V��X��'��a#m>����Z�'�R��R�[�0�a��3xj%�)8��W[Q~
|���y��V��!�4��>�\3��j�m>�9�W8��oC����g��	��sQN�zfVz>�s�2��]+�4������|�-�m���5�T��9�38�	�+�����B(��o��]��+�`���F�]��yZFE	"~p�CC��b�a����H�T���J�35�y���$L5��y�a~��
�/��y���i~��<���l�e�E
����b�@O�N1����4�u���.u���8'���m����S�M�{|Zw�����Y���PwI@_��W��	�w���m�M��T��Eh?���2���]�W�_���k8�i�������j����'��D*+�l$���N�?���d����2J|�~�h?_u M
d�V�zR��2���	Q�t(��R^���>y���~!w]`�+!��I�cd@`w����[c@��~NR}u'j}
��SmN��������:����[T���{��t�����>�3�=W���^�z�������n�:�B���(�i�	v�t@ig�$��g��u��^_caXc����������d5P�-�"V�|4�2�ep�KHCC��Z��N�A�-}a�`�A�,�
������2����\;aUv�/7b��q4T�'C&�y�qN�?q%d����z�g��n���Q�) &���>
q���s��7��R��D��������kX����?��	P�������&?���\j�(H��;�!0��_�s0n����F�c��F�C�^�F����8)����a��~�+��%5>X-������v:�IvID;�����d�V��>,�����jcw�5�pO��O/����A��+S��;5`�'�o0*��6�F�6��v��0�����T�F�~U�����_����T.�����Axz0�'�F��b���?��>Fzz��-�Q�?"u|F���IRv9�
}��Z���o�g��3T�(���k=���R�e��A���o����2z�"������wF�Q9shdKhtY@�|,H���(V�>8���:��p�b�M��xG���J758��i�yI�����,��]<Z�Q��_qx?��|I=���Q��3���(��p�3-�i�7��Q����YEHe���y�1�-0�]=� R>�|���g��>a�����I���Q��|��ll!�uv��2���FsM$�/������$�1�!��8H�v����R��)OZ����Qj�p�� �Xv�m���\�� �
���76���.7`z@��8�of.�����kc���0��G����/���S�6�FP��dii�lzc�&�������q��h�%(��S��	���$�R��u�^J��Q��:^��y�.t���H4���R=����WJ�8��!���8q��RZ0�8�����������Q��0����d� ���^���T��:^J>}+�q����/����n`�kxI��f����%me.M�\�s��U�����6<�I,��X��5����f�������n��=3=�mS�[t5���0��U"1?�R�`�0d�Ymb9���.��A7��/�<���		��0��&N>�
}/�)����h�A��M��8<V�����^�S<�d�i����
�@1�X�}��y��������B�V�3��:�\�k�57_g�U*j��U~Z*-��f[;Xj%*�9`�e&���J�(�O�k(Ke�}�o�����]H*�8�(W#������e��+I_�����n���cr��Ps�[B�f8)l�l^���
��v��A���B��������R��5[GH��������>/KF�Xp	��s����>�L�>����e�)d<m^d4��XX��;���o#���^��Nx8�s�(��<�O)cI�E@��z���%GP�a3�$�9��'�y�w���ju�dM���M)7�'�:��)O��@�����@��`_PbP��<k{k��s�5����<��iw}�������i_�cK���V���	��
O�%�M&��!6�RiQ`��@���$���Ta�
�����TiH�3�����
���zC�f������t.���@���
K�T��*�4�5T�����RT��x�0%�U��M����i�(���QU��$T�
U�v���b�����/���
U�oT�e9��)e�"]MU���
:�������iT�0.n��nJqU�0�t�/
\%[��Y(����g|J�`�����	\UX���p\2�<�%�:i�*-Y��P�S
W��y�C�hO����x�h��>�Z����>���#G��*�j�A�G���\����pU�3�f�x%,�`����U;�
wJ�,��^�	d2��~��t��`����@Vi��F1������H���BB�#(Jrd�~Q�������(��$�CV��u�@�#+����}���
My�X����!+������������v\��Tg�K�����+��h����UB�+���e�`����>\R�2{�+���-������d�����<g:�l/�p|��`^j�*M�e&t�����b	�M l��K�dNf����xY���Q���r�\�� Vy�R����:&JJ=�e�����p,�i�A��������m�$����O��}�p����!pVmG���^����(�R��q�L��EZ�h�,�R&��9%,���Flyl8���(w���b��6�e�PM����vg����c�y ��}��"\��Oq�/c�)�Hr8�d|���}=�2[fM�����-4�1p�l���qV�bp�i/�jS^6"X�cg3�>Q�Y�b�#lEk8���N���X�qV�b%S�F��4�~vP�V�������LT8���+��j8�����t9�*5V������;$����u�UZT6�����4�n��(�!,�P��s�!��cL�!�6�i]�i�/n������d�Z�]���[c��t|��0�?����*���f��X�}/��JF���3fUCX%����`��!,[�0*-����^��<��d�n�&tUS�X��:N ����M��[SiR�������9����t�d������;Z�����T�U�L	�ZR9Z2fM�i��/�c���5���x�5$Wj���.�u�
�I�1����F��'l�K���]j�"�S#�GnQFI��{��*/3����
��)��9�Fe�(��!S�VJ./���-O8Z�\����vi�\���
r�a�z�,�i��Kx�Zv|�5�UZ�*)3�Ut�R��w
���d�+t�k�Mt�������z+:�]i�M-� a]�f�;e����R,p�*kJy�U�d�[e�\+?��A����������h�h��4y�7��f��{����r_�}�AW)���y��]����B��t����..�������t���k��sy;jxKw��6���i�s�������[�m��xY�6�e'�i���g���q�p�p��2���������������6��L})>�V�]����=�����9|Z�h3�\��}��6�XUz�_���6���C���{���Fo�0tm�{��6cO�����~��l�����������H���ep�����Aa���v�w]��ZZ�������d���5�E��va;j-��.m�;����]���R�v��j�`�_���&��ex,?�(��fb���d��i5E9��W��s�'�#�HsM����5�1�{z5pL���t�5��d_���s`�
���C�h���zD��o�o����������]�����]k�G�s�������y���d�%���=�����"�=P����'�`�	�A|aZ�-��������#K��!��=x��#�z�c���g���*��A�^�K�����'��5����`�pGjk�]C;�6�?u����{7����|�:����n����e��q��6����m��p���b9R;����`����zK��Q��]���3���N�xOaB�v�q�v��N�(w����9��V<����
)�u:(��E����q5�!��Q�����}�PF-��[�Q�uW'�����"�8Z-�5Nk��N��8�����q���9�9PC���'`��\f��[�'��N�����N�
]�u���Sc�Is��s��K��9U�8���4�2�����y��XJ��@<�v���R��P����]�
�ot��2�"�y�!������7:��i6g�m���Y���O�v��}��;��uW'��
��o�r�{�Z�f����T���gfb
���h�i��*�'��
��[N\�Hs]b��'�J'�����L��v���s�����WC�)`O{��Xh���&���W�����fHF�)���jk�~��B2��"�CS7����6e-}.y{H���eU
�`;
di���b��������x�Y����m�I��9Q��++�����������=���T�,���3����M������'~}=���m�n�:O,�=�]��O����C�����]�����@g�������O�v��GM�������~b�����t��~�������X�
UZ:���J������B�6b��OoGe��y��~��k��M�����l���>����cJ��zT��lr��&]��,y6�����%~:��e=�:�YGk��X�(�G�<�@���l@6VSk�T�
��������TM�{p���z�i��� �=Uq�	a�=`Y ��{b����g�6�D�O&�J��4��M�_O�s���_g~��������M�����KW��xH2
'���9�)e82�@��R��p��Cm�^���a;�55#�%[�Og�j�d���[�����u��Z;Z���"��;/:��"*����>B3Q?�D����n�H��]@bb�)���jE��+��(��0��Fg��:D�����;,����3�}�!��Q���,F�+������?Ul:4�7����>4���@Gq�J\J���2�Z;������cr�u��Ph�wp��T~btp��X�o=G��p6�G�e�Y��h�W=�o���Y�C�}
�km����	p����d�8���l��P�v��|i�����K�N�B�c�aSGRh�����~��8��Ob����s4pd��3�j���
�;8�������x������T��L�����^��pT����7p��%#���G��nl���7>�8������qn����t��r}	��X=s�M��*�������p'8���u���%EE����bST��y����0x��bu�p���_���V@����]o�}kh�(~�����r��������������j���!c����������!#��l�4x�����-��}6k����F:j��3t
tT���y���`df}�4X���>��(/�^P�9�g"�R�:Pd�"��G�G�Zq��F����� 9� ����F~y�z�64��![�������~���_^\JvLuRLzq|��Mj������%�Jw��1���K���- �gc������@��8�l(�_�
��6���["�
��6<�HGJy�;���0N��6�L������M��CKy��h)y�G��q���f�`�h)O!��q���Tg����%i@�N-�q��9GKy[L	��^0rM���X�u�3|�Z���x��t.����Zx������L���t��R��B3������7����%��� �K�U��-u\t����l3����u���)S�qt������mCL��������}j�����@K�"KH:f*+�*���f
+bv���:������K:l*_X�V��MuF��a/`����P�7����l������z����`���i�)l(,��T5���tz%��5�T�d��.:�.���������_TD�������v�)�(B+]V:���|	 �����x2��tj=����^
:�����k[
��^U
<��Tbh�(t�\�]�����������0�O����
��BB�L�b�Oa���z0k��S�`#�`�j������.O}����Y&hi��u����S����W�h�h8����g�s���*d<�����@�/����������6Z��\:����[A���J���N�&;��X*%�7�
2����
��'�hV1�R-��wW�r,ES��+�R0�Y�W���-�M,XJG;���lK��I�t�����4{n`�]��.N��6�R�~)�~bz(&x(��Ct
4fX�n�u(�4c���tt�a�)zr���4c�*GSi����������Vl���TY�
�
0�
x��������'������T�b,$UF����t :�!B�(>:��`T����H��7����
D�S�j�J�Jsqm`I�:���
���DJ(0/R"T�1�t��\���/�4�bC�t��q��!H��x�1Z�\��=��G����r���/S����Sh��OX��&
w����#���@Oe����-.�SYb2������dL2W
@����G��s�����N�^�!��u�1T;��-��}	s�1In�6�JXR��KH�%3��jK����A��b�|I~'�vp��������A�k�)��2��Los�KX���Q�=����-�;�r��U���7�H�������Ly����mY+�Cz'%[��.��A[j�9/9o}&���%���y��]����*d����E���[��r�N��hI�e���]�~��dgPrt���V[C�^,	�����k�*��c1����������T�*	�,���@X�b{�t�AX!�����m3%�)5�Ip�X2%��%�cl�f�����s�l����-q@�<IPc��g�����c�Y-�f����Y���y��	j -�2Q��,���9��Y0�Y��wi�,�R>�@��,m������Y����%N��}���8�]_���� e��u��]s���}[����_����@&6�*[F�2��W�Ye��.
��8��e�C����Wm\����Yy,V�K�X�Y},�	�+��}=��-0��}=������Ym��5)k
�Ye�l#�AF����L�x�%��,<��gG�YaK�<m���8+M)�J,e
g�jx��H%���j;��'o��z�y^'r�Z����^���`J�pb��R}���p�����%Fz�myR�T�,[�A�O��t�3b�E���(�z����������_�@%�Y!��~1�W~�,YS.p:�6�cw�G�f�[�n�1�U���������
-T~���M��T�<������l����l�lV��������;�2��gf���r��������k��~��{� 
��+5�/!L';��K ��o�}�z�����8�r�\mL}�(��+=�����k���;�r����Z���!71����r��RLD�kt
`�s�n�\-�h0co�]l��gy%���e�I��>3�)�����4��%��S0[W�\�Ea�O(�r�Rp��%k�c�A.�i-��U�\iM!���$���F��w@�>�Zy�4E�\}6��/c��l"4/Q* WY���#�������|> WM�YB�A�2�?���A���u�J��G�r�r�5�
�`r�"���bJ+��iNs@��a�w�
����M�%�\)��
{r��Z=�e�-Ly��IMF[J�6�$F[�s�d��Uc�rO����3�=����i�����n�}���c~Q�c��mt}Q��q�,W%-��8��E�����8�
��s��~��%���b�3	�:��ZnS"u8�F��
����e�_�b�G�[D�!��Cj@{�ijL�<f��S
���B�RC��G�5��_�x��s-���pR�z���6_��#G9�i�Z�}V���&�87iO�o�Y��y�a����}p|F�w��"���� ��-��j��@5=�}F��U����ZFi�<��F�Z��~F�-�����mK��QF�AOo����+��P����@6B����3C�~E��C��+w�8��L�|��PkO����������\�����a}�v0D�����`�����8J�_<���Pj�p�;��@���Pj��������6|h���X�|�TN���p_����y�Xx����&P�J�R�<o�2JuAz�FSF�������(a�����J����K3��)�uN���m��w�At���z�Ry3�Z-8����PY�1���
����p�(��z �����vh�C��������"Z�������o9(��v;Oi�������E�������c��Q@����%J�-�����
~�B���F�Q�����C��W��<��2��No�(c�����H2j�dN�z�������88��>U��(WFy��`�O��I6�1RI��9���m��$(U��O`����!�%��[�-��s�x�z�P�6�P0U�l0O�T�7�l�8�j`�m(�{,k���ed�:e[yA��(��O0�
#�����4���!�M�$�M�@m�&PM�>�H�o����'���U��<Y��\A�D�h���~n���QLZ�W#��*�`�fY���KE���`�-���<����I����U��k��R��@�h�P'�LX����a�-���i��}��MCJi�P*��J]*8)N`� e��2 ����'���
$�'x����.� R	���!��;r=T�������'��c
��;�����Vf��2����ep'��F����>�%��#�r�u���y*��k�p�K\`#�����M��hH�!m����y����s,�Q�|Y�N��������16J�����#���������)u����m��Q���� �����"��aC�����>p��s���:@�2���b�h��pv�T�'��
	%>v�&�5������l��$�(T������jm;1
U�tB'�X�R{��u�)��^�����v�L-����	����2A���Qol�X^���)�K���a_�O
�����-e��J��R�A��AfW��l����R�Z8�2���%�~� Sk�p�5 SI��Xw�:d
��0�U�
;3!dj_b���t���Y�������)$�7
��4�����9f�����>�}&S���n���%�+�`�-�"�����$c�}�0�}N��/GK)�Hi^�2�w�v��*R"�Rk�e\'9Vj�����`��������ZF�"�l���4l��,/J5^��>��F�^�_�zx��`x��C
/�
��Z=/�
�U��WLaC
�T6<g��5��6X�a6�MI���wp��� �BGL�enV
�����Hb�]�Q�'.�j��!�!f_��
����aCL�����!�����b�=��� #d�r�Vq�$�3���0*h���/�bj_>�&�M�Q)�4�lj/����_AF�&^ &�`�lYJ�K���������������"P_��)$����oJ�w���I���h�����PIt�Q�F�%V@�*����@:�,������;�39hzt��g�����4�G��M)�iQr<���dxb��x�WK$J�u����o8�SY`���-�Sh��K�7�5�(TS������r����Sj����O��
�
��lz0��c'h��
7u��M�1��lK�)�ZGHF�
"����eX�%�������l{��Q
=����tK��),p� -!�SY��������d�@COm��+zJ+��H+*��
zJ+l4Oz�L<J�4��VX�p6_<�"��OU-����}	/�u�
6�F[�A�l����4R�4�)����O�+�+"�Pu~��$#A���J��>����_x��J�����Io��������� �Uo�y�,�R�\N �����i�Xn�cXz�+EE����>@�5��B�V�R���TZP�`a��#���F���CP���LA���L=���
k������
�S���p���I+�1�P
g�a�@P���*	Q'��{A����������������R�n-�i�S�d�pN4>���
�]�Hx�?��HoE%g�����X�$����D�i�&Y��&
]N����We��$��:?��eKj�$,���u^m���a���#�1�����������}
{�A``������S���`�Ma��@Qe�<sCyCQe�+c�5�]�c6����V������qT��l�2�]��2�@2�4�+���H��jd
�@R-a���@���-��jH���W$2u,���/��������#V����;�����X����CL�������w��)z&�
�~�"l*�P>�[�*��O��W�����%�J}��^j�	�8Ax
�`�����4�c�jt>����gD&n���d���,u��b-	�3�O��-����ld����4U��kB_B�%�\@U�e*�����;�j���'0)Zk��d#KV��4��-1����sL��u ��cv���k��
}{i8*$X�.��%,A��M'+fdi8���X�=n�H�y����L�
�x�����6��������Z��
��jxX�dTL�kqA�� ��h}+p�4C�!*���������h{t� 0�����m��^qL:<��[}$��#�i�=U�-A
 ��QU�R�`9��[|4'���*[j����pU�]�:KZ������F��[�Xs%��-/�������=-� ��u�~���i���Tc	�y��I0ZF%��
�2�ff���Sx�x�Z6z�����P7�+e5Q98���R{d����
z�c��b�J� 1��]@�WMldKJ�U:��%����Gqo�2����i�l��d�
e�����<9y���|���� 0���Wpy�l������M�E�����x4��lW�V���k�*
Y�<Q�Wi�h(�{_]���8�\�^eD^������b��*��h�b��2f���{A����Hw'��	(��B	���0Y����B�j]0:���*m����7P�xl�;�*%�V?�
R�^������X�w��*���BD	��J	�<i�]Y�����Du<�"P�.-�����MCSy [�|=A�@{�#�����1�dk�R0����A��v��4"EP���b)�_�C�B�\�p��i����mM	���&@UZ��tj:���/P��cx���l�DYS�Vdc6{����A+�����2��<�r4N�T��hc���
���!��\����A�F�Vl�W�N����B���c��U�*��-�e	iZCYP�����7W�F��A%{�,�X*	O���m�7�8�j5�����v�_5L�G�Q���.� �eEui�)�a�	�66�e|��OC������:����S(]�D:��c��k�L
No�R���e�j{V+��t�
��T^�+4�{J��q�|�$R\G�����V�G�9�J{l���Un������OJ���x>>1%K{f+X��\�]!b���n0@��n��k>�
v�2�Gf��MG���L�Er����I/��F��|��}�#��	�%��g=�rGN��������N ���fA�:��/��k��%�J��tI�B��{f��K2J�B�
���������nw}%���64l-`�/e�'b�q���a�o���6���������8�
{J�g�AV���aW��|�� `W����p�K���yv���[*t��j{^^�����t>c2���.���#��}���C$%��_��ekp~1Er��k�Y&���J�6g5
x��Z))����X��
x��Zk)%'x�z�L��*�xIF2���W���K��Z��E�R��Q^hP���e�e�<k@�����@�;���c�@y@��).���+$��Fx���_%���<u1��/����������%�]|��V�k#�I����=�RI{|���>I`���/�O��������z)�l]�/��Yn(�|����T.��W8e�f)b���5���x�=n����d����q��2�G���m�OR��FV�f�U�B�f'��a��_���y�$��7������D��8��s�p��~���U�Q	��/�Q�W��~AF-F�]�/�R����/�R����w����1^; ^��F���/����xq���4�/.��o������_������������hqm��9�o���[=@{�eg�����M�����Ao~l����KF,�}xL��jw��Pq^O!����)�^��������k#��q�b{_��]>��i������n���>P�'0��aY����+��]W>�j�VB�c���]��K0�_�'3PD�%8M��NT
�(LzT�t�[*C_�
�������{��d88��lQ��pP��������
�W��w���p,�b9J�g�Tr��C)��`���IyjZr�a������:1x���<-/p��a�Ar[(������8(����n�ysD����Ca�Aa���J�"��Id,TE�`H2,�/���b#j2�k�I5� c1�U	��(���K�d�\�9�zc���������!���V�k�fN����M����t��P��q=��'R��������/V���Z�%��6�Fn`R����~~N:t�z�����r�����J�����J�/����4����7X��~%��9r������ ����X���~���0��|���^��y4��}2�N	�u/E,�,��P����$l%<�k���,�+DK\��V��Q�8Pu(A�4PK2*��d�,�vc��H�Q�i��<
��t~�ZY���I�o���):4�%�j��"�XjP�P���`��<*f��:	0���
d'/���a$�C:�����6���m��i��`��.I
^����-��+l`��!��:�Rf�~�:���
/�(
�������UR����^��b�c����)���^%������M-c����L��M����Ly��1�Kf�u��H�v��Qp9m]�,}�b�6�u���SE\�%�
"�����/�R����v�T6��X
.����K8f�	�D��c���aL�t.��g�)��2�!��&m��b�Vv�d	4���R=�^/��%h�����K����Q�K�F��+�R����F��u�D{�)��en���Tm��;]	q.A��v��p	2�Z>wL�K���f��2�D'��~IvL#�F��K���!`�WVf2NC:`�%<�N���J���/S�`\K���S�`��0�4S�`7�,#�_^��!����$Z�![_�%���2�� tCK8�3����:]
*�Z*	_���@��'�s�u�T���'h�GKi��u�����!�r.������{�J�����|2+A�@)u�B~��Pj%��'��rQ���`,��U'x�{�c��2g.�+C���ry�s��]�+b2�����t�v@e��}���;R����l���R�Iz%����ft3��$�E�������4���[�R��B��0>�3�J}.x
t��_9#��?�Q����.�%�������u;��������z�����5�LT��gB����$)wQ_� ���C�:�[���9q{�A�u��H���!Q��j:�"J�sw���D�E�	qR�C-b���s�@-���u�����e������Z�<�*;��k�H@��_��[a%@�KG*
l�����X���*:5	�C�<�l@N`�:������0&���������p4��o�`��;T$��
�����}	���c{
&�{�Zet����-�pu�T0�FCJu
7+<�B�J��~'�IL�����������R��v]���8s�?-�B>||4��z�6�$-q%[l�DzD[V�,0�\�.g�ennk���|F%��$�-�?�H5�����	j���T
;��85��7hk^���$a������,v}�e��F:�x3p���x1
�!'xTv7�9j�YPo�a'HH�;��{�yJ�\�v����Z�1�;zj	s2`��m�)���j}E�g������'�@y��'�a����&��U����+���e%?>A��e���������0��c[�>M��m�&��6���W������S�
@����jI@��
���� �&9e�N�"a"���TK`����
��#�:�@���I���*��F�������HV��P�\$��}	/�J����!�'�����j��5K^J+l�\�l��aLv��hWB �H��DA��Qf�$�<*����8����� 3�2������x2Jd���j-��N#�lIeW�!,������������!&� T��-7��1��������P�C��*$X�)��	�V0
\�Pm��eC�J����B��"��5�V���,�3��5�VX�U��B�
���j+f�T
�Kx|�{@h_B�I� TI�m�OV-+��A	:���t��������C@@(�X+	_
���F��Les�L!T�R_Wg��RF�����!=����Q���hO�����2�f z��������;"@���|�j	����e��wU�{x���@������
�����Q�"!ew+V�k�V�I�d���"��
+f�lt�ew�4��|(��\���3��A=��Bk"	�R�b�T	>��4WK
� *u��$�+�$X������ *��:J
;���3�,b������-���{��Q�����H�:mD_�B�c��P�����;��eX�>i���^���l���	]D�_5���D���Z�u6��%;^Y�f��������3�J�\G��h�2L���2�����X�@�*3V;P]JT���q<=�"��#�
������0�j����{`��v`i���f�]a`i_�f�
�6���5c\�p,:�w.�c	,U{y�#;Oai_�������R�Q��f�Q�����	2�;k��d\HQ�W1����e�9)I���%GS����O���cX�]r�m��u�vZ���?�bf�*d��U�h��:FE�Qt���<��c�IF����@Ue�T���+�F���C�x�a{�t.���g��U��J�c��X�$Wz���l�����
������:9�����`ZX��BO�3�5+��#�*e8��e�('4����������*��n� ���������;T4�V�=^?���IX�~����'�"�^W-����Ie(�&L��*�R�6i=\AFm:����&����a~t)��9e����R����M����xQv(�upUz�V��\�-s�k��l���f��j[j���_\i?�d:���4��W!����W�W},���jW},���rp[e��U���+oG��xb����T���)cJ6������c�j�X�����t]�#��K��9(�;Z)��%e��R�������L������Z�f��Yo��x�.2n0�2J�Xz�%[jj7��a=VX�`v��'?�vf��������e�4�����Y��f-�@k0+d���4��xB�F���=�(9���j[��
X	f�)�YV�Y�{���`Vo����4���r1�9�0��`�13'��������'�^5nAk0��Q"�F����ZF�d��d��~����t��R�9;Y �������0K2���4�*��	����,�����j5���M��@F�������$c)o��m)���6�{yv�1+����,�v��/
c��6r[��-��5P�������e�3t�z��a��H`���)�k�KFe��z����i �?T#�L2�u�6���2v����>��q�j�#Yy*~�w7����XF:Y8c{�M���P��������a-_N#����E��g=��5��"�B
�a_�![��qx���3@*�]�J�����U���R��c+i���9�6h	��!GV)�\��pq`��
jAk	I�h�C8�����)+rT�2���
�,����^g@�������F�4J,5�����5`��,66XG�Y�5��1������,����dxe���p6����{�������U���<���u.7�U[�
+�4����b^Z�+DXx�������6�\cbi(��d�aI��
�2�mi����Y�"�Ir���@��X�7@CZ����7D����L����Q2��o���vbv6�(�QIv�-�0�����e���i�i?JCQ���Z�HI�{�����rr�6�J-���a"�!Wj�4j
��:�jVK�
���COHr����? �f�N��\<����I0�`�b
>i�X�;K��l������J����f�R����Il�������a�\��fi��r��2�J�O�2�m�OR�b��F��\]�HIp�M?@W���3����z�����]�Q����K��e`kaX��)]-�@�Js^tIF����[V���E[�MS�4��-c��O
���u�[y�vW�O��_
�}	�a��
�uO{q&��r+&����p{�t�m�0�s�k�7f
���Z{.>�o����LA{`|�������t���uFm~l����bj�����3���������fK�H{"�7��d����N�����/��.��������%�^��{�~cID��e��6��W�-�$���}Y�9K�VZ0E2��L���qb
�A���A=����t�ul�A��s���q7J�������� �g
��uNz�Y�
�?�%4�
���`�A���Zt
��O�P�_�pE8*����B�z`-(����K�B�z��7(T�7f�(��S�P@����z
a����B�x��7�P�:�D6($��]8�P{��{iu���$@�{)��f3hP�qdEM b�2hy=($5�J�I����!���-+�?o`Hz��
������u��OJ�l*�ZW�3`���X�XS���4b}T0eS�������J�$���g����w_?����~�F@����h^h@��X���N�m\,e�g���E�������aQ��*�F�/�����3��v`$�O�fC�!!�(~�����;�F�Q������Q����F51�Cc"b!�vh����L�QF)��$��������F�����{������*)O��<��.M
������#��P��aC6�TIxi�6
�U3�'��	q��V�-U���U_��#8��p4�;�Q9��KW���`I�x�l���LJR����9	���F*�.T#yx�N�(���y�'���~���Z_��>�'p�d<+}Q��}�>���8���$�m��\���_
��q�x$��N��zJJKJ�/
%���VjdH�Q+���2�}X��O�ZT+�O^A)�����M(��}	6�
\)�3�y)���RC�#��`K��*RJ�
1%FJ�H�H�wR��#�9R*)a��#%Y@NGJ�����Qp��ZB������)A������	<R!�R�����)��A*�^2\�H)|����:R���b��\�[�f-
P�7JPc+�6]�X	2�)0-��T"bYp�Ll�Kz`��Q^;|5�\K��\F�{+����a�Z����hX�t_�
/��,��
+�����Ja�M�����BE�b�Z�����V����a%�&oiX��`���+��t�/�����I{)��?���5��k0['�NH:R

l���
��6pItCJe����R�>����6�R����@J1��e,��H�ElYJ1�RoGe�C
��2��8�BG�e�O0-�%��>�QI,�Z���c����R���OY`�
������H���	
�$D9
)�;�7�T�|-t�TG���RCJm@��H	@V�!%8T�7��T�\(�q��#���@����������4���@��6mW[�Ji����
'�K��g�8���e�ki�UX�h�N�(Q��!�����}�0�AR���^ ��~n����f��@����j �UR��*A?h
��v�V?$A"�����5�D�����Q��H�����4o��V=�9�"��1�D�RY`O�n�4����u&%8D*��)k��G��#���g���Hy+��"�;�	N�rg�C���k�"�z=�),���"��/�(M!RY`�BizRY`��&$ RY`���2a�s��t���P��#E*
"I�R���J�:Tfb��{�V��CGH�L�����{$���3b2���,`&7	2��%�Mn 9wy� s�0������]�A�X^��������1���[`@$�c}
!��_����}6l��������>5R��!�ME��'M#
 ���=�Q�$����i��Gq��-����Q"���8:v�&��)�Q<�O�:h�(���������}�����(~����W��>s�I�}b-��/%��"
�)ld��2�`zJA���uT�f������<����,�Z�j�\i��[�>i��*�W[]��Y��WN	������T�g��(mx%�C
�
3��4�
#��86�	Pr�(MX����v3�eCR���0c:52�Ab�#���5eM �b��
�a��O2��sB<0�l0�
���8)m�[�O1Kl81(TJ���U��`I2*��� ���I�@�Hj5
\>�����r��"�e�l��Lo[^u`_N@��q��LlY!P�ps�R3���.MJ�W�tdb�q�����j�B7����g���M�n����c������b�I&��2�Mu�m����l��v�&�V���m�04�pS����v����}6��k���!�`������Px��l���������pS�����
>f�A!�MUZ�����%�hz�B�(�u
5�fl�Q*?�5��JGH��@Mi�T��k=j�-uxK~�D[v,�
��a��o�c�����DZ�#~��I����2��s���mr������
���GN�����2���I?��5��gQ%�E����e]���g����:���>�5��x��,l���;F+���*t���1P�����p����O��Pi��$PB�u&/��:�*+*�|���s�H��=b/�W��5E5�� 
jl�4Ly��}CS�lN�����Xw��PckGK�
��s<��O�6�|�����s����)$�����m�}V�1A.3 T�a��tt���_0�A��i �����>�����.���(*��t�
Uf<��������y,���8�q�Qi��nJ	��}�U������9j�R�e�M�������
c{��Z�����?����#�����A�**��BW��
%		���(R��:\�PT����K(H����Q&�� h�p�l�����*���C~%[*P�S2N�p��*��O���z�|�o���u�����eEi�:������������'x(aL;Kf�S��T��~O�!,3��������U��yf�����:�z��:c�EC���H�t.&wJ-Vc���!G��K0(�����@��j���f�AR����>�s���u,���`WAF��!^aG��k��jb`Q�U�F.C�W��������p�ly1z�*�R^9K�iM����wy���$���b}�T�F�T%���������W�$I�pS�%� ����-Y=���S����i�Tm�X��2L�#��MS�'��������F��j����dI��+�������a�J�|1��a�|P�{���bS���R�a��*9��U�������o@�:1L�x�LJ�������N���@F�,c��)XQD��NF��tV�1W*	��H7����/I����/�l�^�#�6ZK�lh;9�S��������uX�8�Ih�����<K�t�-�ukfV��nc���������M��"��my���e���eL�V
^�)���V^�lN<�:djx`�-%��j[�&*�������+��2s�*�S����*L�P�s9���^�!0V�}v��MFakS���^n���_@�)�����^H���������(����+7���N�KdL��WW>�2&%x'6�5��e[��<������*Z��l}%�O�,}��aY�'��
)_�u�>��h
O�A�lM���j%CZ�f���i�5��
�}u6X�~�Y����7����jd����h���b>���e�O4L��V��1�O�[0&p�]+L������N�_y��-�}��2&�[��+�~8�
���L�x�WZi��%��:�
=��a������/1��j��5*�0��&2�U���s�2����8��-�������a~�Hs�nw�����7����
�FN�_l�%���$D�d��E�`MH���*k<�3[p�5_3�j�+���%FS���o�	Y\i�����\��9��W{�n1}i��>��h]��zt+9s��elQ6������������
������b�\��~;��_�(�lJ���d��������Yj�J�f<��E��b��hK��k��k�;\����|
�����Ono��i��&��m_��,�P�6�����@�v��m���I?h3;�C�`�k�Eox������V���XaGy�����V����Q����+#��8���X��7�����:���p`�����X�oe�@G����:������������R��k���F������B�%��$|\�N@��P?��d��Pp���V�����%F���`���#L�k��}2��c����������S��V���f���q��e�����	�7�8��o�����W�:�-$d��j���E�x]�r���lR�L��p��r�f��b����C��rk�g���a�n�=��Wr	�qX�?Jq�^�|w�c�]{,g��VB�����y���A7��In���d�J���M�����}nw��&YN%��C/�����9���������4G^����_4���e�y��4�Dl��k���
���
Y����d �m)%Y����A������b�5�Xj�|
�K�����`�]�)�]20���f������~���C�ub�0T�W�50��������9�!v0T����4C�<5�:
��a���6�PjO�+�j�^�!����F�����
��s+UC��#W�J���(�����MT����a_�������e�t��]FQ�|�:Jjl:���Z�5+��1��\��8��qO�A-c/\�0�qp���'�DF?��m���i�*��uT�/���>XZ$�:*���IW%*��
�����
�V?��������1V>��'�GC�=	8J���-��y���������zj�|r��Zo��l���&�D����#"�O����^��������GV��pL�>Ps�_�v�-�����i�j
lV8"�p8����8Aa�H,c��`\q^8.'�-)�b�L��E�l�������tYdR@���.���~�?�RL�KxY}}6MY`u�)� Y��x���`��sT�#�������9��u\�# ��Er"��bT��t
d$�u�X*5xYeQ6�$�.���N!�#�-�R��$o)FD����
!�MK�Rh`�4�!$�(����e�b	Md�F���|&��U��Ujw!��7�P���@R[QYN��
T����@r��G����/�nl �_����� ��P'4�l��Bk��AR�_��#�:
�����r��p��$�H�@�J����� IGR$���!(�	����WH�V��������[/@R����)H�
g�S�9Z
a���%��L��02Ga�#�.��~����o���)>��(*P�2��RF���C��U�m������(�Z���QU�Q�H�2�y���������bee���=��b��.a��,R��r9�#�����PGHmA���-p�D���"$@sV!�zkE��GHi@R��)-O
t!j����5����`��7GHw:>���a=L�:>J
Fl�|�$S���6P�Ge�}#�K��%H
n5:�W��k���I�H�b,�3�sm8���fZ5r�|�P�e���G�l�#������3�G�e,��vo�-%�q�{�6�M���H�_[G�@P �\_�M��d_Bm���qC���������b����"�����l|�#%�R�������LGJeaCJ���;H�G@C�)�%���b-��
>��`%���s e��iK�s�.�Lm8�_"�3'�����G�=,w@��kH�2��
HI2�}2�W�Y#�eH�	��2�J<�r���r,+|�5���Q����n�!%����$��{i���l/�}X�NO���#CJ��i$�i)�oW.[�
��K0�0��w�$��1�R�^���!GJeA��������_��R����H�@g�#%��)����5[���D0Y��R����3��
F+��nH)$ds�)�\�H�,81���RYPi�������x�)Q�Zz)#P����H�EX�p>�L���-���H�eXS?LTq���(1d�R�-#K %�X-��
]�uX�}�4?�_k
s@nH�_�$��36�LI���X)lH�7�T6,���j�
�>5�{�c�n��4!���D3:��s|�����#���j�he0���N3�6��LT�U f�Q���O��:b*
��ih��}
*���;b*�Ss���*�"���}
���q1�����	2J��D�e�u��DL+��2*�A�
/v����t=
��2,���D
0��Zt0����&��~J���s�.��4��-��Q�����m#m�F�����V5{����/���}���f,��o���+�����R������?]j(��IAU�IyM�������mJ�H:C$������`����Mx�$����[���%q!I���ad��^����"�����
!��J���M���D��
 �V�qd�C��D��SL��W	��o���������
�!uz�.�ql\�azt��#�����*%����Q���B���Q�oC�4@8>*,C���@*�BGHm�q�e=��[-0R�����;�@L��@Ii���LjW��o��4�W�����R�R����QGJ�A�
��a*��\���Ja��3
����$��-����K%�~0�+P��(�F�R�X��mK���j������V��9���a�CN�+�����e��1����P��0�g,)�np9��a9��
	�6���:��:�����u,��`
�Z ���XA,�������A������K�fvfg��}*u3q�4�d+ e�;�
��4�D���]���bG�h�V���[
9�:lv�2�@����q/��VX�����N�v��#M������kZ�2"tp��};�NXHw�Dj`'��M�Z�NR�6K��#�[��Asf`��Q�s��a`���v]d7N�����H�+'�R	��������IxbD���CpH5�t
	�r���A����a�;�����E4���Nm�u�A���������@
��'��:��3"XGR}�B��I����Kem2'���:K�{�<�X��0������u:�����c�Qk���T�a9���R�f�����y�Z��M����8h�2J�=%z�gz���eh
j��zI�����k}��H�fQ�\��R6�d3�PKa7��D��XJ�T��|Z������:��h�_���: ���/�e��h�XL+QV�\u��x*-�	z^����0��.�6�,�=:��U��������H*��K�#����������T�$���%����E��U�2�^���������H(
U�Z����
;��J��}n���V�A�����������
W�G�p\%K���R�n�[���-U��E��~KS�z+���ZF��go�v��_4��"�h�
.�p�,Y����:=�dF�t
��j}�XzaKI���P���aMGn
+�T��������h�����*-Y�=E�W���xqt����<�Z�D�DW�!Vr
�s�U<���jC2p\�#���xu\�#��~�*�����5���zP#��|��1�,W=�.�U����t��%�q�3���(N�q���=��e<��<��d���,y�"�p���E��C�F�4�ZF������V>�2�-��&��pI
pE[�R8������tv�f���`Yl���K)m�����k_�\��3���Mi���7R�c��e��o�������O���sI�xb�j������Kb����#0��M0eM����c)3���*[�)��7��O>�����3�q�W�l_�W�����6w�l����o�=�/8�M�o��
+����N����b;gG����E_��dJypO�������N%pV�(������,nG����/h���O���lA����S��h=����F�9cz1FYK�rO��g�R�jO	���d#c����T.H���V[c]�0��Vhb���oc��������5S�.��f��>��QHt���d�M��J��[}6�q8����-<6V���n��WA(�
������:a9�[i��_�x�[e��!���2e72�3�Z��8!�	��D��6��oG�JhUu�%{�g�p�ex8+�k��v%�>��M�T�w��%��Ok�Z��P)���y�{�i9�����&+j
�2��9��z�����du����[�fK8Nn�5%����q�-X3f��n�5^�
\��`�V]�R��V[��(u2����P�:���X���>���1l�WB�[r4�S�p+����������1{�4X��C��h����g�����4e�\�����0�$�r��>�������G�b%p�������a��p�=6�S�`��[���N�No�dK���2
�c^F<.��k<
�}	�Z�1!�i���x�Ou&9m���R�����( W[3[Q���Jk����rr�5���X�Jkb�.�r��b]��fo�K��L����fM�4�O3M@J@n_�W���? r��4��o�Z�/+�4����K�sD�j�K�$<�����P�3�r�)�I��r�X0�E�2r�z4�����ZF��
�u�\0����5QZ�:��b����6��e<�W9�t
�e[Vx5�%[���U��=�i����G�lL,�?�m���gv�����4�t�����s��|a(	��Z��._M�Qf���O��>�npL|s7>�Dy�"���y=
���e������L��RB����<���
�.��~}��Q��o8�����������k:&�z��p����$�\g������e����ZX���:�����l�1��>,�n�Nr�~���vK!c�b��7�3����e��n�b?��W��4���T������c�ey	��-��b����-3�D5��c18��(
o]������.������t��#awy���8����N���9��Pj0�T��������14@P,������������w6��M�
��?��/,�'�����'U�5�
�`���/�O�Z�>�0q���+��r��ZY�_����)�i-��;e�%��p��@=��Y� R�C�c�@De��R��E�/#�'�g&[��>�D���#�M5eA�z�^*7��0�@�$��a?`����?���$�|��q4l7Y�O���7T���->��-8�&r��x
�\���h����( +�������!�r�k�k�<������e��Z?2��1�k�G�������K����>��;xa�����F�b��e`����R���2J��v���d�\���S�q 7|���&�@����;B�w�x�1!����
������&��W��B��������:�j0�mHR`������`l�2SgA����|%��:P�
��vD:��/P�h�N�x���e���XA�u�J�s��6$�U�K6|�.8c�����I6�:d��dR�,���2u& @ep��AS��.�����A�c-�jP�Ae���4IFq/��
�d%�$�p4A�^y%�8�}��C��2��/�d����^N��hv%D�dz��6d��Me�j�t:���)lH&J7�������l����p��@S�����MiC
�C��AS�0#v����G@wm�������M�4{�0M�J4�#
��M��h����f�Z�2�����M�17m��a�a`;���e� �� S���
w�X�Z���0��i��X+qd��}x�?�/��S�|:���mL)a����wj������:`��6O��0�
kRY��6@*�S�`w�<c��m����)�h�����%�t���9<��2�
+s�;`��Ni�?�0��l��
	uH9�03
�\�SI���������	�~:S��P*v�D�j�V�����j��56k���i�L�1	p��Z������e�-���+~4���Q��&���a�4����i���X�t��<8�pL��fWBp�������|CJ��&���	6�k������6��I�l
�t�vp���P�7��t��s��j�&���l�g�&N%D���P+��<5`�o�fw�l���'��h���3��h����ecd��e�S�~{|�&�X���@�e�9_��G��Z�������k�l��e8�i����N�J�[H�Z����m�q���d/("k��_���O�\�����1�"u��J��Z�Hr��6�L�)mH2i
4�
$hJ�"�N���f��hC���6T�e]A�@S�0[%mZ�C6P�M�f_gC�7��BB>:=@�/���i�]5@��Y�lM�u��~#5��k��+M���B����H��<0- ��W�l�(Q��Vi� S������Z�/���C��ZF}�CgI@&�b��4�	2Vc:�H�m��O"�-�k�z��
�������`���$�V�@��`��hj+�� �
V$7��M>�:u�:��;�JVd4��Y��L�p/�w�n�G��f���UO��Y�N)���;�k����!.�*
���C��SJ��3*�qJ6�(�)5��5RN�o�B��������0.�,���(����!3d�V9i�'��U��:���	2�7:�8>�Q��'�X-8�m�p�z�#�4��~������%w��Pe�l��4T��EI�(��J+�q1m8�����0T[��$
@�Y�XV���ik�������g_�5��lu������$�7Oa�6�,���xm�O�&h��T6�8d����~*?�O����g���!2��>�
��:O
p�w�&�(��i_&�,���
7�<fx�n����Mk�[V����y���a�)g�&8���5���7A�z���,���:��X�i�7Y1�9nJ+���(N:�����%d�@���
��M�v�D��������SX�_b��-�3�(�n�����qj�)$T2>��r�oxb�Y '�0"W ����<�5.�b}�)��3.�,��
fO-�g}�q[��vw�Weh�+�)9��)�:� Ou&z������,c?����b�4j{[��gK����[\���i��S	0tr
��
p�L �
�$
�-��M��N4zG7��]�d�9`S
�����0a7��4Z�ig���L�D`
��
xYY�~bJ
Vl"n�)�<��f����(�U��F��K!`M#}�2�6Q�8���:��2�\
NL�	�TZ���(��`�J�Po���b�[w@�����������\�3������3H�)��"�6��O�����_^��~�9A}N)��� ��x��b��U�c�<k�_�>�w���N�7�%uF)6oV^y>���*J�,3JOlF��#Ifs�<2&��:��edJC�����
=��N��`�H��g�yLj i_�y'�=+�<9����)�,c���
P�%����:
Q���n�'�dYFi�N+���R���m�A�����%2
��jS�ufR�%�z�EJJ��2&�6d[����%���&�>���t\������G���J2�^���-�����F�W�G	[��z��l�
������-w�8��-��������������G��)X�k���48��e��E&�5�%%��)����y�Xa���i����#����Z@ur� VZ�����]9�_9	b�
����!V�(���n���F�h�W��Z3�A,���������o�(c�����-%��/
b�a�TC�����%��&���BF%~����};^���Acn�XmK�3�n@���:�
�d�3�5r�%=f�s���E.
b�)Q��C,��\�0�C��a!���X4e�h3�)- ��x&\
d������d�2��J�C �����Oa��R�1t������}�;}�����Y�Q'�� +e'�Wh������������E�jK�5�B�0�����a\���L���F)�R,����4
�Yt������J���a}�0���U��}�%�h�+��s�����Q.;���j[�kC�i�+�K��^`a;��8WGW4�?6]I��w�_`a;j��]�2�AIn~���;�B:J
]���B�'��QeJ�M��_A��FeCGQF��
2e��6e�tLu�j|�*��R��	C�`��X�Z���)�S0C�l;h��#,�RG���2B=*�|�2��x�wO�,�R?��[����'�����<������f��x��9���K���m��%Q��wD��h�f$�6��������V��[%4�������������o��`��&]y>Fku��2�S��5at�������I�})�v>�N����e;;:������1��)�7o����r^	k�x�>�W[�;�o�
�Ik2ZOOO��<k]N� \���)��JcZ�Q:�S�Q.�#-��m�N����	�z��Y����7������	��,c����`K	�B�������!�9���6�b���:�l��R|�Zz���NH6�M4Y�~A�nA\�R
�{�*X

~��zy����_>e����
~�=F\!T�_���2����R�MB��
{J���{��/yJ���e�_�b�vd`��WHy� &3B:�jM"^���~��u-L��nW����@�	�_q���S~�1�p�t��z8���)��M�4�8����R0�Y��'�X����QF��Ji	[� ��6�k��e<��J���#��ap.0+0�+�-a��E�K9�&�=�:��LR�9I,k{^�N�^�A����4{�f�K{,�Hqg���|��iW�dxA���=[))yaAm�`�I}��)7F)�U�cp_���~L�������ls
&)5\w>�`m�n����G)M�@/�2�@����Lz8K���,�&*R���[�.�jLz�u�w��,���5f[X:���x���P/�p+o���q���/����a[W��ih��|�Zn�����>��u�����J�4����k_n��<�j�����yX�u4Z{�����0�3ftR>}��'Z��6��<���w��I\��u_�M���:����<��@cas���/���qZ�-��p���5���������OG����u��e������.r��h-c�`���}+>��)���+�.PWX8������o����X��������*a�h+���[�p'�������w��t���`����
��n��i��X�r������J���`�^"�� j���+���J����s*:��DPa0�[�'	��s��`P�m��o0(�~d&&�A��U�h�1$���j0�{�A�aPZ��hs��C0(~��j�aPhP��s���`��(��|X
��KT(%�F�2�J%��HqK�������s�~#Md�t�u0d��� ).}����co���r���E�Q�_?���2���j��C�>�}�OC�S�����eN�J�/.���4�����lR�cfCz7�;0sl�������s�PE7X�m���(p�C����P��6�4`$�����
��#�?4*��Z�I
h������2�� ���	S��;]W7D�QIR`��KbN
0��>0��Jl�,���	��-q|��RbC��|P�*�
�/[�[
�}/�������F��N�A����Q`S*S}y^F(��H
��5�2	|����G6F�9��<+��tL�dt�8������+
���I7��gP���|��Kr��P�qA�$@����]���uxT^x�Z^"�7t���y+8�s�<J	~m�"V#�L����x��O�#�I��d����E2�v������%�_�
�+G�G����}	/kW�����]	u<]��
>�T�A�
�j��(l�`���@Gm�rnF���]6|T6�O�h5`B�9�hT�H��b#�
)HHj	+K�TOs��0)4�O$��6���F����OH���
*� ����
t��V��V�������
�c��$h���s�j���:�F�u�����k$iQ��:V���-�����S��J�#^�W�6CR'~^�%<���n��B�Jl�O5�6X��D��Ka�W���Vy;�C�L�H�/�90;n�Ke��T�8^�s�
�/�
�^�
��hx)l��"ju�T��zx)����J�B<U������F/Q�^*^��
/�.�y�O��	���h�/3=`��_.����m&q��og���*��)���QY��)�����p�AR��&�R�q�M��U��W����4j�hj�I���G��JM���J�N��JK���Li}��OZM���%phj6N0���<��!=(1�/K��QEL6@�x��v���/��p"��e�F���x	n�_�	^j	��*x
/�
����*V�cBX�R�H��hGK%!�zt�Tx��Z�����J�Y��@7���e�1D���$l3��
*A��
���J�b/i:=J���d��*��������c��"8�� �n�j��u������M`���uD��`�mX�8�R���X�
��i7L�!��
��s��<�$C:��Wv�L�������\���N���
3�
�.��j3�.lVY�U�(	�p���3�{�'�t�L�����a��`�^��L��7���kY`&��������������My��4��	��4I�\>!��%mFiR?1��dlttP��&��.�lp��������������
x�4�����B��F:|%<����|�7Y������i��(
��Ve�$
8�
nr���1�SJx&C{8������G�&^
eo��QH.d��$x�\��C�x�W:�^7��%#!p��d��)4�����N�AIs"���dL��'�*;<�9�D�lJ������1pIw��2�y'�0 =J�
��Y��R���e�)����$}m�*(�F��h��V������������:��~��~:�W!tj+��-��SZQ^4�e��S[�3�t
+�!��d:�Y�����vr��j�l�����/�"�������j=u�����s�
8�6�����I*S�)��g��������S�C��!_\�N�Q	���e�%�x�u���:��D�,�2�tsV6K�<�C
3V:i;J_JZD��$�1q�$[Ja>L��K��U
>���V�r���$,<9|
�0]�d|�=X�b��Om��>���������-X133Q�'[M���
.�l�)����������R0
U��L)�@�_�
�����������6Eh�e���y�?O��HS��A,c/���=����7e�Vc5�g	~���������gi��_
>a3l�`�w����)H3�h���>3���a���Dh�x��X�7���g_B�p���SHxZ����xj+��%-
RV� ��<��'�5s�TVX��G<�Ys�<OmE�'�d+���S���u���SHxY5�.��OU�$��	�}]>jTI��3�5�T��Y���V[�%��}�(X���@�Y|�_�i ����r����t!���e�-�����Nz���b)���,����������39��A��'�_���m�q���5��z)il��1�BBy�����ch_����"�w�Pm��<�6b��0�(*���,M~J;^6�T'?�xQ2���sUf8���e��<�)�2���l��t>�}-f#�8��V#E��+���=7(��x��?P�Nt3�}y������1��`*����i8W��1O�e�*�i%���P4����%S�m��T��%A����6�i�O����3��������)kSa[�ulu���}X{���\u:�N�V���s�{P j_��;=����T�/�`A ��v�!+��tH������T���.��nm�q#@=�a*����}r
�a�Y�^����-����FCnqL���y6t������O���O�TeE�F����b�a�:N`c��<��
)U���^R@Uf��` k��������@+�P�h*�(/��D�j;�b�nO,����4�T��,G�
�!��fs�!;����!u�[
����]J�d,���X_��k�z�]���6���������Ki��:������\��X�l�M4���-	�kCS8����	��XFK�i��S:�-�3r@����.V9�J[�LzB�2��X�5���QUlG%���q�jb
5���e��{����U��<�� ����+��#�����F�������X�l�u���h��#�J%�I�*^�k!��/����v���^�!�K\�W�W��|�A��gN�Pv�U
|%K���n;��'%�v`��������l_��%����a�? k�l���%V�R���>V�RE��6���8W����*S^�83_qXm���!)��)�P��:�J[��'�o���:Wv����#�CW`���J��}��2�g�S�{�X}�c2��A���6�qf�N���<}`�V#0���
bY�z�<�(�J=jy/�;�jSV�����q;�)�����z�N�@Y�� ��L�k,-����-_������\�����,�����3�m�����(|�;�
[��':��r/Z�k�g���~��hK2;�qV��d��4.�lV)+c����k� ��Yr1+����8.��u���e���B�����r;v/�H^�,K6E>pV�2��-��8�*[J�d�K����e�����qV��O�#T��RF#J��,�d��"&��U�)���a��r7�����f v<-����X_�d������-���,���4v(^N��Z����D�����xW���	T7��K�*���0`V[3��}�������:bh�51n:��*k"�k�u�i���x�X��k���N��b-�M����2���!���q���V+4�������/b-��d���s���9��r[o�R
(X���Hr�U���5P]:������7�9�%�*c����@����������B�O ���&g���o�`J���x��ly;�].���)��W�3��`�uw��K����<������4����.�T=)����*%�"�	u������BH�k���R.A�K���O��S�������|Y�h
���	����������l�zv�e{�g@�`�������;k]N�
�%{�KXB����g.}a�����4�����t�<o�_!�e��La����g���_�f��?q�_e�{�-��N�D	�u�%�u��WliK�R�N_-���w$�5�|!Rod��g���������vtMR/���6�x;� ,=M�0>�2��1�HM��u�[y�vWOcDb�g!A7�XWi���������O"�xn��S�m��c����������Y{�Q��ay����PBf����n+���z���mw�X������PdU��k�{"=��<��{ll=�H�Pp��C��������v�O�}v����w������=&�����C��������D�@�������HU���R.d@"���	 &5F�^�[0n�X�v�[0���
$�-0�����u�d��������b�}�����A^C�|M���b=�^�W[�
H/��L�`��cw0T?n��q�a���!(��G�����t0$�#�C���:�_1`(���UC�&�8�_2�9��<{'�P���$�X,��0$�"�o���p���S�p0$�Q[�L�Dy�`
�#!��yu����@QOL��xQ�<Q*���m���\�h6�nb������:L�����z�7$
$��\7�gu$$�a����Q�[O��}�B���p.9
��^��~m"���biC�����	4T�'�i���G�4<T��Lx�a=;8E!�?�����8��O?�79=!�O}�������=�
�#�����G
�Se������M� c/����$c-��'��� 5� ��t�iiO��)��4l����'th����0f��	�/�UG�L�|��D�@Ga�E�$�81���i� l��H@���QA�Y�����_CHa�/��oG�����G���Lub��:F*�X'Q�{h���5���#���F�I�F	%�(�;�\��$����_��K�V*O������iX)e�^��f5YFe��R��Fv�\������JIQ��2v��M[R�-�5��#C���)��%PH9���g����P��O|0'��_�K=��]�:u��TGIP�Xk$����I�w��'��B{+�H�zk�W��;@��?�\T�'�Z���`�w(;����}�������B�}aA5�C������57
<H�l��:.��������o�>�"���}� ��3�R�m�/�����*��xc����G���x* �U�<����n�l�09�]m�Y�8:/���$��n�����,g��P���h�@�[���@De��a��De�>%���j�����"L�TT�Vv�FV��.*
\
`�G`�����yl����]�7d���!|�6hT<��a����
b�����6h
�7k!����}<������xV��!���X�gn�`�\��y���a,�����d_�f�2R�0p�l�p?P�-�4G��!�tJ>�R��5��V��FG�����}	���:5+�3�V���@{����d�h
+��Is�a%u�8V*�>�B��.��vc��3_+��]X)-���X��Z�E�������W���~���|�;R����9���#�����R
����W)IFIX�h�D�L�R�C����9���J�F�:Rj�XV�
�[����!%�2����J	2������@��b2���b�3��lH)�r�A����	c�GX)l�>IX	��t���]	�M��#�!l��X�
x&$����R�����+�%U�NA��d-�{��<��Rj��#�����/k�H�v�_����RX`���r��e_�5!�hh�_��������b�YZ�����	�-��:@�jb-�vl�|Hj���QZ��N�]�`K����*�������a��Q	YuN�a�$��tJ�ae�<������>H:�(��/a�)^RB`%�
�����%���qh��)��mh�Lxa����6�r������7��KxVr�x�mX�36�R�0&	����QJ��^

J��f�6��k�
[ix�,��������J��B�=�(4���o�z^*+J�kIl���K���+`��S�i=J5 n���b���.��2!�����,)z����`K��$�L�o��(k�s�|�n��E�Bf��<��C���_Q����R���$S�P�Q��������fb�`�cXy��6�2�)`�	�I��)$
93��6xw���y0V��bQ��1@Y0�x�������81�.w5�$�b�p�XE�������7KJ?�k�Ws�$��'��v8��L-�v�DS�qq��2����H�p����o2�D;��uV���@#E\.��2&#
�������g�ew��;�l0
-���uG���A��4����O<�����a5^k�������Ifh)���r�-�	����T��|�z��PG����e�l�Tb�����a4�y�^��af���KuK�
/��'^�
�����������(�RY���������4�+(�RyB�����x)�0�w����p!)^J%U7SF���`�OR�X���R�J��I�����d�����`������6<�I,.�.u��l�D3
2���=b�Me���)���.���&��QCL0�Y��m�Yn�s����C�2�r����	��Q�/�a��M�c#ELy
kBO��)�l���zF���M0�F����O���"R�O���&$�1�#��G����	�
S��,��CL���zT�K��=T@�W���(��<y���*q6�T1�;*�90�V���oM�S��b)��R&���tP�]6���C0����D^v����1!`���	*:*�"���Q_�*����:6e�xZ���";Xj#6�J��'QYA�O/F6����Dbh�l��:�@KyO���b��W������e�q�9�P��x�F�6Q��GX�p�T:�6�>c ��z����F���_���l����:�z�8�0D��_] [��?yDVb8`���-
0i��0��%|2
y_��VK6�S��dH
�g��� ���4:yi��]^>[F��d���Qb���u|�4�z�4�	�9hJ3��z��6�����6�U��"lj+��6���b�q��V$�����xz�fZ�#t�=��1��S�$��8�>5�w;p*���?�S�oc�6�&��DN��O��y$��#
8_'x���i���)��0��kh5�N�� 4�:v��:ML~�0��9�z �`@!���I'Z�oI�v�$3^u;��o]��g:�"gy�N��#���

��B��07���s�Tf
��p���'�������-� 5lENy�q���fANmE�&H9�
�C��SF�/�d.CNeF)0xb���{	3�2�/a�3�3V��)��:�J�N!b�����5��Fx9��V�#f����S�P,9v
>�c�q`���j@�j��ZKI��Z�DqJLIv��Z��5��6D3Mj�����u���(�.Y�ljHF[p��|K'GVwW�1.X�����U3�IJ���+!����mT���:��@��SX��jrJ+6����YGT�	�!�:
�����'��$6�djm�b\������u���jH��fW�rO����������:\[�t��4�K�$��0L�C�dF���TVl6�57�V�:I���C0������l
#*�lgPSK���:^����������1S	��T���	F,5��!�4�iD='^rv�� ����v�$+jchv���]���$`�������d��Sh�x��T�"6��@�LaHe�]�2�@S��uz��&���b�M}"6�KV�Tv���MD}���^�����YYU�A�4d�:Z�a�)�x�W\+x��DjCOi�d����S�w��X�������Y�U�O��}�]EP���������
%Z9���v�Z�h�H�JQ�����������X�REIi��(�����,�IZx�-A������'��z�@�uX���Y$�.���
�������"F��_�����/��2�XxXJ���`��q��R������%�T�b1dd�34��X-1���M���2'#�P�)���/LIX���>�y��Q5%m����d����W9��1�����|7���r9��*�(��zT��,Y����p���5�q*�`UY�m�P���*��$"BV��i4���A8W#qMU��:��D�
n�Z�`Y�
����@��V� ������P�W��&�S4�U��2XKiy��yX�^����V�C�HO\���b_'/�VaJy���3�U�R.��8�jSv{��"Vm�jm+����U��4]��*M��U��s`�V�a���U����ODE��)s!�LHX�%/�����jK��P��U9��v�@#�5;�lu`�O�b}E�dg�*-����(��]��S<�D�{3T�8�����u�	��hG������+�@�����e?��W�+@��ZG�%m5�hF�����4�c��m���<NZ�q�m�Xl�i#�F����P,�L�DX�Z��uV5���mW;63��Q3��T�TGZ��s2ye����0��� w����6�5�Ah�mw����1��CWidM����L~��_�����W!ek3�i91X���vW�����J� �m����WK���e�����������Z-�[-�Q.�������*��M0vL��u�%�
�J���f?1y�D�w����X4d/%�R�[<�g����;~�ex�e�
"�S�*���V�(�x��k#�����D�
���W2>�O��C<�x����o8�#Oo�����y^���N<�:008����%b9�)�G��	��.�OY�4��
��x��F�����g�^����r���W�[��%E(�s2>>�0�x|v�d;&��	�c;(��G�l5t�i���Q2�C�T���>��'�BF�'������X���0�H�c����l�A�X��]����3S��R��
�Hw2�@7��;��������S_X���+&g��V*�b�>��d�,
��rf�r�=�|�Zd��~������\>bB�	�h���f�'~�n�R�/�Y*
,���<-?���g>�D+Q�g*&2�������-�w��p���<K�t���!��9������)�-�c��zd���/KG�PO�n6b��/�e�qyctT���`dz������J��'D���2�{���w,����W�����n�C����8(�7r������_I�1�iV��1�+��Imxc&���.�?�
��(�����c?�P��
[t����1���t<�Z�+������P��v�gx��X
�R<%��C�������V����������|�����U���h(2����X��Y�2�gh�`����gh���y������M����>r�4T�'$������h���LCC���:��Y�kEC����@��X��X�$�a
���{��!�~2m��01@�
���}]��1�-4_���D����Av4D��8)���X"��xGB�}��|��^Y=�P;� ��X���@��X�Z�'+�&���W���a_�$��M�a��#��u4���&7:
�k!��9��g��@C�~6x��P��Z�,{)7<5��r:��7?�xI�S!�����%I
����#�/�a&���X���F��	�����S��P���(���)-�����'N�,�/���B;�c�0�L��ca&����RB�*��5�n�����h(E���	�X!������5CC4��fh����~1N���?�vW>�����������`�[o�r*t,��)�b�5FB!�#a_w{�e�B�q��qP�^�^A��0�����r��J� �t����K����
��B&�@��c,�� �����%X-K�_={UC~���������/�y
u�����j�\j��
n��T>�a����
�>���
s��H�c����E���F�Se6���`Em^�!OJXk�SZ	���0zD�{�!O,}&���/�����������O�@���q@�p�����J�d<�#l��5�}J��.��Ci��L��_�;�^4�#�����O�~2���O,o=�Y���eO�\n(�7V�����7�����R�s3B���gZ)C"fx�� ��$Y��Z�M���'Y�(g����B�J�������Z�	��y�
O�B�������o����
endstream
endobj

15 0 obj
57220
endobj

17 0 obj
<</Length 18 0 R/Filter/FlateDecode>>
stream
x���M�$M����_Qk����
�frpG�-�H@H8�}!���3��y,��;��t��[�	���f��a^�����_�>���_�i�u[�ay<~��m�������������?~��?��o������?������>���>-��l���_~���~-�4������>N������q�����>.���i�����s����������^��������e�W������?�e�/�c�?��~)f��������?�S���W��W<��>������������~�a�Q�����A����8
�����}���?�; �~���1O��������o[�e�����x����4����u�~��������}���}]�����6��`R��������}X�����m}��c;�����1�����>����oT��~����X���4�>����iz������z���<�b����H0��l�>������m�
��dn�����eZ
��'�l��X��a����m�X&�>������L�z����m�����}����~��o�����1'����~<��?����C��+��0�c���p�:	e���`^��A�3$-�~6)-�4����@)�~�������:�=���3���]�c�}��E������:��������������[e�O�z|�Up1M8\<�����\%���{���|�:��U�;�?��v�s���C����#�I�{�}>�i��#L���;�%T��?���AD��t=��c~X�������w
p\��?�%��cX����|�G.��S���#Wbut?��3�h�a�����0�P����-�|u��B�@C(�5d��g����L�B�d��?�6,�ik���&��$��)��Q�5F�b���C�IW��u���:��[~�5p&���?|N����\���+��X��e�����r��!������4u��"������?D�t�z��#��j�}}8D��r��FP�c�}��y�m~>���ij�8l���K���f�6_���M���*�������2��3��+�T����gT�����l��*pz��!����x�"�`&���_�s������/[0lg�\9�:nm"�`|���@���4u�Ei1G����?bN��/����M������eU��9?�	�HS��}�>9�i���]��=�@T��|��3��+�YS�������U=��3����QSqv���Ua��?�K����/����g��p�r��/������N^���#T'�g��r�IW��i��v�{X�y�{����W���T7B>?�G!_�����};�=l�Zx�'��>���O/��K��CDi�#J:�������J�?���	���m����r��|�}�S�/��y��)_����o�������P"T�=BI����:�L����V���OO('�o);����|�k~s��`����_��O-��E���"�K:r2�[l���y0\}m[��`}���O�'���<����!��C����7�C]��$���g��+'��<�J��o�����sxx�"�����J�Z&�ON�"V��,"��+�Gv��DT�+�QJ���otD�6�]��������s������>qpB�&��g��:m���:��H��oD�r�[��	f�:��������cq��e�c��:�/9j=���|����T��G���_�:/�
%|�<��Q�;��PBW`��3����LE�0uvE�RY$6��"�������'6"P����9����^�@m�p�pp��\SW��'�u��,���-7"�����R��Gr���������:�\�_M��������Z~�%�<�>,N�o|�%8�y`�>��!,��$��9h��2u�n|^�q�KJ���s�(]�o�g���n����t��<p����!�����2�������Z$j��>Nx���Dm�3��v�%#q��l��1<Vq�}���P�j�&�8�������Sx����������3�t?.F=���a1��p�B
p����d��J��r���p}��'Y�'"���`��{��t��c�y��I�?���Y�e�1�G��5���c�?�l��C�!��P�A���|:�����$bN[:|��>S�[�it's[�IS�cn���������������5���:�>��b����>B�[~.�Zjg>��I?�~��6�|>����c�Dj����eZ�t���q����G��;��8���v��U�-��3��������������3ii;dK|d��X��|e��m�r��� ����j����vx�#���]l!~/���.WI�\��v �M�����p���c�!��P��(M�.�����&�GHJS���L^�������s�!Y��!*��J���N���C_��<=�%SCL-�-C�`�v��~��v��Z����M�4����P�w,�������>M��3�Pi��a������PKa�O���Nm�������|O�.G��t=�4�O�?�]$|'�Z���>�I�=��Wl�_��['M-�+H=mQ'M�'r�o�giI�:ij�����?�v����):����$�N�H���p*a����}�70?k�T���-��C����6',6����.��65�h�O����g����P1�Y��M�X�����v_�����5�/9�8���CFSD�t���L�j�����'������3n�5�r-Ux�p�q8�?^Kz�������nM�a��Q�����5p���D��'iq<y����tD������}U�Y������w�-���t����\M�#Sg��"�$��J���lD(K.������tA��#R���R)���3}��\���� ��w��������j���t��"�U���WL�G��.��J*�'�t�K��(,e��~�Z6'X:���q���|XPy�1��B���i�������y��?;4�x��s��B��E�2u�-��S'k|"&�����?��R�j���y����y�
�u�����!�\����"p~��G�zQ�C�����"4���D���8��j#"Z���5]�
T|V�G�hK'7�U���E��k����l�H���XGP����m��<���XL]�6hS�t����"*�W��c��g(ETjK��y,��R�;�L��R;u8�<�;�*����N������_���Qyr�����LET��:�s�����U`���R�#����$����7%D+�J��j�yT�����S'�.<����9o��.��3u�50u��>�R��{"�+���!w�h)Q[:�[�ts���[�i�!�����LK�I������?���]�����;=�������b���a��_����N�z|!��;���Y�cP^����"���������A3�/9�[x�/��G�������>t����C|IS��P}����
�v�2�{���\�^������]m�? ��D"M}�4����`�t������F�>�����?m����-��{��M]�#����y���7���#����f��N����T�>
[~�����""���9��R�3�K����]e�r2=�Wcl�����Y<dr�������'��A����r�gxE���0������$�"N�}A7s��:��n1G�r"��}���q���i�_F(�������~��X�}��6u9����m��X��f@�z��X"�t,��<�t0��wY�_S4�L�h��u9���C�������U�� D��Mm?1%�M<����6���=�2u6��w�K�x7bH��������M]�Im���
L]�6x�'��k<I�p1r��e�U���4P��WN���W(3)b���������T[jS'� Z�S���?���	.��+b���zHr��;��5r�P"�`��^�~<V�X�Pt�m�r����K��5m�l�R��6uq+z{�?�������N���$�Wxe�H�.fR����7����E�K�hh�H��MJ�`\��*�)��/�F0JW|����b�8����0p�ZZ$�:�3�M����X��'"��}OqmmG������2���W����'P���\d����F"*}�Q�DM��/*N�D��k�_2u���,����X���Q��'�&#��x~Z���������A"Gq���y����'*�?��$
����p���~�#�4�k�e����`�[j�M������C��A���W	Lj����C����:���qDO~�=������$�wr������*�L]�������.",��lS�����oi��T�K��Y������
��A�9�R{%k��"�dI�C�
���P����t���W�����������<���v���xB��L}��}.�G�<	�����M���<9���G�>N�5����M�������S���45���!��o���e�w��`�sq�s�[xd��@��y1��L������Om&�w��_R�B��.���NP��*�����������_�C���z�Q�v{��%�,��I	"��G�i(Ws���U	qDuh�������\�'T3?(l.G��,��#����p����hD����'��`x�BL��/nQ��a�5�[�i�G���/���)�KZ�����m��ZY�������y�i���#M��6}�9�J�����t���I��{�q�-]�U �>M�?�z�C������8�''"�]��D���
9�'%M��RF�IS��E�IS�cN�;�{o1�����t��3��L��X�=��w���[C:1�7�Z�S���������N'<z�IKg��q���=��Fwv�������I��7�����r��lV�n�"��%���o��4�
L]Hi�zDj�Wy�����|�x�D��������5�w6>�b���+�����^�4i�z�IS�%�"�4��\.`[���_?�����G��.�Q������[E�9M)�hj� �`�b6X:����LEx����>�������]���u��_1��xi?�p�1���]��0���|��������'S'���C����?~h-~�]B��3�kYD���d%e*K(�P��rM��@N��y����I_��/x�h?|�h��5�w���wjz����D�!9+��\9��W������Uu�*W��P�����*�G��\8�6��W��������v����P[:����6u�/�������[
��CO�"=��S��]����8R�=������T`��B��
L]M%�.���g���gE��"~p���������������j@d���`�*Bu����\��,;��D������v�b���x�/<��?�~�M�>�#��#����#�t����:���X#Kz���52uvla'M��_����DP�-�H��t1�,�
�4e�������3
�p��f����oQ���BG���K��1���>BG��^U��,����.�����d�3��(��6`H�����
����|��]iNBJ������9d���C����ED�2�MW��oI���U�E2u8O���I��3�������T���G����|�"*���=t�I`�l�W��0�	���/�"l�������-l���6�����-~�<*<��;�����r���{v�,<��+�}��X���vC���q����GjW����?�p;*�z����<Wyr���p�
�#����)d��IyD�4u�4u���H�>D�6��x�)�]�2~�p(]Y?�U�n'��>Q��ZuD�v�xb���%�R�:�J������G>�R��>'����C-c��4u��	8f������N����3�\�k-*�SJ���A�m���5�~j���T0�}F�o�+PSWC
�]��"|'�"��a��	`���w��9{D*M]�P������Pi��*�E�4u;l�3�-���;����*���q)Q������T~��]��^�N+z�iS�����o%ly���Ibv�d�_������f0��]�B���?�?e�t>R���D����IKg���z��ql'!�\��x��.���t8
=�q[���>����>�8�p�t<��S�/g����j�=uHF9T�G���C�����C�\�_��+iz��|���OT�H��/G���m!�M]
)m����W�R�t>/8�2UR�����@r[����c�����f���R;����pk�%�_8���B(�H3bJ�r17
M�l
�E���H��=�^4��1���b���%�{����9F���<o��q*�%(��H��'�����*!{$�+�Cq�\=Y{��](��DL	Sg?_8v�H?��-@S?_`�*;������y���3����U.W���:��,h<�~�J�|L�����STHSU�[WW�`����G��{���]�r�<���S��'��^L�&S�N�a��b7�(�"�������B�]��Gu-����������`��q���	0u�8����������R��L��A�~~1�+]����7e�l�iW�I����1���PA��������G�Y|2i<�|:��AGO�����X��s��%1p%/�����"�����`�$�8ei�L���l���v��V-�$}?{k�$'�����Ip�������1�������.�?o��Wm�rR�2�nn������G�}�.�/x@0b�/����ux,g��������
<�U��B��W�T�+�[�'E�����+�����*{�-l����|��v���?�6�Rja#��AT�wi�����I3�B������L��bm������js.�e��?��M�4uu����?~����Bj�M1����J����X�����&�s��s�-Z��=���M��-� ^d�~>���7gW��_��m(M]=���Z\����"��n�"����E�-�4�������U#�J;u5��wu��{X�yA���J�����"��o-�'���Y�Q^�-���Sm���������
�}�:��~,Q?����jX��J�[X�y��A��4u=���V���������<�J�}�����6u2I���xh@���z����J�!�f����h���K���7]���CD�4u=Z��-���>�-���Y-Z����8�3����[�
-���h����wD��-���tu����]��)x���Z��jX����z+���
��8�G8u�q[��������h�E��Qh��4u�R���6uM��,A��^Z(>j�Tn��]9�v�BQ��'j�t.\�lwq��)��[��a���&
]��!K�����D=�OI����*��,'�cD�1F��|���M�=j�X����0E���k����,9�	�����-m���L�b�P��9p���:�?������c5�G���q�����=�������yu�(�g��G�`�b|�S�
���M������L]Ka��Nf�+WO��X�D,�S�V���v�G?z������Y���]m!�*j9�EG�IW�}���G#����dQ�M]��iSW'8 ?1+J�����	J8V�?j��|p00u�L�<��S�"l��	D��8����L��yM��	F�a�"�����B���y����*�G	S-��o],�BS	�f��������Av���}�G��������~����������P��#�tV���L}ts���E�w�fL]���;.�:�?;R�����v�k����z�
�.��k�]����@��kE_`j�|�d>�4p�(gY�u�]9bM�������[���[j��i��5m����s��Ef�W�:+ �k���Dm{�'���k~�L��T���9������B�0��,��p"�g�zE�`�j�:�e�Q8�c�S��e���u�x��.f1�S'g��0��jI���V��\�c����]�/���5��0z�5��b��9�F[:|��c��G�6u��L�ZM�rl��a�M������o?n3=���lx1�����9��4(�^���Ow1�������;�}��C���'d�����6�������d�G�?��
������~��A����"��Ki�t���Ki�z\JS���t&.���g��3!x;|9[\j�W3����>�n\����S	��_����M��0��M]�@mj98�u"���g��C�W=�E����
�
_�b������.>���5��I���{�A
�~��DTJK��R��\����(�� 9�UDXj�W�������?%���.X9#&-���o!�:����KWO����O��;������M*��C���������(%A�����7����o����P��\,&S?��*O���2�6b�F�D�h�A����HCW�8u��Q^���#?--M��-���h��sy�-���������~����-��'-����������!����;I����,8��I����&ME���'8��-�3�>���a�C�#lp<�K���ox�3��~]��3k���������������k7U`�����������Z�d$����`���@pzH�x�� b
����Y�H���?�(�&�x���N����W9`�T6+`�����d�l2{��6uQ�/��E ���I�i�{+��D0n��\u��L]\s�����d�d&l�%�:�9��$������k�h�d�{�*S'�����o".~$����������F��b69��M��~�������t��."
��l��4��|�M����V�����r���/i���x/m��������x�)���O;uQf�L���o(���������G�6uQr����I���%)>Tn���sXv+�N�:�@.
������WQ�_n�e�w�e���>8�*u:�F;}P5����i}��F�r=j4����c�{�[EN��y$��
�H�HR���5�:�]��"S?V���,qx��ax��P�s(k��X{������N�X�?_�����$WN��2���X�P�&%Pt�D��x}��b����X����[�A���+�H�������p��o	�-�E�o!����H�n��=�"J$�kI���w7�>��:�=$��?|F�����4[����!�g��&{�h�/G>�1�����G@����!�I�Z)!��-"���e��$W��:�u�"������%i���:�
L�[N��?T�U����_�]�?��� �55�������LDo��v�j�
�:{�����ND ������~�K]�������F_gM������y�%=��V
�N�"�S&J� k�Wa���X���]�:m���P�	�I#�`����Fry#�]���V�F�#����"`�t��G��.9Q'�'����R�
d�yH���@��Z�,�U���S�����~�x�{��E���7�����������Ea)��D�iO.J����E��>�6#i<�ME��Gq��:�N�:�
���@�=�G��.)�����������W�W ��G�z���z� �����c�y��\?�m!"��2;b�~��������
�+W3���H
o��]����x�����j���$H4<�21��=g���t5� ��7GNV�F�IKW3Y	|�"����|6=�a~�I�E��S��r<'Y�Od�l��zur�a�E�.�c�����)t������4�"h���|���O�������+0u5���9��W��I��W��Ei���Y���.6���w�c���r��|2uX�j���K0ur{�a�,E��O���{�����d�dw���FHD���w0l`�ZK2u6m9�
L���o��M��A�����	���C������_��ZX
S'�=��!/:���6u�<5:*PG��gT�SW�Y�������1�_%^0uvm�A�M��24�y����bF��{;�i�����5p`���}�t��8�%�������E���\nq�8�8?r�i��0M�txW<����0��W-8�?��-M��|����C:�[k�CBpG���>����g�B#���������� �#I�W���>�Z�F���3�x�����P����J����	��0u�Nc��\8���okb�e9l������#����%�~,���`���+��k������pw��t*<|n}
p�����g�����U������N{�h�/��6u5[Q8�=<~�����_M��<��z��?��?�'1�,]MJEHgBN9rU�� ���h�����x����|�pS�|�ZM��������!�����������|��?"G�|5�L]�����LA�t-��0]]J���q�����[�.5���>�B)t��t���S�rb���?y��g��n�������k�"q�������!����D�4u��?��0@QE�IW��Fu1��Qi�o��Q]�?e���?�����������������_�������m���~�u�>o��_��i���}�����?�����e��c�z���1��"����<}����G��ui����C��c������8���s�������$��9�����}�������c�w��u��X��co����s��M>�-���>�������6������{�C ��|��;���������9�l�a;��/���O�6���=����p�s���_;���O��������Ez���p�_�}��c������c����X��|�m��b/c�o�C���_�m���1��&��e����~�������,��c������Xb�c�����yn�����O����Z����������:�wu���?��������e��_��o��i�^����������>l�*�N�y�o�8�j��}�����<���k���y�
�}Q�i,l��<
�8k��6����/�0�nj�k^�g 
����N�k��2���i������>��|~�yy����?���P�S&�����e���&8�f9�<
�.����l�r����������a�U�]�o�(`�n��"��_��
��w�3�����v_l�����:��S_���~|�6�p���6l�||������K
_�a������+�j�m��oKy���>��;z1�����r���mz��e$��yor&�������L<�a\���~��������
�D��m���b��t�Q�����
��f�!y��X�q��Qi�8���A2N/=:��;��D	����������.H�����y����7��)9*c}�����a�>8=*�I~��P �A��"R`x��Y���"�7;�Y$G�?o�-rt 4��@�����V�
)I�=�47��IcI�=��&���_��I�+��W�e|������)6�T�����d��\6��~����Os����X&E�d)m�W~�|�[j(�B���ht�XfX5��i���|�a��k���1��}X�{'�GX�;c����le�1��?�Z��S�_���2������������^�l?�`�ieL=
{
��1%���|�L�L!���1����|��15�k��]��0��4���9Scycl�	�;���7���2��gb$�?�	gj{e�to�<�'E}�3�,�u�{.4Wg����{o��T8�37��W�7�������M8��>���L������
��*�L������6=����������wi���c��r�;��^�wZ�c���wP���3������|�Oe���O�Ll20��1l�|E
�l��,|�$�`M������������I��n}����DQVO�O�d� N�b�Q)�s/��	
X�7��sQ�I�A�}�J���\nc�a�(^e-9�
o��DaQ�7��0M�$�ZR����Z�z�[B���F��b�M�2�w|�e��������}!�
UO��fn���F���B����BJy�f�FP(=��<X�H�B5�g����P�H���^��m'�X�
�<�
%,�y��#�q��+�7��L'������>�r�$����^a)���	���UW��MIT��7�p`=/�p��vQ��b hT�0�8����
��`�o����(�u��������[�y�p�OS��'��T�9�����I��QV����-����hW�pE\���h��r]\��������|gV�'p�
qcS��|(��`�����T�!7{���1�gr��p�V��T�����4��a�Cd��:��j�z�Ip����#���n6h�p��`^�E�QB��d��n�i��
�x�D�WYR�O#�����X�-}+���Mz�*��J���s������3��:�*$�t��jN�L�eQ����}�F��W=��T�)�	_|9��))dZV7���0$S�i&A�rJ���$U"yom7��tB^�
n��P9���"U�x��":tB�^��MDA�2�J�m��P5#e8[uB/,g%#T����w9����w�,;%��wlN�8���YcTm�=�nP��)����5�s*@y�s$�f��i2)tf��6�������Y^�tsz��iZ;gr5�K��:�v���/L�h�*<(����d�U�6^��������IM� /�U��.���9XU#��tP��:��9��Si�YU)�A5!eUR3��m�����r�U��rr3������6��X,���F��zJ���������vY_#4^��X=�Aou�WqF(G'xU��u�7^U^��J�	^s�<���FU��	�Di��}$;���T�(�:��;���%,<�`V
�Y��qk0+NK9Y�	��������Y	KY��[g�����|��L�u�]�/��5�V/��[��U�������U���pm�.m���������T����U���$%gW�R"����Mo�"��q��R+��iY��n�,$�W
��^��]�|�qZj����XV�[��x(V��*��#����a�Q:��EGP��RV�+&-�}X��H_e������-�VO���`��,��iv&t�Y�+<�lX*�I:�ju7NG���bj�.�����Ym���#%|9���������g��{m��*OKY�;X������8F,u?�����2<���:������a�����
�>�����m<����N���g��	�����x/����Y���KYK���<+���`���<������R��g%�����������g�~,�t��E�<���i�aL^r�(v��+(����m�������t������$��g��lv�oA�g5����l���hy;����������u��#xV�Q��h��<+��	��
��PF?�KyVC��08�
��i1vHy��o��o<KX�"J=����Q�h���'y�?���������e��l�R��?C'����J���wV�$�i%?�����-$��Kz�X��uM�s-��s�tOh��^��u���(3����Pth6[��cc�[��R6���t�����YZ����!W�3������W�6�,��S�����`<�|�r�'��N�MCP.Z=���x+�:�f�)�T�a����A4C8������_tx���mLV��onE��!r9{��g��Zy�|���P^t�����H���KSb�[rS��K8���3��Hj�ez5������2�f���W�k)�Y�� \�C����Q�����A�-�VT���b&�:���/�R�P�u�3iM����]��GP���,��w���J���D+����6�P������l�\2$kI��HgY��v� �$���uq�	���}?\�
��Q���U+�aS�+��J����`��U�A
V�kwZ}O��}����Gb���:�UyQ��EG�N�G]�j��
-�(_b��l�*q��V��"�!�$�ZFM�L+r����}��wdN�v�&%1�����|��5) �c����}���?�m���j�i���F��Uho�K/F���t)����/�q�@�����S%��S������i�J�P���XW,��"���)n����u�{�F0�|����?�}���-�|�mw�:���@>:}���o�t��x���z��'���sn5��1~���>���u�����2���m���_wY|�OMU�4����kyD�>,�m���i]��/]l�����gW���.��2��L��A����bP����������`�G9�:���R���%O������lle�#7�N��}x73����Y-l���p��Hp
���(,���]�Q ����S y�9�(P���5=A���u�rP���$��)Pz��"�J��J (P{�N��(P��5YP�������)�}�����$�@�������XZxRJP�4H6��U�e
���\�d��Ax�*:��mlE�*���GZ��2�����6 ���m,%�4���a���b��B�qv�y�'b�������y��{�e���ZQ'v\�����������H��+������]
*��U��,����<�� ���Br�j���<hE+8;?�� ��2��>�����vE�������b�Ng���{��B6G�L�Q2�d�t+���	����a}d%��K�`���%�k)cJ�<%3�]�`yw���.j`ApY��a�w[hdt)F�,�QE]���%�.�S��RF����r�;��K���=e���0ra��e����]��!�hp�$@�A��a��_�K��A�8'�) �X�!�2����A��>a;]&�����.e�:]"��;]�H�Y������
�����y��(�m}7k��X���������1���|([�T�}(^�l�^�UO:�\&HF8�h|y���[b}j��R���@��5��k���8S)�RXH�k_JlS����/�S��
�C�����T_�<�zD�����z	�/i�ER�K�A��|�H�"�Ra�����	p��R�#K_�C�%c���K=|��0��h�e��������}��d��@�K�c�����G9[�����$/\U7�a&Oc��4��d����bl�fw����BEB�3����>k���0��q����/%$;g�-���>��X�J��g�S�]jp��`��9gf�=��P���^�L������3��$|�L=3^4�T�tv�)��j\Rq~����u�s����I����bW���	��H�vU�m��7�5Q���`L�P����yc�>
?�Oh	���j��rP&�Xj
gJ���OP&�QK�S�d�b�Q&�(��y=��Y7����5��v�X��h��w`!�/1�4���5�O���LS����h�C���H�x\k	[]
"�O�2;�N����KQ��c���\-����X]M���JjE5��9�2���u;He9������h/�oP������LB������h�B0	7�J/�����X�F-QLsd	JI1�5�k�8F,�1b��1��+�1c�Rk��N5>N��L�^"�[]���o<�X�c�����X����=,R�
?LL����X5������K��}�X5�z���F����L�b���X%���-�U1Aa=%�X��x�z�Z����<M3���N������X����I��t+O	(?�j/���7<�U�(�����~K8�k��g�>����m|��	�C�����v���-d���l���/�Z����^/�Rb%?���.A�^���+�F�<�O��Z��BPV��[��X/ hU�XM�E�F�j�FQ9y��$hUz�[���z��'�U��I�&hU"�+(�4Z�s��-:��)�bC\2Z�@�t��Ui�8���iUOI] ��P���c�rcYvj�*�x��s�_�Dd$hU�j�\�:�j/�[/|}�V���$������V��k~Q=���@�y��u�C+=
�T0���^zqJNL�Y�j�@F�]���XJ�������,�3-W���[��*U�tB����Z�H��S��BdI�P;�c}�,I+�n
���i����D��V�7�%�c�T'��i<��:����O�V�3�d���������-���n�a�������"�r�%����P���K���0�n�D�-v�6pU6��n�]uI>����C
�M��{������L�_C��Qi��YKH����>��������0^�8�v��	��b�`c/�ZPU�6�+�G�]�B��v��'��4������)��}������<�%2I�v����Y�/8Wxb}\��(W�)��+��6��`BEO�en����q�@|�����ruC
����\��V��n�s�0Y�����5
��~�j��x�`�}X7�P�����r�kM�P��8�9>���X? k��i�g9�����-��!�Y�f��
��lh��F�"@*�-��<��g�����n?xaWo�l�t�����iD+q��R9�I^P�Y���������CP,��.
�����A����*<\��`[�Xa�i�/��q�H�����=XV�)�#�b:���K��C[�Y����\�cDx�zdpF�_���0��q�<O�VM�������|#'[����I����-�y����;�
O���jY\����-X��	�1N�������y0�������d�*+�b��.�uT�\	�i� M��+��)s��m�%����H�-�����Vy��70�]x[���s���g]�K�������mP�n��\6T)��r�z"j��K{�����m��m������k-����{�HV�~�����Z���:�J<&��	���O�u��u���1�!}�������/?T���jG��;�j<u7��������n�@p����.�u��so�������q����LK���po�\�v�n���<����<�WZ)I,\p���T->����a�sa������'�0�}��]��t�>����V�$6���2�#��R�����%/���6�����{��8,�1�;��
Xi=������0��& ���WY)��c�)e���R(�J @�v'^��<S>���x
y/\���x�D!���L^�nz�l�vi[�ON�o������/��M����x%��]��s��&V�@�]g]�
����~�2��l����2�}�����]:v�Uh���W�gg���m�p��]��K�(�%��#�������orB�b^j�r\�+6i%�����/�J��.
�E$�v(m�H����S/�XK����F�kW�����s����TUo��IF�����|N�%&�I�v�X]�6��x�s8��
<��jt}=��W��\2O�����|����.k�zi~�
��x��
0m^xV;�����z	����N���h=�a�����WW�z�������I��Qw4X��T��R�pM���lun�D5��o�S�w(i��&�V�*�E?��y���&��=���j_�H1%^�PGu*v#^m�e{����Vf�D*�R�0R��T�i����{�`���F��J�b���rO����[���5��xf��)&��oe��D�)�W�)K*^�7�%<����['^=?O;��� ^=?�D������)'.zi~����j<��Lf�����VG�S���US��,?_�k*�a�6��(��hf����pA���r��2{��m��4�%+j&5�E?J�n���&
��*C6�[d	� _��W������|�������C��6��UK�/f���c���Z�z�|���y��(��7�UV�P����������)��s�<5����|�����3@'_�c��������,^n�R�|i~+����N���j>�F%_��/�$����|9�����eYa�%,#_i�$z�m���S�zI�:#_��V�P���l�S|�p�4u�7>F���%����Y;�Jw��qM�R~|�5'��^x�S/8Q�
i1c�K@����=o�^���~Q�8�^���,��z3,�	������t��=�a��+j,���;�h�d��WX��V�%8+,{���h`�^��fg`����������yA�O^�����:���Hw�s��xJ*?�S����v�����)
R��z!��%�?xP���/�$�^eb�uC�z���#g[�H���{���%
��6����P3Q�3G������QztP�r�R�
)t��EF�Yv�z�������W�0e�\�����n
��|�_�����#�Z��:#�B��w�,�>"�����8wDY�2��
���i�������R�.��=����2�:j��E�����T+�Sr
���N����)�j<v����_'���O���z�q������D$O8�R��y4Lu���Y9g��W���NT��~�%��&�WxR�hj���
�!������Gq�j�+�|E�!P���t���~�	�}���_�Q����&�=<�^�/�Q��ho9��G��t�^Vn��o����|	I����4���x�X���]���q��Oi�8�R��.	�u����������A?�`�xn�]��jN���4������� �mx�w�C��<,����z��6Lz��Y������Q�o����3����}xLr���X7�[����.�[��p_&�i��a�����alW��&�,�e�����1?�a]��m���N�0N�[��\�����/�V�lD��$�Q�R��^������F���LXX�� }t1��`�Qk�S*�K�S1������,���������h������12���w p�A1�S�2T�Q��I�~�n��1��5
�S�g�_� @N�q��~������_�f���
���r���������GO�������T�3�|����G��]�S�����iO�^1���T}M��H��~������8�L�#�D/�,�K��[�1>��t����\���.��~���x�i�m��]~=��������}�.���yksY1n-H?@o.+-L��Z�5���|;k�e	����\6{
Z���j/��������zsY����\1���7�M�"�{sY�����Xs�d�xk.$9��\6�I��d�e�)`�k.�z)���lK���6��y�������Y����s��Bq��zP��$?jT���F���Wy9�%~U�"%K�a���cZ�b2�r_gR�
��mlI(s���4l�����]t���|Y��>0k�)-]��R'La�>�:�	S{P��y�����}l��PcZRv&���������u�$�,�	���>3j������	�DZNA��M������Scx�n0���M:aJ�l�;�9a����?a�<��F���*G��A�`�D(�~���G�<��9a����$�0���z�A��H+���	~����%����iF/N�\��2�����}����A�������{�]4�L�A����Huv#M���/������0�����)-�L�N��<@g>'M��������'��4�����43��k����eC�4�80
����[�\:i�<�St�L<�3�	�|�����X
��}[5��%Hm�(���~T���4������.B�47F�Pi����ZJ�#'M~��2�@M����my�YbI�n����]�,�(�#�f<&s4�T�lWD���{2VJ����F���n�pZ
��R`�n��H9�Rb�J�RbH[Q2��(��B�7��lw��(���5�RFsU	��c�)Pn���J�F�(�SQ��%>"� J�5A���~v����%��e������F���;Q�U/5�j`5c(=�Ml,0-�(qZ��a���a�^���Lllp'�y{����	�L�{�[E"�������e���������H�������5K�����F�����=]�����������v�zk�t6�dTY���Jx�t|����uO�6LAs}j�t@�WZ����h',��4k3WR&ZV���n��(�8��S�D$����#���!!�������g� a������#PM���z���V��Rz��6�i��*)T����]�cF��
�}:�fX��L��m�=��d
RUc�%�4R�6v��9�N�}������J^|�t#Ui�*�A�/HU#�Yy)H���nz��6�z�{J��N������9��
���S� U��~��N���������IU���[�t#HU���L[����N8�T5��$A�����F�cUs�V�Zb)e�����,w�%d�j����$���Jn�U�:������W��U�Q+<��������������1�D��X�a;�$ ���U�-��\���U��Wm���F�]�
����X�����N���>~Z���U#I���J$^��F��DM7@Y� V
da�� V\��
��X���srr�*�dZN��	k�JG�A��-M��
 U���X���,��R'Vz�R�����������'	������$l5bEEkK>
'VmbO�,�~��(���*Yx�Z��VI�yo��i�����U�����V���"!�^�5���BsB��YVv�)�t#�,�VfWO��E�,J���z���O���E��'�ESh�'5���\������R��,�����':?��R�"�yWu�:T�,��yZzY"�/L��a��%�"c\ac���~�����OWt�*?��,�vp.`3�}�+(���K�^���B�*�{P���.=�t�F]�'�&�f����nm<��\ ���_�9\m�����b�t�iT��H���z���2�sO�h���F���c��M�uz������S�|a�o,���J<uQ���A�O4�I� ]��!c7H��:�B�n�.�ye"�A�*����&']=?�Y�2x�t)��L�(H��gy������z7Z�`e��L�6�x��f[3t�dg+��L�j+�0��`_
g��]�j���[V������>��=3�7gA�����A�����*R�%Y��}��X�y6�%,'uz��W���%5�]h��?�����������+�^a�ts6	vH�q�H�b��7?A����AO�z���S��S/��-��^����N���,B�J��K���8�"�qb���^����*k
'�L�|���z��.������d�+��v��O�U�Aj4��K���J�q��V�7���*�����S����\���Y�o�����l��<!K:[����������(i�6�����e,�X��M�h��P� ,u�����S]���&�����!�)4���(��K���ao���Z�`Y�_�j(u����J(�-���
(�w�!A��US�e� |+�l��L�tV�k�7�rV�� ,��*(V���`Z�r �����J<P3� �.�}H���c�~�%&S�w�~��"����
�\S��z�	V`��^E�_�&�^��*$5�i#��`W2QBL���\�����[����q��*���M�R��~Q�U���i����}_K@�����(����-���un��/�Q������U�h��UZj��UzRn
p�*lT�/n������X:V����h0�������X���4���9V��k`}��$Ks32'�J4e�3�n�,���`�y�ob-p6����V����!d����}O����\�����y�s��^��L�se�d���2U�`�	���,�(��'�V=�[X�8��vr�fNi�����[���)`�o�FY9����[t>B��s�m��Zg	�N���wz����n����q�R�/p��7��������Z��hN�����u����BS�i�DQ��V�I�P�n5��IKTN��fyyH�N���i�s�1eth��:p��-��%A-��-DZ=)�KW�[ab�4AP��`�z�z�����v�Jl8�j��U_Sz����X����c��q['[a#n\�����*�7����m��vbo�&��(Ke��F�	Q��ux�6���V��|)�@�c[)�L�6�A�d5����R�i�������7������/��I�l�'O;�}i���1��?�j4�������l34������1g}p�lan\�	*l�l�'����N�2��E+j5�
4�lM�$���s�
��l�&��')�
�U`FO���C���<��:hy�
���b���W4�������z��8G6���.&�n��@m���F�`���	���*u�E�[m������n�
��?qO�66\}�q2a���Z�8H��X@�&Hw�
���+���E��m��T� HWyRvb3k:�j4�%��.�Yk�1B��Kh����J4��x��������u��9�I���t5�*)A��N�i�����F�O2�*����EOP��HWN��� ��+<)����F�
K������VI���IW:��)�.
���T�����N�l�&He����:��,���L���t��ZU2�\m�������Vs
2�E,e_�����=A�kW�j9M������>b��r���5l���=Y�����gMs�t%�� ]��DWp�Z� ]������t��+k4�9�\A���9��h����i�Zn��.E�hjZO�IW�)�� ���7�������������s�G���d+����l�+mx�v�������'p�
GlB��F��k�
�p�t�~4�`� ]�Qs�2����S��m��U8�j�+mT��&�E55%]�R�a�t������}��Z3~�v����P������Y��LwA���3�NsA�
�3����\Dc���D3�Q���o�+��&H3�K�4A�rn��'UF����{]B���nZ
����k����X]�f�
0-��.��v��l�I���A����T�7��h,'�U�v�#�����^�+��n����!B��G i�����IL�]�$;�j����+m�{�
�A�����'54�tK��?�t����G��4�c���[W�*)�]������GO5�c��t
�>l�*�=����1��]<������'�����s�����/���~�xk��{�����a����I����w5�?�}��;f���mw�X<`��c�W�-�mL��?������>IQ������������&�����2���m������.��	�i�I+��V�:�����vK��v�b����7���F����X~soV�F�XwF�v���I'�pu0V �������
����e4�O�Y��48w��t���`w\���N���-={HP?h�?>Q�
T��\i4��
7hP�O�
���D�hP����gA������i�=��
z��u��CjV� y7�A���V[m4H�^�\w����B��K�`��F��{�*������NO�}�/�����|GJ�T2+�A {�
���3%��T��LYZ'�"m�����(G���+�(Ry7�����������7�^ �j��������`7qY�u�`��k �X�z=o �����l��nC�
d������h
d3:�6�%kB���,`��}}�Z�f��5�%�T^`Z�,������@6�%H����;����,����#\�=���$�F��n�F��5���x�����&�����037�p����6��jh�0?js��0���~��S6������2<:�O�Pt���jD����RQ���e��I��Q'K����FW��O��*�L�
���?�if`g���I����[�&��o��i,ISu��$�KGb�FP�|s�����EB$>@h	���(u�GB�����o�o�������!�SLd�����}�����	�U!��1�3�-�c��*��&>�/l��H��p����$$f*XqR�����k}��YQ�4UsHBrZ�[���3��,dG�N��n�.���5�Ar�S��0�g%����7mA����U���:�L1�����P�G�%j��I�����><��H�5%O��#�N�	��y�1?X2�F�b�4I�	*8O
q�I+v��|hr��'m��eY�}.R����[t���t�~<O����X��LF��H�����_1���T�n�����?����ewd)�����F�������.��L�6�Rb0��t#)-���R���.�9�7��V<�kt)���@�����DL0�Rc���4�R���7{A�K�+�������!E���-��o�%���]J,7�T�yH$/]r,�t�����m��2��Q/� ���Lv�$[�M�]��>a"qf�$Bc;�9a"��f!%�dZ�� �����0iN�v���@�����%9��"���l�IM��A�������������Y��c�}��l|�^KR�����
����6����������������:���AGv6)y����/N�u)�8k��ueE5]���z���������BX�-�� ��h���={K��-��k����s�CW+Jo3��\%S3Z% U�Bn��V�a�\�V�Fmd�U�fXfR�
Z%���h5�����}/�%�o$�"hU���g���*�n�T�i���0�"�A��d5IRy���H��Y��Fb�����`�,)��hU���tU��
S��9���,����*���D|�>�tZ���{�A+Z�Um������ib+ie��
^��l�*"a���U�����V���'\�����|.�����]K��J&J�����*�(>9�fP`w��~��L�7���\A�l��"�����S�� U1����������E����Q�|��Z'U�d��Q � U�d��=��*$�1�#� U9'����l�T5�eb�F����f���^�9��m�������s_'U\#���T����
}S��*m�c|R�RUS��C���IUy��K8�
R�6�\P�����<m��f�
/�t�}>����pS��E`��j��E�C=���K(X��HNUl�E^/�_�s����S���~?D�g
R���dn���RxP�j);S*�V�8q�����%��5�"Dc7�����������F�07��t�L���f��M����1�3,D���6L�������\���l&���SU`��-��	�U6�z�x\�HB)�T�*z��,`Y���Y�b���"/B��-}�jD+��s�9�26n��-�ke/J"ov(��()A�dn��c���l��Z^�49	���$;��E=:'�I%6��
�LSOo[���GtN�g��=�g[m$��N�
�b�.]���V�Y�pC��:�J4e)7cNb#[�f�b|���D�Y�M����h^��]�\#���z6���m#[=7�jJ���H[-J_�:�R�%���>�<����DI�VU��Y���8��&��������Iks���>�Y�6 ���o�>���p�c\�g��+|�Y�]�1'6�w�FY�J��������M/c����z#d4�%_��'�]�R��&7�2C�E�]�Q,�:`��4�cG�����������YF�<��6,wbd����>��\s�������@���KyW�x���	��h�.��w�k���O�w��l�>7U��h&�����]i�5h�����x�{��u��H�6���}O���g-��T�]a���>M�_�R�w�SyY���]�������*x���s ��+��I?�����|��)f��~����IPhc)WA�*����lf��o�F��yi�������ii������Q�$)�2�P��a�����a�:
HuG��ntmGd�a������#~��u���4;8�������oM�z��2��hjS1*r�4�c����u��D�KP/t��h���#9�`]�f��P���6��^����lvg)����������)5ay4�YI�N���M�����c5�$q� \�����������W�!l��:��(��������\����`��E�R4�p����4��F��R�`[����������	t��].b���,)�.CaY�R��Y1��j|����"����7RV
�X�#�m�����-��	K\��'�V@yM�cP���������jV,��uz�h���v���x�Y��i�
03���e�P�Hq�IV"�M�?��&_���K����QlI�3y���B��O#X1)����|��k��W,��J�k�a���
��"��J>�]����V�]����[�[�0����m�eT��OsQ�Uxk5����Qsr	&mb���)����1w%�N�rS�_�x{�V��z`[�O���W�V��q�U���tb�h^���M��M[j�e�S�D�J���[qn�s��47����pgW=7�[�*�F���9��F�+�Yf���Z�*+��(;�6��@��J42��C]MZU��a���N)�!(6i4+x��|����9�j(�G�����7�pxg�l�j�d<+��'6�Ml���h�%mm�t�����}�#c�Q�
�*������fH�����Zb�W�g��;�2K"����o�����	��#)u�V:���B���I�M�j4�wj;���4&G��m����<F�Uh��@RQc[=7k&�l��!b��h�W�PT��}+_���-�����Z��U?�������m�6�3ec[xi�K����������g��VC����l+��1�f�`[�Qez�Z����(ze�`�������6�1�B����?*I�mi�-"��������Y����PMl��8��w���4�v���
S�N3��
#���U���AQ��[������F�
�+�nOdFi4V�]��n	��%DA�zn���x{�����eiF��HK3�	���@>R�m������������3�[��Z5&����m�^�E�XA�rb�t�F��3����$����bY7��Z�e����*>R��B�XOE������?�|&�8"���J��e������~lv�)�C�d���v���d�b	��^f�l]-��,�����k�w#=?6�3���:�
${��[�j4F�@JN��+��P/�h^v��[��������F�07��l���
MI��B���Q�D���znB��D����U�x	����58u�um�G��V�����E�b!�����(;�J,������X
���@�w����T.$��t�b�~�j����*fn�m}�m\�8v��t��6�k��s-���b�<������e+_��m���S��}���:��}�e�����������F6��Z)����Ct�[��������h^����h��@i�����Dc�p�|+�Xv+�����I3^��$%��-D����C���}+5c��H���������������o�6��e<�h�X^\�|���^ �X�|+���E'�V���QP*O�[�Q�}���������~_�~�~�1�����H�#W#��5p���m,%+�D�V�R�A'7D�byA��4���X~��{W�*)�Y���b���������]\����q�x	=c�a���:*����-�'����iX�~}�s�y�
���(�/�m�o���������0o�a�s�]��c�W_K����6���������������{^��H��sO���kB���m�]N�%�C����&=��uG�e����j����a]����{�Bv��q��
����aY����(���h^�����������N�yX[p���&7}f�������\�Q��!sjAo���qJ��}��e�j?%���N��~���6���u"����5��;�Z�J."T���
"�n
�� B�^W����������a��w��i�u��F���s�@#B�=hb�h�A�8��D(�'� Bzg!3)���j7���<�X�z�=���oI�F���'�A����L��r_����(�+R��+IN���p��qbC�~���r&�y��2Rs�7���H�[�����}�l�4z���
{X����{Xe�au_k�B���WGX����,{@���6��+����D���j��Z��7���$��1�
`�����,d���,b��
`�H�<`k�D��~�������P;���4����y%-�!/J�t~�m#yRr�%)�5�1�m����)����q��F��@�n�6��z�����)1��0��W�,S[H2V�0��&��N�r�h��:���1�}�&a�:#'L5���*X�0a&gn&����)�N���%a�L���Hr$S�O�OaB,�8o�	c	�9a&��N�	�\'L�j����}��L����K�PeW��e�F��JLe��@�)iZ��n�Z����l�j8�t�L����X��NF�������2g!I�/�2����y�2���~�@��)�k�z�C�lP��J
�e
�����e"��L9IvG�L���A�8�Y��)#���	jP���z���`�2u,`�pP����J0(�1@MP&�PnPf�A�8ej3��e�<@w��c
����j���>�������vz�(��R�t��6J�I.L��J�������k�]&���&))erp�p�9���^p;i���Nq��<S��w$3�|�<X8c���?|��
��[j;;Y
��#�J���3T�3�o��)�Q�z�&���2P��h�&��:9K����$Hg�6����hA�H��,��
,����zg����|E�i
��MTr��LX��b������f����K�C�DQ'���3����9=Q�B��]�Sb\�^^������'��F?sm�v2���l����"��%�r_�����������~���zNs���-p����IRV�3g ���kS��f�h�%��3�M���9����������4����Q[C�d�3�o��i��U��v��{�XU
����%�g��;�'�*����sB�$�,�ml�A�]��x=�J6�J;o����v7N�5��R��)�VK���j6���g��>}0O'V5��{�m����%<3b�~�}�>�sb�����7��X�m��m����i��Y������Q�U�m�@2�XiJF�3b����K����bp��OK,Tb��X����vb
��������B��+=P�7��
^X�)�o4be{R�Y����A����_D�F�����"�2a{vcbeu���~���H��-#V�Q���#ube�j'!V��F]��X�N9'�[W	��X���!������Z�REb��(}v��� V��
���U=��z�K��X�[�3��J$��G�N���n��ZO��UN�I5�bN�D�X���!Z�5bUS2[��DI�0�5�9�X���m���X����U+2=�F���+Ri����e��Y�����S�d��Vm��(Ol��sF�`����&�X��z,����'�rn�>�7��9CE�U�Pw�)�&6�x���4l���iA4b���/����YD|E���2�"me�*��\%�h�����f�1�x}@��E��r2��m47/^�dxM9cQ�5�M��%XV�	�"�\p�"B������,"4����
+0u��j����F�����,�P��$������P�/�Vc���I��V�"�R�D;���F��� [.�)MA��G�P��V�Q�3P�M��vc��t�;W�a���.��|7�����(�L����c/����u���m����R!�V�~F�
h��t+l�\���>Ygr��6\���~��F��L������n5Kv�b�[�f3Is���t�s��]�D�tKh���$9�[�f����39����]�3#��Q%W���n�\K��
��3���`�Rq����������1
��gx�Lrn���S��3��q�E8I��eno���R3�2Q1���Q��s.�`�:�>�~g���Aq�(�<��\�1��z���`)����*�Qn{���s.b�jBr����������^��G�l��l�����|���8��c3���5��h�Do�q.��-F2|B�e���\�������s%��>�z��������s.E�����s��l���K�j4��-�s���V �rUp����tU�+�J��-�tp������("�8W[y�~��
�W���P����������0�C�/:f�%K9���U�W�oV/�^��E[����v�
�\����g���j���v3,y�j�e��S���1,�� +�:��G�"y����]a�n�]�H_��
���=H9�j4y�9�]Bc}0@��iW���3�gM&�������5�4��h��)��:��W��(h��99�8�b�����'���,��l��+l�ej^V*��9W����-\p���Bcw��W�)gU7�k�q��	�jg\a��%��9���i���1.����d�Kn�H��`�\pc�M$����Qfv�2S�\�e2�|�~<M�!=]F,�?i�u�
��+�T��S�����<n�+|���F���r�J�������h,=���t��v�x)���d���t5��Tu�@#]@c�[zi�HW�	u:-
�����$��:W���y��2V�t�h�z��u�N�zj��El��S'g���F�}0sM9��	��h��.k���X�c#�`:���(gi��DP�z��2�I��A�`���s��?O}a3�K&�N���������\�Q�_�l�\z�c�"�R��c�"{��e��dc-���K�4�cW��T�75����X��\��}<�L-!�k�|�KGQ(�h�+����p5��|����Dcuz1�7�P��Uh��l��� \�&��A��	���(����k�B�n��WmW���A���a�k�S���U��s��n�6fih�tKX�p���V<�Z~�Y�A�
�+���=��m���,W��
�E�L,�[mc����p�%7�Bi���Q{�Y1�`�c++�4{J���A���6�m�[F���!�v�����v�m��-�,
���m{�p��smF-����
(S9��8gZ	��+��4�VB��X�uv���bRO ;�4K�2&�q��e��q�,��t�P*=��XPl����9���1�F�XV���7��?�*�6��t~�����;
��j ���;/gWd�
'W���jy��M�C[(vje+�:�j�e�fU@�:��})��e`Y�]�v��j*�"�`U��:�N�c.�����T�
9�R�����2�,�v��CVhj�H�o��!���Ac�>�������U��J���3xU��@/n��*�X:1�F�����������&�^@J���&�l���|�����`W97���dA�����Z��:-����Y���F���-�Yn���oc���x�Xf��n�>Cy	`���b�����,������m��lc#��`Ym�����?:QS�����_�
��L���Z�
��^l�^Z���$������!g���������c�����%��x#����l���s*1W5�V ��s���F�
M��\��dKhB�)=.�h��Ug����,vH���j4����N��3����fc�]'[D��z�r[a�����M��	��(��Y�P���ba'[a��-����'����l�Did#[��eU������|�{Z�Q�����n;����l�[0��[�<Y���B��t~l���/K�m���:�"�
k��n$/�-ot���#�R�Nn��k��(�j�����];q�v��~p���F���j���Yx�_���{� \�f���tw����,H!j��sS3�5m�*4Ok����
4����8A��f�-azx,�|Y)3-��p5�5��k����G�k��6J�R�CL	W�4O�W��[(,����mA��m��:�o�/5�+K#\c�_���p�k��� \�bw�)�J�S���p��V���Y2=R�bN3�	Ky_N�0�r�>�c�������~��P�y��Gq��4�cQ��,w�[�n��s�']a�-���}��U�{�j@�l�0k�O�=}T~n7�&�C��a�t��P���mx��_O76}�������S���6Lz�3��y�q	x���q�S��l[��������+���p!p*z8�~�N�=l�o���r������a����1�l��p����
BB��6��t;����T1rH
r�����,g�����#�w6�W����=����}wa9��PJ����m��>������1�h��,{/�F��5���?���
�m�n��:t��Qa\�oB��F�j���Y8
�Y� �P:�;J�g�Wu*�������e�A�������P;I�A�7$�lTH���6�
�{�@kT(Fg�l�
%�����
!p��'��"��Z�
i�H����>-��[X�kv*Dv�Q�@�w�-*�
����gTH6����6�G9mM%�����W��'��B��3'�y�m��3�ysm;+�MU������,Y��l��Jvu�s�j�Y=~4�b����%W"Y�Y�!����g��)Z�Y�`�TZR����y �#�?��y��daL�kZ�%�����z��=h��YZ�%�`]h�w�G�
m2�$�a}h�y�i%���������F��I	3��OA��s�-As&�QE���Z�c/�)���0K�L��G���(���}��q��v���Si���F�b�+.�a�Q���Qi�vm�$e���2���e���jN���D10(����e*pu�_KA�0#�&;e"�v�L���c�	�[;e����N��<P��QfbA'heh����h��4�
��2�6<U�lE�]&�������S,�]+[(�*9#��hc��^g������w��D����f3�r&��3�����2G_?:gvG�NP�h�)-��$49g
��K�L�>M�l�����y�3	�E:g���r�3�c���8�0@7���,��Ydp�~
#_�g*O�5
����4�����<��L�HEh���g�X2}1�������8�?�U������dc/]g������#n'
p�D���/)�qL$M�H�5l��~|��	��|(i���&���9
Y1}Q���Y�#n�i*����(i�-���6���D��IS[��\3HSaxa��F���J8�f�IS�+K7�T��<'M��5���<N��B��b��4i����&F3��4��l��{�;i
��,%M��S^����g���I�n|i��7�"�!H�l,�> %���������d(;MH�&�8���������&����Q&O����!���S�9oJ�./�Qc��*�)D�u���f��j}�%������/<������w����}�5�@He
���e���41�:�`��:L���z����pZ�u���y�����.��e�q��#��jx��z�y��$�`I��2�E���ZD2sC9��HX:H�o��-������H��N��iD�l�#�nT��T���7R���2�T����,#���/8��}h�4t�J����K����v�>]e���__L}F�[6N�{Q��0�3(U���08�F�0,/^�,9�N>U0�&z�8�J�������nH��sz2V�I�{��R9��I�w�N���{RgR���D
M^�H����E�<*Cj�#��Q���l��jv9��l�D�$+�qh�@��B�lPh�D0�7~�A��R���v�l��j6�L|�N")}�����Oz��@�H�pz��@Jw����
�RQzSyG�i�j�������I���� O����\�!����c�=m��H�&K��H%��s5�^�	T�RxiW����Q��R�������J�CaJ�x'�$
@v���XTOIMBr�HL!(S'�o�����xkD
6jk>�!�L*c�iyq)�j/��I8���D�8�TN�)~����Bd���S�����;�&~|AJ�*���EN��KPl�������k���SK�k���{R�R;��%�h����� �E�i��!i�81�UnBX��Q+������kJI������N6�Gi�F��A�`���8r�$����!���W���T��5�Z���"I�;I�K�1� |lf:��vm�d�SG��	���]�`5�zP�S��* O�r]��K�������G�Ir~��o�7�;%��&6H�>V����t*��n��n#X�����`������ X����H��	�e,���]��*i�g�����uw�`����pO�����%;2u�U(bw�H�`�����t#X�����,aI�`�V�A:�F��	]_��xBr.���4�&p��X�x�v��A(����P�X
���!=�)����=r+��eLv�A��*���n,�o��*���J��oc����,�(�/�8���1���Xu�������bHI�-����,��
��M�$t�$�?�|�a�C�F����	��G����J&�M)KN�
�l%l'v����Z��I�G9Y�b[�dKF�A�����X�d���X�D#
��$41�R��z��,=�D�.H�k��<G�p����l�l����$��2�K-�B�H������+��%dB����cn$�w����#�F���v��G�����WA��I6���=O-���j�l��q#Y�c���F�8+e���dK�y����k�1.�}�BL������aSa}�b���{D��R;�>���6L�[�'�qi}�3[���l5�-� �o��q����T���>[�T!�q	/b�q�)y��q�[���O��� i%X�o���$�V�>�[�d��*F��w1�Z��|b+���#?�a��{����0����X�/n����7���S}�����/�qM-I>V���]��������Zv�h��8���#�}%�rg���}�o�@����7���`���������W�y��j+�����+�9����:�
+5�^�����tAu6T���J-
���2�Ts���ga�}�_��i��T�	�5L�r������D�P��7���%����rq���/yR�k�_����*+5�v�c��xBtS�V���R����*�K��;y�_5��u��osy�t�Q��>I��2p��H������
�{���9��^��e?vL�v�ll'Z�!�D�1���oz�������k���h�7+��
%����V��3�t�����g�|������d�4�x^VH���������10�2��4<V��/v��q~l��ute+����
�\V�;6Ci�=���%��7f+���j�����XyRZDZJ���k+[�I+������'�1p���kc`&v��4�Q�JK�m���e3�3pfCKi7�P����;�;�e�	���h6f,�	������Rmg�?��T��|T�9�����e&�3����|�^i00z2'����d%��~���/��3qN�g�'�����?g�l~��(8����;s��E�dOg`�g�
;�\O��j'����IY�}^���e7�5�3���&���� �,��0�8���	g`1�����������1���{����~G-���7��FN����R�%?�9�#��;��(b)T��B-��0?�������;����%�B�� _me
�M������� R�/xb�T�Ll�Kx����Ai�+�����9���T�g�������cR� �����FO��q�M#����SI��A�}<s�1�C� _�IY����e+W=����|~��������yQ�[#_m�i�Qp���+���,�S���?�-��^�|���,��(���t��/CA!��_�Q��,��<��\���[���J��F��B"�o�V��Z���w_N�ogt��-U����JS&9������'�61�Wy���������y����xbP�tE^�����.�����oOH�{!2�&��ot�i�8��i{H��6����W�Y]��.��j���98�g�Ut���K0��"R� 7�U���d�U
����"�Dd��`V�K����������`Ua�o�������+]	�\q�nE���a�iw)�jkm��r�DQRo��&�t�_��q=�eSi�Y����0���Xcg�,tF�[�z������S�?4������&#����c+z����'KR����c�?�e.��+i��x����he��7�!�c�mr�.��:��'������,[1�ByR�L+�T����4�k���;����F�/s5����Xg\�Hp.55�Ml����+B�yw%]g�]m"D-2-��FI$���	��ro���~�+}�[�'��'HJ��t��a|�m,Q��F��.�p+����q����/~]��>l�*��:����A[��}��v5��%�����3���Y��mx�w��fw��&���fk�
����5b����R��8mf�a�����}�;��IN������e^��H�������k�'|���}��m�g��������_�� 	���|[S9�mXzv�F�4u=�;(���aY�K�����?������e9�/����{m��U1���(G1?�/�^����oe)[����-Juk4LH��8h������������]|CW��Y���s"���LEN����}����Ic 'B'�N�����t"�GG��F��<6�1"��S�S'B����jN����L@������g'B|v��dD���7�N��=��q"����I9R�Qa�!>��X���r�n!��
*�-��XF�`c�4��7���'6���a�i~>����eT���hW�'���}������y�������t�\$�.�b��et�����J��	BFS��-�X�������N�����K��Kl���v���!��=�D�]b��.��S��Y��?���v�E������%6�d��K,YH$�Kl6:5�v�%v${��������2 ��L�����Gk����Q��&Z(B�YE,�XOiR������M(� 5�$,;%7���Q���
OFl�]�����W���f�����(SZ���h��),L#V#6��6>R��$���0�U&b�Z'Lm�va*O�����P+����&c��
�0	�~ar,� L��A�K@�A��F��`&HF�	Sax������a�':���W�rI)�l|�V
e�	�-�)�k�e�P*qP&��}S�=&�QZ�e2N�
8:k{L����i��a�}�:��~A���E��y5A��BR���,���U#M��r��K�&<��$3�H1@\'M��V���H#M��
wA�?�� M��;i�Sxq��&a�Ed�f���#���A';iJO��v�L��%�e��@�R�4%���{�4�����Q^B{��OI�m�LH��_ISLG��HK�I3y_'����*$��f:-�<�I���S��4������4o�p�����]Z#��������4���Z]���N�}�}(���� �o��,�V���4��L�����cl#M=�#+Ti�<�\'����t����\�(9i*#�@i"Ra
����_7��y�;�F�:�W\�5�����v�4�}��G#����,���*~�V��s���%!A��������n�����+�XK���4yZ6��i��~�xT#M��W���Hs��.�M$m��8rl�"�*M��6�4��Z�t���*�u]K���H\�S�g��CH�^������dM���ya=n���d�
��=o�@�j���^8<%;s���!���p���L	$.X'���IB�N8�.C4��JS2�^����kr|[��������k\T�r�7������U�P���'�(L�g��M|��r
B���"��V�F���P�jj#o5�>x�A��<�etJ����{Z!�`����]�q�V�����RZ6�b7e���
5ZUOr�;	�j$�S�\	�������2��J�/qZ�)��V�UR�
�>�`#2g�����B�2�I�N��q����5F����JZ�* �/������Fk���*!�Y�7hUO�������-|�jB�ik����	~��O��b%�E�����]��')��J^l%!)��l�N3h�lT��4�m��q`J��0wK��b�Y�7��'k�F��_/��Y�s��b���:�)U�������wF�0v�9��N����(D�i:�
k�~b��(h2�M���h%���(�ct���T�X��Y��:�������U�T����H�	���E��}&���A�������������Jt�����������C�g��}��)�%j5�6�1�(���D'=����'�(9���Yf�)n���(�s�|�q'�x�ZrP�����M���)F�?�,����QT��"FE9��b�P�%
i(��8��Z:#u#��p����	,Z����R������� ��z� S
e�mP��8-����i�F��
�����������&�������D��T@�$%g��8%+�9���3�Ue�z�R���;S�E;����`c+��p
j��nl�����P��E�~DPj������*}y]h���b��	��4���i�i��T��?���'��L#����=���&]��+P�e��k�F�KU�#� X���r�@���i#6��eE�`3(����P,��T�`u�-�������b!�~�k�����bk�'�A�JU��G��	PF�/�D%'Y��+i��H�$�=�d�6\7R,5�UO����<�������@REg�P�.HV���6�
���u
~#Y�����)�"���%%Y�R�%U"B,�?\z<��L��!��=yk��
J���Gu�����1��(r1^��|I��t�M��h,��x��BH�&s�a��S�c��'���$����K`L��e�laj�Le!%[�I-|]X%��V���VJyL��b���Z���
e����[=5|��l)�\N�m��PL
��;���&�r�Ml|��^��x��u���-�X�Io��P� c[�G��a)lKX�c���<�OP��	����.]	�5,�vGO��
�B�^Y)��~v[+�|��i4�<����:C���L)��J<V�e���8?��\g5��=��f������
�S�{�+��L���8?O��K[�	+��Yf�	���|e�`:S��=����z����5.�i�+�X4d���=��j����z5�-��l���
Q`��66��
��6�Z��*@��|�.G>R?\�u�z��2�Eb��cX���P�T�n�����v��E����^_E�Z_����v��`�@���i'�xA�����~[m�{�:G�X�[i�9����>A�Mx��d�vqvL���vqv^F�Z��h����+J�2�e<� ��i���wJ��\3k+�
{9�f���]
�\��iWXy�m"_�;��	~���y�v5��M��SN�������9hW�i�{B�>�A���s�6Q>i���8|������9�q�Sn��&q@�X�]�b-Kw(�q�E${�lf�KH��!O��n]-���^ob����xr�XWX����d_�n�J�t����%l�Kx�L�������pH����4���Kx�� x���i"v���]�gO6��w	OM ����]��}s����V���y���W9W��z�]����M�n���������+Hn�%k�]��z�U��J0i��]i�2��w��H[f����jU�5!�^0a'�����a-VA4���������=��liCi�a��?)�2�'�s�|����v�|���c�w���WX1���h�|�X�HN��� _�3f���|�}U�� _�Slm���E�Z� _�S��D�2��v��|	�f��%����Z��RZ'�>��\&�x���+I�$�A�Ly}��\�o�J���'z������X�k�����/:������~������ ('_�~7
���|���T��j(k=��3������ _
�Y?G��;|����K�F���4*�O�	I]S���Nk�������x�v���8WV����G��L�^��i�@�N�O���;�:�"�3L�y��;��U�^��
�M-�z<��;���p���^��e���5/���L+;�W����E��z�#��S�&
���qY�4�YX�tyJ7s�h�R/���SP�D�*I�;�Q���z�k*QLK�����+c�wq����������d�$���9?���(O��v���V�s�(���l�T|�����t������o�����t����O{��-���eu�x�0v��xLR��!�z5�-�M�]/����Y�]P/��]������pA�0?��:Mk����TU�Kx��R�QoOY,�r1��
{�3am��^zyf�������R��&�iO�z�6��L0���J4�mLZ��
0�~�$-����i�&'��h�]���f�G!�����|5��������/>�zS����R��pW����i[:��:P�|	����w~<�Bc�x�~���4����W����=l�m�+��9��� 	������z��"���}1�<����"�_�k�{p�_�3gK�_�K���J�ok�(q�e<[�N�
�l9x�]�W����(^<�����@6��WYy�FEi��`��q�4�U
�����k�t�������FG+OJ�W=��^0a�,@���l��~������!l=oF,5!0�]F��^P	�2�g��U|7���x������
�en�3���p���5�k��a[W5�nIuo��1��\7�$<��[y��C��y�q��gl~�5��;���2���U��v&9��m��I�a_��:P��6�;�)��-�}xL0c#_`��pu�X�`�������u���<l��1���]�}�7������@�}nw�z&]<��6�<��^�i�I~|��w�������
	�w������������jf��H����*��UU391w�A����,�c�����d0MjF/��Bl��0����N������D�v�q��
h-;�u�G�-��|�������������O�7���������9�~:.����F3��������z����$��'���h0��~N����(����q���]�={�%
��w��kA:r�2�m8���o�Z�S
�{`����7�@��H1t�=�&#X��@&�^�%�{�������rmpcB�1�����{W|J�����b��hS������9&�1ykX�[�ZkXoy��z���M0�F���eP�d�a3`�Z��IGvk
��C���brvk�a��[��4��5l2'Z�f���4�5��!��������Uz�6����������0��,RX���	S���%��R�c�>�N����L�1-A)�QZn-(m��T��2�G����23,�������Z���0N=���������:S�
��fH�L�V^�ij�'|#Mma�� M�!���T�G����I'MiaN��A�8 /���1�X�)HS���i�<@QK����O��&b����CA�����m���D��A����Iv���h~�	����[(;��0��> ='Lp��q��Q�a����|�A���|"���X��wJ�����3ib��U���.�����+���]�ed����t���P�� �ht�,$��A�����.����T���t)1�Xxt�=H��.���<!�K�X2]&����K��5��ct)1<�����3��.�)$���.	u�s���h�zu.��e�N����K�%��3��b|�[�KU�c&6V�lr�����#�!2�L�iB|��n���t��6�Ur9#M�Q�hR���O8i�3�W�)i��}����;J'���r�b�\#Mea���t�),���]i��Q���45��i*ON�
���`��r��������4��C#M���w�A��)�I'�F�<�<XQ]����PUK�� M�TMr������ij����&��6i��h�3�X6����K���4��RI����tF��m���.���-S�������4��D�Ti&���F����]m����[�g��C�
p��l�qZ$�6B���RsW&/VK��^X�F�������$2M�c���58�-�o�D���gm��M	�h�0G@6��W���
"��p(N�-\�)�<T+M'^�<5k�J�+~d6��p &"�U���D�5���7h#Yfzw9B��18�v-��/�b%Ut?=�e�8%#V2�bW�F�lc;s��<����������1$S[��YIhfc�[� �m�[G4����X��g�N����U��?<Fub�~��p�Fb�l�6��U#�������
Hv�� V��W�|����$t�*���C�E
b &���n���E�2b�H��D'V������5N���)���� ��-��v'V�bN���"���
Hf,Mb��&�pb����k�D'V�c"Az'Vpc��sz�KP���\�8�SI�F�{ �&XF�EbMl,p���un�w����I�X�c��/�dhuA'V��_�%����*?�q1):�j$������I�-��_#V��j_q��b</Nd�X%����X����d-&��*�$�:	b�H�L�(�U#Yp���"�it@�X��-;�bU@�v��^���lN���"���J$V���)�!�A-o#V�Q^O+���.����@+��|��m��F��
bU
-/k!,5S8O:B,#wy
b��Q�Me�z���$a��Q�������
el�k���Px���Ia�l%�S��\5;,�R.�XB�W���j,�gd�*��W�H�zqZ��� X����fX���	�o�L��=��`?��� X��2)��N�
Hm�J��N��-�t)S,"Y�p;6A�A��+��u�N����j{"=	ll��0��4�G�,>i3ve$�`:cWBR7�yv#�I|�&XV8K
vM��������"�Z����v�����:��������O�QPkBm��M5������/��A���p�i��d�F�
HH1�\%cU����P�t���l�;��TY&�
	�A��5[�E1��2�z}�"uJ�8�D��1���V�����ob�<B}@��T���N��X�)�H��������[��]U&l�J{f/�AtM\[���P_�
|�
�_+�4�"�.�(j�\���
�Tg����P�
@JK��J�6����_phwt������f+	��t�mRU(\ 6dA�h�<JXf\�7"%,#�9�J,�xE\�R
���A��s��R��F��	2UP��e�M5����f������'��	����g�8-�������$�M�'HU�-{���XUb��zp������e���w�I���>U�;]�=�}����&�#���fX�S���#�Je3�Q2o0,<Q;3LU�xV��I��`�!G%H�%���v����."�O{�S{a��(-Vt����f��/�x�� N����6!aOh"�4��"��N���e]F��1����a^�s-����i�M����������$5g[a�-`����-��r]n��&_�`fKL�VY)[�L;��V��z�T������1��Jx���a���+��B
H�u�?��:,@lGKn��4��Z	�4t��@���R��n�d��T."�W���6���ec#�y���4R!���U����5�U>����h4��Z)�]�0e�N���]b�nP�F3�~9&�2(W�y&�F�07V�����r%�BR/<m�+�m���F����Pe�R5��7�r�X��>�����I�N�L�����F�L9�zr���\��X�rH���y��p���^��r�OP�r�U�P�7(W8��3�hcF��F��(���r9��sl��a�^�����l.�.���Y����4�E$�,/�\�Q�Uo���<�8�](?u���nm��b|)��*��U��Q3��$�08�o�l��z��os��]_Y��9W���jJt�4[��9W���a�<�v��h�!��v3��h,�DR1��=��s%�r�l��s��d=��i7�0�H�%�s��N��&���W���,�\B��vp.�6�U[�]�4�ZO@������b���d� ��/Qf6�sl��E7�F�N���Q�.��(��V������3g��S[KN��e�2q��F�����K^l�I�;�c3�7u�t�6�Fw6��t�+��s��7��h��cN����#�:�F��ny���2�����uu���DS�q�� ��)�4��C��B�4]5����G3�����e']
&����`"�@�C#]���R��f��W2�t)���WwA���e-��+�����,HlX����r��G��GQ��6���N��s�|F�	�<M�^ot�=��am��\�P�e9��oKKe�w/��:�Y�����kv	�6�
E�v8q�+�<C�/���h,G�a�q�%��m.��g��z47�N��l��������Cn�Eu����Ms0���h�%w���2���\�e+'���
i;�j0���j%�����,���8N������:����s��q�#��� �q��~�6��
��.t<���������be��AN����k7�rJ=������e,�
}pZj!�L�Z�a]��9��S��
��]�b9M����*���F�}�)\��%��d�3C�� \��dp|q�� \�f���	��h��R�������+k4e���~_�pin��
��s�LI�M�BSu"V�� �>�9B�_nh���+�����S��p�'���W�.}F�lk�����19�	��`�Lm,�-'f�%�B�s�c
]7���J?��H����G�~.B)/_z�P<�"�XN�l�������C,�6&-���@���������g�B�H�]�E���LB�n�J������,�3HO��]���\D3�Y{��@S�M�~���F�2=xR�r��hbI�JX ��c�v��g���F�n�\{B�������v�Z��iW�)���7�A���h��A�rjL�nQ�v5��%b���A���#����#v����`�.�����:WDY�.���2��z��J�e��G��i��>����<om�%D���X�������a|,��t���J
��q��?���S��('h_X�%J����Wet�����Y���I[j���x�xl3����a��yX,���~q��4��yX������0�9&����1�k6�J|�a�u�����><&9q������ync8�fkY�gRz��y�v9q&'N
}�a����x�p_��]��&n�o}�a]����i'��x�jF��e��{���h�����yu��4B��� c�c�1?���(:��*C)��1B��/��l�k�������h��m��0-nd�t�t���aw\Zd���|�d�w���F����md��K22��S)��apMs��i���\#C�<�A���u��*N�
��i@A�8�J���c�'CJ�
2���B�!<{XH42���Td����c�a�=^�5J#C�Q%�S2��h�Wp��dn
��� ��
H�
2$K�J�lX�dN�<-�d�m��$&'����������;l#�Q��5�e��z�
V+�����2����:�j;��EX@Z���U��A����x��_�#dZ�����������}�����Br�w~��ao�������`!��}ep��]_��o���+��w~T��s���L���^���&�"3#��G��C��s#=���!g��&�[0#�'��b$/�f5�E�������xS�c)3�G�����]��Kk���F��+�D���=��j�����]v����G��{
6~DH�#R?�'o��!	�EjF�A4��OaGq�F�K�d�%�}�oT�I��k�O*�<>�R|
��'Sj�j�S�|��Apew|#JM�T��f�2a?l	6fN�
�D7�#m�%=��q^&?��Lt�c���2����grx,�9���$���=��fwd	�s�i���W4'M���he'M��Du�����`-�)������ij���J�����y�+�F��$%G�4u4��5
�D�A��)��l&HSY������ M�%��
��f��o����s�i���q�H�����F�h�f���	6jW�|��Q6B�r�4��Z�H%
���"��d?v��j�I6�B<��byUE��4����y�%^N�bd��.x���)-D�nsSIS���N�z�}� K��&YHv�F���>����&x`��%k%M��if��1<�4�I���}��X���49����I�F��>$��4�}Q��ISb��Cq#M�����4�h�J�J�z^x�����h��T�m8OH�,=m7H��2�z��	�}�Q[Gg��lc��5�3ffc�+���/��>I���2�b=qa9=�������reCsok6��z�YKs����u+���l2��M���Q�����/��������,�\[����.�[���&Z�
1
I@������]`��*!a�+U�N�\A��v6`����� ��s��-/S!$u]��7�!{�M�;��u�W����bzZ[�i<�4���YxR�:�T�QT� ?9(�EIEJOn?�Pn��R��
�B|�`��pSR��\Z:���}�.��
Rc�V�IK� U��K�k�� U�������`����o�JH�S"qR�H����H���x9�J {��@	'U=%&� �tN��7�;P#U=%&�C�BF������T����D�L�Hl�&�$�8����� U�ba:sR������*�x~����Q�[�#�$�FUx��tt�� V����&�&h��7��[�I��5����+���f2�#�q�����W9�t|���I� ����^q�b���l����=^k�FyO�37b$���j3�U=�����-X�X�-����Uza�e����UN�UB� V��1��i+<N�������+K�l���dMZ��* /������������	"�)	b%$�!�;����N�
IY�S�Hk�B���SO��
$q���Y�V��^rSZEz(1h5����V��W]�KZ}�����H���/��b�F�4!U�.'�Q)�0�R���U@%\��m������&](�F��4H�T�(bqR�XVs������y�>4�4Z���:�j(�����y�i�{� ���4b�i�M�X�6j'
�p
bUN,9)�&�E�KA�����$���X%���]o�B�g2Y>����4��x����h��p=��mT�T(�uj7��Q�c�����)��F������{,�;V��*����Qo<t6K��
��#T��2���~j�=��`�6J-�����`#X���n`?� X�����6���b"�x��KX2rt��X���P����� X�RJ�#a�9��
�,�5�$m�����k8�X�F9�J���b1�8y�%	J��~'Y���]"�9�����j	�6����J��7�P��W��P�o�X�0[O��NFO��O��F3l��}3�E(���/)�6�A?J����4��B#������t����u���w4�m����99q(,<��������
v���G�`��M�,`Y�j�F�KM����`5����������f)k��P&�B��Bl�n�A�
�_4��F���16���.Cy�o�I�{��Xs^�'6{[ w&���;���.@��8a�6b��w��e�8�����u��{t��qY�����4�c%?�NE�2,/�F
�������eKQ�H�j����k	@p�I�;�<��'�K��	����#_����s,A�1���5��%�H~t�UP���D�b%mJ��"���;��JP�&�A��3��5e{�g�CZ�N�}#5����a5�W��<o��0)s����ngXa�L����A�4)+����=A�>����V"��1N(�KvJLb�N�d�U[Hv��7�/p=W}��H�Av���J ��*%��(L�H���5�q*��)���|��f[�e�J"�}RJ�����SRj�XU����F�����b�+FL�l�*���j,�b�hJ�E���*�D��4_�����s�BS�3s6O#W@Sz���H�
���H[,E�_�h��f�Q�1�vIK�����
��b�'U��T����y�9N�����r��`���H�f��Wv��<+���H�A���~�U�NE�N��F=`��!��\n����i+�L���e���R.a�k�l���I3Hw�{WR�T�65�~=6�6�����k+!?�A�]+v4������j�t5o�	\A��}���M��Dc��:>�j4c('���XT5����'�HW�y���
`�t�h���Q{�g�����Z��IW�����n��<������h�j�IW�y�-���@A������.��
G��d��l�sl���m?��Y��3.�(��4��px~��He\���W��b������<���'e\�RV�z��{����}���e��x�|,��+lT��%xw�H�rQ��Bg\��&L�-K0�F����YP�f�a���f7?�����kM��d���������9)���s��<o���q��T����3.����:e\
����0���1�\>8���X
���9�J4�z#�]V�q�#/;�������+N��r��6&���'D���V�HW�(D5������a']��Ln|�t�^��2��i�%c�b�����;��]�b=M����
0����mx��'���J$���� ]B�D�j4_.���?HW��l�if�BS3�P����DS�!i��KQ�9Z�t%��[�g���vS�vA�}4s�_���0v*����z-C���tU���!�#���$7�A�
M}�6,g��`l��� ]�H�A3� ]i���lp��H�eF��������b�D��\@RWwy2 1���)��T1$�h�i���H������-=�]�b9�����������F(k���3�@���ob�q�`\���/���%���"�Y0���i���q5��EMV2����5����1.��{X����MU������M�4L��q�Mj�
c\3Zeh#:���Y&�/9�����Au��h���|�q��B��m���v�{"kJ��G�e�ns��F������L�2.!)v�
	�$����/b�qI����<+�h9M�B,/��8wsG���b����[�
y����h}����n�Je]_���Kh�������~�lN^$��LB_��5��h�$��.E���-cg]��y������G���Uh������u�h����u�����*C�Vg]�e�m����<y��f����v��\=5&[H7;����t1�X�?��^�"��`��>B�����������2;\F({9J�	����������Mj�.aY��l�]��5S�p�]�RsK������<
endstream
endobj

18 0 obj
49262
endobj

20 0 obj
<</Length 21 0 R/Filter/FlateDecode/Length1 16120>>
stream
x��{{|SU��Z���y�y����i�#}�P��$��*J�
M�FKr��R^
EG�A�U��*��c}�;�c�������(\����;;ii��w������t���^k���Z{�}b"�:*h|�+��o?|�u8���5	��~/���M������� �nn]������T���-�`�v����_����pp]r������L�����@��h�6}OT�����k�gR%�o�7�n�(��\�
�=�30m�D����{�;	0�����@Nz�h��drE�R��huzC��d�XGe��G��yG�3��?f�8���bO���v�`�����`��g��������V�S��y8�#H[�N8<��� �>��b��Cih7������f�;�t�5���~��$�s�/�-i����E�G����[��pn�}���W�cj�Q��7�F���#��.�e�1-`�!z�����m�~�n�;�/�M�
v���*�h/�|�?�:�.�@����<M�l+��o��ST��p4�}�?P;�k������i#��C�$��&����	o��[�$PW��f�|���7�P}����*+f��y��;������O�<�lBIqQa��1��<g��n5�uZ�Z����8��)�^��
�v�������*,�+�-�*��
"�����wVU�3(�
����0t���b����o�u�t�.�p����N�$.�_�����^���7��'�����QX��$k�
�rMKGE����Rf�r�
g@W�r�s������X�����VL��@������"���*f��@a�Q��MH0���Y����#�����*�����V4�U!g(xS�H�tEG����-�s��������",8gW�nIj��!=��U���tN��k�������`��t_���,�9��V��l���t��
���+������Ru�*x�u"O<��&V�u
-85��z��j1s��:�rU�-A�v����tL�9�C<��#�(�%r���
�O�`Ea�Cl�_�z�a��(����j�(=�S�Di�
op:
�k�:D�5'������A�}��o���5��9�=_^ ��H���"�����4j�����t�����?_�:D&_o���|y�$��Y���oM�Ul_��U�T ,�}��
�L�XEWIq��"� bCd6YL�����C�+�U��#C��D�,����
�W|EG���	�,���g�3��5����D������D:���.�$�l!�oh��l�1p��R�9u��>	����u�5���K���
I$q���
1�:[J���D�K��Q6: 2.����J�q9gN�(s�E�K'r)��3��uh�Anq\�8���N�I�#��R8����I�"6���9��UX@���O+Y�\rj� �v�"����kVAI��JA��9�����}�:in�{���� >O���O��UX ��z����L��m�\�:�<�Xuy� ���;�k:$���@)���M��H-��Yt�:�2��]>���-S%!�9�gM�t�]����m�.Tc����]��r���]>�Z����ua�Q
�Y
3]y�u~�3<��`)	+!�^z�$-�;J�	��@;�2A�O"�|��x�J�t)E�D�(h<��(�AnO�S�v�#WH.�e�>�O�SQj����(��?�
�c*T��������Ob{��gKq��})��^V]����
�h#�@ 0S�
*�-�ji[��CR��(�����
�"�)���"�����3�����9S�{%�7��$��9SD3��"5�/�K�N��g�a��})�T�]X����(8
�����}j�ci�V�Y����O�
X^���=J2zG���?��/���>�n�v=[v���Uj(x�������>^���80dj������4�2�5���gb�*�z�z�[��Cj$Ehd��S�(ed�q�w�����}�/P��D�'y2�7�����g�?`7�����%6l�k�Sd>m�*Z&��+X-cB�	 (�O�g��@Q�������
�F�T�.�#��U�+>t��
V�W�[�I���c������n�?|��>f���A@���
x����"��(.�V���C�>nVa�
�p�
yU���O����v�p�H�Cs���
'|@�)�K	�6����	^�����������!��2P~�P�BP�lY}}}��zr�v]�������������z�����3���DO����L~/���o�)�1�x�������5�K@�����hf.d��|z��\��u�����V�e�v+���`E�K�x�:��wK�Q�\J�s�����\�d4{J'1�����_�g����-?}d���N�$?M~��S%�s����z�?��}/y���yj<[F�����F�V�`�I��Y@�U��V��Z��P�v3��L�:�|Y����P4�Jf�8gn��Y���1yLN�d�dj|�����\v���{�y������m���M��s���EL7�dX��R%�r`Xfy���p��8M�y
�������)p��+�ZNr�D�Z6�Q��$�v*0E�&��
<B�/FH>�g�i��������K�����
,&�^"eQ����+P��T��0��
��%T�"�W��������aQL*����V��D��*����|v��|������x�,#0s�	%p�o?n�Lf�h�hZk�bJ'����6�����������V�PJZ������^y��{J��w�b{)�J����XB��2$���/_V�Jo(/NU[�����`67�l�$/�����18J��T��8gn������kP��LF3>������������,���~3~Z�c�u��WqbI�C�W�o�\n<���n���9�`����J���b�H�G�w/�iM��JB��R��,�&{
,��z��V�Q[A
y.VO�L6��SC��rH�/����].������������*���|��B�!���������Q����+�7��1%��������N����w�d���[�Q��o��3&d�L��kY�<����Wz?~��7�g�}h�o>
�2`:�b�gX�aQdq?��,�X���e��0R'��X����K�C�#�s�����&�HS��fO};q(���\0�(X����s�Q*�LO��8�Q��G��5J�����NA�
s�
{l�i�]6l�a��
6��������5��/_V��F����K~�l�R�4xx�iLJ����v��1��`���/�?|V���M{9���7�U�`�0��Ek�/~zd�T�>JF���@����X`�
 ��H��e��9��l�H��V����������L����2t�L��z=�aE���8�c6����H\����w�)��7=����8�����x�����������q��C�7]����mj��c��\�j���V���h����`_�`C���u�0&q�������.%�99=���&�cU6q���l����9h�����������]�������o����y���G���nK�,{p��s��{�����/��p����;��6��}wn7V�x}u�����k�Js�2p����
Y��7� �+q�rT����Y�lV������l��<�dc_6!;�1�}9�I����a��������g%�!gn~����)�qO7w)��g<����������x�J��������y���S�o�aFKzS����)J�b��89&`�T��z<�����O�C���<z��alN��7��e�r�����R^-J.��1��C�������c�z�N�gk-F���u�?�1��01�1�d��+A��.A�wJ��{Jp^	v�`{	�����`/���B#�OI�W������`�[�#bE�f:Rx}q#I�R��3q�dg������1{Jg ������
��PMy����so�Qr����M5w��Y��*�x{{V�|��TK�hC;�#����I�.���B������}z)���'8��Y��w�
Y:�&K�m�3�ZdFZc����I|��qv6N�F>��x��+�x�0$��!]62���)!wg�nB���y�v!�%�������$n'CR��l��i6�5LVJ�rP�s���]��Oe�g##�}��%�C�P�������4�Wo-�\
�K��O�������*8��A���=�H1aLr�]��S4s�"�5�8�G������:���{�E�����p�x��9c3���v}�g��������7a4h4Z�����@I��<i����yW�����y���=y�R#b�;rCv���!���t�cYj�H5%t������RT7w��������vt<�u�S-K��Vj�������'��1��+�����o�j?�7f.dA�7��Pd@VF�-�`R�tjm���E��#��C��#�S�Cr(�D�&=]���E=EjV���r��/���K��b@����a�����*FD(�_�z	�^=��x{;;Ss���\�w���
o�+x�{|����Y�`21R?��:`
����^7��hw���_����s�/������1��i��t��_��-B>B��������hs�E7�#��v�1��M7^p������7N$$��/�sn�$#Dt��iJ� ���+E���n�z��]nl�,�)����nw�r��w�?�%�U_P�������/��BH��|0��C�����(&�u,S����3������.���D=��[���",Yq����o�K�#�������g�7��0
�|�6fr2Y�����,�������x���:���v����X�t\y��z9�������0�m�s���)���p����������a������'�������g4���v*��{[ZU?�v�D=�?�Yr����r13��,�'��V���r(�]z�D���Vn�rI����|����|���@>��cO����_��c����1
k�5x���v�tsO!�2%�lx���o�r�:���w�.��R�h2�r?��Lh��'/$?���%/�}��W�z�+��X��7����2�lTV&m��h�?@�z��'�,<O�Y���C��,�e]QrH3h(��l�.G�P�������������P�~ow��
77��9��D���������l�H�2�������[h��������s�l*�<�6�`u�K���<����<�p�!�gH�����y����y����y�K���.?�/�C�B�Gq�';5�9�=
?�M�{{�$J�<)�f�I�����m���ko��h�&-���N;{q�8p�Rj�;�N����?J1�2p���!s������JiPr�3O�e�Z0i�B#���**�U)d4/�Q�����3� `��2�����g��%�,�l�[������%��Bo���c�pTx��{��s����q7�>�L�
\�m�5���p������/���g�ox������9��F_���e�rU�.]6�������D@o��x����7j��c�z�f�[��]F+��L��g����~�s�mW{�0;������-Z6&�FNf�Af�?������<�n��������i����������zD�-/�����o��,lxxC|�����'_zU��`�?J�����=�3||6h�r�h�;/��J!`�!dC�`�>��&1�Vy�f�WX�A�eS���G�����Nx@}���K�}V���������������.J���J��7�Y�����=X�z���~}!����
 �e�J��3*ZO�2#�r9*�&Z�I�����2�36�q�+�8��yf4��1�3��������q����M8�f����?6��f|���	�f3&�p�����D�n".b�E��83~j�����f����1nFl :��QS.U��DO�K�h����)�����f��h3�y��-3v��	�kFJgF0�R��{�F���_m;�No|Ewl�����^���,����g�Ov�c4H���'gz2������)���M���	Y����/�������K����S��K�G�j;�Eb����S���f�3(�2�a�*������r�����S�z5[���,�jP��;�=�^5{F��N=3���K��4�O}^��Q(�`�ZS���k)�e�v�^V�*�j6J�����e���G�tI�������w�s�7�������KAJ�,�(��e��P����NXG)�B@!�M�����
��� �)50�����D���'v<��������z1�?y��o���?N��	hH~�|+�n�s�6����L3~���k������E�����Z`��������b���8����gE�)+^���V��_�b�Xq8��a�f������{~p�p~��i��V�<��`�g�o��Vd�x��}V|���X�G�����%i�!�!�!�!��y(��,�b��'����#��o)E�_%�F&�m���&��Ho��~x����;���)�"z2s()�PC�p}i~�+����OY�
t���J6�J�H.V��}�f��i��I�*�u��'��~���L�t0���g
%G3���! ��Q�qh��1{��/
0I���q�	5(C-:�U��[�-����EMT'������|����/�p/��[���z#��a�,c`���u��(� ��*�@��U�Ch�v-���Z�d�	�o-2Lm��W���� ��zJ
���&�{�aM�d�o�~�����N�;��})��O���_�����{�����F�����������r�Jd~�a���Cow=����R����n%�����B*5(2�@�Xa��TvJ'�`er��(s0�?��g��W��1������/����-{�9�>,��a�-H}�Mm��s/�A�;��=`d�2_�!�j1!S�Y3U�L����YY��hI����f�e(�6�������x��izC����x��qf:LZ:HeF'��������g�;��=s�������m�S���[g��c�����@�d�{��.�4�2Y�yP��"7gWge�2�
5��L0+r���]��b&��K�t��:]�zx�~�~�N�l���eE�:�M�^�D�`��n�u��IL�?����#�[������+q��?%�]�e���8���!w�.�������F�����^����-��J}���������i��;����g45�}L�����D)����9C�d��drZ4�-��y����������������`9c9g�M[ny�B�h��Rl9B����(Te��)��-%���`�*��~U|���'ufK��4���R���{����G�������d�]��3��O\�C��t����m�����H���1SA�+|�(N�HsrF����0Z�I'�`zW��(�[���[����PbH���S�D%�J4*�xA�}J|W�=��?���)�Q���b;	[�����s������"LQ9D�2�����D��%m��S�����G����!W���)�G�"I�.�
:L5T}�����QJ�F�o�v���S5��w.�������{�w�������oR>J.���)�#d*�D���\�5��U�����9���"x
�#�"��T9�	1,f�����<�u�2��[��p��	�/#�V�,�R<d,#��iZ#�\F�f����~F�.(@1#@#@�*��0�r����-po���*�:NW����2f
���&�Nn�� K�~#�\�gE���.�=�c�_���5�gj�i:��v�v���.G�U�O{d<LR�/:(�����`����A��02hJ�4d��4���N�,�aO�@��a�]iXFt�ah���30�7�a%dS��~�_D�.
����MYt�������a��?
S�ali�����4�@S��Y�bnO�d3�a\`�������ad���p�;��iX	S���a�$�{V���A�40Q���Hs$�-�C�D�o����#�-	~l�8��dB	]4���gE��h<��D����YW����!�*�(���5�YN1�5�6aA�yuk0~��n��|!����qA�K�&�]�]�� ��C����-|�i�
|<��x8�G�����"�L��|�-�/8��)�&��p<����DK8���:B�FI�P4d�0W�$�k����D",D�f�p������#+����Hc�6(���in�����c�����H[[tM0Y.����xXh��5�B�M��p<���'Z�	i�+��x�1����o�����a~m$�"i�*JY�G���q������k�y�Bc<n���`(�"�I��[��`c"��H�@��h	��`[a��x4������2#/�S���k��n�C�����pk4&)n�Fo�����k#�DK�0{��m	�OD�`(�6�^)-Q,Ol�G���M��J��%��M-.^�vmQ0�*��x��1����h�u�pz)�����7D�m���&K+M�f�
��X�����%�4C?��&�U��H,!	���h��x^�
0"�H@n�0���!A����u'\-�^:<�q�C)��(��(D�Z!<��(�!F�A"7
mP<d��+���"���9��P7@V@x�dj m �q��Z!q�h�0�A������F�S�0�/�"�EPv�q?,3���	B�l\I��x�B����8��$%Ad�8#Dv-A
�����D[�Zx���	� B<v�����b!%9
	hI{�fXM�Q�787�����GE
�n
�y#�K���� �y�|v-����k���m!p��3DFK�������~=|zl0�.m�QX��RS��w�Do4Bz�yb�d]�V��cA������0Ys�� �B+�P���Kk]����$3[���VG.Y���HEKS:6y��A�����
��H���U$��"�J���h!1$+N�p�X+��T��bIz�)��iO.�����JLykxDJ+�J���n#��.:�Y��5�)5�VRnZ�&e)�������o�M"�5J,
A(�����B#�&����T'��� �o4=.F�P"m�J�-$�b0����E$���Jc:S��6���Iv���gE|����J�SJ�`�����+Qs�Z�#����L{��B��+W��	�N��E*##�/"��PD���0*�H��0�<����gw�R��P�3�g��`�k�v��4��T��)����C��br��������~�~��w������������o?_��/?���=7���s;�9�*?�4�����v������l�����v���s}���3����j����/�/�g�����j������g���^s��������z��}��En�7����_��{��_��������g�2v��$}r��7p�PZi?�=1�D����O9!�������QZ{w=����}��c�c�����.���W���x�P�O�OR=O�>I����{����y�*>=�����������}��/��=��������������{`7[r��>��>��l�I���=;{wR��Y~O������-�y�{B���=�6��VYf�Bk�(��V��k9z�����/���o��`_�����r�=��P�"]�����4����
t+�#�=7��O���M���w��|��s*y{Ue����2��J<Sy��j�Ds��V��Z]���B�E@�]��.���2Zm�v�6���=�������sZ:
8��7,��]]k����������T����F���/��"�.YZ��xo`��0st�XZS'6�T���:�'�5u�nt�f���X��.L�p�A�Pzr�hB���_Hnt'V��(		!!�2AH�[�
nt��N���p��	np/)��L!�������r
endstream
endobj

21 0 obj
10034
endobj

22 0 obj
<</Type/FontDescriptor/FontName/BAAAAA+LiberationSans
/Flags 4
/FontBBox[-543 -303 1301 980]/ItalicAngle 0
/Ascent 905
/Descent -211
/CapHeight 979
/StemV 80
/FontFile2 20 0 R
>>
endobj

23 0 obj
<</Length 409/Filter/FlateDecode>>
stream
x�]��n�0��y��CE~Zh%��B+q�����i�����d;��@_��|1N�����7?u
y\��6�}���	md?t!�����,�����-�X����"y��p�!�v�t��H^}~pW�t*��H��<�.H%�B�pI���/�	e-�\�cy*�������Z�J7�p��|�� r�
��������)�K��z�+]�\��*D�q�E��Y����#���W�)���������5��� ��K�=���\�_q}�?0[�#3�kEl��f�4Cf�U���)���@fC1����gi���^:�o��?�s��b4�[�e��:�����B�&�c}������Eg������b��.��-����EO��n���
C��88�?�&����
7�N���w��i�,z�<|�
endstream
endobj

24 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/BAAAAA+LiberationSans
/FirstChar 0
/LastChar 41
/Widths[0 666 222 500 556 277 277 610 556 556 222 556 556 333 500 556
556 556 833 556 556 333 833 500 556 556 556 556 556 556 722 500
556 500 556 556 556 277 556 556 277 500 ]
/FontDescriptor 22 0 R
/ToUnicode 23 0 R
>>
endobj

25 0 obj
<</F1 24 0 R
>>
endobj

26 0 obj
<<
/Font 25 0 R
/ProcSet[/PDF/Text]
>>
endobj

1 0 obj
<</Type/Page/Parent 19 0 R/Resources 26 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 2 0 R>>
endobj

4 0 obj
<</Type/Page/Parent 19 0 R/Resources 26 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 5 0 R>>
endobj

7 0 obj
<</Type/Page/Parent 19 0 R/Resources 26 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 8 0 R>>
endobj

10 0 obj
<</Type/Page/Parent 19 0 R/Resources 26 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 11 0 R>>
endobj

13 0 obj
<</Type/Page/Parent 19 0 R/Resources 26 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 14 0 R>>
endobj

16 0 obj
<</Type/Page/Parent 19 0 R/Resources 26 0 R/MediaBox[0 0 595 842]/Rotate 0
/Contents 17 0 R>>
endobj

19 0 obj
<</Type/Pages
/Resources 26 0 R
/Kids[ 1 0 R 4 0 R 7 0 R 10 0 R 13 0 R 16 0 R ]
/Count 6>>
endobj

27 0 obj
<</Type/Catalog/Pages 19 0 R
/OpenAction[4 0 R /XYZ null null 0]
/ViewerPreferences<</DisplayDocTitle true
>>
/Lang(en-US)
>>
endobj

28 0 obj
<</Title<FEFF0072006500730075006C00740073002E006F00640073>
/Creator<FEFF004C0069006200720065004F00660066006900630065002000320034002E0038002E0034002E0032>
/Producer<FEFF004C0069006200720065004F00660066006900630065002000320034002E0038002E0034002E0032>
/CreationDate(D:20250216131702+01'00')>>
endobj

xref
0 29
0000000000 65535 f 
0000342089 00000 n 
0000000019 00000 n 
0000055831 00000 n 
0000342198 00000 n 
0000055853 00000 n 
0000110769 00000 n 
0000342307 00000 n 
0000110791 00000 n 
0000167178 00000 n 
0000342416 00000 n 
0000167200 00000 n 
0000224160 00000 n 
0000342527 00000 n 
0000224183 00000 n 
0000281476 00000 n 
0000342638 00000 n 
0000281499 00000 n 
0000330834 00000 n 
0000342749 00000 n 
0000330857 00000 n 
0000340978 00000 n 
0000341001 00000 n 
0000341197 00000 n 
0000341676 00000 n 
0000342000 00000 n 
0000342033 00000 n 
0000342857 00000 n 
0000343000 00000 n 
trailer
<</Size 29/Root 27 0 R
/Info 28 0 R
/ID [ <5775671549F38DF0CEBF1A40BDE81501>
<5775671549F38DF0CEBF1A40BDE81501> ]
/DocChecksum /A9F7A204A0FF457880DFF91457147FE8
>>
startxref
343308
%%EOF
#205Jakub Wartak
jakub.wartak@enterprisedb.com
In reply to: Andres Freund (#201)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Feb 14, 2025 at 7:16 PM Andres Freund <andres@anarazel.de> wrote:

Hi,

On 2025-02-14 18:36:37 +0100, Tomas Vondra wrote:

All of this is true, ofc, but maybe it's better to have a tool providing
at least some advice

I agree, a tool like that would be useful!

One difficulty is that the relevant parameter space is really large, making it
hard to keep the runtime in a reasonable range...

It doesn't need to be perfect for sure. I was to abandon this proposal
(argument for dynamic/burstable IO is hard to argue with), but saw
some data that made me write this. I have a strong feeling that the
whole effort of the community might go unnoticed if real-world
configuration e_io_c stays at what it is today. Distribution of e_io_c
values on real world installations is more like below:
1 66%
200 17%
300 3%
16 2%
8 1%

200 seems to be EDB thingy. As per [1]https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/server-parameters-table-resource-usage-asynchronous-behavior?pivots=postgresql-17 even Flex has 1 by default.
I've asked R1 model and it literally told me to set this:
Example for SSDs: effective_io_concurrency = 200
Example for HDDs: effective_io_concurrency = 2

Funny, so the current default (1) is saying to me like: use half of
the platters in HDD in 2026+ (that's when people will start to
pg_upgrade) potentially on PCIe Gen 6.0 NVMEs by then :^)

I'd definitely not want initdb to do this automatically, though. Getting
good numbers is fairly expensive (in time and I/O), can be flaky, etc.

Yea.

Why not? We are not talking about perfect results. If we would
constraint it to just few seconds and cap it (to still get something
conservative but still allow getting higher e_io_c where it might
matter), this would allow read streaming (and it's consumers such as
this $thread) and AIO to at least give some chance to shine , wouldn't
it ? I do understand the value should be conservative, but without at
least values of 4..8 hardly anyone will notice the benefits (?)

Wouldn't be MIN(best_estimated_eioc/VCPUs < 1 ? 1 :
best_estimated_eioc/VCPUs, 8) saner?
After all it could be anything in the OS, that could tell hint us too
(like /sys with nr_requests or queue_depth)

I cannot stop thinking how wasteful that e_io_c=1 seems to be with all
those IO stalls, context_switches, and You have mentioned even that
CPU power-saving idling impact too.

But maybe having a tool that gives you a bunch of numbers, as input for
manual tuning, would be good enough?

I think it'd be useful. I'd perhaps make it an SQL callable tool though, so
it can be run in cloud environments.

Right, you could even make it SQL callable and still run it when
initdb runs. It could take a max_runtime parameter too to limit its
max duration (longer the measurement the more accurate the result).

As you say, it's not just about the hardware (and how that changes over
time because of "burst" credits etc.), but also about the workload.
Would it be possible to track something, and adjust this dynamically
over time? And then adjust the prefetch distance in some adaptive way?

Yes, I do think so! It's not trivial, but I think we eventually do want it.

Melanie has worked on this a fair bit, fwiw.

My current thinking is that we'd want something very roughly like TCP
BBR. Basically, it predicts the currently available bandwidth not just via
lost packets - the traditional approach - but also by building a continually
updated model of "bytes in flight" and latency and uses that to predict what
the achievable bandwidth is.[..]

Sadly that doesn't sound like PG18, right? (or I missed some thread,
I've tried to watch Melanie's presentation though )

-J.

[1]: https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/server-parameters-table-resource-usage-asynchronous-behavior?pivots=postgresql-17

#206Melanie Plageman
melanieplageman@gmail.com
In reply to: Thomas Munro (#193)
4 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 13, 2025 at 5:51 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Fri, Feb 14, 2025 at 5:52 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Feb 13, 2025 at 11:28 AM Tomas Vondra <tomas@vondra.me> wrote:

On 2/13/25 17:01, Melanie Plageman wrote:
I know it's not changing how much memory we allocate (compared to
master). I haven't thought about the GinScanEntry - yes, flexible array
member would make this a bit more complex.

Oh, I see. I didn't understand Thomas' proposal. I don't know how hard
it would be to make tidbitmap allocate the offsets on-demand. I'd need
to investigate more. But probably not worth it for this patch.

No, what I meant was: It would be nice to try to hold only one
uncompressed result set in memory at a time, like we achieved in the
vacuum patches. The consumer expands them from a tiny object when the
associated buffer pops out the other end. That should be possible
here too, right, because the bitmap is immutable and long lived, so
you should be able to stream (essentially) pointers into its internal
guts. The current patch streams the uncompressed data itself, and
thus has to reserve space for the maximum possible amount of it, and
also forces you to think about fixed sizes.

Attached v30 makes the tuple offset extraction happen later as you
suggested. It turns out that none of the users need to worry much
about allocating and freeing -- I was able to have all users make an
offsets array on the stack. Personally I don't think we should worry
about making a smaller array when fewer offsets are needed.

Even without the read stream API, in bitmap heap scan, delaying
extraction of the offsets lets us skip doing so for the prefetch
iterator -- so that's kind of cool. Anyway, we are going to get rid of
the prefetch iterator, so I won't belabor the point.

I was worried the patch would be too big of a change to the tidbitmap
API for this late in the cycle, but it turned out to be a small patch.
I'd be interested in what folks think.

- Melanie

Attachments:

v30-0004-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v30-0004-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 949e896505ae951693ccc808339d0d6b30dcc8b5 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:35:17 -0500
Subject: [PATCH v30 4/4] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator into table-AM specific code (as part
of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer returns the current block number.
Since scan_bitmap_next_block() isn't returning any relevant information
to bitmap table scan code, it makes more sense to get rid of it.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple(),
and the heap AM implementation of scan_bitmap_next_block() is a local
helper in heapam_handler.c.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam_handler.c  | 373 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   2 -
 src/backend/executor/nodeBitmapHeapscan.c |  71 ++--
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 245 insertions(+), 293 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 7a3a9365be3..0a5f48ac5d3 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,11 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,198 +2121,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-	OffsetNumber offsets[MaxHeapTuplesPerPage] = {0};
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BlockNumberIsValid(tbmres->blockno));
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	/*
-	 * If page is exact, extract the tuple offsets from the bitmap into an
-	 * offsets array.
-	 */
-	if (tbmres->ntuples > -1)
-		tbm_extract_page_tuple(tbmres, offsets);
-
-	*recheck = tbmres->recheck;
-
-	hscan->rs_cblock = tbmres->blockno;
-	hscan->rs_ntuples = tbmres->ntuples;
-
-	block = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (tbmres->ntuples >= 0)
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			OffsetNumber offnum = offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
-		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
-		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
 
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
-
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2614,6 +2465,177 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+	OffsetNumber offsets[MaxHeapTuplesPerPage] = {0};
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	/*
+	 * If page is exact, extract the tuple offsets from the bitmap into an
+	 * offsets array.
+	 */
+	if (tbmres->ntuples > -1)
+		tbm_extract_page_tuple(tbmres, offsets);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2673,7 +2695,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..56378007a81 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 46721e091ab..68499e3aa45 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -139,67 +139,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-			CHECK_FOR_INTERRUPTS();
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
-new_page:
 
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b5675b47dcc..4206a6d0ab1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. This is tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1943,51 +1923,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1998,7 +1951,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

v30-0002-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v30-0002-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From 91bc0fa7d44d045b5edf02561124c1d6d795aec8 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 19 Feb 2025 15:00:30 -0500
Subject: [PATCH v30 2/4] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This allows tidbitmap API users to manage multiple TBMIterateResults per
scan, instead of only one per iterator. This is required for
asynchronous I/O to use the TIDBitmap -- as there may be multiple I/Os
in flight at once.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/gin/ginget.c           | 38 +++++------
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 ++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 39 ++++++-----
 src/backend/nodes/tidbitmap.c             | 82 +++++++++++------------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 105 insertions(+), 101 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 438fa936f11..ed682947e93 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,7 +332,7 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -824,19 +824,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult.blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
+				tbm_private_iterate(entry->matchIterator, &entry->matchResult);
 
-				if (entry->matchResult == NULL)
+				if (!BlockNumberIsValid(entry->matchResult.blockno))
 				{
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
@@ -846,13 +846,13 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				}
 
 				/* If page is not lossy, extract tuple offsets */
-				if (entry->matchResult->ntuples > -1)
-					tbm_extract_page_tuple(entry->matchResult,
+				if (entry->matchResult.ntuples > -1)
+					tbm_extract_page_tuple(&entry->matchResult,
 										   entry->offsets);
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -865,10 +865,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -882,16 +882,16 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->offsets[entry->matchResult.ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
@@ -901,7 +901,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
+						   entry->matchResult.blockno,
 						   entry->offsets[entry->offset]);
 			entry->offset++;
 
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index ceca72d7123..c6d7e243fae 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	memset(scanEntry->offsets, 0,
 		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
 	scanEntry->list = NULL;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 45918bf1eb6..f7817588896 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 	OffsetNumber offsets[MaxHeapTuplesPerPage] = {0};
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
@@ -2141,13 +2141,13 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
+		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
 
-		if (tbmres == NULL)
+		if (!BlockNumberIsValid(tbmres.blockno))
 			return false;
 
-		if (tbmres->ntuples > -1)
-			tbm_extract_page_tuple(tbmres, offsets);
+		if (tbmres.ntuples > -1)
+			tbm_extract_page_tuple(&tbmres, offsets);
 
 		/*
 		 * Ignore any claimed entries past what we think is the end of the
@@ -2158,11 +2158,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2170,19 +2170,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2211,7 +2211,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2220,7 +2220,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
 			OffsetNumber offnum = offsets[curslot];
 			ItemPointerData tid;
@@ -2272,7 +2272,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..94bffa6ca53 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,18 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				if (!BlockNumberIsValid(tbmpre.blockno))
 				{
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 052afd3e4c3..fdde8b87c2a 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -181,7 +181,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +221,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -957,20 +955,21 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.  tbmres->blockno is
+ * set to InvalidBlockNumber when there are no more pages to scan. If
+ * tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember the
+ * exact tuples to look at on this page --- the caller must examine all tuples
+ * on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but the
+ * condition must be rechecked anyway.  (For ease of testing, recheck is always
+ * set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+void
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -1008,11 +1007,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return;
 		}
 	}
 
@@ -1026,17 +1025,17 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		output->internal_page = page;
+		tbmres->internal_page = page;
 		/* ntuples will be calculated later */
-		output->ntuples = 0;
-		output->blockno = page->blockno;
-		output->recheck = page->recheck;
+		tbmres->ntuples = 0;
+		tbmres->blockno = page->blockno;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1046,10 +1045,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+void
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1100,13 +1098,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return;
 		}
 	}
 
@@ -1114,22 +1112,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
 
-		output->internal_page = page;
+		tbmres->internal_page = page;
 		/* ntuples will be calculated later */
-		output->ntuples = 0;
-		output->blockno = page->blockno;
-		output->recheck = page->recheck;
+		tbmres->ntuples = 0;
+		tbmres->blockno = page->blockno;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
 }
 
 /*
@@ -1603,15 +1601,17 @@ tbm_end_iterate(TBMIterator *iterator)
 }
 
 /*
- * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ * Populate the next TBMIterateResult using the shared or private bitmap
+ * iterator.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+void
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index f889e4f7d16..1589ed333ef 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -354,7 +354,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 	OffsetNumber offsets[MaxHeapTuplesPerPage];
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 1a381595abe..f5b99f837d8 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -80,8 +80,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern void tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -92,7 +92,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern void tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v30-0001-Delay-extraction-of-TIDBitmap-per-page-offsets.patchtext/x-patch; charset=US-ASCII; name=v30-0001-Delay-extraction-of-TIDBitmap-per-page-offsets.patchDownload
From 92eacd13d60c67eee9812171256026191d2356f6 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 19 Feb 2025 11:32:22 -0500
Subject: [PATCH v30 1/4] Delay extraction of TIDBitmap per page offsets

Each time the TIDBitmap iterator was advanced to an exact page (in
tbm_private|shared_iterate()), it extracted the tuple offsets into an
array in the TBMIterateResult for convenience.

As long as the TBMIterateResult contains a reference to the
PagetableEntry, this can be done later by the caller when using the
array of offsets. Doing so allows us to wait on allocating the memory
for the offsets until later, which helps reduce the memory footprint of
having multiple TBMIterateResults allocated at the same time. Future
commits will make bitmap heap scan use the read stream API. This
requires a TBMIterateResult per issued block.

The benefit in current code is that we no longer extract offsets for
prefetched blocks. Those were never used, so the overhead of extracting
and storing them was unnecessary.

Suggested-by: Thomas Munro
Discussion: https://postgr.es/m/CA%2BhUKGLHbKP3jwJ6_%2BhnGi37Pw3BD5j2amjV3oSk7j-KyCnY7Q%40mail.gmail.com
---
 src/backend/access/gin/ginget.c          | 11 +++++--
 src/backend/access/gin/ginscan.c         |  2 ++
 src/backend/access/heap/heapam_handler.c |  6 +++-
 src/backend/nodes/tidbitmap.c            | 37 ++++++++++--------------
 src/include/access/gin_private.h         |  2 ++
 src/include/nodes/tidbitmap.h            |  4 ++-
 6 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 63dd1f3679f..438fa936f11 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -845,6 +845,11 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 					break;
 				}
 
+				/* If page is not lossy, extract tuple offsets */
+				if (entry->matchResult->ntuples > -1)
+					tbm_extract_page_tuple(entry->matchResult,
+										   entry->offsets);
+
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
 				 * entry->offset is still greater than matchResult->ntuples if
@@ -884,20 +889,20 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
 				{
 					entry->offset = entry->matchResult->ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
 						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..ceca72d7123 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -107,6 +107,8 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
 	scanEntry->matchResult = NULL;
+	memset(scanEntry->offsets, 0,
+		   sizeof(OffsetNumber) * MaxHeapTuplesPerPage);
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c0bec014154..45918bf1eb6 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2127,6 +2127,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
+	OffsetNumber offsets[MaxHeapTuplesPerPage] = {0};
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
 
@@ -2145,6 +2146,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (tbmres == NULL)
 			return false;
 
+		if (tbmres->ntuples > -1)
+			tbm_extract_page_tuple(tbmres, offsets);
+
 		/*
 		 * Ignore any claimed entries past what we think is the end of the
 		 * relation. It may have been extended after the start of our scan (we
@@ -2218,7 +2222,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 66b3c387d53..052afd3e4c3 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -181,7 +181,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +222,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -696,9 +696,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -905,12 +903,12 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm)
 
 /*
  * tbm_extract_page_tuple - extract the tuple offsets from a page
- *
- * The extracted offsets are stored into TBMIterateResult.
  */
-static inline int
-tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
+void
+tbm_extract_page_tuple(TBMIterateResult *iteritem,
+					   OffsetNumber *offsets)
 {
+	PagetableEntry *page = iteritem->internal_page;
 	int			wordnum;
 	int			ntuples = 0;
 
@@ -925,14 +923,14 @@ tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
 			while (w != 0)
 			{
 				if (w & 1)
-					output->offsets[ntuples++] = (OffsetNumber) off;
+					offsets[ntuples++] = (OffsetNumber) off;
 				off++;
 				w >>= 1;
 			}
 		}
 	}
 
-	return ntuples;
+	iteritem->ntuples = ntuples;
 }
 
 /*
@@ -1021,7 +1019,6 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 	if (iterator->spageptr < tbm->npages)
 	{
 		PagetableEntry *page;
-		int			ntuples;
 
 		/* In TBM_ONE_PAGE state, we don't allocate an spages[] array */
 		if (tbm->status == TBM_ONE_PAGE)
@@ -1029,10 +1026,10 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
+		output->internal_page = page;
+		/* ntuples will be calculated later */
+		output->ntuples = 0;
 		output->blockno = page->blockno;
-		output->ntuples = ntuples;
 		output->recheck = page->recheck;
 		iterator->spageptr++;
 		return output;
@@ -1116,12 +1113,11 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	if (istate->spageptr < istate->npages)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
-		int			ntuples;
 
-		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
+		output->internal_page = page;
+		/* ntuples will be calculated later */
+		output->ntuples = 0;
 		output->blockno = page->blockno;
-		output->ntuples = ntuples;
 		output->recheck = page->recheck;
 		istate->spageptr++;
 
@@ -1468,8 +1464,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..f889e4f7d16 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -13,6 +13,7 @@
 #include "access/amapi.h"
 #include "access/gin.h"
 #include "access/ginblock.h"
+#include "access/htup_details.h"
 #include "access/itup.h"
 #include "common/int.h"
 #include "catalog/pg_am_d.h"
@@ -354,6 +355,7 @@ typedef struct GinScanEntryData
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
+	OffsetNumber offsets[MaxHeapTuplesPerPage];
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index a6ffeac90be..1a381595abe 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -56,12 +56,14 @@ typedef struct TBMIterateResult
 	BlockNumber blockno;		/* page number containing tuples */
 	int			ntuples;		/* -1 indicates lossy result */
 	bool		recheck;		/* should the tuples be rechecked? */
+	void	   *internal_page;	/* pointer to the PagetableEntry */
 	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
 
+extern void tbm_extract_page_tuple(TBMIterateResult *iteritem,
+								   OffsetNumber *offsets);
 extern TIDBitmap *tbm_create(Size maxbytes, dsa_area *dsa);
 extern void tbm_free(TIDBitmap *tbm);
 extern void tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp);
-- 
2.34.1

v30-0003-BitmapHeapScan-uses-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v30-0003-BitmapHeapScan-uses-read-stream-API.patchDownload
From bc495f63d39fc271437a4d9e182061777dae9e1d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 22 Jan 2025 15:00:12 -0500
Subject: [PATCH v30 3/4] BitmapHeapScan uses read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam.c          |  77 +++++
 src/backend/access/heap/heapam_handler.c  |  93 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 354 +---------------------
 src/include/access/relscan.h              |   8 +-
 src/include/access/tableam.h              |  33 +-
 src/include/nodes/execnodes.h             |  23 +-
 6 files changed, 143 insertions(+), 445 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index fa7935a0ed3..60c5ac7a1c4 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,69 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		tbm_iterate(&sscan->st.bitmap.rs_iterator, tbmres);
+
+		/* no more entries in the bitmap */
+		if (!BlockNumberIsValid(tbmres->blockno))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			OffsetNumber offsets[MaxHeapTuplesPerPage] = {0};
+
+			/*
+			 * We throw away the offsets, but this is the easiest way to get a
+			 * count of tuples.
+			 */
+			tbm_extract_page_tuple(tbmres, offsets);
+			bscan->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1130,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1210,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1254,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f7817588896..7a3a9365be3 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2117,80 +2117,75 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 	OffsetNumber offsets[MaxHeapTuplesPerPage] = {0};
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
-
-		tbm_iterate(&scan->st.rs_tbmiterator, &tbmres);
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (!BlockNumberIsValid(tbmres.blockno))
-			return false;
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		if (tbmres.ntuples > -1)
-			tbm_extract_page_tuple(&tbmres, offsets);
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
 	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
+	 * If page is exact, extract the tuple offsets from the bitmap into an
+	 * offsets array.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
+	if (tbmres->ntuples > -1)
+		tbm_extract_page_tuple(tbmres, offsets);
 
-		bscan->rs_empty_tuples_pending += tbmres.ntuples;
+	*recheck = tbmres->recheck;
 
-		return true;
-	}
-
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2211,7 +2206,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2220,7 +2215,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
 			OffsetNumber offnum = offsets[curslot];
 			ItemPointerData tid;
@@ -2272,7 +2267,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 94bffa6ca53..46721e091ab 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -149,16 +120,16 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		node->ss.ss_currentScanDesc =
 			table_beginscan_bm(node->ss.ss_currentRelation,
 							   node->ss.ps.state->es_snapshot,
+							   pstate,
 							   0,
 							   NULL,
 							   need_tuples);
 	}
 
-	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bitmap.rs_iterator = tbmiterator;
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +143,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -201,40 +168,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Continuing in previously obtained page.
 			 */
-
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -254,34 +189,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/* OK to return this tuple */
 			return slot;
 		}
-
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,225 +223,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				if (!BlockNumberIsValid(tbmpre.blockno))
-				{
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -573,31 +272,19 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scan->st.rs_tbmiterator))
-			tbm_end_iterate(&scan->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scan->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scan->st.bitmap.rs_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -657,8 +344,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
-			tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scanDesc->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scanDesc->st.bitmap.rs_iterator);
 
 		/*
 		 * close table scan
@@ -666,17 +353,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -709,18 +390,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -760,13 +436,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -870,12 +539,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -912,17 +578,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index dc6e0184284..934b667ad78 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,12 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator rs_tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *rs_pstate;
+			TBMIterator rs_iterator;
+		}			bitmap;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..b5675b47dcc 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -956,15 +940,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
+				   struct ParallelBitmapHeapState *pstate,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-									   NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys,
+										 key, NULL, flags);
+	result->st.bitmap.rs_pstate = pstate;
+	return result;
 }
 
 /*
@@ -1966,16 +1954,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1972,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 2625d7e8222..054af76447c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1825,11 +1825,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1837,10 +1833,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1864,18 +1857,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1883,18 +1869,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

#207Thomas Munro
thomas.munro@gmail.com
In reply to: Andres Freund (#192)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Feb 14, 2025 at 9:32 AM Andres Freund <andres@anarazel.de> wrote:

I think we'll need to add some logic in read stream that only disables advice
after a longer sequential sequence. Writing logic for that shouldn't be too
hard, I think? Determining the concrete cutoffs is probably harder, although I
think even fairly simplistic logic will be "good enough".

(Sorry for taking time to respond, I had to try some bogus things
first before I hit on a principled answer.)

Yeah, it is far too stupid. I think I have figured out the ideal
cutoff: just keep issuing advice for a given sequential run of blocks
until the pread() end of the stream catches up with the *start* of it,
if ever (ie until the kernel sees the actual sequential reads). That
turned out to require only a small tweak and one new variable. It
avoids those stalls on reads of sequential clusters >
io_combine_limit, with no change in behaviour for pure sequential
streams and random streams containing sequential clusters <=
io_combine_limit that I'd previously been fixating on. I've added a
patch for that to the v2 of my read stream improvements series[1]/messages/by-id/CA+hUKGK_=4CVmMHvsHjOVrK6t4F=LBpFzsrr3R+aJYN8kcTfWg@mail.gmail.com for
experimentation... will post shortly.

I also see a couple of other reasons why streaming BHS can be less
aggressive with I/O than master: the silly arbitrary buffer queue cap,
there's already a patch in the series for that but I have a slightly
better one now and plan to commit it today, and silly heuristics for
look-ahead distance reduction also related to sequential detection,
which I'll explain with a patch on the other thread. All of these are
cases where I was basically a bit too chicken to open the throttle all
the way in early versions. Will post those at [1]/messages/by-id/CA+hUKGK_=4CVmMHvsHjOVrK6t4F=LBpFzsrr3R+aJYN8kcTfWg@mail.gmail.com too after lunch...
more soon...

[1]: /messages/by-id/CA+hUKGK_=4CVmMHvsHjOVrK6t4F=LBpFzsrr3R+aJYN8kcTfWg@mail.gmail.com

#208Melanie Plageman
melanieplageman@gmail.com
In reply to: Thomas Munro (#207)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Feb 19, 2025 at 6:03 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Fri, Feb 14, 2025 at 9:32 AM Andres Freund <andres@anarazel.de> wrote:

I think we'll need to add some logic in read stream that only disables advice
after a longer sequential sequence. Writing logic for that shouldn't be too
hard, I think? Determining the concrete cutoffs is probably harder, although I
think even fairly simplistic logic will be "good enough".

(Sorry for taking time to respond, I had to try some bogus things
first before I hit on a principled answer.)

Yeah, it is far too stupid. I think I have figured out the ideal
cutoff: just keep issuing advice for a given sequential run of blocks
until the pread() end of the stream catches up with the *start* of it,
if ever (ie until the kernel sees the actual sequential reads).

So like fadvise blocks 2,3,4,5, but then we see pread block 2 so stop
fadvising for that run of blocks?

That turned out to require only a small tweak and one new variable. It
avoids those stalls on reads of sequential clusters >
io_combine_limit, with no change in behaviour for pure sequential
streams and random streams containing sequential clusters <=
io_combine_limit that I'd previously been fixating on.

Hmm. My understanding must be incorrect because I don't see how this
would behave differently for these two IO patterns

fadvise 2,3,4,5, pread 2

fadvise 2,100,717,999, pread 2

I've added a
patch for that to the v2 of my read stream improvements series[1] for
experimentation... will post shortly.

I don't think you've posted those yet. I'd like to confirm that these
work as expected before we merge the bitmap heap scan code.

I also see a couple of other reasons why streaming BHS can be less
aggressive with I/O than master: the silly arbitrary buffer queue cap,
there's already a patch in the series for that but I have a slightly
better one now and plan to commit it today, and silly heuristics for
look-ahead distance reduction also related to sequential detection,
which I'll explain with a patch on the other thread. All of these are
cases where I was basically a bit too chicken to open the throttle all
the way in early versions. Will post those at [1] too after lunch...
more soon...

I'd like to hear more about the buffer queue cap, as I can't say I
remember what that is.

I'd also be interested to see how these other patches affect the BHS
performance.

Other than that, we need to decide on effective_io_concurrency
defaults, which has also been discussed on this thread.

- Melanie

#209Melanie Plageman
melanieplageman@gmail.com
In reply to: Tomas Vondra (#204)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Feb 16, 2025 at 7:29 AM Tomas Vondra <tomas@vondra.me> wrote:

On 2/16/25 02:15, Tomas Vondra wrote:

...

OK, I've uploaded the results to the github repository as usual

https://github.com/tvondra/bitmapscan-tests/tree/main/20250214-184807

and I've generated the same PDF reports, with the colored comparison.

If you compare the pivot tables (I opened the "same" PDF from the two
runs and flip between them using alt-tab, which makes the interesting
regions easy to spot), the change is very clear.

Disabling the sequential detection greatly reduces the scope of
regressions. That looks pretty great, IMO.

It also seems to lose some speedups, especially with io_combine_limit=1
and eic=1. I'm not sure why, if that's expected, etc.

Yea, I don't know why these would change with vs without sequential detection.
Honestly, for serial bitmap heap scan, I would assume that eic 1,
io_combine_limit 1 would be the same as master (i.e. issuing at least
the one fadvise and no additional latency introduced by trying to
combine IOs). So both the speedup and slowdown are a bit surprising to
me.

There still remain areas of regression, but most of them are for cases
that'd use index scan (tiny fraction of rows scanned), or with
read-ahead=4096 (and not for the lower settings).

The read-ahead dependence is actually somewhat interesting, because I
realized the RAID array has this set to 8192 by default, i.e. even
higher than 4096 where it regresses. I suppose mdadm does that, or
something, I don't know how the default is calculated. But I assume it
depends on the number of devices, so larger arrays might have even
higher read-ahead values.

Are the readahead regressions you are talking about the ones with
io_combine_limit > 1 and effective_io_concurrency 0 (at higher
readahead values)? With these, we expect that no fadvises and higher
readahead values means the OS will do good readahead for us. But
somehow the read combining seems to be interfering with this.

This is curious. It seems like it must have something to do with the
way the kernel is calculating readahead size. While the linux kernel
readahead readme [1]https://github.com/torvalds/linux/blob/master/mm/readahead.c is not particularly easy to understand, there are
some parts that stick out to me:

* The size of the async tail is determined by subtracting the size that
* was explicitly requested from the determined request size, unless
* this would be less than zero - then zero is used.

I wonder if somehow the larger IO requests are foiling readahead.
Honestly, I don't know how far we can get trying to figure this out.
And explicitly reverse engineering this may backfire in other ways.

- Melanie

[1]: https://github.com/torvalds/linux/blob/master/mm/readahead.c

#210Melanie Plageman
melanieplageman@gmail.com
In reply to: Jakub Wartak (#205)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Feb 19, 2025 at 8:29 AM Jakub Wartak
<jakub.wartak@enterprisedb.com> wrote:

On Fri, Feb 14, 2025 at 7:16 PM Andres Freund <andres@anarazel.de> wrote:

Melanie has worked on this a fair bit, fwiw.

My current thinking is that we'd want something very roughly like TCP
BBR. Basically, it predicts the currently available bandwidth not just via
lost packets - the traditional approach - but also by building a continually
updated model of "bytes in flight" and latency and uses that to predict what
the achievable bandwidth is.[..]

Sadly that doesn't sound like PG18, right? (or I missed some thread,
I've tried to watch Melanie's presentation though )

Yes, I spent about a year researching this. My final algorithm didn't
make it into a presentation, but the basic idea was to track how the
prefetch distance was affecting throughput on a per IO basis and push
the prefetch distance up when doing so was increasing throughput and
down when throughput isn't increasing. Doing this in a sawtooth
pattern ultimately would allow the prefetch distance to adapt to
changing system resources.

The actual algorithm was more complicated than this, but that was the
basic premise. It worked well in simulations.

- Melanie

#211Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#206)
4 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Feb 19, 2025 at 4:14 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Attached v30 makes the tuple offset extraction happen later as you
suggested. It turns out that none of the users need to worry much
about allocating and freeing -- I was able to have all users make an
offsets array on the stack. Personally I don't think we should worry
about making a smaller array when fewer offsets are needed.

Even without the read stream API, in bitmap heap scan, delaying
extraction of the offsets lets us skip doing so for the prefetch
iterator -- so that's kind of cool. Anyway, we are going to get rid of
the prefetch iterator, so I won't belabor the point.

I was worried the patch would be too big of a change to the tidbitmap
API for this late in the cycle, but it turned out to be a small patch.
I'd be interested in what folks think.

Attached v31 has some updates after self-review and some off-list
feedback from Andres. They're minor changes, so I won't enumerate
them.

- Melanie

Attachments:

v31-0001-Delay-extraction-of-TIDBitmap-per-page-offsets.patchtext/x-patch; charset=US-ASCII; name=v31-0001-Delay-extraction-of-TIDBitmap-per-page-offsets.patchDownload
From e85497578afa4b3031050652daeec6fc6c8953c4 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:24:49 -0500
Subject: [PATCH v31 1/4] Delay extraction of TIDBitmap per page offsets

Pages from the bitmap created by the TIDBitmap API can be exact or
lossy. Exact pages extract all the tuple offsets from the bitmap and put
them in an array for the convenience of the caller.

This was done in tbm_private|shared_iterate(). However, as long as
tbm_private|shared_iterate() set a reference to the PagetableEntry in
the TBMIterateResult, the offset extraction can be done later.

Waiting to extract the tuple offsets has a few benefits. For the shared
iterator case, it allows us to extract the offsets after dropping the
shared iterator state lock, reducing time spent holding a contended
lock.

Separating the iteration step and extracting the offsets later also
allows us to avoid extracting the offsets for prefetched blocks. Those
offsets were never used, so the overhead of extracting and storing them
was wasted.

The real motivation for this change, however, is that future commits
will make bitmap heap scan use the read stream API. This requires a
TBMIterateResult per issued block. By removing the array of tuple
offsets from the TBMIterateResult and only extracting the offsets when
they are used, we reduce the memory required for per buffer data
substantially.

Suggested-by: Thomas Munro
Discussion: https://postgr.es/m/CA%2BhUKGLHbKP3jwJ6_%2BhnGi37Pw3BD5j2amjV3oSk7j-KyCnY7Q%40mail.gmail.com
---
 src/backend/access/gin/ginget.c          | 16 ++++++--
 src/backend/access/heap/heapam_handler.c | 10 ++++-
 src/backend/nodes/tidbitmap.c            | 52 +++++++++---------------
 src/include/access/gin_private.h         |  1 +
 src/include/nodes/tidbitmap.h            | 42 ++++++++++++++++---
 5 files changed, 80 insertions(+), 41 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 63dd1f3679f..9fbe178ad47 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -845,6 +845,15 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 					break;
 				}
 
+				/*
+				 * Exact pages need their tuple offsets extracted.
+				 * tbm_extract_page_tuple() will set ntuples to the correct
+				 * number.
+				 */
+				if (entry->matchResult->ntuples == -2)
+					tbm_extract_page_tuple(entry->matchResult,
+										   entry->matchTupleOffsets);
+
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
 				 * entry->offset is still greater than matchResult->ntuples if
@@ -884,20 +893,21 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchTupleOffsets[entry->matchResult->ntuples - 1] <=
+					advancePastOff)
 				{
 					entry->offset = entry->matchResult->ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchTupleOffsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
 						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchTupleOffsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c0bec014154..408d4b44240 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2127,6 +2127,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
+	TBMOffsets	offsets;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
 
@@ -2145,6 +2146,13 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (tbmres == NULL)
 			return false;
 
+		/*
+		 * Exact pages need their tuple offsets extracted.
+		 * tbm_extract_page_tuple() will set ntuples to the correct number.
+		 */
+		if (tbmres->ntuples == -2)
+			tbm_extract_page_tuple(tbmres, offsets);
+
 		/*
 		 * Ignore any claimed entries past what we think is the end of the
 		 * relation. It may have been extended after the start of our scan (we
@@ -2218,7 +2226,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 
 		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 66b3c387d53..13ba247824d 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as TBM_MAX_TUPLES_PER_PAGE, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((TBM_MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > TBM_MAX_TUPLES_PER_PAGE)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,9 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -906,11 +895,13 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm)
 /*
  * tbm_extract_page_tuple - extract the tuple offsets from a page
  *
- * The extracted offsets are stored into TBMIterateResult.
+ * Sets ntuples in the TBMIterateResult
  */
-static inline int
-tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
+void
+tbm_extract_page_tuple(TBMIterateResult *iteritem,
+					   TBMOffsets offsets)
 {
+	PagetableEntry *page = iteritem->internal_page;
 	int			wordnum;
 	int			ntuples = 0;
 
@@ -925,14 +916,14 @@ tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
 			while (w != 0)
 			{
 				if (w & 1)
-					output->offsets[ntuples++] = (OffsetNumber) off;
+					offsets[ntuples++] = (OffsetNumber) off;
 				off++;
 				w >>= 1;
 			}
 		}
 	}
 
-	return ntuples;
+	iteritem->ntuples = ntuples;
 }
 
 /*
@@ -1021,7 +1012,6 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 	if (iterator->spageptr < tbm->npages)
 	{
 		PagetableEntry *page;
-		int			ntuples;
 
 		/* In TBM_ONE_PAGE state, we don't allocate an spages[] array */
 		if (tbm->status == TBM_ONE_PAGE)
@@ -1029,10 +1019,10 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
+		output->internal_page = page;
+		/* ntuples will be calculated later */
+		output->ntuples = -2;
 		output->blockno = page->blockno;
-		output->ntuples = ntuples;
 		output->recheck = page->recheck;
 		iterator->spageptr++;
 		return output;
@@ -1116,12 +1106,11 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	if (istate->spageptr < istate->npages)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
-		int			ntuples;
 
-		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
+		output->internal_page = page;
+		/* ntuples will be calculated later */
+		output->ntuples = -2;
 		output->blockno = page->blockno;
-		output->ntuples = ntuples;
 		output->recheck = page->recheck;
 		istate->spageptr++;
 
@@ -1468,8 +1457,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..9a9461cdfd1 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -354,6 +354,7 @@ typedef struct GinScanEntryData
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
+	TBMOffsets	matchTupleOffsets;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index a6ffeac90be..17462fb554f 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,9 +22,22 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
+/*
+ * The maximum number of tuples per page is not large (typically 256 with
+ * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+ * the per-page bitmaps variable size.  We just legislate that the size
+ * is this:
+ */
+#define TBM_MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
+
+/*
+ * The tuple OffsetNumbers extracted from a single page in the bitmap.
+ */
+typedef OffsetNumber TBMOffsets[TBM_MAX_TUPLES_PER_PAGE];
 
 /*
  * Actual bitmap representation is private to tidbitmap.c.  Callers can
@@ -36,6 +49,7 @@ typedef struct TIDBitmap TIDBitmap;
 typedef struct TBMPrivateIterator TBMPrivateIterator;
 typedef struct TBMSharedIterator TBMSharedIterator;
 
+
 /*
  * Callers with both private and shared implementations can use this unified
  * API.
@@ -53,11 +67,26 @@ typedef struct TBMIterator
 /* Result structure for tbm_iterate */
 typedef struct TBMIterateResult
 {
-	BlockNumber blockno;		/* page number containing tuples */
-	int			ntuples;		/* -1 indicates lossy result */
-	bool		recheck;		/* should the tuples be rechecked? */
-	/* Note: recheck is always true if ntuples < 0 */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+	BlockNumber blockno;		/* block number containing tuples */
+
+	/*
+	 * -1 indicates a lossy page. -2 indicates an exact page whose tuple
+	 * offsets have yet to be extracted from the bitmap.
+	 */
+	int			ntuples;
+
+	/*
+	 * Whether or not the tuples should be rechecked. This is always true if
+	 * ntuples < 0 but may also be true if the query requires recheck.
+	 */
+	bool		recheck;
+
+	/*
+	 * Pointer to the page containing the bitmap for this block. It is a void *
+	 * to avoid exposing the details of the tidbitmap PagetableEntry to API
+	 * users.
+	 */
+	void	   *internal_page;
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
@@ -74,6 +103,9 @@ extern void tbm_add_page(TIDBitmap *tbm, BlockNumber pageno);
 extern void tbm_union(TIDBitmap *a, const TIDBitmap *b);
 extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
+extern void tbm_extract_page_tuple(TBMIterateResult *iteritem,
+								   TBMOffsets offsets);
+
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
-- 
2.34.1

v31-0002-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v31-0002-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From 2e23e94b413f3f812887e9168e3c36e680c76354 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:30:26 -0500
Subject: [PATCH v31 2/4] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This allows tidbitmap API users to manage multiple TBMIterateResults per
scan. This is required for bitmap heap scan to use the read stream API,
with which there may be multiple I/Os in flight at once, each one with a
TBMIterateResult.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/gin/ginget.c           | 39 +++++-----
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 32 ++++-----
 src/backend/executor/nodeBitmapHeapscan.c | 39 +++++-----
 src/backend/nodes/tidbitmap.c             | 88 ++++++++++++-----------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 110 insertions(+), 103 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 9fbe178ad47..ea8ca593890 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,7 +332,7 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -824,20 +824,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult.blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
-					entry->offset >= entry->matchResult->ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (entry->matchResult.ntuples >= 0 &&
+					entry->offset >= entry->matchResult.ntuples) ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
-
-				if (entry->matchResult == NULL)
+				if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult))
 				{
+					Assert(!BlockNumberIsValid(entry->matchResult.blockno));
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
@@ -850,13 +849,13 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				 * tbm_extract_page_tuple() will set ntuples to the correct
 				 * number.
 				 */
-				if (entry->matchResult->ntuples == -2)
-					tbm_extract_page_tuple(entry->matchResult,
+				if (entry->matchResult.ntuples == -2)
+					tbm_extract_page_tuple(&entry->matchResult,
 										   entry->matchTupleOffsets);
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -869,10 +868,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult.ntuples < 0)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -886,17 +885,17 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * Not a lossy page. Skip over any offsets <= advancePast, and
 			 * return that.
 			 */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchTupleOffsets[entry->matchResult->ntuples - 1] <=
+				if (entry->matchTupleOffsets[entry->matchResult.ntuples - 1] <=
 					advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchResult.ntuples;
 					continue;
 				}
 
@@ -906,7 +905,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
+						   entry->matchResult.blockno,
 						   entry->matchTupleOffsets[entry->offset]);
 			entry->offset++;
 
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..625140fdf25 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 408d4b44240..058470d0b0f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 	TBMOffsets	offsets;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
@@ -2141,17 +2141,15 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
-
-		if (tbmres == NULL)
+		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
 			return false;
 
 		/*
 		 * Exact pages need their tuple offsets extracted.
 		 * tbm_extract_page_tuple() will set ntuples to the correct number.
 		 */
-		if (tbmres->ntuples == -2)
-			tbm_extract_page_tuple(tbmres, offsets);
+		if (tbmres.ntuples == -2)
+			tbm_extract_page_tuple(&tbmres, offsets);
 
 		/*
 		 * Ignore any claimed entries past what we think is the end of the
@@ -2162,11 +2160,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2174,19 +2172,19 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(tbmres.ntuples >= 0);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += tbmres.ntuples;
 
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2215,7 +2213,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2224,7 +2222,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
 		{
 			OffsetNumber offnum = offsets[curslot];
 			ItemPointerData tid;
@@ -2276,7 +2274,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
+	if (tbmres.ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..3b4ea0f6144 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,18 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
 					/* No more pages to prefetch */
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 13ba247824d..8756b48b9ec 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -950,20 +948,25 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.
+ *
+ * Returns false when there are no more pages to scan and true otherwise. When
+ * there are no more pages to scan, tbmres->blockno is set to
+ * InvalidBlockNumber.
+ *
+ * If tbmres->ntuples < 0, then the bitmap is "lossy" and failed to remember
+ * the exact tuples to look at on this page --- the caller must examine all
+ * tuples on the page and check if they meet the intended condition.  If
+ * tbmres->recheck is true, only the indicated tuples need be examined, but
+ * the condition must be rechecked anyway.  (For ease of testing, recheck is
+ * always set true when ntuples < 0.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+bool
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -1001,11 +1004,11 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			iterator->schunkbit++;
-			return output;
+			return true;
 		}
 	}
 
@@ -1019,17 +1022,18 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		output->internal_page = page;
+		tbmres->internal_page = page;
 		/* ntuples will be calculated later */
-		output->ntuples = -2;
-		output->blockno = page->blockno;
-		output->recheck = page->recheck;
+		tbmres->ntuples = -2;
+		tbmres->blockno = page->blockno;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return true;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1039,10 +1043,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+bool
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1093,13 +1096,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->ntuples = -1;
-			output->recheck = true;
+			tbmres->blockno = chunk_blockno;
+			tbmres->ntuples = -1;
+			tbmres->recheck = true;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return true;
 		}
 	}
 
@@ -1107,22 +1110,23 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
 
-		output->internal_page = page;
+		tbmres->internal_page = page;
 		/* ntuples will be calculated later */
-		output->ntuples = -2;
-		output->blockno = page->blockno;
-		output->recheck = page->recheck;
+		tbmres->ntuples = -2;
+		tbmres->blockno = page->blockno;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return true;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1596,15 +1600,17 @@ tbm_end_iterate(TBMIterator *iterator)
 }
 
 /*
- * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ * Populate the next TBMIterateResult using the shared or private bitmap
+ * iterator. Returns false when there is nothing more to scan.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+bool
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 9a9461cdfd1..dfda25686be 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 	TBMOffsets	matchTupleOffsets;
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 17462fb554f..4a8784d54aa 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -110,8 +110,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -122,7 +122,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern bool tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v31-0003-BitmapHeapScan-uses-the-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v31-0003-BitmapHeapScan-uses-the-read-stream-API.patchDownload
From 79951799d80c21d0facc06c6441e37b373525a38 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:30:34 -0500
Subject: [PATCH v31 3/4] BitmapHeapScan uses the read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam.c          |  75 +++++
 src/backend/access/heap/heapam_handler.c  |  95 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 354 +---------------------
 src/include/access/relscan.h              |   8 +-
 src/include/access/tableam.h              |  33 +-
 src/include/nodes/execnodes.h             |  23 +-
 6 files changed, 141 insertions(+), 447 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index fa7935a0ed3..9deedc89f78 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,67 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		/* no more entries in the bitmap */
+		if (!tbm_iterate(&sscan->st.bitmap.rs_iterator, tbmres))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			OffsetNumber offsets[MaxHeapTuplesPerPage] = {0};
+
+			/*
+			 * We throw away the offsets, but this is the easiest way to get a
+			 * count of tuples.
+			 */
+			tbm_extract_page_tuple(tbmres, offsets);
+			bscan->rs_empty_tuples_pending += tbmres->ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1128,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1208,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1252,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 058470d0b0f..f55a8f43fd3 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2117,82 +2117,75 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 	TBMOffsets	offsets;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
-			return false;
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
 
-		/*
-		 * Exact pages need their tuple offsets extracted.
-		 * tbm_extract_page_tuple() will set ntuples to the correct number.
-		 */
-		if (tbmres.ntuples == -2)
-			tbm_extract_page_tuple(&tbmres, offsets);
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
 	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
+	 * Exact pages need their tuple offsets extracted.
+	 * tbm_extract_page_tuple() will set ntuples to the correct number.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres.ntuples >= 0);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
+	if (tbmres->ntuples == -2)
+		tbm_extract_page_tuple(tbmres, offsets);
 
-		bscan->rs_empty_tuples_pending += tbmres.ntuples;
+	*recheck = tbmres->recheck;
 
-		return true;
-	}
-
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2213,7 +2206,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2222,7 +2215,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
 		{
 			OffsetNumber offnum = offsets[curslot];
 			ItemPointerData tid;
@@ -2274,7 +2267,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.ntuples >= 0)
+	if (tbmres->ntuples >= 0)
 		(*exact_pages)++;
 	else
 		(*lossy_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3b4ea0f6144..46721e091ab 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -149,16 +120,16 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		node->ss.ss_currentScanDesc =
 			table_beginscan_bm(node->ss.ss_currentRelation,
 							   node->ss.ps.state->es_snapshot,
+							   pstate,
 							   0,
 							   NULL,
 							   need_tuples);
 	}
 
-	node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+	node->ss.ss_currentScanDesc->st.bitmap.rs_iterator = tbmiterator;
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +143,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -201,40 +168,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/*
 			 * Continuing in previously obtained page.
 			 */
-
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -254,34 +189,17 @@ BitmapHeapNext(BitmapHeapScanState *node)
 			/* OK to return this tuple */
 			return slot;
 		}
-
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,225 +223,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					/* No more pages to prefetch */
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -573,31 +272,19 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scan->st.rs_tbmiterator))
-			tbm_end_iterate(&scan->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scan->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scan->st.bitmap.rs_iterator);
 
 		/* rescan to release any page pin */
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -657,8 +344,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		 * End iteration on iterators saved in scan descriptor if they have
 		 * not already been cleaned up.
 		 */
-		if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
-			tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
+		if (!tbm_exhausted(&scanDesc->st.bitmap.rs_iterator))
+			tbm_end_iterate(&scanDesc->st.bitmap.rs_iterator);
 
 		/*
 		 * close table scan
@@ -666,17 +353,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -709,18 +390,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -760,13 +436,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -870,12 +539,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -912,17 +578,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index dc6e0184284..934b667ad78 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -43,8 +43,12 @@ typedef struct TableScanDescData
 	 */
 	union
 	{
-		/* Iterator for Bitmap Table Scans */
-		TBMIterator rs_tbmiterator;
+		/* State for Bitmap Table Scans */
+		struct
+		{
+			struct ParallelBitmapHeapState *rs_pstate;
+			TBMIterator rs_iterator;
+		}			bitmap;
 
 		/*
 		 * Range of ItemPointers for table_scan_getnextslot_tidrange() to
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..b5675b47dcc 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -956,15 +940,19 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
  */
 static inline TableScanDesc
 table_beginscan_bm(Relation rel, Snapshot snapshot,
+				   struct ParallelBitmapHeapState *pstate,
 				   int nkeys, struct ScanKeyData *key, bool need_tuple)
 {
+	TableScanDesc result;
 	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
 
 	if (need_tuple)
 		flags |= SO_NEED_TUPLES;
 
-	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
-									   NULL, flags);
+	result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys,
+										 key, NULL, flags);
+	result->st.bitmap.rs_pstate = pstate;
+	return result;
 }
 
 /*
@@ -1966,16 +1954,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1972,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a323fa98bbb..5f743d6699c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1828,11 +1828,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1840,10 +1836,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1867,18 +1860,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1886,18 +1872,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v31-0004-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v31-0004-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 8abb0507ddb18bfb08bb5564eb837b030bc47b2f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:31:02 -0500
Subject: [PATCH v31 4/4] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator into table-AM specific code (as part
of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer returns the current block number.
Since scan_bitmap_next_block() isn't returning any relevant information
to bitmap table scan code, it makes more sense to get rid of it.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple(),
and the heap AM implementation of scan_bitmap_next_block() is a local
helper in heapam_handler.c.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam_handler.c  | 373 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   2 -
 src/backend/executor/nodeBitmapHeapscan.c |  71 ++--
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 245 insertions(+), 293 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f55a8f43fd3..06068d7d204 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,11 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,198 +2121,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-	TBMOffsets	offsets;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BlockNumberIsValid(tbmres->blockno));
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	/*
-	 * Exact pages need their tuple offsets extracted.
-	 * tbm_extract_page_tuple() will set ntuples to the correct number.
-	 */
-	if (tbmres->ntuples == -2)
-		tbm_extract_page_tuple(tbmres, offsets);
-
-	*recheck = tbmres->recheck;
-
-	hscan->rs_cblock = tbmres->blockno;
-	hscan->rs_ntuples = tbmres->ntuples;
-
-	block = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (tbmres->ntuples >= 0)
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		int			curslot;
-
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			OffsetNumber offnum = offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
-		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
-		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
-		(*lossy_pages)++;
 
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
-
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2614,6 +2465,177 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+	TBMOffsets	offsets;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	/*
+	 * Exact pages need their tuple offsets extracted.
+	 * tbm_extract_page_tuple() will set ntuples to the correct number.
+	 */
+	if (tbmres->ntuples == -2)
+		tbm_extract_page_tuple(tbmres, offsets);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = tbmres->ntuples;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (tbmres->ntuples >= 0)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		{
+			OffsetNumber offnum = offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->ntuples >= 0)
+		(*exact_pages)++;
+	else
+		(*lossy_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2673,7 +2695,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..56378007a81 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -92,8 +92,6 @@ GetTableAmRoutine(Oid amhandler)
 	Assert(routine->relation_estimate_size != NULL);
 
 	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 46721e091ab..68499e3aa45 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -139,67 +139,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
+
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
 		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-			CHECK_FOR_INTERRUPTS();
-
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
-new_page:
 
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index b5675b47dcc..1bed5005c07 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. These are tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1943,51 +1923,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1998,7 +1951,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

#212Thomas Munro
thomas.munro@gmail.com
In reply to: Melanie Plageman (#211)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Feb 21, 2025 at 11:17 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

[v31-0001-Delay-extraction-of-TIDBitmap-per-page-offsets.patch]

Nice patch, seems like a straightforward win with the benefits you
explained: less work done under a lock, less work done in the second
iterator if the rest of this stuff doesn't make it in yet, and less
space used assuming it does. My only comment is that I'm not sure
about this type:

+/*
+ * The tuple OffsetNumbers extracted from a single page in the bitmap.
+ */
+typedef OffsetNumber TBMOffsets[TBM_MAX_TUPLES_PER_PAGE];

It's used for a stack object, but it's also used as a degraded pointer here:

+extern void tbm_extract_page_tuple(TBMIterateResult *iteritem,
+
TBMOffsets offsets);

Maybe a personal style question but degraded pointers aren't my
favourite C feature. A couple of alternatives, I am not sure how good
they are: Would this output variable be better wrapped up in a new
struct for better API clarity? If so, shouldn't such a struct also
hold ntuples itself, since that really goes with the offsets it's
holding? If so, could iteritem->ntuples then be replaced with a
boolean iteritem->lossy, since all you really need to be able to check
is whether it has offsets to give you, instead of using -1 and -2 for
that? Or as a variation without a new struct, would it be better to
take that output array as a plain pointer to OffsetNumber and
max_offsets, and return ntuples (ie how many were filled in, cf commit
f6bef362), for the caller to use in a loop or stash somewhere, with an
additional comment that TBM_MAX_TUPLES_PER_PAGE is guaranteed to be
enough, for convenience eg for arrays on the stack?

#213Melanie Plageman
melanieplageman@gmail.com
In reply to: Thomas Munro (#212)
5 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

Thanks for the review!

While editing this, I found a few things I could improve. For one, I
actually wasn't using the parallel state member that I had added as a
parameter to one of the table AM callbacks. So, I was able to remove
that.

On Thu, Feb 20, 2025 at 7:32 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Fri, Feb 21, 2025 at 11:17 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

[v31-0001-Delay-extraction-of-TIDBitmap-per-page-offsets.patch]

+/*
+ * The tuple OffsetNumbers extracted from a single page in the bitmap.
+ */
+typedef OffsetNumber TBMOffsets[TBM_MAX_TUPLES_PER_PAGE];

It's used for a stack object, but it's also used as a degraded pointer here:

+extern void tbm_extract_page_tuple(TBMIterateResult *iteritem,
+
TBMOffsets offsets);

Maybe a personal style question but degraded pointers aren't my
favourite C feature. A couple of alternatives, I am not sure how good
they are: Would this output variable be better wrapped up in a new
struct for better API clarity? If so, shouldn't such a struct also
hold ntuples itself, since that really goes with the offsets it's
holding? If so, could iteritem->ntuples then be replaced with a
boolean iteritem->lossy, since all you really need to be able to check
is whether it has offsets to give you, instead of using -1 and -2 for
that?

Yea, I think this is a good point. I made a new struct which has
ntuples and the offsets array as you suggested. I think it's much
nicer than using -2 :)

I do worry a bit about the ntuples value in the new struct being
uninitialized. Before, tbm_iterate() filled in
TBMIterateResult.ntuples, so you knew that once you had a
TBMIterateResult at all, ntuples was valid. Now you make a
TBMPageOffsets and until you call tbm_extract_page_tuple() on it,
TBMPageOffsets->ntuples is garbage. It's probably okay though. I have
the caller initialize TBMPageOffsets to -1 when I think this might be
an issue.

Or as a variation without a new struct, would it be better to
take that output array as a plain pointer to OffsetNumber and
max_offsets, and return ntuples (ie how many were filled in, cf commit
f6bef362), for the caller to use in a loop or stash somewhere, with an
additional comment that TBM_MAX_TUPLES_PER_PAGE is guaranteed to be
enough, for convenience eg for arrays on the stack?

I thought about doing this, but in the end I decided against this
approach. If we wanted to make it easy to palloc arrays of different
sizes and have tbm_extract_page_tuple extract that many tuples into
the array, we'd have to change more of the code anyway because
tbm_extract_page_tuple is what tells us how many tuples there are to
begin with. We could save this somewhere while filling in the
PagetableEntries initially, but that is a bigger change.

And, passing a length would also mean more callers would have to know
about TBM_MAX_TUPLES_PER_PAGE, which I think is already kind of a hack
since it is defined as MaxHeapTuplesPerPage.

- Melanie

Attachments:

v32-0001-Add-lossy-indicator-to-TBMIterateResult.patchtext/x-patch; charset=US-ASCII; name=v32-0001-Add-lossy-indicator-to-TBMIterateResult.patchDownload
From b234998904f1da321de4568b604d0b1a233a2fcb Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 10:58:59 -0500
Subject: [PATCH v32 1/5] Add lossy indicator to TBMIterateResult

TBMIterateResult->ntuples is -1 when the page in the bitmap is lossy.
Add an explicit lossy indicator so that we can move ntuples out of the
TBMIterateResult in a future commit.
---
 src/backend/access/gin/ginget.c          |  6 ++++--
 src/backend/access/heap/heapam_handler.c | 10 +++++-----
 src/backend/nodes/tidbitmap.c            | 11 ++++++++---
 src/include/nodes/tidbitmap.h            |  5 +++--
 4 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 63dd1f3679f..54aecc1d1f1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -827,7 +827,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * in the bitmap.
 			 */
 			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
+				   (!entry->matchResult->lossy &&
 					entry->offset >= entry->matchResult->ntuples) ||
 				   entry->matchResult->blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
@@ -860,7 +860,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult->lossy)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
 										entry->matchResult->blockno);
@@ -879,6 +879,8 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 */
 			if (entry->matchResult->blockno == advancePastBlk)
 			{
+				Assert(entry->matchResult->ntuples > 0);
+
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c0bec014154..269d581c2ec 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2170,7 +2170,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(!tbmres->lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 
 		bscan->rs_empty_tuples_pending += tbmres->ntuples;
@@ -2207,7 +2207,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (!tbmres->lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2268,10 +2268,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
+	if (tbmres->lossy)
 		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 66b3c387d53..3e0bca651f5 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -961,12 +961,13 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  *
  * Returns a TBMIterateResult representing one page, or NULL if there are
  * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
+ * order.  If lossy is true, then the bitmap is "lossy" and failed to
  * remember the exact tuples to look at on this page --- the caller must
  * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
+ * condition.  result->ntuples is set to -1 when the bitmap is lossy.
+ * If result->recheck is true, only the indicated tuples need
  * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * testing, recheck is always set true when lossy is true.)
  */
 TBMIterateResult *
 tbm_private_iterate(TBMPrivateIterator *iterator)
@@ -1012,6 +1013,7 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			/* Return a lossy page indicator from the chunk */
 			output->blockno = chunk_blockno;
 			output->ntuples = -1;
+			output->lossy = true;
 			output->recheck = true;
 			iterator->schunkbit++;
 			return output;
@@ -1033,6 +1035,7 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		ntuples = tbm_extract_page_tuple(page, output);
 		output->blockno = page->blockno;
 		output->ntuples = ntuples;
+		output->lossy = false;
 		output->recheck = page->recheck;
 		iterator->spageptr++;
 		return output;
@@ -1105,6 +1108,7 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			/* Return a lossy page indicator from the chunk */
 			output->blockno = chunk_blockno;
 			output->ntuples = -1;
+			output->lossy = true;
 			output->recheck = true;
 			istate->schunkbit++;
 
@@ -1122,6 +1126,7 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		ntuples = tbm_extract_page_tuple(page, output);
 		output->blockno = page->blockno;
 		output->ntuples = ntuples;
+		output->lossy = false;
 		output->recheck = page->recheck;
 		istate->spageptr++;
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index a6ffeac90be..8cd93d90a86 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -54,9 +54,10 @@ typedef struct TBMIterator
 typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
-	int			ntuples;		/* -1 indicates lossy result */
+	int			ntuples;		/* -1 when lossy */
+	bool		lossy;
 	bool		recheck;		/* should the tuples be rechecked? */
-	/* Note: recheck is always true if ntuples < 0 */
+	/* Note: recheck is always true if lossy */
 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
 } TBMIterateResult;
 
-- 
2.34.1

v32-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v32-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From a07123ed8017afceea4608272265bd261a6c86da Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:32:33 -0500
Subject: [PATCH v32 5/5] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator into table-AM specific code (as part
of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer returns the current block number.
Since scan_bitmap_next_block() isn't returning any relevant information
to bitmap table scan code, it makes more sense to get rid of it.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple(),
and the heap AM implementation of scan_bitmap_next_block() is a local
helper in heapam_handler.c.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam_handler.c  | 382 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   3 -
 src/backend/executor/nodeBitmapHeapscan.c |  73 ++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++---
 5 files changed, 249 insertions(+), 301 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f35c1fac460..96444226889 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,10 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,203 +2120,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-	TBMPageOffsets offsets;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
-											 &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BlockNumberIsValid(tbmres->blockno));
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	/*
-	 * Exact pages need their tuple offsets extracted.
-	 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
-	 * number.
-	 */
-	if (!tbmres->lossy)
-		tbm_extract_page_tuple(tbmres, &offsets);
-
-	*recheck = tbmres->recheck;
-
-	hscan->rs_cblock = tbmres->blockno;
-	hscan->rs_ntuples = offsets.ntuples;
-
-	block = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (!tbmres->lossy)
-	{
-		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		/* We must have extracted the tuple offsets by now */
-		Assert(offsets.ntuples > -1);
-
-		for (curslot = 0; curslot < offsets.ntuples; curslot++)
-		{
-			OffsetNumber offnum = offsets.offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->lossy)
-		(*lossy_pages)++;
-	else
-		(*exact_pages)++;
 
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
-
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2619,6 +2464,182 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+	TBMPageOffsets offsets;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	/*
+	 * Exact pages need their tuple offsets extracted.
+	 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
+	 * number.
+	 */
+	if (!tbmres->lossy)
+		tbm_extract_page_tuple(tbmres, &offsets);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = offsets.ntuples;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (!tbmres->lossy)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		/* We must have extracted the tuple offsets by now */
+		Assert(offsets.ntuples > -1);
+
+		for (curslot = 0; curslot < offsets.ntuples; curslot++)
+		{
+			OffsetNumber offnum = offsets.offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->lossy)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2678,7 +2699,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..476663b66aa 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6df34094a13..3e33360c0fc 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -138,69 +138,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-
-			CHECK_FOR_INTERRUPTS();
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 507d4ebe68f..b8cb1e744ad 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. These are tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1939,51 +1919,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1994,7 +1947,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

v32-0004-BitmapHeapScan-uses-the-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v32-0004-BitmapHeapScan-uses-the-read-stream-API.patchDownload
From 144ce58edd1f72a7ce52d2cc5371a424eb5225b0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:15:47 -0500
Subject: [PATCH v32 4/5] BitmapHeapScan uses the read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam.c          |  79 +++++
 src/backend/access/heap/heapam_handler.c  |  97 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 341 +---------------------
 src/include/access/tableam.h              |  25 +-
 src/include/nodes/execnodes.h             |  23 +-
 5 files changed, 128 insertions(+), 437 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index fa7935a0ed3..0aec5df3cc5 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,71 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		/* no more entries in the bitmap */
+		if (!tbm_iterate(&sscan->st.rs_tbmiterator, tbmres))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			TBMPageOffsets offsets;
+
+			/* can't be lossy in the skip_fetch case */
+			Assert(!tbmres->lossy);
+			Assert(bscan->rs_empty_tuples_pending >= 0);
+
+			/*
+			 * We throw away the offsets, but this is the easiest way to get a
+			 * count of tuples.
+			 */
+			tbm_extract_page_tuple(tbmres, &offsets);
+			bscan->rs_empty_tuples_pending += offsets.ntuples;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1132,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1212,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1256,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 663660f38f0..f35c1fac460 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2117,84 +2117,77 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 	TBMPageOffsets offsets;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
-			return false;
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
 
-		/*
-		 * Exact pages need their tuple offsets extracted.
-		 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
-		 * number.
-		 */
-		if (!tbmres.lossy)
-			tbm_extract_page_tuple(&tbmres, &offsets);
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
 	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
+	 * Exact pages need their tuple offsets extracted.
+	 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
+	 * number.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres.lossy);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
-		Assert(offsets.ntuples > -1);
+	if (!tbmres->lossy)
+		tbm_extract_page_tuple(tbmres, &offsets);
 
-		bscan->rs_empty_tuples_pending += offsets.ntuples;
+	*recheck = tbmres->recheck;
 
-		return true;
-	}
-
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = offsets.ntuples;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2215,7 +2208,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres.lossy)
+	if (!tbmres->lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,7 +2272,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.lossy)
+	if (tbmres->lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3b4ea0f6144..6df34094a13 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -158,7 +129,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +142,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -204,37 +170,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -257,31 +192,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,225 +224,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					/* No more pages to prefetch */
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -580,24 +280,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -666,17 +354,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -709,18 +391,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -760,13 +437,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -870,12 +540,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -912,17 +579,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..507d4ebe68f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -1966,16 +1950,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1968,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a323fa98bbb..5f743d6699c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1828,11 +1828,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1840,10 +1836,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1867,18 +1860,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1886,18 +1872,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v32-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v32-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From 01c7664595dd9d3fd49b4cc53053b5d6c204d428 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:30:26 -0500
Subject: [PATCH v32 3/5] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This allows tidbitmap API users to manage multiple TBMIterateResults per
scan. This is required for bitmap heap scan to use the read stream API,
with which there may be multiple I/Os in flight at once, each one with a
TBMIterateResult.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/gin/ginget.c           | 33 ++++----
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 28 +++----
 src/backend/executor/nodeBitmapHeapscan.c | 39 +++++----
 src/backend/nodes/tidbitmap.c             | 96 ++++++++++++-----------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 110 insertions(+), 101 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 788b9944467..55fef30f8ae 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,7 +332,7 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -827,20 +827,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult.blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (!entry->matchResult->lossy &&
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (!entry->matchResult.lossy &&
 					entry->offset >= entry->matchTupleOffsets.ntuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
-
-				if (entry->matchResult == NULL)
+				if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult))
 				{
+					Assert(!BlockNumberIsValid(entry->matchResult.blockno));
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
@@ -853,13 +852,13 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				 * tbm_extract_page_tuple() will set matchTupleOffsets.ntuples
 				 * to the correct number.
 				 */
-				if (!entry->matchResult->lossy)
-					tbm_extract_page_tuple(entry->matchResult,
+				if (!entry->matchResult.lossy)
+					tbm_extract_page_tuple(&entry->matchResult,
 										   &entry->matchTupleOffsets);
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -872,10 +871,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->lossy)
+			if (entry->matchResult.lossy)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -893,7 +892,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			Assert(ntuples > -1);
 
 			/* Skip over any offsets <= advancePast, and return that. */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				Assert(ntuples > 0);
 
@@ -914,7 +913,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
+						   entry->matchResult.blockno,
 						   offsets[entry->offset]);
 			entry->offset++;
 
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index bce6042a51c..31256b62cfd 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->matchTupleOffsets.ntuples = -1;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index cf258d7ede2..663660f38f0 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 	TBMPageOffsets offsets;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
@@ -2141,9 +2141,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
-
-		if (tbmres == NULL)
+		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
 			return false;
 
 		/*
@@ -2151,8 +2149,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
 		 * number.
 		 */
-		if (!tbmres->lossy)
-			tbm_extract_page_tuple(tbmres, &offsets);
+		if (!tbmres.lossy)
+			tbm_extract_page_tuple(&tbmres, &offsets);
 
 		/*
 		 * Ignore any claimed entries past what we think is the end of the
@@ -2163,11 +2161,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2175,11 +2173,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres->lossy);
+		Assert(!tbmres.lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 		Assert(offsets.ntuples > -1);
 
@@ -2188,7 +2186,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2217,7 +2215,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres->lossy)
+	if (!tbmres.lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2281,7 +2279,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->lossy)
+	if (tbmres.lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..3b4ea0f6144 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,18 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
 					/* No more pages to prefetch */
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index b87edba5771..317aaf872cd 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -950,21 +948,28 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If lossy is true, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  result->ntuples is set to -1 when the bitmap is lossy.
- * If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when lossy is true.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.
+ *
+ * Returns false when there are no more pages to scan and true otherwise. When
+ * there are no more pages to scan, tbmres->blockno is set to
+ * InvalidBlockNumber.
+ *
+ * If lossy is true, then the bitmap is "lossy" and failed to remember
+ * the exact tuples to look at on this page --- the caller must examine all
+ * tuples on the page and check if they meet the intended condition. If lossy
+ * is false, the caller must later extract the tuple offsets from the page
+ * pointed to by internal_page with tbm_extract_page_tuple.
+ *
+ * If tbmres->recheck is true, only the indicated tuples need be examined, but
+ * the condition must be rechecked anyway.  (For ease of testing, recheck is
+ * always set true when lossy is true.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+bool
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -1002,12 +1007,12 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			iterator->schunkbit++;
-			return output;
+			return true;
 		}
 	}
 
@@ -1021,16 +1026,17 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return true;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1040,10 +1046,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+bool
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1094,14 +1099,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return true;
 		}
 	}
 
@@ -1109,21 +1114,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return true;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1597,15 +1603,17 @@ tbm_end_iterate(TBMIterator *iterator)
 }
 
 /*
- * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ * Populate the next TBMIterateResult using the shared or private bitmap
+ * iterator. Returns false when there is nothing more to scan.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+bool
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 52f25138080..1e42516e5ab 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 	TBMPageOffsets matchTupleOffsets;
 
 	/* used for Posting list and one page in Posting tree */
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 943d163bf35..09d73410e29 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -113,8 +113,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -125,7 +125,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern bool tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v32-0002-Delay-extraction-of-TIDBitmap-per-page-offsets.patchtext/x-patch; charset=US-ASCII; name=v32-0002-Delay-extraction-of-TIDBitmap-per-page-offsets.patchDownload
From 0d6191b5004db7ae0a425babfba1436507c7a48c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 11:02:45 -0500
Subject: [PATCH v32 2/5] Delay extraction of TIDBitmap per page offsets

Pages from the bitmap created by the TIDBitmap API can be exact or
lossy. Exact pages extract all the tuple offsets from the bitmap and put
them in an array for the convenience of the caller.

This was done in tbm_private|shared_iterate(). However, as long as
tbm_private|shared_iterate() set a reference to the PagetableEntry in
the TBMIterateResult, the offset extraction can be done later.

Waiting to extract the tuple offsets has a few benefits. For the shared
iterator case, it allows us to extract the offsets after dropping the
shared iterator state lock, reducing time spent holding a contended
lock.

Separating the iteration step and extracting the offsets later also
allows us to avoid extracting the offsets for prefetched blocks. Those
offsets were never used, so the overhead of extracting and storing them
was wasted.

The real motivation for this change, however, is that future commits
will make bitmap heap scan use the read stream API. This requires a
TBMIterateResult per issued block. By removing the array of tuple
offsets from the TBMIterateResult and only extracting the offsets when
they are used, we reduce the memory required for per buffer data
substantially.

Suggested-by: Thomas Munro <thomas.munro@gmail.com>
Reviewed-by: Thomas Munro <thomas.munro@gmail.com>
Discussion: https://postgr.es/m/CA%2BhUKGLHbKP3jwJ6_%2BhnGi37Pw3BD5j2amjV3oSk7j-KyCnY7Q%40mail.gmail.com
---
 src/backend/access/gin/ginget.c          | 36 +++++++++++-----
 src/backend/access/gin/ginscan.c         |  1 +
 src/backend/access/heap/heapam_handler.c | 19 +++++++--
 src/backend/nodes/tidbitmap.c            | 52 ++++++++----------------
 src/include/access/gin_private.h         |  1 +
 src/include/nodes/tidbitmap.h            | 44 +++++++++++++++++---
 src/tools/pgindent/typedefs.list         |  1 +
 7 files changed, 102 insertions(+), 52 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 54aecc1d1f1..788b9944467 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -822,13 +822,16 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 
 		for (;;)
 		{
+			OffsetNumber *offsets = NULL;
+			int32		ntuples = -1;
+
 			/*
 			 * If we've exhausted all items on this block, move to next block
 			 * in the bitmap.
 			 */
 			while (entry->matchResult == NULL ||
 				   (!entry->matchResult->lossy &&
-					entry->offset >= entry->matchResult->ntuples) ||
+					entry->offset >= entry->matchTupleOffsets.ntuples) ||
 				   entry->matchResult->blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
@@ -845,6 +848,15 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 					break;
 				}
 
+				/*
+				 * Exact pages need their tuple offsets extracted.
+				 * tbm_extract_page_tuple() will set matchTupleOffsets.ntuples
+				 * to the correct number.
+				 */
+				if (!entry->matchResult->lossy)
+					tbm_extract_page_tuple(entry->matchResult,
+										   &entry->matchTupleOffsets);
+
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
 				 * entry->offset is still greater than matchResult->ntuples if
@@ -873,33 +885,37 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				break;
 			}
 
-			/*
-			 * Not a lossy page. Skip over any offsets <= advancePast, and
-			 * return that.
-			 */
+			/* Not a lossy page. */
+			offsets = entry->matchTupleOffsets.offsets;
+			ntuples = entry->matchTupleOffsets.ntuples;
+
+			/* If tuple offsets were extracted, ntuples must be > -1 */
+			Assert(ntuples > -1);
+
+			/* Skip over any offsets <= advancePast, and return that. */
 			if (entry->matchResult->blockno == advancePastBlk)
 			{
-				Assert(entry->matchResult->ntuples > 0);
+				Assert(ntuples > 0);
 
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (offsets[ntuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = ntuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (offsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
 						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   offsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..bce6042a51c 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -107,6 +107,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
 	scanEntry->matchResult = NULL;
+	scanEntry->matchTupleOffsets.ntuples = -1;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 269d581c2ec..cf258d7ede2 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2127,6 +2127,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
+	TBMPageOffsets offsets;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
 
@@ -2145,6 +2146,14 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (tbmres == NULL)
 			return false;
 
+		/*
+		 * Exact pages need their tuple offsets extracted.
+		 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
+		 * number.
+		 */
+		if (!tbmres->lossy)
+			tbm_extract_page_tuple(tbmres, &offsets);
+
 		/*
 		 * Ignore any claimed entries past what we think is the end of the
 		 * relation. It may have been extended after the start of our scan (we
@@ -2172,8 +2181,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		/* can't be lossy in the skip_fetch case */
 		Assert(!tbmres->lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
+		Assert(offsets.ntuples > -1);
 
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += offsets.ntuples;
 
 		return true;
 	}
@@ -2216,9 +2226,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		/* We must have extracted the tuple offsets by now */
+		Assert(offsets.ntuples > -1);
+
+		for (curslot = 0; curslot < offsets.ntuples; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = offsets.offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3e0bca651f5..b87edba5771 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as TBM_MAX_TUPLES_PER_PAGE, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((TBM_MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > TBM_MAX_TUPLES_PER_PAGE)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,9 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -906,11 +895,13 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm)
 /*
  * tbm_extract_page_tuple - extract the tuple offsets from a page
  *
- * The extracted offsets are stored into TBMIterateResult.
+ * Sets ntuples in the TBMPageOffsets
  */
-static inline int
-tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
+void
+tbm_extract_page_tuple(TBMIterateResult *iteritem,
+					   TBMPageOffsets *page_offsets)
 {
+	PagetableEntry *page = iteritem->internal_page;
 	int			wordnum;
 	int			ntuples = 0;
 
@@ -925,14 +916,14 @@ tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
 			while (w != 0)
 			{
 				if (w & 1)
-					output->offsets[ntuples++] = (OffsetNumber) off;
+					page_offsets->offsets[ntuples++] = (OffsetNumber) off;
 				off++;
 				w >>= 1;
 			}
 		}
 	}
 
-	return ntuples;
+	page_offsets->ntuples = ntuples;
 }
 
 /*
@@ -1012,9 +1003,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		{
 			/* Return a lossy page indicator from the chunk */
 			output->blockno = chunk_blockno;
-			output->ntuples = -1;
 			output->lossy = true;
 			output->recheck = true;
+			output->internal_page = NULL;
 			iterator->schunkbit++;
 			return output;
 		}
@@ -1023,7 +1014,6 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 	if (iterator->spageptr < tbm->npages)
 	{
 		PagetableEntry *page;
-		int			ntuples;
 
 		/* In TBM_ONE_PAGE state, we don't allocate an spages[] array */
 		if (tbm->status == TBM_ONE_PAGE)
@@ -1031,10 +1021,8 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
+		output->internal_page = page;
 		output->blockno = page->blockno;
-		output->ntuples = ntuples;
 		output->lossy = false;
 		output->recheck = page->recheck;
 		iterator->spageptr++;
@@ -1107,9 +1095,9 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		{
 			/* Return a lossy page indicator from the chunk */
 			output->blockno = chunk_blockno;
-			output->ntuples = -1;
 			output->lossy = true;
 			output->recheck = true;
+			output->internal_page = NULL;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
@@ -1120,12 +1108,9 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	if (istate->spageptr < istate->npages)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
-		int			ntuples;
 
-		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
+		output->internal_page = page;
 		output->blockno = page->blockno;
-		output->ntuples = ntuples;
 		output->lossy = false;
 		output->recheck = page->recheck;
 		istate->spageptr++;
@@ -1473,8 +1458,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..52f25138080 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -354,6 +354,7 @@ typedef struct GinScanEntryData
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
+	TBMPageOffsets matchTupleOffsets;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 8cd93d90a86..943d163bf35 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,9 +22,17 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
+/*
+ * The maximum number of tuples per page is not large (typically 256 with
+ * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+ * the per-page bitmaps variable size.  We just legislate that the size
+ * is this:
+ */
+#define TBM_MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
 
 /*
  * Actual bitmap representation is private to tidbitmap.c.  Callers can
@@ -53,14 +61,37 @@ typedef struct TBMIterator
 /* Result structure for tbm_iterate */
 typedef struct TBMIterateResult
 {
-	BlockNumber blockno;		/* page number containing tuples */
-	int			ntuples;		/* -1 when lossy */
+	BlockNumber blockno;		/* block number containing tuples */
+
 	bool		lossy;
-	bool		recheck;		/* should the tuples be rechecked? */
-	/* Note: recheck is always true if lossy */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+
+	/*
+	 * Whether or not the tuples should be rechecked. This is always true if
+	 * the page is lossy but may also be true if the query requires recheck.
+	 */
+	bool		recheck;
+
+	/*
+	 * Pointer to the page containing the bitmap for this block. It is a void *
+	 * to avoid exposing the details of the tidbitmap PagetableEntry to API
+	 * users.
+	 */
+	void	   *internal_page;
 } TBMIterateResult;
 
+/*
+ * The tuple OffsetNumbers extracted from a single page in the bitmap.
+ */
+typedef struct TBMPageOffsets
+{
+	/*
+	 * -1 indicates an exact page whose tuple offsets have yet to be extracted
+	 * from the bitmap.
+	 */
+	int32		ntuples;
+	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+} TBMPageOffsets;
+
 /* function prototypes in nodes/tidbitmap.c */
 
 extern TIDBitmap *tbm_create(Size maxbytes, dsa_area *dsa);
@@ -75,6 +106,9 @@ extern void tbm_add_page(TIDBitmap *tbm, BlockNumber pageno);
 extern void tbm_union(TIDBitmap *a, const TIDBitmap *b);
 extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
+extern void tbm_extract_page_tuple(TBMIterateResult *iteritem,
+								   TBMPageOffsets *offsets);
+
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index b09d8af7183..d2974ef9356 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2843,6 +2843,7 @@ TAR_MEMBER
 TBMIterateResult
 TBMIteratingState
 TBMIterator
+TBMPageOffsets
 TBMPrivateIterator
 TBMSharedIterator
 TBMSharedIteratorState
-- 
2.34.1

#214Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#213)
5 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Feb 21, 2025 at 5:00 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I thought about doing this, but in the end I decided against this
approach. If we wanted to make it easy to palloc arrays of different
sizes and have tbm_extract_page_tuple extract that many tuples into
the array, we'd have to change more of the code anyway because
tbm_extract_page_tuple is what tells us how many tuples there are to
begin with. We could save this somewhere while filling in the
PagetableEntries initially, but that is a bigger change.

And, passing a length would also mean more callers would have to know
about TBM_MAX_TUPLES_PER_PAGE, which I think is already kind of a hack
since it is defined as MaxHeapTuplesPerPage.

I changed my mind. I think since the struct I added was only used for
tbm_extract_page_tuple(), it was a bit weird. I also think it is okay
for callers to use TBM_MAX_TUPLES_PER_PAGE. I ended up revising this
to use the same API you implemented for TIDStore in
TidStoreGetBlockOffsets(). The caller passes an array and the size of
the array and tbm_extract_page_tuple() fills in that many offsets and
returns the total number of offsets. It avoids adding a new struct and
means callers could pass a different value than
TBM_MAX_TUPLES_PER_PAGE. Overall, I like it.

- Melanie

Attachments:

v33-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v33-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From 081fee44b0a3e39f54d35b1f67b3c96fd9a1c553 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:30:26 -0500
Subject: [PATCH v33 3/5] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This allows tidbitmap API users to manage multiple TBMIterateResults per
scan. This is required for bitmap heap scan to use the read stream API,
with which there may be multiple I/Os in flight at once, each one with a
TBMIterateResult.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/gin/ginget.c           | 33 ++++----
 src/backend/access/gin/ginscan.c          |  3 +-
 src/backend/access/heap/heapam_handler.c  | 28 +++----
 src/backend/executor/nodeBitmapHeapscan.c | 39 +++++----
 src/backend/nodes/tidbitmap.c             | 96 ++++++++++++-----------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 111 insertions(+), 101 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index f3b19d280c3..791bc70ec26 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,8 +332,8 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->matchNtuples = -1;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -825,20 +825,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult.blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (!entry->matchResult->lossy &&
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (!entry->matchResult.lossy &&
 					entry->offset >= entry->matchNtuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
-
-				if (entry->matchResult == NULL)
+				if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult))
 				{
+					Assert(!BlockNumberIsValid(entry->matchResult.blockno));
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
@@ -847,14 +846,14 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				}
 
 				/* Exact pages need their tuple offsets extracted. */
-				if (!entry->matchResult->lossy)
-					entry->matchNtuples = tbm_extract_page_tuple(entry->matchResult,
+				if (!entry->matchResult.lossy)
+					entry->matchNtuples = tbm_extract_page_tuple(&entry->matchResult,
 																 entry->matchOffsets,
 																 TBM_MAX_TUPLES_PER_PAGE);
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than entry->matchNtuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -867,10 +866,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->lossy)
+			if (entry->matchResult.lossy)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -887,7 +886,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			Assert(entry->matchNtuples > -1);
 
 			/* Skip over any offsets <= advancePast, and return that. */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				Assert(entry->matchNtuples > 0);
 
@@ -908,7 +907,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
+						   entry->matchResult.blockno,
 						   entry->matchOffsets[entry->offset]);
 			entry->offset++;
 
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..f033417e5a8 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,8 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
+	scanEntry->matchNtuples = -1;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
 	scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e78682c3cef..ff1d8085883 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			noffsets = -1;
 
@@ -2142,14 +2142,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
-
-		if (tbmres == NULL)
+		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
 			return false;
 
 		/* Exact pages need their tuple offsets extracted. */
-		if (!tbmres->lossy)
-			noffsets = tbm_extract_page_tuple(tbmres, offsets,
+		if (!tbmres.lossy)
+			noffsets = tbm_extract_page_tuple(&tbmres, offsets,
 											  TBM_MAX_TUPLES_PER_PAGE);
 
 		/*
@@ -2161,11 +2159,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2173,11 +2171,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres->lossy);
+		Assert(!tbmres.lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 		Assert(noffsets > -1);
 
@@ -2186,7 +2184,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2215,7 +2213,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres->lossy)
+	if (!tbmres.lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,7 +2277,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->lossy)
+	if (tbmres.lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..3b4ea0f6144 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,18 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
 					/* No more pages to prefetch */
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3d835024caa..41031aa8f2f 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -957,21 +955,28 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If lossy is true, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  result->ntuples is set to -1 when the bitmap is lossy.
- * If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when lossy is true.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.
+ *
+ * Returns false when there are no more pages to scan and true otherwise. When
+ * there are no more pages to scan, tbmres->blockno is set to
+ * InvalidBlockNumber.
+ *
+ * If lossy is true, then the bitmap is "lossy" and failed to remember
+ * the exact tuples to look at on this page --- the caller must examine all
+ * tuples on the page and check if they meet the intended condition. If lossy
+ * is false, the caller must later extract the tuple offsets from the page
+ * pointed to by internal_page with tbm_extract_page_tuple.
+ *
+ * If tbmres->recheck is true, only the indicated tuples need be examined, but
+ * the condition must be rechecked anyway.  (For ease of testing, recheck is
+ * always set true when lossy is true.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+bool
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -1009,12 +1014,12 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			iterator->schunkbit++;
-			return output;
+			return true;
 		}
 	}
 
@@ -1028,16 +1033,17 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return true;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1047,10 +1053,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+bool
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1101,14 +1106,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return true;
 		}
 	}
 
@@ -1116,21 +1121,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return true;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1604,15 +1610,17 @@ tbm_end_iterate(TBMIterator *iterator)
 }
 
 /*
- * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ * Populate the next TBMIterateResult using the shared or private bitmap
+ * iterator. Returns false when there is nothing more to scan.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+bool
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 50478db9820..82d2c28583e 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 	OffsetNumber matchOffsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			matchNtuples;
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index e185635c10b..99f795ceab5 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -101,8 +101,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -113,7 +113,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern bool tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v33-0004-BitmapHeapScan-uses-the-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v33-0004-BitmapHeapScan-uses-the-read-stream-API.patchDownload
From 0305ae391c883dfea7482cdeff2c9abe131c4cd0 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:15:47 -0500
Subject: [PATCH v33 4/5] BitmapHeapScan uses the read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam.c          |  80 +++++
 src/backend/access/heap/heapam_handler.c  |  95 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 341 +---------------------
 src/include/access/tableam.h              |  25 +-
 src/include/nodes/execnodes.h             |  23 +-
 5 files changed, 130 insertions(+), 434 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index fa7935a0ed3..65e44b25b74 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,72 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		/* no more entries in the bitmap */
+		if (!tbm_iterate(&sscan->st.rs_tbmiterator, tbmres))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+			int			noffsets;
+
+			/* can't be lossy in the skip_fetch case */
+			Assert(!tbmres->lossy);
+			Assert(bscan->rs_empty_tuples_pending >= 0);
+
+			/*
+			 * We throw away the offsets, but this is the easiest way to get a
+			 * count of tuples.
+			 */
+			noffsets = tbm_extract_page_tuple(tbmres, offsets, TBM_MAX_TUPLES_PER_PAGE);
+			bscan->rs_empty_tuples_pending += noffsets;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1133,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1213,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1257,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ff1d8085883..4734283a9a9 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2117,82 +2117,79 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			noffsets = -1;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
-			return false;
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
 
-		/* Exact pages need their tuple offsets extracted. */
-		if (!tbmres.lossy)
-			noffsets = tbm_extract_page_tuple(&tbmres, offsets,
-											  TBM_MAX_TUPLES_PER_PAGE);
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
 	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
+	 * Exact pages need their tuple offsets extracted.
+	 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
+	 * number.
 	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres.lossy);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
-		Assert(noffsets > -1);
+	if (!tbmres->lossy)
+		noffsets = tbm_extract_page_tuple(tbmres, offsets,
+										  TBM_MAX_TUPLES_PER_PAGE);
 
-		bscan->rs_empty_tuples_pending += noffsets;
+	*recheck = tbmres->recheck;
 
-		return true;
-	}
-
-	block = tbmres.blockno;
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = noffsets;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2213,7 +2210,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres.lossy)
+	if (!tbmres->lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2277,7 +2274,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.lossy)
+	if (tbmres->lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3b4ea0f6144..6df34094a13 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -158,7 +129,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +142,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -204,37 +170,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -257,31 +192,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,225 +224,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					/* No more pages to prefetch */
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -580,24 +280,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -666,17 +354,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -709,18 +391,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -760,13 +437,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -870,12 +540,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -912,17 +579,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..507d4ebe68f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -1966,16 +1950,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1968,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a323fa98bbb..5f743d6699c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1828,11 +1828,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1840,10 +1836,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1867,18 +1860,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1886,18 +1872,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v33-0001-Add-lossy-indicator-to-TBMIterateResult.patchtext/x-patch; charset=US-ASCII; name=v33-0001-Add-lossy-indicator-to-TBMIterateResult.patchDownload
From c3ae01de0ded48590995115065889f1613bf458f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 10:58:59 -0500
Subject: [PATCH v33 1/5] Add lossy indicator to TBMIterateResult

TBMIterateResult->ntuples is -1 when the page in the bitmap is lossy.
Add an explicit lossy indicator so that we can move ntuples out of the
TBMIterateResult in a future commit.
---
 src/backend/access/gin/ginget.c          |  6 ++++--
 src/backend/access/heap/heapam_handler.c | 10 +++++-----
 src/backend/nodes/tidbitmap.c            | 11 ++++++++---
 src/include/nodes/tidbitmap.h            |  5 +++--
 4 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 63dd1f3679f..54aecc1d1f1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -827,7 +827,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * in the bitmap.
 			 */
 			while (entry->matchResult == NULL ||
-				   (entry->matchResult->ntuples >= 0 &&
+				   (!entry->matchResult->lossy &&
 					entry->offset >= entry->matchResult->ntuples) ||
 				   entry->matchResult->blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
@@ -860,7 +860,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->ntuples < 0)
+			if (entry->matchResult->lossy)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
 										entry->matchResult->blockno);
@@ -879,6 +879,8 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 */
 			if (entry->matchResult->blockno == advancePastBlk)
 			{
+				Assert(entry->matchResult->ntuples > 0);
+
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index c0bec014154..269d581c2ec 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2170,7 +2170,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(tbmres->ntuples >= 0);
+		Assert(!tbmres->lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 
 		bscan->rs_empty_tuples_pending += tbmres->ntuples;
@@ -2207,7 +2207,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (tbmres->ntuples >= 0)
+	if (!tbmres->lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2268,10 +2268,10 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->ntuples >= 0)
-		(*exact_pages)++;
-	else
+	if (tbmres->lossy)
 		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
 
 	/*
 	 * Return true to indicate that a valid block was found and the bitmap is
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 66b3c387d53..3e0bca651f5 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -961,12 +961,13 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  *
  * Returns a TBMIterateResult representing one page, or NULL if there are
  * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If result->ntuples < 0, then the bitmap is "lossy" and failed to
+ * order.  If lossy is true, then the bitmap is "lossy" and failed to
  * remember the exact tuples to look at on this page --- the caller must
  * examine all tuples on the page and check if they meet the intended
- * condition.  If result->recheck is true, only the indicated tuples need
+ * condition.  result->ntuples is set to -1 when the bitmap is lossy.
+ * If result->recheck is true, only the indicated tuples need
  * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when ntuples < 0.)
+ * testing, recheck is always set true when lossy is true.)
  */
 TBMIterateResult *
 tbm_private_iterate(TBMPrivateIterator *iterator)
@@ -1012,6 +1013,7 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			/* Return a lossy page indicator from the chunk */
 			output->blockno = chunk_blockno;
 			output->ntuples = -1;
+			output->lossy = true;
 			output->recheck = true;
 			iterator->schunkbit++;
 			return output;
@@ -1033,6 +1035,7 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		ntuples = tbm_extract_page_tuple(page, output);
 		output->blockno = page->blockno;
 		output->ntuples = ntuples;
+		output->lossy = false;
 		output->recheck = page->recheck;
 		iterator->spageptr++;
 		return output;
@@ -1105,6 +1108,7 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			/* Return a lossy page indicator from the chunk */
 			output->blockno = chunk_blockno;
 			output->ntuples = -1;
+			output->lossy = true;
 			output->recheck = true;
 			istate->schunkbit++;
 
@@ -1122,6 +1126,7 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		ntuples = tbm_extract_page_tuple(page, output);
 		output->blockno = page->blockno;
 		output->ntuples = ntuples;
+		output->lossy = false;
 		output->recheck = page->recheck;
 		istate->spageptr++;
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index a6ffeac90be..8cd93d90a86 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -54,9 +54,10 @@ typedef struct TBMIterator
 typedef struct TBMIterateResult
 {
 	BlockNumber blockno;		/* page number containing tuples */
-	int			ntuples;		/* -1 indicates lossy result */
+	int			ntuples;		/* -1 when lossy */
+	bool		lossy;
 	bool		recheck;		/* should the tuples be rechecked? */
-	/* Note: recheck is always true if ntuples < 0 */
+	/* Note: recheck is always true if lossy */
 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
 } TBMIterateResult;
 
-- 
2.34.1

v33-0002-Delay-extraction-of-TIDBitmap-per-page-offsets.patchtext/x-patch; charset=US-ASCII; name=v33-0002-Delay-extraction-of-TIDBitmap-per-page-offsets.patchDownload
From e364c7afa95819c67ccb101e9f35dad33f9f996b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 11:02:45 -0500
Subject: [PATCH v33 2/5] Delay extraction of TIDBitmap per page offsets

Pages from the bitmap created by the TIDBitmap API can be exact or
lossy. Exact pages extract all the tuple offsets from the bitmap and put
them in an array for the convenience of the caller.

This was done in tbm_private|shared_iterate(). However, as long as
tbm_private|shared_iterate() set a reference to the PagetableEntry in
the TBMIterateResult, the offset extraction can be done later.

Waiting to extract the tuple offsets has a few benefits. For the shared
iterator case, it allows us to extract the offsets after dropping the
shared iterator state lock, reducing time spent holding a contended
lock.

Separating the iteration step and extracting the offsets later also
allows us to avoid extracting the offsets for prefetched blocks. Those
offsets were never used, so the overhead of extracting and storing them
was wasted.

The real motivation for this change, however, is that future commits
will make bitmap heap scan use the read stream API. This requires a
TBMIterateResult per issued block. By removing the array of tuple
offsets from the TBMIterateResult and only extracting the offsets when
they are used, we reduce the memory required for per buffer data
substantially.

Suggested-by: Thomas Munro <thomas.munro@gmail.com>
Reviewed-by: Thomas Munro <thomas.munro@gmail.com>
Discussion: https://postgr.es/m/CA%2BhUKGLHbKP3jwJ6_%2BhnGi37Pw3BD5j2amjV3oSk7j-KyCnY7Q%40mail.gmail.com
---
 src/backend/access/gin/ginget.c          | 28 ++++++++----
 src/backend/access/heap/heapam_handler.c | 17 +++++--
 src/backend/nodes/tidbitmap.c            | 57 ++++++++++--------------
 src/include/access/gin_private.h         |  2 +
 src/include/nodes/tidbitmap.h            | 32 ++++++++++---
 5 files changed, 86 insertions(+), 50 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 54aecc1d1f1..f3b19d280c3 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -333,6 +333,7 @@ restartScanEntry:
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
 	entry->matchResult = NULL;
+	entry->matchNtuples = -1;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -828,7 +829,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 */
 			while (entry->matchResult == NULL ||
 				   (!entry->matchResult->lossy &&
-					entry->offset >= entry->matchResult->ntuples) ||
+					entry->offset >= entry->matchNtuples) ||
 				   entry->matchResult->blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
 					entry->matchResult->blockno == advancePastBlk))
@@ -845,9 +846,15 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 					break;
 				}
 
+				/* Exact pages need their tuple offsets extracted. */
+				if (!entry->matchResult->lossy)
+					entry->matchNtuples = tbm_extract_page_tuple(entry->matchResult,
+																 entry->matchOffsets,
+																 TBM_MAX_TUPLES_PER_PAGE);
+
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than matchResult->ntuples if
+				 * entry->offset is still greater than entry->matchNtuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -874,32 +881,35 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			}
 
 			/*
-			 * Not a lossy page. Skip over any offsets <= advancePast, and
-			 * return that.
+			 * Not a lossy page. If tuple offsets were extracted,
+			 * entry->matchNtuples must be > -1
 			 */
+			Assert(entry->matchNtuples > -1);
+
+			/* Skip over any offsets <= advancePast, and return that. */
 			if (entry->matchResult->blockno == advancePastBlk)
 			{
-				Assert(entry->matchResult->ntuples > 0);
+				Assert(entry->matchNtuples > 0);
 
 				/*
 				 * First, do a quick check against the last offset on the
 				 * page. If that's > advancePast, so are all the other
 				 * offsets, so just go back to the top to get the next page.
 				 */
-				if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+				if (entry->matchOffsets[entry->matchNtuples - 1] <= advancePastOff)
 				{
-					entry->offset = entry->matchResult->ntuples;
+					entry->offset = entry->matchNtuples;
 					continue;
 				}
 
 				/* Otherwise scan to find the first item > advancePast */
-				while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+				while (entry->matchOffsets[entry->offset] <= advancePastOff)
 					entry->offset++;
 			}
 
 			ItemPointerSet(&entry->curItem,
 						   entry->matchResult->blockno,
-						   entry->matchResult->offsets[entry->offset]);
+						   entry->matchOffsets[entry->offset]);
 			entry->offset++;
 
 			/* Done unless we need to reduce the result */
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 269d581c2ec..e78682c3cef 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2127,6 +2127,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Snapshot	snapshot;
 	int			ntup;
 	TBMIterateResult *tbmres;
+	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+	int			noffsets = -1;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
 
@@ -2145,6 +2147,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		if (tbmres == NULL)
 			return false;
 
+		/* Exact pages need their tuple offsets extracted. */
+		if (!tbmres->lossy)
+			noffsets = tbm_extract_page_tuple(tbmres, offsets,
+											  TBM_MAX_TUPLES_PER_PAGE);
+
 		/*
 		 * Ignore any claimed entries past what we think is the end of the
 		 * relation. It may have been extended after the start of our scan (we
@@ -2172,8 +2179,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		/* can't be lossy in the skip_fetch case */
 		Assert(!tbmres->lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
+		Assert(noffsets > -1);
 
-		bscan->rs_empty_tuples_pending += tbmres->ntuples;
+		bscan->rs_empty_tuples_pending += noffsets;
 
 		return true;
 	}
@@ -2216,9 +2224,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 */
 		int			curslot;
 
-		for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+		/* We must have extracted the tuple offsets by now */
+		Assert(noffsets > -1);
+
+		for (curslot = 0; curslot < noffsets; curslot++)
 		{
-			OffsetNumber offnum = tbmres->offsets[curslot];
+			OffsetNumber offnum = offsets[curslot];
 			ItemPointerData tid;
 			HeapTupleData heapTuple;
 
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3e0bca651f5..3d835024caa 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -40,7 +40,6 @@
 
 #include <limits.h>
 
-#include "access/htup_details.h"
 #include "common/hashfn.h"
 #include "common/int.h"
 #include "nodes/bitmapset.h"
@@ -48,14 +47,6 @@
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
-/*
- * The maximum number of tuples per page is not large (typically 256 with
- * 8K pages, or 1024 with 32K pages).  So there's not much point in making
- * the per-page bitmaps variable size.  We just legislate that the size
- * is this:
- */
-#define MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
-
 /*
  * When we have to switch over to lossy storage, we use a data structure
  * with one bit per page, where all pages having the same number DIV
@@ -67,7 +58,7 @@
  * table, using identical data structures.  (This is because the memory
  * management for hashtables doesn't easily/efficiently allow space to be
  * transferred easily from one hashtable to another.)  Therefore it's best
- * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not
+ * if PAGES_PER_CHUNK is the same as TBM_MAX_TUPLES_PER_PAGE, or at least not
  * too different.  But we also want PAGES_PER_CHUNK to be a power of 2 to
  * avoid expensive integer remainder operations.  So, define it like this:
  */
@@ -79,7 +70,7 @@
 #define BITNUM(x)	((x) % BITS_PER_BITMAPWORD)
 
 /* number of active words for an exact page: */
-#define WORDS_PER_PAGE	((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
+#define WORDS_PER_PAGE	((TBM_MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1)
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
@@ -181,7 +172,7 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /*
@@ -222,7 +213,7 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;	/* MUST BE LAST (because variable-size) */
+	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -390,7 +381,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
 					bitnum;
 
 		/* safety check to ensure we don't overrun bit array bounds */
-		if (off < 1 || off > MAX_TUPLES_PER_PAGE)
+		if (off < 1 || off > TBM_MAX_TUPLES_PER_PAGE)
 			elog(ERROR, "tuple offset out of range: %u", off);
 
 		/*
@@ -696,9 +687,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
-											 MAX_TUPLES_PER_PAGE *
-											 sizeof(OffsetNumber));
+	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
 	iterator->tbm = tbm;
 
 	/*
@@ -906,11 +895,16 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm)
 /*
  * tbm_extract_page_tuple - extract the tuple offsets from a page
  *
- * The extracted offsets are stored into TBMIterateResult.
+ * Returns the number of offsets it filled in if <= max_offsets. Otherwise,
+ * fills in as many offsets as fit and returns the total number of offsets in
+ * the page.
  */
-static inline int
-tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
+int
+tbm_extract_page_tuple(TBMIterateResult *iteritem,
+					   OffsetNumber *offsets,
+					   uint32 max_offsets)
 {
+	PagetableEntry *page = iteritem->internal_page;
 	int			wordnum;
 	int			ntuples = 0;
 
@@ -925,7 +919,11 @@ tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
 			while (w != 0)
 			{
 				if (w & 1)
-					output->offsets[ntuples++] = (OffsetNumber) off;
+				{
+					if (ntuples < max_offsets)
+						offsets[ntuples] = (OffsetNumber) off;
+					ntuples++;
+				}
 				off++;
 				w >>= 1;
 			}
@@ -1012,9 +1010,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		{
 			/* Return a lossy page indicator from the chunk */
 			output->blockno = chunk_blockno;
-			output->ntuples = -1;
 			output->lossy = true;
 			output->recheck = true;
+			output->internal_page = NULL;
 			iterator->schunkbit++;
 			return output;
 		}
@@ -1023,7 +1021,6 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 	if (iterator->spageptr < tbm->npages)
 	{
 		PagetableEntry *page;
-		int			ntuples;
 
 		/* In TBM_ONE_PAGE state, we don't allocate an spages[] array */
 		if (tbm->status == TBM_ONE_PAGE)
@@ -1031,10 +1028,8 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
+		output->internal_page = page;
 		output->blockno = page->blockno;
-		output->ntuples = ntuples;
 		output->lossy = false;
 		output->recheck = page->recheck;
 		iterator->spageptr++;
@@ -1107,9 +1102,9 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 		{
 			/* Return a lossy page indicator from the chunk */
 			output->blockno = chunk_blockno;
-			output->ntuples = -1;
 			output->lossy = true;
 			output->recheck = true;
+			output->internal_page = NULL;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
@@ -1120,12 +1115,9 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	if (istate->spageptr < istate->npages)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
-		int			ntuples;
 
-		/* scan bitmap to extract individual offset numbers */
-		ntuples = tbm_extract_page_tuple(page, output);
+		output->internal_page = page;
 		output->blockno = page->blockno;
-		output->ntuples = ntuples;
 		output->lossy = false;
 		output->recheck = page->recheck;
 		istate->spageptr++;
@@ -1473,8 +1465,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
-											 MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index dcd1ae3fc34..50478db9820 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -354,6 +354,8 @@ typedef struct GinScanEntryData
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
 	TBMIterateResult *matchResult;
+	OffsetNumber matchOffsets[TBM_MAX_TUPLES_PER_PAGE];
+	int			matchNtuples;
 
 	/* used for Posting list and one page in Posting tree */
 	ItemPointerData *list;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 8cd93d90a86..e185635c10b 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -22,9 +22,17 @@
 #ifndef TIDBITMAP_H
 #define TIDBITMAP_H
 
+#include "access/htup_details.h"
 #include "storage/itemptr.h"
 #include "utils/dsa.h"
 
+/*
+ * The maximum number of tuples per page is not large (typically 256 with
+ * 8K pages, or 1024 with 32K pages).  So there's not much point in making
+ * the per-page bitmaps variable size.  We just legislate that the size
+ * is this:
+ */
+#define TBM_MAX_TUPLES_PER_PAGE  MaxHeapTuplesPerPage
 
 /*
  * Actual bitmap representation is private to tidbitmap.c.  Callers can
@@ -53,12 +61,22 @@ typedef struct TBMIterator
 /* Result structure for tbm_iterate */
 typedef struct TBMIterateResult
 {
-	BlockNumber blockno;		/* page number containing tuples */
-	int			ntuples;		/* -1 when lossy */
+	BlockNumber blockno;		/* block number containing tuples */
+
 	bool		lossy;
-	bool		recheck;		/* should the tuples be rechecked? */
-	/* Note: recheck is always true if lossy */
-	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+
+	/*
+	 * Whether or not the tuples should be rechecked. This is always true if
+	 * the page is lossy but may also be true if the query requires recheck.
+	 */
+	bool		recheck;
+
+	/*
+	 * Pointer to the page containing the bitmap for this block. It is a void *
+	 * to avoid exposing the details of the tidbitmap PagetableEntry to API
+	 * users.
+	 */
+	void	   *internal_page;
 } TBMIterateResult;
 
 /* function prototypes in nodes/tidbitmap.c */
@@ -75,6 +93,10 @@ extern void tbm_add_page(TIDBitmap *tbm, BlockNumber pageno);
 extern void tbm_union(TIDBitmap *a, const TIDBitmap *b);
 extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
+extern int	tbm_extract_page_tuple(TBMIterateResult *iteritem,
+								   OffsetNumber *offsets,
+								   uint32 max_offsets);
+
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
-- 
2.34.1

v33-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v33-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 3b8f68ee9705714e9e8977292b53cbd2f7269478 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:32:33 -0500
Subject: [PATCH v33 5/5] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator into table-AM specific code (as part
of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer returns the current block number.
Since scan_bitmap_next_block() isn't returning any relevant information
to bitmap table scan code, it makes more sense to get rid of it.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple(),
and the heap AM implementation of scan_bitmap_next_block() is a local
helper in heapam_handler.c.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam_handler.c  | 386 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   3 -
 src/backend/executor/nodeBitmapHeapscan.c |  73 ++--
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++---
 5 files changed, 251 insertions(+), 303 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 4734283a9a9..8fbf5adca8b 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,10 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,205 +2120,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
-	int			noffsets = -1;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
-											 &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BlockNumberIsValid(tbmres->blockno));
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	/*
-	 * Exact pages need their tuple offsets extracted.
-	 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
-	 * number.
-	 */
-	if (!tbmres->lossy)
-		noffsets = tbm_extract_page_tuple(tbmres, offsets,
-										  TBM_MAX_TUPLES_PER_PAGE);
-
-	*recheck = tbmres->recheck;
-
-	hscan->rs_cblock = tbmres->blockno;
-	hscan->rs_ntuples = noffsets;
-
-	block = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (!tbmres->lossy)
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		int			curslot;
-
-		/* We must have extracted the tuple offsets by now */
-		Assert(noffsets > -1);
-
-		for (curslot = 0; curslot < noffsets; curslot++)
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			OffsetNumber offnum = offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
-	{
-		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
-		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
-		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
-
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->lossy)
-		(*lossy_pages)++;
-	else
-		(*exact_pages)++;
 
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
-
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2621,6 +2464,184 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+	int			noffsets = -1;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	/*
+	 * Exact pages need their tuple offsets extracted.
+	 * tbm_extract_page_tuple() will set offsets.ntuples to the correct
+	 * number.
+	 */
+	if (!tbmres->lossy)
+		noffsets = tbm_extract_page_tuple(tbmres, offsets,
+										  TBM_MAX_TUPLES_PER_PAGE);
+
+	*recheck = tbmres->recheck;
+
+	hscan->rs_cblock = tbmres->blockno;
+	hscan->rs_ntuples = noffsets;
+
+	block = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (!tbmres->lossy)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		/* We must have extracted the tuple offsets by now */
+		Assert(noffsets > -1);
+
+		for (curslot = 0; curslot < noffsets; curslot++)
+		{
+			OffsetNumber offnum = offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->lossy)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2680,7 +2701,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..476663b66aa 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6df34094a13..3e33360c0fc 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -138,69 +138,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-
-			CHECK_FOR_INTERRUPTS();
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 507d4ebe68f..b8cb1e744ad 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. These are tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1939,51 +1919,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1994,7 +1947,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

#215Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#214)
3 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Feb 24, 2025 at 11:18 AM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I changed my mind. I think since the struct I added was only used for
tbm_extract_page_tuple(), it was a bit weird. I also think it is okay
for callers to use TBM_MAX_TUPLES_PER_PAGE. I ended up revising this
to use the same API you implemented for TIDStore in
TidStoreGetBlockOffsets(). The caller passes an array and the size of
the array and tbm_extract_page_tuple() fills in that many offsets and
returns the total number of offsets. It avoids adding a new struct and
means callers could pass a different value than
TBM_MAX_TUPLES_PER_PAGE. Overall, I like it.

Okay, I've pushed those patches. All that remains in attached v34 are
the patches to implement using the read stream API. I'll wait to push
until the patches to modify the read stream API sequential detection
are in.

I was thinking about what the default value should be for
effective_io_concurrency, and I looked back at Tomas' results. It
definitely should be > 1. But, there are cases where 16 is a
regression. So, perhaps it would be good to run some tests trying out
4 and 8 once we have a fixed up sequential detection algorithm.

- Melanie

Attachments:

v34-0002-BitmapHeapScan-uses-the-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v34-0002-BitmapHeapScan-uses-the-read-stream-API.patchDownload
From 6cf32ed8b43492e6b47a6470ccdea7d09e2db481 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:15:47 -0500
Subject: [PATCH v34 2/3] BitmapHeapScan uses the read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam.c          |  80 +++++
 src/backend/access/heap/heapam_handler.c  |  90 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 341 +---------------------
 src/include/access/tableam.h              |  25 +-
 src/include/nodes/execnodes.h             |  23 +-
 5 files changed, 124 insertions(+), 435 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index fa7935a0ed3..65e44b25b74 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,72 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		/* no more entries in the bitmap */
+		if (!tbm_iterate(&sscan->st.rs_tbmiterator, tbmres))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+			int			noffsets;
+
+			/* can't be lossy in the skip_fetch case */
+			Assert(!tbmres->lossy);
+			Assert(bscan->rs_empty_tuples_pending >= 0);
+
+			/*
+			 * We throw away the offsets, but this is the easiest way to get a
+			 * count of tuples.
+			 */
+			noffsets = tbm_extract_page_tuple(tbmres, offsets, TBM_MAX_TUPLES_PER_PAGE);
+			bscan->rs_empty_tuples_pending += noffsets;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1133,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1213,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1257,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ff1d8085883..0f7dd79f28e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2117,82 +2117,72 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			noffsets = -1;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
-			return false;
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
 
-		/* Exact pages need their tuple offsets extracted. */
-		if (!tbmres.lossy)
-			noffsets = tbm_extract_page_tuple(&tbmres, offsets,
-											  TBM_MAX_TUPLES_PER_PAGE);
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres.lossy);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
-		Assert(noffsets > -1);
+	tbmres = per_buffer_data;
 
-		bscan->rs_empty_tuples_pending += noffsets;
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	/* Exact pages need their tuple offsets extracted. */
+	if (!tbmres->lossy)
+		noffsets = tbm_extract_page_tuple(tbmres, offsets,
+										  TBM_MAX_TUPLES_PER_PAGE);
 
-	block = tbmres.blockno;
+	*recheck = tbmres->recheck;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = hscan->rs_cblock = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2213,7 +2203,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres.lossy)
+	if (!tbmres->lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2277,7 +2267,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.lossy)
+	if (tbmres->lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3b4ea0f6144..6df34094a13 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -158,7 +129,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +142,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -204,37 +170,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -257,31 +192,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,225 +224,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					/* No more pages to prefetch */
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -580,24 +280,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -666,17 +354,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -709,18 +391,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -760,13 +437,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -870,12 +540,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -912,17 +579,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..507d4ebe68f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -1966,16 +1950,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1968,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a323fa98bbb..5f743d6699c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1828,11 +1828,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1840,10 +1836,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1867,18 +1860,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1886,18 +1872,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v34-0001-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v34-0001-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From 4965e11fedbd22cc05643b72acb4325a0a1b1654 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:30:26 -0500
Subject: [PATCH v34 1/3] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This allows tidbitmap API users to manage multiple TBMIterateResults per
scan. This is required for bitmap heap scan to use the read stream API,
with which there may be multiple I/Os in flight at once, each one with a
TBMIterateResult.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/gin/ginget.c           | 33 ++++----
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 28 +++----
 src/backend/executor/nodeBitmapHeapscan.c | 39 +++++----
 src/backend/nodes/tidbitmap.c             | 96 ++++++++++++-----------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 110 insertions(+), 101 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index f3b19d280c3..791bc70ec26 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,8 +332,8 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->matchNtuples = -1;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -825,20 +825,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult.blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (!entry->matchResult->lossy &&
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (!entry->matchResult.lossy &&
 					entry->offset >= entry->matchNtuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
-
-				if (entry->matchResult == NULL)
+				if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult))
 				{
+					Assert(!BlockNumberIsValid(entry->matchResult.blockno));
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
@@ -847,14 +846,14 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				}
 
 				/* Exact pages need their tuple offsets extracted. */
-				if (!entry->matchResult->lossy)
-					entry->matchNtuples = tbm_extract_page_tuple(entry->matchResult,
+				if (!entry->matchResult.lossy)
+					entry->matchNtuples = tbm_extract_page_tuple(&entry->matchResult,
 																 entry->matchOffsets,
 																 TBM_MAX_TUPLES_PER_PAGE);
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than entry->matchNtuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -867,10 +866,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->lossy)
+			if (entry->matchResult.lossy)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -887,7 +886,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			Assert(entry->matchNtuples > -1);
 
 			/* Skip over any offsets <= advancePast, and return that. */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				Assert(entry->matchNtuples > 0);
 
@@ -908,7 +907,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
+						   entry->matchResult.blockno,
 						   entry->matchOffsets[entry->offset]);
 			entry->offset++;
 
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 63ded6301e2..f033417e5a8 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -106,7 +106,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->matchNtuples = -1;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e78682c3cef..ff1d8085883 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			noffsets = -1;
 
@@ -2142,14 +2142,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
-
-		if (tbmres == NULL)
+		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
 			return false;
 
 		/* Exact pages need their tuple offsets extracted. */
-		if (!tbmres->lossy)
-			noffsets = tbm_extract_page_tuple(tbmres, offsets,
+		if (!tbmres.lossy)
+			noffsets = tbm_extract_page_tuple(&tbmres, offsets,
 											  TBM_MAX_TUPLES_PER_PAGE);
 
 		/*
@@ -2161,11 +2159,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2173,11 +2171,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres->lossy);
+		Assert(!tbmres.lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 		Assert(noffsets > -1);
 
@@ -2186,7 +2184,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2215,7 +2213,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres->lossy)
+	if (!tbmres.lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,7 +2277,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->lossy)
+	if (tbmres.lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..3b4ea0f6144 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,18 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
 					/* No more pages to prefetch */
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3d835024caa..41031aa8f2f 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -957,21 +955,28 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If lossy is true, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  result->ntuples is set to -1 when the bitmap is lossy.
- * If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when lossy is true.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.
+ *
+ * Returns false when there are no more pages to scan and true otherwise. When
+ * there are no more pages to scan, tbmres->blockno is set to
+ * InvalidBlockNumber.
+ *
+ * If lossy is true, then the bitmap is "lossy" and failed to remember
+ * the exact tuples to look at on this page --- the caller must examine all
+ * tuples on the page and check if they meet the intended condition. If lossy
+ * is false, the caller must later extract the tuple offsets from the page
+ * pointed to by internal_page with tbm_extract_page_tuple.
+ *
+ * If tbmres->recheck is true, only the indicated tuples need be examined, but
+ * the condition must be rechecked anyway.  (For ease of testing, recheck is
+ * always set true when lossy is true.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+bool
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -1009,12 +1014,12 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			iterator->schunkbit++;
-			return output;
+			return true;
 		}
 	}
 
@@ -1028,16 +1033,17 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return true;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1047,10 +1053,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+bool
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1101,14 +1106,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return true;
 		}
 	}
 
@@ -1116,21 +1121,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return true;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1604,15 +1610,17 @@ tbm_end_iterate(TBMIterator *iterator)
 }
 
 /*
- * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ * Populate the next TBMIterateResult using the shared or private bitmap
+ * iterator. Returns false when there is nothing more to scan.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+bool
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 50478db9820..82d2c28583e 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -353,7 +353,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 	OffsetNumber matchOffsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			matchNtuples;
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index e185635c10b..99f795ceab5 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -101,8 +101,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -113,7 +113,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern bool tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v34-0003-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v34-0003-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From e0f329e09c12dc24902f0562e91f93e19dbee4fe Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:32:33 -0500
Subject: [PATCH v34 3/3] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator into table-AM specific code (as part
of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer returns the current block number.
Since scan_bitmap_next_block() isn't returning any relevant information
to bitmap table scan code, it makes more sense to get rid of it.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple(),
and the heap AM implementation of scan_bitmap_next_block() is a local
helper in heapam_handler.c.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam_handler.c  | 372 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   3 -
 src/backend/executor/nodeBitmapHeapscan.c |  73 ++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 244 insertions(+), 296 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 0f7dd79f28e..c4f5d7307b4 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,10 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,198 +2120,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
-	int			noffsets = -1;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
-											 &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BlockNumberIsValid(tbmres->blockno));
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	/* Exact pages need their tuple offsets extracted. */
-	if (!tbmres->lossy)
-		noffsets = tbm_extract_page_tuple(tbmres, offsets,
-										  TBM_MAX_TUPLES_PER_PAGE);
-
-	*recheck = tbmres->recheck;
-
-	block = hscan->rs_cblock = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (!tbmres->lossy)
-	{
-		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		/* We must have extracted the tuple offsets by now */
-		Assert(noffsets > -1);
-
-		for (curslot = 0; curslot < noffsets; curslot++)
-		{
-			OffsetNumber offnum = offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
 
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->lossy)
-		(*lossy_pages)++;
-	else
-		(*exact_pages)++;
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
-
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2614,6 +2464,177 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+	int			noffsets = -1;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	/* Exact pages need their tuple offsets extracted. */
+	if (!tbmres->lossy)
+		noffsets = tbm_extract_page_tuple(tbmres, offsets,
+										  TBM_MAX_TUPLES_PER_PAGE);
+
+	*recheck = tbmres->recheck;
+
+	block = hscan->rs_cblock = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (!tbmres->lossy)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		/* We must have extracted the tuple offsets by now */
+		Assert(noffsets > -1);
+
+		for (curslot = 0; curslot < noffsets; curslot++)
+		{
+			OffsetNumber offnum = offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->lossy)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2673,7 +2694,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..476663b66aa 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6df34094a13..3e33360c0fc 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -138,69 +138,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-
-			CHECK_FOR_INTERRUPTS();
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 507d4ebe68f..b8cb1e744ad 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. These are tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1939,51 +1919,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1994,7 +1947,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

#216Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#215)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Feb 24, 2025 at 5:07 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I was thinking about what the default value should be for
effective_io_concurrency, and I looked back at Tomas' results. It
definitely should be > 1. But, there are cases where 16 is a
regression. So, perhaps it would be good to run some tests trying out
4 and 8 once we have a fixed up sequential detection algorithm.

I ran some experiments on master with datasets and access patterns
derived from Tomas' original bitmap heap scan benchmarking scripts to
try and identify a good default effective IO concurrency value on
master.

The takeaway is that I think 16 is a good default effectio_io_concurrency value.

I've attached an image with two charts of the effects of different
effective_io_concurrency values on query duration. The top are results
from a cloud VM with approx 3ms random read completion latency. The
bottom are results from a local nvme SSD.

The results you see are only for queries for which the optimal plan
was a bitmap heap scan.

All results are for a 1,000,000 row (~0.5 GB total size given
fillfactor) dataset.

The uniform dataset has 10,000 distinct values uniformly distributed
throughout the relation, so I/O should be pretty random.

The cyclic dataset has 100 distinct values banded every 10,000 rows.
So, rows where a = 1 would be something like row 1-100, 10,000-10,100,
20,000-20,100, etc. So there are intermittent ranges of sequential
values that match.

"matches" determines how big the range is in the WHERE clause. In this
query, $from and $to are based on the number of matches and the number
of distinct values. So a higher matches value means more of the table
matches.

SELECT * FROM bitmap_scan_test WHERE (a BETWEEN $from AND $to) OFFSET $rows;

I also tested the linear data distribution -- which had 10,000
distinct values starting with 0, each value repeating 100 times, and
linearly increasing to 10,000. None of these queries chose bitmap heap
scan as the optimal plan, so they are not pictured in the results.

I've displayed the results for the uncached workload (data was evicted
from kernel buffer cache before doing each query). I also ran the same
queries with OS caching and shared buffer caching. There was no
meaningful difference. I was mostly confirming that there was no
regression there with higher effective_io_concurrency values.

- Melanie

Attachments:

eic_timing.pngimage/png; name=eic_timing.pngDownload
�PNG


IHDR
�
�2R
�:tEXtSoftwareMatplotlib version3.10.0, https://matplotlib.org/�rXr	pHYs.#.#x�?vIDATx���wt����OR 		���H/�;	
H�&�� � �(�EQ@����EQ��
H�"%����^L�$��2�?<�#�l�-�
�_��rg��g7�wf����e�!�4ow'����=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=\��=�k�1B^^^~������G�5������~����
�;-����H�s��)S����/_n�{yy�;-���/_����i����	8��g��Tr'g�n���


�����>��	�����	r���t:tH�����������d���W
Phh�"""T�F
�������d�����aC���?��M����m�6���O.\PJJ����U�T)��QC�J�rw����#:|���;���%''�����9�P�B�^��BBB��*@�q��A���G�����������)��*U����)����;U�&,,L����^��m���W���U�F
7f��E{ S/^��q����
���4h���p���������9���3��s�,�+VX������?��~�M�����u������>>>>�R������v�����������ss����3������_��7�����[U�V-���}�����s:�-Z�������+O�n�'N����z��}��12d�S��OZZ�f���	&h��JII���J�*�g��z�����Yz�s��i����;w�V�^����,����R�
T�^=�n�Z<��s [�����+�������Y�����K�������V�z�T�^=�h�BE���lw�!C���/���S�$�����>k��;`��@���?�7�|��i�P�ti�� �������>���s�.LKK��;�c�M�<Yaaa�����Q3>\�������������f�O�5�.dhw� ��W�j���������y�f��_��cX�3::����g��������n�j��������zK�G���Q�4h� yyyeo�f���������/�(55��}
����{�w�^����8p�x�=���j��i6e���]��w�}W���������?))I���������=z��5��S'�1��8S�L��#G2�EGGs�0�7o^
6LO?��������1C>��3@n�������������5k�9s��d����xM�0A�j�R�>}t��qd���G�j������o�eQ�����5kf�~��a������u����]Qh�@�UL	�v����4ibs�����s�������]�������T�V-M�6���=3�.]���S��Y3u��Q���2�]6m����k����v�`��a��u���k�~S�L���#3���h�u�=��"""2����[JKKsSF�P��a��9�Y��~���l�����~�A*T��5k���9r��]������^�i_k��;[T�����?p��N�:e���Y3y{���L�2E�=��E_f��~�M��uSJJ��2�Lk����w��I�&)===[�1g�U�^]���k���D�W�Vtt�v����TpH@@���m��=�:u��2�� ������_Thh�KcV�R������g������te�2e��C�j���*T���%K*((H>>>JJJ��S��o�>�Y�FK�,����M�\�rEg�������}����~����I5i�������L�W�X�^�z9�WVEy���JOOw���Z|kE�<���k���O����s�=�:�B�
�����S�����J�����g���z��W�����D�9��_U��=3-L,Z��:t���M��r��*]�����������$�={V�����u��t�R�Z����OKK��'���x�����m��JJJ2�^�@u��U��7W�5T�hQ���_^^^���S\\�����
6h���Z�z�m?��3=��3z���3��F��GyD���n��E{ S����od�����-**J��/w"���1B#F�p:�����^�
Rdd���p�1c���^���e��6l��b5I


Uhh��T����;K������'j��I�t����v�'�|����m�y�Z�j)$$D/^����Jx)))Z�zu�6??�+h]�xQ[�nU���:E{�����+z��GL3�i�F��OW�2�GFF*22R�>�����!C�X�67f�u��A-Z����s��3���[�����WOo�����oo�(:$$D!!!������];�9R'N�����5n�8���e�S��8s/���0
0@			����4l�0
2D�����+VL��S������J���?���g��_���i�W		Q�=��7��h;r��f����={�13�V�M��m��=[/�������P���/Z�xq�{�T�XQ�~���9�����s����WS�N����]�����[M�6�h���N�>�P^7nTrrr���}�Z<���@�}CCCU�fM�c�y�|��:d�~�=�h���{�z��g5a��m�=��E1_n�~�z=�����������_h��u��������(QB�����G��k�����Ui�
?�����]k��+V��W_�Z�gM���o_��;W��/����-����OZ��;6��m��=��?~\�>���J2�J���u���{w��S�P!M�4I��/W�������	&�����z�������X[���������'�xBE�qI��G����c���5��P��\�tI�~��E{hh��O�ns�X���M���;w���~s:OO����|PW�\��������g�q��<00P����6m��*U�8 7�<y�i�?���
�7����������;[��W�b��
6h��Un�������%$$X�*TH���*T����5o�\[�nU�&M\�V�a�����h��������<�hQ����v��j��Y���+W�Y��:k��<�?����x���^{M��+�������k�>f����$/���i�r@@�,X��
��x��U��
��K���Dqqq����h���R�6m\z,{'��?��E�����	r�<�Np��G�j��-:~��.]��|��)""B��US��U�^I������Z�p���~�A������*THK�,���g�%~f�/_nQ�Q�dI��W��X�k�Vpp�3�;R����f1[s�F��'O5k�L3f����;v�F�v�Z^��x��S�Z������;V��%��[7���O���Y���\�r��n�w�6-���+Jtu��u��������C�eK| ;]�zU7n���{/�0�r���V�Z
sw��~�z���Y�w��9��$���W��o��S�t��e�h���^���'�p{����^{��m���������@7e����=�X�B�f�����u��]�pA���*T��j���V�Z�w��6bLNN������k��-:y��U�@)RD
4�<���[���'���k���S3f�Pll�������xyyy)<<\E�Q�f���];EGG����>_�|Y'N��_���w[}\�"E�����^P�%2�>l�0����5��y�f)))Z�`�V�Z�-[������x������|��)00P��Wdd����.5h�@
6Txx����o���i{��=��m�l=v@@�J�*���0cV���8T������M�j������o�={V6���e��������7on��+V��h/$$D�j��+�$���?�5k�V�\���w���cJJJ�a
V��%U�J5k�L�;wV��E�>�����5w�\-^�X��o����o��E�U������X>��������k����m��9�.������7�
.�
*�q�������W��c�:tH�g�VLL�������O�(�/W��F��v��eg���Z�x��l����w���JHHPJJ�����|���p�����T��eU�n]5l�0W�9����Z�f�E{���P�G}��hO�~��W������#F�Pzz�E{�&M*p�����C��			Z�r���[�={�h���:w��t��U(P@aaa���P�����ys5o�\����&�����������[u��Q�������
P���U�X1U�Z���Qv�E�O������%K�h���:{���^���*""Bu��Q��m��]�\3�299Y�g������u������(<<\+VT��m��C+V�����q�>��S��=[������~������K�.���
��;wfx|�=��G��
������+W�x�b���h���:r����;���d���)��*R���T��5j��{�Q��u��~�~�6����k���W���~��U�t��]�xQ���
S����qcu��Uw�}w���	�����2e��p&��9s�m���=z��11115j�M�z�����K��Czz��/_�E�i��
:x�����_]�|Yy��U��U�\9��WO�[�V�-\�ifv���?��C�V����{u��Y%''+���P�������[7�8�N���e��e����G����q�f�����%J�I�&j���5j$??�ly^�����q������������T�>}�����`��7��.]j�ADD�&M��������y��i�����g�N�8�K�.����T�R�^�������sg&I����[�h�"�[�N���'������t�@��P���T���M���{�Q������$����={�V�X�;v����JHHPZZ����T�xqU�XQM�4Q���U�lYw���.\��_~�E.����u��i]�vMAAA*Y��j���6m��s��


��\��/�5jh���7�.]����]�{���c�6cd#I?QQQ.�=|�p�b�����K��5k�>�[�����?��HKK�z������?6
,hS�Z�j���w����h����}��g������.]��s�������%K�||IF��y��c����l�2����3f�;66�e���e��1����,�MHH0^}�U�����xyy�52��k�����9��>}��>����-���(���6l0�������+;]�v�		�x�.t8�|`�:��1��8�G���c�a�������u�����'N�0��}��v���c���kW�����~���������}�v��u���Kg��]�|�>|�Q�@�L��Y��C�����n���k��/X���j�*��<x������7o^���
�-r(w�����g��C����W���3&��i���F�
:�H2��+g������3g~����)SL_�i��9����F�|�,b�{��.�<g�>}���'��k�r�Jw����c���?��h���]}���|���?��q���l�o���F�^��s+V����k���8��;����SO=e����t����&M���,+fq�-[���SSS�O>��(T��M�����x��W��/:��n���h<��Y����4i�$�����t���.�17p���g����2s��!����6�����g
,h4���m������Onz�������5k�
���=��c���#Cg�-������r<k��8�c�����k���n�����7>��3���k?�����"n���3<f��uF�����g���V��y�f���_v���x����1c�K�.9�\�L�6��+���0c���v����={���Q#�r���3�|��l;��fW�\1���+�b��v�����c�n���1c�M�����;r����O�|N��<��=lv�w\�%''��
3m���FJJJ��d�1t�P�����s*&�<��le�j��h/==�x�����(�x����W�Z���v�G���T�l���^#�0�	&�����\7�9���?w�ot���'�0����Z�w����%���w�1�b?00�HLL�t�+V%J�p����'��y���ho�����?������{-_�������III�\�v���8h� ��t��!����+Wnlo��}�����v��6m�i���M����o����"[�go�����x3+���o�����h����F��=M�]�Lc���Y�HMM5�~�m�k������:4(2����_m���Z����'��
��3g���gn��O�>�S�N9�e��12��M>��C���^�z�N-�O>���k������a���.]�d<���������EFFfy������WE�q����wwx0�Y<W��>}��~�j��N�O�:eT�^���kxx��q�F�0(���E{��L�,%%�>|���;�>��������q�5��F�������/�}�3�mOc6��$��o���\�U��}�v�������[�:���*81b���[k�?w���e�k���~��z�����e��6���:z�����=?!!!NM�r�Y�t�Q�|y���L����\}m��_�N�c�O������d���Lg�+_����U�Vu�ui���q��9��t��E�,b�����|��Sqpg�,<���z���d�������0`@�����+**Jk���;^jj�z�!-_���}��������zJ��]�{_�04d�}�����z����]7y�d
:���]���_=z��h�����+W�8?55U��O�h����������l�2�m�V'N�p:x�?�����W�^9�I�Y�`�E[��u�p�:u��~�V�Xas���t���fh�_�����o���Y����;���w�|��������,��z��:u��w�yG���6�V���z��w��cG]�z��8���o�7n��{��,��.^��6m����u����5kT�B�Lc$$$�M�6z����~�~��EEE����N�����~����;t������������k]���b��MmE�U��E��[�n]��+W�h��=N�u���g��{�9����N]����������F��t�#G��^�z��������t<g��_��{��G����C����S��=����N�8�F�9����K��5�����������{�c������i����=�p��'|����u�=�h���.�.�
��m<�=�i���=���
������kz���4y�d����
*d��p����=.\���;u>��;�7i�D����2��s�=�#F8���9s�EIG�U�&M4o�<��:T�G�v*��#4~�x�b�*&&Fu����%K��s��E=��#z��w\�Y�����e��:p��K���:��c
0@�
Rrr�S����kEEE)>>�E�y����[M�6��]����5���VBB��3�O�&M���������Z�lY���<�N��|�����/3����O���*S�����t��ym��]�V�RZZ�E�)S��C�z��t��eu��A���R�J�y��*R�����u��i-_�\���w��5=�����cG�"w����5l��m>>>�_���V�����������Z�t�N�>m��W^Q��mU�\9���e�
4�t�����u���zH��WW�b�t��%�:uJK�,���S�e����������g��]�o������2�]�xQ�f�2-����t��Y�cZs�������`���`��__���W����$%$$���c��m���9<��;t��I�v�n��
����[�5i����y��Q�&M,%���Sqqq*X�`�1v��a1��y����.�WX�J��4+"��?�j�����=z����s�n/]���4i�������K'O���5kL�g�4o�<u��]�f�����M�[s��%�o�^���o����`EGG�d��*T���\��C�Y-^t�����]�v��s����m�j��Y�&%%�u��Z�n����)SF�5RDD�������x>|X��/��K�,�q�Fu��Q��/�����O�&���^z�%������a�����Ppp�����c��Z��4���?nu�]�<yT�n]U�XQ
��+Wt��E�9sF;v����]2�=�IOO7-��������oW�j�����.\�`�3��c���1���W�5T�|y���($$D��]���g�m��I������9R��WW��]:��C����
���j���J�(����������:v��6n��s��9tl3�v�R���-&��X��4h����������Z�j����_�U��O����K�.�M�6:r�H����EEE�X�b
		Q\\����������z���5i�$�s�������o�m+V���>��m��D���?�N�>�={���_��?�|�|s��Y=���v��	����xEEE�^3]����&M��t�����P�<y�S�Ni�����2��������k���Gk��qV�/^\��7W�������'N��
80�]We�|���������l�b��fn�f�u��E�/_6��'OEGG�\�r
W\\�<�����N�r��%u��EK�,q�{
I�4i����z���U��
.���������e���_o�1�-��5k�x��
		Qpp�.]����xm��M��oWJJ��~�.]R��=�u�V�)S�����3G|������@=���z��U�bE)RD/^��'4�|M�:U��������^��;3+V�P�v��~������u��j��*X������3g�h��M��u�i1�[o�����	��������LS�J��YS
		���o\G������������gz����h/^\:y��6o�l�i��
������G����W����Z����f���B�
���������K�{���sN�|�T�vm�k���m��.?nS�Z��$Y�DEE�$������m���������*T�?~�q��e�G�1��ic�<��-k���O=�T��f��k�������3�����������EFF�����{``����oqqq�1�����~���s����]�)55��S��i��5k[�n�t���tc��qF��yo����k/'U�Z���m��q:n��]M�����V�y��M_��U�3g�4�]���qO�>m|��7F���<y�����D���������59|���r���r�}���_gk������o�o��:u����{�=������i��>��b�E�ex��k�2�[���������1��]�vY����_��+���������[�OV�\i���d|���6�]���-b/^<��e��1����W�^5����f�X�����}��M�m���"��?�?������e���t�s���1������z���o����\�bL�0����0�1r�H���a��e�Lc���t�b����j�s��Yl�3g�i���}��q���,�KJJ2f��i<��cFhh�!��3g���/�:z���k7`��c�^��4��Q�\�y�Z�x��s)]���S������///�q�������}��ez�f��f��a��


5N�8aw>/^4*W�l���_��1�|�}�u{��5�y��J�*6������1��N={�4���k5��
��.��+W�zM��,[����o~N���
��-��w?y����G�X^^^��M��zN�f�2����c����Y^�<x�h��y�}����nW^������8�����TJJ���IF������HJJ�4��c��O?���_���}mA���<�=�I���a�w�6�����_.\h������r�J�v���1����s�'�v��h���+��������q��)11�([�������5�z�-���s�����������Udd����`s.�}��E���#((������F�~��#G�X�s�����C��4h`H2�N�:���q���,s;��1n�8�H�"���A�Y���JLL4J�,i�E�Y~Ow��5c������w��1��;<x���7���/3=�;v�x���2�u�'o�����mW>��I�&Y=?����x��7��{'''�f�2z������=�+�����g5�2e��g�6RSSM���m���U+�����v���W�F�z�2�����x������t���8���������c]qM�����+������7�]�F
-Z�H������Kk��9��������a��C����oj���7�����{/�:w�����KM�4���3l���o���/���\��!��)�?��S*T��x///���C�k�V���-fN�7o�N�:�b���t�	&h��M�5k���+���^^^4h���-�N�:)55�t�����O���+�/^���O�h��������9s,�}�Q��[���~���=**J���W�|�l:v�"E��O��'���c���g�9��\���&ov;���m�6����W��t���h��+V�K�.Y��*xy��Q���3�����a��Z�l��6[W���8ky_w���~��'�|R_|��|}}����iS�]�V��XMT�^}�U�n�Z+V�4�����J�N����?+  ������MW-t��%K��kW%$$Xl>|�F�aS��'j��Y�e����3T�v�L��������cG�o���s��;��C�N}����>>>�2e�z�����*�B�
eh�>}���"""�v�Z�WYT�����sg}������on���F�e�csB���mz_�|�z����;�������;;���s�����q�����T����]_Y�K�.1b��{���������G�����?o��Z�<y��_��'��i��
*h��a6l������S���������7o^����Y��X�n]�X�Bm��Qlll�mg����Y���C9��+��*�����w�}7��+VL?����-�1c�d�f����k�?��c_�z����_��{��,c�-[V�-R��mo\�8{?u���LW�r��;�F��N�����z���MW����n6l�������J�,���^�?��bcc��;��t|�����=�I���a����2]����?���y�Z������O?�o��F���N|}}��K�����N�:�&M��[�nz��g��iSy{{�!K�{��MW�/X��-Z���4,,L��
S���U+��2�9�!C�h����w�������={�����L�)]���m���1b�
����Ghh�
�GyD�z�����3l_�n�,X�v���s���:~��E{�V�4w�\���e�����F��b���X�������t���[����z���	&(000�%K����~�:��G���������W/m����s�$M�:����;�.]Z�{���������b��
5c��(Q"�8y��U�N���S'�={V�G�VPP��y8*>>^���3���CM�>=�<j������>����n�}����������\�sN����L�������s��E�������7�T�����U����:���\�����V���@���L�������R�J���6�:q�D����~�b��=z�i�u��9�]�����=��/��b��?�9F�
,�

2�?nW.�a�q���t��i�������Vf+dyyy�����;M�9p���y�n���Z�nm�����9k����/Lgn�w�3��]3=�}��Y����n*T�����z�-�c���'�c<��3�O~�a��|�A��IX{��bu����8f+�]�i���M���?�����{�Y����cL�<��c���!!!��#�O�����?��������C�����W��L�2�������.����2{n���u��_��t�I�&9��\�r�4��+"{�'�|���:���Y��/��/�`�|������d�c�Y���u���3f����<3�Y����e����v�;|���
����m���,gW���������KJJ�Q�zu�8���Y��u��i�Ls<x�]��+�-Z����0��{��/�����v
#w�������#G����oW>��������k������i���]��iiiVWt���i���c�:��?����#�<b|����M��\��Y�����={///�����3��]kW�
6X]�0��of����oooc����<�\�w^�r�h���S}Drr�iQ�D	#11����}W"����7�|c��'��;'����,X�����j��{�����>�8��{o�������vC�5��I�&��������*�����W���q�q�5�Y��i�5w�\��X�j�������������e���pg�=�4p�)S��@�6?�x��z���n�\��>���rx���Lg��ue����7����K���MWTZ�r�M����h��}�����M���j���N���JE��}��g�����;�l�f���l��V�1���b��*W���y����)#///��L�2%G�>q��i�#������(R����������k�2�$m��].\�t���w�����fm�-�vk+�d����`��S��>g���o��f����������4q�D)R�b��Y�2������ }��79>������>}�X���?��C�?����>����u}||4{�l��-+����+����oV?������������W�\�x�KR������Ng���*�����7������s��V�5j�J�*��->>^,�9������g��Rv2d��urf"##����Z��Z�J�a�*5���WO#G��k�<y����q��������Wz�Yxx���HR����������]����{OW�^�h�����z�)��q��m����k�I�&Y����������>���[_��BCCm�'7�X��M���;wN��M��A�T�N���_�7��!C4c��9s&��u������==l�05h���Xu����|���w�g�y&���l������_&L�������#��1c�E!I}��C�����;v�h&55Uo���E{������_:�K�.z��',�?��3���6k�����-��)����Y�Z�nW�^5�����S`W�w�}W��W�h��a���[�p���n�:m����������������^rUj���Dj�]3`��=�[4o���
�:u����W^��0$00P-[��h��u����\�z�D��G��-[�����?�h��7o^
4��\|}}����;�ov����E�����q�F�c���G����h���">>����V�g��5m/\�pg�s�=j�fo�qf���-�����,J6+��V���aC���f�������k�.��&M������~_���]�f�>j�(�
��������Z����j���v����,Mg���4
0@��
��V�pa-_�\m���9^JJ�����\w�}��y6m���z&55�t��=�{�=��5;�H�gl���d���U3���m���.�����s\��y��#�X��]����<���[���UK������9#o��z��7����#!!At6-��1��b��;�N�b�����'�|�r��8\���#���z
��]����DM�6���X�b���O����w�9���k����k��E��<�L�!YS�P!������o�i��%�z�Y�F�}���w��"E��R�Jz���=����K�d�)SF/���C1l:Q��?�����bJ������@w�^��Ea�a��_�1�^�d���}�-
(����;��u�����c�,�?��S�&z��7,��Y�p�N�:�p��b�����_~�����r8���1C����h��T�L�����h�����-u7��}��y5j�(�����k�z�_�X1yyyY�9r$��	��E{�p�?�k��i������If�9m����[�~}���'Of��$�^�������7dn�|���]:v�hZ���j{f����/�!%������Sjj��9�s%''��{�l��������(�����n]=���[M�65}l``�j��mW��+W��`Vdx�9s�X��W�^�����={����u��K���S'�U7*V��5k�d����%K��
2��4o0+��uu[3���S�j���Zq�����y'1[�H�o@�+�]Y;�'��q�L'�u��������^x!������:�J��uMW��~*22������������9�Y�������;����u�C=����y��L��;W�.]�h8p�S���D�k�����]��=[����������c���'O��q��^E�f{��������+*::��B��c�����?n�dm�����������e��9S�or9gW�����������=z��;�������J����-�����&M�8�L�2j��Y�6�0�T\Ow��5��9���|������2���w\^^^0`��1���U�X��}��y�������;vt��.00�t2W���Sxx�E��w����n�U!�5�����o4h���������-..��X�t�=�8�o���M���?��~III����-���i�p.�fZH������?�����W������>��k�,D�.]��-..N�}�������r��i��
?<��,����.�_�~}��o�*��u{���3���A['O��t�
k���\w��U�U]�t�b�m��]�Z�����j�MV"##U�J�s���3g�y��Ylk���V�Z�������E[���]���Vm\�v������o�T>���7-N>|�����b�G��1���SRRL��Y��ff��������s�$-Z�����4�~�@�YN�����

R��%-�����S����\nv?e�s��a�E[��%�>�8Z�x���H��������~;p�g������1-T�-�w-��=��kb���j���J�*9�G��u�}�9�n0h� ���_���w�u��j���z��eu���f������Gy������Eg�����}���{MWw�{����;<�SZZ������us*����.�	��,_����R7����lf��U���'�|�����d��m���J�*�T\�����x�]���C�������8�g���Z���3��p����P�%����[AAA�gu��u8����
�����]�2�/�t���m���t@�5����V�r:�+���W������y���<��_��'N���J���f1����_��S�����{�L�����/�����U���������Z����leg
�n����F�i�����l����D���}�������f6(����G����b�
�+W���fE{AAA���y�f�B��r�ETT�����miii��a���
3�S��}���M�6:|����.]�h��i����5n���X�*S������a���������*[����\�zGEEi��Y�����o�^c��qj �����|�-W<���vLOfm���v��v��v����*11Q			JJJ���6[���������i�&��f��9�b�+��W���(�c��eh���#���9����d�wv��rw}��
��V�jZ��.���q�{�����
��]9�z��s�:���(QB�&M��Q����?k��i��a���L�6M��o��9s��>���qJ�(�����J�*���H��Mg��r�^9!!A��o��S�������D%''[�{o����-���$���u�2'O��{�={�������l2���7�$��2�^���-[�p&�9}���9Pr��if��]k�
��2;�J��ck���|��9<)XV���3��0C��M"""����h/<<��x�2�U8'9������=��u��i���U�:���b�J���U�J���;C��)Sl.�����-�J�*�-Zd����������>�(C�a���O��W_�s������Z�je��N1h� EFF�;
�����t�$wb�Nf�6\Y�'��r��E{iii���5]����.����M����+��+V����x����m�6��&M�d�����;M�����Ls���;w�t�h������z�ju���t&�A����>s��)==���ve�ZXX���=�����s
,u�����OZ�I����p�BEGG�[�nj��]��_���Jx�2@w�Y���:���=7�����oM�6M������o���iiiV��;r���`COY�:;�=n��)[�����+��"""T�P!����N�B�s��/%%�tO�g�w-��=�i��W�^���{-�k���t���[DDD�����s�=���x�\�R+W���u��m�6���;v��}������[�^1'��O]q�|=��E{���m�]�����+&&F��M��%Kt���c�R�lvs��YU�V����o������z��&M��W�2[u1o���^����_v~�V�fM��3;��2��)R���oooU�V�j���(��3r�t�������;�,��VSqTv�F���2c6�:  �%E7aaaN�p�>}�X�-X��������9s�E���>*///����+�X]q���+������C�P�B�U���}�Y���/:s��M��~�����G�
���������Yk�j��
�Z�j6�_�r��9#:::�c����u������5k���+W�43w�\�{��{^^^���5n�8�V";{����_/������\�s��d�������n���i��_���e���3��L�2*S������I�&����X���|��K��7�$vN����={��e���R���}�]����e��Y=������{���q���}Gvs�s2{/��>����`�;��N�2�&ug?C�k�;�#�vM|��y�U��V���+b�Faaa����F���+W������g��N��~��������{��O�@������j�+�{ek���Z���,P����E}��7.)��l�N�����G���������j���ElG��s�sd�
2�x��d��i!!!*R�����Tfb������X�����p��h�&�.��������$7�u9������Y�������}�������g���3L�������,XP���
.�������u�V}�������)�j�����_�X)��X�b����n�[������l`�34h`Z�b��.&&&���*U�iu�f��e���������7����>>>�������������g!!!�����~���}����i����W^q:�?���tG����>}�M��9rD?�����+�D������-[���������			.����d��qr�9n��q�Q������l���@Bk��ewQ��r�]{p?wr����������=�i����\���_����K+VT�^����_��������C=���S������[������W��~���{$�>�����r�}rjj�}�Q�k�Npi�������1���n��=�s���ma�����Dn{O��F�:7f�9�l�$���3� W�z��E����Kb�*��-ZT�[��h��������1M�6U�r����V�Z��i�:t�`�~�v�������U��y��EI��J�2m��gOg�s�R�ju�������aC���7���K�>l1�xV��e�8�=��_``�����i|�?�'��qt�Qv�����4��zkVd�����p�������������y��'Oj������{T�|y}���n_1+',X���l�z{������sc�^n:�}���z����������s��X��N���g��~�~�3y�5qv�e��#������4i���Yk��Qdd���~���9��M���fw��#����ONMM�C=��S��,�#<�:�}��k�r��9��������'(���y�5{of��p{�h����:2��W�q%����l��;vX�����Z�r�E{�>}��x�����?�j�*������cW�\���(�����+��9��U3m��qcg�s���[�\�l���T�^�:C�Y���E{���g/))I�7o�x\���Z=#���+���S��---M�>��&O��t�;���V���=z������^zIE��k�C��o��j���E����
r�X��Z�%J8;���s������K/Y�^�^=���������#G�(..N�.]Rzz����s��a�����j��N������~�~�s�������A�Z���u�����Zx{+W}v=�;v�~��w�m~~~�������ok�����a�N�<����������a�������c��r��~6�q��w�"]V����������III.������8���S'���Z�>����k��������2#C[�|���{w�ri���7n�	&h��������b�
m��E���Y�?y�d>|X���[V��%�B$��
\�d��:p�@�6W��*::Z#G��h_�b�Z�j���[�Z�W�X1�+WN�o��U������,��������E��
�,�+
4Hg��������===]�����+W��3�8?  ���s��V?��P�v�l�m���H}�������a����_Z�|���YcSa���k��A�_����Q�F9��K5o�����2eL�]Q4p�������}v���o]�t�cf���g-��$�u��=z��W�nW<GW���7�i��U��{���*>>>C������O]�xQ���sI.���cG��Q��i�<�����\�vMlm�W|wdv/K���_|���;[lKJJ��
��q����j_��N��{����g����o�m�m���:t�
.lWLG�����������k�����v���S�N���G����J�.���{g�8�sdn:?f�O���+7}�f��96��QW0��d���v<�^(�@�`��iii:y���/�TlO\����_=z���	2�O�6M|���JY�a��~����K����6m��M�6��[�l��U�����LW��n���1b��}�]���4m�T>>>���9sF{��U����Y�)]��E��'\~��
���_W�^��~kQ����)S�����5�P�w�����YQ�d[��Y������$������]�|��cz�W^yEy������3�6C�
��+W���/:���n���^x��b�V>>>j���6l�7�xC�����y�V�X�%K�h���Vx�>}Z=��V�Ze���|�MW�������T�����={6C��}���a�����*Tp:vN�R�����u�����������}��������m��~�z��=zh��i
����V�
2m?��C�����9��s:njj�N�>�T����{\�\�D	���29Jn�	���g��k��,���I�<U�N�T�T)�s��C�r�h/  @�r�J�vW�����(88�%����?��}��W8p�C1�;���S�N)--M>>>��������]�
RXX�3)9m���V�r���(���������h�=q����b�IE{�^���c]un��s����k��K��5f�;�`#k���o��t�m��9#;�����������-�cccu��!�b�J``�Z�n�Q�Fi��M:v���z�-����k1��ju����~�������N�<����A������Q�v��q���l]e/���< �lpV�|�T�^�,c[\f���{��5m���=���Y&M�d:����^rx���%K�����=..��x��<y��~��z����p�B�����0a������Wk���9�e��U��E��������T�-[��|<O���}c��[y�9n��9m!!!�0a���r�����W�T)����w;���~��R{������Nc��MOOw*��E
��x���9����z6O�&3���C��q'�v�����Yf�������+�����s�Y��p�������:���+.�����������;��5����� ;�OKLL4�(������w]�,X���U�hv�c�}l�]3`��=�
w�u��L�f���k��
N��
4P���-����{��J�,�{��'[r3S�dI�9R{��5-JNN�#
*r�=z��O�2���Od�RJrrr���e�v��5�Y�F�yA��E{��5�h[�|�����Y���qc���f�j����[�n�+G{bT�V�����_�~����M�����z��7�������e�Z������og���0`�v�������>f��9�U�3+
�v�Z�����z�t���H���;�]���f����A�7��q�E[���pLG�������������|���+�����LWAJJJr*��4�I�<yL��s��C���<�����_w�u�E�+&|��I�<U�b�L�/]�������^�������>����e���8�wZ�����������s�C�V�R����y������������>m��m2����~���U�W�n���?�8}�����m�k���5kf��p��h��������k�����k�����N��N}���h���?t����_�|��u������8#<<\�������c�m���9��=��#��/�E���g5}�t7d���������m�~�X�E{���W��EM��Y�����Z^��S�����,�cbb����Y�V��z���?�lZ���{���^�;f��
-�bbbLcA����W_}e:��N8�X+�_�x��1�;f�BE��-��nm��Q��%-��]��/���
et���6ge;�����2��W�\y���v��_��E����5o�<�����/N�;��?�E��+��n\fE�;w��?���#����|�vMl�g�Z������q'�6���w�2�>���S�F�,��;����'O���C�l:^N�z��.^�h��L��������@�*_��E�����=[W�\qh���k�~7p}B%���zA��,Y���8�X�b��f��i�m��']���_%)66��t�e�%'';����K�*�k'9@��h�F��m-�v��e:����L��DF��w���:]�z5����3g*!!�b��}�fwzV�)S�t���`I�GHH��|�I�m/���m��*Q��
.l��E{�52-z�^Tw�@�b���>��������O������<f+������w�m�����;<�M������_-��W����@����n�����������1c������k0h�v�,����_���]���G��w�h���2��~F�a�so�������V����{3������/�h���������s8�����,�
(�p�S�Ni������M����x�>�W�z�T�`A�vg��N�8�������������{�����,��;��JP����~&--M�'O�����z>O�&6+*��}�S+h���k�����u�9q��i{�%���lEKgW�5+.����G��M3���v��`�oJ���3g�t��h����E�t��)�c:s�/_>���f�����4��������~-u����5�52-0�4iR����Z���'��;m�4����0U�P!�}��U���o�s9|���;������3����@�s����[�Y�0C�r���{�����K���{w�
tT�b���U+���������5n�Xw�uW����ATw������_Wpp�E{\\�����7o^���mV��a��'o����<��[�#G�X�huk����V�[�b��J~�r��C�m			�����K�&?��s�UB3;������5g�����'�xB���6���������w�u:����z����U�n�,��o��5k���0M�4��=$$$W�I�SO=e�����W��o�lH�~��L
�*[m������J4��������,�?��S�8������w��������e������*55���r��U�Z����u�����������Q��kgz�3~�x%%%e���w=��]w���t��������S�Lq�}s�IMM�Zn���������R��7WHH�E���~���6%%������@�h�����`mbg���>���}%��'��hKII���C��x�b�i{��i�v��AV"v�����v�j���~��=�
���;���t��n[�X��t������^O����\�n���|��W�+I�;w�h�3g���%''gk�����f��5� �W�N�,�W�X�/����X�/_V�~�r� S�U��]��{�������O}�����2g����sC&�&<<\|�����3gj���.?�a���O��S��{3�Y��
�\��@���+����,����laV��p�B��7�V���������7��%%%���_�h��'�`w<O��U+-X��t����N�z���l��/^���~����1���7m9r���~��'�BbIz��GMW��M���5~�x�m6lP�~��e��i���E�:{�������[����:t���w��O>qh��"##M���7o���Tlxk�����.d�5kV���M���.�Ua=����{N�n�����L�FO�<��$<����|�vM\�ti�l�����/���C�������j��Q�H�����_����������H�"�R�J��)R��m���N�h�}������;s��q����{�6=��������;���[�Z����j���z��Y�O�:Us���+�������~��|$�G�����C����sN��Y�D����6���<��������G����v�KOO��!CL�=��36��S��E���+u��i��9~��S����_?����d
6��x��������r�f�����Sn��9��=�*#F�04��s�i��i6�HNNV���Z��:u����P�����^?����jNy���C=����/_�����t��i��<*T�r�#G������'22���`i���j�������~[�vYq��c���}{����nYA�M�63P�;wN�v�r������������T�^]
��6}�t�A���]�pa���O�>���U�b��S�NYl�����/nWn��y��Z�x�i��O?�����k���������=��cZ�v�+R�����.�,��v��i: �^�������,�m9�����o�o,\����s���J���G/����yM�2���m6?��k��j���)S��C)99�%����S�>}��W�,c��]��m�����g�]�<��z�������#G���0|�p��?����U�T�#�<b��w�^�o������/��?���r-///5m�����~���G�����j���.���:T�'N�7�|������<����'��h�z��{�1�VxNOO��O>��b��}��^wM�2�e����m�T�bE
0@��sY��{����_6�f���f��m��������TnO?���gw����e�]��l�bu��A�9��+��U��m���6���l��mz���]��{��g�f��w���K��#>>^�������'  ��ox��1=���t������{��6mrI,OW�^=�����O�V�=\v��]������������[o���[�Z���[W
4�)��da���v�����W�^JHH�k�[5j�H��U�h���o5o�<�b�Y�F�G�v*��,_�������R�r������P��\�J�*z��W-������W/�������iii�7o�j���af��$�$�ExS�N���o���sg���8t�)S��T�R2d�<�P�K�.��G1���[7�b"�xyy��_~�Z������A�Z�~����������U�re-X���8�*R�����o���_��XM�4����E���;*d�*f�����I�L�_go���_�f�|�,���G
<������4
<X?������y���M4l�PK�.U��-�����z����]�H}�����/_Vtt�&L��T��������*U��m���b����\���v���*C���m�,���s�G}d:X�������r���u���t��A��V��_|��i1�$��1C5j�������%�3F+V�?�`�>f�������������N�R�-L?��[��iq��k���sgM�<���s��ux2	d�1c������]�*U����~�:����Sz���t�}��8����We�����s��������wo����5K<�@���	J�(a�8���5j�C{�\�R��w_�����<�����������=��#�|�r�1RSS��SOi��������h��I��������j���N�c����6mjZ����os��Y1KJJ��q]�x���*V�h:)DRR���m�;v�g��j����J��?���V��p��b�w:tH��o���h��|�k�������/_V�V�����[�|_�zU��MS�*U�a����~/��SO�Q�F�����W��v���p���dM�4I�+W�yU�����cM��Z�h�Z�nm:)TV��9�W^yE����+R��K/���E�Z�/[�L={����!I���}�]�vooo�V��W��*W�l�>a���=���������m���f�����{����rf�l�����?[W�6���S�N�v<��(�@���o���,I��MS�r�T�~}���O��
��/��=z�x������3��*U*W���Rs��	����6=��.]�g�}�����~�����O�{�n��n�����~�Mu����e�,��k�������/���Q�\����L�	

��E���}6o��
�u������llu��e-^�X�?��J�.���~�#f�6��(�����u�f���M�����l��[�����X1+����:h��qj��a��W�W�V�F�4n�8��~��*V�hw^��V�ZZ�|�
.l�m��y���C�����~Z��w�h�z���Z�ji�����:ou��%�����_Tdd��5k�Y�fe������t����j�����)��^{Mk���i����k��M}��G��)�|0;R�H���7�����V�Z�����:p��%�[����5�K���#\��[�����?�P�z�L�<xPm��Q�
��7����sY�LIIQll��}�Y�.]Z/������l�)::��`{��m�S�����ou ��������R�J
Gl9�de�����SRR��_?5l�P��g��C���_�����T��:h��uN��	�W_}e����Q��=U�Hu��MC���o��'�|R��5S��%5n����w�}W%K������Mn��S'����+W*:::��q����GyD<������I<��/��{���t��o�����k��Y^7?~\c��U�����ys-Z�(������tM�����'�N���o��V�ZZ�x��x�V�R��
���_�h��B��r��5M�:U��{�"##5t�P�X���U�RRR4o�<u��I-[�������M�9f*V�h�9�3g��+������^��#L���l��O>���`���3�[��F����x�}��?�w�}W�����3g,�GFFz����������E��)S��U�L>�(***Cq�+��1c��T�R����;v��/���(
0@o������]��p�����W���N�:<x�E,{�c|||4}�tEDDXl����U�fM���[6l���9y��~��'u��U���0`����ks>��r����/�4��j�*�u�]z����\������={�z�����H}���6�?�f����~�M5k������NV�c��i�F������!C��=9��D���F�e�;��W�j��)�Z�j��-g�U[�n��={Z�'''��{���/�l�GJ�������6l���u�9���+����}�d&��������s�***J0}��
2��l&88X������f�R��a���T���������/��-[����_��^zIAAA�U��"##���P��������o���_o��+88��Y�=������Y��������Y)]��bbb��cG���/^������[U�VU�J�T�D	���GIII:}������m���48/�=��Cz������r�m���:w�����]z���h�Y�&���Rt��f��e���
������O?��/^�Y�fYl��q�������x�������S��z��LW�����
�PN��Z�j����=����'Of��d��i�F���Spp��?���.\�`:�|���z��G�'O��UKU�TQXX�������d]�pAqqq��k�����zY9r��>��C}�����'��U��J�*),,Laaa���Rbb�>��7Z��7�0a�������������f��>���kz�������e���P��|}}u��)���h��}����/�8�Z�'+P���,Y����[]Uo���Z�~������+�J�**U������'O%''������o��n��T!����F��x�b��C���}{�*UJM�6U��%�����g�j���Z�r�RSS3�S�hQ}����+��#((Hs��U�f�t��	�����S��m�f���D����Pzz���?�c��i��
6>���w��#G���`.�7���~�2���>����t�O���n���;v�~�a�m6lP��uU�zu5j�H�z����=��k�Z��/�������T�9���G3f�Ptt��o�n�����V����&M�(22R����������u��Im�������n��I��U�V�;����^{�b���{��uk�(QB��7W��������'O�����j���j���S9����|�>�@����R��*T�����+88X���JLL�����{�n���S�.]�4f��]����y��WM'�HNN����5�|��6m�T�K�6���Q��s�E���k����o����V�-T�\9*THqqq:x���-[f�����������3��R�Ji�������,����_�Q��j������+""B���:s���l�b�*i�V�������w*��j���j���i��������,W+V��f���%K�Xl��:&22R���W�V�,�gNMM��?���Q���j���J�(���0��������p��N�:��[��v}��������N�����w�yG�����V�����[���
		����;vh��������];
<�����~�o�^E�QTT��/����:uJ�6m�� �n�����e��g����~k�z���G��{�U��e���8:tH+V��������"##5r�H������c�c��ehOOO����5f�EEE�B�

������j���]�v9���-ZdQ�Y�zu��Q�e�����=�J��Sll��v���JO�-ZTs��Q��55o�<���H�������C�f����{��;{�NJJ���+�r�J��		���sm�
�S�X1�Z�J/������K��M���k���"������y��h���tR�P!���V�KKK��Y����+**J���~��q�h�N�:��/_��#���}���Y]�v5�+��f�?|������m������
<*T���+u�=����#��\�R�[���j���������'�|R����cRSSm*L�mRSS�u�Vm����������g��S�N������������h��i/^���F��_�1c���f<���?~��?_�����y��L������j�������z��L��K=���3f���c��i���Y/$$D�������+22R111j���������f+ wy��W�g�}���No5p�����Zx��Tv����f���_~��t�-������9s��U��)z�
h��������{�+W�����r�q�wsO�&~��Wu��1����8q���������Z�f�r�u���m������V�?��&L�`��]��u���5~�x��mM�F�4s�Lu����<�����*�7��3��IW���?�P���3]�[���5jh����qF��U�.]�h���v�_�R%��?_%J�p�uL�:u�N�:Y�d���wT��w�yGy����o�i�{��].-�r�1c�(999���7����^7��[��.\������W�}�����L������v�������I���{��������5o�<�s�=���iiiZ�t��.]�i��U���~�z��(��S�����c���=�y�P�pa�X�B�~��
,h�>�������v���:u�H��J{�
ri��`KA���q��^�k�VLL��6m����>���7n���]�������z���={���O?u�jN��h���o]~�&M�(O�s����_w�}�S�����r����(��������g��7����d���GC���9sn���e��QLL����.�mk���������8�����i��)�>}��)���5j���0������1E���3�����4nnR�P!�Z�J:tp8F����|�r���N�b���s��N�u%ooo
6L��ow������Km����-[4e�-Z4�}>��c=��s�l��Z�j����[�)SF����O<���mvM(����O�6mR�6ml��B�
�={����+���H�=�S9��4]m����Z�d�Z�j���<O���l�2���k���u:��}�n��i��_~��F���k�������NO<����Zcv��7o^�n��e��E�5��[7eK������?������+���+�?^���.�Nj���V�^��U�:�J�*Z�j���m���\�z�3��w�}���q�w@*T��
��o(00��}����W^yE�7oV�2e$��:�J�*��e��z���I��/_>�L|�	^�u-X��������s����&M���?�\���s*�O<�������S��-Z��g�O�>���?\��v�j����+;��F��|�r��/			E{���N�
�;S���;��|||�������������gOU�\YAAA���V``���-�:h��1:|����������?�X��e�uN+^�x�86l��+:u�/��R�g�V����Z�F��8q�6l��5j8���~��Z�r�V�^�G}���5j��'�|��'O���~�10�]���T�v�mk��ux�@k���n�i���Kqe�Z_@@@�E}������Q��i�&=��v
r���V����i�&���{.���J�,�������7oVtt���9�i��~X�������U�lY�����R�Z�4l�0���O�W�VDD�C�\�w������k���5j8<(�h��:t������]��8��'$$D���~��U�T��������K/i���j����y,[����n���
b��5g����St�sQ�\9�9R������������g�}��~���k����k�����c�����	

�7�|�u���K�.�����1b�bcc�!C�J�*U�`����C��
STT�
.,___����`���_���y�����������c�����g�Z�������'OM�6M�~���+f�>}����]����N|}}����k�����������Q�pa����6��J���x�5�[o������W��}Z�h�M�6�te���m������������B�
�1c���;�?��CP����*>�����������N;v��}���t�O=��N�<���]�VTT�J�*�
851�����7o���cU�D	��-^�����-[��f��N���
*�%K���w���`(22R�'O���m��|��i��Q:y��&N���]��|����/�|||�
*�[�n�8q��;�?�Py������i�����}��q��������}{}���:s����}�s��Z�n���w���?v��j???u��As��U�^��!��=�����s�{�1��Z�h�+V��o����uT����u�Vu����}��+�_�US�Lqi��u*T���5t�P�?/
��������l�,d���+>��c.[iw/�0w'�S���5c��m�?��&O����<�����z�jm��Y���u��%%%)99Y���SHH�
,�����V�Zj���z���W�j���Z�f��n�������JLL��+W�
�@�*\��j�������~��*U�����0m�4��:�
��q���Q�r��i��9S+W�����u��q%&&J����U�D	U�RE��5S�.]l��6o��%K�h��
���N�8���$���*00P���*X��*T��J�*�f���������.\��5k�h��
��o�8��'O*11QIII���S����J�*����V��M��E�;����ah����7o���_�������JMMUPP�J�,�5j�u��������^�xQTZZZ��y���]�v.9FvJKK����o\�:tH��SBB�._�,??���B�
�f���_������
*�$���t��?_�-��U�t��i������K������T�����eKu���bE���<x�"n�r�\����s�4g��\�R;w���c�t���}P��%U�re�}��j�����% w��{�i��c����v����h����q���9���8���*<<\U�V�=�����������_!���s�������#:���]��|��)88X��S���U�F
�l�Rw�}���A�����\������~������~%$$���Waaa�X��7n��]��V�Z.=�$��;�b����@>|8[V�sD\\�V�^�]�vi��}���N�:���D%&&*55U���
V�������[5k�T�&Mrm�wzz��-[��j��
:x�����n|gR�`A�+WNu���}���+�k�������j�����q���;�.���W
P���U�N�i�F-[��������:}�t�6___�+W.'�F�����
2�����z��7]����Z�x�V�\y���s��)99Y���7>��S�J�T�re��__
6t���vc�bcc�x�bm��A��3g���,___���+W��f���E�6������?�Y�fi����c������4�x���T���4i���;g�gc����3g�/^�#G��x_�l���[��:v��6m���
�����O?��E�i������t��5�D��Y����i�.]�d�*���n����������w���/�m�����=�����U�D	�#�}���{�97e �����J�*��o�����`;v�Y��N�����z
6��5k����2~�x=��������������/h��1�^{��;z.�Q			*T��RRR2���=;����+W�T���3����KS�NuSF��rfJ,�C��=��`O������
������#FdhKLL��_~��� [�t�E�;����L���'Z��:��:�^w���_/�����r���'[�y{{�Y�fn���}��~��'��w��=(��+55U����E{dd�j��������zH��W���������+n�r�[�7o�\-[�tS6r��Y��m�6��[W��F\\��o���m��!
sSF@������c�Z�7k�L
������;4��m�=����+���p;�hw��^{M7n�h��G��
�������>�(C���g5a�7e���s��s��m�����=�'�x��=88X<��2����e�d���(�^x����az��'t��1�m}��qCF<��Q�2������)�.(�@���h���+�*%%EO?��>���m���4h�+R��i�F;v������*!!�M@�r����-[�y��n�@V�����C�������~�z5i�D�����z�)�����&n]���_THH�������^SLL�C�&%%�k�����_-�/^\�<������6n��3fdh6l��/���p��h����k��CU�TI����m���'))I�|���V������>����Rxx������������������������-����o���L�*99Y|��"##�������i��m���o��j���N�<i��H�"z��7�#e�2^w,XP�=������?�TTT�j���?�P����r���x}��'�X��f��i��O?�T~~~�N@.����f���B�
z�����n^�#K�n��sg��=;C[hh�j������K���
Tbb�����s�Nm��EiiiVc�l�R���|||�;}���~��;n���_~��d��[��V�Z����u�]w�f�����Phh��P||�N�:�5k�����Vc���h��E���{�;}p�����-&p��w��2e�(44Ty������-[�h��]�lXD��}��w�ew�<P||�>���m���S�����n'� W2+�sF�v���/�(((�e1����9#00P?���:t�������9��'���	�'O��@�����N���<x����
��e��QLL{ ���������o����=@��h����>����;\h�����={j��];v�|||\�!x��e�j����V���1"##5i�$���W�k�vav�{��7u���������������O����z���\����0��I��z��6m��5k�h���:|���?��/*99Yiii*P�����T�P!��][������R����>������z�j�_�^�����#Gt��Y]�tI�/_V��y���0�.]Z��7Wtt����ny{3' p�K�.i���Z�f�v���#G����JHHPrr����n|/����+::Z��5Spp����(��E�
�h�h�h�h�h�h�h�h�h�����.h��7~/Y��������^�^�������=**J����K�c(��@+V�P������1f���N�:�;
@�vw�.(��E��;9�d��~�5k���/��l2JJJ����o�^�~}�1#�������������{����w��s��7~�u���E�p�����{���U�jU7e�QBB������W�\Y���wcFpg������������L�����������p��p��p��p��p��p��p��p��p��p��p��p��p�<�N�3C���2���@�������������J��B�a���+JLLTbb��]�����-|||���`������P���$''���SJIIqw*�viiiJHHPBB�$)88XE�u[���[�
�$''���c�����:z�����(��%�����T��]�zUG����Ws��yr����a:u��E����������� �������M@�2Ciii�|��������)55Ug��Q�R�r4/��r�+W�(%%%C[pp��/N��;����T�@]�vM����k�nl�t��RRR����c9y������������R�7���S�������l����9�E{���E{����`n�'O���?CE{��0]�v-C[PP����vk�^JJ�����S������-�|}}��	x�[����h��lp����2���mY6g6J�?���m��=\��=\��=\��=\��=\��=\��=\��=:r�����n������)��������L;b���_�|y���J�>��n��3��Ow'�������{�j��]:s�����F��V����Y�������������j�����������>6$$D�z�����u�]w�`�@���0%^IQ��kJ��"�0���h��������3b�w�t[��5���vw:<P��}3�G�qwJ�PW�^U��
U�lY���+Z�xq�{�t��E}����V��F��?��<��2}�����[�*�E������(�" dq�'8
��,:"��((����(�2�(

(�Z@v
�����}�����I�����s=�����}_I�'�G�^����p]��\�H|�V��S������4]��3����f�j~S���W�0V
�����i���6�y{{�f���V��222���\����\�7N�N���9s*�d�)��%�I��
'�#�B�s.f�isL�6�$��
'��n���v���Z����e���t�P!����'�|R�z�R�6m���a>����o��F����N�>m>����I�&=z�+J����������������J
���#���.��1_G+%#��P�������O:q��&M���;Z�$�J�*<x������M�s����.\(��O�%��Pa����Y�i��?�j��{��=�~���4U������������i����.�2�	�������������o�qf��S�@�8���nSBZ�C�KH��c����Fxzz�O�>���V�Zz��'-����O�*�p��.����\E�k�.f�9t��Yyzr��8���}=������P[�l��c�/ooo��__�;wV��U�Ojj�8��G�*%%E���


Rhh���i�����u5u���8qB������WHH������];���]������g�bcc������B���(44T���W�f����w��gffj���:w��e4��M��e��vu5���L&���_G�����u��E���(,,LM�4�m��&����2K�����[�*..NIII*,,TPP�n��f5o�\����.����m��]���JJJ���������Q#�h�BAAA�.������e��;wN.\P�j���m[�h���kcbb�m�6����2�U���u����������S:x����9��/���]!!!���P�������G���������.���[��WW�&M��ysyz^��{^^��l��(55U�]���v����`�<�3g�h��]JHHPJJ��;�����W���r-����>��c����3.��:���t�VtX����r4����5 �)�WV�9s�f���?������hT�~�4}�t��[��������_�5k�h��}2�L%��_�����#F�J�*��[R�l��)�2eJ���_�^��u�8f2��i�&-]�Tk�����GK����n��/��A����|�^�l�f����[��:�h4���o��>���G+$$���7o����zK���SN������P�5J�������ku��M������_������I�4y�d���g�����S�b�
%&&�8/88X�{���Q���sg����,��UK�������@�����-n���j���y��m[m����k
�d�}�����s�


l�3�����A�4t�P���&O�l��d�w�$�������4o�<����%���F�o�^QQQ8p�|||��nW(�����=r��&N���+W*77�����H��3G:t�:�~�z������m��9������_}�����cW������������j��u���/q��hT��=5a��2�.���Cm��W�^��EDD(66����������������Q�<___���K#F�����[�PrNN��O��>�@.\�:o4�����;W,����'�|�O?�T��9�`0�U�Vz������k}g��\����.^���J�����p}[w$A��Y��i��?��H�S��L.\���;j��q6{��P��e���ys�_���{��=[-[������w��R{�t��I�3F�[�VLLL���R���S�.]4{��2{�����+**J��w/5VTNN�����G}��p�t�������I��g��2�gdd��GU�N��z��{��N�o���5j��;w�U�#DEE�`0���������d��)S��aC��7���UJJ����Ku����x�*U4d������Z�lY���?��x�����?r��Z�h��j��m%����u��=z��5k��r��H[�nU�F���s�i������h���1b��.]Z�U:���+��eK-[��f`O�j����V�Xaq|��)�������t���j�*�k���{�$u��I�������K
�I�.k��Q���5z�h������#��7O�������K
�I�������O�>}��=��;����k���6{���b��%j���������o��[n�Ec��-1�']�y���K}���<����2�v�{JE������scGv*���Ts7���}~=�������e��������{�n���A�V������]������o_-Y��\�dgg[���W�Z����|�?�*�q��!u��Y���Shhh���Ugpp�������%$$(..�b��M���G������k���
�H���������K���JLL�����Ubb�z��m�����n�I5j�PAA�N�>�������xu��M?���:u�T�=�uyyy8p��/_nu���S�k�V��U����s������d��Q��������[������E������0`@����_�~�����z���Y��<==u����������Z�����VTT���h��5&�����$�9s�V���7��G5�����U�^=���������yyy<x������
j��i�*!777������K�s����������+�Rk�u��U��BBB�������9s��k��9s����\�SqE��k3|j4U�NU�VM������/���/������;u������p��YS���:~����8))I<��<����2�������c�)++������������@���)&&�"��w��G����_���]���|O��m���b��Q#U\=B{p�#�i�k�����8uAG���8��B��V�7�"�e0��s�i��q�S�����S���;�h��yJOO���>[�������o_�w�}������INN��e����o������k��Z�r��u��]+I��o�^z�%��'�x��0U���m���W�����Ou��Q5k���s��9-Z�H��M3��<�W^y���f;w��l���k��q5j�"""��'$$h����������VXX�X�<�W�����k���
���u�VM�8Q����$eff������{����1������������3f�XS���K��"�?�*���E�����������kq.&&F������K���6m���;��"�6m��#Gt�-��U����-x�?��U
�����?l1���K�G���a���iS���.]���[�|�r-^���z�a���z��'-��h��q<x����k1?%%E�����.]j3\Y�
<X����U���N��GyD>>>�.wU[�v�F�a.fff��W_���c����]���M���������F�����,X�^x�(;t����������+��:u���GQ�����uk����d������s���O?5ww��������_=����w�}��~����j��5�s�-R����%�g��eu?�_��&N��x@����������O������5{����:y��������Ok���������3224w�\M�0Ayyy���g������;��S���
�u��Y/���z��i�KOO��_��_]		�����C/���>����;�=�Z���fu���������=��X~A��.Zw��(������FvqM��f����n.��/��m���~j}��<x���z��i���j���F�i��g�{��WC�)�[^��U���O���S�^���U�V���CV!%I���;%]+U�~}�9{
:TS�N-�{Rxx�^~�e
0@��w��S�$]��6i�$������xH��O?���CK��F�������������.j������_o�k�N�V���������;����k5f���=[�� �o�a�i����=�����W��~�I|������^3g�������
h��13f�~���s�~�i�O���/5�X�g�}f11bD�sh��V�Z���u�m�������^�z�W�^z���]��.''����t9����?�v��6�	V��}��o_M�>���\e���k��u�U���9������Kk������n��X�B���Saa�������[u�����3�<�*U�X�C��������O��cGs�����o�]��z�!������M�f3�W�fMs��h�L������fi8�q��Y����-Z$///����][�������{�n�P_IN�<)///}���6C_���z��f���p�B���(��a~~�`��2e�^�u�����1b�z�������������s�j�����������)������j������saE��!�p��������=�:��m���

�e���������2k�,�L&�������+j����c�U��,��zk�������-��b,\�P��O/�:�UR8�$�?�9����������N���3���Wj'���w�+*33����Y��~�����qss�|�]�vi��m��h��)


���k��)S,�,�bq={��y�����1c���$I���/���o�������=��~��<n���Z�nms��5k�u�V�������^q!!!e������?��V�ZU?����������;�2�������K�{E5j�HC����s%I:~��4h��?���P�$=����6m��=*�r�����R����;��1���K����?��I�����v��S����IR�N��d�������^>m��2��
4H}���o�.IJLL������}{���/_����F������%<<\�|��Z�ha~��1c�URr�{��n��-z���-����k�.�@e��?����dRz~��s���_`�UHMM��+�cooo��SI�N�Zf8�6l��m���[�lq��W�g�����,�q�����JY���]�p�<�<y���-���	&���.]�O?����J�p�B�L&�������;,Bo����3g�C����RTT�y���d��T��t�+�!p���v�\�x���O�;�w=z��Gt����9���:��+��B2V�FGG��H;t;�~��K���nnnZ�`�������������k�c�=f1��gO�s��.�����������n�M}��5�W�\����y�zO�KE���+11Q�x>��i���G��*����k��KY�z�O=�7FM6P�����������zdo����S�/e�����u�V�����}���;�U�z�2;9J�z���;#��(u��5_Z�E�m�������s��?����{www
0�\�����"��q�F���Jk���2���G�)��`��?���yyy���/�c
4���6l0����K��x-9{��>lW�Z���x�x��G����Y3���`P�~����x����3�WE���s������E ��{�U��
��_�~�J�fXT�-,�����y�����c�y|�}�)88�\u�u�]��/]�d�9w�{��*''G=�����������h4��2����k����zp�qu�yT�I���KJ���K
����rI�IT��G�����99�E\�h�@��u�V���;����}��G4h�n��6��QCU�T��`��������effZtr���XM�>]�<���4i��������f�E;�%%%��f�^�,��
��3���z�u�L&m���<n����������V�j
^UV�����6l�P=z�0���[��'O�8���JLL4�y����k�.��zdd����P�s�{��!///Usmh���]����I�Cr����_��f�g�w���W_}U�{�V���"�{\��ci��������Z�nm����P����m���i�L&����:u�X�m�����r�*,,����-�<�F}���j���+��\C.������z��S�v1�\�n�����O��C�u!/�I�U�N����T���������a��)<<\�?��/^�(11Q���v�QA���O��T������/k���:r��������{U5>��#j���y|��%���K�Q�����.M�6M�6m����.� /\�`:t�f���������(�^eu��	����f����O��7�L����J�[���#J�[�;Ce����W�n�<�+�������7n������]�vz����z�j�:uJ)))��/�����W���x�4�����������������O�5l�����r�z��g�|�r��`0h�������]X�8���q�R�z�8���W���	)����_���<p��������R��'N�Pdd��������\����s���c��j���V�\i�%�<J�yxx����S�����Y�v�&L����;+((H��w�|����R�KNN��:KSR����h��`0�Z�j��o���.\h3�t��i�����q�&Mt�w��n�pNyBE�TY�v&oo�
�NR���y���k��������{qE����\W�}��)��	&h��y�f����C���"���]]�r`�_t�R���?Z�����c�"����Uq��*�����8�����d�v�N���ZGk�c-*l��j^yH�.]�d1.���,��
�&77W�{����g-�7l�P]�vU���.___U�RE��<��w���5k�U��JNNV�������~�:w��
�V�Z�R�����-�|������__{���|��?�X���������
6h��
z���5j�(���[��������W���_��������������{�xxxh��a�:u�$)..N������k1������sZZ�=��vI���sP��UY����_�^�<��E����]�:uR�v����Py{{������^�zUH�����"���~O��L�6M��M�86q�D���.�pB{�b��5p�I�����_������������Q��T;�|�-GjW/�BC{�������R��]fff������{���su��1��F�Z�p�����2���?�Y����[o�e��a��Z�h���m[���
=�����W_�+�����7k��u��a��o����,����������f����oV]�����iS��5�\�W�J�o�����������L:%�7b�M�6���?�Eh���@�����c///
2����*��VU��o$/���E`�O�>�;w�n���R�sv���l����)��������>}�\�����/u?G��\K����	&X3f��L�����!�.��cg������s����s��i�S���<���>�p���k^a{]k���,�III���h��,_���x������]�^�p�\u]�%K��������?�XjH��+����M�;wV���5i�$���i��]����x�b�����=zTQQQ���,�(f1�L���;����IHH�9�g2������pJ��uu��wk������Qg��5�������R��U������DW������c�m7k�L�~��<==���"���^Gu�������}�f��r_v�{����/������Y6l�f������r���mm�E�HLu��&�hm�E��%�%,@m���=���Q�0��'^����8P�����o����B����<n�����=I:x�`���Rg�����i�s�=v����t��)������:h��):v�����c�n���:|���5aaa��N�>��<�4�L6lh1��k���5j�����-X��<�?����#G��^E��H�����m�,����+�'U��X�>^G����
�U�+yO�|��76l�EW�G}T�����`pae����s�b��HE��<������z�������M�6�_��\��;?99Y����q��������c:w�����$Y|��,			����q�F�����}�Y
8����M�,����;����Lm�������/�y�+Z���-���&u�}�)<��;,X���B�������7o����u�V�z-[�����y���x������u��)''�E�������[��\{]���"w��{����>�`�{���^�ZTAA��X�>}�h�"��p=��
.r�R��]�����]���KY����z�y-����E-u�%��{\�:v�h�a��������611��E��Fnn��5~���v��$___�qff���Vd��U4�'IIIIVs�����G}��z�>��y�+Z�������RSS����h��������Ok��5Z�p�Ehu���vu����P��=����|����V�Z��������d}���.�E]�}.''��{�=��~��gO������W�������������Y�f���'�z�jV�?����������~�����{w-_�\.�p>B{�"+R*t��$�V�~P��nU�/��]#�K����)kW&AAAz�������lM�4��k�������Z��E�b��m!�������!������S���6,,�blo��~�A+W��{�+Q<Pl5g���


2��/_n�����>����N��Z�l�N�:��iiiz�������#d4��O?�T�}��y������(��3f��x���������Ng+^������jP����^�u�.}e���q�54`�����PO=��
�U���7�b<v�X]�x�E���=�)��k�.������_�����k��U���vae@� �.�^��&:�b���-����|X[VqlW��*�|X[�z�=�0f���_s��)�+�g�}fD*��hT�v�����8��1��kbbb��o_������$EDD����<���_��b���S��������;wj��%�^�c�
<�\54H������SRR���V�ZY���/�l�����U��U������c��:��[�zMJJ��
���$EEE�`0���f+�I�&Y��/^��c�Zu+�/��b�^���������+V����������5j��^��=��sg�8''G��s����.h���v��(O<��n��f�899Yw�y���=k��������G�U�
�c����s�*&&��k������{��{�OH����1a�yy�/��q�F
0@999v]�k�.��
d�<;vL��{����O���������w�y��=�������W<xP��s������Z�h���W[���3B{�&�I��g�=����g��Rp�[��dT{�u����%�������w=�����z�)��d2��'����?�?���bnll��y��9R�T�n]��2d��x��	z������hq<))I3f�P���u��5n���}�����gO�855U����;����+W�����*�+^��!C���o+--�����g��k��K�.JII����������n���i���4i��n���L�?�����e���]�v:}���x�����M�k�?^�{�6��������_�~Z�n���Kvv�v����S��U�Vj����.]Z�c����,�=��^y�-[�Lk���x����\��;�����7�c�f�R�V�����*#���ALL�f�����[��;�,�~�F�*���#���$-Z���c�����m�j��q:r�������]�V#G�TDD������{������%K�X�:�f�������x=�%55U+W����U�~}m���"K�a4h�@:t0������K-[�����}���c�������dR�&M��W�n����������~��i��Z�z��}b���V�7m��*,�l�2�z������m���=��>�L��wW�6m�m;��h�7�|���@���[��Y�f�4i��;f����������Q����(>|��\g��T���8�u�]JNN6��������k�.����������)G�TP����
�35�@��s7�=�����8��&wP+�������-ji����a��3fh�������t9���Gi����W���V����$�:u�|����>��c��Xi��O>�����d2i���9s�6l��� %''���S*(����&L�P��[/���V�Ze������+��bs������[7����^����osG���\�����8q�7n,___�?^�����?��_~���X��<|���x�
���2�����"OOO�������V�}||�`���tss�����������L&�X�B+V�����"""���l���������=����zKIII�.�J�5i�$M�<�\�;��i���X����������S
		QFF���=����+�����V��u�^u���
;��N�:���o���������{�����{O����Y��<==������X^q����U+}��2d�9,z��E���kz����5j�`0�������?h6QA�{�=u���|������>*???5l�Pnnn:{���������/�T��-��'44TO<���=��{Qq6���G����'5s�L��'N(**JF�Q�Z��rrr�����]_Ei���V�X��~�"LII1���U����0���*--MIIIW�8���RQ�=j�}0##C����������@n�k��C������}=5k@�D�V�z!e_PD�z!�WT�I`�Z�f�Z�nmq�d2������s�E`/  @�V�*W�%�\�R
6�8^XX��G�j����������o�?���r?��]�j��Y���U�V�F�����u��A���C�N�2�������_Q��


t��iEGGk���:z��U�"<<\?��s�����@�]�V�����n��%''G�������o�>�>}�f`�v�����o��F���v>B�rww��_��^{��u�������k���:p��U����	[����zJnnW�q��]�j���6��o�>���S'O��&{y��G���?���n�:w��9���G�w���3g�T��;j���V��.]Rtt�v��m����_EFF�{�>�@�z���z��}��3G>>>�

��Q����&{����v��i��]RR�8��������6��`(��\�#�STB{��n�����}������Q���.z��������X��x�S�jz����il-�A�o��"W�V���n��w�yG5k��9�h4�����o�Ew:{��SG;w��������]��������~��3d0\�������O������G��UK>>>v����wk���2�6����K��m�/�P��v�������g�����-s~�
���o��������]{���k��:z��F�iW��n��9r���YcW��.]����#�={����~��WO���WLs6���7�|S�VTT����J�_�F

>\;v�(�^C���F
6�����iS������?�����R_�F�Q;v��9s���/^��W�S�N:~��f������:���Sw�y���������
oLO>��~��7u����9���6l�<xE�|�rW��~�I?����
�-Z($$����g�}V'N����?o�..((H�?��~����[���v��o�Y;v���U���Gyz����F�:t��7�xC111z��7m�����`"��p<�f������������'--M���7��w����V�&�IM6Pj~���_� w�wjv������F����{0��`p���Z���u�7GN+??_���8��aC��[�����������M��F>�t�
�i�&;vL������R�����sgU�V�!{\�tI7nTLL�.^��*U��v��j��������=�������t��i������W���S���e���@�����u��9���K�t	W�-T�^����d2����:x��������*///�^�zj���j��u��T&��c�N�8����+33S~~~
�����[n����%���S��=��>}�������J�$%$$h���JHHPrr������
�E�e�]������s����"///����q��j���]��+5y�dM�2�<&qYll�6o����8���(((H�7V�����]L&����k�J���9,,LM�6U�f�J\_K233�m�6���JNNVVV����T�Z55n�XM�4)��CE���+W�����T�A��W���K����U�W�y�A~^����+�~����K�.�v`�Z~~~���{���������t��F�Q��5��:��`��}*���X9���g�}f11b����Q��S_�����W��"���{Mu�+��`Pdd�"##]]�U���Q�=�fE��p�k�W1�"�+�/UD8�/�\�����������������+��=p��jW�~�U�~��|����x��QrwwwaE�2 �.�����VL�����j�W�B��>|X����y����Q�F��"PY�z�N���~��������=*���lm��I�����={�h������2�=z�BCC]U"�D������B��"1�i{���;�8m}��.>>^�z�*�|��u5q��
�Tfn�.nto5�Ia�NY;��C�h���n���Z�j�|}}]]
�$����x������nt��A�F}���B<h�
P>>>j���^y�8p@��v��K�I�4����
�����������<=�U��j�W��\����+����2�u�N{p�h�WE��6V��W�N��Z��1�=\�&O�,��d��ZB�=���x����z(4Hs�$j����m���#j���N��!���^���Z�_��S�����YJ�/(��I7�R�@�
����kX�*j�WE�d2���_�[*����wtz&�=ssu�z��E����{�2+�"Gh*�����E�eTp%(��T2���;����UJ^~W���@%`;�'I{�2+�Gh*�Z^
�t�yn�=�"����`(��^t:�=W"��PK_����2e2�*����TB%u�K�����\
�Bh*���UJ<��Y���(B{P	z������s{���
�=��"|l�Kh�e�@%�o;��?=S���
��=��"|m�*4�hfvW��TZM���i0�<�'-����Dh*-/77��W������
��=��Z��<Nh�5�@%YBh�hF�2�*�@e+��`����ruI����o�n�J�;y�d��6l����c���zx=����J���^��}�Y[�@eV�����6�E�gVp5�'33S
4���H�_\/�@%�f0(��v�����
����a����'O�����KE��n��������(�{Ell��K�u���^��'\]������()�G�=���dR^~�r�
��_(������`;v���Y�\]�4��.puJ
����SbN�B�<*�"(���y:����K�J��S^���zF��|=������(�������<y2�+�Lnn��z�)J�|}}���������Tr%��$):�n{�]�)9�����A������\���$��t>-W����/������O�qQ��ZS�N��$I���5j��+��Tr�==t���nz�i��\{r�
���Em=�����r]�����GS���E��:�B8������o���g�����+���\"�}m'��Zs1#O��'�lr�U�s69[��'�bf�Bp���B=��S����$=��Cz��][�$��.p�"|���T��{�3Uh2��`������y�x(Ey&����W��S���`�x8d��Qaa��l��c��)>>^����_��:w���U�:l���T8p@G�UJJ�rss���P�i�F��j$&&���:q��RSS����������]�v
��=����g����*--M������Qhh�����f���������������u��9%&&�h4*44TM�6U��-e�?7h2���~9rD������������05i�D��v��F���,Qjj��n����8%%%���PAAA������ys�����D��}�v%&&*))Innn


R�F���E��D�KNN��-[t��9]�pA��US��m��E�2������m�����`0�V�Z����������S�N����:s��.^�(www���(""B�������3=zT���WRR�.\� oooU�^]M�4Q������yU����i��-:p��RSS���k�k��
v�c8s��v��������(00Paaa���;��}���)��>����%I�={��+���\"|l��_��Y9j��]�����Bm9�����_�
L�r8U=n�*/7��]�h����9s����O��F�Q�������U�n�+�#::Z_����Y�}���d*��[�~}�3F#F�P�*UJ]�����)S4e���[�~��u�fq�d2i��MZ�t���]��G����m���_|Q�
��{�>n�l�2��9S[�n-u��h�����|P�G�VHH�]�o��Yo�����[����sBCC5j�(�7N���%���[7����V����RC�&M�������"�9sFS�N��+���X����`���[�F�R��������T�V-���J�W�k������y���q��m����j��%����s�N��g0�A�i���	M�<��w���NIrss��g�i��y����K��7�j������4p�@�����������_����#�8q�V�\i�VTdd�����:X�[�~�^}�Um������`������>�Hu�������l}������o�n�:����8�h4�g���0aB�?��j���6���W���"""[��IIIz��w��W_��?�(q����z���#F��{�-W(9''G��O�|�.X�7������y��+
������O>���~�C���c0��U+����z�������S*���'������o���j�������_&PI�L&��� K��9�����J�7�����)J�?6]�y�NY;;�P�c���veu��u��Q������.���-[����k�����c���j����O���{����.X��1j���bbb����7n��t����g������]QQQ���{�!��rrr��_?=���e�+���}tt�&M��={��9?##C�>��:u����W���.w|��7��Q#������!**J������L&��L���
j��ye��RRR���_�K�.��T��!C���/^��e��]����-�#G�,u��#G��E
8P��m+1�']~�{����/��Y�f��6G��u�5j���{N���/�����@�7o��#�t��
���V�\��-[j��e6{��Ps��]�b�
��S�LQ��=m���?�U�V�]�vv��$�S�N����/^\j`O��sY�f��w����G+??��=i��y�W���O�^j`O�|�����>}�����v�q��9�o�^'N���.?K�,Q���]���}�v�r�-;vl��=���s��]����x�edd���3�S*�^]��#��y���:t�3�<Sa{�@�=�������KG��������nn^���!o�0����[|�u(#�j���L=vm��7����M��|�#�M�V�j�
�r�>�Azz����.�������`PDD��U����$s���4���WK�,)�>���?S��UK������������R����o�>������][u+,,L���QBB����,�l��I=z����;���6|�p�`�t��]xx����������D�?�\�'&&�w��V?OI����T�F
����JII1����W�n���O?�S�N���Z�����j���V�<==U�vmU�ZU:w����^IF��?��<�?�E��,YYYZ�h�y�����8����������W���5k���S.\Pll�
�x.����ZQQQ6C�5k�TXX�����t��TX16o��G}�����V�z�������O[�����i�����w�6l�i��Yt�TDD�����K�.������_�~��w�<<<J���}�V�Z
		����222t��]�x�b��9s����\�SqE��k3|j4U�NU�VM������/���/������;u������p��YS���:~����8))I<��<����2�������c�)++������������@���)&&�"��w��G����_���]���|Oq��>�L����$yxxh������TF�����qR));��}��9��9��:���3JI��F��:� �yt��j��,�����!�w��\����`�s�=�q���N�:���N��;���y��)==]�>�l�����R��}u�}��k����%99Y��-��o�i���#Fh���6�]�v�$i��}z������x��R�T��7�y���_���W�>}��cG��Y�j��s��h�"M�6��:x��^y��R������"�����q��i��Q����������7����+��[aa�`���^�������+,,�b���[5q�Ds0"33S�?�������U�Z�=c�s��W�^����~�f��QbM���/���0~�x��^�-����������������}������/mvl���:w���7J��<r��n����Y�|�E������/���z���-�{yyi���6l��6mj1���K��u��/_����U�3���SO>��EW����7N�V��u-�������~���Km�++���+77W�j����S��#����G���jk����#�����L����;v�����K���i���~[��u��h�t������/�e����s���e�U�N=��#����Z�nm>3�L����5w�\}����������t�������Z����6���}�]�Y��|n��E�Q���ZJ
:��5��~Z�~}M�8Q<�����-����������W_��k�x��u��I����������cu��7��gddh����0a����$Ig���[o��w�y���<h�����^~�e����"��������Z����$I;v��/��O>�����|Oq���8�7�<?~�n��VVTB{p
)(�����t��}���jd��l��^�RNa������@(���yJN�������������#���m���~j}��<x���z��i���j���F�i��g�{��WC�)�[^��U���O���S�^���U�V���CV!%I���;%]+U�~}�9{
:TS�N-�{Rxx�^~�e
0@��w��S�$]��6i�$������xH��O?���CK��F�������������.j������_o�k�N�V���������;����k5f���=[�� �o�a�i����=�����W��~�I|������^3g��[	��l������1c���_~�9����6����?����E}��g�#F�8w���k����Q��v���~~~����z�����~�%�rrr,:�I���?���j��m����`���W}������-:�Uv���j�����[�Z�jY�3�����v�Z�~������+�o�>���Z�x�U�<///=��3�R���=����g���O>�D;v4m1��������������o�o��i6C{5k�4����$��;��
k�����-I����-Z$//�����kk���>|�v��m�+���'����o��V�{��:����_|Qaaa��.�?���;���k����)S����_��5���_#F�P�����{w?~\�4w�\�9R���V�8�=�U�}�YsP�a��z���\[PAHp�5"'�������{���3���\�I/e�<��Wh2)#��e_��+��K'2]�XM�
}����5K�"u<��s6{E�1B��/�^��zk���������W_Y�.\X�}��U�Ve�������������,}���%�?v���{??�R;W�jUU�^�����LM�>�<�Y��~���2�s777}��j������,:�UfS�L�8P�f�*1�W\��=m���U�Z5���/��������������-Z�u��6��Y�F[�n5����J
��-Z�5��>��s�Po��U���?��+.<<\�7vRu���CK�.�
���Q#��UAA��?�
���?/1&IO>�����o�>����ZS���K
���W/���;t��!���S�N5w���N�:i��%%��k�����o��i6{E
4H���3�-:��|�r8p�<5j�&N�h3�WTxx������TI�`g������K�����<�7o�E7B�zv���������sKUX�s�k������@�&������������e�j��$W�QaN%d�T�k���]-�����������j�������U��$S�N�;�t56l��m�j��m��-[�8u�+��gO��Y����e��}�Y�s�v\rss�;<V�/��B.\0�'O�\b����F�&L���}�J�.]���~�I�=��Cj�e���Na����"�����9s�8dm///EEE�����$%%%i��e>g���W�C�������R���O�n��v#z��Gt����9�����s-����+���)�:���x@�����Xtt����������y�e���O!..NK�.5�����`���/��s�=g���{L��o7����cz.��������~�m�k������o_�����+UPP`�t�{�_*�^����d�.�C�U���+do�Z@�=p���,����W��$w�I�=�m��N�������[�*'��E�����!��������Q���g�>::�B��u��5_Z�E�m�������s��?����{www
0�\�����"��q�F���Jk���2DAAA[�����v\�%//O_|��y����A��8w��
����{�A�k���gu��a��j��%>��#�<b��f��Y�
����g�����g�����r(z/��{?���_TPP`�{��j��������_���*����?��9/99Y;v�0����>����������K�l>��zOq��c�*11Q�jE7
B{�b���SAA�C�j��f���tB{p�+&��n�������/*!!A}��
��n�M5j�P�*Ud0�����+�u���]��-66V��O�#�<�&M��z������Yg��nII%w������x��A�1c�RSS��N�����7���5R@@@�����U��U�������x���A��
�G����u�t�����\��H�.��m���k��k=22Raaa����?�=z��������6�j���yE���!9{C^��MK��a[v���W_}U�{�V���"�{\��ci��������Z�nm����P����m���i�L&����:u�X�m������
�W���E����3g������=p�����t����+)������|�����:u�b\��SY�wv�GRR��
���p=���Z�x�8���Degg��FEN�>�|P�����/��������#JJJRnn�U���#��i�����K���K/�F�����4m�4m�����C���p��y|��!�������?o^��z���',�W�)��O?m��d2���>+qn�N|#F�(qnE����ng�^��]�|||��:[��n��q��7o�v����������u��)���(?���;�^\����A�����Z�Kz�����_�{r�>},��u_v�{JEKOO����s�=8p�+\���PJ�N��wk	�=I��^q�P��.�wj*Ky��8qB�����������r][TNN�_k�;v�y��Z�r�E���(-��������N�7��f����0a�:w���� u��]|��J�/99���,MI��*�����j��9|��}�Zt�[�p����������?��M�4�w�Q����9�	�Re������+�:Ie�������]�j���W��3���:r�s]Q�eg��T�W^yEg���t9���'���"�5�]]��rr�+;��C��a�V�[�R
=���L9��!��p��t����x����6T���\���[g���8��aCu��U�7Vxx�|}}U�J��w�}Wk��)WmW*99Y�{��
F�~������4h�Z�j�J�*�������_�;S�~}���G|��>��c�;g�����m��A6l��/��Q�F��������g���������kV���t��>>>rss|
6LS�N�$�������W��}-������xNK��'Y�.I~~~���*k�7������g�������S�Nj���"""*oooyyyY\��W�
��zxU�}���)���S!�)S��n���+p!B{�"�.u�����3M[���r�����;|O��*^n�����Q�kW�E]��Wa���y�u��
���*^��G��]fff������{���su��1��F�Z�p�����2���?�Y����[o�e��a��Z�h���m[���
=�����W_�+�����7k��u��a��o����,����������f����oV]�����iS��5�\�W�J����Z������I�_����N	��1B��M3j���o�+((����/����KC�)�����l�U�����/�h����������n��������([�#gt�t�����c��O�>W�f��%����)������q��i��q�^���?���n:%8	8�=p���x�������������� �?7�A��F��_-��BC{�<]�x])((�b���T���������_[�W�X�:�u���U��X�d��{ooo������$���:�����sgu��Y�&MR^^�v����Q�/VLL�y���G�~��b��a���;�����������C{&�IIIIN	���[Ww�}�V�^-I���u��Ys���_z�!U�Z����JLLtp��QY��Q;vL����q�f����������k+�^l�uT����/��Y�B���xO���sp�2�L��Ip��M<�lO.p���\��	%���w��W������8p�\������y�����s�y��E�{�t���r�u���9�?���<���{��eee���S����C:t��)St��1��3��;����u��a�k���,:��>}Zyy~�V5l��b�k�.��5j�(��Z�`�y<�|��#G�,s�����*k�7�m��Y��nW`O��{�t}�����g1.��HW���5���L�*,tNK��B{�����=�$�>���Q!{U��P��{��u-j������_-����ONNV~~�y��qc��8v����;g���A����WB���/O�7ntJH�`0��g����-�o���b����;���<�������^O���R����u���b��nR��w���������Pqqq������4h�n����^��-���cGGG+>>��5;C��|��u��q�g`Q~Ws�[�n]�����qE��:K���-��}���������A�]���_O<���:w�u����+W��W�����T�������=�������%iT�����Z��cG�K���.\�`�����v�(�5rss�����?�{�$��Z�L33m>��������$)))�j�=��c1�����VO���<�qE+������Vjj�S�2�>|�y|��i�Y�F.��>�"�X����<���w���j����n��<NNN��_~���P����rrr,�G��j��={�����B��W�������������Y�f���'�z�jV�?���T???�y����*�	�f����v���G\9B{��so�MK���7��l���{����N�����
�r����� =��C�qvv�&M�d������{T�Z�"|�m�6�SI���[��RHH�����Sv_f1����?����>����Vs���� �x���������=�e������y������{�i��1BF��<���O��g�������{�1c�X��O�������t��u�?^qqq.�E]�}���_���W�����QC0���SO���y�P�a��q��c�����.���yOP����rss�jRBho_z�
�����_������s>��������;e��f��1]����SfW��>��"�T���v����qqq�1cF������o������{I�������y��/�(%%��k������p�x���Z�dI�����C�.W��
����j�������U�VV����/�����z����j��r��{�n=��c�����[��'%%i��
��C����d0�_�	����I�,^��/���c�:����_~�{���p�w�}���+t��I�����W�5�^�g������y����{��������w�^��s�'�xB7�|�y����;��Sg�����s�������*����cG����sS�5����{��W����'��A���0a��������7j������)��]�\�4h���p��1�{�����?�^#//O����y���p�{�_*�^
�����`�����H+��:�e�XF�����xy��c� y
eO.�A���I����C�z����c���'�xB�?����������z��g4r�HIR��u��g��!�	&���^Rbb�����$��1C�[���3gd0��qc��qssS��=����T�o�^����V�\������x��x�C���o���4����={V�����t����y{{��||��������6m�I�&i������������e���]�v:}���x�����M�k�?^�{�6��������_�~Z�n���Kvv�v����S��U�Vj����.]Z�c����,�=��^y�-[�Lk���x����\��;�����7�c�f�R�V�����*##�������5K�[���w�Y��F�U��#F�k-IZ�h�E��?��Sm����q�t����Z�v�F������?�)��W���SK�,�\:tH��5�[o�e�z�Kjj�V�\���~����ukE�|�h���:t�`����K�.Z�l�U�}�������O?-���&M��k�n������<������_?-X�@�W���Ol������M�Z��-[�[o�U����@���g��g��{��j�����mg1����oh>�u�V5k�L�&M��c�l^��������5j���������������)g��SV��������U�|����L5����}�4�>�|k��NUv^�U�������>eO����1C�w�Vtt������>�H�g�V�z�T�jU%%%���S�k������[�J3t�P}��'��_&�I3f����3��aC)99Y�N�RAA���	&����/��U�V�;�;vL���������W�n����^zI������rss����j���j���|}}u��y���Ztj������_*66��:>�7�xCo����F�n��&������S���:y��U�A-X���5����x�b=�����w&�I+V���+������+;;[���:{���sn�!C�����RRR�������@M�4I�'O.���6m�4���a���h=������TDD�BBB�����g�*55�������U�n]��B�:u�����S�����[=����������{�����Shh�j��)OOO%''+66V��W��Z�Z��_|�!C����/^�k����^{M����Q�����?�?�������:�����u�f�������G����6l(777�={V			�k|}}���_�e��v��'�x���������������G�����9s����'%�����U�ZU999�����������4n�X+V���?l��������USXX�|}}�������+z�xOP���"�"~~������2���%�������T�@����n��}U��T�[=n�J`�����Y�F�[��8n2�t��I����"��U�V�������V�\��
Z/,,���G�}�v���X���������G�O��]5k�,�O�
		��U�T�F
�����:x��v���S�N��Ennnz������ZQ:}������}�v=z�*\������L``���]����orw�������c��i�����o�N�>m3�W�v�R�		�7�|���P;�k��������k��f����������}�v8p��{�������SO=%7�+�8~��]�y�f��s�����o�v����'O^���<�������u�M7Y�;w��������w���3�*P��5�|���K�.)::Z�w��������"##���|�^�z]U��������#��������_����t��];w����.))I����u��a���`0�y_.���)*�=p/����w��M��l��f��*�����4T��A��_� VUuh�6
���GaKR�Z5m��U����j��is��hT����o�>��t��S��v�����G����f�����O?i��2��G�����O������G��UK>>>v����wk���2�6����K��m�/�P��v�������g�����-s~�
���o��������]{���k��:z��F�iW��n��9r���YcW��.]����#�={����~��WO���WLs6���7�|S�VTT����J�_�F

>\;v�(�^C���F
6�����iS������?�����R_�F�Q;v��9s���/^��W�S�N:~��f�����Ko`����;��S��������WP�7�'�|R�����t�R�ooo
6L��{�t�+�O?���Q��
S�-R�P���>�'N�����
U��\�������{Eu;��7��;vh��U����<==K�o4��C��������o�is^E���v��s��A5k��<>p��n��VV�?iiiZ�~�y��{w��"���8����8e��az�BS��F�t��m�-�?<���h�a��p����=\��0��`�����i��������6lh�u��J���I�J��S��<�����F���<�������s}<��TXX�M�6���cJLL����������;�Z�j����K��q�bbbt��EU�RE�k�V���U�N���.\�o�����O+==]����W��:v���.s:|���?�s��)==]���Kxx�Z�h�z��]�>&�I���������Tyyy)00P���S��MU�V����2)((��;t��	�?^������Sxx�n��V�r�-W]�n�z��i���G���U�$)!!A[�nUBB����������`5l�P-Z�(3��*�O����;������yyy)$$D�7V�-�
]���'k��)�1���bcc�y�f���)''GAAAj���:v�h���Z`2��w�^sW����aaaj����5kVb��Z����m����?�Prr��������j���q��j��I�*�=�^���P��\����������_����N{&�@z���9|O�>������4�L&��TX(��I�n�+��2777u����LW���O��{���w���=���N[�h4�Y�f�]g0�Oe�W+gt�����,�#F�p�5j�p�k�Y"""��2PD��u���te1���Tdd��K�*>>>����C�����qm�*�H��=d4:����v���!�����L���`0�at����<�n��TRR����[�8<<\}��qaE�2 �.f4VQ�Z������u��^j`;�'��@Y>��������F�����+��=�xyUWx����g4�*<�Q�
�y�N{�;|����}����G�F�raE�� ��/���Sg���_�K��\�:~~��z��2��e�E�s������<U����}������i�$)--M{���������e�3z�h�����DP���k��XEaa���q�RRv*;����zy�)$��|}���E��8oZ�zU����F�^�z�x�n���8qbV*3B{p
���/_����I��KG�������xMpp���$���P-/���g5?:��@YBCC�j�*�����PI��k��W5yyu�$�L&�Ly:s�s���[������_C���>���E���i��/�:���������������7U�^��%�J��T�A�����u������q6������%��L&���k�L���+����2�u����������99	2�
��G�����_���\��T���'�d2������J���������$����}TR/���LVB{P�xyU��`�y.;;�����Q�|�m�������nt����1����a�����$E���<�F�=G"����wM��K
����;p)K�����FGh*!/�0����RTP�mu<���^N�I�3������J��N{���ou��*�v3�������nt���rw����k�\NN��17�n���moOZ�Ck����J�`0��m/;�:�'I-l�����8�������y<;;N&���xd	������8�6��=��J��WX����T��%��L����m��@%��&�`�\vv���:��
�0���'���#��J���C���l���3����9?���C��J������99��=I���y���c��J����y�Y/)������\��p#"��XI�=������-�m��$i����=��<<����e�\vv����������9?���U#����`��W��s���6����m����#����wM��mu����B{��3U`29�.��=��J
�\R~~����_��/*&3����h�@%��V�9[����U�����=i�*��Dh*9���<<�l����btSS�*6�G�e:�4@%+��`����ruI����o�n�J�;y�d��6l����c���zx=�������������T�����6�����KYV���8Ajj�v���S�N)55U���
�M7��6m�(,,��%Ch�^^5��~��xNN�L�F���>���d���2��UP�*F�����~���gk��
2�L%������O?�a������*7Rp���i���T���$���>6����6:��
6l��`0M�<��%]��>���usu9�AQQQ����XW��J 99Y}����?����������h�5J���WLLLU	8�=�xyU�������8�c
}��[B7������b2I�iRF���-�������������?�`u�z��j���Z�j���0���w�V���	��R#����(//���"I����=�������E�e:�6(S�A��)��H�����������{���S��C����'O��d2�a��������g���x@{��Qbb�v���]�v)..N���A�,��={V#G�����"��	oo�C{�PBh/���
r�'i���'�M�K�~��S-�d�^>��}����[��j`���D��;���3�<��+W*22�j~�&M�h�"������]��[�:�V�Y��u������yy�*(��:^Rh/6+W����
,d^�����IDAT?%-~T:��|���"-~D�f��upM��������z��z����������4ibq����sx}@E ����B{���ou,��vhO���m�����Y����[��e��I8����G���}����)���qss�C=dq,&&���������_F��

.Y������o=�c��=�����<���i��Y5�i��A�����S�^z��������:f��Paa��l��c��)>>^����_��:w���U�:l���T8p@G�UJJ�rss���P�i�F��j$&&���:q��RSS����������]�v
��=����g����*--M������Qhh�����f���������������u��9%&&�h4*44TM�6U��-e0��1T6&�I�����#Gt��y]�xQ>>>
S�&Mt�m��h4������j������SRR�
��o�Y��7Whh��K�)!!A��oWbb���������� 5j�H-Z�PPP��Kt���dm��E�����T�Z5�m�V-Z�(����m��M����j���n��)<<��j:u��<�3g�����rwwWHH�"""��}����8���G��~%%%������V�����I5o�\���W�~^^��l��(55U�]���v����`�<�3g�h��]JHHPJJ��;�����W����.XvC�]������S�b�������
Gh�#��a����K��q6�G�hu�E���it��`��/�;.����Ti���3[$���]�h����9s����O��F�Q�������U�n�+�#::Z_����Y�}���d2�8�~��3f�F��*U���nI��)S�h��)%^�~�zu������d��M��t�R�]����Oq��v�^|�E
4H�������e�4s�Lm����yF�Q��~�|�A�=Z!!��v7o����zK���SNN��9���5j���'������~��W�����k���I�&i���v�[��9��S�j��JLL,q^pp�z���Q�F�s����YYY�U��9����2_�����_��77���m�����zMaa��,Y�?�P;w�TAA��y�A���4h���������-~�l���$77W�}�����������{������+**J���������_����#�8q�V�\���\��"##5g�u������������j��mV�����~}��GV���dgg�������~�u��)>>���F�Q={���	���/\�PC��y�^�z6�KRDD�bccK];))I�������+���%����U�^�4b��{���
%���h�������Bd������z��w�(X����O>�D�~��:ds��`P�V�������(���~Oq���@�qVV����[�Z5��T47Wpo��6������Qd���D�g��N��~w�3�3��I��;g�J���������g3�']�-[�L��7������������eKM�>]{��-�sg'O���1c��uk��X��zg7n��t����g������]QQQ���{�!��rrr��_?=���e�+���}tt�&M��={��9?##C�>��:u����W���.w|��7��Q#������!**J������L&��L���
j��ye��RRR���_�K�.��T��!C���/^��e��]����-�#G�,u��#G��E
8P��m+1�']~�{����/��Y�f��6G��u�5j���{N���/�����@�7o��#�t��
���V�\��-[j��e6{��Ps��]�b�
��S�LQ��=m���?�U�V�]�vv��$�S�N����/^\j`O��sY�f��w����G+??��=i��y�W���O�^j`O�|�����>}�����v�q��9�o�^'N���.?K�,Q���]���}�v�r�-;vl��=���s��]����x�edd���3�S*�^]��dy��v��a1n���#J*��*���EGG����JIIQVV���-[�A�ia����������JNN��hT��5��U+�z�c[��;wN[�n�������Q�F����C��^��	(MI������������&D���]�+���\ET�rx�n@�~�,w��/�n{Djt�s�����u�]wi����
�"""T�Z5%%%�� ����o��Z�dI������:����Z�j)00P���:��U ���C������������=�+`����`���)  @999JHHP\�e�t��M����v��Yf�����[s��]����������t%&&������?11Q�{���yJ�M7��5j���@�O�VJJ��\||��u���~�I�:u*������<
8P��[�W<==U�vmU�ZU:w����^IF��?��<�?�E��,YYYZ�h�y�����8����������W���5k���S.\Pll�
�������kEEE����YSaaa2JJJ��3g\Pa���y�}�QsX���[�������N�>m�;������k���j����M�f��200PrssSLL�.]�d>�~��i������(�&[��Z�j)$$D~~~�����3gt��E�9s��Qff�,Xp%O�;v�����hT�:uT�Z5egg+>>����������;���#G�����U�fMegg��������$=��:x���\�����c�=f����S���S``����c�������G�������.q}g��T����O����������u�V��'�����7�|c{{{k���N�pB{����wk���Z�|y�
#<<\O=����sEmL/]��i����O>)1A��qc�����T�����_5y�dm����yOOO=��cz��7����t}>&�^^5$$Y�����8��^��fK�i���8��*f�����rg��/�����{N���S�:u��O�:�w�yG���Szz��}��r������}�����S��]-��Krr��-[�7�|���/>>^#F����+m��v�ZI��}���K/��?������7on���������>}��c���Y�����;wN�-��i��a����W^)�����;-[���7n�F������			��q�����2;�j��?����k���<x����,�n��U'N��u�$I���z����w�^U�Z�b�3f�C~�z�2����5c��k�_�~�5W����[�Z�h��_]w�}�|}}-����������_~i��S��M��sgm��Q�����#Gt�-��U����-x�?��U
�����?l1���K�G���a���iS���.]���[�|�r-^���z�a���z��'-��h��q<x����SRR��o�i���6�����������Z�ji���z��G��s����d���k5b�sp133S�������������6m�����V�n�d4%]n��`��������C�4w�\����_�u��SG�<��z�����[[��L&�~��w��;W��?��<.�����{XDTIQM�35��R3��L��\��m�e��K��i�e�u�e���bZ�T�.����� 0�����ss130������#���u�3�p.�1��|����������{����������j���z�--Y��v����RXX���8:���;v�i��u5v�X�q��R������G�x�b}��7�}�#G�������GyDO?�����Z����4M�>]c��Qvv�$���cz���4q��"��}�v��^��������k���0^jj����[���K:u����*r�<��>��#��/�{JY
��/�h{�K��w�����nrx���;��O�>�����I�(
&kqu�Q�������/����*��"���i��Y����\>g�������<���[o�Us��Q���]�C���?���z���\�/��Bw�}w���*�cr�����q�����m��^y�b���h��e�v���]������_)3���{P�

�f��~�N�M�����&DG��\������@�a�����}�{0pup���rrr�w�^C_tt������
��K�)��]%�5*~\�z�j�i�F�"l2����_����wz��34|�p��|P�f�rz����U�zu��L��Yu���@��}�]H������s�����q�U�\�a�EGG�|�=|��:w�l{/�����;�������
�'�9s����\III���S����8q�^x�[�U�VZ�pa��y^^��z�)������'�|���a�;vtZ��(������/l��^?k���v��~��'5u�Tyxx{����]�����=[�
���}��"��u��Q�����n�:�h����6m�h��U�v�5�����I�&��s��9rD��5sx�$?����k��	���e���S'�c333u�u���sJ�A�_�U5k�,v���������A�b��D��PZ��N�:i����
h����Q���s����n������T��u�w�^���O�g�vZ=o��Y�=�i����iS�k������M[�8����z��m[_��-�f��"�)�;~������m��7on�IR�~���W_����B#6lP�z�����kA����7O={�tz�����p

��c���lrrr�m����&L���^z��BB��W���
�m��Q111vcK��"��^-���x�C����S�z��-�����(�L&?~\K�.��y���^xAo��F��
W���7T�����1B'N������I�&j������Z�M���S����-Z��<�w�V�.]��m�*U�
7����h��������G��s����O���L&�j�������Z�j�ciii���{�t-JE|L@I������_i��� ��q��n[�r��#�=\~_�>+������{��9e�Xx��w�������$
6LC�-�\�_}���T�RE�|��!XUZA��n�������4c�[;##C�~����{���}_�R�"+V�jU�����tM�4������/��R�s����i���u�����3g*�]�
s�w�y����$��=)�T���~����jO������k�������%K�=___�{��4�W����C`�j������]
�IRdd��{����[�}�����$��_��������{U�^=}��NCaR~�����y�f��;~����w9�'�W�5j���v�Z������/����nd�k�Ns��q)�'���%)����o���A��U�V�vBB�!X^���o��1Bc��-2�'������}�Y(���)����C_}����}��rss�p�B=������n��v�1Bs����>��m������xW���\]���{}�����F������-��bHs�>}Z}��^{�5��YYYz���{�n���������JLL�����h�������l�9sFo����x�
[�p��U=z��}�]��w�}g��)���7�xC�����?��C�>���l�")3~���R�">&�b��JI�l�������lyx���	
�w'��������<��=��#�e.����
�������������JT��-)99�P\�l6���y���])]���h�l�R�W��$���?�:������"""lA���G�=������=<<\���/���3gl����;��W�������>}�H���?�����{�u���5kV��0��]k���>p��}}}���'K�5��b�����6l�����M3�G��r`�<^��I���������������w�q��O�n�{��������&�Iw�q���L\\�������_�������?�Y��R���������=<<4s�L����EFF���wi����k�2�q�FC��������%
�5i�D}�����,X���\��ei�S.(��� ����\}�����>��~����m�����#
Uv�+��.3��a��E�]�V={��+�X�zu�;V�-����6s�Lm�����R�����/
<���		��������?��?��#���dee����7�=��#�;w�!�&�����?�4|�Djj���W�<�1�lwr�����v�1������Y�+-��1��g��U�����{���r��z���V$r�:u������+�9/F�
E��`��������n���_~�}��������]�����[�U��,Ybh<X���n�����
�
V\t$;;[_~�������A�9�|�r[����i�rr��1������Z����x�����K�7nlh�L&�����s�9�9���J��^,��~��(77�������{���o��EV3,�p���G�:�����k�����~{������[l��?��s^Z�������g�}V���/6�'I+W�T��}u����������e����R�����*  ����t���~��W�����eH�K�����L�8�P=''G���/r]���g�J!GGGk���N��V�\Y_|��|||l}_��v��U�<�1����<<���X�Kc7�d���jzq)�n]��HR�N�Jt~I�t��)���{4h��4i���0����d2�}}��7�����
U�J��C�4i�$���_
6T�������p�+�%&&:�f���
�A�i��)JNN��uZ�V�\����_�����Jt���U�Z��.��R�;h�.]���K�.����_�`�l�����r����_���Z���Qx��B
����y�.]����}�W�o���q������!��������8��^|�E���Su��UHH��������?����KU����,�S���PC���s������Z�5��j�2����qO)/'N�P�-4u�T����A}�����k���?���t���_�f�2�n���K�������rZ=p��]Fv��mh_s�5����\:����6�����t����
����kk��!��1~�xC0m���NoH.�<f����"�i�����tnn�>���"����	�X&�If�����}�=5���p|\*�=�R<x��.\��8�+;�"11Q=��"##���Oj�����m�d�X\�FY>�;��Su�����?����^�v�Rbb����.i����7�8���{�9�����[n��o��������C�A�9s����c��`aq_�O��]����T���7�/&4S�Gy����j�{�pA�+�
6����X{i�R�]��W���8��:���������/5m�T�Z��o��E�����:{��rrr�=�4���~��p�%g�u������K�'����p
G�ri�S���b�-��b(v4t�Pm��E�>��4h�������n��z���n�:��_�������}��W!B��:����pk�������E�0,X`h2�i������Zu�������6��.���c��q��]�R%�s�=��#��r`�5Vp)����
��pAL����T��+I�����T������bbb����+77�D����y���b���j���,X��=t�(*������Q
4�;���~��1c��}{�s���6m�N�:U�|III���W��JP���&�I��Us�}��1T��5k�������������
6T��m�^��{�K**OW��KSq_�}��b���?�X;v��-[.z������uT�uY���qO)'N����m�.]����?�����sL&�^}�U=���>����#G��Z���U���.�\�R������?�lh�r�-.���{w-_�������t�}��4O��m�R���m�V���JO����[{��Utt�KsU��\
__���ss����*o� CL�����4����������p������+5���DJ����={���c����hu��Q
4Pdd���N�bo����,YR��]���$����.q�
7�}���W��j��!???��f�:G��r�n����q��M��?�P����������k���z���5b����k
�[�����~�����j����_��a�����zH����$)>>^?������c��g������I��K��C�W���&��-���>j�yyy�]�vj������*��,___����w/�5V��QY���������\������W_}��=���^��_m{~~��W=z�D�������H�f���;w*--���]���n����q�N����'mm___5o���5���M�69[�X�6m\����K-[�4��6m��0�Vp��f��=I��<i�k�x��J�����U���7)(Rz��+�\�y���k�n��������|E����_���^(4����4��N�>]{�������4k�,�v�m����g��h]����^3TG����W_}�����4�����_|Q/���V�\��K�j���Z�f�]����,���{Z�d����O��S��n����y����0??�K:�r��g�J�}����Jpo��az��7m��3fB{�������mm___
<���T8d{��R�}59r�!���W/M�>]�\sM���v�����J�Rfi*�/?�������%]�n��E���{JY��e�m�j���u��.�_�fM5m�Tqqq�������N�3�+B{��k��Fm���?��#)�&����j��1E�����i���~�a�cw��ih��W�����5j�����o�rrr��e�R*<W�s]��`������W��\*OO?y{WQv�Y�cK�*U�o�����`/O%�����K!�\�<��*Q�7T��
��n[�����0������|��������u��7�t��3gJ��K1g���f�Y���k�!��.v�j�����o�q��);;[����������gk��}���w�Vll�~���5
�Y�V��u�vQ��HBBBl�=������R	���][��z�-Z$)����c�l!�����.U�Z��������U��+u�W�={���M���qc��7������^��uT�v�2��
��e�/���R�<hh��]�P��u��1��U.w��X\��'>�a������/��ONNV�~�����{�w��������.iy�����l6��YYYv���*<����5����w0�#�[,�v}&�I1A�?(.�d��M���|��x��H�0��m�Jt��-�Ud�����u�l�f����������h]���#:q���}�m������p�~�������7��	&h��=����^�h�]!���pCe���+;;�-���EGG����/��F�a�>77W3g���g��a;|��b�W�kw�+u�W���W�C�u�NY��R�x��S��.�+KsO)k��8:*�ToooC;7��8
p�#�w�i�����}[�8''G���j����|�M��?_�������+��������Z���O���w��o������Aq%o�Q�F��������4Wd��D��y*�c��Yh/3���V�?Z�:	���p	���j�)����Ja��f���M7�dh�X��D��:>))I999�v�
\�c��=%��S0� �WWs��S��������*����d�c�=������oC���[m��������fM�U�,X�$�qYk����]���n��v�{g�����<����������WO�:u*�z��7��������'O�u����s�t�R�@����sK�.-�\�����ni�����]���4�zO)k�+������
��W��5���qU��G}T
4��O>iK��[����$���[W�G���a��n��?��(��
�S��R���N2�t.W�q�_SI$$$��	�S8���y���\�Z�!--��6\�����j���3���m���:o�%�Odfko���p����P~�����@�a���>��=�:���aJ�������<m�.�9.cm���������$I?�����9����b�MHHp9DQ8�qa>W|���.����{�������:K�m������l���D�1��v�~��w[����S�v�Je=�}�$�qY�������������W_}U���n����SC���	$�W;\�d�������C�B��x{{�k�����%�w������/�}��T�F
5i�D[�n���������C��� ]�>���i���K���v�*///����E��w�^�
|����H5n��V�v���Z�h�z��Q�+s��R�j��mh9rD������^������v�W�.'$0.S]�t��u�4v�XM�:��R��j��s�=������'��l.��
��vtMg}%���y�W��T~���k�����'u�]����p��aC�<<�?�b���:s���/��!�tx��k��YNF�����}�{0��`(?��P��������#G�{	����J��I��/�9�����Rz��������9s$I�E����{��W������\{T�Z��X�z�rrr��U�[�7m�T�0\�����]>7<<��v���/����<��(��R�����C���W_Urr�$������?��^�z�}=!!!���:t���w�����]�v��eJJ��q}����2��a����������'�h�����������u�zO=��-�'I�&MR�����I���4<��S:t��=z�h���C��*H���;�����^z�%�*}�q�_��.����eyyyz����|��b3��Q�F�����~�i�i�F�+W.�����=�,��__�\s��;f��<y�>��#�����
=�����uk��(mW��v��>}����ZM�<��������{L�k�.6�n�Xm�������������b�reGsU����I���������y����`�t���u�e=��K)�!��T:���<��S��_|�A���O?�T�~���sxzz�U�V�v||��L�R�9���S�>}�����<��J�*�������=����j�Rdd���n�:[����k�����/�
�+V�<����v���7�h7�r��z���m���<�w�}Z�pa���a��{��E�)�ILL����K4�$����d2��Jf+�q��^��g���O?mWq��?�����"##u����������l���{+,,���u��U�����333u�m�������3��i�����<`�r����n��9E9~��v��]Z����i����>}����W�9��&O�\��
����dA�1c��O��_i���pVQ��_�s���hNw4h��y��g�z���'N�|���l}���8q��9J��rAY�����������b���������`�����.3�������}�Q���K�O��;Vk�����g����'Nh�������lt�9sF?��F�����+������o����9�+�\�����"<&�]22����$�v��?zz�<�!��?H�`�^��]��b�^
n��f=������j�<�'�|RG�5�=t��}�Q
>\�T�vm��<x��=f�=��sJHH0�'&&j��)j����9"���
�<�����v�jk'''�u���8q�,X�����U8�Wx���o����C��c����[:t���ge6�]~>~��gu��I�5��q��j�*�����������s��U+>|����iS�t�M�=z�h�����NMM��w���}�j����.�Ek�������o�Q-Z��w�}W�c��c�����K/�������%K���������[7=�����w�yG7�x�������4�s����w�yG-Z�P�n�J4��#�6lX��%I_}���b��'��eK�5J�v�������~�M��WTT������x�K����9s�B3;v�P�����k�^�$''k��8p�����U�V���������7�lk����C��;w����7o�����GyDV�U
6,�\�:u�������_�o���9s�-Zd�'V�\iw~�F����s�����_�/���a ���c���O��sg�t�M.��K����~��Ce�U�V�q��7n�������S�N���~��#���X�������������G�:���|PC����������O����;�����������c�d���]�e��G�?�`k�l�R,�+[���{�w��Z�p����^[%���'�Q�F2d���~����z\q
W�+|Mg}��D!5W�q�_SI<��c�������o����N[�e��%�������i����v��-P�+��Y,��b��0��9���fyx_�N%k��3v�����c�N�(��4*&�a(?��P~�����@�b���\����v�4�������K�^`D~`/����^E�L��
6(..NR���{�=�����S���V����D<x�vN``�>��CC@�(C��G}d��e�Z5e�M�:U���
VRR�<���\�yc��)q��g�yF.�UR��g�^x��c�-[�N�:���=�������*�eee��_���c��A����:t���R��������Z�ry�;w���/���_~Y������k"%''���v����5s�L���������u��w���Y�V��?_����������T�JY,%''���c�����k�����DI��+gU��������������o�����0b\\����n���(**J!!!JKK��c����|�s�z���]���k�V�ZvaGW��UK�����w�i[��b����5y�d���*""B>>>JJJ��C����w��w�o�Q_~��l��;wN�������[���
��d����u��Q����L�<Y�:u��/������{T�R%EGG���C����S�l�����V���]�'44T<��a����p�|��'t��M�:����~������SQQQ�Z��233���O������A��?_w�}�-Dx��Y��_�Z5���+  @)))JLL���Q���T�J��?_��r�!`>k�,��5K������kd2�t��	[���.�����r������,_�\�}�����~�I��W/��;��C|���SQF������0�pH��'I��9��g~~~���4��������`�����"<��

Uhh�%]�R�J


���������vmW�k��$�������6y�����<�N{�*:������}�{0��`(?��P�������;�Va�]/=���h��u��_�I��$*�9�%K��G�Z�~���j����v������`��U��������[7���������4�������W_uX��(;v�;����#G�����G���JNN��J?�<y��
�����Ds������;�@vAdd����[lh�r������������w�5T ���tZ����5ky<$$D?������oW-�r����o��V������
����,�k�Ryxxh��a����e�������qQ�����V�\�~�����.���=���5j�����a/8~���?^N+���i�F3f���a���������R����������5m�4=zT����E�����V�z�4j�(C���\����Q����n�:�w�}Z�n��Xbb�-���d*v_.�������C����������^�^��3g��a�����J@�x��w
���~��������_�������y����+�*���+N�8Q�5/(����U��6g�T�����W%yy9�����4����bzq��e�����Hw*
�N�j[�s��J���O`��j��i��U�8q�"""����T�~��y�fCu:W��UK����O<!������n�Z�/��)Sd29y�Z1����O;w����c��K��QC���.]/&&F6l����/OOO�cL&��w����W��g�)����]�I�&�k��.U��W��^y����[7�|�Ksxyyi��)��{����{Pk������k��%.U����v�����_�{�V�:ux����f2���+�h������-�GXX��j�x���ASOOO=��C%�NA�5���[��g�)&&���������i�>�@#G���y/U�v��w�^M�2E
4(r�����u�����?�����h�W�|P���:t��t��l�C=����_��/�We]�x�~��W=��Cj���BBB���]��<��c����|�I���9688X��w�������K���^��k�j�������|||������o�Y/�������W^y��������v��i����:u�����b���][�����o�N`W<��������*U����s���[��q��._��g�5��>|�>��c������s���v�F�~J�3			�����������e_��S�NZ�b����w����.���c����>��'L���c��������m�������m�����2_�#)))Z�l����sg>I������4�O�������~v�]�������!���F�kJe�.��P~�����@�a���>��=�:��}Z999v���������tj���{����&����c�`�F3)�F�q?)�Q���
�������[{��QBB�|}}U�n]�o�^��Us�����_��}�����s���S��5��uk��U�-s���3g�������JMMU@@�����6m���Cnn�v����{�����JMM��t���T�f�T�N�K��j�j�����}����,___U�\Yu��Q�F�T�F�K��J�����k�j���:}�����U�R%EFF�����u�]w����K��k���v�^���O?�k���S�Ni��U:u���������*U�(::Z��5+6�X^>�u��)!!Ag������BBB��A5k������?~�&L�`k��w��!�\�R������Tpp�4h�6m�������g�j�j��M��s�N�>m�������Q#5n��i��r������W����JJJRFF�*U��j���A�j��a����R�N�<�u�����JNN��jU����-Z\V3��W���� �R���={���T����xG��'��������bS�.�|���:}�^w�u����;\���\�R��1�d6G8�ef���j��hL`�������R[#��\X#)����*e��r�$/���t�A����P����t�*U��=z����%$$Dw�yg�]���S�7.Q���a2��d�+��*V�Qi��O?5��
��9���J��YZ���U��@�k���*��d2)&&F111���K����.]����euO)K������wy/(�g���Pff�]_I���K������	Wxx�a�
6�<���+
�f��9[��?����<999v����U�Nfs�����,eg���o��4v����������I�
�������r����y����������W9�\	�]&�V�j�w���]�pe����;W����~���9
�-*�\x���Gii�U�Z�r����m�����~��.�U�.���r��[,�v}1NB{�V�v��p��.k��M3h1bD������������""����.]Z�k�������^�p�w�ah����Z��^���Z�b�������={:_�fMC���������+vI�����>}�9�">&�]<<����8��(�W?�,O�������*��;w���������5b��r\�R���t�����6m�rrr\:w��Z�jU�����[o�5�\ck:tH��y�s�?������U�r�"�y���
�7�|S���sv���9s������-�����w2���;
�y�L������q)��@�c�X���������y����[7�|�222lc�x�	�����*�����e����7��m���{LyyyE��o�>
8����o���x___��_�2�=��s��c��9f�������������	�\�$
6L�j�������g�y�i���
<XYYY����Q�FE�S�Nfs�����$��e����;OhTD'O�T�����{w�}��z���t��9����kk�����Bp%!�w���[��sgC��3��cG���vU����4e��h�B'N�0{�������t��~X�_��}��Y�o�^_~��a�3g����^�<`8���_�~�����Go����o������{�w�^C���K��}{�_���W�R%������SQ�.���C{�U�I���AG����l�*�T���Z�p����0��^�f���6m����������[��uS�J�T�N���)))IpX�m������_��x{{k���j�����9#)?����������^���<xP����s[�l���'������>���_����l}���~����YS��W�������h8���C��������<�1���,���,v�23O������Y�=I����N!An_#�����_u�������g�}V��W/�%�+���Lxx�V�X���k����c������[������W^yE�G�vi��
j�������>l�g�����������+???���������l���Sm}V�UG���#G��������?/6|XXE|L�;�L&��JO?hw�b������Vu/������BhT,�k�vXP�bx��`�f�����?��w��S�N��(��T�re=�����u���y�L&��j����n��1c��J�*N�EGGk��Z�d����]��z����t�R�o���8
4H��m�=��S�y����w0���[,�v��4�L�	t\mocJ��������e�Zm_\N��w����P��������j���:p�����e�X��U���nP�F��
�%00P����&L��5k�h��mJJJ����"""��ys5i��-��s�������;���GG���bQ``������];]z�����Ke6G8���MWNN���+���kIR�����tY�����������`Xi���V�v���]�R�G�����2�:Wp�|}W��$���]h/&(�������VM��[�P\|y6����,o���,�x����~N�����uT$���*b6G8�w�����~��oLIs��*
B{pq���L���c���p�&*�8Dh�"�B{R�23O��:�mN�PN���+���U����L&o��,�x�>g����<�I��um�=���L��
sx�Qh��J~�6��������T���*c6G8��XN���zx��J~�����u]�=��8����SN�}���A���Qi��=�����N�ef����8	��J�(-7�m����U�������X\��I������\���U�l�p�o�������� /����)�n]����\��
�Y�y�>�I1����0 �W!__��=�5KYYg��c����KMs���t���*��[]�nK�]����1K�Nge�siW4B{p������={��B{��C{�����u\���U�l�p����^���"}��'��?���*�,�������L��� ������=�J9�I��r��/&(�����tY�V���JFh�R^^��������o�������\������:tH&���[�KP;u�T������/_��L��N��^�����*����d�����v������CR��k����Z��	�E:y����[��*55U���
		Q�z���iSU�R����
��\���p�����xY�V���xy�A�Y;�,v��R��/<�T�
��X�V���Kk�����k�f�m��E����1>��f����9������_��>��5k��3�Lj���z�����_


r���^�����ss3���b���p|\j�[��*f�J9)+-��Vky��h���2�L��������*���q�N��{9.C��������C��$\�>��su��MU�TQ�F��?�P6l0��m��]j���\d`O�n��]�&M��'JmM�:Qi�b���N�Y,����l��	����3vc��f(+/O>d�\��'������R�	)'������RPM)��T����pyX�`�����2�s�����;��b,`����5j(44TyyyJLL���G�tm���������||�*++��������}1��+�eY��~���8��K:�BJ>�|LN�tf����Rpm�vG��u��i���T�Pn�����kn��Y�{�Vjj���a��z����gO�������h��������7��u-�$Q	�r���Y,�v}������p|\�{�hP�e�I[��6}Qt`���C��m�6�:�l����w��z��W����*))I�=��[�������
��g�yF�7o����o����� ���C~��N�8���k�uM���*g6G(5u�]f�iY�92��w���0��@�9g�?��R�Ku�*��xi�,)3���sr�t��3D�����P>�����{O5k�,���x�
�����~������o�|���_i,W9*��U�l�pr$W��	v�������Bh@1R��
3.=�wAf�����I�\n��y�2	�%$$��7��������[o���@q��W9��2��e�f��XN�l�a��	t�����s�9�����Yi��r2�{��)�s����O�{�]A��������={t��I��f��[W���W��U�6Orr��m����w�������Rpp�BCCu�M7)**�ms]���m��M���Wrr�rrr���p�j�J���^�������q�:���������_����[��7n�J�*]������r�J?~\			���Thh�5j�����d2]�c��X�Vm��E�v�����u��9���+<<\
6T�&M���Y��t*99Y�V�R||�������`]{��j���BCC�{��:uJk��QBB�������`��__��5Spppy/��%%%�������u��U�VM-[�T�f��=w��}Z�z�N�8!���5j�S�N�����5<xP��o��#Gt��9yyy)$$DQQQj���%�?�a�����e�u����fU�^]
6T��M���sI�����?���m��)99YAAA�Y��:v��*U���19rD�����S�t��YU�\Y���j���%�WJ��r����/���ik�5J������%�p�3�<d6�+#���1�%�����J{��95CB��>���Wa���i��R��s�+Tnn��N���S����v�===��o_M�4I�k���9�������j��%��y��V���u���SO=�a��������:�M�0A&Lpz��e���S'C��j�������N����v��]��M�4���#5h� yy����s�����S�j��"�yzz��n��w��'�xB!!!.]���z����t�RC@����P�1B�F�R`����u��I+V���_�bE���q��i���.��,9rD�������������T���={j��j����?##C5j�Prr�$�r�����/�5Z��-[��iS[�e��Z�fM�����i��9z��w�n�:���:g2��A�i��!n	�?�����w����,}��������u�V������j���bcc5p��+6DS�w�����k����(++�����}��������-[�L/���V�^mw�d2�w��z���T�V-��h�X���?k��yZ�t�N�t^����S]�v��1c�����5KC�qx�N�:N������C���vbb��z�-}��7:z��}��{��6l�z��Q�Prff�&M��i�����3v�===��_?M�8����YYY������'�h����L&�x��z���t�w����}O�(>��3��^^^���{�q5��x����l�p��(�W����N������u]*��]����;�����@�t���i�F�F�r���C}s��U��M�l��������y���4i�6m�Td`O�8���zJ-Z���}�J<��5j�:t��������$m��U������s�!��233��o_�s�=��+���>..N�����������{��G�����E�����J���������u����~w�����d�}�����|V�U&LPtt�>���bVg����_�:����4x�`[���s�;wn��3c�C{���E���k��5k��j���N{R�c��q�F��w�y��ks�U�V�~��z����e��"�sss�r�J
6L�}�]���-X�@��7���s���Ps��5�|C��	��kW��=)���p�B�j���=K���k�~��i���E������%K��sg=�����qiw����U�NM�4�����������U�^�t��a��8~��Z�n��c�:�I����9s��E�����1�Y�F�]w��~�i��=)���~�z���Gw�q������vi�S�z�.m���7��4i�D��U+��C�=���^NN�rr���`�3�L�	���I��x�Z���B���y��<J��+��.c������[�a�C��dRTT��U����D[������Gs��)�<���/00P5j�P���������O�2v������k���


-�����Y�J���+((H���:u�����t����K�.Z�n]�U��j�����EFF���W���JHH����K����������)I�\s���������������c'O�T�N��x�b�k��Ds^����5p�@}���v�|||T�fMU�ZUiii:~�����3#F�����kk��1��+NFF����+[;00P8���l�2�������W����������3:t�����\^Ki���o�04���p�L&%&&���#�����r�J�s�=����lV�:u���~����u���k��M�����o�i�TY�reEEE���C�������m�N�<��}�j��M���.rM���5j($$D�*URZZ��9�s���|��JOO���3/���(O?��������j���j���b�����%�//HNNV�n��k������������b���{
����D�q���}��������?��{��W�~��SG�+WVJJ����gE��������V�X!������yO�h
��V<=~�����-\��v��Z��j���.]��_�~j��yY/WB{���;=f���R�z���@����)��Z�%*;
��;RJ>T6s%������D]
F�ex�L&=���5j�j��e�?x��&N���?�X���z���J<���������o�];v4\����$��;W���������'5l�0-X���u��7I������s���x��"�T��_P``�����^�z�M�6���������������o�iSm��]/��B�����[glyyyi��Q1b�������:uJ���~���b+����i����g���5z�h���
7�]�j�����K�J����u�}�i��M�Z����S�L����w�n����4e��k�[�n�k.�G���5k�L/���n��V����O?������k��5j�������������k��������o��w�}vk����C����
�}}}��O���R�F����?�U�V��������]ZOiX�n�|�ACU��� �5J���j��m��Y���������+�d������T�F
�����������%�WU����4l�0[p1==]/����~�i��_��$�t�Mz��7��S'yzzJ���6s�L=��3�@��;4}�t����_���U�������={�E�v�3����[�j������Ol�?��s���[w�u��5o��V�~��[oi��%�c_}�������Y���w���O�����c���;�P�*U��=�����o���k�9r�8 ///=��#z���u��������i���3f����%I���k����'y��������o���^]�v5��RSS�������^��S�$Ik���3�<��>����K��R�����+���w�}W�?��]����:q����Y�7�xC����{��g���Bh /�yy)'�>��0����:	Y9:���H�O���E���2��Tf��)���:����I��3���z�j}��'���d��_~�����nl�:u4}�t�x��>|�����z�����[-�j��z��Gt����{�������c����$u��MR~X���u����j��!z���������^P���u��AI�U��������I|��'2d��y�����_?���Oo��v�U��z�--[���n���.\��9���P��m��o���������/)?����/�en��F�sV�R���qYZ�x��M�f�{��'5u�Tyxx8<�^�zz�����SO��?�p8��G������{Q���>��SC{��aN�8�P�F����_��I��+U������{��z��7���]ff�����t���_U�fM��T�RE}��Q�>}4i�$C�+��C���A-]�T5j�03�L���[��o���n��������7+//O���������������G����a�����
�}��Gj���-���d�
7��?�Pw�u�z��m[��o��0�a9�IR��m���E��m�F�e��������+���:<�f��:t���
6����9p��|}}5o�<�����x@@�F����p��q��Yz��W�V6�������	&���^rX�$00P��
S��=��sg���W�4}�t
>\111v���=�"��o���#Fh��.�����k��u���_]j�"��$��:���ef���s�����tB{��$3EZ9��WQv����*mGK~�
J�;��#��jk?���{
6Lk�������/��*U���o��u�]g��5K�&����Y8����(��1�\������~����={l�W�T��J���~WPzz�������/���4<x�����M�����k������3gj��	
vym��	&�,�ba]�vu���w����Rbb�$��/��o�!����{�n�����v�f���E�c�,Y�U�V�����E�
		)��_���C��j������V�t$22��VV>�����w���
�_�������K�rss�w�^��WO_|���P�$=���z��7�{�nI�G����|���o_����{w�5J�������o�B���������IR�v�4g��a��J������{
4H������������m��A�[�v8������m�l�#Fh�����%22R?����5kf��M�2�.)��=��*X�T���7n�hk7o�\Ptt������o�U\\�m������gOm�����?P��n�
�lv����rRV���x{���������}m��%''k������l�89����Nr���h�l������J}����kWC@��u������r�8_~����9ck�?���������ck�?^�/v����5k��V��k��Yn�c�����[``�>���\���W����vbb������T�+\!p���.��S�uO�4���^E���p�
�����;��^x���;/�!�W�+|n����t��~������������3��_�������{��]0�UX�����.��I�&������`������+�{�e�W�����??����Z�~�F��;��Sw�y�F��
6����6TG<x���~��2\9����$�9�a������$�������R�@yX�j�233m�^�z���^�z����N�:��K#��.�k��}_�:V�JII��?��������^^^0`@������!���_�e]�i��%������Z=p������3�����/���������A���]�|�������z�����c��s��]�jU���j����5n���6�L����K�s9r����@��X*����?�0�z��a�|V���[d5���5kfh=z�����$�]�������U�J����r�-����?��9/�{JEu��y��'N���?n��/0�Lz��g���/���������^���$_�PI��Y,�v}1��?�csj�r�Vw.
���aI���S��/���N�:���{O�
R�&M&???�L&��o���v^zz���Pi;t��&M������a���^��|}}��`E���D�������=h� M�2���OIX�V�\����_�����Jt���U�Z��.��R�;h�.]���K�.����_�`�l�����r����_���Z���Qx�������y�.]���[N��<�x��.�+��'���\
y>7%%���)�^���/�g���[��BBB���m���9��]����-�E�.�


5���;�p���-k��H�d�j��eh;��K��R���f���
��g�-��^xA�����srr4s�L��W7B{I���%_���9
�5r�K����4�[�(���
��U��S���+��C)22RO>��f���m��)!!A�k�%+� ����u��w�n��z�������k��]JLLTVV�%����j����}��y=��s
�-���7�|S��������<s����c������N�>m�F��]����oh_Lh�8�<���{���O?��������
�tlY��4\��.M��;~�ma������z��s]	7���_j���Z�j�7�xC�-���u��Y���{~i��e�:*�+J@@�����.�=zt���^�z��h_.�{JEV�R%���~�Pi�///=��C��+V�mm�=�����?3��]�����e_-X�����e\P8pQ�RSqJ:~��������������[Pff�E����k��i��Z�`��JRI������?��
����o�i��1j��������sgM�6M�N�*r�����ZgQ�U�����L&U�V��s����Po��YO�����nk7l�Pm��uz����������������Wi�'������?V���e�����4���~��s]V�ri�S*2G���;�|~�������5x����9B�����ge%)77S���+�m��P�J~��j�i�R�50�d��@)�
���.������.��*GI��-��
�
*�y�������+5�p���dee�g��:v���?::Z;vT�
�������d�������[Z�dI��v������gO�`�
7������^�z�Q�����d6�
�9r����u�j����6m�>��C?~�nLff��/_����������#��k�)00�nliT����s�5�Zjj��{�*)�����z�!��������x��������a�g�}fxN���'�.9�\���u_M�-[�G}�6���R�v���U+EEE)44Tf�Y����s�w�^&k�������}O�������������������WFF����.ym�=���J{R~�=�(C_L������*��
O��J��_�N�����)��[�
����K�^���4��N�>]{�������4k�,�v�m����g��h]����^3TG����W_}��-[{nIC����z����/h���Z�t��/_�5k�(#��^���,���{Z�d����O��S��n����y������@���g%������J%�7l�0�����@��3����\}��������\��*��\]�����9�������O��k�����J��iA�^G�Q)�4���~�i������Y�n�"�s�=�"k����m2�J\
�����g�V�{&��=���W�<=���k�?j,�x��^���8a_�ygZ��s��������7�-/���R����vbbb��/n+���~kh��?_7�|�K��9s�D��s���}o6������(�b���������}��7n�����~�z�����={����g�{�n�����_~1\�p��j��[�n���$$$���Z�JLL,�pJ���u���j��E��_�U�����.�/����T�j�b�^PBB��W]:��u_-������8[�q���7o�|||�=�,�bG����k����Px_���(�}�����Q�F���jUVV�]UIg,�]_IC��3�)6&�I����Y,�v}����r���T���T)\
�]6s����*U8��m����e������i��u�v�f�\�I����K���u���8q������\�edd����nY����n��fM�0A{���|`��h�"����pNxx�������������\����
������\#F��}�����3g��3f�0�>|x��+������������
��C�����n/�*���N�:�v��\Y��{JE��ys��S�N�|~� ����*W�|��$B{�B����K��t�$���U%'������v�2��C��s������+V��|W�'%%)''��n����s���G��wy|� �$�������K������TBr&�I�=��h�����
mooo�m���NOO��5k�������$�qYk����]���n��vEFF��3g�T^^�������?������N�:{�����7�������n]si(��/]�T�����v)����KK4����e��[Z:w�lh���+
��S*�:u��q����
6�|~�����7��KAh`�,���gQN�9C����f���������U�N
kZ�s�7���*��MC����Yg��q�����C��YYY.���?ty�$�����7�,�YRy����h7���n3��{��R[O���$�qY+����?�Qrrr�������C������%K4k�,Chu���.<�����kW[;''��_g�P�F
5i���NJJ��_]�+BA��eff�G��R���]������^�h����[���[dd�!��~-Z��W�?��S*���������\>w�����+!l�U��fs��cK�]_L����FB{
j�[�
*�k�I�{���� ����7�[,�7��s������Z��!|�z�jC���M�6�8�bh<x��s�����s���/����<��(��R�����C�*88������
�����|���R���7o�v����)))z���Km�a����������O������������u�zO=���=i�$m�����Y�
�{������O)����s/���]���\�~���yyyz������W�5��Q�F�O?����;�dt�q��R�
2D�������s�k��b���e���������w/W1B{��Tux�Qh�����K�����0�>R�����������O@�c�O=�����|PlU�O?��D*����Z�jek���k��)E��o�>���G���.�#IQQQ�T���������.�[�V-EFF�������9s�<g�������K��A�i��.�?{����}��7���\����y[;//O��w�.\X��m��A��{o�c���z�����Z�|y������X�L&�WI�l%1n�8�k|���z����*�9���<Wdd�n��v[{���:p�����wo����|��]��}���vff�n��6��{g����M�\��]x�]{���vRR��u��c���t�����{���Z�U�M�6������o��"�����5y���Up�����%1f������������L��_�~}��
dx����=z���._#;;[_|��&N��t����\PV{uY�S���nkgeei��EV>}�����>���n��J{p+B{;fs��~�������M�T�P@�p��p�U��
��^����^%n��f=������j�<�'�|RG�5�=t��}�Q��k����<�6������{N			����DM�2E-Z���#Gd2���A�����P��]m���d�n�Z'N�������
�
�s���z��7���b�?v������C�:{���f�����?��N�:�Q�F7n�V�Z��t���eddh���j���>l�o���n��&��=z�z��ik�����;�T��}�t�R�a����k����_��7��-Z����+�1�r�-��]w��^xAs����%K�q��Zy�����}�YC�;���o�Q���SZZ��9����;���-Z�[�n%�o��N�
6�D�������P����j���F���2TZZ�~��7
>\QQQvU���������c\���C�7�k��fx=_����h����[��V�ZU�K�j��WO7�|������:h���vP7o��{��W�<���V�6lX��:u�d�f��_�o���9s�-Zd�'V�\iw~�F����s�����_�/���a ���c���O��sg�t�M.��K����~��U�\���j�*5n�X�����={�w��)���O1b�"##��;w:[����f�X�����%���N��R�s����^����y�f�j�J.4�.dgg�����Z�j�;v���f��O���G
��W�CW�9B))���33O+//[���;��[����������4u������b�.�zR���tr��_'��T�7��2e�6l����8I�����{O���������U�*11Q���?��+��!C��G��~Y�VM�2ES�NUtt���������*77�v��1cJ\u��g����m������^x���e����<��s���c�����_|Qc��U�
���O���C�Jm�������k:t��u���S/���^~�eyzz��k�QHH�|||�����U������3�^���C�g���w�i�~g�Z5�|��?_������R�*Ud�X����c���sW<X����%���U�7n���_�����o���G���qqq����������(���(--M��Srr�E�u����v��v��Z�j��]Q�V-��7Ow�y�m]�E�'O����������())I�R^^�E��]n��F}���<x�-,z��9��������oEFF*,,L&�I�O����G]�~�K3y�du����������{�Q�J�-;vL�N�������Z��7wy���P=���=��^TXTT�����'���4u�T[����+OOOEEE�j�����T||�N�>����J�
4�|�}������gm��j�������(11��Gi�S����'��{w��.Y�DK�,qx���?/�"`hh����;���C�E����V�\��?x��]p���S�|���6m��ZWQi`���q�=)O���4��;�1�J{�	���=(�)���u��k<���AAAZ�d�Z�ha��Z�:p����[g�i���%������(::��������wk��5��o�!<������W_-�������y�C�'W���h���
3����h���Z�v�<hyxx������
j������������5k�{�n�pEdd�~���bC3�+W�o���g�}V^^��-�����g���Y���7����{5k�,r������


u��////}�������m��������{�f�m����{R�k������������c��Z�r������m��Y�����.�����s�~��w]s�5v��?��7j��
:r���2��M��1��w���������
��*U����~RLLL���6m��!,g�~�m}����7��877�v���e�e���s��Z�n���v�����m���Y��;w:|&���}� w�S*�N�:i���v��s��i�����y�]`/((H�������Rq� ����"����1����pL������t����j�I-�K���jw�B�I^~�1^~���;��k1<�<�Z�jZ�j�&N���������~��i�����t��U����[�'�xBf������[k����2e�L&S�����������;5v�Xu��E5j�����K������
t��������������k���z��gJ���k�j��I��������WO����v����o���9���4e����[��w)\W�vm
>\K�,q�b`��k�.������������������6���W^yE;w�Tll�������C�j���%�k��!�����z��_��F�i�������S�k���Sm���|��#G^����]�v��w��L��
9���G��u����w�}e�����>�?��S:tp:�l6�������/j�����.^�X����z�!5k�L!!!%U?��c����|�I�Pua������������]���Z�]�V.T�.]������xzz���o��/��}����W^q8�,�)Y��s�N=��sE�BBB���Ok��}�����n������)��������qc[{��m�����qE�����e�����;wVPPP9���u�����8b�_�R}���0��l��m���:�[7Tm?�RY#�c�����=�{0�/�a(?��������������{
}���vU�*�U����r$/��G�������������={��� ___��[W���W�j��2������_i��}:w�����T�fM�n�Z�j�r��p������:|��RSS�:u��M�6n�2�����;wj���:~��RSS%�]"##��Y3��S���X�Vm��]��oWbb����������+�N�:j���j��q��\Irss�v�Z���_�O�Vzz�*U����H]������.:4�t�Ru��������~��'w-]�t��)�Z�J�N�RRR����T�JEGG�Y�f��������n�:%$$�������UHH�4h�f���:�X�����	lm��:��+W*>>^���
V�
��M��v����M�6���]�������Q#5n��i��r������W����JJJRFF�*U��j���A�j��a����RQeggk����{�����W�����N-[��lC�p���7T�������=G�����$��?u�R�	�p��$y�J�}G�����:Y��RU�TI=z�(���KHH�����R�����7nl����T&�\I.T�*�JS�~���=l�0��V���������^
�]��eU��8&�I111���)��\u�����,�{JE�����m��m����\���2������*'���/��S��f��7���}me!11Q�����###��W�r\��8������j{1A��e����mMei��i�����G�!//�r\��8���//���Y,'���;	�m=���<�[�P�v�����~�������#�qE�JA�������������^f�U;�2tC�����b������$���h���z������a��O(44���� ��N���:~�]f�IY�y2��W��a��|=L�tPU/.%���l�<yR��wwz�v��;vl�\�<��Z�����ee%��=LjR�����)�n_@Y

���P�KWB{�|}Ce2y:<f����k���q������_�7�/��m���I�&��$p�*�._&��|}Ce����X�U��
��� ����nQjN���S���e�Z�{�����H���������6�Rm�1~�xY�V��B{�"���C{��g��k1�E�}����^\
�=P���YhO�23O�&�I�W�#����E��
��g��cK�]_L���^*�=P���d2�lwx�qh�q�/>3[��Yn]�����Xfs��~����V���Y��J{��)�j{�b#�(�����^^�E�����j>^�e�q8~#�=P���l�drx�b���k���^�=P�����G>>U�����8	�mJMW�����\N�\b6G8��XN���:�������L���rBh�g��������6�5�����u6���{i�
B{�8�Iy��L0��{z�Q����q)�n^�����%��!���qx�b����	�w86.�����\b2���������^3'���3d��s��.��.3���gf:���8��c����p��.��.3�W���9���TC_��<�f�R���6���=�����$�b9ih{�Lj���^\*�=P1�����O����Y,�v}1ANB{)i�\�e���D�U�s�sRi�`F��f��u]�B{���
w���yJVk���Y�=I�KIw��.��%���������$C_
_o��x9OhTD��%��[]&���cK��m2��V��K%���C��d2��bcc�{IJ���o�N��;~�x����������c���"��T<������)_�0Y,'��Y,��\���/&0@�&����KI��j�IP����h��]:|��������&I
Vxx��7o���(�������[�j��=:{�����U�J����U�V���p�<@q�J�l�p�+�Y�����d)���������t��5K�����Y�C�{N���5d�=��
		qy���<-_�\?���~��wm������5���?���X��;~�;������lv����g���a�k�$�'�W����V���2������LY���^�����e2�l_���/�%UH��N�:��r\�bcc
{�+!,\�N�8��\s��q��r��!�7N
6��y�\:g������k��kWM�6����$���C�?���5k�u���4p1��(1__�%�-��
�ckyy*��W{�3��������*��FW�������S�3������<�����Y�|BU�7B�
�S�W
������b�(>>^			�1			����>��3���y��{�*>>��������+  @�N���#G������~��Wu������=@�yyU��g�rs���Y,�����_m�Qho���������tn�Nfs:&3����#:n9�M��(���Tn�Z�u�p�P��?���J]�����G�o�^-[�TXX�������?�������!I�����#��uk]w�u.�e2���[7
0@�:uR�����9�w�}W��MSnn�$)##C�{����;U�F�K|���Gy/p�1�L2�W��������@�c���+;������Yr3�����k��"{���<�E	?���?���QJ+��������{�u�VM�4I�{�v���:u����_�?���*U������4n��b������������Z�d�z�!���$��UK�'O�������k�OII��1c.�QE#��(�B{�IY�� ^LP���yV�N��W����=1K��v^�u��������u�M+�;�^�z%:�Y�fz��7}?���,��s��i�={���w�U���]��k���4i��o��9:�|������8���e*;�����Jf��L�����}m.OIY	�������M�������o	�T��w�<<�uJKK��#G��o������J<���>���+�����Z�|y������2���I2I���X���bk�xx�q��6����R��@�R\(���%7C���A�y���\��<�~9������������(�����?�h��=:y���f���������j��n�'99Y��m����u��Yeee)88X�������.�M��!!!A��m�������������(<<\�Z�Rxx�%�q��Im��Q�RJJ����������P��[W�7V�J�.�����Z�r��?���yzz*44T�5R���er�A���j��-[�k�.�>}Z������������aC5i�D�����L�����j�*���+11Qyyy
���^��M�*44������S��f�%$$(11Q
V�����Y3��K]RR����?~\g��Q�j���eK5k���s������W���2�L�Q��:u�����KZ����}�v9rD�������BBB���[_��Sv���-[�(11Qg����lV�����aC5m�T>>>�t���l���?��m������5k�c���R��[��#G�~�z�:uJg��U�����m�^�}���)���� U�^]�N���%&&�~��n����[�[�����m}E���AhpQ<<���SMY>��b9����
}1��NC{*��g�p[����s�k��?�����r�+Unn��N���S����v�===��o_M�4I�k���9�������j��%��y��V����n��z���4l�0���t:�0a�&L����e���S�N�>������[�}��~��7�������4i��#Gj��A��*��������S�j��UE�����
7��;��SO<��BBB����+��k�i������t8&44T#F���Q���Z�:u��+��W�XQd�o��q?~�K�-G���������+!!���*U��g��1b���oo����P�5���,I�\������}��e�5m���n�����YS�9yyy�3g��}�]�[�N�����L&���h��A2d�[BF���7�.9��q&++K�~��>��cm���������Z�n���X
8P�������P�w�����k����(++�����}��������-[�L/���V�^mw�d2�w��z���T�V-��h�X���?k��yZ�t�N�<�t�����v��1c��3�5k����X�:u���C�y���D���[���ot��Q����{w
6L=z�(Q(933S�&M��i�t�����������&N�xQ����,}��G���O�c��cL&�n��F���K���;Jt����\�,�<�V���^z���R�W/��������?33��/&��?�v�Y�����*�����/mg���/m���/�9�$g��Q�6m4j�(��=)?�7w�\5m�T��-+������7o�I�&i��ME�$���z�����E������]�Q�F�C�z����
�I���[���;+(33S}���=��Sl�B�����4n�8m�����iii���{��];-Z��i`O��$��+��~��Z�n�K�w���X�L&�Wlll��g�Z5a�EGG���?.�gu��Y}�����������O�����;��s��x=3f�0��^��]�v�Y�f8p�V�^�4�'�?��7j���z��wJ�6wZ�j������\[�l)��>77W+W���a���w���*K����ys��;�a`O�5w��Q���7�O�0A]�vu����.T�V�\��$�]�v����f��]d`O���,Y�D�;w�O<�����p��?�Xu����I���I�����_���K�vy�����u��;v������\��3G-Z�P\\\���5kt�u�����v�������W�>}t�w(--��k��=�������{�!<W�R%�W��������;�����l�PJ���������������yP��k�I����6U*FIf�6�[[&�l>�VQ����\����T�r�-��a���d2)**J��USbb��
RJJ�����9s��h���p$)00P5j�P���������O�2v������k���


-�����Y�J���+((H���:u�����X����K�.Z�n]�U��j�����EFF���W���JHH����K����������)I�\s���������������c'O�T�N��x�b�k��Ds^����5p�@}���v�|||T�fMU�ZUiii:~�����3#F�����kk��1��+NFF����+[;00Pp:~��e�����uU�^]�����3gt��!�����������*66�ah4""B���2�LJLL��#G�a�ec������{la=���:u�(  @�6��ggg������M��7�|�P��r����������������W���������6m�$o���'�G�\�5�J�*)--MG���$��(==]3g������<���������U���U�&����'O�x�� 99Y��u��]�l}��������b���{
����D�q���}��������?��{��W�~��SG�+WVJJ����gE��������V�X!������yO���������T�uEZZ�]������z�\4g��$�23O���[O?U���9U��R�	�TR�i��<V&s�g����
��^&�]�F�ex�L&=���5j�j��e�?x��&N���?�X���z���J<���������o�];v4\����$��;W���������'5l�0-X���u��7I������s���x��"�TM�6u��~���W�^j�����8�����3�9����"�d�e�B(Q�DY�����"�O�jQ$���%���X��D��1�1fsf;�?����s��9�3���6��}]��z���������Z�R�*��;z������I�&��T��o���#�n�a�C`+  @�����C�0?))I�V��w�}WdG���<�������X��F��~���r����k����1c�b�
IRFF����~m��������S�!��;��7h�@S�NuYS��5��8�1�!���aC��������jl4�g�-^�X�}��������S�6m�j�*I��������:������
�������8�{���0�l6��'���?�z����9sFk����_�y���U�/l��A=����\DD���~���z�����N����������i��,�������T�jUM�8Q�{�VHH���]��/_������=z��y�������f�����_W��m���/�|w���g��g���v���3f����*��j���w�������6m�>��l���?4c�}���������u����������~��~��oh��e�}s��ULL��Z\��M��p?�Y��������+**������Z�t�>��s�}��=��������=���z��gt�5�����=�3fh��Q����$9rD&L����=����{m���/��:�x������/���/+))I��g�}V���������R�effj������b��z��W|��W_}e�z��o��'k��Ehp����gV^��;�df&B{&�I��C���t��	iE�ypq�ly:�������#mK��wc�M������3�����[�N~��}l2������_�~sk���3f�I�&2d�����:w������-�|��z��Gu�}��c�����E��c����$�v�m���]�f���}�8p�&N�Xd����X���������k����K:�um������vz\����~���\'&&F�z�R�^������.jo���~��g��y��Z�h��k�����o�Y��/��a���;�H:Dy��W�2M�4q�fTT����8-]�To���a��O?���zK~~��j���a��i��a������y��G��=������b~�f�2��r�<`��X�jU���������S����cG����%���j�:�I���?������j��DEE�G������L�b� W�8p@u����+T�jU�>���N�:i���j���=|�`�m��Uyyy���������=�l6���Spp����G�{�����U+{����
������w��n�����4i���^�*U�!��a*I���������m��n���W/��;Wf���1W_}�
�A�i��M�>W���'���o��V]�tq����{N�+W6<�����^{�eg��������?~�^~�e�L&�����<x��t��v�������$��1CC�Q�F����3���_�^����M�������k������ot��q����+��~�IG����0`��}��h	x�����L&Y,���q�a_ff���F�B{>��t6']��~X�����3[����Y���!
�,��/�6m�l6�}��O8
��7x�`���;��r���{4?**J������:{�`��9�2e�G����p�+qqq�9s�=�v��9}��.;�����yXXX��*��.������R��~�����������ok���Z�n�$i���?~���+�vm�����
�x��N�u�����{��G��
Srr�$��O?��������B��k�.�����q��
��iS�s�-[��k���f����^A���E~�}��O>1�z��/����N;V:���JF``����+��^~�^{��3fH�rss��_�V�Z���O

=��C�4i�v��%�|�����B�w�6m<�:v��������^�t������L�8���N�Z�n�/���e�� O���&Mr���o���>}���_/I:~��6m��-Z8����_k��m����C5f��"k����7�|��
��S�NuBJ�{��C����[�c�X4`����+�X�7����y�=-44T/���O����d��P��������h�?����3G��J�f;�pOjj�,X`[,���+'N,2��
�k��M7��	���~����C���Lau�������v�(�~��RRR��q���������Q���3g�h���^���9s��f��?�����5���
����p����^9��l������d���+�t�+�!p��n�JR���L��v`�r��wo5h���y��ww�6r�H��8=�&��������tC�@�/����������c???��=�k���bcc��O�5����3�7o��rn���������n�t�
7�G���������0�W����^}�������O�����Y`���?����o������.�=�%�X���+7��rr���]��$iK:���R�]�VV��>�����!��+���[j��a��Ao�^��������B���4}��w^Y��~��>}�xt|�a�U�Vy����l�2����^�8d��L&�x�����������~j����o��.����/�q@@�������#G�s�N��|��.��+E�����W�~}��d2�g��n[0�y��!���@�{�����O?�d�u��Y�k���z={�,��a~
64�>�t���'o�y��������N�:�??s���k��gJY����)S��N�:4h�����z���x=��#�m]�t��O>��u��.��R��>�5�0���,��NH#��"�@���m������/))I��OW��}u�
7(&&F���2�L�������CW!_;p���L����{�n���X���f��:�wtKNNvy��;�}�����S���z�u�l6�Y��>���k��9BCCU�|y�8���*<�v��v��j���}�b�
������������q����t���
?��5R���_�YZ�������l.�jJ�&M��5/���t>$�n����iii�������G�K�.�Y������p�+�},�>w�|��[P��M��[�R%�����N��^�Z6������Z�j�����/�)���-[]�����{�n��;W�;w������G}���[����^Y{��=�����>|�u��?���!�
x�=�%��V`��@df&:lk�t.�=�4���7�vy*J��N�HNN��?���X=����7o��m�����+33��sG��������T�fM����������*99YYYY�Tc���U�^=����3z����N�:i��IZ�z���C:�LII��w���4XX���'�����j�������f������?��l�5k���;�
<�������j��T�bE�����\�q��u'��j�*�x��j���^�u-Y�D�����S����S������Q� ^aBC��mvu��F���=�k���s8�/���RZ����v������~��-[��l������C]�:���:u�dY_}��Z�l�����Ahp�\u�s��q2SJH?��|�>�L��E�NME�t���{��Q#}�����������V�E����x�x��Z�p��K�'
�����S�:u�Y�|�F��6m��\�rj����~�m%%%���:���{TY�?�b2�T�B����GC�9s�8
<<xP�������u����ovy���OBE%����K��X��T����>����������������|q������gJY��cG-^�X~~�D�/^����_�9SRR��S'�T�XQ��/��W_}I�E	(�e��RE�������$�l�2���������i�9�j�\�������!%��O���d=Zl�U6��}��EO�����Y��3g��;5�`���dee�K�.:r��a{���u����N�:���Uhh����e2��s�x�
-[����.���'��K�`D�
��M��UKU�VUpp�,�����{��L��5�y�f����z���t������j�/���_~�E/�����	&(<���������~�����n�<$$������@=����8q�$)11Q�/V�=�>��#�5-���d�]�����T�o����$?���{�1C�,  @�[�V����J�*�b��l6����c��x9��}������e������>��S��9s�\��jzz����m����-22RK�.uE�@hp���*N��l��Z�e�����,?I���LH� �x���O���%�~�U���b��D���T0t������g��u{��3�{�n�8&&Fs���w�Q��}��Gu]�	&�#��][s���M7�T����CBB4z�h�9Rk����+��/�h���:w��anVV��O��e����_u�:Up�z��i��i�SPpp�%_������S���|����$�7x�`M�4���9s�!������?��>6��������W0d[Z����$�=��!���kW��1CW]uU�����i~�~�|�)��
���y�u�zioP�f�B���3������!���o�y|�s����;���
��BBB�x�b5j��+uE!��dfs�L����gf&B{����.��g3�&�e�w�h��
�x�
��-���z��Z�M�r����d���n+�_|a/X�@-[�t�������_~���s�������D~[������i�6m�h������������?j��y��g�}��]�4`�����s��l6�v�mU��$::����lJNN�I8�z�������d�I��?��#G��CP��}��*_�|���w��q/W�e��+�������`��__�~������<�8���~��W�^l�{C��r�*U�����gJYs�5���������,�s�=���_���f��������o�J��;����+���/�9��>�5�a[���>�9��wuP���������xK�U��X,k�F�h��m�������yyyy��5
6t;�'I��o����u��!������w��v`���s���W�T��-5~�x���[�����;��%K�s�N�1�+W6t�;x������ROYV�vm�x���>[k�����sss5{�l�x�����C�)�|�Y�7�������3�
�V`O*�{�ty���Q�0��+N�L)�������x������}������/�\"��
������������N�n?sN���J���a�M��N�bY��j���a�r�J��ww���'���c��S��5v����G��=?A:�]�]III��'u�Z��'!9����\<��a����
���@C7����_����&����'����i��0�e7�;��S��������������D-^����V�Zj��m��k���BB�iz����q���P���X�BV����AA�r�[�b�Gk]���8w}�]�v������}��54�cb�7�)�f�����7�|c������?�Xw�u�7K�Bh�K����S��{���U��l�M���s�@�r�j�����B��Z�{]�.W�Z�2tXZ�x�RRR�:����n�(
5���������s{�$���$>##��c��NO��IRrr���;���0�>}�����=�����5������T������A�����e�4g�Chu��A���+�������}������3o�Z��n�����������J�"�w��9��j���K�w��A���%K��_y�~I���U������{����$w�)e�w�}g7h�����|�I}����m����������O�x������m������?��J�?�\���;(�?�'�������x�+W�����n�833Sc��u��_|���G���
��u��BL�l�����Rtt�a��~���\��a�n��~�A.t{��Q0P�0g��A*W��}���_:�yS��|�����
�7V�������4=��>[o��������?��C��5�>���>��a��)S���?���:}�`�#F�Pbb���(N{�{������R��111����}����GyDyyy�P��n?��3:}�t	U�w�)e���;����������F���7��o���C�z�>���^.�C�`h/�������%�\�,����Kf?�W�k���KL/Y���&�J3l�0C��w�}���X�f�2���������������:uj�����G=z�Pvv���HR\\����ym�O?��S�N�ul�j�ko��A_~�e�����{���o��Z�r���O�:�p��4i�0/22R/���}�������_�-���M�6����+t���_o�<99Y����GkH��d2�����<1v�X����y���3�8ts���~r{���X�y������o�>��[�n���q�|:tP�6m�c���;�����^JJ��l���z������k���O�<��n�MG�q���G�j��]�*����U+�x����gO��|��z��7=^+�}B:$���Q�d6���U�V�O�>�Z�n�q�������pv�����;����v�������O4y�d�k���rAq����������}��`��m����
o"���{z����5i�$���c������h}�����U����c�F�8�Kh�|���n��x��^���U���A�r��A��-��#���6�M>���~�i>|�0���z���4d�IR����^������Q���������������:u��6m�C��d2�N�:n������������-Zh���Z�p�����>
�
�������JKK3l?r��^z�%�r�-:u��,���c���j��������c�j�����p|-��s�4�|5o�\�o�����Y3��1b��t�b�������R��=�b�
�a���L���k���j����6m��������S�N���w���#Gj���Z�l�������n�M������M��&M���o����g���g��M���M����n�h���4
<��sI���s
����o�t�M>|����O��g������5d����������k^��� }�������;T�~}M�0���|Ajj�.\�x@5k����k���+F�Z���eK�8==]��r������u������������f��n�����m[���|��z�����gk��%����5k��W��CXp���������'�8
d9rD�f�R�v���Y3�C������o��F����mk��U���5v�X�����qIII����5t�P���j����s����|����\�����Y���u��O?�T{��u�����o����{L�76��b2�4}�t�~c�O>�D#G�4lk���Z�n��7BQ;v���E$=�X,Ut��_���c��l�w�i*�������J��Q�@Q���|PE��:@kR~����_���Z�uust:�91u�Tm��I			����O��w�yG5j�P������������	�{��g�f���z����]�l6��N����zK�k�V�r�t��I���_�����F��q��g�}V�-������/�����V��m����^�����~���4z�h�3Fu��Qhh�N�8�������>�Lp���;w��W^�+��"]u�U���VPP�RSS�o�>�N�!!!�={��s���i��y�������l6�,X��l6+..NQQQ���Tjj��9b�������&L����dI�W��@�;V�������6i�$>|�FLHH�=����� ���)::Zg����#G���z�k�~���^����B�j�����V�����[�u�]��233���o��7�T�J�T�J����:p�����.�~oi���>��S����=}��^z�%���K���ULL�L&�N�8���������7�T��m�����D�{��
S�������#G�())�~Lhh�>��35n���u*U��|�p��p/*(..�����'���}���[o�����W�������T�|yY�V%&&��	����:u�h�����{�!�S�N���*TP������4%''_����gJq����������^���5*W��r���f�����:p���.�&�I3g�T�n�
]���v��z�ju����zz�!��3���WHD��b��t{^�U��)

*o���E�=I��~N�F�{�>���?X*��Z�u��t��G�>���*5�l�j!5}Xa��e���s����q�}��f��}�:�EDDh���u����u�m�����y����<�����_z���4p�@���[o�U��M�s�=����������E���sgC`%''G��ow�����7�|S��g�}��Z��������N;�]��������������/��������V���N�]}��������7�|���{;tK,���_��k�����
?YYY���K��������_4l��G���wQ����[�f�����������K����{�U��Uu������=zTG�-���l�Z����35x�`����3g������������Q�F����o����Z�|�E����[�j�����
�rss�>�J�v��i��
�����a�����d{���T�}9?o>SJRzz������W�vm}��j��]1T������fs�$��}�����U�@Up�M/!��5=��O\�5�^�~��:@�"[(�'���0��gQ�%N�"[�w��^�~{n�P����]���'�J�*N�����W�^��u��;���U��
6��'���bq9�E�Z�t��N�*���k����SOi���3f���o��U�*$$���5j�H�6mR�~�����t��dR���n�:=�����)S��C�


-r~�Z�����j��]j���[kh�����k���J�*yL���5d�-[�������r����O���;����j�����������d������;wj��*W�\��cbb4h� ���{�V������~�a���_�z������>R�F�
�Y���W�V�����������u/U�����_i����S�N�s���t�m��?�������b�����C��_�-���r��b��?����_�=_:�)m����������a�����V``�G�y����w�^=������)tn�r�t������~�(\�k�\s�����h�"�o�^AAA�����W��-��+�h��=z��W��+�g��EFFj���z��t�M7ym��o��C��;W���=\L6z�W�����~�����m�t����`E�HKK3��m���"""J�"x�����Z��%"��*U�������i��4����G���O5�$p���=J�`(9���dq���=�2x�uZ999��j�����o�]��l6e���k���)@����z����<�^�Z�w�����e6�U�fM�i�F*T��g����U��g��>}Z���������EU�V�+kxCJJ�~��W<xP���


U�5��U+��pE������;��_������B������U��
U�F�K^�f�i�����}�������*�����H��QC���S��U/y��$77W�����w�N�8������)66V�_���������X�B:t���v������[�K�����v�Z%%%����
PTT�j����
J,)��
t��q�:uJf�Y����S��6l�V��b�7N������F�w���Y�F����Z�*W������V�Z)$$���s`���e����S'N����+W��z���~��.��IFF���[�������:w�����T�B��SGu��������)�f�Z�c����W�����#22R����u�]�n���p����7���/5@��X�8
���'I�#B����3d���m��d2)�$�n{����n���B;0]���0u���g�����h�u�]>;�������o����d*�u��]�|�ij��Y�������FLL�O6}%..Nqqq%]��^�z��HW���F��Q�F%]�%			Q����z��z����l�,����Jg�b@�e6Wq�=++YyyY�m�"��[����f{�6O$''��o���ccc��k�����^e�8�I6ef&�����vBZ�����o�-��j:T%X(��*0�����N�Y���qT`�j;��9���kp���;����>		���CK�"PV�x��d��RE�ef&:lk�}������Kff�V�^-IJKK������;����s�9O>��*U�TR%�2����\����f��d2��5���I��nM?��<��L�����c��������W��1c��"P���t����\��������I7lk�t���<������<Q�R%-Z�H���%]
(#���b��r_ff�a\/,X�&���6�ex�.w����~��9r��m��n���KeH@I����[���S�23^�>����^�E[��9�MH�P���}Z+@���e��J�p����',�*N�[���G8o��~��5��0n�8�l6��	�=�O�����k��("���?�f�ln��}��=�O�
��l��ZO�5
w���I���y�6_!�����
2�����L4��	1+"��#isZ��k�B{�0��d6�8�W0��g2���n{	���@�Ah�3K����D�m�"B��M��(C�|�Uh/;��rs�a�F.:������l�����>�*�'I����F�C{��@�Ah�3a
w�/33�0�1*��t.�=PV����n{C{���E��-���@�@h�Sf����1�ly�m������2d���^������R��v�-KYY)�m�\t�K����sY^�
���|�l�$W����a|cx�L.��9��w�B{�����\�����D�8,�_uB-N�&�gx�6o#��9�����C{��("����4B{��#��9�����YY����2lk�<����9e��y�6o"��9��yhO�23���:�Y�l�q&��ux�=�������������B��gr:7!=���x�=���L&Y,���Y���q��I7�;����v���x�=@�p���L��f3lk�2�G�=P��W��������5�p���aUZN��k�B{�ba6Wv�/33�0v��I�J�=���d2�?P�%W�~�8������z�����kW]u�U
6�k��q>��7n����+W���_~���K�e%]����oV``���S�ef&*<�:���%H���J�v������6��>������?��[7<x��K��Nvv�v������+))I���
S�����A��__~~�R�k����b��2����dR��P����07�N{�
w��I�~��JLL,z2�-�����_����k���:w������������
���kc�(+�t���R��v���l���F!N��.o6�M�g�(��)��9#��V�%����/2�L��q���tI�����m��%]�0y�dC`�F�z��7����k���������`�@�0`���v����.	���jU�-T�fM�1B��//4�'I�O�����������7��oV8�����
�I��ZO��
������Y�j	�A�JB���J[�X���]�;v*��i�>��HY��U�

qgWY���+���?��������+>>^*T(��������������X,�R��*T���g�j��=��������������~�����U2�B{�bT^&S�l�l�}���n��$)!=��pH����5K�6nr9'��ie�]����t�����*��[o-�J�w����9s��=���:v��}��gO{�E5j��C=��;�Y�f
��;w��������K:x��}�{����u���'�,��Q
��t�+���'�%�����D�8:0@�����2�^���s���>���<�X��=g�m���C����+��)U�����
������*����7���K�j���;v�Z�je�IRpp�������5k������_VJJJq��R���X��U�n��<���Q��n{����+s�.��q��/����}�����K��v=.#����qDDD����� }���Z�z�:u�$��T�1QQQ������P����T}��7�,e�=@��X���rrN+'��a[����-�����^����K�?�����r����u��{�(�����;��kAAA������U�ZU=��a���K�U����.pe�X*��g�S@�5�q��P��������L]����F��S:<x��N���y�N�����Uc���s_.�����o�i���:v��,�j���6m��|��^['55U��m��]�t��)eee�\�r�T���5k���8��u)�?�m��i���JMMUNN����U�re5o�\�+�~����;���7���JKKS^^�BBBT�R%��YS���WXX�E�?##Ck�����Gu��q����R�J�W��7nL������K������m��t�M�[��O��y����C����$�>}���p��7�b��^]K�������]���RSSU�B���G���n��I���o:z��RRRT�B�t�Mj��a�����G������-����U��m���������l)��p�����}�:���O+  @������S�-.����v��������d����b��b���[��n��F]�������o�i��mJMMUDD����j�z������;��������S�N)22�����B_?K�6m�������:T���4!�(Va
�PNN�����D�����>,X&)���-�2�eH�k��a������4a�b�|�'�/�rss��[o������������_={���)ST�z��Z#!!A_|���-[��[�&�Y���
���+8����
��?^���wy��?���m���l6�^�Z_}���/_�]�v��
7����{N}��U@�g/��?��z�-�]���y���j������.=������v��k����	�b�
Y�V�s*U���C�j���
wy��m�j����W�\Yh�o���7n�[��B��=	���3G��?��c
0����F���C=�9s�H��-[�_|Q7ntzl��u5y�du������O>��>�����da�����
�^���i��9z����m�6�s���t�M7i���n-�]��s�j������w8�y�����������1c�h������r8G�F������e���~��g�=Z���s�g2���[7M�>]��Us��,���5�����������j��:v�����������F��p�/���y~�6�����
=wrr��x�
}���:|���y����������;{��Z��2e��~�m���8����W�^�4y���
�gee������~�;v8�c2���I��������G���s�4*�<��7�@��W��<K��33
�`?�s�KH��z]|#��_��x�O�H��{����O�(KRRR��U+
>�i`O:��?�n��F�������;��q���2e��l�Rdxj��}6l��6m�={�x���>|�n�����;E�$��?�����];w3hj�Z��gO�{��E���>!!Ac����������Y�{��j����,Y�2�'��$������k���
��� ��d�p�+�F���o��e`O�v��������W_-���w��Q5k�L�<�����t>��n�:u��]]�tQzz�E�g�Zu�=���t�s�����qc��?�i�L:"���[�`�������C�N�f��@��E���ys��eUi���[�V�^�4o��B{��{��e���];=������qk
o���T�F
M�2����t������W]�v����^����j������4�'��_~���6m��������������3�<�2�'��~n��Q=z�P���u���"����`i�=z�0�fc�mt�;�����q��<3��l�<�L�d�F���3�������f�:)�>Rxx��������6m�d�n2��
*(99��Q(--M=z���_~��:�������U�jUEFF*''G'N�p7���Cm�����[U�R%���������(U�\Y�Z�JJJRb����W�^����k��
Ev4h�C�E:��.66Vf�Y���:~��N�8�Q���W�.]���t�UW)&&F���:x��N�:e�w��1�m�VK�.U���=Z��9Ro��OG���pU�VM���:x����v��1������g��.������m��:t��a�����W����h�8q�!h�d��k�N��/w�*U���o���/\��� >|X�����f��{������bQ�5�p������_?m��E�k���I��###'???���Gg����;v��z���-[�(00�����+������j�����VXX���=�C�9t-{��w������g_���(�<���M������_��US�
����c��y|�� 55U��v����O����XU�RE�����������du��]��oWDDD������t�}���9������T�F
EFF*--M{��1�"���;�o�^+W���bqy~_>K�U�V��^{m	U���������;��l���:)���}[��}��I��;�����<��4(�2w�����a#_���Q��w�r��Xz�������d�O<�����Z�j�����������(==]�?���k��f���Cw�y�n��V��/8y������W_}������c<x�.\�����/�$m��U�?��}��>��������ot�=<<\�z�R��]��U+U���:��G�j����4i�RSS%I��o���#��5.��a����kh���:t�����'%%i��U����4�|����w:������Y�bE�1B���S���
s��]�1c�h�����������e�C���S��C~;v�oo����N�����5kZ����_����%I��7�����v��) ��K�m6�V�\��{��y�����{w���u�wB��-[f>\�:ur8���*''G���!����^O=���V�j��w�^M�4I����7m���{L_|���u����JJJ�$5m�T&LP���
�c��u���uy�~��)++KU�V�����wo���H:��/_���������=Z�<��^|�EIR�f������m������t�3����������P;v���3��SO��5���V�VM�{�V�.]��iS����f���3f��?Tnn�$���?V�n�t��w;����o������Z�l�}���s��W��i��9<j���1c��{��!���k���������bw<��s��o�������g��5�\c���Y��1C�F�Rvv�$���#�0a�&O�\���o���k���^x�u����KOO�_|��_~����g�}V��������9X��������6l���K	U���������$�I�s���y��k���6i��sj�|?��l99�>�Tb��� �����T��.�5/�#�%s.��u������&�I�~������0�F��1c��4i�!C��;���s����������/�G}T��w�:v�h�-Z�H;v�P�z������$�!�T�fM�>w
8P'N,�Qll�^x����G�����f����c�*::��q~���r������K�z�����o��9����7�xC?���}��ys-Z���5�����7�����k��az��w$�u���+��&M�8]3**��k|%���0`���5�Z��d2�m�����_��aC{@����Z�x�z��qI����9r���^�zn}��M�������AAAZ�p�������\s�f����n�IC��o���/��O�u�]n�}!���wo��7�ix�E�������S��V�XaJ��{�N��|�r5h��[�`��n����<���K���s��f6���c�)88��;��G]v���x
��}�j���w�`m
4�{������[��u��7i�$���*U������d�t��7�z�������m�4|�p��^�zi���2��N�����5h� 
4H�6mr�3��}�d6�����:
}�������S���
��9s����^s��0''G}��1�����_~Y&��a~xx��.]��]�v����$I3f���!C��Q#�c|�,�^{�5C��
*��;�,��P��;?����d�s�g�&J��>�bV�����:�1��v��P��cI�{pR��S��y%��5�����r�-�8L�6M6��>~��'���<x����
��q���{4?**J������:������)S�xtO�
����3g�CP����_|������������	���������0\�*U���~p����Oo���6n��u��I�f�������\�rn�GM�6��~Xh��b��z�����c���-Y���C{�*77�!�9q�D�������7k���mS�Nu;�'��~��'�m000P_}��C�,�k��V���������K�j��'�|�2�$I=��&M��]�vI:��311�iG���4^�6m�x�5t��Q���k��&�|�7W�oo�8q����$�n�Z_~������:�����I������o_M�>��=~��6m��2����_k��m����C5f��"k����7�|��
���S�NuBJ�{�v�����������K�.��{w
��b��t{ff�a�o2��p��$�ex�.(�RSS�`���b�h���n;q�D��4���k���n����7��y1:t�`�Vg��E~~~n�9�����*%%�>7n\������5j�(����3Z�t�W�re��9��l��9s��t����+�\���{�5�7o������t�R>|�>�����a��:v��	������s�N��=z�����/����{�A�E��������#G�1�L�&$$xVd)w�\��!t_>C��W_��~~~�={���������'�pk�}��gv�y�����������_w��n��8^�p�rss���9xAi|�?~\}��1\�f����'�,��P������;gde�T^����Q��?�7���k��j���W]�vu;�U�b�"��xK�5����`L�����Vg��Uiii�������?�`�<  @}�����:��V��J]W���H�~��n����V�j����a���r�J����nw����v�������u����C��S�{�vk^���
c����={�u�
7�`:t��������~H�}����O�@V���U�vm����gO�B����aC���=������������NEEEyTW�N����9s��5��s���Z�����
�=<<\���+�+�<��%�UhO�23���.B{3�t2+��u@Y�������m[���t~~III�>}�����n�A111
��dr�������edd:����4e����[u��U��e6����v�Z�q���.���cG��o���:u�RSS/�N���5k����^{�"""<:Ghh���/o{�
�7n�Q��J�*�??}��/J�����
����{t|��u���u�u�]���p��*�I�&n����.�x�P*xlZZ�{�������k�������j�����h:���f��������`������M��=7��Er}�Y�z�l6�E�qA����Y���`i����~���<������>S�Z�J�2�F�E�%�f�)7�������(�0�L��.��D��/Xyy���%33Q!!�������$mI�P����������0.�1�(�$�#99Y#F����~j�H����T_���:x���
�E��*,x��woM�0A;v��t����?���G��[oU�����uk5m�T����������b�����_3��|�\��LQBCC��g0����
4���o��0v��Z��h�b��n�	1������[�g�TZ���U����O���w{��|
��w�a|1�7Oxr���\_���#Fh������g�/������?�����>6�L�9s��u�V�U��"����3�t,�;��mUz�v����.�
�^7�rL7���)�J=g2�d�TQF�>�}����qs�*�XV����4B{ 9�
v=*��������m����#W��j�����N�:]R����,����w��K�.��k������k����$����-[�G��������'O���Z])
�����49u���s???EGG{t|�
\��0�v�t�b���|�.&�[���k�������k���G�p���]O��Z������h��Q�����N����PE(��@)�����@��7����sZ�N��S�~�����\d3��
U�
����K�*�g�&�f���QD��$;���9��Ok����1���+���>\��m����Uu��b[/���%���3g����`���dee�K�.����k��[oU�:u���P^��oh��e�v�N�<�.]�8�4h�6m��V�Z�Z�����e�Xu>��snw�Y��6o����~[�����=�0�j���_~�/���^xAC���	�0�������~N�����$��Czz�[�z�.?���C`/  @�[�V����J�*�b��l6����c��X�g<,,�X����|�x�9X�L�4I�&M2l3f��}���e�=(E��Oi���JJ���cSOoP���]u����(T�]K��ss�)'�����5v�������S@����-��C�5+��^H�f%�����������?{��7Q�1c�v��m���h��9���;�<���>���K1a�C����kk��������<��`SHH�F���#Gj��5Z�b�~���_�^���3���������l�2�����
�]�^=M�6��z

���Q���������$��CY���z������]�j������
=���Y�+�3~������]�g�3�<��]�^�9k��Y�z�z�&����F�e�6l�0�?��*BYAhJ��3j���e�J���$%-R���j��c����Ru�a��~W���DCh�Q��������C�Y�6;��dEt���~X��u)��J�r�������?�V�/���0^�`�Z�l���)))�u)���K���E?��c����.�N???�i�Fm�����c�����7����y��g���]�vi������(��l����.�����������.QQQ��^^^�N�:��(�D��xr,�������/�_�~}}���


*���|~DGG���W����m}o(�,�R�J�<K��,->��S=��S�m?���z���e�_I8�����K�]`�J�������]^9�����T�����D��Ax�\�3;!���G4P�Y�\���M�e���Me���bY�4*F��m�G�����n������
���
�������{T��:t�����o���;�p;�w��9����+u�e��?~�v���w�}W~~���{��%��s�����+:�<xP���^����X,�q��M�9q����)3�����[�zt|����k��u���A��
�I�����wf�o���������Q�0��+N�,
���=��������{�f��yIr\9�@	��>��[VN�i��7'���l���S^=��Y,U�n��<fG��V��nz�������A�����Y��j���a�r�J��ww���'���c��S��5v����G��=?���%^8_��$��{R��U�|�3�Lz�������^��0��7�lgddh���^�']xr�KBDD�a\��\��a�+M�-�+Vxt|�����R�����^�3�M�6�qi�W�v����^?_p�9X��,Y�x@����m]�v���s~�W�I��k�x�u�+����]�_�����lv��Z�+//���QD����	��Zx�������kD�y��n���k�v�Z�2t+Z�x�RRR�:����n
����������s{�$������^�8��T�@�$%'';����;�����������k\
vxKHHp�����RX))��?��;��-��S��`���[n��k���r��f�����g{���<C:t�����x��%����<Z������~������{�d�����<K���+u�=�~6��k����Z���%X�B{P���VR�w>]#)i�������b��bO�����-�#B����L���J�;�W���^T@�J>9w@�J�yq�O�]��+WNw�}�}�����c��u��/��vp�|��� ��u��
�l����0\tt�a��~���\���4w�����Z�p���\������(�9�
R�r������Z�/�I=����|���4n��0�����:��W^��s�|QR���S'U�V�>����y���}���
a�6m������z��2\�����_����ti��������>����#�<���<�j(i��7��y��>}�����;����q�Fu�����h���-Z$��R���,"�%����g�C�:#(��L&��8`�&��:�e�����+��@Y��g��_d�W����g�T@)y�wI6l�L&�}�������>+��Y�fi��Yn��������������:uj�����G=z�Pvv���H��������?���N�:�����USll�}�a�}�����~��yTc��}�r�J���:u��z7i��a^dd�^x��8//O���-Z�Q}�6m�}��W�������yrr�~�������d2�?��9�q�m�:}��WE�~f���v@�r����a����9R?��S����=�!l��s�y�>\9Z�je��1C{��)��>�@o����k���I����5j��f�}�j�*���GV����7n�X���}��������sg����n�#;;[�|��&O��r
_</(������u�w(==���a��Z�d��o�]�����9�K��7�Z���:sfW���)���e����c�q�P��~&�s��oW
�dX�\��O?�Z���J��������+���l�R�<��}l�������������
s8��{LC��$U�^��u���o�5J�?���?n������S��i��:t��L&������:~~~����}����-Zh���Z�p�����>
�
�������JKK3l?r��^z�%�r�-:u��,���c���j��������c�j�����d�;wN���W���u��A��o�Q��5sz�#F�K�.�qzz����.���S+V�p���T||�&N��&M��i��Ev�����a|��wk����?��-[f�����+�\�V�BCG���<�y���3g�C��?��C�������e��t�5�w����a��[�����;��_Tb�����}�4t�P
4H6�������S�=��f\~j����-[��������[4�|���[�n�}���G}T6�Mu���h��m�B��|��z�����gk��%�{��5k��W��CXp���������'�8
�9rD�f�R�v���Y3��������o��F���4a����_�������w;=.))I�������X
0@;w�t:���������N�:�����m���1b�6n����FQ�$=����+�����SX�����8Y,Ut��a��������~X�69	�mN�P�X��JK�kUc��4a�������q���yq4���:u�6m����I��{��O�;���5j�|��JNN�������������3�
3p�@������e�}��S�����R���U�\9�<yR���Wnn���Q�F��������7���g�h�"{ph���9r���?�����mk?�������#G�H����4z�h�3Fu��Qhh�N�8��I�����>�Lp���;w��W^�+��"]u�U���VPP�RSS�o�>�N�!!!�={��s���i��y�������l6�,X��l6+..NQQQ���Tjj��9b�������&L����dI����:*�;V�������6e����:s��$����8p��z�)]s�5�����#G!�[n�E�����T�D����7o���k�C�I:�Ak����4i�j�����h��DA�7����_�U�r���o�m���{bbb����^����v�������#G���d?&44T�}��7n��:�*U��>h��^������'���}���[o�����W�������T�|yY�V%&&���n�W\������{���O�:efU�PA�+WVhh�������|Q_�/���e��]���=�x�����o
\���%$-mk1��{���	�����99i��9c��8"����t:�eE@T�b�|CW�x_!M�ztlH������}�
{.DDDh��ejZ���l6���O6l0�"""�h�"�:j����]��a{^^�v������k��=������/���k=��z��M�f������h-Z�H111��999��}������~���������[��x��rssu��A%$$h�����k�CP!66V������DFFj���������c������wk�����u�<�4�w��W�Ftt����U�RL_�����_���k
��9��[�j�����^����h��������YSk��q��������{�a������;��_~Q�]xA�V�4s�L���3g�(!!A�6m2���������Q�F����o�c���T����o��������\�s���/�����k�
68�h����m��i�����s����d2�,����A��"�%�f�)=}{�������&����.�ef3�E�:���l���x��@JVx������X�P��Uh�����4����Th��*?t�j,Z����Q����P�eG�
�v�ZM�<YU�8cu���K[�n5t�sW�j��a�=����X,.��h�BK�.���Se2�<^G��z�)���Sc��Q���U�jU����u�F�i��M���������1�L������[�g�}������5e�u��A���_��_�Z�����j��]j���[kh�����k���V��z��2d��-[�V��[n�E����y�u��M5j�Pxx���J�K�o��v�����;�p�sP�re����Z�l�"�[�dW]u�6l��Y�f����w9�d2�y��Z�p�~�����c���=��C���_u�-���c�X���k�������w�]�t�~��G=���j������=�>�����w��~�i� xA���������~�I��W���}��k�Q||�-Z����+((������j���^y����G�����y���"���&8�����U�~}�x��m���]�������?�����SDDD	V�99�Z�k�b_��[�*  ���u��)'����r���B�6����Z�����4�F7G�B�R\)�a(��@��%�{0�,��Pr�Wo�N+''G���a[����n]l6���f���%S`��B�f����<�^�Z�w�����e6�U�fM�i�F*T��g����U��g��>}Z���������EU�V�+kxCJJ�~��W<xP���


U�5��U+�t�������;��_����JOO�t>4��
�F�����f�����}�v%''+55Uf�Y����Q�������U�^�:eERR�V�\����[g��Utt�4h�-Z�j������������4EEE�J�*^���?���������9�;p����Y���DY�V�+WNu��Q�V����6�M[�l�w���<�\�����������{OFF���[�������:w�����T�B��SGu��u+��_q=w����.��@���]�$���U"���b��3gC{Vk�a\=8H���������B{@g2��*����5???�r�-�v3�Taaa�������-�������|v~��_�����T,��111���{K��2�Z�j�*\�+O���KUG���L&5j�H�5*�R.IHH���o��s�s(Jg�b����y�N�{����$Y,U�n��L���g�L&5�p��[�3|R���@	��S@@d��)����S�B{6[���N��
�%��%����������u����2�L���'���������L4��;��m��1k��Kp�=(!7�z
�u=O�L�?���`h���N{���n{���R9�[��S��]�����C{�u�%����ig�^���@		��r���e�r�nRXX�bY�R�
�eg�(77�����n{	�t�%���������N�!����r��$�5�0n�<��%-Cy6�W�p�=(A*�SLL7���]*����!�a���D����N{��y��a�zm� �%���ce�����A1�s����L&��n{C{7������<��2�]pI��'��f�\��@	�R��+  ���
�T��+00����5��uh/�?NB��T74����tB{�d��R ,���4��k��A1j��s���������R�����Leg��5�q:7!����p�=(%����y�����~I������������:�'IVk�a�(�yho��Le��y�.w��R$00J��K76��r�n��X?�`��`��_���|T����)(���}��B{.:�e�l�q���k(J@IpT�B;U��Ng��RR�wJK�]i����s��1yy�^����������gf3��
�(��ON��mN�P��P����=(����(,��$�f�)7��22j���N���Z�*��*�
}�b����?�[�'���-?�@I�������6��������	P�_Ip��dR@@�""�WHH
�sRRVsU�a6Wq�'OV�q��F�����%���A����nOI�M6�����������r�/3��a�("���}��:�����
Ch���(������:{vw1W�}&�Ifse����D��UhO���m3B{PEE5���t_J��b��7,�*N�gfC{��@U
r~-�	���Eh����pED4t��r����+'��}l2�\v�K��(f����*����S�����s5�g�Tv��`��F��C{6���u���Q�.B{yy�:}zS1W�}��!
�t��!��t^rv�gfy�6W�@~�"��KIY]�����\���������.�������
Ch�(?�EE�t�/�����X�����$�ly�qd`�j����MH#���=(���[;����]YY'���s���r���l��0<���-��@1"�eXy�=IJ9�[1V�fsE�L�N�ef&��"������SN����8Ch����j
�Ts�/%eu1W�}&����JN���;���]�^�
�B{P�E�w�m/%e�l���a�l��t{f�1����`�LN�&�ex�.g�@�<�g�SF��b���,���������A���������MH;���
"�e\TTK������.�b|�UhOr���("��<:�@�8 ��d�0`@I�\`��;p����fff����W��]u�UW)88�p�q����nxn��q���\~����.	���t�K���������d�j]}���/�������\�nyV��0BIDATk�BC����"B������l����*4�����?��C��u���K�P���2P>����������U��x��d��R�����D����N{y�~?s������'O���o'��,##C�j�2tJ�C1�!���h�����>������X�8����(��f�6+�E7�������l6)+K:w����FW�_~�����q���tI�����m��%]�0y�d%&����F�z��7����k���������`�@�0`���v����.	���^zI{��-�2P�t�Kq������{�a_J�jEE5/����lv����*;;UAAQ�$?�I
�C��T��\B{@)v����/��q)9Y�Z��g6K*H+I�kK��K�N(%�����?/_�����U�B��.����6mZI��2�N{p��TTT��RN�)�j��b��dr�/33�0n�t�����.��:xPZ�_����-	������t~|������:?�����|b��9��l�����:���:v��}��gO{�cYYYz��G���'I


-��P����Dttk����~Wvvj��e~~A

r��I�����Qk��[��^����)��\���Xb���;�(-�A����W���w��_}	UW��'j��m����X
:��+BiGh.�]��$�RN�-�Z|�b��t�C��p��=I������\��'�w�����������9y�;u@���jGDD�L!p���}�^�u���w�Qxxx	V����\&����b�u�/%eU1W�}Ke���������^%s�b��N�&��J����w����9_����#��
�Y����d*�J������GyDYYY�����[w�uW��2!��x��dRt���;�+�}))�e����?�\u��l�Z�|�}K��=q�a&�=�efJ?,��V���j=���J�w�}�����o�����w���c�X,�Y����i����{m���Tm��M�v���S�����r���R�Jj����������8~���m���{�*55U999���V�����ysU���M�=q��1m��YPZZ�����J�*�f���_�����.��Z�f��=�������_�*UR�z���q�2�z��d��]Z�~����o�����nR��u}���f���:���x%%%��������o�Y+V��Z��w�^������������
*�O�>���t���'O���~���G����
*���nR��
�<v��=Z�n����o�L&U�ZUm��Ul������x
����������C:}�����8�h�������k�.����JNNVJJ�,�*V���u���oTPP�%�?;;[�����m����TEDD�����������(�|
��������S�N)22�����B_?���o�����K:����w�)��PV���Ht�6NC{��Gu�����(���#00Z~~f��9����cB{���Yh/=Cy6����@�[��{�
�8+�Y-u��7�/�rss��[o������������_={���)ST�z��Z#!!A_|���-[��[�&�Y���
���+88����
��?^���wy��?���m���l6�^�Z_}���/_�]�v��
7����{N}��U@�g/��?��z�-�]���y���j������.=������v��k����	�b�
Y]`+U���C�j���
wy��m�j����W�\Yh�o���7n�[��B��=	���3G��?��c
0����F�^w��Ci��9��e����_����[�n]M�<Y��us����O>�������;Y��d���������Wyyy�3g��z�-m����???�t�M=z��_Ka�m����>}�����k���=0��{���j��1Z�p���U~�5������-[:�����5z�h�[��a��dR�n�4}�tU�V�����+�033S�/���~�+V���c.�����C�5j��=���������,(..N(�����z��7��������.�����c��<x�:w��Q��j�j��)z�����������_�z�����/*������_~��v���t��dR�&M���/�{���������o�>�����������U��`E(K�J���DG��������5�[���L&�����!33�0n�t���\�?��w�P���={|������IRJJ�Z�j����;
�I�C}�����7������5�y�5n�XS�L��-[�O���O��
S��M���?�>\��r��y��"{���h��j����?��V�U={�����[dPA:�4v�Xm�����g���������[k��%.{��N��������Zm������a��2�L�Wa��n������]�$i�������^}��b��}G�U�f���#���I��}���S�����K���_�zV�U��s�|�A��=w,\�P�7���������!�[o�U,0l?~�:t��4l&��-Z�H��7w�QV��k��uk���K���+4�'��g.[�L�����O>�������>�@5j���)S

�I��������kW��o��G��E�3f����t�Z|���j���<���_����N�<�����t���q�F���C��w���E���/��%�|<x�222$I-[��c�=Vlk����\F�^_��8�;��JW]���������s���`h�AX��$�99GBZ��	���@�m��E�mk�t]g.7�������6m�d�n2��
*(99��Q(--M=z���_~��:�������U�jUEFF*''G'N�p7���Cm�����[U�R%���������(U�\Y�Z�JJJRb���h�W�V����a��";4�!�"��z+�����t?~\'N��������K�.�OI�������\<xP�N���;v����m��K��u���	�F��7�x�>W�j���:|o������^={�,�R]�����m�C������z�������'�FK�,Q�v��|�rEEEy����������[PP�>����B�_�f����^{��b��F�


u����������l����kk��I�n���������������3g���;vL={���-[���X���k���\�jUEGG+,,Lg����C�t��i��w�}W�={��\����3�h��i����U�Z5U�PA���:v�����RSSu�m���?��o���U�*U���������NNNV����}�vEDDy����N��w���;g��5j(22Riii��g�!��w��}��Z�r�,�����s����5K+V��$j���uM��e�|tk���S��)//[~~e�K��ss�('']�����	�h�Y�?��2��r�l�\�N���%=����Rt��Y��>|�!�e2���Oh����V��}����5y�d}��JOO���?��Zf�Y=z���w��[o��p�N�<������W_�w�;v����:=����%I[�n���?o�������.�����nW�^���kW�j�JU�8������;w�&M����TI����5r�H�a�6l���s���>|���8'!���$�Z�J�}����������Ng}��1|?+V��#F�_�~�\��a���k5f�{� ##C����l������S�N���:v�h���AM�:�eM5k�,�����������K��7o�W_}U���S@�����l6�\�R�=��!t���O�{���y����$-[��>|�:u��pL��UNN����~C`/  @�?���z�)U�Z��}����4i�f��e��i�&=��c���/����TRR�$�i���0a���oo����Sll��s���OYYY�Z��&N����{+$$D����|�r
<��ueddh���z��g���/J��5k��_]m����������f���g�}����c�f�����z����,(���Z�j�����t���M�:��l6������1C~��rss%I���u����������~�����7���e������������
gO�6��P�fM�3F��ww�>|XK�.���n��������}��G}T�<��������g�j��5j����%IG���	4y��B��}�v��^�6m��/�C��0^zz�������������x=���z�������������������#F����__��,"������:p�����3JK��r���@U��*�'���n7�q��������R+/O:{��y��c{��wc��]���0���d�����[�?��>6�L���O��_?��5j���3��I
2��y�]�;wV������W�|y=���������cG{m��E��c�����p�m��&IA��5k���k����8qb���bcc��/�O�>j���=�5s�L�;V����0�`���?���]��^�z�W�^�������<�s�x�
�����q����h�"�����O7�|��/_�a����w��t>���+�8�N�4i�t���(���������4k�,{h�����m���_U��
���G�j�������%���{r����z����=�6m���_oi������;�^s�5�9s�n��&
2����/�T�>}t�]w�U���O���5o�<���-Zz��N�:Z�b�!X(����:u������A{pl����u������W/��7�����l�c�=���`���G}t���J�5|�����U+�����5h�@�������nu���^��I�����T�bf��I��7�����ZW~��m3�$�W�^�;w��f��c���j
4H�
��M���L�o�>��f}�����������P=��s�\����>g����k.;����O�>���������/;�����K�.j������/I��34d�5j���_>K���?n���][/��R��2��\f"#��?D�������5e:������r��Nu�w>�w�}�8"T�S�m?sN��<�K�����i�g%]E�����GIx��^x0���M�&��f?��N{�
<X�����Z����LTT�>��s]w�u����3GS�L��<�rNs%..N3g������;�/���e'���w�?+�`A������a�6U�T�?��2<x�����~�mm��Q����$��=[���W�r���
��6m�?����Q�����/����o[�d�%��.Unn�Cps���N{�
<X�7o��3���N��vhO:����O.��```����+��Y~�^{�h�377W���j���O>��e�I�z�!M�4I�v��t��gbb����eUi��m����k�������^{M���o����2q�D{W;Ij������K���:dO�?�&Mr���o���>}�=�{��qm���e�������m����C�j��1E��o��F
6�?��N����|�,)_}��������|���!�.p���3�\����KIYU��x��n{����F!N�e�l�q���u���Z�`�}l�X4~�x���8q����|U�]���u�M������~����C���Iau��^����v��(�~��RR�y��q�������_�F�����9��K�z�.W���#��f��3g�O�+	���J������^�x����*�mK�.��������8
6��c'L����^��z�j������G����`��-�w��j��A���w���m������1�L�&$$xVd)w�\��!t_>C��W_��~~~�={���������'�pk�}��gv�y�����������_w��n��8^�p�rss���9xAq>_N�<i�9p�@�k��g���Fh.C����nOK�]��i�\�w���C{Vk�l���bQ��c�fIJH;����$�]�VV��>�����!��+���[j��a��4c�W�n���:�w�JKK�w�}�����������G�w����X�����I������������hU�V�>��+)+W�4�����v����h��z����[����;�=��wo����_�06�L����[��p�
���C��+���\�a�����g�O?�d�u��Y�k���z={�t+,I
64�]�cN�<���x���;�TTT�Guu������3g�^s_=K�3�<����K�*U��7�|��+BYFh.C�B{6[�N��-�j��U�=�-GVk�}�gR�p����������$�a�$�m����=��_RR��O���}���nPLL����e2�>>��s�q�=�v��M�2E�{�V��uU�bE��f�u�]�������]��c���q��}5u�T���^t�6�Mk�������ZEDDxt���P�/_�>��35n����Q�*U�~��i_�������������:����s�����N����UP�&M�����]:�r7�T������$���~
���5z�hu��E5k�Ttt���f��p\a��KU0���`{��M�����"����^�Z6����w�aQ�����3��������/(����K��'3���fY����TZjf�����Y�iZf���*j�� �0�0�2����Gsf`������y��<����9��=w��x�p2 }/)��`E��{76n�(��/_n��I1/5����g�P*}���7���E�Z�}�Ke�TzC&S���=���C������p2���^T:��������������������������VL*I�*I�HJJ��o��
6�*Y"55�����k���oc�����s�(��\�%�5
.��K�<�D��[oa��9���z����]�"44*������h���K� ��,�����#�M�)������������}[�n���E�[�j%j�[E�he���U��Y�������'5�2|������#G�`��i8����V�Ia7o��K��f	K�1��/��s]4�������o�myp�H�K��>hkx��W��������#���I{DD��L&������j�M�����e2�Jh����i��pwo-���IW����CZ^>��y$""""""""""""""""���h�B��G%�t���7��gO���Z4�(�NW��%���@�~��T�,77��6{{{����4h�^�*��w�^����T*��S'6�=�|||L���������P��*���&�JII^��r��Gy{{��_q,�)����,���$�Vf��~����2eJ��uy�?�&�Y��k��8������}��f��%$#;99a��UU�V "������I{99w��s���* *�P��L$��+��J'����tW���:Q�������[�����%��__�w��W��K����eff��E���h������b��AF	{
6D�=��Q#����������*qK�.��={,������1h� �$��-[�[�nh�����GGG�T*Q�3f�0��Spp0��9��>�_}�������t:<x�;�����'c���pu5~��<�G��z�������K�
���!##��y����E����������kWt���]�6T*�J�hn��}mc��q������-�%���Rtt�(Io�������`�Q5�Vw6�M�	���s6���T*?�����@�p�S9����y�Fc�����GDDDDDDDDDDDDDDDD5�\����Q����6i��N�o*�T���m����,���^���]�>>>X�nP���������b����JC
6�����}��Z������9s�`��Y8z�(������������������+�g�>|���S���6m��?���x�rtt,�|��\\\��UK�
������l�j�1c�(ao���X�z5���[�����ZX�����L����]�{�o�����i������g���-����~g����3gZ�����c���B����\'��`�Q5���
W�f���h�-��'�)��I{��j{��A�L�7'�KN7w&��.Q4h����z
l�V%���!j'%%Y4�pr[I~��gQ{�������Ys5�Eq�������*�
��W�	��6N�\�n���[�n�7o���p��)���_��in��!��z�*��������Q41�`0����*U<�M�j��*M�Zu���)$���z���������E�'��%*���k��z�{A����m�6888�8����Z-j'&&V��kE�%~~~6��X�>HT�+:""*?ju����c0
l�����@�p�������m��?��Lz���������������������xy��?�������m����&�]�p������7k�^�Gdd��n����	{p�������;w����{B{��f'���� ::�*q����S�NX�`�]��/��r����w�����/������*���}yyyV���S�T�v��M�y������2D�s��Y4�����#2��'D��'������<��Z��S�l��������l�4�A���I{DD��Z�U�???����8���dP���������B\���������� """"""""""""""""���!�k�J�]�v���C�,�o����d����F�����k�g��������DmK�<r�H�$��d2L�:���D��������=�ty������8y����)�#������D�����N6�i:v�(j������E�����rm����,��n����U�\�^�DmK�_y0�>hK
4���{-�z��D�����h��;*��������������B.WB��m�h������AY�J���,�O{�j��`0�@hm��D�g�_e�'sQ
�Y��AC�~�����sg888 77�k�.h4����&&&���P4���z����������vvv��sm���t���7
���$�1��}����+����������3233Xv�+B�
oQQQ,q^RRR�HX�(=z���������1w�\����R����������w�n��f(��Y��a����U�{H�>}`gg'$������_7��W�����y��B���7ob���8p`Gf�}�V\\\��SOY<�h����_��C�+�Uc
��%�i4�i�`���^�C^^�����C��tb������""""""""""""""""�j�K7����q���t)�d������<����j��7o�Ys�}�]�'���D�>'N�U�3����'�M8���6{�����mn�?������MN���43q�Dxxx��[�b��]�O��S.kXK�6mD�_~���y���>rrr�#�*�_�~�_���������+����{�����u����[=F�J{m~���,��	�������c�
m�^��^z	z���*���3E�7�xiii�c����:&�Usj��?�������i�h�G�� �������m������e���������������������
4P*��_���~U*�����>}:d���V}���������f��Y���5
:t� �����l��b���q��
C^^�����������)))��x�~�����������ys�s"""0n�8�b|���q��!��������m��sww�;��#��z=�{�9������N�>�1c�;�Y�f����$<x��5 ,,2�L�
�x�x���`oo/�����~��Ycv�Zu�P(0}�tQ��Y���?�;o���F��3f��z|Tst��Y�^�z5n�P������'�|b�Z��m���gK��=�B��9rc���N�3k��S�*<A������k��a����w�����������E�:��Q��Glu!�6&�Us����|����q4�#��C��%��h�^�����s9((Rb���������������������0d��*�99?����u�W
t��	/����6x������������111�2e
^~�e@``����?^��={6�z�-$&&������l�2������;��dh�������r���Gh����c��X�x1v���}�����&��s����������.����������{��HII�J�2�|���={�D��M1o�<?~\T�����l��:t������V�Z�]�v��~���1h� ��������c�����d��V�EDD-Z��m�"44��jt�����y���5[�l��={D����[����y{{�*J��z<���X�n�Q���������I�`0��O�:�Je�����[�N����w�E|����[�na����8q"���3f�
f����i��:u�$�322��{wl����j��s�0f����+0h���Ek���S���~�z�1k������E���G��o���Q���-[��Y3�_�^2�<66k��A�^���];����B�����
www�����h��9����k��I�KHH�����'���aaa�|������Uev%!"���������d�M�	G-�>����:]�Q�Q���t�^v����h��X.��//`�h�h8p�z����!��++�IX�lN�>���(�V�X��+W"((^^^HJJBtt�0���_}��(A�8&L��U�p��Ya�e��a���h��!<<<������h�f�����8\�z���y��7�s�N!q���k�5k����g��B�����?����X@nn.�����s��Q�Fpvv��#JL���/���?"&&��8/_�������>
����Z
������[F�����v�Z�������i�.T�3��};�o��R���xzzB��"55����sn����c���HJz��ajj���J�������-���-Y���'233iii�0a^{�5<��P(���%�v������Tk"�B�M�6�W�^�s����-Z��?�AAAP���{��6m�`��U6����O>�={������=z4\\\��aC��r���"!!A������m��1{���k��^]g]?�
����6mn������}7o�DXX
����N���x<x����l�Q�F��};�}�Y!�0%%E�gy{{������HOOGRRR���<��DU+�Us2�jO�j{M���+;��O�?77	z��_���8�N&����Oq """"""""""""""""�r�R}����2��8��|&�Irss��={*�7�u�"##E	{nnn��s�E�����c�4l�P����q��U�<y7n�%������~h���������Z���j5v��	Q~~>.^����DGG	{r��~�)&M�d�Z�����������'q��U�D�����www�������`g'�����p��5�<y�������%����W�j����+j��m�V���l��NN�������s�p��Q�^����s��R�U7���8z�����^����7)��4p�@<x���6������;��o�5zOfff"**
�O�%�yzz��?�@HH��k}��g���o�����O���_]s


������+e��#�z�Bdd�dE���$\�p'O�����%�C&��x/)���A���I{DD5�Z-����}Z�=Gc=���t�����r45QM/*�I{DDDDDDDDDDDDDDDDD& :�a���6�]@��Q*���y8n�p�~@ED[�x{{����X�x1�L$F*
�9���U�3W����i��AULe�����c��e��L|{	^{�5\�|s��E���Q�N899������>}����B��#����o_�8qo���E�EDD`��%������K��A|���z�*:u�d�vvvX�l�^���_~������@������g�Y�w��+W�`���2d������
��r>r��DDD`��&|}}��g�a��=pww�q��W��u�5k��Y�f&��d2t��;v����	WWWFI���/�����{��&��T*�������Ku�V�������_����/Z�n
�Zmq���Sq��M����F��Eyxx�����?������R�]�x�	DDD`������7��P(��S'�����q�>���q��UE2C�:�DT#\�x��7�.\(�n[JOO���v�^����V�U:]"��J�B���G�Sg��#������������yyu����O��u-�����5wq��v��5N����a"���k0Q��5�����LDT�x&"�8���~N+??��_�5l����V�`0yy@A�P��@)��!�^���p\�v
���P*�F�n����m�5233q����qiiipttD�z���cG��_�*kX�F�����q��mddd���AAA����U�������~�:�������a����?Z�n����2�c0p��E\�xIIIHMM�R����;�����iS��S���T			8t�������,��j�l�;v4��I���s'O�DBB������	???��/�����c��B�������������N����5j���;U����=+T�{t?���E��M��y�*q������'p��]$''#''...���F�F���I���
��}���7T5�K����R*k���2��mK��W��=�L�������i���v���I��rV��pRT�O"""""""""""""""""�qd2���/d�\����[���\\\0p��r�����j>����P(��ysQ�ny��d6Y��������U�Y���~���*��j����JU��$2�!!!		��P����	�{���>mu$�
��@DTC��]%�SR��`��8�Q*�$���x�����I�F����].�Q���="��T�^^^
22.�8�Q����

����)�8)�j����t&��u0i������h��Ar�Fn�h�G��5�M��^�e2�6Qm/���������������������������J��GDTC(�����V���
G��{Jn�j�E�WI{��GDDDDDDDDDDDDDDDDDDDDDDDV��="�D��*���vU7qM����7J�3Qi��6I��V�������������������������j&�� ^&���\��F�8�1����%�`(�!n�&���e���������������������������a�Q
�����j�m�QGc=J��d��P�����U��Oi/96*��V$""""""""""""""""""""""���I{DD5�L&�Z�Er�Fs���X�R�
��Nr�V/j�qs����="""""""""""""""""""""""*;&��0j����YY���%�8���P*}$��t�E����I{g��a0���?�A�""���I{DD5��J{����0�R��$��V�1Qi/%����V�������������������������j&��0*���Hn�h��8�Q�|%���RQP�#�[�:Afbg���!2"""""""""""""""""""""""�I��GDT�����	����q4�a�� ���j����*�qQ�YV�������������������������j&��@^�n��yy����j�h����vv.��
'�@�����(V�#""""""""""""""""""""""�2b�Q
���2���6�������R���V{_�q�N��73yz���"""""""""""""""""""""""���I{DD5���3���Hn�h��8�Q����t�x���L%���\��)��������������������������f`�Q
�Vw��OM�@A����X���=�>yy����*�LrlTzv��FDDDDDDDDDDDDDDDDDDDDDDD5����j(/u7�~�>�i�l�u(��a��������2�p�����="""""""""""""""""""""""*&��P���`g�.�M�9b�h�C.��R�-��p���1i��������������������������I{DD5�L��Z�Er�Fs���X�J�'�on���l-2���L�#"�����I{�����M�q4��TJ'���&C�������e�������j0����m)U����J{�Zm��
P9@m�����="""""""""""""""""""""""*&��`��u��(�M�	�m0Vbo��\%�M��^�d2�v�����="""""""""""""""""""""""*-&��p^�n����pGSv2�*���6�6^�q3�����="""""""""""""""""""""""*&��pju����Dde]�q4��R�I�k��E��!n����uy����KlDDDDDDDDDDDDDDDDDDDDDDDT�1i��������L!�M�	�q4�a*i�� ��B;�U��D���Y�I{DD5���+��ZKn��T��=����6�6^x��`����8&�Qi0i����Vw��OI9	�^g�h�N�P��^-��p���IW�c������^�.��z��igl�u�T~��:�yI{g3�Q`0X=."""""""""""""""""""""""����GDDpum	;;W�mM�����I{�0��v7g�q�z���zU������������������J+&&2�L�
����j���0�{/&&���Z��V�����Q�n]8::��5��r��,7�|���j��?�������*:""�xr�<=;���=F�4�p���U��T���Ct�BR_sG(d@�DQ���,4rV�g�DDDDDDDDDDDDDDDDDDDD�����b��!�}�vE�BDTm���"22���HMM�^����;����v����W��u"&�@��U2i/#�"rs5ppPW@T����
��NTU��6^H�sT�����f���J��X?�r����������������������������?���+:"�ji��mX�r%<�A�B���W^y���ag�4-zL^�Q��Vw5�����c6��d29�J�O-�j���!nN���2���������d�����+:�j��9���gE�CfX�x�(a/((K�.����{�
_�����(�*VXX���S�!Q��������g����M����(L�<;v��7l%UL�$""��ST�z�j�mK������
��lT*_h��F�Z��SeZ�9a��d�q�2s�S����9�DDDDDDDDDDDDDDDDD�b0��-@A�
��*d2YE�EDT�����k///DDD����#""�������_?�9s�h[�Z�P�^=�d2�����}q!���O�W�^8r�m1UfL�#""���+���d�����`0T�|�T~����i�������
{mLT��73s��\n1���k�	H�I��;�e���Nv�U����d;x��T`�DD��n�:�[��������d�#F0a���
���c��7t�P��?!!!����/c����������X������g�M����I{DD$P�H������}��OT@T�g*ixxLvv����
�
9�
�F������GDDDDDDDDDDDDDDDDTNb�M���o#�F��1��|�^IA�����6���M��`�
�L��]��5kVA�U���X�z��o��)����$�7i�7nD�F�0w�\����8~�8:u�T��R�'���������S��&���X�����\%�i��?aF!����t�����r�������������������&�f�a�w�����&�I����]_����.B��WNU^�������[�BDT����(((��j��'�|R��w�}M�4�����V���V��b�^��s��!66���ptt����|�I�j�
J�����j�8v��\����888�n���������x���7���X�������7F����R���Nu<&��do�7��HO?k�M�	G�z/�>�2R�����a������!nN8��i4�LzV��FDDDDDDDDDDDDDDDDT%�f��g���[��\�L��k)�zkx��X):"��O����2���"!"�>�^�*j���NN��a
���x��gp��e����V���&�UX�b��Y���h����}{�9��O7{�<���n�:deI'��m�����
fq�����o���p����...��y���]�������lE��*����zz}�r{�UJ�23��k��a0�!�=�,��M����\h�����-��������������������b3���g��������r�}�<3�
�����q��1\�v
����J�Bpp0�u�///������.����HIIAnn.<<<P�vm�k�V[�,q����y�������Z����/:t�__�2�q��}�9s111HOO�^����j�����`4o�..���������G���D(
��]M�6E�6m��e#W�^���'q��=�{��}{��K�f0���;w� ""			HKK�]�tA�Z�����X����q��=������c������Y����q��1���A��������G���K�{��
�8q����L&C�:u��gO���������x���q��E��siii����Z�F@@:v�X�kfy�z�*��?���$h4�T*��UM�4A�V����P��������c�p�RSS����z���G������1��s�N�BBBRRR���.���z/,��`y�h4�v�z���[�~}Q�hET����P�����8q"J������p\�~�����b��QHJJ*v����1|�p�?�~���7�N��^z	?��c��233�r�Jl��[�nE���-Z���DdKjuW���4�/(�BZ�Yxz����JO����7r����R�0�6���� �M�Fo/��'""""""""""""""""*mf�Xq�j	{������g1��P�T�%/oX�|9�/_�{��mW(1b�,Y����R����{����s��M&
����1i�$8::�_SIg,��L�;p�z��)�3�/����{�U�)�E��1c��y��Y����-[�|�r?~��q
�-[�����1m�4��j����Q,\�����N��S�vmL�<3g������}����2�?t�P�I����������<����u��a��	B����GXX�����	�_|���������.N�:%9�I�&X�x1�bV\aaaX�~�����6zO�=�0a���)�{����n�:,_�.\�#����}{��3��c)��m��+V�@DD���:	c���W�\���s�c���Wk
		��_~�N�:m;p�����'Nm��d2dV�Xa�xSUU�s��j�k�.l��
�������M�U(���f��mt�/������?�E &&��}'%%a�������p��]�������o_L�4	�(�Z��a��%����������b���X�xq���sss�j�*|��7�t����L&I:t�E�/��`y*�8���c���cY��@^��i��/���C��}�I�����E�R�����1h� ��6��� 00
�B�m��
x���,��V��c��1F�m
�AAAh��������8p`���pLD����
���6�����);��L��t�x����>��\�J�.�������������������j����!+�8A���rqx��r�wU��h��sg��9S2ax���e��j�
�x��+W�M�6X�d	��=[����n������7nX�^i��9��w���+KL����aaa����ZC��a��=z�Y�� **
�����3gJ������G�k����{���=�a%�>�O>�$"##������ ���/S�pU��o������L����/c������l�������];���K&����L�8qC���A����Q��t:�}�Y����	{���c��i�-[�H&���{��������,X�>}�H&��v���:�u���*�9���+F��M�6��<�f����z���i���o�0��_��� ,Y����=��5���~����q��m�����C��1w�\��=�����y3BCCe�1�<y�7�o�a2ax��<u��
��C�"++��}��}�V����&-�����o��!Q���J��������?�/���������7o����8�<<x���8���x��g������1c���y��o�A�����3���FLL&O�,��m�6,_���cY�t)v��!�{��Wp����uQQQ�h4��m�(�>;;�G�FZZ�Y�T�c"�r�=<=;Jn�h��8��������1��q��L&C��t��3L�#""""""""""""""""*���p=2���ep=21�&�<����@�~�� ��dDhh���Wzz:�
���/[��V�5�suuE�F���}{�i����3s��%t������������M�4�{����	G������3q�D�$�a����t����5C�Z���'11=z���-[����[m��E������)�v��}�������I�f����K�
mWWW4k��������s�b��m��D�������Q��\.Gpp0BCC%�w����z�BJJ��k��������bV��G�b����{Q�R�I�&��=//��������1���/<������-[�u��pqq���>F����<�������P��\�N4o�;vD�-�
���_~��_~����7�x���
233E�����k�-Z�(�5����T<��S8{���������P4o�J�R4>))	C�Ezz�Y�������W/DGG����v����*������������������O?
g���o�=jV��7����
m�J����?�#U-L���n���i��	m{{{l��	��'`t�������[����s%��t�R������c6l���j��u�z�j,\�P4����7����d��}�V�Z�:u�}r��<��;&�#066�~�i��T�c"�(juW��������zI�*��?Sq���JW�����'�����*3e���M���f�����Om�L�i��!&&������Dtt4n��%B������S-^K�Tb�����an�����t\�r'O�����q��$%%=gy��}L�4��~�����{���O>�����6��V�ZI����&L���[q��=h4\�t	'N�@TT������X|�������]�x�f�*�DFFb���B����g�FLLp��?~.\@bb"����-[�`���ptt,v�z�c��}?k����K�">>w����S����$!�����l<��sHNN6���e���VX��-�=����/6������X�x1�C���g4
.\����H$$$���h���h����n��`��3g�m�9s�Y����|<��s�s�������f����wq��MDFF"&&7n����E�O�>�)S�X�_��������[8og����p��q�������q�����:u�`��uHNN��K������Z�3g�=�w�}��];������8w��������D��_�t	�W������z����3f���AZZ�����������8�<RRRp��9L�2
�B�����K&�@�����@�~�D�6n�h�����?J����?���.���u������u8�<q��|����k�9f���+W������M��7���H����HNN�'�|{{{aNll�Qn���/H���������	����/C����o�����06""o�������}��<<<0g�Q���>[l����/c��A���~�!j��]nqR�aW����_~Y�����?b��Qf�/�)E=x�+V��}����?���={6���o>|����O>�����%KDe��w��w�y��x�Y�O=����|�r��������Q�DT����I{�))�Q����SV*�������&C���\��Bi��4y���E��q�4/9.�7l�a����"9.^�.%��N�8�o��Fh�d2l�����3���W�m��x���c�Z����K|0������
����}�
	h;w���K���iS�9���,Z�'88X�L�9&L��E������q���x��w0v�XQ5�o������Z���W��7�|�	&�\���#G����#����B����t�R8p@hw��;w��<�r�]�t���{1}�t�\��������(��m���kzzzZ|�k�G?aaaX�f�(�x�^���'>���[�H����k�.6�L��������5m���������'O
m���?��O��o�E���EU�6o���c�b���f��������Q��i�&��4t����}����Q�F������2�������{��eK�t:����q��9��z�9�6m%;���L�GGG�{�����k��f��U���Z�
�;w6z/��e��������3�`��!B|�1�y��9~~~B����d��KQA��\�p�(Iv�����q�d1&�W�&N���'����%�w<r��-(�Jl��
�
2�����3f���WtO_�n>��C���#���;v�(ao��x���D��quu��I�0h� ���K���z�j����		1�S��A[�5k.^��M�6�����S'<���C@@d2�����~l��MTYr��Y�1cFE�O�+�U2;v��b=j�(������?���v��}��)v�L&��y�D}k��-���^����/��?�����>}��[�nB;##���K�s��1U$'� ���I���#6����J_�������V&�� *=��1���@����
��p(���{�p\�����:����E�B�����	{�M�4����9�5kfQ%OOO���O��?��n�:���T��mKL�+,  �~������*�I�v��������Jt^^^�U������l,Y�Dh�����?�,����r|��g�D��k�"55���HZhh(����b��j�����{O��{����DF���-�L�+l��Ix��WD}��-�h���`�_�^2a�������_�-����O���


p��u4h����7��/��"5j$���;����R�ZYU�s��[�b�KE���W�@�K�.�=�4-Z$J����+6o�l2a���m�������>��c������yt��Ah'&&����u�V\�pAhO�<s��-1���������m��_^��� ���q�F�\�R����;w���i�0d�<����<y26o�,�|t������G}T��S%�J{�L�O6`�Tf
;v��_z�%�����AAA��D��'N�@�N�$�;v<��������Yk���K8r�qb�o��Vl)��xLDI&�A���{����M8C���U&����U���F���x89=,��f�@C'%�g���Eedc��y�tADDDDDDDDDDDDDDDDT�d�������0l���8�'
>�������X!k@jj*�o�.�U*,X`��E�a��
���-��
6D���q��	�������???!����c�:u�������r�(��,6l��F#����o��_Q
��g���eff������1c���u���$	�"�����&.=2z�h�s�g��)����������B;  ��O7k����a�dg?,����/�I�&f��3gKm5jZ�lY���C�b�����Y�f���tQ��s�C����K����(�Z[uP]���q����
�c��IVk����xQ��\��k�Z�_���?^}�U���3FT5���3&+V~��g�k'''���Z�h�a��	�[���F���u|����L�W_}��
��)S��;�K�.�1cz��e���`��J$..����n��5�5kf�5233q��aQ_�~���+����&w���k����o_��|���+j<xYYY�c��1Uju�~�699�mM��d2�T���k��O�hm��+�Qew��q�t�?�|���f'y��U���>�$��������(�..�����������[e�?��Sxmgg��c�Z4�O�>�����'�r�������Yc�j5���/�'�U�C������7���Z�����E}E��6E�P`���f�5e��Qf�k����-��0b����h�B��s��y�U����{���PPP ���
��z#F�0+)x�kR��kLrr2"""���O?
OO���������<��u�(YYY�����'�|���=8z�(F��f��	J@0i�R����D�����x���<kPP|}}�����8�����&����sg���S������\��k��1U���H'�j4Gm��J�����`0�6n������F�� ��������������������2(�`>��������/,!!+V����?�-Z��������dF_?���0/;;[T������`��%5j�4i�Z�jA�TJ�y���
�III&�Y�����?�e��!55��q=��Y�'�|nnn����^^^B��������6m�XT=�v���������"��r@���-���OQ�������������j���Y�
���+77A�����t���"*�9�����9s0h� C�V�������T*E���6�U�D��Nl

5{l��`�.zN��5)��H�K��>XQ������P,_�\���Q�F����p��dff";;7o���u�D��+W��[�n����*(z�l��W�DFF���Z�^GEE���_G�V����	'''�o�����Og^��HKK�_�/��Z�:Qe������t�O���}�������l��?�� �U��^����Y��������E���JR�J�9����������x����i�&\�p����j�f�����}��Gpp0�y�l��W�\ARRrss���Q�D��fff������������?����f��a�F���.]�L,,�����>
��,W4I�$�����21����o��-[��h~�g������V�j�2k����Ps�I���3k������#h��:t���>��w�Ftt4RRR���_������yS�.M��%,������u�|���~�������E������}�"h�Z���W�\�&N�����c��)h�����������`�����������+�����s�=�\���J�h�^pp0233��K/�M�6X�b��?���T���������of����
b��9��sR�^�*j��W�����}����3''�����U4vS�����*���d�&�8����L�J�8��x�uSd��2����M^(Z��$���y�&BBB������������t�R�5GDDZ�j�;v�*Y���>{{{����h������{�b������<<<��W/|��gHHH(v����R�Y��P��*S�TB������r9�j�E����M��8�V��R�s_��Yi��Ue<�_�5z�������z���MN�4q�R�q�mu/)��`EX�x1.^�(�{������&��d2|���x���>�V�3f�k�T5�Ut���7Dm�\����#**���999�����m���,!���(j��[��}||`gg'd���z$''���_4.))It������&Ut�Ec7�_����P�����UF��H�8w�JeW
�^��5��S����kc��\����8�n��w&=/�)�P������������������J%33S�.Z��$E+�'77�
Bll���a�����5j�"�����/]�{���(��JNN��A���Z�l�n���A��S��R�Dq��1��d���`�9s�}����+������t8x� <�w�y�'O���%��-��Qz�����������k`|}���0k�����kQ�w��L�2E�|����v��:   �k��J��R������Mb,�3���b�u����k�m���+W��}���������p�B����������p��]�EQ����JB��]�_�u!aO&�������A�P�n]dee!**
?�����'���o�������J�S��1K��z����(�����srr�c���I�#�_���������(� �������2�b
YYY���������U����O����\���*=���q�^VV,������*;��xK�N��4�����0Q��5�����LDTqx
&"�X�U^��jk<f-.�J��a�
[��K��v�|�pG�	Mm�^a.�������)fgxyq,�'�^���]�>>>X�nP���������b����JC
6�����}��Z������9s�`��Y8z�(������������������+�g�>|���D���6m��?���x�rtt,�|��\\\��UK�
����2$�P�5c�Q������z����we�����gffU�����K�x�
<�L�.v=k�m����HJJ��������������V�Z	9@����x����+UL��$����J��9s��R���oG�n�D�������������i�&���m��a��o�N����ji�J�Nq���Z���,��W_a��e�GDD���_�X�CDDDE�P��agw������p���Q�yz���D����8xp?����vv����/��sr���A�P�J���a"���k0Q��5�����LDT�x&"�8�UOw����r�n���S�I�&��7�����H�v����Q8��$?�����}�vt�d^r�F��(����y��Z�R����*6�����)����[7t��
���C^^N�:�����6m_�z�*��������Q41�`0����*U<���E7
+M�Zu���)$���z���������E�'��%*���kBb4o���m���C�smy�P���vbb"m��5�������^b����EGG������o���D?�R��f1�N#�;S�[
��v�2J�{���?�����'�_�h�Q h��jY����*Z^�h��-���Z�<&��� ��d�\~@������+�P��F�^�S82�(,��dO����z
m�^eR4����?��Y��z="##�v����N���/ZWi��s����0;a/''�������G�N��`�\�v
_~�%����q����/_������}�6����OUW���%��>x����T���s�,�_t|�����������~6�V��ae��N�:e���%((H�.�,gK���Z�*�vv��H����

�U}L��$LUm�8q":t�P�\�\�U�V�.ZW�^��C�J\'77��X�^��b��:�\���DT�H'��dz(�*�����PP �����sk���d��%)Z!��GDDDDDDDDDDDDDDDDD���]����&k�i�/��U�k�N��z��8��ONNF~~��n�H�93)��]���L��cH�0%!!A��$�#G��K��L&���S����G�.j����K�.B;;;'O��z<��z��s\���D�����N6�i:v�(j������E�����rm����,�����*�\i���K�����s������%jN�7W��oj��U�����<���������&M2k~pp0�z�)���G�;t�z��Y�:E������QH�n�ul��-��S�N��Q�,�s��
>\h�o�M�4)s,����������}{8;;W`Dd0p�����3�t���Y�%1��JI����x���@w�j��X�\�Gx����d��E�'j�'qQ���0Q��5�����LDTqx
&"�X�U^��j���R����]7���V!�����Y������ &��k4
�ju�s�NH(��`I!�������������f��e�����6n�(������0����+V�@��]�%gggdff��W������X�����J��RQz�������7b���fU�JII����E}��w�z�T3�������v�Z��*�=�O�>�����w������U��������ys�����7�{�n8��#3�>hKE�#w�����7��O�5?##�(1���T}1i��ptt�B���tuuEHH�������(iO��j�$���,��4�Jp�����`}
GI��fn�^u8&K��]�k�.�>\\\�>u��pvv����$�^��QFfD������Ej�q�^AA��X�yfI&�]���r�LT�U^���*��DD��`"����0Q��5��z���a�I`o4l�����W��T�v>l�]n��
<<<��3�`���(�7oV�XQ��w�}���	///Q"��'���_b����g-N�+�pm�\___Q��*>��'v��a�:�Q49����h������"55�u�V�����z<j�ZH���������M�6��/���g�y��y�����3�5I�~�P�~}��s������+��o�8����%;u��
�7.�P����6:��y����E�5�{H�f��������c�
�ez�/��<hT��2�9s&^|�E���o�s��pw�MdS�����O>��u�"66V����O�j�*�������tB����I	U�JQM�j���E��eaK\���			�r�r�����z{{������$�)N�������1U6ju7������X���h*��d~~:��'���9I����!A�W.�Ug��<	gw�r������y�\�]�L�>]����_~����9k����5k�^C�P�C�B;>>��-+v��70l�0��Y��U@@�(	���AJJ�Ys����)$4��q��Y���?�C��=>%%��|�m��h���;�y�������s�a����w��i�3��1��X���p��A�����0�d2�+,,��}�������������_JL�\�f
V�\Y.�T
���O���5���O����]k�l;c���G5G���E���W�����������'�X�V���[�Z4���P*�B���#;v�(9�8�N�BZZ�EkZ���?/:��]���q��=�����������u]�<������R�����_c��
%������������+�����I{�H�&MDmK?=��x�?H�&�=��s�Je4������K��u-S��P����Q�;�������C����=����M%����Kc�C*{y�5�N�Wc����C^o
��}��k�N�:���^��/��^�u��{W46&&S�L��/�4{�������g��[o�eT!))	��-Chh(����Lf��gq�r9���#�SSS��cG,^�;v���}�D_E��-������G!==]������C�������Je����kz����M�b��y8~���*�#999��e:t����o��Z�B�v�$����oc��AB;##����#��~���V���,Z�m��Ehh(~���b��_�~��3�<�Y�fa��-��g����u��}�7oooQe=�^���~���3�����b��q�4i�x�	[�[�L�>]�p���0p�@���������u�&O���'�`0�c����a�l3U?
4@�N��vFF�w��-[������s�0f����+0F9%����(�w���1b��]���w��mG�5���iS�d�-[��Y�fX�~�d�Fll,��Y�^�z�]�vf'���B�_�UTY����h��9����k��I�KHH�����'���aaa�|���������o�-��h0���/b��	�x����7n���^����E?�NNN�;w�Mb�����P�4m������f_?��jEm''����Ib�.]�h������7n,��^�t����kU�c"�l��������/�&��c+ ����s��������i��pv~�y-{�U�#Vk��Ng�����bKBUE^�.xfF���Yd���<����zkx���<�Y�lN�>���(:_�bV�\��� xyy!))	����WWW|��W���L�0�V����g�5�-[�����a�����@rr2���QPP ��={6���p��U����7����;���k��a��Y�c8��={
���z?��bcc����3g����F����<@LL�(1��/���?�������|�2��}����P(�[�.�j5����[�nUtrr���kM�S.�c��M>|�P��`0`�����};�J%���	�V���T������9����"))	���HS��������[�k[�d	���Odff���0a����kx��'�P(+J"���;��'$��D
��6mB�^��b$yyyX�h>��cA�V�����i�U�V�8j��>�����S�&���c���pqqA��
!�����a���3~��G�i���uj���^xAt�}t�,*  @��~��i�u��/_.���yaaaP(���t:����������F�a���x��g�$��������
___8;;#==III�:�������'�o��~����y��[�u���v���[�.d2���g��<�o�2t��Xi�)z�(|�1G�O&���2��Y3Q�xLL���������[�69���c����N||���goo��M�J����DT��]$�5)�`0X��}E3UmO�_;��9K��J��zLDDDDDDDDDDDDDDDDD5������
���i?
��`�{��'���
{��Ahh���`0���[���%����a���U0�����;��aCQ�^����Wq��I��qC�<����~������G|�����E��V��s�N�������q��EDDD ::ZH�������O1i�$��*����o�FTTN�<��W�%*���c��}%&����c�������;;q��N�k������8w�n��-��W�^�b�P�����_Q�vm3��b`���FEN233q��9�9sF�lu����s��R�U7���8z�����^����7)��4p�@<x���6������;��o�5zOfff"**
�O��Sxzz��?�@HH��k}��g���o�����O���_]s


������+e��#�z�Bdd�d����$\�p'O�����%�C&��x/)���A[���;���'�t����3g������9+>>>����Y��L��D����$::�����O���J�����{�����{������}�����br��O?-j���O�	$���g����W/��H�Q]���2�Rw����OCz�GS6�����`��W���p6#z3��DDDDDDDDDDDDDDDDDdL�b�~/5��W[�NC���i�����D���A��S���q��q,^�~~��L)
�9���U�3W����i��A�R���cG����X�ld2����k�����/c������7���'''�����Oc��qP(�cd2����'N��7��(���,Y�}����������A|���z�*:u�d�vvvX�l�^���_~������@������g�Y�w��+W�`���2d������*z��2���?"""0`��?��������g�����8���n�������5k��Y3��d2:t��;v��?�����
�����_�����r
S�T�����/��><�7������_����/Z�n
�Zmq���Sq��M����F��Eyxx�����?������R�]�x�	DDD`������7��P(��S'�����q�>���q���R��]����b���h��q���������fW,��Af07��l�{��8r������o1q�������^�z�����y�f�=�h�_|������<t�P�k���}���>>>�w���_��z=|||�2�����W��*z���KL�:����xL�����h�����p�B��p�Rzz:8 �{��77�
��)(������:�m���CP��U�h������z�^�RYp"5��nH���
�L������u�����LDTqx
&"�8�U,^���*��D5�����������E}
64��UU%�e�zdb���Nt���6��j�w�O���ae�R�����k�����R���`t��
���VY#33G���7���GGG��W;vD������5h4>|�o�FFF������;[��\AA._�����#..&�����u��

*�:�/^���������T(�J���#((M�6E�:u��NU����C����{����Z�F��-��cG������;wp��I$$$ ==�����������?>,X ����PLL�=���x�t:xxx�Q�F����Qu���`0����BU�G�___4m���7�����l�8qw��Err2rrr���ooo4j�M�41+	�0[�m���������{����
��www��� 44�R��Cb�7T��K��<y�(�k���x���T*���������������c����9s���8|�0������{����`�r&L(��3�r9�����'�},@��=��T���Gt\]]%���1U6
����I	7����W��=��xXlVo�M����Z�:B!
$�:����="""""""""""""""""+��w���t(��Ca'��RQ��l��\.G�����fTV...8p`���Z�j5�^n�W(h���(i�<�d2��SU������2�_�>�N�BV��t%��d		AHHHE�R&NNN��\����������!C�TtTU�Z�5�s�=�-Z�k��a������K9y�$�~�mQ���SM�p�]�6�M�&��8q"���gr��>�������9sf�����\\���C��x�b������*N�>��Oq���DT���J���E!??�����\n�R��_��x���B�����yQ���QM'��������TvL�#""""�*�I{��\.����E`�_��������Ec�����������Bf��d�'�|s��)v���~���B;::�;w���;E%vccc��+���w����w�V�K<ooo�Xf����S����z=~��7t��111B�:u0c������DT��=����<��F�8��Q��$�u���v��tIg&���������}�f��%����������E��u�����7o"77W4���[�n���k�k��jl������V���}��
����������;w����@4w��ax����>�w�y����!��Z�
�|�
������h�����9::��_~����Y�T�c"�l\\�����IF��5����ny���R�!--��?77:(J@��6�'�����^����DDDDDDDDDDDDDDDDDDDDDDD�3
*�w�y_|����E������S�p��e���F�����h���Ykt���v�2�.������(DGG%���?�����-*5/���e��;V�_PP�[�n!**�(������'�t�b�:����*�L�����Fn�h�F��5��p��7'�1y.f�X=."""""""""""""""""""""""����W����k8�<��c��WXPP>��s�?
6�h���{���K�2e
���S $$���+~��G(�J���J��~�	[�nE���M�svv���Sq��%�����u��yLD��Z�U�?;�&��{6�������P8Jn�j���O:��h������r��������������������������.������qc����HOO��c�p��u������>>>h��
5jT�5|||��W_a��e8v�._����T888���:t@�
�r<�>�,�}�Y��q'O�D\\rss����&M��K�.P�Te^�:Qe�V����E�:�lM��d2(�~���e�M�}\i�N.C+WG�H�2w�I{DDDDDDDDDDDDDDDDDDDDDDDT���7770(�5��O������x�A�VK�+Nu<&���T����Ide]3����W��=P�L%���`0@&�B��$�����GDDDDDDDDDDDDDDDDDDDDDDDE�+:""�z�������c0�6���T*?�~�>��iB;��Yr��R���%6"""""""""""""""""""""""����GDD�2�����AF�%GSz*���mZm��:��������GDDDDDDDDDDDDDDDDDDDD%�?>��EDD������b�!�9Hn�h��8�����pp���V8i�����$�E�3i������������������������c�YL�p��G[�m�GS6*��d��=�L�W�j{L�#""""""""""""""""""""""����GDD����*���z96����J��=����<��f"i/#��������������������������H��=""*��t�������GSz�*�z�t����������In#""""""""""""""""""""""���I{DDT*�.Mao������q4�����L� �M��^�v�N����l��EDDDDDDDDDDDDDDDDDDDDDDDU�����Td29���%�%k��8�����P�|$�i����<�����Rr\TzV��FDDDDDDDDDDDDDDDDDDDDDDDU�����������YY���%�8��S��$�'�@��t�=V�#""""""""""""""""""""""�G��GDD��Vw1�M�	�a$ec*i/??���B�����s9���%6"""""""""""""""""""""""�Z��GDD��R������4��6����J��=�j����J'��������z\DDDDDDDDDDDDDDDDDDDDDDDT�0i�����T�=MJ8��Q}���	vv�����x�u3WG��d������%6"""""""""""""""""""""""�Z��GDDe���&��������6���T*_���I{J��\%�1i������������������������&�Qyx��Lf'�M�9b�hJO������`0��v��������r��������������������������&�Q���������6�����)=SI{Crs��������Zd�KlDDDDDDDDDDDDDDDDDDDDDDDTu0i����L��E�?55:GS:Je-
�mZm������==�3r�!2"""""""""""""""""""""""�J��GDDe���&������v�����Lf������I{��J��I�>����%6"""""""""""""""""""""""�:��GDDe���vv����5GlM��T~������2Z�JW���`�QM��=""*3�L�gg�m�QGSz*��d^�Z���,9���������������������������I{DDdju����K��M�q4�c���t���!&*�����An���"""""""""""""""""""""""���I{DDdjuW��4�c6�������PH'�i����7�1���tL�#""�pt�G��mM���)�Lf���V�������J{�qL�#""""""""""""""""""""""����GDDV�Vw���h�a0lM�(�����E���D���L�#""""""""""""""""��)&&2�L�
����j���0�{/&&���Z��V�����Q�n]8::��5��r��,7�|���j��?�������*:""�>��]���_�����pqnXQYF���������K���' ��	����J���`�RDDDDDDDDDDDDDDDDDDDT����_2�o���P����������HDGG###���P��h��Z�jOO������=""�O�N��0
��i4�U(iO��2�V/$��qs����_���\;)�1J"""""""""""""""""""����������Wt(DD���`��+W����<y���G^^�0��_��u����^���?��/��'O�49N&��i��<x0�}�]���Y-�.&������������m�h�Q���
��2r�����d�M������rz�}D�g1i�������������������
<�^�z	�y��a���P5%����=z����+.2����E	{AAA�:u*�4i���3����Q��������hV\@T�}������q��)����l�+W�`��q8}�t�c
.^���/b��	L�����GDDV���*����rz�ry�OfS��$������kg;�tV�J��h\TF6��U�k�DDDDDDDDDDDDDDDDD���`@nN
���������(�����~�Ax������x{{W`DDDU��;��?��t�C�a���HOO�+
��S�k��^�GRR���k���l��GDDV������/������E���cDe�������t���A.���9I&��I�.��������������������wbp��!��q
��7������]P;�	�6xM���w�������[����3{|tt4��\�`��L�#"*g��������>��;�!C� ##C�k��	����A�A��IOO���G�������~�j,d}L�#""�rsm���F��5�U&iO�:]"�m���S��h������p���1J""""""""""""""""�����HD����+M��fe���s�s�"~�����~�H���a�DD���k�D�f��UP$DD����/��k�����]�vh�����,X��jk����?���(a��7�����aoo/9���
����l�2V�����GDDV%��A��	��m�h��'����,co��\��>�h�V/$���:I��5p)S��n�������������������j���t���k\9z���qW.b����K��0��n�!Q����*j���:HDd
s����+P�^�r_���>��K�����S�����=����<�"+b	 ""�:���dF�����8��d2(������x�u#gG8��?� *#�\b#""""""""""""""""��������J��W�����a�4<�c������V+j���u�i��&	{��������v@@�.]Z���m��Y���=���||�4��P����s��_�{��g/����"����E�ga��w��HDDDDDDDDDDDDDDDDT�<��_��6+�*��L�����0z���U?�*����z=�;�k������P�TF�n����e�uRSSq��\�z)))������j���v��!  �jk�Ebb".\���7o"55���P�����E���+������>��9������C�����	�k�Fpp0�7o�R�?;;G�E\\�P(P�vm4m�m��a��\�z'O���{���A�����I�r]�`0Xuw��ADD���&��t��Z�jYu-�y�&��?�{��!55���;v,���������c��!..����h��=Z�n]��7n����w�d2�����={�����GU�T�s��/���;HKK����j5��c�2]3����Wq��y$%%A��@�R�V�Zh��	Z�j�2�?//�������
777��W=z�����U����;8u����www��_�{ay������C��	��3g����#����=""�:G��Tu���m�h��L�����L��g���b2i��������������������
��H����Y-a�mV&�-���KW��������


�|�r,_����3��P(0b�,Y�����Z#**
?��3����s���L����c��Iptt,v����,X���w�����S�g0�_~�{�����W�]�E��1c��y��Y����-[�|�r?~��q
�-[�����1m�4��j����Q,\����=�_X���1y�d��9���&���gO:d\����C�&���7���7+��P4nK���[�	&����aaa�ccbb$�_|�E�[��g�����8u����&M�`���2d�Yq���a���B;::��=Y��d��	��z����^���u��|�r\�pAr�\.G���1g�������q�F�X�F�:t� $���_�rs����;���k����|���������`��98q���6�L�!C�`���_��Y�Y�U�s��j�k�.l��
�������M�U(���f��mt�/������?�E &&��}'%%a�������p��]�������o_L�4	�(�Z��a��%������h��+
�9�/.U2|nn.V�Z�o���.]�#����m[���{:t�E�/��`u��w�	����0f��
������ "��G&�������[�^��Je��!�����I���l���QU������b���5d�h�����e�U�F�A���1s�L��=�aR��-[��U+8p��5V�\�6m�`��%8{�l�����u��OGhh(n��a�z�5s�Lt��+W�,1a���_����W�^HLL4k
�N�#F`���%&*�}TT����3g��8>++�G�F��]�{�n�	{��J�|��|�IDFF��5���A&�	_�������~���7���/_���C���02�����]�vx���L&��N�8��C�b��A���(�z:��>�,^x���=s���m����-[$����I�=z�����E�,@�>}$����	m;w�D���FTU��v��#G���M��M�^3����^�za��i���7k
k�����%K���<�f���o<x0n��m�qqq���#���+��<<�7oFhh(���,:��'O�q��x��7L&����N���a�0t�Pde8)�<�����r��M���E���������0i�������=�����m��
'��K�Y�j���������n�����������C�u�v	J�YFF���g�#�����PQ���t6�/_�h�Vk�����F��}��h��
���g4���K�����	qe%���'�4i"T����3���{#''��5&N�h��<�z��;�Y�f�U����'&&�G���e����u��m��h��5<==E������={"<<��5I��Y��t�R�����f��!44T�{;w�\l����!�(::�;w6J����Fhh�d����w�W�^HII�x���0�yxt�BBB�JT9z�(F�-�U*�4i"y����0n�8\�~���c���BR���;Z�l���[���E4����1b���,>���2�C�ks�:u��yst��-Z�������_~�%^~�e��J�x�
���+��WV(

B�v���E�R]�IMM�SO=��g�
}���

E����T*E����0t�P���������z�Bt��9n����qc�
����;z��-��*�<���M���V�Z	�����h�"t��~~~P�T���G��1g�������^3������07\o�M�g�`��d)��yyiF��������W@�g\U/*#����#QU�c�M����+�����Z����3q��i�-������b����_����������FFF�N�j�ZJ���
��O?�=z���Hrr2�l��>�@��w��}L�4	;v������{����[o�%����?~��x
?�^���+F�����s���Izqqq��q#>��c���.^��Y�f���?7�fdd$6n�(����0s�LL�<Y2�)!!G�����.��W�^����cE��Z�j������q����+{��q��;���dgg�������g���%���e����}�
�-[���e�L�\���+��]:t��>��z�\:�)S����+���_C�5J��������G�<8s�L����hN��U~~>�{�9��sG�����[o���^{
u���o����?�k���N�>�)S����6;����			���P,\��{���'N�����>�����\��S�-��Q��������`���{1i�$�����1g����x��w����G}��={B�PxXl���x��7����.]������k��}�UAe=������Q�0h� ������M��`0���������7���������=��g�y�h�����/K�.��={�m7n����d,���������= 88s�����C���������?���p-6��3p��-�����W^�o��'�xB�������Wc���BRdll,.\������/b��1�$�n����w�A�>}�R���������x�����nDD�|�M�Z�Jr��y���&��`0��/��;��cTM���{�w�N�<��>�#G���+D�P���=""*��psk���sF�4���W��?M*����W��u�z�dr�d2��:����T�I/�4Qu��N��\��Z��/ �N���d��������o��L&��
0n�8��AAAX�z5��m��_~111�5p�@�?�k�.v���^y��3}���v���K�.�i��Fs�z�)0Jt
��k��	X�h�Q2HQ���x��w0v�XQ5�o������Z���W4���o���	L������#Gb������O��8�#K�.���v��s�N�s.����K�����O���+<L�x�����N��m+��������&x���5k�IK��d2����F�������8�����
+����'����mM�65�{��������B���;v�����>�����o��}{QU���7c���>|�Yq?J�5j6m�$����c�b��F�a�����B��y��������-[
�.��o��s����1r�Hl��	�����J�S�L�����=��w�U����xW�Z���;������eK|��Wx��g0d�!��?�X2i���OH�.�H]�tU�-��0s�LQ���#�q�F��w���W'N���q��i��>Sn���R�m��a��AF����1c������������~h��y$??c��%�-X����d2��xWWWL�4	�
B�^�����W���/�����9�y��n��!j���a������o���u�VDFF����B����#D�yE@DD��Z�U�?%����_:\�2�$%0����$���9I�;��-�'""""""""""""""""�(���%&T���=��x���]a�����*���.zn��W_�L�+l��I�8q��k5k������<==��O?A.���u�,^�Rm��-1a�������999�V�v��������J�Eyyy�V�Z������d������?����s.����g�����]+T��

�7�|Sl�Q�Z���{���v��]�������(qs��E�	{�M�4	�������J�R����~��RW����/��b�lV��O>)J*((������A�_��dB����h����>w����KkeU�a�n��}/��o_Q]DD.]�d���X�h�P��v����7�L�+�m��pww7{��?�X2a����:t�����j�Em��.\��'O���s%�
�������*�g�z���}��*z?��a����6m�`��%��};�o����%K��}�
Bz�q��<Xi�������+bb�4�/(�Dz�9xx�V@T�S*kA&S�`0�G�V���?>BL$�%��#^��:*�r�������������������8�IX��K�����������'����}*dm��C���o�*�
,0k��E��a�����Wx��
�}��8q����c��^i���~~~B���c�0u�T������rQ�CYl���Fh��?�d���
f��-Tw�������1c�X%6)����IfEz����M\zd����2e��>s�Ly�e����w����>}�Ys.\�
6 ;;���/�I�&f��3g-��5jZ�lY���C�b�����Y�f��I�9�Gd2���K�
}QQQB�������q����?������j
������_��\.���k�v�/�������Yc��#��y���+?��3����>��#�cj���
&�n�c�%[��}���v)����!����_`���FI�3g��g�}�3f��7�xk���I�d9V�#"�r���
����d�Gc9�L�R�hZ��O�hm"i�2�������C��	������U�V���XKPP��:**�&k�F``����8W�JOO����n�����q�J;;;�;���}��%N9R��������������j��__hN��(����ov�;�Z������>l�\�B���G�5��Q�F�5�y����L&��#����EQ���;�WET�sX����=���AA�
�D��
�m�#F���[��M]c���!��~�ixzzZW�~�������������Uff�d��������JVA��dx��7���������jw��N��GDD�F.w��G�m�QGS:*��'|N�S��!�Q����t&��m~0z��i�|K�����+V����G�-���GGG�d2���~�I����-��S�bbb�d��5
M�4A�Z��T*%�<~��0/))��>���+j?���X�l�Q%K=��9�'�|nnn����^^^B��������6m�XT=�v�����G7U������4le�M�E
��#(�3��TD�GEQGY@q�u��F�) ���e-���m���?b��mM���qN�������w�����+�z���(�#��rI���=:~��A�s�2+��ukEFFz�VY�;wvk^��w�l����R�c333�+�����p��Mz���5l�0�h�Bf�YAAAN������*�6_��Ago��t��������k���k�]�<]���d���������dr���M=����;e�]v�e�qQQ����=�W���]n��������GheBBb]n/,LSq��Q���^<�=>����0.�1�2e�$�#55Uw�}�5j��~X.��]����"����9|��������oV�-���O��/��������T\P���z���mkggg���W���5d���9Sk��u����� -�}�g������N�>m?G���seC2�	�?�e0�<�v�o����;t��0v��S��h��n��n�s|/����:��gU�__�_~�E:tP�n����S��-Sbb����TTTT����<x�a|>�7Oxr�)}}������x�	��#�]w��9\�K�q��EDD8m���{�
�����v�V��*��{�l8O������mP�z����.�u��$�������c�ST���;�����b�MFm��*�
/��zTO�<xP�����c�<:�����:�2�6m��!C.��YE���� }��76l�����p���+�r�JIRHH�z����n�I��~����_�9��9s�������d�:#�$iii��2��_�N�r�WO;D�r����|�Jw'���k����j����Z{��Q6��ip�S�x�}u/��}�b�*���_?��/;w��-\�������Z($$V��'��Y,��}h/00RFc���s��������r�i/��D�s�j��: ;;�a\��Qe�v��HAA��
��k�������V�Z�Q�F
Whh��>����^��+<��|�9sF��
s
�o�^}���e�]��
*44T&�����{L;w�tk�-Zh��mz�����[o����Ns����z�j�^�ZO>��&L��^xA���Ns��=�������������k��|}���r���� ����o��UN����@���[��uS��MU�^=�L&���8;x�`��X�g�U�����^R����������_����Z�rggg+//O���_���x��`���G�����Y,���"��L���9���jM�?�""T����U�g��@���]G���w������u"a���k����=����+-�v��'yQ�PMnn�G���8�yy�y�%$$�������y�t���Vz�������^x���P��-�`�u����c=
6���������)S�n�:���OZ�z�6n����<���;w�V�X������S����m��_��z����n���������g��j=��c�����N����7n\�q���ZZ�����l���������G�u�]wA�l��E��U�}�b��M���`������iZZ�y?Dh�ufs/���<���VXX�j��}&S�rC{6�M�A���
���<�y�����Am_�
8	0]�����4n�����K�����[�j���0NMM�������|��g����G�nk�X<��B|�����&�I?��C������������G}�����SUXX�-[���~���u����}��i��������Q6b��t��W�W=���=u>a��ELL�=�WRR���4����}|���'��%$$(>>�>n������kWz�/�f��a����f���l��P�^��A��K��>x1k�����f�������dy�V������
���?sL/I���lI��n{&S��KJ�UX�f�E��c'>����|�u�~�]�g_���O���v�����;w�tk^II�6o�lw������$���������#Gt��	���k�u;��������*�#((H=z���������7�|S��{��e���1���1����*,,��zj:���0.���"�O���rj��M,��������/{>�]6lp�{��n�$��?���YK��e����*��7w������/f�:ur�v��)��OIIq�FEGG_p]�z��^lVdd[��,�_|\��BBbU^��j=i\^hoON���K�Q���6i�F����Z���S�&�|��?�����k����xw��9sFEEE�q�V��^#!!A��w{~�7�Kg������=���_~�JH�`0�������9l_�v��8((H�z���sss�q��*��t]�x�W���(��'A��a�?����;���'��/;���w]������������a\;�
0�a����
��/f��7W�v��m�����������/�-����'��>.����WII��}�"  H��u\��Z������]�)�I����$�b���>Y������u�U��=�}��w�X,n����v �l�������z�-��JRx����rss�>��uz�t O�RSS��\{����s�z�����'�qu(��->>���RSS�"�R]��s�z�`���mE����x�b�m}��y�������9??_~��Gk]�=d��A
���-[����{�~uk���C8����Z�lY5V�w���[n��a��W_�}��E�����������>a���r{QQ���v����L
\n���#�wYX�"��o��2s�RP��t�Z��W����W?�������Z�j9�	�j�j���n��3����]��C�a��
n��o��q�l6;��>666�a�n����^K�,q{��Q6��4��{�U�Z���/��R�}��W�)�:'%%ye����S'��_|��q3f�P^������&M������z��7�:��g�u;���G�[�����p���g�}�������C����Q�F��%%%���{TRR�Q
�m����GyD�T���^������ �x��E����+=n��������m���U]��=�O���Y&���X������;���BI��`P��0���3����o8n�"b��O<1f
7�+��i&M�$��`�������O*<��>�|��F�Q��u�����5g��
�9p��n��&���t��ZDD�}���?*--��c�4i�F����7o���^�1�6m����=���;���5k�������zw���i^tt��|�I����D��~��.]�Q}[�n�m��V��+����855U�W��h
I;v���k�����W_}�C���/��4����P�X�FM�4�a��)S���?Vx��~��}�����>�y����a��;�����������_�x���6�l��O=��BBB��_~�E�F�R~~�[�o����rw�q��������C����n����P�����Y��]���s|u�����������

4j��
;$�>}Z��~��%t���N{~���'BS���}�/>��s���$��������(B{�+��Q����#*��Sx��?=C��QUz���G����{�c���;��S?���=�07))I'N��i�Y�fn�3f���SO=��\)))�SSS5g�u��EG���`P�V��^'  @�
�������{w��5KK�,����?������u�3F���?��������c������}�*--M&��������S�����m[M�:U���w�JvN^^�-Z�n��������:t�UW����Oh��a�qVV�n��f
>\?�������j��M����/�s�����K�����0���[4e�-Z�H+V�px�:T����N�:%KJJt���k��yN�"��7�=Z�����f���^��r���I�����:t��y�%'';�=t��&L��{��W6������n�M7����q�������G�8++K}����E�������C��v����~�l6�i����������?���?�P��-s���[����m��Na�E���+�����]���;�>�@�UW]�v��[�F����+EGG���_�^������S������S�N��o���	��Q#�;V{��u9���A_�Z�N[�w�KNN.wn�k�+�=�����k���C��u���K~
����W��u��={��M&��y��*x������P5��>:c��i{f�ve)00��rOPP�BTR��?8��XR������)(R�`n�������FN���_|N�i�wqWD�Y�����M�]xq�9s�h�������t6�7w�\���j���j�����T%&&������[o�����q����ok����5����W_}U-[�T�Z�t��%&&����~�SO=����k��}n?����oZ�t�=8����)S����j�*��3�?���������c��v�y�����s��U�V
��������L�����O>�DIIIn��w�^��1C3f���hT���e6����t:t���`XX�>���r������o�w���lZ�x�/^���5m�T111�Z�JOO��c�^sw�3F/���RSS%�
G��Qi����6m�G��j�g�������lIRFF�����������Ke4u��1�i��}5z�h��F6F�Q.��t��Ig� /���f�������l6�'������~�mW����/�����������9r�"""��eK���c:u���������O��S'���W�����N�����gYM�6u�s��C���Cz��W��<��c��h4�i���]�����������O�]���j�J�/�_��{�0--�~��S��bcc���L��������}��N�<����5w��Z�b��}}�Q�����/��BC���j��Gg���h��$&&:}���h�{���:�U+���>c6�r��f+VZ�FW������X����?>	����$m���P�I3�y�
��������W?�y�
{.DEEi�������v���C�i�������(-]���FAAAZ�d�Z�l�����D������u�������>���?�~�����_w���.����K��~�������{�nm��I�����^@@�^y��?���J+..������7j��}NA�F����_����h�\�R�>��?8>??_			��q�v�������]r�%�a6���W_�^�zn>����iS}���
s|�^vv�v���m��9���K�������E�Z�n���]II�<���7�.
:T�W�VLL��*���g��z����~'�����[�:�bbb����*..���^{�5�CX�y��W���o:]s�������;w�e`��h���.;����j��]��q������y�J�%�U�}�b��-_��������;vh��N����(������w���Rq�|&<�r��������x�dj�r��z���AH�b�]��~[f�W�j���(]��d���T5n���c�i�[�L�uOVhd��*���������k��Yj���{��F�F��;v8t�sW�&M�y�f=��C2�L�������/_�9s��`0x��$������{��s�i���j�������:_\\��n����G�h4��c04x�`m��A���<�m��M�={�
����J�_v�ez����o�>�����55g����O��w�[��f��������+����o_����z��7t�
7�y�����T@�����k���M�t�����s��^{M+V�Ptt��+�_�7��������+�(w��`P�n��d�}�������a����u�]������o�r��L&�}����{�y�����d�/_�~�Aw�}�:v�(���q���������;���U��n��v�����ni���K/��M��t�R
8P����7�����f�������w9����Y��}�w�^=����U�V���f�y�8p@�_��
�y3�J�q���{�n�k��r�����?�})33S�V�����(�S�b�{��:y���tXXs����j��}99�JNv�]��5��������D}���4g�9R;\����u��`�>\���p
���u��`������UTT����;lk���S���*�H�~��g%HP����d����#T��ejp��j�����Y�c%%%Z�v��������h�B}��Q�:u�d���l���/:p��222�K.�D��wW�&M�d��`�X���?�������Rxx��7o��={VI����b���W����������%�lh�Q�F�����7o~���l6���[�w�Vjj�������h5o�\m��U��
/x�����SZ�f�N�8�����f�o�^��w/7��?9rD7n��S�������5h���~/��i��i����1q������n�:%''+??_�j�R�V���gO��v��f�i�����t��'���j�����kW#�=�����a��=�3g�(//O�S��Z�j�6m���+�W���Uaa�6m�d���n��j����v���AzU����8���1j������&*/��BCUCU�1�b��g�&+"�lh/.*�eho{V�l6�yRp�����z��0��fS�5OE��

R�)���\��������nF*""BC�������l��7�����F�k��!��
��'��������#����I�&~���O�f���#]e����W��\���0
8�J������*((H�z�R�^���T"���1���%m�+������Z.�Y����qQ�?��RX�#�o�\4��C����0{jB{�
	����6.�Y,���$�����V�I���a*��	�e�z�*�/�|�\N�=��W�l�>��3!!�C{��'��G�2��r^<�=.j��>g���r{QQ���v�����i�f+V~~�}�r�=.n��>W��U
v��bY��j<RG���>�5������o��*,�y�6P��|�h4�V�U.�������`THH��}������%6����Jm���T������TT���j<c2������6<T!���3s�R�~��������V���M>��3&S���U\|��^P�AWF���Gh���=@���h����.�Y,k}\�g��I������\���"��g3m�4�l6���EhP-����\�;������H�.�Y�'�����]�I��*���+���EhPmj�{����{��c�?2�b]nw������M�v��pQ"��61�t��$�e�+�����������v��B�ht9/>��#B{�jc
�UxxK��,ik}\�g�������0M�d0�1�u�=:�pq"��Vfso��-�u��J|\��BB�K2��g�&������'B{�jU^h�������>��}A
	��r�Ch/�uh�D~�N�z�6P}��UL��2�]��X������4p����^x���g�TyM�z�T+�1L��;��w��C{&���^AA�JJ�v���&&�����\����=@�3�{�����E��y>��}&Sl9{l��?i�E����Eh��
�=@�3�{��^RR����>��}AA1
q��jM�?��t�������+���AhP�"#�PPP��}�ZW�>�� ����}��r:�e��@n�Wj�����F���p���C{�*�����w��22LF����3s�U���~�������9������j��r{qq����$Ia��	u9/>��B{�`6�.w������x�dr��$�5��8.*������*�	TB{�`25TXX��,ik}\����P������t���m����+��#��fs/��-�u��l>��}&S����O���i��f���<��|���o��}\n/(8���W���C{�d�K�.7)����������o����Z�d0��w�����q_y�=��X���%IF�A"C]���$������oF(:*��>�e���q_pp�r��Vk��q\d��9�2s�R�=B{�b6�r�==}����}\�{����w��th�ST��9�yJ+,�Jm������������|edl�q5�3�����_��^9�=I���[�5�'���d0�_c������?��c�:��%%%�}��j��o�����N�7Vhh����M������i��9|��U�ga����]�*X�PZT��
�RQQ��>�e]����[y������hS�� �TJ�sW���\
���2�E���~�
7����Ww)p�����������+99Y999��Z�j)66V�:uR��M�d���t���oJHHPZZ�
���Xu��M
�~�:��=�_1�������p�g�������rCy�=I�ZO*<�������<�9�O�=��3g���k�Qrrru����\��7O?���6n��V��f��i��qz���d6��^���D�W��7�|������kW����m�|Pc��UXX����zTw�U^7����*(8��j��������?�A����m����l^�
�Il6��

Th�SQA����[�z���k��i�]�E��k����.n�5k�C`�y��z�������j�����1c�Tc�@�;v�������N�8�|P����?+III�:u���i������c�/_���k��Az���*
�I��={����c����y�[�����N{�N�RBB����t��Qeee)''GEEE
Sxx������M��y��j����Fcu�
pSms�r�Y,�{��q_HH�w�^:��)*���g
�t�Z�&�!^��W9�3J=����)�I=���|�����������T���
7���J�?��?��?�]��6m��:u�TcEpq�U��4h���(Y�V%''+%%�aNJJ�n��V�������c+<�������j6����p�:uJG�q:�_�~�����o�z^���;p���-[���Wk���:~��G�����C��������
8P!!�"�_��^���&��;�������=���rr�C{��'e��d0�!2�����r	��O�r$I�wnS�)�o\����|e�8���tl�6E�o�F:�|I3�
^4o�<��7������:y��}<|�p{PE��k��C��O�>��������4'11Q}��^~�e���I�JJJ4a�u��]�[�vk-������Z�F�R�����E��G�����/���k*..�$�����n���{��a�|��&�
�%&&���?���u�����iqn�Z�i�&m��Is����d����5f��p�


���U�l����:m�X��p��dj�r{II�
-
����@]���N��3suS�o�	T�B�U�����C��]��S��\���\�R-��U����
�%$$8�����j�.
4����u�e�U:�y���1c����*--M�TPP��S����?�����`M�0A�>���5kV��&M����_���Cu�u�)?��{�333��SOi����?A�\@uP������]v�e�1c����/��f�2��%�~���<}��7���[��AM�<YG���g(�l��r{~�I���q5�		���n�V���12�����\o���K��/���{������?S��LU5Czz��8**�z
��Hxx�[���:v���������;Y��r�����������^i�
�����}��������^��_�������;��e��1b�~���rCz�|�|Iry���W^yE�^z�n��v�����_
�$�����nSg,���7)$���}�C{��\��vf�������@M�cI��������*9_An�v}����?��a�sMn�w���+ ����������#�������6m��:'NTtt�}������W{|�N`u.n������G��OWRR�S����s����:��+�T��M��qc5h�@aaa


U``�������'���c�����������c�%$$����~��k��/���_~��o�]��MS�-|�jJ
�RtTed�;��X���%������L���?���th/.*���y%6������P��T�B�U{�����*=oQA��,�Fo� ��J�}�())��������<yR&�I-Z�P�>}T�v�*['==]�v���}���������UK����UW]u^oP�������KTzz����d6��n��)66���8y���m����$eff���Daaa�W��Z�h�v��)""�������u������JII��hT�z���m[u��������O7n��'����]��M�6^]��{����#G�i�&�:uJ���^�z�n]��.����s�N�8qB����S��F��F���3g���������X,�S���v���;Vz���a��8qB�A
6T�����Q�|V5�?�������{��9����l6�i������]3�a��}��s�RSSe�Xd2�T�n]�i�F:tPpp�����P����v�����tEEE��K.Q�~�S%����#��e�N�:���4EGG��/�^����?���R��uu���!OMM���_^���{��Z�|�}[E�@T�j�����z����c������u�����C5`�
0@M�4��5����~�z�Z�J�����a��������'���/����>�����
s�	�]fso������*))P@���1�
&Sed�p�^Pp�^s���
��Gs|f.�=\�����:��U���C~V��C�r�����X����^}�U�8q�i��h����5{�l5k��������g�}�+V8�/��-Zh��I?~�BC+~�Ty�����k�����j�*����a��f���k��_h�����o_�k_y��z���t�w(0���[/Z�H������__�<���������o�C=$�������[�^xA?�����]`����	&h������,�\�����5k���Y�������S5m�4�����u{`�7o�����i�G}��c������������w�u����'IZ�b��y�m�����m����Y�t�
7�U���c5�|�811��w�����q���9}�JJJ4o�<������k��9�����~�i��KE���4w�\m�����n���c�}���w=��sZ�d�


���7�|S=z�p��j�*=�����a��>���n�As��������	���j�w�}����Z?���N�<Y�\���A�����r���U�����?�e5m�TIII�;55U/���>��S=z��y���<x�����C�z����������k��b�8�7�1b�f��u^a�������z����g��s�:w��g�}V7�x�G���}�_���Z�V-��S6������uP5*�R����>}���0/����������Q����7o�����*���������>}���[�c��i�������l6�C-�5k���i�_~����x�l��r{qq�22��|� $�A9{l�Z��c"$ ��`��L���$P�,G��zh�W�H=�_�#I^]�&�X,����&O��2�'�
�-Z�H:t��U�<^��7�P�N�4{�lm�������C�4i�$u��E�x��5y�d���Wo��F��=I����4v�X
0@)))n��������k�������}||��N��m��U:?''G#G�T����l��r{��N��?��.��rm���������ce0�_���j�'�xB�\sM��=I��w�n��F=���>��}���UW]�{������t6��a��x��6l�����k���|��/��w��2���%K��S�NZ�h����t6D��_?-^��a����5h� �a3�l�a�������[�����^���{k��Z�pa��=��5s��0`�z�!��FUz��w��ys��=����t������W�]w�>����W�����s���Ig_��?�\]�tQ|�g����q�Z�n�Gy����t���e��t�M�����S����y�����}��sU�e�����;���c2�^���,X�0��l����������d���[0`��[^�
���j��u��������U����f��c���!��AF��������j) ��r����$u�r��5>3�+u�����CIU��o��a������!C�8�c��5k�.]�8t�����M7���{�z�N��2��V�Z�k������.���9{��Q�>}��](Wu����M�6��^
8`���k5p�@���U������r��v����S���u�W�n�������~��i��EN�7n���;�c��N�wN�<����k����	��L���^z�>����W\�.]����>��s����}Yb���gO��L@@�Z�h�.]�����l�2
0@iii�9v�X������:u�Tz��u�4r�H����dR�6m\�����=z���?�9s��M�fGGG�}������""��z��I
>\���?G�����ks��
��];u��]W^y���������������{�U��G�������l��F�Q��7�UW]�+��������������������5j�.]��]�v
		q�����o�Q���n���o��������=88�~�n���S��o��Ft��*���A����a|>�z�����t��V8U�ZB{��l6]s�5Z�z���_�1c��drt��+��B�����9������?������>�e���q��`�����^~~��q\9��}9V�{�6�:�X�(�Tr��@�������Z�l�����u�}l0��C)))I�����y�u��!M�0A����<��Z!!!9r�>��c>|X��������q�Fm��UG�Qjj��~�m5l��~���'5~��r��r�J�\�R/�����;������W�\�/22R�����_~�'N�b�h��=��a����u��	;vL3g�T�Z������[S�L��5��y�CS���@=��SJJJ��S��m�6�_�^�v�RJJ�N�<�E�i��1


���%%%5j����n��z��������G�j��-���Wjj�=hxNnn�n��v�9��{1g���VZ���+|���Sa����Y�f��$u��M+V���b��]��y�f�:uJ�V�R����{�����+X�������M�<���UQQ�n��v9r��-00PS�L���Gu��Am��YIII:p�����^���n���'zT�?���>�L���K-_����m��M�O�������Q�r�1z�h�a���7o���9�={��_�����I�&�����z����n�:=��3�����J����t�������;��[o9������w�y���X��k��I=��c�������������~�����s�N���i���8q��F����>��e@L��������!C�-X���k�'�|��|����^�u�m-Z���y�t��i:tH�6m���;����#G�����w������������@=��C:p���;���7���~��3g���/+((�~��c���/Tz���w���ns����G�~��222����{��b�����S����s7m�����o�����Af�Z��#�8<��u�j��^Y��/�p�z�^�zye-T���n��O�>�={��v�Z]%��g�yF�>��^y��OB����[���s�����
�����e2�*77�i���l��Z^h�D���<����� �)[I��s�+��%'����z��R�+�|��9!�2TkO
m��A����}l0���k���Ns�7o�w�yG�;w�}�����$��:t����z��U8�v������u�m�i�������K�g��m�������Z��:��h����]�����/�����
�5j�HO>��F�����������Se6�]W��{���q����N���5b��1B����JJJ����K/i��U�q�n��t�R��y@@�z����+Wj��Iz��7$�
u��1�)t��sg�k���x����y;v�>����t�w���������cG�8qB�t��q}��w����.h����c��9�k���[���_]7n������d�]{��Ns/��R��������CW��?�\�F���7��V��N��$�z��Z�p���S���n�pNRR�Z�j��~��!�+�}����+W�}������$-^�X;v�PII�F���:�������'*44��w������������j
|
�~�m�����w�lm����[o��[n�E7�p����3g��[nq:�A������T���W/�N����k�SHv��Z�`�S��s.���{�����{�u�V�.��9t��BBB���_k��aN������c�)66���>o�<���p���STT�Q�F9��O��g�}V��i~dd����a��i������������>��9�����`u��q�����c�����m��E_}��C����X}�����]t>rss���w�qG��w��j	�}���./"�$44T�<�����~:t����?����������^�������N{���**�TPP����(:��]��3s	�����dk����2|���]>
��y��2EV���_]6��>~��]�J?~�6m��>�������
�������O?U����o��7o�f����y<U^8�<M�6����oA������>+�aBB��qDD�G��j��]����\���A������
���^{M[�l��
$I~���O���E������{��
CFu�����>���n��e��P���N��_|�e`�����k��m������vhO:��?����;�����_8��J����5n�8{�������.��2��?��`�]w���3gj��}��;v(99�����k��O������5y�d����t��[y������/����>����>��s�����3s��J�6w�q����k����h�����_���K�����E&L�s�=Wi-�5�W_}��;���s��q
BJ����	&h���1�L;v�f����u�z��������������+k��T�Gy�{`����k������2�O+4��L&�-�-g~�q5�		�-w���,I
0�1�u��m�9.�@E����x�b��d2i���n���/*88�[���l�R]�v����W��y>
�6�������sT���?��b���M�Vi`������z�>�������������7O6���5o�<��Wf���VW��#G:��m������|�r=z�>n���&M����/������x����k�w�^��~����~�e�z��j��}��n��F�mS�Lq�����tl||�gE����5,B��=$99Y_|��}�?�����e5j�H>��[so��6�qE���^{��8,,L���?����+�t/Y�D���
K�u<���/���z�������{-���������v������.�C�����A�r��Y��9|"��0M

r�#V�I��NQ�������\���_���|�����s;�U�n]�5�h�����?c�5kf\Q���4����o���J�������5j�(��4h�Cp��_����k���h]s�5n�5��j���}\:,W]��Y�03f�����f�Sg�����c�F�S��S��z�[���k�06>|�[�^y���#G��W\
q������w�!?���C@m���j�����>|�[�`I�������k��3g�i�&�����WLL�Gu
2��8;;��k���`MPPP���g�U�V���{���U����i�����m��
�C=T���;��^y�=������|[��L&����u����rB{����_�r����%�������N�:��s���;���W^����+44T�����O?������������4{�l�z��j����������u�_��~\jjj��<x����;���9s���~�u�l6�[��>������9���U�vm����hp��S'��G��W��8##�%yd�����zt��A��6lp����[+22��������[�J��Kg^�������^q5�����6m��O?�a���E�2��


r�.���8W���B�
:{;���K�����H�_c��]�� ��5�)@�\�K�q���ow��������-X�@C���+..����o���[g�����8�n�������[�?���C���"��{����\�aq���������^~~�l�"IR���[�o����$&&:��vL�L�.I�HMM��w��F��������k�.����j��u_������������E=������/����+55UT������m������z���U�~}
2D3g����k�~=��!H��b����e������O��Q�|�\��Le�����}L-�����������:8����V�3���[��[�������q�����YU�����_~Q���[7������e�������4Uz�7�t�O���\cJ__��_���'�x����u�]�pW�o��Udd�Z�l�;��C���V�X�l��s�����^���2d�RRR��.���X���.��~��~/(���"]�g������b����O�z!Aj�����LB{<S6�P��Qe<���A������>Rqq�G��������c��M�����,Y��q�������7��U�VN��\�RO=������Z�ji��z���t���
���.=��C����d2Uw	$--��8  ���G�:u�=_E<�������=;�k�������w�U�~��s���^������4O�����k��{�7��5������w�9tb�����r���>��b��!C>��n��Z�r�.�����X�����2���(OK����B��U����2�d�:��Z����NQ�:~:�iN<�=T���uyg����z��RN�l�������`��WZHxD��{Nvv���l������S���
6L��s���eK���O�Z�R�F����P���^zI+V�����u��
6�)d��}{���G�]v�6l���P�L&�:{�1��$-Z���m���k��������������k���Z�z��|�IM�0A/���"##��z�{TIII��5G�������������qAA���N��U�Vi���a���@���[��uS��MU�^=�L&���8;x�o��e�#"��>|y/���`M��G�=Z��}��y���g5++K�^{�v��m�����;�"��.��������W_i������P��u��C�=Z��u���n2�{+��[N�������C�jy����������z�i���l�o\���g���fS@����! @���tt��4�ih/:�Q�>��T6T����������=��w�QBB�}\�~}��7O�^{m�����������/8tj���,X��]�Vz������0=����2e���[��~�I�W��������0���@s����+���?;up*�v��m����{TOY���t<j���{x��k��|}��!T��{�!�w�u���w�Q���+<���YK+�3�����q�����<��#����.��-Z��p����4��w������#//O�_�6o�l�����NqqqUR'|��C{����?���1c�T��333S#G����<wAOHH��u���[oi���z��7kd��l���d4�������Z��I����������?u2������K����5����\�vl��z-}����U���855���K��*��g�9�/^�=z�u��b���������L&���J;�:��O���GS�NUaa��l��~�A.���s�����c�����w8G�`��f��W_}^�\l�a��V�X����C{%%%JKKSLL������xr,PZBB������v������Vppp�����a6��)))j������
e�%
4����*��5���^�0>y���(((�_�������m!!!����^�zUI�����.�2?������~M�8Q'N�{��Wi`���X�\s�V�\)��f���f�i������UXX������U�u�T�e���q��������������ro�������#�\[Q�]����E�6T���O��Ge�h�v�����;w�5�����L����I����=��|9rD'N������Z�{yyyJLL��:�����GM�>]			z��7��;��-[��{�:����������+�^����*r����.��h����x��_v~�����a����{�u+�'���!���Z��-[|�vUi�����tX����>X��=���X����e�������>�����Q|��C{_���?:�������K/i�������}�l6���U���3�x�	�����S22w��0���T�d�-w_~~�$)<����������"��}'���u��UW]�0^�f�G��;���3***��[�j��			:~����K��_��=��8u�����:������x���������k?�>((���Nnn�����P�{�'�qu���r��>W�t����{����~������/{>�]rm����B�!}��q��Npp{��y��������������u��f��w�������-  @}��n����,���C{k����h0t��7V8?;;[/�����f�Y��wW�&M�:���_���O�xOms�r��(-}�OkqG``�#]��Z������\���.�&�T�E��'^�:�����f^]�������[�w�}'�����)))n��


������r{�$���;�ss�_�/��T�@�$���:����k�s���Z=�_gO^��P��[||�[�����E`������a�`���mE����x�b�m}�������r�����|}����u!��A�)00�>^�l���������Q�Fj���}|��A�nn����`M��7�8���o��q=��>��c�mo���F�]e����uh/55�!L��C��W��c���K�?.�]�_x��:uJ�����x�b��oaa���}/<@U
�T!!���Y,���
&S��C{�.����S~I�W�|�E��
s�^���	���UK��r�}l�Z5u�T��}��g�N��]�!��a���?��o�8g6���4���u|���]|���{-Y���u�G�pBLL���{��W�j������K}��w^���������5�J�N��;������1c�����QR�0d�5i��>NLL�o�����>��C��O�>j��u���?���6?���u��.�R�~}�5�>.))�=���������';�y�eddTS5p�>XS���W}�����n�����z�)���^~�eM�0�J�C����^���`P�*=���>�t6�g04j�(=��SmMo��&��_�����l����`0�l��r_�����v����:��l��m�Zm�/�Lj{�
������57(�d����T�&M��`���|�M}��'����>p{
���n��������3gN��8p@7�t�
�^G:�U-""�>���������M�4Q�F�����7���?���M�6y����;���5k�������zw���i^tt��|�I����D��~��.]�Q}[�n�m��V��+����855U�W��h
I;v���k�����W_}������/������|�v@�be45i�$�mS�L��?�X�q~��S�����������gO��;���Tx������_~���J_����gO<��S
	����_~�E�F�R~~�[�o����rw�q��������C����n����P�����Y��]���s|q����<�c��yt��]�t�5�8|�A��Mu���Vx��Y�4s�L�mS�N��z���������m���p~AA�~��g�h�M�s�]w9|R��������r.��cz����wDyyG|\M�BB\��l����*������m�9^�
��psm����*���v���ps�*9���G����{�c���;��S?���=�07))I'N�}��'Ij������3�a��SO���WJJ�����T��3G]�t��#Gd0��U+��	��A�����tu��]�f���%K�������l��l�c���?��Oeff:l?v�������o��JKK��dr���������m�VS�N�����������E��[�n���������*��~��'4l�0�8++K7�|����~��ep�j�j��Mz����sgu����ntC�q�r�-�2e�-Z�+V8�����\�V�N���%%%����5o�<�n�����F������f���K/�u�~e��I����|
:T�<���{�:�	&��{���f�o������ ����.S�=����,���W�-r���c��v�m����e����M������C�w���>|�>��C-[�����n�:����m�\�h����
��?�e����c���4`�]u�Un���h4����Rtt�}������];M�:U			.�;u�����[M�0A�5���c�w�^�s�y����b����j���n��}���:x�������������8q�:u������`���sZ�Z�����)S����[�{�v�����={�T���*X���s�����x�kW���7�j��C{-[�T��]�5���k��{������oj��u���f��=I:cY�������T.$���f��[a[��
	����:D�jC�s@/>��V�&7�V�[F�����zp�y����-��{_:��0g�m��U������w���z��7��ys��][���JLL����z�! V�q�����������k��3G����Z�l�Z�j���3JLLTqq�����zJ����}��~>����t�R�����~��U����������{����=���z�����U+�������JJJrxc����/}��'JJJr���{�j���1c��F�7n,�����`������CN��������{���-\�P7�|�����f�����x�b����i�������jUzz��;����c��1z�����NOO/�����S5m�4��_�f������^��������7N��_u����h4���c!��}�j���������h���5`�9r�QBaa�^|�E��9S��7��l��N���S'����>���_~Y����_���5r�HEDD�e��
��c�t��)�1������O��S'���W�����N�����gYM�6u�s��C���Cz��W��<��c��h4�i���]�����������O�]���j�J�/�_��{�0--�~��S��bcc���L��������}��
������o��t�����X��UK6�MJJJr�9�`0�����
7�P��V�r��v�Z
<��z���.��7����~�i�l�6**����������`���C+�_����?<�+8��"#�p��b���}u���=g��|*M��0�s�g���'�dR��C�f�u��m���Q�
�f�uj���rDEEi�������v���C�i�������(-]���FAAAZ�d�Z�l�����D������u�������>���?�~�����_w���.����K��~�������{�nm��I�����^@@�^y��?���J+..������7j��}No�o�������U@������+����*0��gK~~��q�F���C�v����K*\�l6����R�z��|���i�����/������l���C��ms�
8PK�.=����M�-�n�:�����<xP�7ov\:t�V�^���U��Y��=����;�Nfgg+>>^[�nu������o�U\\��k���k��*��W^��o��t�)..��Ww������s���7��h����]�vi�����w���a0*���V�����������k�����e�����2���eK����������A��6o�,I�?����[��sT������u^u|�l��r{Z�z����W�L&�]\��?B{q�����+����P�M����nQ�[F�q���n�X��!s�C���w���������"�%�����N�:Z�~�f���
\���h4j����c�Cw:w5i�D�7o�C=$S����k����3g��}����_���{����������aC����u���8m��U�G���ht9�`0h�����a�����yT��M�4{�l
4H�������������k��}����[kj��9��o����>��u��5�}���+V��1�o��������o��nP������|��5�\�M�6��k�-�� 66V����V�X���hW��7n���7��>pj�S��`P�n��d�}�������a����u�]����+�}�L&�}����{�y�������/_�~�Aw�}�:v�(���q���������;���U��n��v����j���y��
�^z�6m���K�j���
�p��hT�=4c�8p@�?���y��z[tt���Y�'�|R]�v�����~���A��`����o0`�*EMb�����g^�u���A��������r����������l2:y����u��H����k�1��G��3��3�T���������];�x��]���K����^Pi�M��X,��}��}]:��h�?E��������e.��h��Bt$/_]7�u9��������7�@����k0T��P��@���9T��������~+�^cIDAT�m-[�t��u1��l*.,���X���AA���Y%%%Z�v��������h�B}��Q�:u�d���l���/:p��222�K.�D��wW�&M�d��`�X���?�������Rxx��7o��={VI����b���W��������ME"##��Q#u��Q��7��ul6�v�����w+55U���
		Qtt��7o��m��aC��X�d�N���5kt��	����l6�}�����{�AM����#��q�N�:���L����A�U�{�?L�6M��O���8��SIIIZ�n��������Z�j�U�V����Sw;`���}�v{W�s����X�m�V��������\m��AG���3g��������SG�Z�R�6m�
����������k��=:x�������#::Z�j�R���u��W��C���C����j��%��Nx,w��]����b���y�
{����!I��_hhhT
����.
0������bY�w���:�I��zJaaMt�)Xu�����^|f�=�i��*��}�V���BEDDh���^;U1�������v~���v��9�v��`0�d���~��9rdu�Qc5i�������i���_u����`P\\�����=��
��������z[HH�E�=F���^�����_�0^�vm�s/^ll0��W�J�����0����f0CT��U.�Y,�|\M���:n�&K���G��$���\����_�����J�-�f�i������������>��`���0`@��/{���WA�_�m��r{Ff����}\M�C������$�����K�sj��EDD�_�~��l2*))��1c����0o���JJJ��u���Wz���x���K/���^f6�v��f+RZ�FWS9�)�����d{ /.�uh�tA�N�z�6Pu�����3F�V��t�S���[��U+�r�-�]����]��k����
:Tu����������s�}Fhj����\W���Y,��n�A�PU����W\�����R�r:�Ig��52{�<PE����$�y�����+�c�����O�������3�v�Z{��s�}��J��������l�"���.]�( ��_��g0d6�r��bY��j*����$Y������@�
q9'>3�+u����)�����?�Qtt���!�s]�����}���>���;Wz�/��R������wU��2s��kwn�!Y�'|\M����v��j=iWN�����������$�}��Z�r�.��r��^���I�4{��J�w��Q}��7a��C�z�x����iO�,��>��=�u�;�iO*?��#+O�e:��X���s����c����-]�T�RVV�j���n��i�������[��;w��������k�G��*�%!!��J�9��������
GVCU�3�(+k�������)  Pq��C{��%J���MD�������$)88X�G�����/�<S�N�3�<c:t��fso��=��W�l�2��P�k&S�r���� E&SC]� �A�.���g�����M��i��Uw���Cxx�����_����]�<���]n/*Jw���:����r��zR�d2�m������\�����2��x��u��]��X�����2�b]��Z�����\���3	����j4�1T��]\�;c����T�dj�r�Ch/2����9y�-.�J]�j��x���]n�����b��NW^h��(SEE9��NQ�C{�6��,�z>��=@�g.'�g�*-m����XHHl���u��4,D�F����LB{�3B{�/"�����.�Y�������+00���s���A���O�=�Z`up>6l��e��i��m��o������������>��`�����`���K�N}���bY[
U�dj���L�������q�a�%-�i���o5*����_��g�UBB�}��f�����l��2����_���2��VCU��
��s�n����V"�!@q�t�;b-PjA����[8�]�;���4r�H�v�m��o�l6���`0\���3�{��/�����T�dr ��
UPpF��)*����3s�R�p5"�����E_~����^���~j>SH���[��w�����T,$��$��}Vk�$�~H����������
��*3�|}��7���7n���85k�L���

rn�9�cz)'g��v�e�l���U7RW��'��Y����n/I��
���Ns�3	����>�7c���sa�������W��]��,�2�{���yN��(;�wEF��}Q�0������12L���m���w���?Z����~Sbb��=���h����Nbb��`p�u�bY��j*f25p����������NQa.��+)��k����������;��5k�W_}�z��=�1L���\��)�=I��?%I���z��g�z�*p��:�w��)�c����n�MAA�;( I���]nO��l�`��d4���g�&K�"��<��rN|f��j���C{%%%�$��&Ij��Mu������JJ
��������`0($$���s�=I��t��������C{u��q���TS%��"2�
�r�������T�dj�r���l�w�r��-;O�?���_����k'�l7"IJII��r5��`�����>��f��JJ�*,L�$����/�io��[���������;�v���������@Ma6�v�=;�w����q5�3�b����R��:<T���9���^��?���F�3F6�M6�M��-Sfffu��s���=I����a%Vppm����dIRP�AWF���Gh����=I�2e��f��2224m���.	��BC),���}�ZWS1������B{��:��-3�+5�sJJJ��`��;��K������������V�Uo������:5n�X��������e��i��y��YX�zuu���Vw��[��>��C
>\6�M����Z�j�	&Twi?f�����D���:�l6������@��������VII���������|e+*���2������t�
7�����]
\�����u�V���G)))*,,TDD�7n�6m��u��
���j�!��I��7��>�@��w������h��
z�����q��.�����:v�?N�
R������V�P����������Vhh�r;��$���U��H�����3gt�5�(99��K��Zbb�^z�%}���JOO/w^TT�����O��
����}�]���.kj��Y�����=�l��f��i���:q��>��c}��'<x������.�L111


:�5���[��SLL7F�l�N�,��~�6�`��V���jMVhhC51�d������g����f���_,[�M�A��Cu��j�z�j
0�>�:u��M�V}]�J�����O�W���b��Y�f9��7o�x@m��QHH�}{�-��<�/�;V�����	:�%%%�5k��O�����J�gffj��%2�LU�;v���x��>�O�	�IR����b�

8P)))***�?��~����m0TTTTU�A``��������i���VM��S
U93d2�*/��������?����a����4g[f��k���d�r��V��,��-���tB�(B��#����b���R������k���M�6�N�:�X\<
u�wh��EN������AEEE)++K�Vnn���{����������wjLh/;;[O=���}�]�?��f�Usee6�v�KK����|��8��L�.C{V����)*�eh/��j���-�Z}TI��!��W����?����G�,J��/Qhk�+��7o���������D�<y�>>|8�=�B��s�C`/00P&L�]w��.]�8t�-))QBB��/_�/���J:D/\�P�~��$)<<\999|N�^��=zT�^{�~��w{H��qU�0���Smso%&����������2�{��(L�X�����TT�����E���s��P��j���*U�S���������$e����
�XW�n�T�� /T�+!!�a|�WTS%p�Y�`�C7��
j��ej�����j���Z�n�I�&)--���OMM��I���3f�����s�zTw��Z�6l����+��&����e�*����+�r�%m���)_HH�r�����1�uhO��j����z}�y�J��~Z�^����t������0�����B�"�������o�qtt���YSn`���������Vjj�$�s��>�,~�io�����{�CG=�����]�����S��M�� >)����@���������Y,�H�N�����)00ZEEN���dED�T��@55����iN|f������J�S�������-��J�W�Y��ww����
�
��s���Z�������^x����_|Q�]v������o����J��F���}�F����������������5c�=���
��
��l��2����Gg\��rf25Pv����I����0���mt�@
P�S���vUY`�[^�N�K�'u�1�������_UBB�N�<)���-Z�O�>�]���C����]�vi��}JKKSAA�j���z������R��M�l�����]�v����JOOWQQ��f�bcc��[7���^�'O���m�������L���(,,L���S�-��];EDD���sss�n�:?~\)))2��W����m�N�:���}��i���:q���{��kW�i�����l�*=��#G�i�&�:uJ���^�z�n��U��$<xP;w���'����:u�h��Q���v��3g���_����e�XT�Nu��U;v���h��
:q���6l�����Q�F��j|
�{�n9rD
��lV��M��{��fz��}��s�N����b��d2�n��j���:t�p�y���B������k�����K.�D�����Nn�9rD[�l��S�������h������}����|}����qll�&L����3335q�D���GQ\\���G�������u���l6������w�Y��jsL�r��dI�U��o�i=�1�b�����������Jd0�ST�����4gGV��m6�O����U�����U�$�@��T�Q��r�����X����^}�U�8q�i��h����5{�l5k��������g�}�+Vh����Z�h�I�&i���


�������O������{��U����m6�Mk���_|��+Wj��}�}��W����w���@��n�h�"����Z�~}���F���o��o�Y=���f�[�_�n�^x����O���w9�^�z�0a�&O�����r����Y��i��5k*�M�:U��Ms�^o([�'�y��i��q��G}��c������������w�u����'IZ�b��y�m�����m����Y�t�
��Gq����?�}�����;Y��d��q�����W%%%�7o�^}�U��������u��UO?�������m���;w�6m��t\�n������������{�9-Y�D�����8����������U�V������
���p�
�;w��4i����w5�5�Z��������_���~���'��k45h� =��SN�������V�g���M�*))��s������^���~��G��;/<<\�����5t�P�������={�^{�5Y,��F�Q#F���Y��+_PP���~[��������r��`P���������o�����z����^�Q�F����O<�c��I��5k�3f�lmxG@uP��7���n���x$,��BM����X������L
\n���TPp��r\T��9��%:���?_���Ey;N{w�����������,�z�����'��IgC}�-R��j�*��x��7��S'��=[��o�4<u��!M�4I]�t��<^�|M�<Y}���o�Qi`O�~��7�;VPJJ�[k���k���9rd�A��k��S�j��m��������#��wo-[�����t�����?��/�\�7ov���0v�X�Wya����'��5�\Sn`O�����o�Q�?��+s����u�UW��{�)7�'�
�m��A7�x��
�����Z/??_��_t��w���c��%����-Z�2l&�
���O�/v�>}�t
4�e�L:h[�t��u���5������w��1b�.\Xa`O:{�\�b���zHEEU��������7o���gW���^��������������^���������{�9��=��k�����K�.�����9l��Q�[��#�<Rn`O:����e�n��&�x���������������w�9���u\Y�f��{�=�����VXX����w�u����4I�w��4��$���t�����/�{Lu	�'��(���i������zj*�A*v��Z��9jn�A����VW���*[g�Q����N-�-++KC����[�5m�Tu��Qjj���Pff�n��&}����c�Z��EFF�a�����VQQ�N�>�n��g�����;v�^�z�=����������***J���:u�������]�V����+�x���:�\��]�5j���eee)%%E�O{`MII��a�������qc��__���:|������t��I���_��/W���=Z�M�2E/���}�&M�(44T�v��>��s���+4|�p_�Z���D���_G�8��2  @��5��l������F��-���r�J���x����c���_���^���`=zT����n�:�9�43�Lj�������^���B�=Z��oW��-5s�L�n����j���t��egg���<yR��������s�w����67l�Pf�Y�����#G����0��7�Tnn�>����y)��#�<��_�i��hT�&MT�NY�V�<y��k�9�������������5j�H
4��j������������{�nEEEUz�o��F��v������y�����Vff�8�����o4p�@�Y�F&S��U��}�W��;t� ��������c��)((Hu��U\\����n���Cvyyy?~���n��v]{���d��:��0>����?7�������i{~�I��Rx���P�#�����z�Z���Y�'�A���
�o�yNs�e�jT���(�H��$e�d���L��QPl�O��W�'Ovx=����<y��4ib�����Y�f��w�UVV�x���
		�M7�����^���s8�9g����E���������<yR�����%K\�w�����;v����o���;5f��r�9���"##5b�]w�u����4h�4����Z�`�f�����tI����5e��a�s6o��������<y�&L���M�:�?u��~��}��7Z�hQ����v:5j����n��z��'4z�h���:�]�~��{�9���O����\�~����}�j�v|���9s�!������o�^s��)��-ZTX�����Vbb�$�[�nz���5`��}K��f��5k4q�D����?�o��>�|�����+V8�'O��!C�8S�{UTT��o��!���\��_��aC���j���������n���'���>s��~�A�N��$u��E/�����zl��A�5*��G�VAA�6l�_|Q��z�=c���r�J�?���rss���O��G�3�<#I�������S�����h�t�3��~����o�0��={��;��������&����I�&���[5l�0u���)|f����o���w��{�������1>��#�p�
���[��y�5��_^z�%�X���o���_���Z�g����N��-Z������7��b=z���/_�O?��~-v�c�=�C�)00P���y�]z��q����;�����zJ�����c����^��Y�*<�����{}����O>�A�9�������g���g����n��I������o�<�7�����������h4�i��:t��F���{`FF�8�E�����f���;������N�����K��f�^{���~�/~�+�G�t�I<�CR�$������_��$)$�A9��?��E���m���jm��l�6g�W>�K�78�'���E�m��5�1F��`4T���l��A����}l0���k���Ns�7o�w�yG�;w�}��g�����C�j��1�v��]�����~�v�m<x�=��t�R���Gm��u:�����$��S�-���5n�8�����v"j����|�I�5J����}M�:Uf��.�e������W�:�����#4b����+�G���^��U���n��i���._������K+W���I���oH:��1c�S��s��.������5�38��0v�X}�����9�A�����?���;�����w�}��n����/�=9v�����m���={����q�F�888XK�,q����K/������]������o����5j�(�|��n�}.�s���j���.����w��IIIj���~��'�`�t�u2d�V�\������c�/��;TRR�#Fh���N��BBB4q�D���:��������B{������������R����o���zK��r�n��{}3g�t�k���=�]:H&I�z������]�4y�d�m#F�����T�s�%���{�������[�������C
		��_�a��9��c�=���X�{��y��������EEE5j�C`o���z��ge08������k��a0`�=L��;�����S\\��1�����C���������={��gO�n���8qBc������5s�L����u�^y�����^�Ib��_���}�����?\�DPP���:(33�i���N�\2��E�`25����
-*.��h4).*L�8�4gON���Kj�A��I�3�ur���.�gr6$+��A�sb��J�fS�����_wx���>�2�W�����i�&��Z����+<��O?�T�[���A��y�={�G��Ty���4m�T����=�����>���N��;�DDDT�	�����J���uxm4h��������9z����e�m��A����j����U�����Y�.]��{�U2�[���}�YM�8��m��e��P���N��_|�e`�����k��mz��w������vhO:��?�yw

�_|�6+���/��q��uk�������4��rM�t�]wi�����o���>���]v�����5����G�a����<y����H:�����wUy���]�$�w���������u=����9�e`��;��Cs���pSRR�u��r��_~��v��eO�0A�=�\��4j�H_}��:v�h�g��3�))y�>�K�:��c0t����{aaa����?���W�k���3g�f�-\��!9k�,5j����oaa����{����������'�j����o���.��������f6�r�=-}�JJ
|\�k&S��0�ZOJ:�i��"���E>���Z�x�}l2�4}�t��}������Z�l��]���������<�
r�TTg�7������,��bO�6����9F�QO=��}�������WI]��7o�l6��k��y^]�:��1����9#G�to���[%�m���:z��}��iSM�4��c_x��������k�j���n����O+44��b����[��}�J��x��N��L��P�+�����x�F5����
�{�����/���>���yXT�����a�a�DAPr_p�p�Lm1+�]��l_�������e�i����[Y���Z��������"�l�3����������`fX����y���=��a�s��������~�`�����������4w����qM����z�����'^{�5�k����$p�y�fs��*G��q���zh/77��a�o��8{�,>��c<���0ax��]�g������;w�$�h����q��q�]+?�����b��h��=x�����X��.]�������	
�����X���c�-�
77(�^����w������J7���������������������������`0��'N�9���U�Z��4���H���9��}{��5�Y�sUAA~���Y��_~1����i���u��1c$��={�4H]-�����g�\�V���p��jX�Uv��-?���6w��j������O��U*�!F{�}��6�����d,&O�l��=z���SRRl+��h.�a����{����.	��?���[o���6���w�����kLNN�����[n�v�u�M7�?/**�}�ut���"��m����;$�����o���!!!�m�o��F���={��5������n�C���5���3�<���h����r<������DDD������[v�N�8�#Bh4!�������R��G��J�JV5~U���#G�u���������������=z�@������A,>������+))�t�q���$�X�w�}7�t��V�ZA�V����~�q���V�9v�X��������+-���CE����<������k�9���h���,������Q��������Q�]<(�=�����#8p���:w�����o��6����T�l
(U?�������������������	�V�Jeq]V����j�6�W����������yn��`��w�^��X�5��V���8�>�l�Fv����^��@PP�-[&���_X���d2��������u��y����jj�}hO�V��~���DQ�o���������Q��P�0Hv�.w��vW�hBe�����?�c|���
�#""""""""""""""""j�%���jS�K�-������aaax����a��:u
������6���'''c��I�����y��������s���FYYY�j������kW����������uk�t�MX�l���k��T� u:�y|���`amYYY�sT=��zH�6^^^���������q��=�:�W�^���]��wF��V�Z�4��S�|������g
����{��A�^�0p�@���k��u+�������Z�w�������q]o���S��X����{�9��#'N��C�^�����y{[6��j����;m:~������3��z���)\������@|��G6wY�������K�.��g""" �"���k���������%""��V;Tv{A�	���9�+�j����d0�h-��TZ]y��@!""""""""""""""""���zx�z����;��������g�}V�gz�u�q���8����7o�t�GM�>�J��~�	�:u�8f��X�`bcc����Q�F����BFFF���������4�noM��.LMEnn��s�B�Vk��AAAV�W{;D���k_��Y]��Uc|
?��C�1'N�����T�����#^kg�Kqt6������m�i40@�����������/���<��bg��T�����,]����w���������}���Gy�
B��P�t����d""j���V�����G���N�G�F�����g�>������������?p������������������P���\����:e�N[�=����j��J?�K�����H2����6�;�����&L@jj�d{tt4F��N�:!,,^^^���� �9���:�o�nWmu����	&X�z�����Xt��m�����4���9s��&������G��[oa��5�r������]�va��]�7of���W^y>>>s�=�d25�9���z}���X^
m:���H���;����J�fnnn6l���C��@���[����������;g�K�>�l�[���v�
7�u�N�:a���qff����������M,[���J�)i�����K��`��������C��]W�5o��Q����f�O���(B{
�;��QV�m��`H��jZ��!�����Q�������������������A)�M��Q�H?����Q~.�z]�z��������=Dn�>����7�[�n�u�����o���O>�������W^�t�����_~i�
G���&OOO<����?>����?���v����QZZ*�[VV�w�}��o���i�����]�v��o�mW=�yxx��xj������U{�
����1�l���3g�$�7q�D|��h��m��9�3kU�����,:N6v��%�<�&N�X�sFEE��^C���C�pww�t���Sh��rI�)������g_��/22R2^�j�y��:����������SIx�������Z�0��c�O��Q��@�	�
����*��>�^��m�^:���H9�g�V(�u�y��j����8;��9��T
��������7m�����t�N�����������k4����5��k�
���������E�P^^�����_��
p������L�>�������!�(��o�S=�M}���KX��0��L&rss`����'�KT����ow����=���k=����V+gff�}��N[�!T�����:�^��AgS*����p��)�6{C�z�^2�KWSj^�.�V�BzU�z����ADD-�V;Lv�^����d'W#O�	��n0d�d*����_X� av""""""""""""""""���
��{{�:���{�/T!^�Ol�����>xn�'N�4�d2���C�q���m���������RRR���f�|��6�JKK���� u�T*<K�,�����z�j(����u+��=+9&$$D�/99���
ROS��H;iV��T�����.��������?n����W?��8 ��9������P������;m��R�[���3��>�
}����322�:>33S2�wM��5���(�� "��C�@>����un1VX�&�������t�F���d�����v�Yg�s�i����/������m�������
��S�N6�q��y\�r���U�`��������={�8$$'{�1�{����{�J�_S�T:t�y\RR��6x=U����?_��+
���6mi
$���v_}~����>�f{n�s�����]�	�.F�%���9���AW����$�#G��u|��r?�K�.��;�����/������;���������d2��""jFT���tGa�I�}:�^�m{���R��P(�a2Y����txx����'r�t�/(A����u�����Z�����\y�n��Z���)2d���QVV����-[��������dff�H�z���-��Yc�\���vN,))��Xg�i��C���/�4����-��|��������w�}��
sH=^^^(**`�k�
�;�����}�������(+�2b�,_��<���/�p�B���)�����M�$����5R�P�k��`���~j�Z����3nnn�����[���[t�k������{ws���/b���?~��+��>�l7�|34
�z=����~�O�>m�-p����z��� �:��{�V���GDD���Z��������T!���A�Z-�mO�O��)��S>�_���������������������Z&��:@����s+|��k���)����w�a��z,Z���c_x����������$���9v���a������D��
		��m����/�`���6�S��	sf��	���o���-[RO��9))�!k4�>}�H��|��M�-]�����(�I����n'&&�������_|Qv���E����Fj�zm~�����	����ukL�6�<6�L��?���S��;W2~��g�����j���>�l^^^��~i��_~��c�.]*�1���
V5M�Q�h%�g4�����������n7�����z���/dh�������������������
����G�]��!x���?�C��j��6UO?�4A0�W�^�����x���k�v�Z��P*�8p�y�����+W�x��p��������u���j�����������\��
GXX�y|��!|���5g��~m���>����������w��}-����a��y���d�=��������9��S��8�[�n������k�.������C������>�-n��F�T������ZC?k���9��\)�J<����m�������^�q�~��E�v��9
^�C���?��\�p��c>��C���v�U��T����`�����l�����M��`������< w�}�I^����c���HKK���������%�:������5�����E���h�������vx\�f�E�|���������������B�!�O�c��u8�F#�i�����_/�9'KPne���*���{6X�=��;�g��*D�Y��h�����?�i���xO=�._�,�����G}?�0�}��6����J�,����odffJ�gggc������RRR :u�d�:
�c��1����0h� ,_��7o�o��&����^��>��^{
������������#77����c��-9r$�v��E�a�����d����b���8p �����{��������������	����BL�4	�'O��!������������}��_�~�v�����$�;���������}�v�k|�����hAAA���&�	��r��[g�-��������1k�,���ZvG���~Z�5?~<^x����K�^�t	�g����3!���I�:u*n��v��L�O��1x�`���������-��?~S�N�#�<Q��K��9r�$�����c������O�u�V��m��}�w���",�q�Ft��
���l�<55k����Q��������T*��w������m������;-Z������������g�FXX�O���g���u�}����m+	���o�x�	���RRR������'��l���{0n�8��J�_��U	Q�P�099�,��r�"
O[�d�B{������1>���JM"�K���~"""""""""""""""""WR�x���}���E����y<z�����aO���+q�����������x������@dgg#11�|�����Y#	��d��x���q��1�+W���U�
��� 11F��|��p��$$$���<������������c����sw����#G��������_ 55PVV���.D�N�������,$%%I�I�����_���$��<{�,�.]��K�B�T�m���j�pwwG^^.]�d�i�����>
�6l��I����DQ��M��i�&��jDDD   z�yyyHMM����x����+� ;;@e8�ZG�E�a���v����X�����������1c�|�It��J���������q����C�-�R���
0j�(����������b��e����V�5�NT��O����N����7�x#G�4_���1e�x{{#::
�������0��������O�>6��x@r��v��.""B����'���K��j�*���/b���P*����@`` �����U��m�S�N��i���Ns�077�|�


BHH���PPP����:}�����/��#G����Py�]�z5��Yc�;*''G6���O|��G�.�)v�#"�I�&��������+)�P��e�����f��[�B��s����)�������������������
��:#pz7�G��u�{�/�wC����Y��������_�~���(���K8t��$��������F*�
�7oFtt�d��dBBB<�.H�c�������/����1o����[���Z-~��G�n�Z�����O�F\\��=�B�7�|�f��{���F#�����"!!�"���~������v�����_ps��l18�<<����#99Y6���]���j�����l�W�Z���o��)}s���"?~G���F����N?C�MTT���g�sg2�p��E:tH6�4~�x���N����!C����?���,**B||<�9"	����FLL��k���[;vl��}��7�z�j�k��h4�WO�8�({��5
���h����S�N����8{����!B�����>�lJ��~�-z�!���G��n��6�������*�9�����E��E#rs�;�yju��v��*�]�@wo�9���Q���Y�������>�����<��$��
��������������Y������� �����/Ghh���R�������t��Uxx8:�'�x����A�a��mX�r%A���k���O����X�p!F��6m�������������#�����T*e����c����x��g��-..+V���1c���U���;���^BBBl�nnnX�r%�����k��=~�al����������s���{���[oEdd$|||�P4�G������8�|��VBBB��[oa������sr��W��mq��!�]���u�:O8�7o�/��'VI��C=�?�����:G�����N�>]��P�Iv��m���_����{��V��;���c�����x���,��������{�����������nG���������?b���pww�q�R������t�R\�p/����<g��M�Vc��u��u+�ju����O?����73�G�X��3��O�F�����S�N���3`������Q���k��(�BE��7���}aa��s��.�J*//��;-����� (���S�65�bNg/
v
���2���u���ux
&"r^���\��`""��u���ux
&j�9���
�����m���]��Q!�!V����:����d���{q��ydffB�V#**
���

j�5����g�\�p������@�v�0h� ���7�
A����?�Drr2
������H2�A���F�={��7�\����B�����0�������^GE�>}�O�Fvv6����V�������Ht��m����:MEFFv�����4C���g��4h���&]�����"##@hhh��^�u�/��%K�c�9*%%%a��}HOO��`���?:u��!C�Xt�kDQ��c��]���OBBB��kWt���I\{JJJp��\�|999(--���7�����S't����^U��:��+W��~$''C�����C��u�s���\�/�m��a��q�X�n����x��E{p""j�A�V;�W������uAE�4�w��
��hZ#�G�"	�zU������'""""""""""""""""�Jj7@��J��B������������1~�x����h�ZL�4�a�W*�����$��� 8e���u���2e���h����U��Z����7��t�111���qu)�������G7�9�ut���0�u�]�.����*?~<�������by��X�:t�/����r�����a��KK�QZz���XR�[A�CwC: �W��+D�KUY������o���/&O���������x��7� ??��%��h�C��k��A	����>��* ���V���0�GDDDDDDDDDDDDDDDDDDDDDD�l.���d����1p�@�x����i�F�Kj�p��{�9���c��yHOO�(�.���H�(����@yy9***x�j��A���*�/���@�	����Wv�1���s��i��������������������������\��=������@ee�����s'Z�n��zw�u�����:t:~���_��v�2�T� DQDhh(F���:���)))Avv6���P\\,	6+�Jxyy���AAA���nQ���PTt�b{n�~��� ���Y�����sa4�B��@oO��Z�9�N{DDDDDDDDDDDDDDDDDDDDDDDN��N{������;��K��(	�]�z+V����'�|�}��������d����l�2�x��		��Y��k�.��(�E�Tb��9HHH@lll��&"�Gnn.N�>�'N --
�H�F#


����'N�������uQ�M�V;Lv{EE>

O9�Kj�|h���`���C92�������������������������������1���'�|��_~�����$%%a��5X�f
 <<={�D������0������P*����(--�N�Cjj*RSS�����'O���3�����v���Y�L���^z	����|I��P^^���$����}laa!����C�R9������
5L&��>]����rAU���yC����Xl�O�O��W�������V~�,�������������������������pYh��f��������5k�j�*Ix�����d�������{�������S(�4i.\�^�\� ��������Cyy�:�������]�t����0UR*����n��>]�>DF>����M(��/X�3���Uh�q�e}����B��������������������������I��@�V��g���K���_�o��E�(��uU������y�����O !!�}�{D����8s�L�{��������())i��5wZ�0����GQQQ��j,i4�������P��n{���������������������������qEh�777�w�}������'1g��m������U��R�0~�x�_�x��w��CW�D�B������s0�
z^����g�6X�9���
���9�K�B{&������������u�%""""""""""""""""""""�[�x�$�@DD�W�
�U��[7����HNN�����l�2�?���vw�sssCLL}�Ql��	999��e���h4W�D��%%%9,XW^^���$���9���w� �}9�=N���Z�� �O�O`��^A�	K�*�������������������������qsu����z�����{�������#))	���(((@II	�F#<<<������`DDD **
]�t�Z�v�WADd)77999]#''AAAp�:M� ����,��t��_P5
�
��A(+���������z�x@)F�7]�/,A�C�DDDDDDDDDDDDDDDDDDDDDDD��$B{����#<<��e�[ZZ���ah�fZ�P��^I�E��i�h�8��*4�P��=�R*��K��Ez�9�%��ux�DDDDDDDDDDDDDDDDDDDDDDD(\]QKURR���B��UXX������Ti����k��4�P��ee�0��1>^�s���'""""""""""""""""""""""r����\$;;�Y���������Av_�n����d-��021���3N�Bo49�2"""""""""""""""""""""""���="")**r�z���N]�)
���n��������J�B-�O�O���+E�)*uXmDDDDDDDDDDDDDDDDDDDDDDDtC{DD. ���CtEEEE��k65Z�P�����(,<��j�A�F"��Zh�/
<������%��������������������������ch����F#�F���4�\�-����Ap�����sr5���P��z}:DQ�R���Cv������������������������������=""pU�;��j�Tz�����>�n�����������bTTb|=e�eh������������������������)�#"rA\��B��~m��X��y�Ga4�6����X�g0���z���Tj@ny�C�"""""""""""""""""""""""���� "r�R	�R��5���V;Tv�(�!7/���H)�P�d�����=k���x!��9�DD. ���;�9�����:�5%>�]�Rie��t��\�%k�������*�rw��_����1�GD�"���N]��!��J������ur5�4�P��CD�A�#�m��="""""""""""""""""""""""�ch���E�����zM�V+����<�'W#�V���D��!�+�;ZPQV1�GD�2������q�Z>>>���r�%�v��}:�>'VbI�� ���������wU�.�@���a�C{DD.��M�f�Ns��������>�n����%������t@/����8�."""""""""""""""""""""""���� 00��k"  ��k4G����r�AMN�FJ�	����W���Un�����_P����������������������������=""�k��=T*�C��R���}{�������^V����'W#����n//���X
������N{DDDDDDDDDDDDDDDDDDDDDDD������T*t��J��A��T*��K��;����N�����HY����Y�/,E�ItH]DDDDDDDDDDDDDDDDDDDDDDD��Q�����n��5X�N�R�[�n���nQ������#�O��������Jo�}���JM&�/�;�6""""""""""""""""""""""����="�F���={�D```�������={2����a�����htm��Z�=��*���T� ;'���auQ����A���OwuID-����%�{III6�������c���h��-<<<$�Z�x���&�-^�X���������]�\]507W@DD��T*DGG#((iii(,,�����
�����j����7-��L��F��P�3h4�(.��b��p�(B�P����Z��Jp_���C���������������������N�<�[o�����.����!++'O�������Q��m�b��A�j�
�^ff&:���/#//� ���������_���R1�GD�   %%%���Fqq1���`4�sA�(����� ""nn�����Ow�����"�b�N�������&���:������lh�hA���#"""""""""""""""""""�����q������R���Qq��9���!..��'P^^n���Ca��uu:YY�m��-[�������������O>�i���9'`2�����c��58|�p�sccc����c���uZ�*1�AD��yzz"<<@���d2�d2A�P //�m�i�d2!''�[�vv��� (�
�����t��.��:��5�epS�O��{ b|=�+���+���h��R��:������������������%�"PaD�MA\]���]�0j�(�x��EX�x��
j�����1�v�r]1d����K{���x�����K��j����(W�G�(L�>���y��������� j�>��3�_��F~�e����n�:��_�Bnn�M�EQD\\x����;X�~=����Z3))	��s8`��={�`��=���O���_"88����C{DDM� P*�P��*  *�J���&33������
����,j� T(*���`0dZ��������2�'��da)�{;�J"""""""""""""""""��
�0��A�/��@���T)���@�����?>�JD�H|������ �<�HD�\l������C�8u����^pp0Z�n
www���YtS=t���?��]�t�i�+W�`��QHJJ����M�i�F�)))�������cn��F����}�d�puDDT7
��Z���W\\���b'W�<i�������sb%�4�P��z�U@���n�������EDDDDDDDDDDDDDDDDd+cf.�l��0^��)�X��r#L9�0^�B���a8p���LD�����(����:�%&&����������#"r0//�?�J��w��������+�����'p��a��������1c�����l�|��()��y���g[�f�����\�r����G����C����o��=y�$�{��z}�-U���7z�h��[�T���~~~�j����;��]�:lM"����U+��������Ddd��+j~<<����=JK�,��t{r����ju(������a2�A�pGoO��[d1�(C{DDDDDDDDDDDDDDDD�BbY������o���%(?�c�T]�@po���5����K���usQ%DD�SHH����������?�y�,Y��A�����g�y�?�8Z�nmu^�������b��Qx��� �" %%��/���#G�`��-�m��/������n���3g��O>1o���O�x�b�����%�@ho��]��ka����={6�����6�=<<<������w����FDD
6U�/�v�\I�����Q�~���Z�=@�^�O�v���%��/d'F""""""""""""""""r
SA)�'����'=]1��GB��i��������<�����5�53.�����v��9l�I�&a���vuH}���U�V��}��'���6o�,w��s���u���z?��rrr�(b��-x���m���&�����W����5������e��e��9�K$"�Kpp��v���N��j��@�0��ee�(.����\�R�C�P��3�1����S���*+wXmDDDDDDDDDDDDDDDDDrL�(�K�w`��P����`*�7������^z�sU�"���O�>
���a��
�]3o�<�����+8u�T��$$$H��&M�������q��I�]�p��j	h���������<Al�g�|�(���/��v����~�	nnM��"�D��B�T�h4Z������
��A�E��X����7������F���$�}z}eh���|h�JpS����#""""""""""""""""��**;��[>�S/�F�J�zX4w>�)�d2��������q��Uh4DEE!66���
�N^^N�:������������F����`k�Gff&N�:��/"//�j�		���R�5�^���G�"))	0�L���Dpp0�����{wx{{���%%%��o�\����L(�J�k�����C\N�����"--��=0`�t���u�7��������!##�������C��U�V
�\�x'N�@ZZ����i������gsrr��_���+��t

����w�Z��p�8���4��6m�`�����W��4��011�O�FJJ
�������V���4�^�LGHHH��'���
�N�F�V�Z�K�.�������u���r���_8u��������v��a��h��!%%�FFFrss���g�����������u�����$A���t����1���H���wy��5��>\�Gc\\��������h��];���A�V���999HKK3��z�.]� 88������W�?�U�(b���x�����G9�k%"��B�V�Z�����
QZZ
T�|������7���X���� ��TU�zh�*DQDk�
aj�,��1�GDDDDDDDDDDDDDDDD�T~&��:�Ug�@��4���}nb4�j�*�Z�J�L�5J��'O��+��}�:�����
��o����kEEE������Y�j}��Z�l��%X�d���v����#GJ�����{���o���;,��T��G��3��w��M?6n��U�Va���5�S*����'&M��'�xZ����������
����9����={6�����9r$v��m�}���5��-Z����T�#T�����u�0c��g�>��3L�>]vnRR"##���z���l��/��>,{l�.]�|�r�z��6�5}�t|����qbb���dM��3fH��kj�^�L&�[��V����I�P`��x���m�Zjz����K��������8n����������s��p�Bl��eee��������1x�`�};w����?�X���z+�}�]��JS�^C�^�-[�������!�,�5J�c����,���U�=����fuHJJ������x��������/_�:���c����Y�0~�x����+V��[o�e�*_������/�S������>>��#�9sFv� ���/^|�E�v�mv�������z`3??���������6�U}.�	�O��j�k�.����6m������.�"n�����k8y�$
������8�����Gjj*������?c��ipww�(�EW�^�c�=�={����S����������o"""B��OE|��'��e�+_
""�jz���,'V�|i��d�����d���gP�Ce�����(���w��/(qX]DDDDDDDDDDDDDDDDDU3`J�����2����Y��5��N�!C�`�����=�2��q�F���;w��{���{}����+p���Z�S�.]��O?�~�����v�WWs��������{�����'Ob���5j233mZ�`0`����2eJ�A��������E�p���Z�c��)6l�n�j5�Tv|���p�
7���C6���O�nn�"��0\S��s�a��qV{p��Y�v�mx����X���\������������P�;p�n��6L�0���uZ�`0��;��< ��������Ol��Q6lT��G��M�6I�/Y�c���
��������T5��p��a�����a��{@�5s���5j�x�	TT8�Mj���"22+V��1�T^���L�8���6�q��4.�
�����_�~��!>>����������3�y���=���y��a�~������P\\\��yl)�[\�rE2��cr�����]P�z=`����J�>�T��a��a��eA���'�y��9s���C�n��T*e��j��0a6l��S�Na������\L�6
�W�6����#�y�$$$��G���AE���+��B������^^^�����`2��\Q�h%�g2�"/���0q��z�i�>�+��_Xb�;�U�%���x��l�������n�x�Z�o�����t�*((������g����^�������N�:a�������kg1���3����9W_ru�K�.��^���o��w�^�=���43g����]�bbb0h� t����7��&33#F����-��m�}��E���-��\�z#G����{�^����?����y����n���_�~��������wf��JLL��!C,B2
�QQQ����l���[�b��Q����{����K^�k�[LL�M������)S��5
�t�"������������
X�l/^l~^���={�D������-9�����<y2���������]���i����c��A����E�0X�z5~�a�����3���GAQQ�d�R�Ddd$����=z��M^^n��F;v��-,,���C����V�%����q�m�����7,����0j�($&&J��������;w��0��O?a�������y�J���HMM�l������)S�H:=~��w?r���OI�2$$&L��bj�����g���(�������[��O��":t��m��a��)*�xO?�4~��w�<�J���Wc���E�����q��������Xpp�����r���9��f���'��|d��t��\�uJ�*U��>sh�G��^~������BDDDDDDDDDDDDDDDD�PL�z��%NYK�-������[��s�J�yO<��������C�!11�.]����T�{�1��R���2e
����"998w�������dgg����G�6m��]�z�f��z�;v`��x��7$�x��>��^�z�����3f����~���4�t:�9s@||<�������e������|����1��_�C���/�4�����`�$%%!##G�����q��)dff������q#|�Axxx�xn���i��I���Z��������t\�|�F||<����A�kJJJp�=� ''���+W�4�nU��������������?������������p��):t��s':w�,9����j��`U�s�����;w�M����
�s�=HII1osss����q��e\�x�BRR.\���3gJ�?r�}�Q�����_��W_����m���_��G�"++���GXX��s���(++C�6m�n�:������3��}��m7�/))���?�}����^������rrrp��q����5k$a�3g���>��kl
�k�9s����G~~>�\���'Ob���8q�rssq��q<����FO�}��l@��g�����$����K��������������o�-��u��!++�.]B\\N�8���L������?�\�m1g��;wnnnx��'p��������C8y�$rrr��o@�R��IMM��9����1u�TI=66?��3�������g�B�����>B����s�������Z=�#��t��u�$
[�t���������$�r�^��'�C�r�������[��������{+o��j��Z_~�%v�������:�
��vd�R��?�G���K�`2�����"!!�"��;�`��-���;w�D��}��>��"99Y��^ff&�Z��j>
7�BV��}:����]PU%�&����\c0T��z�x@@��b|A1�<�2{������������������M"D���U$[���^J�"]��E�� (�kJ��8��>��<���q���[�����|��}����FRR�]k�?>���7��&00�<��N���c��h?��#��9��]�Zs��7�E����(�>[��1���*|}}k��y��a��i�nD�1-Zd�9���>��#��1��:�[��]w�����o����s�������s�y<p�@�������B����C�c�<���x���T�:�.]j:��Lt@@���qKp��a���X�v�$@T���9��'z�����4��+W�e��~���Z����z���]���={���q��A�����7o��7�l1�C�����1`�IW������M��I�l�;##p��wc��
��0h�������N�:��?���������n��;��gO��M�p��q�L&�u�]��a�$�T��}�QxxxH~g?��<���6}}MEc|
��}2��w�zm={���5kp�w��[o5��l�2�q��������V
����C%�fks��)���]w��/������5������31s�L9r���5�.]�Z����/�����s��AHH����n�:������k***0m�4I`o��%x��ei���`��Y�0aF�ew}��x���cq�#��T)==o���d����m:�������O�={=z���w���#G",,F�������_�u�V�����
o��6������rZ�F�{��7��GFF6HS�Z����?�������?X\�U*�q,X��|1��g��o�3���qssC`` ���,�����`0X���l������
O��Lww�#5�P���n0dB��rS�/
�[�������@'Qs&��Q�;��e8�)E���K�v�	��k�������.,�?��l`��Y�f!..k���k�n���5?  ������sg��������+�:���m���?���*--�W_}e�������{{{���.00������k�_~���7�W(x���p��a8p����b��%�.�d�~�����>�1d��U+������t[�n�wh���F�Ep��W_�
�U5k�,=zT�9m���6��������.���J��7�|c6���n��3�u�F�������#>��s��&x����l�2$$T�+�?���ts��9h��all�]_���c1w�\����*��Y~7�W_}�����`��a�����P(l:�����e�d{U�w�}x��w����L9r�j���o���S�����gc����������{�6��W�\i�w�J�(b���(((0o���?n����};^y��\����0��a6l� {�B���q���K/��Y=�v�p���d;v� @��C���o�R�4��6o�,;��OE\�x��j "jh5�[�\�������GDn�_N��*�F�4�h��P�}���);'���au�s���a��M��F���%Kl:��W_��������0`�y��_�{��&c����Mj��j�"�Bas��6�����]�.^�����5J�,0�����m�����u��AE���u���+,]�����5S�L���=���l�m�6\�|�<�����O?m�����
<=�?��w�^�={�����yxxx�^l5w�}7z��Y���n��b����%�������x��l���kX=���{Hzz:����X�P��O?m�k|u����N�*�t������������5���C����y3�F��<G��i	���,[�����d��5k���e�9����h�"8p��u��	������zj���k�����G�N�������p�(������������56���V�Q���)y�$���G4�v��t�}N��:w� ��������+��S��(cKi""""""""""""""""�fa���0����my�j����>
%22��yc��o���yMuV�\UPP��~��A��������M�f��c���'���� u�T~~~7n�Ms�Z-������a9W��{�d������N��Zt����?m:V�TZ��u��w�4�{���� �<y�M����C2NII���&����U��c�!����$�6~�xDGG;l���'�
���{K���1999���3�o���U�M7�d����H�5w�}�*�����$�y���mM���1c��������u��?���c�b��A8w��]k�u�:�W�"m�?lU�bc�"%������������!	�`��^YY����\Q�"��n{9�=.E
�juk�}����|h�Lq�H���������������������y�>�#G���x{�W����w�}��wz�����[���� X|���3WRR"���hIIIX�b���nt���Z��Z�����C����V�9v�X��������+���W�:EQ��}��L��n����]����B``�ylOg4���O��GU}��1<�y��A�x���v?f�����6��sg�����Vu�vz���T�l
(U?�������������������	�V�Jeq]V����j�6�W����������yn����]c���+y���5��@��%��R�u��{���J����XI�D[�>}={���u�PQQ��ga��u�t�JKKQTT��g�b��������<x���OR�:�WRR"7�5''��yM�W��]����

� ��233�\M�����n0���$���\����n�����������b��EDDDDDDDDDDDDDDDDD���(}��z���T��d���l���@XX�z�)l���N�Bff&�z��P��'''c��I�����y��������s���FYYY�j������kW����������uk�t�MX�l���k��T� u:�y|���`amYYY�sT=��ZSk�����;3�jMrr�d��gO������dlk������U�V6����68��8�c���!5��p��=�����^{
[�nEbb"rss����8��q��E��.�7{�s��z}����v�=������'J�!w/q�}��;}�4&N�(�U���?���Ex�&YYY������n��h�"������Bdd$4
�����sg<��c8y�$�O�n�_XX��n��Y�:h���k���ON�:�`�������TOuWU�V�FBD���T*��h������r'W������N�Gv�3X�UT��h,��B@O+���Kd�Q�R=�P���r����E������>��h����C���E\\z�����7���GM�>�J��~�	�:u�8f��X�`bcc����Q�F����BFFF��UmN�PC���L�����z���5�P(��j�:����r����"���������5�i����~�#F���u^������4{���r�k��{�#��-Ybb"n��&��`tt4�m�???����s�����������x�b�M����k����#������x�b��&�����M�6��EQ�?����~J�������o!���-4T>�H/���v%"r���`�w1E���5^��f*�|}{�����>]�>�k���������W������8�o�U�XC{DDDDDDDDDDDDDDDD���Q�}D��':H����������	U�vN[O��F��u�)**���mVQ�sOM���0a����J�GGGc�����������������:�o�nWmu����	&X�z�����Xt��m�����4���9s��&������G��[oa��5�r������]�va��]�7of���W^y>>>s�=�d25�9���z}�K#������B��S�\{]��i���x��G%a37776DDD�����h,���;�)5V����v��
�������Tiii������f���];���oh���]���������c�B��_~��c�J%^y�6������/�z�-����UGK��C{�B�0_�����r�J<��s�:oAA^z�%�`�
2Dvnff&�����=#""��6�3������]��}233Rc:�j���
�����T�����ts����**,������+
1V:��]b@A��n��Q�#(��{�V������=E�.�z]�z����������M�����p��y��u��X�nn���Z����O���>^y�I����h|���0`@���l������?����c��}���?�k�.<x�����eeex��w�}�v���������kW����v�S���G��������^���X^����3g�$�7q�D|��h��m��9�3kU�����,:N6v��%�<�&N�X�sFEE��^C�[���l�x���t��y[pp0~��7����}�?������qLL���l>~��!4�U\\�#G�`���v��R5��^�V����w�v.D�N�p������z��'O���W%�����Kv~||�d]�u���I[����������X��6II�-����/8���.����^Q�|hb|������j�3ADDDDDDDDDDDDDDDD
O���KY�[/��ik56����qvv�]�W
��������7m�d�C�:���������6��h�����8���u*
���"66�-Byy9>�_�6l���s0}�t���/�sT����o��N�47�iZP��Zs`��L&���"  ����_O�9������Kr��w���oS�.g�?�Z�d�������;m��P�^��{IC�[���|�7g��5o�������q�
7�������qdd�]�_k|V��C��d������g�5.���0e�������v�����<x0v��)����o_�1B��k���R��
��WBD�\�Z���/33���4?~���Tz�����8�������z�U��	�w����GZ�D�c)|4��XVWB�>���U��:u���O�8a�<���C����{������������RRR���f�|��6�JKK-v�+�J���c��%8�<V�^
���c�[�n�<�!!!��x����n9-�F#�����&YY�76������:�����#���$��3g���w�,>>|�ik7��!��a9g��}�%)..���q��Q�6oool���z���y�w�ts����J����Fc��i�}h���n�m��f�	����r,[������O>��[�"##�����
?~~�!F��!C�����6�
�|����&�	�6m�������+$"r�Zm��I���������5#
�
�!n�n����N�	��.�e(+�A�����e�5�(�oB����>�����d�{�n���u~�g�:u�d������KK���H��M�����s��=	�	���{��{�d���{%c�J��C���%%%8x�`��S��k�y�]���W2�{����a���z��?�������g3���\������=$66V2n���F�%���9������`0`��I����3���7o��u600P2��F���7[M���R�����~�=zH�{�("''k���-���6m����!!!G@@4
�����{{���(���z�(B�P����G�>}d���y3RSS��v��:tp��MDT_�����M&��M-�O0Tv{A�	���;��Jju0���
�t@��|h�hAI���""""""""""""""""j����P��9t
E�����Ol��"�V�e��t:������9�P�Y���2�k\�f��s���K2.))��Xg�i���<�����s��7K���������:���B�o���6����(+�2b����/���Dnn.6m�$��f8TWu�6|���v�U�{��1c$���n��������]-,,��w7�/^���[�����l�6w�2e
~��7�6�J��7b����>���%���8�������HMM�l��c1Uj�=�V�?��}��������}dff"55���0�L��U�Q�Tx���1s�L���T*���k���+W:�K&"j���-i����tr5��Vke�	����Z�5
�
j���������i/�����W(""""""""""""""""�kT]�j��'������-���?����X��c��E6��/���8`S����cv���Z�d���h��!!!���]|~��l����u��z8!  �b���3���o�����e�C���:'%%9d��R�a�7�|c�qK�.Eii�#Jjn��&��������x���l:��_���bcc��s���Z��^�_|�E�:k����n���M3�M&����d2�U����;W2~��g����%U�rl�L&�O�����M�P��/��-��� k6j��<���6_����^��;t�`��5��P�����x�b�T*���-��{}������1k������[0o�<��M7���/����(
�-h����J����g$��P�}:���3k4!�������VB{@e�="""""""""""""""""G����?P)��*%��GBpwP ��y���!�y�z�j�_���c��]��k����R���������Z�c\�p��~;���{s���x{{�����;rssm:6<<aaa���C����_�xL\\���~�j�����{�n�����Z��}��������y����&�	��s��[9rS�N�qN�n���gggc��]v���O�<�=}�t��a�o�Q����o��5��v�Z��
��R���O?-�6�|����5����Z�m������Q�1d����>��j<��?�o�a�ZU�m@e��,�������i���`0�t����]�����$�����1~�x����|���r|���X�|��5q��Y�gz���%�	���k�b��)
�������`�����~�����X�n�d�C=�`��M&�T���p�B\�p/��Z�n-��W��7?�������G5DD�a-�YYYN��y�V����4�'$,+���T��
���s��#""""""""""""""""�R�h�>0��:����>0

M���<x0������(���SO=���/K�&%%��G��?vuOy��%�����7233%�����r�J���)))�:u�y�B�1c���yyy4h�/_���7���~�|T�U����k���������T��?���������Fc���e��9]�v��E���~IW�kJKK�q�F8������z�B���e���s�a��	�qaa!&M����'��?��
���z�����W_E��}��_�Z��Uonr�w`�����q#�o�.y�/]�T��-((HB0�L���[�n�:�n�'O������Y�fAEt�����6*O?��$pk00~�x���HOO���t�f����3g�����S����owZ���t���6�1|�pl����k����1u�T<��#E]�t�k��#GJB���9&O��O?�[�n�\����gq|��]-��7nD�n��������SSS�v�Z�5
����9h�(J��}�������������c��E8���q����1{�l���a���8{���\G��M��[�ma�����nun�kjUK�,�| �v��w�]�vV�gkM�-]�����/++��7��9s��v�<~�8���^<��c��!!!x��gj\�,5��i��-^z�%,]�g����p��I��� 77�~~~@�v�0`�8P�����������
-�eee!<<
E��p7Z�P��[�G�^%%����pzM������<=������2�����GDDDDDDDDDDDDDDDDN���@=,�g�`J�{�E�T]������+W���#���P�{��w��{�!22�������<�����5k�Hb5�1c��};v�����+�j�*DGG���999HLL��h4�`�\�r			6=�>�,~��Gsp�����?����;wb��������o|��HMMP�����?���S�N���BVV���$��w�y���GRR��u�={K�.���K�T*��m[h�Z���#//�.]��4����O?���9
6l��I�&������M�6a��MP�����@@@�z=������*y�m�����W^Avv6��p���J�-�����:C[�b~�����1c�<�������J%RSS%!��������7�T["�R�
6`��QHIIP�A��W_��e�	�Vk����O�>x����\55Go��F�i�&���c��)���Ftt4
RSS���a>������G�>}l^'88<���:{��Y]DD����O<�K�.a��U�m/^�����T*���@���7��*�:u��M�p��w�C�����{VPPBBB������dgg���p�}���^���c��4w�����}����>��jG��;wZl���o��	�~O�������{����w��h��o��7�|aaa

��h�����T������7������Z�&��A��kWt�����5j�����=���N��� T�� -��t{]�S���Ph`2�-��C{>��>��];���(�P
�3J%"""""""""""""""�Lpw�{�p���R6��b��
��[T�����i�������1~�x>|��]E\�t��+���/6o�lW�=�J���7��o���m�n2���������_��3��zF����~s���x��6Z�?��#��/	TTT�����
�x�
��5����k���F#���%������k
����a���7o�y�I'*��`�KRU����q�V��w�}������[bc�o���'O�ts***����-��=���lP�������}�p���������&�	/^���e�?~<���k�6�A2�1f��%����U����GLL��k���[�|�2v��Q�z�|�Mt��s���\s�F��}�15j:�{���������
kU%B�����>H�3m�4��j��5999�}W�\��+W���cG|���0`���l��Z����R�����q�X��k���Mv�.w����$4�n{Ce��_O���F�[�������������������E���(����C+(�U�g�TJ(����
�������
�����~,_�����)�J�u�]8~���;�����q��!<���h4V�
4��m���+!��M��|�I�={.������Mxzz�t���9r����g�A���cq��<���v��+V`��1����u~����K/!!!��i
777�\�			x���\�1�����?������1p���8w��{�=�z��������������q���o����AHH�z�-l��~~~N���j��-:��k��[7�� �����b������_����C��?��������h4��?����O��>Tv���m~��W���@�����j�R��:�c�=��/����B���k�����{������]�xG���������?b���pww�q�R������t�R\�p/����<g��~����={K�,Axxx���v��w�y������Pa�$�U�8Q�p��it���<>u�T�p;SAA�����Q�����\i����w	��W�^���prE�����#9���J�7���B����:��t������g�`�q�	T���f�v�74�	URc��0���LD�:����DD���0���L�24�sZ�nf
77�?��h�(F`�(uzQ%����{���������Z�FTTbcc� ka��=�p��������v��a��A6=�,:���'���QXX///DFFb��!6�jc4q��Y�����r�

T�F�����woDFF�{Qq��i�>}�������Z����"##��kW�i����4��{7���P\\�V��={b��AV��t]JJ
<���   ���
�{A�-^�K�,1�������}��!==��������OO�f�$�"�;��g�"++�|?			A��]��{�&q�)))��p��e���������

B�N���K�BxU9�>H�����#G� ##������h��
Pk0��p���������HVpp���^VVV��O��D�&�3�PXx~~�o�l����X���hT~������s��0�GDDDDDDDDDDDDDDDD.%���toJ
�^c7���������v����j1i�$��_�T�{�����#���u����[c��)�.��
�s��R���oT�j#bbb��R�����G�n�s:�>H����W���5�^�DD��������AVVL&��+j���@���R�����j*��!V������w�/(qHMDDDDDDDDDDDDDDDDDDDDDDD-C{DD-���������sn1��B�F@��}:���J5T*��>sh�W>�w���F8������������������������������+W������|�����\�l�MD�"99Y��^ff&�Z���L099�-�CEE!��|�^�F��r���k��>��]�"p����ZQs��B{��������m�6;vEEE
r^APQQ� �""j�������,�}yyy(++����*k���a��E����h�j��+�����n0dA+��S
o�E2]���#""""""""""""""""""""""�3���UII	�z�)DDD��_���{QXXQ����%��/33���4^^�P���������j*i4�V�a0dA!���);#���q�5sM"�����~��a������0��Ah�"����������b�A�����sQh��=�������b|�#""""""""""""""""""""""jh�>�WQQ��o����������A��m�`0�����5Z�0����I(-Mur5� (���w��-���/CvY��j#""""""""""""""""""""""j��\]@m>��C���K:����F�	&`���������R�w"""��� �����333��������+����n{aa��XM%�:T60x-��������
Kpc���j#""""""""""""""""""""""j�}h��7�0���Kf���e��!  ���5Y*�
��t�t:�������=��]PTt�b�.w�KB{M�����TT#D��P�
��r�9���5���c����.����@��j������d��=A0�||�����Spp��vQ�����j��v��v�nD���j�&��>��* ��Sv|A�Cj"""""""""""""""""""""""j�uh�����qdd$�.]��j���???��������4w7%�Y�UT������������&�-O�O��������g������������������������uh/++��� ���;���������A�v�+--EQQ��+j����A��B���8��JM����B{�r#��e��������������������������j���k��k�~�t���r����V�ZY������J��R���t�}N���F"�]��
Q4���'+���8�0""""""""""""""""""""""�f�Q�����$coooUBD�<��j��������AEE�sj��������������j�|�=Q,GYY|�������ah������������������������~�:�
��@����,���Y
��n2������j�>�6Vv�(�#//���ju0�����t@����~����������������������������C{�
�J�2�O�<��j���'������L'W��y{w�J(�/G����
����,WX��,*A�ItXmDDDDDDDDDDDDDDDDDDDDDDD�Q�������[o�(�E[�l�(2<@D��
���d������5m��@�v��>�n��������n��i������$�lq���"""""""""""""""""""""""j�uh^|�E(�J����/���>suIDD�Np�|'6���rb%��V;Tv{I�sP��4�P��ee90
����B��_P����������������������������F�������o������N�rqUDD����|||d�eee�d29���Mk����n{�B{`0\�J!�����~����������������������������C{��K/��{��(�(((��Q��e�W�ED��X��g4����\M��V���W��>�n�������P�������_O��G�#""""""""""""""""""""""�K���_|����C������n��������iii�.�����R��������j�>�6Vv�.�/��s;
�`���^����%���=
+���������������������������qsu������U*���!�"v�����w4
�Z-T*U��/^�w�DDM�B�@PP222,�@��C������I����?��^^�Ca���twj=M(JJ.Yl���!���N{"���%���
�������������������������F�KJJ� E� ��_�vMii)�\�R�u������
�
��������\Q��?��Q,�����sIhO��T���|Dh���D�LW���������������������������l�pu���	�� DDT���^^^�����$ai��R�	�>��t�=N��hZ[����C���m�Xa���"""""""""""""""""""""""jv�DhOE�~�u�������������j�6�6Vv{^���N�E�P��=Pv�^��c%�w���="""""""""""""""""""""""[�����<��C�.���E	Drr2L&�����,h�ZT�4i�Cq����E�yy�8���h4�(+���~-��+�e1�P�tCB���������������������������9h����>���%�(nnn�j������������2��3�e�nP�P^n��P������Z
���v�!&Sz��w��c%m��;Qm�.������[[������J�6AP  `��>�n���4�+{L02���p�|0/���q�5#��oooh4�}���E��5]��a����`0d:�w�@�Jv��������w��="""""""""""""""""""""""�0�GDDA@pp��>�����'W�ti���@����J*;�Y����W���X	�+,��aM""""""""""""""""�f-))	� �?�O�����Z����K~����l>V�����������m[xxxH��x�b��M�[�x���C-W���]�v��$"j`n�.����V�Z�����]�233���������
<=�PRr�b�N���w8��P��^����_�������&\(1�/��DDDDDDDDDDDDDDDDDDD�\'O��������dW�BD�����#!!�O�FFF
������@�����w�B��{�:t���CNN�F#|||��]��c���.�Ich���d�T*@��Y���t(//�J�rAeM�V;L>����(:��R4�P����(BwO(�(�T/����=""""""""""""""""""�F ''���Czz��K!"j6����b����w/JKK������������~���v��n�:��1��u�1�^�O�8��_��=JJJ��

���c���Ob���u^��bh�T�E����p��9������m�������k]�xqqqHMMEYY��sg2M��A���D�l�����=Q�����P�Ii�����_��ee�(*N��wg���V�X���_��wGt����"�?0�cj����AE�F�b+�J��165.�v���Q���E�a����+����;V� 9����%����H<��c����j�y{C?7M��L�>���y��������� j�F����|L~~>V�^��?����
������f5�?>�y��L�Z�ggg������������{��_}��d[DD����>WVV�,Y�u�����XvN��}���/���o�K�f?��^z�%=zTv���7�O��E�!((���4����U���������2�}���		i�X4�!n�
�}:�^������������|�}z}:��;����lh/����(�GII	���QTT���b�F�>�R	///x{{#((���.����q���/��"..��+�Qyy����F�Ahh(���P\\�.H��/++���s������W;�d���[n��={,�"$$^^^���GRR��l^\�KII��n�\G�[������,{u�k�.�}������q��#G0i�$<����������n�:����?�~���������_�o�����k�y~MD�$������j����EEE���qAeM���7�|c���b�N��3�Z�F��"����P��;�}=�����g�J�7��Q*^#����HKKCaa��9F�(((@ZZ|||��M8�R""�Y�n��[g����D\�z�<�<y2{DD
(22=�������C�R������������$''���Y�]�t�O<a�zs���M7�d�|{�.//�w�!	�yzz��g��=���n��I�WTT�������_�a�����\�k���Eg&APQa��Hn�#X[�1������>� ���w/&L���Ri'%DFF"77�/_��S���_��o���{b2�0u�Tl��Y�]�T"<<~~~HLLD~���HVV����~�������k"jZ�j%�*��1�g�v�lh///F�J�Z�(��hBQT�`�]���(��#�Nd"p��}��]"5s���HJJBN���K����			D���%Q��������-���n���b���V3&����1q�D�7�]F��_�����Vk��]�v��7�X��k�|�r����q�n��e�DDD��wssC�^���W/��7�����9sY�Q->������n����r�
��������\L�:Un����?��N��G�"11III�={�������V��y��_�"���#� %%�.]B||<t:���{I����L�2E|ki_Qc�V����/�/''G�%���a��M&��;��&Tv�(���,7xi�e��^|a�#K#"""""""""""""""����'N��S`�����8q%%|���Z���<�����5�5��������w�^�t�M65�
�?� ���������sd�vKHH��/�l�o�;w������u���� �{�:��)��k��]P(X�hQ������#--�<����_���o�]�z�m�|�^y���K�.�)%���cq�k�����m��1oS(���;��_�}�������x��7[��D���n7�L������������Q���uj-ju+J�}z}:���^V��-�pQ����3(//o����������Q����%���L<Qc�����'�}\�6m��CI�m�����j�����`0�W�^�V�Z������U����)t�s���R��9��:<������������w�}W����?���[�`�m��?������7�x�"�V��+PXXh>����:?,,k�����\�j�z�)����������J�������L��>�N����_-�����#�_K�7���`0\��������'b|=�W^�����bg�HDDDDDDDDDDDDDDDD�Pyy9��;�����5�8{�,z��	�J���n.L&���/�?W�^�F�ATTbcc�y���<�:u
			���EYY������������233q��)\�xyyy����V�EHH����z�q��U=zIII(((��d���'�������������/))��}�p��dffB�T"88]�vE�>}�r���<xiii������K��������� ..���7�>:�!���/���HKKC^^���0m�4����t|NN���/\�r:�AAA0`z��]��.\�����A��M�9aaa�������&&&����HIIA~~>�����j�A�����			8q���������h��U+t���z����{��_^^�����N�B^^|}}��];�1��������������@nn.��������:�>�����b��5�qJJ���JOO��?�l���&LpaE-�KB{�}��C�6W/��".^���/������\_}�����0��1c��x� X�h�d���~��_~���&���{�x��Z�0f����b��=���B|��7x��G[��D��(
!==�b_QQJJJ��)������
��AYY6����V�Fj5�1V:�%��!��*���������������������JJJj�{����#))	���9Se4�j�*�Z�
iii��J%&O��+V�}��uZ#>>_}��o������&�����O?�Y�f������Z{>s��%X�d���v����#GJ�����{���o���;���;��|���`��UQR�%�
w-5�LM���i�-��,�\K���Es���Y�eZjb���Z.�n��3������|8��Af�����x��<�����3p����|�r�k?��c�:u*�{�9��Xw���-[�������c�n'����ys2���*�J�E�?r�,X�}��	����I�&a��i���6��������&�(���9s�`����ke��&�m���7n����7�`�����&&&"""��~����~�z@ll,�}�]��t7n��/���-�k�����a�����`��,�g2n�8�������^���������������H�R�k�3g�����w�6n��/��qqq&���ooL3�3���1{�ll��EEE&����������cG�����3g�����M�$	�/�������u:��p5
v��������CJ��}���d2���3f�09��U�}^Z����������X������d�|����u����<==��OL�8����*�Z�����>��e��V�M�e2�
���W*���_}�V�^��/�n#�H��uk��5�
�j���:��I��������
PRRbl�=���<|r�}���U�mMt��I,[���^�|�eo��]�~��,���GDDD !!��������^�����HKK3�###+�8���~����/�&����D�����E���{O��?l&Je�cj�Q��Z���A(���o�_\��N�A���$��9��c�����������������������DFF�M����@```�U����j5���'�s�N���-[�g����/�&3����/��k�Y���70e��Z�
��oG�
�Z���M���K�Z��?����c�b�������\��V�Q�Fa��m�������xt��	�{�.w���|�7[�l�p�*�
���>��Y�;v�m������&��N��I�~�m,Y���m.]��A�a����5k��"���;w0h� �9s����z=�?�A��_�~��ys����h�Z<�������+2�o��Q�F�����6������6o����z��?��\���`��;����#**��q:3g;�]�t����-�]��!66���x��W�l�2�����U���[o	
�����_~�����h�9w����O>��g���F��a������?���h_p��	�5��Ca��`��S�0x�`8��=<==��c����__���#hWe��s�NA�G����$utd^qq1^x�c������'�������p��AA_��}-�+�HLN��Kd�U����O������#h�����������D������������^o���w��pw��Z}���(���i���-wE���3gr
l�PbU���:�.77}��5I��H$�_�>��i#H �������q��%���h4&}������B�v���U+��[�d��/"&&*����*K,N4n��X��V-�{�>��={���r��	D����:�i��

�:~�J�n���&���S�[�F��-MVSRR��{w>l���j����������iS�i�F�g;{��JT����t���$aO*�"22m�����{�n������V�9v�X�q�����X��#G�`�����B�@���E�{qq1F���W�-Z��s���|}}��ys�l����NJJ
�j�������P��\�vm4k�:t�c�=___�m�/_�_|��^E�x�
���K&	{2�h��-{��J������B���	{aaah��
�5k�\.�>==�
BNN�E����_��G��=777�u��G5I����_��gO��Wi��:����Q�F���N����Wq��Q;vW�\Annn����t�s���7n�^��-[�`��Ah������T*��qc<�����y��BU�����~��������?����w����/""���������]^�v��N�:Y�N����-�Z_�33��������d�\�=u��O��d���4�dH$�2Sm/>�I{DDDDDDDDDDDDDDDDd����������((��-��MT/�H$x��W�������<y			�q�&M�����<y��k��r�1�~�-���������'N�����q��M�������B�����RRR0q�D����w/�����?�X������8&���E��y{{c��q��u+����Z��/����������wq��m,Z�~~~�y.\�����='O�����m��1���HMM��3gp��1�?*�
)))��e��ww�r����1r�H��3((K�,Arr2n���S�N!>>����D��


0j�(�J�K�.5���7o^�13fL�1�T�������Gll,�j5��?��'O"55��}�Q���_�JJ��M�&�6m�E?����5
7o�4����`����u��_���'O"11��]��	�O�>��_~�����w����6m�`��=��v��������c3����G����k����������/���={P�^=���9s&�9�w�}��m[��������s����+V��.^���+WZ��g=�������S���";;w���?���c������Fff&��;��_~2��8��o�1[����7����q��s�w�}'���>��}���/22���GZZn�����8����P�T�y�&��Y#8[b����������W_}��]����q��I���?�����WWW����oc������x��gI�111�������m�n_�t	j��W�FHH�q���8����f�o����������[}����z?.���?5j���;�S�N������Z�l�i��!))��}^�xQ���N�:puu��3g��E�1���+�_��F���L�������o1r�H4m������������@�b/^�</^lU2���O?i���U��n_��T�b���D���Js���D���J%�@KS�T=��a���;wL?�k�)�/�/��v�C"�@������&cM2 �����>}#>����j�DDDDDDDDDDDDDDDD�X�Z��a�����u���T��i� ��~_�����z�jc["���o�����M�������+��uk������-��_?�3�����K/��g�y}��1&����/^�'�w��`R�'22�8f�q��a������)w���0���;9r����5k0g�(�J�ye+��^����3�NHH�
�a����O>�^�7���%K��_������;D��T*E����w�^L�2_~�%�{I���7I:i��������V�������c�b����"��{�{��8x� Z�li��y������~��K�Ln��-k���E?��>�'N�0�����}�v<��&�>��#X�f
��k'�j�y�f�9C��(���T�����i�&��4t����}$&&"**
���$���{��}�w�^4o��x���m��;�^�a��a��M�d'��9���_�����=���_���^���U�x���+t�����T6����c��x���0p�@c|�-�SO=e2�V�Z�����{EJ������M�d�
��7�T���n���0a&L����O�TA5����������E��<==1u�T���
������|`������#G�$���7�f��������'������������+���/"::�d�-�����>T`��O>i�~����z=��;�s��a��e�0a>�����]�&h���`���x���QTTT��+W�`��������+�X�BH�I{NH����^0�	bbb�}���._�,h��/O�������h�P(������/T�Zec7�_^�3��d4�UZNN�������;B"��`0M|T��-i�r�I{��f*�e��������� """"""""""""""""���jq��YG�a7�����8�C��-~�g�}��`l���+�	{�M�8qqqX�v�Uk5m�������������G5���~�z|��GV��Z����	��5k�IP�������V"�r���{///�*��+((�Z�ja��]f���J�X�lN�:������[�y��	�����i���W��d�Y�f	*���������N�3I�\�p�h�^i'N��3g���.]jq�p/�v��
�	{�puu��?�h�lVZ�F�0n�8c�:�W�^E�
�a��	M����c��E�����;���d�%���3����^C�>}0m�4|���U3��]U.\���bc�K�.��y3�R�E����,Z���*m�=����c�J������&�n�����7�'M����gWKXX~��'�l��x�^�t�I"$`����;z�(>��A�{���{�TII	V�\�#G�`��=�����L�O?��1W)  �>�,:v�___��� 66?����B�^�������u�b��A6y]5�eg
���?������
�W������T*A�N�:V�		|P�������������V�����7.��������]y��������7|���������B!^�U����8-��?��LN��1"""""""""""""""""r���,l����V(�7o�Es.\777[�f��aC�k���>z������^�z	n�//�����R������o�V����s�V��w�L&��3����<����J�2g���0������t=G�?~��K��1B�>s���B���={p��-c;<<S�L�h��I(���K�,^{���U�2g���h�\�����J�O�^a�D"1�o]�N����I����$''��4��R)��[We������,�f��3����c�-[f����~���1=��c������C�3-\b���}�x}Q�T9r��x�m�����U�i��%�{�=���������CQQRRR�w�^���[�������0p�@�������I{����������������c��Q���?���~��N�2)Z5~�xdffZ������NBB�{�=c{��x��G�d��Kn���ZC"�������f�)����au�a������	��Z*�
iiiV�)[�4//999U��*{���BB��P(��hL�U*|}}�$��&��l���?D23�#++R����z��?���n@�h�H�+nh�M�O�g����'Q���0���LD�8<9��DD���0���L�p��{���q��1h�Zc{��'y������_l��DDD\8sbL��������8KW��������Z%�hv��e����#G��j~�^� �J��:d��A�������?n��J�������7@�,�(���cq�;�R�!C�`��M����q�����d&I��>|�E�5k�L��H$:t�Es{�1A������)�0""B���5��?�$d���
6��zC��()���U��sLFF�����'�|���V���o_�����6m����u�Yi�Z<��S������M�6�[���V�Z����h����xHHBBB��wo��9���|F;}�4f����K��]���#�Z���m� ��E�[�h�?�����((�W�%##_}�f��i���{���d^|�E�?�}��*��.���L���$�Uv���Y�k9�k���+,~
�9qqqHII��x�Z�	�<������c�_RR��G�K��8��
b��58|xt�v���G��P������r���p�2?t7��m���x&"r������`""��9����x&"r���j��v�?Ue�)��w�j~���+������������
�J������VPP������e���D����8y�$��?���t���Tx�[zz���>}���<��s�;w.^x����U*N���#G���5�o�<���0���2�j���U����������l[�e�'N�={��j~�^�I{����I�*������������j���E��'(���,Q������8���/8{�,���_dee!77%%%��+����:$h����fk0I�+Opp��m�s��a�J�q_�z��K�.����Ag���1z�hA�G�L����
X~�%�/�����O?��������6��X����&:�\������&����Q#�����;w��o���L��R�M�KHH��3gp��edee!;;�����,%�H���_Wa���������Y�zu��/�GOe�]��Y�������Z�|MD��F�����hE=www&�U@���A����Q2��&��E��<<�=m��N��0M�K��A���������������������GBB��]�bRE�VI�Dzz:�~�m|�����D�����y�^RR�L��;v,���evl���X�`.^��^a���z3g�D�n���gOt��m����pDjj*�j��}��E�{��Qzd��I2���4~��
'%%	��$��*/�firz��h�d�ve**X:Ol�3������C���W_��W��Dy��u��uA�2	o���S���?�e���~�m�����W�����Ag5y�dl�����H$X�f
h�u�R)��]�}���5
�l��7�xCt����=���5C�,Zs����7o��sSRR���^���0�VI{���X�b��_�+W�T�~
���������[o�&L@LLL��Q��V����%���i�u���=_Qu`0��hD�I"��!�J���Yu!���\\����\�l�$��
rM�
-$="t���b�w�����|�<U���e�U����_���������V�+��=�U-..}��}�jg��;����_��������s�����{��w]��1x�`�5
!!!f����Q�X�q�jo�Yu��733���T*�R��j~``������
�b*{��gV��^g���p��Ux����X���Q69���]k��X��Zb���3�1cV�Z%�[�t)��g�����1~�x|��'����X����u�f�z�k�F�
p��Uc��S���g�j���������_Frrr�^��U��W^1����>����(���������bob{�c������5y�d>��9��]��!C��v���q��U�����G\\����];�'�s(((@bb�I�D"A�&M�z���H�JC�M��=�m��D����.q��dB����_":uj�N.!��l�E.�nM��G���1M���a""��9���qx&"r������a""��9���P���#��r�l��a�_�v
yyyv[���
4��z���r��{_��\��QE�����&	{
6D�n����0xzz���]p���%KkUl���������$4o�111h��j��
www(
A�S�N���Sdd$��9�e��a���s���6Z����������;�`��IX�`���M��E�(>���V��`��0=?������j�ZT����_&	{...�����o���pC�P�\[���c����W����d�kIU_���E��h�"A�������o�5�^�z	��J'I�%���Q#�����$��T*��?��E����1n�8c�lgI��*[�l��m����>�~~~U�N��D~~�U�
C��


��-U66K��j�k�Vpp�g�{yyU�S,l����ic{�y{{#%%E4�5''���5�|]�\\z!���"#��r�]�0�������)P2Y���1o��)0��X���C��a""��9���qx&"r������a""��9��fr��%�C+D����5i�����W����I5�������0W�\�+W��!!!X�~=�x��
�~���V�� ,X �4��aCl������p���M�9s&�O��#G�`��}��?N�8ar�jQQ����������&���]�I�&�������,ww��O�����1y��s`z~�I6���N�*H�0`V�\�:u��;���YK+�;���gRq��������0���Q���,w���:����c����)S�`��yv��n���vZZ��m�
;Y�����[Ze��q����/b�����t����'hooox{{W�,�i���0`F�a�u����-E������c[*��^t!�H�?���b�T*�J����6w�������H$���7M��Z-rrr�������w��P(�@�1=o���b��=�D�<���?G�&m&i/^����������������������@��{���=���HOO�j~����������m���cG����j��z�7o6~�P(������pPZe��J����ALL������b�:u
���;6m��k����|�2���]�v	�Q���`0�w������y���IV�)����I{z��������x~���5s�J�r�
�����f��������[�s�y�P*���J�B�����~U({-�U��]�%Uqt�~�-^{�5A��������:$��yS���f��[�.���U#�M|-[��2�ZfRGP��S��������`0���
/�����ddd ;;�o�FBB�}9J���;w��D"���G��}$%%�ls��Y�6QQQ��X�My�n.�$www��W�J�z��GE������:	

2��/K��O"�@��,:�V$���BQK�_�MD������A~��fqQ����a��L������e����?o���������z=N�<il�l����=�p��UqU���7	�O<���	{���Uv���+:v��y�����+X�|9������{�n\�tI0'44TP/))���&e��-[��<�U$������s��Y5���e�Gd�����&L�(a����W���S�N�m��!h�N����\��O?�������1b��Y�@	�"%%E�

*w���hA;55�����X5�a��I{���?����p���X�={�d���&�]�x���eO��%��k������WWW��a�Z�T@����h���0�nq�K�+)�EII���==�s���������������������^�k��Q�8��m�
��j���gdd�����.[��<W�\��;w,���M��z z�������C6�N"�`���x��g���]]]����_PP�'NTy<�������A�������:�����j~������Rrn����A�!11��|��\y���������AG��{7�}�Y�t�+p2`�l����������u�����A����O[��N���������8 ������s��O� ��M�
Ja&&&"99���G��[�liv��cG��x���d$&&����h�����5�5U7��������:	)�;�B�����P(B��i4)�t���E&:�[`�����������������������ye������D�N���v��	�Zm�\�JeqBB�����"�c\�b��������]P`�=K���Z����o��O�_|����)}��9��P��[||�E�����"a�Q�u�&ho��Q�|[���Ll��M���k�*��.�=7k�Z�[�������W/�����w����W�Z�������Y3c������{�#�K���r��<������=z`�����{+))��
}�z�*w�SO=%h�������h���yyy����7Z�nma�8y�^��+�D�a���������c���V}}����}����l��A�6���&����kQ������o���f���'�?��������XA�G������&�&������lIj�J��O�q$WW?��4S������L�WW_�1�&�������s�m� �����������_��M�]����	n��h4�3g�Es�}�]�'����(�����V'�)�JA;!!�������[Z�g��]��}���TF�����	&�������u+v��i�xJ���*�Q�V�����y���Gaa�-B�����z���			���/-�;k�,A�SLL}��*���=7��5������]CBBB0r�Hc[����^�^��*G�6m����o ;;�A���%�AG8u�(�^t��;v��B�p`d��E�p��5A���������{�X�ti�k��z|�����C�B&/C��:i�~�����.]�82����z��m�W��T�Ba��XRX���_��E1���_�THH��oov�N�:!00���q����o�Zec��$R_Qu"�H�V�+,,d��)�g����������\^K�_���@�c.i����DDDDDDDDDDDDDDDDD�����7���}e27n���'�d��)�H$�������w��;g���X�v��k�d2�=�����~��5<����.�'��?�Dff�Es������0c������ys�s���0z�h�b|���p�������49�b�k|}}��;��z��F���;������x��g���i�������-�G���c�B"����k�>,��wo�����0�g���'��T2�S�L�M�>��g����[g�l;u��*���:u�W�\i��T��U�L
Y���
���l�3f@.������#��j-���)�'�=��s��p�����w���x�����a/^lv
[\�������x��'���k�k��%v��]�E����+�+�~��'�={��o��AU����M����{�s�O�������D���,��I{����v�,g����#%^<X���`0`��y��q��A*5��#�JMN�����������C�����1bD�sj�k"�n���������1��G��������s�nq(�I{Zm*����;�b���K.$"""""""""""""""�����M�6��;WWW4m����<�:v��^x��6�����_�n�l�����_~/��"XU�p��1���3��[oA�R	�����t�R�i�7o��D"ATT���H�R��������B��x�bl�������lB_�8���?��X\����o����C��]���	�Ba����s'�w��&M�`��98v���*�}�����e��o���$c�-��m[�}�������������!C�`�����o�h��F�A\\.\���[�M�6V��������SOa�����ebcc��������%�z=�|�I�_���Z�?�����Gc���0x��G��S�2e� �V���_�~x��w���,�����4i&L� �_��g�az 
4@������\t��[�l1��z��9<��3x���`0��qc�������3��
0t�P�[��w����9b2�I�&&��[�lA��M�a��$���oc��������mkq����d2���O���5�;v��5��9sp���y�������0i�$���a����t�������Krr2������c���'�~�m�:u���FE_�9q�z����-[b���8s����������+�u���S�
�����O,zmm�����?olc����;w�������/��%K���O�n�����7q�
�YYY�	�	����*�p�0a>���k�����q��Ac�����D��w�y+W�4V�:p�/^�����n��L�0A�7e�Au���5U7r�����O�HOOGxx8K�����2�t:��j�a����K�����#��|����<.�5;NDDDDDDDDDDDDDDDDT����7o���D����
@���YaO���Kq��i��������_��/�DDD�������ooo�X�B� V�q���������g�k,]��~�)6l???ddd !!:��8o���s�._�l��y��7�c����W�\1{��_������o�������o�a����={6���������4$&&
n�������w�!11��8/]�����c�����d�S��J%�������7n�T�����u���S*�b��M2d�����`��m��m�6��r�������YYY�}����[b��1X�`�����o�\E�9s�`���V���}��G��k������l�7���y��d2��}[�D��kW�=����0��d��iz����7o����p�B,Z�P*���DY�Z��W_}e���&������{w�9199#F����6l�T���o#55�8����}�Z�je�:������#8��?�.�{����������O�}��_���c!�����h�Z$'';e����(l��
O?��1�033�x�
Dhh(<==�������J�[\�����&��������Vj��%��;w���.\\\P�n]������
���HLL�P����_���D�������8u��{������>��<�|}}���b�������}����q�J{����L&3���z���#��~�m����			�������^��K/��w�}W0��w����a`` f��)��1c&O�,8���z���/�����"W�vm�K'���DT��������ZM'�������X�������� ��'Vj4�rsE��?7�sL�����������������������
"**
���V����FTT6l��=3|||�6m�
7�q�N�<)H������;�����������a���~�^���/����v�� y����/>���_O�n���g�U���T*�c�����KJJp�����!!!�x��T*�'�|��'Z�Vi:�III�����'p��e�������T�������{�����/\\�5[�Z-�\��'N���sHJJM��[�n�k(�J���Of�t6�����u�I����<�;wg��$����;v��9@dd$�9b�{���q��u�<yR4q�_�~��?��� �T�N��f���d^^���q��iA����?~��7DGG[���e���O����O>����M�9:��x]�����2a��=z���������q��y�8q�.]}���kIiUy|��� !!g��E\\�^�*����}{����UZ���{���O<!���t�r�
N�<)�����/b��,�SIN���T*��wo���o��FP*���y3
��/))	��R�D�V�����c��U����[o�e�Z����|�IA�W_}�z����GA�V����z���pww��?�??���5U7���&�����dJ��,���s��9v�A"�A.�g�Fs��}����8�������������������������iS4o��k������M�2�����]�6�7o��M�2i����8v�/^�Z�j�n#��0l�0�;wNP��R������'����
��,�C���g�.]j,�a��^{
�.]������gO��]�/::�O�������t.�H��O?~o���U�������>B�^���)~�Ui
4�������/[|�����.]���/��_�(��~��x��kQ���]������_~��"""����J�����qqqx��'�����b��e��������#t^u�����'�v�Z4m���v���������k�.������������������m
���.T�:�K���g~��w�?-[��R��:�w����~�:^�u�D�����0j�(�����_�~����Gyqqq��cz��	77�r���d���#����k�����f��`M���/��7�@�V�,�=T(x��'�������cVU�+����v��w�}����������{������j�*�9T1�����t��!t����Aj��-:t���r�����G����R����o��Zm���>�,��[�\n�:�����?�`����uk�.�5�5�����Y3c�����~��������_�v�=�������IIIHNNk�����%����k8~�q�����@p��XUKK����3&�����7U���������4����L#���0���LD�8<9��DD���0���L�p����JJJp��UA_��
k�M��z�z�R�R����^t�^�����q���T*��rDFF"&&���U�F^^:�k��!;;����[�.:t��z��U�UA�V����HJJBnn.<==�N�:UI�9�N�K�.�����s�rss�K	C��-���\�p.\@zz:��� ��������4i��k�~�u����T8pw��E~~>�J%�7o�:�:�n���'N 55999���G�Z���}A�3w�\��7��v�t�ILL��#G����V???DEE�S�NNy���`���g�U��_OBCC��I4k��Z�{


p��q��u(,,������[��W����5EQQ.]������{���(..��������Q#DGGW�`Y��_G\\n�����"�N�:����1�������R����K/���+WB"�`���h��%"##Z���gO\�x�����
PP ^))::���^��%
���{6|���=+����'��y��3���j�k"�N����&��T*�zR�3��xry(���1u�a�%�)���m�_\�	�N�h�?z�Kt�Q�E�O�"""""""""""""""""��D"�L&�7�WR�]�v-�������B�~�l����T*1d���_&��Y�f��][�H$vY��		��#F�U�^=�J���O�����}��������vt(���={���}��:XS����E�h�����~��G*]��,��I{��g�!11���;�����kWl���i��9B����$�>$$+V����Kq��Q\�t	YYYpssCXX��o�
TA���O?���~��]��'p������7F����-�n������wwwx{{��PZzz:����T�����D"�R���[M�����BQ���F����u!���)`��I����+�o����'�������w��W/������GLLBCCf�����^�z�W�^6_�A�U�4W���������`�������j: *�g.i�PsI���y..���<�����i��Pz����
\������`x���19�j���K�[�f
����I�&!==������p/A���������D"�����2d"���R�Dbb"t:���J�b��J�Nf���G���'�H�P�"?��z��$�}<�&�Q5J��S�Na�������D"��`0�����	��*B$"z��d2"55�d,''�
���977�x{7En��1��0��=k�8�Zf���}<�]��d�B^!�z=�R�=�$""""""""""""""""""""""rZ������{:t@ll,$I�|Q�
6;���f�H���������K��\^K�_����8�|<D��\�+�ehDDDDDDDDDDDDDDDDDDDDDDD�B�H�����?�z�^������ _DDT�<==��!���R�x�5C�O�+)�En�?v�A� ����$����f����T��-QM���*�{�n,[��$Q�r9���ooo���:2T""*%88���&�������������rr~~�!�*��kL�2����m��R7������"�F��&h������&�L�#""""""""""""""""""""""�I{�f�2~?Y�Y�f�={6�|�I(
G�FDD����7���M�T*��DH�r���C�����Z}���%�"T4iO�M���M�;���="""""""""""""""""""""""��(��+Wp��H$H$<���8s��
��=""'����R):������";GT=(�]D�sr�QR�k��Z��Zm��b����V�EVq�-C#"""""""""""""""""""�������`�""������������|��7pqq��DD 88��XZ�i%72��g0���y�.1�K��jS��av���B�EDDDDDDDDDDDDDDDDDDDDDDTM8u�^JJ��{�D�#F������5����VEU�T|B�O�FpsOvT��%WW%�R���F��:rW��'�����24"""""""""""""""""""""""���I{%%%`L�h���#�!""+I$����Z-rrr����H$P*;���3���'�H ����i4)�H$f�����24"""""""""""""""""""""""���I{���������"!"��
�D"S�Tv��zP*���$����]bP(�%�%����39��HDDDDDDDDDDDDDDDDDDDDDD5�N����c�Gzz�#�!"�Jpss3I��O�V����(��+�����P�����PR��Vf����JpG[l���������������������������S'��o�
���>s���!"��


�7L�!����Q�1���I{��j{-���� >��!UN��������~��������Y���nnn�c*�
���9?s�����0t6__&s������F�WD��E���GDDDDDDDDDDDDDDDDDDDDDD3�N��Y�fA.�C"� 55K�.utHDDd%�Db��^AA������S*cD�KJ���{�.1�������}������������������������������^N����Q#,]��X�i��9��c���"""k�S�Tv��z��k�T�:�Z}�.1���I{Zm
����s��(��z"=��>i&O��>��%%%x���1{�l::4""��\.�����Xzz:t:��#rn2�~�mE�2���g������V��V��I{�z=�hl��rqt�y�&`������������j�`�,_��<��v��
�������^�^�zU6�Fvv�I�^�GFFF���FJeg�3���gg�AII>\\<m��\�D��4�R�MF��p�HPl0���S��^�6�������������������������9}�^���!�H}�����X�jV�Z���H$���<�~���<�����oU*���P*c��������C``��/�� ��@��k2��$���%�x)p.���m|n�E�M�#""""""""""""""""""""""rFRG`	�� ��%��O���/""�-�T��� ����<�9"����(\]��cj�a���P���h��>�������,&"""""""""""""""""""""""gV-���'���*o�2_DDd?�U�S�Tv���I$R(�]D���G�������,�t�h��!:�o��:�-C#""""""""""""""""""""""rJ�"i�*�����c������[t,==z���97���h~�Uc�;[�����@�IA��x�����-�UXDDDDDDDDDDDDDDDDDDDDDDDN���T��o�qtDDT�������k�_RR�Z���@D���U��U��]k�M�wq��L�	�.�dL�I�#����I��3M���)@{?/��GDDDDDDDDDDDDDDDDDDDDDD�l�>i����wtDDT��J%���L������W�B
O�����j2�V�y��D"�BQ���L�4�dH%������<��3�6�������������������������I=|d2D������h��s3WmO�>����]US(j��k�)0h��):���=""""""""""""""""""""""z�0i���"88��XZZ�#q~J������j��]�������z-��3��!:~KS���b[�FDDDDDDDDDDDDDDDDDDDDDD�t��GDD���	�d���4;G�����C"qS��|}�<�DtL�IF�������Q�����Db�;v��C"z(�;V��KLL�x�F��W_}��N�:pww�k���6���7w�\���^e����������8:""z8I$��aYTT���,����?0'$�y�����N����G>���K��������L�4�d��4Em�+�jM�����O��M�#""""""""""""""""""z���?8p ���
U����|�2.\����T������h��9�5k�����
�����a���$ZUO�R1i��e�h�^V�I�t�d
��/���M��h�M�6�g�=""""""""""""""""""�*����������������;8P���|��������q��I���!..'N�@JJ�`�����_�R1%$$`�����w/>���B�����b����2e
6lX�����HDD����������L�9"��Tv������u���+�D������#��Ct<>�@4)�����������������������D"1~��;��!�H��q���Y`��������,Y�������k�3f��$r��c�
�o������������7���?����w�}��o7I��,�V�: 22o��6���[n�p/�p���h��>��c���Xi���*88����ciii�sD����)\\�PR�e2�VB@@�M�7����� ��Ot4�D���"Dx�m�,�:]��bH����� �H�S����?�����C``�#"""K�����o������8q����B�@�Z����|\�vMPp�����MCBB�/_n�8k2�$��������/aE��my{{C�P@�����T*��]��p ���Tv�J��dL�y������C*�C����i4�h�]b�R��-`��+/�2RREN�9��^@II�q�����M����!����H��������~�z��OHHTb:t(���l`���Vm��i�^���yyy���"""�����O�>h��-\]]�c���������{�!))���b�
4n����j���0pH����e�%������GDd�����y����V�ENN|}}��Q*��&�����6
ry����H$P(BQP�d2�����_�F�
\�7M�<����!�6��������������������������
Y�'�nSR�������<��������������9�+W��U�$BDD�z��m������y��h��-��m�v���I�&��dU�F���1{�l����l~���;F����������l>k�,<���P*�U���!I{����SQb^�mm�U���'00�n�=����1i��S�w1;��<�Z�Cl��\^�L�^2Z�x�&����4.""""""""""""""""�~��3q��<���j��������$BB!��l�����D�p����}||UJ���q��q�l�r��&k������~��,�����_~��5B~~>�{���~�	'N�I�5����K$����ok�/""r,777�����edd�����9)w�0xxD�����l��BQK�_��GII.��=D����H��ehDDDDDDDDDDDDDDDDT�����'T*a����8qb��.WQdDD��F#|�>��'"�^�����}{�%�����&a����k�����������z�8���5��l]e���/88���&�����

u@T�G������~���M��V(����D���p)_�f�����������������������/��y%%�U�?mQ*N�������WT���&���8z�(�\����(
DFF"&&U�NVV��?���/#33EEE���Cpp0��m����*[�A�T*�?��_GVVJJJ�T*����W��j)))8s�����^#22��5���W��_PP�#G����;P�T��dF�&M��U+&q�����q��	��{��3h��7nl�u�����7o"..������6�:w�����*]�_�����w��EVV1r�H���Z4?##G���;w�V��v���e����v��?��w�B"��v�����;����UU/�xp����y���pqq�R�Dxx8:t��@�L[�|�2���o���C�VC�P ((�7F�-����@�/..���Gq��ydee���u��E�n���_5U�o���S�N!55������5���Zh�� �VLLV�Xal��y���T_e�IDATI�KH0M6��m�������������L�T*BBB�OJ�.�}��L���������x��������b��J�&�*B!�@�7�g���&�=���3q���*K����$g��C��;��Z57��:��~�)>��S��{�d\&�a�������P�~�J��~����8w�\��D����2e
&N�ww�r�k�~�y��a��yf����_������`0��������w�^\�\~u��{S�N�s�=�n���e>��S;v���d2�7o�!C���W_�R��h�G����o�>h�Z�m���1i�$L�6
���f���{w8p��������7g���;��xm�l��$��_����3�����;Vt���DDDD��?�<��_��������S�N��m��1/^��Z���c�a�c;!!��=Y��d��q��u_y?+�^������O?����E��J�h��f��i�k)��m��_|����L��o���0f�g����b�����}�������X�|9:v�h2��_a���8~����D"�����_�^�z�NgW��F����;���?c��}HII1��L&C�^�0c��s|Ye������,+<<�����;==K�,����[�n�����}�������_?����j������l�2��j�q�L�a��a����J�/**�W_}���W������H$�n��f���A�������deC��������!I{�����DDd[�AAA�s���XAA����4���!���`(1S���ia
E-�I{�R	�{{ .;�d<>'��m9��W�A[�j�}k�Rq��|4k��M�_��j���O49�>�N�-[�`��=���_�Mf���_���^�x�7n`��)X�j�o��
X�^eM�6
K�.�x���c�����k��O?!88��9Z��F���m�,ZC��!>>������z��]�����7n�l�R��U*��}�Y�;v�@��m-��A�M<+��U�����X�dI��\�t	�
����1k�,;Ef�;w�`��A8s�L����z?~�
B�~��y��rA��j�x��g���?W6dl���F�Baa��m�����[7l��O=����~���O���;v ..���GTT����l��K�.8}��E��t:���"66���
�-[fuR��Z�j�z�-���U�m~~>~�����/�I����sO>�$��=kv�N���7��?�Dll,���-|��'0j��
�k�:u
�������������9��>,�gR�������0qH��}={�4~��A�^�������K����I{���7||Z";���<�C�W����P�Bn��S5��T:D�M�+�i\DDDDDDDDDDDDDDDD�����Bj��6]#5uBC!0��M��rss��o_�d�D���p"==�XQ(''������ZG����y{{�v�����EII	���L�]�x1118w��E	qJ,N������Z����HNNls��a���'O���2��	D����\���\�T*���Y�J�B���E�[�������t:$%%!3�eOIIA����g�t����5I����	{����W�������d���={6�6m��C��;T���{w��yS�/�JQ�~}(�J���!))I0�{�n���{��5��T��c�
��7777��u�����?r�F�a��P(OOO��^\\���G����h��!-Z$�6������pH�R\�vM�������C�����puu��5:;g<�b����kC�T�������y��I����������������7�x�}��I�L&C�z��F�������eee�w������}aaa�U�4
�^�*������A��������p����+�y���M777DDD���999�v�JJJ�z���@�P���-���������$dee����S�d2��C��C�	��5rP$��C�����o,������P���	(
������MOOGxxx��pc�e������������6[[.�7t�j���!:~�@��|\��#"""""""""""""""z%%���:7W3i�*��N��H$x��W0m�4��W��������c��U��������^K.�c���x��'��[7��������-[���������%vL�8��o����{����[o�e�����1c����E������6l�N�:�V�Z&���s7n��E���6_�p��OM��������q������i��a��I7�>55�����Za�<�^��#G
~�AAAx���1z�h���
�=v�f���}��


0j�(�={��J���K�I~}��1�7o����������\S<x�X��}��x�����Gc�/������_$�����4h�W������XA���i���o_�9eV%%%5j� a���o��^{�5��]����u,Z�k��5��>}/��2~����������z��j�6m�`����Sp<�?���0��=z4���P�vm,\��������
�����'_WAAf���7�x���.�m�������{w���Z������o�iL��x�"V�\iU���Y�a�z�0|�p���m��1I>3����r�J�^�:���7�`����j��=�������%Kk��q#BBBDc1����g��\"##1{�l4�$����[��g���{���S�N��7�����^z	o��y��x~~>V�\�3f���p��m,X��/.w�.\0I�����;���^�z	��rss��?`��Y��n\\�|�M|��W����u��������C��������sg<���3f�r���mo999��u�������zsh��}�J���'88X4iO��###�.OUrvJe�HXf���k��}
Jeg��-�B"q��Pb2��$#����<��s����f��s�������vY+++yy���e��������z�jc["���o�����M�������+��uk������{������S�}]x�����3��O�>��;v����h�������{�I�Sdd�q�R������+�D�w�y#G�D�=�	Zk����9s�T*E��M8X�z5��gv���6��
�'�|b�P��%K��_������;D��T*E����w�^L�2_~�%�{I���7I:i��������V�������c�b���&E$	�w����e����;w�`���<x��_�gr��m�X�&M,��}��g8q������������'�0���G��5k��];��������7c���2d�Eq�O�>|86m�$����C�r�������(���O�X�;�}�����{��ysc���m�p��9��z6�6m2��&�����/���]������k\��3����
�:u*���D"A����b�
<��S8p�1�E��&���U���]:�:w������Wi�����i�}��
����&i��[&L��	p��i�+S��qr�?���h����'�N����P�5}�������V6,))���#	{�����Y��E�J�����������W�^�\�/��"���M���:�hg��������={�g���=��9�n��l��>T���O>����/�� ""*������dT*���qN�����E��Gj���-�� ��?aD�IF=����<��)�ehDDDDDDDDDDDDDDDDd�^_������}�;����w69���������>�LPP��W^M�+m����0a��k5m������������T��[���_o���j��u�	{����c��5�vaaa����\�b������J�e ((Ht���}���]�V-�����c.�J�l�2A"��u�������i���W��d�Y�f	�v��m��*���L7.\(��W�����K/	����(&226l�t�AWWW����&�f�5j�H�$���p��U4h�6l0���?�<�����}��9$''W*Vg���0&&���RY}��$��������������@�.]�y�f����n������h��
+�=��sh�����R��X���u+��?olO�4	�g�M�+-,,?�����m��o��`u����#F�$xVGG��'�|"�{�����9�:NQi����>�T��� ��yyy(((x�/�R���;"-m���Z}��6]_�����I�V��D�hoO���1�g��Ch�)8z������;w6����oh�:��{��
YYY��m���P(0o�<��.\��~�-���l�a��h���?������W�^�U���^��G�b�������^$�J	��o��Z�6����k��_Y2�3f�0Vw�_��g������_��.I��4��r��1b^~�ec���3��"{����[�����pL�2���,���~���{�>|�.]B���-�?s�L���[��7|�p4o����
��+W
��O�^�}���
��%K�}����jm5AM9��G��|`l=zT�ZkUHNN��?�hlK�R�[�����e�����W^�h�g�yFP5���3f+V.[������>��C�cz���0x�`�g����C���$[��:x���/
�}��A�~���eK4h�~~~�j�P�T8v����{���K����?��>}��b�J*�
#G��N�3��m��������Xi����NyOb��{��.���yPT�a���P����l�t������I{DDDDDDDDDDDDDDDDD�u��1h�Zc{��'yUX���DDD��������Q�~}����Y�rUNN~���*Y��]��]\\0r�H�����K�8q���*��a�������m�J%���gl�N�s��c������R���!C}�h�L&��#,������[�]�f�m�D��C�Z4����o��iYp�DM9����m�!��� y�_�~h�����:t�EI���eKA��9&##qqq���O>	����������<�cn���#���������c��������#������
///DFF�����o����",,L0���8w�����<�V���zJ������M�6YU����GDDN�������c������v����I�u�m�<�P���F�l6i/���Z�>�������������������aV��|����U�������T|��x�����c�!$$����H$&_���q^AA��B��%&&���>������qcA.���y��1����t���������s�a�������t��G�1�5j��������c���K����V�ZYU=�t���l[�d��U��g��V������}�ZfE}�Q���Z�u��mW�����ei�R��999�WM8�1������3��DFFB�T������,����;7?�����Nlo������-�b�s��aA%8k���t2 ~-��u�Q
d��lN�.]��~��{�=[�gz��G�T?��d������AFV�1i����RPP�hII	233���qw�w�z�cj�a�����
/�1�&-���@?�j{DDDDDDDDDDDDDDDDD6��� h���T��U�,�������#,,���:6m�����C�RA��X�{������!C� 22����n�������(*��a���8|�p4i�������[o��������-����->��$H�Zml_�xQ4������4�>J���W6I�"��������jNRR����ys���h�B����Z��h�a����<<��/Z:Ol�3������C��E�h��=>��C���			���DIII��my��~���]��7kXs�)}~���	vo�������!v-��u��h���,Y"���kW���N�<[�n5�%	��Y��:0���I{DD�����U�Tv��9)�T�S��O���\���F��7�ww�g����M^��RLe��~�:�����7�@��Y5�4�V[������C�-�}��J�[U^b���+~��WDEE����w/f���������G�X�lRSS�]/##�Rq����Ug
���!<���R)�J�U�KW�*���X[!RLe�����l}��9�1\�j�u�������k���Q6����]k��X��Zb��`u2f�A��^������,7c��Z�J��t�R�7�A�,.����H�L&C@@�h�^vv64M���A)�����M&�Zm


����v���Z���*�v2��=�Xh�O*&��N^^��]��QE�V�)OQQ������o�6l�n��!**
aaa������;$�q�%K� 66���*+##���7I2h��9bbb��A��]���P(�8�N�jq2Idd$��9�e��a���s���6Z����������;�`��IX�`���M��E�(�^_���������s`z~����h�����kQ���_���_$�����K�.h��=����B�\.���O��X�w����.�V%{^K��:X�H�Rt��[�l1�]�|��Yf��EX�h��o���x��7Q���=""rZ���f������n��v�����w�����~���6O�����X�hlSe����-��`���?���������������������Pt�x�a�_��_dg���z������'v[�4�<�!��W6������l���[����+q��c;$$����O<Q������������6l��7�]�v��6����3g�����q����������'PXX(����_|�bccq��A�
Ne�n��	>��3��)������S����eL^������{�
9���S	{���+Q�N�r���2kie����L*N:����7�xx�}FFF��^U]��������9(�,_�3f��M�2���sPD5�����iyzz���C�����4��SG�T�����||Z ''�d,C}u�����ry0�%j4���������j��z��?DDDDDDDDDDDDDDDD�"��������m����]�����9��:��������n����m����m���c���U��V�� 6o�l�^�P���/7�����)�J�����3���8u�~��wl��	��]3n{��e�;�v���lb��`@���+OM� �
V&Y�����7&���zdff������e�'��%*���+��������5��?�77�
�����T*m�J�����m��P�ZR�V-�\K��:X���*Z\\��H*�������^��?�~���"���������Db��	EEE6)�\�(���ge��^_d�u�RW���O�h����.f�/����������������������a2�����y=gR6����V�����-�N�������v��--N��.XWe��yw��5��x�	��
���P%q����c���7o�\�����C*��m��w���K�sBCC������:��
��]�zSy����-��������j~������R���'L�`Q�`��p�2ki�N����U%"BX��t��=U�:X�����AAA��|?����/�t9b��Y���.�c+NSi���k�������H$���?�>�DRR����}*���R�R�	�_���t�����{���P��V�2��h�,����;��3�gH|NF�
�Y\DDDDDDDDDDDDDDDD�\������Y�'+�������W���qVm���8`RI�<�h�������QQ��+W����;o_��~�������*h[��C�l�$'�H0y�d;v7n4�>|�76�]]]��sg����U�;q��t�{U�u��Zs����G�NMM���U�d��M���}���{�����o����*�A��e+� �����\�����k&O�l�����GA���g�^�����u��uP$�����>�,t:��o����q��{����$����[�A��f�9)��U���LY�t�����d2/�ty&cj�a�&�����>i��(z}Z�x�&��e�="""""""""""""""��Nx�$d�m�d��z/�|
g��S'�������s�N��j(��
��T*�����u�&=�_�+V��x[����
,����qZ�s���d�{��x�	c�|��6K����D^�����9��P��[||�EI{���N���(��u�������7b���pq�8� 33��m�u����c��Ce��Z�����j������...�$���w����&��YXX�5kf��{��u������spd�]��������^�z9(q��O?-x����[�n����#���&�`08�����_pp�����T=H����Z�Z}X���(������ ��Ct�b~!
uz�FDDDDDDDDDDDDDDDDN'0�BB�t���A�Q��5����z�)c[��`��9�}��w-N�$�?~\Py���g�Z�W6�0!!�������v�*8������o�x��(�����o���	���glo��;w��I<��sbb�M��*�Z����G����?����X������3����_Z4w��Y�d���<���U#=*{n�5k�I���<�5$$$#G�4��z=^x������i��	�o�������Xr���������{�1DFF:("S�N������:`��P(���s��=�D��/""r~���f?���=�I�J����rr�Aqq���uu��T*�s�j�'����"������������������f�j4r���[���F�m���f��)�{d�/_������9k�����k-^C&��}���vrr2�.]Z��k��a���(..�x�^U5///c��?�Dff�Es������0c������ys�s���0z�h�b|���p�������49��[�6������������1j�(������N�>�g�y��m�6mj�>==����j
;v��>��c�Z�K���[P���0�g���'��T2�S�L�M�>��g����[g�l;u��*���:u�W�\�k���;g��U�����^���
���l�3f@.������#��j-���)�'�=��s��p�����w���x�����a��Zg�5lq��^��)S�Xu\���1h� ������y��Uuh�v��<�����5��l��w�|�"�p��=GU�{�=����D��� �1�F#��0
0����<j�u%	�P�1�&
=��������Y\DDDDDDDDDDDDDDDD��\]����7pq��������e�o��Z=+�T��;��^0�
�������_��[��&&&���_��/��_�����3F��1c�z�-�T*Azz:�.]�6m������H$����x�T�^�z�YYY���/^������?�|�M�+��1c���"''G���m���{���+233�P(,>;w�D�����I��3��T%����[�lA������d�o����m+����~���7�sss1d�:���M�h4��������uk�i���jt}����z�)L�>[�lAll����q��}�Z``����^���O>�����T����0z�hL�8��<����u*S�L$�j�Z������.������q�&M��	��?��3<x��b���A�����������]�b��-&U[��;�g�y/��7nl�Z��w$�n��C���u��{�n�����#&��4ib�,�e�4m�6lM"�}�6��]�=z�m��'���L&�O?�_��}�:v��5k�9s����+��RSS��o�a��I���cq��%�mmy���?����x�����w���<{��-,Y��=����'2d��U��/�|���U��#GD����/99}��EFF�����o��6N�:evmKc���T��}4h�k��qtDD�����L�at�J������#r����P�A��c2�VFHp�YUC�����D�~�&R-�=p$+�d<>���8�|^^Qh��{�=;������--[~//���K�.�����^��_|�/��@zz:�s����b�
A�Xy������
g��5��t�R|���h��!����������t:��3f���;�|������7���;��CW�\����E�������{wc����������������"��9�g�FTT<==������DAb���^�
�b.]�����c�����d�S��J%�������7n�T�����u���S*�b��M2d�����`��m��m�6��r�������YYY�}����[b��1X�`����K�4WQi��9�;w�U��j}�v�����{��eggc��qx�����#�@&������$��]�b����$���L&��M���G��y��
Z.��E��Ri|O���U+|��Wv��j��?���w7����1b�xyy�a���J��}�6RS��Y����}�Z�je�:������#8��?�.�{����������O�}��_���c!�����h�Z$''#--����%**
��m��O?mL"���4^�
OOO��� ==�R���A{�j����_��/�|||P�V-���������f�����`��M���Ga��
mk�
���[�|��I����x��g-��4M���$�yyy�[�n�����������E�6����������i.kv%�H�������OBR��`0@"��dm���h�NW���D��I��e�����+
�����+�������		��F�YaO���bcc��_?�:u��o0p��
�Ji>>>��}�U��\]]�}�v���W�^5���z�	y�����`��qV��n�����>���SMn���R���;��_?A�GII	.\�`��T*����'�����j��t:������
��-[*L@������{��;����?T��j�f�$�V�n�r��J%~��'>��Z�3
���[1t�PA5���<�;w�d��={���M�y�DFF���#<x0��9c�����~�:�_�.:�_�~��y3����*�`�:u��5k0q�D�y=//��p^���?~��gDGG[���e�p��-������~��'h���M�&8��t:���3���N�<�Q�F��������tc��9���kIiUyt������eI�R���[�����������R���������5�2 F�_�����D��+����hR��!:�XX����1""""""""""""""""��\]�����h�|-���Y5���Z4_�fM?e�^9q��1,^��j�?�[&�a��a8w���:�������'O��W_�B�0�]��g�,]��� ���p��%��=={�D������a�����q��i�=2�Lt�D�>}�����x��7��-..}�z��OO�
�o����}\�|;v�h
,]��/_��/�h�~������_|���U���+���_|���8p """���
��9o9����'�x���Ahh(�-[���X����9B�U�N�<yk��E��M�n'�H��}{l���v�b�U���D��]�n�P(0~�x\�p�R�)�^%�={����������eK(�J���&O��������_GHHH�����a��Q���?�J���Gyqqq��cz��	77�r���d���#����k���������A{X�z5F�iqrbhh(�L����/c���L�#��J�RH$�l�R��OD�s��4k���>�|���)''������G���80"r&����(**2����c�=f��r���8�`zYo�h.������NJZ��b�I��o+��tB������k�^|;������`""��9���qx&"r,������`��CU��URR"�f
6���K���L��.#5�W�������()�6�������||�#$d ���i����q��a\�r*�
r�������A```������C����k������;����:�^�zU�FUP��8x� ������OOODDD�S�N%�UD�����K�z�*������\��F�����eKDDD<�:�.\��������,��r���"""M�4A���x��"55���w����R�����C�f5�n���'N 55999���G�Z���}A�3w�\��7��v`:�SILL��#G����V???DEE�S�N��/ �H�g����K����f������I�&h��Y�8������u�222PXX///"**
�7�(	�4{]m-##�.]BRR�������L"::�����*����j�_jDD�P�H$

��;wL�


���///D�x�����~9������m���P�M��h�Q7�
�n�H)*6��)`������x�:]>��"H�n��<��yW�T��]��[��Ayyy�_�~6�UQ*�2d���/����Y3A��-H$��S]���`������W��S%����~��NU��"�������vt(���={���}��:hk����t���P�s�Z�DDDf�S�Tv���(��E�33�C�7M��*
E�hQ�
C	�}��p�S`���������������������H$pq����..^L�#""""�j�I{DDT�(
�����edd@���9"��T����ty��9g�u�Z���Zm�����|�u'"""""""""""""""""""""��I{DDT����t:ddd�9���
�L<AN�>b�u��!����i4�he&iO]��MM���"""""""""""""""""""""""r&�Q�����$���4;G�<�R7���S��l]�D
�<TtL�IFsoH����)�Y\DDDDDDDDDDDDDDDDDDDDDDD���=""�v�R)E�rssQXXh����R�E�?'�o��l]��\�^
|\dh�!g��4L�#"�j)88���J��c$��\����Cf�1���P��/)�FII�}<D��s��GDDDDDDDDDDDDDDDDDDDDDD5�S$�I$G�@DD�������D���������s��h�\���Z}�f��K��6�>��c��Xo�UXDDDDDDDDDDDDDDDDDDDDDDDv���=����7����U�+))Aff���q�J���cj�!�����o�1�&��T���
�7��fq��C���_;w�td(DDT
@&����T*;G�<��.����7QXx�f����������r�xe�����DDDDDDDDDDDDDDDDDDDD�,���k,|��GDD5�C������_�j���ODDd�L&C@@��Xvv64��#rJe'�c��6[W.7���*�y�����2i�����������������������j�&�=���`�ciiiv��y��������Z}�f����g0��H�h��3��GDDDDDDDDDDDDDDDDDDDDDD5�����Z������x2XZZ�C[:\��,���y��&k��A0��B�IF+O��+����&&"""""""""""""""""""""""{c�Uk��l����"dee�7 '�Tv�/)�AN�?6YS*u���{���dD{�'W��e�=""""""""""""""""""""""���GDD�^`` $���J��s4����
�R���Z}�f�*�D�5�d�ww���Lt<>�I{DDDDDDDDDDDDDDDDDDDDDDT30i����=��eee�����9�L&��_;�1�����5��WT����>����Yi�����������������������j&�Q�$�o0���n�h��R�E�?;'%%y6YS.5;����O�c�=""""""""""""""""""""""�!��GDD5���
���J���`�sD����7J��u�&k���A*�9h4���O���-F���&1������F�H$f��i4����9"���l77�c�V����
E-�1�&-�T�����GDDDDDDDDDDDDDDDDDDDDDD5������0��������H$P*;����Gl����=�6��.��p��e�UL�#"����
����c())�sD����"�_Pp�]��i.iO�+DII��T�;��o�x�������������������������I{DDT�������9�3Wi���6YS.5;��$���x�����
��DDDDDDDDDDDDDDDDDDDDDDDd/L�#"����nnn�c*�
��,)L.��g��X����d29��D�4�d���ruz\/��$&"""""""""""""""""""""""{a��(�AAA�c����sD��Tv���<
�Ao�5�U��h����2�������CDDDDDDDDDDDDDDDDDDDDDDd/L�#"��\�p�����\�^qq&rs/�dM���h�V���z*D���0i������������������������7&�Q��P(���+:����Ng�����-$7�1���M�4���������St4>����HDDDDDDDDDDDDDDDDDDDDDD5�����F2WmO��A�V�9�������Ft�VI{nn�H\E�4�D{{��]��@���$&"""""""""""""""""""""""{`��HJ�...�c*����8�R�E�?+�4t��*_O"�B��h��#��Wl0�b^a��CDDDDDDDDDDDDDDDDDDDDDDd/L�#"�I*�"00Pt,77��WbX���=���Yq6YS.7����S������������f�aXQ�wQT\pM+M+s������2_�����R���%33+�E�W[L�\pA�%W�d`�a�����8���aX�~��+��9�y�9��t�s�E&�1�l����������������������������I{DD�`��������������RtL����5�@����\t����,:���=""""""""""""""""""""""����GDD
������D��������Q��H�P*����;i�[m������������������������jGBB$��+**��C"�/DEE	~�,���h��'�`��h��	����Z�hQ��M�[�h�����W���C��vHDdc�QM���G~~�Iii)������SQ��w?���l�_Ppm*������
�����i����(:�V�Y%��v��"""""""""""""""""""s���O�9�o���P���233��7o������h�����k���KJJp��U\�t	iii������|||��sgt��R)���
��'"����			�U�T*����g��d�c����T(��o����� ����y��
1P�a�x����������������������L<���HII��P�����������������'q������y��g�y�f��w��y,X������}�2�#F���o����;[����xl�����Ctt4����n�����'b��h�����������e�L�
C��W���HDD
�L&�����XNN�Z��#�=
E \\Z��e��klM1M*;���$������5�/��D"1~-Z���Cj�����v8d�����BBB������_~��}��_�&M��(�jWTT������P�!Q��_�����7��o���(�[�g��$�������p���K4at:v������c����W��"""����3g���Wa�p����k��c�����l�H�>������Xi���<�T*�1�J��M��9��������&�ju=$���+��C	JJ�����=������GDDDDDDDDDDDDDDDt�20����H$N�H$�Q����_����All��"DDd��;wb���v[��?��Y�L���qc$''�KKK�����`0��W_�p�%%%8y����B�@`` |}}QPP�7n����8^\\���g#>>k�����*--�s�=���R���>`�=""j�\]]���":���� K���T��/)�D~�_6_����>nh4)s_�r��������������������~���#33II���n�E|�'���uHJ����hh��*��m������~5o����������jl�=�	{DD5������;v����#�8p ��9���d�>}���8u� �n��Y����j���,Z�111�����[��K�.!;;_�5���s��[�5k�T���b�
�;w���e]��=""j�$	���E�������m��j��WOH$��cju����J ��{�&a��2JJqG[3%�������������������((��;w������X%B��
����(*JDVV,���+���=

n�R�DD����k�v�j)"��)  #G���o�������x���m�����������#Gb��=����`���p���#F�0����b������o_���7o������O8:
�'wvv����=z��z�-��jk_����W�d�c���
����������D":���n�hj���+<=�����15��B(���������yq��5�>�����"%��h�����$!%�HM�
:]Q
EHDTw�/V���Q;�50,@bb"RRR�k�.��?���>�Ri�uv���c���>>>�������$����6m�c��#G�o�>�k899��_~Att4�
f�^���������OP	/;;?���%/K��`��)S���}0���>���GWy�	���������`��RVV����Q�Q*���g��B���|=sI{���p����E.:~6����Q��j�������Vk?��!1�+h���C���@���gI"U�[�nh��i���q�FA�_�����*������_~�������$��g�����g����������v�ZDGG����f��*���q������������&��h��q-De>�H����I�^_�����Q���z
E������\p�Pk2v��������������������6II?@�7�_�*t�$%����q��+���~���q��1\�v
���P(

Edd��bKuegg�����z���a�^^^���G�=l���C�R�����y�&���QZZ
�R��������y�Tjj*��=������B��������

E�����V��"&&IIIP�T��d���G�����[7&q����Wq��I$''���={�]�v5���`������4������[iIU��y.\@rr2�������	&���������8v�����V������={�k�����q�N�8���dH$4n�DPPP5_U�R�a||<.]����D���v#""�Z���p��U\�pP��P(���C�v���K��,URR�c�������������6m�����&�!11�O�FZZ������i�����������V�5I�{���,���s�����6�w������j����u������U�Obb"���gl����h��	�b���=""�oxxx@.�K���R�x_�����<QZ�c2�V�y����'d2g�tE&cM
�<Z`{Z�����"��
p�6�������������������~��!9�'�%����k����5��������t:V�Z�U�V!99�d\&�a���X�b�7o^�5�����w�a���8�|��D����1c�N�
g���+s�r-^��/6;����8p���`0 ::?�������W+����S'��5O?�4���z��mX�j�?^�v2��;w�c�=����C�TZ����,]������^x�g������}
8�6�?|�p���-\��-�(��P>nk�6o����'�_|����D�MHH@HH������b�����{���7�����E��k���/���#-�+**
_~���o�;Y�{2y�d������J��c���X�j.^�(��T*E��=1�|�_KE�m��-X�z5bccM������0f�=�����`�������&����k��wo���b���8q����D"���#�z�j4k����Y���c��h�������~�����jv[�L�!C�`��y&�������U�g�����J�222������o����mv;WWW:S�N��?l���Z�+V��G}�Zm2.��0f�,_��J��������O�a�\�|Yt�D����������Q���M_�C������n�����e�����U+\�~������c���6��|bhN��}��x��������0���Ik;"""{�H$����h4����sD�C"�A��+:�V���z����cw��\D���z\+��<""""""""""""""""�����T�a�tHO?X#����j5������g�&�w���m��.]���A����5k��[7�X�����4y���[�1c���q��
������g���X�fM�	{���"**
�
�J��h
�V���Gc��q�&*w�}\\.\��g�V�}AA���~��a���f���������uk�:u���m!**
���e.���3g|�A�	{p���5JP
�.IJJB�=�����M��&��8q�F������|��V��O<�g�yF4a�;w�D�n��m�6�d3�n���c�A����1d��d3�nB��]���W/���U];������1c�u��
������{�b��A�>}:JKK-Z��>��S���`��&�w������0b���}��5�����&�w�������p���Y�N�<��m����^3���}?O�>�G}�F�$��S����v}9w�����O����+����l!))I��Je����
���;���6l�Tz���_�����{�i���+
��[<i/?�
��6_O�0����U'3O9�[h�X������������������

n!?�f!���BA��]�������a�L�c$	�7o���pA���\<����r��U�h4��vwwG�6m��gOt��
M�65����������=[bqz{{�]�v��^����8EGGc���(**�t�)S��$�w�����!"":t��6sT*�m����5i���wG��]M�����b�������zM7w�\��������;:t����p��v�������b������O�$�T���P����V|��{7
���,������{�-,,����������q����
����=�%%%�8q��
��e��h�"cR���':w���]����M0755�G�FII��������P����qct�����<==M�Y�v-�M�f����^{
/����b�=2�!!!���:u�T�s�=���x��	XAAAG��!���gdd`��Q����h�?��3
���xA��������m[�
�?��3,�~�U�����������[5����~~����G���[[5_�Ra���������N�:�$����z�DDD�������E���V�QZZj�a�!R*���R�  �Q��g.iO��@��C7g���&���`bc���@DDDDDDDDDDDDDDDDuKV�}�}ee���k�]���f���3g�������0{�l4k���������O?E^^^~�e�����x��G��#�`���������m������6V�KMM���S�s�N�����p��y������g�y�&M2O�.]D����1f��1}��M�KJJ��-[�l�2dgg.]���s����?6���S��e�c����g��/� �������G����M�+K��c��	�����s����� �����X�`8(,,��O>�s���T�Y�r��^��C��;w���+W��)4���;r��1��W�^x���1h� �=����K/������8��W_��Q��}o���	��w� yp���6l�����Uii)�|�I$&&�������W^A�����7o���e��q�Fc��3g��K/�����8���iii���p,]���'N ((��>&N����b4n����.��w���}�0u�T��*,,������k���7��������L�ne�M�6a�������/_������+�X����z�5k��c�b�������`�`0��?������a��t:�_|��#G���7���>h�}y����w�^���-[��Q#�X���E�?��c�k@hh(,X�Q�F�$L������g���[����f���[�����_|���Z�ha/((����1o�<cR��;w�t�R,_���}_�t	���$�GFF��7���!C�P(��yyy������[owccc1s�L|��'�����`CT���*R~{[W�������}���j��O7V�l��%,X`�������@DDT����h��^�GFF���
��s8;7GQQ��X��h
$����[m/���L�+��wZm:4�$����$A���\^y��������a��-�H��W_a���&����`������;�M������z���1i�$���W����^|�E�?C�5&�����/_�0���I�Shh�q�R�'O����k�R^PP�x�
L�0AP����>����T*E��O8��a&O�lv�F�a��13f>��C��z������8x�����W/���K��K�R��������3�f�w�:�,Yb�t��{w�5����>���{?QQQ��q�1i��D�����#����1A5))	���+}�z���}O���#k���E�����'O�NNN��s'z�!�m[�h��>�={�T5����1a�<��c�}/�g�����u�h�bDDD��HHH@�6mp��Ab!p��6���C�����c;v��������1f�l�������r�/���������y�K������O>A�>}L~�����sg�[��?�8F�i�o��e�I{��������d��o_A���\�x�g���3[�l1�|wO��M1e�L�2g��1I�3���[�������D�\]]1k�,���7o�;��c���SZZ�	&�/^���z��d{wwwL�:����A����_�i��!,,�dNM^�����4ib���I���\��;��J�����G�x���;?�~�� 1�~"�����������S[h��|����ju�����H�r89�W�����":�W���T""""""""""""""""��A����Z����`����s��^��P�7����������&��5u�TL�2���:t�Pi�^Y������o!��s�����^�Z��w�4a����`|��g�vQQQ����]�f������J��������Ot���+V�0���o�Uz��R)>��#A"��M���������a��
�������[o	�v��]��UJ���$n�����	{eM�:/������J�bBCC���_V�����#~���d��Z�n-H��t�~�:Z�l�/����}������M�6��������R�X���x###+�]*o�������X\�|���U������@�~������M�+�{������x�e��UZ�����F�^��m�J%��Z����q��Ec��^��D��


��?�(�f������`CU6!���i�����_u;v~����?����2gerrr���}�Y<�f��7��GDD��D$%�>����V����������Iq�
����FdV�)�(.�4��hR��Gt����"��r�i,DDDDDDDDDDDDDDDD����<���ym�a7�����{�V�~�����ok�����c���P(�x�b����������P\\\S�Z�j��={�����^
2������c��	nB/�l�"�T*Hp�����
j���^�h��j��d2��7�X�-??{������m����7�%	�6-Y�����{����^z��>{�lM�e�={�����6����1c���.]�_}�
����r�
��kg���������������c��s�J�5j��_/��;wn��&��F�����o����3Vkk�1�8q"�y�c���c��Zm!%%?����-�J�i�&����

����/��?~��j���g�V���������������8�N�:��G5~���s't:�I�eM]�ih���Iv�V�+>�U��J���	�+Sp�G��>}����5k��������I�

+��}��'2�/����# ��?�D����zr��?���t4�K�� K\n��c!""""""""""""""""j��?�Vkl�1��$/??�J���JHH�����8��Y��77~_Q�e+W��������������{L�0���C�$N=z�&q��<==���Z��R�D�f�����r��������I�,�|�T*��c�	��9b�\�L�q��Y��9c���h��;
���G��hn�N����D���'�1,{�j���~A���?�V�Z��z�G��()�v�*h�;�dff"66��~��G���mU\��
3~���/z�k�:�Pi4A�������+=�M��*�V��\�������[�Z\s����������������gL�#"���B������XFF��CvC������cj���8�P�{Z�%���.�&�Y����0p�@��[�}YiiiX�z5�~�it��	�5���3$�����~k�WXXh���-����+V`���h����� ��E�<~��q^FF��}:T�~����r�JdggW9N��������uk�������*�Y���+U���n��YU=�����}NNNM�d��U�`���V�2d��}�Zfe��mwww��*�{��mW>9$$$����ssss-�����066�������
�R	GGG��r�d�����U>�������-����0������`����M@��%5ql��W����q�4���Zz�'NT?��d���o��eK��QXX��S����
����WC`Yj<Q���/��N�Z]a5��B��DN�����X��ZH�r�YU����D������F��0��8��g2�W`���������������������xA�|������d�����3_}�U�����
gg�*������1c����K��`������K������V"z���1�|0�F�~�n���iiiP�������!�H������#��O�������{{&��s��mA�s��V������mi��������9]\�����������R]=�G�����q����)�&��n��)hW%����c��_���|���9s0g���+C�ZR������
���5)_y�2��o77�j����/c�����D"�g�}��#GZ��7�|��9����|�I�bj(Xi����[J��liw�Je�hj����h�^�Av�i2_uH$R(�D����y�W���)Azq�Mc!""""""""""""""""j��'/��zTk��y�&�����_T9a0�ck������v��Y��=��*8���������M�9�����y�	///4}����*\/33�JqV�.T{���{�IVV��{�T
�Ri�|___�����"�T��W�=����������O?���������|r�������cm�kIM\��Iv�8)�}u������O?�T��r�JL�<��}�<y������"44��15$��GDD�-�T
___���������������T���;��������Y1P*��t=�"EE��k4)O����B���i,DDDDDDDDDDDDDDDDD
M~~��]��Qe�W��Hqq1��;w��[�j��M�6

���+���U���}�������*33��7I2���3"##��eK4n����P(�8g��eq2Ihh(��=��>����CRR��6Z����C���o��^���K���n�mMT����6�'�e�����C^��}�b�^������^$�988�_�~����������B�\.�;t�P��X�g����j�=�%��6d����u���]��Te���&�.[���-�-X�3g��j?o������K�.����]�x"&��}���_4i�[m/88����T�o��HO7��Z}h1���)�����yP���;"IkZU�I{DDDDDDDDDDDDDDDDU�������km�����h����B��=l���rp�����'�Z5��J/�����k���F�a���x���*�����[Wu,]�TPi�U�V��ez��Y�\k�\\\0�|��;1118p�:��'O���H�mqq1V�^��{����#&7��_�}������������{�����1y��s`z~���l��f��%H�1b��_�&M�T8��+��U�g<??���d]W�Z��k�a����gE�lyl���i�'N����V�/�}��m��a����7o��o��X�x���*�z���*'k�}p����=�X��UW0i����k...pss3y�����i���J����(���&���]Fq�NNJ��%��'��_m��I��e��r���%�H��X{Lvvnb��=g�&��zk��������a����m������;v�w���U��V�U����{�B����������T*Edd$"##�p�B������������u�V��q�����W��~�M����!�<�@��ih���o��$�5�����=�^���,x{{[<������De]�v
qqq�v����O?��������~(���gU*�7on��m���$00�.�[\��Iv�/_�j��+W*�_e���+���+����{�V��j?T����@DDdsOf(--EVV����?��������t-88��AT�IE����X\^���*DDDDDDDDDDDDDDDDT�����z�Wi(�'�]�x���.\�h;�^�S�N�]�v�8a.]�dU\U������Fz�!�����o�8��wo,^���]���k���{��
���x�o�FII�M���
��]�zSE���mN�,h�?�����/�?"K��0S�L�(a����[�����O�mm[			��&��SU��
Y��]�c���_;&&���U���s�='�/{��q������O���GDD�=���T*����?�`(ME�2��6_O���hR��":�S���"��4'""""""""""""""""�����P�e-�"r�o�6P=z��>l�|K����Dii����������]CRR������������	���y���I��H$x�����SO	�����j9::�o���vaa!N�<i�x��uO]������]�}�H�d��MDD��}����������,U�s��?����DFF
�����A�mk�_M��:��
8���:�v�n��m����\�~��vww���-��{�n<��S��t��#F`��-f������~�}��Y��e�����������I{DDt���d&�������V����|�T�S��m��"P�_�MEg7��'q��6����������������������G���u��>}������P���U�T'$����������[g��7�w��,e�8�U�F����mz�!A{���5O��l�1�
�+����Y4/##�N$����[�l$�V$++;v������f������f�V�M�6Y�Vu�!C�������{�nA�T}��;�7o�����k1�Xrl�
�
&���g��v=��E�*>�'�xB��6h� l������mN�^���X�%��W~??�j�U0i���������n�Hj��L��V����[6]�\���P
G}��*D���GDDDDDDDDDDDDDDDT�������J:U������5�F]��������h4X�p�Es�|�M�'|||�'N��(����sV'�)�JA;>>������U|~��7�����u��|r�����6S�L������}�v����5O�����P#k�J�n��~���yK�,AQQQM�T/6��53�����f������[�d���H�m���1��������z����@��!�5��	�m�^���z���j������^{
999��?,�6d�?����v��J�YW�T&����G����1r�H�50""�v��B!~�6������������YtL�R���\]����>���-7-�����i4��p��c�Q}��72�k�V�L�
?�A5���f���H$����k��7�T8g�����q��k�d2�����NII���++�s��
<���())�x�nU5777c{�������hn�f�dl�:u
��}�sbcc1q�D�b|���q��a�����29���w7����o����������Ob��]V�w���?��m:t�`�>##��j
����D"1~EEEY�K<����@?��C�I?7n�8A����d�1c��o�������6m�d�$2k�,��G��>}�������7*�������>�z���6�n��5����\nl=z&L�V��h����k=A�����k�����Frr���())��_~�����]�&������bO#F�@DD��������������b<������4�EFF���p�K�.���B^^���k����{����&��H$���+..���5����E�l��'�8@.?�M�����yE(�gO'!"""""""""""""""��d�h�x4�Ry�*��q������}���������`�3�<�W_}���`������K�6m�y���3i�$A{��yx����R��X�r%�������D�6m,��(�J1d�c;;;X�|9v���?��C�U>��|��&M�{�����\A��;w�������GVV
�����_�����}{,\���T%������mC�^�p��mc�.]��G�}��3��7������c�a���8p��h��F�All,�}�]t������V�6l������c�����m���+8��n��p_5���WPQR����G����M�E�����8q"�N�
���-Z�;�:e����[�V��~o��&RRR���u/���L�"(|0~�x<���v����-[�w���v^^����m���Tm=�<���_|�����j��
�|���K�=�6m�������������7I��m:t��/��R4����;��q#
�=zX�h^Sd2~��Gxzz��?��;b����v������4���/x�����(\�rEt�����F�1�la�����bv���T1���>����~��g6g��lw��6�����O&�a���?%%��
$����b��98}�����}��*������������D��z*�
^^^�����~��=g���}z}1�R'���PB�5�0����������
\���M�#"""""""""""""""��O.�CP�8$'��������\���h��~6���X�r%��9���8w�V�^�5k� $$>>>���@||�q���;��['H�������'����s�5V�\�U�V�U�V���Bff&��������������$\�z���3s�L����xo��k�0w�\�m<������:���k��s������?,@�6m������t$$$�����o��			�y��,Y�K�,�L&C�&M�T*������l��u������6m�dv�R�[�n�c�=f�~g0�c����r��������F�Avv6���#8���4i�.]���w�#�UTZ�p!-Zd��mm������������������+��E���d�s�� �����8q�1I�~$���u�V4����V�z��w�l�2���@�T'����>��;GM
�|����)))7n�����U+H�R��siii�9������o��[7������3�<#8��;�,�s?}�t��u�V�2���yQQQ��d����Z-RRR���nq|���M���O<��1�0++�x����E@@\]]�������*�����[jj*�j��{�����{E�����J+�����������C���{w4n����HNNM\�b��R���W��TT,((�SO=U�<s���������spp�R����2[n��P*����t��9g������5Z*g�Dt<.���%"""""""""""""""��%���Y�Ipsk[�����E�f���'���{��Exx���`0���[8u�� a����v�������#v���V�Z	��z=�^���'O���������x��w�~=��,��d)�R�]�v�Q�F����R\�t	������7��.�J���b���V�U�N�������'O����&����?��4����������o88k�h�Z\�v
'O�����q��m����M�V��R���?�_a�
������"||~~>��?��g�
��]�vU�g��	

ELL����^����7q��)����~������"���O�>����L~'����3g�������/� ,,���>��#��������v�Z�s�N�3^W/\�P'��4hN�:%Z�.##/^���'q����!�H*���e��`C6g�|����d����d�9s�$aO&�a��U����m�0����GDDT��?8�:�A�<=�B&�r�����Z
E��1]q:��W���3-�MDDDDDDDDDDDDDDDD��L�����|
E�Us� >�������k(�����������(~��L&��1cp��yAu:K5k��N������P(�n�={�`����H��]�W^yW�\��0x�`4n�...�/,,g�����Mn��G"�`���8q�f��iUl���X�b�WW�{��j��%�~�m\�z�{��h
�\�W�^��i�,J�k��9�M���{�ZT1��������f��9!!!pww�TZ7o9����z���A@@>��#������v���j��	N�:��7�C�f��H$���v����~�
���v���g�}G�A����n�P(��s����KU�Nw+�������;�{�9t��J���$��_~7o�����j�^����|�I�����7�R�5�E������]�0x�`899U��L&C����d���qo����v��6d�f�����1b���\�T�Gyg���k��f���$�'$��\�t	;v4�/^�X�n{��������A�����#�;J��t�Idp�8U��d��`��s���jM�
�t���������������z��d�u>�Ng���T����f��o�$�V.r�e����z<�����j��DD���`"����0Q��9���`���JKKq��uA_�V�L�n�WZm����F�
�6
z�?��H�r����P���-�r�Z��~��������k��R� �����H����x��������q�rrr�����M�"""��5����V�q����}yyypuuEHH���c�*s:�W�\����������<w�F�����kW���T{���K�.���K���@vv6�r9<==�����q���^��HKK����������(�Jt��f5����8y�$������ooo������h�",^���f:�]			���AJJ
�Z-�����M������]]p�~�{U��]O��}{t���^�{
q��	�������DQQ�������6m��]�v%��e��`C������h��upuuE�-��o_�}f��������������t�(��tm
2�U��5�1�T_'������N~�i�!�H��������dL�� //�A�����h�^n��()�����M��H$P(QPp�dL�IA�{[�y���))��#?�5$r�/��~��o0��`�A"�A"ql����T����WX������������mE�T�������d2t��Q��[$�]��/5j�q���v�V�f��Tr-��7o^�*�UF"� ,,aaa�J����`���6�����
���o�~N!���DDu����8��T���h�$i��I�����7A�g/4s	�c�
����h��T������������h�o�?������R�-��SQ������fqQ�"�H �8�vDDDDDDU&�����]�����U?U��'&U{�U?b�/���j(��������E��j5JKK������@!o,:�VG�t-�"@�_�����>f�����4"""""""""""""""""""""""[b�Q�Y������Qp�Z��Qp��7#�8�F������E��z=222���H$(������h��u7iO":���"�C��^\^��b """"""""""""""""""""""�5&����*���=
u�6�_�.?�~���j��������Xzz�>����4�;(*�m�u�R'89���i�)sO�;�[h��A"""""""""""""""""""""""[b�Q-����[����56��V��oi����t���D???����4�joJe����VG�t-�"P�_�IE73��T��H���4"""""""""""""""""""""""[a�Q-�Q��Y���
u��Q���}�������T*;Fb_���pw� :f��=�6���+@\n�M� """"""""""""""""""""""�&�����7q��J��q��
n���5*�B�����t:;Gd?Je�h�:�8��R��c.i��E�F����h\�������������������������nb�Q-:�k�u��i���\�=�N�Zm�h�G��+����#7����qtTB*O��hR��*:�J{DDDDDDDDDDDDDDDDDDDDDDTW1i����d�#U{�.k�h�@]�n���R	�1�Je�h�����Rg�1�:�f�H$���cM
�y�����+��`�YDDDDDDDDDDDDDDDDDDDD5m��E0�/""j���GDTKn\��z�u��B*����Wt,//EEEv��>�R9��{����Gm��B(���� �]<i�@����M� """"""""""""""""""""""�&���tm�]�S�y�������XC���TF�����Gii���1��WZ��6��p�����+�YDDDDDDDDDDDDDDDDDDDDDDD���="�Z`0�Ql�d���4���"�����edd@���9"�Pz��7t��:n�u����*�ws:���=""""""""""""""""""""""�{��GDTJ���5v]S����Pb�5s��JJJ���m�`�����N�D�2�16[G&s������F��0w���L�#"""""""""""""""""""""�:�I{DD�@g�������nC����T���R��j��H$(�������6]K.��hR���Ut�JA
u
��!�_L�#"�2����u��u�L����lh�Z;GdJe�hQ�m�m�u
��=�6
]���c:p1��������������������������na�Q-p�8A.U�uM�TG��]�lh���������1�Q*��S��m����=�����&����=""""""""""""""""""""""�c��GDT$	|��'��_�F�H$v]��qss������J���`�sD5���nn�E�����#��Ab�e�6]�]D���2i������������������������&��?�xe���o��"�Db��^qq1rrr��}(�}E��Y�`0�l��D"�\�HtL�IA7���8&�Q��="�Z������kk��*___�U*����e�hiir�.�l�B<�T�IA����DM12�KmQu1i�����8�!@��.k��@��g��:GGG(�J����,����9�����T.:��<j�u������,tv���w.���������������������������`�Q-����N����:��~�����t;GS�d29���V�Y16[�\�=�2d P�(:�[`��������������������������I{DD�(��Z����5Z��C3��]�~����\���J���`�sD5O��+���s���6Y���2����F��n.�cgsYi������������������������&�����!p�����]dn��R#���I$���4
��m��V�(�����������
E���V�����I{�rd�$�OL�#"�e
�3�7�Ta��:J�0��(d�6�/����gvL�R�1�psk''_��Lu���Q(E�5�T��I��*�����f1U�����'?��`��{�27x;��l$���ooo����L����9��%�H���+:��C��^�E;�3��rmQu0i�����q����Qh���&��.U�r�9�������������i�hj�R�O����&4�d��!�fR�K���E�"�����ODDDDDDDDDDDDDDDDDDDDDDT]L�#"�C2g�{��F��I��w*�(
K�m����������J��s45O���ju�M��J���+:��������+�Q]��="�:(��F>������ E0�Ra�1�T� E���7�O��'��#���D"1[m���
���\����E���h���P��k�)3���g~J���@DDDDDDDDDDDDDDDDDDDDDDTU���t�CO��Ia�%����I�(q�D"������M(5����z�e�u������}T=���HNNS�T		�sD5K�����k&���c0��H��<�"��L���tt�s���p�������������������������������������	�D'��e.p�:������z��{T�t�=���(
xxx��edd@���9�����'�_R�F^�e��a��`@�CR��h\n�M�'""""""""""""""""�_%$$@"�����j;$��BTT��w/!!�����|�	F��&M����Y��E��X�d�E�	����Y8t�Pm�DD6�J{DD
D'�p\�����L����L��{]={�Bd
���?rssM�u:233���WQ�/���H�`0���3������k8:zC*�C������S����rL������j/ODDDDDDDDDDDDDDDDDDT/����9r$n��]��58%%%�z�*.]����4������
>>>���3:v���������p��q��}EEE���@�����_?����t-{(--����?��j�pss���/�t��������%L�#"j d�)��i�����>����� ^��N�TB&�A�3�f�R�T��L�/����:n2���F��/V{
�D�<EE�D�hR��X4i����������������������~����|)))�
Q�����c��}���FQQ��m===1q�D��1�Z�������E��V\trr�����d�4o��Zk�IMME������%�_�pa�*�^�~~�!��������N�T��g����3��iS����n:"Qc0`(��P\z����6�����k{����W��0�KR��lb^^^^���#�w?����3��l�Z�@�~�&]��E��j�Wj�8IDDDDDDDDDDDDDDDD���`@^�����+�W����D"1~U��q�\�c<p����,�|�rA�^HH��}���/��o��k��I�%Q������j;$���Z-"""�9s�`��}�������k��c���������`0`��98p���=(..��_��;���z����_�2I����>��;w����+L��Z�U�V�c������l�~]�J{DDu�>O]r69���j��2	I�2H=�x�@��Rw �{n�@���d����Xx�\B���~~~HMMS�T�sD5G��7o�o�o0#;;>>���B ���������y����^����������������������aGZ��
�g^��<���A�N��sw������M���DD����������bcc���[��_%%%8y����B�@`` |}}QPP�7n����{����1{�l���c���V�����b��5�>�D�&M����������0�`�����m�q��2g�������l���K��?���I���Z�j777dgg��������������(c��)6��.`�="�:H�����MG_��V:����=(�A�Y��tG_���M�T�pqpC�H���Q��R}I
������+\]]E�222����Q�qwkGG��X�:�&k����t(e�cq��6Y������������������c_F;{�N]�U8��/H���R�f����*:u����?2sk)b""���y3���y��n/(40z�h&��PHH-Z���������[�����K�������������u�L�*��?�l��O����HLL��3g����?���;w6n���������rdVV�O�nl����N��[o�%�k��	�n����\\�x'N��_��Z��������0nk0��+�����U���a�Qb(.E��D���
C�u�G��B�����s�h'�_'��rKsp.'��R9�����������
�I$R(�����m��'�9���KtL�MEWw�r{L�#"""""""""""""""��%�x�R��3'r
��{"�/����oC]RZC�]��]�;t�PK�5,}����={p��M,\�}������`gggL�8qqq����`�����Z��t���b�����_|��mC�V��C���#Gn��������}y&f�����4@XXX���-Y����n��9N�>�'�|r�\����^y�����4
V�XQ��&����"h��C��S�����$�&�����\�I��dUk2����T���R��M�R*���\�V�f�5�U��hR�a&i/�I{DDDDDDDDDDDDDDDDu���"�����j����,���+�E�	����(_H�l�Y���	������1l�0H$�J�x{{�����:]vv6~���J�~����Jy�Z���U�������/��NNN��o����W�k��w�^|����L��>�2��J�*,,��}�}+V�@�F�*���cG��7O����?W)���I{DDu�>������FO}���=.���D�u�!F�_��N�'�����#:���
�Vk��j�R����Zc�5�r��=�6
a�
��m	R��6Y�����������������l�r~F��@jq�M��Z\���n0q���+�F��$�����srr��#����qc<�����={�T:o������y��P��}O���1~�xc[����/��"�`��i���������Wi_p��m������x��G,���O�)))(,l�\j;"���������mw\�C�������<�����_x���m��}�������c���h����#�
Ec���@a�M�1�:���m��x����C;��?���"����8�uI)�:����W*�T�'�����m�t���b�z=�;�k��!55
�������4����������q��Udee���^^^���G�=l���C�R�����y�&���QZZ
�R�������^#55g��EBBrss����������c��pss������$�T*�d2����}������������8y�$�����A��=��]�]��E���4������???��7o���������l���b��	����h~ff&�;���$��j����g�����k�so���'N 99��7���T�WU���c�K�.!11999ppp�R�Dpp0"""�u��	W�^������Z
�B???�k�]�tTD����;v/^Dvv6<<<��iS0���6y
���8}�4������OOO��~u��5}�K"##�n�:c;11��������g��nnn7n�Ek=����������;wb���VF|7I�������`����V��,�Z-h�����������53�������K�b��/"�ZVr9�v����0T�?��.:|L}M���Q�'[qss���3��L��T*����C����I{Y10�~�r�/$�?���TV8�����^\n!��yUkm""""""""""""""""��7���Y���R�K���IX��n$��:��V���U����l2.��0z�h�X���7��qqq�����w�^�?��d���P��1S�N��Fns�-^��/6;����8p���`0 ::?�������W�V�v�N�0k�,<���pp��v�m��a��U8~�x���d2t���=��O��Ri��cbb�t�R8p@P��,����={6�����k���8|��I����+��k���X�h�E����q[���y�fL�<�����/%�mBBBBB��g�}�7o���o��&N�>-:�]�vX�|9F�iQ\QQQ���/����x��������'^�=�Wz��7o��U�p��E�m�R)z������[�Z*:n[�l����k2�W�^��1s��_��`���(.6�0,,k��E���M�<�������&c�#G�����E�G���p5
~��W���O8p�RSS�n+��0d���7��_^������l�����
��������~�-���o�����b����:u*~�a����j�X�b>��#�D(���3f�/_^�d���b|��'��a._�,��D"A�����[oa��QV�����uQ�$����
����_��}����������c%��W�����h�����;vk��5���[g����O�������J��z��P��� "���T���T|Q�.�t�����X�.g�+�@D��H$���+..��CX}����/.�@~A����D"�\.���6a�OO��m�������������������}9�����5~J�����sNu��j����g�M��&�m��
]�t����^c��5���V�X�s��U�<u��-��1����q����U�������Y����=���?�A�A�RY��V�����1n��J���>...T�1������C�~��{�n�	{�������h��5N�:eQ���Db�2�W���3>����=�r�
F�U��E5%))	=z����?o6a���w��	�5
��G^^^���j�x��'��3��&�Yb�������m�&�l�M"0`v��!�_�x1�"�l�Mh��kz��e�9���k��_�~3f�n�Za�p���w�^4��OGii
L����~����X����=��9���F�a�ff���$DDD`���	{��c����#<<qqqV���'O�m��x����&�w����O��G��Q�PPPP��k�:X��/III�veU���;'h��������g�
�W�V�)S�@��������[<����[����m�g����N�:A�PT;���I{DD���V�]�����?�����Pg�%�������'bX������'$��H��Gm��B!�����O�;�W�ON""""""""""""""""���6�>���k��.//��
3�	Z"��y��T�������>�+W�X��F�1�swwG�6m��gOt��
M�65�����������Tbqz{{�]�v��^���&�DGGc���U��2e�I�p��]XX"""��C���Y�J����m�6��&M��{������I����T8���V�I���������vwwG�.��.X�?���=C�T||<���c�$#�J���p��]�w���A����e��QQQ��p�����������1117n��wQ�P�]�v�����'N������-��E��I�������3�v�
777����T�=%%5S�6��c(vnn��1:v����t����z�]���M�����k���_|����~�L�������:u��9����l<������ ����c�������3220j�(���Z�����
B||������x�n���I�����}�����`]w�������[W�}��[����j���[������6n�����?�����qrr���?.�+{�4�`0`�������&1�L�#"�%�<
Y��&�.AwY�8�Gt�>���S�������j0��spp��g7�1�:�&k(����ltq�������Qh�)RDDDDDDDDDDDDDDDDd_W��p"��
-�p"�W�+O�j�f���3g�����OGBB���q��)������[x���M�{����^K.�c��q����p��m����������'q��$&&"##�|�	7nl������S�����}��o�>|����g�y�8&���K�����c�����};����V�q��e�8qqqqHNN��;w�l�2xyy�]�t	s�����:u
[�l1�0o�<$$$ --
g������q��E�T*���b��m�4i��*��^�	&�O???����HII������O#..�D�{
���O"33�d�+W�4��:w�\�1�4iR�17TG������z����{�V�q��E�:u
iii8x� ��m+�������*X��`�������g[�^�����'�Dbb�����s�������7o���SHHH��70e���3g����^�*����}� <<{��1��g�"==��GPP��}L�8���h��16o����L\�|�x�����f���/,,�����7�|��G������������3���$C]�|�����5�u�6k��f�����������$����8~�8.\����,�?/��d�����/D���4�6L0�e����o��Ft��IbShh(6o����t��u����p�T*��g�	����5k���/888`����q�����S�N��?�Dff&>��8::���sK�.�t��.]����I�������_���c�n_�rj�6l@�F������b���f�_����.77��o�UV��|5J�T����V��p�� An������/^���l�������<�F�i��a�����n����_�YL�M�<�8]r�]��P��].�Pg����\/���n�SC���/�G�������2�GJ����6-U���N�L.2�r�����c6d@'�9�lnZ�6���DDDDDDDDDDDDDDDD�U�7 Y[\k���a��^n�o�5�i,w��TR+k�s��	l�����H$����0q�D�mCBB�~�zt����MCBB�Uk=����4i��+>�>>>x��1~�x:����k�.\�|Y���<&BCC�c��<y2�}�]xxxT�]PP�x�
L�0AP����>����>��|�
6`���f�i�����1c���?�^�7���������z���]�D��T*E��}�o�>��1k��p7�c��%&I'��w]�����c|?�����7
����k��#G��kW$''���������G���e��;w����oo�{�����������v����z�d�-Z���>C��=U����{L�0�=��Eq�������[���N@DDD��HHH@�6mp��A�/p��6���C������}���;p��y��z�3[�n$;w��_z�%8;;~g?��s���+����.�O>�}��1�]*[����n�:<���9r�1�e���T����@�}�e��o���J���x��I���1c�e���w�4m�S�L��)Sp���*����ur�?���h����+f������5}���x��wL��{JKK1a�A�������[oA"1�������S�b���4h�������1m�4��������`]��;�*0�����G�pNzz����I��,��lI�b�N���{�X|���6�h��eK|���;v,�������7���_�����c��pssCvv6��=��[�"))�8�k��������,�GL�#"�%��T��G�S��A��?����Cvn���N�����\n��AY*�
�t��O$n��2������9
��o�������
:]��`q*����O�'���bB�O��&"""""""""""""""j(����y�Jm�a7��3�9�����������������M����&��5u�T���b���V����u�������~��m�o���y���KM0��fNpp0>��3cTQQ���;���]�f������Jt>>��s*,,���@���of���J�����p��i�8q�i�&,^�XPE���
6T�d������zKP�n����N��.�Ng�������&��5u�T�={VP9m���'�w�m���K��=K8::��~0I6+�u���<y�1N�N�����e�����/+Ly��g�l�2c�����#%%��h��1�����5:�g��;���n�7s����������_�~����!�J-�o��g��e�Vi{����z�jc�J���3g�&�n��/^4�_x�,X���X������?�k���k���+M!����u����~(����#�6W^QQt:�������u�o_6i���+W� ���a����}��Q8q��O��c�����/,^��������������m6����LADD6e0����uM}nB]������x������SC&�H���':VTTd�������#<E�2�Gm��B ����"�C�Cm\�}�b���������������������l�����V(�$]����''��
��U�V�����}����f��!�d���,[�H*�Z��Q����
j���^�hQ�	{��d2��7�������={l�9�7o��`0~m���F��
K�,����q���g��TH��g���oc;883f��h���KI(����r��d���������`�;v,:w�\�v�F�2��;wn�	4��{>������.�:����I�5y
III�?�`lK�Rl���f�����������m��/hWt���������������8�N�:	�w��i�p��u���x}Q�T�0a��x�����O�p��=�
�uEw��O+�/����X�h��=�|�i���5��#G�`������}||0s�LL�2��%�L�#"��z���K�*�A�7���H���/��C�6��q5`���f�,)C\H$2(������16YC���V������.�A����������������������������j����#,N����������������1��77~_Q�e+W��������������{L�0���C�$N=j����<==���Z��R�D�f�Y(�,W[>,hO�4���wJ������#G,�+��L��5v�X�������-�H0z�h��v��I�NLL�,�z������f�!���$d=���h��U��7z�h����k�����sLff&bcc��Gy���V�5l�0�����������u�V����?.8������uk��X@�1-�c�C�'��M�,�`0`��)�m��o��s�Z����o��6m���7��06����o����,[��X���`�Qm0jg]��N>���Ct��3��P[�50NNN������Dii�}�!Je_������gT{�����z-:9��������#""""""""""""""""jh����j����������W����F�N���Q#8;;C"��|}����y������mK			X�b���v�����r�\4�����ed��j������O?��+W";;��q��������[�����}����������2�����U���>�?''�&B����'���[5��!���',���m[���[�Vy��w�h��?���/K�������,�z�����X��?��Ghh(�J%M�����*:7WW�D��Nl�x���E��c�����[��=e��kIM\�*�^��'
�<�d2|��7h��e�����[C�4���=���7&YK$l���F++��1c�����7��,2s�L9r���(..�J���={0y�dc�xAA������zJ��c}��="�� �������v����L����\��`��4s���z=233�M�P*���RW���\����Li\e�g�r��6Q}/h���T��U�,������{AAAx��W�u�V\�x*�J���{����m<��c

�o���������BFF�E7�W���c��}{c;??���:5j�a��a��e�����xw� �j��}��e����������(�?�����quu5~o��Tsn��-hw�����]�t�-��V�2ZU���Y����K�������-��cx��Qt���z��{�����w#>>YYY��������{���f
k�1e�/��c]>�n��9V_GF�!�����&��u��/��������}�F�i�|777�>k�K��[l�p��������i����x�[x��w������n��%��=�?�����d\???6�6m��#G	���=�,YRc1�����j��p�����9���Onr�:����'��fA��	O����e�T�J��s45���)���E��������J!�����D��.�.�cqy�&"""""""""""""""��K����U�*c��7o�DXX����jUE)_1��bcc��K���SPq�%�9::���F�6mL�������Cdd$���0h� |��GHKK�p��x(|]��V�UT��>���2~/�J�T*�����kv��B������gU=W�Uu�~���0`.\�z����~�ON�6q�Z5q��u-���`]4o�<|������+Wb�������2�0������8�oo.i��_D^^ 00��/�jk��q�/6��r9~���n���y�{����/�{������T#q��Cm@Dt?�H$�z(����[RgH�T�vn�f��H,�e��V����#�����k��R)������l2VPP�����]�GJe$��n����10���������&9j4)�h�c��&cq����""""""""""""""""������������8�k�0��t��v���^Y��N���=����h�W=��5�2c����s����U�V0`��i��� �����Yx�������{�Z[Ueffb���&I�;wFdd$Z�l������
�B��Y�,N&	

���g��Ga��u�7�k�Z:t��o��^xK�.������5Q=J���|�T�=?X{nL��A*c����<��^zI�l����~���W�^���?
�r�`���C�c��qs�Qu�=�%���5��-��e�},���3�����RSS��;w� ((������XB��C������������iu��Z�n��:���>k��i��!C����?����`���x��7k$V{b�Q-�x�vL��x9�	�*� )9:�i������['(,�@��%�w�����{m�Q�ER��~mq

������$TF�Dn�y����tu�Cg|Q1�%�P:�����4s�W�a
���f����^n��zkS����B���5�^��_�k����5������C�?,���?�*��X�t���P�V��e��������&6���`����;w.bbbp��:t'O�DQQ�`���b�^�{����#GLn�/�v������[Oy����oD
����1y��s`z~�I6Tw��5K��7b��_�M�4�p^MWf-���x~~�I���������^��#������
���u�.Y�v-���'��1c����5��i#H�KLLD�^�,����(h�m��d��	�c���.���x�b�������;g�������#GZ����#�I{p��&�Q��{Aw+�~�z��y8z��gNeG��9��O4��DZ��5l������@nn��XFF���!���c������dL�c���3#�w2��w���B�����DDDDDDDDDDDDDDDDT=�7��Uv[�1/��U�xyy	�V�/��V����N���cz��m�\�ZmU\������W(����+L8(��qJ�RDFF"22.DII	N�>���[�n��7��^�zQQQ�����(�b0��T)���l5DkU%Y�����6&���zdee��������'��%*���k���3�;v���~�	NN�W����C�T
�*�
��7����P�Zh�k�-��u�W_}�W^yE���s�a��UU�g��mq��ac����V��r����j[||��mmQ����Uj���w�Q=&uW@�m}y���x�B��������pR���R^��Y���t:�]�QS����EtL�>Z��;:zC*���A�FN��!��������������������H\;7gDx�V��
Dx�����[M�|2������������8u�����kW�����KV�UU���HNN6�z�!�����Ln@�*GGG����/��k��v�Z���w��mr~@@��2����QRRb�x�;�Bx?d��MIO�_���&88X�>��U��o_~D�:q���=e����]?���Y�:}��������Pe����*������s�='�
9n�8|��g�J �����}��1�����"66������U0��1���(h�t��d�#&��"�P?;�c��L���>C�����FA��Jfd�R	�L&:���f�hj�R)�����z��%	�@�1�6a�	�qyL�#"""""""""""""""���L����6=��]���z��!h���b	K����Dii����M���v��U�S���@p�|e���eM�G���$9�D��_~O=���?::Z�vttD��}����B�<y������k�qm�������l���&""B�>p��U��o_~D���������\C"#�����Jp4h��m���	�^k������SO	��F��-[���\Yk�����c�PPP`����A����[�u��&���������k��a��<��3��O?�T4.A��C,Q�����}�,j����j����@�]C�	��G��4uA����C1Nd����/R�������<���SW)�}E���"d������%�i4���n&i/���������������������~0����{���y�����j����#�V����B�V[4W�RY��P�����b�c\�n�������Jc��+c�8�U6!222L�y������W�X<e��5��6���g�����:��R[ ho��E�|[���,���C�����F������Z-6m�d�Z���2DP-l����~��U����� t�����y�&v��]�����`m9|�0�x�	����A��}�v��pU��iS����������,�������>���v~~~x����
��*�����z��7�������_�n���U��*&��2����u�_-&w���Q��D�C���+�St�����*��OOO�c$5���d27�1�:�����D�u�tq/1�YR�D��h#"""""""""""""""����u8U�Fg1N�x�UP���>������?nlk4,\����o�����>>>�D�'NX��s��9����J��o����=G�V������s�N������	���&�L�2^^^����������H<e�sBBB��a+��u�-MtX�dI�x�~U
6��53�����f������[�d���H�m���1��������z����@��!�5��	�m�^���z���j������^{
999��?,�����Oc�����EDDv���Ba�u��yA{��e�h4��r�
���{c[*�"**�f1U��!C�
6 //�����_����+�_}��="�Z&qr�S��Qf�K%p���e	�����%^)
b2���`�UH�����;�IOO�w���J���-:�VW�d�B!��m��������>�/����K(�l{�����v	�����^���1�?�^�v-����
�l��7n�x
�L&�������+WV8���x��GQRRb�:���jnn�<L|�����2�PY��5CP�?���N���.&66'N�*���~��x���,����{w��<==��o�z�O>�$v��eU|g������+��C���322p��!�����(H$�WM%<���JG?��C�I?7n�8A����d�1c��o���&�����i�I���Y�l�?���#h�_�7n��p���~�>��������$Uf��y�������G1a�h�Z���>}����~�i�q�v�~�a$''[����|���X�|��5j�:x���/�.]�C=$H6���+v��-�,bS�N$R_�v
3g�4�DyOnn.&M�$x��SO=�����4��z��'!�����R����OV���R�0z�h��Cooo�9��b�'&��Rw�z������Yw����
JG_���R5.���E`�5����dgg�7��T���������Pf�L�GG��h8�����\t,.�I{DDDDDDDDDDDDDDDDuE;7g�ki��{N������m����w����-��<�^}�U�����m��K/a��i����[���I��y�����_�J��gdd`���Gbb"$	��ic�:R�TPm%;;X�|9v���?��C�U>��|��&M�{�����\A��;w�������GVV
�����_�����}{,\���T%������mC�^�p��mc�.]��G�}��3��7������c�a���8p��h��F�All,�}�]t������V�6l������c�����m���+8��n��p_5���WPQR����G����M�E�����8q"�N�
���-Z�;�:e����[�V��~o��&RRR���u/���L�"H"?~<}�Q��L
O��-���?E"�����l����j����1~�x����0h���Uk
8P�����_b�����iv��-8������o���I���m���C|����I�w�����1h� �����D��"�����?�����w��qt��.��k�D������_~�/���� DEE���+����u�^RRR0l�0dff�\]]1g��>}���Fe_�qrr��e�}�����q�p��uA�����������
K�,����������g��������������|^���������0\�xQ06�|��k}�G��Rw��Z��r2�)6x��(����OM��L"C?�����������h����
�"X|||p��m��z*���w}c.i0@�>�F�FTk�
E�h��V���!�^h��s��GDDDDDDDDDDDDDDDT��ss���m���I�)��7��n��wZ�����+W���3���p7qo���X�f
BBB�������������c��u���L�<�|�	��;g\c���X�jZ�j///dff">>:��8o��yHJJ���W-~=3g���]���C��]���sE�=x� hl��������q��@qq1�����M�6puuEzz:�I�����7� !!��8�\��%K�`��%��dh��	�J%�������[�n�Ttqq��M���S*�b���x������v���;v@.�#88����h4�����;w���&M���K����nr���J.��E������X�������999�<y2^y��h�2�w��$����'N4&���d2�n��A�!11������.�-[���(�J��Dy��u�'�|b���!���0p�@�91%%������Z�j�T�;w� --�8����|�
�u�f�:���x��g��{������E��O��[�na��U���7o"**
2��������V�EJJ
���-��^��i�;v��'�0&fee�Y������+rss���Q��Q�A{�z��I����<��SU����ye=���8z�����}�v����h��)���p��m����T�/��!!!U����^���� �����x����P(��E���!;;7n���2f��U�����������6�c�`H�]��?}f>�I�V�	T4Ak��c��RS�v\�3�����egg[\.��rv�B�DtL������@�~�V�0w���]�+D����DDDDDDDDDDDDDDDDd?JG�k��;� ���{�"<]��s(��f����w/������n���S�	{��k�U��s�N�j�J����q��U�<y�������x��w�~=��,��d)�R�]�v�Q�F����R\�t	������7�\/�J���b���V�U�N�������'O����&�
AAA���?*M@�����}������y�V�k������8�<n��-z|��M+\C�T���������vc���pqq��������8{�� ao�����kW�~����P��������z��y�N�M\z���q��!x{{�)Rj������>���w2??qqq8s�� a����������^���>���C���~��k���st:���z���:��w��A�p��)��v�x�"N�<�+W����DR���,[^�5k�`����>�����D�9s�$a����~�-��c�0-�����{�����hp��%��B��*�3g��7�|cq����I{DDu�����P8�kY?H}�G�p#G�>n����,����J�J�A[bv\L�r��r�����]x����PE����-!�H�V�S��-zjDE�%�:tT�'<�
�ZPT�u�����������������f��������m0#��{���Ax�������0#��h��uk�|<j)�����������(~��L&��1cp��yAu:K5k��N������P(�n�={�`���U���W^��+W�`�<�7����E���3g0q�D�d2�m$	��'N��<_���X�X�C���k�I�-[���o���W��w��������+W�����6m�E�u��7��i��w�^�*�������Y��#G"$$����J��-�>� bcc��C��9�G}��{�������]M�4��S��q�Ft� ^���{��W/����������%5t�>�,�9������F�P������K��t��V���g~��w<��s���+�J��I�/��2n���W_}�$�<///<�����?�7o^��kB�-�]�va���prr�p{�L���{c��%�q��~�m���ql��=,������4�����~�i\�x����c�������m��g�<��#������`��������~X��d}#1T��y"�w.]���;�/^���=����������A����?��_"W��@*dR�?2
�O��!�Pt�4�Na��Z�Rn�����;xbl��p���3Ua0p���&�999!,,�^?! M�/N������U������[k`0���y(!���"m�o��46��J��y�����LDT{x&"�=<�.����j��D�[��UZZ�����Z�jeRu�!0(���� �J�Z�^)��^���h\�v
*�
r����������m��������Gq��
������M�6EDD�5������V�q����}yyypuuEHH���c�*s:�W�\����������<w�F�����kW���T{���K�.���K���@vv6�r9<==�����q���^��HKK����������(�Jt��f5����8y�$������ooo������h�",^���f:�]			���AJJ
�Z-�����M������]]`0p��9cU�{�����o�;v�����B�8q��7233QTT777����M�6h���EIxe��:�P��s��Cbb"4
�����U+����^�����g������������B������:t@�.]j��3��o���/5"�J"������1�17�����Rs ��)1����j�E��������\�I����F�H$����?��;������hX��%y������HBv��UFy�?V�,�Z^(�/#P(���K�jJ);a'������)kY�d�s~��udK��~�+��9�y���,�����FYYYD�������O��
g�D3_1"f��iS�� (����������j�H�m�����7��=�?uk�  E�DJg'��(
L�>��nFm������?���o/F��^zi���T*1b������ BB��.rss�t����o��]���z�~��u��t-c����1c:;�6INN�Yg���s&�<�S����N���)S0e���N�St�^�DD7E����Q��}U�������yN����M���q�H?����z�/����l��Z������1�uM���j�e�{���*7��2�|DDDDDDDDDDDDDDDDDDDDDDD�E{DD=��$B�V>�
 p�:��r4��:Z6&"���������j5�l�f����'8��e4�wa��6@���������"�D���W ��U""""""""""""""""""""""��b�Q"(P�(�V��8��sB�4h���*<e8�>�|�������$�l6'8��e4���.�;v�i�hE{0T� �_����M���E{DD=�"#��YQ������b��i�ZL2��_g]���+G:!==III�1���������R���Y�k�4�J��*E6�'���R���7���.Q,X�GD���B���I�>~��k����������:���6�	!j����F8��uE�J�$2&���Z��|�=��cR�;Cnw���.QKX�GD�	JT#��� x��{�1A05s6����������������1����L���8Uv���~}���j���<��I����;�i�����������������������:����z(ef
�E��q��JH��|�I��6N6&A��2H�w���F�AFF�l�b� $6�v�ha��o�����$�����l���G����u�����������������������Z��="�L5$��dcR����u��1���X���\{���������(�b�$8����\�F���j]���5�D�3$�u��v�#"""""""""""""""""""""����="�LP+�^58\���|I�$L6���`]	o0��������j���dJp6�G����,m,�S(��h�ec)�i�����Q�x��G!IR��\,�#"�����P���%	�=�q}�/I�"m�l�#�����5i�j
����h.�.�+���q��~��8���6����E��cR���m���\Q���="�^@=�P+ec���`�%��A���s���|�v���nU��Y��=���K`&��h�@��Ymk�4�V�/���3cL�F6���
�w�!"""""""""""""""""""""���="�^@���"_��C������P1:}B����%1�{;�N���T�X]]D�{>�IIF����Y�m����DM��e�;"�6z��.QsX�GD�K(
3��J�E�VB������HU����|5����5i�j999���� �Vk��i?F�4��6�z�b�����P(����JK�9��}DDDDDDDDDDDDDDDDDDDDDDD��E{DD�� P
/��o���	���|j�S�gG�o��Fc�o��Zff&�J�l�d2%8��c4L��4��aW��Z�|�=e�C��},�#"""""""""""""""""""""����="�^D���i�Q���������+N�b�@��O�b�ue�9�f
�YYY�1������g�>22�E��g��m��Zm��~��c��ec�X�GDDDDDDDDDDDDDDDDDDDDDD�E{DD���8B�N>����:�����JP������So��ZNNN�X]]]3i?
���	�1�uu����i/t�t������FxE�M�E��="�^F�G� k����y�Tu:���5���A)w���^��^������A���fF�4���
��W����C�����������������������������������>��B�T-T����{� �c/��~2TF���o�^���s���u��������M���Sd�KR6��V��Tj�V�����Z��u�;��^������������������������9,�#"����!�h����c�KPbJ�9Q�[�k�jC7��&33�(�f&�)�����4$%�#Z�k�4�V�/�?�����:����������������������������h����
�GE����8c��HW��!�1���:���s��T*233ecv�>�/��� Q��Y���4w��=���1i,�#"""""""""""""""""""""��b�Q/��H��_V�x`w%���|gfA-$�����x���s��rr������^�q�����R46V�z�hE{@#t~���F/��@��$""""""""""""""""""""""��E{DD��jP.�|����C�������R0>C��������B�X���@���WWWI��Q��t��uM��MJ�� �ecC����v64�zM""""""""""""""""""""""�hX�GD��	*T#
����������6Fu�l�>`����q��	���������HpFm�I�BJ�P�������
�M�l��F�Z%�V��'�/(v�"H""""""""""""""""""""""��X�GDDPf�@Yd�����$�1����9;j|[�8��xS����� �l�d2%8��a��m�j]I
�z^�6_v��[��i��\�s���9+d!# ��Gk���5x�h
��0c������<�����������������������X�GDD��|@#��Lj� x��\y�BN)J�����f1P��0��)�V+���W\f4N�����ao���V��c�^���3pO^&f��1P��dE�G �(����]6'>/�����8���:""""""""""""""""""""""��X�GDDA��zXA�x��	�3�"�����(������(k<w��QNN��~I�`6�^H�Ud���B�$�XW�z^�6/b�_J��L��J����M������XYc�'[�I"""""""""""""""""""""""�E{DDt
e^:yi�AI�we��t�dL0L�_kY��kM��Jzz:����L&S��X�Tj��~�l�j]��yU��T��m���m8u(n��p����L�z�_WC""""""""""""""""""""""�,�#"�0�a�Z)��n�,1�54er��ec����7�*��D�����t:�Q��Se���oC �j��Z����KJ�.��[=���A�T�Y�GDDDDDDDDDDDDDDDDDDDDDD1a��4j����@�P-���:�	�����@� �U�6_�E��Uvvv���dJ`&�#Z��$�a�oj��Zm>�R�`��z9>Q��J<A�]�%"""""""""""""""""""""���E{DDAY�Ef�|0(����$�4W�&�RG��D�Xc�>��z+�F������bA HlBm��2ju�l�j]��y5�|��v����;(bc]}��MDDDDDDDDDDDDDDDD����B����s�vvJD����s�~�JKKc��x��k���/DQQt:]�\�>�h��M�{��G�~>�{5}-�������3Ug'@DD]� P�(�o�! YP'����Pb�����8�:�F��������ms�=YNN�v{�~Qa�X������ZI0���vID������@�P���Zt��%�:��k;t""""""""""""""""""�����]t���:;""j�k����#G�r����1`�L�2���MS�2Qq�����f�


HNN��h��#0j�(����N���h���d)���:-����q��j(�R hZ>Ij�ZL2��
��������\�$��M9�dP�����1������ �8U�h��>��Zm~�s��{�#���9Y�GDDDDDDDDDDDDDDDDDD��b���s�Eu��u�DD�1�n7F��#G��������;��j��;w�����_~	Q#�J�^x!�q�5�Uk4��SUU^x�����0��Q�������k����C���&@��N����.eq&�t�|��_��
�C���l�ta�}mkR�5
���dc.�.�+����8%j�j���`��Q���%���6�`�FOQ��$	��O0_P�$I��u��� ��=�����R�t�s<s���N�b���O������>�,���K,[�,���n��,�:���s���JKK;;%�����/���-^|�E�?K�,�-��`0�%K�`��qx����m����1}��>|8�}��f����/\��G���O?�.�w%��GDDQ	���"��d��k��u@���\S3��'U�BD���=�m�2�I9��{O�����8uuu���	�����<����r����������;���^���hC#���e�����������������bc��q��u,^?|���+%)dj���&�$U�� "�?����gffb��MQ�Q���i^|��v����+���������(((@UUU����@���o!I~����K��������o����R���A����������O��n��������t���o�\�v�#"�f)R�P
��������4�1)#����$HXmY��b5C��!55U6VWW��
]��8Uv�����c�KP����	^������������������:�����f,.��.������=���}�es���:|}���.O'eLD���y�H����_�f�?v�jjjB��]v���:�����7��f��
W��[����?l���3�u�VTUUa��-�������1c�������^l���M���������_�*��`0��W_��n�����a�������������x��'�f��V����h���Z��
!E#�8X#�1.c2�J���Zo:��&�^#'G�a0��jMp6m�h�������<�$����|`;���Y`JDDDDDDDDDDDDDDD������6|_eEm�7P����}�+kl����������C�����I��O>�$��9q�{aa!n���6�w�}�!��y�E]����c��
;n���X�t).�����@ �����M�����}�Y������`��u�p�w %%%�X�V����[�lA�>}B�%Ib�=""�]���EQ���V-���R+�0�8+j|�m%<���s�-233�T*ec&�)����!c!I6f��~��(!����$!��="""""""""""""""�V�z�X\f�Qg��:����e&X����3Qg���a�iii��Q/�w�^��/	m����HM�od�o�����mgff��������NJJ�[o�������U�Va��e����������|�A2��1x��g���X�Ngl�	]����(&��d(�eF��TB���U��OC]��Gl�&��V��(��-�<O�3j=�2�cec�8��DtN�\�����������������z���o*�p�S�<wP�7f�Q���ZAA:)"��OE�|����Nt���/�K/��Ms.\�0l����5��������;����yb���������w�e��4���/�J�
m��~����:��D��!DDD'��A�u@j���Kr����!�-�#���G�o#�`D|�s��D���]��irrrP[[+3�L���o�3j=�q*l�
���-�T�Z����j��������������������	�XVi�Ol��%�D	�*-��8Z%���#�"��[�C����Z�%%%�6mZX��������g<������������3�@qqq���&�	{����#G`��`4�����'"//��k���`��m(--����(�HNNFNNJJJ0b�����z~����k����&�	J�9996l���"�9x� 6n�������`��	:th��+��M�����i�&������>��0e���HZ���#��k���`������������1��X,X�n*++a�Z����	&`���-�=|�06l����*������9���m|T�KW|�;��{�������P�T0�(..��I�����<�]�v�l6�j�B��";;C������cZ��~?��[�={��n�#--
}����3`0��1���c��-�����fCzzz�w�����>&�/���78�����_n�|^��}�]���n�)��7�t����7�|��������j����O���&''#++555�}M;�vW,�#"��	*T#���|L6<f�2?����JW0:}"�������,�/���B��hM��z��z�\��X]]����m�p1�����"�K�v�fdfNoq�(�-�HV$���ExE	I��-IDDDDDDDDDDDDDDD��m4��[����A��1#�}.b�)�� ,X����*"�T*q�e���g�A�~�Z�������`�����sg��D%%%����q���B�k�������?>���u��+0s���}�$a��5����l�2<x���G��{���^{mX��X|��GX�`��_��qJ��F����^����F�1����]�'�x��/����=&''��~;���>���F�k���X�re���+W6{
�#�<�G}4�|;B���)`{��w0o�����o���s��[ZZ������o��F���;��K��O��l�";v���x���q�E�����s�������;�;���d��ya����~V�(��w����g��c
&L��?���1?����E����^��M�"�M�81T0�g|��<���X�xq�;�����W^yg�yfDl������
"
���.�/��R�j�����z<|��W���O�|�������J%�>�l<�����M5�=?��������QZZ���f��>�,���Gt;�^�����q����������^���g�y/���l!�R����_���~�U��>��������c��}����q�������_��}L��G����
m��/AAA������a��<8��e�~�0h� ���O����\��g��y��xLrE����1666�mgee�)����DDeV
�E����������F�O@�J��(f�	�v�&�^!''Gv�����fKp6���:j����j]�~	���3�U����������������������z��.�:[>�
�64�����kt'V��'O�}��'[��(�����p���c��q����/c���x��g�c�����=������������^�����>L�>/��r�{�{�n��;�f���d�i
����.�W^ye��
���~���x��G�m���w�\���+1u�T|��7Q����q�v�i��ysL����s�B���h�p������s�=7j����_|qX7�����g�qn����{����
6���/�\����V���z�?��?����e�b�x�b�;}��l�p��x����������?g�}�l�p��m��%�8qbL��UW{�N���/����~�{�����K�b��Y����$��Qx��7��<��3��'��?��s\x��(++�y���JL�4	?��l�p���������c���q=��7b��!���{��'~�[�l�%�\��/�X��HSy�������
��
8��3q�w�y�;v�mO�<9��S�Liv��t�cJII���������C���m8��9u,�#"�������I
���6�B�)�s��7���p�*��.33�(����b{��AP�`���k�^�B�q��=�jQQ�
�.�8��DDDDDDDDDDDDDDDD����&�:��6^o���2g����A��_?�?>������%�\��������Y$������c��	;v,���q��}�0m�����J.O����C���{���G�f��u�Y�_��r�-E.����3�&M�������w�&�	3f��G}+**��q�0z�h�7P������3�fMl�bQ�x�<�������T>������>������O�b��;���'G�(
���`����������5�U�����<�|���S7��k���+��.j�Z:T�y�������B]��z�)<��������t�5
�G�FJJJ����\v�e��{Mb"t��P�����#F���I�0r�H��]���
n����x;���{��_�
Ng���R������3����#[���n�9��V�UXX����c���h4a���f\|��p81���_`��Y8v�X������y{��!f����u�Y�?�Su�y��,\���/��j����quM�����a���5����|~���W]uU��s�=����z*l{��yQ���nz�� "���J��Eo�8l�����U}�K�/y�l�'y���R6���T��m�m6[�;�tE���������z[�R.E����i
l6;�Ey*yw6"""""""""""""""�fY�~�zs=Km�6o�+���}����[���A�]w����R;v�7o��c�p��Q�~��N��y��q���hp��W����CYY8��7b���(//��l�k�������;�������u�e��a��e|_�������O?]v���T��7�1���`�Z�o�>l����oGUU***��SO!###4n���x���}6o��E���U*|�A��������m�����g��L&������>�
7��N����(�����yfgg��g�Euu5�?�-[�`���0���B���n7���X,��������v�Q�F5��p�
���S�Z�
O?�4`���X�t)�V+������7���+V���!C������m��`��������}����*��k�Ayyyh�J��<�������#��y3JKKq��a�r�-a��n�wG�o��|�`�������B���m�PWW�������0��]w|>


��;��b�`��}������C��}C���n������k��?�	p�g������b���;C�3���jX1��}����������������{/~���������w������k�.�l6���w�q�Jeh��o�-[ ��{n�w`��9a�E�E}o����%;��/��_|1l_II	�y����������iv�������r����a������{q���T*�u�]8|�0***�y�f�����=��juhLEE�x�����w/�����"�i����/�D}}}����~X�V���Gnnn��M�6�w��]��;�<�Y�����k���~>�]�n��R��iz|��-;�1'^�yyy����������^�.�"}�Q�����}}���C=�n9u6�6IDDD-P��#���V�����J$M*���~��,T4�" E~Y��k���B�6�#�Ann.�f�l�����?`�c��=�Z�"?������$���_����5��`i�����J�Q�nyQ���W �i��w%|�����z��v�V�Z6l������� x���p�u�E������7nn��6����������n�999�����_��W����0{��P��%K�o�>�3��sDt�)))	�b5o�<<���HKKk����B����W_����7��#�<�F�M;������y��������/��_~9����B���>���X�bEh{���X�d��s�P(0e�,[�w�}7^~�e'�:{�����q����i0�~�{�����s�b���aD�����3gb��U=z4����������p�%��i�S&a�a����3{���q���vRR/^���;/����7���	�����?���W_�K/�4��kkkW\q�����i�4iR�s���b���X�|yX�/p�y�3g�-[�Q�F���>��3����(���/����V��(:���;����~g����7��ML�������k�����'G�.5�m��Qx��W��_�]tQ(���z
��e�5�����������)S�:��d��=E��_~9-Z����>}���[n�-����[�FtA������h4���Oq�D��z}�(��s�;���?���?�������������������;55��z+.����5+�q���_�m���1c�D����`g���;a���
��������M;
�5��5��v.���F���9�=�\���^}�U|������a��1HOO�����]����^_��_?|���a7O��X�GDD��^��	"?(Iv7����[n[��J���3���J6����Sp#�B���QJJ
�Z�l�i������vkW����$'���>����X�cR���������*�^T��a`�c3��W��JDDDDDDDDDDDDDDD]�+����]���w�@��S���_R��{y��/�I�B�����e�Nu���b��MX�pa\k����`0����7��@��w��3�<�<��V�Mqq1�|��PTcc#>�����:������:�effF������&??_�u����
^x�l��6l���[�?~���3�?����-2����C=����o�is�^[�����'�|R�`�T��z+�m��9������h8Ql�������B�V��?�(6;�i���y���������0p�@����Q���o�SO=�V�s�NTWW�
�z���N�6-��0{�l�w�}�����D��h�����'����sS��S��?��
EL��=�<��S�{����k��K/�
pM&�n������?��={B���~;~��s),,�'�|���G����?�|D!$�q���������?m����j��6�������q�oz|���t�c:i�����};���.|��������:������m���?��O-�`��������H��QC54�����ZH���l��6j�]6��[[�cO&B�;Ty�^82]�(�q��~�um����2���v�#�pC#>)3a��_���������������������z6����>�,���j1����>���HJ���f4&Lm�[����l���>;����<O�^�P(b.�h�{�����~��G[,�;I�T��m;�N|��w��W4���$I
�{��w:t����c�5[�t��W^��m���J)f�}��?�...��w���'�x�����5k�`���1���?�:�.�d����+0j�������#�=��a��!b�����K���)�a�"��<�TWW��?m+
���[���Taa!~��_�t�UW]���{�/�����d��/�9��#G�/^��`d���:������b	�9o�<��5�]�hZdo�\��������N��|��Wx���Z�4����_������;{\���=""j#e����`P�OeLEWJA�i���������>Eh������^�����Q�n)>_\�C��S
M�aR�_�����^QD0��rP�����'e&��� �0������������������=�_�^�7�}���\�����bw������w���~������<O�\�p8��_���';��J���W_����>;�pb�����Wo����s�=7�c�F#����>�X���\�2l��n�����h����j����*���"�x]q�17b���mAp�e��4v���a�����%�M����������~�!�@������A�:l��.�,��`=zt�v�����M�6����_�XD���9sB��t:e���:v�{��'t
vNN�{��v_��	oR�M4M���E�r��N�b�
�37�tl6[����n<��4h~����}��	X�GDDm"T#
�|��hvB���4W��/�������+Z�f��V��~x�Z�a-��2C�D���kl_��oJ%�Q���-�x�d��+v����������P�l��x������������������-N�0f����x�?Umm-^z�%\{��9r$rss��� B������qn������Sii)�y�\q�:t(�����hd�\�~}h��l�:���������Z<��������S�$�]�6�}�i����F��#333�Og4�4v����G���������#R�������:�����}��a�6l�i��!C����ZM�7.��N}�'
�b-Pj:���Y�&��s�i�&����\����F��������J��7�U�B��.l?~|�����D�Y�fM�����q�������#�����o���E�B�,����h�Y����5�ia[s����Nz���p�9�`��N\�~��7c���0�L��|�X,X�r%����PO���`��9p���_��h����L������q��jH�@Ls�i��$A�n���P�>��{���O�$�C�iO*U
�������51�1�����3�l����`7�P��}����(�����bE�
_WX`j��C5Q<����i���4������n�	�����o���{����d��$M".�/++���^���������l6�t�|s9^q�6lXh��t�������9s�������5kb~>�E�V�5��o�>����������8u>�_�k�������Ndaj4eeea��F��k�����k����Z#;;;��N�;NnlW�������^���~:&N�����/���op��1�l6-_{����#G��m���-������D������q�G.����9��%qL�����W�
m�w�y����u�Z)))a��>/M�M�;)��	-Z�����(8���z�j,\��g�Fvv6�j5�F#�O��`���())	��j�*�q��c��h������_&�t�|��UL�$�Rp�aZ��Z��������Q�"�L�n���h�"��n��`��V���$�q�X�p{��Z+j��M�������f;���^�&�_U����
���a""""""""""""""""jM��v=jI��9rc����o��`0��S5���6m���O?�/n��T����j|��<xp��e������i�����Y�f��^@mmm��Y,�V�������;k��Qw`��B��P(������u����!RNk��������������o��3f`��]�^�#�M���-��WG<��:�t�y0�x��P1rrr2^{��[�i�����k|����%�1�������
����b�����2d�����k��{��������� "��A�G���0 ��O��G0�en�|
K����0�L1G�����!_��	����TTTD��t:��Z>��i8z������E}���E}P���[����r���9��aU�='�h�P)�hT	�3����u���5������:���G�����2��N���1:3Z�2������������������ZC�R��~{�ysV��`���^�V��y���w*��s�q:�a�M���i����|>\p��-
43f�����QXX�^�NAB�<���X�ti\����b�\Qd0j�(L�6
DAAt:�ZmX���{o��$%%%��m^x���������8�������?��?��������O�^����Nv�������x�����������������o�����;���T*�N���'���999�j��h4acg��������Fue�<���y0��;V�6�|������������GC�r��7��s+WP��������}��3gf�����C���n���C��|�ML�0���L8�Q�Q�j������b;��������n��)���T�l|^�/���F�C��s�X������~`3�L��a6ii#�R�!pD���5Q�������������������8=Y��$5
�Ta]����J_>?v�=�
�|���$5�}z	���0>]��
2��#����lp5b���������)_�����w�p��)�����1DDDDDDDDDDDDDDDD����q������$�h/O�������������������_��C�B����x��wp�y��8���G\y��O<�ih��AX�hQL��[�����?���x���v�Z,_�?��#6n������c}>^z�%,]��V���������
��,��DIDAT/�W>M�t�6���-%%%TP�{����K����{�
+�������������q���TM_�N�3��dW��\r�=���/l��%%%���^��D���{=�w�}��������w������NOO�-�<x06l��>�
/VM�2dH�1�~L?��C��E]�:]tQX���U��K�����Q�Q�F���S�C�7����G�8O��CRF��3�.EA����������f���,���e��&J�QW�mD�j]u�Vs�A��O��~�N'�� �:~�� I����P���.�5���
a<�K�b�o���
v'>\�]
'���J�:\��j��4=�&k�h���%l�4`�c3�00U��4�8�Su�es�|`;)I���Ia�f�9�������>�����p��g�4�j���W[��?�	��V����~�l���Z��B���i�0m�4<��#�����e���[����8|�p���b���������hZ"I�9��V����������!T�'�"l6���'4}?�g,��:������G��O?�III-�M���h4�m�L��T���K���r.i��`O���n��}q�����u�c���m���?��M�����)Z>���(v�B���w��"h�������*��@;�x��?�*��*�&DQ�������^�s/|��/��^���~w���
x���5���|��(��MJ�c���:�8�`/���|;�4�mh_�%�C�A������C������XSk���:T�<1�!"""""""""""""""�.�5r�-_��ruI0h�-�C5-F��gO\�w�����Q�y�������c.���{���Wk������*�}�y��\����qzk��j�y���?>:�W^y
���q��7�����u�+++������]�V�
�n���9uuu��N�Q\\��s����7=��|D�:���r�-1��;':��j��-	[��4-�:�X.�Zs��F���n�����]���|��iL�*�sju���`P��Kw�N{DD���P��D�T�P,����� (���*u�h�����d�����G�jEb����222�V�e��1�L��6:V��iQcV�:��]��O�E3 U��T=fe(1Y�G}z,s�b�/
��h�p��RbT�c���4'CSb���Bpe�f���r^+7�Q<QX��ms=j�8?=I-l������d
�g�����@&""""""""""""""��e�1�U�g�!������8�����+W�7��M��W�\�q��@ �=x����8t�P\�SN��8�q.V���a����z��)�w�y'��_�E����Y�C�
m��jL�2��=��6n���S��{N'�:����w�����������_�Zl��L�4)�w|����9sf���/_1Qk�������%m9�L�6
���zh������w����m��Ya��>!��`"
8��-�{�{��������9s�����m7-D;i������p�N4.9t����b*�.--�O?���&55U��<��)333l���&���g������wU,�#"������1�K��C��Z����8����8���Zo���l�V�zL2�h���;�B���,TWWG��N'�n7���;!���t}���EccyD�j]V�����+ �d���Zm>���$�p{�Q�$~Ur�4
z�� �:o�R�������L��h5>�����a�/�l����4=2T���t{QY^�Ai:�1�A�nyQW�G�EI�G��w��WI�}�����&O����$�|>�W_}��
����X������:�u�=�\/���j���^��v��1�Md���2eJX���l�8������K/��aE{z�N�@|�qghZ��}������fs�(X�,3f���O?�^�h~����!�l6|��ga��O���9R����f�����z+���r9����R�BE��|�
~����|]Yaa!F���{��|��78���;9���������s�9'�qk��	�����i�V�9s�������[�?~�c���w�y��*������������/_�y�����?��=`����ve��8"""j%A��jDQ�x��b}�|A�T�9 _P���6_�}H�j���g2��I��t������P;����#��gjN4�����F�
�4#
HV"��U�M�������A��s��`����k,���	�(�4�O�F|Rf�V��`lc�������������������9�HVv������o���edd����eh�����G�i������'233�
}6l��y/�;v�]������c1�����nz!z4_�5/^�:���8�`0Ds�-� ###����������|N}�KKK;d��2v����?�0�q�=�;�p���3g����>v�^~����>��Ca�N��M��!C�=G�Z����CEt�kI[�!�������C��(���o��5�]��]���{�A}}}'e��X��=��7����+������1&�)�sT�y:��g����G���,��V�o��F��uW,�#"���J��0�(��JHb�m��4��:F6&B�j��q����t:RSSecf��[��`4N�������>oP��Z{�����Qx�����N*/G���c�^Ee���X���m{��4=�;�+F���6�+�x����
ncx�%	�lN|Rf�~�"_�DDDDDDDDDDDDDDD�Mi�
�.�D�B�����0�0�*�n���n����+�����_��Y�p!.\�J�'NmWWW����ov����q�%������p��ZJJJh��~��f�il��}QXX���y3����4;f��M��������k����+c>�f�E<�����8.==��B��(��k���%K��o��������=f�����6������Z���AB������8��s�V�|]��~�b����c.P���J%�����}<�@Dw���z���"�{�������c���a����:>���7�x�=�\�k����(~���>�F�^�z5���jx����o��������������C8���QUU�~����nX���kt�y��D�_��/��I�B��7�|s��I>�7�|3,Kh��i�p���vx�����K�>�y�^\~��-~fs:����+`�ZC��j5�����5���	u(��|@#�:]j� x��;�4�0�J�l��{�]�[�cO��^ �@�U2�� (ecV�l��Gc��s)*%��N�w����<��Ecc9l�M8~�=TT�.��V�� �4��5����������K��e�j�����4�'(bC]=>+3����BU"""""""""""""""���5�/�j��{�J�/����+�vg�yfX�I�p�������-�?vlii)����v�m�~�����
7��������a2�����f<���?~<���!�:
�"����n��I����Oc���������5�8�i�7�p������p����������a�����l�j�1?_}�f���a����G�������������>�'N�>s�����3��������\�nhh���^��.���/�-�x<��i�|�I�7���o���9s����_���G}��K��=�G���������
�()�"~��_��w����{�n\w�u���[!I��t�����;�������������'TWW�{��Q�~�����[��W����p�%�$,g�y�3�<3�����������>����s�N\u�U���~I�0t�����9sfX�������.�o����������k�F�6lXD��G}������w��-H������1k�,�q�1�w�R�O>���?w$^�~=F��Gy��W[[�/����~;
1w�\��/�vG�{�g�}
���������3��m;n����3g�����>�R�g�y&a��$+++����-[0f����{p:�a�������c���a��n�������(������VB=�������O&(r��H���O�(48�0?�������@_]	4����
�F#JKK#b&�	YYY��U���4���B�c{D�h��4�Q�N�����^��F��-��y0�<�JTWW"%e��gA���=�I:�w�����F<u�T[q��K0����u�q~z
�i�Z���bE�
9�$����]�c������������������F�K�s���G�_���T&f�������[�n���'���$	/��^~�e������0��8v�XhLjj*^}�������7���v��Z������0h� ddd�b����ca�2=����������_�����K�,	:t<����+V����3C������������p�S���G<���<x0�z=���PZZV�����
����PZZs�����c�=��{J�EEE0�HJJ��n���G#:�$''�����:�B������K/�4��N�$|��g������hP\\���������
����s�
7��'���lp�82ZG�Gy�>�h\���g�y_�u��������o~�0J�aE���O�u�]*R���J%��}��5��'�����x��'��SO���0���������^{-�YSO��s�a��������j\y��HII��A��P(PQQ������^���_;vl���������{�=���Tqq����������G�`����#G�`���P*�(..Fff&�^/���QW[C�D<x0>��3����O���f���YYYY����^������ln�����`O6u�T��/	�����?b��q(((@~~>���"�����S;�u����y�������2�x������1p�@������G������)SZ�U���_)DD���y�P���%	�=�1u
��m_�X���{�.z#�R�0��p�����[g2�F�*2P�:?��az�%�hA�������V����<���������\�������arFJX���uv��l���2C8����*�XQm���"""""""""""""""��B�T`F����M�suI8���y�E�����K�b���a�%I���G�y�������4,Y�$�Fj��/��A�������b���8|�pX����{��������1/��bX��X�F,Y����a������M�6���c�k�
������[o�{�S�A���a�����q#<Q�PXX���������t,[������R��l�z�8t�6n���;w���L�`�O�>��a4��'� '''�G��������#999l������;�m�������:K�,i�k��)))���k#^w�(���#��y�l��������!A�RO6y�d������N���o���[�
����K�3&��^x���=�M�����+����C��]�vu����f�����7�v�3����g6n������>AZ<���=��=�������{J�2lUU�n�Q��T*�`�����Od�1Q*�����p��wF��8��7b��}�{�^{-���kh�=���R!"��P+T����F����� `��(����6lG��V6��4����_DtUM��$V���������y�0���Ce��]��K0�Be���R�#S����x{D?�k���>�j�Xlk�3(�4_���O�L�`��'��cu�>z-.(���}�1���]�B�1I
�$�2�������(}�=�b�������������F~~��1J��_~9v����.V}������q�]w5{���I���w������ Q�k�o~����?�0�:�, 999������[�������(�$A0{�ll��������m��Mx��gp��gC���x�����������8��3cZC�R�������q�m��T\��_?�v�mX�tiL�O�����_�E]����#55
E�����s���M�p�y�E}�����^���K���������"l��.�����'&N��������Fjjj�����o��U�0}����h�Z�t�M��wo��S��N��}����[�t�M=z4�Fc�E�w�y'�9�������Medd��k��?��~���*��0`�l��	K�,�Yg�����o��T*q��g���������������`Ov���b��-�����s
~��_`������{�`�Z-^y��_��\s
t:]��'%%��K.�?��E�!--J��nJ�bimDD=���{1b�����={����H�+V�m��5�����f��V�T��
h�
��]�6�VaG�F�XNR>.����_��$�w���Y��V�1v��.����V�G0�����%��ce!G��`�����[����J=���Je���E�Ua���8�EzA���dLMM�:���Z!`�!�2R�R�����a"����`"����`"����`"����a"����`������
������
4(��VO I���$A)P	B����;Ek����C�`2���hPRR�i��!++�]�p:�X�z5>���z�t:����&MB��}�e��`�Z�j�*������z�����������\0������O?���


N�b���������$	{�����{a6�a����h�������c��a(((h�:�Emm-V�\���*�\.�F�5
�&M�Z�I?+//���Q[[��������v����=����?~h��'���b���������EFF���'Gt��
$I��;B]�N�O���0l�0�1�[����nl������bAcc#RRR������c���1��*Q����l6c��58z�(\.�z=�)S���g�D�����s'����������d�v�i7n4M����C��������R V�!Zd
��"�{+����/���O�a�~8�����W��]�zz{��megg����~���.��^�P�`���{����paHA��=���wH�p��^]�
��]�nsj
��7W����j������{^I�R�\������d--�n�E	[-
�_����4L��k"""""""""""""""�vA�Z_�j�B�������f�V)))8���;l��b4q���v��J�#F�+��� $d��"77W^yeg��m����K�R���_�.���%� `��13fLg��&���8����u�D�{�������hj��������;;�N�5{Q�$T#��|�X��Xeoq�"	���? n��Bc���4{�����-�M&S�����8������d$�0�x"�r��y�Csr:��:���f%����>X>a0f��#(�[^2Yq���i>w@��Z;������i�|����������������������(:�QB)����5��_
�hq�~��WW"��l��ju�=�J���h���l6�|�g�L�T����;S6.��k�Rq��f����:r�!z�}z	�*����V�5� �6��u6T��1�g�������X���!"""""""""""""""""""""��a�%��_&�t�|��U�s��)���T������T�%�!'''j���.���/�*�=��Q�������^o<	�y{<��z�6� 8'3
���'��R��{�x�d��V��`LsV��X\^�5�6�bCDDDDDDDDDDDDDDDDDDDDDD���=""J8A�Y�l\��G����<i��I�5����$�:�� 55Z�V6f2� IR�3��$IXk���H��k�G0��m;����;��k�n.���ICq[Q6T���H��=x���o�������r4��R���{��QGa�u
E���Q������-w;=m�T�1��{��6�A�����^/���#;��z7�}�A���Qx=e�]OM�2K�zjT���`NfZX,`e���X����`E�AI�.���������E7�����������������������+�Q�Q�dCH����\�R�05������5p��M�G��������dJp6-������0�~!���X�8�����MTz��6�]
$k���|x���wOt���wbA�������El���ge&�:�l�E"""""""""""""""""""""���E{DD�i��EQ���V��������$�4��_�a������#��j���j���OpF����5�6��%yw#��?k�h�Q�&,GE/$�s����T|�`<;��jUX��}����(�F�T�����j������!��E{DD���d(�eF���TB
�-�s��,��l��k?*�Z�cO���#�_�$���g�^�&�|1� z�i}N�l�
E?$���GG��`��JA��YX?i(~�7IM:)��x���E�z�����4y|����
�F�Q:`Q�X�GDD�N5(�N��Nr�����9RT��1%j|��{;�������#))I6f2� E�l�H6��,�������T���A'�����8#�NY�Ti*%P��������/�Z���g��P�
�~��r�BT�Z@DDDDDDDDDDDDDDDDDDD1y��G!IR��\,�#"�N'�P�(���!�7�8����0��dcv�����:��N�����t:�Q8Q����1���Z��8?��o��� $A�Hlg8�B!Jg��P��`����l�@�J���D\�x�������/(���E���8��!�CDDDDDDDDDDDDDDDDDDDDDDX�GDD]�2+�B�|P��+ �P8����9;j|[�:4���f����5VWW��L"��:a��ecj��q9D��-�5MnG�F��� 	]3gf�������!}���%�+IX�p����!�P�')U�����2;���QX�GDD]�jH����$���������E8M?\6�Xg]���3�F���t���lF0LpF'X<~��6D�O�JC�a�l���	���6����%�.[��\�o���C���\h������Ol
x�d�!�7�9]� V������.OG�MDDDDDDDDDDDDDDDDDDDDD�c�h����!I������aDg�C�3�����J��Q�>���������(�b�$8 (JXUk���wBa����a4N�r��m=RRwT��������OMB���^��J��v�P�Ond�o����:�|�]���XZe��J�Q:#�v,�#"�.E��En�|P���S�b��d�2�E�������;�T*�n�&�)��;�
����$���������w����@���V[���F�x�QQ�>L���	];��$�2�_��qi���^?^6����{ �n��n/��aM�
���,�#"�.G=�P���$��rk�sM=YI����@=��olS���B�@vv�l��t��N\������6g����t$��A�v��Z��3�?�8{P^�6��m���[�66]�/�����Q�Q��$��<_c���NxD1�9r4��R���cCDDDDDDDDDDDDDDDDDDDDD���h����A��jH~�x�`
�F_�s(�e���Q�	�~[�s��rrr���m/ �X]kC����z-JRua���)��66����z}	RR�s��E/��Q^�O��e��C,A�����8��C�2��`��7���`]���Z@P�����'e&��� �0�����������������������'c�uI�"�z�`P�o%���r4��z�lLDk,��8GO������*3��c���[-
p����i�
���A����E{`�o������TFy�$��oEU�'��^�����h�N��=���~�P\�g��$�%|Q���Z+v�=1��	��PW���L(s6���-""""""""""""""����Z
���DDDDDDQ�]/�wUGa�uI� @5�P���:'�*{����1
Z�N6V�)�Q�����mE��`�Z;t��������9�������2��2\v���E{J��A���O���Ph��w	����t��u����bYQ��k.�)W��C���������bGK ����f����|w��� �W��u��:bQ���K>�A��&�vr/��]�QX�GDD]�"9	��r�����!y���U�0�03j|�u9|b�+,2�P*#��d2u��~Q��Z{�xI��R��,�h�*��f[Q<�Z�h�QXxe�u�S*�(,�))���K��_
�:��q������o���`������d|:z �1��$�"������c��f��s'�<>|Ua��j+���Qt� D\�����I�um.Wx��J�N{DDD')�eAH�R�������9NK�<M�l�tb�}m[R���J%���dc���C��\��3 �7�R�I����Sd�44�mk4������i}�RR��o���d8���^_��}oDf�T���9'jk�Be���z���OGfg���}�?�Rd;��/�Z���g02.����ge&l����w�#""""""""""""""j�>�&�


��	Q������������=""��A�zd��]��G��hq����@�2�n�VX}]�������D������Q�����5>%7e�M���C������5a�J�yy ?�Rh��E��h�����yy@��,�	(.�sa��S�������]�.wI
s|<���t_C��E�W#���`��E��.|\j�.kb��:HDDDDDDDDDDDDDD������m��n�|�N��������kr:��l����������S�j���������^�I9�6V6&A�j���b(>�I�z=���ec&��]�oP��=j|PZ2�����N�Tj��q�l���h�$��EEW�O�`0L�N�
�&��B��/�	���]����|T�T��]������D��LB}�N��������d��ui��k=V,V�����W�����s5lq5B����%l�4��2;���w������������������v��$	��G �����������������}J�2���E������ZIU�
�����8X���������#��p��o~r��i)#�+�n!''�����~?�v;C�������|��^������Z�i��uu�~�c��T�f��dA��
������$!J����ct�B�?8{`���(6�IO=�����;��=:]�V���N�%���K�����G�p��;�������N7�OO�iZM��~�
�����6'�g��0��M""""""""""""""":q�ijj*B�|>�9���4���A�VC�`O"""""�DQD0���BCCCD�=HOOo������=""�����m8*�B��EfJ�9�L6���u_���[W�X7e�) ���Byy9D1���d2�K�^����
�����f I��F�T����������8� ������ (��>
))��j]�����$���QY�RR#3s:�j����&fg�c�1
�V�������-k�A�m��@����� I���V_K��(L�`|V�����v�����|�z���(���������Q����������[�Q��0��,���������vRI�`j�ec��M��n=�J���h���l6�|�6��	��d���GAr���N������l����&��:�R�Ev�,��s}�����(/V��b��3l=�B�-E�X?i(n)��J�f��~�l��#�#��/�J�������W�c���������������z+�R�>}�@�b�"""""�������� �]��Q7�:-��w���>��/�f����}
;P��is��Isw
���k���M�h�RH��Vb\V���A��8E6f�v~��IM

.G^�EP��Z<^��Z����]8�?A������j�<�?N�����M�����5|[��G�����������f|-��fj�}���^���T��������R	���i{������TJ��F���A�olv�����5�����{
�RSS��jec&����cGQ��D�O���Z���"F�4��n�146V�j�� RR�o�a4�	A�/=U P���/PU�	|>K�l���Z�sT	�s��G��V6��\�����Z
Jv�������v�.\�HDDDDDDDDDDDDDD��4
�����";;III�v1*QgS�T���@��}1h� ���v��H��NDD��2;b��J[dP��+�4y E����I8����@}D��W�
�0,mt;f�u	�������G��^/������b��5>��G�No�!F�|�=����PwU���
�F��HM�e��C-�il,Gy�{HO�q�J����`�1�����-x�X
,�@X�%J����u�F��������'(bC]=�������z-����Z���,deeA�$H�Q�=7�&""""��M(�.w�1���(I�PZZ���w���v����
�g��+Rk544`���8t�t:���1y�d��Z{�����[Q]]�`0���L�1'N�J�~/��������<�_ "&5x<V������
5&��w��d�����_?:���r�����p��q��z&�)��=I���d�W�������cZ�s�&))C�t��Y�kPX����NR��������a6���gna����mp:�#3s*RSGt��'�n(�����PZ��u�5y=YA�ou������S�O������m��&���4��ZCDDDDDDDDDDDDDD�[	��`�������:+������?��~�-�/_�9���j�^x!�����1�M�;v?�0>��C�|��� �1c��������zI����o������C��233q�w���^��B�����(����zX�;"��@��	��t(R�ws��<���(k<��l�������-��,))	�V�5"f�Zb.@>����.�lL0-7�f� ��h��ho$)AP�y�����}�\���]�Z�B������F�L�P_�YY����o�y{JS)����P����T����n������c�V�����R���2y|����~)Z��LCZ?�Q��[�t���������n�	~�a�{�������c�������p8Z���~�#F`��E��m�����3g��< ���%v���{.n�����m`�X��?��F����{�^������)�������M���S�����YP	��?��{P��hk��Fvv��~I�Z</����Q�H��Q�di��S��8Uv `GCC��22F���&����i��[���P[�
gg�6�t�cD|:z F��d����bA��m
p���-uz�Y�	���	�3e"""""""""""""""""""""�v���.b����fJ�EEE7nF������c�{�=��=Ng|���G���k�v���gggc���(**� ��	I�$<�������:���8��s�l����III8���0r���tG���Y�p�pd������(:A�V��Og���`yd��S���1&����5�eJ��0(##II�u&���HI���d�_�?��Q�tcj��<)#�(��Z�k�m���T���s���ZmaLc����m�l�!I���m&R�������>����'��j�s5�p�����^������&��6 �5GDDDDDDDDDDDDDDDDDDDDD�X��edd��;��W_}������c��-��s',V�X�i������i����G���y� �?w�9����|�r�L&l��������q�e���}�����������{l��)��P(��C�����]�`�Z���o�`0�������W^�`�]tz�c"��	Z5TC���k 5�w�<����HWdcV�{���cw!B�n{n�.�������r{ec
�r
P�R8�VJ����ec��v['Q4�^����T��x�$�a��Fy�{p��& ��S������C���\h���$a����j,��j�C��_�����O�L8�p��s.Q{c�^��_?,\�UUUx��Wp� 55�#�R����3�b�
�v�ma�O>�+V��i��z(����3���U�0k������?�8b�����@��}8�7�|3l��E���c���%%%a���X�z5222B��o����{��>&"����E�^>��[�l1�RPaj�9Q�[�k�
4�5�n!'''j�d2E�5��lvD���L�Q�nSnr2�Se���oC0���ue�  5u����`�@��������QU�|>[�'�z�(����C����cA������C�"��\� V����x]��Q"""""""""""""""""""""�Da�^1�|<x7�|3t:]��+�J����?>�����[�w�^��?�	m'%%��w�EZZ���� ��_��A�B��9���~���y����r�_=������>�=�\��������7�NO|LD;A�^�t���bu}�s��a@���_�c�5����N�� ==]6f6�e;�J���5v�Ffk�ah�s\k��I�6��Y3
523����F��b�vCy��0�WA��.����Ixmx?|5v��%�S��ms=�QgC�/�s���w�,�����y����������������������:����/�IIIq�Q*�������}��w-�{��� �bh�������C���j����k�@�f���O?
m��G}�����������vYY����f����DD�Q�5P��5��W��|7�3������������-)v�����������Z�|��R����*�*%e(�j�l�j[�!k&�Z����KPPpY��N���eeo����l���`\�_��W��0J'��^?^6����{ �hTN�����uXSk�+�1DDDDDDDDDDDDDDDDDDDDDD��E{���i���-�nw�c�,Y�}��7���UW]�^���y3������W_!��@f���())iq�B�y�����������OY�!=J�R����@�J���)Q�k,�#(5_���T*���d
�����jqD�k\f����j����(�3�Z�t������}�^���P(Z.�]0��Ee��xj�a�	���r
X=q(��?������mn�����z'<��7�'G#>)5a��_0�1DDDDDDDDDDDDDDDDDDDDDDm���n�`0D�����z���q�����^�����cZ����$�����z|���9sbZf������_F=�'>&"jA!@=����M��G���F���Q�-����~s[���
������*%	�k�Fi���K���|��Se��\?����k�%22��o�yHM�����dZ�@�������T�w���n�P\�g��5X���s5�kp#C'��$a���O�L�owA��������������������������c�^7WYY�/333��;v���0aB�nJr�L	�f�t��b����q���hB�UUU����i��������Z(Kr���{� ����
L�<'j|[�8�����-��DOv��ms�����L��� D��lG������m�$�J���sQTt
4����8{P^�6��m������ O���C�����aR�|��K��E�j�����4�'(bC]=>+3�����{DDDDDDDDDDDDDDDDDDDDD�AX����^�:l���IIIQ������a��Z���M�;����u��w-�F���VO|LD�6�������������i�08e�l,(�����)vy:�����1��s�;,
Q�����Tu��m���A�$�Z�&$������������2���E���G���nwY2l�Q���l�@,�}���m,� ��:����R�/�y� �W��u�������E{��[o��}�4{���������zM�o:�IG�E m�t:deeu�Z=�1Q�J�#����V�VW�sL4��F����5A���l�'��m�`e�b�q�Nk���=
Sd�[�k I�2��A@Z�0�CF�x���������TW/���w�������C����(�_�/�7��Xd����=�)����*�XQm���"""""""""""""""""""""�X�h������j���}s��mv��d
�.**�k����"������i:�5k5�3��������=���Q��������t�dL0L�_k�~����:���R���K�#(��IR���A::�0F�T��~�N�����

����o����/�1.�����e-�.�Z�(�u���47dF������Z+��l���T�N>+3aC]=<�`�%MDDDDDDDDDDDDDDDDDDDDD�������Z�������]z���0aB���Ng��^��k�����~x�^h4�v]GnL�9�k�����a2��Fs�px�0��	����\����jv�(.��P��!x#q$�����g�:�@��Le,��[g��
��8=�����.--
6�-���L�Y���Q)I]p4&"��)�� *HRd�������_Aw���^6���p:7 l��]����6��~RR&@�)���;�+�k�_~:����/�-X��Blp5b��������uE�"��v~�wa�>	��P&�����ga"����`"����`"����a"����`���=�#"""""���E{��(�����PQQ��������o-�m�%�V��km�N';gKn��#�V�E{=�1���W_�����4��M�PSS��\:��M�:;��2���ecBE=���C���>�N S�����6��I��l�R���y�c��*%�R��n�����8���N��C�:����8P�	u.A�Bf�
YY6(���OE�p����:'��N����7���c��JuD�+IX�pa����������B���q������I��_}"������DD�����:����:����:���z�����N�������:������w�}���o��������O�c=O�vRR|�&M���1��M[��[Kn��X�+>&"j?�����B0B��lQ��Q�dK�|P8
M��|ATw���u���"��@���*���`p��~��(�f
3{(I`6p�p_��)1���=0���uP*#;Tv%�Q�F<����+�%�|A������CoLs�j
\�%p��>zgI""""""""""""""""""""""9,��f�������k�����W]uUL��v����+b�z#/v��8��u������'>&"j_�x��l,M�A?E����J��������R��d��kfW����J�65�1�5eP���D	N��/(���M��PY���G���r�� F���`��xQ�
���<���,�
I>�o����:�|�����h(�����Dv�%"""""""""""""""""""""����(v���>�����}s���SO=�))��v�v�k�\g��s��:rk���ku���;��W\qE\c>�K/�4�=a�:�������M�6��'L��^��QO!�]�A�ll�:���t�]����6�V��|��1;�<���;pv�@��NTs�(��0q���&%C�����m���~����gV'd��H�����-����c*���3��HK�����e�z8����
+~�w�s����&�$k1;M��|A���)��d�X����$����u~&"�<|&"�<|&"�\|&"�<|&������)Q'a�^7���_��o�tJ���.�.���BN�"1��WM�W�T��������X��z�c�GNNrrr�4GJJ
�����KG���]67�^��T��>����� �cv$M,���:J���O��VD�%7wa���v��+Xo����/hT�AL�6"U�5:�ffN���u�~�k3�K�+=}��F�j]���h���(�a���������:z���`L�AN~�:���*tE'J��=���`Jj2f�&C�h���@�7��z�4� ��{D���Y�����=�����=���s�}�����=��gj����������{������+p�W ����=�����T���TM��**"�O�SYY�����:M��f�h�i=�1Q��a�J��'���6;~j�9PD9u�ql��gj�\��*��t,�|��%�5�h�*���<��.��t]J������������4��<����a�n�(�;8���iL������`T�^
X���s5�kp#(5_�AI�.���������"""""""""""""""""""""�]X���m��_|1<����L�<�}������o���a����q�oz��!Cd�+))�J�s#���F���W,�Z=�1Q��j���G��@j�E���1"m�lL����eaQ�;_P��Z{�x���T#L&S�y�F�|�Xmk�I���d���r��]����vJRV�:������.�s�F�pca�O�;�dC���K��E�j������'�������P�l���%����]�v��������3f�����wt\�y.|_�LL�:�N�]ER�H�;r�c�Vl�R�8�IN������9q�O�qN���I�-�K2UH��{'���^w���D��`H�����E���g�{���p-\��S8�k���Cb�����'N���z�3�LX�x�5��X,����U��z|LDT?R����k���|lt����8$�am�8�S���hsN�I!���5YU�������J��ZE6[�����XlG���A��������`�)�������0:�J��3i��I���t�������]q_TQ��X
_��_��}�TY���8~6Eh��/�8���N�:�{���x��Z__~��_�������Y�n���oE����/_9�������s����s����KokkC0��>��c"����@4����������D3���R��'�"
j~�}���lgR����l���W;y��*M���^�4�)��	>�f��@2Y� ������U�nB�lZh��������X��U�7XR��p��$)W��b�P�O�#x~,�T���!DDDDDDDDDDDDDDDDDDDDDt�aho�=���P(tim���x��gft����+��e����g�l�v���wA��w����7��}����|��w����^�����KtX /k�X/�>E�f�}:�k-����3mqVU
/O$*�=�4��+Z�h��������J����
�f��$'��[q�B;
s't$�18�(��#�u��=��m�&�|�2|��A�\q��B�����x�����)��!�'QP�'U�����9fllw�}7���/�utt����%:::jr�w��]W���_�jU����o#��\���
���^q�}��Y����/����??�}t]�c�=v������)�\�����K�i���0i���|b��YA��$H���C+���v���W(�E-���u]��D��Yu��M��M,�����_��
��u���Q�L�_U��������G���H�����sS����J�7������(�OeQ�bZ��D"����p8���q�#�����9$���{���s�.�<���X�pa����CA.�b��O>�'NLy�P(������X�����)��|>��=���w]���������#�������{zzp�=�Ly�z|LDT_�(���0��@M@
�*�w��X��X��=�,�y0q����y�O�+��h��j6�B��*M�&�Mp�n2�1�w���+���\�������FF������(�i��6�,�O�a��>�'������x&��g�����C���^�t�������rs����������������������������9"�N�mo{�;vi�����g�A___M��j�*|�����R��x��q8E�u�����9sim��Ex������_��_A/?�������'����������>u������f�y��\�����Ot� -
T����B/��7�7�%�
k����_�i�
�WT�'+�Wzh�[�r���l���*>�V��xb/T���n�?I�!�]]�	�������	<�x|t]�s�3�e5�K+����b��^q_J��T<��q�P�s)���>���Ca����#""""""""""""""""""""��1�7G��]���}��X��?�D"<��sW��x<>��>����n�������w��^x��}�O��������_�������x���X�����}��G>���_��}��e<��c��u+����5k�����>��c"���!8,��B����gEn�U���/�9un�����:v��(����&��.��.N���B{�V@2y���\?,� ::>���� I�i��z��v~
���t8s��x�R�{_7�-�?��<I���8FK���+*��H��D+Vw�����������������������y����,�������k=������;���d�|��_����]���]w��@ ���n�B!_�������|��~>���������?@�4����
���.��b������d�8�����|�;�������c"��$��(�6��1Hm�>�a����K��;3�V���{o	���=���t���aMp{��(�V+�n7���S�"�zzz IR=��VS�j�r%=������e��>����^8���E"��^y"%��	���v�B47�	����n��(x����KC!��@y�8�z�X��
�q���{]x����#�"F�X���&U�!""""""""""""""""""""�����n`�����o~6����p8�`hhhR��S����_����c����_�oy�[�X/�J8u�><)��`�l��
��-��{]�����O�: ��+��G��W�@[|o�,O�:�=�����{����bwxr�u��N��+�����^M��Fk���E^�q0/���n�O�h���������3��>�H�%hZ����]�'Z�ss/>�Z9h�8�+�����y2�B������I��T")��x�!""""""""""""""""""""�������?�a=z��?L&��	�q�x���O��O�����������+_�
�,Y2��?��?��#G�z����p}>&"�?yY`5~���%(gC�6�.����b}G�9��L"�-�����J�nX��e��5M^�z+N

�*����j��NC�4�������A[�����>�L�*NhH$�c`�Q�R�'����6������o^�Mn����x1��g�����A����������D"m|=���������������������hj��mO
7����h�"|������E���g��A:���jEww7n��6ttt��>�(���>��O���#8x� �����*�~?V�Z�M�6M����� K0��@y�a]��������W�6�T���a�x9���X��X��k�L*��\��&���I�lE�@ccc�j�L�\v����^����;����vs�������H&_E,�k�Iz��E(�s$������A�^�u.;~p��8��_��P��1f5?Jf�3��[]��[��vA��;���D�]�vX��?*@DDDDDDDDDDDDDDDDDDDDD���=���r����k��V�^���s��c"���MP;<�F��:P>:��K ��$A�V�=����
��?���p��w}��e{����u�&�-�C��`�0�\���`����8#6[7l�n���j�����@$x<7���E4����i��c�\�U���B�g7�9A�����]���0�u`U3�UT|+�Bw&���M�����u���mcq�X����B�f��C """"""""""""""""""""�:g�""�������3�z��B���[7�8�k�^����5��t]����
�^�-&��9����fCSS�a-�@���L����f�����)��;Yv�������Ku�R��|��A��Z�g�*�������������P=XR��p��$)+U]�P�O�#x~,�T��3DDDDDDDDDDDDDDDDDDDDD470�GDD��Y�iE[��rvZ�X���{'���d����]�i�5q"��x�dX���Da�D�7���� ����Z��n7\/��JF����������F0�6H�c���VD$���\n��\�l�g{���-�q�w����B�����x��t�7�����v��(�s?�HDDDDDDDDDDDDDDDDDDDDD�M"��!]�EMG��H���Cv��qP^�=E���Y�����t��M~<SU�����$��
����Z�zoE��;���w��_Z�������|g�}����6y�.�
��|�T���\�at�)����r��=��
�
��v1_��l���4��y|v<��SY���jN$�x�?���4�!S""""""""""""""""""""����=""�7����l�6���P�b��hZ�9hXK)	J��I��B�ul��C�
Z�X��~"��$I���7�%�I
�k��VL&l���S�$����"���|����o�"�47����`�/��L6{���#}�V�o�5 ����������-Z���x&��g�����W5����8M�{!�M�8!���������������������h�bh�����`5A�m�XWN�C���DA���{+�}%��r|�=^�c����eA��-��pU������Z�T.�q��!�?�g�}8t��q���<K������E{������L�i����x|E:}j^������
b��><��i������x��q�P���YE����
c4W�"""""""""""""""""""""j�����*�:�}�����F*�Z���u�1>
;c�>��8KW�ohv�e�����v����g%d�����=o����ft�����g������Qg�:�c��?�+�4�~E�`b�'�/���>���]���o���>��{��
�$�H8��RuScE�����(b��?�����������������������F��Q� @^���c��p�X���M�;`m����y������jh���	h�sm63z������Pq�^�TB"����^�t�$���DM�W,M���3�W� ���������W��BaCC�@(�K�j����2��\�O�Y�ev��{�K��P����T���?�+���0vL$����C{DDDS�K[*���G����U�a����gw�����f�c5�2�V��elm�@����hnn�x>
]�u�V���W��TS^EI��WD���u�"Yv�������!X,��+�H�a`�$��B����Xw�]�v�r���N�LR�}:���>;���+�m�t�L*���C8I�����	����=""�iH�!��'����|b���^�j-m��������Z�8�H��C�t���f7�&yF��e~�����Q*5&�x��_�l���K8u���rm��fkGg����XaJ�iZ��6
}��P:�9Y���f������
�4EXV�b:��`g:M�>���:�3xj ��lUg������������������������#""�� 
0��*dk���P��� �v��*>���x)R�V'Q5�'����[��R �*��'������c*������Q]�11�4"���z�� �p�W���A��7����J��|��?A�\9�:��M2�rI^���_kvO�7���Q2����H�P������$�?�@&��=""""""""""""""""""""��ah����
��iQ�b�|l����--X�t�aM������y%�F�������Z<���u5���`�Z
k�p������/�����3�����F'IVw��������:���������vC��u��6�-xt�B|w�b�rN��**�K�����=�TY���8~6E(����DDDDDDDDDDDDDDDDDDDDD7:������$/BpX���2�S��n�n�]r�FC8�=Q����p4��X�5��]�jv?A����M@�dN!��W���Q"������������Gk�;!��i����Xl'G&sf�L���m�/6,��,�B�,O�w�����8�M"^!,�f�~2��c1�*y����������������������6�#""�� �0���XWc�bY��E�`����gw��GQ+����M���8*��z�V,�f������P(T���n|�Gu������F'�����~>����6P�������P*E���I�����������8��c�">;���4��V�=�3| ���$
ju�?"""""""""""""""""""""�:�]������X/���g�8��n�6�����w��G8M#U6�X%[n����ka6���z
k�h�R�	_����\���7�~t�(���mFw���t.��L>?����!~�Z�s����%��Em����z���������x>��Z�dA
��DO��p8�����i�DDDDDDDDDDDDDDDDDDDDD�C{DDDWI^�XM�5=[�r�x�� ���b���c�W)N����\���`K�
�,��>��A�u]��Dj~?]��N��u��J�^E8���dr���ho����*N�H&bp�Q$�G���M��m�6��r~�~)nj�O����x&��?�Gq0����Y�t�������r|N�C{DDDWI�%�VuT�����Ry������������(8S�4��HT�/n���i���W����l6�B�P��A����$kz��(J�Z9I�a�w���#�Q�L�_U��������G�am��v�'7/����F��80�����;�4>��|�T������	<=�h�X�����������������������nh�])���c\����a��q8m��V8�&�Z�4���#����p
E5��%��k�v�A@ 0��r9d��
�iZ����������A���==��Z@��L�8���'11�3(J��M��(��V^����gA+l�����
�#��#��^�,VT���(��"V���+""""""""""""""""""""��C{DDD�����%���*@���������u��_D^�]u?#�N�*���������J�=����Z��'���(O��!I6�w���7a�V���F��	<�x|/t]�s��a�D�������h�N��L����;���V�=FrE<=����U�����������������������2�������`�aZ�^������-��������V�
��~U�U
;B���e.;:����LX�V���S���(T�vA IrB��?A��d�
Ir4��T�%��������e���u��ht��l�|:��6���������S?us��h�Hf���S@�|�L*���C8I��V�#"""""""""""""""""""""�����fDluC65��#�
2� �6��������a�F��cO8��b�q�6\U_�V��������F�5�� hjZY��U�n_AzO�����rtw?�w�x"���	������G�o@��q�����_^��N��S'/�s����f��>��������D"�������=""����l�����P�b�5������*^{G�9h����2y�K�+���x`����z!����p8\�{�\kkz���R����G<��0�Is�(��������p,��L.w���#y	�V�s��!��b��>�������y�j:�O����8[��1T
��I| ��L��{""""""""""""""""""""�)0�GDD4C��yy[��rjz�lX[����1�EK!K�2������d�z���6�e�k��(�hnn6���i�����W����5�V�b��8���8p��D�1�4��L�������������Db?E*u|�|o���?�i��M}��6��UT|5��C1D��{��*������(B��j$""""""""""""""""""""j4�����j@��B�9���������,������u��w �dk��cW(��j<��e����i���(V��B�����\����]�j$S����O`���c|�ih�2+}�������(����(�����Y�B?����(��am-&�so7��e9n�8��?XR���(�M�Pe@q�P�O�#x~,�T��y""""""""""""""""""""�7bh����A����g[i�4�1��x]��Xd_fX+�%���`X��)�?S0���/dqv���v;�N��P8���EO�'kv�k��������{���������C�A�������ZU��bq���B(�%W�kg�����[��V-�B��!�c�"�f$��%���'�?S��B�N��V7�����������������������z��Q����-����+L��������v6{#��+�r����D�{��:�REH�*M�S�x�f�in�--�����U>?����;w�������dg�%2 �v������a��Uu&�:���G�H������ x[��7������%O��_�R&��	c_6_�=4�Y<���X�V��>""""""""""""""""""""��C{DDD5$-h���K*�'�KN�	<[*^wG�Y����t]��P�
��Y�M���k���~?$I2��B���k��O�b���	Y����n2K8{������q����\�]@�j�jmEg���
���v���������#�h@��aE|�+�]�V���fH�CA/)�:�O���"8_*Wu����@4��
�p6���3�GDDDDDDDDDDDDDDDDDDDD7&�����jH�Vw1�hj8mX[��^S�a-Q��Hj?�l*��l���no�@�I�4�$I�����d2�B�P�{�L^�[�(d�]�k�,�q��oa�-?�M7}>����*J�?��w��3g���xM{��.�
��<�g���\.�0:���~�r9Q�k�o��w�:���^�UE�7�j��P�:CB���GVQ�}"������V]��#""�1�e��(P�^>:]Q'�K����{*�;����B{"��{���h������k�p���r:����O�l�������?�s9A��{+n��q�����Z�uT5����b���p���!���IT;�hFs���~v����d��08�8����i�M���;�xb�b|k�",�[��?^V��|=�@��2VT���(��"V�?_""""""""""""""""""""��bh������A�
A�B�)�ik��.,u�0�)Z�������u����UL��
�v���������Z9���i�O����]���]���'p:�O��\k�f��y�/���>�\�5u����oc��{q��"�>1����f/��������d�L�_�U��{08�(��S5>��[�.<K/�vi|&i����%|z8���2'���H�����1�@� �LDDDDDDDDDDDDDDDDDDDDt�ah����I�iuG��:���6���Y����()n�3�����(T��i0A*N�+�JH$5����������5�	�g�U��x6b�����������r���+V�n��
���(N?��"
�c��w��C��Db�U�H��p,Bw�����A0M�_Q2���	FF��bm'H��,
x�3�������L����^L����Bx%_�X����L*���C8M��i5����������������������h.bh����ND�R��b�|t�:9�b������E�	I[_�Z7����L*�M���*��B�P�{n^�6m�)�<��6����GYv���
z���?����@s�]Wu�����%�ly	==C��U��F������?�h��y5��z'2��[��� ����:S(�`h��~	U�������d������okvM�_�_��z$�aE�j����8����!�Hd���NDDDDDDDDDDDDDDDDDDDD�!y� ""����Z�N��ByRM������uRmE�:��E�4�d�V��VVy���Y�����D&��J��fs���t.�����:T5M+A��$G�@������d��������A���l"��&����=~��[!RM����e'ZZ~
.�ZD"��X�����T�2����o����0?�{��<�zv����������t��x-��O�z��"�WP5�'q<���f����������DDD�� K0���XW����&O������������yIp{��<	��u]�
�|�"d�	��Yv�%,$�MX��a���%,[�iX-�U�Mg����?��=o���w�i���G��fkGg���Q�M�_����ah�����a�l�6��
�����0O����P|f8�o�����~�Re�����p�<��DDDDDDDDDDDDDDDDDDDDt}`h������@�v�qQ�G��k��R��������u�}��	�*�4s�����j5��B!�����|'I6tu~���
+��v�����rp���b���08�(T5W�N�Z� ��^����v���,W*E02�����r��M��$��v?vm����RE�h��?��/�Y�U��&
%�d8���bH����MDDDDDDDDDDDDDDDDDDDD4��#""jS_`�kz����9M��-�B��9M���4R�>�M����
���t�;jQ4��������X��hjZU��bqg�|/��\��Q.'��)UK���Dw��`�uWu&�9�����������a�8e	���7��]AOUg�Kf�?'p�T�:���)��!�	'QP�tLDDDDDDDDDDDDDDDDDDDD4{�#""j�,����b]93-[�b�H<�X�8���E��]�m(i���Zo�B{��i{�;A��l���{^������1���9����=�(�u���e6����~������v��+��vbp�qd2g����n�_Y�?�i	�6�����Z(�O��uT���Od�T�ci(�H����������������������2�����]�P�^�s�<�"��
1�d\�t���\
���e��<uN�BY5����h�n�f3�^�a-�BQ�w4;A�����n�.�������f00���uN����Cu���!�����~>��<�EIa|�G}
�R�]��&�?�y����f���s���������*���4�i|o �����
7��m��&&"�����! 5
(��5���W��p��^�TA`Z��b�4�h��z,u(���������"M�&������X�\	�����&"�OZ�u�H��7�����	k�|��)�|	?*>.��FF����'�|'zz>	�sY���D��o3��V ��L���g��A~
n�:�|�B��
�t�DA�Z}�/��C��`�i�������nvZq�%�x��e�'8����f���Z=""""""""""""""""""""����="��(r��e`���/�sW������X����GN�F�t�	����4��^
%/O��Q�"��0�J������*����lX�B��������V~�n~�� ��L�U�O�{���$��W��(M�dr����������*N�H&_����H&�@��m�I����
/o����O�|���G�v���RUgb�2~1�3#Q�����LDDDDDDDDDDDDDDDDDDDDTW��%�,p�I����D�%]4E�Z2ASdL�4%�/�;������%u� ����$�H���O2������0�d����z���d�\.�l��~��=���n��"��?I2~��D������W>�X��69W�l]�����@���iy���bx�	���
��v��f��=���Kq������)�I��5V������xz0�	d���GDDDDDDDDDDDDDDDDDDDD�h�l7@DD�I��>S����&���PJyPJ��+��n	r	fW
fW��Q������C@�p�����D7�=� ����g�r�J��-��`x��aE�k)�U���;�zl�a��u����FFFk�PN����=KK��)��.�������Q.��:��B<���5X��a47�A��a6��{�����v"�<`�0e�8���'�����v����yX�r���K��P�9?����S�4�>�[���84@�&l�8���|:�U^V{�0�|~����l%"��c������G������#���X��=�3��f���`b����|���e���+@f�����$:,���\�v�gG�l����"��X�X�k�����������Z/V�n����F�����:������my	K��9,�����a>�0���cc���M����$�����X�U�I�O``�Q��{��J�;�A��/�o���-j���)zIU�_L�+��f���+���C�����D'K����l+e/N�S�PK&D��C��[PJ���2	�������PK&@��<z��4'I�!�.N�Ye��T���%��M� ����X�-�X����'��UUE,kp7s�$���� ���
}���8�i$�=��'>�]�����7���:vJS�X��� ZZ�^�=]/#�����!�=��k�&���=-�������
������G�L&��T�}
����$�?�@&��=""""""""""""""""""""�E���S?�)��M��s;��3�\~�{nG9�tq�����Q�5A`Z����iq�q�e���M�K��|X��X�����B����[>��l<]0
5���C-ho� n��,V��<�����
#8u�����W�?�e(J���R%� ��i9�����	� M{�\N`l��>J�x�����������a�g��"lKd����Rx*L!}�TY���8~6E�P�I�DDDDDDDDDDDDDDDDDDDDD���="��9	LB)����M���'�]
�hEh������C�Cs�����B?2&���U���79�r�{3����L�4����5��^DQDss�a-�N#��7���E$���o����*��
U�-�"8w�����q��?�T���S�DM��oCw�p8�Tu&��������M+����Z�d�S���U��f���c�1�I�8���<}�&
%�x(���bH����LDDDDDDDDDDDDDDDDDDDDt��#"�M�/B-�y��Ju��j���Wn�Z2�/���T;��"N�l��@>��nM��w�s{���Ws�h����`���UG4�������������+U�U�4����w��S����X;�JL&��������d�UqBC"��!�:]���c���_x���^|zq;\���$�k�vp?��"�"V����L�aO8��:?&������l���~$N�����7��V$N�.������a�D�b}a���\�@Z<;����=���g�Z{�/�������p:'O�p8Mc��jx=�`��G�����`�T�hZ������w�b}����l��{���Q47�	Q�>���Y�B?����(����E�pw;7���;�!U�T)��'�F�D<�f���3���,�����X�6�DDDDDDDDDDDDDDDDDDDD4?1�GD4[�!	 ?�^����;����Cu�]���$��jX��U��\��W>2�`J��[ ��5Ne�b�0\�f����=EQ�������i%V��7���Y��}�`����+0�����X��#�=Q�N��A�������ZU��bq���B(�e~L�|]�Y��/��/oY��|MU���������XB��R����c4��
�p6��W�	��������������������h~ah��h�����7��Vk��E@j~��nC������BY��0
J����<��e��&�����}�>�'���~�����P��f�n_������[�GW��E[U�A�l:��'��+�~����L������bi��L*u��� �8]7�U��X��\�K��}'��'�#,-��'@VQ�}"���"�g�2�!����f���<�D)�k��J	?�#	���9��jx9��X_�(�5_����C3��u���5�V�����k��Q$IBss�a-�L�Xd�f���6,[���m�KX���!�����b�q���q���lcx����Vtv~��� I�i�kZ	���:r��tX[w�]�vK/���xei��EM����?�a���5O}�X��_�D��H����\""""""""""""""""""""�k���lP���4&�����PK
�'�J"�O�k2I��l2>��##��+S� c�������������~%V�q�^���>,^���m�v,Y�?a6�>�L������}������4����	��kzz����|�/�c}
cc?D���{��d�Vg�6�������g�%�:7������.W�O��\O��c"��2�������l�T�R����������<�g&O�{���}m��x����C��LZ��-�b{����^�����o#9��v�Z8�t��e'zz~[n}���
�����f2'q��c��{12�4��E�hn����n_X��l�G4�24m~M���d������om�n:��L��3�<��0��'�tgR9<���h
e�8X}�t]GI�PPU�T��cDDDDDDDDDDDDDDDDDDDD7����f�.�(���J)��.��1���]�d��J��6�������3���CR����I0��w.w�������A�8m�T*!�H4���$Y��q?n��V���lK�>�����?���wa`�?�(�:vJod6{���^���&�g����"����G�N��w���v+_��Y�+����$��GO���aQ�
U����8����!�Hd�]��)V,�@$��G�������q<q~�<?�o����#8I!^�_J""""""""""""""""""""�C{DD�@Wd�����4CW��-��cg(�b��Mn�����AN��
1�d|1M�rtdR��!7a�gk�vD�����i�����hM8np77Q����n�\�m�sAU��>[,M������;o�����r9^�N���E������!T����d01�S�������3u��	����]��f�<������a<|v����*U��p?c ��*�8�-��C�p0�����%��+��4c��3��`?�`([��'""""""""""""""""""""�?�#"��qn���Ug���K�1X!�!���Y�V���d�V���P�'�V���gj6<�T�8����7�,���|��x<�R����n<� BUW!��C�s���\�YEI�B�����;p����P�c��:A����������W��BaCC�@(�K�j����$�H��6�����0W��Q�����_
���dC�:}��e�����p����OA���X���0QaO%������8
�,}8 """""""""""""""""""��ch��h�����W������e{�����^'����	rok�s��1���k� b����g^I�B�\��� ����H$��nndTu)�/�"n��}o�����08�U��yN��3�r��k�.�e'ZZ~
���R�	��!<�D�U���(�FM��?_����z�����3�s<xb������D���	��~<��c1�J�'���e�p ���������@�by��DDDDDDDDDDDDDDDDDDDD4�1�GD4�����`�*B0WN���u/�(i�a�k����T������u
�c#��+��f��2�*�#���c��k~��\.X,�Z(��x��\�5X�����hk}A�����0:�m��}/��C�3'��)��������I�M�_���D�ah�����am��,��U����`M����������8X*c��	K���o��)��!�	'1�+�g��j4!/�j��p��="""""""""""""""""""��C{DD�@�;]
����A���F;��a$W4���h�B���"L�;�x�JC�<9o��W`��g�g��;;}��D����
���t�;��9K�b�?�������Q��q�r2
�c�����C��Db]���?G.�jtw?�{=��_�K�FG�����\N�����q��7/���v��l�v����D�������8P� \
��D?�Vd_������(
5
��`h��h��;+OW�����
�P���
��+_�����L,�KZ*���G���+�l�=�W<�r��(ksw�S �X�B
����lX��/�e�K��y����l4�<�
8�aD�/qrb�I�������l����d2�18�b�������Q�m>������
��7J**������(�]6,�rZ_��T
{����DDDDDDDDDDDDDDDDDDDD40�GD4K��*���r?��L4��72]��c"�B ��b�jo�A'ia3���<�T�O�MZ�mZ�����HFM�������hf�^������(�a��bn�������v`��O�d�U}6���W=�}�����O��j;%���������]���'����Xl'G&sf��+���wavl���[�_K��|����
����X���v��������f��DDDDDDDDDDDDDDDDDDDD43��S���'j����d�}��i�=ot'�Y��K�5Ino�@���:A`Z�	T8��$���W�������V����^$���{h�`0h��i"�H�����r,x�my	��}VK{�g��c8z��{�[1:�h���
�� p:�����|[ ��g%���at�)������j�����O�/����3�����sx6����^��_�z8���}��������������������h��#"�EMwv5�>&�ka.���0��!��Q%K
�G����.x�������AZXyBc��t��ieK+V4�3��A���ssv������d�u
�B
���!I6tu~���
+��v�����rp���b���04�T5_�Nol�h����������3�� ����p�y����������/��V���2����cQ���9�6\������D��x���{Qm0�GD4�l�>��Va�Jvx����t
8���O.��)M��}"�B��j�
����//	Bp����2����7zn�M4�05R����k���A�8m/��!��6�#��(����~l��s�^�45���l�8��g�/��.�_���:vzc3�\hm};::>����:��W00�(��#���{� xO�;6��-l�]���BU���0�����nA����o��O3�JDDDDDDDDDDDDDDDDDDD41�GD4�<�Z�U�@fp!��n��Hw��(����Fr4�A�`<Ilm�@�k�� �0���XW���W��,��}�R����6����<*�Z9mo���[q��`�����l��l������;������b1\�Nol6[��>�@�n��u����G8�,���@>?��k�&���-���n���W��B	�s|G3�
�E
������������������������j��="�Y&9L<�
�M���
����
��Z(#r��e��IV�/��J,]�����y��g������X/��^9k�c%Z-�a�������3���V+\.�a-�@U�wD�B�}[�~�7�����������j�_��]w����@>?T�No\� ��^����v�����y?��d��d��XL�\o7����V9�!^{��ZD�e�&������`ju ��5
��W��������Bf�� 5R�{_�4]�K	h��63z����O^�
XM�5=[�r��)t� �v�=*q��"Z�������������b
��f���	k�|�6�--�B�G5����ob���q���@&s�����$��@�ntu}VkGUg��x��^��R�kou��[���Z�����A�]l�?�J��<��DDDDDDDDDDDDDDDDDDDD�C{DDs�����?\�����c[����S��k%+�6#7�zq���8q/t|F�����+�
k&Q�m-B�&4	&	������0�T��5�9���
��u��}nNNt��|�e�	���������X��s�u�s�h�0�����������5:�I$�������@G����v��s���^F4���_C6{��� �/���{����$M~�;d��o_���	<?��X���
�|DDDDDDDDDDDDDDDDDDDDsC{DDs��0���^�?�����:k^����+��P/\wt���U�R���&!vd=RC�he��7����n�e�B	�b���M�n8M������.�������@���
�-pH����Ng�����E�����t:�|>oX���n�Ao�gp�����	H������s���8��G��<'C��� hjZ�����n� T~Oy]�����0:�=�J�tY[Q��u�k�
<����K�,>�Re��D�xv4�'/L����xv$����y�J
�����������������������'��h�l�>�z}(�g�;Fi(��Hz^��G��0w8a�j�}m��+�.��^^������
��:�J�o����)������4nt��c�D�b]��lu����
�p(O���'�P"�^��h���{�
?mx����c_�T���E0����a-
�����Q�Y,A,]��X����:��G�\]�+��x|\Mk�`��hn����6E���	~�mp�V!y���i��r�|�z�|� ��tZ;�f����h�_���4������.���V^�0�+b8W��f�,&�-�Kz�2�Nz%"""""""""""""""""""��1�GD4��Zp���uzI���d�Y�0�/��Z��ZD�~��T�}��N(y�kB2����@>��0����\�J,�DI1��E[��i�O3!�e�V��|h������tAt\�,�/C�u�����<�%��v�����kb���t:��L�h����q�ihfL&.�tw�FF�����D�h�|�T�0y�R�t--��(������dr���]��?�r96�	
��~��'����������C���'�.�/ci�����,��g�������|	���5Q���!��A>>�	&�f�
S��h��E��0A��U$���^
�M�)��~��mA9�����Y`����t���D�����!�����.�Z����h2.j:��#����A�V�=a����!��c�huF�A����(�����F��$���� ���
}����i���?�)��}7���U�<m��������������&��j���1<�$
���s� �������B�W�4��8��aO8��G��s�x�/��p8��H���2yb+]����n�I������w����w �o
1���l�� 1��.�E��c"�B}����NkCz���d�����P����M^�so�x���g��ZM��)��_q�^(jp7�(�hA{�q��g�j���t�U}�P������]����/CQ�u���"<����~.�����c�B�g�(�:wX{&Q��b<Yu>J�U\�p ��3�1<ya�>?�gG�8M�?�G��\�&"""""""""""""""""""��0�GDt������p/ W��+&D^������,p�?��W��<�?�F�l<��*��5��zb-6����u���B�������$�
�GJ8�>T�gJ�$477���$��b�;�F	--o��[~��k�
�{C�gK����G���v�;��(��u���"�v������a��Uu&�:���G�H�����n��cg*��RC�w�X���q����Z��v�����S5��8����8�������g��	'q6�C�X�� ����n�����6�kA�k��e���t�kP�9�^r��G�
�"���������\'���-A7�����.��|PG����)��FaZ�})L(�&l������2����v,t,�]r����*N������lpG�h� ��'��w"�����/"}�����F��08���=��
�������Vtt|��	D�����_#@�J�D^D2y��]����;dT
	E���Z�u��K��e����~�����"V,#Z,_��R��J���|	���aEI<f�|��z-2L���h�#"�Y�]��u�<v�D�����"(9;|�A�T��/�\�{ ����Q�4��HT�/n���ik\Co L�;P�q�&OA�B)h�)Hm���u�a�}	�sg'�/�E�����������t:a����M~��B!ttt4t�!�.��x=� �>���/!���'�iZ���cd��hm}z�?	�cQ���	��k��%��� �8@��L����Sp8���W`2y���(���z�P������u����N.��6�9��YF���>�}V8�X�v���������S{-�/���
jB���k��7r���B|��i5�J���������������������h�1�GDt���V^��'Q8���nEx�
�� [���@>��`v6��9bo8��b<��.��p�EtX /i�rz��^>>
���`��`��-�@�'O^<�=��M��n��[�WCL��J%$�Ix<��7F���i%V��7�r00��������t]���w16�����g������_�D������r�B$�r����f�!�����^�F���������%�Xh1�]�@ZRU��D���PIA��������,�Y��iC���NzV�����#YR.��^������,+H�\�\^����|����5]��#"���V���D�'���9Zq_9�Fh�4���+$�}_�=8�
�xv
g8��<��������&ia3���Tar���|r�5�CxM����bo�%����>����07�%B�'OB�C{70�}!����w}##OB��U��
��������=����P���^�����yD"/�\NL�_�U��{�N�����s�{��Dxd		EEN��h8��	zak����4<N WE�N��3�"�������$��O�s���a�
�.Y���H�����]����'"��1)rJC���5�(\��[Lp�e�s��MDDDDDDDDDDDDDDDDDDD4���I��]�!lH<}����V��o�o�!��@>v1���7���6=����'��\vt:��kh
�(����]g
���Hj�R�������E���?^��h���7���������h4:���Q.�a2��)]�8Vk�-�s,��=
?����AQRU����#��{=�<���9���E����H��Xl��S%����"�<�@�.X,s#.V7��=~q�����+�8xj2q/��x4��D�i��J�������^��a1]�9m�uZ����( ���|�������1���c<_�x�tiM����|>����H"""""""""""""""""""�Fah����[�!���~�$���/�������p/9g�yJx�Q���@��t���p�
������W�;����AZ�z>lX/��u)�b�D$l���O|�p���N,v��)7�-��t]G8F{{�,tEs�����E���O`d�[z������%�q��'�t�������(����^�-hj�C4����i�
#�&\�5���@�l
�tj75�/�������O��NO���=��j��%�UM��V#�2F�e<�`5�:,�s�.��|Mh1�Pt�R���?E�����@�XF�x9�)p��+&��,&X��T["""""""""""""""""""���7�����r������A�+��<��r�o�Q���>��K�
��/�d�8��W�om��4'�K��&������|��	�V\�u����������+z�b�po���l�j.������i(B[[���%��DO�������?�����P��l&s���1�_�z�mm��(Z����K��hiy\�5�D�G�81�	��!d2'����{
�Y|�yo��]���t|;�����h�c��\���Kx)������t�t�2�����u�IB���N+V8.N�����("QR+\�S���
u���dI��7�;d���|)���%������]���@���C�k�QLW��������� DSx	�E�U�H�����bg(Y����@�}nxI�iU'J{����(�67D����f����CI� 9�;���t�����	��`0������B��t:
�knM?��'Itv����"�	���l�tUg��A�<���p�����:�?YvL��l������QD�;������iED"��JFs�]��������6lv;�;��T;U(�T��Y�Z��f:�2�ou�4
#%��2�
�P�'��f���jNd
8���D���<N�
(�q"��*v&2���<UP��f�
�
�+V8m��7��jBN�����e�+L�����"��z���"
��i"��,Cd���������������������fC{DD4��4#��5�}�4�����~��m��>��9 |��e`��e��t]��p�
��I����wuuD�R��`��^>2�mK HC%��
����f�G�9|��A������=���=���Q����n�����6�|���U�-�&p��������|]]����o��)A�r������n$����l��J�FG��s��;`25����u������	E�3��i2� @E�8��Z����������;|��kM��|��y��p<���L�u�����/�B����/��m������|��n�a�+B|�b�r���L5c������x��������M�E����������������������f�7���hNL"|Z�t���s��)9B{���� ��������^S{;���<2����/�7LP���e�PCi�P�T��E(��0-k�����&��E���?�$p(�7{����j��fx�^���I�X,EQ ���C�	��@�47��xb7���X|GUg%������������~VKk�;�>I����p�W#~�|����e2���������ES:���f7�����DU�K���U�{_������(`����+����VT��^9��x6��R��w��4�����t����<i*_�����^�.���%e����Su R,#R,��k�Y�b"��b�E����DDDDDDDDDDDDDDDDDDD4�7����"A���r�
����8&����ye#��G������V}�5����)*v�����Nm�vt����v����!H�.�.@Dl�����p�+�=X�X��S���
C{��!����!*�� �yo��{+R������_TuVUs�*����������w`�/�o��)������#�=�H�(Jj���� ��T�(���Bc&���e����b�49=S�f>�����5�6���v\Z�u��2�g�8��@��\��[z�L�L��x>���&	�b���|}��V�t��R��ri2�rS	�� QR�()8��_Zw��!>���,6�9EDDDDDDDDDDDDDDDDDDD�����hZ�uAH^+�_;-[!�����X�r���S�p���������y�K������J�q`�c�q����]��tAmsC3"�@����C/~�Z��u�����I�U]���_�m���z�����d2�\�������Us��`��/ �=���/c|�i��2�9]/at���Z���g��hr�6���� p:��n�A"q���i��������`�u���NX,�u��g����Ex�+g�P��]�#Kxb�"�L��g� ����a5��f������\�x)�w<���L�.!�7Ru�t����~���u�,��qy*_���.�EC��_�XFA������"���^��kE�,��0���I�8�>���`h����b�q!���!��1(�\�}���Pr�V�(���������(5��kw&��p�hX����$��_�7������=��:��0pim��\��AQ+L�?�?���Y,t,�k���@����j�l�l���$���%X����p�ap�?0:�_�4���+i������z~����{�E|��hjZ�h�%d2��=��bh��p������d�k�}N��|������Z�&<�v���t75�(b���o�W����kA���������aO2�=����VV8l�s��k�`���&A@��\
��
��j��i��0�/]Z�>�|�D>��y~. """"""""""""""""""��ah����&����ZD�u�����
�V�����n?$K��b�����!������L�{�Z_���vT;�E�iE;������	�AD�`�����/E�1��3�
������z�A���B!,\������f���e�~CC�ax��P�LUg����>�g#�<���Y�N9��LMhm};������T�LsBG2�
�����o���
� ���>�
�6.�����&*�/N�}-^|fiG�&�]+�I�m�&���<MV�uJ�����q2S��|��hkg�P�p��g��KkQ�2��N+V8lX�u��$C��KA�DI�[o��#\(#\����o������~�="""""""""""""""""""���#"��"Ze4?���Cv�X�}����[�_{fW
���}X�q��m\�WA�u��H������b�Z���]�����8��NO.j:�c#0���R����'�G*M�^g�&wc���z�=%��
���T*5��D���
I�Si�����d��������A���l"��&����=F0��>'�������� �:�h�eh@�H����C*u��o���^��|&_X���=���v�iZ�T6������w����l,�Yp��a���Ne8��_���Z�/V��wP�t��q$�p9(�3IX��8=p����3�D���h��xQ���'��H�$J
�������tE��o1�.����#"��&H��^S�
��G�q6j�������~�@���}_�~pw7��*�L�0�/�D���q���� 0�lGq�@�&��h�pr��������{c_�n��>���e�����u�}*�`�0���*b����)��'�MX��atu}�c�����P4���f��1=��������hm}7�Y�T9���{-��e��v"�<��o@�)CyMM}��o�,�/x}o��6�q"��B	����p:��r9���%�i��&��	z������z�K"nr�q��~iM�u�K
�g���w*[@�N�����*v$2���<	S��f�8��n�R�-&��#V��+��JFQ�QTf/�L-��Z���d>�I���/��������������������J��5s���oC�������utMF���p/=	g��p�?�Z�4���R%�#�C_�[�k��bj`G�#�����B9n4RN�A
4A�^|����l�	G�'���aG�9�����:9���A�e(�2�
�����$�:?���cb�i�|������rp�������z�?�����$���V�I�
���p�� ~����g���d�����g=�~��s�.��t]GV�P�tXD����&����]��h:���'�e8���x6��B�������8�/�'H^Z�K"zV�p������lB�("WV+��Q�7-��j�1�+^Z���B|vM�b�C*�!�9�HDDDDDDDDDDDDDDDDDDD����������ky��D��.�3}Prx��8����f9���:�O$�T���������Mg�
R��Xz<7��h(����K��
��8�=��6y�hag�'�����mW$�"���1>>>��N����a�1E�'�&������E8�,���t�hUg��q�>�7������|������s���%��� �9�h�E(Jf���^F4���Q47�	�cQ�{NY���r�dQ�r��V��
�)E����|�3y�|��t��@N�p0������imzV�t���jB@�!�:�%��2�\�k��:��2����t
R��}�ZU����Y$�N]Q-1�GDD3fju ���!���(
�+���tC���_s�I�?{1���}�8{oI�Y�
%��$����:��$L�;Q�q�&��������"�h�����-�������n�bXDK]��J04������4�#����`��~�����"���U�-�c8�s�tv�����`�p:d5A@S�r8���E"��>���r9����n_����`6{�-��K�����F��X���.�/N��p"���L���u<7V,c�X�����edXb�b���6:�&8EEE��T��� B��1XP0X�<	�)K�[L�YM��/�i��'8�G�QMHMf~g5b�9���H�}�x3B���y�~��0�
P�k>�
���D����T����&��������@^�rz��^>>
������_�����a��&���Y����m�����T�v;�N'2����"���� ��PD�%������"�|�_B$�\UgU5����`h�1��}=�����U����h��\�U�D^D6{v�3�\?���>�&��:��A@���.���|y�dQ�p&[�4�o����ENf8�-��7��e	}+�:mXh1�/K5 YRP��7)0���(*��KkV��$>�k���\&�A>""""""""""""""""""�Yt}���hV&	��"�<�������)9'B�����,�8���}X�q����R��c�D����V�}��	IZ�:���.L.�('�aZ�	�b�b��|w�qh�H8�~����li�w��A��^�\F"��������F�v���k��L������?;o�i%��|��O�%�N��|N���7|0��hk{r�D"/�T�NsBC"���	�������A�9�"�X�d��&������+������7�"[KIE��d���+���f�����nE���
Ye�	�3QP5����/����E�"��5� �|~5C{DDTS�(��� ���4*%��������;G���]����[��^�3���5Y���s��7Q�iu'J���*u$��
)����������N��C����xO�o�������������P(���
�s9V��-�#�F������=��*�'~��� �|/z<�km:����tu}��!�b��i�)��j����L��@�-�Z[�)���,c��	[�M��T]�@��Z��r��?_2z����B	��~��S|���U+�:�X`6�#�t��Z�~]G�PF�p�s��c�/O����3�`�8�����������������������#"��p���� �������&]D��Z(9\�OCP
�+���:6���h��W����M�L7�����]��w>lX/��u)Y����������~��Ne���iM]{�D�$��~���K"�@�X��b����.�z{?���;���������G�E8�,��[���ax�[��P�L	��g=��^�b;�J��L�8���o��i%������M[�u�^��k�`���$A�"����=����UU�����w"�G��S�������c:�z�I���m��,��BY�b����K
�%xC/M&���|~�	��������������������������i""��no"���W���_%��w�!���x
�E�%�
����j:���+N���[��e��}�2yI�xz�`�W���L+�&��-�����
��'����*���rE�`�0��p���
���JKK��)��.�������Q.��:��B<���5X��a47�����Y�#�U�\k�lC�06��t���3��n����P}��X#�9�Ba���S�D���Vk+��^X,������8$	�]�w]c�������<�g/��Nd�8�-���w.�xY���)��
k2�������.��.�� @���K��"]V1�)\Z�I"|o��,&�LC�DDDDDDDDDDDDDDDDDDDUbh����J����u�~��g��CmP
64�=�R^��[�A@2���Wc��Sf�E��xn�_J$���(�9oXW�������K�e[����I{Z{�/�W��Z��+q:���l��'EC�:::n��/�M&����#������X��l*}��<�c)z�?���w@Mu�x~�Z[���!d2'�l�v�������d��;a�/�r6{��>
#S\��|~�� ����Z;����c��<$�A�j1��b�]~������\���|o���u�GpBp������$��&��,h�$��������\#���S�(�g6]��XdH|O%""""""""""""""""""���=""�;�&���+�x��{*R�)B{���n?�Mi |8�`�������.�p$��X�p�!W?Q�z"���|P�b������,� �����wF�
u������u�F����mO"�� &�J���$<O��"�D����z��c|��������_#��?�)���9�t���~�d�s��� hjZ�c	b�=H$��<S.�0:�=8����+0�<W�U5�px2�SW�O�0���8����4KJi2�(��aC�����x/�'�
Nf���e
8��#�N�<�������������Uv+V���4��hu��5�&
����<��4>������	�DDDDDDDDDDDDDDDDDDtcch���B�Dx��r���O�~�\-��+|�^�-R#��/���f�����>��tkt;�X�tc&���P�i�0y���)B9�ii�m�b�g$v^kG�Y��������~ss3������Pn���B�u�I�8}�f�(Z���A�������?�Ed2'�:[(����O�B�����!tv�Yn�s���(���|;\�U�D^@.7yj��e���������w#D��b1����M;�o:��I��Cho,����E��6���qb��yiM�uJ8��r*��\q�H���4{3y��\�,k�N�	kV,����%�z��]3����
��}4��KA�������Q""""""""""""""""""�11�GDD
#��v@�[{�$������������^z��~�$��K�����|����e��f�Dl	�o���`�`Z����)_���V7�������6�L�8RJb��H)���W�����-2�L��|�F��j�X�����^�(I�N'���a���.�ABK����h�E��������J�;���":;>�����l������l������f�#y�rb����"��t�\�uH$�A��5�EU��/tt|���yFt�,��Y��f������L����M�;�)�x6�p���H-�u�B�����{@�,a���v+�L2�u���.�H�U�g
��l�xE��o1����<]��#"���������>~j�R�A@��
(9'<��A@	x�k��w�[�����"�%*OB�p��	0)�����6��\����a�o]A �2n������kx�}��Xd_��4��S04��"����S�R�FGG������vx��F�JdH4��D��N��00�ED�/VuVQ����A{�o����a��������X����A�b���������d���y�V�������1H��=��z`�D�n�cu��A�p�����^���P��3ORT�2y�|�T>�$��$��n�B�	IB=?	�U
#�"Fr�?��D>�	>������+?�C������'!�,��]n���$ER�H�@R�-Q�d_��������>�W�U�����g�e�E%R�MR��D�H.�� c��:�����=��f�=�O��w��=3g�{��0_LS 3�GDDDDDDDDDDDDDDDDDD;C{DD�%���~�4��<��b��J��aW�H�x�j����k�=im��[��f����	3��zt�B���1/W�3��@�	j������uM��w2��M�P��|;��I������P(���KH&����]�!���c�!{��y��ss����bb����~��?�`�`�'�	!#��Q,.��B�����qJ���>�%���Kk*�	�%��e��a�b���%���eLJ&dR���dY�����X�U����:�U��V��r=�VM����$�����OABW�JR�fADDDDDDDDDDDDDDDDDD���#"�-#G4��$2_�����3���;�4R��B	�����%��G�w���]��h����/Kx2��s����@=:�������YH�QH
�t�y��������ji�Nb�W��R�T���7�[iqq�|G�E ��D]������
����g����p�y6������?G_���5D��{0��GQB��� "��XX�c��s(/�Tz����,�����������}��T����P�`�T�h��l���{Uv=\3,\3,�C�P0�*TU<�S�_����s=`���d���Q�z���cK2mW����4��>�|j�o����]a���H�zz,,^�|8�q����d����r��g�c�e6��#
� M���Z]��	���!%�GcO�{�l�������8d����K�.\����@�eY8�<�;��m��=��q��?��[������aKs�����A"�F�?�X�q���������?�B�<_������<����AY��� ��<���i�B���b��������{�zYp��q����R��@�Vdi*�h
�����_K�����`�Xm,����F>I���"�km9����h�	I ��()?2qp�_p�Z�_}���Fpp
(�g>
�� ���f:.^��v<��H��wo��_	!�����im�sKp&2P�%'"��r�2�b��Yko���t������,\�xq�{�����(N�<	UU7u�D�������
F�?�[_������k�vi�,-��h�������F�H�8��CXZ�.r��l~(��ju��]O��x�s!0�k�5�7i,7]��F���X�h��)��m�������^_qo��,aHU1�)�����)�K��9B�q1Q60Q6�TI4B|��1M���oDDDDDDDDDDDDDDDDDD�C���|�J���/^�[�������?
�B���fx�s����O�Z�{�9������"m��I�5(G`_�j;n_���C�T�B������f�����f���GV��������6?���ccc8|�pW�Ot/4-����LN�n��=�������^��o�
B��0�����$�?&�$�>�����Y�����q�����g{v<��4I���GC~�X��8k��6����6��{�q\d���]PRUj
�T�51Y�ZH�r=�VL�V��2IqM]�K�
�.
����������������������q��h[�D����X��y���������x�-����?�| n��Z�����1h2/�^y�t^��:h��.LA{d0������q�t�uU���K����HW���d��������J�����2�P���{�~�3����A�zkM��q��������������$�]���bY���Z����hw��
����T,�X�znUM���Pj��]/��(_��p�0q�h��4!0���V�!U���@�R����E���a����QUABWa������]��_�#"�mGI����SX��(�k���!�UH�:Y7�k��Q}����\��vE
0��VB����|�J������y839�Q���wc�|
�g��;V������8�����j����0�G��,����g14�S���+�����5m[����K�7n�g�����3�Q(J��3��<��a�����1����HF�/I�u�u|0m,�8..��m|� ��bV��
2=7M7M(���o9��*��Q�]l��Y6r���jcY@�V����|!E��!�C{DD�-I�_>�����+����|sg�A��Yh�0���T�=m��2���tk�������}�}`�:?)��� �?�������/-}C�_�"��6�r��B��i���B��r��@ ����IR00�����0�c��A>����5�Y\���16����1���1���X�<��F�&�5p����F%��Q����D~Y��p�������V���X�h���T��h��(���`�r����qY��V�
�
�4�{mxe�E�6p���|�$��-��b��A>""""""""""""""""""���=""���,!���������
��u�N����O!q�u����F��<�������L>��3��W���6��3PO�<>�K�sX0[C~y;�7r����g6mn����o���==&��BB:�>�R�E&�]��}K����mgqc�?��������b��_�O�����s���&Ls�9�v\�-A>U�@Qj�Bt/�D����"�P��D���v=�����R���f���cg�����f�.$	�*�4��K������z�����4��,�����/�+<�$""""""""""""""""""��6'�@���P�~,��Exf����(����{r�������������'$��^����6@�Lf 
E!�����g�����R�}����Ft�Z������g�J�RO�G�Y�H��B"����06�Y������u�2n����5�E�(���*���Nxb{q��)�0���*J���=�l�m��E��"	�p8��G�b��E�����V��R9���c]WW�f�N���`=���*P����x��aa��������|*���O�����DDDDDDDDDDDDDDDDDD�=1�GDD;���$��8��/���omp��>�Sm��j
���ty��������o|��MBz�0�"�_���I��jY��������=^L�y^�Ct�b�������R$r'O|��U���6ff�
����������SLM}�}���'=��o-!4H��5���6b�E�v��d�Q	���.��V���r�_�h�B��wF�xg4�X�y����W�]-WawhR^/��0nZ7-�~Z �S�F�oH�}��R� g��Y6�+��EB������Rd~~�b�����	��7Nc�`M�nV�>��p��v�s��y�H���B�B9�w&��&<Y�`_��z��x�x�]�Q���[iYw�:���8<rO�q��y�=k=������C�@0x?�������[������1��bv�����:���12�I���v}�[E]�G�rs����\�v��C�r�eT�%����O�|��!���a�O��V�D�t]\-���bKUL�h���i���e����H�r��o��/����e�E�6p�����I�z�o9��H��""""""""""""""""""��#"�E��H�$2z	����j@��'S�9�;�t�{@�p��Y��tw%!KP����������"���x>��'���\�������-���*i���mRE�:1�G����G�?02��u�����"�x�
,.~���B,�8F�?�D��]���vYh��<��e-��������V��6�����$�������g,��*.�*��F�UT\����Xt,V��4Ct!Ij4�-��Rj�~eb�f*&f*�� ��kj3��S�(]j$"""""""""""""""""��ah���vI����������8���������K<4q��;T����z��s�m�d���[����	hO��%	���[�5�Z�+9��}O&����lU0�����������2�D�']K���#������������]6�
����p��G>����!��	��BG��������}��m�`Y9XV���WD-z��<��i.�4��K��c�OQ"�$�8J��UO�Cx:j,s=7�f�����X��z��������r���j3D�Q�����
�.}�w<`�����iP�hJ��o��'3�GDDDDDDDDDDDDDDDDD���*I""���$������������p�.`)����L�	�����B=�����3��e�+���C=�!�K~?�|���������x0t	�s[����Y��8�����R��R����	���X,�x<�h4�>�%���Ob��_����qs�s��	��S(���s��@���?�+Z�t=
�o��������H�X�1�s`�XV��k��l;���qJ]��Z�n�Q�a�����m��e9��U�O�w������P������\j��.+�P�`������0fZ3�!:@�r��0���6<@���3m\/T���\�)�0_P�y"""""""""""""""""�m��=""��
��7�X6���KgL2����U
"r�
D5��,p��@�Hg��U�zl�����;��!D!�}Hj}8yo�_mY��������.4B "���{��bY���1??!"�H#�����l^D�A�����c�3�Q��~c���r����-�o`��������CC?
Y�wy���?���������:�	!CUcP�X�q����-}����V�4��q�R=`�.*�(�A�f�OU#���I�NG8	4�y��y�����V�K�*L��z����i�����2 ��� _#��"��6����d;��"��K��|I]EDS �s���������������������#"���<�8�������\�oeW-+�8�D��� `o|8�a`�S=���$�G�F�N�Z=����zB�3���.���j�����<j�*u7�PhKC{+y��\.�\.���q�|�F�/C�RQ�I��������b~��4
�sk��0fp���7�����8����j��3��`� B�#(/u���Cnx{IR�iIhZ����+Z���P_�c���n�[l�4&���P��� �r�OU��$?C}�1!�t}��w'"�����z���bK�V������=���E�����<,I����4I�{��1\����L	]ABS����|qM�"�����������������������#"��B���$�$�.�{R�<_ev�U?�'_����������T���P,�e��U��-B9��&�x*�<�~��m������a����7��R)LM�kj�z�j333����,��F���b��b�4m��G�nBH������c)���>�L��k����p��oa����w��b��_����<���N���D�%ns�r�������$I���������u�m}��>�k�z�{,+���RiBm��W�)J���~���I���W�k�m����|��������
��KU���sV]�Z�OS�|}��K!S��0_�0_����
��� Yo�[n����HDDDDDDDDDDDDDDDDDt�ah���v��i�����j�Z�:7���8��<����PCE���@e8�Q@�E��%t��AXo�kB��3��#�>����0Y���^�-�L�E<�|����Q(��m/9����%,--��`��/��v!��g�L<�\�u���\���S��������cp��0��W������7�,�14�c���3��q�
�H�t
�d��i�\/!d�_��@���yp�R����f��-���yLs���v\��z�/��q�cIR{<c�JE������<���a�
�����Z�������y3-���sU@��6�A��G�R;� k���6�����"�
�%tAE��	�0�GDD;��yxa6��b�~��G�5��P���sN5��3O!y�u�R��%��g��|������b���p���������@�g���/O�>\���\(��#��H��A����K�62�u9p�\�E&�A�P��m���R��R����I���h��F�P�������N�6��K�,fg����������CLM�1��?����@(�`�'�	t=�={~
SS�)�{�����m��A!%E	��2�y.l��*�����8m�Ol�5`s0�����h	�5#B���������������hc����R������������lLY6P�@R�k�|�f>�.��mE���R��L�$$u	����"�SQH���'"��\���j�=E<��$I�^()���<�}p�sT,��bG. �o(��|8�@t_7���#��zl��N���.��Ld��K �&p*�8^�}�e=^\�&~d��������L&����Ui3$�I���a�6r���,��,,�s���X����y���C�p8�x<�X,�����B�#8~��p��o����aj���y�]��<33�
33�
���cx���FN�`��F�����c�������O(������ao�!5�n�x�
�Z����|�F��u+m��5�)�q�0������b����%
E	A���hk���������/�6FK+Z��U\,UQq�`n��`;X��]i6zF$	�Z=��*�T$���H
��T��T���\q]i��%tqM�"�\������������������hC{DD�c,^_,t,AXm~k�K!�k>,|�<�|���@��1X� b�B�����
�;���`w~
��������!��>��>�+�(:�����i������vFFF����)<����Y�LQ$�I$�Ix��R��l6�L&�Ri��[��!��#��c||��7|�H��0mo��0z����9n��=LN����������o 
#��D<������B��2�3�V'�������cvq���
4-M��w]�%��2���w���ma����%�*��|�B���=M��<���l<�X�x�+&FK�U�|c�S�]�]���K����O�UA�AUE�*C�����<�W�U7��Z-��2��w�������������������h;ch���v����l��J�:�D-��=!���i,|�<��������J�o@R,��/�>����k&�O������[m��)h�C�T<�|/�n�/������q p~����NTU���Gq��y8������,�8z�(TU����P�P{���i���\.wO�1333����$I�F���b����4m��%�6]���C�#�����/���`Y�5m��|��w	����'�J�o[����a,�X��ju�1�m6dI�]���7�P�!�zjg�=I�]O�}m<���mZ���eyx�����������8P���5�5C}�+P�X���n ��:~0k,/9.���X��B���7Z�`����B��p��p�h�����!M���`HU1�*�������6���k��?��H��|I]E��" K������o-�d�oOS%�g�b/���:��8��?��������.�a��SH�>�_��-P^�a@����B@=��KW��C������A�b$p���f�Z�z�[��2���S\���;����Mi�[�j����>����u]
�F_�Z��|\�E&�A&���7-|�P������18����?���������a��i�|�-���'���O���� I��[�8{@-d�y<��2�P�9z��ed���e��<8N�%���������<���Zj;��C,K�i*(��M��}���$1���e�D�x$l,�<����bJU�+-Up�d�����g��lLZ� ��R�Z�������W�m7K�s�,5����|aU����DDDDDDDDDDDDDDDDD��0�@DD��B���K���O�����!�2�?��C����Ka��y�S�B�f���@e	8������S��H!��>��g��[�� %C��g����8�6�H��o���q���{�@'O����;5�&�Lbdd��
{k����F1<<�j��L&�l6�|>o�/+��(�������(��b�?��S=�^d9���~	{��,ff�;��?�Je|M��JWpa�_�������_���O��[��B0`�+B(J���7�2�y.l�T��n��a��-�u+Yv!�&|>�����>I��h����/�7����U�*�OF�-���J��oE�o���,��0o;���Yi��Fd	C��*��P�|n}/�������rs���J��OW�T�]j$"""""""""""""""""�6^�GDD���zxa6�N��}A��k�	I ��PS~d����Mp��:�_}���B``�\�|8�q ���3����p�s�
m�L��4��{Qcx$�$�d_l�����$��UUq��a�R)LMM�PX{#chh�x|��]�����A�q�r�F��������,,,�=��>����/�6$I���Oap��17������5m[�N����7��3���e����P�p�gL��T5U
��o
�{��.��,+���q�[0�V�[�aT`����\�[�Cl�{*mUx(��CA?~��y^��l\,U��|�*FK���I�y�����X�C�R����r��%l��|��|�y$�4eU#_BW�u�������������������h�0�GDD���Kyd��6�%���b�"���a�G�U�����s��]"|�*Dy��;�@��z��}GH���0_��v���@�AN�p*�.�#ggZ�[��q.�NF������q��q��e,,,�T*�X,�q��:�,#
!"�J!l�x�%�2��<�C�\n����&��P(�P(�����u����F!I�����2��}}���?bl�3����i[�\��k�'��?��{~���"4-���n&�U�AUcm�]�j	�5sp]��v��8%8N	�T�QE	���4��d9���U<��X����<����0��V�ke���U=�
�
@��Q0�h����TZ���<�F��q�����2���������DDDDDDDDDDDDDDDDD��0�GDD��l���L����}1yC������Oa���a/�i���_v9����!P^����?>����O�����m��s��}�������W�_n����Kx ��J���Z���@��v�u��.$I�$m�������w/,�B6�m�Y4\/�00;;���YH��H$�h��u}���	!�J����������g����k����4n��=
�4���S�|C]�1��$I��%;�C�h����|+�}���&��������|�Q!�z����=�>�$��ngB��������T������R��B��o��o���1:�LX6&��v@J�k!>��R���W�,���9�O�M|��|U���������������������C{DD�-Y��f[�����|8���1�t�O���^�y����P����G��k�58�e��| �Vv'��~��yxe�e��X���@=:���������,��w2������y	! �2dyc��^QU�t�t���P(4Z�*���w�����  P4�b1��qx��I�'��x�1�c��P8����bn�oP�[�3��bb����~��?�`�`�'LT'�:d9
]O�����X��P_3�gYyfo�s`YXV�s0!�U��Zc_���'��oG>Y��p'����LK�Z+_=�w�TE�]���`�v0o;x��l���R��O��V��7x����:.&�&��9(B4|	]ABW�T�]j$"""""""""""""""""Z��=""��^](�`��x�/Kx�/�vl�����?9��_^E���������<����PCE�����"��O��)s���,A=��+7��;c��b��<�x�*�a�i"�V���B'��?��)o[BD"D"�Z�6�w�\���v�r�rSSS�e�H�i�0��oL�%��1�8��Q.�����`z�/��T�y6������?G_���5D��{0c��ja�d9�o�e��<8N��4��{�fAUm����y%�vk	�v��Y0�E��b�qI�W�n�E I<g�NR��g�0������X�hi������Nr���cb����/5��S1�)H+2�.���������s��4����S��Th]l$""""""""""""""""��C{DD��L�
��J�������
iB����P�~��v��zN%��3O!y�u����[@5��@w��~'%C��%��Zj;n�����!�0�{���������M����C<}������q���F�i��������������y�q�R�b��D�.�'�$8��G�=���y��br�O��ki��07�7���$�ad�S���{��%!%M���5�)�y�H�������Z[�����yS/�����a����@K�OU����b{7��d!�@��>|������R���*F�\�����"+���������u\@��`Hk�Tj��V��LK�
��K��\o�S�|�.6�������h[1/�f;�
��?����
!y�>(I?2v	���]�sT,��N��\@h�M w8�i��/��M��n��3��e�+p��C9��c�Gp�xK�B�zY{	o����������"�2��8��8<�C�\n��
�
�W�J��[�n���[�4
�X�x�H�&�g��������
F�?�[_������k�vi�,-��h��������"������v=���m�n���t�>�)�q�0��6��j�V��P� �`�V	*2��H4�X�yfL���W�`���R6`�����	���e�����C��AM�5�i
R�������`�Xm,��R#�����2���0�GDD����<J;�����/V�,�)(q_8�`�_����xv)�����,p�3����vu~;�Pe����zm���}m�@r��g������q��^�}��G�Z�Z�."b��=�,�\�L�\���\+�4177���9!�F������m~���MK�����������~�9��ms����[��P�!����>I��D��I�MK@�m�]�l	���}�G��xC���`��v��d�q	��7���E�(Q�2�`{M�A]������Hc����V6!��*FKL��o���������1YZ�S����Wq\L�
L��sP%���l�K�T�42�{DDDDDDDDDDDDDDDDDt^�JDD���R�����������oX������������.u\�x��J���C��������l�kG��������z��'�=�}{�`�8.���f{6^Z�|��G{0��AUU�R)�R)x��b��L&�l6�r�����x��h����h��B����C�����b���cz��1>�;�Vo�i�b�"�_��~��0��W18�c�$}���y��� I*d9�Pm	I���i�z�e��<�n�%��2��y�o��[n}N9T�
�����Q�2����I���8������e7�|+KN����eY���j3d�UC��!M��� �������r=�VM���� �+�F��G��BDDDDDDDDDDDDDDDDD�5����h[0/�f;���'�������������\Dut��z��>��}
��g��������?^�{;����"`�^���*p��H����0V��5Z��\�X�*F�z1�]E�p8�p8�����0d�Yd2��y���.�o�R��R�`zz�,#�"�#�AU�M|D�����{~C�?�������gQ*]^����M\��op�������=C���i>��%��~
���(����AeE�">�H��?�P��=�h3! �~��@�x-|Z�7��n��-+�����<��e-�����I�^�5�|+�}���x�������XO�B�e���V��h��o���z�X����z�fX����O�@=�7�*��
�.�\K��%��L��U�!������f@"""""""""""""""""�^�#"�m���9T:�l���#=� �2���0r}�';�g#�{��N����^*������on����@=:�������H��A<{^X�F��^^���
C����������p]�\sssXXX�,o��r�q������Zp"
5Z�����+$I�������XX�����k��0gq������g�o���o������o�����0>�����t\��s�d^F&�2��?�X�1����:Q/	!�(�z�u�e��\�v�� _����b�'���0�y��|�qY�7���C}���0���O�A�~�~LG�+����z��@��e�u���2m�2��J���!M���4�|�.��,��X��X���F�o9�Ve��B�������X����J����cP�xA��I �C��������d\S���O"q�M�g������N�E�ot���b���p��\��x��MB}l�O�b�m��3-����}��������$!�C�e\�x�,7B}�r���],Q,111UU
|�h����D�!!�~R��"��.��>����k�����1��p���b��G�o�/���q������fg����fsg�}���?�#��u��!$�j����o�<����:�����������88N�1�v\�C��]�[~C�ayS�e	���
V-�7��V���*��w���fm����W,���TeU�/��6���b�l`��l�V%���"�k��b��A>""""""""""""""""���=""�R��w�r��1������P>,~i^�i��+c��G`�/!<r
�8
��_j�����NxB@=��W�6���b�d���K~?�b��m��F�=�������K���\.cdd�@�l������r��eY��������D"�>�������wB$�O!
��[�,���nM�:N7o�W���"����H�z��E���/�0��|�jv���f�������{��v#�M�C���R]�j	��|t]��v��8E8N��T�QQ�EV��5C}�d��&Ik*�	�J��l������R�����Y5�����"����b��$jM|��!��K)r�Bt��a�jbv�$��Z_��OABW��F&DDDDDDDDDDDDDDDDD�~����<�����&�QU���H�g���p}�:������T��^���� ���0����?
���l�7����}�����=:
9F�7����q��F�:.���M�`�O�B�.S�T
�T
���X,"��"���S��y��r��r���k����aH�0�6I$r'O|��U���6ff�
��{���LLM�)������ax���P�������;���0g��k����1�{t_�$����%��;NuE�/�^��[��r�y��\��B�+B}��P�$�x.sI�p���A>�k,/�.�V��+-U��;�����z�jX�jX�e�@#�7�*��
�.����hXX\1��2�� _����f@"""""""""""""""""�8����h�\/T0^j~��A����j_}�~�_�s,�q���^���'_��Y�[_���������,�L������0��a<{�K�Qu[�����z�>��Pk/������oL�l�r�\�}w-��*���1==
Y��F�����i�&>�_�������M���9LM��[�\��}�s_G2�<���y\��6-����sx��_�O�T�}+��F�}�et��e��<�n�%�Wk����
����s`YXV��������#���o���B��wF�xg4�X�y�kE+_�\-Wa{��ey�M��M���C���z�oPU���M������F��3T@�j!>���V{)2��DDDDDDDDDDDDDDDDD[��=""�e��w�;�N�CH��gHG�H������_�����M`���H�>5X��
PZ�a@b#���=0_�
x�WI��y839�Q<��>����i������}������~��4MC__�����.��|#�gk	C��8���������`0������{p���##��[�>���/�q�k�vq�[X\�V��f���t��������1�v!d9Y��l�<�S�-������I��<���\h;.I�A�H��h��/IR{<��K�=>
{|�����t]\--VpaE�o�����\���Y���+��e	C��!M���`PS��w�_v\��&���.MH����[�b���ODDDDDDDDDDDDDDDDD=�����yxi6�m�t\Sp:����G(�?� ����1�q=������<�|�E`�P]N���{8��I
����}e���ua
R2���p��6f���u�N�f_�S���=]�I��x����V��_�P��&��V�R	�R	PU�q�h4
E�)-m���p�����O`b�q�������zZ���*�?�T�_�����������i�<�]\��}\{t������VaUF��%Y6|�@�r�/!x����$	��x8����X��l���P����c�����Y8���8�W�!��$0�����TIE�Z��t=�TL�T��2Y1��k��]l$""""""""""""""""���
g""��+���&���������!�@�=����X�������]�V���c�9���[��5��g����z�����������
��4�{�\�}�����i�y;�*GRK�`��B��~��~��m�r9d�Yd�YXV�����,��������p�����3K��(a��|���"�������C����9�������L�n��w]�]X�[~��\����p�R=`8�fT@QB�f��-}Q(JB0��I\U�t<�����2��p�j�Z�V��W����%�����������l�R��
�.�X4,,��-��IDATU�z��h��)z�+���������W��O'�H�jgt�'�P�>,|�<�b� �'!{��r�����Zp�������w���zb/����w&2�cH��8yo�����������G>
�����(��d2�d2	��P*���d��fQ*m����<��y��y������5Z�"�$���:����~{�>����bl��Q._���d���X��P�����IR�i	hZ�����-A���yx��v���`��v��C��[�X�E ��[�F#~#~?��~e�����V�bJ,YN�����q���i�S!@Zm��-��|]<��Y6r������"5��C����:0�GDD=�y^���r�wP$u'��c���/���8�����5S��^������������80���v���~�Rpn,���M@z�A<{�JQr�-����\:�#����.�#!B�B�����4
|�\�������V�������$IB4m��i�����v3IR18���Q��c��F�p������C{D��$i��4t�����<�n���m�A����G������������,*��Q!�F�������z?�m* K8	�t$�X�y�M��f��b��K�*L��g"��ec���Z}��e�|���!MAD�^^�vQ�
�*5��5I�
�%uQM�� Q[�Q�������o��\lG_���|H������:�W]������<}��
��3��|/�����R�����+��G������Cx*�|s��m��������d��K�H�4���������P( ��"�����hM\�E&�A&��F�/
�-��J	}}@:�~,e^��s����-v���o��XD����e?d���e��<8N�%�gY�zc_���y����i.�4��K�^�E�+?����������U��*�/n,�]�+.+�X�����Ums`�q�Tqp����$�!Um��
�
Rj�~�g�f*&fV�<' ��n�K�
61�GDD��3m���9���dq}�_�+�
�{�����KS������4R�_��7�(/�Z����:l��%(���z�F�qgl�`�b�o���u�ng�/�����<[���v�h4���aT�Ud2d�Y��yxmZi��\.�\.crr�� �!�#�BQxZL�	!��?�Z�Q���o���P�0C�D��������{��.��k��l��ux+�����i���e����[n�C�����"	<���������4B|+}�5�Yt=\6L\6�!:M�Z_��oHU��*P��=������a5�	U���|�0�Of�������������������/���QDD;��Fp�Z�K��V6����lv��M�O��X����!	�>��t��^�X���>��}�co"�?��	T�����PO��]���}	8��7ZoO@{��M�6��p���s��&��N�O��t�|>188�q���-|�e�}�����,,,��p�����3 E-����1����,�ii�z?t���]����C����~�z_=�CD��T5U����@��lXV�]��B}�����{?�6����0f���r�� _dE�/!���WX��X4������<���a���]-W������y7-��P�-����6��f>�Kmx��e#g��^�4�	]i������"�������������������v-����������_&_����e�0x
��(p�'����j�wu>[�\�}�F���!���5COBI����QxFk�<W�����._Bx�Dn8�i����P�g�=(G����n���k�������x-����xa������t�]������D"�D"��P.�-|���5

��y��#�!�!�B��E������C���q��T�Q���q�Z�o9��]o���#�]�P�iqhZ����Z-A����k�x��9N�SD�:�fT�������m��d9x_�����������hc����Z6j!�b��Z;�����0m���l���O	Yn��[������Q��l�J���&�U!���"�)��gC""""""""""""""""��0�GD�]�;����|��:�,p�k^�����g����{5�5�^[�w4AD����|����SX��8K������]"~�m�J8�Y����C=��� T��=�^kN���C���'p�t�6�W�,Fo�X���.m!�� �� �����
|�\��>(��a`vv����$	�h���u}��$��n����C�2v�����~���������}D;�$���t=�v�q�+Z�����m}��z���sa�9�v����Q!d(��@_����$�vu�O�$�q,���q��1ZZ��W��b�������,:+�U�!��$5�|�0_R���j��a�bb�b6���k�_��"�)Px""""""""""""""""�avoJ��h'*/���s_Y��7_���Z����@ ���['����l��~|���h4��Im�?��O���Ga�w0�������<�dT�7~8�����{8��A������n
���`�=���L������h��W�/�`�A��`�gK����H��H��p]�b���W�T6�_�u��d��d�@�X�x�PhW�h5YAQ����w���������f�o��������#��d�Y�A��Z�<���TZ�|�p_�����<���ee������k�>��3�����Y-�g���2��0^1q����o�bb��j�E�j�r�����`=�7X���
�.�9�`XX0�
�@TSV5�%u�� m_�m3��/�P������e`�E����?�9s�����X\q��J�$�l��	��!
�z�?�����3�I��y��g�K���������(U=:c�X��i^�g|�#`�c��-�����.�#�O���mD�$D"D"�Z�6Z���<<�C�x
��2��2����(
��(��8b��.6���B >�L�-�����P��������#���P�%�o�e��+��j�l�`��k7���0���B�qI���V��$i�|_������?�n./9.���X��
�-�8�6<c��1��s��_Ua����z���<Y�F��q���CP�!��� ��*�}�3&mo��
$"��l�������x��2��@�t��0
����_��-�-V-��T�8�x*��z}���O�� ������� ��<���W�K,7_*�����������Ga�5�v��<�/�������l�nY�r�<
���oo��K��������8��|���4������������E@8n����~^0�E"�����Z�'���}���|m�}}P6�mg�P_����:�yl��"���YV�S����p�*�
��m;.�A�j�����?�@Q�B���7_P��H$�G"�����a��q�X�h�Z��J��Y���`��1e�x�\�NH*r������"��6����d;�Y�6�����-7�E4������������������������vT^�5��	���~,N���EI�-c�SF��B��@��&��m�V���8����@����6�����L�~���#����������a��������*^���!�g����m���_����:�P�T�B�u��`��D��<}
�d_h������]pa5�;Y������y��2��,��,
��A��(
(
�u�4Mk�"�d����`����L��w���AQB0�9��,s�1���a��0�`�����^9N	��
��7�����}��1����'!d�j�k;��V=������������������vM����HK�OU�����
�!�����U<��4�[��k�z+��@�d�Y��`;X��]1��%iU���"�t���p]LWLLW�7f��@BW!���"��P���oDDDDDDDDDDDDDDDDD;C{DD[���U�o�%�L�����@��l9��|9�!LD��H�������J�i�o�W���[�o���2fk�h��3��{�f	����a�.�-Z�W�$dFO�*�=t�0��4p��@d���"B����x�
��-��b�d'�<�����ZK-�,Y8�
����b���!�g�X��\.�h�sg��6Msss�����h�X�X>�o��R(t��c���t�X���H%����9Nf=�g���p_=����}!�zzU�����f��h�$���������mZ�j�����u8w�)���m�Q��k�����UA�fK_���yUI�������xcy��q�Tm��.���s����R���j3D��h�[���
�.�&��a�ja��|�Qmu#��v����1�GD��.�p�+��Z��c�B���w��@�w��8��T�Rx�������f�����&���iE�{2E���
;��?��O������-w\�8~v9���7!y��g�?���l���kP��������G���Cx6�>|}�����j�%<|!%�<�g���B�*�w�4m>UU�J��J��y
�B���\��9z7��5�~��������a��?��[��
���5�'�>��������z��}�@���Q.����^�5���#�N$I�������1�������|�zc_m��m<t�yXV��E��:*�Z����>�@�wN�?�*x"��Pc��y�U5��@������
��
��S��J#�7X�����y{����i�Z���$:	�Z�R-c��![���5""""""""""""""""Z7����������aI����a*�{��B�4��<��y�������=	����o�d���`8��������I��}�<��?��r��z�����#u�,d�������?�����p�r��m�S�����c��Gq�4����Y����EJ���1�s�[m���)�i}��G��Z/����H�H����a�f��d2���p������T*�T*����,���X,UU7�YP7�R��������Z������R�o�>���-�g��0ga��p�,l;���������V5��Z��p���C�=�9�NY�C��Z�=����Z�|�p_���J�x��\�i.��$��k�(I��|A��~��:��j�|[u\\)�h�+Vq�T��i�0e���l�~�/$yE+��AUAH�N�\M����"q|'[�w�U����� �S�|U�t�FDDDDDDDDDDDDDDDD���V�=�|@-�w.�Oao�E����������j������@w��^], o�o���������
�� ��c�~�J�i�&V!��3� u�,�H���@y8�@����B�'��|�*��^h�������d��/_���-�LT�0Qk���b�z���x#�=�{����8��O�v(]�������~���\.���f��m�����"k��B�F_ ���m����;��W`����o]�������w�j�������q���}�����a�5Z�vf����[�5}��}���0�����������{��.��|+C}�`��tn�%�5j__�����h	�5?�@�����O�p"������������V���**����������X?"I����z�/��6w�q1U11Ui��)B �+�_RW�T(��<w�<����	�$x�JDDDDDDDDDDDDDDDt�m����$?.�>�i��e����/�����V�s_���)��-u�/
/����,��CP�d�v�c�k�0�I$��	�,0�
PYN�,���C)��r����!���=���������c����	
�3���'�����G�$��q��q����R�4|�B���],Q,111M�
|�h��������q������>
��m�~%������}v�����?��}���t=�W[�pQ�!AUk�6��y��lXV����j������I��8e8N�1�v�\�BU#�������k������Y-�g���2��0V1p�X�h�����X�D�u����Xm��|B�|�?���"C�R���<�W-�W��2 �)�_��G�b3`7-n*���X4,�n��TMH�*�>
�~�����HDDDDDDD�[��JDDDDDDD;C{DD[e�U���G`*���T���0�,�Y�x�`�.^��v?�c$���Z�����a��.�3��z����A��%���C,]�~8�q�����{K>��3��W��6���8v�8�9;s���Z�T�>��Hj�{��>B

��md�����7�o�4177���9!�D-|>�o�mD(t�>��x��_���=]������P��&�n��P����a��
��~s�>�'�4�����"("P����
4-Mk�v]��o���}�e�k����l��.�Z�l3*AQ���|+�}��=�~e!�@��>|������R���*F�\�������F3D��W�F+���b@U�u�
��1mdL�
��gH�W5�%|*��-^�vn��x{���j�6i��0]11]1�V��~����y�JDDDDDDD��xs%""""""����="���y���X��B�TW�<�t�M$�����Y��h��d	O��J��|G���),|�<�l�rW�U"��9������S���{:�^��zb����w&2(�=������Uv�������?�����(H�RH�R�<�b���W.�7�_��������0>>���x<�X,�p8I��
.;](tO<�W�t��av���O�Gp���#��e�������F�oU{�,l��Z/{��p��5�.^�b��Z�����������Z[�Vd����$I���������Smi�[������7�������8P��S�(e���L�|[6*2��H4�X�yfL��*.+����
LZ6&���.�C�Ro�S1�*v�
�h;(��K���diU#_RWQ�-}m������p���F������%��D:
�m$"""""""�Nxs%""""""����="��`�j������&��Bb�s�Y�����T��\� �3�1��`o��� �~�4�x�������>8��'_������80p�w��1)�| ��B�q��4����o;����g����E�d�F��!���o�>���L&�l6�\.�u7��j����iLOOC�eD�Q�b1�b1h+?�u���c�����`��� �}e���b�cx��"�z��3�]d��@`����w���0�wp��}p}��}+���~F��d�Y��o�<�Sn�ja����_���
6��9��%X�R�q!����p�$��<D�A]����=�Hc����V6!��*.�*�4,����4o��%��F>���+r��\u\L�
L��sP�@BWV����
�K��+-�nrU�����L�
|`O	����������hCxs%""""""����="���X(������py���~m�7o������l��#���6LkH��	,}�
*o�w\��$1w�i$O��(��(/���f��@9�w6��zW������C8�iS�Yv�xi�����m�~���i�������u���-|���U��������j���F_0�����I*�<R��Q,^��������|�l;�XGQ����#9���#:��3����k���9�,Lc~���%�l���j��z���>��'����(A�|C-�����K+��j���P�mx��x�<M��L��
4$�U�����|����*R�$
�q4���m�Y�����V��R�&.��k�_�z_��oPS�����tne{����Vc���U�|	]���[-�~k��9��������C�R��o�DDDDDDD��0�GD�d�S==�B�$�����2�C�n����"��T����Pe$~��)?
��zv9��W�F��k�%��������^�+B�����m��.�`,2����F]-��P�(�l�~��#IR�oxx�j���W(���E��R	�R	PU�X�x�h�����	��4�x�V�\��$i�e�(�����fa�����9����
��v�]Xg��������V��1�Gto����a�j�6�N����� ��P_�����z?�6\�
���0f���rpU�OU#���(%!�������XO�B�y{F���W^���aRV�	�0V�p����j�PiJ��O���@�R� c���6Ph�Y=���B|I]�_��}�Qu\������9����X�O���n�DDDDDDDDk��+�>��*~"��@����!�����kt�X��
���������~&�@������X��e�i�Kz�������=���0�P�'��=�s/���}q8�2-c��>��x���P�����m*!�~?�~?���`�6r���,��,,���N:�,��������p����o��MUkU�����u��+��}�����[�jM~�S�������}���4t����1�Gt�����1�j����Z��|��ou�/���v�8N�0�j3*�(���|�p�,��~���>]�i�������O���J���W�b�T��b����� ��Rjj��OA��?,��x�9�,�4�ET�����g3���48Z��f3���dW�ODDDDDDD����JDDDDDDD�C{DD[�P�����%e����'�y_U���s���G�A�{>�8�9���\�[���$d.��]
"r�Dv8�i����`_O����A8s��[��F�����C�5mL`��GBKo�~��)��d2�d2	��P*�-|���[t<�C>�G>����8|>_��/�@��uD�J�F��q��p_=�W,Nbn�2$����b{�l����z������~hZ��>�
�$�����H9��&��k��<o�7	�<l��L�����F�����$����>�,�d8���������*�7Z��b��7*Fc��,�|� ��� �t������,�,7����������R�%�{�w%�JU���z"""""""���7W"""""""���#"��e����c���������_����
^����*��v,��x4���������i,|�<��r��
��*�8�&��p�3����z8�����X���?���#3��:�s�t�3�G= �@(B(��}�`�f��/���q�
��Z�bff333�$	�h����i�&>"�]�p_>����o5���w=	]��0�`.7���0�Z��r���l��[�/�������p����YNC�[�a=���VW���}����m��c�8��,,+�J��w!�� �rS��D!��wc���"�P��D�g_��p�b�B|�J#������"I`���7��T�R�m��\��\�l,��4Y���'����,~��@O�EDDDDDDD���JDDDDDDD�C{DD[�s���GO(��o��=<���C?Hk����Bc���/�s�q�lk�*%�C��Na�K�0�d;�W���Y?R��BFx����~��X���r�b9d��c����	���w�m�u�s�����h4MC__�����.
�B���Z�x#����d2�d2�`0�h��B��ZCDk#�~�ko�[�[�����p_-(��p_=����`_#���A�y!Q'B���������<�SZ�[�+��'��<��i.�4��K���[��W�8��P������������|�
�*U�B��<T0Po�RUi
Tj���\Kfo{`�.2�����������8��Qo1�GD��:Br�z\o��yS��1 ���?N}P�|1s�v��;���X<�~?��zA�)H��qd�v
��v�Y�(�^y�S�B��������bw�+=��w���
�������*1��bbE������
���R�k�`���<�hK-��E���j�Zm���<<o���J%�J%LNNBQ�b1��qD�Q(
� �n:5����K����U�>���i���p���>]�����#Z!%E	��2�y.l�p[�/�h�s��m��(�5�v$��\X�
�TP�\����C~����C��wF�xg4�X�y�
J��|U\(V�Z������CZ=��*��w�
r^����T�`���b������v��_�
�o��m����u�r#����lp�����>��}c{����=��n�pG}���{���"""""�u�����X��Q���["�- �*M�m�;�[����K����&���7�����'�?����yxy.�m�i
����vZ;!�~��i?�_�����1���I$��z�6P^�� �������K������O�]������%T�HU�HV#���s7$��<�9��L#��sX�p����/"��#��!������$}S��z�|>bpp�� ��5B|�emx��mcaaB 7B|>��
� ���@ p��������>���i���p_�t���1�G�~BHP�(T���\�^��5��k�n��3n�u+��sz��"
�����bdU[��F�(Q(Jb7EB`��a���}�������j��h����^���s���1Y���z3����57Z������Z��i�vw�����}��m���n��0���"7;�y��m`��
��.�����^�.{7��m�_����Jo��,� e��:�;�������DO�;���t'���8���n���
Od����`�_�
��iK�eY(5_{&W�Zv6��uo��w�����w��=�C�ah���{n���X��==&����="�- �@0�Fnj�g�t��?���K��c��.�������/O~
�6[�*�Uj2���A���5!B�����c��.�3��'��(X|�QD_Dh�
������N�wv���j��zt
���SJ���z
�?�����]
C���)�\|��%�����P�K�Y,������(�j��Kj}�(1����dYF"�@"���y(���_������y�������y�&t]o�"����BD��?�W���P�a��7�>]������Z�O�c���6��@����x�q�5[�|+�}����3=��������6�T5Ei�V��d9���	4I��!?���+�g,��*FK���P���le�E@��Zo�S�RdH�������������>���p[n���i'����8�N���>K5>�Y��*�S��(�6$HDDDDDDt�ch��h���}=
�A,�a)p!sC���,�
	����"������N���?G1~���u���D)��ol���%���SX��y8�N
��+Ga���9Q�^�4p��@x����L��7K�;����������)N%��[	\�L���Q��Z�
v;�����2E�H�)$��0_��Og+���`�`{���eY�f��d2��rp����u�a������,$IB4E,C,���=N��m(������Z�vg�/Zo��-��������L�I�]OA�S-c���u�-A>���������p!�[�PiS(�R�-7���E Iwn/��
����t<�<���f�����}g�U�X�C���`PU��|
�U*�|DDDDDDDD�5�y�<�7�%""""""������H����x��-9vQ������� ��A�T��+]x�K���^���+z�������pfMw�������`�*t\�4�v9���� !��,p�g����v��B�.�`�U��*^���'f��}�a���7��E��� ��Y�3�1gN�Z�#Hj}�F�Z�/�� 	6�Qw���t:�t:
�uQ(��f��fQiw�����L&�L&��P(���#���=�Wl�������?�)�h����s���=����ki����%��,�!�~�-����q���V��
��7���g���`YKm�%Ik	��l������HB`��c���V����K�V��R���#k9H+2Ft
?���DDDDDDDD�#MX�M��z*DDDDDDD������H0�D�������%��x���y�J�a������u.�iLu�I���Afc����~���|��:�gdR�;�4R��B	��7�<��������)�@J��d�&`��.$lN�-`���������l8��N���X�c�M+_��Kj}H�)��o��K��r;^4���0��j��/�����
��\.�\.cjj
��4�b��?�Q+E	AQB���Lc����C}���\�p�G��`p>�P������"l;�h�[������f'���&Ls�9�v\��-A�Z�/
E	C���VY��H�#��2��0o�-Uq6[6^�LDDDDDDDD;\�v�dh��������'x�,��s����W[=
�������	?�xeC��5����3��W�{G<����p��B������O����:�g�C�;�4�'_�������v�/��� &�7��*�7��M�-�]
�������`(���{�;���C|�@[��|>000�q�����d��fa����k�6��P���F���g����}���_�p�,�������������z�o9��p�?���a����-����[��(fq��9h�
U�
Ipoo��"�[�aT`�m�e9U����4B}BH��U��*�����g���������v��0�GD���G�:x��|����U
����E��Q�)��~/l5�v����8��	<�	��_|�M�1m!	D�?%�G���N�_�������@���M�*��������v(xo����g�"`wg����g���=o���S��U,��X2�azFW�����w����V���FRM���6�,��������<�r���W,�[�d�P@�P��[��i��8b�"�d����6�f��c�9�K�}1�z�Vk��V������!I���$�M�C����8���7�x���
�W���a����\��?�����8%T�SmF%��)Js�Ft�g��V5��K9!p�5a�������;��a������{Dl��w����F�w�m�0�������F_���7�����=|�mp����|�
>�M�6�������o����x������;������w��=��������9o�6����+������s���6�����p�����}��-��{`c���<������X�p�r��A���-������9�
C{DD[��S�B~f
f�����A����Fyi���@v�����<�2�����v����!&�o���o���~x��@���O� �H?���pn�n��'!s��r�.C,^�|8�q����7(��q�����z���!d�&�9�lc��y(:�F�o����9�����\�����Kj}l��{&�@0D0��={`Yr�\���q�
��4M���bvvBD��F��3$BD���p_��oE����Q���p_��]c���[���z��}�KI�
MKB��m���������yx^�Z����m���U��H�n����;�����w[��]�o�a������v7�o
.�y��|�}���.�A�^��y��8w�����n.w_��8��}������>)��x�����?��G;n���n���e���������5gC��}��������:�O��%w{�o��I��w�5������Q�f}_�6�o��5i7���e.������m���_�a�y�f�����C[�{��xM��_�\����F^�v6�}r����Kw�g����k���6x����w����{����i?w��Z�������hw���O���l�{�����}���\n�>��C��U��im�i����O��=�e|�On_�����O�p����+�Y6B
o�IDDDDDD�+�m1�����0���_�67�.�����|��m�>���C9���sob��%�wX��F�u����ha����/������(��?R�6�����G�����X��y�������.?�&��,p����_��{8��;�t����_:���B��(�J#����r-d��F�o9��5�|
�j��c+�+UU�J��J��y
�B���R��u�n<�C6�E6�����~#��!zx�Q"��-�����w\�5�7��7�����p��;����������&?���>�UdY�,�����<�[i	�5���6~��{�:��ehOvnan�z�o���������c��	;��u����������������W�8�_�;m#n����g#�Fw���>��Z�yk�f-��m����7���x����F��OA��6�~2� ���M���gF"���������~�;�D�pFDD��|>�o}�[��?����|�������l!��Q1�GD�
I��������4�i� ���L�n�8���~����x���UY}����#�����]�����(#�;�X���Kcx��k�0��o{���C�NI�����X��(�����U�aW�H�z2�����I`�d�&�n�
-���h9n�
)|���*�����6��Z�
�B|K�<rvfMw��(��1o�`��Y�<$�����a�4j���i}��D"�D"��?�h4���y���?7+�
*�
���!�2b�X������,��6�z�}�P�9[��[��z���n<�k���C}Z=���1�G����,��
��{��)�	�-��
X[��=��K��������������wD��=�p����������=�w�0q��w����Y���6�	E/�}}�Esy������f�������>��M��b}���=~�}�*����F�W��w��������6��ZB��}�F�Pi��o�T�w����<�����Z�m�n��6���!������{����#��z�^!ukn"EDDDDDDt�bh��h�&�8��?����6�]��~R��'���9P����w���s�X�~S��Dii��w�H��v��1p�5��"�~kC���.���W���_��yx������SI~�_:��W�������Y��^y��g����?*��������3�������������AX��m�[�-��X��`��n�+�X)���V>2�ajE�R�1gMAw4����������u]�r�F�i����8X\\���" 
!�#�!�"�q��[��P��@_��Z�o7��T5m��O������������IE	CQ����{��.�h�����q6�{@+����8��w�MT�p0��m5���+�n '��m����������r����tk4nm�����u!���cc��n���q�������Z��w���>6?0���4M������B��0�v��Z�������<��m���km���{�f�����W���C=����g���sDDDDDDD�y�#"�FT�G��~�>���_G~fj��F����;��7��m$YF����>t��)\�t�G:����6�j������Z��0����`��������^���?^��Q@f;�V������
 ���;78��g�B������k�(�G������+�}��<^vs/����Wr
��9�%k9���| ����_�PXn�K#����4�j���6��$IB<G<���*�J#�W(�i��b�b�n���i��h4
�C[l���6<����������-�W����g��;2�gYXVfM��F�oU����f��v$!d�j�m;��v#�w��e������^-'q:���s�Q��=�h��ODDDDD������<��$���+�*;��w�	���&{vs�}X�5(DDDDDDDt���U�DD���$��������WP��Eia��l�R4�T�t?R#�H�a�w&�@h`��
v�uK��N���� &���d�]H���P�%����+����W���w�S�<�����i��?�J���?��t���9
�|������~�d��?����<�������n���t�!%���p���r�����h�5}K�<���A���zc�,$�T=�W�%�4|���s��I�����8G����}�P���azr;�3������@RVm%J>RGI$��=�;��Y��>�m�|�%�?����,��LY�H��%�qf'���������*T����@7�
���y>x4P�[htD����P�P(����B������P�����e155���J)b�X��/�J�l;d2fffH�R��i�)��u�p8L$����P(���	!���p�������'��B}�a���#}m���������C���A	��-C�|�f/��[s��Z+�|���5�m��\0�_�����]m�������������o[!�B!�b;������T���B!�B!�	�	!�&��+��<���m<�Ai:�a����g���	�i���o���<�c:��������H�%zr�P�W�\�_����O}�x���8D������3�?	g����b��S2��_B�����g��n}lg��Z�v�/�G�
���H��L��������-o������S�o��
L[L[U��z�>s����gJ+�X������O?���J��-|����3=�caa����@9��F�������[�A�q��D���1��(###����eLB����}�M}�@�R�o��h��
-��p��4���������u��������+�/�>~�o�PG��.<;�����=!�B!�B��t��J��g�����!�B!�b%	�	!����g����9��fSu�?bxh����O�]f!p��=�H�e���{���9���/�x�G�����pb=���?�(3�~	�^��@��>
� }��F��{�G��PG[���P�j�{s�����U�DEh�*@E��`k����k�+�6sv��������V���$]�����+6�����v>i�Pj�F�F���������c~~���\�v#h#r���������:]]]��a<v��%o�E&�Lr��5���8p�@K�#����p_���*�7Yj�����^��@1��*�_
���C�f?�&'���C)M���y���[��������������8�^|�_�y�.}��@����i���[��s��x�uVle�m,�S���f�����i�W�m4�N��������f�Y��5��B!�B��t��J����
!�B!�;����b�+�_���{���p���v��$�&�x����
�rF?7{>���oc8�
�R���$*��W��������?
��<�����1���?���]#{�~�$?;��k���5|�,�������m
�5��Xxw����kKA�h`���h�k��m�K���)�v1��`����o��d�����#�_��o�.�WZ�v8�4bhh�uI$��|>���:����,������r�/7�M��\�z���^x�x�D"���'	�B�-!�����}�_u�o+?�E�}���lc�>� �9P�+7�I�Ot�R
��l���4���
���c<��l(��m���x)�����a3]��a��=���h���cc���!�F�Y>�m4�N�c���*m>d��:�t��_�<�������n��jA������������fYg������]�:������_��n����w�k�8�F���:��S�W��i���=�k\!������@���W-�B!�B	�	!���f<��U�9��i<7�U1��v�E.�`��[L^���`P�������X�]�e.2��:Q������x;��bx���&���i�N��<I�/n�������Q�^}��3�������8���Q!+���&�"����gp�3U�U�(6���}*dv��/J�e_h�)q���~�F�S���y<����vR����V>tz�~���R#�����`�����Mww7���'���[���d����N�I����w�0���������.�5�M��\�|�i�����t�=�����Nu��H��j��&�[��iV��oK�����r+�}���A��Pi��������=(�>;�
���1~-���DC�7�:�����d�}�>;x��$���	�U�
�����o������Rh�0	c8"!��Y�_�����_|�Eb��~^X���f�i$���:�W�F��c6�N�C��]�x=����j���u:�z�
���uh�6333����}�|���t�k��x+|��[�:���]>}_��c]z��W�4?J���B!�B!�#�=!���&�y.����v���oeh!�q��w������~��K����
��S:3�3�����2�|���eT�?�����m��bx����&W{k7�)�>x_��?z��o.�����O�s��]c0�U������'+��b�x���f�em��
S���at�������h���p+�����xq�x<���Xf��5M��b��f���|8u[�z�R�OZ�v$��`�`0����B�����������;�����fzz��h���W,{�����9���+Wx��G0y�T���/�W�YA���+������
�D�37�J��.��/�]���$�����~���1
v�>B�������U��es>�c�>������`���H�D[�G!�Bl~�B���o�����#GZ��������+��C���B!�B!�$�'�;���|mr��������Z�L���g�u�a��o1v�<������������,#��L����/-0~��c�s��y8������v?>��'@�7.�fj�0���]:K!&v�m��E������HR]!�B���o!�����0�m|��|agZ�P��0��]�Z�
��q����4qk�Yk���]ekn���n�VyZ������ _�9@P����������G__���N��-|����'x�G"� �Hp��m�@��/�2::�@�������(G�m���b;h&�W($K����r�/?E���u�u���,��R-	�
�i�i�����r�W�{.��`��V����V2���Q���OA���8n$9i&���&9d���+�������B!�B!����������J��p[�G!�B!��$�'�;�k3	�v�������`w��R�F����<Lrz������u������^n�|�;]`(���/p����?�_�����x��!����D������Yf~����A����2azO��J��W�=��	����hA���9���iC1��������wg97g�tr��O�n�+6�Pfg~��i>�C����<�#����|qk�y;��V�)f����!=B�9@�1Pn��2z���vnWJ)"��H��{�bYV��o~~�]��j.�cbb���	�Rx
�|[�x<N?===m��BlwJ)#�a�
����b�oG����������A	�mS==O2>�2�������M���}���<
S���p�IO����B!�B!���gn����Z}q���N��0�B!�BQ����b������;���n�Vw�j�C��9����_�����8Vc'�:Z�����<G_�2#����P>03_����_����$t�Y�8��|�A?y��o^!��B����#LeC��y
�x�W���B����E���\��u���0�c���	�^��K�p�9��[�j� \/��I,T�}� _���O�@+�R�}����n������=��V���"���OC�����(���a>i���L�dpp���A\�%�L�[�r�����������1	�	!D�T���o:���[���b��������b��,����P�����p���qR�kk.���C����'9A8|h��B!�B!v(��@`7�\�/�����o���B!�B� 	�	!�c9._���;�H4��H�����D9��s�}�	����������_U�F<t�x�4��]F�/����F�%�N�7���Yx���O����XI���i���;�_������f����?�F$	�~�}�=����
`�~��Yz#C)�
�!�G�*O�
NU�o�#�6�����)�N-�N�*�G�Jm|��>�Z���C��l��f���D+�[����T�����Q���t�����h�FWW]]���l6[n�K$�5#�L��d�$T*��������I,kz�����\9�W�+��C���G6{�Y�
����a^l�v�B!�B!����'������+-�G!�B!��%�=!��a^�I�.��n����@W�y��&�N=������e��y��3@������,��+�
�S���J
In��v�v�����a�s4|)9��kt�|�A��-�e��\��W����7	�O��/��}7h�?��1�]]��
�C�A���>[s9��Q=a��py��yxY����&����6��y��>+����|��V����c)�n�;X��x��8q{��5�l)���V�4����|=f}� _�9(�|�H0$�k�.�aaa���g��F�lff�}��m�0�B4��p_b��/?I~1�W���OaYS[3��Z-��J���e��!��R��9�i�K���t=����q�����5�i~FF�]�l�B!�B!��U8|�H�8�����#9A8|�m�B!�B!Dm�B��n:���L���va�Z[����w�Az�$�f��yfn���6�<f��������������^&X�/-���o{���?�����N��"��=������U<����s|��=A���D��F��d���G���
�k1N���MC�����}�F���R
2!d��R��s���|�l�[���L
f*[��4xX �Y$=����:��U�V��R�/nM3kM3o�������)�o
*�GBz���7(�|����������[|�e2���177G:����f$	��<>�M�:�u(��s���.���p_e�������7�eM��m� D�x�v��7���C���R�o���'������������4��z������h���B!�B!v�������k��g���0/�|�B!�B!�X����b��;./M����+��p�CU�����<�,�W.2q�"�|��u]��D�Y&"O����H�%b�[�c�^���[�w��<����L{�N|����9C���p�NV,\�B&B�����ux��p�' ����)����A�o��v���:��Qf�uR����u/5�y�9{Y�/��ns��Z�fD�.M{�>yc������b3_��jS��Re+����V�b�o��s��[!���8i��F��44z�>��AzKA�b+_�������"���g�m3??_n�s��J*���7�,����a>���Vk��M�~B��U��8Vw����R����$������bS_1�W�I�om~��v}������;��������B!�B!�h���>���=\�u�	k�����C��-��B!�B!'�=!��!�9�@��6�:O��j�k'3f��O����L������d��[Yi�O1<E�c$�����;��o�~����3�3<�1t��`vsw���;���/c�O�].}o?�l����DKM�+���8t�m���h��CX��jM������	�B��l�&z���e�|�|)��-���k��x�WvT��~T4P�Eh� :����u���A������}��uZ�Ja�A���oK1����m��_}���y�mc�vS��
���-N���V!��������R���Oo�p�j�U��JA��G���iw���]m#�N2u���~��5I0��X�Q��
����g!�&��m���g�~�H�xG,�B!�B�������C���QK�t=�������B!�B�
$�=!��F�Yn&�u��k�cO��}>�O<���S�������������is���~����+�M���`,�m�&��|�_�{�|��m:��C����#���5r��u����z�Y�������������m�
��Q��c������.�S#mi�[�k�� ZW�J�|���V�l���k�`<�R�b���96�eA�RC_�Z�B���|��,qkj���-����O�[�P�Ph.��iZC-~��t]�V?!��"*�}�5�}m}�0_u�o
�������+��J��y���s���}�!��~���4�������z%SWy���I�P��>��M6w��%:�ia����EL'�e�������ly^����7>�������B!�B!����o��3=�eR����N$r����aO!�B!��`[��!�k�^��Zz�;�p�������g�~z��'3g��[L�s
�i�E��c���v��^d �&#����3�	x���o�2<�������h�f��L���u�����������Q�^y��3�����������e�0���IP�9�7���UO��~���7P6K)=`��R#���x�|E����������4�l�����/����V�b@n�jz��"nO3[����k�{;�t�xP�g��|�[��'�|��N
����eYXV��T�p�j�?i�B������0��M�����}���|�����F�O)�B!N*U;�W�$���i���m�p�m�q��O�{��f�_�V��RJ�x������[(,p���x��?�0zZ>n!�B!�B��L����	��^%�������nzz�$>��
!�B!��Q��l!�-�y/O-�wjP���m�PR���#�~��O<�����_�����X��&#O1y���5v'_�+�X���7N|7<���d;e[S���;��2�_n�[�����L��4��.�w�23p�o@�O^�c��1�dg|o>����]5t�X�D���
����t
B,He�����Z�rx�<x���� L�q'*N�iA�`����LP�v+���/��fK�|�6��e��r�+Z����r�o��/$�|B�ut]�i0H��x��m����'�/��zC��i�����Blv�����j��}��|���gMo�pxX��5�P��oa�J��b[�F���]��������<{��^��5�������~i��B!�B!������LN���w��b�C�����^�����i,k�t�m�����B!�B!6		�	!�6v3��N:Ws��=��O��'�� {}���<��;��t��l�������'dM0�z���y4
�W��x����3p���������F�
��+x�:Mn�������0�Co��_��,��Q0Bm�
�E���	�8n1d�)�wND�
t���|�Wn���,0{w��2	�6��Xp��28s��82�Z�T,�
v��O�����K�|Sm�������y���������V��PJ�I$=�m�q�!��7���V��B~����}^!6�u��*���b��V��Zm��p� ~s�m����/39����Z&'����G�����B!�B!��Nl{�k��a��n��U����R:��������,�o����G8~�`=�B!�B!V���BlS���7����'�@�������;���,��g��y���6�~��F��s������p�[�n�l�;/�o�����O��?������������La�~+b��Q
�0���B���W�=��I�wl�J)�P��V�4�� ��h�q��~�i��������mTl/c�e,���p��U��X	�����aB�0{���V��C}�i��������b+_/}�`)�7@�1@�i�Xv�H$������0CCC

��m�������5s3x�V�F~��5Mk�Q!���*�Y+�7_��B}V~zY�o�|~z���.����4����u�}~���W7�w��g�s��s�W%�'�B!�B��d�*���yk��2�g��-79��������[�lB!�B!�h/	�	!�6�y/M�c�	���>��Fk����Rt���{d��9�/����Wq�:�n��z��]��^�2�I�D��(����3�W���$<����K3����<����u�~h4;9�t.H�#��/��Q�9�������x�|�Xy��zx��R�/Q�H���L�o>�3���/h����@_,Pl���|���5�\GZ�f��g`Y+_9�Wj��V�����gll�c�$6���y���T��P(�8N�b�Xl�k��iM��|>��K��Bt@1���a�<@�o
+?U
�M�y����aY�X�ts��R���e~����t~�R�krr�B!�B!���������P��>{3��$���Q���3B!�B!����BlCo'2���k������k[�d�Pw���}O<���K�_���I��"�)S���
?NW�#����]G�A�������sx�o��?��6����~�4s|��k��h-�0��s��}
#��7���^y����R�BE	��Z���N1���.��h���xY���8zq��!>����V��r�/nM3kO�q���^Y7���m��h��-��[��zX�Fk�BD�Q��d���F	�BM���B�ut]���7�^e�o��_����u],����khj4�Wy�V?!�h�F�}|�+��-�T�S�F��D9���Oam�p_{MN~QNB!�B!�X�m�q��O�,���PX��������a��t�B!�B!�X����b�I��5��;�L_�^�����������<|���w�x���T��/��8B��fW�e3o�{6���k���o�����~z�	������G1�,|i����\��W����7	����?�L���e���0Zo�<��<��Un���9�d��k'��[��,d���� _���Q1[��mw��N��[l��������������F�Jyz@U4�
�k�c��+��������]��~:E�4L��4����<�q�-�w��5Nn&�����^G�u4M����uq]���qj���@�4	�
!D����q������/�h�^T��7I�*��U4�m�p_{���eFo��/�*W�c�eY�.
���K���U�st�v���Vl�����1i+���^�|����AUL_���1����u����K��,�_9�������v*��q�4����x��Z���[�j>5��-�kf�������^������^��Rc���
!�B!�h�k��!y��qD�����_��C����!�B!��>9W!���(8�����������<�vB��o�HO�����3p����������������Yc�������oc8�
��o�wP��k�	^�58�=���a����6��"��^|}Af��];��93�����e"{o���!3� ��+`��(�Pa?�������=��K�p��V>��a�����a:���*Z�*}fg~M�a��h�[�g�!>k�����V����|��f��n��������x<��}�����������R�k�b�_��_��;��88��a,�����cnn��:����Z��O��_�B�
�6�y��m�aY��p_E����O���wH��e��*���B�i5�
�z�G(l��������@������,^�������T?V����B�5��
�p���+��t�<���������z�����j��sRs���O#�]e���W��|���m"d�V@���j����[u~��B!�b����2��_l�>&'����G�����B!�B!D5	�	!�&����7�c.U`>mc;Kg���;l����?H,���B���Us[��ww���7��R��G�
��K,0v�-&�_��;����{/����?�#����c��p��o_(������QK�t?�~f>7Y��	��ka��t����Pl:<�c��vr�����z�h=�Z��6^"[��2�^3-�zx�,NbY+��Wj�.���k��5�58Z1=�dJ�|S���/X��������V��H$�����08p�@���Y����������(B��_���7���|�����B��I)�i�b��k��\l{���o)�7I>?���}B�����p5m����!������_�cV.[�\(]�f�`��c�=.��B�e���h���v����m)P�|[5��
���]=d����
�.-���1�w��599��Bp��l�v�^����ne����l������1���Y�^>o��sy�Z_K���B�]���������JhO!�B!����qV�Bl1sy����'���g;�	���������}��-����6w^kY ���g�����b���/�'�N5���t���2~�X�#����^A����o�����St��Z��'����%��K�c������dC�>|-q^��p�' 2�������B�L�0\��Wp���R�/���Whs+_���O�Lj)�*�_j����A��S�|!���'��<my+��]l�k+_���;���)OS(��>�v@+�a�<y�K�.�8�M�����'����F#������r�_#��[+?���b�_>�ox���C#�����o��!�h5��r�������
���I��t)�W�.�>!�B���!\�5�K�����q�f-�i������j�m(���\o�v��������K�����Zo�������W��v����5��j^����Sc?j�~��B�.mG[1�z���O��dE`Wk~���,{�,h�@���6��[pW�����O��+����R��_x�#����T����B!�B!DkI�@!6�����h�{���y�����8���������a
������3�L?�>��C��}����INM4�~"p�D� �B�]�o0�~
�g��������Ex�����3��#��|]~>q����F�r��r�� S�>K��W�1��
<�Q��7v"��Q=!����+�� g�&r��|���'��y��$s��o��V�@u+����R����W����������c��a�F+_o)��W
�u}�����H(������+-i�[�B�3��R�����������l�[���[���V?�����=i$��|������Bl5������>k�\n�d�BG.�B!�h��!��o*!��pd)����Km���p+��
6�V�M+��U�op�����o��6]3��-��r���p�:��}lk�p�[u�vq^|�k�_m09�E	�	!�B!�����B�md!m���yr�R��=,���y8>�*�_V.��
�N��O)�5��&-'(M����!95�����������9_�z>���0�z�]�op�a�6������Sx����������u�~�$_�E����]���2�����y�<��<�0�}�s���R
�&z���Xy����!��}�67gY�x
���|�{�`E+_����N�o��+��v��/�4�>�^97�X�c���
�Z�"[��+
��#�0::J<^?�����>8 
{�@e�_0lh��pg����]�������q7C��5[��O�V?!�(Z+��y���)6`tB!�B!�XN����=<o������H���CB!�B!v	�	!�&������9l���w�����A<(�
&���[�D��)��k�s�}�H%����.�4��h�b�f,�}���$�N���8|�����5<�����B�����4E�w��1��7���v-?��?M���
���/@f�}w���BTS����u/o�+�&�+[���f�^*���W��:Z���-�"�l������'���N���&n�����
n�+�����|�ap��Q�����$f������2�k���G�^XlZJ�rp������R)�_���ih����@U�o'p]��V����Z!����B�4J)�����{�c��F�������K��A������^���y�+��p���|���U�km��<j��b^�u�U�-�Yz\�_:���^��B���y���C�c�]zNj�a��l��n�}jlg�c[c����:�_o�~���t���y�X��������Y!�B!�[["y����B!�B!D�l��_�b���./_��v<\��
{����dC��lk;�G�|�y��}����2~�<�d����N<�0���D�wI�D_�����~^�p����O�����~j�7@�7�����\����R�������2d�p����wv�bK*���A������_)���@+�����OWT����[�F�Z�v�������\��r�/nM1kM���V��b��,��m�V��������F�
�@��� dG	�|�R��l�F���d>0M��p%w����������O�4L��4��4�0�d2���?�8�X���R��Z-~��-���}y��m�����z������|��i����B�W,v����������|��'D;U��
��\~et�������Pd����_9�mj����8o)h[�^6����K�m�<y�@0P^o�v�����Z�V�M���C����l����z\���6m2�[��]5d�|?�����6�5��4��A�^��=/P����|�7��B!�b�*p�4>_d��"�B!�B��B�
��h�����������%I���)�<����no>�d��G�u�4�wG�x���X��'�������0���7J�������+��|��x����t3��g���K8�\��7�Q���9y5s
^�8����`���t
�D�
=@���|���Wn�K��{>�^:�����/,M7�r���c'Z�4��c��S��o�����|�i��3g�y����~-@�9Xj�+�z�������)�l��T�sF�	�����<�*������F�
c��|���gth�b+Zo���8
��;N�C����88�C>�ox���C#�����������}��;����wl_B�[���*����l'�D�Ba�"&��/V]�B�vXow�@�j����\Z�]9���U=^m~e������/��P�2LZ+��r?��V����1��������a���]��^�}�������mC-���K�k�����)�L%���D�h�Z��\�5P~^�5����+-�B!D�����CB!�B!v	�	!����s/�k}`@���^<����=�J�(�i��?D��C�f��x���7Jod�-��a����{?C����|��37�G�6���3p�C���=�-�1�����2���
�����A�������W�=��q����h�v�����0` Z����V�� ���A�NCd���lg6]5Y��R�/X�E�`'[���;��<���7G��"nO3k�|i'�����\�V�.���3��>s�pZ���_��]�n��1�bP�'�'~����D����������>�y^S!������W+�W/��8]���B�<��q���d~�������)"��m��B�,	�
�$�H��/������Vx��`m�-��pg�`h3-������[rW��|~uxw����p+r����9Y%PZ{����<�����]�]j/Ke�t���{�����9�T-7�Rg��p���������V�y^�]c��C��[r����c�=��/��M37zB!�B!��!�=!��@�����
�=��Kt^��XZB{����{���O>���L\�H��&W�3}���3�f�0�z�X~5����C�ax����G���H67=l0��3�Go�yc��r�B/S�>G���0"Ix�W������V�4J�P� ��T�l�r+_��1��K�+N�h/m��-�����O[��DE�(_����V�>z���V���-�J�|qk�#�|�v����|���|}�4c]��9Y�l�W��C���g����$=��
B��R
�00���N<��u��~;��o�x��iZC-~��t]�V?!������o�?������!�B��IW��a�-������f���nE�s�m���T�L:��so.>�9s�P(�b������5����K����i�y+������!���Y�^��T=��]}����b?^������+>����z�K2y����r>_�����B!�B��NB{B�A26��M6��>�W�i�
{��6�L�XH����?f������L������d�i��b6�a�>#����\@�}��3�����x��!�������O�������h���l��W����7	���[�	G���G����>t�#�i����+[������\���\�z�!�*������|�� #�}��j���!�����e,w�<���gC|��0_X�����4��d�T[��qR�4����Cm�����*��5�u��C~��w�u�,��^G)U7��Z�OZ���Y��_dh��LN~�m����/�m�B!�B!������	']~�����j;��7����;��X��\�M!�B!�� Io!��7��6<l{�l�����;���}��W��}�'N3t�!���f��y��5�~����}?���2��&��W0�S���_�W��O��?����&��"���������5<�������{�������7��8�=�5�������M����m�4�� �n��[��77��K��ms+_���X���|��V�R���p+_�Dy��V�Yk�Y{�k_(���/S���[
�o�U�|�3�p#}�m�������I���u?Bl��a�&�i6���y8��p�o������N<���ml�nj=]�
�UN�4MN�b;~���{��5��m��!��-��B!�B!�v���lh/�H��%�B!�B	�	!���K�;s�p.�2�n��]�:��{�����8c��3}�^�'�[�.�t�{������K������o}�!x��0p��G�9�����g��/�&��v=����)��t��{
������\�|j&�C�.$���]������0|"��90�c)�����e�|��V�D�#�6�v\�����V��Qn���ATl���-6��ZS�:��7���x~y+_��S�������W$�'�**���@�����T���m�i��l���8�|��u�����[�I�O���0z8{�s���G)Z�]����g?�a��l�B!�B!�������}��;����wl_B!�B!����Bl����Z8����1`&a�y�� ���>���}��&�\d��E�\v�W3��<�D�iz�WI�DW�����s�	������L��b�1�F��G���x��r��)d���~m�&���p��!�_\`�*�~�G������w����@�8������Hi
	@$��ki�g;� _����is+_����0��O)5V����o����/��*�|S��i��
mo��e��m�>���c������>��	4M������^����~��=����7�i�k4��8]��6�;[$r���m���XK���g�~�Hdg^�F!�B!����q���d~�������)���B!�B�a�B�
Pp<2����-��\
���Kh�]�`�}�=��Gc��u�.�'3�x�c.x���	B�8#��H��v�������g���c�;��e_����9��o_%w��s��d��g�;�>����S?Pl��<�by�����
�y(�@U�u~��[��}�p��M�z���z�h�K�;���2VU+���Cv��zxY��eA���,�@��(��?c�z�}/#���tI��!�b+�4)'�������U����N)�a���:����nS!�B���Z���iZS!?�����r�!������k����/�{;CC��� 
{B!�B!�M����������}o�>�B!�BQMB{B�\_g�7���xt�i��|>���b��I��1v�s��4�~������v�w0��&��oa��&��7��8<�)x���g��(6������X��[��~��rv*��+���5��8����G�L��Jtc%bx���O�,�X36Ohx#�*��8s����Ad�-�'D#�R���~����t�v�R�6��@_2N���97g���V��-D��|Z4�2��'��4��^��^�m�+6�������dor t������]�r!������zS�~�A�FB~��w�u�,���Z���_�MZ��Nd=�~������*���4�nw�S���q��_l��B!�B!�����0��_l�>��>"��B!�B!6����b(<�v|���M3�`��d��$���vRJ��{/������e��[L�}
�i,,b��v}�{�H�g$���k�_��������~�6��S���C��
���7�N���L����'44@vf���a������
&��~���$G�`v�=���i�'��_�'>.�=��(CG���z���e�b_b)��e�94���9�D�z�����/�
o�V�b�o1���V>WG�4\�bk4q�qk��2�U�e`j��������^=����e|����Blr��a�&����<��q��~��]����e�xs������^3�W/�g����X�-���H���R����"��[$�)���|]�����ah��D"�7p�B!�B!�[��c����+����o�oq��?h�v�B!�B�6	�	!�������,�0>�g|.@���2�!��I����v	u�r������g��z��+�3������T�	�"O��{���Kt'�F���_��������Cm>��yz�������sj/���^x+�6N6Lvr���X������O����d������3����@J)T���	C�|/�/��e�Z�
mm������Z�T��OEh��@��h�XX���t�y��1k����[�v�Y{��V��\���]�g������K���f$�	.p+6�| ���m��vl�N��u5�r�o)�W��/��XFS�<%�f��*�������H����8���8�������<���|,A?�YE"��a�b88��Zh������+�B!�B�B��������7>Zu����uq���0���mS!�B!�����Blo���@U�<k����qg��:��C|�1�.'�������~�Qfn�`��9������e>p��=�H�e2o��_�7���(<�)�;��#�x��=~�,3�v	g�~cJj���+;���\���A�N��oW���|:�;��*O�<rv)�W���n<��.�W�O2�;V1�,����v>��:�������aW`Oy�b+��5�dn�����]wr�����o���&#�~F2�<?�dp��7�i����pq��Yrnv]������[�*��K����z[�j��
�y�F��9��a�6�m7�^e�_#!?������VDgC����B!�B!������~�s�>���=�9����+_�I!�B!��'�=!��s��Z�\�D�@"S���JAo�(��u���
4MN�oM�<z��#�HL�1v�<�wn5�~��������oc8�
��o����������>�o��7�1b�g�����Fm���0���>�-���0|�O�u�Bt�R
�&z���Xy���x�\9������p�*V7��xe+��^4�
�}���NT���'x�fh�_0xj�$���ze{������]!�k.��i�ga;���oE��f����?i�b�PJa��x3��y�V�F~����?s6����5�[����������<�C)%�'!�B!�B�6�D�����������������p��?��=!�B!�b�IhO!6�O�������n7���"
�X�yO���6W��������`��@�I4('���R��]�����lb��Ko1y�
n����=����������[�$_"r�p�p����g���a~������~��?|���Sm��W0�~�I�����_KhOl{J�P]!��e�|�n"�����Jx�<^*�;��4����|�@_�}�|���yw���'�w� T<��%F���{_c>�z��nJ..Y7C���k}S��@�����[�����4��GW�x
!�[������ox��V�FB~�����gY�e5�^#���4MB�;U&�aff�T*E:��
���N8&����O(���m!�B!�Blw�����~����p���2?�J��vw?��}����6�P!�B!�����Bl;��0v��������G��k���11g11W<14`ht��&����r�;R0���g�����f��%�/_�J7������cL�#���H�%zG������?
}/����l����C��u9$�o���|�����3�Cj"�m����R
z�����|�� _7��V>���M�l�z�a����@�x���R�~s���;@1����O�w����P!�w�~�/�e����YX�Ej/+
}��O_-�W��k���?!6He�_0���0�m`�����������������|���mmsss����L�o�u�D"A"�`ll�h4���==r�v!�B!�B�V�����I��19�E��H$/R(,]����"=M,�CC&9��#B!�B!�r�B�
�l
�nu4�W�7��;����S0t��!4��\9���L��3���hPg��d V�>9�}�|~?{y���g���d��yR��
��"8D��3�z���7������G����c?f��G�YJ)bG���#u�H[����Mvx���y8"�=!`��/]A�����U�M��[�R�b�ky�<^zY+�OCE�h�� ��PM�����~�����>����"�k�mw��_"��9{�G��&����y7O��a�y�n��[y�b����g�t|[������\VS��?}e���q��?�&r�IJ�rp���6�[O�m�r]��V����Z!�����X�m3::J<���P��$��]����`��b1B!�B!�)9^�/\��u-4�D���5!�B!�b�3�b�>��W	��]����+d����u
�g�{s�8��Q����uo?�uHf���������`���'b�k���fi�����:Jbr��������p�%g�q��#���6�S��+�
�_����O}�����|����0��]%G<v�#�b�RJ��@0` Z����[����9�Pp���8s�[���_4��P���|G�'9��-��<I�h�PC�OM��k���h�$�V�Al�u�s�B)�W�-��C~����\�n���<��'�$�^WG�����l���F+h(W.� D�h��i��f�a��V�F~������y�mc����u]_��o�4M����H��\�z����r�x�D"���'	�B-�B!�B!�XT�`Vd��!�B!�B�IhO!6�b��G�c8�������L�UMs6������(]'��0��1���vA3�H�����\����4��Q��R�/��f����
}�d���o1y�
��X����{�������H��D���K��Qx����@{��<������������{��� �fF������Ki*��R+��/�B|��V�d'Z�,���;Q��iA������gp:w�C�����Pb��>�^�������}�04Yx�y�gC|N�F���?���og4P���!���8��^�X�����&�V��j���Zu%��N�mr�@�7-�	�-�s��G�y8���8�����Y�<4������K��4�/_n����m.]��C=$�=!�B!�B�[����y(��u]��%�B!�Blbr�Bl��3�����^�k_Zs�qH��w��4���A�]G��>N`��?���;.L.XL.Cf�O1�e2��g��$�����X��8������SL]������'l�Q:3�G�	=B4���K���Q��'x�{��O��3�=�vp�d��vt���!���r���]
�-�7�=�$�'D����#��teP�����Z����ep�2�c[���h��KN���~�QJ�W~��������n�*��<��Z���6������]�H�cu]�����7��a?S`*S���Mt]G�u���[�=�k(��|�����f��V�ZA>�u	�Bx������it]/��4m�5������W[u�+W���#�`M^9@!�B!�BT�d2����J�H��U���u�p8L$���_.�$�B!�Bl2�B�
2|�w�������3O�m?�����~���<�!u�����7P�����c�'0r=���Z�{�<��������X��o����m��![�g���>��S3{�c���ox��?�������|��K_�w������O���N��u���e��y�����hF�p_9���k�dn!��)T4�@u+�U�h�[
�����/c�e,:37\�d-�������|��!"k/���yXn�"�W;�W,�wr8��F��8^��Sh���D�J����e�~Z`Y��8MWrA!ZI)�aM���gk��-��SZ��w�h4Z�����y��5��W9o�_�|tt���c�l�ftt��G��e�B!�B!�����ccc$��/��8�D�D"����h���zzz:8R!�B!�B�#�=!�� '��W�������`<�k�?M���?���l�������[,������}#��9F`�1�@�'��s�rYnMe��JM|&}Q]��'9n4�i�8L���$���t���w�<�����F{���]�g0�:#�/x�{`�Yx�g��G@��'�{J�J�:���l��>�/�G��������Y|��U>�
���m5��"�W����l�
��)������V>��K[x�lE+_r�9	�S��y���F���R��~=@��������srX���xx���^��|��_���r�O�^���?!ZB)Un�k���
�*����bY�e5�^���['Z�������m�G<���_NB!�B!�h��������d2��k�������M]L!�B!��'�=!�� ����C��z����
���;h�p���f�$?�o��i��������w�V6��;�<����N�&��_�R�����]�wGE��N
������2h
�bf���;�����r���N����/0y�������>�x�Y�����D���s��y8�7�����+��
��)��>�Ur�a��sh����p_��f�W/4t���.�V��l�����W?�=)�P?D�����{�S����M��R9p����*��y���OC�:�4�5T���}t%?#Yj������\l�Z�����wsX�R���?
^���"���^w������2X���\FZ��x0��a�&��������8N�����6v���������t]o(�W9M���~k�P�ellLB{B!�B!�
J��\�z���'-��I$�<y�P(���	!�B!��Yr��Bl�����/W/�L�'�����TK���������<�#?��G�����0=z�{W.r��E�_�H.��	�+x�������8���}#v#���=����o�q=�^��^��.>�@�,7�������#x�Y��}����2v�<�D�-9J#:M<t��u���K����A��?��?O�mn�.,�8�6qmV��R.��_5��r(��z���+��S��W��b`F��c�CN�;�2tTo�w)�y^�����9�ls�9��q�Y#��\9��-��KA������+�)��A?g5��[���y�W���	�-k�[\��6�kpT��5�����~�������Q�w!ZE)U�5c������Nj�s�q��o���<���m�d2��#X�L&�d2rr�B!�B!���4�/_�qZs�@���t�=���oF!�B!�� �B�
t��'9��\}��8��Y����~��������o�������8��z���|M�:t��CGx�����2s�6w/_������r�l2���`����c$��
F�0�=�	�9F`�q|���_v�cl6��l����_c��_n��ZK������S3|�4swo3v���^?e��z�cv}�R�`�����~	�Ix�����}�o�������������v�D��a>mE�o��������-5Qw�(���A�3�y&�[9��-k���%_ob�QJ��~������������|n��g�Y��.�����*~���i(�^;H�
�QJ)|����n��/�����*�������B��r����,��9\��k�M
�M��I����v��R���WO[\�����'D�����L�oq��m����y��Z�:ajj���w�����j�j=B!�B!��.l�����-�-r�+W���#�`FK�-�B!�B��IhO!6��>�	�]�@jn/�&�����+��A�����}�:��}	�����HO/���'V]Oi�2�� �}�G�\������|��W.r��2��=��1�M`�M���U|���'���=������f&�r{*���,]!]�&����o+�ZD)E����;@:>����L�s��F5�������n�}��`���!��g����>C��|�S~��r�7��9>
�Lx��4#_�������Lk��>4�6���sP��Ki`F*Z��`�����`�$�'�e���0Z��V��]���qn�l�7�b���������W�������+�[����|Mi��>k)���<D,[s]��(xvE�_~e��b�������[�rn���]���2��>��+������>i��!J)�h�#����~�����,���(��4
M��a[ebb����Y�fC~�t�F�Pl�����������r���y�p�B!�Bl���m��m����r����l_!�B!��IhO!6X0����/�{����\��b_��}����#O��s}d?Zh)H�f�8c�)��z�����������"�N���4����������n<�cv�^��o1`�
��)��S$/~
_����b�/��8�X�'-d
,d
���)��v���tG|h;���p_?G��~�?��W.2q�"�\��u]�d"�����]c��Kt�u�������gY5
�&J)�=1�7�;��������;����r��<z W����/��[�*���D����B|���e�}����b5J)T���������vp<p
�m�TU�o)����O�RC`�P`E{�	*�0������6����5~k��-����"������lz]
mY�_�G}ep�2����K)����������\"��������}�{	��6�����V��b�s-�����������-]����h��T�p��K8v����c�����c�B!�Z������m�G<���������G!�B!��$�'�����<��������B�<��#�?�xiA���x�|��e|a��s��}xlJ)�v��o�^�|�w�y�����t���H2^���y����3�.���%���=�	�=��k���\f63	H��1���	�;�$	3f��O����L�s�������5�����d.x��5���/3����y���.�p+��'�����H7��N��I�K-��A����p�A�|p���^(�t�f�O��Q�'�z�����h�5Z��}�O���|:�[��|�r=�<�x5����������C�W6.���0�)��$�����������~Ka���_�<��a{��r�V���s3�����7�Y�+���:!���_�������X�R
�41Ms��K<��q��B~���[����:�������,i�;�4�vf��%��X]>�NW�Yg2�������G��B�������P��#�=!�B!���$�'�������1�#?�{�_�x���Zy�U�z��G���w�_�wG�qb�����(���gx�G��A<�#1=�������HLO�d_Nr���o���M�pw1����3z��z���x����+>�Sc�"�0���{+�}>���b��I���e��y���ix��9����v����&���q��x�S��w,`:;@�+w;�/�������������p����}N�*K69��Q�D(d"�.��yt3��h�[��k�=����m5�Y���:�}��z�'W��Z,�O��p�:Z4���PpKp���DC\\l���?�S�T��?�s8��S���C��@a��n\�.�����*[�"�h�s<���n�s�~�����|1`{�c�:[����'-B������UO��n����B!�>i��Eooo������
�
�c��ci��7��t�|�6�X����dH&����z$�I2��P�#�B!�B!����b���-~�s����A��?���Q[x������s?�����vh?���O��W����CO�}��]��t
s�� 13U
�]����O4~�q����}���o��bv#��8���1�F�z�(g����qg&@4�3��g���?f`�;�d�={���g��Y�.�g��5\��F)[�r����}/�s���?"�W�������A����7���bX�����<����>��@�7:<����U�>'a������<�Z~\���Ze!�V��*?j��}
��23��j|��[���b��
R]!�`hO���qlx�t���a2���+T���"��8�t1���N�G
.�����y���A@��W\pat��koS��[���
\��W�lu(�SA@]��A���<������>g)h�h���-H�Pl�����l�3������j����������'���������m�B!�;��c�h?	Z��B�@,V����y���133��ckv,�9���LOO��G;����o����S!�B!����,e!��`���KL&���FC�
����s,u�����4wi���g�`�?���f����L��?�x���Gm�qT��r�=���{�@rv�{W.q���^���������$H����_@F�>Fp�q{�c��F5����:$������D�r_o�@�v�	���^���E�?�W/2~�v6����f0y����tg�3�����k������OBte��U���K��.�m��������W�B�����O��
n1��X
��}��}y<�}��t����B8��J������_E�����N�(��������e���}f����)V�G�qnv��S}Ww��J)�U1XE1��
�[
�U��}�:�"��\�q�D����Q7�n�r���U�V���K�@}i��R���I�����-����\����?i�+�<��H9@�9H
})�����Z��?	���l��~�B�7�|���!�B!�k�p��	������7�#����8�B!�B!$�'����N���cu���}|����<�F��c+8I����{����C�v�����|�N>���9�])5�]�@����������x���7�a���Sl�3����B|��I������i|��/f0�e2��'���I�F0��G�d�#�1s�m�.�#=ox���1�������{��o��3?�}
���|�����=��@M����m�~%�������.�y^�)����0_U{_�����s
�B&��Rh�U��o1�Wj�3�F�E��)�R�,���{�}���4[�
�zBxs�k�j��	�E���e��f����R�oY��^(����V(P���Q���x�By��-��z�~�P�^^ve(P}�A�b�_��^�Aw5��?�*�W+����o1X�
��v��,����)1U�v��m�}��+v(��G8&�hK��H$��C�j��Y9m��<W{����]�A���c����K+���?g��M!�B!���R���m�s�B!�B��B�PB�
�+_����Ja+�����~�zsCC{���{8���9����$�w�"�J!��;�-���K�y��w����F�!�������l�*�������ohv����B������:�GO0p�8���t��&>GYc�wz������-v�{����g`��-k�G������Z�]-f����-���PJ�>��c�~���z�i{��/Y����l�������;�U1�)5����}�b�_���/��7�f��Jo��U�V�-��U��*B~FH�}[������;���������M���� `e#`�Y��
t���:��I�S.Mz�g�V��b�oq��P�^g���5NX(���15����x�R�o1�W�����&�,/�U���`
:z)��2�W���2�'-b��D"
��b1B��[���j:(�L���j���,��]+?>v��@�����M���������4!�B!Dk9�������=�A!�B!��L$�'���D�WFg;��Wn�rm"���hG���P��cO?���� �Jr��%�^������}�X}���|������ze�!��8�=��@���h��.wgr��)�4	��_�I���m�@�R���=t��!�0�����z�
n���WAs��}�����������9��~{C��k��?u������m]M}��i����mv��z�D����~��g�,��y���`Z��8<|=N"_j����-P���8�N6�S>�Fk���>�Bi�|� �(����N�UZ�*���-�����pvu�����z@��.��X�����%�y+��*�����\<�Y\\���+���g���+�|���z����������u�#���ah�����<��[l�[�����w�8����C�I�q��Z�^�o��_�+�w��X������utBl7�?�%�����l������XL�&���C �A������cy���� n��.�B��KB{B!�B!D��YBB�A�p�s'�|��}�����z#Q�<�G�|�\:����Km|������'�{V���E��P������'��x1��k�,�T�!��rs�x�QO�(7��F
tm{������s�a��O1y�2�����4v���|L�g*�8]�w��@O��@=�)x�@�`�1f��0��.��qO����i���ok�S����'+���|�����<���98�v>g��I��Vy���Z��h?�`P(����=������z _�S>�����B~�x[����������p_��F���!������qj����RJ��� `�����_e������DW:��h�G���C���J<xPU�������-�c�>L=F�X�u���[h*��|YQd����X��|+}fE��� ���
h*S�!���B!��(��z^���F���'�b]$+D�-���_��W��_x���h�e��x3R7�XZ=�N>O�i,�i��Bl���.@,�B!�BlV�B�
r��|s+x`��h����w���n�p���?���� ��0v�2w�!��������<�;������t��a�{��s��!�C|s)������it
�����.���o��hb��9�#�!~��.�'53�����,�g����_�3�g?��8��7��9��0C�~��/�C�����<;@��o���vPJ��>��c�~��s=���j��IX-mDl�kp��j�iN�������`��-@v�x[u����}��f�,��L����u���Sf��OD��g�v��*��|�����](?~��	B���88����r`���������C�Bk5�2�W��O�RC��5�����G����@i�U.6�z.�k-�U��*��;�y.-���������?�*�j7��l�����J��-�FFF�v�ZG�#�B!6���)��_�i����";1���c��A\�����(O�0�M����]�]�%�'�B!�Bt��
*���<.�O��\��8i��r4�����iVyL�.����aF_���/�y����C!>�}+�e��U�]������q�y� �����^%w�*J��>Tj�;��a4���v�,�,.�O1[��	������3p������g��y��oA�o���~n�|�;N��o~�]_�w���(<�	��kLz���GN�=;H��w�n��5��<#��^�'z��oJS�1?z�{�/�����>'���x��q�a������g����}��o�<��!/�V������n��)�h��CX��jM�����������A�RHk�_A�y�^E�oe����VP�
t$�i�����hyK��+���rP�5�>����/ztec�Y�"���������Z�_�)N�<i�����4a�2*Z�j4�����ea?������m������>��5~�|}}}����m�B!�B��Is�XK"��������?�8�����m��z��������_�k�"��|?B!�B!:HB{B�R���}M�l��r>�:��\AO�������L������@�[F����6��srW�����f�x�Q<�(v>�����{�"��\`��k8���X
�����������M�?|���w���#h��a��q6���<�$���-|�1��u??J)b�#��G�%�]z����~�z�����E�������Dz��9�=��1O�<��}�<����5
V��[j�S*�������`<����%��____��2���eK!��|�`����Z�Th?�`R(����)�����}������x���Cf�x[�s��>3��)�E������y�l�����x�*,�=�yJ)��!�V�M_V�������C��0���-���N�)��^�r�������r�_�w-�.b�(���AA+`)��f���A���?�z���I
�M���8���]j�T��*C�����e��o�9p��D�//gh�v�B!�B!-�m�0ZWWWGC{���B!�B!Dk���B�l��i���58e7��y���7�s�(��A�\���G����4���0G�"�rl(���(�C�}��$J�`��3�;}��e1~��J!����(X-h�p�c7����W����O`�1�{N9���DZ��;����Ne���C|}1]�zo.�1=�.�=�$���0~�-��dC�zJg&|���bwF��c�<�z��a���r�����k��CgH��!=8��EP��S��"\#�����������?p���q����R���20�����9njYS����>/�tp���i8� N>�j�P+�����U6���Rs�R�OiM�l���\}9#�zk�?V\F�?[jJ����f!���PpO�yC
���$>�
�=o|�D��8`!:�*h�f��A�����A���������
���y`�&h�nQE���D�����^����p5p4[s�4{1��,r*OVe�yy,/G�������a��n�k�O�[�����0��%O����`��!n]E�Z�obG�wd�!
�B!�B!�����gll���B!�B!D�HhO!6���<�p�Q|�O�{�O�>�t� �gF_y*l��x{*��S)`�<]���B,�����|�������&{O=��S�)�L�x���/p��E�_�L!����M�7Yx�K�T9��}���c������O�Ox{<���/j������-w���������<���7�x�����+�$�H����e�����|��y8�"�V�ef���Wfo\�~�=$�?�l�|�xA��;�B��b�%����?���=�{���B�M��<�+�.?z���b�ZN���2����I�B~��c��7��Q�� ��U15�B����}5Z�4�j���No��UR�V��@_E�o�����b-��qx�?@���fm��i+�����Et���T�v)�
	����n���	��������%�'D
�A@�u��n����F@�v���P`�:�������Q|�n�A@
��nK��-R|a���?���t����y8�K������oy�'�EN���#�2d���2�JZ�`��/���?

S�W��-�����@i��/�d���q{]���p�k��[�s��"7���O�����B!�B!�N
��F�$��]��AD�QB���WB!�B!D�HhO!6@���+h��-�'
8�N�	>``oQ�S�H����	����7����N������4�zC)��a���aB���1��v�8�����)��y�{W.r���]����>��<���(��Q^�����K`�q�{�C|����p=�NXL',.�->��r_8�o���4��������]<���
7��}����w�C_��
�s��m8�7@_�Z����[?�M�S��D�cM����9���0��o��CMoGlN�������	����f
�v>�N��M���
� �6qmR��)����}�0_ W�X
�)��D��+Y�%���o
����}f���a�N��p��������=Dvr�4�%3��@�t�c�<�e%�N����^����>v�,��9x�S� �������� �W��n��95���B�K�%�!�A�|�<i�^�-HV�W���"��j���V
�����l,e���������S�����S�����`����%����4C+C~���R���{�b)4GC9:7E�
���-/��%'������G(h��H���{/�3�������OB!�B!��FFF�v�ZG�#�B!�B����i!����R����q.|{����R~~-�#��E��������R�O)��,��
F82��P�#�"����E��9v��c'x�{~�q���wK!��W/���[�'k���o�f��b���wG�o����<c��f���1�e��|sk4HD�8���s��g�|���ql��u-�X�]�y.}_�KF��Y�O� ��3I����r���|]4���Y�����'���.��D)�6������'i��s^����M��p�A���m(J/T���l�+���&&����m����-���
�]�"�X�(3�����.Z���\d'v���c��W1H��/��i����4����h�6�A����S��W
t�5.:[�Qv�(��B1gW����`#<��=\�R��b�_������K�����-��!��i�=h{6�c�v��b�����u�6�/��U�*>������6i����;�H_�'�w� T��+0�I�7D�m���A��P�i�b�k�R�H_�H�$�C��uB!�B!�[^OO�������o������m�B!�B!��mk�*�b9����n�y� �������x��O������ypw6���,uu�j�HW�#CQ�
F8:��`1��l�I����:�G�1|�O~��p]������|���/p��Er�TK�e�����G��_`��[��'��8�������r{:���b�S,�+��b&�1��9O]��D9��s�}�	������s��k�H�Hi�C��s���7����w�)�����]?LA�d�����]?����8�O|B�-���������������wp�Rs������9IkK(<�G!��Y�)T3�Ua����R�O3���u����m�����x�[��V��U�<���2���x����Tr��^{��'��1q��B���l[��U[����.^�Y���N{���N�!�~
P�Bs�g�����b��[j�+`k�R�_E��]�
��������nG[�2�����7�Y��k~L}e�o�2Z��������+@1����O�w���t|t�|d5�y�@����]��?-u��F���m��K3C��q�)����)�/�"�=!�B!�B�5����9�p����l-���;G�wB!�B!:MB{B�A>rv�/��-N���V|��q�v�e�k�����B���}}�j�P���R���P�cC����Pk��i:C3t�0�����.3wos��E�]�����&-��=;�=;F���`�[�JA>_d���%2�7�3(�����6���y��n��:��'N3{�6c�$11���)�^���b�Z��|?�V��j=
z��������o?���n[��_Ga��z������>��s+�}	7�� v;����c�b�R����r��2��k����!;[��F����Wz�W!F��c��{�e��E^�d��'z�k��-�=!D[)��hC��pY(p1�W��o���;����������W��o�GU+X�����A%����Q����i����Xf����5�D�����>Q�U
��\q���x
�Wl�T�|���&�v�	�p�%����5M�9�� �B!�B�������e=!�>��k���
��f�Er�G2'��JB!�B!D�IhO!6����'��$��� ���[3i��L��T�SI��Lqk&M���I���<��<_�1S5�?��h)�wt���wl(B_��W�k�i�?����<����<������\���d�[�/{n{n������,��{�����]�� ���'m��K���1�����.�hPo[k�z)M�o�A��$53���s������K����L� ,_7�]�_�s8����G�\JS�=b�H����[l�[����*�}y<k�<
'��W]L���p_~)����g�QZ�?��<d���������w��v7��p�"7`��)�������p[�#�����>��_��A@�:�W
\��k�+~\�(:��|�o]��z
����W���VC��P�f
��d��u�����\��K��Y��7�S�'	���F���f�*xj�$_��7�WyJB{B!�B!�5�[x�������84w�%�{��/������/�"�=!�B!���$�'�$~?Ew�3'�v�\R�YN��qb����v\Fg��=�*����Jqs:���V��T��T�o��WM�
��V��[��o ��Ta3��{���w?g?��x����}�^���R�/5�F�S�
S$�H^�:�X?�=��9N`�q|]�u����11g11g04��r_��[2�V��p�����'�c��&.��`��l�u�	�e���M����R>
_O_��'X��B�`_��Y�p�t(�� <���1(d"�-�fZ+�}��}94���!�l�dg�N���l���n��c'��	�	!v�bP�Okm��*�~�B}U�@�f��R(�� `��<��pZ�x�(�:��l�����V�V(����	���ga9)XV��;9��D{�9��fl���[,�s���������Vo~��*~�[���G���j/����_�m�����R�Wg�M?�����9l���M��j�]���|>��_��hf�+��n���&>M}���w�15����2�����1���P��5�\w{����^�_+��X��_+K��V�ZYz������~��z_+�M+no���\!�B4&nM3��W~�32\�������������c��h�����=f�iz��JB!�B!D�HhO!6��W';���_��o�����k�0�P^�^p\��f�>Yj�+����N���	��i�Wn������[W�(7����������#{����o�N<�c~r�{�����/�������Bb���R�_@��|�M|��u����rw&�����^��L�c&�Ok��?f������L�����W����4�
����N^��S6!�|h�`��2������>g!�[��q�����<�������UZ7�S��h����\��/���	'G;s���!�
c���[��>P���Q=��f�X~��Uo�+�-����]���q�y��A��F?�v��VP�"X9��f3�~���;zK����7�5�X
��[-����[��5��=��G_�f�ZG�'���-��jjR7!���6�\���zk\�O�D�����\�X���5���9t���dy��/�!ZJ�;�����Yo����k��VY�<���r������B��}��5���z�Yo�N_�b����I�=w�����"m�5������o��_��ke�e�V�\l���{�(�L��V6��J��u_��������E��	6�k�R�������khsy�������7]���=�t��9�F�*OIhO!����y�$�]�{ODn�wu��-��jI�lk����=^��ya�1�y�������`�2�0s�;�2����	0c�����,[R/R���]�WW��Y�F����"2#�2������_����8q���������X6��`�\81�����r���h��A�Z?(�^�����/�U���+�=w>����.S��lQ�?Y�?9�~0�U���qH{6��o�����h)c4�i�F7m�_�Yk5s��N|��;���/�&���/+}�_�>�/�$w`���z�R�������o�f=�f�:v.+#it0^���v0����$���6��Yo�IS�'u��G5u�7��n��v*���h����p�3��;��;��"��U��7������_^�xT���\��\�0�$�X�)�'I����1K��T��W|pv��K�8�onp�;��m��[�\!BA�����|����~�?�T��,I���ZGn�J�/���_u}`����S��]��4���jMnPS)�7�6�S!����`��2ue�T6��{���y����:`I�R\w��Q�f�H�����DI�������}��R��h��jM!�>���o�u�=�����b�����y(\���
���������sS��_��X���RZ���XJ}C���������m��o�X[��V���:�=w��K���BS:_�������������=+���Z�o������1��I#6���Z�43qQ�����g�����4u�7,�2��yL�#�I���a����T�������P��4�.j2]������n8Q��7�[�����^�]��mWf���|��.}nY�g&4P*H��^��V&�(�6���T�6�Z��'o::����O�������+�U*�U�����m���gWfp�K^�|[)��vl(�E����c����m������A@����w�����u
o�����Xr�%}GI?��S��m����YS~��j4��#�v?����mU�8h��
�S[W�y������[��5���f\�+~����hnP�>u��K����|G}����VV�$k$c%G���v�l�������}��D����+�^?�B{��9O���	�U����_=����;���d-�W�:�6��5I9��a(�1�nm��[����o������t�\���l%�����g5�[��`���{�����th}*�h��r5���jU��_��X��K�����W���^q�$ivrB�������4~�iM���8���2�=��s�K���A���S����v���F��<_:?U���rx#w���I�?��d~�X;�����r��L��e���E�?�?�E��/��\�Q,�����&�rI��}r��r���
�I
��������~��}Cp�3���brR1�7�lg}+?]l��W	�y�y�����sr5���N^>%����e��M�/c����p�����{��^94��Wn�Ze0&S�)��|9�d��`I��������}/��_=����jl�l�����^�|���d�`0*X]�
k�L���0bs���au.��5���������m�����Z�78v���>`o����Pi�\Uv���
�6��6�������"(
W����~��;��[p���+uT������<�����Zp/��T�E%N�r �+��VO�!��k������En7����D8��p?�h�2�h��>mY��{��������l^���T������i={aVSs��g�\��3gf������D���u���\��������)�7�v�n|�=��e�H�2S����>���O�������g��;����>!Ir���J|� _b����z����/�4~)'IH��0R��N([�����h�[��$�s�u�����H*Vn������2vB���ksr��b~N������W��\���9rc1������L�M�+�(������@�/9$%�������N�n�f�-z�P_�9�W��������k~!�����x��L��
/;^9 �6@8Ox0��j���/�o�dH�k�W{�����1�DUl��(\�J��\�1��H��Qo����������
z��@O�b�92�%��OA��X��H����� g5Y_�Tl�M�j���eF,[W�\�;��X��g�����i�y�m�w�qC����l�"�Q5�N���s��X@�$Kq����m{��O��N�����M�c��0<[�Dh��@hV���U���V�����y�=:��o(�T�/�5��|��1F�S�0�������g�.e
z�|ZG/��B}G/�5�.,�qJ�����s���1�h����V��8����c]�����47�fT7�������$��L���gt��S?��.�<��q�����=��cOJ��d�R[�*�����Sr�v��X39O�sY?��$��*U��Z;��,�U<^>����d���5�Jn�J�`���-��aV��rm%������J0&_�c��R�u��cr�q���b���d���@���I����XO��L�D���]����k��Z+�-������E�d$���������`D��M���A�]��`xq�/J5��_,�� ,�$�.��
6���4�f�U�����A������|����l:����+�����C�X�u��j(p}(��9�4���^��ja���@`����������QA��*k��.���o�8�rl�v�l���hp^�94Gx������������'�1im
���w��i����\��<��K�%�������o���~O��.`��[8��x�U�?����UnYJ�����E]x~6r{"�jh�/�R�XJ}Cq������Lj�`R/���6�)���Je��i�����gua6���(I%���i=w!Z�:F���+U��ja�]���/M��xD{�.����$I���NzF������O���c�]��X~>���������M<������Z	�m�!�6����)�r��g���1���D%���H�����+'�3��g��9��L5^����/���������r�o����E�i���l��s���%�r��_,�_	�
W*���*���ys	��?3L\N\�M-�Y��O��y�����s��`�����&�*0h;�^���.@X������.Z_�
��J�7��*�nL2��6��T 4.�A�*a��b�k�)��_��}�������YFU��������!�R�@T��(�Cc��j�/��.�[6]�������i3I�[n�o���n�W�~D����
��������X*ib�b-0�n�z�����m���� j����Q��sG#�5�B��hu�64�m8�����J\����S��O�j����j�������[����������g�����y�4����v�_hm�q�|O���4j����E<g"�,��Z��c����<���k���~;z�D�_�`������R���D,������w�=\��{������5�eI��5�E���jbdVq����`i��`�����4~��JOeYr�.�N���t�v7�T�|��@�����$����$t����s�����sE�X�UCuG����tn9O�ou�bF�.f������w�t��~����a�=���m��opH{��A���%I�LZ�����5~�)�?�}Y�~�b^�O+{�iI��%���G�m���m9���������.L���x�hC �7�Z���7����u����t���
�[HQ�%9��P��V	PE��\��u�b���XLn"!7�T,�'7�/75(�HN(���'0�3��;��;��4���_�������*����bY���Vz"
�W� ���`��Ac�^hy�}���i�/�o+�����w�U�ABs
~Hp�������P_ X�Q����no\�sTfUf	��ex���3�����xj�f�����Z������M��Z������-7�5��`��F��E�o��4�����U�=��>:��2���s���>������}V�5.�������=��������O�|��j�*(��!�G{R�z�G��_`�K�^/<���������zz�y�9,#B{�B6�^����m�Jhv2��K9y���=��k������En7����D8��p���ku��p�o6W�T�+W�{����������r�|+��4�����C�0�1����rU�
���aP{7��|����hN
j�mwj�mwJ�
�9�>rH�>U�;*�[|���
��<�����,��q%��V��}Jm�A����4���%���y��,WH�O:Z?������.Jw	�TTI|"�J���|%U�/�jU��%e�<ISr�rm^���ks�`����s�\���9rc1��q����J�/���7(�o�9�������I�r��)������Vg���ln���j�+�i��	m����j��[����������kmrE���b��R�3 ��J���n��`��]���2*�sz��l�S���.��/.��%i�Sq�������`��@[��J8�w�^�.��h�_��r�*6oS)M�N�a�p�����]�O��Ma������W�f���@MAJ�<o��5�s������MB�-�Z<W�����6�}D������B����V�>���5�#��_�������Msk5�q� ����`���c������6���s���J*_���-j�RN�������Bv%���Y�*=�Wz2��G�#��
����
�M����n�i����]s���!�g+!���_ON�E}�^���J�&�:5��W_m������0����R�o�oq��D_�v��6�|�m��b.�������5~�)�}�Y������+*w��r��W�1�6�Tj�~�m�W���W���}=!��/���#��Z����bn�wh�1HY-SaEIR�)h��-�
yy��J����'��U��<��������|%Tt[WC�)UnM9���������r��J�/���_�#��s]�qWn<.7���H)����(��R�2���_r���%z�`�2�(�mX��S�6�3�Pj���/[��
:���K%+XW��S��q�V��|WV�����k�*�?�x�}ms`���+�_py�i��W(�V�qWe0��`U�7�j�
@+��52�#g�O����;��36���;��o;_�/j[c�/�$���>"�~i9^C�m�!EX�.��f[�<��u�U����/�<O��5>������
��8�<}�r�����
��Rxi�%�,����;g����bdt��l�lnk���_��������������h
E�����<gc���7H�k����,-Oa? B{�b��j����!�^��wM-�'�/��N�8��;�#��gK���@�/;��G����-������)7T�op,�[������5t�N�'�/����jU����0����u�RF�2�#uz*��SY}���������|_��a��x*���D;ny�$�����sGt��;"���j2^I���)w�9M=*�q���S}����R[��I�B�L��4=W���sr��v(�
#	�Nj�`LN���C��h������C�w���{�����}y�b9�W(�+Vn��J�Yy���\F�\V^!W	����'�W�f]�-���Trc*i`��^�������\��\������J�9V�+�n��_�LU��
��j���R���mC���m�F~x�����J^%�W��@_C��������^ 0X
}��^�~��W����r�@Z2��[	�"�1�g�	FU/lFV/�V8���m�+�o����$�������I�����Mc���w��|(�f�_Z���Y�\��g}GU-XL�����a���r��aL��#r���ap��Xm�.]�Ak�6,w�,��:uj��p��mJ$�-��uP������8�.��m���k��v��R���~�z��^��������DhV��?�]_8��%�%����}�}1%�
j��������T�/x?3U�]E�r�.������������Z��{�����[5�)%G�P*���ze��i����L�x~&��3y}��Dh���d�*_����n��`�EO�������t�^$I*
:w�Y�:���=�3�Q����}O��G�?{T:��q���C�m����������_��[ib������������r��#	
�\c���wi|C{�^��y��Q,�T,�Tw��0km-��U��B�~.-/;�R.#/7'/��W�+���|y�U����Y�������K*Tn!E�N������*U�\?W��gr[���(�T���K��&+��RrC���
���qz� �����5�����E���1F����E��z���0a0X	�y�
������Pa08l�6X��*�X�^�K�J?2��YG�:���.J	��u��}��|z�)��e,�~@��2�X9p��aT�0j��g=���F����7��x��,�X�R3�U���gs����������7��E�������"��R�mWe�18�������'��#���0f�������V�v\�������x����j�m�����aW=&+km��[����
�1����=wy�.B�;:��I�z�o,�jt��F7EW��=_������������+��+�����YM_�Fn7FX�����^�6��]k�wkRsq��W���������i��Q�[�c�H�5�����.���Hh��J�/�[?�����DB�nz����I?.�T����i���:u�)�9rH�|.������)�����d���W�u7(���������������y��\�%�Ih�H�RI�2K_��0���cK>N�1F�DB�DB��k�Z+�Tj��W(�C����i]8sZ��d�U_J��*y�\\�:�\Z�=��3}����+���J+iF�!��U�����X��u���[�����M$���d�b}�r�+����_rHJ��h�4���aN�,�X������{%3��#_]����06lW�M5�����
�^C_���_�T���F�J��-V�ud=G�[��40^ �g;�� ��
��}m�}�2N��N�.O�\�F���` ��Pad���6���\�s�s�R2������o�Hft@�Pj���&����2�=
:J�E����>m�&�.�����m�mx1�l7�
�N���M���j��m��1m�������M������~9��4~�����:v������R�]��pM�j\XIO~Gwo;�3�>e���w?/��m���~G������������4<�'�m�n�Uv����/dK�:�v�����J_�������$�:�=k�4p�i �YG����|>�#3Y��(_Z�0�d����O������#}�Ze�=�j�7
�����X\[�����o����J%�?vT�������t��A�����X����U�������$%�oSj�
�J|[����W�|������9%�n���7?�y�n��%c)cj�����@333:��������O��O���������B��_%�W����g�r��Ey%O����]1�Z]��+����9^��I�Vn!sr���J~������9��*��T�����'�&���r���
�I�4��a��**��#C�^�K�yf�����%u�12���zffFW��V���{5�?�&��(X��0F��T(��B`�YW�sWY��vQA�F
>,�8�6c/���.q���~�!8��uy//�8+Ut+\M4t���=,���}+�7�[�^*-�vvR��/:6
m�r��N���vt���a[�a�N��6���+�6�m�����w��e>'G��=X)�.I��*���{\����{��X<�zz��q�b�t��4yIZ��`�1��8����6��~�7�-5�����La�g�^v���lQz~���H�Q��1���HB~��L���_��|A��s����1Z����E=��e=�|����dL{6V+�
��o���4O����e�~m��_w����=ON����t��S:}���s����p��
Oi�;_�$%�mSj�>�����m�����?����Ng52�a%��Ng�����\I�����(cL9��I}����F0�W
��yy���lZ^.#/�U)��W��+�=�<_�g��F>�����|%U��G�/)_��7��gjU�\����rmN�J�+����#7��)O�M&���R�r����5V�,��W�����G��i =�dcd�.�����K6��&t��
�U��r�o�
�Q�*�������{�aEy\d��f$�������>�.|h#���8s�����&���q�	��1����rEmp/���<9r2�$'�`���W����(i�RK6F�|A�tD}{nZ�1p�
E�&��eC�����E[U�l
c����c���1��Ae�V}�`����m�d5�j��1m���M%���I���}_��Y���`i\�W��jp���������������zRqo ^�w�k�/j;zT�s���:���)�mP��
Fn/=�'��U�f/�������O�+�<r�rWc�����q�l��l�h�z:](j�z�v�f�U�����������srJ�99Z��p�g���l���C�P���p��q]m��W�v���o|�|����Oh���?���=�\zV�P�Wab\3O~E�_�Y}�n�I����7u�K_�D��*d���������������t����Kt�q]9n����-}�+W��V��s��iy����\�`1�R�(�T��y�<��o��+�����;q����v��J*Tn�\�'c/��������??����u�\�(���rp�M$�&R�%������eR�������,_t���yZ�
��*���Jn�-jr�����?Hh��1F���#��b��0ac�h�6�0��q���"�X��gd}�(\EL������@��� l�H��q�T/��������x�Me]�tVe0*tb�T
���]\p0}N�����*�&&7����^�W�hV�s�����4���c@�L��c�btZMtvvF���7$��W/{��548X�$��9��2,���*����m�/��DP���mp���������x��-�����=�Ub���������(������B�c}������F=w9��\'�����m����N��2)��bW��?w�fc��l����{�2���*}��^���w%X�J�%�I�*i�\I�p����K�����r���V����sO������C�SqG��W*�m����_�/�1rWw�����u���$���8��NUC|�Vvv�'s,N�Uq�lm��t�?�X�w#J��=q@�bQS�Qo�M3��\c�:���c����pWN�U<������r��XP���s�z���\��_N^�(�TT�T��'yv�f^������T�@g;�*���jc�����?��y��W��\������cr�����L�M�+V���B�s�kFc�������8�K������S�������f4��s�i`��=���������m��`-�0�P�0��`u�`�0Pe���k#������[�&YG�+�]UO��
��-G�m����Sh�o(l]�P�FW&4
���������T��+�j���F^4('����_�5�TZ�dU�S��'�����*(W+���m\�:�&sUT����+�
` �)_�
��)3�q��x?�etu�6�Jc�41��:���g�otF���Vg��a�([���
��1����K�'���X9��LJ�T�k*p?��,����]A�u\GCkSZ���*;[l�KO���[�O�k�HJ��r�Y�TfL0�����i�*��,Q����33z�L8x��9��n@{kU��w����
h���Z�}�n}�e����S:u�i�:���>�����OLR6��3�������{�\N��8�l:-I��~V�O�����"����8F�c*�>#�����\G�m���\6&�_��@X�u�a��0��X2�X2���Q��Z������yy�Y��y�L��_!W
K�J�<�W�#��P��*��*����^��k�hN��
��A)^�Z[L�t~�1m8��'�JnQ�W1Y����_���5����{����sE����1�����0��X���`�
���!�`�A������+����I�0��Vz"
�E`�v��8s�}������2������{Rq���{^�~���w�jd��]��k����������O������s)��.���u�����f>����~��a�m��������F{Wsm�1~7���9�z�����'0/3�/-ch���[���=X�������c$�#]�&���a��K��\Jy�^u-�zZ���������h������R��������>�C�����P���������#��a![
���}s3]<��`�
xF�=)X��*���|���_&x]�J�����s���q�h����P���w���n����a��5���V����x5�w�i�'/-x�tZ���7�c�MZ�y����8{F'T�X�OyLk�E��<_�|��2_u�����A�@���
�%��h9\l}M�y��bm�[�(HX�5c�b��b��U{���/�"*���*�2����J��r ���W,�+����|���,���G��������������g���
��.x���eM�?#�
'���5���e��o��*_M�k��
]?l*��cj�2&�\���8���#���r��w���}��2n�r��qc��1����+�c�m��Q�q]���PE���5���+%�_/�k���@E�@��R�
��@`T������a��b8��8����daB/�k��Y
��Sj��_����9�-��
�=�[����d9"�ZR��@,K����\_�@���z�������+�)�\��D������r�q��~��7~�|�����n�-����p�y�_�?���z���1��j�j;��4�oH���������N�}���i�Q
�5.wT\L?�[T?������m��v<F����$g���.���n�A���z��\h�6�/'_�%�nY#����o��e����uv��X_Ac}��|�JE����\�+�������l�|��1�@_��_����?�1}1�m����������d��J_�Z�����z.�M�h�o����^��l(�W��7����x�=�g�����th��m���
C��qP{6�P{�~�^��_��?���>�S����DwoV��E}���8{F[v������;39�3'�i����O~E����q�� �����n���o]\rcrb���6�>c2f����`OJ����v��I�-��Q�?��������@u���a-tX	^�1r�q������Z+�y*U���B��������l9���+��*�������J��"����M�������Je�^D���5=zQ�����������^M�������J�[�C
������b�kd8�!��`X�ra��]�o�������U�����FUC�����b8�X0�����V���s�S9�W������|�o':��sgd�+_���Y�d��n\TW���#�F���>|b�Xk���jx0�k�6X��.l
6W*��k��
=K�=gKV��s�_(�����k:��qq���S9'[U�7����������F��!�va�p����1���A�y�5����&���A�i5��q��������A����$�"�o<N���tl1�����+w�7�1{�O�m7�-G?�m���m�|A7��k����)]Ju1f�m���������8f��_�t�����u �E[����J���e�#K>����J����=X	n��#%\�^M�|��r���[�D�P_��x�"w�fc��l�����V��|d���K9�'s*[$�V@LF���h�)��J�V����R��z����������w�t��~���V{��^�^�N�$�S��q�?���=���;cj���&.�opP�6m���
+�W�(J��(3=��sg�M���(�BV�S�;?����=�	��~�r��KM��@(��W���������V�/-�e�F��h+F�LsX0&l]���B/j0���bJ�bR_���S��U�~�J�X	���s�r�r��|V�|V^!/��+y�<��|�����Bv`V��Y��I
��Q"��D�O�_���sJ*$�*����R1������W���0N��_I=z��Wn���0�����_�]��X,_�/��������X)J�1�h���b��bc������<�V_l
��n���T[����:��b��bF&�H���M���a����Q����@`s���F��z~��'K��L��w���Pl�Ul����{���R�Si�S�BA��x,'S�JA�	���l���6�46r�Z���<"Z-V��g���vdm�/���Z�It!��Q��
��Q�*�jm�j\����.�_��`Y,2(X���ep�]��n�i���~���%���<�c���B����;����zl�m��������F{Wsm�1�B��V�{y��?N�E�+��4�U$}N1�;*��%*�?!�wK���|,PFhVB<.���Z}
=j
��m6�
QK�X�P_0�b=}��q����4�6%�i�n�Uv���,���s��y��h�
{jn��B}~�Z��c����o���t����t��3F�6z����2�(i��i�������s���:u�����������;�~�b|O��d��#���h��7��N��`T���%�\�j��[
����mjA@���	�B����t\W���x�oQ���W��*�B����\Z�l�\0��T�+�+��<y���*
��yM%+�-+��X#k����=������``�'��8����������J@Q~�2�v�L�����F��-�C���]C���Ze�Z��Z]�	T^���z�E'V�yV��Y�^�����c�M`������+��W���r��^90��P��=Xm0�za�v�o�F�V�b��ys��N�?x��*����]��>@wAP�X HY
.$XmW]|]T�����B���;
�V�mG����]��c�a�4�1����1��3b��cZ?��N,B��j2,�
���b�A��m-�k?�;
<6��A?����~"���~m���e����d����:g���VldDK�43�����w�=��X.��`%�b>��2U��&�J�[&��~����_"��w��1�N�8��;�#���p��!�77S�z��4`�<���$5?��jU������h`�tj2�S�Y}E�����G?��C{�|�[�a�U�z%�+�������5TtcR�y]t0p���
�j!�X��0��p�5U	��L��`d�A&tZT(t�J��%�8����x2��~���+���`�P(���iy�L��_!_��W	�y��g��x�H�����
�����n�Z��P=��Z]�G�`����-Wf�TW������^�.����5-���.�+-V�&Pu��W_T-�/6W[�����~S�#��4�0�+_���Y/����3�i}��'k�����f����
�Q�#*���������������0� h�he��� h7a�j�j�����v��<A�� ����6������|`���<���iX��4pZ������_�r��<Mp}x��N�c�zD�py�qE�N�������}����-����~��}�z����.����C������c�i||\�BA���������.�R��(W����Jl��l�M�W���I9�#��$S(H����Wn9)W����+�]k|_�f��n���lO&��9����A�m��^*zJO����U�f.����������F����%Y���|�J}3Ny�xc�[�*EXy���
��Ur��VU������jlY�0X�����
�U������J��*���_% h�#����n�lG�DR�Dr��)���z�b9�W	�y�b=��SqnV������W(K���K`�
_�X,����P��6�W�����TT�"�PhQ��b�V	)������9��82�
��z`�V��S-�u�|���!.�&�%
�_+�kd\WJ���!?#��?�/��p�����V�m�����
�M��+�A���t&��KJ`q������&�,U>��9�lr���l��w8����A�6��i���1�}�����8����8U����i},�5{b�l�j���F^4('����_�5�TZ�d5{b��6}���?0��+N�x�������z��'"����~�>��k��u�<;�F�ZM>v@#oy���y��G�����+'���IDAT\WN�������������L�M&���rb���������L���E�B%�D�k���d.����Dt����_C�R�1w�fc��l������2S��*}�@��Tl��[1��F�-���*m�a>W������w�@���=��jx>�J��t�������6�j[Y�a��`X�5�����0a0,X��.�8,�K$K$��m���jF��Z.��6�t{�9U������Wn�����R��-/[��v_���U��l%
c�q)p�,�^{X����m��MCV*/�/�����\VY�_<��\�V\TSXQ�eG�1��b��b0��X}�\q1�:!�!M�!��x���s�Zc$�������A$��G�?�|c��<���E�*aE+���2�e[�Q�{��lWmSo'��F�]�n�l�����-���
�_�O�~���s�<���5W�X��lm�p{k[��m�������*T
����r����a@-�JdC����|A��~�s�(V��
R��h�i�4�~��GN����<W]�����:p�8��I���
Sk%I^���w�~�`O*�y�r`����x/L��8�*����>t����|^�}�{����m���i�����>����s�������e�!V+?�Q����?��m[�|���i�/M�Wz���Y���=��Rr��QlxX��!��������L�IT�n5��J��|�5�P(���^�b�+��~N2��TRC�R����~�w=������U����s���92�F��k�%������6��;��
��+O�
�|��S�������T_,+�e���r��}��9��sc��a�zc���j��J�
�����X�E�N  �~1�����zG����J��<�j�(���@0���l��}���K�@�_�	�������@;ke=O�+�o~��|���/U�6��aE5��?*�X=�������j������qd���M���l��E�~��
��h��X�*���-�������b0�h���L������4�������.V*+��X���k��c��r���Z����`�U�\LE��V:��oF���V�}��7 z���`%��64�����������-���a��_�5<��;h�4���"�3v�n���N�6������ph��
��<�Bc)b]���7����Q��l�K?^�s6"j�	V�U�A[W����������c�����5�G����z|V{������&���/(s4+[
��;�E#~I�=��=`�|��;��N=��C�������������?�������/���}����/��/}�rO��-�+2\z�_�%�w���K>F�����r�&'��:S&��JnI���

�T��_n_��s��Z���S*�o�Lw�9N(�g�)�%��K��!��6'�))5Z���Y_���M�������Ks�2�MRi�B{n���U����+_��L���o��5��6���{�F�/k=9��B4���%��}G������\�
!�n*�c�
F�]=q��l1�J���2`(��������e���s��>r�|�������/Irja����UK�cdT�DX)���A@����My.��>T`]8H�T�q+_[�b�[�����4����������p<��4���z5���V�_�%�W��dk%���W������������:�$�R,)7����;"Y_���s��J�c�_
TZ��a��r0�HVB���C������
L_�e�yIVN����8�sP)z���n�z��tpC���*b���E�B���b���Ni�^�lS=�����X�}��_���%�����0��������"�\���@{���T_�}6���"$0��k�@�6��fM�C��	���Tg^�O���(���4?^��X��h�������k�C��n���=~�B�v��I@��AP+����k_�z�������l���u������<++"�����9�p30~�GL�p����
x��yG1#����kx�t��:�~�������U�� �dKV��s�_(�����k:���8U��������[�Y#9\.�r��p`�~���)��s?�s�O��?i��-�����zH������'�'�����x��~�i���,���:�x\��>~B���hd�
K6������x~���5[*��N��N��8����TRN5�������T��=������\���]�|_��+�:��4f����Z�O[R��rU?/6��B\�yW�Y���Uz���LI��J_������7q���cK�����zE.�l�Uy���@S	
�����'�X[�
m%�ZYS���d=YS�Z��*=����zrT��W���������Kr�/�r�A�Dt*!B�t�_	�j�B���
+�Z�M��v���Y��K���������w�7V/��]h�x1u`{ X���	�����v�w���
{�.Twi�a~�Pb�x
�m��<�x�����v�}��ZOch2��6�_�S��l����\���e=_9�UF�udb�
L�6����+Wi2j���p>U*wjY������ek��j�����WB��WS6�/���=�/���-�T����\��?��_������~9�h���j�j��2v5�h�aFI��6ttC���u�
�`�5�������eS0�`���\*�TnpI���Kk*����~��U���F��6�l#�5-�����6,K
��w��q��}���jl��TS���M������J��;M�D��3����k�N���;�����v���|tV�_���bn �Z��6�AMx�
���eB�+�cU{�_��	�(�x���g��n�O�@��}-��D�����T~��:���V	�S{��<6��;&��n��(8����S5�=x��.���o�eM�4a*�eT��i�a�@��-����C��}M����%�����u�>+}X��>0W[;F[;�Z8�:N������
��3��7�9O`3�l�
�o�.����~mE��������|A����%MO���;JnH(6�*6������}���J3��
����TavD��7�^��=`.]���������G?�|��u���-oy����N���/��'$I����o�������_�)c�q������������m[���r�tZ��Z��]�������2��$I�#7���@��1����'e���~�J�\������r*���	��>����-%4[Lh6�j6�hvN���U*-���]/�*[:��>:eb[����|�(�L��H��2=����0�iq��D�����o=�*��%YS����*ACyM_U	�*���R��a%t�p�	�I:s�������8�����h>]pmB!��E����,oo�,��i����l�Wl�r�F��r���_	�W�W���������c�N��c�Hm%$��U_�d#����@p�����W��,	0W����:�������K>���
��E�R�����_�/�����yI��H����[���smxY���������T?8$4n�<�P*�q�6���z����kg�h1�|s
�����6�����]�n����
�@��}����zKS�=���rB�k����h����^WV�j[�._����`���@���R�����1��)�n�W����}%$�`�{��r���\�wS[���^v��������d�jc�u��7 p\�c�����|�aX[�{�~��p��������78�"��^'�>��o�_�_��j�
��D���
���9_s'���W������O�l1.[�e����@hX��������lm������������n��O|�z��_][��������?hlllI������M7j���"/����?���x��T�gcT��"V�}y���l��]�d�^�/���_����q��;��8��U����Y*���*��T�z�f�r��B�|�X	�b���qK��bz�C{��K>���N�W���#�uYkU�4�Z0�����
T)�-���*����P��Ri��N�?%Kgj��&�����[�l���g45��XF�:��C��q�#���c��R��R���U�,�~�9N�R�Ju�j;'����j�j��
��F5DY���r-�Z��cj}�.��5+�V����P�����ef���������������
W�v�\�+��axM���p��X^�pnm�e@w��sk�R;!�z��c��J��c��;+{�*uV���X�&�]��
������&��������r�M5�h��!�jO��k���1���F�����7�%xk�M�`�m�=�G���-���L
�����������{[��NK���%����O:��#�H�rB+�z����W�B_���%I���z�������_��bu�{�-����H���.�����{��zRq��N���R������w�����O������+����U��G�2���d3s��Y�Ba��������|A�����3�x�@_5�Dlw�]V@��#��<��<m���(��gj��t5�W�k����>��]��7�/Y�y:��r�����^�������#%�9��W00����M!��Pa��lh��x���jxt�=�Wr9�8|������\4c�a�j��1�X��Xi�����S�-��o����,��E����V�`*��V��
g��*���w��[���3=�+�p.�
�P�'4�j�1�\��"hi�����jp��.P��6�-�Hk�N�Z�1N��O����R�	lk(�Z�G`n�c�
�W(�Zo8�P����`�4<����:����/* [Y�V���I�C���U�Va�`�&�9�r!�t�[���.^�W>��k�������}�{�[�I��>Hh�6������?^[�_�����x���q����>tX��ZS��5o��]��~�bQ~6����5�����ss=��jf�E��E�f�]�g\��k������:>&/�Z��4��Z+}��=�{����T~f\���O�(�w_���G�J>��W���r�`������a��r-4�i��6a�e�BX*u�����P,��a�z��J�b���<k�j���W0��k:� �X[�4Tf�$����l_	6�/��;����s��wVQ��w=]�z\�w��{�gb�)�����]����7l0���{�<:���}
�F�#U����r`���e(���4-��U�54ZS������������?�x����Y����S�����Op�#�t�_�Bh��~�����l��#�(��h``�g���#u�>��~����km������I3G����o������?�KW���M��o�]�}�z2�*�������O����\s�/S�
�l[���^%��y*e2*e��9��d2T��	��RM�����:=��$c��}9��d�>%�����������A�J�U���$%\OkS�V���o���<kdeB�}+��}>�W��y�-�*O��|��C���`8D������
��$�xX�P`6��3�������{�\N��8�l��@7W�uM��@�:m�-B�N�S�cl��G��J�����o;�
�w���^�-����*&�$����S�UNJ���Q��Oh~�Y��T�(����>�}��]"��X�i���6U��w@�*�A����0�S}��e���J�����u�5B{@��|����]w����[�l��;t��	IR�P���u�w�p������Ok<��J?���J����
7(�i��6n�x����/(w��f�Q��d�q~���d��fG��_NO���Bs��Ls���@`de�z�+����f�e�]��$���}�*~�����M����a���$�]���;T��|o*��%��*�]_[��uS��-]wem�
�j���3��������/[�W}������*�������/���o=f��K'k��tZ���7�c�MZ�y����8{F'l��g�-��He�6�l������6���b��v�h����
�#�a��Mj������Wt����=��4v��6�.u�?h�^�xy�������r1�����j��-�]p�����\������I������B���_y�4��
�����~Z�+M�r�I��P��M�1j��`d�q�F�6?>����g�����j����~�����<��}����/��18�O�7��rp��r�}���>���������|.���p.�+C!�]��^>����S�������C���o���������j��j���]C������^3
���&u�[��-;�����z����
��
������Je	��������i}_�e�/�>��2�J�����|^~>��tw�9�x ��K��������Uv�7:�'����w�+9�.��/^P���$�+�w_��^�����g*�9&����*��j[���:'���-�ND#�$B{�T*u���j��m��K�k�v�������8��������69���L��m
�4�g�����	u6�#�	�Z�����$�w=Ml:�����/�W*;�q����G/*70�=3=���^]�
��m���
M���6�O�	��6��.$���Os�su�s�s���Ept���������	�y�M���F�I8����{�k3l:��ADk#�O20l��������`������g�q�����F.oX��|9�6�:B{@���N�_�}�u�u�Gc�#G�,z^��m��i���.\���_,J��$)�a�6~����Z0�#30 g`����B�u��mu�6UPao��bQ~���l�E���m]�/��_��X��y`Ng3�*���Sb�u��U��-��|���������m�����
]���pb����*F�k�BuN����pb7q���c���&.jj����n�f
������b�D�M�XPzfF��)M�;�l:=�x�{:����������3�^W^����nB�j���l���Pg�q�g��m��;r[v`V��Y��I
��Q"��D�O�_�3���THfUH�)34�b2?�xg{:X�"���2���{@hS���R�s�������VQ8��1n|�"�����q�h�~j���S�+"�"8�G�/A=	�6>;
A�P87���_�q�p�)&s���J�:������UL�U�(1s����.LLL.�����6l����n�Z��APW�������?���z�����������?�#�FG{�'�^�*��5=��z��lN�\�^���*`�0`�������18�R&�R&��~������'��c�M���.��]��	y����s����
\Xj�r��2�Mr�������z����������	'��x��U�������^&��m8�N������rG������ib[���\�u�B����:��9�l:����m]!���k*y�6����5����������Tp��z.p�[`8�)<�\]np�:(��pn���~Z������~����4=6�F����sC�����}��^�pnm����|���)���O����r�����Y{Q�3K����R���L^�=�pb����t�EF���]�qo��_�}v����x�bW�=z�i333��G�d�:��W�������&~��w�����_�u���T��I�U���*�J�ok�f:�[7��R�(.+����|�-g���_6[�f����s��\`�������Whh%w��v\����=wy8����������U��'WR��������(3>�3��E�8�7��	�w�oU�����|���>��Q�B�#�)��_�Cx>����8�������j���fY��q*���#����z���v�>k�P��!�>�Ig�w����r��y]���b�;�&Y����j������XW�o���������u��l���86�C����m�1��}���?���&b]���8
�B���q�z�VcT�5�k#����%���N��i���~Hg�k�1�5��^�9qL���x�+��:b��u���g�"���o��8Vm�n�b��������7�aW�w3���M��1����n>-��?������OZ�i�\��m�_6�������[�!�8{�����c����p.p
X�pnm�Z�����_p��F�^�@zt�G�Rf��r�J_�����Hq��rZ��a�+��]h�#J*��������}v��������Q}<��c:w����X*�=��JOaY9�����o�N�O>��>f^�b]���Q�O��N�����n$��[��}_N� S(�����������N.������z��������)��S��9�������V�4�=}V��\w����.��U�h�
1v(������
C�C��@cW���*��U T�v�g�cs�,;	'n����.y���,�\��~��]����^�������WtR�(�h/�m����-���l�p�a��q���U�T�5m�i>���Z���.�-�q���8FT���yE�Q�sx]�8�����	�v��m:��t[��	��C�NC�N|��&���3Z�y���g��MM\���SNl���Xv�A�Vq�6m�
vv;f��k_�7���u�����k>�����XG�������
�/q@;���9���D���WT��������c�vB���J��3��Z3��
g��*���{!JnQ���H�2�S:����c'���8h����+=�
!�t!�����D�}$���r6�]��pu�t��L�/~�F��U�?���s;w����(���Xb�#�R���TC�Y�����z��q��s�+��=�V������J�|I���%���w�/x�V�Z�K�����&qx���#��ySm����
���9T�iZo���~,��}��}�s�g��%����y\Bm���<.�rY{�>�~�x���sku��������(*�WN���*���6U";�d�YXFW�4�h�
��	�)��J�g�%�����}�I�v&�i��s������q}������N�~�l�n��������}������������M�y6��D���I�M�E�u<�����h��D�j�=/�wL��N�8����2�XH��8�/+���.oH7j��������c:q���G�*����O!����%I}{�st:�=�S�����]�g[��k������i��g���j\��c6__���b�._N� ��W��\l��G���������l0��w���x��kQ}5l_���y�6=�;�w����G����=w�}�t�W���.�������^X�!�����������k�b��X�������C���o<����b!�6������Z_�Ni����]O����]r��]��9%]�z\�[~�}��%]������B{@+�
������m�$)s�~en����sz��J�:����r!O��O��[���:���E*l�S�q���fDs����m���
z������o���^'�E�q���������iMl�����d�}��*�b[-,i���
�4++�D#��6<��y4�/�2�(I&4�~
�V;�?8���������o��
��~
��s�j�����+1�Vf�l������Co�q��epN?�C���[���E�y��m��7����E��A��cj�8s����{LL��������`0��*j>���m�0�:����
N�6�
�2�� "wX
������a�jx7t�Q��
d��	l�l4��p��!T
��3���j<������k�Z}O��]�i���Q�#2L�����q
aZ�y�M�7~�#��Qsn����M7�]i�G���j5������p�����0��4O�e��a~�4���
�G�7���9=���]�C����R��=q@7������`�VJ��=q@�bQ&�U/���kO,��6�������������=�o�(�����qt����������i�������������i\�U_]��J��M���U�iM���n�r��}?�i���ws_�k�}/����-�����m���{�u5�<�7��k�}���s�<��{y>^���y�w]|���6�`��_�� ��_�����K�s�����il�����m�l�����e	�t�����F]|?��[��+���{�^1�KU~��?��\����Z�9��vLN��I���[����UL�?�|frR����>.`��[8������rc��N4V�k��[�{����?��]�s��Q���o�-�y�����5�^�d2z���j�w�y�VpF�����$�Z+;7'[,���2��\T��N�>�!�o�*I�+�������7�����w�����v�VaO�.x\7~�������y�F�������u�&��c�r��J�C����'���Co����$�d���v��������+�`����M�
�[n�����������������9x����>��\�����u u�������z������;zRq������M�%I����9��������	�/�*�E�����?UVnnK����|��<���5�R��;�Y��TG��6m���L�/�����[�y�s9=�����}{�)�J6w�j�E_!��K�W�����<}��y`I�o�{a�M��b7��7t��$Jw
sP�8���Ko�/������>n��-�����O��n<�b�����7l��x<������[���yl����}[����s�����|:���Z���d���=I��}��3�vi����:lnu���&�fcC/�IS���M�mmv����u�m6���t��������o�EM��A���-��:�f1^����=_�Da��Ek��5�Vg����ZIR1�����j��-�]�2C�5��L���$�9qL�����?��&����C+=�
!�t�1`777'kmW��d�u/6��a�m��aQ}jxx����400�j��"FFVz��t������#��$)���g�otF���Vg��w�epN/�0�#�s�������k����y�K������O�wtX�]���Wr�]*f�_8��~��~����q�$���g�����R���4���|���l��	��ccW�98�6�m3��|���#���������o���[����3:q��J����k��F7i�XV{��j��B333�)�j�Cw���=�j433��?\[�q�}��`�������9�>����M����������3�������M�������Je;��(�����E�fC�'�����E�_�F��d�-��0������u���S���'O^���;���������ec?��:���Q���*������v�dt)��s��u~.��s)�=��&�zZ���������h����1���G��-�����p�B��������^g�}��2N������R��l���U��V�Rw������u����><����-�a�k\�������:3�J�g�%�Q�X�����m��K�k�v�������8������f@�����
���eKpW����t��V�8|P��k�H�j�����*�Oj`v��~%�}r���~�SR!�U!5������|��\N'��m�������@�=�}}}�����������<y������'C��������Z6t���y��t��i�;�&7���$��4�7!I�V*�F�u�_q��]�T/����?��W�Z������`������A�qwL������%7�K�7!�pX�tN�w^��7GMR��Q&�Inb�w]���������������<,p
I�v�6}���olXG�[U�}���ej���&.�opP�6m���
+O��/J��(3=��sg�M����Co����6�����k9����-���cy]�>�CO��w�@��0�TL�5�<_^�����5���_j�>w�X��'�T,j������W.���F���.���?�;x��������?t�PS�������7�Y�?��t�[���d��p�$o�>���N}�!y����`�g�J3t��:���:oRo�+����)S���;�:9}/��Ju��d=����2-�����{\���&)m& �������3:���Y�C���K6S��M�u��s�e�u�8�|�����=�(1�V
����m'dw�`)����a�n�?���7(�>�g<�o�#Tq/�H����]��t�����r���xZ�}�z:�����4/~��C�����:�����:q�Dm9����n�����Q]�G�b�����>txQ�M:���*�J����H������l�Eg��u�13���'�wt&��1F�$d���������~��������W>���P��(nZo�=���Z%��%'����|�S�Xl�s��~��k����������7,�������=�_2����������g����3�����l:-����=�xE�f:Eh������K_�R��������)�|�}�i�E(���n����'2��:�����V���]��?�����|��d����O�D���Ae��Qm�������G���f�Y�~����u����9�~��^������N������a�,?�.��)�e�I
&cJ�N��7���v���mU|��J�N�������F��?��%�9��c��{u��	
��Q2I��E}��:�����������I~�q}��*��Ijx���e����g���[�	W����K�������$���cz��Gt�}����'?��������%�#\�R7��������/����W��	%��j�����Q}7�M�j��\N���;w^3G�(��������� MR7��������������&��q�v�dt)��s��u~.��s)�=��O����?���9���X_AR���������	�e��I�����o~M?����6�Q�]�%7�K�7!�pX�tN�w^����&)��(�$7�_��NR�z����+�eUz�}Jn��BGpe���_��������M���$����EMM\T����m����5V,���W*���QfzJ���+�U�
�I?x�������8*@h���8z�����}�c�u������^cZ���/Y_���k�CCCz�;���s�kYltT[?��~��5��Oj���u�[��mw�q���<��bh���o����4�6���
����(��[���6�m������;X+}#�:r���c|��?�K���j�_?@@,��m�*/)����������;��Lz����K�������$�J����epN/�0�#���T��>%o�uE��J������_������L����%I�tZ��>Wk��������=/�?'�_��/����K{?�k��
!�,����~������O���W�������>�����O��O��O����/����[��s�k����j��{�{�Y�|��{�{�>sP���T	�9##���&�^x��_�:��Q�
@g���G��'>��_y8T�3�JI*�a�X����Kc��+���J�v�J[�h�O�D;F��zpB���ZU���U�'�E�=�H��O7|���������y�����R��l�t���y-�z&�U�����k��Ok����R7��7+�������?�A}������_��<yR�����-[�H�|�������~�t���Z�-[����?��e�7\�R����x�Z��9�bA&��3���Z*��1 <���������\�����k�-�a�j�6mR���e�����9���FF:���������Vh�W��
��������/�xnN'��Fgs���a��9��y���;��w�Ll���~mN��>�em�=����c*��������_���������u�������}�FFFt��qMMM������<�5k�,��5����Vz*�2�����
o���F��xB�o}S�\F�TJ�dR�����
������z�R��������FG��c���G��O|RSg����^M
��K������'WI�h������}�/�f���~��5x�=+}@���sG������=������z��t����}������}N/{���k�X!���*y��JV�x���M���s2����a�9�
���6t����^m|�Y�|��{�k������l,)S��M����&�^x������}�$X���J�����z����������|���v����)}����
�w����;�f��pMJ��W�Yk�g�d��xB�@��1+<C�
�=������mo{��=�G}T�O�V�P��5kt��7�e/{�R��JO��#wp@��JOt���C{����={VzV����jAh�!�@���G��#���B{��=z��=Bh�!�@���G��#���B{��=z��=Bh�!�@���G��#���B{��=z��=Bh�!�@���G��#���B{��=z��=Bh�!�@���G��#���B{��=z��=Bh�!�@���G��#���B{��=z��=[�	X~�|>�|����I�t:��'O��:�����\[8���+�s0�����8���\��j�np�"�\�N�:Z~����2�k��S�t�����4��Y�	p� �@�k�]�IX^SSS��W�Z[�����L&WpFuG���������>�={������yV�`X9��`�p���yV�`�����u�����=���5k�����&������Y�7��M+=�����G7�|�JO�Y��`�p���9V�`XY��`�p�^��z�JO����WB{��=z��=Bh�!�@���G��#���B{��=z$����������ph�|8���+�s0�����8���pu3�Z����j����Z��G��#���B{��=z��=Bh�!�@���G��#�����JO������������
��FGG��~�u�]J�R+==`U��r�����������J$��m�~�~@�v�Z���a���'��SOi||\SSSJ&����{u�w���������7��g�}V333�������u�]wi��-=V��8�
��>�'N�������U�X�������t�-���o���=�T*��G��O?�K�.�u]m��Y��v�n�������"�`Ux�������z��'"����~�>��k��u�<;����O������>��{L�?��fggk��o��'N,z��/�����g>�e2��6��v����Oz�������F�/_��>�/~����W������m���^�����u�=�,j������~�����P(4m7���{���������{Qc�j�\��'Nh�������vQ��j���}N_�����o~S�V�Tj�~ddD?��?�_��_����4f:�����U������67�p��������~��1�g,-��������������;j�~�z}�s���X��|�#������O��O�3��L�&W�o~������=���:s�L����=��#��������]����)�H,j\X��28����?�;v,�XM~��^���'"Cs�y������?����������{���������_��_�G?�Q.XpUY�s0�=��m�6�>}������>�����pW�Q�z�)��Mo����;j��?����g?�����������������w���
�w]W�_�FFFt��qMOO��]�xQ�}�k��/}I/}�K�{�@���7�7�2�7��
��u�S6�
�_�f�v�����/���S�<���O��O�N����}���\u�	Nz��G�������7k���*�z���C����O>�/���x������������������������t���Z8�Z�����T>������.�(`uZ�s0`~�T�v}���������'C��b�����_�N��'?����=r��^��W6}�����v���l6�'N�X,����?��^����+_��R�To���\�~���)��s?�s:y���;��|�;�����?�y]���6sssz�;����#�Z�����/���|g(��}�v=�������O<�������������������P�U��&�+g��5z����/|���x������~W�.]��?�W���}{�1�����x����z�{�
���E/�W��]�pA�����S�N���Cz�[����~�����~Q���r���^������������j��-����������=�L&�#G�������?�'N���K���?�m�������>�O����Q*���?�������k��������w��]=���:w��>���q��}����/��/����`�?�	���K��s�N�����}���>�����O���_�r�8q����~��t���/�T�����|$t����>���E��e��t�MK15������������m���;��Cw�y����?~\��w_�����C�e���~P��Gk�;w��7��
m��%���/�E���j��
����V��98������tmy1��`��[n�E��;����/���d{W��o�]�.]������'~�'�������yz���������_��WB��[����	��_�em��;�����%
7�����~��Bc���[�V,�w,X���|��	������S?�S��g>������{���^����^�������W�ZO<�Dm����5>>
�5���?�����Q}��h���_��_����S[��b:x�������<�4�X����[��[�����[�<�H�?n��_��_��������?����%�+\mC{?��������\�����+��k���MX<��#=	�]�xQ�v�
�O���/�U�zU�}�����{���}������~�7~���`�Z��t����s�y��E��l_���C?�CJ$��y�~�P�?�xm�O��O���������3���[n�U�K$z��'u��7��'����[n�s�=W[���\?�3?��|`�Z�s0�=��C����oV����}�kMQ�
������S�N��}����������8?��?�?��?�-wr���j��M�D|���?�����|�#�~��^����ggg��,������[7�tS�OD^�����
�������=�0���?Z��O}J|f�����F=��3�����?���������vm��}��W�����]�E$�u]��/�rh�?��?����>��Z`O�~��~�m`O�R��>����}���b��z-�9�;7�x�n�����C��l���������;����g�q������kMOO/`��B{�����-]�x���k���+<����
-?���=���<��C�������w�}�O�?w����_���s����i@�4V�t�������������N_�������@m���:s�L�3���B������{whybb�e���	��=�����c�s�=��b�����r��%�j�����/����~��?2W�=��#�d2=��Z��i}�k_�{�k^����������������
����h��vU?�9��G���t�]wu4Vc[km����Z��9�{�\.��f���m_�v�7a��z
�&���XvO>�dh���-$i��-��cGm�P(����=��z<��3*����;wj��M�����,���:X.�O�nZ766��}�k�;��S�X���x-u����e���B�n����������s�j��dR��zk�c�:`u!�`�:t(�|�M7u�c�������p�����Z��}��D����������S�t��}��_�3�<��/�b�pU���>�3g�������;��3�m���={�tu�n||��Q�J�.f�^��cI����N�<Zw�u�u�Gc�#G�,z^p����:v��.]��x<���1m��E���+=5�f5��]�����^�\N�Tj�s�k���gu��e2���j��u��y�JOV�O}�S�����um����0Cp-��������e��={�i��;t�������������'\�����X�{��j�������e��l�������W*�R.��$
?~\{���r��B{���������x<�
6t����[C�.\����Z��?��:v�X�
��X,��n�M�}�k����O���_�����u��m��������b�OR�}_�.]jz=
��SO=�]�v����M�6m��{��G�~���#?�#+0;X����A_���B����w��g���_�R	
��j!��(Qa��'N�3���>������|�>��O�����z�=����-.��|���~�i=��C:x�`m["���?�q��U�j��b_K��-[t���P���V�=�*�N�����[~�\+m�t'��aP�T���>�G}T�����_��_��?�a����3�kS�������1����O���-�tnrrR�������;��~����g?����%��?�c���/\���399�����
�{�����?{��T����-��(����)�L�A��� �8q�a8QQAP@����Sd�-�(���8�?���i�6i����q]�.��s��}�����;�z���y����)�������w�3gN����,�s�=6n���5kj���j��i�����_��S���������m��?�X��WOs_{��-�{�����<ZR�!���is//�4s/66V����Z�j��Y�kgx0<xP�����%K�]
8URR��������������M�����^����f����U�X1
6LK�,�������x��qC{����I�T�ti�cn�����;���9x����S���n�
{�	<lh������L�s��as����kWM�(rqqQ��
���j��


ULL�����U�V��^0�����`���[���N�\;@��?~
0@?����9��7o*>>^�n�����5}�t������o����e����{��7�n�:����3����^[ZQ�ka�{�`���_�U.\��_�=z�b�������������:u���7���S�4n�8����G"""��o_�����������qc5m�Tg��Is_�x��� K�l��w���9����fN@���i�'Nh���z��w��U+-ZT^^^��3��)�'�|R3f�������Q#����Y�����I����kgp��Qaaa�3g��y�U�ZUy���������T�Z5
>\���3L>w��=�����w�(�6m�>��s���o��^�zYu����)��-�����s�$���W;v4i�K������o6������/�X=&<��������K�.i���z���MV���u�����}�������.4��R�s�6����R~\����5l�P����j�b����?����?n������?�����y������^��L>�����*���li��5j�Il���8q��9����������3���_V�f�Lb�����q ;���R�b���C��=[G�Q�5�o���P�.]a�x�x��� K�|C8&&F�a��#:::�������?� ww����k��~�z'V����)���c��,��[7=���&1>��Q�z�j�����=�n��i���rqq�:����)�wwwg�=G���x���L�7n�����,���e�j��
L������O?���������=a��i@���?��������k6�3�pHm���-[V�:u2����+�unhh�M�_�z���q�����?�Cj�.���9��W�:��:�6mR��=M�A[�n���Ynnn6���Z8�{�
��xx�8r�G�-L�0**JW�\��� ;��?�&L�`�;w��}������/��Y��=Y���K��7�]�x��)��X���u���eK���'O:�x4T�P�d����%J��d��U��| �0�:u��@���{�:u������X��
�|�r�����|���=d3G������V��yMb��_�� ;����IS����u�������v����A�9T�ti����� ������c�l:����i�d���@�m>l���fxp+V�d�kg�#G��]�v�s�Nr�f��Z�v����3��ka�Nf������0����wJ���������$��?�����������w������.S�����m��D��,W�F
��;vX}��+W��������+;�2@Z��d�*U����!!!�r����o���d;�u8 �p��Qq��I�n�Z�n�J�U�TI����|}}3�7�����{���`��\xd�l��������
(��Z �K���$*TH�
J��{�����ouN�����d�'�|�d��?��aV�~�z�����+w���
�������- s����i��&�
6Xu�a���?Lb;vtXm��q��Qp���j�J��]K��*UJ6l�{��X����)��m���EGGk�����...f�I��.3�`{������������UQQQ�y��I�`�����������	[�������=Y�a����?���s�l���}���v���Y 
��m3�tR%�������v����l��I���O�.X���������������&1��<l�\���-[*4449V�hQ����*Z��C������E�t�����:u��H�"�	�����3*�\����+W�\N���5k��|�q�T�pa�����3g�U_�|��Ym��9y���C����`�p��d9WWW
0�$6a��t�h���?�u���m=��S�Q" ���-[��$��eK'U����{���;y{��-��qc����	&��(WW����������*W������y��Z�n��g�&�
(�
6�T�R�������K����u���4�������Mb�?���jg��98#���5�|�X�.]�Sd#���7n�I��'�L���'�xB��K�		��9s�g���&������|}}3X5�O�p���G+w�����7o�'�|���aaa4h�I���_6Y��y^�uEDD$o���C���s^A����#Lb�
����S=���?��-[��}}}��odZ���s��q}��g&1>��a��m�����N����i����T��C�z���L�����{����n��mq�04j�(�>}:9V�ti=��s��%���
6h��9JHH����7�[�nJLLL�.\XC�uX]�lo������k�17o�T�N�t��������^y��T���3��}�]������c���z�����?��������\�����L�����w�1�
6Lc��Q�"E$IIII���_���/������)RD��������dx�M�8Q�[�V�����?!!A�G����n���4u���((��oWll�Y����z�����,h����*R��*W���7o�T�*U��?�$�J�(�i���c����������>���3M��4iM{)���j��y�v�%bS�C�i��Mz���+W.��������^^^:s�L����k������Mb�����q�s��][y��Ms�3g��z�����I�U�^]_|������c�N���o��_~�������g��6��QV��s�����U�hQ���S�:uR�Z��VkJLL��}����_��TRRR�m���Z�t��v�jsm�]��QC�V�z���W/�h�BU�T�����~�a����Z�d��M��7n��������O?Ms���x��Y��Q���_S�LQ�>}���.�����L���>��d~����W_�{��M{�&))I�;w����M�nnn*Q��|}}u��y����?��a�5j�(���CPP�6o���
����R��-U�b�����/22Rk����I�t��!����)���w+_�|YX9dO%K���������;7�}�l��'�xBqqq&q???�*UJ�x���7�KR����|����>x�df�����|���[�n�������������g��=�Y�f��o����wMn���/���/g�� [r�u��M�L�R�p�B���G)�;�@�*^���]����P��G��i��9�^p�����7��T�hQ������[�o����u���uN�:U#G�tX���o���9r�h�����S�9�K�.)**�b�����������k��?~\�7���7M��s�V�2e����+>>���z��)88X^^^6�!�=�] s���j��%8p�.\�OLL��s�,�/_>-]���=���;�c�IR��9U�X1������M���
		1�F��
*�u����Y�i��Z�f�z��i�!���<x��1}�����O����3�<cU����W��uk����8�Y�fi��Y��m��?�|||t��������[�}���h���������?o��}��u]�~��1����&M��U%�#!,,Laaai�S�pa��7/��ox���wO���Ow�<y�h���:t����V�TI7nT���M���s��Y��}�Z���%Kh��&���&�D��������t�R��Q#��������/���cV}�2�zw�����gu�����W��������}{>|X���sB��-Z���c6l�r����~5k���e���O?)g��YX!<��^�����[�v����G-6����G?���&O���
�����O��������<<<R��i��
���~��W@�h�B&LPPP�|||�����U�j���3t���<�~��g}��'j���������...�V��>��S�9sF��
���z���������o+o����W�\9��5K�������Mc ���a8�����3��{����t��=����R�Jj���<==�]<�6l��_~�E[�n��'�������s�V�v�4b�5m�4���'66V;v������9r�h���_����-��� K�,Y�������J{��������i�&����d���T�XQ�=��
�����}���m����O+**J���*^��5j��E�:�<x����g����3�t��"""'ooo���W����W��U�+�0IJJ����u��]�xQ�o�V||�|||�����%K�V�Z�����{�n=zT���rssS���U�V-U�Z�a��qh�xD������c
		��+Wt��%%%���Oy��U���U�jU���9�T��.\����O�����u��bcc�����y��p���_�������2�M�����:�4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4�� 4��)�P�&M���"��������.�f�����	��O�x�����I>��?�F�J3�a�������/�v��*T��r��i����CYrN��������]������uv��1�.	�r��.���'t����uK���������������e��J�*rsssv��~��m��-y{���z����X�m����W^yE3g�TRRR��;vL}������X�h�s��>�s������������|||�����|��rqqqv�� ��0d�}��:s��$i���8p���)�����C�x�����T�R�����Wi�3~�xM�0�$6g�
0����������k��%Z�~�����=&W�\�U��:t��g�yF���v�`���H�=:y���K����U�i����R������K�t�KJJR���a���;v��4h���(�����4o�<���M�dW���/k���Z�l�8����4���/��x�	���G�����
|�������?�P�z�����5J�V�rre@�quv��a�;w�*T�����k��9V5uHRLL��m����~[%J�P��-3��-=�|���^���=x�`)R�)�d���S-6����Ce��U���M~�-j1O�>},6�����r��fy���~.��%K���%����W<�������/�t��z����w��t���`�=���z����b���/�F������S�*UJ�^�z5s)����8{������]�v���0m��Q7nT�4}�t�,Y��"�p��UM�6-y���C���z���������/Lb>>>�>}�z���9rX�g��
:|��I�A����oT�F
U<~��W=��s
�+��c���kWu��]��������
3�a����\\\4z�h�F�w�yG��ow^Q@�i<r���U�lY�����8��l��A=z�����-��3gN5j�H���S�T�@yzz***J.\���G�e���q���5k��G�Y�z�G}�������}�*00����*U��Y.-�����s��]�x�$6q�D������R���+W.����*P��My�������;��0����YS-[�T��EU�P!�������:u��V�^�[�n��l�2=zT6l�{����4�@J}����1c*I��c���]����;�2 ���9u��Qpp������5k��[7��w���J�*i��	����r���f���$m��Y�f���%K����Y%�*<<\�g�6�����v�]�vm��&�g��X�^�����E��Hj�_�~>��#����fq
2D�G�V�R�R=>>>^����������O��v��I5k�L��mS�"E^{z��,�����A�4~����'�|B�	��.�;t��z��e���������J���z���nS�$����y��Z�`��?�N�:eV���1c�bbb��k���:u�dy�H��^�|��/_>��T�P��������K5f��x``��o��3f���'�;Wv��IG��k��fv������K��{�au[�a�� 5�=��������l�����;�" k���M�������Vtt�I<w��Z�f�^|�E�A��l��Z�r�������s;��t%$$h���&���>K�v���H�mooo��F�/_��A��VE,V��6m�����|����<y��������w�^�;��zm��������@�n��$6u�T'Ud�����>�H'N�0�/^�������_?m��]��sH���[�N���O������w����:Z\\�����K���\�+�y���+��b����������L�2���{�����3���g����3������������e���j�����`���k��������
S�v�:V�j��/5?����v���U�`�,�Qt��=���Waaa�v��n����y��@��\��*W��ic���h����r��n�����Hyyy���O���S����/_�L�Qr��U8p@��_��k�����
�`��j�������]��>�%K������J�*�����>���kM��5n�8-]����iyP����D8p@�������)(P@���W��UXi��_��]�v���s�s��|}}�����D��2�a����u��i������rqqQ�<y�J�*�t��]�����u��a������;��#�
*�~����+11Q���c�t��U������[��US��-��s��E9rD��_������������H�"z����d5���Ok���
���w�/_>)RD�7V��y3e�{��i��}


Uxx�n����9s*O�<*S��*W��B�
e����K�.z����� �����K�j���N��<4�dC�f�Rtt�I���W�&MrRE��������MbO>�����M��%u���To�p�B��s��Q��%��y�4��0a�&L�����a�[�aZ�l�������`���)RD]�v�[o��������4{�l-Y�D�v���{�R����E��US���5p�@�+W������*U*������y���[Sj�Y��k��q?~��~W�^U�b���$�s��Z�bE�c�e����9s�I�����R��U���uK��M���+u���T����U�j���A���s����������i����l��z��7����O'N��L���/���U�xq��cIv�������>�L����n����~E�Q�4z���|���7'o7k�L���������������*))�b���+��w�Q�>}�@�e�}��7��q��]����T�V���O�m�V�������5����;w����?��5���������h}����5k���;g���6����m��IAAA��m��4i�,X`����Y�t�����4e��Y������yxx�A�>|��z�)��i�/III�7o�>��s=z���nnn


�|�
�4�%���Z�`�~��'m��U111i�_�B�m�V���W��5�n��������������g������C���5j�(M�2%�c�����aCm��%9�`����PK���4s��1����/KV��������Lb�?����u������={j��5i6�I������W_�l��;vl��1��1c�J�.��#Gj��-i6�I�6�>|X��*T��e��ex��T�`A�����]����g8gll�.\h�W��U
{����8q�J�.��������i6�$%%i��}:t�*T�`�$�]���j��Ef�A����q�A��W/�U��7�d��:���qC�{�V�z��p��4����Y�f�R�Jz���u��]��q��]
<X��7��
����;��}��m����wi9|���7o�f��i����6�I�6����O�����t�����i����\���~��T�l��w��R�J�����}�X�7�xCe���g�}�f��$���k�������j���js�������qc=��si�LLL�����\����]c.[�L+VT�~��������'I'O����SU�V-��w>�d�0�fq[}��7f��C�Z}|���-[����;v�dg4�d3�����g��/����q�u���l���G�j�rR5�o��V-Z���l>����z�����kW�_�����o_
6LW�\�yl��F�����R���1���/_����4��$**J�:u��o������=��Z�n������c����������f������S}��5��\�����~��95l�P�-�j��������i���u�5j�W\\���k���g�t������}{%&&�<��E���aC�U�lu����,[�lQPP�.^���|�~��
dU��%�������4y�d�k9rD
6���k34�}���S����s�N������4f���KJJ�o��=z���36���`���U�N�����nS}Zc���O&�-Z�B�
V�H��w��=�����x8�����6m2�,X�������+|��QCnnnN��6�+W���_����M�S<<<T�r�T����W���U�zu�����M�,�B�
�\������o�������uk��[W�����"##u��im�������_���?o�
\j�����Oh��-f�����v��j����/�|��)..N��������{�n;v,��9r�0���;�������y��x��V�i�'�|R
0Y]o���z��W2�o���&�������w�����(((�bSf�2e��ysU�VM���rww��7�w�^�U���5h� ,XP:t�P���R�T��5U�`A����m[}���&�}�����;���]v���]�����-V���u��J�*���_��]�����|�r������u�V�j�J;v�P��93T�s�=grU�PA���S��������H<xP��-���WM���e��L���_���f����*aE�U�6mT�jU(P@�u����;�}��i���j.����u�����z���M�6*Q��|||t��;vLK�,I7����5q�����9s�y��


R�B�������P������jW�^U�
t����{�15k�LU�TI~�v��v����k��4|GEE�{����c�j��i�]�||�v�&IrqqQ��
��U+/^\�s������}�v-_�����8q�:v�����[=���>�X����S���U�L���_����y���;��{�����$�1�������Z�t����cu����?���z��a6��S��\\\L�V���m�x����Xj��[��*q���(�<y�$V�Z5'Uc��+�0@���K�.R��:�n�������l:T������?��S����I���Kc����/��<y�X<n���
��A�LV�Z�h��4i�����;�+��b�a�[�n�����]}���3������W_����>-Y��ICG�N����2��������)S�$��9���Z��K��V����IS�%/�����P�re}��j����s����XM�:Uc��Mnz4C�>���9�b���TV���Y,�����PI��|u��!5n����e���0
0��a���K~��^~�e����7m�4�?^�'OVRRRr���z���L~W��{���&�B�
i��������}?��
>\?���I��?���������x;w��K/�d/]��>��#=��S��^I����^��������=;yU�j��i��z���-�;m��t�M�4)�	�{���2e�-����-))I}��1k�k���>���T�^~�eEDD������)S�����S���u��a����[�}�������___���9~���
		Q���M~�5n�8���oV�7y�d�
{AAA�4iR�sCXX��,Yb�x�_�{������7n$�f������3f�l.\X]�t�)������)c�����{m�xP���;�*e��d���Aq������d`���(=��3&�m@@�v�����z+���������~�����+&&&�c��7�fM�<Y��-K�aO���-����
		Q��m����h�H��?�`��`)�-^���IT��t����u��i6yyy�������������u��>��#���
Y9�Xl.�T�#d�������u�Lb���Z�j�^y��
{����O>�D�|���mS�N��}�l��~�T����k��T�$)w���;w��x�	�xDD��-[��X���S���u��=�x�f���~���+��+I�����O?�m��eY���o�k����n��j�������|/����.]�j���|�'O���Mb����m��]����O�}�����;�����->7�s�9���O*888����%Kj��
f+�n��A/^Lw��G�����2��5J���U��E���Q�t��)=������3�
d��u�����t����m�t��Q���A���n���V�Z�d������!�aC�x����O5j���'�;.]�d+T�P���N�:e+Q��C�h��������~���2��3t����mWWW�\����i��������#G����74{��4�{����bo���^{�5������3�?��V�j�\�`������l�)^��Z�h����a�����W����M���i�F���3���3G��]�:GVHHH�?��c/Z�h��i)��9����������&M���-[Zu��!C4t�P��a�Z���C�/��������8���{����;����|��Z�fM��^ZR�dI��q6___-Z�(��nk��W���=&&��u�C��>}z�M��5p�@���)S��<?K�>�?���U�����f�jRR�6l����}��Y�Z�>}4e��T�eS����f����C���f���1��nnn<x�M9�K��������;��������'66����u��Y,#��EHH�Y��M8���;GPP���d�{����/�0����O
4�9W���������V�|�r���K���u�v��i�R��&L�`������ �_�U=z�����[����3&�����f����N�j�j��^}�U}��'�������R���S���m��Y"##�V"��m0�,�r[��!;���v�����MbU�V����m����k��E&��t�RM�2�l�����G�k��z���+�V�Z:p�@r,�9Y2i�$���y����m���W_}�����~��YcXz���{��q#y���U_~�e��;v����;�!I����s�N5k���<����i�����F�i�����TW����&Z�x�I�@�Z�%J���O>��+W&�����O>������7�t�R�X��lLK�b��b!!!�2 ;`�=�l�R3`f6�d6K+�d�����;v����&��+
��C�&��v����w-�������^}�U��?�����O����r��������EH���������	�>///5o��$��\�%�F��ll��;�����ni5�^x��U�������O�����3�����]���3���������:{��I�I�&jx~P�������sX�r���i��6�r~k���J�*���V���9����>}��tL��yU�\9�Xz�0�Y��l���C�:l�CKF�a�}��m-X���c���{�U�
��Z
.l���Mg�i ���R����8���}��Y�QZ�(3l���d���Cu���p���qqq��^�����C�{������y��K�.&��~�M���O�����h��%&�f�������qn���u��"�x�+�����jiv��4�o���,��{��z������///�<k�)S�d;11Qw��IuK�\�>����>���-kq�����*�w������Mb�5��{��
(G�6���9����x�j�J+V4�Y���a�9s�I�t��z��'2\K�\��b�W�6��_X��Y�l���yyy�5DDD8����1��\��^���W��%�3;�������R��#I7n�0���{���F�?��08p�.\�����������7�H���K��5%�������b����T�F
�j���
��cg����O�	�����z>g�����&�����
��k��������R���%J������-�T���s[����f1{��4�j�rz����+..�$����k�������&���o)W��V��`z�U��`�2<�-���#G&o<xP�w�V���S=�����s�Lb/���]����������3����l������&�...ruuuR5���P����x>|��c�����n��a�xV�Z���fg�Z�R``�.]���;wn�M{s��1����IwU����$]�zUW�^����Yz��������K����R��y�f�X�en7����T�R�����[����p�Br���)��m��/>>>��S������u�������4�]�t�dn��������i=�$���k&�Y������;&
��|�M�M{)W���3g�
��qw7�o����r����f�+fsd�NVK���aWv�����*66�,v��M�Xf58eG�������I���c��gO�����h���&�^�z���[V<�)W�r6www,X�,~���L���+f1Ks�#d������f��~~~v�L9X�+���U�2"e]���v�� ��'���9�5,-Y����2k����P=���&������[�

��5kLb=z�P�������������GM{�L�
�b���sB%����m����0����3�����b�s�vB%�3`��X����k���2�$f�JE�z��-+��7n���V
��]�����u��y�)��4Fv�r{��/��JgY��Q����:b�����X��;����~�������
��K���?@vE�@6S�vm����{�P�c��l]�	�R�^X�`A���K�i�VT�s�Nf�f�T�L5m��$�p�B�����y����*T���<�qR>��4z�h�?��M�Z��b�5�Y�����5jd�x�en���1�EGG��3�����R�a����]X�������m!!!Yb�p�kh�J���E���3�^4{�l�X��U��Q#�k�t�g�:x���������;v,��q�%J��BCC�P��#��&�Y�jQ�|��b���I)W������+��6k8p�Uc�|��G�����w��A]�v��c����f�:u�dZ�Yv�����#WW������+g��������YR�a�����y����xg��0������#�XV���\m���S��q�Il���r��Il���������D�a@�@6S�J�.]�,>s�L'Tc?K�B��}
,h�}��=��g��������$v���L7�����r��m�3g��~)cnnn����Uc�|�%���6T�`j���r��e���7[��^w����?�h��':�e�������i�������/��,5ee�
2�NHH�����MZm�wD9���:�I������+K�����Mb3f�Hs;w��z��g2~XX�Y�d���
d74�dC)W���y��)::�	���Z�jf��'O:���G����b[�l��qs���Z�j��:�@>/�������z�$���4�FEEi��e&��m�V��j��e���V�c�%&&f��C�\���gO���Y�z�K�,1k�ruuU���6�%�enO�{��W�f(�������d�]�v�k�L�?��Yl����:f�<yL�o����<g��qD9�B�:u�V{����� �s����:u�T�����f�j�W�����3�<��HO�8a�]�T)���aA�@64x�`y{{��"##5z�h'U�qe��1k>���e6�[�6����/Y2vPP��vBB�.\��c�\�/;4��l�JJJ�?����x�b�����3p�@������e��&�;w�h������2r�H�������g�9$����-���;wV�%2Fj�����aC����K3�k��%V��R�_�4��L����d���s6��w��v������������������av���`J�V��9��4{�lI���g�����
s���a�]���[�!�����=�l(  @����Y����vx���#G��84gJ)W�;|�p����k���|}}Mb��-����3}��]����L�����L3�
?w��������Q#�+W�$6o�����;�������S�N6���sg���lS�Q�����[7������"�������/�������{���;=�en��'�b�~����y������Lbj���My�J�J�T�B���m��s��L3�x�N�Rdd�M9~����nESK�����PI�z��'��g����3�@�f����5K���&�c��+V�^�!��={�����������=�l��w�1���a����6n���1����F�)44�!�R��M���g����+�:��������'11Q}�����w3u�
�i��&����[�����1���k�����2C���N�:����������m��m�<��<<<l���W/�-[�$�u�VM�2%c?@�������$���[�������{�i��Yf��^{M�=�X���";�����S�:uLbG���3l��w����7MbO=��l+8YZ�p�����rE���-^����###����;�,�1b��*�?����/_����H``����c�~���V����#L�/]�������>;���[���,5���)///�������6���}[������3m^��3g��c��0`@��Z��}{���M�2}���+������������=z����}��]��1c�a��4�;v�Y���?���n��w���?����>U�V5�>z��.]�d�X�����������c���d��g
wwwM�0�,���oj���6��o��fM#�M``��s�x������g�����{W�G���\Z�n]��sf�.s����j{����e����������_��\\\,�$�����W�K�6��:uJ:tPDD���BBB���M�6ru5�����{��y:..N}����Q5�����o�a3C������+3�w��uY�g���~���{��z��We�M�3�zX�^=��[�$�l�2��|���g��6�NM�������J�*�d74�dc5k���E��#G���{�4t�PU�VMK�.Ulll������g�yF+V����3�l3���W�J�Lb��G���0��'�.\(www�����U�vm���OJHHH7O\\�V�\��}��D�����m&i���Y��az�����G�:u*�q��?�?�P%K��o�����
64�NJJR��=�o��t��LE�1[Er����7o�I�V�Z�^�z������Y�_BB���������#V�	

���S��A5j�H���k���J�{���Lw��E=���z���m�JHH����U�zuM�4����%Kj�����tT�V�s��O?m�P����k����6�������������F�e��\v����E�)g��&���7�N�:Z�dI��S���Z�h��6m�nCn``��jb���z��'�l�:p��������~�f�7�|S�Z�2���sG]�v��!C�^U����������c��}��Wt�N*V���>��,>e��l�����+W�h���*_��������r�������a���?Mb�;wvHn �rO����}�T�F
��z�����S'��JM��j�*���CQQQ&���������<==��qc��WO
P���������(]�pAG���-[t���L�5-}������������*!!���,#��oo���u���������UZ�l�i����_4��={V}���k����� ��][
P�������;wN�����C��jJ��O>����V�Y�l��/_�:u��e��*Q�������7o������w�>l�X�;w����n�����{����+)R�bc��C�l>/[
8P���K����2�=��*{�5c��9s����_~�/�������Y�f*W�����'WWWEDD(<<\G�����u��i�Wp���+�������7���o�Q�����E-ZT�
RLL��\���'Oj���&���*_��6l��"E�d����s��9sT�F
]�r%9��#G��O?U�n�T�R%������:t���/_�7n���U��>�������������k��!&�g���SO=�b����'�P��U�?~���+""B������}�v���H��5k��x������_���������U�Bu��M�5R���u��]�pA����o��\[�r���c��f�����k���j���N�8�7C�f�����:u��i��*U�����������]�~]G������m���F��={���4�o��Iu��U�j���uk�.]Z���W||�n������k��}��o_�W���W�^z���,�>���h���v���]�v����&�~��9,?���9���65�%�fGk���8��}�j���f������?����u={�T���Qf�����1c�$7!���+88�l���8~���9$����!y���a����5�\�zU�-��E�>������]���{N?����mIII��g�������<==����k��f�EEE����'#:w��|��)<<���9s�T�>}�#G�Z�~�����������;lN�������J�*<x��9w������M9�v��9s�����Qef������m��Um����3gLn�x�������j���~��W�����A����G4k\

���e���SGc����q�L����������O?�zl����n�:��?�a�d'y����;����j��5&�%&&j���7���S��-��w���WR���9sj��A�8q��m�Z�R��e6��e�L�+W��:u�8,?��:�X�l����s����{�)S��\nnnj���v������h���2u��W�Lbi5*�z��w��}����O�����]O>���U�f�����Z�`����Kdx�|����_���5{�l���dh���#G�4����h/OOO}��w���U�ti�r�����u��M'N���!C�ZU�b��Z�l�~���7������L�2��c��z�)����4����F��
6(o��-�iz���m���q���Q�`A��;v�&L�`�}\�V-������Ev�7o^�Z�J_|����gjJ�(a���Y���U�'O���U�d��pqqQ�2\��a����f1�(���f_��/8,?�]���qqq���u��)�Y�F���W����:6w��j���&O����P�Y�F������M����&��/Vddd����*_��V�Z���k���*U��U����O=z����3�U�V�|��6�=b��;wN�&MR�z�����������_����}����c��V�����+,,Ls�����>��5k*  @^^^6��hi5�8�y��g���S���O?�]�vV71V�\Y/�����]���0M�4��ue�
h���:��>��#��U+����oCP����z�j;vL��u��jm����@�Z�h�����^�z���W�pa
<X����i����i�x�I�Z��u�V���o����U�����<x�6o�l�J�c����={��O���=����-�/��R�w�V�%��� sqq��/����}���j���U�+WWW��UKo������u��y���kYP�����K�N����3��Y3���U����~['O�����3<v``�Y�d��E�~]���u���������{�a�����0��E�>���:~��.\����������Sy��U��yU�|yU�\����V�vm8p y��/���#�X������:r��n�����p���)w����'��/��+f�*��n����{u��U]�~]����������s1O�<�Q��������
���7���*���W���S���;wng��)n���#G����s��5www���[���*_��*V�h�
r�������D���O!!!�~��n��-???�|��V��� JLL�����7n���[��3�|||T�dIU�TI���{���Hm��Uaaa
�����-�Z�j�R�J8����w�o�������[rww������������B�
t��%�����{��\��7n(**J������S��eU�re�V��������O�����q��9$��������k��o��@6���iYj������K�v�r�t���l�P������~����mwww���8�������X�����$I���:w������$�T���U�~�����Ok���N���r��%�\��$��sg���;i����=Iz���i��#�����6m��-Z$o��QC�����x4>\_��Il��-j���C�����t���w��$���_g������C��+� �5o�\��wO�>t��-Z���
���~k�S����$i����
{������G
+��).]��J�*)::Z�T�ti?~\9r�pre�0�t�R�����r���m������i��q�?��U�*11Q�T�V-���W��|�(��.����@���O:x�`r,$$D���wbU�_�Uc���$���������3��C�k����b�1c�$ow����=<rXix���;WLs�B�
���*\�pU<�ZK�S�L���4������\������W�j���kW
0@�r�rvY�C��0��E�0puv<,h��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah��Ah�����������'((��ee+�G����$��W�d��_����B+Y���k���s�]<�����`g�e����`g�v�������H�����8�,8HPP���;~�x���y�����L�9rd�X������$�;wN�����K�t��������Ky������T�Z5������Z�������{Mb�~�����EEE����:u��"""//^\��US����]b����������}��bbb�#G��������j�����uv���g�����u��"""t��yzz*w����'��/�R�J�`���.�M���k���z��w�c�|���j��9�2<jh��/����e$�����#�]�G��4o��,k������K��i���fq�0^��K��l�2�]�V�w������=���M�+WV�z���}{=�����#��k���[�L>�!IO>���6m��1�R��5����9s���y��WZ��;�n��%ww����9s��j�2e�F�eWn�����+Vh����y����S��b��������
da�������|�r�^�Z;v�Pxxx������|���[����i�n�����;�x0���i���Z�p����c�5�����5j�P��uU�n]5o�\�
��j�Q�Fi����|����9r������B�p�[�n������HV�D	�� �l��M�&M����mnLLL�_�����K�}�������SOi��a�������7n$o�����?L��j�����O&qG|8������k��������^�zv��Z�AAAv��<�������u��!��?q�������'��>��#�����Ef3G���I��h�"%$$�t�a:y��N�<��Q��
S�n�4d�5n�8�*������?�P_~��n��e��w����m��m�6I���^�zuu��Y����:���sb

��^x�yyyi��1z���c[�l��%K��gO'V�G���<�.]��=z�I�&Z�j�CV��y��f����5k����t��*���4s�L�X��m*tuuU�&M���������������TowDc��y���V���7o�<5j�������}��^z�%���S����/.�y��^x���YS?����
{�DGGk���j���:u�����;�R�����U�V-���{j���0:tH_|��M���;W&L0����=��3p�@�������D'U�G
M{�Y�j��W��e��eJ���$���*_��v���)cXk��	�w��I�����������������7��3gt��e�x�&M����	��f���8p��\f�e���G����wPe����;U�F
}���JJJ��1V�Z��U�j����� ;��c�������;��C���S/���I����?��*����������^����CsV�\���l1u�T���+i��W�T)u��Q�5R������s���Mw������u��)���S���8`1O\\��^��Y���S�N��~0�5j�H�5���f��Y�o��Y}���p]�5�m��MIIIn�K-jM���]�vi��!��|�����^R��U�|yyxx������e����k�������k�j����������,�t�R���'������c��j���*U��%J���G�s���]����Ok�����q��o�n��OLLThhhf�@�q���k�Nw���x{��y��{w5m�T��US����'O���(<<\���:q������={�h����I�3|�p}���&�=&L�3�<#'V�GM{�aJ�,�f�Fz\\\�b��5Spp�U�k���?~��yf�G@�1b�J�,��2b��)z��WS��U�V3fL��j����'???U�\Y]�t�$�<yR3g����~���hG��a�}��Mb��
����5k���W���&q{V������;Lb9r�0YA+22R�R�Z�24M{��!..N�<���3�m�V,P��yM�%K�T��%��_?}���5j��jsS�LQ����y�L�?�-Y�DO?����_��u����O:tH�)���W���*W����o�	&(44T�}�����K���g�)�I��[�G�az��t��m��r���1c�h��Q��3����)�"E��j������$���[Z�r��.]��~�-�k8�����W�{������c!!!Z�d��������(����I+W��k��f�6???-Z�H6lH�a/5*T������
<�b3wV�q�����o���W�������������O�>�+W�d��}��)&&�$6`����i�t�����W������g�}�s����[�h��+W�5��4r�H��1��m/���Y3��l��=�����{���S��O������cG�W1-V�����.����R�9U6�����]���
����5z��T�R�7o^
0@�W���3g��k��{}x�2�,��_d}!x������K���_?�+�/^\�w��SO=e�8������~���`-Z��|��1c�bccMb�>��<==m����tm���e�Y����W�B������x��Y�I�&67�p���h}���fq???-X�������[���=�e���]gv��={*..��6???k���v7�{{{���?����U�re�r<H���;��~�!�+��W��%5y�d?~��\��K��u���l�����}��*���O��2x�`��}�,�?~����*_��C�k���:�F�94�����Y���}���9Wj+f��.�q�s�V�Z���I����[-6Y������dO?���n��i���T�`A�rM�<Yf�)S�d�����7��������u���A�������{��kW��������m�6�x�f���m[��e���
O?��Yl���N��wg8��t��A]�tI�����+���c��J�*v��<L~��7����o���T�l�L7�����?t���L�����`����@��[��\�j��������L�i�KLL4���\���j����,Y��y�����/U�V��1R�+��C������b���:t�����G����&��;w����*S�L��t�c��Yl���mJtt��}�r����Ku���L�d��w�j��}:y��n��)�0����2e��f�����wv��ld��=JLL4�w��%��$�<yRG��������s�p���Z�����
@���{w���[&�_~�E�|������Tv4�8�����b�
���Gg��QDD�\]]�?~U�^]�[����>k��cbb����j���:x�������y��P�B�_���u��6m����-���1�=�%K�h��m:q��n��)(P@�
R�&M��}{�����C���j����5k��;��~�
��O?�W_}U��3�}��1f��X���u>�����n�:m��]���g���o���E�r������-��%K�\�r�_��4h�
8�|�b����}��Q�v�2ulOOO/^<S���R�K�n�2��������k��u&�������k
�:����V<��L��iS��7o����=___��Y��<���?�h����u��;��/���;2C>>>
T�����Iu��E��y����������a�9rD���O�o.��;j��iYV�#DEEi�����y�>���EDD�������R��U�|y5l�P�;wV��U���s��i�����e�N�8�+W�$7��)SF|����o�n�]�vi��
:x���;�����}[������R�\�T�`A�,YR�K�V�:u��A���,#����s�N�x�N����������3k����K�j������?^IIIf�F�e������j|�}���n����w���:y���_����o������7�����z���i��j������j�����m�6:tH.\���7+OOO���GE�Q�*U��>������+Z�t����=zT��]���w�/_>�v��j�����o��|H3&&F+W����ku����/ ���U�T�B�k�N;vT�"E>��}�����k�������������#G�k��&��3FG�5��w�������k��e�����8m��A[�l������+&&F9r�P�<yT�P!U�\Y��US�-T�N��_`��Nvy�d�k�;vh��e��}���9���Hyxx���_*TP��
��{w��Q#�j������R�Jeq%��U�t�����.���e�}��V�{��gU�D	�jHJJRpp���_��{������q��bcc����|���L�2�[����i����;�=��=zT�����o���'O���k���Q�<yT�|yM�>]u��I7�����i�&<xP'N�������~3C������W�b���Q#5m�T�?��r���)�u��-}�������->���,YR������#�/_�������#���~���N�>�5k�h��:q��BCC���I���U�jU�K�.|IB&���g:tH�������u��������;JJJ������������r��j���Z�h�<y�dx���$<xP[�n����'N�����}������\�r%�W�\YM�6U�f��m�k��eU�Z59r$9�_~�E�>��+�C��&$��4k��!���gWnk���q�Q�zu����'w�����~j$&&�:f||���������*g��5�={�d�������c�O<a���?��7f��R��a�h���///��/�H��i�&��e�%K�X{��m������3gN����}�=z�����?...���?n|��FBB���)��������?�i55k�������{-�������L���3|}}������p��'Z��,YbS���'����e�a����h�������{w�����Z��C�6���������nnnV����F��]�#G��4VJ%J�Hs���5��g���7�z�W�����HJJ2�z�-��������}�Uy��=k4�����i��_���~���n��.�8q���������f-S�LI�~�9s�Q�|���H2��)c���;���W3|���s�Z�~�����{���+W.��-[�t`�Y���+������j����.�����O?��h���Ms���\�r�����)�9r������3gN�k+R����[og��Mwk���7oC�5r��a��4����4�>K����6mr��			�g�}f�����s��3����o���>�����2���t���?�52y\-]��7�!5>���;5�<�����%���3^|�E#w��6�3���3F�a>|����w�� =G�uMl���;����[]C�-�����$���-�Ij�[�.�kI�}��������w��6m���O-Z��:u�q������9s���(Q�d���wM�6M������:���7�x#��-Z��2e���s����~2���m�����X�`�M�aF�\��x���m�-G���!C2�5�Aa�����v�t��Y����_��Q�B������6m�K�,�z����5�-[f�����=FkZ�ha����v�{f�����o��l�������id��s�Ah�KJJ2�y��?�(�����q��]��BCCm�����	���&�u�a��1��o�������i.��M���������?o$&&:�i/..���K��1F�e��������J����7�������'������io��a����g&V�\���f����a��s'�9w��e�~1b�My:v�hr�����|{�Ln/P��M���'�u~���V���h���K�	����w�}7��M�����SV�)������k�������J�2N�<�n���������������_�}(2���Y�fY���Z�^XX���A����Z����|=��������v�m���YNOOO#>>�A�g�O>����T�n]g�f���>��Z��?^^^&>�Wtt����/���v�V�d�t�Ko���c�Q�P����SOe�����9�i���+��T�b��������U�f�q-P���o�>�0h�{����;�_�����q����Iynia��?�s����)}��z|r��a�w�=�����/��d��=;�kqV���#G�z=��}]?t�P��;������[��M���N�:9�~-Q�D��5��_��Z��o�}h�.X����___����A������~VJ7n4��-�����s��;^HH��'O��?���FLLL��?3�vX�~�YN///#66���@j\��9R}������_~�E/���I���Kj���v��is������K���6��>��C
:T�����X�04j�(M�>=����9S/��R������;����>�r�����{��/^���8��'$$h��f�=z(w����i�&�k�N���v�����_����oW�u��[g�S�����3��v���6o�lu���$m���$V�^=���3y�I�&&�_�~]���z�-[�X��{���w��sg����JHH�z������S�N�{�n���t��)5l�P'O�tX�����T��m-���k����;U�|�4s��}[m�����c���~��5k�L�n��+�}���<xp�^��S�f��k�.�������Y�p��*\��]y���c�����'���,+W���n�q��]��Z��bcc��O�?��\!!!�[�����k%%%����s���?��E���?:~�������]58Zhh���������4i������-�l�R��W�����i���.\���p���;u��M�h�B&Lp�uaz�w���#������^��1c2����wO�w�}��������[�����Y\�s����j���]�������5�o��������K/i���v�+W�^uPE����Q#�Y���<o���&O�lW������o��+GJ[�lQ�������'22R�<����}U�h���g}��'j�����9cW���y��������2�$����j��������^�5����I,66V�6mrREx��;��������W_��r����� �*UJ����u���9����+11�,���s��cGu��M���������=k�O�����iS*TH9s���+W�s�����w�����������Y����1c������T�^=U�REJHHPXX�6n��+W�X����o�]�v*S��M�<xP#F��x����z���^�z�j��*R�����u��e����?�<����I��#G��w�����6�EFFj���l�n�:]�v�������P���c�v��WOe��U��y����;w������x��>��c������RXX�Y<g��j���*�6l0�5j�������j������=���p���/�����H�6m����oc`������Ra�<yT�f�t�����V�^���%J�P�F�T�hQ���(,,L;w���z&Ik���SO=�+V������S�:���&q)00P���W\\���;�j��#\�tI������G�nk����,Y�n���;w��M���;�}J�*��\��'�n������+88X���f����O�:uRpp����l?��������������-�
(  @>>>�y�����/m���b���{.������N�:�P��������8EFF��������t��Y�|��A���d�Y��y -��8r��{�1��g����T�:u����dL�<yT�Z5�-[V��������{��'Nh�������x��	T�jUu��=Cc�;wN��5K�������I+VLJJJ��[�t��E���O��_��������������YT�PA���W@@�r���k��i����6�/]�T,��{���j���BBBL�j����)"___���'�����<{���x�
}���6�0h� ?~��m*TP�~���];+VLy����+Wt��	-]�T.L~��v�����g��p���;u��M5k���5�}9s�T�F�T�D	���]7o������o�>����y��d��Hv�&�<y�����To/Z���6m��E����M����6l�w]���e�Z����/:x��Uo>�v����]�*66������


R�2eT�@�������
��(���������������o������j���Y��
,(OOO��qC��={l�p���^���-*___���(::Z7o�����u�������>}����C*U�����Z�J'N�x�����~�i���S*TP�B����P�]�V�����S�����W���/�\�%�7oV���S}?���Cu��Q�*U�/_>����������:d��j���
0��@X'�����;����?Ns���+�z��
����"##��.�����j>L���M*T�c�=�|�����W���TXX������t���OL�K��Z�\�T�V-�k���]���sRUx�9m�?�$��4k��!���gWnK��(Q����L���?���7����s���m���x��K�6��C����4ib���3���/_n,X�b�I�&9�>*Y���+W��mooo����n1GRR����?�zN�:u������k[�U�zu���Ci���d|������W�q�e�*U�����m[��v����c�����1�������J�*�����{���;��+W���g�:u2���
IFTT����,����x��?�i55k�,���Y�fe������$?��3�|�s��G��_~�����N�jv����M��w����%�x�������?�X��}�����W_Y<V�Q�F
#888��d��������i��YU�}%J�0�Q�hQ��R�J�/6���k1Gbb��y�f����3���>lV�����{����O7GRR���K�9r��i:�8u�T�����3f�0,��0a�U�b��i�&�9R�c��]��G�������f��Z��b�|��S�N5"##�����;������~~~�$c��UV��������^x���;v�����>p@�Yk��
��D��.�����
I������aCc�����S���N3�_�,Y�����g����\Odd�Q�R�T��z��k��Mu����������oT�\���>�y�~���S�>}��'O��g�����/F\\�M���<�6m������$�A���M�R}�������{[����b�����sZ�b��\nnn�{��������g��M��k���q���T������Sc��/��N�����w�$�B�
����;w����������n��W/�Xk0������N���a��3r��������7-�u�V�V�Z&�Xz���������{�����s*R�H��f6Ks��^�������K[<oc�������-n�����>�J�,i��}��Z���c�������;w�����1h� #$$$�<!!!��s�,�V�~}C����it����7o�q���tk�u�����_�
�x����Ow�M)**����y����Ow��=c��q���k��1���p��Y���?������J���������M������e?~��zt�������M9���Y�a�~�m������w�}7��oLL��b�
�W�^��Z��������
4F�i��^�u��c��!���������{��d��<x�`���Xi �������U����U�`�T�/Q��V�Z�.]�h��5&��;wN����4s�����o���>�(��t��r���Q�F���4�m���z��7l9%�����J��o������������z���Z�j�i���z����k������U�H���1c����o�^��6o�,__�4�wqq��#T�tiu��Y			��9����_o���Il��
�r��
.���7o���U������K���
���?�lo�����]�\�rY5v�B������������5u�T�Wx���w���z���������j��v�

���y��v����)W�swwW��
Mbj���6m���v����K�����9c6/�7d�M�>]���qc���K/����j��4z�h�i�F*TH����w����;k������LuWWW�����?�P���u��m��������[�g���Z�b�Y�t��Z�d�j�����9s��/��N�:�C�f������:v�h��������Ms��U��}��?����?�Il��f�h��]V������.]��K�.�6m�f���
Xy�|`��Y�i��V=/S����E��]Cj�a����;wV{�^�r�����{No���*V�h�q�W�������o��������S5i�$��y��W,���������k��!V�(Q�|y�3Fc������5�|�����+8yyyi������X�Nm��Ym����m�Ln�v��V�X�^�ze�G���T����>���4�/R��~��g.\XS�L1��0��5K�|��Uc��{7��g�������t��Z�~���k�|]b��S���i�b��:uR�j��]��9�w���?�����u��1c����q��W^�+���m�������j|���9�9����
����C-����[7�������J��������={��W2|�xxx�k������n�|��5j�=zh���j���\]]�P�����kW���/���_������_c��Q����uk��2CBB4j�(}��w����'{{{k���j��e���(Q"��
(����k����/��u���i��z��g��o_�]������wk��uj����9'L��K�.��[�n���W+G�i��������H�"����{����g�}V7o�4��o���1c����������^;v�3�<c��cll������{�Z������S���J�(�g�}6���n�g�:u*�4h�%K��X�b�����R�����sg]�vM�'OV������^�z=z��t�b�\\�jU��9S���S���nr��~�!C�Xu���,]��?8;����������of�����/^��y����BCCMV���3j�(��o���������st�}T�@��I~��Es}��'V�(_�����s�6.]�dS-�a�~�i��YV�r�����f�}���ovqq1��=��1G��x��3g2\���a[i�M�6��9sf&W�<��O7;_WWW�W~����{_j�����IIIF�������c���q���t�>|x�^O�~�i�����3��$R;��r�����<�V�����uk�V��5z�X>o�<������n|��wV�n���Z��r����r��-�d��f�z��e�����r�g���6�t_���$��+GH����c�7�/]�����~����I\\�������2��������.��-siZ^}�U�����7bbb������w��QT���?�!B��zo�{PDTD�EEPl����TPPA���z��!B������d�%�����r���9sg�{�p����7|�|}}������83��������h��l�w��1�
���z��l�c����n����;��%)))�F�f����dY���Y�f�2p��l���v�BX�b�����n��\=g����nZZ��������������c�<yr������q����������O�-�u���b�z�-�w��~����)T�PZ�=������-[�dY��^������4���6l����"##-V*������*������L[�l�-��	G��7n�Hk���]cDBB��Q�D���W�f;&K�J��U��6m�a����vLii����Z�GfUm]����"{+�����|�����[gY]�u��y�f�*��g��V?��W�Xa�>o����������������?~�����?n��*U�h�������^0|b�����m��i�����[7�'��^����W�Z�������;V=�6���U����-�|��}��6�i�m���U�lY��=��R�J*W���q����)#��L�>=G�>}��a�-����h�(Z������������2�$���S����n�w�^EGG��Y��e�n�RIV��n����������n�^�paM�:5[O������_��E�������T��EPP��M���O�5j��}�Y���i��������}�7����������g��e%$$�������n��o��;��g��i�7n�}�%�C�v�t���D����2l
???����>�Yn:�9�����#U�T)��K�.i���V�1l�0��YUYr��^{��<93���z��g����]���4G�f����k�������[����Y{ll�v��eU�+=��P�B��E�����1c�d{;����S��������^x![���q�:�����9�7�|c��������>[������:u�BBB��&7�T��U��/^��Y�fi���[������&M����^��9s��`����2�L���{j��a���W������/��)�;����j�����8b������)S��Z�h��5��9s����4v�X�������>�V�@#��������4h�I�&��g���������O�0����5�v?k���Z�x�Y{��E����fY��u�S�n]����f�F�V]�R�P�{���H��C�-l����S'��
2$��!���j���Y���������_��Id��w7k��m�U��p�<y4`��b�������n�����W/���{�j�����k�����i�Y{V��.]2k�N+r�.�)R$�#�9'N�0k�n�qf"""��RSS�LJ6J������Q#���d���bbb�g����M������vS�N���7��G�iS�Ppp�F�e��������:������f���)%%E����{��g�Z�"E�b�
=��CV����d�D��wo��]��8�5kfv>���l8q9;>��c��5:�Hg�o�n�U#���fmW�^uH�9�^<����G=z�0k��a�U�9rDK�.5k�S���z�-���G�<y��������uG\\��9boXv>|�M���<����]���:s��V�Xa�����{�����)8���SW�^��Y����/�q����+1���3�n���N���%K��_~��L�dI��
�����~�Z"�z�����5a�u��ME�U�����;��m���k��U�L���6�9p�@�e��9Sqqq6�)I���]�F�f��iii��/��.Y����c�����o��6m{��t��I���?�������f�l/^��g��������gM�<��}��I


�v<�f��������/.������|0����`[���V�Z��AAA6O0��d�|��^|�E��m���Y��3g��F%I���3k{���
'�[���7K�q�Gy�0q��j{F�dZR2����A%''g;�������x���8;i�e����Y%�e������f�������/[��^���
�Q������/����`���3��2��SON�2�Wvdwr�=�]��N�:V��T����_�iC#����a��k��fk������nk�~���^����[J.��w��}�K��I�&�:�����}��{�'���#7n�j�_���X��od����q�+���W�p�����������}����q���i�����'�|��X�[�-O<����#���;������kf�/���]�����k��������7O���f��$�����m�?9���~��'�����>8�O>�D�*URDD��$���j�*�Jo�{�����n���5���������t��r�V�s[����T��C���
�k=��S6o+I?���Y[�����iS��-S���7on�����5k��������g��ySs��5k/_��:w�ls<�T�bE/^������:v���"�?���*T��Y��=a�^$��!�DK���
'�4l���	+*T0k�����/G����m��J�*���/_�t���x������]�v6�"I����������g�����?>!����T��Ow��%�	��K�6k�����	��?���7�����.^�h����4h`X�&�������Q#��2N�:s�L��+,�?�c]bb�aU���;������W�.]��w��e1�&+����Z���1eGTT�"""�`����4i��k��L�2��w��EfmU�Tq��eT�q��
������C����7�ar��a�'E;KZZ�[�>����������p'��XK�tg��1N��+f�fmr��8�?�,�����

R��%��-U��)vM.7����w���4k+Y����[����8��Q�����SF�����a�Jn��k���W�U��Y��*W�ls
��>h�����t��!�����s��+W�q���������9�R���_=z�0<7�'i��k7g�u�<p��ap{���Q��:���VM����]1�f4v=����+\~.u��Q�ggp��Yk��5����g�����s�lF�T��	�r�L�{P���U�D	�����TPP�Y�Y�z�l���	�qqq6���
2L����d}I�O������
'���Y��X��c���v���z�����M�bbb�`������������}g�F�


5�T7x�`�={V����[>��U
�����U��������d)��n`T���	;����q��Z�l�I��m�t��U��������&mF��2���g����\�R���3\�(i/(((�jp[�n5L�*6k�l�R�}��I[JJ�"##-V+�LN}g<�v��>9�s���5k���'�IwM�4������)#ooo�j��/_��c�T�l�l�����e�����?M�����:��/��k"������9]�Jx4���>���
E��w��M���WG����W���x�o����T�NMM��-[���7ons�G�_��]����_'O�4i������;ed��d�wv��rW}����U�f8��Uwoq�g���������u�������~�Y�%��7�h������_4k�,EFF����Y�fi����������FIt%J�����N�J�Rxx����=I{9u���;w����������W���`���m�6����&��H�;�9s�L�����a������u�V��}�r��YF�?���M��q�'Nh����t�R��8�=T���qN0�7gtO�I{6*\��]�%�*T���22z�pN��=��7�a{V���s���U�fW<���Q4h��U�j���&���O�:io��fm�J�R�V������S}�����cM���������������>���;�m���0�Pxx�����<y�VOr�$vg2z��#���[�s2&����h��5�Uh���J\k���<<<L&��\�R�{�6[���+��c�Y{��M3�z�{�n����kg�5,��{�n���,Uou�u����G1��4`�M�0������T�����k����p��I���m�X����_�~fI{���*�/VDD��v�����������*�I2��n�~rcu:Kc{n8����O�f������o�>���)))�o;~���$Fw�D��k���z�����z��A�V��mw_p>W|����t��A�vwgw���3�n�����:p��Y{�Z����}�������W_}U�.]�����z�jm��Q;v����x��]z���i�&��s�����������g����zJjj�V�Z�Y�f������������g����� ��V��.\���v��i�������iT�����2�>�'O��Q��x�q���������_�i�&�\+[�=�	$� ���G`�	{+fM���O��UM�V�x��[��2c������I�	

��Gz��g��.\h����W�j���f��<��<<<����!C,V��q��~��=��*X������W^yE�g�VTT�U���,Mr�
	
�2��k���,M�1J��������������[�����
���#c���*U���v��4y��>���J�F���o�n��,a���Cc�������Dv����_�����C~2NN�l�#���z�0�U�� �|�r����*S����)�g�}V�|���d�{��s����;���f����r�1n���j����V��Q�Fi��]K����>u��a��<���Y]w8��~'��������z
����w��Y�sRW�3�����3�n���/_6�fT�*��Gn�N�:���>����u�����_?������cU�������h-3�nu�u�d|�l������@������U�R%�j�J��MsH��d�y�;���8q���P�B���oo���T3sW�v?���_�b�L��L��_������E��������Kv��.��F������;��`#G'p8�OWr�?*=�5���g�+��m����6��$%%���~�r�9s�N�������/P������"E�d�^jj��o��/��R��wW��EU�zu���;f��^�/n��.OEv����6����h���a�����U�V�,W�\������77Y>q���d1K�������������kv���&�:�,_�|��������s����Y�fi��!v���y��������~���j2���?������R�J*Q����������4y5��T�6..�!��������D��v��8q�j�������)�g5A�Ru4g'E[�U����\��?wgw3������[:gp�X�xy����*U���={j���:v����Y�'�x"�N���o��qcF�
�!8��h�]�3�}�����g�yF���������������1��H������2:���x�o�>U�VM#G�t��P�}��jdtO�I{��$&&�����9�oG��(���<`�>c��,�5Z�Y�f*W�\�b�S���l���;fk�={���O>Q�j���E��$��R�J����?�#�9F4U��6???5j���}����v��I��c�����U����3J�3���~����o4��Q��$�	q�N<sF������8���Q�uN0:�Z�Q�wHH�V�Z�A���������9�o��V�����/�3f��bVN*P��a{�J���t����:7&���c����W_}UIII.�����]�G�8�����;�3���������������Vj���~���_�^����3fL�vK���J����-����NNNN�O<���a}���c\1v��y3�������,�c�+�����S�V�t����wN3z�]	�v$���c����<m����q$��x��m��]�,ns��1�^�����g��)���0��?_k��U��=��T���W�e������S���U�^��}���9I�1C2&�9�Q���d�[����(����������������[��k���M�32�v�����n��fm)))z��g���������p�����>��38p@o����-����=�^�z�Y�ff	�w+K�Q��R%J������[�q�6m��o�i�����k��A�����f�?~\111�v��RSS���f���	��i��u���)���gw���|Ns
6���k-��.]�����9����c�����������|P~��������H�9sF�/_���������4}���6����1�]��������zJJ��w����(���/��={j���Z�x������/*..N7o�4���tF��T��3d�����B��������#u��I!!!fOx�1c�>��3�m~��������[�nv���I5i�DS�L�������i�����m��������o���c��h�"�T��9�D$���d��:|��I�#]2�����#��W�\��m��,gdm�^���U�\99r�bk��5�~FDDd���x����W�\1k��?���w����z���L�SSS��o_��qC/���������?������p�}�9���
���~���G+22R����V�X����[�X�a�5l�P�6m�:�l������P-Z����_�L�vG$
?~<[�tg��;�����k���)������y�$=������T�F�l�gk��<y��[�2��+$$D�.]2is������+W�h�����Qy���Y��a��e�a�u_�vNl��#�]�\������_��G5{->>^���j��I��d�:���)Z�l��Z9**J~���k���CU�H�l�i�������
-�]#F����k�����?���.��N�K���O?������,�c~N����������P�B������]�f��^�\���^o��%]	�v$���c��))):s��������+�����{���2e�I��Y�4z�h�LOKK�?�`�O����4���@�k�N����t�J���k�j�*-\�����m��-����5j�(���4k�L^^^fO�����T�R%E�<�K�6k;}������Q#���)11��=cR]��2e�dkI���M���9b2%J�%���������WPP��1IJJ��������2d�������L�NKK��t��

4���-����7�o�aS������5j�F���w�Urr��n���+W�����+,N;w���x�	�]���}������n��
�*i/_�|*\��.\�`�~��A�c8t��a{����;�U�ZU�
���M�SSS�f�=���.������C�6m2k����f��e�$���X�*X��a����m�����s��I��MNN��s�������n76�(Q��I{�<%�p�q�q����9�3�����Q��S�N*U��������9�����/��q���Q	8F�@^^^
vH�����_����+����6�i��i4N�={V)))�������l�/li�0`�BCC�	�n�~����B���e�I�s��YF���>���7fm����U�T)����{�l���fc�d|O��k�8��I�FO���;v���3���������Z�x�Y��5kt��Q��p���@=��9r��l���'O��>�8Ya���f��!!!'�}��w9M�0�u�������_
64k��iS���S�N�U����^f��9!�hrV@@�����e��&�YJ�����s��t�2�7�|c8���7���r[��%���a�cSwooo5h�@������)S�XL*^�n������2���S��m���JJJ���m��Y�?w������������_�����OS�L��*Gtt�M�Y���w�^����2��r�����Vp�1���������N��EXX�aBEN�3�������CCC
�q���#���X�N���g/�keG�M���CBB?�9�h�����9aO��ogts��
�<�������s��]���g}F:�cg8u���o�n��������'�n�����F��{����N�
�vn���������gh����T�b�>c���J�,�����)�)Y��F��&%$$�	�E���
��O�nw��;2�������j{-[�4k�y����_/�8�.�I{��77k[�b��[������I���d�w�j���&�d��>�W�nw����O��1�p������w�}7�}����l��f�����)��Ypp�����]�v�o������3'���yFI�7o�����5n�Ow
W�B����U,����O��`�y�f��GyD�����O[?����U'q�
�bt~�k�.��!��gE�U�������nz�����a�}N~vw��������B�
f��x���>4�]/^�����k9�-F����N��������N{���:vZz��c�����{�n���Z��a;����n���^KHH��3�][�l1k������?ns�'O�t��TK��Z�j�p$������������g�n��
6���v��L�>��Y����u���������O?���U�Q�P!��=[���f��[�.����=z(  ���������\�s������a�~;Y�I{���W�b��_�~�a����2�[��|}}��W�Z�������eU@w��gO���/������x��l���Q#��U�V)--���v>>>����'���K��K�.����'OV�h����}�Z�v�T�dI���7oj��I.��TTT�Y����m��{xx���W������m4h`�v��u-X���~g��m��w��y����[)�nK�2J:��{���?�#�g�u�vNl4f�]���~��������eddt?���S�����N�<i�}�3g�����V�/�$&&���+f�������6�����������{_x��y�q��M��w�}��n?P	9���g��H����kw<�0:�)S��m�������-U�T�}�I{�+=��Cfm{��1|����O�nGD����O�UuJLL4�;w�\����m��W/g�gQ�2e'M�k���O���3|m��Aw���D�*R��Y�3��7nl8I�vR]��>��7�|�����<����[��dT�����j��m����<�M�5v���of�5j��k�PN��������������_���^��d������EGG;dR�����[��u3k�v�JKKs�����[��7i�����=�U-mk���-<==5h� ��>�����7�#2eT� ��6�w��Y-[������kg�v��%�1�W���U�@�v{��N�>�������n	w�X��';�R���fm'O�����6��h�III���~�#�g�u�vNl���s�N�*h]�tI�/�'�{����
�K�(���F-��.k�\*����5�����r��JZ���s�����ht_x��%:{���}�s`�p�y��)%%��~a��.?���'��k��~V���
���7��HR���$���k{g��s�Y�����"iw���~�0��7�����{���$A[/^\m��5k�1c������IU�P���e�h��\9����;
6k�����/���}/X� ��,}�Q�Zdd����'O�I�7n�����*ZeL���Qu��+WV���%;v4k�����?��� ���/��T	�l_�����_�eX�a���z������jU_;v4��5��8�f��1���G]�v5k��s���_��������7������/W'�I�/��R�J��'&&�W�^N�H�i��L'oM��41�_}���J4�����<<<��?��s�O8���������6k_�`��/_nS�o�������
-��V��Y[ZZ����������_�
���o���|g������w��w����?��#����N�js���O��ss�INN��n4�fd�y��
j�-�/_>��������mRR������@�j���>�R"�=c��	l�V���y����$
:����.]jw"�SO=e�v��*��;�����Q�.]��:�y�����}�s��A-\���������F���#����R�B���S'���+Wj��I���������O��djT�a��
:p����9c�������@d�3�xT�xqDK
*���G�6w�\
6���LKK����N�:���;=��(���o����c���%�Y�(�o�����q�Y��������p�w�}���[||��y��vooo���?�����m�j�������{�����cLpp��8�t�R&�e�^>������}�������6K$��g�y���dn������'��>}�8����Y���U+]�p��:�
2k[�f�M���w���g������#�n��O?�����^,�/��b����O�+�-*T�`XE�����lW5wd�4z������������K�.�6m���O�4IG��v���9r�#Bs+���c�����3�ME�U��U���h��fm�+���@��m�����?���8q�����O?mxl�)���3�'`����w�i���v�T�V-��_���������������K/��$u����3t�P]�x����}�v?��C�^z�%�D@G2�l:t(�kUK�����_��h����sf���aDp_$���5|�p�x��W5k�,��HHHP�n�l�H�
�:uRHH�Y��34s�L�jNy���O<a��V�Xa���%���s�y*V�����������Oxx��q���/��x���?�PtXr���'��C
4�%$��kgV�������g���e��'���f��Y�Q�����o���O?N������)b�4�s����_��$���4����:{���k�>�������;i����.]j8F����z��'t���,�y��w���{�9m����J�59+66�a�e����
'�fWjj�~��w�vk�1w�
��/�V���
%�����od;������&������[LR�>}��x�	%$$8d_111z��g��g�,�������/^����gk��/_�SO=����#FV}6l�������{�Z��z��a�~��u������K�.��O>���r-5k�����~��'����E�4~�xE�^�*�����Z��Ms��wsw;'����Y[bb��{��lUxNMMU�~�����W/������;l���c�*U�������������<x��k�j��e��q�FEGG��K/�d��>|��m�����m�f�aI�)>G�S��Y����������;����;$��?���---M��u��e������Kj���>lw<������'O�����k����t�w��e�C�������������6��{���5bt����jS��������3GX�b�Y[�
T�\�����p��Z���z�-����T���S={�������-X�@5k�4ys�����#���&������1c�Y���>�|���������T�Rz���t�����b��IDATv��z��a8��k��6�	��������-&����S��
�i�&��q��%
6LU�T���m��^E�U�
�����?���i�����1k�8��`��VU	0�����M�f��m�M��n%m����9S�*�2%%E���3�^��'�]Qm�Q�FZ�l�
(`�����{,���E���1c���_����M�2����Y���;�r��:��]}�c����R���t�bW���C�j��f���1f����������U�Ve�}\\�y��'�0��J����/
�i$i��9�Y��/^ls���]�_|�J�*��~�j�d���du�������g��U�V��[��W�09����z��G���������m��$�_|���1k��
�Z��~��g�����=�W_}U>�`��-O�<*[��Sc�
�*/%$$�����z2�����{�m+���D��S�����#G��`���W���t�������{�1��-IZ�j�z������g�Grr�^x���;���s���$}��7�P���y�-[���q����S�f������N�j���a��{���+Wl��R�J������C=�]�vY���]���CV������U�fs��b4v=zT�����o�f�EDD(..�!1�i���r������m[����������5k��V������v{����j���Y��5kT�~}��������7��J�*z����	���n����o��%K��&f%**JC��o��fq���+�d��f�c����855Uo���>���l������v�����^A��j�������%i��Y*W��4h�>}�������A���{w������6IF+U�T�H1�Rs��i�����u����k�0a���/�
h��q��w�YE����������^�zZ�|���������n���_j����qv�	#!!!Z�d������[��aC=��������lu��u-]�T�{�V������:����2����	��W�^��5k��0��Z-Z��r�<y�&+f�|�����O
_�8q�5j�i���u���qcM�8���1c��R�J�����SG+V�P�"E�^[�`�:v�������^R�n������/�N�:����'uft��5�Z�J�
Rxx��7o�?��3�q<'�����?�P�f�T�L����Z�~�Uk6l��v��i���f�-ZT�?��3BvK
40�������m���O>�8����U�z�+��.]Z��wt�.��������~����9rD���S��
5m�4]�x1�>����f����+*]���x�
���XSDD�a���;T�n]���?'B_�|Y�~��*W�l�8b�1'+�}������$���G�5��E����r��!�5JU�VU���q�F�c��*TH_}���k����SO=��E��k��z��������_�~j���J�,��'�|>G�e8������S�N���W�VDDD��q<�=z���K�m}���<x�Z�nm������5jh��9Y�7�:uJ���W�
��E-Y�$��wsw:'�����_m�0���]u�����K-��v�Z5j�HS�NMos�D,g�y��~��G�n�Z���:t�V�\iUU���$-X�@�:uR�6m,V�6l��1�H�J�������/�:��7�����
��dV)u��q�	�QQQ�W��F��K�.n{��e�5J���WTT������nSq�O�>���5k�>}���m�i���c����l��$9�c�_|�R�J�����j���
S��-������z�����K)RD={�4y�����������///���O*\���k���S�Z����O+22������3������K*TH��������w?�\�r�4i��kk��U�
��dY������7o��w����p}���Y_z�%����$u��Q#F��������%K��n��&	�y��U�
2�gN�q���C�������g��������-[������DFF�<5�Hpp����o��n�I)���Q#U�\Y����t���0�i��a���>����


R�:u���P���())I���:x��6m�d1�+88������q��9��Z�j�O�>�7+�K���U���#�X�T�t�R-]�T����V��*W��%J(((H^^^�����s�t��A������y9��'�������������W����*T��C�����g��5Iw�i��y��4j�H~~~6���K/i������?�^��ysz�U�&M&�={V�����Zg��5`��brW��W��U�t������3&�����j���,X���`�}������5�x�}�v���C����S���V����P���W			���ULL�����C��E�^V�?�1c�h��1���V���U�re���*44T�z���;���7���w�2e���������g�}�������7o��;���1c��M�6�X��|||t��Y�Z�J4����_�g���Z�;��?����_u���bE�M�6i��M����*U���U��T�R
����t��<xP��o�+���S#G��c�=f����G��C�*UJ��5S��%����.���CZ�z����M�)V��&M�dXQ&;�������y��:}����7n�C=��� 5o�\%J�P���������/��������*����[7?~����t+�������g�yF�������g���]O9�������'�|�����H��WO5j�P���U�pa%&&�����a��D���@��=[5j����s����������������}���[�n���W��M�B�
���K�/_��3g�e��1*3����;�W�VM}���~�m��8�x@%J�P�-&///�9s��z���G�~��5jdWL����'5z�h�=Z>>>�Z��*V����0���SW�^�����w�^���[��]���.]�X<nY��[o>�#!!A���������6k�L�K�6|-((H3g�����o����7o������~�V�Z�\�r*X��bbbt��-_������93�k��T�T)�����0a��k����j���Z�j�A�*\������m��V%m����|�I������
(���G�Z�2�RSS�j��,+�/^\������_���{���Gm��5�������3gj���
		Q���U�D	������OW�\Qll���=�����uc������^�z���#�LHH�G}��>�H��US���U�P!���OW�\QLL�v�����w���d��W^������%%%i������O��iSU�ZU���Sll���9�+V&PO�4I��M��C���8��%K��k����5k�("�H��]�x��Z�f��t����q-)V�����/��UK,0{����a:���>��C�f���O?-OO����������z��lm�/_>����V?
�S�xq�]�Vo���&M�d��Djj�v����S�3�����_~Y�Z��'\�,XP?��Iu�����������C���eK}��'��co�^��u�i�HDD�]����_��K��R���c��Y��C=�_�����S�bE�^�Z����?n�������h���
		1����O�������3f����lUbzn�������k��������C&LP�N��������E��={���~����n�[���9s�N>0�.���y��������>�(����\����SO?���x��L�����^�u}�����<yR?��S����/������Jv���k��U����aEg��9�Q%�.C�Qhh�^y����f���/�W1J�p��)g�������O��=��uk�����4w�\U�^�!�����k��e�����k�7n����s�~wsw;'~���t��I�UJO�>m�gg���N9�����w�)))I;v�0L��V���5e��l������^|�EM�<��}[��qc��;W]�v5<&%%eY�N����3g��6m��0�6f�m����J�$���5k���9sL����Z�jZ�f�:w���{�f{���+���Q�%vS�n]�Y�F�:u�������{j<w5w����G)O�<z���-&��������V����;w�Z�lix���5-Y����j��a�����M�������G�^�r>�S�3Cp3E����+�����@�Vm����>}�h����[��$V�+X��Ccuk���iGO������j�*5k�����y���4q�Dm����7///u��]��������jN4k�������M�����su������k���,+5�l���}���i��yz��w3�}������C�������'��)SF�V�R�
�^��a�Z�n��������j�������T�hQ����qc���:���p�1�h���3g�^y�����,XPk��U��m�#,,L+V���?lW,�
}�Q��u$OOO���{��s���oFz����m�6M�>]���r�O?�T������,[����]k��$�2e�h��Mz�����u�%`�>}�h��-j�����T�XQ����W_}%///I��z*'��9����5
*���Wm��upT��@�Z�|��~�m�������c�n��n���&M��#lzo}}}�������������w���G<����a��5k�k��


rJ������E������<V|��W�<y�
*����v��i��u�V��]�T�ZUk���C=����v�=z���j�*���X��"##����*00��m4d�m��Ue��������U�j��mz�����!  �%�����~�;����Z���]��4h�y���|?���G����4|�p��w���8�����@�+zY���X���K����N�:��3g����R�*U$OOO�l���������;vLS�N5�G������k�D�����F��R�Jv�c��I�7o����kWe��5k����Vdd�j��iWLp�
h���Z�n��y��&W��YS�����3g���?�O�r��-[����3i��a���-	

JO6��I�L���Z����I}�������#�e�=��c�������G}T[�l�����k��d��Z�j�����[�*""BQQQ�����O���C����T�lY�����P�:u��{�����Z�n�
.lS_����Ok��5z���U�fM�'�+VLC�����KG�����O�������U�re��

��o���{��q��v��|�r��z���e�J�*�����������/���(W��F���G������y����&L����=[�py�����C�k�.�'�[�i��i�������Mcwxx���5k�8!B8J��U�p�B���K����Z�l�"E����G>>>*P��4h��_~Y�-��}���#��o����.�����S9���[�f��w�}����[�M�^��g��{�a'>>>���O�k�.=�������vE���A����������9�|�U�V�~��Vo��U+m��������e����^z)����+j��9�x����������J�*v%�zzz�u�������k�.=���v���/���3���?4p�@�l�R�J�R����J��n����u����%Jdk���0}����m�j��eW�T�`A����5jT��~�������j���N{hS@@�F��3g�����V�.]T�|y���K����X���v�����Z'O���1c�'O��>}_8((H�'O���;��wo��O���w�)**J�|���1����~�<��{���O?�������:v�����[={��z���k�h=�����u��>,���~2����s�9�"2`�GZZZ���r�n��i��9&m�{����~������S��n�:m��U���#G���x%$$(  @���S�T�F
��SGm��%Q�.����u��i�����}��;���O�����q������?~���_E�Q�:u��A5h�@�J�ru�ff��e6�e���8q��"�]��;��s�j�����w�N�:��W�J����U�D	U�ZU��7W��������n����W���:t��N�>���x%''+00P���*P��*V����+�V�Z���p�JG���Z�~�"##u��A>|Xg�����W/___���W!!!�\��j���f���U�V�D��-����b�
-X�@�6m��C����d�d���Y��x�u���a�g�\��
(%%��}��j���C��L)))��iS�9���Gu��I����������M?�,XP�j�R�
T�~}U�X�!1��������%K�v�Z�;wN111���Ppp����U�F
�i�F�<��YE���$9r���r��9�������_i�����{�N�<�+W���A%K�T�*UT�vm�m�VU�T�{�p{��5Lb:y��]�$$$h���Z�p�6o����(������G�
R�j�t����[�n��{%�JD�����j�*���S������u��M(88X��W�*UT�fM�i�F�k��99�q7wr�s�5k������u�t��!������G����T���4i�.]��N�:��$����fU�u��1�T��ELL���[�={�����:t����=��W�����JNNVpp�����7o^����v���U���6m�k�SSS�|�r-^�X���:r��bbb���(P@���S�z����������x���oZ�l�6o���/*66V>>>��?���/��u��]�vj���Y���+Wt��9�6�+W.'

4Pdd�I��~����!�_�~]K�.�������]�xQ			���L�/^\�+WV�*U��A5j��!��r��YiiiZ�f��.]���H>|XQQQJHH���������-U�TQ�����U+��K�������X�B�Rtt��_����@-ZT�+WV�f���S'����'O*!!���`��.��T�n]m��5}���SP���s<�[H������%J�M�0a�^}�UE��RRRT�jU<x0�-88X'O��i��M���7����Q#�_��E�)�'O�K/�d����Ew�7�xC_|��I��o�M.�qqq*X�����L����gRY��Y�z�Z�ha���gO����.����W ����1aO�Z�l��h�///
>�������4i�k�\l��efm}��"�����k����g����+o��<x���r�o���,a���S��7wQD�5z�h�eooo�{�����X!99Y��Y{xx�j�������'�xB5j�0i�����7n�("��2No�����i��h��?��S;v�0k�Xy�111��s�I�k�����PE�^qqq?~�Y{����?����v�����������S�r�\�5$�Vx����y�f��g�y���i���;v�I��4e�E�����{�n�6��w�'N����7k�c�=������|�r����/���_o���#r���4=���:y���k�>��"�#G�4Y

��a�\
�E$���7z�h����&��������^zI���3{-00PpD�r�v����G1i5j����\�.'��i�F-Z�paD�r��A
:T����i�M�6�i���t���k/������ko��4H���sQ4������Z�j�M�����K�.�����^S�=�
�m��Ys��1i{������p/"iw�
6�c���\���
�;vd�M||��M��j��i�����|��*T��������/�����h�3��@��|�r��?��E��VBB�F����p=������_�z`��;��W/5k�Lg��1{�h��z��w�2@��]
������h�Y�h�Z�l����Oc����C������K7n�*U���s������������p���z���A+V�������p/�H�����<����7o�I[HH�j���
*($$D����z��.]����wk��mJII��g�6m�h�"yyy9;|n�����]���5x�`F���oW�:uL�<==U�B��UK�VHH����t��%�={V�����,�����%K�����wv��W�vm��*TH�k�V�2e�<y����+�����m��g�e6��W�^�����:;\�tI����L���o�
�("��H��]�(i����������>��%��#00P?���:v���>,1J�����?�)S�����a}�^���-<==5p�@��?��=��2e�h��U$��\���W�|���M�F��j$�����+��[�n6'�yzz������={4~�xyyy98Bp?e����#T�zu���7�|�����s`t�{�����������������K/���#z����n������� ������-[�h�����s��;�S�N���+JHHPJJ�������P,XP��w�"""��eK(P������:uJ�����M�t��!?~\.\��k�t��u���G���


U�����EEDD�v��������u�]��M�6i�����{��?���O+..N			���H�/\�pa5h�@j������]> �"i���8I{8I{8I{8I{8I{8I{8I{8I{8�����bcc�r�����%K�������%11Q�N�J_n���BBB\ �����V�\�G}��a�=��?�T�N�\ x�:�$�� ��@�+Y�����������(S�����iS�r�
������8��������8���>�G}4}9��-����=����g�\�|yU�V�E������������T���y��0"��0��0��0��0�k1��0�����w/OW����=��=��=��=��=��=��=��=��=��=��=��=��=����~iiiJMMUZZ��C����!OOOyxx�:$��RIII�r���\����$��������y�*  ��I|$��2��������k�\
�\rr�bcc+///���O�vY�I{�HRR�N�<���dW�n'%%E�.]Rrr��/���=��#l����S�N��Y������g��������@.q��9%&&��yzz*o����7�|||��IM����4%''���k�z��n��a�z\\����U�H����=�\ %%EW�^5i���U�������P�&���GT||�N�>mR]���+*\��<<<r,&��\�v�d���C%K�$a���� �(Q��-%%E			9I{�@�*{���uQ4��������o���1���d����H��e�^����������������b��'OE�-00�d999Yiii9����\jj�Y����"�gt�dt]�,$��9��.�����y�����H��AH��AH��AH��AH��AH��AH��������#��W�^�	@6�������t�������b�����2��w�
�gwoW������h��=������W�
�f���^��<=�K��I{���c�����t�R�Y�F��_��n�|���gO
8P*T��(�!
n#--MWo$�����z#Iiii�	.�b�
yxx��>��!���|�#""\7��W/�������	n*11Q�5R��e5d�-]�4��=I�r��&M��������>��w*���������g��t�v�����I�������ayU�D�:�S���.��IJJ���
_���W�b�T�`A]�vM����7�_�y���c��i��I92�$��%�����G���%��\�����c��p��ZqD
�C�bD9��\8#�������\	 G�)SF�>����m�������'���������{���'N����W�R�������tu��\�vS���M��o�4a��������H
�e�._����qM�6����u��
6LM�41I���<y��g����m����o������K��w�����c���S�	�4�Y�������MX������������[k���< �,���?����O��������wf��S�����\���AQq��/*.QO|���=7����:d{������g�5i[�x���r������������&]����~�\O���m���-�?���}�-RSS�n�:<xP���������-�����@��Oll�v��������y��BBBT�pa��__�K�v���q�����[G�Qll������E��a��*Z����8���n�����+..N���
P���U�lYU�^]AAA6������k����3�p�����T�paU�ZU��w�UU��6iii��s������/���+
P��EU�J��QC^^^�����X�_�^���Stt�RSS�r���V�Z*\���C4��7����������BBBT�bE��][!!!���bbb�n�:�9sF�.]R����A��];�m>�
6�������P������0�b:v�������'O���+���Vhh�J�.�F��5�8���s�NEGG���K���W�B�T�J��UK��������n�:���[�����7�J�,��-[*���N�<���7+**J�/_V�|�T�hQ5m�������)��y��������O�<��h����6��*�e�������u��n����/��B_|����=k�����{�1�;V���6�c��m���_�d����Ciii�-[����}�*O�<��k)�l��1b����/_�������4�Y�F�����.]�d��5jh��A�������7�z��9���/�~��L����R��5����j��


����k�j��QZ�l���O�V���5x�`[�+""B+W�4k_�re�I��
������7'�<yR������.X\/��j������������_�~]��Wll�$)_�|:w�\����v���Z�j�/7h�@7n�t���T��=[���������<<<T�N���C�=��C���n�]2��Xr��MM�6M_��v��e�{����F��W�^z���`w�����r�����>����7O7o�4��N�:�4i�7nl�������;�h��
f�yxx�c���8q�J�*eU�7n�����h��e:���u�����uk
:4��������s��V�L���.]Z�������h}�������u��)���m������z��l%%'&&j���?~�.]�d������v��1c���X~��MM�<Y�|�����k�����������_�<�H��w�1�e��\���H�y�:��������Ic�4o�Y-���}�&�.]R�&M4x�`��=�VR��9sT�V--_�<�����/u�}�i�����}{�	{�t��Q
8P���������?[
<X-Z���_~�e��$���K�z�R�V�2M�Sbb�{�1u��-��
��{�m�6
6L[�n�r�k���[�nj���.\h1aO�UI���>R��iU����W/yxx��������KKK��#T�B}���Y��._��Y�f�E�&�y���3�<��|����3'��L�:�d�_�~����~��][O=��6l�`1aO���n��U�
��	��#�_�^+V��/���;wf��OII���k��o_����9����7O��w����c��'�Jjn������k�>b��n��0aO����?�6lh��%I��5S��]��O?e��'���,Y�D�Z������l�>����V�2e4v��L��[�����:���V����3j���>����=��{1{�l��WO��m����q�FU�\Y������=���s�������y�]�v-���yL���:���9c�����@N���j���9���Gu�"9�/wv��U=����e�I����J�.��*:::�
R\\�:u����ggk?7n�0kV����/_>%''����f	{��U����c�.\8{��
����?��-��y�*11QQQQ:w���:k����������,������,1G�U�.,,L~~~�z��.\���/f+�.�}��fOI*Q���)����8qB�/_N�������������Y�l���%%%�����o��f�����J�,�
���k:s�Lz=K���������S�N5I������5s������`u�������/�c�=fW�B�T�X1������K:~��RSS����~������0i�X�b*Z��<<<��'O� ���v�Zu��-=Y���_e��Q``�N�8a�OJJR��=�}�vU�PA�G�6�T�/_>�.]Z���:|������_;��{�1m��]>>>��d4�/^\���


��k�t��I��e�&MRBB����;[�
����k���^^^*U��
,�7n�����/o���U�6m�������0+VL7n���C�L>����z��G�g����7�����/=���~��I������)�|��)..N�6I�����t���k���������3�)�n���&�+VtQ$��H����?�M��+�8��c�t��UU*�#�sW�6I������/�����T�R������1c���_����z�����/???u��I?��Z�li��m111�3g�>��������W��}5o�<�~�.]*I��c��|������~:�d�Z�j��k�������4i�b����s����9S�G�NO���g��~��L��EFF�$ly{{k�������J�.m�~TT�V�^����+��n����������P�B2d�z����E����~�z}��Z�l�$)!!AO>���o�nV�h��q�I~m��Mo�Y����g1��e�fsN2d�Y�^���������T``��k���4k�,���U�VU�����E��Y�����r��V���o��$�=���f1�v��qu���d}???
0@�{�V��UM����������o����~�*g������>kRU.o��<x�z�����p��/_��U�V��_5L���z����7o�x����������+  @���jK�.U��}���;����^����+I�_��>��EDD���K���j�}��^������{�j��)z��W���T�Rz�����}{��W�,�,--M�v���)S��7��Ww������cGu�����|0}<���O�d����f���"E��-%:O�0�l<-[��>��=��#��?��k�N��������?��k�4h��=*ooo���z���T�\����]��)S�h���JJJ�$�>}Z�F���1c2�{��=f	{��7�[o����[�$�]�zU������}EE���i�&�����<y�a��<�����8���}��.��I{w���T��b^�'���p"�����k���������K�}��
��7��/{xx��~P��=��-S���L���u��_�~������C��g���Z^���/��'�P��m�������{��%)IR�6m$�JV�S��e�_��s�=��?�8��Iaaaz�����{w�j�J���t����a�j�]�$�o��F�=����)RD]�vU��]����gZE��O?������6l���������j����.]����/��t+��?4K��[���>������8'-^�X���7i{��W��_�����W�|y
8P���g��/�`R�i����&/�i��i&�}�����SO=eR�x��Z�h�j��a�~PP���m��m���O>qI���D��r��D�E��d�������_�:uR�N�4v�X�
r�����U�R%-[�L��7y���C<���.]��5k�'���;W;v�Pjj��v���~���z����^|�E����d���o�L��<y��4i��h���C5k��W_}���;�c�����=�0i�X�b�I�w&�IR��M��53�{�n
<���k���9s�����)Y������>}�h��-fI}�=zT~~~���?��5h� -Z���8}�t�9�be���du���$ao��z������a�~pp���������U�V:t��$i��)�������c��3�)�n���&cE������0"�>$����]���c�g��]��
'�c'
��zH+�
p��o�0a������_~�e���;���W�6m2K<�J�j���~������?�r���I��O���c��OvYJN��t���:ujz�������/�X�Dx�����

��`F���)!!���)V���������yzzj�����y�6l� I����4b����X��1b���SO=�i%��Z�nm���K
8P�����~�A�|��|}}3����Z�jU�r���U�^=�u�,Y�����/���e���Qhhh�g�1c�IRo�����V�4���\���G����Y���*V����{NS�L�$������C*_��f��a1)L��}�Y�=Z�t����s�2}��7o����m��<x�F�)�V�7KI������W���f��i����m3��X>z��,�����C'N���%I.\��-[��Q#����7���;}��������%,,L����j���~�7n�Y"���c��[�n�>��s����{/��%���Q"66Vs��M_���7Kp����?�29�*T��
�/�[�����E���Md2����K���V'�d��~��K����nu�����������;$.K�O����������;|�6m2Iz��I������z����m�}�$;U�2V2d��	{��1��c�Z��w7z���U�f�,�{��G���~��,��<<<����m[���B��ng�������������������a�eFaaaz����Z��'�0Y��u��u��.��O>�:�5j�S�N�����SJJ��z�:���cuv]�pA��w7y?�����0*�~$�@.������)������)&OB`���JLLL_�����I^�
��"���)S&������(������Y�wV�����_�������?���������gk���[�${�^��!q���%KL��y��V����<<<���N����III�������G���X�"}����b�Fwr��i���/}�@��{���?n�z��W7Y����c�=f���9O�<i]p�p�X,9w<����L�z�!U�P�i�{���2�fx���k�,�:u�p���m��)}���V�����<�����������)�*11Q�;w6y������O?�������#i��������Y=�������
�w���[���f��~X9�}����pW�3�@�"""��}v��STT�&N��=z�F�*R�����#����9}�����B�v��q�;V�?���T��B�
����0�;+�EGG[��m��&�=z���q�ks�iiiZ�vm�r���7o�l��
�/��x�[eL<tt�i�
t����//[�LG�����y�t������\���3\w���&��:u��h�����2��������\�{�[��U�����n%�Y���q���8����c�;�������l��


����������8g/gw3�W����.\�d���+���Y����Jv�q[�R�L���egS�Ujj�z��iR����K�f�R���]���`ni�M:yA�\��Nlr�V_��������j�/PJQ���(��;f����SV2Vv�Ftt���~����Rv���*O�<6mk�'Nh����?�I���2K�x���5j�(���W���Io����y��l�R����5k�z��������EEE���K��{��5�g�;����9b�lK�LV^x�����n%ON�6M����+�����b�9�3�����P�BV�`�vF�Z���z�j
0@;w��z?wrfRXN�2&�e&00�d��{�1�n��!2dH��������c��z�����o��/{xxh���������J{�F.%%��=����c�&��p��z�<�������d'EpW.2Vj�Jv�?r������������=IJLL�y[kl��I�j���y�lJ����7oZ|���G���*U�d����K5t�P5o�\!!!j���������L�cS���T=*7�3����Ct�>:u�dRo���JN6��y��	������U�TQ��M-��19';IE��[�v&[��I��j�������eK��$���9�9r�{�S��3�)�h�������M������{�E�G�=p{����Gu�f�]��uY�.���ZeU%��O�������!�\���fo���sl�J��O������X>�V����7Y�X�)+�
e����j���N�>m�^�B�l�R�*URXX��'O�*q�~���,Y���l�����%F��YS��7W���U�xq���G���&q4����e�j���?~����+�9s�l���D�X�B+V��[o�����k��Q
6[��RSS�gN�z�j������5l|||��w���z�������S'�����[��4�*{�i������+��}/Y�|�^|�E�d3ooo5k�L
6T���U�pa�������d��m��H�w��('�eGS�����5z�h��>�@�����"���=p{����m��l����t�f�:o;��u�������<U24{�[���Lh�&�5,�����2&�%$$dk�k��Y���)St�����"E�h���j��]��~�������F�2��T�B��9S
4�r��&=��w���o���k�j��eZ�b�6n�������{��MM�8QK�,��U���Ne�w��U5a��l��Q�<�>app�._�5�$$$(55�)�{}�������j�N�j���������>}���O�<�L���)c�����q�K
d����CM�2E%J��t;gW9������2�)����k��C�v�Y�l�L���c�;�4i��j�6p�@�1�E�C�����d=�����n�MN��;�jY�J
�a����.��V����
��}���������lmgr[V~�����s��q��Vm{���l�e���g������-Z�i���l����S��7W���5l�0%%%i���Z�h�~��'>|8}��W�^���L��������6m����$444=i/--M���NIN	��>��J�-Z���O�'A�^��s��*P�@��������9rk����j��m����W��!__�,������s�c�w���r�b�rd\v�1�]���z��WL�z���/���E����
�����u�f�S�>3I�2/�9�r��j�����L�*
�z��T�d���wgk��;wZ�^jj�"##��k��mu��$���'[q�����:{�l�r�v��N��~���;��8|||��qc�1B��I�L��-\�P���3��h��&��N�8��$��5�M*T�`��y�f��������������.}y���&����/��r2vG��q�+6l�`���O��������sT�L��;��r�-�w�����w��&U!�u���S��������C�����+�{!����#���F_q�> 3/DX�(e�[����������,�\�2[�[�~LL������+U�d�><�3g�����L&�g%**�d9;q�^��)Irz�����SO���Y��d���GM�6M_NHH�����q����8�5o��d����~�a���_�����N���:w��,X��^�|yEDDd��}��������m��������2����-Sbb���AF��s��-�����s���,�Z�2Y�����S\m���z����������C��9��s�M�t�M:�3%�sj?`���E�H��N�G�����ra����5i������t��%���p���I5n��iu�_}����JR``��rBB����d��ugB�$EGG����];���':-�;�����9-�{���?*66�)����R�>}��O�8�%K�h���&I�}����J����Z�n���������#/^\5j�H_�����Y�\�d�8���hR=�����[����w����u���l������T�z���#G�h���.���XsLq��+W�K�.&��V�Z���~����#���=p�}���������+��/�z����x�����sJ�E��ix�jN�;7			Q�����o���a��Y�����ku�G�L�/6l�`��d�������j�|��1��-Z������������7����"cBE���������BBB����7�
o�t��|��q������>5k�,}9..N/�������o_yyy�/��7�6mZ�����z��eu4Y;v�v��ew���1�!C����s.�w�u�{������e����H�"���{�rjj���y���f+W<x���k���+W��(��c�1�6o���;��������Q#��?_���.��$�����������Bl����?�W3z7P�<����/��f�n����Y�|8p�I��I�&eYk��i&�HY���R��
����;�q��e�������S'%%%Y�I*]����������?]�l���R�J),,,}922R�g��t�M�6�g�����G�Z�r���_�|����[���z����[o�������'�|R����V|[�l�O<��:���_�ktt�V�X��}HR�^��������d��6l��g���~�k��fVq�������}������N_�;w��=����cG)R���Z�n�����/'&&�]�vV'�]�tI��o�z����O�\�r��111j���N�>m��g������=�I�&&�S�L����3������g�}��}�9NH���c�����������W�{��JLL�j���7�<A�G�&������C����V�����3fh��1���c�m95V���G������W��j��������I{�"���l��mq9S�,�\4�f�o���{E��iv�F�\4�C��4n�X�?�|�rZZ��~�i����:u��������/��~��I�������3�<c�<t�P�����p��I{tt����z���������P�J�������Z�n���F�i��1�7o����_���	}�|��g��'�(..������z�����E]�|Y���V�,PDD��V��a��i���JH0�#x��u��3G
6��'��k�������=d��o�>}����z��G��c�i��e��.7n���M�����n���W��~���L�x�d�s��z���5g�-Y���=�3i���i�7�x��m��	�[�����]�f>_�����0a�����6m�dk�����Z��}���$��9��b���g��A
<X���7[���kZ�t�������K��?���>�������g�$\���W��W��Q�L>�����j��yz���T�lY�_�>'C�g�/_^�7N_�z��Z�h�9s��U@��c��x�	���JKKS�*U��������_���3��c��������M���k��m_�jU�d�9s��Z�j�1c�aB����5m�4�j�J����:i�Y�������+_�|�m���W���5l�0<x�p���(�������������W/����p]gSr��s���(&&&�-00PC��������Y���w��---M��^�zE�y�����L�.9�r��Z4�����G��[_�&�N��kx�jT�30n�8m��E��m�tk�������_�L�2*P�����u����m�����W_�$�e����������~���i��q���/T�B���(&&F��SJJJ�vC��v���_]���O��v��A������._�\��o���~�����`7o��;���>�@�*UR``�.^������Tj�����Y�f����V��o�>}����������%J(44T���������G�*
����������~��'=���������4w�\��;W~~~*]������7n(66V�O�6y����3�h��Q����t+��R�a��i�������F��S�N�$#n��M]�t����J�.���P]�vM�O�Vll���z��n�Y(U��Y��5J�*�?��C�>�hz\7n��g�}��>�L�V�b�������?~\���6��(u���?��g�y&=Y���+z�����{�),,LE�����.^��S�NY]�������>��;wN��uSPP�*T� OOO�>}ZQQQ��j��Y������O������O��Y����J�.m8~0@G��_|��v�����K^^^*]��
(���D�;wN/^�:��R�R%��;W]�tIO"�|�r��_�`A-ZT������Stt�M��3�)9���f��]����z���K�[Qi\ >%U���� �Wlr������
��jB�:��W=5(��whP&T����	����gA��y�d���W��=--MG�Udd�I�^��y5��lU]�����y�T�B����T8p@7n����M���x�
�92��O��-5a��
O�


����U�H����d���G�6m��c��<==�����TA�N))):q���m���7���f�aaa����L���/��.]�7�xC���5[u��Am��Q;v���'�J�,��>BCC�����p��V�������_~�E����������:t��6n����w���'��L}��yyz�6�e��Z�v��w�����c�"##u��Q�H���[�n���U�D	����9��[�j��-:y�$I69�I�&�:u��w!>>^��m��-[L��������[u���������m������I�&)  ��=%%%��s�N�L���U�V���4�h���wk�����o���������|'GS����n���B$�E�#�W.�_�7���Z��V���|A��c�t�/����/��[����Z������r�H,r��j���3f��+f������v��;v�T��V�R�������z�5����5n�8yxxd{?���+�h��}���t����x��
���:u�h��-�����������P��m�a�������m��M;v�Z�n����,�/_��>��#8p@�7�j���7n�8�~��Y�\�~��i��%VUl�������/��R;vT�2elsb��yxx���>��}���W/���d�~�"E��Om��)��z���L������w�l�s��U�j��]���oU�N�L?�^^^j���&M��A���_{5k�L���q�T�R�L����U�6m���?��'����M�>��V�Z�-ZX\���_�{���={l��[UY/^�E��w���]��BCC��T��K/���#z��W���3
		��O>����O���6�������M�4�|�������A^^^j���>��C>|X}���z9qL�3<�Ha�9{��Q�����w���j���0�������/�j�Jy��uaD�q59EV����n^CA��7@�w�apG���:���:���Z���:�����������u��!��
*�U���������LN����}�lN��-���Z�f�<�.���Oe��U���U�`A��#>>^�W�����u�����G%K�T�F�T�T)���.]��U�V����z��U�L5i��!U�RRR�o�>:tHg�����W%�Jt	S���U�L������={�h��=���Vll�����/_>�)SFU�VU�����On����M�6���#�x�����0U�VM�+W�y,Y�l�Z�n����C�����
]�����+**J111���V���U�B��];��DW9q��"##u��]�|Y~~~


U�J�T�vm���l5|�p�1"}���[�?��k����sJLLTHH�*U��&M��U�siii��}{zU��cs��EU�jUU�^�b��;IHH��
t��)�������


R��U�R%U�R%����:�w+W_C�}Wj�yy*��K���%��%��K�^�������CA~����#�{xzz�E��V`�WPP�z�!���(���z��G�������W�n���9����v+gT��6m��r��}��"E�8���,�K�V���]��V������:u��N�:��.�����gNS8����'G�Y38O�����h�����aaa����#�I{�"u�s��t���+/p7?~������/oooFr���E:����{�pH�� 7��o�>���������������p�*Ay�(_�6\���}5��*Ay�������Z�f�$)..N[�n��_~������3`�.\�U!�\��=p��K��]������8}�������m[�������>���@n����^��`>u.��}���6�:uw���k���
tu( � i\lT�*�������%hi���p�	P������ok����Q���C�����{]���~�UV��Vlr���O��o�q��UN
B��?@n���4W��T�7P%(���)���{�S����c��)�9i���JKKK�����n�JP-kPI������$����#:q=�)�@�vu�w���k��=���bbbt��
����p���W�������={�h��-:w��RRR������������4M']t����[�LT�l�2T�
� �,���,�%�((��@�,J�{�$�?�{��M������E�s�q�4yN��;����7o�N�:���pO���,�;w���Gff&��������]�����`����Yf�o�zc��#��J�����vv��tow�K��w��4�I(,���q�m#������I{�������

��K�����>�������J�}��E���/����p��e(�J�}�����[oa���pr�|�1�J�~���/����5�qqq��o���s������k���c����w/
��={�������G�J�C��~�����d����t\��AHV���>�R���F�Z����&v��>��H)*���4�s��b��0h��R�<"""""""""""""""""""""""�g���Q�����U�p��E���|�k����W_EXX��c"##1o�<�]�?��^|�E��MOO���#q���r�������?��]�p��a4k�L�������'"77Wk�J���O#  s���_|A�^��]M����x*�
9
%
�*�%l���'A��}�)p<%S��7�����p�j�+�����������������������������Y�L�gTpp0<h��=���������t��~~~e�����1h� ���[�5�����/�I����D�����E�2U������W/�������}�0f��2	{���h��-���+z\*�
��/������:D%	�;)\,-`g!-7�B"`C3tr�^I���l�s;
���=���Ge���|���;c��u�u����q��]\�x>DBB�,Yu�R�	&����:�����#((H��H$�?>���q��=��� 55?����������0r�H(
��y��!&N��R�>��U+�<y����|�2=z�;w�`��a��k����t~LDUa-�`{_4����������*&����q��������o�>DDD���#�["�`����y�&��?�i���i��e�������>��������>^TT��3g�����w�i�&��;v��O?%�YZZ"00g����������W�}�v���?>rrr��:���A�^�D������~L�2Et|��9(..�i-��r�Y��V
�me�����T,�7aTDDDDDDDDDDDDDDDDDDDDDDDDO/&�=�^~�eu��S�Na��>|8���
2�������5�iL��-��?�����?

�p���E��^{�5�3Fk�f��a����c�/FQQQ����u{��Q�---�m�6��UKcA�v�Z4j�H}����e'�1��e���\--��Y����M���I{��
�i���H��h�����z%���+e��������IKK���mA�h��
��8q�(I122��g�c�l��R�n�=M�4)w������+:�y��
�#2$k9~j�{������X��O5aTDDDDDDDDDDDDDDDDDDDDDDDDO&�Q���{wQ;**���G�Eqq��??�
��H$�8q���/��R������o��f����Q�`kk�n#66V��D�����Z�A.���y7
'�3L���I{T�899���'=zT������k���O����_���w�BCC�m[[[t��U�uJ�U�Te�&2��Nv���G���PSnE (=��q=-��G�NLL�����Rn�k�����&�@�v� ������X$%%��N��aaa��Z��u+w>"Sy��+����|�R��n��Nv�	�""""""""""""""""""""""""z:0i���J��g���5n�Xk���"Q�;h�������r4h�@t���;��>��:��k[����q�'~u���(V`�����+0aTDDDDDDDDDDDDDDDDDDDDDDDD5���Z9}�4����mA���/j����bu����k��k�z��������_����j"S�������j=�PX�Q�"����Q�lL��jC�Tb��y�c/��"<<<��ILL�����^����sj;^�n�*������x"cX��#=����+���a�*V�0*"""""""""""""""""""""""�����=�r�J\�xQ��H$X�dI�c���Em[[[��-=����Z�t���"@.��5Oi���z'������������R����Sn�o��#��
p2#W���yx��lj�����DO;��DD��=���|���`""��>LDd>����
���FDDDDDDO?&�Q�p��|����c3g�D�6m�W�?5����^�����9
�V�u��Y���o���/��AAA������d��	C! ��
������1!���%�D+�3��0��p&"2��DD��=�������`��STT��C """"""3a��]XX�
���b����[c��������---�^�t�\^^�Q�����m-"S��
�rQWQ���U�-vZ9Ce��������������������������j&��Y%''c��HNNVsww��t�@W��]a���#m


���Pk�^������*������"�}�Z�����tA�0���]YYY0`����>����?�����:�agg'j��������J�i��4U����>�y��1B�1���2d����cG4i����BNN������;�����={��a��X$+4�?&w@�~tw0qdDd
������{0��p&"2��DD��}���|�=���c��������L��Gf����W^y�.]R������G��U+��)������w,�������Z��[XX���������4���j��U�X���������jQ�mm��WC��Pj��4:u�m1�������q&"2��DD��=���|���a""��L�t2����ZDD���������[��/ "�� ��{�����Ok��h�",^�X�>u�����~*�����9=
�g"z�H�={���0r�H�/����8p��u���\���bbb����m	p��GGGWiWWW���Rs{lk��D��g��(�H�0aTDDDDDDDDDDDDDDDDDDDDDDDD������J%&L��#G���I�R���/��������������yyyHJJ�k���(Q�����������q�Z�����d��M���(*`���g�4.""""""""""""""""""""""��rss��aC� �
4whDU��=2�J�)S�`����c� `���x��W+5�L&C�
D�n������������iK�+}\�u���;:�CT�pu����i=��T������g��������������������i�R�PT�DA�E�J�T*s�Dft��i���-Zd���J%�q@@���!�j(00P�WDDD�;$z
|��'x����� 2
����{������^t���_�3�[�n�{�������/z�������/���@��S������SRpp0���E���s���r�#����qAja1>��x>�X����H�F�o-7qtDDDDDDDDDDDDDDDDD�4��-Btr>�����S�"��z2�G[��,P��5j����DDDD5]PP��]k�0������$���_f3]�t)�O�^��_z�%Q���:�-����_������U����������:9998���-B�����i���V=W��
�1��C$�0*"""""""""""""""""����
���T�I���\$e���H�BRf!�������s+�iZf$""],Z�*�J��
�DdJ���x��7�T*���f������GF���_���?�7o���g��(�vw��i���U8N�Ra����c�.w�+��"j�����={����n�o����:�%�A�������Ox^!�]CV����QMTP�D�������,�>,<%����#�A
��F�������e����y�&���S�N5sDD���=2�
6`��9�c��O���K
����3��n�T*,Z���q[�lADD�������}��;��7�� �����q���r����c��e�co��f��U7� �+����RKk���<�G���FDDDDDDDDDDDDDDDDD�e��dH
�S��4OtJ>N�� #W��?""""2�[�n��/�P���[{{{3FDdL�#���k�y����'������Z�x1$����?��#~��'��o���>�@tl������,w����c����vaa!^�udffj��R�0s�L<x�@}���o��F��UW�����������1�N$*�	##""""""""""""""""�� #�gn�!�@����8s+��{DDDD5�R���o����B���CEE���&������s���+s�����v~~>���O�sxzz�i��e�����x����T��G�s�=�Q�F�����+N'''�k���>M�6��I��q�F��������;x������(**���;����#==]��e��x���u����?��#G���F�=�f����������D��-[�L��ZD���T��-|1�j(n�h����I��^4���+�NIDDDDDDDDDDDDDDDDD���"%����"�a?�H���w�����2���D�T�������+++����{��pqq1�:����y�&������4���nnn������
�VU$&&����x��!���Q\\gggxxx�S�N���������r�
"""���	�R	��������7���]�������s����DH�R����i��h���3��=�J�����{III������
<<<��I�h�R���aj�������#..���P*�pttD�
��U+����;D�p��E$&&"99����h��1Z�n
GGGs�ht)))������T��];vD���+�. 66� �������RL����u�������8;;����;w���c���CHH������
+++����I�&h��U��y*RTT���7o�Dzz:j���z���g���\�������K�������4888�����u��}���SZ�f
.^��U���[g�����I{��q��!22��~			�����s���:�n�Z����gQ\\,:v��]����z���gO�>}��~�W���+Wp��%��������|�r���B.�#,,����q�k���}�`a����a������1v�X��%�����W�^puuE���������h��'����#F��i���Af��Z5��W *�Pc�q)p���<�:&�����������������������,�U�+-�H���,th�`��k*�B���Wc������-s^*�b��aX�b|||*����W�{�n?~��_/�������0c�L�<������-�l���X�x��q�N�a's�={{����'p���r�n��f���q������'������W�������J�h��%��������Y����;�%K�����(((�����
S�N����aoo�u�������e������&�-\��-�)^S������Kq��A$&&j������b��������x^^<==�AW�s�����j�J�����:1E�R�={��������P(4�m����q�0q�D�$-Z�H�Z��������7o��
p��
��{�T���;#00c�����M��6����'�����X�`:��VR�6m��7��K�.e��:u
}�.\�P�� x������_�~��:������G����8y�$������J�������W��|����8q��s���Z�y{{#""���������_���~��G������E�~�0y�d0@������X�k��Ajjj��R�������+�X^XX����7n����5����������+��5���)�������_|�<==��q��D��acc�?���{�/,,Tg��N�������'��qc��=z4v��Y�����$\�|�=*���|��k���Qu�.�aO�p���k#����?���������������������V���|������4�IL����Tt���g����<N���oZ�j�S�N����u���m[�X���]+7ax�f�3f�}��

�{���={6z���u��U��7n�@`` z��UnXI6lF�Yar���_�z.��+W*������#G������c��&��+	~��gh��1���u��!��+00����T*,^��5��
*�Y���a�����������5&L��ngdd`��}z��i�&Q{��)���{�.Z�n��c����Z�������+�5k����|��y4n���MCHHH��{�B�s��a�����w�	�4�C��m����o���=�qRs��=q��A�����O�>���?����S�N:�Y����c�����kW�	{���������W/L�>�L�S��a|}}�b��r�����/���A��T�����t��,���<�{��A���q��U������s�a���Z���?�K�.a���x��W���S������z�.i������t��o�����&2&��S���'N������a�r�}��G�q�Z�hQ������7ob�����dZ�����O���_~�L������?����T��dAh,��k�E�������������������
�c+~�zMZ�����B���$:.|||��}{Qe���L<w���k������������G����m[��W�L���o�{��:'�U��8�����It��	�[�F�:u��9{�,z������
��4iR���q��6m��s��h��\]]��?11={���HV�n]�k��[�.S}->>8{���kVwEEE9r$-ZT&a���
4@����Y38::V8���SE��	x�����;�m{{{�=Zk�S�N�K�.�q�F�s���h��%��o???H$��-��w�F�^�4&N��Sm��A��mu�WS�;w#G�T�
VVVh��	��o_�5^TT��������e��a��E�dG�l��[�����hl||<�
����
c���yzz�y�����3Z�h���h����
L
m���x������J����E���E�J��O����o���v��������o����C.���'''��W^Aff�N�9r�z�Bxx���������s����z�����[���$c�S�e���8y�$@&�a��M�����~����RQ���X�h���^K$L�<�'O��7p�����A�P�����7G�N��M�����v������g�������+++��_��u����Q�����Z�aL�C(5Z���Qp�Y��K-GGDDDDDDDDDDDDDDDDD���[����!%�����e�l�Ev����|���-�M����g��i����|�rl��YYYx��w�^K.�c���x�����gO��:)))��o>��3u����xL�<��8��'��_�|�>��k�������U+�����1|�p4]�v����;v`��eHOO��us��-��Ypp�(a����g����S���]�BB��9�#G�TX�M�Tb��������+����������C�����X�`�:1"77c����k����"�{��UHKK���O}�e��X�j�������������������n�����/�[[[����P=z;w��X}�i�����;��9�q����w��s���������qq��1<�W_}U�_.�c���x��7��iSQ���l�?�����]�t�����������$k�����gc����D`�qe���{��-���������Bxzzb���1blll<��v��	L�<QQQ�?��#��9�1�C����/�T
�qu�-[�����SW��}�6��_������0����c��8p ��o�Z����U�T�q���_��7��;���x���1t��2s�������/�������v��www��X[[k<�v��2����,X�W^y�L���G������~R�k��5k���`aa���z3g�D�
��srr�~�z��7O��%K�`�����}��-�5J����{w|���������������{�n��?			��� ���{����4�o�{�����a������9s��Y33FDd��_$��k��E�+���V�Z8p���!���:�a}So�y3J
��U�������::�i�ADDDDDDDDDDDDDDDDD��T��W���=�_q�2C
K�E�:��e��Z.���Uc.\���7��� `���?~|�����X�~=��k�)S��]b���0a�����������z�F�B�~��	h������$)@��}�L�"???�9]M�8K�.-��R���>��C�=ZTAi��MX�p!���5�+�$�q�FL�8Q�:���>|8�����
J�����_~�S�N���:u����5^s�D�n������1c��[�q"���~Z&Q�]�v�trr������5k�������X�z���t
6��30c����_����[��=��������6o�,jO�<Yk��c���%����~��w��y���C�~���_?|���D0S*((���#E	{M�6�������&��y4x�`<+V�(SU�&������?N�<	OOO�9A���8q-[�T'�<x��_�R������k��2Eh�r9�~�mX[[�������������]�vU'j"Z�l�o��C���/���o��e������Nr.�H��u+��Y��7o��`�����cG��wO��W�&M��I�p���2I}����A.������okk�Y�f���Ct��u+>��s�����1z�hQ�����1�|�U����1y�d8�z�RW\\�~=�L��6m��c�{�����;�D�F���O>1o@D&��=""2���X�\=�����yJ^��_�4D;���ADDDDDDDDDDDDDDDDD��W���k���d���`�D�'���
[+�	��v�Z�T*u{��i�J�<y2����$UD�*9NNN������s���
�n��+V�5���%�i����M�6������{�n������������J����~WRnn�����S�������'$	��Y�K�.����-[�`���ptt�9��j�������c���XZ�>}4��W1c�$'?�/�o��/�������w��=���?�v�����}{�}�?������r���������+����m�DI�...���?5V������H���L&���{�$����qcL�8���(
<x�
6��m��&������e�����{W���+�zw��]����_?��=��9�����%Q���K�U�������={�&����^�l��
��7_�5.^�HLL������sg�������7o��S�N��*����?��3Z�n����Z��L"$`�{�����������a�Q5B���n����q�'~�� �(V`��0D��0*"""""""""""""""""�gCzz:<�n[YY�Ip�f���&'B�F���cGu���5�����OQ�Lyq���$�HtN@���������n/Z�H��-�T�y����������?�6[�n�J�Rm����k��������7�dn�\���@u;99Y�z�F�*{�+��3G��=s*��+tN�{�1-[����+��R����saccS�8A���z��~A��tB�1����8���W��H$��e��������0m�4���5J��r����%_666���/t��E�<x��}��!(�2��uOy�{�)))�*�'ND�^���Qu��=""2�i���V=W����0��C$i�CDDDDDDDDDDDDDDDDDD�;�<

��P�A�������ZaE"C���Uo�DC���Q_^�%�meff���#Y���~Soaa���G�5�O�>�d�3g�$.s:~���=a��V�2e
AP�7m�Tn���"l��]������q���=}���maa��zcu�;w���...Z��b��:�k����-�
������QQQ����{1`������%�
0�52�z��
+��aI�[��=z��_JJ
������^z	NNNz������������)�0s�L$&&����r�J3GDdZL�#""�xb���_B��
1�z���~:UN�d�k���KJHH��_�q���E�pww���5A(���O?�������
[DDV�X�#F�I�&puu�\.�g��n���Z������=n�8�Z�
�����S�R���s�v���Q�V-����������]2���*�xh�D�F��w������'����C��	)��d.�}/]�$z��i����J_���{C.��)���]�v:�+��'����Uzlff�n�������>������ggg�d�2{\��cy�\U��[Z���u����&jgddh�w��Y�T�J��D���EmM��1�)�p��1���C�^�z��$@��`��D���>��h����<�G�Bi���������������������^����v�*O)]�I���x��7����w�}�v����7������|��0E"Bdd$�???|�����?������dV)�#F�i���vvv6>��������X�l��=���'A������o���XX�WRR�z����T>�+�4S���zK��J�������-]�o���Z��"vc��q����N�lll*5N�X]����9�V�Z�S�N���/p��1���#--
����7�^l��Q�D���������u��9s���'4H4��}��S�����/��"��k�����I{DD5�J��RY�"Je����#�D��f>��`�����lL�	E5,DDDDDDDDDDDDDDDDDD5A������*�o���M�6����P(�[RAAA���"((�Z���C�*�����d2�9�2cN�8�y���{��pttD�^��f�$$$��^JJJ��,���Q5I�AP�vm��1x�`Q��[�jLx�������n7i���u�:o��}������mLVVV&���k��
���'BBB*��1�bS?��q�M�/��bjs��ETT��	��}���#"2s@DD�$!;����QP����_�%9�rwXYy���9���������lo��!WCq'G��9M�������]�`�������������������~�r	��6���.�f 5��d�9��������+�Zn�z����v�JM)]m�<���8p ���E�5j��={���^^^���������a_~�%�?�Wl�������I�h��%�w���
����������9k�,�`���p���Y��~�-bbb��)((����q��i|����:u*�,Y{{�2}�Q�J�T|NS���Rocc����9�L�7�xK�.�������<x�����/���U��������"6�������Sx���E�fx�����S'x{{���
VVV��������3I�O��������)�.J�[�x1|||��1i�����	CZZ0�������RY���(��E!--VV^pr�[[?FZ1�v�j���<@T��O��K���c��������������������~A����l���%3i�^�Z�f}��T:�.77W��999:�]�~=����n���c���x��+�����WU,Y�DT�Q�F��c:v�X�X}�mll��Ga���8w�N�<���O��������-,,��_�������)Su���M�6���k���4kk�*�����������[�T%qo���X�l�:�f��M��=�B�~�A�����0aB���T:�����q?Kf��%J�4h��_��u��;��UNK��<2F�Lc*�/��9�
���~~���m�{�)edd����g�������g��m��m�����`��I"cb�Q5�P�!)�$����=6??qq1��{��� �V�?���2�i��\}����%�`md\dRL����DDDDDDDDDDDDDDDDDO����p?V�����W��dkU7����vrr�^�K&�Ud���������K������WU���G����~���r�$J�l����wG����p�B���K�����k�.�������w�������Ds�NfQ�T���o��y�8;;���T*����������^x���������V'A=i?1t�P���T{I�����8jj�����������v���q��XZZV8��{���QM��Vz_�S��I�eC�S��<�[�����

���R	{%eg�ET�v$(2����cWK?�K��z��b��� """""""""""""""""�s����^f��\�e�e����(��v��M�������O�T"88X�n����	{p��-������(�����/����	{yyy7H2�]�t����q��}|��7��p����;wDc<<<D��"##QTd����U�F�D�K�.m��S���W(��e���i�&Q�)S�T8�)c7����������I�tJ�L�O�����W�.�,gJ����y0i���((HBL�^(9�O��AL��j������Z�A.���y7
�d�0*"""""""""""""""""2����O�:�U�D����[����OIIAqq����������GLL���K&"����*!!A��'�3g�%IN���;;v�����gEm�L�n��������x����)��\cS�����m�jR/�������-[�@�T"..G�Uo��!*��m�����Q��^����x��l�����'QPP`�h����s'O��k�����|�K�^�Dm}��1�zO1��
���z���k�y���/:��!3="��c���)y��=����(���=�"���VUW';�o���T�&�Gp�a�������������������<����be�5��X��In�5���]��*,=z���:�MLL�9��t�Faa��1~���:�[[q"fnn��cM��J&�@rrr�>/�������_-���Y�klj����?����t��%�J1i�$u;22�����[EI��&M%=j#����Ou������3C���D�-���������QI���


D�#uQ���O�>������c������77///4o�\�~��!�;f�����=�T�����o_��JW��S���|��=����*�I{DDf��t�`�JS(r��t�(sW�WG�|����yJ����Nv�J8$""""""""""""""""��k�c+�q��j%�����Q��I1t�Pu;??.�i���s�����(�����$&m�]��w��������XQ[��C�����+��N�prr*�g��IpttT����/��fH%�sDD�Q�0��m�����W�3331m�4��7y�dH�Ru{�����y��-����|3f��W�X�7nT9Nc+��9sg�h����s���/S��"U�����1z�hu[�T��7��R��+s�={��=s�Lddd�)���rO!"�c�����!;��Q�������0��Qc���c�:Z�g+0�z��XB������������������i �I���#d��+R�C&���#�FJ�if��!����7�TXk����D��H�Rt��I������U��������H�u���vvv��_����4����_^^^�vpp0���S���� �?^�������[��iiie�w�v���spp��~�n+�J�3��+���/c��Q��i�������d�>}Z�5 00� ���If����E��]�va���e*�i��_�����^z�%u������=�/��2���u��O�>�����]PP�_|Q�����T\�vM�����^C�
����������:������{�}����k�������Z��
6`���z�Ur�'�c��y�����{���=��W���KfO�7n��:��@ll��sa��mX�|��5�qOy�T{51i���������u�5�������||aF_CR�~�ICDDDDDDDDDDDDDDDDD������9����L�����`#3�|O�.]���7�T�U*^{�5����x����oDD�~�mL�2�����:&L�����>���������X�j��o���(����H$�����������;c���8t����O�W����qN�0_|�233E������'��G�HKK����������@��M�p�B�?���e����a��}���"##��[�j�:h�{��98p������!C�`��a8y���d���|a���h����o��{������/j:s����}�p��q�5.��f}������/:�v�Z�k�@NNN�1���X�v-��o��}������S���<y�^s��;D�bcc��cG��=w��-�?'''N���)S����_~�E�5����{��%\��}��7��%KD��'���q��!�;~~~8��)C~f4l�]�tQ������G����L����c��Qx����R���I��
�L���v��m6l�l��c�����s�����i�2�����C�f��m�6�	������y3z���:���m,R�?��3����?����c�������q			���_1u�Txyy!00w�������"2-����1$!??�$k����� rym���+A���'R���7^�/�ayw=?�i{��>DDDDDDDDDDDDDDDDDTs8�����B"���_�y��X���=+�i�j�*\�|W�^�8q������u����$''#<<\=����~��(A�<'N�w�}����R��j�*�^��5���#RRR�B�7o�<��n���{8|��������1w�\�}O�:���u��>��?���VXX��>�,���?lmm������Q�������s'"""t����;���O����B*��n��pvv���%���V�����
�l��uN�D�]�va��!��w*�
���!�����
'''���#==����k��	&`��%HNN�8�J[��b��Ez�oh��-��G�D��W�^����
KKKx{{���999���Fzzz��z�����S��P�~�2����_�>8�!C���������+�r�J����N�:���DJJ
"""�T*+���k���o��	������O��'�������IIIx������jV�\�������#G����5�D"Att4�clmm�s�N�m�V�u�����k����'{Qi��������#,,�W�V{��!!�J���
 ..III:�g*���8x� ^}�UuaZZ�z��]�6<<<`kk���L$''W�q��BD���R���$;��e����~�Ju ����~.���	��C��p�+��G'U�\&A�F���{���������90aO�Z�j����h�����J�BXX���E	{�j��������$��p��!4j�Ht\�T���{�x�"BCCE�c���>>��s�O��=�v�ZQ�']9;;����pww/..��[����pur�D"�W_}U�
j%)
DFF�����x�"���W&������g�I38q���}XX�k������x�"�_����H�	{���+w
ggg����pss������v���O>�������<���q���*%�����o��&$���A={���s�4��q��u#,,�Z$�=1r�H�����[�n�s111�r�
._����(&��P��]�i��2����l\�z�/_%�999��_E�6m�^k��5���_��������7����Ft\�P��Q!!!�2a��^�z!88XcE���d��y/^��;w4>A*��K2�=��L���I~~�S��>d�������>���1�N$�#���������������������$G�f�����=m��`	�T��I�:X���-��tA�f��p��)���v��8�<�/_�:u�h�#�J1|�p\�~]T�NW���Gpp0�O�+++��:w��?���V�� Z�������p��,X��{����'lllt��M�6�|�2���T��� ���.\����{O������b�
��������D��
��g����{����NkXXX`��U�w��L��Sr����L������T1�G��{�.��[��_~�������tb��	���>�w��A`` ������I�&!((H��&N�(jK�R���z�SR��Mq��
|���h��M��e�T��]���o���Y���nU=���x��V�Z�r�ZZZ�o�����1f�E�lz�����?��G�Z�XYY��7���[�*��������������o�u��pvv�;���w���������I�.���c���_��J�m
4@PP>���{������R�]�t���~���P|��g����BD�!���N���u��7o�n��y��53cD������S���^�z�V-��j*�J���o�T�lM�D_�w*���QT�!WCq''_k��u\���j�8�j�ge&"�����`""��LDd^������{0������*..��D�5jT����@�R�X��R	H$��D����H�T������>!����������v��Y#;;g��Ahh(222`mm�z���s���_��A�0���T���?���DVVlmm�����]����B���;w������ ++��D///�n����U^G�R���[�u��������\����i�������:5�B�@PP>|���$������^^^h���{��J�%'O�D�>}��A���_5T�����?			HII��������Q#�n����Ds���Dpp0����\ggg����u��:%U��E��x�bu���EDD���s���CAA�����]���nW�T*\�vM]���������M��y��Z�����\\�p�=BJJ
���`gg���k���M�4���`�{
����C=}��*U�I�@�,�JUA(�S��Af�����+�_������XZ`���O~"""""""""""""""""��M��������k�D�=z�[������0`���o(���2d����J�h���(i�A0�:5��*V��4�y�fQ{���_������Mc����������|||�UE����6m��M�6��Jlll��wo��i�{
G��ULD��S��fZWa�u��.�aO�p���W�62%�0*"""""""""""""""""""z%''�������
d������&`���y�_A�=�k#���~��j�NBc�?>��Q��f��5(((P��N�
��	����&��� XB"��tM�DA��t��hao�m-� �Z����?S2M=+�������J�������S��L�'"2A ��#//�dk����	p�QW';�o��7oF@��|�
�|3{[7D[��GDDDDDDDDDDDDDDDDDDDO���|�={����+W�`��u���S��>}:����"� L�#"2++�&�YYy�l-C���������G��)U�_�4D;kGGDDDDDDDDDDDDDDDDDDDO���x���O�y,X���QM&1wDD�*;;���I�3���.�������
�����FEDDDDDDDDDDDDDDDDDDD�777>|��������j&���\�
++/��ee����I�2�����V=W����0�z�
�L=�lll��ys��;7o�D�-�� ����Y���qq1F_��U��A,h����b��O��',������6
ao!5q�DDDDDDDDDDDDDDDDDDDTS���@�R�;"""zJ�������$�.5�rs}c�����~.���	��C��p�+�&����������������������Li��EP�T�/""���I{DDf���R��Q�P*{YYw���)�$64�A'���\z6��������1i�����Rkxz�D"7�J
$$����K5��Dl�lo��&�VZ�M�����k�c%""""""""""""""""""""""���I{DD��\�
/��F��))� 9�4T*���2&�v�j��V�Z���K���xFE5�J�B�B�|��
%�;�����������������������`,�=&���~�	HJ:���������1��B��Fh���q���pw����
��2�i�/_y���b�}�D&�Ef���\MU7�E��CR~!R
�P��/Q�R"�E.���%����$��1R""""""""""""""""""""""��jn��SH*����@��<���`����<���NN`k��J��������?'�bcsQ��+�J�
�Y����S+?��,�����Cc�$�b��������QN>n�f#!�Pk�B�
qy���+DHZ6��,����l�L)=
��GDT
�������������x$@�,P��H����ae�;�� ��V�	\]����RS�j]'??��{��92Y-�>&cjao�m-�0&�!
JTO+i��(8�,����>N�O�B������{lB~!bS�go�N���J�!=���GDT����!�?P�TP���R) R�� h+��;������h�BWT�������9r��1�Itu�����x�f��GZ�&����
�������i��DL
r�T_�UXV�s����r���#"""""""""""""""""""""������ @"��Tj
�������j�j
O���	G
E���"77�P���WG�����|�R��!a�S��kTs��Xtr����U(q,:�E�������������������������nL�#"z��x�n�Q�J�W�S�
{���M����t��~u���(V`��0D��0*2�|�'bRP�Tt�B�
'bR�o�D@""""""""""""""""""""""zz1i���!���n�1������Db��HM
�Je��'S�^�
o�s�z>�����!�����63Va��\��2�27==��GD���j�n�Q���*�_j�Y$%��JU3��	��
<1��Ik�������b�	##cz�����<�����G9�F]�����������������������j6&�=c�Rkxz�
[�F��������#P*kf5:� �+����RKk���<�G��*��i�H�6�:i�Y�����������������������j&&�=�$xx��C�r���<DL�~(��^f,2��
�|���Vk�s���v'
�������!!��$k%�"��f&���1i���%�����+(�Ct�O(*J7M`f#�`{_4�����hR>�
�j��,�&���x=""""""""""""""""""""""�9��GD�NN���>�Tk���tDG�F~~���3 �v�j�zV�Z���K������H2Q��'�M��L�#""��?O�a�H�Z�(�������0Ff8�r��j��2�}�D&`��$FE��R��RPd�5��X������������������������4b�ll���k,,���Q��w��7L������S+?�K���������TFEUU�T�Pi��B�
�L�#""""""""""""""""""""""
��GDDjrym��;������Bb�	���[#+��������K�}f���_)�&���B	�<5��ODDDDDDDDDDDDDDDDDDDDDD���=""������(X[�+�_Z�$&�J�0Qd������zk�	��I7���c���r$���iLR�<�Q���=""*C*���s(�������uqq��T�(2���������*�	���<FE�!��,�r�1XJX0i�����������������������4`�i$pwG�������@L�>���tc=]��_��3�s=Qy&���%\�2��Y[.���=""""""""""""""""z�DDD@�W``��C""=�|���w��E���O�6I��T�1���ix>�����Q�%j��{$'����� �����9��N&�����wCrQ16<J�x>������P��p�4mb����qy���X���dk=
������p���C�T���u��E����a���I{DDT!G�6���EB�1�T
�}��3���kkOGXy� `aO�c_|��>ayw=?�i{��#$]��[#$-�d���[�l-""""""""""""""""""""�����X�nN�>
�J��_�6m��[o��7���S��f��;""�����s8$��>Je>bc�!;;���U�D��}�s���OHv&�G�Bi��HW�r�MT����NrV]$"""""""""""""""2�
��rR�[����w��i���Z�h��Cz*����������@�^a���HII��A��������S�&����W1u�Tt����5�=�D�1����tfm���u� 6���35�Q���?W��pphe�+O&����\��9��M���;����RA0q�T��vH�M5�:NvF_�������������������p�����]���;g��ix�Z����+J""""�Qff&����+W��9����z��A��� >>^t���������9ELdX��GDDz��tF���!����K������|��OC�Nl�lo��&�VZ�M�����5�q=+��Z�����k��[�^9�""""""""""""""""���?�-���g���'����?>�]����7G�DDO�E�A�R��Xa�����>*����+����+HLL����q��%�������7n��ott4�L�b����I{DD�7;xy����w��������;T*��"�:�v�j�zV�Z�������Z���trs���8���H%���`�������������������9����7�]#����/�k�����Q��������������8t���iS��&M�c�|�����'N������+��0i���*E"������7-�_V����RY`����].��V
P[f�����lz�d��HVR	�y��R"t^K��~^.�2RB �3%����z7�Wm����p�0q�A����P(�+������+WV8���?F�&MD��9b���L��<'"�J)��^��S�r���E!:z���MY�����S+?����5?4?�����g���6X�=A�����,�d>"""""""""""""""�gZ�M`�  +�0�e�?d�Q5r��=Q��^���M��$	�*:j���LE{	!"""��n���GR�_T�&#:�'xz����i����6���cC�P����f�����}\j�8:*��\���n8��\��Js�T�[���������������������
���v��t`�����6����)�T*�������������������{w����\����y�&������4���nnn������
�VU$&&����x��!���Q\\gggxxx�S�N���������r�
"""���	�R	��������7���]�������s����DH�R����i��h��-�g�=O*�
!!!�{�.������xxx�I�&h���R����*==���G\\����T*����
�U�Vpss3w�%$$����HLLDrr2$	��qc�n�������RRR����"&&����]�6:v����[W8644.\@ll,A���'���U�����q��-DEE!##pvv���7:w�\���������$''#55VVVpuuE�&M��U+XZZVi���"�����y�&���Q�V-��W={�����ACTT.]�������������[��+���Cj��0J�z�t[�~}Q;==�!������ Z�����G�Rk�S\������Sg0����8����d��M����hJ�*V�n�co����`k��H;	�e�������������������������������l�U�+-+86xu�q���
V�^���W#66��y�T�a��a�������W�^����q��q\�~*��H???��1�'O���u��jK:[�x1/^�u��S� :�R�p��Y���'N�(S���-Z`��Y7n,,�{���}��z�j�?��~R�-[���!C0}�t8;��pz��9,Y�'O�DAA��>nnn�:u*f��
{{{�s����.s����.7�o���X�h�N��BTT�.]��"11Qk?'''8S�NE������������N
qpp@\\\����BBB��U+u�c���x�b�c�J%��������B���O�i�������
�d�h�"�kI�kG���Bl��6l��7����R):w����@�;V�*[�Q�����{��],X��Baaa�qm���7�|�.]��9w��)|��G�p�B�s� ���_��_]&yI���|=z���'���T*E�>}0o��
�[�n���5�����:���������/��?��=z�����-������'c��z%%`��X�fM�$2���>|8�/_^�����B|��w��q#n����� h������W^yE���}O1&Q;//O������]� 1�����������F@"����RY������}���U�WG�����yJ����N���L��E��C����d��`���cmY��aYyH-(2t�DDDDDDDDDDDDDDDD���7�w���CW����+f���1ax���o�>�j�
�N��{�u���m��X�b�]�Vn����a��h��=BCC�^��f���=z`��u&���7�^�z��VRAA�
��#GV�\<��W�^���q���
����`���x���q��1�	{��J��}�7n���`��7���@���
4�z*�
�/F�F��a��
Viii��s'z��!:nmm�	&����o���l��I��2eJ��������[c����p����=��c�r�
f����k���!�?�7��i�R��^�P���s�<y2���k�(����Ch��-����1ax����gO<xPt|���������=�����������N{<���>|8v��Un����r��q�����OGq��b��a����b���&����_~��
Bdd��k����s��X�`���=�����g��o��W���.^����{3g����<�y^�t	��+������
�6�=�T{u�J�������D��;"$"�c�=""2(+�:�[w4����(CK/��E��ptlk��*k��R���$L�'}e+0�z�m���rGG��eiN���J0��
J
�
RA������Af.�&�kw%%}=]�0������sn-����U�eee����|���� ���F���������������c��=z����_����=<==������b$%%�I��}�6�w��������M�W	��trr���j�����$$$ .N����g��w�������I��$����yyyA.�#++���HJJ�+���D8������www(
DFF"--M}.>>���?������fuWTT��c�b���������W�\\\������u=m�N��������M�D�|�����;�m{{{�=Zk�S�Na��a�ruuE�:u`ii���TDDD@�T��1�������F�������dDEE�!B�8w�F��N�������/lmm)z�a����v�5j�e���*U:88����������V������a�p��5�d�rc���yzz���vvv���ATT22������o����-[�T�RT���35&�J�R��_�k�F~~>�����/�HOOG��}q��]�1///��S���x����y����W^y�n�B�Z�*����#5jT��p���������233*J�<r�z������VVVZ�7�=�T^z�%�������;����k�<YRhh(~��gu���
c��5j�D��J{DDdp��N������~������w���T]L�����\���/,���aH*dE6s�W(�����|��!�H �H`%�B&��K�7�������4x�S��<��NEDDDDDDDDDDDDDDDDZ$���5�Z�����n��g�%x	�����#""���Fxx8���0u�T���y������9r$�o����Hdff�����x�"._����($''��������z\||<&O��u�'N���X�r���k���>���U�V���������~���"55�o���p��U���"::��-����z��[�0w��r�App�(a������CDDp���?7o�Dbb"����o�>L�0��d@�R���G�~�������/�G����K�z�*������O���b��1HII)3��U������-[�{��If3�9s��I�k��5~��g���"44/^���7����`��5�������6m������g��%�Td�����1c����Vc���������r��f���[��������#88>DFF�?�)S����N��-88����(��V�Z�������X\�r�/_Fdd$RSS��/�`������4[��0~�x���[�nEJJ
n�����`$$$��?�@�����sss��G���s����:t������\�~]����o!��W<����X�~�Nq��_�f��_����������8�<BBB������������T*U����4&��/��~����_tn��Z���;wj�o���e�����u�V$%%!,,AAA		Abb"����i�&����Y�f��������������h���HII���+E�����X�dI�s��u�L�^�������"##C}�s�RSS�q�F�������� ���{Z�7�=����G�������V��s�(�^�����$���Xi�������^^#�+rs���KO����l���A���%A���'R���/>Mc����	���
ag!����/"+�RA}���A"�s���8�?���YP�R��GDDDDDDDDDDDDDDDT#(�������i���=��]���D-/@j��A]�p7nT�A����1~��2}}}}�~�z�k�S�LQW����0a��
�L������z�F�B�~��	h�������i�2c����q�BI~~~�s��8q"�.]Za�$///|���=z4z�������}��i.\ggg�����'jo��'N�����;���������*����_~�S�N���:u����5^s�D�n������1c��[�q"���~Z&Q�]�v�trr������5k�������X�z5$�5m6l�3f`������4�y���p��u{��MX�j�N1m��Y�./!u���������������E�������_?���_|��Y*��*����w��WO�'''<���+D�j�����������dd������8q-[�T'9<x��_�R������k��2���r9�~�mX[[���������WnL�}��v�*J�+M�l��~�-���_~Y��e�0t��2c����:u��(��u��r�*�����={�������c�Q�bI�����I�0i�$\�|NNN:��\�`���e����b��Y�����n���?�\ke���b�=Z���x�b��?_�{K���1y�d8�z��������)S��M�2c�yO1��s����[��k ..]�t��A���x{{C�������8p����D�g��e�����zgGQ�&��P��`$%����Z�eg�Cqq��yR��R���D��}�)�gJ��>!Yy��-�`%eQ[s���x�^&Emy�%���Z��\������[�z���yJDDDDDDDDDDDDDDD$��mi�(L'x��/s�8y�g��o���P�����i��iL�+i���

*�xT�f�������	?���{�9uR���[�b�
������4m����i�&u�Z^^v��������������U����E����\���S�~��7���OH$�Y��.]��[�l����EUk�����c��-��X�>}�h<����b��HNNl��_|�E�U�������G�n��5��o������q��yu[.����W���s�?c��m�(�������:��"^^^F��<d2���[&a����c����*y
�<@��
�m�6�Ia����c��e�w��������+�z����~��a�������<���-��P�.]*J�z����g��������/[�Lc�^I�����_��/q��et��Yc������������S�`��
c�����?����[���V�*�	��b�;v�@��]�x�b$%%A�P����8|���q��u�������D53	����AW��pv�Zn���h���AQQ��"�<�D��f>����t=�M���;�P���{#c�)V >�P�9_;�
��	��v������L�jU���8x���meeU&�I��K�V��d�5B��������kVF�>}D	2��Y���D"�9�"��oGjj���h�"���R)����nggg��?�0H\�l��*�J��u�V��$Jz����7�|c���r9����d��I}����8g�����t�+V��9a�i4b��lYq2�+��R����saccS�8A���z��~A��tB�1����8���W��H$��e��������0m�4���5J��r����%_666���/t��E�<x��}��!(�2��uOy�{uI� `��i�r�
^z��
�w��
�f�B�^���)0i����N8;w��[��
S�I���l�lk��&�T\;��������ebY�������Nsx���i��? S��V�#""""""""""""""""2�������@�4h��I^���V$2___���HD1����Y��Vff&�9b����7��=z�^����#J�8s��A�2������&L0h��)S��>~��M��/**�����m�7Nk���O��Z�7V'����s��������1>+F��S������� `��a:�-���[pz(�������/Q�����Q#��7l��r����ukQ���G���� ((H�~�������W\���W��������b.999x�����qc�����?w��
�f������TL�#""��U�9��
A��K�B����=��5���(��O�����O��16���M�iI�s����\�?��my��R��d2&U3%�	   @����/)!!_�5���-Z���������O?�����+�*dlX�bF��&M����r�\c�%+�%''k��_�~���q��j�*���W:N�J�s�����7F�Z�������-\\\����W5U��CC'�6j��{�V�O�<���0��:���Du{��ppp�����K��z�6m���a�����5���7�r������k�S���?�q���I^��fff��>��#8~~~pvv�L&+����9���U��_���o�^��nnn�vFF��~g����g�'���/jk���qO1���X�o��W�V�������oq��]dgg#77>���[E���w��{�����_�=Q�1i���L���^^#!�j/��T"6�����x�e���j�,��Y��M�����Afa1��4������V����\I1�H����z�GDDDDDDDDDDDDDDDDdL����v�*O)]�I���x��7����w�}�v����7������|��0E"Bdd$�???|�����?������dV)�#F�i���vvv6>��������X�l��=���'A������o���XX�WR��]+9_M���CQ�2I3y������T*l��Yk����&O����)b7���1�������F�^Y]�i�Kr��3g��U+t��	_|��;���p������������M�<*��W[[[Q[��.�`7g����A�����/��b������?����>6i�$����������?lmmamm
???��������_\\�1c�<I��lb�����;�����OQ"!����D�JQ����S+?�I��V���������]x��?J���K���.�������b�R�9�������������������t�E�JM�������M���P(z�-�����cu�V�Z���C�~?Zy�}2�G�����1'N���y���{w8::�W�^X�f
�]/%%�Rq�G[����d�� �]����<x�����[5&<EFF��?�T��4i�n��i��tr�>IE�TS�6&++��5@�{��
��gO���Tz
c���~�Z�j_6�=��/_�[�n���{���
`ii�u� ������k������c��YF���X��"""2"��u��F\�!���j���r��Y�]��������������_�g�����}\j�8�gGx�����rjY��k���
k�����zy
%����������T-/`F���_e&�.�n�z��aM�^I���������-j���T�����SXX��"::Zt�Q�F���'���������#�}|��_~�����[e���`���e#Z�l�����a��������5���Dq��5K�???\�rk�����~����2}


p��i�>}~�!�N��%K�����{��Q�J�|HyVV��{H$�_�L&�o���K����p��Q<X�����]����������@WM��Yr��)�����d3<������������+++��r��~���$���yd�}���SS(X�n���������d����S}}~��w<z����3x�D���=""2�����"!�rrB�����������D"3a����d��M����h��XL��}�������E�I+(BZ�������W�{�����r�����������Se��������������������������f��=�n�}�fT:�.7���U�'''G����������mwwwl��/��b�c���{����%K���#5j�;v�@��+�o����
>��#��;������'q��i\�xyy�$/,,��_�������)Su���M�6���k���4k���������GZZ���o�Ri�����'c��e���M�6���
~��u[.�c��	�^R�$������,�5k�(ao��AX�~=���[�8cW9-I����2����<s�L4�Js��������)����du�v������������V�Z����W?<{�,��c�X���I{DDdV�/!9�422�i�������Q��`H���?�:b�=�����yJ������
��m�}5Qx��*{�kW�km'��s���^�?$�*�L�F����HDDDDDDDDDDDDDDD�U�����L�^���[��qtt�K�a^%��*�{�nQ��������NcSSS���*��������
���{�I%U6N�D�����{��X�p!���p��%������kBC����{��!00����h���,*�
}���T<Ogggu��J�Brr�Q�S|||��/���cWy���V'A=i?1t�P���T{I�����8jj���������y��8p�,--+k��X������d�B�}�N�:&��
qO1���pQ���GT�V�������j�D�����	��k���K�r����":z7��2LY���t��~u��O/V`��0D���J�v*�
aY�����,a+�Vi��Nv��������+�4?�S��P��i����75�Z�P�d��7o�5>$$D�~J�����v���uN��[�n�WeEEE!66V�~��uN����+�tPY2�]�t����q��}|��7��p����;wDc<<<D��"##QTTd�xj�F����.]2�ZS�NU�P(�e�u{��M��S�L�p>S�nH55�g��D�I�&����n/��������]2Y��*sO1��U-,��7&��Dm�������I{DDT-�'�pw��nOEEi���	��	����w��z�Z��a��0$�?Q!��YE����zEC+)�;�i<W�R�zjV�� """""""""""""""z�=?�4�t3�:�T�D����[����OIIAqq������������ZN�D��|�*!A�>3}�<s��Q��A�;����c����={V���d����������/<��q=��56������YM���^������e�(�J���������
6D@@@���m�666����Wo�����5?y�d��2���s'O��k�����|�K�^�Dm}��1�zO1���GK&�����
�����MT]1i����{�&���D��|(���������'A���'Fx8i��W�q!a�f��*�VeO�cge�5�;�B.������\dk<GDDDDDDDDDDDDDDDD�4n�5Z��7��\��]E��=���T��&&&��DQ:Q���P����[������������XS����	y���\���/�(j���F���u���Z�k���?"==�(kI�RL�4I���������u�VQ���I�DI���d2���G�...6���<==��Eu;%%;w�4cDTRe����Q�H]Te?��������c������77///4o�\�~��!�;f�����=��|||D���(<|�P��YYY�����AC�FdRL�#"�j���>��FA*���G�*B\�Adf��4��$�������K-�}B��x#�
�	#{��T*�gkN������Bj�ud	Zi���p5��������������������5�K���q���Xa��kGGG:T�������u���������"J��p��(�I�k��������,j����<���C�����o���C���Ne�N�pr*���&M�������~Q�7C*y�#""���!�m��?�������i��m���'C*��=h7n�����m�L���@���1c���b�
��q��q[��������83EC%Uv��?~�*}��~������G��J�o��&��������g��3g�DFF�����.�Sj��1���+:�r�J����W���666������#2&�Q�$���n�1��t)��
�� 5��^%�MI&���:9hO@<���iw"������K�/Dn��?�|��
����-l�$>��CjA�A�#"""""""""""""""z��8��
;����ym�+��,�1c����7�|SaU���7��*"�J��S'u;..�V�*wLhh(��"��c���
;��>l����BZZ�Nc���///u;88{��)wLPP���W��������s����2��]�ve�988��?T��J%����������1j��r�4k�L�}rr2N�>��A�_�$��c�������]�0s�L��G��_�����^z�%u����S�_~�e����<_�>}��{wu���/�����{����v�����k��&�r�����}�"::Z��111�w����{�u��U�^�~=BCC��a����(�O���1o�<��ru���3=z�(9�<�.]2{���q�D�����0`bccu������m������a�{����K�K7l�����W8���#����E�F�-z��L�#"�jK&�/�Q���[n������'T���i6R	���E[+�}�&e`���j�|X��gi��'���\����h�l�����L��GDDDDDDDDDDDDDDD��qoL��p���<���Y�}�]�t��o��n�T*���kx��w���#Q��������2e
���G�u&L� j��7|�E�����j�*�o�QQQ���:�#�H��Ou;==�;w����q��!�������	}���0a���df����O>�=z�@ZZ���t�G�E@@�6m���������-�///���C�N��>��U+t��A��s���������,2��
���'5&����#((K�.E�v���}{��������Q{����;w.���������q��5s���/��}���k��]�v8p�rrr��	

���k��}{���W���N���������v��!�X��;b����{�n��9998q��L�ooo���/z�YU�����g�(i����h��9�,Y"z>?����C�a����������M�3�a�����������=z`��}e*�^�~�F��[o��J�&M���V@@d2���m�66[�l��c�D���s���o��i�d�}���Y�f��m������hl���z�B�tN�6�T����c���G����p�B��_���������:u*����;w�h�k�{�)��3G���T*�����8q"n��U�hh(����C�=wmll�`���Ldhw!""2��
^^����;��5�"��7P\�
�� ����3G�~j�/_y�G���������?$�J�
��������\j��'hP�7���QT\����$�������=5��o����W�yZ��`�=
V�Z���/�����Q������u����$''#<<\=����~��(A�<'N�w�}����R��j�*�^��5���#RRR�B�7o�<��n���{8|���C������s�j�{��)��|�~��GuE���B|��GX�`���akk���$DDD�>t���v��������s�>��S|����J��[�.���aii���t�����4hcc�-[�h�S"�`��]2d����J����q��A��rx{{���	���HOOGtt����b��	X�d	���<N��Vj���X�h�^���e����#Q2���W����������pvvFNN������^��^x�����y.��_�L��.����`��!������r�J�\�nnn�S�,--������(��/j��];l��&LP'�fdd��O>�'�|///���C$%%���G,d`"+W�D@@�z������#agg�F�A"� ::			�1�����s'��m��:nnnx���D{����4ooo���������W��=|�����J�������


���$��3<x����:�0--M����]���Eff&���+�8�qO1%'''<x���%�o��[�n������A����2s<�z{{�2t"�a�=""����������T3���#&f/���~�Du�!�ao��-��3�&2�U�?0����(4�g����Q�����^m�rJ&�������������������"6������{�n�������x<�4�U��?�������T*���!88X��W�V->|X��K2��B�F����o����>I��i���vYe��A@�GA>�W�Q\�2\(��P�8����!C����G[�n:��6��G��9I����}���K�s�s�O����u���3����q��9r�/_6	������k��V��3h� ����&�l�����[�"88�d�V���3g���d�=?����n�:����������'O���#�p��Y�"<<��g��ooo������!�����hp��E9r			HMM
��j���~~~����d�#l\2�k���K/�d�������K�p��$%%�T`�~M��}�QH$
���A8x����\NNp��Q\�z�I�n�4i���ODDD��KOO��'p��q\�v���9Q��������}/�������8~��I`������z��Q���{�=�1���}��w�r�J(
��:�������${72G��h�R�����#G����s��C�:��5��=���?��S4t���c�f������m�6�;��9C{DDtK�0��<�&��kPY����-�V���{�V:��|9?e�;��[�Uu��v� ����a�Fz�!@.����J��iD�Q-��f���0�i f0��c:���z�������
h_��V-M@@:���z����s�R)&L������t�j��5�=�y��������~��a���X�|9A��:���8w�.\��C�",,
�����������i� �JE���#F����x����U[||<�-[�a��������m�������.���o�i
�L��������={�M����(��=;v���c���q��y|��G3f��������`��	��W_}����������cu~pp0f������z�5c���T*�#�<R������O��/�D�=����R)�����+W������uo��w��K�.a������������>|8���;L�2�I�L?�0�����Z�����Gyg��i�5����}�v���x��G??�z���q\�rO<��Y��6L�2�v�BTTT��v�6m� >>[�n���C���ju�T*�����W^y�/_����*:��)�t��w����X�b:v�X����(���k8s������*��;Q�s��t���8NJJB�����c��=���!C�����QSTRr����`0�4�$w����������5L�
�^�mX&�t��0��-��
X���*��0F��A��]?�L���y����2��*��`lL�5^�����DD���`"����0Q��5��e��}ZZ��.]2���];��[���T��J@�
�*�[�>��D������x�"rrr ���   �.k���`����|�2�������V�Z�_�~h���]�����|������P�����@tt4���o�.s:������K�����Z
�:����8DGG��:�g����3g�R�PXX�\oooDGG#66aaa7���D��!>>W�\Ann.����T*���;�c��
��k���6l�q<z�h���/�*����C�!;;yyy��d���E�v�Wg(������������AAA�r9�����C����:j���c��%�1��RRRp��AdffB�����:t@������5��N�2v��qm		All,�t�b1p����������~�:���P^^�R���t���:u������S�)++G�EFF
a0������`����I��@�������FDD��R�R���[���w4������!!��������_O|��I)k\�53���!�-z{;��[YzY�h`�=��~�B�PwWd�W����h�\R�'�ADDDDDDDDDDDDDDD�� ���]H�!�H0p�@��n�R����#v~{�����q�v~�T�.]���vA��s+������������Y���Fpp�C_�������.�j���jR��"z���=z4v)7E�P`���v=���S�)$$c��i�2���i�*&""���{""&C&��8�`�"3s+���X��F����,�/�0-�*���;��[G�Z�yq�W8�/��,����b���=DDDDDDDDDDDDDDDDDD�4�J�M�6����=zt#VDDDD�������������)pu
�2����?��w�I�=������Z�_��a����^a���%���q�T��b��R���:�\��&�O]����2��ADDDDDDDDDDDDDDDDDD���{�A���~�9s�@&�5bEDDDt+`h���ni2����������#����A���l7�u���<�����SW���:����zitB�1��N��g�',EO����7��(����sx��w�c�B�9s�4bEDDDt�`����ny�aa�!'g��s���g���"4t$W'Vh� X�&y�Zl�.�s�\��`S\[(eR'W��\U��nw�J��������z��R�yMe:=�������5Q�TTT������b�8q}�����7l��y

j�������5� EP�� �*QXx�����T���Gh�8�dM'H%����Z��+���.������{����,W��#�T#�/Z��`������y���bM���h���\�r�fDDDDDDDDDDDDDDDDDDM]VVF�aqTT.\�������V�������8����F��������w^q6p���s�x{X�s����M�� �k!RK*���/�������t�����[�����'WDDDDDDDDDDDDDDDDDDD���[������}DDDD51�GDD���wBB�@��h��HK[���t'VV7�T�o�F��������Ex�b-4���.��!�"���������2]����\�srEDDDDDDDDDDDDDDDDDD�P
�]�t���?���$t����K"""�[��� ""r��-������z}����<
Je;'Wh���k�����p��Rt�wyp����P'W����:d��?'��n,����M&E_��7���5��_�~A��P�%**��~�>�;�Q������)��,��������+�[�����A���|���l|�����_rI,�I$Z���Z�t�QB.���BQ)�UZ'WDDDDDDDDDDDDDDDDDDD�<-^����QS��5k�������<��<�jT�}M����k��@)��v���t������W��\t����r'Wc�U*Aw?��>=��yj�DDDDDDDDDDDDDDDDDDDDDDDN��5{2���'B���:��������t��u�T�����K�s����]y�N��q�Ti�SQ)�/���`�9r����IE�]Q��@S����������������������������#"�A"qEh�Xxzv�:���226C��pReu�����FZ|����I�8VT����-����$�����X'����m���Q����� EP�]���������HO_�����F����,�/�0-�*���;�*�JV�?6?W|\]�\�um��v����^Z��r���DDDDDDDDDDDDDDDDDDDDDDt�ch���ZA��w;��F,����CZ�h4*�W��a��_L����Z&�����/VT�E��Jt_S��w�D�������y�0N���������������������������=""j����"4t,A�h�%HO_����N���y��0�U���Y�U�|�
T�Z'V�x���M3��J7���;f�W"�L���������������������������#"���#��� �Z}��ddl�Z}���Y&�	��`_�s��k�`��huN��q�Z������r��1	��^V����m�����������������������bh���Z47�DDL�����Y:dg����cM"d%������,�IT�c��dh�z'V��ZU�w�i�]�nS���*�/OS���
'WDDDDDDDDDDDDDDDDDDDDDDD����x..>����<�����}P���`h� ��D�g���������%x�l*tM hx3,u��(e��	��^���'������>DDDDDDDDDDDDDDDDDDDDDDd��="""R���������������z�x�7gRH%��k4:y�Y��kn^���$:6��`@���^��+2��+��@7W���5*���Rq��+"""""""""""""""""""""""Gbh������H\2^^���+-�������Y��,>.2�����\-��6#����X���VT�D�������������}�����o�P%�ch����A� 0p����:��"ii�PUU���,��`]�6p�Y��"5_��:�*��Z"�D*o�����m,���z�+*urEDDDDDDDDDDDDDDDDDDDDDD�(��"��� (�_��VYU����5�hr�W�1
9�t��Rj���.����|'Vus�R����p�nVkS�����N��Q��;� """"""""""""""""""""""r�[�nw"""'���EX�}W�st�R���CYY�+��S�o�F�U��0��5��k�����*�D�� [���uM��E����4z�
K�\9C{DDDV(�����T<lC226����+w��'Vu����53��q����u5D��.{Rh�tsr5���W	��P���R�kuN���������������������������=""�:��A���?+�������G`0�V��Q�>x�C+����LK��������@g0 �D��Vnp���?������+�H�g�="""""""""""""""""""""�[��y�;����x!"����[������`0��T���a��_L����Z�$\���J'Ve��2
4z��c������W%�B��J���:�"""""""""""""""""""""""�'�����l$��#,�~xx��:��8YY���W9�2q�ZaND�����*L>u���KV�w�s���psr5��*����Rt���<�s"""""""""""""""""""""""�bh����$BBF�����y��W���:�x��A���a��kq��r
L������Y����ZR!����d���_Go(d�?�]V��@���O""""""""""""""""""""""j8������I$��V�i4�HK[���B�&B"X��5��{Y���.�������N����R
����Ow'W�2��~���`�="""""""""""""""""""""�[C{DDD
 |}{#8x��yUU�HK[���,�W��D�g���������%x�l*t�r�t�D�;�\"A�B��j���^.���k��)�trEDDDDDDDDDDDDDDDD�����@���Oo����j~�<���������w�Sj�����Z���z&��G����<=;B*�@V�V���9:]���#$�xx�8��j
��v��}'/�\i���_s����4��>��~y����f��(�$���j� ����f��?�W����	DDDDDDDDDDDDDDDDDDDDD
�����G�"99j�...���C��m��{w���6v��L1�GDDt��V��������1�������������
������{�9q	�+���}����	uru���V@g��_���s�q�(���.��T���*�DF��n�P��38�<����#G� 11UU��?���c���v[S����~���+q����A@ll,F���������[
D��.����9��1��Vf���yy�`��Ls���uo�������"-��U����\t��T�`wW'W�x� �����������Z!"""""""""""""""j4��*K����'Z��{�B��/n�����������"j��O�nr�HIIi��������1|�p���"66��O����������������z�!��=�:Px��,[���Z&v�#""����� +k+���[�WPpZ�AA�!R'VX-F!���1���e����s^��_����9��
�e�}������jq�0�!���*7�~���BJIE��2HDDDDDDDDDDDDDDDd�$�J�������?���0���P�4^�DDDDd�-[�`��]N]�����������b��R�aaa

�^��J�������&�v�#""�#�T�����Tv�:O�>���-����Z���S�o�F��Jn��k��Wlq����T��g��4��Zu�=���O������Qs�:�8�>����b����W��~�z��|cTKD�l,^����;,�3yxx���			3f�I`�S�N��������k�����c8q��]����"���o�����C����	��������������o�V[���L����U�#-�0�53��q��9�%��E�+eR�]�RCc	rwEk7�}EUZ\..srEDDDDDDDDDDDDDDDDVY
�^��(L����)��%��>5Y!!!3f^}�U�������3�<c�5*++���B�V�=��SHHH��i����gv���F���?�����kMD��.����9!�yB��cq�F���������?:��@����� ���\o������g[t�p\��2�Y��]c<�!X��\������
zIDAT�}'����T@&i����L��j@S\�T����d��@b�������>.\�?��Z�r�ZK�.���g�����������;�>ij��i�����||z $dAjq�V[����(/�pbe�������Z�_��aJ�U\�����.{��2~�������Z�����:9�:8����n��>J��s>""""���={:%������K�����x����.Q]�i�������v�J' 3s�z�Njz}226 8x4���N���:�J->M�������SW��g;������������X������du9�"��K��KW)?s����������������nQ������?��A�������O��=w3����������������bbb0`�����m���B$%%���(((@ee%|||��n�
���v[�f��� ))	W�\Aaa!�Z-�����}�"$��;7fee���HIIAqq1�z=
����.]�@�T6��eee8x� �������T��� ����g�������`0 11���Gnn.����P(�N�:�k���J-c+,,��C����	�J�^�i���wGPPPc�(*;;G�ANNT*$	|||��}{��������Kt���<����HOOG~~>��O����y����q��addd@���a���������q��\�v
EEE��d���Cdd$���wS�G�p��R����777�S�N���;\]]o��UUU����������Bxyy�U�V4h|}}���]��c��!;;���FHH�����~_q�{����o��F�1�,X�B��Uk9w�5"w�pDDLFF�&h���f0����
��C������	��Em��W�����9W�5��x?���Rf�?\��������toQ<�t������t����8SX��^�P�\�f�{�i�����.�s�[�N���+�b�
ddd���J�?~<�-[�����q��I�]�;v�@BB���111�?>f��www���t���%K�d�������6�f0p���_�;w�������kW<����:u*d���n�a��X���:O*��[�n7n���???����A������{�I@���� ��3,�����s
<����������}[�-����m���]��7�x�7oFNN��y���5j��������#,,���ooodff���-11���s�_�>}p������z�[�|��=
�N':O���S�N��3�2Z�x�������%������/�����������R)����������eC4��Wn<����c�����e*++�����V�\��o��l��={���/����f�A��1c����u��6�XQQ�_��6m������e��T*��a���/��5_�z5f��!�/::��q���HII�zn�J���~k������-������#0k�,�9�^��j4,[���������K�RL�0o��V���������O��g������sA@�^����/��{�������\|�����d2<���X
�?������I\]�1r��O�1 7wT��V�x�A����1�J(,A]���������k�d��ON����=���~J�,�B�TP�r��e�����������������4�y ;��kd%T�C���|���,
����
6�{����gO��������gO,[��N������W�b������7._�\��j��8p >���:{p��iL�>C���I��`����4iR��
���?y�$-Z�'N�9����&M��w�����b`��$�����}��8z��M������!������;t=���%K��]�v���O��Z��~���M�������2�����a��z�������g��mu�����|������'���O�����wm�t��!�o�s��Ebb���{�N��b��YX�~��t�-[��g����a�h`�54�7o6��d�6L4�T��n���}��t��;��&L��?�h5�T]v���!C�`��y�j�6�aO�~�)����l�2��=������?c���HMM�y���t���.
�����u���wo�<y�^����#���#�|�I��=���y��1�;��{/JK�;����g_����+&�']�vE@@@#VD�������H&S"<|���Ga�Q������-���:G�����9
K0�l*tv
^���������5v�I��W���H,(qrEDDDDDDDDDDDDDDDDv�b���1��s�:M�Z��]w����x���  **
�{�6��W\\��c����s�Z����l���':t��>}��g��h������g�b��6�n�X�������������8�����9p����r�L~���3��9@u��=z�_�~���3�]NN
$$���@�^�g�}-++�����fSWUU�I�&a���f�)WWW�i�}��A������S�����c2���Kyy9���{�����'[���g��~��8}������@t��
�{�FLL$��s����k1d���Thh(z����={���Vu��AL�4�xmpssC�N���wo�����*L�6
�.]����X�x�1�����n��!..J������,�?UUUu�$v�C�.]��_?t�����fsV�\Yg����|�I<��c()1�R*�"::��v�v�����
���>|8N�:e����{�K�.���&�U*���^��x��m2d���M�����;v�h��u��m:t����&G��47���5;������7�@�~�
777����_�~x��m
����w'<Q#�H\699;�V[�d
����R����D"�8��R	���q'/�|��/�����ix�}D����V��BA��'����.{7t�Q�|a)4z�`���Rt�����?��-�$(Lq�Z����)C��^�`�?~�8s����L�4���x�������B�V�����Zr�c���=���A���u����a�������YYY�5k�l�"z��;w��3������6��V[���k�����	0z�h���_4��������o��&
g�����?o�����GM[2�,��9si�������?�m�VgG7�^���'�|=����b��i		1�{��!,\��w����a��)8u����M��|�rF�a���[7,_��bM111Vkv�g�}7n4���_~w�}7<<L?8�������_��?�v�������~�������c��6��q�F�k�L�bV�
)))����M���r��7�<�bccM�������C��q#~��G��q��G����6	Izyya���6m�I��l�o�>�_���ku��6m*++�7�x'N�B�P�Um����5k�]������_��O>������n�
K�.����!�JTwW������SO�i�={�V�������YW���1q�D�5
�{������~�����Oc��U���������k�3��w��9���n��������;�����{����.~����ov=������q�������_�����c��5���-�~�i\�z2��=��|�I�i�������V��/�`E������_�[o�e��g���<`�0`�{�96nnn��j�k����/����l@||<�z�)|��'��w�{JsT�����>��=��Yg���ddd���#X�t)&L��?������^x�7Q#)����L����#���_CZ�:����L��8��|\dX��
������m�������������V�%�?�*J�rC{�R	��y����[��d�B|E�$"""""""""""""""���:�8D���c�^�@��y���Hg�����������cA����b��ifs����j�*����g�FJJJ��9r$z�!Y������{<�F�a�m��g��5)������KQLL�q��f���7�x�,�R[xx8�{�9L�<�������E����O���!��>�3f���Npp0&L��	&��w��^��8������={���}�b������D"�w���;wb�������TQ^y���L�^�D������s�L��o�{��g���'���+,v�k��-�������c��]�s{�1ch���[/���_��g��eq��>hK������t��Ut�R���#0b�,]��s&�F�I�&��bcc���v��_Gc�����c�l�2��j����t���w�FXX��>Ap�]wa�������10�y�f$$$@��c��	������br�\.�������\C����:C{�|�	���o���u������c��1����o���BCC�!��A2���;����$%%a��&�&L���������
�Z����31s�L?~�,�g���W!���i�&�5�l����~�i�����?�^���������V���'���,Y��_~Y�	���'f���Q�Fa��!����V�������G�c���]�|�d����9s���1u���8z�(������D�bh�������; �y"7w��jPY�BZ���������G��`]�6���%������H����3#��^�`0��Z<���
�K�����u������i�y��.GW_%|������5v��v����p���{�~�������{����+��i��Y���7��s��������5k��c���P�����l�c_���i�DFF���?7�����v�Z��/^�h��R���	�����j*++3ynBCC��o�Y� �H��{����c8|��{������%K���csmM��%KL�>���N��
6Lt��������C�R���[,]����V�w������8���C���E�����2��r���^m~~~u~���o�1	������?��X)&<<�A�5�_��,�WS���1c��Z�
���p��%�m��|���P<���x��7q���G333�>���c1b,X��^{
@u�7K!j{y��7�]���;���u�,�mk�����7�
��4u�T|���8r��rrrp��q���Ot������d��3.�����p���O���3��-_��,	8�=�������v�8q�8���'&O��v���~~��]��'O����b��Q8u�T������FDDD���
���B,g��Z5�����<���1
9~�����/]J�����-��TA]����r��� �����gp<O���������������������+,,�����c777���%o��F��${h�����c����_�!�
f��Vg��K���J]���[�����/�9�%�J��/�%%%��}�]��d���0��V�^m�5���MBo���X�r�]�-��1}�t�X�R�|?YR�.{�;>���6�S���-[fs`�9�8q"�u�V��{���l���?�Ba�8A���0����nG^�333�~�z�X"������������p��;���<����f�����
�K�.����]�b������-[����G�����q�v����_?�D��>�����0n�8�7�>�,�?�w�}��;brr2�|�I'VN-C{DDDM��G��O�Db9���k���JJ.Z���<X�5�"m�ox�\*v�������	��n�:Ws��K/��V ����QSv��!h4�x���6����Hd/����;"�b/QQQ�[��f����bl���.����o��d2L�<�^�6�$���~����v��a2~�����=p���&!��?������*|�����B����S-���w�q,��,volJ���p��9������cl)&N�h��.]���A����m:�v����k�W5���c���v�2	��9������o��aMqqq&���������C||�q|�=����~�u���.��KJJD�sG��4W%%%���z�-��;���~� x�����+��l������F-C{DDDM��[(""&�����,��~Aa��O�p�;}=��s���`fR2���t>������^�Bw�xP���z�[n�}\U��$5o5�0x��z_��5egg��?���S��kW���� ���f��qeee&]�-%%��-�����S'B.���Y���J��x�#F���N������u��������������{��xxx����8���U��;h��];:�8��{7�^�jq��-[���cO�8����;v�����G�����j����:r����iz��e����@uH���W�c��m�_0>>/��"F������������W��h�:w���[[���m�d2.**�w����qC���M�b�eG��4gnn��B:u������u�����m����V��W_}e���ech����	qu�Ex����V��T{������G���;����\o����8_Z��r**Q�����QZ�6�E)��'�����Jd�iD�Q����l2����.�;;�B�R��GAxx8�x�	����HJJBNN***l:�3����7nbbb��s�a���8�<T**++o���'"66�8.))�3�<���`�u�]x��7q�����:���o�={V4XX�����s�<�����+&���f���c��m0��_X�[���Y�,�uF��p���H���6�S(
:N�X[�����G�����o_,]����;���QPP�V[����;�uT;�g�������s];`�������<z�h�s�]�����)�J�m�>��I�YKd2y��m����j#bh���������"��������C��H���0�jq�V�)	Wq���������@k��'^�d� �������U�N
oQ�U;pQ�SS]�;���+������k�t�z[�F������G����e���kc-�����m���C�f����/��2�������������:���=�VR3�"�����cM:��^�Z4�����?���8�����������O��1��u;�Xg/G��k���~�A�!11��k8�Z����#�kg]��������
d����;v��k"�A���9�����"7w��O[�WRrZmBC��T������B^��������Ta��+���\���H)�t���R~�@ma
9B�]�Un��?��
�%��d�B"""""""""""""""�@���l����(Ju�z��@���^Mr��Y��+))1���T����������Q����f��]�v4h:t����pxxx���� �������cG�jk���<�5�,��[70m��EXX������fR��O?ms&&&'N��{����?����fs4
�����{�������9s��������C���J�������V���V(6uR�/<��#x��7������_1v�X�y_~���sj��`Z; 4i�n��[�={��?���I�L&���;�D��}��� ���A.��;b����^G��.��=�96���}{����,))Ayy9��y_.�<������(A� 0p8d2O���mq^EE���!4t<\\��� X�6yUZl�.�s�\���W�S\[(eR�}�eT����f�L� ����_�T��O���Z�I�?I���o�������ot�>�FT;tWVVV��KKKm��j�*\�x�8���������c����z�u3^�u��H�������>}��yl}C�
�/��"��y<x�w����{q������������~�;v`��}f]�j�����^������((��o���z��!��Y�f��7�4j>��s���N���_m��r<��Cu�^S��mSu����<���&����Gc��U����z�����$�:rD�LG�}]~��'1z���:gLL��������u���d,B���^^��PPP�,�3��1�GDD��	�?�~������	@��vee��~DX�x����K"X��5
�:��W,:'A]�I���[�5�(�\R.:_&h�!�G@��+Zy��z�y���*-.���w��HHDDDDDDDDDDDDDDD�!�����]�����1�T�mI�p[]��]k2��y3n��v������W]7c��u������?������uJ$0��E�PUU�c����?���?����/�^�p��O�o��fr��a������7��������3P�T	�DEE�����������?���fA��p�}�������k����s��q���R\�x'O�4��t��M�6�����c�y-{EEE9m}{�}]

u�u��)�Yll���`0�������%����7�Od��?V��������BC�� �X����"=}���9�&���:G�����9�J0�l*t��\tzRK���Vnpq�'5'��-����bh���N"""""""""""""""�F�|����Ot�z-T�0ZRRR��OLL�i�^����G����8�{p���z��P��]CFF�q������^yy9����R���n��v,Y�/^���+M������8w���1!!!&]~RSSQUUe�zne���3;v�ak��3��o�N�����8����M���=���9�v{�U�n)>l2�9s�M�=�y�b�y�����M�5�r�������g��f����m>�vY*�������"�#""�exxD!<|�R�����W"#c�j�����J�m�ht�p�8���"�p1
�ie��,��d����]����T���BQ��+""""""""""""""""�Q� '�3�9�4Q��v���������������V�5�;t�`�/^Dzz���%�>�`����k��_�:������� x�������l?p������w�q�q\VV�#G�����u�P����`2vd7�{�������W_}�^���L������m�������<_��=M�7�<yYYYv��j?��w��F�i�j���������^k��������2d��q}�?G��=�9���F�.]L�?~���k�m����{"��`h���������)pq��2K����QP��?������{�r���,�f�aYr���]�\%����n�z�{Z�.!��:�S�!"""""""""""""""�I@G ��c��^�N���K���+���m:6''��E���*++m����?�y.xxx�����l>��u�W�@�T*�9����L�~������<��9v����w�}���B��%�J1s�L�855;v�����MB�3g��)�����a���Z����3{C��]����<����X�����F�1�i���62��8����q���z������M�aW�\����������������3���O6�a���-!l"[1�GDDt�qq�FD�d���Y���w*�n�q��]��{��,���Z6������T�A*��R���E����4z=��8�"""""""""""""""""u��sn��~�c�}���1�q����-������6�=���M��6	1Yr���z�����L����6b2����o���-[���NC�T�������3���co������=�|�SRR��=���w�y�q\\\��s�:l�Y�fA*���}����������O��|���7/[��O���:�v��>�,233�������_~��K_]n�z���'�z��>�(��[�Q��L�O>�$������������1...���
p���:�KLL��?�l�m��I�.�Z0�����nAR�;�����G[���������*�������1PJ����&��X^���q�5C����Y�d���RThuN�������������������@�����������*�A�-����M�~�\����X_|��I�.R�}��5�333�|�r��\�|c��EUU��e����R�4�w�������m��5������G�b��uV������i��U���S��_�<�����������<ooo<��s��^���)S�u��z�w��q<��V�t����o�J��{��k
�>}:A0�W�0[},Z���5���?��'�4�8f��]�l^+<<��s�q�y�f\�z�83f���m>��a�0`��X���_��������|�:u��������7��ic���a���HKK�����t\�p�Q��h���7�Z�
�/_�z���~�w�y��k��N�A��x�� �������c����h46���F�M�:��y�x�"F������QUU�o��o����5��r��������g�����<y��n�����2e������������#""�EI$.	���qV���^FF�F�t�]�������F�U$P�]�&z��T�P�\t�s�I�#�Gf����v�#""""""""""""""�&J��m��{r���)C���B�~��x��G�c������x��'p��u��)))���c��=**��uz�!��/��g�y999&�U*�/_���{���k:t�y�D�a����������z�-l�������}��|����t�R�lOKK�K/������nnn6?���+���X,Z��BYY�����rl��}��Ejj�q{���q�m�����g���Q��c�Z�q��a�����{�h�������x��7��W/�����������.��}�����6l��;L������0|�p����5������W�^��iJKK���|�2��}�������zs����o��Y�:|���&�222��O,X�@�3Tii)v�����g#22��+�3���b��u&���g��K�.x���M^�7b��-x���C�9���m�������c�Z��b��
fP�������`@�N�������M��}��7?~<���+����&����k��a:w��o��F4�����/��C��m��fsh�Q�R)~��'x{{�:t]�t��E�p��E�������/�`��9����q��9���|Oq���
��iK�%�������s���4���o_l����{���
?��3�����g�����a��Uvx�D���=�����*A�  `d2O����8��"iik6..���������s$f%��F�r7A@{7W��QJ7H,t�#���*q���z�O�:_T��>P��G="""""""""""""""j��!@�'��������'�;�~;��X�|9�?��'O��}�������
�T*$''������l�f�����O�]��/_�+V�]�v���A^^����������������SOa����Nj/^���?/:w��=&]r�y�|��w��`���x���p�Bt�����EJJ�I��>�?��RRRl����sx��W��+�@*�"""~~~puuEaa!�^�j�iP�P�����xN�D�����3v�3��y36o��\���H���������HKK3y�m��C���_�J�P���j��EX�xq��ooo��&�_�nF<y�$���~���"22~~~(--EZZ
���w����(��B�������h��56m��q�������;���w�yAAA

���+�������^o��N��W/|���x����a���"���Kx������`����\\�~����ts�y�<�x}�����I��T*��];H$���!;;�x���~�������u���������u�ZT[dd���s��y�z�*V�Xa�v��L�>R��������F�Aff&rssm��Y:t����7����7�

��������������P�T
z�xOq���,�1���;v���;D�}���uv

����1r�HTTT�������1����l��J�������{w�j%�;���A���m	ko�UUHK[���l�s�et��uhewv�Cf!�����z�#�T�n~�����T�������e2�0�]�c}����2��=����c�����d��`���Wq��Q������n�Z��K...��e��kg�]�����8r�._�l�����^{���g��Ax���M:<����[�nEpp��v�V�3g� >>����p�D"������j5�t:�������8r�.\�`����Ygh���;w����_�d����hp��E9r			HMM
��j��l[M~~~����d�#l\2�k���K/�d�������K�p��$%%�T`�~M��}�QH$
���A8x����\NNp��Q\�z�I�n�4i���ODDD��KOO��'p��q\�v��='���?>��s������<y��7	������_~A�=���{��gs��w�}+W��B�0������Q���M2�w��!Cp��Q��v*�
III8r���;'�8A���\�=�S����c���f�eEEEHHH@BB�Y`���?��3���;�Tj!�#""j&<=;!,l<$��v���!=}=JK�-���ia�x1&�]�&:G��C��J��N�PH���\\���*�}DDDDDDDDDDDDDDDDMF@G��l��| j0�����h�{������z��>��
��C���[o!44Tt�T*��	���`���V�[����G1o�<����#��������|�r>��.����s��a���:t(����P(l:_�=p��qL�6
R�Tt� 1b>���z�^����c��e6l<<���m����*.\���o���5d2�/_�.`���6�����0{�l�������������Ga��1������g��i�&^}�U�;w��O����������9s&�������3L�R��<�H��SSll,N�>�/��=z���Z�J����?V�\���~����Yw�y'.]������C�V����b�������0e�'U�2=�����ohq���y��9s�A�|��+��������GA\\�����~���q��<��f���|||0e������-�)h��
����u�V:��������o��v���+�|�2^}�U�y�xOi��s����g��������'�|�/_�=�����E���8g��A�.]����$t���+�Gqq1���c2^^^�X��G��EF�f�t%Vf	
�^^���7x�r"�D�
����X������*9��BQ)��)�����a~�:��DD���`"���k0Q��5���q�:LD�xx
&j�}��V���K�L��k����V�`0�J@�$2@�
40�E��z=8��/"''r�1110`��FII	������/������h��������[�e
{�����}����
�Z
DGG���v�2���p��9\�t	���P����.������Ctt=�K�08s���9�J���B��rx{{#::�����un%:�����r�
rssQVV�R���pt��;vlpht���6l�q<z�h���/�*����C�!;;yyy��d���E�v�Wg(������������AAA�r9�����C����:j���c��%�1��RRRp��AdffB�����:t@������5��N�2v��qm		All,�t�b1p����������~�:���P^^�R���t���:u������S����*����+]\\��;�O�>M6�N����C5������Z6�<S���	��yf���Z���}��������8�*��P�AF�S�����P���/UMM;/N�@]�3��ZZ���J�Y��"""""""""""""""�&E����+i6$	h���R*�9r���o/~~~7n���/�J��K���#���un%7�X9���_|a2�5k���v�k�Q"##��eP
QQQM�#]]A@�=��G��.��(
:���t�{Js����;��w�qGc�B-c�DDD����'����[��y��#7�Oz���RR!�]U�EF���.���dh������z�[�����DDDDDDDDDDDDDDDDDDT7�J�M�6����=zt#VDDDD�������)��
����T��:���423�@���{
%UZdWT��K(�����`��T�������n���7P�,�DF�FtY��{�A����9s�@&�_�����������1A�!8x4||zY�WV������j���~��.{�Xf����"�p1
��E�����S"""""""""""""""""��9w��}�]�X�P`��9�X�*�'""j�A@@� �d�P��Z���d#=}
BC�����.k'��E���:�hu���������������"\!G��+���;�4UH-�@���*#"""""""""""""""""j�***p��@qq1N�8��>�����7o�<5V�DDDtah��������	�L����a0��������aa���vs���J-�4U��n���^�����W�f��U���7UCKr���oi*��'��h��� 8�2"""""""""""""""""��/++#F���?**
.tbEDDDt+�4vDDD�<Je{����Dnq�^_���
(-�rSkY�����X�=J��E^���M�7UCK���V�_��J-�[������ l���]
�"�#""ja��#12���9���[QT���5�����\��"C7OVw�����oO�K������R������d�Z������
�t����III���kc�DDDD������Z WWDDL��k��Y�������0��*����R+�/Z�n�������s��H����+*���-���m<�E��ju����������������������LTT�����R�>}K�.E`��{������1�GDD�B�dJDDL��{k��

� 'g;���NV�w���Z����>X������z=�%^��R��$S=�=a�aBA	��z��CDDDDDDDDDDDDDDDDDDdo�/6	Z5%��`�aa������yj�Ydd�����s\��qw�B&5�>-�/��Z<g�V�)	Wq����	�t����Bt�F�GR��9
C{DDD-� H�/����:��<������X���T�D+��/�V�����u�DZ������SW���Z]��u���L��w���FDDDDDDDDDDDDDDDDDDDDDDts�#"""��;8�x�4����Eee��9���	"��C{� `Q�0L��8�J�S�X�?2)b}<D�U�
H,��$"""""""""""""""""""""��ah��������#$dAjq�V[����(/O7��7�l!����Mj�G� `E����eqN��3���������.�J�J�C���JQR��#��1�GDDD&����������QRr�d{vy%�u�a�hO�]�jr���Kn���J0�l*t�M�l��R	��*E����|��+""""""""""""""""""""""j��#"""3��a��������A���m(,<i�v�B�=�����M!���n��h��_r����4��*���:^..Cae��+""""""""""""""""""""""j��#"""Q�������<��<�jT�}���H-�Ex���Bp��vo�7�s�������z����I$����gp2����������������������������="""�H&�@x�D(QV�����������(��~��������������"-�A�o)�{+��"��RRUE��+""""""""""""""""""""""j��#"""�$W�����gg������X!Dx�5x��k��@i�S�K���)���k4wA@O�n{p����������������������������="""�� Ht��n��3H���}�J7�$�M���S��]��*X>��R�;����i�����s�X�Q�AF���5O��MA����
�4<W�P��"z\���]�����t������<���cE�vY��=�,�?�*��`pbEDDDDDDDDDDDDDDDDDDDDDD�C{DDDT/^^]:��O��D��uS�����@,�����r����|i���lN"r����Si�p����5?�Q�yx� <|�R�
*:��pe%����0�#�ju��p�+*-�1Pku���B����s� �W�������-�� """""""""""""""""""""rY�S�������� "b2N\?�N�G�@�";�(������ vY��ZAU��gi���35U�|�
��l�������csvN��pZ]�B��8�G&EWOw��T��`_tR�����(�]��ie�}E�Z�VH�*"""""""""""""""""""""����="""j0����f�\QoT�����A�U# `���
���m��_�����9W�5��x�Z��4�Z<_�V��%�_P�������Ec���M���
�B�5�����J�;�5���5ODDD-V�N�������WQ�Ide�
�^|~}I+:��0?���u9f�I��s�����������O�M���1�����h|�\Q����-�`0@�����
Z�v��& ���^���f����22~�NWn��]$>����<�r��6e`h��+�O�MI?O���� ���DDDDDDDDDDDDDDDDDDDDDD
!k�������2�T*������:���O*����J�P(�X)�TW��a69J��<�}�HK[����pq��%�V
��u�����q�����W[Ve�;y�{�E'�xw�[����8_Tf�� sA�_0�U��P���-T�������9s������@qq�I`t:���������D�9s�T1�DeZ��+E�E)d�?fTU�#-m
4�����"���m*w��ju��p�UZ����t���T��W�
����@DDDDDDDDDDDDDDDDDDDDDT_�5!UUU�t�.\��Z]�c�j5.\��K�.����A�#�B�=��
aa�A\-���J���ee�v�'D��.J�u�����K��v����I��!�S*EE@�s""""""""""""""""�F���A��M�>��K"�z���;x�`�s/^l2���N���j?j��������O!"j"JKKq������������:u�B��Qr�xh��U_W!����:]��\��
�t��bo����"��+��s�eSv����o���L]}��PT�J��l_�o�tzx5B]DDDDDDDDDDDDDDDDDDDD�<����HMMEff&JK��-���AHHz�����H��UXX���O����(((@UU|}}��}�"4�M-�9�#"jJKKq��Y�t:�����
g��A����#�PWi�[!0�Q�?�F.BD�ddlBUU��������Z5|}�4��nV^�i�q
Y�9���R	��*q<O���D�s���u~]DDDDDDDDDDDDDDDDDDDDtk*++�����o�>9r)))u�3f`��y����y-�^��{�b��m���?���du~ll,��������^{r(Ic@D��UUU����v�����p������G$&Y-�e�=�M�..^��xnn�V������`0��]���r.��go��Jq�B��[U�����?��kQT�urEDDDDDDDDDDDDDDDDD����A��-^���Kj�j>��n�r��	�>}������\�;w.��[g�k%%%�-B�N��i�&����};"""0l�0���{u������;w.���p��Q��!j����YJJ���uUUU��������������|�Rw����vV�[\���������=�9��^�o��9�N]��d	��<-�?�W��j�����������������3��kP�+C�^����%�����S�N���/�w���� �9999�8q"V�^]��.]����L�}~~~����m�����[�;h� ���������w��� //��k���!  ���]�Z�BM
,t^��e�&�D���{�R�EQ�I�����"=}���A*����Iu�M���d�s��9S;o�
K��2���RRUE%�\�2"""""""""""""""j	�*sq��r5�PU�@��0��K���@y(�yt��k`#VJD�<,^���+����t���#Gb����������$''�����;�������"z�s��A�~���cG��������1x�`������v�>�����{�����-//��1cp��9������%2��Q#���p�:���$��w��h���cA@`��d^�����<�&iik6..>V�i0p�B�?GIT��`0@���HRA@?O��.�<O�����[5{�eWp�(Y�4�s4�
�W\Cz�5�*:�yzx�EkE��c������������Kh��m�s�����+�`���:t(


���X�h��[g�xWWW��3���eq^�����;�`���=z44
���/������ �
$�]QKUVV�Z����j5�������'����rAn�P���y���<������B���EEE��s���(��w�s�B��:�S�t�Owx��<�(� �L�����������������������cW�/�#g�����,M~��	�rA����LDDDDu����)�WS\\�.]j���_EEE��#�������������j6l�-[f�m��u())�W�Duah�����T�f�5Oy�*W��b<��u.O��Dnq�NW����(-�jqN��P�u�E�H�:� ��t���x^1����������������������*s�!c5.�����\.=�
��W�k�������1M�2�?Q���R\�v����={"22�����?�����q��h�w��z��������9;�_ZZ����yJ��eO�t����V������OZdfnAP�pxyu5��*���=�i]Gq�BV��V�i�/��
�J+��_@��������������������l�Z��r���(��`[�Z�	��@���9�������q��Edee���
1110`�����Naa!���p�����>>>

�m������!''III�r�

��j���������!!!7�FVVN�8���C��C�P ((111����Je��_VV��"==999�J�

Bll,z��	Ah��7Yc0�������#77EEEP(		A�N���kWH���.����B:t���P�T������A�6m��{w5v�����q�����@�RA"�������G\\|||�D����������t���#  }��A\\\��^�|�FFFA@XX������)99g����k�PTT�L???DFF�_�~7u�q�. 11*�
���pssC`` :u��������rC[TUU����FRR
����V�Za��A�����c�v��;���l���!!!���;n�}���)M������m��R���}{������~��a����m���D
��Q#0N�����`0��_��>�K��X���]��?f��������������������R���v���R*��L�B�x@G��I�!m�
�A�{v���D���S���$��Q=U���[�Ov����W�����6nR~qM:�+V���+���a�_*�b���X�l�������'�v�Z���			0����`����5k����,���d�,Y���q{������M�8p������;q���kw��O?�4�N�
��~�[o��+V���C����J�������y��������<x���:v��
�F#:'((s������i���7<�������������-����m���]��7�x�7oFNN��y���5j��������#,,���ooodff���-11��w7�����#G�X=F��c��u���p��Q�t���	��=z`����1c�]BF�/6�^������_|�>��S�>}����T*E�~�0}�t<���P(7]wc���r���?.��-[PYYiv\�=�r�J�~��f�����_|�6�'���?��[������
������iv�����,�s�R)�
�^x�������1c��}�������DJJ��s�T*����X�f
�_�nq���F��Y�fa�����Z��`��ex������o�_*�b��	x���,����'�|��>�g���#z����_~��{o�����������gEG�k_K�����\��ns"�&N��Y����k��z��I�KNE%J-��o���L�������������������:A@WO������{������E](���R��:.Ys0�t%9w���w9������|���,
����m����w��={���G}��={b��e8u����\�z���G���q���z��P,�����G�����Oc���2d��XM������I��W�����'�h�"�8q�������4i���N����{@u'�W_}������Gm���O�A��M�>���,Y�������~Z�����?��h����=��q\TT�
6����?��d<{�l����?���8<���8|����J
N�8���~���~�k��C��}���;w.�~��t:<x�f������X��m��={���
D{@u�y��A��y���%K�`��a��=����u�V�����k�y���0a~��G��=����c�2����V��i
{���O�e��Y
�������G�Fjj��k����_�~X�p�h`�~.��[���{�����zG�A�����OZ��_�c��a������{mj����g_�����&�9�Ri�.{7�������}�`�="�FQ�&E��7�����Y
jID*�n��R�aa�!;{;JJ,���V��NW���{ �T�;�������AWL/���X�s�P��#��d��JwH%�7�HDDDDDDDDDDDDDDD��Zv�K�9t�������"m���@�V��������M�����H@�R� c���X�n]����	<==oooh�Z����2��=� !!AAA�{p
 V���/BBB����F���ldff��9p����G���um���f����]xx8�r9�j5rrr���[��srr0j�(��'DDD 88:����(((0���������}�v�y���Z�������>��7��suuE�V�������R�����Y2g�|������n��Kyy9���{�����'O�8��=?~�h]���

���+�������d�6�]���O
����"$$� @�R���k�P�s<x�&M2�����
����|�WUUa��i8u���k�7�|��S���7"##!�Hp��e���s/dVV���S�N����jMb����0���A�T�����]3�$�r�J�������j�S� O>��h�T*��u��@EE����}�������������������
\�t��u�R�p������3��������m�<��r�{k]]]
ooo����&��m��a���������f��[G��4u������!]omQZZjptT8�Z.����Acu��H�`�Fo0 ���:�p�\j��� �<
2�'
�Y�WV����

������k�}��=��q�Z�E�)�kQ*��?5�D����R��(�2"""""""""""""""��*�w�:	E�����\��� �;w.,X���[�'''�������~
�Z����k��r�;��s
dr�����a�������YYY�5k�l�"z��;w��3�������������vOOOL�0�G�F���j6'==��=�|�Mc����3x����v7;z��I`K&�a���3g"##��gggc�����m[���z=&O�l�����>�i��!$$�d��C��p�B���PVV�)S����Sf��/_n��1���[�nX�|���bbb����>��Y`/../��2���nxx�~0����������~�>�`��������G��m�g���&�)S���pCJJ
���~��r�����#�<���X��%%%8t�6n�����z����x���M��yyya���6m���L�`��}X�~�h��V6m�4TVV",,o��&N��B������;1k�,cp���/��"�|�I����v�mX�t)ll���h��W_����2���=�U�V��������u���8q"F����{���N�>�U�V���>3vw����1f��w�}f����������~;v�0�����,Z�������ov=������q�������d�����}�v�Y��x]���O?��W�B&������O>�6m�������V��/����*@ZZ^�u���[V�}��������s�a��a&a<�Z��k����_Fvv6 >>O=�>����;�=�)������?o����+�8d�����t=����w������bh���H�RH�R����&C{�P�eT��?�'������$B&��J���<�&iikv:)�������n~��y{�����f5�9�����Xo�����R���"""""""""""""""�C^e.�4iNY+S����\��:e�����������cA����b��ifs����j�*����g�6v�����#��C��-����=�x��1�@��u+��=kR�����Yw����>[��1o��F��������s�a���2d���Tw][�h���D�������0c���c��	�0a�}�]�]��~�m����}T}�����[E�s�D�;��;w�������G�����+fA�^�z�����[�����o����{�d�O<�+VX�O�m���?>����]�v��y�����=���n-�X�_|a2�5k���>��IG���0��������|�R�#F`��X�ti�t��h4&��������V�Z������c�b���X�l�I�[]JJ
:t����w#,,�d� �����s�Nt������y3���1a�����f���r9������������_�����O��cP� ���>��c�w�}3f���7�|S4�j9�S�w�a��&))	,0�6a�|���������j�
3g����3q��q�P�%W�^�\.��M�0j�(��x���b���z�j���k;j�ZL�<�$��d������M]<==1k�,�5
C���K��V�������G�c�����9�ZmWTT ''���O?����x������~sHG���2�0���S��hIT_������`�TE�T6Z�?��%[��'���oh��	A���V[����(/�������\��H�O�i��UD���C�N�3��I����PW5�g�O9���->�h�Uoh����}�|L���sE{5��53g���Z�;w�������X�f�I�j����^��z��Ug`����H|����qyy9��]kq�����V*�V;������@��iYY�-[f����`�H$x�����_?����������l��%&�|������
�
&�����G@@�q�������,�p����g����w���sw���C��r��j`�6???����4������P���?���O���������CU�|...X�~�Y`�������t:.]���m���o��z���M����dffZ�i��V{��1�$@��g��||C�����vp��wb��u{�������6����o��j�:u*���k����t6�m���HJJ2�������y�vxx8~��'����P���S��9s�C�#F���1c������O>1������c�!11Q4�h�<���5���/���C���������R�Dqq���svH�������r�}�<����T��T:��[�����
ddl����q_�6�:������o����N��V���`�o/���=�&��@5e�Z5~L��������S8Sr�Q�~0|6<]l�[aa!6o�l�����,y��7l)��v���O�>8|�0����v�z
5l�0����2��7�q��5;.I$��cu���o���o/^��b����R)^x��;PRR�������KmbV�^��f||�I����+W�����r9�O��w�y�R��y��:���t���!��g��9���j��l�2c���h������[�����^�Z��d���?�Ba�8Ap�������6n;y�����i�����^3����o�������������_}���������c���6�}��p������&���j~/(
,]�����v���c����l��Ng�t�{�
��V7���+�x�	��=�a��5k���O>1��t�R�!\�����t��{7>��c����x����f�\�z��k]�rk����o���_�1v����
��GC9�1Q�Q��X��z�|��iP�7l@�����wwGD�d�d��r�YY��\H!B\��:����w���2w��>���*������������������������:�Fc�=���W```���%::����'O:e�����2��Z�5o�/..��m����o��f��L&�����u��a�L�����K]�i��&��z>>>v;����M:f���(���
�~��q�P(0u�T�s���k�d2�A��$--
���3����->��b���6������X�?��ck�9�]�f[q�P�Z8�z�k�.�t:�x���h�����?~��n�5��^y��u�yyyy���7���������������������Q�)����J,[�:t���3�V�����x<���&�F��y���u��i�������x9r���8v����-22���gC���b��%X�z5JKKE����/����S=��������'N��W*��>}:-ZtSA&g>&j~
<==����OO�:?����d�x�=W����Sjpu�CD�dfn�F�ca�����8�/I�B�Vga^�I|�5~.-�G���J\(*
o�+*E��.R�#������������������j�	`����:~��������vvv6��_���#11999(..���BYY�����������_�G�ERRT*�����0�R�,�1b�I���S�b���x��G(38x��q��}{xyY��s1���Gnn.��nU������k�C���]��w����W#:��-�������'��[����c�L:h���!!!v��1j?�C��\.o�j��^�z�4����dms���������������N�����QXX�Z
�Vk�8k��������z��m���� �qQQ����`��>���qC���M����3;�#�S��S�N���j5����~����;@����/����G�{�n�����|�2��cr���#���;��6�=��^u��A�?������������[oa��=	������X�r��p?~�����?�������M�}��g1�T��?��#���b��}�^p�c���Ymt����J���R�?���p�T��Re2��O�Biu^P�|�:!����������F.����Rt���b�="""""""""""""""�&!99�d\��S]jwv��J��#�<���p<������������:{7�{��JMM��q����{7n�����R�l���Z�'NDll�q\RR�g�y����������o���6?@u2??�8>{�,A��7{L�w��r����!���<��c�|������7k�,�s�Q�#��u;R``�M�j7���8�ck�,��?�w���}�b��������������:{�c���~��Y���a2��\�>?�����&�=��b�eG��4U���h���N���~�
;v�0	�&&&�����u222p�]w���[�j�;v�����!�k��=���7###��k8p�F�2K�����G�����Tj����o���)SL��u���x����?�l�J����F\\��'W���b���8t�P�|L�����o����:M�4��t���� ��\�+z�u�"r��*z��� �2��P�{��&�����H��6i3�����C>�s>��;irN�����		qJ�[���.�LtN^�z���{�lu>��11����ks�������q\h;��Q�g��X}��vUi�j���O�6�F���DDDDDDDDDDDDDDDD�Z�.�>�����9�����O>��`ph���Zm���#==����;|g[�}r�?��RSS��l��.���c�	&��7�@III��UTTt(�����K�Op���N_c��i�V�\)�������7��iii����l��:9���"O���]I�T�u�v�]���>.��:t��k��X����+�kw�]qN��&M��u� ��}���u��a���YYY���'[�� ""6l@|||��%j���J@�x%�������7�l�m����������o�������{���b����������������W[l����������L����������-��666���n��w>&���� ��]2�\.GRR�K���!�N<IM)� ��3��A����	��~��<<���� EU��m1�0�x.Z��3�Z.�``�F��`_E��DHDDDDDDDDDDDDDDD�-���-��+5��u����t:\u�U�������wo��3���*���K�^������
�?�'Ov(������UW]eu��������/��_�5k�X�9`���III��}���/ ..Nt�V�-[���GABBz�!��������WF���s��������Eb����r�u�]�vQQ��[g����_����*{�~���f��|5��d�������-��d2���'�x������[�]�����D(Gu���;���>�����Gc���V�\������p�W�����mAAA������"�\A����4
�����c��>|8���0a�������ZT�KNN���[k�_�=��{�!!!O=��y�s�=���g�[%���/������^z	,��&�Hp���b���������
��������%K�x�c��C.�#--
G�����Z�J�HKKsYB u}Z�����������#�� �2�ee��l���1�
�QU S����(��d�u���IR�uH���0e%���������M�ON	M����.����z����U���(o�!\��������������������-j�������/_�m����V����)n[�|j��M���~�����F��744���{�����s;**
+W��W\���������/���Eu���{���?��#��h����?�|�I,X���m��M��e������Xp6���7��������ZU�j�v��}�b�
��iM�Ruj�7�h4��:{���F�F�$���;/���9���?��i�����|����P(0s��vc?_�$[o��qw'�>��E���)S��{��G�m�su������\Q)��Z�~�aL����)))m���s��������g�����owx���&\}����{�y���?��[���;%N��0i���:u*&O��>}�X}P=��gg�����7������Z%��o����������8[����^�J�k��W^��
7n�x�	��������>�e�]f��|�r<��Cm�vw�c�����������������9�������|�
��UT.Y�_�
�L�Fq�:�L�6�M�k��~��	h2I�3I�'�8?��������<�s�qyx �k���K*���%����*�09��y����������������<C"H��yl�e�&��(�=�x=)88��]^^���������W_Y����=��������_����J����k�I��h��c�����c�h�"���`��=���_���_�����}O�<�Y�f������u2��d�����


5'��L&����$9%))	�_~9~���������|s���9�^{m�� ���|���N��5|5��"##���7��������~~������b��QRR���w���������qN�5={��h;4^������7�pg����G\t�EN���������={�o��.���9_}��������'�9F,Z��b��l�����h��S,^�B;�&N���c���uuu���o����D����?��m����u�<�}e�5�n��I�E��������������K���_b����Kp��Lt���;�����]]�F�?��>4jQ���;��o��Ns�z}���7i��v����:t����F�E��A����G�u(�����Eaa��}�W��������Br��G���%K������~���_~����mQ/''�iE|Y���-�{��q�Z��{����������Z�{�=�W3ug����qw;w��h��3���=�}�b�k�����-��'��SG�)�N.�����`�m��fN��L����
�&MrExD61i�\f���������q&L�8�[}�8����QV�wbEJJ
��o�Z�c������]���/�\���{#55����


���]y���&��f�Ur����hwS*c��;_0?�$%�_r�o������K$��!a�6��V�21����������������,��E Z��-k�(z �/�-ky����[��������EE���i���v�������+/�.P���)%%���8�_���$9A�����n���u�V��\.������]�v9=���:����9�`�V�����gn���0�(**��u���{��e���C��������~��GyB��|��M�jyswo�����M�Z�3�cw�w]e��	mG�?W����krrr,�QQQv�3�L������w���I$|��'�>}�3C$����%���-J������+�U���k������0i�$��IZgJo��


����1����_�~0`bcc�Tj��T*EPP�j�����/6���]�[J�h��h�Nuu��+H�T���3l���)���F���+��
D*��ZR����~!CDDDDDDDDDDDDDDD��p�:#����3f�E��u�����������v'Q�N���tv���;���/�k���f��q:���<(//����+��h����.���������Z?'����P]]����R)���cn���`���X�r�E���9s��vY.�c�����^�w���bccq�������/<����9�VkQ=��9O�82������_p��)������8�����>s��E57O����K~��'����������>����;�`��N���L�#�8z����E���m���'����u��1c�^'66III��N���c�D�u�c":���			HKK��a�0|�p:����a�����>}�X������b���:$��It�F.E������������I���K0VU&��7���Bg4:}]o'���]m���w�""""""""""""""""�K���^�4���K����������q��������X�h�]c�z�)��=���,�/v��i��d��NR


�hgee�=��u��V�����z�j�����	!!!V���3�������~kU��Y�����]��32_|��][[���.[o���E>��|��G��\.��Y���o��y�W^y��t���:��EEE�������3�<cU��=�9GEE��[n1��F#���n}�����[�~�a���x(���sN����'�|b�m��i��[�p��g��^{
��{�S�#r���%���v��o_������|�X����H� �J�����J������r�����1�L���wg����P�,��[�Few5Sw��?��y�rA���XC3�g;�GkW�R �_!�W��#�F�'u_�N��4�%s�KpQ���w����gq���o��nU��>��"�=R�#G�]������-ks����1m�4�
�HLLD@������UUUv�MHH@\\���{�n|���m�IOOw�"�����?������������C�Z��'�x��6����[�f�����w/n���6������������e�Ck��Y� ����d6G,Z���5���_�����8f����n�Zqqq������~��������Se�|'N���c�m�V�+��������J����;��gOs����]v������I�\����.x��{�����m�y�����k�9����	�l"�#.\�������/�r�-v(��g���n��v��!##W^y%
������~�)�.]js
W�S�q�����<�����9r�_~��Mq��7�9n���x���-�-Z��>��C�9���%Z����wh|��srr���l�_SSrss������zLD�\��YYY�W��'��]o;�*%@��H���\���C�-x$$�f�rKp��{����������V�#""""""""""""""��(�*\u�S�UH��*�(��ym���=w�}��m2�p�w���B^^����������q�=�����^g��������Cii�����r,[���
Cnn.A@jj���H$L��wBfuu5F���K�b�����q��O����q��9/��jkk-����������q�PUU�Ri���n�:�?}����E��c��������j�*�9999������E�~���q�UW��uuu�>}:���:l��I4�������x��1t�P6�|�M��a����k��,��U��~�z�����5O��������b��+0t�P|���hhh�s��i�X���
�e�]��zmUi�;w�Cs���nQ����#F�����q��	���a��s�=HLL��?�������������"����c���?^x����9���X�z5n��6���`��������F�mn���a��qX�j�U�����o�}������4�*��?��z�O?��]w>��c���/��m��Y�����U���U���_?|����	��������0a�>���mW�J�����d��c�����-BF����%%%X�v-���^���a��Y6�����.����.RRR0u�T|��g8s��hr�N�����q���c��!�UA��o�	���g�O?�,��v�����/�������c���$�����Z����G��GEEA&��?(�FTTTX��8����n�\���H��j=g��mmw�c"��T���8�%�sss��O�E>+�F��?�����d2�������DU)6�J�G��9�`���o�.�B������#9@�,�D�z�'k�7X�������������������[��E`j�-���[4�;=��4WE��0�'D�u,[�{�����������7��[o����d������YYY�1�����E�X[f���w�}�\��d2a��eX�|9z�����`TTT ++��<n���W�z��G�f��5�V���y�f�?��~��������\�G����'����>���T��j���!;;�������?���/l^�'����x�����s�A*��G�

���������iUi������9%	���KL�>�\��d2��~�?��B���D�������������x��1s�L���(//p6��V�E�a�����l/��2���,��������~~~HLLDhh(��������u���#))������`��h���|����>}�9���f���kx���������������0���Y���>�3g�4'����������O?���8DEEA���!//�����9�����o>����nB@@z��
�D���|���}��Z��_|�!C���Ndd$����c��cQk������|���X�|�y��3g0k�,H�R$&&",,Z�EEE(++�;>wIMM�?�������DXUUe>����#::j����(//���p�9��ZZZ�v�Z�]���������dBMM
���E��
��?�S�Nms���7[m��u+&M��p�w�y'V�\��8"[��G.Q_o���Z���� @�R������b����-�]��ulb��mw�crTii��'��%�������)��n"v��R����gQ����j9�����NoD����/��I��Xq>�Q�����%�c!'qP�j��U���f�|2������-��{+d�b_���E4��I;7uW�,LD�9<y��DD���0���L�=8����*�/7������q�A���=z��pQ�DV�������+���={��M&233�*�b���U����X�z5.��2�:u���h4�L���������g�v��\r�%X�b}�Q����5k���+��HX���8z������������/������g0���#Z�����8�Z������� l��O<�����XT��j�6+;�/>>�����P|��w���m��&2�_}�.��,]���u���,^��%�H0w�\<��S����nH:x��K.���m�
7�`Um����k7�tbccq����a�)((@AA��"�����?�s���x/������������vx�7�xyyy��aC��}�����W/��?�����`=Gy�	&`������[�{�n����rs�-� �{\>�3�)�TWWg�OaK�������c��	n���u��G.������R�I���:m���������;�`��%��#==���������=�OQ(�;}�4*++����� R��h��=(jqmr\GH����d����d`QE�����|�8����������_t"���U�F�=	Uy�+B#"���Y���sx&"����<��a""��1��k����t^M)Uab����N���ti�����(z`P�H$���0B��;v���_�o���"�k8�R)���Z��������������w�����G}���f��F��%K�t�*�9���?q�UW���>���[q��	TWW�����j^����{�`������h:Ap�e���^�����-==�W��o����;w�����W/�y��x��G���L&��e����K�.��?��nbWRR&O��n�'Nlw�q��������/��o����#(//GCC�WTzkM������Y�������l��^TT�N��{�����f��m��'�Jq�]wu$l��}��������O��[o���6_�R�#G������;���S�v��_�S�N��w��|�f�L???�7w�y'n��F7F���y��HMM�O<�?��St�R��n�
�?�<bbb:��F��o��������o���}�������:���x�\w�ux������_[$U��+��s��q(���z�����t���Ox��7�u�V��+�H�R�1W^y%n��v����q�9��������������q���6���������g��n�B�pS�D�#�Xs�Z��e�EF����m�8q"6m�dn����u��iBB��������_|��>����gn���;�E�������"��7Z��������w:i�?��:5y�����YW�V�;W���5����0(��<&m�GPV��j�J�iiYn[������d����l(��m�x�L��^��F	=�N�D��N""""""""""""""��,77=���}����������z��Q�{��L�5�7T��p��J�E(��@k�;�K!Q"�/
���R�A�_�#�MF�[�nEFFJKK�P(�����c�"<<�)k�����������QSS�J���x�5���Q������������A�V#99c��Ad��uA�08~�8N�:���s��F���84����^�d2����8z�(���Q]]
�B��� $''�o�������:��`0 ==g��AYY���8���}��� �{��M��S�L���k�:���;v�@II	*** �����{c��A6�:xZNNv�����RTUUA�P 44���4h�K��Z_G��������m�6A��"88���3f���=��������(++3������o_���R���a����;w�D^^***���������#55iii��uNq5�V�c�����3(**2?��� �O�>���m^O�Q���k��F^�u������N,�l��u��Qg���#44T�/  �I{d�A�M�E��Vi4���d�����!'q@�j���R?�U�Zm�[b�}��%h����I*CsX�K��u?�~����L&ZL-0���
2�y�m�,�D�q��YJp���\y��.��YBCC1}�t��/�J������ekg���c_"�J1z�h�=��s��G��s�:}���(��6]%11����������U��#���{:�N������^��9�uNq5�B�%~�D�b��D@@�E�V���455�9�;�q�Z�x��.}��i��#F�@ZZZ�cq��������#F���2��$77���V�e2h3����#uZ�6��&��T��n��~UU?����-k�H[�xx�,��_����i�������uF~-o@����t�1��OO��������o�,LD�9<y��DD���0���L�=?~��!�,A�'�`�"����r|����v\\�L��������0i�\�u2ZCC�C�M&S���a2���N���M�s�crTddd��� 00�����Z�����YJJ
:$�WQQ���x�(M�c2�PP�$���CTH�{rPKKTU�'i�Ea'�������`an6K��$�9r��(���:��F�u�EQ<�9�����<��`""��1����x&"����&g\FDD���o@������{/d2^�ODDDm��+��+�N"���wh|II	�z��-�Hn�_xx�E�^KKJKKZ�����m+�]������!������B�%7�o(���^o�K�����R��^������_��j����b���
��mV�;U���^��������������������?~���������{������`��Dj�e�Dnn�C�[�����Ri��J�BBB�S������~�zLD���G�U'�������y��:�*{���?V)P*����R�"a~2,M�as�wrK�������N.�`@�F��`�H>""""""""""""""""""o�����7b����������Oc���hj����|�f�"""��1i�\�u���c����6���Z�|LD��P(#�g4��LR�e4��e#i/�_�T���:&$d�����������;��f��-qy�� ��_3Y�M�hnqsDDDDDDDDDDDDDDDDDDD�+..��I�0i�$\��x��PSSc�OJJ���>�������0i�\�_�~����vvv6�����m�6���A�l���o���v�STT���ls[.��o������19Kll,d2�h_II���_��*i���FbY�F��h:N�NA@@j�;vB@@��)�^��"���g��x%���1y� `p�x�=�[Q��h������������������:/22k���Z��t(DDD�#��G.��h0n�8�m6l�k��d���-�M�:���W_}�E{���0�Lv��~�z���	 ��;���d2��������sc4��lU��
@�Z��h:'"�RH���RD*U#"b���P��\������J����%1y��
�6�(n��9"""""""""""""""""""�������X�`�9�/���!�a���5�\c����k����7#++��������#m�?f�����������e�]k��i��im����D�LQQQ�������D]]��#"ob4��]�,���_	?�o}T�JU�������J$
��^�T������.*D��`��\���"� `hX������v'��CRRL&�������K/����O�GDDD>����'�r�-�X�����?�i��6��L&,Y��b����!��~�J$��5�b��%K�M������_���7�tS�c�����I"� >>�fnn.�g���F-�F�d�d�x���S("w�S+��T�P(������q��Q]�L�K����/�W+�����6� ������������������������/^l�hIDD�M�5D.�|�b��9sPXXhs�K/��?����

�����]��'�@@@����`���6�/((��9s,���7��b�w>&"g
����h_]]����y���&��2A@������I��@B�L�q�|

���l�X�r^M�� �~^v�48%_ ��Um��F~IBDDDDDDDDDDDDDDDDDDDDD]����m��a���V?{�������Yt��7���cm�����#::�������1c�f�����������SO=e1����Bhhh��%<<O>��������H�3����1f�dgg�������Gmww>&"g			6�Ym�{�M�mh�KPB��A�R���BL�t(�q����lL&����\��BD�L��E���9��h����?�uzd�H%"""""""""""""""""""""�e2O@�s���#''���JJJ0i�$��;��+W��9644_�5.��r47�M�����i����dTWW#77��b��i���c���x�x�	l��k��5o{��w�� 11AAA�����(�R���7� 88��u�����)88AAA�����kjjBYY"##=yJ~c3Z����)���q�:ju
��r���@ss1���Z�>�
E�H����^_o5�V[���C��z������P��[�e6i�4�Kzw>��W	���Q+����I���������������������������\�I{�r�����u�p��7�����������s�m����?���E���V�������W_��dff��	���~��.���u�=&"gKHH����E������WW#���r�'k�:�/S(��P\0�L0�Z`2 R��||V��QT�������2���:!r^M����Y������� ���#�
�J?$(�]o]��^o@FM#��m?�DDDDDDDDDDDDDDDDDDDDDD�����^z)�;�������6�<x0���;|��P(OQ*�����?|���4h����j5x�;v���wx�}�����j5���D�t:����yJ�����$*H
����A�D��T���"�Z�N�Z�Kt���EE�_��?9<7F����<|"�c�b�EC�a�u��-���\Q��J{�Xvv�[�����;���e��a���8~�8���������8�9�z�'I8�������_���Oc��](((�N�Cpp0���p�EA�Tvzw>&"g���Gee%L&�U_aa!"##!��=�Sn}3�/@�F��`�Px�x46f�d�[���C``�T=�������We=�u-V}YM:��Y��n{��"�O������m��k2q��B5���������������������������Gn�R�0q�DL�8��k����-Is�|LD��T*���b�>�����B$&&z 2r���&��*��*?7G�}��@���BE�V����M���A�]�8X.�k}�1�P�h�G���*"���������F�d��U�H
RC!eh"""""""""""""""""""""�}�2�������T*�+..Fss��#"w��(h���%iT���#�N��C!�����t����������h�9L>����3a��\�� �h��h���z7GDDDDDDDDDDDDDDDDDDDDDD�L�#"���r9bccE�L&�����Sv}D��RTn���	����������D��z�"F!��i���3E���\��\"�z�������HDDDDDDDDDDDDDDDDDDDDD]��������h����D���hhhpsD�.YuM��dRD(�_���RE�L&���hw� �������oA9�w�*sJ��CD�&�@e��#""""""""""""""""""""""r>&�uSR�����rss�
�K����&�h_�FA�������� �'3���Dcc����a��5&�f��'r��M���VC)��Q��Z���9���������T*��������9"r��z�*{���=�&�i:�fY�&�L�'�-��X�x�_n��gu8F_"�H00T���	��
V�#"""""""""""""""""""""���="�nL�v���L&7FD��Y'��$�!�O��h|Gp� �������T��z_�s��X�j���IA9�Vu����@5dR����&Th[���0i����		�F��khh@EE��#"W�k���Y<*Y�� n��w�m�WV�@KK�	w�q{L���GN��A�~�>_'�&~��}��n���������������������������GD��	������yyy0�n��\%�F�=H����oR�z@�I�3��(/�b�<�{�!N!��k���3�
���hT�Q�1�Q��&��#""""""""""""""""""""""r&�4
BBBD��Z-JJJ������P�A6���RX�8H$~�}

�����������(�ia��l�j�����QmooyL&�#""""""""""""""""""""""r&��Ym���z������U�ZP������d25BC/��_^�	&S���KB5�#6�f�#'sQ�7t(F_��V"B)^u��Y��FV�#"""""""""""""""""""""���=""�T*DFF����z�9"r&[U� 9@��H|_P�@��E����T��j�]�<�3q
�����<w���1�
A04,�f���ZV�#"""""""""""""""""""""���=""2���$�SCQQt:��#"g0�L������#@.ssD�M$���h���jZZj��G#�by�.?+���u�����+������m�v�������������������������������111�}F����n����R�Gm�A�/Y���h��*M?�>�����-v�3.T���a6��u"uz��]W24Lc�oe��GDDDDDDDDDDDDDDDDDDDDD>�I{DDd!&&2�x����R45������o�.HP�7�.$<|,$�
q

g���i�<���E�\��@��%�;��W�!��k����S5��a""""""""""""""""r���l�`��5k��C"�f��e������{lss3�}�]L�2=z��J���k���.���x�b��u_�_[�l�tHD�d�YDD�m�d2�����|���HMMuoP�a&�	Yu��}1*?�dR7G�uH��������ee��R�C"O�;'@&�}p��3���U��� �
�t��lHX r��!VS�@ez� ��~DDDDDDDDDDDDDDDDDD�>|S�NENN��C!"�rZZZp��I=z%%%���C@@���0`����^�Jm`�Y���DQQ�Z�U_UU�����h<9���
z�h_�F��h�������=����O��AU�n���iw��C4�������:��-#� �'Y���;���U��F�n��Pw����������������������_~9���<
Q�����o��6l���[���ds��� ��1���C����%�
�t��D���x��9990���a������(�����	""&�����
������I�A��O��P����:�/��T�;\U������������������������l�A�?�/�tH]�������=�a���	{���x��W�v�Zl����3s�LFI�Y�f��8�egg{:$�RZ��F�BJJ
�ql�����=�����o��������^���d�����HTXX������`�W__���*���z 2���dBV����8�
)s��A��F`�����3�(/����k!6���?�L��}�q��3��_U���`\�����Z.E� 5�V[wtFW�cXx�}�DDDDDDDDDDDDDDDt��d�����r9$ju��^u7������Czz:���=��jii��]�D��J%bbb����>}:������0�|dee����vW��x�>�			6�sssy7/W��C���d����TaaA"N���p��y.
���8�_�<z25-���+�@.���Xu�7GDDDDDDDDDDDDDDDD��|2��/G����5�����1�6�F#g�l���������V�\	��d�IJJjs���,���]w����(99�/��m�P[[���L��������������?$&&Z�y��w��[oy(b�FL�#""����$�������R7GD�����'$(�M�&��>�fy��-v��T�$*�D���-Xt��C1�
�T����}�	+���R��-��1Y�������c'�55�kj��c'*>�Y�LC�����ELD�y�������H�����.������9�E�a��1�����T*��1�������-��y�TVV�3d�bL�#"�6�Um/??�^y#����z���x�r	?8�F�Je�h�^_����v���J�F����W���XQ��}E�5�R�����F���v�A""""""""""""""��@_U��GC�}��i�^��6����{�C�c����rQ�DD��������@���???�]�[�n����!B�cBBB���?B�V��UWW����se��Cx�>�I�V�,�������"7GD�(h�Bg4���hTn��{�H������;g�����;x�D�[�n��\"��P�j{&�Ym�����������������5�<��i�Q�n]���]�Y����dF�;u!���m{�K���6???L�2��q������;-����o�
�|��������GEEL&�$���"DEEY��%���QeO.��ts4��B������9 �kDY�&��^o�$Sb����M:��b]�=]���%v>h/���������yf�5����*x�!""""""""""""""�5�'O"g��0��8e>}i)rf�D�g�A�z�S����F#�o����C�T"%%c��EXX��������#Gp��ITUUA��!88���>|8��z���R9rg��Auu5�z=BCC��#G"::��kc��}���Fmm-�F#����������7��Gcc#�m�������B*�"22}����!C���&'O���]�PXXh��1iii.]W�z�����Ezz:JJJPSSc~?\t�E���p�Zp��:t������Fxx8n���5�����oGAA*++�#F`��A��=}�4v�����B����X�?qqq�|T������,=z�������L&Chh(1j��N3]����8t����QYY	�R������a���������---��};�9���j">>�\r	BBB��rss�g�������
AAA��~g���>z��c���w�1�sss=
y&�Q�
���E�� ))����(�����f��D�2	��q���1������h�������h4�����J�F�\��4��^���
S#�1)��/)|�T"`P�[K�E����bR���0&"""""""""""""""��WU!o�=NK�;�XS���s���G��t{Wa0�|�r,_����V�R��]w^y��_��~|��WX�~=<�f2QJJ
�����s�B�R�9����%K�`��%6�m�������f2��u�V|��7��aN�<���^x!}�Q�~������z��UX�|9v����~R��������"44����m��^x�6m�V��'22��{/����Fcs������?���������h�",^���x]�u��$��\��g�6�?����5Kt���l$''��w�y'V�\	X�~=�z�)���GtlZZ�.]��S����Y�������YYYV���~'�g��x\����2�X�r%�/_�#G���#�H0b�<���v?�����?�o��&������9��0f�w|��	<���X�z5t:��<o��6F�m��y�f<�����s�U� �:u*�|�M$$$��8��/<����X�n���{l��	���6��J��8q".\hu�o����|��6[KLLDvvv�s�����W_�����!//��~j��&M���sq��W:�H��j��+���7�@ee�U�T*�
7���K�v(^����w��|�c����#��g�y�\s�C���<��Z'Q�8��.�.�� ""��T*�WRRbUj�<'�A��/!R4m�E�'�*6�fy�������=l�����y�n�;����Q!�O�K��F-J���t$"""""""""""""""�T������dn}i)J^x�%s����J�3���M��&��Z�
����^������!C��+�����&Oeffb��y6lN�>��z5�|�7o��V�	{p��a��5&L@���Y�V����7�tS��
���~���X�h������


����p����_~�����$���\pv��mW��0k�,�`������q\~��6��������k��������������w�m3a8���s�N\s�5����PWW����Z-���z�q��	{�X�z5��U�V�&�g��/�������,Y��'�&�g���Y��#G�u��U��^|��������_����=f�_�&L��>����N����HNN�+���f�p�����?b��)����{����5
�>��h�p������1l�0�������k�.���?����=���s��=�6m���444�;�+���~~)((�h;��1�6&��]d2����&�����>�uM��R	b�n��{�h��T��_�TV����9Rb�������x�T�h_W 	�}����u�%����������������<�n���[��5j��E��-.]�W���a���V�1�  ))	��
���U[[�i�������#v�w�F���T�1C�A||��>�����c�N��,�8CBB���f��c����[q�����I������3�*�8[�n���5j������7������\r	V�Ze���G:�
���S\\����c����I�,X�W_}���h4����
&��}��g�����3�veeea��1VI2�)))6l�h��_~�&L@UU��k��5��y8��
<�������mn��&�{Q�T"--M�yoii��3p��)��/������5

��0h� X�-..�u�]���������P������c��Q���d���o��{�����$?�0���>���[l�J�HNN����q��v�Nuu5.��28p��-..��
C����PX^KZ^^�k�����v���O?a��	��������g>o�������O?��K/���/�<z������}�x(�6L�#""�EGG���O�������(���`D~�����%$�����?��������5��T�7����	���
���n���
�h_I�����GDDDDDDDDDDDDDD�*>��-�T~�_���������{���� ��Dvv6����{�ndee!33��{/���~<���k)
�t�M����������Z�8q�v����{������r�������5�+..���sm��a�l��������;����'�3p�@��4
f���o����������c��s�N�����������/����`���G�b��m>�w����nn�d2,\����())��}��c�9r���(..��U�0s�L�T�6�6����[,~�x��WQTT���<������Gyy�9�����F�z�������{��e���|h�9�9sf�1wU��'�.]
9r$��_���J9r�w�FII	6o��>}�X�{����R�������-����o��J����[oEnn�y�L&������3g�`����������1g���{�������P����+���+��a���o����}�����;v��YXf���N���X�\�8v���y�������`����O>�$�m����z
0|�pl��8x���=��;�X$C;v����C��x�s����G}���;jjjPPP���c��8t����p��A����J��q�|��h�\~��������-�>��s���/��Bt�+V`���RRR�r�J���!33���8t�JKK����?���Xl�G}'N��L&��>���O#??�w�����QQQ��^{
r���T�����^hw��G����o�HB;v,��]����y��������|���(�����x��Gl������������~k������P4�md��BDDt�D"A�=���)�������4L����fmK����Z_�P�#8x������PV�;��n���2"8��G���2���N��� 5B�]��� ��
��4�}������q�����������������5��@��k(��q�4gd@��+����|���->��3��1�j���d���{:t(���dgg;���W^��3g"22������p�}����o��I��	hk����c���o_�1�]vXU�III1��k���x����~qqqx��'p�-�XT#����h�"�����k]��>����m��n�7�p^�u�F��������y��=r�H�Y�F�9�H$�����a���7o����I�=��U����CE�		q�9���f����>��"�8�^?~<���O4�������[���M�����N���-����k��l����k��������W��+����g�����1b���f_�5n��L�>���KJJ7�x#���K��4�5��9�������M�6Y$�g����'c��
0`���7����p��A�F�p�
���/-����I���?T*��{����/������|�7>����.��c�^j����;���k����S���������k����������H]t�E���9r�*I��n���nU�����x��3s�����{�������	�B����^4�K�V��GEtt��9}���x����~7���z�r�-	{K�,�3�<#z��F����sq�UWa��	���������<�j�+��������(|�������7a�=""rHDD���E�jkkQS�u+~����&���2	���U�uBCGC*U��57�����s-H�AO��x�:=�>U��}A�������R�GV��������������������2����x����WXr������c59��Vg�X�&��w���?�!��w��s�ZU��G�~��M�;_HH�������0�\���u5t��v������?���njj2W
���a�w@@�C�����!�����W^y�������?���s.�H��oX$B}�������;.7l�0|��m&EDD��g�����/��:�v���_|Q4a�|s���}��g�m��e�����O?�T4a�r��|��U���.���$!���S�N�W�^���Om&4��w����Ts����(**�P������c���^jm��I	t���8v����;��_DKK��}�������������Cd�z/��r�U�n��v�9��.--�������~�#G�����{/�}��v�%��������8g�z���<���o���_�b��O?m�Z{�~�^9""r)A��'O�����"((�U�<�Yo@a�V�/9@���H$~���u������?R����TR	V�%��}� v?��J�05"WD����/�����WQ��$|��j).��nT5���/Q���Y������������?�����T*�d��������������\�w��1bv��	����h������1'�l��<�����W/�H$	���g������^�x��j�I�R,\��\�������n��f��&f���nI�����{����sn��&������}�\�]~��7���������7o�]c_x�|��ghlll����GZZ�]��|�I�T*����n��F0���������{�,X�n� ���k����������\��+�*���3��������o���EEE���o�m�D��?��i�����������}o��f�������Y���7�0����/����1]x���6m�������a0��-]u<��/������[`0����|��Q��a�=""rXpp���566�����d�7�d�/Y��?v�s.�J� �g04��r��s
R��x�w�����������~H
On�k1 ����y�;v@�����S�L�;�+""���>����l�������fG$%%���V��W�����O?������g��e2n����O�8�"q����rJ\�UPP.��r��


EB������,�)���E{���vW�

����-�����v��J���������o�������o��]w�]c/��B�vnn�}�������\{����-����J����e�]w�uv%��A�,���1HOO7����j���8���������}�]u�VZ��^{�����h���_:T=��>&���A��c����<�b����2��D�k�R�+��O�'"".���]55����=���1��/^V�L��S�	�'��V-��u���CDDDDDDDDDDDDDDD������������+))��o���o�^x!����R� ���������566ZT�q���l���+���������(
�8w�����m��~��I��o���-Cuuu��4�L��m��}�����-j�aaa�����;C�q�zTdd���555��!�W��K/����'N�h�����>}�@��8�VkC��k��_���/{�Z�����/8���azz:�|�I\u�UHIIAhh(�r��qY���~���FZ':�:�}��av�{���}���u+L��K�8��9��;���<���F#f��aQ)X*���/�@�^�<y#&�Q����N�Cqq��#��Z(i���%����<��/�����5���w�?����J��O��q?�V�������������/��d0�Xu��#""""""""""""""""�.YYY������J�=���q�]w!..=����K9r���hnn�kw\��������#%%O<����[�8q���������7�o�}��5������c�!**
�'O��/���[���|g� +++��c���&��SVVf�����q��d��V���vgb�-999�84~���m{������v���oy}�����z������9����0p�@�9/��~��dee���
z�����<�9s�����7G8r�9���~�['�=����G�L�b1�����Ao����o�5�A��~��S�z0*�VL�#"�KHH��VPP`��er�,U� E�rc$dKh�(�d�wjn.B]�Q�����	��8{�d>*t]��7(T����U��Xm����������������������������9�����O>��`ph���Zm���#==�������vkm%���r���OHMM��a�,\�c��Epp0&L��7�x%%%m�WQQ��8��
��|�R��t�RUUe��D"�Y�����p�����
�b:��w�w��c����������%�\�C�ux
W�?Z'�9���(W<��:���<��.\����b��e�0{�lED�N�����w)�JDFF�~h2(((@bb�"�~�������dQ��
��H�����D�����Z�R�}I�����������,o���S�x�_RgB�Jr)��qT����h���z
���<DDDDDDDDDDDDDDDD���������Q{ZW�i�N��UW]���|���{��%�\���T���A�VC�RY� ��W_�������***p�UWY%0c��E�^��J�Ri���>jw2IJJ
����7�x���


���j���e�l��'�x��{/^x�h4�7wE�(��7����?>8zl��uuuv���y
#Y��y3���~�d3�L��/�#G�Dbb""##�T*�P(,�N�4�-1�~��e]gr�����Ao���/���_��������G�PD���GDD���G����~+..Ftt���er�Z����>V��.ju/��'��1���hlBE�6DF^f�\J�+�p��S��gui5�FT����N���� ��-F�;��n@Z��2�"#""""""""""""""�N��(����c����������j�������;�<:�#���:�������

�7R�����CFF����+W��+�hw���_����^x���P�������c����u4����O>�$,X�m��a��M��ev����&���t:����X�~=���O�
N�����/V�X�P<��T���;0'�:zl����dC���G�H��2e
�{�=�����q���z������z������������)S:5gJJJ��9�<�M�~�m,\��b��y��d�ED��I{DD�)r����VwK��Z���G��==Y��U/^e��%�7������Um�!��Rm�|C��GB$��-�"#�����>�)�R���J�;5�M&����.��HDDDDDDDDDDDDDD�Q�L�q[��p�&������I������r��������������?`���v����t(��������V*����_�L88_G��H$;v,���E����{�������/���O�6�{��I��5?�����CL&.����wu�WCtTG������s���hDUUBBB���x��X��edd`�y��������~~~��u��#44��]ZZ���$�����%111n9�8�<�->��3������v�]wa�����|���������Y�����[����u�I{�
9�X�VW�����a6���~��$^:\�c����_)�W����������
��G��5��k��9""""""""""""""""�%��]_�*���MZ'�9r�����k?�����w���
�;a�=�P\������Bs��+��;a���	YYYN�C.�c���X�d	222���oC"����_~����mQ/''---N���)���K�������2g��3-�th|��[�Gd��;wZ����cW����p�2���������%99��}~��;u�<�
���;�u�]U!o��&|����J ���I{DD�iR�qq��L�����h��*m�u��I)V��V!!# ���i�%�����R�D�i	�����SY5��Vw J�&�H00$@��`�u>"""""""""""""""�e�P
�����
������7>|�E��?�ph���WTT@�������T�����@AA����Q?���SRRb�v$�����%Ir� ���m��f�}���m�\��.���nll��]����q���s�	����������l���5���i�&������|D�������mg�!c���h{k%��L�0������
��=��_~�m����`�6e�|���V�+"[�J!""������{�9������usD���*{���=�%��1�fE�_0��P98�&D��_���2]���Vj�j�T��L]*�]�1���9s���\������cQ�h��u����klii��		��t:��1���;v�j�����h�u5���Q�'�@yy��>W\q�E��7�tY<�?��<����������W^^�	+�r�%�X�?��s����TUU��~��6n�8��F�KG��Z���Cku�2q�D�d2s��_~��S�Z�������s���3���_<���9z���������9a�|��������|
�����)$	���m����x��w|��dBV�x�^���f2y�:��)�}F���1�_IQ��O��l1`AF~�{�$�jl���`�0������)S\�F��W#�URJw�k����nnn��E����SO��8f���s�N��8�p2\hh�E;++������m{������X�z���tD������}������`s��o���u�\���svv�K�p�!C�X������=��shj�}���n���HHH0������[o�5��g��Hv;v,������{�����g�q��&��sHTTn��s�h4������ht(O�?�E���FMM�����=�AO��g�N�jq�5j��Yc��
�-L�#""�	

E@@�h_CC��wl"��k[P�b�K	`�=_1� �\Y[{MM�v���H�"-RA�]Y
V�Vw J��3P� ?�h_^�%MZ7GDDDDDDDDDDDDDDDD�D=�d��.�[����t���f��y��/"y�����_�9���>�G}d�R�#G�4�����l��6��>}��MCKK���g���]�������*��&$$ ..����{7����6����c���x�����?��{���*��{���V���'�0��F#n��V�Y���������o���}���g�wyy9�l���0k�,�`��5k��s����.��t��7������G����UI�R��7�b�������9���?�J�}��G�uc���h���{8}�t�c��}���k�u��
8�����B�P����n��h��]��g��'��~���CFF���J��jKK>��S,]����8�������Gq�W�����m��A���_l^#O�&����`q�����|���,�N��?�������A	i����w�L��gj��PB���'O��L�����N"f������.Wa����������������W�BB����9u^IP�?�2/���i�G���w�mn�L&�q�x������g�ovv6���~�s�=���$���9s�E{���x���PZZj������-��a����A���j�:�'N4����1j�(,]��W����-~Z'���s���x���P[[k�=??O?�4�����*(�J���u��a������/-Z�;vXT%;���	�V����#���c�>p�@>\t��W]u��]WW����������M�DG�������_|C���a���F7y�d����^�`��UX�~��s�����\�nQQ�h4�������+��E>|3f����sa2���gOw��U���g�p��jq��W����BQQ���������{1g��k�n��fL�6�m1S���W/�=�������q��j�*�����7�����&�	iii�5~�x�$�O?��]w>��c���/��m��Y�����U���U���_?|����I��������0a�>��DsW�J�����t���;v���X�h222D����`������{�Y�f��������<�.EEE�<y2***���j5�q������F{?D ^������"�������Ve��q&��f�^��J�x�6�>���PWw--�V}:]jj"8x���=��_�kp��������'N�����,�����J�+�(�Z'$�4�P��E5Y�����������������2�$~������UrWG�"#���P�^�����e��a�����?�������x���������0���#++�<F����w��Hk������������5�-[�����w��FEE���`0��.\����<y�����#�`��5�����,X�@t���7c�����c�=��������t:<���x��g���
�Z���2dgg[$&��?��_|���l��<~�8�{�9<��s�J����BCC������jdffZU�����lsN�D�/����O7W�3�L�����?@�P 11!!!hnnFuu5���-�s{��9/������M��UQi��EX�x�C�;�+�������������=���?��gOH�R���[$��73f�0'�vGR�_~�%&L����\g+h����x���������P�{��!C���w�us�����k?~���XTT��n�	���7$	���QRRb�V���_`��!v��;����8{���Zbb�����Dff&�/_n�v����5R�����V�EQQ������]RSS��?����7_�]UUe>g���#::j����(//���p�y�]N�<iU}�����v[��c�	Xi���\ >>�f_AA��_���&
���5*7GC�!��~�����������O"���Hm���\^�K����	�����6��V���"""""""""""""""/�L���D��Wwj����F����'"00�����a�,��L&dffb���	{���X�f�C��r9V�^���{[l7�8y�$v�����O[\/����?������K.��+,�%�+44k��ATT��v�^��G�"==YYY��K$	^�u��;����g0�������c��]8y��U�B\\6n��nJPP6l����_��,k�h�Zddd`��]8x� rrrD��k��>�����w�!22��G�Y������o���o������}�,�.��R�Y��C���&%%��m�z��F�9s�w�M\���+�e����)9��1c���Z�'�����~����"a/$$k������A8��7���I�:�������~���c0���C�ye��9&L����E+�������#��k�?.�8Ah�\r>g��|���������!����bur\f�x�=�p����:	juo�>�Q���?�o����l�?���R��t�,�_�X��h_�V��z���DDDDDDDDDDDDDDD�9�����*z��.�[%����0����^{2&���;v`�������G*���n���-���+!!�w���>���uK�F��o���e��Al������?q��q<������K��<x0����3f@*���#&M���;w��Gq(���t���+�8q"�ju���������q��I�=��5d2�-[��'O��{��+�.))	��s��_oW��q�����x���0u�T$''C��@"��K�/��r�����+���:����o�����#((��z�=z`���������_?��	���#Gb���������h�%uuw�y'���O�7��>J�w�u�=���p���o���_�w�u
���P��xx��9s=��U"xk������[����#))�Cq�B��=����5k���K/����u��H�R�=�=�N�>��������<H����u;G�E�����#G������jkk�y�fs{��	�]=���V���D�[I$4��z$�h2���hE*�%��������ZZ����	L&�h\�MP�z�=��h��{3p�F���������U�|.k�am^�h�F.�u���t�K_""w��c0���1���sx&"�,���<��`�����i��z�:u�b[�����n������������1kj�}�� �������r������F#�n�������B�P %%c��Exx�S�����_����O���*�
���5j���3TVV��?�DNN����V�����1c�8����`����q��)���������84����^�d2����8z�(���Q]]
�B��� $''�o�������:������
������P0�F����I�����]�PRR���Z��� &&�i�������d�s��geggc��m(**�V�Epp0RSS1f���v��d2�����t��'������/��������F���yyy���@SS���T������w>w���������_jDD�u
bbbD���F�W6jE� E�rs4�,r����PQ�U����w���� ��G��D�}p���E�������T��������C�Z���D��2j�'��?����������������=�\`N�3�L064���� ��Dm_55�M"�`��qmV3����\y��.��YBCC1}�t��/�J����]W�-�����(�t�M��g%$$xUr-u?III^U��=� `���<x��C�\z��N��]�A"_�������K������^RR���&7G�5d��?o2A@�Z��h�����B.O���*P]}����k��pb����N�D�����nH����?XQ��w%"""""""""""""""�v� @��,$�5��������0i���\F&�!..�f^^����F�h1HPB&����	���XRY�z}�Cs�K�B��
��z������u�����(�x
F�ipsDDDDDDDDDDDDDDDDDDDDDD����~""r���((���*++QW�XRwW�����Rl$f�o��O@@@�h������?�O.�"-27�[_Q�oK�
��
�@b������`to@DDDDDDDDDDDDDDDDDDDDD��0i���\J"� >>�fnnn����j�uM���$b�����{��/� ������Dcc�C��P�_I�6��>U�bm�Csz��}���}:�	G���u'L�#""�����h_]]������j1����KPA*�(-F>G&@X�h��ee�`2���	Q`�c����N�u���!��xO�n@���������������������������^L�#""�			6�Ym�>���0�x�R4��X������/L������{�O.�"-r�l+j�Mq��qz+�L��!����&U��������-���$�������27G�{���D���D���
�� H1�fe�N���:4gZ�
�&E���t>�uz���f������=Y������X����������������������{0i������j{���0n���h
F4hE��T����F�M�����h���Gy���|0!
lTf���tN�J�K?�CD���W��7 """""""""""""""""""""���GDDn�V�&����P\\���|GN}�6��m$`Q�6�B����4��O&��O�l$z�Y���r��qz�� 5�2�h���&Tj[�uW�/��d2�Q���=""r���x6��
���1�uM��dRD*�n���I&S#4t������0�����c��6��Q��JOt�52��A����Xm������������������������I{DD�VJ�QQQ�}����n���5�
(n���%iT6� ��
�"R������{����H����5|�
CW��O�@��2����f��xu��������� ��W�*..Fss��#�n��M6��RTn��<C$����fU�.���84�L"`EZ�l$}���M����J"�V��Z�L]%E����������������������<�I{DD�vr�����}&�	���n���e�5�n����F]�R�����}&�ee��3U����h����!(����%(����7�P��usDDDDDDDDDDDDDDDDDDDDDD�U1i���<"::r�xMyy9��w�o����E�/Y��`�JuMaac!�(E�3��p��9����`��h_� �S9e]�
� h�OE]�x�DDDDDDDDDDDDDDDDDDDDD�yL�#"�&�	z}t�J����\"�Jo�?77���x/[U� Y�rc$�
�R��.��_V�F�x��-2��i	PH�@��6���J���V��
���D�*�-��ovsDDDDDDDDDDDDDDDDDDDDDD��<�V_�%?��� ���B��1��dA�h�!0p ���"  ���vLDD�����d��VSS���y 2��Y/����!�O�R!um���Q[{Zm�U�^_���t��]�����x<9�>S(���t��j�C)���K��bm^�h���Z$(!aK"""""""""""""""""""""�V�#"�B����w�-��~rr�EU�v��=��kPU�99�bW�U�����o�P�#B���rrr|��`gT�ZP�������^w%DDL��_U�:]���������}�#�u"�K�#�~HP+E�j[8U���������������������������a��ii�������9���������8xh�}--�'�xJHH4�h_cc#***�����k����a�^w�TF#0p��^��79�`'��'~6���YU��v����0
l��;PQ��������������������������s��GD�%��O`��)()��S������]SP_�I��� HHH�������������dBV]�h_�R�\���������D"�����������[��#q!6���)Dn���y�M�B��6_
F�ipsDDDDDDDDDDDDDDDDDDDDDD��0i��������}�A�+q�|Z]	����g�4
BB���Z-JJ�����J�5-z��V�#R�
��cm���o�������"��S/^���`��N���`?o48L��r{�+��3t�da"""""""""""""""""""""r&�yXKK�z}�S���kp��l��T9u^Wi��^AA�z���*�F�=@R���,����X�>����;�S*���r�x����z|VX����&@.C� �h��h���z7GDDDDDDDDDDDDDDDDDDDDDD]����<�d��U�kM�+����\2���T*DFF����z�9"�1�L��������L����[	����Kq6��Zu�^�t�'�E���������B�4i���	�L��V5�IopsDDDDDDDDDDDDDDDDDDDDDD�0i������7���'��QR����]������������:���yFisl$�hXe�,)�
d�����M0�L�{��=���}�#�u"���MT2)���W���L8X�j{DDDDDDDDDDDDDDDDDDDDD�8&�yPN���Y'����Y~~~����3����wsD�a���@b���Zh�H���}MMy��?���w6W@i����z�,(wx^o�/8
��'kP��wsDDDDDDDDDDDDDDDDDDDDDD����GD�!��'Q]��-kUW�w(i�bbb ��D�JKK��$���UM&d��?�8�
)O�dM*U <|�����?`4:^�2����q�6��}�9MZ���&~R	������so@DDDDDDDDDDDDDDDDDDDDD��x�?�������J��^G�d2����fnn��q��&�F��dV��6�A��
�����y���� �h_����O��h2uhno�'H
����3uM����9""""""""""""""""""""""�eL�#"�����n^��[�����H(
����*��u��WYu�U��������!_""".���w������9<�D��OTA�Gu>.(wx^o"������������������������������L�#"�������n]���L>R
K"� >>�fNN��<GL&d��'����Kx���)�l�����Mz�$�+�T�X��/�)Bv���y�I�@�e�}�
�(m��9""""""""""""""""""""""�U������z��5n]S�������5;#,,j�Z����UUUn���
����R4*7GC�*4t4�R��Nss���wh����1*H|�&������i%��!a����������DDDDDDDDDDDDDDDDDDDDD�|L�#"����C��N�(A���`�?77��%�d���'���W�9�U���������C���
V�%@e������7���y�Ib�a
�h_q����]M�����������������=�����3k�,O�D�-��5������m����f�����2e
z���Je1����]79n������Z��l���������GD��xR����������`����f����7 ����O�JP+!��3�_@�P���^
�FTVn����*��c����Bd�pb� �f���.�,LDDDDDDDDDDDDDDDDD��������x�����(((@s��7u'"""�c��H�������L�T��5�!>>�f_~~>��q��-�6��R4*7GC�NDD\
[�jjB��X����p�	�k2����\|8�-�_�h�x�s���6�k�����������������������_~9rrr<
Q�����^�zYTJd�b��=""M?������e��j5���E�ZZZPTT���\#��It�B"A�����PW�����a6zM(-��CU�$���}��/��^�������[���h�_E-�>��HDDDDDDDDDDDDDD�L&@���������[��e����/�tH]�������=�a����P&''��W_���k�a�����3=%�g��5����������x���q��O�A>@����������������m-g���GEE�h�QQQ��� ��=�s�F4�W�J�(!��dK�!!#QWwz}�U�V[���#���yU
<�33�E�_�,�ea����txno��C�Z����em��kqA��U.%""""""""""""""�j��S@Y)P^h��)@x8	��
��y.N""/���������0����,�@DD�����+Vx:���GD�!�QS��^���s&�B���h�>�����7G�\9
�0��XJ����P�"��>�fy�_0��<����0\ ��l4���y0��]���il�������������������������������8�((�L���
��������9�����%V�\	��d�IJJjs���,���]w���\L��������h��,Amc����"8h�[�
���T���*qqq�J��}%%%hn�T��������D���
u5ju/��'���������y%�����C-�8�����uhno����F<i�Qo���7GDDDDDDDDDDDDDDD��47�o~�(.rllq�������CD��dddX������H����_|G�p���{������c��%&��D�?�-���L&C\\�h��dB^^��#r�f���Z��d�
ApsD������K!�I������\,����������4��}���Aa��U�Cg0�5""""""""""""""�.���l����;7��Sg���pN\DD>�������@�����G����^2��z�-h4FD��I{DD>QQS]�NQ�w0u._�������'^y������n������a���l������`���YV�;L��%���
�����f�	����`��*�n�������F#�T��1�����������������**��V�
������|L�#�n��U�Q���\�h4�����Nw�z�k����O�lP�d�����K�`�������l����p��}���;�J�.[��$	z�����L����\������Y�M��5r)�r7GC]YH�p���^_c�������0��:<� X�'�O�^�����F��W�$Dv(nO�S5���$�j@Z�*�xC"""""""""""""""j���y��:w^����7�(}��(W2���};222P\\�R����;aaaN[���G����'QUU�N���`DFFb���HLLt�Z�QZZ�#G����3����^�Ghh(���1r�HDGGwz���b�����������h���?"##�������# @�f��hll��m�PPP���RH�RDFF�o��2d�O]G��N�<�]�v�����;1b���\����7R���Ezz:JJJPSSc~?\t�E���p�Zp��:t������Fxx8n���5�����oGAA*++�#F`��A��=}�4v�����B����X�?qqq�|T������,=z�������L&Chh(1j��N3]����8t����QYY	�R������a���6�������o��#GP]]���@�����K.AHH�SCnn.������TUU!((���������Awz��7�k�.g+����[��|����<L.��A�`��[E�i����<x7�2�x�(_���b466Z�������������7�W@LP�Kr*�D���	(*�Q���b+zwh�x����������daRX .P����*��B�8Xi]UOo2�`U=FE��E��c����������,������������V��m�4���ne]��n���e�W��]��-V^m���L�
.(���3���,�?�91���ay=?������s�0��yu{'��^��������������(�F�M�6a��M���1��J��5k6l��^�z�j���x|��W8x� ��;�l2QXX�,Y�E���������j��5X�f��yG���I���t:?~�|�
:�+W�4���!C�t�R��32�e�[����6m���'�'�J1t�P�s�=x��g���i��O�8�7�|���D���//^�e��A�P����I���m���?��m��UX�z�Y����q[���c�,X�@�����������MKKChh������b������W^��3gD�0�����w�iV\������;����T��ds?�|_�5���j���c6m�����1��F����+��^�;n�v����[m4o�����1S?���/���^��}������������c��9r+W���S���A��w���[�"88������
����?�����{>|yyy&�J�RL�:+V�0:�7��u�X����BBB�������J%�y�|������49�����M��E�p���[tO�J���
�y�f�K�R�w�}X�~}�����������O>��K�D��������W_�]w�e����:hk)))x��W����~=z�����+�ttDD���cx�����k�uJJO���GQ__����'Ad�?##��O�i/i�U� L��RD���g���}Z�
J������/L���O��aIb�����lj���%�0_)�BE���uA��@rr���|�ac��qX�l�h�����g�6G��x�m��!**
6l���g[�w+%%K�,��#�����,[�&L��m�ZL��.`����<y2


�ZC�Ra��Yx��ZLT�}||<V�Z�����WUU����7���L�*	�������bbb������A�_������^z	��z���=HLL�]w���_����/;;#G����?n2ahH�;u����.��1�ZO�R�o�y���=s���QQQ��g�h���D<q�D����`��5k0u�T�d3�!�m���=z�Y�������o���wv���l��p�<x� &O��g�yj���������
64��4������b���H���Ivv6����^{M4ah8_�5F����x�����O���x���M&�
?�3g������]w�������������,Z�H_lf���x���l�6u}L�#"�$\\�1z�O����iMyz���t%���x�����:�7r]���;\]]E�����T*mQ���H�s����^n�h�����A�WE�E����j�� `c� �H��^�WT��L�>��l���OH����E�� ����������������[9k�M��v�F�tr�>}�Qr� ���F�aP����w�}7-Z����h�B�@xx8F����(���_�t	���7;!��������������?~S�LAM���_�p�B�$���]dd$���A�������

0q�D������g��>|8"""���a�����I�&�����I��/_�w�yG�V(4hF�!��}��������2����b��qFI2�aaa1b�h��`���())�x�������-22���-�?q�x��k���=�����;w.�^�
X�nV�^�O*vss���C��yyy�5k���-�;��x���=z�����1f�2nnnFc��}<���}�V������'�Dee��v�T���P�9C�i�9����R�r�-8{��~[`` F��������`�R��]w���r�������<y2RSS
����������7�0��?`��)�?����:�Q�o�����r9>��S��&1i�����=0x�&����,���>
��nGd�N��2�����0T���@#B���333��jm�����P��� 	e�=jGr�<<F����8�u�z:�aM�@������JU��uV���$�|���&^�DDDDDDDDDDDDDDD������Z��@q�m����-[���X}[<��3HKKCjj*bbb������,^�@C���O?m�Z���x������#==����|�2N�>���Xddd@�T��?D�=������h�"��=t�:�w�}�`�#�<���6l���
,X�o��999(..��K�p��)���#''YYYX�n�����.^�����7{bbb�k�.}[&�a��HKKC~~>���p��I$$$���yyy��g���G����j��={���������rss����3g� >>J�R�hx]uu5z�!�.6n��?n�
:��c<o��fc�Q;v����=Dqq1���|9r���7���s�Y�*X����e���-[f��J�V���BFF�~�L&��������k��!&&iiiHNN���
����Z\e��_~�W_}1b~��W�q���Caa!N�<��@�����;uuu���v�����"\�tI���W��J����r�J�8q���
`�������PTT�s���_3|��A2��K���GY�=v��c�������QVV���l\�p'O�����QRR�s�������T*������-� ��z��50}�t��]�v�<�}������e�l�b�-,,;v�@aa!RRR����������O
���X�t)._��L�g�y������BLL.\����"�������*����7�|��}_�x>��A�������?���L�NLLDqq1>�������FGG��^0����v���\�s�K/��A�u`D���Y!"���=���QYy��?���<�+�V����dnpU���P���	�p}���������PW'^u���*b�f#*rz����\\\���)Z����yyy�t6�������9�|����c����Wj��V��S@q�{���p�'~,,��b��su:�$f�����I���Fd�
�����O ��S{x�>0"""""""""""""""sh�@Ue�������_oX�m�����tlM�S�N��O>��A�����s��


�G}������'�@ZZ�Ek�~���7o|}}�����'�|>� �M��O@��?.]�������[���OXX���\,�[o�WW�f����_����
�}���X�j<=��iZ��O>��L����������w�{��fR��;����#�������~�c.�Hp�M7���CX�d	�m��!�c���FI'��]�����c�\�}�?>�o�n�@4��&M��c��!""999���l���O������~��IVV�A������m���O�������o�>�v�mFc{���O?��F�2�j���_c������{��;??p���c���F�i3fL��HKKCxx8>lto� �>}::��C`�Q�IDAT�B�R����s��A����������
��������z
�������_x��g������x?��C�7����4��C���>�����;��S��u�p����	�WOm�H7�t�A���$$$%��w�}��k�Q�������p�B,\����FUPMIII���=���{��1�����K�.�����5}��x��7�~6���j��=� ao��5x��WE��)
,Z�3f������?��#<�����4���������O�����o_��������Kb�Q'���O���t�h����A"��T��ly]�p��
q�s�R�����IGl�������z��������QRR�/��Xvv6|}}E���R*������p���1��Cd�������E�}}KP^�����EA�1<�/�Bc�G���j|�Y��B�Dfwn}]��PR��z�Q_FU-
k���`������-^=��t�b�WGxx�h>1��m�����������	{�-Z������}�EkYZq���_~�%�����A����a�E�����4SBBB�������jjj��W_��D���������E�����L�UWW�������&���H$��y3��9�S�N>��3�Y���� Yn�����O�M2�������jP����mN�k+�Fc����[o�&�5�h�"���TN��q��I{@C����;[}O�\.�7�|�l1�~��a���85
�^��>}�`���&���G��u�p����s�����O��t�c8~�x���i��a��ex��74T3��m-o��������o�_�5$f&�[z�Y�n�h�^cs�����[�	����5������"!!A�^�x1^{��c	�w�}����5{���F��@�];�7�|��������������}��M�d.����L��l��uNN��5�M��U� 6�!TV]�f�6���`�	M����6��<%�z�����U�����S/8;���J���+j��{8�aM�@�����!��j���D�e�C�3�r�$b""""""""""""""""[)--���{�m�Y����o��������}����Q��������fkL�:� ���8W/�H$f's����?Gqq���z�����J�X�b��]YY�_��*q��c��t:���;�u���v��f��{���qqq���~��Wdff��!!!X�d�Ys�|�M899����Gbb��k�\�����?�������C[w�]wm[�|�A�bA0�oY����r�&���5$77�|���-�H��g�Y��T`` �����5��4h7w���y���NNNx�����i��!	�����Fc\���������RTTdP%r���<yr��G76&���{"j��pr�mrL]]��FE�%Ff={�4��.//O_�31UeB]��G���3	� ���{%��Z�X���'�x*D��t:,���zm�Kp���/{�c�WS����w�!""""""""""""""�������L��9��$/���XKhh����91�W�^�7g��U����������?����L&����-�?u�T������O���]�����[o5k���'���*��8Y������y���]���������c���+�J��-u����5n���mA0k�,��2�����a^p]��r_?��������	j��~;��/�`
�f�2+)"""���1EEE��������xxxX���������=��u��?�<


���x��w;8"����GD�
8��cx�n��09���q�sPVv�v�Y�\.7Y�[��!++��5O��!�D�1?;8��6���3�LOO�r�P�N��}������*�y���g��j�I�OF���
V�#""""""""""""""����|�4i�E�-�X~~>�n��9s�`��!������#A0����/�����
*�����4l����?�����y��I�<�Rir���M3h��37nDiii����t8q�����_?���Z�gggxyy���TF#cQQQU����������=B�����
�S�L�h���S
��N�2k^����P������7k\��w�!�����s���������0::+W���3OOO��r�����������m�4����G�a������9�����4Z��u���kI{\;���k�.}{��Mf?��H�����	;;oDE~W��c��r�������&�tF&�,QXX���jGdZ����e� L�*{d{��Q�����pp�GMMB��`o��}M�oL�G��$�����=��D��T�H���qDDDDDDDDDDDDDDDDD
RSS
�M+&��i�$s(�J<��c�s�=���w#!!��5�>
[������{��aaax�����������P*����kS���?�oWVV��_����O��u������f�!	���X��t��hbaK_����}4�Y�i�LK������eb�)�����C�Z4��ams��5���>>>f�srrj�<����gfM������6lF����~@jj*JJJ�V�[�����k���[��f	K�1��/��c�4����^��:2s�L�}�]K��:hkx��'���n�
?�pFD7&�u#r�"#v��}��1M��[��"���wR�={�4���J��T��)�rq�m0DA
�OL����Z]���?���[����U��aIb��]�2]C�=�O-�+���������������������4M^hZ��%���v�"##���������R�Z=����6l���gPq��%���r���7�s��!�X�������;&O����7#??������Zgs:C������k��WRR���D"��z������5��
�bZ{���3k����������?���q���V�������i�&�Z�=����%�q�������9wrr��~����@���m�d.���_x
�����jU8w~1����6��u|||���+����R�������"��N�C���b=��� ��8"�NN�pq	Ge��>��J�1�����2A�nx&F_F�������5����z��j��������2>�����\^�~n�"3���������������:������[�����<����L�j��sv��u����J�v��G-iZ��9uuu�1c�������'NDxx8���GGG����;�������ZEEE�1c�Q����C1~�x���=z����#�\�t���$aaa��������� ;;�h�J����Gq��Q����X�x1�|�M(
���Q=J��Z}��u4>?Xzn���=^.�[����9���z� �L&����o����___888����`��i�lc��q������-�%���Rjj�A���5k��W���nL�#"���RG�1.$<��7�1:].$<������]6��r�AAA�z��hFFl��������Z-�F5T�h�h�y{ODUU*t:�'�UV^Au�89�j���r��7�%�W�|/-�z�a�K�zDy)D�� ��a
'�$w�!""""""""""""""��HE�+�Z@�m��zt�����&�TWW[4������}�����m???�����v[�s���YW[����������]�va��Q-��4����	+W�����q��	>|G�����QSc�����:l����c��*85]{�����e�E�4������!�rqq�'�Zzn���dC]���K
�f����>�={�lv^{Wfm���xee�Q��������������+�p]XXX��Y�:hKeee����-��e�,����;�s�N}����]'��`�Q7%��c��m�t�E��(:F�����@�U�G��m��<==���b��(������bxyyu@d
R+���I ���%���A&s���8(�GE�Gp�#���}���?��`Q�Q_�N�%��yx?��P�������&���Vkq��
�=���u�����������������O_�l�
��c��:www��R��h~����|��W��{�b���f�-..�(��������vpp�/���l�Ac��S"�`���?~<V�Z���z�9s���v�����d��+W�`�������
��41D����[niU<7��<��5�j7
}��V�EII	<<<����|b�\������������������]�smy����4ht��kM�%6��X�:Ht#�ttDD�q$9
z�%���xy923w63�s���+�eff�,����:R+�+r�tr����d�xnn�J�?H��/Aii\��-�	��L*���������w�H/��7���+Q���sQ�����f���������&�%$$X4����f��j������#""�N���/ZWkedd ''G������N����Ajj�U����;v,��Y���$�����H������HLL4����oP/==���V���sp0|H~��M�),,�v8]FHH�A���s�o:�����u��)�����J�lw�*�6v����m-������r���� ���DD�� H1��[����f�%]]����mU�����|zKmm-


lQ��jT&�wB����lM$P(n2�_\|
�������g/�}M�oJ�CBE�z��B.C���h�J���R���DDDDDDDDDDDDDDD�RD���N'5r�H���a�|s�A�V�����f�������l��7��h�8g��|��H[����.Ir� ������?l�����m�\��n��^���j�>}���4��:K�qGpuu5h7�97�q�iw3f������-��t|����-�fKo�r
?~�A�+V��<y�A�������R�>}p��!��y��������������#�,��GDD	��]�������vm��l���������F��a4
R*���#9��8"����QR�����P*��i����m���}j��r�:�"fk
�t������%�T�Vm�sQ�����k��w��O���3�V��O?������f'$4�������?������������(�-��T��<P*�Fcn��6����[�-�����c��Vx���7k�R��	+e����]�v$�6���{��5�6a���F�Kk��*�
�}��Ek��2u�T�d2}����z��E�w���@<X��v�8�������������[n���i��������]�~��GDD�Z���2��>�����mHN~�S'�999���G�O�V#''�����:�W���;;@.���:��|Oh4���UU���Jm��A��~A��IE�/V�bK��O��eRt�����p�������������������7�����������nn�}w!������{����Z�Z����������^^^��N�2+�����'�yzz�SS��w�����mn�������4MN���0�p�B������~�-~���v���qNKKk�5�%**����7��5o�����w0}�t�������m�Ys_}�U�d�������V�������_}�U�*km�����a�����V����?m+L�l�2����?������/�\��:f	�� 
}}��lv\F��p�����:����� &*_���Z�������E�V<�1T�h�8�����PP�i�_�<���',������~=M�oI����������x��^"~��\V����/""""""""""""""���0c&`oo����7���������,Ybp������/����9��o�����^C*�b����vnn.6n������d�}�����7{�����������������������cbb���_7;'::s���(�9s���?�0{|II���>|��8777������V��C=����[_ll,|��f�4H�o�R��G�Z���?� �����o�>�q�-�@.����|�M�I?��o7;A�F%�J�d��m��/��������>��(�v���V����q���?��#$''7;���?����k�Z��m@C��%V�X�F�[���O��=*����g�����9s����$�~��A������;�~�z�k��u�:[]_���I{DDd$8�q��������/q)qY�w����D��Z-���mKJ���y�$���$������N������1m��������&���K3P���Fc'�`��B�O��W�8"""""""""""""""�N����n�U�srn����u�w;v,�q}[����G�s�=���L��iiix�����Oz��e�:���3h�X�/��"


�+�Jl��#F�@FFA@xx���H$L�:U�.--��1c�~�z��������W����q��7o��6���
�gee����'&L����888�}<~��'L�4	��U�p��I��d����`��==z4������
��#G�����^��3����
�s�=�5k>,�8R[[���h���[>|8F��b5��������^,_�{�����
�qJJJ��jo���%�Z-����������.\���s�h�"�t:������v*K�,1H�U�T������+� 77�`lJJ
/^��B���p��>�����f1���O�>;v��]QQ�	&`��=FU[��;�|O>�$t:`�Z�&M2H���s'f����>�08��8q�h���������A�a����I�YYY��};&O���#G��h�^�R)���;���u����'1x�`�Z�
III��������?b����������(:�=��D]���!DD��|R�.%�@<q&/���jT4�=H$��=�G�(((0z4�������c�V���j�Y%�4�GHMT�"�xrs}&��ZR
�b�r���]�>�'N�U��^c�������r�x�mg4���J*Q�1>g&��`�����"3����������������//���������O���M7�����7"66�����n��m��!44^^^P*�HMM��Q(������`�|���8{��~��7b��M���/���QTT���Th4��b�
dgg���+f?/������OJJJ����E�9r�&M��_|�E��?�AVV���+W��k�����p8;;���iii�I����/��iiif������k�b����J����'<==agg���R���Utrr�g�}fr���w��=����~����w�^������		���jkkQZZ���,�cn�y����7��R���i����U��z�j��om6l��?����J@YY,X�g�}�{��T*EVV�A��	0w�\}�jw$�J�{�nL�<*h���[X�nBCC����M4�?���Q����w���I������\<��pqqA��}!�H������|�ggg|�����2{___<��#������BBBD��y����`��M�m��]����!�J///�T*���������l%<<{������7}aII������
8;;���J��U�G{\��2V�#""�fa��-�9��p����h�+�lK2����&��>5�=dV�B��������0H�V55pp��N�Aa��6���N����4���8Wa����J&�%^mO �������������������������,|�o@p����L������b���u:RRRc���������[T�H.�c��}�����v�V�+W�����HNN6H��?��7�x���g�����e�A�$syzzb������3��V�q��EDGG#55U��'�H��{�a��E���F�Azz:���q��i\�r�(Q!00���[�	(nnn8t����@&3��O�R!))	�O���s����.��������������k�w��BBB��������`{ee%��;���8���)S�`�������������F�wZ���]CLL�h�������G�����F���l��q���O�^�������Gll�A����~��GDFFZ�����1m��6���{�����7:�h4�u�����2a����'#&&F���R�DBBN�>���D��C��%�Y�:H�U1i������;C�|�l%���#8w�q��U6��<~~~����+..FEE�&��T��nw�J�����5��2������)�����������>n�}�$1*�x������r�h_zU-
k�lQ'�uOC���( �'��~{����Q
�����h�ooo�<y���G���H�T�������3�Ng���`�����g��C3	�c��������7B���g�}���x���0e����NNNf�/22����;w.�R�{;A��i�p��)�����
6`���pvvnq|�>}�������+;v�Yk�d2l��W�\�O<aVr]�^���O����fU�0a._��m����;�Dhh(
$��y��������h�v�m&����y�f<xnn��)uG={�DLL�o��A��'F��}������B!�Ps��x��Gq��1L�0��<��c�x�b��S@C%�_����{�1DDD�����$���~��]�s�=g�����;z�!�������W��n�{�Ftt4����)S�����{��R)����k�"99�����8[\��"A�3Q���nX/^���������f�p�Ryy9�9�oO�<���]W\|��/�V+��nnQ��d���G�R�Drr�h�B����[�APsT-�J��X��7g��������u�4�&:^&sEp���HZ����zL����z�'|��!~Xf��:PJE
��+�p��m=�mu|/LD�qx&"�8<u,����:��D�����R���z�����}�U��!�t@}=��R) ��pOw��jq��q$%%������������m�{*++���"99eeepttDPP�����`��a
���8v����QQQggg���b��qV�2��h�����W�";;[�`y�B���@DDD 44����t:\�x/^�R�Dii)���������P8=z�h�:]E~~>���������
���:t(��c2Q��������O#??������@@@��^����Wc��5�6�9����������J����;���1n�8��v��N����g�U��_O���1p�@<�K�{���q��)dff���555pqq���7���1`������u���7�
���O���g�=��RtLYY���"2b���S����999���6����@iii��kO��M��P���Ju6��CP^��*��O�.GII4��nj��}��x�_O,��.��5#�y�!�����-&���e(V���rk��S�B'�
�DDDDDDDDDDDDDDD���*��e$	&L��l5��rqq�����n��OOO�s�=���T���$��Al�NW����x��������;Ur-u?�z��T�Z""##��������L�b�}��:H�t�Z�DD�)���@T� ���SQ������R�.����������
����2)|��"u� ��g�����3���,g��}=p��x�I�Xr9*��4��E�2��Xe9��DDDDDDDDDDDDDDDDDDDDDtc�Y��u(�G��\�erLUU��Bmm�
#k���;����jjjPXh�$�j��5u�}�
�`����������������p������\����ZlL5���Y:���Q<9W��GzU��#""""""""""""""""""""""[a�Y��%��������1���������F�����eeeA��Xm���Z�J_
uq��:D���y�R�����tTU]m����dX�����m�+�j���R��8e���GDDDDDDDDDDDDDDDDDDDDtCb����s�G}� �cjk�;UU�l�i������XWW��<�U�J����*���^n�u�lI*u�����J�Qh��&�u��;��u��X���Z��Mk�������E�����V.~� """"""""""""""""""""���I{DD�j��A>�+89�����Gl�lTT$�02���� �h_NN�����Fe����Ka
G��u
�@88��S�+Q\|��k���'��2����*��f����L����
����GDDDDDDDDDDDDDDDDDDDDt�a�����?�����K�c����0����02q�����h4���n����&�B�m�?QG>>S�'��������Mkx���>����2
[V��5l��^��&^�Uj
�t���������������������������=""j3{;oDE~W�P�c��r���CII�
#�T*������Z�Iw�H����i'����M�&���}��a�W�������VAn��;��u7�����j�mZ�V"�&�t�+�D��k|DDDDDDDDDDDDDDDDDDDDDd&��U������nn#L��h*q���i�����r���C�O��!++���.�S�XU/��*{t#����Y���&��W���[�z��N&�w�Z�
�ym^�r��9���4Z$������I{DDd52�������&�h��8w�	�f������C.�z�T*QU��$�TU�&���E*������J��jUmZ�S.��~=M��Y�3e]#�m��2A�K(�D�Zc����������������������V�^
�N��""��������R'�	��������B���������J�

2����a�>u:RL$��8����W#��\\���Q<�N��BQ��6�q��;f�y���,I�@�F��u���L�����	�:��T�8""""""""""""""""""""""j/L�#""��J�1d�����ar�N�A������
#3���GG��weee(++�h%uj���E��Xe�n@� ��g*L��,+��JU��u��_;���k5*�O�m��0��v�j{���Pi��ADDDDDDDDDDDDDDDDDDDDD]�����]H$r��kf���_Ff�lWc� 4[m/==�������	z�0i�nLvv^pw�2��Ca�a�^Gb<�2�n���qf!�K;�:{�C=\D�4:�lq������������������������eL�#"�v#R���s��������(*CP(�}���(**2k?:��&�����$��:F����s�R�d���lTT$�y�[��p���h����3Q���y��6���R������(���qDDDDDDDDDDDDDDDDDDDDDDdmL�#"�v%��[���E��K��))[�\��R�  88�dff&����
k�Q�����*Xe�nl�||&��/*:�������7~v2�������y��&�H�%�(�WTa���������������������������GDD�N���2BC�4;.5���|m���
<<�+x�T*�������J�*{�&������/CD�4�j�h�r�	2��IV!N�V�y�����	
�x����Z���8""""""""""""""""""""""�&&��M���������f�edl���U��Z�ngM�U�����Z�6�����V!���d)/�t�>>�a��eY�y��������n��_<�V��������a)�  ���d�������1����l*$x���ivLv�HL|Z��D9kstt����h�Z�FNN���y5u�1�$�`�=�>��<��1�D����[����}�o'�K����)�_��E��<�e�}95u��V�8""""""""""""""""""""""�&�����9�Gs�����q���j�lWOH$�1�����N<�TU����`���������}*U������\�w����4K����m^�=	����T��U�[%�����������������������l�I{DD�!z����6A�+M@A���p���hlSq����}Z�YYYF�5:�*����� 7�Ht��H����l����Oh4��K�����=M�?���*������@'{�9���)U�����qDDDDDDDDDDDDDDDDDDDDDDd
�$ "���w��� �����8~4�j����G�d�����6�#�Z�:�x5�P����#�
��{��)T�O��EQ�q����O��E��k����\���^A�po���[T-��u9L�#"���=��}
��������?�juE��#�J��gO�������
��ar���N��'�� ���A�����_@mm����2�d��_�J�(i��F[�9�#��^���N�k&�1DDDDDDDDDDDDDDDDDDDDD�y1i���:��������������3���������/����hJJJP^^Pk�H�����Dh��:;����#M���N��u�z���O��/\�D�Z��u�S�������
hLT�$""""""""""""""""""""���I{DD�)x��Dd�����L����������S�k,�AA��wedd@��!�J�N<�&L��^�u#M��U���_��:k����\�/��o����_{����<gT�5�\Ve������������������������-��GDD����0DE��\n�jVe���=����M��������x��())AJE�h��D�N������D��&����C��n�:�2)6��N��w��K*��N{��T�Tm��%�����*!������SQ������`o�grLuu
b�BMMf��!���M��fd"��V����$�������9���E��Z�����:��\1'�t���3Q��Xe���j'C���h_�F��%��GDDDDDDDDDDDDDDDDDDDD�U0i���:g��>�+88�49��6�q�QU��nq������]��P+�V'>/T��n1uE���!2����������:��"�^.��Y[���r��N{����D�oBi%j5�7��������������������������=""���1<�K89���R�!6n6**/�[AAA�����+b9J%�s�k�x��"���M���N��u2)��o�B���"�Y\��u���L�A���}�Z�W�8""""""""""""""""""""""j
&�Q����QQ_�����1��E��{����%gggx{{lST�D��*!1Q)��;����C���N����VYg�����2����T�;o���.����C.�U�����NDDDDDDDDDDDDDDDDDDDDD
��GDD����7�G��B1����q�����L���Q"^��`"1/L��.1uu� ���������Zm�Jr�z�@O�h_Vm=�^���:��^*��>�8��+Q&�Q�'�{ *�?psnr�FS����Q\|���������_�.�w�"���^<Q��'����W��j��T��:.2)6����<�t������p���MO.�FY���Qw���A�_�������������������[[[�?�3g�D��=���h����W�[�d���W�|��j��p�������L���C&S 2b��_�������jkp��B�
>�S��~`` 


P��e��c�������QU�
�������2�����)�����T`^/|�S$����8:�?2i���6�D�ON�����cr���#""""""""""""""""�N������;��������JKK���T���B�����
={����#
��5��=""�2�R'�����#�c��:\��4
|~~3���L&C`` ��&�B�V[��F%�)��9EE��+��4���d��z����rd�'f���&9��o{�`{������JT�k���*k������]DFDDDDDDDDDDDDDDDDD�AQQn��V���vt(DD7������m���G���L������O>��{2���/������R�=����3L����H��<rs��������pp��S�A^Wk���nT��Q������+Bii�U�q�I�����]�E8Z\n���M"��T���-��a4DDDDDDDDDDDDDDD����PW�FMe�j���$M7��G�B�����;:�R�c<i������~�z�����P���;���q��!���y�:0J��5�|��[ZZZG�D]@QQf������o8r�H��E����x�b�3���6����pQ�#��a��M�H������(-.%���={����U-�����\����Y�@0Q������S���G����$�p�d����u�����#[)�����8:�?\em��gma
G\(�DI���/�Z��j��; 2"""""""""""""""�+��DRL>
��Q�QU�_�_n�$�O���\�o��]:0R"���?�����^^^������wFDD�����c������3����APPA@vv6����ccc1y�d���������"��������K�Hd8`nv��������*k�V���sSU������VY��F�����}:]=��?����avO��Q�cur����&A0���dlQ9�$HDDDDDDDDDDDDDD]^�%�7_���_��u�� aT�jd].A�/����h|�n,�.�?����+��ct:����d���T�d�Y�f1a���
V�\i��w�]w!..�����3g����K�.a���2YYYx��'l2ubL�#"�.K$���A�7;.9�m��nmsrK���=�
v��
333�DCd&o�	�H���*+�P]�n�u�eRl�d�wn1�[e-k��d?	��������qDDDDDDDDDDDDDDDD�Q[Y�������?���2���&��������.�����"$"�������
��H��n�����=��S��o"##��0�v����k
�:t'O�l�X�k`�ui� �O���l��RS7���
�N�+Q���N-���������J%��Ed�����L��N'����M
<h�IRK�d���:kYSC�=�����
h�(LDDDDDDDDDDDDDD]�2�_�~Wc�����1�����(���RdDD]Cii�A����c!"�������h4�����}������+0`���~����Q���=""��A@X������f��g|���5�����Z)^e\��
�����j-_��;rs����x2]}}	JJb���+�b�j]����s���5�9�����h_i��LT%""""""""""""""���Y���{q�*��������wc���[���5h��A��8�\�b����[�����<�D�{���`[rr�Uc��I��YK����J���������@�����oA�f�W��!�DR�c}-�Z�����:����G��O�M	�>>S����hI�i( ���IP�R)6����}�W�;|�q�W�{��poWde���-�@��#�~�FDDDDDDDDDDDDDD�[me=~�z�j�U���V���;�����������Qh�Z���CRR���������0�?^^^V[���			�r�
JJJPWWwww���b���		��ZmQPP���\�v
���P��������?F�
�6�������8������Z�NNN���EXX�V����'N�@vv6


 �J�����"**�I\6r���>}999����Q��*.Y�N����222���|����_7�t|||��\�v
���GNNJKK������g������EEE�������l����F�BDDD�s���q��)���@����&MB```����3���T\�x(++�L&���'BBB0f��6�3���+Wp��y(�J���>>>0`�
;;�"��������?$$$������

������a��!##g��A~~>JJJ�������Z�����P\\l�

2{npp�A�iET����GDD7���� �8"��
����~���n�D���tE�zT�kD���������������Z��8:B�����F}:�J��m�����`aOol�R���x9GG��]��^���r��8"E��g�Z�+�U����x%""""""""""""""j���IV���TUY�}����j��wU��6m��M����c�/�J1k�,l���z�j��������p��A�;w��d���0,Y��-���c��5�t�f��Yc���G���I���t:?~�|�
:dTI��!C�`����3g��������6m���'�'�J1t�P�s�=x��g���i��O�8�7�|��J�������c��eP(&�5i�$���F�����f��V�Z���W�o{h�%	l;v���������?�����4������>�(v��8x� ^y��9sFt���~�z�y��f�5�|���S�NMM5zM6�3Y�`���u]s?+�V�;v`��MHHH#�H0j�(�\��������k�.l�����F�F��O3�3�|�2^{�5���uu�����H����;v�Q��#G�r�J�:u��O�y����u�Q�MW��amm-~��'|���8|�0���L��J��:u*V�Xat�o��������M��� --��}+�J���;���/���ir���3�M��E����o�(�Z�Ra��
��y�Q�p,���>�_��U��uuu�����'����K�cA�������������h��}lOM�kj���t����Ub��M��Y[��c��M�V�+(�	��F#��Ec���	�\�Kk4dgg�/^^�!����UU]CUU���Z�^��O�����k��������?��W�^��i<DDDDDDDDDDDDDDD�H������v]�jL>�.�?��;*..��q��l�2��=��>�={�`��a8r���kl��
QQQ��a��=�b�TJJ
�,Y�#F 99���Zk��e�0a�m��b�\�p�������QPP`�*�
�f��<�b��p�����j�*����8���
<�n��f8p�d��PI���_G�~�cV��0�|���2������K���[M&�@bb"���.����6��|���9r$�q�	{@Cb��S�p�]wa�����h�z*�
�����#��&��c��}�����={D����$��'b������Y��S��&�
	m��������:GtU���|�������{��f���s���1y�d<��3P��[���1BCC�a��f���s���_��9���f�����1c����^M����_�#F >>����������?��y�	{@�����3����q�]w�����}��u�V����&-��6=��5�!Q��=""�!����!��� �.-�T������Fc�):��"�� ��aA=!��_N�����`���"�9���&����G��Z��lg����L��&��eVY��\�d��&�(\���bi�u��_��a�-�f�d�������O7��\���#F�0��U^^��������S[[k�M�P <<�F�BTT�����\�t	���7;!��������������?~S�L1�������\���w���3f
��/((����g����={b����������A_^^&M�����[�&�[�|9�y�}[�P`��A1b������^���o�[����q��%�H$���a�����8���'�����5���op����H��Q�8q<������������z��;W�^�[��W��'���a��������������<��5�����]g<�b��=z`���3f�bT���}<���}�V������'�Dee��v�T���P�9C�i�9����R�r�-8{��~[`` F��������0�R��]w����r����?`���HMM5�ngg��n�������?��)S����k�����q�pvv��O�8aVbrr2���;}���?�p��H]��������3
��~��������8{v�j�������Z-^�*��r�=z����t����<p�n��u(���D���2��Z��_c�]����?��]�Di������O��x�aBI%j5��GDDDDDDDDDDDDDD�OQv%r�m�����(��ly�
n��e�����A�3�<���4���"&&���HII����4$�=����eoo�x��9���Q^^���/�������EFF�J%>��C�{�����h�"��=t�:�w�}�`�#�<���6l���
,X�o��999(..��K�p��)���#''YYYX�n�����.^�����7{bbb�k�.}[&�a��HKKC~~>���p��I$$$���yyy��g���GG�f���j1{�l������y����"33g��A||<�J�>�����j<��C(**2���������C�6{�����l�7�c��a������G����(..FBBbbb����#G������{�9�Tk�3X�l�A��e���Y��j<��C���+�Y&�a��������k����4$''c����ccc��SOY�/������
0b����������B�<y���&�1w�\����G���c���p��%�q���_�_]]��+W���x��W#G��o�����"�;wN�������.]���>�����+���088K�.�������2dgg���8y�$��?����;wO=��R�~����o�1���[���������������/����-[�e��maaa��c
������h�?������~jp.6���Kq��e�d2<��3HNNFVVbbbp����w��\.�������o����/^��|� 	}������QVV��n'&&����|�	�����3::/�������u������r�J�m����������3fT�|��7����nqR�!kyQ���5���s�B��BUZ����"b�g���
�R+���$�`��d�������>���pr��ED	||� +�K����h(�^���<,��#���"f~�����m�����dRtw����\���p��#}��,DDDDDDDDDDDDDDD��V�Ee�����J���]�X6"��<��x�C"����N��'�|�o���?�s��5��>����O<���4������1o��oL�����O>�|��M�'�����.]������r�-`T�',,L�g��������k�����/c�����>��S�Z�
������V����O�`�����������}�����{Z��5���;8r���=z�h���_��K$�t�M8t��,Y�m��hH�X�v�Q�����E������w��������$
��I�&���c���@NN ;;?������6���g���������m���O�������o�>�v�mFc{���O?��F�2�j���_c������{��;??p���c���F�i3fL��HKKCxx8>lThAL�>����C�R5\�����s��A����������
��������z
�������_x��g������x?��C�7����4��C���>�����;��S��u�p����	�WOm�H7�t�A���$$$%��w�}��k�Q�������p�B,\����FUPMIII���=���{��1�����K�.�����5}��x��7�~6���j��=� ao��5x��W!�P(X�hf�����'�+.~��Gx��'i4�=����|�r\�x�w����b����9s&�O��������l>|����=���/���K;*|�d��GDD7<�Q���g�-�Z-^������ 2b'��J�ku:�U��r��������T*E��=��E_���a��"��W�!(/�`���iPXx����h)'������d�D���/�������s%�
�p���*�i��N,��@w8�M�ADDDDDDDDDDDDDD�Oe�
������f���y��u��1��[1f��-���������h�^c�-Btt4�o�n�Z�
�h������K���_���;�a���c)S�i������O?�'A�������2Y�0))I�o�*�yyy�����686����M&^'�H�y�f�9s�N�|��gX�f�AA���#��'�4�d����W_}��"������V��(q����M�kl��E���3���q�F�����d��;w�&��C.���o�1J6k�_�~X�`�>N�F��W��O�>��s���&x��G�n�:\�rp��9�����n���?���a��iX�l�x�

��L%~[�[o�e��u��7�����Db^�����u���&�56g�l��U��[PP���X����~�-�������^k1���@|��w����_�7n�h�	��u�#H$��������5kPXX�F����c���&��t�MX�f
�N�j�h����Gy���[�"��\n��������{��<@n�
��'7�*?X�����������R����2r�����fH$�����TTU]��Z��]�D����eW2QR���z�`/�`���h�F�-��qDDDDDDDDDDDDDDDD�Y���b���������Yc����zvvv��^��}1j�(}���_���S�N5H6i.����$���-����Q\\�o�^�������R)V�X�oWVV��_�J\����:�N��c��v]�#�]������x��v\\\{�d�_�����vHH�,Yb��7�|NNN��������h��+W���c�����~:��qw�u�������.F���������(��iz{^Crss��7�����}�����M����Yc|�A�vs����7��������~����b�p�o�>h4�q�u����A����qqq���;Z�M7a����<yr��E]������P(bx�����59����bBMMR+kD��A��%�%	���M�7##���UDd�T�//�O�Q*�B��7�o�����(^���N�^��'�5g��3��o���W���s%�m�<y*�J��9s��I^>>>-V�����P��;sbL�^���n.���������?Xe���Y�o�L���g[4�������U������p����5���������r��?�0h��7���w���F���;f�\�Tj��h������q�6h��Y�f�5w��!������"n�c�����5���7HP������o�v[o��Yf%@DD�A��9��������w����>}���������������
���?��_?����-�?q�f���A��+�L�#"�n����G}�@�cjj37i���A���<���..�������xDD�su{{�>��%%�����T�-�M�1�.�
K���5�%�T������6 """""""""""""""����&M�h���������[1g�2~~~ptt� F__~��~^uu�A�������
6���������{{{�8O�<���T*M�s��i�9s�`���(--mu�:�'N������WWW�����///}���hd,**���Q��(++k��,r���=WS�L�h���S
��&����
���N�>|�Y���
	^�&(5�[^~c�����att4V�\�3f ,,������F�e{{��7wnn�������>b���6>���1��7(:b��5-j"v-i��`G�����#�i�&�����p|���|�2*++Q]]�k��a������/c�������A�Sg��=""�v��B0<�+8:�29�L��z� ��/�.B����Z�E�uW� ��g*��aI����Xm�n�X�c����,�w��u�����KE��*k����qDDDDDDDDDDDDDDDD��RSS
�M+&��i�$s(�J<��c�s�=���w#!!���5k���?==��s������/��o������T*QW��}��x���c����vee%^|�E���a���X�n�?n��� ?(���K���-}�����M�$��8;;��m��TS���
�C��h��a���VQkZ�5||L������S�����?3k�����?���a�0z�h����8p�RSSQRR���{����q��5�vk�,a�9���0}��&����K_Gf��i��kI{\;Bmm-�O����/��-\�����SO=���p8;;���aaax��G�W^yE?^�V���b�<`�uS=0<�+8;����v�Et��D@���h����|��J�BAA���uS~ps3������
��V/�����wa��$eYm-k�
"MT����
FCDDDDDDDDDDDDDDD�A����U�Zb��k��!22������h,���J�j�\sDGGc��a��o_��7i.�O.���~@xx���C�a��?~<���1y�dl�������WTT��8����ueB������t�DOOO��{{{��_s,�)����-?3k���t�c���c���8�|��h��G��4Kw-���V����v�����������)S��������A��o��G�o������K�5V�dQG���AT�n�=7���
�q':'��R�x������L�1���H���������M��L�Fc����tTU]��K?���(�`K�`�wb51����R��q��z��p���J��?Q(�Z��j�I4&"""""""""""""�������1���?��%���.Y����-���v�����O_YYi�nZ��%M+�4���3f�@V���������'"<<�����4���}W���<hQl�UTT�3f%:���G�>}��G8::���� ��K���L���8l��|�������T*=zG���/������7��Ba���������C�E��������PQa�C��r��k�����#x�����d2n��f�=!!!��������
����M�I�M�]\\l��5��Zb����i4l���`�o����Zio��&��������_������ ��J]�����[���Dd�.�;����57A'q�"��1'''��������O�V#''�o���$�:��k

~�/,<
'�^�HL?������T�/�������,�qs��]�x-�{���\�r�[T����&Q�#�J����}/��G?w�&��u����#5M�����h~UU��c?��#$%%��~~~��cn������_��(��x��7
*
����v���Q�Z�kib���V�\�������8|�0�=���O������uuu��u+<�c��Upj�����e���i���{�.�����>y��s`|~�I6�u-]�� ao���������g�f��we�����WVVU����^K��y��9�M�kv=k]m����P*�����7��c���� 6��
���t:?~=���c���s�mLDD���rWDD����O���������hJ ��8Onq�AAA(**}�Dnn.����-�LDQ(��<���O]�h*Q\|
������^�8�,��j�?���j��������zm����r�����#�J�`������������������A��~��%�f���g��:www�v�����8��%_}��A{���;�������(n_�������_�M8h��qJ$�?�����U�P__�3g���_~��������{����??����>�&��t:�r�-���F��X�&Y�F����O��j�())��������O,�K�XRR�>�	�������jmy����4h�W�^6[��^Klr-��u��RSS
��z���zj��-Vm����4��d2g�/�y����"8UFB�S�/8���������/���j�����x��A��3��?��qP�,���9R	�6�Fy_A)~((��zm%�{����-*�������������������l�+�}�l�V����
t��Z�Q�d������?��qZ�111�vDD��	{p��E��j����������v��	{555F7���\.���c�f�$%%�����D���)@bb����x�����7~�sw��`������SXXh�p�������s�,��t|������S���]�V���2kcg������j�n�,gK���Z�*�2��5��r�A[���)&����GDD��I�P��
r�~������#!�9���mq=z�0�������
��;{{��E���B�<���\���`����'eAY���zm��h�@'{���:5R*x�!"""""""""""""��u�m�;"��d��j����?�������/**�Z������f����dQ���7������|��%q������$'�~�i<�����?n������������j�>}���4��:k���\]
p�����������1�
>l��������\m97[�{��k����
�]	�5&O�l�����s������e�n��o���o|||�u}L�#""j$�J�C�:�u��:����e������d2M�gff�6L�n��k,�Rg����,TV^��z/������h_Q�+�:W������U@��?L%"""""""""""""�[�!��;��]��;���x�����q�����O(..6knAA��		M��������>0{,8;�/R]]m�\[�i��	y�T*���v�m��[��[<���%��#4��o�<�R�)V:���
��v�2H�mNII	��5,v0a���F�Kk��*�
�}��Ek��2u�T�����W-Z��b������k�p�����/�\m�W�^���\�v���F���{��Fh��1i������Qk�[��s�>��H����W�����???���W�*..FEEEk�%�v${x{O4��T�F#�n
{�[C*���PX�}%V[�����uq��Tkp��s�JDDDDDDDDDDDDDD7�	����]�[�����.��J���q��������X�j�Ys_y��'���N�:eV����g-N����4h����=�����mn������3{��h�����a4f���pww�����[���O�O������.kXKTT�A��o�1k���kQSS�!u	��OGp�_�HSSS�m�6�������N���G����#u�=7����U��v
��������m�V��Z���:��e���?�<���:(���s��~���g����}�]�����{P��������I�I{DDD��U��T*���D�_M~���L���H$

2�fFF�E����;�p8:���4�*���z��Nx&��S�V$e��N�BgG��R�D�!�W���}X@DDDDDDDDDDDDDD79�|.�N��[��I�;�����������,YA�����_|�E�s�o��������T*��������\l����9�������Q_o��!!!pqq����w��������`��111��������s�Z��9s���=�����x>�h���^~�e}[���������-�/66>�`�c
���R����G-Z���A�_����x����[ ���z���oZL���}��	j7*�T�%K�l[�|9~���f�}��gF��K�.�z|�}�7����G!99��9��E	T�5>�
���X�b�A��?���g�6H�j��3g:<An��9�!))	��~;rrr��G}}=v�������\�=���������������?oq�?��7�x�`����M~���I{DDD�_j��tQy}��y)��p-�]��w^^^prr����@ii���uW� ��g
L��-+��JUh�5�����D���5X���i�o]�d��*~���hq�����
t��K��Vq����.��W�K�����c������u:y�<��s���4������z
O<��W�^f�3o�<���+���/����`�R����1b�ddd@������D"���S����R�3�����}���o�|5M�k��y����o����`{VV���b��	())���������~��I�0p�@�Z�
'O�4�Jv]MM
������G#==]�}��a9r���_z�%��1C�����=���Y�f������#�������[o�����c��-V��>}�A��{������g�<x�����4������mPQR����;���;��E^�ps����E������wo[���,Y�� �V�R���o�+�����\��)))X�x1.\hp��>�����f1���O�>;v��]QQ�	&`��=FU[��;�|O>�$t:`�Z�&M2H���s'f����>�08��8q�h���������A�a����I�YYY��};&O���#G��h�^�R)���;������<y���U���$~�t~~>~��G,^�����?>E���u��^z�%���:��>�(,X��/�ONN���>�{����w���	����Mb�����*!""��*�����������q-��:��?�FS�~}_� &	����`\�|YtnFF���
�nED���y��=
��gDzu(,���Z�5e/�`��`��M�F$7���2�+(�=~[���/�+�Ec�PR�p7g8H��""""""""""""""�8^�.���h�:	Wc�[���#�0��~��'b������E||<�����n��m��!44^^^P*�HMM��Q(������`�|���8{��~��7b��M���/���QTT���Th4��+V ;;W�\1��y����~}�PRR�/_.:���#�4i�����/�?�����uuuX�r%^{�5���������HKK3HL����?|��HKK3;���D�]�k���T*E��=���	;;;���"%%������>��3���H$��{7���}�;�N��{�b������GHH<<<P[[���Rdeess��7o��&�J%���HS�V�Z���W[�k��a~��gTVV����`�<������7�R)����H'L���s���T�#�T���wc�������PA������u�
OOO�k����(|���6��nD���.&M��?'������������D���,����>���_|�����^����<���y����������g�y)))��i�~��k�0�|H�R������*�
���(,�n�k���{����M�DXRR��fy{{������(//�R�l����A[������{1}�t���;v`�����E��=!rrr�������!!!��:)��KDD ���d_��#z�z
�����>��>����@�3�������	����t�7�D�����d�O����AE�%��7L�����L�������z����$�b�������p����sp�c���0��C����Es{�u������1a�WWW<x#F�0������������=WWW�����
Fr����C��}
�k�Z\�r�O�Frr�A��?�����?'N��-[�%������������j�/^Dtt4RSS�	{����-Zd�Z�i4���#>>�O���+W���o��������C����d2��-*�
III8}�4��;���t������f�����w�}___3����o��NNN�+++q��9���$�M�2���o����&,,'N�0���j��v�bbbD�n��v=z�������7�~���k���������5H������?����H����y3�M���x�{�=����F��F����?�S�<y�d����V�S*�HHH�������(�}�����1k^mi��	����D��


���X��=???����FJzL�#""�ZQ#���Nw��?������������
.^Z
��8y'88�����L��lD��I$v���d����4�����B/?pv�+����+YO[�HC=\`'?W%�V�J��
u��x���Q���(�-=�{���0)��I���=0���~u�]�^C�;(�����'O����� :F*�������s����+88111x��g�� ~_�3���+6n�A0}�Us�}�Y$&&���^��)S��G899�����H���b����J��cA��i�p��)�����
6`���pvvnq|�>}�������+;v�Yk�d2l��W�\�O<aVr]�^���O����fU�0a._��m����;�Dhh(
$��y��������h�v�m&����y�f<x�������={"&&��o��A�L��G���}����?C�P�0J��=���8v�&L�`r���{�1\�x�U�)��������_~��=�"""���iq��O?�k������3Jo���=�~��w����Uq����{#::�����)S`gg��x�T��c�b���HNN����.:��A[����q��l��	���oq|�^���o����fW,��A�u�;���f.^������			�������r9rD��<y2\]];0"�����>�@�o��C=
������K�/�V����{����`���WQTT$:'((���FOd]]�<������=jj�E������g�U�<_Q��IP�x������9�$u��qE�U���:�&?w�DD-�J�`"�
��DD��`"����0Q��9��{��}Zj�W�^5���o_��[7�N�z��R�r{i����V��������������#,,������u +++���"99eeepttDPP�����m�����Czz:***������P�7�*U�4
q��Udgg�����
�B���@DDD 44����t:\�x/^�R�Dii)���������P8=z�h�:]E~~>���������
���:t(��c2Q��������O#??������@@@��^����Wc��5�6�9����������J����;���1n�8��v��N����g�U��_O���1p�@<�K�{���q��)dff���555pqq���7���1`������u�����������B�����
~~~1bD�z�C�:�o��/5"""����
G�m��wA"�GB��t���Py��/��!B*�kAAA(..�#+''���?����>>S���9�$���sP(����'�Xb��	������|���IY������:�����*�h�F}W��1��nv�s���������������:A`�����&�D�	&4[���\\\p������������sO��_*�b���I��A���U�������0����`&�P����W��H�A������M���0e����V�A[�����w���aP�9k��N�CJ�x����
����>�b����*�5V\�'��{ju�~�����������DODvv��a����w�?���?rq�+Qk�RRf�x��\"��&�B���/*�m@DDDDDDDDDDDDDDDDDDDDD������[+�S��N-��b\e�1/�����R�e�KKO#�����/�o4Y�:??���fDND�yx��L�*��R�����U���H��0d�x�/�r|�_b�5[���\d�����Z��W%""""""""""""""""""""��c�uk)�U� T�|�xx�Ad������Y@y�Y���E]]@.��G��cu:���Z\���"����=�dQ�qh4�_��1X���C�M��r5���O��
��L��bYm�������������������������GDD��N�C���=G;8��N���[$�"��\�irLe�%��=�*�a�������c�J%����Z��8;���S�h�V[����V_sI����Y��`��L�t:��k�P�#��d�}��*�U�l���I{DD�m���R��3��^c
� DE������1���������lH�R����a��D�� ���AO�-/����\��)��2 2A��`Q9��/����!�r5����S$�(��GDD�Vj�x�=@���Y�qq���Q_�����155��{����������:eee(--�8��L.w���(�����C��Zu�A.��G/������<U�U�l� g{�8�W�,��Gf��Y�����[��tH�O�t����u�H'�^���
��!&��T���{UUW[����WD�qw	��M�O�*@y�y���l���H�-Sk����-��������C��
�U0i�������:�h�+n�*,�����c �G}g��&���".�a�d�P(�c���QTT��X���Do�)&���N@�����r��-�!������M^�U�l
G{:������M&2�e��GDD�R����;;�y�������
�A&���� ��#��4�����	�V<����9;�����h�V�BQ�1��9��K{���59��:��k��^����U@�j{DDDDDDDDDDDDDDDDDD�f�����t�/""�q1i�����N��J�������Z��hg����]pu�49F��@R�Spr��W�T����J<D����$�L����jj����3�~j�Rg�Z���3;�C/9B]��+�$�Y�
!Qw��=""�vr�UPi�g�\�nZK.wEd����69F��FQ�*�5gE�����V����N.w��������C��nK�D����������*���k�F��+�#�W���=�����������������������I{DD���V�W��	z:�W�j���>����c�:T�MP�c���j5rrr�����c8�r���:%���Z}�.�x1��d�kW��S[g�u-�f'C_W'����J�l���I{DD����:�W�����8@&1U�m�R�||�7Tu����QO^^��:6����)||���/*���J���t�/"�Iq-�^��N'^��V"���8�%�TB�a�="""""""""""""""���wx��7���nz����B'TE�	�*R1�(G�(�z�����,�`+ UjB�IH���f��/+��
�dwS�~�����������3I�{n"""""�U,�#"��JvM=��e�\,["�C���C�IM�RC������j5���-�Q{��
g���s���G�S&�Ndl�����U�&���qM�$�"��ItN���l������������������������n,�#"��JZu��v;��G;���Hd��}=��5�J��S44����������M����A��������L���p���0?���Ss�]���3{y���@w���j�(UV�����������������������}`��6*5�k�E�B� 5���A�n��DP��M�S4|	E�.�mYYY�L��]��\��y������h�_��0��\E��Tj<w1�?��^*A/g�9�H,��rFDDDDDDDDDDDDDDDDDDDDD��������YS����p��"�vy���\���
�maOYY*++��"Q������^�s

�(/�7{L�D�;�!�3���pY��+5{\Stww��T�G�K���P(��Q�'k���$��������d������������ETT:w����J%N�:���$���@*�������G�=��J�����'N��������kW�u�]pv�bCD��^U'��A*A[+gs�p�s��!�: -�m�������6� 233��G��'�n� ���(����/-=	�n��\����=^��kWrE�W��`������}<�q�H�X ��
#�=��Q��=����8l����=�r��u����;w./^OOO��TWWc�����y3JK�;�DDD��_Dttt�
_>�+V���C������>}:V�Z��;�r"j�z�9����0HZ�.��S�Jq����(��z���Euu5���n��Ht;sp��s7TW_���hPTt�����`�^T���Z��j��]��w}:�X!n������Z���K��C/�3��lZ 3""""""""""""""""""""��I��	��A�Vc���4h����&��k]�V�Z������?�4)��s���wo���� %%�=������
�b�F��/��#F,��B�/��={��?�`r"2���u��sv�j.bB���[���(U� Wl�F�Bff&4C������D��]M�e��f�=�T��[�$���#e��2���q�%���e��`|�~>"""""""""""""""""""""2�E{d,��5k�V�u�;::�W�^4h:u��0SPP�������QqRRR0j�(����lwvvF�����K���v���g�����z�^��O?�u���l�����������\MM
�O���~���8DdiUu���eR����R��3���z�����8��wQWW���B+fG�>�dN�����|Q�h4J����d��a��W^�Ef]�5��p���7����#�s#""""""""""""""""""""jkX�G������O>����{w���o������gq��)������+W����?p
}�Q���5G�Tb���(..�n�����m�PZZ���D\�t	���x��W �������x���~M;v���������DJJ
233���"���_����v�J����>����cQ��*U��S����8��$���������*�i��o#++
*�����nn}ak�#:��P���8��}<�]�D�jTj��b�-�AS"�j��^\q�{�E{dq+W��0111?~<d2��.>>>X�l�������"l����8�}���;�{xx��������u��yzz���_��_~������q������B�_|Qg�O<��;w�K�.:�G��#G�`���mUUUX�|�M������\�.������{m�Dbgp�J}U�o '��3#jA�����N�����q���M�����
-���%f�k�'{��G���a�="""""""""""""""""""""c�h�,*--
III:�>��C89�w��n��Q�;w���_~���z�B��_]g������{w��<��C�5k�v�T*�b��&��O?�T�S^�.]�q�F�������m�6���_�5.^�x�XDd���E{n�2x��D�Z���H���	�RG�k��d\I{uu-W�C�V98������F�Dq�!����h����
������u-S'�{���+�d�="""""""""""""""""""""#�h�,*%%Eg�����>�3NMM5�v��=�����;v��9s��4��+t��v������;�|��':��^z	���M���{wL�>];V�T����o�5_U�E�
�s��n[O�;���VH������q:�!(�V���}��f��eM����Y$�� r�A�J�g/fA�B�q��vtO�J�5�������������������������a�YTi�nIpp�����������
���k��x��9F�t��	��������\������x������M�iz��LD���D�I���3�5�n��5d2w�k�T������z��R�#���28_Ttj�x�o��
6u��D�{������Sl�����r18�PZ��5�E{dQnnn:��:���4^���mp�o���3;v��q���3���_��3t�P89�w�il���ptt��SRRp��e��$�[c�+���
�leV������D����J=
�����������bfDm��k/��u�S*+PVk����vx9<���kW�p�Nn��7�mo����]��T�TQk��������������������������E���Wg������������4Ht]AA����c;;;DEE����Cu�g��1�����w�it�L����ED�W.o@�B):������9�A�2����*�����6�z��q� ���h�����hh(�H��A��&^�_�Vcqr&�-��.���z'�V�A��j>DDDDDDDDDDDDDDDDDDDDDm	�������t
��r9�}����'���i�&�ms��]����3���3lmm���{��:���T(��E>�c5���X��GD��Vm��g��.R���s8"�~A�5��^�������a'O"c���������F�BQ�h,P<'l��xy���|�Sl���p�������\�J��r��@DDDDDDDDDDDDDDDDDDDDt;b�Y��5k ���Om��e��m�������2e�NA���1q�D��))):���`��������?�;
������x}����h4�W�������Ff���# �<��� \�P">�!TU��bfDm���]�H��ykk3PSs�"q���J'���7��!�Vn��7���R����UC�b�=""""""""""""""��&##� h�DGG�tJD����h��^FF������c����0a�������s�+VX,o2��+t�>t�j�o���C-��Y��X�6�����������z
�J�������0y�dDDD������8u��o����R��c���7�|c�����:��� �s@ZZ��1�t�������Y�u��s'"�)�7��A%:��`�l�Gt���_E}�[Pk2E�54�">a���nn���%Q�#�:��{
�����c($��~,�����H��:��^����:Cb�_�8�H���	�E�R�58WV���V��������������������q��9L�8W�^m�T����������tTUU���������3�����N����=���"""O?�4�����)66����	�/������t�k���Zg���dr~��i|L����J�[dj,c�����P���fRSS�����lv.�PSS����X�w���4����B"�����Q/_�Z��RY����������n��f���a�&2�/�J��z��
��G��<�"�_����Z��5zs'+j�Aj6��f��M	�R@��.�U#X���������v>�4����Z��DD-��a"���s0�����RRR�{��yyy-�
Q���hp��E��� &&�N����g����]����b���f��V����_��>��S����w��	��+����
Z+����5
���X�l6n��Ww���<���x����,���aooorn�]��~Y"���X��1��~��+W6�111���ov.���)P�P��7`c�7'�������
�L///����z�z��E��������us�REZ9Kjn�����-����v���HL,�Bak����8�[/���YE��x�J��n���?�����U�_��S>��Ed)��9���5�9�����LD��x&"j9<�O���-�B���h����J������3�n����#�����c��-�P;u�gl���8t�P�%CFY�f�N�^XX�|�IDFF�����'���["=�V!::��m�������c��K�Z��?�_�5N�>���
���x�"f���������h48�<��?�9s��h�c�Y��-[�j�*�������'�|����n�:<��c������mmM����oL�k]�n�Vb���O���H��U�Z9�P*���������^�\�*�9�������g��*eo+gJ��������^^��8%���W��0�o�F��.��
� H�������}��K
P���������%��6�nJDDDDDDDDDDDDDDd���\<v���P�~�5�<����a����+"��wH��K�������/����BLL���[0#"��o��]���Uc>|�&MBe����R�����Z�Fqq1�����5������PCC�L���j�<==�l�2������
������{7x���:JKK1w�\,Y����w�S(&�(���h.�AOl�����CD��p����aSYf�d,�����`;�� ��7�VT���2����@t�+,��R)�sv���k�E�J<ZW;�Zt���l],�)�F
��\���Z7!""""""""""""""jW��c������E��y'2�u
�����I���y'�-Y�o������������n�
�F��s�N`��������'O���=""srr2�11q�D�����H|���(,,Dff&N�>���xdff������;.\www��C��N{dq.�?��4�v������:L�8'N����1}�tmw�����{���3g������u�b�n�q����4��Z�+����c�'�|S�N5i���T������A���\����111���A�,rq��K�����Z@����������n��,'//eee��>
�bT��kA
{����	>>X9Sj+x����2������V���^H$�w�5FCQ%Vd���v�����fo����4�-�E���U���~aAp�/t$"��LD�rx&"j9<�,����Z��D������N�U�������������)9������m�p���.�������t����G�-�	Q������b��A8p �w�}+W�4[�B��zUUU�m�>�,��Y�}\]]1n�8�76l�6����E{dQ����~������_���O��M�4	|�������d���1:k��������>b�t�J�P�T:��R�lLS�������Y�pvv��k������S���Z���z������.puq�rF���������j�v�OB���Re���d\][[
�����*�Q��y��%


������S�k�T����p��~��U��hy���\�����sTgH���V�`����s)�j����j>D����LD��LD�rx&"jY<�����'s��^]M��o-GuYi��s��ad_8��/��OHG�$GD��������$�y,[�������-��������'�|o�����7����G��	P��������y����]��]�j�%%%�����5.X���69����&�y]��M����{�s���H_z�x�M�  �����m���
�cA���vd��M�w��k���b����,A��3
�xa\yy�r�nx�%��-NR�o�c+k�QV�Eb7����m����]+GA���Q[Tt5;V��������J�c�Ref��xDDmA}������DDdQQQV)�+,,�[o�����b��u�K��N{d1���6q�D���H$�0a�N��#G�����Y�3���4)���B�o\mmm.�6""���:�lt���u����\��i*�W��D����`#i������(((@CC��_�g3������~W��A��Ex�����H��������"^dV����j��O���u
�����&=c�]���z��A@�������Wa\�-�'DDDDDDDDDDDDDDdP]U%~|k9�k��z���j���2�^�>\�mJ�Z�����q��%���������6l�������IIIHIIAYY
��������"44�l�����III�r�
����T*���	???<~~~��������xddd���j�������Exx8z���������8v�rrrPXX�T
___t��QQQ���JRRRp��)���j��
Bdd�E�j4�/33111(((@EE���0t�P������+8{�,rssQ^^ooo��1nnnF�_RR����#''��������A���o��������'O"77�    #F�@```3_U������t�?�������L&���'BCC1d��V��8%%g��Eqq1JKKaooDFF�O�>���m��p��q$%%�������������a��������O���eeepss�~��{-��u����m���%,Y����-�Y���b���PQQ��-,,��c4^��S�_�v��(
�/r���:�N�:A&�ht��
���olEz+�X�Gd^9�r(��?�������R�AAAHOO�n66��

��7#��Tu���e���H�����N�JU�7W_�����pq��/�fx���r)����z���3�;��V���8����E�
zs�
d���eWS""""""""""""""2����l��.+�����	O/����*�J��7b���������J��<y2��]��;�R���|�����w/�,&
����1�|884}O����V�\��+W�����1b��6�F��G�b����oRRR����W/<��sx���
�Sj���;�q�F�8q��uR��{������E�������;vo��8�s���|}}�`�,Y�...�5b���b�;|�p���-_�+V�0*_Kh��)l[�n��9s���?�����k322t�e~��G�u�V���{��+�������FFFb��5F7<�����m�����t��dS_�9s�������Z��jl��7nDRR���D�A����_6��4��}��Wx����������c���/^��e��k�.(
�c���|����������_���'��A�����{�!$$��������������~��G8p@��NcR��G��K/��w�o����FM�3���"##��cc��u���o���ep���������c��q&��+���v�Zl��	����7I�RL�2k����bx�B���7���>2X!����W_}�&M2������~����2���Oo�l�R�g�!j�~0���J��[����S�-��gt�c�����z:@�����G�T�}�i����xiU�]�l%�����%�����^�5
�[�`k��������))�B�Q[2E�6I"����p������R�����A��n!p���WY�-YE��TN��?�0����O�""""""""""""""��!->�����c��k�mIii)���N,Y�D�`�v_���;��O<x�����>����v�Z�9s���
���a���0`RSSM�w��,Y��������M����s������#QXXhT�\���'c��i7-T���			X�|9���o������M�]w��?���`�p���k����]�"6�z����h���c���{��p���,��5��4i^{�5+ff���8s��5X�\+�;y�$&M�������������r<���x��GD���k�.DEEa�����f��"�������~���r�J�=Z���V��{�n<��sD[�������S�L�����,���3�����#Gb��EP*�F�0�������k�,������gL�0W�^5:FNN��e����������@BB�I����S����y��&i4�>}��w&M������Y�:���/W�\���������-�Y
���b�����������W�0a��x��}F�h����@4�s��q�.@������Z��k�������yQ��jd�����8�C*i�]�$��'�������M����
.$/�Zm�b�Z;g�88���T�(-5���T���X�9�����<\2p��G;8����*�H�/�&"""""""""""""��[����'v�V���UUUa���z�1� �c��0`�N���J�w�}HNN6)N}��}...�����A���`��..\��a��]�\byzxx 22R�����_o���G1j�(����~�y����������C�A�=�����B>;w���

B�����o_xxx�����c��8z���1I���K�n�:����=z���D����-��?�h�o*==w�y�^��D"Axx8 ����?����#QVVfr���h�������_?�
U�;�i��i?�������}�0k�,\�|�z�j�X�B[T������{�o��pvv��7??�'OFCC�����k�����9  ={���!C��W/�����������������g��O<���j��R�aaa8p z��uK������q�=����3�m���0`z��	;;������1i�$TVVu�_~�#G�Dzz��v[[[�u�[�nz��~���5J��u#K^����}����=''o��&����#00C���/�lT�?�,�#���������&c���:�N�:��k�r���?7����+Wt�����`�����_�~�quu5v��q�8�n�R����������U#����>�������~�S��!$x9�����������V�?=��v%||F�������r�u������.�sr���3�T[��]/�| ��
jv�#"""""""""""""�ef ��y���NNBqf�Ub�fK�,A\\�v,-Z������#66���HKK��\+�{��'M�egg�i����/����WQYY��/���S���Cff&����y�f������|��?��q����}��a���:�y�����o|��������������(--��p��I$$$ 77���X�z5������?K�.m�=����W_}��d2���K���@AA���q��	$%%��������s'f��
���oS���1c���������C^^���p��i$$$���X[hx]mm-f������co��A����w��M���g�n2�����#X�f
`�����w/JKK������X���������~O?��Y����5X�d����%K��Z)�J��9����m2�K�.EVV�\����Xddd 55�����?...4)�?���~�-`����g��}���GQQN�8���@���5k
�u�V��������}��=:�jkk���/���cx��W�_����$&&j?3~��N1���e��^c[�Z����<��s��?***����s�����8{�,��������B*�j�����E���{��~���3��W_<�}�����{��w��;��l���[QTT���4�������(,,Dff&>��c�s�1�{�9\�x2��-Bjj*����s������������v���l���7=����1}�t�"�a����_EEE���������R|��G����vmLL�}�Y����u�=j\��F�w�y�:u�+���S�N!??r����8u��z�-���S�N�iwJjd7_Bt�F��s���i}�Q��k1��k�:z�h����{/������
��������{��7V���>(Z���s�b��E�����1s�L����'99�}��v,�H�|KV��&�J�IF�R	�
t�joA@HH��v�������&\H�4�_���������J
���n7��^pw����X�Y
���#0p:��]=A��n�s�*��|BU-6g���D��o{[tt�GF���s�T�TQ�n�NV������������������V�PUR�b���n�xg����'[5�u.^���PT�N�<��>�H;_|�f����6,,[�lA�������###��X������������:///<���>}:���-@��{7.\�������s�=���=�����9c��3o��&\]]�\�_|3f���F���c��������q��>�s��1�C��2e
�L����~j��=!��[������w����C���}��x�b�����u�Z�J������1=<<L~�o��=DGG��O>�) �}�F��#G��o�����p�k�o�����7~M��3}]���������;8u��vlkk�]�v�_�����N�:���?��A�t��}��w�1c���~��.((L�:��o��|��!M###8p��N�/p�};v,������{C.�~��'$&&B�Vc��)��}�N�p��x���ppp���~�������m��k+Z�{�y�f�y��z�������~�!x�L�8Q�������������m>tc-:T����$%%��N�2_}��^������1o�<��7qqqz]P
IKK���~��G�FDNNNx�������sM��u+^�u���uJ�3f��)�[�r%^}�U�{]\\0�|�?#G��v\��e�q�&H�Y�:������]]]�`�|���F�����#66���^�8�.,�#��5k���.))	O>�$�l���p����T<��C:��t��;��Ct���^y��'7<���2d��r�}�v���R)V�\y��4�|�]�V���K�.��g���~(z���������P������2��N�R#�V��rGg{H,PD�Z������C����R��w��8�����z%%��xvz��d2�]��9���P*�����sQUu��=-;��+;���,��u�����'��Fy��ju=�z��)�BgW���~���������������������{nK�a5�{C���Z$���>�����+��w��ih��SO���h�������'�|bR�=z������|�
�u���A���X�v�I�1���4CBCC���k����������Dx��%�����M�D���ep���V���������n�x�:�D�M�6����8y�$���>���+u�����>���"#����:�5����.�k.�J�W����o���h����������a�����k����m3������C���F]�v��9s�y�T*\�|�;w��m�4���>���W#%%������<m�W{���a�������%K����_p�����osy��7�����u�]��������������W�������{���-�-,,D\\�������III����l�����~�}���^�7l��W	X�:�^�����������k�QQQ�1c�t��������"!!A�����?~<��9s��P��]�dQ��{/F������?������~�V�%%%��a�}��uo��f�����;W�����26_|��N���R����x��Gt�_�`�v�z��dkk���W�l��e�M���"����6lN�>������U�V�4/��j��a.�_����`�s���pw�}z���{SVvg��TVY"E�6I"��������C�/ 6���=1��EtN��`qr&��N��f+CgWG��:��k��]S^^��~�I;���7��p�>M[[[K����K4H;>~���c����G��4�����$���7��_���T;^�b�M���J�x�������j����,y�u�Vh4���[�Z4^KX�jU��K�M�6Mg|c1FK��g���yhxhh(/^l��o����W����HNN6:��/��[��s�������M�M�4Io���Kur#���7����=l\�n�kH^^v���K$|��gf;�7���z�����O�7u���i������x������W�^:��v��J��[g���u�����h���O"����������d����������/ ..o���N����t<��3V��L��=�����#,,Lg���Gq�=�����{�������sg�������GEE�����{S�Li2���
v�����Hii)}�Qxxx�o��������^�u���
�����~M3g��y�p�=""���0`|||0z�h�={V�F"����?�{?��y���D�;�$�`o�_"�6�������S*�������P���R����TT�#>�a(���n�����1TtN��CI�1��"��"��LU->�*�X|1}=] 5���\Y5����e=QK;q��r�v<a����|||n���\n���5�t��Q������sUee%~�����������d�1c�I��=Z�p����6K^�+777�{��F����DHH�v|c�\K9|���x���Fw�������w�����J�zE���:u�Q�z���3�'O6j�^�z��333�K��h/�a���-y
���N���q����,a���F@��}u���1%%%���������&�5v�X�����E�sK]����j��k���SO=�S�w� x��g�H}�����|���h�,������#�����q��9������+:���k�x�W���u���� 4T�f���j$&&���K:�i��{���={L~z�����g�}Vg�F�Aff&���P\\�3����o������Dd�:�
y�r��0g�oZn����R����Bw����%d2w����:���� �Y(S��Ex{� ����2����`o��]
��O�G��BfKp��������B�AR���DDDDDDDDDDDDDDDd7��@�������Fx�������W�^���������7�|�����V�C��edd`����:u*"##���;;;�<O�8����}�73f�������
�:��B����� ��kW����t'''xyyi��tF#}QQQ&u�������qC��p��)���Q�L����:��'O�_�n����bR�����o�����
��-Pj�oee�q����=�����/�����#<<�������;/����������:[��}��F����>�=zT�F����X��_K,ql������EFF�?���M�]�t):w��+�J|��gf����E{d�����?v���#F��V777,\������/�hR�M�>}p��9���KM~���K|�����w/����>�u�o��68�a��\gkk��~III�~J�������\����Ro�lmm���':�V����
pu���Q�ac�%�jj.#.~��s-�+Q[ck��?���{�9����(O�_b)4,������7���6�������V��#"""""""""""""""�KOO�7��t3��$����=����Oc���HJJBaa!����:�5n��z�*���~�����_�����/���
��Y9N�:��w����������C�;v,V�^��G��~�� KKK��.���OQ�?l��xd��E27�������Y�j���Wu��{�6i�>}��������3�����1j����-�'�ok���Sk}���o�����[o��?�����(++�R������~\�rEg|+o�0�s��0�^7.�{��L��L�0A�b�K\�3ggg�ms��5�0\&���������*����%2�D��S�b����������������r������^^^���7�w�n��(sqq��o���+W���SHJJBII	�R)���uK?X�9r$F����l?~����������t�������'��������t��������U@@
Eh),,���?�����C|�,������2?��~	G�P�5D��A��J�R��$ �������f�/��%6t�����T����V����<�Q�p����R�twFBi���J�Abi��u�J.DDDDDDDDDDDDDDD�����������\��#Fh"~��ry�������;�Y���*�����/������#%%Eg�}��a��};;;�q�����0s�Lt����1KJJn9WCZC���L�3R[RVV���D"����I�{{{<^S�q�������Y���-�5�������p��f����~4.N3�p�T�x��u-��u�=+�>|���7^{���f�D���=j...�b7K����]w�������q ((�������A��z�_���8����=��d�{:�uYYY���+��1������g�����A|�L�����:��!�]H$6�����]��%%G���R�e:~���bU�@<sQ���!��z�!��:G{x8!���*�"���Z��p��
� """""""""""""j).^�����-����#�R���I@Dw�_�����������,���Zg�����4����B������u����GDD��������[��{�����*))������z���a���s��������u�|���p��Y�����#>>�6m��~����5r����C����/b��x��7���������j�{;��q����s�~���������;x��^��L&�]w����#44������������c���J�����Z�v�����:���+^���:���j������:����x�,�Y���f�[�P��������E�$RZZ���*�7�A���[$$�Fm��� W .~&���..�����sr�G�p��������()���c-��'~-��_%���4,N��o���Fb�f��=�S���@|I��yX<""""""""""""""'�J���r�L����j�^p��-�z[R�����Z�����1z��-[p��%��C���u+����t�O?�^�o���i�K�.����0h����kja���#^~�e,]�����p��!�:u
uu���)
���{��w/�9����q������w�1)��x3�����Y[�j���??�nE6d^�=��N���	�e�5���;��������j����]�k�3�<�	&4�����M�3�u�=����[���bL���x�o�X�GDDmVZ�x�����v|2p��}pp0RSSE�333��{w�������?j;�<������44�">�!���9���Z*u�6��g$23�B�Q��UV&���'��,[�������P��?[]��2���~��X77'�/�A�H.iUu���O����������������nK��G��;�������qww������m7��������'�q�F�[ZZjR^���w�i�noo�?�������j����
��a��|�r444�������?�}�v���RRR���]��C4
����[�������n�X���������j�������q7>���/��.]������g�����akk{�}�y������c��V�o��%���V����:��u��]g��h�P(��JR__���V:���IZ:""�[Q�P�D� :���������7bUUU(++��fk���~_�����c*��H83ee1f������q���`��EE�����7?;��%�����\h�+�9I%�y~�K�HG@""""""""""""""�=��tD`�V���!��5j\����d��g��5j�Z�Fll�v��o_������&�u�233������_�2�`������f����w�qV�\�K�.��>�D��m�����u�Q����t��z�*����������wojJQQ���i3BCCu����&��x}������:�y��U�X��\��z���O[-�������
5��[��gQQQz�


�����Pg,�J��������X�GDDmRzE(�,��!BBB�gee��w������O�����9()��l��E��`c#���\^��
�~�e��<0�K��94h4x:9
j����urq���x3��9
��V����������������Z�A�M�J���=h�8�������>|����]_RR�R�GDD���K���1z��7�����)�o�7%�����"Er� ��'��C=������:c:T;�����S�����y]g�{�\]u��1����b����!Ct�0i�����X�97����9��a�����b'��#G��M}�,���`{��={�l���3z��k�v���.�d9,�#"�6G�� �J�h���.6�#�3www�OP���}z�L���}?���]��V�#���(*�g�\���Do�Q�KK�C���X|A�."�2��|Ru��j�/&�C"��D�����V�K]""""""""""""""������6t�Ect:��?��vp��w�t+����PZZj�����F$4���Bat�~���k���Ig\[[k�����T7�@qq�����_:���{�b���>������������U�����u��_}��N�mS�����O?�l�������^n��,����g���9����GC&����?���/_6)~K�)�r�
�������\��x@g��?����;u�#F�0GJd,�#"�6�L�D�B�Ev�3�f��T*��v���{o����h8���~1K�Dm��S��:����r�w��`g�����t5IU��ej��=��lD�
���e�="""""""""""""����9���i�c;{xb��9v[����sx}}=�/_n��������^^^:�'O�4�����3&�yz���IOO7z_???���]|~��w�����8��qq������y�����];������o�Y$�������0���(���;��o��U��op;;v��}����x�������W_�)v6l�u�f���p���W_}����@��!:t��3�c�Z��s�B�V��CK[�d����g�AEEEe�c�����9s`c����;w����o����g���?�l�6m���#3a��9���@��rrr�����\CC���E��R;���|}'<�F�����"7w��5D�����x��������h�;x�_���sJ
��b&V�e� �o �+�d�="""""""""""""�����+&��
�N�f=���3&��
.����v�x�b������������O>�'�|bt�T���k�yyy��aC���������CCC��q�k]�����7��~����oHH�yrll,����&������Y�L���������^_VV��~���_o���^|�E�X�Vc�����{�I����a���M����������8t��I1 ::� h�DGG�|c�s�=:�;v��i��'�|bt�Z{%�J�x�b�mK�.���������>�+�}������>���N���-[�����>�����~�z�c�xn�?����^����v���c�����{x����[�@����y.]��q��!77��c444`��mX�f����^g���5��������
f���d����"��9S�A	C�a��V�E{DD��h4�(��s���Lj������ �_��(77��/�$����~6qt
�/.EV�f������q�����EE����w�4A��k0<��W�c�U��2t���`+:W�P"���*yQ����V�6[�=gOL[�>!�r����;����s�c�F�GyO?�4���t�fdd`������;v�ht���g��_z�%<���(,,��^\\�
6`������ ���0:�D"��������r2k����]���_��i\��8���g����Bee�����l������w����2����~���o1b�w��������:]��������;1x�`\�zU��O�>8p���_x��?^;����������'�����#��������o�����c��7�F7v�X��<��K�b�����w��{������,���[���Z������a���z�"��;�Y�fa����h4������mU/^�Sp+��1n�8���+����Y����`��y:��>}:���>��L�O���q�wh�UUU�����s�N�������>}:�x�	h4DFF�k��:E���m������g���?��9�;vLo��������=z���m�D�������'�`���8p�����"�J��?���M�������'�/_�K�.��WPP�_�,@`` ������,����Ak���������///�����T1��-����v������c���:��������<x0.\���noo�-[���U����!""j���
�V����������C��]�T*rrr��I���\
��99_�q��J�Uu
]`����w����<�����TT�������4���
���'/\��j�y������r�.���Y��s�%���l��"b""""""""""""""j�|B:b���q�����1���4�m�p�����Dl��qqqHHHp�p�����������0xyy�������}\\\�����5e��9��y3��9���a�l��]�t���;JJJ������{�^z�%��� %%�������b������K�.a����k<��q������_~���l�:�����X�l"""������"ddd�&�����������at����X�jV�Z�T��� xzz������HKK�{����#>��3���H$��};���~m�;�F��~�	?�����
���������:��1f���7�x�����(//7�Qi���X�b�I�7��k����Guu5���s������ot��	R����:E�w�}7f������v#�J�}�v�9���������X�z5��������L4���7[9kj���_�#Fh��yyy�6m�����KH$dgg�����;99����FTT��q|}}��#���g��?

�w�h�"���a����mW�\Att4�R)BCC����\���<���DDD���~��>�-",++�^�������'''TVV�����^�%�������1c��v�����w�����~��������c�����k��w&vss����������T��>�}��1*Wj��GDDm��.{�����M��
�T*�����@�M�A� ��
���o2F���HK���K,��� H��3��|I�	(����_w��v�Sj���3�P�-����"��y��A�K��O�!"""""""""""""�����+&<���A�=M�7(�'X��^��=\]]�w�^0@g�F�AZZbccu
�\]]�{�n�:���`��]�����v�Z����:u
���:�c���������z��w�yG�[��<==�{�nt��Ag�R��������t��N�o��6��o���Q�T�z�*p��)����*�����i����������?��t{���r\�t	�N�Bbb"�^�*Z��dOOO������5�����P|���pt�}xuuu5�S�7j�(������
�7���8v����;�Z�+W� 66V�pi��q8t�<<<��)�gw�y'>��c��duu5�S�����_����39��M��.�2�����|�w�Q�T�����g[e��u#G�Dll�hG���b$%%���SHNN}� ��Zr#s^��#F`��=z����
$&&"11Q�`���?��3y�k�J��E{DD�f�5�(�p����B4�ecc����9�F�}��!� �s����u��!5�-��m��1���s������@c��5A��?'&��ccF����Ey��P/���*(�P<HDDDDDDDDDDDDDD�[x�@L_���{����^}a�������!��b������1}�j������ty{{���X�f
���E�H�RL�2���:������X,Z�����>d����6l� ���i��������e��a��Q����Q�������0k�,�<c�����'������[LL��]���G������;w���^{
)))���;��!���a�������7���c��x����w�^�:�}���x�"��}L�8aaapqq�D�:o9���{���_����a��M��w/����};


Bll,>�������:A0x�`������;\\\��%�w�>�(�9������{{{<��c8��-]��k�d����?���=����OOO��x�|�I\�rO?��^!xc����9s&�������t��	111��{7F�[[�&�K�R�q�X�jRSS��k�����u�=��������������yzz��g�Ajj*�����z	�-4�����s��y��������������*++q��A�x���pu������Z9��)����]E�H�J�Bbb"
��|�^�����j��HM]�������u%�u���t�<lJe�^�
��At> `
C,���ex��U�9����+��X��y���
t����^��E�u<�����Z��DD-��a"���s0�����i)�J\�|Yg[�.]��n��
�uP64@fc{�[.��k�j5�=�K�.���vvv��a����m��������������
888 88C�AH�e��0Eii)�9��W����
NNN��w�i�.s*�
����|�2rrrPUU�Z�H`` �������f��h48�<��?���b������nnnC���
>��=*((����������xzz�w��2d��BM�Gff&N�:���TVV������f�\�?V�X��+Wj�,��&##��C^^�r9����;��S��]k��hp��mW���???t��={�l����Z�<yYYY())A]]���������DFFu?���ul������������u��A�Zm!}k��?C��������2�eO*!N���D��R)������&:��������'4d>��\ZnpMN�v�Tu���	�����L�O�;PRrDt���BB� X����|��KQ9~+���Si�����3�+�,�\_Og\���Z�wKg�����	vR�IDDDDDDDDDDDDDD����uh�L��D������nF�����q��Y�����������b��J�����N��%�`�8mE�0m���N��
		iU��t����c��Hw3� �_�~���_K��,���5j�Y�i��`{ecc��C�b���-�
���%"�6A�� ��^t.���,�0�����YQQ���r��4�#���o+�����B���G���������\CC)���-_��O����5�x;���9����n�O�Q�5H*��xDDDDDDDDDDDDDDDDDDDDD��
""jrk�����s�.|�������333�n���� z��A0�I���w�;�T*����E� ���h����'��Pe�|lm�V� ���g�Le�Es����	������*U�����������������������ZX�GDDmBZU��v�  ������pqq����EII�����az���`kpMq��=;*�����Z� ��D��i4J�x��z`�����J<��i�(�\�eR��p�Sj4H,�l�"�5�h���Z=�Z���z��g{�$���*Abp>++j�y|�G�O��!��\SZv	g��T�H�n^^wC"/f���������V� x��w��T[�������������K��jPZ<"""""""""""""""""""""k`��z���hPkD��]��M����OOO�9�\�������y���
�T��TT�!>�44��tl��H&s���P������X�`��V��]���Y�����`#����n{j	%,�%"""""""""""""""""""���E{DD���W��n��p��r6�Spp�����(��y�DT�/!��\SUu��A�(6��Dm��[�����54������s�����|�E��'g�^e|g�[��'�Tt�JUJ�
�ODDDDDDDDDDDDDDDDDDDDd
,�#"�V�A�FVM��\GgH���O����S*����5������66^�T�� >~���L>>Q["���68_Vv


���.A�����]��c]F�E��$�z���/��h|"""""""""""""""""""""k`��j���Pi���\��L;�D�[���|(
�����
�����m�kjk�?uu�&��-qp��K�9�F���C���V�5A�7g"����9tvu������9
�L?��&,�#"�V-��Nt��T?[+g��������_tN�V#++������	��{{��B���������+��������Nt���
jj�,��w���.:����L����/Dy��WR	��@�6Q�b�
h4�""j�X�GDD��\�FN�\t���$�`�������d�����P[[{K�upA��o��fp�\�������xK1����^^w�/*:����y��5>������r�M��h�Pg{x�����)�������������������������Q��Q]C�	wv�j.��T�� ��n�����#*�[89u5����������-�!j�\]{������RY���X���i#����?���
q���b�A@oW��q%U|��Y,�#"�V+��Nt��L
{�M�|�������+++Cee�-�����������5Je�AY����Z� H��3��|yy,�2��1���;x��i,N�D�Jm���v�w��+�7 ���b����������������������,�E{DD�*�*U��S����8@+gt��H$		18�����X66���%���\�RU���h����8D����\]{��i4*�J������V&:w�N�5�y��T����J��m���������������������� �Q��Q-�e�]�������NNN�s���(+k^0����n���P�k��z$&�GQ��f�"j����B"?���f��&��9x���."������S^m��>��u���lP�re��bY
�����UJ�/�s����@W(2An�mO�V7+�T����?���(�k4��{�5+Qk$�:��{�����CP�,����n���CtN���Y�U5����(o��z��
J5��Q���=""ju��(�/T	sq� *� srss�����\}}=����C*�C�^��w��5�I��A^���G�����������RY����V���.��`� :�N�5iy��nk���:��H���Xl"""""""""""""""""""""K`��:���@��xaYFpp�����l�T�f��Hl���F��=��*5.$��������5>>�������P�Z<�E���]�����������J���`�?"""""""""""""""""""""sc��:���<�l�f�Y������E���g��[��#�"0��&��\Z����%&Qkag�7�>f�(*:�Fc�<�z�a�������3Qk��9g��9����$Y�`�����������������������X�GDD�J���
��������`�x���\444�%� H�uB��6�.5u5����J��xz�	��Qt��.������k��gk#:�^��[i�����2���e5�S6��'�5�h���ZC]� ������uvvv����S�����6[,A���K���&������+kX�G��Tj/��
��Z��x�62��lp���b��P�;�==���)5$����
,�#"�VC�� �@����
�mdV����T*�+,,D}}��b	����g���M����)�V@�Q�-6QKrq���}���JU���V��/WL��48�Lr&jT��z���v�QR*jP� ������������������������5a���r%*�A�\��
�H&�!0P��H�� 33��1CC�k��M����
��K��X�����A���h��|yy<��b����s��lD���+���<����J���YtN
 ���"q�����������������������E{DD�j�U��n�9�[7����[[[����RTWW�=fp�lDv[
CEL�����?������������Qf5(*��Fc�<�ldXlp���b+�L]77'8��L�RU�29?�DDDDDDDDDDDDDDDDDDDD���h���Z�F���z�9[8��V���H$6\����i�b������c#�������p.�)�Tr��'�6O�; �:�������:�*y��r�LO���^�B���].e�<]�����r,�#"�V��^a��#������!���ptt����Dyy�E��u��^=?� �w�����8{�q�Tu���Z$[x{�08_\|*�x������;���z^O��H����p������Ga��"q�����������������������E{DD�*��'�����B�&��eeeY�����A����DbopMi�Q�93Je���4
��*(�P*�,�3��rv�
���JU����V��U&������s�q�����$��(/����J*��%"""""""""""""""""""�V�E{DD���
�����:��N��Uk���WWW����Z[,�������sH�N��W�"!a6�u�WW� ��z�'<�#���#}����8|�/����	� ��zTW�X,"c	���0��zEE"��B��2���{��b��N���l/]�������=&�9�
���Z\~��*��\���:�  $$��|VV�j���9xxB��_@&/�����Ox
E1��".nN������QVvJe��z��ee�q��f�����(.>h��@d[[O���70�AQ�~�u�[�9�
���Xu%��1A@�&���K&�N,�#"��V%�eO*q��r6dgggxz�w�R(����h|7�����66��UW_����xv�+bM:~yE,��C��g��P��t�n����d��k��y��:o�<\dR���p�����]Ze���v�s��+�7 ����1���������������ngA�'::��S"�-DGG�|�222������7o��	�c�X��by��V�X�����W��j�����d-���Tj
�V��;��F����*$$eee���rrr�����r�j��D��7HH�
��@t�JU���Q^v
}�~g��f��VH$6�����_D������S'H���J:���x�����gS2qh`78��f�)x����b����J�:�C�_^�m���s�8q"�^�����;����x�"�^����<��\�/���~~~���Bhh�Yb������s�t����������a������7K�.�Q����C��/��p����������/

��T*rrr����!NN��
�<������+
?���a��'��pt�����9��%%���{�UrY�)K+�]��7�]��UWr�6"��1}�m�d����z�
*�V�����Yc�v%%%���{������������u+�9�S�N���c���3g-ZOOO�c��j:t������/$%%5��{��x���
GGG��P�b�"""jQ�U�]�l$���
�*((����!��-���c(�G}����TV���9hh(�X"CA���H��*+���>�*�8���bp���.�2{�(/���PZ���o"""""""""""""""j�:A�V�X��)�K7��#F�h�t�k���)���u�����b��}�?�g�n�,�ZVtt�����",�}��������w�}g�����,_���������g��=

�����i��������SO�o�����5*�<v�kBAA.]����dee���
555P*�ptt���|}}���0t��
R����DD��A����N��I�hPkacc���dgg��i4dee�s�����>������c�R��`��q/��*����"�'j���<<�����|Q�~�� X���<]0;�_������b&
����/���A'��z�*��XQ���f�GDDDDDDDDDDDDDD-K��@���ZA"�����{���n���_j�������x{{�`FDD����;���������z������PgMaa!�N��O?����M������zzz���NNN(((@ff�������������Y��,�E{7HMM���C�!66999&�ogg�>}�`������{1j�(���Y(["��/�F�F�;R������[������444�����NNN���*�b{���_�I����uyxBU�E(�zsry*+�����*�,����U��W�����25���5f_/�U�A�����*tuu������������������������]BUQ!j���T��s2[;8y������]����������[�u�V�����#??_;�<y2�����g��7n�
�A��C�zk�������c��������@�Vc��2d�u�fT,Ap�=�`��1b���u�333����b��MP�T���:L�8���h��%K���������_`���HMM�n�("iJ}}=bbb���{���3ff����'�������yi"��N*��#���
�T��� �����gee��gs\��?������h�Z�Db�����Yt���o8;w�T�h�\�eRl��)g����W�	>n��j��.62D�9!��FoN�� ��Qf�GDDDDDDDDDDDDDD�Q�������,�6J������Fvb<\;�#�O<�;Z/Q"�V���K:�=z�P&DD����?._����;�tmXXV�Z���'c��Q(++(
,_��}�]�����b�������;\����c��q�0a��k�����K/��m�����n�V?��F����;c��U�|�24��� ����uuu���_0u�T���c��%���j�WND�:(Tjd�����9�C�����6������^t���������:���q]yy��S���1'�p8:�����r�m�\��pAt���s=���J���1�x8Cf��p��uf�GDDDDDDDDDDDDDD��P_���{����&��T�!y�oH9�
��� �g���:cWW>���������*��Q��}��[o�l����P����w�y'.]��w�}�����=k������w������|��n��=�R�-[��K�.�2e
���o�Ez7�����qJKK���o�S�N�9s&��?���Q��ZS����a.�M��M"� $$��|ff�-u�5V~�/;��+�#����H�Tt���<��r�����������7`Ej�Y�9�����$:��h�X�>������������������b���[�]n�q��\����EMi��2#"j�l�@D�bf��	�������dff\���P��,\�nnn��\.��C�L>Y�����F�/��+W�DFF�^q��5�����O�>���BCC8::���2�uuu���Cii)��������/"11�.]�R����J�;v������3gb����BD���W��nw�I��@�npvv}bCMM
JJJ��m�+WsTV&Z������j<������c0JK����Gp���?��I&��n�x�����y������^�{�WOwg\,��\���K)�Aw'���?��I5��H��g(r�OQ[���~B�	����,�l��j5�?�K�.!??�����a���e�����IIIHIIAYY
����������
��PXX���$\�r���P*�������??�f����G||<222PYY	�Z
GGG���"<<={�����-�����CNN
!�J�������#**�E\V����S�N!77W�54h"##-������DLL


PQQ��<:>>>f�W�\���g������rx{{c��:�(M)))����������Rx{{c��A����M�MMM���'���A�#F 00����mi��azz:��?���LTTT@&�������2dH���������g�������������"##��O��6�~���?~III(//���+���1|�pxxx��5dff����(((@YY�������^-}lM\]]����������bt����qlll0d����G����@jy��n����c��EHLL�)���f���������#1r��&;C.����8x� ���/�<yR/�J���_�;v�?����������Yq����z�
����tsv�/�(A�.��gee���S�I���hPUe���UI�N�D-��}��.���\oN�(BEE"���Y%��.x,�����?���C#�f�B:[��=�[\�7�p��
����	""""""""""""""2���z\����
��S*�����}`l���z��N�Ra�����q#rss���R)&O���k��c���#!!�~�-����s�����p,^�������C��5to���+�r�J��<x#F�����hp��Q������CJJJ��{�����{?�0d2��y��s'6n��'N4�N*��w�������h�"xzzu�c����7��� ���|}}�`�,Y�...�5b�>|Xo������7j���X�b�Q�ZB��M)`��u+����������]������0���G���[{���+�����O���5k�`���F��m��i����z����&s���y]�5��R����u+6n����$�5��
��/�l�ki�}������{�!&&Fo���k�}�/^��e��a��]P(z����>���q�zs��/���'O��	���'����kv-Ak�����z���o���q�����\+�J1z�h���Kz����ot����BCC����������n�:|��7���2����	c������1n�8��7���X�v-6m����R�y�T�)S�`��5�T�P(�y�f|��G����������I�&�t|K_[��P���-�q�fEE�E��yX��F�={6�
����b=WWW<����?����u�V<���f�����a��X�r%�;���l���{���;��htrQ(X�f
"##���7;6Q[�Q]C?"��4��j�\]]
>�C.������1U�j(����S���JUc��D7�Hd��ep����J��}��?B
tI��7`y��/�����e�?�\��C��������������������<�N���2�����A��#9v[UZZ�;��K�,-������}�����M�����#**
k����3gnZ<������c��HMM59��Z�d	���n����7-��s��!::#G�4��'�\���'c��i7-T���			X�|9���o������M�]w��?���`�p���k����]�"66����!::� h�*�k�^x��{��� 99�&M�k��f��������b�����k�}'O���I�0~�xTUU�R<�\�|�<��h��1v�����(���S���VD<|�p���O:�W�\���G����v�����u�h�Z�{x�]wa��)��}{�{��s���{1r�H,Z�J��������aaaX�vm�{��s��?��	&����F������!C�l�2��=��{��w�a��HHH0�5�:u
��u�3�<c�`���<}�4���>L�4	557�������~}III�)�svv6{���rrrt����L��������+��F������u�V�����?���#����1<��S8v���;����pvv��i4dgg��;DDmQZu��v)��l��
�[pp�����l����V�Lq�Z-�+��89u��S�9�Z����G��T�M��~�m~)����V&��S�)p�%���A""""""""""""""�����]�h��+�Q��a�mEUU���W#:v���t�����}�����d��4�*...�����A�%z?��0l�0�<\�X�����v�����[s��Q�5
uu����h��yzE.���w�����!C��G�����aa!���;w��������������1b�=z���$n���X�n�v����=z`���_�e�����f�7����;��S�HF"� <<����`���(++39ftt���p�}������o���c�0m�4�g��������{CCf������]sV�^�+Vh�������wo������:����c���hhh
o�����9  ={���!C��W/�����������������g��O<���j��R�aaa8p z��uK������q�=����3�m���0`z��	;;;������4i*++�:�/����#G"==]g��������[7�����F�%����%��������3��N������;w[�8���]�]��hp������C8q�f��
�j��G���;����k��f�7DD�IM�
u��Na�&����������sJ�yyyf�'��L��D"�U�����G@����JF]]��r�����o�$%�
�+����W��\fM=��YXKDDDDDDDDDDDDD�����y'1��9gZ���j��%�����A��E�������t���"==iiiX�`�k�~O>�������0m�4|���z�**++q��E�:u
qqq���Dqq16o�����~����?�������������u�?��#�9�?}��=�������������(--��p��I$$$ 77���X�z5������?K�.m�=����i6"����K/!##�����'������B���c����={6�<�Z���3t��>>>X�n���������O#!!����B��jkk1s�L����{��
���F�{�n�=�={v�9�WG���5k����{QZZ���$������D�n�t�{��������K�,��[�d�Q_+�R��3g"33S�M&�a��������+W������b��y:����a���&������o�0{����o���(**��'h��f��B�@@@�n����\�pA�����!!�<t���/��2�;�W^y0p�@���_())Abb��3����C]�p[�l1�5���=		�s�=�������9998w�N�8��g�������X�p!�������E���{��~���3��W_<�}�����{��w��;��l���[QTT���4�������(,,Dff&>��c�s�1�{�9\�x2��-Bjj*����s�����������?��fgg��7������?������6���+***�����d������>B��kcbb����<�%���Y}}=�y�������U�VY$��;t����b����E�a���Vf��aX�v-
����pss�+������?x���u��@D������.m��.����b��j����<t�����)z�J�!��A�4_����� �:Y-�!66.��������Gp�,�xq������J*�!R���h�������[!Dy��P����NW�_�^,'"""""""""""""jjJKPY`�=R�����8yzY%^kt��I|��G�� ���/0k�,��aaa��e�����&�7nf��m�!��yyy��'�����1f�m����q��t��]o�{���:����k��5g�����puumr]`` ^|�E��1C����������St���>��#��3�`�:`��)�2e
�~�m����[�n<�<�w�}�%	��}��a���x���\+�X�j�^�I���Eczxx�����{����'�|�S@\���1G�A��}�������o�������Y�o��dg�>��{��F}��y��:uJ;�����]����Kom�N����c��A:]����;��1���Qy�N������v�2dH�����@DD8�S�\{����}���w�������~�	���P���2e
�o��S�\+:^�p!t>��~�)���������n��w�y��g�qn�{���~�x'N���z�j<��z����k���XLC���4{3IIIzE�S�L�W_}�������`��7���C\\�^TC���`gg�������wrr�s�=???�k���[�����}m�S*��1c�N����+������_�������c���9r�����-[�����_�~z�X�:��N�:���*�������8}�4~�����~~~����o�}������+|���
~��uh���~��W:t����������
�\��q���t:DD�^%^��n+���ih/lmm���':�V��~a�� ������gW��,�V���?ll�!�P������rq�J��[}:v��ao��
l;:�����#�N��Z��b�e��U�-�'?9���7�bR��VM+����w��F����z�)�����?_���1z��a������o ��s���[M�k������`�F�����������:m�01�.]�������Nt^^^����������k�c��$	6m��S��g�������H����G5Yd����W_}Ug��a��nJ�R�n�����{7�?>�x�	�m6l�*AIDAT0)vxx8�m�&Z�g���C���F]�v�)R�T�|�2:w��m��5Y�����"""B;NLLD^�u����5����
k�����1ct
�bbbp�����o��&������}���������777���^�Z�`�F?�0��tcm����GR�?��-X���-��}�������t���>����,��1c�&N���s�b�����={{{<��8{��hQ�9<���:Wprr���_��"�i���nv�jM�����u�>���n�
%��
�s�������J�Ro������fki���ee��r,����Z,��)||F!7�{�����pq�
���*�qw�� |�]$:�$%����n��EA@/��-��+�B���l���������������'��F��/[:
��ON�z��u��={�������?���vloo��+W���o��/��
��R��t��A���������w��)F�
m��������O����{�D"�)ph�/�������b�
����J�x����������g�L�>�,����u�U�0[��U���j4m�4,\�P;����dZF��g�������P,^���}�x�
|�����=z������4j��_~�Y�N�:�{����I�&a��-:��.]
GG�&��&M��u������������5����v|��q�n������;vh���}����������2j����u�f����X�i�&����[o�S�^�p�}�i����kT*�^������������-�~�i<���+>���o�y�f�mo��V�E��:��N{DD���U�w��0g��72�����o�����:L4��������n��1���sM���X5����w�P�B��^�1[�G;�9�����p���l����������������Z�'N@.�k�&L0������j
3����OHH�J�[��cG��������+++��/��%�������L&��3L����:����Y��]�����{�5j���'BBB�cs�/w�>�3�={����<==q����l;r��{��R)�M�f�ZC�N�j���={��A�������W�^:���L��k#��{x����5d���P�T���q���K���<y�QE���o_���sLII	bbb����������Iy�;V����j���R���@�P`��������y�PUUe�����`���:����E��5Y�����j���{�U���{�&�L��R)!�J�.*�X��+"V���]+��bYAYe�W@t�����"(H�%Ho$��:�������d&�L
����!��s�y3��;3����I{�j%T=���y+""�i	���2��0��OBP�9Vk��.t�E��BC'A���jjN���{"��exm@������?�+=2Wc�=�w(�_Z
�(zd.""""""""""""""�����|�<y�[��;����"�X�7�|3�������B�����������*�t���,,]��_=����Z-��;l���z���>}�]���o��e�PQQ��8EQ����m����# ��*��!!!�vjjj��!`��nU�
�}_Y���2���*L�:����M�f�>[-�5�V�uk��F������@c���	J�����r-�n��?��w��O<��3g"11:�J�����|MjK���j�������F�ryl�����m�6�M���3�YM��kIG\���BE�WUU����f���1�6�b���>�E]���R��}��i\y��v����?���l�&u%L�#""�(7�Pa4K�%jYe����d���q����c�f�=���{�8��{�W�!r�B�����N�KJ6C-N�=�� �����#'sQn��.�+�W�X��d_����Uu����������������������k7�����U�\���q���#::�����������(..FCC�K�������l\}��HLL�c�=����
'N��^���hlW��_=hk������FDD.�����K��m�����YVVfk?~\2�������1����<I�5����7S�����k:����
f�v��Z��hm�|RS~~~m�Oj���;��������6lF�������a233Q^^����ey�HOO�k�%����c��_��u��G}������_nw�kIG\�*�V�~�����o�����q�F�������[om�<���KP\\l���7�\E�:�����+2�T��x&��h!!!o�����Fyy�G�	
����+=r,gT�0�t�:t���*D��d*CE�>���xB��JW�,6���S��kD���q(����j{DDDDDDDDDDDDDD��5O^h^��5��OOOGJJ
>��#X,m����`h�����{7�
�u����&�-%�)�J|��wHJJr�g��MX�p!&L���� L�2������Z��SUz��
���3��JwM���d2��>BCC��%�V������=�3O$�*��c��;�`��I8|�p�����G��4ww������%q�.�O��~����?��M�6���eee���K�n��M�6�XL��Eg@DD=�(����N���UA��{9"�&A�'NH����"88�#e���/BE�n��B�h,��cb�����2��A�#,l�����/+�	�P*��A�+|�2,O�����`�����W�bFXP��
V+�G��t�$�:�'*k18����ue555vmg7�v�y����F��9yyyv�����I�&!))	����h4����[���/c���n��V����9s�C����C1a�����z����/|||��|���\N&ILL������k���7�D~����
�l��-[����������/@�u�YqGT��Z�Vp�������s�x~���vi?�R��\���������{���
.��"�=qqq����j��O�>�+16����~���y-��u�;;v,������W���\��M��������p��1����@���OI���q������O����q��aTVV",,��
��9s0z������S�
&T�������*{���� J�]���%%%��R���?���7�l���B��lD���00�e�S����Z�@TWw�E3��-�����xFj0?&o��H�?����A��)���$%D���z���e5�����[""""""""""""":��5�y�-�6��M�.>������?�;��Sk:wA�����:�����uy��o����4[;""+W��e�]���|��[q��/�`Wi�_�~X�f
.���V�u7����O<��ql���7o��-[�k�.������h4b����q#~��7��S��8p �/_�V<���r�����������s�x~��I6��z�!����/�o��6z����~]�����555'�����|�_~y�������|��v7�^{�]�����1���q�W`��=�m~~~��������8�����'���U�V�m�;wn�%F���p�
7�JW��p���a���x��71g�����2����2%�� ��{��'�������#�}���		�\������I9�8x����w���A.� ����H�i!!P[������������F���xM����*��s���h��iyxkP|���*H
� ���?V+�U� %�;U���������������A&������40��W��#�;���LAAAvm�^���M��Z��g�����]��c���oYY�[q����n����?��c�	M�5N�L�	&`��	X�hL&������~�)N�>m{��I��7����;F��Qq���)���=k�����S����V+��������'��K�TZZ8`k<�|�
T*U��z�������������������Z��k�'���M�>}��g�����h4�/�~��7�6�Z���������=#y�L����=���{����{/�}��V�,.��Rl��	�(��A��EQ��5kp��W�d2y�G!"�RDQt����O
E����{�h4N�0b2��~q��$��""�WML�������K���B�U(�t������a�����\��b���X[\�J*<2�0�?N>�=Z^�z�t�W""""""""""""""�8����<_?����4OF;z��[�>|��qV���
����]N��c���W[������������\N����Gff�G�P*�;v,�}�Y�����7��Lvn%��
���j�Odd�]e���l�E�S�5���7�������tqqqv�C�������G���;w�����N���]?����M����ks{JB�����&�yS[����R�ty��b�_��Wl����M�P���>����S=�<�I{���o���w�=�����/��]�vhL�;�%��C��_��O>�q?QUToD��*������N=W�����������*)��<�U�>��.tk���1l��5�K���+�f�������*Q��Z�\��T��
�~�02P�{c����dJ��O$�U�1(X#�gE.�i�DDDDDDDDDDDDDD��.Q^�+ �4����]p�v��[������KKKa6�����$��HKKC~~����.���M������������wH�� ���������n��m���J����N]]�m�rGh������< ���f��sK�&��o��c���y�[�7��xD�j�������\C&L�`������L�b�v����^����l�vDD�K�����o�_��m�L&�G}������!R'`����m�f{�)f�j�2OMM
^y���:�c��All�C��������Qw�Q#}��iZ�hJ=����������\:#G��/\���{��"�n�B]�x���������Ch�hc�� �9O0M�X���U����A����N���w�d��bD�#����������x�T�G���L:A�De-jL��2HDDDDDDDDDDDDDD������<)^���7n�]��~�eee.�[\\�rBB�����r�o����c@���yo]]���z3Nw5M��^�0���.�k�X����i�8��w���8��~z��K$�t�I�&����Yc�|����r�]��n���=�_�zn6������=��i��A�P��6l��S�����EGGc����vzz�]5����u�;������C�ui�����W������ob��9��:�����n�L7l�0��;�_}���M����/����"���������k�N�&�	���^�DD]�U�U� ��������Qtt4�r�d_QQ��f���?	}�<�����8a&M<�	�����0q�>���F�>�����-AA�0t������N-FA�W7Q{���B@�`�>Q����W���#�ayr��7!��+�]qE��Q�e��J�YE�@iu�� """"""""""""""��b����C���������

�5�\ck744`��E.����O��8b���s�N��<�v2�N��k�S@#22���j����c��u.���������y��

�����+���O��9++�C���#��������[�x1����.����������x���]������Kv�0a������s�SO=�VeM�}������=���Z����;`�Z����=��#v�|������W���Ejj*>��#�mW]uU��-\���u�+������{4>�<�����A��a�Z����>���'f������O���������6FE�~DD���:N^�&j�W.��M�T�W�^�}�("77��c
�?T*
���RBta����dCH=�E����9�|!! �IW����@mm�W����b�� ���<���������B��Nzu=*�v�ADDDDDDDDDDDDDD�I;*?M��@��A�V}����y��7��'������������9�r9F�mkb��e-�s��i\u�U0���?���8�����������]�766������={������������ns��7c���.�///wx�G��0.00�=���m�Zq�M7��o�u+�}����olq��A�l���zl����9`��y��5o�<�����/�J������/ZM�y���]NP���r9,X`�����/����~~��CR�C=�����1n�8���o����O���;���W^y���������gw,\�j���w���;f��
�����{������o���qHKK��3PPP��1L&V�Z�%K�8��#��gy��R]]����yyyn�w��Q\z��v7>������_��~K�,�K/�d�m��E<��0L����m�8p`���F#~��7�74�������[��H�������vDKD�}dTK��F!��H'���!22*�t����R���z9����]���/p��g��c��^���eD���}2�iI���Z����pB$���H����X����^)
���N��������)}|0��+�Pyv��B���K���G����7c���w�ak���[n����n�����{��w�}7 >>��y���k�^�p!~�a�m���X�lF��������$����d�6m��]QQ�1c�`��%X�n~��g���	}���;w.�������n{^^���a���(//�������?����'c���X�hv��aW�����z|���=z����a����.�<���>��3g���������q���b�����#


��{7^|�E�9�F�j��%�\b����k������/������������BCC�*JZ�V\q�X�r�C��#G�`��9���� �"�����p���%���1O>��������?w�y'DQ�m���]� E�L��}1v�X[���'N��_~�P����C���q�=�@E$''�5������|W�Z�k��~�!6l�`wn��}���tH���/1h� �Z�J2�<//���>�L��.���D��"�����_#00��m��<x0-Z���4���������c��������y����*9�#���b�X��[o!11W^y%V�^���t���YF������^�1���� X�b|}��Y�j�q�m]t.��"��5�}?~�sy���!=����g+�����8~��]hhh�%�������+.��2�����mG�ATT�g�'"���V9�
�}��>P��7~>��������orrr�~c�
��W�l����OI���	G��
��}���1^���������:�����l�By�n����Z<j���cq��4X�����
�+.�U��+w�/�G�kPe�8���6����0�b""""""""""""""�]_~
����u�����O���^	�������e��a��}8p���5�+V�����������@��#33���V���o�i� ���n�
o��<h�c��ex��W��_?�������X�����������'O���������~k[8��������_��'O��~�a|�����9F�O<��~�i$%%A�����YYYv�������O>AVV��q���b���X�x�m��N��J�BEE222*
�����?tzL�L�O?�W_}����(�X�v-��]�Z���8�������{�]1w�\����u�N+*-Z��<��[����K�b������TVV���n�<�>}�@.�#//�.�t����3g�-I�|$������b��)����XA��_�K/�����t:�s��#F�����r�����+�<y���XXX�n�������d2���PTtn��F��'�|�#F�<Oxx8n�������gsqqq����?222���������c��y������CHH
QRR�r|������k��/��-�����v�


Edd$4
��������st�u��L&���{|���_EFF"((�(���YYY���A�{���+����9~���@��m�0}�t�����[�r�J��#�`�������?����� �1cF����T=����'��k��*�� ��������.�������n@.��W��+��X�:|7*�y1*��	�aa���������������������Pbl_@�  %��k�}�*�}DDDDDDDDDDDDDD�q4��f6B��k�qB����kf3aOB@@6n��Q�F�mE��g�]�^@@���[�n��T*�n�:��g�{�Z�8y�$v�����O�%��������?���3i�$,_���Z��t:���[DD��S0��8v�v�����L[��L&����u�]n����bAvv68�]�v�����������?����M�6����'
��-�iii��k:���l���������t������O�������W_����n{MM
:�����%�M�:�~�m���z���Dl������j�"=={���L\�1c�l�������������{��9YSS�`��}v	{������������\���Z��������7�x���c�Xl����w�����L��={�HV����8z�(v�����T��C�V�%My�:�����q��)���{����S�$�����_~����1���'Lkw���g�^�O�8���g_����W]]��8������z��*��^�����H���:�����,)����������[,�8x�6���~70��������Nz-��7{�9�����H���,x<-��1%��@���������:C��ODDDDDDDDDDDDDDm���A��K�<�rD�rk���^H��r$M�J��w& 44;v���%K%9F.�������C�����*66{�������~c���O?��e��������@jj*�~�iL�:�z�����K�KII��}�0g���r�1� `�����s'���������t�RL�6
����}���s�=��'Ob���.��P(�l�2�<yw�}�K�u��������q�F�*N�8'N������+��			�j�������K/��w��e�]��� 22���6n����@/G�u���{�������P��)A0z�h�[�����V��b����z������Z����������c����:4VJ�������?���o��������N�������������������n�/������6��������w��o����S�R�Z/��1v�X,^��O��s�='9������[������^��c4��`��iX�f
�9�)S�x!R�N����������^\��w�yw�y������())�(�g��AXX����|�
���:�������'���A��c��a�������G[|��MUUUv�^�L��j�K�zLV+��Q��%���Gy?(��DQ�����&�������^��5�(��������1*U(F��~~	^��}x��,�zdg���*�Xy���{5�C�u��/
'�J���#�ww���l*(��U+qELh��C���x&"�<<u����:��DD���`�����i��f�:u�n[�~��nuW�e��g�BuIj�%0���U�RCmXB���^X�Vl��
iii(..�Z�Fbb"&L����9555����q��iTVV���1113fL�7�����2���o���Fuu54
0n�8�T��X,HMM��S����o[��j����#!����DQ��c�p��1��zTTT@�V#00			8p z�r/!�;+**���[QPP���Z�t::c��q��I����`��](**BUU���������3���g������(++��oGaa!�������q��9T��
DQ���mU��^O"##1p�@<�[�{����s�N������������Ghh(�������R^S��v4������#==�����#00AAA0`��Rru��~�3���SPP�s�������=z�(���mcZL����J�%����z j"��+��A2a�<�9g��;vL�?77:��K��I���$,�Z~!9�h�c��[0j���9>��K.�Eh�o�������/2�{wj�aZ?�=6�fI�?q*����j{L�~jD��p�����7��]��x^���������������:�FbK�E�	��A&�\���X�I&�a���-V3j/��1����):�W_}u�_.�c���vI�A���]DDD��n��0�����.�\K�����.U��5�  %%)))�J����a���=����M�V���1u������o_Md��mN��]���� ?~|��///�k��XD��e�HWp������	�=�V�N'�g0PT$������Gx��N���`�/FF��V;�i��\����^��G|�5>�}e&;���;J	���!�_��/���w�""""""""""""""�2A�B����
��	{DDDDD��0i��!Cl|DQ��;p��	�q�}�A�-�2eJ��o~���{{ j"���`�"�� ���?@#	111N����a6���{A�A�!4���F���q���0�*���  ,l*��qE�>��^�I%�ayr,N.�������v���B����J�����������������������������=4���4iDQ� �Z��;w.***��-Z�YYY��B��W\���8`w��>}�x*t"�.'��V'}	Z_��B����/���%��f3


��{d2%^���1N������C��l��bdD���pw�kEI��vU�k��Z?�=.�i�iy(6��5������e�0[Ym�����������������������I{�;w��{A�o�>$%%��{���O>�I�&�������� �1cBCC[<nUU>lk���1i��z��j�JE�
9�}�^������{�*�6w���F/G���C������N�TU���w�bi�^`DN�t� ��I���������#��� �jx�fM�mW2a�Z�>N�k����m������������������������b���n��2��E%%%x�����K/a��m��z��V������dj�"F��4!�����3[p�^:�*^�kWu��9�J���(�>�����\/G�>����}�N�TT��������������
���_��
������L��b�pr��Q_�o���5GJ�����C�50Z���%""""""""""""""""""""r
���$�����#00@c����zg���&��������#[=�W_}�c\t�E�����������G�N*5��W/(
�������y9"�)��>|����)-��c���j�bdD�������[��b�EY�N/G�����H��O��G�����k�
$j$�+�U����DDDDDDDDDDDDDDDDDDDDD���:�6mB�������,X��K��z���\|��wv�~3f����������z���Jt*�D,���r9z��N �-���Z��������tLq�z�8�D�U���������K�UT���P���,���`�d�
����u����a:(�T=Z^�����&""""""""""""""""""""b�^3#G���C��z�j\w�u1b����1c�`����?^}�U�D<gV�X��b[P��c�v��@D�)�Mf�4HW>J���t�$���p��j����rTUUy9����������R�9Sx�k��z�]�GD��V�"(h��^%%���7��	X���k���*|UT����*�$]m�,�8\�j{DDDDDDDDDDDDDDDDDDDD�vL���R�0g�|����w/N�<�?�����*�
��q-Z���r�Wff&�V����rRe�������d2���:�����6In~~�H�

E��1yy�����E$A��\:���!���^�����G8����|�1H'��bp�?T2�������1��|l"""""""""""""""""")�<�DQ�}Q������hh��h�B�5�I{:�A*�����N��9�n�����������?	)�?�\��tLV����~��Q���T
������7X,
��O�F`��t�w����O����+�\�����K�,c�=""""""""""""""""""""j&�Q�UM(3HW$Jt�lA�AZ��g�Z�Q�����A&�q:&=})���x1*"{�����+���X�PV���#�2��c�tR����*|q��I��A�������C�����������������������������=""j��j�*{�e��M`` ���$�PRR����)8�B�&�y���i�PX���Q�#�����[���Chh(�nP��}�P|����N���`l��2��h%�D�K��t\"""""""""""""""""""":�1i����EEdV7H���(�U*��$-U������b�b4�2	����^���x�%?y-&��T*��G9�QR��(z5&�?6C�$�W��x�Dn�����R.��]�����%���I{DD�.eF3*Mf��DV��v���Chh�d��dBaa��#j����00�%���h���PZ���":'8x4
��sC!���z9"@!�|@,T� ������)k��e��!N�����t\"""""""""""""""""""":1i����%��^r� ��I{�~111�$��d2y9��������i�(�p�����������$�):�i�^�;,�sGJ����	�N��>���6V�K���N-]�����:C��KDDDDDDDDDDDDDDDDDDDD�'&��`���X�h���J������P�����m�R(��FE�&D���_Q��� �"2�$�E�����{9"���j5"#�u�V+�����g���}q�o�6���;PUu��Q5�h���/^��jm@i�v����b�1\�'�Wm�����m�>
���-T������]""""""""""""""""""""��A&�����SO=���4�6.�%��`�n���be�U
��r�S)�,�B���� ��x=��j���D-����DGG������[qq1��������@{�������oI�[,58x�6�H�������A@X�T����(:>���# `0||�W��
��������$���-���
���^!n;�O�_�����
&��6 �d��������������������������l�
7��o�'O�l�j��� ��""r���
���0n;KF	����	{`��ZZKF	��N��3��*������`by�B�@tt�d�(�����rD��'�!��}��~������l/FE(�A
��iI�/E�#j����#	���>��������Zm��V�����������������������\���&���������L�k����/"���F3�s`��
����}��`��
���FsEx�U�U#���QC-�%�<+22*�J����555^��3A@�~O#*�Z�c��b8x
�|�@�>��UUG�Q�{c��������X����6����U!F����4���$Y����������������������)Eg�U�Z�
�}��]E��}{��������C��B�TvV�D��Y��a����pg-����� ��x&8	g����HWXJ`�=�2�111HOO�����Arrr��n+2�o�-u()�QrLCC>���#��*����J&S",l

�O���t���A.�N��(
��������$V���������sz��}�!��-��;PZ�D_�e��<CDDDDDDDDDDDDDDDDDDDD����?-^�����d����������^�Ya�y�ZU��L�d��
fwe@5:���2�T�b�;.Y��o���(,,D]�c%���*TTT 88�"k?�L���^���u(-�MrL]]��)�@���~F�iM"4�>��uL��Z
��GD��^�����&D�����E��1I�E��t�Ngtj%��������-8QY�A��m��������������������������+8r�233!DQ� ������O?1a��:�h47V��T��Y&�{2!�W�O�E�U#���QC)���:� ���q����cK���d2�yAA�_������;`6�z12:���N� H���������:�=1a ]���b�C'�vN���Zz��k`�JW�%""""""""""""""""""""��8x��];>>���j�CD�������:���x|+�5�h�N�H��z|>����� �W__���/G�Yr�/�
}Z��c*������X^���gJe ��G;�/)����D6� ���P��S�~+����nW�T )P:�`��X9�f���������������������9&�(**�}/n��F(��N������*X+;tka%,�U=f��*{J��h?��E�� ���u����k7���Ph�2�#h4���)/������j�bdt>	�2H��h,Ae�A��sV?�O�r��lzr��Op��B!H'��A���r����������������������`�`[�/��U����;3":��3�S�������V��4H��j|�pR�������"�g4q��/G�yJe0R����o��1z�/8��D��C��A����N�������9���	���Z��<��(]!�?����i��8\V�v�DDDDDDDDDDDDDDDDDDDDt~`����P��Z���H��|b�n�X^�����ZX�����[k��I�C���#s�"&&��*X���0��^�����p��ju��1EE�����n>@������V��Z�(-���5�^K������m5X]P��q�C���'*kQcb�,9b�����m�qqqg�CD�	KA�w�+��|�����2z�1����������}����^��c��FcD�(�������:�"��+BC'C��}�������rD����`ab�������7�uL�\�!���}8XV���������������������������=#G�DH����;v���h��|!Vz���m�
�d;w-V��IW����@���QG���7d2��3g�����^�NW��������P8���!2�Vx1*:_)�Z�tc����l�(vN�;{���@�d_�����������A����3���Pa4�'�lL� ��1w�\��Q�a�TUUuvXD����k�t�[G�V���
Wvm,N�����c��R�D�^�$�DQDnn�T��Zm2��r���1����������UP�(�:�>���Q#� �����I'��QQ���z�����0\���(e�=""""""""""""""""""""����?=�����t���x��g:;$"���V���*D&`����������2D���ul������R����������rD'0p8�}2������/"?�^���G� GX�T��ee;`6wN2[��O$J'��s����w�
g�@?h�r������n��������������������� ��y��uvHD��y���=����\����o��.��r������v�������g�����������-[:;$"�0Eg�U�����?���^Q�|�r$%%a�����D��x�f����`���N:�!A��7�i�r9z�����L����\0��Qu]�X�&��h�s��S��5�������|���$���t�E�������"���J*���1i��j���|��2�]2A��-������WZ�K�C�2���9�+������
Q�g�X�o�>?~���0�L���G�������@&cm5:�
M��5���>�r9DQ�}����n�
yyy��4���&k��Y5
p�����m�q�<!<<>>>�}����rD+4t

����q<�a�������<:	� ]���&
uu��a�L���X�:��������z������J��'u���DDDDDDDDDDDDDDDDD����^z)���:Xff&���>���b���������c��_��|�A\w�u4h���q��Wc������w���������yXi��y��!>>s��AAAV�^�O>���O��	��o_C�T�y��'z0b"��2@)L�������jg��Kn�*�U���H�	�  66iii��999<xp��q9,�:��x\�_-8z��>t��^���
�?BB�A��"�_R����@���#�O�'����N�K���^�i�$��]:� ���$�������3DDDDDDDDDDDDDDD]��-[0e�[{��Ex��g:/�����I�&a��-��d��%(,,��p�}�!99j��51����Q�0o�<�Z������D|||�D���j��%K�����`h���UUUX�n|||0s��v�����G}�������=	�'O���1u�T�l6����?���c�����(��;�XKk�6�,�����f��%���~\"O
���?jjj�jkkQZZ����N�����u=���:��d��j�������
A�#��/����(�F��u&S9���C���"n��%�Q�x���Z��9�&�/d.^�z����BQ��5Qo0!��q��>KDDDDDDDDDDDDD�^�(B4X ZDr�Z�5JDD�|�����CBB�{���F�����L&�|�����/����TWW#;;uuu���{�EUU���K����fjjj�p�B���;�X,�7y�(vrdD���~���D�"��^eUKW��D-��k8[m�����������t��dE��(B���������`1� #�5�~�����)�B������ 2��MC~������;���R���� ������$��V������ O��b�\:� ����R����������HDDDDDDDDDDDDDD������`	�y�0��@�?W A�U@�Uo-���A���H��<o���X�r���333q��[��k�e���q�v	{
���������Q�F��;�Z�HKK�O?��/���#k�?��S|����F��Z����0i����\\v�e8q��-I����O&�QS�^A�d�xm>Q_��SP��,L��y-�I�^�J�`��S!�[@@���Q^^��g0p��I�����ZX,[�\.�F����?BCC�������->�~�-���yO��l�����b�������rtt>����V;���I��h�^�QQ�:!2 �W���D��S���/f`ZH��./�W��~j��9���0��^]�~��Qa���B��2��&u��e���c��*"b���0��@��\�����:/FJD�u�����
�I��<k����f��W/l��C��/��0`�0,�\���^����/�C=��cR�`���0s�L����O�c�u��B��r���uF�5��/�
� h�J^����$���*{����8}�[YY)��b����
UUU(((�V�E�^����z� ���1X,����Tr��T��b��������|2����Z��jkO��6MB'D����%��������*��9X��r�F� /G:�~��
J��2Z���P�����Q!Q���w""""""""""""":�YjM��6������1�
�+��wx�������JD����
�v@@@�BD����z������u�V�����c�w�����w��z���#�`�&�uSL���K/��c��9$���+�@JJ
�����j�T��y�"1�}�^��ZZ�������_�����*{����=�z�������6���'O�DHH������_$�s-���c0���s1r�gP�#�!�t
�:�x���%�������2���������='Qg�:������y%����tj%����h�-V��.Co��(�7������5��Qa��1�~ """""""""""""�n�XX�GGa�2��8�K`��D������x(:"�������-�x�j""j�/�`K��_|������������� ����{�A.�{m~�,&�0�x��7l/VDQ�B��������*���#$��JKT �����:�%���J(C!O� �9��JH�P�*^F�k��t�J�;���UUUHNN����"�X� Cr�RX,u(�o�S���o���O�R��!�t��CQ]}����d�DE��tc;!2 �W������iy����(��!���Z]�N���z��&wQ�EeH��btX |$��DDDDDDDDDDDDDD=���%��Xo����UF�s���2q�V������p����� 11&L@HH���������Gq��I����h4"((�������������G�Ezz:***`6�������G#22��s�9s���GVV���`�Zm7$OLL�������������a������Gqq1�r9���1p�@�1�I\^r��I�������^�����W��j�QNNv�����"TVV�����GXX�G����t>|���@hh(f�����@��/--�����|���!44^x!�����O����;QPPA��W/L�<����������fff���c���Aee%
t:���0f��v�3;���'q��a��z������aaaHNN��a����b2����������@@@bbb0i��vWr;+''{��EQQ���h{���Z�����`0�z�j[;22������UUU���{m�|)))^��<��v�����R�Q!>���r�-���{�PV<�!��,V�O��SeR$d��lo��
&T��J���uM���8u����g2�p��14�[$��d
������m�cjkO���y��	
��#��Ld�����$���wC�M�R����4�W�/���������9X7��.|h�R ��Y5
��mMFu=��0=::u���IDDDDDDDDDDDDD�V�Z��X��Yb�%E���k���MY,����x��WQPP��/��q���b������o��g�}��7���C-&%&&b����������4gIg�>�,�}�Y�������<y��6Q�m�6|����iN�<���C��C=��o�
�{�����K������cG���r9�������?t:�n��}�v�����y3�����p��?�<��Z���&O���[�:l��uk�I�-�3�<�R��y��$��\���v����Ga��y�c������`k�z��X�r%`���x��'�w�^�}����d�\y��.�5o�<�Z������txN��;�����~��Z�]Y�V�\����*�=*9F&���/�O<�������f��X��w�v�o�����1g��'N������u�`4:VkMII�o���co,������'����;�A��W^�+V 66�������aCC~��|��7��y3��9�t�\.��i��p�B�s|s���M5��l...YYY-[�����_����?���:��h0}�t�u�]�1c�[���K�.�k�����2�~�\����K�,iS2��h�[o��w�}���#F����z
�f�r��}�Hk���{�g����*w�>�(�����c���^��:K9v/2A������GD^#�P]�(=|AW��Yt�k�
f�����iXK��U��&�Q�c2�p��	X,��b� 55&�����(2�C������N�TW��Cw�b��bdt>��������}�hAI������d������IE��Uux7���c�L(�����-�,Vl�����=�3DDDDDDDDDDDDDDmQ�m:�U�	�`�2����9vwUVV�q����G�L���|���6l~��W��x���1b�,]�luM@FF,X�Q�F����n��V�<�&N���_���=8r�����)S������9���Z�p�
�&*�����h�"������������p�Ea��
N���J��=�����={���'��7� ���%�uw�>�(.��R�	{����Y�f�����bd�����\�;���i�����s�N��53g�Duuu��3��_��[n�E2a������#���_J&��I��&M���k��?����6m�d��������b���.�#����^t�E�����������4�37n��)S���������b)����t�����s��������/Gvv��s���c��1x���%�������?��Q�p���~�]�va��x���&�����{�������Y�P[[���;�:����?�`��2eJ��#e���x��wm���z�[��1i@yy9�s���f��L���D@���jT�!�B54�q}!�4.�*V5��;������N���UA��$C"������:����T�����}�v��1���p��}�Z=�xD!! ��H���e��.�������>���/�,������5X���_
�����F��M��h�X=z\"""""""""""""����D��v#�6�q��'���o���q�%�8$�����x�5���WUU���*����5OC����k�Z$%%��/��#�0�����0a��	q�%gpp0���m������l��
S�NE}����u��w:$��U�RRR0f�4aaan�_\\�I�&��/�t����7F�����#88�����3�<y2�m����$�����/�lkk�Z4�F����>������o�b�2331n�8�$�L���D�5J�z��
0e���{w��7��q8����� 44����o��n���\���Arr���n2�0g��:u
��K/��g���
b���>|8�����=s�����ns�wt��P����W/<c����!C�0��7���w����!>� �������m���HHH�\�!C���VEE.��b<x��-::�F������V�����z��5UUU.������)S���i�]�R���p�0��w�a�������:�:�-���
�1�p��
�={6�����h�~����n�G}���������]w�e{��t�M�������P���=�������DD�!��@}Q?��_\�u�����h�%K�}��0�q�T.G_Q�j'I���G]Pyy9JKK;t����6}��Y
-��~~}��)+�G�=���w���K.�EH�EN�KJ~���yl��+��%��"<�Kw��U\��J���X����C�MDDDDDDDDDDDDD�����\��c�l��<]�#�<�}����� ����GVV233�g�dff"##������w�}��=�Z��
7����W#;;UUU8q�v���}��!''z�o��z�:w��3g�����rz�M�6a��Mx��W���r�-�>������j�������W_���eee8~�8v������yyyx���d����cx���[|����5k���
�.DVV�����~���G�Eqq1��9�/��s����o����V+f��m����/����B���b���8p��z�-�����:�t�M�k��-[f{��:th�����s[��������d������q�F���������g�������b��v�����HU����Gy����Gq�we6�q�M7!''��M�P���Gnn.����g�dee�������;����o���^�������g�F���~�������%%%��c����c��90����V�\���R?~������O���������O<������'�\p�����QZZ�C���3o���]>�������o��3v]�1����C=�_~���������#G�c�>|���8t����^���
�|��G�	bp������\r�]��5k���>����-_���/�������+W�����{7>���b��������;������'�P(p������������={p�������W^�R�������^x��c;v7�x�]��	��������v�NMMEYY�}�]DDD��������?��#���RYY���4[[.�#..�0af����?�iii���Cee%N�>�/����~;�����?��Ms/Z���$�����k�y�G�.�C%�����H�����D�9��������9C���R��}�5P$�B �/�G@�KN������������������:SAA���i~G��L�
AJ�*��7

�J��lDj�c8�e�~������0�8���U(/������Y�5q��XL�}5�w����vn	����[����������H��"F��-��3�0f�V����U0���2R������;w��w���A����1g���			x���1r�H�}�����rk�3f`���w�?��BBBp�=���o����m	h�~�-�?��:�s���C����D[��n��6�����^_wVtt4{�1��=���{���E�A��I���������n���<����p�u��?��O�k�_~�e�������������J>�2������M��`������:/^��t2r�H�9����~��g��������.�h|�M�<����n[�����~�W]uU��o�;�����8p�K�����c��]��J���u�$+:������.��B��f��9f�������������_=>��S��4�3��cdee!))	�7o�K��K.��6m���Ca0k����C�`�Zq�u���O?�Kv�����^����=g?��<��.�|�EW|�z�-�7����<��C���7��5�\�+����K/��k���a���([����d0~�x��<=z�!I������5k�G��;��w�y'�����������j|��7�9s�C�F��C=���H�k���+����;�n�2���={�]����>���z
� 8��j�����0s�LL�2��L���o����FJJ��>y����[�;��q8~�8������o�_PP��s����cx���\�w��}���ck������������p�d�����9#�zL"T���Od!����R�����AuQ?��$:M�kJ�����zb��C�["��tE�(�j9/���������+sUWW���ug�QGbD��P�"��9S�8������aa���������y�+c|Tx����s-�,DZm���#e5��y��3�D�sYC�}��,���[����~V���k/�/_n��o��d�^Sw�u�CE-W4����������������+W�=��F��j�^Sqqqx���l���z[�0)M+�����U�.$$aaa�}uuuX�t����������d2���kv�P~�!***\����5
���n�IFaaax�����m����Ck��bqH�|��%������p�=��m[�l�[s'&&b��U�	{�P*����/�������]���b��S���o_�Z��iB�z��HJJ��:��B�^�:ZW|'L���s������%������wy��x��a2�l��.��������F����@��{���$������1z�h[�����ks_}��=jk��?O?��d�^S�������������u����HAp�W�����p��wb�������z�j�q���,Y�+V�4��d�w��������q�������.���<111�;l��?�p'GED��>�i����X��Ud ���b�%�Jer/�cC`>y��sw�*�Q�^!�"8����(�� �k��D�����>_�2����oRRVc���`2�I������4��$j�Ce�!�^JJ6�W�k�u=k���t���[��~
VRs���~P��+3�P�`�JlE�F�LV;�����������������U�J�,���axM��B�z9Q���G/�B��)s����]kk�����g�ui�_|�W������7��_?\x����s'��?�����j��i����%��������$�6�^$����c���(+;����g�qZ��9�\�����������~��7������\��+I��i���-&.�u�
7��{��������a����~Bnn������/����W�nx�m�6���"99����x�	��w\��:th��f�����~�n���??����
��Y�f���_�m;p���Z[O�S�9s�����������j��PXX�/������d���=v�o.::���\{��7�U������������{???����v9�!C��������X�n,�C�eG]�����y�^yy9���9�|�����[n�����p�UW�������<�.��R�����9�,Y�C��W��j���;�I�+a��?�w�}E�(b�������������A!��R4����F
��8�F'Bl|C������L������?�a<���;�D-���nE���Z���)M_�_	�B�t��3+�T���������C.�����>�����9� ��1�wRA�@u��-��3��%�u�/�GDDDDDDDDDDDDDD���;`0l��/���$����V��xJBB���xe������}�R�M+WUUU�����������}�P(0{�l���6m�]���������W������K]�����;�&�u��[�������r�;�N�����n�o�����r�7�p�Kc�����]7x�`�� ���k]�w��!v������&z�c���t�5��_~�U@�3f�_�~6���^�RR0>����SZZ���w��W\q�������K.�}_SS#��w�u����E���76m����G||<~��DFF�����+-����j�������$?�~����|���� 0�L���{a�Z;;,""���4P����h���$���5AemmkA����v��"�QGE��It555��/�!�v�
�2������T���
Qk�r��Lt���o���y	��}Tx�o����3��dm��KU��:So@���U���""""""""""""""����`���n���������b�
�|��2d"""����x��f_����l�����U��hYYYX�t)���z$''#,,j�Z2�;v�����N�9}�t���7��e��9T�q�(���}�����u�F���[;55���0b���G��������������*L�:����M�f�>[-�5�V��F��9r�K�����	^�&(5��������������O<�f�����D�t:(�J���Zm_���ss{5Ot����Q�F�<���p~���m���3w�8�y�����#�����#])���_n�9��^z�n�������j�w�a����A���c��!j��\K�?��j���������
�����3g>���v��%"�NA@q��
���5��V��Xr���y�`�U$r��b�������Z��������6�<t'DQ:	I��E5�)�
�z$�v ���������l�AY�N��:O��h�����
�ZV��gE�=5���C������L�,�@��V�2�2*��\�������}��6����r��DDDDDDDDDDDDDD=Yff�]�y���4���
�^�G}�W�n�:����_�������o�m��s[J<������/����o
�����'���I�0u�T\t�E5j��������PVVfk?~��k�����<I�5����7S�����k:����
f�v��Z��hm��8??�6�'�oW��yRW}��w���8|����4��Ia���v��$����sL�����n�`������Gu?�&��%q�6�m:���_\���o��l	�


��{7&M��0v�����w�}��*���0i����d�������+�����?�����3�<������.�'"rGF���6�UDtm��f�����]
��H�C�wW"WuV�����:�x�_9�7�����j�/PV6�y9:�iA@X�4������������AP�Bw�A�,)�v�@�������z��[�����Y�V�Y\&�.�O�,����yR`c���	�DDDDDDDDDDDDDD]R����U�Z�����tL�<yyyn����J3e������K�U��ht�~N�T�������3q��I�}6m��M�6h,22v�X\u�U����������m����P��;���&�*//�}/�������?44���Z�n�H)m}���;�����+>��������v=�y�h���n���:������#���&��7v�X���|||p���~V��w�C�^VV�|�I[��{���q��5uuL������m�_s�5x���`0�����o���s����}�"88�]Y�O?��'B&"�8�UDv�t��h�
^��
0���%LER$d���&������(��:e^O
��������B*�JDdd>	�������Z������< �kEI�f��u]�=�{���l�h��D�d��9�x,*T��;����b��m�R* Q��1	��O��(c��G������W=jM��=-1��9s�C�^�~�0i�$$%%!::����vk^~�el���������3g�tH2:t(&L���}��W�^�������]�=�������~���kx��7����0�`0`��-��e{�1��?/���Z���wD�(���w�n�����s�x~���vi?V�")����C��B��E]���G#..�������Z���w���^�����TRWW��k�����&�@�������d��W\\�0��g�Amm-�W�^x�������&����g�qX |�-�"����2|��I{D�U��5����P��P(��`N-�X��])�%�0��!��A�7����r�r�K��O�2gOH����Y�Xjq���$�E��#G����>Dp�/GG=�N755i�Xj���sQSsZ��N���M�:|_\��e�(�wb����"�
H�k��'��gW�O.=��DDDDDDDDDDDDD-�����6��'a����|���nL��|M����@��j�������"rW����HKK��#""�r�J\v�e�����W{���v������5k���/lu_w������O��������y�fl���v�B}}��X���+V`�������*85�{���X�|�[�4�������{����%��{n�]!�����z�.a���/��o����{��_GWfm���xMM�C�����������_��c&&&�8�������O�T*����V
m>^�"i�D�����������*|��6�:3(�i^T�������!DD��������	�����_�,���2�O�V���%���
(��CA�3����UU��`����G]���o��R����-�o�p���H������(r���QT�A�_��
�&2Y��� X6 �v�@���n@QD��
����UXD��bE}����*vU��RI��c��GDDDDDDDDDDDD=� ���t����@�&��;���LAAAvm�^���M��Z��g�����]��c���oYY�[q����n����?��c�	M�5N�L�	&`��	X�hL&������~�)N�>m{��I��7����;F��Qq���)���=k�����S����V+��������'��K�TZZ8`k<�|�
T*U��z�������������������Z��k�'���&����=z����$����v[��R�����M�k������/"���d�"�I�8_�e��1A&@��$����7���30��KA�G�����v���w$�	�b�DB�N�-�Z<t;�kNx1*������W�nHK-JKwx9"{Qj����+0��
��"���XQe�@o0���������Gje-��`��
;�+��L9~.(���R��)��Y��4�V�.����Y�|�U��rJ�S������r�*����*)����ZdT�#��E��L�1�a�Xa��"""""""""""""~���;�0����4OFk����vi��j��={l���������s+�����AAA��}�e����W__���L���T*1v�X<���HKK�o�Y�o�����v�DFF�U������d�H<����}Rn��M-)))�t8�F\\�]���Cn��||���j���v�;�����=�{���2kS{��������[�d9oj�u�3�1��]TT������v����v�D�+�5�$":���4���<���u�&(�P&EB��9�����ORo��P.�l=�� �y�O�9BCC�>\��|=QB��������~�����#>��_�����������]���_Yy��Vw������%�����.��F������'�`@��V&�&������V���E-�}f��q�Ya�4&��B������`4[`Q� X-�m�<HDDDDDDDDDDDD��(#5P�������T	PF����.������[���o�����[]WZZ
����o���\�#--
���.�o��po�o���������wH�� �����c��Y���}��mHNN���J%�����@c��]�v���.�xLg�:��v�5�v���"��_5M6=��3��9�y�fL�<���7o��p<��h�����ak�s
�0a�~�m[{�����������M�2������\�v�Y�fa������}�����x���������w;��������Y����������?Y��[�ID��e�H�i�G.C�����
�������t�bE�����zwf@ER$d~�K������Z����>�V�����A@L�C��;
�j���Q��n�����W�Qk��P���B�
�����������U��W�b0i�	T��%N�k�������@?��m��*�	~��I��I���g����&��b������l��+��������4���_�����A+�Q�����_G;)��������J�����PVV�N������X�~�K�4Oz8;�+�|�M���Fc��uu��Q;��q�k���v�
z��a�e�]fK��+VtX��F�AMM
��������\J����]"a��L�4	K�,����Y���~
E�)���X�v����'z<F:?���l0����5W{�!��M�B��%�o���N�r����EGGc�����������af������v���.�>>>hhh�X������c��J%F:�#��?���u�<L�#"",V��$��}!sa��,��1�����������P������
��(��CP������^�z����^��'���`�RyPr��P��:�uo:�XTW���R����������	�5�T+�\�h�=5����lA���u�'�G�����2A�Z.@-��>�g�������2��*:��K��E�l��N�*�;����V��9I�����1����������������w����P������'��dAAA���k�����h�"�X���}�|�I�'BBB�v��	���j�����N�k�p���������v�m���������n�:��i���	���c���N<������|��W���p���{<�NgK�������=i��v�/���\sM��-^������\r	bcc����&33���:|��V�}������&L��tT���I��g����~O=��C���H]C
rm]ZDDf��mK,�Z����;�e��
~]�#�<�[o���~��1n�8vbT�]�M��`��9x���m���y�Z���}/^l��4i���=#u/��LADD&����R������� �&��")P�p�EX2�0l=	sv)D+�S�#$$�C����APPP���5�`h�f�@�#���q��\�L��z�L����N�KK������$\�KB��m�������{eW4&���U*�S+��F���Z?�`H�?F�`Lx &DcZ/.��+c�����N����Q��onJ��u���*63z���(&FalX F�h14������"V��H_B�Jh�r��e�3g�MLV�f*�f�4��_g@VM���p�����[_�����L96���\=�f����"�I?�U��Iz!��,���b��[�����RX��E�]R����8V^�S�u���GA�%
FT��3[`�Z��FDDDDDDDDDDDD���Y} ����T��O���Y�`��M9�x�
|��'-������-Po�\.����m���B,[���}N�>����
&S�7�o*..������_~Ayy�K����"::����g�-�����wc��9n�x��7c���.�///wx�G��0.00�=���m�Zq�M7��o�u+�}����olqL�$�^�-[��5��7��7����s�������T���_|�jB������_�C��.�r9,X`�����/����~~��C��C=�����1n�8���o����O���;���W^y����'�}��Wn��p�B��j[�������a0HKin������tkNO��������4��1.�d2a��Uv�:�������u}�E���������W�Z���7��_|a�m���u/��GDD����s�F!G����	r�a�G�|���2����&��`�.�b@$daZVs!����������\������<���t���9�oET��Q]�[rDmm�
))��Ph��M?�����>���b�GY�v��M���	����b�{�	T�-��
F�k�p?�������E�����Yd���vV���M+��0Y�W�s��'����G`��0Z-�:�8���X��i��s���#@��DDDDDDDDDDDD��\�D���Q��a��f�W�U ����k��>�;w�q�m1�(����[�k�.<��#vk_����d����;���Zem�����}���p�B�����G��,����j�*<��s���� ���?N�<��<2���M�U������1cp���c���h4v�G�iW�g�������m��������7���o^^�~�m���+0���Add�K��?��O?��������q�e�a��a����W__����O>�$�����6l.���c?��������~�z@uu5���j\}������1~�x���q��������?������������K.�6l�������?#G�D``�]U���D$&&���t���P\s�5�	���+���������B�:�����#X�d�-q�O�>HOO�������/���]��3f��#�<����QQQ��X�d	�{�=����x�������;�}�����c�c�����'b������k���:t/�����������T���<y2�J�m]��U�PUU�+��QQQv	����?~����+���x����/�������SOa��Y�������?��O>��-[�����U��r9���k�=��@�c�<<�n��f����a���"����}���]�����}Mu�u��z����{�>��m��w���������{���������Qg�t�M���K�3u]L�#":���-(�7J�%h}��ZP+�
y\�'��ZR��>b��}���h�Y�o�����R�Drr2�;��}I����C�P�}8�s)����8�~?��H���>�C����aB.����#��� 'g5 Q����0�������~p�P+�|�h���c��]E5�J����O.�������;��r9|���[�$��M�3�}��h����0��Z1I�d��tB�J��?������rL�#"""""""""""�2e���������VI�[r�,@���C�i}�yd��e��oh\�!�"V�X��_					�^�Gff�m�V�7�|3g�ti��n�
o��<h�c��ex��W��_?������vky.\���|���������[[�PZZ�q�����+&O�lk?����������0�x��'���O#))	�%%%����KL����O>���$FHMM�����x�b��r���:�*�
���p�!���_�|d2>��S\}����w�(b���X�v-�j5������TTT //���Ss���/��^�19�YE�E���g�q����t�R�_�555���J�v�mx����O��r�����������1g��}���v�������O1e���4��1�Lx����K/!!!:����hn��x����5�D���
&O�l;'��n���?����L���<���h4���O0b���	�-��bw�={�l...N������GFF^}�U����t��7r�qqq		��`@aa!JJJ\��[����v�Z��/�U�-//�]�BCC	�F���*���6�q�O=��������@�u��7���o�i{UZZ����}G��w�}��!S��="��\VM��"x��~Nz�#���jT<,��OB�nhuki-��OC�;�~|x,r���
���������
�\nwG��J.���a`���QS#}w����8r�o:�m�d�W����J�Cp�(��KUtQR�z���S�j���K*���
Pg�QI����}U��R�L�iw%:r�\&@.��=5
EQ�E�{U�,�I�,����*����?�V�?�*�*�r����������������� b�T|����m_��;<AW�a�=	��q#f����{���������E�X�n���]�C�Tb��u����q��)�v���4!����'��y�v�mn�<�&M������C��&H����o���3��?�f3�;�0^&���W^�]w�e�������v��������_~�jJ`` 6m���{���a6��Ti0����j<M+I��t����q����%�uUqqq����p������������r?u�T|��7��:����Dl��W]u��
#���MOOwZ�p��������j�*�`����{���������^SScK8o*88�|�
RRR�����^Cnn.6m���x�����o��x��G��9�E���M�2{���M7��={�����z[��3� �z-i���Ao�������0�|�Z��������f���O>�����
��8�%":�eV�InP��S{6�[����P�\<�%����`>U��Z6�???:!!!6GFFJKK;��]�R���+����tLi�V;�OX�f�c��	
�B��<�����z9"{� `i�+��v+2[�nq9*=T��O.�������I�� P��*�T)��B��q������A�iqAh��aRd0�G�`fL(����	�k�(��7
������~<}���:�1�>�("������`
�������~jD���R�_!�J&�ic��0X��1[Pf0�����Z2��q��G�k���;K*�{Q6����R|�������,�����t>�8�����.��������)���
��W�pY5R+j�^U�����3����*�
,"S7�������������"�(2{B�
�*!��}U	�7!�0a������c�,Y���(�1r��]w:dW��U�����g���~��8�m��1c��O?a��em�q�<���T<����:u*z��???������}��a��9����cA�����s�N���p+���wc����6m4���>����=�N�<��c��4�B���e�p��I�}��.�p<>>w�}76n��R���'���x���q��W"!!Z�2����.��R����]v������H���k��q#�a���wo������>
�t� =z4��[����3a�<��[o�o����':�����o���k�u
h�$��O?����������C��A�t�5�}�����t���GDDD�c���p�M7��_~q+!������w����~��S�B�j�P�\.���c�x�b�>}�=���8o\�M�Vc�����a���t����w�}�u��1a����UaD��c��a�������G[|��MUUU���_m�)S�  ��d�u5&3����#�p�?RB:����3��d�V/Ej�I���
���K�����������.���j��W/����]�A@RR���<i���y������FCC����"����� ]��:��jjN���o%�d2�������Q����������L��AZ�k{��D�/F�������(�0������V�k��_�1g+����!�P���*J�
�2�V&r?� "�<<u.����:��D�O��2��v���_�~P(<{c��b:S��C%0�V��_�����_T��P�h�7,�����=���m��!--
���P��HLL��	��9jjj��������������/bbb0f����zdO(++�o�����lTWWC�� !!���s)�5����8u����m���Z-���1|�p$$$�{Qq��1;vz�P��DBB�^�z�{�����[�nEAAjkk���0t�P�3�i�&�����]�v���UUUFTT���t�3�<�g�}��f:G���,l�����0

BRR��??����(�8x� RSSQRRb��DFFb���<xp�8����a������Eii)���������P$%%!99��$���u����|������hhh��'����d����z�;5'~��'\z����K�������Q�Fuv(Dt��ip������A!��_�u0�:k~E�;�0�����b@�!��.88�������^�Gmm-jjj`iRK.��������vo����>�����|^�A���R������a4�H�)<�5�

��{��������PW���g�6��t���wBd�\���+�^_i�Vg�yY�5`��q���<���l�� 
&EwD�tJA�����M���'��$�9$���%�{,"`�X�`��W��h��w.��>���>�T_��L�#"""""""""""oRFj�g2�(���f�B���sB;�d2L�8��jF�����3ft��=E�����������r<�.i�#���y�����p�
�F����k����*��F��� %%��Ci???L�:�����u�����q�u�uv������3f`���X�t)�
���H2X�|9^z�%<���L�#"�������S)�r��s[	�J����
��B�e���#V5��;��(DB�Q{!R�����l*����
��
�L�L������pX,dggK�[�V�8qt�n"���_<R�������\!9&/o5r����w��nM��MANND�1Q�����'��k$�$�������c<�`��#"r��Ao��*�d�����V���3�p��Efp���W��~��){��3�F�&����w�:��g��0Y�N��+�9K$�XD��bE};����P���(o%�I��������������]� @P+."""""�n���
����1r�H��5O<�D�I�����[o��W_}g����p��<Ti4��`����*{Rd��P]�kq5�'
!�[��Z\cI��!P�
�����5�A ��].=�����|�~��bK������������2�#�?p,��1Y�oB��G|�|/GG��R���P^�S�������WB;���C�J����=��y��l�:���(�,FQ:����r�Q^��
KD��?��������}����5M���Wb��	�f'�Ar�,�0[D�%��T��i����L�#""""""""""""""""�����n�Z�X�n��[�)S��o�f����B}O:}�4�}�]|���������A�m'"osVe���=��D�����a�)��t1`jeq�X�Ka�/��o�q:��K����w���X,N��M&RSS1h� ��=�6oC1l��8xp���1��K��k���/GG�Yp���N��\��g0���;���U�A�����K'�6eE]�:c4����6�/���*��@;*�YEf������g����(�?�ffw�6�HH $�)T,�=��)��l�wv={?���v'b�C
��{�63�?�,[��d�i������<3���df�y>��I�vnc��{G�J������9U~CDDDDDDDDDDDDDDDDD}nH��.��|�����X�����~�O?����x\q�8���1c��>Gmm->��s���������c�'�����D,X��O�AD�IUU�	��j����� �����4"��J�k��&G[Xr� �@��1>��q��A@JJ
,���]�1�L��{Z���#������<�%��u5T�u����e��`$&�����`%�Z��.@Y��.�������th4����:����a������dg���@T?_���"����
�ME�.��9������z�����@��*v�:���?>:+�*P!��W""""""""""""""""O������>���j\w�u��o�]x����?�8�q������O����1o�<�����_EQ�y�f���O����~�z��l�8��$	7�x#�/_�����=a""��,h0[\nK��*{�:
�Y# %G��[����}�V���!DC��1��B4���1c�@�e����l������deeA��o����c��g�{��\O���};$)qq��wp4h���!$dZZ���)�55� >������+A���u���Mf�k)^��'�'������L^T�sUPf��k���V7�]<e��������N����
T�F3
��Pe0��h�I9r������
�!-4�C��%DDDDDDDDDDDDDDDD��3������;w��7���>�������_��/�HNN����1q�D��� ))						APP$I��`@[[jkkQRR������b�����o�#�7l�z�a=����� ==��/	��*{������$�@7=Jm�9eP\���Z�
���GD@;.B��#��@���#''�����---���EVVD�w����S0>�1����M{���)����>��c��+&fZ[BU��qMM{6AAI~��������>>����qX���Q��U�OvQ��,;�m���

2�����N��1��k����g
�I�B����j1`wm3*&�mL���6��L�U���@&E�1*$��#%"""""""""""""""��|h$I��W_�+��/��"�~�i��p$XDqq1���+���=p$���ME�s�9���{1e��>#"��SU�mh/!H�`���yN�
���1P���W��������Rj4i�����CEddd`��}hiiq����	yyy7n���%&�YnEn�2��U��]�����+1�����H�
Cd�l����r{U��5�2��^(��[?��'$A�$	�m�OQaV;�����o���&+��]7��h@�|�s[�Or�9%���-��`ce
���I��
�	�k������>
�"��)  ���?p�
7���?���>�-[����$�����'44W\qn��F�3�G�&"��*���BSC^�=G� @J�������*@�fj��B���|��q��FFr"*��$I�����}����zbk}}=���1v��a�=7r�e��-����vE1`��%�>�]��M���h0������}0�����L�hh�����~Ovs64������d7�!kV�%��IH���{\�.*�����2(i����e���*��?�!@Ip����Z�kJk������(hjCy������������������������a����hp�����K/���{�b�
|��'8t���MO'���t:N<�D\v�e8��s��������F�`� �����4*���9:��,��)�|���H��}?P��Z-����w�^�F�mjjj��h0z��a1qyt�R��&|��vYn�������>�^?�����F4��=������������F���xVVxp����+��#�AG�zs�RU�
����eW��}���
���0�2�'�!>�}��6�X%�������Vk4���j������
�-��i#c�#""""""""""""ra���X�|y����`X��lM�0O<��x�	����~�-��[���7�����ci�ZL�8s����'���N:	!!!}4r""�)���&�����H��G�{B���#!����]����}�&�[� ����H��P5��N����f��6�$	���~]�HK��%%���n6�a���1c�G�������~�������	�������/c�����~:mjh�EQ�a`���A��O���>����2���QQ`�]�6���u�I���x-u� +XSZ���^'��bMi
�N�C� ��������������������}h���I�0i�$�v�m���b������%%%hllDkk+dYFPPBBB������!++��,���+o3�Mv=k2-tpW�C��9Ju3,�eP[\W=��T5�T���(h��!��H=h
�����$��F���#�<:�����liEY��
i&SUGp�c&�y�4����CKK!T�9������I��cPU������-�n'�Daa	zIB�FB�FD�FB�$A��-T#!�v���� Q�>��l���hz�RU�1�����*G��1yGQ���(@���I�?��~�U��	��X�A�Qe�a6�������n�l@���z�UV����"���DDDDDDDDDDDDDDDD�	]HNN6q�hx(t6� Y?���	�)6b�rI-,�+S7;U@>T�p=4cb!����J�������Dvv6������bh4����yt�'"23�,����[�m��������b�<BL4�PDE�AM�/.�WW���Q�A�>C�������@o�)
�L
*L�C#���FBXG�/T#���D����������D4,	�� @+�����3�gW�O������
d��[�
��Cw����������:���%ApY��>��Mr����!�w�������!AAS�B�0*d��@DDDDDDDDDDDDDDD�-�����	YUQ�fB���@h��TD��hH��TA.�n/��Y�%��C���K����D����Pddd ''���{����$!::����?Q�`��C������.���`����>�}h��~!
&����&S��6�����yT��?��#YT��"�����`It��W���^��e�?"�l��E�OvU��1��~���Um���^V���]�?��$�U��:�m��&�������z�O]3C{DDDDDDDDDDDDDDD4,1�GD4Ln5�
���y4�!h%h3 ���%�JYC�;��a�yBQ5�Y�#C�~�4����#==yyyn�8p�$!""��'����I/b���C}�&�m����c�_1m���h�3G�	����p���.�������h4�}�������V�7U��?����FB�M���*����GD��/�����v<�	Z�������*,>�yR��6��f�Qa0���t����:��Z��GDDDDDDDDDDDDDDD4P0�GD4L4������w��u�MM���
sN���n�Q�`�P1!����:?������(�3���.������<dee!4�oF�$a��W�}��hl���Mc�v���S&�I
��i��>��9N�T����uHH8�O��K""4�{Y��|[�/���_g�?��~azV�#"rI�$:	�M�OQU����*�c(P���=��;�S�{(]�]����h�� @�(��^:���w>&""""""""""""""",�#",���f��m�!���R���4(�
���Cm3w��R�SE#����������dV^bcca�Xp��A��EANN������_]N�	���ob��?���u���?�g���4�E�"+q�k11������\��9�����~A��� �R���cS�tV�+�E� ����D�U�l��>f�?"�DA@�$ @{uW�����		
��
8�Mm�ws#!o��BG�����c�t�zwl��u��'��a;>O�GDDDDDDDDDDDDDDD���="�a�P��m���� ?��	�)1b\��5��W�n��*��j�%u���C��������X,(--u�]�ekp/(h��,j���6�l�v��\��k�b��[0a��!��3�F���cP]����UUk�����������%	Q� !
M��F��&��&��F����&YA��c�����"c`��8���_�$A��	J�U��4G���m��GD4��:�g�
��G�]U�3)
f[Z�JTQ����|O����}���u6�]H����g�s)�>��x{^�*���#�5������B7w�E���hA�I���	��
��j���g�a�w��h2 ��r�uk����e���.���fdggc��	�?���6�]l�v��2�m**��$#3�a���K��S���&S��6��uu[5�������+}~\w��,���^UU�*���-
���>��_���P`�EFsG(��"�M�$xO����^���@��"PU���rD�u������v,;V�x�$�a������F��k�uy�����������~G��9n3+
d^N�(@�g8v���b7Cw���y������9��m�������������������g���\n��8�'�h'$AJ��%�JUS���-F���Mf"���_!�zN����b����9`&����j�~��%a��w�e�E0�k\�9\�	$��c��Ar""bcODi��.���mDhh&��p�������lhh��q]�����~�	�H�HH�E��(hr���S�����SPf�?oXT�^V��u`C+����q\U�k��vU��<>���m�(��KD��(�$���������u��w
�
��D}��=�U��6�������f����� ��������!E��J��Z��iuI*C�=4�5Um��I�
��<�������h@ch��h�+n1���j(�f�D} tG��\�KN�&�AG[JML��42��x�C?lE=#��Y�QWW����`@NN�������h����6�l��gX,
.�:�&4�ii7�yt4%!4t���:mSU��Fb��>����8l�]���:�>%�����N���_UUE������_{5?�`����*���@��y�WU��+�u��D���M����Y����D�(!��PU�
����d�� ��D�*���b�����,@������.+�����H�j�=���*�Y��x�aH��=������+�F3
��Pe0��h���o&:Q@t���:��!2�s���������?#��h�+hjs�>X���h>)F����K�`�_�� $��A.��&5Rj,�����`#���������F�mZZZ������LHR/Kz��LL��&������rYa�s�4!HI^����`=--�(F�m--�hi)@HH�O�\�s�"�������u^|$N������ �k$�}T��I���'[��U��k+��gP�3�5��5��:N�������>��vm��iD�cV�#"j��j@#J���wTU�EQ�IQ���.""������js5�o]�4��i���P�����S?]�=x�]`���.�-��cwq<""""������w�3)*��L(k3aW]3�u�������B��������|��="�!� �8��d���A�G�A�fT��pX
�!T�Mh�UXT�r��q	�"8��������dgg����e���&�������(�hx�TL��*v��?��+8p�h�$%]����@��#:�XTU�u����'��(������?�[Pn2���������$�w������_G��1�g[��60���k������V���:�?	zI���g}��&�������u�R�����zqr�Rb�'����vZT(@��
��z��v��}{g F�j=�b���x.��|�z��=��X���zw���h��K��!@��n�����>��*�>@v;>������������`ce
�]���+*�"-4�c�(
��7
d�
aE��S�B{s��A�H���C32
���PJ����h�yw	����d&B����8ip�$	�����w/��\��������;v���t9�&��]��Uu]�2'�HR����h�����=0+��Y,
�������}�g�V������Po�]%2[	NIC����������h�����,+.+6���������v?��~���a	��P`������D4�����
�A;nH��m8�!h������Pa���9���9��������xn�;�?�p�v��(����o���
������������CH�����.���] �;������Z�kJk�*+�:NAS�[�X��������������<���DDCXa��@�^#!��zL�B7y��Xr����t���h�yS!��0h2 ��"@C�F�AVV�����uu���H�����a1�"&f&��7���	�S4���}$)���<:�ADl��()������M
��V��~��AX9m,.�Y���{	:->���,=C��/��)��VY���w$�W���-���&�0�G%�(j��6Zd4��������a[��6������cV�#�$54��\W���iP�l+�O�'WTOC��0�X��c�)�x<����HW���h�a�F�����0�O�PU|W�M����c����W�s��0���zcw�f�����K���oK�a��g����oK�q�����������	C{DDCT�EF��;�����= �A;+Je,9eP[��L�T6�T�)9��qt��R;�Ng
����?����h4HNN����G|����Vd���r��������:�uDE����@����Ihl���MUeTU����s|~���a���k)>����q������I��7��6U�l5j� ����Q1s{���������_���X����SX������_����~!@wU�:����FT���:T���^|���F>�9!��?�Fw!@�
������!EwaC�B�F�	��A����'$@�h�:���|LD�M���:�y�EV����
(���h�t����1���c{�����u����DD�Y�����:�kJkpvJ%���&""""""��qV(�U����~W}�A ��A��C.���@%���m��@.��fl<��("?' 00YYY��o,�� >�F�#F�yt�c��`�����.���	;w-��io#"|��GGYt�qhn�E18mkm-DKK>���>�7J����Spn\^(�������v���S�qR��PQWt����U�k�e4wT�s�k��l�i�$�0�����U�/T�<�Xf�?"�4)J����}�O���� "g��zccc#�Y�ge�����b
��9��iD� ����M���q�Wi��x��9��p�������bW!� {R�$��}������#ybceZ{���;����U
���'�'"""""""��#"�
���"tD��[�	���H#"`���|����i��(���A.��&#b|�HGFff&���Eq�����bH����x?��$�����O���(m�����>�}��N���h��� DG�EU�����Fpp
D�o*�,�	���pd7����zlol���6�[��#4&�aZX���@��!z��U�z7*
���uT�k�^��I���������a?�.�g[�/��
`XG(0�&$��D����@���P����?���Q!�}v|"���Vol_���x��C����#�}Rt{O����{t$"~�H�F���d�g!E�j��U{�t}��T��I����j1��g4@��~VCDDDDDD�Lm
AMf��f��R�A���	:
�Y# %G��[����}�V���!DC��1"�#��L��###999P��?!Ibbb�<��1z�u��,~��v��	�w,���"$����hp
�����0���Y,���������tY� kOUU��
���Q@�$�LCV�("�U�Zd�=���s�kl��c�U���Y���w��c���P���dt\f�?�~3;.�m�>��{�$bvl���KDD�c�Uo�/��]W-�M�����PaO�����i@��qw�FDD���9�����j���] ]�{Rt��v�]�[-2d] :��-��"w�d�q��]���~���#""""""�3����� wU� 5�U}����(�-0��Am��Nxj]+L�C��xA:?�����p���#//�m���|H����H?����1cn�EnFi�.�������
�����F�y�4	����QR�\Mx������	����3$tV0�KoD��(�P�/����d4����9.7����)_U���U��~���"`G��0�� ��y'P�0)��T�����N�0)����c
����!��
�)�VY�	@zR�6�b?O�]����ND4�8Wo����N�>����n�v�*,����}�E������Hw�t�F3*&��U�fB�����_�#"""""""������B7���-�u<��%1*���@9\s^`��j�r���H�1���B�H~)
DQQQ3f���]nWU���Gff&����<:����liEy��.������/�1�#$�w�4 �#<|2v�����j-F�8oP����z�Z���{;��5v�l���[>��U�z�YV������>���a	z��a���`�v��F��8md������^pG0����������H7v��:�c�B��p`w����V����#� `\F&�CzS���q��JcW+���Vo�\WaC�p����
)����)����z4�a?�!"!55��|�W`���7 �ab���x��������=z�G����[�����s�N����`8�^c��eX�|��GL=�|�r�w�}�eU������{���~�����o@D�sLn
1uF3�L���Xe�/A��	1!ra5,U@w�r~�Cu����42���a*66�,�����vEQ�������#$$����� "+�1�J+��V�lc0���W`����E�y�4EE���<��s���� ZZ�C��##�����_o�V�k��d4�T����Vl�e4����|Y��=�g_�/L����]T�c�1L��8;%�P��&@�H
���p~���m���76�fh��.�k6�>{V=
)���cEDO�mS���z_ �g_�>���
7*y�Uo�B��������g�y&<��C!"�^�������������:�����H�9s��AT�o��VVVb���8t����!"""������:���
W�
1���'���3��O�$B36��HX�W@>T��N&,{J!UC��)6��JNBB,JJJ\n�e����0a������(j0q�3���j�����Mk���������?7��$":�xTV~�r{U��
Q��ydD4��U�?k�Onv���~�U�-
�Y��+�U����:A8��$�����������%�"���u��h�|W|��"���#$""""r��zc_����B��7aC�C����=��hR��x=@�S"���f���
!5558��SPVV��C!"rTUENN6m��M�6a�����k��#�IzS��d2������_��p�V��97�p.��bh4=���(
�~�m������eK�m�������]tQ���v�
!����+~|�zm�*�P�Zh'���Kv���n�Q��0o)���&3b('?7III�X,(//w��b�X�{~���b&O~	�w,FC�V�m���b���b����`?������hl����i�,7��vbb����y��U�-�>7U�:+�5v>vh���3���_h��SPb�?���6#^��Ca�S�1R�E�N�`���Q����dA��������� C{DDDDD��?�7� ���>l��=�����l�����hp1)*,�
-C{D4����X�`�uy��eX�|y�
h��
v��7?��s�
�<��c���RSSq���"++�nNYZZZ�h@X�x1�~�m�raa!F������������-[�����O�X�b��������0h��f��M��_����{���>���������\r	6l��Q�_~�����x�
���{�����?j���Rc4��������_�k�C��9Ju3,9eP�����T7���~H���I���K�p!RRR �2���\�1�L���V����O��1u����R45�u���a+v��S��
Q�aFrO����C�����"��oCh�x��pDD� @���"��U�l~�U��a@���M*���U�����m��P��Pk�OBhG���1��
/�f��+���z����-��:A�F,*�~�+Z�aW������I����V"""""�����s(^w!E��m8���>)�;������=
:
��b��e��
UU��~R@#�R$��w�}��8::�6mBL�����U����?�i{��q����C||<t:>�TMu���8��c�~�zdeey�_ii),X���"�m#F���# �2���QSSc�}��58����n�:DFFz���3(���wU������@ ��P��z�%����L�W���B>\��XH�c �Z�� ��� �2jkk]�1�������{\�z0�hB1u�
l��g���w����W��s#&N|��?9
g�����m.�*��Z�����""�V�K��q:��5�T�sU��s�����P`��{�{����1[P����#U�lC}a�?����G�Y�{�@���
�Y�r��o�������*��{]3>���,=oDDDDDD4�z���)**����_��p�1G#8D�u��
���*�������W2���$�]�8���p=��V(�����Z	bX ��`H#" �r.
-+V���+<n_XX���r��y����Q		AKKK�
���jq�g��������1b���999x�����[oY�UWW��SOEvv6�����c���N��+��w�q��g�~��-���{��w�Y������v^{��<��m�����	'��g��$	aaaGTT&N��Y�fa���}�'
?�����uh/18A��#���Mr4��X
� U��e�+�K^,�j��11�A�a@�;���n�l���"77����������Ea����u��h3�lSU����c��'!�>�EG���\���/�C	��s���f���7|U���#���kt�5Z����2��y�Z�������C5��rG%@�E@�U�|n_s��~���o&��r��n?����2�GDDDDDDdCH@G�����Q�([�mB$a��9��H��=�'C=��cYU����
(�b}��l�N�m��M����#4���}$��n��`��6��oDl������-�����+4�l�(����*�u���e(5-@M��*�����B���@�����<��	&��H��������9�f����31s�L<��s����|r���P�t�M������]ff&�|�M,X�W\qE{Ej���x�������[���_��{���p�m��l�QG��o���%K��oX����X�|9��zs���gx~����?����CLL�,Y��K�"99��}��Sa0�����D'�
X�V�6#��(X�����e�i3�����jh�!F���@�_���q��!;;���.�455!//�A���xL���n�Fc��6�� iB�1�~\�1Q@L�����������N�$�ydDD��  �#����
rgu�n��Y���}@��U�<������Y~�}ge?U��4����Pk���;|��To�q������(-?~&"""""��m��Z����#�c
9����Pg�8�sh�}���.����B�M���1\����0f����`W�
8t��9:�������;�G������rl�n�]���d6�"(���7�M�}:���������sz
��n�}�t�������������_c"06�w7�R�,���4��&��{6_�q��V�������i�������z���0����|��{����?�Q�F�Y��s����*���/�������O[�������V�Ze�<q�D�z������3����?GMM
�������k\}�����s�3}���]��l��MUU}�Q<�������p�w�p�DD@a��*{�$��<����nj2��V�s���wq��jCL
 &�C��1����I����L�������?p������?�������=���e��� I!;��a���kz}&������6YnAm����]�##"��(��|S��H�OF������_���``�v�HH���Q����GU�:��*A�T�
v��"��`W�/���_g`4d�W��;���^$(�Pn2�_�K����>9>
~G**	{�TT����"�O��(��X-�1`�:l�U@�]H�]������ T�md�!!7!��.��c��U����� T�!!����!!������m��u��.��4��6p1f���Z��z�7bZ��~
�����*�nJ�����"�h��m��)k������C9G�����`��k<�oL�>���8���z������g�y��O*--��={0q�D������-�s�9]3�z=N9�|���u����3�������F�l'�G��OUU��f�}��X�n���Kh4���wUEQ��������XA`�#��������2�m�O�T�`�h�4:�1q��FJ�A�� 33{����ht�������HMM�������+�m���X�\�).~
I�����<:(A@l�	(.~�Nc9��a��&"  ���#"�A���_o�V�k�������g}�P����X�����\V��[�T^���ctV��H�;T��
�
��k�����O������E`aLx��CDD4�X+.���=z^��1��M���<���YH��jG��n.�}�����!���<����������sO����[d�!#�
�����Q��bl����P��;[
X�}C����Y����e������B�,���FL�����^E�������<���#00iii�;w.���}�O}}=������\����d2!""qqq�9s&RRR|�WoTVVb��=���G}}=,���������g#!!��}���c��m(**Bcc#EApp0��������'B������������PZZ���JH����8�?��Os����\l����~
f������>���5�*..��M�PQQ����������X��������]�p��a���#&&_|1���=�������;JKKQ[[�����5S�N�v�`��
8|�0A��#0�|$%%��Y
.�5,,,���{Q\\���h4DEE!%%s����9�/���b��]���Fmm-���,L�2:]�n�a6�����c��=���GXXF��y��!22�'����[�lAEE���n����������Q||<��g�+..�2�W[k_��
����v��U^�{L�u8������n�����ol1j�(���#  �����������mm�������8X,��������Mo�SU�W����^�W_}�O�+
=e�F�L�L

��h��A��1.��X�+K7�oUra5��:h�� ��� �C��H��!++{�����:���!�@������N��)o`����e�w -(|�&������h����1��[\lUQU�#��.��DD�o|Q�OVU�tQ��)(����:����wT���_�(@o������h}���
�Y��v��U�^(���x��Bq%C{D�9@c�hS!X�7�
T�����M�����g!�<��8\\U;�������!!O�P�B>�a��V;r���"y�:����u�&���:{_��>��\��s���B�.w��s���9
X���cS�����*,2
�&��}���	FE��RSM��
{�
�u2�0m.D�q�t�kK�e<���x������v�$	��w�q�=�G}l��}�V�^��;wv&JKK��7�����
AA]�ms�7������w���~��'��?�n������_��'�`��5NUgM�4	7�|3.��R��q|���x�����t�N�$L�<��s���zDEEyt��~�
=���]����qqqX�t)n��V����=�����n�:������r��e��|�r�����M�m�����#s��z�-,^��e���"���Z����
�X��z�j�}������\��9��=��<�L���x�b��������B�����&W^y�������JQ�X�O?�4������(��5k���.��KW��{������6mr�o��������qNN���^�Z�
&�����M�/����>�i�O?�����6lp�&�<�L<���N!��j0���_�5>��3�]����n�J��O<w�y��9�����-��MG)))(**������x��'������Cn����`�������p�i�y5/�h4����3�<���_���?�=�X����L&���Kx��W�o�>�mA��3p�=��������}}��


]�wC���y��c������v�����?��=�y������
� @UUddd`���8��3���	Ir��Pmm-6l����{+W���	.//����q�X�8p_}��{�9Y�{����7���g���O?�/������&�O� `TH��GC�"H"4i��FF�r�rqM���5���+�|�������A��������}�`���@QVV�F3l��>�'��;�@U�?H����F�c��\n��/*j��s`�4;m3��i��&������|C�����������5u,������
��P��K����v��:����MfZ|6��lhhAvs�����B��U��AH�1��}H�q����\�
��Z�Pj�<
	�������������M�|��c�����+{u���{U���q����[a6��Q��DDDDDDC���V����7���4�7�����0`���E-0�;��������Z�v�i.�1�dY���~������y�aW������n��}AAn��F���+X�j���U=u��������������x�b������������n�1����K�r�J���e��o����q�1����N��}KK���J|�������<�^{�5|���9s�Gc�-���mXk(������Ot�&;;g�u���~�s�=~��JKKq�Yga��m]�S6l�Yg���N;
�q�APw�F#���?���>����j�*\r�%]N�o��y�����?����k]��u�TU_|�6m����=�@6�^���;[�n�h��,c���X�z5���:<��3^��{��W^�-����f��g�ZZZ�������?w�u���g�qv�����,��������?b����6m�����q#.��v�NUUl��g�}6�<�L|���	��Rx_^�������v��UL�:u*����Y�7o��q_��!g��������=���8������
A�Gy�]w]�����(,Z��-B~~>�.]��k����_|1*++q�u�����n�	�]wn��&���Kv�z�!����c���`����Q!�����GD�&�4��)9
��r(UM����a�zbt4�������*88�����o����C�A�� >>����QQ�b����{��PU�w�������x���DQ����(/�������	I
������_U�k�����:*�u>v\n�6��_���M����do2��CN��{���0�s
�cv
���U%-��JDDDDDDD4�D�������*����YV�k0aG�S����S;Z
�5���"q	�/��JY��@zK)k�<�R\X��3455���Ov
C�����������ZQ���g�}6>��c��1������b����bAUU�S5�}��a�����s�G���r5���H$$$ ,,F�(++�k������N�������d��A���8$%%!  MMM���DUU�W������E�\�[F����x���������������������;��>��;���.����d����N_�{��&L�y������UXX��������n�(�=z4���PUU���m���o�`��Y����Sw/^l��|�t::����.�����p��Z+�"55!!!N���l�e�]�;v ==�>��]����p���@E8p�.�U^^���;;v��V���9t�5tun1b������������b�Jb/��Z[[���o������n�	�>���zI����������{}��T__��N:	999�uIIIHLL��`�����*�VWW�������{��{�/��]t�ShS��!55���hll���
J|���8���n�:����/������%%%v��������/����k
�����<�����_oW-1!!�-����/��l�������������{�u��1����q�����O>����������O<��N����^��(x��W���6n���[�b��>{nD4t��`V\OKePk(���5ru3,9eP�\�5m)5-0�vRR$4��!�_"�;�^��������{Maa!$I6%�ccO���'�w�?�z������	I
FL�����t������6YnCm�o��=���DDD�
I�� �����
���W���6�����C��"`�����V#�[��7$"""""�A�H �#���X�y,Z����s�I�
6u�w������>t�;�8>vl/8�.�t��Ex,f>l
p�L����]c@{�����_w����s;����������\��z��1���G�yd�����uv|��_C�1���t{SxG�8�_���e}R��$���D�,����O
�z�D�f)���lKA5C{h�,g��]wn��V$'�FXXX��{���
���p���z�W@@�>�l�q��7o���;�����O?�<���hv\u�UX�j����Y��s�N�r�-����_p������)S\�

������O?�s������������>���z���{q�w�kt��y3�{�=��F�������K�"%%��}EE~��|����V�S_|���366��v.��2$$$�����?p���b������V\r�%��c�S5���z��[�p�u������L�����������[�S��=<�,X`����*��[�k���.t����g�uV���u�L���������z+N>�d�}�V��\r�]`O����[n�
7��#FX������G����n]�u�V\s�5����<�w�}���
�QG��z'�p����a�$%%�=�e�]���#F����\���`����5kp�UWY�Wkk+���.�t�M����3g��#�<����C�x�e4���o����5�o�>����^U�k����.��-�QG�>SU�w���/��W_}��~C���zg�y�]5�N��r�����'��������{�=������}�Y�k@ZZ���^�u�YN!�C�������~h={���oFAA4
�������n��1c��[ZZ���/��;����~3���<��Cx����<���{�{s�������O<�.������>���s��gw��M��?���^z�����:HG�X��n�pVVV���q��a��%x�����eO?�t�Z��m���?��\`��?��t���?�0��������?����'�x�Ww��$	o��6�n����(��k�����N~<��s������T���O��G
�\�������<�)F����K�`����n��K� ��C�)5��w�*���1n�8����m���I�����`��pd�9��r�]U-���ZL��&�"������	����P\����

;:����B%�@&%���_���U�e���N?��m�).�"��Qh�`W�U�����������5��qxt��6�W\�\����Mw��{�����1�Y��]�p���.��>����� ��._sO�`�A��CB]� 8���^g��'�_g� �c��q�����N=�����
�X�$O��2
�B��K]3ZoU����H���[~�����z�v�zZX���M�J�j]�_�R�Z�4 ��]��n��
x��W��� ��w��e�]��655/��2f�������Zy�S��v.���n��EGG�o�.��",\��@���/�o�>�?�i��N:	��Niii�m����+���w{�MJJ������/�,��^{�5,[�QQQ.�s�������+�����?��>���CQ�����'��O?�d]�={6������(�8��c�f��x������=�q���;�N��U�����5:�/^��_�Z�$�������c�����jii)���k�}������k�Xii���}��}�Yl��������j�*�z��Nm����^{
�f���W_m]������/�9�����;C?\p>�����9s�ty���"ddd`���v�B��u?����f�L�<�[�r%v��	EQp�����>p���k��AAAv?�o�����
�����^�1�����8���'��_�����3�<�:�G}�eh/11���
�������Gw9.[{������j������{�������G��%K�`��%��u��s7

��>��eE����|��HHH����X�>������_|�]`�����=��������P\u�UX�h,X����^~�e\}���6m��>}y�veeex��g��-^���}�}�Y8p��~";;�&M����'��?III����}����[��D����g�����'_>�a���������SSS��X�T@@���YO6��������.Z��]w���N�I��_~��+�+fE���w�O�A���JhFFAJ���rA�������r��C���K���?�
���3f���]nWUyyy���6�KJ�����v�]QL��k)�M}��S�;8�w:]$"#�B]�F����~�����IDD4DxR����?���./�3������0(*�;��5Z:���U�-�M[����DDD4��
��
wxpq�������CW!��MW��'A��T;��������B�����`@nn�u�Y�
r�:{�mo��	yV�����u�#�1�V�r�:�Vt��{����7����s���
��W+�pel�O*�5�2���G���M,�����qipS���o�[�����hRc��g'!P���m=���vUX���:��=[W]u6m�dWQ�&L��}dd$>��CdffZ'��X��?��W�����4RRR��k�YCPmmm�����V"����>���]Vt�X��Vkk��k����o���mx��(�x��g�e�l�����o����CDD��c#gGu^}��.CF������{p�5�X�}�������,�N���~�e`��UW]�m�����_��{���<��a���~����Z->������q����+���S�e���c����o��6�W\q}�Q���w�����2�9�����;����p�B�z��x���Ws����~�Z��;�8|���=������G}�e`����^�����������[��_����b��#7�Y�t)����n���������:u�����SO9!���R;UU�d�466Z�%%%�����h��� �^�=��z�)455�h4��>�|�rQq�)���`A�^`h����c�����|Ct��gC�$�Ij��U.���-��w�	�����{""[�Z�����~��)j84�������y9����w2Z`�]�`54�����}>N�{����e����TUEnn.������q�����biFa�s.��rv�����P}��GG�-2r���a�4:m3��������adDDD4	�� I@PT��
��>n�:�-2,,�GD�o<�v�>��Y�#��Mo��E���98T��Ow��<��H{X�A�!!o�P�_��>]���s�$�i���T�!!����x
�
B�z��|-���*�ECGcc#~��l]^6ln�FDD����A��

-��{�U����PL
�����|Y�d��s�C�����ipS
f�����0�F)�����_������������+W��.�����h��~���L&S_
����Y�fY�d���{���S'�x"QVV�}��B{���DQ�8���w�y��G���/_�m`��$I���;�������������.���\Y�bV�X�g�����.�K�.��B����m��rX����q��!�rJJ
n��F��}�����;�����j�������ldeey��]w���������0yr�sy�:�,�p!�q��r?Ap�Yg��'�����}��
�
�����.�����ss_�������'�X�EQ��o���s�#oBX]t�]��m���
��Vg�#�<���&M����>���b��U�e�)��W��N�����G}�|����_|�������-�\�%K���?�����E�p��72��K�����Bddd������Cyy9TU���h���

��`�7�DD�4\��D$�.�LC���n�(()1���A�m�v����B�qa�d&@���`���Y��>X�%�2���1a��^}2��������r������/�Q3>Fpp��GG�I�������/\n���z}:$ix���xR��;�U������FY��^g����o'Z��dP�{�)`���.��Pq����'��<
����a�p��jG����jG��D�s(�v�������u���L�M@����� S��;�:������[�Z���yBCB���d{������7w��s<��gH��������u�q�����������;Z
8>4i��~
�&�ojE������S�}2^"����F������q�+66�-����G�;"55����}{���S�G������m����F|���8���z���}�F��/����O<�D��h->��/��iho��)���Q���($''��������u���-_~��W�����9��cW�i�����$I��^��`\p���8q��� 8���<�w��Iv��_��b�������������?B��T�>�������g��w�y��`���v���1555��i�u��3�@dd�W�:��������fl��Gu�]���R{P�_��������o^��������[��{��b�t������W_}���gc����dq��`h�O9�Tdd$����?
����������|:"z���������@���ix�����
��	��2���O�T*a�j��
��8:�=�F���b�����b���~PS�������>q��l�������#((��#��2���hm-t��(��������adDDDD��V���w�?UU����[����NpYbD�30$XCB��<�v�.������
	��4�uH�����0f������<������/5
2j�#�aM@Xh�w�%"""""*���������[�k0!�`B�F���@��i��� ��ZE����dA�����T������H��J�D����|�?�W���?������
|��'��av�����J466ZZ�������6�������|�	6o��={��������V���v�m���v�.��R,_���_��q����~���<n�8������ ::UUU�������M�>���Qqqq�y�


}5,��V��N8���O<�D����
�t��n����Dhh�W}9���Stt��rjj��%�}=� 1�_�M�6���?��;������z455u.����[�������E���/NA������-�;�����P�#U����Srr��rvv��q��:H���?�����=��;��z�'�������->���p�������Gbb��h���k����"//@��c��YX�z��j��g��2��|}�����>�-��������������(n����*�p&��0��z�������L�T�`
��:h��AJ�� �M�n�[�  99���a�#�����l�?:��wf�A@f����VTT~����X��;���?B@@��64�����(..��:�'� ,l"G������h��B��K]������3F��?"""""""����q#�G}�Mf�m�[��:A�F,*`�`~Y�N��y�R������������X%����������;��U$�F}}}���<�o�_|�E��������v������}��W"���[p�]wa��y8��p�q�����B``�G�UTT������o��^�h��x�=��LwBBB����C�/�[�<y�W�O�2�n��*j���z"66��v���7��t?W����/
����_~���_�]�vy����������o�����7�9���_���cX���n�m�����l�����up���w/N?�t����)S���_zU����
'�t��,[���-sz_������L,Y�K�.�1���p�Yga��=^_�;����������cWUU��������e{�t�`9*lv��*D#!.p��p�{�(B3:�2 ��9r���XXr�a�u?����)A����e�`������J\� a��'s��6mm�}�0�Y�x8�j#9������PUw1y"""��g���WM���0����)i��H��5�*Z���^�F��S���}�����BW�V]��}~~>�M����z���=0�=���6m��)S�j�������V���_~����}��Y�;��s��EDD,X�g�y]�g[4�WB���l�M�����E���e�t��wu��x[!��������
����5|��W0o������~8���:������%}q�
q��'�}�������Gxx�W������{�/�������N������y��Y�UUUa���^�M��1�H�UU������g��$u�AHw����BUU�7tbb����?P���%����"������T}`���CC�����J��Kn9�������&��C��63b���� ;v,rss�~�������dee��}�@'�ZL��<v��+���p���%;v��M{M��GH�%"b&����lv�Y1+���S�?0"""�>pn|$�+������������������,}VN�Kv������NIC��o+V�����l��m	��=]1�LX�hJJJ�����c��y���@RRBBBd7���'������[O���`��ENsh&O���s�b���1b���h?����o�8L����m����g���/����R�6F�?��3~��g�~��X�t)z�!��:�S���Q��g�����q<?455y��V���/�~��'\s�5va3�F���;�g�FJJ
����TUl���~����^��K����k���������q�I'�����u�F��?����x��USS�����,�"|�A���$	=��;�8��w�y�<�t:�C{f��
Q�'���2<��S�.�����x� X�{�s���������� )))�����UUaVT(Pq��
��=��\�51$��)Pj[`�)���}�q���?�!���v\<� ��LDQ��q�������l���f���!##�8��0KR&Oz�w\����.�46���]Wc��7!I<���AL�	(+[�r{m�o���A�a������,}���`CCK��5'<����������<����Y���R|V�Y�W������I��GN�@-t�2�o�G�;A�o�[BD0�SF��?���7���im��uoi�����_~yyy����x�X���zj�����^��7z�!�JC���x���0k��n��6�����w�q~��7�]�?��36n���6��Z&�	�?�<V�^����;Upr�{���x��g���� ~n?���zkx��s�|~`��z���o���~��x���1r��.������������*Nt����n�	��~z������e��G���8���PPP`]�~����^o���0���f��iHJJ�x�c�9�����Q---��u+�>�h��2\�7s����;w.��[g
��{�������g���c�w�y(//������������������{�/
-�F3
��Pe0��h�I��Lt�VBt�HB]�B�;z���0�U���������Rj4i�4C�*�P!I233�o�>��444�������F��S�������9�e���M���ZL��
D�a�� $$!!c�����MQ���Y������@DDD4\��
�����S����p�����)87./Wzu��9�!�>%'E���i0DBp���[�
�������o����[����j�p[w>��#���+Wz<������q���l}�����������SE��;s����e�`6��e�|��w���p��k���\,^��|���1�!�����N��x������IXm�������EA]]"##=���|���D������'N�g�}�Q�.^?�����+++1z�h��������D�\K|qnp�)� ;�������^������1�����z�gA2����*(�{�u��?��u��h��2�L���q�-���{�A``�����q#����a��]vU�f���y��������v��9�R�Dnn.v��������"((���7n�L��T������;rrrPWW�N��#Gb���������|l��	%%%0�L���Dff&�9�����P��k�Qa0y�_t��W����!��H�	����a��d����r~�Cu���C	A���`��h��=����Mmm-


�]`zJ�
���+�u�%hm-p���v=���&Nx�����AL�����Z��55�CX�$y~�"""��jaL8�������>����HN#"""""""���1�X���6|^Y���-����z�lm��094��BpN\����D�4"rA���K��[_����={�`����k�.��)����7[��N��U���{�z��7���q��a�����������6���=��jq��G����������K/��n��������o������,�>			

�V&:x� �f3�Z���q^n[[��U���w.hRRRPTTd]��s'������;w�t:QOl���ny��%��]?��BL?���uy��-UiHCZ�a9��up8iii�����m��Y���z|����2eJ���X�R��~.���Y���$W8���Yg����:_|�A� 0��x��G�������/��E�0}�t����!�b�`�����a>�������������/���oEQ�r�Jk��?��>|�����	�?�<^��.���t�5k�?�|�x�����
��wV�X��T��3p�=����b��?�<���	��^������l��a���3�
6V6������.6 ��avl8%�����H�Dh��A	��J��<�����R����L�����N�CVV�����u ������p���`��w�u�E0\�����;������� <�uZm"#����W����~��Q��{�����������-(7u_}�[	:-L����������z+Kd
����Y�QQ 
�D���14Bd0����p%D�@�7��9s����u�p�
7x�g������b9rS����������J�(����s��'***����/���������k�����{�=��_��.���jq�����~�^!n���8���|>��qu������!,����W��
�7s����_�v�W���k�:��'zsnv�>�No�!s�����|��7���k����9��}��������h4��s��o��f]�U�V��<m�l{#O9�g��������6����ob��I�q���������8��30b�!!!������D`` �O��k�����+TU��TU�(�x���0}�t���Z�
%%%�~���1c���y��W_}���t�}������d2��_�#�<�����g�?/�����l����s���
�����F\v�e8��s��������0~�x�_���~h��5���`e�{�
����`%j������.!@��$��K���h����"�6Bir]�����deeuy�����qT�+00����.�m���������a$�Fd�h��.��L�hh�����(�NIC�F��q#4>���(-�GDDDDDDD�K� @����@����AI���	����}s�c�9��Z��_��Zn�
����|��Gm�Qx3��_��-����-��z���8�u����-WWW;�9��S�����>�����k�+�m��������D`����7�n������v���+W��[7���P�����h4��7�����\CN<�D����~�-����U��-))	'N�.�����o�����up��X,����}�=�������N�����6m�2c�(//%%%v�<�XL�����k�b��v����]�?�����J���������m��G�����^��%K����j��#�X�=��S�z�~���O����rJ�"--
�f���I�z\���_��E��N��6mF�
I�����;���K.�j"��(�����������$	����:u*�����UUU���N���������h��%�h�}S��UV�mI5�{�514����=j4}�G�(��0���=�P�=7�!33��zh+44AAA~U�
N���o�
j@I��((����A��������a�4�qDDDDD}'K����"A����tZ��6�z�w""""""""""[R\�������).���CXDD�=�\���`��e�<������88md��a�G��;vx�����[��`������_��������Z���~z�q�kd����%K� ""������_�u����u.**��>|����'�|��~��?��zWXa0;������l].,,��������{��Ns��Eff���H�CO����s�S�;���������/�.+������P�����[o��n���nBCCC?��O��C��(X�x1����:Q��{���3��I�w��7��8�3f���m�C{����a�,_�Z��)�����������e�\u�U]�y�g���o��;�����T���7��?��O�p�i���o������������k�.TUU������.���?�������:\t�Evo�SRR���������mCaa!����t�R�}?��3<���?�'�x�������o(..FAA�o����Z|��gvon[[[q����
Y�����Vp2)*������  
� @�
���th&�t�U]����.��J�����z=222���bhh(�8�������)oA��W�,:���^v���������\nSU��Y=������,}����y����y��X;+��="""""""""��v� @�}�����p��7��y����8z�������{��$I�={�u��������g�
�������@�?2���D]]�G�&''#))���y�f|���]��i�&\v�e^���K/��u�<n_WW��z��1��]xx8n��v���(���K�&�{b��������l3a�����j����^��/��S�x�b�����N:	Z���~��'��~^�u��
C�$I������q��������7�t
��|��>
�s����/��t��+���'�|���l�m@{��w�y�]���_~��_�����[�l������^j�:������N����=>4O��IDAT��l��o���{�m}q�����?]w�uv��A�����/��g}������^��~����KX�b���+���gc.�sA�$�{��8p����n����U����r�)�����i�&L�4�����p��\���e�V�>��|�
N=�T�Y�#F���.���_�����>�x�	�Gjj*~��w�}��v�|�9/��2z�!�����~�~����q���G�K/��#���/�"�=�\����vi���������>6V6�����VY��*�D�gQ�&9�g@J�D�/+Y�%���y��{U���+,,���s�aaahjj����OX�$L��:D�}X1��	*y�����3����LssZ[��<""""�������)xwR*���x�����79
/�OA���&���!�4��L���D�cZ	���t���>�h����.������/�����C���-**�5�\�������r����-�y�����[PYYi����O=��:�(Cdddx��(�8��������3g{�1�Z�
?����?�����������#�����n}II	�������G]]=~=���k��?�����e����U%�����O?��g�������L���3g�<�m���E�Y����p�9��������k]G6m���~3f��QG�m5:��#��{.���|���X�z��k\PP����ZLL�]AQ�q�X�b�S����w���.�UW]UU1f�w@�����F���v���n�����-((���K�d����]t�>�l������c������.755�������~�T�u�����������
��"++������o�}���q�y���7����~kwn������?~�SX��O?��	���o��������_��0s�L���}E�$���Cx������&N��e��!//��~�����t�R$%%a������v��/���f0��[�������m�xN�u�}������H��O��Q����19������h�L&�z������]V���s'���?��k��[�����n�����;����#������Gvv66l����w���uuu0�Gdd$F��Y�fa���ve����W_
��`]~���q�x�w�N���������{����Bt����N|���X���RJCC�|�I�@����.�p�������QRR^�u�t�I�uO?�4����#::���h�;�b@As��Z/hjCZhF���Y�[�V�6#��(�s���y5�a�yBQ5�Y�#���I��1c���C� ())Ahh(����<��1�'�����BUM.���-�F
Fb���<:�'�&QQG���uU����HN���H""""�Gc��0&��m����[���
���&B#arh������V�#"""""""""������N�is!`�t�Cw���b(�G�z����u�Vl��@{p����������"::���v��CCC���/���r��W���^��;�}<��Sx����������������|���;���������������_|a
�����;�p����~��������r�}�]���h��~�]w��{�EFFBBBPUU���"�`�s�=���EEE�3;;��?���~H���#G"**
:����(((p�4�7�|��1EQ�|�s�9�Z�NUU�\�+W�D@@RRR	�����z�������������C���@{8�]E�e��a���^���q|��7hnn�>��+��
7��1c�@�$�����H�?�x\v�e���p$I>��,X����7�6��x�������"55QQQ��	G��O�K/���Q�P���Ob����sbYY.��B��z���CE��������OHH��}L�>��~���������<�y�t����������GAA�~�i����|,^��$!%%���0�(++CUU��������\�����!���:�5+&&					Acc#���{�<��:�o���X�p�GmW�^���W����[o����O?9�����u%H��krzz:�~�m�������e�������IIIHLL�,�8t���}���� �Z�
���^�o�ch�� `���?~|ePZ�j��I��.�*����>����hSm{WWA��e�������x���VRo���������m���O���s��/�h��'�|�k�����h��]��}#_�S�������nj2���0g�A�w��#��
�
���H���v����X,�.�����\deeA���wp�$:�xL����������}�w@�Bw��GG�1
MM{a2�8m3�kQ_�
����>DDDD������TUE������Hb���uG
D�q�0�;��
��'1��#Xa����0�^���v�l�b]��*


������a��U^U��j�X�jN:�$�����^Q������x��q��Wz�|����g�}7�|��d��DEE��/��i��f��X,��w�S{Q���O���������U_�dY����*	9JJJ���~�m%<<k���������{����ht[%���Q������������%D)))������;���Sss3v������N�g�}�2�3�������~��g��m��Y�+����|��������N������1���^{
W]u��y����8���>���M���g�y���5kz<����;v,n��V�s�,�.�����y�f\r�%��y�����j�a-[� t{-���� ���_���\u�U����YZZ���R���;���f��������
}�������e�|���U���m��we��HMM�.���c��
n�����v����4���t�qL���G���Uk4�������U��Pg���
"w��`���A;5B���(��0���9����;8Q�KHH��)Y������T�P{
�2]�)���={oBM�:����O$����v{m���Mn�
� @����@���#"""""""""�t��&C;#Bd�w�F�@;#����u!&&��{�1$&&�l#I�?�|������������y�f\��tc�9s������SO=����o��dgg��{��	'��#F 88���M�6
[�n�e�]I�\�.��
������m��	�?�8N<�D��t��<v�X<�������G�Q�O=�rssq��W#..��}F������W���b��������?���g����T���B���SN9�6m������� !!�<�V�^���p?�p�9r$6o���_&Lp�N��=�V��7�|����W\��������w�&00�����{���:�W�������w������0u�TDEEA��ll�k�������������.�FDD��K.��?��U ���3�6m�_|�N8:]��8$I��G�����<���?���;��{.���q�}�!99�������s�=�;v`���~��$��u��|���)))��S�Nu�|����fDEE�%����������W_}5^{�5��]w���z�e�;���>��uy���x���=�����HJJ�.�t:���ztQ���{�b�����={�t�����*3.X�aaa�8��������Si&G�1#fh���TY�|���J��x��V�&=��h"'{�����eeen��t:�?��X�������������S�Bd$� 2��������BB���x��GDC�pz/LD4��LD�x&"�_<�����_���X,v�� ==���)M�e�P���4��7��J�� DAJ��:|�.���(���_������J --
s��ELL�O�hnn�/������AAA5j������p�������q��A455!$$���8��c<
�uG�edggc���(--ESS�
�CCC�����S����)UU�w�^���������G@@����������c����g������u�p��a��� **
�'O��9s�5����bl��hllDdd$}�sAG,_���w�u�q�vEEE����PVV�����ddd��c�Appp������c���QUUe��$$$`����8q��8����b��
8t�jjj����^���ddd ++��������;���[QQQ��������1�f��6�:X���PC�75����;k`h�������k�KMM�8��{�]ho��n�:n;��c<�g��=z��N%&�	������3=>
-U~��������� H"4i��FF�r�rq
����f�}e��B��1.��A������6����lc2�����	&t{w��b���`�[�������b��]Wa��w6���#������(�����e?Z[�<��#"""""""""""""B��@���s�TUdPT@I���^E�|���zK�����N����JTT�9��>;�$I�8q�]h�/���~���x\x���=�A+99y@�ki�=z���H�A0m�4L�6����+���8��|zL]�wRRR�������f�b26o�l�<e���������;�L����Hc���X�p!�|�I���z�Gvv��������c{���W_4��������>Tm4�n�g���#�;.b\�G��-F���ysa�����	����D�m�F#rrr`�X�8��5:e)F�\�v�,7c��+�����Q�?i4!��r�����P���3ADDDDDDDDDDDDD��A��� �4��g`���������O9��������������>}:��y������hkk�����?��[oEzz:���.�*z����O�5j�Wctl��A�a���6��/����aVT���L�
C{��D} t3FC;3Bh�G�(5-0�v�]%P
�
��3A�������Mkk+rrr���uii�������n��c��+��Z��A�_��O�N�r��\����~
T���`QZZ���444t"�N_�h8`��Y^}���������Gy�7o�g�}��P���*++��G��������h��EAMM
�����UWW�U)�j������/�c:������U�~���)F����K�`����W��K� ��C�)5����O�������N�s����yyy����(��� �~dK�������T��;.���!0p��GH}MD�������\n������Lh��~
4��QVV���z��=v�����f�Wk8l�SMMMv�����[{� ��3���E�0r�H���`���x��wq��a�>?��/^�����y��MHH�W�AAAvcu��v\A���ql������DUU�W�8�)����������BKKK��C���U�:�45�$z�}K�+a`Z"��F�������UXT�\\99J\����z���[__���$�7,hhh@vv6F���5q�JJ�c#�����n0�b������&��(?�������`0�9mQU��~@D�B�u*T�@ B���g�zf��&"�x&"�?<�/�������D������������V�q�x���!�2�UW#�5448�v��mDGGc����;w����.������t�R|�����}��y�\~��N�8~���X{��i?]�'^|�E�w�}�:��M�P^^�����M�6����
@��U��iX�-�e��`T��K$�KQ!��
�&�5h�;�\����O�$[����������F��|����m��
���,D`�!h49.���u�_��z-�`����$Y��.B��m&�A���Z��� #��h���XDhk@C�Fc�?�N��P}/LD4�LD�x&"�_<�������������0�TUU�����/����QC� >�7���I������)��I����w���'�l����v�4��:�����O�nkk��~hxHm��K������+#d��������g��013�#0M�`h�x����(���������� ��z?���i`h[�2�mI:���W0p:�����(�Q���z��mv�=�h��m������%=�z=��KDDDDDDDDDDDDDDDDDDD4�0���b���SOENN�SP�3������JtK�,������WE���K�#�����X�n]���L&��j4�<�?���Cc��$}��C�D�4�&l��a��-�g��81�jG"S���Go_$�B��8k�:�{��\Y�SHHBBB�8���C[�_!��n[HR1��`����/�������*y!!���#)���>KDDDDDDDDDDDDDDDDDDDD����0P���+��}�]E<UU�E�a��Y3f��������'�U�����<�?--
'�tV�^m]�n�:��?��~+�y��������o]{����������8��s���f�BVVV���---��i�uy��YC6�`��C���-�9����?"�(*,�M�5@����(H������<*Jb( z�ZL�[ 4� ����S5"��P���!�WS*�:�������n�{z�c��ET��*dC��rrr��������$��c�<	Q�{���l�B]�*�+"�QQ
""N�F3|~~��pz/LD4��LD�x&"�_<�������������:<�����^gU����
�>�("##�sh�VPP$I�,��i��y|�y������l����1����]51UU{�kmm�Ve����|����C\\\�������������;��
�*���}�Fo��0*��2�"���I��@%��5@7�iY���BE4�	���<����TA�kuL���4 �4B��&-R��<�x��<��� dgg��"\^^�������s��(3�����.B[�A�-��P�}�8�i����Q_1������B������k$%]������C������:�������DD���a"���s0�����aDDD4�,_���/��a���=�� 77�O��a�q�x��W��%�0���c!���edd�-WVVv�GII�#***`�X���("&&��]LL�](�l6�OWJKK��{���oR�>���i`��Y���M�����6���a�X��9���,0�(�y��.{.�]�
���0�(�j�t��0�q��u����Gmm�G��b1m��Ht����k����m��Yn�����W��N�b����A��W����������������������|��=��m�[NMM�����O�Z�������#�c���:�6�����b��pl������@�vAAAHNN�i_���^�OC���@�������� �
q��&������@7;
B�g?j]+L�����+W*�m0��JYC����5������5���3fL�m����������IPP�O{:�s�����O���C�
UUk!��Uw��,�����>96�C{�����A����'h4�~��1~�x�e������}H"88���c�m��}^���������/>f��#X���q�$bvlx���/�Q!�=��#�@�G�(e
0���iw	L��*�-��������T��UUEnn.����8�����S��F���{��[(,|���"_ki)@ssn���������>�����������������������C{�u2yg���p�s��O�[����j���J����h�6&L�V{$�QTT���2���������N����������~���PTTd]�j�N�F�%����W'
X���>
�5A %E"��q���<�^VT(%u�E��`�2L���|"���1j�(��EANNZ[[�8�������oA�B��),z�_�������6�~������������������������n_
E����H���O?�x����������u�V�����6���8������Y�������~��n��g����g�a���?X���Y�z������FVQZ�62�g��%���AT�g��2A���y� �����-0�;��PIII1b�������N�s����)�2�U�b��6<����8*���
C�_�2Ja4V��/""""""""""""��g����*�?������M��2����2-+�K7+[��3�,�J�����l3�z�l�j�zs)3�PY]X��a�������`f>����������;g`�0��y��������m1� ""@��>PP��c����n��F�e�~��Y�j4|��w�F�m���)S���Yc�������?�
f���#����o_�p0k��5M�:������R*05��nN��O�����1�G��T@�'7E@�c����J	���v�=���;���L�W��HIIAMM�
��/O����gAn�Oj�2����aU�Z��i6/���Q�%It:��*�t*�o4NDDDDDDD�a�*�Nd���P(�h4���O������G�o���o������������3���"77W�vww�m��f����3�t�RTTT~��W���c��5�I��j�*�e���3��!�L��s������~��U�0z�h}���_~��������{�1��:/GQ�Q�ws���r�U�p�wr@_OWtwq�b�D�'ss���0h��A�zR����k.@�s����� �V�Eaa��>*�
)))����\�9�����AL��8sf!���SC���;���QTW�6��
Ci�i�\�%���n�S4�NA�|?KDDDDDDDDDDDD��R]Eyy��s�R�A�����2�J�?������=��u�+��������'�g�����������6r�}�a��u�0dzz:y�l���d@����x��g
�=��c���0����O<���[�_��C���C4������_�U���������}<�=�6m����r����n�:,Y��h���<��C�.\h0cQC�]���E*5.�U���*5jt�%�A&�G�������������}� �v���5h�r��PT���*�+������A@�=��jQ\\l�OUURSS
Qm[����M�6�)��]/IZ�>����^^7�C��$IP��l=*��*����0�9�&���-""""""""""""c**.�����sL���T���FUU6�����O�!pq	�a�DDDDDDDd
C{Z�lv���N��/��O>��>h��:�L�7�|����$���n�����]��
��-))���+V�Cq��W/,]���q�}�Yl��U?;_FFF����_�<y����K�.��W^����o��/�//�f����.]jP���?���l�������N����;�p�Bdgg��b��E��C�J���$	I�V� 
�������d����*T�f����W�!s��x��L����������h���r���!**���m;�����j��~�e��%������-��e���#sIR���K;"I�@�jg�jm1���0�%�* ��5�������������_Zm�^����4�������+9pu�������*$"""""""s1������c��%X�z5A�����a��������K����W_}�`6����<x0��[7TTT�������1����_�5�������_~�%n��6TWW���0u�Tt��aaa(..Fvv6�
�B�:u*�y���s�=��������/{����� $$���h4�������+t��������� ���5&�U�v�b��|u�E���HNNFee��>���8{�,z���i������F[��0�^��BB��1p��������$�f6��E�N�VaH�����b�y�#""""""""""��S�����o��V�j?���������iP*}��:"""""""�C{���������g�}���R�3[�l��I��]Z���s�����-�Z��/�������Pdd$v�������������?`���v��~yqq1����ns���c���]P+���}�v��7_|��~�V����nS>��������'It��
��J� I�&��rDGG#))I�o���.\@xxx�9��!�A�)GV�F�k��HH��A?��KOWG��,m��T�����m��0�Z����5�t$I���T�������zJDDDDDDDDDD���TW���t�����V[����t�{DDDDDDDv��^�����u�����S�L��Q�0�|�5
����.�����Ob���X�r%���[��^}aaax������������1�����d�Z�
[�n59������/b��i?ptt���������W^ABB��~...�3gV�X??��EDDM�����~mI��:@.�v���B�����[����E!!!�"h"z�xmrr�c��Z}
���1h�pr
�q��Ap�L�l��R� IH�:&j��'CY�!����� �-�P-���aV""""""""""���j�p���m�(�N����Ep�l��S������������������
�
�j��$����8x� ������
E�����ou�����(|��(--����q��Y���������8p "##[5���?6n���������HIIAqq1�a���g����������w��s���������AMM
�t����h�x��pttl�����I���:;�{Q*����F�1�'77r���u�qu�!"{��V[����������?�{���H&	���UU�6�����C��4F�o�]�=`Ar��K���$i�*\*� �gN�P��v��S�������������s�zu��
��[������0�*�'"""""""���Sff&A�$I�-�SUU������������o���~���prr��q�0n�8��Q�g��m$""���*�9�NNN���Frr2�Z�3"^�t	�(�k��6��>A���u�j+q���}��/">~
��6��Lqt�ih��%nnQm�?I��0��nQp�6<F�:]
�3��=��a���
k�x�'""""""""""�������4��Q^����(���7����������C{
� ��.���5QG&�
P�0�Qf���s...���Djj*t:�3}eeeA.���������L&G����x�\����>�����0�r���+$c\]#QTg���.��F�2�C���I����	
��M��g�T
��6'��@��Ua@�����?���H�N�~��f"""""""��QTt�f�0�GDDDDDDd[���P��G���+����2w'^�j!wwwDDD ==��{����CExyy��:������w#�������>e�IHH�;�n�(:��BjH����c��[>�����T�X}k�����x��m��M��7dGW�3����	c��h�0��u�-]�T��(/OCuu.T�<�t*�:�L	����pu�������Ju�&�w����T�,�������������9s�]�����0�'tq��X���'z���s����s��YDEE��������(:#��G8?eeg��))9�S�E�~B�6�����+W���SO�!V���
	�a�?s�B�-
6\WSS���B�dAggG�N�����d'Z�t�!A�ZT�(8X;s!o|@��UT\@Q��&/��T���FUU6�����O�!�S;�����l<^*���l:&Qg����>��{�@DDD-$v���U��������h|||��j���at�$IHKKCtt4���l\�}��n���	N������F�\+�g����}��Lf�Y��8�p��FZ�����Q���:Q@!��M����		���1c����]��$������6�N��s��I�$5�Z��Fl����M	$2�V[��W���=Nuu�\���k|}�@y�""""""��L�$R]�^[��F�v��0���}��a]���a-����c4����**.�s��Luu�M�#""""""���#""�������3��J��%x�@��h�q:2h�Zdgg]���������8;;��:�pp�����8qb&�������!%�9���O���R}��cQUu	Zm���)�.�������Ad��+ ��O�$+��^���Q��\Z�Bk���
6��0���h���TWq����~oS^�����������#""""""[�<@�����}��������:�����ai���:�j5�w�����w��\n���<�������_*U$I����������l��="""����P����8>V�3�F��������j�HIIALL;GHR���������P����27oD���/��iv$�N���������l�2����8;
�� @l3�g�� :��j���j:�<6����)�����i�V�-��|O@��R]m��4Zmrr�BP�=��3
:��*el[��[>CU����_mqoo��Z����:
� �sw�����J������t:$I
Ap�w)DDDDDDD�C{DDD�!�~��v���J����u�����|G2K�����j���gt�Z���:�?����c@lmpO��f�O���!�]���^�oGJ�/���i�Yi���8+
uv��i"DQ������k�L�-
�`j9�3$�Z����j:���8�\���?:��
�/��7!j/��|�[�������l���Ji���5��uM)jj�&�m������k6?���:����ZZ3�W��I��7?�&"sdff",,L��3g�l�b���:��s�b����vFFBCC������|�	���{$&&��������+V����+��bj��+Wb��U��_�Pg��ga���=z��
"�6��u���P]�T����\E����o'&BCC��hPXXh��J�BJJ
z��
��63=���K������C�)3�';�#�EW��=i���>�����q��~����x?��Q�������@d�Q��h��$Ij&hI��� u|=��O���Aa�����d�y`���������h��zu?&Ze�DDD�MS�F�,�dl_hv������P�5g�2�2�q�{�,�������������k��q��������|NDDD6u��iL�<YYY�.����Q��HKKCRR���PVVWWWx{{�_�~���d�����J�c��!55����j�pssCHHz����={����C{DDD�ar8	C��������A�PAp����$z���V���b�}���������{�9�R������7#>a��J�}.d�Q�����l\�'�N����(Cuu���::��s\\��X!�'� @lD���Sk�,�-k�}�(9Fv#I�?�����&7���b�@���:]
�����?�`E����Yu���TTTD��Q3Z�2?�d����m����%c�2�o���\-M��t����g�x[Zg�A.""""�� �)�������:���B�v�m�r���K!"�0222���_c���8t����L������Y��p�BDDDX4��-[0o^���5j8���O�:��_�~�-*+�_�
>>>?~<�|�I�p�
-���U�DDD�����0,5�2�|����l(o�	A�d�%�L�^�z!%%ee�g����@ZZ����������c �����SA��1����W ]x�����\\������������J��N��#�)�T���1��QP*}�X1u� �Cm���$�����m4��Ij��J��{!����R���$:���Wsp������_g�]��j[EE�l6C{���eh���Ss�,K�a��H��m�YM�
��A����J�hb��ki�_-;&-9�c�=A�U�1K��u�����o��0h7�W�e�����UUM����J�|E�R�$A��B�$�Q�3��8pc����W�X��+W������Xk�d���3�������Ctt4�J�~yx8�_C����s�u�V};##����+��-�J�Q�F����foSRR�
6��?�����h��v��U�Ra��%��������s���?Gpp0C{-��u827G(o��:�2tWJ�n�*
�	�A���T_od2"##������
�}JKKq��Y������Q�V��nD�>�����h�XJ�R��3����qud�R���&��D�
�h!"A�i~v����2��M��
	j����
6*��MQ� I��h�m4f����
�d
��jj
,��5��s�Rt�����R0s���������M�ZZgk������v�W�9����S�e���M�������:��BQ�
P5�2�o��X��mX�Z���K9�u��u�����������h���Z,;�M��,���}]�
��(�f�9:�l,�����DAA���QQQ����������������v����}���������qqq������!"�6�Zm2������]����8w�jj���pMM
/^���l���V%[���w�q~���F������� 33*���^�:����mtypp��}����DDD��9b��
,��B�"�A0���J�3y��U@��ET�6�����rDEE!))	���/�.**������G����p�������DR����E���A���3���QA� �&�BD�Y��eE��W����k<�`Kgd���������Dk��#m�>:/�'(�~��2@ey���5�m���������j�L[�������`R�����k|���Y-?-�u\�������oGG����+"[su��ih��5�fcY����/_FYY��>Z����(--����������@xzz��R""���e�l�bv����������Mc`���
���a��9?~<��B�_WUU�o��/��"�����7n����h<����x�b�z��f���}�Z��]w�e�svv��O?����111�5
������?���>�h,�K�����6�Oh4���n��5������C�s���]Y5�W�!WAWZ��]
�!sw���	b�.\�����6���>��uq��a�G�y(
DGG#))��.$�@.�#$$�S���@��Dj�F�K���<���7�����YKm [[~�fl&���h�W�h���c#{�m����*jj��tL""""j�2�c^��eA����6(���������ZZ"3���kQ��T���1��9V��1J%/���G�V#33���o[VV���4x{{#44��"j"�� ==���0lADD-s��7b���?~�������0k�,L�4	��v�;�_�l�2�������h���{��[niU�MY�n����o�����~@HH���r����G�����s�����5����P�N�m������/27G���y�����@�5zc-�	���
R�����.ApUB��h��;�R���h$''C�V����Q��{wWg?AA3��V����F��t58u�a��l\Y� �2��&�I���a@���
�dj9""""jSm��$@�|���:,
&5��5a��P���-/����GQ���n7773�l�q�9<=������<=�X}"KUTT 55��u�*,,Dii)�������F�����m��LD�:����1i�$��������_���j_������?�Z�Z,--
��������������}p���������h.�g�0HDD�>������2(����9�Y��huP�������Y���	QQQHNN�Vk�B�����rt������Op���h�������Zm%�����-���QG 2��6x�+I�3Z2���u��i�����c,�dYh�-g�j��g�2�oc���!2s�m����c���H�\.GM�_3���+�r7;VDDD�������5��iV��5
..�V�?QKTTT4y=���j5�����u���7���6DD����`Q`�N`` �����7������]���,Y�J�oo������\��q�="""j)����C}<��z�B��KP��C+pqqATTRRR���������(�����qu��$��rd_���z���	s0h����{� @��m�������
}��%8y�A�L&�O�h8:*�$8/KDdm�1/��\�I�����@�_(
����I�
E�����������T8�����se��?.����XTU]�V[���E���i����Z�Fjjj���h�Z����_�~�>[��t:>���t���������9r$����l���b�9siii(**BMM
�t�???2!!!m6Vk������38�<�����h������6�#77'O�Dff&JKK������???����O�>puum��+++����#''����khz������IKK���Gq��e�s0t�PDG[���m}�{vv6�������������7�h�`����q��)\�|���������3���a�����8|�0rrrp��5���`������mv�s�����#�|�2A@`` F�����V>��K{<�HJJBvv6JJJ ��������>�U�������S�N�����]���#|}}��������U�W��8|�0��9���b����{��5jT��z�������#//EEE��������\h��`{2r�H��^vv��1t��|��������1q�D;V��t���'�|b��DDD�y��n�"��9�ot�.�����x�	kpssC�^����f���.��8�A@���C�-���_��V">�o4�+89u�������R��ib�iU*TV:����=����&cJ����?u�a@SmIj�]�z�V�c�6�1�2]G�T����"��T��ki�_
�o�}�?�������o��9��^�������������i���
:���
�$�)8
���|g"����Z�����j5233a��_��Z-�|�M�����|�r���(b��ix�����1�����_`��=HLLl2L��b���prj�5��gZ�V���U�Ln��~�=�`�$I8t����+���iiM�r��o_,Z�<��r�.���};�|�M���M�E�����w��'�x��k_~��w�^����3�5�>???<��#X�x1��L��>z�h<x����6����+�r�J�����u[`��e����o��'�;w������������-[�����^x��7�mtt4��[���'�U���s�u�V};##���dS���y�W���+�N�-[���7���3g����d:t(�.]j�ci��m��
������m7l�0}`��s�������c�����i��`��
������?�.]�#G�4Z'&O��w�y���f=���z8�����������b��}���5�WE�7�?�|�������W�g����dff6������������q��E��\\\0~�x��?&L���4*�
����z�-\�v��zQ1}�t�[��Ea������{������l�� 4h�-[�)S�X�k����!���;U����[��h��Y�f�����C�����c��DDD���=��+���j�����\�N�;�?��.]��g��8{���>g��ETT��wZ��	�������V"/o��>*U.�fa��/�Tv�������A�A ���.���$�d�O��An�NH�u.�1N��d2�,(4�|�*s�5�msu6�j�����Y��'""""""���R����{p���m2��(� 0p�J�|�����"Zu���B������3��k��a��	F�1u�Z-�o����w����o�ac�}�]<���f��p�.\���;v�@��=-��/^�����������;w.>��#|��7��k���J�����}��Ych�Z���#>>#F��-���d���
��7��oov����x������b���2d�Y5�V��Y��VG�������_o�OJJ
�L���^z	��-�Qe������)Sp���&��t:9rS�L��	���_65E�R�������~����c��w�}���2�'>>�F���_~����K��.�k*�)Iv�����88p���-��=ko����n��'��]��b��=��g�q���[��[�����3�<����f�VTT����/����
������;��			&�h�Z|������_�g�0��G=z��w222��'I�?��S�b������������6�<���KNN�A�-g1n�~���=f�;U�9u��Q[���Q��9HU��,	P'dC6"����v����j��p�����$!--
���-�P�z$"zG�����SU�����4�s(��Qg A���&��]QU�m�z����k�I6���������z�T�"8x6�^��������5
��c8��K�fy��8�eee���[�!A@HH|||PPP��Q���S�N��_~i�8��������!00�h4�z�j������1r�H$&&��k-cuzzz"  ���P�T�����+W�:tc����c������2T���CPP�J%��������W�ZT~~>&N�h4���[7���C��"++EEE�u���=z4v����n���1��%K�����'''dee5zn�/_���L�6����������G#;��F2����������W���e����~��1c�w�^�_g���k��;n�x�"


������=�������aaapqqit��j5f�����DDD`����
zxx $$2����3`���b��iHHH�B���l����ks`` ���������
dgg7��l��
�������[r(Z������o��h�(����������k�k|���b�r�-HM������ t�����8{�����2e
���������w���{���Qh���aaa���@ii)��;g03��]�0v�X<x���&�o��`{��o��{������]'{��U�ooot������j�Z�p����������c�����Frr2rrr���:'N��w�m�plG��GDDDdA!B105�tF�S�EMB��C��l_`'����F����::���������������L�>1� ��C(*:l�OE�Y�'�����\�9�DDDDd��c�MC{��6���������z'�N����(CuuN����1��C��n�
�Z���eee6���������S/^l��?�8/^���`�����[����>�����c�Y<�R����Sq�w`��Q��SXX�������_�8sss1�|�����~���HLL�3�<�_����
�g�6YO����.wss����1i�$�1]�vm�'''��m���kQ\\HJJ��%K��5�;v��m���r9/^�Gy!!!��������~��]���9O��a�������/�}�Y��5}���,_����P��w�}�!!!���?���������_��_�&g&����_�U?;��a����/c��1�@�$I8x� ,X`���?��)S��:�P�;{��1.^���zk�m>W���w��5Xr��<��|�I���?k���G}�_v��	,X�_|���u�������<�W����c
���#Gdr�f�BMM
�f���1C�:/I��������Wee%�.]���z
/��`��!x��W1z�h���vf���7�����������i�&�f���c�3f`���<xp���$I8}�46m��>�Z���'�`�����������/���:����_�m�6�����T8����nt����1e��F!��/b�����������X�h.\��\�G}O=�z���__QQ�M�6�����Z�\�t	�W���u���wRRR�����#��s�a��qa���2|��X�l��w7..O?�4�{�=����y��+--��_m�l����g��5��?���=�L&C��}1~�x<��F��)���������u��B��'O��08W�A���"�����O?E�^����o���o���P-�������$sw��O��.]/WA�r��P�B��6�J��V�EJJ
bbb���KG"�J���			sPRo�OY�i$�z��7���DDDD���k$���l8^���""""""""�(\\������������J����Y5d2%�J8:��5
J��+���$I3��Znn�M����3���R	A�2v�#G���>��A���~�Y�f5��M�6a��Ax����3��k��	�={v���y{{��G���������h;w�Drr2z���h�[n��������5o�<�Y����������s�a���3f�>����b�����2�]���|�y��������O������o@��������c������a��s�N��\&���o���{�p�B����jC/��R����A������i�1��~�����>�HZ�#F��_������jNN~��L�:�U��N.]2���w��f=go��6�=�o;88`��F=z���~��C�����/���/1s�L�y��f�]��1c>��3������7����LDFFb��}�B����z����w/����?�}��wHLL�N�������g�5��M�Tb��prr2������;\h�=���{#F�h�����~��a�������0y�d}}k��5������}@� �x��

m�����9���,�>}:�m��Rit��������C=�'N�=3���T*����
}���`��E08�o��������
5
f��i�[�j�-[f�=��������'b��18{�,`��Mx���1`��F�X�<�����+�M�����;��x?u��!�N���D$&&�����C=�7�x������smwww8p��v�~������c��I��������B�#"""���	]q%������f_���3� ���"�u��
�F�aNCj�Z�spp�qu�!�����8������).������_�M���X@DDDD�R�G� ����R��A�X����������J(�7�
\I���� ���CAt}Q�THHH�w6���g��k��������~�mH��o?���F{���?qqq3j�#&&������������@��-x���,���L��L			��~�AUUU��/�09azz��{WW�&gl���w�UVV��]���4�#����[o����8r�`���X�j�t�bvm�������42�����e��`����~�������j����k��iv����������i�~�������a��[��x�A�B�����Q���^�za��y�:�Z-��=��={b���&M0g��]�iiijg��r����������#-z���������+�����T����Y�F?��t�M���/!����������k������;����������&��_�5��9�o?��#X�|y����o�All����~��FAH�z�������x��7�����V��Y��`��M�����{��f_��f
��������=ooo������������\����|�
4
����O<����c��)Vy\�y�DDDD�'��
���;T���@WZer=�� 

�����U*RRR�X��
w����=L�)��+�$�t:�
+#"""����sH����������32�D�	2�{DdRqq1���;}����V�2k�5k����:t��}��a������3���:��^$���s4��O?��k�\|�����������^�.//������.S�l��g���k��-V�^z��&�Ku�������'�U��v����/��!!!X�p�Y��^�� �r��!����=���K����3f�_�~��3(Y�dI�AmoY��\G9�
C��<�\�r_}���-���y��6{�o(((�������^�vS�1o����{ggg����f���o_����;��j���y�N{<����c����c��!x��',�Oll,^|�E�������Dyy9jjj�����{���g������6�O�����QQQ�����233��+&L����4��_��}����'���_|�����{���>���(**���C{DDDDd28L��G'A}2���&�6A@xxx���WUU!55�������n��c7�}�^����C����������u\\���i�1\]���n�1������������?��*�J��4i��!/__�fg�i+aaa���s0&44T�}Su�������v�j����G��r�3g��h�q��'~���6�������m��fV_///����r�r��A��������������z����Y����(�h�3f���O�>mA0m�4������A;;;������?�=����/�N�0Vo��if�����W}�^c
�o�q�M^wi�����������1��y��R�T��������>���&gb�o���8q�������/c��			���
���q�-����_GFFF���'N4;cbyy������;��������������x����zl�������Z@pT@�0q�B������$���u"2�pss3����iii���;G���)�L����-��_��'Q'��;��b�}��|}�Xe�DDDDDDDDDD��������-����������w��<��}����NNN�����������`�k����k���3f ::���P*�F����?��������
�<���_�h�KH����]�������-����������F�
8��������~����%Y������c�Z���q��G�1k����&��2��A����0�fv@�������w�h��0..K�.���///(�F��J��`��^�[�a������������`�5���C�	Z2F��d�������J��a��Y�<������?���������hV_OOO|��7��7nDNN����.��aC����z���g�}�`�|`V������XFFN�<���4���j�����qVHDDD�"z�B��&5��z��2h��C�o��:�L���H���������g��EDD����oo��C0 v+N�����t��r�
Q���=��quDDDD����!'�+�t��70�L�D`�4��S�����������������a�n8cRs��d���<������O
f$�Dqq1�����rVV.\��;w��F�Mf�����W#99@��6�<��.]�Q�Fa�������0x�`��7����k�������w7S�����d�����
mL5%++����_?������A��Y�������f��?+�%���=<gm����~�
O<�N�:e�8�Y3v��y�vKo���5���`�X7�=�����X�2v.��y��z������_��� ��?�����:�L&�G}�}��������}�v<��SF�quum��O�>>|�Yc��?�V���o���BVVBBBZ�:#���(++����e������~%Ibh�����C}�+��.��a4��!tq����;�ir�QQQHNN6��gQQ.\��=z�������k/���'�gA�5>�yV�{��.
]`�������=P*}t._�Z���`XB]8
J����#"""""""""���0��p���X�����=z4.]�d�v
�Tmw�9c���p����j������
v����'"--�`��{�b����R�n�S�N�}���7/,,lq�������g�{�������d2xyyY�������5��"�i��o�s��po{���������X[���0�fip�R�8��:�X�<�=���x���
��_����������x����o����������Q��/00={����g���?����k`��]X�`�\���'��rq8Qg#}����<�
���/B�2gW�y(
DEE!))���E��������{_����	s��U�s��?!�]���lWGDDDD��R������zu?��S[�W�(����{DDDDDDDDD��R�Dll���?w�����p�\]]��gO��W�R����u���5���=M�������"""0j�(DFF"((...prr2�^���_��={,���
1q��F!�~��a������'���GGG�:-Zd��O���8y�$�z�-l��999���T*8p�s�=�Gy�W���[��[c�(�N�����G��K_���eeefm�P(,�:����7
���r�t�M6lBBB���GG�F���������?��P��-�%m}lo��]��k�,[�|9�~�i��1n�8��^��dC�B��z��h���H��^~~�E�wv���m�6��7O?5wg������ZG��PF������#j-��Yp��(�}���R�D�������Zm�O^^�r9�w�n����K����wO=I2hLO_����]��quDDDD���&��"
EE�P]���'�8:��s\\��X!�� v�!������=ww��~F��j�����h���
��n��	�������?�l���o���m?��c��j���W�4�m��a����nki����K�.��%K����c��}8p��=���*��555x��w�g������fpj8v������o[TOCNN��^g�����Z��4~}�B6�~-Z�� �7i�$l��	��ukr;k��Z_������F3N�w
�%O=�&M���}�����p[���
6����7X�p�B�Z����4������&�FGG7Zf���
��;�*�bh�O���x����j
�z�Onnnpssc�������:B�����F�K���$]��oo`E������Brr��F
���@.��k��6��~��G�O��p����$��%9e	D�~~�pNDDDD��K8\\��R��<���P�������/�L	����pu��Ry}�S���������������/_��x�U�.]�m_?���/������w���n0k�k��YTWk|��������?78���u�d2�9#G���+�V�q��q��������p��9}���4��;?����>�K��[n��E�t4����%a�����S���t(**������7|=�d[������o����~�-�����///�v~~>BCCm6~[hx.����M�%mql/>��S<����|�A����v��a���$@m�����`�HK�����������1���E�A�����I��R�y��a���0`�XQ����|��0�a�6�B'���m\Y�������(������=++�(��;��5?�������������_|���lZ�/J�����~N*IjH�� B�	Y������������/&nF;s���c���N�2��N���c�����X�{���dv�����6��~��f��������&u(
�p�
����r�J���{x��'������OHII1�'  NNN�������V�9��h&���*�gljF��.$$����vbb"F�m�������G�G�1h?��Cf���?���Y��}����f�����������l�%�����o���>h0�=���?��n�7���5h���6������_����<�����7h{{�hK��]@{PXX����A�����$l��c��e`�����"��������+�w��5����z����E.\���pA��;��%��%I�S���(��UQ{&d2��d2������������;�8���!C��h{s�B�������f����������d��;��p�9
/L����~����kZJ<��c����
�:t���P(p��7�����8z�h��S��:�c{pww7h[@�6�l�n���o�E�7��pD�j�k��?��9��9���^g�kJ�������=��O?�����Z�V�l��I��m[��+[jx��w��d�)S��O�8a�XZ�			�,�}%�����Q�I�T��~0�NDDDDu�El0�41��$�&>�Jc|=��.]� ""��>���Cqq�m
j'�u{={<kr�N�B���(-5��yDDDDDDDDDDDDDDD�����������~��#F�V��?���kfm���ov �a������7n�hv_pq1��ve��7��e��������F}n��v��;��c�z�gK��=4��->>���


�E`�^F�e���m�A��)EEE������|��mVu.-}mV�T��y�Ec��2n�8��]��O?�����ooAAA�����}��y���Ov��/�����������
~6��������3�j4l���`��q�������2h���Cii�Y�����(//�����0h� 3�%��=��+W�������3�GDDD-&(�p����Z
ub6$]��#UG������:I�������2Ve!!� 4�q����r�'�Cyy�
�""""""""""""""��.44�j:+
���Ze���.]�\�]]]�+V���/�`vp���� �p����?			������fo`�6w��;v�0{��hN08}�����K}�����?�`�z����L���Vh����������^BUU�5J�.�z����322��������e��N#G�DTTT��H�CK_��-[f���@��!����9s���������:����m������z
%%%v��/��������<y���b�����s'�X�v�Z�;w�`���S��&<<��r��]YY����7;�N��+��b�l��iE�����=@��Kl�t�M�,����:��3��]M��V@s��?�e����]�>�N���TTTT��*�{���1�^�)F|�TV��!QS
�����b_Qm��O���B�w��
6�?��O��|��G�����CE6L��r�J���;wS�N�Z�6{�vV5WWW}��_~AQQ�Y�#((H�>v�����&������Y�,��������_TT��x������=������p�}�a����w��	�{��M�����_PP�X4��;� �����k�>�q�-�����W��~>��#�j�(�X�p���%K���_~ir���77
�.Z������c���M�65
"5����������c�mj���x����T*���~�
3g��J�2k�����= �����tL�0�/_6{j�[�n��u�L�a��`[�_���p���L��~����Hk���{����o`�����L�b��w���j���?���6K�,��#G�mA���y�C���5LS���YP����B�k���t]�v5��!�V����Nu'-A�+�Et�:�d���������j��8'""""""""""""""j���3bbb�,`�P(gg�6�_Gp�
7�����-I�������.^�h�733,��?�V8{�l����?�g�y����

�~�z<������f�#��0n�8}�������u��c����3�j�kX���������'��s��%��������QTTGGG���?����G�w��X�b����Y��TUUa���6l���������!C�����>��'��eee���;1m�4����hp���qqqX�f

���7;����j������d�l��{��18�.\hr_����c0��N��w��-[�4�-�����5k���I���G[���,\�� p�R�0a�����r��A�.��G�C=������fgv"jJ��=q�
7��eee�����}��F��&&&��{����>
I�m�X�G�6x��u�VL�6
�7o�O?�d������7��w�������oGLL�n�j4D~��%|��G3f�bv��ZDQ�7�|��?��}����+���nt���<|���x��G��s�"%%�h_k�m���+���[QXX�_����g�}��o�~����=z���Cll,��Y��'O=�WVVb��]5j-Zd�Z����7�x���6x�`����$j�S�N���+q��U������1c^�u��K�,����y�]:��={�����Su(� @���jHe�F��O]�������zj;��u�V�Enn���j�)))���1�3NG&2DG��V[������V]F|�l��>6����������������:"ggg������F[�������a�����������P�{��w����",,���(((@FF�~777l���  ��y������CBB�~������7�DDD�t����Bddd@����{���������4���O?��;w�/VOOO��%K����?F��o?��3�����K�.jjj�t�R,_����pqq���W���ip1����/��?�Aff��u������^�K/�Q��[7xyy�������p�B������y�f����d����p��w�g��$	�}����;(�J���������(..��K���9f�����W���@����fTZ�bV�\i����k������������7O>�$z��Qq��%���7��Y�f�C���(�����0f�dgg��nj��5X�v-���������hh���x���l\5uD���?1z�h�k��+Wp�=������d�t����������?��h�8~~~����f�:[���PHH����'�x.\��o��_v��y��;�("$$���P�T�r�J�T{����w�}�>DXTT�?g���   ...(--EAAA��5�������h����
���-�_���$&&"11/���r9�w�888������Fg(vss��]�,
�o��III8~�8���C�V��+���=z�������n�&L��/�l�X���`���EQ?���g�\u�(�b` 7��K��:>�����r�  $$>>��g555HMM5�GNG%"bz����h�}*+3��0ju���""""""""""""""��M�P ""���pss�h[777DFF"""��=����g�<�`�$I�p��;f�sww���;-�AE�P`�����0X��������G����s�������+��b��5j�~��=�^^^��s'���
�k4$%%!..���e2�x�
��?�����j����B||<�=����F�����_���������p��J���t=z������2����{�cxyy��o���������BBB���_7�e������8y��A`o�����s'_3������o�s���p��y;v�hpi��	8p�<==mT)ud#F���~��w������8q��A`�����=`�Xo������z�x�
l����k�V���WO�:�.{u���c�������g�����G���b�q�������<v�HHH@\\��=k�Z�a��!>>�`�Js���`�������
�k�Z������cF{?�0v��	Q-{@��=�o2o��H�I�������$"""�@d�P�7���T���t�Yw������M~pTUU���Th4Vf_2�����.]���S^�����C�)�aeDDDDDDDDDDDDDD��yzz"&&���C`` <<<],�"<<<�~��!&&��3�����?���u���kW�}DQ�������h0;�����q��1<��ptt4�o�����{7��_��d�RO>�$RRR�|�r�;���pvv6k��'0k�,����������#x���-�-..������f����/��2������^.�c���HKK��?lV�.44?�0���c���7�|3RSS����b������d��y��m�����8�~��&��[oa��=����q��W�n�p��1|��G���1�O6;v���?�hq���)s��������o��dGGG<���HJJj�y
�
����?��3|�A���������c�=�������G� xC]�t�}���_~����-��z�����8���c�����C��EQ�
7���^z	���39��-������SOa���f�:::���o��]���X4�^}]�t��?�����?�����~r���r:�����
�|�������F����}�vL�6��UYGRR����o�9s��7��TZZ������c������+""j;��y���7�^��0����Bgy��tHMMEii��>nnn���n�:Z�FS����(-M4����p���1D���D�2��5���=�k0���5�����:LDd?|
&���:-�F��g�,������J��N�N�L�L������t8t��������R���p�9>>ms�Jyy9~��7�;w%%%prrB���1|�p��m���k���_������2��� ,,#F�h�Y��Z-RRRp��Y������@��(AAA���EXXX���$	IIIHJJBAA����T*������0��������z����������������������sv 3dgg�������Cii)<==��k�6�����\��V�����������W�\�J�B�.]�#F4���=�$				�Y���'���7���s]��TVV���#�x�"
QUUWWW��� 22���f�����y�����AJJ
222p��e���A�V����������l��%��?���8\�t	555���F�n�0r��t���P�/�9r$}�Ql��	� ���Cll,����]u��~�J*��j|�2M��<� �����L&Cdd$���QQQa�OYY�����W�N���]�3N���iF���3O�_�� �Yv�!"""""""""""""""s�Q�����2�7�|s������+&L�`���///�y��V��(�����Ah�A��8��s�=�.���������������#����Vqvv���c�t��:v���?���o��{����Y��<���c3��������!I�^���o��wYDDD�A�E���L�$�&>R����uR�("**
NNN&�������nF
E��n��S��>���������]aDDDDDDDDDDDDDDDDDDDDD�	���Q(��c����C�$\�|�����	�}�v�����D"""��	r(�2�x�MmpO��ma��B�@tt4�J��>�������T�=�����@�}��@J��$���'�w��B���~��'��GAAA����={�������	���9����o������:#�p�"&�������+�I�������DGG#))	j��Y��� ����{wWg?���0�S�8955F�\��r�/BLQ���������������������:���8~�8>��B�YU*++QYY��}�bf"""��'t���^�ft�6�2'�A�6��srtt���Z��>999E���'L�������������s���rW�����O2{������>|8���I� IAh�/"""����]!x8�\�>�]i�
+��������[���l�����*�su�Dl�'E�}23�EV�6������������������������bh����������
�Ng����������>A��a@� ��������6>��=777DFF6y��.�����U���{���!d2��>�������lXQ�$�w��O?����z�QP�J%"##777(
{�JDDD����"6�������O]�b`g��DDD ==�d�s��AEt���v�����0����N=
IR��������w��8""""""""""""""""""""�v���?-[�L�}]X�O�>X�|9���8::��4"""��DoWH����]��/���U�{��������=z��������$	�����������������yg�,�3�CBJ������������2{���������$A�}��8y�$�O���Y���������y�^-�aE��������u:RSSQQQa�����o"��_5�^��8}f!
��aUDDDDDDDDDDDDDDDDDD����+!I�����:.�����������'�@.�D�DDDd� @����>����U���*���+���L��j�HMMEUU�
�������+b����T�S�Eq�qVEDDDDDDDDDDDDDDDDDDDD�>0� 77W�� ���{���j������3"���[4���lHZ�m���u�������j5RRR�R�lX��u�>=��\��U!!��(-;c��������������������������=����������Q'&ss��o7����*h�/��"!!!���1����)))P��6���BB $�����r$$�Ey�YVEDDDDDDDDDDDDDDDDDDDDd_����4h�����""""@��1�t@L{����lX	��=z4z�X_uu5RSS�7��j��b�2�G�.BB�TUe��2"""""""""""""""""""""�ah@dd$����������A�+���������W��"pww7����iii��t6���A@d���dUMN��F�*�v��	C{�
GGG}����v�����db�J������lH5�gV��@&�!22..��eeeHOO�d�=������6�}��/">~6jj
mX��1����	w�}7$I�$I����QSSc��������
8��
��j5�	!I�m��DQDtt4���L�)..����;�s#���'�Mxy�4����<�A�.�aeDDDDDDDDDDDDDDDDDDDDD������-[�R	A���������$""""�<] ��jr�����y6��@.�#::J��d���Bdddt�������.CL�)+OB���C���aeDDDDDDDDDDDDDDDDDDDDD�����z�������/�^�bv��i������1���.&�k�_�6�3���������P(L�������mX�������nn}L�))9��S�@�U��2"""""""""""""""""""""�`h���{���
$I�F���w�����������Q'&}� �9���>u�
�l������E�d���/����6����r7���..&����@�S��2"""""""""""""""""""""������";;0k�,���`��%P�TX�z56l��{��7�|3z��	OO�&gTiNppp[�MDDD�� ��������q���Yp��'9��`K������Frr2t:#�
j�k��Wg?^�)N��UU�F���)�"��zn���������������������c`h�O����`� �$	EEEx��������zA��hZ�"""�|d.J(�w��D���R�
�3��������.WWWDFF"55�$����Q���c���G��������{�R�����r���/�����������������������:NgQ�$I_@m��.��V_DDDD-%��C��gr��J	�Y�6���xxx ""��>���GQQ��*j���a@��P(�L����9��{������������������������C`h����^�WS�Z�EDDD��~����\�I���
VDu�����G��%I���gQZZj�������~
���d���#3�]VEDDDDDDDDDDDDDDDDDDDDd������q�="""�A���pR� 5	�����-����

5�^��!--
�+X�����C�M�����/~b�����������������������������|��������!8��0 5G�:#7PiP��
���d������hp��%���Z-RRR'''Wg?����H<�w�t5F��=�
D�A����:""""""""""""""""""""���������c�����,"�p�<&��9F�KE���]�":���A�� 77��z�F��)�JWg?^^#����8}�1H��h��� ]�����#""""""""""""""""""""j=�� """���w������zmf!���mW�	���������SSS�����jVf�>����?��RBR�"\-���e�	�������s���<�L�W��]Y�
+�:�  <<^^������HII�Fc|���*�2��V�\/I�9��];l�����������������������Z��="""��� ��0 P��;h%�OfARkm[�
����&�TVV"--
Zm�z���ED�L���jp��#()��aUDDDDDDDDDDDDDDDDDDDDD���Q 89@lr�TY��K�$��UQ�L�^�z����d���2�={:�����_p��{��z��	���,�vEuR���A�5w�\{�D�)��;��w/33��m�����{�a��I��������r�J��M�[�r���C�W�����$"jcr{@DDDDmC�q�����<��u���^�
y?WF �"���������*�}���q��9DDDt�d�B��VS���]���">a6
�..�6�������������������}:}�4&O����,{�BDD��Z���4$%%!//eeepuu���7����>}�@&��pm��="""�D����
��R��5�y<�!������G.�#::IIIP�TF�\�v
�4�=A�����h+p��F������7�%�����B""""""""""""""""�������v�\�b�R��:���G����-���O>�x����;vqqq������G���k�'##���-�)##_�5����C���x<<<0k�,,\�-����#Q"}�Apq0�G��
����UQ}����B�0�'??���6���A@T�K���b��J�����A���aeDDDDDDDDDDDDDDdk�$A�)CM�5h4e�$��%�8p� ��V�\i��:���x����.���n�:��^XX^�u|�����w��k���v�������k�����i�������3g������������^��;�ZJ�Ra������>��{�6�j�6l@�>}������[�C������]n�������7>DDDdM�B�b@j�8h��YVkQ�
�a�D������dh4�}�\��\��� Wg?� �w�k�j+QP�?�}����0|/WHDDDDDDDDDDDDDD�R^����](-MDYY4��:��nn1pw����pu��c�DD�����o������������+"""s���Z=��V�q��Q����kW���������CM�_����`��������
�ZgG��C{u������L���������dn�P��u�E����*hR�@�����gggDEE!99:��h��/B.���������L�@��!��C(*:l�OE�Y$$���� ����B""""""""""""""jK����>�K���������0��#+�=t����G��3���Y��-[�e���gdd��4m�4����`�������i�����(//o�~
��9s0~�x2
�B����
�|�
^|�Edee��o�����x��'�����C��������`���n�U0����H�]I%���F�k/^���yw�Vf/������Djj����E�S}�&�J���>�������>eeg��8���@�l\!��Z]���U���e���%�P|���� ��r(�V�����JOO7h�EH������[���B�~��a��!2d����{C�6��o����1~�x��&'''��5�&M�m���c������e�p�������[�S���~��	�Y3Tg�@ QC�����TA*�4�^�|2w'�<z����iii&��?�(������A�����8������).9�S����!�)m\!�TYy*��&�U��������������mTQ�W\\l�vww�O!DD�"���8r�bcc�TZ��G|����4i���xzz����/z�����
���o������J����X�$I�/K�Z��������������tj�� �hl[���D�=L��$	���(--�aU��P�c@�8;�>6����3IOC���0����<'O����^UMN�����o�KD��TWW��9q
��.]�`��aV���=K{u1g��e�w�n��:�=�^FF�U�]O��������@����P�uiT���/�Z-233���$	iii���7\\\l[�98xc@�V�89������zu7RR��w�k�_"""""""""""""���Z]��������~5�$$���a?@��l�}w:��Fzz:rss������p�9���m6Nqq1��9���4���]�t��������6�5���q���?����h4���B@@�
����V������'O"33�����tpvv��������O����x��������������|��???���d��F���p��Q\�|Y�:���V��'����F\\���PRR��}��������c����q��)\�|���������3���a�����8|�0rrrp��5���`������mv�s�����#�|�2A@`` F�����V>��K{<�HJJBvv6JJJ ��������>�U�������S�N�����]���#|}}��������U�W��8|�0��9���b����{��5j<=���Nvv6�?���<���C����s����d]#G��������l;Vs����=K����?�����A��yTWhR�]�+(��l>�d������h4\�d<���j������89u�����+�7���55�F���~QtAd��������������������JK_�f3�5���CZ�K���U���j�x��7���o���������i�����^Chhh������_|�={� 11��0Qxx8.\����7{������Z�
�V�2�����1z�h�e�$���C�����w�^��5=3c��}�h�"<����-��z���x��7��4�OE���w�y'�x�	xyy������W���}��R�������#�<���������F���6Z~���&��X�bV�\iV����nKl[�l��y���O>�s��5�733aaa���9s�e���={��/����F������u�0y�d���;w.�n��ogdd4��l�9�7o������s����e�����8s���>2�C����K�~,M�m����w�A\\\���
���z�SSS�|�r���555��1`�l��7�pC�u������Kq���F�A������;� 88�����]����?�����[������&����q������o��P������l6b���u


�������?���M�sqq����1�|L�0��k�T*^{�5���[�v�Z���(b���X�n]�r0555x����� 99�hA0h� ,[�S�L�h��>�m4�����M7:�N1
���c�_?����!"""�1�����D�=��Z�
+"c�����kW��5
RRRL~��Q99c��O��#bN�6���OVEDDDDDDDDDDDDDD�*(����]V#/o'

�[u����k�0b�,^��h`�
�m����������w�}�k������f�S.\���1x�`�;w���Zj�����������6����Oc���3f����`�!�J�i����{�i6�����x�X�'O�l�EE����t�M������v$??/��2z���c���U[�;w.A��
�]��}�Y�v�m&{����)S����_�ae������!C�����d`�
�9rS�L���QVV���T*���n��o3�3��;0p�@l���h��
�5
�}����U�Va��qF�f@m�m���6l�Y����vo��&L�>�}�Y��=��5s��=3f�x�	h4��hK���>�����k�5�j_�����b��I���2{���>��/7�j���_~���#>>���p��QDEE����2�j�����c����2e
***���5������������rf���C��W����drqq�}�!"""�A���
5e����h'O/�3�������Z�  88�W�^5����)))���7l\����D 6vN�|Zm��>YY� ]����QS�����8���g�M�j����p�������A@HH|||PPP��Q���S�N��_~i�8��������!00������1r�H$&&�����������D@@����R�����+W��9t����c��5;3�C=�(���z�R���2�����&����|L�8���	��u���?�Z-���PTT�_������Gc�������,��[�d	^�u}���
���prrBVVV��v��������i�l]�I=z4���
��d2������W�^m4����0f������L��;w.���[}���988����(((hr�����s�>h������0���4:�j��f�BBB"""�v�Z��=<<�L�s��������rss1m�4$$$@�PX����x��6���������@vvv��6l����Jl���%��E�z�)�����������`������������)..�-�����T���I���q��Y��vAA�L����$���7��]�v��{�EUU��r���������8w��A(r��];v,<GGG����y��JJJ������b��������u�(��.�j~��7�v�^��T���S���X2�1QG$�ePA��s�F�x�VB��G4���;�� �V�5y����j����w����;��zw�>���1��B��2����B���{��6�����������������)/OCq�mf�*.�Cyy\]#m2^{�x�b��� x����x�b��gdd`��ux���QVV��{����J%�N��;���F�2����Bl��/���~����\��?;v�0���{���3�����o�����	������nnn�>}:&M��#F�k�������`��mX�v�~����$,Y��hX���c��m�6}[.�c���x��G��^^~��7�����o7�_�v���3g<����x��g1k�,����?�|�r���PYY����			�f�Y�~�>�7~�x��~��a���&k
o�����_EFF`��ax���1f���;�$����X�`�A�����L���k|�~'`��=������[om�M��J������3���r<��3x��'�_~��y�]�}��~��'�`�|��f����?#//0x�`�^�c��58G�APP��}��5555��5k0c�8;;�=�{�����������K�.�SO=�^x0d�����=z�>h�R��y�f<����0Trr26m��'�|���x=h��0883f����1x��F�3I�p��il��	|��Z-��O>����q�]w5��m����}y����g���m������h-���o��v�s@xx8�/_�)S�4
�^�x�w�����-6��E�p����r<���x�����G����
l��	�?�<�j5���KX�z5��[�������F����{���3������/���e����qqqx�����{���5���6`��:u
:��5�������q��wc���P*�v����������6X6q�D;Us}�<W�@����_w�O�r�M�D�������N&� ���'����)�Nee%��������P�.����&$&��$�����
������m\Q���i�R��m�K9���x�!$x�M���T@&����G��|�o��O?��f�j�7,,�6m��A�����g�3��	0{��fg�������>�{�������v�����d�����6��r4
:������k��yX�fM�3�������31f�}@��?��+���et����>����39���?�O�������7�h����_������a��a���F��L&��7���{�b���x��w��:^z��F��A������c���<��;}�Q��uA��������"66VP����?���S��j�����K���������������G�m�����~{��=z���~��C�����/���/1s�L�y��f�]��1c>��3������7����LDFFb��}�B����z����w/�����}��wHLL�N�������g�5��M�Tb��prr2������;\h�=���{#F�h��7A��_?l��w�u&O���o���FC{]�v������oDhhh�u�w��,^��`�����m�6�!��������C=�'N�=3���T*����
H���`��E08�o��������
5
f��i�[�j�-[A�wss����1q�D�3g��l��	?�0�hk��-!!�����r����w��������3f��mqV��+�������;����]��#"""��Dw�z�B{�x0/PtC��2��lG&��W�^HII1�����2���#222�������M���m�>�$Ik�OJ��E��M�quDDDDDDDDDDDDDD��J�����w6���
99���h#n8'�nv���o�
I�����h`�����#..�`F-s���X������9�����o������E����p�)!!!����!���*|��&g"LOO������L�
5������J�c��kW����&��ud2�z�-?~G�l���V�B�.]���<x0>���&CF���X�l,X�_��O?�:��ZZ��Qps��5F{���?'O���M�����_ovh�
�n�����
*
|��W��f�����������jq��Y���[�n5h�9s�`���HKKP;���+W���y�j��p���=����c���x��W���f*��V��Y���n��&|���f_�g��g�����h����w��p���q��	������g����y�,_���Z�����7� 66V�^�~}� $`����"77��s�y��YP�G��o�a���_���I��<W��y�?d��&�G��J�mX#�"������������3���3������h|��Z:$%=���6�����������������~�����w������X�j�Y��Y��*M/""C���>l�1[b��qa����?{�L&k�/����v����r��f{uDQ���?�o��dM[�l�$I��-[�Xu<{x����.����{�'O��VIf��{7.^��o���`���fm�z�j���:�����^�t)����/��3f�_�~���2eJ�eK�,i6l"B�m���-+���(��a����+W�������e26o�l������7�����k�n�5���������W_}������k8��c���7���y����/����<y26n����#??555(++�����m�6L�4��L����?�v�Z��fM����9s��s<d�<��v�����Q'%��G�"���H*���d;r�QQQptt4����k�p�B��u
���/�\/Ij�>������*"""""""""""""""����?�R���I�&�����mvv�����=cBCC��7Ug���JKK�k��6���/��1s�L��7n�Ap���~k��:+�v�mf����Bpp��]?,g/4h��=����������������(��B���1c�Y����c���M3k��}������+�:�Q�a��`�s�/��b^�0a"""�6��i��
@ll�A��kLaa!�����;������u�����///7z��u��������K��s�N,X�7�p|}}�P(������p<����������"((�`��K�"11�N���J��]w�e�������>����e�i�ub�����LeB�5�!�:W�=rpp@TTT�w��z�*���;]p�[�����9��u:O�GI����0�%�_��G��h{K������w�y<����899A�F_���~���J�z�-33���f�����h���B�T���?��oWPP`r����7h?��X�~=���[\�$I������^�z�����}������[��df4jl�������������%Y��Q��^�;�����g�>r��Y�EEE������4h�Y�����/sJ
�---5���D{?�qqqX�t)&N����pxyyA�P4z]V*��5���Z
����<����__��1�2����1�� ��%�8���)S�,�r�M7���������<,�z�������Ude�5�L������XyK[��Z����i�������m�f�e�MK+���Yd�M�e���ff�Y���y|�s������s��c\'I���:�<�0�;w�I�JQ��g�!..���u��r2o�����]���.��+"k�J%������Uqq1����X�{�����Z�����������tbUDDDDDDDDDDDDDDD����k���cR{ZwI�Eyy9���.DDD���;��[�c�����MMM6���������Cll,{�1�_�(//�F��T�7�tl\������>���PL�>/��"v��m��4� ��=k\>~���`a{������hy<�_��L{|||���L�&//�dy��av�?|�p�e[������}���i���w�����;|����>�������c��_���n����\TVVB�����#�999&�	��������/����u�n��%v�G���j�cX:�8�<�]������_6Y�e��nu�}���~�z�� x���1k�,V�30�GDDDD������p����W9� �������m�?}�4���}A���G0��<��u�j��

�V�ug���v�������1}��z�]���V�;��-�������c���&���V�O�P`���HHH0�g���X�t)&M����L�:���:JJJ������Cu����ugJ���%tJee���L&CPP�]���$��xm��C�%}�;�9��k��r��p��5�<y2�=��9y�h��7�k/G<��:�8�<���q�&W����~����n���X�f���U�Va���.��g��������z��~�V�CVo���?!����v�?>�*�
			HOO�����S� ����X��	����'������k�c4�r����Q���Ri��$QO���	�w�l����@u�!����?
C����Z��s�������,��z����{���h0s�L���������������������� �������m�]�uTEEf��i26l&M����8���^^^P*�&u.Z���0Ill,>��_���
����j���;w��c�=�����?�<|}}��:�{��`��cR����������������
��sQ��c���o3��M.���K.���c���(�Jxzz��{�W8���_�*��)�v%g�K��<���d2L�2_}�����LVd�_|/�����e����GqQE=C{DDDDDt�}����,tq��M���������s���a��A���������(���E�����^_���-�4��p8��5�Kxz��P#�^2�^^�]6@��������u������������y�������e\

��������}�����UWg<���&������v�Z�3��}�
6y{{��'����?�={���_~���;�o�>466���h4x��7�m�6����f�Z�=x�`���v�����W����M�R����6���=dC��h�"������j�^����}�vtg��Z����u����>�<�������;u����6����`w3`�����2Ub���~K�.5Y�p�B�X��E�L��J9��J1Jfr����z5�@1"��vr���@8���V�dee!))	~~~N���A������7��b��1���p$���
E�s$"""""""""""""�e�Bg!/�]��:�is��������r��onk�_|a��a��?��}��=kW]����_+�J���mZ�h�2��&M��I����OC����������n�:�k=2331o�<l�bzs���I�p���w����3�-u$��SC{����v����Io��8u���,������o�������GPP��rii)����6Wh}.	w���+���M���Z��E����O?��L��u�]x���\TQ���B{�������\6� ����]6?Q{*�Fd�+/���PR}n9��}�\Y�N�S�NY�.I233����J���\H&��EC�����PU������LI�#�?�\�{�""""""""""""""gS��?U�>W@��T	��]��;vS�N�y��G��4�`0�������d�{���f������GQQ�q�����9��������.�C�P`���?~<�/_�w�},��`l�����HJJ2�///cg���<h�Z�P@o�T*M�m�"����)**�����TL�2���SSS��G�{��5Y���{l
��;��Y[f?<hS�Vwc��V�G��y��9s���r���y��7�|���������7������<��������k�.��-I������[8i����!2��u�g �{A����;�^�����-n��������!Cl�eO �J�R�����#����"��}H�!DQiqu^T���:���^T�}����=�dy��]f�T�b�5���t������YYY(,,�y�L&3Yny�y{JJJL������~sH�A����?����k��w��mVP(�8q"~��'������K.���k:_����������L�KJJl�~�2l���7��{��_~�+���/����#:������=�9�L�4	�W�6.o��<��]��Z������#�z�nv��m�<`�Ub���[q�m�A���]}��X�v���
u�^��J���DDDD����2HJ��x�����qbE��~��!<<��v�N���t4559�*���UH��T�V�TU��������g""""""""""""""G	����Y�#4t6��m�*�M�0��[�����g���oii)�l�b�����j4�����;��<||Lo:���`�����^'N4Y.//7s�UW�,��������l�s�
�;������_yy�[V\e���&�k��5	�����6l0Yw���vYm��t��Y�V��?�k���C�M����5�[�n��'����"""0t�P�rNN�n����.��<�]���999&��M���j,��k�����|�M�:���g_�u�=A\���������]b_@f�g���|Hz�s#�A@dd$BBB���h4������=�B���O��muLE��_I�[CDDDDDDDDDDDDDD��0�ixz�:����H��!��Np����������O����O>i�5}��1	2��������#G���,�����oXX��r�.8�l��7n�y��hN4s�=�   ���~�z|�������|��)���UF�i���W_���3�<���FG��-L�>�������\���[6���SO���&M���D�7�&jKG_��z�)�.}���9$44s��1.�}��0��5��/6Y~���Q]]��j.��<�����������.����.�����1k�,�s��q��i�&(�JV�������:���uG���������b'VDm111fhh���	6�%������������1��[���$�{�Q����������������P(����r�.=�\������Pt�������MN������������>�|`��(b�������b�Z���}���q���B���<��UM�R���gTVV��odd$"""����_~��>������s�����o��]�l_YYi�|�5�l���?{�1���`�����M�6�U��C�p�-��9f��!�������s�]s��y�L����7��c����/7�
��W_�����l��T�(b���&��q����m������m-Z���Q�1a�����W#;;��}��Y�W^y���Z����g{,]�������~�
s���Z��i���< w����<YYY�1c���l>�V��'�|��+WZ������u~Y�p�]�Kyy9f����G���_�bEW��aiii����P[[k\�����[���|E�!oH������eub�������]�,�o�����@���!33��/�


���@RRDQtr���T�������9�h�-�).^Q������1���������������T���9�����n9�xz�"9�#�T	]P]�0~�x�}�����%I�_��W����/���cO�:��+Wb��5���h����q���g�qy���(++��%Kb\_^^�O>��>�,���!
���L����d�6m���]UU������������1?j�(�n=w�q����,�<y>� �����

�z�j���+P��P*���������n�:$%%���n�UW]��������d\cc#������'�D^^�q����1z�h��^�d	~��7l��P[[�����]wz�!L�8�$P4������������7������f`q�����u�q���������Q�F���2��^1���.� ������a�`0��k�������n�
����'V�\i�8999.��,\�_}����P���1c/^��z�����'O����+�����4����[p���:�v�9���0~�x����_�.��R�������M:������^0~�'%%!==����L��Ba���'����5�\���p����&N�h�������+�`���u_�5>���z
�g�6�WPP�~��}�v�����\��w�
�!�"����;�xM����C�b������1h� ��JJJp��l��6l@YY���N�s8�<�L�����f���17�x#&N����h�q�O��_|�W_}g��1�v�u��t=n����m	����b�����y����>}:**.\�����%K�����6�����_n�>�]���T*L�<��eu+��0j!U6X��K+��W	����+#Kd2
�������TWW���,$$$��Q��������Oq��m���,�)(�r�
c������������������z	�*c�~���gPRb_���BCg#a�2v��`��U8t�RRR4��|�M���[���A�>}P^^���\�>���x��w0s�L���?>�}�]9r�8��U���k�!>>���@nn.�z�q��K�������<��#��i�18��������;v`��)��G}���QPP�h4x��'�l�2$$$���eee8u��I0����7>��3�C�����g�y�<�DQD���TUU����f�������Z=�L&��u�p�u���I��
6`��
���DTT������*�<�����;��������F�UUUV;*=���X�|�]��j/���l����:@uu5����`���E(--5�s���b�������\U�����u��a��������A��^��/�����'Z9r$�}�]'WM=�+���)S�_���q��7C�R!>>2�()������g�}��#G�<OHH���������l-**����C=��'O���^3������y� �"�����O��j�������%!!6l�_��c����J�9+88aaa���AMM
���;�q8�<�lj��}����;����������V����A�I�&a��u6���K/��O>�i��.���n 33�����z�v�m6��R����6���\""""�0A&�Gr$�a��	��<H�s#�DQDBB���jZ���Fvvv��EJ�J���� �>V��:�6���8�*"""""""""""""��E���!�a��0��}�`��0t�k�Y����m�����/6Y/IN�<�������i�&$%%�<�B����o��`0 33���Cvv�Ix����{�9�?���'��7�0��d��� l��	���&�u:�����~�������dx��Wq����=WKz�yyyHII��}����iT����O?��n�����o�?���T@s� ++���Cjj*���,�ZvX�$((�|��I�Dw�����]SWW���T>|�$�w�e�a��M��ibcc�g���;�����8p�bd����s�YW1���0a��}�����:������C&����@�����#�����_�W\��z_}�U����f�9z��x^=z��[���:u*8`��]yy9�;�}��!==���!B������<�J555����������b1�'���d�������b����=""""���T�cD$ X�.5j�=z�����\.Gbb"�J��1g�����'{����o�{2���1�9/�����������b���1v�DG�
A�!�������8�Q��1[0j����������`���X�r%���-�E7�x#RSSM���*22�C=���	�����?��U�VA�\|�� ==��-�e�]�~���������1����s!���1� ��+����{��#��U������K/a��i���~���������"33����i�\�U�V!33��w�M����h�w�}��m�M/��Rddd������Y�___�d�y���W^����������u��_��m�����1�Q���q��|��2d��q� `�����q#�l�___'VI=��w��_��^z��1J�w�u���:t��;��������p�]w!99AAAv�xx��������Y�����z���������a�����?6m���.�m�E����3�<���l<����9�<�������cs81,,.Dff&V�\�`8��^pu�L&� �$	���8|���K"r���4:��|���6�v��������<u�T�����""�����a]n9t�V�!��@��/��\j�iii�h4V����#22����**v!����$��~�a�9�,����0���5���u�LD�Z|&"r��]}��N���'L�����u��	$I�^_�A���������j��w�FVVJKK������XL�4	���]2G]]~��7dgg���^^^0`������.��+�={���+���P[[���`��	]�eN��#=='N�@aa!jkk4�F"""�������N�#I���������rTUU���������������_�N��]���`��](**B}}=���0l�0�7�jP�.�����}�PRR���"<<���/�����c����^����S��g�C�V#  			�0a�Yw;w I�9b�Jw�|���c���������{������QQQ���F�T*#!!III6��Zr�y��***������<�������("00���1bbcc]]&����C������������>0T7�P\mq�>�2/�!|S�]xzz"))	iii��t�CE�������V�>�1d�k8v��FHHO_Q�BH�+�]Q�$�r����Qd2.���6�u�J���3v�������a�EC�5	�:� N���

��7���2����H�
�R��V��#F��#F���N����e�]���t�y������K.��\r��K�n�={����T�V�hSO��`��9��������{OAA��9����Ch�Nz��vI�����QQ���""""""""""""""""""""����=""""�� ��V~���=�Io�s���� ��1�N�BYY��r����AO[�.I���PUu��UQw��u�L�	���V�K�M��B�$'VE������A����������N��=��>ju����#�w���O'VEDDDDDDDDDDDDDDDDDDDD�
C{DDDD�ab�?���V�
����}�/w���9������vRE�#:�o���?����:I����N������������������������������S��������]�^Ce�+"[#&&��vI�������:'V��>����]��DJ�hl�o�8�$A���Fs:]-�N�rW�L� ��"""�G�	P����l�Ik>@��I����x����O�
�N���O[�n0�������������� 4ht�:�9������S��Q#��Rn\_W��3%�QS����4�t������?����*��9_���'I;[9��)���H��M�:h��C2��1w���p��u:���������\OdHJ|}�^iuLSSR��	����;p����?yy����w���t����yy�b���8th��w8�C!""""""""""""""""""""'��Nrss��=<<\X	Q�%��|p?��
-n7���.���b�������(--��]��"==C��U?O�dr���?T����������
�t5v�����@h�l$Z�"��%�����������"BDDDD�#�a=x��-��L�����  &&}���:F�V#==:������L���.z�����H`����M���j��ev�8DDDDDDDDDDDDDDDDD���/_I���������=""""rA ����������X�B8V�466"##z��y��Q��������"��������[�#"""""""""""""""""""��#"""�.%�2(FD
�������t�+���d2�����������:dff�`08�2���}1"�#���;l��G���V[��9�����������������������#"""�.'���b����z5�@�$'VE�E			����:���'N��u�?�"#�?�(Zn:K�)Af�3;>9C{DDDD�b__��C�n7����T�+"[��r$%%A�TZSYY��'O���^mm����QR�	��;:9C{DDDD�0�����Z���<}E�+"[)
$%%��������2������^^������S�!"""""""""""""""""""����9� P��J�K�GNCj�:�0����'��� ����9s�
�X����e����S�������L��EDDDDDDDDDDDDDDDDDDDD]��=""""r(A!B12�	�ht���A2�[����IIIE�����;�*�8S�����8y>""""""""""""""""""""��[fu��C#�=Z`q�T�]z1C"�\����			�����J�2//r�}��uru�SS����J����;2���2Q	Q�Q��L�y�/����� X	��S1�GDDDDN!F�P�}�Y����g!������~~~���GVV$I�8&''�("((���9�$I��Ms��

98������ B&��k�)�����Jc�����qJ����������������������C{DDDD�4��pj� U5X��=V�W	����+#[b�������:���HLL����+s<��:]����J��������A�u�<���&�?[����+$""""""""""""""""""���=""""rA&���H��d�����|xL����_ �+88z�����K����L<*����9����$\7�p Q��#""""��
(�@{ ���K�hSOC1*�a7
�^���|��
2220x�`x{{;�:����.�Wqn8Py!hc8��2��DDDDDDDDDDDDDDDDDDDd	C{DDDD�tb��0�2�X�n(��>���P'WF����t:���,n��tHOO��!C�T*�\]�E�r�t��.��Ps8�z}�[��z�e��	8s�4jj$""""""""""""""""""�f�#""""���a�j������D)o�}}�\�j����t(--��]���{N��k	�_�!����is�dJ(�0���7�`hr�����	��V9]���y�
�d��B��tT�0HDDDDDDDDDDDDDDDDDDd;�������%A���hj� ��-�����0!2�����A@LL�z=***,�Q��HOO�����P(�\a������^���8�Q��$`0��>��	C#��F�
M0��mSCoh<��t�q��1��[�����:2HDDDDDDDDDDDDDDDDDD���� �	��9��`>@��6%�Be�/��%�^���*�c������CE����Bg!/�]��:�dYd���#�44��ljqL��3g��I ��p��1�p �
C{DDDD�R2��a��M���]�i�.���"�pS2�������@mm��1������Dbb"d���T��?U�>W@��T	����}$"""""""""""""""""�n��=""""r91���`�s�-n�VB��<2�����DQDBB���Q__oqLMM
N�8�A�u��JT���:���^T�}����<��+x>L�p`��p�L���'x.L�p 9�$I���`0h!�) �*�����=""""r�Aa��a8k9��;^���o'WF����HLLDZZ��,�*++�����v������"4tJJ6;l���������6-��
E�����p�Z]���@�B4�Uy������@"�>��2q�d3jjRQ[�����M.������
GX�,�u&"""""""""""""""rg��[d��P�9�u�$	��|xN����c��B�@RR�����h,�)//�\.GTTT�|$zU�����t��==B�0hY���+��555���a\7v*���L��<
��s�A�>�A�����]������� xt�sQwU^�yykPUm���NW����QY�;���E��hDE������������m�rx���f�I@��4i�M����2^���<==�������Ck%1r�����8���S(�������Lg���HN�������sn�@��@���@���\������@��D��Df��u��>���:	���g"""""""""�n���S���1.�y������]WQ/1o�<|��'����\DGG��oSS>��#���Cjj****��t�����~��/������/_�+V�%K��Q���ka���2e��
"�.���Y�7�I��/���PQ��(��\�������8~�8�z��1������wru��R%`���q���.���������R%tAuD��TB����2�y!hs8Pi<���]��e ��]�����d�*��g""""""""""""'���?1k�,�����""���grrrP__8'ND�>}:}|�V���L���������P�T����
��C�B&�u�GBC{DDDD���� �`(���]�2/�a��-��������D����`0X���Q���:O�J����#3���l��q���z3��%j��@�A}.$hO8�B�������@��j�2p��m]�=X�)����b����#"""""""""""r���
\y��(..vu)DD=�$I���������~���G�����%]��855��-����?��[�������>�,�
f��sss�~�zl���w�Fcc�������;w..\���x�?[,]�/�������y��=""""r;� @1$��&H����TJ�T�N�������A�!33��/T'O��\.GPP����<�"C��������UU�m�7 `�"�Cp�TVHD@�y��@r�4��+����p`���V"��]]�;O����#�1v���)u�$I�$
$�A��o�����;1u�����~�i,_��u�P-��&O���;w������+M{111x�����O��T�����<"�0o�<|��'����\DGG�� r{}�>��3<x��]�~�5o��}�Q�t:�c�z=6m��-[���W_���=�Z������o�>�k�����o�����?�<-Z��?������W^����;�������-	���Q��9�,ti��M��������$� ..'N��:���HLL�����<��SQW�������9���c&������
?�a
���3D=�[�
�s�3�;t�p�I��@g��Z���!�VkJ����y�!�'""""""""��I�.C]]&���@�.���6n��<��
�2*U"<=�]X)�{���k|��O�����|}$"���7���v�|���*-Zd�><<���CQQ�I@[�����;$I�����6���j���J%������zdggC���k4,^����x���;�����t�����'�4����y{@1|���,n����+�b�^�������^��'OZ�.I233���___'W�uT�cO�$���04��< �>�:%�.��p����]��&����	��ue8�`����suy���lv�%%�:�]�����������]��'QYyMM�V�j46���1����TF 0p4||�=��z��?�����sssq����
7������������������c��%&��L��U�Va����u���>�]�v�-Z������1cl�/&&w�y'���
�=
�������|�
���"/��5���������Cu�C4��K/���#���tW�Q�#I��zIQ�`��&���}v�����j���!����]HHt:���-n7�����!C�������� ��U�.����$���p��J�IR ���ro��@�gs���p���q��s`^�����C{DDDDDDDDDd�^����_PW�i��MM�(..�J���}�B�P!�����2Y2d��*!"�����0z�h�3�G��������+V���9/^�^o\�5k��_�q_|1�m��n���=���u�/6	�Y3q�D,[�W\q������0w�\\}�����+q������z
��v���:�a233��3���y��{������W���!�>e�b�kJ�nq���L�`���G�O�<���R�D����Z��u����{A�����^����N�CQQ���z����2d�J���#""Wp�p`��m����I�� H�54�:h4������
��e�������^U�~��e;��V����[�����QW��������xz�z"�=���L����\SQ�l�2����0`�C���u+~��w�r�>}�����,�w���>��C<�_���o�W\au��������m�+00�}�
d��WUU�o����{���iI�$�s�=P���k��7�pC{DDDD�]^C�T��u��1jC
��Q���#����#��"�;���R[A�bXh~���h���hR��91�Ra��������QRRbq�V�5���JDDd/��}8�s�i8P	��0�FS��I���lfh����������L��e(,�
��K�������+DD����MMM&��:'�}F���y>����|}����lHHx�<���&�i+�gO`��~����;��;��c\���?v8����oc���___���[��t:Vw���HM�F�9�3��������[K����A���P!�K��C1"
��9�A2��A����1d2�H6�����t�;���V�������C�`������[��$���v*o

�B�	
29A����� 7nk9N&(���Z�;����V�i�� �Lv�����_�� ��""""""""����7����.��g0�QT�-"#����<,2��������3g�@�T"66�&MB�>}�l���*;v�������F�A@@BBB0z�hDEEu�\�QZZ�c��!''UUU��t

BXX������N�q��>|�N�BMM
������X:*����ohh��={PXX���R�����<#G�d��I233�o�>?c��ARR�C��$�OuB~~>������TWW�&N��n��#rrrp��Q���
����3g���m�������;
q��Yc��1HNNnw���l���EEE�����)S����{q��077iii���Guu5�r9����q��u�5�233q��Q�������P*����/���0|��N��^�������c�PUU???0�'OF``�\���������������7~�w�\���`w�V����?������l�����2	�m�����$L�4�$����������c�����^x�����S�:[b����8�Rl)�
��N'�>EM�13�F����������!��i�s�T�]�(�sred/A0p�@��zTUUY������<�(:�@"""7�����A@[���s�3�s������N��Z��<>�k��e�B(�B@�eX�d�>�[>�j���c^�ADDDDDDDD�VV���z�[��GY����t���+�^��^{
�����������n�/�����;4GJJ
���l��
���m��bcc�p�B�{����j;`i�o�+V���+���c�L�2�d�$I��{7���+l�����m�}�Ea��E����!��w���_��^{
��G��DQ��a�p�u����BPP�M���g��y���/P�-`CBBp���c�������z�)S�`��]f�w�������~�i,_���z�u���>��c��?����Ga��y��:u
111��;���1`��mx��'q��A��&%%a����5k�Mu��7�|��q977��{�������M>����\|���x���p��1�cd2���'�x������m���x��7��~����k�Y�gdd`��e��q#4��1F����~���7��c�<����w��6A0k�,����������tw��9ljj����o�������9cu�(��6m�.]j��Z����Z~m��n����/��2>��s�>}��8\q����{1c����S��x�����������f�EQ��7���+Wv(��h������������-��F��SO=���g�u|G�{��;w������			6.����'Njkk�k�.���:�u0����C�����QW�|=��q���t�����="""�Q*4��|�K�
M]r�}6�����0��&���0T7@�o��(��* ���/�����d2
���t��Z��������HLL��������@"0�`�0����E�On5�g��Pa�b���v����IGDA�"Q7T_uum�:��.������u�<����g1c������z=���k���������3X��[oa��6�?y�$.\�5k�`�������k��Z�x1V�Ze��?������|�o��!!!���V�q���b��
6����������L�0�_~y�����1�||��������>�,��}l��	�G�����j<k��I�,Y��_~��1����={6�y�<��SN��v����={6>��8����{�b����1c����6�����j�v�m���o;Z26n��[o������KII�������_����7�?����$	�6m�����s�N$$$t�Nw�n��%�\�C��T�^���m��m�6<���x����Uw��5k����Hm����w�}�����b����B\s�58r���1z�_~�%~��gl��
#F���#����[o����m��$	���^�Y�f���?���O��8�<���/�?�&L�k��'C{��������B���tf���O��?
�{��^w(C{DDD�c4�����.���64aK�z��o�b�w�"��'��P�����@PyB�������dHHH@zz���cZ�����'��~a#""�-\<���-G��}4-�b��!X�C�Rw$IzH���;/w'-|2�������� Z�ph�����E�C�����P~.H�"����6C{�]W�O�n�QQQFyy���PMM
���Z|���v���d~����/����t:����u#:~�8&M����T�q�e����@������j�%%%(..6�{�n\v�e8p�@������A���DDD������(--EYY�]����b����-���Ghh(�z=���PYYi�v��L�2?��#.����$��q�����/"##������<����e�0d��p�
�.����\L�2���&�e2������2����l��u+�N������u`j��y�L{��7�>}���m��g��|����pJ�111���1{��Z-����#G� >>/���I�ADEEA&�!;;�$�u���p�
8r�
�]��s����ks�~��J���z����u�z�������?��#OE�<���x��7�������H���	g����5����*\~�����0����@xx8���p��	������={6���������7o��[n��,������������������t&�]v�e��k�J���;�<������,<���[�o}����o��,4���KKK��#��}�Q\t�E]R[w��Q7!I��zIQ�<xAQ+{���}�w0��}�����^����}Q�QP�~���$hS��1!�Bt~�d�\���D?~��]�*++q��I8��?"""�0k�@I��^�
���SmzS�k�@�:2H�&I�A���,�[���;i������n��
/����hK����d���������S����T���.��T�����N��]-^��$�%|�A,^���������X�r%��Y���Z<��v�����k���\s
&O�lr��***���_��g�EQQ��`������7Z<�������x��G��������;��Z����-������7�����&L@xx�����B�]�/��"���iiix���-�5�;p���]k\���X�x1���~DEE��/))�o�����7��9�`0`��9&���}�b��%�;w.���L����X�l~��@CCn��V9r��K��U��!��z�
�fg��������_������g�}S�N5v��$	�v�����7������w��=��]��O��m�L���/������i����t���[M{r��>�(,X�~��������_�|`\w��!��o�_|as�?��JJJ_|1��y\v�e&����{a�s���F�A�~���/���n���7���}������{�WCC�x�	<���x��'�G�����/L�2��|M�Z���~�Gy��:~�8V�^mW���]����H�t�M�9s&.��b��i%I������W�������C}�f��e�
��+��������/c��m�mk��Ehh��Z����x�
�s@ll,�-[���g��XO�>���������-���'!�����x���1p�@����z�^�K�.�V��������+�<vZZ�Y`o��Ix���0m�4�0^mm-���<��S��������G����k���<�D�����`�����>^g���`���&�f��i�1z�!�={�e��uY}�	C{DDn�BS���t���Q�)5��)S"�#}=���� ��.�����r�]��w�h)�>q>I����`r8�KEr$��-�i�4�=
��(����B���D������Zyy9DQDtt4?�DDD��\�9�<�n���{�
���QO"IZ��ZW��d-|��~��:�����d� �������m�-�ZGC�M�>*�����9���������$t�Z��_]}����"0�b��y�\����������qY|����;w������^��F��}��g��g�3f��;�h�[^�>}������[p�Wh�6m����-v������,�k�f������^h��}x���0g�L�:��z������O#((��~�������ou���P�x����������`0X���/c�����c�b��M�s�L��'b���X�p!�z�-���g�y�,t2j�(�s���������>��Z:OL�2���+�������B|������k;5��IAA�������9{��7�o�>����6n������l�������c��1���������K��3�]w�Mu���t�MX�n�����q��<��S�����_~��$X4?���O����1l�0cpl��
HMM��`��7��u���u~�������7xyy�|���?��q�=w|�}�]L�0��{�um��
�;�������f�2����/Z������-�d0q�DDGG�YWK������M��x��X�v-<==-�3`��s�=���{p��!�;S�<y������o-�|||�h�"������?��c<��sV;�t:��3�$��b�
<��S����������3gb���8q�`�������0b��}y��JKKM����o���C����Y�=��I���`\s��MO6n�h�5�f��6�4�d��������3��c��&6���)G��!��?F��E�w���
����N�'�z?C{nD����]���
����,�|`�&�������#--�x'��JJJ �����QO��p����������]�R%!&f$CsW4�AI��p�K�d�6�o�X�B2Xzlm����uf�%I�A�w��C�\�o�����gTT�t]I$b���j�OfTX���NGD�����tA����"5��j���W��455���Iu��QQwC��w�������$�����Z��t���b���&�l1d������?Gbb����?�/���]����p�5QQQx����!���F|��V;fee�T�6;����]K


&�Mxx8�l�b5<x�L&������b����?�+V�@@@������/����^�!��}���������7���[�v:��Yz��,���/X��t�������X�z�q��U�l��a�O>����
���+��YK�
�����u��z�8qqqq���O����;���/�h�V������b�9�+w|'M�d��p�W`���x���4w���*/�����l�\r	���K�d���=������v4�������o����8t��������q��1�����oS����|��7HNN6��W�Ze�w��Z���@�=Z�o}��������������?�i������j������N\v�e]V_w���i�7b���;�-���[K����A��-�h&��*4em�\�R��g5e�n�F��`�`(���]�U��b__'WF�T*�������C��[SXX�\���(FDDD�,~~����3!}�t�|��$�1�g�I�s�B��-��s�@����!�h:��������^xl2��6@j��%���$=$I��w&m���&
[wA4{��6����IGC���������/�""""""""SUUU��a�qY�Tb��6���/��O?�Fc�����1c��d�����[�c��iGqq1��:���Zv/��d6�9����������������;OE,]�������?��[n��Kj����?�������g�y����y7�|�Ih�����,�&?��#N�>m\������m��������~�������������$����'�����Zo��&6��q�g�6	���?�n�D��=/���q]JJJ��>��<�s��5�����fG�������W_�e2>���.{�o-"">��Mco��������{��������������.��"\{����-6n��^o\v�y���v~i���]����
����b��9&�n�==����X�h���l��}�j��.���bh���MThJ���4�;w���OGQ�i��}*�^@�$��;��9��30��_nC(.�M]�z��iSOC�����������Abb"����������(�	aE""""{���B^��N�/4t����� � ���<]]J�I��$��������Zx��8������->n�[b���q����{�tB�0�iC�]��v(<Z�?\��>��������e���� 8�b""""""�������������my���3g��w�}���.���1��RRR>_GEGGC{m���sUMM
6o����gwz�-[���r��3����M��Lf�����~shh�������W�v���� DFF"??L�r��k�.��;�����wAAA�����n�:��_�����(������+���n���qC�5Y7�p�M�^t�E&��?w=EOycbbL�y����M�K3f�@||������l
@rr��������
�����|�5� 00����O�n����!%%_|��G�{���&�e��m��4}��eh���j5���z��%___�[�����-������.t�~��W{e'���#"r�Rl>�%������A_��g����9����%=��:I�����������y�A���N���9�Xn���� 9��@�����Q����Hh���B^Z=�)��A��Q����/
���LH�����'OB�^�K�=T���FU���0*U�����A<��H� J�d��nh��J�C�����Z�����VM�-jh��['����I�@�w�]��C�"�g����YwC����%Z�h�V0��c�� 
���'�������,hya>L�2����L����^II	���+���G�Eii)jjj�.Lo���������e�S�N������p��1������������V�]q�&�n��v,_�w�}7:T�$I��g�qy��A�����>>>�������������9���Q!!!��Ruu����Y��\p�e�����i�LB{{��������~�������k��F�e��������Pj�oMM�m�u������}��9���TUU���:]�7�l����~��7���3g:l.fA�����������w�\g��EFF�,��������L�T;����q�4�?^g��;����(�����g�1p�����O���s�v�����=""k�7bK�7]�;Omh�������<(E��1���A2��Z���cZ���&a<��5�Z����+�kJ I/Jq32_%�������H5��/����N��:*  qqq8q���1���E����!*�~Tu|h/*�>��A�� 4w�l�k�;�$C��a�p_[�-[<n�b[
[uH����z8�|0��������@� 
��"�'��k���b��v:"Z���FG��� �?n�������$	z}-d2DQ��c�����\�������K�-����d�|���&��QUU���^^^.\�M�6Y��p[����n�������������;=���x��'0y�d\v�e���Kp���|a}II	��=k\>~�x�_�[���:$�������Yyyy&���
�k�����,��E�ug���������������9�J�����ox���p��Q��i�������q��IDAT��1Y�H������|}�?����K�,��%K�/�K�G�{2�Je�k����|�T�N���`����eA����c��Y6��'�4�����w�}�S5������?�A_��c7������������#It���\���
:�$��;��Nt��u�x��C�
M�JZx���&���a��>���s���!���������^��'OZ�.I��������;r���S:%%�6Gh�lOu����� � < ����s��Z�n�&aB� �=�Lljj@��\z�#<<r��FD�����oC/����H��\�Qu�c�]�������� ��hhm[[
�;$���P��q7?����L�)����T���A���=C.������
GX�,�T	.����I��B��G��w|NN�L������k�u�����~L�>�S������P(�y�f��9���&�l����oxzzb������kq���"44��1+**:\�5����;��A���J�c�L�� ���
�z����!���>����u$�����9\�f
����u��v���u8������\;�\���`O�R�PZZj\����k���;�[�t)��Yc�n��U�?�����o�����~�i���v�����=""�k�Av�c��g��#�'	Q�:Ow����m�9�f�#]�����\��v��1@���%����|P����Z�%F�V���o�������@������<�����<��BDDDDdY���QU�jMI���#	��u�q��y�����<>WMM
��w�cb�v�@���CEV:����q���D����&��]�|h�-�zD]�<'DdY���6�pB�`�iC��� �� @�U
@$�9?����U�P�"��������?VX>��c�� s��IDD�R��;���U������QY�;*+G^�������y#%�J.�ET��.���d+����6�R���3�6_Kr�ko8[Wgz��]��c����3g�4����c���HHH@DD|||���e�%���_��m�����***0s�L����a�0i�$����_�~����R�4�s��E6w�������������w�Aaa���Z��;wb���x���p��������x�bGt�2x
[o���������������
��sQ��c����\.�%�\��c�"**
!!!P*���4}���+�pJ����;����y.���`Ob������~n;(}�����/��[�ly�����c��.������'bh�����T�w�<����:�'I�����\�M�f@�<Dw~��\G��;��<�zt�w��
��rW�L�G���dj�I4)��������"<<:���/������=///'WGDDD��(�HN���jr�����������.;&QG	�A������}����b������v� �Z���cm�][vll���%r	���^o���%�&�����k�(Y���.�V��
��%Z�hh-��r.�� ��Eh��%"":G��Df�
��l�{����:z����0h�>CfA���e�{y�wjh����K?^Wj�ihh�k{:��^�YYY����P|����������?���]uu���?o�i(>>k����1c����`���7�x�	<�����g~��������Ccc��X�F�7�|��m����jv�}���7�x��zZ�5��J�2�W�}m�_z[�����E�L{W_}5V�^��������;����k��������k}.y���q��Ww��muP���`O�����{������������D�kx����t�R�u.��+�>V�phjjj�������a�\w�u:���U�DD.R�)��}���*V���A}�+I�Cg�xk�3���CwZ��\�����O�������N�3�S�����,�}o�B{�4��y�D7���t:��X���j����!C���]�������T	5�s92�K:�yz�"9�#�T	]P��@T��w��$C����������-:Z�vh�[�1X�5
���z8��+��FH�8��� �-|�V�>�����xl1�(�L�0�������.�m�#�����DD�T[���#wu��4%%�PU���!��R%���978o����{�������r��onk�_|a��a��?��}��=kW]����_+�J���mZ�h�2��&M��I����OC����������n�:dgg�fffb��y��e��1ZC$I���_��zz���~���ZOh�TVV"0�����{�%j)++)))���C���o����G��:��d�\ZZ���h���Z�K����r.���`O�:dw��q��OOOo�x����O�`��uw�u^{�5��C�ch���E������~*�EP��u�v�BwD�$rAQ�C.����C.������������]p�������A�j(����?�P��d�>�'�Cw����u��(�bP��+��������V�T�h4��{�[Qo�R%`������JJ6u�8��;�JdEWW�9�D�1��2,h{D��
�����a�-"[vHl���G�����:�.��b<l��a�.��\�)���x��a��u>�yXX��O@D�#��e������Uw����:|+F����=r��}�TF�����s)����^]p�R�0��c�0u�T��?z��M�8`\NNN�9�iii6�����|]�v�����9��������.�C�P`���?~<�/_�w�},���|S��[�"==III�}������e�L����V��!��l�����.�eee�(�[�����S�������2e���������#Zv�{��������������6.<x��.��$&&�d�eX��:r�����M���w����gO��k�7�|���������7�����7�r����\�L]���*����~$���L�e����)�c,�������At�t�M�N
��V��X�a�=�(����o�)#���#�`�j�����v}Nd��C��[u� ����^�Gee��1������@RR�r��CDDD��"C��������UU���: `�"�Cp��|��DO�d��.�S$I:*����u���[��h�#����V;j-��uA����$��$c����t�`�3�v�0��h��P�"�h����:$Zz|�����-�%^N�\�dQ�j+�z��.����U����;�{�h��F`�h;>�8��s����M?�]�v�uRi��]�lWQQ����a		������PXh���Lf�sO����SRbzM�=u���o�j��f7� ������k������$��P(0q�D���O�;�����\rI��t�����=��+���^�SRRbs���a��f��q&������]��_~���xD�����_����9d��IX�z�qy��-x������Z��}����`O6e�������@��Fyyy6��O�:�'N�}}}m~-��u+n��6��z�����k��5�^���5kP[[k�>%%%�;w�������,>��5�^�JD��$�\S��2����r�a:��������r2]�ZC�=&`���#��\6^c�s��E~�����w�r� @14��&H�M�h���0!2��}qUo"��������XS__���L$%%u��I"""��$8x*�����.%%�QSs5��L.�����;~~�:�wj'""�A� ��������n�9����3�|�5��hC�v��Z��h�b������������$H�z����t�I�C������:"�wK����<��0
!��������%QGdf���A7�UkJ����y�!�'���O,T���e:l�*>>�uQ��&L�h4�?�|���8{�,��������[�l�i���������w��y,����,744���3�����M�
���fc���*ch�|�M���|||PWW����Z�RRRl
�����E`�U&O���+W���]�e���tS���Jl���d���^��5R����f�Z�?����:s�6m�r�1��u�V�8q���v��J:t(�;������[1c�Wf�y��R*��>}�����~�+V��o��������N��v��_������S�b������;v�X��i�����/��Su�#����\@+i�6X��{�A�"��h~�:K9������������L��������a��qF]��:�j����G���I��1�w|�*��D� ��	�������uh��c|9�]��L&CBB�?n��Lk��������A��#"""��J�`�I����2�D������j *t���I��E�PI�X�bh�#b����kj�C^�IzzD��\!�u4����p��X�����7
��@�E��B��ZG����=6	#����UGCk��#�>��L�+/��������d�Bg#8xj�����o����X������!�>���_��������_������O��7�lw�'�|���D�>}L�{���N�k7�s����p�����6�f��{�n����e6n�h�<�:�h���{��s�=���*��������������z�����=K����#G�,��W��������g�Acc���r{��OGdd$���4/���[x���������2	;M�4	����*�z8K���g�nw���z��K_{,�C�b������3g�1Xf0p��wc�����z�����;�4.?����0a���]X�m�������6	�����x�����o_�������u��w�;���1k�,�s��q��i�&(���f~���=""����v�Af�IN�V@�t����q?a;Q�C&t���Y���P����yM�F�T�Ej�~��$�"�Q�wuY�������=�gq�T���X����nDE$&&����V��ZUU�������sKDDD�� @���9� � < ������'N�0.GGO���_��!Iz���� ����C��c�
-vD4���������"9�$��uU���N�<l���� ��W$�Dd����UGC9��M]/t4lc[��2�����.�<�Q^�����C{�6D��������`0t���L��~�n�(zu�1�������2v2z���1n�8�~��V�������<�(�;v,���(..��U���c�Y�';;�^{-�Z�~�����J�2�~��gTVV�tqdd$"""PXX8p����K�r�-V���?���kW���~;���>L�<������f���Q������������K4Fn��V�]�����y��K/�dsZ2d�c����;w���)Sl�����O>���|��w���?��������P(�_K_}�|��6�~��x�������DE,\��-2�{���q�Ea��iV�����B"-�Ad�	&�,�^���w������f����+v��:��~�z\s�56��t�R|���P��n����0g��������g��<x���.
��~��x�����������3�~�z�����ch�Z�[�g���x�w�y�<g�_�������q��w�^@EE���n|��7;�i4�}�����0��4i����6�IKK�UW]���Z����dl��*�p4����\@��� X����q:��\6
���k�j'^�N��(�{ �|��]���9�h����`���0 �>�������~����_�31���!���Z�n(��>���`'WF��P(������4�FZ����\.Gtt4�{DDDDDDDDDN&"DQ��EL�L��s�"+-[-v>l�#�����si�C�C������s��I��5�ha0�?Vlq�Vuu�����E��R����-����@�]-w;l�!�����muK��t�k��2QU}�)sUU�G]]&T���G�O�����EE�vI�=Q�A�~7���zW��f���������K��������o/^���:u
+W���5�A���h����q����l(++��%Kb\_^^�O>��>�,���!
��L��2���M3v������q�p�]w!11>>>&�G�e����;����d����x��Mn\RPP���W��W^�Z��R�DXX�M�����u��!))	7�t���*>���&�����O>�$��.�|z���=z��c/Y�����l�����u�]����=�&N�hijj���G��O?��o�������������u�V����_�����F�����IW���X������8Jpp0���z|��W����\s
^�u�v�m���0����?�r�J|��g��"''�%u�����}���j5f��������Bx�����<y+W�����o�-���k�����S�������?����v�����7����_o��555/�����=))	���_':e����'�|���\s�57	Gyyya���&�<���
,X`\���_����x���0{�l�yAA~��|��g��s'rss]�E�|�
�����j����C�b������1h� ��JJJp��l��6l@YY�I���yt���&��yO�<i�\\\��~����!C����Z���/c���0��#����1}�t�Z������C��h�"�����NE���Km�����O7	����`��%8x�`��Zr�����Oo���(x��P��6�"UA.S����.�Z.��j'���r[�����4�u]~loQ��as ��O��5�pV[f��%�"���G���H�%���t��H�
0�[��eC��Y������<<<��=kw�+))�\.7y������������V� @�h��B��r:�9��3�5�o�������_o��eGC����#�wA��!ED$A�4��5�.��L:6�Z?VX���V���:�)Z!
r�w��PR���=r+��}y��v��.���Q����Tv��`��U8t�RRR4����o����BLL������r��������;����3g�4�����������#�9V�Z��^{
���@EErss�����-]����6����G��M������,<���������C���>�����(((�����'���e����������S&���������l1@zz:�y�<��3E���GPP<<<PUU��'O�]�����?���1e2��[����;w���\o��6l���'������&TUU�����9��w����������+W��8���������:~W{����e�c���j��?,���!�"


PZz���^z)��������Ue��(�X�n�N�j����j��/��_DLL�������9����������W^��)S�����������R��L�����������g�}ffjOHH���������l-**����C=��'O���^3������y� �"�����O��j����kK�%!!6l�_��TVVh�vw�����0����������8qt�3g���+��i��m��m�6��>��#��7���/����_�2�^�s�N�5
���Cxx8���P\\l��K/��q���y���L������m����~���9�l�����`�6�;m�peL
����J)zaf���|��.
�z���z�1d��{TCQ�t�j�Tc������b��8\�;�}�"�Q�`g7g����=R��p�h���sB�y{qr_J�����G���B���~��9�:""""""""""��@T���$��_�
-wD�����.��;���x!�h�C���^�D�8=!��q55G]]�Q�BX�L��'�����
m�W��@`�h������������m�0c��N*�$����f�b����q�FDGG�<�B����q����������j ����{�9��?���g���x��7�h�"�7��&((�6m��3L�:�iiif�e2^y��{����l������g�I����|����P����}�v<��c����
��Bm�Z����v�i�F�AAA���op�M7���UTT��_�n�


��uuuHMM5�e���o����mbcc�g�\{���.�@��nNN��N�3f���_~	___g�J=��	������{�5y]���3�[
���~�#F�=�������Oc������W_E\\/^l�����-�W����Sq���z��8p���wyy�1�m� v�4�+��=��%K �"{�1�k����w@s���W^��?��*���#"r����N
��x��^���������`K��.���-�03�F���k�^DxE"�+��J��� ��Oh%����I:��Ez�Q�WF�"��1�+��,�@��C1"
��9����j4G��1&�����������HOO7��o-??r�!!!N�������������� � ���<]]J�I��B��e��J��sa@�����%Z�hh�[��U���n�-��D��jj�A�$�'Mn��'>>�P��QW����3P�K`0��cd2Oxz�B��J�OO� �������?�������_���EE\��x���mWW9��������|���,�h{��qX�b�O����`���9�~�)v�����TUU������/#F���C��������?�xC`Ap�������������m�����q#~��G������m������w��Gy>>>6�!���j�*<���X�r%����v�u����>}:n��FL�6��9.��Rddd`��u���q��1����������t��Wb���x��G���?Z�:���?��z�(��J���8p}�^{�5�V���b��1x��'0{�l'WI=��w����<��c���_-�Q*�������s�!<�c�B�������m���W_�������Gmm�]A�x7�p�����/�4	���3f��{��+�h�����y�f������{74������1c�`������k��	�8�d�-��i����[�n�x���d�9s&�{�9>�URG��:iii:t�q���c2d�+����;v�0.O�:~~~.��q*4eX_�������<�
�dM�F�9�3���;|�8�$L�f����A���c8Vs5�*����b��H$��B!��{����^�ug����]���>P$�#[wT]]����6� �>}�8�*�����`""w��`""��k0�k�u����$I�$���_����`���
�-w>��
Z��h������HI���u3�/M�\�ru�JW_����L����}��=�C�9EI�CD����N2��{7���PZZ
OOO���b��I��d]]~��7dgg���^^^0`������.��+�={���+���P[[���`��	]r`�^���t�8q����������@rr2bbb:=�$IHKKCZZ���QUUOOO���#&&�F�~���������EEE���GPP�
�q��1�g���|���%%%���A`` �������.X�|9V�Xa\f����S��g�C�V#  			�0a���]]�I�p���������x>	����1t��n�������{��������@cc#T*���������$�Cu�:�T�����{7N�<���z���`����8qb�������w����Q7���/�<������s�{�g`�z���i}�A�OR�������p��H��Ho�w��C����Fa���7���5�PdGG�j]%���*w#��"�	_��]5����� U5B�����S��{C������������,�c���!�"�WQ'A��K���.�S.�EZ-wD4�vh9�x��acS=N�<zz���B�fGC��L�2
6wA��+���`����i>�����=�L&���^�K/��as�T*��1�a��*AAA����v|Q1t�P���#���y����P�|���.�����t�p-�>���n���=� `��1b��K�ooo\v�e]zLg�{���`���B����%������%��u�D�*�{ �������(U�\S���8�S�D�G(B<�������L�!�;��q����X�a��;=�6����8Zs�B�w.��a��c����a�i�T�hq��X_%d���M��(((���8y�����$!++III���uruDDDDDDDDDDD��.�E<���555�����4r����J���k����`�Y���.�mu;��8��y�� 6o���3d2�����������=""���8�$d��;l�8�$����DA}1�\O�$h%-��� �BP8,��#������K�^����4��m�W�����m8�`�\�7
}!
����#"���
h-�*��)y�A�����THH�z=���,n7��������������������������CdO�d��.��$Io��as�O�"HhKG�6��u7lJ���jG���?v6���������������W|����i(j:�}]��[Tab��.?.Qw'<���Y�Do����cp�>�B������kJ��|+�����~���o���%/(�#�=�kq�T����(FD��a7�N���B���z�1��������������������� BE�;�(IRR����?�6���P��IDDDDDD�D2W@D��)E/���2e��S�����@ r'� "^5�����a�a�w"���H����~�g��`G���KXm�!� ju�����eN���R���fu�V�Ezz:�j��""""""""""""��J��';uN?�aN����������ch���
����Yas�-���x��
�����G�.9u=A����!�p[����7����zd�����O���s����A28���O��Y����������+*9� ���Bpp��1�����j�N��������������z���YN�/����v���>}qS�y��I��q�|�pS�y�u#*��M������\�E��/V`{�F|Q�R�@�orP�=� P\�����1�#��5N���� 8p ��ijjBFFt:�+#"""""""""""��H�J@��h��0*U�S�"""""""�f�����i}��U!7 ���]��{�����`Z�k��T!9�B��`�d��o>��	�^�v�_������X[��+~B����*�����(@,���I���gW��H������zG���zdff�`���������������+*�~��y�S�!""""""���.����EyD��@���!�>��b�kJ�6\���)S"�#!����ID;��� ��W4�{E�J{�j#��t����u�i�)H�MA�W,.��e�J�L�|�P�m�i����F��������+�d2$$$��������8���YYY4hd2���������������#8x*BCg��d���
�����;>Y������1��x�$A+i��t9���^ @�K�\��� ��O�9�:}����7�D~�I*�`��(���B�p`�=��/���OUX��?}�����\uQ������4466ZSUU�������|KDDDDDDDDDDDD�0�iTU��ZS�����E��e]~\""""�����c����.�����m#���	A�!����
�D�����p������������o����
�V�
�����_Q��uP�=�<!B������E0T[|�����HJJ�����1����$IN��������������z�"��A.�������HN�
E`���������l��Q7"d���k�o�
�w`��� ������#����`
~*����"V��	2#"O+��
�)y�4:�F]���IIIP(�w�,--�����X�6*UF����]r<O�P��9T��.9���="�nB�$�t��kah�����g(��������Q��%���5	r2������h-N��^�;���I�T�#9���Tj�B�z�����R�DRRD�z����EE����T	;�{�����qBCgc����#""""""r1+mC���h����H4���Aj���I���#B����N�E��+%"W���pq�D�����Ys�R��/�������r�<�`���m������| O�.���vCyt'J��5w�$����Fbb"���a0,�����(�
���������������C���!�!,t6���CU�~��
����<�����#"rC�gQ��44�j���uPgWA�]�������)����J�����	���3���9�S
��`[�}�6����wy��+�>��>0T5�P\mq�>��/�!~N������/���a�sbnn.DQDpp���#"""""""""""��$8x*�����.%%�QSs5����]x�R.����P��
Ch�,v�#""""""r3��}�U�r��Zf���S5��8
^�}0k D�*$��@�S@?��j�q��02j��FR�v���>5h�S�_j6#Y>Q^!�cwc� @1�?4�M��,?����&�A����������#>>YYYV����@E2�JDDDDDDDDDDDD��R%�x�$A������L�Q������;�� "�f��z��q�C�����������������;�U�c|�T���4
�r��F%�"�X�_~�?kAc�8�R�'�eP���V~���M���78�0�RAAA8p����$�������
���������������	��\� ��*���������C{DDn@S\�����P�5aC��k�2�GDF
�����-wcF�_�_e��5�*�~��=�.~?�j�U�)���|<�6��v��	�c��$��UQW���/����dff������$I��t�j���t�� """""""""""""""""""�%��.������kQ��1H��.=���C����p$DE����/A��H�X����X�!��?�d�k�V����C������p��(�+���8��~0�}������*��!������+���C�������v�^���t2^^^��


(//G]]��������DQ���T*���������������������������������=""����e�Z3�hP�9}�$:��D��y���+1&�R��EZm
���6��1�������F!�'	rY���R
����:��u�E��)!�qre��"""���p����u:�1�������"��Z�������AMM
�������~��!00�Q�?{�E�����5�����B
�	��^*\��Ul��STl����{���
@��NH#$�'��}~��������~�'����3�������;_""""""""""""""""""�N ��	����a��x���������:uo*�##�an�|L�N���
���k�����^���?a�4d�IA�|Do@�D%Spm/��tw��(�A@ZZ�������ra���8x�`������f<x�����"""""""""""""""""""����="�Nd^}�c�Y�1�Q�&�HS�CLN*����F!����
�j������k���p6^���2(F����N\��@��;1
+A����l5<����1����k�.�l�6���������������������������:���
W��C�r���.�v�XD�3(ljD�����`�a<Tu�}}�!��_�|�%#�z>�m���Jb�@6$���b����^<����L�v��vc������u����og��GD=�F��IQ�qi�u�s���!�/u���o�I��Q����f�yd��!Mi�
�7�������D����C����^�������n�1�����������������������:{D���p`��u8p�jjj�P(����q��!###�c���b��M(**���BTT��'B�R�u,�9\E���H��GD=�L"� �0�
E��{L[q��t����5k����u����(EL;��c�'�gr@45Jt�.��SB�����L*�b�����};�^o���v�QPP����v�?�?���K�;w.>����eiii(((y_X�x1�-[����6�G��<���;�5�����o��#�`��m����t�7o-Z����*Q�&�"\���Ul�(��C�%��E�����NC��{L�p��n1��`��}���g��U����>���$H%P�J�����H����{{!�B�K;~�6f���{�TUU!66QQMWp$"""""""""""""""""""��K�� �����Zk���<x0^y��&{�u�V������+�r�B��t���.��Y�����b��/����c���!�C=���B�{:vL���}CDtb1��0)f:.�}&DM�^f���?������^�v�}����A��|x�&��V'��� �b�������=j""""""""""""""""""""
?���S�����n�����O�u�Y���X��#G�O�>�J+������;wnH��|>��3}�Q�r�T���t�1C`h���g�y&��_����J�vN`���8V��dx���G)Qb�a.N�g���$U����=����|X��W���m���?i���	M�������lr=um6�
f��C�2����l2�C{��,X���b�V�m�~jjj0g���v����4|��7�����m�������\w�u}���+<��sA����Oc������z"//��oGuu5���+�������l����P[�}�>�T��q��JP��^]�����������($�}4���x1.H�tY�B�r��q���i��O�����(qt��t��8H��M��,�����3�p�s��6�C{�iV�^���z �H�h��V��������G����t�[���w��pTJJ
�.]��{,���?��������j���'��k�����$�2�D�Y�fa��u����yQQ�}��P�@�R
A-��	�D�
�0�~�o���-����p�!�}�77"�b��{&.�}�DN�F|8_��<[6�-�_�|�l�^x��.�a�!hMn��Q����YQ8X,��Z�:�C{�)�v;������o�c��m��***��K/,{��7Bt�-\�S�L��kkk��������z�)��f{��)������>99�L<����CUUU�cQ�&�������"\&�;��7w�x�:T���_��_����Z������$�:L�=�����W���{�����ul5����=BL�\
��4����./\�!zy|�.DQ����b���&����������������*((� ��y��u���N���x����p���^��g��������}=��C�6o
�C=��C'����W���)Q�ub�':�=����������G��-[Z��O?�4����)S0}��f���E�l��;���Gm��������������9��O�������f3>��s�p�
����O���3����h�G�3���Z��Br	iPf��	E����o"
�T���n2��Q�,�n�6���!"�@��k��_�f��~�A��Xeh��&�� �J�{��F���vx�@>$��gF���z��vl�G�����T���Q��{�n��9�����8n����{QVV���N���6YYY�H�{M}qq1��_����n�#""�����'���
��������{�nTWW�j�B��!66��������v%�Q���y3��y��W^i��c������:�~��MCzz:��������a&L�������CEE�������S�5��W_���7�|��A3"���9����3�����a
	}Pf��	y�BS�����#U)HT���1a�i;�[v��s��/�-{�m��^��1i���]�
�4)>�
���W��VCb�@���3�PuV����BDDD@��C�Pt�����������������������g�������
Q�����/���V����	�������]vn��Vdff�i�5k����j���B���9s����O�>m�1���<x0jjj�/Z��U[:�g�}}��fs��EGG��+��������{�<NW�5�n���v�����W)���q�9��z�k��
Xv����W�v�i�����&�����3f��$��3��W���j
�/�\�D-}":d,i�
����h�a������]�P��}x=*���ym\����	6Q���E`|�)�,�zL���HytH�K�G���|Z�v�n�3��_G�
L��ir�{o1|�M���!��}�VVV�C�a��m��m���q��Q�L���GDDDDDDDDDDDDD�QDQ���E�����i7Z��a���������e�?������d����^zz:�~�i|���X�j����+���Yu�y���


:{J�E9�N�?�����j��f{P[[�W^yYYY��������(�������S������|���,|���!������
{�����c��aX�ti��=����s�=���,����a�+a�=�PO<�v��
�����/�������n���NOOGbbb��'M��7�|����cG���_7q����IJJB�>}�'y���}��a���A��z&����Z����������E�2�y�p�������i��E���p�*��P���2�y�������qr��#F`�~8�����G��A�7{j���wl1���������T�$(F���.p6r���po?��~|{�UI�RH��N
��\.TWW�����L��@��A��C��A�RuZ����������������-�[������6�6�a�����H�C�j��k0+!
�t�N�)Q������M�6!66�gDD�}��nl����u*�
�z�Bll,�V+rrr�r���].,X���|���+!�{�-����_X&RRR���BTVV��Y�V��3��/��Y�B�)_|���������������`�B�@ff&t:�F#rrr��4�L�7o\.�������+�U��a�����{��^�dIH�����?�=x����������=�������3�GP��zx�;+�o�qP��^%��Z���ML���.���DG������j8���
$����__d�
��A��IG�&5�*�1oC�e/<������{�����
���1���.q�Tr(F���)h�F*��
��#����%�K
	��V����S	`��`��P^^�.\���~���T�%"""""""""""""j�*k�Ja96�Z�������������r�7hqSZN�������e��a��eAo������R{�����Qzz:���J��1c��
��n���/��������������4hn���������������'�@ff������������]�^�W^y%F��>}���Q555��j��Z�~_����7��X������z
�g��R��/7�Lx���p������E7�|3�M���}��j]
C{�!|>���j�x����?~��{����v���C�_�����p@�R,���(,,�X��N'��s��U�3�Z�8D�"g6}�$I:(�t���\�;j�;�W`��l{��g����
��Uu�����0��'�85C*D J��13pR�d����^�vX����
��(��"Z�������L���%I����9P��z_���r�2:xf,�N��B{�y�^��������L�R��4
$I'����������������v{p_v�.7��wC�v�avB�LF������%;;;�=d��N�	Q�2i�$<����1cF�����j\v�e8���q�g`����u<�.��DGG7;�����w�����������`����c���8����e���l��E���{���a��~��(++�9C���~��}=�����+[���6l@BB��b#""��I�&���t8x��������j]
������/b��
��Z���a	��(rLJJJH� ���a��������v����\������JNNh��;���Z9���A�/��q���T|HE�P��������������{"����Q�9m�,n�wU��M.������7����l*����z#��R���I��23��E�2��N��vWbm�����ul�Y���N3
��O$�M�����[��Ca'��z72�����J`��=��y3������TUU��t��KDDDDDDDDDDDDDj���S7lU`�x_����M��b�����	�����`�Q"��P(����������O*��o��Z����h4��/�l���o����;33�=�\�����{P(�e}�8��XMY�r�?�'�J���oB*��j_6�
�V�
X��SO5�;^VV.\�����k��"�Z��]~~>���~{���8p`X�m�X����!�j5���/������i4��C�����8�Q^^���������4�KW�S��jkK�v;@sil��A�x��;A'����5^���k0��(^���-���[d<m���gv�����u���^Y��4-di:H"�-�����+�c�����JY�l�n�r��/���;j7bg�f�V�c�j(be�T�.-2�
�����G���:�2 5N���f���8r��?�����Jk���������R�L&�Z����T�V������`"����`"���c0Q��q�����Ltb�5b=�>��������e�.7fm���#�a�N�}uu�#��b*DD'2�B���>;�~III���+�����������?~���z�������R���3x�`��3|������w���%KB���j���^�o�r�-=zt��9����p:���\.�9��T���������l6h4�V���`h�����^��bq������{����_j�t�jLkB{���}���������i�6m�_���l���������.� ���!��X'����wo9�7���� $Z��Z�&9�f$b�?��f7�{j��Sp*�0Gx`6�a����.�CDm�u��bd}`�1�S�<�/�E�P��E�+r�
��H��z��/�4�c�<2�aS���cs>6z��V?�j
����}���r�\.u_������$�E�=�f��}�(��x<p����7<0��u�c0Q��c0Q��1���s�8LD�yx&��
;{
]N���Kv��-�w������y����������|>�[����(--�J�BFF&O�������c4�g�<x555p�\���D||<��������������grssa4��x���D�7���m�����mCAAL&|>4
���������,�t�V��f�����Bqq1���!�J���c��Qqu��b���8z�������N��A��u\Q�uE�����i���P[[�=L�4	qqqarss�k�.=zF��������a0��_UU�u������������I'��#F��7''6l���G!���0u�T$''��Qu/]�9������{QXX���Z�d2DGG#--
���o�1�=<x�v�Bee%����R��A�a����Z��vc��u��g�F#"""��wo�r�)a�����[�lAYYjjj`0�������<��L�<9 �������"l������t������������`���
�-\�������G	y����h���6��4%55��2����QK�~�m���/�.6~��7�|�9^��D�f�Je`8�n�w�8D^���L+�c]H,VAo���Y�Fi����V�i�(,X"<(���X�O�I�%<!>�S
e��u�#�����
nx�����e���G�i�-����r��qk��������Hh��x;���
n���c����%Kc��Z5]j.�v�=���a����=��KV���L*���d2YX�l?>(x��������LDDDDDDDDDDDDD=�}�E(u���M�.7�?T�Ww�PXW��z��s��������G��J��={6�z�)����Ucl���~�)V�\��;w6������z���?~�{o����/n��������S�,E��'>��s�Z�
lv��C���;����^
�,����/_���{���ov;�T�a�������M7���������_����o��P��x��������`����&�5u�T�Y����5k�4{��E���C5��P��\��l�2\u�U������y��5�mAA�����+����-�\���w�l��h�A�a��%�9sfP��7o�{�=;??��k�������*�q��������e���s�a��=�n#�Hp�I'��{�
��4��}���x����i��q�������8�|+V������#G��W^��	�����q���b��

�	���3g���^j4<�u����p��~�W_}��~���"4R���O�������:?�������������}WVV�����'�|�#G�4��V���30�|�y��!]��t:��SO����o����.�K�,iU��r���^�o��}��5�� =z4x��{��!�����]Q�emmm������I�&A��5��I���h`����G:�������n�:���+�������M��%/S[�D�����D�)))��w��o_s�5�<yrX��_���7-�����*z5�1�(7����;�%�v�nx����<RL7J���;��Y�
�5F��%�vdg��sl
��P�l�E��(���~�S��r2rt�5
C����AT�2�Dt�D	45�d�"*'�Z-B)P�Sx`�U���y�M)�[|��-�E��5M�O���[�����y�fs�U��z�U�����p�l6�����������l���h��I$(�J�t:DEE!>>1110P��?"""""""""""""��VU���rc���UY
VU6������'N��
�u^�|9����=�1^~�e�5
O=�v���bx*//��z+��������k�`��)x���[�����1o�<L�6
���A��t:1{�l\t�E-���~���X�hQ@���X�V\t�E8�����O?5��*	>��#���?6o����a��y���T������p�g4�������s�ms���R\\��c�����n2���6l��s�=g�uVP��4��t����'.���VW�^�bF�����7y-����q�)�����X�x�bL�>���Ph���o1n�����UW{O>�d\p������
�u���+Wb��i������x�#�^�u�������j6�������}���jf�(..�������6�����>�c������Cz7n���q�m�5���?�l����;��{.�Vk��n��`W?��[�b�c�������K&����Njv�q:����k���e������:+��M����
�Fc�������c�6��G�����7�F# 11O=�T���_�~E�`�O�6Vb���i�o�^xaH}rrrp�����Q�;XV�5��{�I'�9��S���|�"�($��f��E��#Vx[�9l���R��)*�*�qeumI��4di:HSu�hx�#
VO9[�&d;� �un1���D�=���Z$��1@5I���V/k@��[Im��-���9t(D�����y


�\�A"� ##C�
���n7�v;�v;l6G�+��d2�d2�dA�T*��h�V��a�v}� =�LD��LD�yx&"�\<u��N�����)t)�|
�83b
-o����f�~����uk�rA������XTVV�+
�L&�w�y����B���)�z=���`0��xPQQ� ��o�>L�<;w�D|||h��gTT�����2���l�����SO����[�x�5�4�uU�����T*a6�Q^^������_^^���:���'��� !!^��FM��7�.--���S���?���OiLj�=�����~�����HMM�Z�������>���2df����SmR~~>�N��������}��Att4***�~��'L�6
�V�jPU�%����W_}�o{�
�9����f����_�����A3�J���th�������e�]�;v 33O>�d@�A�����4H$����b������b�����cG���uW|;6'%%!:::�V����
�����+��lx��wZ�T��m���^x��r�T���T�����p���4�c�1F���v8�_����^�z��p���C����J�{����w/"""Z��w�}�9s�4�5(
����`0�d2!''' ��w���SO��5k�
R��y�����?����ov����x�������_sy���QQQ��^��B���Y������=���x�����'�b����W_�9uL1P�X�|y���^@ddd���|&�}<Q[���lE1�����-\�����6`��tA��;�V���s�V��F�������_gn-�yF�K�a	��*��U:��Z�'j��k�2�e�M�� E����q8HB
&�NE�ev����1���S�2K1�(dE�B]E��U��s]�hX-U��J('eBP��{W�N������n{�[�\�A�A���av���|���0���X,�X,��EsDQ�����L&�N��N��^��V��L���`t�c0QO�c0Q��1���s�8LD�yx&���u�XO��b������k�
�V���1H�|���[�`A@�K����������_����%K����_��l��7��XJ���w�9��r�)�?���
��/�#�<���WZZ����c����w��U��;w��;��/����q�W49����7�\����.��g���'�W�^
�)..��~�'�|�_�b������{���}�������m�L�����CZZZ�����������������/P����/�8��3..w�u.��2$&&l�~�z<��������]�:w�\����A��g�y���1c���a���3�49����f��S�]�����q����G��i���A���5k���n��r�-8��s�|�����\�2 <�`��~��
�����x<�;wn@`O&���;���7����$����\<���x������n��n��~�i����������c���c�=�SO=5����a������e�]�����$<������������U�Va�����e��p������n�}��;v,�x�	L�:R�@]��w�y��~�?�o�>,]�7�|s���;���ajj*.��B�u�Y3fL��E�(b���X�t)�x�
x�^������3gb��Y
�y�g�_/O?�4V�\�_���"!!���4�~���222�����s�mb=r�~��g|��'�cq0������A&������m����}���[�V,]�.�_�VTT��{K�,iv�{��m��<y2���nL�>= �g6���������v7m���o����Z��o��`Wg2���_,k�r]�j��{�i���[�r��]���z���Ck,^��|�
l6��7�@ZZ.\�h���p���o�����_6j�(\��a�Sg����.,X����g���.��]��V+**
�YYY@
\"� 66��v����_���v���<�T���qg��N��A=(�Au_�l��_^]��]�/���V�K���uy/-��uA�t$*��z*�D���Q��B{v����Q�r��������_������HD�#�:GA)�bd*\�����9=p�(�|l:	��u%���
CAA���Z�����������%�H��j����x�>������b+\<�F���@�\��|:���������������������'����i��W�|�������F/I�������a������ x���q�e�5�6==K�.����q����+���3��W\��5�111����1g���1�@���o�o��F+��v�i� �����_����
�?�x�!���d�}������1m�4@��7���E��h����7�xW]uU��$$$��.�\�g�}>���m�~�i�������q�����6��K$L�4	�V�������_~@���?�p������3***���Dp��a��yx������cA���S�v�Z�1�P-..�?����;�M��R��������/`�����B���+������}����o���N:	�^{��g�}��/���~P�>�������7^?~|��(((����o�������O��U�0l�0p�������;���p����?np}�R��
7��Z��}���{\h�+>����&N����Tn��
�����Y�fa�����=������z���f$�I�&�O�>���x{��	�F�\�?�J���>�{��5�\�k��[�n
�2e^^�J%����FC_Z�w�q����-���>���g�_|q@`o���x���fK��c���8���0m�4:t�t�R\{��9rd�>�y��}���j����8��s��S��`JJJHc�9���\�����_���?�9e���W����>��\x�������w>����3YYY��t0���m>�������#���?��J�L)P�8���~��U�>|�A����c�������/��������5Z�U�V#555��saaaH���c
80���$9�Cb�R��Z�u�<#�������>���Z�>j�����_����Pe��	�Y�8�  M�i���rU`�iY��+zZ��%�����M[�������K����$R��$x�7��Wm�'���
��F�K.�#33���8z�(�fs�}�z=�����R�=�d2DFF��b��w|��X��p�������/�
�z�?��P�OuK""""""""""""��Q�'m�����0��Va����|�-6��Tu��w�^x!�������
�o�����iS@E�`2$�������'�`������-[P��=4NkJZZ�|�M�n���O?m�avv���:���J����~w<�������?��c���c$	��yl��6l���;X�x��j�1c���7�h6d�x7�p��O?����^[y��������������m��a����e�<�L��=�.l��{�����\.���� lv����������������C����{��fC W^y%�|�I���;w��������UW|'O��c�1c,X�G}@]�����������CNp��'���>�D"	����'�|��*m�^z)^z�%���[�nm2���_`��=��u�]�|���$''��/���#���g�y�Ah��`W�n�:<�������~�����7�?�F���������<��3��&(�J����r��s�=6l�M7��u��8���7�'11��r������0lw������|��o_H������ ]G�EDu�Z94Ccu^?$��h��o���v\"dq������,��)B��{qt�z�����-��P
|��V"�����)�g����06r24R]�}E�(��w������q��_p���H{GA��tx��_	oimX��������!C0l�0$%%�`04�rV*��`0 ))	��
��!C:5��A�V����t:c����!C�������v	��|>��f=z�����m�m����l�;�M�����������������F|�����J�j�"��=���r����L�t�I����������M������$I�a�����������z��{�H�R,\����X,�����2��,[��(��-[���u��~8�
@]tQ@{��m�5������8r�������[o�5���=�X@��?�lpmts���^�������/��a�Z���s�m���{�i6@�]3S�����C�d�S���!��<�������?��%	�y�����KNN��������3gN@��c���?���F��O<���8^�bE���~��c������_|q��1v�X�t�M��k,`�X����?���;t�z�!��{�mP@+�F���k�b��%-�cbbp�����k��q�=��=��������%%%A�������W�����PN�%%%%��ry�&��z*�^��8D��D�c����}�h�&B���&�W���GP��������]YG������B-�`T�x\�r-����xEhwE�r�cu�O���ul��6O�w*i� �
I�������>��M�P��h4HMM��A�0f��;�G����c1f�4���-~���H$��z��������Q�0j�(���III���h�/�\.���QXX��{�b�����{7���QQQ���
�DDDDDDDDDDDDDD������t:����>;��W\\\��}�%==����������������U&�	�}�]X��������d����C�?}��������a����`0��3�j���h��������:��5k�W\qE������T�[�vmP}�Ri�c�.��������
h����g�w��������&�M����������_�5 �u��g"33����={vP�`�a���cLUU6m��o�s�9!�h���O���b�4����y��r:��5kV��������7[������z������C�����k��������q�=��4^����0w�}w�s�~G���n�����'��q7�o]}Y��X�"�l0v���;����NHHhP:�_�~m�^�)S���_�/[�jUP�TEQ�/���l���Mn�9�`��%��/��Q�*	�r�����i���_���'�PB3"����	g���Z8s���-�!^�\&�;�(S#��0@�	E���x��L*H�O7�t�P�8����������@v�
�j�cG�F�������S&�j.�T��4����F*}z}po+�bb_��?�Q�R������B�@tt��;�(�f��b��Z��*Qa�Za�ZQVV��Z�z�:�:�.�/���������������z��/���S���������oZ5vYY>��sl���v�Byy9L&S���f��n���
W(


����c�����g*++a2��r���WYY���3fT����K��C����Fddd��)�b@q����#"""�}h�Z������B��F
�5*�����CK����5��m��1�}��������������
6����k�������C����G�]LLL@;===��R��&�)��u]�9��i��������h��l���i�_s����tn�`��1c��6>>>���1��?��1z(cs|�;���O{��*����.�,��T*�G}� �������\��������y���K�!kA��o�ke�[o�/������jq���b��Y2d�z=�F#�o��O?�|�<�V+.\�;v���>�1�]�jFj��rJ�}�_\�R�p�i�����s�
�����A��~��w�����			7n\��O�8����{^^V�^�i���8��o��>�D,��,R	��hG'<���C|yFxk��R%(���PA.�"�!���P�� H�#��TIHP%�5{�����N_p��|���uY�!Q�����G�	��1A�Q@>�7�[
]/Z�p�.�|D��n@�A�V��V�EB������ m�X`6�a�XZ�-T����_:�T*�O��C�V�K%@"""""""""""""�����"���ZR�JR0*++q�]w�����H
����������[o���~`��hlr��^��{���PW���;������SN9��z*N>�d�3&������P]]�o��������?
]��LK�Z������qk>|8�=l����><�l����Z#...��4M��5��+���SW}����t�M��kW����cs[����[xE(����/@��u���]w�����+����sI{���o�_|���-�|��fH���O�#�����wS����p��w���^{-&M��8�z��G{����?�����l��O?��~:�����3g���
��g�a��X�xq���#1�G���_�{��V�@]���~����?����E|�UW5{1�D"��y�������l����:uj��~������^�os�g"
�,ZYt"�c!�"�U8��p����|��*�6Ft���1��cp�BE���FB��� e�������5��c������qW���Y���b�������aPJ��@%��C����Py��}����!K���&��`0`0��w:����Vk�����������D"�V���t:
C�DDDDDDDDDDDDD�#�/��z��P�������SQTTR���W�	�M�6���OoS���*���r|��w8���p����>�V���U�J�&L�y����s��o���c��SW����u��IMM�������!����mr�	�BdcZ�����,���t������������\����~8-��n������sI{�������_X��3�����
zj�R�4�FV�5�����3�4�����a6��z���%K�#T999�R�����A`��	&���>(���O��k�Errr����0�G�^||<n�����5�\�?��III��y��'�%>�`0`��-�u��wc����X,�5k�`��%���{�����\sM��[o����V"j� @��.V
�I� �"<v8�!�Z��a��|pf���]A)��O�}#��0���$	ur����1P7����m��B{^��-^6����:��
�������e��o<|F;|�F�{�B�PC���-��F�T*�T*��a�����w�'�_��|>��f��@��D�*��t:h�ZH����KDDDDDDDDDDDD��$)�4~P����}���d���N2h�����xIJE��{�����_��%�+�4��r����j�����)��� 99Z�j�:���O?�4V�\��Z���
g�uV����a�0y�d���IIIP��P�T����;�������m���������������8�N�^��W���w������=��z}�m��z����>��8����hx|8�Z������������o���d8���1n�8���!>>*�
J�2���3:d����
Fuey.	�y��y��'���O,{��q��������8�����EEE!��?��JW�^�~���~���7�o���*<��}��Wb��A��>}:N;�4���/���e������k��v$���G������{��\����8q"^|�E��9������>�h�t�}����"bccq�����{��/[�p!
q����C�>��~�-n������III���;��x���A�<^y���Iu!�r[]�/�g~-|6O�;j����q���uw�T2(���%j�#�A@��R�}`tWc�iZ��#���n�3��>��V�ch�h���4[�K����k]D[#wj��#�L�A�/��{�H$���_���n��l6�j��U(�n7jjj����h����z}�?�ug2��T���
���H]���&D�:��v����-���~���,]�����vBB�-[���-�}���C�W[<��c��233������Nj�o��&�F�{����s���/���oX�z56n��������K/���+Wb���
.��?������/�4���ju��S�������P�
@��Cw�P�u�w��>�l,]�)))��k������;n�X�]������n�
g�}v�������x�:v%���
.\���[o
�,���
1n�����Q��6��~`��/m���x����9|�p�����v���k@{���!�3s�Lh��]��QW��>�g�q����8������t�F6��������w��Xw�}7��[���������^�o����4���78���j|���!�-%��#�	Z���ML���.����w�Ot�=0 :<p���c]�l�FE���}#!K�0 @��E��qr�iy2Zvc�y;������r���#�|D�c0T?
����K��� �B>2��������.\���A"i�C"�R�r9���Ev�=�_k�8n��f��fCyy9@*��C|�~x�7""""""""""""������;l���#;l����5����!�?>���O?�4����_c��	A����i^m��g����R����������Z;O�D���'c���X�h�n7�l��������������������7o~����}������N;�U��i�r�]{\s�]DEE�C{>�555��3�Q�xJ_��eggc����vVV���+(-W����G��@������O����%�z���sI8��]������o�9`����/<��s������f�{��}!�����u�����vzzzH��o�X����W�R�1e����
N�F���oG~~~���%�\��>�,�7����/��_����"//��oo������?��I�&�������$�''#��!Hzp�o�Y�P
�����e����*��C���P��FT}��
G�.��E����T�a���8��wz)���O}Fw��^���^���50{L�n'�PC��t�s�h�gIHcu'� @�� >>6l���A��w�����j�0���Emm-���q��Al����o��C�PZZ
�����q�������������z�A:5��-o�
Z�����������R�]�v����������#F���{��4��*,,���G����A��v{��[K.�c��	X�x1�����+�@r�
�����'&&T�;|�0�nwX����T��v��M�����t���������;C�_���#
��
��\sMP�=���@]e��m�������A���r�5�����/���������/��"����m
��1"��n����z<l�����u��U0e��j����~���b�=�QN=�T����/�{�����0F������g�n�8*�
�|�	.��<���������_y��X�hQ�.�JD-$)z(R��OI���>j�#�g^-\�]m�p�gu�����uw���Pf��k�*#�+�u1A�tm�k���Y��������}`p��i��]��H������HP&����Q�m�6~� oa5$�H�y�*:1H�Ruwt�\�X,0���X,�Z�a�;�N8�N��%A�V�
���T*y�&""""""""""""j��S��awxP��)-��������^�fM��0�9��Ks�����x��=FvvvH�S���@H.++h�2�?���]Br� ��o�������������4h��-��1i�$���/�*�m��'�|r��tl^����~������vYYY������h�������0u�������o
�G�m96��=lI[�!�'O���K���7�xcH�w�i���C}��C������O?��K.	��}������^�����h�[�V�Zm�7�����r2���G���l7i�$�Z�*��=���X�r��}�����+����z}��bbbPR�w��G�������0...��]C{�eL�:5,o�������g���u���~�F(
$''c��q���_f�����?��O���`���(..���Bdd$
�I�&5����T�����z`jo�^\E8��s�OB|f�;+`�Yww�AeF���|��E�C���*0-�,��>��;���v_�7�O��<�A��"N�������PW�S6�|&Dc��s�)��WAq��-�N\� @�TB�T"&&@�]m6,����p�u\Q��>F.���t:���T�%""""""""""""��f�0+>_��m��	Q8-&��
{��'B�P��r~��TWW#::����������������������\��TA��t�<C5i����Beee�m����C{��K/�[hO������s��Wx��}{P�����.X�,��r
�,Y�o���x�����TSS����:`��)S�>G:1����t:��;��4V[�!��O�L&�����':t�A��,99YYY����������p��gv���;v�5k�����g����i���_4���{����#�}�v��b����������o��v@����kt���8�v�i!�������s0����O@h���~km��������o�}�2����R���>}:�O���c���/lA@"�����(�"�S�������_�	��=���u������i������"�m���N#�bL�$�4�C��v����Ut�
W)~��jVc�~$��C-�@12��r��a'���B(&�� g@�H"��Cs�������b	�R8��n��������L�VC��A��C��A�V�������F+J]��^����������������Y���g�-Z��^z�����w_������� ��
��xZ����#�0\��a~~����gP�~��G�X�"�qZ�~8!**��6�\s
}�Q�F�_|�~��A��p������


���p5jT@���?��Y�Z�����n�������O?���(,,P�Zz���q�m�����;M�<l��R�����s�m��<��J_K;�2$��			�����!&�������W�ns����`�\y����m����'�`0t���;v�-[�`����������o�
kA����7�t�����Ob�������~�{<���y���mNm1}�t�_���~��7p�]w5Y��x��_|�`=A�9Ru#�Le���!��aH^4���Bjo(�D��\��5:a�Z����(}rJ����/�a�^���1������uY���
��8��������b��O|td)VW����G�FS��.�w	K�b��H.�#**
�{���A�0f�>}��E||<4M��k��QQQ���<����7o��}�PXX�������HDDDDDDDDDDDD��E�e�dx"e��m�L�O�g Z�Zp����H��W^�G}�l���zo��V�cH�R�7��.))�3�<�l����w�yp�Cm�������_
��jsRSS���w�s����7f��M����B����^�5k��}MMM��{���
�3�����m����s���o�
i~[�n��9s����Kee%V�^�0o�<���i� �i��P����?o1���[o���_n��tR���zk��{���Au���y��a�;��#�������K�.ENNN�}^�u��?�	y�������,\�J��5���\|��p:��Fw��-���
i�p���K����l�y��8z�h��p��x����u��=���t��e�����?����_6b����O�E�a���HMM�����q���7y���d�W\p��%�\����u^�5w���0kyy9������l���r��=;��aTTf���ns�H�uA.��o$��A�����hb���~Zo(R��$L!�*l[�P��A�<�	���������^3D�E�R�����07y>�E��B�2�^���G����`Jo���
3���W�#:�	��Z���8ddd`��a;v,���TDGGC�P�}\������G�";;��m��m�PTT�F��""""""""""""��f�N��G�C�"<KT����~�S�e=��	p��W���(���/�-���#G�l[PP�n��^{-�O�>A�s�W�.\�;������-TVV��g���1cPXXA0`�����H$�V�F#���%K�`�����_~������+��O<��������?�L�����T����~�S�N�����h�"�_�>�*�1v���/��q�p��a�����c����������Yg��o��f����={6~���F�#��6m���?���Gc��1�����}��~z@{��Y���{�|�r�\�2�9���kv_�-666������9���e��5�q����q�e�a���E}�����v)��zk@���t��3��}�������m���p�u���k�	���3��w^���z�~��a��	���l��)S�|�r�cv���9s������(�4hPHcM�:5�Z���{�g��;����~�)����_5�?x��a����c��!x���
�������i�0v������E*���/����~�zdeea��E���n�_YY���{\w�uHNN��y����F�m��`G)))�������*�2�V����[�li�~����(
<�����.]��.��
X��o�a�����e��N���?��G>�����^�;�|�M��+f�o��6F��={�����{;�d���"DDD�@��B�Uf])g��WA-y�p��.�a(�����Si�uc)@������H(3�j
 �hz���bL�Dd[�b�i+j=�(?�(���BL7�AJml��x�C0h �k��8�J����@DD������b��X�V�|����r��r�����nEQD^^�z=t:�Je��0���������������A:5~;i�?T���Z!���(<���
{�x��g�u�Vl��@�� _z�%����HOOGLL*++��������������s�UW���^��;�c<��3x���������HTUU!??^���o���(..����~<��~;���[p(;;��sO�������:u��}��w��>@QQ�����{��x��1`�h�ZTTT���  ����/���>BAAA����?~�a<����J�HII��0�h4"//�A�A�F�w�y��}J$|���8������DQ��_����J�iii��������hDQQQ�s�+���=�*++��#����h�"<��C!�?��z�)�����X,���Z\u�U������o_H�R�H�L���.��R=I�R|����6m
�U�z������O"==�����D}�F��k��������?���N��?&������.�N�Cff&$	���PVV����j��Ga��QA���/�<�8{��Y_ZZZ���7�t�����s������b��y�J�HKKCLL�N'JJJPQQ��:�����_�����?DXSS�?g���"11Z�&�	����z�q�(lP}�j���K.i�����w��s���?�8�~�����/��wo��������s�1����.���[5����K/a�����={�`��YP�T���/t:�F#rrr}�r���j���BDD�H�R�DC5 �sx����3��<#�%�����m���`]_wGy��.���e�
C|DE.Q`H�H���{>v����Q\gX��g�' ��x�u��#&��D�*aD'�R	�R���u_��l6X,��fX,8���)���G�L�N�#��c=uO�r^��Y��x��j�A�o��������'����\�g�yf����n Z�RZDDV�XR�=�\�+V���N����������}�Q\u�U!=�SN9/��������$::�~�-�<����������{l/�H��������G}�X��z�8|�p@%������|��(��V���w��_|1����l�J��z�������h|������TK�������_`�����,v���`�SO=_}�U�A�MFF���/�w�y��m����Cnn.rss�w��g���>�����-&N��7�|���8�[,��xQQQ����0r����z���q���Z����}��g��_?,X� ����z=�vE��M����1w�\l��9`]eee�`X}� �x.9^8��=��/��J
E����p��4
�}�]\p�9��h�Z�\��^{-�����u����]����n�
O>�d������'@DDD
IT2�� ��$�2
I�G������y�6l��Km��;�����#P��6���}|O�; �6����x!.J�
�t�!Z�x�^���nI�U����!z�[
���^�Z�			���F��1c�`���HIIAddd���<������-[�s�N������V�5�;4u%3b
�fT&~;��%`J��2i�6�2)�D�pkZ~;���d`/���X�~=�,Y�^�z5��T*�\��;wT�Vjj*6o���n�	*����������<�L�/�������~<���8��S����F��F���[����.�T*mtA0c�l����~{Hs��i�z�)L�>Zm��w����<�<�	&5�L&�3�<����k�E|||�}����k��+W��b��)Sp�������9s&������!�t�K��8�l��	���?��=HLL���?��+W�`0t�����l��o�����v� `��qX�b~��G�(����J�]�S�Lir�J���_��wo��S@]%���������#F�@tt4���
]�x������-������f�������s������oo}����M�������SO�B�|Q�T�	&���FNNy��F����`O%�H�������~������N�P��K/��={p�Eu�C��������9�����L�����.��M�������;��"��#:����YYY���={�}���L&~��w{��i����+D�y�n8����9sk�)���)T O��]��O$JV���x�^;Xva�i;�^s����0����I�� ����<B��������g�X`���=T'�H��j���������z�DD������:��DD���a"���c0��!��iy<��jf����.7��l�(��������J%��w�|>�������Fyy9�J%2220y�d����e���?��999����Z�F���1~�x����e�p������kq��a��fh�Z���c���A�Z��z��~:t���0�������HNN��#�����qDQ���{�w�^TVV�h4B�T�`0 ==�FRRR���.����f�=zV����6l���dP��VXX��7���&�	QQQ���W�^���z�/����SPP����%%%p:������0q�Dh4���^�(b����?***�����D<YYY���c���a�9rUUU�����t�����0h���Bx����`OUTT�u������z����8������v���m��C�PSS���N���(2��o��3����}R#"":H�rh��B3��3��g~-��F8�j����}pY�.�������?��H��D��?PuG*�#�04b
l����e���n[Q�=�<dUg4��[\w��>'���D]� P�TP�T���P�G0��
�����\������`6�a6�QRR��.K:�����j����DDDDDDDDDDDDt�:����H"�H0e��f���N���g��n����h������T������n{�C��.�t���.55�K�k����O�.U��%� `���9���w���zjX��Q���*%%�G���j5&M��I�&u�T:C{DDD=�T��fX4��B^���_n-yFx�m��
�p�a^}�
P��C�a����!��G@E�N/D�A*@PJy76����}��W;���6mE�� |�l�-�b���4��@6�{��4��^1u"j�D"�^��^�G�^u�E�����g4a�X �H�:���Buu5������U�;��R�x.$""""""""""""""""""
�����z i������+K�1:�U���Fx�����*0�U`���#�L��wT}�B|�T=YxCm�.�����"3\��v����A���"E��8�C+�M����0=�����}��g������(�X����O���j�W*J�7'�{?C�6C#F#]����F�NT
�������Fdd$~��w�d2��r�����t�nC�z�V+�V+���������N��\.��DDDDDDDDDDDDDDDDDDD'�����N�H%d����T;��3��[g��ZW���p����_��\EZD]%���P�� H;> d?P
��#p���F�{��1��c�y�(�D@?�7��;p�D���tu2F�!���M[Q���C������G�8H������1�x8~I��_��A+�#+b$��A%Uw�#!��x<x<$%%!""�V��_��b���v�uL�����Z������T���F�	{@""""""""""""""""""����=""��,ZYt"�c!�"�U8����m�n�?���@��P��0@��� �<NS�V7������"�������zD"g��T�JC���$r���Pub�i#��c|��F�$�b1�"���a����f-��!S;C#F!J������!��`0`0�(��t���V+DQ�������AT�S(��;�uG���A�,V
]���zAEx*���3�>kB|.��5pf�����B�'���Pf O�A����W��������
��p��"�_Y�'j�27�p��4$��P����v��K�Q�����Ve�ReDaD9�#z����-;�������[��Q&T*T*bc���>�6�
f���s:�aWE��f��f�2�\� �'�J�:.Qw���8
�q���/�Wn���������i�8����8�/���A�~\�/Q�������7vA��}��3�P��.�_7��=���(L�=N����PY%�n7�d��u0)m��(r� �BV�(�eA.Qt�����$�?4w�����g�X��z�:���FMM
jjj��4M@�O�V3LDDDDDDDDDDDDDDDDDD'������Y� @���<A��$�>�R+�y��DG�����j8�W$��2P���,A���^����	[`�?7���A��� ����o�����!3��_��
���F���
�H�~k=5���Wl���C�����S'�0������BTT��Jyv�= �g��Z�K�l6l6���*zJ�����r�O��������������������bh����B"H(�tP$��?9�.�Wb��������m��l8�V���
 ����0@��eF$dq
�������j���������\�\<�]�On������z����.=&�dam�N��<�Ktb�iv������F�A�2����)A��h��h�z��Z�0��� �����^��������/S*�!>�V�����DDDDDDDDDDDDDDDDDDD�
C{DDD�&�D�"YE��))�"�G-p�/��*���jX�+T>�������H�r(3"���������6����
�G�C=0�]�!
i|�~����7�>��j#�G7�;F��|�!��!V����W;R�'��;�T���DDD����r���Y,���q�N'�N'������ @����J%C�DDDDDDDDDDDDDDD��<��Cx���:{DD�x�-�� ����������W��<#���p6At�!�gv��������c.�7�9��u+�~������07�~L�@T�L(����JW9~��	��`p����F�
����	��R	�R��������f�9���+�����d2����j|2�� """""""""""""""""���W�Q��(�"�L�����3�����,4�0T����PS\�&�K��'2�D�� �K�k]D���z	�Q2�F�{?D�Z��l�j\����������L�����H$���1��f����z�a������55���ju@5>�F�j|DDDDDDDDDDDDDDDDDD��0�GDDDJ�I�L7@�n�n����_��#����mg�Q7"(d��L�kC.�k����DL82cF�����o��/�*Z>x�m��l�^�R� +b4�h�A"H��0����d���Ddd$��Jy�#���f�(���n��a��QQQWi��@���B�1�������������������B��u*A.��o$T}#�i���p>.�Wdi4d��\G��=��Ij�����U��z��e����Q�p���M�`tW=F��%E�������PJU�zD��	��Z
�Z���8�����j
��\������`2�`2���
t:�z=t:�Z-$���������������������0�GDDD]�D!�*3
��(��������������3|�bDQ� �;�I���3��-�nt��p$���"1X?�t�Q�(�n�V��=��S�
5�������1
���p="�&�R)"""�_�r�`�X`6�a�X`�Z����:���Buu5����u� @��T�S�T<�Q�ah�����4�R
��h��~|�&8s�p�����:�h�@ty!(�V����^���!��]��SA��D_h��NGou:��j�6mE�e/<�;��<�{���������dU�2D'0�B���hDG���EQ��f��g�7~|j-Qa�Za�ZQVV��d!>�N���u""""""""""""""""""
^�FDDD��D%�z`4��.�wW�P���>�#�������ip�;��
7��po;��~�R��Hy4&���I��q��{L�a�������B{��1���L�`�%�p<$"��A�V��V�EBB�����,<OX��x<0�0��e*�������h4Q�0�GDDD��T���q/���KP�!�
���F��6���@>�aU<�T����04b
l����
������qW�����T����1D?:��M���z�L���HDFF����t:�>����Q�:������@ee%@"�@��T�S*��'"""""""""""""""""��1�GDDD����BP� ��[���1�2
i�ua����,mt���o^d}�]/$��@�v*�e�c���~��j|������v2404b4TI�~<D�s	��J�J���X�����j
���t:�:�����l��l�/S(!>�V���	������������������(C{DDD��	�E��c���H�5�>F�I�c�3��+35���]!B
i\�����	�w�EM�>�N�3���gj"D�� �v��^1����
�Q�$	�z=����O.�+ �g�Z��z�:���Buu5�����4�?�����R��>���������������������u{�}���z7`"�.A�|h
\�\���+T�w�dR?jE����t5	#��k=�����r�=�rW	~�����Gb�~�RM������P(���h�(����A>�-�@q(l6l6����wR�4��N��\.��DDDDDDDDDDDDDDDDDD�u1�GDDD��fD���t�x��:l,��&����J�k].��5����k[!�3 H%A�S&�a�>�uCP�,�n�V��@�T�����?��v=2��14b�|�QhA�F��F�A||<�����,�nwX��z����Emm��J�
�i4H$�S��������������������ah�����=y��>p��},Ez���v��#It*���������������M	i��  I�I��0���k���]p����{EXv��e�U����4u_��<����J�00����\.��f��j�B���p��p���@��Q���C|z�
���7"""""""""""""""""���="""��S{�j��vG�W@��$���zi/|����W6��[T!RY��V�?B�	��0:r�-{���&�1����B;
!�DV�(�
�B�h�\���J�J��������P���p�u\Q��>F.�T���t�J�a�������������������:C{DDD�#�FC=<���:�}W%���=g$*����E�?�Z;�jk��=��B����i�
�Y�0D?��<�6mE��p��M#�U��-5b�~(���!�l�|����H$���1n�; �g�X��z�:���FMM
jjj��4M@�O�V�Q7�+�������<�/�����\�:�c5�_���+C�n���:� ����r���>�m�PN�A����  M�i���vU`�iY��+62n#\��M[���}��04b4z�z3�BD�B.�#**
QQQ�*�9��f��f��}\�������r�T*�V�
�)�:JDDDDDDDDDDDDDDDDD��0�GDDD=�T+G���P��.����?��)������d T�Q�:QG�r(F���1��8�p�8��>a�E+�pJ�8)j2�wa�y;�^K���9(�� Z����O;2	?�Q�j�j������������f�������za2�`2����Je@�O��B"��u\""""""""""""""""""

�d%""�E��E�u�P���v��'�=�|gge@wr+|Q�!��B6�<��6��We��P���:�Z�����f�|k6v����Yt�jw�T�k�b�~8�G@+��u�DDM�J����@DD�������,�V+|>_X�u:�p:����P(�h4���� �R���"""""""""""""""""����8�D-n�w����h�~�#�����\�No��@�yp�X5+���m�g��F�g��w���zon$
�	��o����t��O7e���c��<�A�\����a[�z�������1q������T*�T*��|���0��� ������(�j��j����d��j|:�2�""""""""""""""""""j/������z$�V���"f�(�C)�#3ob.����8�U�}l��Q��.xM��L�����d�������gm���e����KR��H�x�$������!�>|U�V�|�\�A���V�""
�D"�V�Ebb"����#F`��18p RRR�.a:�������"8p[�l���;������2X�V���q��������������)((� ��y��u���N���x����p���^��g��������}=��C�6o
�C=��C'����W���)Q����DDD���FC=0�R+l;+�:b������o#�eP$�����fx����}��H��T}r�C�&�r1�����|����>F������p��<���<>���bB?����V��IQ�1�0������5�����:�QZQ�T�!#1H7Ji�a\"�� �����Hu������b��f{��n��n�����*��@�N��^��N��B���DDDDDDDDDDDDDD^�w����3q�����
�AUU���/����j�B���o���4ibbb:{z!��|8p�v�����J��fh4DGG#++��
�\.��i�������� O����0�(�]^��L����x��F��yY��o>,7����B���5;��	a}D�A�UB>�7�[�bO�8��S���r�'�D�A�a��bG!v�����t����5k����u����(E�|�En����T�B.(xw,"j� P��P�����P����j��b��l��b���
��>�f�f�%%%�B�N�#��oH����������������SUU�3�8��7^""�6�
��
Cnn���W^y%�-[��}���>� ���{�|
�,H�R�}��x��G0l��V���p?��G�������������4h�Z��;����A��<NW���pA�����ID��y�5_<MT����Y�
�Qge@�2�C��4>������7��WRo��>�6'A��NC�:
���1m�A�n�EwP�=���;���)�>1��}���rU ���T����9���b��S�B�v�qm��N�z�z��z��\��j|���/����r����������& ��R�H&"""""""""""�v�z�jL�6��^�hz����Pu���N9��^���&CAY�dI@`/==7�x#
�����222:czD]��y���{���������O�M�z�����A��-^x��y���x<Mn��z���������>��o�9l��}L�~�)n������Z�x������������w��9t��H;:�x
*?����*7����]fC�%!�����tb�e�C���Wiit��@	$jH��<3� �����u2�wc�y�����9
P�(@�,Y��_7r�"�9��bG�&�:�����s��Q�bG!v�nD�2#
�����D:�B���hDGG���i��B|v�=�c����
�����2uw�:������t���u��(�p�D� Br��	������M�6!6��n�MDt"��i^x������g��w��`y�^������G��=n�����[n�%,s�c���p��WB�H�Rdff�`0�l6���Cp��.��r�p�=��b���G	�\�^EEDDD�
��z$�4U������v�#�^���+C���a&�p����Z���H5;p�(�rb?��	�*%J3�AV�(��b�y+�:���������`���
���Q��"������W�����y���"�T^�~�A�=*�:�}#�Z-�Z-�}Ig�Za�X`6�a�X��#Wkx�^���������J�
����h �H�:.�<�N7��vT8\�r����}��B" F)G�J��QJ�<��z�e��a��eAo������R{�����3������>���ja�Z[��u������
X6u�T<��35j���-[p��wb��5�ew�q����N:����}L�������{QQQx���p���C����;,_�w�}w@(����g���O>����kah�������
����or`�Z��v�*�_���9���3$
/A!�|d\r��p���P��A�yw8��k3���D��{��p��>x����9����L[���DV�h$*�����U������x��`�X�����J�1��6����x2���@�i�Ng@5>�����Vm�p8�p8PYY	�.Px|�O��A�P�n�DDDDDDDDDDD8bu`w�eW���|"J�.��]�UcA�J���:���:p�DD]Gvvv@{��!�4"����?�={����1g�<����������}]���3��_@�Pl7f��\��g��?���f�,��F8��O?
���oGEEa��u8p`�mU*.��rL�>�����#uDQ�#�<����Us�jx�s"""�6�D]�	�9���]^T}��_�~a<QG���
Ijr�Xc��`I��;Z�2Sc��������I�H��x)BD�-��~��J>@�e/�b��*W9�+�����cl^�+�U�������1� @�R!66}��AVV���!C� --
111P*�aWE��f������C��};�m������&�)�H""""""""""":18�>�)��/G��
�5����/G�������fHD�u���vDDD�L����w�^<�����/��^������OX�n�����~�A`��B�w�y11Y�v-V�Z��9��1�X�"��p��F{�KJJ�SO=�������k3;+��� ���y�U�h�4��i�a�K����?$Ji��(|d)��vx�T7��[P�AiRd�N���#'b��$�Zb�i+*]MW����U��+���5������p�a������e_���yPI�a�7QS$	�z}�nn�;���b	{���v���555�e�&��Z�f5>""""""""""�������*����3�QjsbFr���0�����s8�[��V��������W_
���F�f������;v�z�o��V@����7������o��<�H�~f�����~Lv��_-����g���s��L&��Sw����Faa!���t%���*3
	7�@����)�5��}w%<v�\1�hU��(|d�z�g�C��7�����^��k��K��� S;e�b�6mE��DW���b�iS��������_1=��v���%r�QQQ���PW)�n���l�������f��fCyy9@*���t:�r����������������v��SQ%\���N������*qfJ,�{���|X�n���QZZ����wx[��?��Y�������d!�@�$�@B�B�@���.�G�-�-���Bo��RH)e��n�a$@���������v�eI�,����<y�s������-��y�l6�����:*�c��
X�lV�^
���T*���2TWW�����Q�
6��hnn��e��~�zh����r63g���a��x�;v��/���M�
�`���1v�X���~p�\�}�X,�`���hnn�$I�����)Sp��2�U$�W��g�}��������C�����u^�,�c�.[�l�������`0��}8��#z����������BCC�*++q�9�����j���V|�����};���PYY�C9��M�q�u����O?ECCA@]]f��������W5���p���X�|9�l��`0Y�Q^^�Q�F��C������z�j|��WhiiA[[l6���0y�dp�y;����������l�2x<�9�sL���=�e�|���hjj������M����sa?�}����>�@{g�������L&���of������^��_��_��7�x�T��?o�������@�9�W�:TVVb���u];�V��\aG�����5H�h�;N�E���Q~�d����@�$���H.X�9�/�&���a9l<e�u��l#0�6a-����X�
)#Y���.����1�1���h�t8�7N@���n|��t^]����Vk:��v��p8 �bA�%""""""""""����
����`��]R�������Q��I���3]�q�����{�ECCC�vI�p�g����-F��[s,^��<��z�-,]���0���cq������.��n����Bgw�q�����������5kV�:�4��G������o����Ww;����������wd�o�[?������{��'�t;N�$L�:����q��W����W�_�`���N���;H&s��P]]��/�7�p�nw�c��5���~��������m����o��W����u�%���O���/N/��/�E]�s��M�0f�������}<�����z?��O������w�������q�)�����.�O>�dzy���Y���}O.�����k���W�a��'������e���#�"9��r�-��Z����z�)���������9sf:0��{�j�*�z��x������:�>}:x�v�aY��}�]�r�-���O��	��SN9��Q__���s��a"��k���^x���NF`�+I�p�q��'?�I�c|W]�;������Q��i��n�����{��������u�t:q�	'���.���s��N&���o����/gJ�$�y������w+�J���C�O�V�X�s� 8���������zj��������a����?O/����F]]�����C4M/O�8������Gc��	X�v- �����S�����r����x����xf����=�g��_&DDDD&ZeT�?�������ih����|�P�+�`�@��������~�m��|�e/-���G�G��2���/
�_7?"�B�$	^������q��b����0ajkk�r������d�����y3�-[�E�a��e��iZZZ�H$������� b��/���>��y�^���
�~8n�����=�=�������������9���~x����o�%K���Y��
p���b��X�n]���]7�p�>�h���=������E]���g����Ws$�I�q���w��cPh��/^��n�
_~�e����(������#��o��7��w��/�}���-�U��p�EA���|a����o��'��7�+W�������
i ��};>�`\r�%y{@{���O?�����y��!��|�d���wp������/��<�?�|���">��c���/f����;p�q������W^y3g���c�`5���#�<g�y&�~��n{@�c�[o����g������i����y��3���o�
����/��N>�dl����sl���z(n�����=���x��g1c�,^��O_�g�}�I�&�����������9N;�4�z���|��y���/�]vb�����W\���\�dI��������8��n������\.���lT��� k������������������������� 
��0
�0'���������^^�!����A�yM\�J�}j��i���h
A��y\U�+�;E�`_�tLqO���&|���JRKcr�R;Qn���~�5��
�����
���b��n|�D������>�.�������'I��+��fk4�
�x����pc�v�t��u�� c��9���/2���Q�F���---��B�P��v�}��>���������:x�^h���;wf�V�X���:
K�.Euuu������N���a����� �L���	���c>��#{��X�hQ��/��������n����Z���hnn���;�Tss3�������#F�����c�������m;v���Y����o��#�������7��{��'��v�Q__�����7g}oo��V����8��3�]j^7n��Y��e�����(b���(//���;��Fo��f�����~>��Os^t�Ex������7����[�������,X��~������f��1c�t:��wUUq���c��%�0a~���dt�z�5jDQ��u�2>o��c�8�,Y�����k��}���������p�\�F���eKF�x��b1<����sW���������K����zTVV"�H`��}~��%������U�������Z$	�]�6#�����SO=��/���������*�>����f�c�����E(��u�2B����*�=�X�������������Ry�����;�h?��G-�E�W�\��<e��>��u|��u���&8���q�]w����������q����7�_|1Dqh�O��Q?r�_	���������_�*�h��*�����V�D�4�
F0�)�s��f�R�����AP��z��S�X�k"+��jQ�X]�C�#�AL�thnUU3B|�H��t^UU���3>����p�\p��p�\�����	���������������-���B���0����r�^� �����
7��������7�����#�<�p8�+����sY�V�v�i�����c�9&�����������/��t��;v���.��/����o��6`�������^���/�[��s�����g���O>�~8jkk��l��O=�~��� �/_��o�9gXc�E�����J/���n��_~9F��5���	~�!^}�U<���y��_,��s���~VUU��o�����a��e����Op����O���b8��s�d���8w�����\��NH��:u*~�����i�����<T}����q#`�����/���gC��O�7M���>�����������SOM��]�~'������p�
�3gN�>]�W����s������������kPWW�^�~�z��7��c�=�^��_��+��3�<������������3f���w��c�=6�����O1|����8����J�PWW����g�u��������e�]���b�n��\w�u��O
8�����_��f�J_�5�L�����~��tj��x���q�5���k�}X__���:�����3��g�i������?�?��O�s������SN�����u�O<1��r�=�����Jo{���PSS���|��?��Y�c�������SO=5+��u�V���������~,�����6l�,�������.�sY4��?����'P��s��m��;��w�}w��^�|yV`�����M7����;.#����3���?�y�ww������~��z(����y�Tq�
7��o��F����9v�n�#G����]����e~M@�����?������o���������%��h�0��_���_��F����������#"""�g�Z'�������DrC0������_����2�]�
��� P��Td�h*�u��G��`\�T��GU���eG�����E��9��� "�AFQ�|����i"�H�|�p�X�����q������:
w���� F[RES"�����O��T���I}�����O�SzY��?��~��1c�����A�����{�5w�\\x��=v������C�}��8����W^y+V���afWg��A��c���kKg_|1����;
>7�t�9���=;�z��Gq�m����<�~]���p�������g�y&�<�L������;��{������^�9s&^y�����(�8��#���o��k������=���_�"+tr�A�������>���y������c��CK���Y�f��>��i���������^�i���G�w��l��-c��)Sz�=�����>�,�l�X���/���N�;n�8<���8��C��� ���g��9���o����{W�������O?�3�x���v{�M�6a���x��w2��@��>g������:uj:8���/b���0g�y&�~����oV�W\q�v{�������!����C=��?<�w�kmS�N��>��O?��rJ�����79C{����`v� q�=zt�uu�l�����y��x���`�Zs�3r�H\z�����K��_��3��
`�Z��/`��yY��N'���z6,�9��'���~����
5M�9�������;����<���n7.��2��7�g����k?�0~��`���Y����`�\y�����	�����`�nnn�X1bD���r�z�|��k���r���K8���2|�A���������������"������3�<������G����7���
ZW)
�~�DDDD��TPy�~p�}����`
�������&(E�2} ��Z��H-�Sx\��U�!i$�:gs�Q5�4�:/Q1	������*�3S�N���)S���������3�P


X�f
���K|���X�f
���DDDDDDDDDDD��0M�U�d�V�E�zW�%�Z�����������������.��2\z��}�k�}��1���������w��7�0?��}���:��{��5
�>�hz9�w�Yl��5��.���N�]UTT���*��X,���������Z����=���(�����B=�����i���1����
UUUeu	z��7�����������r�:�������0c]w�s;v,�|����6�(
�{����Yg���OFHH�u�]������O>�7�����1q������K��8�.�=����:�����N8�������b��^��;����tW;8��#�����
�uu�A����z����79{��w�y�9sfz���9�kW���?�l������_�[o�5g`���������g�sv����z,���{/��Rz��G��F��"���N��O�w��x��������3�x������[������9����s������/��t`���7�x#�.]��82��Q���i�a�u���:@��&�f����H5F�=q4��?��
�m����K���n��V6B�ox���j���S����0A�W��#�P������#��U|����<!"l$I������4�J�;�E"D�����R��������=P�p8�r��v��r�`�Z��KDDDDDDDDDD�RT���M{��WcX��d�3GW������@ �_|1�l��p�w�j�������G*��]'L��C9�~�)���?���v�q�����t����?��W^�sl��E�(f�������_�������_W�$�'?�I��[$��o����>� ����O%�YJ���/�
.����~W\qEz��/����z��7�������3j�(\{������;�������?�~��GX�r%&O����o��������������S{w�������Xw��7��pt�� 8��Sq�=���-^�8��m(*������_��W���?�8g��Bhll�s�=�^E�?�x���>|8����^�=���3�f~���y;V�w�}�������{]������N;-�����_���Ya��z����/���]"/��b��=��st
��5<������^1�������^{
��_p��������p8p�UW���.��v�#"""*2�!�P���]��yyZ�\#��2�='��A]�w���
�����*��K6�j�hI5cCl5�~�w[���;�������������������XY���H���KD�,���1j�(����8�������c��1�����+���h4���&�[�K�,�_|�U�Va��m�4�N#""""""""""����O>A2��g�'�|r�C^UUU=v�)�1c��o/^��(s����G�owWg��U�P���jA������eY�9������;������~X���V^�'�xb��������>��9,W*���~���^���w�����������>����$����n���s�Yg�j�~����,�8��^�����g,o���w�
C�>�����s�����7����;&L����8��^��`��i��cZ[[�p�������-�|�>�5g����H$��>����R�������~����j��w�+��Df������vz����_Sg���.�O�������6��w���;1a������2^���GDDDT�QT_=�]u{�+\$V����T|
����TC4P�ka�0���Z�-o���C������M���@�H�9���Tc�6��@���G������L��#�A��G>�@#�N'�N'jjj��!�d�+t�N�4��:������r��p8��������������J����0k��>�?k�,���K�5wSS�{�9|�����������P(�ubzW�X�x|��p���M���s�a��EX�lZZZ
�z�0����w�	'������������K.�eee�U�i�X�`Azy�}��s�����
����r������x��}�U]]�-���*��:w��c�=�O�w�qx������~�).�����4i�nw���������������3������B��7H��p���x����d��Z�
�@�p�����{l�S]���l�1cF��VWWg,�{�����`��n��K�2��\��8��<X
o���z�������������fKw.��.�]�m�]��X_�.����p�M7�0��(���q��gc��i(++C8��e����/�O�b�TU�����/��o��F��=������JD.����S�����/��w��G��KP~�$�'��e�BD���H.X$s�ib�Po����,��OE��*��4�� a I1�H��#�=k�Cr��|�N�>�\Y�"��dYFYYY��^�4�L&�D��D��2��.�D"�D"���SE8�N�\�t���WD#"""""""""""�]7n�X��1�']�$�FKKn��F��??�#Q_�~�m���^{-^y���������:���p��wb���;���?�-���c�9�{,�<�H��1���;kjjB[[[zy��{|������������L���R1l��9cy���}����X�m����vGUUU��u
y�v�\���Y!
����?��W_�������t��c��Z�~}������/�1�_���u����7��o����u����?��-��?�az���N�����~���re��z��AW]��.�+��b~M��SO��nH/WUU��W_���33����������G��/�'�|26l�����W\�'�|���,&��IDDDTB�"���������F ���fRG����9q4���`�����z�n��sm�U�K�B�1zP�<��JK5�'z�f�@�#��4&�fmsI��0�W��-{l�A"�\A��f��fCee%�0D��t'�p8������0��a��a46�wB�X,�N|.�N����T"""""""""""*�����]�z��������Y��m��>��U��1��p�B��3g���u����(x��W1o�<�^�:c���~o��6�j�����i���s�=555y��������3��
f5h�[~�?}[�>wZ���k��u��"s���~O�g�� l�
����G�W\�G�u>t
��5��W�q_���?�����oN��z��~���r���9��F�����B{����� �����u�=�\V`��I�&�_���M��~�5�|\u�U8��C���bah������A���P�9���U0y�8f�o����; Zx�7
lb���Zh+sn7Z"��6C�g�����*k��	�u'���C������n�����>�dDA,Q�DD�'�"�n7�nwz]*�J��v�3����R)���e���p8���\.l6������D2��v=�I��=�I�R�7o^V`o��	8��c0q�D>N�v�=���{��o��V�j�]����7o^V�`���8���0~�x����n�g}fs���������c���_������>����g�I&�x�����{����n���_�;��3���]��{T�?�����C_����p8���E��\4�����Y�=Y�q��Gb���5j���a��`�Z3�=���Rc���|������%�~,��7f�����=������Nw����t�osJ��5=���������Y�f�j���'��/�c�=�^����2�GDDDD�c�X�����u�
h;����/�	�%���@.��G4H�*`b0s_�M_����z������;'cI����wJ�9!����GP��ok�Z�:v1a"������DH�(��0�W��)�B!��b����<}I�4�����"������vW,C,CSS@���n|.��^Q�8e	g����0��`����}�YmSp�0_����)��"�]C5�X�O������?�5k���kjj��O���N�q�?���}�kO�y����&L����z�W'��5��p8p�-����o����;������g�}���S*����G���[����N��:��)S��?��O�te���h�\.W:P��� ����!���������'���~#F��v�����Y���H$��qr���\r�u����O��c�;���
�<XL�`0����n�
7����<���x��'��^�7gpr������O������V���&M�S���?��O��)����yN9�����|��B(����������������H�j�;N�A���Qq�dXG{�X!Q��e�H�0#��0Q�n�p�x���B��Ta�uv$�vU��Qk�:�H�0��f�&bzA��PG�/����nj�^_Wt�6�6�K�Edx��NA����e�KN��h���#����i�F���T��'���`0�q�1����s8Ev6%"""""""""��n�t���[��f����-���������>��9���g�y&c��_�a���}����Sh�>�l���f�����n��n��(�����QG��n�
�����?����o<���X�n]z����q�E���_�8F�`�i�8���w���fO�5����P�����G���������'}����5k�`��������/��,K����c��winn��Ne���sImmmQ�K
�<8�u
��X��O��\��������������������q0�;�"!"""�D���� ��f����w�Q����Qv�8��-b�D}#�"�G!��:@3�h��[`9li`�y����?�7�;3�6A��]p�.��Ffl3MQ=���+���k�����?�L
mj������������+���l��GD�,��z��z�/�`�&��dF�/�f\����D��/A�t:�v��A>���4
xc�v|��m��������a�e��a�����������8�0�h�����i�z������z����e��'�tR�{�x<����(
;�0v�a������C��k��a����o`����<yrz�a���n��;m����BQ���4��l���x<��.�;w�����Q�Fa��M���K�b��Y�����Y�#��;����^���P����3k��a��y���$]�P��r��;��C��i�2�?���>��`��n�W
]�`�r��j]_�����5
�
@�(�{�h(������'h����jce�;�O���V(SGB�rs��f8u�v(SG���(�8�wN�����������w����A�K��%{{���i ��2�|�n�� L6h���BK�	-���mV��)��M����`vWF"�A��f��fK_��0�b1D"��aD"��7$��i����.��dt�s�\�$�����r���M�T��Uc��g�{CM|p������k�������������
M���'N��k���S�Q�<�/Rlj��<�/u~���P��w�W^y%>��<��S��}�QFXAQq�����?��>��3y���iW]���B_���<O�rSSS��_u��m=�����w�y�O��w�y'�xD�cO����dO�C�:�(<������_W^ye��/������������4~�x����}�o�����_��^�3gn����r����Y��t:�F��6��ys����6m���k��n�;�cy���������M����
������@����8�r���W@�?�;�I#�1T�7	��wW�!*6��c\����Xf4��9 ����}�8��84$�"��*���#��+�q@Dx�2x�2��g^AI7u��`�0_[��"z�_��I�H�9���Tc�6��H��:�<r���DT�(�Cs��
�����/��J`����������9����n��x""""""""""�;�_�BSC[���s��������T�= ��k����
���=������_�W�t
=���7|��^�������z�o1���#�8"#�����5���NJ�����c����Ng���}��K�k�a����
������J�s�1������O=�n���^uC���x��3�}���������L&�����i�=y9��� �r:���o`����0aB�j(����c�����e�����o���s�����=���������>��������^�f�a��9���?�8�������;p�I'��TY��i������O�����.���^����%�7���dl�BDDD4�Y��P}�4XF{���D��K�j(|���P�	5+�@��l�������Iv��9V�V��ZE���	�d/�q{C$�)�����8�b�5�l�7�r\R���s�N�L������Z�8$g��'q#���XY������W���'���?���������7�$��bk�O�@3��LDT`�����a����<y2f���8c��Euu5G��������
6��������+V`�������rEX""""""""""���t�0������u�1�Y��r���2�~����D"��n��W����?�up���"#�����ft��g��%}�u
n���������.]OD����_��/���yvG�p����s������,�������Z����~��iS��Q(x`��s�=���~��_ ��GI���9sP__�^��q#����^�����<#�t�QGa��I����������<�K_O��9�����sNz�0\r�%0�O5�Z�.ip�u�!���o��yp(���K2�x�����!�.���Y����T�;.�Y���?���7�j���6<��#�o�bh����h�\T]�?���v�Hb�CK����D�"�i#[��0���-0�;LPa��)���C*���;����]�[�0���yg���qj���`�����k���q|�)8��H���5�:���w��4$�bU�+|�o6�����?o���^��>l}_?���zU?t��]����v����;v,�N���>S�LA}}=|>%�s��u�P��o������_`���X�v-���
DDDDDDDDDD48����!����I��*o�{����k!Bz�������n�y�����c��zI�0s���rcc#~���w���u�p�i�����F�������������{�o}}=��^^�h�}��n�Y�p!�?��>�x�y�������x���ut�AY��^/n�����a8��s��+����/��g�}v�c��w��������{}�.��"���w�E���q���g|���s���y���zP�$I���^�����o��n����?�����^�=?�����~����v�Gy�����<W��6�=��?��O`�Z��~�!�9�$��^������< w�y�e�k�����s�����c���'�|2�[g�9��yp�b=���'��C=4�����K.�$���T*�K.�����uGuN<��~��7N;����k�dg�yf���"��:�,��}��[Q�{���Vk11�GDDD4H��P����(�g���^��[�`f�qD�"XdX���s���Z�u���VX�pV�E���G������.����(����sN��e�av�<|��<|��j\4��^{>��<y�x�dTY��"Z{>p?��!lKl���|��n~�l�|/���Q���,h}�B_bk|#Bj���/I���xPWW��'������1a������vg|�^(�d�����y3�/_�E�a��e��iZZZ�H$`���������������$����ts�����N^[?��;,���i�����������uk��M�6��+��~�����{=��^������?���������������1c�l��� `�����G��n+�@�z(���n����������]O�Z��^�_����B��m�����g8������a��z}���k�5k�L���n�
�|�IFW�]��8��y��93�����>8��o��F��7/����og�q�y�����D"�������A�3f���n��9���~:n��f<���x���2��
6t{��VYY��Q�0|�[��O<��-����������.��ib��q�.w@���k3��ds���O�S466f���a.��r\z����}��8����V3
=����a��^��8�������gum]�t)�>�l���?�i��<�o�j��5+#����O��3����?�7�x#��m��Y�O�2%+,����c�}���O>�3��m�6<��c�={6>��^���$I��?�	����|��'�o��p�m�a��59�kjj����/\~��>|8.��"�\�2���|������7�__}�U��3_~�e��/��s��������:I������h�����2���������c����D"�v�,��1���N����C��Z�y
$�Ck�T�����0�Z�q�w�Bm�����m|�G��u@�Rm������(�5;�L�-re}c��8��[������hLn���������z��~��t��
�R-����C�4�0��~5���nkf��,�0�il���m"$x�2xe�J��^�^����� 
��A��j��jEEE����8��0"�"��DA�5M3}�]dY�������������,�u%��r���#*���V��=����#XnUz�����/���/��Y���G���3f***����������v����u���/�C=�%K�������{��&L@YYZ[[�q�F�����'?�	�o����W������~�W^y%Z�f
n����c�}�]��5+������_�m[�g��T
��rn��VL�8N�;w���M�2�I��������o��iS��\�r%~��_���$I��#P^^���@ �
6du�q8x����SE<���������~g�&^|�E�����Z�5j|>���m��q����^�;��---����:*�v�m�����t�B��o��_=��V0��_�k������$I��m[F�������������$I��O?���gc��-�;h�u�]��o~�1c����<�;�����z��U�P�����f�J?&666����.\.&L�Q�m�6455��q:������<���TWW��.�x�������Q�r��_}����a������������.�$I5j***�L&�����;w���b�8q"^|�E|�;�I��~�9�����
���D(BKK�n}��<8�y�������U�����A���:������!+T
�?v��7���?��E�2���7o����}\r�%?~<�^/��0��_���Gq�nu��x�
� d[�����u�
�����+����RT^8r����LY3��-�����-�H�����Q�q����N���Bs�-�&$�oV��JK
�������A�Y�A�]r�.90�3��������~���
�`@G@mE@m���dA�G.�W)�����W|�����`DQ������L��4-������=�4
�@�@ ��n���r��9|�#"""""""""��+�*8mT5>���p�����cf���r�x<x���0w�\|������ib��
Y��<^~��>u�S/��2�?�x�]�6��0��������~��_���/���s�1����������{R^^�W^ys���h�����g�E����p�e��o�[���L�ul��9��PW�����?�c��������M7��������D�L&�vI�l����n///�?��O�u�YY��Q�F����8���nN�HK�.������^�����;,�i������0�_���������s������v�T�?�p<�������2�#�H:p�����/������y����[�n��o�����������n�!�1G����������h�"�{��X�hQ�����th;Az|.�����C��7�I�p�M7e������������$�w������"V�;�$�������_�|0c��iX�jU���w�yx��a������bh����h��}6T]q���A���,i�14�����>�"VH�3yJ�Pf(��0��� ��]����rK����	�T��$A�"(5�@8e��u��7xL�DD�|�
A5���GH���_���4SC���65�1X,YA�]�mC�D��dYFYY���tt2M$�A�H$�X,�q5�B�������+�����s�\�X,�������������&�$��a>�u���?��x�����-����H���,�T*++��'����p�}����"IN?�t�s�==zt���@}}=-Z����gx����H$r�;��Cq�w`��9��������7����G}�U�V! ����������_���o������C�<���N|��}�m���x������o��O?E4��"�0~�x|�����~���7vG�e�����UW]����/��R�����Gc��98��3q�q��8��G�U�V������o��e������h�Q���{r��'b�������7�|3����a�p��7�����$I%�r`1b-Z����/���{sX����C9��rN=��"WIC����}L�87�t>����cl6�����W��jkkwk���7�|o���{�9|�����e��p���W^y%�8��������>�����s�����^��@|7n.\�W_}��w>��#�R�_�I��C9s���y����c��W���������q�����gx��7r>����y���W��8��T�;6�
<�.������/^z�%���/�a�X0w�\���7�=��"VZ�Y�3w�h�[�|9��o����e��������o�B!��������g�����""���4M�����[���^�	�w�X������0��O!�`���$8��6��7N)7�4���!���|�
!�������c�YE[�0�����{���LD{�0D��t'�H$�����b�X�r��v��r��t:!��
�|LDT:|&"*->�����>OK���nf0a�������O����%�BKRE���s>�(�����f�X�>�R�J'�0��Ga��5hnn��j���cq�QG���� sD"|���X�n�� �v;F��C=����������`�����p:�3f?�pTWW���u]���+�v�Zl���p@{hd����6m�����������c���hiiA ��j�����1c0e������<�ESS��}444 ����S�N�����^/l���}����
����P[[[��������;��#��8G�M�6a��hllD2�DYY&N���?����e1MK�,���+�s������a�0e����~���'���O?���[����x<�����JL�8�'O�s��X��CUKK>��#l���hN�����GQ��l���*�.]�+V���#���p���a�}��A���o���o�����^Lxf�C�q����0���O0��k�6F�;}e`�8M{�n�2m$�E�rn7�I�_o�2����('Q�8 �
�����!>��`G�/����%�7i$��jDs*�*��	R�9�`y|1j�a�*>xd�<Q�����
���^�J���p8�/WEM�RhkkC[[�����#���f��:e�Y��3M�iB7MH�Y���EG}4�>��~���ra����v�B)//�����~;�$I�o��2B��A���3X�������n������T���>�G�P�z"�O��������=�p8
���X��CUeee��N)6EQ0c���1����C{DDDDC�}J��<��W@kM�����8*/���W� ���
s�hk�rn7�B�7�@[U��h��	eJ9����m��"��C|��|A���-A����0�8T��U|!�f�Sret��u���A��=���bAyy9���M�D,K�"���xG��4�F�F����\/�rF���r
�+A��� ���$""""���g�
!J��WMC��W!�6�w��5��?.A��a���@�nHc�`b0�sw?�V����C�p�2�dQA��
���0h�Heu��u;a6��[Q=��A�f� �%{����Q|(S���>���$H%���A�t:�t:QSS�4
�h�p8��4���j��@ �@ �^g���>��
��Qdwh""""""""""""""""|�#"""bD�����C���p{�qF8���|��<����&��#��x�X*�u���O�`���YD*�5��f?>&�D�0_P�#e&�^�	a-���3������*>xd�JY:�����a�(�,��z��z��;�%��t�/#��4����H$�H$���EN�3����N�DDDDDDDDDDDDDDDD4�1�GDDD4	�����B���������j����5P"��[�"�r	�����d����M�H-����$���4��
�R��V�IDAT-����M�D��g��:��L���0����Y�DH�(e(�}�(�����e��A�^/
L� �f��f����`��h:��D�L6�l��0��o��*�����9�NH;�������<�J�-]#��sD4@m��r��"VG����A�o��[sn7�qh�����WXA�]r�.90����i�&bz�SW�����T?t�E���������
�3����\������m�DQ������N�K�R�F����D"�F����>������6�����9�t���v�f��q�����������������J��="""�!�2��������Hm	��\@�/1�FIH8�!�L�+��A���s���
��i�����A��]p�.��Ffl3M=���v|�r4k
�U��LF���Q�z5SE��m���m�����s��&��^+
��>_���i������b�X����b��bhnnH������(J��%""""""""""""""""���="""�������S�qb_4�gR��`����j+$�&O#���}r��|;�
��!!�A�[��T8Z�����=.�a-��@Pk����GP�#��`�,z�)3��TZR��'V����*��*>XDK�k%�������]�3B|�H�Z�����#"��Y�V���t���p@���KDDDDDDDDDDDDDDDD�C{DDDD{	A�;s�:'��m@��M�!`�j7����4�!�EEX��#��: �e0L�_n���	���(��0&c�nj�A5F�/����wV�OI#��T#�S�Y����S��^�^����"���B�$x�^x�^���R�"���0"���h�_�&�I$�I�������t�C|DDDDDDDDDDDDDDDDD����^D������������0|��6���}!Z���l
,���Z����q���PA�_ Q	I���>KE�6�P��~�:B}���1=Z�j��C<�����mN���+����+��Q���uA4�	���
�������3�0��2��%���k�f���TVVBUU���h4
��	I��`"""""""""""""*��o���~{�� "�"��oDDDD{!�xj�����+�5����V������p
�r[+$��X��<�����]`�C_�yBM�+#�QA��
���m)#���G��+��}A���/A�@T#����-�p�xe_�.}���e/DA,I�D��DQ�����jF�/�@����+I$I��f�����y�f��v���t=v��
 """""""""""""""�1�GDDD���+�����=���y��;�h�1�������H��4�F0�1�s�������S����hA������kRO�|�-��/���2�E�����DXb[bS�6"��7+���}p�n���EQ�������w�K$���_,��b�+�#����@{���t�C|.����������^L���82B������g�4���k��2�Ck�]��N(�
G*���R�n�p���8O����
�R-����M�D��u�����.}h�Z�Z
�uh~�K�@	<J�����N�>����� �v;�v;�����#�ft�K�R�W�u�B!�B��:����s:�E������������������f���Q���QP�9���j@5r4�����6DQv�82OD��d	����Z��s��j�/7�r�8>�
I�%'���l#2�����m�ut���H
@�^�zu�������Y�>YP����U�}^�#���`�
b�$��������n2���E�QF����)�L"�L����{� p8p��� ��j��/�iB�u��	A I���Z�������������������=""""8��D�����+aMJy�E���C���!�����KtZ�Luq���f8u�v(�����DE"��N��:�gl3LQ=�����0_P�#�a������L��N��;��YKGg�rx:�}��`�M��V"�sV�V��0����A�D"Q�9M�D4E4M��e9�����,��fc�ZZZ�AG]�&�-I�N'\.*++�p8JX)��4p�!"""�����X�c���	)y��6��|�bT\0��"VHH��0�VA���c{z�r}E�+#��DA�[��-{1�>:c�ak��0_P�#��`�,z�)3��TZRMY�l��^�#����o[D���Q�t:�t:��4MCss3V�XEQ�(
D��]{5MC @ H����!>����>�~?����u�P�P


p��������+b�DDDDDDDDDDDDDDDDC{DDDD�AWL�����T���L����P~�8�U�B"@�P3����][��c�X��/D�(��Nv]�����
�U?�z� IJq$�q4'���EG{���+�W)���A����h`���sg��?���b�L��a�x<�x<��;�/D�+P�r��v��r�`�'��*6m�����>���z�jTTT`���P>�1�GDDDD�D`�������=�	����gV#�������v��� 
P�G��u@B�`�H}��#&@�����Fd�,�Y�;f����@PmCP
��|!����;����F�d;����9%w�0�/}��x!	||"��V+<����a �"� #� �JtN�0������X,���N'$I*���h�V����xM�����B�<y2^8����������L����0M� @�$?�%""""""�xv�e�V��
��u�H��x#�o��#��s&A��%&�`�a�^����\�o��%[�<��R�!DTX�Pa����2�� _H�#��u� a�KP-����a4`K�z\�'+��U|p�^��X�z�(7Q�v��v�Q[[H�R�N|���Q�yS��������##�g��v���h4�+V@������*�/_�}����="""""""���bhiiA$A4�xG�$8�N�\.TVV����D���\��Q��8D�x�e��j""""��u���LG��P�G��K�����%��p
�j~ D�!�9 O���|{��F[��P&��2"*�hE��U���m	=������/������G�,l���0a"��������M����
�y\��WN& ,���Q^^����X,����6M�h�hMMM�O���s�������UU�V�*X`o]��r�JL�:����DDDDDDDD{���������ct]G(B(BCC�n7�������X)[��KUU�{qDDDDDD9�jf�A�z�C{DDDD�#�kE�������-��w��G�KP~�$�'��B��I#}01���9��[ �9 
��2"Hl�6��k]�z�4�0b�~T�K_P�#����;��F{�P�]�>$x���0���W)�Cr2�GTB� ��t��t���=<�i��h:���iZA��u�`�`0��f�e�G��<�6m�zs�PTU��M�0a��~9>�P��}����>���z�jTTT`���q
Q� �b� ������H��������r�B���0�GDDDD��H��=J��76f�qfRG����9q4���`x��� ������%r�Q���e����:"�A�]r�.91�6"c�i�����_{�/�������zC���
��}��,(���>��#���l|N&*Y���z���_<�4M$���n|�h�����nJ$H$hii��X�9����n��������������������z)�b��U{|����V�B!L�<�A�!��vg��
�PUU��������:�4-+�����bah�����zM�����������V0���7Am����	-Rq��� �P��B��u����R7�~����A���HD�#��N��:�gl3LQ-���#������0`�^�T���D����"X;�|>x�2�)��.}V��f�b6�
6�
����02��E"$����k�&��0��pA���������������z!�b�����\,NUU,_����/�{CP�������};����T*��[��02��bh�����<��rT_5
��W@��;.�t'��8*.�����_�����P?��s�MB�z;�i#�a�1Q�V�p+^�������:"Z(+���}��2�������Y�l��er{����P&��o-%��h�"�"�n7�nwz���!�H$R���)#���0"""""""�n���U�V��]��r�JL�:����TZ6�
��dte��X�~=<\.dY�(�%��������xL������b�D"��b0M3c���,�����nQ���j��Y��������4���O�utq�PA{��
sB5���9�;��7�!��*reD�7�)���+��R�a���0_A���^�X�$�8�8���Y����k)S|��^����<����(��|�.u�i"�g��b�X����m����
��pB��}�@��� """"""�6m���*$UU�i�&L�0�_�O�!����e����PUUEkkkF>""""""j?������2�GDDDD�M����p
BomF���y�;�e������"VH{#i\5�@����m��;�
W�+#"$A��R��"k�j��;�2�}q�4���EL�bGr[�6���G���+��q���A�TK4t	��������j�WJ�����N��mmmhk����	���\���,�������������D"���^H�R�#�z~?&""""�~��Z[[QYY��@

����Y�=""""""�d�Z1r���t�gh������� 
��4J�������&/���E�)c!Hbq��� P����`��O��	��l����l�ED�"*��T��R��-e$;�|��0�7�'�D	�"z=�l�X/@�K�d����n�Q�k�B�$	^�^o{7k�4�J���|<ag�������v=�@CCC	+�������h�r�/UX�T������R�D����TU�Ux���DDD{�b�
�������+����0 /�EDDDDDTjn�������\���=""""*�U�+�h��z0�w\��F�M1T�7	��R�
io"(���H}�0r�����Z���c ����g���C�uX����&��)�R�H�9�������DXb[bS�6"��7+��U|pI��I�A��j��jEEE{7O�0����p8�d2�ku""��`@�h����J�^�vm	+�4�C�{R�@��R-��.�z~�����=�@����2W8F,���(�|T<����C2�D(B8�y"""""���$Ip�\p�\p:�%�����e���LC�S+���;.�1�������)����X!�MD��~��~�-�v3��j�)uE�����l�6��k���i����}�!-�,�Uw
�uh~ ��Mdx�2x���0_y:����<��h7���~3h����_��*""""���f@��
���F�4������N$��9z�?C��Y������G---���/��T� �f��f�����i�0�n"""""��� Eq��_���������xu=����;N$�������S���#��p�`���������vH�}E�����	����Cr��6"c�i����t�h~���E�W75������m��dv�����&��nDW�������2�: ,������*T�����G4-u	T$� ���1�GDDDD�@�E�N�����+�#������WA����QD�DL�'O#�����.��m����2"��N�
���pd^Y�0
D�0���
A5���M�>��2�f�hM5�5����"X���a>���U��V��L�$H�]/n0W��u�>)��������ho�D`�&/�DDDDDDDT$�Q�qZ������������jc�gO�h�KT*,Aa�^���u@*���aB�r,G������DD� ��x�V�a��M7uD���jB�A-��,I�)3��������k�9�|^�E���Z��N��P�hsz�^L�<y���+�7���Z?��
�Z�R#�����Yg��dz��j�:��_�P��:�`6""""""�"��DDDD���c���z:Z�����;.��
�.E��S W���`S�L	u�F�je�SP�n�r�(^]���� ��o]����DPkk�u���Q=R�j��G"GS�!k�Cr��y�2��R�j����r5��t:���^��5��
�������g��
��S�:RP�T���X���h�r�/��������b���&""����=""""""��ah�����������������j�;Nk����%���$����	��s�0h��;1��3}�N����\�� 	2|�
�,Y�T#���
�U?�F��1=��Ecr[�6����y��r�e/$�'���VYY���� k�GD40 LD������F"|������3g��r�q��\�k�@
��ZJ�.���~��I�}����;�(��""""""��C{DDDDT�EB�������[�sv;3���/���7�#�x��4�F cG0�vmm�R����
m�hA����`t�H��5?�F��=���������e<r{���3�^�n�Q�	/4�9��n���~���v��p��<DDDD��@�R)���^�Z����%�����@	C���@a��q�Z�*�\0q�D�l���R�qm]����v^o�&����)IC{DDDDDDDE��� ����R�D���a&��M �����N�A��GT� @�8R��h2�u�V������:"���E���:U�aY�z<3��)������j�DH"��-�)c���=���}�v�\���'�uVWW���We""""""*���A�=��+
e��|><O	+�b[�bB�P��s�\|L """"""*"���������S*P}�h��Zk�+H��l��3���'C�Z�X!
e�,A9������=@��.���� H���M��&�Q����i�����B����VZZ��&	2<r���#��K�vHN�(CE���PQQ����~����>����ODDDDDDD4��\�����Ng��""""""""�������D�'�������Brm �8ukM�/A��a���E�0D�
��Po���%�-o���p)�� A���pHN��Fdl3MQ=�)����@P�#�` O��~���j�jK�6EP���u	�yl���C�oF��P(UU~lEQ0z�����������h(���DCCCQ�#""""""��ah�����JFt(��h?�����g�S���W��>�5E���2i���J���o�C�9 �,/reDD�'A�Kv�%�1���@Du��@PkCP�#�a�,z����5���Ts�6�h�&��%�g�lE���EQ0y�d,_��^�0�$I�<y2E)�1���������"�����p8��s��n8�~�������������� 	(;y,�Z'�/��<'��&��X�1���$v��='�3f0�-�s�������b
� ������a�}L�6���B�m�.}!����GD���������L���f�9�|^�E���Z���w_�\�� �vyQ����a���E������������=""""��@�r���+`�Ry�E4@m����I����A{F(���\�Hj�L��[`=|<+�|""�$AJ����
a-�����~�:��E�H	�F�dM���m���+�W)K��<rd���(������S�i�&�����q***0z�hv�#"""""""�������=z_�'�����$""""""����N����h���t����h}jR[�y�%����T~
�g+��H���L��g3G���
u�(�� ��#��He�,��Y*���F
!-���O�#���/��7b%���Q��(�����$O{�O��+����n�I�JP-
��`��	���DCC������r�������_DDDDDDDD�i����BPU���V�G�.�q��������g���"y,���T�_\��My��m	4?��g����'����s@�Rmyv�"0Z���4A�8����@��TX�Qa����4��_��3���I#Q�j��BDa{bK�z���#��K����.�QKR/������C,CKK��("�t]O��$	.�N����p8%���������h�S�'O����3���S�$a���P�`�$""""""��ch�����A�;s�:'��m������������z���� ��>id9�@��@��������j��-���-�hE�u���������~�f����0�il���m"Dx��� ����Kr���p8P__0M�a�0��Q�='"""""""*0���}��+W�,H��]A@^p��������t�#"""�I�������W��iy���o�Q����*�JJA���p�B	�������� a����:""jl�6���e�7Mq=����kCP�#����_�ZZ��&	2�rY{�O��L��o;$'�]C� �$	����DDDDDDDD���p`�����iZ[[w�8=z4;��C{DDDD4����P}�4��_�)�w\|Y+�����p
�r[+��D�D(�B��u��g�
�_n���qd��NDD�'���Z���m�i"�G�C|�}�6���|����njhS[���dmS^�������U|��v�����������P&L@ee%�{����F]]|>_?VHDDDDDDD���
xr��W���� �<�U%�Q4����M�m\Y�
�!EtX�0���rn7#I���C9`$�DDTT� �%�����Q��@Du
�����Z&�����*ZR�hI5gm���t��s��+�`�x""""""""���|>�|>�b1��� �"�@�����$Ip�\p:�������(a�DDDDDDD�C{DDDD4(�V�MF�?[���������?��o����Z��h�HUn����������u@SY�����r��#�c2������
�U?"z�$���$v�v`gjG�6���W)���w����U|PDK	�%""""""""*
�����z�i�0�a@E����B�������0������h�D�F�R�D�s�a���
 ��z��Q��6�,�P���0�q;�9�k�!z���E�����o$AB�R�2�<k�fhi��0_P�#�GJP-�0bH$chJ6dmsH�N�����C}����:��������h��$A��R�BDDDDDDD��3Y����h���W��J;Z������;.�h��*�����,�7� @�:�������L �d����`S�7�&��i����)
<�(��R�rKv�X�H!����~T?F��1=��Acrk�6�����:�|p�^HOd""""""""""""""""��ah�����%e��WMC��V"�!�w\js��/F�S`�.b�4�����d=`���RK��r�X�#������%U�f�"A�� x��� �m��B���v�"ZPa�F��:k[�H"��hm�~��ZRF��=���������eoV��+���=ve��i�P�tS�$HP/D@DDDDDDDDDDDDDDD�������h���
*/���6"�qC�qz0����B�w&�1=��s���;���C�j[���?���05����C��5
�F�o�	���<�
R���*'""�?V��*�0TY�e�7M	#�������.}��>�������0�il���m"Dx�28�F�69�@JY�#p���6�����u����lDK�I����V��JK5�������rKU	+%"""""""""""""""��#"""�AM�D��:J����z�nh�h{v5R�QxO
A�;O���#
����oi������1M����z�L��`��gDD4�	����]r`�gl3Mq=��@Pm���;�@7���k�@@mCm@�k;�����\������P&�`��C2��9�K��#��b�4������-X���#0�;���E�����������������h`�Y�DDDD4$8����������%��6�;��8wD;_S���ja�0����h"����1������h ���B�mD�6�4���A���!5F���L
mj����m�����d��rx���m�d/z�{*�����?X]��}w$����m���#���_?Q��,e""""2��<��f:Z����H�q�5~4?�N�R�(b�4�	���QH~�H��=xRC��
������A�K��%{0�2�����
�U?�Z&�tZ�G���%���Ts�6�h�W����w�+���]��������5����������so���DCb+����
KU��#"""""""""""""""��#"""�!E�ZQ}�T����%;���Z�h~`	������"VH��`W �;��-�?��#�h#�GN�`��jDDD����R�R���1�tSGXf����=T�z�F��F4����D�:|^���S|��ePDK�kmM5���"i$
r����;��)��ap�����������������j<������A��;{"�:�olD��+fRG����9q4���� �-�%cG������h�eZ}��ADD4�H��2�eJ�E4CCHt���T�`��v��]	#��v$�gmsH�t���)���� ��7���z�?��%i$�z�?pV�E�I������������������h�`h������$A�>z�Z��
fB�=�B���1
�w&@�H�-��9��C{�� ���jO��CDD4����rK%�-�Y�T#��k��������E���y���bz1=�����m.����*>�e/$a�^�.h�O��cz�������/�'"""""""""""""""��#"""�!�6��WMC���v����/�	mgN�\f+b�4�hvi��������"ZPi�A��Cxw��C�1����,)5{���C_�H����BDa{bs�z��7+���}p�����x�c��.��_k^]��������
D����T9P}�4�=��Umy��
Q4���O�u����``�0����e��0�	�nH����M4$T����2��i"a���]a���G@�C3���j�DH ��3����Q�����*e��}�X\X���2�GDDDDDDDDDDDDDDD{%������h� �dT\8��6#����������~��S��5����@�7�;_c�{XQ�$""��A�]r�.90�3�����EP�#����v�j��V�z
��m�m@�����1�
m��(�T��"""""""""""""""�ah�������(�{�h(�N����j�����jce��� ��-�$3X�.{��%:������L8e��u���L�DD�w���:n���yM:D����!��^��=""""��8��\iG���������6Bm������\�"VH�i�0B���i�����!�V�Ud� �"""�3� �-{��=�}T�6�4�Bj~����Z&�U]8������E�`����]�%A��"""""""""""""""2�#"""���e���LC�S+���;.�1�������)����X!
(��zq�4Lh_m�\'
�2`����u�-Xe�"Cy�;�@'
"<J<JF��dl�Ma-�)���q;������@������	r��Q�,(PD�.��f=��DDDDDDDDDDDDDDDT
��^KrYPu������v������R�����UE��s�t�1L�q��=�����`:���~�T�������$AB�R�2�<k�f�i�N���mj~��h	��s&L��$Rz�N��C��0���N��
�!���%�������������������{��^M�E�N�����+�#w�T
�=�
��(<��b���`����`�4���Ib�`_��Ef�""�B�[�Pn����j�:����F����f��Lq�p�!��ev��f��;��
HDDDDDDDDDDDDDD4�0�GDDDD�uh-�jZ��FT�;.��V��Q��=��/���(������tf,�R�w���{��)��y�#�'�E*�����RD*�5���dm�!<���T5�0�4H"��a�0_w�����.#""""""""""""""*�eLDDDD��:������u�
�����+����RT^8r���R���c�����b�3$5�I
&������U�`Q �::���H�(CDDTD.�
�hC�����JB5U��Z�cJ�r����9��f�$�5QO�#""""�D��Pu���c
�_���5��t�T|ol���X!���u��)`��fo�B��Z
���{_G��=��)�g��c�>""�=&*-����R�9����j���TS���+* :t# ^����a��]{��A@""""""""""""""J�#""""�B�H(?w���zk��Sl&4��e����udO2���2�vm>����6��3�I���]���eHiyV���}=P�N��NA�.����Qw���E
���9���J/��	�����u��T#��r��*T3�����F�i�#&Rf)=Y������(����M�O���^���HDDDDDDDDDDDDDD�[�� <�GB�q����0�yN6��k�6F�;}����*�m��s����}.��������D��t��i�@J���C�@���`&4 ������}�S�aF{89\���������e���W""���wN���gE�oR�� �2�%G���M�#���`��5S-X}�3��>���������T���v��,�+ �C{DDDDD��O�@�U����rh����b_6Cm����)���"VH�$������"�S��}�Na�������g&4���A?�S7?mw�/-�*��
���*R:��5��y�����h���Ta�uv$���\��(�T��< 	$I����4��a���_v�?��r��)���=��e�@�H �
��1W��/3���-
���P��Q�jG{p����\�;N�A��KPq�dX�=�+��F��@���h��b�Ru����A��������t��L���3�~�������Ez��'
9����Yd"�}DD4�M��7�ho�wf����A����}���0M�>��2C�ZV����4s^laSM�^�N��A���r�n��Y/	/>ADDDDDDDDDDDDDT"����PPy�~�����g�S���W��>�5E���E�R�d[���Ye(S�
�����Oi�u�4M@7rv�3�j������8)��W���s_��'��eY��Q9QN��0�9��+�m�����w����V� @�I�a��`�5L#g�?-G0��oB�����xt���8�x��
:��rt����������=""""�^$e��B��������V���k�6F��7����"�r��>���),��`|�	��R{���}���[_���7�0�I�)
fJ��a�$vt���S�u�)SG:��a�&O�&"�~qD�qhHlEL�����#��+�q)?Qa�������4��Z��~�������J�Q�L�H�I��:K��,(�N�r�N�Br�`�����	"""""""""""""z���DDDDD%�<�J�-]#��;.��jS��N����S
.�����H-�X��{�� ������8A����t�1M��N���~���,��K�T��`���1��!)l���O������� ���J��h��Iv��9��xI#Q��ZE���	�T�.rT� @�P`�;�n�a����_��j����i�y�(�A�C�`�x-�k����_����ev$""""""""""""�bh�����h7XF�Qs�t�>��-�[j%����T^8�0g+��&�m�9�����?N����A�a�?	�(E\��5u�S�>����A���D����D�
Y��Ye�-���'/��R�S������Q��{��y5g��RU��h��	�$���]��4�<!?��5����O����
&�k��LL��	!#��>N��
���`��_�1���eQ�xV(�n�<T�`*�/�C��������\�����}��"VH�M���L��^����?��}}N�c+!U{����� ����n�v�i���w
��A?t���mH�hL-DS��^. 3��+�g�!�:�,��GD�7��T�������?X]������#��c�=*	A::�u�z�/L���!���Uhy��Y�N��k��B���Q��#��P��
���=��^X�������������h�ah�����h�����9|m�'�c�t��u%<���}l=�'�
%R�R�F8�13����� E���C(�C�-��.\g�A��hpw?�����A���A����Pa&��KW�t���#������
n6���������X\����^�[k�i���w���
��OH�!I2l(\�0����!�|�s���xt���8�8��8�Wy�������|�NDDDDDDDDDDDDT:�
�	�I��Q$+��.��A�>b8���^#��sB���@������R��b�6��a:���`��(��&A!8,����R:��0_�n}fJ��������>���:LU�Mv?N�t�>%��_FG?���}�����(9��������2kSm���jI�-�%����xi����3`c3��,�`�pf8p��;��s.p��a���1�����i��
6���[jukoI%����r����GdUeVeVeI�Y���s�dF�oj)�*���ZuOj��I��XaXg3/j(?���
�������T_|�[�'�W=��U�1��8�Q�$w
;��V��4�J��������J�aYVV[P!(4�����5zs
����nw
?��Ah���������+��5������I������-I�[Vo�IRr�&
|��F>yJ���������9��?(������#y\�������r������|�O9_�P�?�Wq:���ak��e�}������p������{]`�����p)�g�U�X_��hn� c�<�����T�����[Ip���-6l~X�_�5�6��!��%C~^)$+��i����=X�F^�.~C�X{�����E���K�;��o����h��j��6
��a����^�9�x}FC�uT=�r����[7A��x������[Ur����OH��r����N�XB6W
��6��5�����-4�l{��2�}����W%��d.��f1�(n���n��������J�q7���.
�ML������:�B'�}{��K��������� �u���u*T�|�S^95���Z�����:��o�B{��2�����W���E����u��wK�t�g���p��/�i�k�5���5��3�F�����w��������SP ����Qs��V
��_�+���x5m��V6[����/��{5�}�i�XU��R�|8�oSbj�g��'�����cZk*XA��|{Q�����u��
}�XZ�U�������Z��6�����������.��`�����������\?.�� �����!S��q�:�����5��gda���4��s*\��������<��c$���h5��f��Vi�+���+\�-%_���N-3�uJ�}�M}U��\��^c����zJ��a�
mXj���UB�����^/�
�B�aVR�a��F�f�_���z�����Ch���A�����lc������=�5������}�k��'O)��7��
��Y�~h���x�qp+�c�dL&�����Z+�aY�����<���:l�B���4SX�Ri����XY��|��s	[lD�q7	���o���Z�_��W(�6�-�^;6*��eYYlA�����z&6�X���w�khXM��`�2Q�^�{���t���G~Z��{l�����5�����i��M�W�4���:�����]-�!D�1R����R��cm����K�|���6����eU;p-I��D�,��0�Wzsi���c���<����v��a��B�Ko�m�a������y6l�19K���RH0f�����=Z�FhV����f�f�OJ/=&�@s�������Gh��4��k5�
�������:2��������2mK��Zk�bP��������|Q�x�j������2����f��J�1��'��d�1��5����p�+�u�P�a�������5��e-����`�������kF�
�s�+�F�1V�-��D0�����=XM#/J7�7���K[K}{�{������=�������������>sF�����g�����_��(���eJDmV	�U	�|��k}��\Q6W\~�1w.���'�,��f�~��?���$��R��7�X	k�B+�-���B��
�#�W�E��61�r����@��
�������]���XU��`5]�F���MB{���_�E�@J�rJ�t�����yE���~p��6��`�3�#��K�:��
�l)��R��Z�O�:l�+��@6�_z�1�\s_����l���CsV�1F�<�����v���U��*!�Z����:�aVR�a��F�f�_���z�{����+`�L_��/��\����oi���J����wD�rJ�+�5��_����>���Wl ����e��j��~���5���/�|�BQ6�G��u��amY{_v��1�,�W�S�s�����c�MBq'��cZkXA�_�,,��v80lT"
���*��
Ac���m��U���������sk�=X-����|{��Z�u%4������j��P�q�HVC�}L=����=-�!��sd���^��������\1Z/k��m�S`[4��m��^���15������C��1&
g)�6�q7Q
l�(���J80z�m�a������y�������!?��)f���`�XOS�gb���UFhV��+->����Ps����+�5���� ����|�����:��So���n�����XP[��V
���-k�+o�Sa�h�V6[���Z�$��{5�}�=Z#Ir�+�u�P�a������/h�������c�������AB���9��S#�������B�L�M���	��.i:�Uu_�8�� �=X
�J��Z{����>+%;�D������K|�
����G�RlsJ���E�\��s�4���*f�����'�f��<7
�-�������}��S�/�-�Z	���:�������m~��>B���cJ
l���Z�PA�0_��_���-�����6G,�h�*u61n����/K����r�����j���W����=X
A^���=�
��g��f�(���\z���@�$����k������w"{|X���z?�_^w���h,�)�I�����s���
~�A?�a{_������]Fe�}���~.7��#W�\�SRm
;nh�R+`�p_�����@�N�@A���mX+��Y���TK`=�=��
Xu��`5�k�B[J��hY��l����.}Q2��XJ;��?;���c5��e4������}J�����#�\��+�/=�a��o���z��������A���c=G&+��j�sil��8��������+a�U`�R�_a��_�^}{�p`��D�eeU���0=���k���U���5nC�����jpV����R`��52��5���waQ��E�R���-}�N)^zLtF�~���r��z?�_�{IS_���0S��'N��=�������Z��Hmq�������R1���g���p\�(�a�f�@~(���L~��>� �Wj��{2IO&�IzQ��}��c��gb�S��j�q�h���p`���b�������o}��-�#�J�/V�|��)�31n6�=X
n"
���%�e
�F2)M�������H='T:^PG������q����������%�R;�l����ov[��%��t"�>�u}�N���u��/�k\]X���Y3�~�.I����'������ \&�WZ/�Z:!�Y+������S��sa>�=�d)�7��
���lx�q���J6����!����������jc
�����+T�|�S^95���Z�oQ8p�1��;�8V�=X
�H����sU_�I��d�&�����CG��&rI]��Tg"��]S�i�5k�
f��d�,��-��X�Xk�
-�z�_^_�F?yJ�D����?
�x#���On���K�3�#��K�:��
�l)��R�����f�
�a{_1�-�����J��R{��>��Ec�}"��R[�~vg�U��F��V�r=W�jbz\���N(3
��ny(���Ac�]�U�|Q�W�p~{�p�k<nb+@hVK���B{�����n���V|��|B�C	��f��g\1w�E����M�A���d����aQ��E�R��A�*A�x�����74P|{���a�~��
k��&5�[������oko�wcJa���?N�~����([���/[(���h=�/
��-�f��K��+�V��J���_�s���G+f��+O��)��[:�����x��������j�h/�V���*!�Z����:�aVR�a��F���o����������6,B{�Z�<$]���j����>������4�Oh������`��}���
��Le�/7)J�������O���h��Xb���{�N)�Y�X����6DXC�������;����k�����������:���0�x��������%��V*�s!>�+J���_������z3��7�|{_����p_��>��Gq�P�Y�{������~)X���������k��F%��,+��-�46��O�\��|��Z8�����&�V�=X-�[�����Ee
1=�_~��;IW�����CQp������$'
�����m��RaZ�MH�))������uM�Ra*Zt��0��������Sr�-�9HQb������v��\���-����*f���{���f���j�%�Yk%?,��K�R�oA��
������f�Q��rc������u���D-m1����v���4�$=�����ayQ��W.l�19ea��b�P�|8�����@��d��'� ��i��U|��N
�5,�7������7�������dw�,y�|ek_�eJ�������c��/� �We��K��9�FA�0�~���XW�_�U���F����L�H��xE�����r����~c��+s�k�+�7���/�=/�����B)�8��8�)��7�U�������0�u�5�\�UB��3j��+�����������iA��
�s�+�F�1V����j������~F`���]XM}{u~f�
A�)�/��gw����M9~/!y�R���J���_����t���~.Z2CK2Qp�Vs_�K�wH���f��.]?.M�"M^����k^���M��[����fJ`
J����O��'O�8��9.wzLC�sL�~P������a#%c2�:��J�>�k�T\7Y(eg
�La��B����bK�\.$��E��q��x��i�U��v�����������6G,�h�*�mbt�V	�E-�^�V��������=�Z@hV����kN`o��hA��/�g�����.��l�v�c[�q����R��+���������Y�0-SWks�(�����������}@|�yQ��
i�b�1~V;-�.u��v�YjE��
������C�����=1Rs�?���oS��U��M-�!kWE{_��cm�����������y=��k��-=�sd�R��v�O1��7������n6�9��+d��+O��)���\-�a��Z��V�o�p Z'P� �J�6���D�u4�-�X�L�V@`
���h
l ����8?�`
#������Zs��G�Fh�^�'%���k�q~���orA�_��]��/eoF����d�����x���-���U�Hg�n_����c�����-�����0N�U��jj�M��E����9_#����y������X�:R[\�m��hXk�bP���<���[4��CY?/e�������R[_��Iz2��L���h�[�����k��3
's�m�1WNgR�+%w[�����M��9�Q�$w
;��V����|E�B)X�[���v80lT"
���*��
Ac�����5��������>��3Z���i
�5RR>���V�I�/>���V�����x�*�,DhVIflT�7[r�����U���%�k/!y�Rz�<[+gj����BF5�.k�������L���Ui�����i7��A��G�����q����G��-
���u��n���4�ggd�5.~���/�8�����O&�E�4�1&
��=�c��6�Ja�|e��
���V���R�(�+.?��[��
��=)9�����"�������7gj*
G3�hF��a�M)y���t�n������-�����
lPW`}�������M�����r
��#���o���r���o��@���6�K3�tl�)]�_�9&�t5wYWs�ul�ImI��#]�hGjWg
j!��d��K->��/�Wc���xZ��Z{\H��%�}���\�c�6z/�)i�Z�a���+�%�$w�6�5gjPz��%?����'�g~Oz��"��5�m_�>vX�������^�<7�����~x����������L*.��h�+����~��?�����������R{_)�g�U�~�X4������_�S�.U�^c��3*>{I��.��o����k\�������V���+���)������_�B��
���e���|s�K����n����Y}k��t6sz��^�_��]���>���;�t��0CP/���U25�TSZ3�w���[wWJvG�R�|��MJ����Z��6�S�f����-KqQx�Vc_�S�wD����������g��$=��QX�b�(��gg�������i���c���}J������RX-�������J���/�*�~*�-�y��V�e�E��e��?�����3�p�����'I
'�*<sQ�����ppB������WNG�.��Z�V��bN�n@i�U�`������R0p�u��������-�4����[%��.l���ZK@�FC�����L0}[�9�9�k�W���?��x�fV���k�2#�-=���u�����v%�i��u���Vx�hI��c�T�Y��o"z,LK��N�A^�EKM�F�Z���%������c��s3�'���|�9��I����5��������������	m��=J��&I�;��2�+��n����
e����_���U����YZA{�l[��J��^�m��������o���p2��S�b�n<��Ux�����"�`]2���'���T��B�Z���j����u
���l�Z��t���F&p���1%3���cNL���
�N������(�r��`Z�]�3�{���J��*�E��e.l���u��_�[w�q�Si%��������|�T�����vy�$����l�������0��{U�}e����7���KaZ��V{�qK�}�4�yK_d\���������q�����������8F������v����$����������`F]��%��u���8FJ�d�1i�����B|�R����+�TXm��V6[��E9�v�]���VAe7���6�-���E��u���a�Q��Y�@��/(���d���$�1��&��s���`��o�Ea�(X(5��?Vn��H�����ZYWR,��`�!�@�x���|�!��!�z��f���c=�Y}��_6,�7+�������}DI�qAdP���U`����#(�-��Ys�q�(��J������_iq\~@KWJvE�R��������o��o�
��x�,�M��%K�����p��o4s�e��&�=�+�#���i�ON)��}���o]S���z>�Wn:�����#�\��J���� �/�=/�����B)�8��8�)����~*{>����7�)��&���}d�W��5��h��2�D�*�����k��X_80z�m�q���0��\��c:rj4�U��7�-�hb������[c��`�)��	������w�oS�j#���8�#�f�P��I��&�kkS<������/�J���[4�
��K��h��Z�8#��\)�W-�W���.�
���p�,%�����4~�%S��i�����5� ~w�6���~��
�k_i�?;���>���WlK��3�]e{_ms�}�@����~
o�k� ��)H3����2*k��-�s��OshR��D��[.�P�mR�@gS�h,��r]W	%v���Z����)p>X,k�,DMuh�P�
a^��8�V�o��_� �[w���f��l�tS�q6sZ{��tOjwS�*��U��b��	���jO�!������2��Vn,6�[�K��b�6��w�����hY*LQpo�������Z7��Q�.[��qi�=�/ng\����n~��f��Qs\0����S��P��%�������}��6K�}�m}��~~t#���j�y�j���<G&+��j�s����?��
R�??BhPj�+�4�F��Z�
�
�-�=j��I����h�*�mbt�V	�E-��
�g]�5�Z�cO5���x��-FhV�1F��~M\���Si��XTv����7k�1���J��D*�x��y�s��ug�5�q�dW�,%(T�-l����&�����X��h���������x^
����P��:�������#j�h1�:R[\�m����R1���W�������Z���~^���i�3��}��~a���9������S99�kg@�>sw��u=%�����6����W	��^-��	(���
k42�&��6.��oGu=�����W4VVO��%���`�t��4�g\W6h�O�������S�OO-9.�l��|���/Qz,o�scqZ�n��R}�R�������&�B�c~*Z���t������a2���
��mNi��/*������e3����$L���#�=��'u,=���`_�+Lg5:xC	yJW	�i��o�Z)W����w`��������c�MBq'��cZk�[Q�o"3�c'��u��j�}���;��`��X;6*��eYYlA���L���@�����	��2��`����_W�?���=������K������
3����*d2s��33�vm7sYsYeFGj�qb���o���,�OE��d����p��1R,-�K\�R1#��h��OF����J/����=z��[�xz�g�Hr�&
|��F>yJ���M+�F���1�~�Ay=4������L*.�*�����:��������-�H���U�f�����W[8��~�\Gr
7��q��Z�b������B�^�|yn}����������
�n������������F�u,����KC�����;�=X%��^un������h��mJ��J���]Jvv�k�P�\v>�Wz�g2*d��~�_��i-�Ee'����9�G�T*j�K���������_Z��?���q�Dg�,%(.�U[�5�g���h����7�����H������ex�m�����3��0Zs\����~��z~h��{�[7A��b�L��I,������`�_3����^������_;=��1Q��s��x��:2ni����?_n�@���5�\�UB���b�
�8�W���g�m��Z�a���4T7R�!k-??�EH!�*�~�U�|��-8�����)��������*(T����f2����_!�Q1�����
� bfz�q^"Y���n�Z�J�D:-7������I��h��Z���|�����t�k��g-�)ilJ;[��D��}K)��5zl��-�X�����OS_����^�9.��5��'��������|�(1�+��R:��8Z�P%�W�esE��/�J-~���-��F���r���cgA��s$����
��e��ec�0`�Z��9���Z�PA����A�m���3o�t;�aNE[T�4���FhVQ�����u�F����s���O=w�l�1�1��	y��R�zj�����V�����[�
���
:�F��9���2c�[��+����*�~�v�����:c�X[��o��Y+����_H�Z)�F�c���\wi���hz~~�+k�+k���7c���c��]�(�%��??#[��u9���pN�k����=2_��e#%c2����������B|�R����+�TZ���V�g�{Fr�4:��-
,;&�@�c��+O��)���DV*���F��p_�������.
;����*���j��5f2
?v<����=�����q]%;:����9�Z�b.���/z�g����b��3_������Pnr�� coKU	���H���\��W��s�4vn�a����LJS��2���p>l�9����:���g��7���aQ��-���Q�/��,��Yr����v�O}m��)c���f��!8�������O�F2�H1W&����b)�W�[������ZiUB�fq�o�A�-�'���@��1��&�����OV�Z+��u5��B)48�^;j��x�5\�@��]8��X2��o����_�/�v\/�����[�d�a�l3dkK�����8�PPaf6�W��������V��Q(q&������Db.���
��5�E��x���u�]3�76����M�kX���&rIM���2���D^�����V;���iilz�{1R��,�W
��z%C�/�%������O+�v�piRC�yT����]-�!fU���6���
*��y)X���w����k,S

�#���1���b���m�q,
����2�W�m�n`�p����������^x����WkH�^<�����[����nm��qy���{j�	�`.W�L+?���}��}3�pm_������y���9�q]�SQ��"��*����oK�8wH�k�C���Wl*���ukd&���M��J�/5�]=�����l~H*LI�7�b�[2+Yif4Z�_������@Y#_)�� <����c�������yM�Z�q�dAC���z��>���p�X���>7����M�h�������B�����Me� �@�:�W��*���.oNl�������/����h!B{�F�{zu��>����M��{������>�z��k�a��U��S����c���s���\S��`_P(�p�+�rS��MM�4�bXj�K�����-~�u7�����E��)�_�$e
1��S!������4�Oh����q?��}�t��sk�v���(�7}=Z2CR���������R.�^�k�,�����q����[��i���Y)�q�j�3gT���{vFm/X�LWJjah���#oG���A(����~5�6�^Z?���+lX���fB��� �����oqho ��e���`M�%�z�-���]�������^��h��-��������y��1���)��&�����X��|3����p_1;����
k��5R{�O(Q��O���m^"��/\��f��Ee
1=�_~����B���:�y(
��|t�Ec�f�D��{��vF�x�!��@_vL
�T��bF�y.Z�'*�m*���|m��s{�Fl|��n�7�����R8]�9n��WT��Q���i����������p���������Yk��}�z���oe��v?���K�K(p
[7��*
���I����'[x��-; ��������:y���\����q%	m��I��w�^���*��f���)}�[��K/����I�����{���_�zm�����z������jppPA���W�#�<"���V�g�N�������F��������/���x���}������]�)����3�x�X\���R��j�	�@���R�oZ�LF���\�o&#-�����f
y����c\7
�������_���b�������U���N�iX`o�::5����)�W������������P
���l�+6���F����4|j~��I��� ����xq!!�%�����;��?9�������/���oS���+6�j�P/�#)�)%{��7�1��
�I�
y����6�;��B�s��4��	
\w�
4F��1Q��r-�+	���������%q����4�\[w�'^�����H��n������������}�k�]�����w�K?�3?�7����u�.��������*
�^7���o~�>�����G�r��Xk�G�G��_�U���KU���������_��_P:���s�������Yk��a ��rc1�����U��C����c������@��t��o�yP�\�l(75������bm�������p��7m��ov��l�����c������K]wGK���|�o����.MIa�V��}i�Z��tH�����0��0���1�����%/���`M�����t�sg5st��8$���>���U������v����������h�����*��%���P`�9�P�:a�T�n�d�~��P�l��s$���G(���]��C���z������i>������D��\5�bQ�������^�����������\�y����\��G53S�n��Z}��_�[������������Yq�i||\�������/9nttT����}������=���+:0�#/������X�M�d����/V�������W�+m��Dw�a�����e4\s��W����p_�����%�V�uy��E�\�p�oaI#����E�����':��w��6F�x�A��R�ofL
����t��~wR���t�o����6I�-R���v��^i5�R&�j���WlkZs��E�4��^P��w���w2Xc��N[�N4���.�+����`>����(�L�o��*cJ
�
���&�h�J��������<G�\2�7��,���2��'�#��vkOz��fN7�{���#��i���C�<���U{��j�����y����.]������>��O��_����������s��_��>��*����������544��W�F�(���W�W��������u�'����o��z�����x\;w�T"�������d�^;������������������pn,���n�uu�c�P���\�/��^���� h��oAP,(;^Pv�v#�q�SQ�/�JW4�������w>,v��s�����<���^5��R}�2p`~{P�2C�a�����t����-#e9������o����|�p�1�x�.���5�����_s�4���*^����_N�p'�Z��M����������m�?.��M�j����^� ��5�<X��6����]
�U�P��W�������
�m��4�`�zC�w�Z�����7���
=�������CKtww��~����w�Koz�����1�Z����{��/������~n�SO=��|�#��g?[�9��;��~�����zH���������s���9�����?���}nn�o��o�Moz�����u���~��*{�����?�O�����6m�$I*
���?��������Q0exxX������O�u�p���Q"��D�v��Z+���B|�i�KA�����i��|�c�6���R~zJSK��%�O������1���M^������=�-9�"n\��+Z���|���������4=-�bmQ+��0��h�|�2��7i�c�5��S���5�eO��������u'[8C,��=�_{�
O���
��K�U��������F��P`X
��
\Y`�P�Z�#G�Td�_����[g����6��:N�f
��t����?������a�a�M8I�s�(��5���~\9����s��������������\��[��=������I������k���'�x�"tW�/��/U4������W��UuvvV�{�����~V������s�������������k���/����+�}�S��?���m�x\��G����Vo|�5>>.I:z��>��O������	V��X"�X"�d�,�}�����}�"��/d+��*�j���e������%�.��K=����P��-���fF��K��+f���R.��2���%jt��G���>vXcvF��j�+^�h�7���C������3�R������R���i�KDA@���5��c���p��P��P��8��A�QV��{����$�h����M�P pG�����[>�/��lC�Rn������o���� ������?����m���u�w]W��;����{N�<����O|����^x�}�3��[����_��-
��2�������'�xB/������������?�K������o��]~��xQ`���>�������?��s�>����C��b�����fq=Om��j���9���
�lY����L��f2
�\���L
�X�)��8Q .�'
<8�=(J����l���T�a��nF����y�R�A+�V)�)�f\��Fr��z?�_��_����f�������������Kq:�J��>O]S88q�������m4�a�+Jjx0p.�0�����a�[
�k����a����m�^ic��VMo�_���}k��t6sz�j����7�|'
{�2��@���]�Z�>����������n�W���e���?�C����
���o��%�I&���_��������O|�K��n����}�ss���������G?�Q�����u��%I��K����~U�x�;��V�q%�i%�i������

��_!3�|�q.�7�����v�M���v�^�������R��Qf�����:��:�m��e�bs�c���`9/Y�+k��h�Xk�c�����mI��g_�-���4����*f�������:�?�C��I��Gdof��wSZ��>��o��iV-8�+o$���Z(�J����R(�1�C(�G�m�w��������S�_�{����t���H�j�@��a�y���T�>::����R���|�_�X/�-����?���d���~�i]�vM��m�:��_����F����-��k�t9���~���������{�y���DB�����B����f4�e2s��33�v}\��
�Eyu�������{t�??����{�:ce��L��ofDj������/FK�d�|�ovI�K����`Y������i�ON)�����Aod��/��m�`��1w�S�@������q������T��\9�m2�mr�v����@+�N(�.����s
�sm�a�6AB�k����	�-� 8?�P 6�{R�uOj��
�:�yQC�A�n(��07�$�����V�I�UO���x�� ��5g��M��MLL���9sFg���[O��z��__��f�>��������/�l����X������u�G�����U��������}`�s<O��.%;�j������Q���7������e���d�`�A�1R�'Z��o����|�o���O6N��h9S6OWJ�/�%������oo��O���N�p������I
��1�~x����[8C,��H���"��	�(�������V#�����g��+#W����d<Q5�W�M��AkT+B�N��gJ�K�W� H(��'���Ka<k������r������T�0B{Xs�^��h[oo���c��U�?�������h��
o��U;�R��7(I�~���H$��G�3��]��������H�Ea�TZ�TZ�@�1�Z��
�RS�LF��	]9�lk'+����nnL��-��3�!����v�ZC��6@���%��l�o���5Z��5w>w8�=��?����)�����������6��~��"���#yw��?�Z(�����M���uv����n
����M�.j�e5�{�`s����R��#��1�(n����=PB{Xs�����b��{�Q<^��M�O��X�����-��x���bE��J��H$�{�n�:u��\���~�y���xB�M=������~^~����2^<!7k����XJ��+ZfY5�U��]�fF$������4q)Z�%���J��t�����F1��M�w�b[�5��s���U�b��O���`F�o�G��5��i}S`��_=����BB�k_+C��?��s�4:��O<B�kW%c���?����w���K�?s�L���w����-��x���?/������������s�����9�G}tE�T2�(����kWZv�0t����}���������6EK�����/e���nH����)?-�e��GJ����f�dw�pK�_�U���F����L����'^Q�zF=?���$�kOkC�v� `X���-��M���Z
\�p�Ap��S�M�P �r�k����%}��������|d�}���*������s�������u�g�~�r�����������|_���	]~�Im{����= /�h��7��:�FK�b�2�7�<hr��
���h�qb~���l��]bm���������:��O�Rq0Ss\����~��z?��b}���,-�V�o�p�1����
�m,�^�&X�A�P X��a�������b�{��^=���K�7==]��N�Wt�����������{�j�,<���4�������199y�si�L&��:T��y���Z~�bvF���'�r����_}��U,����5�u����z���uke
�rg��d������������s	����h)�:�������FaD,�J�����W���9����oU���������k���w ����k�*3�>-�fW�[?��Q
,,���V&���R�`i��5�L�k���8b[kXC�V��R��1�� _����{-
V]/=���\�c�;8��aX=|
���>�>qE1��0��}HW���$uuu����������L&Wt����-.������Vz�j�j�e~�w~G���o�O=���_�~�si���zj��`�������U9w��y���_:�|"�l[�/�*si���u�SR���U������XRN��,8�)9S�&��m�4m�4�4�4F�glB��?�:�%m�����m2�~Mr�2vNW��jhk�_:�����`�������XJ+t��D���?��kf_+}~���x�n�eF�o��d4���Z�]B�*T�@V�B���5Y6\4~������p�UP�uV_��������=�*!��5�?�����������?�����w�����\�b=�����y���f~�j��v���Iu�krtU�`$%�3J�gT�%5��������47���)��T����ku<�e!�����i�=9F�4Yu:YI�}�h2L�-Q�����\#]��S6�������~�})�T����Y���k���+�/I
W��f6�2X����J�9U�/
b�1���)}p�6�R��
�-�[�m��aiX{�a�������_������?��������_�xW(��Y'��/{�F����n��P]1��\�M�|��V�_�/�������mkW!�Fx��|y;5v�m�J�Be�������1����3�z�i���-��0��0��0�)�*5��)��O�Ml*���}�C��[s\�HB���sL���$�<��@�B(p����)�P�z������V�o����l��

��������?����������|D��+�R�1���+�6�-�Z���c6�<��U�<+��?��z�����}��=�����s�?�����w�si�L&���zjn���V:�^�XO�|^/��c�s��y�6�|�[u��9�]8+�����M�)������k��]r���_�;���t����������M?w�)*�Lh@���2
�=
S�
������&�7d���3_3��e��j�Ig<=t�_m?�S�����w�;�k0�|
����`��EaCI��� �B+S�\A��P
��~��5����k��d��,����9�@��1�k$��uk�;���h�����e�-Zw����'���w���O���d�^1�
������#?�#�v���/��>��O��������L&��y,�y^���=O�}�����m���]����\�tz��
��t��\����7��*/���w�s�{z���{U|���~����:!��wazJ��{R��Nh����e��k�q���:�I���M~N��!M_/-��~��%��������*��_p�Rz@j�R�������R��o���/j��Wj�_3�:�M��G��li���s�|
������z��]v6������y�������~(���_

��dI�Uf6�KR��\�l��ud\G��qd�R��+m/����N���1���_��q}`}"��U��O�}�{�|�������M���o����c-�]�R�b�j�^�Z����_�y�w+����`�tO����t�+��0����B�TZ���n�{z����I�}���v���^>�k'�*75Y�����.?���V�xP�<�D{�m�M�%��{�e��R~�,�W
�e�$[_��-
���h)���7W���k�|�8F���W��i����$��Z�������`F]��%�r�
@��H�+��f��56�p_B�k[h�0������;�08����sdJ�@������P �
B{h�'�|R�y�{�+k&z��_�����R<_��x������/�h������[u��]��y�\�0��jxx�f��v��=��^����?}S#�^������O�^��bUX%��b�����<�_�������������k���<uB�����CG�������E���]��W��0�fF*��2�������0%�MIcg�'*�zK!��R�����G2N��t��G�k����R0Y�9n�[�T�1�����^?�D���B���
\�V%h�f�R(�qd<B��Q�CK�8qB�x�;4===����#�����t:}K�\|;u����?}��������{�n�9s��\o~���:O>������:����I=���V���u��QM^�V���[�i��#��{g]������=���[�Wu��Q�_�3Dn������s/����~����n�C���qK�����o��R�,�7U
��M���B�3#���e�����������<�������O���N�py�����q
��1�}x�b[n����s�,��~=-�����	�a-.�Xe��6AB��t���2g������6��9�8�o�>}�+_QWW�-�����O?��|�������[�����[�Zyh����v���g�}V�|~n}����k_�����S=;v*36���/kj��2#���_��xB��~u�oV��������sc���.uo�K��]=yT��_�l}��_���+���7�������]���X�����#ZfY������G
}�!)��;��(M^��r��(���R��,�+oAn�3��uH7?V3���9.�i�w������M�X=s�@�2����V
K�>���C�0��[o�~����5�,z�ZS��*
���Me� �@w(B{h�K�.�����4444���{����?�����:���{�{�n�;wN���d��o[�>����f2��?����1F����[s��~���3�������?�_��_�k��?�x��������4F��w.�g�UP,����������q��O���m���Gt���q��~}����!���W������5p�^�^����*2FJtFK�����@��F��@_v��s*LKc������J��� _)����Zp��m��������Ka�q�j�S���];���vDG�\(�kl(prrRO<��$����ox��S�����
�4�ak&��A��J����U���t�������N]�2���}�v������o���s��=�����������A]���|�3����[�k^�m�����w�S���/�.����������k����������+��������9�1���iKvtj�������F�O?��N�����onjR�����|�)m�H[�T,�l���jWJD���������� �wC*f�<!+��F��e��Es�k�+�
��1F�o�.osZc�>�p�v�u���U�h����p>`�d��+'����[k�o,���B����6���
\��
4&j�swa@p%���r�8����jllLo{���Z�$���_�?���������G�G�����=�����L����}����'���W~�W*������������{��^}����}�����'?��%���?�C]�xqn��{��w}�w-�`c�%����k���a
�}QWOSnr��}�\N�<����xN����m+����c��R��h�em��W�������oYX���FK�Xzq��}����>�=���a�|���35�e_�������������y4�1F�JM�M8~]��`����6AB����R��@�D
��"km�o��s_�h`�"��������|������Y�������K��n������_���g$I�BA?�#?��~����\j���g~�g���/�m��k�~�Gt�s}����>�9�a(I��?�����?����O�:����}��_��_R�E
O����<m�{@������t��s��k���5x��O?��{�h��#j��o���&5�%:������0j�[������(TW�H7�E��D��Me!�R���7j\��M?yXc~F�FkO����~��z~h��{�o��4��R���"�����~�4T�B�U��a�R(p�A�P��0
�d�e�u|c��#9N�!�$��)�6.;1�p27�5I�s�t&e�Rr�u��H��D�"���4�y�{���OWl����9�����_������W�Z�6mZr��/�E�=��ff�����~Z�>��~�7~Coy�[�����K��_�E}�s����W~�W����������?��������m���t��i������<�����O�T?�s?������������,{��fG�;w���]��>��'���W.����9��F����mwk��#��vwQ�d)�-��o
��l#_)�W�n��l��I���7;�����o��K�������OS_����^�9.��5��'���]J�~[k�nL_���&_�&�I~v�5�M��&u�-my(z����P��
\&��l�`�?�
�
\�����9����������`�� �@�i��I���eo��T�f������2�R�v��X|�s�z���4_���m��_��[:�O<Q��f��=��?����P���������o}�����c�


���+s���w����}�{_����_�u=��sz��g$Ia�?����_��_�����D"����kz��B���>��_��<��z��1F][��k�6e�Fu��c>���
����+�����}�~�U��w���4y�Xw���uw��+LG!���ea�!),6w>�/M]��r�Te��}���,y��!�1���{�������-���J���Wa0�M��]t�L#/J�!�_�=��Jc����������7K}{�;7kZ
4Q�Z��|(p����
\��C���u��B�����
�m��4
��|O]S88��}o����%[���M&��I�&�3����|@�Z��������V���a
W������_��_[�yR�������}�{������m/
:s�L�}v���/|�����Wt.��#�����N�x�����	]?���b}�����^�����3�~����'��Y����R��h�e��o���m��U?���8#�<-��6I�-R���0_��^
��a�|����\�C�<sC���zx���x��\�Hg�n_����c�����-�����&��a���'0�5���@���9��-���R��S�M�p#L�9�dV�g.Jy���38��XF���+�#����#��
����y���/����/�B�a�G}T��?�'���o��������������~��t���������7��_�E������w�D{��}�
���kt���u���*����������{]~�im�P[�T����3��b)�-��E)3T
�
���
����(���2rz~��)����wn���7+���&��S������~���h����c,�'o�8��K7/HG>�`1�mkM8~y(Pa(�/��N�`�/�(���}-��1���	
�-'�*<uA*�9`�W����?��������������]���������]��?��^~�eMMM)�Lj��z��������y��O��O�'~�'t��I=��sT�������#�(F��x���z�����C:����<���x]����^9����8����i������j�����1�s{��+L�������Z"oY�K��r5���&���~����������	m����>2p������}��/P�������I��W��Ly(PR���s���0_)(?��
�R(p��X�V-�yv�@�}
d(�����Taq(pa���eL����-�Q�^�{���
O_P������L�V��qlh���z�;���s<xPl��w�������|�>�]���'�������
_�O����W��������5 ����K=�R���m6����C|����5���9���~��bS�y�A�����n~���g/�������KN��K)d���F����������OK�tc�
���������
����eB�������.O��D���
\���1����V)��&���<��x����w4���&B{��1F�;w���{5ucPWN������Z�^8��g��u��z�����mh�H��hxp~{P�2C�A���Ra�!�Mo�"/5���RXH�7�lA���R���r�7E�v�[���R�V)�)-�w��cQ3^3�'���|�9��������_y�`F���li��u�M��f���j��o$	�&� �y��	�&�t.?4�=�u���-���6������i����C�:L^���U�{z������#�V����rcR��h)W����2e�|Aa��Ht�k������W�8�]s\~t@CO�N�=������dY�o6��%�>��t�����"��K[K}{�{���fB�5��+�FY��>.���������@�DXp���%��n�yF��b�����������zX�/���_PP�/�������.?�O�v��6?����j����]�2��Rv|��/S
���D�-�M�5�����5s}{�q�LZCO�^=�������4~1Z�%�%?��wwk.~��`���P`E���o$��5;(U��R��[;��p*'{s�Aovi�fF�TNNG�%���6�D�];~��:�j]�]{���3�}���L�����W�>�M���	Y�����#�z�e`����(�������������6=x\��IM��W�.#�AL��_���/�c�9-��jn���V��/D��}K��	@��>X#�WO(p6P���a�A�P����P`��_E��#�����1��D#g��`p\N�=�*��6/��]�^�m>��s/��������k_���������K��m�h�d�[����m�R�8S
�
�����
u�sA��)��<"��j�h��*Nwh��r�5�����>8�V�6h�����y

^�k�\m���+g���M����
l0;�]�)pG!��9�������}{u����z��&o�������(����?~C;_��:�77w������M�F�,k������5��u�~�(�VpO���&&��������`��>-u���i)������u��Un'�����+'���zh�R��c�B�a��o�P����5�2CC��YYk�?����l`����W=;����A]=yTc�.�����+�u��eun���Q�];���1R�&�m�b��4������Q�������4���{�9%6��R�4���?���x��x�1��������;|��z4
�s��hm��C�0����	�a� �=����	w���Ctn����[53~S�N������09xU��*��G�Q�����|����Iz���~M>~ISO�Rs\XLh��������NKA���\F�K��h�����[����&�y��	���&���
�}Y���RHp�P��
��W(��V!�p�Iuo��7�U;^����pB�_|^A�P��37���7�N��}R�|H��//o����1�Q��w*�%���}I�X#�j���nS��W��m�2����?���6J���y)[�a����{�|sa�TY�_i���>�(c����eZ�03� ��Mp�P`��p#q�<�V!�p���������]�Z7���k�Wa&S�����.>�-�r�m�����?�x*����z�_^�F?yJ�x�&����U�Q�����-i��L�����q��|���j�~��n��olx�1���^(0���Rs`�s?����*��A
l��+�Nk�	����������m�H��pB�{J^���oP�����t��1
��W�V�{S�g4F|[�~��F?uZ���5�.Lj��V��~�Su���46�
S�R/7�t�oa�_,}��"��:�p����6���&ch��U�@����6���c�/)V�)53��_�k_��q��n�9��{v��CG�1���3n��W����c��y�z�q�x^�O�Z��Sjs�q���l���F��2��}j\IV��
vZG�B������k�������f�y	�p�X����������nk���=,d���6M�����?��F/��{��K�5v��:7o��C��������X���h������v������l�h���T�:���/U
��;4s}�
��*Lv�������T�s\�-�k�^zb��I��6��K��T��g���Li�L��~�v~9�6?-�o�q�[���|Z���NL+KW����[�����okw���`	��~m�w������1
���l�����AM>�E�uo���G���~9������u[�����N+�k����G���8.��%I��~M]���xO���W~�O��>M]��x��:v�S[_�c�<T
��EK���7� �Le�o6�Wm{X���k6�
��R/�+��j�������X�#)�)%{s���2��r:�M?����XV[W����-����5��	
�~^A!_�����:��_��g���i������X�{�4�S�5��S*fj���l�����M��k��.eol[��
�==���-W�}�)����\��R��[y��J��h�WP(5����ej</k���x������R/71��k�������q�������W��K-8O�7�
Chu���t�k^���^���N����T���`U����S��+G���}�u�!%��&�X9oSR���!���K���9��th��7H2�u�������U���k��6�|����bn<Z�����V
���}���*��YI���b�y)���cu�`�[���~���noPy�[O��5���1n\2��g
�-�@���]
Wp3�r�v��l��@u���b^<�m���4r����8����u��z�9]{����<��+����+��]�|p���^���^\"k��U�Oj��G4��'��K�����6�1�������
��^y�oQ����A}������3�s[�$���:3�������Z�S�k�;�&���c)�7��	O���\�,B{�e��j`���}������'��������a���Nk������S��J���6y�@��1�|���mIi����������q
}X���Z�M=�*1N:���zK6C���oa�ofA�_)�g����jl �'��^n|q�/V�=X�=���6����X�L�S������y����9b����W&�%���#�m3�h�];�������G5z��dk��U�|Qc�/�c`��:������4���m_�>vX��<%$��s�����<��t5�<���I��h���RP(k�����l��]����h����m>�7�[��W��KF����9I�����������NG���n	�=4TG������+;9�k���K���rj��^������[�Q�����>a��R���4����_�n������=<���=M=��d��%��mS}��P�s�|�����������g�E#��7�|�o.�W���<�����X����o�O�S�N��q�v)�
{�2�3@S�uvi����G���<uR~>_����q���'t��'�����e����&�X�����;-9��7^!��*s��T���A����|�_��a�y�a5�P*LGK��X����������=��P�mR������������O�@gg�EhMkk��W=��_�/�����)?=U�����.=���r�m����=����&���x=�������paR�����[r>���J��h�WPX��Y������������7�c��VSX���R//Y��m�K/�������@&��;�)w�S�TN����xV�dV*��b���6��6�[��t$Wo�`B{h	7��i���pVWOUfl��}�bQ�N��'���~m?xX�M�M�1Pi��pk�w|X]��67-���Cf&'��O��������3�����m�+f[�VV�����X�;�*m~��-~����dLS�+�t$�tl�$Yk� �B+9Fr~�
��Eh-eG���W���4q����xN�����
C
����^~Q���G��J����aZ�p����F�y���kd�<9���6/ZR����������D�r�NIu���@���a���_��_Ph��X=v�}���j����/�9�X���sW{�N\]�Ua�Q������nM������pV����o�rI7_������~��zv�+�8M�5�T�Z�N����DA�_����p+�|��}�R���u�����J��h���1(���[��+~���BF�AS���	})?-�r�B~5��5��$��U�����k���o�n��������t��i��_��S�7���}Y��.m?xD{����\4������L���
������vtMY��J��l�o����-������1����]���6j��
�-�Um���T_ {�	
���Y�F�%�C}��}��fC~�v�MH�l`]�jf���N���Gu���j��I
�:)?��k�����}������������; /�l��q���V�tQ�tQRvE�����������l�ov=F���`��%�����}l(�U~e�}���}�_l��"+i��]��8�W��Wm�o��,����X�M;^���:���^����)?5Y���lV��}RW�?�-<�mR����3�FG����v�����W%��,�U4��������f�(LOK��o��/��6�Uy>��^fC�P*LEK��}���0_y�_{������wB{X�\/���j��5z����8���p]����k/������}��<�tOo�g���$\�6O6�ACA�X�SE�S��j�e!�*������q&Fi�r<)�-�

�!���_Y������(��E)7-����|�~���^2
d!��5�8��v���{�hb����8��������P�g�h��m�k��z�:�l�14w�~����+v�e�tR����������0�K�m������|+��3�A�jA�*�&I������%�]�xk%?�8��(�W���g��V�����h�;��a��-~���q���`�0��{�]��v�2�#�z�����/�p��e��rY�}�~��z��%�������hih/��Vu�}����V�*��D!�p��������|�����Ww�|�p��p������v���~e�~e�&���u�)�-�
�(�W������|{��?��-��L��8��P_���@�]X��	�R��O���m���Gt����q��B��k���!���W������G4p�^��5��R��5��WZw���+��12	WN���Wv,�e���p�-�V��7�M���g%��dW��gb�LE�/�������gnS�
�q�x{��+(.��|^j��4h�R~2Z��&�B}��������$Cx����d�k��N�z��t�������5x����l]���&u����+�=���i���%�M�1������;;U�����-������t��g\Gn{\n{|E�E�~AE���V?[e[8��6h�h��
'o������K�g���f&.)�j[�[�3�5��In����o��Q;�\s��P�\��LY����
�
�R6/eo���l���0_Y{��mn"j^�!��
!�L��#�����5������1�&'�������sO���g�����v�!%;:�<c�Go�[��B������~�zD�~���'mZ���/k�+o�+��l�ma�Xj�k��Y��d����o��'��k|�]M����E��Xe�/5�n�A����KD�z����R1�8�����,����6V�-2���U�|[���������=l(��i�����~�^���'����P]�����S'4x���v����G�����c=i�������=>��s�W��:�:k���q�����*�|Z�f�~���/�����_��LL�������|��T��U�*��h�[s���iIu������Bf��_�������jl ���^Nl>�W�[��7�=%9����!���dG}��V��]��~MWO��+����Z��{Y#�^V������um��F*H����[�
'W����W��w7����1F&��I�����v���a�be�oA��l��Z��\y����-~���m���!�'%:���JaqA�/S#�W�n7h�6,J��h���,���n��
�y�(�	`�!��
�������u�2c��z��F��,[g�`��+�������~���v��q���N��c�����'d��k�2m�����t�a����r�_Xj���+�5�E��<�W����e�B���W0�_���������Z�f��������Kmq�mS}��P���[�*~��~���c5��h���7�8�-}��}�j��Q �X`���#������]�������u��)��b]�fF����K��~����+�#\u��mIk�_��>���=�3��=���tf��2����'��}mq��oq�����<hK�wl�_��0S���r&�.n�[�+��������H��hI���O��|35Z�����o>]l(���^�� �W��W�+����X��R���~:��&�,��rp�I�w��G����F�_|A�^8�b��f�������7u����u�Am�P�d[�g��(�%����Wi��s������W��w���N��#7��y�~9���/3:�O���y��]�������?�wj�_��(_i��Y�����/U���-&�Ji9���R���t����o���{�)���D���M,����-��no������K��K��H��*[0�6�s��y���!�}���`�"��;��H���^�m>���gt��c�M���������O�������>m;pX����Nk�����{�=<��o������������7����=M�!�*��((��k&]����{�uv.��b���V�R�_�V��q6���Y��E������p+Z��������W��WZ�9������.)�U������`_Y��f�_V�/P���y);V�������+o�+m��m�yQ��
i�b�1~V;-�.u��v�Y����I�}��p�s<O[�>���������r�9M��k�0�5x��O?�������������c�i�����=*^�h���
�L�puZ6���1m������C�����^�c=31Wn����X�~s�~��}35�~�m
6hXi6(��B��k��}UZ�RU�~m���G�_+#y�hQ��iF���a������_��?7��-g��:�f�[�+������RQ�S�Hg�n_����c������>���%�q��s�z��W�7u��Q�|�b};[��g5r���������{��4-�ab[��*������@��2�����y�����Wk�l1�-�U�JM���@���n�����/��]M���-h�+o�3e�h�k2�DA����B�,�7S��W������w=��T���z��*-~5���i�k��y�a#��������1�������#���4dj��=`c���lS��m��9��'�j��K�aX����h���{z�����w��i����cd���24`�1&
�*���Za�_`��B|UZ���J����~�@A.Pp���R��}5��f�IO�!���'%:���JAaA�o�2�W�m6��
�w%(DKn��}����_�v��m^2j^��M
J�����,`\S~Rz�����+�{��Fh�k���%7&%:��Z ��G�=�����G4��	]�y�b]�f�F�����g�I�<�������g�5r�1��������m�+��������/�������
���7��I���������*���f
e��%��mS}��P��Razq�o��oA���k��XM~�>�o�q�Z�RNB�ML+o=lL��OK�����l���m�����a�Q��Y~V:�G�#?��vJ�
���e7^�N~V���4x��a �-m}H��j������Wk�pGH������������_����83S����)]���+G���}�u�A��RM�1�_��~N���o���<�W��oq�O�m,[���
r�Vw��%[�*�~e�h�k �H��h�W�~�����[�
)\yt]�ax,L�����'���V���J�}���_e�_{Y�_*Z�5�#�3�E�x����^zL:���`�[�W�����H����o���.|#Z���J;^/��g����U��;�O��C������3�z���7�����u��3�v�����mR[gws'w��v��Ykeae�_������B~���;���NNV��Y��W��o�����L�i�{��8n�������P
���5�e�n��a���j
})?-�r��}s��a��F�X[�l�����{����-�����=�Dh���1�K�Az��+�����O;j�{��I����0�q]m�������u��QM��k�0t���u�����K�QG��&��c�L���p����k��v��l�_�����AsMK����
�+o�3����,�[4	�v�����%�]�xk� _��oQ�ov=+i��]y)���cu�`�[���������%��?��qKoe�.~���#����������4U_����!]��C)m~�1s�d�Q�=����{5ycPWO�����l�F/����s���]�Q��2+�������m��m��h���/�|�����ja?_�pg���b��X�&W��7�3�Z��R�����o����d����}�@����|��8]������6V��o4��o��|�%�J�i�bS������u�}Kk��F��������K��7�xS���S����@un����m���M]=yT�g����U(M^���U�6�j��#���G��6y�����yr��ie�Z�������|�.j���l�2�%Y��#5�[��&�����p��V���L�%���+���%]�>�_%������y!#�
x���������qi�=pg!��mf,j�kT`oVn\���K���R����,)��I����i������~����37G��7��K����xH���//���&��g<GnG\n�
����v�l������_
�E�l�� �Fc���������9�o��
�-������i����I��h���RP(��MW����75x����W��)���1wd���^�G����
�8�����3��q*���-�V>v������S���	�������5�5����7?/}�'�s|`��V�OIAQrcR�C�M�H�������z�n�yA��?��L��}�i]|�[z��3�����>xH��T�g���cd�����$4��7��Y��h��e��wd�)����0��xWw�����uo>8�H������D��U�[�''u��|0����VuvvJ6���|�_���W�����_Y��Zg�dO642��q��}����W�6��1���j�����:���F\8��{a�������"=������_H�'�����X�n� ���t�Yi�xe�e�[�����������Wk����x\�����4r�e]9����7��7(�u������1
�y@�Q[Wws'@�������-n��k��
����~�PA!�`"��U4�����*����V���#�R�R����������� `Xl�{����\���d�
������{���T�s\�-�k�^��6��l-k�����.��F\p�jA�Z������`"����j���h�y��������W��k��]{Ln\���h���*�x��������V�w�u5p�^��y@7_���'�j������A�gN���S���K�Q���&���g��n���.��Vm�Nn�+*��<`d���E��������;��-�xQ�w���}���&���~��?��Pkv�_Sw�0�Ss������)?����{�S��sj�n�|�6,�YZy+��aj�jF�����#�7(�8`M!����K�������h��efL����6����>���u��&�j_���?{�Yv�	��}&��7	$�H��@f����U��DJd�l��i9��Z�g�����9��^I�L��tV#�v��[�&[����D���(R,�d�D&2��!��	�{��/<"� ��w�;���/� ������B���~���#�x�W/aa�~��/�����}����s�,�{�by""����@�]P�[h��l������a��� ���k��v?�
��i�S|zf��7�S��K��rOSa�K	���a�D�/}������a�t,�:��lw��[n���x�&�t�:T�.n��J:
����<$X�-��%F�������0�C[��������Q�\-.H$%�UXR@.�*�:��_^���,*�	�]lf��g�������`�-���t�*��ei������+���z	��������
�L!03_Sz����Q(�Z�3&""�}B>�OZ�;V��V�
�~i�~{�-a��W���������Ez ��A�l����u�B�������T83l���'aG=�:��L�K�h?������"�bI@Z�����f��I_��K��w�0tXc-������&�5�������������h�`b���Z&/n��\����v���8R���'�y�Uty�x�?�6Oh��������h���47����7��tOj���z�m
�$Tf3��?D�K3^p�����}��=*+oc�<���=���W1}cV������"���wx����}z��OAs�HDDDD��PU�����K��m�3�����`���(���S��}9������~�
������=N`o����fi�w��<~�it|��Tp��
t���l�����ki;���u���o��B��K����F����b�
�5F�Z��D""""""""""""��#"�)���������B/&��y���:�C�5���>�xW�T�#�_*�l��:K%)z� ����F!�|��mWx��=!��4��*��Y��g����ZJ;6Q��>�z�a��uL�� �V���Xh
c�^�������it���WW�3&""" ���RJH�N5���|��}9�2����J�Jo�u���9Z�4���)L���J�Wa������j�����`�t�_~�d��i�0w�It>�&T�t��T�9
?��Ks���p��0�A�u��\�3Fvp��v�xk����n�#��X��
��F, ��i�c��]�}mC{DD�
��M
?�=�������7��5���1^���f��D��6��Y��m�++$�#���,�8^�QY��m�����w�%��?/��DY4�=������������--t��a��0�F/���q��9_Ss�������B�R��T��v?K��d���u�~�f?;����"���\Q���%��n�CF��o����[�������S��~]���kX�u
v�S�)����O����3_��(�V�*a����a�|A���c)��[hQ����E�kI+:�������\��-�(�#��3tXHp�7�#"""�8)+��_YQ��k�������jC{DD�`�V�E|����X5��H3��@&B��t�(�=���+���T<,X����q������0����q�+����}����QG����1,O�c��%�':V�6�����o��� z������gLDDD�"T�N�Z��|\��/�#������_��n��~��4`��~C�x�/W�/=����~e
��w!>��lwy���� |�������������y����(�#�d��]�_e"*�=��Z�o\D�B������AI�&Q
X�fF��# 0���6����s�$������������O���j��g���������z���j������W��6+�,X���"��DH0q��W�����2���'�QU!��{�������KX���Q����8�
���s�,Z��!x�������Tl���
����d(O�/m?�{�)K2b����
+MN����~�a���B���(2��������m`/4:I�>��aq���ucl\�b�bv����D��L�&�����j�5#�h@�0�X@�b��`�����n!�HDDD�i�&0�:�<�3,�s�����~��E��D�N��������6��Q5�OYF����G�K�K��:���4~��0��Y����I���f�,Wp^Q��`b?E_�/|�R1[�%T!�R�����f��'���DT
��8��O#X���<�s�UX�Mpv7g��mlF�������"""*�P��.������RB��T�/�sZ�d�V���2�W��l���@��� <y��|�a#6Q��c��5�]u��hG"����?��6������@B@����D}��Ba�2�(��v5�=f��n����6�������y�s�"�*��Y1�|����5��+��H��.������c�\��Q51�GDT
B��������j�lP�U�����{n�O��`D���bD�!�(`�3^G68.��n��.mBF�Y�T�i��\����v���8R���(:<�����m�5T�~��W�=s�m���p���{�IL_����Wa��^Y��7_������� �N���*��GDDDDB���M��l��n�K���h�K�����M2l�
������������@hP������D��9�e!"S��}�@��
'W"��7'�i�(���E�.$HX�E"�5$T$�P�p5O�L��m�����a1���}6���.��7����8�9���$�FDDDDDDD�ch���Zz����+��(�47x�����:O�u.�eVt� `v��������s��M����~��.�b2��w���c<���P3�]�C�wO�=���<�����=k��ry}8p�i�8���70u�2�k�k�Bx���0q�}t�8�}����/�n[�~Qk]�_F�_<�F�_�f
��������vak�S+ 4P�����4"m=���~�����v\�z����>NT�����JL(�vuk����7#�	.�
#n5t�k�m�(&LD�$�����v�GJ�	V�E1�A1�9e��HD�Xp��g��G�����?ap��������J�#"��3���������^:����UsW]e�K���!�
�s�<�w��YaS�go);n�_?j�	�c��y^��������3@�~�q?���4tZq�������'Nc��=L^���BA�Z�����0um������Y��[�|�DDDD�#���hP<��4��W_M���/�^��Z�r5��������MH@6`���K��A�T�/�Z�
����
f���Q��/����v!�@�n&���%
#$�F�h�s�S�E�|�hW���6C��4�nF����0b��c|_�&�E�5�a����f�������5DDDDDDD��Q��E�6l�*��P#��>�Ud�*Q5@m�
��SJ�6+LW�6����_t��{[��t`"��O����Jm�6p/_�V���������W*+EQ�~�����#L^�����������wn����h����3g������"Tj�jC��~������������L�pZ������(KBZd��'����������+����0�\���B-���E"�E����.�����u�n2F�u����(�����2�z�i�+�h��
p��3>���Q��|����w������e��E��w@�!Uw�J������v���_~8��]���U��/?������K�3�2�~�]4��Y��������._I���6!����yV�c��%���s��`i|K�chh�D��9�8����Rx�_6i��`_z�/�k��j�c����g[���l!$"�����
���R����l���M��	s�hQ���J�bm|�@D�"�T�x��3�i@,�E������B���<�O�3�)�3#@��v���Q�����d�����7��o`����@�u��U���\P5�Y���T�����O�3_'�k���6V���x�6�	*E@s9��2m����h��_�P`v�/gH����h��65|�����"���?:�_=8�fn@3,�s�||�N��������i���*B}[���Q�`rt�o��m��987���]x��szG�C��_	"""�R������v���j�����������2��u�B�B"��@8��(�����78�yqm-�+#� (�8}�$|��[s��
.�	Y���'�^���x8��>�	CB�������6iQ�d}Y���AI�&��X�n�<�C{DDDDDDD��?� "�]RJ<~�AX����0cQ����P�$%G�O��i�P��������[(Lfs����$�{���l�	���!���������X5�e9�U�����{n�e�uB�2�������S�|��xk_%C��cx��8���;�$�o\����0��5iFV�q���0>��O
���)h�
M """�B^
�w��J)1��?���f$D���[��6�����BHDD	�ht��[c��'Z����X	I�>H�/��$,I��f��-�(f�KD��L�&�F�=T����\]������!�
B���#��Eq]hp���������`y�|��[~��W�U�����������="�j�����������m��(�hm�UM5&��9�3�iz��0L]�C�ZVx0;p���/�R@���������
n:�z*7x�����:OAlXw�|����>OZ�o��SK�JH;������S�8���obr�2��@A��0��c<����'�}j���2�1m���zD�.WlNW_��������	X����0mHKB6�e�m�_'�}���5�U�.���B��8Ua!��Nx����h�
V%�X��]��F��������c�$� $Xp1$LV����G�#""""""�������2s�I�j�mY��0�H�������p�+�6�j'L5:�@-GH��1Nf��+$����CQ�������V&H��b/�9
�V&��I`�Y���E�����%'4te�tw;��v�"�ju�^L�����w��N����=L^���|A������L_����G�s�,�ZZ�|�DDDD���

��7��]_����YA�x���4eZ(p��`|[2\�DDb�s��%S���BCZ���A*�-$"o��+l!$"��)�5q���oN� HXS��-�(�."�����j�����Q����p�i�2M5"\�<��:=������-����v���8}�q���t�CQU!0��&��U��O�1?�E���37D�����a�J���Z�:	��e����x:}���x;_O<������Y���@��D(
�E��#X�����KX�|T��R���{swo�y�������G� �P;���}^I�l��\��N�GS�26i�����V��Z�C�l!�Z���x��cS�(�OP�
��i!D�l!$""�"�8�N��T"��D{}80o1Op1o1W`�����u�hQ���FQ1���(~�GDDDDDDT�U���������j�
Q�,��e��!��;
t���?����t�p�\lX����9�$�'�}kse?�b	3,�q�||mm}�������R����h��ESw/V�0y����-�uqi�!�&���=g����A������~?bc����:���UW�yv�
U\��0�-��gH��|V�\��Bd����f�	&�z��![���j��P������`b�a�|����lQ�s�S�E���v3��hVsW�L�������������@����1>:R�9������O`L�	]Y�G���2��u�i���R�
���O,�'y���8����Q�������?HQ��Ng�>�>F$-�7����m���!4�,��soWt�����������P�S��������>������fo_�m��:��~�7���sf�GN@���"""�Z���^,|�Z��y���sP��B�B��-��E�B�"O(p-�Z���BHDD���Yv����M~9��	�����	EH:��K/�bvp�����Q%��Y"�*�:r����g������8wn�-3L����@��42B��������f*���-,hB�����BJY�;�������"%^��%��a��t����6���������j��/
�U��9SO��~���=�$fn\���+0#����Vp���1~�]�;5��'NCw{�|�DDDD���x�)_��w��-e�v�����`�����BHDDD���X����@������<��_�y6$%��0�A�\���F������[k�;����rA""""""�J��������s/��o|�r�=�B��JB@�t�������#������$��*��D����b�9�[
c�T[�a��"��"k�0"a����N,�kq�}���'��2��K�����w!"+��8O��P����'-������mv~��lt��g�D���x|�&��^B$��@F$����`b�":��D��Ax*��3%5}�0�V`J_���]h�D������B���0=L�B����B�
���0c|�Q	���cW����"��k�<
��	�]�l���TW��#""""""���#"����~��8���y*%����h��/�<�NM������%m�	���-�f������[
�����V?�n��:�>���:Ru���Y��R�|Y��<&�T���BH�9��$0�n�}t_*���I������V
��a���u�$����KX�\���ib��L_���CG�s�,�Z��|�DDDD�M������x��@�KwS������P�j���D;�^i!�����ya�h�7A��-�Tl!d!�NBq�Z3����������MP�������*��="�*z�S��_W ����>S�9�xBQ��\�\.�}u�>����9[M#�#�gfnK
f���m 4MV����}�����������u�������=E���t�������u�V�������[��u�[�7�������p��0B��mg���=��/�����J
~`W��������F`f
�W��41^��Rb��m������>��E��^�EDDDTAzW:~cs�y�$�{��������U���Qi���0������_z���7�IR�-������f�BH��B������pho��""""""""��������'q��q����6���^���O�m|�=E��V���}&��R!�um��d��4b�����h��')%f�����;����
n_���������Q�s*� �7!�7�<���B9#�2�|+�����k3\�s�����L]��]u�������>w}e�yB�q_��`mq�W/c���������X�G][;��9����OU��U��~���C������������GD��[ss��
&��r��B*#�������J�k{���Q�0�GDTe/�70q�*V�K>v}s^��o�|\�JPT��B�g�}�=����
�����5�y���s������?y��F���{�������@h�	�&�B}�`_p��K|R��4�,�x����r��5����mv]K����8p�iL��`��5��Y��k�s�������G��!t;U�E�DDDD����h��u ��#�
>�u���{�=�R�3$"�]�l!�
�����Z���BHDD���wM���X��j:��GDDDDDDD�w�&&"��?>�;��/������j�����������6�h�"�e�����^���GX�|���|��B��pp�<�����ww�}Y���Y��r�c����x�/��/���T��Yv������4t��|=�P_zs����5����
8����=�L����+0"��/F������.����'�@�l�%"""����h��D��5�F�{Dlr2��	��jp������`;���*�1ec![�
vx�i�8���"! ��4�o)38�B""����<V�y^(�DDDDDDD���="���������_����$�{��-����>����rD;���^����J�OcC���+����%@}k�[��N�S__�3�U�8K>��T3_Fk_��`��V1���(�>z]������>mw43jnz�>���Cx|�&�^B$PX��D�h�]L^F��'�}z�������N��Cc<�'���Y��t.�v������
��<-��sQ�l���
��E���d����� [������:��2���k����������*��="�����_���~�?����oy�����?�l��=���='Na�����U��Uw!07��qV�q����?�[�`�������:��T�n�5���,�'so�-`�q*����7��*{��0���[��O]GZ��7��/���(�q�[!MC��S�<��`��0V�t�m���~�7F�v�z��E}[{�������'p!��;�)ADD{��l!�
���jM�����}6E�
5�M0���B�f
�BHDDE9�	`�
l�����4H[@(B5��?'n?p��;W"""""""*C{DD5�����������{��&n�|��'N��O}��>Y�3$�]O}����
��>�O�>���)�����a�_�3���R���}S�o��W�O}�J���[ZK�vE����7���X(��ob}s���yb���L
����wZ�/��q^�{w�58
EAk�a�8���4&�c��������`��4v����sh����[�������hG��B[�ld!�:[h!,��Z�C��j!����-�DD5�U�����p�&c���}���!MWr��bp�p������^��9��u�u�U�]Q����j��sO���'1?>�������x|�."k��z���q��9���������0Q
8t�I�x��m5Un��s/&��-�=h������L����k���0����5Od5�[?z�~�&���?��9q
��o���-.�v�Yr��i�[y�L�n����-t
����g��������B}i�}�]�Z��!���������������{Rvk���	�LM���
=g�v�D�5J	D��e�����N��������*K(�U�-����.�B�e��>�O�K_����;��rK�C��Bt�
��6��������{���9
{g?��KDDDDDDDU��Q
k�����0��F$�0��:t��Xey�s����W���X����[���~#�6M�q�������y��p����w�2"��m�=?>���1��������=y����?x�����`�������l�}�����������\�%g���{�P����;�|��}�����ZZq����������k���c��q������?F��!t{j5������_&/�#@d9����z�g~�<Y��$"""""""�Il!d!U	[�BHD��������c��|E[n���x�Ch��g��7��$��������P��B��>���>���m����������������������m��CKN��S8��O��-������N���[7��bF�xp�}<��>�����C�p`��N
��+��*�����%��JZ�/��7���'k�����?�G��q�g��e5��{�_�p�������w���y
S�F`�C]
������K�b��3���to����=��?�/��'�<x�Y��#��Y���H�������������Zc�(f�f���Z�Z�Ba!U�^o!�
"���ho�M�a�7a���ox�����������UW��#""""""�b1�GDDD�J{_?~�w�W|�_���4��7������h��^KQT�;r���O|� ���������a�.�o��s���w1���BQUt{����?x�� ���#���it��S����q�{�P_"�.}K���V�������;�B}��[����j���n�<������{�W/!��\��f4�G�����K�8��O��/�]DC��w~�j���_������3�ZJ~DDDDDDDD�+���0`��{��}/=	����m!4e�9�-����������E��
"�����b�k���W �fI��1<�W���U	C{DDD������W�����_�����[��s/����F�
{������3���3�CJ���GN���EL��e[��,L����Q��W���g�?t�g�kl*���-PT���Yz���Ol�	�&�B}���xk���yoJ���2y1�.�'��I��2Z�z��UE����8��`��%�tV�ea��(fn^Ck�a��9��������fF�/}Noo��_��~�k�C�DDDDDDDDD5d/�&�u��7>[���B���0��-���Yk��0Z��^�������������%��������6���J�?>�[��'������0qc��c�?qO~�38t��2��sg���}h������0bQL^���a��cq����Vp���p������?���u;U�35�U�s�\���S�|���P_<��:[�s.��9K>��������>�����z�����2��������b��]4��A��94��n����Q��"��'!8
|�c�����Q��B�U��f��f!��a!�[�BH%���{����dbX~�Z�DY�'""""""���#""�]���'q������o`��m<�����>��zt:�}G����/����*����N+��y@`�1�����#����5���{x<v�~�+�=^��D���k��*�[�r�ow��s��1�@`*��/��/����j
/:�����
h���q?����>��p+��m��;Y�����$|-��9sm��@Q�p'�����W��^Bd���~��k)��DDDDDDDDDT���f�1l!���Z��������C��	)�pt����B(���l!���7�+������?"""""""�$�����hOh�����0��F$�0��:t��&?���u`��?���4l����[�2���1s�.
N*�`D�����q����u���9t{�i@a�����������N8l%GK_��/0��P;�m+����(�>��
�b��iX����B����0����}z������
?�������		�nH�BH��b��4�i������~>DDDDDDDDDD9���-�T%����B�������R�K�ZUBga)_{T�y^��Q�1�GDDD{�.�.o���p�����I��8��~��
�`���d������_��������Px�����G���S5j�-�6;K����X&�:�=�������Rq�A��|��a��)L�?���X����U<x�-<�x]����y�Zz�_�|n�j��kz'�}���cM������4+�:c

�	��FPg����W�3?�hA�����������h'��-������!
�R���BU��mC���.i!4f�Td�����5�]u����������#"""��|�F�x�E�x�EH)1?>��/���aL���4�>�m#<;����~�]�5��������Yx��{#T�T
h��,x:�>��x3���������$`p��d��o�;xs�AL�_@X�(�X��1qo�w�#4�e^���O�:4�{�7�(�����lxO��C����z+�#�����_GK�������������������d����l!�WDa��@���yn�X&��942�GDDDDDDT1��pB�8�����>�X$�G��bld�;
z�����k���^� �E��9����������#.U��h?�,��6��j��j�[{\��R`�34���%,y�m�K'����`V�C��u�L����������>������5�9��� ��.���+��pj������@����%"""""""""���-�l!�*���
�=
V���������������v���������O�gg062���a������7aRb��m��������������<[a�f�(
P��,=�s�cF�m}YM}i���-M/ �����-\��lx��'Q�]����i,�N�����h�����mM����_CLk��9&��
!�>���_D��vG���x��h@s;�J�/� """""""""��kO�Z2
d!�%��UH)���DDDDDDDTv��rM�]���0����2
L�����.����m�
���;p�����^rZ�zN���r��-�n����C����@x�	�%�}��Z�&�� 7���?���/!��a��y<�;)
��P�s�!�b3�	����(���wa���T}����bZ#F��1N��Y*���r�t�����Q��_��M����DDDDDDDDDDTA5�B��+��0�`r|��l��&T�R���	� ��d���������?p"�BJ	���%�@S�~FDES5�'����|��������%'�w����m��8����p����������d_KO/�nQq�|-��o �>�	���}����&��2�g����7���w�n�	L�?
K�t*!W���6�:W��L�3%�%����~C������6����%��`jz(0W�o�p`!a�
���� UM�[��_��|}��~�����g!m�4%���UC{DD5l%d`b>��U�k+��n]h���\������_���xuM�8���8�����������W����"s�N���F�	�Z��?x����wf���R�
��T
h�u�|��T3��#��8�2���71n��z1����bZ5}�D'�k�F�o��/~�lsl�u�h����"[�*���3Q�nn!�ZY�D�n��x�D""""""�Ja�����,Eq{j
A#�>�%1�a.���Zt��CW3o�FD[#����Y��:���p{������������9\������BQ���q��o�:��@����8�,i4=��o^���Q�V�4�U�|��C#h������iF�Y�A���*Q��)XB���@d����l$"""""""""�U���ban��9AO"""""""�����jH��qe,���H��.
���2��z0���^?'��K�]�?�$^�0��X���7�]���WaF�^�%mS�o`��
\�����o��3C�:�����oi-�;!�����8��O?������r	������d����b�m�zN_1��\Mn�"�Q[�f��*C�DDDDDDDDDD�c�������1�Z�sq��;K"""""""�����j����7�1�m�3��| �g�hB�O/���^'�@KwZ�{p�g>3�����2���a���mk��j�~�&n��M@{_?�C��9��8M��3*?!Zz�������L^����{U9��� ��N��k��]��:Kt��se��@�
����16�X���KJ ,Pu���wd�B������z*61�GDTV��y}	�%K2^�����%|�T3�{DT���C800���.����%�����K��m�����1�����W���F��8��C�����;@R�5tt�����eL�^��;7!-���0��3����0#��?�/��������I���#�,������,d_7�)D�7�^�~��L����6O�o�9��9��d����������hG�
�#�����7�^�����������="���6.�\.Y`/��$.�X���p����FDTJ
-m8��O��K?��0{�.�F��`�"f����[o5�Q�~�����;:�?x����wz.��to�(���	G����=�+����*�����o�����j�P�:T]���P���PJ���mV0�E����n<�m��}��c@�b�����=_�o;
��G}�c��A"������c`�B�}"�������?�������T�,��������v���~?bc����:���UW�y�������(��="�*�2D��z�e#���� �<�X����rQ������������b|�2\���a�.�ok������w1���BQUt{"�;���C�0��=^X��*,n���M�ST5��u(�5=���N���������@����C(J��--�i�Ko,�%p] p
�(�
h���&����-�a�"[�s=f��T.�LDUZ�����W�?v����������R��#"""""""��>���/^+�</��}"""""""���Q�,E1�)���y���.�<DD�x��q���q���!����#<�|c#���1
�0�<�mY��1���x�����&8�������T�7B{�e0��l��-�e���ap!�P���K��B�@`j���G�S���@��9��
wy���M�~�46��aD9H0B�R
�^`K`!�b��2HT3���>��7���co��5��Ti���������h���h�w������1��	�h����������#"���Sk���="�B���C��>|���,�h7�aldc�/bqjb[��V�q��Wq��W�����c'�j����F�V�O�:��e�`1l=^���j��~jZ 0�ujE-�!L@s9K5�6`EX���7^�jPdO�B�[[�3�[l ��h�f �j�m1��3����6����X@���af�����ri�N_����0�GDDDDDDDT��OF��
�@��c+~�>q�����x�2Q���,�q��zA��	��_�����n��������c��|�A4��p������=���������� �C��94vt��]�^ �"`T0�2a[&L��yX%+���
�u
����3����aE/�iBToJ��;N~����2������@Y��H;S��V*?�P����9&�~�w�*!��4��*��Y��g����xw"""""""���u:�?����p�n�'��?j�^�1��������pLoU��|�/N����N��WtN"�b��:0�������ea��-��\���0f������p���1���c@��n��G��9��<��)���]H�uh.7�X���B����������2|9���������@+s��U��K���UW�y��ZF��_d� �f������*����
!g�E/�%���MZ��V]l�+���N3^9����K�3^����������v���1���<Z��=��B��OC������������C{DDU��Z���bj1��
��8�.����(mSQ�(���'�s�$���_A(���W/���0�F�����������4=�K�
TMC��S�tZ�������2!P�����������t,��mV����m�e�}i��;'�����k�t=g 0�u"��&
f7*j�[�K@s9K5�v�ep���FAm�y�<���My�3�X�:�o����
B����`%��0����q�+����}����zW:��9,�r��s[�;���Of�Q�1�GDTR\�
�IDATJ,��s5b���������x��	�����}��y�(����*��o����'�{RJ�=|���a<�2���a[[>X���������/}��-80p��gq`�,�
�����;*��9=�x����m��
3�3`�Cc��������a��LXF|{���1��+��hs��f83\���[a>�u�@��}} 05�T5BQJ���(��u����2s4��s}�
��z�-�r�?SX���B��X�cFa1
�n�0��E����m�[\�y����������������h��u ��#����#�A?^���DK���������
��Q���a���@�����
>NSE2��N��~Y�?UAm5���%�@G�!t��S��,b�0]����a��\������_]Z����k��]���[��c��cPT�D��v��C�012\���&�!�65M�����l�J�=�����_" ���
��jK�Z@(J2�����������`b��,���U�}�K�������-%`��i ,2lh�*��ig�6`���kV.����B�%t�7�2C��Z7{,�U0{l�U����k������f��'+3�.�=���3k��!�(���*d8��}����������v�]uU<c"""""""���Q�������0-�h��(�6����;#��j��U��.����R��$l������l�sy�8|�)>�`yv&��#���*)1s�6f������Wp�����!<���s�����]P��ki��s��������������(*�
��.��R��_"��a �0����;A)�XK�m��E�X�$A�u�jv`�u*��L���0��Z�K@s9K5�6`�
,&<[~��[iA��eh;���A�|��B���_��{�*���*;'�.�w��1��RB�,HSBh��ovGDDDDDD��0�GDT����-�H�F$V������>�&����/-����_d�k%d`b>��U�kFF���
4��h��������o�v���.}�c���`��n����.����m�][��w���w����C��Y��C����]�=Q��8����]�y��}�JB@���T9���������������<�@�bK`��
�a�	c�!T��@`*�����*���-���(��u�D�`�E�
�=��(����F�v���)�T�LJ��s�5
�������Z���ZM��q��~�����DDDDDDDT��n
���DDDDDDD;�H'"�M�U���b�D������b]��+G��;��OU����,Eq{j
A#�>�%1�a.���Zt��CW3?��
TMG������������W.�C|��ab����oB�]��4��-|-=�����������Q���S�9�EKo���mU������%�i	�8��6���������u��^��H��iY�i	"���e&���-���j�Z��+?���el,��������{��me�����YlnK��-�7� �X�������!""""""""""""""*C{DDU ���5�����h���i����MK��$B��[��x�O�
������1�S����+cAL,D�>v!h�G���������u^���55��/��/C�6�����0\���;7a[����F,���v��o�<�N�SW�`����x��)�Bk%�����g^(���5NK���*��RJH�N����e���{RBH'O��K���D0-(�&��i��m|-�2�2�h��-k��B��K��� `�����x��P~�[jB��Y�����
X���@�k�0 �k^���,��*����(v�Wi�U���� Q��av���a�24>��M""""""""""""""C{DDU�\�U4�w�����!�f��v���F�H=O-1#����U��6"Fqo���_Z�����rZY3p��r����&"����Mh��%:;�%BQ�y�:��?����B�6���16r	���m�\����-���o!��G�����y�E-�;�J�=���'0����Y�F.�����~��S�1�v	! �ZME���*�����Z�G�6l+�K�Y
��m�-�dK`��-�	jF�������%�~zV{`r}zh0� �U�(��tou����m ,}hv�Z�;1�D��kz7L����Y!�Sh�M�-4�:c{�3�N"�p�/#�Wh���a�R�
l�����������������.�����d���B�/��4lH[B(B/�����	!�k��������x�/G�/j���_|?��s;��B1�����r������������+k���T�?�������S���n�G��	}�' ����d�9�����
hI������}��%x�p`�,��_}sK	�	�[]K+N�gq�{���q������~u-�%8;"'��*����r-���|FZ�/��x����'3��:����"��{i(GD�i	,"���No�����@��&U�z�]�b)+�3�����K����A�
�9y>])"�������{�j�s�
/ �9�wS�aE=��L�?�z���%r��gJT���X�������MR(�B���P�-����X���
C�[�����(7)�h���M������������1�GDT%�>�
:��/}5�"�_Al>c!K]�#\*�V\m^x5Bo�����������|U��Tx]��B�R�H����9����Bq�iK�1�P��&8!��s�
�e��{�B��a�����F
K���e�<�
���tl�]B�t�GK�~���O���0y�:��c��E�?z���#�A���n]x�����_��S�t�Dk]]K+�~�q��o`���-��v�(=��h�Ho	���n�@`Z`�@`F0G�o]�`|��DK�Y��@�%0�K5������zZ���������������F��4��`�a9����/[l;���+-�WP p+
���2��?
���M��|�`�o+�9��� ��.���+�m6�f2[�����R5N���<�-�6�"�X��M�����P�s&""""��f�W�
L^�G��rj��	�7�����y�ZgIDDDDDDD90�GDTE�����[���G�::��l�&>��^Clz
�W������L<�r�S
�p�������%�������i�~QS��w�OJ'�5�bn������zV�_Z�OUv��W����!��\1l\�����:]�a4��p``/���\����Kx02��+�Y[���s�c����|����S����nj������>��C�0y�3S���F��Y������v �(�\.��*��RJH���4�7�=�%��H	���2bej	�6�9��f@g{*4�Y PQ�Y
� �(^@/qj�,�	�}������kz���b����3_7��� N�u�lj���>���@f'��k�	4n�:~L�k���D��%[k���z�6����6��e�!K�6�h�����?�Y'�<x�Y��#��Y���H����������6��Qu5����������Xyg�+E��
aqv�C�h|�����������-�J]�5��_�j�2O�O���9���m����~��gX�����H���v�D�O�j��hju[�f����K����rb!�����w�����
�_�)�~��`�f�����1ve3wnCn�d�3����p�=@cG'�����N�����mP�������k�����Y��������4�um�hh�D����ki���MB�x�P�������
�B�Nhp�@�a���X�l��m�0��{��B�4��uF0~���0�����Q���@�3�����.���#�ji���i�m��8=�g����_>��J2~)���d�/�+ �g�y�-$P�>�v���\���r�����"��d�k�Y��m��+FLoJ�b�b�����6Q
	-��m`���;~��N�����k)��Q��#"�����b�������C��� |��5���4t�0���yo7R�K��Ux�O��F?��������~�l�pL"+<t$����������~�&������Sk9�������C{�����w�8�=�g��Y]����162��+�X]����+�g1���`�������>������C���f���&�xRJX�i[�
U�� ����h[V<���hi�����6��V���v<L(��������a�b�b�i�Io�s����S�$�kP���3���#���~�d��S��z��ch��@������t�$!R�S~�]`��a�\�>�r����?�XDD�[P������%hm,a�R�"��!�	�i�q���DDD�03
|��@pz{�\�
0���_:O�����������h�U�[W�D�����1���\$d�L,|wO�� �:��!��EQ�FRJX�D4��/�/���v�OJ j���h��U�
������KO4��^�J��+!����r4W�B�@ d����Q������y���!���������QX�hK�-�G1q}o��_����g�?x�g�kl*��mB8�"�B@�4����-���m��iM��@`v`Z00��j�R�@�d�I�I4>��P�u���`_"�
f���������%�$:O}���j/bZcY��i����	o�:O�e*��PU�����dkc)��������%[�h�����
>��b4��bA�-
Kpl��V�P%?�#"�m���q'@_
�i�>�����������W�UYd��k6Z��^��������O�S��JEM�T������eF�/�/�gd6���%aX����*H�)g��1#%o���=����#8�W���i�B����z��gaD#��q
c�/bld�S�?���o��o�
�8x���pp�<�;U���DD�9EQ��Th��7
;-����_v 0��?me�gK`m��
+�+��"��������@`�EP�s5j{�������k��c�&��������R�Y�J ���7��K�M�F�q��������u��>�r������v3i��qS��6�:��Q����[}_��z�E�a�T����2�_?������U��%"��7��m����C�����o������U��x\*<E\�%��a�x��	�Es������~���Y6����_Xk,F0�7c�%l�����~�?�[Z�zK������y:�=N��=�z�ph[�?~p������
\^/zO
���9��CcGW)�QQ��@'@��L-�������3_��kdK`�I�F�%��R(��7���r�&�����im�����m��CQ��j	����<`h�h�P5g)13��D�fIGO���_�y�����R�,V��q�s+b,����D��������������8��c�ho��o;�x����/���yy�'""""""���#"��������lY����,�=���3me��JO�&��
�`NJ	�FZs_�6?S"���6Lkw$�����<,Y`/A�,,|�!:>y�G�| ���,��+p�
tM@�?�4�*�k�kM5uq.�{~��1��?
�41}��C|3��:�mQ,����{�������N������&#�>EQ��Uh�2��E
#3�g�&�K^�^S!% -D���+P�d`2��f7&��?�".�\[\@`��-{	��)�-.����"�U[����R�7Fn'�Xlkc�XDD�[Sl�q[a�2�����o�[��0����q�+����}���Q�����h�{+2���gho�B@SMU�s�g�2#��j���o��S���~+������;db��4��R�]�+�!>WZ�OW���k5���c�ooQ5
�O������/�
B�<�z9�[[^���K��X�����y�����)'�7tm������(���C����o[V2�ge5�%�����@`" �q ��x�wM��is4(}K�P���_��/�N���]C�qyo�m������(�����JY���l|,$�����`�ng�L�*�-ev�\���	2n9P��c�����k�B�
��P���x[UR�{��+3����Q��1"�*Y�\������5ug��h����|��(�����S�M���0,��Ko��e���LQ��]��_�Q���;����Fxz
>FJ�
,�maNM[
���Uak�����s/���^��s`,���y}[�[���������/}��-80p�C�p���
��"""�EQU(�
��%����\a��v�T�`�@`2X��~;m�Tz��`Z���9gn]Cxe	
�" ��(B���g<OmG1�%����\c�<���j��
7����f���#<���ED�����F���W�+�$[nm�J��
�%n|�/�
��?���_��\�f��'+31�GDT-���������C?��8
�G���yT'���?Q��xH���3��~�:��am~A����6�M�VG��
�m�iI��b��9ZU��e7����a��aC
�6�7��!�������>�X$�G��bl�"�F��<3���W�q�����?�@����<���s�w����N"""�>�%�Uw���-����x�o�@`�uV�������-��'LUeF"X�_��(J2���)@!�C�yLb��������) �,��]��!%�z�<���27>�#d�������D����qs"��q���b '/V���~��W���������h��DDU�x,P����5��om/�8��;�����`��g}��E< ���p~v��7���1!�����(����P�}l*�����	C�Qf������
h�
����-%S"���}���[7��
���Sb�!K��E$�����1���;��
)-\��G7���r4��7�B��sy�8|�)>�`yf�i��2���#0���.%f�������������p���C��9���K�.���h'B@�[�.���N 03���e�����v���@�4�H�������ii��p�V���kT���J���F�4b������~���}f�#��X�a��4>����h7�v���Q�3)�J���������8�����@J���`�OcK��%�����64&�[Q�;�1=DYH�2�|�!JE� \����������7��D8V���*�%G���������k
�H����}��8�>�qX���[7062�#���f�Itm
��y��y�����g�?x=O���r��-��@s���o�����B|N�/���K�!��������9���_�����!/�]X���E���"QQ������y�vi��7#�2����ec����v����E� QE0�GDTF�B4��R��I[BQV�\������a�N`��a�6,~&0,	��@��_UA*��)p���\��~i�@U����j:zO
���>�K����%<�r	._��+�n��uab����oB�]��4����Zz��� NJ	���%��i��6DDD�%���4(� u#�����&_�9��E2[�-�F���v�x{`v 0�0������E(
�m�8��b��X�PR������|,�E��^�3�]��6��e������[�X����8Q�E���*�n����	�U��T��f,Dp��?��]����bf<�g�i��m'�f�_[2���,�F���.�����a�x�_v�/�~�^�W����/���/�i�x<v._���0�n�������i�062���a@Ck;������N�SW_���#��L�G��jby���{��Mu:��5��y����cDDD�M�[m����Va��d�4a1�LM8�����S����S��Tl�j
�"����"r��"Q����0%km,���a���,3_K��iD!�

$��{7�
3c�2EDDDDDDT!�J���
TU��)�6��&��w.������:4u����Cc�
��un����R�d�/3�g#f�����x�/��u����1S"fZX���N�/��/L[��si
eg\�&������<��_@4�����d�.0�x[��p������=E���'�?x����y�E-�;�-3KQ��Z�B0�aI�b��p{*��������OF���hsB��U��{�����w���*�UW��!m�i����\������s���q��H$���B`�Z��"�T��"�[3������/���

%nJ�Dq�s��XlmL�,��*����(���V+����������(7�����@��p�4DC{���D;��R�KQ<����^�4v����M�9�n��@
!��\l�R���l�Ko�sv*�g����D,d���d���_UA*����������*��`�������������K��N���E<�>
3�����1u�:�n]��/	�?�B����W��R�wRQ���� &"E�4��[�����@����DDDD�jh��hh���q��3�OJ	d���y������
:.�1�V��;�D�
��E�K}.�,n*,$�����"�	��7A,����[mY�Jkc��f�-��7�������wb�7��k?��n��/�M�B�3���@[hu����n�&�U_��"""""""*C{DDU �@{_&n.m�s�tm�G��)H���d��ym���xL��\l�4ye>f��yL�\��O�)�����7kN[J���%�����v|�{�l����D�\7>G��L����*&W�m�6�h��%������U�^XGM4U�V:7l�	�-.��{�j8v�$T��4�x(0���g,�l(�R7!�j��?���k��_b}�.�B��{?Z�����|f,�����`�"�c���m�	p���u�
@{_?������������;����psc{�����1<�D7	�mW��c���|G+6�T(A�{7D``���0,���b��X$""�;vKk��$�����=�1����y7UV�#X����C�G�'�:Z"�s�=�|0IDDDDDDD��Q�t��+��w�u������m)�#|�����,q�2�,_�2=L����mDVwFke8h \������B��y����:}��]��DQ��@�[�0R���-���
��R&�|N����\���M���z^[�\_3%b���-��R�~�x�o]�_V���)P���4��p``�����<��cl���\Bdm}8�s�c��{��t����$[����k�b��5o^_*Yh5b�x��>x���="""*���V�;�!0;]���]��ki-�<�``��E"��0��8�
X,�x���h#=�������M��|�`��<�D��eZ~�^?UC{DDU��8S���+:�^'��>����|��!�R�����0V����B�6�GES��>4w��|M>����&��Kpi@�����l8!�Ds�i#���b���N���am��l�0�D�a�� ����~�@����_��g?U�1��.�\���a���
)��bD#�?���h��B����;=�����K-j��ps��-��%q��2^h�[�{ZQ���C�����<g�>��bi��W���aV $H��|�DTR����d����M�0'�w�����,U���o�Q������m������a���p���/���Mm8��m�KDDDDDDD�ah���J~8��E�B�U���#�Bhf	�;�>Q5T����b���ap���fw2����CS������a{Z-B@SMU��B��������g�=�������8p�SY6`�6"P����h�~�'�v�#���!4~�{W�|�*���m����F���|�;PT���pB|C��q�`U/��2D�(Ob4b��2��G��a,�FZ���v�(���)�m������l��c7�^}�����/�����q����k0���E"��B��
�������d`���*����,0~kzF��L�47��i�m��8=�gNp��s@����MDDDDDDD�ah���JF&�1�1��V���;=�V�>Q�{����b����`Y6�fCX�	a�q��X��OX]�bu)�.��j
;��0_g����O�^��,'Ep+bK�dR�x�o��_��/��Y����kc�D��x��gQ��,|/HS=Exl�������yl����QL\�[����p`�,������56��=mff)���HA�J)!cH��P4����e&"�m�������%"""���O����b���������3/�|\"�t�!��U,�
�%,<\X�(l��"�e���0�����Z�{	�����_�������_���������hs�U������6��&N��r|]7�@�1~o��g?��������������j��GK��{t�=:�=���E{[kO=�i�����S��6��K�����M,?a)�[�M-f�<�\�X����5,N����S���|^'��Y��N/��}P�|���pi.mk�?���K4��6b�F?#����S-�6��$*NW[\m=h:�Q�F���N���5���?X��7_��7�&��~4@���:��]�5.�y�5��@��
�|�������'�z�Dg ��!�h(�Mq���8w�A��x���_K��ah�����I�xp�������f,Z�q5�'?�	�O��$"�L,����U�q,Q�X�m���s``�hW9�Q���g��e>�5�~�?��c)��DDDDDDD�C{DDU�5�6�5�k�h���%($����cI��������5x4���G���<{�G/� ���|�����s�#}9���:��q���^J���(�fCX�
9�|�%�*|�Md�������8
4�zP��B ��VgC����CC���Y��T@SUxQ��9��i�~�������@#����(���g�;x`������o@���?4=���&����o��8
o�)������U'���C}�x�/������c6�F�s�?����������iGC?����X~�;��E�������}�!~��FDDD�S�����Y\��+%i�s��p���@]Kk	����h=k#�h'�3�HD���E�v���1�-e�c�hA��Z���:e��DDU���(�W����U7�%����W���l��������	�D�t�KS��
�e���y���z��mT��3m8�d'��7[�9�>���3mE#�@}���������4,���3Z��%��Z�`P�H	�#�G������hnM^4w����Cs�/������o'�BQ���{��R�dc_v�/����dM\��������������'�76���Cl'�*c��]B��%g��Nx����4<��C�����1s�mX�U����X��N��F&�`f�OP�i�~���z�3�?���T_}������J���C?�����70/�
6�v�(=��������E��6����,��ahF4�.^^�j,�1�W�+3��K�U��&"�]�����*�W�Q|v�]���`<�7�V����ic~5������"������OS-�
=+��si{�"����_8���KX[������5���/+����������C9�U#��o9���2�mV����0�h��V�m�5����:|��y����WB���o��R�����%��L1+G�/�==h�ex?�O�Qxz���,�P��k�]C��(�P`[�K�0�f��w����}�~'����l�����#����Z[��9��|�G�����������gBX��(�TE@�(B�_;!P5�n�}s�z���}""�=J�xp�CA��c��z	������wu�g�,Zz��w�DDD��1�X��bF�0��p(�[7o!q#�#����X$�e'��������>~���F�A6,����f�+2W`f
k��ki��|DDDDDDD��QU��54zu��SMZ���"�pX�Ic�_���&��kl�a�VH	#&����-����x�/�����glK����u.uW��/�����o
��xf�t�i���!x�����O��}���w�1c�mK"��|��!�-G��V>��B+1L�^�X�����d���+��6��;U%Bh*��*�P�>��S�}�����������lT_�O<���@J����cWzx
��;���������?���7���	��S�8
o��uMw��=��W�v4���I?��eL}��������=��XV�uS$�P_Z��y�)�oK��������&�J7�8�!Q�������k�����Y������������kkGC{'���^DDDDeT��b @��d�u��S���e��P��E;-<X��"�h7�����*k`���a��b�����o^������;�YQ1�GDTB�������#
��:7OE4�Z�*����x���i��6"Fs���TE������7��������q�b+6���(~:�����o��xQ�Q_(��kl�����3�EL�<;a��!,���}F��������s��>�	�%}�>4w������*>HF��*�K�g�J)s��bi!���_��0�������'?;A��M�^Chl���m�km����������{�|����:����h�W1��\��^�
a������� ,%)3����A��_� az�����"k�\c�l t���^R�����KJ	�0 mBQ���	�_z`q�}���"Qa�r`q��s��>""""""�=��="�*���.��p_�q_���8S��R�i)����BbV�1�����0�n�!�3�Zp�����`�D ������eK,�,�[k�����p�����m���?�G�GWxQd��b��/��Y����5W�����w�7��4��Jx����hh�k@{_C�z)%B��g��|��a��H���GC&f0� ��A
���/��tZ������.i�B��	�4uE+����I�>�
�|	�icqfS�.a������m�mR":s���X~�(n�}O�����5�$���/a�-oc����e,������R��w[:!`��XNB���~�M��	�����R�p.�Z��P\��y�BHDD$�������6,����-��s������AJ���������*��="�*��P7��k�6�g^�x�k:/$��$`
��"~��{�<��]
�cX6V���@�D0���p_0���u������P��L`�}s����{54���}]�_C||[�G��O��o]�l�	����r6���r
��gK~��&�@]�u�n�o��f�6�a���qs�V0~w��;V��$\� ������4]Ac<����u�|�uh�����+{�TqBh���^��.�k9�S'�4,����x02���a������v4��;�v�"@o����4����[�lk����|������`Y���H	XR����-�-'�O���;��.���$��&���
�����7<.o;��("$"��l�Fh5�4�i|�>(�^�t������*�����x���E����Eao�DDDDDDDT!�U��.?��o��c���B�-$t!aHC
��{�`���=�U�u�-7�I)���@_z�/�<�Ko�KlFD{��� ��X\�aq-��1��ZF��	�e7������U�o��[#S������������n�|��l���TMAsW�����@ �����x��p����0�
�]5
��X�\]������|i�|�>���P�������j:zO
���^��_�������W.!�bj:�X������1�����0�GJ�@9C�J��j��s���m��f�(���
���m��[wq��W1��.V��`G���O�������}�e�;\�3%"""""�Xd`��R�mU����������������~���b���q=�O��0�����@��
�,[
Fc:F�n|s���F���o�X����wk�wk����1���`�L�%�~���m��V�&?��c5jb5j+�-�R�d{_���_�0k�7����A)c�������Z�j���_���B{Qt���~�?c��%�K�� _��kX�
au1w#T9����L�]�X/���>4����:}��]u�ruM�8���q��C�6f����.b��M�����
50�c'���[J���%��z.%��>���<�O���v�
X��U�?lB�&	3~m�i�@u]�0�����FC�{CD;��7.��W����[y��#k<����k���o���8>������V�L������h�����������!%>���Q_W_t`�����!������z�������v����������`��v���a�������4�6��F��7���;7�t�������>5���Nt�������p��h�wo�x��X���r���������rTK��1��������H����r4������]Z���n�
o��xP���5��>X���`A����P��^�[��;�����YXy�����<�R<��=OiK�<c�q������Q3���K���T�6BQ�u�(��3��DCk���a�]F`�q�O1'���8�����%ef��	��s�[������8���S9I	XR�������|�
��f����������������(���e|�O������cW�o����q��g��������T�$""""""���E�B@u��{���;$m�N������bq4���Wm~""""""����="�*��O��;0��I��{�K�T}��q��D�t������.4c�V��w�w?q�g]�E��`[�As���5����`��d[����������J<���}��Jx�����$~��DE��)t�����h�_��^J�p�Hk�%�|��0�
���"?�����m����_S���W��)k[$U��W��O=��O=)%��'1v�"�F����(�X�#s�~?�OEq�0���c����N�KlO���?6�Z��S����s=c������+�ob�F!�����`z 0k{vH0�o���~\b���l;P$*'[v�������~�p`����C������V���C����7���?�=����g�������O������GJsrDDDDDDD�+%��&�'�F�����{����*���v�\����������#"���:��������^��m�A�fmk��_�3�(���>�/�
�u������Uxt[,R�l��Ds_V�/��������d� ��a#bD1�n����L�������J�������M�l�F`>�
�=ay�	��[kv����(V�������^�4vxSa�N�����z��r�B��{?Z�����>3���k���a�?zX�s-/b�o�]���k����(j*��&����`b���>+���'�u�<��@��X���Zq�CH���;�D|;��B��' ��G
6��~�:[(��?G��l���oC������T^�
X��U��7�@��_f;a�`VxPI���d�L%�7�B@0DH{���w�����;R�������������ap��������(���������������EDDDDDDD��������1Tc{���.����=��%���*�>����x���v<��e����g���C���Y��~�`G�����)�wk����c�[C�Ks�����}n5�8
�n
]���+��l�����X~�R<���8��g�����e�X�Z�����=u���|h�����M�>4�{��w�$�������8��?DpacW�q��{�����}z;��mXve���
���P�jZF "�
�(">D����d�0�?�)D|�BLlOB(���bj�������E@(�`d�y�=n�-c�<�&C���H	�R6P-���`f;`v�/Wk`F�p]�p}av�a�q�3M�����W���J�K�#k���.~��-�Z�J:6�n�v�&F�+8����EDDDDDDD�U_$|��P���I�F������y��)��T^Bx]*�.�������j�K6��o�K����e���6�Kt��"�:��K�����K������&�~��_��DXp����:��q���^�k+Q��o&3�X�T��������+�����^������:4uz�'6u������w���6�y�#8|�i�)C{T	RRB��i��>�Dd�����Y�r7
fo���~�p[v(q�}��^�Z�y���%��2_;���_/J�%`[5�Bd�r��r�
�	3����\��,�������\].����2������?�NY�'"""""""�
�ZZ������t���wu������Q
C{DD����@��w�O
�o�|�'�3>�,]U�\�Bs�kK�K)���@_z�/�<;��:����J��%��FM��������_���?5�s�����p�����0R!�Zi�@}�����h��fV���_bY�
!�V���@`>��|��2�in5���Cc�/-�����o�k��m�=��*E�	�j��m�H��D�@_�u2��&� S��"LnK�S����Y�!T�|�
5���^%~���tZS����yC��}�c�7H
Q���$�,�F�0=��ak`�6��
��B��P��6B!�����~t�����])�
	��\��7.����u"""""""���w�LEB{�Cg�>e���DD���!p�ny��{8r8p�����"�@}<���qkcDM���4����%���v�pz0��j��,����BB�X�N���5mD�nT�����K[m�un��>+�h�K������\�i�t���h��_�-�j8�|�k�0_K�!���`��� ��Z����G����]!���o�@����;����������_DD;W"����
�Ikb�m�&�o����#7{�v��'i�L�)K ��$T��P��uj���Q��
H���b�m�@�	wj���W�V�y.��5����������60)[a4�����lsD{1i��p�f """"""�\�#"����6��F.1�G��T��U����t�mK�����D��	�}��$�MH��1|�>�Aw�]��T���`4�c$��7W}�ml��p/�l,
��8���6���_2��<OoL5�B�n-���z����pf��%��u�|��!�-������B+1L�^�X�����ua��N<����h|'B���a���TlN_czN���m���<�v�1�u|{j��n[�}m�BS�DD����N��U�@���u��xSc*��j_��:�����u!��F�|���K��`<���<�8G(J�=RQ��GEU��*Eq��U@UUg��q���P5Z|��(Pu�Q��m��7.T���\D�����bu�V~����-�����c�$��������(�J��B�����6���|K� �54���x� Q���DD����LWf��i`qhi��|D%�(~��G�t���0����s�K�0�iSO{���T�{�x��?k
������ka����
�h\(�
0?U������T�_�[]���4�yU�k@��f������|$#��X��U��.�mI,���4Z����RA��x�����v/4��c4*V��c
��y�#x��"sI)S�>���?Z���@�/,�I�0�:����f��X�n^�Yhq�c���?���������R��	�v,����R���F���D���`T"��,�U����G���sK.�	5&��oK?��m��E�P��c5�X��-���E-�&��s(��=j���N��~����������5RoH�^Zs�N����w
��BU�;���<�����g�l;�k�2��\�a#�
��2^kE��s��^��N��Z-�nm|�-���������Cv��c�&������X>�A4���2J6���X>�AH������N���l|"""""""�C{DD�r�N���<���N�����������O��7m�iOOw���>��B3������`?>sn?�b&����&�b�GkQ������P,��7�}�f@�:��FL#�k��J���RQ�����A�P�7�c��
=dA����f��B��L�>`�A s��=h�J��;}h��������PAN<�"���W*7��/Tl.!��BQU@�<,M)%���������j�.]��m@J�9}�;Z,(ie
������>6RL��(H�o���KDD���m9�^Zfb���tg�����������.+	!��9����g�8&�H68*Y
��-���#�s'��J��������p����{~��O�\/\��h9�|:�0�9�GDDY��%��}'
 �M�����:�N>���a��ch�Q���>�v~/����-O#��?���o��q��<X>�AX��������������hs�U�����w�PW�����9����'�'�)Je��h�>9�������z_��C���P����O�6��[F�N����C8��������vZ�/�K�C1�Q+��L��Y���3QN�F��aa���U@�M�@�-�b)h�Z,�f[A���G�.F\������M���1�����u�|�uh������������)L��V���?qm}�e���G��_��m?�pk:�=����������m4�h��ka�:VnR� �����Qh1�q��
3nZ�h�|�����I1"������
:!A5�(r���	���\�9��L�����������;�����?���cz���&���@����C���XtW��U���.dwD]���
x�r(�rH�)��M.B29&�L��=��U�?����������9^��#LW����o�L�NO���{Ly��u�����~
�������YA����c�$�st�P�Z:C���Ph��~�������*�%�m���m�@�p'.��mK�w�v�}���/l�L���C~>��u����2�g		����0�i��:-�y�^mj��@�~?i������=��&�����kM$�0���$�������}7��e������������^�
��nG��#��%Y��� �!��l��l)��Y���Y�b�����J�L�h�RKs�Z��3�U�4fB�*_}���	U�W)�o��t������������A('�4���m�3��@����t�+0h���9~��V�}����W��g������J�*��B�lK�Y����M�����:���uF�Pd~�{�>�`b�����AD#m.��
m��9+?����F	�_����+\?]U��(����%=Uc�9���N�����Z�>��@)��r�D���r��o�%��QU�X����}�0`_!Anq>�h���j�����h���1>K���Ki����rPQ�.�4TS�WM�_��O[[��.]*I�Z�q'�,#X�
f��X�Q5���P
P��Mi�ik����-����|�
}X�b����_���G�������>ME*MY5~u���
P���!U�U
�*�Y�����}��e����MU�Us�4������}�i������5h#������������;��m��R�1#,�o�0kX0�_��9n��E�m�U!-�=�X�*���#c�w���b��#��B�A��:�P�W1�&���U�13X����Uk��t��]�19�Dh���g��%���9��=�6=���S;I����oyK�.UV��w|6�D��U��R��G��8��~-K�o'R�@9p���h4���VL���?��*�%q��	����&F���DLw������
/~SSP]]UQ��Y�:{U���U]���:R��_�U;zb�Y#�VGCj3l����$����RC"�������*qu>CR����z�]=�:��W����1�x�A3�z��V��*>UW�U]�UW$��3�~~�$������J_q��e�������^������k�������g_��s?R��`42�d� ���+���*�����}yT~�Zt
���d����bOO����#��%�VuU��H��@�������#�=*	v"�K�S�+m�w�FW�/m]o��H�������Ukts�"Sc;���~R!DG0���Y�1��p��1�d����q<@�u�S{W��������>�L�L}&����r��w��<"k�<���!����V��2U=�&��Wt�G���7��h��ql�E��Q�1cP��|���P@���&�?����z�~�
���{}*4����>T�F
i���.�-�QI���l�|��|�
}c,C��*dhR����)E����xx�������������~N�o��_<�WU��KV�K��RAG����U_�j���������u�������F��/T�����2��][�f�~2��h�P(�4�%��pV���������_}���Q���R�p����dE-���bQK�XT���X,>F,K��b�v��c�x�0�i��?���=L�C��12$��%%*_*Qi2�lx�Ac���|�j�Y��F"���n��&�E�]!Bg��MG�H�G0��2c�ui����f��dY�<�%����K�U��W<�[�XZX�W��=mo��j���EW�WY������](.B{P��TQ!u�B��rT,ZH�k���"�������	�
�a(�)����`Q�LVtW�s��b��������_�b`	�R�!u��������Toj���%+���7%7u�������'*[{L�7��x��~��ek_WD���w�yU�������W]�Wl�n�,����:]v���7���'<�q��!]2�8���������������p����������$�=�w��Fm�-�xu�O������sUYt#��3z�Oo�]9�v�����1W��Us�+���rd��`����R�G��2�������>_|�4]�����L�{�a���m�m�}{��1f��l��o�6���Y��8?�5����������o/��Z��?������a
i:h
����=N�8
C��������x��!��(D������7^#�`H��������R��CA�����M���VniW[go�{�fm�6�:�h�����k�M��K
���Z?�&P�� _���C;Vjn.����T]��F�Xlh|���JV,U%�� _F���=��-P��}�*--��m�9�m����������rV,�d5@�
�i������3��#V�K�i�/�[p���
��*�Y�b��%�����q��q�$�+�v����Z}v<��x����iv��������m���W
�.�q
�}\]m/��Y��1��\�N��k��{���yOm���0d��|�!��7
��!���5��m��|���~��$^����J��5�����T������qz�����_��������g�4�7v��y����� |�V�1#X@��#p�~L/G�I��^s�v\��^X 0l;^
&KE�-vL�|��2B����c�����D�HC[�B�`�Gh1�o<����#����
h�_{��#���x<��f�\��G(�
#,#��Z>������2����Q[g��x`o������,J�����z�w4���S���j>o���@��_�����^g����3��
�E�o��>��o�-����B�����"o��t����h�w�v��s{z��l������V
�^%�Bi�{�}��}�}}��||���B�������7%U�R����$���Z�b1[1�V���z_�,[��-+�l'�%���Zv����T[�D}��	��'�pO@�|9�OQ�T���b>M������@T5=����:QMED5=
�c2
;5���
���o���{������s���B�7M�1���g+��hx��h��o7�S�'_`��b�C�U���7��2�;��]��lQ�2���mC�����?v��G�`r�S�Bgp�L��������m�����s����������4wi�^C�!��1����6�
Z�}�!M��L�9�~>���h��?�H��;j�������#�#{��+�����#��=T�_�����c��ZQ���#����mgPf�Xi|��`����%��fY�y��R��3+(z�,B_�@d!��m>�>�i���y��o 2���]A2�"$����
i��N���������K��;���h�?.���F�����	
�=(��Ko�^��fg�3�x����*J��>�r��!?�r�#�X��>KH�*�#O��f�����($�p���_+�L���x��~?�L�)P�2��;���A�
�_����;V��
uE���+�"���4��G
=������8�_GM=���q�������X�j����b;$��1�
��	2��������;������+�6)��tP0�[��4�n[�v��LW���2���K���=������ $h�R��%k������������\��V:�V�1=0�U���K�Wa����>��R��3\���c*��Q�1���80�x�l�L?D����X����9
�8@1�)�i���O�����p`�U��o�+/�,%�=���UUY�3�9�/�}��D�0{ ��c�0g�Pe�@d���3M�m)�$��!�#�w�F_��_��WH�+����W���E�Pe�@���p����Q�15���<P�����kZ����u��1b{���^������������ril�&N��o��&M�h�q�b��?�~GM��YE�+���j`������`4F0�i���'U��+���po�oO"���; �.������]!���|Rhu �1W�oL�Gu��
��<�e�:"��/3}ceV�,)~�����d�$��1�#�s[&��3������*|��R%���Q[�����`wZ0�Z`w�����RW|I,[�b�2K~�P����g�EW8���cf`2�*dF�IGh1#\�9v�J��U&�����Y*=��6=h	�<O8�$��N����`h1C���L�|��>����b�����V]]�`Mq��m�]�1����U�1���O�0�b���d��bfF�~��d	s�U�2�@$`p���X�wo(�a�]��@dF�lU}}�����%�"}�!z�sW��R�1k��0�A�#Wu�ju�yeP�h_���[N�t�����@9�?J�K	B{���1��!YE0K 0g�A��*�1U��4�&�Zo����@�2���`*��-�6�:"uDjn�r�7
[�Ag�/��������i_���������g���S�9
m�Y�Q��e�7��VM	C`�@_W�a��*�fA�A�� <�,[1������������i�@��b2��Y�1�*�Y*=������
��p����dfUH����Bf63�Br�
u��Z5m�����1����};k��AF&�0�7���A���������X��/G1W���@df{��f,#��w�2w ��#������~1��_�
�FZH��B�(}��'��c�!Dw�1�����$#����w�TuMM�)}�s�#�I�q�z����d�u��I�,$�@)��r�1C�m�UUW;hCt��W����?�YE���`��������I@?��T_Q}ED3�����KT����%�}����,����
���yW�b��|k[KS������^9�L[!�S��z�3�����n��`��������"��&������m�S������#��
.:C�A�J�^�Ig����������{lwh1{�I���^���e����p����mz��U���?Vm�����cU��?x��lh����u������t�i�g�������m�E���_ 2Gx1�8�b���%�R����Zg{�=��e��'>��l���d�����g������G��|��^���!D�m���:�{~��^���vmjR��w����-����MM;}fI������/[�m�����+��)z���vm���4���]�����L�D�BB����2�F��<�������n���v��m�3�������; ��a���O;:+������nm�RKWP��=%���4l�,M�(�	:~�B����G��\U��K��
@�����R	+��L~�e���Y�,&����"s]�3��Y�Bz��>�����3
=�F�$i��S����(���hg����S���HP���k[��3��0�s1��j�'�0�!��I�O�rOf��m;�*c���g(0�����c��l%����6m�(%��'M���w��
D:��g 2[{����mY�Y�$~'�_Y+0z�sT�L��o�����K��dB{��=(��;�T,�����.�/*Z��~c��Z���=����"���#��+��K���-��u��s]A�
��Ro�Y����S�55��������ox�2i��j2���&e�{{�������?����P��jIS�~�b1[��,�����1��K���yO0_��QG���a�dZQ�V,����7�'B�a�T������G�B����U]��M��
���>��_�`�23�^�c�a��l)���w�aoM�F�q������T�3��������&������s���c&�{���P_j��
�%�K��f���6�~��M�oJ�2�0�����z���wr��1���1�!�|
�X��x �pl���?���v��6������\�w�������<�1��{��K��g�����K�����W���$��s�jkkS�����-^����2�H��DWh��U
2�*�my"sV`�
Y���
9f �T�` 08�X����.�m���{
�*���L�k��k��%I�--�x�5���Rq/����>���IR��
�]���9�T���*��[�����W�)S�s�+�x%����e�4�4�$����;"���S{wvj�����;����T�����=��47f'��
���]��.$;��z�9��������4������\���'�:�K����HL'\�7u��/�N���_�[�)U�V�Js�AL�zd�G�"2��x�#S���n���mCa���]�`W"�i
�Rg�P�%uZ�:cR�-����%��8 �5\�H�?(]&�gu��1�s�S�H-aS��>�lI����U08\��!OWP����g��+p��'=��J��3��f�`i���3X��?3XZ��������wuu�����A�o]�������HM�����!O�=�g��U�s(�4�3�rOcX���
f�����D��j�+��
/f�-�*J�y"�c���gYg����/;���m����!�e���c����m�����h�����w��V���e�)���8�=�\���6�7~|����Pu@g�k��z�z����5�
��I�no
�s�L-I�<���ut0�ACW���sn�
�C��A�,�%��^���j��<���������X��O�*e�R7?
���-������e�|�?~Y>�,�����)��3MEM�b����S�05ME��O���Q�k����-���_-[1[�u1��Xj{��d����mS�m���Q�r�'�,[�-���-�
0"�����B�2����U4�\v4�_�)����/0KAIW���}M�v��mK�������|�/��[�iP���J��dJ*�� W5�Z���i�q�����*���g���:���+������\�:&����>��n
�m��~UeL-f	�7���s���c�0g��3��=&CS��]�p���U��
��=(�����X���/O�m�Zp�1��:%��:�4�e�
u4m������W��w$�)��W23LS2M>S2}���6��n�s�Im3=���sM����j���1n�6g������t�c�d��i�����p�����������[���5��Ezb���S{wti���x�/Q��'\��c(-[�l��W�A��a�Paz��Y��w�������3`�^��]I���e��������2FeQW_�a+�A0������$���%���c[��^��}�����.�A���Gp�Ro��3P�f�����aEg�0���slG�>��isH�+=�N��,w��y\��HQ�r?0T�,���
U���_`�|�Y�b��Y-;�]Vl�d;v`T��M���(_p�L�XW������W�������(C�P�B"k��,�f�U5{C��0gF�f����T�
>�V�?�9����@j�q:*�z�Wu���K���$��D-E���-��
��V�d�>I�rOgX�m�3���+�*cZ��#p�QQ1sY�������^���n��w,U��'~����g&��%�(XY�Y0:��2�m[����no����
M�h<@u����	��0^�P(�&�k�N���P��5�ni�9��o�:^|�h�0��
�9B��}�dd�'-�f�o�H���q}2L#3��<��*s��T�2��Pxw��-��* ��_[�������}7�$�~����Um�w]b}�>�������lG���p��]�%~)���m�N�I�w�������������?���S���N��{�d����l�x"��s�,G�^sP�����<]�����lsp��m�r�������r�q�=���m[��6�-�����UG�Q�������CJ�W(K�d�K,I�������b� �wp0�_f��L�G�U��@:�K�_F�E�O�����%^�2>���0e���u~��@��_F�/3�X�e�A������������j���P�3��t �D�03��5F-�7��%��
K&�L+f
.zW��]�Dx�\�
Z:����\G�XN�
�����l����<YR����d�$#~�j_����
���c��"��>:I~f�����_��@�U=4`�
zV�To�1[PR��P=��ow�33��%������aV�`�3X��w1��z�9MC���,My:�RH���c���;��CG:�0��K�|R��c6mmmZ�tijy��������U�b�0aZ�1�P�w���>����:�X"@����m��/[�2qL6��l����d�@X�����]wK�v���������O�p�[��bR,�����A2��%)�)���w��;@��~���J�kY�B���U��C)em��* ���M�A)g+��p8~���m�|G����{|�6�40��%�i���Q_H�}�����A��2�{.��J����	����h���g&+i�����1L#&4
�>3����2}fb�)�o&���������6�����q�����1��w���o�L���k0n 4MC�|E�v������Wp������Y�m������k�t��G�"T��2�z��+&����6v����\�nf�2�:��*�1K�=1���:4��G�����]�84���HL��$0Q=��
zU�T��0]Kg;���zh��e�`i�M�����MsK%��,N�����Q=�9��j82LS>���e'~Z���}"�+8&�dD&�bY1-��������#PU�@�2{�
�=(���;+��a8�m)��?)���{$�[�F�s���U����Q���z���Sn�7��^��ba�#���=t��v<�X�O(V�%������`�z�������e_��4_��
��w����]�K���#�h��
�a�gH�"�������{�?4�����G���������$c-�U{`�n:���sB���C,;6L>S�J<�J< �v��7�)��m�_m��Y��V��"V�\2�L��w}j�s���S�Y���v��q��sI�)eg�x������J��u�v�~����o�q&�����q��B�TE�� L�<�X=�9������V,��{����������������o�z��8}2
_�yf��L?�A����^����~�l�g��ad`8"�e`��0"�X����NQ����}G���c�sE���`H�m��=
sK6fC�j��Oe�l�'�0_M������d�'�������-�������y�S��U�2��e%R,����
t���
sU7L]�E3~c�3�X� �W���NE����$���[f���co���z����jU�:K2���Oc'����
%��������b���RF1[8�+��oX�k.�����fZ�T�!��sI��
t�.s����tK�^�5X�#��_��|eg�������i�S�s�nM��Y�"��>��d�|��d��@�v�j}|���I����oO���K�?��A�#`i����%�����%
��20��e�������SF�X8��>��]"_(T�~c�p��0���m,ih�n�L;&�1I����-�����C��
7���~)�����H��l�_�d��_��m���#����J'e����f��b�:�������7)[��X�F��l��-Y1[V���k������o���pV2�d�"t��
2zUx�.&+<��u�3�<c{T��4�9��T�#���9&nV��v����m�������/���A��"Y��M������K���/^���i2$�N��L�v���2+RfV��
\f�V=�9�����1�����3h�n��t�����
��+�&�Wis�z(J��o�|����f��=�
���^5f��m>C�D�@���������K6f`���}���%�b�����d���1K�b�6VL�eg��Y�}��_-����5��c�XL��S�U�������E����]|AQ*�E�����G���R���&�\��3�,�x�3$�%�zA�a���������RF�BfEHF($��B
�dT���J)��!��B
VJ�
�
���D��BJ��e�aC���wm#~������o��b�u1��=�.�>,t��9���w��O�qb�lK���sr��b[�P�5��4�^��_��������u�v���"t���n�u_�G�����~����3<&�����l��0s�����OFx�������c�A��9f����;������g,{��1s�Q3'���uB����s������y|�3�������R�fj��W�Vee��1�^z�������f��}L�2����g�N��T��g?�W3�K�mi�����u=)������w��]�1en�!������l)�T��#��w����c!U5S�B�����2�!{p���C���U��;��>��U�,�8�-�F��'+�:�c���h�]����j*�e�R�_�P&��Q��^���j���X�������3��Zv�,!@�N���_m��i���,�C���'���2������_*�l�:�>��#4��-�<�����
��W-T���W���j�v,{�
{H�di(^�$q#X�u�FH��62���e�c�d��1{oz�9�6f�M��6�}�����.�<�����#��=�K���l��Wim���&��������w��?�������1��Gn���Tg�W`�<�������pw�u8L�}�3l[F$";Q���4c2B!�
�*B���PHf�BFE�"��J�I	�m�P|��Bf�������m����A�����b�Mj�}�s��u>VZ�v�9��AF��s�o��p��K��y���	��W/��T�i`��
K:�g�%��9�glY!nC�?G_��I���������OFx39w#�ld��~l�cr���
���w�9Z��y�������;�;��d;[�a�N,�r�w�O��I��mz��wj��zz"j����w����'��n���4�����$�g'���9�8��%���	Ho���J��v�I�g�n��m������m���
X�����������p�O��,�N���`ir.��S!�d6��,u�K��� ��wg��r�������Y�^�m���������]��8�e0D���-P���A�:t����D-�b��"�eSw�9j����wv��(�0$�O���}� JB�����d2$�l����|�'P�Q���E������q_,���<��5ku����z����M��f�,_�����
��y�33��5l���;l�x���$#w��+��U�Sw������*1/����u����������x�����&�o��{���7
��s����,�������z������R��>���m[�Ddu'B|���n���P�����-��Lns����v��Hd���e'B���_�R�������3�������,AA_($r]uHF08*���m�V�h�1�����dG�����1Y����%+�X���c���&�X��a�u��b�FC#q��!�67������{?��%#qS����������w����R��dr�*G#�+�"�tff��#�����0a�pb�r_����f�����
a:�g�mg��
��}��������k�p���w�4�������������5�����y���;^��y|��g���r������>��"+�����0�s�������~��@Q��2	2G��������=V�9s}/�aH~���uo��uY+W�ohR��&U4��CQh�UN/_(�j���c���w�m�u������c5�{�-�1F[��;�M������+�������s4���5a�r��p���3a�r�m}Wu�|�s�aR0(_0(���<��X,g@0t�]U]A��pZP�����.�q��b1Y��Rggi�3�x�?��`�r�+�oP0Uu09�Y����3$��+���x���Q)���^G{�e{��'6����!���HLV���m;���}�AA���{�����d�0>�$*@��/������D��Q/GJ����md�+���YGU��S���E�;���Q�@�bI�4��������a���Q���jK	B{���v������#�����[Z�������@@��';�U`���G�k���d�~��k����S1��c��j�{����������Y]]��l���XPP0���+0�#((�*���Ll[v8�X8,��W�!�@�
�
�U,4 X�V��?�?�I<PBE<C}�c���m�1���|�����}����`�6w�0p��l�@f��Bw�����!�d?}�!}?�1�H`�0�Jk/V���$��64*��X�Y)I����4������v�"��s��{l���;�\��r���u�����o/h+�
���wv��0�5^{��>�9��'zm�
/���th�[?Q �1���a���P�$��l��"��@_ZP�������(�#(���a��#������K3�����(8��`2x��(h��������f<�r�c��~�B�<�q0)^��V_F�x�0[��F�3��j��J�i�2*):^�{����+0�_��k?�2�c��R��b��)X{�z�?X��{F������K����HwL��P
��l�7���������}�����o�P�~��&Y����+�Z�+������t����#>_��{������OT����}�!���RmmI����x�@G@pk����K2�����s�*L���`����">�CS4*+�::+�x�pm^AAg�+(�:����+d���)����f<���C�AA��\U���I�R��G�L#^]!�G���-����+I���h����\g�������+���J;�.�:c[�k;K�Y�������6sn�����}���]�l#c]����K����[�:#�!����$}[�����xxU���?�����i��=e����}H����9�����n���CH?6#�mNF��3�jhd�;�ql9��{�T��>���y��>������0���e���S�+**d��������vBl����S�m;����s��kG���^�
�a������t-�������*P�8Ua�)��0��2�74h�wh�'>!k����k��k�w���P�>�����k�����^�
@o��f�V���Z{���1�����c���w����������eV��&��6*���Z�\�XuuuE��,�==���z�f�(h���
vu��3����b������*��F0�G���mfe(30�
z����c3���&XQQ�1�!A���g�/K5�B��(���pIC{Sk;5���8�22���eA����yl��?�}��D��};�FoX�0d���c�r��c��z�����!�����k��r��m�����b���9���!;��=�����kNv�~�6��c��:�t�=�.9���n�9H�a����t�X����;lj�v�����3�o��jf��~2B�i}y�T���M8cL�cr�������<&g?�\����\��^��y09B��|�2�I�wrz_����:/Y���sL�YLoo�R,S�����uu��������/2���dF_^�=����������x��g�7�\�R����U4�\v���������:N����m|�a�p4��a~���C�h��~����tQ*������;�P���a�HV�j{��A��W$w�>�o�[u�&�X�M����1������i���4��]I�1��LU3+��eG"�P`�7(�L�
v�eu������P>vOO<|Z���<+	zW��(X�Vu��d�����iJ���`i���>�~!�,a�H�K-;w�g������k����}F@ yNC�^��X��nh+�X��NO�����Q
	�w�34���7���:}���n���b���,���k�~��!�����MK�.M-/^||�"4�e(�
�f
z��,8L�5t�-��3�@g�����6k_^aI���a��9����0!�������'��F�{�.%�5666��|�T����~�v��+x���1GB��
q�������X�j����b;$��p$�B�o��D��se��������@�o��y!�CD��9:�����[�V�������s���o��
������~MG�+N������jl��j�����U[�����h����?�����T��&�\���m���c�1CF0(����F?;M��WI��t�a��W���$��2�FeE�RG�JR��4�!���`*����G%��6�9���mR �3@]mmz�u��G�S�vTxP��u�����T+{4��S�:���w��5�j��z	a��7h��B�UVL';*�U��i)���O�a�l�K���s������f�g��`i��`���7��/>����+������5{s�o����<��/E$;&>I�=l�������!�C���AS��]��{�Z���:W��{��c�U����
F5g�+k����K�+^��5�T������l��*d�~�VT�X�g��@q~�|5~�����E`[Vo�����`�G0We��J�v8���#�e���R���dC�������`�����a�o��|���R������c���l��hDjn��Z�����5�u�����Kr�a���L3A�j���:�c��#���8c�`��|���E8�H��L~���5���>C{})��� f
����T�h�j-Rx�Z�=���o���wW�BHf}�*;T���P�9g+4��<��Y�j��~ �\�{C�?�-��=�%po�i��H��%��m��H"�
&�]��0`Z��Z`_AAE�%96����#��G����E �5 �
f	
��%�����
)P����$���)B5��G���v�nh�{{�F���4��C:�Q:�����
�����^�9��:�>����ub���v������������I
����|(�����;z�3� ����1�@8���J&���KU��_��Q�s�9W����n���T�n0@h(���_�����l����544h���:��
��==C�9sRa<��eut����eVW
���A�U��?�~ _�6�0d�R0(_]i��lG��@��`?�����dG"%9.�Q$"+���+�x����$5M���Kv  ����[��O���(��6,��>n�����Swhk{�:"E&T"Z85Q�e�i�AET��@C��	8�j�W�1G��9�:Wy>�s~�xn02��oPUJ:������i&%TP���:��gA!�BB�����s��x��m�&U���j���/�k:���,i�����E����������k�yn�����W_�o�Qc��-��0R�!_M���rOrU������{#����W��jJ�o;������O@�t��
{V�gY�;;������QmO?��~id�$�4+B2*C]��

�|���T�����ym�C�MWw��~����t�A[�[����CUPl1���_/����D���NPmu�
��]���}�y�E����g����@���{�GO��c�?�w��Vi'��R"�@ww�>��O����m�v�������?��z���p���@�+�B�
c�|2��dV
�
*�d������P`?+	��i�*&�)V��r(#��;>-���@��`<�W�V����?� UM����]t�&����E��W��������G����Y��4��#�Cb��<��c1�!d��F*QeaaE
1:_�T,0�X� e��?(���?�������1zm�f�w���6��g��tpC�f�wH����G|@I����,]~��z��G\�}>��O����zm��A���]�v������O?�N8��S�Q��Wp2CFE�TQ!_}i��#G%�|��}�=*&���Hi����D��v	m��WUS�H�+{t��&=�e��n;��M��HU�����+���Q-w�QXg���_%}��X��`cd����_M��X�����X�m�}��5����)�X���?V���������?�������m�\����g��BwOD�6o��������������O���l�e�9�>x�8?�s-��>��E�����hs�y~����{�~,�����x~�+�����������T�~|/r��������{���A���g���d��~���!���0a��\��3���-c���f���+Z�������~}j>����`���g�s�x�����=��O���X8u���W��J��-��#���-E"R0X�q@&B{@?}�����}��������k�������GyD_���i�&IRgg�.��2���;��/�]��_��@@�@@��)�xv,�������
���s��0<�oh���kT?�IR�o��3�iNC�^�y����_�rrM���Z���U�����t���M���m�[��������l��2�'������c]�>��/�E��u�x�q�c���_^�����.02z�Y�Ob.fo�pq
�L���x-��os���'�J�c\������6W#~|Fj���\�gg�9-hk$�3��-m[b������k$6��q}������F;�Ob����pnv��p�p�����l��[����e���B~K��E�7]�1_�;����ymq=dI�B����---�����Zw��7�k_��k�i������`��|��jjj�$m��E��?��%K��j�`�1|>UU2��`
�m��{z�����d�����}=����dY}O�v,}VUS�(���������t���:��iWg�u�X�/�qUaM�
���65V�d�io��e���8F�2>��
��ap���x�/�B�����rZ[G��������\NE�sU�r*���[���8�r�q��O_�6��B�}W���1�9'�3���sr�k�f_?i�+{t���������^u ��������x�@��=�n��V���?��p�B]��Y�O�2Ew�y�N?���������W566�\J�0RE�|��?�m�R$��s�3�y{��kWs��HTF$��PHF4"��T$2�V"�pX�|D3.�D�P�����G���%���X�b�)�a)`������Qy
c��mgg	���
	���,wh����#���L�7���~AS�f	{�
��Gj����;����s9c�������d8Bt��=�bn���2A���������6-���]aOR��[�����'(.B{@�,���w��Zw�M7�~���i���}�Cz���%I����}����}�s�6W���0)�/�jk�W[[��\�4�|�������1���r�+	���*
v��T����t\}�ni�����i_����dR�gK���_��]�|D�--E�)(A�!o�%�z�t������gn���6���mm�����5�:j|�f�wxn���C��]��Th� ?������K��kWjy��YZ�hQ^�~�S�J��$���&�0L>���j���������j��p�������KR�7�����
��W-T�������U��c�sT��S��������Y�������S��!���;�[�������&T�upC�+{r���C�H�$B{��=�@�=��k��3���������e�����������0��
��w��l��u��e��X8��yRmk���c�Q��)y����Y-�W��i����>�	_�>�`�>��N��������T�{����q���>c9��1f����I��k��'����k��<�'}�����ce�����u^�:?9�J�?��h�����E^?�y��ce3�X9���6��h4���w��466*������R��z��Uc��S���n���k����:�>d�k����_}���k���m�Z�]p\�6��=j��-)�v4b���|���i+�[����Y��@p S ���7�p-�x��y�;y�d��9SMMM�����\�R���8�*?"#�����I��T�x��9D��T9a�|�P�M,V���
o���5k����s���NR�����,mmmzk����!������3
���'��>�x��S+��+h��X�������+@���c���5g�7��[�\]�%[`������s������So���$��m}����2�h�����������"����i��������5�ut�\��\�����
��6f��<��4�$���DR�~�?���|��k�}��9W���������E�[�U���C
�lI�������H4&����}@��
�j�*����Z���zh*�����J���s�r��9�t��j�KK-����Ov,&�q3a~����y0\��&�8)�
0���6uXVj�r�"��P"mmmZ�x���a�\��O��f����}]-+��who Z��P�a������P���.m����n��i���~��5����!sTy�1�Z�����"����$U{�Bs���xpAqT-X���o���kT?��Ag����h���3?2hc�Lf�''�w�v=�+h����1e���X;w�,���|4^{mi��ti����9G��c��������v�X�\b��e��J{@��> ����}zX����s�Y��;wj��]��n���9���
h�����s0��@�p
��u����V��?��'��!*�<S�QG
���]��C�a(�����
����7������.�/*Z��pX�|D�pX���R����������a����P��QB������2g����O�%K���W_}U��oP���W_-�`T�:��5�g4\����/�,� �������/��ti��0���k0e\��|��N���k�o���E����]|�55�7����>���I���G�>�)�M�6�{
�21�=`8	����`0Xp������	(�U]�-���bi��Xe��|�������/�H�1o���)I�ni��_��}�V��}�Vk���M����W����+(�=����zzz
����;g�@)�L�������uuE�/ZW�����z&M,J�����O}>���/Oj��R���������M=��yR�����uu�y�yE�3���������rz��|�W�K��P�]w�.�����Y�n�.������4o����X:::������,X�j��%�u��k0��h���>[���}u=�D���<�L����1���30��k0��a(��p����]�����6IR��&�ohRE��;��&NP����9���c���w�m�u����4��4�g���g��X��j��rOP&�����:;;e����������}j���?~������Q]���^l���Cvn0p����3���uuj��m��l�Z���:W��{��c�U���U�)���&��C�a(�����G������OZ��;S��[Z�������@@��';��d��?~���q�B���i�o�70|�
0v�X�!��%I�HD;w���	�������<��P���v�"���U�c�+��[�zw��}�Rm��zUv�B���s�Vh7~C��9:�����[�V���z��")GXO���=W�q��

�1M�'B{@*++5}�tm��1�n��M��6m��Z�;wn��Th��T��mY��#=2A��U2��3��

�������s�z�/��bE��V{�?}�jN9eg�Eh(���s]���+W�����{�U�Ve�E�a�WS-���S5j-R��E
�]���W������JY��������<�P�?Bu���z��?��x����K/�����*�}�m������r ���Z�)�Bs���x�m����������ae�!��,�����s�u-?����m;�}�|�I�����USSS��y����Z���j�	�0��
t��'j��������k��ey���_���|�sj���P �4u��W��-Y���j{��_������kkku�e�
��	�=����z������}�Y}�;������Y�^{�k���W�>��=����n�����_�����:m��5���,=���:������Z?y�d}��_.�t��=�����z�{���u�������������G���F]t�E��iS�Mee����>�3��30���d�����~]q����XL���������{���566����I'�T��(B{��B!��w��<����gmW]]����N+W���E�J6?��/�����K.�%�\�u����W^Qss�zzz4f���7O'�t�B�P��	`���h����={v���L�rO����EBh�"!�@���H�P$��(B{	�=���EBh�"!�@���H�P$��(B{	�=���EBh�"!�@���H�P$��(B{	�=���EBh�"!�@���H�P$��(B{	�=���EBh�"!�@���H�P$��(B{	�=��_�	(���n���u��4�L�����iSjy��U���)��`t�:��5��k0��`(/��P>\���!������#�=`��y�k��/,�D`���y��>��rOPf�'�HAh�"1l���=	��w�^=�����i�������3��n�:]x�����~X�g�.��`��:��5��k0��`(/��P>\������[�7oN-�r�)3fL�&(�'�����.���������u�a��{0jq�����5��k0��a(����u��G�{
�20�=F
B{	�=���EBh�"!�@���H�P$��(B{	�=��_�	���q�t��7����u��k0��`(��P^\��|��l�m�v�'�H`�{���(B{	�=���EBh�"!�@���H�P$��(B{	�=���E�/�����������-[����G


�;w�N<�D�B�rO���^z�%�^�Z{��Q0���Su���k��Y��F	��������~[[�l���{UQQ���|��:�������������/j���jkkSee�f���O<Q�'O.�X0����������W���I������"���������#�8B������+�x�hT�����y�������i��I:��ct�a�e�=C��?������k�������FW_}�n��F�;���rknn�����W^yE����V�X��������1CMMMg��]Z�d����uttx�9��c��������<�n��=z�������E�<��v����m �9���/~��:��S4��
�������������0�r�)Z�d�.\8��`�*�5���Ix���j����������O?�_|Q�W�V4�����^����/|��;wn��loo�-�������Ukk�g�C9D�_����j���qP|��������[��������6������<�M07�t��,Y������*�s�=��S/���������W^���[s�-Fho��e���Ks�����O|Bw�q��������n0����m��
�9s�������������N��\_>��O���������������t�5��������a��_��n��fnX0���Lh�M�:U����t�
7��o,�=��o��.�@6l����g��?�����/x�(>*�(��t�����Gq���|�>}�����a����/�m��]:������O��N(����������*�X/����>�luuu���3Fx�������7+�����W�R{{�x�nV0���+�����|�4i�&L��H$��7�>����OW�^���������{����_��� ��\����i��i���jnnN�Cl��w��uww�?�A?���r\�}�B��,������i�&Wx9�h��%��y�~��_����5kt���f<����F�f�RWW�����DR��x�	�u�Yz��g
��s��7��0z}�����}�����M��~�z����jmm��>������tvv���.���#0T��={����/w�f����~X���z����a�555�3���k�|���H��4�=(�1c������c�=�z���+���o���EK�.��>�!�>����������x���u�5��{Gy��y����S����y�f�Z�J_|�k��n�M>������R\��>������*��T�'O��?�i������u�����5k���W_��+�������~���:u�k����Kw�}w�cD�Q]z������_���jmm��o���k�j�����7�!�����o���������o��|��HKK�<�@���?����o����5�����:�������Z���Z�d�`OF��n��u������#�<2��'O��C=t0���m���/}�K����1����;N,�q��
6h�����3f�p��-�
7���o�9�|����^����=�����7����r��uCCC����(y
�RSS������@���J�Gq��������'�����(�{�ZZZ��o~SW^y�*++s���b����t�����?��3����\y�����~�Z>������O���.��m���g?��������������R^����t�������*�s�=��;�o���?�p������G��~�^{����I�&i��-��]��o����������Y?w����c�Xj���k���:�����'�=eq�����[oM-/\�P��-����_��W�~������Zm��A����:Wi�C{K�.��E��7!���}uwwk���7X,[��(��]�vi��Y����O?��N;-�>�mk��Ez���R�n��}�[�*x|�J�v~Nq�)�h��e�9o�=���8�������b��?�+V��]y����o�s�w�}WGqD��^0�o��y��e�'��#��{���Zw�������t�������`B{P<�V��a�&��Y�=�\FE������=[�7oN���/~�O~��9����G��7�I-�s������&$�e����v������|�i�����z�������e�@_:� z��9��<P����]�����I����7��Zw�]w�g�I�;�<������w��.]�[o�U��G5c��rO
F�s�9����$�|>}��_u�{��'������J�$��+�����P(��}�k�uw�yg������`@���7O�s�k��U�����'\���3g��k��s��{.���~����3@��Pr/���v���Z�5kV��>��O��~��"�Zy��r���l/^�z"�������/unPN�N�'��HKK�:;;s���?�����{��/�\��������k���y�F��\��u�A��w����m�g��\sM�@N�q�)���#����g
�b��%��c����8���>dN�uZ�l�:::�67`�hoo�s�=�Z��8�}
������Z����mn@!2�����f��[�.�\]]�O<1���������4�&�^���]�c����6��k��	K��S��0@y�Pro���k9��-$i����9sfj���G+W�,������w�U$I-x���8qb���t�I�����@�477g�kll��>��������������k0��l�����]��9���;v�����S�:�������C�=%�j�*����Z������F�7`�x���]�3f�P0�����P<�^�s��y��/_���^����v��U�)��v�]wi������s�j���m�����=��kv���u��)�0[S��%�"�����M�\��M�VP����Y3�y�h����������E�@@����<y�����=5�����}����
�<7��m���[����C


;v�&M�T�i��v�]w���>������^����f�^��<����<y��m���m���Z�h�����I'�pB��	#�/�K]w�u�e�4���X�ax����q��)
)K�zzz�a�|����@h@I���[�m������_PS�Lq-����(s���������_��^����1����:K�]w���W�����>w����?a�������-�RKKK��i@~�~�m��5K6l��6q�D�r�)�������|��������s�=�Zw��W��g������R	
�h��k���^RSS�����s�=:��Su��wk��������k]-�D"��g��y�=��#Z�rej[0������N;-k},I�'O����]}�(B{J�����\UU��)r�TWW��P�/����^y����+��w���|�+������J<C��������a���������	�_kk�Z[[=�m��]����?�AGu�~��_���/�`�imm�g>���/�P,���@����D"���VEEEA��p��k�@<��3:�����Ci����6?��O���0g�0���|D7�|��<���m�>�k>(��0�� 
�
����2g������������O��%�{g�^�u�������=(+�����\[�lI������~��>��{����^}�H6�k����S���}N���V�Z��{�*�h���Z�|�n��V��5��Okk�.���^��(�����^�o|�}�$>i�(�p8�Z����4�����	F#�0t��'�[����z�)m��E���
��jnn����g}�3���e��e�t�W(��i�0z�����c������o~����[jmmU$��={���o��?�q��w]]]���?���{�L������7�����k���sM�6��}�^������&�K������'m��Q?��O���~Ts��U}}��~�u���������v�Z�x��2��[��������m�����}����O>Y.��u�r��3a������J����Gwww�>�}���������/��n�����)S����R�<y��=�\��g?�{����N:���c�=�����e�=��w����o~���f�}�����>��?\


���3f��8�}����o�����g��zzzt��Wf�p���~�#�����k�W��U]~��y�?����������j��`Ijhh�y���
�e���t�M7e�����]>�`�c�pt�m��������Nm��Y�>��>��O���=���:����b������0��Bh@I������s�Z������v��'j��9y��:u��~�i�p�	������������ ���P~����~��g>��{�����������d��C�����/~���uW_}�n������{a�j"�0��__��t�)��������q`(������Su�9���;��[o����������W^x������?�	�,���T������m��>:::r�	(�P(�_��W����u;w���O>Y�Y����>7�}p_l��
(��/�X�����Z���F�G}TW]u��3��/�Xw�y�������No����0`�+�5x ���/���y�E����
C������SOi��i�u�����w���~������3a��!��������`$���;������<~����
�����u����������>w��-��c���q�ij���E� ����z�-����L���Y�t�.��R�{�3�8C�������
�k����?C7n\A��pS�k�@�z�������_��m+��0�;VK�,q����{<��}�$m��5g�(B{J���R��Ow���iSA}���;w�����i���Z^�fM�f��!��Z���3fP]J���w�g����][���{��Wt���+���x��z����������HV�k�@TWW�����n��]%�E]t�+��u�Vm��1��@��������`0�Y�f8[�=%�~����+���U9��i��������`��:u�k���F���zKg�u����S��:�(=�������W�����5x���k9��e0��3Fp�k����3���o}��������8���:� ���f
�b"�������Z~�����w��mjjjJ-z��E� n���:���\����&m��-��_|�E�r��p����3��b��5:��3�g����y����'�P}}}��M��|�rE������0��`����F����Z7n��������$i����8qbj���[��������C�=%w������~�i�����O>��ky������)����?���-`p���j����uO=�T^������~������+������h�q�F�~����sgj�����zj����s����J-wtt��������oK-����4w�y
��_~�������	�V���Wkk�k��	<��s�9��|?�j�g��Eh@��x��;vljy���Z�lY^����p-_p��� �^x��<m��2�F���?����~8��K�j��
��	&����/����l���7�����H�m�6�v�i��eKj��)S����US�L)��}/��?�A�����c�=V�'O.��`((�5�����'�p�����4:{�1������I�&y�M|��w�����_�>�lj9�������P����i�����]��,Y�����_������kkku�e�
�i����?����u��vZ�f��W\������s�=�g�y&�>�mk��%�u�\s�L����oT�6m�>��2�����Ug�q������q��������X�q>��O�0�����{�Z�*�>�pX��r�k��>����	��T���X�l�~��_��]x����!]]]���]��=������y���:ujj���Iw�}w���t�M�{..������s�(��P�_�jjjR��>������dm����k�����_���b`�|�+_���{S��`Pg�uV�&�����������u�^{��n��u��o�Y�=�\j���^��o�6hs�Z�j�������q�2��d�����G>�w�}7�n��1z��'5o������|������]u�Ujkk�lo�����/����K��5k�>��Ou^P.��?��S�����F����g���_�X,�Z7i�$}���-��������j����������?_k��M���|�����u���
}��p���W���+Wf���{��o~���v@�v_��`��|�����\�>��������&O�,I�,K�����/|A�6mJ��<y��}�]�3��S�a��[n�g��c�9&���hT�_�������_��_���p0����/�������o���������'L���i�i���:��C�������;L��oO��1c�~������KU��e�����[?���]��z�����*��-����S�3f�PSSSA}���Z�t�>������*�}.�������Z�n]�s�/^�e��������N8����:��c�������u�t��G���3���#��m���E����]�V_������������t���<7�Ju
���{t�5�h��)���Ku�������������b�
���?�o~�Y���f��x�]t�E�
�������7���t�����SO�a��@ �jg����Y����_?����{�n���|�+��w��s�H$���:��>�����@W^y��~���g�?����o�u��������d���"��l,��\�G}�����i�������
\����
oO=��N:���F�E���g���'���.�L��v�������^��}�������[o�o���v�A��W^Qccc	gC���3�q���q�UW��{���������g��p8�Z?f�x����w�6m��z��$]p�z���R�>I38��566���/�E]���;Nc��u��m[��������~�����vm������/|�?�CR1�W.]������������J��:k��q�>}�v���-[�dl�����G?*�|��Ju
N���M�2Ep��������M�6����s�?���/��/E�/���S0��)S4f��A���_�7o����=�����t�]w�4�>�[�j�N>�d�����������RWW�6l��H$���`�-[�L���!���w�i�����5�\��������XL��������Q<��=��^zI/���$���BS�NU}}�|>�ZZZ����z"g���������.\��{L�^z��&��{����_����+��]w�E`�����},����;t�gxn�+8����;��Cw�q��xp������U{{�����g��}���/��"���+d��>��O����v���]�<���W��[o��TS�Q���Y���9�L�4I���/��������G6l��]]]�n��}�������y����g��\������=#<�t�������'�0D���&D�PH������h���Y�UWW�������+�z�2 ���z�����k�i���Z�~�g`������o���>���z��Z�r�>������*k���:J������V%�!�|;v�������_~Y����g`���N���o���}�3�������;���+�T ��n���Z�l�������
��SO=UK�,��E�T[[�g{�4u��G�g?����[G`������N���wt����������a��#��w��]�[�N����
~�z��G��������u544dmw����;���O>�1c�4�a��]�I@��u���+����Y===3f������N:I�P����a������>���^�W�V,�����Fg�u�����Y.,�,}����K/��U�Vi���
��2e��?�x��=������9sf^��r�Vi���E���/�t�R�����*����;W���'u������00mmmz����{�i���
�B�>}�N:�$M�2������m����Z�n�6o���{�*���Z


�6m�,X�WxF����{�i��u��i�����DT[[���z��9SG}tQ���HD�����y�������i��I:���u���m�=�Q���S+W�TSS��m����vY��1c����A�z�?�p�|�rO(��7������M��g�uuu)
���A�&M�������rOC�=��,�)�P$��(B{	�=���EBh�"!�@���H�P$��(B{	�=���EBh�"!�@���H�P$��(B{	�=���EBh�"!����m[���d������;��S�il��
Z�d��<�LM�>]����cJ������������E�]w��9�M�8Q����%9��.���t�M��#�O~���g���o�{J@���=\ss�V�^��7j��=���Ree��������=[�v�|>_�����_�J/��Bj��k��>��2��0�������������,����\�RW^y��|��"�������oj�����{�:::T[[�i��i��9�3g��(�T�e8^������t�m�i��u���}�{���kt�A�yf@��#ZSS�<��A����^{�������n��%K\����n]}����,=���������O�����}���t��G��s���>�1M�6m@s�}������O-WVV�?��?��w��Ez��ge^=��.���>�Y����;OO=����[�r�>��j��������j����t�[�t�-Z4�~�n��_��������^{M�X,g���F�y�����+u��g��p���$}�[����_.)���/~������\���c�{��m����{t�!�������w��W�C�:;;��/��_��f����N;m��o}��w��;v��?��Ok���e�K���?���A��=[Gy����)S<����+={p�=���~*++�~,����3eF��@C��ZZZt�u�i��Y����������K�w�����s��>�=����?���k;$]z���7o^j��G���Q�J{���������z�����m�z��g��3���s����c��9s�����;���(����|�$cC,�m���ZW[[�������+��������o��Z��~P��������i�����?�I���'���2�~V�\��.�H�\r����.���i��7R���d����zW���n��/�X�I%Dh�:����={������-�l���SO�������<�WTT���N��4n�8�7N�PH��������;���������3�}������~�d�����o���#����\��MP�����;,�K}}}�m^{�5m������[n�'>����J��UUU�?��O7n\A�#�-���n�A�m{n?���t�i�i��)�8q�:;;�u�V�]�V�>����������G���;z���|���tm�tW^y����oj��-���^zI�?���>��2�|����s���j��e��F�{�1]|�������6o�<-Y�D��s����r�cY��}�Y�q������Fk�Y�����;�t���������?^�jR���j���/�|������<��k���'�Mbbj��j��61+j����Rt���m/���*U:������j�V�!��*51&JD��K�'��pNN�#����Z��=���N��}�_���y���rHZ�/8��'��w�1�]\\��/�������>���			Z�~��x�
;v����#G�m���L�2�{F�������k��!?~|J���>"����knoi��o�z��e
u�����/�����?���#�P�$����Y�fZ�x�>��;f���4k�,��y3e�����GV���W�X1+V,��T�^=K���+V��w�5�����}�v��5+���t������8���G�^?u��:w����o;l�����vH�����/_����-[��;r�='�g�}Vqqq�������[��^z��K���R��V�^��������Pbb�>��sC�������)&&�0�����y������2d��+b�r����Q�F6�����)S��������={�h���Y��-�������S�V�������n��Ch�IM�8Q�����l�2�/?������}���+�����~�z]�x1e����n��e���o����5O��^���E����)�����
6�r��v�;a�
<�T�:u����/���E^;� #=z�0�W�\����\�
�3�r{0�|��>��S}���z����V���:_Z�����i��*Y�d���0�s������s�������~���-�%J���_��������7�g�]�pA������Q��U�HU�ZU���*V�X���0�t��������/+99Y%J�P��%��aC�����m��~-_��T;v�j������N�����"NJJ��q��b��,����lOJJRxx�N�:���(������G%J�P�j�T�V-�4mQQQ��k�N�<�7n�p�����U�
T�B�lY�b�������c�t��EGG���E�
����j���J�*�����c���~EFF�����?�J�*�����<WRR�����C����K�������j���-Zdz�3g�������RTT���������L�2j��Q�t�<v�����t��9��}[��S�2e��iS-Z4[��s��BCC�+W�����*P��
*���+���_�J�����K������/*11Q��'�X�B�
��������3g�������k�������������k
�:��nlS�bE�>}:��O�>�nxc����X���5k��:�����{��4_�X,��b�h���Z�`�6o�lz��W�Lu��Eo���C�q���k���Z�|�v���;w��y����j���v��i��A�Z������=���i��p�B-\�0�=��=K�~�7N���7]w��%�+W.%d I�:u��?�����6l�f��m�<xP�=�X���z��f�����Wk��}i~����
��!C4x�`���gi�9e�����J�*z��72�"E4i�$
8�P_�j���9����;dk��l

���S��������i^W�L�o�^o���]�������������y�������5q�Dm��I���V�����������!�-[�h�������u���t�-Y��Z�l�>}��m��ruuM����!��l�����M���\H������g�}�9s�����V��?��y�f�g�����`IwCv�'O�����>?AAA����;�i��i��uV;R������
j��������@z����d-\�P�|��<h��|��)88X�����
���5IIIZ�x�-Z��[������^_�zu�m�V��O>iz������oS�...:q�D�����o�i�W_}U��M��^5n�X[�lI�-^�������K2r����M�����HW���i�&���j�~���u�V�G�Z�n]��=I:�����U�REc��M3��f�R�J�4j�(m��%���t7h��~}����^��V�\i����d����g?�����������[Z�d��V�~�L����4i�$U�TI������{�
�$''+44T��
S���
!)gu��--]��T2d����7�z��e��u/�����l���V���U�~}-Y�$���t���3g�j���W^yE�o�v�>n����C��Y�f��qc����C���o_�m�6��.=���W�f��%K�d���z-Z�����s��v���BBB����1c������_��5k��/��������[z��7U�JM�:5���$%$$h�����������f��V���S��M5x��t�LJJ��M���Q#���;YZs����Q������_�5���$9rD��OW@@����#F�0�-�),n��3g�j��
�����[�l��7��'���p2���'L�_|1v����7�*����\�M���W_�y��
�����o����W�.]l�����o��>|�.\�`���� All�]����]���w��=��U��������c��3f��]�f���N�R�V�4o�<���I�����9tss3u��*����TO�����l?y��7n��K�f�s��4c��j������������Ok���6��a��k�NIII6��t�R5n�����V��_�����e����3����?��!C26�����
��)SL��8p��7n�������9y��4h��;w�t���������^rr��|�Mu��]�����{�=�
4P``��6o��C����h�"C�y���^�z��H��s��6m�d�~����41��?�0�J�,��N\�*u��:u�(_�|�������H�")�3g��)������O�~yyy��'�0����o�,YR�J��y�&M��1cLuOOO�j�J���S���������;vL7n4���Y�����.-			j����l�bz���Uu��U�-T�|y+VL����r������)$$D�Js�����_�RBBB��h��*_�|���U:tP�%��,X��^{���,X`{xx�w����s��M[
eV�\Y��5S������#777EGGk��=���			2d�J�,��������f-<���O�d��_�m���������P��q#[:�9��~��e5m��j��\�r����j��)]�|Y�����U�t����[�nU��-�c�(P���<��=�^���~�i��QC>>>������{�r�J]�t�p��-[4m�4����^o���iv	+[��Z�n�Z�j�D�rww���Wu��I���j���v��������kW��������[�B�
�����t��!-_�<��6l��I�&��(�f��)88X�J�����"##b����K���aC�>}�����?��� =��c)���/_���;���?��������v���'�|��oI��O?����;'IrqqQ�����eK�/_^^^^��������j�*��?i�$=��3j��A������/^l���\�Z�R���U�xq%$$�����C��g��;�J���#
����(�X�B}��������oM������4G``�\\\���y�:u�d�~��='c-�S�^�\��c������#�Z���si7�K��g���Z�pa��L�2��o_��������06l���o��6m��w�y�P+X������^zI�
�z��I��y�f
2���k��������#Fd��k��f5���kWM�81��;������/����Z��i��
���;��o����]}����i�RjPxx���"��=k�*��kWC(���^z�t.�����O?U��-M��=�n�����5v������bQ�~�t���+W�������0S-����]����������M�:|=g;�-�h
�,XP|��^y�������1c����)S�(999����~����Y!!!)!�R�J���?W�n��^��Gi�����o�>�@#F�P��3\o���z���M�J�*i������g�?W�����k�Z=�����sS���][�f�R�F��^;c����<yrJ�[�n�6m�����^�:�����>}��{�7�'�|�f��W^��k�����k��i)�����[�n������3���������5h�@_~���3~�����P�n�?�III7n�~���L�7e������`M�<9�����sZ�|�)x|���{��7�PtttJm��Yv��f��e�.]Z�;w�iOOOU�\��Up��=6�xP���;rU���d=\��7;��d�5���z����[___�������N3�wOpp����L������������/���*...�2e�V�\�a`O��T���������P��m3�>7
4�T�'4��7��~��}�e��B����sg���W�Z�J7XT�`A����Z�v����S�W�^���m�N�������j����������^���7�<<<��O?���^����>W}��f��izm���


�y/��R�*U��]���I����,X�6m����]���+3\���;�������c�),,L�z�J��J��������j��m9 v�{��&M�h���i����Cf�{����b��4{���2e�~��wCm����m[���)��S�����6�O�:e�����g�C���ys����+j�����7n��3g2\����z���M�W_}U�6m�T��l��z��Wu��Q=���V�)P���b�m��U��W���o��m:x���6d�����wAk��e���7��B{���:u�d���8{���V�T�lY+'=z�T�P��C�h��]����?���{�n�f���K�R����Z�z����S�pa�Z�J���O�EGGk�����7a�Sm��1=zt����������Z�j��U�/6�~2�:�S�|y5o�<��-��{��Oh��e��,#�[���q�����������#'$&&�����z��e�mMks[;�����O>��T�<y�Z�h���_x�
6�P�X,V��www-[�,S�...V����_3�w���`U�j��n���^ZS�bE���m����K3wgV���m~�o��i��m���>���C��4h�)�6m�4��g��{��w�e*����c:W����q����8q�)���OM�6-��lZ����nPr��a��/��fk�1��������Cm����?�7o�Tdd�]s���?�	����������<��[����W��j�	�EDD���������<Gppp�7�C����O?��P����6lh�\�*UR�~���V�Z��_~���[�n���;
��{L�����k?H
d� v���Y�F��w���[�n����
����X�n��#����
]�2���_�G}���XIw�J�_�^�y��c�D(�
eks[;�����]�v),,�P�U��F�a�<~���.]j��V�X�i�����e�O�>�[�n�����W@@����Sj��&k&O�l�-\�P����^�A����;�s���?6�22o�<EGG��]]]��g������c���_�b�H�.^���;w*((��y��g�y��wo�5��K���t��D��-3�J�(aWw���P��:t����W�����[}��G�z�����b�
C�}����S�\9S-""���pt�p2����Z�n�:�8{g5g�c��?�PK�i����7�w�����o[�v��5�����.7������}�YS��������Z
80�{R%�V�js����Y�f�������+�����`����+��Lg��n`/����]��)�g�}�PKHH�����sW���
ck�]���_��������/��*
<�a�U�ZUO=�����>��7o�G}��=��������zzz�O�>6�S�hQU�Z�P����u�L]��
������9�0�~��/^��{���g�Z8|�p��R�tiS-����������)�~...����~����0u4����a����z���=_��D|||��S!�����wo��~P-ZT�;w6�~��]�x1�{o������jAAATR���7��f��z��{�fi�����j�vg:��o�n�u�����z������S�`AS/3*W�l'%%���i^o-���_?��}�U�R�j�3{�������
		1��4i��}d�|k������o��������t���g�e���Q������~�E�g�6�*U��6m����Gy�T���k�����"((��:L��`������k�rg3p��MS-u���:u��*V���9���@�=��{Rw�����hS����� D�:u��~^4h� -Y�$e����o��Vo��f���X��J�������a����/�S��M{�_�����87,X�j=�LVX;[��yv��=<<�0.W���P���+WWW%''�9F*T� www�����0&&F^^^V���s�������&   ��S||��6o�<����v����3����[��y������J��(Q���m1b��5*e�w�^����A�i������������/������s>..���gFh�����8M�����c�����n����H�8!!A���w�W�\1����M�g�Z���3k������t������2���?�0������Y��X�.]��K�.����Y{�sS���M�/){�?ks-Z4[�r���b�����5k�=�������t�������)����KHHH���??nnnY��D����>���������5�l=�����I����
���0`������3g�L7���_�2�g�����%�4'����('S�\9S��A�������b���
��a�[�n�j������]'g����j�������'""B������W�����{���UnsssS��%M����g��.\0������,g����M��"E�di������"=�t��G�}.\8K]�D�
���r�3,=9�����B}9�����~��j��-���W�^�u��j��wW�����k�����B{N�z���Zhhh.��1<==M5[�Fi��}v�~�������;�=4�Rw����d�X��t*���8����m����Y���;m�c���E�����R�a��%Y�t���=��[n��9�0�u��,X`�������Yw���Y����e����='S�n]Sm��=������5�l�����K�,)�����Y�Y��t�����2�R�����SOjK�,����b�h����Z�����Q��I�K�[o�������j�u�Y����Eu�������l���6�����4g�����R�a���,��o3g�t����_Xr�3�f��j����6k�,�gAbb����k���UKM�4��������������	6�.^��C���f�B�
�Zddd.�$�(^��a�S]��+f�=��Rw��v��~��G�u�7o6G
��5R����v�v����W�/_v�Z������m�3g9�*$WW��v�Z��L}���O���.�������Z�����[p���|���������������=zT��������?������a�����Y�w"��p2�=��*U�d���=;v�u��B{YS�dI����;�_���������v���l_��t��]^^^�����M������O�������cI:}��
�|0�h�B�<������`�X�U�o��w�}g�w�������Y�vSh����v��3g�j�BY��T�R�qbbb��&S���
�]�r��q
��&������9�~�����g���5+�������������;g�U�X�!s����J��K�.\����\�M���]�T;r�H.�$�h�����e��l_7��
0�����@>�Y�����={j����!���+W�i���J�.��5�T�b�V�c�%%%����#�<�=z��s��q���|�rS���Up��8�����822R�.]�k���0%''ju���{o��Q�F������u�B�
���_�k����;b;N!00���1'>��A�g0**JG�������g��wg=k���{�9�u ����
�G}��3�������C���i������������r����QNw��kZ�je����9�vpp�a����%K�d�����9Cp-u�*99Y�|�M�x��e�y����A�ez~WWW�h��P�q��6l�`�n,�F�2��;��S�:d����[=K;u��
*8d��8����qcSm��v��|��L��R�_�����f��E�1�O�<i�w����]�������c
v����������3����CU�@��qbb����+�n�=��b�~���Y�b����W�^=��
8#B{N���W��������_:<�s�����o�3�����������uAAA*\����r�J;v,�������6m�4%&&f���;���q#����&M��j������S��^+^��:v�h��:u2�>��C��x��[W]�v5������To�����?o����O&L���q���M�6��W_}e������-^��PswwW�f�l�'���YS��W7��m���;wf����;z��bbbl�c��Ey�����m��I������CS}���vw`�G�%L�b������8���t�3�O<��uO�8a����9�+�8����?�_��X,����~��w���p�B5i�D����/-�[�6�O�8�.d��y����)������}�������v��
��SOj������mk-Z�0��SUvH�9������}��;�m��^{������n���z�R�*U��[�j��i�m������P�B���[���U+�:u��y'L��9s����G����?n���p���~��
4�8�Y�f���;������P����|}}m�p���p�����K�Q.11Q��-���111z�����\7r�HS����N�V���
�???����P���rX7��9r�a|��Y
0�����}m���T� �
B{N�`���������i�_�~]O?��f��msW�{�?�g�yF���e���3�����l_7/{���T�xqCm��������]���|���}�]m��1����k�}������Ol^�����x�b����U�0>x����=k�Z�6`�����P�?����d�e�����{�=S�����f��m�|�����q6~~~V��3g�(88X�w��i���o�����.�W����svq�����_7��x�
m��%Sk��7O_~������b���3����*U�d�=zT�����k�l�/"""��[�n-WW���0aB�����x���7KAUgU�pa�������bQ����z�j��]�~}��l5f�S�{���z���e�Xl�+))��������^�z����+
�b���G�6������+_��{�1��8B{N��'����K�?~C���;6l�j���+V���[�������7����S�5�v�����I�j�T�fMC���~�����B�
i��%rss3���]��u�j��EJLL�p���x�^�Z}��U�
��d&i���)�c�X4z�hu��]G��p�S�N��>P����/��{m���
���d���C��������)c�"�l�2-\��P�O<a�}��1�5l�0u��M��<����>}�6l�&M�h��5v�''����j����3j���^z��S���Z�v��x�	M�<��z�����?����Q��g8��}�YS����[j���>���4�����3f��j
������r����]K�.U��?��S���Z�|y�����8-]�TO=�T��\???S7���H�i�&��Uxx����S���~Fs����o�l��P�q���t��^x!�]U�;��'���W�v��vts&5j����SM�i���E���l�p���O��j�������k����6p�@�=w�E�6m2�:u����g���%yKhh�������&L���;:d���o�^?����w����X�k���z��!5m�T���W�%T�xqyxx(66V�O�����e�EEEe�^���o_���;)�5k�(11�:�G�v�L�{j���Y�'��h�B3f��K/�d��8qB}��������u��D����Rll��]���'O*,,L����T0(��>�H{��5u�Y�r�V�Z���@�h�B*T���������?�������g�������:u�$���?)�����WO���*S���`��}�l��l5h� �_�>ek�9�����f��������(?���~��=��


R��UU�X1������k�r��<���0;v��N�`���rqq1uwLNN���35s�L��[W��7W��eU�T)��yS.\��#G�v�Z�ss�j��i���*S�LN|)&�p���?_u����Rjqqq5j�>��cu��U5k�T�"E�}��i��U���6��?���}����@}���z��?'N�P��=U�\9�i�F�j�R�������k�����S
����u��MIRPPP��M�0A6lPRRRJ-$$D��WW��]��I/^\7n������i�&m��=eoU�V�3�<cW7Sg����e���q������S��Es����y����zJ�>��|||����k��)**JPXXX��]g4j�(���[�}������^�z�]��Z�j�J�*�x��JHH���Wu��a���*44��������K�G��������a��ei�����K���7�������gDh<t���l
�'�0���n�Z�������BBBL�������~��{]�=��U+Gl3]}�������B�r��6o�l��c���gyI*R��C��I������
d
�\�tIK�.���K�����~��g
<X�������d���[�w�v�Z���O4p�@�k���:r��C��G�N�T�X1]�r���
P�>}��F����a��1B���3���~��i������{�1
:������0������������;j�v������W[�nU��mu��q�kg�����~����6m�5k����9�!C����[�
2�###��^fM``����q����n���E��h��4�-]����_�o���a�q&E���;��_?�[���ZRR�BBB��l�.T��%�v�;p�@�;���@�2d�&M�dz�e���R����Z�r�a������@��8#���2�J�*��s�������+gi�|���]�v
		��e�T�lY�2m���W���
���
��n��)44T:t��<nnn����j�����=<<�x�b}��g����{�b��ex��4w�\y{{��Nv��?���{]����C_�����;U�T)Ks�����3:��]������/�����5j����+��?�z`���>�+W��;v�g��rqq�i=www�5J7nT��E��v������m���M��=G��%3u���c��{���=���;��\8��E����~���~���gZ*T�����9���US�L��%KT�bE��pqqQ�%�������/_>�uGIJJ2���_|�a��������E�
���G�n�:
0@�K����^^^


��)S�u���~����c��_�0^�l�bbbrtyU�j���O?i���:t�}��L�W�X1u��]�g���s���O?�Z�j6�=r�H�<yR�'OV������������U
4�������=��3�Z������s�4�|���OO>��|}}U�`A���h�Dy���t��Q-Z�HO?�t�C����z�����'ueIDAT��?���s�<y�C��J�(���g���S�8q�2|�������{k���:t���v����Mn��%J����K�{�n���+�^���5t�P>|X3f�����M�9���m��U�����t���0������?����N�c��������M����y]�*U��g�)$$D*T���2���+�����_~�f��e��ruuU@@����k���:u��F��;v�^�z�����={����2L�]�����#G�h��v����g
J�-[6�����~�zEFF���)���;l~�Y�X,KnoY��������v����������E��h���V�����3p�nu��Uxxx����>���#sqGy��3gt��EGG���+�������
*�����F���e������g�.]����(��uK������Iy*��uF�����w�N�>�+W�����������U�hQU�ZU5j����Wno5[\�~]���'S�5777yyy���O��US�5l� �,r�lOJJRhh�"""�����H�"���U�j�2���A������0EDD(::ZW�^U������+�f��*_�|��������[u��9]�rEnnn*[��T�fM|%���o+444�{t��U������[��W�j�T�z�:4jM\\�BBBt��EGG+66V���*R���T�"�Lu���
6�M�6�����5n�8��/��8�f�����o��@�[�@�Z�z�:w��2�Z�����o�<,�u��~�!e���������;�5j(99Y������'O����!�����@�����4h�2>v��V�X��;x��={V�W�6�:u�����'ON	�I�+��B`
:� ����j��y��N�:
���K.�
��0b�}������-[����!��;wN�*U��;w$I>>>:q���)���gG�=��f���[�n)�}��i�����#��Cxx����+C-00�a�=I?~|J`O�������*t�@�8{��j�����8IR�J�t��a���?�w��X,�X�B����.\�`x��_U��������U�V-%%%I��g�����D��p��
������E�i���)���U�V-w�7�Y�Fc���$����������7]��}{�������w�Mw����:t���h��A�^S�T)����t��9�+�����2�+W�o��F`�n������M>>>�]���t�����G��my���b���&�\s{���pB{8�=��Bh!�����A�� ��pB{8�=��Bh!�����A�� ��pB{8�=��Bh!�����A�� ��pB{8�=����J�*���\�IEND�B`�
#217Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#216)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 10, 2025 at 3:06 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

I ran some experiments on master with datasets and access patterns
derived from Tomas' original bitmap heap scan benchmarking scripts to
try and identify a good default effective IO concurrency value on
master.

I've attached one more set of charts for cloud storage that includes
effective_io_concurrency 0 (no prefetching) so that you can see that 0
is actually better than the current default of 1.

- Melanie

Attachments:

eic1_drilldown.pngimage/png; name=eic1_drilldown.pngDownload
�PNG


IHDR
�lg�T�:tEXtSoftwareMatplotlib version3.10.0, https://matplotlib.org/�rXr	pHYs.#.#x�?vIDATx���wt�������PIMBo��# �tAETT�{TD��
Xh6$H	�I�=	!BI�������$��M6����=���[f��sg���Z�0����
 /!p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p7"p����Ge�X�^3f��t�r��3L�~��QO7@����*_�|i}M���=�$8���V�����{�I��V�ZY�]�Z������/oU���s�~����~���=��r?W�o�}���+W����+Wz�Y���}�����y����,_�<�
�3|<�nE�����g�>��'O*!!A���*R�����T�hQ�y��*U����j��g�URRR��G}����m�\����H���O.\�a*R��*U���
�H�"�nb�ILL��]�t���>}Z			JIIQ``����T�xq��SG!!!�n*�������wk������S\\�RRRT�`A*TH�K�V���U�|y���y��p�;v�.\���dI��a��}�v���z�e�[�{������������eK�"	�1�G��[o��-e>\�}�Y��)_���;f�fF�������?����Yk����+W2�����w��z�������v���TDDD�v�.]��Y3����a�i5����[k��q��]�v�V�Z��'�xBS�Nu��y�����J��������Ry��l��������/����kv�����v������W��ms��9���S����p�Bm��Q��������;t��w���V������-Wn��������������b���t���Z��j����M��"6 C��_��?��o��Fk�����W3������5k�A�j�����o��c�*U���j�����={���/����?���n^�n�]LL���2e���g�����
����?�z�����P
:T������%&&��W_�J5jT������`��q�F������7�J���2[�n�ry������z�����Q#��;7��=��~��W�s�=�������s������c��������������
���#G�h��Y�����7�x#O}6@JMM���W�#G�(22R,���c��O�q�*_����ym��������b�=z����t�j�����U�V�n�t,^�X+V��?�?�����=IJJJ���[5y�d���G%J���a��K�����Z��7f����y�A�[�{d`����T�����r��
/^����U�b��������u�����{��Wu��M��>>>j���UZbb������O/@���C:q����$pp\BB���o��':�*���s��iSEGGgS�r�a���OT�jU��5KIIIY*/**J����������
n���'�|�z���U�V._;��0���O�K�.:y�d��KMM������2����)�>}��m�����>�`��
O7�C�|�t��w:�����:t��UZ��U�bE��q��nMe��Qppp��	sCk2����a��i��	��'44T��s�*V��b��)$$D����p��<���Hm���r��e����z����{7$IW�^����k�f���=�[���e���V�\�v��9U�aZ�jU�_�r�����T�QQQ�����BCCU�Z5��nW�a����{l����O�>�T�����t��-\���z������S'�^�Z���������k���#����N�=���W��mU�|y+VLE������h��u��m�RSS�����h��q2dHv�p����]�zU/^T\\��_��a����5k��\_~��
(�M�r��������l��j���j���b���`���|��.\��h�����}{��@�y���4c����/��B#F�P���=�(@�G�$I�J���m����r�J��F���OwU���/_���^���������n���~��[�{n�����Y�f��f�X��C���^R�:u2-+..N����_|�;vdCk37c��={6m�F�j��E����^�t�;w�TLLL�����RRR��t6p����U�VN�
�]�?^K�,1�����z��W���k�>r�H-\�P}��������###���oj��q��fw�~�����~�X���7___
8P��W���3-���s�����_������\d�����G��]�|Y�7oVdd���Y�e��)99���o��F7n����%JdCk�3F����G{���������WO|����i#���aW�\�o�����Y?������T�VM�Z�J�}"!!A&L���4nM^�n��o�a7h�j����y����{���$)00PO<���o���s��\�rnnm���g�}f�6h� ����[W���Vi�6mrz��m���?l51���o{y�0����o�aJ���/���o���n����V�XaZ]��O?��������'���w��wk��=�0a�CA{�T�D	
>\�����I�����\�P�Bj���^|�E-Z�HG��k���B�
���s�N�n�Zqqq9�P�G����{����{w�]�Vm���4hO�
(����k���:u��>��SU�T);�p�����'N��k��y�5�[�{�$""B����)�I�&���T�n]������v���G}4+Mt��e������|��9\����ie���$�Y���6�����C5k�L�>r���;��2%�G}������Jk�����i�
h���ViIIIv���j���={�)�k��Z�|����]*���[�
���;��}��6�BJ�.�w�}W�6mR���M��g�������<a���������4c�����Tf�"E4b�}���nh!�U=z��z�att����{�5�����������0����p���
�r�9s�>���,���o���j��{�QPP�����9�B�aZ�jU���bQ�-��eK��<w�����c������h��)�tg�^x�-Z�*��~�������kw���M�j��y����r������_5b��,�n-U�T��
��ys��/^��~�����_�����x�5w����<`�6}�t�p+��t��r��m��A�����������P5l�PU�Tq�����+22R��K�T�pa�,YR-[�THHH6���.^���������x��
*�b���^�z�Z���������
t��i����@�*[�����.�/_�����������c��={V���JNNV���U�P!�.]Z���W������%\v�2e�:d������3g�P�Bn�����wky�\�pAK�,�J����Se�����p8��;t�����Z�j)88X�Z�������tt
w���M�6)**JQQQ���V���U�D	5n�X�v�Lg���h��m���u��9]�vMT�����m�l��Uqqq��q���;���h]�~]!!!*^��4h��%Kf{n��9rD/^��bQHH��u����������{�����.���K���V��r��)<<\aaa��9m���:{��UZ�
T�^=�����S��������]�vM?���������f���_qqqVi�
���3�����z���\
��z�������{�*&&F������QPP�BBBT�N�lK����=���������G�V���U�Z5�-[���FGGk���:|��._��"E��x��j�����+����e��]��u���=�������L�2j���
,���RSS�q�F:tHg��QRR����U�jU5j����;�}������W111���U�b�T�re5l����������y�fEGG+&&FW�\Q@@�BBBT�JU�VM
�RQQQ��w�:���8%$$(  @���
S��
�>~�u���������u��%,XP����\���W��-���<�o����������t��q�={V���*Q��j���:u��b��������_s��Q�z�t�������+����K�bb�<��{���?����`�V�ZN����S�Ni���:z��.^���W��p��
V��e��A�<P�f���r��9m��E������Rjj��+�v�����$&&j��M:y����?�.���O�Vxx��W����PO73K<5^�)91��	��3��u�]hI�������_EEE����*X���/�2e��a�������6\�rE���:p��bcc����"E��u���Q�F��=}=�o�>���Sg��Q||��)���p5j�(����~_nw�����G111���Qjj�T�T)U�ZU�+W���<G$&&*22R'O�TTT�T�hQ/^\5j����;t���o��S�N)>>>����Q#�����g���9sf��?������B�
�R�g.���0$Y�Z�l�ryG�1�7}��L�M�>�����#i��w�����������x��W�X�ti���Z�����{
ooo�ex{{:t0v�����g������U�r��Y�}���F�=__�t��\�r��_~i$&&:�n[�-2Z�lixyy�[_�:u�����HMMM���eK�}�2�i�&S{���r;t�`U����q��������6l�Q�D�t?��_
0�7on������}�����6j�(��gw)W���������+W6�{���s���c�����9w��Se���E��*�����t��C�?��3��C�5�0���2��22x�`�~M�6���W�\1>������2,K��������ysc��iFrr��m���92"""����3�y�#((�n������|G��;�t>���2>���L�^�r������&M��{.���Q�������/_v���RSS���g�7N���������N�:ex^��U�T)��4f��e\�x��}��^x��~�7��r��[g*�W�^��b�IHH0�)bj��o���6���k��1^z�%�a�����O�����K��7�;���,Z����������U�lY��'�4V�Z�i����"""�v��e8~�^��1k�,����l�����4Of�%��]3>���|����9_�|F�n������6����1�n����[_�B���Z]Cdv.���s�\��dv�v��c���O�����#�����m���3����j��];�1���g����O?�4�������Y�f�=��Q�l�L�	ooo�~����)S�����e
�0����w�}�h��a��ooo�q����1c��'OfXnn;�
#��^��9b����(\�p������G���&�w
x+p���Q��������?��2�n�j�5�h���������W�X1c��N}�����2�6���6&O�l������ ���3Z�ha��3�HIIqx_�������Xc���F��u3����������&Mr��\V��l�YyArr���w�:t0
(���W�R�>|��e�����������8|�p���u�VS;F��T�5^w��vg����Oh��������{����}��S�����g8>�d]�vuy���wm���F�n��=O�5�n���z<))����O�����[������cGc��5Vy���xj�y+��m�����e����;ht������3�r�u���it���(T�P���P�������8s���u���=��M055��:u�Q�^���:����8~�\�b�w���t9������r�[!po��	Ml��>|�iB�����!C�8\������w�9����KMM5�x��Lh��U�n]�zn���1�t��p]��V�Z����a�\��aF�Z���*V�X��O�8a�h�Q�����|��9�y��*Q�����)�b������~��7o��g�n��Y�K���]*�{����e��e�����U��'��NJqt"\��UM�q$��?�h���9}���Q�����j�
M��:uj��	�#p��?4M����7����i�)S�%K�t���;w�S�L��p��Y�E���io���c�������_vj?r�F������q����D#��V��,Y2Z�>3g�4�����K���a���M�J����c���Y��a��[��v��NOz���k��'�|�����o��Aw������y(�����1q�D��|���@���`����3� p�Q���7o����Y��E�u����v��/(����3��������S�NeX��/����p2{�.]�����$''c��q���=7l��n����7��{����>s(����l����M�� p����#<<�T~�n�2��g���q�e�X�'�|��v�Z�uew���?�P0Dz�j�����,O�INN6�{�=���;���X�re�ud��J�[�{���3*V���g�����\�~��}Y�|���Le�������=^�d�^N�c<�s����N�<9����>"99�x��7�3�x�w�}N���]KLL4�y��L�=�������[�5k�t�N��b6,�c��gf<5��U>|����k����^�j���|w\�:t�n�pf��o���S����w��a�Y�fN����C�z����&M��T ���G�;V�<���_��p��?�\���z�vbb��v���':\Frr�����E�9�^wIMMU��}5f����8�o���j���._��T}111j������r�J�h�B.\p*_V
0�j;::ZK�,q�����N����q�~��i��1JLLt�Nd���������z��y�5Y�������[��j����Z�nmJ[�re�����U���-�Z�h����eK��<{�����k�V�\9�q��{��w��C���S��ak���j���~�����������O���+Y.�Q)))z������/�0������X�B=z�H7oRR��|�I
8Pg��q��s���W�^z��w\j�
g��U��M��O�:z���5k�R��&%%E��o�J���U����.���W
4�J;s��K���b������BCC=����#:q�������5f�u��E���.���g���{����[]nG||��y�]���;j���N����?t�}�95�u��7�I�&��PFRRR4d�M�2������k=���:���y��M�4����u�&M��>���8���?^��s��m��t}����w��O?�TW�^u:�$]�~=�k���H]�v���%����j���f���R���X�{��z��7��lo������+��{O��^�u�1�������j���6o��t}�///
:����dz��={V���w�n�04u�T�h���s�;�]�����$���G�76]�f&���\�tI�;w�����R_u���k�N�|���������_T��=u��A���w|4j��t���7���]�����������i�*U�d��S����S�O�w�9g�����\��n����w�qil�l�25i�D;v��R;RRR��gOM�0��^��<}=���[k��]�1C_|�������>�,�����"""��A-\����;�����7�i�����?�������#G�w��N���>|X-Z���5k�����_�������&������u[������
������J�(�N�:�^�z
		��K��}�v��3G����������k��j����y�����i�Z��:u��J�*)00P���Z�f����g��Vjj���V�Z�H�"���7y����&��)SF���j�����]�|Y{������u��������+������;TWrr�:v�h����%K�k���Y��BBB�}��i��Ei����G�=�X��y�>��^~�e%%%����1C��us��o���j;,,L���O���&�+VL:tP�Z�T�T)���_W�^��K�t�����[����� ��MDD�)�M�6h�{l��U�.]�Js%8G��g����}�v��k���������-[ZFGDDd�*���������;9r�)���G�[��=�����0%''���Z�l���_o�#~bb����#ooo���+���������O����S�����U+������G'O���
��NOBB�z����K�Z�W�TI��������������]�j��e���*UJm��U��u"���j������_u��������#G*$$DC�qzRSS��W/>|8-�B�
����U�jU�������:r�����o��������U�N�j�J�+WV``�|}}u��%]�pA{����;�i�&�e��G��/��)�|���T^xx�) r��}*Y���m�N�������������R�j�T�|y.\X
PBB�����s�N���o������d����k��������^�{��g�o+VT���U�J+VL�a������6m�����,M������#U�TQ��U�jU������u����o��Z�J�~��^x���w���'���/�M����Q�V���uk������_g��QDD��.]j�;�����]�v*_��C�����2d�iB�����7o����+,,L���:}��"""��_�M\~��g5f����8������g�M�?+R����o��M��x��JMM���G�d�m���*oBB���7�����m�?��
��I��?��7o�-Z�D�*R��.]���g�j���Z�v�N�>��~Z,��UK�j�R�j�T�X1.\X����t��>��7*""���+))IT��5U�n]���x�����n��s���j���Z�j���0)!!A�����m���_o5~pVN��{}��';v�)���O��{�Z�h�R�J)!!AG���E��&�'$$�k������Cu�n��mkJKHH��;��>

R�
T�Z5����p��*T���^�������[����wA�o������O?�[v�B�t��w�m�>��D��>��T�R���������5j�j��*Z��
.,�0�h��������t��e=��C��u���)�i=9}����+j����l�b�[xx�Z�n���k+88X>>>�������l�2EGG���F E�%t����������*!!!m�`���X�b��uu������W�������YS���Sxx�BBB������X������q��n�����g�}V���O������y���#�8���3gZ�?Ir���x=�yj���6m���'[�-_�\_~����nw��>"55U]�t�H�x@
6ThhhZ����?��kO�>�-Zh���������#����;�A�*^���^���'O��_��b�����?z����o��/��V�F
u��Y*TP@@���;���7��_~I;7���Yz�\n����-]�T]�v��������{�Q���U�X1���+..N����M��v�Z�=���g��j���=�J�*�[�n�X��
.��g�*22R�/6���y�v��~���lo�;\�pA�[����'M�X���w�n��k�����K���~�Aw�u���c�P����^�Z]�tq[�<"���@�aH�z�l�����9b*o������>}�)����!����6�y�����v�^�x�����)��������m+V��3gN�m8p��Q�reS9c��uh�����#G2���_?�<���3,�!�0&O�l$''��{��u���_6����m�<y��v���[��������c���D�yRSS��'�
J��?~�}���[7��|||�s��9]��5kL���k�����+�>�>���v�Z�u%''k��1�z�)#<<�����Q�F�t<�K�r�L�g$111����5o��j���?��?�6mr��������/^�0���~j���g�����3g��^�L�L�1h� �~}�������5����)O�f��}����o���F��UM��c��e�N{������G�������w������+�aN�>m��W�����������tF�i�[�tic��9��[�0����)S�X��7�Q�7o����-[���-Z��������T�ySSS�����W���B�
��5k2m�aFll�1{�l�E��+����������+3��/7�i���C��=���i���\^v:~����,+�bVM�>��P��1f�c����INN6f��e���Z���b1"##�{���v?�:u����{��cbb�)S��k�6�����{m�i�����fx��t����c�����\������	2k�a��.���;v4����n�������7�1h� ��m:�J24h��w�����=����~�1�$#""��6x�/s����[G���+�{�o7�#��x����.�����~��N�x��������F���M����g����Flll��SSS��k��6���3��l�����}{c���Ftt�Cm���6��v}z�U�fM���h�<`�O��b<���]�n���x���"E�d���qo�{�������c����'���`��D��9�g�����b.\�T��_�a���#44�x��W�
6)))�����j,]���T�����s�:�f���F�r8�=�*U2�w�n,X�����s(���G��~���������9}���ZM�Q�zu��?�H���0���+�{��g���Z�

�����v����i��o9�����f~���2Z�j����������~jT�P!����k�������7o�poV�fM�rJ�,i$%%e�''������j���xJTT��s�$��0V�^��mpw��{�����f����7F``�)_��
3=��w���"ooo��7�4._��n~{��<u=���j�m���?�������w��%c�����=_{j�i��:�0�������D����3��^�v�X�h�q�}��������^�^�v����;My�����3g��/66����������>��^W���������H�"������Wf���u��ISY����Ke��[�W3�J�9pO��������7$&&�&PX,���%K��p��
4�T�\��]w[���?�m�����h���;�d�����F�|���������w��U�V�����[�x����?���r�|�IS9�}Wv��ez����]jBB�K�r���w������G��P����Gx���p��=�z�2}>K�,�0O�.]��oo��m����3,�J�*�v����j�����q���L��������$�S�N���(�k��a��������;we��5������~��k�^^^Vy�4i��D[��o���$��;f��v���W�%���w;\�a�/�`U����q��������7����5�����s��0��:u��<GZ�����OS[}}}�}�@N����p"wF�;f:�~�a��FEE���W�^Mf����2�c�B�
�gSSS�:��g4�f�
���z���
�8x��i2X����Kl��y���MJJ��`�/����'�7������w�����m��u(���)R�X�b�C�ov���L�[���m��1��VG�0&N�h�����p���.^�h�?>��{������u��v�	�����{��x�
�;p�0��/��r�y
f�'66��[�����(��f5p/+}����M����{3����_~��'S}]�vu��������7d��L����{;w���p�#F8�o�,999�����+�zv���T�&���of�'���9����Oz��3�����0&O�ll����~?=��#�9b��$c��q(�������G����]����'��-f�S��?���i?BCC3|���>���t�O���=9�4���i���Q#S�5jdx�HOf���z]������;���k������e�`O�������*d�[���:�
���'=���Ve�o����y���<��W^Q�n�2}����F�i�f�bbb$I3g�T�J�2-'<<\�J���:�D��c������;z����/����=�|�'OVbb�U���?����;To�����{�9�^w����BCC���O��TW�\��9s���5k��w�������:U�

p)���9Ru�����w�����'N�M����J���o�]�xq������Z�nmJ[�re��OMM��U���Z�liz�mZFe�={V����JW�2e��������-[V?�������n=7k������^��j���>����:����R�f�t��q��_|Q?������g��1JMMM�.U���-[�"E�8��;��S_}��U��������;\���N�����;����m���*V��R��j�{���XSZ�B�\.�^�����\^v���-ZT���h�d�X\�[�lY��5w�\]�x1���~��.]�d���ys������s�-���s:��������P^��b��td��n
6��	����m���p
:�*->>^����0_||�f��i�V�H��3��~���G�}����-��{�~�=�������{y�5l��*������k�2��	&X�Y,��3��x-3���������V�~���gO���S�f�/))�����_~��z��v.\X���N����^���k�������J�X�����;���J�*����n���x�����'Of��@����q���� ����u������T^Ve�9r�4h��m��M��a����b��~�m��;��Ss��q�������k��QVi��OWTT����M�;V)))Vi�<��>��S����y{{�{?A�,ooo���':U������3�>���zv��8���~�m5i�$���:uJ��O�SO=�:u�(  @�5��a�4o�<�;w.[�����+))�*�{��z����_�~}M�<����_��iG=��sz��]�����������O����+;T����?��'7���M���m���*-$$D��g�����/_�M-�?IIIv�G3f�P���*��w�����k�v��uS���|���v�7n�P��>�LM�6uw�L�_l�@�\������k�9��N�:���O��_�Jo�����m�p9={���I����l����p�����-[�s���?88X��w�,X���m�6����;�%55�4�288���g�yF&Lp9�U>>>����>�����]�vi��M�_��Ce��?_���Vi�?�x����p#�0p;9q�D�r�v��S����K�r��G�Zm���e�<{�l'��l���V�k���U�X1��Z�l�)S�X���O�-�^}M��7����>R����c��;���/����G����	&��/�p��>��C��?w�1c��z�)��T������/5d�����k��-[f�6v�X:��GyDo���8���p�B���oh���:u��t��}ov���
rz�rRBB�)-+���^�r������~���tn��cG����=l"99Y6lP�����s��e�D�|��i���NOt��GyDw�u����^������-[���m��9;���q��9D������>�J��ys���g�6�����S(X�����G}��<�<��e%���
.l
�����>��������d�����w�	&����ViO=�T����=��c�7o^��?���i�����:�|���8�=9���!I��S�A:t�<�_~�����.��_��Op��5k���k��q�A�f�X��o_m��1-m��5����/K�.������>��s�����O���Kk��k������_�~ni�#���=6(U�T��9z���!Z��s:��Q���S�N��h�����3gj��q�W����:�I�����a�Gn�g�[q����Z�l�{�1�����]Sdd�"##���_�b��E�z�����O����v��)h:_�|N�����&M�d������k��EN�X���i�\�����t����)�*3�~��.\h����p�/�_g�7�����_�d����$���?_g���J������8U����U�J�����'������C��s��-^��*�^�z���f�b���/�t�~�#J�.�m���m�<yR)))����C�����{;��?~U�RE;v��JO/x$=u��5��tP�+6lh�w��e�:u*��${�����g��z�!��p���������W_u��Y5`���=���G�f��a�]�`���ko���5k�
E��z��)-+�xZJJ������U�TQ��%�&l��M/^��Y���go�=���2������KLL���m���J���z�)���;V���O���T��Z�h�t>G�9R����UZ����O?����w����.�vi�X��cG��<+W�t:�����
�}��
������%��_���D�������Z�1=��lW��-�Z?/�7�
O�((I����p����m
���w�����x�����~�y�J�L�����QC�
����`��V����.M������}�Y���9�WR���r�^�z�p��N����o���l'+Z,���N���lW%?}���?������)I/��������:�=9����_��K�,�����A������ S�����U�T����~�z=��S�^����![�lQRRR���s�����[�R�t�}3�?~�n����[�re��u���������K��V�<x���_g<���V�{��������~��7������[����V�dU``�-Z�Y�f��������k����o����z���4v�X���'���M��;wv�!aO?��������t�^���=��W��m��$��w�-[V���sz��p�/7_g�����%�/_��U���{�O?��������C�V�������-[��Q�,�1;����JNN�J{��'�^9�^�z�_��6m�����v&''���3*]�������@��J`D�r�L�{��7w����`X=������re���/^��n�����Mi��w���J��v����j���q��V���?8����c�L+=���Nh���������;p�@���/�Q���{w1�����������MO]v&�9=�[����������U�V�}���$��&=���)<<\��$�:uJ0M��W��6��e�]�v�*�k��.l�,YR��7����}:��S+78;��Q���z��'5s�L����P-Y�����NR�W�^���������[�:]FF++f�Q�F������9��j��	N��UY���������J?�k�.m��Q;v���c��K�.�V���v����T����}��u�����?�AI����������96Y���///�/_�j%��/f��v�]�n]��������m�j���N��k�y����x�y�I�&�X���ug�����f�m��]�v�Rtt����u��eS@�d?�;�����o�6m��g�S����^QQQ:r��UZ�.]\Z�C���E�{+��29t����_�;v���C���W||��_�nw�c;.�l��S._��U�Vi�����u��y���+!!��ge�:����u���t'C������i��Y*��Ny�'����s��V���{���M�81��=�0���_[�U�PA:t�0_n�g��2�����>�����������k���N��z��q=���Z�|�&M������[-�g��.���K���Y]�:��-W�e$���m��,�������S'��r����d����k�Gy$���f{�,X���Q�^�L�0���?�2p��o��������{��1�[p{#py�+?�Xm���_�J�r�����l��;�����G{+�d���;w������t��T�jU����lr���~��������3}����~k�����g�'88X�;w������9�;��S]�t��?����g�S�=m���������a��U�r:����\�bJ�����
����Tf�������W[�e4��e��i�{7��
�;s��iu���s��78���=
4��@g��n��{����2\�'3�n���&�U�^]��-s���)))��;v�P�:u\ncll�����3\!�V�%\:K�=����^�Z�d��Z�l���������M��������������s������������/���������f����i��uV�^^^j��q��tV�r�>�o��x5����;��������t��I����;���K�^r�;��uXdd�i2��w��t��:x����}��7/����W�Rtt�UZV�a\���'�^�7o6�u��7����v�����c�����Yjj��M��)S�h���noGN��y�>��C-^�8�+����{�+����>}ZG��J�����t��={�j����`�+V�����<������u�Vm��!�����]��J4hP�A��a��]<=��
|||��S'u��I)))��m���Y��7j�����o��� �l���r��~���j�{�����O�k��:����[��_w*�]��r�z��7�J�*�~�rT��u�zn��������>*!!�t�n��.6h���f�x�
l�]���T�D	��r��'=���<�`��=�IAAAN���A��2������R9�v)��S3j�����������J ���)���?+z�!�1�j�����3�3C�~��UZ��Z����>��U��~�NII���`�y{{�n��j���4h�-Z8t��;v�]��������$w<����mW���m�����i�U�V�����-[��o��*�����������&8V�V-��g�z���������\�=�.]R��M�g�����[k��
t�������/\�`������O����V�dI�;V�=��UzTT�>��}��
T��M��Q#5n�XM�6��@��f�	���s�����^?�����O2����U�rVdHs��9������<Q�U95^u7w���1������lW@@�r�;�������Z�j9]�+�~�m�;6�G��Q����YN��{EEE��W�J���Z�*�{�����H���={��O��`����YRR��{�9M�8���z��l_r���m���_�e�s����������sC�~���k�Y=�m����M�8�j���/��~I�c��]r��=�����]w�e@r��m��A�;w��J�7�3g��5kfP��l����������^��U�^jj�.\����P��p�=������s�Z/7���mn�>�����Jf�~w��UM�������z��N>>������n�p��='���;��y+>4��l�����"�����*\��z��a������3��Y�j������"�������zJJ�6m��/��R�=����/�;��C�?�|�}�i^�����9�.'�{��;V�W�2e���o�n�lW�h�={���^ZF�{�&���v��`n�'Kg��+j������4h�����}������e�s1b�>��C��(�����-[�Q�F�C�


R���5~��\;Y�UE�5�]�|������WGn`�������D����o��m����l�-WT���[��v�;wee���1��*'�#��9q?��35j�������+O�����?����^;}N��w]i{]ek��]j��������
x���|P&Lp[���r3��_r��u�u|^q��%��{N���o_��9s���r��I-]��*�g��
		����0^�.�����(P@�[���o��={����~S�5��w��1�r�J�������{l��w���l��x�/���(w�����2K��9���%7]�����{x��F���N���/_�����f��NII�w�}����O�n�����~��9\_��u�k�.�7.��z�t��Q}��'����t�=�h��m���/_���p��MhM��[��]'l��RSS�j�*�4� �V�ZeXf�r��V78s������a���{���o��J`����##����^y�6m�W_}�r��~��;��s{���k�.���G����799Yk�����CU�\9����JHH�rr{O=��R��N�8�P���'q'&&j��h��Z���M-�����}{���{�����{�n�������JII�aV���m���[m���%oU����2��W
F�l�a)���Y�f�[��'��7�|���W�����p���^�j���9�T���OO���+'������@�
*��'))I�z�Rtt��o��5�����d�m��]QQQ�t�����M��3�*���q��h�"SzXX��~�i��5K�����'�k������������/���)/�����g����z��f��a���'OVJJ�U��!C�'/��=�x+����6n���;������H;l�Y=�{�����������z��2g���m�[w����w�X�)������j�w����x�{g��-�>�2�?���Q4��n�Z������G��f����_~�����/k��yVi���Kw���(P@/���^|�E�^�Z���V�Z��7f\��_�Q�F�<yr���������V�Z�@���Hu���C�r������Mw=-�u�������u��E��@>G&��l��������@�S�N���V��Q���/�ny���_��k�����_~Y�<����$��#F����z����.��j��{���?����zZ�*U4k�,M�0AK�.UDD���Y�}���}~��\���>�H�/��a`j��M����OfG����b{+�;v����?�P�A��ebZE122R�������;�4�~������U�R%��q6(�p��V��������������2��S���y�j����_��������,���qRR�^z�%S�+����#G�7��J_e+��W�{��x���;�~3L�<���vxx�~��G��GO�z���{�*���G~���}�Y��.���y�������/����w����x�b�9�#u�*UJ��-K���>7T�VMm����+��&M��#F�b���%''k���Vyk��������z��x�����������Txx��z�����C=��m�3d����{l��/R����w9y��[�����L{}TBBB�
0v���^~O��NO@@���{������.�n�=��iAAAV��.]Rbb��O�����f�X���=:-m���Z�~�7nl���s��~��]����[�h�-ZH�or��m��z�j-_�\�	���z��'t�w���{�j���w���[M�r��k�������u3��$����n���/�mW�\Y%K���\����+Wj�����3j��l�)IV?�;�^���`��s�!C��P�B0`����x�
]�t��I�!!!�4w}�E��#�<�GyD�O_�v�V�^�e��i����<��������-[�dx��|���o��mm��r�����_��]KK;q�����C����V���6f�V�Z��W�X����$��qe�������ne����h��Vyx�~�b����qrV�z�/��	�III9Z_V-Z���������3g�X�
:���W�*[y�����+00��v�8�YY���-_����Z�j����~0����*_��Su{z�x�b�jF�����#�*����_���Sll����]�����������g�}��>�����b�
�m�6-m����s�3�yy�~;����p������>��#��}���H���)Y=�{�����������r�Z/���r�ufz}Tn
�s�����TShN��^�Z�kn�n���%(((�@<���
p�)S����a��{�Ke�?^�O�vG�\��_?��cK����M��M

R��]����__�=���.]���(M�4I�J��z_JJ�^|�E����t�����q�Fm������
*Xm�:u�-��+W�����;�&{��9������\�+�{��3���Z������fo��'���Ws��1^�7N�>�l����S�X1S���nAAA��������k����o��"ooo�����[��M�P+����G�k��JKLL�����.+))I7n�J

u(P�S���.��s�r�{��1M�6l��������

��>z�h�WN��/^\~~~Vi����c���6)����5���w+Y��R��?����V����.��{��a������I�{�["+{���Js����M�0��~��������&��[��*���s:hOr��s7�>$((HC�u����w�)Q��)-�_;y���!+�$Wt���tOt��In*TH}��u���<^������a���4�����=���D��q��=6//�����m����)�����x��Y�Bb�����}��)55�TGz�y�l����Kn�n������$����D�����T�����|��� ��~���i����5k����#��&W�S�B�4h� m�����~dd�N�8�mu���5k�J�*�����+�&�l�s�_���G���l���0������Av�Z�r����p�.]:m���sil��X,���W��f���3l�,��:<�{��Z�x����o�>a�=���V��e���_w�y�U����s<���*W������j�������W���Mi��7Gl�����Jn_	�{����xIII�:uj��������Kf�n�j�z�#�4ib����j
������N�:Vi�����t��
���R�paS��J�8y�����'5h�@>>>Vi���O��g�_U�T�n�Jf��g*T�`�g���N�{+�������2���/��zYn�����?��5XFA<�O�6������;���=�>�Q�F�,f$'�*���X��)�d���_{�y�c���h���?�����6��w�
{7V��Y�>}�Zu'/��sz���,��<��;��%&&��5k�4=�*�x�z��7���8�������~_�l�_)��Q
P�*U���m������~�d��w]�'%%����N��m��S�\���z�c���WM�b{� ���52=�����w����g��IY����[m_�xQ?��s���3L�V
0 G�V�D	=������~�x^g�X4|�pS�����a��(k4h`Js�w��jwJII������]q��{#""t��I<x�*�v��*Z�h�e��WO���Vi.ti"��s�L�U�J�{��:t���~��4)p��z���~r�v�Li,pKo%�<��)�&�	��Z��a{9��{�5���7���%�<���M
,�������#G��X;����J��O?9��^0���3�.��v����g�t9����R��'�2G��Mi���x���"  �4qz���������W��UIIIZ�p���l���O��_��t9�O���/nZ
b���.����JHHpW�����Ok��a���+����O7���	s��q:�
�+O�:�}HLL�K�AW9s����Km���J�|������lk�-����
����c�G4����z�Wrrr��@&M�d�.2d�S���}�.9=��k��d�@w�M�65��rA�~��S������'�������Jjj�~��G�����}��:�Y�f�c��~�u���������o��T���s3-�f�
2�]�����zh�#7nlJ���;g��{�k�.�w���2��iAAAj���U��5k�~��C�rM0H���MO�1c���~�]y�v��>}���V�jJ�x�b���8p�*T�`������}��}"�����l5j����}�v��m/po�����u����b��
s�\�	�+W�4���^��|}}M�;{��K�'O����d�4�>0�h������/����s��[�n=
�K�.���>����l������n��4�/22R��ms������s�
�������Z��^y��J�.]R�~�\^�����T}��gv�V�`AS��������7�|�t�Z�l��� ��9s����cN�����woS�G}�t9~��;��k��������H���<y����cl�Z�0�����3v������|c%"g�;�����'�^;v��>}���.]�t9S�LqW����W����d1n�8yy����;�	III���/��s3��\�|��r���L�0!�WFu���������s{������[E�N�LA_��K����X�b����U��)S����o���*�I�&N������99��klWs���������h���������N�>�tY_}��)-'��y�z�}����{��)N�k���t��I���~_�L�G�����C�Li�&Mr��#G���BBB���y��bQ�����r�:�]�v�1���S~��
��m��C�l������2��%��=x�`]�r������4h��_�����$��z��������/�8qB+V��������S���`o�k�b�r�
��|��i��)�%8��;���Y�#>>^�>��^x��,���%J�&�������0U�T�*m��]��m;�����g%pO��y�S�/��p?%I������o�f�X����:\FNk���V�\���P���K������t���w�mz
������<�����y�������������p�|�������z�!�+`�6E����~jJ_�z�z����q���g��c�t�J�,iJsve�g�}VqqqN��@�:t�UZbb�������E��q���[��U�o���Y�f9\��+4m�4w7-W���2}N��-sj������j�*w7-�
2����)S�d�
O������Z��s���<�}��M������d��'�^�6����JLLt�����k��E�l�-m���j�����]k�[��=��{���c���[o���N���mP�++�H�}Y�v�S���{w���������{�b��Vi�W��;����WG�qz���L�2z��G������^�.�l��8qB���Sll�U�+�������x�/������:d7x(�\%��~~~z��'���_��#F8U��y�L����S����n��<y=�?~����*���sN����=����}�{���Mi��
s�A$��[�n����%K����:U���CMA��
���o��lf�i�&�����z7o��~�����%K�4��7o6�g�0�96�lo)^���^�{\��S'��7w���x �	���]���>����+;�����j;55U�~���O�n�����>}�8U��34�|���8����$������T�f���j�J���e�B���ic7�e���j���v���r�s��U�Z�4{���4�a��w���?�����$��m<g�&L�`�f;$3�+W�
6����O?�d�///�h�������>�j	G��#�<����/\��.]���x�S�bnS�V-�Z�Je���J���P���3�`4f�S�_|�Q�F�<t��]z��������^����Ky�l�b�|��j	���a�LO�����L��=�7o������|||��+�8\���GM�'��[v0`�i��$��?_���wyreJJ����k��Y3��u��U�B���>��s������og�<2|�pS�����������WV��M�|�MS�O<��J��V�R��]����lW
�r���x�
�����#���.E��������P����>� 3QQQ�>��y���4{�Y�9��:u���
[�������)}������#���M����^�j�2������8 r�������������q��x#�;q��^�u��__�v�2��V�ZU/^�������^=}���Yv�U��������
��}������[o9���������Kc�������cw�^z�%}���N����k��Wm��_]�x�n�h^������
���{���s��LII��'�nC��
��A�����[m-ZT>���eKy{�������/_�t�q�>g,]�T�+W���w�^��9}���u�f��b���]�v�ug��������s�:�b���[M���wooo���
O_����3�?m�4�������N�:��m��]��Qy�~_vi���i���������3=q��������{��{�#G�4��������~:������~X������W/��6l����7:���^��5k\�;=V���{o����:��oooM�>�����+T�jU}��W������������f��i�-M�5���Q#U�V�*m��i������x��W]��m�z����+��7���-[�w��1u������=��cZM�3f�=�������w�n��z��G�8y��EM�6Mw�y�z��eZ�1;u���j;!!A���sK��V��]�������-�n����e�X4m�4��E��}��:x�`�y7l��f��������_:T��U�TIk��1��n�:�i���b�����n�5�����o�M�6��x��yM�:U���S���5s�L�&��j��i�Q����k�)S���K�Y�d�:v�h�4e�_�+VLo���)}���z��w�
l]�x�Z�nm�,:b�U�R%[��]����i����j�*U�ZUC�ux��s�����?W���5x�`�?>��������.�m����>}Z�<����i�Z�#��������&��3GM�4����3-���i�6{}��[�n����UZbb�z�����{k�����i���4h�Z�n�K�.I��4i�cm�������������Q����RRR4u�T5k�L����X,��/_N4���|�M5n��*-..N:t�+��������H=���*_�|���{����=g�=�������j���6m�$���J���*=z��J�~��~�a
4H�N����]�v��W^Q��e��������W_}%???�����^�;w��3^�p�Z�h��g�J�o��IBB�V�^��>�H�;w�w���c��=6����+V8|,�����t���fd������'�H;G�z�5m��j������������T9=z�����O�~���|�����?�I�&i+�9�9}���G1�'''k��������}���'�����q�������x��L���_I���ybu6{�V���?��������m��i����9s&m���*������������]*;���sj�$''k���V��7n����;�r��+W4i�$��[W;w�4���?��;��>�\�r3f�)���^�3�<����t�~��wj����a
6t��W����x�2e����?��5l�P,0i=zTc��U�j���\���+������3l��k�.��__�'O��ap���Z�d�x���������W�:u��bbb��U�r�'�|R�����o���S�R�2��{����<��
80�@��q��i�;W��-[�4�Zy��%�o�>�����?�G}T�|��$�]�������.]���l@�����u��][����������z��Y=��3z��gU�xq-ZT.\PTT���I�&i���VO�����0`�^z���m{OE���G������w�}W%K�T�z�T�N�*UJ�����/�._���G�j���Z�r��	�~~~v')�v#G��g�}����m���r�c�X����*  @'N��[jj�f�����g�d��j���*V�������(%%E���:x��"##�q�F%&&fk{���aCU�\Y���OK�?��+�e$���*T�`Z��-[��p������4m�T�F����#��#""T�zu�m�Vm��QXXX����-[��k���4m�X���_�l��N�����-���W�]�vV+l��U-[��������1r�H���W?���U���+��EU�\Y�Z�R�5,???����������y�f���'WL�Y�|��/_����F��[���W���E�*000����g����O�O�o���z�����g������?�������f��x�
M�4I}��Q�J�����#G�h���v'=�u�]v'��v~~~Z�t�z�!-Z���o���?~����;��C��s���/���+11Q111:p����_��[�:�=��7��O?Y�������u���{�U�6mT�ti%''���3Z�r��/_n4�������C���������;���_7��m��U���S�J���}{U�RE���a��������e��[�.��u��u�~dn�����g�i���9s4g�(P@��������3gL��������#MO���8��J�*��C����7V������U��
������s��.]j���_~Y?��C�Z������;w�6lh5�;11Q����_|��-[�y��


U���u��%�;wN��m���kZa(((H�=��)�{��iZ�p�|�A��WOAAA��������d�������>��s����������j��04y�dM�>]M�6U���U�T))!!A111��c���_o5��<5��Z��������*}����X��:v������d���z��>�E�Y�?�����t�����N�����k�x��.^���W�fZ��b�SO=��>������=����o�J���g��uk�h�B:tH[=����Z�n�~��W�sA��m������zox�����oXML_�t��.]��� �(Q��Y�T)-[��*�r��z��GMm3f�f����={�v��*T��bcc�o�>-^�X�J{o�4n�8
2������/�&M���M,��t��w�e���T���-*///���������k�6o��8��Q�F�T�zu�>r���j���������K�@��|��-shr~n5t�PEFFj��YV�j���j���v���B�

		QRR�.\��={�h��M��iS�{����������E��R�yy��S���f��
��a��������!!!*Z��,����u��1m��]+V�H�A	�z�2����>��^���i
����4{�lu��Y
4P�%��j��v�S�H��=[>>9?e��������kM}������G����D�
PTT���@����1c��J�^����}��\�ri����#�����A���o�]�v����T�X1���+..N'N���-[�f��� �r��eK�������^
6��EGG���������kWU�XQ:w��6l�����=��f����A����5j�F�a�>u�T-]�T={�T�:u�.h���Z�l��������zHg��q�����Oau]������w�U���U�R%*TH�����u��d�����w�qx�������N�:e�\@e.���0$Y�Z�l�ryG�1�7}��L�M�>�����#N���_?�2��+�t�a����*�_�~��qu��f{����<y����e*#���b1>��s�0������[��]]�w8{������n�CCC���$��>|�S�Oz/???c��9���eK��)w5j�[�7�Wfl���\���9�tk��q����&g���;Vu�.]�HMMuK���UKw�R��w����[�t�K����[Y�?���5f���p}Y�W��J�c��_���
*dx�III1^�u�b�����a[m����-�)��6��Y�8u������.]�d:;��V��q��9���7��J?������~h������/U��1c����4i����i���v�Z���O>���1��+�����iW�����]�.�'+�m��S��>�������i���m�\���*!!��Q��K����{)))9z�f�m9�F�r8�����;��3�}VFmOLL4Z�h�R��������|L���m����~f4�-��'�^7����.�_�`Ac���v�e;�u�X�
{���x�n��X�n���Z�t�����R�5k�4bcc�t�0z�h��L����8�j��.������t�R���<q��0�������?���P�������r����9+7III1���,�Y�k^y��e�k��m���uW�������3�����Y�G��A���?���LNNv���#�N�:eiJ�*��uIV�k�x�z<%%���'�W``��z�j#))����>����=5��UDDD���Y�L2{e���������g����w7�^���g������Y�-�+W�d��9x��Q�ti��������TS�+��������!C�8]���%���j��
����z�
��o�i��a��.X��H�"no��J�(aZ��f�=��KO.^��,KV���5kj��z���T�����j���z��g�?�,�U�hQ����:t��������'����o����'�j�*�����w���������X�bv���������T���#��?���@�������O�>.��-ZT�����;|���7on����yyyi��1Z�l�����,��H�"z��'U�P�,������,��X,������YsK�H��B�
i���z����>Gu��]���S�����7::��V�F
��q���^xA{��Q�>}������0����:p�@�+ 4H_}������T�?���-[fZ���=��~��w��U��2J�(��v�����_�^�F�r�����[�
�?����%K����g����@�������aC���8����{yy��?��)SF������r�P�p�W��������^9 00Ps���SO=�R�n��~�M�G�V@@�Ke����p��YnKv���k������O�������K+""B���w�����
j����2=��;�����?m��M+V�P���].�������s���v��I�W�VPP��uK��F����:=N�U�H-_�����T�RZ�|����>�����M�6M�f�R�
�T������O;��6m�������d^^^�������?�|��.�a�X�����!C��]���"�����91��������Z����O�*Ur�NG���W}��Q``�[��P��-Z�3f8������
h���z��7\�Oz���j��uY�d�������4c�}�����j���"##��Y�,_�����rB�V�������2����_����[�{������[o���s�:�2������_~q���G�������X����������v*��O?�Y�fey�(��J������
��ry����4�\�~�������+���O�N�:*Q��|||�����o���7o����������={��UY���9�|+p�oy���t��M�6M}���w��P>___u��Q�g���m���iS��G�+VL�����'4~�x�i������)���{�����3g����w�d��z�����&O����3
�k������h��n�]w���dmIz���t��A}���[�n�?�����Y�f�:u�v������-
.��~�������l����o��n�{��W��m�/������;��P���y�����3�2e���A�b�����y��y��k�����7&�n��E3f��s�.7�����_�����G�N>���Q���h���..����G�T���/_^�f����G5n�85i��*�9#���0`����O?~\�����AC���-[��w����/�x��Z�J��MsK��
��s��o���Q��{�Cm�\���
�-[�h��qnk����4z�h=zT���W���U�bE,XP���Shh�Z�j���zK��I���:�1���qvv(Z�����M�8Q��������[;v�?���?������`�����/t��=��sMB/P��:v��)S������N.R��/^���g�v����x��z���o�>�����}�����F��#G���7�T���3�p�/_>�j�J�~��N�:�z����=��Sc�#Fh��]���_��������7�������A���'99Y�W��J�U��z����r��b����OE�Q�r���Au��M����f���#G�������������[7���C�
������K�Z���E���/��%H���K����N�:�����w���Y��BBB�����i��U?~|�m����;����{��{]�O�����������g�c��_�V�^]��
��e�t��)}����������3g��x�	5l�P���*X��[&��f�{��������_�e�����][��������g�y�����)c
��<�r�����zN�c6o��K�.Y�
8PaaaYj{f���n��5KQQQ����4r�H�i�����%J�O�>Z�t�������;��w����z��wt��
6,���B�
�K�.Z�b�~��W�-[���p��p=������C������woU�^]AAA���Qpp��������k���Z�bE�1��k�[�~_N	��%K�~�z�����`�����O�>Z�d���[��m�P�����O���z��T�`�L���s�����9r��������/����~�)�kD���f��i��e�9s���'*T����5e���[7��yyy�m��Z�b�&L��T�sFl_i��������0���p�:p��*W�l�6m�4=���jQ�9��8���+&&F�/_�$(88X��US�5�:�������W���S�t��e%''�p��


R�b�T�N�,���;v�������O'O�THH�[�y���������hy{{�X�b


U����t�VV���;w���C:����?���T(00P����V����,�.���:z��:�c��)>>^W�\����
.��%K�v��.���\�rE6l��}��V%(R��*V��F������{�������}��wj����nR�����k�.>|Xg��QBB�RSS���@����^�zY^������]�V�Vll�,����U�R%5h� ��^��um��Q'O�Ttt�.^������H�"�P���W��+�m�\�>}�����m�)SF���`�r��'�GEE���K
Pxx��6m�'�9v��v�����h���(%%E*Q���T���U�fi����k��u:w���������R�J�F������g�e�EEE)&&F���*T��BBBT�JU�V����r3O���_��5k�����:{�����T�D	��][u��q[�������I���[�nn)?��~�z��������
�R���}��q�FEGG+!!AT���U�vmU�R%[�������dm��U������+///(((H�*UR��U��JE�����
6���3�����K�T�`A�b���^���-������u���*m���5j�[�OO^��{������W_M������C�T�T��h~����S�t��?~\����t��,�
.�����{�u�D{������w+::Z���W��U�X1�-[V
6��
��-�\�;j��)���:��_o��}9�0m��]�Rtt�bcc�\Y�LU�VM*T������Dm��A'N�Hk-ZT��S��5M�����'�n�:EEE)..N
�w�����d���R��<�m������i�*T������7���D���)&&&-m���.�
�}���>��3=��sVi;w�T��5=�" o����.\�����o��7��\��������������K�.l��\�~]e��UTTTZZ�=4o�<�
��{�=���ki�u������s]@?�����,X�������G�f�Jnp��U�o1b�>��S����]�j��Ei�!!!����`����7�|�'�x"m�A�����`���<\�����?��*-$$D��W�P���k��1V�b|���r��[�vi�W�~}���l����Z�IR�-<�H��+���~�m���z'N��
���.]����$%%i��5i�
�+����Y�w�^���/Vi��7�Pk��Kjj�>����w�}�C��J��1�=���=j���OXp�5j��GM��������=�"��������z�C-������^�J��?��8r���D���?i�
6T�N�<�"p������������{�5H��
�Z��3��D�l�5��_W�>}���j���SOy�E��e����o_�v�����];�p�`6,�,���_�`��d��$&&j��!������}||4x�`w7������+   m{����t��[�vs��:�7�}�������o�����;�g��uj���.^�h���O��y�e������W���~�m��e���������W������
2=������+22��<�O�V��m�e���J�*�C��l;RRR���o�m{{{���?�`���d������G�/_^��
�o���s��������;vh��q
��I�L�=z���/��nO%K����������5n�8�5�m����Z�n]�6����}��G�P����o�	&h��JJJ2�/66V�����u��f�����SV/Y���{���j68���x���n&�������s��S'%''[���w��P�����3��
SHH�[��%K��Q�F�[���z�-�]������]����Wk��a�\���J�������S��b��T����7�|��{��m?����U��[��X�0<�����_����)=00P�����?����c�$}[����o��&//�/d���d}��JLL�$,XP/����[l�������Vi���*^���)���d]�pA111J�6�|��l�2�m�6'��g,^�X#G���_���c�t��5�����~-Y�$���v�������J�X,*V��������8EGG��o��;���7�����4y�d�>}Z����#T�H�
p���t�Mqqq���s���?��&N�H��|||��k�y��III:u��iU={J�(��i��9�2��%66V��o��=����2eJ�@^f������{}}}��_h���9�2���SOy�	�[�bdI��uU�zu��6l�P�-��i��/_>7��uu��Mt:_�B�����O��o'h ����k���*Y�����s�=�(44��|^^^����6n�H��-�b���F��8p@�V�����u��;vL.\��+Wd�X���`����y��j���4h��f����W�z�j�]�V��o��#Gt��i%$$���k*T�����U�xq��__-Z�P��������f����m���(88X�k�V�n���(P��-p+KMM��M��f�m��I���'��W����O���
V�Z���E�k�Nw�q���'��yy��%��F��F��F��F��F��F��F��F��F��F��F>�n������;m�L�2����`�������:q�D�v��-���E�p������kWO7�m,\�P]�t�t3@��t�K���|<�9�L�2V�.T��=�����/+222m�a��*T��[��>���~���~���~���>���~���~���~��u��Au��5m�v/���nC~~~V�+VT�5<�����x�={6m�Z�j*\��[��>���~���~���~���>���~���~���~7���y���@^B�nD�nD�nD�nD�nD�nD�nD�nD�nD�nD�nD�nD�n�����3C���2��M�R�E^^^�X,�nJ�G�� �0t��5]�tI�.]Rbb����E���O
���?�|���=n1W�\����������nA���:����?/___�*UJ
�t��/O78���+:~�8A{�HJJ����u��O7%O!p�[���=�0<�@b�{n���������O���|}}U�pa*TH����X,j! �3CIII�|������Vo�q�	�\��p�v��U��$(,,���|}}U�@+VL�N���K���������������-��<����+��/���b�(,,L���V����jQ�B��������������[���o�����Pbb�UZ�B�<�@^b{>ILL�ajM�A��\jj�)����-�5>>>�4{�8��=r9{+Y,���xy�C�Xq/��������������������������r��bI{�j�����
|<��M����s�N:tH.\�a


R�����qc{�����p[KLL������K���������}��bQ�
4t�P=��C��!Df^�n�
�a���$�&$���$���&�t��QY,��W���=�$�b3f�Phh�:w�����:��=��~*22R}��U��Mu���j)n%�s��{6^������q�u*^�&���H~_�+�;K�K�0U	
�`K�E�v������x��*Q��������O���3V��q��6m�U�V�Z�j9�\�"��b�9�?��<��:����p�A6A�TP!�]+�h��l�R��,�j��fl��C����_c���K:jV�ej1�e�K6.�
����;��G�'���sX��������/�������pD���6���T��CY��P���pX#���������h-���t�-�������W_���0����d���������}���������$oooG��&�����%��\O.�U~�����5���z��m���_�ST�Hhm��i�i�����c����5n���=I��������`0�������o8�d4q���$���
�o�����E��j�	���6*�T~U��5j��9�3f�}��v�������SOY���7��CsEp8D��|��p�N��5�~���t��-��\�!C�(88����}�Y�[�����g���,
����-_NQ�&�OT^IE���WR�	'��)�����{�T��m������.u��Mqqq����u]ii�~��'%%%���@���������C��z����B���W������RII������}�*::���nEEE���_������UTT���O]�tQ��=��c��>#--M�7oVZZ�L&�BBB��wo����"(v�����e����*##C���
		QTT����J������B�w���={������"yxx�M�6
Wtt��u�v����o�^�������/--M�]v��BSAp4�����`7���t~������7�O����l��Aqqq��K/����xUUU������Y�t�����������k������+((�+�����g+?����!!!z���4i�$��<p���.]����N��oWee������z��G��O(00��}#""t����,��l��?�&N�X��k����o���~�I���6������{�������C�Z�<��m���s�)!!��x�N�4c��:k�e��=�1c���Y���B�s4~�xM�6M����{�S�N��W^��%K���S����`]s�5z��5r��z=CSs��d^^��*AS���@���|Z_�v�Q�X����O7��UQQ�n��FM�2�jhO����5s�L�1B%%%�����_�~��?�i5�'Iz������O�U������{w���k��-�����a/���.��rm����3���'5|�p�t�MJHH�5�'IIII������?_�s�}�]]u�U6C{�t��1=���<y���������RO<��z���+V��IRnn�f�����H}��7v��~�z��������3�'I���Z�|�^~��Z�����`0X|����U�����[���m��J��p�hT�7q�9?�51�rVsa2�4f��_������0k������2�m��IS�L��~�3g���k�QZZ�$�`0�K�.j������t�����;��������{�������}^^^������i#�����,=z�"��������Z��oWll�}=�k�������t���c���
����rss�������:g����2e�����������*==]'NX_����������s���b��O���kk����*44T...:~����9c+((������K�j���6���w�n��V��Y��������������Jyyy:z���������QQQN�M
7��F�|*_���9+1%[�O8���b���Z�z�$i�����o�����m�6���W�O��c�=f����>����u���+--M��������8qB�Vbb�>���d
6�b����7��YF�Q7�|���������P��������m�69rD���Z�x���������5n�8�L&��~���Z�~�/^l�?b��_������#k������o��"�����|P��oWVV�������D8p@�����i��z�)��58���C��^ll�V�\���l���O���JOO��;t�UWY��6m��������G�����j��i:r��N�<�_�U;v������k�.�u�]��UUU�4i�:ds��S�Z��z�����W+??_�����u��o������H;w�������/����QS��'�X|/����K�.N�M	7���UVU�d^��e���?o���=����r56�;�RSS%Io����y���m���{�������?_�����s�=JJJ�������[
:������k��5�������$I�N��7�|�Q�F���_�~:|�����k��M�6���{u��w��;����~+I��k����;�x��5�<������������Z�;���>���s���O_~������������!C4d��������k�9������#G���?���w�9}������A����~��{�q���7��o��eZ�p����[7�]�V��u�:�W�^Z�b�f����S�J����g�yF�V��1?//O���3�cbb�y�fyyyY����M}��Q�>}��/(99�f�M���'��;�X�M�8�)��i"�@v2�TC��g��0���"���45N��j�����{���;�+������Z��A���z�jh�,oooM�6M���3��Y����^}o$�����E���kW���I����o5��P����l�2s�`0h���6C{������W^i�y�;w��e���������_�x�5k����L&���[��-�w�������m�V�X!I����u����%)%%E�������m�������{nSb2���C)??��w�%����wbUhj�V�
�`0h��u�S���-�����������[o����_�����!((�"��y��?�\����L&��=~�x�9���{������_�����^�������;m�]�v���vS�L�+�w��/�h��d2��/��1��������f��������d�����h�3.����n�����_>>>N�M�=��g��5nI����.�h�q�2�u�����S�����F{�{S_zz�222�IZ�n�E��'�l������n���F]~���vFF������=?Xv�}�����={*44����iS�9aaa��������^�47�V��5J����g�v�mN�M�=��_�~v�m���E�o���6??��u����7o�x����W:t����C���^{�bmff�������'u��as�]�v5n#lH5���i���E;//���s�v>>>����wm�:u2���Tc<<<\QQQ����[u�
74�����e��7N������C���w�q^Qh�\�]GHH��s���dmIII�����4}�t����6o��Knn������=�~��q~�.>>>m[_�s�vEEErq��������������{�5��������9R����A�~Q�;���{u��7�������W/}������pbeh��q�����t���dff�������3/8�'�������Z}�u�u�_g��T�������>�n�7n�^~�e����T��3G���SDD�"""4y�d%$$X��)KII��#,�7����v�Z���;�24e��@���S���9��������9;�x�������;W��	��4�G�����-�:u����8]z������|}}���eqK����h��F�����������g6���������/�����^3f����kUUUUc���G5w�\��;W�]v��z�-]��
^gC;q�����:�8q����S'}���j���+CSGp�����NA�N;��.A
�]�5�����}��W��a����M}��;v�EH��~�������s:�����m��@PP��-[��g^q����ot��I�[�N6l���u���s�����#G��������O7j]#33S�]w��3�k�N���:w����������az�a������������m��3g���k������(���� ���3grnC
����*++%I%%%����rv�4a�M�0A��7�%$$��/��W_}���
I�����3�������W^����#//O#G�TRR��/  @���Stt�+CsQ{�"���i`DP���.A�����p�-[��?o������n������1J�!22���c��������������8q�)����i�������t��A
0�<f2����o;������o���;�}���Z�f�z�����������Wwu�9����sp�N�>m�<22RF���u����
���XFfL&��kCCCen�9sF��o�{}Sg�NHHpR%��%K,�~��''Uc]YY�F����������U�V5���t��������WX��q{�0���k�3p��
���������?Vii���}||,����v���n��������k}Sp�3��5�I�X���T�������L'Vc���Rw�}����{s����V�X�k������9"����z���G�����C���h����BCC�����W���u�IOO�����u�����m~)))�Z��OX���x�b�[��^{8��Q�ino��U|��+�]yy��������@'V����jM�8Q_}������E�/�-������\��.��](/�����M�@���c��A����������:?##C��r�]�s���)::����k�>l����(�7��6�L=z�6l�`����"m�������h��/�l�7e���;�^�8p@�'OVzzz��%K����^SNN������{*))1����gsnjj���Gjjj������?�O?���6����t��w7�yh�\�]hbB����+5��D��/�����yh���������~�p����U\\�3f(<<��_PP������_��S�$I���JJJ���#F��WUUi��a�<y�z��)___��=z�C��g�����7���#����|]w�u�8q�{�1����b���Rm��]+W���E�t�-���+���W���3F6l��9s$I�<y��������V\\�|||,�TTTh��}�����+W�����d�/�Pc�3g���^�+���o�Qw�y�
d�oy�����������������/����5{�l��;��S�:u���_���v���]�6dyh����	��wS�)���Z����s{�0��������#F���n���~k�[�p�.\��]�*$$D���JIIQyy�y��q������}�c�=�9s����T�t��	���[�;�|M�8�����__}��n��?~\���y��i��y


�%�\"///���(55Uv��(���������������� WWW���+((H������Uzz�������Z�r�V�\)I
Phh�T^^�c��)##���1c�h��Q�|
�?��O���>�L�}�Y��z���l~��u!�*��]�oL��;L�<���l����G�wS\L�F����O?���#���h�����v�3f�����������9���Z�h�x�^P�=z����[5z�hm���b,;;[����:�����-[�~��)>>^%%%����J>|X��u���`yyy�}fnn�rssk������}hI\�]h���i���\��O
��q�4$2X�^ns���4$2X��u����i�#W�k��q�FM�6M���6����CK�,���K��~a7+�u�]:p��^�u�9R�:u������{�������������h4��k0��wo���z��7/���2u�T����o��:w�\����P�?^���N�8��������#�h��Uz���Y�����;�i�&}���ru�N2�\��drvk���������={��G�N�����oq�o\\�����X4^��6��hmx������5�5@k������=�
�{�WC�g���R�����j�������*�WV���E>��z���������_~QRR�rrr������0
0@����.����m��Y'O�Tff�������[7���K��5�`��C��k�.edd(''G������W�������z�����}�����#���Vqq����������K>>>
�0�(��c��h2�|=\%gWG���T\\�����]��u��7;���i�-y�����k���
�/��8�Z�{4 Wg4��$���LL�2�L�.	@+@p-JvY�R
J�QZ���rU��3�}�Q���
�x��k/z�9�R-�=���J�;�P�K�m��0I'K�u��\��)T{Ow]��N>��@KGp�ZiU��������z�=]Z��'�����������*���k����������T������@���S��m��gO����h46�y�����u�������,�Fu��A���S�=��������/�����*))�������5d����6�9-������
�O�RqU�E�s��D���t�%m���@�h��5!�}�����{����JNNVeee�����5v�XM�2E111tfaa�^�u}������:�{��z��g5q�D�:G�~��G���k��
V����u�=�h�������sZ�3����*��x���M
�_qU������	��(.�.x���4g��������$���i����������e2��M��w�V��=������I���������oT^^^���$����S������p�~�ep��E�����r��z�#��g5�VUk}zV����*�6i}z�J/�?���&���S���0`��������7�UTTh���z�����w������k���b������={***Jnn�7��]�V7�x�JKK��O>��f��i�g0��S'���W���cEEE���{��_�����L���g�T�H����jm����"�����������E�t��!i���JLL����������,}����������?�X��������J�=Z������� -X�@�������t���:uJ���?������/����S���<��/��Y�,����N���_iii��c�222�����g���9UUU�0a�RSS�:�%>��XQ���4�G
Jt��~�~8��^�����������5~�xu���"`vV``�~�a����U��}-���������g>��c����b�M�6�������.((H����-Zd���>����|���r=���}����b�
EEEY�_{����q����o�+((�K/�T�9-���u��sN�c����kBz��)��`����@-^��b���'���?�\S^^�W^y����7����^js��q�4~�xs���R���u�7o�<���������o�|F-X�@�����O?�T�������	X�]V����9�tI�r�*r����^3�~��Y�%%%���v�Z;v������<P�9�����+V(//��5}��E�������g�k.��R�s�=�vUU����_����L������w���h����u�hgff���j�*��<`�-��u��������
}���6�?~\;w�4�}}}u��w�y�$M�4������	X�������t�yZ�{-@ii�E;  ���o����=b�������-��W�����������s,ooos{���:x���g��g5�L&e�U8����
�L&��	��#����L&m�����_�~V��>}Z�N�2�=<<��o_��<x�E{��]6��?6h� ��quu����:�%>������j�����M�$����5s��N�8an���������d���������g]z���C��������_[�����VKx&`]����"����5c,�c�=fn���h��Y2V��������S�z�"OOOs���\)))�r��������i���s���q����V`����mPZZ��]QQ������G�V���}��c������u��������3��;�����09r�b�����222.��K.���}~���[�3��\rw1���q7����Jp@=�k���}�����j�c0t�
7���^S�^�j�[XXh�����wM��9OI*))QUU�E�e�9��[�3���3gj�
�r�������7H=h����jm@S��������'6�W8�<�X�����u@k������<�
�{Z^��6���^
�~a�<�k�F��'�|����T�?OO�z����U�����{�=�X�o	�T_�����O�~Q{$&&���S
R����Dg�v+nw��������?��v44~��������u@k�k����=�
�{Z^�Z���4g�������,_�\C���a�j��v���R����{������h����y���e�9��j	�ls��v�y��=@�@p�	{��wd2�����:v��V�^�I�&Y���i�&
0@��o����7����������Z���W���9�ZKx&`�kY�\�
sVQ�\���?Wg�yyy�c������n��f=��s=z�v��%I�����Q��g��X���k��v�\]��%��=m�����+�f�9��[�3��c�=���G�k��C�4j�(s{������m�z��)11��8p�|||�X����Jm��������K��C��F??�hmx������5�5@k������=�
�{�WRR��KNDp����������o_;vL������3g��W_�1���XQQQ��<��������F����,�Y^�9��[�3�W�v���]������W~~~
R���4+~�NU��Ha���������6���(�����u@k������<�
�{Z^��6���
�~a�<�8�\���`M�>����O>�:��p�����}��'j�������:+==��sZ�3��]��_����Q����+B�eo�����;���`0�O�8��G�����{w�vZZZ��9s��JKK�mwwwu������=���111�rNS|&P7O�������]uO�'7�A����@�Ap�PPP�E��S�j�;?(v��a����}NRR�E�[�nruu�:������g�9���rk������;7��{�U�����{��`0�?���jg���k����j����*44��.++��;������h��������6o�l�9���JLL�����L�~An�=�����j�}���t�����`�����@���}����:���o�h�_���s��{�����{�9�7oVQQ�]�����*..6����m�Y-����<�.�������X��.�c?��UIe����d��97&��HMMuvihb���|��L&���:X�{�m�Y����o�������4����t�M7����S'�����.,,�����<G����g�����k���	�_'Ou���u��A
�rW�@_���;#��������U��t:���+
�d2���L%U�*�.�}\� ������':�$������S�]�	�{�\II�^z�%��[n�E..��iG���;������?~�����[��s��w�����5�&M�h����*--�uMRR��-[fn�����?�-�����.�����sF��;tk��FvV�`?z�������m��^\���b�����U���9���2-86K�����c�i~��Zpl�V�Z��9�]���R�b�>������]�	�{M���S�m��z�����m������F��~�i�k<<<������o�����gs��%K�x�b�3�O�^g}?��:w�ln8p@O?����v�������_�����q����K/�����L���M&��[����P]-��Pc,��C����w{f�rl�h�a�:�T���D���*�4Me�����U�*�4M���j��O���R�qR�Z�%K�h����$'W����^�n�:
8PW\q��z�-���K5� n2������_~Y��w���o1���O���/���I�&�G��vNN�������������i�������X��#�(::��grww����n�7{�l�}��:x��EBB��������|}}5c��:�i���'��RU���2��~k^��m�����X�I��T�*�ml�������Z���\����k����Zsf�~�X����F������)S���dC`WgK���JLL��{H��K.Q@@����UPP�c��������	&��7���777�X�BC�Qvv���m&L���?�n�����D)))5����o�i���;V�6m�|`������r�Ju��I!!!:z��233-����h�������]���g��m�V<�I��������a��*-SUVn��)����|]���@��U~F��^�������PQ�N��M��R[���jz��'�9�~��i��)z��g�\�:n�k��������_�U[�n��}�����������k���rq���466V			
��/,,�o�����]w�uZ�v�������f���O?m�g2�����;v��y{{k��������uNK|&`���J������������!~6���)��������������U\U��O�[Y�
��o���Z�t�$�h4j���2�N�
�7�5K�.��_����+11Q�����7����u�}�i��	
	��_����v����^{M�g�VNN��yQQQ�:u�&M�$��P�s\\\��[o��[o�K/��M�6Y�������G���_��[�Z�3���q�XZ�m{�������2���m:��Q�C���/[P_�U%���J�U7�Q/�.���?�����4��R��j��m:x���������n��)..N�����+--�O?����$(00P111:t�\]/<�RXX��{�*99YYYY*))���������o_EGG_������H�������������
����K�.����:v�x�g���i���JKK��dRHH�z���>}�\P�|�����e�RSS������j���(**JW^y�E�***�{�n���GYYY***������i���pEGG�[�n������G}��~�����O'V����^���XM�:U���:x��:���4������Bm������"""��o_�����^m�������j�����u��E�h4�C�����.���xB)..Nqqq:~���<JKK��MEEEi��!<�`6�{e�v�a04���2�������xIU�~:��k;6�/������C���w���B�����
��Q�oN6l����8s���^R||������{�i��Y:x�`�u���z���5c�yzzZ���W^�����^T��^{M�&M���h��������}�vUVV���G}TO<��k�7""BG����`�-X�������k������f���������T^^ns^ll����M�<Y:t�u��m��M�=����w��I3f���V[����3fh��5*,���c@@����i���]�vv�}��)���+Z�d�����
�5�\�|P#G���38���Su��qI�o��1���9!������{��������tss��!C4d��F?�c����������L����*�Z	�I�k���=I�45�}�����:~��T����S�:��:Z|X�����CEI���U�w��������t�wh���6�k�����e���]+/��o/<|��n��F�a��222��Ci��=z�����g������[�����Sz��������/����^�N�<�1c�h���v�OJJR||�RRR��'��}�������������9���cz���y�f��=[...v�]YY���~Z�������������\��5K,���Ku��7������5z�h����UOff��/_����Z�{�������E_JJ�"""�:�b���������>�@����~.Z����0[��I����=I���S=j	�%f�+����K��r�o:�91�L3f�Eh/,,L������^*��h1��M�2e�$���3���k��=����]�j�����k���y�}���u�TZZZ����K�����������.]����������VRR��@��{�n
8�jh/00P=z���%77�>g����2e�9�������X
0@aaa5���;W����]{��[n��Y�j��BCC��wo������z�����b��Z���w�n����=u��]T�~�yQ_#G*))��?,��$I;v�n��'W�����=[�=/�\�*/h��m��n���*�I?��QU������$�<C���;���e��]�������j����~���O�����m�������O����X��Gi����������&OOO�����N�8���+11Q�Vrr��
f��o��**����F�Q7�|���������P��������m�69rD���Z�x���������5n�8s��|�~����_���[��1B�����a�����\�~��:~���_=�����}�����g�%&&��������M���SO)88����Y�2�%ccc�r�Jeggk��}JLLTzz�v�������b��i����U���>����]kn���j��i:r��N�<�_�U;v������k�.�u�]��UUU�4i�:ds��S����������V�^���|%''k�����}�<���"���S����.��r��F���K/��AAAv�$�sY'2���
�������tu1hxh��>��*+��g�Ujgv��_�	���jU8��}��~^/��=�,�6r14�;�RSS%Io����y���m���{�������?_�����s�=JJJ�������[
:������k��5������S�N��o���Q�l���_?>|X�������M�{�����;u��w��o��$���K�}��n���kl��gu��A�]w]�����GUJJ������/��RqqqV�{zzj��!2d�^}�U���������tI���#�����������}�������A���o�I�=��x�bs���e��i����v�n��v�Zu�����^�zi���9s��N�*�����y��Z������<�[�������������eu777���G}���/����d��;��;��[o��3g��q!`�{h���������3�o����kKF���=9E���Sa�q
4���-I���e8���]�[��)g��d���5�?�=�X
����W^��T]]-I� �[o�e5�w�����M��q������YSkp�K�.����@��E���kW���������[
�5���d-[���6Z�|��������u��W�}^����l�2���s�|���-�{��56�{&�I����k�������m��+VH����k8p���CIJIIQe����8q����5111v�u���
M�4IUUU�����Z>����Bs��b�@=UTW+��zp���x����{�c-��M�rTZU}����f��Q����0�����/<<�������*�?"*���k��CPP�E`m���
~���}�]�L&s{���9rd����s���������_���@s{���6��]���F�)S���;��_4n2���_��SRRb�vss�{{DDD�d2Y|DDD4��z��7�7zxxh��9�vZ>�{h�rl��'I������`����4Z����Z?��������g��5nI����.�h�q�2��#����a����z�h�so�KOOWFFF��#I����h?����v��`��w�m�\����/������PYY����~��E�����W]={�Thh���i��s���,���/WEEE��i*�����+���/��������@��]f��;W�A�FC����j���6���Ju0��A��!������m���h�����������.77W����<��}��C������`����k�Y��������8y��>ln�k���m�
)""����6����h���Y�wn����G111���S�N�����j����+**����u�n���F���UWWk��I�d�=����:�*4w��.���{A�2&�'I�|<�����"��[3����C����
h:BBB������ kKJJ��_TT������w��yc\]rss/h]]�
�I�?^���xu����h��z��+**���������m�?>>^��{��������EDDh���>|�
�����:�1��_��/��"��?��C���9�*4w���f-��Vp��Y�����J�IO���dj�s�P���NY[���L]u�U�9s���$]����P�o���.��l������������o��qz���k\�����9s�h��q���PDD�&O�����5;Kjj���������5h� 'V����@�lU�L�)��:�{p��A�su1hxh��>��j+�/f�UhWV���5��p1|\�h�%��v����tY�����D����������)�67�G�����-�:u����8]z������|}}���eqK����h��F�����������g6���������/�����^3f����kUUU�=�G����s5w�\]v�ez���t���7x�����"IRXX�^�u'W��������*U��%0��M*o����}���Sbf������o�z{4��p!\.j�����;xvthp��g'�>/j��W_i��
�v�6m��h���!=k~���F�����UXX��s����E;((H��-k�3���
}��7:y����[�
6h���:r�H��{�����#���z�������r<q����/���K�.���~[O=��ET��������
��I��n*./m�s/
�Qzq����_!��t�n�"c����>��������8�,�����o���9s4v�X��fgg7FI5Y���9��sR@@�\]]UYY)I*))�u�]���;t��	&h��	�~�%$$��/��W_}������i2���3�������W^���G���h��m���]��bh�s
�����+����3��^	�E[��ztt�Y<:*�=�!g��l����y��mu��w��v����QR
����;v8���d0nn������N�%,,L����g�}��j���1�����~�)u����l�
�y�5����F
i�NZ��=���:TP�(?o���������w�9W4��8�O�6)��h�����z�\\,�8}�hh����t��AI����}�v�����=����8>|��NHH�����X��%K�(**����O?9�"i����_�R�u�_�E{���j������{���
��=4[6�{���1������{k^���-g����]~���p�n�������F;#�'V���6��h������^���������>>>��b������n0�$��w���������p�
������Y�f9=�'��l���9������zz��� �<X
�Z���MOqe�J����9��������z0��d���9���_���jp���6�6���F_
��Q�F�


5�w�^�����&==]��O��9~~~������k�O<aqk�����n��z��l�F�Rdd���u�V}��N��w������7��X
�x��Y��q��������������:��B�e8�h�<�^���]�p�l�}=\<uS���i�j�}�8
d����\�?�|��322t�-���;���������]�v����v������q��m�����Gk��
v�/**��-[�>�1�F����}S�L���s����4y�d����[�d�^{�5������{�����s�_�~6�����`0X|�����~�Y��Y����2����hu����tS�`?���e�tI�+����{�n
�`7�y}uk��ui�������~�����5a�=z�����@���S��=�k�.IRlll��1b�����*
6L��O�_|��������7�<y���Y�f�k���v~~����:=��C��s�L&�����R���Oz������g����0f�=��#�vEE�&O��k��V�W�VQQQ�5������;�h���������sUQQ���g���/���;�������Kk�[�u����/�3�<c����_�SM���.DNY��~G��w��|�^T��%�5�L�6�����C�n�ogh����ht�D����%]�>�>�t-7�53#F��M7��o�����p�B-\�P]�vUHH�rss������?��7n�8EEEi���v���c�i��9*--�$�8qB���V���?_'N������W_}�n�A����{p��y�7o����t�%����K999JMM�ns���_��������}			JHH����������J���*==��ko���b�\�R+W��$(44T*//��c����Qc��1c4j���z>���]�h�����b��I�=�������p1X/���/y�
�&O���
�E7���:xt���uc�;um�-����O?�T����m��U������3F�����9���Z�h�|}/���=zh���4hP����l���[���:x�`��I�����-[�7�xC^^���TVV������m�~���������k��Mnn�����e�����jh�����E���@@3Ap�Neu������{���j���6����p~��
�&.���n�0V��&������3\.�s<\<u�g���_��au[������I�!h����6m����m������,Y��K�����������t������9r�:u�$___��P�5aaa��������k���2�6����[o����|�����L�:U)))�������;�9?44T�������'N�}��5�<��#Z�j�z�!EFF���������m��I~��\]]/�Y����n4;9��2�sfpO��}��W�6z�d���������8�����!�$���
S��L�2\�fp�W�������e2�z�]����Ak7l�P���1c�^x����/JJJRNN�����(::�A������}�Y=����^{�;��Cw�q�rrr�y�f�<yR���2���W�n���W/�k����.��H�>��}��'��}���9s�f���C�i��]���PNN�\]]������;+66Vu������n�M��v�$)##C�����#G������by{{+00P111����|||��7""���V�������w���.�~�����6n���������2�WT���6i��\����\�?���� w����a
����������R���o���e\���H�n�����
>\��o�}������e+����$�pn..([��)-��Z�!��f'�Fp/����������m����]�3%�����@�Rm2)����XS
�I�e��
�r�:f���t�*��[�FGp�JAE�*M&�cm�Xp��`����rw1X/����3y�
@c#��f%���j�AR���c�����Q���?TP�#%�+@�#��f�Vp���U�.M���.m������/grUXQ���4����f�[�� 7WR?W��W7����j�6��U�����4�{hVl�\\I����hX�@l��*)���B���q�@�QRY���j�cm���{����]������U���rV�1�@�a��=I
j�=I���v��V�L�6��QE��p"��������J��^Fy�\��q14,4@n.���UJ��wpU�=4�n�k.������UW���?�_���V�!�@��R�{����[]�x��|:WE�U�@C!��f������J�c�1�'IW�����hu����M�rd2�\��Ep�Bny�lE��<\ZKCq7�hXh�6�O��kOn�Ckp���Y�.���o4���<�{����C��|m����WV��g�4�@��e#���*��;���^Am��fu�Z���rTY]���\0�{h��*���[�5'.������b^E�3�\�EpM��dR����pO���]ue;������VX���\(�{h�
*�Ti2Yk)�=I�l��_O��?��Uqe�+p!����u��$z�:���e04�]�|\�V������t�L6B���{h��l����rsiY?�z]4�}����e��[����[�z�3Z$[7�y�9����P�@_�����k���s�@��]n=�����$�w�6
��|�&��S9��69�*� ��&���J���V�Z��{�d44,4P������Jm��wpU�ApMZvY������$wW]�gs<)�H��JX{�@��]Va����"/c��q6��[�>�6�:����*V�.-���h�l��<�d0\��
j o!���j�t:W&���������,��=WW�<�F


�9~��L�y��\��`������]�F�z���f������J�cA�n�����=tY����Y����P/wz���@c���Vrr�v�����L���[AAA������gO����MXGpMVny�L6�����Z� ?�(.W��[�L���rtK����P@�p��	���;�?�233m�������c����U��������l�P�$�A�so}���b���
��y9���������a�L&��8?Oe��2�l�	x����T�����]���������f��YkhO������G�w��z��7T!����ng4�e�V����b#�����i`��~���:�7�H�x{�OW.#-U�?��S��L�a���<}|��K7�FF+v�pw�p^�Z�E�i��	5�F�QQQQ���WAA�<���?.�(//�s�=���B�����.M�=4Y�n��psp%MKwo/.���R���N�jTx�<�FW�sd�6%��L��{m�)-*T������7%~�B�����Qw�k��@K����?�������@�����������k�/--��+����������W_}U#G���!CZ;�&gXc2��]Np����!���e���|IU�~:�W���@SQR��o���/��^kh�������������*)�o�
�63g�Tqq�����7��G��I�������>m��]�:u2��L&n���=4I��U���<k��=I�t5jh�����J�?���88K��-��_�����O��?j��������)@��j�*����?����Z���������E���6x}h~��I�*�~��$y�:����O]�cs<1#_�6n-g�8�����WaNv��W�������pQJJJt��1��?��Ov���������{[+**�������y��h��m����rs��O�����N�)����X���O���N�2N��PR���_{I�E
{UiQ�>�����3g���_���Rm��MTzz�\\\��[7��������u�������������*&&FC��.�Waa�������deee���D���
V��}}�{7���"���/JOOWFF�***����.]��g������E�������7+--M&�I!!!�������#C�'���\[�lQjj�222T]]���EEE��+���h���+**�{�n���GYYY***������i���pEGG�[�n�
);�f��S�Nv����Vpp�N�:e����m�����@�d+�����J�6W�����c�2��.����
����\	��4�M{�+��V��9����7�����
gn���K���WUU��{�=��5K�����[�?��f��!OOO�������+�={����k�
		�k���I�&�]���t�R}��w��}�*+k���BCC������'�P```��FDD����5�,X��\7�|M�8�����Y�7�|S?������m�����=�����'�C���y�m������SBB���N�:i��u�j��={4c��Y�F���C�?~��M��v������S���+�h��%����unpp����=���9rd���1X����������%%%������W��I�.��8���=��?��_9��S��e�,��M�?���g$��������g4WEEE���5e���=I*..���35b��������_?����������=��Cz�����g�����������e��ZC{�����^zI�_~��ms�����'5|�p�t�MJHH�5�'IIII������?_�s�}�]]u�U6C{�t��1=���<y���������RO<��z���+V��I��7k�,EFF��o��k����+&&F���^��=I����������/�:/55U���#55���������-��~�8p@yyy�v``�"##�>4O����UU������=�b����������9*���thH��>s�9��Z��s����1c�h�������0���_�^z��F���M�6i��)��3g���k�1����v���k��5�z��w�����YSiii�>///EGG�_�~�����t�"��Kzz����j%%%���
d���8p�6n�Xc,00P=z���%7������5e�UU���I///���j��
�1���z��w�����X��r�f��U#����{�o��5n�+((�����+V�����{u���Z��$���C��w�����_?EFF^�����s�=�7�|��u����E���������49�e6��Yg04�}�<���/����3�2�L�@k�������9�x�e��:���b���Z�z�$i�����o�����m�6���W�O��c�=f����>����u���+--M��������8qB�Vbb�>���d
6�b����7UT�~�YF�Q7�|���������P��������m�69rD���Z�x���������5n�8������O�~�z-^�����Z�~����#G��+77W��~��?n�sqq��>����+++K{��Qbb�8���|m��IO=��������u��!sX266V+W�Tvv�������D���k������,�M�6MYYYu�����j���������M��#G��������_�c��>}Z�v��]w�e�[UU�I�&���C6��:u��������{k������Wrr��n���������***���;�������/��k��<��BCC���k�����y�buu����5�|s_�N�4m��F������g+��at���`$/W�����'���-,���E�{;�2�T]U���L�����oz���k4��?9�����
��y7�9[jj���o{��gj��m�V����JJJ�$���{��GIII������~��C��X��{w�Y�F���7��w��)}��75j���������+<<�����i�{��Ww�y����N}����K�v��w�}�o������[<�Y:t�u�]W�y�{��G���bn�����/�T\\������2d���W_}U����:'==]�4r�H}�������>��}�������A���o�I�=��x�bs���e��i����v�n��v�Zu�����^�zi���9s��N�*�����y��Z������<�[�������������eu777���G}���/����d��;ZPP����K�9�|{��������Z���S�>}������B��������o�m������NNz45���d���uw��`pp5�K'O���()������<��r��;�
�EAV�>zb���p���}���}�����<��k���ks�=�X
����W^��T]]-I� �[o�e5�w�����M��q������YSkp�K�.����@��E���kWs�j���V�{
%99Y��-3�
��/_n3�w>ooo]y��v���sg-[��jh��=_�u��^�f�����dR||����B{������m��i�������Z���P�RRRTYYinO�8�fh������:�W\�_�U��_�A�c����7���&  @�'O�?�����9�T4\W�&���{An��y�����J�IO���drpUg0�1cF�����������p=���u����[���GD��_��u

��m�����8����+�9��?~�F��h�=��s����s���_���@s{���6��]���F�)S���;��_4n2���_��SRRb�vsk��zFDD�d2Y|DDD4���������}���_kk����������#����I��6)�����=���4<4P.6.'�,���Y�-
�={��qK�-�]v�E��;���h�s����E�*--�^5������������(�H��u�,�O>�d��e0t��w�5�h4���/7�322TVVfu���������UW��=jno�������0�����UQa����?�������|P999��-..�������(�����o��������J�������<����������B�*��Ch����g���m�Z����{Ak����^����y����P��}��C����`0��x���,�fff�}N}�<yR�6���kW�6��Q�k_�v��Y������;7h�������z���S'��III5����eno��U7�pC����X�|�M]w�u��k���o�4i���[�3g����\YYY�����SO���[�TQQ���~[#F�Pqq��M�����]f���
��;?����>:^\���zO����!�0��<��
		�{�����-))�s~QQ��O��w�}��o)�����uu97�'�/�x!��������m��}n����H..�~���l��������{����%$$(""B#G�����5h� ���_���m�������nn��������W\a1/((H��
��a���#����o��#G$I7n���>�8�v4M�CMJV���^���\W��
m �hUV��3�2�l�qh�<==���6�������4s���I����9?�V�`]}]����������c�f�q�����_����y���j��97n�"""���'+!!���w1//O��_,��/_^#�w����^�Z������*11�Q�D���%hRl������JZoW���W����)���XP�H?o����6m�����9��o���NH�{b	�~�n��3;�\m�;���f�����{�E_�N��K/�T;v�������,n�[�p�-Z���X�}}}�������{��u���k��Z�v����j�9z�������s����.�[o���������,�&�1BW_}�]kcccu������>2���;Wl�2���@�a2��Cp����z��_���[��L��y����_����h���N;����94����������W_}�
6��m���|��c�Z��������?j:Waa�C�mH����?((H��-k�3���
}��7:y����[�
6h���:r�H��{�����#���z����.{���u����k����j���qc�����w���(��Ry�������]/��?�*)W^Ee��J�IO�����r9��z�X1��+���;o�0��������m��3g���k������(���� ���3grnC
����*+�`II����:����CM�0A&L�$�8qB			���/��W_����KL&��y�]u�U���+R�-)))�.]��k������/�&4�G���q��$�s���puq�����d�V������u��Kbz8�����)�s�C�����e����m������{���{��"##-�;v�p��
�`0(<<��.))��'�RKXX�����>�L���c&�Io���S�:WYY�E���~N��Y�������kB�GpM���^7�����z��=��7����o��:]Rfs.����r�9n��!����>}��ydd��F�]������sq�|���d�{mhh������3g�h���v�o*���,�			N�����Z�d�E�O?���j���m[�v}C����r�5�����h2��*��yp�^C�,�G�����$m<����j�����w�bo�3bW�>���:7@W^^n���?�X���v�����h��V�n�������[��M���0k�,'Ub)22R���7�333�X��""",��
9����n��]lIh����u����c04�}��]V�+��%#��Uh
�y��5����A���Geo4���P��{��Unnn�k���5}��z����gq�_JJJ��?����-^�X������6j�(EFF��[�n�|���~W^^���|s;00������k��h�X�BG��kmvv����S�~h���I(��Vae��� w�{
������l�.(�����e!��W?������m�}=}|��f���_����1h� �����z���k�����[n���������mn���K��{}TT���gn�L&�=Z6l�k}QQ��l�b�y��h4���_���2e����[�}8���'+==����%K��k�)''����{�=���������9755U���#55�^�����o����Meee�����|���B�=Z����>777�;��kD�CpM����$n�km���ms���<TT:�"�AH���z�������_WH���������h��=[&L�q�YAA������={j��]�����z�5b���UUU6l��O��/��B������o�8y�d���f�R��]����|]w�uz����s�N�L&������������O+<<\�g��W��a��1z��?n��������u���j���***�����B�����y�
:T111�;w�**j�����3z����cG�u�]Z�t����8����/z��g,�~���|�������}��oW�>}�p�BZ����h������,�&O��n��5z�h�\�] ��y������hW���TI�
*j�tXQm��S���c[�N�@K�9B������s�����O������G�i��1b�n��&}������j�������BBB������������7NQQQ�>}��g=��c�3g�JKK%I'N�P||���������-������W_��n����%��7o������� ]r�%���RNN�RSS�����_���rrr�|�rs_BB�������p���R���JOO�������X+W����+%I


U@@����u��1edd�X7f��5����������m��z�js���G5a�M�4I������WAA�>����{<Xo���#�F�;��$�
�y��@p�Q���hxh�l}u�����9�6F��y����O�]w<��:�^V��c/�������;��f��O?���k�9rD[�n����-�cc�������}Ntt�-Z$__���G���u�
Tc,;;[�w�Vbb�<�$C{�����e����7������Xee�>�m����_��<+88�������*99Y[�l���;���~�a-Z����H�F�V�X��{��Xee�����u�V����jh��{����~+OOOG��f�����r��=4�Ow�m������e����������{�_����t�w������c����U��{��;�����tO����g��*FC���5m�4�������G-Y�DK�.�����u�]w���z���5r�Hu��I�����T ,,L?���>��s
<XF���\�����{��7�hr7�M�:U)))�������;�9?44T�������'N�}��5�<��#Z�j�z�!EFF���������m��I~��\]]/�Y�����{�=���/;vl�aEwww�~������x�b��&�&����"8���{u�e�U�={��G�N���������?�v\\?p�*�I��T�������}A���g�j�I��g�t���^7�n�"7���������u@k������<�
�{Z^��6���^
�����J<x��/**���^��dREi�*+*���&7O�z���������_~QRR�rrr������0
0@����.����m��Y'O�Tff�������[7���K���sv�v9t��v�����������U�������bccQ�=322�o�>9rD���*..�����^�z�������TTT���~��}�������B��DGG�_�~���pv��5�o�#������WZ
�I���.�������W���U�r&OCC�P���`0���[��_t����Sqqq���sv)v��7���2.Zdd�]���GHH������7��������������.�Wf����*����w���#�����v6��(���q��=8]���^���\W�zum��nml����grUXQ���������Vp/��������q3Z+�6i��U�L�
h^���L&S-�=WWw������{O��kON�Ck��{p���*�W[���������z��9�3�@����h^����l��'IA����g���y�[3I��T�*��[�L��S��UZ��u5�������b0hXh��\V��+����������wB��l����m{����UW���?�_���%�h����m���k��y�k/��?��UQe�v�EIDAT+�>�{p���j�}q�^�qe��|]�V���M�t*G&���UM�=8MN����$)������6F

������r��-rhM@SFpN�]f=���b�������<�3������|e���Z�{p[�� 7��w���j�O7�c��~<����j�4A��4Ye�V��<����\.������Pe^E��e�;�*��!���6��[n��=4M~����������b��:�"��!���-�T���X[�{MZd/E�z���L��+�X����Sd�Y�m�E����c�A�
j oW��N�UU����2�l$3�����Vp/��UF������<�.�>��xzq���9�"�� ����rwsp%�P�=ty�����Y�6�������d2��y�kN��m��6���M���rTYmrpU�s���UV��F��VM��`���@�V�s�+�=+��U�Epg��=I
$��������?��I�E:^T����"�����u5������Q���:�x��t:W%�U�p�
������f�`0hp�y�^�VU����2�L�p<�{p��r[�=WW���it���@�������W���� ��*��VAE��1n�k���=tY����m�y��q�"�R��C���mO"��R�m�g���*����UU�\�8��PYe�V��]�u5:�4��A�Ce4X�)����|�@b0�W_}�����_�4��2�7�y��`���B��������%#�����"]���K|<\@�UUU�;vh��}:s��***�����;*66V111rq�.�������Z����:^\�cEeV�7�����y�i4yyy��m������[����SsRRR�`g���h���Z�t�rssm����S\\�&O���n����G�#���6��[n#��Np��1�.@_�e�����xIU�~>��k:r�"3�����*�L&�F�c�zKMMU�.]��	&��O>q^Ah�N�:�g�}V������L&�C�����o���������e	������U����Ip��#���+�T���a�q�e�t5jH��?�mu<��T��������hJ���������B����<f4���#___���<������k�!'�H ��$����xE���\[�j��Z�����8���m�^m��R���#U)�� �$��2�0!����i�����C�	��L��ZY�������w�$k��[����X)�����@s���uO�����������������s��JMMUyy�������*[���!���F��gHJ��[���[R�NIO�oe����e���t�.�NII�8���r�c������TVV�(%%E]�tQFF���h����UQQ���x���=��������1c����m4
i���Z�h����G'�V���`�"��^z�KN?<�ec�Ru��V%�@���ijY�Wv� '?D����W^^����}nyy����eee�W�^r�y�p��v�5|�p�7N�������u�)���t�t��_~Ys��
��t���j���Q�w84h�
�;��C%%%1��Gp�)��ez��I[�r�����+T���^T����r���jqlUYY�m������LYC���L�Vbbb���^���K�V����#��x�t�#G���;����������_�~
�]G[>Gs���4ME��&IY����[c�	�m*����Z+`���Jm����C{������y����br=�Wzz�N=��&�I�o�[9r$<���~���Z:��U��j���kt�k?�%ie��-z�����q�#@[����m�6���^7j���>|��n�Gk��k�j��������P��}5e�����{^MM�>��3m��U��������A�4q�D�\'Q��������m�6���Ziii����F������Bee�>��s������P~�_���������n����{�����+�w�^�����l�9R�F��a'}}���U�V)//O���
�B���V���u�i���t����~�6n��M�6���H����x<JIIQ��=5`��������������9s�������?m���T�������Dp��0C;���������
����WSr2b��-G^^^�:����+//O���o���&K�.��)S��|P�f�R0���>�g�yF;v��s^bb�n��6=�������X+//���>���{Neeeu�������{�x��
�s���z������[���S �<6''G��r�n��vedd�{�^�zi��=u�_z�%���K����=[�]w]��^�p��|�I}��g��|��
<XW]u�n��fu����kk��������d������w��?|�Z�l��I?��.\�����������k����3��c�_���@�>��^}�U����{l�t��g��n��i�u���o����������>��$Z.�X�V��$���j�L���3;�[�������j�
��JJJTTT��{7,�^UVV�����w�5�'IUUUz��'t�������g�v���1c���C���$���n��w���z�{�=
8P�f���U��
�I��|�A
6Lk��m��t��AM�<Y\p��,YRohO��n��Y�f����u��y���u���[��$i��}����u��7+���V��n��v�1B�����I����3�<�~������o��/^�A���g�m���#G�h��yz��G�=.//O�aD|���5��������A[�-<!
[X����>uO����D�����*���������>��i������x���\�.]4v�X�r�)u:}-_�\w�q�$����:����a?�0��O�7N}�����SO=�W^y��5�����KHH��4f��;V�{���{����Yg���[���cd���?~��-[Vg-##CC���q�����'�L�s�=�;��C�`P������k��q���K��_x�=��S
�vUU�.��"=��3u�~9999r�F�]��^yy�.����?���o��Y_|�JKK#�=�����k��1����I}���c��#F��$�A-\�PW_}����$���������+5{�lUUU5G�8A�`�"�����J�R�������������L����ZUU����m�����`�1������{O�t�5�h��-������k�y�f:tH��zk�9����q�F���?���{�x@��]��f����K��m��I�"�������Gf�hN�S^x���y���C���o�n�:�]�V����z�z���5`���yUUU�>}�L���^y�-^�X/��r��������[~L�6����^�.�����?<�p8t�
7h��u***��M��f�m��]eeeZ�|�~��_�C���|g������������o���X[�l��5k����/��B��~z�y3g�lP'�[n�E�-
����5s�L����������/��_���C��a�.������`P7�x�v��iy�{��W�������#��{����L��m�����n�:���C���Z�~�~���j��a
�������}{x�t:��gO���j����������k������Rii�v��������nP���5w��f�4OI���C!���Q����~��������*��'Gj����\c:��_������[AA���:tH�;w�u��x<��,{[����$=���������gee��g�Uuu�f��-�������J[�nUrr�>��M�8������5v��p����������K-k3f�v����={�[{JJ�����K�]v�.��2}����
6������?��:�L�0!�����sg�s�9��w�[n�E�w��SSS��;�h��)Q������g��3�<S���o���_7h���|I��i���[o)11��1�G��G}�3�8C_}���oC�/��r8������9s���}����E���o����1B����O<�{��W�������K���n��KKK������
���+�����n�[�F���Q�t���k��m���E�������m��Eg�qF����8p@?����y�f=��cMY*b���\�E�=I�"���ez����5G���]R��I�$xl�h;jkk�a���.�6���C��e��#G*>>�Y���UW]5�w�G}T/���B��$��x�����������3gj�����������w#��67w�\���'n�={v��^�l��M���zxl����g�;Vbb�N;�����G����QC{G_�������Z�L���Y�"��/�w�{��Gk������%I�����}�������{�n��������E3h���x����a�����_�����>}�&M����,��O?���������y�?���v���o�����H��.m_qm ���a(�����4��'�K�u0oY�W����@�a�~�����K�;6b�g������{��_,������_~��B�#333"��r����q���~:�3���^�i��5�~��w�����{���S����_����E�Et����;���o~����M���o�]����d���b�W�^2M3��W�^1��N��JJJ�]����[���^��~�#]p����~����o��e��q�=�������U:N�=49��{�qn�as5hi���N��8��xR�����_�f���u��Y:th���?������ArrrD�j�����������������&�G�>�����/~��&��0]y��
:��tj��a�qaa�jkk���D���5�����+'''<^�|y�c�t�1�7o������B����:��[7-^�X=z�����W/}������z��'��N��=49���'�����+����N�����F���-���3���feeE�G�}B����5�<���_|Q�_�F����;+))I�a�����q��#G�Oc<xP�v�
�;v�X�a,�������>;v����F=���]RR�
����w�����[�����S����W�^���;��;"�V���Q��x���N��t��A�=�X����s�t=D�ApM*d�*�����LN���D��U��*�l�Z������������ Qee����^������n�?��}���*((PUUU���z�
��1��I�?��c�x����1��|�����������c����kG�g��Y�%K�h��	����~������^��={u�mUrrr����L]v�e
:����RZ���jjj�f������"��&U�(hF_����--���T���]�C�>-(Q�����a��������#Gt�����'�Pmm�	_�d��������d?�f���*++c�����7}�t=��#2#b>//O�?���O��^�z�W�^�����d���5���{��~����5��������#���[��{<)
�&UT���!)=��{��v84)']��;�P�����*.���T�kZ+����#G6��;w�TEE�m�%''�_�~��w4���,��6W\q�6n�1��{wM�2E��r��u����d%$$����g��9s4w��&����<b-l��5E7���v���o4u�T=���Z�h���`�c����^xA/�����?����:uj��l�:u�Tgn��������x�������']��=4�b_��^Z�K.�u
�[��8��J������_W�Kb�:%��\�:��d��"55���^jjj��/��`�-]�4<NII�_��]s�5!�h>���&�����f��o�$&&F�333����7����z���}<xP~���.]�e��)77����6m��i��?��?���;�����o�����������6����������6��=4���@��,��`mhF��W����Wg�����D���V���_�h~:t��l�-�?�������?�k���A�7EIudffF�[cG���t�\.�>�Y]]�s�9���;w��3fh����h��%z��w�`����6�0MSw�u�N?�t�v�i�����N��M�6��jkku�������!M�<�
�&c���k�w��$��z��I�2g���"���R��p"�t0k*)))�XZ�U�V������+�����n���)J��_�~�/����}c�0���3<����5@{�.]���k��o��;vh��q�5�4��?��Y�j.�G��:t�Q�$���:���4���TC�	������$����1�r}Wy�r���+�	���K��'���R�~��t:t^YYY�tGdd�4��������������u�|~K1e�����%K�������S���j��g�}�L�4�����C�=~���']��=4�n{���q�X	Z�^)	��j��W+�����"'"##���Beee)##�I���;:@���|����w���4������qUU��(�����?����:�%8��y��f�$R�~���S�����#�X���;�<�����_��v����s7o���[�F��u�Y�,1DpM�*���r(��������w������B�x'$��W�^r��Mrm���^�z5��[999�?o��Y^����������j�>�����v�����o�����}/���>���F]��]z�����_x�z�j��/i������TVV���mRR�������G}�A�>������'�c��1�
�EpM��"���i�_��mr;���!�b�P�OK*l�	@���n
<8"LN�S�n�P b��3���������u�����.jP��hn�[�7l��]�v5�����k�����i����+�t���_YY�U�V5x���t:��#�D��q�z��u�������oV~~~��W_}U����URR���=���������cyl^^�������kT�-��>�uo��9����^�9���5o�������A�"��&c�q/��);>N��R,��,*Wa��������D
2$f!;���!C�(111&�C����1~���4c����'b���\/�����
6H�����=�������&M���zHo���/^��>�(�q���:�?��3���Ox\VV�s�9G7�t���_/�4#�����g�}�;��S={��s�=��z���W_�����������7�������{������:���~}��Wz���4q�D
4H/��������>|X����u���/�\���Z����l��]?���u�]wE���'?9����-[�D|]�q�+VD=n�����[�n�����/b���n���s���/b~������[����<b��k���i�N�.aWs���
�����Gp�7,#Y���:%�gJ���D��������-Ybb�����<��u�����W/:��2��{�.��}����9s�h��9���������z�{�n�|�?/6}�t���_=�P�����[�������F�t����5+���g��u�]1������������%}|�����/*33S]�vUBB�JJJ���5�������O%%%���,Y�%K���r�g�����T ���U~~~���!������o��7��$���+''G�����|��o�
��w��W��K/=����?��z���t���^u�g��
�
8s�L}��z���$}����g�����g���[YYY***Rnnn�sG������
���'Z�$Jj�kt���p�&��+�aD]/��������������k���JIIi��)))8p����Oh��z��W4~��:����Z�z���������W_���g7z�h���JNN>�Z����W��3���V\\��7j��5��cG��I��{{�������+!!!b-h��]Z�v�����:���t�������z���m�V�Z����G
���'?���sCm����o��3fD������\�]�6jh�?��>�������=��I�F���eJq;m�mE����;�[��(����j�
pR2224d�
>\]�tQZZ����g��N������K
>\C�QFFF3U�XHOO��e�4s�L���Y7d�����z���wB{]~����}�{�1M�6M��wWrr�#���G��K�X�Bo���&L�P�k�h�ah���z������O�P�M��{�����u��w�G��=>''G�^{��z�-8p@�:u�s�O�S����������_��^�����?���/_�����r�\'t/m����?��-\�P&L�<�0�z�������w�}��^+a��i6w��y�f
:4<��i�����Neee���O��)S�(55�+�V�8�����:���ta����k^����D�,zqC����d�h�x��������u@{�k����=�
�{�^���X?��c�����������i�
�B
�Br8r8�
Y�u��������[����Dqqq�������4wyQ���h���:x���9"�0�����}�j�����cs�� ;w���
TXX����\.����G�<x�z����kj��-���Uqq����������
4H#F�PRRR�o���������={����F����&L���_W���;��@�������[P�����t����@���/dj��M��%��Z�0�t:��j��#>>^S�L��)S��������^��e��~��5�K^cdggk����<yrL��^t��U�_~ys��q4wh{B��_ �Z��ms5h���M���U,����M%��|��b��P�4��e�C�tL�������E�:R���"�[�s���������!vFd&�c|��)S��%��B��v��b���u>-�%�����e�����-����A�),��*�w�sV��L��{)n�N�N�\�^V�=�6V����b����'%A}�,�W��*��"�g�SU������k�q.��A{a�N���d�3�zm������iseh�� ����It�C��8���.�b�@�O���������b�*���t(��+9	
�L�\���LE��K�X ���*�
D����223E,��B��iA����U�=!������Gpvq�&�d�eQ�K}�=RfsUhO� f���J�t�C�K�s���i���J����������@�x}�C{�=��_J�z%�[�/?�UU hcEh/� f�j�Q�]��T���j����3:�+�����`H���4M�+@[Gp1Sl����d��������N���U��ZZicEh� f��{n�+��9��a������Y~�'��b"d�*�
D]#���6*+EY_�AS���D��isUh�� &��A���'�{hnN�����#������2��@[Ep1Q\��:oH��s�[EZ�K��S-��z+�������V�@LX�R�\r9��-���D�H��\���W�����-�	j�D�Ep/+�ms%�5�04�S��������W�i�\��{�	��{������w:41'�r}_e���V�X��{8i�������k�:���������$���GJ����Cp'����Dp-���Te�E�4�OJ�6W����N�Up/��P��is5@�8�&�d�iD_/��EQ��E�M ���V\�:O�=�t���wH�\������Z+@[@p'�����=���=�c����D5�����#����*��q��a��1]	��?UCZq�T�i�\Z+�{8)%>���LY��J$��:�S�����m/��� @�fF�����j�r4Ws�����u�eJq;m�8q���uJz��x+���),SN�Giq�@[f��rss�k�.���O^�W���JJJRzz�
��#G*!!���
�B��s�6n������L			�������5j�(��4�h�x�'�*���q�a6W��1Y�:PU+�/Pg-`����Dv� '_��)�V���o���>�L_}��*+�7������^��n�MS�Nm�^z��7���j���*++�<6!!A�_~����N�5�Q��y9���nV��L������049'CN�\^Q�__��[����)_0��`P�`H�i6wIh����dF�����k����=��3�����+W7�'I�@@�����=�\]q��z�
���K.Q��]����\,�7�'I����;w����{��G>��A����q'�4M���L&�C���qkl�T�.������
uM��s�������������*�����/_���^��P�����8�IIP������T���������8���*77W~d��7�xC����������^�5W�X�P(Tg��v�K�.���VMM�rssUUU^�Bz��'�}�v����r����tt��	+��x'��8~1��kpZ����[v�D���?4h�}�5�`����P_�T�`�/"�'I�����>}]R�w���}G�����*��%''���/�3�<�
6���R�w���_~���Wk��m*//��t�i�E��~�z�q����S�N���{������LyyyZ�v�6n�(���h��a�,X�@��w�I�+��=���Z��Z��w�@�e�����xg���!�<��i\P��`H�,�G�u����s�����b}ZP���@���9SG�����u�m�i���x�6�x<�����b�
�x��ks����-[�����C5�|���_��t��g+>>>�����/�Xk���E]����Ok���'p���=�0��^��%��o5��%��:�c��z^E�v�U�W�F��������8��or��������	=4������8=������W���o�Y�y/������+]~��r���(#>>^���?��[������K/���Z�<x�'����t�C�=9^��-�W�����"�u+��k��#��Q���`H�!��Yx<]~��s[�n���K.�D�F6�HJJ�/~����E�5��OT�����{n�+����:X�Si��^�4�iA�.��A�h�����&���"�BfL���Z�_�KzvT���F
�v�Z���C���r8�����L�����z�����g�}��[����\4h�&N����aV***�y�fm��MEEE���VZZ�:t����Gk��'|��PYY��?�\���*,,���Wjj�z������GtF;Q{�����+�w�^�����l�9R�F�����|>�V�Z���<*
);;[����i��&��y�������q�6m����"UVV���(%%E={�����o�������{9r�H��3q������{�d��=���@PU���xDpm���������P�~_x���
����jq@+��pi�:��*���RM��h���&K�.��)S��|P�f�R0���>�g�yF;v��s^bb�n��6=�������X+//���>���{Neeeu�������{�x��
�s���z������[���S P��������[n�E��~�22��;�������Sg���^�K/�dy����u�u��{����'��g�}&��gy����u�UW���oV���������]����OK�,����{w=��������M����k�������zLzz����Z��9S;vl��

������W_UIII��v��Ag�}�n��M�6�Q������D�����d�c��KKK�d�Qr���(���CpmM���1���.�PAu�������VT7�����WYs�����J������;���$���JO<���=�\UW�w�k�.�3F�����$���P7�t��������{�i����5k�V�ZUohO�6���j��aZ�vm�����j�������d��zC{��u�V��5K�������O?��O?�2�'I������_��o�Y�P����@@��~�F�����[��$�����g�Q�~�����7���/��A�����7�'}��n��yz��G�=.//O�aD|���5�&��^�:b<f��&�'???b����$� v�������'8Jt�x{t�����.	qQ�LI�
��m�wZ����!���Sb�>��i������x���\�.]4v�X�r�)r:#��[�|����I����u��g��~�a�O�>7n����Sg���zJ����qk:�C�$%$$h��3f������{���������������[��1�q�F�?^��-������!C�h��q������o|��s���;�P0����c���7n��t�R��^xAO=�T��]UU��.�H�<�L��_NN�F����G���W^^�K.�D�������7o��_\�������5~�x�3F���;��QK�u�V���[���������d����G��$� v���[������0M����aD]����R��ise@�V\�����;����j�J,�ok�������{O�t�5�h��-������k�y�f:tH��zk�9����q�F���?���{�x@��]��f����K��m��I�"�����������t��/���?�;v���B�|����[��k�*77W^�W/��rD@���J��O�|V��W^�������/G��{��Z�x����i��\�����K.�����s�C7�p���[���"m��Ik������UVV���������:t�p���wv��K<Xo�������e��Y�F������/t���G�7s�L����r�-Z'''k������������_��/���C��a�]~���c���n��F��������{�jkk���#G����SYY��m����Wk��u��c�*++�~�z������a��9j�V�^�i��Et`����ou��=�{�A��3'b��.��>�-Ws������D�S:�k������+��������6WX��*�f�[i���
�H�u��$��r�������I��|�I�u�]u�����������Z�g���m�����J[�nUrr�>��M�8������5v��p����������K-k3f�v����={�[{JJ�����K�]v�.��2}����
6������?��:�L�0!�����sg�s�9��w�[n�E�w��SSS��;�h��)Q������g��3�<S���o���_7h���|I��i���[o)1��3h�G��G}�3�8C_}���oC�/��r8����������-Z��}�F=~���?��x�	�{������w�]w��w��s|ii�>����x��AZ�r��^��vk��Q5j����~m������VXX�\KR(Ryy�v���?�PK�.����g?��>�$�<������
��nw�u�C��@�B�J}��k���D��39ARk���*��������7��2T�z#�ps�a�m�U�V����vy��-������*jh�h�>��^z�%�B!I
����?F
�}'11Q3g��-\����^���Q�����s��O�>*--�$��=;jp/V�m���_=<6C�����+11Q��vZ������^���������c�E����-�{�ij��Y���;�=����k�j�������_��}{D�CI��{����)����,C{�4����m����x���
��z�A���]�v������������[�&���h���x}~Eo0O�=���S��vF]��L}ZP��i���c�~�����K�;6b�g������{��_,������_~��B�#333"��r����q���~:�����^�i��5�~��w�����{���S����_����E�Et����;���o~����M���o�]����������H{��%�4#>z���=N���������/n��WUU���/Wyyyx�g��
�7��Gp�V\��:�4���w
b��phrN������*���&�f���u��Y:th���?�����or~�����0���{UcC��/??_���M��$}����_��M��a���+t�����a�����B���F=��>���G?jT]��WNNNx�|��:�t��%b<o�<����3m���_�+��B�����E�bzm�45c�m��!<�r���+�(%%%�{�i�@����g���0��L@��!>N�������\��}6Vu�3���feeE�G�}B����5�<���_|Q�_�F����;+))I�a�����q��#G�Oc<xP�v�
�;v�X�a,�������>;v����F=���]RR�
����w�����[�����S����W�^���;��;"���K/������u��a-]�T���o"B�{�������^x!f��u�]z��7"����W&L��hZ��hV�2=�mo�t�2���u�����D�`����(���
>6111&�VWW����J�{������M7�������/UPP�������z\_c��~<���')))bl��>:hWYY)��5Y����k��(..����Y�"�K�,��	��wo��g?�k���={�4�["�����lM�<Y�<���o�������M��-���U�V��^�=�����?E�=������[O����=4�i�*�E�e�C;c�&v�P�#z���@P�
����!>>�Y����#Gt�����'�Pmm�	_�d��������d?��i�����������������#��0"��������?�����W�^����n��f-Y�$j��MJJ�����/�0<u�]w��u��y��������/~Q' ������u)��E�a��{h���N��1]KJ���*�V�$���$F]�Z����{5m��>�
Jt�&��7���nM���m��%����oks�Wh���s��w��)St�)��[�nJNNVBB���{V��3Gs��m�����#����M�g�5E7���v���o4u�T=���Z�h���`�c����^xA/�����?����:uj��������O?�>� ��Y�r�v������7�z���j��z3f��SO=�ra3�{h��Z�_�dx���S���W�hGYu�����c|���������f|v%'�ckp/'������-X�@K�.
�SRR����E�\sMDH/��?��������UTT��o,%&F��|ff�^��&���SO��������?���K�l�2����9v��M�6m����Gw�yg��������#Fh��
���+W6:�����j��
�B���.�L/��b�n�h���R�����T�S�����e�f�����r�w	��L-+���nYr��3���)	�����S����B������?������ktnqqqS�TGfff�������K���r�\
����j�s�9����sg��1C3f��$8p@K�,�;�������YT�4u�]w���O�i��fKmM�o�������F���G����
�}I��i���������gk���h��{����-������Y�������_>-E���N�q���)!N<����Z�*����,]y��
>w���MQR��������K�a�g���quu�8�,�t��E�^{��x�
���C�������?��O�RWSr��:�b�
]r�%���
�M�8Qo������y�D� ��F)"�X��������/��UX���"�e��l�>���w����������nbeee�
�9���4|nNN����>|X���k��-��)S"�K�,i�J���gO����s�}�Y3U;{���w���A��_�^^x�����sc���{�������v��`5�����k��o
�H�|w0S��%����;���I�����!�>)	����{������F����USS������"�G������?����:�%8��y��f�$R�~�"�mG�i�jN���~���������-[�h��i*--
�
:T��������:a?�{h�b�n{��Ep�$9C�r��0�����Z]XfsU@�;�c��McHt:tjvZ�\�����������z�{N~~�z��F������o����:���o������/��?l�5����^�~�����W��_���f��[>�Oee�?G�����������O�����w��6lX�����[S�N�-���O�/VVVV��
{�@�Y���%4�/S��(�����-�w�U)������ �����Y�o�}����v�R<���
g�qF��>�O�����=���P]tQ�~Gs��0`@x�a����������_��O�M��W\��K�6����J�Z����5���Gy$b��;��/����l��]7�|�����������������_��g�Uu�����3�����<���������/�������x�����^��;7b���������s����s=z���lE��j��zX�2=nFl��v}R���F�,z+{�!>N�ng�u�-���u~�Z�_��`��'G��fz�1�v����W^y%<~���TUU��~X={�����k��y��o~���I�����u���u�������4i�n��f
>\����>2D�;w�8��g����+���+I*++�9������N��z�F�q����[�No��������.�H��vZ#>;�w��Wk���z���%I~�_7�|������;���)S���q�����-[��'���7���+d������:�?|�����~=���:���u�e���3������������O���s��O~��������o���������t�UW��.���#���R����-X�@����M�6E��z�����~f�OUU��=������m����������}��F�}��g*>>�Q��>��`��=���9-;M��}����B��*���Yr|@;��q������T�o��}Rtjv��Z�s�=W\p�>������9s4g����G����z���{�|>_��������z�����������^555���t6k������=[�]w]�\ZZ�,X���;O�����m��_��/����Lu��U			*))Q^^�����Z6�����SII�����[�d��,Y"����={*33S�@@^�W�����������o��7�|S�������������i��}*,,�s��W_�K/����/�v����{L�=���P��]������$UVV���C:|�p�sG��>�@��k�����y����`0�[o��������	�����h�@�������;��9����������^P����

����<@[�thrN���$hcI�U7<$�)!N�2��=�.S��+���i��i��5�������s��Wk������~��}��s�����WEE�	�:d��^�ZW\q�V�\�V\\��������n�^�u�3F�f�Ru����@ �]�vi��]�^�C�JHHh��^�W^���c~���������������C�V�n��6��w�Srr�M��5 V����Q�G���!�X�����?��/*�����3�VtO���:������.	q�s��9uI����d]�#[t�@h��KOO��e�4s�L���Y7d�����z���wB{]~����}�{�1M�6M��wWrr��8���O�.]�b�
���[�0a��N����ah���z������O�P�M��{�����u��w�G��=>''G�^{��z�-8p@�:u�s�O�S����������_��^�����?���/_�����r�ZFO�_���������/�\]�ti�9]�v�]w����7����&��:�4����Fm��YC�
�7m��!C�4cE�SYY�>����x��)JMMm����K������������Y�F�k^��R�LS�?����4�K�� ���V���u@{������=�	�y�^��7��hox�k�b��n ��;"�����bB/�d�����i�irF�BVh]jjj����k���*))Q\\��t��q��i���]^T%%%Z�r�<�#G��0����o��1b�:v���%6���;�a����D.�Kiii�����^�z5�������e�rssU\\���*%&&*##C�
��#���������|}��7��{�JJJT]]���$����s��5jT�~�A{�?�N|�� ���Gq��Z�ahrN���[(��{���ZSX�	���/ha���0�n�B`���xM�2ES�Li�R,##C^xas�q������.y�������'k���1����v���]�6wh�h���
�ez���)n�N�N�\�^V�=�6V��Bp�e���}����7%A��,�W*UU hcEh
�p\���!3�Z��es5@�e�N���$�3�zm(����2�����:��q�F��'�qh,���I9�2,�T�j�����[�p\V���Sn�R�������d��/��TTO`-OY���jQ������QY)�`�o(dJ��(
�\b������^&�=��9C�s2�2�������)��*��=��6Re u��prR�\:-;�r}[i��U��Xb���e�mO�2��'�_j�z%�[�v��*��,Z&�{��Up��p(������2CgtL���T��C^��ise8Q<i
�zY�2=.�as5@��q:4�S��z~U���V�XN�=���2�����m������d��uG�,�=�e!�KA������Ep��QY)��������D��isUh,�{����X��{N����9
#����Ee6W��"�K�����NCJ�s�\
�>���tjv���o��W��X��,Y����rXtp��&�GR���g���	m�������i��P	�����I��w�8�`�*���q�\	����	������#[u0��{��+@;�p�}�$���'/��'���A��@T�i��s�\
���;���)�r}_e��)��� 4+�0�t:#������@[RU�<�����^�@T��|��������kR���'Y��9R*�/z�mORR��$����T	�-����'''7S%m�=De�mO�2��v������].���iA��![�-)))���*�|�f���|�:����=DU\�:��v*�����]�C�s2���8_\���2{�@�8���i���o����{P�@ �}���4#��
NL��
h��:��m�_���q����4��&o��&��K����`'����������|>�v�����T�����v�������B!��~������L�P(b=%%EN����k[� *�������%je��W�F]_VP�K{vT<1����;��������HB���^��^o�h�<�:w���e�<�	�:j�!U�Q����0��)�2�Wi�!o�v�h[�N��w�.��>>��q�����;��b���(���'��S������-��V�hGY�}�Y��n���CIII�]
�
HJJR����v��p,�@E�=��P���~�S��x
NO�Voe����e���QZ?��e�G=z����Wii�JKK���e�fs�h�����VZZ�����5��@����[�a�\
�c��J���Zy}�:k���%��{9��
����nu��A:t�i�2MS�P����P�C�a�L�
���b_��^��w�Z��������P�(o�VT���E��!����l�b8��.�v���!h������%I���#����,�`���
����"|��"��
Y��Z�S���5�c���P�j�V���T� Bq�?������\6W�>�a��N��8��hWi�a�L���2����"X����r���8�D�SgvL�\������j�
�=D*��ey���T=��5(-�r}��R��6V���@�i���2=n����:�*-.z�6`�Zv�D!���*�����*A�B��=�����phrN��y�5~m(.��&������k�kq���.�������_W�������'�{+��G�Ov9�q��#�IOR����k��e^�C�����5��,�{�����a���!����^jUa��U�/�f�q����$����)�r=��Z����+��!�I�/RE u-����'�gr��&Z�^X�r�����{�$��w���,:�����T���Q��!S�
J2M��h��@�T\=��0�������M���a�~�����+l�	�= �IRqm �|��-����h�:��itV�����r���X@�Gp��;�ez�6W ��f$+'!.��)�����!{�h��@!�T����V9C;e(��{fE �U��6W�v�����Bf�5�{@���v����������[^m_Am�=��6z�=���8���h2�S�/%�r���^U�6V�6��ep/=�%�a�\
��tZ�4���Q�|!S�y2-Zp�A��2���q�\	���v849'CV��C�>m,���&����@;g���kQ��mSv|�Ff�X�YT�����-����@H��P�5�{@�5<#Y�������>-(�����#�����-��m��041']n�u�����2��h��sE����d�S'�.mY���3:�Y��(�R^y���
<�
��Yu����>�IIT��������m���#���Y�\6W������d�3��/dj����isU��=�v��������#�����t��>m�V�Z@kFp�+�E��'���N	��L�\_�LGj|6V�z���Dg������q�F���_^�W�G�����������.��m��Y_|��<�`0���,
:T��z�\��}Y���k����}���������={��3�P�.]b��d�=K�����n��d���j4��)���UaM�PoH���.��An�P�D-HII��y�������%Kt���c�n�.��B���������O^^�z��}R���yB���=[�?���o�����,�r�-�������t�����[<�����'��nW�04y�d=��C�4i�	�c�=��k�w����e���hn�������P�(����Z[X�3:��_@+B�����nSNN�n����7����$��~���;:���4c�����T���z��6m�n��F���$��G�����y���k��y:t�^~����=������Ku�Yg����;� ���@S�/��}Jq�tz�4��o��������Z�{-��������N��u��1c�h���JK����9s4u�TUTT�Qj�UWWk��iZ�xq�|\\��a����D����)S�h�����k������kTUU1������G�[�n��L����?�_��W-��h*!�T�/zp/+�����MIP��x���JU�X@��j�PWzz��O��/�P'NTJJJx-j���z���|�����5kt�u���7�h�~��{���������~�+�Y�&<v8����o�y������$�|>�������~���IRaa����J�]�VN�������K�_�B�Pxn�������)S���������z����sO=��&N������lQ�@S*��h:K�=�}3C�wL���BUF	���BZ~��s�dF�1�Ep�����~���h���JHH�z����Yg��O>�D��z��������|�M}��'!�������9�������m���/D��������k"����t�u�i��q:��3��z%I_~�����������{��9S������q���G)555�����7���~�����������r���ga�=���k�w�3$���m"��y�M�I���EQ�T�j��RC2�m���s4w��C=�o��F7�x�eh�hN�S���5v�������oMU�	y��~���G?�Q������'�|2b�����=X����7���_������K/�	�}�0�����������k�f��]�>�}�@S�
�����t�A������z�y���,_K�3�{-��^����F��t:u���F�-Z�(�e�������[��a�5k�q�������g��x��=�����=����B�Px|��Wk���������/b�x�G;�	��f����m�@K6*+E,^B��iA�!���Z6�{����#�EEE���j�j"����
��Yg��>}��<������>b��w����D�o����x�UW))))<^�v�8`y���@S2MSE�@�5�{��0M���������h��2��h���ru�JKK��������������s�N�1~���,����o�s���8))Ig�qF��9�X�4��}4��	��V�6��Fp����\:5;�r}ki��U��X@�Fp������3�������a���qC�t�4f�y<�����*,,l�>������j�^&L��z��5�=���j��k�D�?5A=��-�?;�Uu hcE-��Vn�����={*..����o�>�]�V��/����O*T���#��I�)�����=����1�u����;��}�o����@S+��%���w�-"�������JtE��	����W�i�\@��S���������\��k|�������z������k��I:t�:v����{���������k���*��			���C����{���7�|��c��=/V��yO45��^���]k�?�C;eX��W�jki���L�Z�>�@��-������}������Q�������Cg�q���?�C{��m�5>1���k��:��c�i5��[���������@S���m�@k�%������������5����J+U\\�����s�^z����d{.Y�D�F���o��I�&�{lEEE�8))���{�����^����U[[+���}��cuO�q��a�����;w�������kA�PYYY�@���*���%m��^�����mj��!o Tg-hJK���9
��k�x��������u@{�k����=�
�{�^���X<+Z/�{�P(���^������������O7�:��u��_���>[C�U���������R���[�|���{�9�����)..�%�\��?�\�
�����d���7�6IJHH�������}�����{MyO���?�Y=��I]c��5*((8�Z�:�Y���K`3B��{p�����h�������k;f\�������Vi��]J:��*��x��������u@{�k����=�
�{�^����{�6w	��k����-\�0b����W���t~ZZ�,X�/�P���zVV����4v�X��W��#�<�GyD����4�^����Z�]�V�E�����q\\\�j;�������&���}�����hJ�����o�r�����r�j�X�OU]zE]������Tq�m��'@C�Mm�E{�����?�1b��{��UW]��kddd���/��;�����Y�����_�����<��nt>����}��628`���d�:v����'�R0>1����J�#���[(wY��ze��
9y����e+��������e��u�]��{������;���o��O?
���;W�]vY�����#��v�k�c��{�X���]���������[u�W4���;w��K/
�������t-h*++�f���x���JJJj���mIQ�j�:�=�25���f�����4�������T2����8%����-�u#�x��������u@{�k����=�
�{�^����[�6w	��k%�{�=��1C�������������o�={�]wE��,Y�@  �����������F�w�9

�5v�c�w�\Q;��yO���cGu���������������SRR�@;2M������������A^���1��������u�tiPZ�~}i�x��������u@{�k����=�
�{�^���X<+Z/Gs�����Ot�W(���N���^{MN���:�>����`yy�<��c�d�������s��i�����������n�>MyO4�2@��M�$I����h3�&�kH�u0o��2y}~+h^�Z���W�?��jjj�sg�q��~�m����ZKRR�222"�
���O��N|�����Z��wo�x��AQ�8p`���j;�	��R\=8cHJ�#�����JUF\���A���%
�,��m�����������������Q���()���ESr�#����?��v���o���-[�4x���Z���F�Y����o�>��u���c�=�T�jQ���\r9��k�.���9rZ����������	����o����SURR�<x�-Z����f�)���(b.;;����#GF�W�\������������;wV������kD%D�b��z�W�ZS�M���^��n{N^���q�^������Z�u����^�g��s�9:|�px�w��Z�xq�A���j���@���RNN���]tQ�x���
���c/��b�c
�	���������J}�����au�>�]�@S0M�2��Ip@�JKT�D������C6V`?�{-��������x�k��������k�f�Lz��#���~�-�����r����K�*77��������s�\rI����?��V+����***���c��K�.���yO�Zu0d�!� V���������fU0���2M����Cp�)..���S�k���\vv�/^���{7ce�����1w����{Nfff�1�ij��Y������������={��s����n�A�a�����?�u��z�����c�=1w��7�{���@�Yu����8��4V������-��V�hGY�}���^Q^^���;O�7o������?����c�����5{�l���d�������`x�s�����~v�sz�!9����;W������[�l��w�17s�L��������Cu��W��>�O3f�PYYY��M��/�K���#<��O�p�
��#�wO��Up/��P��is5��nI���d����L����\���k!~��h���s����t��}��G��())��'??_7�p�z���;��S�|��JKK��z�j��1CS�N��������>�������)����n�)b��k��<qM�����:��3��z������3���$=���5�]�V�&M���K#���}�.��r=�����=���nw��'b�*��w����D����t������%
���U4��OP�v���$��8�k}��':����=&??_O=���z�)IR��]������$���i�������s�az�����������O�����n�:IR(�#�<��\�{����Qnnn��:t�������j��i�~����/j���2����_}���L����l���C������������u�W��{ ��k�w�����4\C�s2��}�
E�������\c:��_@"=I������=�s��z���4u��F];11Q�-�W\�%K���}>����������K,�����W_-�4u��7���:<_XX�������}�������}��'b�
��=��Ep@���56+Uk��E]���B]=�I��\@�q4w���g���zHg�u�RRR�{���������s�i�����}'33S�/�_��W���������~m��Q��
;�����m��I��O��mD�4i��.]�'�xB�a4z;�	��Ub�mO����wJz������P�j�!+hZt�k!L��e�=z���< �4�k�.���S������UMM�����������k���JMM����C?��O����D7n����u��A�Aeeei���:��S�
�5T�>}��+��/��>��3���C������W�=4a�u���U�'���u�eJq;m�@{c�����w�F
�UBZy���r2N�M5Z�{��a���_������a�l�>����.�������'N�Up/��&$��.������G]������j�OM��2��s4whz�>�����>=��50�:���p��|+h����i��6z&��������JsG
LS��(d�6W[���2@A��=vs9���a��ha�_��m�	 ���qV��Iq��/+���R-��.����Z+�-�{m\q�?�|Z�K.�as5����I��u�����+_0doQ1Bp���
�ez�������9�X�+A}^XjsU�Ap��#���Jr95�S��zny�v�U�W@��h��AUCQ�2�\6Wu�LN���D���KU��X��#����Xt���������T�3��?djY�W!���*�Gp�
+��%8JpE�����&�d��X?\������p2��a�����t���d��itV�����r���X��#���[t��"���������k��OJ���-
��h�����t��z8C;e(�aD]���������@U���X#���Jv;uF�t������-��� �@p��*��G�w�R�N��������~)	��������(@K@p���
�ex\r���@���1�2d��Zv���i�W�y�h��,�{Y���@��M��!����j�6�T�Z@C�h�B����@��L�{Z��	q��b����\�5>+h�{mP�?��iF]#��5�����qQ�LI�
J���-
�8��A��������8����Ip�&����0�����Z]XfsU�#��Y�R�.�|�uIq�tzv�����*��W�X@�xj�
*��ez�6W��75Q}R,�W�����"k��������J vN�NS��u�2��P�L���*����1�������kYt����9���.�b�`�O�����
�=�6�����$e���uJ�hDf����#e:R���"����1��@���C	.���@���LQv|� rH������G�@p�����G�=m��04�S�\�u����#e6W�=�{m�=�Aj�K�uL�\���J{+jl��{���@�T�/u�����_J�z'�[�v���@����Ep�
)��eZ�ez\��M�0��1]I.g���`H�ye�V��M��@R\��:�4��	�h{<N�&uJ�\?PU�-�J�
�=�6�*���q�a6W��I�hxF�����2��G��@p�
)�
D���s�\	�kTV�:x����L���B��U����@a�f=��h���I9rYt��Zw����@{Ep��(�0�w�"��=H�s���T������WYccE��"��FXu������J���OMT��x���yU�Xh���E��4�Kn��h���������W��C^�J���w����}��w���w9`�`V�1`������%-EQIB���i�T�J�
m� j�6��*-�4M���)�*�����mo��6��������33����������g��G��y���~GXs�;z����;�D��=���a3R.������������V���a��0 ����|�Zp�����z\3;�;���j,��.�����tb�����)�C�������Nq��r��i���a��0�v�LqV�R�f��$���V;�]Z+80�@���y|�\���K>`x���q������+����N���a�.n��W���W#��40,^:5����vb%v���Nq`,���0��$�[M�n ��t������i���A������4V[���|�Rp��4R)���3��G7w�����Mq����v#oG��{?q��H�|f<w~���Xieo0��{}���.���$��6��e��O�l-�����q��Jt�yuh�������v���Z%JIRp��V)%qla6�9���n��X+60p��\����z��$�a�^�L�����Ol5L�=�>��i4Z�{����x�X=w~�����tL�=�>����n7��)��K�$n9<#��o�����+�����g���������""�������J9n9<�;���N|wm��@��P��c����T���K=�sy��H\==�;����Xm�Lws�����\�Zp��u�����eo)m�i_\�n��
�g�{}������p�*�$�-�F)���n��W���
�5�=�>����f��9S��0s�j�0?�;�oy#��&���@�j4wsg�{��3����z�����hv�&���@��+����+���PI����3Q/e�n�;���+��i���~��n�>�W���U"I�����J9n9<�;���N<��]\ �/)������\�Zp������x��X��K'Wc��.0�o��P���JNiDq���x`*����Y;M������i���~����VZ����(�\�J�Gfr��|jg7��X/4�?��P���y��DL��7Dpa����S���76��v��D@�P��CK����l��$)8
���ff<�5Z���q|q%Z�n���������6����'lI��������K��N|��j���^���g�4�-��*����J9n>4�;x};Z�*.�����F���4s6_��`8<r4^<5�;����X�m��e�{}&o�^D�l��=�����S1U-g�v�i_\�n�]����@��+�MV�Q+���\��R]��$g~r��-o�	�M���3�f;��\��=����H-�����mi=Nn�
L�"�=�>��qOq���N���Z�,���'�c��-6�S��H����v's6_S�(B)I����������n'�|r��T@/Q��#y��"l�(�D��?4�;���v|}��@@OQ��#y��z�c�vE�jr4^49�;������m�����#y���z%�$)8
7���j9s���q�����i�������G��{���Q+�������N/n�����f���@���i����3�=��sh����������wZ&���@�Xm���3S��_��M���Z�,��[�c���)�=�>����<^J"fj�������$�.�D��d��v;q����S�Eq�O4r�{��j�������V���s��Y��ll��/�{}"��7W���</���&Gs�_<���N��������4=Kq�Rp����c�R��5�i���i��
(��@�lw���.y���[j�R]��$g��v+���Yh&�X�{}`)g�^D�\Mq�����s��{O���N�g;����@���<>Q)G�����zn2�d���q��r���bC�p�7@h�l�������JIG�F%I2�������Z���"(��������@O��U�u��s��^��G6v
LAq��5;��hw2g6���M���'Fr���\����y�?)����V������z��$\�$I�
�fb���O�f���X�4MN\.�{=���.��JI�W���b���8zx6w��V3���Y`"�rR��qy���z5�$)8
�Yc�x��D�������|��(����f;��|�Zp.�k�'�@��w7��uq9����T�^S��a�4��V��=�K9I���lTr6����q����S{Mq�������xIq�?M�*q����������N����������m{��Q�������x��H���+�����K�{=,��7S�D9I
N�^I�$n><c����t�q���H����@OS��ay���Z��$���r)�,����j��W�
L��=���i~q���0�=V�kf�s�w�^����@�R��Q��n4�i�l^q``\7?s�J���F������@oR��Qy��""f�F������('I�|���{��
N\
�=��W�����^v0Hfj����T�����x|s��D��p�7@��+����0�^:=����o;�;�N�����������^��$!I����L��lU��t�����i�������Z�n��foU�q`p�T�q��L��������Vq����������E(��+�G��3�����Z��������@j4���k�$&*���P����b�V��u�4n]\�N��
8_�{=�����4W�F�$��h�R�f�����h���K������@:[q��0[��
�r��\��'��&���@���i�����zz<����o;��N��D��P��1��vt�����pI�$����r�?�������J�i�/`_(���F3{�^)"fj�b���F+����L���;���������c�r�{3�J����4���������r�_9���v����Q��1y�f�����K^{`:w�j;M���rt���T@�=���i4������Z������(�,_=���om��
dR��![�n4����������W����������;6Q`" ��@i�vsg�{DD�|f<�=V��o^qUtK�O���C����x���K7"�$�#�g�^������c�YWFZp.�'��
�C��{�����U�q����ykz>Z��&�2�=���S���W
N@��rb4^:5�;�\�26��?���#v��X��d�l� �kN�t5��].�]k;�M�bC�{����m/Bq�l�R)�.���������7��(���F��y�ZJb�R.8
���H-�������'�[&�zD����Z5�$)8
�����x�h-s�F����hu����!���#r�{�j�I�7I�����Q��yo�;��S����!����i�-�=.�x��O���Z�����
L�Kq�����I�gs�J�a�[W�T��|*w��S����.0'�=�������D�L��=����#Qj�d�v�i����4�-�	�=��he�fj�����������?�v3�'vZq��F��`�(���F��y|�n���������mi=N��
L�Eq`��i�f��=�=.���'�@5���iD�������|��Q��g��n�t���{\�$"^;=�R�9_���WN�
����>[���1W���A3V.���������_�..	�=�}��)��UJ1R.��As��h�pr4w���+���)0>�=�}�W���WN��z�����d��[�4n;��4-8.�=�}�W��S�`����8�0I�|q��\�(42�=�}�����n's6WS�`�����&s��.����V��`p)����f;wf�{�Usqh$��K�..�n�[l(@�{�����<^-%1Y-��AWJ�8�0�R�9_������
N�Gq`-���j�H��R\��j%^p:w�������v��`�(�����{��J�I&WM��U���;N��V�S`",�{�������.�����`�$I�;4�r���M���r�iZp2�{�dm���>����Y�\�#3�����n��+��f�A���O�v��$"fj�{\~���vn"w~���Xjfo��)���FNb�V�J)o���W�M���M����uq9��n����)������\Ny.�R������$����V;�:�Vp*�o�{�Dq�^1U���M������l������>�jwb�����+��^49�����~r%���@�R��y��""�j����$Io84c���
��n�~b%�4-8��=�}�W���b�R.8
�H�\���gs��o5����@R��y���Z��$p�g��������O��us,���/�v�������5��1��;��F����nZp*��{��vcuWq��UN�8�0�$�����q��Z���(�l��]��P��wL�*q�����+����N���(�l���y��$1U-���dj,�7>�;���Jl�;&����P�FNqo�^�$I
N��$����X9����N7�8�i��z��@���{�������Kqda6w��f3���U`"�}�{��i,7��3�=z����������]�Wc%���Hq�@���h�i�Lq�^v��T��+��Nq��rt����`�(�h)gQ�5�=zW������('��F��,�
z��@�9���Z%*��&���Z5n<0�;�e3��)0�&�=����m��O�tz,�;^���vb%v:�@�Q�(P^qo�^)8	\�$I��C31Z��Ja���;N�F��'����P��v'�;���\��=��h�����?���Y�*.��=���m��P���<g|$^>3�;���Z���&����P����h���r�i��]??3�J����q��rt���T���
�hfo�m�~U)%qla6�I�|��_]Z/6��=��,��7��+���������T�����V��D���
��vc���qoVq�>w��x\1V��?��N��D���
��jG�3�q�~�$I�rx&F��_3l��q���H����0X�
�h�f�$ILV����7V)�-�fr�?�����m���@��{��J����4py<wb$^6=�;����Xk�L�Cq�y���z��$py���TL�*��v������M��S@��.�4M����.������Jqla6J9eO7w��K�����)�\fk��h�l�W�`���q��T�����X�n����p�5��������U�
y��x<{��;?���N��DP�=��,��7U�D��r���$IY��z����v'�tr5�������)p��������@��*����t�������v����{�Y~q�Rp(����������O���n��Dp�)�\F;�Nlu��3�7���j9s��M������i����Q�����
B�{�j��f#�������76
�����e����<>Z.�X%{��#��n~2w���z��n�.�=����S��m�a����X�e���8���N��Pp(�\F�{�I�����Q+%���v'�|j��T���.�v7��V;s��������
�fr��o���[���@q�2Yi�F�3��W
������������N���nv�����e�h�f/'ILU�n7���j9s���q|q%�i^z���e��S���U��$���R-����l��F<���o,o�	����e�h�3����'��tp������ui=N��
L{Cq�2H�49����)�����#��Y�..�n�[l(�D�{���n'�i�9�q~��$qta&j�$s������Z+8\�=�� o�^D�l�R`�}�J���L���k[������%R������T���K0x��&G������;N���n��Dp��5p�m���WN��u�c�R����i�vb9�iZp*�p�{��RNqo^qr���8�0I�|q��/o�	.�����tb������gwx����������wZ&������v�Lq��Usqp$�wf�..�n7�$�@q`�5����G��-���s)%I[��j)����v��Sk�����q�=�W���W#I���&��x�����w�����&��������{���@{��h�`b4w~����jw
L�Gq`��i������Z��4���$�����J9s��v����H���dpv�{{h��y�����\�z�Gf"��?����W6��������m{�$b�V)8
���z�rv"w~��Z,5wLg����9���Z5JI�� �\^3?r��v��[�����
�)������\N�8?�$�c�Q�)����q����S@6�=�=��i4Z�{p�L�*������o�n��;&�l�{{d����n�9��W
N��ES��������'Wb��)0<���Yjfo���q�J�$��C31V��Jc����O�D�f����{{d9��7Y-G����J�\���gs��o5�������A�G����������{�X=^9;�;���Z4��
.'�=�=�W�S����5����Nq��r��i��@q`O4;��lw2g�{py��$�-�F9I2�+�v���Vp*P��y��"��r��U���S��o�l�c�;&�=�=�W���K1Vv���K���y�#���O��v�f\��E��r�{��J$IRp.I�����c4�,����'W"M���0���@����z��$0�F��8rx&w��f3\�*.CMq�u�i�����y�=(��#��������Wc��]�����p�VZ�Hsfs�{P����b�V��u��[�\�N7�77�
�=�K����SN"�s���Q.%qla6�I���j�=Kk��`�(�\�F3��7S�F)�i
��L��=0�;�e3��j��a��p���{s�j�I�{��X<g��;?��;�n��&�{� MS�=�AI��-�gb�����v�w�X�4MN�0P���N���7���+����J9n9<�;ds'���U\ ����%���1[�q��s�G���������b��.0�@q���&����]j@/�a~*fj��p�i�..G'������������3g���J)�c�QN��K�����z��h�{� o��\]qz�\���O�����On5L� S��H�N76�����������c�������tL��R��H�9��"��%I���z9����v7�xr%�4-8�Fq�"-����$�+.���U�q�����6v�{���` ���"5r�{s�j$IRp�|=ob$^6=�;����Xk�L��Q��H�V~q�m�=0��J����q��rt���T
�=���I�Xifo�Q���W)����l�#������z���{a���n�Lq��|�����������f���{a���y��DL�*�.�+f��Y���Y�W�����@6�=����)����QN���+I�8�0�R����v'�|r5�4-8�Lq�"������@������3���7���������.P������z��4�^�rb4^25�;����X�m��~��p�6��hu������N�T��9���q|q9�i�5�e�{�����3WS��~U-����l$9��;�q_c��L�'�=��h�f����Vvy���H-�������'�[&����-������� �fv"Fk��4"n]\�V�[l(�������7����$q��l�JI�|���/�Z-8�Dq�4;��hw2g��J�i��e�Z�7���?���o����p�[���"l��A����x��h��K'Wbc�]`"����h4��{�R��r�i������1Y�����q|q%�iZp*z���h4�������$I�i���Z*������-b��X�(4�Oq��m���WN��H-^=?�;���z��i��^��p��i�-�=F��N���Z�,��[�c��-6=Kq�<����M�g��{0�JIGf�ZJ2���������S����S���m���J�a��MT+��C�����m���L@�R�8Oy���z%�I��`�\59/����qr%6w;&�)������\�Zp`?���tLT���V7��'�#M��S�K��C��������Z�Gf#o���v+���Qh&z���y�lw����������h-^57�;�wi=N��
L@/Q�8�9��"�`X�jn2�d_t#���J�v����'(����Vvqo�R�z�%�R������$I�|u�w�Z+8��]�����q��=n��J���t��������v����{�!��W)8	�k^89/����qb5������������n���6�I���M�x��9ov�q���H���d��=�sXneo��P�~�^.������[����fq��W�{���lg����������z\;;�;�{i-��?��P�8���g��H���4@/{��d����M#n]\�v7-8ES�8����\�M���*%I]��JN�����N��
��)��E7Mc��]���)��4]��M�s��^��G7v
L@���b���N�=�q������rb$w~����nw
L@���������D�L�Rl�o$I7���J�W/;�n�vb%�4�/����"��7S�D����'�r)����?���V7L@Q��"��7W���G���5����O��r���������i��?�o|���c����J��������������6FFF������q�w�w���X[[�������+�
oxC<�����s���q�=���O>�N'�����k���n�)*����r��I�4�Z�����p�����'����Q����..��|�����00��z���r|�S������w|�s����O�>�Z�����������8v��%�����~|���O~���j��1O�$�;��G����}�4M���D��o�F|�;��|���|������`���_���=P��N7��n�lVq8O�$��3�?9�4}�|���{������������������Q,,,�{�����'?y��^D���n|�S��7�����w�3���.�����'��k��?��?�,�E�����/|!���7�?��H3n2<���������x�{��[p��XZZ�_��_�k��6����>O�`�'�G#c+���)�`�V��N������m����Iq�G|�+_�,����x�s��_}\{��1=�����������7�9666.���'�x�;bkk�������.����D�$OO�4~�7~#����_�y�������������k�Z��%/�W�����D������������7��	���W���c��2
�0/�������o?�;�N���\�q��fff�W~�W����t,//���>w�}w|��_�������?G�9�5w�yg��]�:�s<��C��w�;���S�^��W��>��8y�d�s�=�����<?��?{�k����������}�����q��w>��T*��>��X\\�|0����h4��O|"fgg�z��S���~����9���=����{s�J�I�A�$I�|x:Fs��v���\����������??>����O<�����x�[����g<�\.�������?����3f��������?^����>���O=~�k_���7��Mg<��/}i������q�|��n��y�o�����<�����?�����B[�V�w��]q�m�����S�����������{`���'�H�G����l���[�s���^���G>>�`��������s>�\.�o��o�
7�p���}�c�|���������Z���?������|~�$����������c=�P|��8����?�ggl������;��������������>�����nvq���=��v��X������\�+�G�3���;O��J�����^��������j��r����8���|������?�n������W_}�Y_322���8v�����r�����S��$�_��_;g�w���q��W>���?�a��_��Y_3��	���h�oa�W�.���S1[�d�:i�..G���
�������9r��������:�k�����g<~�{�{^��������F����+�x��������v�'��7���q�UW��<�R)���w�q�S���Y_3��	���hfo�������N�r)�c�QN���f;�]Z+6{Fq�����>����j��|������������x��p^�z�s�4�O����������v^���x���|��?��?�}� �'�_^qo�V�$������������o�l�[��W�����?��c���������v��o�1*��y����o>��;��|�t�_}����?��q����:� �'�_nq�^-8	0�^6=����o[\��N��D���>w�m�����+��Z����x���/��/�|O����������B�U����/|�y�k��������+��9�\�$�[��H9�+��N7�8�i���K����>������-oy�Y���������}����������~8���S�GGG�����\����_k�vtr���q�k��r9<�;ds'���U\ .��^��?��8~������w��5'O�<��s���:�W\q��S�N��y����9��f��AxO��F���$"fj�{��{��H\==�;����Xm�s����~��4�����q�mo{[�x��g}��������o
�������F���z�����z���^�����8y�dn�0�����g�X[[��,������>"�\of���bkc��4\
�y������^Z�x�\��N��v���?o��R��C:�M>��a�s&>��a�s6>��a�sox����@�R��C�n7~��~){����MOO�o��o���O����s���f��s��.�<Y�:��� ����������|��~��w��������t��w�w�9k�{I���3���>���������36>��P}4�/�(��1Ziw�}��1v��}���0l|���g0l|����0l|�
�Gyd�#���w�����?�'�����:�������s���s�vgg����Z�����2[D������'�\Y���s��{`������w��
�Js;�N>�;��V��M������g~��~+�����g��>?��?^����V�uA�o6����{q��s�m�����I+�H+��Y���\~����n�f�$6��*��r��� �����/��������3���]���~����3&&&�x��-r���!��?s/��u������z�=]�_��_��������}�{�������7�xc\}���������w�y�S�o�����D�[���c%�3��
�G����K�36>��v�������n����1n��G��6a������=`������=`�����������w`)���?��?�w�����?�c�g�g�c������������x��+�J���K=O�k���7��B:t(:tI?cbb"���.9�i||���������,��UJqpf��@�)�y�������"�Hu$��������v�L&��Sc���s6>��a�36>��a�s6>���^�+���~��>��������h��O{����G�r��~��^�=������?������<O���+��6��	������<>W��v����M���|r5�Z��9�Gq��}�+_����������?ox������Z���K_��3?��#���?�e/{Y�������T~��q{{;N�:uY�5��	����+��������TLW+��v�����M��Sp.�{=�������7�Flll<u�5�yM����y���_��|zQ�[������8����j�/|�/�\�f3~���:� �'��n�k�������*�R[������n|��^h&�Mq�G=�����7�9����:v��W�g>����������W����w�uW����~�w�q��w������>�=���f����z�����C�u�AxO���f�����2?R��L���kl���f���)�������S?�Sq�������/��~��q���K��/{�������y�������������$I�o��������>����w��?�o������A|O��Fs7�x%Ib�Z.8
�O\33��e���8���N��P�R��1O>�d����W���{��W\��������+��o}�[�x��������?��?������p�
��g?;��oy�[�R�<��_�B<����<O���{��{g���o��5���(^^qo�^�$I
N�I���������I6�������S�Gq��4�x���=��S�<���g�/x����=�y�����_�k<��g}���N|��=��{�����fnn.����=�8M���_��s����??���z|��W�O��O��5���(^��W��d(�x�7���?���m�\�{=b}}=��_��q���?ulff&����?q��W��������������Z�x�;�kkk��O�4�����w�����]u�U���������G>��O�3����?����>�[��V������>��E�V;�y�=P�n�F���������v��h�dj,w��S����}M@q�z�[��������8����?N�>�qA�[^^>��~��=��~r��]w�G��/|�g<�;��N����w�w~�w�8���~4��s�^������{��c��K�����������{���rK���<u��k��w����<���'�����N�f����r������3g��4�/�D7���bT�;?��rYD��?����Y������o|�Y����(~�w7~�1��w3�����x�����=�yq���x�������?���8�����w��o�M�{��q��wGDD����/�E��o�F��/�z�?�plll��������D�r~���{�8y������)���Z*������GOGV=��N+�kl���'�����7�~�~!���0FGG�8~������{��G}F��W�W�7�7/�<ccc���|&��_�+go�Z����}�������������>/y�K.�\���(F���y|�V�J))8
����ug)�}��'�[&�/S�r�x�;����f��/�bT�����=_���_��Ir��������g?��?��x��^t�����O���F�������D�{���+���m�z�5��0Z���q��r�:�bC����<}\�������?��������������wc}}=FFF�y�{^�|��q�W\�yJ�R��/�r��/�r|���{��7�|���t:1??�\sM�t�Mg-�
�{��R��M)I������9��3�W�hw�+�V����>�n�{<ejj*����r�W����l������jwb;g�\����&��x������r��{��q��H\59Zp2��V���m9g�^��{@�{��h��,��/�\���v��P���RNqo�\��J��4�u��c��}����q��Jt���T�Kqz�f����~Q-�����Hr�'�[����B33�=`�5r6�)����h-^=7�;�wi=N��
L0�����������{�`�vn"��2giD_\��n��PCHqj+���^���JIGf�ZJ2�k�������S�=`�-5w3�W�$&����\��j%^p:w�������v�����0��s�{��J���M5���Scq��h����+���)0�pQ��Z����z��${���c���A��M�����i�����0��i��v�lNq�s�r)�.�D��'�[����B3�=`h��v���eFq�G������������N��D�AqZ��n��$"fk�b�\&�����#����W���
`�)�C+��7U�D��2	�$���g��$����v�yz��T�����Z�)����7����Z%^h:w���V�pc��D�MqZy�f����\~/��L����8�[�N����0������t3g�u����$I���L�W���f���X�4MN0x�����m/"bNqP�r)����?���o�l`@)�C��jg-�b4g
� X�����������G87�=`(���n�0^3?r�{�i���������{�PR��Y)I���lT�$s��j����
N08��������jg���a1]��M�r��n���;&�{��Yn�F�3�W�������������'Vb��)0�`P��N���y��$1Y-�`�$I7���J�WD;�n�~b%�4���Eq:y���z%JIRp��U/�������c[�x`u��D�Oq:y���Z��$���c��fv<w~���X����������i4����\]q^��M�^u��[���MN���������v�}���0���$�-�D9I2���v���Vp*�����Fs7w6[�������q������V6�����'�=`�,�������\�tj,�;>�;���J��;&�?�N�J���9��"""I����t����6��t������i�����0T���^��$�k�R�#�gr��n���k[��3�{���iwb����)������x��x���Sk���G���04�v�Lq�������Z%s�I��uq9:���T�OqK���0#�R�U���}�R�f��d��v��X+6@P��F#��g�@��z5n80�;���f<��,0@�S�������zz,�3V�����;�n��z��0��4V[���|�Rp���$I�rx&F��_%mu�q���H���d�Iq
+�������=�s�����3��G6w��k[��a�{�Ph4w3���$��6��������������Z��r0L����hf�@>[�D)I
N��n803��?|�N�8���4o�1�pP��B����z��$��RJ���l�r�����n|ui��P=Fqxi�F��]��W��`s�j�0?�;�oy#��&�-�{��[���n7���*�\�����������'V�����w(������1W��`p$IG�D�����f�_<�i����0�����T����8��J9n9<�;���N|o}��@=��������7W��`�<ob$^:=�;����Xk�L������hf�(���7n<0��J����q��rt���T�Gqh;�nl�;�3�=��Q)����L�M�vv����B3�'�=`�5����y�=�=s`�������'��&�?�{�@�+���K1Zv)�����g��2giD_\�V�[l(�}�nu`������H���4�-I�8�0�R�u�F�_:�Zp*��)�-��W��`8�W�q�����������Vq����0���4VZ���\�Zp������x��X��K�Vc}7�:
`(�k��i�Lq�����TLU����n�W���]��7�=``-7�������Z��4��Z*����Hr�'wZq_c��LEQ��Rk7��l��$�r����Z\7?�;�Zc=Nn�
LP�=``5�����z��$�����8<Z���q��r�v������������@(%I=<�R�����N|��j��./�=` m�;��M3gs�J�i��D�o84�;���v|}��@���0����E���^09/�����Jl��Lp�(�)��7Y-G��`?�tp:&���Y���m'V��foM�'�Z�R3{[�m{��V.��������[����B3\�{�@�����������s���{����N��D{Oq8�N76����|Mq`�];7�Fj��4"�/.�n�[l(�=����m{6���R�����������n'�<�Vp*�������^�T�����^0Y���N�����?��.0��q�:0p��{s�J$I�V������jr4w��+����`o(�'��W-8	�����1Q)g���4n[\�4MNpi����I�Xi�3g��{=�V.���������v+���Yh&�K����V;�93�z���z\;7�;���Z,�doU�E�{�@i4�o�.%��J�i8_�����#�h��..G���'z��0P��{��j����4��R�����Q��f[�m����
Npq����W���goo�wL�*��C���W�����\�=``�iz��^��4\�M���'Fr���\��v��DNq��N��i���=���$I���L�U���jv�q���H���>�^�����m{s5�=�~Q/�������[����f��.��00�v���j9je�=�da���N���^Z��Y�p�~r;00�n��m�?�z~2�����i��������87�=``��rn�����$�.�F%I2�+�v�}z��T����f��N�Lq�M�*q����������N���Mq�9��""������^<5����~b%�s���~P�B��]������N�^J�$n><c����v:����J�iZp2�l�{�@h�l���W#I�����F��8�0�;l��^�*0@>�=` ,5��������p�<{�������:��9��H�{@���i���7�08�����z%s�I#n]\�N7-8�������jG����{��\J���l��$s��j�=Kk�8������m{�$b������5S����r���l���;&8������{3�j�&��K��������m'Vb��)0�O(�}o)��7g���J�$n94������;����j�iZp2�=���i��qo�^-8
E��������#�;���Vq���=��m�;��foQ�W�xW����g�s�w�Z��V�z�\����h�sg��{C������U2g�4�[W��f����Aq�k�f����J9�e�:��RJ���l���y���.�
j�f�Z^qo��=��2[��
�r��\��'��&�����-�=~����x�X=w~�����tL+�=�o�:�X��d���������$�[��H9�+��v7�xr%�4-80l�����m/"b��=��4Z)�-�gr�?�����mJ�{@�j4��{�R��r�i����M����rj5V[��Fq�[�f���s�j$IRpz�kL�L��9k�i_\�n��
�{@����7W���^S)%qla6J9��ts7���^l(`h(�}�����R� �\�7�O���[����f���a�����V;:i�Lq�{��x<{��;?���N��D�0P��R���m�3�J�a�YI����3Q/e
�����N�D���U����������L��$)8
�l�R��O������o�t�{@_���7W���~p��h�tj,w������j�d�{@�I�4���������S1]�d��i�O,G7MN"�=��l����v3g�{���Jqta&��S;����z��������Fs7w������u�����76��v��D� R���R+��7^)G������fv"�5Z���q|q%Z��
�����@�Y���g��#I�8rx6j�$s�����O��
$�{@�Y�)���+'�_�W�q�����C�����Vq��������n7�w;�?{w%�]�	�����K�%K�%o�$c�[�,�H�B2��$��a�ays �o�@�2	�N �%�nl6h�-[�f���{������jm������9uN�����S���]���������8��*����[�Q{o��O�#`����<��"�8uW��G]YI��x6����D6M���	�J�h��'e�$jKs_p
��e2q���H�����������,|�{���o�^sEY$I��� �������.o�g���>2V����NpXPf
�����T�+�s�����Hw�g��m
X���#���=�'�W.����$IlY����S���'��c��
X����wl"&�������6��S[V�Y�����8���!`����������h4q�Yp^]U����[��XO�O�#`!����������(�$��������--�Y��q�����yFA����t�N���\a����$��h�|��82<��
����B���5�{����mYUy<��.o�����+`G�B"�,�������	�067�������iD�v�;����Q��MpX:�L���`nd�$��h��L���7>����+`!���<������,qJ���++���5��?�7������w�������#����{������������������X�lY�Y�&��]]tQ����w����k�X��3, ��U������'�w���h�,��R�?OXW����+��������?����������������K��+�����%��� ***��[`.������$I��e
qld,&&���f���Hw�deK$I2��h�{{�������������]�vM�O���_kdd$���������/��/���2^���������_��(+s�?��l6����@:"����q�^EI&�Y��v�3r};uxx,v���������|7�t�������~�_�>>�����>i�N=�$9�GDL����p����K�������:+���0��y~�@>��yk&�P(+�*bss�`�O;��3��h`i)�����D��_�U�������&�����A����N�9_���+>��O��u���~��b�����<]W����2I������g4�E[e��Gd#����1���)�������4��|�+��~0���{\���5Ojkk�K/�46m�k���U�V�Yg����QUU���1<<����������??�����G���_L�y�1&&&��_�z|���_��_�|�q�y��_�'���������P�$�-������1������;>?����,k,|s@������w�����?�����"~�kkk����>��������b���gt�������~��rK���?�{����cONN����������x�;�������������|��+rO:��T_^W-k�;����?�;+�+cumea�Ff>��7�)�������S{�������-����=>_�����o~���""***���~|������+8��y�s"M�i�����������_w�q�8=�4���|��y����*��!�w�����,`G@1����W���i�i���W^_����������}.�����d�����:+~��~/������m[���A���N��4��-��2�}���O�d��f��%I�x����.�����d6�<�i��dX��%���4M�%/yI�z�����(���7Eee�;���K.�$����<���������u^����=m/���r�=�OEI&�,o�[?84��#�X�[p��k��{��'������-[����444��7�{�����QWW7�-���9:�sCyi�f�w��U]��j������f��5/��o��q����W\1�?)UUUq��7�c�=�_�|�KV����+L��8\�R-y�O�i�mG�c"��+`>�Kp�e/{�|�����������n��n�=�\I���+��4�=�gl"~��W����4/�=��141�����|M`>4���m�y������v�'�=�hu����\^Z�N��.����5�y�w�����v��=�h��U�f���������$��-o����_��Lf���=��i�;
Mp(Z��{��e�NNeI&�Y���~`h4�*`G�|��V��D����{���+������w�FO��T�C�|70������7�����uk���F[[[\z����7�1�����n�c<��������=���-�qxx4��(&����t���i��L2�s���{�����/y��7��MQYY9������u�{]��?���4M#"��G����+>���������g?���s�<p���L���h����d��vES�����L��w�M�O;������7��������[��mo�$y����]vY��������������%q�}�M�""�$�����~5<���w��L�I��x���I�e%�N]cyY\��?j��Y��3+�+be��7���|7p"��O��������������?��{oD<�{����q���rK�x��s����5�;��\Q:��bwaCu�SS��~�����,`G@!}p��;���8?I�x�+^1�������'>1���4M���9����X�z�T����g>����g���	������\aJ.G�$��e�QU��k���l�u�w��*`q(��^GG��@���^��-��9���7���+"~1��O��O����q��w��={�[��V���L=g||<>�����;NG6M�{t"gMp�����$�^����p$�*\C��+�����>:�s�$q�����9���O���$���������72�_��W������|fjM��S��_��dL��8"��B���264������=c��NOQ����7m{��
3���o�=�$������9����o���WO;������[`�t���`9���r�=��[����4gm2M��#=1����R�������xbz^DDKK���������>�����xF��I��K_��������m�v���<�����(�$9kP�J3I<ES��9���:��0'�:�7444m���~��w�}���I����_?��K.�d�����O�C`.��5W�����TQ�j������8<4Z����P�������ONN����?�qD�bB��-[f\�l���x"������P���K�	���jbeuE���G�ct2[����V������i�}}}3����;�BxW_}������O�y��?���&&c8�E�&��$IW/o����_�
Md��c=S7����566F�/&�=��cy�n��=�;6��v��hkk���{{{#�������]`t���!���Q]ZW/k�[�70����0��:�w�L����;������5�s�$���=������=m����;f[W��^UI&�JK
�
��sj+������{�{�wl������{�6m�L���4���G����nrr2���/F�$S���������_k��U��5p&�Fs_�l����[���4gm"M��#�����������{���q���F���$Id��x���===������I���wj���4^������x��H�dj{��u��:p�:�rO�k�`*�$q����$�����@ga��X��y�7��Mq�-�DDD�$����4.�����_��hii�;��3�����i{I����_���3�n___l��uj���Zp��D6}c&����T���-������������"VTU�3�t}p�7~�7�S��Tl��=""�4�������??������������u���o���x$II�������d�z!,z�c���	���]�X�F���h���Gz��������W���>�L&����DCCCD�T�.M�H�tj�����w���_~����7�1�W_}�l��������K�$��J
�
N�$q�����sc�������������V�������7�~�������=u��o{|�c;��=����/��/��_��4��|������<��6,F��%���
y�{�����v����n�d]~������<�����?��?�������?ZZZ��+�����-q�����k��_�ELNNNm����s����j8I�y�{�e��������~4��Y���7�W�G]���Z��u�Oyyy���o�7���g�:�'7�x��vii���{@��i��9k�{,%W��������<�6�M��#���U��R@��w����&�555��,y}��1��9k-�{,!e�L\��)�w�#���������%��O��x��ID4�/�!�p�Z+���-uy�?����c�8�{@Q���/+���S���M����<g-����t��d��M'�U�@Q��k�(+p'P�$�k�7Ey&�Y���{�{�p2����?�WZ�N�x������5��?�?���
�pR��y7<1C�����X����������t�7�'
�p"r��=�����w������;wFOOO�������_��$�=8}���ED4�@\�VG�G�|���X6�����KW�D&I��;��Tp���F��}��Gydj_����0��r���J2QUZR�n���e2q�����������#c��{ .m�+xo��Dpobb"~��=���o�Kf�.��0��M�3m~���<.k���;�s������+������O���N��_����7�i�F�$�i����_�{pr65���<��4"n;���la��S�����/�����L���d�n��Uq�e�����uuuQV��~Xh&�i��M��	��t�$�-+����1�=��T���qo{o\��i��T���}�CS??�{��_�����+�����Y�36���6W��
\mYi<gYc�v�;g����XY]k��
����|70�m����={"I�H�4�$�n�!����	��"�5:�sI�D}���r^]U��!�w����,`G�Sup�g?����s�=7>��O�O3�����k�(�L��X8�jk�������lw��l�o�50��:�w������$�_��_����y��m]�9�7���3)/���+�"��.��������<���{�l6""���3��_<���,M���;qOpNdYUy\�\��~gt���# ���{�����+**��`.��O����NpN�����V���9����t��� (���m��1""�$���c���g;�,�7m/"���������I��vES�e�����������]��V����/�<ZZZ�����c7�l����/+��LQ��@Q�++�������}������"���$���7E����i|�����>w���{,wp�����������*����[��hOML�#X��:�����'���#I�����|���0K�M�k��S�$I\��!jJKr�G�i�q�;�4-pg��}p���-��o�6�$���?��?���������3529C��5���T�db���H��
�������KQ��""^��W�����;JJJ"M�����7�7�����p��F'���������MM�y�?���;�������z�[���{n���o�C�����������x��_�\sM�_�>�������/���e�,v��+����%��*Y���uYK]�����4��#���sZ�4�����	�ED<���������� �;�o��o�o��og��I���D��?����k�(�$I
�
,.�$�kW4����c"M����M��;��9��,�������g<#���#I�H�$�4��P8�y�{��P���K�������{�����vK���2�����������O����3y����&�i����t�\^V�n`�Z__�Fbo�����z���mQ]ZR��`q+��{###����,z��H�tj�^D��T��x��
�R!��%I�x����.��5��d6�<��;2�eE?q���h���c�d�4M���)^����e�]k������(+s�?,]�����$��EzJEI&�,o�;���~ph4��
������2~ll,>���N��WZZ�����xG����s���������,2O	��������T��r���+�*��l���n`&��{otv>q'�4M#I�����y�{��`��s�0���Z��%�9�dq�������
���m��}��$I��+����������3��it�	�@��$I\��)J�L�����t��+X��:����O\���W�b>�f���d����!�s���4�h��[�g0��#X��:�WQQ1m��s���F�Y�9�{�^DDsEi;������X]S��~�����,`G��upo�������<u���<�����(���	,
I����7DUI�����l�u�'�4��l������K/�4"���("���C��0���+�
�	,]�%%q������Gcg�P��E���{7n�s�9gj�?��?��`6t�N��/�����2.i��[���7z��x�YQ�""n���H�4�4��������w�wK�i�����d�����-��\^��6�F�v�;&�i�������{����8���#I�������l6;�m��k�i�{Px%�$�]�%I�z��D�����M�"P�������������!�4������7�1�����5���U�d����OK`Qj�(�g�6�����CC���q���_w�qG�Y�&�4�����.�,���!&''��=�$u�	����F���������������t��������w'��}h��_��_���������x��G�
oxC��mo����*��_MMMQVVv��z���?-y����\q����3�$I<oYc���=�'����'�q���x�YMn�'���{�������4M���/~���~��3>�����l=c9k�{0��JK������C]9��G���������������NV���O��$9�v:`n��MD����{PV�T�����y���Eo�r��`�{O���|�T;�0��F�s�/I"��~0,�j���<��i���I7��-���lL�3m�W�X��^cyYd��h�f��vES��9M��:��,0E?�&���w�,��3q������'�\Q�j��{��r��u����8�������� &�[���%���
5�r�`��G�ct�M� �=`�
LL�X6�Yk�(���$%IW/o����_!Md��c=�����`)��\�i{M�&�@��.-�k�5����]}��k�=`������Dy��@q8��2.j��[���7��&
�?W�s�k4�E�����B����h(/�Y�H���Hwd���]@���\��{�{�0�f2q����_&v�������3�=`N�Nfc`b2g��\p�������>o}k�@-`GP��%����}o>{Z����'?��|�V�i{&��BsIcM�]U���F��Gzbt2[����Kp��������%����|>RFGG�c�X�[�.��_�u���+_p�"�DM�����$I��h��L��>81?:�i��3(.�v���������U�zUQM��O|�q�y��{���������`A��k�(�$�}�/P��KK�y���������5Eh^��d��������+����E��o}+&''���]�v�����X�zu��������38������=`aZS[�W�����7��'
��y	�����Z�i:5e'M����[�5�yM�s�9����7~����y]]]�������0.�����'?����z;���������^`1�L���}���,lW��G}YI��x6���tG���X��%����}-n���������9r$>����W\��w^���A|�������3>n6��{��7>�����^��X�bE��o�v�z������^JJJ���|g���3����3>6,E�c��S����,��kW4E���>2?�(hOP,J����^{m���?�/|������o8p`Z�/"b������}.>���ED����c����q��X�fM�\�2V�X555QUU%%%122����������;c��m�������TO'I�H�dj�u�{]|�����?���$��t�����I"���4�%��������ig���������X^U^��`~���%%%�;��;��7�9>�����?��i��_��""�������o���|���N�/�zO�2�L��/�r�����K/��4��T]y�{M�e�I�����M�qph4��WK#��#����mQ^�)|s0O��j�������������+_�J\~����i�i:�{�T��y�{�����������sg|�����Y�/��\QV�N���I��fyS�gr��c`b2�i�-pW0��"������x����w_l��-���w��U�f������QVV�_}|�k_��G��g>��X�n�|�}XT�4�!�7�C�YV[V�]����X�p��.\C0�����K.�$>�����?����m[|�����n�-~��GGG�)�VYYYl��1�����/�����^����������������9k&������*���}�z?:��*����h���Y� ����iSl��)���wED������G��{������/���brr2������&�-[k�����;/.��������wKK��D�Zs��,FW�5������<�6�M��#=��U-�I�y�
gA��n����z���n�A��x����%Q^�)p7@!�e2q�������k�������=�6��7($W�s�3Op����=X��*��-��yt�G��X;����D��{-�{P���$��#Ms�}`�mn�����9kiD�v�;����6T:�
���d6&&s�L�c�


EGGG���@,[�l��s���������hmm����y�`��$IlY�7�o����7O���{�������o
@p�u�c���ED4W8�`ntww��C����?��l6}}}��������8���������,
�e���e
q�����G��bUuE�[WU���2����t����g��)-)p7,v����������;g�����;w��G}4���N8=��U���yw�������`!�f]��^sEY$IR�nX�c������yF����[�n����Y��']���yn�1�M�����M�wsKp�u��9�7W������x��gmR���x���Cx`���db����w�#�c��{��=�\�fU6M�g,��=�
���������������d<��C��	����������;��cd�����fU��Dd����=f���{�,\7>>{�����X�.m�����d#��#=1���)�#�{������DDCyia�aQ�������9=Fgggtww��1��L���+��,�����O�}�}�
���0���+J�$�}�.��C�-��,%ue�qU[C��#}C�o`�����fU��^syY�;a1��������?���
r,��d]]U����[��hoML�#�}�{��I�4p�Bp�3�������$I�Y�5�%9���l�q�'�4-pg0{��Y38���l��k[��=���`A��TT�db�����CC��`�s1.�=`�����$��J���A����^�������T���������o(f�{�����--�����������,�1��lA�	��\�R�yn��M#n;���X�\A�������f����5�Np`�d�$��h��$�Y���w��+8s�{���7q�������%y.��k��Sf���P^W�5��?�;���#8s�Bf��d6��'s�L�c6���DIII��)�0�����5��y�w�����o@1r20+��rO���cv$I555=fmm��M�XJ�$��-k����_W�Lf���=��i�;��#���������3I��vJ�WmmmA�W�� �RVQ��-������C���N��0+�FsO�k�(3��Y���������U]�����'}���o(&�{���)�����:���
r�$I"M���_xfK]���;b2���HwLd��P�J���y�^0g�]RR����������q�����+b��
svLX��i=cy�{��{����>;v��9��I�4�o��W��+V�	P %I[V4�?����7R����v���m
�������z���H���5~��~+��������zlX�z�&b2����mMMM������s~�4Mc��}����������9?&��eqe[}�}�7g����XY]��NVf�8Ui���8��3�ioo��~��q����G?��B�EXp�FsO�K"������t���FYY�B�����m�����)�1����cuMe���G{b4��"0�Lp����$I�>fk]��1>>7�xc\��1111o��]��^cyi�d
;9�����,.���()))�1�������}��E6�-�q��$I�y���$�W�����i�H��P��~��-["I~q��}��###S�O��*++��s����������������C�M�}��\|���l���������8r�HtuuM�{rm�����?n��������9}��P��5Wn"KOuuu\r�%��C��x��OEYYYTWWGoo���>}}}q���Gee�	0������fyc|�PW������nj����w3+��{��zk�r�-��o}+���bxx8"��]p����|$�m�����s��������;������q�������o������>����&�9r$n������;b�������<�H|�S��5k
�IDAT�L����i|�_��|�;��OE)M���=��Ep�9V]]�7o����3z������ys\t�Eq�y�E&3�i���`l��5��] 0�V�T�%�5y�C�W�d�*P\�>����W_}u|�;��$I���:>�����>�~����K.������mnn����e�����}��x�^�������>>���N�]�~}����?b��������S���'B	��:�o���l�Nfs�L��JKK�������������������H�$�-[�6m:a0���c�=�v������Uf��-��T^��������"M��63X�����5���F��Q[[���w����#9��q��[�����u�{]D<�{�������>m]YYY|������������q������O:;o
�����5�=
ahhhj*��=�|1��DCCC�}���y�����K������UUU�������:��;::b��m100pzo�*�$q���(��u�dUM��,lS0���}��_�[o�5"������x\}����z%%%��/9��[I�D6�=n���>�����U������[N��������DEI��j�������[�.�;6�������/���W�p�^&��5k���^��y���������cG:t����0����xvkC��H�Yqt�$d�C�_M��O}j���k��������kVTT���O]T��c��M7�t����������iS�����3>>,&��{��Q�l6:::r�������<�4�z�����������ys44��H<��i������~8���N�8��E
����"o�'}�12�-`G�[Q����?���"I�H�$^��W��k�����������o�����^���M���i<��c��,�y�{3O(�������������q������.���W�0����[�n����Y;>OH�$�^��y�{�d���h�)��������?�������/���nll�e��M����z��7FUU��vWW����x6���9k&�Q���9�g2�hnn��c%Ig�}v\r�%QQ��KD���D���3������/����$�Y����p$�*\C�CQ����?m{�/�njj�������&I�hmm��69~�k4������=����D�s����())������������#�s�����}{�I/K�������&o��������
����

M�3vGG���~gg���3]L]__?�������������2I���Mh
����������mN�]RR����u��E&3�)���Pl��-�;�\`=��>�Ks��M�i�v�;&�0OJ����<9�$I�����}���v{{{;vlj���%��������g����������/8ccc���]tQ<�������Y;���H�}�����Gwww�����U���+����;o��Q��Pl������~�\�wS����i7^�KmmmQWW�>�h�]��fc������k������>
XJ3I\Q_?���q3����x��?��Z�sCx���b������9M��������������'�|���4M�Bg�uV��]]]S?755���O��������{��7������O~���S�5k����{O���4H�g��8��sO�y7�tS|������?g���6���������L�6OG{{{|���/}�Ky/������}�{_����<��D�=������w�R3<<9k���
�VVV�%�\�?�x>|x�����100�������u�x5��D��1�bu�����XY]gUW�3���oE]D�����<�n���O~��g��}}}��8�$�
�=��������c���O���Ys��������W��U�r��X�jU��U��?��?�[n�eZho��7����+��+yn������
6����~Z����[c��
���~v��7?��O������o~s�����q
���U6M�{Lp����������V�N���db��5q�EEY���������;������i�:X�*��F�@o���G�ct2[�����{mmmq�5�L���4�����q��7��k�����^��8r�����y�kr����m����}�����������Csv�B�f���������}m�����X�vm<������i���������G?��)��;�����e���1mccc\v�eq���7��������~��N���B�'�b�76�y>>�+�z�/\�����RmmmTUU��_hll���7w.����?=��i�D�_H"����H&r�Xdh"w�q�
���{�������$����x��^7�xc�����k�{�����<'n���i��.������ks>�_��_#"�.�����N�������9y���7�~��Sz�X���_����qA����m�����{w<�������O��W��Z344�{����7�������;~�W5������Y�&n����������?���{����������O��O��O���@���}Ql��&�1w������Z[[���������.�5k�D�$3������[�Fwww��X�2�Qsho�������?�����������W��������$I$I������~4��o�&^�����^��x�3���/��������cG�s�=����q��wFDL�""2�L��_�U�cg������5�����e���'������_�~����+��g?���g������f�XMMM���h�_7"���3��O�t���|�#����g��L&��+�W\qE\}���w����8p�@|�S��~��'<��?��i�
��]w�yg�}�����Z�*����*V�^7�x���}�C��������T4�	��u���5��Fif����������$)��^���u�YQ__�>���7������;w��+b�������5�R�@O�WU��'r��9��+������`XW����ml��i*<�d����3>�����_��8������j����������g>��q�
7��w�i�N���4�L&���|�3s���o�Lw��
�n��9{���K�;v��������[�c�X��5��5k���1���>���������eK������~��������������ttvv�x���������i�>����{������B������O|b��D�=,]��/�m�0m��399]]]9kMMMQZZ\a�����M������k�9��o�6A�S���"�r�N�i�~�;���]���knn�������/�|Zx��������8v�X8p z{{#��N�?�9eee�����[��[y�[VV��G����'��}�[�.6l��(��d�����8m�>���I�����/�k��fj���?���������������-[��_����$I������}��;��W.�|O�.M���=q�Yp�9����l6g�d�q����$��[��������

��m����c3���[i���+��~��>2?���S���`b---q�=��>��(++;.�w2�'|�|�3�'?�I��o����|��_�~��������B��E������������;/������s���o��o�����|��3>?����.��];�}������{��/�{(v�������c.=�w�S���FCCC��95����i������q]6����w���>�'[�_KeY<��>o}k�@-`G,E&����������k�����c����&�����x�K^7�tS�w�}�i��y~7��w���i�/~��O8���k���[o�����k���o���d�I���^��i����o�]_�������\QZ�NXJFGG���/g���uAL-����
6��g�}��]]]�u����7�Tml�����s�����HO���	��ye��U����p|�C��z(������m[tvvFwww���FCCC455�9��W\qE\y�����8��/?����m?���=���}��q������{#"bll,|��x���}��;v���/�#k���+V���������?���}?U���B�/�W]�����w�R��������V�N�L&����WGCCC���k���������;b��U�r����i�R�$I\��)n�w,F��q�������7�]�4��,�����$�
6��
�������q�������hmm���:��_�����}��7��a�T�����r�����z�}��yOAg��^KEY�;a�H�4���s����������������ys<��c���3��Dooo�_�>***
� �WSZ�[��q�;g}w�p����u��\�����{��m���y��{��9��b�����k�-oyK���/=������O�w�9��R_O_�s�������L��o������i����|����#122������`'������^G��}��E�?
�I���S�n����`�ZS[���#}C9�?j��eU�QW�kRfWf�`~uuu��ED9r$���1����x�3���m;������v�yYYY,[����Z�r���c���\����V�:��,_�<JKqaV6��������=��l6��'s�����yk����d�%I+V���7w�������Gy$����l�@,lW��G}YI��x6���tGv�(��p+iN�<W^ye|��_�����3���]]]}�Spjjjf|�|����I�$�������c�=��c��E{{�)=g��]�����7+�P�g�������(�������te�����jkkcdd$�4����w�����#G���g�uG�����X�r�	�~����>����~�=��<n��\��c#�����qqm�t0���K��<`���,5>�������5[�������/���E/zQl��9V�Zuuu100����;��#>�������������X�|yl��%�k?��t.&�����5g�X�����t�>����?��3z����/�92+����w�}���HS[�Y�_������-N-�'VQQ���9k��{��_k�|�UTTD}}}d2�d����c�=���1<<\����d�|����>�*[V���sr�����,���?�����������{�R�sXj|�-������y$��}��_�����Q^~�]����16o���{���o��ctt4""�������c��]y�kO�x��8'RQQ1m;����:V!�@�������ttHh�9���������9�b3::������0�yG�$Q__������i�k���Gb��!&j��/&I�</v��$�-|s,:>�w����������?���i��b��7�������o����x�k_���h�������~6���w�|��}ccc����/��,��
����DE��^��P�;a)H�$op�����&��Fwww���DMMM$I�hleee�����91�b�DD��=����HK��Z4[^�+�D��=�o�Eg��>_���{��^��g?����Yy�$IbbbbV^k�y��^���_�����}�+_�������}:�?}��_���*�{:U7�pC����=�����+~��yj��+���/�xV���
�}��7�}�WDMM�<v�B��i�|l0g��5�c���
��]ggg=z4gm��
Q]�;H�����788��|���$������5���f���b��8Y���w`d"������Xck�_�2��,��>f��=`)��,5>���������[�z���n�G&�744�y�{�����brr2"�P�|�;���n�G�������������H���.�
9�����w"i��Vpo.���Z�lY,[���^���6���g������������d���]�X���'�����wo���|��S�-������hmm���wGww��k;::btt4��_�(V�s�t��������lw���Y�Y�X�ij�����)��9���y�R�sXj|�K����c����|7p2����Y�zV|�������H�t*45Nl��M��ai��#�<�smkk������8v��)��������������t��G�N�\��d�����u�|O��k4���$"�M�`v


���P��R�(WVV\pA�{��'|�����u�����,Pw�U����$gm,���G{"��a����MLL�K_��x�����=�;�'g��U�����s�������WO����S:���_t�E9�]x���z�5k�Dee�q�
���Y��x��
��Q�YZ!*�^�s����_
�$�+V��M����j��������������&V���L&�,o�|��m��	���t�8������x`�T�4M���2^����W\�������(+3�g.=��w|<wx#��P��}���|��x���}��z����{�|�y�|���q*�y�V��P����+�fv�i9kuuu9��KIuuul��1���w�)�������X�~}����C�����<��\t���?��gWWD[ey�;`1(���'>��������~��;>���FSS�|���9rd�v[[[���x�3�{������w�o~��O�8���{�Nm�����
r����K���l*D�w��8|�p�u�Y'u��������)�{(f�{JOOO���t������y�������c��8Uoxx8�o�k������O�)�R���6
������jiD�v�;^��-�2��7��V�W����sj�Y���$I��=�������+�L�6q�9��]����|��������|�����}�u�Emmm��uuu�e��i�~����q�4��������/�R���zO�jhb2�'�9k��E/�|��2�L477�������7o������i{���Gyd���KI&I���Q��}c���������]�up�������v�����>4O�,m_���m�s�9q����]���>7Z[[��w����z�i���|���_��W���|n�����g��������+������	����a��kbb"���r������TP��***b��
�j��������[�Fooo:(~ue�������G��bo�p;`1(��^{{���I���_�jj���z(>��ON������3>'���[���i�>���pB������w�1�]WW�{��f|��_������������?��?f|N����~p�������L&��$
���Q��^uI&�JK
�
�Yggg���mmm�f�H�$V�Z6l���������C=����l6�$M��d]}u�WW��~����,`G,tE�����p���/��v����g��O:���N�9/}�K���j_UUU��=�9�s���wGmm���m���g�w�����~����{���>m�].��-���������~�����Cy����|$n����������?���Q��P��F'r�7m������sYYY44�������c������|����|0FFF
�@q{N[C���)�X6���v��N����=���������+~�����O:m���H�u?�������===��w�#V�^��;����ws^��il��-����q�UW������?�����g�}������G4m�{�����������l�t�M���>7���;������w���'<ND�����X�b����={���}n��?����8o{����o���o���.n/�{(6�&�	�1�FFF��0��Z[[#I�w�0�������k���q�p�7���m[��$�RQ^��-+#�������3X��X�J�������Sh/������7��}�N��������8g��o~s|�K_���������?����#"b������uuu100������}�;�o��O�F���������������������������5k�DCCC���'zzz�=���*����Gcc�I���9���1^���LM���o_��������X�vm�������crrr�s_��W�����?E����x6��&�1���������
����$I,_�<���b��]3N]����]�vEooo�{��QR�{��b���".m���u
�����gU�Gkey�;`�)��{W]uU���"�m��y�f�:z�h���#������}{��^}}}|��_�O|�����L&���������~�������{w<����ZZZ�_��_�y�{�)k��-���|���y===����={������z��?��)M�)�{(=c�C{�{��4M������&������P]]7n�����pm{{{l��-M���K����2��9����HO�g��m
����{����K��K��i�i���w"M��nk���iS����Y���/=.���E]���b�����7����[YY�������7��x�3������n�!|��x���Z�z�^>�`�������_v�e��o~3����EEE�)���	�t����_�$Q_f2����?FGGs�L�;3�L&��]\pA���<t{dd$�o��v�
,I�$�-���4���z�'���}�
��f��v����������#�����?_�������:�m���{���k��������x�������G}4������1<<������g�uV\y�����2k���_�~��c��]q������cll,���/��=�yQYYy��Y�|y|�s��O~��q��w�C====Q^^+W��+��2��_?��p�	`�u�	�5W����R�I{{{��I���9�R�������k������y���o������u��M��
�����s�5�G{r�w�
����XS[U��X0�>�w����{�����?��H�$���w�W\7n����5k���5k
~�����Zpn&UUU���0^�����
���K���0�crr2���r��fQyyy\|��q���x���g\���[�n����GCCC�:(������H��Y��ho�U�Gu�)�/3�
�����������i����u�]���w��-X�i��9k�{���������Ykkk+p7�_�$�r�����K���|�������C����#���C���$I<gYc��	��f�q���H�����,��^D�W���x�{�I�Dggg�����������C��w{�h��O�D�Q��-���9����Fccca�YB���b������r����;v��H��3�QEI&�,o�[?44��!���n�D�;��i�eee1>>i��m����v[DDTVVFsss���^� I�x�����_Xl�F�s�O"����O%X������7g���%2�s�����4��_


�w����
��m�b������Z�.�������T[�r���gUW��	����{���$I"M�H�dj����4<<<��<���_���//�R�*fAGGG�Z[[[;Y��$�e��E]]]<���144�w���d���+zzzb���QRRR�N��e-uqhh4:r�}�M#n;��tN[�f|�������uI�����3Op���4	�\�������VUU555�hi�����7��+N����#�m��'�,&�$�-+��4�w�=c����w@1[��4M����o�^sE��e��������V7Y��L&�=�������t��������;���C���E���4�l��[�w0)`G������o~�|�K���dOfs��+L���utt����������)6o��v������c�4����Gooo�[�.����%@a�__Gc_����G{��W�EUiI�;��}p��_��|�KV�i{�{��l6�7�������+//��/�8:�q�^oool��-��[����k���$��-o����bh�����Lf���=����M�X�2��P����J2&Hp�zzzbbb"g�����$I�\�2.����)�������}��E6�{Z'�BWQ��k�7����z�
��Hp��k4w���=fC{{{���L&����
'R[[�6m�����=|�p���#����@��]]�j�����3L0`�����}���gj||<zzzr�ZZZ���D�bTZZ����u��E&3������m��hoo�4M�!@�<��>��F�i�mG�c"�<`��r����;f�s���3o�������p*�$������iS����2��f����]�v��D�����$I���Q�$9��c����w@��r��|�!Z�8C���9����G}}}���tTUU�%�\g�u�	�vvv��m������NcyY\��������888R��(�{@N]��9��&I���������Ykkk�$���O&��5k��E]ee3zGGG��������]X_��T���q�'F&&��@p�)_p���42�U��|��""Z[[�	����16m�


3�K�4��x���cll�@���$I��e
QU������l�y�������8����s�_�z�I����KU��^s��S�`&i�FGGG�ZmmmTUU�#fKyyy\t�Eq���x���g�0���7�n��������v	07*KK������C]9�������������0_�%�w���F��I=I�����I����KQ���5�����g���/������w�lK�$�>������]�v���H���s��X�bE�^�:2����meMe\�X;zs��������X�o*��`���M�������������������E���������$����w�\����M�6Ekk�	�9r$�o�����`n=��>��s�+m2M��#�1��=$�R0o��$I���v.�t]��ykM�2��E`rr2���r�������[�IIII�_�>��_%%%3��m����c��PX�J3I\��)J�|��5:�w��)�EQL�;��&�����k(+�����>��uvvF6��Ykkk+p7Jkkkl��)jjjf\��fc����k�����(Pw����,�������{0
��#����5���8'k���/��l�g���#�����hll,l3Teee\r�%q���8t���k;;;���?�?�����+P������888���8��\�,*K�`��������7��Z`vt�������������Ykmm�$I
����db�������v������3ccc�c��8��s��������$IW/o��������S��&�q���x�YM�u)�t�������/,��������Dp�����!6o�|RS��x���blll��eU�%q�������#�h�P�����i��&���8i��
�UWWGMMM�;b������^k��9��������uktuu�;��sNMe\���|�������o0.�=`�������J2Q]ZR�nXbdd$g������P,�$���:+6n����3�����Gy$����l�����Y���X^��6��q����L�w�\�����3m����������R�N(F555�i���
q=z4�o�CCC�`v�f��vESd����u��)���0���)��Fggg�Zccc����#�QIII�[�.��_%%3O��������G#5�X �+��Y-�y�[����h;`�	�S&�i��M��5W����������Y;�	k,-����i������q]6��={����>�?������8��"o���=1:�-`G�%�=`J��x��_e�����=�����hjj*p7,����a��X�r�	�vuu���[�������$I����QQ��+������X��������g������c���������1>>~���$I|�_��`������$I��l��60O������'g���%2�� �L&��sN�����]�f<��|0V�Z+W��$I
�)���.-���5����Y�;0�������w�l[PW������>�������<����n���{]�9�7��FF�S��������V�NX�b����{������q�����7��_��������cg�P��=�zcyey��/��nx�3��_��_���/�?��?��;wF����~!������w�b����seee�������������s�=�4������uktu��`P,�h���<S�'�4n?�Y�],h"����~5^��W��C������xB���5�;��"��)����DZ[[��qJ�$�+V������j�������#�����crr�@���L&��h���l��x�����=0�r����<����_������ix?uZ^]]]���EY�P���������`��*��������v�bRSS7n�}����c�f\{���������??����!��k�,�g���O:�r��v
����X^UQ���
E�{�;�S��4M���"~�73^����e�]MMM��%,|]����ED4U�)E$M�����Y�����
s�JJJ��������N��m����5kb���&=EgccM���c������HO�ru[�����@�*���;;;��?�a$Ii�F�$q���w���8�����=XT��r���J�,�"QN^OOO������������X���Dmmm���+�����K�4������q�y���
�$I��Mq��c1�c���d���7�]��eMQ_��m�M��QQQ!�s$����
!NM{{{���L&ZZZ
�
�YEEEl��!V�\y������m�����+@g'���$���1o}w�p<�7T���E�;|����I��k^��=�#��{���������Yknn����w�b�$I�s�9�a��(//�q���X<�������G�?�`��[W��W�����7��'
�g���{ON�x������z>��Ekd2C��5�=NEggg�@T[[[��a)������7GSS�	�<x0v��###���\�V�e�ot1�M��#=�u�����{uuu�������X���L���h�������_^^���������4.���X�vm$I2�������m[tvv�;���e2�eES�;�962[�
�����{��������3?��"�/�WY�����>]����@��[[[O����$I,_�<6m�UUU3�����G}4v������ ����xfK]��������X;�t���W\qE���L]������sG�8��5W�	[q�:::�����
�	DTWW��M�b���'\{�����m[�3��ml���U�9kiD�~�;�&��m
�SV������x��^i�F����o{�[�E)p�����P�i���9k555'�|s!�����k��.������������������i�:8^&Ib���(����J��d���[��8UE�����?����H�$~������y���l=c9k��e������/���r�L�c�577�������n�ui���}�b���1>�;�P�e���e�y����cw�p���}p��k�����mSS/n�����{�<w�G��x��-�R!��������?I�hii)p7p������aC�Z���k{zzb�����k�
0��U������t�'�s����W�����?��?�������i�����-[��[o���`Q��}�gIQ_^Z�nX�&''���3g���1��@)I���U���K.���������C=����l6[�����!��Jr���i�q�'�i�[�0�Dp���,n����o���E��q���x�_�_}�������#��",X]��9�7��E&I
�
QWWW�`S[[[���������7Gss�	�:t(|��)@g���db������������=P��89f�NYYY|�������e����5:::����~|���������hjj:��.I��c�=6�-���5�;��\aJ'���#�����hll,l3p�JKK����������w��S�b��m�v��hmm-`������u�@W�����qVuE�U�<Q��Z0�������'�7�7���I�D��S����:��NL`	J�4��=�=N���h��������F&� <�D%I��-����x��Gg�{brr2v�����q���FIII;�����qph4���WK#��#����mQ���h,�+9����8��������i�F���$��<`�����l���\������|��"�d2������qc�X���k���c��m188X����I����1�2���������
�3Y��w�����|$�����^DL����KU�i{&�qbi�F{{{�ZUUU����#8}�L&�=�������t�����Hl��=>��	�`��J�9m
y���
����v�L�~��w�����������^DDEEE\x���f�������28��{ue%Q�Y�~����`���������l������7o�]�vE__��5i���}����'��[����X���W������'�w���h�,����w��}p�}�{���O�6n������/yTVV�Wk��u�N���b�'!��������v����<.���8t�P<���3�����m����u�����0
K�s����XLLW��q���x��7��gE=J��G����?�$�4M#I�x��_����5���3�o�^��'��f���3g�����1�$Ib���q�%�DEE��k�������}��E6�-P��RU^��-+#_,���Xl�,hO���{��w����������(--�A�P�F'�1�cBC��'����'6�����;uuu�i��hii9������;bdd��K������\��~G_t���Q�Q���#G�L��$I��u������'/������r�=f����sIII455��[����?{�$������������� �I�f����R���������rW�T\G���H�q9���\���Eb;����*Wb;qdY��D�D�.�]����B n@=�������fi�{�/�������U����a�=3<�~���3q���(���jee%.]������������d�������E�6`�]���{�����iDD|��}�n��}%���]*E_eO��.�����������X���bA�$�C����D���m{��n����7n���L	�i��$^=<�$��/l5���������]���288�KI`��+��uW"���""fff>xc������b���������������tLMM���r���h�Z�=4�;{a5�.��������W^y%"�������n��}%���Up:M���������8J�R�8q"^y���T*������+W���r������89��;����Xm�
L@�/�}������q������]L�G+Mc~��9W�c�������9��j�5r�������d�o���H�4���o��Vlnn�8(�$����J9s��j���{�����^ooo����L�ii������������f�sf6����m{�z��$�7T��8{�l?~|�����B\�t)���
J��R�zx$w�`u#��g����.�ED��?�����;�$�G�������v$�x�[���I�p�Rp:E��1==�9|bS2$I����?.\����m�6��x��������n�U�>�#}�19:�;���b���<}{�����/�����D���K��K�k��k��
:[���#��(��1��kaa!�����c�D���d�j��>|�0._�kkk$���F-g�z;�x��\4�i���=_�����_���o���&�4�f�?�3?���_��>����X�
��h42�'Iccc����\.��3g��_�Ri��VWWcjj*?~���|�$�W��F%�
Y�7������SL�����w�FD���"����?��������?���|����W�g�g��W_�3g����htu}�������Vl���4������5`�4����������E��;������������J��v�7o�����8u����Om�Z�������2��V�hw��)8�����
=y�d$z��$I"M�������7�F����7>��$I�f�S�9��-7[�����d�yfgg��ng���z�i�3��������������333���g���������KC}qoe#���g���h>~�x=z+������Q�i��?�)�}������� o�^D�XUq�l�F#�zWWW�:G�T�'N���gw����W�\�������T�$����r���[����y�s<CQ��nI���l7�$��A2���av�����:9����cii)sV��|?���HLNN~���{����]������UO�_<2�;���o-���`������V=��8��6���G�����Y�^/0	t����8{�l�8qb�����b\�t)���
J�G��u�������M/��6[���*�`'�o�����Jnq�[q����i4��Y___����:[�$��s����P\�~=���s�6��x������#q���(�:�}W�=������f����4���s�����R�I�i�����������ol����le�������3������������}�vn9��>|�����K/EoooA	���\J��##�kw�����3��l��f�G����`������m{�{d������$I�j�����R.���_�3g�D�\�����jLMM����#���`;#�����P����J�_�������LNq���D��<��n���L�ldd$���=�i��j111��k��q����~�z4������+�}q��;w��G���������}8@fs�{��]�$I�i��fgg��s��m{�t����������������l\�t)���
H�I���Do9�W�k�v|�����O�� ������n���^�������r������R����s�����rss3�\����ss=���T����#���V�������c�{p@��4�7���1�=>dss3���3g�Z-J%�F��2<<���122���{�����Wccc������=q~�?w���b�����;���X�lF;g)����m/�;�=������W^y%N�<I�l{vii)���bvv��t@������V2g�4���G�V_�OEq�����	�$b8��M�4M��hd�zzzb``��Dp0%IG���/FOO��g��f���;q���h��%:U���kGF�����[����bC�3�r�����7������;�������_��F�]Q�a����j���e������������?&&&���;����m�>z�(���^������h��+~�6_k,d�/������x����d����~��>�����\��gAq��l&��7�m�O���Q��
L|W�\���O���p��y3Z�V����������'O��C��m�\������z�[�����\|����)�
N��v���4M?����}��~��i������������������


Ew�m�����crr2�=��i��u+�y��h6��:M�$���#����f;�|<��������$����{�Y���J����-���rK>�z��4@�����p�B=zt��sssq���X\\, ��z+�������������Z\ �}b��{��@qf7��-�V���F��R�ccc��$I���s��E�Z�����f\�z5�{�=?���������������i�/��Q���u��39d�����>P)GwyW���4����������E�\.8����������7o����]�������8s�Ltww��?\��k�1�Q�k�i��p.��jQJ�]H�yv��w���gr�6�S���m�azz:wW�^/8
�Quuu��/��=�;w�l�Uoii).]��O�����S{]���kGF�����v���[�������P��:�����'~�'>����9�o��]L�����;�����^�Vch�����%IG������~�z�����m�Zq���XXX�'N��	|`��+~h|(�>��9�4�G���H���;����o��oG�$1??��Q`��l�ci��9���o�C���byy9sV��>��
���������q���x����g?~KKKq������/(!�����{��`u#s�������zt�K'�,{���4Mw;�[�9��""�m����h4rg�z��$��U.��������/��Momm-._�>�s������#�]����J�o>�����Dqxvf7��{�R���i����t�l`` z{{N<
ccc199�����K�4n�����Nlm�������R�����^^�w��
L�y�`���hf^���$I
N�^��������Z�Vp�i��������/��������t�R,,,���N��+C}���y����?o���^���������W5���I�(��>�$I���q����V�������k�����w��n���~�>�]��Y3M��Gs�N��St�=���is��{�k�Z1;;�9�J%�&]��

���d����x���q���X__/ �Wu�J�����_"7�����.�	�S(��>6���v���=""fggs�j������Z�R��^z)N�:���?.//���TLOO���j=����P����.����t�=��f7����"b�j��F#�z�R������EH�$>/^����m��Z��q�F�����j�
J�5G����j�,��7��f+�
A*�=����{#�J����4�5����9��j;n�:[___\�x1>���F�SSS���R@2`�I�$�xx4����#������B���6wc�>�W���*8	{���t��^���-�R)N�:/��rT*�ob]__���/����i���+�����C#��w��������q�{�O�i�����i�F�������E___����466���144���4M���;���o��Vv9��N��KC�?+�Nc!���8h�`�Zm�c����)���������Z�I���m�j5��;�������|\�t)
H�%���`W9s��N������� *���n��?�?�k��$I���Ow���i����������t��V���K�$��G����P\�~=677s�nmm��k������^x!J%�AW����xo:��y��7���r|fl��l{��)���������+�����2�;3�����J9���Y���-����D�Z-8�����d��u+fff�=����XXX��^z)zzz
J��zO5�|0�5��9�g3K�|ow���pp�����4��`����g�sss�j�2g���U�T���3q��������������<��ebt ����x��\l�����C�Lq/I�]�������Y��.�+����+8
��%I����������l���7n��7r����QJ�x��HTK��c]�j��>^(8���g�{��q��=���V;���K6�l[[[1??�9�q�p0���������#;��������X^^. ���*�c�Fr�7�����Zq���=�r���3��������/�mfo��P�;����s���V���$�R)N�<�������F���=���W�\�c���s�=g�9�c�{���z��S�{��|�{�1�U.8���3�����x���v;���e��R7Kd�F#�zwww��D���1997n������si����wcaa!^|���V�������x�����}������<:%e~�)�v�������7��e����������z���GV�V���sq����;bjj*����	�Z.���G#����k�qyn��L�Mq����{\y��""j�Z�I�� I�8z�h\�p!����=���o��V��s'��vA	�"���g���xkf)��7L���`�i�i�mf����{U��1==�9���������@LLL�����g����r�J����(���@����3������?p@(��>����V�=�q���������Bg�^/8
��T*�8s�L����Q*m�c���JLMME���4�y�:R)I��#��UJ2��[��zc��T�Cq�����rV#�J�a�3����J�+8
�%I�z=&&&������v;�}���q�F4���E������s��,���e�w��Oq�����H�����o�f3fgg3g���Q�(tOOooo\�p!�{���������T,--�(��C}qz�7w����Xi�
LP<�=�g��{c�]'a�����4M3g�z��4�AP*����q��������gcc#�^�����}�:����c�R��m�����9�������H��1����)�\��������bxx��4�A222;>��i���^\�v-677J<K��R|��H��}m3����	�H�{�������jg������XZZ���j�H���h��j�g�������������.]��������������sz1f����t�=Q�s�8<3�7<*�L�F#wV��LdI����?.\����m�6��x��������ng����������d�<�����E�k>��zq/M�H�t�c��0�S��������/�,M���������G___����n`` &&&�V��x����q���X[[+ ����$^=<��7o[�j��M/�
��������u����Z��b���{c�����.YZZ������m{�n)��q����[�nE���=���SSSq��������@��V�G
�W�g��ZX��}=q|`����dW��?q��n><�;�������4���I����x�i�T��b`` �_�+++����v��y3���SQ�(�@':3��V����z��+����{��W)���(�v���j�cq+{k�����j�bvv6s622]]�7������p�B<���;�����K�.���R���-I�������d�Jz���/?��4MN�l(��>1�����+�8sss�je9��z�i��J�8~�x�;wn�R���f\�r%�����~�@��R�zx4w�`u#���o��$�{�O�nle^�*%1P)����h42�W*�)6�G0<<����9�����k�������<U��u���@��3��?�t�=�'�nl�vE�$�a7mnn���B�l||<J%�{SWWW���+q���_����K1;;[P:�i��������4���s�l��t6wm�>�[�����kzz:wV��L��%I�=�\\�x1zzz�=�l6��w��[�nE��.(!�i��$^;2�����f3�1�Xp*��Kq��v���f^q�RpvS���h42g������_p"�O���?&&&>R����Gq���X]]- �4W+���P����J���^`"��Kq����f�����{���J���e�j�Z$9-��r�/��b�9s&����gWWW��������H��E`Oyi�/���o�����Xk�
L��(��>0���m/������A2==�;��j&xzj�ZLLL��������v��u+�_��f��t�'�$I|��H���M��j�W�+�Iq�����r�p���
kE���-�
Gwww�������8�|=zt�����q���X\\, �i��K��#���{����j����=��6��w��w�����n��m�J�R;v,��;]]���mnn���W���{����|_w\������B�����W)�@�K�4��7��w�4����R)���
N�����d���o���{�����Wccc��d�'���C1�]�������E���t�=�pk�v����3���ckk+���3g���Q.��
��uuu��/�'O��$I�=����.]������W���kGF����>���o�,
�SP����m/"b������gff&�4{�D�V+8
@1�$�#G�������w���V+�y���y�f�Z���H�+~�6�;�2��W�L��)�@��+��UJ�S�e��h4����j

��X���q���8t���g?~�/_������+�}q��;w��G����t�=�py���jW�I�-kkk����9����$I���W.�������K/E��}q}mm-���������J���$I|��H���u��j�W-x
�<�=�p����c��{E�����Z�V`��7>>���188���4M������;���Vv	�=�r|��H����z��h{.��)�@�j�ca+��7��w �i�����������-8������������Gw<;77SSS���P@2��z��'�������X��M�{`�R��6��m/����bqq16773g�z��4{G�$q���8�|T��m�nnn��k������4MJ����b�Z����4�x8-�����lv#{�@%Ib��\pvC�����$I����`��������������+���^@2`'�R?~d4�I�|fc+�5�Tl(��Hq:X^qo��+�$��F��V����������T�7S4�J%^~��8u��������155333��3��?T��_�[��&�h����n�������h����z�^p��-I�8|�pLLLDoo��g[�V\�~=n���V���@�s��q��;w��Gs�����`�(�@�j�i�n43gc�]�a7LOOg^�������b�t�����������x����155+++$�$I_8<=��_g�6�������i���)�@�Z�jE+��D���o}}=3g�Z-�$)8@�(�Jq���x����\.o{v}}=._�����2���J9�ph$w~gy=�/�`�{��f6�2�'1ZU������E|�������brr2�=��i��s'�~�����~���c=qv�/w���B,lfo�(��t�����p���mk�Y�����������/8@���������/��������t�R,,,�������V2g�4�7�E��\`P���W���mo�[^^�����Y�^/8
@�K�$^x���p�BT��m�nmm��k������n�J|W���kGF#��j�7���3K�����Jq��j4�������/���199ccc;�}��A\�z5�H
<;��]���C��Ks��pm��D�Kq:�j�k��-?c�J�i(R���������������^�R��^z)N�>���?2///���TLOO���#��|_w��������s3@����l���qo�����V��9�������$�C����D���m{��j��7��w��}~��$I���G�;�h��l��<��4MN��{��fr�{��R�V���H�F#�z�\�������o���q���8r���g�FLMM���J�����J9>x8w~ky=�]Z+0����hv��y����mss3���3g���Q��4�'W*�������+�D�R�����z\�|9��}�}� 'z����
���X�������%ww@�����7�����������z�I�����������m��iw�����z+677J����b�+�`��N���s�V�
����n����{Q��������8x��j�;w.�;������������
<=]�R�zd$���������K�fP��3����=�{����J���f�j�Z$IRp"��)I�8z�h\�p!����=���o��V��s'��vA	�`��T��s��|v9���Gq:���V��J��`W��4ezz:wV��
L@D���`LLL�����g����r�J�������q���9K#���s��R����&��7�]���k�R�����������)8�J%��9�O��Ri��WVV���K�h4
JO�$����Q-e�l��l��6
NT�{�afr�{��]'�(��������n���J�$:������v����n��q#��fA	�`�*������]Z�wW�X�{�A�is�7��)��[y��J�R�����,���q���x���v<;==SSS���\@28xN��KC����i,���=�l)�@Y�jE3M3g�{�S����������X������T*��'��W^�J��������r�J<x� ���v���l}(��^�j�������<C�{�Af7�2�'1Z�� @g����-t������Q������do{.M��{�n���[���YP:8�J�x��h$9�G��15g�-��(�@�+�
uU�R���5����j5���
N�GU�V����q���H����w,,,��K�r7��L���?>�;���R4����g���A��{c�]'�kkk�����V��X`w%I�?�|\�p!����=�l6�������oG��.(!��q���9K#���s���x�����*'������z�^`>��������Z���������cmm��d����$^=2�R��,m��k���S��t��f+V[�[�m��w�4�F��9���������i���8s�L����Q*m�����jLMM����#M����5�U�;4�;���������Kq:D�����1��}gqq16773g��t�z����������v�7o��7nD��,(�_�{����7@y��|,o�
L�w�{�!f7�o��-���R.8
����t��$Ib||��4<M===q���x���v<;33SSS���T@2��~�>9??o������h�v<%�{�!�6������Z���������DW��s�NW*����q�����766���+q���H�	���K����Hr��6���r����Kq:����1;;�v;sV��N��422���1<<�����{/�]����$���Po5�ol0w�����^�Z|z�{���46��3���gzz:�z�R����b���uuu���g����$y;��cqq1.]�sss�����������t�?����7S�����mnE�3����gkcc#2g�Z-J%���GI��s�=/^����m�6��x��������Z�|�$����FW)�0�����7N�7���0���y��$1������m���Nq�����?&&&�^��x����q���X[[+ �/�]����p��������5���������+QJ�7�y�4�-����F���
�r9^|��8s�L���m�������T<~�8�4o?/���`o������|�6[&��=�����c�����,����nM����(i(�Z-&&&b```�s�v;n����_�VK�>�$I�G
G%�(��N������ODq��4Mc6w����~�h4rg�Z��$�===q���x���w<;;;7o���.��G�].��GF"�mR�m����B3����qK[�h��������n�cff&s6<<�j��D��R)�?���������������_P:�|Gz�cb4��7�c&�
u�(����m/"b��R`�����h6���z�^p������������m�%I1::[[J�Q|��`�r���?��f�]l(��)�������]��*y)�/�F��r�����`�����W^y%N�<I�l{�Z����7cvv��t��JI��J����f3~oz��T@'s�?�qy�l��?���b~~>s666�r��@�iI���#G����������V����N��u+����������p�����xoy��D@'S��=nv3��7��Up�����H�4sV��N@��������8t���g=zSSS���Z@2�\g�z��@~1����c��*0���`[o�b���gLqo�h4�����cpp��4t�r��O���^zi�
�kkk155�=�-��A�$I|��H�U�u��j�W�{-v��{��F3w���?������J��V�E�$'�������d���n{.M��u�V���;�l��Yw�����_��k�?�|���a�[��{���-{����ED�����������������������t�R,..�:�s}�11:�;���b����{����8��e�>��iLOOg������Dt�$Ibee%�����jm{vss3�^������E?8��|0�s�������E��5���{��6�=:���Blme��j�����lmm���L�x����q������( t�r��kGF����9��������@6�=����46�����J�ix�F��$Ib||��4�7i��/�'O��qS���R\�t)fff
J�a�Z������������Bq�����Hsf6�u�f�sss������T�3���$�#G����D���n{��j���������j�
J{��C}q��'w��G�����	<Iq��������$��.��N7;;�v;sV��
N�~���/^�C��x����q���XYY) �}I���Go9���k�v|��|�i������Q������J����4<m�F#�zWWW�����\.�������_�r��������|�r<|�P	"��\�/�����o-����`����7��Up�����XZZ���j�H3x����brr2�=��i��};�y����������=qa�?w�{�1���<p�(����i�n*��W�����z�^`����8�|���;�����K�.���B�`o�����V2g�4���s�j�V(�����l�V��~�{�-M�h4��������+8U�$��/�����Z�n{vkk+�]�w���v�]PB�{��$^;2��E�������b���=Iq�����m{c����OgXZZ������m{�������������>x� �^����$��i��+~�6�;�2��W�V�A��{�lNqo��]%/��lzz:�z�$Q��
N�Q�T���^�S�NEi��5���cjj*�5
���}q��;w��G���j��k��{P^qo����$<M�v;fff2g###�������$I>|8.^�}}}��m�Zq���x��w�����$I|��H������j�W-D��'�
�=��f7����:���ln���=������x�b>|x���F#���bee��d���V����#���+����jq��=Eq���V;V���.���6==�y�\.���h�i _�T�S�N��/��Je�����q���x���m��y��'�������X����7��7�=�cf7�rg�{�kss3���3g�Z-J%����������d

m{.M��s�N����������G?4>#���{3M���s�Rn�����������+{��Ty��"�S����Z���s����c;�����K�.���B�`o���x��h������V|{f��P��s�?�1y���j%�$�.@��4Ms�{===100Pp"�x�$��G����Z�n{vkk+�]�w���v�]PB�]c�]�C��
�Ss����F������{L^qo����$<-�������9���
�t������������>x� �\����$��wn�?��u���x4-�v8(�`i����lf��:W�����j����W�T���3q���(�������JLMM�n���$I������.g�>�6�����H���d�nP��=d~�y��)�u�v��[V����m�W%I����������l���7n��7��j�vG_�_<4�;���7����=�Cf7�2�����j��4<
�lfoQ���������7.^�G������tLMM���r�`���������m,��f�������{��fvqo���$)8
OC����^*�bll��4���J�8y�d���+Q�l�F���q���x��A�i��a�|?\�}�f��������5�=�C�6��uw�����l���\�lll,��r����������\��q���x���bss��tP�J�������V|{f��L@��`�H�4��7�������s�	�������W�V���sq���Hv����SSS1??_L8(�xwW�`-��~in9�m�(�����Vl��K^������4LOOg^�V�;n#�N�$I=z4.\������������z+����v���P�#��|o5w�����hy
��Hq���m{�U�:���Z,//g�j���[���
���D����x�����+W����Z��8I����Fw)�g��f+~��B��v�s)���W��*G��%��4��Y�^/0	��J�g���_|1J����YYY����h4��+}�r|��H����Z�\R^��F����f���n��:M��1==�9�������I�$��zLLLD��g��v����q���h6��7�Ntb�7^����Nc!�����~��{D��=�����������Z�Vp�z{{�����s��xvff&���bii��dP���PW9s��N���s��u�
�=�6Z�Xn�2g�U��N�h42�'I����V*����q�������{�����z�j��?R%���R)^;2I�����|v��L����{@����:M����������hT*����3221<<���4M�����k���n��NR���������R<Z������y���R)�*^�;���l����Y�^/8
�]�j5��=���$��=����q������+(<;G�Ho5s�F��b���s%�94`�+��uWv������hd^�T*;n��&I�x������������f�o��v��};�$���$����Q-e����l��6
N<m�{����
N����������Z���o� ���@LLLD�V������������V@2x6����C#��w�����jq��������Zi������^g���������@�)��q���8s�L���m�������T<~�8�4-(!<]�{�������<^�����{������f�sf�{�#M�h4��������+8t�Z�������v�7o��7nD���@g�l}8�����4�x8m%u�H�{��f6�2�����j��4|R�������9��j�$I���s��������������L\�t)���
HOWW������o���r����Cqv�lNqo��%e��1==�;��j&���T*�������s���������r�J��?R[��0��j|f|0w����h�o�x�`�������A����n��FFF�Z������������������{q�����Tn��L��������x��\l����>�=�Ei�nS����Ojnn.Z�V���=�������W^�'ND��F�����t�R����>�R���GF����:�����5N|�{��V���l��3�:G���r�ccc���)I�x�������������f����N��u+���!�*��C������q{i��D�����h&g�^D�XUq�lmm���|�l||<J%�n�����Q��w<�����|�r����>���}��`o�����cy+{�;����v��F3��@�����N0==i��5�V���r�/��b�9s&����gWWW����������l�K~�>�����v_~4m�i��i�.����7�m�^�h4�����cpp��4p��j��������m�����u�V\�~=���7N���Z.��GF#��?\��+s��f>>�=�Ey��q�����������z�I�w�%�������������;�����K�.���b���;�[���/�kf)��7L|\�{�K6Z�Xn�2g6�u��m{���T*��c����s�����Q���q����w�^�iZPB���ol0�=��k��x��\l����>2�=�%s����""��+&��H�4���3g������Sp"`xx8&''cttt�������W����F���+%I�vd4�J����Z���-��W)��.���.�UKI�W����ZXX������z�^p��������_��'OF�d�kii).]�������g��?Z�����w��
L|T�{�K��{c�];�d��k4��K�R�������$�#G�������w���V+�y���y�f�Z���G��`o��=����Xmz
��Fqv��F3��xwW�I����f�f�����T*'����������C;�}��q\�|9VWWH]�$�c����R��o�����s��i����(��.h�i�o�o�co�����!�^���N�\���O�K/��rv������bjj*>|�����].��GF"��?X��+�+�f����`a���{����F��y���+���N|���199�����K�4n�����Nlme����#��11:�;���b�lx���Bqv�l��t���V�
�����KKK��Z�I����m���q���8z���g���bjj*
H���F-�
�i�����n�
���� ��7�]�������m/"�^���$�$�c�������Z�n{vss3�]����^�i��d(P)I��#�Q�����f3~oz��T@�=�y���j����7�i�����������+8�I


���d����x����q���X__/ lo�Z����s�o-��{�^�`�)�@��4�/�u+��eKKK����9�m:O�R��_~9N�:�[����cjj*fff
J�^��=���<���f��D��)�@�V���h���q��=��hd^O�$���N<
I�����cbb"z{{�=�j�����q���h��!�=I����D_%�W���v|��|�i���gOq
��m/"bTqo�j�Z1;;�9��.w�����bbb">��������T�����u�K�������������
v��,��7P)Gw�K�^577��Y�^��xJ�R�:u*^~��(����]__���/����o�������8:�;�����o <;�P����l����F��J�###��������������m��iw�����~;���"�?0>�9�Sh��?��f[�������+�U
N�G��������(�|K�Mwww�?>^x��������K�r�_�g��$����('I�|~���Y,8�.s(�f�K[����{{���t��^��(R�$��/���Z�n{vkk+�]�w���v�]PB���j%>[��_�_�{+�&��@s9��"���4M��hd�zzz�����D@�crr2���v<�����z�j��+GP�����xO��+��c���fB������hf^�����N�G���kkk��z�I���
�J%^z��8}�t�J��:eyy9������O[�$�����[�~�Zk��+��#M������������7����Gmw�}�V+0	���$�C����D���m{��j��7��w��V�v#��S.�����[���V���h��{O���-�
Gwww�������7.^�G���l������XYY) D���#����O/��f��'��Gq
�N���������h6��3���`+�Jq���x��W�R�l{v}}=._����~�iZPB���j��S+�x��\��^��YR���,l6��sO������m�T*���X�i��htt4&''chhh�si���;w����������pP�KI�vd4�I�|v���Y,60�{P����m{���y|v���V���e�����\.�����j�;w.�;�������������g�m��+~�6�;�2�V7
L��d&��7R�D9�y|v���L�i���Z�Vp`�K�$�=.\����m�nmm�[o�w���v�]PB���}�B_����b�����=(H���������Q4����j5���
Nt����������������q���X__/ Q�$���#�S��Ok�v|��|����� M���lf��������XYY�����HlH�Q�T���3q���(�������J\�t)�M��������Gr�wW����jq���P�������jg������n���j&:U�$q����������m����x��w����lf��|/��������������C�'�������)��-i����t�l`` z{{Nt�����x�b<��s;��������X^^. ���b�Z��5�4^8�4-8�_�{P���^��e/�{���blnnf���z�i���T*��'��W^�J%�0�]q���x��A��<E�R��r�=����o�,
�1M(@^q������hd^O�$���N�'���199�����K�4���o��V�
�'1��?8>�;��[��W7
L���`&��7������j�bvv6s6::�����T��8{�l?~<�$g���gaa!.]�sss�� 8?�G��s�o<���V��D�?)��3��n��V+sf���233�v����z��4�~�$I<���q������/NDD4��x�������������$I|��Ht�����j�o>��4MN���<c�9��"��������]]]122Rl`�������j;�}��a\�|9���
H�~�W)����o/���%�9�i(��36�����UJb�R.8
y666bqq1s6>>I��8��r�9s&^|��(���5���jLMM����mA�S;>�g��r���x!7���Lq����{c�.e�=��h����z�I���^����d���o{��n���7����l*S���pm(��*��f������,���<c��������'M����������x=�����.\���{n��333155KKK$`���J������P�X��6��>	�=x��is��{{���r���g�l��T*����q�������������r�J��?R�����{��jC��K���pm��D�?(��3����V�=�c��b����h�����L�###199���;�}������k���Y@2���#��\o5s�F��c��.6t8�=x�f6���%1R�qo/h��133�9�j5��E�g���+��='N��$I�=����.]��������$I_<2������f+~��Pp*�l�{��nf�F�����G������je���z�i��$I<��sq��������l�����~;n�����H|<��r|��H����Z���Z\ �p�{��n43��u���W4����r9FGGN����?&&&>�<|�0._�kkk$`?91�/�����K[�������H��1���qOqoo�����������x�J�U��r�/��b�9s&����gWWWcjj*?~i�����G�C1���:��N���s���;��v�����x��7���������V���/�g?��8}��S}�w�}7������{�bss3FGG�������}.zzz������	�,k�v����3���aff&w�Q����Z�q���X^^�=�n�����1??�O��J����YW���_o:��y������r|f|��l�I���G��?����������������7bii����'������q�F��/�r����wbee%�������s.���/}����_�������:���oe�������~���V�}����_��fr��ED�u{	��F�����(8
�G�������{�����=;;;�����K/����;��T����3K��6���u���j���s�v;��W����������G��^�?�G�h������~���(�=-����������W�jn�-"����f��O�t����\lnn~������?�'�D��?�Grn����?��C�?>�x����8��k:�\Nq��R��r��4|���J���f�j�Z$IRp"���T*�������s����F�����r�J��w/�4k<���@�)�������l��
Dqo������?���s�w�����������1==�����������8y�d�?T*�������o����v�?��?����'����8u�T|�3�����'f�F#���_�����9�_���6��woS5������gK*�I���crr2FFFv<{����z�jlll<�`t�R���F����6��V�nc��T�9�:����S������g�gcmm��k'N��_��_���������n����o������O|�?�G�(��_�+����_������?~����S*���7o��o��1;;����8~��gVWW����?�����5�o6��7�����4�-�


EOOO��>����x��W����;n^ZZ�������-(�j���;4�;wi-n.���� S��������O��?�����}�v���O�������_~b���S���7��/}�KO����/���?������������������gff�{>�/�������x���?�V*�����?o��f�<y��������������t��v;�Z������n�������b�m{@�J�$�9/^�����f���;q���h��%����3�����y<�[�@gP��C����q����������������R�����'N�xj��h4������'�������(�}���3&^}��>^XX�����ow|�����R,--}����������{�����?�O�����_�+133������	�|s�7������F��R�����x����cbb":���G����T�����N����c���9�l�����h�i��`oS��C^|��8�|�J��������X^^���W_}5~�'r��I�$~��~��k�����D����v;�����O\�/������wY~�'2���/~����R��������5�ov#{�[W)����b4���-�cccQ.��:_�\���O�K/����7kkk155�=���b��R)^;2y�	}��Ss�9S8��������{�����>���?�N��������������7��ft���������X����������_��fr�{c���<[333�7������<[���199��K�4n�����N4����8��=����`���3K�X�,0�m�{���r���O\�����#}n�$�/�K���~��=��o��o<��O��O}���O��O=��o��o���J����5�C�����J�I���_�����j

�������.���Gw<;77�.]������i&G�pO5s�F���b��.6�Q�{��+Wbk�_IN�:G������������?�g�g?<���>��������'O~����f\�z5��~�����N�����R2��Up~����X^^���j5��}+I�8v�X�;w.�����w}�g���{/wS1S)I��GF�������V+��P�������kO||������>��?o7k?~M@�[�jF+��1��]5==�;���&����111���;���~\�z5666
H@�������s��W���Z��`oR�;@�~��'>>v�������s�N���������{��S}�g����&���ndo�K"b����[�4�F��9�������������x�������;n^ZZ�K�.���LA��/�����?G��|�l�
L{�������'>~��>��>|8*����������#�}��������C���=�����w}?|M@������>\�D�����<;�������9�m8h�$�#G������o`�j�����q���h��0����@��9�l�����'~�
Me�#����O|�����>?I���������?3�Z__�����a���8Y�����q=~�8w�T�7n|O��������oeee������e^,��v�����;�V��n�)�y�A�y�O����������������c~~>^x�����)(l�������s��y���x8��WN��y��y�A�y8h<������i�/t&������}���>I���>�v��~���5}\������_��O�g|��_��>�<t�����a��{�3����>}�V����vK�^�R�{�
��������]H�n��4���8���chh(�{������w�}7���bm-��������|���f�./���K����j���{�A�98h<���=����wp��{w�#�(�N,�����'>�V?�;www?�q�MzE=N��U��t�v�iFi/"����zzzro@��s<�A���333������$Ibhh(FFF>�6z�����(���IYR����#M����������n��������Y���XE~M@gk������{�&�9��n��3�A�n�cnn.���#M�m�vww���xtue�qC�oF�Z��vwo�>Vl(�*���<��'�0��-q�3�|�"�������_���7���c}��7����?��G~�G���sO%{���J|��_���������]L�����������[J�'_��.$bkk+�_��9��jq����Q$�y�A�y��iuu5����f3�L�\������jQ��m��p��`�����X�~s���C�����=�����y8H<���=����4���k���v`������b+++���4�D%����H��c����l���������Cq���O�g����S�C����������f^�����.��~�����j��t�y�A�y�Ochh(j�Z��y3fg��������X__�3g��0�������`3�������g�Z���c��W)�l��$������p�x��{����`+�v���r��{�>��?z���w�/�JQ����\�V{������?�X����E^1m?~M@g����F2��Up"�S���������z�*�T*�x������SQ*m�k������������-I���C#��S��h�����#M�����P�;@^y��'>�{������?q�D������������c�={6��~������n�����^����=�U��^����U�$q����x�b���m{��j��7��w��V�UPB���r)^=2�;��W�W��Hq��pQ�������]��������&�s�of��"�vK����emX ____\�x1>���F�SSS����p���������7fcvc��D�;��.DW��(���};������_��W���3��L����|����8���~��}�����������g���t�����*IC]����n�cff&s6<<�j��D��T*��S����_�J��������|�r������iA	��|0j9ob�N#^8����7��dpp0^}��'��?�����>7M������'���?��s���?�����7�7?�Mz����?��� ���y?~M@��{����J$IRp��������X��N��������d

m{.M��s�N������e��AQJ�x��hTr~2�����^(8Kq��������������H��[��[q���>>|�p|����=���}.j����y3~���#=��3}�K_���~�����_��~�y��F��y�\.���h�i��j�����c���xv~~>.]�J�p������ZX����L�R�;`����������o��F���������i����������w�T���O�T�������/��/�������_���?�xpp0���c�~�~�����N��������W������������E�\.6�>�$I=z4.\��ju��[[[q����{�n������^��=���<���f��DP�����C�������������������/�o���������������~�1>����_����b�����������k���=��.�~��������fN�Wq�x333���z�^p��opp0&''c|||��<�+W����-K�]�$��C#�W��O��v|����o��Hqo���W������=�|���|����z��������W�n�������#G>����[���}.~��~��$����O������>��������k��j�����������3���O����v����j|�s����op�������?��w|���5�efc+�z�U���5������188Xp���R���3g�����n���XYY�������.(���\�/���_��k+&�bTv;O����;������G��O��Oe�~��~.����;��;66�������~���w���/}�K122�N������{�n�Z�'>�K_�R�'������_��_�7�|3~����k�������o��'bxx8n�����O|^ooo���bdd�#=�~����2�S��V�RJ
Ns������J�
�Z-������$I:t(��������{��j��7b~~>N�:�r��������8����^���b<�������������W_�������-s�����o;n���=������������
�R)��?�������z����7o������)��������_�����M@��+����W��m{�z��$Wooo\�x1�9���������������[~`|(�s�y�4���s�l���gGq�������z�j���}}}������?����������^tww���������_�������g>�{���?~�~!�^�?��?��'b~M@g�+��u[n[�4Mczz:s688==='8�J�R�<y2^y���T���x}}=�\�<�4U����I��r����m6��3���gG�`��}�v��w����k���������o���]�����V�q�����g?g��y*��3?�3�3?�3q���������������s����?���R���_���5[��jg��r�I�gcaa!���K��Z��4DD������d��q#�i����wcaa!^|���V���#�����P���������x��;����*�Oq����������������|��u����V���~����)o�^��^��F��$Ib||��4|W�Z�s�������{�n�[XX����x��cdd�������������g���h>~�x=z*�����U������{��R����0�f3���2gcccQ�x����$I=z4.\������������z+����v�vk:S�$��C��[���k�v|����%o��{�)�n43���W�������k�Z�i�300i#����W�\�����P��J9�xx$w���F���Z\ x��S�����7��W�F��y���+FFF�
��*�J�9s&^|��(�������JLMME���}	`9��F�s�_�^�����@'P��O��n��f���Q���������R��V�E�$'`'I�D�^�������/nDD���x��w����lf�
@������V2g�4���E���
@gR��Oan�y����W�����Y�^/0	Wooo\�p!�{���������T��6�Y*�$^;2������h��f�
O��|
�[��+I�]���Li�F�������E___����J�R�8q"��=]]�����F\�z5���ij@�����
��/�����������B^qo���$���y����cc#�>��:���HLLL��p~�#�;o���{���k�bss��t<+g�����������z�]`"����S�+��uo�%��'o�^�$Q��
N��U�V����q���Hvx3�����t�R�����g!I������)g�'��V;��h��U:��|Bi���F3s��W�v�333������������$���>.\�===��m6����o��������	�S�V����#���+�q}q��@�))��'����f�;��+�bvv6Z�V���=��700�{������cmm��d<��{��p��k��X��~%�k��������D�h�Rl�jzz:�z�\�������,���8s�L�9s&����gWWWcjj*?~i��l���Pm(Fr~��L�x��\�<�������8���}��z����	p'A�+k�)��H-�{|�$�x�'�(���������=��w���%����8q|������9r� E����2
�+@�	6�nl�U����	�
\D����B�+~Ql�����@p�;����-Y&�bZ>���������Q&�?()������PU��$9����A
�X��	��4�ds�L�{>�+���d�Kp���;�������<���I�n�@���b��m�V�Xq�sGGG�����I����G�z�!�;�����\�p��p���{V����u}�{�XL���o�����5k�h��-
��hF>����u��Y������akm�VTF}��
�+g;n��!���m���F�����������,�L�0��7@���:;;U[[{�sO�>���+��/�b���0�h�U4��k����7/N�,Z��c�������K�R�����7����i�&�]���o�d2������X@���J+�-���Me509�B��{���\��xE�T�
x���8�FFF<g�x\�h4��p/��������]�Xl�s����;�'N�q�������6%*}�o]L+3���W�p�|�{��-�t:�b����d2�6X,������qK�	����������6�_�4��[�������q9��V���w�����J�<����������b
��a����*��	{ffF}}}�K�5�4�ds��/4R���M�7Cp��Tt\����o�V�X����������7g�<466���C������8�N�8���~�Vg���������glJ���7`~��M����8��V�������6�d2�6X�b���n���+W�����1���(����N��ViyE�s�Jz������R� ��m�<��C�0���422�y<�(��>��i�Z�z��l��px�v�|>�C����3���[�ahGs�"��9�*��q*�Vx#��m�	��E,����cx�fgg555�9kll���{�H$���T]]�M�=s��:�\.�f��Ue��xS��|prV�33�-��{���\��x}t��?~m{��L&�KQ8����n���>�arrR===h;��XW]���J���SiM��� (��
��j<����@po����T*�9���VEEE�`)2C���joo��kH��u��1
����6��G�q��!�Y�q���	9��V��=n�d�V����������d���=g���o�����J���Z�l�M��x�����433�f�[6M=�\'�����z���	�k��6�����$�.j�Iy�k�3���H(RKK����
y76]1;;���^]�pA.�M�h$c=�P�;?06����`���6����{�pHa�o���m���y����dY&p���������$�����!;vL���=�j��VsE�s�J�wa\y�	v)Dp�����W
�I���x�`�L&��(�j���Z�r�M�Woo���t�n�4�h�S�4<�SE[o���
�=n��Op�����I�R��-�R"�x�*�0�z�jm��U��ws��|^�������n@�T�CzlY��|`rV����-��p������w��{#��)��x�e����������������{��Y<xP�l6���Y_S���
���/Nh�Pp#@��nwn�X���.�{cdd�w�L&����,m��Q����a��;55���^�������%Ty������'���
�=n�X��y<2U�[�����R������B���o�rb���������
�'I�m[����m�m�^�4�DS��"���y��O��|�2��������p��MMM)��z���$�����Jutt������^�xQ������`3��e�W_�;otR�l>�������?�g�Iy��566�	��i�Z�~�6n�(����6�U__���?/�u�p���j-�E<g���.���8�.(;��E��D��9������9���K$�D�o�R}}�:::TS���$I������:z��
���iz��Va���g
��Ne�
Pn�p&��ue4D	��m����m�s�L&���h4��[�j��U7=wbbB===J��l�VM���d�w������l��
�=n�X��m/dH���6���m/
���>�m�����U��m����A
>|X�N���8m��
�J��T����8������x��p�r��u��L�x��V(411�9khh�i���CMM�:;;o�������C���f�p��dB�V�s�w\�><.�u�
P���[�������������0����6��,�R[[�ZZZn�����)����6L��H�����{������&��	P�p��j,Op/(�T��x4UMMM��7g��-[���UVV�{�m�����e�v@@yk������w��HF#�|���=nb�h��x7��G���)m333�����%�I�����{���B���jnn����TJ�������	�p_}��1�09�^�0��������&�r�m{�{w�_��$566�	pgL���u��i�&Y����f�������������a���:Y>J�zg$�V�RFp������C
�|+�[\���������F�X,���;WWW���N���y�s]W'O���#G�����S<b��������������6�&FsE��
���U�tZ��wH2�L�
��E"m��E�W�����tZ������X������Th]����~tqB3E;�����7���WOp��J�R��M�T}}}��w�aZ�r��m��h4:���BAG����'�8N@@y1C�-�U����lG�O�u��7��{�#g;��y�:����X,jll�sVWW'�����jjj���������{��y<xP�l6����DC��h���������tpJ�=����'������|�d�L&�X�e���U---2�������VOO�o35��i������w������p3����
Z�����F��������D���0-[�L�����\�qt��q
�X,�!���j���`&���]W��~�7C��y���"��x����f599�9kll��3JREE�����|����;22���^MMM����a���:Y>�=L����H&�������k���y;n�_��$%��7�e����]�M�6���y���r:x����;'���	��D�������pzZ���n(��a����������]���FFF<gUUU���x# xuuu���T"���<�uu��)9rD�|>������+��*�;����f�v�J�=|L��r|f������I�r9�m{('�HD�7o��5kd�����i���h||<��������jU���I�v���	O���>�r��!CJD���)M�T���ajhhx��2C+V���m��F�=�X,�������=rp�b!S;��|�gfr:��	p#�RGp~���HX�M0ps�mkll�sV[[�p�VC����juvv������^�pA}}}���
`3(m+*�j�����d$�q�����=|���������q���9K&�o,.�PH�����a�Ls���fff�����/�u��6���@C������]W��k-�����u]�{,�Jy�,K����.,R�dR������o��$�q488���������2
=�\��ax���E�7�	x+�RDpSE[y���7D���)=�|^�t�s���p�F���b1m��M��/������������d�@i����Hc�w~pbZg��nX��+~m{�T�q����%��7��4�v�Zm��Y���?��r9<xPg����z?�0�M�J�����_�P�h�`�!����^M8�H�o�����J�R��X,�����7����Zuvv*�H�����O�������l��0}hYB>����~t1M@����rE������o��������%�I��F����y�f�]�����3��zzz4>>�vP:bVH;�j}����:��	n!��Bp~�{�Q�{���������1�M���0-_�\�����b��[,u��Q


�q��6����*���U��wRM���G�7�{\'g;�*��3�{���8���D"�h4�F��VUU���%����{������6`�=�W]������}&d;n�[;�{\g��mO"��~MLL�X,z�h��Bp]WN!/;��S��u����P(�
6���U�Ph�sgff�����/��n�ez��N!�{>�+���L�K=�G�P�F}�{Q�P�E����k�3MS���o�R�:5�#o����cPnf������QSK��[7j��O�q��{�(�]������j
hjj��<�q488���	�����x�n�.�C�	��J{������2����7,V���u�|�{���������B����q�YCC�M�A��|�]���wt��A�sr3�:��3����������������Sj���7X8�XL[�n��3gt���y��������TSS���tmIT��tVgfr�������5���'��o���X�?��;7::*�u=g���o�R2;���������4oh���#�?�?�I/��hv2�@�4M�Y�F[�lQ8<��1�|^��3g|_�.1Cj��
���9<��S�$�{�a��&rE����'�Jy�D"���o�R�:yB_�����7����yc������������"�H$���������{��:tH��w���
+�5���ONg���	n!��Ep�k��E9>3�{wnvvV�����d2)�0�� u����?�o��+�����?�o��@I	����i���[w�������������y}�juUL[U���S������{\c4W�<nR"b�M��k������7A������������Sw����)}����kv2sW�p/����f���+��{n�X��c�t��	9��cM5�U��^Q�u���q9��V������	��F�
�
wG\���������Zo�R������5�]oj|L{��/���RUU�:::�l����;<<���^����,=�i���:�>o��
���d�K�{\��q�!J����d2�����d2�6(����#o�[��q��}|����B(RKK����
��=wvvV����Kk��>�C
q�y���.�������2�u5�������t�R)���a���!�mP
�y�;�|�w������


���Tuu������'N���c*�mK���*�����_�P�v��X���������"Ap�������1�Y]]�,�&C����!�=r0��u�p�FN
����h4�m��i���7=w||\===�d2lK�a��T���������7/N�\
e�������#�#�����������d2�mP
���/����k�~>������Wk��-�D"�����u��!�>}�
\��
�����|h*����nX�p�X��y��
)�[���<�U[[�2(	��������D"����������g����C��rlK���
m�W��|1�L���Q��C
��F}�{�Q���D.�S&���544�0��7�R���.�8���88@�(�pX7n��u�n�z}rrR===
h;X�N��[�������q9��	e����5�5��#�T�w�L&��"?;���T��3;=�Bv6��	p/����futt���b�sm�V�e�v@��6M=�\����T����M���!�����h��}�i]��I�����FFF<g������
x#����]h������Ree�����l����{��E���izz:��`qk�E�@c�w���)
���p��@�X�?�C������R6������;�����0_@y
�Bjii���
��=wvvV}}}�p��\�
hCX��k���"�9s%�vaBy�	v)@�� i,��������oP��R������!�MPJ"�UU�9C���&����M}}�:;;USS3�y��jhhH��S��be�0�h�S�4<�SE[?N��
4�{H�=��G�2�����q���z�jkk�x?q��0�l��@?�](��������?���T�tP�����n��U�V�����q���(�&��|U�Cz|Y��|prV�33�-�u�`1�k�����d��m���d2�6(5��u��g���{t�`�b5qm{b�:v=��U���^2C�V�R<����������BA���+�j�*�&�P~��T�m&�~����Si-���&��j�q���9���<���%�Jy�B���x����?yO?v2��/�������_���A�u������������������{��9:tH�,����G�q��C������r\7��A �({��������|>���	�YCC-x��k�i��m�z
I������?�c��o�Ku�K�84x�W�eYjkk����o�:jjJ���	h;X<���'��d��/f���
t'@0�{P��r�m{��D�
v�%ntt�w�L&�����}�^�0GnfZ�^�7��_�����;�tw)����k,8�0������vUVV�{�m�����e�v@����EtC������.����{������Z
~�C��T*�y<����:�mP�ZxX�rA?G��6-[����s���/Q�����/Q��u}*=JDee�������t�sS��z{{5==�f�xt�U��"�9s%�6<����`AQ#({~���H8�M����i���x�e��]��_����4�I��kW�����REM\�������?zU��[o�+dg������.%���s�nm�����Uw}_���4M�_�^�DB���*���f�Y���i��5jnn�ge�4=�T��N��wn|��d��[���\w�,�e�u]��^������566�	���*ZQy�����'��VEM\�����g~�����
=��_���M�}�������%���������u��!Z�@����Wgg����������'O����*�&�RS��}Y��|`rV'&o��1����=@Y�):�y<�\"�w;\��
���q�b��7B�{�|M����5���������\���Y8S������9�N
]j�{m���S�|�b>����up_�V�Q��������!A�R�D�e��;wN�O������	������U�D"�
��i�����������8�d,��0������=@Y�k�������	����p�
���~�������������gh�z�5����/�_�������i�����|�gN���������K��'�S}=����b�V�\�m��)��{n�P����u��)9���p�|0�PM8�9�;�^���������V@Y�{������!���*�Jy7MS


o�R6=1������c�5�NM���Vmi����Z���w	G���c������sg���:��5;���k������OG�����+���9�?��*����bTSS���N�8qB�����{��9��i�����
��EB��h������+�wa6���)u�����!�(k~�{����b����q�Y}}�B!�'���u}�K�U�������^���}Q3�:��k:?pL�������zN��JM���u�6?��o�a�V��X�'?��z�����?yK=�]:�{���1~��^��������
=��������d�����fY�Z[[�H$4444o�����z{{�~�z����e�W_���y?|���I����16���u]��)�0e�������5���"o�����Mb�h�����G
��;��o�;U���'�����t:�=��@�������sJ$��k����}�&�/�o����MOx�[�8�����T��o*�lR��g�m�3���O`�2C��-SMM����533�{�m�������_��@����j����b����\I�.����Ij�`����R��F�y6?x��LM�q��d,���
��0*X4H%�V�v4Y�=g4���T*�y<�,h@
�����^��_����'������!3��?����65�C��9m��g4��w�������u�f��I
��������oi��������er�:X�***����S�N�����;22���)������:�
 8�a���:�t*��s�C�2[?tQ�����W:?�����z�������Z��b�:������w��Dp�V���jjj�s���hH
�����{_�C����|��
��/�J�[���e����j{x�2#)��}E}{_���w����:����������|V;�S<�l7X�ij��uJ$:~���>��$)������Z�z��/_��JNM���dB�
Ox���y��5|nL-5z4�P,d��-w���l���o����-��n�����,�L�	J��o|U�gNy��hT����W�Za�xcR���g��O~ZC?{O��]:�������956����o��w��u���������#
Y��KK]]�:;;500�L&�{���:u�����6l��H$����6�+uf&�����v���Y]�����
<�
�������w�^]4L��-p]W��wcXUU�***��h�'o�g�|�w��_�k��X�Fw�i��r��j��aM�����?T��.�/��E\WC?{OC?{O��Zm{�u�zNu�+nq��,�h��-:w����9#�u}�M�������
T[[���&:?�������������>������ek�'���L�&��(��{�h���056��?�o���GS����haT����������t��G={�4��������^f�z����������:���n�>���0_���g�V�\�D"���~�r9�s���9����k���n	����^�Sy��+gG�����w���e�q]����{
�.�bdd���ajhhx��q�O���Nf<���
z���-�vL�4���>���O3����VOw��������>���{��k�;���y5���v��UWW���C'N��������?^�LF���m���i�����.5���J�����>��=@YJ���}���q��l�������VaZ��>�������C����{���	t� U�z��������>��=]:���d��^����%��%���U�O���>�p4����?�e���U���:q����=wzzZ�����b�f�n	w�����f�sN����B�����BpP��r��CRm�o�73>>�{m2�x���������;�c���m�nt���U[��jk�v}�Ez}�z�����'o�:��������k_��O�c�n-[��@[�?�a(�L���Z����=�u]%	E"MNN�%�=�cS�|��)�{ �	������X
�F��,=�T���eY���
v��B6������E�y��6=���"���Xu���Gu����������#o��b.w����L�@��:����[7�c�nm~�	Eb�9�������m�t��i�?�����a���(��!�c�����@>��l^������@>�;�{�����������rJ������F���F(%{���?�s����~_!��_���7k���z�s��#o����.]<q���sa��.��_��6?��:w�V��6�e�x����k�*�H����*���.=HdhhH�mk�����$���
��
N��A���@��]������F��m^
��tS###�����7A�9�����������T]��7Z�������/������������������Y�����K��]J�kQ������)E+�ps��S[[���?~��A"W�>}Z�tZ����D"mw&P��#>(gT�����(g;�3�����op���BUU}pg&GG��_|�w�i�m{��7Zz�ZZ�����~�����~�Z������T�W��?�s������9$�u`[���D�y�f�Y���mz�LF===h;�}��j4��$�Fr~�����(;c��Epo~�����i�J&�7�y��8�����e��<�5�I=����nQ8S������9�N
]j�{m���_/�|N�u���n5�Z��]��������/��7g�V�X�x<���e�Y�s����=���f�Y�F��3�,.�U�	6D�w\������a%���K�!�F��FpPv��{UV���n"�J���������:}��sf�^���S��:��JCr�:�����������7����3��n��gN�����^���������k�Vo� H	����jutt���cJ����{��e2������"�
������339����9�s�|���D�Ru8$���������^}�o��qG�����D"�H$�F(���������O��Vmip���D�u�Nm��Sc���w�t��jv2s���yc����Ou�W�}�sj�U&jnq�y�B!�\�R�N�RMM���z333�����u�h�h�Z<_�������p6?��iH����|���"<�EBPv��{��7YZ&&&T,=g�d2�mP
��Y���?�c����m�����<��J_��Uz�����?�+:�������S�n������o}Mo|������|�y���O�<7�,�l6�B��D"�p���:�q488���	�����xk��6
ELCy��4��
��&�EM�o|O�"d*�T�_�;�Te�H���L�q�)x����/�Jy�B���x��=���p�s������2C���*V8�M�wh�������?P��W4=1~��pl[�o�����T<�����j��gTS�������m���i����M�W���ijjJmmm���	hC��aj��u~6���Y���l^��?dJ�C?o��XJ���GB
��e��������$�����B����	�Y}}�B��p����u|�������T���F����Y���i��>�������.
xO����52�a�������-��!u>����� �K���&-[�L*���%)������Z�z�V�XA3�{&�,����u5�/j�������_��Ti�|-Pr���X�����i��"\�gttT��z���d��`���.��/���|�����;�W�,KmoW����I�o�+����&G�7�������hp�;��oP��g���9���ps��K$�������}@r�����N�����H$��p��5��
��mNT*��J��J��*����P�������)7��es�|W>��-Y&�>K�=@Y���G�<�{��wh'����&�m��9�����)73�9�'����������xcR���g��O~ZC?{O��]:�������M���������ok�P���jy��,~+k��M�p��N�:�� I�d2���QKK�������hXM�������T��e�W��u]����_:_T�p�������\����4���]�����j���K!Z�,n�1(+���h8�M����MO{���A
�����w:{����0M������Uo���fH-�?���������C���R����_�u5t`���We�V��zF��S]���[�=�0�|�r��q���+����[,u��1555i���2M3�M����j
�[��SW=��
�P�R������Y�q���J
��l���MmMm�����1���|�����D,�x�
�"@pP6��x�/���D?~m{��L&�K��c���w��;������nWu]���/���}J��z���K��X�]��k��'��K���/}G��u����j}�1Ya�`aTUU���CCCC��|#I������Tkk�*++�@�[]SKu��f�s��ThuU�����b�bsVs]W�E{N;�D��L���������*�-(���~�!�&�����/
�#��FJP62��l������u]���x�jjj���
_(o��}��(����o���z����V�S�ijm�}Z�y�f2i�����.��?{[�9}�G��(V��'v�c��jX�z���,
i��
J$:q��l��=wffF}}}Z�v��-[F�8�@<�,���	�U�L=�L��k��������������t�R�o��`_�P�`I�+)S��)�:��-}Q�T"R"���	�d���]FpP6�r�m{����=/�tZ�����������R���/)}q�s������e���%�2��C�����u��A������~$��k���dF�_~I�_~I+6mU�������+%����FUWWk``@SSS��9��'N(�N���E����V,d���
��3#����[�4����B�]����
�J�"J�"s�;����}5�wm[_6������b����Z�LI5���]	�E�w�4q�	�l�����K�����R)���a���!�m�T���:��^��3��[�'���aZ��]���k��_��������9}���s��!�;zH{��em���:v���u-�5(G�XL[�n���gu�����ccc���Rkk���x@(W���>��Q���+�{������{��*�0�X�G,���;���� ��?�BQ����.�P(J�sg!S��A����w�F,UY����=@��k�k��7/-V�bQ�������z'pK�/��_�3���'�����p#!V]�>�Q���Gt���z�t���������5r3�:���t��������[�B�X�n��i�Z�z����|��%)�����CZ�j�V�\)���T
�ck���TZ���w|���
=�L���~DC��UD��������}9�W�����j#�������5<��s<d\j�����/�6��w���{@Yp]�7�w��:�X����q�������6X����_�C�gg<��M���_��V�aZ�q�Vl���>�:���������o�:����1����h��O�s�n5mh��y��%	uvvjpp���%W�9sF�tZ����F�m��B��l�SKM�z��n����"���j���-���4��!8������{���� _�p����hK��J�w�^e�������*+���@!�(�����B#��-�Jy�����
v,Io}�ot����
��/�{E**�
�J��Rx�}��4<8��=]:��W�����BvV��]���Rr]�:w���O)ZY����R��q�F
����r]������zzz�a�����%�r��*��U1��
���H6�T6��5_�����E�����Bu%�>�a�Y!����*���m��d�������
En������u���>C�HH�p������`_H-}@�!�(~m{�T�������&''=g���<7u��A������?���B�[7����V5����������5�vw�|����FjhP�_���}�����C���[+6m���#�a���Y555��<�m[����e��v�Z�B�7P���a=x9��N����������'�P"���.!�Pm4�������j�v���|<U���v]�������We����]�S2�YX�H*��_p��2�&��������d��`)�NO��������-�������}2����c1u�|N;�S�������*;=u��(�s:��[�u�a�u����O�TEM|7����J���:y��.^�8��/^�������TYI�4�`�!�qd������a��B��BZ^9�����������<
�a�hk�h��rs�[������� _m�����%�����bFpPF}�{�����r���R�������R1/�u�����2)���cU���o��L��,�J�Y�]�Q;>�y����z��t�p�m]c��)�������5�=��:v���m��
nK(RKK���e��mL���������k�����Xb,�P}4�z������t���|Q�|Q�|A��f��*Z(E��H����7k�!���j�i�K�-�h��{�����w�M9�������<g���f��GG�|�w���������#Qm��S[w����3���|�������5�BAG���#o�S��j�����zF����[����UWWk``@����������!��i���(��LX��PU8��pH+�k�+8��V���`����`K�4Y�5Y�uvf�{y���K\��	[
�CpP�
��L��!����
����Pccc��`)�pN�_�s�y������
p#,u�+V����������O�ROw�N���k��?����5���oh�C��������>��0K���F�u�V�9sFg�������q���j��
J$mZ�4���1�s�u]M����t�x��Y;�����*�-(���03C�Z�~��V"R"V,�����FpP��sE��{s9����Q�Ymm-��e����P�����n�J���o�J�k����}�&�/�o����MO���5�V��o���7O6�c�������H�3C�W�V"�����������|^����+�j�*�@�0C5�K�v������3'�w%��)����J�le
�NO�m�����
}�+-}!�|?��=@��<�[���p(�m���1��w;!m{�����-]8�93C�~���H�"��P�j����_����3��������������^�I
��������oi��������e������quvv������g��U:�Vkk�b�X@�H�T2Q���>�u5U�=C}��[�r���v^�s�����A����x���aKQZ��y��<��^}4L��uFFF<��B!����
����z��?����C��+jji
p#���e����j{x�2#)��}E}{_��h���������������A�;�U���O.[���RfY�6n���/jhhH��_�455���^������!�-K�i�_�����/g;W�|��2�?��
��O�tu�S�sg!sN;��?U-}�DpP��~�=�
^+��kbb�s���(��	��QvjJ���?�|nX^��=�����M�1��~�3��'?�������.���\���	��F������������s�n�<��B�+�\�a���I555����������m���_�tZk��U��_�-��L-��hY��-}�[�����t���d�O�����uavnK_��������8�{�(#��
(i��j,W��5D�o�����I��{��\��+_���F���������_epCb�!����Z�XS�c:�����K����~�����:�_��Zm{�u�zNu�+nq�$UVV���C'O������7.^��L&���6UUU�{.�1
�j�Z��*k;WC|����
v�-}�+�������l�e�m�[JD���L�������L�(��	����U����b������KA������o��w�������Q]W�G?�Kz�c���������;?�c{�����'��K���/}Gk�;��k�ZyLV����4�~�z%	
�X����f����5k�����p��2CVHVH��93�q�)�m���q!�������b^��k��C��������P_m�R<��C��D��4��=CRm���333�����%�In(�
��������y�3�������0M���Ok;��L&�C��������go�:��zt��G����=�S��W����5Xj���UUU���MNN�����N�<�t:�
6(�����a�]� 3�u5k;s�|W>�*���Xt]��
�n�U[!%"��`�����-}X��J������X�Ln��"�J��iL�\v���}�T��<��+V����z�[7WO���~B~��:{��z�t��[?�]��^�%;����_���_��M[���nm���
Gc�9X
����n���g����3��;11������*�H�!s��J+�J+���s[����L��D����0�D���E7����������3s��
�����|[
��/�{�������jp��8����qE�Q�������<g!��/���@�	��aZ��]���k��_��������9}���s��!�;zH{��em���:v���u-�5X
���U��H$����|>�{n�P�����b�
�Z�J�i�)��LS�Q���Q]��t�Q:_P�`_��r[�L�	t���j$W��u�����������-}�=@I#�ws�tZ�b�s�L&�����z���;����\���������#:�T�{�t���|%��f�u��e�zY����k�6?��"���,f555�����������=���sJ��jkkS,�0��a��Ti�u���\
�]�]�8S(�����4Y�5Y�u�����i�i���'�d��]FpP�f��fm��<�G�xE*��<n���������dF����Er���Z�y���?x+��0C+6n�������~CG�xU=�]�x��m]���1]8�W��m~�	u����
m<��2dY�����J�444$��o!���Voo���_�������	��c5�"s�;������P�5�>��oJ�q�������[�_��^��6b)�w���d����I4�]Q,5>>�9���W(
x#,V����'��n��'����w2Lnd������}Ax�
�wO���U�ggo����z��������u���-;�R��j7��aZ�l�jjj�������sm����������[��c��a�j��j��V]�cq�v����o�rC_&_T��>W�&,uzz�,2�6�]��:���"�(Y�>�����
� %ittT�O{Z2�x,f=?���}�w��7���j��FSK��ZZ��gMG~��z��t���m]#54���~I���Um��!u�������@���P{{�N�:�.�{n*��������TUE�P��!S�PDI������L������+�n�����v^������q��oN��r�/BKDpP��rE�����\*��<�D��������z��_�����#���#n/��c�s����R��.����W���[�F1���}�:��[
���c�nm}b�*j�z@90MS���S"�����U,z��*I�lV}}}Z�f����	���iW�p���em�jC_�PP:o+�/h�`��e�q���-�����"d�����X��B|_(#�%k��q���%�������466r	$I�BA/�T��<���������������u�����3�W��o���Kg���5F����_�K���_S�#��c�n�����^�@]]�:;;500�L&�{���:y��&&&�a�E"�s('���XEDMs�7������|?�]�;���fmG��y]��������������{��Tp�4��gdd�w�L&�������Pjh�s
���~_�H4����!�j�����c����Q�����?����
���yc����Ou�W�}�sj�U&jnqp�E"m��E��������=7�N���W6lPmmm0��C���j#s��u]�RK�G�o*��>����E��o|���2U�����X�����L��D���	�� �w�f�T*�9���VEEE�a1��{���?��������u��,f�+V����������O�ROw�N���k��?����5���oh�C��������><q��d�V�\�x<����r�-��T(t��-_�\�W����n�a��B��Bj�����sMK_an��pK�L��L1�s���Y����[�L}��=@I�<�[���p(�m�L&�|>�9kllx,F3����g�;_�C������4X��6m��M�whb�����@}{_����-_��m������~S�d�:v>�m;�QM=_�(E555�����'4:::�����W&�Q[[�b�X@P�,�P]4����-}������������E��h��Q������g��"DK�b@pP���{uQK&7,����Apr]W]_���A��D���7�7�7Q��������S���O�Uow���'�un�������o������?��:�~^��{Pf�:���,���*�HhhhH���zazzZ===Z�~���d�[P>�P�R�����-}�Q�`���/_T�PP&o����7U�5U�uvfnso�4�����aK!Z�CpP���>,I
�=9������1�Y]]�,�����^��{�������U�������e����j{x�2#)��}E}{_���w����:����������|V;�S<�l7A2C��-SMM����533�{��8:~�������[��q(l�j��7��������

}�BQ3�[���Pp\��
��}rCRu8t5�W��X�
[���p�qG��8���\�sVOpOccc��
�5`���^��W}���1����7JK�1��~�3��'?�������.����yZu�756����o��w��ux@��v���G��}JBEE����u��i�?~�sGFF499���6UWW�!�b�������V^7+8�� ���3���K�\I�[�[g�k�������v�D$�D�RM8$�@���N@��,�*��w;��R)��'���H$��I1����*�����u����e�[��4Cj��a�������t���wO���o�"����5t`�*����3������W,�� �ij������:~���E���HR.�����z�j-_�����i�1Qc,2��smK_����a�t��Y;�����*�-(����/~�������
���������\���!�.R���r��2������Q������o��FN���Y��~���Y�����������%=��O�T_�z�ti�����o���LzB������w���S�v����d�	���������S��W:��=�u]�:uJ�tZ6lP���,	�a�&l�&liU��Y�v�)\
�]��7�/*�H�+]j	,����X����6�WMK�$�{����G,YeL��%��7�b3��w���G�����u5�Z�F@�1LSk;�����4�I���n�twi�����������Q�&�mO�T�����j�m
Z$����u��y�>}Z�O��$��i���h��
���pKp�EC�����-}��j�/}M�/�����e�����9�M������P_��>PF�J��Op�!R��C��*�Jy�***TYY�FX,�'������;�������p#�����'��G>����gO����#���q^����%��%���U�vk�W8[���B0C+V�P<W�r�����bQG�Uss���YC�:%�4��A��em{N��J�o�`�?��9�4���x����D�Rm�R<|��D�R��AK(1�%��q�.Z��������f=g�d��"���8�����f�����z=����p���U[��jk�v}�Ez}�z�����'o�:g���#���k_��O�c�n-[��@[��R]]���N�8qb�FuI�p��2�����TQQ���^��B�U��T�s�v]M^��w%��w���I������.��m�������"���-�0e��6	�-��`�����Y����
��n��������7�b�������������*��7�'V]�>�Q���Gt���z�t�����8O���r3�:���t��������[�B�7��T�B!���*�H���r��gff����u�����X�0T	�62�=r�u����EM��\n�K���*���h����E�]����A����\V29%���������������=I�/����8���D"�H$�FXR'O����W���>�	���/����0�b�f���YO}�7t��W�����'���u.���cz��_����P���j���
o,�dR555��������y��hppP�tZ����e��0��0UX!UX!5knK_V��IDAT�q�)�m����������r�Q�-��l��q�0~���yS_<l�2y�{��()7<������
+�6�����l��	��d2�m��9��' �����e�7�C��+o�vE++��g_��}A�������?zU���[�F!;���.�vw)��E��vk�����Z�������m�6�>}Z��������QMMM���U555m�*�4T
��@<�u5s����������[�����\A����B?�E,��-�#�*h�"�()~�{���'��m/
���>�m����W5z�����F�_�}�����
��4�����UO~��t������K�����5RC��������_���R���Z�i7�������k�*�H����*���s��<���Wk��|���0UY!UY!�����Wpe��� _��P�-;����������3�9�#�q�������������]FpPR���P(hbb�s��� �4�]���O���~���|���
��X�F��p,�����c�sJ������^e��n��|N�u���n5�Z��]��������/�������Ugg��N��=����J��jmmU$	hCP��������XXR�����j�h�i���g�v�1��JeJe��.��T]
�]������{��Qt\��E�Y9�FFF��<����1�mp�M��������������kw�XH�5����/j�g>����Tow�����k��9�W���z���v�k��m4����am��Y.\��S�|��L&���m��Auuun	��a�[�[Zy�,o;J������&��)�X��J�le
�NknK_�4��������j�!��?�ApP2��������{^���jjj����8��?�ce'3����=����JP8��;�u�N��;��=?��W�Y��^�BAG���#o�S��j�����zF����[�6�0�|�r��q���+����[,u��Q577k��54���EB�������-�����xZo����HLN4��e��r�l�-}9�����������j�k�����x]�J�X��y�2��Co�8���hzz�s�L&	h���/��N���>�����j��@��_�JO~�W���E���z����6�?N��kz������U���km�}2���E���JR*����.(�����Mm��4U[�"SiIiI���[������i���'S(�>�o!8��
E����+B����|�K�����,Z�('�%�/�W�����������&�����_�w��?����w��{�
��i�m��C���������'�o��m���7�����'����Ym���j���b
��a�%	�8qB�m��;33���^�]�V��-�A/`���L-��hY��-}��r���t���w���d�O�����5<��s<d\j�����/���H��{��������dqp]W###�����b��7��R�f���P�]��7oh�c��������65�C��9m��g4��w�������u�[�F&5�7���z�����<��������*��[���FUWWk``@SSS��9��'N(�N���E����`�0
�jN���w������EM���*������4�����W2��m���
�P�(����u5��%�G�3��N�U(x���d���^z��_���3��p4����
qC.I!�R������veFR���������Q���������hp�;��oP��g���9���psp3�XL[�n��3gt���y��������TSS��'
)VRSEt�q�q5Y(j�PT�r��J��pK���hf6��7��JDBJ������/�B�h�`Q�m@I�,�*���D/��^*��0C���o�{���7���}���_�M�5�p#KE�1��~�3��'?�������.���\��[���F������������s�n�<�aa��4�f�%	
�>�E����<�U�Vi�������2
�F�������j�v�4�]�x�h��}���^/��Bs�������~`�nI@I���lX-�ow�bQccc����zY&�����~�_��o��C��|:��,E�R������55>����P�{���8|�q]
����U������Q���p�$	uvv����������3g�(�N���U�ht�sJ�a��B��BZ^9�5P�q��&�wm����e�hk�h��rs�[������� _m�����%�$�@P�kPF}�{����i���766&���d2�6���?����������1�g��y�2��R]W�G?�Kz�c���������;?�c���w?3�	���w��K����Nu����G�.��\��p8�M�6ixxX'O���R�&''�������@��LC����=Z�f��� _:_P�p)\���j$W����Nj�!���j�i�K�-�h���#�(	~�{�e��'I�T��x8V"�x�?�����{<g�a����=����
@�0LSk;�����4�I���n�twi�����������Q�&�mO�T�����j�m
�g����USS���~e�Y�s����;���&�]�Vf>$`>�a�*RU8����G�|�jS�D�����>;��>MlMl�����1��!��5������>�Hy�%g,��+���l6��I�����F��[.����������Vmip#��2��C�����u��A������~$�����Kv2��/���/������c�nm���
Gc�9����J:y��.^�8������d2jkkSeee@,ma�Tc,��Xd�q�u5U�������o�v�1��JeJe���c�RK�����JDBJD���x��!�X��E[3E�_`�cp��mO���d���^�gg���@�m{���m�?���
@90C���k��v����:��^�v_#�O��u�9��Gi����-;�R���Z��e��W�B!���(�HhppP����4;;���^�[�N��-�1w�0��/�����;���� ���3���[�\I���L�����-}��9��/|��/$����,}c������{��jdd�sVUUEB��W���=g��
�������K@+V]�>�Q���Gt���z�t���������?|YnfZ�^�������Q�vk��O(�X��@CC����������)��\���'411�
6�����*2�E�����q]M�������l�-}9��E;����������A����x���aKQZ�e��)K�h��y<2Ui�������T�'����6��������w�����j���@�3C+6n�������~CG�xU=�]�x��m]���1]8�W��m~�	u>���ZZi�`�D�Qm��Mg�����g�=w||\===jmmU<hC��e����p��k����� �D��L��-}������qjz��"d�i�������Pz���q��^���IR*��<n�����W�������?��;v������}Ax�
�wO���U�ggo����z��������u���-;�R�����ap[�������u��q��y�s���:��+Wj��U����h������U���7Y�5�/\
�M\��� #}���hv6��s__�)~m�����&-}����`��k�+���m������*.���ql}�������<�l�3��[o��ZZ����'?�k:���������Go���Au�K����j���c�n�����wY"�PGG�5>>>��g��U&�Qkk���h@�fL����������&
��
y�|Q�BQS;��>����E���7�*-snC_�R"V�e�^`Q#�X������/q%�!Z^�����e���,�L�
���?|Gg�����~���F`Q
�b����:v>����K-|��Uvz���Q��tp_���V��5���[[������n@y	����q����u��I���-�������QKK����0�������+�>x�v\e
?�]�+��7St4S���u-}�a(�T�����X��C�h�,��h���|��������J�<�[�����`�A`�;�7�������k��-nw&�f�v}�E��������������}�u��3�����R�������c���[��u��u��0����x<���~�����k������N��v�Z�B�7��2
�E����w-��j�v���|<U�~��B)���r��
7�����j��J[_E��>@p��4�_�JR�0����|>�t:�9khh���eKRnfF���?��8��������R�[���D�u�Nm��Sc���w�t��jv2s���yc����Ou�W�}�sj�U&jnq�Dee����u��I]�xq�s/^����I������p�R`�*��*���W�m�+:�2[��2��|�K�im^SE[SE[ggrs��MC�k�|W>��-�L}���|
��4�+z��X2����###��d2�&���~I����he�~�w��L�-,a�+V����������O�ROw�N���k��?����5���oh�C��������>���c�PH---�������e���*���������k���D�	@	�LS�QS�-}�EG�|A��}���m}3E��-���j$W��u�4$U�CsC}��}1Z�w��`I�k�������u]�R)�Y,���D���:��^��3��[�'��,+���;�i�M_P���o�+����k8�����T��o*�lR��g�m�3��o\��(m����������&''}�s]WCCCJ��jiiQ8\>?��RK_u8��pH+���R��r�����BQv�%}��������3���ELcN;��?�py=Dp���,�u5���5�QpoffF�����d2�S`KP����+�;��������n��mj��~�s����h������KC�������3�a�������-��!u>����� -���h4��[�����:s����������G���J$m��,l�j�E���9�������C}��f�`[����T��T����x�R�r������K��������`��,�*8��[�+���_��$56�"Tj�����G���x�k��k��z1�� x!�R������veFR���������Q����s]G������wT]������c�s4�p����U���500�|>�{n�P�����b�
�Z�J��
���i�	[�	[ZU5w���9�|WB}�|QAF�\����NO���B�����W�C��@!�X����$�>Z��������,�H(���[���;v�sf��^���HEe�[��oL��_��>��Ok�g����K���#���[���F������������s�n�<��BVy���n��������������=���s�d2jmmU,hC��H�T2Q���o�p��o�r������[�������pv�C-L�RK��P��`_��>(9��X��r���x8�p�<�bbB�b�sF�^�9{�����o�����jy��7���4Cj��a�������t���wO���o�"����5t`�*����3������W,����������/����r�	�OMM���W����gX�o�a(��XZ}�,k;������J��,�r��q��|Q��t]K_E����/�Tm�d��K�=�����������k�3MS���o������������7������?���������^�~�����>�S}=�����w~,���{�IO�����w_����w�c�n�>���p����N����&���h``@333���������i�[�N�P(�MP.b!S����*�������B����|Q����w���I������.��m�]i������,`�"�X��r�7��Kp�P(h||�s������%�u]��+�L���<ZU�����4��9\�0M���Ok;��L&�C��������go�:��zt��G����=�S��W������UYY���v�<yR���7��R)MNN���MUUUm�r2�F����������Z�<B}S����4�/j<���*-S�aK�HX�������J����{�%)k;�.���r	�����u�5����6XH�^���o��;�_�����7���2��C�����u��A������~$�����%;����_���_���[��k�6~�q�������4M�_�^�DB���*��o�������f�577s�1��0Ta�Ta��\�3+:������
�����:w]K�e�
}��%��u6��`I���`�P&��T*�y<�(��
�����������w>���P���g�Vmm�������u�������FN�����=rHg����}Y[v<��]��l]�m
��V__���j
(�������N�<�t:�
6(.����tX���hXu�[�fmG��2��&.��2���|F�P����\A��O��B����-}p��,I~��X�TE�x�����jzz�s�L&��j���E}���Bv�s^�|�v~�7�
JK��Z|�������|�Q�����7_S1���k�f�u��e�zY����k�6?��"�����'�h��-:w��N�>=�����Qkk��D@w�0UZ!UZ!������Q�`����rC_&_T�
��o�hk�h��������1'�w%�[
��w��`I���G�eZ�k������7�B��w�Z��z����_�� w�aZ�q�Vl���>�:���������o�:����1����h��O�������Z�O��ah���������W>��=�P(����Z�b�V�Z%�,���4Y����������}5�wm�o���c�q5�+h��������������x�Rm�R��>��=��������6�u522�9���VEA�Rp�P�������?������5���|D++��g_��}A�������?zU�Y�T/���z��������u���-;�R��j7`����Qgg�N�8����y�=w�����������Xx�a�:l�:li�u����	�]�8S(�����4Y�5Y�u�����i�i�KD�JD,��C2	��=��c;�&�E�Y�uO*-E�L��� �L�
BvjJ���?�\����i����D�[@yjjiUSK��������_Sow���{���I

���_��o~U��HO?�7�4r@��,K���J$���7�LOO���W����ie!l�j�E���9�\���/j�r�/�/j���/����-�b�����������K-}P.����|Q~-��^*��<n��w���z��_���w�b���������U����mim#��l�����X�
���d�@ 4		\��]���Mn������>��I���M��RJR���lb�H���Z����F�Y�������3�d������<z4s�_���Y��������"��&"2�b���f7�jvc��
��p��~�����	���z�:X���e������5�;]X9Qr���p:�hnnF0L8W�4������b���$��J�������(p*2��������������[�XD���>��%0���c6I�
�]�s�K�!���(����q�K����K��i�;���
YN���4x��I8���_�3��%�����e�Q������#h>v��u�:�4�}wu��S���O���M[PU�K�U�-Zv����Ggg'���f�;44�@ ���
8�*$""""J~VI�G���K�XT�
��.��g�|�B���A(�].������,��GDDDDDDDDD)�W�Q����e[��_�sxxz�/P=����|�����a���;�b���&VDDD3Q,VTn�A����t�q��8u�UL��g�-��#q��Ad/)����X��Nd���p""�$%�"�/_�����V���pn(��S��t�R,Y���w""""���0��.�i1��.��j0L�Q7o�b������EF�E�K���m��)K�,@DDDDDDDDDI��=""J9�:��X�+1���P������v�\
�'M����|�p(�xNQ	v<�I��""���)*��8�>����
4��������1����O?�#��������{QZu#�+���������j�����O�7�����|(//��bI8��������Ilv	vk�v�006�;��`_D73�Lh:&&"�����'	���Nw>����e����%���(���h�{�p8������dJ;��G[K�1I�q���j3�*""�+YQ�z�6���
��>4�M�_��wt���5
������Q�<����u5w������%����k����]]]0���|>466���YYY�IDDDD��$A@�EA�%��7�0�t�"*�Q��.y������Z�f�����/S��)rL�/C������������L������!�`�kz��
&�x<&VB�����x�?�p����Q�(7�"""�Y������������7�X_���o�0�Y��?��#?�	���i���T���7n�(IX9Qr���p��hnnF8N87�����X�d	�.]��m������ �����B�v�Su�hlw�K?��q,�qU������#dA��;�;�>�"C�#""""""""����	""J;�����q�0

����@ff���|���7��{ ����7a����\�'I��r�f�����A4�M�_��p�P�t�����q��8GN.���BU�n�<�X9Qrp8���B{{;���g���������
��v�*$"""""�E9V�����@p�K���d�o��.}�a`8�p�����M�d)2\vv�#""""""""�k����D�=�"AI����B�P�1v�K]�a����#q��N�~�@H�����W�[>�n�����[h��C���0��w����_�o��,��fT��A��M�d~�'"��%�2***������v�3�v������+V�@^^/�%""""��A@�,!S�P���/���G�� _��P���.}UC@�����g���|Y�u�sZdH��ADDDDDDDDD3�U}DD�R��j����mw����5��O��uhy����{>��pd��X�E%���e7mD`t����}u�
��~'����'�q�2�YX��N���e��&""��A������@KK�����u����z�X�bd��������"������)���m�U-�;����6�E��CD70�b0�������^
�]���&I��HDDDDDDDDD��W+QJM�q/��{��cxx8�XVV,���|������x�����6�X]/�����a�}����
���r�u�Z��	��x��g��s��^PW�8�._������#���u���������q���0�***�t:M��������-A�Pd8���"�_T�?��{Y��U�������j�G5\@l�>�(�m���(1�>�"Ad�>""""""""�E��=""JaMG@����Z�7�7::
M���=����|P�Q��O��	��-Y�����U��&�"J�oDi���}8}�
�u����~&�{0���A�����������T5��!�"JKK�v�����h4�B?�q��i������/�%""""JiI�G��c�]�R7�Zl����!����u!��������]
�Q���?""J#	����qopp0�vI����mr54^��S�h�;&)
��G���jrUDD�L2\n�r���������)4����7^�6C(a:=F���A���A��JT������B���r"""seee���
�����|	���.����������������(pYd�,2�f���5=&�w��Uab�>����*0;fh��!EB��!��UQ�2���*���(e$
�YE�hr5��D"�z�q�rss!�����Y�������#���?�8<���W%5APR�%��Q���8}x?�_����s�O����>{���!�n����=�_^�@U��b�`��5�����`�/����hhh@yy9�!""""ZD���|���+���E�� _��v�wDEX73�����tA�t�zC�7I���/kZ�>�E���
�����������{DD�2�r�2�4]erxx8����1��A�/}��	�W�tn�{��Q*�9���{q��{���6�����CP��Y�#���p��V�BU�����}+'""Zx� ���.�---�B	������~���X�l�!""""Z�DA�
�������t��EUx#*Q��.}�x#�=]�$N�y�/S����S""""""""�T������=��J�388w��f���0�z7�@���������,����KT""�*AP�j
�V����?��G�����s�O_�9������~�5[��z�^�U�����R���@UU���1444����>��~�\�v;C�DDDDD�&I��%��1�5��XT�7��?�������/��ND�;��.	�	nE����L�$�\�����������4�QJ�#�*��������q���cyyy��>��������	��~� ��e^ADD���a���a���ok����g����_� �hh��uh���gy�k�`���fd.`�DDDG�$TTT ++����4-��`0���F,_������������$Q@�UA���(
����O��.��P.Y�a`$�b$|���������O�$�3�<cp���R�7�BO0���f����gb%�n
]8��?����7��^��q��Q:*(�����K8�_�Y�������6�?�}��X��vT����Ukx�����<8477c||<�<]���������2�2O���	��YB�,a	b������a��n���]��U
����c����,��d�/K�x����E�$""""""""�����R�H8~�Q���{93#ap��r�f��\]+5���
��H�q������#�EDDiM���W�U�7��@���p��~�����	���z�:X���e������5�;]X9����lX�n������3�����\�N���
�����h1�E9V��I
�@P�����������,6�Vt��`oC5������S�����Vd������������hF��t "���(��mQ ���A^��h���n{����Ob��#���X��?���-s�""�E#�x)�?�(�=���Ec}��4�i�]�8���8��'�r�T�����*^�CDD)CE,[�n�---	?o@$��S��t�R��������� �T$d*j�}�Sc����f�������Ov���m���������`l�>�(L��.�9?O1�GDD�!Qpo����bpp0�vQ���kr5t���[����L8~���Dn�2+""��J�XQ����j0����}/���W11���>�hg���#����kvc��;���Z���������Fuu5Z[[��zg�{���|>����j5��p�K��fA�-vH�0P5�'�|��`�/�bB�M�1�E1��.W�d����|
�	n��$�Z#����%=�0f���K����;���I�L�����w/}����r+n�u�yM�)*��8�>����
4��������1����O?�#��������{QZu#��QrS�W�F__:;;a��T��~466���999&VIDDDDD�� p*��g��E4=&�w��?�B7�K�����j�0���*����K]�$���GDDDDDDDDi&��DD�v�U
��$�c����������\
]�0P��@���;������~�|$"��HV���
�7o���M�_F��W0����@<�����Q4;
��U5����N8s������� X�d	\.���
��UU���CAAJKK!2�NDDDDDI�"��Hx�u��
������L���th�"1�E�� _�E��2�[�ae�>""""""""JQ�Q�N�mr,�����b���v�\
]����_h?y"�����d�������GVA!n�al��!���M4�����[0��_�������G�4V�|�w���7@d�`""JR������BGGG�������cll���0�B"""""��!
\�a������5��}������:0u����1�$�t����)�K%7���(��������K���
�������C[
<��C?y"��-����o2�"""���d+7n�����D��W����
�f��a�h;qm'������5�PU�.O�VNDDtm$IByy9�n7����iZ���`MMM(--E~~>?�QZ�J"�������7���D��|��`]D73�Lh:&&"�����'	���0�e�vL'"""""""�$��%���S�=�x<&VB�"	���45~�4y9n�#&WEDDtm\yl��C�����o����'���g��/02�7~�3���g����Q]�e6A�y:����K^^ZZZ.������>�eee���FDDDDDiJ�����@X����;��n}��fj�>�F#*F#W~7�!���n��LY�B,DDDDDDDDd^U@DDI/ap��^�=�0�233a��M��������pWg�1�b��_�$9���%"��'��n����6"0:�S^E��:��g��@���8y�,��q'�jw#��h�
'""�#�����Jtww���{��###������2�B"""""��O�d	���B�5fL�
����.�EM��Tu�z�u��.��,E�k2��e��R$���GDDDDDDDD���=""JjaMG@����[poll�H$���%������_H8^����[���������#;���C�t���lj@��:����l<A�o>�,�|�Y,[_���=�����^����(5����K���r����h��� �����())Aqq1;6��'���
��}�k&4=&�w�v����j	G�.��%�-�T��R�>��.}DDDDDDDDtm�#"��6I|�\�5�^�u����&WCsA���1�x������cbEDDDKE�V������p�`=��0�;sw��:�������u�kPU��%����v�Q]]���6����8���>��Z�3�%"""""Z�A@�,!C��$#�s����G�wB}��T��.}UC@���lWD���|�n���@%�^�""J;�V:�( S�L�f�h������cYYYP��&i�����mL����;rr���/pN""J[.7n����p���}������A��C�t�1?N��N����T��vV��������LQ�Z�
���8�<�.CCC������cb�DDDDDD�ME�XE����7���GUx#*|�(�������ZcT70�bh�w��"���&�}6v�#""""""""0�GDDI.Qp/����������_0y<����8��s8��������>���;]�EDDt�����(�\��G�����X��.���~���F�������v�T��A�������hf� ���N�---���H8W�4�;w���(--�$���CDDDDDDfE�C�P4�K_T��������GUh&6�3�E5�E5tM��g���|�~\�1���&"""""""��1�GDDIm8����kM�t���q������,s��Y�oo����-����~��W�XQr�9���{q��{���6�����CP������pp'�^���PX�
U�{�f�vXl�����(���L�_���������s066��+W"##��
������E�g� �f����U��P�e��	��.}��`(����]�\��d�/k�v�E�UM�����������{DD��4��7���^�����|q���� ���&EC!��O������������U%AP�j
�V����?��G�����s�O_�9������~�5[��z�^�U�Uf""J~�$���n�mmm�4-����	466���|�""""""2�(p*2����������t����GT��3��uDU\��Ibl����Eb�>"""""""���%-_D�n�K�����P����<+��8���0��wL����/~	��>���[�����n���n����q_��v���Y�#�@c}���Y^���=X�m��W�c""�y�����������%�g:::���PVVE�gD"""""���"��Hx�t�D/v��N�.����/��i��"1�E�b���P�d���.}DDDDDDDDI��=""JZ#����Dp[��%�0���=����L^�����EC�K	�k?�(���XQj)(�@AY���'p��Ch��Co��s��`G���>��	��|;�v�E��5�hDDD��Z����DWW���g�;::���F�����v�T!��(pYd�,2�NizLw�����jH�����
�Q�����.}vI��C��"�!K<WJDDDDDDD��#�@DDi)Qp/��@J�/���1��������)Ihld/��w����
�v�ibEDDD�K��PU�U5�1����}u8sh?B��Y�C��q�`=N�Gn�2T��A���������K�.���FKK"�H���Hg��Aqq1JJJ�y������(�$6���.}�a`l*����fF��	M��D}��I�K]�,2�,��m�E�"�K�Y�#"��5� ���&��`pp0�X^^����l����|�[���;s=�����L""�k��l9jy�z������]g������Nx�q���X�i�w�AIe_���hA�\.TWW������3�������CEEl6�I�|�YY%f�a���	�L����hD�hD�b,C���p[�&�}nEF�,�\*�<K����0v���*q��]�1<<w��v�b���������p�!�� ���
��arUDDD�E�XQ����j0����}/���W11���>�hg���#����kvc��;���Z����hQ�e�V����:::`�/�hllDYYrssM��������� �����B�5fL�/���
�EM��Tu�z�u��a�+���}.E�,2�GDDDDDDDt-�#"��4���$��"7M�{^��z�
���xL������G��q��[��A��]obEDDD�/��w|�����G���7�P_����s��ho?�$�<�cT�r�v�Ai��Dqa�&"�EK��t���	�j����f�|>���B�$+%""""""����l��l��]�&4��
D�w2�������5����p�q�u�R�P�]b�>"""""""��0�GDDI)Q�=W|����n�$	���&WC3��&��w�]����������������YQ�z�6���
��>4�M�_��wt���5
����cG����f���	gN�VNDD�QFF���p��y����8w``~�+W�Dff�IQ���YBQ��.}:|Q���|������B@�P5t�1�Q�	�]
����1�GDD�)Qp�!K�J��%���������J�If��?�hoO�1������eH2�V�!���?�06���~�&���q�-�>�}��q��?��_<�7����{���
������(�X�b�n7�����j���PMMMX�l
����������("�*"7N��qU�
�]���?O:����pC���8	Y��!���B}Vv�#""""""�E�W�QRJ��I�n{���0����xL��f�����i�+	�w~�3�*(4�""""I��r�f�����A4�M�_��p���������v�89�X_�U5����/`�DD����� 33---K8�0�?>����P��8�ADDDDDD�O8EF�������.��GUh&6�3�E5�E5�]������mQ���p*D��������(�0�GDDIi$��������[�V8�N���D�Cx���$_����VcbEDDD�+��-|�}�t��-4�����q��W����_�o��,��fT��A��M��KDD���jEee%������5�\�����TTT��v�T!�E�g� �f���_��oZ�oB3�K_X70�b te�>�"���
�]��GDDDDDDD��x�%���O��w�k��t�A���������U���k��w��p�W.O���g�����(������6���������W���������0�q�:N�@�;�v������.,Z����(�	������n477#�$��Fq����������������NE�S�Q�;�t��*��B}cfF��b�0�����I�T���P��]��������(��~�����N�n{�������y<+������:�wLD���/���w�����?Gvn}�����������}uh9�:tM��>�>/�|�Y����X��U�{P�id%������t:Q]]���6����8���>�+W���f3�B""""""Zl���d�'N��������OX7�K_H��"��.�#
�u�SbC}v�#""""""�$��%��p���E�)K&W3�����`�1�����Do��8��O8~�D���&VDDDD�JE�V������p�`=��0��=��t65���6������v/rK�.P�DD��dY���+188����3\�8>>���F�X�yyy&VIDDDDDD��(SA��B����������u�F.v��.�p[ddYd��������]���������$�Q�	����cUR����C4?����C8����N���m�������h>d������c�=�C��Sh�W�so�-���xBc~�x�9�x�9��DU���m++` "�����p:�hnnF0L8W�4������a������^��������R�M�`�K(�[c�k���i��.�"���>`B�11A�Dl�>I�V�w��Yd�.�Ed�>"""""""�_�Q�I�q/���\����]����\
���___�1�=w�O!�"I""��&J*���r=jy��Gc�K�p~N��>{�gOc��?��m;PU�����j""JGv����Ggg'����dppcccX�r%233M��������h�$A@�EA�%��}�0��� �7������L�a`$�b$N��Ly2���1��IL�E����������`p�����n�F�3���*FFF�����@���|��9r��K8��S��;�������h���|���i�=�m~���p��!�������d�8Y�
+V��v�l������Q�E��/���Fkk+T��/	�Bhjj��e�PXX��������(%��,�.K(Dl�>U7����GTx'C}��`�j���o\�0�j�A��aY.���N�����E~6'""""""��� "�������{O�����t]�;���gr54�o��>���Wn����w�X�I�Z��Uk���O���h���@{�����r}-�p��a������eV�Uegg���---���	���������������*���������,
��*W\`����]������v�S
��(��W.B����o�'K������K��=""J2#qNt� ���/[���q�+����,s�������|��`�qwA!v~��&WEDDD��5#7��7���m-h�W�3�@dbb����&�X_���:x����v�n�kF�VNDD��b�`��������f����������r�W """""��#2e	������.}Q]�?�M�����4h&w�����`l�>�(Lu����[��"Cb��������h�H���x+�C{�|�:
all,�X^^W������3�9w&�� �x���=������(�U���w|�8��!4������9�c��
�O|�Vo�U;��h��$"��A@qq1\.ZZZ���F�8{�,�,Y��K�BE+%""""""�>QD�MD�M`��n�U-�;������ZcD70�b0{
���HSA�����$���������h�1�GDDI%Q���br%�khh(����1�����i����%���?����M�������b���f7�jvc��
��p��~�����	���z�:X���e������5�;]X9�*�����*���cxxx��������X�r%l6�I%A�Pd8���"��d��Q����[7�I�����j����z���E����������$���(i����w,��{�a`pp0�XFF22���z	���w�	����b�������\%��e�Q������#h>v��u�:�4�}wu��S���O���M[P�sJ*������b�����
��nttt@�wGCCV�X�E����������H"�$�l����d�>�e��.u����/������O����o��UM������������=""JAUG8�h����q�x!��c^�����;n���]��S��dreDDD�*���jP��#=]h��2Nxc�Y�C�Fq��A�=r�K���f7������+���R� ������Dss3��`�������>���/�,�+""""""�����"���X�;��� ��T��M��S��x��]���eYd�,g���GDDDDDD���=%��p4�X*�u����<+���9�g�L8����<+���hvr�Jp��?��|��}
�u�l<9�}������O��3?F�-��j��V�A���DD��v�_�.\@oo��s���066��+W��p�T!Qz�J"�������7�&�tQ�����a��H0������"�]�d��=�[��s�DDDDDDD�ap�����H$~p/S�`�R������;���EI�@b*�������'__��n�������(]������a��m����i��h��
�������i8w��;��U5����N8s���b'�"JKK�r����
UU�
��8u��.]�%K�@�*�DDDDDDD�B��`�iZLw>_T�7�"�L����7r���eH�T����2e�����������{DD�4u�K�n{###�4-����nn����x�;�Ddb"�x��"�<��M������QVA!n�al��!���M4�����[0}����������xe6��vV���$-`�DD�����Q]]���V�|����@gg'|>���a�X�%""""""�w�&I��%��1�5��XT�7��?�������/��ND�{E�>n���\�mQ&�}dv�#""""""�&�Q�N���������P���$!;;��j���O���v�1Q�p����nrUDDD��$Y�����r�f�����4�c�����a�h��1���9�X_�U5����/`�DD��,��Y���^\�p���"?���������|�u ���
��-\l&4}*�wy�������F�*F�Wv����+:�eYd�%�]��������f��I""J+Q]�X4�I�T���D��z�����B��t��:��7���	��>���4�""""Zl\yl��C�����o����'���g��/02�7~�3���g����Q]�e6A�y���h�EEEp�\hnnF8N8WUU����(,,��e�x^�������(	��YB�,a	b������a��n�3,���U
����`��E��|.�����NE�,2�GDDDDDD�+���()�$���np/Q�=�x<&VB
��w�H������x��M�����+Q�Pv�F������:�*���7�?��:N�@���pga��;QU���EW8%%�����j����x>�������r�J���8ODDDDDD��dQ@�U���	�0T��}���M���
���s��S��B}�w���K-"�QR	�q�+��,�\��gF��l6��-n�a����������6�{?�'�m�����Gvn}�����������}uh9�:t-�{�x�>/�|�Y����X��U�{P�id%5� "���$	p��hoo�>C7�`0���F,_�����A��H�T$e�v���:|u�S�7��?���m���������i]�,��EFL�B�� �C�M�"HDDDDDDd���()$���cUR���`0�`0w������Wq����������3�""""�+	����QZ}#�~N�GC}F{������t65��ta��T��En�������������Dss3�����ummm��|X�bd�_�:E�g� �f��n��d���n}Z��BD70��F���s���s4tYw>n��E�M�"�DDDDDD���M<%���{�hp0~g7��c@�L��������p�z�^�����������.���-���y���B��:�{�5h�����	��q���p���P��U�{����P���������f��u�p������8wxx�@p:�&UHDDDDDDDfNE�S�Q�;��� �����
��&xT�?���xl�>�$���S��,E��"��H�p2%1������
���=K��t]���P�1����jrE���F��?}�p(�xNQ	v<�I��""""�=APR�%��Q���8}x?�_����s�O����>{���!�n����=�_^�@UQ2E���p��hmmEt��w8��S��t�RA�oDDDDDDD��E��,�L���Q-6�7����/���"Eb��\.EF���`�K�ae�>""""""J��u�������cM��*��UU��y<��Y��������wL�d���/C����������7����o�q_�=5��O
�q����{��PU�k�n��f_�����z���Buu5ZZZ���f�{���|>TTT�b��8����������(CqK�u�k��.u�3�It��
oDE�x��]/�.������������������zi""J;���+��R�����`���("''��j�����_&���GQ����������� (Z�E��`�����#�P��[�����s�k9�O�k�nG���((�`�%"�4�(
��Y���>tvv�0_B���������rdgg�X%�
�$"�nA���.}cQ
�H��P�w2����������&b��I��<�w�mEd�>""""""�_��u7���������hXUU��������$I&W�8M�������@�K�o����3�*"""��g���
���
��B[����k����>��	4�������e������v���y�?&"��!�,Y�����f�B��sUU��o����B,[�"/Z#""""""�Ya*w9�0�tx/��7a 0]�&.(��hD�hD�b,Cc;�)2����E���������0�GDD��H�����cM�n{���	W��x<&W�8�����;���;]�����Q�)(�@AY���'p��Ch��Co��s��`G���>��	��|;�v�E��5� ��(�dff���
�qn__�~?V�\	��nR�DDDDDDD�nA�M�P(K(�[~���'��!�,VT��Y�
���*�&w��:�j�������EF�"�5����p)d^{@DDDDDD3`p����+�00��q/�{�.x�X,p�\&W�85��C���'���?�#;����������l���������@��:�9�������F�8u���#�d�j��r{
�N��%"J�$���n�����4-��`0���F���"??�an"""""""�W�a@�Pl��r9����	M�	�]�P��X���-��oq���}����{DDt�Mh:B�w,��{�_�����&����O>�p��=�A��M&VDDDDt}�-[��G���A���h��C���9�c���z��$Vn����{PRY���DDi //�---	�i���hoo���CYYd�_-����Y��k�����G�wB}��T��.}UC@���lWD!&�w��K�!�<�NDDDDD�X��u""���t�R/�744�p����X���F�x���	5�;�[��?�q��""""J����m5��V���.4�{����1����E�8{� �9��%EX_��w��w��NDD�f����]]]����q����V�\	��9�\"""""""��"�"r������qU�?��Q��D����FU���J/��n`(����bE�
�M�l��GDDDDD�v�#"��j$Ap/S�`�D���v�a`pp0������n7������=�����c���=_�2�5�8�b�ST�;>�ql}�#h��h��Cg��9�c����~G��1*n�
U;����Fb���'"�w���e����v����h���"�N�:����b2"""""""J� ��Hp(��u������|��
��&}��������i]�,������K�!�QJbp�����D��kj�D��~D"��cyyy&W��t4�'��������c���0�""""��'+
Vo�����������/�i�+���z�����#8w�\�T�����;���{`"�T�v�Q]]���Vx���vuu������V+�!""""""����"�l��,1�u�������,�7����/�E1��K�K����eM���������DDDDDD�Qj�"��(�$�)&W��$��'�{,���������+n�����kbEDDDD�'���?�06���~�&���q�-��/J��������xe6��vV���$-`�DD4�E������������0/9?66���F���!''��*����������(p*2����������t����GT��3��uDU\��Ibl����Eb�>"""""�$��]7Q]�?�����NpO�4��������,��v�����c��0�,���C��h"""�Y�d+7n�����D��W����
�_�"�����ch��18rr��f�jv���_����h>	����B8�N477#
%���*��;������B��;��$�#Y����/����;��t;lr����#�E���l��]�bB}��>����I""�nF�j��T��722]������\����W~�������#3+���������+��-|�}�t��-4�����q	���������3X~�������
� qq"��������*�?3����������+���aR�DDDDDDDD�.��E��ic!M���w�vcQ
��5�����FT`Z�>�$^���m���%.�LDDDDD4�x�]7#�h���(��H&Ws��w�en���j���q��%����b�M��XQzE	e7mD�M����q_|����a���	t�<�w���U���]X�p����$	eeep��hkk��i	�NLL�����/G~~>/�"""""""�E�&���-(��v��cSA��`_D73�Lh:&&"�����']��g��e��n�-2�]���������{d�P(��G�������bAII	n��V������Z[[q��qtuu!� ;;k����-[`����8f>&�t2� ��cQR���p8��w,//"O\.5����
��H�q������#�EDDD�8�sp��>�M�����4��C����k��iO�y��s��������������M[ +��u��h1������@ss3�@�y�a���^������e���������  �� �{.�0��]����&w��`4�b4r�9�YD�"�mQ������2��]��|�����k<��c�����G���O��o��c���'����x�96l�_��_�����������5��o�o��V�q���Gy_������w��1�1��D�r��s����P�1��cb%������`gG�1Y���/~��w������=AQZ}#J�oD������h���ho�����������.��^�����-Y�@U��e�Z�n�:tuu��{�����Q444���.���
��������R� �����B�5fL�/���
�EM��Tu�z�u��a�+���}.E�,2�GDDDDD��������?8c�N�8�?��?��?���9�.��0>��O�����g����~�<��}�Yl��}N��{LD�J7�F�R���0�������0�����w��[�����w|��[ZjbEDDDD�[���[�}?6��>t�9��}u8��k��������������xM%�j�`�m[�XmX9]A�t�R�\.���"�$��Dp��i��������,
��*��^��oB�����GTx'C}������Z�jG1g�n�,�
��%v�#""""��#5���^{�5�}�����������+V`tt.\���s�����B ���>;�������s�=�]�$,[�n������|Sc�����������b���I�����?�BK��W�t��Bq�<�__��Q���H8^�an�}�y�APR�%��Q���8}x?�_����s�O����>{���!�n����=�_^�@U��r�����B[[FGGg����
�����
X�����A@�,!C�P�1�K�_T{�;�d�>D�j���/�j�������(��.�\��]������(�0�G�o~�����f=���hV�FGG����JKK�����x�{�;j�����������������W�����m���������o|�����?�i��_��T���������������}MMMp��I�����H���@�eI���L7���L�dq0u��}����Y����?b`����(	��|���i�=�m~���p��!�����xR88��u/�d�(�X���=X�u;,6�VNDDs�(
V�Z���~�?�������eee���5�J"""""""��CE�ZE����7�jSA��C}AU7���n`(���k�EB��b�/��P��]������(E1�G�
6`�����o|�������b�
���kW�JJJ�����-�W��������/|�cCvv��������;f����������b�������}��in��vttt��������{,iQ��q��-2�X=K����=��
��brE��w/��O�H8��s����DDDDdAP�j
�V����?��G���%���i?}-���r���l����{QPV�/����� (,,���Bsss��g�i����f�|>���B�$+%"""""""Z�A�C��PdO��zL���mT�fb�>�XT�XT��Ub���-
�NE���
�����(�1�Gfpp���wb�=���3v���?�s������C���o~��W��������blll��������|%����b��G?��w�9�����6���/�������(��&���cM�n{����4-����1���7x����_�o��}X^}���\Y32p���p��������}u8��DfxL
M�����u�,/Cu�����������f###�������1000������������|'"""""""��QD���<[�"���]���&4s���u�(BWv�s)�;���`��.}DDDDDD�?������~�@ 0u�����s��#�����l{��'`����u����a���������;w���m��������?���c�c"ZFR<�����$I���1�������?}Z4�3���q���\�e�������c����d��9�c��
�O|?x�a���o���3��MDt�I����2�Z�����&&&������>>%!Q�Td�d��.��-Y��$����B��4�d�:��e�6�-���|Q��!4��Z�/t
���>���/^��~/�F�0�?�B��("""""2;���y���b���������`��hoo�����7�������?z�(�����a���:�'>�	>|x����k|�3�I8���D�����p����E�Qx���c���E������<�����c������%�J��wCDDDDWRl6T��FU�nuv�a_����x��<I��q�`=N�Gn�2T��A���������f������L���`ll,�<�0��������2(�|ODDDDDDD����d�'N��������OX7�K_H��"�Eb���e]���N}v�#""""�y��-�@ �C��l��{���V�y��x�����=���	Cn/��B��]�v]����s/w�����#33���f>&�t����X���ihh(�J�yyy&W��ZO�����|�S�-^jbEDDDD�P��-G�#�b�C����Q4����L���1���O=��?}+7mA��=(����y""�?V�������FWW��sGGG������
��n�*$"""""""��&
�Tn������,�7�`f<����z��]������p)�-22e��5�5I�t��S�N!}'��b�
����n�r;y�d�����l�2��a������D"�>}7n�b����(�%
�e�"l�dr5s744w��j���4���A���!�x������������������m5��V���.4�{����1����E�8{� �9��%EX_��w��w��NDDW%%%p�\hiiA$I87����3(**BII	D�����$�f�P`��l�c���]
�Et3#}���cb"�����X� ��H�t���p+
\	
�c���)�pmmm��(���EQQ222���3g���������O�?}�}�K��K���3�1��D���br%s1>>w���pu�yb�:^���^������G���tU�a@5@` a�L"""JN9E%�����>�������:t6���>F{{p��'q������P�sJ�n��/���L�r�P]]���6����8���~���l&UHDDDDDDDD��$��(��v��aizL��Q��^��g&�00Q1�K_�<�S��`_�$��"""""bp�.���>���6�B����,c��
�������~�gV�{���c�/]�tN�L���y�B�+.����@gg��kz���/�c"ZF�W���k�������XIz;��s8��������>�'�;]�E)c82���3�b0��HUxj�W�.x&
��.���������
]_��`��mX�y��}h��2����q�����k�;�s����)@U�.������'"2�,�X�r%p��y���pn @cc#V�X��-DDDDDDDD�� �����B�v�Su��
D�w2�����&/�;�jW5� �]������s)2d��>""""����=�>}:�vUUq��1;v_�����/}	_��� I�����_RR2�z


 �2T�b�G�u���8f���PL�EQ���?�cM����m_��D����_4~p/7��{�a`hh(����dw���������p|�{?�e�o0�"J���8�;��pW�9#��P'�C�8�;�Bk	nr��ee&VJDDD�FVA!n�al��!���M4�����[0�������8�����/�F�������7n�x��DD������8�N��� &��iZZZ����|�����&"""""""��C�X�+	7�K]�.�L��Us������p���c�K]�&�.�;����h�&&&�7�78|�0�����#��@ s?33sN�v�ccc	�o[FF��?�N�-�q�m_��4W3v����%�~ �����Pj���B�$>	�D����<Y�,�����9�4�p�����k���y�e���^���a=��#8i���i��]��@J-���V�\"Jm�����
V�C��u������#0>2<��7��=���CfVV�~V���\v�M|�#J]��-C?FGg��:88�����b��v��K^|�#����yD���y��>��Brp�@�Ml
�a ���t��:�Tc������HP5T
���.}�8eI�S��������<>�-^�q�0�.�1A�y�f��=���M��v�Z���@E�������?���C(������s�=�p���o2�������83�s��5����}�{x�����>�?����w]������z�P�(Z~�����������nw���
�������tm����'�� �����6�*JfQ[�e]��ww�|�����V%d������?���]W���{��o=���N`����#������=��XRW�d�B�,�����R��j����8��m$A[[���]�#>��b��<"Zl��GD�
���z�������j�f�O���P,��5������;`#aH����Hb8t�w���)��yo������%�u���"�{�n<��CX�jU����"��{��_��_����#G��_x�|�{������y�,����Zc/�����n�1�XD�L�e��.��I�����/	�B�����v�[�&�l���mbE����0F�/����O�]�0R~9�K�#""JQ�("�x2��A���v���P������	�v!���f��l\��aq��(�B��������� p:��X,��|<CDDDDDDDD�B E#��(���1C�Yl�������?�
0s�?A�n�A��uf���� �T�/N�k��������-[��znII	^}�U������_��������'>���+C8�;RE"�9�����������},�t�&�I��^-�f�A�������S��8����c�
8����iq�%
�e]�����u��u!����������(5�������7`�����tu���?h�	xO���������5p,]A��"����:FGG�������pqq���\���k:GKDDDDDDDD4[��C!O����+���|��o�j�!+��h�
TY2����]����!��fj�DDDDD��{4+6�
O=���]U��Z}``/��2�������#����Z�w���O3�c�������,>����oZZZb��m��	k��}��Pj������o��	�����0<70wl]�2�X[nJ��������BY��e��/(������w�#����9�x���9����9����@=����H�
��lq�,������|�G�
&��h~�0��_������=�:Xy�6��^��%�T)�����O0Dww7��h�9�$!;;������_T�e��GD�	���h���-6|��t�
��:�4���c���f�0�A�n�C��1�L�U��8eNI�c�w�$,�smf����u����]]G���UTT���}/~��_Mm�mpo|<~P'�0�)�a��><N�m����zLs�������w�������k�����i��_D�����e9��YL�c�B�P��x<��n�+J/��{=gO��|���,)2�*Jf���8iY�cDZ�V�FiF����f���zD���r������x�gN�a_�����!��4��4����DU���|;�u+����Q�s�\���C{{;���g�;<<�P(��+W�f��Tar��-&|�#����{D���y��I^�m�a`,��Q���G��ET�uS#}�������]�"#�"�m��V&[d(�hj�������V����R�{4';w��	�����q�M�uuu��8���S��@E��]�q6//� �0.~p�F�@AA������s?Q���D�����/�d[s�������c���J�O_k3�<��������(�\obE�
N��_}�<���8�{DDDiJ�T�GI�z�>�(N�����0t�����}�4�����'���jP�s<�+�j"��C�eTTT��v�����'�;>>���F�X���[��������(i��0��.�M�.�L�����]�4�FTx#�c�8U����LYb�>""""�0�Gs�t������,�W������9��L�_ZZw�d���e�����w.�����Spo����Yw�Y��(��$��-2d19O�������c������0���	M���|���_R����o&WE�n82��������7���� r,��3������7����o�q_�=5��>��q��{'��Ga�*T������a���r"��&����t:����`0�p��ihii�����+ I����;6I��.��n���������������5��z'"1�eA��"��(��}dv��aQ�!�}�a�7�hN%�#V4?�3=�v���9���33�o�������Oc����~,3Q�J���&o����1�\��U����O>�����c������%H2��P���3W�4��;�M�-
� �h��Z�
g�DC�Kho��~�Z����<�#����;�������]#���������}}}3�B @EE�I-I�eU�5��*�00��1��.���h/�00V1��K_�,]��/�"�.���{��p�cE0� �f���
�#o,
���2��I|
];^
Os2���'��������(S�������b��%�:��#Gb��x��	��x���������Q|����qz{{���1u_QTVV��k�c"JW	�{��}9J�YT���so����/'���AV���_iq��z���GDDD�����v��v����4����� 211�}DCh��Cc}<��P]�k���5#s+'"JO�(b���p��hmm��^y�%�P�N����K�d��Es-�  C��!KX��.}�nLu���SM��6�jW5�cMWDa*��������Td�bz���0B�H��H�9Q���b�0@�����f�L������Z�&%()���k1��.]w�������Q__?���W^��?|�c��W_}5f�����p�=������S�_}�U�1�2^~964RSS�p%f3Q:�P5Lhz��d����:FFF��eee]���f�?4������k�����jL��R�a��z��H���WQz*(�@AY���'p��Ch��Co��s��`G���>��	��|;�v�E��5|�AD4G������FKK�~�y�a���>�����X,&VIDDDDDDDDt�����r��X�a ����&o����/�
G1gx�"M��.��gK�.}!M����_���P�=#(s�q��
�$.@�DDDDd6�h��^/~��_�l��sg���}�{cBn��/�2���������>u�����zk��[�lA^^���mmm8p�jj����������w����zLD�(Q�= y�{###���'�u������|���;����O~6%N����Fa=d�1�z=�(�C$S�MDDD�E��PU�U5�1����}u8sh?B��Y�C��q�`=N�Gn�2T��A��������(�X,�]�===����1�*�>����(//GVV�yE%A��H�T$e�v���:�
�h��P�d�O3�I������u����T���P�S�!%�uF#�(^�F0�����66��`��s���:""""�=�h����/���N��X,����������g:t���Cmmm��1�=�X���}�c��+����Gy���7��=��c��c������z>|x������>�����|LD�(Qp�.�������]�e^�u��|���:�wLD���?�5#���(Uh��+�]�|�3���B��Q`-B��v)���CDDD�_����}�Ql{�4;������s��������>�����z��TVq"�Y���p��hnnF8N87�����X�d	�.]���DDDDDDDDD�(��\��\��]��U
��
oD�?z��/�b�]���*�E1��M�d�>��E�[Q�B}fv�	G���!D��I:5���]%y��8�����v���
6�j�����W�rEw�O��X�dI�������?�y|��_����O~����������������CS��n7���/_���|�+��~�@��*�����u����Y�������'?���������7�q�|LD�f$�����'"�|>_����\^�u
z������$��mx�k*M��R���x�*z�]�
wMms��(���Z�k1��\^hODD��(+*���r[
Fz����e�:�*&����������8{� ��a}�n��q'2�YW8Q�p8���B{{;���g���������
��v�*$""""""""J]� ���p(2�����t�����|���y��������j�0;f�Dd)2\�A�K���q��i:^�����%��+����4��"�/��[�^z�%�r�-��u+���MMMP�+5>�?��O�q�F|�[��+//�����W=��������S�����e����'��)]]]���?��~��1���~999W=N^^��/�"f���������,zzz�����_�����e:::���O��O�z3Q��������������c���J�Cd"���
z����VW���?`rU�j��h��eL���8h������������������(�&�#�G�w�DDDd�����������p���n��>F{{p��'����(��[������=4]$�2***P^^~��������������s�DDDDDDDDD47I��fA�+�\�]������#�K���|�Y���y.�re��f�.�����?A�?����j�~u~?n���@}�N���b0A���!�@���c���'"""����{����Gq��Q��jEII	�n7$I���0:::���8������o���{�c�����g���={
�����}�����,�X�^�����4-�o���>|�K_�����W���G����������?��QZZ
�����vx��������������Y���D�.T]�?�:�����`�1�������c�X�?���/������?�����M�R� ����;�y�K�+b�qa�&��X<(���Z�k���]�������(X�yVo�o�������`�;:�}���s�����#py
PU��j��3'o+'"J]� �����p������	������Vx�^�X����I�����������(pY.v�[:����_���R�>3���x#*���N%�%n��r�K���L9~���!�&����	�9�X��<�]���i��a���^u��w����E~~����}�v�����?������^��������C=�'�xbN����_�����>����gS�5MC[[[��������>��[���8�y��(]�F�\I��^0��D�*������#q�����w~�sp��X�2�uI���3``82���N��dH�(��`2���@�����(]e�����B���Dc}:N��������~��Op�O�l�FT����7p�"�8�v;��[�.���w�����������4�B""""""""���*���[�o��l�
cQ
�H��P�w2����������&"1�%p]����02fJ]�������R�^�����b���8|�0��={EW�����.|�������������8}�4{�1������`�y7�t��/������86�
?��Oq����o��oq�����233���~_����B��Y��(���q�����|�&��yy�p1��~����%��^��[�0�"Ju�����I��a��Js���lF{� B��Z�k1
�E(�!Cv������(9H���7c����
�i�+h��
�����0t���Z{��\�������py���Q�E���p��hmmE4��pqA���O���EEE\�����������:a*w9�0�tx�*��w�|���@T3�K�f\\�~4��x�w�OD0�";	�'"""��1������v�p������������^�����,dgg���UUU��a���|�{����������8s��^/,���q�������]>����ZZZp��1tww#� ++k�����[a����G�|LD�,Qp/�*CL��t]���P�1��
��jrE�K�4����G88w�]P�����UQ�2��86z��c.���=��Hd�������A@���1th���?����m.�=����V�l%� ��1�����r�y�����<�������:��8C�}���0����������nFu��m�I��>"�K���PUU���V�|���������PQQ���p.�G�d	���B{�5[�n����E.��������,mc���Q���<�\FFn���r�-��n�c�����s������������(
'��$����U��2�������9z�>wLE��_���arU��&� ��m��F���	k!<�B�����:6�����C��/�����_��y���?�� �_����%�J�~"""��DQB�MQv�FFGp���h�W�@��wb�8y'O ���u;�DU�nd-\�DD)�b�`��5�����`�/����hhh@yy9���M������������Jd[�+:���	M�	�]�P��T��
E�w	DDDDt
�#"�eF���p��K�mOE����\M��~�^��	��|��d�j+�T�=��}C�#�����P*2�bYFY�1���C^�����
�z��~��������VK���;t����d��%�"��Qh-�K���dL���h��9��}����GgS������������	��x��g��s�b��jT��A��-�����EDd&APTT������B��sUU��o����B,[�����DDDDDDDDD�Dd�2d	K2b������M�����PgX�+Y��0�������hA��Z��I��F��;���I�L�(5���x�;��a��@V�v=6���&WE�F7t���[��M?v������w��EKl%Xb+��~���p7�C���`$?|�F�C��L�`�(���V�k1<��br=���	����QZ}#�~N�GC}F{������t65��ta��T��En�����(58TUU���=��M�������c������&UHDDDDDDDDDI�X�+�7��T�7����Q�������"��0�0�GDDD�R�#"�5���.��$�����0�!���<��I]���{����ff����	D�!HJlL�c����_�u"t��IR�h����&]���� ��d��dc�c= ��0�E�d�o ������Z��	��h������Y
P0�+�!Sv������h�e������c�=�C��Sh�W�so�-:���1?N��N����T��vVm���z�?&"JC�$���YYYhoo��i	��A466b����x<\����������(M	��"��H(���/��Wt���s="}�a��8���JLQ�I�s)2dQ4���
��n�X�r�L�&5�>�g�L8��S_�+/���(����������3������<K>^�%�Z�];Cr�����k���}Mg�lXj_���.v�M����S}�v<:"����'��[
��(�!���$0DKDD��A@I�z�T�G�#�����h�	C��i?�gO���i���X���;��S�b��&"Jnyyyp8hnn���x�y�����
^�eee�e~�BDDDDDDDD��(��<�y6K���������/$���~�LDD*Qp/��\k�LLL$�P��������������kva���M��R��G����;y����;=�"���`�#82R���3�|��������]u��Q�k�G�%�p`\
�?�����0�`�:w����G`�����.����(��X�L{�DDDtmln��^����6���}u8{�����\.����q��yV�BU�������b���n�:tuu���g��###X�r%�Nv3'""""""""Z�,��( �&S��k�����R�{DD�����%(Q�=��*�43MU��?}������K�P��7�*J��a�:���]u�:�M�-{d����d�N�=��\�����7�5�c/���F��X�Qv-���L��2y�2WT]�P���n��{��������F=��	]�������Z�Bk
���Rr\&""JB� �h��Z�
g�DC�Kho��~�Z����<�#��z�v�AAY_��h�E��-���FKK����� ����SX�t)����\IDDDDDDDD��	��\�����i���*</IDDD���+5ADDieB����c�I�q�0
�9���<q5o����my;��(I��_f��a8h���z��:�\�h����X��2����r�f�c$2�����b0����N�`��Z�|�Td�A��3o�g����B[1
m���y��>�Mv��uc$:��z�7:oto\��~�_��k!�2o�#""�w����v��v����4�����$\T#�hh
�/���%x����v�n�kF�VND�<�n7������
��;��.������V������������(�xls�{6^�ADDD���#"�����$Qp���#���I�PO��:��c�����[�
���hq
�az���W�[h-�N�{��]��w���M��<���}���j����v����A�R��R��������?���P7�=��wR8���9������5@@�%�����>[1��+�%���
�U��g_?���:�6�_`#���6�?�}��X��vT����Uk�zODiOQ�^�}}}����a$^$������eee���1�J"""""""""J+�v4�L;^�����"���h��D�w��K"��dr5�
��.rssM�&�������a����l}56��~���d7������1�7�<nr��
Y[ 
�5K��s?�XD+J��Qb_�bW����&;���{�SG��xE�1�G��[�L���� _����|HB�<�-F������������4����C�����j$�S�q�`=rK���v*������b
DD�H,Y�.�����B	����s���������k��JDDDDDDDDD�)����fAh����-�N�������h��#"����^2u��4
###q����!�|�L�0���������G�������p�&����������#~���L��Z�=(�-5��� r,�X<�t���������{0��f�V_�q-����h^��#	2<�BNv�+��.e������hn��-G�#�b�C����Q4����L���1���O=��?}+7mA��=(��J�E��.���DUU:::.�tI?���PQQ��~�!""""""""ZL�r������'���� """���4-�T����@���<�����S�q���	�w?�8s�L���YP��������e�r������<�KX�Q����0@�dG��p7�����\�f��w�/��/ns��(��Z�����B"""�)+*���r[
Fz����e�:�*&����������8{� ��a}�n��q'2�YW8�u"I����v����M��
�hjjBii)����y���������h�X�iC���������i��L���������{DD� T��/��S2����(
�n�������n�{�	��w���M[L���Y�D�
��	=8�<n����7�"�$	��K�o]�b'��6����|��0���>u>u��O,���%(����o]�h�����r�Jp��?��|��}
�u�l<9�}������O��3?F�-��j��V����D�v����p8����@ ��'�����>�eee�e~�BDDDDDDDD����F�DA-����F�$�V�a#"""Je������7M���&��O8����Dnn.D^p��F��?}�p(�xvQ	v<�I���d�~;�N��_u�[����{�g-0�2�� p�.8.T8��z��>��{��������#��P�TFr�<L�
��p�n8�����(X�yVo�o�������`�;:�}���s�����#py
PU��j�d�m"J+6�
������Fww��sGFFPQQ��eR�DDDDDDDDDt��$��s���!D��[$�"
�U���k�����RYr$'��(����q�K���/?CCC	�<������?�w��5�%������l&WE����~�yDz�:wU�:��{'�bBe4�hA�}���\������2����7:<o�3``8:��� N������Qh-B��y��br�~����B�����|�Ch���h��C���`�_�?��#?�	���i�m����=Xq�������C���4���0�s� �a! �)Z�D-�%G�e��B��&M����n:O:I;�i~����v:_���fR'�di�L���h�ZlK�d��I�+E� A���g�~��)
 @	���.]��{t�2#��y�G���KQVV�k��!�J��$�I\�p555�����$DDDDDDDDD�K�������K��c<�R,yX�&��JDD��!��Rd�s�f%�4���9���yE�C��6����3���������"��������n�I39�y���������H+�%*�nTZ�XS�H�q����o��U����o\���CG�*:bcAa���� �O	�Dv�m>"""#�2Vn���[�c(�������w0�����tL����'q��I8]nlh�����(�Vp�DD�Q^^��7�����������;��+�(J�VHDDDDDDDDD���X���*���p���S_j��r6�-�QADU-�q�un�422�D"�v�m{���������i�����=�[�]�))#���C�4���\�����Qn�,���l���X�����d�� _O�#�P��3��7������)���|.���7�����������y	���/���������gN�4r�)v$��?�)N��g���(665���m�d�-ID���b��U�
�p��-��+���a�����G���*�*�����������l��]�J�����?�P|�M�'���h�tbi���+$"""�b�2DD�w�i"��qon�2�����.�J��4����F�}i���ex��+�����/Fk�W�O������1<Q�4$�/EQ�U|�*>l���Qmx,��v!�"��@�7�g3�
bX�����Z��%��|��)K�H|C����a����-[Q�e+F��8� ��`�7��ELg����8�+�~�^44�G�?P��� ���(--��k��g�A[�u\�rUUU����$IE\)��������pc8�H"�p"���=�,��Y��YQ_jG����������wKQ�
�thv��=�0���>\TQQ��Z��}��Zp��������c8+�k�bd�&.��������6���v��<�Z�#EZ�����j���hF
�dh��/D�D���m���BW�]���c����|���J���9���g�O|�����/��\�����`����,68��x��:�m����f����e�^$"����l���n�Boo������bxx+W����(�
���������h�T*<6~���� ��.LA�`h|�i�����
�������#"��������?����C���c^��������;8���8�i��x��'��"�+T=��}-������m�<��Dvae4W��Kl5Xb�����C�BjzA��.DS�������?���6cR�k�����a ""�)AQ�q3j7nFlh�������]3�N��6t�k�����nDC�3p�,-����
C�$������7n������q������>�o����y��13l�EDDDDDDDDDs� �����7��	""Zp�����2��(y5���i�K�����"�fn�R)��WMU���k�a�W�^�U�\������[���=O���+����' 
����[A@����J�rn���^5��DBj�j)3s |�F���q+~ B��Z�R
�m,���K�6�b�(+��/~���9t]<��C-�r�}������C8��8���^�
M�X��)X�JWND�_n�N���]���p��L�DGGQ__K���X,�H$���������jb����p:�p:��x<l�#"""""""""""""�C�#"������Rf��(�Lb`` �����8��s����3z;���,<�G������a8;x
�����w�wJ���}~[M�VG�"*Xj_��������S�� _H���6���'{N����c��w��J5\V/$A���DDD� �Y�5�6���Wp���ho=���[3�N����t�_���l��=���./�����KQ�[�w��AW��-����hoo�#�<�������`p��a����� JKK�9����]_���{����2�y��"�d���v�����O��2o�]dF����`�3��u����n�M�ae����X#��Z����i#�A����j���9�c$v	�c�� �k]2��)~oeas:���/b�3/���e�j����fl�NG���l��8��&�+V���k�|V���hnK�.Eyy9�]��d2���d2��/���555�T
�������0._��������m~DDDDDDDDDDDDDDT8�Q^%t1�H;6���p��6�
N������bC�����e������g�]WD��3v�#�F��O{�	�]�XW�� iu��8d'�����d@75���D#_O�q#���4SC�z����c�X+��_	�����<Q�  �j
��`����K�����zo�o������\��#?�>�>�
{���_Q�U�GYY6n���������s���088���j��q�T���r������!�]�����EDDDDDDDDDDDDDD��=""����e������(b��A�����8�4��?|�������
4����k��M���E�����VX���}nkUVF�)I���U�o���ibXo��BH
"�����9RQ���<����x�o,�W�,�E��m>""��@q8�i�����Y�n\C��\|����7��,������Z�[W�U;vAO��|�%��I�e�Z�
�������if��ddd�/_����T
��������#"""""""""""""��Q^E�����$vI,�j��D2�y<�"�dn�������������(��,��h����~�dO�s�8������	� ��R�2KV:��F�j7B�A�P"����m����v�&n�o���V/|J�X���S*c����h��~|�+��+�K����t_�YX%�q��$	��GP���i1DD�E�|>��������� ���t]����q�FX,����b���U���K��jX�4������R�l�"�hn�����?�~��-����-[��"�-WG.�����2���.�`�NO3V��)����U���^�{-�����TBjz� B�.j�y����H��d/�pHN��|�A>��I��6'�|d�����
����@��\|�0�#9_��u����W���3���9�{�������h�p��-�B����J������+WmN""""""""""""""bp�����/cpov�r�J�_���-�j�&-��[�����i�=����K�_�UQ���$���������VY�`���Y*
�0�<.�.�kK7�zl��o<�����njy�3���F�
n��$H�*��V>[>%�T���������:4��
v��2��<�������u�d�]8���{?y+����=��Y���["�3DQ����Q^^�7n@���3�t�����xPYYY������������������=""�#�01�L���j)�j���En�����������H;&[�x����j-����"j��71�E����l�V>��0ZP��u��s�����d/Bj=�.��.�����d�CG������+�+�o��)����!
b��$""�,V�v6b��FD�w�~�m�?r�������R�t�(.;��%lh��
���Q^Q������BII	�]��������#"""""""""""""*"���(o�)������4MC�1��Ib����3���od���?�gimWD�d�&���G`@��\��@��9,�//���f�$H�R��JY����#�z��Bj�df�g���0�
���y�U��J	�g��T�JY���m>""�������|O~���~��Z[��~vF�������c?�g�x�3h������D���hv)����:���e���a�b18���GDDDDDDDDDDDDD��1�GDDyU���IPf������>�f�P���)�j����~����q���m����"���)��q$r�����[c�E��98dgVF479�2�����d
 e$N�Jt���.�F"o�%�$�$:p'�1q�e��?���S(�+ B��$""��d�������;1����o���w0:�~��t]����p��1�y}hh����{Q����D4{����:_$��e��:'�b���MTM�=^i�@��@A8N{�j��������[L�D���b�i�K**�������*���C�71��L{�[+����m�^ ��"Z�-E�������Z?z��Bj�S��7�
#�
���'��0}�A>�����,�G=""Z�*|~<���a�^��cGq��^G���a��t��!���p�_��������7?���DTd##��L�o���E���������������h1���DD�7��{.�R��|*�Hd����,�������Og�?�	e�;�����?�G���77�����y>[�H�#��A@���
�kJ�����v�W��f��|q#���5t���3E��(>���|J5J��IDD�$����7F�����P�na4�{h�4
\?}�O�������}hh��2oUWND4�4�������Fa�Z!�2,$����������������
��=""��4M���^��=�z�E\���������{�s�����+�b��q(�&��;Y��w�����P$[VF�p)�
��X��0��&��Q�&}��`��3`�W�F��=q�T.��W���z!
b��$""�m�'\
�a�����W�����gN�4���1�����'~�3�mz��Q��6H2�B%���u��uN�0p���{�����r�����t��FXDDDDDDDDDDDDDD��]'DD�#������k��{�if�����n�yEsG*�������S�����z<���yUTh�k8�
T#1�y� c��	k�y3Q��X#�G�a�j#��z�.D��4�fX��6�k��`A��dR+_�!]""ZDQD������#�Q�?r��Z0���"����g�q��X�{/�����j"�/�L�^Z��UU��jN�O��zLE��@DDDDDDDDDDDDD��{DD�}j����y�F2�L;�����}���w�3��lU��}�e��)�4C����87�Q�s]�z_D��S���]%���j���0���H�=j!�=� F,o�if
�D'��O�*-n���|~[5��J�`KDD�����'>�El���y�
m�Zp��0t-�k������7^��
�����v��%"����z[�4h��x<��\Q3����dY�(������������������(/��{e	�Y��&S�� p��E^��q��)�my3�x��}���E\�@*���_�/����u����������f�,���j���k��&B|!��T$�s���������6�M��J	����U�k�����hD�7�v�f��q�h+�Z[���5��t�kC��6�J����F44=w
v"�'I$I�������1�d2��ZS�
����$i���������������hq`p����"Sp����
������/�XEE,��a�?�����2����
{��� *�4qe�<��;����	VQ�.w�D��=� ��R�rK%V97TCE�Dh<�R��2s�6	#���ut��D�p[������rY��#""*GY9��x������y�j���COM��y������������CCS3Vm
�R���B$JJJ0444�K�3����B���}��~l�#""""""""""""�bcp����"����f��{���0#����-�j��0p�o�'���osV����os�� i$�^���6z1��>%�=�P*�aeD�O��`�}9����@*�P"��!5�!m o�0N� ������%R)|J~[5|Jnk$A���DDD�"j�m@��
hz�\x�0�[ r�����u��.]��W���;�qO3����j"Z��NgQ�{�(�4M��Y�9�4���I����o�/��Q>0�GDDM�
�jz���
������eYFEEEq3G|��_�V����~���^����.���`�W9�u���W<	Q���D�(�5���UX����>:��/��������>������^����U��%G��#""*���G�}[�y�W/��P.���|
56��-o�l����X���f�y�iXm�������`0X��6l���]��J��J��i��$4M�86�����g����:t]G"��z� C}�������������������ap���ZTMe���^2����`�1���(o������~�j�������l���-���4M�����wa }��]�M��Qm�-���h�8�,/Y��%+��!��"�v�G����������;�V�L��]���)��+TX�l� "�9IV�A`����7p��Q��@���3�N��+��vG~�}�}r�4�W���D����@ii)���>Wii)���5dY�,�����
��/�7]�o����}<�����K�O�e>'-��C��S$��!�Lm{�Xpo�I�	��W���������_��E^�S\��H�7����z�R�r4z��]*)���h��y,Dg`#�nF���3��R����D�n�������9�UT�S�+��)T)K`�y����(���=�M��E��5�j���� ��|�T"���hk=o]=665c���P|-ND�
�|�rQ�y�(�j��j����4M���6��.��ex�j������l
~��K�T��Q!1�GDD�/Cp�m-����i"�����()Y|7H���
�I;fQlx����$����+~�"oem�!�����P�8wu'�	� ��R�RK9V:�RF�j7Bjp"��4����4T��������5@����o<��W�����o����������.}�.�[[�}uf�p�
����p��`���h�����5|�#"@ee%�n7���
6���Feee��� m~6�-�����r	��Q��P3i�Eq������BDDDDDDDDDDDD4w0�GDD-S��K)~ltt�
^�w���r���v�@������p���"��4pz�><���2�{�/�����2"��,���ZT�k��H;��C�x#_(����|&LD���${q~�c�C*�O��_	��T��TA��+�.������hh��Hg���������ZR���q��A�k������n�����+'�����CCC9��f�b����.���Arn������M=��UU���m����o�/Q���DDDDDDDDDDDDD��;����������vl6�{�p8����)�Jf�p4������W}�)l����+�|��~!5���%k���VQ)���h!�V*��-���1���c�|� ��nhf��"���f�
n��$H�*~���|>[i������YV���_���^��������;���}w:q�G���~�*Vn���{�Q���
�E�b�`���8�<t]��u%I���ka��}�B�$	�$���75�7]�/���I�4h��qs��DQ�����e�(�-��CHj03�;�g����������s�B`���Dbd8�x���}��o��n�^���H���.<���U����LDyg��u<�Z�#��M�'�|!�#z����CG��������D}J�� _��Q�M�DDT\��u;�ng#��;h?�6�9���P���S)\:v��E��64����{�(�(���hNr8X�~=.^������a@������?� L��raF�����0�L&�L&s:�n�/���$I|O�������������=�����D��7�HPn-�����4-}����-�Zf��7�/:�}�~P����6�������)|��3�w��m�bo��C��U���0���U�h({0�
!��3��K�����9��i�:z`��)K&�����Q�5������/}�O�@[k:������A���Wq�g�a��O�aO3j6C`����p8�q�Ftttd��*n�uuu�i�DQ��(P��?G��	]������Z�_.&'s	����������������"�����D���{V�"�����$	���E]�l
��������O���t]CWD�?����ME�����Q<Q����yD4��r�r)YH)��=�|!5����|)3�;�[����sY<�)����)�(�+��@DD'[,X�}'Vo���P�~��������a���<�+'����CC�>�o��R���+'���b�`����x<��������@`Q�6A�,��ev�=��w��4MC2�L��7��i�Ex�e�����$I���7���������������h���DD�P25�������J�000�~-.$I*�zfK2�[���02���d�jl���yU��L����v��B3���\m��yu��EZ��XD�����7nP�G(D�x��?���LDSDS\k+����|�A>��Yd	N������5l��K����homA���`�����C8�/�������mECS3�o~�"�9�h1���Dee%b�"�FGG1<<����QQZZ���x<8�Y\1e2�����d�s�����M��o��u��#�Hd=�np2S{��cl�#"""""""""""����=0�4�Lp���/�N�^���k�M�_�G�w��Ylv<��?�$��>P
�FZp#v9��~�{�/�)�aeDD�!*,.TX\X]���	����F�.��nhf��"a������5��>[~�>�%�3o��%�2Vn���[�c(�������w0���9>�4p��I\?}N����q?��U\9����-����c�v�Byy�l-�
�A�������-�6���'w��r	����6?""""""""""""���ODDlD��4����V�����QQ��.�0�������3����B�IWD*��~�����	�h�v<Z������h�S$�9�c�c9�0
D�a��O[����8�&����F;��R��j���V>���c��(��<^��������:>���-�~�L#���hN���8����n���������q��E@�{�W�(��Z��Z�Y�5M�adl�Kwl!�����l
~��Kl�%"""""""""""�i�N""z`�����Z���X,�����c�gQ��4	����u��5O�������"z�i���S���}������&���iuDD�'
"<������FR���|A���~f6#������E�,XP�,�Ok��R��&eo� ""�F%�o���-[1���#�~�����/b��8{g��Q^������i?*���-����-A I$I��f�z��f�L
~S�3��e3i�Eq�����{�DDDDDDDDDDDD�)�����e
��Z$X��5�D"��c^��h��-���7�?�f/�y���?�!o
��b�G~�;�[Y���?���g!�E�Dv�^^���U��I����J7by�O3S&:LtN����o��)TX\|�%"����t���}�>�t�kC��\;�=�����>|�u|���X�a#���b����m�CDD� 9��c�v�5�M=��UU��jN�gk���KE��IDDDDDDDDDDD4�1�GDD,��������@�4��������s�|��?�����	������P%E^����M�:k�D����vaC���i��h�,������U{m0�
L���$�����VxP�>��pi���6���|~%���E���V""��QD��������A\8���Co�?xgF��<���sm���a���hhz��uQa���oj�o������i}6i�M�����+�b�A?Y�!���L�������������r��=�L�{��
f�����m����e����q�3��%T�YW��L������'C���[.Wb��Ex_VFD4	��rK%�-�X�\H*z���V�D�jI3��9U#���
t�o����*���|�j��ey����GY9��x������y�j���C�ACQbxg�zg�z�k������?�U)������a"t��0�6�M����d2�d2��_eY�����$���{DD�@T����~�c��x��H$��� p��E[�lH�c��w�F������3��r�WE�J
�5�&z��Y�]U�O�������YE5�:����i�?���x��G���6���L��$C�$C87��Dr�7������VA���IDD� �Y�5�6���Wp���ho=���[3�N����t�_���l��=���./������KE(�E�>7M���
���-�6�D"��������~l�#"""""""""""z8�������qO�4D���kp� ��i��?�B�C_V��}�O!J�E�F/��HK��'�`�S�}�QDD�� �m��m�b]�f@\EH
�'DH�BX������9���F�2n�.$A��������`�y����&���G�}[�y�W/��P.���|
56��-o�l����X���f�y�iXm������xA�h����?��m����7u�4�"<��2MsFm~�$el����m~DDDDDDDDDDDD�Z��""*���=EP"g��h4
�0��y<���a�\:v���f������*_WD�H)�������z�>����rKeVFDDv�u���s����H2��x��G�BL��|���G���04v�\���V=�S�Qiq�fG""JKV�A`����7p��Q��@���3�N��+��vG~�}�}r�4�W���?DD��<L�_����iEx���:t]���/]�/S��m~DDDDDDDDDDD��1�GDD$�!��R,E��/�=n�XPQQQ�5���p/~�o3������O�*��(}�0���T_�s7�=�m�OC��HD4[$A�O	��<�41�!��G�BH
�/��kZ��18��+#�VA��_G5��%�����GDD��p`��g�i������C-���$�����J���zm�������f�������+'""���oj�o���Bi���xr!IR�P_*���b�a0cA������=�h2sp�������y<��`�:�����K��S������,��h:�i���Y|=����D;=�a���H�#"�\	��R���r�p���$z����|!5���>�����v�&n�o��\V/|J~�>%�R�|���!"�������~v}�p��w�������gt�p�
����p��`���h�����5|�!""z�(�j��j��	�i�0#c{_�c��6?UU���\���}����
~��K7F#""""""""""������n�P��P��^$�8��z����p�����/�D�}�O�8E^e��	�;����Y�
�����<JdgVFDD�`���/C�}���,RQ��.��A��.��y�����d/����0|��J&�|J���DDXl644�GC�~D:;�v��=���H����*�=��G�]�
M�X�t#��e\9��%$I�$I��lY���l���o�q�0��(
o&m~�(f��;��
�����������(��#"�Lj��1�{�i"�s8p,��Z������?�8��/!�jMWD��I�Ak�-��C��'@��Obs��H�#"�B�V7*�n�)�H���6����^����V��>����!q"�VXF����7b(DD��gY�^~;_zWOG{k�\<7�k������#����X�m6�iF����NDD4�A���k����o����0�����o�t��La?Q�Z�������������bp���f�OM���(��?����d��}�����Q����f�]��������N�WE�����'qz�L���������<���"������&�Q�x��G��#�#���v!�f
y��FI��b�m��Q6R>����U���aX��h�X����u;
�A���q��A��s�S)\:v��E��64����{�(�(�����(/f��75�7]�O��"<���4
��!�g=W����ta?Y�!��9�����������h1bp���f,�!�Wi�@,��������|������C�P�1���}��A�"����Fp(������.w��.�3P��7���!	��^��
x0�
O4��AD�!��gnH��6�����*%0���.���"�
�`�W��'��U\?}m�-�l?;�k�w���_������?��=��m��7��{�Ci�0#k���c�9��g��i�H&�H&�9�/�r����a?I���GDDDDDDDDDD�@0�GDD3�)��Rr��a������c9�H0�\x�0.�$���o|e���-�����#�� aL��	;\MX[��7_�)��)��#%�)#�H2������X�/���L��������sY<�)�l��+�(�+�<ED��Vo����wb ��s������`t�?�k��+'����c(��������rp�DDD4���EQ�(J�sM����i�~S�~�d����mf��6�D"������\�~l�#""""""""""���#"�1Ms��^��V��(t]O;��z>�
�z����6����{�z��"����M
'��E�����VX���}n���^%"����,��`��({�5�
�G�B(���D4����T�TG�6��R
�-�R
��Y\x$��*|~<���a�^���?D{k:�~���f��p���5���t+���|�c%6��A&���v���

����E�(b��-�X,���c��$I����b�Qq1�GDD32��H�?�.F�^$��&uI�PYYY�����u�����x����%4��+E^M6������I������;\����"����APn�D������@o�=�A�^5���~s��0����[�k"<V|�A>�@�\�����h��d+�n����1	���wp��;��|
�0p��I\?}N����q?��l�'""��3�a��t���,�yS��&����4M+��(]���z�m~��}��~l�#""""""""""z8���D��d���
�%�I�s����~�t_��vL�$<��?��6���T8WF����w��$��;=�XQ��H+#"��@�lXj_�����4M�qk��u}��#]�_�����d7z��h�X��S*���_��O	�e�B��DD���y���;/�3��%t|��[[p��)�F�-|#�>���Oq�?C��G�����m�$��i"""�����c�������~�������$IC}S����6?""""""""""�)xw�HTM�a�S�`�
����^���s����p���q��/}����"�+e$�~�A\=���*�����2KE�FDD��(��(>Xmv�������O<�!�!5���=os��C���KY��J��7��)�$n2@D�����-[Q�e+F��8� ��`�7{���D��3�8{��
���
M�Q�n�DDDD�EV�V�5���i�0���}��-w��TU���l
~��K7�!"""""""""����=""����=�R��= sp�f���t|�bI�������4�7,]�[_�|�WEQC8�����n*����O�y���f���Xj�GYY@34D�!��.��A�]������)�L��8Vaq��T���S�Qaqq�}"�y�Y����"�}��<���C-�v�z�7�������7^��
�����v@���"""�!$I�$I��lY���l���o�qc��s�L��DQ���o�q��@DDDDDDDDDD��{DD4#�������"Kc���]0����w��o0	���8���ba�
�^�i���G8=����.:��}K����:""������~[56a��mXD����x�/������9RQ���<�PD�D�O�F���E��l@DDs� �����7#64�G[�v�m����:����y�
��2��
M��]��@�&"""*Arn�����k��z|!0������.��)�'�����������������7���(g�n`DKZ*t�^8�>����s�������{����G(u/��;���F�V�z�skl�h�<��p ��h�e�
�Y*����4T����A�$����4�y�S5���@g��� �m��O	��T�g��S*��uDD�������y<����u�<����������������������CCS3Vm
�R���
3m����.����oF7_h�M�����+B�@_���,��Y"�{DD���d��\J��R�@___����2(������'�C?����
{����E\�q(�&F��i�!bk�S�T��A""�����{j�u�n�OE�3��R����6�	�d�d��?�HN����0��nk$A���DDT8� �f�������_������"�o��:]�.���~�{X���4�[�Vs""""��PZ.����7��i�~�g�&��$���6#�e9c{����$I������������r���,���YE%r�n�D*�.�^��`���i��w�)5�v�2P���}���Z���G���`b��J�r����(������G��^��^�+�`��64��Q�'{��Z���Gp#v7b�� �k���������#o�Qa��N<��������z��Zp����T5�k��Q�myg[���*445c��O�j�p�DDDD�(�P%�MM����i�~��~��/�H��d��������GDDDDDDDDD��1�GDD9��s)���.��E.��`����?��~5��(�x�����V�U-N#�Z�o�G����z�j<�i�".��G""�\�%�+P�X�M}�^��7���]�ei��	�����{n;V.W�7��+TZ<����h��UkX����
\:vm��{�����s�
z�]��}k����=�������DDDDy$�D����}���m~������c��$I����b������,��oRq)����i������rA�
��W,���p���3���������"�h���]���o����+2v��`������'	��%�R���mDFhR��/����v&�~j��2z`T)K�o��R���`=���8���Yl��,B7���P.��x<�k�q��@[�x�����kw���()������(��i�������I�7��C�������2����GDDDDDDDDD4�1�GDD91L����{�����qV��[�y�%>2�����2<���[����U�E-B���d�Q��(��.�{�/���)������AP*���Y������DX�A�DH�e��D�Tq'��;���5@����o<��W�Q*�3pOD4���W�W��������homA���3�F��Z�w8���z�N4�iF`��{ODDD4=H���p�ta����w���B�������eY��d"""""""""�Y���d ����������p8����jEYYY��-�4��?�5F�}i���ex��+��ZP�(��}���k��+�����!����'""Z�,��2����HE���A���&z&L����K�qa�,�.:��U���S���� �|[��h�Yl644�GC�~D:;�v��=���H����*�=��G�]�
M�X�t#����}"""��LEX�VX������	�02���;��m�SU5���5�M>.IR�WODDDDDDDDD�8�5""�ITM�����Z���x<����7�y<�y�3h���q���������Y�*���4qe�<���fN�{�UT�������EZ��&*�nTZ�XS�H�q����o��U��>G�D���#v������ �O	�Dv�m>""�9��:4��
v��2��<�����xnF�����#?�G���W�r�l����u
��=""""�LH�I�`������.S�����a�Q�L��DQ���o�q��&"""""""""J��=""�I��^�"C*��q�H$����-���
���~/�����c��OqE�K�P�^�;�6z1��>%�=�P*�aeDDD��M�c�����4��#4��ItaD��|���� ���R�>%�x��e�B�~LDTl��u;�ng#��;h?�6�9��p��z*�K�������\������{/��[8�� ����5�M��7��B`TU���/]�/S�OE����������h�`p���r�)���Z
2�i���i��N'�v{A�-]K����9�v�k�a�W�^�U-a�����6���-����O��}""�Y 
"��^��
x0�
����.�AD�!������ ����p�E��JY2��W
����}�~""�W����u<������hkmAg��]��;��~�*���5�x�	4�iFm�f"�#"""��f��75��.�w����Ex��i4MC<�z� i}��~�,C��v"""""""""���#"��L���S
�B2�L;��x
2g����F���i�$����w`�*E^��g�&��N�d��Yo�wH%h�<�j{m�VGDDD�(�KQ/�F}�j�f�N��Z�A��A$�X��K�)t%:����8Vi�|��g�\��.�DDE [,X�}'Vo���P�~��������a���<�+'����CC�>lh���]���b29���0�6�M>f�f�A����d2��s��dY���75�'I��!""""""""�9��=""�jT3��?t(���mO�y���v�����O��2�������!���p�7�����e�z��<��(������a��Kl5Xb���n��R���"�v!���u��T��.��l�>%0��g�k��"�52����������_x	7>���-�8�L3���p���5���t+���|�c%��+'""""��(�P��}CG�4��z��_���Bk�K$Y����%��6?"""""""""*4���(�Lm{PY������F������,������ ~���q�n�c����+���;�[8y1}t��D�x�r��n�DDD�� (�T��R�U�
�P�����BH
�W
"ef~};S	#�[���kT!�m��O���6�s��y����>%�2Vn���[�c(�������w0��~3�tL����'q��I8]nlh����}(�Vp�DDDDD3'�D���n�z��6�t�}��~���O����}S��������������L>QQE��olv�)�;QF�QF�]��k��i�x�������DGy����~y��:����'��[&W`��ExVFDDD���
���c�}���0
��"A����!m0o�0N� �����3�T:���W���z!	lt""��2�;~�%|�����O>B{k��93����D�p��?��_�u����f�?�
�<�@������m��.�ww\��"<���u������.��)��6?"""""""""�#"�dj�s�m���;���������Yhm���Ofo�������+Z���A���DH
f=wE�Z�t��U���5��0����Va=�b�Bj=�A���=os����]���%�,��Z�L�|J6)�N�DD��(J����[�b�?��G��P{C�_�4�q�:������w�EC�~T��[8�,�����0�	�e�-�6���'�$e�M=.�27�$""""""""Z��#"��2���4��*�����y<�y�;e��N���3�oy�E�o�Z�-l7F/�h_��:�y�`�S��XU���-r����*,/Y�M
a54�����B���m>�����F�z{�X�����O��_	����k"����t���}�>�t�kC��\;�=�v���>|�u|���X�a#���b����lfDDDDD4����
����\�4aF���L�~��6?U��������UTT�0��p8�D"q_�O����������������=""�VR70�J�6R���H$�q����}�B�R)���?��J��,���/�~�W�0iF
���qq������U��}WVFDDD��$������U�
�41�
���u!�M�a"��hQ�Dqy��**�)�6�U)K`��GDD�D�7�v�f��q�h+������]��\:���VZ��O7����k�h�DDDDD� �$	�$�f�e=�n�]�`_�c�a�Q��&?EQ&���a�����Eq�����9��ap������L���?�g�f���n���p�u�bx�'�"|�f�1�b����S�9�FJ��&#h
�
�T���]J��� �|DDDD�e�
�Y*����4��U���A$��vP�E�Pq;~��c�%p[�����J5�ro�""�!GY9��x������y�j���COe~�c������������CCS3Vm
�����A���k����7���aPU5�6�t��La?Q�~Q��u""�V���=n8e)�s���"�H��z���C��g���[od��_�gY]�����K#m8=�L��z�"����,�+��:"""Z���5�Z��k��.�O�!�v�G
"��������L��${I��������_	���lx�>HB~_�-T� �f�������_������"�o��:]�.���~�{X���4�[��@�&""""�������4�{�|��~��x���i4MC<�z� i}��~�,C�"<""""""""����=""�VTM���K��=H��m<O^�*�������8^��Vl��|W���z������Y�]������riVFs�i�Hh�f�0�{""�B.�.�kK7�zl��o<������e�����#����+	��>�~[>%�T�����*���G�}[�y�W/��P.Z����Fq��M�my������5O>
��^���LL���0��
~��/�� L�D2�D2���|Y�3��M
�I�4�6j%""""""""zX�������a�D"i����a�Z�:_!�����!68�v������/�`�!�A�F���68�y<Z���o�(p����R�~y6�O���� ������O����j*����X�g����
�.9P�X1����:����A�$�R�0���m>:z�.��]�dh�X�\�x#�O�F����EDD����5�Z��_�.;�����y}F���v=��������O�B��f��W�}""""�yFE(�EQ��k�&t]���o������H$��;98�K��m~DDDDDDDD�0�GDD���d���5�������Py����Uhg[����Og��+e�E\��a�&>:����c�sK$'��/ `[Z���l;t)��?r�:��Jh8v�����o�\��:���4��*�J��h��	U�T)K�P�`DB�x#_H
"��D�vg�0�
���y�U��J	�g��T�JY����3"��Fq8�i�����Y�n\C��\|���x��H%�hk=������ccS3���
��6T""""��F���9�={��a�����q��M��QQ^^>�����$I���7�����������h�bp���2Lj�3|����p8���$Ip�\y�����8��2�?��o�n��E\���Fp8�k�I��zn�}v{��M���(���I�?�<�_~���=���W���������,�?��DD�08�2�����d
 e$N�Jt���.�F��s�4������D��1���x#�O	�L���NDD���W�W��������homA���3�F��Z�w8���z�N4�iF`��{KDDDD�H����
����%EA{{����l�����{�����Mm��4m6R���]�sn�K���c��{DD�QTM��'����)$�Ja`` �����7���*~��?��J������S��{E^��p;~���F��M{�	�]���to~\$.v��:����P�y�l'n���_��5��<����h�,�����`�41���g��/�v�?���9��0��0.�����|~%��Y�[HDD�

��������j��w#1:��5����G����p�,CCS3�=�{)!""""��&���bj��ta����w���B�������eY���DDDDDDDD��x�e�)�Wa�!���p"�d�@����m�B{��B�v�68����o�%�M��n����=|2�a�s+d�x_�G�ae4\����w���>��&4��K�p?{�3���!*,.TX\XS�H�q����A��]�U����y>��CG�:b�"Dx���|>�%�3o��G�euhz��|�e\=y��-�s�����w�G~��x�'�b�����5�xC(=�tm~���	�02���;��m�S��6����7��$I^=�'�QF��{.%���H$����((--��\�r��q����������YZ��C����Do�;������k,b� ia�M��:����]��~��p���Fe	����hn�Iv,s�c��`���0z���|Ak�y����^������J���_~�.��0?������bU�ng#��lD4x�����#��z*�K�������\������{/��[8�6��$	�$�f�e=�4�iC}S��Q�GQx3i�Eq"�g�Z����y�����e�&���wLt�1���0::�v�����*F�q�o�g��[?��{�)����k���^�I39�y�����X�\W���\����<BC���:S�!�����/o)������M��<��(`TAh<����B$����(5�
bX����Y��JY2��/E�~��B�
�`�W��'��U\?}m�-�l?;�k�w���_������?��=��m�Ad8������f� ��\�����o���0��*TU��9�d��}���dY�$I���s""""""""��{DD�VL7���o��g�^8�8��x�6O�������_f�I�Y���W����(e$q<z�F���������"�-�EX�%�.���O�����A|vsMk|�����PJd'����/Y
�����X�/D�D���m>�L!��D0�9q����o<���U�\���b"Zd�������;1����o���w0:���5]����p��1�y}hh��
���t��r"""""��������m~��~��x���i4MC<�z���d���,��	��cp�������w4�Wp�4MD"��c������~C�G��%n�}�~P����K����y�/����_a �z�������iHBn�����Gng��7�#"�C-Xb��[
P>�Z|H@H�BO"����h*�k����C��F�6��*%���V
�����MA����
�O}�k����p���������4soA
�p�_^�����G�����7?1��_���������������o�q�4�
�4M$�I$�����$���_������������
��=""J+Sp�D��H���opp�T�y�^o^�(���x���f����Q���h���L������ z:���&���y��EZ�5�z�p�#{�3N���r�0V�K�2Q1	��rK%�-�X��P
�j�� _H�F���&�\$�8:����!�m��o<��Wp�����&I��r�v���C�0�~�����p��0
�O����'�t���q?���[U���M�(BQ(���\�4����
~�-�6?]���:�D�s�'�6�e
�����������(7�QZ��{�j��p8��i� ��r�m�BH�	���?��ii�}�+����R�U�?	=��}-��]�zn��M��Q";��2��~y6X��>��w�k�:'�lQDK�����`��S�A��]�Aiy����p��d�
(�J�S����Sp[���LDN�����>��_B�'�������i���7�����'~�S�mz��Q��6H2��'"""""�J��Y�a����oF���ta�����)��6?""""""""���(������<uh��h4}k����<�o4;������i�dE�s��$9!���;q��obD��<�x
���A�s�b������w{����%�0����Va6b���F� �jO������q#v7b�� �k��7��)�%G��#"�M�(�~�V�o����(�9��C-�
�~�D��3�8{��
l��
M���/)��������8Qa�Za�Z��;��/����ac��f�m~S�}�����GDDDDDDD��NE��H�S�o��W�^4���������r������do��W�
TqE��a8;x������O:�2������4��������y��F)8m��C*����X^���"j/Bjz��@_L��|���[��n����r�>[5�J~�7w�&�y�Y����"�}��<���C-�v�z�7t�p���q����l�F445c���-�y�������P&���bj��ta����w���B����ta?Y��� �i��}�j����y
������-����2G!�D�����8���'�a��"�h~�Fp(�&���m��-w��.w3�V���|0�j����^>���go�[����@��d�k���r;o�%"��Kd�l�ll��M8#�z��Bj����6�������~\9��
|�!>�@��1�n�DDs� �����7#64�G[�v�m��d���t�kC��6�J����&4�i��zi�VMDDDDDD��i��a���_����PU5���k��z\������������^��}�j�`�E�����D"�����c�g���g~�7��p���R��������g���u��	#>�y� cGe#��n��%�#������a�av��7V�������
����a��1-*� ��R�RK9V:�RF�j7Bjp"��4r��&IC���M���[��^���|~�N����D4�8�������c/|]���P��xz�
�����
g��7T�Y���f���,V��+'"""""�|�$A�$�l�7;5Ms�P��c�a�Q����O�94�i�_����1��HDDDDDDD��=""�O������7�3�����}����7�/:�}�~P����6�����tS���w�>t&��7�z_��:w�h�X����X,������o��&�n��o��g������>""Z,���ZT�k��@4��C�x#_(����|&LD���${q~�c�C*�O��_	��T��TA���� �f�������_������"�o��:]�.���~�{X���4�[��@�&"""""�ba"p�]��6�M��B0�6��!�la?I�����w(�}2�������i��D"i�JJJ�p8z�B�������������u
E\��0������I������;\M���}F�p"E�j�g�������A�w
�7��J�6�Mj���� ��`���&APi����������C��=���"���fjy�3���f�
n��$H�*~���|>[�$o���������-�������~����-�@���l��8��&�+V���k�|V���+'"""""���n�_.���e���^����i�4-�6����la?Y�!�b�6�����i�?Y�����p���<�C_�R���������8�_�
���R�W5�]9����A��~�E�`���f<R��H+���4M|���W��D��t���%�M,��b�.v�7��"��&�<c_��%T�!1�GDD�]r���j�tSG4����.���y�O���=j�er|J�� _��Q��3D47	����5�Z��_�.;�����y}F���v=��������O�B��f��W�!��������1�6?�0�6�M>n���3@�4�L&�L&s:_���������GDDDDDD41�GDD�Jj�3�'�R�i#�=.��
��������v�b���o�����RF������Y���.��(�T~a4�$R:�8��W��Jl[�T����\��o�"	XZ�@�{j��5�vX$��h����F<��GC�c�m!5��� __����;�
`H����`�OY2��W���J��#"�����}�b��g�q
��Zp��#H��pW*G[���������v�n(������EQ�(��O3M��O��7��Bi��u��#�Hd=�npr����g�������OM��&��>\��a�F�i�***r������<��Cog�����
��"�hn��!�
�Z�s7�m���OA�"����;�1���[����1����~��[!�":�Fq�o}1�����T-A��H�&nDFq#2
��0�$
����v�����:�5��,���_N�N�l��9e�N�L4��� F�!�lRfw�p'q;��x�S����S�Q&Wp�k"�S|�+��_�]_�\��]�������]#�q�?�;}�X�}'�4#�j
��#"""""���,C�e���������/]�o���e
���s�l]IDATe�?��{DDt�h2}P��*C���h4�q�;���P�.��H���_g_��i�{���+��L�����p"z����.:��}5���,��<�4���>�z�/�`�����-wa��*�S+�m5��:"�{}w�������n����������{������&����V�h@DD��E� `[��m)����Z?B� z��|��H���L4A4���O6���o<���� �soC"Z|,6���q?"�h;����Fb��V�L����G����p�,CCS3�=�{iYWNDDDDDD4=Qa�Za�Z��;��/����iEx�7�6������~l�#""""""���KDD������v+�i8N{\�eTTT<����0t����xC[��
{��r�9q=��������[���!�ae4���~�Q~�A��r�y�X�����c�(`I�K�������1�4Qq�/���X;���X��fd������4���8��8~�����R���>O�=�}�6��h�*,.�.�P�Bj�x#_Bj743��	#���5t��D��X}���+��)�(��y����Ax�����W����q��q������s3�F��N��?�������v`��f��k��"DDDDDD4�Mn����6���~�������(�����{DDDDDD��1�GDDL�DTM�f��!�{�d���i��n������7~�����	����������`�6Z�o"�O�!bk�S�T��o�n���G������@!�zO	��s]CX���n�qM��YAPUjCU�
[�\������X
}c���_���|,�����Vq�#z����:)�W�:���}�����E�a�c9�9��@4FH���oXK�s��0`�7���d7�q�����U�������^��������U����X�����z��D|8����T
����cGQ�$�
���a�^8�+
�p""""""�"�i��a���_����PU5���k�K�R�X,�u�ax�DDDDDDD���=""��
$��o�>lp/�d�z�u�|��v����d��o	�k�qEs�a83p����w,�����|J�H����0L�w-�����������4���������Sx���Eh(��f�W���^\���c���+*K��������x
�A�Qt��&�����Xs�7�D�hu�7Vn����i��v����]����.�)� ����Q|X�-�Qmd��o,�QC0���DF�!\����Y��JY�2��W�,�M��m>"�\�5������/}�O�@[k:������A���Wq�g�a��O�aO3j6C�c�3� �$	�$�f�e=�4�iC}S�-� ��������\�n�z��EX���A��!@~IDDDDDD��{DD4!S����0M�p8���fCII�_;���~������i����3��r�W5��hCh
���N�sq��N�~(�R���\4�H��g��G�������|�M�_��~�u�O���,���_��/��	�3��5S�v~��m�,���r�
5�h�)�olT�pkR�o��XS_�`bV;f0��'w������J��}
}c_KPU�@�a����zy5�KV4CC$��58�K7by�O3S&:LtN����o��)TX\�����B�X�z�N�����;�6�~��9_��5\9yWNC�����}���N���+'""""""�_A���B���
~����9�6��!�la?I���+�
���hB���Ca���n,��{����So����a ��v�jw��o�7��w1�u���H�Tc���,�x����
s��/���~t�?��#�6�?������Q��m�FI���~��g�{?8���=_��~}����Z�P��X(�����K�t�����u����?c�
��2��q�{����YD������<�_������!1�GDD�De�m5��j��,2�
 4��IM����A
��0�����v�"�������qv6 ������S_���%���C������G0��w�
�p�_^�����G�����7?���K!""""""zw��r1��/[�O����|�i4M�x?�d�����~�,C�"<""""""Z�#"�	}�{n%��2��������O�����Gf����U�"�h��
'������Y�uY<��}��������0L���W�w�����yQ�����u���;��������_��g��l�g7�g/������e�HX�+�J_�}cI�����D�o�����YJ�%R.��q94|��U��e����W]a�,��2""*APn�D�����ICE�����F�^5��������@g�:�7��nk���|>[5�R)7� ���d+�n����1	���wp��;��=�l��>���O��rcC�~44�C����+'""""""Z�f��gF����Ms�v	�#�4�L&�L��>�$IC}S�������������M����z���a�D�x����(�_;����8���q|��F�}jw�4��'����rhYW��+wC.�I��`<�=}�|�n��f����|y�R|�3�X�r���W�X�W_���n�������������.|s�#h\�po��"��N�{���i���@b<�7:��/����z�����
\��zx��1YPSi��� _���K]v(2�<�������{j�u�4���Ch<���vaH��|&LD�!D�!��P"9���m�p[� 	|$��*�x��w^�g~�K���#������S0��V��������)�6=��M��l$�O�Q�(JN�k��	]��m���k�����]��H$��{789]������������hq�'�DDH�R��@uY<�500M������=C�����Pc�D����=_�f�W5�L����s8m�f�u�e�v?��%���:���������G]�g��c:k��xyG>��v���d�����5>\��/?��'��vgC�O�
*���XS�MK���6Uc������D�D,s;�����gL7L�%p+2����V�����o��a��/�����2&@��~OC���,s9��}FDD��(�p[�p[�XW��GR��IR�V{�#����n�.�F�2@dx�~���|Jvi��"�#���lE���������h?�6C=�_�4�q�:�����v�ECS3*�K
�p"""""""z(� @�e������|�02����-�6�La��c�,��������h�cp����j�p�p�{���DQ���z������t]��vLE<���@q,�^����������Y��+�h�>�R��+���&^���;p�z����$
h^���m������|���_����q��4�E��=O�������D�vTW��c��c�i"<������Eb��9��L���k �c�������P�v��]�Z����p�S��FDD�_v�u���s����H2��x��G�BLO�y���M
=���w���c�r%|���0�R�J��7y�CsV������m��:����P����������z�u�z�u,��
M�X�md���EDDDDDDD�OEX�VX��������E�(b����X,�~�6��of�� k����������6��JDD����QM�Z��H�4����s�����o>
^��^�I��_x	�Uk������v�5�&�����>Z��U��(�����4���������3���+~w�R��'j���c���@�����A@U�
Ue6l[~o�4MDG����|�M��YH=C	�%p�f��1�S�h������%(w��a""zx� ���S�i���J��v!��������0=��cp�WF����-0��jT)K`��@CD�� �����7#64�G[�v�m����:����y�
��2��	
{���^Z�U�\!L���������,��S���k�[(m~&O.DQ�����??'"""""*<���@���K�<�u�H$�������Oj,�_��_�4����k�c��~����=�i�m�C��������J��y��eEZ���!��x��lTm���t���{;����%�=`��A�v*p;<V[y��@,�[M}�~��CdD���������8}���y���Zw�D�o�WW��h��r9J��X�\HI��=��z�.$��=?&M��7q;~sl
��z�S�+��)���|n#�s����?��^��.�G��\9�>�o*������o8����z�:445c���`�*\9�3i�3M�adl�Kw|!0��BUs{_y��������DDDDDD��{DD�&3���"�=n�Z��%�XZ�w�
�S%x���
��8�x���8���
��Yf��n���K�"��fCJ7���~x��:�o&�F<������.����t�
�+6-��olD�pkr�/�i��g(Q�����0�'��+Ud�z������T��?��E����lb��41��"�v�G
"�va 5��g��0���E_������n#�O	��� 	|��r#j�m@��
hz�\x�0�[ r�����u��.]��W���;�qO3����j"""""""ZhA�$I�$	6�-���iN��z���A�|s��������m����:��I���������""�a����ws+��f<���h�1��;�o�]|�0.�w8�����-�y�����s'~�#o!����u�OT�BC�c����
�oD�ONu�����8��'���?�Ue�?� ����X(��@�}c������ �(:�bc_#1��P�Zp���s]C8�5t���"���@����������� �������'*�nTZ�XS�������_]�U�����
:���f�*n��DH�*>��j��|J�����h��9�x������}�2�����w����;��Q�myg[���*445c��O�j�p�DDDDDDD���08����Y�&�~!�i���_���$I�������,���C)
z�����{������<�5�e �����o3�������,��f�n�8=pgOf=�L��^���*�"������^=��7?�FR����[�U��uxv�Xe�+$�V	���X�/�oL�t����
�����n�N�/��q�g�z����"���Z�>m�T� K���g���u<�Z�#�^�G�a�� z�.�A�����}"(�6~�L.�h����Qi�@��ED�	����5�Z��_�.;�����y}F���v=��������O�B��f��W��."""""""*��m~�����i��d�����^}q�}����MNf���Q���DDDDD40�GDD�����L�D$I;�t:a�����������/����`�	�~��"����S�h�����z���ux��V�Z��Q�$5�9��W�w�����y�$��MK���:l������fB�%��rbE���?)�@W|��/6�k}���?PX5���k�#��;r��,
X�r|��7�kM��Y""��$H�*~x?6�Q��6<��JI�` �yC� ��A\��T����m���.�"������8���Yl��,B7���P.�$��4��q��@[�x�����kw���()������������PZ.������o�13�F���i�H&�H&�9�/IR�P��cl�#""""����!���/������y544���4��;����?�)��\J;&J���w`��^��n�^��H��:�y�`�N�^�rn(���z����N����O�=���L�W����>��R���EQ�)A����xu�D�`��b�������UmvB}�a�fd7#��m����>%�7�����������DD��9�R8��x�d5 e�I�R����%��C2���������sY<�)�l��+�(�+xs��W������?���E{k��^��5�7�������~���w�aO3����"""""""��DQ��(P������	]��m���k�����]��H$��{789]���������������=""��s)3o��p8��� p��t�|�s�N��g�w|�+��XU��f�p<zG>�z��Z���QaqaeTh�i���������)}�;�m������C�z?,����A�T���=��s��a��V�}������:�������v4����;&��2j�C}w}w_���?"���"Z��V�%��|����6���Dz� �S�[�T4A4���6�M���T�o��T�k�A�gN"ZX,6���q?"�h;����Fb��v�L����G����p�,CCS3�=�{iYWNDDDDDDD4����<:��0�������P E��H��NI�$k�-�����8��Hr����igz�����;�;�9�;g���|Izq�'���N���-��6K���ZI��(�b+�
[�����Q�
UX
������s������(��[�yA �2dY^u�_�@�Ra�����T�onL�e. EDDDDD+���DD�jp��,LNN�koo�,o�_=�l?����������u8��>���Z?��$������=�	�w�
I��	[�nZ����x��8��i���,��7t���1�nm��6/Q���AW�����;��d�X���e1[07d����02S�KS5���6�[���������N"Z�v�*������[$�Q$�a$�a���0�����`�1������a5�h9���u�/]�mM���{�������WN���O`�������/���x���b���q�����#|���������v<Q��*TU]���6���~�a?����H��H�����G����O���DDDD�2>�OD��,y�~��Cm�����I�v��E"�����q��_�g����=�>����Ei�g�|���L��4�Lg�������A��o�fG�2:����<�o�:�Tvu��U�i������sGw����
{��FD�"A
��j�I�s����Rs_nM�O�e"�c"����T�X�_E�W
�-���>�LD�h�}�=���������H��OA�l|1����1^�xq'�:  � ��F������5I�~���he��������w����!�|�8����O����a���������}W7��a������5o�DDDDDDDD�De����Y�x�q�l���[����f��k5DQ\����>~F�=�r9$�Id2d2tvv���;w�@�@�p>�ogJDDDD����7m.}#l-�{��q����uc��}��{��%�?��?@0^���*���/p1wn�cwi��/�q�p�e9����Sx�D??=�n|U�c{Cx�x<�	Y�JoDk��Sq�O�
��j�fS�� _<Y���O��?���l��"���k�����UM}�!�C>D?0""��DADX�"�Eq7�f	}���7�	=�k��X��dg�~�,@tj]���|Q������hk�����_�=�������2�y�	�|��sL����o=��������p����\����������� 4��g�v�@�RA����m��]_����5�-�/I\o�����������������Y���bdd�`���hoo_��Q�1�GD���,��I"�rc7ut]��l���C��
xjjlO���u��#�?���_���DaOM�k������8nl��������a����'pft��s���������.7������pO+��������������������d�`����3T���S��@��6�C4��(2�GD������Wc��j�i�HH���G�(#o�\���)\�H����6�Q�]Z7�ZD��7�v
YQp���p���0���g�S�>��tm��Rl���W^��W^DK$�#�~����&����������*	�I� I�������
�m�6�|>���sm~K��qq��1�x�T�����i�;w�P�X�����DDDD����"�n���j-m{�dr��H$�����e�����)�~�����>�?�����q�5�*^�~�o\�KA�y����4;r��T�|y��eL�_]���������n��Vo�m~M��]-8���f�`X�<�[���R9M����MW������
k�Xn�����������#"��dQF��]�\�����9��r#_�0�I#��{�FL��6&q.s�
�=2��J���+/����]��s��g���o���O?��[o�qV�P��D/~��q�{�������}`�
7C���DDDDDDDD�� �����,k���_�A�m~�!���~�$1��J�lg������R�fggq��A�|>�fGDDDD��="�n����o4��8&&&���|>�����v�^���0��{u�DI��_�WPV�r�V�33x&�SV<6������G�����-�����Sx�DO�I�)�s��09�=�t24C��x	��A���6cM���R�/���7��ap2s�R}�i�|"���L��"	�����Un{��P$��mE� �EiC�����E[��>��>���0����k�,::��Co��7�u����j���z�t# ����mJ�e�?z���lr��}��}�T�{T�8����
���+t�p�����BK���3'"""""""�f�k��4m�c����
�-�YV����������U'W
���Q����f�Y������7bN�>�C�1�GDDD��1�GD��9���U�a�F�{�L�B�f��h��|�����.9~��Bt��u�Qs]�_��?E��-{�	�:�����|pu�M���a|��x��J��������=���@fHDI�E�	��'���3-�3�S�@_e�o2����F7���Y\����I���v/�C~�w��}����>x6�m%����C�7������X��/��`��r�z$�	$�	�N�	�Iti��j�v���	I��'D�MK8��������F��7p��'������W�3of2����m����E���p�}`���B��Q
�vTJ�zW^�����*�;��,��&�qP,Q,�nQ>I���-��]������g]vZ��3g�����[u�$m>����h�<K�pj4��T��B���u���4~��������#7��c]��,�c������k+�&w�������03r�@*�o�4����2�����
����~|��^=��G�����>�������c��`l��H���}�������i�R9�j���t�z���?�Gln�������f':�:��
^�[9$�A�1}�1XN�?�.%gep1ws�� #�v��|�D�nx%�VK�]����7���"35���|
'��fc�?�� ������:|�m8|�q������y'"""""""�MOEh���6?���m����]��,��eYK._i.8�\�_�����/��0����0��q���������hSbp��h3��&�����ll�F*��;���UU�4��pO��?G&��;�	������A��7r1kL���c����g���������{Akc�~u!��N��������K���#x�x��(n�����9DQ@w��m^��z�qL�uL�OV�R����{a�F80<���t'����#��U�B�r���3�&��|���!�+��[��Tqc�F�1}9�����X��1}c�0[��*�#Z�ui�hW��b�_��.����~���������w��3O���/��V��lnf������?|}�������[�C�
�DDDDDDDD�A �2dY^u��J
~��vz��Ra��1Y���>��������%�J!������!"""��`p��h�<��{Zc7.����\�)��inku��'��+'�����t�o`3\�����_�p��q�*�
}�����h�2����>��^���D���5�u�n<t����	3$��Dt�x�����XG���8��� _�d��M��S���$��Y�Y�^��T���:�-}��_���v"��D$tj�������A�J#Q�K�����f�)��S8�=
P�Z7���|��.���+(��$�"����������}�i���/052��yO���S��l����#�?�P��&����������vQ����H�k�[*��8�g��0��i��b��m~###kz�Z��������f.�kl�������%IZ��#Cx���-9~��>�}���n�i�.���gp.sr�c#j��|�
o�lf'2��K���C����jg��S7����G;"j>A��W��WqS_��139�� _r!�O����0��d��d����j�Z�JEK_y[���*���6� �-Z�/p@����>����8�xE_�l�v��S�P!��B�4�P����|]Z�r+�� ��|-�������M�9�w�y�_�,c�P��x����������}��cwBQ��u�Q�c�$q[��NDDDDDDDD��l��x<+�8���}��l����i��k5DQ\����>A����N���OQ�N�������������6/>�MD�C9,���X#��b������c�Ph��5�2
<�g
S��������u�K����xj���6j[�������H��3�F���_���'��������p��(9���B|X��6�V���|m����f,��He1��!��b��H�0:��U�a&o����=4S3�d��|������a?:��&"� ����������K3p��������$��L)����A��@������^����]Z7�Z�j����D[� ���0z�=���2�}�Y�|��H^h�<�g����w���������"�{\���`g_|c�#q��\v���������j��n��b�^����������>AV������j���;�m��C_����EY�E���$������DDDDt��$	�e� �u5�K��~2�4<�����~����;&�2���B�V^aj3r��o���_�������{�E�o�:��1�7��__�7_�@*���[�
>wt7�x{?vwp-"�z��C��8��Z3V0,N�O.���#�y�T$��M�������1�".
����~�j�@�#"Z/�����hii�<��Q���H�#�Ga:�=@��s���C<�@���E���j�����GD��	p�G?�?�q��w'�ygO<��Q���,�z�'x����k��8r�8p��.�p�j\|�5��������^w���<�6^��w�s�n���`��G�|]""""""""��$I�$I�n���[*������[6�]� """"�t�#"��LO����]]�_���<��y@q������`�����%�W:_/+��R?G<wa�c{<}�7� ���K����8���a����/�9��#�c��
=��lQ$����H�:���`��nZ��c �E<�+mS����<�
J�g��8;��Se������o>�����,�O+1�N�������_��vl��H��|c�ad��`�Z����G��G��[���U�u��� ��A@���}�������/>�w�����E-e��y�]8�_~���w��� �w������Y<�������5��0|�4��ON��w��/}�`K�� """"""""Z-A�(
eu�[��b�_�/Z��d�8���3�����e-�kQe���"�f���������u�I�������Zr<v������h�<�a�0�g&~��U�$@���;q}��|t�lO�I��q�x�f��H��E���n����nD��i���"\�
������|�o!�����<�����X4m�?���������v�BC_E�ow��������ADD�("Z�q k�K!>}����l��wG��A������"(��v��z�vA��f;<�v��|��C���(/��3O���~�b>��s�<�y��x���#����{������k&.����"35yE�?��sz�$>���H_���EDDDDDDDD���6?M�V<v��o������e5���VbYl��$q�o"""����="�����B��V?�d2��X8nxN�r����#���L��V|����"n�c�������	8X�A( ��������Y���J�sE��k����0<�����t�U|����������m����E�_n�"Uc��`l����BC_<��@*�x*���1�>�vO�O���CE�����>��6�G_�����/�W�{��L��D1Qj�+�`LA���`�Z���� �������B+���r;� �d�{�!�w������/=��O?����5t���E<�W����_��cw������U��O\�w����l��yg�&��?�����	�{DDDDDDDD��T��y�+?Cc���
~��g���6#���������v(s���mu58��dp/��i~c�;O�����%�?���������MY3�g��c�py�c���������I�;2��N��������A������1|��]e�D��y�����}�c��`<�#�\�Un3��!s�`h*���<~u�v|W�g>��W���X��qDD�4YT����]�^������9]n�FB����"6k1e$1e$q6��#z��K�|�nD�.(���!��Q<���8r������g�����m(hgu�~�)�~�)�z�p��p������[�B{s
�~���
����7�������������6Q�i����,�Z�����fi����DDDD����dK2E�;����a���i�Qw,�������e���c��?�	���h��������e�g(����I�����`�z�0l0����wx��8^��o~\�,
���]x�x7������h	��h��n��s�l�����k�+m/%��-lL�Fg
�)������v�iPta����M�Z��V/DDk!Z�v�*��&p�[�G1V���#0������`�1���"D��ND�tyJ���t�zD�6���{�������WN���O`�������/���x��������T��V#35�g��5<�_m������������A �2dY^u�_e��X,"���_�{�$Ibp����hbp��h��h�V�[�mOE�B��cn1
����
������~�KM���,������T���mWB�`��P�����2:�������0:Sh�����/�������6&m6�  �h����f|:W��U��
��Hf�0��dFG2�X���������������b��6�G�Oax������n�������)#9�K���5g\��
�1L���7��|#_���5I`s7�FPT
��u/���^L���3���_>�|zv������&�8��s8x�=�{��Z����������h3E��BU�O&���]�}�+��.����d.��J"����������+�wtt@��������(&.����W!��7�c
OM����g\�c�A���QN���q�����W��aw9�����*s,"��������v����F9�7�[h�K��_t`=L�L���������GF,�G���
����C$���"��B�/�v�n�����A�	=�k��Xidrg�~�,@dD�]�A���
���
�D����^��������x��/��������6zZ�^����#""""""""rI X�����_�k�{�#"���j�[m�^*���8u���������^�������w����p_��sp���i�*�$�X�8U�������:��*M?;5��N����t��W%�n>��uDD��=
���pOk�X�hbp2�x2W�H�02��?^5]�`���N��C�T	}�@_�W��j�@�#"��'�G�{�W(5�O���F���0�v������Q�2F������D=��j=�������&Z'����cw��cwa:1�S����}���
����SH����3""""""""��,cddd]�GDDDD[�{DD;��80�+�%����UUEkk�C�n��L�g�����������?�����h����x/����v��p��hQ��?1�2�.�[��o^�D����h��/�������HPk���h���2t��@WK�X��04U
���a����t��1��\����4���k�TYD��!?b!���m,���Vd���DDs$AF��]�G�8��L��o	}��	8p���is��I��������������"n��z���-��;?��}����k8����������=�<�dp������������|>�A������-�����mn�����K�<&
E$E�o��4q������7��p�V�wO���r3�u��m�x����M�0�'����1c����
�����; 	�:����go^��c'����QV�������1<p�
DD�JE��� �uk����T�&�Oeqy2�����P4m�7��{���1E�������`�=m^�2��$��M�(mhQ��?p-��"/��(� _�0����""K)�:.�/�r�RiR#���|]Zr��_M�UI���G�a��c�MN���O���O"��X�y\|�5���������@-o%�5������[�����Oa������NNf�(Wu��S���-�HG�����LL,�0Q8^�<W��'~��o����G~����ymW�q�J���'��
k�c���ED�7�>�#�����=��^������_��">y}7>������!mM�$"�#���Y�����|�����<�`8�0,�Y\LfT��(���<����/7����vw��Q�h�L������^o?����)#��>�1}�����Y-��q$��8�~�����Ka>O7�j���5AK8���������?���`
�v���K�����u�$Y�	�����}��;�_�x�h���=���@0m[����BH�RM�F(B{{{��ODDDD����6T�l�2>���|��M�H�Lbo���"��T4�9��d2Y�u~�>�o�s^Nr0����������@����rm7��~��9���xl�'�{#�O�}0��76S�_�<�o�:�Tvu�J��|�X?>w�~�	3$""Z�$
��Q
���?���v<+l8t�q�t�,��\�6W\~1�f�l�'��<���U�	���S
��+���!?���D�s��5�5������_&��r#�0��c���k��.���b�<@��������.O7�Z7�|�J�S/�kho%�i���Q���;� ,
�-
V��P4���rP-�E��b""""""""�b�fgga���V�X������oDD���n���r�}E����c,��C=!th
 �NC����G"�+��R������Oa-qc#��;?�pS����� �N>���Y�8"�����[�r�&s������8~~z��4|���v���1|�`rE����h3��E��--8vU�j�qLdt�r�_��K�,��B �p`d����^�X�*egP[h�/4���|h�(0c"����|���!�����8��
�H�������,�������li_����r#_T�A��(�}�ZX���l:��b>�b>�����uQ�_���� `UPp����(�/GDDDDDDDD
S����aY�-�*I<E���DDDD[�{DD���n�gCI�D�'g���P�
�CS011Q�8A
���]���Q$/��U
~���7��	�����	�1��������?�	tj��af;W���o
��xwt���{�yc/>��]-M�!���A:��uT�9�����x*��T�f;���Z���u��u������ �\C���m>>�MD��$H��v�S��#-72�,���|	}�b��O��4f�i������N�QO7��tj����k�#��$y����*L��("�n��RQ�h�[���-n��
���y �7mw>����3g\i���|>fGDDDD��="�m�`�xr8�ZhoN�v��p
�
!��m=�������s���������=�c�zw�~�+�1g���O0��x�U��+�ah|��i��r������
b:�����^<t{��e7Z}|�����?A��W��Wqc_{��L���|�o��/��a"]��y=��E��E�18]3����
}~�B��m8�2�GD�J@n�>����]�D1�Da��������Wt�*�1T����P"�*7�E�n��m��������@!�^S&��c��sY�97�Y��������h������`�>�>��������6�������x|���V#
!��i����h�`p��h�xe|9�n��s��GSh���?��~���~�_��%����v\����~�+u)��K�|�� eA�����>�������)<v"�'�M`-y��������=�	I����V��#��8��Z3��MT�J�RS���{!�F�L�34�w�fj���T
��}��}~t5��9���8ET����nOi��q0cNa������1e���z&�	Lx7�6�+�-���n��.�"oM	���=Wa����zM�qw�/Z���0u��Qt�DI�
�-��5.
j���������������
)�����#cdd�tz��
����F{{���DDDD�u��"�m�r����|S�1\�!(���eYF[[���rl?�������f	�w��_���
������~���7W<�C����O�]
���v�\����9�o�����o|���>}s/:���@fHDD���5�v��������a��d�&�Oe1<�_S��
���wGg���l��G���G�Wn��!*mw�z�'�-I�)hS:p xP���G��G0�c\��4�X����C<w���a-��r#_T��_�{0����]����[��p���S�Q,`��[�P���P,��B��U����8�YT�j���B6�n[� @�<P*�l��
�-T4$�E��������v�r9$�Id�Y��i�����`0���p8����3&"""�f��eDD���I�X����&�
� ���?�1�o�^P���������e�LSxj���4&V<�P�F��~�\6���/���__�l�l��{�~<t����-�	3$"""�"a4���`�X��14���Un/O�`nP��`�8�H�]@�D�vx��|���v/�m%D�ux$/�|{������	���V���02Vm�y�l��G1�������_7��t���,����w��~w��w�E	������@���2����\�����x_��W}_/<h
0��ks�8N��{��i�N+�r���r�O��		z�n�J�eU�T��-������033���{n~����Fk��y��������"�-nR7�(��,9�����c-���D\��x�"^����?��O���
�^s�����)�8���M��������:�n�s/���c'�x��8�5<��5<|<���@dc��Qe{#����-�����B9���h��a0�C���f��e��D'�5c�(���������j���M�6`�DD�'
�F���a�����F�Da�b6��38m� m��B�@tj�*Z���I��G�YD�b�9p�gO7�Z�#�k��A����Upq�-��jZ�������_�o
�	��F��e��2i2��a�� ,
�-
V�������}��5D�?�Q�����&""""��#"��.���z�Y�O~��z���];������),�~cZt�>���_t�zW�h�x!�������zp_���-�0��/�����Cx��x��W�d|��^<t,�=a���%""���%}!�B>��FX������@�d�����am��-��@�� ���1A�[���}��}~�u��U��0mN~9���5���`�&�	$�A�1};���L��Ha#���}�J�r�����V��6��p�'?��_����O~���p�(I�|~h>���8���W��U��������0�Em�!���iR8��<��<�;�4YQ5��k�k
��W/<()
��""""""""""""���#"��&��moNAV�����>t��7�
���������}���d������>��'~�Ysf�coj=����C�u���vq"�o�4���>�����P�:x�X?>uS/�"""�$Q@O�=m^�W=�8&�:��\m[_2���'��8��t��y�x!U3���A�W
����!ba?���6YT����]�^������9��>����0&�����2R�2R8�y�������u#��AD��"n�}�F���(�q7���\��q�������M;�V"B)d�y�s��i�(�����_���!��@�^po��"�(�4���g];� ���@u>��]��,�_'<�y ���LDDDDDDDDDDD���/"�-�q�tc]���U8�Hd��W��k/��'���}�|�=�]o-��;�����`�^�X��}����[��mO���������<~���p��(9��B\����h�-t�xp����1�q0�-.�m�s��3v����fx��d�X8��.�W����h�1�BDK�*�hU�qu�0@�u��#H��|	}���D;������!"�v"Z�ui��-�]�������1��Id�j�R�����/�~^�&�
��O ��9��1�8��U���o
�
���4S�D�mC�e����,-t7T������@�����6��yDDDDDDDDDDDD�
�{DD[�a;(���^�%����UUW~�*d&Sx�k���������~��k�U������b�_��>�^��(������f��������H�~}�W�o������;��@DDD�A@(�!�ps{��t��������@*�dF���$3E$3E�>0U3��S��#��l;�*0 �
��v{�`�w�vlLI$
#����G0kN�v=6&�c�(��T�
�_
"�u���������	I�\�&�[��|������B6��y=�>��o�!��h��M�x�G���k�8,�������`�^��o���;�����3��S�������@���z�A����i|/BDDDDDDDDDDD;�{DD[���
��q���=�������PH������?���~�?�����O���_Y����������0���H��������_��@W��7n��W���DDD�6m>m>��n���&*}��`��la�'[6�30������k�������@_���3�i�h��B�/�v�Z��Y��F�L�c��^T�J�b�.��dAFD�B���j�\x�6�H_���?����q�y/���O��#������!dE��(������-���|���>}���1�&���ql��H��-�l���0�"�W���-��*�k��A��QHM@���=����A��7m
�T��h�1�����vwVx���?�����
>���%<��+�j��X����xk���m�����'���af��e;x�L����R
�^|��(>�m{:��95U@�q����[k��E��sA�,��\i��ad&gc��@Z7qjx��k��*�C>��|�0_9��cW��������|�{�����`9&��8�0��R�o��ta:&F�!��C��Z�vD==����z������6L�/����/������/>�����n���/�i���(JP�>�^������2����BE}���a��`��i]�#��q������.��o$EYjs-Z)��U4V��+�e�M�DDDDDDDDDDD�>����0E�����=,������+o3K\��_}�K�����������E���S�c\]����kqg�CPEuf�}L�����.��/`h��7�}
>k�x{?���M�!Qc���k�������D7-\��W�����<�u���R��pv,��c��1U����h�[h��n�@��
�1mw� #��F����P
md�Y����0R�	8p���s
3�)�����6���z�vA�{~ZG�`���������}CgN������'?��7m���� �U��-�g��mYU��m�!���`)X�}�1�R�d,�@!]�8�Z	�X�����U������V��j���G�(^�g)DDDDDDDDDDD�u1�GD��	����`4�~+{�":wE��<F�����Oa[f���}W��g�p��Y�����|�	}��dA�]�����u���pft�����o
�`�
��pO>�'���G�CDDD�5h��}����m�6,�S�rS_��+�x*���y��frC��qa<����1Y�����oa����*3�GD�A�A�����q}	}d>�W�������r�.�/��!5R�u�K�A@na+5����b�MG������1z�<��=��B����^���]��?�p_l�&L�E��������vN�q`��v�����>�_����(Dh�������}�c�������z^Y��h�����n`MXP�@R�BDDDDDDDDDD�E0�GD��E<�����6�4��o�%�F���)/>��I^�����K���L���
���?�	�)�0����l���=���&~�,
���]x�x?n�k�C	DDD��(��X��X���a�v0:��@*7��'��������L���d��YUc�t�yk}��}>.�@DWLU�x����P
KL)����L����\���8��q�N�	�I~D�t�[��Z'$����9�}1�Y������'��!H"�������^�� P�R�������i,�*�z�`���	
��
���iEfQ�Y��w�P+Z��j9X�["X(�<D.�BDDDDDDDDDD�6>I@D���	z��TmF���^qh��+/���O,9~���S�wu_�55YL���c�H�x�������| oR��e����i���p@�n������h��	3$"""��$Q@o{����}��1�v0�����,�sM}��6[�6d��M�14���.���j�T����|�/����&��	��v5�v5����y+�q}���W�Dq��^kQ���R�<.��$H�h]���|QO7|�{MNDsA������=m_��@
(�j�����m�������b9�g,j�������p��YTd'rlz.[���Y��������`�>������d��9m5|��h���D=*����������@]:���_��%��9�\������pg2o�����Vx��#zqO����]�N���N���q�����s��6<r�;���F"""�zDQ@W�]���7T5�8��bu�o>���l���J�Fg
�)����mX��6�[�������>�h���������[�����|�/�#c�]��c�0��a�Z�6D�nt��|�J��&""�Xsmm��?�]9��8�L�N��RM��A��}������huL]�����{�%�n�_e�o~�V�o���X/dMcp�����������������#$Fjzu[/x<ko=�m?����B�~C`K�����n��V�������������������0���h����Q<v"�7�~�"	��u�x�x7�ns}~DDDD;� �5D�n�u��O��5
}���R��/
����������S5c~����W�U
���>�ID���R#^D�����s	}c� _�8������5��^�]�"��j���:�nh�������6� ����lq�����x��'al���7�U��[�����``�&,Xt���2Q�f��\hM���,j�.j
\�����E�����#"�v�=���b&��k��Y���]�9^��p���u�A�G�������k��XaOO�kv�����8nl����/a<]��^��^�x����-~��~|��>D�|`����h=��T��S�.�0[00�������6�]��{n��1�-��:�D=�|�o~.m#�1Q}��W���Dql��/���`�w��p�*`�00�d����z���FT�A���?�����DQ��������+:��(��|�����8��_\��Y���?2������LLR��`_E��B����v�`���������������h�cp��h����cy9���be�DWn���5�c��y���_/9~��~������8��y�M�
�e��KA��8vyz�>�����)<z"����a-����[�����>r���P$�f��Qp���{Zk�����������������$]0qrx'�gj�|�Tn��Uo�>D��"�$�ET����n�n�{3�����|SF��kNILI���
��>ti����|5
YT\�&�N&U��j@K�{���-���������o!,h�(��!��P ������X��0PH/��c#A�j��l��	V��h���P<D���DDDDDDDDDD[�{DD��G���~6�D�v��\���{v��m�����Q������)l��;���8���]�4W%kf�l�qW<6������G�6}^[�nZx��Q<v"���j�^�*�����x�x����DDDD���5w��������a��dn���r;4���oS�+Z83:�3��_j������rc_w�C}D;� hS:��t���a�n��G��|�H��0�v
v����"D��(��nti=�j=����GDDD�%	����w�����,�Um5��U��aAC����L��9���F1�C1�s�����jZu����:<X"�d���DDDDDDDDDDM���6��)�hoO�\i��m�g'�����5�����wL���S�><��Qj�����Kx6�S��?� ���{p(x#?��06S���2�o�:�d�����[=���~|�h:�jfHDDDD��H�
b4X3V4mO�KA��B[�@*����
J�������'25c�$`w��:�.�z��l�&��4��>����l��dqb��/�� m6���Rl�/�b�8��x�Z���AT+����D�&m7� ���4|.��g���^��/�m\|��o\�Ndu�E�Y�~�%i�������[E P� ��9����������v6�����M�'�;���.��k>O��E4;���(
����t��'�����Zr����������Y��r,�:���}m�c��|����M��V�8~=0�GO�����5=L}��<r<��B���DDDD;�*���cO�\S=fZ6Fg
������`�dE��%Y�rp1���d�D��$
�i��?��o������}�m���4wa"�<DADX�"�Eq7�f���7�1}I=��Y��fq!;��3YP���BT+��uj�����]�����IV x���:�
c�0_��W�X�������p��y?���=�����z^�2�����u�i���$Yqu�DDDDDDDDDD����6��D�����A/NNe����!�g��"`,�����>7;1����?/9~��{q��{>�j�Sxz�'�(��x�5�#���>("��
���5�GO����l���("~��^<|��Z�0C""""�NdI��vw�p���1�v06[
�
�r���&K��\���9[����R[��%���n�V7��C}}>�T��#���r{�k��_J*���dqc�H)�WA���v=�10R�Hap~_�BW��/�u�M�X��"""��D���������qX�Y�p�@�^
�=����2?ZC/72�WQ����U����iu�+�5
��Y���25�""��v�=���`J7p1�G�P�D���8M��G�f�@r��9O8n���m���������������>�j]�����_�p�-*���>�}��M��V1<��7_���6��\�+����C����[v����N����������6/���8~U���8����@_�"�W�>��2g�)�l=<����S5��
�!?�;|���U�}A�&��dQF��]�^�?�f�i$�A���&�����i#�i#����M� Z�ui��h]\�����65A +
dE�7��"��m�(�U�?�P@Q���+�U��	:���m�(d3(d3��T�!?OM���)pQ��S��A���EIro�DDDDDDDDD�%1�GD��k
n�J���������#��~�hii��o��B��������o�����w1|�t�1A����+h>_��]�a����8�9�����G>�V���_�"�q���;���&`;+�f�;������;�	I�j�DDDD�>A@g����GcUc��`*g��|Y�����x��]�BnI��H��x��d�X��V�J-}s�}m>l��A����Ui���C���c\�X��o\Aq������/b0�4���*7�E==HA����'�4�������i�7�0t���z�@}a�el�{��q��yWO+)�B�O���W� }�"Y��(H�z(\��?�m!��0� @�m����d2(
u��D"
_c�������?�����j��R�q<5�cL��.v]�Q��~$ag�t�+���7���8�H7�z�*��7�������l�������Nt�Ut�U��W�P�L���d9��\��S9$3���$�-"�-������V��Xh!�W�����V��z�1�zc��1e��(���a����]���d1�d1�S�7~)�h9����AH����M����!U��j@K�k��L�^�n�[�}M ����DHP/���i]X��0PH����?z��5�A�j��l���/mqH�U[|��G�(�g""""""""�f`p���011��X(j�\z.�����c�u�{�m�������qp:�&^��%,X��}�7�1����:��b0��7^��;��������c!:�gn�E�Gi�����������:_��m���&RY�r���,oR9���_�d=��
�=4���fj��\�������� ��h�!5�����y+��>����0&����4"kep1ws�� #�v���������k�!"""��I�I���vN��a��v?�N�����2X\��������ql�9�9W�+�Z�@�Vo��(���J������������h�cp��h��m�T��X[[TUm�|O����x������c_�����X��x.�s��V<����{��/���V�8^x/��N�����5-�z�5<|<���G��/mkM���V��mI('s�'�}s���<�
*-��&N����H�
�EDG9����j�B���D[�W�#����o?�r,$�	$�A�1}9+���,���>�1}(���*�#Z�ui�hW�|����hDq�y�M�i�(���>}�``������|� ����,����.�V�$-�����U�4OUhp�@��AE��HDDDDDDDD�l��p�t�Uu�H$������,�������'�-�����������	2Vz��8�v'nh�mG=L��M���!<z"���?��d|��^<t,�=afHDDDD��x	WG��:��MCSy���'s�m���<���A���a�\"�s���M�$bw����#.���B>��y!K|�h3�������q��f�(�`LFBA�8���3cNa�����i�*h��v�������NmT��E�����h��dR@�'�n;�Q�k��Z�j���r[����r 0�b>��]�#-��,��,��{���y�=����k���%��OQs���73S�DI��������������,9~����cw5<�zl���3/���+>|�Zp������r����D�xi�{}�l���:x�X?~��^4��@DDDD��,��HWEjR4,#��� �B�/���y��yh�h�x"���,�!�z���A��`_o���^�:�C�V��80�"��1$�A�1}E[w��EG�P!��B�4�P#�j���z���[w�BJDDDD�A�z�P=^����,��8,����D P_��*X(�,��36���K�7��i��)�rM�oq@��!��	��)p.4(���{DD;�(��d2u�B�Dqu�
�e��?�(��u���v��/��5��R�L����1�_^���������$�+���l��s�'���8�;?�����@����}!~�DDDDD�"E�_n����-���l����x*��T�TccB}�� ��!����Ec�t�y��U�B~�u��U�#�,QE��=�>����I$�a��#H���6&]����8R�q��~����f�R�/�E!	�h������� ����lq���m�(��!�BE}q0pQXP��B�z.�����m���^{6-�2MX�4
��{'��0��-��T����:�W����<%�w!"""""""�J��8��8�|(��Y:��D�[����-F���;&J��W�z}�M������e�g(���s$A����p0p����|��C��Kq�S��_�����[�����cw���Qc$Q@O�=m^�W=�8��:��� _�v-
�n�`h*���<^����j��?�C,�G��-����M��A@�B����u���GB)���>
�q��������{��{ BBD�"���K�FT��O�m+%""""�*DQ���A�]�gm���x��g��	|��;�Q��&���_m;`������>�0��G��p�y�yd]<�����Z���z
�� ���=��e��NDDDDDDD�Q�������L&��d��d�����������:{�����?��/�k��
�w1�1����8�~}�c��0>�8:�����i<�R?xc�����t���~���amR�  ��A���������A*[,5�%���J�K�,f�����fx�Rm�W8�U4���^h�k�*0["�H^���B��*��X�,N ��`LF�0��5���lX�A�w��Z���F�.O��0DAt��DDDDD[� �U�������Z�Y�U6VM}Q(p�k}�� ��(�4�(��{�&b�@��@�\�_m0pQHP�@�hE~MDDDDDDD���6655�������^V��^!��O��?�q�����=����S
]{�icOO������\�c�A��������3	<�R�n��JDx�P>�m{:�j"�&�
�����;j��s�� _eK�@*�d��3.Ift$3:~=0U3��S}-}��~��a���$H�h]�h]8��3=���(� YL�F��Ak1k�`���{�w���������A����q�zDDDDD;�$���<~�Z���Y,����\�o���2X��:�j|�RZ��Q��P��\=��j��Z��`���E���,�m)�mC�a �#�j<��d�� �AQ�����S��� ���;�����/�h���Sx!�L�X�8U�����������M�����.��/`h��+�}
>wk�x{?z��M�!m6m>7�T����f,]0�!��@�B[_bV_���M�L���������&�?��
��B~�4��y-��
�A�k�����d1��>���0�
�{-�c`�0���0S���������K�A����5�����6A��*w��LcQ�_FA��/n��n�[*<X,�a�w�c'2�:������k�%i!��-��W�=P��
����DDDDDDD��m3�lg���a,v[I*����,<��W3���������|����C�5]�h�������/�S���?�����kmfgFg���8~��0
F����n���c�G�w���=@IDDDDD�K���pO+�����MN�O��}�Ff�p�
�0��n���,N
�������{��\�����������(2�C�6ET����]�^������9�Dacz)�7e$]����������;��ET�A��Q�5
Y��m=���P�
];�m[0u����j�[��W�K���FrZ�mY��Y�����]��V����m�Z���$��<"""""""bp��h[�f�x��waY�+�3�O���C���{Sc#x������;r��q�mw���zOM��������zni���}Bi�e��&���8^�4���eQ�Gw���1������������!>U����j�+��J��x9�7�����7&�W�������w^04?��"�;*����m,���Vd����A�)hS:pM�0@�
H��H��H���Ga8W��T����@��"D��(�� _��
����DDDDD���������]�v���e5A�%�z��`m �4����Vf�������k��d�&�7�������6�4z �� """"""�b�#"�&����g]���,g���u�]EQ`�&~���F!_���]=�����u��������s�����>��{�C�7��u6�TF���v��Fg

�>P��[��;��#��i������h��(�u���6cX6���5��x*���9���L��g��x�fL��n�������������]	M����}�=��1Y�@B_h�K�3�]�����(���8���QO7��D�nt��m�m<A �*dU�7X��Z��������������ze(��a;�z�LV&�B&��I�:��-
z<�P`u��:<X�X
��+5�{DD�D<�a��jy%�0����~���oa�����������P<���V�L����+����������
]c�:5<�GO����GP4�����mx�x?>vd4�7������hc(��X��X����e;��W����r(���5�r�a9����b2`�jL��v��@_��ow�����%
"�Za-�C��53H�#�V�L�	�poQ��5�Lv�g�dAA���h9�������]o=8�[��S��������Q���|�|���F�~�����}���@���?w������A1�G1�G������������D`9X'<�z�����DDDDDDD`p��h[���B*�j�5R�����~w�c���C�����y���x&����o+�qk�]�������kX6~vj��������_�H>~]7>�
���� ��$Q���R������1�v�HO��}s�\��V�����d�'�x���1Av�xJA��o>��_��T�r%Z-��^�j��_
0m�b	}c��a���k�3#��)\����t ���K�FT�A�����=����=�	}z�#������G�va�� :���������63A��UZZ];�e��`_������BE}q �N�`�kZ?�Q�i�O��vNA+����C��("5�� +e�T-mK�5Qtm�DDDDDDD��O�m###�r��K��%V��;rny�7V}.�����	�1��������?�	tj�V}��h<]��_���ye�i}�,��������[�	jM�!��E�Z�������BUc��`"�c �+�Z�]Jf�.�2g�Ff
�)������t5�B~��|���X����-efL�u���.O�<=��?�����|��0&�$��27mLb�����I�&z����Z:�.(����1�{o���1}h�c����� ��xk�ti����6�����L�����h'�d���p���m�,���U���B�K������6f�����m��,�����}��GdM+5���o��b_���Mp�>I�=;""""""j�����\.�t:�.�
tu�� �����	�������ze��9�g&~�1}x�c��������[7����;��'GaX�?XvK;>�GwA��z�� �3�Ag������1�q0�3pzpO��&
@� ���bhZ�d��A���:��:^�O��u�U��|� ��m�O�t-_DM�(mhQ�pu��h��G��G0V��>�������]�`�"�Ks��������.�QO7RKS�-Xy�8�4.d�4��1}?�>�A��q?<��	3$"""""j.A��*����LcQ�_u��B`���:�ASo|�^Z;S�]�w.J2O)�j�!������@�~XPVU������d2���_s�'~Y�����"����E.e������������;:��5��[��E����;�x�Do�4�zU���������6a�DDDDDD[� h��������)������`&o`0�C<��j���r�XC�[&�ELf�xsp�f��##���|U�p@������A5�zc������SFc�F��>�s���9p�,&�,&p:�&�'�Un��z�V���������i���Y�+:����.�c�� �F\��V'�
��@��s��S��C~�a���zaQ�_����A��]�#-��L�Yzv�����h��j�U��jC��6������=��2�q`E8�
A�8�/ODDDD[��mq���=���`Ww����c�w�m+���M�4�,�M����J�|��������L����� ���W{�n��wn���o�C�_m���������V��#��8�[�JV71P�+m�L�02��"3�4[0��������_�JA��oQ�����Qd��v.A��F��Fpm�z@��!Q���#�(��rL����2��;����I�Q��j=���}^���yS�q�x��V\���y�x�o����1�GDDDDD�$�(A���z��q`Fu��\�O����W'h�5�����{���v���,�i�+���z!�����1��eU��aDM41�������H\�=�~�{�����}W��w#����Q�0�GD��9����+~���5�uG�n������k��)<5�cL+{(x#no���u��r����'�x��L����n���G����k��%�	�$""""""�k2��n���-5c����\U�o���7<�����"[����,����d���@_���6/$��h�J>�|���X��Tqc�F�1}���*Y��1}c�0�.�o�*�#�u#��A���v%��Cp+��&��Zho�n�����[���#y]=75� �U��-�S��mYU-s���B������}����� ��n,���I��I�wRA��i��U!��``���V����$�7G�-���������^�=�����1x�m�������!��������L�������N*���jX��������IQ����U(�g�c����I�8�L�X��������`���Sn��a�Go�����O������{�����}`���������G��?��h�f�h�����*��'skZ��
�i�|"�����"	�����Un{��P�p�� �S��N�� ��8�Xi$*�|��8�����9�s
���sTAE���.O�Z7:�]PEm��'�v5LX)ge�����?������������Q�����|~���8��>��\�_��<����Fa���*��s�a��ks�8��<��<�\:\V�E���+[+��K�%Ea; mz��,����p���~������?9�w�����ex�|�����h;`p��hs6h�2A�p�gFgl������R�����+��K��}��#(o��
��y|����k���-H������������F�Om��������m�,bo$���@��i��.��|����S9-{f���Y\��}�F��{5����;��d��M�� �-Z�/p`�EL�c�G��K�>7���NC�8�
�� �C	#���$���=������=�}����]�����"B�um�E��2;;�g�}v��{��--��F,����h��h�+�Q����a���BZ?�Q�i�O7��RQ�h�[.��U��zA�:�4���;&.����"35yE�9��sz�$>���H_�����ap��h��U�v_{7}�K����xj��H�3+����c���8Das�s/_��c'����cXK�����x�x���$r0"""""��B�D��|��D��,���l�,&�-}�����am��-��@�� ���1A�[��_���}�����2�G��"��������t/h��D���G0m�\��)c)c��s����W�#"""""�-A�eHr�"Zk��6�b�"��_�[.$X�+B��<lkc���D�mC�e����dM��Zu���i��Wlk���$Yqu���M\�w����l���e�&��?�����	�{DDDD[�{DD[�$I�$	�:�4�>�O�Rw�)�q���kxm��X�M�'p�����6�\����c'�8�H7�z�*��7�������l�������h3�D=m^��yq|���8�H���r�m}�2��!sv�R���t'��
*E[�EM}�r�������� �����
V��(���|��(L�������>���:���m3�(��U��.�2�E������a��!����������g�z��������(���~�`_��rP]��W\,oeM��E�iy��,~����k��9�l?�w���_�lq��DDDD�~�#"��A��������]��� ��Q�?ge���O1T��x�>�U�'�x%_f���T�|9��{�2f�?(����>sK/Z��"�!:[<�l���=�����d���[���m\X(1�#1���K�5c����r�/V����h���1mm��>�^���l�F�8�D9�7VF�Z��tkq&�nn;I� 	2D�vq."""""""Z=IV�
(��[���-���t�_�>}.�/�~Qx0���,�7���L�w�\�E����������Zmh�^HP�<�d>F|���������_����$������|�)�'"""���O�DD[\ X��^dWw���|�L<���[��"$��q7o��+@9��_]H��q<}v���9��&����p��Dq��3�� B
������k��sE�7�-lR9$3�"w2SD2S��S5cm>eQS�����G��n�{D�-���a����R�OF�0�d1����S�7p*����H�\���|��`_�����?~aL$��^���W��!B""""""�Q��z}P��-��8,��m�+P�����������B�Qtm���)�{��zZIQ������E���m�}�cee������k8��sM������;�����6�:DDDD��mq�p###�z�9�c���/���WV|]����#�@D�6szk��M���!<v"��'�
�>����-�x�X{��&���������Z�OE�O����j�2����@_r!�76[X���M�L���������&�����|����j;�!���r{�k��
��
LH��+� ��`��p��p��t����x�Y*D���`98�
.Nd��������vA �*dUZZ];�mYU-�`_�jk�K��zuHpM�m��X��0PH�wNA�x��@��(X������-��EIro�.y���.�y�G�gp����h�bp��h���|�H�]�{��`0������1���?��>���������A�fO�!��Y<v"���>��n6���"~<r<���������d�n����p�E��sA�,��\i��ad&�a��dt�Gfqzd�f��H�f��@_��/����iS�E�<����ZK�������1�����������B�
�5A���!C���`���7��O$�^&"""""�MK�$h>?4�{];���W��-4������+B�����A�6�c��������%��&+jm��^��������+��e��^&�>�>�����Br0�p_l]�GDDDD�a���h�����s���:�~��O>���/{�,(�+�!\8�����m;x��=�s�'~� �����c�s_�����U%\��5]��1��py2_�+o������I��
g��8;V�h�*������|s��r[_O����,�\A@���V�}���mR��	�����B�b�Up���\n,�W:v~���l.d���������� P�R����r@X���/j�/
���+����i��F�QD>]��Z	�X���T�������s/���<V����q'�{DDDD[�{DD�@{{;B�R�T��
�h
���8�yg���j'��|mJG���������z�|)�x*���[<2~��n���1��|M�!���d	�:���3,�S�rS_��+�x*���y-{fM�3�0���E����@_,\��n�A����%	�FO����!6A��B�o�ae�ou������/.� 2DHDDDDDD��dR@�'P{�s���Qn\��W�����X�-��9������B���
���o�����h
�#"�&b����`��?('�"�z����ob�X9x��f���H���5�^"��^��o#Wl���5� >�o��
����<DDDDDDDA�D��~����1�v0:��@*7��'��������L�A<�C<��s��D�n�"Vn����������0PE��*4������uX�	k3��Rp.�'����p�\j.,���Zb������������z����2��
��-
�����2h���s��7~���}"""�-�	"�m�,�������$o�<N���x3�����~���=����w�k�_�v���{)�/4�B(
�������c�}oov-C���������Uc��`<��}Y������mv
����v���<��������]���@�Bc_������AV;1\\�kF�n��,������c��Xu��Yw|���v��X��1^��J������3Y9D(.	���P�b5��2C�DDDDDD��$+�xA��i�L]_��o>��LXP�����8���^
��B����S!"""��	"�m���
�K���7p��>-�r���3�x��F.5�r�|����v{v��������0j�t�����2������
�����s�������������������v"Q���AW���
U�9��d�X���e1[��F���Fg
x��d�X$�-�:|�/�Z��������k]�{��>���u�����C|��A,\]�p����f���eS�����l!�m,��!��s/:��!�&"�T������8�����P@Q_��NXP�
�L�����0���6"""�-��="�m�������r�	������{@���5�s��)\��0����8�:!�~�N���������!
���!����Y<v"��s��ou����1�����Q�&������������HP�-�����\�������C*�qnL�uL�u���k�)U
}�py����0�@5�����W��z��Z�DA,�;T�m�T�W
��
��>\1<�D�]u.��}s��m��������
ZE��G
��/�i8\"��!QS�YU!�*����ym��j��o�+���!�����Wg�Y�B��������������W��{U���<�����8w
=�Cko���534���N`*�~�X���U����}��c��w��_#�����	<z"�W.��~�Y���]x�x7���C{""""""�M������v�����r�A�x��Me1����eS9S�i�uy�f,�����-l��m$����R#��z1�5�Z��^t���_g��n4�q�C�XE���p���_c�,���]7��!�o!Dx��]_���rk;�\�O\*8X'DXj���
+��?~���BA.52DHDDDDD�"Q�����|~���8��^��W�X��V~_�&X����C�f\��jx�(��m5�mq�q�=]wl��L]�_(��5����?���
�Q�#�Ezl�s��KM,y-����,�.?b�}�;�x���0�-����o^��L����*�pk�p[?�Z=M�!5[�G���V��]�9����k��n�[����&N����L��O����*��AD��og7�����7?�wC�mM�5F��yS�W.�X�|�p�VC��}��]"�m��5j����f����s����c"$""""��B(������r���_��z����B��}|GDDD�1�GD���}�����&0x����K�
A��X,�����&p�>�k�7����S�3x�D?z{E��7����G���cGvA��&���������6�&�����R3V0,\�����Un��r��
�0�\����Y����d}��pi������P�����
��q!{�i���?�>�������M"D��`Mx�\Up������C��l���56U�p�P��������_W+��)m5]��^����}W��������=�mqc�7��(����1������������c'�x}`���+�������c����	3$""""""����H�
b4X3V4mO�KA��B[�@*����
J������3xo<S3�Hv���Z�����E7`��wt����e�����+�����~��K�,�/DX�*X4a��U��V"l�������:hZn�L���@�V5�_�(0X�bX�X�!���;���?���]����ZDDDD�����0�q0~��u��T|��4�C����o�2��ye�i���w5��m���m���4a�DDDDDDD�����=a?����5�c�ect��x����M�P47����\Lfq1�0Q5&�z���/���mcaz�}�(������H^|,��x�o������|,�x$�k�$�IJ!B2d����2Dh�
�	��"hW~�B��u"�&�a�v��(D�Dx��Up�!�������
'2DHDDDD��E�b�9p�gO7�Z�#�k�u�����}�ma�|����p/����(��z}�����)<v"��O����d���v<|<����*sEy"""""""r�,��������_=f��fK���T������d)��+nL���N��_x/Y5&@w����W��W��T~t�Bj���~���+�{>)��E?��qavD��6[���U��X/8�\h�uC���$�����2DHMP
�0c��R7D(V����W���!B""""��������!�w���n�5�����9��;�f����iP]Z�[7-<��(;��C3
�^�E����������3)"""""""�UE�m^t�yq���1�q0��K��dE���}Z77d��O�1<����S5��Am��/��j�z�
���R#���G������=��������i���B�rX��!���Y<������{��hii�:f.DX\��p.<h�_"�:�yC���5DX�����������k_W��'m{o:�w���/>��k��n���h��ODDDD����&�����\�u��������Hf�
�~W�_���;�����.LDDDDDDDT� �z���h��j�qL��r�/�x���O��S��{8{<�c<����d�X��V������|��v��H^��8�����W1������^��z�|{�8C"��c�B��Q"\]��������
.:\87��6[�p���:��������
��u���\�}_�2��=��T���+h��}_����%"""������x<�2�����.xe��gM�u�L��q���L�i�����#�c���Q�?#""""""��It�Ut�U���^3>�300Y�%}�T���3.Ie�He�xcp�f��� Z���[��C~�*AX�	oa������
��	\����>�	}Eg��_4D�.tj���jdgLD��U�7V)Dh/�b.<���s��U�+�Dn��� D(@�������"���h ��-`�x�\�*|(	D,"�5��S"""���
��S�����k�������?�cx�-+LDDDD���j@DDkf����uaz��)�`������^0,���<v"��#�
_�����{������"""""""��Z}
����������nb ��@*W��-7��0:SX�����
�=4���fj���T��W���� ��-�C���r ozz?�Y�����{�E[[��N���6�R����h!��&�R���k��C������g������1��.|�bfh���FB�K6
b�����
���N�!C�DDD�E�b���	~����+�{��|������O�����6�{DD[��Xw�7������������<���������5�aUo���go��6����DDDDDDDD�Y@�q����[k�
������R�o.�Oe12���l��d��������:y��v�X��-���j�B�����c���[#x{h'�f0[X�O���~Gz[q}o>yC��
n�L���jU�7����!�����_c�������`�r��s�%r��!�+P7D��`�����/�Nd�����6F�/����/������/>�����n���/�i����h�`p��h�	���0���n��o��$,����8x��$;�/�[��`w����1�w�s�?�EDDDDDDD��"��hWGk\�iah*_j�K�5�������6(�W0l�K�q.��S%�;�� _uc_w���}�}�l����j|��g&^����R�/�|��:����
��\��m
�1D�8<X��R!��}�7.8\�.C��[!D���`98�
��p�!�N�
���?�*�y^���1t���_�{�0�~���{��&��������{DD[�"������i�}i��������"(5c����9�o�������V�S%|��^<|��:�28��4Y�U���j����t~>�7���a0�C��7`�@����D�Odk�$Q@o�w>�W�����&K0�+7�-����4~��H��}5>�W��'o��}���J ""��*C��&
.�[&D8��W�V8Z\�p�`�*�i��|!��A�2<(H!C���`���7��O$�!\D�������}�WY���������(X�U�����:k��h]Ok�Tk������Ukk�C�����=��:q�����WB���������IN����������WBr���l=|��z�.1w��������I��O>����}���fm���mb��_��#��n���`��@3�H$�[i�X�w�X����Q}�[i��o�������)q�k����E��]7����?���Oth����%c�5]�"�g�H�c�����u���[��[S�-���	�U�����e���e�\�c�DD��m2:����m���Y�)m�����Xcny5f-Z�Q�<���xe��{����C��Z��a�����;
F�0`v�����
�8"$�V�W5�N�kC���.�5�]�����������a����h����{�	�-\�0�~��HW�"Q��}��zt�����������6��C�F������
v��a=�xp���j�H������1��)���#�?���+�c�����W�G2���MUQ2[tj[tj#fK��1{���2w]����KV���t:b���1}��xq�����:��-�n����-���}M��]������/��~%.�O'�Y�V�qz%�<c7�=��H&��L�6�a����t!L�W��5��U�����"�H'�Q\Z�H	� ���	�#b]��!������pm`�zxp]D!BN"��dIi��b���M��@37���x{��hu����� ����~�D��hu����&N�>�l|2gi��i��8���O�����u�v�.�F�H$�g����C��u�����t�[Z��C�����V������hE���hE�\�"��e��n�ZUv�[�[����mt��a!���,���j�B{k-\^'��j<v�^��mi^�h�;D�h��x��g*��G��V�CM!�T��7<�8���pu��.�i�?��P�0�\�+���U����;����v�!@��N�#���HDDz���Op���Z�=z��3cZ�>u�X��	���
�6�����"��$��l�=0��K��6N�?�9�O�^����H$�[�V��]��i�.Y�,+��U������1wI�_����.Ys����?��u��f%�e�������wi[��U^��{1k���-=�Y�V���|/�=~�Y����:��6�&����i�"V�^���av��T�
��A��cnU4����B���!�:v!L�
F]:l�yesb���c��/b��YQ������`Zt_�3���<�i;$��v/`�4�	�`X����iQ�y�hs��������^�Ci�>u�(�|uw���~���k��'��{����d��Yi��4����ul���5!����u��*�V����eb�����oU[v��[�v���j�������&�h��|{F1�w�3�g����ou�0%M F�6D����U�.!���+��8"�!4�a
����`�]�;��,���G"��D:������k�V��a��O�f��e���_��+k~�������bjL_15�^8>z��;v�5�m�u#V
@C�h>��.���Cl���(��]l���c�C�b���7x��a=���#�v�\���C|2��z����8���o|g�����f|6]�[��W��_��c��ee�b���b��e����-��G�@4.^�*���(���(�X������f��k����������I��w����hQ��#J�U�k�"���-DX���U����bU��
��~��=D���7�^<=b��/�
L��10���U�+^3Ws�����B�@+*���_>���_�kg����=-�{t�7Z�i�
hl�{-�
�&����z/��mWE�mI����X5�G�=�y�>]X���[u��Q}�xp����K���z�z����������{�f�>��06+-���:��^���(��i�W����	���}���Q�*L�oyyE|0sq|0�O 6�W?�2>��8�Z��s�S5DXh�t:3$u�
��6����5�W���B����aY�K��%k
�'DX�+<�(���0w��d�8�����W6;�uo,�X�Q�LZ�~�X�y����Z�=O�P(���3��S�������~����D�����]<�k�3����gG��EQ1}I��U�hSE[��d�Q<�G�j��������~�|e���d"��C{��#��n[w�M@
�uIQ��>����W�b���Y��)����_.�����kDM���\�2��H$�8Q�M-DX�P`F��z�S��n�B�4��"L�����*����`��k]wm�5��5�z~�M�������w��������bI�s�?��^��4s�{��Co��|{����o���������jEn��1e��������a�x��0��/[g�w��$��/N�m���S�x� �J����[����m���T:f,X^%��4��[��	��\�2���3��M/|%�d%�8���d"��k~_=.���������r\W�L��K&����(�^E�d���W�������������W�������g�9�����sw!\�5�jx�J�/V�78Xu��z;VD**
��A�����M*D��P`���5t,,�x�J��*�D�'�1��X���7o���V�V�����cz���E��h����	�d��|�:n�k������6���O$��#Z���{w�'^���io������3Z�ml��$%���f���f��6�2��R���xEL��,#����ee����tD�(O���i"��j��5��j!�� ���`m���s*����B�U��THV	D�
4V�+���j��!���aq7���*C��#�W[�o=!��5j�XX�a��?-���a�+�HFr���d�!8���p]�������`F���c��o�^���XV��A�^V�$^�������
�>
����`����xwzv8o���x��>����c�a��_�eu^s��������'S��<>{��hU�����9I&�y�6�y�6�������t�Y�2>��l��u��O�.��+V��MW*Q�*��/��rw$\���2�W�XeH��A�������k���.�3b���53�UjO&=�@��"\��.7��!�TzU���:�#�WK(03�������W��c���N�#�HG$�@��'�H���P����`FW�����
�t~F8Q�0�>[�ILZ�~��c���c`�!��f�>4�=�fl��U�pyy��?��>>��>�u^C�Y�{,�^��G���^Q{��d���&f�n?�s�����������h���6m�D"z�o=���]�w�8�N�c����2oi|6oY��_.m��2��T:V���rU����H���k��5	���U��k:�T&f�A�u�k���6�X�#cm�b�(�B�-Z�<�L�x��Q��C�5����V{�Z(pm`0g���y����*�����:D���t��z5�\!�dF���!�d�1<�������^�j��g��W��)��f���n/5w~�x�����t�����(�(+OFD��R�*U�}�&-�HD�����mi���s�����W<]���yH�#�*R����-���D�3��$�h�	&k������+�0�[#�3b�Z�w~,JF2��AL^"�X�i�S9;��aV`0W��!���
�i M5D�����^S�(�d���XX���D�^��+�3WNk�?�L_��_���.���~���@3VR�!?�NDYyQ�F|����~��2���::�)�����P8�tT����{pW
fu$��DX\��HU��E�HFDQ2��y�u��*A�Z�0VY��@deE�������g��Q�LD2)��R$�5��J�0U{��j]����j����*�D���"��s`�P���y�Z�����=�fGp�k��������$��5���%J$��-:�����m{w��+Q^�:(T^���T:V����"���c�TTT��<�z~�9��+_{M*k�I�r����kW�#�t����d����z^�������D�W2��C����9�Ek�0fwF�Z�@����;Y\����s_��^������P����I������x�P�z���:B��
�j!�\f����%����B<����P�`�>��{{�u�}�l��m����Of�oM��b��TVq]H0Uy�� a�5kC�����9C�k����L�������Q^!�-M*QV����BW���u5�&�����@c
A�\��s\�}N�������e�KZKM!����uoW
�$����jx����k���0�lV��i��43�{�\c?��C���v/h��;�8�����[4��6F2���5��6Q��
!�NG*�!������b�J0�$\�X�$����HL����3�XC=������>�,k�m�\=*p5
#��u�����k�~X{�0G�����A�5stV\{��j�����K�:2���h������YSfw
���/H��U�jM��u7�8��Z�Z���(M�c���h�<����^bD�.���/�^#���z�o��P7�D"�E��h��Z�NW�����0�3b�n����B���esuM��&�����v,G�1-�-J:Q^�:��"R�.��$Q-t�&�W-��$\�-�XyN���9��B�U���qm��2�X�\W��"���b����`�]�;�Z"�unV��tE�b�}�����{�I�Q ����=�|�9j�x������Y{h�{@u���PEIQD����=1""��
�2�@��vE
���g
s+j f�SK=5��%��([���B��rw$\���2�W�XeH��A�������k���.�3b�@d���1eqDQbu���9K���d�z����d2�I�D`��!��&"�1��#DX=tX�v���j����T�p�����������_�����i��=��z�Cf4�=��;F��`���.�LDi2��,t)
&�����Z�0Gpu��j!�jA��T*��*����W��O�DE:�"�{�>�,.�
6��WMa�j���u�Y�B@Z����W�j.��<����u�"��u��	kV f���t0,�L�h����3���b����,�uO�f'3DXx�t��N�QC�/gHp���R���%�F**�}h�l%����	@}��������������Y�V�}��Z���m��u�MK"�&\���-Z�TL��= :t����L��Q���6��A1wg���j���5�C������{��|M8�|m�j�d���`bF����Q^!�-M:QV��F|f� �*�������� a�@cFH0�XVL�&fw=���q�Y�s�Z��cQ2��P��L$#�(�k�p���1}��<�X�n�=}��	������s��{��8�O�����y[�c��{�����4ok�d�d"�������FL)6�������u,\Le��v2\{}F��Z'��@c*+�X5�X}�\]�h\�{"�8k;����V\5���0�a����ta��V�:#e"�������Gq2���-C�V�7jp�G���^���@��h���w��[�|��yyq��Z��SG��^
��
��gu���L��H�����uF\��C��jg��A��*������tS\���z���4�'B��v��H���LDF��������Y�
s��va�2���qM7���a-!������'�_���������
l;$�^8��7���@��� ���kp����{���|/|{��s���q�a�z1.6Y���@E��'F�jg���_:#Vf	�wF���X@�
4�Z\h��R�����*�Gy�t"�4�tDYE*�*
]I�Z��0;�Xc���5	���<�(�uY!�����������ki����O�\9����y�>���{�����ha<��W���q��;��z�
�N�W?�������K����=�GV4�d"J��&�D�L)���H�#+$X
��evF���X� af���@b*G��2�X-�������c�Z�!��em���/��2S��D����&�W\C����H�b��d%Vwb|l���ui�b� ����9:+fswF������z��5��y���{"P�aG�c�>�7���
~��@��h���3��3>��8�0=&|�0��� �XUyN����}�N�C��q�[��^�X1@�%�(JD%[f0q�t:_.XO?�l�����G�m��� �
���X=@�Z�!HX5��}}�ss"���v,G�1-�-J:Q^�:��"R�J�������Oay�LD����P_��_� a��`m���s����Z�z����%E�B��A�u�
(���r��`n���mV��c��^����
�>
Kp��p4o�z���{
�����cO��U���d����;v,p�l�Dbu���J>�k�����u��j�T�P`����r
�k��X�!1�#�XKh1G�uk��am�\�F�eI�#�V�����4��	3;�T�	�5H��XQ�`c�������b�`bF��J���p"������v�������Z���xiq����s�Y����y_��'��	�p4�D"ZED��14�d"J��(��a��I��tAL���j�����Y!�:	�]Sy���W�#�3����51G(�B@Z����W�����M_"�:$�	�$�@�
4V
��`XR-��3�X-Ykg����jkX����n79��,�;��>|J�i��C�W$��G�����q�����)�=�M��{ ��5��������R��Hg�vP�
�Z\$��Fv����� afX�|m������k&f���������e���BW���*��;�-f	s3B�����b2g01��a�.��������������L4�g�>��(^��eDD���u����q�!S��yo���a�9_������_��3��^�7zm��u�L&"�()��|��hm�0#dX�k���W�Sa��!�*A�]
�	�������{e�Z�@�*���Y�����4���!�������$��c���{��Y5���u�t�����3c�mm�������z�����x?4az��k��@a�@��V��`bDD:����2���Y��� a�c�������._S>��tDE:����#�,^}��n���k�gMh�r��@�|"�<�*���B��a���x��>����c�a��_�eu�v��������'Ssw�����|�	@#��ML"���T���-�g��R9=z����C��+���m�2�WK��zHp�5�!��3��k��V��X�cF���A�\�T�������|2�}|2�}t��"�n�(z�X��-�6��
��H���mb��61��1w~�Z������N�#�H4t�����"%��(M������E1�NG*��UB�!���aF�jA�U�s��vk�6V�W��b��������As2w~�x�����t�����(�(+OFD�Cx������h����������D"E���d�&��NW����a�����)Vf�3�0V=';��q�r\�z�hL�'�P�(+/�(���V�"Z��"��MZ"����D�E�.i�!�T� a-�W�V
f3;$�s�s����W[=5����d�K����	H&�j���.�����a��������Z��5�vH���
��55"W��Q��"&�]��?���$�������Hph�D"��Q��sh����xq��F��v[t�D"�h� ?�L���tj������� ?����a��~;l��� ?��hp�1��F�������^��^���@=�9j�F��Y{h�����.Z�O>�$^}���6mZ���E���c���1r��h��u�� ��3��w<4aF����a�c��
�>
Kp�����������o�<��]�3fL\r�%��[�F��|���mc���b���y_�g�Vq�a��}]O��@s�r��8�����F�����%K�����:th<��s�X!
�s��{�����$��vlScO����u]��l�T*�w\��o��/**����*�
;v�86g��8������_n�Rh�{u�;��-zvh���zvhw��[��!/�P8�{��~��_��>�1w��g���Sc�����[o��_~��w_������e�����.l������:�c��G��Q�1�w<v�^B{-��l�y���/~����_���q���G������L&���F���K�����i���o~���*���mi\{��q���c�V]�u�����-cv�k��1:�-m�
hl��.�����*/^\9�k����.���-��"n����o��*�������~]�vm�Zh�����\M�>_�L[�V��<�C����O���o�8|�-bP�����"���J���[n�����K#�H�z����_�������������]w�g�uV��
@���}��kpDD,\�0{j\�JE'#�w����c�+��%]47/��R��3�r���[��Q��t�i���1~���XMM"���E�J"Z�z�E�2�A==��#�����������3������K���6������~������#�|m������������8qb�*��=����?c<t��z]_������������c���s}���������7�.����z�;wn����qIII����^kl�����g��6�i(.t��,Y�$c��f�E"���m���u���={v��3�^�L�4)��E�mT4K�.�u�����M�}�����M�}�����M�}�����M�}o����	����C�/�[�n]�5��iS�����?�1.����Z��W_��3gn�4_���j�Kh4�<`Sc�65�=`Sc�6%�<`Sc�65�=`Sc��tL�:��%�,t���X�"c\ZZZ�5Z�j�1^�|�F�4-�{P�;�����{��+W��&���hN��k�1����.�w���f}�}��q�1����I�&��GY91bD2d����X�ti������#FD��mX@������������)����������������/t	@	�A=T�-[�,��t$�:��t��Z���=zD�=6j�v��E�6j
���m���6�<`Sc�65�=`Sc�6%�<`Sc�65�=`Sc��tl�s�@��,t��t��-#�W^^�g�����O�ol�hZ����i������:uj���~����7�.����z���8qb�����k]h�����
�1~����|�_|S�L�������C�T��A=z���'�|2��t��}���3��G��v����6�����F���u�O�<9��W�ko�����G����&@p�)�L��1c2�.����v�{���������o�>�=���(( �=�\pA�k��r������W^Y����O��O?=c��s������{��u�]tQ���^g�}v��1�r.�J�<#G��)S�T����;~��7V�@#��
t�����1w���G�~�b��1|�����k|����S�V���M������S�N�\1��`%������������������'�[o�,�8��k�x��Gc�=�h�J��$��u������=����6lX���m�6�>���8qb�5���_q����������:*&M��������GYYYt��)�{��G�n���e�@p�h���1p��B�P��@K"�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�y$�yT\����r�����I�
T	��d���:uj������v���"��c�65�=`Sc�65�=`Sb�65�=`Sc�65��MW�gt�?��l�{�	����3�Gyda
�M�����/t@#I�hI� ��t:]�"���`��x��g+�}���V�Z�"��I���#��?��1p������y����lj�{����lJ�y����lj�{������Z�re|��������;:u�T���FU\�����S�8��#
]M���c�m�-t���lj�{����lj�{����lj�{����lj�{�������@��.Z�=�#�=�#�=�#�=�#�=�#�=�#�=�#�=�#�=�#�=���B@����{\r�%c����lj�{����lj�{����lj�{����lj�{��D:�N�h)��.Z�=�#�=�#�=�#�=�#�=�#�=�#�=�#�=�#�=�#�=�#�=���B@����O��W_�i��EYYYt��9#G����[�<�UYYY|��1e���>}z,^�8����C���k��~��c��!QTTT�R`�|���1a���6mZ,[�,��i={���|�+��;D�V�
]"��r��x����������������C���G�>|x80�D�����lx�����o��f������1c��%�\��uk���P�t:�L����b��i�`��h��Ut��9��f��e�]�@���s�=���O��/�|�A�Z����;v�������s����7R���/^������o�O?����JKKc��q��G������P_o��F\s�5q�=����+k<o�-���N;-�=�����K#V@cH���t���a�\�2N;������V���w���sO���^
\@��>}z����1~��x��W���_���W�r�-c��)�+`#��??x��x���������s��xnIIIr�!���0��{�F� �����O��u%%%q�E�%�\��j��[��V������^�����K���.���O>�����[�W@<���q�����Y��|M��=c���
X��3fL�;6/k��.���R������W��U�R�:_��g����[��l��hl:��P�T*�;��x��3�����_�~��c����Oc��������tP<�������7v���_�_���1~���1cF��h0��sN�x��QVVV��������x N:�����~:th�*^���+�o�J�b���1u����e���q�e����7�tS������Y�=��k��&~��G���n��u���;�u���/�/�����h�JKK]@��q�q��7f�o��f1`��h��M��7/&O���u��Y���#��x :���,��,t4�_��WY��3�<3�N��'O���z+���������_�~��,[�,�=���@@S��k�����/��x�����+**�>}��N;��o�}t��1���n�-���X�dIc�
�W�{���~��q�����I�b������VvX�2eJ��7/���?G�>}2�������[n)P���p��8���
]���n������xX������_�`�����Ob�����;���9sb���q����QG%�lr=��B�P'��sOVho�����#������w�������I�b��Yq�e�e|mWVV'�|r��?��K��$��_��fo��y��V[����+�~��_�O����O�>=��s��2eJ���_�]vYC�
����o�G?�Q�c�����l����@s���;�o��:u�N8!9����������<���"������������X�����{���Q�����Nl��v�H$�t����c����7�|�rn��7�i��E2�u����{��^��/����m����K+��?/��\z��?�����c�v����{���C�6Di
j��I��v���+""���$�������t�����s��
Y"�F�8q�����g�}v���	b����Wi
f����w�}�r���;��q��m��5^���O��V���������/l�Zh��.������2B{{��W\p�5���[��7����_��5�\?���k��
Z+@>�o�>v�i��e�]b����.����~�G�.tiy������~'�pB�i�&�9EEE1j��x��g�����?���������x��g��@�Q�r:w���_c�m���Z��_��/�_����D�F3n���W�N&�q�%��O~��W�?;��S�5��e4��}�{��������oq�1���z�=�9:t�����O?�1�q����fa�������?������""��g�8����O�S��?��O�=��KL�0�T*n�����K/�t��	��w��/^w�uW���o�vX���{�`��x��g�������>:��r�B��W�]vY|���q�i�������(���?��;��1��ao��j��!��N;e������ ?�/_��~ze(����~���.�
��z����g��s�1�
��d�T*n�����1c���z���3�}�������:�����I��V�%������K1g�����[o]�W�=���2�<�@+h8��C�F2��[�e;��C����^�eua���������d����[�J�������|�IDD���/�������!���?g�/���U��<���1m���qIII�p�	��������q��}�|m�~�2�,�GI4�lhay���������n{U��j��q�t����@aT��1o��X�lY��h+V��w���0���k�����o+����]�v�+�
2}����6lXl�����i;vl���C�n��������c�x���u�����>��Cp��y���3�#G�����{�����W����b���y��B���s����P	@�H����k�e����N�`�����i��q�1����Z����=�X��u�G�.`5M��E�������3fLa����
�����u~��W_}5c<b��|�@�	��0���~�x�������������>}z�\��]P	@�����c�������!7�l��������?��{�u�]W���P�_df�v�|���������;D���c��6��������W_}u����$w�uWF��=z��\����O�>/��r��:}/o�������6c���N�wy��@�|���:uj�\��}��F��?�������z���3�[n�e������5v��8���+��d2~���G"�(`Uf�����_��r|��WF�^�
X@�[�re������/����c��I�l��B����{[o�u,Y�$N;��>|x��w��w�y',X��/��>�,�|��8���c�m���.�(���T=@����[3���������0�l�+��2��u�f_|��1v���_�`A}��/��a��a���u�x����;wn����qIII����^kl�����g��6
���o�{�Z�9����2^����<������n<���1q���c�����?�9��w�B�
�QR�T�v�iQVV_�������n��hX��sNL�<9V�X�1_\\;��St�Aq��gG���T!���4iR�8�L�^{�o���z�]�|y������^{-����h��}C�	��&M�/��b��)��R�j6��{�������s��t:�V��1c�������7��
�6m����sc���q�w��_~Yy���������o�{-��%K2��m�Y�;
�m���5h^}��x���2���S�b����c\{�����H$���_�����;4Re�u�u��+�������-]�a�j��U1~��?~|\y��q�y��%�\EEE�\!��K�R�x���������D"�zh|����O�X�ti���[q�����3*�y��'c��1q���6j�
�z7�����v�mW�j6�Yg��
�����{�E������/W���[�O~����w�������Ww-H��]�����F�6mj]����/��3�8#c��#��#F�"��q�1�����������~?���*�^xa<��4��/�������~����,\�0��t���o�]�v�g�}6z��8��3��C���;.���������N��������n���jhH�t:kO��@s��>��k����w�z_t�_�~q�y��	'� ���
�Y�bE������k�j�*c�|����	��H�Rq��'��i�*�:v��]w]�hw�uW������^{��I�
]@�}�{���K�FD�������.*pE
'�H���#���E<��1m��X�lY�X�"�O����?��3��z��q�������~j
�#�<_���ro��]�~�����=c���/�
4GO?�tL�:�r\ZZ�Xhnn���0`@\}�������S����������7��H�X�Z��?�.++��+W��uM����??���e���O��}��"����o�t����e����?��~8N;���N��?�|���.�����b��������'����a�?����]�����������_��.�(��o��b�-�M�6��U����wz��q�
7��{��G���<�H���,P��S��]O?���u�]k�6�L���_�����?�g�}6�5���c3��zht���@�l����8��������/��"""�t�_|q����1��(++�3f�C=���7"�HDD��_~��vZ����|�3�=��]�v�����z���k��]w�u����&c�'?�Iw�q����i�&����rH�x����;���a�*�/X� �<��X�`A�j��/��"�;�������^c���`������|�N����'�|���}��3�����/�-[���UM?w��w�[����z��o��2����n��%q�}�e��3�0���Yg���{o�x����{��e�]���Kt��)JJJb��7��;,����x��2^������[n�����Z��?�Y�lY���z��t��Z��i���;��?�a���1c��+�(LA�l�����Odt�>}z��W�*`Uus�9�T�{��W]uUahbZ�n��v[W���=;��VP7m�������������;�X�5��{����@sw��wg<���g�8���
X��7n\�t�M��=z��?�z�����?<���?d����Y/�@�$���t��-�D����<f��]�5�O��1���G^j��=���q��'g�x�7������3�Nh��u��]vY�����Z�b����������r|���F�N�
W@5p��8���3�������^�d��4hP���?hj������v��44'�]w]���?�at���N��3&�#��y��:��<	�� m���~��e�M�:�^kT?���]
��g��c�9&V�ZU9����������W��|���-��1#>���VP���?���C9$�=��V�������?��@����!C2�:t������?�F�P(�'O���>cn��1�)`#���x���3�;��:_�L&��C��{����R�%���T�M�8�^�������@�3~��8���c���s#G�����?JKKX@�t��)�t��17s��U�~,�|��G�D"��_�G��X���>�:����n�w����7c<g��UP?C���\��^�W��_D�f�m��5�m���t�r<|���n��
X���?~,\�0cn��������>}�F�@�	��0��
����Ku���/��)S�T�KJJ�~x@���;��AK�,���q���G��m��2�������%����+///P%�3|�����Y��u����3�]�v���
!�N�m���1w�)�����������F���VTTlTM4
�{-����1~��'3^��6�?�x�x�����]���@~}�����������+�������c�����/^_~�e�\��=T
�T��r���T	@�r�!�L�{T��O?���km�x�����A��V@cz��g��O?�����	'�P��6N�T�1cF����a��uZ����M���#�[�n1w�����<yr�7.F���ko�����G� 5��>����o��2^e{����'�x�q"��G�x!�������o^��j�����c��	��������3����f�3p�����������}�������G�������W��w�}q������U�V�����17j��|��(���1>����K�.�`�������o_|�E���O?��vZ��x���2��[}��@�L&c��1q��WW�]v�e1j��H$5^��SOe���}��q���6h�l�/��"��w��6mZ��[lO=�Tl����iX�|y\r�%s�zhFW��f�����5���?�i��u���~�*	�IZ�`A�{��s���o����3�8#��������;��N�j��������dt���Cp�
V'@CY�ti�s�=sc��)L1y����f���o��8����������>/��r�z4�Th�.���h��]���g��+������O���*���{nt����j`�|��������'�|R9��{�x��'b���*`e�����$^{��z]���_���}�Q�\QQQ��G?�wy�y��,�����AT����[��Vl��v���>�(�8��H�R5^3~����O~�1w��gG���N��r�����%K*��z��<�����'��1~��w����������I�&�	'��1��6�������h|�{-P�n����.����������3fT��R�x��b���1e������{�����*�:Z�xqx����{�U�u��)��2dH+h�?�x�1"v�u���o~o��v���g��N���>�����1h��x��'3���G?�x(�����+��7�����V�����q�M7e��y��������<��L&��k��D"Q97v��8�������o~���o��2B._��W�~�\�z���o��u�F��p�1z�������/���{�SO=�V��86o�����;��s�3}�_~y5x�4�D:�N��/�J�G?�p�|QQQl�����c����O3^�6"�M�6��O�{����l�_|1�/_�5?a��8���*�={������9����w:��j�X�G��q��e���������N;��;w�Se
c��a1a��������b�-�S�NQZZ�/��?�</^�s��O>9n���H&�����7.�a�-��2����Q�F���>#G��c�=6��w�<xp�C�.�G}4����x���3�
0 ��]�vm�����+������Y��z��>}����K��O>������]�v�g�y����g�}[m�UT}d�?��O|��_-`U�3s��9rd|���Y���k[m�U�i�&����'O�\�p���?�����1����`+V��SN9%�������]��=���F�j��@������>��5N>���WxhJ��
��z��g|�4y��{u��C����+��3����	�������^U�Z��>}�D�����(���S�L�T*�u}�^������m����J�����w���8gw�\
���?�}@�����<.�����N;����z+���?�<N:���d]�������?��O�\��2�-X������{�s�=1l���k��m�}��1q�Do�d����+��2��o�����z�O$������~���4iR�u�Y~�
���\�2>���x��7���^���'��|��1a�����������Nw�qQRRR�y[m�U\{����;����fm����1c�����o�x��������Q�FE2Y���;v���:+�����\��-��{��I�&����c���QVV�:u�!C��{��[�.tyE�=`S���)K�R�����I�b����h��(//����G�����1|��:�Z
�����'�����/��������������ktP���W���^�T%@�Y�hQ���K�������]�v��g�>|x4���l�^x!����U�KKK��/��.]��*���x��x���c����`��X�bEt��!�v��o�}:t��>�/�=
f��e1q���2eJ|���d��H�R��S����s:4��n�(***t�u&�y��2������������������������������������������������������������������������@���������D"�D����[�����O?��.�,8�����_�o���}Z���?�a�k���x���������v�)z���Z��Z����n�������z����$h1���?d|����~V���(.t�0}��������>���������M�6��S����s80��v�(***t��n���x��*���rJ|��_-`E��r�����~���"�Jm�:'N�N8!&L����`��d���0aBL�<9���K�.����h��}���7�����W���H$�.u�4���{��^�����I�&ED��W_��rJ0����IpZ�)S��V[m� kw��1,XP�9�^zi\v�es��rK�3f���J�����w�}�����������{�f�m���C9$���oG��}7����p�����*�m�����������F��g�}�A�������#�\�y�T*;��x��'6�~'N��v�-/^�Q�@S4f��;vl��3�<�F���ug����~{�{�����oFEEE��w��58��8�����n�!����DD����/~��8���"b�����?�����hL�BP�t:n���4hP|��q�-��)��l��x����/�-��2��w�����W^�f��������{��
q�����������c�v����[�\��N�����K:4k�6m���}i����D����_i����g�}vl�������4^{������^w�w���_��W��h�b�����ks�11d�����?lo�M��{@���'���'�����F��N��������~:9����������"�`��Yq�u�U�KJJ����k�{�CEEE������k��}�������?>JKK���O<&L���m�������a����Zhz��8��Sc��y�������Fu�Qq��7G��T��k){;@U�D".������E]/��b����l���m��u��o��j���'����>:-Z��x�V�b�=��#FD����{����u�X�xq|��g�����s�=s������G���>����]~���t�����'�}����5�R��\m:v���s�|���:uj��W\'�tR��U���f�m=�Pt���^�@Kw�W�E]�t:��w�1��w��b�-�W�^�l���1cF|��G������������{��w��'�xb�������v��N8�����~��M����^z)}��8���\��`���;��q�
]F�=��#��o~3�����
2$.���8��Cb��6�u�T*�>�l��/����;V�Z�P%�h��yq��7f��}������>�h]�^}������;n���g�}��IM0���/�<���'k>�H��������b���������������w^|����>����{����^���{����iI{;@.%%%q������^Z9w��W
��&"Y�j���o�q���())�?������'�9���;""��d�=:����x������o��kt�
7��e�*�����w��������u��5�v����4h������{�����gY�}���_|1n���ZC{����?<�y������u��O?�#�<2V�\��������59��S����r��s��o�Q����"�4Y+V��o}�[�t����v���#�<g�}v����1p��x��c�����]�|��^�V������s��vZ��;�.\�1n��mA���h��q���guG���O<��3�����k���[��W_������c���Z\|��Uo}����6}������?c��k�-P5@c����/�<>��������+��
u�I'��/�}����z�����3g��'��8�������b���q"���u�w���u�%���~�nm��u<���1`��
^�����SO����������[-moX�c�9&c|�������T
�X�]@.�g�����7Y�g�uVt�Ay����o���jr�m�e���s����g��{STVV���ZL�>=f���-���;G���c���1t�����e����^�/��"���.�6m�D�N�b�m���C�F��]����Y�f��o�s�����gG*�����G��=c��v�.]���z�0aB�}��Y�_|q2d������>�hF����".������{6z��4�����"�|�����Oc��9�p�����Kt��=�����v�m��Jk6g��x��Wb����d�����c���#v�u��r�-���t:�{������c��y1w��H$��C����o2$��z������c��	1m��X�dI���F�^����N��Z���o���c��Y�b��h��ml��������y��S��;��s���9s�DQQQt��-z�����{�t�������7��������+�k����w��s�=�s��
r����x���c��i1o���?~�j�*:t���C�F�^���
��#��3�8#V�Z��N���{��SN)pe@C������/�t�����;�UW]U��6���K�����;��CTM����?>������g�8n�������=���\v�eq�e��x<�N���t:��{o�z��1n������z�����7��?�i^�r�X�"n���������W^�����M$��������rJl��6��L�[m�U���;6�����j�3���u�%����^�u��Y��O�>�A���#�8"x�����6g�yf��O��{��wc�m�����������.|��x���k|?��d><N?��8��S���d��n,�]w]��4p��8�����~�N���+��1c�d����1u�����_^��KS��_���������c���5���w�8��C��.����F��g�}�r���{��q�*������/�<�z��H�R9�:th\t�Eq�	'�%D��s����_O?�t��=��s{�����_�p�	q��F2������CN>�����[�]���^��9�.�j���.]�����/�KL�<9��U�{�����\��3���Q�"bu������;��#����{����������k��Gy$gg��JJJb��v�s�9'�=��z����J�b�������&�}������Q������b��v���s����;��#�������?��-���A���'�|r����Y�O:������+��D">���Z?����o��u����q�5����.]����#���������;������ht�-�d��t�I��]�!<��S�b��������?�|����q�1��#�<Rkh/"b����?�!_|q�������b���������s����X6�0aB�����A��������nH={����������9s6x�����?�����#F�)�WQQW\qEl���q����[o�Ukp'�J����g�yf4(#(�T-_�<�������O?=����z��w\V���a���T���s����#F�������"V���_b��!q������+�R���+����n�=:�x��Z���'��'�x�z���L�0!F�{��w���Xoh/bu��o�[r�!q��Gn��i���1t�����k���M7�C��?������e���q����������u��������x��������a�����������{���zj�kVTT�SO=���{�����F���{�����I'��������������k��������y�9�d���tV`��������3�<���W}>��s�d����	h���&g�����'�d��q��&?���e�;t���/P5-������g�}��7����+W��������o|����+V��'�g�uV|����w��0����7���P�Pyyy����������X�pa���e���q�����^,��}?���������o����������8,..�����Z�n'�xb�|�����T����'���#��;��S���������������ZU�X�":������u���?|pTTT���w�yg�92��_}-Z�h��-���{.F�S�N��z�������O�S�,��3g��Q������
���;��#G��G}t�������c�]w��_~�^�]~���������K�Rq�����G�&M���k���u�]c��w�������������2���g�4hP����+++���zj������4+@�<��3Ys={��SG���z��a��EQQQ�����C�F�N�*�S�N��������Ck��K�.��]��a�2�'L��1���g������]q�q��f��m�6����e�]b��7����������?�'�x"+���C�i����
�&���q��s�=�u,�L�N;����o���/�v�+V��y������?~|L�8���KKK3��&N��������;G�~��T��:��C�{��]�n������~�A��z�����[���_�5��-�Q�F�f0 F��o�}t��%���c�����k�eu,//��O?=z���r����YEIDAT�r�v�q����g��u����~�����_=�,Y� ����>{���s�=so������7c��!��K��={vL�0!�����7o^���?�|���~��K/E�V�6��SO=5��h��Aq�A�����K�.�p��x�����{��Y�fe\��s��5�\��w^����?���na[l�E|��_����.�w�%%%1���<yr�������/oP��)�9sf|����������=��r�h��}|��1q�����������?W\qE��U�V1z��5jT���+���c��i1~�����f�����[|��gY�������{��n�m�����g��/��>�hF�{���q�QG�K/�;��c}�H*�?���b����H$b�����~�E�~��]�v1g��x������������+����]w������w�w�qG�c_��Wc����D�n����<�����8qb���k����_��_��9s��=��'�pB�k\���o�
U�u�Y�Zc��w�D"�Q��q���#��w=@� �49��9���K*������~�1����������g��11v���q�������^�:��I$�3�<3.���z���SO�����d��i�&.���8����C�9����+b��qq���gt���;�k_�Z�s�9����~�����o~��q�������I����{���:V��������?<+�PJJJ��O�k���r��w��7�|��]#?�����B���73����}��Y����C����m���~YKk-_�<��������+���t:�����;��}���W����7���k���z7�����~���s�=�~�������3fLVh�M�6��_�"�=��H&�Y�]w�uq�����W_�T�r��7�������V�j����A�^�z����8���r�{��W�9����v[��/~��8��s�M�6����/�?������z�������c����U���k?�p�������+�n���q�
7����������n��]u�U�A���:*�������o�s���R�T�p�	Y���#G�o~��Cp��{n,X� ~����5�\Sy�+V�QG&L�����������?V����������{�9��S�L���:*��tEEE\r�%��c���~W_}u����Q�����Z��0}���������U��q�y����s+�n���
��p�
��7�<�<��z���m�0`@Fw��^{����G�O
�z�-"w���x��73��;��q/^����3�l{����������5���5jT���Y!�K/�4�-[V���=�XV`%�H��W_��{�zC{�����_L�2%<����_H��rJ���o�������������FDy����[o����_k��M�6����4~��())���?~\~�����14����G���\5�CS���������������[�?������~�3������+�����>����^���z�kY��z����W^�1���]����[����_�`A�{����WYYY��QVV�1���{�o��w\���""��o������^h�q��
�����������X��P��~���=��Sch/�zW_}u<���s��sN�����\��S����7�tS����~��cs}�~z��1n��Z������'�x"��O<S�N]���}����O�5���0�z��:z��b���}�Q�v�i9�i��U�~��s�?�|���{�]��^x!�}�����O?=������m�]�������Z�=�����1l�����P���?�<k�W�^
r����Ge�m���y�����������ZSC���b��Y��d2>�`�C�����c���QZZZ97w�����k������.������\�{���u�&����v�e���������T����/��g��O��Y�;��C�u�]g����=.�����[n�%f��]�5��U�b���Y�[l�E��3�����|hj{�o~�������*��w�:]���}/�<����t:�s��())�����N��D������^����zkV��+_�J<��#��~�K����}M�u��1�������j����{_�lY���C9$~����78Y�)���N���k��?G�����_�Z��b�.]���T*O<��z�������j'�pB\s�55fkRTTTkX��3����������_TT���w���Z��}/[�,�M��AkM_�_h��.]&L��u�/_��j���??knC�M��)S����y���7z�Q�Fm|!����,~���f��t�I��n��{����:����dt-�����?�A�����x���3���v������}����SN��$6o��x�����������?�|L�4)cn��1��4y����H�^{mF�����������+c�����������8�����VCY�paVG���!���k�\{p>4����W^�7�x#cn����s�9�^������;��3�}���{��k���F�>'�pB���Nu>���1|��x��7+���O�\u�UYsc����m�������������~���p���|��1w���q2�����wt��/�8n���H��1s��x���c�����:�\rI�����?>����g���x��;�E�������������u	��-��2=��x��+�n������+��1?w�����{2�9��Z������O���)S���@������
6dp�������;�5u/��R��1#c�z���8��C2����J�\�2��=�P����Gqq�~��o}�[Y]��w��M�s�D�3��k��%��f�zQ�j��M�=:cn��q�VC�)����\k7T(�)������q������S������1W^^�A[��k���\^�z�����O>�������A���*�H���������f��k���}]��m�}�����j�j���oV���~�m�6N8��z]��s��f�m2������G���w��g���a.��_��1^�hQ�q�u����o��^x�Ygmp-�o�y�\Cu9
Ophr�v��*�H���X�hQ������!<��������e�]6x��a�+V����z���$�?��
�ws��s�8��#3�{���9s�z�]�lY�}��s{���zC*���G�Y�bkP�~o���F����[s�������_|1k��������=��:�_�6m�d���b������X�dI���
s}�;���}�����z��6�[���+c���s{���F�����n�������o�����z~!>��o�<xp�\]:���������1���[����l��fYsk;�-O�~�_ ������u���M�6Y����<X�lY�\��e��O?�����u��,W(fCB/kU��1w�����+Wf�!�
��A����SN�������������������{��'+����W3f��)S�d�=��c1l��z�\U��a���Bj��M���a6F����>�������of�������Pw�i�H&��J�j\}��r�())���su,\�pa�k�.��/��r���������|�7�x#V�X�1w��7�<��uL�:5c\���z�����1������`���7���q�9��������[o�����]w���k�������3��8���
����.]���M����t�����;����"c�H$"�L���a��i�����0aB^�1o�����s�f�}n��vy�oS��~�E��}���?�����[�����[2����_ow����f��Y�f������;.��;f�"v���v����^MeoO��Y�C������k}����>��r����.]�l��s�����k<��������z���=z|�\�������n���o�����/"b������z��'�E]�"����k
�U����U�������8����V���5����!@���O���|�u[��*�t:g�7��1W��/�����/��*��%��8���3�&N����j��L�2%�}������;n�]����z��B+..��={f���1�����_d����������-�
Gv��i������+j�!��6D��:v��Q����:|�B}�Mc|.^�8+��X�C��o���w2������?~���M��<�H���G��u��:r��l*]{`S$�49�
��{���PI~�m�6k���������E�����kW�J
g��1Ys�;�Uu���F:����K��B�Zc�s����W[
��T�������O�G��s��)���mj�WD��g�������s���e��/_��zk�s���?gu�=���6��\_�m��4]�{@���N;e����k�$?z���5W�nLd����g���N���+W@-Wg�%K�4���$
0 ��k�����9�����;vl���A�b��w_�}��GD\p�y�{nj��5�P�_�u�D6�A��T�����g�-]�t���~}�{4���Mm�j*r�o�_}^��)S�4�;���:d���g�}2�n������V��o�1cn����=��c�k���_����AphrF��57s���8qb��[n�e���i�
PI���[��qcu/���k����9�z���<�u��q���#��rJ��Q��8b������z���={v�����;kn��wn��YS��;t��d���,X�QkV��K�.�^C���-\��IXs)///t	y���o�����������Z���G}O?�t��<_|�E���g�������/���@� �49�n�ml���Y����
P������m��={f������o��u������w�y�����}����]���[n�%���sEEEq�I'�����#">���zT�<������f�e����gu.�X+W������Y��zh^�SUS���DVp��������.]S�N����j
z���1^�jU�'��64�7o��|��$l��[D������F����}�������j�k�.���������O�����^���=�I���+"b����t��T�q��~���?�������k��s�=���---����g��������rc�m�6�=����'�|2#��x�����{3�9��c��7��=������^����
��y�l����c�����_���������
B%��8����v�\���^����i�b��Y��o��T*cn��v��������5���/6�=;t��1^�h��3i��|��$����Y]�sXSP�cp��9��G5��������U����������u"���2�[m�U��������~����m�����\P��6���H��a�����������F���Q�2��V����
z��]��Bx�z+�J�m��V9����b��e��r�)u^?�L�����1�d��x���7�������~�����������E�r��GqDl���y�GM���>r����{��g��������~SP}����������:u�O�<��k����+�����
�K�.Y��>����6�������n�j��r�j�����#bu��t:�q�Yg����������v�e���
4M�{@���G����~�5��?�1���w�y'�|����Y]�q&Lh���t{��wt��1c��{���?������o|#k��k��U�V5�=�w�Y�dI������c��f�m2���[������q�[�nq�����GqD��/��z�����N��o~3k��K/�Kg���;/f���1WTT������k�OS��8����?���Y���g���q�wd����������Nc2dH4(c��^��_~���Y�~}�Q,\��^k��okq�Ms�oW\qE*i\�zhV�O��wb���w������%�.]��y,bu��v�!/����O�>�� ��{@�u�E����������,]Q��bAQ�.�]�X�a����f��g/1�h��5jb�{C�
��XQ)R�>�x��e;,��9�s��{��S�����i��� �W�^8y��^���q#�5k��O����������<x������cfii)	����F������^�u7n�������7ob���V����hY��
��z8w������g��>���LMM5*?  U�T�a����5��l�2XYY����}��m�"22R�r����5k�H������UK�r5Q��
6����(-<<�V��������������{���Q�"E�<����g���������������s���Y7n�8�l��7o����k������o��������j��q�����<y�A�I�g}�+((H��(�������������>�#""""""""�"�X�b���`ii)JOJJB���h<;R�����s��<xp��^��cGIZ```���1����`oo/JF��=5��)��W�0}�t;vL��f��!I[�p!~��g��LOO��/�~�v����7n���'��o�
����(m������i��:LLL0{�lI������h\^����KG�����+\��������������)S�(0m��������c��_-I���oq�������?������d2��������r������t��				���s???�I��3G��tZZ����S�jQU�T)L�4I�&��{�j]��C�
=NS�}��$�������_
A4*+;;[��a��
��AQ��]�D�vvv�����e�G��W�B��YSo�Q���="""""""""*�<<<�m�6�����3220z�h��S;w����oU�����S�N�_�~pww������nnn�^��(�����V�����
[�n����(}����_�>�l����,�����a������?*V������(i���$�G|��7���'"""T���������V���M���srr��W/\�|Ye=�l����$�o���7��<==Q�n]������$�/++�G�F�=�V9O�>�/������Y�f��o�V�)L}��QP���c4i�_|�������,���u����?�(����{�����������pl����%A�o��E���|��|������w�a��� �/��R2�\Qcjj�m�����\�~��ixyya��*��RSS�m�6x{{��-_��dV��O��]�vJ�BCC������Y��ha�<y2��i#JKII���?F����������P�V-t��Q��nE���;~��'I���K��uk��m������_����u��i��Y��
<Xo�� 8q��(�k��z)�������������.�_!""""""""������Q�^=��5g�t��E/e��S�N������gO$''�>�y�&z��4o�
6������aaa���d<z�7n���3gS�mU���������������,I��6:v�(	�������]�s9��u�����_��_��<x������o����/����(Q���HHH���q������$o��E�z��d�]�v������Z�n��+���iii�����7�k���]W��]akk������K�.�A�(Y�$��-�0� ,,L�����!Cp�������d�~��l{�[�j���/	F��{7v����u����U�V������������8��qW�\��{�4���(�1cd2�d�����\�+W�D�����U+8;;���	o��Att4�����������������c([�la��DQ8��_����Cttt^Zjj*������{���^�:������0��������������j����������c�����������7��+�v���v��������	���P�;wo�������o��98z�(�����.]��j���{��h���������G����8w�\^��V����;k5�iQfbb�����i���s�N^� X�f
���Oxyy����*U���-rrr������������+*x�����#88�7o��A��S���m���+������x��5n�����/����Z���+  �|����Y&�a���:����/���������|"""""""""""*��GDDDDDDDD�	JMM�(hH��B����������?.]�$�<--
���j�^�z�m���h�R�����������p��)�l;��}���e����^�)Lc�����#�"	�y��%�m��m����^<xC��?��#�,''����K]����1x�`�g����{��^��F��]agg���8������o��:�aff��G�b������?%�_�vMo������j���#F(<�^�rW�\��L�_��J��W3�b�c���#�����}{��_������l�2��j��9���'���(>|8J�,�!C�H���>}��,f�xyya���9s�(������e�l��o�2e����C��i���S��������0`8 �,;;�.]R�o|6n����K+�}/<<\�U�enn������~�|��MT�REou���K�\�F
xyy��|"""""""""""*���""""""""""uU�R.\���	WWW��266F��q��%l�����zje�*T��N�:���+��z�����/���>��|��g�S��Z���������~�
���Z�igg��{�
���kQ�dI��)(fffJ�rg������[���7�r��:����(�������;�����#G�4����;v�����w<h/�������8�<z��
�L�Q}���?~<�;m�m08{�,�7o�u�K�V�{3f�����5��===q�������������-[������+�<�ia122��%K�u�V���hU�L&�����m3f�����Kvv���F��[�DDDDDDDDDDDTt1p����������>(2�C�ADD8�A��L�2j�-Q�|||�d�<}�@��
��b_��hy���HLL,�6|����������k1b*U��V>;;;������={����nnn�=n�8<|�?��#6l##��������Q#��;QQQ����Z�6��=����1`�xxx����������,HD�$���CDD�l��:��X�F
L�0��g����?��]������"##�`�xzz����wAA}������q��-t���Z�C��m�6#  @e^�2e0b���}���+,,,4��(���DPP>�:��/�#F�����h:c��]�v011��{U�T�o���K�.�b��j��!��d�8q"��������e��jmWFFF�������q��)DFF��o�)��O@@"""�����G���:u��������w1v�X��._��$X���Y���::��O��-[[[c���z+�������������.� ��ADDDDDDDDD���O�����x�����������nnn�Q��ZA.�~��

�[����0n�8������c���#66qqqHKKC�%`ee�
*����@f[|��5BBB���K�������������m��hee��z?EYYY�z�*=z���8������%K����
�V�
www�(Q��M-III�����5�(Q���������5�I��0��=;;�/_FTTbbb���kkk8::���M�Y9?D����r�
������_���%K�����W��
*�\Obb"������3������������D�����&���t\�|9�7z��5LLLP�dI������
��U��GIMM��K����X$''�������R�
j����L��8z�(��k'J�5kf������w3����/oy��Id�8i��{DDDDDDDDDD�l������[�r��Uq���"THDDD�����v����lbb���(����w������XZZ����ptt�K�DDDDDDDDDDDT�qQ!���+5j��|��=�����-""""��<y�{���u��U�3�����yA{0q�D�}B8���U�Vy����Chh(d2�[EDDD�i;v,~��wQ��3g��E�����3T�\[[[<x����z)�������������>��GDDDDDDDDDd-[�D�=������m�6����������W��������f����y��1h���������������������������'�^�:RSS�+W����afff��}|A���;1q�DDGG�>;r�����R����Q�vmdgg<==##�W������������Sbb�}���/�-[�����yiQQQpss3`�����>�����3iiix�����$���������w/g�>}z����?�������������>A�q���������������>:6l��!C�~���	���(S�L!�������������>|�}r\]]q��q�Q�01t���������������
���	lmmQ�N���c���(^����EDDDDDDDDDDD)� ��ADDDDDDDDDDDDDDDDDDDDDDDDDD��02t���������������������������>&�#""""""""""""""""""""""""""�#���������������������������������{DDDDDDDDDDDDDDDDDDDDDDDDDDDz��="""""""""""""""""""""""""""=b��1p���������������������������H��GDDDDDDDDDDDDDDDDDDDDDDDDDD�G�#""""""""""""""""""""""""""�#���������������������������������{DDDDDDDDDDDDDDDDDDDDDDDDDDDz��="""""""""""""""""""""""""""=b��1p���������������������������H��GDDDDDDDDDDDDDDDDDDDDDDDDDD�G�#""""""""""""""""""""""""""�#���������������������������������{DDDDDDDDDDDDDDDDDDDDDDDDDDDz��="""""""""""""""""""""""""""=b��1p���������������������������H��GDDDDDDDDDDDDDDDDDDDDDDDDDD�G�#""""""""""""""""""""""""""�#���������������������������������{DDDDDDDDDDDDDDDDDDDDDDDDDDDz��="""""""""""""""""""""""""""=b��1p���������������������������H��GDDDDDDDDDDDDDDDDDDDDDDDDDD�G�#""""""""""""""""""""""""""�#���������������������������������{DDDDDDDDDDDDDDDDDDDDDDDDDDDz��="""""""""""""""""""""""""""=b��1p���������������������������H��GDDDDDDDDDDDDDDDDDDDDDDDDDD�G�#""""""""""""""""""""""""""�#���������������������������������{DDDDDDDDDDDDDDDDDDDDDDDDDDDz��="""""""""""""""""""""""""""=b��1p���������������������������H��GDDDDDDDDDDDDDDDDDDDDDDDDDD�G�#""""""""""""""""""""""""""�#���������������������������������{DDDDDDDDDDDDDDDDDDDDDDDDDDDz��="""""""""""""""""""""""""""=b�)�L&���a���U(6l� Y���(C7��>B�n����Y���q���n�i�����������DD����������[�������<xp��OD�O�~����5K��~��o����
6����^�:���abb"*���Z�m'"�O�w����
6�����n��]��%"""""�eb��KVVn��������HMMEFFJ�*����n��([����*2n�8dff�-/Y����!�����7���w���k��R�J�j��h��!J�*e�&�����q���x��9RSS���
kkk���������������JDDDDD��={�`������1tS�#������p��w���HHHXZZ���
������*V�!""2�E��U�V���LL�0��3p�������H��FDDDT�EEE�R�J�����N�2H�DT0f�����gH�'N��e��~����=�	��s������u+���_�?o��Q�����7F@@:w������[�"000o�k��h�����^�tI2_�f�p��Y���q�j��-I6l��]�U�;w�D�^�Di={���;�*��S�������CZZ�������m�����o��u�Bna�x��������!!!���P��R�Jh��>��s���q�!�D���"FFF077���9lll����r�����5k�D��M9#6y�6m���
������`�����a���E/��������
�U�Vh��5J�,Y�%"���l�:t��C�����]���G���������ed�i#66���G���1v�X?~\��=�]��]���wo899a���x��e�X*##�}��(m����~�~���3!!!j������K���2[�l�uyD����t|��h��v���o��n��C��M�6���7���
�����G0`*U��I�&���sj�@dd$6o��N�:�����O��~"""rrr���[$$$ 22�����{7,X�~���R�Jpqq�7�|��W���:��d��Y�f�I�___��������DE��g�0z�h��9;;�v���[�n����/�[�n*T��#F���sj�@ZZ.^���~�
���������������":�
<X�5 "�3f���N����,��������t��=""""""��l��U�V�����Z���������J�*J��
��������}{xxx��}�h�B�����s��iU~z<��'O�V&������
???�\�R�YIw����M�"&&��ZW8A��?�wwwl��Y�A��y�����WWW�\�RO�$""���G����?������Z_;���]r_k���x��)�>}���p��������!HOOG��]1|�p�~�Z��233���3=����4��qc� ����?���p
"""""""���DDDD�?333��[W�<)))x���(���U�T��M�OD�������V�r������rrr0a��X�"��899�M�6�R�
`oo���,�~����Gpp0BBB$� )))�3gf��]��x��-���/J��}O��-[������S�N�m���/��9����N���4*���W�u��(���	��W���O� �����}������C��Uann���H���G2{���7��g�!((fff��t�IKKC��}�������n�...ppp�������{�����CNN�(_ll,-Z�1c��j���w����HLLDBB�����q��i4o�C��o������DS����g��r��
�v�Z�d2�4�>X���������a.www�h�5j�����+���$������;�|�2n���������)S��^�8w�\4����ki��{DDDDEX��e�Q�S�NIf6����wV%U\\\4���c1x�`<��� *Ps���`�sA0h� l��Y��L&C�>}0y�d��WOeY			��k~��W���@kU��a^�x��\�fMx{{���h����@���~�:bcc��������-*S��=E����
KD�-_��������3S�N����(}����g��������`�����E�
�������N�:������LMM1b�L�8nnn*�z��%�n��_�>,�����m���H��KII��+W��g�����
���O������c(]�t���>%��m���q��QZ����GZ������j�
�-�����2��~���@FFFA4������];T�\9�����O���c��!ni���
 """"""R�����������+�����
�kkk6��]��;P�bE=�V9A�l�2Q��Q������kkkQ��������Q���>��s��0m��QhHDR����>}�$��_����?I�^�n����������.]�{��H[��a��5k��o���+�
����Kc��������U�`oo���QS�D	���`��I��w/"##1m�4�(QB������e��HHH(�����{�Y��U�f����,113g����7��W+hxw������{7?~���g�l���n.�I&�a��a���K��5DDDDDD��Q���J��4i�s�����C��{����������4Q#DDDD�������If�������g5j�|�]�=P�V�����H<z�H�2����_ERR�(������W��A��1c�(-33S�q����a�l�"I����?WWW��566��Q�p��u�����L"""���+W�������Q�N���o���A��2"�w�V�,--
������_r?�����-�z���Kc���<y�>�HDDZ2d���x��������������6�Q�����#F@Q���+�=
[[[��(Y�$6m��%K��\�:���O�r�6m`cc�v~E�p���'��9��,�����
��|��%n��-JsvvF��U�.��S����5k�H�5	����oagg'J���-j�����W_I��6m��;w���B�:���p��!|���:�EDDD�j�����Kh�����}��a��mh}����$i�Y�����C��1c������!""}*S��5k&J[�~��ZCDDDDDD�21t���������\�t	w������abb'''4l���US����8����HNN�����)����h/11/^��{�����%J������pww�{}�^���K����s����x���P�������!>Dxx8^�x���$dee�X�b(Q���+�������Um��5x���(����6mB�%�Z�7�|���y��5���/J����Fe(
�T;xx8�����k��
[[[���b����2���B_���z�
�/_��W����+����K�F���aee�q�����FXXn����/_"--
����S�Z�n]��k+!!!!!x��%bbb���{{{8::�A�(S�L��!��/22�����d������������oq��M��}�_�Frr2���Q�xq����b��puu���s��Ga;u�^�x!Jk��<==�.�����O?�����������WS�?����QZ�%�i�&�4422�*p���������;w���$����������W�^���r�KQQQ���E||<LLL`eeT�^*T�{�111�x�">|����*U
���h��*V���������z�*^�x���l����|��h����g1���AHH<x���hdff������h������Z�.33����u�bccajj
����a��6�9&&W�\ALLbcc����,Y����V��W������T��W�p��<x�			HMME��%akkggg4l�P��gy���y����8$''������pssC�5
�?W��}.C�����q��9<~�/^����1J�.���k�^�z�P�����o���'���E�M�:={��j��������q�����`kk[[[��][��[����3��sQQQHLL���oaee[[[T�P
4���g��//_�Dhh(bbb���+������!��S/���C��j+##���x��)^�z���T������5k�,�-=~�W�^��G����K�.�����>999

�������l����n�����R�8��������u���077G�����a��T�=����_�-)x� �����w�bbb��/W�T	������
Jn?0�����[[[t��A��IJJ
��������>���9lll���///899X����p��]DGG����������5jT���x.VN��y���C\\bcc!��`ee�����z���\��A����w�?���������������@�r����t��
��u��?��7o���������gO�-����HII)����������@ """��J``�@�����uy�������_�2����%�"##�>�s�������B���?OOO���J�9s����}{���Xa���B�v��7nh����!?�
��X�����W�
=z�LMM�]��+
��������q�����W���������^�z�_�%����������v�����%��8q����k�NT�����4���w�	&�K����z��x��B�-����w�����m���Z���R�bEI�����nnn�|C�-���k�J���������#�����011������l�2Q����� �^�Rz�Rf�����Z�n�Zy��y#����B����L��>gbb"�h�BX�n�����v�r):G�}���#a���������U���c������HX�d���o��~��'�I�&��s�j��)���BJJ��mTvN����l�"4n�8����gy�w�>��3�������-+���K��y�������E�~��d=-Z�q9.\����w�h�����
�J���{��9kSNN�p��Ya���B��
��e�r���'
�=�k[���+t��U�o$�W�Ba�����3gT����(�m�Vi��F�����E�Gu��	
�2������4���\\\�m�������/��uK�6����&N�(899�[_�%�#F��!T��>d�\7m�U�o��������O�����_~)���j�ny����w�}'��SGi'w�l����t�R��-�������7*T���8all,xyy	k��������� 			������
����7���'<}�Ti�Em����{����
$XYY�[����0k�,�5��k��6�����k���o��]j�q��Ua�������`nn�r�spp���v�������k���a���B�����bff&x{{��o����^Eq�%>>^�5k�������ldd$xyy	�V�R�����W����>��A������UtL��O�{����t�"�(QBiy�+W���k!::Z�uV������.��][�m^�9�����w�}'888�[�����t�R!333�6?|�P6l����V�Z��}���ME�����W���L�?u��{W6l���/������o_!44T��Ru<;x����M�|����k����9"L�0A�k��������O����j]����
3f�*U��o����B@@�p����|�>#T� �����O}��Un#�K����'8p@e�L����l��]h����~p��5��3gju�����edd�/����]_333�g����k����k�y�������7k\�����������!��X�B��M�'N��HOO���v&&&�_�����;p/''G�>}���}��yxxh��+66V�����u|}}�V�� �A:=�}���d0������333�~/���E�������r�J!��`������F�Z���{w��r��A��v��M���A�5j�}���C��T��Z��[�n���5��j��)�>}Z���R�����B�����Y�{�/�T���v���2��5k�2e�hu���c�F����������[e��V<z�H�����L���zU�5����s�4.'##C(V����2e�@��g��M�u755�z���N�:%�/_^�m���D�>}���������������4a��������qP���n���t��������r�J�����[�J���YZZ
6l��{��w����;kkk�������.h�vAx7(��������377�={���I�&)}���r�����LVV�0o�<�~[�}���K��_��{A(�����-[�����_�
���/���=E���WWWI����*���}[ap��2�L>|��������������z9A~��W��%Y������%,\�P�cU�J��S�N��C��+��{��������-���~~~�kii)��3G�k���;""B�U��F���s~PP�F�_ooo!>>^����Wk�7=z�V���P�NI��=Z�uV�^jj�0f���Y2�L�����mA���g���B�=T���^��m�{{{�������/�h=��8qB�}�����
.A?�G�q.�����	���Zo'�;wVZ�>�BCC�
h�6{{{a��U�e���

U����gbb",X�@��������U9DDDDDDdF """"*D,���c����v�_~���}�rFF�u���+W�]FVV��{�j�^}�����0o�<dgg���������FJJ�F�����U�V���S�������_k�OWC�-���`���Z���_!''Gi�4h�����������o�>I���<==
��eff�����4___��j���$���S*�	��3g��-�d2x{{�-���h\��/p��QZ��Q�R%������>}����g*��w��M�m������y�-^�����7ot.K]������/0i�$���noo��'O�G����������1b�DGGk\���/��wo��;W���z���6m*�������k��c����k����LMM����qY���h���(-::Z����(:�w��NNNh
�'O�h�?++���C��]����U��-C�6mp��U������q���4t��k���(���G��cG�����&M�H�C�dggc��1X�f�����������v���T<�V���>���U���W/$$$��'..m��AXX���=~���5���K���[��@zz��k���`���iU><}��[���M�������c������������U���!�^��=���K�~������W�\���O�����/I?z������������nA�v�Zx{{ku������k�W���o�q����[U
��Krr2�t�����N�cUdd$��m�?��S������m�u��4m�G��8ojj*f��������+r��4i�7n����\'O�D�6m4:��9s�������K�;w.F��Q�l��U�4i�F�5E����o7@K�+����+5>g	����7�y��x���N�HMME����k�.����u���Z�����7c���*������cG�~���L|��w�:u�Vu���b��m���M��u>?��<|�0Z�h��������b����8q���]Q��-[jt^�����i�����O�y���G?���������Sfb���c��=����K���>���'�������k��a���x���(�?��n���a��;v,:�����;>��3T�Z���������g�s�N�`����3���(U�T���{���{l��%o�|�����j��
{{{���������k"##Ey�����S�b���j�����: <<\�Y�2e��[7��U���������w�w���zo�����������?�L�"P�a����kU���E������������:88�]�v�]�6��-�b������HNNFdd$n���.z���&00P���U+�D?�^����dQ�6�9���=E���k��!>>>o�f������[���F*
|�)j������3fH�MLL��eK�i���������'Op��A\�xQ�����~������{�VZ_~�=�~�!o���-[����/���`bb��O����KQ�'558p��(�j��8t�\]]������n����������-���[���������@||<�^��C�����3f���^��?999���7>|��V�ret��	������G\\"##l:t����z�����nnn������)������k��s����|��7�R���(I�E���aff�Uy�������w��L�2Z�� ):~���������������VVV(^�8RSS���+\�~���W�D�����i�������i��a���
?�R�
���P�Z5888@�~��|�2���u�?t�P�y�Z�j������akk���D\�z�v������9��K���o���~m<}��&M��fbb___�l�������@tt4q��������F��m����V}���/��#:���1Z�h???8;;�����?G`` N�8��0n�8��7O�'�:t�����?+U������iS8::"''QQQ��?.]�$�����!C� $$&&�=Jy��16l(�G�X�bh�����Q�ti�*U
���x���^���������Z��L&C���Q�vmT�^������1������C��� 00Pt�����#F�V�Z���P����D4k�La����)�4i___8;;���������AXX.^�(�?h���{C��~��g,X�@�nnn�������e��Ejj*"##�w����������z���V]����[K�RSS������
4h�������VVV(Q���}���X��yG�����#�m��|�.Q������,�����K�|�A��e�Zcccxzz�f��pww������ ���p��=\�x���
NIIA�>}p��U�/_^e=�}����7���Ehh��3WWW�l�u�����-LLL���<x111y��
�-]�4:u���������������eKKKT�REe{����bE�o���$�VRRR����w\]]Q�D	�����n��
___��,�V�
T�RVVVx������o�>��w�����4������w�\�.]D/��U�:t�WWW������W�����;T����#|���y���/???x{{���	���x��v����7o���>}��-��I��e�����}���HII��k��m�6���t�R����7��7),��6��_�N�:�[�nR����h{�u����icc�
*h]���o�
�������?���GGG����=[��O��u��7GXXlmm�j���#��\�l��g;���HJJ��G���H��+���5j�@�r�P�dI+V)))x��9���p��$&&���Z�
�k��_|�v������G��
6D��Q�BXXX���8w�>�w[�h�����
�\�����?0z�h���>��]�6`jj���_�����|�2.\����\����;+��T�^=t��...(V����q��i9rD����";;[�g�����C���I�E�S��v������?��S�D/Y�h���
`��
y�qqq�~���XLDDDDDDE��f�#"""�(����h]^dd���������~�zI>sss�`ll,��;Wx��������B���%�����]�v�-;88��o��
������$�,X�@�uW����*�
4H����L��d�d���������,�y����)S�H�566�>}�V�g��-�ojj*,X�@���P�'''GX�r�P�D��<����v�Q}&&&���/5.�������6mZ���R����������4�ueee	g��F�)���j���6s�L��g}�X���~e222���������Z���/�������.���Q��&&&*��t�RQ��c��>���}^�|y��5j�d�6n������=+K�4o�\�{�n����?/���K�Y[[�=R�NE������G������Wt��?�W�XQi�?.xzzJ���Y3!66V�:��1C��\�r�����=�� dff
k���s�QW�\QY���O��������_	999
�������AAA�u�\��p��Y��A����l�"x{{S�NU�}E���������%yZ�l��o���c��u��.� =~�X�o��qQW���*W�,��7O�v��Zy������7NNN����dBpp��u���C��Q�^=���#*����
k�����#4H�w��i��;99)=�&''Tx,~���Z�*�'P�^AP|]�~�;t� DDD�����k������Q�F������y���A������6m��}_��
@T�
�<���FE�[u�M�6������mD&�	�|������|�o��M�M�����?j���������$����0i�$!>>^i��������������-[�����-[�111j�1&&F?~|��i�_�Z��������;K�S&�	��W��5,,L�4i�P�T)�����{A0\����;
��:O�<�7�������K+=�|4�v�Tvv�`ee%���?�P�/00Pprr�N�*\�tI���VYWNN�p���j����v���v�����9S���T�ZU�����{�n!!!A�<QQQ���.iK�N���_��_���5j��=���� ��7o��
�����666J��\��,]��):������\�^�G�������e}����&��[WR�����i��|�����V���l�2���_����������7oVV�����������=�������
����,X����������e^�������D�n�$������{Rxx�����
8P�z�j��A�� ?��5��M���0++K����O���W�^�����u�b��e�����E�;�9s�P�vma��eJ���KKK~��WI���\��DiiiB���%�E��U���O��������������u.VtL)�?u�#
��{�fff���+W�n���7AHJJ���o�Y�f*��>�������%y+T� :t(�|O�<:u������g��z
}!''Gh����
e������o���(����}&�����5k�*�������
����������V��FFF����U����j��%y�loo��pD�������<�ussSg�����gkk+����U��#$�����2����%�LLL�]�v�U��3g�3�s;R��}�$u���O�3|�pI9�m+7n��|w��YZ�?55U�|��C��w���m1**��Z����d2���������Q60J�k����+,*�|��}�eV�VM����rrr~�S�NBzz��u������}������&L��2�"�P�~��P�BI��z��w�����?/��6i�D�����n�����:��'?2��t�����7��_��o��ajj*��wO�2r�s�-��{�7o��8p�V�� ���k%������v��1I[MMM��+hIII*F����G�}���?W+��W���%KJ~���{�5�]��se~�t����:���������W68�}�
���9r�Z���������R�X2z�hI�-Z�P+off�����1pOJ_�{����_��V�[�l��o���Zy���T�R���'�����/_���49����a����� �\�R����\���%&&
qqq�~n����}/E�D{����:��sGa�q������A�o<e��yRSSE�&����<<<$������k��.��Y�fI��w��Q�����l��MR_�n�����u��I���1cT�c����r��r�V��w�?��[[[�_B2m�4��uu����U�={��z(;����j�1r�HI��������w�^�e���5j��add��%OEE�^���������1c��7
�n�R�O�	}�)
N122R�O��~��P�ep�=����T���.��k��I���}��Zy���z�������	&��=��L����!p/==]�}b�/�Q���h��S���J�*�@���#���_����A�3C�_��q��~'''��agee)���3���DIY#G���,""""""*|F """"*DS�N���������b���4A��i�V���WWW2D��h�j�X�~=�����w��XXX���9�2�������!J���o��{w��m��.\��w��C�prr��_�^�2��y�������7o������CI��#4�3W�����gh3f�@�z�t�(��=y�Da��v�!���-;::�X�bZ���eKI��S���~NN��9#J����|O>MY�/^����wEi���(_����8p@��
*`��m033���\�����o��wST��6l���Y���:q��7o�����'M��m��I�����7999y�e�����Q�T)��Q�n]������C����kj����k��F���?�����J�*Z���{�/I+Q����)��uyI�q������h�;%K��L&�*o�
$���;����2���K���,Jk��������k���+j������oW+�L&Sx�T���o
6��+`d��V���+��/JKJJ����KJJ��M�Di�J������:�������B�
T~����������n��}��aCQ��������4_||<V�X!J��d��}����*���*�-M���
��={����]�2_ff�����~�
}����VVV����8_a�����^��_G``�(�J�*�����Z�j������R���*GGGI���O��)^�8LLL�����F��r����uK��t��1d��h��A�� X�n��<�y�E��3G�V�n]l��]�k�\~~~�9s�(m���x�����%��P����������%�6l@�:u�*c���h���(-==]��Q���	����-[V���Z�h��������g���X����N�6
]�tQY������DNN�=�f�
g���J��<x�+W���A�P�F
�*U
����<y2���?�~��[����K%i_~���}�N�:a������~�I�6�������*�.��:u�`���4U�\��v�r�JQ���	�o�������KE�{M�\���
$�����p��X[[k\����~����X��ccc������S�_&�a����]��(=&&FRnQ��/�H�6o���=lcccl���*U�k����$����&""""""*��{�DDDDD�kkkL�6M����g077Gzz�(�m��h���������V��������U�2t�������\������#v��������|����H[���J�2v�X�X�B�m���`����7n���������V�v�BRR�(m����~_~�<�.`�S����|�M�������(�����N�).?��}��]��5j������{>>>X�f���a��),SQ}��+T�d�XZZ��G^�J�0e���5+/M�X��������Z�x�dp�>m��#G�Dfff^���1~��7�3F�2n������,X��@��}�b����w�^^��={�.���eK|��g�/�-��n�%4^�����*I�%�WQ�7o�h]^ARt��f�.J:t�{{���Mdee���K����7OJJ�d`���6m��V���������W��5j����'BCC���\�RMSj��EQ���?���(���+J�/�l�"�W�N����,--�`����_�<�y,�%������$=U���?��������.	�{��+���"J9r��}����;w�-�;wNe��[�J��k�N��m�~o�������@sM����k���;��������
E������V�Z�s���g5~���d20!!!yig��U��0��8p7o�����/Z�������E�������C�a��Azi�:lmm
��W��!|�}[M���������;�s����|�rT�V
���yi�W�����5�o��(�p�B��������iS��mll0e������3���D/�

���XQagg���@���[���� ((AAAX�x1LLL��];4��w/��d�<{�{���9::J��T�����n�:Q����

����Fe���b���������c�����������������#x���(m��a�*e����t�R4o�\�6�\lfff��gu���O`����#/hk�����f��Q�W���e������~����(}���9r�Z�!!!�����k�\�X�bX�d	z������+W			y������������b�����:+V��UCxx�(]����vP�66l(
�KII��g��������x���(�O�>�Fddd�����������2d��-�6lP;po��
�eKKK���+��+$v��Y��Q�y���$M�7Zvv�d�u��j���L�2��ZaaaHLLT�[����h�=���f�S�Y~�{8}��(���I��X��9s��
,;v����T�ZU�7f�c����|[ZZb��m�������?�x7+���]�d2t��A4x���S6h;hM��{��%deei={�*^^^+�������\����E�{����qx��ruu����/*
�9}��$P   @�Y�t�m���L�����U�J�Y���Y����@<U�'O�-k5`�G�7n�h��&��������7���4��(@����J����'Z��d���o5�����J���s<~�X�����	�'O�{��)����}�C�����)�Q�1��Q�������$MQ�D��V�*:w^�x��ZVF�����|������j���^��R�X1�l�Rt�;u�T��u��E����;b�VS���|�������v��������F�iT�>���U��f��i����C���3�����Z�j�~�z^Za?K�V�r�p��i�\�.���T&++��P�fM���Oh��]�V��'O����^8�i0���)F�!��;vL���!C�@&�i�G�J�*GGG�|�2/����J���a���f�����w���(����e��-���7o���Di-Z�@���
�"��u����A��5E����_���/Q�ti��X�����]�v����F�bU��)�7n�-��1���������Q��&0�b�����-ZhT���-J�,)z����e���CIE3&&&��w��EIZ��5�x7��!��W���������Qkv�G�If�������A4h###������1���j����Z����E�}�$������@/o�m��%��������l�9sF����������WW����=��{�$�3���&EBCC%o�����V[e��A�-D���{qqq�����ouedd`�����i�(���	�������$����:wU�TI�|��U��P6��2�5���[��###1b��X�B�`���.�:EyO���8��
��� <<�=BRR���%�B����hY~v*y�������(V��������W������Rh��is}add�����D�y���(S���u[XX�u����k��yI;���ORR��<��IT�RE��u�����g����k�q�bbb��������g@qP���=A$�ggg�j�J?+�����
��z��"##Ei]�v�j��v��I���_���C<x��/"<<<@RR���������#�/P�O(,)))8s����q��-���!))	���
+�YF������K�+WNa��y�E~�m���N�����
�������l����h���Ve���[2���s�4
�+V��^�N�}� O�g	���"
�+�g	�055��	0r�H���[�l����5
N�y�&��o�i��a����:��Y�{���UY�{����3��<m��G\�rW�\�������S$''#))I��� >>^���� 
����
h��N�:i��s�rE�>�*����t��(���]�~[�^�$�0�;w��w���E~�)Q���r����]�t������4�����,�}�V����������ha�m.�,YR�\�X1�-[V�r��S5HO�,,,�����g������4}{l.wwwXXXHl
��!CD�����o�>�3����%����4���-�t��={���EFF�n�����+>��s���i<K��d���<x���������@yo��������|�����|�^NN������������{��)I�^tt��
���*����s�;��"
4
tW�^E�6m�.C���2			������Q�<��,Z��������W���m������t�y�K���|�{���i�D��6l���b������{���O���\��^�533����T�����������~�z��uK��T���D�FFF�����+����/��ja
nVP��v+�c'$$H�`��������{�H�mD�����`I`�������������s�N��s��<x���Q��p�Q��!�^W�\������LLLP�N�y��Q���{}����u��a��5		�{;
��+W�x�b���O����UX�_�?���(Q����u��gIyfe*�>���&RSS%�c<<<�
��0�G�=e����u����Y���)�g	�baa��� ##�/_���gq��e\�z<P��� ##�/.�VK�;SSS��[W��*V�QV��Z&��ty_bb"�,Y�M�6���G:���� �����C��4��s�j����y
���w�J^��}|y���E2pO���n��Z������������T�}�GDDDD����F�<��,�)CQ9���� ���j�O�e����-���i5�n�_���q��=����O�>���/E���_�4pOl��Q�V�J����d��9sF4�2;;�w�����all4i�
4�����A7�E�NZZ���U��X)��D���Y~�I���������Q�t�|�������)*s��*�Q�jE�*�W����U�Q��Zu(����u��$''�i���}��(�e����{7���5.3..NH���k���>���+�&����V�L,X�_}��(���W������?���M�6E�F���qc4m��H��E��;pO�{E�yC^���{��A��e]�����K��������������vk����iK~�*X�l#�n���0��][�z�1g�,X� �@5��xe��|_a����{�z�J��j��i]���;�����S�����o�_�~z���P� ��������r�J�3�iC�����`{���K�1L[��T�|�}[M���I��t�����.����W��,A_���@]fffh�����III8w�N�8�;v�;���%K���-yAXA���\\\t���F����4��K�(���������Q�F��|������%��0�ay.VM��011��^��}�� ��]�^�����t�gVV�^� """""���i��������m�t\e��j���3Eo������eee�=z���=����|��9s>��;����+�?�����l\�|���T�T	�|���o�%����~}>�/L��z��Y-]]]Q�|yQ��k�$���������s����)�S48V�@�\�_��f���g������5h�G��z]k0�&�b��n_~�%/^�p��.x�����9s&��k�h���//��:tagg'IKII��<Ey�Q(:����t�I`` �������)���E����@��[��K�~��������F�=
c?;v,f�����=@���P�)�0�O
��R��cN�Pt])]%�������[�`�`���L���+V��[�^n��������qO�C��jB��W���$���������Oa{����:t��%K� 22[�n��<�������O_��m]�k@�_MOO��7o���������F�=�zO[�9���I��U�?��*U
2��@�Q�(��/III��qQ�St
���b""""""*x�#""""�H��433��<C�h6d��rvv6����|��~�z����
�v}�q�-Z�r�DEE���F�����M����]����E�vx��e�Fw�f��eV����������3�4� ;___�eV�XQ4�Att4�����LU�&''K�t�	LQ^Eu(�_����w��e����Z����]�A����~�7n�_�~*�������g�b����X�"&M����T��P(��P���������(
��:##���h��}-  @2����~~~X�p!>��7o"66)))���� �?U������D����*EAQ���?�Y�I9�}(��x���
����6l���O!**
�_����o%����H��4�z�!�^��_�w��U�\9�<������7bbb$�5o��f�����q��5�z�
��������{���((�-���{%�������/�y�f\�pO�<ABB���$��h�uu����x�DT�}�P����W��!  ��]������������K����N����:��u�~������lQ���)����t�R?~w��E||<RSS���#9�j2���ay.V�C�T����~=��y��������>�{JDDDD���s���
�,,-[���������6l��)S�H������;w����m��lm�)^�8&O��I�&!((����3g�4����h��V�^]$�}LLMMQ�vmI�^pp0�w�n�Vi���%K����z�l��-%��������+��|�������
��y�����'�~��5����oy%K����|�(��:
���3�L���c����\|���HII����q��fk���[un��U�V
�7o��+p�������{�n�os��
�,Y�}������*/]�|��/���E��bE3�<z�H��?~�VEA�
`oo/�E188X�`���`��`|///�����Z����h�mee%:�2�"�����������]�^=���j������2X�E��Y8
r?�������%�S�N��3���X%�c=^��U�ez��h�U��X�z�dfmWWWl��U����^���W�^a����4,^����S;@A��(��/���)S���~�����o�>��1� u�-[4H���������
>�����UCFF���'N�q�����%K�f���v�[Ga�:u�$��}�����?Q�L�����k�k��p.~��9:v�Xh��;x� ��-�����VE���S���HQ���dkkccc��ADDDDDD��{DDDDD	�rrr2222�~�j\\�>���L���c��Yyiw�����%v��!y�%?c��u{{{�����Y��������#00P��<##��
C�J����~���J�N�<i����b���q�F��.�j�O~�=@<���W��������������S�Na��������}��)��8�R����V���e��1(Q��"z����������@{{{I���>��R�J�o�����/�wo�>�<���p��A\�~]�'""�:uBhh��s]JJ
�]�V`m�U��aaa������'O�h}���$���]�6$___I���'��5�I> �|��8~���Ao�h���������E��s�.�d]��XV�	333�>]���I�
r?>}�4���Ei���������J��z�2d����Z��~?^S����?~\�V�dI��];�<������������Fu��o�>����-��_~�Q9�X�����1^;��������6>�������JNN�$8�(�_������.]�H�����[(������e]�C�����Q�xq��TWjj*���?Q���'���SSS�����]�D	��� +++/�0�a���8##�����������!d2YA6K#�}|M�VVV022BNNN^ZQ�����l�DDDDDDdXF�n�G���E�� ����Z�������YZ4h��A����%��O���A�n���xyy���������+�Z�J�����lL�4Io��;]�t���������h��*W�,Z~���^��X��dF�����A�Av�����{���M�����$M~�
M��uK��hp�!0��o�^-Z�����w69E$�C]fd�����S�N�����w�b��1�7��y���3P+����u���edd���+�������Q����Foq/l���{�����/��o��~�0a��A{���e;99�����t�9���������4E���
��IE���������,��a�`���;&Z666�jF��j���^OC2d�K������s��.��(eggc��������;�>%%.\�
8P��=@�}O���!666?~����z���K���%i��SQ ��h{�7�K�>4����s�.�W���+
R���>M
6�����J���###%3�iB��aan�g���������8h���'W���5,����_[eee)��mH���o��2�L���r=����/^����	Q���=""""�����/^��,m������$h��m���?x�g��}�o������T�D	�5
��������x��I���)j��9�V�*I����
�������#**J/e��/� �����Av���j�����r���-�|�2��|�2�Le@����$M~FEM�(�d2�uJ����o�>+VL��b�
:T4�2�[��(-""������
����h�\�v�2@���E��4���:�^�*�A�����{wIp\ff&��][��Pt�V������WE�'��I�&����Ip���)���'J�lVWQ�g+++I���-�x������!5h�&&&��s��X}����U�*�������+K�9����~���_��$M�`~����5�R�v�Rx
6`��|�<�\r�������K���C5j�q��1D���R��d������}�E���hs�������9������Z�j����0��u��+��s}��F��[P�������������W������u�A�s����[�ni}l����b���{
�
777�(QB�������������u��5��_m�����h&M��V""""""*��GDDDD��h����M����Vem��EM����CE���������7l� ��j��!�����K��o������Z���d�8q�$}����t��Z��
H����(��.00���

��;���������uu��������<==aaa!J��g�V�_�|)Y�j��I�Z�v�p��a�,YR��a�|���j�)�m������w�����}�JhT
H���� �SG���%i;w�T�wQ�GQ�E���%F�!I_�h"##��f��x�m�6��(
���i���P��T���j\NDD�N�y,S'����Z��M�J��>%K��0�x�b����9Veffb��=���>�'N�������^����Y����U���#G������}�?�	&H��T��N�:��O_�����k�'�������1$66V����4��bdd���[��RRRp���k�<��]l����/�����h5;���0��M���SRRp��a����c�������e�^��c���N��#���kC�g������R�{�����h��(��]\\z��jV��>����$���;�y��V�i�?��B���E�)))�Y������}��i�/?��]��)z�DDDDDDDE������>666�����={V�7�>x����t��]�f�
6x7���Ku��)������K���O��#P�reQZvv6����?���^����Q#I����P�w��)\�zU�]V�R���j�+?@���S�����_�����{/^��j�����%o��?���8q��dp��;�����[�v�*I[�d��7��{?��n��-%�����5z�|FFF�92����������5u�T�����1h� �g5S$''��-S�����$M���			���?5n���lllDi��o��G�4.�
F@@�$m��%��x�b}4��rvv��K�����z�j}5���kA(��o��X����������StN�X�kC��:t� Z~�����`��5�j�G���������`�E���(�G���'dff���~�(���_����U9�8��X���gF������w���zoS~���!���
��/[��>N�<��&}��k'I[�j���DFFJ����%/&�O��}���Ui}�Z�n-	V��i���������
���>�<���{5��G���q��e�e�/_��o�j\����E]���%�Nm��4}�g���p��
QZ�:u�������������/^h�/?���d2�������> �#""""���3F�6z�h�y�F��YYY5j�����4�+V}����8qO�<���'���c�g�5�^.E�]
�
�333�Y�F2���{���C�~�Z�:�����|���:��L���Q�n]Q���q�rvvF��UEi7n����Z���}_��=;v�$��o�U�8�=�?� J��d7n��e�
���Sprr�8p;vT9��Y�f��1?|�P��;�c��p�566V8��w�}�v?��3bbbDi}��Q�������K�.���w��z���x�:t�7p�L�2�4M�?n�8$$$h�����c�������0@����������C�v��al��Y�2N�<�u����iE�����w:x��F������3g���7f��G��YS �J��"""��	x7���}�^�zI^�q����2@��}���GK����[ddd�]���������s�6l����K>���'�w��4�>�	�g���{�4��>� mf��r��y��!n��i�����	@�*UDiAAA
��A��*22R���?T�^����kT��)S�������d���?:�Q9������5
���:��
���[�k���s
g�R63-���T��e%/�x��%f���Q9��-���wEi��5�\�$]�999:t�V��+W�;w���qCr?U���oc����
�\�!�2e�$m���Ej���C����B��j�*����]FVV����i�3���
H��w������iiiz�$��~������kDDDDDDTp�GDDDD�����$������sg��������8q� ����C���srr�q�F�_�^�njj�~��iT��
�k�.�~gff�����V�ZJ����B&����gH"�V�Z)`	

B�-4zX,o���]�6�l��K���cG���s����������A��+Di��Uqss����`��m�����[��:v�(�-!**
}��U����_�F��]%�~�;w�.5�k���3gP�|yQz`` ���T���7O�����b���Z�q���Xu}��7�u��VyCCC%���a?T&L��������}X�+W�`��Y�4L�:U�����$�'��� 
2}�������~~~��������l����U���r(Q��(��_~���O��g��9:�G&N�(	�

����U�"g��������a���5S��3g��[��~�> }3��7o0}�t�������8��T�R�8q�(M(|��*�^����-Z���)��H\\>��3�f�����������K���HJJB||�Vm)��{��][�������!C�
j�w��U��7x�`I�@��Q�=y���=���$�|�~ku�����&J��e�����_�^�`���k��O�>���n�cHJJ���QQQ����V}����bbb�p�&O��?��C��s�?^aU���Ubb����������z|���		Q+��y���S����������}�=c�������/���O���jM^���
6�R�J����������}�6���#����UKrl�'���7�n�W_}%I�����u�V��>|Xa���_~���>o�<$%%������Q�F��R����^2���3������h���V���?���/y)JDD:u���K�
�8coo���������G�fp���������
yA��x��NPrvv6�h]���o������4��LDDDDDDT�1p������#bll����K��|��I��������W�D��~�7nD�Z��[Z[[Kk�Q�F�^��(m��u���Ei�;w�x����0���U�T�����V�G��K�.�Hm�����E�3o�<�to��	���_������X�n������{Kfo,H��u-������z)[��w�3�i:���<�ezxx�=��L&��u�$G���???��?���.]B���%�����j
:)
�V���g�J�:}���j�J2c���5k��3gJ�����V�Z�={c\\��]��m��N�:��i�Vh��n�:��Ym����5k$������:t�XWg������s�����?����7�u��}h���d��_~�j��H[����V�ZI���9www�?^��j^�|�_~�nnn=z4����~���Tr|~��5Z�n�48��������h���uK�����q�$@d���h��	�?�����_���+H7�������(-##=z�@@@���$�����5
-[�Drr2�I�&��fC<x���|�r��93��Xvv6��]����#>>2�fff��\������������];L�:U� ���`|��pqq�����}{I�����1|�p�A<G�E�&Mp��e���w/V����(-==��9F��g���,����:u**T���8
�!�^���;���Ei��7�t���7��g�������f������"((K�,A�.]P�R%,X�@�������'O��/��233��}{���			�8q"�
�w��v�k���h911�}��F����FF����/����?�/R�����I������Ga�����d�vVVF��=z�}�y��)~��4n���5��}�T�����;?���.Z���A�N�p���|�DGGc��Ay/H����T���oP�^=QZll,|}}��'$$`����;w���E��l���n*��o�b��epqqA�6m�a��_�����~��5R��u����rrr��W����&�6m�1c�H�0`f����,�����������/�����d&��V�L4o�\�v��}�k�N��v�������c�����/^\�����$��� `��	h��-�9"y���[�0e�xzz�������5���C`jj�m��I���O����v����e!�����m����%8.����(����h����{U��=C��]�q�F�g�W�V��o���������������������v��@�cAAA��Z��]�R6C7��������N�:X�|9F�-z�����;������#������k�z�J2hp��UX�r%�����&���0
2�'O�[V��P]LFEEa����?>��)OOO��We�����5���������(�?�N��<�677�O?��ue��X�l�^�
�K9���d��q#J�,��+W�>�����-[�e��)Sm��E�*U`oo{{{dgg#>>���Gpp0BBB��Q�6l777DDD�����K���Q5�^���%������G��/E��4m�3g���3D�����Q�Z�n�V�Z������x��	<����K,�d2����P��Fm0�
* ((m����q��U����������1c���#y���S����
777����f��������9���k��uW�\����5P/?������1z�h��Y�Q����`mm�����}����r�h�h}��8q"�=�C���	�����c��U����V�
sssDFFb��=
=��_���+������98�>}�`�����222�|�r,_��*UB�6m���{{{���"##����w�.^���W�j�������m�D����xxx�}��h����+���,DGG���S8~��(hr���x��N�>���w�����������h��-�V�
???T�V
			���@hh(.\���v��'�V�\���o���������c���(^�8���`ll���hI����'f��!yk�!���V�lY�?^������G��^�:�/���8\�~�Da��)���>��#MMM�c�4l�P4�@FF-Z�_�>>>h�����`ee���d�|�aaa8��Z����������{�[�{��A�^����	$$$�������h�566�/����5������o�f��W�������iS�l�e�����
RSS���p\�xQ�.���rww��$��8�*U��C�h����)��o�������w�������z���������JKKCbb"��F&�a���X�l�FAB_}��/_.����h��%�����];���@&�����p�:$:�n����������7���1}�t� �������A���%���-���������I����
6�g���S�J�(���x��{����R�xq,Z�HT������j�*��_d�{�n���u������V�
;;;!!!qqq�q��\��{��i<�f�F�P�F
�12""�Z�B�b�P�\9�����F�������e111h��9�����m[�+W������FPP�;���ZXX`���
g����������F��
E��������f�B�n�P�J�,Y/_���K��o���K��S�N
g��GNNN�8�'N@&����
�5������`kk���$%%�����z�*N�:��}���'���� ���^�t	
4@��%Q�lY�����'���O

�7��������r�J����N�:�����w���[a�a������
������ukQ��������]��y��prrBZZ�={�c��!((Ht��1c��[�����9sp��e�<yR��{O���NNN������/%3�U�X���6l(JW��P������/_��#G��������7��+�v���v��������	���P�;w.o�vm^��[[[l��	~~~��222m�����':w�XXX ::g���������&)o���j���B�����/�/�={��>�����{Q���9���q��i9rDt�p��9�4i�Fu+�k�.�r��5����s�DDDDDDT�""""��
D>>>Z�))o���*��_�^�/22R��
$*�b���!�P�bEQ9�
R�G�u�W��_����������e2�L���_A�f���>����V��/^�LLL�m��������q�'N��������\��}�Zu���h�O����3������"��rI�i�&���Z�����-Z�u�41w�\Q����rrr�Rv����]�!C�hU���7��v�����g��fjj*l��Y��t=�*��1?66V������r��J�7������/�d2�m�111J�*���oQ�T)���V�Z��g��nGQ���,9k�W�zu����������qZ999��������-+l��Ai��V����V�Z	iii:�/?����}8�?U}]}��������k{]��.�#��WO�c�����c��I>�j=����T�f��Zm�Bvvv�^�)"_���3�����c�n��:���=##C�����\�L&���:�S���B���u^Oe}�������������|KKK!$$D�5��������Pt�����-[
.\��]������V�ZB||�N��f������NHH����ZSSS���_[��� ���o��C��m���T��'Nh��h{�*J�?.���j�����{������C��
�~�Q������:m���w��}�v����"�:��g�����k��������F���a��u(���+�a��:�C����G����z����S�j�����999:�oo����m�q����n��%��wO���={���P�����[�b������:��z|<p��`ii�S��/dggk����B���`��eO�<Y/����l�9���c��������>J#F���K�P�~}��_�re>|&L�~�Z�y�R���Fu�.]Z23���'wtt�L&��i�U�N�<�^�z�Ti���������cQ�X1�������I�������i��a055�[~��)��9�����~����Q�~fbb�-ZhU��3��?�h5�@�5p��1���O���;;;�8qB��=|�-Z����w�322��y�p��A��[W�6�*U
��G�%t*GNNN:���d4h��=�A�H��%J����9r����������ptt�����IZ��55.Gd2���[��}������>ggg��?�����A��~w��Q����aff�QC����%3�h������#GP�vm��(]���� ����q��E��9S��occc�5
���C�2e$}l�����P�xq�>}Z2+�2�����
#���E���q��9�?^�c�������LMM�o�>|��g�kmm����c���Z��}6668|�0f����%KjU������tnKA3d�k��X�t�����S�\9���K�fP�7�U��NeB�J����_#,,'O�D����.�c����c����g�}��� ���h]7�nv����k�O�W�T)?~\���l��8~�8:v��q����baa�u��a����\��N�;::��/�P���Z���������Z�n��{����R�<���8r������b^^^�p���i�q^KKK��=;v��h&R�Rt�tpp(�c��������QA�z���������U4h��]�u�P���1z�h���d2������C�
��m-X���O��<hll�i��a���:�?�+�����_U���G����z��:_��\�!	���g��ys��(��L��q����1����r�J����_���B�
p��I���c���X�h�Nu�:~�8^�z��lnn�����l""""""*<�p"""""R������8y�$�����W�K����	J�,�5j`����s'"""����������lmm��"C���3e�M����h�[����C�J���gjj�:`��-C��M���t����������'X�|9Z�j�v_������������u/S�>��sQ�����R���=�����V�^�~}����������?���QLLL��ys�]����:�OQaee��������`Nooo\�v-�����GXX���?t��]�m�r��1bv�����h�Y��P���sW�\���s��m[�
��	

��
>�@��YXX��?������G��&&&h���=�]�vi��J�f���UY�������7#**
�-B�&MDA�����b��!8v�?~�i���=�q��1

E@@��������sg�9s����K�^�6m����k��u+��o�V����0a�����mp)fnn�Y�f!**
��/����T�KKK������	����={6����U�V������������������+�����������C�;w�/����rYZZ��_��{���W_�j��*�/^:t��5k���s����J���}��e���SG�w1i�$��{={��h]�111���3�����S�����fff������K���3xzz��=�P}�/��7n���A����1}�t��y
4P�|E���$J�]�6z���S��&��`nn�R�J�b��h�����1u�Tl�����x��!~��'��.s���#<<�F�Rz�idd___���������u������M��g��|�r�V�Z�����?����3g�`���*�W�Xs����;w��.T���_������l��:tP��F��0a<�g����T����;#**
��o��a���aC899���R� ���C����P�lkk����V�Zb?^�+W��c�p��Qt��Yee�����W_�����1c�G�3$E���'O���c�t��	�w�Fll,8�)S��Y�f���/�Q�F����

E�f��j��a����3�_������
�/��+W���:t��>���->��s\�r[�l�9h^d2�����g��C�J������o���r�
������������GTT��_�.]��Z�j������)�����iSL�:�����sg�o��kXC��?$���

��������������c��8}�4�m�V(m��m��������*�|�����o�"�����f����M5Me��Yc�2�49�d���������q2[�}5��I3�\DEPTe=l8�?�u��9x��9��������?���e��|G�8���z���'�xBYYY������\w�}a����u�^x�%%%���������N�6m���?�������������M��e0��fw�u���l�?@����8q��*r�c��)33S���Saa����%I������PJJ�RSS���|8Omm�v�����,������\���
		Qxx������_�f���������G}}}u��AEFF��*������M�t��Q���SQQQ������C�uX���f�v�����,;vL��S}}�����=z(%%�)/v���zegg+++K999*--UEE�|}}���;�O�>���ww�nSQQ�
6h���:~��������w�yN�o:f��X��������n���^T\]]���4���O���hT}}�������h
0�i/�3�Z�n���������`0(""B���<x��n������M�t��A���D���


U�����W�V��
�w�-���w���ccc������\c��=����u��Q���)88X=z���a��ep�������/*((Paa�����N�:�g��JNNn�-Z�������������R���)&&F��������#��e��=���B���(((H�������RRR�v����g���j�]�V���:r��<<<��S'���G���s��S��_���?�����>�u�]�������j��h������������������i�&�h4*00P]�tQ�>}��g�9��������[����c���������Ppp����������d��L��L&�[�NYYY��}���:��s5h��f�������h��
:p�����;t����(���������w��X������o_������WNN���������T����7�		Qll�����*n�0����}������G����X!!!���R�n�4h��VB-..��<WTT$///����nu���?�����������UVV��:�^����:�������Vaa����������`���+%%���I�F�_�^����GUSS���Hu��Q���Wlll�����/���C;w���C�TYY���P%&&j���N�Q>??_���2�L�N�w������=
��=[>��U��;��wo7U�O�]w�>��K{���6m��
pV2�L
��h��}��'���k�X��TWW�k��:z��������|�����g�}V�=����������.�@k��gO������={��L�����������o�ni8P�7ovcE����'���O?mi����������g�u����������o����H����M����3��z��9���pcE�F7n�
�
4����|�M���$]|��n��[�j�U{����hD^^�Uh��s��]w������[�r�UhO�wX�U���5w�\K����*�h[�����*;;����;��
p���T�?��.,,�k����������{��SO=��J��k����:u�U�������������������������{�c�=&???7U4��c���?��A��>�7�|Y���z�����X�9x�-�}�������TWW�����M�<Y����U�������ng���{���li����TYY�+p�9�V��C���+�pc5@�����+77�Ik~��']z��*))�����[�������_���JK{��n��������v��;������y��g�����5�v���_��w�#F(%%�������T�=�������n��\��v(==]�_��������E_����������/�����^=z�������>}����]P5pv�����O�ni����w_A�*�������,m^�4��_T���5j�(��7O����L&S�y���������N^x������;w��g�}�Ue��N�1��.�����X
m���?�q������7o���RSSu��j��Y��y���4����L�~��n��6���G;w����y�\U6pV{���u��1K����Rtt�+4��l6��]�z�������6�SDD����UZZ���B��#��F�����Z����jkk��/���F��B<���n�
����O���V}�������BCCU[[���"����}||��W_�w���+J������{�n�>OOO����TTT���������`0�����n�����4k�,�FI'��4u�Tyyy��*@s��!{����8q�^}�U���l���S�N����4l�0'V@C��{M�%K���k�qbUg��������W�^g�v��!���O��o�Nr�u�)00����������U��o'�p�+��RaaaM^����;��C��o'��L���c�������~�zeff*''GEEE�����`Pxx�"""��G]t�E>|�����V���Rk����u��}�v���_���hTUU������;j��A����5j�(�����t�Y�d2���~��?��-[�h������SYY����������u��A�E]�Q�F�s���.�] ��y����{8�=���NDp'"�������D�p"�{8�=���N����^qq�����Y�������ucE@�R]]�X��\r�����Wp)�{�Y�������Zw��5>��]s�5�.�����=!��y���k����O�����j�j�����q��=d���"h9<�8����l����
�{�&<�8����l����
�{g��{���k���O}
/h��g!___�vBB�RSS�T
\���TG���SRR��������l����
�{�6<�8����l����
�{�6<��W����o�.����NDp'"�������D�p"�{8�=���NDp'"�������]h>�����z��fw���yxx�`0��+�h�L&�JJJTRR"��DhpV2���Vhh�BCC���������TWW+??_F�����vf�Y555*((PAA���S'�����&����d2)77��v�F����d2���{�uuu:p��jkk�]
�Zmm�8���:�����S@�>|X���V}
		QHH�������?��G}}�L&�JKKUZZ���z�Xuu�>�.]���.�{�uuu*++�����Q\\�����^>>>
TTT�rrrTSSc+++S]]�<==]Z1z���h�6���%���������X��S����=��So��������u���Q@@�U_yy��� �@p�mA���n���-((��Mp4`6�UWWg������jh�N�q���Nf���5������o������Jh�l}�����%����uK��`pC%�~��Gr�m�=���NDp'"�������D�p"�{�����^��r�/w�IAA�v�����,�l6+<<\]�t���C��������lVyu�Lufy{��%������s555Z�b����K}��w��w����A�������c������_p�]GJ���C�~�Xiy�*�4Y�B��������k������n�mEvv��u�fi�v�m�������������_��W94�l6k��������9s�����VbbbW����p�U��5�>m�>nwNI�I?�=���+��4$>B�/����]X)��,--�nh�c������|||t��!>|�j|��M6l�~�������\��.�]��5���[5���
���1��n��&Myo���5-T!���������:�������S~~�~��m��Y�RFF�n��v�5���3f�***�T5Z#�{�e2�j���g�5k�O�����]GJ�T��Ypp��M�����>��q��`^rr�����h���2����\=����,��=��K5����/�v�~����i�z�{���k���}�4c�u����5�����X����-P�*�{��k4a�F�T���oI�I��g���5N�����/Tddd�������u///Oiii�,
m��������;���S��Vk�������-�{�i�&eff*//O���������F�UUUi������PYY���������.�H^^gQ)//Wzz�v���c�����R�����������t�{�����~�Iyyy*((��dRHH��u��>}��K�.�>#77W���Snn��f������_?����*(v�jjj�~�zegg���@������Rbb��*OO�3��d2i��JKK��c�d4������`���)))I=z�h���t��IIII��{��/77W�{�vcUh-���jW�>�~�E��t�!]�/F�%wj�sZ���Wk������O>�������N������s����`]@@����^��1C~~~Vceee�9s��������k���������;�p��={���w���_���7��������hM�<Y�������7>>^999
��|�M����v�-Z�H&Lht������_���kUSc������t�M�4i�:w�������i�y��Z���xll�f��q�Z�IKK��3�|�r���������k��i�����{9rD3g��;������F�FFF���.���5z��&}
����&KJJ�T	Zw��������������h4���/��)Sl��$���B�f���Q�TYYi���������/��IRAA����N=������_�g���>}���_�hhO:{��'u���j��M��L��%�\�+��B�V�j4�'I�>}�}��&�3g����vC{�t���~���4i��������V����������nhO����5w�\%$$��/�th�o��F����7o�iC{�TXX�e������nt^vv���Gvv�C5�J^^�U�C�n��
7����H�6fw�Y���#e���������c���o������(&&F��{����,ck����)S��k������������+I2����:t��c��i�>������5h� �r�-��TUU�����_���
��`��c����cN������^���7+%%������c����
<x��Xxx�bbb���begg�d2��9�����)S,m���+((Hyyy:t�����*99Y��_O�wEE����?h��
����-<xPG��������k������n�����������U]]m�������x������N%%%���9���5������n��
�=����z.i�r�%�s\~�������_u�����[��g�����n��fM�6�*�v��1=��z��W,}�������~=�����������N����'+::�2o����4i�~��K����7�x�����n�.OOO�3F����u�e��{�����~������g�i����g��!�q��i��-2
�}���UYY���|�?��?j�(=���v�IMMm�W\\�k���*�����	&��{����j����������j��%�~�'��w�%������3g��+�����e��-[t�}����~��M�6M��v�iox�<y�Uh/((H>��n��vu���j����5s�L}������:�q�����l�?u�T��^�~�4s�L�9R>>>VsM&�����|�r���{���������l��SRR<�8{��;\R��^���e��[�s������Z3u�b#�r�=���^|�E=��C
�;t��y�����R�-�t����n�I


�W_}��.�����={j���4h�222$IG���_~�k���nMTVV�����=88X��r����z]������$I��m��_��/����.�����U���5b��F�;������~K;$$D�|���ns����.��B]x��z��g��/�8tN^^�$i����������������j��a��}��!�%K�X��w��K�j����v�=�b�
�������}�������Y�4u�TI'�=��>����KJJ�r�JK;99Y�����������������_�=��v��e��������={�U��	�RZ����S�t�M6C{'�9s���w��^z�%���_h��iV}��/o��n���6�w2???���[


���2l)�v����K-m���e���
��*  @C�u���]�j���6C{'���s�Y�5�X��fM�>�j}c���=������,��?��r���������ZK{��	vC{�$'';<�51�����;UZZj�;��st�����*�6��)���3f�v^LL�
d���'�v��W_m���uk�=�������[��3N6g���fK{���=zt����#�X�9r����-�-[����b�
���L��Ph�W�?���s����?������J�������;">>^f���#>>��g����{�r��^y���"�F���>}�())����{��j_w�u���<���� �0Unnn�jtT�n�,��������E����+WZ�������Y�A7�x�Cs===u���Z�����9��`�����&���OEGG[�k��i0'&&���l�2�L�&���|���V�FI���������M��"��N
8���:t�j0������:����Xo���n��v
0@�;wV``�C��g�}�jmaa���4�������eiw����m�����oL����%%%6���Trrr�k����|����`<..N������
4f����]��_�q�������w�Ei����+
����@����rxn@@�S�VVV�v��h�SO=�9s���1�t����h������~<��N'00��m��>9hg4�������?n�������[,�U�Vi��U�������u�%�h��a���k�������+��R���}����?����+CkEp�v�s���L���X�M?����Aq�z��~.;�d�C��rnc�������mLaa�.��2����Y��i��tN
�55X�T�}��fs�>��������~�����}���OX�����h���N��7j�(�;V����`pj}-i���5j������D�X�B���n���=�1/O�F�~b9�[�K�{�u�p���������bcc5|�p���K]�tQPP�����n�[�x��z����������g:[K�Fh+ ���\#G���3�b�
���5������j�������^z�%�9��u:��C�4b�:t���o��V�:urceh�����~1zeu����{���B�}��gZ�z���W_}U7�|�UH�����������������\g
��FDDh���-z�y���/��R����+�z�j�����o_��iii=z������l������P#F���:v��o��V]�vuceh����!���}����-B=��O?n��{�Y�,X��o���������!�D��dG�u���&///���J�*++5b�����sg�v�m����$���n��U���O��g��d2I:q��C=���?_C�uImMQRR���G+##����+W*))�����h<��Lw_��%�L���K���[�~���:��otxmzzzK��@BB�U���v���d0giWVV���Cn�%&&F����|���L
<�2f6����/�����F]y����e��/((H��/W��}�X��{�E]��I����g\�/F��;��h���|��			���th]iii�t���������h%&&Z�G�����^�Z>���j�*7U����8���;V}k��uS5�UWW��k���?�h�������~�*oD�Ep���~��N!�-�w�_M�:�E��s�����qx���UUU9<?00��]QQ��ZI3f�U{��9MZ���5��;�M�XKHHP�N�,���B7Vc���V7�x����[K������}]v�en�m�=���}���!
��v�����zs���8u_����h�����*..>����<=��SM:'$$��6����7i����ouk��%K�r��&��n�^{�,�
6��W_ucE'��������wc5������	��g�Y�<<<�d�]u�Un�m�=���!Zz�P����)�WK��������7l�0��555z��G�_PP���������������dio��MYYY�OLL��q�,m���n�A�W�vh��h����>�%xzz�������2e�.\��}����I�&)//���;���g�}VEEE�7o�<UVVZ��;7;;[���#;;�I�;��{���o�mi�������[�<�^�.�=��C����5��t}����sM�M�:�����[o��*5�|UTTh����������i��ez���u��IRJJ�222>k��Q��uuu����5i�$���GAAA2������������s�j��u��o�$���T#F���	t�=����V{TUUi��������[o�������C���8���c�z�j-X�@�d2�4i�$���{z��5|�pZ�1�L��s����{}������e6���c�5�����z���4s�L]~������5l�0������g�����W^y��������3��SOi���V}�_�bcc����6i�����{���,m�=�R��>������_���o�6�?���!�"4�����+DK5j����
}��W����k����������T\\��������2g��qJLL�SO=��Y��s�,X���*I��C�4}�t�s-Z�	&X�������>��1ct��AI'�o����x�
EDD��s�����������-���p}����***��e�,}�V���U�������8EDD���V�������z�QQQ�?�P~��$),,L���
SMM�8��������k���Y_�3|���
�>��}��M���'����g�{�-.K����;i��2}�=O��hG^�J*?��{��sB�76T��{�zF��b8��o����Gk���V������nw��c�j��E��?���s�����[o���oWyy������
6��n��u����?����������.]��j�����������*++KYYY��)��,..Vqqq�s���?7�}hO�������%If�Y��:������C�>�2n���~�A�<����������RSS���C7�|����?�Q\p�/^����^;w�TQQ��F��f�C{����������_Z�~����l�5����n��fM�8���n	S�N�m���_|Q��-Snnn�����5b����UW]%oo�s���.u��]���V�^��{�6��������
�����^���h�fG�e���������������T7VW*--���w���
		qcE�rx�p��y����=g���Mx�p��y����=g���^�~�nmm�233�����}>h������O?)##CEEE���QLL����$w�gSQQ���[������P�A������������;��D����W��mSAA����������Pu��U)))���o����s�����������B
Wrr�������@�1�)Z��M�C�-���4|�p
>���8,<<\W^y���h���%$$8u���(]r�%���K��/�y���n�@�e6�U)��y��2���.	�Y������J}�_��e���B%!]-cOn�Q����u������J�W��.|SX�y�G���hwNI]���kMQ������@��I#:���R��=�i�M�������hq���/1j�/���N���x�"���@�y���L�,��ew�Qh�d������Q^�������M�Y^�?l��#5&��w������%������9n�����T\[��}�k�t��}:n�u���.����c�A���w�#5&=���"{8;�@��Ma�>>Z��g|�_�o
KZ���=�)�r���s�?��fd�Wj}��%g�/1*���%gh_����8����}r����h����ZV���J]s���������e�.=���J��f��	��#��6���^��u.=���N��z��	��#��6���=7�U��\m�=�	>�����s�]��&yz(����g�yy*���4
�B@�`0tn��K���/���4
�=���\{^H�K��>�@�q]�p��wm�0���} ��6#%�_CC]s���@����,��=�)�v���s�����s�?������u�Z��?t
��!-z������g��(���E�������sZdog�{hs"���n��
��t���}����}�=��MJ	�����~��/��z)��S�8��`�|\z���.@ ��6+%�_����:�;u���������{8{�@����Wz���s��g�_��{��q�,����:VS��
�^,X�����_?����]Z�{hFF����a��	�����A��I���UC���is��������ln�j���f�j�Um������q��dgg[��&L�����<xPS�Nuwh#��]�,��U6�{�*tWe��\z�BCC��^J��i�6�}{�ThRlGg�
8II�I�TT^�b�I����z���z+<�K���
	 
�=&O����Rw��6��Vh7��+m�w�����2
���
��s"���B�k��:�����78����#E��s��ce&�sLuf�����F{U�C���b���J���y�}������@�F7W������`�����j�c]���AG����Q�@?�c&�Yw�g�����5N�6�kSf�~�]�hh��ce&���X�2KTm�o�
�7����2e��=c�7V������c��v�b�j]����������������}�A���N8��h��_�����f�s�X�V�rL%M�@S��/Qaa�$i���V!>��{h��+m������\{��I�~z&����i���3�p"��fg���tS^��^k���h1_|���}�]I����.\(OOO7W������`/������w��9:Bk������6��sPC��wfE�Y��T�u��e�3;u_S�Y�2�uY����~#Gl��I����������z������+44��uUUUZ�v�222TVV���p%''���.����GT�������]�v���c���Thh�"##5`�%%%���-�h4���~R^^�


d2��n���O�>���K�������u����+�����(���O�����`h��555Z�~����UPP���zEEE)11QC�mV0�d2i��JKK��c�d4������`���)))I=z�h���
����<y�������n�m	�=�v�{������`�=c���B9U5
�+��uWz���$?O��M�Kv��n�;U��^�d�ipb��������5|�pK��'�����UWW�y��i������l�.  @��{�f��!??�7�/++���35�|���6X�g�}Vw�q��u���G�������km��Y���v�FGGk����������������i����o��7���n��E�0aB�{/_�\/�����]�����3�UJJ�n��&M�4I�;wnt�Sm��I�<��V�Zes<66V3f�8m�����i��Z�|����m�	����5m�4u������9��3g��w�QQQQ�s###u�e�i���=zt��W�:u�<(����3f��"�%��m^�����U6�b���blK�������������W���CM-�jG��u����y9��cU:RT��g�UF�Q�_~��L�b3�'I�5k�F������L?++K�/�`3�'I���;���:T�_|��={j���Z�~}��=�D ��'������M�69t�3>|X�\r����
�Z�����$eddh���z��G�t��9st����
�I��t���k��I��w<[[[����_}������o7�'I����;w����_:��7�|���d��7���=I*,,��e����O7:/;;[���#;;��������^{�5K��W_U@@�K�F�@pm^ve�*�������=I��t��;�F^��.(i��p��s����iK�f����o�����A��W�^������f�M�2E�t��Q]v�e����`P���5x�`u����Y�g���o�}�����8��������j��A����<<�c/yyy���K���q�/�Iv���!C���~h0���T
<X������>�s����)S����N���#%%E�VLL��4.\�P�g�vh���
]u�U�;wn��_tt�����4�]���L�\s����F�OOO��W_����V����g��2d�����f=F�TYY�?���2�����o�Yc��qsUhk���K+����!��z��yWl�.��;���\�U5=g��
�����k���X�I����v�Y�x����I'�G;w�T^^�6m����t�����{��Z����k�����[���+???=��:t������q�Feeei��]��������o��t���������+�`�eff���\�w������i�&���O���Z�d����,�***4n�8K��To������-Y�����Q���o�~�=��^������kt��AK����&N����7���cJKK����g����j��5z��y���W{����%SRR���������s�6n����<����:�����M�6M��;���'O��+,��� M�6M��������u�V���������m���?��2���Nw�q����kw��S������.����/��B�����k�6l����7+33SF�Q[�l�3�<�s�=������|�IK`5""���$p2/w4������#I�~��)�����x�wJW���[�5
��S\[�{v���~	��0���
�f�*��O?���?b���[���
%vt���������u��,;;[����/���j0��C��7O���Z�h�����t�M���PPP����+]t�E
����S��/��A�,��9rD_~�����Z�5
8PYYY���k����`�r�-����u��������$m��M_��.���k.�����W�;w��#=�T�'O����-���}��'>|���~~~���u����g��/����9yyy����G���>R@@@�9���~�a��i����N��,Yb	���t�R-^�������V�X�=z����o_�����5k��N�*���{=��>����KJJ�r�JK;99Y�����������������_�=��v��e�vw������K/Y��f�jp!��{h���l�Q'���Y�F�xk^�8��-K��J��W���{�f�-���^+������_����
�jT�H�y�����t�M6C{'�9s��|�M���y��{���l��~�i��i��q�����7����[�?�{�����{w���H�-Zd3��,�v����K-m���e���
��*  @C�u���]�j���6C{'���s�Y}���/��3���>}����B{'{����i�&�������?�\{�����P��������.H�0a����-����u���;��Cuuu��K/�T'NtsUh�<�]�\;���������/���Nv�g��kmQY���%��1���bbb4h� ����8�BKW_}�<<~��l������FDD�U`m��uN?�ds���������?^�G�n��y�����v���#nio�����+VX�h7e��B{�z���-���f}���
�TVZ��������/��l���3N����[n4�����Z�,��������j����������GkHh��1���v������8���O������wo��u�]'O��� d����mR��:�����<��9��r�J��_���;�`0��oth�����=�\K���@���6�~��WV�?��OM��O�>�������Y�`NLL�U{��e2�l����������3-������l!��6mg����$)%�9�=/�^��P/�|8Rc���\�w��58p��s;t�`�0`��---ux]qq��x�
�~��0`�:w����@��>������B��i���+++�����c���)>>��c���;Z�KJJl�;9h����&�k�<##��x\\�-�
6h��1-~#�������;��� SSS������U���rw@s��	�u��R�����������c51-���w�K�������8���������������2�z���4g��7��Nqq��;��C{R���g�� ��Z��=�'��F�<<�w�����m�O�>]��r���j�*�Z�J���=z�.��
6Lqqq�:�%�����~��'I'n@|�����������q���4;���A�2N=���0M8'�������^V��3h???��mLaa��?�|��5��C{����1����k��>�f��A��ht��c�f�q������n�����l-X�@���S||����5i�$�Z��f�����������w��a����"����6m���^����c��1�X\����c&�Yw�g��A=�����9�}=4���7-oi����x��e�EykPB���;��/�+9��n��;��bcc5|�p���K]�tQPP�����n�[�x��z����������g:[K�F�X�������#5c��X�Buuu
����h���Z�p�z����^zI#G�tz�M5}�t�FIRLL��{�97W��������z��h��N����<=4?5^�7�Qe}}�����}�A�K�����Lx
�s���G�x�4�����������z�jK;88X����n��f���-�}�]W�[M'+//w���`�������K[����;O_~��>��+Wj�������o��s���4z�h��_���>��u���!�C�)4������u�j����z���Q�:�{h�2�U����-�������COR����t��u���G�E�8<Hc;wh���-���=�*\v^l����B����{V����ovh����[��"""��G�u���&///���J�*++5b�����sg�v�m����$���Z�J�|��>��3�L'^�i6���C�������C]R�J��
�6+���f���A	-�������c���G��i����l����.9�C��B���5[�~���:��otxmzzzK��@BB�U���v���d0giWVV���Cn�%&&F����|���L
<�2f6����/��.����m��r����~��0�v��9�^��-����i0^Y_�������$�y�~�nI1��iw�K�A����o�<!!A����+--mR������{f�������JLLTff��7�m��Y�
rx��`��������W�Z������")..N����-}k��ucE��3t�}�5y���#��K�,Q�N�,��={6�6�m��f��q�W��K������x]�%S&����WiF�!�3��K���*:�W]:���1�o��]:�):�����s����i������?�QU���~�C����1c�X�{�4g�-^��I{���1c����[�s��u{pO:�����%�YXX��z�����}.�����;e/�\��6�l6k���^�`��$�_H���������jyA������O|���[&�����>��-�7�+::��yzz����O�&//OO=�T��			���o���MZ���[���d��\��I{����^���K{��
z��W�X�	555*--������X
�r��M:TmRqm���^���I���(]a�>�:��*���#_o
K	������z{4,%L�-
�s
6��yMM�}��F�����r(�w2ooo%%%Y���mSVV���5n�8K�l6��n����Zo4�~�z��k	���z������L���6i�={�h��I���k0��;���g�UQQ�����7O���]�0p�@�s���e0�>����T?�.|W@��n��=IJ
�sa%�����tU'/����u�gg�j��.�Z��o]�������=tQj�B���Z����j��?�n��6���X������7�P�>}�m�6IRJJJ��5j�����:]|��z��������o����~k�8|�p��s��U���-���R�1Bw�y��l�"���u�UUUZ�v�|�A���i���M��%�;Vw�u��m2�4i�$��w��_|!���`��d����5{�l]t�EJNN���e2��=z��{�1u��E������6�o��={������C=d���?���_%�:�~e1����u��V���������^q�a[�l��6����#�{��.�
Z��o]���~�.��cUg�O�~��M{m��Q�t�W������-^�X�/V������b���_555�9���Sbb��z�)�����{�`�UU��wv��!M�>���E�i��	V}�������4f�<xP���o��7�xC:��s������"egg�����������H��-���Z�J�V�����������Z+//���wDEE�>��C}�������0EGG+,,L555:p��


�;v�����f}}@k�w'�Iiv�{���]\�o.�q���������2V�����'����a�����:{���a�Jh��z���5d��������
�{�n�����c�h��&�������zKAAAg\kjj�6l��a��5;~��v����7*33�U��$���[K�.���?/��Y���*++K�6m���[&�`mc����k�.�_�^[�l���������z��_�F�
m�N;��^n�I�C��hs�,����*��umQ�JE�������O%�**�G���9��E��()&P���A�F(:��M������?h��i


�;/55U�����}�]�����Y���g�=��s=z�bcc$��p���_LL�~��G}��G������iw��`P�~�������_<��[���S��~��oS��]O;?::Z����G}�C��S����u�]���Ou��w*!!��{���������5k��k��������-0��f����Z��������������T7VW*--���oi>\!!!n�����N	kv��O�x]&�}�y�j��M�UR[gs�w!Z��[�~�G����
�{�6<�8����l����
�{�6<���������ZeffZ�%&&�����lVm�Y�������a��V�XUU�~��'edd���H>>>�������������l***��u�t��a�`0(44T=z�P��}��cGw����{�j��m*((PQQ������]�*%%E���M����@;w���}�t��qUTT(  @���JNNV��}h����Z������^����X��o���.~>z99V��m�w�T�,�]�m�sp%��p��=�����������5|�pw�����p]y���.���%�)���t�%���K.q��@[�����J+������X?Wc�Qa���H��3�k{Y�+�*��������/������d��
��9f2�uWz��j�\\��FpmNZ���^j���+i���������������5����2��.�@K"��6��l�.c��IRR����t���������qV���@����Z���o���
�{�46:B�nw��=y�4V��"-�����r���yHJ�sm12z>����}l�W���������wqeZ�=�);��z������x�������m0�O/����C.�
@Kh��llH������J��_H���������jyA��
�"��M�Y^e��W�I���(�."������`U�+�l��f���H���X[�qO�<�;��:�x�/����;sT[ovqe��������v�R�HpO�"}�4�W�v�7����#.�	���@��f'�������.��y.�q���������2V�Y����w�^j`��m�d�GkHh��1��{w������Eh6�{h3�����6�{^��+Na^�6��kj5%#W�f��+���&T��koE���� ��=��,�J2�K���������^J��;���R-<X���4������J�vrw'���w�H��*-����4�Z��n{N!!��W���VPP��.�!WD���s"�(�������:/4H�B\\�3ApmBzy��~_�z�����{��,Pq�&�{�����h����)'�U��V\�]���Re;��1�P\�����
��f��3[���`/O7T�)<�]�{���o��xP������-�%����;����L�"g�y��<=� 5^��D��������l��A��=�	��{��+?��f�����6l�R�����Os%���I���(�HK�waE��=�zf�Y;��l��S���3�k��������?t
�;���<em?Z�{h�V�TR[gs,N�N;���D���.���i{6��`��I]��cs���^w�g������p�=�z;�+��uU�S������=3��gS{yj~�xy6�w��T�!W�Q�������E���
������
�w��M�/$@��������B-/(v]AFp��N���^��[�����ZloGM����"B��?���V���"� ��V���{]����,.�����-��#<�;��:�x�/���=;sT[ovqeCp�ZYm�r��*��=;?�����>^��+N;�K��W����q����,�}��$����{�TZ�K�������@\'���s������h�=�j�v�{f�"U��g����l6���z(>ZCBm��%��3G�5��-
�M�����uU��;��IDAT-|vmm����-|�c�<z�W���<m�����/9�o%AC`��`�|\z���.@�rw@c���l�wU�K����q�9�������cu{Z���U���������kh�����k�.m��M���*++S@@�"""��wo���G����.��=�Z��f�2��q/N9.�����%�8���0�~N���f�a

R��W�>:tH�g���E�TXh�5����o�Y��_�����
�x����}����7����?��+T���-~NS=�#F��l���f��3[e�u.�
��l�j�����k��:2�1���2��	&��$�����RSS5k��FC{�d4�����_�~z���]T!�
n�@�����m{�:��-~~Hpo�?���<=� 5^�6�Qe}}����M�}@���k��@�G�#���R�!�����y�K!1RH��W
�v_�����zK��v����===������P���)33S&��2^SS�GyD���z���]]6Z)n�@��f'��<��ds��BB���g*1�O�&�cw����z��qVg�p��y����R�j�x�uhO:�>�ub|��O�/���j�c��������B{���z��WT\\����_�^���*--������sg�=�y��]������"��V+�Np���]r~�NW���3uSt���)���c{��i�raE�����=i��Rqv��g�X����}�	f�����
K;<<\�������d5���O����y�f���Z��f37����Z-{��8����((�g����A�'uQ�������z������zW�(;,m�#�oo�>G������s�pV���O���>�����]�^x������Wyy���C�Cp�RA�IGkjm��������Z�g����^��6l��4V���C.�
�(;,��P�.u�~������h���J8p�����Ck��������6�L���uj}h��N?p={��I���$�4�������9���w�~!z�Gg=��v@oQ^�.
�Qa�-NVc���W�����3R[)m]$���'��{�S�6mRff��������=zh���


mt]UU���]������)<<\���������KMU^^���t���K��See�BCC�())���n	F�Q?������TPP �����u��M}��Q�.]�}Fnn���[���\��fEEE�_�~����v���)jjj�~�zegg���@������Rbb��*OO�3��d2i��JKK��c�d4������`���)))I=z�h���L��o������EFF���������*
m�=�J��U6�;�xih�����U��;�\�H�Lz�����I]����r}w���P�u��	P?W�����w����K�=�K�����m����5|�oo^���Oj��������y�4w�\eff6X�{��W3f������XYY�f�������������(=������;�s��=z��w���_k�������;7::Z�'O��������F����WNNN��7�|So����u�-��	�{���z���v�Z����������n�I�&MR�����T�6m�#�<�U�V������3N[�=iii�1c��/_���r�s���4~�xM�6M;vtx�#G�h���z��wTTT�����H]v�e�8q�F�����%�
�VVV�����]VVZ�###�R�6w�b���� y{��_�E��j��}���w�<=��oK3�wJWu������u�gg�j��.�$������G��8
�F]~���2e����$UTTh��Y5j�U)++K�/�`3�'I���;���:T�_|��={j���Z�~}��=�D ��'������M�69t�3>|X�\r����
�Z�����$eddh���z��G�t��9st����
�I��t���k��I���wx���Z���������}��=��mqs��UBB����K�����o����y���6�'I���Z�l��~��F�egg�`0X}dgg;TSS5���k{��QII�����������Z���{��S�+_�NN=��b�23�u������y��d�3����e�3
-(�.:�������f�;V�|���/&&F�
R�^����i5��5�2e�$��������,a?������k������{��f�����~��5UUU5����WRR��A��[�n����������K/UFF���p'��c���~h�o+<<\���<x����}����?_S�LQ]]���GJJ������.\���g;�wEE����*��;�A�/::Z�������WVV�k��F���~����������
�I����z���!C�h���JHHh�c��n��&���/������{��}���7�����
��T��koE�_����{����y�}�N�~�������|��!���0<X��3������2V��W~D*�v�Y��O������/��$�|����s�����i�&���+??_��s����_];v��������\�����'���C������7*++K�v���_l��o��L&�i������W^�(33S�����{�6o��M�6i��}*..��%K���dYWQQ�q���l6�������7�|�%K�X��5J�|������G7����X�\s�<h��������y�f;vLiii��q�������R�Y�F<��"##O��j�����dJJ�>��C?~\;w����������Y�����i�����c�����Z�b���i��i��}:|���n����Y�����m����?Z������;����{��?u�TUWW[�����_|���R���K6l�������)���-[���g�������c�
=�����-�+V��{��{�b}}��O��E�Y�bcc5m���m���N���Ju���
�I��w�z����N�Wf�3�����9^^!��-�9���1�R@@7��k-�����rm(163K�wg����H~�
�uR���J���
�?/����k	�!������Pvv����=��C
�;t��y������@2������������ }��W����������/_�A�Yn�;r�����K]{��vk8p�����h�������[t��������W_}%I��m����k]~��
�\p�V_��:w��#F4z��&O����{]bHH�>��
>��|???]x�������3���_~q����<I������G)  �����o���a��}�vI'B�K�,���lY�t�/^li���C+V�P�=l�������}��5KS�N�t����zH�~�i��%%%Z�r������u�������\I���V�����=��c��k���]-""B�|��F�m�=��W^����q�����


Uyy�~�����{��(%)>>^_������������hu��+m��y�����Xd�p;�?U����Qh��
	��N����Om�x�jj
���+����h����i�������y��4b�n��5����_2r��Owyn��KU�J?���*\����p�T�?�=g7���n��;���3���o���^�,A��^z�fh�W�6m���g�[�|y���n�����~~~z�����{wK�j��E6�{��k�.-]���6Z�l�����4t�P�������.]j3�w���=�����|�r��=������[�o,�w��~X�6m����/I�����g���%i��������'L�`7�gKrr��s]�������[u�}�Y�����?owMXX�&M����
		qU�h<�]p��2����@yy�������7�Ty�?���j���X=z�MAA=������e��������|����
]�|�rr���U�������E@�b04c���������A������4q������������k��n���BO#""�*��n�:��q�9s��l6[��������[��GyD�����7r�H�����e���+V����n��)��~����[>7����������~�������;">>^f���#>>��g��[�n���/��������%  @��{����B{h��Z{7����]c6�����u�u��$��`�v���������y����#�5^p+uyT�&�iw��}������\�O�>
nI��w��V����N����]d����mR��:�����<����\����������2��������s�=��.((Puu�������?��OM��O�>�������Y�`NLL�U{��e2�LM:��������M�8QEEE������3�<���D������g'�{hU�f�v���_�^Q���:�!���s=3>�ED\dw|���e4�kt����1v�&�Yw�g�����U\e��������U{��g������u���z��7t���k������e0|<���Vk>�)>���,K�c��
n#t�����}c:v�h�.))�9���]``�����\[ll�������qqqJLL��7l��1c�����-��_��#�m�6I'n���;�r�J=zT555:v��������P@@�$�d2���_��Q�TQ��
8��Z�U5*���9�Xp��,�f���������i0x(��������x]�Qii����v��5�����^������NU���> ���������_CH�][Yy����FM�:U������;����W[�n��#G>;\_S����~<��N'00��m��>9hg4���a3����M�,{?~��9��O�j�Z�J\p��u�����[����rrr��5���%K��������X����f�����9r����������]|��z������?�{���=~��M�<�]_Z�{hU���������^�����N�|N{��O����O�������g�i�i���l��[?>Z�����e������emc
u���k��Y���>�}���1����k��>�����h4:���w���q����O�`0X�gggk��7n�����I�&i��U�������w�}V}��-�y�������d}���������/���[�N�-^�.8Yzy���8?{��I�o��������a����_��o���C��),l�:w���=[���#���\��lO��*)�e����|C�������R�o�
��z����N���s��n�A;v������������W/u��EAAA������owV-^�Xo��V��WVVf�

j�3��%n#l,l����k����1c�V�X����srrr�p�B-\�P�{��K/���#G:��3���oZG��K/����)))���[����[�.\�!C�8�L�1�����q�w�����f��������4gK\�$�l��c�m���=M�!����}��`0���.�Rj���������;=[_
L��'s�����������6����_/��g�i����vpp�^}�U�|��V!=[��������NV^^��s�)  ����K������w����K>|X+W�������?h��}
����i��������|�E�r��������&�������{?���S�B�Fp����^�@�������-�9V���$�`�P��Y���jUWi0^__����5x�G����C����������L�l���Nc���:�g����@���J��]{Z���{���`��|���=~�xK��@DD�U����.9�����������ZIRee�F����;w���n�M��v�$���CZ�j�>��}��g2�L�N\���C�������C]R�=����jw���I�O���������q�Z���:�V5�
Nj����2���I���4����=G����03�{��M��5���{t�;�(�P_�� �_P�������8�����-�w��A7�x��k����^����?���K�u&�����8K���R�rK-111?~�>��effj����1����_~�-u�����������������uuu��	m�=�;���'I��������|�J�;�Z�B�G���?|�#:����n��DiD����:�v�pF�/q�9������|��			���th]iii�t���������h%&&Z�G�����^�Z>���j�*7U����8���;V}k��uS5�����U��!�So����jvMh����H����T_o�c�TV�f�? 0�Y�t��S����;�{��*/���3��`0hvrWE��~LKj�t����;�G
hTd���o�����9h�N���8�&����TUU�����@�vEE��k%i��1V�9s�4i}kp��0w�\7Ub-!!A�:u���X�	���V������;�v�=�[��{h5����+�O�����l�{�^@@J��1��������9^__�i������s�!��Ks{u��GU�Xb������&�\��%�����7DJ��e��SEGG[>OOOWqq�i��������j�9!!!V������I����~�[��,Y��+W6iw���k���`io��A����+:���F����vxx��9�w��������WNN�Ck�?�4��N��j��	����]S]�/���������s��w�z����`�v���,�����;�����Nv�g��kmQ��c���������f&{f�B �,�$��Z�
�R�WT�VT��Z\[QP[Qi���P�TP��R�J�(.�`�	�$�@�������!�2�l��u��s����}G��\���3���J�o���_vF��O^�'��k���=���?WVV���kp}nn�����F������bcc��;v����{�?&&F�'O�;�N]w�uZ�n]�����h��
�>�%�l6=���.s3f���%K�t���4M�6M999�b+V����>����F_o���*+��5�#G�4]���)����������������n�WTTh��������b]w�u��������������#�
��&T�:�����}C�{f��$)�
�{�<L�������z�-gy���P�l��*���S��[Y���t\�Pi�4�u��
:y={����M����]��-��)S�u7+**�����!C�h����A�5���.����555��/~�9s���?��5k��_�}:t���h��u���B]r�%�����m��zo�_^^�o��F<��"""�h��&��&M��;���n\UU�i�����/������z{�����?h���:����%K������	�=�?��
������o�v�KKK������3g���q���������z�!��-[�h���Z�l����]beeeZ�r�F���k����M������m�Wk'H���
U�w�;��=?�pyy�%7I�~�

6)7���}Z�
����bAO��Z�J|�.��[�5��G+�5#5[o ���
�p���Y�Ki���p��	*�N��^;s�e���+����~Z7�l�2-[�LP�=TPP�}������n�����9s�4�����[�/Vy�������
�.]�T��r��\pp�V�Z��/�\�t����_������]��O�>���W~~�233
��Z��/����|���OM
��]��k����K�������UPP�����}c�����������/I����BCC��KUVVj��������o��I���k�u���?�Q�7o��\7����)S�h������Vpp�����w�^UTT�����c5o�<O��6��{h�����,Rl���>��=�#�-y��b�hP�s��7���V()�^UW���>~>���4�6�H�_��e8c>�R�$i��K���������I��So�����So>##C7n����]
�&M���K�6����X-_�\v���sMHH���u��������i�����i�����d��$y{{��w��s�='�f
�����w�6o������+��Q�����mHAA�v���
6h��m�E{w�q��/_��j!6�M+W���w�]/V]]�]�vi���JII1,���o~�O?�T~~��{E�B������?����m-*J2�ww��$y{ip���X�
�����k��twl�.����t7��)����z0#�B�8i�4��R��R�h���� /�����\7j��}h��t�����Z�f�Rpp������X�Bo���|||����'*--Ms��������o_��vY,�F_#,,L�~��>���;V6��t��b��a���s����k?������|P�������BCCu�M7��>�����W�zk���N}��G����}�k����������_����o���:�{i)~~~Z�p����{�x���-V�����W_�/��Ro������<�)���=��@�$''+11�n������7�m*,,�������q���@�0i�^��/�7?�W��G���<����e:�u�x�h�g���o(-�)����O+���f��i�5��r[����
�~>�b�@9����u�������������g������������^�����VWW+==�e.&&������)�TJ����K��HM(�B�R^^����^�������������4z�h����vz������w����C:v��,������C��g����b����G;v�Pnn����������`���O�
Rddd��������edd(//O���
PHH����4t�P��N�UUU���������|��Oll�F�)__��N������Qr�q��x��;�����DU��5[x��*(�����
���O+8hh�t�kI~6�'D��-i*����*���������&��4��"y�J��3�����q�4n���N��BBBt��W�v���.yM��G]p�����z������Q�Fi��Q��
�!kk'��Rne�a,����d�y_�^�������X,
���������Vjg������A������c���?<Z���`F@�C�Z]r�q�=�t������f�t:^^%&�,���0^V������t:[<w�!����b�CZ��JZ��!�P��V�dR�����>^���
����u:A�D��<n?��Zr�{$w�X,z.6\��M�kkuWr��jj=��>P��V�bR�o�3�SUU���l�X��
�$�O�����J�xz��UX�?���.v/�%D��b1����k����
h(�@�3���`�7�S\�bs8��ScY,
�����#
�Ng�v&����B���.Cz<��i�9��in���	
����jj����0�P�^QQ����w�|}���Z���C��j�5����W��G�t:=��;L��K�����_��+=���Q��V���\�&�3)�s�d�X��Y�8���i<7�s�?��%�&�E���)���0~��Fw'g����%-��=����2�y�E�;�IR�Y��#�-y������j���=su���%�&�}��0����!7�h^�a���e��U�����f�9���T��{
c�Y�g�X4p��
�2�;��JJ�OUU�M�
��8���^����:�o��<��vQ��VeV����7�ST�*�ik��=I��
����e����+*%�a9����e3#CuVp�a�)���,�VVy6)�
�p����4-���7P�W�l8o������-�5��>Pc�����R��_�`F��e����u����VVkFj�j�aQ"�N����/�TqM�a,�
��xY,m�[�������L�{����[=��{�����8����yEZ�?��mO�xU3:%�n{�4(��4f^������i��9
�1�9�5JJ�_��y���.����t7��)����z0#�m�p�&��p�����^6�Xmm�JJ�
c{�*��������V���������N���m�QaJ�WV;���3UT]�������=�����x�q��$����6����{�d�Q���M�������y0#���Y�8!R6�)��+����r:��h}����u�Kl�p��(�p�j�S@����n�{�Za��7�g����6{0#�����1���-����<��6P��Vq��Z��c	
�����d�z�%������
cNg���f������j��CC4�W�i��i�VR�����G�ZEJ�\�g�q��HhvN-�f�Sb��l�����#JNyPNg��3k���������c/�u���L��������=����2��.^6���6���V��8�0���$)0p��>c��[���W=��{��lZ�)o��0�RR�9{z8+��P��VaV�o������4C�������q�G���R��M���������PG�fE�6��#��>�-�\B@+�p�"���p/��o���(�p�b�V``�[�����Y���M��JJ��**�y4'w�#��.�d�����_n\x	t$����j��]Zn�����+,J6���ce���%7O��|58�e�lv�xee�����Y�����b�h~\?��x�OT����,U�:=��Y���������x���{��{{�[�����H
��i<?�;��\������������$���D�2{4'��(������{Y��@��{Ng���ScG�+���^=�Px������{Iyy�z0#�����L���uD���<��Y����L
�b��k5���4S55����Z�'I11���H4�:����**�z4'w�}D��4�9%������*�&x�{����r��x������d��Uv{��jV��'�,��n��:����������5��������e3������l�:��hy����N�i����
�����d���k���)~�s���������3r�>~>���4�6�H���z0#�3(��G����*��q	gP��p$�%������
�b��|E����`F�qy�`M���4�����^X�����G�<����$���9��
���W[���CL�N%��^��=��;��
3��X���J�TQu�����X,���/������Z;t.)&�{�}���������UW�0�9����$Y�>JL|Y�6OPuua�xUU���~�������~����Y�(!B�mISiMm�xVy���_��G�b��B�mCMM��n����=zTUUU���
��A�'��^n�A�y�/:�d����@��l�L��I��1��9�%���������.�x����������pf���gc�5cW�a�_G���M������:q��6o��M�6i��M��q�>��f��}���t������/����~[�����4n�8M�6MW\q�����Q��2+�Kt4T��d8��)//�[�jKz��T��NU���
�YY��%x��w���������/�{G�
�L;�QA��
��pf����*g�j�5�Yl����b��vZhg233������)S�����B�w��a=��#��i�v��-����skkk��s�i��9���8����B}��G����p���pSZS����?P��������;�9	n��-��zH'���p�a<9�A�5�����pfg�b�hnl���h_Ye�xY�Sw&g���������L�W�jOI�r+�X�QU����|�~���S=|{+&p����h�LtT���e�<zfUU�~���h����b����������TTT���,���z4?4�{��]%e�5�%��;�9�Nw����{V��'����&����^���@II�k���e�z{>�3d��iQB�����*�w�I-)���576���iY�{���&�8`����\9���)�������g�_�f
�3���*..v�u�N��R�����;��SS�L��Q�\�����*--M�}���}�]:����cR��
���VE���*+�����a�#�I��_�������n?Q�]{3�)&�1g�<C��[O�9h�G�1�b��=�x61S^S�o������&�=\q@��Pt� ��z��l�og���[C�����5z�h�3F�����ln=��7�������aaaZ�z��b��j�*..Nqqq�1c���������=xLRq��|��O6�w�(*J1�����������)��4ee��0�����t��/�pf�sGx��/����������!�����pfZ��������*�i^��=%�:X�_W���n>=����*22R6l��a���k���]�;�x�n����J�����FHHHK�7�p��������������|���)((H={���#���������q����t��q�l6���[#G�TB�{���������WVVV�����������nw�9��h�RL
����vTT�d8��&��n���0��*8�U'Nl5���<�1��-�>���Y,�����7�����z��5�;9K����V�@Gq����}�U����z�5����jB�$��4K�.]t�Ygy��?��O:v�X����s����>P���m��U/����{�=UTT�������N��3f�k���x���Xs���������<�5�#�<�[n��YE�_}��f���u���}||t�
7����Rdd����	�����T��%�;�-�o��Vo%&��6m�����oS]}BI��i���jm?���xia|?M��WN������<�G��xn����L�y�mE{?��-��G��ua���f�z4�d���JOOWNN��V����4n�87����\�|��RSSUTT����������������+99Y�v�����UVV���`u��]#F�Pll�_�%�������WNN�rssUUU��� ���_C�Qxxx������w�}���l9�N���C��
����������R6lPff�rssU[[�=z(&&Fg�}�l6�_���J;w��k�TRR"___9EDD(66VQQQ�������B��-������;�l���R(�k�jkk��?�A/���jkkO�>''GO=��/^�������}���;u��Wk��}
���{�n��6���;z��wN���TN�S�<��^x���UVVj��������o��k�m�9R��':���J��oC������VB�<���6�xa����y��<����gl�CD��_3���/���v����g�����R�5�-r���b}���.�qU�\�=Y�n���W7~��'5{�l���h���Z�`�������=�����zJ~~~.���"=��3Z�h�
�������}�YM�:��y����������m��E����kCCC5}�t�w�}
		i���������7��o��7�0��t�R�r�-
^{����7o����UVV��4h�n��M�6M�{7���7o��G}Tk��5����WO=��is5������zJ�W�Vq����.]����n��Y���g�F_����z��g�b�
���7��{������t�m�i���M�����?tiR5i��fJ����v���;��s�=W�h/  @���1cU�B���#�����z��F��{�n]t�E�
��v�����y{{��>��3����Tyy��������W�f�X��o_�1B��ww������n��~��s:�=�Q$w��H�g���Sy�A���������n�.Pd�t����Ku4�3f��������1��{R��[Y����UV�^�)Im�3���*�to���^��������f��aX�'I���z��t�e����������W#G����?oX�'I���������4*��?�X�����a������aO>�����77�w:t��.��]q�Z�vm�E{�������g���k�9/����9���=I���n��VM�6�Q��~T]]����OC����+M��$���@,Ptt�>���F]��5������O[�'I���������~��u����X,.�������:�s��B[t,��1����^{�5����x}��':q������i�����g��9�9s�����nmee��L�r��\uu����:;v�n�k��z��7����~�Aiii:|�����?�j��������~�������j��.s�^{�v�����lm��U������/4d���5555�2eJ�����H�������*���]B��SL���:������K��L������,��5������
1�{p��Z��f����pf�e��M9����8�NM�4Ik������Q�_������5c�I���Gu�E��Y,
0@�G�����5�|���[���������bcc5r�H�5J���wy��$�����/Tjj������;5f�}����b!!!JHH����

5��E�4c����H:��4h�F�����z��,Y����7����������`��z�~���6l�F�Q��^QQ����j�\����'''k��	:q��������1c�h������n����8��t����N���^�Z�&M����.]�(&&F�_��.]�����Hg���6f��9.�Q�Fi��M���+���������x�	�^��%����E�5x����w����n�������ovyv��U�<���/_����W_5������J=��#.sw�u�V�\������/�X_��F�U7WTT�'�|���t�{�#1+���w�����d�y���m|����j�Rb�����j��.����T[[��������^��g�o^����`F��xe�W��Y�*(������e����K�n��F���(''G�7oVrr��9�����e�k����;w���oVvv������O������w�6m���{�j��]��/~����TUU�i���l���+�x�b������X�w���-[�y�fedd���@o���bcc�����j���r���[o��5k���7�t������f��������VAA����j8���_����n�M[�l��������M�6)--M���Z�~�~����{�����h��=u���
�������<���h��M������[u�9����5k��?~��O�>]�}�Y��n�k��Y�����C��}�vm��UG���;4q����555�:u����cz��~X?�nq��a����UXX�]�vi�����e����URR�m���O�����QGq��	�����m6�"""������?_W\q��y�������T'N���={�r�J�v�m����W�����K�)JJJr�{��W����.�HS�N�����������T����3�<�27o�<�����1y�d�^���Wuu�f��}�J��_���\LL�^|�EY,�����z��74|�����o���{�1�������	����p/��o���(�p��v����o/%&���S$���CQQ���<����=�[s\�#XS�t��9���8�s��5<(����[��V%�E�v~J���74x�G��Q��CVK������������3g��w��M.TYY��.]*�d��n�A���������Ou�����;p�@�^�Z�F����w��a}��'���kLs9r��������sw8��o~�k��V�^{�>��SI��;����G���/��;v��}��w�����K<�T��O��}���AAA�����q�������y�����;O��������Q����H����>�@�_'7b�}��:��s��?H:Y����o��y��w�l���qTT�>��3EEE�:t�V�\�^xA?����
�f����>����'N���?�������������C���5|�p
>\���k�.��;�����S������{���:9x��n��f%''k���-�*����6d���.���p�=�Q{���Z����*�?��3����n�[o���g�X���b���z��Wl����^s?��c��3��#I�������*�kjj�t�R=��s����H
���Sa��9�
�w����{����X���W�2_6�8�\]��Q��Wx8�����'J�dP�Y���J�����ek�������H+r���ixLr�%�h��'��&�����[�
7�`X��s�<���x�
���JR]!�_��W���h��Y�<yr�����,�����?Y�|�r
0���i�����{��k�.���;uc���w�}��h�T:���}^�~���;�����s��u����W��9�N��=�eCE{?��Ci���Z�r���
����\�J��}�T]]]7���[L���t��H.c���������u@@�&O��_�������?����J+V�PY�O��|�����O�w�}�LM����;���<�q��}��_�~.�S�!������z�i�������\P7�����V7r��m���nl��u�����I�:uj�9��#��Y�=���^uu����c;�{����}
	9�4����JK3=�����Z�����*Y��zh�~�w���X,z���N�.,,L�F�r�����m��v��&L�������o���DO�k��.k�}�������^z���j7�t����b�=���
6!����^�������kN��g��t��1cF���~��������t��?�����d���z�)������3<��z�������#G�Tjj��,Y��������+����V����RRR4d���=�����<�:��{m���S^
9um���M�~��'.��.����\z��.��?�����;V����:g���.U��w�Vzzz����@G�R\n8�eSo_����RL�G���,��_�����~55���t�jj*<�Y�D�inl�i���z�P�i��!C����f&11�e��_�Z6�����v�K1Uvvv�rl��w����Qnnn��#I��������o��,K��
�l6
<�n�����
��	�������m��2d�BCC�������&,,�e��������I�t&��������Z�fM��^?�����_~������B���k�<���!��
s�������Q{7m��23f���#G�����uc___�1��9�;�e�c������=��F����U������@G�d�q/��o�%����p��+X~~}��[{���C		�e��}qq���<����������+�4���J+1.�d����^��[7�qS^���������WPP��_]��z�F����{+00P������>�����c�>�):��{���{��Y��;EFF���7�g��.�'N��y�]``������[��}�����Z/��������u����xG������p��^p��h�{���;w��������8�E�^�RVQQ��^z���***4�|���S��=�!-�F��2��g����u��{�z���h�#�MJ�{f������b���k�9����|rrV���{0#����������:ugr��jj=��/=z�h������mL!QII�~�a������o�?��m��]�Viii��,((ht~M���=�i��g��B��	t�}�^�PRR"��jX�����������gx����]�k�����c���u�]z��������{���v{���]���k�m��n�A���u����z���vP���<��s�Z����O��7�0]_PP��'�<L'L��	&���{���������G�����J����E�:u���s�9m���H�j��m�-��P�^��������:�����5�<���]Ti���8m�����	��6)�L-)��=9�
��_-��!���9���^xAg|���m��jM-�k��~��Ng�����~�:�M�<YO?�t�����Z�x�&O����HEFFj��iZ�v�a���Q��9��#oo�F������1c\��l�����~^��\�w�yZ�`����9�NUWW��[n���������������c��i���Z�b���K/�To������=�2or�aaa���p������(77�Yg����e|j�f����H�������+��{55e*)�k�p���bSB�_�i��TQy�^���D;�������fk�_���!�=�Y&zo<��C��g�&�#�^M�3������':R��7������_���~.���*��7�]w�v���2��o_�7N���
��n����Ks�e��i���-�_QQ�������k�n�
�=������K��SO���>SMMM�5YYYZ�d��,Y���D������^��<��^�z�����m�5�5k����Mi�(�k��O�������Wr��N3�7ovi/z�����w���E�T���.�S��6��{N��t���������s��;�=5���G����={��QXX��\�>���48w�|��p��"���TaaU�Xq��$���Z"�u��=�|�����k�4}���w)9y�"#gy>�f�>�Gk���������V��F}|�n3@G���{:;�{:�{:�y:�{:�{:�{��;^+�.V�U��V;��_�G�z��m��E�V�Z�u�����^}�U�x��
�CH��_~������������2�����y��=�����'�|�C����?��u����_�4Z�QRR�������/z��Z4��$**J>>>�����

j�5N]�������~��Q]t�6o��'�xB/���a�������|P�'O>��S�X�I;U��8F_����zVc�1�������������kl��I�nv.h�6m���)����v�|���Wu���j��/�oe�e��������T����,�<o������a,�����_��#=�U�\e�j{`oX��SXS��;��`��Z!7�-�,�=��=�
�=�	�<�
�=�
�=�
���#;;��Sh3�i���</�cg�������/^�o��Q{���Z"�z�v��2n���t�"///UWWK:����K.����{���)S4e�I����v�Z��_���U�TUu��������3u�9������Hn��f�)66VIIIusM�Fyy����"M�
Wy��,Z�HQQQ�7o^�E{��o����nEFF���{�kO��������|}}]�eee�=�L�j�9Fgu�{�#�o3�z����p^�l����5}����WUy��������R�f�|vg������4�gx����]<��F���C���9��o������Y836l��s�n�t���7zorrrK�TOtt��x���9��,�"""��eee:x�`����n�I�������5z��������/��*y��#F���i�k:O-$���[�sB��U�mLUU�&N��������C�NVj?����i����UYY��j��U���-��"�d����S��C�^��q?o��X�V�u�3�k�Y�9�h�#��S��q�^x���Q���p����;���*/����.�Q��R~~oHj��M�)��BWV�0���'H�6����a�c<t�Y9g��EJ�����l��WXX��:���d�i���FBCCS7>z���l����m��q�\�k��m�L~�+V��}��7��M����~�2nja�������2�Z;��>}�������1c��G)44�e]���5a�M�0A�V��
7�P�n��y�������Z��v��el�E�tN�w�5������T���s��;�=5��w������I{����k���n<f�
4����}())��M���c��Q```+f�#;RY�������'�� �z�������a�|<0�u�>�~�Dg������K����f;�������l����;�:�vH[�����X�Vp�V����w�~�t4������������3���������������y����v
mJD@��iOI�}^��_���>���tMi������I��>kKKK�W�.��r�����_z�%-[��I�hm�_~�^{�����t�M7�bF'EGG�W�^uE���k��<���/���_������JOOw)5���\����^�i�
(�kC��[��_�n��gO}�������6������p�BM�:�n�����I�����b�S�JJJ����{������e��TS����KJJ��K��c4���)z����={6�v�]AAA���S`` ����M�Mc�{uS�w�oG���tV���s���3fu�g^P�/T]=S{�>o?v�#��9V�{_����g�`]�y����$�V���������������=����������g������������^����
w4c�^����UZS��k����b�_��}��I:Y�TPPp������h��9M:'((����3�������U[[+Iz��7u�M7���.k�uZ�5�\���h���G��q�F�����>}z��UYY����^c���x^``�n��&���g�yFo���i�>��S.�.���5%h9��/�����K.����w�-���-��������������[w�?�49��6x���{S����i�9���(R����|����hO����
��V_D�-���_�;���y��]��Pqq�3j�>~>�?��i��yEZ�?��h?����5Q�V?�^����+zM���������=���?WVV���kp}nn����*4�ooo�:�;vh��������'���N����:�[��Q�KJJ�a��F��l6��~�i��3fh��%M�NZZ��M�V�&B�V�X�g�}V��������UV��kLG�i�633S���#33�I��EO>����~z.[�L������+���w�u�;���.
������k���M�0����V����J�����������������t��Q���>>>0���ps�:u}\\\����	��"��p/�n������y�=NV+
���b�*!����6����kg�}��nz���4�{�n�n�s�Am+l_�t�|zhB�$����0�f���I�����9h}7�|��x��E�2e����\��������k��!��c�$i��AM:����jjj��_�Bs����~�5k���/���8t�P��,p�/(,,�%�\��o�]��m���tY_^^�o��F<��"""�h��&��&M��;���n\UU�i�����/������������?���������W\\��,Y����zk�=�?��
������o������4�{���9s���w����t�����?�8���~k���o�=�9���z��G\�n��v�{������|vv��O��{���e��o������.�)���������'\������k�������B��{����R>>>�:#55�e%//��Fqqq������))�/�o�YfEn���(�:�5\�g�q��HpKN���w�'����&����/-���iO(~�<Y,�V�����
�����j�4=9KkFT����`��O]v����R{JRO��Dt� ��z1�����.�LW\q�>�����e��i��e0`�z��������O���uk&O������3��g�}��Z�xq]���j����k�.]�[n��e.88X�V����_�H:Y�������_W��]��O���+??_�����m����_V~~�K���k�j������RDD��v����j(''��s����z�������K��t����Pu��E������rss���4i�����f��;=���z��7����n2����hTW�Y�fi�������%�l
�p�B���+�����u�����+##���#F�o�[��D���^QQQQo��x��������������P������u��F�qj���a�L������}Nuu�6m����:�=����hoi��q$�����j��a�p�9���+:�a�������C+=�Q��Z�Z�����5Y��zh��z�h�����uq��ty������M���7\��y�.�qE{��[o��1c����������{�n���I�&i���M>'66V��/��~��q�F�{���byyy��s�6m�����6Y�'��7y��w��s������Luu�������7k����
&��{�z{RPP�]�vi��
��m�a��w�����7��:�����{OS�Lq�w:��������
��~��_����j��kx�{mD�n���<x�I�8��^���~���J���5k}��k'L�`���s���;��F���[�����ccc���:�=���..�Y��Y�^ii�jk�
ct�k��}oS�����w��VQ�.f�|�~�k�K�����Cy�@SDD�W�o�ua�hx����!_���_����Ehx���.������0��2�;t��E_��f�����`�u			Z�b��~�m�����Y'NTZZ���������o������X,��FXX����[}��;v�l6��Z���a��������y��(�����k��}z����_���

�M7��>�@T�^������;��G���oWtt�i�����_���Z�~�����5��UG������Z�z���k��b���������o}��G��'�'����0:t�n��k�i���������������=[O>�d�u�V���W_]7���TFF�i�����W111uK���������#Fh���u��������[O{/7�|�K��C=����t}G�����������qRR�(��,
�����n<n�8�bF:�e9��p��z�6���?XV����}�����[,^�����j�mR<����:�M������o$) ��F�������t��d��#��1�E�5P��@G�s@g�s@g�s@g�3@g�s@g�s@g�s��r�kv�������2�!�^�N���U�qV�f�����IEVh_�������+55U������QXX�F��f�����������C�t��1Y,+**JC�U��=[;�F��g�v�����\������K�������
����&_377W)))���P^^�JKK������i���
t��t999����������r����w��;vl��{�V�����+t;v����7����?_S�Li�_������h���?~����u���kgffj�������<c����y����^�`��$M�:U��{o�x��������g�����T���;uc���[n���s:�=��%�����IRQq��|``l���`��;X�_��������/-��]�WB����]sc����D��*���j��+9S��������@[g�X�c��tf������i��q7n\k��h!!!���+[;�f���nT�������.��]p�n�ng��OM�8��������6���nr'%%����Vmmm��������'�������s�1\����?���.s>��RRRL�X�b�KQ��f��9s�K�������iiiz��d�����P7�|�*+z�������9��h��
����{����:��SP��D?j?r���9��3j>��M�"�mRl�ZR��{r<�:+
��������_�d�.��}������v�?~\��_4j�(<x�%��?�Y6�����S���Y��������e��������Y�f�������;���Q-g}||4w�\��E�������nr���:����e���9�����z���t�{���u:�RRn3+�s:kUTd\tO�����OQ�������6-�l��8�DT�i��������%�N�����+V��s���}������]r�%����������u��qeddvy�9s�i�bz{{k���:������'�dA��)St�=�(**Jeee��o����\��3F���k�=�x��Z�~�^}������{O��������=z(++K��s�g�Z�t�R����Q�t�{���,�Ti�q��D�����,���:����bQ����T�����z���J�L�OcF$//G+dxfn�������x�a|�����~>��	�����P}��W���������s�Nm��I{���W������s���^h�Y�
���kQ��~�Aiii�
�.��}��g��7~�����p�s:�������[������>m��:�=�%��[$
������Y��rObp���P���e����e)u��,���X,��O�>����5�������sOh(�k�����/��R����.��BY�
�o
�����s�N=��#�X,�>k�����s�{�1����������%K�����K�.�����V�����j���:���M�����7������t���7��c��M�I��_�l��������(�ln�
�������i���Ou �Mf�|�|��J|��;[
K5/��Gs@����	���j�u�]����NEEE��e�222TPP���r�[�n2d����O[�����?����3g�6n����$?~\6�M�{���#4x�`����q�4n�88p@�}�����U^^.������w�y


j�9��hO�L
��n�:�9�������l�����������a

r��O�pn�]D��_2��_�:��]��EW��3@g@�^;�p8���Z�����;�<�w�y-z�$���{��\G�'���{	���{N�SE���{
�Z��b���?��(Yee���Ng�v&��1�W�����!���6�XN���9%����/GTo�'���������SQe3��WQqHUU��1
�<������/�j�1����W��G�t:=�����Z�J|�B�l������?5[�����>P��J6��'I	v?����$�=v{|�sB�8���y�4��������r�0?���4���"-������P��2+���mS���a��(�p���������N/,l�z���i|���t��f�|��������?g���f����=��Y�^��_��0VdR��p$�-/4��bQ��g0�0�tV))�>UUx6�f���v�X�S�+9K��5�
�{p��
����������+P��j�3����(%�9�Ngv�|�V-J�P���G���J=�{��'�]��m*kk�VRa3+���8�����1�����b�������c������\Bn�����������Cy��{p���
U�t,K4)�3��'IG�[�����{�BCm���y�8���5���]5�W�i���������#�pn�\\f8�c�(:��0fV���*�nn�
Mg�X7�)����j�L�OUU���y���k���a����;�3UVS�����P��I.2.��
����b+*N1�w8���������e�wL��8�����t��B7��M�"�c1�;���\O���pV�H(����u�K�}I���������(n�S��������%����84+*�4���q}|��s	�C�pn�t:�RbV��g8_UU����1
�������z���4�7�/*(�����������[�i�����]V����QP��8TQ�����Y�=�n{�{m���'ks:k��<C���=����X,��O�}�
�����;%KU�Ng����=�Er�q�=���{�������-y�}l6
N\ �-�0^QqX�)3�t�z8�3���KE��`���T/�;�����Q��0+�����.�^�1��� G�,��r��F)n�3�������Z��������4/}9����+�`Fh�(��[$���u����b��=�#�-9�e��^���L�{3^T~�Ff�|D����@��S���Y����lRh�(��[�u�3+���.Ri�>��������2bc���>�$Z��������Gsj/�E��G(��f?ZY��S�U�tz83�G���J�k����0fV�WT���zt�k�l6?
N|Y6�q�����JI����gv���|�������W�W��z0#�W���RK�e��,�aR�W�d8��$?�p7e���_���l���V�2_�`F�wY�`���4�l�Am+,�`Fh�(�@�%�������c+*J6�w��e�X��ZV�^W�O�������?��}����oVT��t��vJw%g����t��Q��f3+�K���jR�W\�b8�p$�-/xFL�����s*9�UT�z4����Z�(!B6����+����r:��L���p�fV�o�����\%�{cG����g�l�JL|Y6��0^YyL������~��E����p����Zq(���=�p�R�t*���0�`�3�/.�mZ�E���)  B���3��lP���<�Q�]�U{���O?��&�h��b�����[;-���@��YV���Z�X�I����d�y�-@��J
����
�Y,3�gf.T��Q���|gv����k[a�2�*���j��39S�G����{��Q8�Neddh������


TVV���@u��Eqqq6l����_+������g�v���C����P�������
��������
wO�p��\l�q�*).��p/�p�n$������
b�U��*,��A�������1�����s;v/�%D�����t:��w����=9z~`�V����
�����o��?������{yy��+��=���K/��Ig>|X����>��s�[�N����k���5q�D=��>|x��A��-�%���p>*�W&]��:�9	n���j�Ub�K��
2�WU�))i�jk�=������a��e�����K���N��R*+;�_�7�N'33S�����[ni����-X�@�?��������IRuu�>��#]v�e����TPP��s���j���G��{�V�Z�`��$���i���5j�z�!UVV6��>:��Y�
������jk+U\�f�p�c�����A��;��NlV�����z������}����"}~�������������z83��8~\��.����**~���J��K=zJ11R�n��'�N�f��o������|||t��	edd����e�{�����}������K�����oU[[[o���[aaa���������������xmm�������4�������,�������p/��p��d��N�w�p8��ZW���o��L�YY����u�K��,�^����������Z�����Z��h��,��I��+��.����I'�99'�+�=�>;�5�����vM�8Q,��;TRR�}��i�����q�v�����"�Z�Jg�}���m��i��M:�W�^z������_���P�����y�v������Z�J�v��j�*=�����W�<
�p��WV�PE�a���^QQ��������(�����������SRTy�A�%�L�|��pP��Q[
K���C�	h����/�H��T:����>$��T�����7�5k��;��+W��{����C���[o����&L��o��VS�Nu�-[�L)))�=+11Q+W����������.�����oooM�0A�6m�UW]�{������vw	O�pg,����d�q��p/0p��V�nfh��V%&�$/�`�xUU���g������-:7���G���_�>����<��?~�s��=�������9~�=y��hX�g�j�j������t�����������~������u�s������S���usUUUz��7�+Z�{8c�&�{����������$�y�#�my��������y��'�io�_<�Q�=�Kg����M�Rne�)F<��q��I�%��^i���Q�����j���.s���
�����e�6��+00P�����g�}��k��N_�	�H2)�K���b���w:kTT��p�{W���_�;����0���D!]��{��<����Y,z%>Bo�����z�����?5[o
 �����*/�>�D��p�u+*N^���%??�^����y�������#�����(�7N���
�+//�7�|���T)$$Dqqq:����9�Lqq�����k�.?~\eee
V���5b�������[BII����{���(77WUUU


R���5d���hg*;;[�}������t:��G
6L��7|�fSUVVj��
���Tnn�jkk��G���������f;�kWUUi���JJJ����URR"___9EDD(66VQQQ������{9v�X��s��������[���{8c)&�{�v�_|���Sm��� G���B�5`�N���'���S������gvf��|����������+���suO���h��]��N{�*-���F�����~;�n�:�7�n���Oj����������`�������{��GO=���N)�,**�3�<�E�������=z��g����S�gZZ��~�m��?���-[T]]m�644T��O�}�����������z�o����x�
�}K�.�-�����W�^�y����o�Qee���A���n��i���w��y���7��G���k
�}���SO=u�\�$%%��������U\\l��K�.����4k�,������>|X�<��V�X�����v��]]t�n��6�?�I���������t��"���w���-r��i}��_Em��J�
c�v����d�y������n�
m���������m����JJ�_�����hk.��;������8�m'Z���@{��%����g�I?y�)))�/�K��1��hO�JKK��/���.SY�Oo��w�^�9R�?��a��$������o�<��|>��c
8P�g���
,��N�=���<x�6o���3����C���t�Wh���
�IRjj�f����{�I����K:��sL��$i������[5m�4���6���������4t�P�\���hO�


�`�EGG��O>i����Y���8-\���E{���t�����~���eff�b��|dff6*'O��q��x���-rNNN���[�n-r���=����rU;�c�M,���������F���V|�<�xa�����3j����4���{�S�3%K��5�
h�vl��9?x��v��tj��IZ�fM�\XX�F����x�l6�������3$IG��E]TW�g�X4`��=Z�w������[o�6�S;�I����bcc5r�H�5J������Z�����/�P�����q7��s��������^,$$D			=z�bbb���}��,Z�H3f�PM�������k��A=z������_�d������k��������������j��a1bD��zEEE�����r�������	&�������j��19r������9j�RSS�������4y��9k���.����9�C��Hr�q�=�E�~����$�y�=�my�m���BEDL7����w���1��5�V�%D(�f�����J=�{��N�*W�38~\:|�3g:$���Y���e����K�n��F���(''G�7oVrr��9�����e�k����;w���oVvv������O������w�6m���{�j��]��/~����TUU�i���l���+�x�b������X�w���-[�y�fedd���@o���K�Rii�&O�l�����zKk����o��2�e�i��5�����w���]}��:p�@���j�m���-[�����JJJ��M�������B�_�^������{��~~�g���b�A�����W^^�RRR�i�&���h���:��s\���5K�����������g����v�f�����:tH��o���[u�����C'N�[[SS��S�jO3~�aUTT���
��?�X�����k�6n��-[�(==]%%%��m����?i������E7n����]:0���T��}�~VMM��-[�2w�W����Wk'��)���p>.�O�VK�y�������A�^g2���t��Vl2���>�1�U��w��-!*�O������l����� ���������V*)n��S�_;���
��3h��m��Rff�$i��y�9sf�x�n��p�B���i����Nv�������*���O?�T��~������5j���.x��'�|�k���4��#Gj������h0w������7���ku�����O?�$���C�����_�����c�����z���K.����N5}�t����n���_7n��z???�w�y:�����?�I����uNNN�$i������Po��#��_��s��?� �d��o�YW�g��w�q)�����g�}���(��C����+��/����t�����3��G�[��	}���u���8}��w���7�������������v��e�{k�����\KRmm���������?�\���s) �������O�H.�/VFFF������:��}(��1+�����UV�_55����p�s�Z���0_7]����z���B%%���#�����
6�u�]�u~�V�7�?�~@#�h��hQ%����Z;�IN>��&�Fr���
�����~��g��o����ZI�+���_�jX�������5���h���
�����	��,�[�|��'NH��.]jX��.�v��;��S7�X,z��wM��N���>������O����a����9w�\��^�z�i��������]�7T��s=��6o���+WJ����+--����$���O���u�[n���h�H\\\��z���~�_����]7x�`��3�Qk����{�������s�=
o���>m������4-�Kt��UTl�K���An����o/%$�(�~wFI*,������lR�47&\�}
ce�N������Zg���X,z���N�.,,L�F�r�����m��v��&L��g��o���DO�k��.k�}�������^z����M7�������y�>�����O���K/UHHH�x��m�k?��3��v3f�hT������?;�N}����������������o���H9�N����H���#F��O<�	&���KKK5q�D��EDD4��4Z�{h��U*��1���t+*2.��//�@�����[��y�i���7t��<�Q�z��8!B>�b��%�zrO�����
2�^�43���.�_�����l��g��]�������cc��S_NN�rss[�I����]�����e�Xt���7j��f������������0\���������6)�!C�(44�n�~��zk���\���������tN{�m�6]w�u����g�}��k;�NM�2E;v�������[o�%������2(�@��u�������Y��������>
��B��mOI}D��Y��y;�Dt�i|�������%��9rd��v���e<b��3�[XX��}z���u���j������e�X�}<���.{�;��s����C��wo��g�����Sddd��}Cz���2>q������*..������������������o��Q�_~y�wD��k�����_UU��=�u�����w)j����/�K-Y��m���9S����������i���n;-��=4�Y�^��������;�N
�`�b�)!a�||��kj���|�jj��
�-����.�d��;[�e��~�o=z�h������-+3o����=���


���������}�>����F�YPP������E{R������x��26�|������DV��� �����7�]#//�����g����]��c�����������o++�����///���C\p��~�i���i���uq������k��
�>k���z��]��|�I�}����6<��=4Y�I�^���p�������Xs�)���|}{(!�EI�xQQ������I5��b��A�����0^X]��)Y��uz83����_��m��c�t�9���^PE���zs�6�����5Us?�Ng���������c��o���z���e���033S�/�������HM�6Mk��5���q8Z�|�����������9�Y�]�x�{�1������^�$����P��H1)��7)�3��'�q'u�z����_����a<'�M�t�^���pfg����^�������� ���T/�;�?D�y<7tB�vi�oZ��/�����y���E{���������u�]��;w�����W���S||����e�����/����U��-����[<���"��������D7�����q]z��z�����g���������,-Y�DK�,Qbb�������K/u{��d�Z��K/��O?���|��wJOOWLLL���b��z]��L������#]x�{h����+�4��u�3+����+o�`������=:Q�Ey���Sw�QG��{8�3sN�~�y���p|9����8tAW��3@�c�J���;�wo���k��E�V�Z�u�����^}�U�x��.EzF��������~����#��S@@���k��z��wZ����:K�|��:��?�\�����_����zk���4~�x��/�<��y��h�����cG��w�}�����>�HS�LQm�O-���Z�������}�pM�ZRnK0+�+6.���~�b�)>�����*UV�����kg�}5�=�l~��a�=�K�����z1��{S��v�@����|r��D�H;�{��h���&��?��2^�x�n���F����k������������9���t�"///UWWK����t�%�x����{k��)�2e�$����Z�v����i��U����t�����3u�9������Hn-%**��p����+�������I�����b�
�l6w�	k�8ERq����fU_?��Y�� 
�p
_��JL�?���R\�����=�T3�,-����?4�VV���l�:����n�����9�wo�k7���3�a���?w��M�_}��&'����O)���u�G�u'�������qYY�<�*�������n�{�����t�=�.�t:���/�J^-����o���������VEEE������?�P>>���E�@��$��p/��/�A���c��0~�:��HH�Y0�w�������Wy.�f
�����~��u�Ezu��@�2lx�:g���#u���nt7����&�Y��%3�&��zhh�bbb��G���-[���7n��x������O"""�b�
��o�����q���,�q�^��o��m���+UZZZ77j�(}������wk��<
��$�
�)6��'Iv
�`"2b��v=�4�k�UR���5�e��uGxw�����D�3<,"B:����E�H�"N����t���������]����^�2�yaTc\~��.��^z�I���S�a��������h���c���b6�w��Am���en��!������������us��������� ��	��p�V�t*��p/��p���p��7T�>��L��,���"_�P�xMM�v&������m��Qal����)����U��
����K��_w&�������V��?�.,99Y������9s�4���� �n~���k�������k��o���?��I�hm�\s��V0�q�F�������I���*,,�����b6���������n��
<��=������^�R��5k��[�n-�+<��=4���
����7��WhR�����-/tL>>�����Xl����4�Nk�/bZ�����	�
�����R�py7)�C�����R��u�u}}O^�����E�8��s��\YY��{����������U��s����������C{��m����M�<�n�t:u�u�i��u��_RR�
64���`�����O����1CK�,i�u���4m�4������X�B�>�����}������7�9r�����LY,�����&�������}��&�����Z?���/_�2���6��������Kt�����~����/�t)lE�G�-�����UR\��/<�:�9	�JX�.�4`�L���C+u����y�jnl�i|���8������M�p��:�������o��e�h�"M�2EYYY.�EEEz���5d����C�4h��&�u�e������F���/4g�}���Z�f�������C����`�
0�n\XX�K.�D��~��m�V�����\�|��x�EDDh��EM��%L�4Iw�yg����J��M��_��?�X%%%��TUU��~����u���+..NK�,QUUU��G�������k���z�������QZZ����^������;����w�|�w��
7����(=��cZ�~�����>|X���4|�p���.���:Kw�u��9����������Q7g������*--���dc>�����	@��j��~��E�����XU�	���7�C�+��*(������w�~B�����x6�3t]hW}�_�����]�����@�.�@����t�����H{���:�1�������\v�e���+������-[�L��-����Gh��}����[3y�d���h��9�>�����������<���g�]�t�n������`�Z�J�_~�8 �d������_]]�vU�>}������|eff����_~Y���z��w����]��k����K�������UPP�����}c�����������/I����BCC��KUVVj��������o��I���k�u��o�>��;Ws����bQ�>}���@������#:z����a����O?��j�g����JNvm�QSS����������<��hyt�@�%��%�����SL�E��b�*!~�|}{�kk���t�jjJ=����������Z��L�RYM���<��O����+����
2�����+N��h�]z���4f��z���q�v���R86i�$-]�������j������g�kBB�6n��s�=�^,//O;w���M�����&��$���[�����{�9��������Z{�������}��z�?���{��
)((��]��a�m����h��;������~C�t:u�����S6l���;
���V����>�_�^]�vm�L�VQ��FK)6n�oV�W�l8�����0�����/�b1n^R��]������pfg&����	��X��K����g����W����7|��'\�=�M�}}O�qr�����E�F�p�.]�������Y�l�.!!A+V���o�-�3:k���JKK���s5~�x���Wv�]��o	���~�>�@c����f3]k�X4l�0=��s�7o���R~�a���O>�����w������������������W�5w�y�>��#�~�����>�5}}}��_�Z�������7yy�.��{�1���k�8q������O�>�9s������K/5�@���^^�
�m������X7NJJRB]�:���B������7NAAA�����Xe��M2��=d��u��,IJ~@G���7����>��N��yOV�k���Y�����
���5�kr�x�y����HM���s	�������������3���������������y��5����JOOw����i3E/n�tJUURM�d�I��R�����������Wjj����������0�=Z���������|}��w:t���;&�����`EEEi������gk��({����;������|yyy)88X�����A���k���*%%E���Sii����8
:T�����7��������o�>������L���


R���5|��F��u�����+4ZBJq�i,���
�qf�������:v�����'4Dv�@gvf����������B�������W?_�8�!Y,�vWC�����q��i��q��J������+�l�4�-::�Q]���G����t�������O������@;gm��>$�����RO_�z���%*-�0�C����bQ�����g��pmm�v&����bgvf,�������$���V�S�TUK�t����=4�Y���@�n{�������v
�p��������,�b�����=KNg�(v����W�#L8�ZX����hNh
��(f�����{EE���^^���s[^�����*:����#�t��?=�Q������G���d�WyE��A�N���V{J�
c��������X,n�
�W��[���x�xZ�S**J�`F��@d/��%�0��toj�r+�<���{8���rU;�c�v?���b��=�#�]i���X,7W~~}
������t����G�:�����"���f����})��u��c@�A�N+���p��jQ������
�����p������/�b�1���e)u��l'�na~>���4�.�H�d�`F8���RL
����j�7_R�[Ng��
��nAA�������*'g�3j�����������i��f���p�e�q/��o8_T�l8o��)0`���~��&��y�i<-�%y0��y<*L�M�}U;�;S�t����Y��(�@��N�R��
c�M,�s��b��-7�G�E���,����Y�����������_�U�"h3��my��}@N�����1(�@�TT�Du�a����D���������d���������h�)v���b�M���-�[��<���=4(���4f�q���J�%��;	n�0�p�+&f�i<7�?:p`�3j���]u}h�i����Ub�o���=4(���(������l��KJ�����p�{��>a7�W�	���=������y��	W���a����;��TVS����
����n^	��$��(�p�b�Q``����X,�
|F�
�Ng�v&�������z��(!B>�a|wI��������
�� ��{��{���v{��V��4�������ZM:��PJ��r:����v���0�������h��@�(�����e�W��~�{L
��x��4������M���}����z.�f�����w2�?�;[�e�f(����b�n{�o�q���Qqq��z�#�my����u
�u�i|���t��v�%��E/��S���a���V�S�TU�>�td��T�I���fU??�z���Y��)5��Hpkn@cX,
����Ng����WUU�g;C]���0>������z~�!����(�����r����,K����$���Mv{�[s��+P�_���g/�8�����t�z8�3sN�fF���_�>�uy����p��:�%��
����
��d�M�`����sL����Uv�k��y~�K�t	4�������*f���yx�����{�/3			�5��
�MQ��
�U�u����KE�uCP��*Z��h�jUD,�n�,�
BH�!�d�$�����a��$L&	y��+��9��<�3)��t�9����PC�]YU��Y��{K�����o�k�'�j�������l�;j;o�I/'E+����^T����j��=�$�{pawM�j��C?�����n'��No��'gX����>M��%��m�������.�_�Z�r�!v������J����M�������}jh�0��bIqko@[y{jX�By{���(#c���&w�6"B5������B�P^��� ��i.�{�A
�v�1��i{�d1'��/�D�j��']��K���=�=���ydH�bv>S����{Tnk�pW��=Jw�Kv�Z����������w�u�����e=g�*-��������K�&�(� P+I{k����}������"�C����g1'��'�������������i��?����jp����������2�(,�`G��=8)���P}�a-��4g��U���=�%�������a)��lX��?������=�Y�\�k��\�����*�@.�����:mO2>q����l6���,����[P� %$<��^R����^�`G'fn\
	�7��6�uG�U76y�+������W�����Q����|�5���8q�]T�����$����TR�?v�v�>�Z�-?������V�wx�+�����d�8q���=I�������o����K\�����]T���~����<�S[�X��Xl_��������2�5pb2����;���n@;�������2�g���[,��P@���������z�+�������~�F�X*���:l���E��R���0�?�#_�-����pgtMPjj�rsse�Z������p���j���
��8"���M�U]kXs�3>q��	f@����yJK���^Z�^��/i���<�X�L&�%a�.H���u6�zEC������F�������555i��Z�h�6l��r��dRRR�.��R=��#
		9�����u�)�(''�a���n��o�y��G���������U���f���/V]]��zN�CW��������.��yU\��;j�p_����E���j=�k�o�Hv�]
�F���`k����Mm�1����d25�|�������,�v�i�������<o����������������>��C���{p�^Yc8�e��@�y�5���,���xJ\�C*/�*�u�A�����u�i������{k��=����y�/���0��?�O�NDUE��+Wei���k�`kj���z)84P��E�UpH@v
�;����_������p����V��}��W/555������w�����q���������,N���t�qp/!8P>^&�y�5�p��_/��G��7����5,�%��X�6[����SSS��;k��bz���.��d��P���?+9`U��y����*�.V��*���$5��T~�J������J�6O���1����m�t���;���l�2:tH�����i�6o����|������>�]w��=z������������t��08��{����W'�%��?��Zi��X����i�������zY�F��v�O��6��rR��}�
��m
����&�����;��7h��}���W�������Z���j��d���
�k�����I�d�������m�6M�<Y���N�������/��/�����+&&��zx��g���&I���������:�=4�����r�4��Z��	����9Q��������������^L����R�^�?�����U��j�v�pA����}�������uSg���s�*##�y|��w��^���o��T@��a-�����s�6�.\(������c�@�����hh2��l�
�����X����b��TH�pU��3������=����PM���>/�P?�Wy�#tGU��J�.O���9)���A����p�:���������=�SS�n��6���K����*]y�������
��H�4>mO���{��+���S�����������6�^���r���V����4r�
yyu��W����e�����z�]�3c���P���X������>_
6��o�[�2�����������Djj����UPP ///
2D���Whh�1�������~���LY�V���)!!Ag�}�||������Tzz����T\\������*""B#G�T|||����������O***��fSHH�
�SN9E���?�=�������+??_v�]���:��S5b��L��}}���_���<���I���������c�����{�l6m��]iii*..VUU����e�X���x
2�������[���k��1CAAA���_��
$I!!!Z�p���F���Hh�^i��C�~��8��Z��{>>=����%0�����������7i��;��������^M����v������{k����}z-9�-��~)��n;i�h��
��~@��N<0��}��W?~|������������E�i������v�.((H��4g�8��V��z�)�������p�622Rs���m����>w���w�yG���6m����7���t�]wi���
;�}cbb�g�����zKo������,Y��o����^�z���y}������ILL�u�]�)S��O�>����RSS���j��u��h��9������4��3G�W�Vee���=zh����5k�z����{8p@O=���~�m���smDD��?�|�z���8qb�C{y��7����������c{���[�f�j��;W}��^�����@�������i{�d����X�	����+
x������:|�?������x����WQ��{�#t%�:\��r���*Tr���{tUUUU����5m�4���$UWWk����0a�jj~~?aNN�F����{�0�'IEEE����u������O>�DC������~��c���#���\��
Sjjj��p���B�{�����K�n��c��$)33S�g��C=��},X�3�8�ehO�����[n�ES�LQSS�O�lhh���S5|�p�Z��ehO�����p�B�����O?m����]���-Z����=I:|��V�\�'�|������d2�����Z�Sk���h����a��)""�����������$�q�����<�7��=4s�K
v��4�Y,�n�	�,�~@��#]��3Pm�~v�vWG���(��:5+�@YU��@[�������>]��n���_��k�6����W�G�VRR�������7�6m�$���C:�����~&�I���1c4x�`��^|�E�X���=���:�*>>^�F�����5h� yy9�^


t�y�)33���M�o���N;M_��S-,,L���3f���������}^}�UM�6M�����|?5f����^�u����-�wuu�.��2-\��)��SO=U#G�t:]�j���+���U��y���t]~��*//w�������Cu�i�i��Q���=��Q{:::|���?��g����c��O�_�~;v�~�am�������������������'	�{�$U44*���`�������jUU��'�������R��*__��[CC����US����������oX�m����=�nl��1�TU�����#{UW���9��-]�T�|��$��nPFF�


������t<xPw�}��5����}�v�x�����W@@�{�1���_999��q�rrr����s�9���x@6���G����K/�T�/Vvv�*++�c�m��I�����{�����|�r���7_W]]�I�&�n��w��Z�v��/_�0?a��]��������UVV�+��B���k���������M�6���Xiii��q�v�����
}��7����ZuZ��]�������z���URR���m��Q���t�g8\7k�,?�z�]wi��5�c���Y�fi���*,,��-[��?������u���������������k�.���9s��������z�>��UTT(++K6l��M�������*m��YO?���
���Q{;:�7x�`��v�����!C��#�h��
:p�������~m��As����Q�����Vh������1cF�x���JN�}�'��n�C����$)�������d�!���U@@_%%���o7��WlQN�|��=���Z/��[���u���7����Z=��@������N�&��j;����zv��R�����=��+�W�:)+//O�����k���N��={j��E�����%K$9�����Sff��f�>��3�}��N�:T�W������O�;p��>��S]y��.{5j�rrr}��-�~���������W_��>�L��u�V}���������7n����I�>}t�s���u�]���m�����?����
������Yg����~Z?��c��)((�$M�8Q|��������9R_~���<�Lm��M�������CF�}�]-]��y<d��Y�FC�1\?|�p�Z�J������3%9yo��������������/�h'$$����W`��{O�#'��1B#F���?���,��{�������q�z���[t�{�����T}���JHHh��w�}����$Iqqqz��G[|-:?�{�$�����x�������t����f��4��ED�W��;�'�a=����4EF��<!���c���������:;��_������Vu�6m^��������R�pX�'#/�U@�_��},�]w�ah���z�)���[jj:���?�^x����O���4k�,M�4�yn�����
4��	�-[�L�Vyy�$i��%��=w��������<6�LZ�r��������4v���7p�@�������_�s��y�{���.�{v�]�g�v��X��_�1c�RSS�j�*I����/������CI���UCCC����ov�3���[{�)<���K�j������#G����W\\�$i�����?��-[�4���g�.��m��U!!!��s���������/V@@��=t*^�:W��$s�L&�O����Y,I2��1'��������.��3TS�������"tQ��_<�#_{j�<�w2�L�3g�q����W�G;�/*::Z��z�q���������{fr���p�������=~i���������'k�������>����������<�e��hk��q8�n��i-
��������v����tZSS���S__��"NDLL��v��WLL�[����{?}_����p�Bm��I3f���W^�+��R3g��?��^x��}����������_qq��N��<���[Z
E��;� �up/�l��'��{�n�	����|���W����*��~����=�Y��L&��0P}
N�����&���G�&�a@�v�)�8���JJJ����������q�3��a����V��R�<����@EEE���$}���{�����2�L���k[����[��
k������?��3�����V�u�)�(**�y��7�8������x�����l���3���4���g��?����������)�l��������t��!IR�^�������stf���&���j
kF����:UU�4\o1'��7��
��Rr��%9�����m���Y�6�F��>z9)�����z6���=p�Q�F�xm��=�#G�l��-����Lo���n���9R}��Qpp�L&�����s�=|�p��i���B���4�{���t�;���8}���W�^���r�u��+!!���
0������N���h���5�7l���.���ODt�������D���<��>��bcc��


�����r�����|����_����$�����SS�:�i�*+w�no0\��{�Nz�<G1�w������Z����nl����0���*i�/�t���-^��kkjj�����J3g�TTT�n��v������e�8�����YVV���Z���=�u���8:�w<���cW��_�������e�<�Wjjj�=JJJ��={��x��u7n�
�;��S�����������if��i���n�����W>>>���[�������Z����;��]t�&M���n�U���+�_����� �O�Vf����WP���tv�MS����gf�I55�>�����[g�p���O�����:�;p��N����r��a�q��?�����|���X���6X�Z'�}���o���r�����~�&M��O>)���0������k��I���QLL��L��u�������{��{n��?z��M��=�����?����� ���+��]�OG7���*��o��z�Z�
�������GLt/^^>JI~Q6^&������`����=j����;����6��(i�~��C%�F��a[��f������u�/X�y��j��������6w��*nT?���K���oW����V��ow�0`������$���_f�Y���'�-]�T��-k���V���(�����i��
�=������5g��Y�F����A��g�^�u����JII�/��/���}�E��������[|���C�������Q```�\nn�CP��'�PLLL��E�����t��/DR������{K��z��^JI���l�I��/&��4eg�����=�[k����_���s
��-�jQ�!M�v�%:'��IA~�H� ��Bzw����}����������E����n�������������=�Ree�G�u��� �qxx��}��v����O���~���B}���������_k���Nk���4q�D���������}�Dbb���d29�=8�������R��^yy�C�q���1cF�{}�����[o5�CCC�%��GpJ�2��H�Ap���A�����	��;�A1S�������`�z����/�pg�waD���������ruf�F�{�3tE�CU�]����4�<���8�/^�n��E�����GKN�����������G������A�TSS�.��#{���G7�t�n��&I�����n�:}�������e��$9�o���:��34v�X���JRR���n����^���-�����i���$��cG�p�;TgSQ}�a������55��'���n��{v��zf����6>���yxH�����F�tg�����;�_
	PHO�XBz)8$�#{�m��_����={��k�m�����������X��?���}��d2)::�y\SS����wH/}��������{�);;[c��i���v��/���~i���Nsl��G�;���z�}�k��=�n.����=���=���E���+sp����"��[��������������JmO�W�G�'o��}
OG������1�p�U569��������Zr�L&St���olOUW��>��z��81�C�������E�UTT�*@���x���no��QQQ���Svv��#��M�6i���-�Gg0~�x���4���[���'w`GRtt��~�m������o���;:b��AJIIQZZZ��?��������n���;��.66Vk��muoK�.��e���&L��3�������'<��@7�*����G~�?.�
���������H�'��E(%�Em��{I�����eg?����<�\+
��s�����|�������������pg�j��,������GD�����������������������m����`�quu���]tQspO�,X��K������.���������;<�'	�����9�y����������!���������j���V�r�w�yNk�f�.���V�ut��O�>m�<���Kp2s�K68mOr��X����������A�\����>�`GmwuT���
wY��]��c��	�d�)Q�h����|4hXT������N���*++;�5z��'Z�OHH��i~�����~�����-_�\_|�E�������J���6�7l��W^y�;:���^?�x���:����r�-���Z�JYYY������~�0w�����=tA����J�O�1
���M�Vf�'�8���[��g��g�xTUU�=�Q�=�O�A�'j�6�ug�U7:�.������(_�F||��x�@���O(�u��g6����^=��1����.kQ���|}}�<��u�rrrZ|}\\�&M��<�����o�����E�WUUi���-��=x{{��'�t��6m�^��V�g����2e�


�jo�����������o��E�����G��rm^^�L&��W^^^��o�A�i��)����z]��*))qyMQQ�n��5444��;���=t?�����&��nyp��f���[,In�
��L&/%'�Y�~�
���UJK�G������`o��-?������V��r��p���%������|�|V��C�r?��o��a�������n��={��V��x�
�r�)��u�$)11�U{M�0������:��s��O�������]�/�����������j�������
]p������y�f��v��������ou���+::Z���j��m�_��������f��)S��_�J�|������j���m�6����:��������_]6��i��C����������k��;�8�o���;w��{�������������<��c���lo��M��~�>��c�p��f��~��O?]?��)�wG�@���QU+Wgd�*�i.V{�lNp[_�������S��-[~'����^Y�C;w�Qb����uR,Az<���6�-�_������W��;@W���+w��W���D���aQ����L�0A�\r�>������K�j���<x�"##UVV���\���7��4i������O�x����[�/Vm��C������g�]�d�n��f����P}��������o�>IG�o����x�
����_�~
Tii�����m���^Rii�V�\�<�n�:�[�N>>>���Vxx�TVV�����}KTWW��������/I���������G���k���***r�������W^yB���z����+W���/n�{�k�.]q�


ULL�$)77W��_���z���4|�pO��N�����J����L��4_i�0X-��w�[{Na=�h��?���/\���z�����_�.�qY k����y�#tU�~>��_	�PH����,�g��P�������+V���Ns���{�6l��;v8����z-Y�������k��e2��m�599Y6l��g��T+))�����q�Feggw���$�����w����>��@��������Tm���)0�����k����LYYYZ�~�6o�l�����?-[������w�yZ�f�z���0_^^�m��i��mN����}��������V�����\���m29�[����-�d���l����g��\��v�ReU��j#����$T__����Iwe��������U�GY�rV����~q
����c����K�������+�����tP�p�=z������Y��r]rr��~�m���;���k�^�\s�v���y��i���0`��f�L��t�o��������h��q���v��d2��SO���>����M=���3g*77W<��x��QQQ�<y�>�����_�{�vZs�w���>�������������_W]u�������k������s�9G���z����G�����u�}�i��]����<� ���n��@7��������qZZ���	\t����<?~�BB\����v��lm(�r��}���?t����n����VCC�����G4p����f��������DS/W]��zpp�����K�^���R���KM.����G���hO8��=�
�{���t'<��nx��������y��r�{v������qqq�6�r"�v�����d���I^>^�
Y�k�������?eff���T~~~�����������n�Pii����{����2�L


��!C4|�p���:�]�vi���***Rii�|||��*11Q111��gQQ�222�{�n������ZAAA
SBB�����`�?�vd���q�F����������Udd�t�i����s�:���������h�&����{If���kk���$�b!��_�RRh��I����UU����q%%����Zgl���r�C����0����d@��L&y�z���f8�h���?~|G��baaa���K;����S�Z#22R��{��=�\���#���j��q7n\G��.�H'@7���^����e����i.�e�$��/�d�#t��y�e����_��;j�i��uf���=�:Tg�`G��=�n��i{���4g���
�����m}'��nWD��\�w�x\��;<�Q�x�LZ�4P����kv������j��=�@�#��M�
�������q��X���p�3�LJJ|N��MM���6U

U��������	]��[j���C��s ��M�
�%�
�]�R���]���PJ��L����������]���#BuG�H��y���T��C��Dp��J��5�7
���R}}��zN��&4�T����e�����p�;j�����)��o�]�3#O��w�q�tC�����7���\��'Is������oVd����;���2�������'�(���%��Z����K� �����*���$)�0��f�������������L&%&<�������:������Jw�z����\|���iya�;�8�������>�����4o��0\o�$��/�;��
���2��������z�K�VwuT���r���]�L�?'�{����^�9P&��i�jM7\o����/��
	9Eqq��<��
���������~�
�7��6�uG�U76y�+�"��
�[��{)�@�9��T����C8qp���~�^���gg?�2D���x���h�{9��%igu��6~N8Y��flMv���5�%�����������d2)1q������=�54X=�Y��X�����.������Rv�Y���]���k���N��Z����E����[{�;�RR^���gX���Wf�C����
w&����E!.�d����:v�9������y��|�^�5�p���,�����H!���=��~�h��,�`Gmc2��������kX�66���=��te���4�����{9�xhu�3'��/?��o�z���e=;�UT�����&��G/'E�|���Z�y���	��t3����I�@����jj��[,)�l�/�L&%&<������n���{e�Ux��68��Y�rY_�H_�t�����������d�������^'������a)���oX������?�n�{�����[g�0������Cu6v���t#��Tlk0���*�
����* ��[{��bIT|�c.�EE_h��7=�Py�Lz9)Z����������GM] �����t��IR���{i�k-�$�L&�����}�ST�+\�w�������k����}����.�_�VjQ�!v�~�t#��{}�}����i�j�0\o�$��/��L&
����������M��V�������P��?�e}^n�6�Wy�#��Ap�q�K
v>m���FUU��[��O��	������`X��������������G�X��s$��.����r[���p/�{����^�A���r��&��K�;��f�P
��e���+��<�Q��{yiqR����_������;�v�"�+�����&�T������xY���k�������P����O�o\�sr����v�6���5���O���l�;p/�{�DVU��������{Vk��Z�9Q&?Fe��'gX����v���K<�U���w���
wYlW�2]�
����k�n"���p>��K1��N��J��,�d���u������������TWw@��nw��<����� ��I�m����=�n����h���4'W%��m29�55���r����{@�3�)a��.������=�y���	����I���2�wV����wp��t.�{�f�S����e���[,)n�@���s�����e}w�*-K�`Gm�b	��C���//,��K=���#��
4���
�Y���k���4���h����ejX����6M���=�U���/BG������W{j�<���!��
��������f��p�3'������h;o���,��w�a�����3��n����0�Lz!a���?�X�tg��������dj�:���:�����@�Kwq��IRbp��|����������Ap�`%}J���KJ�Q��W4(���u�|}�rR����KF1�-�j��-��!}=���f�i��JOO���e�Ze6���gO�r�)JII�����nkhh�����}�v������Jf�Y>|������_wFp�H���+���a�no��2�p=�=�s������6�`�;����_T��Q
���Z��f��gs���Y=��3�������r���j�����q�6l�����������6�?77W������]�o��V55�������PM�<Y��MS\\\������l���Z�b��V��u�������t���k��m��G�n �����$��i{U����Tk����y�������������TW��=�����uf�����|��y�#x��nW]u��+�UW]-����-������dj�����;�%tr�M7����D�����/�#�<��>��)��Vuuu;v���3gj�����IGB��-RJJ����6='����:��S����3�'I%%%��_����-]���{�g���
�:q/��4g���5�|<��}poo
KyIS�Pcc�S���H���k��o�d�6�C��m2���h����[�S���A�d��?������=��)�������:�������lV�AC��q�*b`L�5
��u���v��l6m�����>}�(""BUUU��k����������1c�rss�h������O��Gu����S\\��f�����k�.56������
�|�����������G��p��I�����S%�"�'oo������b��8�e���{�����zG����_��]Z�E��<������������h�������!�'I�U��O�����[3��?��voI���tGf��]�;h� ��=[�}��***�{�nm��Q���*++��e��p��/����������5k��\������o���BiiiZ�~����TRR�($$�y��n���S���s��"�p�K�t}|vkN��X��������%����.���TR��;j�#Bu��H��y���T^����N5�
}�`����*�2~��+Y����'������V�S��+___�5Jw�y��x�
m��]���n�c��qZ�f�rrr������3���������@M�<Y[�l��1cj�f�RII�q��3g��v{�8&&F�6m�
7� �=BBB4u�T}��w����Z=��smy���=��\Fe��|�����;��o�7�Nqq�bIqQ�+-�~��u���G�X����h����S����]�D�����(�����}�������GE�y�i@������j�j��Mz��Wt���*%%E^^��`�����O>���~�	&�d2����0}���
n�+++����������v�Z����{N�{�>�u)))z��������O8#�p�Ksq�^�9������|56V�'�t^^����||,�u��Xi�����s������8)F���/]�����{>
�[��\�|�!U������,-����p�z����O?��$:w������^��������n��an��5��f��=���k������.k�~W_}�����P���-�?�����2��;����$�,�D7v��Tb�����n�zY���-����pg�3(�_����{���k��b��/�����j��`����2���������<��/T�%���>Y���*;;[�����!C4~�x�������Z}��������jUXX�t��g�������J���+++K������Qhh�"""4r�H����������J����TPP���"�l6���h��A:��S����#??_������e���SO=U#F�h�)m�S__����+//OEEEjjjRdd����4v�Xy{{���6�M��oWZZ����UUU%Y,EGG+>>^C�9�����}��z���������\_R�����P`�����8�i���LAAA-�G�8�����QUkXK��<�4X����
t5�"'j@���w��������#t�z�<�����oz�����q��S��U�1��J4$��X�d��N�;Zei��-Y�K���.��J���+�?�y����k���jll��E��p�Begg;]�?���3g�jV�UO=��^}�UUTT8]��s����nkq�;w��;����?�\�6mRCC���QQQ����4u�T�����111�������z�-���[.�[�d�n���c�{���z���������������D]w�u�2e����s�{-55U>����[gX0`����s�^]IKK��9s�z�jUV�h{�����'k��Y���W��}��=��Sz���UZZz��:���u���j����z����������� nM��a F�^�������_�#�:���]�����
k�9q�bIvk_<'6�O
����jWz�U[w��=������oX�m�kJz���<�Zj��Te}��v�#���j���v��������_�i����$���Z�����	B;9995j��{�9���$���o������~>��
:T�g�����������q
6L��������P��{�.���[����=I���������C�j���3�p����{���[n��)S�����L544h���>|�V�Z�2�'9Ym���������~����]�V			Z�h�qC{�t��a�\�RO>��1�����d29|�������MAA���g���\�p�^YY�v�����6n��06l�S��Gp�$�^i���&���
���vY+3���.//?���$����V������t�_|u�`oo-N�������]]���k�x?z�#��~��G��J�v����z�]��y�o��=z�����������o���i�$I�������3�L<x������;����/j��������i.00P���5j�F��A����1�RPP���;O�����n�}�v�v�i�����jaaaJNN��1c'__�6�����j��ijll�t������1c��o��N�_�u����-�wuu�.��2-\��)��SO=U#G�t:]�j���+���U��y���t]~��N'����k���:���4j�(�����������o�����\��������an������n�����s�k�i���=��X���^|����z1[WW(���p=�=�k�����\���S�;�/��m���z|��/�~���X<�'5�����T������e��p~�G��*�.]�O>�D�t�
7(##CJMMUzz�<����������o��}�n��F���+  @�=��������m��Q999����9���p�< ��v�����u���j������Vee�v���M�6)55U�w�VYY��/_�P�����I�d��
��b�
�]�V��/w��0a���]��k���N�*++�W\�}��5�yyy��[o��M�T\\���4m��Q;w�TEE�����w�}���8���'�v�jK&&&����WII�222�q�F��~�g��p��Y�T\\|���u�]Z�fM��l6k��Y��{�
�e����:x���n��k���ymcc�n���c��6s�L���5�O=�T}��'���PVV�6l��M�6);;[UUU��y��~�i
6��������B�������K�{�O<������k���g�y������ZM�2E������F��;�����wo>��O���^�9�i�ju�K�����EF^��nS��7�{�����1�����-�"�Mi�V.7����W#B��oX���e->�a�o��3���u�j���7��'���:������'Iz���5}�t�z��=�h�"���h��%����u�u�)33Sf�Y�}���>�l�k����Wk������8p@�~�����J�=�5J999���>f��E����t��W�����g����u�V}���������7n����I�>}t�s���u�]���m�����?������
�Yg����:KO?��~����SPP I�8q�>�����OF��/��Rg�y��m�&�H�q�����?#�����.]�<2d���Y�!C��>|�V�Z����k�������7}�t}��GN������_4�����+0���������#Fh��z��������w�����Reee�8""B�]v�q�����;�����������$=��#Z�l����:����l6���L�7o��o����Q:�����8)������v���RZ�(_����c2Ce��UQ�������N?�_
p}�]G3�Lz!a�~L�VA���rY�tg�}<2N�^�����������mx��/>��/>���o�
����!{�u�]g�����zJo������$�9���/��~�Y�fi��I�s�W�>fpo��A���H n��e<x����|���%K�{�����w�}�yl2��r�J����i���-�o���z��w
C{����y�����]��v�f���p��B{�4c����j��U����_��s���������������7��2�g$!!��k�����^/�������>z��+���_�Z����=������^����O<���k���t���������� ������>�7���hXKnEp�b��=�d����a)�������P���{�����L�|}�rR���[����[������d2i��9�]��o_�=�a.::Z��z�q���������;z�l1�p��X�)��^,X ���<�<y�&N��n�=���


=��/�Paaa����7�\�f����M�����O}���?��v����tZSS�x���Of�����nw����q����C�t���������3F��sO��3b�}���z��g���������~�~����N�=������$)���m�Ur��.��[���u��8��Y3E��/�?��Wx�#�s:��S�NIs%%%�a|�UW��������f�0U~~~�zl�_��WPP����v�G����������n{�L&]{��-Z����a��5����TWWg����>s����oU_��r���~~��7�|���o����+W�f���U����������{��,��~��������{OC�����'���������?�I�
��y��O�D��8Ie�����U����\]]����'��|""�+z����������=�Q���[�z�]������:~��m��Q-^��gO����#�tmEE�?t���Lo���n���9R}��Qpp�L&�����s�=|�p��i���B���4�{���t�;���8}���W�^���r�u��+!!���
0������N���h���5�7l���.���OD<�555i����Gooo�X�B�������i��������tpp����~}���*..V}}�:�5k���[n�����WUU�����I�N�C��8I�:q/����J���$�bIr[O:������P���������v�z�&�%E+������m
���GMv��;:�����

r���;�K:
�9s����t�����7���-[t��UWW�h��������I�?���A��	v��~�2hWUU%///�@���RSS��QRRb�����������q�4h� �y��z��w�g��V=�������{���<6�Lz���u�����>O=��,X�<���������/����Vxx�|}}�	&�������k� �����9s���������\��g�����������t^^�JI��|}�
�

�JK����zw�:Q��Z����ui���`G@��!�����u�gh������k�}N��c9:���`]k����n���UUUn���:�o��Iz��'e2������x�bM�4I111�����)S�n�:��q�C=���;�����-��������KO<�D����_�|������y�g��w�}�an���*(���tF>�����Q9��/�Z��X�����% �������m��+*�iW�s��{�����=Ct��H-�[dX��[�3z�5:4��p������/��a������3������$]r�t���K��|X~K�������������+))I�����lV``���~>�j���Z�lY��g�Z�f����t��8��Xa�G}T^x�����5k�����i��={�������_WJJ�^x�]x��n��+�7o�����0��c�����o��^~�e5444�o��&
:�E���W��\�/��R�d�����o��Giu��=�����Z�zi������p����\�D���=����]�=��W�Dw�:�����U�G��i��v���<}9z�z��2t?^��
���������������}�8��?�X_}�U��b���W^�
7���3���������_��������0w:E��N?�t}���*,,�_|����J_��v����6--M'N�����6��NF�-�C=�07m�4�S�Z��/�_~y��������{����_�k%��pJ�t�HR���b��l�r���3\��{@�0h�}*+����
����?�bNT`�@w�r~^^Z��7�Pec�S}_�M�w����cd2�:�C��+a�����*��w�9������a�x�b�p�
-�����=Zr�0>t��G�u�=z���������]p���O�>����t�M7I�����u����?��,��&��	~��O�g���c�z���j����:u����������/m�gnn��x��A�����m���:v]R���^Rp���
��:mO"�t^^>JI��|}�
�

VmO����:w�:������.���k��bvI��~	�y?Z��E���^h����7��g�����k[|mz���<�Sll����~����d2��<�������;���}�j���z�������1c�4��v�	��N����n��V�����k��V����	}P}]��{�||Zw������������tW�NB����I�@�9k���X_�p��G��/���o�$�(��E�����]s=�S[��w���2 J�c�
��"���s��xd�1W\��}�vl�sll����[t]EEE�t^^���_���'**Jqqq��C�i��M-���?~��x��u���������o;�}����M�[�z�&M������K�|�r������gO�qk��G��yB�tG�N2Mv����C))F�='�Y,�'�)����qs����}�t��g��m����� �Zm�]S��T�'�x���c�0��v�#a��<b���C�2@W__�����������`#�������_+I]t��x�����38�1,\���:q���{7�>���t�����������?^�����iwm�0nmp������x��!'�R�Cp�$���^��M���V�R����a���
;�e=3�!UW�y��6������{������Xv�a
���[��9,�]�m�����.��{EEE5�9==]eee�����@O<�D��			q8�/77�U�O�:���������/�h�=:��W^�������
��+�t`GG�������y���t�M�6���/WM���u�;V������~�+��k��&����k�����{��~8>�{'��J���L���?�74T�����������t&�����"?��zcc���MUcc��;k�ds���e}Ea�><X���h	�o���`�[�l�o��@K�[���q��g6����^=��1����.kQ���|}}�<��u�rrrZ|}\\�&M��<�����o�����E�WUUi���-��=x{{��'�t��6m�^��V�g����2e�

�?0�������sUZ���c-Z��!�6j�(�k���d2�����Z�g�����.��!Dw���j���2����x�
78�O:�n���'W:tH���od�������t�����������{e��
�W�/>9F�*+�$�
����-�H%'��-[n��|�gee��w=���O:_����/B��Vj��r���{5"$H��������kg���<������9,\�yx�"��xs��o�Q+V�h���������9s�<o�Z�r�J=���:p��$)11Q���-�k��	��u�9�h��):��Sd6�e2���&''�O�>�/\�P���v��-I����\��o�Yw�}�F��p���Zm��I�����-[��.�Lc��m�w�����z}��WZ�x�$�f�i��)��?�����_���Wpp��56�M������_�}���v�~�a��:tH?���z�)]|������u��g:�o���;wj��z�������������dddh���-Z��w�i��]N����7n��5����0a���������5s�Lm�����^p�.kIII�����d����O?�Tc����O>��/�X��?���s�=�������Vhhh������d\���l	t��Z����X0��}�Z�����A�jw����������i���y?A�d2����1�Zu6����Iw���G#c������90F7�_�uK+�����>	�������I{]��	t�%����>k�[�t��.]���+22Reee���U}}}��I�&)..NO<�D�������x����������g�]�d�n��f����P}��������o�>IG�o����x�
����_�~
Tii����N)�,^z�%���j����s�����u�������h������Aeee*((p���Duu���}������=z(**J=z�P}}�������"�����z]y��'��������[o�����'O6����vy*��;�BqUUU�;���n|��O^z�%m���!�������J2d��f�����k�.566:���k�������_w�;N2�N�K6
������>@�s����rY��zD�������|}�JR��]<�m�Vk���m

����{g��?=���)���b��z�q]z�B{]��+t�i�9����[6l��;�c�_���a-�e���l6�����dm��Ag�y�S���D��o�������)C{�����w�}W�>���O���������j��-N���DDD8]{,eee��������y�f�������i��e�@h���`}�����k�j���JOOo�7wth�d2������+x_q�8���O��\���"�gIvk_�&��[����_o�zcc�������Zw�:��0���(������+<�~2x�]7{�n��P�_u�;U��!��`�;U�_u�n��P�����#�tP�p�=z������Y��r]rr��~�m���;���k�^�\s�v���y��i���0`��fs��H}���w�}�>�@���������&�I��z��}�Y=���m�����9S���z��4p�������������h��������dw�q�>��#�~�����=�=���u�UW��o��k��&�6=�\XX�V�Z�5k����.����1�i�����q�^x��6���d��LD'���t�����iiiJN&��]TTT�?��O�x���
	��F�����V]�5�����$�������:���a�����NNzAQQW�[���s����y��$5����N�	�x��Vj��u��}WViX����uc�����!�������y@w������<�
�{���t7<�u_�~�nCC��������N����n���F
6�||}��iO'���Z���Sff�JKK�����}�j��1�������������Waa�>,�����P
2D��W�^�:����k��n����"������G���8p���{)##C�w�VII�������0%$$h���
v��A����h������Vii����e6����d
>���oKg��f��.�Yze��|������(UU;C{'�pv����rv�����*����:��m2iQR��O�R��������{2����C��/y:��d�_`��;�xB@@�������wt+-�K/����8a���-:%�5"##u�����s�u�}�>���7n���������:�����^�����*�i�k��4��������P�������QUU���YD��jAb���7��Z������=�����{G�Z�
�Z,�2�������d�RR�����2�76Vk{�=jl4~�,.��;D��?�[�M�U�����$�����������^�[�p���WJ�_]�{��vj����m�
�G�X��%��.����2[���'�{'�]�u�������{MM6UV�0\k1���7'�=Fk��\��Sa���������8)Ffo����jm��c��.�S����I"���p��dRl���\U�.�����9q��x�z������1UV��`G�7(�_��pY���\K�{�#p2!�p�Hw�������}Vk��Z��O���n�
���d�Rr�|���1�75�j{�T54Ty�����w�n������e�xn8�{'�t�q�$��4g�L3\k6����[�pr��
����d2����wi���d��=�Y�<�OqG�J���&���������]�����I�n�+��Up/�i���{K�[�pr
��!3]��P���<�Q�{{����{����uz,���]�����I�������PG��g�7�j�4\k����7'�nUD�.�;v���2���^�9P�c����(,��K=������+�O����{��yjj2^o�$��/'?�����������T���{��P���Z���=uID���;�jOM�;]�=�����^?_���q��Z�
��L�2u{oN~������L&_�zuu��v<*�����Z�d2��	����1T66���=�oj�pg�+"�pH��5�?��=I�Z�����;��}�>BBNQ\��.��K���`G����W���m2�o�Vk���m
tI�N�N�3���g�$��'�O��7)2�"����']>u��0kFL����{i]q�;]�=�.���Q�5u����{v�]�J�{���dRR�<4�75�k{�T54X=�Y�L����z�]�3�u�����@WCp�������E-�������20c����3����E)�^���gX�������e��z��x�&�&E+����^lk�=�{����X�������`o/
p�TX�O��L2�����*�����G\��L�
�{���������h��oJ+�0��;]	�=�..�Ep/)8P^&����Ep/(h�||�n�
@�����l�w�IDAT����.������b�;j�z����.���*��������@�*��l	t��Z��Z,�n�	L&��V``�a�n�������*<�X+=<���<�JR�]�3=Oe�w:;�{]X�����Z�Z�9�al��]��g1'��7���hX�K���3����Uf��d��=�Y��yyiqr����/��l��co�~���tay5u�nl2�%�O���; ���p-'�h/K���sY/*�B{������ &�_��pY���\K�{�#������+�O�������Vf���=��o������]�w�zV��<�Q�]�;L7�	wYlW�2*k<����ta�.B"C���������n�6 ��|}{��5hf2��0�)
6���6��M��V���Z���~��7��5�uGz��=����ta��{I�@�9W�=N��	>>���P^^����ed�Iv�����\���'����dX����c��
tF��0W����^��Z�{<�l����]��R{���s
�A�9P�c����(,��K=����tQ��
*����>q�������%������FQQW����yN��[<�Q�����.�uY`�^����`G��!��Ee�8mOr>q�j�p��bIq[Op<&�I	C�(88��n�7h{�T�l���:�������a���Iw��Q}S��;��=�.*�Ep����z��8�Y���k��z��/�����x{)%�%yy���
��1Cv{�
�����+I��6��Z�5o��I���Gp��J�2���e29&I\�,�d��-a�S��9.����Q~�����N�a���(�������
v:�{]T��8��dp�#��3���7����.�9�����M����F��Y=�����:Xg�`G�����u�y�ut;��OG7���ojRvu�a-��0��*TS�o��bIr{o�C�WE�6UU�t����JK����|,?�����y�LZ��_��P����^lk�=�{���!�:�4T@�UTT����+''G������
S���5v�X���wt�'l��=����g�UUU���_����������e6��`{�=�.hgU�lv�a���^ee���X,)n�Z��;P�R*u��jl�v���Pz�t�:��2�:���Q��Z�8P��q�a���J-�?�{�{{�3@K���k��5���O���[�v�r��d2i��1�:u����z���.��={�������?m>����^����/^���4�����5b�]z��z������9��������+k
��L&�8�Y���k}}�������@kQ���]�KJ���=�z����U��9 �e���B��Wy�#���n����A�U65�6������c�����dj�����;�%tbo��������_�Z�/>fhO:�<�q�F������g����luzb��_���$M�:���=Ijll��M���O����C�\8q�J��1�O����a�Up�bN��d2���EE�Z�e��?�9�����Q
;���������e��fu~�n�Kw����c���//��f;P���E��gU}A��5
�5S����������S#����8����������W/���[~~~���
����:��3���_+11������+5y�d�l6�y___���O���������u��������� W��$s��\����%��=��������m���4�6)-�>�v�������Z���K��ctA�U669��l��c���Cp����*�������p��^���]e��U&�W{�"�y���Nt�������t�5�����S��}�YYYz����d���������.Rff����Z�_����|��V]3|��V�_�f�~�������P���c5c�M�0Af��a}qq����+}���z���Z�~Fp�����.�{)��^cc���s����x{hX�K��z����������G�z��L���������tg����E�Z��X7����COi������l+j���y*~3]��F���C����n,����>��P���]�KHH����w�?^7�t��v�$)??_�>���x��V��.���z?����x������^��]~}��=u��W����������n����:����:��
kI���=ke�$��Z�{:���AJLx�e���;������Z���a����Os{lW�2\�����*���6��~�fk��u�l�?$Z��+�����5g��c��~��������>��7�x��;1��O��C����=���O��2�w������#�{]����$)��0�Z�
�y{�8��}����}������zn�_UR��;j����).�������#=OU��!l��Y}a��^�QM�n�_SE�-����r�Yg)""�����Or�(--�����m����7�l�~���>}z�5���tthW����
�u���Up�bI���g8���bQE�VY+����J��_���D�����%����89F��SuM�'�fW�iVv�^H D
���*�/I��������4���i�=m���}�z��Ujj����UPP ///
2D���Whh�1�������~���LY�V���)!!Ag�}�||�Q���Tzz����T\\������*""B#G�T|||����������O***��fSHH�
�SN9E���?�=�������+??_v�]���:��S5b���~V__����+//OEEEjjjRdd����4v�Xy{{���6�M��oWZZ����UUU%Y,EGG+>>^C�9������[�����cG�\~~�RRR:������k�Y�f����{
�=�.&�Ep/��4w��tf���JIyIS���J�z}�a����#��dj�/��S�9PO����;���.,�9a]�;���t���s�v����*�U����>�]���|��W?~|������������E�i������v�.((H��4g�8��V��z�)�������p�622Rs���m����>w���w�yG���6m��������(�u�]�:u�����~�������i�����[o����%K����o>��W�^���^�~����]�]NLL�u�]�)S��O�>����RSS���j��u��h��9������4��3G�W�Ve��{�$�G��<y�f���^�z����SO=���~[����\���?_��z�&N�������w�����:qTSS���~�y����]
I�.&�Ep/���^cc����_XK�t
AA�JJ|�e��l�v�.�`G�wS���$����=�c����y�#��Q�U��mE����"�d���]UUU�.��bM�6�0�'I����?�&L�����������Q�F����3�IRQQ�n��v���-���O>���C5{�l�_����=�H �����a������=����P��{�.���[����=I���������C�j���3�p����{���[n��)S�����{744h���>|�V�Z�2�'IeeeZ�p�bcc�������k��UBB�-Zt���$>|X+W���O>y�uyyy2�L_yyy-��S


�={���N}���*++k����h=�{]HeC��j�_�%����!�����������=��u�����e=/o�����`G�c2��B����5�W66���=�o�/��"�W{=��=�OWb��u���k����s}���������$ooo���|���M�&I:t���?������d����5f�
<�i�_|Q+V�8nO���Ns��������Q�4z�h
4H^^������w�y���<�w�������N��_�TSrr������8���O�%^}�UM�6M�����|?5f�����i�����_|�E�����e�]��:�����t���j���N��Y�V]q�Z�j�1������/����9
:T��v�F������uF�����o��\\\\��u��am��U_���n���{��n�����C���o�svv�~�a�5J���
��t�9���'����;��/~Fp�������S�
�Y�������b:���b9�E����?����G{j��>z%)Z�&��Vk���.�lSd;P��<�����>�B�U���X�t�>��I�
7����(55U���:x�����n�k����i������������=��c���rrr�q�F���(++K��s���<��l6�q�������^���+;;[�����c�6m����T���[eeeZ�|�����������I�\�V�X��k�j����&L���k]~M�8��^eee���+�Y^^^���[�i�&+--M7n���;UQQ�o��F��w�"""��=���]�������z���URR���m��Q���t�g8\7k�,��w�u���Y�<6���5k�v�����Bm��E?���<��[���k�i^�����n�M�v�ry��3g����y|�����O>QEE�����a�m��I�������������Ok��a-�uVo��������D
4�U�8t������#F��s���#4p�@EDD��+����+�C�-utpo�����lz��������s�j���:|������o�>}��7z�������;��CV��U{��t!��5��fo/
�s��V��5'���t^^�JIY����VC��/pm���M���;���i=���Gss�z��-�Ya��g��;���������/l'��=�����e9��G���w��L�>������I���yM�>����gO-Z�H555Z�d��#��]w�u�����l�g�}���>����C�j���=zt�)x���~�+���eO�F�RNN��������b��~�;]}��������g�I��n���?�\_|��5���sx�?����.���c�w����K�������}���?~������u�Y:������O��l�>���'��>PPP����#G��/���g��m��I:b\�|ys��������K�6���5k�h��!����U�Vi����9s��#'�M�>]}������r}������}���
tZ+I���1b�F���~XYYY.{��
�N=����[}�����H������>�G}�!C���7���������

���k}��������Q����6n���>�L}��i��p�9��C��{��@y�_�[���=�%��}@{���g�����e������b�<���Z���^����o�*
��f�k��������������N�K=���D��BUy8,����c��!{�u�]g�����zJo������$�9H��/��~�Y�fi��I�s�W�>fp��'�h��e<x����%IK�,1��KVV��}�����d���+]�����c��x����w�5�������sx��W�v�����={����
����3����U�VI����i����JRnn���7�|����������L�v�n��vUT��a��������v�3''G������?���a�����9��y�m���y|����7���
���:���k�����n^�u�V]u�U���o��C���:�����^���NS�M��������{v�]���jhhPcc��Q�����	0�V��={^����<�P+y�LZ�������(�5�{��s��d2i��9�]��o_�=�a.::Z����=;?�������sDe��-�o�8���k�������8��p����8qb�����*44���.��B���5��:��5kN��6mZ�B{?y��G��l������iMM��{[}}����111���_111n��-����|�O^~�e��!!!���k��oh��M*..��fSyy�233��o����r����Q��������G�~�����{O_}�����^]~�����k����+==�)��a�=��3-~\��=�.��nW���^�Q�����jj�7\{���w��A}���z������/���������?���_�[o��/��R��V�?��;<����������Y� $�@����EGqU���m�"�a��"�
��=T���LEI�&B	$d���?#79'��;'�����.�y����B$�y��Q��

=�����{UW��.P+E���������%�z1g������p�	����IKKs;�����p8�x���tk����mUFO:�///O���m��$-]�����{�i��l6�����Z�����7����p���e&LhU�N8A���M��|�M�5�z�r;^�p����Z�Og�����55J�����+����{<��S�����t��7k��a����|||�A����o�7�|�w�yG���M��\.�r�-*((hq���r��s������
k���z���u�-������TQQ�����h��$��jT�h<����{ee���l6_'z=[G�e����k�>}��/_����f�����(++K��/������k�i��-�����������||��,UWW���)jl��?��U�P�������|�9�8���
�xm������zT����z|]II�^}�U�t�M:t�bbb,��������w�k���<��5����}�������f��)>>����%���n�0\wh�]pp�
��l���M���qc�z\\�y6u��U�����|"b{Y�r��������sg�u��{��V���k�����h��W_���+0����+++���������5j�����#�����*44�����Xo���Gy��:��2�i{vI����a]Z�a���L�����h����R�-����[�����\��?_o���*++�(!o�����M�|��;��0Q���_�N	2�5���3�URWoq*tE={��d�pAA�����UU��<���B<�����u���j��Y���TPP��3}%%%�k�C����5?����$88�����}h�]EE��v�aCdK���Y�t�����3u�T��e����3�PBB�n��v������i���edd��K/u��9d�}������o��O;�4=��n������@x8������7���c�������?���/h��$2�������@��?��L�B��^���


4}�t��O���
4}�t����K���=�S���?@��}EEE�,L�:~v�^N���a�my^M����S.���U�SFS����%EEE:�����SO������s,������6����~���3�������l���q������f��������34n�8���+>>^�'O��e�:��QYYY�����l$&&j��%
�$��)S�p8�������k���7j�;��s<����-�c>��I7i�Ks��\�*/�4\���\����@�f�Ruu�W�WVV��3g���nRTT�W�	�m��w�X��7�gd�^��P���-N���@==0V�g�I���z}�>M����d��q��+��������U�Sj�~~q��v�@��;�#�m�nu�^{�6l��v.66V#G�TJJ����#�����@����{����3gN��+++s;6j����baK�v?��.��M�6MK�,QCCC�5999z��W��+�(--M�>��.��������w����������������?������
:�m
����u�)�������;��������t�:�w��V&�{�Df�q�Z�a�{���jh0���\����R����Z������5w�\�q�


���x��������z����+nV��?���{4l�����!��]����4?�a��my:%,���z���9l���6��<��fi����v�x��>�@_}�U�qHH��O�������I��_|���~�t���rK����������,X��{�z�����������K�������_��<����t�5J�<������6�u,���t����}���������o_������5���MNN�w�}�t���__\��9=���=�N���^�u���'�������.�s�����O>����l����L�/��������+  F))O��o1�������O+1�O'�������@��V�4��4�t[F�>=9I�G;�8vA'�T�W;��oHO��B�����n�3f����_������ ���u��v�'�������G�������*������o�Q7�x�����-[���{O|����>�r�t������O�i��fI��8p��F���76����K����.�|}}���\IIq�QS����>`����r+2:���*�Z���{�������������l���t��D���a��l���{����U\���������3�N���������[+k���<�Sx�ot���[7��h�%��7:���ptV�\������k��1_������0`����u�,���l6����������{��v���W/�?^�-���[5|�����������v�����
]z��������9�N-^�XC�i�\n�={�7*:��x���M���8�a�{��_��h��2L�z��(����ee������z=W{X�|�%�|������;�%����SL��PU�uomk�g����>?���Sla"�
97��}��f�={�4�~��r8]WZZ��:���e��ry|mtt��������k�z|}G1r�H��e���S�_���i���n��z6�S555������%
�������kjj�f��s���_��:�,EDD4���j��
�w����z|-�q�0k�K;l����j�q/�����g����Z�WNN��tlv���R���o7�z}}����Qcc���<wc����g�i��w*����D�8����O���'�T� ��G�q�@W[���<�������=^�>y�����k%���.r;~���[u}Gp�����/�SwPTTT�qQQQ;�qW__�1c����?o:������zK��w^;&��|�M�?����:��3L�������.s;���o{��[o��v|���z|-�q�0k�K9�q��:O����8;����������-������Rj��$���e?i��X�l6�����MR�YyC�n��Qmc����#�����������~
�����������������<=��c��'44�m�_VVV�����������;WK�.m�=��UW]�4�Z�J��Oo�D�����������p����Q�&M�|�t�n�k������VPP�?���n�.��B�x������_~�e�%/^�6e��ph����H��=����Q[+������g6mO�BB����=���u������T|�]��]�^����Z��u�}}4=%N��C�/���w�[
�K���ys�l�>^��-�G=oN�#�����XF������Z���lq}aa�.��2��������������k���_����q��5�\.]{������<����B+W��x���p8�������2e�^y��V�g��-�<y��s��������w{|��^zIUU��6l�����l�l6�_����������K���k:��l�����1c�xm���|=�����|egg���.r���l6M�:����y�����K������q���8�r��m���[��]{���������q���RQ�z�q-��v\Vf<!.00^>>!��f)����|k�Uv��-��������p�"�O3�gn|P��9&j�S��z >��>}g���WjZ��|��y�	^��g�S�m'�7:�+�C��8q����/��o�Q99��������W_�	'�����K���[7���/l�}CC��>�l=��cz��w��g����?o�e����/��~��5�����������������3����Z�|����>������_nU��0v�X�v�mM�uuu�<y�~��_���>REEE�k������?�����Yg��A���W^Q]]]��{������'���G�\s��x��f�[�l��-��o�������o~��c�(��c�=�����G+66����'�v��a�OMM��M���}���n�;�����w���m�~�a�x������jS�L���C=�����*0��a!�}���<�L}��Wn����4k�,�1���C��=���O{��y�M^�^^ex��n�������'����z=��jjjZ|�G[���Vmm����-�����JM}N��\����f���r�g��aC����1�~�6.R�K��Mq�a����Z6|���yK�||��5e�J>�����G}��{*���L��d.��B]r�%���O����=[�g�V�~���gO���(++K���Mk�����D=��c�u��wj��M�����tJ���35i�$�saaa���t�Ei��]�6����z��W��[7���[���*..Vvv�as[{{��T\\��6�[�l��-[&����[�n���WII�����>�������o����~[����h������V;w�Taa���c���UW]uL�7|�����-Z�H�-j��}��#N�+//����5�|IR������PUUU)??���%�~��3�x�'%%E���������FI��u�4r�Hu��]qqq�����;TYY�vm``��x�
�������&�tp�&�{��c�5�\.��O���{


��o}}}�������Tj��d�moYY��n����Z�a����8u�5~����z�������N����c���T�%���Z��Pu����c���I��7O��rJ��;v���U��y�f����c�j�����'))Is�����<�����Z�j�F�����~m��A�W����[;d��$���j��z��'�&�I����}���Y�~��Y���z���������h��MZ�r����{�&����7�3gN�?�.h��}��q�V�Z��~��������g�yF,���������^,h�wa��}���������i/&&F_~��~��_���$�:<��{iN�o~jk���n�����4������h�}}|R
tV���PB�=��������#�N����O�kZ_^R�s�Z���uS�mCu�P������p�������@�BF�*�����m�uk������p}���z��Gf�.55U����o�!??�����k���-[���C�F�Rll��N�l6��/��z���o��V�����8���i��l:�����O����>��m��PVV�~����o_�g�~������w������l�m�����_��z�p�{��������7�|�������s�QQQ�����������i$..N?��v������w���{�k��F7n�o~���������S�e��z��G���\��8�ddd(-�����t��v�IL�Lii����#G*4�uo)`���A��u�����'{��>=��������~cx���Z+_��6�i���'�|�i\�����78�������o���o
��S�OAA	'��c��4}g��'I��&�{��~�-H�[����{�7|�p<�k��
_�o���x��������������[��%&&v����%Wm�\�.�|l��9x������w�}��7���X~~~�����������g���X+V�P~~����d������k��!���l����m���_���B���Gaaa���������{*33S;v�����UYY��� EDDh��A2d�������tR�����y�rssUTT���J���)""B���>|�z����}�����w�i��M*..V``�z���N8AC���~��#�w�����USg��'5��WZ�a�.��W�o����&&&FYYY����W/~�tr6�C)��j���T[������\�������h��G��~1���B��*��\��9�b�@���->�l6�l�>�{'�4r�H�9���x,""B�^zi{�8f�hJ^k���S��s��9��������QLL��������y��g���{{����*�Z�a�{�&�{!!]g�j�����~���_���[f���o����[���v�H���a�?��N�o�)��eq2`��=�,��q�o��B}n��������[�_ZZ���h;��_�{M��w������Jq��zz`�i���z}�>�������5��6m��v��kv�
	�:�gQQQ����%{���)**���X#>�u�v�i}��?��b���Z������fZt[�6U�X���q�3k�Kq���g���+M���3�<��}�8�K�`�����g��mXoh���������koG�xbo%��j]�7k�jd�88�{TY}���j
ki�M�++�0\���S���^����������S}}}��tQ~~����o�l�zE�m�����<�p������7��������S�����Am4��'I)���
�u�i{?���K�f��������U^^�f{h?��'�_��M���o)?��N�3P�
�mZ��/D�}�,LG�@�n�����o���9��{]�q/((H���W@@@���o�>��;WUU�
�:����Q�����7m���+�Z��n��]��3����B������h���2��
��:e�������TU�c���6�IRTT�n���6��WPP�����������>l6�RS����a���J��w�����d���lzf`�z����mv��C��.����=��l�^�3����,��!�4�f�h���t�wh����t���@����;�`�����:_�
N{^6��t[�i�_�ru���p_��/����������[
H�q�C�otiS���{��||�����:��� �=ZC�m��qqq7n����nEFF����}��~�m544KTPX�P����zA����_da������J�k{��}�&�{���U7OxJ
9�q���q/$$U6���.�����k�����_?�u�Y���;t�M7)))IAAA�0a��u�fz������������t}coQ����7oyT���-L�:����YN���sTPSga"@�@�Yn<m�a���3�����\Ucc����
k={�����u�	'��;������_�JQQQn�BBB4q�D������~�z-Y�D.�qS%���f�)%��
�mXol����������d�q�lz19N�}}������5��������4�

P����54T��b�����q���@�������0�����pqaxx�&L���� �5�V��W_}u,qt@��aJK{A6��a��r�6m~��6�F���������%�z!g���8����e�4��:����7Ij4\���X���=������V��g���0a����M������V�X������B�h��M�{�|�����0Q���=T�D�����.����95����=�(�������uG���������2<#����������q����c�f���Z�n]��
�c��3I={�2�o�:Mee�&j��zuS|C�a��%������z�Sp��q��)����Z���Tg���Y�^�3E6���O�������bcc���qqq;vl��~������z��fS��( ���Gcc�6��V��e'�����[+��2���WS��7�����8����in�N$����������T�f�����U[[kX;��=I0`�����l6�5�����l�rL��X|}C58��l~����m�������U��U�L������up�h��`����G�����o�qcc��+��������,��>>>���9�������+�0�766j������>��t������'�����(/o���Zgx}���5�
8u[�2M�{��{�Y#�����+����3\K����o_9��q�I'���.2����k��������~:�>��+2�����O��,��D�s]u����j]�-#[

���@�@c6q�������uv�����{=WGT__���\�ZBB�W�:���t�����kkk5w�\������h?6�M������8���U��
w���|�]{��K������fX�ZY����p@[�q��nh���j����{N� ��>^�������������=I:��st�i������4g�{}o���'D��^���gX���U����r�,N����~�6��i����zw_��6�:����j0��h���i�.$$���:���,��~~~�����~6�M�F��I'�d����L�g�Vii����>BBR����i���S��5��D�3�Ww]�3�����;�]Uca"�>�:���*��v���776���|���'�{qqqr8m���f���_����5����3g�*++�$���u���.7�o��w���da"��l6=30V��}
��
��-#[���'���q��(3n�(�����r��
�/�����k�.�ZBBB��m����_�Z0]SXX��s�����'���f���O((�����U�
�w������<����S����,���v�[
�.��=��l�^�3����,�p���#�3���:��;w�����������h��1��������w��7�P]]]����||�JK{Qv��a��z�27> ��eq2���	1���w��}�&���q��p�\��0k�t;.+7n�N2m(�j����(::��~~~7n�bb�arrr�p�B�&C�K�s�&M5�}��;gZ��~�7RgE8M�wo�QA
��+�:����*�o4�5k�3�����\Uvv�����x����37  @���W�=L�l��U�����������\����L���?�~�.P+�m6�����>���u
�mf�:��@:�:���j�Z�!�{.W���2
�/�{555���3�%$$X�F
���n�&==]��\4����f����+(h�a���Wz�=��+�6����}�Br_����r�����Dt=4�t��U������h:���QCC������q/77�tz]||��a����PM�8QN��t��u���g���tG��=/�=��^]�[�����1'm��=Tw�F����.�����8v6���������q�����2M�R��'Iee&w�����TSVV����� EF�7���n��i��	�5k������\�b�t��g[���9�5p�c���A�z��e������&[��3�����r�/�lVkpIwd��������+(,,��
�}�v��r)""B}���i���n���w�.���:��{�6������\Qvv������l6k�&**J7�p�f�����Z�5��-����N=�T����^1���x���6�o������*<�d�������q:�f�54��WS��7���i������W_}��#G��qqq����q�\��i�V�^���Wk��U����TWW����o��Y��*Smm��,Y��?�X_|���m�f��f�i�������5v�X���vv���Ri}�r����<m�
I�z�����J�������xk���������z9�5�/�����������
k.W��3���v���<������?):�Y��Y��`#Kuu�***T]]-������	egg�f�5��4iR{G���9S���"""����I�&�?�����[���w,f�����h]q��1cF�M{�����W���	4b�m���+9�g�>t�&��$)5���=�����L�u!�I�^NN��a,Nc.!!Ac�������|��$�������Wrr���x����i/j�����P��^SS����5d����:��s����7�e��o�\8u[�N	n�H�M{����
������|UWW7����{k������j��p���}}��m�Gzz����
k����������v���l���5k4b�}���<�zh��2L��|����t\S���:�@/�{f#�CBB��{wk����u��W����6��\.-Z�H���S���-N����h�����y�a}�����3C��wX��3�'����ZY��V��������$�0I�hl��E��/Wnn�����jeee)++K��/W��}u��g*))����7&L���=^��������+������.��2]s�5:��s��W/���M����S3g�l:WTT��.�H7nTPP�W�/h����R���lM�ee���p:S���#���2<����(���}��G���������8q�bcc-N��b��RI�*��_hX���Y��
SD�)';� �]�M���������T���5zxk��5�o;�]Qee�>�����?g&77W�������u���P�M���O��~��������SN����5|�p=���z����r����{������Z�V:h� ���k9r�n��F�\�#�����O>��<�{{�y�^�����e�����7���:���
��������`q��|��-~�VWW�y�������T�BR��r:�T��1E��E�f�T�3P�
�mZ#���c<��5


4}���j�;��
4}�t�������_����\�����>��?�Q�F�[�n^�������;4m����5a��{��n�^}�U�e:������]�TQmX;�q���q/$$���:����ZGn���3�<Sg�u�i���Zs��QQQ�l���#@��^��lX��������r5X��3{u��=�L�l���������@�f�RYY�W�WVV��3g���S:t�bcc�t�3�<S=z�h�u>��l6[�q^^�17Z�|�;��n{U�j]�5����^��eee�WDD��iZ����Suu���YcX�������u��7+<<��p�&((A��U���/Wv���p���<`�����X�XV�]�u���
��-#[M���w�������y�T]m����U]]��s���;�PPP�W��U�Y�F[�nU^^��v������#G*,������������q�F���)""B�
�Yg�%��oQ)//WFF�6m��}�����Jaaa�����������w[����w�}���<���N���JHH�	'��>}�����Z�b�rss�r���gO�x��:�������Vmm�V�\���l���Q={�Tbb�N;�49���w]]�6l����t���O���WHH������������������$m����\nn�����A#�D�@;�,�2<�c�����kj���v�������q/>>�� G�f����/VMM�~��'�5����3g�n��&9�N������UR�Zyy�
�;��WX���q����,��G/������������*�mG���m}8��}��'^��w���2-^�X�G�n��w&_}��F��t����j���jhh�K/��_|Q[�nmv]PP����.M�6Mn���2=��z���UZZ����={����n���sn��Eo���>��S�]�V����k���u�w����>�����������������_����3gj��I-�{���z����|�r�����KNN�u�]���'+&&��{n��5z����l�2�zll��M�v��f���5m�4-^�X����k���5~�x=��#������z��'4�|���G�:���t��7k��Q�����{v���vJ���z|�v�n��7 (@�_��f6mO�BBR����)++SQQ�a-!!��4G�n���+���A�L����Os��QU���
�C���[������{USShi&O���`���B}���`�l��E���m���
�e��6��������_�)S�6�I'">��S�����_��}��
�����M{�TXX�[o�U��w�Gy>��#
8PS�N���+[l��6�=���<x���Y�������s�9G�\r��-[�b��$m��QS�N����V��������O7m����;w���n�������������u��wk��!z���L��$���D/�����?������g4h�^z��#6�IRQQ�.\����u�����ln����=�������v��{�vJ�������&��:������c�����1��7Y�e����F��b���={4o��#~s��r8����������E���W.W���<����:;�|��=sTPSga"��-_���}���[K��L\.�����>���\�^�t��'+%%E��m�7�|�)S�H�������;����f��_�~>|�����l���{N���;b����f�����a�����OVBB��v�����<�{����q��?p/��a�N9�}����jJMM�������(__������_��)S��p�y���@%''k������W�������{�9��]YY��.�L/��b�f���h�x��:th��zeee���+��[o�x���]~��������k���:��S4l�0
0��>G���ri��Z�r����[m�������,++K�v�r;����Ni:7������f�{���{!!f������,����uSXX��i��������>}�����k��|��#�I@�������KV*+�y�n����8���1���k�]�9jp�,N:�={�(77���rrr�g�K��,f����>�H�t���+33SyyyZ�f�222�g��y��n������
4q�D���*  @��_�{�nm��]�W������i�&�}��n�����W]��_�p8t���j����u�����y�f�]�Vk����;TRR��s�*))�����J�7N.��V�����>�Ls��u;�����>3�5j��f�*))��W^���d��u��7k�����o�����z�jm��E������ot����G�G��l��mM�����z�����~effj��������u�t����]��#�h��}G��w��%K�4;�N=��#��c������?h��u��g���_�k���imCC�n��m�����<��jjj��O<�D}��G*--��M��j�*�]�V[�nUEE����{�������=����_]=z�P���u�����3�TJJ��u����d�u�]��0~��3�5k��������U����w����:�7e5���i��xo���������n��Y�LP�c�-Z�H�^{m����"/VI�	��k�a=+�E��������8��E�����������oK��B��mq2�


*--m����Yc�~k����#,��g����Y���lI��O?�����Y�{��z���TUU��3gJ:8e��������t:��'�����jv����x�b�|��MS�


�������2�4l�0m��]qqq-f		�
7����Gk������O$I������~��/���5g�q����������-�w�;��������P���{9r������y��:��3����U?���G����I�F��w�yGAAA��:T���F���Q��&��s�65�Y�`�f���t��-Y�D���7\?d����[z�����H:8y���������l���t����A�i��
l�V:8����N�I'��?��O��i�i��v���Cm��I�6m����5z�h��1C��u�.\���o6�q��I���+�q�e�L���g@����JT]��p����w�������qO:8�~��	z�����~�5�6m�|�+��Rv;C���(q�u��z��m0����q�N=�#��GY��HFv������������tz�S��;-N<UZZ������2k����Y�gS�LQDDD���������i�PO<��^�u566JRS#���>k������ =��#7n\���������g�4g����O�$��9��q�[6m��4�l6-\���i�pAAA:���<��o��Z�`�a������?���q/^���q��ri���n����w�?��Z�f��z�-I��~�-[��M?�f���e���I�L���4��������E��z�j-^�X)))����\.�z��n���{��]w����:7��hGf�{Q~>����t\Vf>F�xh�3��'I����i#N�S'NThh����Q�~����q������i/��'��^W�_�����x
k{{�_�N
1��`�K�33G�u3;���f�i��iG\��W/�|��n����t��7���/�����?��C��A�n���V�X��=�����=�7~�x�5���{���v�u\p�[s���o�v��%n��L��Q���~�����\.������TU�?����l��������r�����&%%�w�����}m��M���������{�|�r=������v�&77W�\r���������?������?�������vJ��������R��o1k����.��7�����z��)��kLx
���[|S�������_Z�
�7�*9�I�zI�jeeu�7����z95N!�#����w�v�\��p�	����IKKs;�����p8�x���tk����mUFO:�///O���m��$-]�����{�i��l6�����Z�����7����p��MX&LhU�N8��A��o�i��W�^n�.T]]]���(������_j���z��gt�W���
		����z���3�8CS�NUVV�n��6��srrt��w�S�c�����5jJ�����+����u
4�����j���6�����f�y=WG�r����mX;����G��0a����M�|������o-L��"{�Rl�M��������ky..�_O
�5�/.:�Y��Y��6l��k�w��v<t����������JJJ�������n���C���`�l�f������][TT��>��������7GFF6�F�M����>�-���t;>p����C����5h��Vg�������76����)11��x��U�����|"b[�������������������{�����;Z�v������+Wj��qjlll:w�Yg����k�P]�{����Q�*=l�+7n�	I�z���������u�bbbt�
7�8*���>��u�,L���@��CL�.ed����|K3y�������>u[��4Y���={z�6((�+�VU����
=����������Y�f��~PAA�*++=������|�qh�������qx#����}�m������n7l�l���5k����~�}�N��v�l�2�q�JHH�����7�xC999��;���zJp;7w��vJ�z���K���
2D~�a��(������j5��m���/See�����4��]IV���.u��=I�������:9�5~��6l�`a*�b��)-��������+=�^56�[��3�'�Qb��dj]�-#[

������v��%EEE:�����SO������s,������6����~�].W�s^���
b7n��q�l6������1c������x���k���Z�l�a�����G��s����K��S�������^���=11QK�,QX���mh��p�2�Hh���!
e��L�q<L����6<���>]��4z�h���[����������WRR�������JIyJ?�4��~��Z����x��dG�������x�U76�����F�������C:`$44TS�Li���y�������bcc��_�����.�v6�^{m������j���JIIQ�>}�t:(����U�g���9s�<_YY�����l�=��-���l�����.��i��d�5��;''G����^y������g��\���V���~�v�u�V�\�f������u���k���M�bcc����+**��u-4�����A��r����t�u>>�
��&�:
��e:q/!!��4�KII��W^���{�������j���]v� �����+��{�rs�gX���������c����,������[v��,�������Q'F�""���������q/>>�]?^���>�W_}�t��������wk�3��_�q�_2�����}������u���t�SO=U������t�R}��W�����c��fk���5j�(=��3�����4W[���u;���Wqq��u��N�ZVTT���?�����H}�������{�{�$��q/-$����,�p]HHj�~�7�~�{�4��x��������~jX�������u��7�w���p������^|oX����N=�C��8��M��]_������6��I!AJ8d�,8>
<X��/�l���4��B�����n�3f����_������o�H��p�w�^K�����p������^�TUU���?���cbbt��7��o�tp���e���{���>P]]������~�~��:���,��|}}����c�h8�Q�Fi���M�����t�R%%%�c����Vd�	��e:q/��a��3���:�i{6�Mqqq�i?��v�F�4��U[[��s�v��;��Wi���������K��~�;�ql6���>��$I�
��-3[���'MTT�eS����e�^8:+W�l�}���5f�����0~����v�n�:K��������������%K�^�4~�x-Z�H[�n�����j.�K�����%����l6u������������^�����E�N�S�/��!C�1Y�E�@;���UY�q#Cjp@���UY��p]HH�#Pvv���^�z)  ���U�}��:���M�UUU�={�eo�=�����i�@����)y.��G/���a2���*�uG���@�t��gZ��g�a�>8z{��i����p8<�����U
tv�{���������h%&&6���Wk�����������-k�$����������Y9��-�?&&F>>>���XMM����*}���M�����w�i��{��l���>q��b�\��u!!�^���466�6����[��#��l���5t�P�5����={�JKK-L�zt?Wqq���sw�����-L������`B�i}��B}���K��������/�<x�����t�C�jkk=����^Suu��������+++=�V�.��"�����U�w�/��b;%q7`����EEE��������n������)����z�3F���3h���z���t�y��c����=�v`���'��/o�)+3��p)((�-�u{��5�&9!!��4��f�e�]��T�������3G&�
��SX������PU�.y��}#uv���~����Y�tD�\r�BBB���!!!��������������gdd������������k�>���n�����Zu��w��6�o���Z�ti�������*
0��x��U�>}z;&:����mHADDD;�96s���W_}�v����j�,F5i�$}��M��v������.���h�hf�{��L�����t�uNg�l6�F�wVf���v����km��n�����Vbb�����B��;�Uo���v���[�������J��G����e�*v�M/&�����a}]����Q�!oK���� �?^^�o@@������ ��mc��M������������.����P���n��_����{|}bb����t�r�t���6k�2SQQ��+Wz�_[p8z�����M�2E���J���e�M�<Yyyy�j�������w{|��^zIUU�<K;l�0�������ln���1=o����y����G��o��[ou;w��'�����v��v�]wi��yM�6�M����4f��vLu�0~�m*�����y��������k]���mz��-???��t,>>>���k5o�<��������o������������V��RS���o���@��?j��'������� ��W/$���?�0�[R��s����h�:8>DEE���n���sUVVv��		������t������^~�eUVVj��i���k:_VV�����VAA�$)99Y7n�x�/��i}CC��>�lM�<Y'�p��N�l6[����T����]���/j������31���:���5i�$�y��:�����Q]]��k�������9st�e����Nk�g��������J3f��$���i���z��7u�}�i���
v����N������/���o��o���������f���w����?��'���_���Gk��n�[�l��-z����������o~�/~�Gg��Mz���4`��3F�]v�N8��f����Z-_�\�������I���O���g�Luu��/_nX�������������5�s���{L/�������G+66��~f����~������`�u��Ym<-)������Z��o1\���M�����`m����O�_�^�u����������u�u������E��g+>�e�����s�,������Q';���Cugl���s�a����w��p���@G�;��C�/��
��>���_���N��/�%�\�O>�������5{�l���O={�TII����T[�������Sbb�{�1�����;5c�UW��{�nM�:�p���35i�$�saaa���t�Ei��]�6����z��W��[7���[���*..Vvv����<�g�^xA���Z�pa��e��i��e���Q\\��u����z���(//��s����J����z���%I������Vxx�jkk�s�N6�n������������m���o�������n��O�>
W``�8�����?O������y�<n�,((�\����K�j����5�?�?���/��[�h�-Z����z��GM������o2+���IR�!�{��r����\IAA�jjjk4��"  @���W��=M�l��U����-L�X%$LQx������TUU���<�P�h�b����tgf����-N:��� �=Z���3������8�7N�G��i���7o�N9��f�w���U�Vi���n�cc�����3[�ORR����#���_4����U�Vi���j�����
�z�jm���C6�I��,X�'�|R���n���zm��]k���?���a�g=z�hvmKJJJ�i�&�\�R���a��o~���3���E�����~�I�V���M��������w�����u;�DGF���2�����8�������,�p�������m������2<�p8��O��tl����0a����M�ddd���>����.�cb��(-�9��v7����iC��jl4nrnO~v�^N�S���Gy5u����|M�6��t�M���;t�Yg�_�~
p[�~�������w���n�IIII�������Z�<�����L����j���z��7���wT{]s�5��e����h��Q��������f���z����~�w�yGg�q���Z���O<QO>���~�����Vx�eee��������{�����?~��y����[QQQ���v�mz���u���j��G��������j}��7���+���X�m��1�����O?��E�u�Y�?����5l�0R����xR8�ddd(-��IM���JMMm�D�Rii�����#G*44����6��������w���~��e�������-"�!'h��w�4c{�;w��m���|||��8o#����������^Syy����O?]^xa�~��}����~X�$�o�������6w��{��)���9���%���}�'��':��=�_�O���x��=���8��u����gv����u�V�s�������\.�jkkU__/�����SV]]����N7nTqq������W/
>��6hk�����WQQ�l6������
2D�����#��m����UXX���b���(,,L}��Urr����[}���Beffj�����*++���
4HC�Qpp��?/jhh�����c����K���������TDD�4|��VM ��:�7���:��2��{iN������s��x=SG������\�ZBB��i:�n��i����9s������}��w
�9��cq:G�[�3�����7�������������dGvUT���kn�>��c�w��p�R���
���l������{G�4r�H�9���x,""B�^����i�x4%�5z���s�9�S?��p8���������.����O�]�\YmXKq4���jPY�&�u!!]{J����U[[kX�q�e���?~����L�|���Z�r�������*"b�i}��?��2��D����[IA���F�n��VEC���h{4�Xh[U�j]��C'�UVf���xjZhHZ�d�(����O|}}��W/��t>�{���q�Z�����j�����pLl6�RS�%?������rmH�G

5';� �]3R�`���U���[�,N@��q�Be��x>6)1���Dee��l6����I����q�o��-6�����3f��v����������0�c���Ci��������Lm�����<�����M�o��;{�-L@��q�B������H��Y�^pp��6�����k���������tnIII����M�.�K�-��m�,L�XDD��~	SL�y����}�-L��	�����a��6�TVe�����q�B���R��n��e���B��^������K�������xk�t��e�]fZoll�����ka*�">�Nu�v�i=;�	�l{-L����g��O��a���Q�ef�����d�
�,�r���A����h:q/$�k7�eee����WLL��i���O>Y\p�i���N���S~~���-�����g��eXol�T@���j�
��0_��/����SY�����E����=������:�iri�4�UU�TCC���������mx>..N���0]�g����>��^SS�9s������T���_w���[6���E�#_���Z��3'����F�;�Y��6h��H���=IJ9�q���x��d�����TGmm�v��iX����6L4r�H�r�)����J��=[%%%��p�"���_��L��~������D���o���p���l�UAM����>�,b������~>M�ee��{AA����&�:��;w��������`q���f����.��!CL����j���*/7���c�������5��,RU�v�y�n����8���1���k�]�9jp�,N����`�����@�c�����T�g�H���
�***��0]��n�W\�A�����������*�	�:��������mR���������dG��������-)��9{,L�w��`�����_�\.W�{)m������2</���z����5�\�~������g��������8~~�����l6��u��;�y�TkCyhd�P��7���TV�V�0�9�4������	*���������7\����jjj���gX����6�q���Gc��U�>}L����Ko������,L�h��
S���7�������,L���b444���(�����[
/�q��*��hRKs�2q�l��$��t������\.�ZBB��i�~~~���e�&++Ko���,L�h���U=z����y��*/�la"���m������'�j���M;M�@GE��2�������o:6k����oX�d����
��g����9�j��	������M�6����Wc�Y�)���f�)%�����1�76VkC������8�����������E43���D;�,`������fk:.+7n��������������v����t:5a�����������x�b&^��o���{R.���^Y�]�7��C�]�**B�c����n����Jplh���Y�^�3���l�^hn����R~~�a-!!��4����pM�8Q����k��Y�e��Y�
��p:���2�z����;���<7-����k�.�n��QEC���8:4���F�K�&�{)�4�������p]W�����cZ�q�:=z���	���o���o�����-L�h���������-[SY�&y&�a���8��'�n������Y�
��C�@���UyC�a���{�&��$������������[�n�9�EGG��n�������?�\k���0�����z����66�(=����/�8��%;5m@o�����v�~pth�hc&��l������L��������-�uf�{			����.�����Wc�����0]��Gi��
��z����Q6�q#nee�6m��\.����lB����g�i��-��UYca"Z��=�6�^f�����`�_��JM�B������
��������`q�������kZl�|��w�y�fSh���X������g�G������<c�����X�	0n:�hh�m���m4�f@G@�@��0n�Kq��M�qv�����l��{�+99YW^y�i���Q.4���c��y�"#/1�o�����S���^N�������*�uG���h������4g`������z������6���5}���+<<��0h��O��_lZohh�o��]�vY�
@k�l6%����k�!����/�8�����bL�3v���&�s4�����z����Ri�++�4�GH��7q�i{�������;��^[[�y��i��=��>>!JK{A6��a��*W7�Q.���dGvW�H��4�O�����Z���PF���=�}�^YY��_�n��7�6����������F�^�r�Ygi������*��3G����0��
ISR��������+o���<c���br�z�����5���\5t��C����=�6�Y^mx>�����c�����T�l�6������IR||�e9pd6�M\p��
f����\�g�Vii����F���y�i}������'y&��W/��5��()��9L�t,4��!��{��@���������,����wWhh��ip$6�M�^z����L����h�������0O�l6%���
�.W�6��������{n�P��7���TV�V��[�������Zj��Y}}�*+w����{f��
���v]}��JLL4]STT��s����x�$������i/�n�7�WW���M��rY���J���� �Z��;3sT\Wom(L���F�]�\a���rH�^y�FI�
!����WRR���b�Z||��a�*�Cc��Q\\�����|��?_���&����d%%���^X�T;w��.��|�6MO�S���G�k�t����t8����F�UV���y -�������5>>!
��&��[VV�i�������W�_�z��e�&77W.T}=�����W��u�i}��������P\���d���O�J53���D����lM��=�����
��w��*��������� ��c��=�3E6��M�����l�����r:����Q	����5s�L���m��y�]s�5��yg���l6
��J��UY��Y���Wz��:����n}�\���w���}����v���`��Y������������k�������(
2DC���s������a��o����b�\.EDD�O�>:�����[�c���q����4�%����&��r������6���\.���=��u.AAA�0a�f�����b�5������u�Wt�FT����	����f����X��^]�[��	�gt����{k��
m�l�������9Z2,I�>�vH��;p����Y���Wk���Z�j�


��deey�����:�����s�=���<�5}�������{��G�������VK�,���/��B��m3]k��4|�p�}��;v�||��vVPP����f��>����:u���ko��h#�&�{)����74���b������6���������R�ZBB��ip�BCC5q�D���������d��\.����9P�3�}�����0�g�v�H�S����p[e�����X��s�\��/Sm�~������Jvv�l6[��I�&�w$tp���������]p���������Y������S��z����?�6�I��]�����^��~z��5k�,EGG��+���3Zl��~�]�z�&L��#Fh�V�g���]w�e:,�+b�@p�\���i����,���p�3$�M�����l��:������{UU��W�\����{����pD�z]���U�/x���}�S
���a'kY�3P�'��6�2�/(���#����d�h��oV��UZ����2T_�������T��Qt��r:�cR]UAA�f��m�~{�����#�}�v�������������������u�4r�H�X�B=z�h������Mr����������v�����|���5k4b�}���JNN>�����E���;���uUL�h{j�����!/�������5v{�����I�����ex>&&F����5t|���?~����L�|��WZ�r���xj����hXs���~�jk�[�����t��=�M�l������V+*�R�������('g���W�5�IR}��PN�t�Z}������/�)1�������='M�������{NEEEJOOWff��������*  �i���[u��7�j/___]}���7o�����g����OZ�v�v����7���nr����H]t�*++���T\\�����M�����|����=�6`6mO�R<h�q&�fsx=W{s�\��{L���z���q�����|����~�~���T<�p)-����
�55���{�\�'k��f����O��a���Q�ed���c�R]]��3���?���kZum��5���[��q�����I�������a�t�����W_��
t���#_�
K�.������\�d��L������������������������>��C}����CBB��#�h���z��w4n�8������A����^����e���������'�<���}���={�H�N:�$]}���|����=�6�i�����W�|ij2m�Ik�\����P�������-���k��1�����������ia*�p'j���M�����rr�ka"����hFJ�6��O�U���|kC���o��U�j����>{�|�U�.Uy�f/%p<������+UVV��k�j������������s�G��Gq;~���t��g��?��s�����{���[�������;4m�4EEEy�k��	���{������]kf���z���%I�C������7���{m�l�^�!���T^��p]HHj��jo�����m6����km����$����6��\.-Z�H��m�0O��\�^1cL�;��UqI��pg�aa�z(!��>cW�>+�����)+�������=^�_M����z�����p�z�����o�}6l����W7����{���t�b�
m���t��g��=z�:��>�6u///O������$UTTh���M���s��
vT���|���e6q�������jl�5\�U��������K�A[JKKSMM�>����X���z��75a����Y�@K��Ui��*�h��l��A�St�)����?�iKw�����r�_q�a}��\}1|�b��,N~VWW�����z����������I����|}#�z��j��5��u����d�����9Raaa-^W]]����k���*++SDD�
���:K>>G��R^^���m��I���SUU������G
:TIIIG}��PQQ����Nyyy*,,T]]�BCC����N8A}��9�=rss�b�
�����r�g��:��u�I'�5U���Z�\�R���*,,Tcc�z�����D�v�i�4���N6lPzz�������
���+$$DqqqJJJR�����c����}��1c�($$��������k���Y������{JNN�j���(%%%i��_�!���UZZZ����?�Q999����8=���^�����e

�^YcX;�q�����6�����I�����h:q/!!��0���a�TSS��K�����5�|M�4I11���X��PZ��Z��*54T4����QF��u���d���!�1�������5�UTW�����Awe�������\�����1�M�;\M�m�2Mi��j��w&_}��F��t����j���jhh�K/��_|Q[�nmv]PP����.M�6���������O���_Viii�k{����������[<��e�������O�v�Z��7��g������;t��w+"��������F�C����z���M��9s�&M����/^���~Z��/Wm���IJNN�u�]���'����5k������e������6m���IOO��i��x�b����	������#�(22��{��'�����U\\���=z������7��Q�F��c��>��c��/���k/������>�H�������h}���+��K/5��?�q�x<�8O�t����2��7�e�q:�d�w�i@{��UU��$B���#F����6����h��9*,,�0�#	��A�0������s�[��3���z1��i}EI����6?�-+*�R{�|��{�������l�=:���
]|���2e�a��$UVV������^�������5l�0����4l�����B�z������<���Gi����:u�V�\�b��t�!��G�����f�������|�s�9���K�l����$i����:uj����y�~���M{��s�N�t�M�<y�=�w}}����n
2Do���i��$�����_���5������4h� ���KGl�����"-\�������e���~�
��\.�~��'�s#F����3�8������e�������s;���{�����������g�����%�\��|��{^�Qa����+>���<������6���������v���Z�V9r�N=�T�zee��������B8���+������;�Sq�Jy��n��m_��|=�U��%�?tm#'g�5�����}:����c����>k:��W/�|��JII���p[��7�h��)�������kj���l������~��5�������y�����������@%%%i��a:������ ����%//O��{�6n�x��K6l��SN9E_�u�ZDD�RSS5|�p%&&������y���5e�544H:��HNN������W�f�_y�=��s����R�]v�^|��f�~���:��5t��f�����t��W����j�������Me������u�)�h��a0`�1}�����UVV6�o_���...NAAAM���s�W3feei��]n�[u�����iDD����{-_gB�����7���n�I�\������f���Y�^�>}����&�6�M�F���'�h����T�g�VYY�u�Qb�#r:SL��J��W5�E�f���	1dXk�tgf���Z~K�����*9`������*/�l�^�������GI����zeff*//Ok��QFF�����;����������a�&N����\�/��v������k�����}�6m����>����������;b.���K/�T3f����[U^^���7k���Z�f�v�������;WIIIM�UVVj��q�S������>�Ls��u;�����>3�5j��f�*))��W^���d��u��7k�����o�����z�jm��E������ot����G�G��l��mM�����z�����~effj��������u�t����]��#�h��}G��w��%K�4;�N=��#��c������?h��u��g���_�k���imCC�n��m�����<��jjj��O<�D}��G*--��M��j�*�]�V[�nUEE����{�������=�u�7�}:���_s�=���Y���~%''+!!�����'����l:��?����(�f�,|�;@W�Y��-0���l�}ee�*
���6Ht^


���1�������v�.��r������h����3g�&M���6��������z��jhh>����P���g�fs��}��m�����lVYCc����:��)W3�d��M�te�����)h��w�y�w�������t����G�n�X��������~Z���z�����K/���J3g��tpJ�u�]��7��t��O>�Yg�����j���:�����
+((�������4��a��}�v�����=$$D7�p�F����G��O>�$�_�^�~��.���f��q�n��bbbt���������������z���4r�H��:��3u��g����~��'������$�5J�����3tC�����#F���t��q���MMF,X���g7���_K�,Q���
�2Do����z�)=���N���������7[��-]���x��AZ�b����$___�t�I:�����?�I�6m2��������O�>��G������������o6�q��I_�����o���y�����-����|�M���@'��r)��x�^�!�{ee�kl6���Am��=��I�P4�?�F��7�xC��o7\�w�^��7O'N�����		
�Wr����~�a��x���_R��{,N���@=3��&gd�?-*�kyE��OOk��jj
���s�;�e���*/o�������[�������:���C=��z�����x�E�?7�=����M{?

�#�<�q��5�[�xq��{�}v0  @s��Q�~�t��I���3
��e��MZ�`A���f���M����N;������������� ���p��/^l���r�4u�T��[j�;����Y�Fo���$��?��-[��JRVV������'M�d��gd�����lK���_���{~���<Z.�K��z�JKK�����[w�u���x��g�n�:I���������/W��w��$��V��}$)����r������r8�$[{:�m3����9�7�������u�]��h���<����Mo[���"/Q��L�YY�k��o-L��+"�5�Ww��c�v+��x.@Wa��4m��#�����N>�d�sqqq�����x���_.����~���A��[�nn
k+V����z����r������Q�F��~=���������.PDDD����o�v��%n��L��Q���~�����\.������TU���������������r���=�tx�]@@��>�1�[�{���?��Z��?������[�nuk������z%[gE����O��I����f�BBR�"V�3k������C��7~~~7n����M�deei��Ejhh�0��$&�Q!!i&U��3�SM�^K3y���50���[�.�n��QE=_k@�u�	'4��f&-�������Z����9�N�f����Ve��������TXX�&�H���K������6��f�i��1�u8<xp�qaa�jjj���5a������p�	n��}��7�������x���������n�~~~�����������G����wk����o�]W\q�G��<���,)))z����9WgG��e�4���W������rW�{


����v�=����@�?^���O���y��{�=56O�`-��_��^��O�a��n��3�Ucc���Z�����8�m��m�5���<�SXg��a�=����C������_WRR�W_}U7�t������f�5����������"��i���|m����822��4Bo���o�y��EFF�8p�p���v���4hP�����6�~�����qqqJLLl:^�j�.���6���Y>a������8�Q�h��j���7n����g�u��{�9�����/�����t������Q5%v54�x������_FRWW�R}��7����:���<�7�t�Q�8vN�S'NTXX���
6��O>����03��}����i��d�����0�g���z<��i}A�~-*�oa"�������AAA^���	`z���[o�U�f��?����UVVz�gII���Z���=�u��G��F�#	v;6�|�hWQQ!��n����5k�4�c�~�gl�N��v�l�2�q�JHH�����7�xC999���*���v|�>O�����l���]z��n���?���d?3�v���>�t<y�d�q�G��+�q���&�����g6mO�B��^�����������wo�&
���4q��f?D8���k��_X�
@K"{�Rl�I�����h��oL��e|Lw]�3�����]�QYcZ���e��N�2STT��O?]O=�T��a�q,������6����~��^�_QQ�����d�q�������fs;����3fh��q���W||�&O��e���/�?��������8���m������^���=11QK�,iq(��n��v���I�bbb����/�?���w�����^y5�����WV�n�&((A>>G����*;;��|\\���a�!u��]&L��Y�L��|�r��3��8#<��?���G��K���)�|��h�����lzz`�PV�]���{]����3����D��y��k��������������Xg�~aa�����e���=/��]{����a�����X�9R)))�����N�e?�Y���gk��9m���&���D����[j�{���u�h��iZ�d�������+���W^yEiiiz��gu�x=gGvx��]�Z}���������w����������������?WTT����������7?����j���h����i{�����M(f�B��^�������s�N�Z||��a��EGG��n����UWg��������_���8����~JK}^��\����f�����H�W'�4Wv{���C���f��������g�?�W�o���X"a]������>��x�)�6�E����/Z������j:		����u����5����/�8�/�U^^n����v��[7-X��M�<��S���+??_K�.�W_}����Z;v�h�6==]�F��3�<�����Msu$t;6{��%�_3h��V]_TT���?�����H}������o��ux����^�����c����k:2d���_T��H:��s�\�I�^7_���|%|�H����������k�.����,N��.66Vc������
��#I�����u�	'X����(%���i�����k�#�_��'k���`=�����7���U�3"���o}�[��.WN�t���������zo������3t���{t�����"R3��us;��w�%�zSxx�|||����������o��111���u��7J:8�m��ez�����4����r����������N;��l�-..N�����:��qEE�rrr���999���l:Vll���8p@�F���������k���JJJ��>�L����X�I�^�3P6�M�TS�Guu��4v�����l���������6:������k�m�;c��w�����-L�L���o�-�����UT����<sW�H�bZ�wS��kj-L@��tTx�pK�
?EN��#/D�Y�re���w��1c�x|mFFF[Djf��n���Y71�[l6�[3XUU�v���.Yz������k��E��u�������������v��l6[��+V����o������Nh���CUTT��K/����t��tj���2d���9&�xIfy���g`������a���{YYY������8���A���������kXw�\Z�p�n�������t���Tr�{���`X����N=�C��8�9�������5�UT�|2��������N�/��?�-���M%?�i�}�Nn�=pl��������pxt]iii��N��ry|mtt��u�VI'�����wxT���wf�3�����B�EE@D��" b��^+W@�lX.��UDCE�rE��H%��2i�)�\F&sN2��I{������9{�I<��'������9)))�����1c�����=����GXX�q��?�l���7~�x=z�8��w��]'���k2���:����b���&���}�Mu;6l�YN�����g��x����5k�q�R�?��-���DDDD�@��#�R�p/��p/Ap��C���Y#���h���%�8jkz���q����u:6l� �5FD���m�#fll��Zm)����^_'mb����������R5��qE4NDDDDDDDDDDDDDDDM��5�:YV`r�:u�^^#������4���}��7���WS����������c`���&�e��5�����5,_���21�N�:����-������^������V�=����7o6��0aB��i�ZL�2���3����b�������-�Z���7F������;��'$$�$>h������`�Q3�TU�:�'�D���	�i���._��^/c�Yb������;D�uuuX�v������e88�!:j�h���4RR��-�6<�#_���#���B����������������,���:5����uBD���rnj^��������QZZ��1���X�hQ��qqq1���������}�Y��}k��5��L�8�������G���_�`FWi4�������-���z����j�|�A��}�����4����������={6~��'��\.���k1~�������{DDDD� N]-8o'�!���8���\�R���=�p��#^$At����c��a�����Y�EEEfEDB��F"0�q�xf��((���Y�������$������:��I�S�����{5ll\���66���{5lm;V�O[5t�P������Z��

0~�x�
��gkk���p����3HII�����0L�>�86����q���������#G,��
�~�m��y������j�y�������#;;�,�~�z����())��|��9������_�~�k���!��L>�����k�x�b��{���?��Ct��������dn��%�����Oc��u��L&��_�)S�41c�6-�Q{/R�����=mE�)Bmm�����qO�p/((��	4D
��d5jjjjp��I�5j�����3g\]��zD�4!!�Di�I��	�{MHx�G�.g&�V.��Q�u<	:�N�9�u���L��	�L&k������������������2��n��3�Vs���go�	�{��R���f��eRH�b�
TUUa���4�WTT`��Mx��7������Dbb��{�=��^��a��x�����gO(�J��A�����sg���/_�C�!55P^^�Q�Fa����;w.���cr����8q[�l��5k0~�x<�	:�o��i8p�V�\	������?����/��F�	ggg�c��������~�
[�l�_�����_������x����d��u�]�<y2�j�wyMrr2�-[�/���d���k�+�9			����h�_��K�.��;::6�������G�8���a��1x�����c�������+++��W_���^C]]���q����;�hp�E�a��&s�'O���?���g�5^����&C,�#"""j���{�JG��	���T1��SK�����%88X�l����d������hp��y�5eeeX�f
~�a�_ �t�r[�D�������b��V[���g�������Z Ca�����{�O��ZX�o��HWoi#""""""""""""""j����������n�<�:������^3z�h�7;w�4����"66!!!���Fii)�����h�k�O����0,Z���������+W��������
�]�z5f��m2�����~�	c��EVV����V���U�����.]����%%%HOO7)�j->��3���`��M�����c������A`` <<<��jQZZ���l�?{KTUUa��-��e���
���pss�F�����QPP`v��i�0q�������������h��3�-�
�!C��e��������k���������~��������F���o���������=����zK���c�"""��d0�P)V��`���"^p������W!@ff&�`��{t#�r9&N����p�5���X�f���D$-����Z*//?�K)H��e��q�L?O���K9����0#""""""""""""""�����1���W����6�I���
D��_#&���Q�����������8z�(���L
��M����W7y���p�Y�J���s������G1t�P�Xqq1��?�c��������hlmm�q�F����ptt4�i�Z�������8}��Y��5^^^f�6���.\��#Gp��)����{k��i���:u�o���^�z��WWW#>>			f�D������������������nRnm��t�1��{j��=�*�*y��kO��O�T���K�l��P(����$�&//���o��~��yyz�����D��/�F~�n	3����.�pv�i<��J���|"""""""""""""""�1^^#����A�O��}ll\M������}�����;���xy�l���9�����?������*�.::�����
`ggwC{�w�}HNN�{���1c����J�2���s����������[1l�0(
��2��{�������K���������4���Kht���/f����[�"''�:u2[��O`���x��G��9���1i�$<x���`ccsC��^���cx������'����|��=
	3��!3��B!�v+>>111�q\\���_�	+//7iy;r�H����`FDm���2�</\�vax�l��@q��HTWg��	
z�B^�j�R[�b�����cbbp�}�I�_�����Z|��w���]��[7<���z�xZ���^���3�PZzT0nc���?����_J�Be5�:��j���K��z����+g���5��I��{D���5��:��QG��="�h���q5�=�Z�/^4�k����t���5����P87�������>|���())������0`�����tz�JJJp��!������2�������z����N�"�.]��3gPPP������������l�A�b


������T���
NNNpwwG�����W/8;;7���z�'O����g������A�����o_��������f��MDDD$�u��|{[c�^]]�`�����{UUU�E{,q6����c�����o�?�������[�b���
>����G.�AL�'8zl<�����Zm��=���6A.�o��uwv���.x9)K0�1���+q�����u2�66��N�$�����#Gb����E���w�}wK�q�BCC-���������[q���6�y;�\�`��-�
5�Z��8u��|�����Z� z�J#k�222Dc7��"!NNN�9s&���E�$$$����^��03"���}'�D
@��wq�x�]Is��������M4�JrR�j�K�����������������������
�**���������U�j)iii��...��`w"j>*�
�f��J�]s������A����z���h<+k
����0���d2,��
;�x�N�'��Q��`""""""""""""""""""��="""��P��!�Z���i��p�=U4d2�.DmUzz��|ppp��Vjy����5kE�9r�����YQ}�����}�h<1�5TU�K��\mm�"*6"������)��&EDDDDDDDDDDDDDDDDDDm�����n�u
��x����;��T�V�����j�������%��:
ooo��9����k8���K�]O&S :���y	�u:5��=�N����su�+���qWf`Oa��Q[��="""�����wV��h���PY�"�����u���� ���������O��������w���SfED����Ft���U�Z������4'K<��[�U���/d"�V#aFDDDDDDDDDDDDDDDDDD����J�RRR��=���,TUU����:uBxx8z���`���������C�p�JJJ`gg��]�b��A		i��RRRp��1deeA�������w���C����l���k""��%^�p/��r��V_�\��
�����������&m2��b�����a�z�s?��3���������C�R�>�gg����@t�4^�� ���<*�OB�Fk/��anB~�
�����p�
����g�}����Z�fx������q�}�a��y�����-���~���J�5�����0a��&��m�������t�T*1{�l���[�����}��5Q�$V��r4~^^/�F�P��1�*y���{����&BVXX&O��~���,n0�e����!,,�2$����(-=���?��^�J
'��������#1��p�����4�
^��83""""""""""""""""""j��-�5l���o��`�h4����x��w->����?�\��
N�<��'����F��������b���4i�h���j,_�QQQ���?���>����Z'������X���n�"�{*Ud���v���EEE���� i��-::��s�h\��c�������0+"�F&S :�#��u��t�8�t:���-�V�	�����#�j	3""""""""""""""""""�����)�}��'���{q���y���`�������
wq���?1n�8������O�>

�B�0�������^"F��c���X�n���B�@pp0z��
WWW�XAA���.>|��_�^������c���;���E[%����C�q����o_�3F4��j�~�z���H�]cg����O!�k	���/.�4'K��}]�czs2P\��6)""""""""""""""""""j�X��J�Z�
���?M�����.������HII���Gq��9 ;;k������agg���KJJ0u�TTWW��m�6���SHKKCzz:�x�	�c�n��O>���k����}�v��'�|���HMM����Q\\��[�"  �����
S�LAYY�E���k""��-^-�	H�����=�������T��U����.8����J%m2D��[o�U4^[[��k����@����w����O�xN�F��m��[�_F��F��)9�ux�Bf�CDDDDDDDDDDDDDDDDDD��Z�K�.��g�1�mmm�~�z���c�������1~~~�1c~���={��=>��C��"���8t�&L��Lf����+V�X�w�y����������}�����}��w���_����8'��1i�$:tAAA����,|������^����Z�xu��|7'{8)���R��a0w��(���>H$��n�
�
�WUU!66����D������x����7QY�"aF�t��������r��.�Q����V���GM��|��[�x����������>3�����L���{���0b�����K�.m4�>����#��+���������k��O>�EEE
������Z?���(������x�5r���B��WK())Aii�`,88X�d��#��0f����[tMEEbccM���4d29�"����W0��U�|�3�������{}�0��S4��R�*�$��������������������Z��2��o�o��f��������u����j��81b�������dx���L�����c�z=V�^m2�p�B��wB����r�-�qEE6m���1�������K)����pO-\��Tv�\nc��ZBzz�h������r�s�=���]SRR�5k�����6DR���@L��!�)����HJ^(mRX���1���'�3P��I��,�ke��������5������y���9r�I����<9rDt��C�PPP`������n�h��9m�����������u+��"��N0f�q/Ap�Jm��ZJZZ��|�N����,q6D�
&O��n���������u�P[[+afDnn��-�%�xn����"aF�sR��2:�r���T����YgEDDDDDDDDDDDDDDDDDD��Z���l����8���7�����~�Z�?���dn���+��0j�(��;v�����_L�w�yg����_{����Rpm{�&""j����@��
��z-��D�5��p�`0�����&666�:u*���E�dggc��
��.�%"�	x^����/$�ju��5���#��*��W���%��������������������Z��"���+t:�q<r��f�#>>��&���`���Z|��a�L�g��][?6t�P�����3��_�� !A�cQ{�&""j��*��<mm���PU��^�sW{*�+..FEE�`����D����|���/���c���&�����d29��>����`\�����g�����<���x���_I�Bj;yu4,�kE�?n2��������O����C�^����'''��;����K���m����]�����c�����{��k""��/�R�p/Z�`��ZQ/�F&���9�j�IM���L&C``���5���3f���������dl��
z�^������
11� �����.!)�_0g&N&�aiDW�;�	�+uz<��Z��u(,�kE�����@�V��GA��}��g����s(--Euu5222�o�>��������n�yNHRR������I9�_�������u������l����.6�����Z�x��{�JG��b�{J�p���V��%��������Q0F���J%f��WWW�5������;[U�QG�����������!7w��5���+�a#��SW���\i�""""""""""""""""""����V���K&c�\�#F��o�i����j����7n***D�������v���;u���;��z��+,,4�����>>>M��K�.&�������k""��M���bU�`���=�*�*y������t�Xpp���5���+f��ggg�5'N���}�$�������F�����B}A������w��'�{
�$��������������������Z�M�KH
z������������2������q���kWTVV����X�f
rrr������g���-[�Q��&��nR"�����h�k�s
�999A&i= �~nB����kj���|4���E�j����7��
���
���q	U����$������"�{������naa���H�N�Z�:��G�����?��l��	������d2(qvDM��^���.@yy4���^_�sg�"*j���hM3�p���w�}.!?Eu��C�\����%��GD	_������u4|�#����{Ws�+LDDDm�k%���L����S�������q�-����N��7�|O<���_o���u+bcc1k�,�}���spphr�7R�v��4t����5]SS|��X�h�M����c�����\�m:v�XK�@���u���md��d�|8+��OL�D|�oV�R
�����v�k)|�#1����t��z�`��?�Dzz:���%�������=�|
�>�L�3���f���gQ[3@��bMdr�s�C�\a+�����d�Pu����#h��{DDM��="�H��GD
_������u4|��8233[:"""jA�O��+�R(���_����Q*�X�f
F�m2���f��PSSc2���kr����&��j�NR�#�^R^�n������\�E_��\c0����Y)3���|���3
�������!!!
vT���Bqq��Y�^M�=�q[����=,aF�s1��pu�h<��;�\%��������������������Z�Z	��m�>�(
���r�_~�%����:�������7��F�ir����
�S�}��K�k""��-K!\��UWg�\��\���hz�wkd0D>�T*%�����T*7�&##����$DD���[���)����\��nK���`lm�h|��+���q""""""""""""""""""j�lZ:�J����{���CBB0j�(����8�������nkp��]�,Q�K�P�R�#�^R^SS��;�����t�&N�h8���7��
���8v��q<p�@8;;�`FDm��`�+g3��,v{�@���ZX������|��#$d����D~~>��9#>|8�MH_��F$&&b��]����L���fEd������@B�t�����dZ�{lFt�z(��p|��������5�d2�s���Q]�n��D7�������u$|�#����{D���u��:��u\���-�� �����P(��t�9�J�>}�X|�[o���p���fk��UVV6)O��pCEnUUU0��d�U?7K���55���|||n�J�...7��M�����'j��
J�����;\\�0��N\�����������W(�����]��,��<���A� ����/��u:�o��Y�f���_����������g��q���0�����^FV����^�����me�y"	�Z��yu:�+������������GDd��QG��<"�h��GD
_������^���
Q�%o��o���BCC!�[�Wa2���ot��,�n
�r�
�Z�q,�����e����������:�|���m2+Nk��DDD�W��Z4�t���@�-\�RE[#����.8��k�VY�G��w�!�����u����'aVD��*�ao����w"+{��5.��K#��s�.,���B	3"""""""""""""""""""��p����47�I��������_������=�������:GGG���x�{u��]p]{�&""j��
��:����j3�
�p':P������t:�h�^pp���Y�-��������kjj�f�I�Q��������[4~��������5�^7����/����UfDDDDDDDDDDDDDDDDDDDR`�^+ez#mmm�����1;99���_(�����=<_K������Z/���h������x�5�����QY%/����B�������M���������_4^YY���X���I�Q�%����8:	�

��=���rik���.��l���x2>�Z��Y�5�p���������+M:>??�d��i�D���h�����������x�����d��wo���c��x���\�.>���f�����k""���f
�T�h�������mll��kW��!��L�q���G��k����Z-afD���
=b>�\n'�������`0H��8G�+��(�	�S�k���,��""""""""""""""""��$�����v[K�CDV`��	�����n��r��zWo�/..����E��<y�da�F�Ra�����k���w/f�����
���g2w�=���?~<��}�x��}0���oT���={L�#G��R�\�����Z'�V��j�.s���X%��p}1��`c�������rL�8�III�k����v�Z<��Cptt\CD�G��Bx��p!�M�xA�\���K������x;�+^J�,��W�[�U������u����HIIAII	�����kW<��zKi�Z=zqqq(**�B�@�����_?DG��"���8~�8._����R�d2���!88���o�?���wU�">>>6l<h���u+}��F��j����M��*����^�"�U�VYT���o��t����
$�~������Baa! 55���#�k��U&�	&4��=^�>��5��������|h4�k�K�=�V���L�XPP���ID�P������u�DW����~�z��9vv��������MCI�1\���`��������.�$�L���=�GI~�/�����~.�q��61"""""""""""""""""�F�������/�����/.]�$�V&�a��x��g1m���j|�V���{���/�Dqq��������+�={�E������^�{��g6o0��=-N�������_|�'N4���[n��O?��S�6y��@��	��'�x�d������������+����...3f���i������8���?����o0�h�"���~r����\.����M�-Z��?�����&��*�
S�Li���xMDD�������
9����u��2�*yI-;;uuu����`��!����-x�t��Et�����q�Fh�Z	3#��d2�G,��S�`�`�C\����+�6��d2,��7�o��J��������%�����������������u1���P���B�������t�d2�G�Z��}������������+W6X�\}�:v�f����C�����7�������gO���;�E{����9s�����BYY�
�%����X�ti��+==��
��9s-���b��i=z4����%����{��<�=z����x��'�o����G�b���&ss�������z<��3&s�>�(rrrD�x��w������x����x��W�T*������������l��������W����k""��G�p/Z����\QQ'����vv����X�1;;;���I������������GtMJJ
�l��N'afD���3z�,�\� ���FB�+����.6
��
���C�����NJ��I���j�_J�?s	��!��yD�u������3��)9H�����f������D0����=z�_�~����Y����:t(��gRRn��v�����+�J���aaa���5����w�ujjj����V�9s�4K����l�9G�1����������<==��{����Q�D��*��2r��|��I�����c�����'M�������?��Q��V������x����g������5����0t�P���O&74fee��'��o�ar�o��������ry���0w�\��:�^�m��a���&�~~~x�����^�.b�{QJG��b�����m���@�PH�
�����0s�L�����ILL��?���8��y(��_(/,������.!�uu��������?Y�S��O�"""""""""""""""j���a���y<	�2�q�D�R��C�K�:,QcYf>FO��S�����2&������&M��u�����+W����s8q�rrr�����~�����B�;UUU���jq�������8����������8{�,�������7�xr��%`�6kv�>���9s���|S�z��'��<���HJJBvv6�?�S�N��������cM��?�����`�^+t�w��w�5���o������;c��������^|�E��=OOO���P�T
������7������0a<<<��o_��� ((+W�49v��	x���,��W^y���7����/�n���o�������I����i\����M�6�����}��5Q��3D��s}��:Ap�Jc���VWW���/����%�����T*��5...�k��9���w��N_D�U�����w�h�R�(+;-aF�������v�B&rk5fDDDDDDDDDDDDDDD$��:-��O���i8RV��c��Ub��T�M�@q��w�""���`�\�|[�n�������g��{�����ok��+33����E{}��78��q�����b��Y&]�<<<�d��Y����/��/^l�%�HJJ�������?o��'O��_~1�{�����7� <<�l}����k�.<��#&��V�Bvv�
����p��z��W�l�2���yyy8q����������G��1b����/f]�JKKq��i���A�3}R�����q�F�����rl����M3���tHMM����QZZj������;1l�0��i��DDD�CZu-����7�:������F����*�j�I)++��{�5,������3g��������G�����%E�A�d2t�Xg�0�������gQWW"qf��2>�
����`��N��	��������������������u5n?���Ko�<[����cI��'"�����������S�N3s�L<���&s�V�j�8�F�%K���-]�QQQ��L�>3f�0��Z-.\hQ�B}�Q���������
�o���&����������������$���m�Z�g�}������S�
������8w����oRs���#!!O=�T�7���[�l��u�`oo��=���6l�?����{��svv���s�����n��������������P/���j���
�n{�j'�{iii������8������3f4�~�����C�$���cR(���rG�xmm.�^����83q�v�X(?\Z�O��H���%���������k���i�0��%��M>|8����|�+��b�H*;;qqq
�{�n\�|�8

��?��^.4�k���(++kr�������?�p������o�<�$%%��'N�hQ�-�R�1c���]�t��riM��N�F��������������QVV�R�N�:�o�������=:u��/��}�:���D������]�t��A��,�3y�dL�<�.]���G���
�F777DFFb��appp��}��5Q��������=W��PQ!�&���vv>V�MJb�{������L�����0}�t�Y�Z�Vp��={�����}�J�Q��tC���HH~RSQ�o���
��OH���[=Tx6��e��?J��Pw%��)%�������������������i1�l*J��f=o�V���b��x��L���������
�\�n��a���puum��������HLLDEE�����{w�r�-����?{�Z���x\�pEEE������+�����o_�����������Fvv6


PWW�g������M�����C�!33�������7���cQATc4
�9���t@�����aaa<x0
�
�������G\\���PYY	{{{�T*"<<��u��kh
:u����p�����L����S�;��?l��i�n�p��������9���<�@�r����k��f�����v�����&��z���&c��
0����p�
�#�...;v,��k�=q�w��;�������6[�\C��5Q��W���(���S^/�F��n��Z�F�Avv�`,88X�l�Z���@L�6
����^/�����~���]�?������()=������������nn�%�L����8T����*������w���}o$g5[����4ux�b6��
�����`�����[o���B�����?����q��E��������Oc���f�k***�d��X����f�z{{��w��#�<bq������a~��W�8qB���������z
�>�,���<oPP222�����;|��w���^��g�n���v����K���B����������S�����s��
��������W_��������X�xq�����������k�.��j�5nnn�1c,X��W���a��%X�~=JJJ\�����o�s��1�������l��/��b2=z��{�y����=��cG���x�	������1w��&/�~�ou��]P���������Y ^-��1����
��=e�Ur�Zff�hA���>�a���
�n��U�^D��"������S����A�)�8+q�r��
�����irk��|��'��U{��c~�U��z�{.���*++q�]wa��y��0UUU��?����M
iRRR��_?|���E{PPP�G}/���E����X�p!�9�`�p� ����B�=p��q��hN������[1n�8������=HLL���M��Yb��e2d�h�\�|?�0�q��:�h�Z<������6o�,Z�\�x�|�r��������w/�w���?����=(,,��M����o7�.==2����f:�YC������k�\����<����}���x�a������9c���_�`kk����?��o���w��&���;=v���x���7�Ok��="""�Fj��O���_��V[���t�5*U������&8���ooo��!j����q������z=6n���~i@��(���
��`��6�	/�`�����h��"D�{���*�P�����������������������j���`0`��i��w�q������GTT
����b��y���|�~���b?�L���0!!!f{}���X�n]�9�����9::"<<���C���lVP�����n�
����_x39�<�?���,������h0aaa�����}V�X�y��A����������l�W_}�O?���sWUUa���X�|�Y����/z����}��u������	�y����{��������="""0p�@������7�g����!++�d.,,Lt}�����P���Y�_TT�����K��^���oR\��K/�G����)S��4>��e��������?p��a�������k��Z�5"A�����p��B�@��}t�{��,O� j/�����c����Z-��_���	�"�x����{�;�������X!aF����
�������R�WTI�Q�HTW�HY�${)�Db��uD�����c��@BB���q��q������+�;w��1_�5��?�Y�f!33�������������cHII��0b��c_z�%��	7L��B���w���+W����P��HJJ��'p��q������k��Exx�����*L�>�A��������{�v�Z����Gc����c��1;Wii)&L�`R�%��1g��8qEEE�����c�������r<x�?�<����3����K�b���Hl�����HHH��c������'Ob��!&�-X�EEE�����������c�R� 55���8}�4N�<�+W����3�����ku:y�\�tI�����Gmm�q��wo�������p��=�'N���������S���;�4[�XK���oM�###,�>))�d������������`k4�
���g�Aqq1���������wC��������555����E;|����q�����-_��I����MK'@DDD������ek��O��P����q��C��&������
������<x0jjjp����F���5k����=��������()=�����)�������I���E�]p��*��*�1�D|����F!p4�0����ZM���]v����
h��r���`#�5�PB�����K���_4�{zz���?Guu5V�^
�j���S�"11J�;w��-��bvlDDv������;������_~���Es���RRR�`�*�
>� &O����'c����3g���_�]w�ev��a�L�����;c��Q
�W�SO=eR����m��a�����0|�p>�����;g�>����1c�`���prr2[��o_���C����g\-b\�v���O���kw��
�w�F�n������7o��~������y��_���������a��=�q���q��!8::
����}��A�>}����������v���f]g����1���]A�v���}������jr��������M:'�\����9������K���o���]�G��<y2n��6t��:����_�k�.cH���������5����="""�F��]��q�kT�h���mUFF���i����M������[QSS�#G������f���3���gG�q��-@y�Y��B�q����{;��pfM�
9VD�������M���k��Yd���&""""""""""""""�^N���������"|��x2k868��-�wC�N�*X�w�%K�����3�\+��������qrr��0}�t���]�,�kj��Y�!!!(++�^�Z�p��\�p7n4�e26m�$Z�W���l�~��q�`����|���L�{��]��{�.49���������8~�������Frr�I�CHKK�V�5�g��-Z�'�{���mM}�Q�����t����~����j�������{�?��9�+++3����C���oo���qtt��={��;����>BEEjkk�~�z�_�^��\�1c�����F�~��=��&o�����Z;���(��=��{*U�Ur��Xm�R��V�D�L&��1c��O�5���5������B��1�A���F�����`�I������x;L�IZ��J�9�X������������������-��dX�xq�����������@��3��c��������>}���6�����`���C�����-[f��`��3f���{��W������;����a��N�]�{�n��v�����h��7�|����`��?�h�����>[[[[��o��� ����t����3v����/�h��~���t��_�X���/�������7>���&�i)���[8r�����q������g�,�X�GDDD��Z��jc1��ozu�jTV��Q)���������&88�]t$��L�{��QQ�E�%%%X�f
���$���cqr
Fd��������/$��qv���>n��W���"������������������z={�4��&&&&�d<i�$(�F�S*�&�T���M��R�w����FAA�U��={����{�9��%��0e���*
����8.((@mm�����e3g�lR^={�����q|��A�5~~~&�M�6����I��5��o7)j�'�|��{o�������cgg�����M�z�/�����_�Z��8���������=-UXX��~�z�����]�c��y��<x�I�i{��="""�$W�@k�E)�>�B�N�\�R���%UUU������'��vr����?*����k����	��N���K�E�ii�Fq�u���2�K#��� ���*�O�g�V/��������������������t��_���o�:������JKK�j�*<������/:w�ggg�d2��w�}�����B��i���\����������as


jR1��������Lp���v������{�s���7~���hDXX�q|��Q�;��[��#G0}�t���o��[n���~j���;�i4�&�P�^C��}UUUx�������Gc��M��R������'���[h�Z@�������"55���P��HLL���nRP|��Q8G��Z~-��{DDDD
�S?��^.C���7���k
g89Y+5��u�L�\CD�lll0e���������������ZRX�
t�5 >���Z�)lM�b����@��4�=�����i�"""""""""""""""�6������NNN�rlC�������������G}�~�-N�>���<TUUY�gii���5��E{@��oD�B��8;;������/�����\.,�l������s��p�B�����1l�0��'���
�����kl����q��w�|}���?���Y<1J��d\��%��}�?�5o�����\�����_6y/K`��Q���5����[8v�z�!����X@:w�\�?�g�6�����������|��)5�5 A�p/��6��w�WT�	�Q*#!����[b�{���pww�6�6�����OG���E�ddd`�����tfF�q(����
��/�4�B��?��������W��_7��*��B�'�����}lC
1d�|���f����f�mH����5���9�����f����7}�t������L�P�����+Wb���

BPP�q���_0��,--
�G�6���������j�y��UVV69����=z��-3��z�-���4y/K��?yyy������p�B���������������j�+((0+m�lZ:"""��,^-������
�p�=�J��O�r�I�7�f���988`��X�z5
�$''���?����m�����qr
DT��8��`���R���[�g&nn��,Q�@I�`�����?~vgFDDDDDDDDDDDDDDm����
�l���N���r�:�5����X �~��������������������c������B��]�T*���hrUll,��Yc��**L���h��Y�aC�vo��&���N,^��w�|�}FF���+|��W������;�����ln9995jrrr�s�����o:u���s�/�����|:'���+����v��?���},UTT�u���r�K�,��X�B�w�y��7������O?��]�=e�����x��{Q�+���5P�������=�Z����XPP��������9s&��������������g�,����E�����+OO�n����y���	��d�,*�OB�Fk/��anB��	���DDDDDDDDDDDDDD$�F.C��}��?�M)i��7e�^/5���~���c�J�/��<�@�;���k�����zj�Z�}���������7n����
�/�����\��������T��qqq3f>��#��B�y�v}���5j��5���`��}hz�pDD��833�I���������$vvv����/�<{�,lmm������������M��������}��A�.],�c������DQQ��O�<�!C��P��	�����Dd���Lk����_�^e�Eu�kT���&�n{���{Dtc\]]1k�,�^�Z�:'O����=���N�YAX��(/;���sQ���Aw���iO��o;[|��gS ���#e��$�
^
��<7""""""""""""""��L���e����7��M�������{����+��Xtlqq�5R2���a2�������������Z��EWWWc��Q����sg<��Cx���\���~l��
?������`0��_��!C0x�`Irk���2�3����9777������7t������SRR��h,�.w}.��[7���lyX����z��L&C``��p����%���p)2Q&�m��p��"^0.������U��Rzz�����\]]�M���������3��� ����C8x���Yur�=bb����E0^WW���y���;���*<�#�8=�K���������������������T:b���${
vuF���������#��===1e������o�������O�<)����Z1�5������i�\���0c�����x�"`�|��'-�WC*++q��w���S�9�R�]�v�W�^7|^___����p����&}}���_&���{�p.�����d|#���;�t��W�v�#"""!V���`�\�pO���������$m"D�T�N�0c����B�����?0p�@��#j���>��J0^Zv�i�"��Kg&n~pg*U�dy�YL`nB�; �m�}�/O���y�{���3������+W�?

�B�������&8�����������",,/^p����'������9)))�����1c�������f����?[0#s����8q�I�����o��,����n�Z��8��w/�b��{��5�s�=��V�\����&�u�������	-zzz��o�@�~�=oo�&��5�]\DDDD"�
�b�{�X�=�2�*9I���L��|S[X���]������kE��s�N�����Sz�H���h��������32���[xy�&mb"l�2|�Q'�P����sk��|b&���L�	����|��c~����G'w��t����y\_@'��s!�|�
jjj,^��l������A�
;v��p�-[����&����;_��q�|��/��lv���X�YXX���M��b��)��o�q����7o�����,{�{��&�{�W�����'%%����I^���\;h��&����n67j��F������c���4�7(&99YYY&s!!!���_BDDD�1��E)�ju���*�jyIE���5��G�����1e��'<]o��mHL~�!����e����'$�����?�Z��QD�h|OQ9Ve��_f]�NxW���Z���v�X��*������k�<>>��������E�5i�n~iiM����������v�Z����I�hi'NDhh�q|��Q|���-��U��������{f�7�^���g���~2���r�]����o�}����]�����X�zu��-\����u���puum��n����aooo���`����������u��n�Uf���
����Oq��q��*z���[�C����^^^P�TgC��EDD`��I�q���~�)))fE�1��v��^�_b��� .~��:�3w��f�y��_�����=%�����������������<lm��W�l�/n76�
���M����c�����5
^{���`����]���������3g�t�UXX�O�n���8p��E�WVV���#�g
�o������y���W_5�<���x������m[�~=�}�]���X|��?���7���������t�d2����S����~���3�e2���kL�2�Y�����o�a2��K/!!!A�����c�����B�hr1��899��������k��/���~����C=����(�	H��Q�+������d6pv��J^R+��8���G�
>�G����������%���cpt���������SHI�H���(��;;�4����Z��8+""""""""""""""��E*�c��f���kg���"���Q�7k�,���+��C!##�d����V�B��=q��@ddd��=z��s�N�#F`��E����w�^��������kv����b���c��Qx��Gq��)��g��Nc��'^x�b��M���M��'�x�8������?�;��;v�@ee��1uuu8{�,>��S�r�-���;���+���?�:??���:�v�����6l0���&99�<�^|�E���{�&���-Z����k������7�:��#55���y�DG��(�����rbcc��j�����X�`f��ir�O<aR���/^;;;�X��`���x���I>{�,�O���s�����������v��a99��8��=�B���o*�
�����P���������	�X�Gd]���GMM���f����n�:��=���gG��yy�������)�D������6^^�K��0G�+�q��dT�
f���Z�v1�E�@vDDDDDDDDDDDDDDD�"���?0o^���+�w������$�;��1�G���q��s�N�\ll,bccooo���"--
���f���kR���s�b���������`����kW�^���g��������~���c����j��U��j�*xxx�K�.pttDII	�����Z�g�}���l���8��~���666����Z-JKK���m�go���*l��[�l������nnn�h4�|�2


���6m&N�xS��~��7��~�?��C����[o�~�]ckk���7c���(..p�H�����O?�n�����iiif_S����)o	aaa����0}�tcA�N�����?�]�tA������p��e�������o�J��:}�a�=""""	���h�#d2��=�*Zp�-��AAA�%B�A
>������`��5�?�����"\]����^Buu��5���#��u�o�+���b	3"""""""""""""""����
��
�������c�:cm�|���6j��u8p��|jj*�=���$���i��a���M�'<<k���R���\���q��Q:�,V\\�������c�x�b�,���m�����>M�Sj�Z�������8}��Y��5^^^f�6���.\��#Gp��)����{k��i�������?M��V�q��Y$''�}M�5
�w�n���T�M��-[�����,����'N������>������~|]h�X�GDDD$@��^����\�A�!�:u�'''��!�����0@4^YY���X���J�Q ��"&zlm��Zm����^��'�Y������&%9)U�% """"""""""""""jiwz�b[�0�6 �;a��n6
�5n6
�pWb^`'�6 ���a��KeL����
��,XWWW�u���X�~=6l�;;������Crr2�{�=�3���P*��F�����_���[�b��aP(�ke2z�������uE�?>�����K/!  �������1c�n����t���l�O<������GEhhh�������I�p��A��?���M�.������?��^{
����,W;�}��W��g����K��&M����D,Z�������(,[�g����A�$�PZ2����D�a���#&&�8���Ctt�/2!�������9r$\\����tB�8�j�����#�1��UU�8|������7�~�N�j>��cTTT����c��@V7��y����zl��
���]�����~���E�_��Oa��=��h<�����.aF
+��0�x2k�
{(��_��|��/|�#����{D���5��:��QG��="�h���q5�=�Z�/^4�k�E/��:=j���epV��TdEmKMM
>���D������~~~0`���[:=A%%%8t�rssQXX�LWWWt��
�z����OK�h�K�.���3(((@II	lll������DFF"((���,((@BBRSSQ\\���*899�����wG�^�����.�E]]�=���8A�P�s�����/z����������<yW�\AYYd2��������
�6���}��}�&"""�I�U��E{���qO�� �Ji���QTT$X����gC����rL�0���HJJ\STT�5k�`���ptt�8C�����6>���/���W��m����83a.6
��
���/B+�6���KRr�vXW��#""""""""""""""j"�L��|�u������#Gb���-������q��w�t7-44��.yM����[o���zk���#�������1|���N��"00���h1|�:Q=��j�y��pr ^����
���r�BZZ���L&��o��Z�B��}���`���+W�~�zh4�������?7����������,aF
�����B�D�_ebOa��u\,�#"""�G�p���W�>��������T�
�:w���!"��St�M��.]����|�2���{h�Z	3#j��r�D
[[��V[�������������1�C%�B&rjZO�DDDDDDDDDDDDDDDDDD��������)��Q9*���{JU������`@zz�`��n_Dd}���x�����#�&55?��t:����o����	�`���.^zO�� ���,2�v6���:�&d@g0H�Q���="""�zD
����v����E]]��U��������*�XPP����'''��9�������������%���}������E�YY�!?�W	3j���->�)5��U���+��DDDDDDDDDDDDDDDDDD���p�����:�:\�hc�:�UTw���m����	���rH�
	Q�T�5k\\\D��={���+��E�lB�����`�xB�+����0����P�������P�Z��������������������:�]'A]#�V6\���[[�B�� ==]p�K�.����6"����Y�f���It��c���o�I�Q�&�)�)����:�q��B���83q/wF��	=��3P\'��""""""""""""""""""�9,�#"""�N��Zp����v���T���mO����I�5���3g�l����?���C�$���}���Ft�'�uJEE<.^�?i�j��\�/��b#�onm�O�dwN""""""""""""""""""+`��uD
��u��o�^^^jj�;K�
Y�s��x��akk+�f��=8y���Y�oC��h<;{-�\�!aF
p��G��=E�X�](aFDDDDDDDDDDDDDDDDDD������#�q�Z�^mmj5W����=�n{
�����&CD���S!���x���?#..N���������p&O�����$��a���a���h|������0#"""""""""""""""""����{DDDD�S���R�p��k�{j�n{�REY%/���	���7����Z^hh(���>�d2�5[�nErr��Y�_2������G0���q>�Y�t��+Z���.��� �x2>j�N���������������������/��OrU
t���p�B�p���vv^�J��t:222cA"�:IDATAA�&CD7$**
��{�h\��c��M��5��i����)�~��V'"������G�+���(.�M���k�$���������������������b��������2�8�/�S�b���rrr��hc���gCD7�O�>;v�h\��b�������0+����}BB����|�����K��X�U4�9����%���������������������b���$��uwv�������E[-/)�u����A�.]�M��n����1r�H��F����k���/aVD�WP�S���E4~!�
TV�H�Q��w��7����YH���.!"""""""""""""""""�v��{DDDD�W!\��t�����&Kp�Je������&8��!��5b�2D4^]]���X��������������q��
����N'�>Cj2�F�#��N0^��������gFDDDDDDDDDDDDDDDDD���p������`@B��
�QJG@EE���m���V�Eff�`,88X�l��9�d2�=}��]�V����r	3#j���<�o�d
�xee2��I��8VD�F&?�����i�""""""""""""""""""jgX�GDDD�r��Z��21�
����q[[�.;mAvv6�Z�`��{Dm�L&�=����h�����R�Y����fF�>���GH����������*aF
�����B�D�_ebwa���/,�#"""������qO�pO���L&���
HKK����C���%�����\.��I�*�������CM��� Y&0�1xz�&���/�+/J�P#����H�h���L��h$���������������������`��8u��|��T6

��X-/)��B�PH�
57L�2�krrr�a����I�Q�#��������z}5����NW%qf��2�E���F0^��anBt����},�#"""� R���n{Z�UU�n*U�������:dee	����%���������Oo��fFF6m��V+afD����;z�,�L&\WYy��C+)�������@��>RV�O��H�Q{��=""""�w��V��V_ |��K.��|�2t:�`��{D����f��///�5/^��?��^/afD���k_t���h</�G��� aF
����>�����p�D-aFDDDDDDDDDDDDDDDDDDm������+���Y��]+�����������o���--M�����:u�$q6Ddm����5k���D����c����Q[����F������Z�$aF
{9�3��8	���N�@��9������������������,��="""��D��@��Z�^�`\���L&�J^RHOO�

�\���D����f���R)����S��w/���n�L&CT�pp�"��kq>�h������\�/��j��������|] """""""""""""""""���&""�/^�p��F����(�SE[-/k���Evv�`,88X�l�HJ�5kE�:t�0+�����11�A&��WU��B��VS�h��"�;	�)*���B	3""""""""""""""""""j�X�GDDD�X��(�d2t�TV]\�R�X35�����^��I�I���3f��������������fE�����Bh�+��+W~BN��f���>n���)_|)�*�$��������������������mb�uxq"�{�����*+�a0���TQV�������������#q6D��t��x666�kv���3g�H�Q;��u6������/.FEE��5lQhtwv�i<��V��]��="""���z�*kc�
��+��r�#�����������C&�I�����`L�2r������oGBB�)*"jkd2"����^����g��VH��0G�+���(~?�Z]�W��$��������������������ma�uh)����c�
�**��*U$d2��r����j���
�����M��Z\xx8&M�$7��eRRR$���}��uA��� ��	���3�x�
��K����w�����R�My�fDDDDDDDDDDDDDDDDDD���p����:�u���B�;9h�p/�jyY[FF�ha@pp��"HD7�G�?~�h\������Gff��Y�/..=��h<?�dg��0��=��|�D��&g!�J�s1QG��="""���D
������C���Z�$�F���fjV���.8�R����)m2D�j���w�y�h��������ID���e||����/.AyE�����d�0��]�tz<��Z�^�������������������>�Lf�����Z:"���N�����%�u��V:*+/�`��i���������!��$���Z�a���������b��5�3g���$������d������Guu�Y�`� ���8�'���Z CS.6
�����.B+��7N]��Sr�$�����#��N���3g������z����}���{|KKKq��q������z�������+__��N��X�GDDD�X��k�{��q�����V���*++q���XPP���Q�t���������WUU!66s���������66*��Y�''C�7@@uM&_E������m}]��z������*�-�*��r�83"""""""""""""""""��\�O>���|ZZ�
��[WW�������O���-��k��x�����s������{4���i���X�|98�A������O<����3gll�_���� """j)��u(�hc��=u�`\���\��oz���a������`	3!��J&�a�����������r���B�VK�Q��RE!,l�h���Wde�J�Q�����H���'f"�F�K1QShtz��t���
}�IOO�L&3~��=��S�v ++���o��]�|�
��/�,Z�wm��^z	C�ip��h�k***��w����'���~k������x��'0x�`\�t�YrhM�_)"���E��@���x�=�*�*9I!--Mp���
���gCD��\.��	��hp���5���X�f
f��
GGG�3$j���=���c�r�g���K����\\��h�"���,2wOB���J�:�M���Ca#o�.�DDDDDDDDDDDDDD����!��5��A�����N.���-���r��}�|�>�}O=������\���9r$RRRL��^���4���c'O����#q��!xyy5K�uM���=z4N�:e������?d2������g�v]���;�Q�%V�����v�0t��H\�����\"j
���wBBBD�\�r���Cmm����2��#���I����P��q����L���y��byd �����U���<�(����5�y��3p�D��j�I�h��Vkp�D�m��y��+kD�HDd�����;���7}���g��988��O?Eaa!���������B|���ppp0��x�"���s���{M����Y������S�N!??'O���'������<���&k��������T�
������+��V^�UU��^xM[-����@aa�`,8X�h��:6L�6
]�v]�����7���N����%bb�C.����d!!q>�`\j#<Tx.��h���+8T��0#""""""""""""""j�jtz��[�}9��R�i��Wj4��S���JP��[)C"��b��y�����o�|{����]��c[[[����������q���/��~��W����m����o��vS94�5���c��&sO=��o��>}���������k����w/>|�y�6,�#""�+^-���k�{	�q�L�s�������t�;��;;;<�����I�X'55[�l�N��03��A����������}�|y�t	5�� _�wq��<���"�V�����������������M)�����|��<��R�������Z>p�������36�����I���X�`����W_��#D��z��x��WL��|�����9�i��&�z{{c������o 22�d�����<Z�Q�T��#�����8���S(
�Xk���&8���WWW��!�����3g�������.`������3�����~��N�_Jyee��K��r��
���B0�[[��/d��.�DDDDDDDDDDDDDD����aWV!���S^�N�]Y�,�#"���c6l�P(�����P�;c�������c����3^~��F��?>�����C�!11��rh�kJJJ2�3��s��\�I�&��]�t���hmlZ:"""���TY�������U�hk�eub�{���gBDm�R���Y���7����\p��s��������2�L���.�L��o��<UU��x2���{�[[7��'��E����t����r|�U�����M���������������Z��{����7��`5z�faB��od������������\.G�n�0r��F������?�Dbb"***���������[n��������j������(**Buu5\]]�����}�"<<���m
���8|�0���QPP���:��� 88={�D��]oz���L:t��W�������{�O�>�ro�F���#G��������zx{{#,,���"���:�?qqq(**Bee%����R����pt�����A
���x�������}����sn���d<e��T�F�S�T����������m�f���1�����b���������KKKo*����{DDD�!%����2�8��`0�B��
�JKKQRR"c�Y����X�WUU%����c����w�!qvDm�B��1����I���;��� !�e���2Y��O��>nx����	���`��3z�ruG�����^}U:=���V_w���-9p�F�i���[X�p!t:>��s,_�/^4;���	O?�4/^�XEE�,Y�+V>�������.y���LNN��
��������j��k}}}��SO��g���{��AAA���0�������w���z�j��=��s���K�.���	�F#�.22S�N���?���;7x���?�W_}�������c�����*&..�/��]��V�����a��X�`|||,>w^^�,Y�������z���n��v��3c��i�5Hi������p�kk���7}�_~��d<z�h�����;M
�v����^{�I�[����VW��-��Z//�����h�������Z@�H�^wgG(d2��\�V[!�F���fjV���.

�,"j����0s�L�����9x� ���/	�"j��pDD,��Gf��f����]�� �3�d|�Z��YQkt���"��5���j\�4X.]�w�]wa��y�E{PUU�?��G�6)�IIIA�~����@AA}�Q�����c�DDD`���8r�H�E{������z=z�����-��9�����[o��q������ 11.lrA��e�0d���=�|�2~�a<�����-/��j�x��g��W/l��Y�h��,b���

5+2�w�^t����y�E{PXX�M�6����np]zz:d2��GC��6��������/��NN7�k���s����
:����
f2>{�,���Z���w��&���;=v���x���7�Ok��="""���:�E+�������V�����������T*%�������;���������{����fE�>�u��}'��SR����u��rT��":�r�`<���&gI��F������u�i�iK�M���{�������DEEA�P��?x� ����������n,���d		��b����~�u��5�SM�y����#�����_?��������M�^���q�m�!11��o&�������������� ,,�����b�
��7:���$;::"22���������
�~��E���������|�r�b?___���}��5��WQQ�	&`���
�?>>��s���L�������_�~

��?#)UWW���3�=��;v�M�7##UUU����3,>>00�������/_��Xk]�?�����_����7z��K��e�������Oo��Z�Q�c0/V���Z�W!R�����W�f0D�.,m2D�n`��if�����;p��y	�"j""��9L0f0�?M��Y	�pv�;a]E�?\)�����+����:\�i�CYs�R�AIm�${������c���:			��������+W�`���&�|���8�<f�����L888�_��rrr����c��!%%.\��#L�}���PW����B���w���+W����P��HJJ��'p��q������k��Exx�����*L�>]����u��w�^�]��d~�����w����1c��UZZ�	& +����r��3'N�@QQ���p��1$''������?//�F���t���X222[�lAqq1p��1dgg����2d��q,@QQQ������{�n�X�Tb��HMMEnn.N�>��'O���+8s����>�Z�N�Gy�.]=����Q[[k���;v�@yy9.\���G�����x�"*++q��)���;�����FR{�����I6&))�d�����s�?��9�X�����
���������������q���t�\�d�Yi[f��	I-�F�
�pk�hg@EE�`\���Z^�TRRb��kX�GD7�[�n�����i�&�_��������CDD����]
�#z�,�����U��kk����"z�Z������@g�QR�m����W�����	���M���������������z��Z]����R��b�[�!��6
�e��[���/]�/���Y�����9����z�jWL�:���P*���s'n���c#""�k�.�����///���&N�(�S�~��������sW�Tx��1y�dL�<;w��9s���+���.�c�
fr��t���F�jp���z�)����...��mF�)������������;����s����
3f�n�j�Q���}�b��}:t(��=�j���k�EB6n����X��[�n��{7�u�&��W�^��y3>��C��?���{/��"�o�n����{��1��w��C����Q�������������_.\����<y��q���6[1Y~~���kW�f�����I�^�s
��5]����">>������b��!����1z�hB&�!;;������[M�|_}�U������{DDD���u��(�#�h���Z�w���5�C/Qc"##1a�l��M0����y�f<���,&jg�PDD����_F�����
zJ����d2|��S�U�xBb�N�'�3�K�0��[����������������������Cz������*\(3P��������jL�:����%K������^�9��B��?�X�h�''',X���O7����������G����5k� $$���`�����{������q�q,���i�&�������0x�`��������?�{��gr��v�-�3X�p���
�]���_�����y�f��?����d�����{T�Z�q<{�l��=!��w�x������#�@��Z�|�m�a��9�v~�Zm2vvvn�9�S���Y������X�v-��E����:�?��~��'���
�E���;�h��Z��"""�G�p/��Jjk�PWW,�F�l��{��s���o�?�Y�w��
�L��b��
�'C�e:�N�_�)�����QRrL�����(�":6"
�SW���i�""""""""""""""""�d2,^���u~~~�����\``�E>��s��=�����MO�&�(:t������e�`0��3f`��1V���W_���k�����N�����N�]�{�n��v�����h��7�|����`��?�h������\[[[��o��� �����f��z���������=V�\����_d�����s�/�l�p���t=�L���~�N�����]?l�0������5,�#""�G�p/Zy�M�X�=P�����5��{�|ED�i��A
����h�v�Z\�rE���������T�=YL���y�h
%�IL_g��'�:���$�����������������z��i�%MLLL��x��IP(��T*M��233�������1;;V����c2~������L&��)�w��B�@�=�������
���s��x���M��g�����5�<h�����^�M�6����I�����X�d�q���oZ�o�R555&c;;�&�����d\�x�zR\��*++��������cG�����/���@tt4�9b��Z
�������W����	�q����u�VZVSXX(�$
k>q��:�#F`�������j�Y�����M���B��1��P8�5�|����A'qf�����H�h���L��h$�����������������c�����k===M�}����c���->����V���?��}��s��pvv�L&3�x��wM�-,����sss���b����u#lNAAAf�
���1��	?H��B;gggt�.��hq����������3��=��c�Z�#bs���x��G�E����x��W�}���4���GS�PS�k�T�tMNN����O>��XL�/��.\�Z�FUURRR������6]�p��r�m�f��Z�����C)�������1�t�S�������w��mv���#��dK^�'�c);�!P���]�PF�������
��V�B��P�B�0�*��U��0Sflg���L'�cy�����<��	����_�����}d��M�8�s>�d�m�0UVV:��pg�N:��������S������9`_����i�����-T$��s�n�>^����-��%
M�'M���o*--��s������;�����.}���WYY����/�����;���
6���{�^���}������I�7��'>>��I�������G�����r�,"w��h�������W]u����?���:�(��a]|����������[_��n��V���k��_��?�I999C�:�@`���o��������N}M������O���Kw�������__���5u�T������k��	�����h�"]y��;�����5k���h�bp�S����V������up/�X;v��6`o��3�8C���n������V]]]6�[��35n�l�|u�-��������zs����2l���u���
�v`_�7�
��:���7��#�����A��v��<wg>>����u�ko�;���(wuu
���~�g����^+�x�H$�w����g+
)
��_����y����D�]|��:��#S�Z���k�>���='�&I���T_����O�����;��zm�c����:��;w����^}�;�IYO�Y��`������H���q�9��6����"�l�K&���{�P��.�-.�K�������b�
�s6o�����.b��E�'�D��S��jCpR��W��C�Tn����.U�-	����us�F����FY�Q�A����'���y����K�����������e����G�{�iy�ls���k����UTT��NPUU��������r}�����V���Oy�h4:���F�L��m�;���O~��N:I�\s��~�i%�A�455��;���w������w��I'�4�=w�UW]�cn�������S�Zmii����v���~N���)�H������c�]w����;��_�B��s����$������5kTQQ1�]������
�U�2C�h��s���T�J�M�6��������q������`�555Y��~�z�{���3g�N��`;�;W55���E�S"�9(��6���
x`�#����P�^m�����wKJ�FC��s�T���#*H%�a(����-��::�W��M����{������/�x��?�Q�f���A����?)n�a����|�F��������D<�@J_����?��O�_�^�<��^|�E���KZ�z��s���t�)���������o���'�����u�TXX�G������x�����+�:u���k�������s�M�6�'����_�7o��x���:���w�5***4c����;���.\�P�f�������D`�b7�W���)��^#�zG+�;2e�R�n���������-`�����Y�f���V����<���Y>��f��)�����$//����W]���y[��jl�U&\�l19.C������i[|�]�6��u��f���aihpB8���m�
>M�{-�������;��c�t�n���J����x�i�&G^w(���(�K�zzzt��':��c���E]��.�H������^�=���q��o�5MS���wt�G���W6������WO��k�����������]z~SS������i�L���8�q(��k������=i�V�l�k;��x����^��:��/�v�{�`u�z���������V���4g�������r�J=���;V�����NSy�\��1�{m����F�*|^�v������?�l����$7G�}�\�6��Uqn�#��=��������#t���s�����j�&M�����r�u��a��zzzlo��jc����9s��Ci��:��Cvd�i��oLK�t0C�����c����.?��W^�x���O�
����<������s;�|��l�*��X�����i�
���d2i�q/
9����4w�\���U{{��9��������g���$�`��i��w�.�HM��K���rsG;����U���F�o��X���Z�C��5#��p3�S�+	h���oK��8�������q��_O�4In�{������[t.��]W�i}
����2M�<Y+V���}����_|����92�	'��U�V�x����k��9il�}��������'�8�pazoP}�5���K/����t�I/X�@�Gx����S-�w�g��7�����g������>����g�y��yN~M#F��xOD?�aog��	�{`�Q��<�1�)�>��oSOo��9�8��a��Aw��@8v�
H�7o����.E�Q�s�~�m������Ofx�.W����Uo.:S����S��[UW�<`�\�����I����.-����o���>�g���g�~�.�>M�����Z��0!�WE�/e�C��t�Xl������U����;����?�qww�.?W�N=���{�t�-����v�>G��z��������������I�6G��c�s���i���
x{�������g�u�~����x����]��r���G�Q���p�s�����N~M�����j�*M�8q�^#�j��E���s3���O�;���69��\�K����f��^cc��q�����r���v%%%�;w��~��9����^z�%[�������7����o���f���]��:$����Q�=1�py���N:lT����c�s�tXiaJ>7�VYY��_���������v�Z]}����:���]Wi���.��o��z��gv�s���g��I�&�x��o���cm�������qqqq�8o����!���qgg�~��_}��~��_���k���?\UUU)��;�L�2������7������w���������~����g�����:�}x$���sr���;&e�R��/����q�
|h��Q�3g��^��9/���^�u[�kT�)����mi���l��a�)�>�b�8����mzp�V��s�t�����!��^������/EC�ZGy��_�b1��G?������:��3vi���rrr4e����}�]�Z�j��?y�d��={�c�4u�����_���wuu��(���k��v���/�\w�y�n}������_����];(���{��_�Rmmm���n��6��|x]�Ad{n$�a>"��n��D�\s����_�Nox���������7�����R�mO||��w��K*�x��A_���3���;�����J`�`���>ap�3j�q/��a�	R-�H����2����������g�������SO��w�q���&M��

f����������v�3kL��Ud��py�Vv[oJd����V>r�6���]:�|�Jr��}��7o�����~�.���A�=F�Q��/�����w�}W�4}���z��O>y�����=�X]}��z��G�����������~��k+~���k��	;wtt��O����e����2Ms�����Z�p����o���R��~�n�M��3g�k_���������W���|�3z��'lp��9����n��&s�1�6m����N���:w��M������r�w�y����l�a]�|�.��R}�;�p�+_��^~����SO�����~�r�)���������xWW�n��&�z�����~����g>�h�����������M��E]�/}�K���\e�������t��g+��8�������g�tv������X\[���Y��
�u�l��S�+U��[g��#��=�#
��.�����d2iy���?���\UUU9��..�W5����Eg*�6(������+���������_M��;�j��
��I]\��4Y�.�9�QIn�>W9Jo�n����M�w���_���i/��|��:������k����Z���j��	*--U{{��}xm����5y�d]}����Z�\r������n����u�t�UWY�{�]w��_���c���z���u������E������/��_�����7N~�_mmm�D"��o��������6=���;�=���z�����xTYY�����q���k���������n=���z���%IEEE*++SQQ�b����Y����A��9s��>������Umm��8�566J�>�y�W�G?��&L� �4�z��������u��w������b=���:����������w�����[�F�Ryy����u�,e].����^UVV:Y=����	�6��$�*�W"���n����8�����������cn��L�������i�z����r�J[������_�����W�W���F�
<n�^��f�q]g��]���RG��.WV���h���[������%:�����,u�=���Ct|���z��7�l���c3g��]w����3e���?_�@`��VWW��7���G9(��u�/^�7�|S+V����=i���<��n�����Y<��U��h�"���;�&?0r��A�����v-]�T�����~�m����|�+�?��A�������/h���������^


���8����*--u��.9��c��s�Y�m��Io����z�-�����G��'���>�9'�:��P`�`7�7&7G#�E;�H2-�N�{�������e����Fg�y�m�L&u��������V@v*���e����m������X��O�����[6��������|�N/����j���������	��24������=�T���TE�/M�1�����K/��?��
m������������O^��
x~��������u�����SNQEE����������W^yE�<���:�(��n�s
���n�A���o��s�|���Wcc�����j����x~YY�����GyD�����������}M���?��/Y�&M�������s�9G/������?����VVV��7��
7����c����~�+������p���9����x�b�x���6m�'�
�t�u����^��~�
�e��i}�:�a���^555;�����:��R�g:::��^�{�	'��� ��g\\�c���LI���1AkZj�|����nw@���#{�w��u���+��N<�D}��ih���d�W_}U�<��m����/~��3f�����A���~���lm���e����C�����-�I������[��y������q�=��;�?������=�������=��������}�P_����b���&O�<,�^L�T�4�0M�
C���!+d���^���kZ�d������z5v�Xr�!�2eJ��Yjkk��������k���2C����8q�f���Q�F���.Y�r��}�]������M�G���?~��O��P(������U


Z�z��n����n������X��M��3���?�_�0�L&��[o������M�$I�F���O}�Sr���z�l��A�-��u����.�4UXX���G������=�	�7��whv�j��WvG���y0X�UC{����b9�'i��N9��#�����^z�2���������/}I�������������������6(���UW�M}�S����IC��C�L��,Z�M���_��	}��I0I��
�0�cJ��j�)>�O'�p�N8��tW�e�����g?��{m��I��%ow��������q�7��w_�r�t�!���CIw�!SVV�3�<3�5�&��B�=��Vu�YfU����e���F�����l���N8�z���yww�������v�JY���������:���U�v���Ro�n�^)�����u���
�v������v�*i�U�J$�����2����H$by���Rn���2��������3f��������ZE�Q��g���UYy�m���/jm}��F��)	����m�#�J��d���W��cy��r)��UW�2�f���l���bZ�f�e�n{��r��������m���u�������?�l7!�-b�7,��zzZld���2R�o�%%}��Y[b��� �0��=��������h��2w�|�����jCn��5J&���B!g��^p��:��s5a�����6m�=�����>��������&���X��x�����d2�p��r\��P]�B����
�~]��Y�i:�v�{`����	�%I���<�.���p<S566Z���=z��m`�x<��9S���������W�������-Su��$�yG�{Z��gK���y��i�������;[Zl{��=0�%MS
6�{U��l��S�+U"����P($���~��������UVVf{Ncc�z�!%	��e��c���m���nm������}��H�a�_�j���v;�vWo�a��7��D�2�	��L���s�e^�e�{}}}Z�v�e
��-C���k��91�~�g��e��?��d���|R8|������,��zz�ld��I�4=�g����.���3��.������m���������Z�d���l�����$�4-�p8�pZ�@@���Saa��9���������Y��\.�j�oRN��l<�����L�9�l0���;�C��ln����[�� c1�������^���|�[�h�en9�����jC.�X���Wii��e 
5w�\������h�"��?�q��]rsG���Fm���`�h�V�����lL���S���ol���l���=0�5tY�U|���h�eL���MY�Thll�<
�d��@�9r����+��g{����p�B[����(�C���-k�k��:������=��6������u��"���V�i=�W�K��6�{�@u�:�BOO���_o���a��@j�����/TNN��9�=��-Z�`+ �������H�|�������N2C��Z�J��
�I]\���D��f�s��a��?���~��*��i&���`��5��6����l3�G�9s��n��9���?����;�
���Vu���zK-�D�S����D���f�x���:$�����]�j����0�����^��&�WwwD�D�ef����F��8*))q�
8c���:���d6�<�}�Q-[���V@����TM�M���Pgg�V����Nv,������Y�YO�ns���{`�����<^�qkLn���:��0�
��������B;h�l7}�t�}����i�z��m���u���kB�r�|����a��6����R�P�����Yk{c6{��a�np�*��a�v�[�yy�v�RYmHuuui��M�Y8v�
8o��:���m�D"����O---��G(t�JJ����.����V;����0t�����X�m������x�t������j~IR4�`���)��
�H�6cp����C��?�i�<�i����q�����`.UW�V����y"����K�HX��rR�7G�M���>���u�wM�N1���Zj���+�dr�1�����������u�ZfU�L�T4j�q/�Ie�!���hy���HEEE���4:��ct��G������?��l��`+ ;x�#T]s��m�wv-����8���1%A]^i=d(I7F6�������.���������������^�J��aiew�b6w�	����V��6�<���{v�{l���1C'�t�:� �s:;;U[[�m�������C4!�m�|���~��6���P�)���LI�hh�����@63C^�w�����4� �}�{���e��P����<�c���k�mO������5�:::l7G1�`_d�>������~{��m�4�|uuu9����_�����K��T�]+�+d��2���Jz�7n������2mn��*x�������1�i���c���u�{`X������+���h��2��C�x�S��"��m
�����r��s���)Sl���y�,X���^���0\���k���Y��d���.S"��p��*|^�nZ�m�������`#H�����k�����L����k���?�xAA��]<��"�l��~IR��z�^0X��N����hy|��iys	���v�����=��c;��~�z�{���3g��^������������l�f|P���B��]���_���@�--�����k7[���Z�����s�����SNN��a�h4�U�V���@�@@�G.;~��d2�x<���Nutt����Qnn������i������T����c��{Y6�g7���-(''G�f�����7�[������f=����9s�<��|��� M��]�\y�e�~��**>Tc���p����8Vo�w��k���~����={�T<�4���e�������[�����e�m��%���<|�4���f�;cqm��F��~�b���o���`�&���T{{����,�P(�l�P����3g�JKKm�Y�r�y�%�I��o|��5r�gl�e�~���e6��s�t{uH~��E6�����-��
�Y^^�������a?~���������a����6�
������`U**�Dcc�m��|(//O���Sqq��9


z��'�>�0UM��|�q�y2���u�)�r��`S�}��������6=������>����Iw2RNNNZ��$��0d7�767G%9u���|���c?��i"����Q�F)8[2\0��y�m�y��w��3�������"�T�"�������UZ��g��fVY��Ud��py�Vv�:WR,//O'NT8��#��z�]	���z�1b����&N����=I����R�np�*��$E�u�y0�=��L�����n����Xs���]w���������|>��?�xg����M���Xq�e�a�c**>T��~��f��_M����j��
�{�I]\��'?5Y>7��0<�!��'���Q�F�4M%����+N1C.�K�a�����a�np����:�
�y0X��NCm��������B���e ��5Js����w��Xl�`�$��������G�p; sU�Q��o����|���UP0C��4��
��u{uHg��\q����������S��/0Cn�;�5�$n/���DB���,���_��V��������TVRv��$����;V�g���c/���~Zo�������f��O�A>_�e�L����R���7���<]9a�m�����T�6�1���e���X�"i���h���=)�6�E"��c�����w�d�P(�/|�r���Z��O�����V@f��)�~5��0��yww��.�R�i�n�9_�(��K���K����z�&���R��cy<��R��U4j=����*7wT*�
�4m7��mv�������^�aX��i�����+nd����5y��l������u�9����0t��������O�
M�'�?d`xbp+uQ����|�\��h��2��m{������������m ������3������x�5559�
�l���j���m�+���Y��J�9���R����������
�v��`p+
�����~I���<��"���q�0TYY�l>��O���O��������^�[���V@�2C��������y2���K�Gn6���A]^9�6�1�Q�������6����.��{5����zz�7&e��^cc����c�*77��60<y��:���l���>-X�@����2���~5������{z��d��d�����n�L��[f��K��%w��a��=0l4����HZf������5��5�������p8�lf�?�xv�a�yww�jkk����`+ s���<�������e�|Y�����R��e�!����6g��!����=0l�wZo�3$M���[�O�|��)l6t6m�������=�;�a��SN�`{N4Umm����s��6n�,��Y�|���QG��6�V����i��s[:tg5���a7�7���|��vp� X-�0RYm�466Zw�\�����k\.��<�LM�>�����6��?_���62�a�>���C��i�kq�7����l1�����F����Z�����04�����^u�/I�vZ��U)�4��������zn����������'���i�&�s�=���s���<������\�\���w��,��L�t��`WM��|�e�o��Z}D�x��V�#���a;���W"����U�y0X��ZC&�H����2���������_��N���]�V��w����ld�`p��L��m��������\!>�K�W��wY�H,����d��!�������Z�g=8Q���s���e^�Ia���a���N����z��={����l��D"�����D�
]���_P�����+W^�m��u���)�>�b�8����mzpC���G��a�n��$���F�-3�;_~e�j
���F���G�����}�����9s4b��s�/_��{L����8��0CS�^������i�UWw�����-faVY��Ud��py�Vv�:W����l�Jr�*����U2��xKd7�WQQ!���p�w��7O�����,^�X����d���������k��[�r�,���ujX����^1C��Z�J��2�I&����z��3�q�:�'�����e���^�:���L"�Pss�e�n����B��7O������������[�)���S���7o�������F�����)�0,���^]�j�����a�����xU��d�O�]�-�l�[�v����-�P(�l�G�1Bs����g�IL�.\��_~��V@f;�<�)��m�j�����-Y;� O?�0�6����z�u������K&���zp�&�Wg�
����[��566Z�����q�n����2]x������=�?���-Z�`+ 3M�z���'[f��P]�7�mu��`_�(��K���K���7�`#��{ ����S�iZf����z����U^��TV2�H��xee��n��e`WQQ�Y�f�������z���ld�;O55����[�}}����2����r�n�>^����=��%
M�'��o��@�����<�5M���������@;��������2�B��H�&L����?_�a����c�i����2O ��M��6������'Y+�����J���~c[�~��h'���=���m�����u�l����T�2---J$�Y8v�
���M��g�m��������Z�z�s��4f�9;��|u�������F��.������MM��-�`#���=��l��~%�quvZo;
�RYk�D"�����3f��e��1C��~�m�H$t�}������V@��2��
�O��L3�����mv��`�
����|���tiC�6�������Y�4M��{����W+�����e�^cc���P($���s�n�z�>��������Z�`�6l��`+ ���>���^n��P\_l���+�L:�l ����*U�q[�b��|I�L�t��l��� �m��kk�2����[f��Q 0%���D,���
��-�u�1�������{{{5�|m����V@f����iS����n}Y��?:��Z����U������?��:�@6bpd�����=���:��������MU�!����d�z�L8v�
`gN<�D|���yWW�jkk�m�6[����,�;�6_��&����`#k���K�F����Z����6�m�Y���������xl7�����5d"���q���Q�F9[�S�a���O�~��g{��m�T[[���N��e���*��I����B}���v����cU�����MS_��(������V�i�q�:��i&�6X��2����hy<
����d�����>[S�L�=g��-Z�`�zz���������jn����c�V��K����8�����C����������-2M��f�W{���������&%��
�`p���W���������m���v����W(�=g��
���{���+d�����O��m����#�9����|��g�8����mz`�V������HhuO�eV�+��y�K����"����\�������Y�fi�8���5k���P<w��9F�:]��������h��WldmfY�>?��6����Z���`#���=���v��z�m��{���v����ill�<4r�H��vWnn�.��B�5���U�V���V"�p��9&O������T]�������Ng�n�R���k��$��Z}D�����d2�@�����<��v������SYk��
��B!��p��������sU\l��k��%z��'�L2��}�����jn����������
%���L��u{UH96���;{u��u����Y��fp�*�/CR���^�*���Fww�6l�`���a���F0��y�Z&I�������~Z�i�K�����>�����
5Fnq���
�t��1��_�n��[��+ �1�����^u��������-�`0�7�555�f�@�)..��y����g{�o��_|��R@Uz�*��h�G"��-/;W��W+J�����[K�hmo��F2�{ +%MSK�z-���O�h��s�������hy���@�������R��3G����������^{�5[�c����`�Mj��������H��a����5������	]���x�������=��"=1u'��Yu���h�e���WN����L�D,���a��l��;v�f��-��z�G��~�i�����2���UM�-�x�����oU}�J&�7h�����*e����m]�m$�����=���:{,��$M��+j3�����������M�,�p8�p�P�������\�%��'T_o�����rUM��m��m�V7��`#kGuE�h�����Z�u��L���J
6�{�r��v���SYkH�m���P(�X@�L�<Y��{��U�4���k��7����D����l�����y�6���P�-���LI�64ks,����{ +�m��
����I�����`0��-������2�������g�i�'�I=��jjjr��&N��

�������u6��2���Jy����X�._�,�4n 0���������v��$�U��4d�6���ag�R�S���N9��<���{���u�P��r�h��[��Y��x�����d���bS���w�*l��l���ZZl S0��������Y_�������1�zG���^�����-[,�P(�l�#�8����y,�������->�XUW��6����V����rzi��4n�m~���z����F2�{ ��m���op��zp/�NU�!���h��q����;N�~�m������Z���9�
H��#OP�������V���8����'�UU��2�7M]�Q4�p��tbpd��������F{=�����T��H�����#�-p�a:��St�����FU[[�h4�`3 �&L��
�������6��v�����.��Ezb������p3����:�]��{����m����p;�Je�!a�q�m{0���3�<SUU������T[[���n���r����f���X���6��_�d2�p��&���?S����ll��:�@:1��N�������v��$����4$������n��B!G����r�����&M�d{Nkk�,X���>�����Qu�ol�����r��ldmfY�>?��6����Z���`#����*�dR+��v6���3B�������"��m���;<�.���?���u������S�����1�8�*�n��Ys�6�>�`����
S��{-��dR_���7�t��1�����>���e�����`��He�����hy|������w�
 ��^�f�����2�s"������+�H8�H�p�
f�/Y���4;�h������B��y�����kV�s��1��J]�����04)��h���^0X��Z{�4M��=�������i���9r��9��/���>�d��]�7�\�T�����<�jq�eJ&�74;���<]9a�m�������v�
p�{ �4tZ�M���Hv���z�-�Ie���e�E�Q�,;��)���5w�\��SWW����2m6��Mn�h�T�$�z�]4Z�+�h'+_�(�gJ
l�o-]������8��=�U�l��~E;��>/�7�E"���a�����2��RXX�y��)����[o����cx�����]j������M�r��`.�����k��c������I�$�o����=�5L����W�+���<��|������7������;��iF���s��������+�h��E��+�L��G��K��H���
Y�����J����������G;p�{ k���W[<a�m������j�����g�����p8�l@�=z��������s.\���V[�cnUW�(�w�e�Htjq�eJ$�n6���A]Q9�6��i��El�	���Qo�mO�����e���VuuuYf�>���\�g�����=���E[�nu��>������Iv?���l����p������tha�efJ�FC�6�����R�t�7n�����D�f�E�Quuu)�+//O���5j�*++�5m���^�����^�/GAW\���,�` ��-������;�������?�|=��2M�����&�\������#4!�M�n��2_������p��Gx\��PU�-S������._��������M�v]V��\�R�������/j��EZ�v�n=?77W3f��a��SN9E���������� U���~uv-�i�Z���{v�{����=���i�t�9���G�='����Y5556�#�D�����������?V0X����m3.�yu��
}�.b��gk��li��*F9[@Jd���u��Wk����:u����
=��cjii�i�������7�|S��z��8���������#�<����t�`�lp/�����<���R�j�$�IE"�,N��������������mn�����h��5���0�����r��-�D�K��.U"��p��N+-�������[�^�vt;�@�d�����>���?^�&M�5�\�+V�3c�>$��===z��'t���k��1�������d��xB���e�}p��2��0����W6n���^���|�C9D'�x�m����{��G6lp��^�HUW�$�wuv.���8����'�UU��2�7M]�Q4n�I@�����x<��o�]�'O�y����_~�vPow��}�!���l��U����4q�D��5K����z@z-���i���d�^0X��RC��������VEE��m�������Gm����j�����e�����(.>T'|�6_��m��
�s�tGuH~����"=1�`y���g�N�t��i��?����jE"�Av�����R��1C����*++U^^�1c�(//O~�_�G===������[�����k�j���z����|�r�����������������Y�t�UWi��	��;S��cy<�vi�WZ���2����H$by���\999��d��|�3�����E�,���.����K_������-8���kj��H[���e�t�O�(?���>49��_N�+�������c��9f�����
��������K��{�
��>�+--�i���N8A'�p����W������^{M/����{�9�����^;�H��{���>�o����O~�����z]��l��~�t��i�,�`�&���J"�������d5�0t�i����SK�,�<g��m�?����/)8�p�a�T5�7zs�����0(O$����Rr�#r��ih���J�R[���f��h�ZT����>��
�t���y�t�1������^AA�.��b��?�����u��w���.���=I����������Z����ZZZt�����#��i���b1�p�
�>}�^~���~m�w�l��~E������U~^�6�|����+�8�B��d=����O>Y�����l��E,PO���U`��zKTS}��m�wu-���W9[�c��
S��{-��dR_���7�t�������xl��;�0�}��Z�~����?��N����zc���7��
���+Z�x�.��2�|�i���E/��BJ{��K���t�Zf5;��O�����j{��������Qyy��m����V(��F�
6��{�������5q�wm������;�h������B���I}\CW��^���V�BZ�>`��N9�����z���4o�<�|��t�����7����f]{��9rdZz��{�����4�}�^�eV���^�D"����/���l���r�4a�������f�������6�7~��5r��m���~����6���<�d���������v�
i�;��c����������=��t����PW^y�"�����Z��tW`�W��cy�%ij^���K,�L����jnn��B���e�������wzS���W���V"�p��,�p�����������^-��L�x����jy�>SR`�k����%�&i�{��'���/��CM������+��R�V��i����:������{�r���(����3ypo������������m������������s�,Y��\I����p��S���[d����Wj����4M��}�0�<}�F{�;�����I�d�:�=i�;������{d��:��C�]�}Z}��`^u���h�efn��OMe���D,�{�^�k�������y�����~��{�����z*�CK@��I`�o��������������J6�������G;�si�������~E���Y~�d������W-�WVV��v;�0�i�������=��7��/��`+�y_���'����_�h�R
vtqPWT���oj���mQ�S����9��X�eV��#Zg�����W����f��,
9[�O(--���s��k?���K/��W_u��,�0T5�W���-�d�Ouu�*�t��@�	����|������&m���-`�1�2Z���=I������f��^KK���e�n�W�3F�g�����=��g��[o��`+�Y99����VF�e������~"�4n�!���mU�*�Xoa����K��LcG���=���m�F�xLnP"a�%��-��|>���9��/������3�r��8��'�P]��F[`8((�_�'��6���	�]w���+�yu��
����Q�iM����.�@F���	�����'
����^������� Ca��I:���d��9�<���/_�`+�Y�����T�|��km7;;���"��q#m�_�^�w;�l`w�+��~�i}��_���������c��e�]�7�x#���.���
�m/���� �'?���X__���]k���a���UUUU:���l�d2�|P�H��R���P������������]�x<�p��~6q��>���4uqCD�x��VvE������O�������O|^GG�N=�T�~����_��7�|S��-�+���?��:��#u�E���������dR+����������T��+k��Q2����8������o������{m��l��U���2�e����%K,�4n�!�����B��le�����ek������{���t����_�������O��|>�;� �H��SN���>+�4w\�d����ij��:���������v���^�m�A���e��^cc�����<���:���;���u������XL,��M��+8� X�)����7m��Z�.p��`��}���q�����u���6�+2~p��G���w_|�'>������x�
I���>�0Ms��^xAW^i�H������.C�������@9�B��\6�TH���;NGq�m������Zm��`��q�.��Q���W��ut,v��`_(+����m�/_��]����G�_�p�B�!i��Yg����;;;����f�s��C%%%:���5~��A�n�����@��
�M�������y�@U�*����^�_��2���`;�0t��'���=���S���WGG���g����~!�?d��fL��.S���o�n�R���k��$���>��D��f�d���������1C�F���sz��[>���/~��7��W_Ucc�}�Q����xN�����|`o�wZo
���Z��|��)Le�=���������B!g���a��3�TU���{[[�������n���x����V�\��q��k�d�l��9!�q����r>r���j������9�
����[�b��_��3f|�s���~I�������3���H.��_��>�9�r�-;�1Ms��@f0M�v�^u��hg�eV���^���4r�H��0�����?�yM�4�����V-X�@�����@6�4e��l���g���n�
Y8� O?�8�6�k�f�����Ble��^SS���;���$�b1���K2>r���}�{��^t�E?~���Z�~�^�Cim_�������{��{<��D,�����_H���.�`���?n��u��������`3�c�����g��+W��m�9�h�����������QKo��F�d������%m��#I#F����o������O�<Yp����a��SO���%i���{��m{�4�����
�Y�n������
������m���z5{�l�c�����I>���������3C��^���	��i����2���;[�#��M��k��c�o�'tIC��I�2������������n���������a:���vz~u������w�!H���
�W��%��d�����=I
�B��`W�|>��3G#G��=g��z��G�L&l������j~/��g����U�����Fz=���Rv;������F�o�=����?�q"�����-�����c�=v���5J��!?I�F�{�=�����_�h�e��[�\���A:�
������2����|��7OEEE�������'�L��
��TM�r�m�y�sZ�����ptqPWT���oj���m��H���wtt����������>z�����x��
 }���>u��3t��$566Z�����I


4o��A?����~[�>�,�{v��9Oee���+W�J����`���*�a����)�
M��;[
�������\��j�*�s����i������JKKw���m�&��
}~�o��!�O(���v�q/������N���Zf�P��2������;w�g~��W���/;�
H=�04m�5���l��f\��.S���>�q�CU��<n�|c,�o.iR��Z�q=�7e���.\h{���>����a���������6�������lR��f��$M������2���{v����7 ��=Zs������=�����o��`+ ���<���*��zp��o���'�L:��C�|^�8��6~kTZc}	����{����\��M��k����K�:/�H�����a;���p�	���?�������5�[�]����n��b�m����{�H��xII�
�-�7n�f��%��z��$���������\)�����6��|����|���;��H�o�H�������n����@ ���;N�i�0%�I��7O�������>��x���3�8�?�;��#�0v<�8q�PU{�>j�q�:�WgW�e��S����T��cv�B���E�K�pX\p����X��?��%K�8�
H�1c>�1c���W�������`��~6q��>���4uq}D�x��V��+��$i��y;~m��z�-M�:U_|����Jw�q��/�c��a:���4r��]�%���C������yyy��!�;����z�,�0��)�m���[�Zf�p��6���S���s���M��C=�U�V9�
H��S~���)��i&TW�b�-�������!�����������i�7�M?�7w�\���~;�����V�y�������p��A���?������O���_�����>x��3���]{6���>������V����N7�'	���jnnv��Zn�_���^nw�e���A�
��i&n��Iy>���q�����u���JZ?��r�4�|J�>d��v��>�]�����:��O��=��$��G}�PW{`uw�z��[@�������Y��566Z/--U0t�
C����I'�d������{���
l�V~�DM���|�����t����BY��]l��x�Z-��u��o���=I�������j��)��>����/��~��O�|k���O<1`����NKMy�[�;����
i��(�z�/���=������:J�s�m�������k����R���,�;�6_��F����`����
S��{-��dR�G��H�f@`_��{�t�A����Smm��;�<}�S���I�t������/��o��o�q�0��[o�U�Db����#t�G��K��npo�����z���	����Z{���M��m������mH�O��:��Cl���.��������R@�M��S�m�����P_,}��[�W��c�s���^]�j����}K��I�����9s���������-[�W_}U7�x�f�������?�����v|466���H�:�����_����^ P�������Il��a���N����o{NGG�jkk����`3 u�n����Unw�2��6����2����>4#���Lc���v�����\!`�U�{C%??_���;>����]	������|�����{��TV�cv�{�G�V^^��mH����}�s�6m��9[�n������c���6yyaM��?����W������jy�NQ`�k����9��w���{ 3����1����<��Za������GL������ ��n��=���~���q�������9�H���?�q������7k��Wl4�a�i�x�ys,�m������x�t�0�1�2FCg�mr��4�Y&�m��E�����{��*''G3g�Tyy��9---z���[��f��+�{?j���[��ku��G��zt[�x6�������G;��@�����<>������2s������A8�m{�a�����68'77W^x�F�m{������C)����������[�v,�Xl������	��*��J���75m����������=�1���~uF,�``����Z{�npo��1��|��Y~�_s��UII��9K�.���?�d2�`3 5��*U5�����u�n���F�}'T��
�-3S�%
Mj��;[
��cg�{�����`�&���H2�T$������@*��7O�����{z���d������5�T�����#���e��6��2���Jy�oz�)��K����#0$�rp���_���s�y���2e�F����\���=��x<������&�Z��k�M����k�eV���immUww�e
��-@i��y����=��7��/��`+ u&O��
������������v��q>�n�6�6~kTZ��`#`������zH��O�QG����N�����r�Jm��Y���2Ms�>@�,��U�����&%�1�,�-��\.�o�4����#5w�\�������K/��W^q��.W�jjn��c�i�����.W2w���N--��7�6����z���&v]V���q]p�����e��
�3c�?@��u�X����o������I���G"����q���th��j��1������c{���>���z��V@j����~�m��m�V7��\!?�8V��e�o���>�h<�p+`x����s�=W=������n�c����fpoj�O=���Y 0E.�7��v[2������� ��?^3g�����=��'�����l�Fi������yS��y�������;�C�s[�h��7��/[������Iw�O����MO<����x\4T^^�<P�PH�`p�w���.j=�W�+���SYi�l��A����Y(r�f���:��s�����v ��GUnn��L��p;`hM��=m���::�����Cy\>�Xg���Iy>�rr�._�l�?��]��5k����C��]s�5;~��E}'�t����Zz������i�j������U��%�Y0X��Z{�n����VEE��e�@UUU���>��{�2O&�z��u����Y���������L������m���\�:�^�\���e�z�-��7�Y�?^�V�kJ���f@�s����,^�X���2C�i�0]r�%z����`Y�SG<i�M�iW"�m�e�����F��l��p�:���l�x<����Ok��u�0���q����m�m��Z���6�0�0�\a��2�I&uq}D=	����e������;�q(��7���2 e:{m�q����
��@��TU�#�DBMMM�Y(r�����	'�`��b1-X�@�6mr�0�F�������m��|�6o~��F<n�^R�aX�
]��z�:�[�/��6n�����a�_��j��:{,�W��2�[fyy�v�RYk��[�N�X�2��� �{��:��#l������j�������	�Qa��l������'}&g����cl���n�?[��+=��L&%I�iJ��O���: El��~E;,�`�:���H$�<����q��9[�,`�N>�d}�S�M������UGG������r������[���6��S���M ����R�8��6���5Z���~@������#Gx�����& ��m�|�F�-�L�kll�<^QQ!���p��a:��3T]m�����]������r�0�|�1����m����V���S�0�4m���9���xB��7)�4nd����������!I��iS:����j���1���x�z�N0X��Z�-�����2��� ��\.�s�9�<y��9�7o������`3`h�q�*+�n�7���Z[�u��@#��V5^�M���K��lp���2zp�����#v<~������B���=I�4W�f���T��ck��U<�����y<�������=g��������Y��`B�
j�7,��zz�8�h�����Vh�m~s�F-l�:��N=��v�5o�<��)�4���[�[w@v���+���}�2����	���nkll�<��z5f������^�f������MMMz��m��L�ryTS}�rrJ,�x�Cuu�T2���oW����|���tIC�Zc����LF�I��C����0m��MW]uU�+�!d�qoz�O����Y0P��J{�np���Rn���6d/���9s��������+W��GU2�t�0trsG���FI�e�}_+V^�l�����VU�"����M��._���i:��?�WZZ�����2��2�|�����;��
��{��:�u�Y0�Y�{���jii������m�~����;w����l������O>)��!d�%G+��m���7m���������i�m���Fu��V�%��$��������g��n���K.�D_���l/��!�4����2������e�i�{k��Q"����`�h��y
������z��g�C����������@��M6���B��F���X�N�tt;���t�U_��
�4g��[�N������{t�I'��c���I�T\\����=~�c�=v�O���O�I��+�f�m��i�{�����}>�F��p������7Ow�u�zz������k��|:���n�=�p���&����b���D���/�A������44�~:q����e�);nJ�G��!S�����\Y3�'I���y�}�����M�����SO�������m��q���

�J���F�k�E���+'�(��v���^(�����X�F���9s����M�X���^xA���:�p��e@���-Uu��z���$%��h�V��M�z���$��.�^]����\�����zc���5�cU��HCC 3e����������t����U�a�0��9d�YV[;$ir�O��:�,�Je������u��F�p8�p��q��i����x��?��SO��w�q�0tJJ�T8�M�|�����I
4)��_N.������6lu����bpo��5:�����?�A�x|���|{���n�^u��h��2�SYi�577+��yD��q�P(�.�`��l�q5448�
:��%*)>�6_��Juw[ozv�e�:ot�m~��-��u���2~p���W��~��,Y"�4��i��f�qo�?�����Y0�Y�{���O���i��Q�`x�2e�>������i������+l
�p���w�z��C&�Z\w���������+��Z�=IS�G�����������'����U__?`3�i�*..�g��<P���
����IcS�;Zc�j��-��a=�'I�`M�*��H$by<������Q__��x�	�<�L������y�4~�x��{��������;s$
���\��+���i�p��������C:�����VCW��^�N�O)OC; �d��^,�m��6`�����5�\�o���z���
2_���=I�hP��q�w�rsKSWj7���h�z�!�P(�l�!t�z{{����Z��x\��s����/j��1��Nq�a�8�[Z������u����0����p��f����c����,���n�1�}����b@�q���������e���C{�a�/��~��2�@���Z���z����eV���nkjj�i�iD��q��QG�c�=�6��������y�f[C���b��c�/]v���V9�h����������������������{uuu;~m�;�0��;7���Pi���<^�+���2mp/�X�1b��e��p�	:��Cm���n��������R�0���~���2�<�����K�H�o�N%�0t���*��X���	]R��x��&�� �����$i�&���:+�u����7=����f�� ��-���a��p�=�a��SO��3l����Pmm�:;;l�=�w�j�o�a�-����Z��j�[}h��������]���.�&���N@&��������C�Pz��!��HjU�����{������TU�m]]]��q�e�{��r�t�Ygi��i��l��U���WOOz��{���`M���|���k��Gl4�Q�A}+4�6��i�^�u��92zp���l��d2��&`(-��U����'�[��)Vn����=MMM�Y8v�	p��:���4a��s6n��{��G}}}6�^���h���m���~������oW����|�����%Mj��;[
�=�7c�I�a��u����"
���n�.CE��Xf�@���������xQQ����n<�f�����r�sZZZt������!"d�p���7�7�H&{TWw��n��m�q���R��e�)��K��4m��S=�WSS��������4�C��fpoZ�_�]��Y0X��J��np/
9[���zu��j�����466���R"�p��wrr��_�-2�e���BK��Lf�������q�x����Q�����F@�e���$]r�%2MS�i���������]	�%��{U�9��Ze������[���6o�l���a��������;w�F�a{��e����C�d��f��),��&N��m�a��Z��!
tji���q#m�_�^�w:��H������+4y�d����~}��_��:��i�������&���|&
�E"���=�/h���*((�=����������m(�����O#G�h�/[�suv.s��@?�8V5�e7���#���v	�}C��������Saa�L��s�=�9s���������{c�&��������������T��-���=KJJv: �STT�y��)??���E�����w��w�P��_��g�'�}Z\w���N��m�s�t{u����?rl���{��00�}B��I�������/���R�i��������_�w� �4�l�����;����*F��m��c��e����;w�|>��9/���.\�`+`������VF�e���ZK��4m�q��|���r���M��o�V��Iw�Or�5����9���?����������u�����/����I�&���X99�-�����gCQ�D���^��U��=�,�Ne��������6���=2OYY�.��B�����������{N>�O|����=SX0C�&�@+V\g�o�������q�n��e�z�-��6Z�o�ry�.���|��Z �e���UW]%�0���i�������>�g�}v�_��=R�����xu~��6/�������D"�Y(r��u�9s����^%	�s�|�I���j���s��g*�����Ejm}�2_���P0X�p��?��~J����RcOlP��4�����u�����YJYse�i�>���1(�����{���2��e�I�-����*8����'����ts��z��G�l�2[{�0M�v�|�
�<��iq�����7�.�q����rl~�-���U+�:�
pN��}0���������������7$)�5��].���&���.3M�v�^8v��m��O��>�9��4M=������@���)�~5��0��yOO��,�2m7��?���Nc��m������B���bpo(6��m��k��������<L���IU������m��Yf��8��v�i�y"��}�����[{��`?M��c�|��j��{l4�W�Ku�����K�����f?��L&�H$��R��;{,�z��w��2�SYi��l�Nee��M��8�����O�6��bZ�`�6n��`+`�����Q�N�����N�:}�0�4m���9���xB_���?���0�d��>����}��Zj��U���[���������p�7�9�y���yoo������[�:�
�3�ah�����o}3	���n�e���7�n���?TU�� ����Md����Tcp8�npo��W�d�e�)�L�T$������e��L��+.��
��� mt:���t�A��������Zm����f���x�����r���yOo���0m���,���h�����zykz�T`p8"�4����2�-�F���SYk�m��Y����Y(r�v�C��=Q��+zc�\T��[��(zc�Z��X����CW����0}���UMM��9����?�������Vi�������O�����F}��L��[f��o,iRk���R@�0����W}I���K,������Me�]���hy�0UVV:�Vz�n��������V��5�[�.�&���P��vE_\��7��M�����[���\.��9�M�l����7k������	�I���������W���::�w���<.C�UU�����7�����f%���a��=���h��q�!��}�2�SYi�D"��c�����s�Ht�k�}K���z�"���X�C[������*��v�W��n]p�;�_�~����^�b1���0M�z������i�kq�e����p������i�x����Q�����F@j0�Q�i��fr�O�]�-�L�K&����a������.m��m���ww�����7���
]C��mrrr4k�,�;�����f=������6v��PM��m�W����a��e�i��)#��������^�w:�l=��#:�7�M�'�HXKe����M���c�?
9[;��w��O�+�14���1m��}��`���4g�������r�J=��#J&�6v_00MS�\e�o��������B���cU�[fqS��>��x��V��I����O?����#mmm�����d�:�����nS�K�����
�H����������-IR��_�����3�����Z�Z�DW��~^@�������sU\\l{NCC��x��g����������3�N!	!d�!A-n�j]u�lu���vi���������-�Z����Z[A�UT@!��� H��g^�?���\W�\Y��������|s���p�r���<;d����5a�E��=���e�mjm]�\����\���PIn��'�{B�V�v��`�����O?]��z��}���8�~	�����)S���^�8�h�������&���\ON�"��z��*++-�������NIj���A���q���Z��������Z�t������k����;ME����?QR�T��iF�a�u
�[�
��&%������g�[�H]�����3$�{���K/�������?�&�uvv�����&O���|�;jmm�H�xv��$)7h}��+���b���������75��]�I��t�u
���E�0�eddh��%JL����o��U�V9�
8pnw����%���g�'�S����i�N����L]�c?��{�k�~g�����1d�{����y�y��:�����SO)�I�-[������TPP��n�Iuuu�5�ARf��7������Z ex4����)Z����NIj_�����r�8��+;;[K�,p����+��o8�
8p))�5s��l�{�����u0Q_�N�Wq�������+�����B�`
I����^*�4e�$�4M�������5i�$}�;��;�X_�?������?�A'�t�f���_��Wjnn��m��	:��������qof��H���6\&��M�s�����w6���PU�#�
U�)����c����<]v�e�x<�{����Z�v����7a��0�B���m�TK��4�xK��uI����y��m�����p8��I���+���/k��Y��v��������?�&O��k��VO<�������������o��[o��'����\}�+_���+e�f�,n�[7�p�***t����c0��5�M�4�~O 0;^qHee����I���zN��u
��]g������h�"�\�����UYY����7c���<��f�Qm(�^�P����:$��[�������Q���8���og.�����x@��������>
|��	7��s����IRAA�9�������P'NTnn�������(�����uww���I������UEE���_���r����f��8�a�0����-�O~�M�f}!�����v-k��n�KL,���g���FU]]mY+..v8
$)T�����;{<��5}�t���z���-��i��'�������SN��;QsJ���>O�hW�z0�K��7��C�a8������Js���h=a����:45I�|'��5�I{��}��_��?�y�s�=��o~���O���N����USS���{�������>l����r�t�����[n���z��|����lj�k-����:;w�T8�����<�4����1C;:�Le�m���
�z��g-��XL�>���,Y���B���'9y�f�����o��76�����UTt����~^w����V�v�����F����JO��&���3o��:�����7��
m��M��/���.�4{/������e�<)))���kTQQ�'�x��=YYG��z���@����@�4���[e��D@�����<���FevG�=fwDf(��1�����SN9���D���k�������s�7a�m}��_��y���>4���=�m?�|��K����h&�`���x<}�s������~�z�p�
����o�>�^�W��~�V�X���w��;���)S���0*�5��Lr+���
��{v�{�x�tp��dF�}o��q#Cs\��u�1�h����`0��zH


����?PJ�L�jL��W(���L8&#E�(����Y�[�6�;�8p��q��JJJ��_�B���z��wu������O��q�x�������su�UW����Rcc���y]z��JHH��
��f��7��a�=�������"���o�nY+..v8
$�pCs\��0��x��:��#m�]]]Z�l����L�?�;AsJ+�;��
�������L�Fa��J��fJ���j5������3g���3G��_�%I����������*������M]]]�F�JLLTrr����UXX���'k��Y���C�*{b��r���"Y7�%����e�3�~���U$����74�[F�Gf���K\�����s;v<��a�N=�T�A�[��rO{{��/_�/~��
��CRR�f������nYoj�����Qq�����q�gv�Nz�B����������X�{��������q*((�`�����Y�&F�[�%����*++-��~�rssNio��ob��[Z;�ob���{k.�Kg�u����6n�h����I��/���%%%9���������Z;v<lY�Vy����Pf��'��|�}V�>�������v=���d�s��5�����f��!)��������WUUe�^XX(��	lC�����"�$�#�v�u�h��)�{����b�
�A��o���+�bwSY��68���f���|��z����J���D���q�M�M�^Q�GF���6�B���o�nY+..v8
>*�����Pg��<�.��bM�4�v��;����*;��?n�_��w��N���B{TV�u�f��d{�<%OsR-kI����n1%��{ n����{l�g84�m��]�X��VTT�l���M��(����Ze��c��\>�O�]v�rssm�TVV���W4:4�O�@���4k������7TYy���>�w�t_I����e�qy�P�8q�����=7v�{��:�u�/K>_v<#����J����D���8�8�~��`kyz��VlT�;��1#Wbb�/^�q���������O?m{�`(�d����%���������&�����:=����7Y�y�'C��=-��j{�����&��@�D�a�3�~����\/**�����PK����C�;v��
��}�k�;&`�JII���K���f�g���z�����ai���(�cS5UV�
�����E���0'���hB��t�L���s�=���������x��o�`P;v���9����"W����E��j��=������0���4-]�T����{�~�m����t0�\.����%�'`Y��������f"����59�oY.}��^�Q&Z`��������r=��RR�:�Z P�D�����v�Mqq��i`�����/��H�8w�����U��Oe�v0�0�q��i��%JHH�����[����������8I�f�f[oiyS��w8��C)��+)��fRwEwH?�b}#�I4����k�����%�R 0�����,����5~�xg�`@��de_q��{P����S��|�c��WOE�v��V=[[����+77W������zm������[o��`*`�d�?U�&}��^U}�_q0��	$��)y��?�l�s�-�,�����qo�{������������_*++-����e�L���qg&H�O���x�x�\?Oi�+�����8��X{H{�w�Z�Q-3f=�I�4i�.��R������?���{�=S�g���Rj��6USe�7�����L�<?K��j[�fE�j��&��q�p�TEg�em���r=(�����n��Y_x\TT�l���wv�������S5�%w�L���NC���(���J��=�7�R�?k����m��p����'���.�\������M�L����Si�]�x�,��p�6�}]�����,�0t���x��b�"1]]^�07Y��q�-]=
���N�m���3�~�����;�����j�����|�iR��.�Np�?5]�')����}��J������ne.���E�e�>eU�i�k����`_
`�9s��=�\��i���_��m��9
���5{�/l���ok��_;��C�|��8[���o�u��U�N�E�te���^C��~��6�*++-�SSS�����C�{}������R����+Q�%Z;�I��h���M
|�D�/���S���M��1���(����Nxo�+��?����m2#��z=����C�g�a[�F�z��GT[k����Y'���r�zu�����e}h~ Q�
�������W��L�E�tv�{S$�B��@��m�+**�a��@L�T����E����'J��P�-E��bn���w|���>L�GO����Ww���wi��;����u�I'�����z�!�����T��M�|��������oTO�N}��`��Ez,k��k6V�!v6�<����m���X����JJ*�_��������z�Zqq��i�/=�
����%���'�?��3�.e�3U�����po��C��\���5`�8���t�����{zz�l�2566:�
���Ui��z3,��H�6l�N���
rnI_����X��^����5�����0����i�*���vQ(��v))�dC{ZRUUe[�qo����gH��q;nbi�r��+_A`�}f0���7����2����.�0t��'���������e�������d���4{�/m��mk�u�/L��3����7�������sc8��=0�v�"jG,k��,���8&�?���M����JOOw6�jU�����8{���Iq=�'3A��8D���n�|s���^�p��t@��e�>���j��9�{Z[[�|�ruvv:�X��TXx�m�f�jhx��D:4����������Sk���g��UYG�m-��5���a�������}U�m-p�$G2n��N/V��J�J��7��K�w�U���d��#�#���������������g��/_������P�\�
��}��^��[���?g����8NsR-kS���Zm&" �h����q/�+�����@�4������M����5�����N�ll������7)�h�����~��S��g�cj~|���\�X�z"%`lr������TTTd�g��]z���
��������vy����H�M��S,�����e���B%��?���	�[������=0�����:,�].�����3�>UUU�������>���S���(�3��1���u
��k�B;��>�&���K/�T'N��SSS�?����Dh�����U��_�����]m�r��������6=���L}����0Xh����q���n�JI�)���H�TYYi�>n�8���:�v"�=�z������"��tg}��2�zR����S}����V�=����&�z��~}�s�Svv����[���'�P4u0`o���UTt�m}{�U_�w}���L]��a[���ZUt�8�c
�{`�tF�����M��Y�%���_�&�;�xu�����0�1����4e_?O	33�5���65.��XW��p�a/))IK�,QF�}��������*��Gp������~�m}�����]�`��:=_�������+��������=0h*:zd7?,��5��@��6���������F�������]�5��%�f9���;��q����3'K���	{�����
V�9�0�-]�T�@�v��u������������������G"�Z��Z�b�7����[���gs��M�=�����XA�4e����I.i�i=ec�'�UVV�������u��Sf�zJ��|�����Q�a(p�De_u���	����p��j{y��
)##CK�.URR���7�|S+W�t.0�?[�%��d}N���A�7���P���@�n��g[_��Q���8c�g����?���=���Vjj����������R��?_�g���1��:z,���{�����d��L�w�UUUY�ggg+99��0�F���:��+�S����?_~@9��U��������1���U
nkQ��r|��K���������?�I�����U�V)!!AG}�����23�Uq�������^�c���?����:�L���,��������F�U��w8F�a���r�J��T���t�����+�PAA���`$+k���W��m���<M.��]k�������b���N��]2�#���qex��iW�G���T���jyv���@I
nn��;�(��J���`J�p�����.�L��/W$b�o����w��~��7��t@������m57�nY����
f+)��sm�0���:��
����m���.��Ss��;�&9`��W9[0Ms����;�����z���6m�n��V�_"#R�4U�i��7)��r=(�g�}jjjR[������"g��������5#���#sNtp�P��\e�0y����k�6���U2��'U����B]|��r��?�y��gUVV�`*��a�UR��|�-��h��o�N����x����Y�������_TZOy��i��h��a�_���4M��a}�{�����n{g{�WuwH�Q�Ib9�7-���q�n��D��p���^���e-��<����>������0%�3�FSjy�~��"-�_�^�M��.�@�a=	�4M=����y�������,���.��;:��y�O���c2R��"�?�US�W��L��l�7�-X�@,����p�B%&&�������5u�Tq�:��cUZZ�	&�N��5k�.\�c�=V�f�RFF�e3�i�z��u��W;����:�����b�s�^UU����	��s�yf�T�+��E���c��
4H\>�2/���Kf�����n��;������t�����Dg�u�m=��������LX��8J���������v�����>�����lY3%]��Z
����0*
����+W���_�SO=�@ ����M�ij������~�������]Z�z�^}�U���������={��s���K.����m���k����j������a�������_����UXX����4M=��z�������]�^�/�YM3H��P0M�v�������FE������;�s8��J:,[9���wb�����������[eF��Z��y����SO��G"=�����s���kEEW+3�x�������s����r���]���
�C]��F���8P��qO����t�q������aJJJ��w����r�t�M*))��m}�Mff��8�=�����a�>��OK����u�%�������;u�T}��_WEE�����>S�L��O����PF0����n�IaIIS�v'�3�����iY+..v8
>�4M���n]4����
'��De_u�~M�x}���}W�=��c��G�������z�!5448�
��0\*��+�}9��h�S6\�h��s�����U`[��]�n��>���w�����\�i*%%E���t�5��0�z�)S�����-Z$i���_��������zu��w��+��i���y��7��;���`����gn�\O
��3�>UUUY�����Bg�����V�k;,k����g\��������~��[:[�$��{�;:T�Zu��w(`8:��t��G������l�2577;�
������;d�7����������T{������g���m���Y�����q������+%��������;���~>���?��O�2e��P,�7]�w�y����������}lF��pD;�a����u�{`��*++-�'N�(���p|\�*�i{��mk#Y��q��n�|���3CQ5=Z����W,u(`81C��z�;�0�=���Z�l�����X�H��&�����1��=�`�}J���X�"bJW�U�-����o������������W�����������~o����[���O����z���}����W_}����n��$M�n�\���X,f;q�����,�/T�����Z����R�
� O�_��z�'N��1\�������Z�w1	�"�����:K�f���������������d@��_��q'��7U�������?~�K��*�m�iMOH7Vl����/��q���Z����a2C��s��=�9��#�������3�X�;��3z��4Mm��u�20Z��4���c�P�e-%ev<#
���^�������N��k_Uk[,��`��a�
��Z��/����po��[��N����� ���.�@S�L��S__�+V(:���0\�=���s-��X�6l�V���M�S�t�t����o��u�����{����$�^�<c��A{���tegg�>������R%&&�>nj�B>n�M��To������y���
5���J�u���I�Fc�p����
{,k���|�C�s���i��~���������-jzd�b=G������/�X�{v���GyD�p��d@_>_�JK��ax,����UQ�CgC���r3uQn�m���kU���`"���q���������A}���/���}���0��������yP30�wX_�Z�j��@�$�q���q/??_>���4���Wj%��q�&�NK+����X�����y������s�B���>|>�.��2��ZO3����*��/Q4u0�Wz���2�F�z��'���q}��i������u�L]QV��h��T��u�^WWW��{�XO_9X�������m=)H�RS?�����?�W(��6�'&��Y�e�^4Uu�uCaqq��i�Q���:��mY�d')a����a�0\�RO���W*w�����6����w����[`�IHH��%K��|����}=��S��h>��)�t���N��WT�@&�+���}%����(bSg�~�e���0�
���.6�`���
��T__��x��q�{?�����4h
�t�i���g�>��{�v�R0����7��_�!E���e��������*���J�m�*I��j}~��T�hg��p�a!99YK�,QZZ���
6��^��C�0���s%$L���b=Z��ZE"�'�	$���y��e;�l}�s�0�
�����/�1MSO?������<���?��"�	&��mjj������A9>�EY���Z�a*O�)����4���J�u�����|������:�������J:l����'W�W���R��S$����=��T���:�0���i���JNN�����o���^r0�������;e^�zW�VUT�2$
�_���S����o��QM���@����{Gy�\�#����W���'~���6��'?�a2MS�a��c���[__���I{�^XX����h���q���)�"����\�|Y��e��qo��I�x<��:�����AC���2�����Q�a(��<e_}�<Y�����������R����`�7n��.]����=����^}�US}����So������v�=�`������
4�o�T�����j�9��>�+������?����4M�r�-z��g�9{zzt���k��]}�/��B��k����x��i}lF�r���b�n�^i<�(������V\\�p|�G������+���O�:�hd�MLQ���)in��M�����������	r999Z�x��^��#I��?����W;�
�kR�4~�)�������;69�h�L�Gw�*������.���zZ4��a��'I���7z��0�B!-Z�H�������s@����o������/��g������Z~�/� I2��w�>�����0����2�����2��@�$���c���a�ZQQ��a������uX����'���p�����(c�te\8]�w�S���V��c�z*�Jj������K�v��[��/��w�u0�!�04k�mJH�dY������E"'���H�7��o qWM�V5�;�#��o�;���u��g�6���p8�[o�U�&M���^����o��{w���D"z��wu���k���:��c��{��>�$�\.�w�}����bz���dF����0r�
���Z�&D�/�����J�u����':��dFM��b=m����|t���F�0�|D����+on��{c�a�y�L-���9�0�&O���.���g���Ok�&�������jN��2�e���R�6}���yN�FQ��NO������X����
(�a��'I��4g��>�{�i���Q��s��<�L���)11Q���*((PFF�4o�<]}������-�4{����)���{��W����<�3�<��������=[S�Lq�u0�mh���'I���\�����*�����'� ~��7(�d=E9y����'���I���aJ>�~2�:V�������]f�����;��n������h��m�>��z��M��m}w�s�����6�=�P��B]��F�!h*��7"�233���K�~x����>�
����Wmm�Z[[����?�=^�W��{�.��r��z�^��g?�����~��K`D(��n������~�^o����x���USScY+..v8
��M�+k��nC)�3�@^�2�����f�����i��;��{�����!���~����h4�GyD��ow0����K��}�m}��������D{�%�t�����M��w{���0R���=I7n��x�
���?�������?_4���7Oo�������x�3�<S7�tS��)����K`���a=qo�k��z P"�0��Vmm����e�����0�$������N�Z�a����N4z$2^9���wR`�}fOD�mT��[d�c��O}�S:���l��pX+V���]�L�e�f��%&Z7��b!��p�"�v��I�d��+�Y���m��5�����FL��$��n�r�-��e�����)''��D���$��SO��O?���Wk��9C�j��m��c�[����3���*�u���	&8����6})�0��0��'3A�W����\��F���Y�pC��C�����q�g[�����������`*`/�'�9�������ww�h����~����O����D�Z���(�V[��F!�<C�`����'?��~��k���z��7�~�z566���Y�`Piii�����I�4�|y��JOO�������u-ky�����@I<#
����r���H.�������nS�����0{���I'��K�gL�r���R�Xg�vo��S�w�U�9S�|x��)N;���������~������e���K_�����N��.(��i7���f�z}��T�c�&�/u4�����%E�������T��'�+�����C6e���l���a�={�f��=�Qs6u��n�E��,�S��q/
�����VTT�lH`�����33��n��P���v����/�+��E��L���v0%�)�a��3�P0����-����j��e�������b���w�Z������,��7���RSj�!���������u����_�[�0#����s4�'����R��m��dD�����=��&�;�����b��bHRqq��i�����M�5��4�RN46�����9
�T �cL��z��v�B;;�	p��������3f��ill�C=��n��> ^��������"��i��~�u
��'8��E���(7����������������bO�\��)%2�}t�IUU��zbb�����
����~(I����s�0\��>S�������po��[���S�v�4��kF2���/�p����K?��B������7��S�[�\~�zO�vm�t�����:-_��su�L]QV�����C0v��J�M�^���r=(�g�UVVZ����t�I��u�k��y'$�?-��@cT��t�\7W	3���H�"�Z������8�(���K.�D'N���}�v���V$��pV 0K���b[ohxQ��v0�^���/)����$�=�����p������LS��=��������@i<#�������;-kM�A|t��C�YOE	�0i��2�E���}�DigK����woh��;�(X��P:���~�>���
8�x���z��'�FLHyy+7��zm��r��L���@�n��g[_��Q���8��{��Uu���Y�
L��vC5q���F�i�(F�����au���������,��p
,���+�;�?��hKP
����U�e�4_F���$-Y�D��X7n��g�}V���y �ah���()i�e�4#JH\&���`��<1K��K���PQ������0�x�:�'�c�������U�p�=��)����n�u�LMR�inw�������Ze�u#aJJ���hsR��;e��/�,���f��P��*��yj~r������3���*�lmU���r���	��@ ��K���T[����u��������NcR.��$kN�]z��������r5+!�Q�t��\�a��Y:��
��.�����j==w����p��g�5����������w�[�N����a(��s0���4�Mt��	�[OI�)�p�;�%�����".6wP,U��;-k�����8��J�(����\�K-�n�"�S���7k�k�y�%LMw.$ �222�d�=�����������o*!!A'�x���0�������?��M7Y�=�2y�+%}��\�^���]��n��-*�i��/*���)y����s
u���������N����������[���2Ms�������Wd�X�%��c���K�v���;�fl�\�Kf��MR��(�;bNKG5�0�r�em�<��ki����b��(��0��?^�/������j�*��������5!�|������;�9�����o���������v`8WH744��#���w��H$��hg��|�c7q//��r=�R�8����mk4�9�����j�e����r��a_|��}�\%��I������j���i
:����<]v�e�x<�{^|�E���;��3~���i�5��i��o+jr8������lY3%]��Z
����0��}�^$�i���M�6�k�c��k
G�3h}�i���r}�&�UVVZ����*##��4cW��zE�B����'��`�������y�te\<C�o�_B�m��c��76:�����B]r�%r���x��g�a����xp��TZz�\.�����n�o�Q�s6�a��Y����-�
���-�Q��"��a�������k����g��t�gh����2e������z�0)c���=I*TU�5��)9yj��k�+..f��C����U����1�r�Dg��%���/?EMoR���v_�+��?�+���J;�H�g��#��N��.�@�?������|�I�|>M�>��t�R��i����|������U�������t4W^�O��,�������ln������lGs`h���_�����p��W���z��L�`��4����J�6�[OI�!�������544X����N3v��7*�`�3�|x�����p0����}�ajya�:�S7����P��U�.�)�8�I8�����D�PH�<��e=��������UTT�l8�Y&������Y��e}[����~�2�?�h�S�����,��v�e�g�v���d�KKv4�7��`TTT���Z���=�0��o[��?M{�
6�{E�Y��J��FUU�m���a������R`A�����^�2���q�g�H������s����n��<s���i��f[�D"z����s�NSa��>�JL�fY3���6\�P���.��?%OsR�o`1�+����8�
N��{k�������X?����(
��r�����F���j�����\���Pzz��a����V���[��4�*�4K9���� 0�>3U�#����f�BQ��������	'�`[�BZ�|������1��N��)?�i�-���n���(��9���r���"%��?z�������i������u�^C��:��\ �g�� ~B����Z�&�[,�S���d�n�^qq��A��v�i{���7�y24��C8a����w���u
��t  �.\���:��������������T�������������u0�^����m����_�[�p]�����a�����!I�w��5k�P�`���T�f*D��O�3���g�;V?mmmjll��9f�
��P�}����3��Kq8��v)��be}�T���{#��T��u�|k�e`�3C��z����k����]��-S[[���0�E"�m[���v57��`��.���E����o���N�����u�^ZZZ��))\�
�P��n}Q�WQM��~�����v�������M�`��3�Wm������6�	�3�s�<���������f5��B���3�qa��:�,��=�vOss��/_���.�a,�U4:������+��h&I�uZ�&'Z�N�3uEY���1�S�	��qo��i��^&I{�8q
�Py�u�^�k�<��[��_�OUUU��YYY
���"{�������W��8�������S��J�zJ�d��{]���Z���g����r�������Sm�444���ROO���0vy���T.W�e5jPY�7d��o��d�[���gX�$Ut��[v8�	���{Gu��^o�����a���qo�Ya���3�-��{L�sF����i],��{S�.��P��4��C�N�
�7����{����2M�����x�h�"����s�y���a�a�2��*.��m���uUV��`����t��<�����z����@p��n�KMM�Yg�%�4e����y.�`���i;qoRl��z P�H�������bY+**r4�Xm�����5Ov�fe:�N��)��y�����j}v��oT��f�|>�.��2M�0�vOuu�{�1E��N:������O\b[���SMM�9�h�/O���Y���*jT�t0�mX7�I��7�,��-�0�}�v=���C	�1ig0���������pg(%ef|CY������������7Z,�$�������������v�d�=��yOy�v��V��V��[BB�/^���,�=�7o�SO=�X,�`2�U��}g�����P�
���f2C��Y�	~�e�-�U��
��i�h1��=�P}��������o~S6l�T�=e6��$�@����������3���J�&B)''G����[b=u�QgYs���t�x�a(���q�}��r�Kpo�5�������kdr�:�H���Z�t����m�l��A�?�|�g<@��\~�)�KO��7jC���E���������������WZ�O`���{�����D�]v�L�T[[�N<�D=���C�1��q/���du�[J���4m���o��ZOeL9~���8�� ���s�\%��q3&���Z{��A���3��*55UK�,QJ����y�����yq��X�Y�n��������;L����)��(��~WM�V5�;��2b��^�|����o�0566������?�i=��#��s�P�`��k�+0�Y�E�^cc����/r-..v8��b�������+�����'c�s%x�y�e�?M�w�_A�[Z���5����P:�`7n��,Y���i�����^}�USa���&���^Uu���Y�zQ��N��~��j5��&@<x�:��L�<��c���p8,�4�j�*�Z�J�������Ly���:�a��u�'��hU��c�>)���z ������*�u�0TXX�l�1���z�:�/.N9&O.���Dn�P��\�
j|x�"��l��:����
,�����p&|R999Z�x��-[�P�z�����/��~y����X3u�Mjm[���w-���������U���M�
Cw�*��oW�)�buC(�k�k�����28��}�^UU���i�2>r��k������S^���E0���DU�����r}(&�UVVZ����*11��4c�5��J�e����|t���0�ys��������6u��e����WnW��U����'�~r`�������^��zH�h��$I����&����;��pS\.�JK�����R$���7�l��5w�Cr����4/���gh�z��aV6����z]S��X&.�P�_V�u�a�����65�����I�z�����L����W\\�h���{C��M������|p�1z�|ne�?M�����xc��M��X���=����b-Z�H.���O�<��6n��`*�E����=���������7&����4}5�m���:�i�t0��h�3M3�_``:�-�����T�o=��H�444�����V���4M�����'������
�%��l�\;W��)�3�#j\�Q-�*3s(`0��1C��w�m�4M=�����u���0��
&}��^]}���y��D{}o��b=<bJW�W�5q8�g����?������Wn��W��,f�%���Oee�����RAA��i�����
�Y7L&6^�t���0�x��}��j�U�����v��S��Ve^6K�,�����9s��s�Y����}�Q-]�T�&Mr8��)S����5jk[kY/+�QG�V		y�e��\���H�y�B���7(������]I��p,>�a�����u�<��{�b�-��S�^^^��~�����n����B��a�����,��45?��b]�Se�;;U�Ze�7UIs�L	�$�8�������^����a�X�B_������p:�.�WsJ�����R$�����h���4o�#r��������m��u�����
-ZQ���q�e�'��`x���6v�X�
Te���1Q�XLUU�Y����2����l��%�'oN���0�%������W�:�>3U��+����EJ���;�8w�q����-_�\{��q0����<����m��m��n�������Z��a[���Zm����
�'���*�����,k��?��������X}���[==���4��O�������=O�_��r���$��zg���V�]���|b'�t�>��O��;;;�l�2���8
cNV��*,��m�������&��g��5%�zZxO��e���Z�n����=0����.�4I���%���Oee�BIr���4i��i����N��7Z�|�i�<1
��6�vJ���\*W�;��H}�v�v�:���i�%,�0t�����C��������������dk&O��������K��;L$%{����P>����=��g3����T�n���g���P��������/�w�������2m�$aj�r��'����7Fbjyj����XO��l���r�t�9�h���{�|�ruw[������Ui��z3-��H�6�]�X���<�TH�-S�l��v6���-��A�q����r}Rl�����{�hT�������bG����u�k��y'$�?=��D�����X�������K��=�}�Z���;�
p��n�.�����v���+V(r�q
cGB�����m���]m��s����Y:5�~���5��:���=0���)'���r�t�^]]����EEE�f+:^�!�L�Z��|��p"�v��P�	�4��C�N��7����{�U�+�2m~N�����%�\��|�i����z��G�0Q�1n�B^e[���A�7���D�a���������Eb���Za�u�5����PD�Ba�Z����y����'�9U_���
��g���qp��au��eYsg&(�t���0��S�s�\%��xc�T��j�S�����a������s������m�l��M�?�������0�]��G��7n�I��5&�2��3�����w�����:G3��x���55�����x�:>cY���=I*�h�J��VU�?����u�gHNuF������Y��e�����r%y5n�,u�Q����IQ�I3=��}���d�����	8 ���Z�d�|�A555Y���i�������s����}�0�\.�JK~�7W��p���`$������?&�k��������P��_TY�8���z���2S���7$W�����0E"���v�`,�`����v����z ev���Dl������2�BQu�����J�*���a�2C)G��W����7)����8�R���+��>] �Es)G�@@K�.������Y�y��w���u���;~��~~�JKn��u��������y��4c��������]�i���_��F�����y��}�[������@����Uf��W`n�\J���;v([�����2t���X���R��(���8�����k�*in��M����������	8`���Z�t����l��^�Z/�����0�df���kl�������In��=���u[�B][^��m;Cvu�a�_�7_��m���,��n������������h�����������w+��	'�r����x�2.�������V��c�z*�J8PYYYZ�d��~���W^yE������0�_����m�7~G]]U��4����3l�+��uOM����?�������=��������V��~knw��/&�����9$���Pn��D
��wm��T�r��<'�J><G����77y�}����<X��*eFc��	&�s����^�����z��wL���0�*���|Y��h�C�7\�h��)��d�����m��V����N`_��
�|0.{��y��G���BU�[Jd�� k�������"�r�f�T�*����J9v�����$e�P�<_��7����J�B����t�<�	%����]|��z����Y7Z?������*--u8F;��JJn���K%�����(��-?��?v4���L�-z�b2z���,��KGLW���jCr��?��������bPI�*�	��o=(�w�>jkk�F-k����f�z66)Ro���|x���>���[�N�J����,���}B�B�����5��`���XO���S���/�_�����%�|�I�|>M�>��t�23��������v���+��>_99g:���r���"}��
uZL������]I��p,�97�(v�{����b����{�����			���u4�hf���W�L�3������S�����n�|��3{�jZ�Q�Oo����:�g���g�m[��bz���TUU�\(�EEW+3�8���M�UW���%�29�������?���uM&����������r}�4����g��*[��nYK��%OV�������L��+Q��}7�v�Q����)\��@2���;w�N;�4�z$��?�;�O�>	�p���W��r,��h��o�F����N�ran��f�����V�:�o��pU;��4M��{���0�r%(9ir�c�
��f;�c,h[Yk[,��`��n���(��/����poxW���Z��wv;����:�(�x����P(��zH�����X��e���v�}����I�o����$�g��5%�oY������Z]Q�	%�@?;�a�F���U�[���a��������Y_�J���	��P��f��z�|SN�����~�����g�cj���j�s�bA��A��X�`��>�h�zww��-[���&Sa,����)��i[�������I���/)��0,��=���P%�@?�6��$�PU����8�������?IJJJ�����2���h�^��I���N�+��9J=�@����W��z���V������a:��S4o�<�=Z�l����L�����
������������`"�4��[������l�_�[��>h��l�i��z%���z 0;����k�+**�����`�4v�����oR`�S����pJ=�P��2G�T��{#{�U�:u�g�L�t(!` �a��3�TII�����-_�\���&�hg.���K�����h�K�7\�h��&(����Y:5+��~cE����&����Sf��WhZ7��N������Y�����1���R+��)N��a�c\0��'�+���J��1�����g������u��	����y����S���ihh�C=����a���2UZr��mY��|_����L�a�73���Z��"1]U^�p��8�3�Vee���Y���
������U���_Hk�x��AL��e��W��~k��Ur��8'�Puu���+�G�=��wv[�<��0k�����p��4��%�xm�Z�_�������Q�wt(�����O�8���h��EZ�b����-������G������Z75*=�M�|��l���^W��2��k����������:��,�k��t[e��?%��La�{������{��?�Q�����=�i�4��:"QUu�,k��{))��r����C���S�RRR4n
e����R���)�0_��i{=����������M�6�Of���p��J=�H��]�����t����O���D���j=��c����������0�\�������_��M�(������e:*=E7��U�,�����q):!�8�5�����>�Y�f�����***d���|���m��I��)%qL�_UU���i{�A�'����?���S}J:,��D�3|���n��d
�1&���*��c���M��$$$h���������y��z�)�bV���g.���%��'��b=Z��ZE"����zQ��NO��_S^��`��Dc�����C=�/~���F���E�q�����_]�6mRss�|>����u��Gj����z��[�j������U(RFF�f���c�9F			�v�����	e������������;R���.��e=A������Y�u2�Q�Z���2<#���s%x�y�Lu����g�I������}�e^<S	S��	�'99YK�.������X�)++����Yg���J^o�JK��;k.�iF��������[4{�/��s���]����PS��9��pD�n��#�N���q7�������/}I�h��E.����z�"��.��R=���}�
m'
���A?�����?�Q���w?���u��7��s�9����~�i��'?��5k,�)))�������)_F�k'��[O�+0�duig �������+**r,�he�c�������Q��\��3C)GN��0U�+6*�`?�4����+p�$��T(���0TRSS{��:::,��Y�F~�_��r
�{iis5u�M������]��VF����[�X�	~���Y�%�+-����uwM��-�q,�X5�G��p�
�D"�T��)���+��R/���������ZUVV~�����g����w�V�\���g�����mp��w�yG��{�>���+
�q���/^���;���M�:::����V�g��+��r���F�k��uX7�����a���23��>d��uZZ�222�1Zu���XG���rL�\~�������MV��s�t�>.j7��mW���S�5�L8����L-]�T����{������9��I_������+����;69�H�LV���o[���N���n��1����K/�0��	{3f�PYY����}���S���������������3�8C{���������s����Hnw����-[�K/�����}��b�����b��>�n�[���:�������������O?]�����k�EMS�:��q/)i����8��������b��|Bf�T��Z���u)��<�C��s+�����x�������6���F����X����������l�����z��7L���0��u��-��XP6\�H�zd�|w��b��1�+����8�	`���{�V�R4�}�������k���C�j�|�[���;$I����<����������acFaa��~�i555i��5���TUU�����>����O�7���~�����y��>kW^y�jjj�m�6�]�VMMMz��'UPP�����K�-Rkk��}M0�u��nf.�h�J���Cjhh��9�c����G���Z��r�N�:�>��f+�����
|���qY�Z��*3s(��&N��K/�T��v����7�[���P���4�)�K�a}���U�M�?�G}R~�K��)�m������n��u4�X3�����z��0]x��c�io�������_I����~���~�_����sg����b����:��s�L+����}�������}���?������y����~�����L��{���>���r�t�y����_��xQ[[�_���c�5�P(�����RT���o������J�Zqq�c9F#�4������$�e(�����!oV���>l��Ov��S����H��{* �����h�"�\�}=��3*//w0F���C4m��m��w?�;q0�49���O��(I�6���:����n�kkk���;?w�qCg�tww���/���p����S���A=WCC�����>k�����4�}�w��-X���qkk�~��_��X?��������x������l�O�8��9����o��8�D��5�P�k��`��O�~�������,�333����X��(��E��N�Z�a���Hp80<�����qKf�H���$I��}�Zu�[�P:��M�>]��w�m�4M=����u���0���^���f[���'jo/s0�tAn�.������y�6ur��x��{�@����L��LF��o���"�������A?���>������,�I'�4����o������FB+�XL>�`�����}��Y9���t����>noo�c�=6�����C��q�P����Y������=��}r���$�O�����,�\?W���������P���EJ��9s���3���G�Q=������q0F+�04{��JL(���b!��p�"�v�z������������L]QV��h��Lc��n��:uj��---Cd���[����{�}��JII9��{��g�<�����_�w��'�i���k��x�
������zO�<Y'�p�~����~������C��q�@U������o����V555Y�����0Zk���jYK��)oN����������_���	���������T�:�w[O���G��|�3��p8�+V�����T�<��J��%��Y�����q�w�y�`K��u��B�ln>U���l��X��bX7���?_n��w������8��������/+�;����.�.������W^y���)���_�k�N>��>k�=����������|�3��L����r�JuvZ_�<_��PX�C�Z�E�^ P�D�������������N��``�1�.��V��/����podw���N�o�r�B}�^�{��?�x�z0�����g�Sa�J
�j�������_P���L$�����y���;�������q/33S'�|�L��i�6U�F?����~�zIRzz�����O�|eee
�����������������y�n�:���s�1�}����>M�PH����{G�k��R��c[�j�Ku�q����r}���
���7����S�hY���_��p"`dJ�������?5}�}f8��'6���
�z�����OZ�����wuui��ejiiq.F��?������7o����w0����Y:-�����UwL0�
��=I��w�+i�t�M�6��'��H�P�IDATD�(//�O������v�5�Y��qc���g�>������?�Pk4�&*e����f����o=(�w�^v�{L��d��w���/�*���}����n�v��V��vg�$��l���N���j����M��-SGG���0��Y3���"��i��~��
��������[O
n��tUy��1��a��w�����+��i��`������m��8U|�b1}��_V(�����W���O��}O�t`�|uu�zz�Og���VMM�������G�k��b��W`1mO��k`>X���jm��8(�����i	�k]�e������'F>�e(�����!r���m�Q������;z�������g���3g��ijj������m}~�/�'�9�w���Y�{z�k���=��zt��B����u���:���f��qO�����v�i2MS


Z�`�V�\9�����;��o�!I��|���~'�0>������8???���?''G���q,Sccc�}{���s����Uvv�k���}<���hxM0T�q/!a��^g����IL��$:��C�Z_ 8!P�=���_�����*aV����Z����e��v��	�����^���'����{�V�X�`0�`2�F��lM�v�m���Em���s�$����sm������&�&�V�}oz^�W�<�����j=����s�N:�$�r�)�������?^�����$����������;����w�?}'''������D����>��ZRR�_���lV��Z
��@���������g��-����qA�X���9�c�M�XL�;�O��B�����o���������W$��� ��"�x�z����S��?j�������=7_f~�����m�����M�u�;J<�@�I)&�h����>������W]��yQmm�V�X�s�=��M0�������3�������fY���Vy�3��R�X�/f$jUC�����=�ke�������gnF�����5��kx�0���7v
���`d1W^x�^�����g��+��B{����/��_|Q�������y���z~�0�u����|P���������9S���w��?~����p��q0Mn{���s��5�^�����{����=�����k��A���g���C�@���h������������r�SI�i�k6���_���h�����,kU���j����{�B�l��7�(��m��l�s�����]{$�^b���,++K---����>]SS�?��O*..f"�1|��()�����*�QY�u������)�'q�����	�t�?Gi�Du��
]�U/�c��������<c
�{����5���555C���'Io���~������Q�a�4?�Z��������~��p��<��^zI��<���������{z��A�`�����ylua�S�q�XN�&
�����^3�	��o=��H��`0�H$bY�dm\Q){�uz�S��������+%��sZUP��q{�����=I�6�*�v(�����GS�L����Z�������Z������#�T~��,Ub�2�p�������G���%9���aF���F�6)������}�:-4:�q8m��0������:�(����2MS�i�0�A����t��7�>����u����1>>%.
�s|�"6��sN��c9��`(����'i����[����I���ISRR�0������>���#�~ �O ����v�jJ�b���R[���^�-#�>+0by�^M�:U^���,$���Y���}n"�X,O���m�o���U&��D�uR��1������bc���������������>�l7Z.��������IRnn�~����1>����)r���S���&�:���r�5����Z]t�}��-[t����>�?�f��5(y0�uvvj������������!L���+vJ���
T�o����	'��D,=��s��999:����0��QS�n���>�si���5+atu�����(������k�?���]��1U����_�+�=<n8����=����?_�>�h���?�g�M�2E�{���0����g�'���S�����$$����@))�8�����K*vhCW�U�C+2&��Y��]�+#�H{��O��<c
�{����5���]7n�`
������o�����L���Y���k��*,,T �����_��=��S���������q>�(���y@�o��A5�uuu�NH�_����{��5���legg��HIIQjj�����������g��*z�'����Zjj�#?3�XL������S��s{:��-���iOR��yJ��p8��x�������k����m�\�k�����K;��y�Ly2�������RSS�t�R���T0�����o*55���al$���)���z�B�����L3�m��������������$���+��?q�6��v��w%��Yg���=,��kx�0���`��}o������4��n�������a���T��r��<�L%$���W���o���g?�Y-Z�(.��xs�]3����w+��>v�\�����/++K�a��y��a���+''g���c��>���F�k���j���8S�
-&�%��$IjhhPWW�e�������3�����I�����
�q.�[�O�J����,3���i��;�*��iJ,��
<&L��>�9-_�\���
��������#�p8F�;I��w����S,��c0X���o��C~'�p9��8���O���6�X��mh�Cu)Z�����r��������k��5�
S�a��.��5kt�����=Ijii������w��@_'�xb�������g��u}���1�����q�||aa���Abb�


�X3g���7_8�������d1q�������M���&�I�&9�a4����H�u#d��9r��N@��������?�������oT�3[d��������@�\r��n�����{N���w0F���i�9�������US�{I�f���L����whc�����kX7��^������=����x����a���b�����7n����X��5���l.��6w)I�k���xG�$UUUY�O�8Q~�����i�j_���hH�����g\���<T)��{�e��T�:��q�c��)���e�����zJ��h3a���0�"���m�RK��&��g�DMM��}�'f���juE������{�v���o�0�h�"��<��JJJ��z{WUU���n�����^������������������������z5{�l����5����
T�o��IWBB^�I�X��q���8��mB�m
��[�K���Jt8��3<.��9Y�>?[���oT��T�]k�����t06��5K��s�m=������
��������5��jC��
����q������4�Vt��[v8�`$���"����Sb����:�����g�Q8>��y��wu��7�>����C=�g���S�<Z�`������������K�y<�4��K/�Y;���l��y������z���K������/�y|��'�6l���N�k�+�h�K
�����'�k�.���X�����~���}���=I��L����Y���~����PU��>3S��+����s���s;����;L�`P���,��hT�<���.]��|��p���D�)���z�\E��'���TV~�;�2g��VH����{�����l�q):';��<#��n����{�G �$��p������]BB�N>��}~��g��������&��_~���srrt��G��?��c����={�H��m���+W��O���x��>����4:_8�=UuO��f5q/(�s�������nM�4���Ehg�z*�-k�i������+`$���5�+�����jy�d���zg�B5m��l�|��	c��G�`0���_��P(�+V�_��rrrN�� 9y�f������aYojzU������j�2}ib�^mn���c}#�7m�a�$&��0�8s���4c�I����A��%�\���/�}��Wl/<��i����~�g��_��\.����/|�}�~���4��X�?��O��������-Z4�����N)���'YO�s�q�����%i��I�z��d-�W���i��+�m(��"e}y�\����"
���{�:�����)����:��cl����Z�|����L��$7�l��]b[���7jn~��<�a�734�o}�����j�c�{���{Gy�z�Y�f��������k��]~����s�����g?�+����8--M�����y��n�I)))��W�Z��n��v��;t����Y�������5�qF�k�l�i�K2;���~�N4�E�QUWW[�����~��$�������9J�7?E�)i'p���+��y�O�xc�T��[���&��#���1�0}�3���y�l�ttth��ejk��P���i7+%e�M5�
e_W0����2��=����5m]�����<#��n�KLL�\ �4e���{�9�B���5�����rss{WVV��c��_���>:jkku��W�{��^����������}'++K���w��}�;���W_���.������1��g�R^^�n���1���	v�
T%�cknw���i����������I��;$��'L��j`xs�������^$��{��~�v��F������1�0�y��*)���EKK��-[���N�a�p�4��.��)��P�^�e��iF�tTz�n,������^+�hV�2��$���o����a��{�~��_
u�/33S����L3����9�����L��7O�'OVQQ�����>�{�9���o��c�t�M:��3���{��*((��)S4o�<�7N��w�jjjz�$&&���Szz��}M���{����H�-�����G�?���j���q?�hm���]�5��D%��p"���2X8I��<D�t��{��A�����_����������?_��M���g�=��C���q0F���b���?�����TYu�����stL�u3�$]S^��`��D#��o��>}�~��_�NM��~�����C�j�[�`����~S�ZZZ�v�ZUVV*�{���.�L���h:����_��]r�%}�����m���k�����Om��qz��t�����������������q/`?Yd0UVVZ����8�a4�xm��n�	,�����]�'A�r�����}4��L��P��?�)���rLn�[�-Ra��4���:=����������|V'.��WV�������6�3�P�^�e}O8�k6V+fr�����{�t��W�����e��"��.���r�-��������OZ����������d�o���z��'�b�
��O������GyD�?��;�0�}�������U^^�N8���#������;��IL���<�D�^$�3�������~��"�Q�vZ���>%��v8���J�*s�,��3E����S���w�U��g����zu���*//�vOMM�{�1E"�a��6���f���
���������W�;twM�cyF�a?�����/^���d}���V0�O�S�}�������`�M�:U�z�}����O��N8�w
�'����{��G��������k���jii������u��Gj�����X���t�h��-z��7�c��B!���k��Y:��c������3_�CY�u���j�j��;���c�������~�����:���e-���2<#��
`�R����0UMoRd��MMbm!����J=�@�O0qIBB�/^�|P

�
T[�l��O>�/�P.�`�n�_�%wi�[g+��W�������;w��z�`�LV�����k��o�����):"-��<���o�+**�a����0�����f�������?�q��w@OLL�I'���N:)���:u��5�
d4�&Lv�{y��O�>k.�_IIS�������?I��|�0aB��?��������f$z�<?��D������k����-�Z3��Sj{�F�m���d���>u�_RR��,Y�?��jii��S^^�g�}Vg�}v�����$%j����~��,��-oh[���2��e���	�Ok��k���d���,��?���4���� �F���M���%�m����o��K��
U�o-%e�\��_xi��WXX(���)#]������-k)GO�����h�����h�2.�.�7��x�m��}�uW49�F���T-]�T�@�v���k���/��Xv�i��_j[���[���:���r���EJv[�s���uC�v~�4B�>h���k���|0H�^ P�4R8Vmm�e���8��
����U��
�K)��9�����Q��s��Mp_�3������6���C�`t�����%K���h��?���^y�Sa��6��J
bS5UV�M���S���/fL��?������0\���������=��PX���e�`���o��h4jY�qo�to��Hc�e-�S�r��N�i��I���aJ>j�>�v��C����H�����dggk��������^~�e�����h�r�UZz�<�T�z8��
�W,f�;^<�����s3m�7o���67�+<C`_|������c7mO�����J��������;:������NU�Q/��f�-�N�4B*��)�4��.	������e��.)��.�v!$�=��'�$w���,��������C6���[s5#�_�������~b�hJ�s�������L�T�f��\R��zg�7�������y�F��[��uS�$%�c���9�_�RE��L	S}}����J�~��J����~�a��~m����t�g���jY�����G,��c�h��Z���e���������N&��MgL]����O]�"w^�;`��|��>��������n�+3�U��#���@���g�k��Br����X{G���[��N������D�[��*���k�f�c�����������*{�2^��)`�	�B����t��w+��X�y���������p:��������O���-�zW��TVv��*�w$O�����4����Q"cU�=9�O����4:� �p<�P����������Ur��Y��H$t��!�Z8���E��n�Z����%��U_�^�W�s`�w��������t ,l�V���_l[7MS��{�����`*,+�R%%'��;;?��i��V��,�g�/����;���8� ����"d7q���q/l�r�����HB�P���w3�1%��Y�
�V�����Dr��v���aU}�U�b��{��'��6M<�'�<zr��kkk��^h[�d2��������`*�;���������Z����w��L&�X��W��U�y$�;��5�p,@��q�Ef*���)��{����D,����TSS���������ot0	�\V��B�7n������d&3�w�F���L"�P:X�N9���-o���R)�y�����u0�]aa�Z[�h[{N����<�a�?�4��o}��X:�k;���pS�����"�kbZi��%��Jh��F�>W���������,�?���!��/T"s����2w�_U�N%on����ur[��oy^3����������=�\�z"����[500�`*�������g������_9�����W[�m�l����#4�����=�������Lh�^y!�K����������0��z�B{��d����=V���76�����]��uojpJ�_y^�'�4����
ox�N?�t������n����Q�B!�-_�q��n��wt~BSS=��9�,�O�����r�_��;�`����"�a����.��9b��x����������m	�BY=;������oY�.)R��r��'�e���q�
�T��1mj��}�}�2�Ig��c��������N��3>>�-[�(�9��������fy����S�1�w��Lf��L74���e��u�����Xh�`��k�kR�Qk�@k��(�Z��AUVVf��|�GJ[7=�o�a'�o��^U~�E��K��fLw���mJt1)��������n�]��v�����n����I�!������������o�}}��
C_miV��mYL�t��.e���|�e�����7����`u>�i���{���f�q/9�\I
��4��"3������5w�_���N _���9
��J5t�N���m��G����%���
2\������v��K.��w�����[�����w����7���;�����|57D]]_����������7;�g�����4i�������+�u}s�#y���4�}������q�no6��X�L�(��X��=j-��{������B���������9c�w<�A�1&g�+����a�F�������3���Q%������r}���������/���[���m����Gw�}����Jy�^�"-����~����-��;�J�Paa�#y�\U�k�u[��e���^�Y���������<�4��~������b�i3mO���u�Z0���8�F���p8����Yf&��oz,k�b��Oer���*����5*�h�����bb���n~N�{GJ�����W^�%K����D"���{�N�L�|�ry���ey���Tj\��7(��q,��-���`�e-mJ�vF5�L9��i���g����������b�n��Wk��P�G�6��	f5�]�^YY�����zv>�|��2����Z*��v8���0��S�u'�Sc}��ebI
�O��~����(�Z����Vee���]�v��?��2�I������jm�/I��w���k���;���r�������_A�N�/wusS5�`�[���p^g|�r�z�^[��(�X��B������tF�����>���s8�����X5�mP���x�R�����v�F���"h���*--���}�v��'?�;,�*�g+��m����U����	�������������cy����C�.�?��`vv��u��m0���,�XL�����p8������J�4��n�\E^�X�\>�*.]��e�o����������o~N���Ra���(��JKK�i�&}���������g�yF~�_oz��N�|�,|��F����S����R �VEE������\�
�t��a��������b�
�>� ��K�^s���(������)uO�X��=j-�n�^4z��D��53c*��A���P��zgX4�N���!���v*�����LihK�g-U���2<�6��JUU�6m���|�;�������O���@g�}����o����/��g�����o��N���q�N��=��~G2���z=;>���G��d:c���.=|�*�y��y���.x���?�������9a}�$5[6��d1��T���J���d��|5�sX��I�Z��Z�K�������*T�GNR��K��7��C���J
ZOzm��%�������OP��/~�g�y��T�W~�Z[�Kv_��b���_�S�v��-�������i}zO�cy�0��{�<��}�Q=���z��g�3
^G��y����RGNa�����Uf5�]�^(�����4M���.R�\���>��R����rS�����'{���e�&��w(����F]~��r���{z�!m����T�W�W8|�m���v�����<m�"}f��
n���F��m����G�i�w<���fE����`kV����jd����p8�����Lt\3b����*y��N`1+l�T���k�}B��Hk��]�w�23i��@~[�|�.��R��d2I�����k�.S!_�CUE�Y��;�N���7U���W��U���O��V�T��<���{ �fk�{�`�-�Y�����#&�Y���')x^��I�<e���z����:�_a��>�����}���<�v�Z���������{��G���w.��a�������j,��t\/�_�tz��<��sM���^�z,���]Jf���4���2�vMX_��d��W���{���D���j�����fz'4��zB�E�|
A��nC�o
��O��
X_��G��I�����O�2u^��N:I�x�;l��tZw�u�<�`*�#��Jm�_��W������9���{=�jK����b��|���<�B�����i%l&XO��^��i���{�p8k������L�;�i{�_��r���Q��e��3����W�w�Tf:�L8�c��~�.���z2��������>S!���������~���:|����Q�'�Kl�_9��_�;� h�`��[O�s�)����0��R>_M�����h|��L����������! ��2g�
w��������c~���>����i�`��l���9��u�Y����im��UCCC�B>jn�V����w��;ML�s,�
��:��~���;�?�t,�\�q�E�=6e��T=����G%�V���,v��$���9k�������u-x^cV����2\�J��������?���������bO��4���$�0��7�I��r���x<�-[�hll��d�7��RK���[O�K�'�b�uJ��??�5�a�+-����-���������@��q�E�3n}�e��n�[����qo��%***����&���3}�5OU�
[+N��?T��7���?����~�_C����u��az�;����6�=ccc��u�&&&L�|��U���&�u����n������Y����5M���F����~���%�X�m��=j-���D���h��3%)g��|��!)e=n/x^����.W�W������e�{��W�;���sJD�v\.�.��"�Z��v�����n����i�!�����e�>n[����z{�s,���JuMc�m���^=;FC*�?4����'�L�,k��:j-����-k�P(k����tJ���Z�\%>m�q8�v�a(pV�j>z�<���M��h��5��23�C	 ���n��}��������u��wjff��`�;�M����m�;w}Z��=����euZ,���M�����l>��*�X����IGO��xJTP���,�H�r�0577g��|4��a���������m�������
*:�~��$�������yQ�qN�����W\��K���9p������R4:��a����E��u��LfJ���+��t$����m-!���sN'����e�4�����,p6�{���J4~�Z0�*�0��%�Z�/]�T�ObZL�TF��{,kF�G�g,q8�8������V��+exg�(��7���������@~�������U]m��w�^�w�}�d2&C>�z����f���>1�G;w}��f�p�_����������r$�\��*c���W\p���o�~��_���d�]�^�+��Ih���L&c;q/g��|4�\�21�IS��������p�����S���T��;v(�g?�'3�����<�A%oi�a3����"m��Y����42b������|P^x�\.~��h���|�'�w��Y��_�egh���9����r=6����-������J��6P�H��3W}OLL��G���M���t!��]�^�U�^ {�{�������
��vn�13�b���^��_�p"�{��"�^w�F�_�;<����������5��3�^.�����,�l��M~�_o}�[������FG����/,��vF%%��v$��������;�8�6�1����~z�j��r\�\�`����`!�Jg���bG�n�^[��D�G�'I.�KMMMY;7�Lu*5h��Xtj����� ;�[��T��kd�����9S�M�4�>�P:������i�
�'�=��S�v�,�>�0���?TPPoY�dz��:�RqG�����5$����t�dB����H��3�{�a��/������^9q��.VQQ(kY"���zCC�|>���?�� ����=���9
���V�
�m����Ni����^�I�W7X�jjj�i�&��~�=�<��~���:�
���-U[�-2�e}rr�v���n��(�g��O��wH?�q$�����������=�B�����7��D��X��0��� ���N��BY93%��*�c=����y*
N��T����8�z���M��W�_}^��I�@�X�t����Jy<�=?��O��s�9�
����$�X�)�z_�:t�n��|��Jo�*��rW����'���+y�b�
}�����,(�6�{
: �+f���Y�����D����p8��s�M�Q�i{���1m��fx\*{�2���i��]�L�l�&{'��6��w��7�:�r[ss���������R&c=������Wkk���#56|P���h`�����{�I%%')l�z�0��k���I�$�G�c������W��2��������@ ���;o�c���M�kV���l6��M�s��jh�!M�f�cJ������wI���`��������{�f"������F�����Q��g�\~��) w�\�R�\r����^��yT�4M}���������+�!!r�aZ�����:5=�}T=���������~(�'��<�^��������������-6��Gz���f=�k��� ;2������������e�D�n����Fy�����Ob�}Q�������)�����+��&�t&��W���4�;�L8�������m��LF���w��u����-���[d>���T�v��;���l8�,�O�����r�_��o��/4��@uO�(��X�^9q�����hyVr��i����pV��7��IMuY�|�%��JN��p*}s���t�\A���?J
L��+���cM��6n��������T*�;��S�r0�EI�:�\���������s�cynh��Ye��u;�/�t,��A�T���=���Q�X������w�R2i}%�{{��d�g��=�]��2���A�U��oL���>
��C���3� ��y��:���l��DB��~�L�|�P�jj�a[����5kw$��0���fUx����dJ���R�~�Ch�`���i��Q�
4}�Z0����H�r���j���Y;7_�����oY���`u��� ��>U}�U��K.c��S�C���9%�;�r�����3�8��>99�-[�hdd��T��ah��Uaa�e�4g����J�b��Y������Y$�����r����|�q���q�YG7��G�^SS�<O����'z���T����2������2<�A������?���HB_����ef��`q3Co}�[u��'����b��e�b1g��?<�����*��gY��>��-��Iwo�,�5�����Gz����#Y���=(���&E�Z�V�^*�Rww�e-g��|��Lj�w�-k�2���W9�r���D�7lTa[��3��~���v(�q&�(���/�Pk����322��[�jrr��d��`�V�������:xp�cy�nY��-kiS��3��d��<vh�`M�tp:iYk~E��axT\�:+9<�T���I���o{e��-k�sd�y�V\�U\�Ve�].yf�L:�kD}7m���Qg�@�r�����K�|�r�=������;�H$L�|P��
��^h[����4>���,>�K������tp:����vl
 ��`��O��^��W\�Rn�?+9"��������%K�rf��������*����Z�@~1C��-U�GO���z��eb3��5��.�.��xy<����Wcc������u�]J&�o���0�Y��**���i&�b��J&��.�����?40�����`��=���)���S���x1h�Z�����f������&��Sf�za���r����Z���\�AEkf�hJ�_��7�+=�$)������W^9��4�������)�������	���V�\�7~��>�������j�u��
�����hG���1�r�q�0��������8�IQ��U7l�J���<x��[OiX,�tF����l�[�3�N���w����*�l���sg"����9M�v(����B]}��������{�n��?P&�q0r]0�F�W}��>8�uw��<���^+�l	3�>��
�`��{��i��������f�@��G�e�q�����"�P(��3����A�G��=��D�"���`a(�X���7�[W<���dJC����C�e�hH�8m��Y����{^|�E���?��;���}Z��������]cc��R�v�����.����L��{z��J����D^���C�g�d����i�Z�Q�{���Y��D,�U[[��3��i��=�m]t
�]�l X`��E����*~�K������/(5d��]ii�6o���b���g�}V���/L�\g�������VX�M3����L�:��5P�����uG��~�7�H����������~����Jpl{'�5c3�YG6�-��3�T���F-�C��\�y�;o�w�(�7iY+�P#w���D��^����B�W��Q��uo�`\}7o�����@n�������UPP`��7����qS!���EZ�v�\�B��t��:;?)�tf���V�U��#?��[]S�S��e�^5�����6��W�k�`kV2$	���X���pV�����)x^��a`�+l�R�
�k
���L�5|�N���Gf2�P:����������zm�������O?�`*��@`����G�����t��;��0}iM������c������L��FB��=���z�G�#�������%�f�_(���� �Lt��V�Z)ou���`��T������9z�w����������
Ycc����
��n�=?�����/8�
������]j[����}��,�^����,�a]�����v$�D��]�^��G�e�q/=�,I*..VuuuV���G����5:���R������6����IIR����o���g�6��B�l�2��}��a�t>I��~��;w:�
�n�����x�e�4�j��Q33��d9�,�O��������_Y�L`����b��:����&u�d�q/�X����Y/^���'4���bU��2��'���`U�jo�(���Y����F��G#���L"5�^Xh��Y��.���n������i����B.s����V����������L3�H���kuVY��~���K$�7�X@�fRJZ74��f���&y�%s�ajjJ�����P(4�������M�kp0	,n�����:���Y:F/������y����	9b���z�;�a[O����������`*�����Z��s�������u�#Y�����4������L��]�0Yd�{, �)�Z��G<[�������~��rf�K
Ok��~���> ��2g�"g����I�^/w�o����)��y��#��,"��~����7��������>|��T�euK���u������O��<�H�%~�n^�l[|$�[XF�+4����5�U��
��iA%���d�D"��%%%�������.��A)c]�� �8��'@V�����q�
���)mj�����C���3� �s�9:���l������u����L�\�j�g���f��q�ff����]�Xm[��H���p$X�h�`�k�{��=I
:��
�e�Z:>��g�,k��B�V9��r�b�*?���w-����NMw���mJt�;������&�z������	m��Eccc�B�r����V�������~ut|\��v$��.��I�B�Z��>��h2�H������i���l���B��������-k�px����'I)�q{�sd�_3#��0<�^59I���Y��G�����[f�t(!��0��w�C�����366�-[�(�����QT��5�b[yB��W��s�t[kH���������n�&��`����1��h�d�����=��������Fmk��q/�H)�d�e���hc�����5U{��?�kdF�iT��nW:6�L8�G.�K�}�{�j�*�=CCC����55e}3,.Kj/T}�������5<�[G��
����F��Cc�rh��,`q�q�b�����������=I�D"��eee*++����l�w�eN�,k�s�exx+��U�Q�kT~�J��N'������4�g��t0�n�����)
��9|�����N����i���W0`��3���?W"1�H��j�uE]�m��{{��f�=���jq������jt��5��'O�]��b��g�2�=�cY3
<*>}�����a*>}�j>v�<5E������V��~��6J������+�P}}�����n}���U*e},n�_mm7��X�gf����2��#y�ye�V�-k���wD5�v&Xh�`���O[�7�K.�H���{�����-����m���[O	�Y'W���D�����X5����Skg�hJ�_wk����~=���������RMM���}��������4A-zEE!�]�y����S�Dnq$K����ZC�������>����+���=������&u�����h4j[�Bs~^.33�b��.z\
����@�����Uq�*U\�Z��=����q���MS�����Pi��M*//���c�=����d2&C.��y�6��#�[54��#YZ���
���w��}#�d�{,�T��]�^���^o���%s�!�X�WVV���d���eSCJ
Z�}�Z+w��p"��*:�F��o��>0�>s*��-�}`���*�`0���7+��y�������T�i�����r��(\gS5���J$������zGU�m����5�p$X�h�`����D��9�YG6���2c�3�M���s~V.3MS�G���.)xn���s�SU������&���<������M#7,�����y����l���w��#�<�\(�$���um����n�L&�����dRY�b��sM���^�z<���]�aZ$8A4��t���3�F8b-l���GGG522bY[l�{�}�J�[�
�W�SQ�p"�\2<.�]�\��[�*���7�W���4�|�C��y����������m�<���z��'L�\TX���k���>:�;E"79������Z���������>���#Y��E��]����@�#�����Dlk�Ph���e�G����5:��M�-���a�|�%��3g��{������L��t���K���+���c������L�=������j��������]_���c�d9�,�O��������_
�;�,L4���5�5����`��������y�j�`L����������-�?X<e~Ux��oh�l&�����}��u���'�	knn����~�\�_7>��joow0r�������l��::?���^G�\�\�������H:�,<4���5�5���:�'����9=�4ME�Q�Z8���r]��Y�����=X������T�'mr���M�O�����W�i:���r�J]r�%2�n����O{��q0r���S[�-�xJ-�����;�\�L*�Y���[[�U���9�L��]���
��{���dJ=6�=�q �2�E��cxxX�����P(4�g�������-k���B%'8�`e�jo�(����7�2�o������t��i������m��LF���wmo������^--_����=������,K�^����7���u��~G�����=�\���=Ij~E�^I�m���D"������G��<�a�&�����Cm*y[���������m���9�
��q�F���o���R)�y��:t�����k������?��w�M���v$�+Ktmc�m��#�zfl��,`��q�<�a��0�U��#����9?�nRF]]�
���\�Oh��>����Hk*N�/��P������$�����MO���/(��A��M�7��3�<S���m}ffF[�nU?�����>��������Ohz����]V�����a��tmGT�I���W��=�\G|�r�YQ�r��\7���i;q/��Y�,���?\�i!x^���`��7����
*h��}c���C
�o��Ig��C�;�<��u���OMMi���q0r���U[�M�z�-������oP&���H����ZC
���2�I$��]�4��W��=�����&E�x�r��hn��411aY�BszV��L&5�T�e�]�W�I�'�
W�W�������%��M��;���sJ�s(d�az�[��
6����b��e�b�����K

���������m����d	�������������#Y@��q�<6��h��������0�sz~4�\7C���szV����W�L��<�^�����`��_����,OU��{��3��v���Kf�i>�0t������v�����l����I�!�TU����km���G�p$�E����������=������q%9yl�dB3����G7������H�r���^~����5f2���,k�b��N[�p"@���Ts��*�P3�FS��
���J��8���r���/��+l����oW"�p0r���_���4�z��Ojj��#Y�ye�VY�MdL]��D��.D�y���.�n3���9b-����L&c;q/
��Y�j��>e&�����������C@~s�=*�l��/]%�;�����1�����w
;��������.SSS���C���;�T2i����Qk����ZO�K����q�2��7�����5$������L��{z,kD�y���q�A��(u��\O����������pxN��Ef�T�1�i�����u'��0T|j�j�� ���Y�f&��v�F���8�������+���%���������}Oi��-J�%jm�OI�
s��/h��w$KK�P�]Qo[��wX?�q$�O4���:m���u�c����x����D,�].����\4����#	�Z��uryN�'��"�|�d�a���G�Gj���J
O;�����@�6mRUU�����w����W&C��bTYy�B�����~G��?u$��V�U���O��V����B��S�i���q�YG6���r���|������|s{V�1MS�G���nC�s��2�G�����V���52��Y������m�jt(dOqq�6m���R�����v=��C2M��d���7��������������0C���Q�~����]����L���S�g�N�-k��������tZ]]]��p8<�g���]#J���m�����p"@>+Z_��7���u�9����;4���2�4�o�����y������������N��"dn��~Y^o�e=��������d�]�����4�mX���M���g=�?4���:����fE�x�����V"a}��bh����gH�s�
X<��f��{j��S�����JX7�@������M�TPP`���'����?�`*�
��Fm��%��c.k��=��H����dh�m��������#Y@��q�<���\�4P�������D,�=�v�Z":������-���9��P����L�l���3��d���o�����9�����VW_}�|>���_��Wz���L�\QQq����m�{����!G�\�\����'D^����IG���@�y�c��q������@��9=��q���Q����.��A�Z��F���5��a�|��Y��3�|o�����L"�P:�{


���+�v�m����?�/��`*��p�:������c��jr��3�\r�nmiV���3�P2��uv)m�Y���{�)��{M�h�+.Z!��`��M�R:p��e-��9�(yxB�;�-k����5NX���~U��:��$���|�_��n����� ���a]v�e2�z?���c�S!�[���%�����N��b�
J�Y������k�l�O��ukW�s��@�yh"���)��_9q/l���:�d2iY[��{L�8�p*}s���t�\%�Y�������5��A�A?�����u�E��M������}��9�
����R[��e�uv<��={>�H�7V��#��M����^=36�H��h� ��O�^����{s���D,��^��.]:�g�����&_����������@�E�`y�jo������oL���i�����:��>�Q����;��N�z:���w����nS!���N��7��{����p$��,����"�Z�����j4�r$�]4���:�S����j�w�Z`������zss��n����K���H�Z��
��q|��@�J��\������v{��c�u��v�i��Moz�m=�L��;�����L�\
}T���w��{ML��z�����6+���z�'���wu�4��bF�y���q�Q]r�b_0�v��M&�:p��e-��9�&���3��+T�V�p"�bd��mP����.�����pkuG������i@�9���u��g������u�V���8�
��0\jm����Z�z:=�����N[f�K�B�������������P�s��E�y���q�Y�#�������*�N[�B�����k�O����<�A�1&0��M%��a�
���8n������w:���8�����F�v�i����	�{�����g�b��U���&��d���.���O�dyom������fo���w����@����:'�-k�l�Z���H$b����UWW7�g��L"��o{-k��W��'=�M�B�*�\���VH����G�w�6M�u&��0����]��������w�^%�I�a�����e������G���;��s+����zn"c����&ln�6��3��M����5��q/8��{�h�r=
��Z�o+&�>,s*eY�]/��0����0��S��6�S]8��LlF�����~��6J'��r�=�y�V�^m�'�Hh��}J����cajn��*+�������O��z�b�[��������g2����� �p�9y�=>e�n�i5�����l�������-k�Ph���%f*����Xn��0�����X5�oP�)��kJ�_uk���+5�p&����K/�T�p�v����������E�0\jY���K,�������W:=��,-�B���z������A�H�s��B�y���qo����#���q����d�'��vm>�������e-���rxN�5������R����v�>Qo&2�������!�����z�����U_o�511�x��{���W����e���&&�h���:��K+���R��'vu�k��y��36�{������A^o����F-�USS3g��
3c*����Ay�Z�l ^_[�v��d��M+������S�?�/3e�������������GWW����^��i�a>������?a[�=�}��7�9���V7�������]���������=��]�^��G<��i{��D,����\����b�sH��?��S���9��W'Q���u��_2}���'z�����~��\STT�M�6����v���;���N��������z�m}���(���e^����,�a]>6����� 7,���X���)J$-k�Yl������C�,k�Ph����ij��n��!��w6�������*�$$��3������n���J'&j���*))����/����i�&�|1C-k�C���2�i��~�R���g9�,��
�����=�_�g=�4��G:m��I�{��9;��������9;'W$��)y0nY+\_-Oe���8>�����q�|M�Y�����������(3�v(���2m��I������~�i����v0���[����e^����>���iG�9�k��9���
;����<`��q�<�a��Wb��L#G��msvn$�\�����srE�n����y
&��y�T}�z�?�k������������D"8Q������K�v�m�<��cz��'L��TZz�V���m�p�t�����p�n]��J�����dJ��R���,h4��G�m������>_����9;��q/
�0�Z����+�g��V��\���S�U������U�'mr�'�Q�oR��>��g;2�NDMM��-[6������g����`*�������-�����Q�������{u��&���q�����`���@��i�kV����`���999���[�������+b��6m���$���U���a��+�f�g&3��
w�2�)g��q
�l�{������`*��0�v�������[&�P{�uJ��Y����}����:���3cL�`��q�<1��h�D���������.��Bk�KNi��A���)(_���D�=w�OU����4K��;����o�����77��())9�D����O�w�v0���[�um7�0|�����v��;G&����:�,���M����F�4����@��3�P����W6���a�^$�\/))Qyy�������l����8�E���e���&U_�^�R���?J
M����+��G�x����-oy�m=����{�Q4u.�MI�z�\�7�������]Y��s�t[k�n���{I}|W7��,@4��'�cS��3���9b-l��s������jdK��h��}�5OM�
�T8�����JUs�F�=��\�����5�u�2�Ig��qhmm����6�z*���w�����=X8�7�����={>�X�#�9�����F��Cc��CCY��E�y�3n����ny�~���[.��nN���������99#W�~�#��'�k��Z8M��������-*}�2�=���t���n��Dt��t����u�����o[����������~�Ba^���k�U��M��LfF/�_�T*��,��-��u������c���'���6�5���x�@��M��F���P(4'g���TJO�Z���~�\�p"�e��g���#'�]Y0���XB����_���nz��v�y���3���OMMi��-v0������[�r�,�SS�c���4�������ZY���%2����j"�����C�y�4M�;�7�����`����D,����UVV6g����S�2�G�����-`q�5U{��t����4��.
~�]���3��50Coy�[�a��=�x\[�l������0��V�\�������`����(v������6��L&�{z��8�������FR��eGM����=��{�px���of2��o�/�tyT|��0�\U\�Z������k���Q�������8�^=�0t������v�����n����	�a>�/�B�5����������k������;{�u��,4���m��IV��/J}-���544dY[H�{��S&���^�T.���D�?�0T|��\w�<�E������V����L�%�W��r���/��+l���;��������4�0�f��������i&�b�
J&�?��K+���R��'wu+:��z�]4��:m���~��&C��6����H��
�����f�M����g�\*>s����-��b�|�d�~�	��{�[����(�/r����e�]���&�=��]w��d���X<����n�����OOwk��O�4���n����Q�~�e=�����.�d2Y����=�����&E�x��0���=�Z�WUU)���m�������O�����"J�����W����2��O���W�M�4�1�P:xu|>����J���������=���T*�`28-X�U+?m[���~'�9��}�5$�a]>6����� {h� t������j�k��3�&����9;c>����#��nC�s��
@�+:�F��o��>0�>s*���;4��>�)&�����UUUe�g��=�����a����t�����=���{?���������b�U����k����x�s���q�7�J+2��������������Z�B����1��w�(yx��Vtr�<�~���<U����I
�}����������������X�7oVYY�������G?�i���������SQ�r��i���~�����g���F���7���������s��=r���i�].����{v������{���<���$���R����rs�\E�Y�&M���m����P:8���m��Y��}��s�=�����4�-`O����"����>�8����n���k�U��~MJ����.���@��q����RS`N�Z�w��U���esrf4�\���Uqq���1�]����[�
Z*��)r8����R57l�/T2�>s&�������v+3�v(����B�6mRaa���'�|R�?������@`�V��G����/u���������-k�l�O��ukM����q�6�{M���e����r�f�z�j��i;qoQL�;�i{�Z�2���l��4J��{'���[�)yx��pp����������l���W���~�;S�iK�^��%������F�~��T��#����������x�s��C�9�n�^��G<[�����!�b1�Z8��3�S�oB�;�-k�e��7�>5�p*}KHU��M��w����)��������i���'�����+����������D�?��s������Q��+-k��V{�
����9��fY�NZO�O��G:�4�Le=�4�������i�Z�+�J��q/�Z������99c>�=h[���`�����a��+�f���h����s�2�4��pX�]v�\.��J��j�������"���"�����HV��O�43Y��s�t[k��n��=��>����w��{���TBS��9��\M��D"��uuu*,���1_�F�5���e�[W|�F0+w������m�c~�0����n���n�I�����W���.�����{��W���s0�(^�5�?g[zT]]��z��B������2?���zp�h� ����,�
3�Fu��c�����'|�i���B��	?�|�?�#e�'�o�a'`�1\�J�oT�5'�]��uozxZ�_{A����y���[�N�z��l��tZw�}�8�`*8���"-�����?��}&�9�[[�+�*l�����N��@��q����\��!�4���@�*�\�>o``@��p8|��?��IM<s����,Pa[���X���%��a�
Z+g��15������C���3�������7�����d2�;��C������V�����-k��VG�����z������"��D��5QM��Y���{��������u��`�uN��D"��.�KMMMsr�|�?yHf2cY�� ���=����������=��c��N�Q�M�)���p`�����9��c[O$��u�������jk�Unw�e=1����O�4�?_��b�[�h
���~��3������jpbh� �uN�5��`�����K������>�$����!��+�U��Z��x����KU�����*�uof|F�|Q�����1JG���t�i���'''�e����:
�).^�5����><���]_�z���B���z��]����o$�9���q�54�Ro"iYkR���s����d�F-k�p���>M<sX���e-pv�/o��6���j����
5�o4��_�����x��p�
�a��o���_o�g||\[�lQ<w0��d��U��
����_���SY��yi��Y]j[���nE�x� q�:9�3n=mO���h�s)Xs�����izz�����{f*���-k������N�����U���*��c6�'������4�k��tp$������=Z���������n���)��o�_+W����jF����`V3��/�nT��kY��3��#��L&�9�kG�9���q��U�F_z\\�\nw�	��D,��n�O������J��X�g��U�q8(>�V5�o�wI���2)
~�C�?��L���yn�[�^z��-[f����Ow�q�	��-4n�_��n���������/d����(�z������u�����uoV3����=rT�M�^����`�uN��k�khh��k}g�\gfL���.z��w6x���H5;I��b�m�����v����@6y<����WCC����������������������7������D������Sa����w��C�Y�^=��Qv�{�G5����Y�tZ]]]��p8|��?_�w)5`��X|J��A�����^����BW��Q��u�LwL}7?��J��������Rmm��������������N_��jk����M��H�f
�&�9�k��9����$��]:��y�\A�9(��h���D���'>q���W333��P(t��?L���#���<�~ZpV��j���Q�����������������8�����P�6mREE����;w��?��2~F-4+W��,7�1���J$����e�um�*���p2��:��6�����{����J�\gw����'|^$�\�x<jh�����1%�c������T:���SQ��k�+�*��'��U�W�W���d���6o�����=��o��?,������k]�-�x�����!�w��2�TVs����em�m����n���j����@��OY�{����������
��h�r���I����s]�Q�i{����g3"��v��aU~�U�����$O���m��=�	�UVV���7����v��O?�_��W��
��v����GG�H�������Dm���!zXO�������=rPg|�r�A�V����`�	��J�t���Z8>���3=q%v�X�����[p8x-
WW�����/+�u���h�{�5��]�$�����J�6m����������7����������������h��z<�9�z���nM��G:�4����?0;��A�6���u��`�������Q2����B�~��{���Vr>�������t�J��$�������[�i���8���NW]u��^�������z��gL'�X�)���dS5�����N�j����Z�t[���H��;�e�fVs{4��cL�T�M�^�"G<���{�h�r���i���'��NK
Ni��A���)(_x��= w.C%ojV������7�����������=D��455���/��������H/������m.�Om�7��)��'���h�se2��x�\��V7��<8���j`��=rLO"��T��v���@�	��D,����g��4W�?(�\�<�Q�q��= �������
*X]>���������;����(sm������Kf��q���k����B�6�e�l��c�h����������������=�7�E�9f���}�������/�{5������-k�P���{>��g4�l�e�SS���'����;�S�ZU�������cH}7oS�k��t�����=���g2�s�=�7NA~��~����m�����u�s|ne�V�-k���k:��H[� d�{��v���j�OE�|�q0�z�guww+ms�^8>��wZ�7=R�z�^��F.�������9
���$�+
f��Mh��4�H����8^�C'�|�������S�����.���8�
��|�'UZ������	MO�j�"�K�h
�o��w�dB��w8��=rL�M�����Is���F-�

�d��~~'e�S�?�kYs��UtR���@�����a�
�U��1#�?��w:���8��v�g�
ox�m}ffF��~����'�#��\^���,�����J����e2���X(�?������;���F����=r�]�^�Q�{m'|V$�\onn���_o�O��LXO�S/��_�=`v��*�\���VH�x�O�Q�M�iz��3�,j��{��<�L������n����aS!�

���������m����>W6/��;�Km������T"�9�p;9$�J+:e=
�������H$���cY��'��N3�i����oqyT|Z~M��a
�Q���N���p���XR�����~��6J`12Coy�[�q�F�=�x\[�l�������MUUoPs��m������a�K�U��Z�������j&��j�4��C:m��IR���|�*��5'tVww�26��[�������'-k�g.���v8p�wI�j����Sjg�hJ�_uk����c���1C�z����j����Qm��E&C6-[��*-=�����IMMY�tf��y=�zkHn���BlJ���7����@����\/4'T������=I�D"��EEE���>��w��6{��e���x�R������U��U�x�j����g�����9Mu9��b�r�t�Ei����{u���kz��� ����U[�M�z+,�����;�W&3�����S�:������!�=�m4��C:b�������,?�^�^(���?o���������%r{N�S�����A������L�4��S������B'������.Sss�����^�y�����n3�QPP���/����_��}����5�����m��]:���\�F�\��"��n�kV����`�	�3==���^�Z8>��v�i��=b=mO.C�s��
r���P5=�UM���������RC����Dy�^]q�Z���g��t�=�(�J9��RYy�B���ww[�?�j�a������z,�������R�4������=rD�4�s��6�������.�6��S�^b����������)+p8�����w/W���2
���(�W���4�B�C�,6����T]]m�g���������0t!��\eeg��w�����d5C���[�6���������f`1�q��2���u3]���<�R��$�H$b�TYYyB���q�i{���58�����*���A���Y�����������(3�v(�����X�6mRYY�������G?���
����Q[�������R1��~�2�DVs\PY��6����=����������=rDG�z���L�A�/=[e�	��F-����	?�S�5���T�[[�p"��<e���:�o���Vg�������J�YO��QRR���7+��y�������������U[��e����k���z��^�D�E���)}��K#�T�s����@��k���!�4���`�����������-k�p����I�������=p$��R��B���6��Y���&����x�0�3�\EE�6o����B�=���o��c�9�
�RQq����l�nU_������r����
���w@O"�����5�9F�9��q�Y�#�h����=I
�B'��NI�Oj�s������T�p"�/
V�������(�u���h��=�{�2�L!0�jjjt��W�����������z��T��p�z���i[���o49�j��B���������1}����lp|h� G�5�5)z���`�	��D,�KKKU^^~B��������J�������O�T���c~32����n����1g�X4���u��W�����y����m�6S!�������WeYO��jo�A�t"�9�[[���*l����c��x�h� �$�7c=���e�{nw�
�O�,��{�pX�a��s;!5����~����X�U��|���2T��&Ux����Y�������{�G�i:��b
�t�e��������Pgg����
~�Z[�,���c����/Y����
ZYd�������#��t:�9Xh� t��mk/o���0���;�k``�����y������`>x~C^4�������
*Xk?�H��65�������D��p�U�V���/�����{��W{��u0����L-�`[���C}}?�j�"�K�h
��e��y�dB��'�X,h� t��,�K��j����`�	��Dlk�P����	���&�>lYsW�����D`!pyU��E�.����`z���o~N�������hkk��^h[�d2����u��S!B�����l������I���sam�P�����~W�����j��v�{/��'I%'���F-�+**TZZzB��������X���6�8���v�P��z�|�$y*f�����7�k�Wd�L����SN����f�z*��w����^Sa��[��_��WkYO�'�b�uJ����c��J����{������d"�X�h� �5�5��q/l;�s�&����z^'df��?y���
xU|��E����!���7���cL��H�?��������8��w�Yg��s���'	m��U��\������e�}=����=����a�K��P���������f2�7��F��l:���I�;��|����WQ���>gllL�����P(t������+3��������m
���*��Z���<�{���Q�����w�8��B��7�A��~�m}rrR[�n����s�0���O��ei[?t��:|��Y�P����-!�
�!6����G�W�0�vON+eZ�^>q/X#��s��D�Q�Z�7�������X��[���9�,t�a���%���dyj�f���'5��v�=��f2�c��������N��3>>�-[�(�9�s���UV�g[����51�/�N--��������=�_�g5�{��������L�N�^z���9�H�r���Z�`���;�&_Pz,aY��N���oh����X5;Y��/9���#5p�v�F��)���r���w�[k����3<<��[�jj��3%r�a��������_c��I��~�����_�T�s���vt�p"��,D4�0����-��obK0p��{�i�6�����������E���Y������V��+Uq�~��{g��w�6Mu:��B�v�u���j��e�{���u�w(����	r��W����d��/��k�g���e�um����7�N����.�M3�9Xhh�`��5�5��F���722���1�Z8>��u���a������O�����p"�X�T��6��`?�H�����������Lff���x<�������h����������L2-_������>a[���W����j��W��m���f4�[��������=��i���{��z����Q �����F���\��g��b��L�3��9
�����P5��������;��^��y%&H`���|���+U[[k�'���{�U:�v0�RS��������]�V<�;��PY��6����=����������=���DR�)�),�/��W\�J.�����D"�����***:�������f�c���uU�T:�@2<.��k�*?�"W�g����	���M��J`!*,,��M�TYYi�g��]���L�I���0\ji��
�K-����^l�^��DVs���%���� mJ���H2��,4�0�:b���$��e�����>�4M���p8|�����G����5:��h�k+Us�F�B%��3g2��.
o�23L�p|��6m�����9��o�O~����`2���Lmm7�0���''�j��Og����r����
����AO"������1^��Gq���j�OE��Z0�z�g

)�[�r�qo�P\��#�5��2��'8�����?[����1��������m�����$WYY�6o����b�=�<��~��_9�
s��t�V,��m������{Y��\��V��,�'�c�����f`!�q�yd����#'��H����=�0���|���m�Gg��w>��@�0��J�R��['W�;��������M��z�V��TUUi��M*((��������'�p0�Rc��T]�f�����U,�3��[[���*l����c�����Gv�5)��G�����}�]�^]]��z�������X���A���:���
V�������*�}c����j����L��	`AY�d����*y�������/��3�8�
s�0�]��*(h��g2	��_�T*���[���E~�Z"c����&���f ����<��������5��q��h�����:#��(�Z����q=�b��l���� �0�
�*�>U}�U�oI����L�8�����Lw��p���F]~��r���{z�!m����T�+^o����"��n����h�������"�K�h
����l�dB��'k���h�`�t�L���l�+	��������j�^:6����Y�<��*h�t8�kc��kT����.��T�G�������b����^���i������Kg�������]�v9�
s��d�V��k�z_���9tWV3�
��V����><���F���|E�����q���P�^z<���H$b��r����x���M���H)�����5�8���\�o*Q�
T�z�dL��8����P:n=���]�V�y�{l��i��{���|�����UW����g���ud5����zgu�m��vu+2��j��{����&E����l4�������}��|�L��m�e�]�S��5'81�"�*�^���,�<���`z���n���}����`�|��z���n[O������t��ASa.�����WaA�e=������+��e5��V7���kY��3��3��L&k�G4�0O:�������8h9���d2���������z�l�?�+3����i�����?�a(p�R�|�dy�
g���������w��XO!+g�q�.�������n��v���9�
s��	�m�-2�e}j�K;v��L3{�e^������}{lJ����F<,V\��<HeL������G��M�zK�����kz��90
�sf���(�D�e�(����%'�[���\�AE�1E��b�<��o���X��p�s�9G���m������u����L��Pl���g[�������������u���������f ����<�?�����fE^�}0�z�gD"�u�������~�l�x�O�x��x�R��n��=�����V��}�d�f�Zf&2�������a���w�a��o~�N9��=�x\[�l������0���RM�;m�{�����_�j��5�����m��]:���l�bC���#n=m�e�U��/=��q/�Z�766�����f��1{��e���x�R�dW�)���~��K�g���Hi��}h��T��t��az�;����6�=ccc��u�&&&L�e�����,��9���W2���w.���k�U��X���i}��Ki��fE,&4�0�����|��;�o�^:�VWW�e-�sf�T���C�������]�[��s�[]��������so�����]�a��L�r.�K]t�V�\i�gppP��~������O<�����"��gY�������������W��m���f4�����v>���=��]�^��G<[���:����Z(:����4{����28���@2�.��w�*�Z+��=��dwL}7?��J ���n]v�e�~�����w�i���)l�������L����o�,���jl�_���F�Y�@��q�y`���������/��Wu\��F-��^���s�.�gT�C������)/p8����U�����5g�gN�5|�N���Gf2�P:������+����Km�8p@��s�R����p��.�\���������!��:\��%E���)}��K#I�]/�p��LR�3��5+�������>#�X�755�����f���=I��L0�<��v���=�����+�+�?�@2��������Vuu����{�����S&�q0N�aZ���UT���n�I��_�dr4k�.C_kiV�m��zI���n�����2�p���=IjR���������TJ���B��z�lIWb��e�`m����'�_������U��V�����M�T�-�4�lMfUTT�M�6����vOgg�|�A~����X��n��e=�~z�G�;>�����B���������1}�g0k���h��a�1���2sX����6����(�������9�%��A�Z�|�������q���Jg�g&3�w�F���L��= HRII�6o��`0h�g��m��OJ�^	Vk��������oe5�{k�uu]�m����&F,T4�����i���O����q/�X��|>����sfC�R�C�5_�D����w�_U�N%on����Nn�W�-�k�'�L8y���\�6mRaa�����zJ�>����p���.��%�������m�j�ZY�UE���S�tD5�Ng5���=fw����5�y����j���������v���9��i{�f����I��^���{S�S�����?y�iYl���h��M����<��#z���L�a����'����fJ/�_�dr$k��.�����u������nwO�� ����������������`��cU,$�I<h��_��eKj4����-k�%�*XU�p"���_V��7�`M����F����w(3�t&���t�R]y���x<�{~�a=��s���p����v�\.�i��D�::?)��d-��@��iE�m����������@��q���V�f�������z���n��i�Z.5������D����jZX���^U~�E��K���/Mw���mJt�;�@�	�B�����r�E��������T8���Z���l�CC�����j�MK+���R��_�>��d"��4���������Lh�z_z<���H$b�^PP�����z����Hj��^����@���N�?�P���\{����M�&4p��[f����U�V���/����������g���p"��.V]��l���I���f�|�0����j(�Z�'�]��L&{���4�����u�^�����]�V2��{�Ph�)
N���!�3�����q��1�|�A���A���f�����j���J�f�	 ������/��g2}���UWW���p"V�����WY�L3���533���K�}�%d;v{lJ�����>��g������?���]�7;a�6a�p/p[��������vO�~muP��b�����{1�6��7����P��������G������PBrs9���=��q?�]p�@_��ry��8�����y�e��������h0����{t���2}��
�;p$��u�8e�:Jru�O`m�jo["���8u`w2}�t}����p8�|��gN�Z��$M�8WNg�e=�����4c7�n����x�m����z��5f��+ �@���i�+�W����d}�:WUU�h����]%����F���e-��a2��8w�{3C��
��+�������h{H
�.U��2#f�:��8��5c��z ���U__����RRFj��?�����Ve��b���y:43��~��*�B1�����qR��=b�+P�����	�u���r��)))�����k�'3U�[�,kF�S���?��sNQ�S��w�M������g��-��4`�1s�L���~����N��?_��L��|��=���~�?���a��w���/T��eYo
EtyY�"&ar����qRf3mO�
T��c�w�v]�����xQQ�vM��o���i��9<e�!r$Y����qx��:c���+���$�`E��n[����8u`w`��9�M�2�vM{{���������5��6f�o��:��U��k6�l��������m��m��1�����qRj�dnQ��[�{{&�uuui��-�����>_���QS�����NC�����!�=X��<�]5U�a����v��8�L-�����
`�q8:��5~�]�Kjnn��������=��DM�x��N��	�`��V\+������Yi�� ��~Cy�>h�����,�������m��9��JN.���+++e��e������o�UM
�Y���2}��i	q�`���IR��{)�������f�����
��,N�S��~�F�i����N<������u$'k��������Uy�1����C4--���tyY��C���@�� N�&��|�����e�>_��������Uvvv����L�T������zh~| �C'�T��I�n��6u�����\V����\.��:�,
>�v��M����+
��3l�A����a�����oUS�{1���0tgI��N�����UmJ����q��h�?hY+P�����	�u���
�����2c���_��m
V�[��&��������	�t�Ty
��]g"jzx��_�h0����<�f�������)//���?�H����1�����V��H�@}��/LJ������/6�j�����@�� �l��IR�������|>�jkk-kEEE}�^k_d3mO�w���������'�{�p���:t~R��������9����$�w�y�Ns_�z��z�)E��8v��r84q��r:S-��`�V��F����y�:o������mVi{g�� ���6��d�C���i��3q�n�������)��C���������{����e8
�S��'����vm��Sus����-2M3N�U���j��9JOO�]��g���^�k�..9�P%��f[on�@�o�i=Lc�-kA��%e��1�� �@�M�+T���'��QJ��>_�.��������>_�?�/���yg�c'�R��L
�z�Fgt��E���ujzh���p|���JOO��9s���b���O>�������=���U~��zE�?���v��Ov:t��B%:�G����Wk6�l���q`7q�P[?NM+����'V���-���i{��.u-�����S�0�~Rb���(���J;���w���7����
V���7����l��=[�����$��w���o�.���1z�����lS5���Z�1�|j��0j�m���&=Q�����{�X8jj��oY+�&���N���������`Y+**����S���$���6s�������a(�����x���	���4�Uw��jg�L��E�a���:��s�v�?x���_�����WG�&N�M.W�e=jRi���Fc7qu��l��k�P����Vyg f�k���u]~��77�`p������3'�E���}b�d~Wn�K����$�k��S{~�1���5��L_(>��%
>\��s��N�����^�~�i�B_%%
W�����[Z?���[b��a�i�p�'Z�@}��~XV�`4��%�{�XY���=��0m���i��}�vyy�����l��Y?5?:��,��o���/���=�]�#������q����k5��&���D���8u`W4b�}����v��SO=�U�V��+�Un��>�B�ze��jh|3f���]�����[���.�y����@,� �J��,��&��$�S))c�|m��^QQQ���_���:��lYs�y�<5/��7�P�A��w����]i����j{�J��ti{�q����SN������{L6l�_S��Q#���)�������[���������Cl�wm���
����{�XY�up�@[?NI-�3�O�miiQss�e����O��O�kd�#���C��p��`W������*yJn�M���J5��3E���i�.g����q�g[�D"z���T]]����G'�&�+��
5�t���FC1����<��j[�zU���^��p�<1Vj�+�W�����|���
�����g��j��fL#���}��#lG�K�g�U��e���(��U��.���C%����w_q���P(�����&�]�/���iB������%Z������0�_���������*EL��v����@H
��e�P�[?�z��+//�<�����T�����oi����O�O=`�	�7�`�c�R���+��5(���Q_H
�����r��h�:�+9��Ct�A���~�,X����8v����9\�����QC��b�^�[sK
l���t������@#�@����'I���q_�{�i������t��bFMu,����v(���q������AWLQ�~=OOn_T����+���Cgv5Gy���{o��������������#G�X���l�+��SW����?3+MW���o(��-1���Dp�*�	�e��JS��e(5u\��������6���
�u�6(�h}�v�>��L���#���T����5k��g�k�U���u��J���]�a:���4i�$�5����?�|>_;Co9nM�p���L�z8���W)
������4�I�QI��U�9�����{�P�Mp�p�i{���r�R�t]�i{�TXX��k��4�n3mO)��a�m1�<9W���*w~��_MX�W���u2C�8u`W�p8t�)�h��1�k�`�uu�O�����8D%%7�����i�z���r;�YR(����/6B���*������!��{����	}��]po���JN�~*},��(������W�\��q����NR�%{���������e
�w��3�
����~��***�]SSS�|P�`�&�a��d�Ta�������V}��1��0)A7�+������y���
��� F�"Q��X�
w �g��***,k���}�Vis�m�;#?�� �C��P���Hvu�6���������6N����n�s�96�>��q�F=��#
��q��5��ed�k[/[�Suu����N�������������v���]�=bd����M�k�R��khhPG��t���nlW`}�e-q|���S���%i\����&OqZ���`T���Q���
D����-!!A��{����l��_�^O<��"�6�j�&N�Enw�e=nSi�U�Fc75��Q�46%��4M]RV)_������1R��ey<��k�j��w_'����[7C}�V�v����q��6�4
��
e���n	�=�+=A�M�����~m��:��]��_|���%''k�������]�r�J=����F���%!a�&L�������/��u����N��UR�D����:���M1�����
��*�	���J�/f�%&������VTTX:t���B+��Nu�5Z�<EiJ(�~�
�UZ��"��[��
���*����5h�(
5F��������({�a(��B%�HW���m�����R�?�*��J�o�����������9st�}�����r��e�����c�=�������UTt�**�Z�������}��wlL����?�������?R��C3Su�`����,����{����q_��E�Q��{���}�Vh�Z�`��=���%�����U+l�:}�*�TU�������q��)gh��}��){���t�T5=�F�5����Z�Z���e�>F�$���t����3g�������N�5~��u�a���;�dD�Ujm�D�-X��V�L�����\�������:�l}�e��k�5--E��	1������
�'���V�"�����^]]�����[TT��k��pk@�K�,k���J��~0pu�����n��������M�V���^��o�A]�m1������Q���~\���~jVWi�jo[�@���� 77W��w���U�-�����������	������G"*]q�"�@��7t��|�'�-��HT?\Q�@4���������:"�7�l�K�����v���


�t����&)b=n�;c�������P_Y��?�B��]�C�Y��"�����������!�����d����O?�4T���j_T-3j3��c����5k�\.�I�/����,Y���		��P����B{�
�]������v���"9m�nX���������+�{�@���=��j�*����;�O�����<���/����k��hgH���o�sf&(irn�z��U_Y�G���:����z�Mz��?'�@?J(H����)ibv���Z_,W�V(��Osv���B�u�Yr8���~��g�bE�&j#���Tq�U��M�������?==E?/b[���^�6��l���1��&���Z%�/IJ�R�'����F����������C:��"3h=Q�{h��������M�����������}��_~����~�.�#���s�+�������������u���[����f���:���m�����'�xBk���sg�Iq�e��<���r����Y��//���L�m��UU� ���e6��B}u���;�O���e���e����O���`D�n��9R�J�>(n�`������m��7u47��������P��C�w��r��]m������j�����&L��'�h[�F�z��GTYYi��gNM�p�<�<�z$���J�T$����������vY��B]^V������Ep�(�	��b��}
��M�s:�������vD��5�v�-k�
����[/�6,�X��]�=V��H�|�=�<CS�w�T%O�{leJ��W������Z?���a��i:��cl��pX<��6o�����'G'�"�b��X�5k������[R`[��C�V��lz����5V�?dY+���^yy��������>]k{��������gx�J�H\��������e���y".�0�8��:s�2�#���[S��6���D]�b3i������3l��`P.T}}}�BO23���?��o���jj����3��tE�}���}�����	�=����mm{�{�HD��������^_gGu~Z�H���������!���
mZ�".{U�,UCUE\�` J�6HyWN�{HJ����a5��B-�o����;�6s�L��������N��?_���q�
=),�D�Y���W���|��1��g�C4--���tYY��C���@w����|]��S�ve�Q��vg)!����6o��P�z�_qqq���f�T��j������aq���w�w�����~4��d�]6E)������M����
7Z���{3CG}��L�b����]���W{{{�C��������0���t���+���k��a���By�����9��VU�4���@w���J��oF+P��/>�z'�0�uV���-���n
:��-n��&�k;-k)�����>0���[����y?"��P����}�x��n���;T{�Ru.��Sw���p���NRII�����f��?_���?�"�<�,M�p��iY���h���c�aR�nW`[��M�mj����!�@?+����b��^��>]�.�WPP ������K��6��)�P��!�L�T]����Y�a�����9t�Ty
���35=�J�O�����;��p8t�i�i����k�����(��3t'#co��c���-�i����l���24{h�m��u�U�N�_��G���U>�e�`;�{�pX7n�������hU�����41G�������-��%��#�{�}
����������������q�����s�Bu1�=����Yg����)j�6m�C=�P(���������=���j�o��[���5LcS-kA��%e���	|����h]�_A��\_���������
����x�l��I��������!7������t(�;���p�)�n��j:Uw�R�>�aJ.���x<�5k�l����B�=��"�X��phB��JHbY�F�TZz�"������5�P�����3�_�����Bp�~���z2��)_�����T%%�O
����r��			����_�[|��j��aT�<����H��������r��}��dj����02��uf(��'�������x`�������g+''�v��5k���O*���3�q�35i�m2�e��[�U������$�q�0��#5Mz���=��=��]po�6���o"�z'�0z�-�.�WXX(����&��c�F��w&��?��$%���u���T����'��3����OR�Q�����:�����e
n��Os�"%%E�g�Vz�}����T�?�<�7w���4r�Ol�55Oj���c��yC�ubn�m�gk���3����=��]p�P_����	��^0Tuu�e����o�m�p�_���-k��T%���y���P^����[���L�`�1���(P����L�t�6����;����Mx�=Hzz��������5�/�k�����]D���+'�H���5�SG����m�n������3|��.YQ�?�b����4M���[�
T�����6n�����d����]-�����1\������
5&���}z�����_�����P���,	����z��eu�0b���
j\�R��P|�s����3g�m�����z��w�������Wb�0�z4�g�W(����t�K�*)���m��]���-1��/�����j�-k�;q�����xRR������`E:��}\kYs�$)iBvL�������-�v��M����=su�e��G���y���@�Lq+�{%J?a�l�_��5����
T���;�6h� �w�yr���k^�u}��Gq�
v��tM�x������s�V��M��$NOO����������+
�1���������V�
I��������fEE�����"9��6���f)l=n�;#_��i{��4���E�w�%Z��{;����6}��C������nU����O��0y��K��3�~��$EZ���S���Qf46������s�9GN��v�/��O?�4�]�Nz�^5�g����g�y��1����<������YU�-�`��l��'e6��,�A^uH����e�7n+h�&��b�����d/E�au�����H�(yjl��_j���������u����v����*}�U������_~��O��lJ����j�US�49���Q���
5�+U��p�'1b������0�(��SOi���q�
v������cl�k��A��e1��a�[R�\��������*E�y��'v����'I^��^_����6TTT������Q�L���=x�/![�HD?�_��e*_�xg����O�����V�r�J�xU�Phg����Ht)��q�<m�w��Qk[T{���6��;�4n�8�z���u�4����k��
q�
V���qUb�p�z4�g�W(n�����n_`[��C�V��do���]����{�_�M���***,����(77�/������m�IF�K)�
����$��[������Zx���@��O���i��������/�6V����{.�@<��:�Zc�%��aJ�w��.�"W^r�k�!5�W���+dF����&O����?���D��Ci���q�
V��4M�x��cY�����U���$��Yi�� ��~cy�>h����������3��N��������-��0�>���K�mZ�R"G�+f{c`vu��������N�=O�H���;1�_{HLI�i��������s}���5�����Ogk��}t�����z�\5n�&a��=8EyWLQ����_hJ�olT���n���91��>���#����B!=������cW���6I�G���^W��6mz0f���x���Y���.+�TS(���=��*_��6�/�{��VJ��^]���K[�l�����^2�������n�R��1����C�������gd�v�>�p:���g��[��9�A��Y��Cjf����_�[P��Xz�`�����;����.�7���.����������R=���UU�<f�#����������Hpv�6X���[����1N����>X|�m���k��jl�����?�<��g[_��Ojk/���n��;K
����g�����]U��m�~Cp�~�����x���<}�T���1r8<��^EE�m�������V����/�{�3�w������gn������jo��q��Qcu����Cf�/wB�r�4���w���c�A34���_�m+!9E{�x���=:���h���}���%��?�R~���~C�ph���K���AWN�{Xj�����������2��?<����#���{�m[��|�?�Z[[����0��%%Z�M3����T8����t����K
m�oSCL�<��+:�����J}��vo��^_�.���������.�M�i��M�i{rH�C�c�/&3��W^��k/����q�')I�_x������[���j�7M�_�����)��>��?~�N���t�U?Q�7���N�K���s�r����_5j��%���~u�����t����O=������
$WN��.�K��<5�������S�lb`�g��;�8M�4�vMkk��������8v�or���4q������U*[���M�;)/C��f���_�Y���1�0��vv�	V�[��[���{�����[/**����P_��(��������re%�d_<
Uz�����fU�����~�����v��i�h��}�PU�U���-���v�Z:}[�$$�h���2j��x�rl&���0�������\�YK^xZ�o��p ���;����C���}Xg�i�����=�
@�.�2N���j~|���a���M��m�2O��)yq�@q8:��S�z�j�5���Z�p�����))))��K^o�F���V���e���%UW������������Z}Z�����������+{�Q�����=vP�4U���|-����{>�Ouuu����b����}���=I���c�/�P0��xX�<�_E#���fe��/�|�]���/y���������De8:�������=���<TG\x�<�<-�%-{�Yu47���p �e/?�e�<�Q{���'��acKb�`�J*����ijzh���m���`DM��]�2N)�����q:�:��3����>���F>��f��-��z�bo��s����jk����]�JO�������w����&�;��QW�����w�����m|a��
8;�vwU��|��e�P��$hN������***lk�
�7�+�����8.K��)1�G�g�4��+��S���3M������;�����9�9�p{b�KJ�j�S������s���-���MS�>�@���gz�W�j���zn���HP����=l���K��OjU7w�B5���%��n�}��6l����7���V8l?��e����������0��>+�R�PkL����?����?Z���kz�P��`��[O�3����J���<RNgb��g7 33S��cO�m��yg�������U/��I����j�������b����:����������V���k�_o�w����O���Y�V��v��������*�I`��b8
�S��'����vm��K�s����-2�oOc�kKHH�������<�56l�O<���i\�TM�8WG�e���V��������C�tbn�m�gk���3��{>�{��������D}~s��;����������w�kE�e�S��������=�i�Z��u���R���F��]�z�:�/���Qc��a������u��~��o�S��<V.�����7�k���t�e��������6��0�$������)atF��Q�<�NM�R��T.`w������g+33�v���+��3�(���3l��:Nc��������6n���
���c�5<��g5_$�KVT(��`;�`��
T����������h�+..�{s����Z�yp=���=��l����^��������h�i:��j��N����C���=l����
]t�<x��JN������.-~�i������?���kV��Q����&*����!�Z�����*��=.��?^�Ws��QZZ���O?�T/���5w�!C����O���[�7��.����n��UR(�a]_���?��y�<�Dp�d�+�W�������VEE�m-�"�u.����%+qlV���=W$�O<����
U�.�q}rz����':��+=op:�����u���������K�Rv~A��5���|����uz�7?���U4�a��������������H�vm����}����	�����L��=[����k>��#��F����ah��?*9y�e�4�*-�J�PKL���������]]�WZc�7`�Ep��
kS dY+P������{u���r������N�^��n�"�7{g���y�<�
�V�i������.T$d�wb[;Z��|��4C�1�>�\�&v��w�?u�/���������kV����O�]}������]�1���!�0M��������FL�>_����)���5�]Gnn��;�<%$��t�z�-���{q�
�r:�5i��r8�,���f���D������if���~��*m	c�7`�Dp�Pf3mO�
��%%��J����&����E;C�}PcYsf$(yrN���=����W�����S5VW��>sh����_u�%W))������0�5M�����
s5����t�z}~k]����n�}�Z��>�76��[�l�d��g�W�I#%g���jR��K���%`w2t�P��5K�n^s���+Z�xq���RS�h���m�
��SU��1��a���@�����PD��U*��U@/�`��	���m�T�$�����k����������^�[d#�5���2��L�=�4���wt���j�k/����r��3fi��oW~��8t���)(�1�\���9O��~���������g��{�������nX�N�s����*��)r�XO|�R�-��{����J�QB�����Pg�}���y�}�Y�����+lk���5d����nTK�'1�;���������[|���6&{�<���X���<^�
}9�#������r�ZQQQ;�^4Q���-k�������a��V_����=w�_�k��n+�D����:����r�����-%#S�y�.�c����
e�����HD��]����F�\�s���C��h�`�����+�(yj^�M���*5���"m��4`��5Jg�q��~����_�Y�&�]a[c��^))c,k�Q���6�d�Y^]Y`�����}����{�{���{��������bv����<�������t.�U����8L��_���!�������?�L�|�����T���t�o���a�������I��#��7��S�;L������J��
��k/����W�o4�	.e�9F�g�����-���V���D���	��%%%:���l��hT�>��***���r:�4i�\9����@�Fee?�i��A%?-��i�{G%]VV��P8&{���N�hTk|�������x-�4mo,..������D�����fx�J=`H���=C��uz�W�j��+�96��:��;5���e8x��#�C#������/����Tr��r8]�>�y�f�~�������������n������)���r�p|)��a�
��X.3��[`w0u�T{����p8�|P�6m�cW�RJ�H��'�zc�[���+&{���()T��������~��J�i�d������N�:
����ep/1q�����������6�Z���7(�����7X�dw����[���7���~y������>-w�N���:���(%���}�M^�}��k����j�S�����^���h��O>�{���^�������N������w���7�����U�r���v�����9���p�B�����)l5x��:�L���
7������]������_nh��75�do�����iEG��q��P}�4~�wB��U^^n[+,,�{s6L�T����NC�����^��mX�����eZ��S2������>�4��?U<ez�:��Y9:�����;���^��A�����U�����gW��?�J�~,3�T zb���<u��f�����vm��]��-UW)�`w0c���������.-X�@���q�
_3�wJMgS��t��
c�������m[����*m�������=��]p/_�RX��M�]p�������!C����]�Y��nV�������yr�'��^�}u47���UO��z�7���~���:��n���.�;11�K��DM=�]p��t�u���q�������O��_����]�����P�z'�J��\
�z������3�a5.\������ve�a��c����Sm����k���jkk�cg�$�3Q�&����bY��b��e������a�b��n�4�����c�7`�Fp��d�+P���{3q�4M��{�������v�i{������{a�cF����t���j�����������X���F���C���p85j��u�����Y��!�����M�6�������/�{�=�����5������NV��=O��}�Euw,S���L���0�x��*))�]������������\�q��l[oj~Gw�d�$�CwM(T������
�k�c�7`�Fp��`��mp�P_�����=^���^>���VTT�]�Y	T�*Xa= iB������v?
+���~����C�N���m��{�������p8��!zk��1:��������O<M������jk���?��/�@/��65VW��Svo�����F(��	r���]��S��K�[\��l����N;M�F��]S__�������3H��A'j��Y��
��������=.%Im���Gk��xMSL�����j�!5�"��/'�y<�JH���Z��
�Paa�v��M�o�?��;cx����K8���,���]��kV��>53K'���:�'�VZN����y�r�4����;���9)-wP����B*}���������N���4�v��+i\�]5M���n�����[��GW+��Y���r�t��g����v������C)
��3H��Q��7u�M5�+�Q P�������2l�?[S�
����
�=�`;����~�*$I^���d_W^^ny|��aJHH�soVB5>�WY?�=aT�<����v/U��j�O���}D�H�����)���o�S��=0>
�_x��5�����[���?�������+�-������J���������8��{�$y�(����v.�S���
n��Os����h��Y2d�����J=���
�{�Y
���L������L���
Z���f��
���c�kx�����Du��
��~��{"��vX��ey<��W�>��7��h4j;q���h{����E�M����}�{�lk�Kw�C���Wj�����9E:�7��/UBrJ:D,8�N���`���M:��7h�~�0z��@CU�^���s���������n��C�G*���H�u|)\���;�����L�vQ���:������c�f���z��'%�W��E?������T^~{L�Ns9���B�lB��;����[b�7`�Cp����g��r�����^mm�����U\\�]�}S����O�,k�a�J��/�`�g���������R�X�z��]n�>�{:��n��1���!�e���:��_�����i�9I���^�����w]��/�@���O5m�0%������*qlf���Z�^��V*���.`W����9s�(##�v��+��s����Ay�Q~�l�zy�\56���������������+
�1��{!��v���W�mp/ub������p84|���i�[����l����/��yL<�(�5������ys�&�N�����O�w�w�t���!v����:���u��t�y*5�~��7��}������K��������Y�/8S=����W,9���U���[�(P�4[`W������g+55�v��%K�����z8�F�����I6US+V�H�@mL��� O33���kVUiK ����{��/����e����������=^�����x~~�<�v���HGP���oRs�$)iB�C:�=E�a}�������lY����i:����_�A��'`�����}N<M?��^w�O4h��>��a��z����_\��o��H��AC�C��{�d93�]i	��_���h��(�`W������g+)�~R�{�����~;�]��H���������BM*]�#E������0t{I�r=��i
EtYY�"�9`@#�@��������/�{i�	=N��D"������@�_�xo����=4_F�?�{��f���j���|�C=?���#u�?�����$���ri�A3t�_���~�W��{��u������t����GO?.GG�`��P��AWMS���5��b��_�HS��]��A�t���v��������������k�����[Z>Ty��1�;���������[|��"6���{����.���f����
Y^���SSS�@�zr_����:��bYsx=J����{`��������~�S5l��n+s�P}�7���^�$oZ:���0��L�)?��.���4����J�~R��:�����������������E�$��f�S���$W�����f���T�u-�i@������s�����]���/j��e�k
��=F��_`[���S��o�d�Y^]Y`���M5z����@Ep�>*�	�
W�_���Mp��������R~~��7���52�a����a2\������5��y�^�O_y^2�fC~��ti�������U���q����!�t�����;���g�QJfV��
�Z�����5����M��d��y	���0��7Dy�O�+7���������Z_���{'�+)..��g�)���g���~Z+W��cW5��JK���jjE�������"?-��i�������*��~�g��}���&�W����Hpo���r�\�����pT��l���N��7x���]O[C�����z������������h��o�Ag�'�����KJ�j�S��Es��c/��r�0�4�������~��c�z�-E#��5�.�3$EyWNU��A�/4���mT�=�n���
`�;v�N=�T��i�z����~��8v5�9M�p�\�t�z(����(����a���B��< is ����!&0�����2����ep��LURRa��	��������!c�si��mA�Z�C�H��` v�hDK^xZ�_{�6,����	�):��+t�������8t�=�����Gh��n�w�gO��O���[��o��������'����Sv]�SY�������t��\��Mu�.Q���8u�7&M��N8���D���k���q�j`KJ���l����h���c�wAR�nk�3��
m������
�u��*����D-k_����e����y�B��emG�{f�T��j������������-_�u����=
���{�!�����#����e v�a*���N���u�Mwj����������z-Z�o�}��zs�=j���a���R��)���rI�v]�3�������
2��?������[Gy�m=
��PMMM��rs�PA�l��Uw������}b^������a�f}�����&���VttY7����R���N��:������n����`]��F���L�{����k�k
��Z��>=���v����������N'\�3�dd��C4���u��W��;���������^���������W�@���7mY�:v��r�&+��)J9`H�k;����}�p���}�w����C����~-X�@

L[���#�Sz�4�������o������q)����i�����#1���!�@���F	
J�]p�����xaa��N�v�g���m�.:$����}m���~����L�<�_������C�O8U��x�FL�'Nb KNK�g�������/�J���>�4�Z���z��?�C����~���Qnh�����G)���2]��
Uw�������>N������}�������i���jii�_S�����	����~pM8��������}�$�C��P�$�aY_��/�V����]�=��.�W��&����B�����os��[����%M��+�������Z�������{�����~��Q:�/7k�������;����h�aG�{7�S���zN����7�.�37�E�]�C-y�Y�LIs4����x�]g"jzh����V� Aw`g3C���w4y�d�5mmm�?�::�fG�JL���m��mK�~�
1�{\J��8���I��4������
������{��$9	JN��5����X�\[TT�#��}��S��3�����s��������]{�V��V���	��9�"���M4bT:����)�u����97����G���~���Zkk���w��K��[�S{cC�`���LT�'�;��i���jT��e
������8�|��;v�����&-X�@]]<�"r�g����z��������}��,���a[���j����do������
ks dY+�"���:^G�����r��			2d�v��nW`m�e-ql�<CR����9�7����W��������GL�G��|���Ng:z/��H�^z�.��<��YJ�����@�O?������z��U�a];`�3��[��'����vm��Sus���q�L��S��8�N�q�*..�]S[[�x@�@ ��
\#����}l�e+��.�� m/�0t�������wF��dE��h��
�u����l��I_���	=^�����xQQ����������L�����A������+�iUY��S2�t��~�S~�[�����C`��dd���f����#p�2��<M�K�HD+�ySq���Z��C���
��%������)aTF���PT�O�U�#�����Kn�[g�}����_�VWW��GQ8���Xs8\�0���Y��p�M�+�R4����\N�UR(�a]���K^�����:��K+l�{^�Uj����{�`P���������PC��J,k��4y�z?�
;���5��W��'R4��M�����:N�|������n@`�NH�^G}G�t�N��o5|��>����3=��?j���h�+/(���Sv.g�G9NT���R/��������
V���9�t���*/���*6l���?�H$�������Pr������}�u����������Cl�wW�������
����K�6��BUl�����^UU��6�����������%�����O�k7������u���/��eS����t����?�L	�)q��
����������E���V�?�09��^���e�^������������n�9��������r�{�]n����O���&���	b.))I�g�VV���7IZ�j��y���	���QQ�e�����������}YA�ffzm�����f�O��|���2��^�*$I��Vj��n�QQQay<))��'�w'��oq�e�5(Y���o��g��V���������j���n�>{�f��V
;>�3�x��������k���PBJ�C���v}��#���������<���s$�+��iJ��k����g7�q�JE;C�i��x�^��3Giii�k>��S���Km�`D��������r����U���:C��(����7�"�|e�"|�����F����~�KM#�#�����[I����pl����w6K����3�e8����j�����^�{���Z{\_0q/}��j�S�����C�������!����w���/��2
����pX+���?�R����*_�	7A�(�����(���������F���T���_k������3G����k>��#���q�j`2�&N�EO�e=n�g�W*�~�gG�z����B�}�~���[*���}���v�	~|9q/�[��5�~�6o�lY+**�����!�>�bYsf$(y����.b+������\�����>���c/�������9xh:v
��$M=�D]p��t�u���q�t~�g�����^���r-�e���u
@|�!����w�^rf'v�6�P�����F��(av`g���������`�����zK���n���4��f�&B��^��k�/&{���y���*j�~KGL�����]��]fHC�I���v(������T\\�]}u|�Ef0bY�2L��o���-kW��_\���_�`�O��0�]p���0��109N����}��4��7i����������*�z�������c���%v�G�|�]9UI==�#*��\���Ji'��C�����+��~z�����������)+� _e[���@����d����4���QI��U�)���i�t8u�d:L�]w��+���{��(�>����+//�<�������>�d�"�x�z��#���}�����@g�^��_z�7�����������_�I�^�#%����A`71d�X�p�O������N�'���W+]m�z��u�����nScuU; >�.e�=V��������������D���q���


t�Yg��t��y��g��g��������refh[_������~gG���,)T������@H�������!-nh�K�
z����q��2v���M���>�T���
mj���g��#�@/�M�+��7q9��:��k������k����ZE}�7d�8L����������|���������N��;�,��a�
'M�O��n(-7O3g_�q�f��Hi�y�>7
������|����S��eL����P����w��uj�v��p_�Z_����o�F��������O>����Y���pj������X�t������}����4����Jc����A������tU��7whKWP�o|�������7w���z���A}�~��w���i����UJ�RRF����A���S555�������1��V�e��8�z��>_����AO��'=s���������c�k�_o��g�������_Br�����=:���k���}:�|�b=��_k�O���E�+bB`�������(e��o�R��U�r�[w�VRR��O>���F�������"~M
@	�M�p�������Lk��1&{����9C�m�7l���7����M���t�ZP�mn���f�#�m����-������������Fee�mm{�{]��+�l����}������5������������Z��=��$%��\�����r
�b� �r8�{������t�n����a������
�t�?t����>����v@�8<Ne�6ZY�������`e�jo]��
q����L��c�=������j��Mq�j����_#����o���jj�������q)��:>����y�j���CE6�w���:5x8	�,��A���=���{^o�����r��iii����S?�i�����E���C���z�_���z�7?����`�������w�.��N�u�q2�4�����u����������9Q��o�k����wY��/�@��{��6s�4`���W�]9U�a���3��j\�R-���f2O����;�0�z0���UWW��������u�m}��_������&9���B%9������(7S������������{��pw8=(�	���uJ�O������e�e��u�B5�����yr�'��z���_o=0O~~�j���q�7;W����:��_(5+;O���:����;����^����^����/h�������A�>�i�1�����IR��{)�������f���L���>��z��:��l�]]]�?��������bM(�I	�A��H����+�����q)I���|IR����9J������^��(�p6��=z`7q�@[?�zKl����P}}�e�������N�3$���}�v\�����u���g����F8�ph��'����������C``KLI�>'���v����:�������
�?����Bq�V���"�p����.�2N��9%r$��]��S�mK����^@�����>Z��M�]����������-��
,O�&L�U�a=����Zk��!&{�����2tb���&�}Sg$��[crm�=�{����oy�P�����B�\^��+**lkEEE}�%P��`���zI%�r�%��z�1��-z������N�u�=��+�s�r�f��H���8t`[N�K����������j���I}�zZW�^/�~�������������a�����l�]5M���n�����Y����(���;``3C'�p�&L�`����E�������cgKf�>Q|�m}��G�e�����a���<MIN��kokC{�6�����F���`���#*�
X�
U.I�z�o�����r���������S?���mk����t-l?�4U���zk�}��z��t���i�wN�#FO��{�a(�d��K&�i�&-y��x�5���_�����Qo?x�>x�aM<�(M����48�]��\	��h��^�T�%�~m��Z7�){�x����I`�r8:��S�n�:�5


Z�p�����)11�!�����b��~���7-��V�F���JM����o��������C�S���xa��X�����Z�
I�7����������>���������0"]���S���6W��?�B��u[�B{�S���7���O8����:LG~�R]|�<|��dd���P���/>����X���mZ�R��M�]��4�~t�r�?Q������.��]����=����3�<S����k�l���zH�`0��
��P����`�`�h�K��W*���]S �Z|�<k��j������Z��ey<��T��$u?q���M����������s�C!�������+T]V������p��t��~���Aq���H��i�S�����c/��r�z}�iF������o��~}�V�����H���$������)atF��Q�<�NM�R��Ko�@��xt�9�h��!�k*++����*��d,x<Y�8�6�����������������{��
q�2�{t�.�W�J9��������_^^n[+**�u�f�:?�������|�-vH��R-���z��������<V��_{�!2#�/.�[f���]g��O*�2�O�oY�Z���7�����������I�7����&*����%���A��-Upc{\z���D�w�y����]�n�:=����F�q�l��H���#���o�yB��<�/{��i�����d������{���$%$���m{~EE�����y��^����&��^<�����b������O����^��6\G]|����Oa�{0C����p�5VWi�O����)
�����:�9�^����t�1�v�IJ���q����0�6s������*EZ�k#M~������-R���d8�9������3G��w�ZZZ,��X�B			:��y_ 
��@--���u�����S�w�RS�n��i�1���1�KC $�4���8`�6"����e�������}@�n�^qqq�����q�e�������O���1MS��]�y�^��������g���������/��_���9O�1KIi��>7�����?�{������o��nu;`�%�i�US�8���$������������6���4��3G����k�,Y�W^yE�i�����0�����Y��Q�>+�R��o��EM����FM���Q��ju�O5]�������Q�PW�z�]�>�y�m�onn�}*~QQQ���xo���u�C��r��Z�j����T����Z?�d����
e
�����#9=C~w��=��|�M-~�)5VW��\3����������q%�~�)��~r8�1���s$��}�x�>����6H�0�u�jo]����*aDF�����,��3G���SWW�����_����1cF�������8�6-^r�L��a����Z���*)�q�&�E�s�[��������C��2<.����K�.'��`;��Fi��
q��pm�$�u3q�n�����^4Q��[,k�[)���:�Y4����{�>�p0����T�f���&�8������h��Gk�aG���%Z��S�\����oZU�M���>h��}�dM<�Hy�b�1�g�R*Oa��\�p���E�m�����vD����P F���t�y��?��������7�xC			�������/=}�F�������e���)ed��aC�����u�n�Q������s�iH�n��=������.����"�������!�,�>����Mp�������A������|���
[����v��:�^��5z���������%��s~����w`Wf���LW������������w�T4b�u��Zkk���w���j�����cN�7;'�]�;�����r�Z�Z���u�M���*6�*���r�%��I`6l�f����*�~���K/)11QS�L�os����������_���Ys�����7u\���F�����i��?(bJM����_��3$���_���_���_�=l��[O�(T�$������g��4M��{������G��v�e�Ht*e�!����:��#����e�����#p��&O�Cwv'�E:��kt�9s��+�k�+/�����s>�>~�q-~�I�=�PM?�
*����#�����*aT�Z�Z'3d��9��U��.Q��c�46+�]GQQ��<�L=����F��>>����x<*))�sw{6�04~�����R~��o����JK��>{?%�+��k��Z�����N���vh�;���PD���6�_�%9J���	����q+������~`{��F��.��y ���`{�Qcc����EEE���sY�"mA�Z��C�H����X���z��;�����Z����O8U��~��	�q���*53K�5[���]���?-~�i5o���s���V���V�����L��N���{�p0��s�L$�p��\�P��v]�V��J=4_���`������SO=UO<��e�4M=����5k�F����lnw�&M�M�,>K����k:;��j��4a�-�z��4MUw����M��o�����D��TM���r�Wa�m�}in�n`��p�?�am	�,k��$yS��^_QQay�0���5���z��\�R��5`���Ao��[k?z�W�����.�R�E�m�������:N��8V�~���=��e�����e�ic�g�2L��?Y%�Np�S����w�^jy�\��t����j�[�u�8������I�&)������G�Q=��#�={�


����--m�F��������^[��22�S��Y��@$�um�Z��S{(�Vm���S���\�Syn�������i�!R�7�s3$������W72�#�����i{�6�=�D�5�������������5*\o�C�����zz����F���/����W�����K��$r���|��r8�q����p84r�~9}?�nX���?�����h�w7�6o�����C�<�PS����s�R22c�5��S���R��t5?�V����Ypc�jo[���G+yRn�����[�@@����e=
�������!C����=[���ji�Xuu/X���������

���.�M3�������ONMu�u���v*o�_3\�{/���
�5V�7�&������v}mZ_��������!���R��^����H���	�kL����WTT����i��n��!y��5�u�Uz����e��^����:�������qg�A#F��+��!���������^T����DI��6}��G��3Oh��35��S�
�i�'��3����V)���v������U
�����G�p35	�Ot��~��~�m�z ��t��*'��o��a?�/jo/UWW�����J<P���U��.�s�5i���o��5��<��)x�P����/}.�r�.���r�10���3�f�����f2�[_L�Ku;� �`Ap+l�{��!��JSbb�����z�l����=��������I�s���yb>
����g����V��9:��K5j����������Cg���O;K�o��%/>����^�	���������T8y��������	@����{�d��\���l<��[�hS��qr�%��C``8�����GY�;;;5�|]x������os{0���I����g(��RNP{�)�����ZQI��|�s;5!)������N�V���^4Mm��9��	�9$e����"����	����QS�����!I_���4��/B|_���=.��]r9��	@|��B�Mp�P�>��g�(//�<�p8TPP����on��ygX��m�����{����-=/6M=�|�ly���@|x�4�;'j�1�i�'j��Oi���^�_�|�*�/Uv~����<S.�'��u�������02]���V��]�������8e�R��c����0{��
���O-����m
�������=W�3F�������{�.;���)
������0��q+����^[#=���C���NS] ���~uE�>_+*�!QC8"}#��p(��	}��������)5�j~�{R���5��y���`_����b����F���oY�6�g�.�7t�P%$$t�wpS�k[,k�c3��
v=�lk�������������b}��<jL�;k�S��=P��=P[����������������*�r�mz����r������������J��,y�����W+���v�����5
�kQ�)��H�_���9�t�I
Z�j�����&-X�@����������#j�����������������%CRQj��g�(/����P�����V�������L%�����hT��[�5�z�N�������_k:����kM�_�H�~���hTm���B_;�h_���>����r������:�m�|�x�����M��������v�=�a��������R��{�hT������n_�����=�?������?�IDAT�^���������.O�<�\M?�d9���w���Qcu�5?S[}�����>���
vYO�����������GUr���~�)���{ >�i	���$���Jm�WI�q�\Z���ve���I�~�t:u�g����
,����������{|����hu[�V����{�-�ah\F����(���� ./�����6��u�� 7�_&��F"�W���pD�tE�WO����&%��m�1MS���!��}���R�v��%�o��k�7��9%����u�����KG�s�HT�HP��� �2�m��"���q�I�@/��J;�n3�!�$I�z'Z������o=����^��K]�5X�<^y���= k��I���Om\��W���L����T�y�c�l���<���p�,�����������zun$�g����^Y�S����OQ�����9�a(��B%�HW���m��
7t���e�8~�R���)��\.�}���?����-�TWW�����Y��v�����������;��&�l�(���	�8����m�����S�2�d��!��j�tb�WS����e�~=��������6(SGf����a����D��f�i�������������}M��v��T�l
n�AR���<�K���&���\Jq��4���MSM����1A���u;��qmB_��%O���#��7�uX��U%��r:S��\d�������������O=�x��v*�w�pnd�	����O��'Q$�q}rz���E{����	`����������������O�{R5���������|�'�-,���O������
���J��AWMU�ck�_�l�0l������kQ����H�{��<��=�\�������\S^^��\g�y��L����i���Ke->��{~��[���;�'o�J��$5vJ��W��lO���|���SM0����G������C�������A������L��q�O������
�04(��A	n���Z���@��o���1a��LI-��Z"A}���d��� _���\�KY�c�����-�F��kIN��0�����KIN�E�=��n�^�*%I���e�O������w�$�H[P���7�����8.����M����=s�X]����?Z��{��R�=/�]�����������+��������%�wc?�+�������GS�9A���_1�L�(�{���&��T��FU�W4�vS�����B&�;*))I�g���y����h�f���z���u�)���`B�$u�#Z�����>uE�}>?��Pf�m��orF�Z^���JO����)��g�]zh�:u�:�|1�n�?�������+9Q���y\J����3��`X���>��kz]������,w��9(��R�'Uf�~�xs(��>��t�����@�:��*�!U�~
�!��\�s9������S�8��"Quu����Sg�C�n�6�>�2<ny�N9�{,�{l�4M���
�y(���`Y�D"�����w�o���lod�������/�}z�������z�>kh����
��L�qg{�ah��
W���-Z��3*���
���~���I�<<_<��&�8R��;I�Cvl�v�!�!�J(JW�C�i��~i	���O�vt����3��RSS5{�l�w�}jkk�\�|�r%$$���������A���T��������D��g��(5Q��q���uv~;�g�a��^�}�}Vnw�����&����t��T�M0�6�+m_�v��\�6�`7��q���Fh|j�v��v\���}3R�o��}������Z�uB_@k:����\�g!S�
kK(,u�wH�t9��r~kR_RC�����@H
�-:$�}��F��M����`���O5��/'�y�%��-[�(������^�+,�[,k��%O�����4M����q����|��or�\���3��)����i����<D���Cx��Z��KZ����h����M�@@����>}������>�T
?a@��
��p�]5U�O�U�g
��R�K
lhU��c�L���I`����9s�h��y��|�k>��c%&&��#��sw;W$j���K+[|�
R����Fx�4>=U��_���p�h�����'�)�vX�����?��Iw��������;V�^�I���~�#h�
�0|��A����a1�����.����hZz����"��|>����|k|Ut�+T)IQI����������:_���\�u9��rn�n��_K0��`�[����>�%:���&v��`'���'I��$y�������-��\.
f?����-2�a��C��p�t���:�~������^��?QG^t���
�qg��%��j������O�����'�=�����;�4������5h�(M?����`9]���_�D��f�����<�A
�G0k�U{�e�5N��2��$��������5o�<�5o���t��������#Z�����N�#}��������1��JtZ��RS�j����r��,�

��j��*,��v�,�Kw�������N�Z/�����+
����^���Hq:��7Y{y��v��jCW@k|~������+�p���G�jD�����P���\�Ky_���r*���3��9_8"_8�M�_����0��q�����S}�.��1�F�Mp/��U�:�px��<�rMEE������lf(��w7Y��.��3����`�HDK^|F�>�Pa������C��Pg)�A����t�4���4����^Y�O�{R���k7�������_��=Q��8F�)�1�0������(�0M��T����)��������
W��2���5x�`�{��Z�`�B!��r�������{����3MSu���Z|���k{r^��<������^��=C--jK�-�������i�H���u��I�Q9�Z�����Z����O�:��M�0���^i�����S�24>5�o���@�����$�|���FU��|:�6������O�LS����C_���������>�S�.���>T ���t��������rB�{k�/������Q`g ��6V��
T)IJM'����z8VUU����������*�a}�\��C��X?�} ���N��}���{75j�A3t��.RrzFl�]�a^2I�K&�i�&-y�i�X���������������H?J��;Y�y;H�_��)��r�Z�^�����M������s�����&�=LAA��>�l=����D"�k�{�9%$$h��Iq�.6�QS�����CM�p�'|��04����)�J��{A=;�z��&�o��j�Qi�U�w�g��d�x���I[y���z��E
�\��cg�Pzzz���x�MI�����GMU�_�[}k;��G�?��T��>��_7$�9_���]�u��u�/�1��`XM���m����v*��������%��?` "��6��{�*�$y�,��6m�}j}QQ��q3b��-�i{���������)���{�.����iF{\��7HG~�2M��)�0e
�#p�<�\-�%-{�9�Z�{un(����������}���'���c���c�@��8���1J���'��Z�$)X���[�(��1J*��c���e���:��3�������F���O���h���q���t��Z���5��
D{~_��R]N��H����
59���8�v}����F��~S P����i����0z��aJ�)}�gh�b�@�r�������N�W�#��jP��6���`_g���+_2%�F�j����KI2�m�����r*��R������������=Qu��Lr:����E���y�/���s���BG8����e�@���{�����=����u}V�H������`9S��4���������T{C}�k
�C{�p�8��{\YrZ��?�,�}�iZ��[���'�PU��sM3�������!��j���j�����Sa�'yj����jzp�B�}����a5�/S�AC���b.&�c���:�����SOY����}�Q�w�y*..�os;�4M�tU���F�_�3Smh�G�3R����o�����7��*[y�e��q�*+�VQ�%����4&%�0)AG�|5��4Mm
������:�oM�_m���IR�i�*VU��S]�r�N��\_L�s*��T��%ws]��������{�.��*��M�/���[����+}�!:I*�!�WQQa}^a����4��f��fC���w������Io���|�N��5FG]t���F��3����nM�q�J=\U�}���?��e�{}������-UZ� M��I�x�QJHN�a�������������ru������nV��M��������=��)S���/Z�#��z�!��3G������hT��������o�z�e����)����JC�������y����
�7+=c�23������a�O�(��������<O��+e!@���s��q��L�����=3��~g����{���w��������6��6�l��0c@(�$�*������C�P�*��TH��9GG��>���ltU�~��]�����q����S�|�?�$2w�	�����	����'�K"
�t�+�%*2�b�B��e�[K�[K�����6��d�>""""""""""""����=""�A{C���+�t@d�\�O��H$����v��������^$���&�\V�oY�S�e�������'�E2w�8A�;p�}����� ���DD4V� �l�R�-^������
��F"q���u���'��O^x\s=��x���\5��Y����������X�������r��T��6�X\|���4
���n���xO?�46l�����,Wwf�	��0�"������Q$��\��:�J6��������p�)�,����?�E�
U���Zh�A@�MA�M�U���m]}c�e�5L�q����2
)��@��#g�=2@0�#��qx�[yNY�_��S��`�C!�KMS�
��!�W�\�JH������VF�U�+**�����>���'�j������~�[����h�����[~O/b#"O���p��+�[��om���� ����h;7��][_A�%W����P<�j�+&"���ca>�f���������,�@��:(Ks!���u=�F��+�D,�'�|�v{,�SO=��|�;����ru��,m
��0Z���wHc���~f:mY
I���;�\�8u�"-��}��/,]�(�]���|UF���e9�������p�-%����l���	���	4�S�K��
�|':����,�;��&"zm�xj}�p2�7���2����>"""""""""""":�1�GDD4ho��^������������v�2���!���T��<(��3;���8>{�9�x�/0�3�B�������#T^tY�#"���>?.�����N�~�vn�������CY���O>@�'`f����v�]q�����~;
~p��F����}2H��A���CUa���T!��A��5k���k���sB��|�Il��>�/�H�&���
�L����"
��:Q�s�����D\�9�����o�������!�[~����d�2O9����n\�O
����1�%;�i�����g����[�:�:���V@�,%�|'���b��q�Bg,��Xj�P�r�3��w>E�����������������&�{DDD������{MMMi����!�������V���������[�;�dA����������<���DD��������q��5h�z���	���=��������_<�o�
�����>q�yI�D�n(�m�=���e�T���������X�iR~Dt
Ap��7C�4���/��@ ���z
6l����Zm����`�}$���n�T5>�yP&I���V_�h��������V '��,WF�+KX�sa�/�w(lh���>CK4�,�i��
t�0, �E(
e9��W���+��:�S�nY�;��������������������{DDDE4D3\Vz"��^p�6M�p���������2�h#V��v�m��R��
�b"}A|������;#��_Z��~���Q9�+#"�LQD��Q��Bt�4a��M����uK���cx����O�{���Ko����	�����7���|9z�����8O4�r!��ax���h���D#%�"�����q444��������~����a��E,������@G#��wHc���~f8T�0�������`������jb����Em�M�s���%IX�qb�'u���a�P��@���c2�}��>��A-5o(
d�'��re	b�B���n�r�I"�Jj����p����}'""""""""""""�,DDD���w�-��
@��]s����V�f���+**N��H�<�f���)��,�~����#b�}g�/+*.���X����)DD�EAYn���������on����"����p_��"���2�/�
+n���s&�b"":�H��Y���[����kA����7_!��j��<�+�h��$	��s�~�i�����s��1<���x�������?n�h���6F����(���D���2��O�$.X�|��6F����x'���[,[�8����+�$b����nG�x�<��R}#��u6fYh��h�O�/K(P�|��y �����i��v#��aeA�W�O	�yR�#""""""""""""nr�MDD�%��{3�q8�s!��S�755����t��� eL����v�2�[�tEOr��������~=��e��������\��;'W��0.^w7�}�.vm���cm#��4��p;���.��7����+ ��WMDD�A�]]
[�=�`3w�2�c������X��%��C4B��������O>������>�����w�qXp'�%P��/
}��UF�����)����,GM�����v{o�'hj�����)�,�����4]���j����@�nZh�ih�B}����H1�����u�zj�V��D�2
)��@�����;�[z�z�uxi�3�2�S�}j�#"""""""""""����="""d�����,L�=Sp������B2\(�Y5������������_�=?�|��������+V�7�
���w�������%���C_����_���{G���=h��9%���������Pl�	������r�~�=/�#V��y�a!������U��d�H�)�n�����c�=�����566���^�]w�u�{#aZZ�1��8=���	J�v,��P�P��{	E�7!0�9�T��MM�������#��������5������K��j�����^���{~�M"�(`���yN;n���aY8��.��o �1N��v�,�D���~X��)
(�e��
v��K"�,��Z��Z��:$qHw>%���)�S��BDDDDDDDDDDDD��{DDD��+�@0/]p/����ci����H�m�q<�\)������;i���b�������_�z
�zp�WFDDAE�]q1���������Q��G0
��;�m;����/������������p�s&�j""��D������
��M����P��������a+�e�J����t����c�=�����s�����^{
��z��.�a��/��0B���/eET����9�V���6*+��}_��?�"�|��\s���;�}Fz{?Ao�'hi����(+�!��WOX�4uH��2�
e��?�w��,�i��0_2�7��O?�@DL-�Z��]���e�
d	���|Y����\�0��q|X�X�yH�O�_U�Q����������������q~|�MDDt��:��z�me���������_ :<���
V"�E/��fA���EZ$��}_��:����P93fb����g�:""���9���g�+x����=o�-����>|��?c�+/���U�p�:���Ol�DD4�	���3��K��x���q�����{���l���8�_e��������������?�����
6�
�_�i�{=Z��0�Ga��=��rm
�\��8 �g���h��~�/v�
]?���a��6��N ��=;PTt+�W�#�c��DA�,��Yv��;���eYh���a�pu�z��M'a�:�%t z�� G�Pp�C����1t�s}��.-�.-5p(��2��B}>U����������������hjap��������C:��O
�555����v#///y���?mK;Wt+p-/M���eYh������!��s���$��uw��uwCV�,THDD���/�Un�%w�����a��W�h����c�{oc�{o�l�2\�v��,q""�~�N�^Di�y]��M���h����g>$/_��INNN��^4�����>�v��V�J7-�C1���>���H��v��](�����A��55��o�����o{���~��K��=\���_� ��������\Or��,t%N���N}�D-@�a��0p��
�(��D�o�S_�,�'g��7@0�#��ak��d�d�O9��K�y}�""""""""""""�3cp�������{>�>���BQ��l�����H� #��8�H�X�W���L����:�������_�h���X���"oV�WFDD��jw`���b��kqp���r��h����-{�B����7�+n^���W1�MDDi�2�</�~_�-@���Kk�����{�|������L
��C��'�@<�>���{��n���K.AL7P���`�������>'�}.8��9�
���Y������z�Z�;w���72�GgE�

T��xR��$t4�t��P�����ug#d�i&
�OUP8�+�%~��%HY��ua�@[DKWEa0��$�}~U�K� 2�GDDDDDDDDDDD4-0�GDD�^��{ehx<�v��D"hoO�=���"����}x$�<�&�}��QV{�����^����{
	-v��6�W=����85C�DD4v�(����Py�eh�?��[_A�g��Fv!w���x���m|K�_�%kn��������h����8~�
�����#�������Y��)� �u
����9<��~�i�z�����|��������,��P�v@�g����8r�iX��t/;A����{.�x��e�����n\�w�����1�Eb���@_kl�]83�[�$tI���Hr��}����[����:b	t�R��x�t���
���"C���@"""""""""""���{DD4�e��Wz��^sss�������L1����S�Oq{�Al��o�~�aD��_z%V?����0������j�TU#�����x������������g���/`�U�����!o��	����������,Ep�!��8~�����v(����!���T!��T^^�{�����a��0��s�����b��(B{"�
�5~
��������=�w�oG]���E5!�O��W�����
�+e<�h�j���Nv�k��Gs
9-@�n�S7�a���$1%�w�K�G�^�O�z�:z����{	>ENv�;��q�"""""""""""�)ij�����Y�0�I�5�d���lkjjJ����CN�@H�2-���������3G_�9������`��W`�g���-(����1*�]�����h��a�������7���]��������'���������|%V�]��C���������;*a��G�K
�4#����~���W������Y��h�����w���6o�g^
��5���3�8�CQ�sa��	�����d������M�1��_Eq����_=��!:�,a���%g�x�0q(M��PTS'�L����G��:���0���!]�r$	b_o�'�'��h��� _J�O�K��z������������hcp������Hz�?Nt�s�����n{��n�����VA�L������o��_���q���(b��u����������N��t���o��oE��c���q�������];ph�����k�a�eWB��	������������x�#��������j��t�7�����
Q:��8��g����`�!$RhWQ�w��m�jf*hi��������I�!�X�v`���27O���@�����5~���e�p\��a]�d�'}����}�%����a�x4���xj}�����+2<���Z"""""""""""�s��=""������K���f+�MM���������]�N�,�B�{G�T<W�{�Y�b���G���h~��yX���FQ��	�����7�$����0��+q�n?vn���/?Fxfg�!��/�<�8�]3���g��&"��@�s��GK|�����vn��c�7�!��j(���%�.�BS(��@]Zb`pAI�x����o�e[(T�@pGV�|�P�n����h<���j����@�nZh�
��7�sc$��9~�>���������$�p0���.�pJ�[@�,tk	t�8G��;��oh����P�X�t��Mk��{��
	&<�������P����s� �9�n�,��7����}Z8|�����+�{Ko��(e�B"":_	��Y�1�z!��a���b��mHh�����G~������o�
9�%\5Mv�,�������B=���qn�X��
��+�ZV��*�&��n�.F]0��a�z=B��w\�3�r&��������z��������,
���c����
N����X����t�k�h���|����0�k�Q7l�K:�)A����}9r��;�:�	��S�Sd�U%%���D��GDDDDDDDDDDD4��#"�i-Sp�M�{�����\�|>@�����\=y��ui��?�G���9+.�5������������x����������7����"��3�}uM��7�`�[[1����b�:��^����9GM��/G���7�e�g�M�>W�1�ms!�\�������c ��Pc�WkoC�>D�4��?<��|�;��ax/�����|�=Y=Q�I��r�
����%�M��Q-1�C_
����q�@���'�O���
�e	����!���d	r_�Ft=�c�xj}����7��o ��Q$�|=MDDDDDDDDDDD4&���eYV��^Z m�������TTT�GC��{���U�@-q���	����|��b�0���'Np���[~���.c���&����E���koC�����/�����v�,4���;>C��J��y�.�����DD����������N����t����v��!���3\�+�(�t����(j�!�hg~O����������D u����~<��S��a<�8U|��,����z�����,�����#
f�U����&���,�q=�;������ZC����������v�6����
�n�q�����:c	t�R��x�a>yH�>	r�#"""""""""""��x�"M[G�����)������`0�����~������f<�w������o���_�{���'���	W��6'/\%"���d�\��+V���o���M8�����~�[���������[��������h�$���a��G�s`�'2��;�������y.\3�B��PB��`��4s������j�s]6������_������z
�<��N���}^1�t=��c�z�]o��]U-�y��=APlSPlSpU����eY�J��i)��:�c9��	�K7�����v���"
	���EB�,�P��������@\G ��v�|��P����,�GDDDDDDDDDDD4�1�GDD��������-P�\�l�)�������(��t����z�V��V���������������eX������f�+#""�L�^��.FO����
����D��;����O?�O_���u��x|��g�����;�y~�|9z����5�[lj�v0��;*!:��*M]�e�x4��@����5���������,�
�`���;����q�����ttt��g�����a�����_L3spx"}�������U	��.W%\�*�]�P��sR�d"
T���sR;��$t4�t��P���6������~���a�m�Nt�+�%��R���
!�@H7p4����D��0�O���%������������hZ�U&DD4m���X�p"�g�)477����n������7���&�E	�e��G�a��D��������K���r;$Y�B�DDD#�[2�~�'�����g�������#�7�b��W�������K���u�MC�[E�#���o���� �M�G���@
������&��i�P�����D��:P�w������,����{��SO���5�}=z�����@Q���������A�_"�2e\Qr}U�>W%��J(J�9��hr�Ud\�w�b�;e�O7���.�����O�,��u�;�K��|��+Y|oZ3M���h�AP�T	~EI	�y�x��;'"""""""""""o����?�>�W���z���q��2v�+//��G�������5ygQ��?�����h������.Z�k����LpeDDDc���B�������[6��p����,�����?���j\�v����$Ml�DD4i�����V����-�\�WC������r���	���$���Q��/��i���x	5>*�N��x�������O<����������_|��s$>��$�!�>���V��D����>OW���A>W\�����03xe	+|.���R������6�C�@��%S���1t�:t#e\��D�2
;�*�N����q��������R��"%;����c��EDDDDDDDDDDD4�0�GDD�������R4<��)�����_HUQQ���G#����g��:
]��-����BO��8���b���������K �H���E������A�7��s�&4��9�����k����"���V,Z���9��db+���g����D�ug�hZnm�v0���� ���I4�e�-��6Fk8s�tf:mX�wa��6��z�!<��c��N�{TWW�M�6���o�����d$<������\�2"�x'���S����S;����r��,�2�����%,�:�����2j�8��>�����Z�����0L�8���ip�
����
��@�O�����?a�?a���K�\)������X��Sd8���GDDDDDDDDDDD4V�����h���������777g����|no�m�O�si���������A�;-��\��w���&�0""�	"�/C��e�jm��-�����0�������O�?�_{��p����o9e��T��P
��C`�!@�|�|�����
����}�?{Ee�0M4�EQ#�����0�(���D���:���n7��_�G}4�H�|�
l6��];�C^��)��D��C�������q�}&\�*���
|��$9�Q�D��C����"Oj�O3M4E5���d��>�����5��"���x-������	���y�)��nKQ�+*t�_���u�@0\���}���|��"C��[�����������h�`p��������������,{�p���755��_\\�� ,�H��}�,r�W��"|��'�����.����������d�:""����]���3\q���z�V�~s��}#�7����^��-�0��+�b�:��������\�KK��y����]�_?�}qt��x�U
�5����:M_����`�}$��:|�����(�����%�{�p8��/��v��^{��s�*.�--����d9����c�bG�Ew��!���p
v�;�����I�e�.���&��v9P�J
�&L-����~n�����Lp,��XB�'��	r%	��YF�2�+Td�Y�%L]Z]Zj�P�Qe���@��P�x��#""""""""""")���hZ��!�����G'���SV|�,+cp��������&:e�V�}�����'x��C����sEI��[���w�E�RDDt~r�sp��b�mw������yz���h_�4q���q���1�z!.��v�Y��(Mp�DDt.�%n��2^iDdWG�����ah����o>$_W���,G"ja�hg�!��.j|.�8m��.//?�0�q�b��s>��#��v\q��~������o%�~,��"�X��D�p���C���7 ��F��B4z��atu�=d\��Y���7���
Ng9DQ�B]D��"
���c�����4�7,��8��1�
����1�q���m�6@<e�[Q�H(�e����Ws&B��������.YJ���C���%q�w�%""""""""""����MK��{�h���Y�2����P(�v��f(�v������]�����w�?8��g#�_RU�5?�)�g�MpeDDD�������p������N���	��~=��������_<�o�
�����>���$�$��3��~^i��|�{�)��_�B�=������*i:�&�"�
���0F��*
��:Q�w��L�����x�����O"�H����o�
����+WNx=�UY��3��������J��S����]'}��B�>]Nxm��H�"�C��|39*2����@_�`��GD�q�$(w�P����|_r��,�C:���?�O@�B���f�iX<UP K(Td��JTQ����\X7�
�
���0�SRB}nE�j}DDDDDDDDDDDt����DD4-��_����ga�x�n{� �Wk����p_V2�"G�4
�~s+>���H�����9]���G����!dq�c""��BE�Y�s��DG�!���	>����h���cx����O�{����e��wn�WMDD��kE�Rz�9���p�yfXG�c���r&|��C��z��G@K�6Fc_���}����2�]��q@����g��}���g�}��>l�e��l6,^�8��M���QTt��_��c�����������U���sir��,���A�p=��a�P���~���dYz2HlM��
�k��}U����v�&Q0��b�]�5y���eY8O�>�����1����G"nY8��q4���[�'K�P_�"a��"W!e107-t����%����S�U^E�,2�GDDDDDDDDDDDg��M;�i�@8s�=`���"�c�/fp]T������h>�m�-�7��h~�%W`�#?�;� �����|n���������om��omE,<���c�����|�eT_v%V�|;
��Lp�DDt.(N�d)[!�����
}xZs��������46�e�5Cm �c����������P�P!���As���]w����V����/�UUQ]]���&��U���/������mj�W����6[!l�B��^��,�v,�;�Ga��*=#��#:�P�@��(��r����
v{	�aj"`��z�M����s=�q�����Q����%;�u%F���h�:u�������u^ID��.}3e	��[����u��O}�nY��C�+�I<��I���s(�!f��H�ME�����i�hnnN;F��v���3����Jh1|��F|��eX�y����\��c���Z�T������������������8~�`�	��c�������(]�+n�KV��-�yFPD����\?z�R+��+M�������;+��� �U�T�&��"8#4��G6QD���j�ne�|PSS�u�����_N���,���x��1g��[AQr�t�c���~�zp��W�}X��1(J���'0���K`�� /����e���������}���k
������}����2.IN����rW
v���g��8��V��D�

TW�xR�u�u4Dbh��W�P�����pog��0�g�hv� �P�P �(T$��T���l�6�t!���H���.�!>%5���%�o����������������=Q�����'Zf�<� Rr����H������i��K �'��B���x�O��`��Wa�o����T�c�j""":_(v;�^�K�����v`���q�v���?�w�����YX�vj�Z
E�M`�DD�m����t�g��[�3��bz�9���7���H��h	��8����+����,��P�q@'g0`��%�4
[�nM��0l������1k��,Ww�����b�F���a\:���",]�����P����c�Y���Vr��D��������e����hF}�{���'e\�����]�k ����
����S�����~x�n�!C]2�C}$�#����,��:'���|��7�C_�ME�*�-
�f�/f��E�h�-W�C|'�}~U�G�!�|CDDDDDDDDDDt�bp�����L����<��)�MMMi��Pd��n�\=1�E�l�8���#�_X1����Q4g���CDDt>D�.��.��6`��M����u����#������??�%�����n��?��N�����s�(��b�jA��#����8�-}�}�J�3K�T`Z�b�
�q<:�����mG���B�:%�F]tb��}������~�il��EEEY���s����������A{��c����[1������X	���Ng9

�$�MSG4�2���n@$���Os���0B�}�`�W)�����C}�J�]UP��	��h*��V�\X�s���u
���|C}-�8FM@�n��D������~IL�Jm
f�
|�����nY����AP�Q$�U�d�O��Sd����������������hb0�GDD�N��^z����L���%��R��<(E�4{��eY��}>x�Q���3��m6\q��Xv�-%vt "":[�s+��g�+x_���y�Mh����������l��W^@����b�:��.�����(I���
�����|=�p��2��t��+�o����)���3�#8� |"`0
vI�|��}.�������+���i�����n��bx��'���|yy�/(�(9X��W(.�-��@�����_��� ?�V8~DQ��5.�\����i��4#��
��"�#[H�l�z���;R�%w ����k�;��U	E�OxMDS�K�����Ro��Q���H�-%���`LP���k��5���!��D��EB����&#G��d�y��/a�/a�h����!a>%�sH"�KM����)�W�H��g�&ZZZ���a�_���j|��um�����;��s���5��+x
��"""��������;��������� ��>�}
]�����w�6�/Y�k��l�2^lGDt���E������u�3��&z_��v0���m|{v����Q�)S@!��`���r��8u�C��k���X;w�L;''�{>�/�N�������P��_C_����a�%�H�>��z�������a��GU��Up��0���ah�D
v��O���V`��x��H� ����)��Z�kHw>�@�O�=^�T��D,�8�����L�R:�
�|(Cb����p<��x;����"��BY�l��2��<Y�M�����D$��a]yUQ�)��>�"A�{DDDDDDDDDDD�
�!"�i�3�@G\O��M.�����������/I�S+|��z��V=���^�������y(�?���.��""�	�:�X~��Xz�Z4��_n~���x���w���]��]�k����U�e+&"��&ym���������[N��|��xk?r���:���"��0-��j!t�2we�DP�q`����:��#� `����4
{��_�(������
�r��\���v�O��� �{�
@�K��U7L�`�$�������I7�(���� ��P_,v4+u����w��7����V�`g>��
.w%\�y������(�(���@���2���>B�������1M	�
�9q����%t�%t��j�q@�,�@�0KU0���@���r�/nZ��%�9�y�(�d��d����PD1��	��������nwD��E�MMMi�J��B�������m��������������/��\��#��x�'Q6�����/G������;�����?�e�#����o���������b�����N�����7�(�{M)l>�����x��zW����s��t`9Euu���#{n0�CQ�s����S�&��sOE�~��������O;���O=�y����,W8��+��p0�$���x����z��A�C�)�>M;���4�84�8�{>H��g
t�;��I��
��M�� ��s������,������1�Gbhk�����;R&�.�@�n�6���mQD�"�DQ0���X��Ed3.gZ@ �#��2l�[��!>�����y������������h�`p�����}�����V|����0e���9��B��h+3\�U���o4b�>x�Q|��[#��7�k��S��^pV�%""��WRU���;����W���o!��h�P�`�<��x�,��[X~�m��9{�+&"��b��C������z��d�hX�z����Y	�������X�a4�G1��@�]A���2��4eI������<�L��a�?�g�}=�T���:HO���y���]�2�H�!i@8t2�7 ��J]���bG���}����t0�w�C_\�
��-+uM� ��iC�����O.~cZ�j	��}'�}������~�D�f������Hr�&(T$�PdT:l��*��"���B���-e�&�)a�?�e��p""""""""""�q��M+�:�����,J��������(1sO���5��-�B�'`�@$8�|IQp��a��w@�ya'�d�+,��o����y�M�z�5�w��`=�����������+�b�����^,GD4I.y�^��GG|�0��sc���~4����a+�f�H7�i�)Em �.-1��%�p;P�w!�>��i�������O<�����s>���{��?d�m��Q/����V��'���A���D�4!�qc!mA4�������� ��(��U5��r:+ �|_�h(Q0��b�]�5y'�SY������ZJ��.C@7&�&�������E�����<YB�"c����6~IB��5�DG,��Xj�hI|��������Y�{DDDDDDDDDDD#�O���hZ��+K�Nv�kkkC<O;���YO�����`L5;���?���w�h����q��~����c:e��������e7����?���7��P���?�k������Xq�:���
����A��rl�>to<�'}x0:��kx�+���YxA���
�Q� 6�N>NYD���*�v9��w&����z�?�8:::��9x� ^z�%�y��������&��� '�"��\�2�w!n@8T?�k@8\]����,�@$r��!tv��Ng�`����}�J8�E~�G4� �aS1����\Or��,t%t�%;�i�}]	}Bk2t�:t{�'��	|��BYF���r��<Y�M���@�}���O�� p+��0�r2�g���HDDDDDDDDDD4E��;""�6b���H��$��A��v�O�577��+["
����fA�FwQ�i��e>y�Y�q����n�~��Xx�5��CDD4�H����������������e4~������h>������g��n��ko���9��DD4i��=(��2��������M���fh��g>$����6X���X��0�C1���b����n;D��Or:�x����������7�����CUU�z��E(;T5�j>rs.M�Y��x�c0�7�;��a�&�&�J$;v`kr\U8�s}�C}�!��!J�

TW�������h��R:���5�����hX���G�����SP ��v�0���@��XYL�Y��Z���k8$>U���W8e��i����Mu���_��.�<H�=9����vn�������n�E���xc=���o�����-�r5�^�=8��Q����&A0�z!fU/D��6���*���
�v�?�z{���'��K��Uk���[�S\2�U�x�2r��Fx�q^;����i
��zr�������(�t�BS��a�h��h_��8P�w!��.��x<�_��>�(�������{7�v;���z��6[l�"��^��,�v�p�`��a��F�ft��2�8B�Z�B�h2.�v�\s�rU��������Se��n\�w��:;��%}1�s����Z�	��@��� _�Q�P1�aC�"�-��e�i����&��8�GS�� ��
	�y��y��=""�6����0F�4�<�u�1]�q�����K���&�W�������x4���{
_��yD]v�E3p��~���KGt�DDD45��������� ���v��B�=#�W�4�~s3v���.�+n�3�/�E�DDS� p_<�2/������9�a�'�������
��e���N�'��q A}0�����-K���P�u�&13999��^4������>��f�����\��	���v{	��V%�-�D,v�pB��d��p��9��<��i�������R�%��k�`���0��U	����1���)2.�����J�F2�W?$�w8�����xB������"�q@�$�����i�LE�W!Z�,&�t�B��@��p������N|W�U����������������/��B��h������#G��z��3����%3Ft��/?�;�����3�%	�r.��>(�mD�ODDDS���������7�C�'��-���|hd;[w|����xn%V�]���'�`""J��?]�����=�D���
�)����!���0[,���h��0�cc���������,���d����?�0�x�	h:����������K�\��	��c6�����Vr��D��}��O��"�`Y���0����}}_����'�;�����3�G��[�����2�3e<b�8x"���0�k�j0&8<g�1|���a���E��6�8m�eS�#IP0�a8[,t0&t�ns�"���"�t�sH"�ADDDDDDDDDD4�0�GDD�F��^)Z���Xsss���%!��$o�/��~�?��=]�������'#�sF�|���_���|D����h��d��j�\��}�`���qh����`�����;7���������X1�-Q��{W����}�V��87����_�B�]Up,��b��O�4q�?��@������,��u����_U&������<��z���,������lX�|y��#� �����Y��������@4�2��
���6��F~-]�G0�����qY������]5���*�>���D\�q�Oj�O3M�hC��
�|(�!aM|x.dZ��aw$�2�
��,t9PfS�'K�	�nX�9p��n"�khCjx_�!���;���%����M�ea8Sp����:9����vn���q��,�}����4M_o{m|�h�c�:����oc��!�����G�.Z��E��}��������=����.�z����.x��G����z'�j"":���Pfy���GC���O�����n�� �u�x�O��
���A|�f<����^'T��o�SYY���^l���i����k��f�a���Y��h����k\�ynL��f�H�`���d�/i��wd<�z�����(J�`��.W�`��J(�o�k"��l���5nG�x���������e�^��p ��X��"�����v���(Pd8�iNx����L��:c	'?w��;�;���2|�Yd����������������hZh������p�Mp:�!�n@"���#G��-1s�?��A���d�y��~�k�Q}�_�o=�C�s�25
��9k��S\~���z�V�~s"�������u{����T^|9V�]����3�HDD����@�_-ApkB���vn��6h�}���r���s��,�B[DCm0���v���������,�
��L���J�y��x��a��BdY����@UUTVV��
��GU����v�G��q����5 �G8��h��B��D���n�>KW�����r�C_\�y�e���D4)��J��.;��7,���d��n0����lO&��x-=�S��2�z��k�a�"�%
�i�i1��2,�7�������d�o �7��s�""""""""""����hZ�����-���M�nmm�ai��0s~�U�N���k�����r��03��P��|\�����/>�\"""���^.��~���N��}���	]�-#���,���?�%U5Xq�:�[y	DQ�����h�Y����������zX�S/:>!q4���|�������0�U�����(ja��;g���y�����S�{�,\�����W_M��4M<��sx���QVV�����=I���Y�gA��aD7	�5 �GL;}P|�����w�����q�m�`����@�$9�R�T#	*�6T8m�>�d'K��p$G}DK��W�!dL|�:to���v��I"���r�P����"D�3q��B���n�h$u��$����o��K�� �^U@DD���P,�x�u���,L�555��k�d�Y]������y�Wx����`��3�#"��p3.��!�^�BDDDg&�*�^����E����s�&4�k���������WX��7��E����"�I��0E3��gc�-}�Y���?�!�����U���$�Q��/��:��5~�yPDvh9�/_M����o����:�}�Y|���FIII��#��$�	�w1���)�������ig~os<h�1h�1t�|�2n���
����J8�s!I���E4����R�
����&�-��1-�������������a��`��)�A�b��Nf��E	
�0`d1�3L��8�c��qY���yU}DDDDDDDDDD4J������^)���$�Wl�@������g'�#}A���Q����RP>����Q<�rD�������K��|�rtn��������0��u
v�c����'�?����o����	����FC��Q����{�����t-I"_�#~�yVC)re��)��,�h���ee�f�l���P�����$p���"�����O�]�4<�����a


�\��!�n�|K��-MO$��
t��9��J]�X+b�Vtu�;dT��1{�+�@�������h�J]DS� (��(��X���������P���OC�:�E���y��GR�eX��c���2��<Y�
@�0��c�[z�z�D����H��JJ�>�"C������M��{e���i������sK����u��ea�{o���E,��d�
��� V�tD�������������W�������on���"a|��K���T]r.��v��7��H	����������:��D��zG��
�-s�ZY�p.�n���@0���������J�5~<
�F�lV�Z�X,��?�<��H$�'�|���w��������6E����~��)��xO�+_h�{8\�D�7U��F[����k[rT$8�A>W\��P��QQT�P��#
m

m
����l���h�
�
���3?O�|���p,�fU.p�1�nC�,�!0L��Jm��Z}	}	��M���d��D����pH"��Ms������{}����x�m�h��>��>|������=����i;����/h��gD5T,]�k��c�
�F������������<��o]��O��� ����a��������c��EX��v�]�������&{e�~�=��Akd�g%L^j��@�������@<��@�}Q���;��U�.��8��o��%���zh����w�������y<��s�h�T5�z1rr.N�Y��x����}��p���MxM�e 9�H� :;�H����b0�W	��
nW�RT#�$O����q���2L�h�h��P���pT�N��P�P=�{r�M���6+2\��B	���Q�D4��h�gQ�(���CB}2���"Ad�����������hZ��WoL�e����|�
�9�@ �����TVVb�������z���~|������G__���p�e����d\��o�>������a�����E�p��C���������h��g��eh���"y���)�<���o���r���^������8���N����_z%WU%""�	'�*|�j��[�H[+��#h;�o����G��E��,��6,��(������FO�������A��f��*���.�����@5�Y�#�dZ��5�Bh��_��t�.;j�.;T�~�"DQ�-��M�P[[�vNoo/�z�)<��#p:�Y����'lj>l�����,9nY�x;���!]�B}�>�=��J �G8\��!������;���U��r8fC�&������'�B�+e<��@_��@��X�_>alZ�Z�g�
����r�P�(��"D�BH7�0�U�0-ti	t
�Q�=����DDDDDDDDDD���&���^l��	o���}�]tuue��(
��]�������W_}V�mjj�?��?����G<~��-� �����/�K\u�Uc>�eYx����O��O���O;'//�W������J;g$���DDc�7Cp�i���.x<�c���i���9 `G��������k��Ul���>�d"""�q$\3K���o#����[6����4���{�
�<�;|���X��F,�n-��y\5�� 
���
[�=�`O�8r��C������
��(9o�h�a��/��0B�1��m��*��>'�
�*��$I��w���7����i�ttt��g�����a���\!��$��b�m����29nY4�B��!�����0�������#�E(��E\����N���`���C���[�����2oj8>b�8x"�w"���)�e���x�zx��?e<_�q�����T~I� �01�������O}��%K�:�
�����s���&����'����6d�N"���M��i�&�_����o��zG}���6l@$�8��,���{X�j~��_�����>�����l���������������>�W_}.<��t���DDg'S��24C���h4�c����;��A_�uG���-��5?�)f�,s�DDDD���|n�������c��[�g����C#�7���/?�����������PX>g�+&"�����P��e�y�����'�[A;@��U�\J���`=Z��0�GaX����k�Q�sc��Y���S�,����{��SO���5���G�b���x���(����T#����%��_��,����_�>��Da����:Z�E�^���M�$7\�y����0��]	�Z���i8%x������L�"�R:�i8�A�R������!l�M}_$G�P��c���R��<I�M�
�'��u��n �8I]��&
����0��w�,��DDDDDDDDDD4�1�7I|���iC{�$a��(**B"�@KK��`��'�|�;���(�:�������a���`���������Ga
^�bY����	���W������Fq�����/�HWU�����l8t���pr��C��z�j|��'�7o��~LDt�2u�+C3������$�����8|����d�~/V�vd^FDDD��'7W��m\r�����������_�`8�����w���wQ�h	V��KV@�	������
��A��6�6F�K�cz�����{5l�,V9�L���P��0�GG����X�w����������x����������i�477��^����I��\!�� �p8J�p�� ����e�F#�G8t�C_="�&XVb��2���v��ow��,{�]�}?�j>����MQ�v���HO���������F5hfv"s���O�a|���%�]v,r�QaWQ��p@�0�7��a���L�8:b���%�)':�)�P�W��H�$���$�����`������+��x�����~�����~����/��#���_�1<�
6���,Y�_��WX���*�uuu��������^J������q��W��;�������.%�&�"�������[�����8�}�Y����z{{������{�c��]Hq>>&":{�i�.K���P�B��|@S������
rBGKh_���Z�k��S���:������&�b�c��7c��qh�|��e=��y�p��~��{�F���X��6�\��j�����(A��|&�rz�������/}qt�~�����z6�)to�0P��@0��n�z�$b����>\2��;���v<��Cx�������e}}=6m���o�"  ��A��Y��(�>9n�	D�-�}
�F�`Y��[1Z���`p��])���3����U��YUs'�&��LT���r�S�u���X��@_CDCt�"�%d������H��CQ��a���J�
E�� �4-:bFv���������N�&�	>�D�����l�e�{�Hyy9����x���p8���$	�V������������������`���)!�L���O)��V�\���~^�7e�������/�G?�Q��~��_��[o�,�������?�!e���������2��*y��\�W\q�������O>�
6L��DDg�1��"k���,L�>T��v^������8��V������Z������hJE	�V^�y+/���z���
�>��/~�9��m��->��SXz�MXz�Z8}��-���N��t��g�x�����'Z@��h�����W�^�c���6FS(z�������]�p; M��"���������GE0L;��o���f���k�^�%�
\�yp���'�MSC$�<���;�yow�%��@ �E�����������x3��,
���a���p�s�iY8��>�%�|'�}�,����=�Q������D��6�8��r�P�*��",�BBGb���'X���D��mI��7�S�}.Y��#"""""""""�q���$��_�k�������I��������k���������3�������{.y[UU<����N������������@w��{����O{�����3��?��)��.\���?�'����%�~��_�����(��1���J�q@�t�D+<���p0��pO�����>e���UX��{�@�������yUX�����|_��{�~�h��;�������+/�������u��U:��P�MF���a��G�����/X������{�|��r�X������P��0:b�Q�/(�8���B�}ri��|�dxo�BoC}�����lX�fM��#��$�6����v��N�F��A�������B���Z�RW"����O���i��M-������\� ����E4U���R�
���;�Y�eY8�%�t��P��.Cp���B3-���o�gS�0B�v�1��b���/I�,�?��/��i����&��8�GS�s��p2�7$��Ud���	�{����kG��$I��/~�{��'9���o�q�G}��
��wjjjN���n�?��?����nr����iCn���x�����A��/����m������W���ZZZ���o��o�������h|�E����(��z"����s���[�[��m_a����Q�t���KDDDt.y�q�C���w�����a��W���>�}�D{������B��X�v�.X������D�.,�Z�E�3���3��p]�����Y�^WA�X������`u�0"c����DT�\��9���	������<�_��=�b���:}���������+�\e�$���,���0e�0"�:�������R�o�oGO�G)�v[	\����}���J]DS� (��(��X���������}�zVjKX���J�
�
UN;j�6��T��"'t�:�f�}�e�[K�[K�����6�������d���7�����nD"8��?�{��WSn
����������g�U�w�����6������e����;V�Z�9s���8�(b��
)��M�6�6�v>>&"����J��i����?���H������w@E\x��������U2�9�:�X~�mXz��h��)���2�5��x���;��{'�K��b�:T_~5dv'"�
�����.E`�!�??~������D����s��:�3Gm ��Pc�������F���Aq���>� �|�I$��s�y��l6\t�EY���&Ir��]�wq����#n���G84���#[��l��6��6tw�?dT��>n�� �@����I�e�.��J��\�����+��!��/�����N�����������CkP�PQ����iG�]E�,�.a�D0�#��.�`&t:kh��E�>UI	�9$��9���)/''���`0�1�WWW�����m����.�lD�:1w��mV'��eK�u[�lI�}�u���8�f��������3�=��}����24��m��?��]58����K31�(�W�5��)
���%""":_����K�@�%W���;7oB����F�
��p3�������>�e���%����{���������+a��G�_`i�/���G�?���*�X�?�����P�ati��T�#	@������4+�
1{�l���x��g`��n�
���%K�d�:"��d��o|�e)��D�d�o�C_(T�D�;UY��Z������!�"�R�]�p
��}E��$:�|UF����~w�x ��!���;:���cah���������m3m
�\v�w�1���H���t���������"���G[4�2���� �`����p+D����������hapo�;z��)cyyy����;��E]Y�?��/�<rKw�;�H�t�b�
�l6h�hkkCgg'


�x���1�������*jZ�L ����������c���b�u7A�	�����hr+��A��� �q����o�oC"�~���"�>~�i|��,��[X~�m�-�5��sq��nto<���P�yVLG���p]:���@P�q�%�8�.A�Y|(�,���B��	����4rs����w����{���2�M�6�f����:���T�(>�����0e<�I���@�2�6#mFg����A��Q>���]�p8� ���Nt&~E�J���>W�x�n���%}��x��rG��j	l��O/VT�l�r�Qi��D��E���}����X�\�Q���K�3�v�����7�]�O� ���:�����������\cpo����Sn���AU3��Y[[�r{���:�������D"��o����l�;w.����r�t!���1����|!y)�����Q��=��
w�������	�����hj�c�#?��w?�o�}�^������5|��u|��u�Y��|;f-�WZ'"�0r��?Z����}x�"`C�?=�xsr��R�<�c[���X��0�C�1]�\�P���B����4f���������K/��nY^x�<����3gN��#��NUs��#'����eY����

��z�i�m|X��H��H#��zr\8�p��}��R��Dg��%,������F44�c����)�a�KV���x��	|���`G�"��e�r���*�K�D �#���ceZ@ �#�f�M�,
	���n�x~"""""""""�����)��GM�}�M7�v~]]]����g��x����:]?�f���@~~���54�VWW������y��c"���7Cp/���}������KP/������ah����(��������7����?���/��P��wth����sq��u���JH���NDD#'�"�k��6�����`F�w����0:~�������hL��MM�Q����%���0� `�����6v���x�b�b1l��5�v�0�q�F�_�~��1
'l��l���<9nY�x;�����d��0�^�e%���)��h��9w�C_�`��v�,;`��K�����bO��1�DSTC]8���W�p(����w]	]�>	��rdiH���R��\YL��@�.�0��IB���n�hDK�I"�Jj����p��"""""""""�I�W�Ma[�n�|�2��#��v�������f��1g���r���sD���X�5�>3����������24���(���}����*�q�u"""�3�d5�_����������M8��s���]M����>x�q,��,�����	���hzrT�B��r����M}�Yq���Ck��<���u�%tFP�@3G���-K���P�u�&1$@����.��ix��w�nO$x��g��#����8���t ��b�m���;���eY���������F�fl��2M
��~�B�S�E��k�`��.w��*�l3�!�$���@���2�0-4E;�%}14F4�G�~����
|��`jh�#�)��r��E�dY��$�
Y�4�D�G{,�2.��|J�����D�����������hr`po���������u�����.:�~�P�Jz.�kT�>?�H@�4�l�q=N�}���xk2>������6���1�F(B__������O{�|���g���S/�.E3M�<qB��OL�+..���7]�yDD'����wf)����aE�1�}�
����v��z��������l���Wa�57�[8�NOD4}�����$�{��������S#�:k�qG�BG�9�e�+a�1�@�f���U�<��6	�`B�0��D��d����a��i��b1<������{���������=�������'N?�eB��";�h��W,��������iF���
���IE�9p8��a�;��1�R0��>���|V��.�*�����[�h:cq4F�h�%p0��h�,��
;�"��Iw���U��+��PQa�Q���	"B��~}�+��}�e�GK���[��x$y�K��E(�<���M7<��t����5�
�����d�&z�!9r$9�����_�����g��Gul���tB��Cn�=N�c�4�w><�����W����<�����/p��������/���\�0�,�BS��������)C3�=n�vU�^<���ZZZ���6Q��9p����������f�c�-�6@�~�h����5
��}��}�Y���\{~�9���������hpCMd�ng�h��SZ�#�*���`	"4_��Bv��n��a�i���@����Y����|tuu���D���O���
��f����y�h:�3���A��(�(��� �-H?�F8�
���@�e9`�0�"���f1L���F�I�Y�9��	���/0�2�I
�D�D�������N���������%6�D��c��@���L��H�*
L���Cu�Tm�y�YB���a�X<��($���1HZ�K�,��q8K�?���h��y���������������bpo
����{����)c��o����g�q�X,�r{��@4zj���=N�c�;�xk2>&"�x�_|�h{:
f��XY�f�B�����s�v;E��Z������fG�������-8�
����>����f��
�����2<�#"���t�.	���_ �{]�%���oP���"�r
`I�{Y��`�����hN|��(A0k�,������
%	466������$$��
a��0�x��A��(�4$�'�]s���($�	�R�-��,�1�3�b�F1���Dt>�[:�u�����^AJ	���9"HY�-!�h�T�J*0�)�dX(
%0��3���:f�����0l���j��^���������0 ��|CB}b<6)}DDDDDDDDD4u0�7��������_�+e��������?�K\<��5M;e,]���=N�ce�pw>>&"�0�{`z�~����3�8�\��P��(������{<�	�����h�$	�9U�TT"�����oik��Zw'�?~�N7|��;��$�~CD4U��������1���u�e���Z���	���
���%���4)����2���`0�v��i8x� ���Y��)D4H�r��x�����O:A�� X^� �!�!�`��izN�R}�	���| ���'���	R�;��!��~1;�>C�&�h�R��-3B}�av����D��(lv':���cZ(d�$	��
��N�LH�1���O�b��D���O���g�}�7�2��#�����1��p�S�h�E�L�u�~��q�t�Jw��8�d|L����w�}���ill��u���/��"����u-45��a|����]t\����m{c=>|���m;�2��?#���h���
�Q��S��p�%����r��%��:��yDDg2��{���b������a$#�G�����������W���ko�'�`�+%��l*����h�M�a��e�*=h��!�3���,evs�
<En`���.�������_~����F������w�9):���GD��4c����6"=�h���F��mY9�(�C�4��+J!����R��`��]t�yDg�'a�`,��X����cqt$��
��K
�%���f�2�I*�*
����d������7L��&����O&��;`����C��ExeI�G����;�\������h��yo����=�%�9����y�f|����e�|��;�����Q��;<(�GU����,��w��I��H�{��c���B��}��nx������&��5%��k�0>|�	|����u�t:�����B��I<���kjj�t:��^"���9��h�&�y����l~
"_������H00�}�(���:���&*/��]���'�`"�&�yoJ�za��us#emU���;r�5~�yPDq
%_=��|�I=z4����6l�����������/�(pQ�����D(\�p��pB�h���T�Ht ���)�C��5��g>\�J�]�p���r��$�C�Hy��f�x ��!��>��|?��l���e8��8��xwX3�YvUN;�\_�6�2t�D �#8������H���h�@G<5�h�T>U�_��Se�U.Y�8�@���t��M7<�M�q�0M]��fJk���������zrl��5��q#$it�x9r$����_�PP������d��a4��N;efY>��>�{�{{�������l��!X���i�3�GDDD�%N���u?V�z'j?~;7oB���#���L��!�?�%�����0w�����L���;��p4�a ��K�v��l�
5>J��1w� :l6|�A<������H;������_�����k���M5�����^���q]�O�����C����?w��x��������!���p����*�t��$��R�����X��������_7�0��k�@��X<k��%p$���=�)�3l'}6T����y0CU`YV2�w"���Yt�h���X����$^EN��N���Y��'""""""""���{�����[o��X,9v�e����_��������S;><��!3����N;o��9�e96�F������;�c����������;���q�yA�q����P�f���`�B[��^EE�Y�JDDDD�#�*.X}�Z���w��-�������V��������o�
�V_���DDg7L4�Ep F_�8�������~��]�q�����(����~�>�(z{��gT[[��^{
��z+Dv�$�iH�=�����[�2�H7t��#j@(\�D"��{��B4v��atu�=d\��Y�`�����U@G�+�t��%,���������OCsT�����i	�x�75�W��)�*s](��-�'C}1#[����u���S�y	>E�&4>D-I�f�6"""""""""�8�Mb{����7��P(�[�l�n�
��u�=3��������=����(
��������c]}��#:��i8t����u>>&"Je��z}3>~�)$�����,O;.X&f����"�
�Wep�������KW�|�
tn��-�p���`��^��N��8�?�o����������[����������@<��@�}�1u�p��Q�/��!�Lt��>����!�����&��������GE�9�w���f�
7����DD����B�������C:���5@�Y��D$��H�	��o%GA��Y����9eE~tN4R.I�b��=����a�Pt �W������g��]g\Gg<�����YJ����vT�](�+�CH	�:�������O'�Yr�s���a����S�������%>%""""""""�"���$UWW�5k����[SS�7�|>�o���t����;v��������S����O{��

�}��'#������%o��1����3����������������P������*���8<e[!��@��r��mO����U�DDDD4>
J�q�_�
��������~k+b�}#�W������`��M���X�v��������&7��p$��6B[4�b6g�c�� r��0�2�xS��yr��Gu���L�m999X�~={�1D"��s>��s��v�^�:��M-��U�CN�%�1���w!�����p��p#t�{��3��2.*\�
��U�a��P��Q
A�&�.���]�����#e<n�h���u���`DC|��E�n��`��)�IL
�y��i�[��0����u�%tY
 �fZ8�����o� ��������*Cb����������hRapojii���^�����XEE�m����������j��;��a|��'������o8���~��-n�����o��f<��s����m���w�nDun��-��-���q�����H�b���g�k�+�,����E�����e��o��S�&��`��1�6���������������������y�v��;�����##��4�~�j?z�\�7���e+!��WMD4yh��������aT�\�k�������X��fDG�����b&|7�C�y������=��x������z���a��p�e�e�:"��M�l��
��{yr��,h���}������!cXp`�,+�P��p]��(��r�;��o0�g��� �y�H����.;��R?��M-��}
-�k��5����7L���`g_��
NID�����w����E�,�0���g�^�-�Z�Z"e\���74��Sd��YDDDDDDDDD��{���c�p�5����� ��9���f��9.����[��_�*y�O���Bn�=�B��+]^x��())�8���n�,��u��{����C�3g�i�cY�����n��������h:;�����������sQ����p�]@��
E��-E3l�Y�%�-C������NDDDDJ���d��X|��h��_n~����x�����u�7��Q��7�������E�����%P�`��X��d�����q@�6X?^���Cz����>:
�9����!�9N;�h2*))�<���z*�~�po��l6V�X������?� �n��}��>��������@����tA7Z;��if^L`������>�����K��d��=�sU�f�����FL�u�1�i��C�M�Bkl�C��@_}$�������u�w�����9��V�I��$R��hU���d�I����d7�fssws�'{w���n6�>���l6ec'�-7���^,�jV#)�`A�$��33������� I��z<3�|���Be8s���~��o�9���O�|�
~����w�+����b���p\�lgR���1��Sf����m6DD�Pd$U%�K"_������������{����Q�v�m��q@ig�W^yeN�$���7�������u~���?����u��M{N�X�����j����y����������'�x@)������c�=v��������������V|�3�9�9�w"��1������_�5���Wv��o��M�g����E�����E(��Q!S�~L[[�������jKE��tVn�
�`�sOa��o�sg�j��1������������q�� ZW?��&"�
���g�7e�D����Z�!\���(�NY�)("��[���$F���_�h�h�uv �����Bt������_�2~�����/��g�i��__��],D�~=\�K���x<�}��Q��|9��|� |�;��n��d���d$)Z�u@/w���P�E��Q����p�����8f��_)�g�+_@��M������+L�HT�����Sac2������|i�A�rP���y����>'��P��W��W
��	"_������������{��l6�;���wO���L&���/�2|6�������%��'?X�����x��W+_vM��>���===����+��o~�����������������������CU=~��=��?��@�O��O���E�;]L|����^����a��x%���|��qDQ
���M��n+z�e�F�4��DQDKK��M���������U����7ly�����g���/��=%sY���O��3�����������Vv`&�S�u���c_:?��!I��Dk:tY:�����h^�������N{�o�}|�)$�]	A9�c�O:::�����'��lw�����PU���5���K$D"��DZ��4��<�B_9��]	�������o80W\7�Lf;2����,'&}�P_)��8�s"ZHA����e!77L��}���n���J����k����}�3��g���`e8�����R�x>R�]	��L��6 ��s���*�:icTQ��0�<�[�Yk6?""""""""��{���}�s����?��?���0^}��3z���7����������_��3� ��>��C�p�
����K�t�M������'�'���8������(�i�r�%���~�������#�<��{�����_��m����?��?B*���q�F|��_?��,����b0r�����������kp����xc���������E=F����4�����3TKDDDt���7���|���������/�8>�s]���_����z-.�������7�]F�6��s8�-���):�FM�����h�xf�{r}M����������Sk����^eQ��'Jt]z��0M���/��{������x��G���V��Q�(�������X�;*u������0z&��zP(�����q�H�?B:�Q��(��@_�;��w ������^"
���fM���c���r����@��5�a^p}�'o�'o�9�+u@kXE�x�OaYHBq��d����a�r%�Wpk�����T�yO�%$�I����P
�DDDDDDDDD
��o��������qV������j��^���O���~��K�'�|��o�MMMhii��� �=:e�?��?�����������m�����J_Dy����_����ohoo��i8x� r�\����F��g?�,��?���;-d�e���~��z�{�/��u���������=��]�����B�(��8��_���vvW!"""����0��������q`����S�����'����};?F��l��>\���!ss":�x���\{S���/h��qIRGS��^�ID��vh���I<���X�D�����B��f����i�&����^z����8x�����o|K�.������tDQE4��h4��uM�����n����������(R���J��P��`�/Z�/��i������hT���.���z�"��f �w���3�\�*X8T���Hfb ��������Y���cM,���4A@�v*���� m���n
^�&�9�E��5Q��K�2����DDDDDDDDt�bz�"���|���7�7Q(L]���044T��?��?�_��_���D"���K�����^{�R�,]]]U�ikk�/~�tvvV��B����#�w���;�����v7>����E���'7}pO5�b��`	��������h�E	W]�������]�����~�m���v&9��W������������o��Dr~'MDt�EW:�����,:-�%k::D������C��������y =�q��a�_{`H!��j�/Q����k��i�U7�J��������G��E�j;9""�I���C,�.Pw����������2<W,k�5���wuM[|R��zd5d����QP�"��dW'�������(�����������)�5"�e�H���h
:#!t�Z�K_$��Mq�%	��t�K��>��]���<-���J$T	IE	����|������������.4\q�{���p�5��O��O�����]}��n��g�o�qV�S__�W^y��O�����������=�w�w�'�'�F�U�9���;-�l���w���Wgt|��V��;�����N0����(VkE/B�V���K�������y�������d�����?���7���g���/�*�gtn!�����>x�	\����������e�gLD4T��7e�P�ok.�B
.I�h��!�c�)���77 ��d^=|�&5���`�����P���]8n��F�E���{U����������&���j<;""�+�F<����@�q���}�0�������4O�4O`t��@=Z]�DT�(����jHR�&�"ZHb��M	��@���8pRw�n�Do���o�2;�M�M���M�\��"����A��w�J��rk;0g��l���Q����\UU�Jg���>Mk6?""""""""�����y���.g'[�r%~���������~===�f��Bhii���_�e�������������o��oc�����m�?�u���������k���(��������7����#
��i���z�+�����$������"�i^O[�-s-�M�kii���DDDD\�qn��o�����_���FfhpF��������������7c�=�e�e�1CD7����+`O���Y}c�S��=������:3�N�om��2�������+�3\���~������[��T� ��;���ib���U��f�x�������"��x�DD4�dYG"~��u���0z����|�����
������~��y}RU@8�bR����/Y	I�j2/��D�$l�E�1	������R����+�P��S�e C��!+�wR�@�^�N
���)��Y�az^0�W��9nm&��^/Y�E�vq�0caI�t�+�*H(2"����DDDDDDDDtAap�*��8�����<��
�a��y���;]hR'����[�Q}!��Z6\��~��"�x�?��\�j]�m,�Qh������v��GDDDD&-��{��w���~���>����f|�������[������>�5����@��;.��
t��(��BD�6�cM<��,��gFkO`������u��ot�]�g�x ��/t@������ ����,L���={�366����x��G�D�CDD�,��HlB"�)P��r� �����g��x4g|
}(�0<�����H����o<���Ak���B�D\
��h����y8T�N��W���9�F�sm�v�^��{i#P���D��|{IC�4��#m�H[v ����Yu������P�p��F$yJ�/�H�#"""""""���{DD4/\��G�>����{�����cq������-7�z��]����2d��p�cU�ioo��s��K�$��v�\��]{���'������3��������x����w���n�������}�E{S9�����Z����K:Z���f���+h��%��s����Yq���C��k�������(����<,������344�������Mcg#"����$Q��
u��u���M���8���C>��A
�T�
��H�������p���eDgJE��CX��u��q�h�}f%���/�X�d\���Q&��2�@]�DtDB��5tDJs�L�XR!��n9�g#mOt��j���=��=�3� ��H��K�2Q������������N�+�DD4��u��+��7��������������g��{r���V�b4����:�(
�-[vV�MDDDD�ek�a��uH
���~���������dFj����x�����o����C�R��$��s<�r�M9i��LH��U�0�%u�k�g�:A��Z[#���;:�k��61��� ~[b7.� �D�����/}�K��~������;v�?�8y�(��KDDe���z��u�Vj�����JA>�F9��3z���y���;� !�|�.*t}e�;_g�S_8��p�:<]�dQ��H�"!��4Qw}{�G��[q\Tp\T�K6��i#?�n��a�>���q6��jH����O+����TH�$����w�K��})�A�����������e��K*���$�zCY""""""""��bp����������>~�y�?���uK��3��o�����~n��������eZ���Q�mAKK$�_.�l^����;���c�/_���AndxF�:��O^y���Vn�
W����[�@D4E�v��6��������,amRGg<M�0:��ch���y
;N�����zaL��Kk ���M�hTU��?��������s��a��g?����e^�""�i	�M[M[����+u��a��+!��@������a�\�}��>�r�00�.�!���I�J��Ph)��x�Jt>�-���NQ����u���o��}�J���|���^�{����U+��|��>]���TQ��y��|��������l��qq,o�/
��2��O�U����=]��#"�9����x������i�%W�� �y�����Y�7h9���c�85�B�jp���}N�@DDDDGH����=�Mw������G�>��Cfv�����pp�X��
W��:?����0D3��1P��'m�/W��"�%a��:V��r��Q��Z�W ������L����
�_^�PG]
gIt�B�y�|�{���p�`jww7�|�I|����(2�@DD3'B��������J��=��`��@��
#W
�y�y�G��WD6����@]�"�#��G;�]�J�4m	7�!�A�<�byH�-
�J��}Z��"���|�@����dn��c�Q�>#�Y]����}!\_EH��>��S5���`s�9���c�hc�hO�\�'�|���*#��������������W��Y������;����t�%��w~
�[�t�u����P����:��MG�e��r�^#����G�=�[?�Q�i<t�����7�=\q�g���;�F�y�Dt>q<��M��o8s*� `u<�u	IM���� ��^�%�������K���1��]������B��@��_����_�*����"�NW=f��]�4
��{/�DDt�AD8���r46�R����B�H�C_�;���8���}^��G&����@]���������M�{�hA@���YS���X`l���>)�78������@O�DO��s�xo,h
�S}�����a8����I���,������,��g��,��|��[���9���������:���hV<���/=���}���Cs����O?�
l�������i�{��0b�!oRS�{��a���s>""""ZXA��K�c�%�1z��^�v��*kf]r�#x���{��c���6l��>$��>�h!����tg���3�S$�K�X�,���b�~�r�~q���?����y0����@N�j7I�3�H$���}
���������u�Vh���n��!""�� !iC$�����*u�sP(.�����������q����Hg����(����}����y��B���hT���.�y�����(�;o}�L{�G�[�C�
^B&0�"���|�N}k"!l��!&K��&���}�A�vg��~�r�����h>xM0$���������DDDDDDDD9���.2����-��A���S�d����?�5N������~7����?����]�����B.6��W}Aukk+$I��y��S�t>��������������30Rc3:�6����3�������Oa��`i�Z.�!Z |�����=)G���cYD�����m��6����/t"�:��'��7�i��g0�����b'��p7�����~����P,Vx��w
�p�
7�xvDDt1E��
��
�pg��y��^Fw9�W
����Q���/�I#�����������|�N��0_T���$�}NDU�"��dW'�������(�����Dw��#����9�H�����_��K5%���#��3��N)-wr<��K�C}�r���a���z(,���dA@���%U1U���?�Q	�{DD���^�{�W8����������@���X������-m�>�m�������������Xc>���+7]5��)����y+z�:q�X�������-`�X�<�%l��t��&�>�$��zgt��{���]�|�.��^����������M%�.H��a���ii����(�����%u$����m��EP��0��}������`��=�^����!��!-���x��G��c����/v~����i��������(HUD���F;�<���&����}��@_�p�A+�E*�>R��uU]��^���G;+�e96�s"Z�b��M	�z�n�.������(�p��A����i��i���l�����@_gDCg,���(A���0���or�>��]���}��6FN�j(�)��2�Se$����DDDDDDDD���
���"rp�����'��o����y}�>A��O��S?����������W�v�o�����H��yA���?����PC���=N�p\rl�������+�M4dp��������(���[q�
��o�'���S8����|�����x�"l��sX���"�y�1����`o�@O&{����I�0��^�'7����.C��C��s�����=�p����8���fc���x�������[���/�M�p����vrDDD3 Ib�u�����[�a�/�&B}�b�
��e
b����;���-F���O�KA�HddY�����ttI�e�.��S\S}f���
Y���I7�W��}��K�:A���(����0_���L�~��2����Fp,"���|J%��D��GDDDDDDDt�ap��h*d3x�{�}��������O��n���F������.�x����������h^����{�vv
���K��"ml��2��h��y�],A@������r�=���?�=o���O2��� �x�����n������|�Jt��}�y{R����c��a]B����Ew����gWA[�������w/��s������jD.�k%�������/}	?������W0?����4
����:NDDt���0��
��7�����?#��������4O�4O`d��@=Z]���E;�GVC�B5��B�D\
��hp#��p�`M	�����y?<�Fm��
������8���[�T>������������� �]�����`�nUJ�>%��)D^[ """"""":o1�GD��>�����rc�g�8���m����*N{���p���w~�$��s�����*k�4��f����_T���A��;��hX����`�����_~��
���ITc
���S���/�y���|��X�z�<���N�r=����7e�v�?C�(�#�������������7a�G�`�L{�o��q��SH~nD���#�fb��5x�����������x��'���c��U5�����(����_��vF�Fn"�g=������X<�b�(FF^�T��}�}z�z����d^D�*�X���Fc����x�>����Q�E����8>���Q&�����H��V	���C�"���<�G�v���)�>�F���1T�1Tn&
@��+�����*A�w�DDDDDDDD�W�- C�����OP4rs�xf�8�AVn�
�~��o�����,�M���������������y�]�"�$�������/`��o`�sOa�h����=]�~]�~��^�����UW^Qd0���R���)�38���Te�K�Xs�����~g#2�F��#�)���?���A����,�k7I���q#L��s�=Wu�u]���?����5�X����#""�_�G2����@������T�|��>�>��)g�G�p��a�Z�
��p���Y�u@�v"n�(*5���$�VEBX	�������8Z����W
������3\g��8��E��4t�!\��BK�>��Qp=���|�`_�rP�����Q�������T��7�Se$!����������j��="���������5g�����u���o����!������G��������v��,�lkk���M�Un��o�
��l�������g|~��=�������t�}X�g����8c�����8j���6p,o����z�$u,���3��N�$�h��2���t�����0�7#�����^��t�����`�&^}�����m��?�!���o`����>���p]��C�i�{���uuW����@�����uO
���0��8�wb�+��"�?�|� ��^��AA$�V���Y���w n�(r��lI�������������8f��}�J���|�6����cg����B��
VE�I�����x�8����zH�����`_�vO�/���9.r�����mh���o�����DDDDDDDDs�W�����������b���n�[�:Bz�f�y2{0c�zn�>��"�o�:��:������A�~�f�_�C}����S����\gF��N���{���`�g��w��XC�<����a�z2y�M�9����::�&"�*��:WBuh�w�0��.�=��t<����@
u�����:�l���bo��v��b�����x��G��8�����v�����~;v�9�����K�.��e��a�477���ADD4�T��������R�}�5X����uW����oh��v%H8��+uQT��*�:&�V@�m�h�DA�����!�4�+u��1`9�0�QD�Q��,>������k��(������V�!t�'^\�G�.����P_�r��pS��0X�0X�uI�P%$��K�2�Id���������h6�r��h8��C�{�W5y���-�����^R��;���Gq,$ /W����0p���c����-���������6��o�[�>y�9|��(fg�A�4|������Xs�
�|��hn_5�3&Z��L{Rf�Z(W��X��be,����S���zd�<�����)�,v�:�C�Ck����l�D3q����4M|���U�
��c�=�o~����o�����i�4M:t���o����l�������+�� ��fhZ3��T����4�#g�;��z�����
�x���yr�����b`R]C��U���I��N�BK���Y�5�57�O|��}��x��t��f�Y��r|�'o�'o�9�+u@kX���/��M
~�qO��� m;(���2��c�t0j��	��4��OQ*�>MbP���������T�#"Z>x���<O�i����IVj�|���M����Q�:.�V�;���:���6��#""""��h]=���Wq��_��7_�����������.���:���:V\���}+����3D���>��"���(X�?�$��h�$u,
�\�[�( ~�
h�	��h��9���h��	w�!�e���yC�u�]0M;v��zL&���������������?�86l������H�l�LDDt���R�BK��pS������R�/�S��g�����9W<��lv7�����$�����}��|��M[���DgA4�
�T��7o���C|=�Y	�3����p�`�P��Kn��"���|�N}k"!t�!,�C������eW}���\��� k���.�����$��|���%UY�k�#"��
������82C�;������<�����\=����8���������������������p�mwc��w�������pd���d�N��uK�a�=���n���N"�E����N��/��1�En!IDg<��	�R}3�_Zk����O���gd�]���<�F�;!��~#""E��wL�DWWW�cf��l�������#�<�����z,""�� ��W ^���[+u�wQ(��0z�3z`���������q]��'�d>	�e9V	�M��:������zE�5�(�IF���b�QDW����0��/�H������#EG�~9�/��@w��H)����9�����:�Yv%����~�~
\��5eS$Y&:����TqE���6"""""""��0�GDt�����j�|���-�8���m�t��/�l�a��2�z ��q����������fME��|
Vm��c��O���7��3������o��O~��o���q/�d�<����7R��7���laV�5��:��a�"��kbDA�W����q��;�S�K-���w���+k��L�p�D��$	_���������C���l��������2�GDD@$D"��D���t{��y6
���0_�'��F�p�?��'�tz��m��,'�;�G;���R�OU�}ND]\��)�cS"�	����_(w�+w��6��-X�U��i��i���l��H�O
��nW�����<�G��K��P���.���>�M�'u7��`�o�V�o�KDDDDDDDt!cp���wbwM��x���������J_�N�q����Ukoo��DDDDtAh^�w����O?�ul�Y�x���1�s�����O��/�k����������{6Q-y���\{Sg�k��-����������A�n)��8F��pa�c��������-�����K:(���|�+x������?/�Q,�����{��H$2/�ADDt�E�����]���Y��!gtW}���|�0o���8)��"��0PW��r����Y���E�&DgK�%\���X��s��p�J��`��Yw�A�������\�^�H�@�������B�r���(�^�C�S
��R���3��i�yH����;�2gD�T�R�oR�/$��&CDDDDDDD,���.`��c����>�����}��]�,�wK��
p"\=���^V_����6_�#""""���F���7�����x[���3:�u�~�U�~�U�n����m�m�bZ�
���t]iy����%k:�$"���;���C]��?��� �}p�} �j��i�e-��Z�IMC�4��o������4�yy�l6�^x>���<>�B%�*��5�F���k"�?P��g��0�a�zP(j����G0��X��@]S��W}�@�j�r��.�h����K�a\
��7�3��y�_�D����������\B�i���[V�$���=o"�7�6c;5�4y�C�1q,�l��B9��E	"�q�y��="��U(�h�N�*9�������;��<��D�_<��^�}��X{{��������h���0��������q���������o���?�c;�����-�|��X��&�*�+�p��.>>1�C��Y�,k
)�$��5���_Q�Q��Nh��H=��=}`�<���w���K�����,��;z���������6l@gg��>��@�4�b� �$Pw�<c��@_�\7�������`Z{;P��%�}��@�$�/��REk�0���@����-N��W��?_Dq6,f!���0c��L0��Kb9��U:���CXR�
^'�|;����(���c�hc�h���'u�K��}	E�,����#"����}����c�P��?n������G+��W���3��
�)L�A����dr��HDDDDT�(�����q�u8��[�}
�����Yg���}x���
o��1\~�=�����'�y�D���+^�b}3^-��������.�OY�FA�_��%�����>���X��1��������[!H��1���o�}����;�����<�������7���+��'}FL�DM�e��a��12�f�
�(�������Hd$)T�y-d�(`u$����n�����#E�F]�:���M���]�;[����lg�����9w��J��N=�������u����#�xHY6�'�
5�=���1����L��R%�W
���}!~�'""""""�cp���&��9y^Y97���175��xO�z��V���o0u����y����d�����2C����/����`f^��Sx�g?��O���p6�}?��������bO�D��2���|�E�M�X� $O���.<������z� ��O�:�����Q��Z��\�L�700�����<����100�����<��r���H$.�m;]	�����}������#(�`x��IU�p�D�O�@4��HDQ����2I����p{��&Z������S��W����5
�<;s���+���UmR����V�La�I�c��D���+�s�����r�����?�n��JW���>]� ��GDDDDDDDs��="��#�GQ4r5{����}�=���}�H����^z���m����|nDDDDD��x�"������_x�^�^�2C�3:��m���K�����~���|��hY��y��}m�M��J��0��VqIBGK4���/X�"���h������;����,�j��DdCc
gI�������k�.�������@2y%��+u������
����<
�(z14�J�*���R�O��-��"�6������h!+B*V�T����}�����|���1g���s��}�5��kuY����5�@����Ea��j�x���)w����W����0�Wt=
�I����� _R)��U��Y`p���&��B��Oj���V�>'�w�]�p��?;p0Z=���^����c��B�E"�|���������w���O�����h�G8��#4��c�=�c��7��n�D����\{SFL����`U,�uI��{��D66A]�����>���8��b��{a~j	�����T��@4��������S�z��5����R�}�=#�
�������d�}N��"�?�|���^��AA$�^�u@�v"�w"n� ��9���5�57�Ol\��>���@�Y	�u�������������������Ema
�����:B��L�.��>r�[�C}�W�D���5m��t�IS$$Te"�W���J�v@DDDDDDD����n����������sM�}�h����[� lE/�����U��GDDDD�����5�~����c�����'����f^���������W�q/6�v�Q������.���2y��w��Ge	kt$t�����%����[�~��7OZ2�;�p�������b��>�?^��<v�|�gW]""�� ��Fh������R�}�5#7�����s]c����6�&�TE���R����v"ZA�g3��%�TM�������Fm=�}&��E��FH��8X0q�`�EL�+Bj�C_�>��/���)2V���*:.R��0_�'W�n����.2��#'���%qR�O�������\DDDDDDDT���n��7���~V������=�8�7
�pp���X�/�$��b�8��Lc�=""""�	��ek�a��uH�8�m/��^{�Y�����(���cx�����?��wuK�����b��>
��
�������K�*�%u��C�P�����+��Lb�g]���;��
��v$�[
}ss
gI�4Q,�����R,�����hhh@}}=���*��P��s!""��'B�b���hh�t���>L�8r��J����o?<�0���<���r{uQC�W�;�u�C}���2�B4G��$��&
�3�����J���;Z�M���W��W���H���e���I��:#�P_R��X��8���=��K��������}�����P�p�`��( ���P�x�/�H�NEDDDDDDtbp�������ek/E�����\���GcK��?��N��=1����q�\��`�{DDDDt�K.^�[��-\�����_���/>������uL���>y�y��|5���,[w)���q<��M��UM�s��k���u�2��!����7a��]���=��<����������U�At6\�v]"&;|�0><��DA������h4������. �  Z�Ph)o��}�C�x���uW}��~x�u�G��W@6����@]������@_)��G;���|B4G����	���v���'oN��W
�.X��Li6�M���7����"U.w�M��B�*�1��1���|Y�-w���>���o���a���I]E�J�OFB��)"��-T�-W��<Y���U�=8��q2������)��x��-8#�Pu���m.�FDDDDt�
E����/`�=����o�������3;��q���q�����r56�s?:?����L4;Y������L�,Q�V��A��al��������~{2��C��>�j%b~� �#Y�?�������$�_��|>�|>����)c��L	���&���w!""��AD8��p�M��V����P�C��������|�|��q�n����d>�e9V
�U}��k�*
��]�py<����@��z8�/�;oV}=�"L�5��
Z��N��zE
����/�����}�G��*��*�>�A��]�>@�*	O�JE���:��H*24I����+����������o��w~5o����������������)5@w�zp�����O�/Z���W9�������%�2�}�f��r������}�~0��������������,6�zB:�-tz���x�����>�8��X���
������%:S�( q[+��	���^f��"�P��1������%\0GsF�4�B!��{�%��188����)c�  �LV
����AU�*�HDDD�A���#i����=�F�p��@_
�C�����8Y��[�No
�����;'}zTu�w�D4;aI��X�c�@��y8T0�m���|�F�&l�6��Q��{i���@=!���@������,!"KX��X�W�������n�:������?o��( �*SB}QY��	""""""��{DD�-�~G��Dnljw�����-�~k��t��"�;����4)u��{�\��z{{��������h�+.���l���~l{�i���/�X��O���?�~������������X�x�gM"��p S����������(`u,�uI	UF&���y�']<B��h���Y7�]c���H=}�������u:{� `��%8t�����Y�}ccc���P4����D������<&�
t}5t}5�h��y&���r��{R����R�����J}�T*����6VB|�.}���N(J|��Dt��Dk�0���@��|.Nt����?_D��M.���0c��L0��Kb�C_g��[R�J"�$M���#��#[����P_�r��(���c�ha��pH��"#�*�0_B�Wd�"?c�O����h�������g���(�9{������?C8V�/��o����t��`�w;��S���L��e��o�\�����W_��/=#u�0�$�Y�����/>��W
W���v����� c9��6�?��5��Z	E������0Ti���D�!EU4|�R���G��^���v��:�
�������t��-[v��N'��!�����#S�4M�������x���|""���(j�F� ]4O�]��|�rF�;���F��A�8�}�|��aX�0��~�kjs)����o5d9V�y]Q��H�#!��4Qw}G���"�&u�����������=���l>P�:���mKH�,
Hj
��8��}�[��W��W�k���������6�D��+��C}����- M-m���s�������^����?�M-mg?�3��,T��X�Zo�� �e��4e���uN�GDDDD��E�	|��_����<��}=�$��zgt��{�y�]���.�t���{@���B���W����}��M�M8��Y�����5�K�X������ 
���j[�?�wl��f����������~z9�dOga��
x���k�|�]w����h�K���nq��L���'p���)c�$!�LV
�%�I(�R�����\��b�K�]��n��������A�<V�y��Lk�c��]!m)�ht=���HM�Et1�ma
ma
�7&*u���o��:�+��5
�<;r��uM�*�}z�a�("���*2����+����Yr�[��|Y�E�vq�kaID�����e������������{DDLSK����
^���c�;�������F�����I�=��sp�_�?��NqJ�����O�/Y��px��HDDDDt1���x+.�����[�{�>�:����t����s�������a���A�p�Bf��g���2���|a�*
��G�6�#���%���G��7a��=(���@�G��^�Q��NHQ�v�����---������jmm�����y��L&S	�����[�5���������H��x<>%�7~������/�A<����@�q�0��0��R�/W
��V��=�Z�<��y##��S�(�J?Q���*HR��E������!+B*nm�X���>NX6�
3��2�H�(gz>�E�1�kdh�EBXS��kIb�'��9|�p<{<�gWB}�����W\������<Y*]�*�>UF\�!2�GDDDDDDt�����h
������;�m�	��_qt����|�z\u��Xy�U�8�S��r�>^uL����x�3u����6L�����������.:� �u��h�x9F��a�sOa�[���������#������;����"��h�gM���l�M��)���|�QR��.�cU,E�a�D3#�e�?��'�z��L����=���lG��� �:Y�I���e�<�����<�_���(�H&�H&�S�|�G>��&��r�y���d2d2>|x�X8����F����yA�cH$�@"qE�n���0��#��������[>
�>�}�����p����/�9)��Q�FDsE,�T,�T�X��}����������t���,����M��M<�t�.hk��5tFB�N}�#!D$�(�^SP�)&6�|9�-u���;��:�Y^�}��c��1l��
�J0�7~����������f��="�l����r�U����w�����8�3oT��":�Wu`��N���4����	���_�~q]�~)�)��^���)�������E�ayn�����+_��/?��_~�L��'�
yl}�Il{�it~j���~,^�9�3����>�&��
��g|�`�����%aw���� �^�jK����3T��X/ka��v"v�
�om� ��c:3���X�~=v����[gj��
��<��oA����u+V��2nYV�.}cccH�R�g��+�B�B���2&�����D"Y�WgDDD���$�L^�d��@��F��>��\7'U�Yy(zQ(�bh��JUd��m�@_9��;�B����� �TM��-u������'_DO�;_�a�;_�qsf��-�����/"31g+Bj�C_�>��/*KqUF\�1����(�^�3�x�/m90j�u|i�A�v�g�"���"#�*�P_Xy}��������$�����"����-�@^:��k���� H"n��v$�s;�I|�C����cBH��K�wN��{q0wS�A@kk�\O������DI\���q�}b�[o`�sOa������=]����w�����`��`���!���N����z����/m k���!M����.AT�%J:�Kt,��+�z��[�?����y0����BNh��$-w�}7>�l6;����p�]w��������f477Os]�t:��?66{�{���8�����1A�H$����k��&"":�T��z
�����|��e
�(��&��g��[����������^��A�YY
��������-^� �K
��5�O%��z�q�c�U	���/�h�6�G|}E}E��dc�4eR������Td���,!,KX	~�=��K��������[��y�������0�C���R�UJAE""""""��W�]dA����2���I~� ��Uu,z��1����b�"</�s��e��������h�)������
7���O�����B���g|~��=�����K��������@	��o�4kc��=)�8���T��X���2�,�_�G��#����	mu�'{�[���Z�~g���������.t�H�<������X,����B!<��#�D"s��3!IR%�v2������t�����5���sK�RH�R8t���q]�������yw�����b 4�	������+u��aZ0r����r�o?\�8�#�
���3��3�uQ���BT�,w��@T�@(�|��Dt���6'tlN����������M�.X5���6�M�����<%��	�A--�SD�!�!5p����L����t;�kx�ey>��6��6�B�.
@������@<����������j��="":o�����G��"��/��������a�suS�mmms8C""""":A�~��h��J>���=��o�
��������x���w�l������{�o��Y��x��#F{RN�o�r*��h��:�C*C
t���Xuy����}|���^�����At�2$�l� �5�%]���������?���t���bx��G�v�;�A@,C,Ckk���b�8m�/�N��O0�a�����0UU�6���!I��CDDTK�  �-FH[���*u��P,/�������~x��m�0�3���A.�'P�0B�vh!���[�\���s4��e	��#�<����z8�/�;o}�
&���,Vo���EF��U}k���&���O$UI5������;����eB}w��������!�d�����$��Cy�	UAH��""""""Z�#"��Fa�0��B�1��fHQ�s��[��\n�����s:G"""""����v��o�=�<�u|��s����Q��,�P4r���'���Ob�u7`��`Q��y�1���z�N����p�3>?$���G�6�CWV��Ai�`���������S�{�fo
������B���������/���;w��q6l����������B(���K�t��)c�� �JM�s�3��j�X����L�xLE$��)������TyD"""�� "^�pxo��}�C�p���A�(u������|�3�y��{�(�o
v��GHR�^������N��"���XX�>��X�s��y8��W�0o��Q�����S~�
n$��%tDB�P��N}K5� @��]��4�/����gO��r�[�����<U�
`[��&@�D$�Rw��.}IU�.K|�#"""""�
�{DDt^�}�7���'�O/����s�=Q�b����*��h]=�|�����/b��^�������c3:�s]�y�u�y�u��t#6�s?V^q%��-�����������vo��K�h��!�\DC�����o5B��}�~q������j;�>���eM5�%]�"�|�Al�����><�s[[[q������sgx������F46N���y������bq�;�L��<���btt�2�������(����AD$��H�MM���=�A�x���}���{������us�d�#����r������h'T������&�X
c]4�)����-L��:����0��D�R��3>�}QI,��?�R�oEH�X~��$��*������#kOt�KY�������QP(\�`xZ���|�D�/���x-��������C��y�������:���>��y�i.p����M���+��j���������-��o��}�N��!>z�I��k����Gv�@����|�}�����h�y�����}��7eLY3"��X�:�B
	�E!�������>X}�w�M�?��@
�{WBT���f��������]�������~��Y9F�4,[���-�������|g|n���D"�D"����)��|~�P_6;����%��"�����o���iU�����#�A��DDD�JeD"��D��Q�{��|����/7��A�����.���A:����@]Q�':����ND�P��y���Ft�!t�!�3i����W�*���r���0Q����-�z���c{6��E��@_��5�B*_��Eu��:-���}�w"�7)�g�����1j�5��i@L��P�Jw��p�*�s�;��y!��i����T���{�n{����0��n0����6g�#""""��!�"Vm��6_��������������3[�6v�(^�_�o�������q���@Or��l]�<�����/�	K"�$t�ID�F���\B��6"��ad������y8����Bi�k4CZ���+��t:�_����}� ��[oE"�8�3�0D"D",_�|��eYH�RU�}�T
^
���4M?~���2&I����t����G2��,�k@""��"�
��p�]�{�	#F������]����NU�=�T�}�R�������/:��O�����}NDI����pG���5���o���|���nm>s<;r�8i��&
X������r;ASd��O��Qt�`���O��� �8@�v��]	6 DX+���R��Dn@FDDDDDD�����9g�����:Z[eq���t���8;�R���6�?�W��������������W_��7N"�b6��������'�v�M�������6�^@�����0Mc�Sj
)�$��5���Mt�$�;���Lb��]�r���:y���H~n"W6sq�1A IR��t�TU��E��h��)c��"��L������S�\q]����:�H$����oC!v.&""���!]�Xtm���E���+��C}���7�+�5��������-.��:+��t}5dy�w�DtvDA����!�6L�f}��	�F�a}]F��L����=F1P�`e8�N]����!��h�&u�I�%,k��m�C�r��l���`_�rP��Q
��B���B���"
H(r�C_�VAL� ��6������;u��������r��@M����g��'���~�Q|���`���b�O#=pbF�����o���o����W��{�G�e�d���}�f��60T�>X4Q��a\���RO�E&�Y��oo��O����|������x ���WC�2=��lrW�����0�
���6$�/�t�t���S�����.}����(�K�1I
!��������@�����]����x�����L�L�FG�
�C�e� _���O�WC��5���D,�T,�T�X��}����������t�������Q
���P�R�:�������&}�(�!$�!���}dm�S|��W�U��(��oNZa{>�M�f�Z� ��SB}	U�2)�HDDDDDD4\@DD��=�GaW����8��D��������wJpo���e�5GDDDDt!QCal�������q�����sO�X���x�v��
�[�������� ���]i]�<
���e�E�M���G����@t��*���7� ��a���
�>�E�Ck�.�M ��A@4E4EKK��q�4��FGG�N���5\�z�B����~���OS�V<�[_2�t}$""��#�:�����7"����_/�p�U���X�C_�9��5X�y��(�12�����ph�h��@_"�U�$m��"�YM��&U����u��AO����m�8a��f]��8P0q�`����@��%��S�#���t]Q$TBHF���n7�t=��U��W��g#m9�������~�rw@��LE��`��r�/$����������b����������.b��mo�vp�r����0r+����9�#��(J���:t\s��t����B�{���g�8c�h^�����?z��q.��nD�������������)�����C�j�X���
A���D�[Z��L`�G����i�uF���� qw;��-�/�F�4,^��/�2�8�������64��m�����d�j����*7M ""�#aD��!�t�j�)�~��nF7�\rF7l{�s�Q(��P�������""��r���I��v�"���UF�����@=m;�)w������7k��.Z8\���H&0�LS*!��N}K��A�%Dd	K#�@��zH���P_�vgu�s�����8�7uM�]���P�*C�%^[%"""""��1�GDD���6al�:&7GZ3�Eow�0��,6O���4Pcp�����haX��������l��|�%X��?L�O���O���.��l��>4,[1�3>����\{SFf� G���.I����y�!��CkK`��7a��n��b��#��A����B���#������444L�<�\��;9�W��{����>���066��N�u=��|?�0�LDDt�%�d�J$�W��5��A��������j0+��!���04�r�*2"��r�������p+D�����CB�qeB��	=P�9n%��=)��W�jz�7m��6^��]�%��%��Cl�DtFBhP���$�IR�
�]�G����`�S�.��W�Hm��&+	@\���T}qE�,�����W����������/��nZa�E���{1?
9+j��`���s7Q""""":���q��~�~�!�|�el{����\�����/b�/_��MWa�=�c����q�v�/m�+�����3�dQY��D	!I<�	D4#����k� ��1�_84�u(���wr�h
����K(���x<�x<����)��B�j����Qd2�*�X;�a�09rd����U�����!�H@����h�T������OUj��������nF�\7rF\77�s�}���FO�.*�H;�hg9�W
���-i��Et1����GpE<��]���P_9�w�`����J�2���}r��
}��EF��U:��)w�kR��u]I��$O����}�[��W��g�n���~:[��Y�,@10S$$*���n}��-(��9��m���:&%5D66j��Z�#W���B����B�Et\y��t�����;����8q���'���!n�Mm+q�=�c�u��$_���|��@���������v�^V�.�c������D�A��Z[#?�w�8��n���?�@��V�nnjDD4.#W����m�R����T*�u���K,���'p������(����j�����ra�_#"":�A��-��-B}������0�0��r��������|�B��B��
�EQ�Y]�����B�e�X��CD�!��X0�gz��I��J��M�5�b7b;�u���SF���%t�C|��V��DS�>AUdD��
a�R���mY����������h��C�8����O�������="":'r��oU���a9��v�����cz�;)����>7�$""""���(IX{�
Xs��q�k/>z�I���=`�G�z���������3���^l��.���y���p<��I�����,Xc]BG��E�D��.��������Q��C= ��a�����H1�v�$���(hjjBSS��1����d*A���}�iVy���<###�:��������p�gKDDta���BK��pc�����c�_�D�>�<o�
H������v#��
L�%)2)��Q���	M[��<�D��a���k������@_�C���	��M�/��� m��t0���I���OD���:e�2M����u������|v%�����u ����D���������:�C_�~L�!��������������g���s������\��Y����`���V�"�.Bap�������!�����^�������/���W`�3[Pf����?����	���l��>�-����|���K�N�a�b!LL��.�cu<M�N�D���Q��5��J"����7������
�_^�PG]
gID�(�H&�H&�S�����|>?�K��m.W}c�Z�f��f�8|����P(4�K��m,�(�}�L��px9���hl��R�}���JW�\9�g���)qn�n��d�;uI��C|�}��Uu}D�Dt�!t�!�3i�����+X�@_W9��c�(x�_��K9���L�2���aQD���3�=��r��5�N	����zMA���-z����"mO��W���:�l9�����i�����w�Sy��������cp���j.�u�aW�^��*j=y�_���%�q�Z*�BX�x��M������.��Kp����u_�
�������/�����i������/?��W^�����ek/=��|������)G�"f�dYD��������>DT
�W/���������=�����.�n\��m-������ �u��c���S�-��6��J������|(�8v����Y�,������K&��e~UJDDt:� !iC$�����*u�sP(�������z����;�>/��!���Lf{�.��i}��>'���$h�hh�h��1Q�{���E�y3����("��&�W�<���#[�5Q���6�;_��=�A��PEA@\�We��'�����zH[�@_��90��^i������F���"�����B}aI��b"""""���QDDTS��!���U�UB��%S��s�*G�o#�-���N|����A������"�Fq�}_��{�C����G�>���3;������������������\����m���L{�R��/v���%u$T^$:)�:����~� �NL�d�8�P�����n�DDe��������S�\�E:���N��v�M�j�q

ahhh�� ����@�������]8DQ�������"�Y�{��|�wR��R��P8��� ����N�t��@]Q��!�R�O�v"�w@Q��>'���(h	kh	k�LC�R�}�M����{p\Tp\T0�E��Q���|�1��cuYV�C���J�o�������(�  ,K�G��l��������l����l��w<��
���(T����|�`_L� 2�GDDDDD4��j���j��cn��:�_�bD�R����[�#(���Z{{�Y�������IV���7c���pt�N|��S8����?p��������W��Yl��h��'����`o���L�w�K8���uI�c���Et�U	u����*�����oN���:���w���_�NDt��$�z[�jU`��}�r�i�����w�o��#�N#�N���CS�#���.}���h��)����!�*��ND���������}]�
�#@
b,�=�T�}�R����tR��t_�c�>'��� XR�G`[�J���o���;_D�QD��N}���w��G�+`��+uI�B�;�������rVE4�T4��@��}dm)�����{��g��|m���W&:�%U	EAB� sm"""""�Yap���j��}d�8R}P������l�j�����jmmmg3E"""""Z�A��K7b��1z�(�=�4v��K8�u��dG�����_?�#l��vl���H,Z<g��}�y{S���otr:�#.I�X������l�e1��h����A�/8��^D�[����d.�"��� ��b��bhii�2^,�
�e2�~-{Q��y��y=zt���(U�����!�H@��s0c""���$i���![��nF����@_������e
al��@]�O
�uB�v@���,���ND3A�HS�HS��.����K!���[��	�6�]8P0q�`����@��%�N
��n;"�����P�t��m�������|�P_�F]���T��O���0��`_��������N��=""��b����;(G�X)�M����]�<J�;�Zp���^8��E��l�DDDDD���/]������u_z;^y�_z�tjF����=�4���:�����K;����iX����<��d���lMGt�#X��Wy���B'7����.C��^���?���w���M���uP�5�!���BX�d	�,Y2e�q�R�J���p�������b�61888eLE$�@�o�~]]TU���DDD/I
#[�xl}��8���I��nFL�DM�e�'`�'0:�V�
-��w"�w�;�uB���$���|jPe4�Q|*
���S���U	��o�&��8\�p�h���L`l��T}k&���k�� @�%���������K[R���e#e9��n
��N�9.r����6��$IE����7�#"""""�{DDTC����	@���U���6�n�y��#+n����������������"�>��Wp����w~���=�������������%�kq�=�c�U�B����)��������Yt�I�2�%t�����3��"�"�����2��'�����n>�>f`��������\����h��e���hll�2�y���������9�������066Vu<�N��7~�D������L�u$��!�,Pw�l)��+u�3���nX�PM�U,��X����������}���D"+!IS7�%���Pd\��qe"�
3���@_��@__��Y�����o�x}4�/Vt��I�Bh�fs6M�(�bQ8�	�������J�>i��[�����a��0P�uI�P%$%��/���D~�!""""���{DDTfoVo��X��(M��c�r�i�>����N|mmmg5G"""""������7}��x+��[�{
�o���������?G�������|����7����0�'m��I;��`�����%a�����%
P��	�?�7���-�?�Bq
��VATg &"���w�K$U����iC}�lv��P.�C.�C__��1M��t�����������,��LlF2�96�mRIDATP��rF�\w%�g=�����G���B����N���D�J���D+��6�"�����,��xW���j����A��`�Q���	�Fs;a�8a�xs,�7(r)�W��)��T���`IP�)���@��}�w"�7�[�����\����`�nL%�*R�;�R���Peh?������D������n\1���i�{
��L�k{{��&GDDDDD=A���
�m��Gc�sOc�������������x��?�����+��,��M0]=�<��
dm�����::�&"�)��Gt1���~{#2�<���Gp����[`����uP��HDt��D"�D"X�l��1��+�FGG��T*���B�����'N���S�$IB2���[�,��"]�%���U�K^�[�p)�7����s�t
f�!�?�|� ��^�TAF$�^�Mt��[ ��;�h>E$bl�������y]�}&�pj��n�v����_��@=)K���Mt�[�)U}�  ���)2��t�����}���s���g���]dmG��&waI�t�+����E$�����W{��h��'�U��P[���"6����F�z+!����9������&JDDDDD�qE+���oc�W��O^y��
��;^Mf�����c����s�nY
g���^��.�ce,��U�.Z�$ q{��	���^v�0�3X���|��gWB�z13MCQ,Z��-�2�y������,�:3.q]###�:���
��������������WQ_wm���>,k���o�K_\7w�G���T������ ������|���px�����&�X
c]4����|*�;��}=�"��M�^m})��i���g��8)�W��hXR!Ns]($IX��8����!m�H��D�>�A�vP�_Pp=
N���Q@B����b�4��JDDDDDt�`p����]�W���������f��[q8�kkk��4"���}&"""�)=Y�������/`�[�c��Oa����o �P�lD��[��\��>��5��������8DTZ]��oo��O�`���?���zr?��)�=�1������(����C]]V�\�}�|~J���[���	]�d2d2���N��� ����X,���DDt�����
�[*u��a���!�n�r���~�n~����r�}���a`R]C��U�:��B}��R7|"�O�(TBq������U	��w��1Lj��;�z���c[&��Et�:#!���Bh	���y�/�"B"BJ���>��[��W���`�U�D���6m��M�D1UF��P_B��pC<""""":O�[{""�W�h�O��)���V'�=�p\6}�Jw��^
��������CD'#S���4rcE�Ry4bUel���M���qyz<t�G""""*QT
o�n���l�G�>��]�T�����-���	R���?$���G�6�CW�{:U'�T4>��7�"�r/p�5`�����shxh-������h!��C�u�X�b��i���&�����9�P�P(�P(���cS�dY�������d����DDt���R�BK��pc������JW>c<����3�}^�WD6����@]�"�#��G;�]�J�>Mcv��&	�#�#�hLT����h�Bw���oR���[�@_���#[��l!P�D�#�I�BhkP���� T�p��w�����z��|�`�� ����J������I{���T�{R���$���DDDDDTS�����ut��d����b�^��Jh�1��ap��FOdql�2#��x�:>�����{Fo�`YG��������NOE�_q%��������o�����J�z��W'	��1��h�4#��&D��V@kO`�G����_ ��1�??A��6D�,���"�y�i/^���Os]�TjJ���[�q���K���������	��D"Q5�WWWM�������jOD��+�@c�-����(�Lt�3�����}k����yd�;����%)Z�u@�Nt�S�&�U���(h	kh	k�LC�R�}�M���6Lt�K����[�������"v����"XY	�i�@���m��u�  "K���D��,��t���9��j�����0����g�(�C|�D�>EFT� �5��������{DD4o������crC����<w�P����2������f?Q"�����C;N`�?s��fF������<��
���|{LDDD���>���+�1r��8����������^G�X��>���`Q��y�/-LZk������������|��?�@
u_ZIWj7I""��$	


hh�����}�r�)]��o����k��}�R)�R�����W�|'��t]g0���<A���!iCS�m���9(O	��������w����Hg����,���}�����Q�hn	���!KC*n���,�����gb�������(=?&��!	@{XC�x��H)��*BD��U�$�h
7�s}Y;�����C���,�,���$qE���
����"s�=""""":+\�LDD�&��1���n/z������+kT���0�����������"e����^���}i1|4��p��m�������h!)8.�2yt�
����s*^6
��7Q��M��t�����������~#6���/�a�]���&#
Y���H={p�_�T���w���+k��L�n�DDtZ�  �!����u�x�X�&��d�|#��d����G����Z�K_}}=�D��%"�Le��*��*,�����Y���}������p��������J�T��@]Q�KA�h'�r�/�w@Q��>'��� X�)X�)�R�
[z*���n}Vm}������7����5m@KH-�������}�,M�x�  �*H����|���xH[v)�7�[_�����q��Y�����)�P����@;E�������h�{DD4/<�A���U���
}S�icg&U���^�&����g5G"���"v�������V����{q��6������b�hao���\�,6�u������vo\w���v�@���_�����n��z�����b#��.�������O����X��������--��P�����PK�.���K�����T*5�K�����������|�,�2&�"��d�P_]]�b��haE��D�k0��r�5��<�C_7
�#���m�"�z������.*u��;�G;+�e96�#�\jTe4�Q\���)�AO����7�iin�-.Zxe$���2M����}
	e�e��  �H�*���1���]���}���]��:Y�E�vq4o�!I,��N
����
���������=""��'�O�+�e���N���}y���V��Q�/������l�JD �r����9��sl{���n^	E�[e""��������7m`�x��Dh���������k�G�7��-����������p����������;�9��E]��?����#�}p�} �j��i�e
�8�DD2EQ�������)c��!��N��7~k�f�G�
��*��&�����X����4
���P( ��x�DDD�O�4�b����]���_�M���������1j
bt��@]��L��ND���DVA��i���RR�qUB�U���s9���M���W�j.�7m��6^���U������P�@h��������;���]���})�A�v����Pt=
V�.��0�R���2$������.:\�LDDs�w<d���e���_�����[0Q�����G��K�QWW�d29���������	�-��������|^�����_y�EW�@W:��{�Ddk::��e	@�|�������v��%�ycF�U�f����>�3�����|��h\�z�s"����I���h��H=��)6:1�1��m�������p�DDT+�("�H �H���=0��>
�B�@���(r��9�uI6�E6��R���F(�������X�x�M���.$�F<����@�qrU}�y�&�2��0��}3P��C�;�;�]�:�GVC�B5���.*K�"��H��w=�M��w�`bn����	��	���c����\	�uFJ��5z��|��u�(�^SP��u{��q+����P���.���>FL#'uA�	IU��S%~�!""""Z��#"�9��>/cU�^�b��������E"S@������7z"�����>����eQ�86��CDDD����*���2p(W�����!��:Z�!�U��p�#���~��x�����=��8���+���+h�l6�s?Z7^q�ED���48��N}���2k@p'A\�R�d��lI�%[�lK�����ezf������w�p�F��F���s����v��t�L��v/����mm�,Y�v�$@ 	�R�5�*���
�@ �@��/����VV���U��>��nl��A�;���	x������_~����#��]�8����!��a���}�*�u����B}�|�B�2�IwC�V���$&''��$IZ2��N�!��5NDD�Y�#�:�T�p����`���*#�4B}�5
���I]��j�	�r/,��l�����~��D�]��z��D��0pk�5�WB�U�l����L��G�Y��l��W����,-
��w���YU�xm\$	E��E
	�(B-�a>oq�������k(yJ^\v����F��5��D� """"��xw����TF(�<�yR���e��e���L��$��gp���s�T�g�ap��������*U/Xm��.�${�M�]���R���#�?�N���=�.�_�9��y������p���p���!+�;7�X�M6���Qxz�k����*/O�+"�������@DD������`�\(�J��|���<o����J������l��T*�����|$"��OQ�H��"�:�2�yyT*�m�<o�UE�V��Z=���7GAB,�{Q�of|?��n�"�w��.�8��P<�2������|�@_
�ln��D_��z�����t[B�}������qS�y�  &K��6�54���@��0_��Qr��u$������j�F��(��|���K(����������������9�3����wBJ��z�w��o��8*�l���w�^q�D�qY�J�����V���J5�I.�!""��X^�E'K6�`���MY������	}���DQ�����������8��}�UD����=?�����������?�E���j!����H�<�����0��������2���&2�>���VIDD�|W�L&��{���EQ��:����`������b��b������9�0����������64E� ��2������,*��E��QX�|�����(�m��m����s�qAP`�����}�0b��E.s#�E�����0������k���	����J6��Z�[�D��������};c*���,��"�u�z�z�0�P�\�-������0�L��L�u�Q�J�+�|�/�*H�qu�.������;xE����LE(�x���$>�}����������h�����#�`7,���D���+����=""��.�"L�\/X8[�a5��7�T��6����t���b�����Sx������n��f(��������/��w���������m;��6"�>�@�����O�=_^�yQ-�������"�����p��� ��������sg���8C}�|�bQ��wtb�6l�����EY2��J� I�:TLDDt�T��l?��O6��(��N�C|�P_���J�k�"�$��3�qQTa{u����� ��+Q/���=��=��/`a#�0�p��s����k���F5�n��w����5Q�>Ckv�����iP�+_��F�;�u�RE��pQ�o!�W��?/�Ph��rqYj�>�K+2t��]�������{DD�f��Ex�/��n��]^�%����;�E
�f�EC�����JDV%_���
�[4ODDD�&?q�\�����7�?�,����P�DFS�P����A������������o>�$���e�{.���sx���a���p������[��������u�?<���W|���$���_?e���
���F�i�l��-[������b�������1==��/�q�u
�y����iLOO��	��t:�����j�W$""�v	�M��
�/{os<�"8�$*V�C_e����������E�r��qL-E����@�~��V^#�Q�+�aWL�����(�E���C�������6'��A��*���B���f�o��A��nu� ��%������z� D�����b#�W��Um(�Z?@�p�vZ�5Q\���(��%��IDDDD�E���)��D�=������������J�B<�{D7�(�`{��
UDQ���DDDL��q�ha�h�	W~;<�H8�21�4�I���[3L���_�����z�	L�]��g�|g�|�v���G��O�I�n���6A�����)��{��t���da���B��}0���J""�Q�����>���5�J�^x�DQ��p��7�u����C��������|�|g��i����Kv�3����h������}�7��(D�v����6��Y�(���z]aXC��>���[�%�\��w�3�ah�f���� ������x�/���3���������Xr��7�[
/�p�������`(vy�>
{
�e�+�$���u� �P���.}�B�/��&%Nb��b�����$H�R���K)2���LHDDDDD��=""Z�D�h���~ u����z��^2*@,-,8��k��j$��!�"�n�����\�l5�C��������{!B?��H==/�\E���8^�p���j��m��C)�L
�:/��d��>�i\8�!�=�N��5`�7���O��?�_����%�K��s_@,��r�D��d�~����$�3�%�y!�7�T���B�x;����� PU��oG2�l��V�-a��?K��:T��R��R������5M[2��L&!~D�""�k� ���v �����6��(@�z�5�JedQ�����z]A`�Tz��;-���h��B}������� ��)��)�7�z�z��1������o��M�/��S��S��gf��	v���}:�

���k	$Q@FS��Z7����4C|���'���� �0���sZ�=�����������DDDDD����(�4��\���w��w���wbV%�i.?HD�� ����P���i��Y�^��(��#���5�C�.Uq�h������ `8i�P�DJ��.�	���o���7#�"�|�x����;��������o�����[�G��ed6o�r�Dt�������(��J?9�+�������/#���P��{W$�2�b1l��
��mk��<�B���oq�/��#��:��8�t�.]��6'I��t[�/��"�NCQ�U����m� �0�`Cx�9�����X��*�T�c����u�~���(�l��4����}��@_��5��~UF��'����
��Q�i�]p������.��.~�k�d����:�M�e�A@\�Wdl�l	T-Z�|����W����e/�y���DL�a�E����C�&""""�������6o������v��$���;�^�e@�M�]G��

��N"��(���|8��Z�k�|0��=���������iI
�~�>�>
;M�����x����
7\y��"�P����u���������O~����?���{������o��)��������q������M��NtD�����'����DXr�|�?[������#{`~|�� "�
CQ```�m.C�J���������K�7v[��r��r�������b�X��%""Z>QT`��`��<�C�=����;�5
�>��A{�/�P�%
�_��+J_=�������(���DD����R2�J����~��C���������D��D��O��-�[��@���E�������$A�I�i-�~��(�^3�Wp}�<��U�j� D���R����,��C}���"C�5EDQ�H	"�(D��?��8&"��Vyyb����m_�b.'q�����fg
a8��{�J�$�5xj�e��l�U����p��%v�������X\E��D��Sc�������(������	{y�.���pS��VC����X<���M���c8����WO}3�g�wp������a��a}�1����%v&�Qi{��ww �w#���/�D?B���Q;U@���!�DDD�(�H��H��msQ������|>�J����)�J(�J8{�l�\,[2���!�c�""�����x���-�A���O�;����*�������������/��/��2�����|��}�a�� ����DD��#IG���>+p��C������(p���a���R�5������~C�w�3u�+���Y���>MD��zm.�"T������Qt�f���l~�Z~a��0{Y7D@Ri
���T���(s���r35�5�����'g,��=�*�$b�h��JDDDt=bp����JPr`��8'�fW�z�V
:_���Q� A��]�V\+�LFpj�B(�ru�����z��n��������V�T�����tC]�
����/n�T��������� �(`8i�`�DR�~.�I���>��{?���=�=�y��e��(����/��p�_����<4������#�U�������������yj�0u����B���]�DDD=$L��i���cG����-����
���vM�V��V��x�b��,��d2m��l6�T*Y�~�/��A�4$7!���e<lX��F�o�5�2������
�;���\�g-����x�+��@�$=����LI�m	�%Z����g��@��f������G�g=��
^-�n���E���}6���}�  ��m�@�(B5Ql���a>����*�X�Z�z����:g�"��R�-
����a7`��V
��U0u��^LV]LV]���`PWqk6����J������x�����J�g�\���o;qeP�/W;�+����`��-��b+-��.E|/X���4���,n��:�/�PjV=�8}�PcJ�_=�������LDD�^
����JU���`�VeJ����]�;�
�������������x������~
�[�f�b���������o���<�;��e�6
v�j"�������C��B��'���|nPp0��� ��n$>���?DDD�����`��� P,����y^�W�
��133�����9A�J�����i�:TLDD��$H&oC2y[���W���F����q.��.����L"�{�e\�w n�l����0c/$���^�%7�c�)����#�5}�a���S��G�&�~���^/�����!��c��@\�A`�Y���3����|�>%��AO����\���qU!��P_\�����^jA����8S���J�j.�.�aO"��R���������=""Z���`�6�qNJk0nX�k�[�u��s�V2���w��u�nTa��z�5�yN�[�|����;���(	�����o"p���z��������"f&�E��j���}&b	�����F.X>,Zm7i�C���q(mbK��{������?�=��;x��g����],,�X�Z�����7�y�wGy[��n�Dt�Qw$0���@�FQ}ov�'�@��q8g��~u?�8;��$I�.v����Je�P�m��P�Bm�B�Bcccm��a4��.���y�}�""�k�,��JF*u�e����_�i>v�+|�]C��y�j�1����Q���z�o�C_�c7D��y�^RD��[�#���m��Q��j��h[9q�d�X����!�6�f��@���
i���Q���b@o��D�^k�o��j6Y\-7�0S�0Sk��D����|)UAZ��Td���������9�����9S������m}�j�UGDDDD���=""Z��������\�S� �b���J��v�,�J�&�����_��zE<'h	��,��sk�z������P�5�y��B7h�
E��|T�5�r�_�"X�����c�B	�JY���3]�LI�[�����!FK6N-����3�D�LLH(��e$S����6�������_���������:6�B���3���3l�G}���8DQ�r�Dt�u�����K(<y���/�HS��Md� �}��IDD�	��D"�D"�]�v���j�f���P_�X\����
��111�6��*2�L[�/��"�LB��]��������N��t���q��[����y^�U��V�Q��cf���� H��v#n�����z�����(2�A�K�(`��a���H5��(��f��i�F���l-��x�\�;���n�(`�|g��`��c��-;�&	�����`���(�`�!�������������>�n�z��,5�|r�gJUz��n�����,�5
u�A�g'f���~������68�b""�U����]�8'�2��6��5�'��/m�&��q����;w����6����F��F(��9�E�nG���d��8��@��S ����}}=	���	
�Y���R��c{}�2�n���2�&�I�����)�:�GDD�+y���������vj��2�M�I� ���������[x7��9�}�-{�	�������8r�����4�#_�
n��sPcF+&�k� �����$rs�Lu���e���=$���gwA��}���h5t]��-[�e���9��Q(���+�e������)LMM�����t:�����*����Q�,T�nd2w7��(���`UF`Y#�@_�����^S����������qAP`C��|�~����Xl'�!y�^�bv�4<�h<�"\t��:�98iWQ���Xk�Fx�R����ky� `��}�@��=1
�2�����"!�H�v����:�-�*^�^�h��*~�	�i�%��S����P�)�o&�� ��rk��������Wvm�I���������=""Z�WS����'�ATW~a����v�!h���C[�n��i+~m�kYEp�>j���-�vQ���<�Y��!�f�;�-�������������lv�����Id7'��bpW��J9�����������/D�R�K�(�H����3��3�� 2�GDD��0�p������K����
v�uJ��Uv�]A���#�}�����g�������_^����^��������������_F����U��@�lb�������}�}1~S�z��"�_;9��7DDDkI�e�������sx�(��K��j��:T�P�|���O�����fw���}�X�������A���C��#��ds<�"8���|���f�/���E^�#���ts\U�>��zg>�F<������Q/	��m��m������(�0���j8����}s^o��xQ�V
'������Ea�z������
�b�$bSL��X��~����B}��^�Q]B��.�.�'%B�+_�K�R��TeH+�.��tv���A��g��os�+�ODDDD����XD(�<�qNPE�?���r|PYz��T��YCCC�zm���{�B����.V�\��dUZ��g��M��B3h����pC�mF)g��-o��J����[;w
�F;��������(�lT�N��V*B�-��7�DI@"�����|wS#"�
��)Z8Q�a�+��K"�'
L�0�"�Z�;w�������o������Q-/oS����'�o>�}��������1�g_�+&��&������4��;��]��pw�����&2�����zX%��KE�R)�R���Ql�n��?.���P��J��J��s����i��1���f�H$ ��:�� ���������Ts<�"8�$*��� _=�w
a���|��T>D��a��(�`�{������������� �j
>�M���6}#�����_�I�l�l��j�+�^��1lh0�����EYMAVk��=�"X~�(�����Y��uW�Gr�����y� �HH�J�;_���O�l��y��3WX��������a��w�<DDDD����U��A��N1?����k�Gy���8>M!(���kWFp!���@^��w������VDQ�w�k���F�<�P�
�kla���8�����g��������8���P��}LVu��R���x�_�5~Y�����6��6pD���T�#_"k@��H����]9�����3e{U;��i
�M�c���v������?���
�{�	�]��I��� �����?	�����>��G�����D�5��MPv$0����..�M �}���������� ��
��2�a`��mms���P(t��W(��wm�qLNNbrr�mN�$d2��P���,s)�� ���������9E!j�	T�QX��F�o�}
a�^��FVQ.��r���qI��4��;��������A���A�*�_����x�x��1j�0b;�jm�.\0���x��x���r��m���@�C���#��@�(H(2�����F� D���B}��r�"%/@�p�����$.t�S�,v��*���0�GDDD�A�j5�HE(�x���$ �������N1�=��gQ�d!Iv�����'�Q�s��ny�F8�������Pu����5����E�7��3���{w��/��I�=U�����/t*����I�mM�wZl�f-T�������sU�����	`�cH��_�5�$"�OE8[��x��Tm�QC��M�������(���>�����0��1{�{8����>~����8�>2[����_���}����D�+�?�M���(>3��������/�/���!��zT!������i6m��6J�R�P_>���v?t�� 0;;�������d�����p���+DD�� "��Xl'�?������zW��|w�Q����������R�m�Jo���r���/>��/~���k�D� ���X:���[}e?h��F,�����*����D��D��O�Z�wo��}Z�C�~SGFY�2eA��6�6���9/�A���`_�����F� �]u1Y���������!��nC}""""Z?����N��]�;��7ANi������Spo[0��a���P^|��	�N#��8��4����i�C�$Bo����<S���������L����={�f'J}���'1t��ew�[.Y����@vs@����\�s^)g�R�!
����(*�**�*.��w/5S�B���X�6""��T�'K6N-���o��$R�L+����� ��s�]�s�]�?�cO?�?a��M������g��w��?�0?����.WMD�A�E�������~Qu��'�L}�-d~m���DDDt�Z���rQ����@��c��M����J%�J%������b����l6�x<�pu� H0�!�0���xz�V�6}�}#�V�E��2��%��P,kW�L#��!�gCU�]����%d	G�&�$��q+p���o��5}��N�Bm���I��K��@��*�t��o��}���6�VD���~]m�e/@��Z:�=������)Wq��="""�
��w��hE���'�����u+~�	������~

������B���f��z]�<����u�h1��@kt�[��U��\P��2����me\<�C)�9\�I�����>d]�p�$�Ho�#���+^����(��(�,T������U��*�0yf`$�f�/�gB��U�����L������J�y;�J����A�?�\k6���������_�]���������fU�ul�R����.���?��=���G���{�\1���������O�=��f*�`��'��*"��=U����6:A�����c���y�q:v����C�XD���j��.���ms��4�������4$��c���;DQ�i��i��{�l{��i�FQ��z���<
�_�P�e����/�����S�d�k"�v�$�����F�x-q�Z��l�j�:�{��|��1�V��B�=��"]���TW�)UF�����(B5Q��-
��A/{����vV$"""�����DD�l�x�x�EX�M}P6����U[r.S�Pap�����z(��1��9��s���t7�&Y����tC���T���"�/e���U�av��J��J�F��j�$�g��1�oO�L��X1 I"R�&R�&v`a�R����P��(������]v`�\�tSE��#�	-�]���h��(�x���E35o���0������C*]�~|�k���?�[������3O�pirY����_�)>|���y��8��c��(���Mt#��:��V��?��K��+|�����\	}_?e�\��DDD��i����7c���ms���X,v���y���m��y���1==�6'R�T[������i�P1]�DQC<~��`pa<j����X��|Vek���1�1�����"��E������o��a>��Y���."j�K"n��pS�u3u71Vu/��W�i����M6���-�Vl������@��c����)W��,��%l5Z?��A��7�[����J�7����!��rSo"""����=""Z��KK�]M�=x�8�q<YP
"dY��m���t}�n�k��Wkt�sl��w�W$�B�c^#�W��W�i�Y�n�W�L�0o����"^z�%���{R����w%�$��t}� tF�A�Y����_� _�rQ�\L�-4Ci��D���f(��KDDK��'�NmTW27dS&�'
�d~��]���?����{�z�{�p��e��wp��w���G�
}�(*�]/ID����Ma�;'V�s�S6���m����]���ADDt�e}}}���k����r�-�7��Z��C��

����i�u���i�&?����$���H$nn�u������TF�8����j9���)����2�k[a��A�x�S_.�*D�m�(���������F8[s�>���k��h����W%�*�-��$b������@�]������$b@R1p���A��5�|�����u�>�
#�Q��-����6���hY�Kj�;���=)h;�W������mi'���d�s�N�2��nQ�w�z������zU����_M^��wy�<]���"��O������D&�D&�m��>�����|G>{�����a�.b�|��2��� _��@,�n�DD���(�L������JuU�u��&v����J�Q�����c�]��S#8���q�� 
����p�����g��p��/��C��H��[4��>���7�`�;'��*,������Q�N�y|D��|����N$�I$�I����m�Z�v��777�R��/�,�e����NG��.�K�R�������$H&oC2y[����aY��A>kV��s����Us.��\D.���Q��EnF"��Bn�a��$q�/�� ��:�:X�5'[:���}�*6x\
;�N��w���y���}�}�`��c��AWv/Jd4Mi����t��;f��70�� ��|����������DD�,����m��W��Vj�m����pCCCW}�v�A�!���5o�:�u�(	-���ny�=I�
v�A`�t�)[��!�"T�.J9�����
����\n���D	���.�&5;�%�I�A>"��F�Tq�`!�����I8�6���V��d���x�������>�z�I�����V��>@�T�/���������}w>�����r�D�RBE����K�Qz�,p����wf�N�����P�'zW$mX�X�X[�nm��<�B�c��P( �f��p]�.]��K���DQD:�n	��?�d2P~�&"��'�	�Rw ���e���a>kVek���AUD1Q��83�S���N���a6�����0�!���Q/JD] 	v�4��ix�?������o�S�I��R������W�x���S{u���4��iPW�q� �+2����f}�
B�����������DDDD���#"����k����8�l5�
�����(�)G�87X�`b���Wu��(���|���P^��������I�)��y��@3~*���]A���`$5l�"�"�,���o�F1g����o� w����2@V��|����a��������(Z8Y���b�TS�p(e`8eB�����,�?��������x���q���4�������/����#�>|Gy�n=���D� 
H>��P
s�>���,�� W�������C��������h�E������0D�Tj��?v��?�t[��Z:I$Kv�3�����FQRH��D:}g�������QT*#��B�
Q���Z������� #���9�������vAt'Z� `��b���3}��xE�v}�X5�l�������l��FNX5��j-����]���7���~�"
PEn�u�KRE2��m8��G��rX�"C��W������Y�-)[.CT3wN��xA�k�B(�f{p�����VCVDh�
�T�?
��9��5Od�6 A�k��5��j����]��l�,wM��{�.�1w���d�l=���3`�c�sDD�EQ�����g+5��������&v�:D�<���1G�����8��/��������e?��1��}�;w��#���=�Afg	�
M����7������v��Bt@���8����~H&������j�N�144�2El�n����T*�Tu]�\F�\���g��t]_2��H$ ����<U�BU�F&sws,�"��,�F�oq����]�)�|��)��)`���� (0�=����Xl'A�z]D�Nj
5��&Z�f����}�no6"`�v0j;x���`WLm��34�R��%� �OS0Y]�5���)������hbp����(�<Xo\�8'�������x�T�8.D���M�vA�p��+
#85oQ�<�]��,����VK��-����.z�������*��*6�L�����f-T+ks9�C�+(L����P�5��%21���DDt���g�U/X�[��QY�7���������N�$�������{qq�8�=�F�D��:7������+��+���Gq�C_D,������$
�~�&T^���3c��1K����7�D�k��N��J"""��	��4a�&�o��6������b��0\y���R��p��E\�x�mN�e����@���t:
Y�r""ZA�i��d��4��(��\Z��g�6�}�V���"�$*���qQ�`{7�A>3>�����
����D��_������L�e<���j���@�E��I]!���������2�CWa�z����aS����6���=;�^�%"�+��z����c���!�A7���Q����V\�SNa�������EQ��4:��l�����]��k�iMjv����tS�n�Pc2w�"�@�)������"X��Q��(��(�,�%gM��3�3��q�( ��-��$�7����[��q�ha�h�YE���"�`��p����6u�u�!l���P���7�}���G�j�ek��w��?�w�����������E�Dt��{�A�����O����|nPt1��"��]H��cM�=]
UU188������ P,�}��=�7��;�}������m��dr�n}���C�DD�Q	�]�]����O7��(D�6���4}���S���
��0tP�|�J���qQ��4�!n�lt�����i[���heK���tk����j8����`���|�w���5�k.~2�:~0����z���mH���B'@���:@L(0����\�����vD�P���{��59��(B8U�����9����~��.�(	��y���*�FP�����j2��&�������(��!�b��UX��fQ5;�����t#��_��
;a�BE���8^�p��a5{5l54��2��� r!-Cj�f<�{���������o>�Tr��G;�]�<�,�y�Y�9r�|�ql��V.�!����	l��w ��)T��Y��!P��Y8g��~��$w�&""�k�$I�Nv{��m����Je�n}�m�S�����"��"�����
�X2����}����ED�b��mC���(
P�N`f�|����K�K��YDQ��8aXE�����Z�%)��
7:��G���n�{�:J���LI�-�V��e��F��V]�j5����1�������g��e��S!]��#"�%Y�����w�K��
��6�����oG�k���6o��&��EQ�	��.jV�k^3�g�p���w-Quy!�g�CzZ�k��I�N�c�*!�%��������(�,�r6*���t��"����������L�H�H��H�PT������8]��x�B�]��DY0�4p(m"�����f���K��##��������Z��g�|g�|�����G���o�b�D�
�.#�[`�M���������8�
�����~����VIDDDt�A@"�@"����;��k�����R��h-.���m��mms������R)H����	����L:�]x����OA���|��F`�����w�
�
J��P*��2.��fW>�����CU��^-��$��0p{�h�!�T�}cU~>b�T�{�{�lc�����Q;��""��"?D����q ������yf]���8������D�����a=���[^#���.�`�n�.�$�-����y��@�)���/��NV$d���wm��|������r��(\����b
V����s#�5:��Hf
�:���F��q�ha�d�]���IE����}	*?���d���?�i\8��=�N��u,w�����x�O���,��{��w��u�j"Z+� ��k3��	��u����f������>�oG��]�^DDDD�	]��e�l��~���}
��@��� ���:��0==�����9Q�J��������LDDK��������a�����}��@�(��qDQ��}��b���c-���]�5B}��0�����$��x7�c-�nb����N����4�d���v
�
�jK_��v
'k.��Qqt"""�
�+_���#��i%��\��[!�Qx��Ri��T�����^��\��(�[�[�x5������9�w�uY@�-������
�T!+"/]G$YDj�Dj��A�J�����R�Fy�^�@�]r`�\�bq���3��3���59��(�"\�|X�0a;�z������&�?�Q�����n��C� ?yo>������;����*��z{s�����(�|��d��&������o���X��t���_��s����B�to��@�e��������O�(��Kv���j�P�Bm�|�|��|<_2�g�?QG�� n#n���C�=�2�E�i������7�B�u
����j?�� �93�qs?d9����hi�(������zm�#���w�s���Q���27�|�P��� ����� ���2����q�]�����6����MF(����d�{������;�q<�!u

���������z�<gQP�*6n�	Y��7;�-�)�t���D7*Q��3��k��V��R�F1g��������ZqQ����/��M�q�F��P����nxn�T��������
 TQ�p��������F�[�-���?����W�)�}�Y����`���ul��(�|��������8�|�ql=p��
�6Q����ah{����(�+l`��+c�?���o#vs�"v"""��|W�T*���w��W����|������H�RA�R��s���4Mk��?N&�Ev^&"�V��!?�D�`�xTa��aU����C}���`�����ug����2�i�[�����,�{Ru&��:�:X�5'[:���}v���#��L�)c
?��a���)�^ t��[����hc�
,"�LE ���r�s�g��7��)��Y=��
Rm�;��6c��Mkv�n
�nu!��8���.|omB+�"�B�[^�k�|(O7�����DD�#�Y���m����XC)g������"H�I��P�
�>W�1�� _��T�X��nE�������
�B�U�R&�&cP���Y,����w~�q�|�����a�����"�z�8��/�y�~}�1����]������q���q��}�De��E5��v�'� ��=�o-���m�6l���m���fG������9
�����r�.]��K���%IB:����/�NCQ�u�����U�C2q��[Z�}��m��w�kv���L��.�������WZ�u}[3����I���."�L��i���P����0�p���v����`�9>����<��@zM:��9S�����B���DDDD�{DD7�T��D�|
���~�m����E���3:���`$4����'�O�����;�������{���EE���|��������<8Uo�K�H�.Ckv�k��A=E����Dt}�t�t[��!�"�e��+�,xW���n���D3E����_������w]W�(������������;L��&��v�k�$+������O=����cO?�3o����/���������p��/���<�0�X1]-�/�M��v�G�g��\��p�K�~� ��Gml��`��M7���b�-�7��u�u��.�r9�r����d�c�/�� c�����d�D2y���Z�}���Y�(��*�(\w�'u�jP�]@.���Q1}���F���3���$�'uQg� `��b�� -K(,
�M��95�/�8l��>��v
O�-�� -K0%ndFDDD��0�GDt��T��S9�r���	��Y�YFs�F"�����mr�����!����s�VCC�Y�s-G����-�i��Y.�`��KzI�D��e��L�Q�I�pCD�A`&u�I[�dEj�\#�7k���kr.����XB�b	 �R=���e�t�T�hCr��%'����b����L�H(�4D�>A����������8�7��>>|�����--�����������n��C8��W�����nD�,"��h{S���B{������?~���a��?�DDDDWCEd2d2����e.�"�����wy����u���T*�T*a||�m.����'	^#&""�r���RGZ�=����F`UFQ�F�ys=�*B�v��9���x��������Q�o����."�'nM��J��2n��3W��v
�N��-������e'k�������+���YDD�!��1��%�^(��X�xa���}����v'*�:���U

����(�[���.j�B��Z����6A�n�w�S�5:��Cz���*��m8�  ��Kh��;�(���J9�Y��
�^����`n����z@]��� _:Q���Dt��;�,�.W�G+�T"���)mbO"Y���1�m�����p�o��y������������Vq�����g��������<�-��\1�V�P�o���O�_��y����$�S������Z�� 0M�ib��m��� �������P,��:�Z�V��V��x�b��,���e�Y��iH?[��%�L�.d�w���n���o��������=�*�m����03���� �0��F�oq���/�Q�Q�n�#a������8Ys1(K����]U�M�a,�Gg�!.�>&\��5L�W��������Qo�[�u�*�p��s��V�T|�������������[s�:�9�������5}/hv���^3�����G���5OV��ny�z�
5�0PBD�=A��*tS���i�S�P��Q���|�����|����� ?U��.J��F���D<�Cd�R"Zga��U����+��O�+��P����r��n�>��_�������?�p�=�������#�x#�x[��;y{�����D�9�a�_���O����y�
�u�cSp�����!�[��������4M�����y���� P(�B}�?}�6��}333���i��T�c�/��@��u�������U�C&���XEp���}#�X������E~�3�h�� �0�!����@_�S_,�����DW����yn����������Z��G���
.��^M�DDDD���#"��X�>��8|/\�����%�����y��-�H��o�yl�|����(��T/��g{pA=����C�Mh1��@3T��!=S�f(�^%"��S0�#��)�[�Q�-����&�	����DQ@<C��@��D<�$3�GD�QB�-�(��>bw�N4I����)q~������H�=�����'' N_���[��O~������8��Wp������X1�� 	H=���4��say����L���[H?����X'"""�H������vFQ�J����o�q�����n���B�B���i�Kv�3M��E��n0� @�6A�6!���9E�,����
��uE���u�d��(j0�}�}���@�0t}��C���P<���L�V�>��
n�]���O�8��"""����="�����8���U���j#�����T l3����>�t^h�����Mwa�Bq�[^#��T�+��~-P4���������uDDWI�e�oK�[@�=���Q��akkr�0����fmL`��3�fG�d&�a"Zcs����m�����)8�61�Af�f���s�<�O~Nao>�}����P��������w��}���_B����U�J������}w��:l�
O��s����
C��6��J$	$	����m�V�u��777�R��/�,�eabb�mNU�%C}�d����DD7
A��[��[��w_s<�B�j!���.}�i�������0tP�|�r�`ja\��E��a��z�>M���.DK�7;7�����~�?�5��sQw��5�ub��Kpk�[��I�bK]b+n���?��G�����5��)/�q~���.����&�[k�$�Cy�����6�z��DD�[�*�oK}[�A>�P��Q�����B����(�UQ����h�xJ����$�vN%�U	�g+5/X��u�L�JC��M�
o��
o`�n|�_}������=���j��-�tlo��p��'p����G���}]����K������Qye����?�W���;QF��A���a�DDDD�Vt]���[�u���9������B}�cA�C�u��bjj
SSSms�("�N7�|�C}��8AD,���v��?������fW�J#�gYgE+��RA`�T~���-���i�;���7��������O��Mi|o���s��`��Kv���������#"��]*c���w�������P�(�N��������^�E<�_��g{�Y?���)!���u<~�va�;��zE�)m]�tC�f�P4����a�"!3�@f����!�sv�+_9_Et����B
�B
O�fJo���}�_��hiU?�H�����_y���$�@����	C��.�������?�������p���#��B'a���^�����7����>�=w�A�F-D�M$��u(��o�@P�|M����?{�/�F��m��������!�2000�6�!��r[�������g�n��Y������E����4
����l�����Q/	���
�������a��Z=���7��m�!�V���rA��[(��j��T�@�0T���5]K������\o�_{�������KDDDD��U�DD�����j%'���/���@#�v�T�����k��j��v���#�R@����Z
�rnO�E�fk(o����B�B."���$�Ho�#����!��j=�7k���k�`k��5L����}R}��T]Y����6[s�a��X�z�FAK�J����A��DI�t���������������������6���=���=d�l��/>����M�b�D���$�����(�\��X�����d~s?����"����h]���T*�T*������(�P�V�����,���Tu��y�<�e��W_m��u����g"����f���[�(�4��4�`��C�=��C_=�W��Eu����Q,�
���Z�%���g6B}qs���zMD�!�����{��[�P����^Z����� �p�7�F�OsDD�U�����@A"	����:�*��"�~���R��[/��W���Ww���T@���@4�~��U�6P�jF�K���S7T�*;���DID��D��a�*TQ��Q�Y(�U���U'���j���x��j�_�#�np�0��"�"���8^�0S[�n���c�)m�_��D�!�"��{������x��'p�����~�������?�����p��_���?�x&�����JDCA�����$
O������yL}�-d�����IDDDD�A`�������]�E>���+
���v��Z
������l��$	�L��[�K���e.""����x|?���-�A����4}]�����fC�+��9
��Px�e\U.���r��5u��x��c����5���YU�����P<���z��9"�
nv����Q,F��V��T|H��
�" .q��U��^�Z��[�3b�����	d�����&5�y���i�-�@`�""ZQ��Hd
���V��/�,�s6|omc��zw��s�S�!�d�	��������,Z8Y�Q
V�w�!�8�6q i &s�	��28�����{��{x��������cY�:�V)���}�z�p���q���``��GHD]!���
uWs�:���s����������gwB�������Z�����A��A�R���[����~��jA���Y���v�O�RKv��uv�'"��H��D��C-�AP�e��Uit��w���&zR����ug���v�����}�a��a� �fO�"Z+��1��c�?�^�?N�W�:�6���<����������TGD��U��%������*����s�
��������9/�:�o�����z���-�P���nyZ��$�]����n\�( ��!��a��>DQ����|�J9��;��s�f�1s��Wu����b	�A>�
(�"��</X�T�������P�����uM"��O}��q���>x�'x����0���������K?�/�;o=�;y��{7�:Q���������O�~sz�'F@�'���)���@Ji�+�����6��]�.E,�j��7��Z�f1�R,Q,1>>�6g����x<���DD�I�!����--��o��O���w����RO�r�Kp�K��{�e\��7}��}�a{!I�@F���"�Oo���7������k���x�������]������z��="�
,�"X��]�E/Df���sW���"B#D�����bF��87$�����M�&�F�;A`�t�)[�dE����R#�������[�1{���%��JH�H�H��0����a~a�R��������%��0p(m�OS�P!-E�c��������c�������,��s���s�����;q��_�M�z��v�b"�D�$d�z��4
�?��]:>��1��7����d{X%]�A@<G<���;���Y2�W,E�:T]g�6l�����Ei���lK�/�JA��u������,�H%oG*y{����`���@�h�K�\w�'u�j��&����hT@,������_��{ ��������`
�+U<1]�[%��l��k�)I��Iw$M<�)�Cq�R�����G�m`���Z )����%�����Q�6�S���$<s�o�,B7Uh�R��g��E�����w�F��X������M	
FB���DQ�����J9����N'�`n����2@R�f7�d��xJ� 2�G��,/�������Z���z�,�`����	]bWi��$�������&O��������~�(\�����9<�����������=#��n�D��<:ugss���w�-����OmC���!�|&"""���4
[�l��-[��|�G�X����x�
8��q�(
��"|m6�[
��0==�������  �N/��O��6DD��$�NE:u�e��
�X��*#�0�e����zPU�j���s���qsT$�b�!�a��>��(r�DZ?���f �X,��_�/��_��>�R�u���������="�
,
[�y��c�%H����({6}P���W�	�S�*tS�v�OY��:����i{)#����{��v""�^��B7U���C)g���Q��Q�V�w����TA�R@= ����A�~�t"�|D=E�j.�,�����O��c*nJ��a��M����e�<���J������O����n�^���R���o����{���p��������u�2``��9���g`�6y��V^�g����>���ZQo�����>(�������<�x<�J��d��j��nuGQ�|>�|>�3g������%C}�a��C&"��CQ����B&}W�����}�P��c�/v��(
`�g`�g03���� �0��F�o�K_,������[� @G4�-������<��6��vD/���������K�t{�R�u|��A�tC�SV����]���=�@:��m|��`�Hc`G��<�r6����|���&�	��i��zQ�����ot��� �{����g�6�,��+��\�M�p(m"�q�W�� ��	���?�'~�kx�������Gi���@'���������G:|Gy;o��7��zDPDd�mo�AT�|�w���o������m��U-ME$�I$�I����m�Z�.�+�J�/x�J��J�����������[�8�LBy]��h#R�~d�~d3�h�EQ��iv�[��7� �t��(����F<�����;�i#�A��^�8�#"��$Y������1�����y�!3n!7�����<�]�"�(�p��s���7�����E��oK�[
�9>J9���*���<a�8[��"C��@��@"k@����h5*���E�EN����	E��������Z�
I3}�+���b���������S'�}����0��1�����>���4d�^�^0n���-��o��{����"'���N�9]@��=.�""""�k[,��m��m���9��P(Z}����<�0\���\���K�p����9I��N�;v��d2P�]��hC��	��	}�{��Q�q&!�X�F�>����z]Q��R9�J���������C_=���[!��CDDDDD+���&�T�hf�����YV�m��:L�r�(m�8wP�M""�1(����I�mM|/X��Z�k����0j�.`��|�>2#-)�"LV]/X8o�V��r������m������$��'���O���#������S�|
Q���3�������x�[����?�0b�d��&"9�c�_����������k�~	���_?e���
��������(��@{G�0Q*�����8�:T\r�r�\��d2�1���f��z\-�� ����������9E!j���|��,�����OaXC����Z�%�hv��w���4m�U��"""""���{DD\<�C�P�����P>���^�����2������^���h��	��	d7'�����8k���P�W�E�/*�**�*.��/z0Sz=��_�)*�&ya���*�-\���������ii��S]���?�/��C(L]�[�����G���u��
y��;�
��������������	D�vID��!�{R���B�[���%���_���&.�""""���(�H��H��msQ���%C}�J��/R*�P*�p����9]�[�|���q�";%]�AD,������9E������z�o>�g�!����9��R��J���KR���_������DDDDDD�#"��2��Ry���WC/�H^�b�c�3@�h���{�mW��DDD�I���GzS!*sUsJ9��*�p
�|�b
V���3s#�5C|�>����t�(�>N-��l���3�T$J���0�J\Dt#In������o~����x��'Q��.�X�u������?�=G����>���n���.�d1��;0��'��).������8�H?�����DDDDt��i�4M����m�u��@���B��h-v�[�Z���/����ms�,#��t���N�!���ODt-	����5���G�z��������m�!����**(��B��V��,�����|���@__�k"""""�k�:mp��Ro�w������(�i��.W[q		�=�GDDD�$�H
�H
��0Q)�P�Y(��(����Ya��e����X\m���������%�"\�|X�0a;�z����Ci��A��n�q��G�����s{�{�:sjyG��%��%6
����>���u�����/nE���(��,p����[�p�����A����+��������*188�6������<o������>fff033�6'R�T�P_6���i�P1-�(�0��0����/4����m�5}���>�> �z]�_@��
�7Z�%[���a6�|qs���zMDDDDD�>����h�s'��=����/������8�GZzws"""j%Jb#Lg��(�P).
��l���p�V\T+.����4�|�~��0�D��8U�q�`��+>^'
J�W�����?�,��=���'?��?���~���,�����i<�����7�;��%���/@�3,D��Q@��;�
�0��'�:o8�l��6������-�LDDDD��$I�f��f�7����Je�P�m��P�Bm�B�Bcccm��a��?6M�����A��"?�x�G����m��e�4}��*#�����;;���C�����Z�UuS�C�B��4�!����DDDDDD���eDDXEp/TzzN�BQ������.*[;����.�DDD�%������F�K��J�z��wWL���=��E�����U]F������@,�r�]�������6�p�7`���C){�1(���
��z"��t��t�.^������c���:|V�rx�[����oq�g��������.WMt������G����N�-�� B��Q;]@���!�FMDDDD�\�  �H �H`��]m��Z�-�7��X\�M`m��m����h�S�c��L&�T*I���b""Z�$iH$!�8�2UX��F��zw>�E�v�'u��4��i���2�i[�!>���x|?c/d��I]DDDDDt��#"��"'@T�{{����
 h+y��q�n�8wGf���FDDD
� �L�0S:���CE���r6�9�Y��6�!�����f'JE��!�d�#�1�G�.�"LX>,Z�h//,��`���P�����D�:�������q�W�	���sx��'a��:�sjx��'��sOc�]��G�������L}�w*?���s�@�t���AS*�~� �]��IDDDDt�u[�l��-[��|�G�PX�[_���u��y���055�6'�"R�T[��L&�L&UU��b""�D�bH&oE2yk���W�����>�����g�3����-���qs#�73>��I�{R-�{DDXt�D]=�+l��!���%�{G����2"""�DIFR���,�(B�r���fms�5��s�.���X�����%��)�!�'q�d�x�B�[��U�?e�`�DB�%"Z�Dw?�U}�q�|�e{�{�97��c�(��/_��/_��}p���0��OB���DkB$>���r�>�`���s����?��v#���D~�%""""�Y����������0Q.����jK���0������q�����x<��[�8��Z:�5@��H�#�:�2�y%X�(��*�P�e��ug{RW�6�Zm���.���i7�������(�p���:#"��i}.����;33����NlK������h�A@,�!�0�+��.J�v=���P��59����T���2@�E$��!�T�3��E�������E�KU���7���2nJ����A�.THD������,n��gp��wp��'0����}����x��"9�	G�2ny�!h�����n�������(��^a�U���s���W@J�[Q��w�K�Rj��m�-�7��\.�C�*�
*�
��;�6�iZ[�����d"�[�+EI"�:�t�h����Q��v���Qx�\�
Q��E�z��?n�
��Xl��@�0��~��E�u���#"��M���Q��e�3&CPW�����f�L���r�*�"""���*��*6�L�����(�Z�V�59O��(LUP��DI@"[�%�$21����Q��V
�&�+��U�+��P����r7k"�A�����u�a�&���3O�����[^��43������7��3���������.WMt�u�����
O��p��:�L}�Md��}����0�a`��mms���P(t��W(�K�6�q099�����9I��N����e2d2�2���E� ��2������,*�� _�����K]�)���i��i��<������C�9�Xl'D��%DDDDDk�����60A�n��9U��9�m�U-b�����s��������lOa`{
�:>�9��zG>����y� Bq�Bq���D&V��HdH2�|��Zb�h�D�F�V|�&�8�4p e"��|�
"����}���{�w������=
�XX��n��cO?�7����}�>���;�����s�  ~�h���}�8�����
�f���H������ q""""�k�����i6mj�'C�����|>�]���V#�r9�r����d�c��l6]�{\-���#��G6���XEp��z����4�}AP�zMQ�5�����EQ�a�mt���������%""""Z)���68u{������!�/�����;���L_eUDDD�m�&�ok}[��
�A���R��U���y�0jv�� @<C����/k@f���9>,X8S�D+?�OSp(mb(�,ra=][�T������/�:���E{�	�&�-��(q����/^���7��#�a��wC��I�Z�f���~p����~b�_8g���o���zW$�)Q��.E,�j��?�,k*^P*�P*�0>>�6��:��2����6�%"���6MD_���xEp�IT�F���H#�w
a���Rk%]T*�Q���+a���4�5}���C����������
�#"����(�x�w��}`��\�t	���P��H�H����EDDD=���[�n���}/@y��R�Bi�F�PE��0���(��(���0Z�=�L�H�H��H�PTna�l���S���h-������]�MD"�����[?�ny�A���&�=��������p�C\8�!R��q�����>U�u�b����J���~������)D���~�����&2�����zX%�� ��������cG���8������X,"Z����T�Vq��\�p�mN����|�C}�t��k�DD� t}+t}+���o�GQ�Z�B=�Wmt��m�Bv�l�P.��r���qI2����@_���m��8"""""0�GD��)�M���p�K]?�:����\�qccc(.���
���73���hc�	��82�q@��(�m�f�����*�pm#X��B
���FRC��lv�S5~�����'K6N-�~���c��)R&��K�h�C��b��Q��������������u|q�^��?������s���?�D_��&�>�7A�����O��PY�y��#�_?D���H=<A{X%�'M��y�fl���m.
��.}�?�e~����133�����9A�J�����i�8ND�m� "��Xl�?������z�����g���� ����J�wP*��2.��f�/n�o<�U��a}��~
| ��5�ODDDD����DD����;������V��l*�qn���,r���F�E��H��|a�R��8���ks#�.9�K.���|���d��d_=����59��l���c�*V���J����A�Ao��g`�n|�_�����~o��)����������cYx���cO}>�i}�1��r�D��?�M��v�C���W|n�������������������F'I��������;�"����.}�����:T�P[�P@�P�8o����>�4o��Q/���aa`���xz�V��2����b��ZC]����(�D��f��,���_���e�^�z�TN�����p���'��������-H&o���/!?���Q�0�GDt��"v�����|�f�8<����_ 	�g�����:/<�wg'"""Z�$��������a�PE)g���Q��V�I��j�E��bj<�M�qn�~����y�;�(�x���E3��V`(����������e�3���~{�7���?��������e������v�t+�>�8��q'n�C�l�,"������1��#��Kw��.T0��o!��>�7��J"""""�HA@2�D2���]�����j[�o�g���M}���,X�����������]�K�Ry=���+DQ�i��i��ps<]��*�Bw�Je��9ks��J|��B��(~�2�(}�_#�7��OQ:o���}g��9
�7�|N�����|�U�=�gH����]����a�DDDD�m�]'�_�g������k�I�/�n��/��-\�w��%������h�E���D�����n�V��R�F������f�����f0}�Pc
R�_���n����`�Nm�,Z�+�)hH"�MH��R*$"�6)����"n��p��_���O���.����������m8��Wp��?E��X1��%vs����o��{v����`�oO�v�����BT�y������V&�!�a���ms���P(�u����C�P@t���R\���������DQD:�^�[��(�P1��MU�������>]����*������^����/��/��2�����|��0�i��,'�^�jx^'G�'LM=��c�7Px�
~��_�(�.THDDDD����uB2��-���w����J	1p$su����d|���q��l�@�XA@<C<���}��v�i��J9��6�����"f&�E��!�T��XBc��G�(�L������ruU{x�*�M�������n`�(b���a���a��){��8�����0/?y?����}��q���q����LsQ�r�ixJ?>�����������se�}� ��������(���@�\�(�JKv�sg*^�m>h�I"�X2�gF��%"��I��D�&$7���
�:�����F`UFQs.��.����Na.���qM��x|>�7��IZ���r��y����a�����
��q��_�,����h�ap���:�l6����
3���5��'&U��-W��hll��������~m"""�~	�3��L���'�(�P��(6B|�Ynmm6+��%�.�;����d���e�t��XF�Tq�`a��V|�${�L���q���r�{����?�S_�=���Sx������e[+���?~o��p���q���0�sww&�����wC����wN"�,����1�'o#��=0������QA�!	�������6��.�Nchh�e.�"���d��R��S�u�r�rg��m��u���<��H$ ��:TLDt��$��mH&ok��J#�7���9�����8�p�I�r/������a��P_��a��$�]��\9�7��:|��&���S8���p����#"""���#"��(�M~�
O�F���U�N���_���N{��>��;��[���y$.�&""��&b	
�����3�������Q��P��p���:��s�e�M��,.��M�)�� �jX^�E#%�`���LY�����)��EDD%�����������>x��8���Q�Z��������?�/��n�Gy�o?�0;�G��3���}�$����O�C���Sd~m���������e8e�Q�6���}w{������GDDDDD+"L��i���}{�������� ��P_�XD��:�Z��j������d��,�H������i�2��]-Y�#�:�T�p����!��5�|���=��V;�Z�<fs?]4*"�Y�5B}qs?c7Dq�
�����x��?X���<�/�������i(JfM_�����z�W!���C������zx�/��;VZ���P��v v0��O��}��m����U�����nL� @7U���M;����4�����Q�\}b���
�S���EI@2k �o �g"��!2D��(�0Usq�`�l������SqS��S������zw|�K���/���^������.������������;q���p���!�j+&������v�/M���8p�u��wg�NT����P��n~U=1������_��^-�s��T��C��D�����GDDDDD��*188�6������<om6�[
��1;;������ H&�C}�L����LDD�;EI!�����-��;�(�7
����|�
Q���Z�����QA���F����
#n�G,������O��Op��n������n�����Q�1�GDt��"v0[��������r�,<I��mO@���q����=>>ApA��q�f��w,""""����Ha`G
��|�r� ��
����y� Ba�Ba�0Q����3��3�� 1�?�p�l�x������xY�7������.�DDkA%����'1y�$�=�F^�9�e����8���7�����8��#���/�H��\5��$����6����O"(.�Y4��a���A�C�����������3�����%���� ����L~�"""""���$	�l�l{��m����Je�P�m��Tu��b��b������y�0�}����8n.GD�*������L���XEp���,k�����|�����(�m��m�f�m����i��|�����5fg_����]�sj��<�e��?���Qw0�GDtP6�H5y�b/��E��H������T�;����� %,��������]9/����mI�oK<����Q����k��7��k����,�gbH����|�$E���NT<��6F��p������Ci�I�DD]�e�<����Q�����=��~��juY���^�����O|7}�38�����}G�+&����)~����(j��~b���T?����",_]g���3p�1����F]DDDDDD�!��v���6_������A����R��(Z����b�6l�����E���/��"�JA�n�{DDkAhj?�l?��O6��(��N���w�iv���uE���8�i<�E��qs���o?��������s������
F�)j��<������K������su��2��$�������9�F��R�k� ���\��*.��xJG��D��@���|���(�d������VmU���Ll75������g��p���s|�����_��|�(�L/������O~��~�C�q'�>�v�r;w�'��h(���C�^���3c@���%w��f�
K.���]l��ncx�������)��c��-��eK����(
Kv��`*��<�����n�v"�"R�T�P_&�����P1��$tm3��?{����	����l$(R�fY���e��i;����������������������so���~���3�������Lo3����Tee���e;W��vn�d��-Y�MQ+)� �~\� p��{<�9�8�c�@�y�?�����RJT��P*���������,��Q|�A��J���~��r�_�Tz���%?7�����+.]����M�Z��(cK4���""""���T���3x���D�+dl�e�ET�k"�R��R�����*+f2��%�B���������P������.�xM�JD1�2��C]!�+l8|�(�x�	������sOa�����z�
���m���G�b�}����w;�$!b�m��=��o�����D"�ecv
��N�&�M���i����������>������Jei�k���~��`+�X�)�7�mB""j���FD"gT���G�r%����z��l�<|�Y�w������B�sf �xCCC�1��e�.���DDD�����T��`���Q��� ���b��#��,�����Wp��	@4F"m ������T]p\��[8W��,"���L��7��JFHDD���*���v�~\={��{
�^�EPR�
c�Cx���������x�q���G���<j��C�C�����S�a�[�s��g?@��{��|DDDDDD�2Y�.�Lb���M��ryF�o�v�X\�OS*�P*�p�����p8��J_oo/������>�
����F�b]�g�}�E�r)��W���w�=)k�8��)�^�!�"0�GDD]�|\�o���T�v@DDDD��
�}&�}&�g|_��+�0n���P���{~G�U.VQ.V1z!X�7b�H�C|������A>)%��U��[�dU���0S&6a.�@D��	!�i� 6�Dn�N��=���Q���r���������S����,?��l���Q�JXC���AxW
�g>��u�3�G)�C�P?�{[/�EDDDDD�D�Ql��	�65_���j��x���e�Y�~�����Z�bdd###Mm��"�J���R)�B����h�R
����X�pc���P.7}A���(�/@JoG��
�S�R�>+�*��u\�Z���W1
���-����[�Q�EH�H�� }	+_A>3���uh�u�rP�\���P#��H����%�!S�}�+�q&g!_s||H�5a`0i"��2�j�Z����?�'~�����_��/>��D��c�jo����������p��/b��~N,����]��oM`�{X��^��K��M+
������Mm��#����MLL�q�eq��<d2d2���$��@��v4]�����i��i���Y��*l�B=�w��;�ry�\��Nr�<<�����{(DDDD��1GDDw��E���j�DM�-����m�GEDDD�YB��D��b��4���U26��A��u:�"c�\���<�.�zD���$�LDcz�y������E5�7����}I�$�)JG�FDD�#��cO�&9���|o<��}���R��7~���v���#G����C�x��nr�\��8C�F,���Kr>"""""��BQ������;w���&��m�3�|��-�Z�Q
�
��������hS�o�9�A��{"�%�Xlb�=���~����?@�
��Y��(���Z���c������pVu��� �2Z����7_�!u�f23�����R�\rP���
Ne��Zq*.��0~��t���pL�
w�FJ��v�s���E��V3����
���	��heP5
��?���}
�O���cO����d{A����������}�����'p�3#br�`�9�'���|o�!��Q��0M�ib��-M��j�l�e��\.����n(��(���z�9X�i����d2	��-5�j��~����\���vh���(��'"""���������&�{�f�e�6��0Wn#""�5N#�c�� �W�j(d�A�q�r�#�r���^l�5�1~�eSf2����z>�l��[(�^%PWv'
�M���x����f!���}�e�AL\���?�w_�1\���w)3��}�k��w����?�$����<j����\\��]Z���u�p��������4<�C.�k������vf���p]ccck^PF�d2�������0b"��EUc��$\7�d���$T��r�6�MGDDU.�122@���z����������h%B �������N�_a�F�Z\����#���� US��"�6��3KE�(�j
��-|P(�]���=�����[�Qh\�������q>�w�����������V.����jo��,N�x�>�q����q�`�GL����p�������9\�Wo@��Pb!(f�����Vb�>�XA����������t:�t:��&�D�T����].��a�Sc��r��r����3Ms�j}�i��$�����#�����3?���DDDD��{DD�Q����R")������m�������he�:"���-)�S��0a#?�����*��s}��[�]� ��
��(��	[c�K����9DDD3D�	|�7~w=�x��?�������m+��s��9�����p�>�E���{��jwM�Ld��,/}u�z��6&�*"��B�!�z�o2���B����DDDDDDm
q��ql�����R������f��/]u�V,��eY�|�rS���s���T^�!�5$��}i�{����\DDDD�9�QG5V[KU�=-�����#""""Z=�h}��������TE��
+_Y�k{�@�GG�'w����`O�����X�7�����i���3���O��;o����0t�x��_;�>��_�9�p��_���>��atq�DKOz�x��|	���/�YZS!�����U����LIDDDDD4�H$��7b���Mm��"����e�Yx��#8����Q���6�)��T*����\.�p8�p8��%"�1������]��
<�d�""""��ap���:����BOd�>�}DDDD4S(�!�1����b��x(L��|�J�
0�|�JXA�7�BR�T^%�(���-)�"�'"����n;�m�B��E?�4�{�%x�Z[��F��?����_}?�0�|�	$���<j��!�5���������U��/\����}�`�����A1B��� """""Z�4M��u��n���6��Q,[V����@�Z]�O�mr|�AS�����N�[V��F���ND+N,������_���R��!����Q�1�GDDcYVc��L,��OZ������bh����q������B�����B�B)[��A��!�F�\�g/)/��3QE��!�	T�$�$��#��tDD�@��[��?�S���?��<��?8�r!���N������������������]��<b��a"�A�������o��7�^Ui��}�d�O�Y��Ap�	"""""�	)��d2�d2�;v�h�R�\.��e�Y��eu��,X���/6���a�������q(
{!���m�#�v��{������������������c&������������>�O
������?�d��3P�I�-�+���He��Uh��R~V�+_��&F"\��H�
�^b "���>�[���=��x���p�����r��c���������g��w?�E�r�cP���&�<!�M1T���{(����p+.0^���cZ�ov�o�~�AD5Vn """"�5O�0`6o����8��l�P_.�����0�@�Z��k�p����6UU��������E*�����uO_�Cx���v�_@_�C]{}""""�.~+%"������.*[[��3�pDDDDD7�����9���||�v�3QE�X�"��v�
�P��P��SA�>�hh�� "�������3��C����N��cO��;'�>����p��{H���;{>�Y�"��
�����%
�E{���o9�J5��|����/9���M��(	�V����m�W��*~����Y�Y�/��U������h��uh���y
�B�j}���og��0>>�������d�)�7���$"��=��r�_���v��������]""""Z:�Q�

��<�ac�>�z7-�������,OJ��x/ga����BJ$�5$���V�O���\r0:���i���"_�qr3�$;��;��c�C8~��~���=���s#���?�w��_~�}�z�q�{��<j��0�C���U������Z?��Z�����d����&���~A��m�����~��_t����F�of�O����!V%""""��mzU�����,�e�/�����e��|>�|>�X�z�h4���7;���x_���
������������;������C_C(��������V����#��bc�2�')ZOF�-�	DDDD7�v=����~�B�[xECU�'ebO�@DU`�+(d���un<�U��1;��K��)=�!Q�%�"1�7������m;��?��q���N~��������m[�J��3���=����$?�E�o������z������K�����(�
EW���+H)!�A�of�>gf�or�r�5R�������W��BWgT��������BP���t�-u��X�X[�nmj�V�-C}�L�B���r��+W����+Mm�P�V�����E2���r�"�����;���'����{a}�}
�����������{DD��W&���-���bG4�D#""""Z;����p:o�B������)�b(�s�T�ToICJ�r��|�Fa<����U;��Sq1~9���A�/V�HA�D�#f����b=�����|�����?����F������=����{�%l�9��w��0C+S��-�|�����S[:�zB��%�AKG��/}	YqU��z5�������]`����o��7Qi���h��>s2���!��������h�
����a6l�0c�P���c8��q�m�6��=#�����G��Z
��_�������H�RM���g]��a�D��b�=���cx������-�u��=��)+���QG

5�����}v�+P9�����m�/1T*�t��x��Z3)nID1��!	��_#���`��^H)Q������|��S��M�Z�C�j���j���"���if2� !�������}��:�?�4.��N��_z�m\z�m�l����=�}�|�������Rto/���C�������:D��v���!aA�vH_��k���9��}����j������i������xy��P��z�d�o��_}��j��MDDDDD+��(�D"�D"8t��D���}�J������,��6�3u���l�l~�aS�i�MU�&�
���2�5,�����3�|��r�_�}l*�1l������PGHDDDDK��=""����^H�qY����>��������a���,�-��x�����O\�g���Tr��B #c`[��c�v��
k���V\���H#E��)��
$�� _*
��D��nZBQp��{p��{0��y?�4���+�=����W/�G����W��?���������j��r��p�Cy�����$t�������mBPc:���v�~����S���*~N������i����'�r�[.��"�1�z_hF�>��gV��� t�J�����hY(��D"�D"����7����F�ov��P(,����,�e���KMm���������d2	EQ�a�D�i}}���!�J�ct�Y
o#_x�7��IUH&"��
O ���#&"""�nap���nX.�C6��f������T������hu�Rb���t��p����XRQ��}��Yae���D�����k
P-��!>�q�Rg&�{���h	��@Q��A�/�g ��BQy����f4�s���x���o��,������V[�V������?�]���A�u�(��n�������!���������P�cQ
���T��*w�����0�D{������fW��� �7#���b>��@��_t������ �W��7�z�R��N�������E�QD�Ql�����V�!���Y����hb�8�������4�)�����������Bk��=�Z��i���<~���R��>�dr���������.4�k=*�h���T������h�p}��6N�-LT>I[���L���e��V���[8���I���Tr�n=�T�������$�c�c.!����"����=T�A>"��I<��O��W��/}�^�N������Z�\���Gx��?�����]G�b��w��-��z�|���TG*�)	���B���n�Qt��=�y�J)!�e�oFu��m��k$��Jx�*�|{������5�~�C~f�&�������� 
a��uX�n]S���(
s�������X����d��dZ���������ht�GKD\�`rW^�&"""�90�GDD7lhh���M��$ 1h�?	�����fQ��8��q6o���I�1M�`���	�z��B���a.����1���	@��P���g,26�\�#���lT�!�XO���D�D�7
��>��n
z$�;}�~��+�q�i\}����~�M��&������G1x���t��#&�[h���t'r�~����E�N��:���������a
JX���"��%d�m���~N#�7c�]��Jn�@���Mx�&���/"Z=�7U�O1'~��*��P8�������n��(H�RH�RMmRJ�������J���4�b�b���Mm�H��J��s<��p�"""""�����)���������&������DDDts�Rb������KVeQss7a&Ml6�PV�*�!]E��8z7�n�Cq�nT�+�����,%P�(�8Q��s�J�f*�d=��H�t~%"Z�E���|���	\;�>�8�4���5H��u|��E����k���?�������=#�������f�/�E�P?�/_�3Th�X}G�OmAto�kt�4�" � h���M�/���Y���B~3���j���W�^�d��[q��6!�bhPL}f��Q�oj�AD4������hA�0M�ib���M������711�\.���T�Tp��U\�z��M�4������R)h��u�q�
�f�(��C�V�UmG�~�N�&""��W���A���99g��l5!�+�`�DJ_�US�����8z� ���(f�_!c��-C.�a+V�+W��&F"�D�D��@<m@���Z���=x���!}o��,��������Lk�s��w��_?�W���O��#O"�iK�GL�,�������X���s����"P��:ET�7��o���}B���0-�P��5���O������@_iz�����?K���EW	���r�^o��"��TS��������T�O�U�U�8
-]�100�����6�����[����,j��2�8��.���066��&�@"�������a�DDDDDDkg��
�^m/��0j��`��|���Xsq:g�\����0Z"�b0ebW���*]��S5�u1�������-�26�6|�3A>�P�]�bd(�Ec:}A5�d��]��H""j�����wp�o�.���p����8�<A���������"v�y79�-�oc���\h��d=�����������'?� �IV���M��CM�7yR��F�oF��rf�J�>��W!��|	�X�_lsr�&�C~�g}Vu�V�&""""�iTUm��f�R�T*5�|�C}�m/����������g��dFS����X,�keDDDDDD�`p���n���vj����o���d�R
����hYI)q���t��%�����l�1�2���t7<UA��D�/����V���d�/c�s����\rP.9��DL��<�D�#�!"��6L���q��_��_����=����}��'^��'^���;q�������j|��B�W���3�|DH��R�Td��RJH��Q�o2�7c_��_
�P��e�Jx�*�|{����@��A�oV�����������b,DDDDD4?!��8��8�n���^�TZV����@>�_�O�m�m����Mm�Ph�P_2���r�""""""���h����p�B��Br���������h��|�
e��Y���RnM��4���u}���{
�{
���3�����m2�Zg�|�A�rp�b�GCH�C|�����sr<�*��*�~���s����i?�4���@�:��!^���~�������m�{�X���&"Z:B��%�AKG��/��,�������^�����k���I��7Q�7Qi���h��}����zU�F��P��������f�D�a�l�����u]�r����l6���a��Z����Q���6�)��d29#�7����]���DDDDDts�L@""Z���q�J���cfO�~q���a�BODDDkS�qq:g�|�Fm�&������]�(B
+0�G�X*�X*����!��]��C|A��V��Mj�\���<�.����}F�K��o���DDk�����������/|�^�!j���Vv������O�%<�Y�����Y����&"Zy�F4����K_����&���������,|Q��JV\�/��Y��A1u(f�������*"�A(�nBDDDD�i����>���5����b�����U*�]������f��f[��b�9�����/DDDDD�f0�GDD�644��VU���-���J^P#""�5EJ��v�s���E��3�})���v#�0��6���������m8��[���\) s��t�z�/�g�H0�GD���o�������o�>����x������h�X�Z�����<�]w���G�b����{@D4��1jLGh`�������*�M����MJg�*Mt�|��o��]FA�3�z�o*�7}�d�O�U��"""""Z&��%�Il��������U�&&&P,�~���J%�J%\�x��-��K$P�&�"���M��f�8����xb��DDDD�UU������y���'��������)���w�F<#���=�R�j����26�v�#�r������VC
�}i�d�U/��V�H,��=��8|�I����x���q���,%���K����y+?~�������DD7Bh
�Dj"�VY�fT�����L��7������+����b��u4Q�M���x�gU�A������������0��M�65��j�9C}�\��/���j��]��k���TUE*��3���z�0��BDD���>.\���9��
���{{j�������;r�N�-�/����O���5�L��B�*�KJ���#b���T�5���%�#��j>��%dGKEU�HG�U�L�z�P�#"Z�T-������������������������_����q��O���?�������h���R*����WJ	�x�`_���v��Y!@�k$��Jxy^���BBW�B~�@�d�O����i@��{/�J
���������6�����A���>���}���<�L�L�e{"��3��F�x�DDDDDD��"]�~�r������&��}��x�����V_J\�*8��p������X��&�:�``k�GCX�%�u[���6B|�qv��������u���1(�@�7�d�D"m ���rB+�J%�����a���0q�2N<��}�'p���N3c��7�����q��������d��.�����%��kP���������e�9�7;�7�k���I��7Q�7QA;5�DD�Z�5}���5�FB��e""""��DQ������;w���&��eYsV��,k�F(
(
3#��F����q��#""""��`p���ehhh���D�~|�6�_�����h��z>�l��Y(����+
�$
�I����.��:M�h���D�� �W��(L���|6�|�#��}���
�@,A"m"�g �k@ee
"��w�f|������oo��E����������U�8�������������������0u���fX7�K�v����������g� �n����n�����,���!��@��Q=�2!�!�Z��,��1	�J�DDDDD�F�X,�X,�-[�4�W��9C}�|R.�
'�rW�\��+W��4Mk����E*�����-�{DD�(�W�R��-����N>&""��o�Z�����ex��i��0�2�#��I��Z(�!�!���`q
������R������(N�Q�(��9�%#H��i��DD+��H����;�������^��cOc���������_����z
v��]G�b���B��"�5I(jL��j}�|����Y!��a��`��,|��I����\�A�[olO���� �g����U�&����EXe�""""�%��~�z�_�����<�r�F�ov��u�oA�u166�����6!���������2�������V���h�|���3�,.���}���%���R�b����F�������L����8p��B*z����>�0��>�SA�b��w"��r�r\=���H#��H�y)��h%�B!x��������;o��cO����m��<{��#�n��<�9�Q��#&"��Nh
�Dj��	���������oA���_
p�.��%�~��Xk��&�!>����a?=�W����u���H��H��MmRJ��9����mT��)%r�r�\�v�4�������DDDDD79��""��v���j�g36������m���Q�*���6��-����Q�M��4ah��w�Q5��R�1���(e�A�o�B1[��u ���W`�+��� #�6��3�H��#��CD����v�!l���/
���gp�������F����x�;��m�}w<�}��<j""ZDH��R�Td��RJH���kT����?�������w���[�G���@���}�C~��?�)]~DDDDD7!���m���^.���
�e���`Y.]�����z�@_oo/��$��)������:��""��^m�D
�l��`�����1^qp:ga�T�brU}���Ll�E�*\��� �g"�g{���%J�2
�6
�L�����b�b#����#�ga������y��h���l���Oq�������8��c(��4��m�����������p��Q����.����nB��%�AKG��/��,�A�oZ�� ��L���5`������s���U��j��_#�������!�������#�"�b���Mm�Z
�\������r�<oFp���mjS�Tj�j}�������


��y"����������������2��Y��W�f:��x�)�"z�Hk��$z
$z
}��D)_	*�e,26�Zg�|�A�rp}8!$�i�� �''�-%3��O�����'�_y	��{W/�u��}�y�e�y�el��w=�E�<|7�~��h�! � h�6
�J_���U�k��f������v�M,Y��V��xy��P�Z=�7���3���� �h��B���[�u�������B�0g��j��#��d���x<����R'""""Z-�#"��<�������p=���o���7�?5DDD�<l���y��-�Q��P�I���4�8Y�O(��(�=Ql����v�����|�F!c�u:��k��a��c�R�G� ��g"�6���-���m�y�<.�uo<�.�z�����yW�����
���'q�S�E(������G(jL������|��;���M�Y5�
U��*To�|���o��m@A?�0_J��_�<&C~��DX��=""""�Y&���R)���cF���r��J��s�TZ�Q��"��".^����DZV����E<��(�0b"""""j�i
""Z��W��V��Tcy��[��o�"
-�����r.�XLM���������Nx�.B�LF`&#�pK�+�F5����Z�3(����+�_)Ba�^�/��0'vu�P���.���.\��!N<�N��2|������k����;��/���>�(�x�q�z�]5Q�U����&>�B�P�K/��������F:����_��U�j���
����b
~�����*���f��U��`��~����M�0`6o����8��lS�obb�|��|�=*�
�]��k��5���:g�/�JA�8m�����h)�8-������c�	c{����K0"""""��%�Je��Y���?`U;�Q&cHGB]!���0a�0���������mT�����Z�C�j��E�ROH��|f2�0�GD�-��w��������q�����<��������_?�Wx��������_D���]1���*PS}�D���+%���/9�0_#�g�f��|�/���t�'��xy���BW�!��@����!?�Ah��ADDDD7]�100��������!��7��&��/���<����8���[�'��F�ov�/�,�h������>���hAf��x���e���R����nb��������6*��W�45{�v'
DT�4O+����hL���@�v!�B�F�jo"�|����H	�� 4�j
��i�>f*
�A>"�������/��9��x�����O#7��:v+����W^�{����n�������P8����HV������y�K)!�n������������Fr~���9Ux�*��R,"�T�o2�7���3B*�K����j#�v�-��h�R���Fu���>�n��v��y��y\�p���0�9���b1���7BJ	�� ��R��/�DDDD���#"�����K�.��WHD!E�I��c\�����:OJ����,�*��/�>�c0eb���L�
DCG���)�P���g� _�X��y<�G�z	��A�OQ�=}A�/���2BD�)�H�>��?�(>8�:�{
��;���O�����F���8|�(?�Bz��#&""Z[�F4����K_��gW���9S��vYv��&���xp+e`�<g(Q�^�O����3�Fu?%���;�B�b1�b1l�����R� ��6�&&&P(�5�e�6l���+W��B�����d2	����4::�w�yW�\���WQ�N��{����q�Fl��	lY������V?����m�/_��N��������oT���D1"""�����X��|	��O|S��-�(S&z��.��h����6'��9	�U��"_�a�+9��I��-��-�P�=Q$�� _�Uc����F	E�����������p���x��@��U��z?�������������?3���
-�P��5�#��|J���-w�z�d��4�����'�^���R��o��m@A?P�z��^�O����_�r����ADDDD�V$��
�a���6�u����B}�A�����V�V����q����6!R�T#�7;����2�xy�={���*.^�8g�j����!

��W_���[q���c���K8R""""�6����mCCC3~6��+�+C�C����DDD����3yg�6�mN^�.��L��5a �Ja�F���HoL\�Ca���P�W�����H_6�� `��H���|�^Z�+�������#������!N~�9���Q����-��_�?�W|�!>r}[�uy�DDD4�*P:�D{�Te�oT���M��f���R
p~�dE���R
�=UL��W�MV��5�St~O%"""��A�4����������}�J�Fu����J�3�:.���.�����c������XSs������N�Z��/^����-<x�>�(�������h�1�GDDm��3c��{Z�=�H-�����h��Rb������KVeQy��Q��6�a(k�fQ;4]E��8z��^�C![Fa�B!c��-Cv"�'�R��R��+�33A��@2m"�6�I"�EI���'����o�N��G8��3�_m�X�uq����K?������#G���;��""��H�h�0�
��WJ	���!���i�'��w���J�Ixy^�0�"����M���!��*���+��
�(
���o���^.�[�&&&P,�~���J%�J%\�t��-��K$P����|dd���7o���;���.�+_�
�(�NDDDD+�{DD��qp�����X��e��������������b�sr����5!�+�`�DJua�D��R��CO�9�s}��e�3� �D~�&pZ�
�|�>��0i���D����("�����|�8�����8����z�t��_x�.�u}[������{���B��DDD��	! �*�pZ::o)%d��W��7=������D���@�|x�*�l�6�������!��a?#�rq""""Z~�h�6m��M���j�Z�"��p_6���/_5�j�������4����T*��M��R)�V�u���|��_�X��b���}�k��W����*��RDD��K�.5]��&*������oM*�\��Y8W��,"<�L��5a@WW���D�E�$��H�3�����4*�&l�^gfh��*�B#CY@4�A�� ������DD+����}�}�}�}�z��{�~�sH�����K�����_����=|��1�d�GMDDD+�"�A�j����K_���U�JSa>�^�o�~�T�,/|��JV<���1�VJT*���}���F���?�A(���
�B���GS���(
��|��}��,����!�� ���lO$sV��F�n��m���7������J��o|���?�����&"""�����ehhh��q3������X��c"""��MJ��v��.Y�E��&#�})��0���'��RT�^/����V�������j����r���p6BH�C|������g"�yl��w��������w~�8�r[���~��o��O��}�����'�����#&""��F(jL��j����|��;U�oz�oZU��*��u�M,	���v��yLc2�W��W��7����'�*�#QW)��T*�T*��;w�h�R��������	X��L�

7�E��9C}�X����`��y�����t�b/�����/u���������#"��\�pa���H	�j�I]�����K0*"""Z�j����2N�,�k_�=���0�7i"��k-Q7(�@��@����[��V�2#��:��dY�k�~1��s=�!�6���"1����������wq�o�����q��gQ���u�[s���^��?z;����|[���\"""Z�*P:���VY��!>��������j@��Yv>��Z�������`_L��?�����BPt��#"""��B�4M���-[���U�Ud���P_6�E.���rF(��(���z�jS��i���i������$4��{�g����S�:9�&���<���ww�<DDDD���HDD��V��r���}���������K1,"""Ze����y�6j��o�$u
�I�Q�:�"�O�X*�X*�����V�� �7n���P�P���b�r����PXkT�K�0���ID4[�0q���;�����8��S��\��x�u|x�u�o��?�=��Uuq�DDDt�!Z*�����RB:~=��L��&�C~�j��o�pGy^��Wp�_�D��i���*�M���B~���x������/c���X�~}S��y�����|��}���^;�u]���al�y4!����������a^}��%�k�����*���kxx�i�X,�alo��@<��"""��@J��v�s���E��3�})���E�R!`&"0l��)%*�S���g,8���p�U]d���Zh��Do�K�
��7�������$�������?�4���K�����_�/���	�|�k8������ �MDDD���aJX��������!����FU?gF���j�����/[�����FV�`_�������P����������j���lRJ�J������	���e���r�r������
�h��P(��/.�����1::����%9u�{DD4�V!�x��e���h��DDDD+���8W�q:o�X[x.]��0�7e"�WW��N�h,�h,���=�R�j���|�qU��)��s#EL���LU�K0SQ(
'��M��{�c�����\�����S?�!�j{)��x���	������?�;�z�o�������:C��D5�����/����r_i*�����5�'�~��U�4Y��V= Si��bh������������DDDD���x�x��mkj�T*-C}�l�|~F<��m�����//��O�:���*���DD4�.��#��%������+W��t���Bn��]���5�L��BS�.�����SG����5����|�q����sy���h	��@Q�����*_,����	��z�o�g�������x�G/�������h�X�Z���?��?8�]w�������c�S"""ZS�"��A��Ps`�����z�Y��R�Q�o����.|Q����� �8�FP��U����_#�7m,V�9������H7n���������\.���7=���f�yk���lW�\Y�!�"0�GDD�\.���k3��aWC�Z�O��������dUp:g�Zy�A`k,�}IQ�t���p4�u��X�9	p*.
A����a��5����Y��YE��F�HH�M�z�P5������q����]����xo<��.|���R�������������G�b�������4�
$TjB�������5�e�o2������W����7�|��_���j�Tb-B~����BPt~%"""�i����>���5����b���Z��������Z.W�^���������V����#5W�b�	���������8@DDt��z>�l��Y(�_�0�(��4�7i ��S������1���A5��������X(���������%
�6
�6.cB�� ��H�H�F��8���n�������������������>~��s8���%~�����G����<��1��u"""���)�Ra �������?'�M���O.��X��Wp����EH	|��@�:�Yol.�CDDD��)��d2�d2�;v�h�R�\.��e�Y��eu�*�
�A8<�w""""Z983���>�\��������D��"""�e7Q��t���2<���A���%M��G�)�Q ����G���;�[�P�w���R��E��i"%P�(�8Q��s@�d$���H���j?���z�6l=p2W.���������^���^�����m���q�#_@����&"""Z��aJX��������a���}�C~����V
X#9?Y��e���U�S�O�U���*~���
�c!(f}��Py�����h-B�0����77�;��\.�T�/��"����WFel�u�#"""Ze�#"��444��/��2����?������h�R�b����F��M��N��`0e�?��B/�K����g �y��2���-C��H��\�\W?��0�}f�*��P����hmKo�������~�o����7���|��c�r��=��?�[��9����vw�DDDD���jP��n������.��3#�����������%"���d*m�Wm���dE���_#�W�� �@����:���������y
���P���8��=����4��""""Zm�	����dY�_���������`p���hM���/�8��`�_E0�*��4�7i��X���O���cH������-O�&l�^g���*�B�>�|���D��d=��G[""Z��D���q���3����������������_����|w���G����CQ�����h���j���!��(�,=��a�������F�?Y���&��o�Apq�<gP���>�M����'�*6#"""ZETUEOOzzz������_�Rioa�N�D"�u}��GDDDD�������M�B�2��[����.#��Q�R�88��0T*c19��p�R&���P��4u��*H��H�����re�36
�A��[D���r�A��`�B1�F5�D������D��h��}��,��9���=�o�h���gO���:�d��|�Ix����FGLDDDD� Tj\������5?����7�����d�3���������m��(�F���r_M�����
I�4~�
?�A���J#���
044�d���q#� """Z��#"�9����M�-lk���CW�n�������J���p�R[��
��(S&�Eb!���(�^�^����U��0n���Yp;4!�b9�X�_��h(�����"���D�&!���;���;0~��?�N��<�m����Q��������8���q��_@<���Q�r!Z*��[��w��r_���T�z���Lm[5,j������
�������v����w����Om�3��)�j�"���DDDDKa��MK���i��������:��=""��\��a<����x��~"""Z�l�����3yeo�����`o����������he�@,E,��]iH)a��_!c�V�:r.�\���<�.����d=��H����#���o�v<����������[?8�r����U����
N<�v�~���1�sW�GLDDDD+���PzUh��y�J)!+^=��4��fU����Fr~����U���hg�5V�0����!������kDDDD�q��A����Kv�,�������s�#"��
�2�L�~36��sT�;�v{XDDD�Ac��,\(���T��)�c(��
'�����LF�ag/��(��� ��
��^����.��0~%�h��D��W�3a$����e�zp�o�>>v�7q�g/����1q�r[����3���3�����p��/��;��PX�����>�"�A�j@���$�/��� �g���F������vg�	�����z@��V��fV����k�)Q
B�5
""""���[q�����k��m��y�������#"��.\��r��Q��m��#""Z�<_b�T�����j;�3��
`g<��I}�#$"ZB�0�x���@J��]C~|�"_�^���V\����"&�jH�W�*���Nz#�U'��q�g��OCo������So�}����p��)�l��;}�?��"�WZ!""""j�PT3��Cz>|�
�}��~��i�e���;X:��������fV���A�oF�oj���\���������������~������� """��`p���Zj��iU�F��<f?�{DDD+��zx?o��������z��bo�������va�DD�K���#b���T�Z#���Q�����������)UA"E"m"�6��Ba���V	�(�y���y���~�C?�4���3�^{K������o��w���?�(}�b��.������h&�*P�:����������z���3U�oZ?��4�em��dW$��{��m��*f����f�����X��k�DDD�������S��v��b���]{}""""�.�����V�=36�!lk����'�?+D��H	���@���\�-))%�W���0\�`1��Gu&Ml�E�ped"�����)���8�
�q���r��������u��@Q�=� __�SU�#�""����;���������x��������Uj��J��_=��������>��G����.������hqDH���p[�}�k
����
UT����"���XO�+8�
�-�$B��`�>�=���R��(B�^BDDD�������0��b�_;���G�����a������r9�r������q[�c��c]Q�2��9`�:�cc8�L���]`�:`]?p���8����8�/a��^���T!pK<�����p�#$"Z��H}�������n��?�|�#��=��xP��B��"H����T���h��������m|����w_�1�?�4r#��:��\��������[�������C(��GDDDD����PzU�72g�B���_z	���	��^����i!?kf�?��aQ���@����U������_��!��U�&+�����P�H ����V�0���|_���P�t�^D"|�+_�a{M""""Zz�Q�V��� �w�[��E�8""�6'��M�}�U8p�J�8�&�~p�����D�V�R������yU�_��1M�����	aVv""�W(�!�1�����ySA�q�|�#��/Q�(�8Q��(i���B�������B�=|�}�|x�u?�4.�>���O�����B��-8|�I>�Bz{M�����V-����F8�����%��������&���V
�����V*Y��U=x��&�+���fW���M�� �����=��W��o|��������|-'�����\��H��lh����="Z.�
��+���?v���5`���}���W�%Z���);8��p��,*�1�c0�f3Ep"�bi!����]x���D���[(�*���'��J�2J�2����ddF�/�e?"Z9E���?�]w#���cO��_���bW.����������8���p��G`$S�4�*!�����j,����n=��f��j3B���-��X��������f����z�o����~Q!x}�����600�?��?�/��w�yg��s��A<�����GDDD�Fp� �����+J
�zR�����{D�,2��c�m����?\�
<vH�;36�.��>>,��^�B�Y�
�����b0e"���0B""R5��R�1���(e�(��(d,�e�^J���X�
�}8���H�
$�$�&�/�����[q�O�1��?��/>���"������B������g�����]�Ez��.������hm�5�C���y�K��g���}%����7Y�������@��'Q�5��m�WE�������/t�A?""�5�0|�K_�����k�axx��c�m������w�������h�q��011�B���?������S�E�n��h�Lx��Z����V�zO<���h����9�
6�ETm��T&M��0����DD��� �g"�gX��A�/�
�2|�3����*��*F.dSG��^���D8��6-�D�:|�+�{��e�z��8���Pkg6,��j8��p��`���8|�(�<�I�DDDDD] 4Z2$�m��of�ov��^�or?:�����$������]��Y���!��*JL�j� B��ODD������w����(N�:�+W����+�N����i�&l��	����2���������=""�ahh���Xl'p�e������h)U*A��N��&U�����o�Hg_��H)q���t��%kq��o2���2��sB3�
�("��
}��D)_���l26��R_�T,��9@���m"�g l�������5p�cO��������������g�>�����p�8��n��#G���OA1�LDDDD�\]������g�RBV=x�P�_r���!?����5���5^�
/WE���"��
�A�V!?�� �p��000����y���?��B|�3�A2�\�Q�1�GDD3\�p���u�ec{��}�h�DD��k�������^>����>��|�e��Y���RnM��4������h��@�'�xO�v���B�q�z��u����j�0f�1v)�#}A�/�6�����RT�?~?v�~\={��=�s��9�l/�<~���o������������x���&""""�!���hP"�7�=g�K�ew*�W����M���[5������T����z�2���+���f�&�'��t(Q
B�u ""�nB@U�?�����DD� �������"��l;gp�����0p�|w�q���V`[��{D��w\��[8_�Q��|p2�a0ebW"���Uu��V+!�df2�
��!�D��4*���m������T\�_.`�r
���|��#���D�t6������_����;?�j�r[���^��7����
�?�i���������#&""""�� ���������$|{f�o2�7���d�?Y���I+�o�Apq���RSa>3T���������J"��:Q��#"����1XVs+!<�	U�:���dp�����7��<o���-))%.�U��Y�bW�[�0�&6W�EB�0�D�w�BJ������Q����p�����V���ZD�j��&�|}�D�+�Q�%������w����=�������C)3����S�[?|o�����n����y�A~N&""""��U@��P�:B0��/]V��i
�y%���A�����I��TC[KD�bf��^���=k��~#""""""���{DD�0W��X,�alm�&��E�8*"�i2`������5`"����|t�r<�
6N�-k_�WWnML�������f"�@4F4���@�vP��0_�F�r:r.��ab���� ��j
��A�/�6`��P�#�.	&�~�7p��_��_��7�{��k��O��O��������G�����j�.�������V#�)��a n���x3C~���}�j~����.��%�I�~���N"�4����}�!?�A��.�"""""""���Y�DD�p�����7o����l�
�T��
��h���O�����cp��#W��t���B�\�����a_���x!�7���(1tD�����8�
��_!c�\\\U��<�G�z	��%��� �W����BQ����:K�4���S���O���wq���8����6?O_��^�7�^���q�#O���<�H,��Q�Z��*�^���[)%d�kT��K���z�o�~����~5^�
/WE���"����������M�75^�"""""""���=""��?gp����0�h��?�����L��<�V��-�����|���R��U����k��W@���L�������������6'��9	p�.��_~��]�L���$�c�c@(���T�����qu��`��d�]����S?��j{��J�������8���p��_@j��.�������nfB��%�}��c���_v��|������*~��v��],
Y��U=x�J[�ETk��z?%��
������{+DDDDDDD�t�#""���(��r�6=<�����mb��4��n��|������ks���y��,�YG���f8�nP��q�`�L�B��||XQ�;i`o�@,��qDD�xzXCzc��	��x(L�(�[(dl�����/Q����T,U��A>-���Dt�z6l�g��O����
����8���(e'�:�V����������8�z����g�d����Z�������$|{Z�o��_ir_mFPV~�b��en��Z�w�A`*�W���BSU�bS�DD�wD"""""""�!��IDD0g�=U�����u-��1�G�:I���	��
������c-�V�oH$�x<x$���2�Gi�Z�����ex����C��4�#��`���4]E��8z��^�Ca��B����;����@1[F1[������ �g �6O����Ecq�s��p��G���_��=�������_�����������{������BP�:����y�K������7���A?�T���K�.��D��K5�uWS3C~fP�oF�i���0�GDDDDDDD30�GDt����C����b54�z"��\���9�-����r���;O���*��Cv����m�b�hE��XH����B}�83�w����R��F������"L������KDDKJ
����g �\�l�z��8Q��;S
��W`�+��AP�H���L$z
�^�$��S��}��|�!\z�m?�4><�z����?�c���?�[�;�~���Oz%"""""ZM��@K��d�����M��&+�5��M���������e�I�~���="����}�B~��)]~DDDDDDD��8����f����c��g�������������<t�F'��e[oH���?%D3x�<��Z���ims��her] �
���T�o2�7�K$�Phi�K]U�<���8��a������
�$
�I�05V� "��A�$��H�B+����+�0n#��Q���wh"�]��.T12|���� ��6�HG�����'����c�����r	'�=��~����&[���������~?�y����H�����������V&EW���@od��RJ��7#����7�oz���kd�QY�����rU���/�����Z�����U�k�� T��������V�-�����a���������5{��`��0�s����[��EY�V/)��U�Ju�V�����X��fr`"<Z�DfV�������j0^qp:ga�T^��}���Ll�E�*��JDD+��*H�M$�&6�}	+WF!c7��������r���� �1C�s��|�|D����-��������o��y���1��\[�:�2�{'��~�>�u�(6����&"""""Z��
JD������%��;�z�3U�o�s}��v=�U^������_D�F�O��&��)��'F�����������g�E�
��+���murZ�4�i$�1��Z�������#<�u�n��v���[�a;Z	*��16���0Z�	�4�U���/%.�*8�+�z��5SgRl�G�/eb]D���������{
�{
l�5XQ��W��x�sk�D�J���b�p�b�G5D:"H��2���1'����H��/�.�~�K8��Oq�����|��c��q����/^��=�p������{�(�^FDDDDDt#�"���hh����$|{2��L�f��&�e�3��VYv��]`�<g(Fh��_lZ�����DT���DDDDDDD]���Z���l��C�
�m	����
6�l?���6���������X�n�S ����ok�����B�{����m����6!����P_"1�3���;uT���~���������MQU�����I��	�DD��!KEKE���4�����F����P�vf��Sv��]�1��������H�
�0'QK����C���?������=����l�����������q��O��C���u2"""""�� T5�C������t�Y�����~�����~���{��c[K��bF%��Y�Y�o�~�+��FDDDDDD������Lx��Zm�WJ\�#���,���'B-��3�����b�N��vBv���
�����k�O�:Wn���
������P�E�X^	�J��q�E���x�P_=���?j�X��{9�e,�vm$��T�b���NDD7!�Df"�
;{!�D�rP����(�[p*��l�BC�z�������"�63�d""�A�����������p��gp�������/?:��������|�}��������<j""""""Z�)P�a��p[�}����W�5��������'����'�����G�hJ����}�!�TS�q�Q""""""�91�GD�VT*A�����j������Y���-�t!���,p��(�U��iA�9�t-�vs��X�n��^������i����|��'3����
�H��Z�m��v{�~)�J9������V��/�
�������D��<�Z_<��+���%��C�2N�,�WLV�#�`�D_D�����V!��0��0��@J��]�W����P�;� ��x��V���"@���A�T�rs�!�)}[������p���'p'�<*�B[�Vm���q����s�8|�(v���8���k��C�
�\#D������VEW���@���!���Uo*�W������_iZ���[�
�+����U���h�j��3���!��D��0j�������!�� T�������hm`p��h�x���|�P��ji���q�`��=f!Npl����rU�n����X�n���
�i�T���0^����6��^\����;Z������]���qaV�o��T
�,7�r��������7};��\�l�������6*����������	�&�wJDD�&!"�����k
P-��|�
�R��|��s}dGK����*�����L�R(�Dt�3S=�������-���Kx����^���������?��W�-����G����!���2v����2F������Q�v
����b`�.�����}
}[�����������}B��%�A����_�~��V����������.�n+v��z�������[`6���g1��WD�F�o�r_���m�C�F��W������h�bp��h-��_��CN�	�[���u\�����b�_t^��<�#*������?�����~gt�������t��	���W.��m��]��{�-�n����7/!3<6lhn�� �WlQ��P\T�+�d�G+�H�P������jH)q���t���ReQ�@�Gu&Ml�E���<����!������I�Sq��� �]XX�����Dn�Bn�0E��F�HH�M�z�P5��nV!=��>�~��:yo<�.��v��_z�\z��l��;;����4B���5L������g��+g���O��p��[�x�-��������������w���sQ�	E@���?�I���@�T�i����YY;�d��[v������A��)�7��Q
���������h�����DD���7uXMJ\rZWs���P_�0��l?���=�*C�������[	���L�f�S�n��(���=\�����a�������(A��D���v������
�T�T��Y�J�k�nsW�3�S1��%��e���0Q]x�SU��b0e�7�v�-'=��oS}���������X�^/�\t p���}_�0n�0n�2�!��6*�%z�PC+�3-�(�y���y���'�=�3?��6o�^���_�^�����?�=|����<�\,�'_��8�����3����.���)|���h<��� """""��A�j\����](���B~5xV
~��W��M=��K���{X���NU�������}1}������U�������h��#"Z�2`������0����
~��(���{��Z�>���;+,7W���������~���5���}���V�5-@��);<�P�L�@8�ndaU:J��T*x�R�5���W���������1:��&D���K$��}�������3yg�6���oJ�4{S&v'�U�."""ZJ!]E��8z7��.��K/#�B�"�X�J���:-R��2�e\9�KF�_�@"m@c����2��<�������6N������Z�-(S)����o<���{��8|�I�����������g(e'nh�g^{��{������n��z-""""""Z��@M��&�m������d�oV��+�o�,��I�~��������7#�7Y�/63(x���������ap��h�;n����������9����W~
���!;V�[�4mf�vBv�U�SUV���K��'��?���{������n
���t�h�Z
|��T���P_�T�[nRUK%�U�\Q�X�E����F�;EJ�����9�
�kcT�`*��f
��>�p`�c�o�i�P��QDp�IDAT��b��w"��r�r\=���H#��H�y���f��������7~���c�8�r��-���.�}�Gx��a��C���Ql?tB�
�;������q�����O����?gx��������(�
�Wz�_�TJ	Y�fU�s�����_}�U�HA?�>�\^��Z���!���}fjL��������i�IBD���]_�����{�tV�:����7l�U��vy�����b7;,7;l�i����U�h�I����m��Wo(��]�������:%����u�mR�r�R_qf����ET��8�
�������D|f����pxF������X���������&v%�L�H����+"""Z"�� �C�?�=�l9���(fm�Z��W`�+��aP+#�6�LH��#��@����(�x�q���G���_��sO���w�>��;'q���Ho����<�x�o:��T�J���������A4���k��C��D4h}�y�K_BV�Y�����d����Q+@�	h����X4S:�	�D���"����7���B~��P��'"""""���{DD�������u|����k���(�Gq��l?P�@e������[H��U������������W��ap�`����o%�����]��z�\��RieTVu] �
��:��������8��%�C*�&nM���%����
�}&�}&��}	+WF~�^�o���vf��r��r�������������|C��y�heQ��}/n��^��?�7�=���|���Q2�/��?�?�6�Rv?�����?��];�tBF4C�>�B�~���	|�c��T"�`�3���dE?���@V��{3]&�.������,�h�3CPbz���OD5�+!"""""ZV��f�P�.���5sM��k8�0��l�W�u�U���t�G���U���o���1����_���LU������v�z��8�H���
��=���a���B1�-3	������;p�o�����0S&6a��"""Z�E �k �kV���26���
��� _�rP�\�����F�/�61C��A���������'
���8���x����S^�kig^{��?��w���C!""""""j&%B(a"�Fw���_=�g�����}��K�3����D#����_S�f��&��B�BWy����������#"Z���� v����o(�HEMb�[�Y1�ZU�k'd�2l�?k���v�i�cA �������
$|<��O#�L.�W1U���M���T���+��}�J��VS5�_��7�@��/���[��k1xyI!�x���G"�����w ""�5C(��(b=Ql����v��B�F!c!?n�u:��w�\���<�.�zD���� _4�sb����������_�]�z��8��3(�]_�1����fp���������)P�a��p[�}�o�����3����Wr�Y5��]~K�����b�9BM4%�M����`�>���!�7%"""""��{DD��
������:J�1\�VH��J������r�����	�i�D4?!�N�x�I���i@*<Z������}s�m�(�����w�����i���9S�*b��v�\B���.�m�#���f���`�a��*�*'�����LF�ag/��(�� �7n����T�Z�z^N��������"�6�LH��0�L���
��<�;y�~��)\;�������S�x}[�/�������������Pt����WJ	Y�f��<��
�5B~S��F
�������rU���.t5�M������\���,T�G%""""���{DD�Y(��@���!RJ<Wj�'n�u������1�������>���!;N4$"�P(����n�^��Bqf�or�
�vIWz�������7��qH�-�#�<���1,�/��AU�R	���]Q����SU�&~���o"�*#������~{����5��!�B�F�ng��\����"&�jHiT�K�
����%�V#EU��������q��i�i���/ ����;����~���������$���hP"������/!+n���Y����d��r��np�s
��o��7Qi���h3*�M����~�!@#�k�DDDDD�&0�GD��	��W�|d��Z
��+�Rsq�VCE�}pGX���(�q�e�>�B���6QK�0^��kn��m�\��3U,|5F����k1xy�������@!<Z���`_|V�/�0�GDD��	!1uDL�zU��B�B>c�0n�b-��p+^�Gv���H	�j
��� ��g ��B���Ug��Al�o��w���bf|�����_c���E
��(�Q�hz$
U�-#""""""����0�����/=	�<=�7+�W���]VZ/���������;@1B������>���ET��}V"""""Z�x��h�[�?gp�l��W-��W�6W��[Fqq��{����ADDK+��p:g�|�WJ`����]���`��%�|�;�l���l�hE���|���DP�����V���:#�u[R�R�����gl������s}��[�]��*��"�W�����.|�"Z���*��H�)�/������M�A�/�5�G�B����s�5���QKBPc:���v�=K�B|M�>�Q�o���t����%!Q�RX�{�����
������S���U����-	�/��V�]�'�����}<�/��"&�\C[t���e���}�&�B�R��U��\	W��X#l5#L�X�q����b(�G���@��V���b8���V"�Y���v"T�c�""�A����)��MI@��A����w&��{�q�����P�A���D�@����1�G�R9�2*Vi������5��*�/��iAU�H�h�Q��U�oz������ZH�D:""""""�i	M��CM����;^x����W��lwWv�,_�/:��m�[��F�of�O����!���'""""�5��:��V�tX����������V�2cY�bUi��o��=""�����l���������xaE�����I����;�T�K$Z��@���+�}K\cN�J�k�n3C}�D�K$��;���5�7&��|qk�T�o�B)_:0?F���� `���|���L�V��-���s]x�*��
��P�F��#C~�j����*�a#�Y�$"""""�5M�U(�
����3����fV�sf�&�-X#�����Ux�*��B#tuF����~���_,�ApA5"""""�cp��h-8t��5��j�z&��\�l�Xl��e�`�]�k�e�Z�����ex��;��0��ag<
MY�$LMR���J�6G���s^�+l;x��4�	��&�}�YU�Px���h)h!����]x���DP9���P��q_��J�2J�2��*���H���|!���������{���}T�*V	�|-!��hs�oV�/��_
0��w(""""""Z��
JD���>���������;��/�*+���3`0�$AJ WM�e�HS�������.�
�Ex/��>]�W�Ex������^����'������"H��I�`���{���)++�~�GfUeUeuWu=uu}^�TgUfef�LwU��+C	����}A<��{�_�~������
�����Waj��}�������C��5nZ8RJ(> ��r/���we�O<��'�?~��cE{@�}/�n{���R�f""��PJ��9x�\�vc��Mx"o��+9<b�������z��i6���R��Z��?�k���T�Z
���]Q��|����d���F�M��)Xy$��G�� Q�o��g��WGm��0������z�����V!�����9&�2&�#��������})KC�M���]���t3������>�LL��������
M(
'���&aE��0d(����8�kn<��g�_��tN�k�"�����w�b%���/q���!��t_������_}�N�;U|�Yko�����`<V���&�s�9^)M��ADtF�~��j�}�|~��D����9m������)��^�Q���o�
>T���R9����1�2���f�6)�G}��	�>�0*�hI�i�������a0�#""�UUP��������D��:���Q��Q�k &���]m��6��� �7�_q�B&��`D�"��#O>��o�6�s*�
 F�]��yN����>���t}i�_k�u���;�U�/���	E@�P��y�Q�!B��u������s�t�����V��?bE$�>�kz��3����uCe�7����~��7+�wr4o�y����R��x��k�CDDDD��������x������.��*n�����8��$j""ZN�����x��@p��1�Vrx2���,�BY+Z����K	���Q_�
�k�>�����A��1�N����
��>�o�'"":)EU���}Ru��|�6*{62!_���Qs�s����v�W����t���h��]�2�p����9������=^���@�aG�Ng����6�M;��5l4��h�h=8
������l�>�w�h��j�}��_+����E_S��,��#"""""������Z������3��m�}������5�I%�������&R�>5M�S��}�6����]PA���������X�f{���>���/=
5��e������{DDg������'��G������o?��������C(%n��uX�g��
Y|x%�M����B�|��?��=��/�U*@��}�)	�]����4����$?N� ""�P
�YV��p�R��4Q�mM���O�������v?������F<�o�B6o0�#��^��������~��B@72��������=n���4���8�K������h��F���������.�},U�:S��l"lM��B7���u�vB@#kA���(�
�P�U��}���n��uM�k��= <#��/�����v��5�����v����,BS��
,�~�_yae����>D��26�Y��r�:""""��3��h��������9V>��[�4p{�������V�� ""���������u����_�������,X�����F������E|��/9��qf{��8N�<���������/���9Q*!r%���G�^���j�=�=�]^s2�\����
v�TzFmG|�
V!�(�h�/�������L�\�]{/M����C�K@�4���o�|nb�_�����NL[S��poF�����Z�S��},EU{������
�mfZ�����
JF���=vJH�O��������.B��H�'��~�`������}�V�gtG���������u<����lL�������o|�����-8�{DD���_�����}\�������m��7�`�GDD=t\�uX�����>��S���<���P���h��-i</
�*�xJ_O������-;����r���/�,P�I�DDD-BXEV���'� ��Sw�i|�Q��6����k��W���(��t���-�J&�
�c|�g~�;�p�������c\��!�/ �/�}�0��!����u�}��������A�1���� �S�����>���_�~����P0���1!�;%%E@XQh������Dh{=��:�_�����L&�:
���w|`w��O�XZ����t���j^�0���������1�h�E6|<�o`���$��>�c��0�#"Zpw���������^�@L�|DDt6���Zo����
����gqm%�
���.9]���%M��	��=Q_�M��7)���V��lW _���kbZ_�d�Q�GDD�����3��3�z"���Ee��b�=N}21�����b�
P5��(�+�[��d�,�-�f��O>��/����|cj�����x��O������0sy������a��t��V��4��A`w��
&��<#�?GR�h�u4����i�L��L�4��o�l�iBQ81������h�E@�P�����"����������/�*�`���LH ���>�C��������O�}S�DF�����V����a���W��_�:����1�#"Z`RJ�������)���U��A�^��w�����|""���^����
'G~��)�V��J����Mms���M`#��"������Z����O\�r�����	}��b0�}DD�tL��y��#W�����*�u4j�y�A��8���p'������(�+�[(�f���rD��/�
���:j�?v~u
����L���D(JfYcKJ	���������	n�N����ZA�<
��-:)��
`��3���{&���VT>_BDDDDDt	M�Z�@-f��_zA;�����nw�W���F>4(��.����Wk"
�S���_|�����>������h��p��y�W���#�^]��y����h:�-�f�	�q&r�\���p��n_�Eo�w��"���#"":[��x��x����5'y�+k���.�M(��N7!��-[[��������5��^;�$|88��4�����}�0��IDD��2Y�����X	�6}T�l�wmT���+���'$��(?�&$	E����B�
�U�����O�P������7����&v\3������#[(N��4!t��n���x��R����T��_�����q(��`���5xM�����@32����i�=�_�4@U���DDDDDD�J�*�X1��WJ	�]�ZA_�}�)���t'���M�����%ot&��b���/O�Ky����&�]��~��{DDDD����`b����q�!�5l�:l|�g�GD�d�P��jo���oz#?^O�����Z�o;3���h9�{�a_"��$�����9��{{���4���b��b!���Wk"":{����G�X4�}<7@u/���{6���� !���?��x��Eq#���fA���-�����7~���w��?������~�W�/�qt*	!��FVie�����	�vW���5����Ln]v����6a��>����E~]A��z����0&"""""�SI���d4h��c��RB6�����F�%'��=���}��)$����`������a_�	�7+S����~�v���L�GDDDD��w-0U�����}��K��	���O����t"��Q�|\/�x�l��#?>������������)KGU���8`����jz�W��,<6������[V������E�����n�X;_�����T����Q��Q;hLd���@����Aw�����������z�u���[����x	���3|�+����|�������������h$��C�K������>\�1`�
����������L}]v����yhT�C������}�N��jF� �	! ,�����/C��N~�u��%b?����&fD:>|�vs9���C��-�DD,���4M8xS{>��[�K��V�U(�G%��	�0�>�^RJl7\�uX���s��;�5pm%��s&����4`e5Z�x^�U�Q�����d��mG��v�6!�\�3����Za�7BDDH�U�n����~��A49��k�z��'����C�C�M ���s��|F�Os���-�����q�3?����o��[o����=������'���O�4d�d�����������Lt�����&8�*�Zu�c	E�����B��pw��C�u�	���� ���gLF�DDDDDDS&5o@�����_�!B;1�/1���%"@���&���������
DDL���������8,��L�������>�(_�&":��0��
�uX��;���iB�r1�k�V2������k�����L�|=Q_�M��7)��p��%�
�S�Z��,�>""Z��`e3���(������Q�W���	��Jv������/�7P�����|�,����O>��>�<vo���?�&��x;?|M���'c����38�
���g�q���.�hJU�������>�C��s�������Nd����a�f��f�~�������w�i���a����J����P�	}�DDDDDD�Kh
�bj13����&�u�����~�����n���AJ���-�{DD���c�{��!�"qk@��^��{.\�\DDt�T=��x�b�=�T����Z)��E�oh��d���h�%%�4�i}iQ_�
�����W�r��������^,F����N!EU��x�9@J����(��������]���h�\��<�9=>�����2&r�y��x	����r������������_A�T��-�(�X2���w,)%���=��o`��#B�x]���Q�����g���A�`�UQ��\�Y't��
����+��t�8�����}��q��D���C�D�o�&"""Z$����h�}������������c���B������g�}v�s�� �����7��������������'���#���ek���@���U*�d�J��N����%�atE}��c�q`�*l�)���NE(�Y(�Y��L��h����g�O���`"�r���!�>Y�8�+�[0s~��%������MD�!��"-3��w,)%|��L�K���&����`��5xM��<�fd��/9��'���090U�ta"""""" ��\d4(
�z������
�?����Z����%�$�K���JDDD�P�-���-\�x�o�>�1��}������*�'�x[io|'"����!nTx�\G��M\�"p�h�Z)���_'h�	���r�|�� ������Jb�����&�u���h`������-�X�L�+�|(���wLDD�!�@~%��J�>�)%�j��U�����	�����w�xx'�`"=��#����l�DADD�%��nd�������3��� ����z�y��w���&�����Ru=}��������XP���B@X:K6��_��}A<�/Zw�������/����\6���;������|�3����_�����n����
�:2A���/�p�s�|�]��u�[����$\I�pm%���,tE���2�En�b�v�����E}�
��l���)�&��A������>����Pr����!�+��M�j
RJ85��8����u&3=�k���[������4CEq�j/�������������bi�c����70���o�C���|�9����C����V�>��jGD~=�'�����0""""":[�"��
�yz�g�K)�xs�1���"�A|�����h�0�#":�\��g�}o�����"D>0p��z=z����(�\�2�u�lI)q�n���:��'{c�����rx��o��h��-i\7
�*���}�u����b������M ��L�K���M��B�B�.�BJ�����g��[Ge�F��� �
�����U��)��o#�\�����<""ZN��#[��-�`��AG����i��j�?���"�<���m��mx����9�.|8�*�Zu�c	E���V����,Vr[Z�Y�3� """"":��0.���q8�s��]����h1�#":#���/���[�VG{q5�-CQB�������2
�~��~jWIDD��!����^���#?�P�)Z���CA��D'b��z��i6S�R�>v��8��Q|8��{�}����Bb=�e�GDD#���3`�<rq�lx�����E!_�6�0>�C��p�S(�@q�Bq�Bq=���	E�j""�Q)�
3������R��/�����K/�X��0�9���v��?�g`��@��Lc�a�f��f�>���P�������	��P�4!��FDDDDD�g<V�m��xaf�""""����p������K��K��W����f��}4`bG�O�~���K��K�,kR�JDDSr�zx�������h��pm%��Y�|3�te2��f���p���*qH����^aT���F��C��z��3 ""C&�c��6/\�Ge�����M����8|X��"�_���n���C~-�!�L)���e!3��.d�s��q���/
6z�������w�'e�����}<����z����/
v�AEQ��������L���D����|Oym�����N=�{DDg������/�_��5���|n�������*���&u�DD4a���So����5F�0"<�3����e
N�"�?!��-i?�I	���Q_����e�z����DK�H�Z�t}��KDD�05l\(b�B4��s[!�����zy�::J�h����;��@~5��z.�������
�DDD�B(Ji�Y`um�cI)��F�NO�������0&�].7�i�s���},-�.�KN�
���ADDDD���s9��poV�~.��"�s��������&���1[[[���������������7���m��O>���/���&��x�b��a5�7�d�+���,�u�Z@�P���h��\�T���}
� ���3����(�kM����\w/����%�ivG}��z�M�#"":�nhX?_���(����}��(��6p�A�}���
T���.�K&�9�-�-h������z���1�[Y�XRJ����#������w���f~�	�|8��4���=f`b�_W�j�$""""��(������?��y^||�� """�������� ���s?�s��G?�W^y�n���D.�������#�,'/�2�Mo���j�	�e���p���S�,4���ER��[��=}�b�{�jU�R��&&�U+�3�iDcs�hy� }��K��
E �TDD�M�U�n��U~������W=h@��(��������{7�@=W2�_q����S�DDDt4!4��f������^�����&�9�u�mN�;$�s�{.����RT�=���i����Z4����DDDDDC�^]C���h��pz�xn���M�'"""��������+W����+����o���w�����h6�T��*4���#�=""��PJ��;x�����;���'�&>���#&�tA��4
XY��4��	��=Q_�m?
�z��l�o���b<����_s�h""Zj��`��<V�� D���|�6�6�`!�z�A����{��l!�����F�&'��t���lAG�P<~�c�A���M����w����<% �����S���V�>�Pd�V4
p`���3�,�x
`�����f��L��G�����O��~ae���*E+_zz��%"""��a�GD�������(����?�CH)a�!���D�����x�l�z�F�F~��*�P���J9�4N�"�!��-�����J%=��V��~�&e�����{B_r�X�,�>"�%��
J9�6r���0��6P��Q�����@��9W��D�������3P�#��z�!�^�����a��c+x��2
��������@������0�S�����>�
t����z"���f���	�(������&K�����g��7����k�"�a��������DDDD�����B@U�xC��a���L������c���V����
�d��FF�����g�*O�h��2`s3ZzI	4�1_�M��U�p2��X�(��%���G}�xz_&��g"":[E��f��f��%�e��8����{��{���p�.�:d�z;�+��`�tN*!""�3IQTd�2Vn�c�0��tO�KF~���A����9�'e���'r<���L��BOL�kG~�������`���#"""��������|�����
l����������="�%�(wp����P����-�PJ��9x�����O�*.���J��1�$"��eEK<����@���U*Q�W�����d|��%�a��|�B4��Pt~�%�Y$��j��,.\^��v������n�=�;���4��������(27L-��,7r��
�|DDDD=�����5������f���������0������s��p�?���L�+��u����`&[���zCDDDDQ���_�_�!�><�q��mb�KOs���g��������m<����e"�*3�&"�����]��v�;���������,X?!��N9!�|>Z��l�����3��������u���hIc�������|!��GDDO�\�D�d��Sk�R�QsQ�#���
��'r.���{�����f�(�[(m�P\�`3�����&H=cB������u,)%���F���f�o�4��������o6�7����cK�
�&�v�<��%"""ZtjN��/^E��GP��p���X��"
/>����)^!��)FD���8�
�����?���="�iz��x����k
�'.�i���JO��P�]":+T5����������WK	�g��;��D�����\z�W(FQ��� "ZDBX��B���B������U�l4mo"��������_h������z�u��	���"""��@�0������|�g�_'�k�6�8�k6lx�P0e_����6��	����\4*���(Pt�f�������������/�����L������5��������%{u
��k����_{��*�w�����m��<V��x��7����������hj�-)E���'R�$����-� ��Yk���:v���aW���,����aS�B"�SN����hI���!_�����z�������M �����}��\.����N=!��3g`���������WGy�Fe��S���M��`����@���(��P���_�Ba�GDDDt&���lAG�0���F�><�����	nO�7(�����]"l66���W�:���]A���/���o!����Z]�kN�&""":	�\�8�+����~"���g?�(�Js�B""""�6�{DDKJU���"�z�v�{DD�c����x�l��#?��\-����SS�p�DDg�a����K�(��T���j5��7oRF�kU���+J��Z/3������X:6�l>�p�=��h"_�:��'���A��E(�Z(nX(�[(�f����JDDD��TM�������>Vqx�4@�F^{�_�4@_p�58��K!��$���?��?
0cB(�}�������
@���DDDDt�1�#"ZR�z�qi��g����!����[�5��9�'8�V���K9\��P��-�x�2`s3ZzI	4���*qH�_O\�r�����Q_��3 "�S�0ul\(a�B���^�Ge�n/��d����Dy���n�	E���Eq=��,��8KDDDD'�(*2V+7��d�k:}�����{&�W�S�����2D���i�Q�`B�0��	������%�?��P~�!�^��������-���m���i�3�""���%��5��a{Mo���B��B�VrX���b"����h������mwG}��z�������A��1����X��N����"�y�3�-b��"���N��[G���D�
�C��}\ �k0��|��(��t��������C(JfY�c}�cI)�7�=�����u������ ��w���lOY������3f�%���i�=��afa�A`��5#����� """"""""�,�{DDKH�
��[&�=���=":����)BN1��y�.��v�F3��{����+9\)Z���tADt�(
��G����A������3���g~��\����4�������h�����X;W��� �T(�����Q;hL���4P;h���=@�d��a����� """��#��n��M�����%�����S��&��Q�c�iG���P0^|B��r�����������=A�1A��}�Y�? ����������-%E���3�#�����~�����]��w�G���������M��S�,V��h'��N����:n��
�8�5pm%��s&!��""�#U�"�b1}���*P�vO�k�;�l�w������[�h:_�'�+��Qa|ND4M��b��<V�� Dm���^�=���p2XR/;����a4�*f��/������DDDD�\���t#��2��|����L�;�}��~��=����KO@�a��q`�d��W�s��	���/����cK���	z�B�'4���F��������������_Y'"ZB�z4�����a�GD������k�q�8�I�~��������e��Z�������!~Xm���:��?W��Y\+��2f<HDDB����hI���1_r�=%o�������mB�|�z��B���}��hbTUAi3��f!j�*{uTvmT�m��dB>���]ib��h�E6otB�
�,�!""""�����P,2����������^Bq��D�|���}�:���h�sh��� �o6���.�����V��V�>����`J�����o�U32���������f���R�;��������"q�����j����������
Y|z�S=zJP��q���w*6�L�(�*��r�\��9�\DD�dX_��^RF�^���U��$?��|�����Vp���t�|��b0�������J�Y�@�����n4���g#�����Qs�����u�X:��J�D����DDDDD��j�������
����i���_;�k��BA�����}��vC�� �S���U�>�J�g�N�KN
�B��]DDDDDDDDGa�GD�d��P�;��O�n�(Og33�*"���oz�Ow�`�����j�v?yak=�����p��a����������)�DDtB���-������R��V�N&�K�r�������5�/��S��F%��j��,.<�~cW�('B>�
&r�����]���?�
SC1��J���������������X9d�����a��$"�8��	�#�&�!'3Q|�I�i�����L�9D��;	��v6�4�(���DDDDDDDDt�0�#"Z������**��P��E��6.��{5gBS�&*":��������&����pg?���2:�0��Jo��(��O1����Vr(������H���e�\��0l�?�k��k��MO�DK�����E _��}���8""jB W2�+�x��uH)��6Q�#���
�9�)���c�N�w��O��(�G!_q��U���uBQ�8��XRJ��f���v�M�sv�4�N�����4|����2/'3YQ��=A_"0�������2$""""""���� &":�vw_��[����w����m9���{��xi�WGDtrN�?���X�������=\��x���w���t
WWrx����(�>""�Q ����)����;a_2��V���4p]`o7Z��f'�+�L�����~DD�E�h�*�8����p�n;�+���6&�y�{�*��Wh���Z��-�J&C>"""""H�4��&�:�����=�k�_Z����n�����a0������t�5�|��4#��������L�����3
P���aDDDDDDDtr|���yx�������n���w���������i|��?���������2�`:���!���(<���Z)�G-N� "���Q�V,�o�}�V*���}�u�����8���A�v+M����A�l>�l>��'����Ee7���W�S�&r.�
��]��v�j

�J�q������w+"""""�<!t#���*��}<��:�_+�k�N�����|��$�n���]>�X���O�8��wj`g���|�������h�0�#":c���x��_F����.6a�|����	���=��{�+��?4�K%":����5�}Cx�h�j)���������4`e5Z��n����S�f#�-���&��Ga_�'�+���o�!�%eZ����h6�8��Q���Q������p����@Q
kQ�W���_�BQY����:4��X�X���u=�[�l�v�uP��4��'����;
<
�C�Z�X��3�/3
P3�a�DDDDDDD���.&":C�����������#���'n��[�����?���?���x��N���k�������t!��y��h���-�������Z�&����D�y�2��Z������	��Q_��}f�a-�LV��c%l>�!�m����(�F���d���u����V�(nD1_a�����1""""":[TMC6_@6_�Xa�Q����	��LtN��j.�0����pj���%%��z������Y�3&#@""""""�)a�GDtFx�^{�������L�S����u������_��?���&l��~���3��=��9^��\���WDDD�0�h����.%�htG}��z�
�����W�r���������	~��l���h�����G�X��� 
�������:9�e{���_���n���Ca-MW'r."""""��@QU��<�\~�c�0��8�������:��@�	|��M�!��:�����3�����wB�i��z��&?��������������;�Mw���$�{�2,E �@3���x?�1Mwo���x�#���.���D�����<3���RWK�:|&""�(!����s�����N�W���W���7��>pp-i�{Z_�gr����z���H7T��/`�|4��T����Q��Q;lL��n)��~��������(�!_q��f0�#"""""��(�X2�5������N����i���l�v�?L�+O�-:)�����AOF�G�����E���:v~�.����8PQ��=-6�������};;_�����m�e4�k��+�i������a�{��\�v������{8�����xi��-)%|)H	?�$�����*;�[�~�~�6�I
�*�~��&4�������BQ�|>Z��l�(��T��|�a�=�7���u���hIc�����Q_>M�#"ZP��bu+���h�C������F���
�p2v��A������b��J
���<%"""""�7���ff����%�������R��x}��a�O��\r����40�,��{�����L'�kO�K���]����*�g%"""""�9�o�DDg��[��z��1T
���sk)
.�.�P�%�8��X��u���<��9�=�3D�#9��� ���t�������>fB����F@e�GDDtz�j����}?����}���3��q������V(�|2�����Q�HD� TM��f+�Q�!j�
�[!���0��/�v�	�����Q���(nD��J��,'�-2!t#�� 7n�����/-�K���`b=�|j2��w���&�����Ru�;�K��z'v���5��)�p�-�Z�m���u_�q���������4��C�9X����������vx�m�jo#�����MD�d+���2���!���z�0��57����{DDDI����hI���!_�����z������mBD�^2�k�Q���e��ST����9@J�(��!����'r�F�E��b����(�[��a�����g���P�n�dh�M/�*��>V���q_�T@�����4���m
�ns����WF�R�X��u�}iA`�~3;x_���|��������b�GD���w��u�������R���v�����$�v�/0������|��-�dH������H��������;�4����%�Q���GK/)�f3=��T�I~�?�kN�����^�vE�
��e�GD����,�,���w�z�Ae�F%���{�D���]8un���R��-������z����2jj�66�t{��o�C~��U���+�s�R""""""jQ5
�|�|a�c�AG)S�z��F��}=�1������S���U�>�P�!"?����}��3��x.�������:�-�J�����?������[j�������S;��T�?�c����Dbb\zL�	��}��1]br��6������iF��f�v)�F�;��$�kU ������!P.GKM���E _���"����z��z!�_�"����O�CJ	��lG|��:��dB>�����2�����3�V��[�23}���v�n���g�'�%��u�w������.<������JDDDDDD����0sy����"���D�Z����������@�=OJc�a�f��f�>���P��&�'�����i]_{CA��P�	|�D�"�D���A�*��3����h)0�#"Z`RJT�?J����E{mj��=.��M�a���R��@��p���h�\�������#��M4KM|��@V�"���(&L5}]|����h�XV�l�����mw��J���z�t�������hIc����=��t�&&��B W4�+�8����pj.�q�W���:����5}���`�n�*�q�W���*N'��\���yG��66+�����n�e """"""����e!cY��x��a�m�L�����N ���� �<��w:�/]pR��?��4
�'��XY���������*�:�k"Z4o���W����`��h��H���-l=u�._��^���K��P""""��bKD������>���hc>�:����+�
���C�~AP��M8��	{����?�������&����|��&E��W���@!7!���5�}���>���� ��0�8�S��/�m�&2�uDDDg���|��O�Q�W�tO�k���yc��\����4��=�/�
��7c�t	!�-d�-dp��*��h���q��g�i{9����_���*@��,7,�s��Le���^v����;>��SAe�����\��XDDDDDDDi��D���VG�J�R��/� ������2�v�������@��A0�ow)yN��@�`�ci�L�Y}A`2��d-����L6���,T�o{���������w��`�>M���o���o��o���W?�O����S�x~�WJDDDD���`��XFo:j�?/��T���^B��1d�?A�S=�Y�L��L���Dw����:�&�����&E&�9�O�t=�!Dg_���D����A������j�q�����V�bo�}]���7QEy�s���(�3������/y����S�(t+���~��\w��^� �-�o�r@��=�����G�#�	!`��9[O��
�D���M����q�S��N
��
���x*_��:��s����r�N��\���u��%�{DDDDDDt�	!�e2������u,)%����z��NLo2���f~�	�|8��4��"��i�G���Z�t}�o�(�Q��k_�
\�#?����w��p����/�
���!�Ba�GD��%z��^��`O#�+�<��	�����'�
�:���w�q����.����.���[������`.�/�-�u�+�k�t=q��B�Y�[3
�B����q���HD~q�������,L����P��-MVW�%������h�i`��e{��Q�WH	���(����R"Z8�����K�|� 
�*{q��k��6'r�0q����u�(��,J�9�-���P�|����?�=�h���B��'������n�%!"""""":����a�*��>^�{�S���hw��h�u:��;�� �����=��h���Q5-��gf�&�=
0���_�
>����z�������9���+���7_�����c����\�
_�%"Z`��Gh~�yy&������AUs=��
��.��zc��0����&����IG"��[�D�d$�wM���H�3}N}�>�!��Iq�P<�"���B�)��Z\������?]0���h�_�2�#"":eX_��^R�fw�W��*P�F_}���v������+����P���/������q����'V{n��������'3�4et�] �����z�
�5��|��3�?�]����o���<6���e��#[�'2�*�����{��M�mx��<���GP���V�>�P�v�wd�O�k���8��i������0\0o����G�W8��D�W;��o��?�����x����h�1�#"Z`B<(����s��������qA��x���.`HG���Q����:��z���h.9���;6���U�d�@��`��^��9�s��']x'�����e��l���8d�GDD4B�-�������	}��z�
��`vx�r���4�r9|�q`�lU���m`k+
�2��^/-,���~������|/@u�F9�j�
`O�P���@u����@�d�����_�G��S���*���z"""""""LQU��<�|~�c�a�qR��D�iA`rr��D��Xd�����k��!�l��}z����3&��L�{�t�j�������Z�z
����!��?�g������h>�-�}��:ox���o��gxFZd!��V$'zn�M�KDr�7�������M��h-Z���u��?`��v�-����I�?;�&^-���&Tyij�w ��T���<V�
4���A3t��!����4��/pQF��A]���/�%���@�5P�2�#""�&!����s��������D�W����x��C-�}���o�Qg�at��{��
������hh����V���-�CT�����g�z��'Q��C8��'�����p���������P+����X2������7�k�N���A)O��-8)C4�:�v}��	�4a��	Y�fg�_r`k�_kr`�o+4�(|-������L��t��}|�+��/���?����1�#"Z`RJ
�lC���t=�������'����z'���=o�]P���5�
����!\b=5�K���%B:!���Qt����{�w���@���9$l�w/n�U��Sj�����|N�5�������v�,m������?M��S���f���V�
��CDD46E��hIQ�W�tO�k���l�w��v�%�iFA_~@����DQ5+����H��b��4��o���Aap������W����/��������N�(0�hZ������f�����0
0�����TH��+1��L�d���x�_�}������
Z���r���/����|c�����7p�3?��>��T�CDDDD��w�-07a(��/�� !�?��{�\w\���:�.q��ZK���TQ���L�kEui��"4hB���kb�d����@9u��i�nl�\�1l7���^���ed&v|�&|�e@�8�y,5�!ta@W�Q��R��~���f�H��8��	��%�|��v���3��=�T3
��NU���8�� �������l&K�q������V(&B�d���G�#-%UUP�����>��0��6P��Q�����@��O��A��3|����������B=cB������u,)%���F�i���|B��r��M��&��cK�
�&���GLT5}������k&�����6�="""��w�-��:���:��A�������������1�����a�ip�L��1)�����s�O�ypR���7h�K��'a��^���y>=�1{E��]���hS������^oO����51�:�r���	���7��z����lb�_�)�������������u���J���/�i�������M�(�K�|���B������(�5�5�d(Q/;(��B>�w:���wc�n�AQ�*�(��@Q��V�h]��u����+���?u���Z��<E�0��bi������G~��
�5p������wH���/����cK���T?3�[���������i����ZPu}��������0����[o`��Ml\�4�����]�DD�O�~��7���>�3��k�\o\�����n�B�h��q�[��M�SS����ri!]k�\�98]�F���4.���F�-HqO�P��*�<�1�>���p�s�p�zjR�<��#���3�/���5�/v������	=�u�>�g�_�2�#""�a����KJ����*�V���Z5��7oRv�C����(=Q_�^���,�>�3L(��,��Y\��)%�J�=��(����NUC	�2��>�k}`g=���00}{w(�Q9."L�>/EDDDDDD�$TMG��#[(�}�0�_�4�D�����Ml�k:��(�}�
�je�c)����G~w�~kW>���M|������E��������������Ls�!��q];���H���.}����ZQ���8]����>�{��� \�#oB
?En
}�P� P��T:o���<^X��4.{.4E�����(�kFS���/9�/=t��S2!gF|��<�G��8����_��`�=�OS��}3DDD���iF��f�v)�F��9b��wa>� @NJ���!7a����F�z���~��l����J�\�D�d��Sk�R�Qsq�S��<������@�������o�H0�����������B>OGDDDDDD�XU�������>V���i�v�v����wb_���t���A�^�S���R������/�����N����T`�s�T���9�k:������6]NIL������z#���F�8]�h2L5�/l�<���?�F�>'�{��{�%�!�!�:oz�hB�}H��P�	)��H�QL|a��a���~?�Q'���?�;A_W���M�KN\�����Pj#���_F�vM������,��h�:��-���a{�K/����%��U:����^?oZ�}�� Z�����Pt��N����
������ia �/""�V���!`r=
�#���0-�~|b_>gIDDDDDD4��"c���rcK�!�f66�x�_{�u�d�A�J9�]���������-�{DDLS4�����{����F��?=lrJ����.���B�Vh���N%$��[76��s������h�^L�2�������=�s��a����~�F�d��h����?gp�X_��/�>���oj<���
��8����_r`t��	�DD�h���%MD�^��������U��g{���.��-iL3
���>U������?kSD�A(�@����	��"�d8 "����cu/���Jt
��������������Z0��X�XRJ��f��?�i����M����}�`>�y�%N��i��Z��""""�="��6vl���ul�?��Yh�60�kGs�.GDS�nl���xe�q��V��x�r�^X�<'���I��@�p��_��`g�_3p���������C��5�/9��;�&&���������tR�(t+���~w����8���A'Z����u�|��b�������N�h���'���I	�@��Mt#�d�wl��=%*�/�%""""""�>\G7M������X��R"��c&��h6���>
x���`���G��,�=��BDDD�P�-0!~�T��5Of�������O�l<�{z��""��f�������kx��m�o����3�����q�zj�WH��

9�d�_k�������S��a<�/�e������H�k��}�)~�b"�f���S����i��-i\7=���_�S��B�-������&v�}��b�r�>D4uB�JY�wG�y{�O|��P"$�����z�Q����������{�%���%:c�P�D���B��
�;�`|����=	�=�o{�\DDDDDDDg��a@3X������`���fz�4@�i��O���6|���!M��}	DDDD4"�{DD��u���<�yl����<��.�O�<DD'���4������7����y��pe���!2����#������5cs�WL��

���5r��������N��<�XO������51�/����f<�/-d�GDD3c��z���h6���J"��U��~�&e��p�����|E G}�"`���&(�j�4�[��ces���NB���O�!`+
�q(�����	F���c
8�IH	��'a�F��h��HL.��
*�}{�w[p� �R��C�K@�4���o~n����4�N��
]������g����C79n����h�0�#"Zp�s�p��������,sj�y�vp��.�����AD4	k�&>y�r_���!)���~���O���R�
K��Rs#=���q_�z������e���q��&��(d�GDD%D��&���R�Fz�W��0��
C�\��4���
��2��^/���x�������|���GUP ���&��L
LF��(0H�~\$�z����4���D'a������E*���
��DT��Wr|'M��i����#?�����o���kS��t�<u��o- �{DDn���gWM��;7�d�J���S�po�W19����J�t�&��q�?�=�o����m
����@���xr_&��g*�S��1`:�?"":	!����s�����(��%���k�������A��1��Q_���l�����M�-T������n!W���6B�h�|���N<���_08D$x�������tR2�B����D��		@������	�G�����PI�oo���]�|^����������|e�����Wfv.""""��{DDg�s�O�/�_�o�����KQ����0�o�?�/l���J?=����T�"���+��'���8�K�/{���h���I�?��C�x�_o�����o�#"�����%MDS��1_r��~�3��v�%�i�A_J�W(S�@"������3	�.<�>�sP?������=g;*)e�4@��6a"����wZ��������$D��7����]`W4����S��D����s
DDDDDD���^��������~��3;M�="�3�	�i|�x�����>���_�oLd�^9�o�v���o�c���h=5��%""�i/�kFq_O���{�_'tesJ���4~�����6��������R)Z������Zg��;��D����s����P� ��G�3f�\���[��96+bu�0����&���
@0���RJH	��4��H�����	F�b�w��0��SJ ����@'�v���v{�g{2L{|����������(�y�.\��^�������g�q����CDDDD��p����xa�����K|q�O�/v~/7��e��x��^������Of������5��9Cv&�������0t����! �"���/��!|���+!�"���i��j��q����RjU���y���A��h����&D4��+����B�r�>D����Ce����?�ajx���&~\�Q!�?����*ez�'���8lo�	���{�Mk���NBJ ����F��h��HL.��
*�}{�w[p� �"������� �{�g~n�� """��`�GDtF�j_��y|u����c�������>[��T��8�5]|�j�Po�����U]��~������"S�2v�������t�����pB�}�����|�l�jO�3�lb�_�v24��GDt��-�������5��V�&�����k������}q�W,�B��d�G��nh��c��o���M.��t�~�"t�/��AM���|B)egR`2LF�A���"��cu�''��A:�0��`��pTxT$(��PID��hp@$�$����|���������O>��/����|cj�����x��O��DDDD4]|����Y76��s�����-��#o�{��|	��>n�x��q��`)��+v�������5�����3���b��R�����c����wEDDDg�8��6���V�7x�_�,4������&���u��,�������"��L�Ly@J��H����V��OA�r�����i}�b��Lf��K�#W4���\�[r{"��3�sEsWGD�"��&��s� ��Q`"�����<V��8}�NJ�A(�0��PDQ�:\$��.!a����P��""""�S�s_��y�u��'~���>��_��q����hv��1��&~����W���[�b�b�����9|�V�}��@��K@.�\���s[��2����kxa����GDDD��"�j��EI_�q]�_����8]`��eM�k�	��@DD@���e�\��0l;�z��j����o�|88��4�������a�>�'
�P�h��/=��_���������XO~�'��@BP��;O���o`;�B�ju|�{�B@����4��0��qz����<W�NtR2�w��h�`2*<.�
�'"��6>�CDDDD�.[(�g��������k;����g���-'vL""""�=�bKDt�j���k�������p[k?���J�T����|=�|�1<W�4.ZO���������+������)~i ��1����������NE��h����� ��������=�KN����n��1�8������(�S�<:����p�G���*���Ceo����-\xf�[�)^!�d!��P���R����g�������YQJ�	�z���S#�!#�(T;�a�>
�q@�)$H���v����~���z|;1M0-*<�X�}������i��%��_�'���'2y/������_���K�_��="�3�	�i<a=�}�!n���A�>6�!dDj�63��H�<.��b����U�.��oRJ�a��9��fk=�z�[����c�+�Q+�3�,2j�z'�3a��uC�@��(AD��T(��%���G}�*P��)��'Z<H���uO�k}-�\>
�F�v���s�+v�TP;l�v`#�;?+��@~�B~%������9^1��BDn���g�/e"����#@�	��=:����#���%�y��#����q�`g����w_��l��]p� ����x	���3|�+����|�������������������{DDK`����� �\.�k�� $ >����4��sDDDDtbB�(&SG{��Q��Q����w�#=n`�O�K�M�������u���J%
�*�}�7���^�����mBD	{��b<���E���M�>�LY.����� ��g^�s{DDg��&�xp>	����H09)0
	�2�Hv;S�Et"2�>0�_Do�������=�E+�>�J�`��*�
��b<HDDD4_�B_�{�>�����6������}���x�g~O}��)^!��="�%#��*]�������'��+���uH5D�����P2`��c���w�_�v+�k�f�GD4���GK/)�f�?�KN���_s�u��	����j�����|<��PL�a�~V�~v���DDD� ��� �>��������(�`�����A����4	MPk�`���~�c��~��#=^tOL���E�'������v�*}���+�5��T"""ZrO}�y<����{�&���7q��;����h���>+�������Wp��?�����w�DDDD45���������!%�5��]�\F�X<�q�	��~q��$��u�8a.k�7*C�t&��D]��	��d�GD4!���4�����R�FbJ_O�W�a8���@�-i4-1��5�/1�/����M�PTE@���;�����'����:�`�������}���NtR"��9��/)L�]��H���������t��x	����r������������_A�T����1�#""""""Zb�L�s��f�>������8�s�&��9�����D�g��q �?"�!�������m�A_O�W��:N����%�a$����}���-!TU���AJ	)MlG�=�_J$8x����LL&�����tra�w���R����:��h���(0m�����	�G�}�RQ��n�����������="""""""��AFm����t��D������/����s|��<t����0D��L�S���2�#���(@>-x�{DS��1_2����_r*�vw�%M6�������O����������B�2����L�}����P&B��}����m':	J���G %�����0v�=�S�5x_N$"""""""�7�{DDDDtvI	
>H��cR��B�'��Q_2�k���p��?���7Q9�3��C�������������@�-i|�?��V�J�U�����hD����s���/�Z,�|8��B@�D<|p>����H09)0
	�2�Hv;S�Et"�5}0��]F���������w�`g��}���x����������="""":[j���k@��w��\����/�J�������ss�P""E2�+`@<�"
��(����9a#�������p}wb�_{�_{=�f�&��*8����MVW�%��v�}������;7���h����&D4��=��M�+��-+������h
�������]G'��G���Jx��r�@��d������tRa(�P"� ��5�xZ`+�����D<m0-�i�Q��}�� �k{|l!����������f���
�����o���}�M���h��u`�p�E`��/���f)
����v���3�/��Z��)�0����o8�0��}�S��'�u����h���-����������Z������:[��{��U5�ZS�ZS����4�M�����������fL(�"�j��F]�T���?h�~��_B�Xl��2v�?�v"��}��'���������$�D4s�����#D���0e�������X�>HDDDDDD�l�-)����{���p���_v^���7�WoF���|	0r��:""ZP��������_;LN�K���y�������	��8������)q����N!���4�����R�F��R���j@x
���\��4��=�/�
@&3��]D{{��w��Px�_t��&�;�������3�ZJ$JDDDDg��*�9>�!����&�F�������+-"LnO��%n:�0��[���	������q���bb�P���J�m"""":��-��6��P���]|1��7��x(]��G�J��/��hD�����h����>�����2�$"��!��b���@�7�kO����6�)���`��<�����)f|;�2�/�����XV� ���0l;�R���j3��T�DK�H}�_����zO�[��W�l�o��7Y�u��w��������p���^+-!�e����C�PFS�R#�8LD���	����Qb+D$:	J�D���"���Qa���0m��$��v��\�x���D��`�N��Cx������!�r������J��9^)M�="��l�:p��D�X��{��a���:�r	��"�qu�JDt������������������x���fn����q�O�k��`+\����x#����������P|����LQ�|>Z�h�� ���d���l{����u���hI����|�"P,������q�W��qc��n���>p����D�������������w)���`"���D�2�����i�a��D'"[����P�u<@BB��?���?*�ko�[?n�x{k2�`@HD���]��{��
~6�%��u�w������.<�������������� "":��:��W���F��M������+_������h|n=��7�h��o��
����?���h!$��<F
���)~���/��z���`��?_z��8��L�K�G`r�_'d�GD��@�-i|�;��T�Z���5����A�hy� }{.�?��~�|8.��=���`��;��w�{��/|X_���Q���1���K)!%�����/��D�DD8J$���K���!�$�[���m�v������>Ol�'�{#@��6M�>V2��[0 $:C<���������^W����������x����|������,�OuDDgM�~�4G�����k����'���SDt��������Y��*��/N��DDD�@���y����~�uM�k����h�_�'�l�p1o���
x�?Nzg������ML�K���������hD���FK���Z������i���e{���D�v�W�������sZ��_����&�zt�/��=""""�3H�J����>�D��H0�;�
�
{����s���D'!%�@u��W���	&���">^g��cq� �$������p��^��SAe�����\�������=DDgI�>�����&P5+�w�9�������O6Qt����6�N�<DDDHSt�O�u�����&�%�F|������x���i���T��O��>5�����h0��b���K�(.kE|�Q_�
�`B����������}���bkj_�����>��&�Mz�a���F��M��*
NS��}*Z�� ���"�!`g_�9V������>H'�k@8�k	������q���b""d<H��^v��Wn��&��c����o��G>s�����;s���
�M��T���7��}�����d�MDt7�1��|���i�M��;Q�������_r�_z����d�����TO�uO���][�4E��7CD��Qf���f�v)�F#�R��Z
��F�� ��hI�i����Q_�d2���W�(��7
vx�[����t�ODDDDD4g����2�p����2�����`"
��w�H0L>>�[!"�I�P"%�y~���p�`2*���	����?u��!���F��>������Z|/�[r�)���MDDD�����Y��W�	y����|x��s|"�a������9�����8q���h�:�_~�����f�hO�kO���������_
��6R��
��e�,2�	�o�_|_"��-!���s)�S�!P�w�|�a�i����A��1�D�����C��w�p����;��w���O<1��-1������q��Q�`"���D�2�����i�a��D'"[���^�q���H�?��
S�M������by���p��T�������q�G�������h���������{����s�q��2��!���w[���o}�����g]��W����l�IDDDq����L�4�)~�����-���z+��O�kG�)~%����]�4���
Dg��t�6<��=�x�+���*P��=�KN����n���f���b�5~��������=�{DDDDDDg�qD���ghI)��w;a_W�J�@�V�������W>��	��)������P�D��'"�����	���`0�����r\D�X�����oW�{wJ���S���*���z""""��{DDg��o��<�d�G�'%������w[����l�m]ZO��z{�kHn����v�u%���b���et���o�(:�j�WE�������%�'�{�P�g����h.4E���G����#�v�����~� ��1����Q�?�]S�ZS������>_������s���?M�|c�"RU�T��4���U*Q�W��k6g{��4���A��\0M`oo6�s�>������|DDDDDD�����(���/�E�}{�B�bqb�!e'{'�D��H�3�ppp�=�w��9Wk_������O#=�!L���a�{�3��5���?���l���wc����b�GD��j����������|�s�9�i���F�$6r�uLHu���"��xk�m}�<��!���u�Y����Pt'��"�����8b�fDDD4Uh�i'�:S���_<�/pR&6�-[��vP���7����\���j�v+�kM�3�)��D��������4`u5Z��n�W�v��N����z���������'���
@��7s���i!`;<&�K�
����86�fA'�k��"B1 �k�}J&��@�;���"���'��zA����g���Ce�F�� W4gr>""""��{DD�n������?�=��F�HvL�ud�5���c��IM$���D45�h���u�=SNL�[��8U���(�

���5r��������N�k�N;��;���t:2�;���|J��E�_65d�Gt���-���&�
���U f�������E�>�E�����x���O���"~�"z�W�
:o��a����������jMT����-��/�`|����}@x�����>H'$C� �|���vB 5�]���{�����-�{DD����l����h!"��C�S���N��*x�����Q�9�FDD4i�Pa�9Xjn��u���)~��������_x��O�b>5�����~�`�����hv�L3Z6��.%�h�A_J�W���>a|l�����*&KQ�&C�#����	�����p��k��$�������� UP����LN
<.���4�v������#�VH��/�IH����9�W��1����0�#"ZdR�{��
""�%�
���e��O��x���u-:'�)3N���'�
�����w�����F#�Gz\+�kM����S�������XV��;��=�z�;�K~����y���b��'%����)��(S�N[������"��B@�"��U}>� ������'��	"�d`���,�~�N�~�����-�{DD�,h>?I�����
g�������6���M�@�F�7�s*Z,8p��q���[���7/���BEV�!;V�O�q��\g�7^��}q��u;�������D'�(@�-x�{D�^o�W��*`���s����F�G��GL[<6b����=v�#�E"""""�IBD�V)*�9^����`8x��}�b�$�&�����B���_0����"�y_������vP�^b[�~��@��	�	%e��5�m�kO]O��{���M��/�?��'�/�x���?M�< ��������v����z|[.����Q�G��P�8Mp�)��*HDDC/�kFq_O���5����a��R
j��\?gM"���D}��_<�O�2�#���R����N�wp��������F�������}����q��(����2m���A!%d�{'""""":�P���8�	���|��21mp������|,�Y����DDDD4:�{DD�L���g��X�'�J�7���C�����m�c��cGl����}Y������*>>�po�`�C�?n��������0��/^�% ;SgE�����pp�X��>N$"ZQ�g!�Z�>x�J���������Ed�FO�������9����8i�' �"���d����:4
X]���/����\��,Z,��x= ��f�hQM�=�-*j��)������8�Q���EDDDDD&��P���z���D��n��l�C��`����-l����wD"""�E�p��h��@�~c��49�wB�4��<�l� ,-e[Z���6��2�O������_����AQ�E3�s�^R�O������p�k���T�� �0�����&���Am���_�""��(B*�������~G�N�X��OB�	m8�
���Q��|j���z���)&%����6!��
������T�}���a�z���Pq_�.�M�n7��� 
A:~,�cC�A���`r
��`0�\GNt<�������������PTE@��>d�k�`p\$(!�i����[�{~K�(?�����h�0�#"ZdB�Gg;}j�2������GD��?�\oN�\+OF�;��B$U�
�c	�#b��9M0������{��>�@(C�C��]�S��h|S����a�+�kE���E�2�����q���o�������1��e�G�e����{O=
|�����8i���`�q��1�`Z@8�5.�x^"�aI	���b>F�z�=mq@�x���t�c�6�E""""����>8��)�k(���r]ir+Y>�MDDD���-����
�����\DDi.��zs�����q���
"3��IMN`�`��rI�0�ld�h����o�i��������
�@;x�J�L�TA"��R�S��T�(��C?�+��S��+���L&�uO��
��\\~x�{3<����kB�-�f�`��p��xp`�8L�8�:/��Z��2���M@<2P<a0x�d�a�{�����`�HDDDD$�j�4���dgv.""""��{DD������_������i�*��q`�����������Z#aFOV��;�g���S�����h�B?Z���
�>��e�}��	%}�_���)��LL;�PF��������'�z�������z���Z�?:��u��y`����u�<��>���p-(-���}S�����x��F9/��Zf0Z3mq�`��hq��N`�#� """Z8��p�����8�s��0�#"Zt�s��%�������dt>"�y�������N���Q�r�K?.�ABT#Zf�5Up�X��)�c��qGx�;-.�-����h�X0%j���`�~���ODt&$��QH)���v�����8��]o-r�>8�+�Q{���E&1��o�_"4����}�_f�=�����h�-J�YF
G��8(J<.b:P����DD�Z�h� �()��p�~����/��������N^%��Z�����P�h��n��gO�\�u��9����1�#":.��zs�����AD4��������O{�	���Ef�u|Jd�9~w��JN�f��|�T�A��	��3��s���Cg5Jt�����2� ��C�d�h?C�.[���}Wp8���
��n3�;��x�|�qcz���p����������h1=��������!��?�1��f<��
Nt<f��Pad���-
IH�����Tsr��z����M=L�
�=�0�]�1�$-�G/��$�������ADDDD��p���,��
l}�ymz�8���<DD���oV�������w~YY��
����*�:�����)M�J����
@�O6*L��WZ���������/L���(�s����>D4q���/t��c'�1�^{�_+�KL�k�'@S�2�;�^�K����=���}���g&\"�a�0Z2&����k�>
�����J����x�������~�5�8m��"�T���etT<8�������c1m���j�����@��"�mk�
��P��������X�[�����������Y��/!��W���C����&~\"���>h��^4���n�k�/�c���q����C�~�'��,�����7L�[��=��S�h�);���&�1M��~���2���G�# �`V����*x�4����)��l���lJ
-��2����_2�sS��n�0��5���d`*&2q����N�(&��Y0M�_D�{�����
���_��ODD��I�����S���L[:���r�~6%�11Z<"<"���8J0x��3mq�5�F�DDt�<��s�<��u'�w�a(x���&~\""""��{DDgDSd���_��������9�Ef�u|Jd�|��N�w�uOpE�5
�Wq��.6��CkW��w����d�y�-!�I�dgsN��"x�&�
T�PDC�,Y����S�9�P������'��&����s��5��?���O������%���	7l(�������v�6��+��O5���Q�k�����	���o�/B�O�����F���%�y`�h1%\:q�����1���HD4�e��G9���`p������4mq��1Z$�3N}\�?���W��W=\�zx	|�7���OrDDg��oV�������w~YY?�A�h����/P	����U<�LiWJDtre��^5}����$v�'Qv���6V��;]1���-([�@�����s�U=TlE�?2��	�2�>�^����_n�~���P,��o�b��i��ML�{�s��r�a4QpfS�|=���S���CA�o&!ZBdDe��[����'h$"?�/l���f� �r��������'�%�������_�4��;�
;����8������7��{��+W�h����~���
S��U-;F�������Pp�hq��������"
+�g��������C�0���M;z�������C���������+�\mqxk��p��_6�&����_^����<�%"""�y���������&��9�����Y���5�����O|�������+�7���s�����SD4Wwv�c���x��I	
���>��"�:����I/���tq�4����	�LL�
�K61ii�~����	&C���&x�)�K������8a������_3t��K��&\�������L��'����/-4�P���L�+�;�����5q�����o������{�^}����R��^��C|~��M�������,{�8h���`��v�V��_{�$���G`e2���P�S����-����h����-*���ZmW5�����xD$x���A����L[<*�d�Hg��[����_��w��������:�!7;x�r���;n�\~x��I\1��="�3��{���\��w����U\q��������U.��G��=�z�{D�����Rv���.�r_b����h�������F����!���c����&/�����=�k���}�u_���'��h�I��� g��kP�h�^�H���_S�G����<��-��A��1�Q1���-	n���P��&�
���X��>N$Y2�+�4������B��{��6�_�|���w�
�����}1�i	�n�?���[}���p{�������)+�(�0�����&�[
����9���Vn�����5<a==������h�	���\T*xp�z����O���W6}�D�#M[
1mq���t^F�D4�e��8t<�&��!�-&�EE=�\C��Ly4��g�"�{_�~���.}\)_����r��b�}��{������o|�{������="�W�=�U��m;�����D!�����X
w���@'|q�����ehB�5�*�^�C��Q����Q�f���ffuv;y���/q�����ct��s�]�\:�L�9����9F���������9��^e��h=O���#?e��G������a�c����/yM��#":u5Z4��}'A�=�`O�7l@�w��\����?�L�
�N�	�FS�	��������@A;Y������:�1`<����pta������}]�:��	���}���B����\z�!(��"�Es����p�����&o���J�����x�����F��x��F=/����`�W1����B�#����A��QA���;���e�����������Xk���Y�5AM/����+z{-���j�{l8����������'�]���� "Zpwv�3gU���� OJh�� @>���,y��
Y���0+%V9�p����� ��h�$� l�%�.��b���O�
{�����G�"~�`@�8 6L�/����$@U� I?~����	��a� -���>+B��R��cA��cS=D(P�������>-�q�?_z��}N�u�����d�|��']x��Z0���BoO��$��e�d���M�K{�Cl7�Rxp�?��7�`�}�5c��&""""�>�GG�z���`@$9�5���r���&�'"��#��c����-�Ot�L||����(r��\�&���!�PB@��"�a?�+r��)�{DDDD�����;���=@�0N|��������hy�[�r���a�T��a�4���PA_(����LR���!��iMDf6��2��zc�A����[��K����!4�eL�O�|�����Ne� �
�) ��.����V�q��_{�_�����	�X�?�=����D3�������u|����-.c�x\0�1m1&�!��c@�x�t�#�{D��h������5\@Pe������������f����R��������$�)o-^��o����ab���������!ag*b��z�%����#�C�SK�(BRu���S�=a`�������,���t��o��|B���w��Q�������$\��9,��T�Z�o�OQhU�����U�?�z[���j��x!�(�) ��g8B������d��;{%���g4;����g'�1�������,f��o���cQP���'����Ut��<�V�	���Oyk�[zX�a���Y�^/Uv.������K���!C��
�����U��y{������k]U��uh�-V?0�l,����u�d��aJ}z�Rjr�}x���b�|:/���h������%~/P���z��e���v95W>��B'����`AA���]7�@]	��{�	mC�^��n���@�)!Y1�*h����U;,���;�����L��*)����q$	V���m��2(���Xx��i�������]h	�����:V>v5��_4���`c��h0��}�����P`�a��������
�}�c��������
O��G���(8i�}mF?�@�Q�zh���Qeo��Y����R���;��1��a}��A�-��#�����O
v�
u,uGq�TZ*%%��D���c��yo>�:���#�����(������<7O�o�������Z4��1+o@��#�h���bw�s:��D�L�,�[�iV�}��DQ�������]W����uC�����a �����%3�i�Se�h�[��4d����!+�����SBJl�i��������\�(x��E1:���`M���U�A*�%*���teD�o����+vUu��������]&!jD�Y�?��w���G`@���V�b�����cy�G��v��+dn 1�:I>s;�B����`Y����}Ai�J�Jf���������G/0����aU�nl�C��	%�l��a���q	-�.s�ff�
�=����a�o������vUs[�B�Q�]�����4l����3G�:���|��~����
<�����m��7������w��x��������W�<�>wE��;�����:���{�@AA�q��>���kSO�>j�mJ2M��/q��j���p��bI�a�V���Jh�w�]_B��N�B4<�*�`^��3�3��_��]��}��`�0`X]}��i���C�N�������:
Vn�P�C��DG�e����}��?�������"��-�����{�n�v��z���,�h��?i|@�������bV���U�(�����{{�mo^^g��p�l�0�W�u�}^�1e�-��(B �X��`�]�#��4�a�Gn"����"@@p����D��RW�~abHj����qZ"�E0��R�����B�09��9��i�m����M����7 ����&`�����x��U���iJ��V�����a	����X�
0*l(������>D-r8��������n�A�z�9����R9��y�B�LW��	�����Q���`�.�au����.b!���G����+.��W����g,R���+��5����	/�hx�F�tu�+�txm� �������u�o���*��VQ�_H3���W`4������av=l�����q5��]s�c�e��Rbb��@��@=f���%������U�$���E���a2�Y���+��:�]~����>\��4G���������������ur�f�~�x2*$�Kq��z���J����0bU �;Lh����[�_g�`�6����������)�=olQ?��|}�aC�n������
��-�>lX1��Q1���� ���Fy��(��������d��Cn
9k�2�R���5z����T_�1��wW����p&T?�C!]#R����Ne���]���W�.R��P+s��������rt�l<���o�inX�������C����G�����t���������-TrIR�6�G���w��20�<�>���s���y����<����N
���-:��$�B�}��J����V��}.@=Dp�9�����L��x�oG+S��wI����u�	K�>�U�6��+|�� ���������^�xw��>��gn��N�q��|�_���3�|��?7����3�����.�f�<�����%��o8��*�d���A���������������\M�m�,&�������}�z��mJp8�0��C�P����Qf��s8�p�����4���\�����1�~���u��v~c�����T�`7f�hT������t����������lC�n��W����6�7
��k��
����?�.��
b��	��	
K�B�0�]P���M�0T7�@!D�z����S�\r�Ll"�4�����o����u&�	�iLwyG��uTE�/P�P]�	�<6�����`������.��Y-i�tui������������`�$����7}����nO]vs�fn�pX�w����}K�����J�J�{���.<i�� z����<�^�2xp2x��U���-�z^���!��yP
��%6���V��(Qih�C��������5���[����4m���g�m=�8@$���O@Kv�&���w�*X()``�'���9�_��X^���,�������BM�]0+P���X5
A���}�Z���v���c��yP��J��J����C�@�w��w�^�	V�����]����9��h7V�����X��.xx����N�`c�s�\�u������������A�b���e[����FS6������L�<s����V����o.��z������`�w����������QKC2*�NJ��1M�5���`����z=��_��wE�TE1:��#`�a�@]�u4�����N>.�����A-����j[�`_�/���
+z��$S��P���X,�]_�u����%X`�4-�F�����l�G$�J�>�s�;�n���[� ����������
Lx�E�/DX���!d��"�h�^A�'�XUW�;X�N����:XV/0x���U���]$��������*s��F����SZ�}��#v�@���zny�!��s������<�Y�Gs����c@0���R�Vj�����������i��3M��U~�]{��K��+� 4����~��;P��jvc�
/�m[�t���5�X1�����H	��{e��[���;�w��?H8L�ka8�
��m6�.6@m�\<]���]�����Y�7��6������	
�n������7������!9�����i�w��$�zwYl����\%��b�pV���O���m�"�*��h�����}��*�G�}�7�����.��b��������^�p������V.�������FU��U��]X4�s�;��������|���-�R����<�Y:���}Q>��H;=���f���������z�#A��������Z��;w���e���u�+�k#0���Qef*��S��Bo[C9�N�jY{op
��Cp�1�4�.�����$�7��Z?�����W���Ig�RZR����/)�+�nRAi��R�OYE+���\/�
)�����'�$�l�H�������}���>Y�.�a���7���vut:���<z��,XPqO��s�����b�n�^�������
������WDGe�s�T������L�[������Wn/Vb���������6��0@������\��^�pbxuLH��1+�
ZB~�t����6&���%�������	V�g��v�J�75���:��T-K�Hi]���+n���>^���x�[�
Xe�/�h�-ZX>fH��s����m���B�*,�<X)��;q�X�����Ry���
o��uz�:+��� ����u�}^��P�0X�w �����%}�-����1x`�.Dh�����D������b���<(��
?0*���
�F�
�.��o�����4�Pj�kY�c:���Z&���c ��Q�e�-[�L�v�RII�Z�h���{k���JI��
NhT��)��T���Z���v��w�Y���6����� R{����7�wg��J��#�%z��M�s�0
��.���K�D~6(�!�n��$W�S�!9
)��JHp����:���P���.�U���1���a3&9�Kx�j��c%�+C���3*�Ug����Y�G=���R�����tL�!����n�.��.������B�j�4�3�.�]8>_\�i��G
�R�������}0PWBkw�p��F��`e��/�$l�x����
�~����U�0���@���C#`V}�������b���H*�F����x���
�Un��o�y,�����q4�ux���������a��3w�}C��P�Tc_�����5�s��:�!���$9��<��Vm�G4T���4�2����aJ�F������!	���;��b�N�U���N��d���U�1�k���h����Y�M���y��)��m�'�	�����iY�&���*��tXB��AI�0�`Q�����"8)�/����]���T=�����6W���]j�����w�Q�������U�l����k��qz�����U�W�����[�{k���UFT�+������YQ�jj��B=1�G]zR���W�<���f�i@��6%���F�b��U7�,�UW�����Ox1X����cM�1&��N����0M�1+C�UA���byv��c�U��MS�a�GlO7CSU7=�vT�����<_k������o����	:�A�zGe����f���x�y����7xX������csM����%,f7A�q�}�:���S�u)(U��bm����a��bu.�Fp���	��%
�%���%��e��h���OP4�y��'LY�8O�����KK���lI�����yRRr��?v���2h+��C�#��BN�� ����H�����k���U�
�����1MK/���I��b��1#���@2�������O��F}�w��hIi�v����_��k�V	�	�sX�����A:w��|��e��*��}�a����w���O��v*��z��'��M����/���P��5P\\��������w���;�^xA����f���s�9'F��KtV�����W���Ig�RZR�.��%ez��M�YU�7���tn�rC��=U��|��OU�����gL�9$��G
�1Uuc�oM^�Wmc7������]��FS���G����������y/�9��]��w#������s�����?�����?���G,���R���r�V�:�a=��G���_��s�4���EOl�T��	r�%��-�[*s��6M�����nSn�)�������G��?V9��,���5V9�����<�c������F���^��U�
:C�C�	%:Jr:��4��(_N�x�T�1�a(�Y�Q����������a��+��n,�wT��Y��B��J��z�w]����.*��
b=T��N�0�m��k}�0�e[�9lC�9�r)��NCFB�����N1���}�t�M�r_��;�@�v�&� !�7�4)s��Q���p+��I����a����*QQ������b]�������{�&�zYg�j�c�}��G�}}:!��=��
v���cy�v��j;�b�V{�s�w^=�@�8��q�s������s��Q-��@���1LM�6U}IX1x��0:X��Hi�D��X?088���>O���f�M����|����z����*dKH{�I�'�t��T���wSQ��O���}�sJ��4��G��"�T����UW]�?��2�t:��sg5k�L��mSnn�g��4j�(}���:��3b]2���5KMTna��e�9Z�������3*������o7i��B�����o�&��a
�8����*@8�
����r��e�/D���\u�������BT~���/`�*�s`=��sPy,�`W8���\H>7F�Z��x���v��T}�����~��J���j��\��H������"M�7����K���H���k��������^�un���|
u��7�g�r���vc��C�`�Ox� ��^�+��m	NZ��ZgVnc�]���Z��|m�y����L@����\2��~��+{����n���; �n[FL��+B��+��N�c��9�	,����;XE��QR��y����h0�����s�a�����;�@a��!���D9I�aCGE�i�H�	9:����!��K�T�%��T�\2�R9�e��fY���������w���2T��^x/��������8�����A��g(C�M��LI���e�t����m�7&�����VK������z�r�0��
e�����Qq��O����?g�A�sm����f���+e�xU4�r�+�iT��������FE@��

��:�6!���Iw������i`����~`TA�W�����:�����& �Cn�wP��_���{��n}2�H�2���bw�J�R%5�/�Cp��'�x�/�w��7������o/�<�������oWVV�$���@W^y���[�f����n4,�a�����=c{����?���:k`��j��r�A��6���������	����P�o��-�t��yE�dC�g99����2�[�e� {�������s89d(�z���4�+����6�k^���h�y�g�HC��Clu���N��Ph��hX�&x=�����m��a�/�9=��������=��+��Nr{�����II��ZB��� V~tr��S.9U*�YV��,��9L� �Y*�Y���T����Q*��X�O�R�����aF��e82K\� ;O����J��&e�����z�?�F���IG����PGy��br�@!B)��i��
�F2�����w�0����~�)�9��7�90
S�������i8*�}�M8�|{�}+��$�0TT\�m;�K����v����$y��9+�	4V9���3�U{e���6�������~�g�{\��z7
Y�v�[��.����)yB�~!M�����P��lj�P�[3�����sOb��t\���]�����e���������p��A=��#���{L��{�e��p��K.��A�t�Ygi�����]�v������)SbU2��;6��$�������U�iX�v��*#��6��i�����/��x�������jP��Z��P����U��o����z������0%8
~h
�4�����n���	�wA�\W�vW���|���cv�E�`�]x�;,Y��b��}�/#� 
��)��Ti��C��m�3���������y�%�5�9�����T�1j*�%Gg:C�������R�Q�D�)�p)AeJP�G�g�LNU	��4�*����Re����g�������7��hsF��C��b�y��N{���qT�!�����j�(�A���`A���aT�0��P�*�"iH��H�b[y������z��+��
�z>��e�g���2��k��[��y��D���+�i	gz�a
��6�����;�i:���zGJmOL�6'I�O*����t��$�?�;*�n���n%��:��78
�`�o����\yyy��s�9G��sO��;t��W_}U#F���=������[��Y��h�����}�Z�/W�2R4�c�:�HS��M��Tu��/)��#�:��U�jo^Q��5��S�����e���U�-C���1���09
b����������h���;��6M�������/��	����"��-�)�N��a����������]���`�7���.���[4l���zh6$k���[��PBE�/X1X�B��b��2�j���5��4v��T��*U��
��.q���Lg���vZ�S�����W���i��=���;�q����H��c���&�\I�����=��['I��=^����������v������t����?F��{��y�?�<���@���	p��f�����`������`����{l���ePs�	����Dg	zw��O��7�X��<��a��������o�M�u�-������aOk`�r�+Z����pK���������j�RV�B��s�����u�U�S)eU�%��i���fnmnW�����:�m(��~'?��= Bn�[o���el���2�Vi���:����x�bIR^^��}�]�r�-�V+�p�O��+�'�=��	%8*s�U\~*�O����V��^��]k���{
������89�2���*F����J���gy�)��i���w�Z`��B~��E�1����cv��:=�����_ 1XH1Z]�q�	��LUt��)~��:� ��B�������*��m�s�l�F��'�C4����{����KA�%9�9=I�S���T���?��V�b�������,	~a�qvR���wQ�X����A�!�`a�0��f�c=�LO�������>,,(Zy.�	�������5���#����o8��0�����$���?���f��E����
p�����j�������L���Z��>��}�����pkyFI��)%�$�[r9�R�"J��*.��E�z���%K��������?^C�
k����{�{����CTD�}����b���D�)u��O��m��hq��n�4Y�/81���c���j1���fywB��`��-�[����-�����cv�E�N��^���7�i��`�m�r�L�����l~��
���&T�����Q�%�b����#@��|4n�z�W�����,qi��BI��E���0�4M%������^�/�
�������2��,h1��h�b8AQ�n��E%�����'X �j�p����"x�5X�T�c���VP��k�����|������Y5���
����|�e{���o���y�q�@]���,dp���J��j�Ma��*���9����9s�X�G�������.\���|���E�>4Nt����HK����������J�_��D��q�Z�%EmNj�ar����j���:/V�}�1F^�Gzwzt��r����|�����T�����9D���7D�{��[�?S@��fy�>��
�<Lp��m:��m��|��
3������5q��J9�j��k{CR���zn/��Ay�V����}�F2G���� ��`A���������V�P�p��[#���	tF���ZG�a��1���������w,���}^|��}�A��n�?Oa�[t�A^o�u�m�6�����J��ejL�'w�$�{�	�= B�W��,<8�}��o��]�j��������_�^��vZ+DcE�)�M�vM��M�����E����i�f�8H��5�Bu��p89d(�.�A��Ox�;� �^t���B���������bQI��w�)pI�l�Z�#!p���y�nW�t�w���1�M�*^c2UR��z�	�V�&B5�#�yu^L�s����S��(��^M��`n��
cF���Np�3 HnV�7�<j��J��/�k���-���������u�����B���n������9u���y�� �k���7�Lf�K�
K�75��{�t\a�Z��dN���g���a�e�o�����o_Op�r>�{��Oh�z�k��n;G����>\]����o�����4Z�a(�i(���=���.���U����F�Y�������]��<h+s�-�-c��v�C��;�������IWG����T�T���C>�
6�
��
�?vT�`��:ej_B7�L��Nek���L��}	�d��
K�?Q���^��^w�^�����}��a��ap�P'n����*E��5Pw���b�w�����~���9{�N�W������4li��A#
��u>}�
'�f�V�l?�cx�[�p����������<\�#��p�>�Ap���"�(YR����~!�D���PYYY��N�:E4���7���h|�>�1j���g�>E�o��m��m���wP���eHw
���+@Ca����tT&�Y�1�|���@���n�P�]h������������)��-�)�unw�>vc�:������l�������9���
q�6%�i�?��bf�d�����&U+�.���Q?F�����C%I?���K~��1���V��
z������|��lk���]��u��T��o��'�h��m�'XX2p�A�����8^����N�sa=~s���P���z,�X�|��w8������6������7�������]��x�9�������1�z��u�9�����������ZT��k�v�c�������z��X���� �;K�!���>�@�a������~M��Mh��+�r��@'(��f8AQI~��p�r��k��,Y�.��#�X�3��Ne���+V��R�wvVB�[-k?'�("�D ''G���4���j�&��;t�`Y��Tj*�}
@cun��:�w[m�����dk��\��uDG��<�4MI�I���N�t����]F+.��P��;�B����|������1��/���]�����L������m�^i
F��;[6������:�MS��Z�r��.��$��
�*�(YKR.Q��*I�:�``(���L�����?�PO���C�F�!���
hZ�l�<
�YF\O��g�;H�3h��R�:C�h���_�o;��V�l�}#�'H�6P�v�<� l�:�����;����mU���c�|��Us�>v�c��p�,���e���>��Tg�1�~}T��5�� ���j.�sP��B���kk���������<P����*HpD�M��:�@�$����Z���@}Cp���c�,�M�4��r5iiiA������u�������y�_
G��Q�[��>��F��Bo|�S+w������n<�����Rr�����+j�qM���h/��^��������-%8��O?E���[���@����t�{h����l���������)�)K��*@(O��n�P�_(����TY��c�`cE
�c�c���'��/������4��q����VZ�z����{�F���\���V��U�*=�!���* K��Fv�[�"�>Pw�p��V$�/��3l�O�B����
^�x"�lW�4hk;w���C�Z���v�/H��v�������`�U�g�v����ZG�}��'H�6P���V����V����N=^��B���A����1�
�������>���3��b�:���;�����#T�����:v��3�s@�~���K�J�+�m���y�o�;��Kv�u��<�T����f
,:��Q|�/�FM���= ��<���D<Gjjj�9#����MS�L����-���{k4���:J#ZJ�r�qL�u�P����<M��:����.
h�V�&�T�����c�E)N�'�%-_�<��@�-[�,�%@Lq�P�(I
�U���tF�����������;�u���&������T���igB/�M���'I�s���Q����=o]N�/��a���
kp�����X���Q�3��Q�����7���q"������k������X�1��X�m��H_5�7�_#���1��+y�����bt���~��X���X�}�w,�of���y��~}"�v����C�k�H���~��[��t(H di�XO��h������e;�:|����NN��V�le��tAv�>i���{M��C{�%.IR���~�K�k��"�Y�dee��G��Y;�%%E~+Grr�e����F5�h�Dj���������t�Jv���8��.�������#U+RFigYo�P�B���a�������N���n~��o��.�6;�S���?��U	�nq^�������K���+��o�QW����p�����X��M�|��P�m�I��]OU�����e��tEV��i�D�3��Z��b�y���iO�~N:U���e��u�= ��JJJ"�������:]���0k�)�10��/��j����)��n_B7�K��W�:�mT�>5w�S��~�\�dq��aG[�L��<g+����yP�����F�=�o����7,@cV?_����~���K��6J�R�����W���i��=��a�w\a��.R��R����^���M��~���;����[����_8|;�����'��+��h���7���/�,4H}���Q�?����l�2���A��������p���p���p���=�F���R�Vj����>��J�+y����!��r�L��;Ym),�{k�4�SS�f�����V���������������|-�)OI�C���K�f�g]��Ru)(��$�6�'iJ�r��*v:<�$��jU�R��2�8V��%.�ciZ�<T�s�t����
���h��
�.��= �!�����)#������-�5
��i�Fm�������j��i��@������@��5@c�u@c�u@}���'���+����4��^JK
���P���}������o7�������5@���z�{�{��S�6����V�V�iI�%:�p��Tl��e�K��7{0%���0�4M%�����(YKR.Q���]G�h`���dP�jz�0���7P�U�V��^ii����������������������k��B���F),���G
K�����h�.��^�z��h �.p�V�<���VZ�z�
���II���6�"�Wh�iq�:�l��;����^;b�����Tu���2�����������u��)���M���h�����V�<X��V�<�'���=G��i�&_pb�*P���mU�.���u���&�jgB���3���7�VG��t��D�f	o�P��"��[�~}D�o��!�|���EZ�f�8H�RUP���Vn�?����9y��9'O�|�I�Z�M�.5KM���EZR-U4n�W��nW~I�J�T�H�%))��!�yr�$�"�H�#U�%e��v����*@,$��������>��s���%Kt�������={�}�v�rbb�����*h�z�k�wn:]���L��k��\����v)�1S�[��c�&JK���N~I�v)P��|��uP{��<��6M���w���x:@��"-IO^u�����5v@75OM���n���M�u*���}j���${�+Q��8�����v&�R���g�����j���M����#�Dh��1�6m�g��/��i�2#��_|��ey��aJOO�z����w�����s4��?����%I{�����l�6�	%8*s�U\�������5��������������Mo�����j`�LIR����W�LS	*�C.��T�%��NW�<�������
�M�G������U��w6��u�.\������e���.�fi�z�EZ�����>�T
���o}q�[�%e���A�Z��q����O!��P�vM���3��*�?����9y�
CeF�J�T�I~���9yz��M�s��Ig�h ��D��ph��qz��'=cS�L���C�v��7o�/^�Y�����W^Y����s{�����j��<}�&[kv�j��#:ZT���iJ�N��\'wj�O��^�2�X1��U�)������E[5{�
����-���y�%U���_R�]G
�u8_�vT�VMt��4�w�8>D�=��������:v��$i��E�6m����^�����5a���m��f����^�2tW������\}6o���R�C:o�Yj��Y�+���M���U[U\�V���2�[�	��r���A�)@Ep��V�Z�����������������x@����$��n}��G����������}���������aJqJrV-����)�P���p�������{4f���K/����;�{��0`�233u�%�XB{���z��w��y�W�X�|S��D)���r4��jr8�9s����j�������[�������#�u������Ot��g��R�Dp���������5k����p���4M�8Q������CcV��K�w@Cp�e����.�����t�Regg���D��7W�>}t��g*%%%�e��{@���C=z��w���hH�E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@� ��E����x ����-��7o�S%��c��)++���a������"�=\�46\�46\�46\�4&\�46\�46\�46\�/�{t}��
�=���s�e���/�O!@#�s�N
0 �e�q���{D�a���"���#G�h�"�r�N������K�7o��_�Y�����G����k���������������k������������^�U\\��;wz�������� S	�.@�5o�\]tQ��@��G�x���.b�k���������������k������������^�2`��x����hH�E��"�{D�=���QDp�("�@� ��E����x����[����,@C�5@c�u@c�u@c�u@c�5@c�u@c�u@c�u�q2L�4�]
�#���� ��E��"�{D�=���QDp�("�@� ��E��"�{DQB����-[�l�2���K%%%j���z�����+%%%�� B�ij�������k�.9rD���j���z����N;���4(%%%�����}�vegg+//O���j���233u�I'�O�>r:��.�j��q���Y�]�v���@���j���N8��|��JNN�w��@qq����{m��A�Vaa��6m�6m�h��������w��%��������k��U�����5n�8=��Cj��U���������e��t�R-[�L+V�P^^�g}�.]�}���5t��a}������4�|����611Q�G������!C���J��Y�f��/��7�|��~�IeeeA�o�������v�m���w�������k�����2����S^^���y������m[�����4h� ]~������bX!Dn��q�1cFT���]����+���Ok��Y*..�]�4~�x�v�mj��e+@,�i��.P;���5~�x����k���[k��Y:��sj�2��o��F��_�t�R���;���Q@}6i�$����*))�x����N�?���6mZ�@��������#�/11Q���z�!��@�����W^x��8?��o&O��)S�T{����^��O�^A��&L��}����O��m�w��Z�
j.����={�����\P��n����~=��r��a���m[M�>]��w^-V�X��4Pn�[W]u�>��C����T�����Y3m��M����u��Q����_��3��u�Pm��/�����2��-]��6��t:u�q��m��*--��;,��I��o���~�I���Szzz�J�Z��������v+''GYYY�~����RM�2E;w��k���j �rssu�-���D��O?�?����}�����o�^�Z�Raa��������8U	�7f��x�a����������7i�D��wWjj�<��[�Z���o�.��"}��5jT,K@-"�
�O<��������?�Y����T����u���+++K�TPP�+��R���S�f�b^7D[zz��;�2 ��7o��c�j���:�������Y�r��x�b=���Z�x�g|��e7n�f��������o���G��s��g��n����pX�9|��f������/��k�g���_�Yg��n�!�e@�����<�H��������P�������?X�F��[o�U��
Srr�e����5�|}��Z�lY,K�j����u���F���M�4q�D���q��T��Y�f�������'�xB������Pu�����K/��G��ykII����zm��Q-Z��i������]�z�����������<c�=�����^�����u�Ygi�����|PS�L��R *�y��q�������u�i�i��A:����m�6
6��m�.],�;�ON=�T<xP<�����������\.M�8Q����e|����k#�ek��U�~�dFX�>|X#F���U�<c�w�v������f���:��se����N���������y�7�'O��-��'���'������W��}k�4�U�7oV�~�TTT$IJLL��3t�5���������@�u�������,�r�)���@]��_?�[���|���j���JKK�������_�Zeee��G}T��w_��
�� �
�=������|�9�h���Aor�7o�F��Y�����m����Y��@4l��E����������.$����3g�F�������q�\:����b�
����c����6J�:a��
:���������Jg�}v���),,T�~��e�I�m����/���y�k���h����+b��s���<���������8Vu���V�.]�k�.����>�[o�5�U@x�n�����[��-[��N;-��7�|�����{��8�-Y�$�5 �x�ih`�n��x�
�����Cv&>|�����<�����R#D[�����o_:�h�F�QhO��N���$}����,��>}�h�����
6����?�����^������q�����ZB{W\q�=����_ZB{���;vl+��m������c��B{�t�e�Y�7o���_��
��%Kt����������?����D�2��o������ N�@l���mNNN�*��[�|��y����/�������j{��W,�=�P�*��g����1c��U�Vq�"s��!�r�N����s����#G�D�$�����3g�ey���!��yo�m�������Zm��-Z�����������"�r����S�Pii���/��%��#��1c�\�#;;[���g���:���X�G�����o7n\|��jh���e���0�}}�%��p��f���������o�����kW�rII���_��/���~c���q�b�4M-_��26p��8U5��c���~�TB~����\����>��!�$
6,��@�����Z�+m�������� 2����,o��!�7�_�l�ey��A�*qFp�
6X������������g�����.]�()))N�@�{����{�n�r����#7�zi���z��G<���MS�v��Xj��MfN>�d�����^��z�N>�d�h�BM�4Q��]5r�H=����o�
����-����o����b�:v�hy�����������X�<��el����.qBp���BeeeY�:u����o����u �^�u�2�P�!�1c�&N��Yv8z��dF�����n�?^%%%����>[���o�\����bm��A_���.]���7��� �e@T���?�x;vL���������k���:r��
�c�}���������gO���*--�S�P{6o��o���2v�
7����i������5����3n��]~���7����t��j����������YNLLT�6m"��C������G�6��'�|�����26n���Q���?[�����T���u����j����uIIIz��W4|��x�
5��s������Tu=#����4i��n����"�xBB��Q�Fi���j��u�*����y�e��p��s����r���B=��cZ�|��{�=edd�V�s����_�~q�������/��I�&�4M���i��qz��u����W�^JMMUNN��.]���zK���?r�H����q|�6�{��;v����I��o�IKK:'��C����n��]|��4hP�*�������g�}6�6�a�����c�=��O>9F�@�l��M<��g����S����X����0x+++���K�t�RM�6Mw�y�z�!9��W��v����g���[=�=�04f��������������������v������/���q�4{������4M�����1��@}v�-��W�^���[���?J*����}��������[���o-�P���4 �!������HMM
:'����k��V�v���5k�L�=�\������+��?����z�w������%I�{���������(,,��?�#F�7�Jnn�L����Z�J�����E����>��7��1c��������S�q�F�;���{���r��j�������,'%%�]���9��s�|�r�y��!�t�s�����;5v�XB{
��@RTTdYNJJ�x���d�raaa�j@|�u�]���O-c�����S�8U����������9�����7����k���/��RRy��W^y�Z�����0
<X�<������]�v���@EEE������_�t�M~oV�p�B]}��r�\q�"(l�t:5g��}����������S����,��>��_��3fX�������8U����/�{��z��'C�������'�k��z���cT!b��4 ��.))�x�����s��{�����SOY����n]u�Uq����g��i����s�>��c�?��I~���:����b��8V���g����N���	��

��~�+���O���ot���k������RSS�������k��1z����i�&�y�����������oq�"���&L�/����:���K�,7n��E��Z#���c���{�Y����b 
JKKu�����[n��={$I-[���>�e������*))������G��K.�a��C�i���������e��IOO�,�v��o�=�9P����[����-c������S�S����Tu��Q�G�������k������G���_�#G���F��I�<��v������oAP��N8!�m;v��/��Rg�q�e�����TPPP�@T���o����?���5b���=����3����Yn���F����fn����=��<h� �����2e�N;�45o�\���:���t������|`y��'�|Ro��F<�@- �
��{


d�fDsx�B�nN�]�����z����^z�^}�U�;5@C��G��;W�:u��egg��'��cU���3����{��}�Y5o�<~@����7�|S			�������/��cU���T9�N�XFF�N9����2d�e�������[����X����d���z���<�m�����v�����/��/�h���������=h@Z�je�!���T����h���l�r�6m�Rj��t�W����36r�H����~7@C��U+M�2�2�{�5w�u������u��W����z���/��2Fp@}����=z�����^�zY�#�[0�%[�n����-c����O1�=��e���oW�����w��q����{������IMMU���-cYYY���}���k\j���Ku������36x�`����JJJ�ce?�\r���mv���;v��"���#��s���a!�
6�2��;��Y�zul������-�7n�S%�>}�X��6m����>|��5@�����2M��<`����/�@�������[�.�����w8=z�e�����Jm�/�{������_��6l:���k�j��Q:v��g��SN�'�|����8V���ys�l��2�w��8U�h����e���q�"��o_�rqqqD�{�q�$5i���5@<���7�|�2v�
7������+77�2��[�����>;;��u ��@�����%K��w��=��}�g911���G�;6n���#GZ�Y�O�>������Y�8VuSbbb�K@�~_WZZ�J 2�,���/�����oY����qM�-��m�<�III;vl+���{C��������Y��r��&�
�}W�����i��y����K��)�0B���_X��
����������c�F�a�Y�[�n�;w�Z�n���n�����C�,cm���S5��~q�d��5���;=�m������/�6=z��J}P��vR��`������p8�v�%I��m��C��:��r�J�r�^��^#���3,�\pA��B����Pa���u�������
�=h`�V�Z)''G��u�V-\�P��
��k��fY����j�F���={4|�p����3��C��7O:t�cePw��3G�iz�[�n���;.�@pC��x�w�NII��#�U�Y_��e�S�Nq�"��M�y��Z�x�g������	B�[VV����26t��h��.??_�f����7.>�@�$%%������={<c���������c��y�����G�>��#����p��Bs��)�����7�����]y���Q"j���C9r��l��k�������;6@CVXX��z�26f�9�:��;r��f��m>|x�����t�M��'�xB���!���?�a�8��iS�����z}P�f���c��y���k���;/�@t��l��3����,�}-Z�o��6�|���S�{��G�����E�i��i�����{��n�M�Z������<�w�y���=c��7�_|�>}���2�w�}��/_�>���^����3�t:u�wD�<���w��#G�x����4j������k��_?���?���n�In�;�>K�.��w�m�8q��5kVku@m�>}�e�7���_Gy�����Z���u�4q�����I����5v�X�X��=u�gD�F��a�j���{�1�����[n�E<����o/Ir������t�m�)++��]������?�y���,j��o�Qaa����5kt��wz���m���_�s�o�^}�������
��Z�����T��6T�-�T�����k��54h����*�{��:�����h��4Mm��Q3g��s�=�����;��SO<�D,K��X�p��
�Y�����o��� S�N���#5p����/++�=�����z�2~�����g�������7O#G���-;#F����S-����\���kz���,��N8��X�B1�jj����������?���E���9��s�`���Yg����'k��!�����5}�t=��������3s�L]~��1����4Pn�[]t�>��c����T�.]��Y3m������������s���3��a�Ps]�v��;j4���_���P����,X��C�Fm>�
��=oIII�����7o���$���i����������������.���� ������E�i������+5|�p������Jnn�>��=���Z�z�e]����t�Reff��r��i����{��o���:v����|m��E%%%�����Z�`��k�?��|�A�����b��8V��w�^
<X��m�[����n��)55U���[ew���G=����(1@�yh��f���n�A���<�.�K[�n��'33S�f�"���JJJl����i���:u�n�����]K�,��%K$I��������5k&����j���r��~��k�N�~�)�=��=���&M�����JKK=�{�����{m����������g���*�j����q�����%�����E�t�u�i����u���?�p���D=�������k�J�o3

XJJ��~�m��5K����]ZZ�&N������uPg�����6m�F���M����0�t�Iz��'�y�f�r�-������bm��E�V������u�V�������5k�\P��������]����J���������}�Y�]��k�z������-[<�III;vl+����S'��7O�����*�#�����5�-���~�A��s�h`���2�A��y��.]���l����y�������<�L�����<r����i�6o����,=zT������P�f���kW
0 ���o���z����x�b���Or�\A�OOO��Q�����^��sN����9z���,Y�M�6)77W���j����^�z��<TS^^�V�X��[����#***R��M�����N:I}��
�@�Ep7Z�~��o��={����cr��j���Z�h��}��_�~r:��. l��"z+E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@� ��E��"�{D�=���QDp�("�@��81MSg�}���ar:�Z�n]�����m�4e�����V�������yN��n����s����>�L'N�����];%''���z���<�����N�<9�%�`�������>���.	�AB��h����O?��;v����*,,Tjj��7o�-Z�G�:���t:�]���o�������|�
7���E+�Lqq������������<������c�f��(V4����5k�u�V���(??_������P�N�t�	�9B�<wIDAT'��N�a�.�Z���~�����g�����%IO>��n��u��=���X"�4p��oW�n�je�f�����#A��<y��L�b{��74n����v���?���3��_(;;;�>M�4��4z�h��7�Q�N�jTCM�����{��,����/�KX�:T�-�����}]|��!�s�����4w��o���:������W�y��h��q�1c�el��:th����{����j���Z�j�\.W��333��_�Zc������_�C|��������GyDW]u���7;��������7���Xr����i��>}�z�����?_o��FX�I*((��_����O]�t����k-��i��o�>��o�[�o�>.�T���>k�KJJR�=t��'[�u���v��c����Z�l��}��������Rt��U�ax��4��������8q��?�x�{��Z�|y��^�~o������_�����j��5�k;T���+��O�����	�F��{��-[���k��w�}W��L�����5�|�=Z/����v�Z�"��o�>=��s����D�y��19v4�\.=��3���������������<s����5k,c��~�^z�%���?J�
�G}�o�Q��<����%�\��.�L�����6m�
���\���a���{,a����_�|�M��1Eph������G������j�3w�\]~��:z������d�y��4h�Z�n���[+%%Eyyy��c���[����J999~���3G�_~y���=�������,_{�����S�����O���`�5kr�U�V)++�26u�T]w�u���W�&M��G�u���4tS�N����/�4m��r�)>|�:t��v�����@�w���?���?�X���g���Z�n����[��OM4�k;�;v�x����K��d�}��':����\��{@#t���j����.#ls�����^����u}����)S4z�h5i�$�<n�[�-�?����9Seee�Ur@����j�8qb�����Ob�Uj��e~cW]uU��9��s	��H���G}T�����
���~�;�s�=���[��KKK������;���M�,�6n��!C�����V����^{(
��v5a�M�<�36m�4�{4�x��^�ZW]u�_�#11Q/���~��]q�!���p84l�0���[��a�.����*;��_~Y����SO�y5��m/33S���5��W�^5�hhf���x�o�S�N���o���/
�I���/�Pk�����G����m��_��������vm�@n��F9�N��W_}��+W��"+��YEEE���k���oOOO��9s4q�D��������>��C��1C����(7���2���������������kYNKK��<@C�{�nM�0��;b���`��q������'�|R�����-_�\>�`���DC��@0�:u���#-c�>�l���Dp@��������~���w�n������N�|��:v�������O�w�^�����e�]V������"��a�����Wu��;���/�����/��B��w�����_t��7�������?�X�y#�����W\aY�={�����T
���xv������z�o��[n��Q��z��N:)�����oZ��:�,�m�6&�n�JJJ�|�reggk���:z��Z�h���[�o�����o����@��/��={������\����y�������������Z;~c�o�>�Z�J�����v���uk�m�V��~�Z�l�#�f���9�o��T�>}j<�_��W}��'� ����C=�Y�f�x�`�����ri��U��m�8���\�l�R�[��	'��~��E���8����N[�n��c���Y3�i�F���/��K�Z9�i�����i�&<xP9992CM�6U�N���O��
.l�i�&�Y�F�v���c�����v�������x.�����Wk�����o���������N:I��{���,�]�V���t:��U+�o�^g�qFL�Jn��I+W�Tvv���������������R�-j��%%%Z�b�v��������JNNV��M��{w���W�����c���/�X7�t����$��0k�,�p�
q��&�{���������5k�L�?�x�*����|}�����1c�����t��U;v��~��Ao����v��a��=��)S4e����M�Y�i��={��O��������o�^�\r������t�***������3g����SIII�m
��I'����?_7�p�z��iY�}�vu��-��3f���3B����~�z�!M�<�o�}���c�����$]t�E���B;��o�Y���-c�����'�����s�=�?�P�W��<��	&��oTbbb������{��9���Cw�uWT�o����N��q��Y���}eee�s��Q9���~m_�b��������?����n��}{�=Z��sO�: :T�-�,2D.�,/\�P�>�����'��m;G��}u���k���Q	�}��Wz���4�|���?��m����#4v�X�w�yr8���o���_����G\��������]�������������n�j��wpo���~�-[�`��*�<h���������}�2$dp/;;[O?�����c���Rbb�N?�tM�4IW^ye���`���vk��z����n�:���N���������������\.���[���������� ���z��y������^��r������N���?=��ah��-A��������u��������o��-5x�`}��W����z��
\���@���~c�]w]L����y������2Vy�?�c���:��Su�Wh��9AC{��{�n��������|�����p����:��������������������5k��c��W�^�={v��]���m����O>���=gaa�����X�
Vh��ri���:���5y�d}���A�;n�[+V���7��^�zY�RuUaa��y���	&(!!z��x�UW�u������zm�����W_�A��?��O���T~���?��>}����nSqqqT�(..�o�[
6Ls��
z]Z�~����Z�w�y!�w��Y�F��
��!C����'dhO*���������u��W����t�R���W��w_��^$^{�5���G/��b������B�u�]��������
�IRii�/^����Z�����Tvv��:�,�x��A�t�\�7o��8���O��1g�����{�������2�'I7n���>��v��4i�e�4M��x�^z�%���o�9��}C�_}���;V��@�Fp@��~�zm���o���n�C5�����Z��6m�������W^�����U�VE�oqq�~�a]r�%�_���t�����[n��={">�T&���������
���T�����=���������������/�P��w��9�q�m���#G���_�x�X�?���0!!��;^M�����k����Mu���u�V
<X���NX������������#���VTT�Q�F��W_�h�/��B���\.W��|��w4x�`K��H=z�����W_}��C�*+++*�=���0aBX�3;{�����C���O�����v�Z
<X�|�I��_i�����/�o��6��}�Q=����v�������_���7G�%���/�K�z�����_=d�>�1���[��=�\���+�9|�{%%%�7o^���C����d��~cm��
�#W]������r:�q�&2}��U���=�YYY��Jbb����p��-[*==]'�|�e|��5���m��]�v�7u�T�w�}~�iii9r�N;�4w�q���Pnn�6m���s����>��#�?��\ �����������o������5|�pu��Y���***�����?h���Z�~}�����,�k���*--�,�h�B�;w���3f�Z�nm��7}�t�q���o�������]}��A�)((���Cm����w��a�t�I'�e��JHHPNN��/_�����T&LP��m5z��j�_��T��r���m�c�w�yz���-c+V���c�j�^]�����_g�u�m��c�����K��O�l�R�����5k���������m/^�#Fh��%JNN�V-7�x�����K�F�R�����eK������������o�>��_}���~�i�y��a���{�na:t��~�+���O�[�Vbb�>��[�j�����o�0�����K/��R��A���_�J]�tQFF��������k���!����/4u�T�rrr��
��C��]�vJHH��]��t�R��j��������;v����/~�!C���O��wx������o��'�XB�yyy�����d��r�)�����F�Rvv�$�0
<X#F�P���������o���������:u�.����������?����z�v�/~��9R��wW�V�TZZ�C�i���Z�|y���������z>p��f����c��]c����~��[n�%�9N=�T�a�{�������"����9v���N;-�DG^^�6n�h;����TM�|;��7N3f��,�o�^�W�9��6�aX�o��fM�<9������?��O����T=����8q��6mj����S�p�BM�0����w���g��I�&�<�w�a����K��������y�f����z��������]�ZB^x�_��$&&��k���O?�[�v�V�Zq���;w�u���K-�P;'N��.���W�<��F���Z�TXX�g�}V>��'�h�����Gk��U��#�?V�\�7V[�?�nTRy���W�����������4M�7�/�����GyD��v���~�=��&O��'�|Rn��3�j�*�{�����p-]���j���^x�]v�e��N�6M�&M��o�i��G4i�$����<���~�[o��o�������>�+��2���T����?����U��������'�t�^~�e�q���>��s!�{���=A��.�LO?��:u�d��o���vk���~��������
�����t��=���z���=�/**�e�]�5k�(###d������y���/����o���I�&i�������,_�.�K=��>��������O������<��!;;[3g��{����u��w*''�3���/W+����/[��;�8]|����������[�._�<�Z@����F�3���d0�/V�Ze	wH��dP3yyy��o~c9�m�����Ku����U:t�V�\���<y�


����g��V���O>���g��IR�=��?�Y��o�y��r�x������|��7���������Z���t���������#���RSSu������?Vbb�g����z��G#�?by�k���m����h�k����~[�~��e,%%E���u�w��������i���K/��{��g�b���k�L��������$)==]��O���k���#G4{����*))��W_������!C�r�J]u�UA��$)##C�\s����������2�w��gj���C{R��!��n��V��5+`h�n�'�|R�����M�4I_�u��u��7�_��W���k��m����6C�|
�3F.����������	t������
y�u����{������5o����:t�������Y�����&99Y&L��-^�X?��c���}���Z�n�el��	JH��=r���gY����=�!����+V���5�W[���;w���k��V�?����X�.]�z���?����'�x"�5���_~Y����,;}���~7���Y3����JJJ�������W_
��_�������O���>v����:������_���������������=�������w�O>�d������Y(������CY��x�
���?�9b���L{������C��nn�kp4��k�SO=�7����k���a�����N7�|�e�4M�y�����w�}7��>�a{��?�<����O�W�p�	�3gN���v�v��>���Y3���;!��4hP���������=Z/��B����n��/����OG|}��?������
,�l�����v�5w����>���~a��c������
��t
K�|��r:���H����;�N�����h�J�_���kW��u_�o�������5kj<Oaaa��w��a����	�������E;��a���1t���#%%%z��g,c�]w�N?����:����?��?��E����n��V��/^�o���2v��'j��)�>���,��<��>�H�_~yX�/^�X�7o���7.hHc��9~���}�YK��p����i����'������~����>��jKnn�_GB�<dT[����GC]����wZ�r�e�_�~�4iRD�<��cz��w,�m��Yz�������2v�X
80������h��U�1��d�����1c�����>v}��?�!��~��'��a���������,;=����:��>��^{M�iJ�����o��VC��h��z(����W_��������V�\��T�=����kk��u����K�.3f�>��C��?��OM�6-��|NN�f��e=zt��`0;v���}{����
t�P��k3�R��:���ku��%K�{�n��o��H�=����w�����v��>��o����{�]s�5~]�|;����a7n\�}|�={��8�R)55U��
��-\��Zs��@a�����][���tm��
v�M7E���y�����k,c����zmU����A�,�v^�������e�e�����V���2C7�xc�������9��������{�����[�j����_��H_�iii;vlD��h�B={������<g��n{7�|s������oY>z���z����}������r�-���������.� ���s*;�x3#�D���G��Sg���h�"�rbb�N;��j���(**
���7�����������/Z�h��/��2��g�i���!�-((���3-cC�	R��<<8�b�=���_���k��58�����o�������5��W^�������{�u��q���
��j^,/je?���Z��61����m�.������n�:*i^6-55�Yfe�����
%D��{�����e����|�����=��|>�|�'y�6����e���qaa���;w�����F�U�u�f�Z�r���U�t��x�����
��]�Vh=�n��V��U���:��999%^��{�W�^
7�����n�+..�Pk��������^���k���	T?����p�{���i�����c
dgg�g38��������>����[:�'s�q%��;�n:����i�]�x�������_���bcc�h���qaa�>��=���%>o����`Bi�N�8���4C����R�����?r:{���N�:N��a*���ZY��'�������
7��r'���(y{{��������Y�f�Y�f��v��0''G~~~N���m��V����&22���%%%)??�P�3g�V�X��>�=j��|s��WV��`i���=��aC��.�	&h��I��;v(>>^]�t��s���k:t�P{��G+8vv�����<�l�x��� �	wX����0��������vS=�����/_��]�,]#++�T���4������t]O��W/������c��y�����;w�a���_jw3��X�N�<��'O�c�%s��S���M0�r�?gsV�Z�r���v�{��|~~~


��#G�k�
M����������x�����f��k�����}>g���c�gkE��|��,�����~��0������G����7��g��Qbp��+_���K
���f3��|AAA������qn��S���NUs��b���vxC�UE���������M��
9y"ooo�=�P���_���p�������~0�F�QjW��x�;^���fS�F�L�'NT�����3�
�r��={�����������$�t�s������_��aW�z���}>w}���*����\S���>C���5j�(Cm��%:s��������v�ZCm���
��>��/�J�^�E�x�6m��j���n��5|}}M���B=���������������v�>c��1�;����y�d��
��t,r�{�nUy�eff����+x�����[�svN�������	��k����w<����������'N4�/\��y��9����>2u�?~|��������?�s��q���L�����a'�		1����	F�]5j$��n�����uV:w�\e�L���eKu���P[�h���uv�]���7���i��n���u�cIz��g-�=Mdd��VY���y�����c�JY�S�vS-//�Bs:>��������/O��|�1c��g[ZZZ���R��34""Bw�u��6s�L�gAAA�f��m��k�N]�v��������DP=��qz��a��������_�~3h����������T����qUu/j����v-vNr������+V����q�)<[�5�c���:;�v����~�������kS-::��Bg�r���WO���"��������

��|���������3�/_v�,s��o����Y���V����]�RSS��w�j+V�PFF��6n�8K�w�����@�@p��������ES=..�
��8g���^�4j��0�t�����+Cpp�l6�����R��z��C�����P�;w��:�Z�5����i
��X��9R�]^�z����u�j�/_6u.���/j�����,]��<�l���2������|yyy:z����,��	���:���������A-WxYYYVl�#\���d�����V����w�BCC
��3g�8�����Q�,Y�����Z���-�x�{<�cG/I�?��������i�����o�>7���������i��J_�V�Z���4�v��yU���������j6l0Rsss�l�2�5w�}�7n\�5Z�je�Z�u�V����C��u5l�0S}��Y����?����������-[�O9������u��I��JJJRQQ�����*�m��f�m���R��W��a|��Y��9p����������U��	��S�N)55����Q���{�;�9��7r�H�:�����0���M�#�� ��#�;V����ZNN��}�Y7��u-[�4����Lu��woSm���U�v�=���-Z��R�t���	�5�VQQ�������,Y��������-����������v��9�_����^]&M�d����_o���%��={��Y:p�@5k���5��S���o��T[�t�Ks}���e��8�_���'�T�����C��=��K���O?Y�#�

2�;���[��=�;�AGc��U������={���u��������o��v����_�N�,�x&�{<RHH��x�	S}����wRRR�a�K�t��!n��]��^u��{w��_�P[�l����_�k4�T{��wTPPPik:v�9w�\��UV]�vU���
������y���}��W�5h��������j�����/���%���z�)�8q�P�Q���N�Z��K�)g{��}M��>���9�4999���O
��5k��;�,�<U%""Bm��1�~��Gm�����t\/55U999��c�����������7�p�N���La���8�;1��a������f�R^^��sL�_��:X����M���:����������~��n�k��a����,Yc����������-��J���c<xP��fu���k
�*&&F/^���o��Vu���P�������/V�������+�*�c���Tm��E�����?�hxl����Y�f��1b�Z�je�m��Y����k�������W���v�����[�vy��S�j��Y�����u��7�<oyx����sgEGGj)))�9sf���������Oj��WHHH�6\��u73fL��;�h��%e~~NN�^y����v'N4u#\�`�����l�������0�N�:eYW���8q�a|��1�=���l��6o�l�9�����U�N}��g���5���=�{��Gqqq�������{���1c��{Y�~�L����������x�	j			:th��9����~�/��o������L�b�����z�������������xM�v����w���c�^�j�G�V�5��s����I��_Y�l6������3�<����r����[���#�&44��k<z��z������r�w��E=���N��:ur�u�,�r�?�����SO=�M�6�i�9s�h������������$&&F-Z�0�RSS��egg�{������������$9u��2���������PX�S��__O?���f�����j���.��n��*���s�=g
r���z��'e���5Waa�K���;wV�N��e���
4��a��=��8����iS�t�M��<�=��[n����U�V-C���K7n���o��K������UTT��7j���
��5k*k�&aaa���0�6l�Pe�WG�����E�d���5k�(**J.TAAA�����k������Q�f������(����)�c��5y�d
:T�����{��a����j������������
���"
6L�����S����zS7�%K�h����Zdd�:t���<��)�WPP�q��i��!JII)�<���z���t����k��Z�j�K��J����@���Gu�m����+54UPP�5k��C��6m������k������j�e�	g����gS��������>���+������s�i���������7S�9OS�fM-^�X�k�6���EGG���?/5<�������[�n��rCCCM]������o�W������G��Y��hUx��g��W/C���s4h�y��2wW���^{�5�|��������n�$<<\o������;��g��e�l����{�����0}���.������1c�Xv���v}�������-�x.[���n��cGK��:u����>K������k���:t�rss
�����6l�|||t�w�s��j������������\9rD�w���M�t���J�kIbbb�����x�j�*��g�����)����h��=���T��={�����c�=f�<xP111�<y�z�����(5l�P~~~���Uvv�:���$����L� G�����c�S�e����/�Ptt�z���f��)((H���:}��v������k��]e^k���


�����k����������u���;
��������bcc�n���qnn�����n{4s�L8p�FY�|��/_�:�{��j���4h oooegg+++K�w�VRR����_�NN�`��)���2uy,**��34c�EEE����R�&Mt�u����������}��f��}�Gaaa���ot���W�K1���}�������222�kyyy�4i����k������P@@�233�s�N}�����4���_��}T���h}���z��G�����u�
7�o��j������e��������+99Y[�l����%I��w/u��S�j���*,,,�����M�6<x��v����`�;wNG����~�-[���u�����{]�j��l6��,Y��o�]{��-���v��5Ks��Qtt��u��o�QAAA***Rvv�N�:���%%%���D�&MRBB�,X`����������o���{�E�
����u�����G���JLLt�3��F����';�~�����q�*4����O:q������Z6?�L��kP^^^�BC%�R �j}��Qrr�bbboz<??_6lp����a���wo+�Y�������A���,m����m�{�����`�<Ui���
		Qll�)�s��I-^�X�/�|]���/��R=��>��3�cEEEJHHPBB�%k���������1cL����j��}������A����r�x�����Th�Z�ji����0a����cz|��]��i�����n��&�;����������r�9h� ��;W����j�.q�����7�������=zT���n�����;�j�*S;O������_�����rzz��]�������)S���/�.\����p��+>�q��Z�n�>�����I�u�V�5Jk��5<VXX���x���������Q#���RRR��Q�U�k���?�7�x��X�^���U+��Z�l�a��m[EGG[6?�L����U�V��m�6��3G-[���\5j�P�~��%K��I�&����6m����j%�PvC�Qbb�P�yl6�������z}���������
4(����Gk������wi��R�V��y�w�(}���Z�`�Z�hQ��BBBL]=�����w�^=��#���e��i���n����g{��-�u�V
>\^^^�Z�f���4i������m�1b�~��G�q�.���Q�2]7e�������GFFj��m�/<]``�V�^�w�}��_�+i��Y���Vooo����Z�h��7o��^^^j����{?~�j����n���B�x��G-�x.�{�*^^^���Ujj���]���G�q��ez�����w��7�|S���Z�v�:w�\�;6z��'
�%K�(''�J�P]���i�����k����o��L�k�������8?~\�W�VXXX���8q�:�i���s����.�?�{{{�K�.z��W����{���L���/����5w�\�5J��r�BBBT�N�r��j%�D���9R���Z�p�����2��m��������/u��qM�6��}U��
*..N��k������R�5������_k���/�����W�n���g{��
�x�b%$$h�����7n��c�j��=z������S��<Idd�6o�����J�
*S�344Tc���?�P���S�LQBB����+��v��Z�j�>�@���j��Y����yyy���WZZ��O��;���L�����"##��3�h���:|��&O�\;���#������8u���L�����������}�4a���

5�%�4iR����X�n������z���,�x./��nw�&������g�9rD�������������0�m��L!��������|��'�qG����G������Leee)??_~~~�W���6m����J��x��m��]'O���S�t�����*((��^�W����^�


�c�9rDYYY:}�����������@�n�Z������s�V+���g����C��k6�M~~~


UXX������I�S��l/,,Tbb����t��)�={V
		QXXX��r^�
������4eff���3�]�������ysEDD�i��^'''G�7o�������%���&M�(22R���������X�5:s��l6�������0�i����:������xedd(33S������U@@�Z�j��m���SmY�_�^}��5�^z�%������/�����U���O?��U�Gp����+��?��x��uk����#B���!C�h����c�����4�B����Wxx����$I���:t��BBB,�x6~������K�������t�R7���r��1�\��P8p���x�M�V�������:��|���������;vTrr������+�k��	4}�tCm��M����?K�?~��Z�h�K�.I����t��AX2?�|t�7���;5d������;�x�b7��������>��P����,�'I/��RqhO������C�=p�c��)""Byyy��-Zh��=�U���wP���v-]�T�?��222�}�������%����G���Saa�$)22R��o��7W�k����kUhh�.\�;v������]T�V���)S$I���:r�����M����������?���/�
Dh�k����y�[�5�]w������q�*��V�g����-[j��
��@���{T6����� �o�^�
��1cT�n]woTS^v����MP]x�{T'���=,Dp��B���=,Dp��B���=,Dp��B���=,Dp��B���=,Dp��B���=,Dp��B���=,Dp��B�|M+\A�IEND�B`�
#218Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#216)
5 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 10, 2025 at 3:06 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

The takeaway is that I think 16 is a good default effectio_io_concurrency value.

Attached v35 0003-0005 is the same as v34 but is on top of two new
commits: 0001 increases the default effective_io_concurrency to 16 and
0002 adds a READ_STREAM_RANDOM flag which disables sequential
detection and is used by bitmap heap scan.

- Melanie

Attachments:

v35-0002-Add-READ_STREAM_RANDOM-flag.patchtext/x-patch; charset=US-ASCII; name=v35-0002-Add-READ_STREAM_RANDOM-flag.patchDownload
From 7c32867976d485beb3580f0347b824dbf021aa0c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Mar 2025 18:17:06 -0400
Subject: [PATCH v35 2/5] Add READ_STREAM_RANDOM flag

For read stream users with random I/O that want to explicitly force
prefetching. The read stream API attempts to detect sequential access
and shuts off prefetching. Some users may have runs of sequential blocks
but wish to issue advice anyway. Provide this flag for this purpose.

This commit adds no users of this flag.
---
 src/backend/storage/aio/read_stream.c | 38 ++++++++++++++++++++++-----
 src/include/storage/read_stream.h     |  7 +++++
 src/tools/pgindent/typedefs.list      |  1 +
 3 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index 04bdb5e6d4b..b4dea112d9a 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -103,6 +103,19 @@ typedef struct InProgressIO
 	ReadBuffersOperation op;
 } InProgressIO;
 
+/*
+ * Whether or not the read stream should attempt to issue advice.
+ * RS_ADVICE_NEVER disables prefetching. RS_ADVICE_ADAPTIVE enables it in
+ * general but may temporarily disable it if sequential access is detected.
+ * RS_ADVICE_ALWAYS will always issue prefetches.
+ */
+typedef enum ReadStreamAdviceLevel
+{
+	RS_ADVICE_NEVER,
+	RS_ADVICE_ADAPTIVE,
+	RS_ADVICE_ALWAYS,
+} ReadStreamAdviceLevel;
+
 /*
  * State for managing a stream of reads.
  */
@@ -114,7 +127,7 @@ struct ReadStream
 	int16		max_pinned_buffers;
 	int16		pinned_buffers;
 	int16		distance;
-	bool		advice_enabled;
+	ReadStreamAdviceLevel advice_level;
 
 	/*
 	 * One-block buffer to support 'ungetting' a block number, to resolve flow
@@ -228,6 +241,7 @@ static void
 read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 {
 	bool		need_wait;
+	bool		sequence_detected;
 	int			nblocks;
 	int			flags;
 	int16		io_index;
@@ -248,13 +262,18 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 	else
 		Assert(stream->next_buffer_index == stream->oldest_buffer_index);
 
+	sequence_detected = stream->pending_read_blocknum == stream->seq_blocknum;
+
 	/*
 	 * If advice hasn't been suppressed, this system supports it, and this
 	 * isn't a strictly sequential pattern, then we'll issue advice.
 	 */
-	if (!suppress_advice &&
-		stream->advice_enabled &&
-		stream->pending_read_blocknum != stream->seq_blocknum)
+	if (suppress_advice)
+		flags = 0;
+	else if (stream->advice_level == RS_ADVICE_ALWAYS)
+		flags = READ_BUFFERS_ISSUE_ADVICE;
+	else if (stream->advice_level == RS_ADVICE_ADAPTIVE &&
+			 !sequence_detected)
 		flags = READ_BUFFERS_ISSUE_ADVICE;
 	else
 		flags = 0;
@@ -501,6 +520,8 @@ read_stream_begin_impl(int flags,
 		stream->per_buffer_data = (void *)
 			MAXALIGN(&stream->ios[Max(1, max_ios)]);
 
+	stream->advice_level = RS_ADVICE_NEVER;
+
 #ifdef USE_PREFETCH
 
 	/*
@@ -512,7 +533,12 @@ read_stream_begin_impl(int flags,
 	if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
 		(flags & READ_STREAM_SEQUENTIAL) == 0 &&
 		max_ios > 0)
-		stream->advice_enabled = true;
+	{
+		if ((flags & READ_STREAM_RANDOM) != 0)
+			stream->advice_level = RS_ADVICE_ALWAYS;
+		else
+			stream->advice_level = RS_ADVICE_ADAPTIVE;
+	}
 #endif
 
 	/*
@@ -662,7 +688,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 			if (likely(!StartReadBuffer(&stream->ios[0].op,
 										&stream->buffers[oldest_buffer_index],
 										next_blocknum,
-										stream->advice_enabled ?
+										stream->advice_level > RS_ADVICE_NEVER ?
 										READ_BUFFERS_ISSUE_ADVICE : 0)))
 			{
 				/* Fast return. */
diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h
index c11d8ce3300..463dd4ac6df 100644
--- a/src/include/storage/read_stream.h
+++ b/src/include/storage/read_stream.h
@@ -42,6 +42,13 @@
  */
 #define READ_STREAM_FULL 0x04
 
+/*
+ * This flag explicitly disables sequential detection for cases in which we
+ * know we want to issue prefetch advice even though there may be some
+ * sequential runs of blocks.
+ */
+#define READ_STREAM_RANDOM 0x08
+
 struct ReadStream;
 typedef struct ReadStream ReadStream;
 
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 9840060997f..b5b547f9e89 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2378,6 +2378,7 @@ ReadFunc
 ReadLocalXLogPageNoWaitPrivate
 ReadReplicationSlotCmd
 ReadStream
+ReadStreamAdviceLevel
 ReadStreamBlockNumberCB
 ReassignOwnedStmt
 RecheckForeignScan_function
-- 
2.34.1

v35-0001-Increase-default-effective_io_concurrency-to-16.patchtext/x-patch; charset=US-ASCII; name=v35-0001-Increase-default-effective_io_concurrency-to-16.patchDownload
From 7b35b1144bddf202fb4d56a9b783751a0945ba0e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Mar 2025 17:17:38 -0400
Subject: [PATCH v35 1/5] Increase default effective_io_concurrency to 16

The default effective_io_concurrency has been 1 since it was introduced
in b7b8f0b6096d2ab6e. Referencing the associated discussion [1], it
seems 1 was chosen as a conservative value that seemed unlikely to cause
regressions.

Experimentation on high latency cloud storage as well as fast, local
nvme storage (see Discussion link) shows that even slightly higher values
improve query timings substantially. 1 actually performs worse than 0.
With effective_io_concurrency 1, we are not prefetching enough to avoid
I/O stalls, but we are issuing extra syscalls.

Moreover, when bitmap heap scan is converted to using the read stream
API, a prefetch distance of 1 will prevent read combining which is quite
detrimental to performance.

The new default is 16, which should be more appropriate in the general
case while still avoiding flooding low IOPs devices with I/O requests.

[1] https://www.postgresql.org/message-id/flat/FDDBA24E-FF4D-4654-BA75-692B3BA71B97%40enterprisedb.com

Discussion: https://postgr.es/m/CAAKRu_Z%2BJa-mwXebOoOERMMUMvJeRhzTjad4dSThxG0JLXESxw%40mail.gmail.com
---
 doc/src/sgml/config.sgml                      | 38 +++++++++----------
 src/backend/utils/misc/postgresql.conf.sample |  2 +-
 src/include/storage/bufmgr.h                  |  2 +-
 3 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index d2fa5f7d1a9..8c4409fc8bf 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2577,36 +2577,32 @@ include_dir 'conf.d'
          Sets the number of concurrent disk I/O operations that
          <productname>PostgreSQL</productname> expects can be executed
          simultaneously.  Raising this value will increase the number of I/O
-         operations that any individual <productname>PostgreSQL</productname> session
-         attempts to initiate in parallel.  The allowed range is 1 to 1000,
-         or zero to disable issuance of asynchronous I/O requests. Currently,
-         this setting only affects bitmap heap scans.
+         operations that any individual <productname>PostgreSQL</productname>
+         session attempts to initiate in parallel.  The allowed range is
+         <literal>1</literal> to <literal>1000</literal>, or
+         <literal>0</literal> to disable issuance of asynchronous I/O requests.
+         The default is <literal>16</literal> on supported systems, otherwise
+         <literal>0</literal>. Currently, this setting only affects bitmap heap
+         scans.
         </para>
 
         <para>
-         For magnetic drives, a good starting point for this setting is the
-         number of separate
-         drives comprising a RAID 0 stripe or RAID 1 mirror being used for the
-         database.  (For RAID 5 the parity drive should not be counted.)
-         However, if the database is often busy with multiple queries issued in
-         concurrent sessions, lower values may be sufficient to keep the disk
-         array busy.  A value higher than needed to keep the disks busy will
-         only result in extra CPU overhead.
-         SSDs and other memory-based storage can often process many
-         concurrent requests, so the best value might be in the hundreds.
+         Higher values will have the most impact on higher latency storage
+         where queries otherwise experience noticeable I/O stalls and on
+         devices with high IOPs. Higher values than needed to satisfy the query
+         or keep the device busy can be expected to only introduce extra CPU
+         overhead.
         </para>
 
         <para>
-         Asynchronous I/O requires that the operating system supports issuing
-         read-ahead advice.  If there is no operating system support then
-         setting this parameter to anything but zero will result in an error.
+         On systems without prefetch advice support, attempting to configure
+         any value other than <literal>0</literal> will error out.
         </para>
 
         <para>
-         The default is 1 on supported systems, otherwise 0.  This value can
-         be overridden for tables in a particular tablespace by setting the
-         tablespace parameter of the same name (see
-         <xref linkend="sql-altertablespace"/>).
+         This value can be overridden for tables in a particular tablespace by
+         setting the tablespace parameter of the same name (see <xref
+         linkend="sql-altertablespace"/>).
         </para>
        </listitem>
       </varlistentry>
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 2d1de9c37bd..e2939079088 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -198,7 +198,7 @@
 # - I/O -
 
 #backend_flush_after = 0		# measured in pages, 0 disables
-#effective_io_concurrency = 1		# 1-1000; 0 disables prefetching
+#effective_io_concurrency = 16		# 1-1000; 0 disables prefetching
 #maintenance_io_concurrency = 10	# 1-1000; 0 disables prefetching
 #io_combine_limit = 128kB		# usually 1-32 blocks (depends on OS)
 
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 7c1e4316dde..b204e4731c1 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -152,7 +152,7 @@ extern PGDLLIMPORT bool track_io_timing;
 
 /* only applicable when prefetching is available */
 #ifdef USE_PREFETCH
-#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 1
+#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 16
 #define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10
 #else
 #define DEFAULT_EFFECTIVE_IO_CONCURRENCY 0
-- 
2.34.1

v35-0004-BitmapHeapScan-uses-the-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v35-0004-BitmapHeapScan-uses-the-read-stream-API.patchDownload
From 1eaea06936980651f44221f1dbab28a03e0b659f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:15:47 -0500
Subject: [PATCH v35 4/5] BitmapHeapScan uses the read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam.c          |  80 +++++
 src/backend/access/heap/heapam_handler.c  |  90 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 341 +---------------------
 src/include/access/tableam.h              |  25 +-
 src/include/nodes/execnodes.h             |  23 +-
 5 files changed, 124 insertions(+), 435 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index fa7935a0ed3..e06cddb1220 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,72 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		/* no more entries in the bitmap */
+		if (!tbm_iterate(&sscan->st.rs_tbmiterator, tbmres))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+			int			noffsets;
+
+			/* can't be lossy in the skip_fetch case */
+			Assert(!tbmres->lossy);
+			Assert(bscan->rs_empty_tuples_pending >= 0);
+
+			/*
+			 * We throw away the offsets, but this is the easiest way to get a
+			 * count of tuples.
+			 */
+			noffsets = tbm_extract_page_tuple(tbmres, offsets, TBM_MAX_TUPLES_PER_PAGE);
+			bscan->rs_empty_tuples_pending += noffsets;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1133,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1213,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_RANDOM,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1257,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ff1d8085883..0f7dd79f28e 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2117,82 +2117,72 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			noffsets = -1;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
-			return false;
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
 
-		/* Exact pages need their tuple offsets extracted. */
-		if (!tbmres.lossy)
-			noffsets = tbm_extract_page_tuple(&tbmres, offsets,
-											  TBM_MAX_TUPLES_PER_PAGE);
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres.lossy);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
-		Assert(noffsets > -1);
+	tbmres = per_buffer_data;
 
-		bscan->rs_empty_tuples_pending += noffsets;
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	/* Exact pages need their tuple offsets extracted. */
+	if (!tbmres->lossy)
+		noffsets = tbm_extract_page_tuple(tbmres, offsets,
+										  TBM_MAX_TUPLES_PER_PAGE);
 
-	block = tbmres.blockno;
+	*recheck = tbmres->recheck;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = hscan->rs_cblock = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2213,7 +2203,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres.lossy)
+	if (!tbmres->lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2277,7 +2267,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.lossy)
+	if (tbmres->lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3b4ea0f6144..6df34094a13 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -158,7 +129,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +142,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -204,37 +170,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -257,31 +192,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,225 +224,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					/* No more pages to prefetch */
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -580,24 +280,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -666,17 +354,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -709,18 +391,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -760,13 +437,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -870,12 +540,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -912,17 +579,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..507d4ebe68f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -1966,16 +1950,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1968,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a323fa98bbb..5f743d6699c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1828,11 +1828,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1840,10 +1836,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1867,18 +1860,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1886,18 +1872,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

v35-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v35-0003-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From f1eba8bcadaae3ed2e49cc390162a543980c641b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:30:26 -0500
Subject: [PATCH v35 3/5] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This allows tidbitmap API users to manage multiple TBMIterateResults per
scan. This is required for bitmap heap scan to use the read stream API,
with which there may be multiple I/Os in flight at once, each one with a
TBMIterateResult.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/gin/ginget.c           | 33 ++++----
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 28 +++----
 src/backend/executor/nodeBitmapHeapscan.c | 39 +++++----
 src/backend/nodes/tidbitmap.c             | 96 ++++++++++++-----------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 110 insertions(+), 101 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 4a56f19390d..f29ccd3c2d1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,8 +332,8 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->matchNtuples = -1;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -827,20 +827,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult.blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (!entry->matchResult->lossy &&
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (!entry->matchResult.lossy &&
 					entry->offset >= entry->matchNtuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
-
-				if (entry->matchResult == NULL)
+				if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult))
 				{
+					Assert(!BlockNumberIsValid(entry->matchResult.blockno));
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
@@ -849,14 +848,14 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				}
 
 				/* Exact pages need their tuple offsets extracted. */
-				if (!entry->matchResult->lossy)
-					entry->matchNtuples = tbm_extract_page_tuple(entry->matchResult,
+				if (!entry->matchResult.lossy)
+					entry->matchNtuples = tbm_extract_page_tuple(&entry->matchResult,
 																 entry->matchOffsets,
 																 TBM_MAX_TUPLES_PER_PAGE);
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than entry->matchNtuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -869,10 +868,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->lossy)
+			if (entry->matchResult.lossy)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -889,7 +888,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			Assert(entry->matchNtuples > -1);
 
 			/* Skip over any offsets <= advancePast, and return that. */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				Assert(entry->matchNtuples > 0);
 
@@ -910,7 +909,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
+						   entry->matchResult.blockno,
 						   entry->matchOffsets[entry->offset]);
 			entry->offset++;
 
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 84aa14594f8..2257b7c0480 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -111,7 +111,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->matchNtuples = -1;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index e78682c3cef..ff1d8085883 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			noffsets = -1;
 
@@ -2142,14 +2142,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
-
-		if (tbmres == NULL)
+		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
 			return false;
 
 		/* Exact pages need their tuple offsets extracted. */
-		if (!tbmres->lossy)
-			noffsets = tbm_extract_page_tuple(tbmres, offsets,
+		if (!tbmres.lossy)
+			noffsets = tbm_extract_page_tuple(&tbmres, offsets,
 											  TBM_MAX_TUPLES_PER_PAGE);
 
 		/*
@@ -2161,11 +2159,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2173,11 +2171,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres->lossy);
+		Assert(!tbmres.lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 		Assert(noffsets > -1);
 
@@ -2186,7 +2184,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2215,7 +2213,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres->lossy)
+	if (!tbmres.lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,7 +2277,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->lossy)
+	if (tbmres.lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..3b4ea0f6144 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,18 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
 					/* No more pages to prefetch */
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3d835024caa..41031aa8f2f 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -957,21 +955,28 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If lossy is true, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  result->ntuples is set to -1 when the bitmap is lossy.
- * If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when lossy is true.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.
+ *
+ * Returns false when there are no more pages to scan and true otherwise. When
+ * there are no more pages to scan, tbmres->blockno is set to
+ * InvalidBlockNumber.
+ *
+ * If lossy is true, then the bitmap is "lossy" and failed to remember
+ * the exact tuples to look at on this page --- the caller must examine all
+ * tuples on the page and check if they meet the intended condition. If lossy
+ * is false, the caller must later extract the tuple offsets from the page
+ * pointed to by internal_page with tbm_extract_page_tuple.
+ *
+ * If tbmres->recheck is true, only the indicated tuples need be examined, but
+ * the condition must be rechecked anyway.  (For ease of testing, recheck is
+ * always set true when lossy is true.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+bool
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -1009,12 +1014,12 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			iterator->schunkbit++;
-			return output;
+			return true;
 		}
 	}
 
@@ -1028,16 +1033,17 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return true;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1047,10 +1053,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+bool
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1101,14 +1106,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return true;
 		}
 	}
 
@@ -1116,21 +1121,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return true;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1604,15 +1610,17 @@ tbm_end_iterate(TBMIterator *iterator)
 }
 
 /*
- * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ * Populate the next TBMIterateResult using the shared or private bitmap
+ * iterator. Returns false when there is nothing more to scan.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+bool
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 95d8805b66f..aee1f70c22e 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -354,7 +354,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 	OffsetNumber matchOffsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			matchNtuples;
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index e185635c10b..99f795ceab5 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -101,8 +101,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -113,7 +113,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern bool tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v35-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v35-0005-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From ac540e4ff062060ff81807e9f978cd16c62de339 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:32:33 -0500
Subject: [PATCH v35 5/5] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator into table-AM specific code (as part
of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer returns the current block number.
Since scan_bitmap_next_block() isn't returning any relevant information
to bitmap table scan code, it makes more sense to get rid of it.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple(),
and the heap AM implementation of scan_bitmap_next_block() is a local
helper in heapam_handler.c.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam_handler.c  | 372 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   3 -
 src/backend/executor/nodeBitmapHeapscan.c |  73 ++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 244 insertions(+), 296 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 0f7dd79f28e..c4f5d7307b4 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,10 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,198 +2120,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
-	int			noffsets = -1;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
-											 &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BlockNumberIsValid(tbmres->blockno));
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	/* Exact pages need their tuple offsets extracted. */
-	if (!tbmres->lossy)
-		noffsets = tbm_extract_page_tuple(tbmres, offsets,
-										  TBM_MAX_TUPLES_PER_PAGE);
-
-	*recheck = tbmres->recheck;
-
-	block = hscan->rs_cblock = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (!tbmres->lossy)
-	{
-		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		/* We must have extracted the tuple offsets by now */
-		Assert(noffsets > -1);
-
-		for (curslot = 0; curslot < noffsets; curslot++)
-		{
-			OffsetNumber offnum = offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
 
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->lossy)
-		(*lossy_pages)++;
-	else
-		(*exact_pages)++;
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
-
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2614,6 +2464,177 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+	int			noffsets = -1;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	/* Exact pages need their tuple offsets extracted. */
+	if (!tbmres->lossy)
+		noffsets = tbm_extract_page_tuple(tbmres, offsets,
+										  TBM_MAX_TUPLES_PER_PAGE);
+
+	*recheck = tbmres->recheck;
+
+	block = hscan->rs_cblock = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (!tbmres->lossy)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		/* We must have extracted the tuple offsets by now */
+		Assert(noffsets > -1);
+
+		for (curslot = 0; curslot < noffsets; curslot++)
+		{
+			OffsetNumber offnum = offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->lossy)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2673,7 +2694,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..476663b66aa 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6df34094a13..3e33360c0fc 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -138,69 +138,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-
-			CHECK_FOR_INTERRUPTS();
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 507d4ebe68f..b8cb1e744ad 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. These are tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1939,51 +1919,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1994,7 +1947,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

#219Andres Freund
andres@anarazel.de
In reply to: Melanie Plageman (#218)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-03-10 19:45:38 -0400, Melanie Plageman wrote:

From 7b35b1144bddf202fb4d56a9b783751a0945ba0e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Mar 2025 17:17:38 -0400
Subject: [PATCH v35 1/5] Increase default effective_io_concurrency to 16

The default effective_io_concurrency has been 1 since it was introduced
in b7b8f0b6096d2ab6e. Referencing the associated discussion [1], it
seems 1 was chosen as a conservative value that seemed unlikely to cause
regressions.

16 years...

Experimentation on high latency cloud storage as well as fast, local
nvme storage (see Discussion link) shows that even slightly higher values
improve query timings substantially. 1 actually performs worse than 0.
With effective_io_concurrency 1, we are not prefetching enough to avoid
I/O stalls, but we are issuing extra syscalls.

Makes sense.

Moreover, when bitmap heap scan is converted to using the read stream
API, a prefetch distance of 1 will prevent read combining which is quite
detrimental to performance.

Hm? This one surprises me. Doesn't the read stream code take some pains to
still perform IO combining when effective_io_concurrency=1? It does work for
seqscans, for example?

The new default is 16, which should be more appropriate in the general
case while still avoiding flooding low IOPs devices with I/O requests.

Maybe s/in the general case/for common hardware/?

[1] /messages/by-id/FDDBA24E-FF4D-4654-BA75-692B3BA71B97@enterprisedb.com

Discussion: /messages/by-id/CAAKRu_Z+Ja-mwXebOoOERMMUMvJeRhzTjad4dSThxG0JLXESxw@mail.gmail.com
---
doc/src/sgml/config.sgml | 38 +++++++++----------
src/backend/utils/misc/postgresql.conf.sample | 2 +-
src/include/storage/bufmgr.h | 2 +-
3 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index d2fa5f7d1a9..8c4409fc8bf 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2577,36 +2577,32 @@ include_dir 'conf.d'
Sets the number of concurrent disk I/O operations that
<productname>PostgreSQL</productname> expects can be executed
simultaneously.  Raising this value will increase the number of I/O
-         operations that any individual <productname>PostgreSQL</productname> session
-         attempts to initiate in parallel.  The allowed range is 1 to 1000,
-         or zero to disable issuance of asynchronous I/O requests. Currently,
-         this setting only affects bitmap heap scans.
+         operations that any individual <productname>PostgreSQL</productname>
+         session attempts to initiate in parallel.  The allowed range is
+         <literal>1</literal> to <literal>1000</literal>, or
+         <literal>0</literal> to disable issuance of asynchronous I/O requests.
+         The default is <literal>16</literal> on supported systems, otherwise
+         <literal>0</literal>. Currently, this setting only affects bitmap heap
+         scans.
</para>

I'd probably use this as an occasion to remove "Currently, this setting only
affects bitmap heap" sentence - afaict it's been wrong for a while and got
more wrong since vacuum started to use read streams...

<para>
- For magnetic drives, a good starting point for this setting is the
- number of separate
- drives comprising a RAID 0 stripe or RAID 1 mirror being used for the
- database. (For RAID 5 the parity drive should not be counted.)
- However, if the database is often busy with multiple queries issued in
- concurrent sessions, lower values may be sufficient to keep the disk
- array busy. A value higher than needed to keep the disks busy will
- only result in extra CPU overhead.
- SSDs and other memory-based storage can often process many
- concurrent requests, so the best value might be in the hundreds.

Afaict this whole paragraph was *never* correct... Obviously that's not
criticism of your removing it ;)

+         Higher values will have the most impact on higher latency storage
+         where queries otherwise experience noticeable I/O stalls and on
+         devices with high IOPs. Higher values than needed to satisfy the query
+         or keep the device busy can be expected to only introduce extra CPU
+         overhead.
</para>

I'd say unnecessarily high values also can increase IO latency.

Greetings,

Andres Freund

#220Melanie Plageman
melanieplageman@gmail.com
In reply to: Andres Freund (#219)
Re: BitmapHeapScan streaming read user and prelim refactoring

Thanks for taking a look. I've pushed the patch to increase the
default effective_io_concurrency.

On Tue, Mar 11, 2025 at 8:07 PM Andres Freund <andres@anarazel.de> wrote:

On 2025-03-10 19:45:38 -0400, Melanie Plageman wrote:

From 7b35b1144bddf202fb4d56a9b783751a0945ba0e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 10 Mar 2025 17:17:38 -0400
Subject: [PATCH v35 1/5] Increase default effective_io_concurrency to 16

Moreover, when bitmap heap scan is converted to using the read stream
API, a prefetch distance of 1 will prevent read combining which is quite
detrimental to performance.

Hm? This one surprises me. Doesn't the read stream code take some pains to
still perform IO combining when effective_io_concurrency=1? It does work for
seqscans, for example?

I went back and tried to figure out what I meant by this. When Thomas
and I were investigating various BHS regressions, we did see that
effective_io_concurrency 1 performed particularly badly on the read
stream branch (as compared to master). One thing we noticed was very
little read combining (especially for parallel bitmap heap scan, but
that's a separate bundle of issues). Re-reading the read stream code,
though, you are right that we should have no issue read combining when
eic is 1. In that case, with the default io_combine_limit, max pinned
buffers will be 32, which is definitely enough for read combining.

Anyway, I've removed this text from the commit message.

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index d2fa5f7d1a9..8c4409fc8bf 100644
--- a/doc/src/sgml/config.sgml

<-- snip-->

+         <literal>0</literal> to disable issuance of asynchronous I/O requests.
+         The default is <literal>16</literal> on supported systems, otherwise
+         <literal>0</literal>. Currently, this setting only affects bitmap heap
+         scans.
</para>

I'd probably use this as an occasion to remove "Currently, this setting only
affects bitmap heap" sentence - afaict it's been wrong for a while and got
more wrong since vacuum started to use read streams...

Well, technically vacuum uses maintenance_io_concurrency. Bitmap heap
scan is the only one using effective_io_concurrency for prefetching
(since sequential scan doesn't do prefetching). So, it is technically
true. Sequential scans will try to combine IOs only up to the
io_combine_limit so effective_io_concurrency doesn't really matter for
them. I removed this sentence anyway, though. Other read stream users
(including non-in-core ones) could start using
effective_io_concurrency and then it might be more confusing anyway.

- Melanie

#221Jakub Wartak
jakub.wartak@enterprisedb.com
In reply to: Melanie Plageman (#220)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Mar 12, 2025 at 9:02 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Thanks for taking a look. I've pushed the patch to increase the
default effective_io_concurrency.

Cool, anything > 1 is just better. Just quick question, so now we have:

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 16
#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10

Shouldn't maintenance be now also at the same value (16) instead of
10? Also, fc34b0d9de27 (5 years ago by Thomas) states about m_io_c:
"Use the new setting in heapam.c instead of the hard-coded formula
effective_io_concurrency + 10 introduced by commit 558a9165e08.", so
there was always assumption that m_io_c > e_io_c (?) Now it's kind of
inconsistent to see bitmap heap scans pushing more IOPs than
recovery(!)/ANALYZE/VACUUM or am I missing something? No pressure to
change, just asking what Your thoughts are.

-J.

#222Melanie Plageman
melanieplageman@gmail.com
In reply to: Jakub Wartak (#221)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Mar 13, 2025 at 5:46 AM Jakub Wartak
<jakub.wartak@enterprisedb.com> wrote:

Cool, anything > 1 is just better. Just quick question, so now we have:

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 16
#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10

Shouldn't maintenance be now also at the same value (16) instead of
10? Also, fc34b0d9de27 (5 years ago by Thomas) states about m_io_c:
"Use the new setting in heapam.c instead of the hard-coded formula
effective_io_concurrency + 10 introduced by commit 558a9165e08.", so
there was always assumption that m_io_c > e_io_c (?) Now it's kind of
inconsistent to see bitmap heap scans pushing more IOPs than
recovery(!)/ANALYZE/VACUUM or am I missing something? No pressure to
change, just asking what Your thoughts are.

Yea, I'm not really sure what if any relationship the two GUCs should
have to one another. As long as they are in the same ballpark, since
they are tuning for the same machine, I don't see any reason their
values need to be adjusted together. However, if it is confusing for
maintenance_io_concurrency default to be 10 while
effective_io_concurrency default is 16, I'm happy to change it. I just
don't quite know what I would write in the commit message. "it seemed
confusing that they weren't the same?"

- Melanie

#223Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#218)
10 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 10, 2025 at 7:45 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Attached v35 0003-0005 is the same as v34 but is on top of two new
commits: 0001 increases the default effective_io_concurrency to 16 and
0002 adds a READ_STREAM_RANDOM flag which disables sequential
detection and is used by bitmap heap scan.

Attached v36 is built on top of the read stream updates Thomas posted
earlier today in [1]/messages/by-id/CA+hUKGKH2mwj=mpCobC4ZyBdR4ToW2hpQcYFDivj40fxf4yQow@mail.gmail.com. I've been doing some performance testing and
from what I see, we've closed the major gaps.

The case I was most concerned about was cyclic data (narrow bands of
sequential data in a larger random dataset) with reasonable values for
io_combine_limit, effective_io_concurrency, and OS read ahead. I've
attached a chart which compares the query time for master, my original
bitmap heap scan streaming read user "og", the bitmap heap scan
streaming read user with sequential detection turned off completely
"random", and the bitmap heap scan streaming read user with the
updated read stream changes Thomas posted today "rsupdate". You can
see that it eliminates the regression.

For some of the other cases, because we still do sequential detection
with Thomas' changes, we sometimes pause prefetching which means if
you have turned off OS read ahead, then it'll be slower than without
the read stream user. That's okay, though -- in the vastly more common
case of OS readahead being enabled, we can avoid unnecessary
prefetching and beat current master.

Overall, I feel pretty good about merging this once Thomas merges the
read stream patches.

- Melanie

[1]: /messages/by-id/CA+hUKGKH2mwj=mpCobC4ZyBdR4ToW2hpQcYFDivj40fxf4yQow@mail.gmail.com

Attachments:

v36-0005-Support-buffer-forwarding-in-read_stream.c.patchtext/x-patch; charset=US-ASCII; name=v36-0005-Support-buffer-forwarding-in-read_stream.c.patchDownload
From eea764665d042b793138f857e58ca3656bf05519 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 30 Jan 2025 11:42:03 +1300
Subject: [PATCH v36 5/9] Support buffer forwarding in read_stream.c.

In preparation for a following change to the buffer manager, teach read
stream to keep track of buffers that were "forwarded" from one call to
StartReadBuffers() to the next.

Since StartReadBuffers() buffers argument will become an in/out
argument, we need to initialize the buffer queue entries with
InvalidBuffer.  We don't want to do that up front, because we try to
keep stream initialization cheap and code that uses the fast path stays
in one single buffer queue element.  Satisfy both goals by initializing
the queue incrementally on the first cycle.

Discussion: https://postgr.es/m/CA%2BhUKGK_%3D4CVmMHvsHjOVrK6t4F%3DLBpFzsrr3R%2BaJYN8kcTfWg%40mail.gmail.com
---
 src/backend/storage/aio/read_stream.c | 102 +++++++++++++++++++++++---
 1 file changed, 92 insertions(+), 10 deletions(-)

diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index 57cde89cfdc..51c15330117 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -95,8 +95,10 @@ struct ReadStream
 	int16		ios_in_progress;
 	int16		queue_size;
 	int16		max_pinned_buffers;
+	int16		forwarded_buffers;
 	int16		pinned_buffers;
 	int16		distance;
+	int16		initialized_buffers;
 	bool		advice_enabled;
 	bool		temporary;
 
@@ -223,8 +225,10 @@ static bool
 read_stream_start_pending_read(ReadStream *stream)
 {
 	bool		need_wait;
+	int			requested_nblocks;
 	int			nblocks;
 	int			flags = 0;
+	int			forwarded;
 	int16		io_index;
 	int16		overflow;
 	int16		buffer_index;
@@ -275,11 +279,19 @@ read_stream_start_pending_read(ReadStream *stream)
 		}
 	}
 
-	/* Compute the remaining portion of the per-backend buffer limit. */
+	/*
+	 * Compute the remaining portion of the per-backend buffer limit.  If we
+	 * already have some forwarded buffers, we can certainly use those.  They
+	 * are already pinned, and are mapped to the starting blocks of the pending
+	 * read, they just don't have any I/O started yet and are not counted in
+	 * stream->pinned_buffers.
+	 */
 	if (stream->temporary)
 		buffer_limit = Min(GetAdditionalLocalPinLimit(), PG_INT16_MAX);
 	else
 		buffer_limit = Min(GetAdditionalPinLimit(), PG_INT16_MAX);
+	Assert(stream->forwarded_buffers <= stream->pending_read_nblocks);
+	buffer_limit += stream->forwarded_buffers;
 	if (buffer_limit == 0 && stream->pinned_buffers == 0)
 		buffer_limit = 1;		/* guarantee progress */
 
@@ -306,8 +318,31 @@ read_stream_start_pending_read(ReadStream *stream)
 	 * We say how many blocks we want to read, but it may be smaller on return
 	 * if the buffer manager decides it needs a short read at its level.
 	 */
+	requested_nblocks = Min(buffer_limit, stream->pending_read_nblocks);
+	nblocks = requested_nblocks;
 	buffer_index = stream->next_buffer_index;
 	io_index = stream->next_io_index;
+
+	/*
+	 * The first time around the queue we initialize it as we go, including
+	 * the overflow zone, because otherwise the entries would appear as
+	 * forwarded buffers.  This avoids initializing the whole queue up front
+	 * in cases where it is large but we don't ever use it due to the
+	 * all-cached fast path or small scans.
+	 */
+	while (stream->initialized_buffers < buffer_index + nblocks)
+		stream->buffers[stream->initialized_buffers++] = InvalidBuffer;
+
+	/*
+	 * Start the I/O.  Any buffers that are not InvalidBuffer will be
+	 * interpreted as already pinned, forwarded by an earlier call to
+	 * StartReadBuffers(), and must map to the expected blocks.  The nblocks
+	 * value may be smaller on return indicating the size of the I/O that
+	 * could be started.  Buffers beyond the output nblocks number may also
+	 * have been pinned without starting I/O due to various edge cases.  In
+	 * that case we'll just leave them in the queue ahead of us, "forwarded"
+	 * to the next call, avoiding the need to unpin/repin.
+	 */
 	need_wait = StartReadBuffers(&stream->ios[io_index].op,
 								 &stream->buffers[buffer_index],
 								 stream->pending_read_blocknum,
@@ -336,16 +371,35 @@ read_stream_start_pending_read(ReadStream *stream)
 		stream->seq_blocknum = stream->pending_read_blocknum + nblocks;
 	}
 
+	/*
+	 * How many pins were acquired but forwarded to the next call?  These need
+	 * to be passed to the next StartReadBuffers() call, or released if the
+	 * stream ends early.  We need the number for accounting purposes, since
+	 * they are not counted in stream->pinned_buffers but we already hold
+	 * them.
+	 */
+	forwarded = 0;
+	while (nblocks + forwarded < requested_nblocks &&
+		   stream->buffers[buffer_index + nblocks + forwarded] != InvalidBuffer)
+		forwarded++;
+	stream->forwarded_buffers = forwarded;
+
 	/*
 	 * We gave a contiguous range of buffer space to StartReadBuffers(), but
-	 * we want it to wrap around at queue_size.  Slide overflowing buffers to
-	 * the front of the array.
+	 * we want it to wrap around at queue_size.  Copy overflowing buffers to
+	 * the front of the array where they'll be consumed, but also leave a copy
+	 * in the overflow zone which the I/O operation has a pointer to (it needs
+	 * a contiguous array).  Both copies will be cleared when the buffers are
+	 * handed to the consumer.
 	 */
-	overflow = (buffer_index + nblocks) - stream->queue_size;
+	overflow = (buffer_index + nblocks + forwarded) - stream->queue_size;
 	if (overflow > 0)
-		memmove(&stream->buffers[0],
-				&stream->buffers[stream->queue_size],
-				sizeof(stream->buffers[0]) * overflow);
+	{
+		Assert(overflow < stream->queue_size);	/* can't overlap */
+		memcpy(&stream->buffers[0],
+			   &stream->buffers[stream->queue_size],
+			   sizeof(stream->buffers[0]) * overflow);
+	}
 
 	/* Compute location of start of next read, without using % operator. */
 	buffer_index += nblocks;
@@ -730,10 +784,12 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 
 		/* Fast path assumptions. */
 		Assert(stream->ios_in_progress == 0);
+		Assert(stream->forwarded_buffers == 0);
 		Assert(stream->pinned_buffers == 1);
 		Assert(stream->distance == 1);
 		Assert(stream->pending_read_nblocks == 0);
 		Assert(stream->per_buffer_data_size == 0);
+		Assert(stream->initialized_buffers > stream->oldest_buffer_index);
 
 		/* We're going to return the buffer we pinned last time. */
 		oldest_buffer_index = stream->oldest_buffer_index;
@@ -782,6 +838,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 			stream->distance = 0;
 			stream->oldest_buffer_index = stream->next_buffer_index;
 			stream->pinned_buffers = 0;
+			stream->buffers[oldest_buffer_index] = InvalidBuffer;
 		}
 
 		stream->fast_path = false;
@@ -858,10 +915,15 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 			stream->seq_until_processed = InvalidBlockNumber;
 	}
 
-#ifdef CLOBBER_FREED_MEMORY
-	/* Clobber old buffer for debugging purposes. */
+	/*
+	 * We must zap this queue entry, or else it would appear as a forwarded
+	 * buffer.  If it's potentially in the overflow zone (ie it wrapped around
+	 * the queue), also zap that copy.
+	 */
 	stream->buffers[oldest_buffer_index] = InvalidBuffer;
-#endif
+	if (oldest_buffer_index < io_combine_limit - 1)
+		stream->buffers[stream->queue_size + oldest_buffer_index] =
+			InvalidBuffer;
 
 #if defined(CLOBBER_FREED_MEMORY) || defined(USE_VALGRIND)
 
@@ -906,6 +968,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 #ifndef READ_STREAM_DISABLE_FAST_PATH
 	/* See if we can take the fast path for all-cached scans next time. */
 	if (stream->ios_in_progress == 0 &&
+		stream->forwarded_buffers == 0 &&
 		stream->pinned_buffers == 1 &&
 		stream->distance == 1 &&
 		stream->pending_read_nblocks == 0 &&
@@ -941,6 +1004,7 @@ read_stream_next_block(ReadStream *stream, BufferAccessStrategy *strategy)
 void
 read_stream_reset(ReadStream *stream)
 {
+	int16		index;
 	Buffer		buffer;
 
 	/* Stop looking ahead. */
@@ -957,6 +1021,24 @@ read_stream_reset(ReadStream *stream)
 	while ((buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer)
 		ReleaseBuffer(buffer);
 
+	/* Unpin any unused forwarded buffers. */
+	index = stream->next_buffer_index;
+	while (index < stream->initialized_buffers &&
+		   (buffer = stream->buffers[index]) != InvalidBuffer)
+	{
+		Assert(stream->forwarded_buffers > 0);
+		stream->forwarded_buffers--;
+		ReleaseBuffer(buffer);
+
+		stream->buffers[index] = InvalidBuffer;
+		if (index < io_combine_limit - 1)
+			stream->buffers[stream->queue_size + index] = InvalidBuffer;
+
+		if (++index == stream->queue_size)
+			index = 0;
+	}
+
+	Assert(stream->forwarded_buffers == 0);
 	Assert(stream->pinned_buffers == 0);
 	Assert(stream->ios_in_progress == 0);
 
-- 
2.34.1

v36-0002-Respect-pin-limits-accurately-in-read_stream.c.patchtext/x-patch; charset=US-ASCII; name=v36-0002-Respect-pin-limits-accurately-in-read_stream.c.patchDownload
From d739172daa7cefa550ebc137226077f7a43ceffd Mon Sep 17 00:00:00 2001
From: Thomas Munro <tmunro@postgresql.org>
Date: Thu, 27 Feb 2025 21:42:05 +1300
Subject: [PATCH v36 2/9] Respect pin limits accurately in read_stream.c.

To avoid pinning too much of the buffer pool at once, we previously used
LimitAdditionalBuffers().  The coding was naive, and only considered the
available buffers at stream construction time.

This commit checks at the time of use with new buffer manager APIs.  The
result might change dynamically due to pins acquired outside this stream
by the same backend.  No extra CPU cycles are added to the all-buffered
fast-path code, but the I/O-starting path now considers the up-to-date
remaining buffer limit when making look-ahead decisions.

In practice it was very difficult to exceed the limit in v17, so no
back-patch, but changes due to land soon make it easy.

Per code review from Andres, in the course of testing his AIO patches.

Reviewed-by: Andres Freund <andres@anarazel.de>
Reported-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CA%2BhUKGK_%3D4CVmMHvsHjOVrK6t4F%3DLBpFzsrr3R%2BaJYN8kcTfWg%40mail.gmail.com
---
 src/backend/storage/aio/read_stream.c | 104 ++++++++++++++++++++++----
 1 file changed, 90 insertions(+), 14 deletions(-)

diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index 36fb9fe152c..11ee16ec228 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -116,6 +116,7 @@ struct ReadStream
 	int16		pinned_buffers;
 	int16		distance;
 	bool		advice_enabled;
+	bool		temporary;
 
 	/*
 	 * One-block buffer to support 'ungetting' a block number, to resolve flow
@@ -225,7 +226,17 @@ read_stream_unget_block(ReadStream *stream, BlockNumber blocknum)
 	stream->buffered_blocknum = blocknum;
 }
 
-static void
+/*
+ * Start as much of the current pending read as we can.  If we have to split it
+ * because of the per-backend buffer limit, or the buffer manager decides to
+ * split it, then the pending read is adjusted to hold the remaining portion.
+ *
+ * We can always start a read of at least size one if we have no progress yet.
+ * Otherwise it's possible that we can't start a read at all because of a lack
+ * of buffers, and then false is returned.  Buffer shortages also reduce the
+ * distance to a level that prevents look-ahead until buffers are released.
+ */
+static bool
 read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 {
 	bool		need_wait;
@@ -234,12 +245,13 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 	int16		io_index;
 	int16		overflow;
 	int16		buffer_index;
+	int16		buffer_limit;
 
 	/* This should only be called with a pending read. */
 	Assert(stream->pending_read_nblocks > 0);
 	Assert(stream->pending_read_nblocks <= stream->io_combine_limit);
 
-	/* We had better not exceed the pin limit by starting this read. */
+	/* We had better not exceed the per-stream buffer limit with this read. */
 	Assert(stream->pinned_buffers + stream->pending_read_nblocks <=
 		   stream->max_pinned_buffers);
 
@@ -260,10 +272,39 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 	else
 		flags = 0;
 
-	/* We say how many blocks we want to read, but may be smaller on return. */
+	/* Compute the remaining portion of the per-backend buffer limit. */
+	if (stream->temporary)
+		buffer_limit = Min(GetAdditionalLocalPinLimit(), PG_INT16_MAX);
+	else
+		buffer_limit = Min(GetAdditionalPinLimit(), PG_INT16_MAX);
+	if (buffer_limit == 0 && stream->pinned_buffers == 0)
+		buffer_limit = 1;		/* guarantee progress */
+
+	/* Does the per-backend buffer limit affect this read? */
+	nblocks = stream->pending_read_nblocks;
+	if (buffer_limit < nblocks)
+	{
+		int16		new_distance;
+
+		/* Shrink distance: no more look-ahead until buffers are released. */
+		new_distance = stream->pinned_buffers + buffer_limit;
+		if (stream->distance > new_distance)
+			stream->distance = new_distance;
+
+		/* If we've already made progress, just give up and wait for buffers. */
+		if (stream->pinned_buffers > 0)
+			return false;
+
+		/* A short read is required to make progress. */
+		nblocks = buffer_limit;
+	}
+
+	/*
+	 * We say how many blocks we want to read, but it may be smaller on return
+	 * if the buffer manager decides it needs a short read at its level.
+	 */
 	buffer_index = stream->next_buffer_index;
 	io_index = stream->next_io_index;
-	nblocks = stream->pending_read_nblocks;
 	need_wait = StartReadBuffers(&stream->ios[io_index].op,
 								 &stream->buffers[buffer_index],
 								 stream->pending_read_blocknum,
@@ -313,6 +354,8 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 	/* Adjust the pending read to cover the remaining portion, if any. */
 	stream->pending_read_blocknum += nblocks;
 	stream->pending_read_nblocks -= nblocks;
+
+	return true;
 }
 
 static void
@@ -361,14 +404,15 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
 		/* We have to start the pending read before we can build another. */
 		while (stream->pending_read_nblocks > 0)
 		{
-			read_stream_start_pending_read(stream, suppress_advice);
-			suppress_advice = false;
-			if (stream->ios_in_progress == stream->max_ios)
+			if (!read_stream_start_pending_read(stream, suppress_advice) ||
+				stream->ios_in_progress == stream->max_ios)
 			{
-				/* And we've hit the limit.  Rewind, and stop here. */
+				/* And we've hit a buffer or I/O limit.  Rewind and wait. */
 				read_stream_unget_block(stream, blocknum);
 				return;
 			}
+
+			suppress_advice = false;
 		}
 
 		/* This is the start of a new pending read. */
@@ -382,15 +426,25 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
 	 * io_combine_limit size once more buffers have been consumed.  However,
 	 * if we've already reached io_combine_limit, or we've reached the
 	 * distance limit and there isn't anything pinned yet, or the callback has
-	 * signaled end-of-stream, we start the read immediately.
+	 * signaled end-of-stream, we start the read immediately.  Note that the
+	 * pending read could even exceed the distance goal, if the latter was
+	 * reduced on buffer limit exhaustion.
 	 */
 	if (stream->pending_read_nblocks > 0 &&
 		(stream->pending_read_nblocks == stream->io_combine_limit ||
-		 (stream->pending_read_nblocks == stream->distance &&
+		 (stream->pending_read_nblocks >= stream->distance &&
 		  stream->pinned_buffers == 0) ||
 		 stream->distance == 0) &&
 		stream->ios_in_progress < stream->max_ios)
 		read_stream_start_pending_read(stream, suppress_advice);
+
+	/*
+	 * There should always be something pinned when we leave this function,
+	 * whether started by this call or not, unless we've hit the end of the
+	 * stream.  In the worst case we can always make progress one buffer at a
+	 * time.
+	 */
+	Assert(stream->pinned_buffers > 0 || stream->distance == 0);
 }
 
 /*
@@ -420,6 +474,7 @@ read_stream_begin_impl(int flags,
 	int			max_ios;
 	int			strategy_pin_limit;
 	uint32		max_pinned_buffers;
+	uint32		max_possible_buffer_limit;
 	Oid			tablespace_id;
 
 	/*
@@ -475,12 +530,23 @@ read_stream_begin_impl(int flags,
 	strategy_pin_limit = GetAccessStrategyPinLimit(strategy);
 	max_pinned_buffers = Min(strategy_pin_limit, max_pinned_buffers);
 
-	/* Don't allow this backend to pin more than its share of buffers. */
+	/*
+	 * Also limit our queue to the maximum number of pins we could possibly
+	 * ever be allowed to acquire according to the buffer manager.  We may not
+	 * really be able to use them all due to other pins held by this backend,
+	 * but we'll check that later in read_stream_start_pending_read().
+	 */
 	if (SmgrIsTemp(smgr))
-		LimitAdditionalLocalPins(&max_pinned_buffers);
+		max_possible_buffer_limit = GetSoftLocalPinLimit();
 	else
-		LimitAdditionalPins(&max_pinned_buffers);
-	Assert(max_pinned_buffers > 0);
+		max_possible_buffer_limit = GetSoftPinLimit();
+	max_pinned_buffers = Min(max_pinned_buffers, max_possible_buffer_limit);
+
+	/*
+	 * The soft limit might be zero on a system configured with more
+	 * connections than buffers.  We need at least one to make progress.
+	 */
+	max_pinned_buffers = Max(1, max_pinned_buffers);
 
 	/*
 	 * We need one extra entry for buffers and per-buffer data, because users
@@ -546,6 +612,7 @@ read_stream_begin_impl(int flags,
 	stream->callback = callback;
 	stream->callback_private_data = callback_private_data;
 	stream->buffered_blocknum = InvalidBlockNumber;
+	stream->temporary = SmgrIsTemp(smgr);
 
 	/*
 	 * Skip the initial ramp-up phase if the caller says we're going to be
@@ -674,6 +741,12 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 			 * arbitrary I/O entry (they're all free).  We don't have to
 			 * adjust pinned_buffers because we're transferring one to caller
 			 * but pinning one more.
+			 *
+			 * In the fast path we don't need to check the pin limit.  We're
+			 * always allowed at least one pin so that progress can be made,
+			 * and that's all we need here.  Although two pins are momentarily
+			 * held at the same time, the model used here is that the stream
+			 * holds only one, and the other now belongs to the caller.
 			 */
 			if (likely(!StartReadBuffer(&stream->ios[0].op,
 										&stream->buffers[oldest_buffer_index],
@@ -874,6 +947,9 @@ read_stream_reset(ReadStream *stream)
 	stream->buffered_blocknum = InvalidBlockNumber;
 	stream->fast_path = false;
 
+	/* There is no point in reading whatever was pending. */
+	stream->pending_read_nblocks = 0;
+
 	/* Unpin anything that wasn't consumed. */
 	while ((buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer)
 		ReleaseBuffer(buffer);
-- 
2.34.1

v36-0001-Improve-buffer-manager-API-for-backend-pin-limit.patchtext/x-patch; charset=US-ASCII; name=v36-0001-Improve-buffer-manager-API-for-backend-pin-limit.patchDownload
From 1e1c26ffe382dc6519e724d20b611fb1f0ee6c8c Mon Sep 17 00:00:00 2001
From: Thomas Munro <tmunro@postgresql.org>
Date: Thu, 27 Feb 2025 21:03:39 +1300
Subject: [PATCH v36 1/9] Improve buffer manager API for backend pin limits.

Previously the support functions assumed that the caller needed one pin
to make progress, and could optionally use some more.  Add a couple more
functions for callers that want to know:

* what the maximum possible number could be irrespective of currently
  held pins, for space planning purposes, called the "soft pin limit"

* how many additional pins they could acquire right now, without the
  special case allowing one pin, for users that already hold pins and
  could make progress even if zero extra pins are available

These APIs are better suited to read_stream.c, which will be improved in
a follow-up patch.  Also compute MaxProportionalPins up front, to avoid
performing division whenever we check the balance.

Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CA%2BhUKGK_%3D4CVmMHvsHjOVrK6t4F%3DLBpFzsrr3R%2BaJYN8kcTfWg%40mail.gmail.com
---
 src/backend/storage/buffer/bufmgr.c   | 85 +++++++++++++++++++--------
 src/backend/storage/buffer/localbuf.c | 16 +++++
 src/include/storage/bufmgr.h          |  4 ++
 3 files changed, 80 insertions(+), 25 deletions(-)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7915ed624c1..a6138e79306 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -211,6 +211,8 @@ static int32 PrivateRefCountOverflowed = 0;
 static uint32 PrivateRefCountClock = 0;
 static PrivateRefCountEntry *ReservedRefCountEntry = NULL;
 
+static uint32 MaxProportionalPins;
+
 static void ReservePrivateRefCountEntry(void);
 static PrivateRefCountEntry *NewPrivateRefCountEntry(Buffer buffer);
 static PrivateRefCountEntry *GetPrivateRefCountEntry(Buffer buffer, bool do_move);
@@ -2097,43 +2099,67 @@ again:
 	return buf;
 }
 
+/*
+ * Return the maximum number of buffer than this backend should try to pin at
+ * once, to avoid pinning more than its fair share.  This is the highest value
+ * that GetAdditionalPinLimit() and LimitAdditionalPins() could ever return.
+ *
+ * It's called a soft limit because nothing stops a backend from trying to
+ * acquire more pins than this if it needs them to make progress, but code that
+ * wants optional extra buffers for optimizations should respect this
+ * per-backend limit.
+ */
+uint32
+GetSoftPinLimit(void)
+{
+	return MaxProportionalPins;
+}
+
+/*
+ * Return the maximum number of additional buffers that this backend should
+ * pin if it wants to stay under the per-backend soft limit, considering the
+ * number of buffers it has already pinned.  Unlike LimitAdditionalPins(), the
+ * result can be zero, so the caller is expected to adjust it if required to
+ * make progress.
+ */
+uint32
+GetAdditionalPinLimit(void)
+{
+	uint32		estimated_pins_held;
+
+	/*
+	 * We get the number of "overflowed" pins for free, but don't know the
+	 * number of pins in PrivateRefCountArray.  The cost of calculating that
+	 * exactly doesn't seem worth it, so just assume the max.
+	 */
+	estimated_pins_held = PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES;
+
+	/* Is this backend already holding more than its fair share? */
+	if (estimated_pins_held > MaxProportionalPins)
+		return 0;
+
+	return MaxProportionalPins - estimated_pins_held;
+}
+
 /*
  * Limit the number of pins a batch operation may additionally acquire, to
  * avoid running out of pinnable buffers.
  *
- * One additional pin is always allowed, as otherwise the operation likely
- * cannot be performed at all.
- *
- * The number of allowed pins for a backend is computed based on
- * shared_buffers and the maximum number of connections possible. That's very
- * pessimistic, but outside of toy-sized shared_buffers it should allow
- * sufficient pins.
+ * One additional pin is always allowed, on the assumption that the operation
+ * requires at least one to make progress.
  */
 void
 LimitAdditionalPins(uint32 *additional_pins)
 {
-	uint32		max_backends;
-	int			max_proportional_pins;
+	uint32		limit;
 
 	if (*additional_pins <= 1)
 		return;
 
-	max_backends = MaxBackends + NUM_AUXILIARY_PROCS;
-	max_proportional_pins = NBuffers / max_backends;
-
-	/*
-	 * Subtract the approximate number of buffers already pinned by this
-	 * backend. We get the number of "overflowed" pins for free, but don't
-	 * know the number of pins in PrivateRefCountArray. The cost of
-	 * calculating that exactly doesn't seem worth it, so just assume the max.
-	 */
-	max_proportional_pins -= PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES;
-
-	if (max_proportional_pins <= 0)
-		max_proportional_pins = 1;
-
-	if (*additional_pins > max_proportional_pins)
-		*additional_pins = max_proportional_pins;
+	limit = GetAdditionalPinLimit();
+	limit = Max(limit, 1);
+	if (limit < *additional_pins)
+		*additional_pins = limit;
 }
 
 /*
@@ -3575,6 +3601,15 @@ InitBufferManagerAccess(void)
 {
 	HASHCTL		hash_ctl;
 
+	/*
+	 * The soft limit on the number of pins each backend should respect, based
+	 * on shared_buffers and the maximum number of connections possible.
+	 * That's very pessimistic, but outside toy-sized shared_buffers it should
+	 * allow plenty of pins.  LimitAdditionalPins() or GetAdditionalPinLimit()
+	 * can be used to check the remaining balance.
+	 */
+	MaxProportionalPins = NBuffers / (MaxBackends + NUM_AUXILIARY_PROCS);
+
 	memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
 
 	hash_ctl.keysize = sizeof(int32);
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 80b83444eb2..5378ba84316 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -286,6 +286,22 @@ GetLocalVictimBuffer(void)
 	return BufferDescriptorGetBuffer(bufHdr);
 }
 
+/* see GetSoftPinLimit() */
+uint32
+GetSoftLocalPinLimit(void)
+{
+	/* Every backend has its own temporary buffers, and can pin them all. */
+	return num_temp_buffers;
+}
+
+/* see GetAdditionalPinLimit() */
+uint32
+GetAdditionalLocalPinLimit(void)
+{
+	Assert(NLocalPinnedBuffers <= num_temp_buffers);
+	return num_temp_buffers - NLocalPinnedBuffers;
+}
+
 /* see LimitAdditionalPins() */
 void
 LimitAdditionalLocalPins(uint32 *additional_pins)
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index b204e4731c1..74b5afe8a1a 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -290,6 +290,10 @@ extern bool HoldingBufferPinThatDelaysRecovery(void);
 
 extern bool BgBufferSync(struct WritebackContext *wb_context);
 
+extern uint32 GetSoftPinLimit(void);
+extern uint32 GetSoftLocalPinLimit(void);
+extern uint32 GetAdditionalPinLimit(void);
+extern uint32 GetAdditionalLocalPinLimit(void);
 extern void LimitAdditionalPins(uint32 *additional_pins);
 extern void LimitAdditionalLocalPins(uint32 *additional_pins);
 
-- 
2.34.1

v36-0003-Improve-read-stream-advice-for-large-random-chun.patchtext/x-patch; charset=US-ASCII; name=v36-0003-Improve-read-stream-advice-for-large-random-chun.patchDownload
From 071245707d78fdcbc0f6bb76858793a85eb53769 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Tue, 18 Feb 2025 15:59:13 +1300
Subject: [PATCH v36 3/9] Improve read stream advice for large random chunks.

read_stream.c tries not to issue advice when it thinks the kernel's
readahead should be active, ie when using buffered I/O and reading
sequential blocks.  It previously gave up a little too easily: it should
issue advice until it has started running sequential pread() calls, not
just when it's planning to.  The simpler strategy worked for random
chunks of size <= io_combine_limit and entirely sequential streams, but
so not well when reading random chunks > io_combine limit.  For example,
a 256kB chunk of sequential data would benefit from only one fadvise(),
but (assuming io_combine_limit=128kB) could suffer an I/O stall for the
second half of it.

Keep issuing advice until the pread() calls catch up with the start of
the region we're currently issuing advice for, if ever.  In practice, if
there are any jumps in the lookahead window, we'll never stop issuing
advice, and if the whole lookahead window becomes sequential we'll
finally stop issuing advice.

Discovered by Tomas Vondra's regression testing of many data clustering
patterns using Melanie Plageman's streaming Bitmap Heap Scan patch, with
analysis of the I/O stall-producing pattern from Andres Freund.

Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CA%2BhUKGK_%3D4CVmMHvsHjOVrK6t4F%3DLBpFzsrr3R%2BaJYN8kcTfWg%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2BhUKGJ3HSWciQCz8ekP1Zn7N213RfA4nbuotQawfpq23%2Bw-5Q%40mail.gmail.com
---
 src/backend/storage/aio/read_stream.c | 71 +++++++++++++++++++--------
 1 file changed, 50 insertions(+), 21 deletions(-)

diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index 11ee16ec228..a8a96baf8c1 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -133,6 +133,7 @@ struct ReadStream
 
 	/* Next expected block, for detecting sequential access. */
 	BlockNumber seq_blocknum;
+	BlockNumber seq_until_processed;
 
 	/* The read operation we are currently preparing. */
 	BlockNumber pending_read_blocknum;
@@ -237,11 +238,11 @@ read_stream_unget_block(ReadStream *stream, BlockNumber blocknum)
  * distance to a level that prevents look-ahead until buffers are released.
  */
 static bool
-read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
+read_stream_start_pending_read(ReadStream *stream)
 {
 	bool		need_wait;
 	int			nblocks;
-	int			flags;
+	int			flags = 0;
 	int16		io_index;
 	int16		overflow;
 	int16		buffer_index;
@@ -261,16 +262,36 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 	else
 		Assert(stream->next_buffer_index == stream->oldest_buffer_index);
 
-	/*
-	 * If advice hasn't been suppressed, this system supports it, and this
-	 * isn't a strictly sequential pattern, then we'll issue advice.
-	 */
-	if (!suppress_advice &&
-		stream->advice_enabled &&
-		stream->pending_read_blocknum != stream->seq_blocknum)
-		flags = READ_BUFFERS_ISSUE_ADVICE;
-	else
-		flags = 0;
+	/* Do we need to issue read-ahead advice? */
+	if (stream->advice_enabled)
+	{
+		bool		no_wait;
+
+		/*
+		 * We only issue advice if we won't immediately have to call
+		 * WaitReadBuffers().
+		 */
+		no_wait = stream->pinned_buffers > 0 ||
+			stream->pending_read_nblocks < stream->distance;
+
+		if (stream->pending_read_blocknum == stream->seq_blocknum)
+		{
+			/*
+			 * Sequential: issue advice only until the WaitReadBuffers() calls
+			 * catch up with the first advice issued for this sequential
+			 * region, so the kernel can see sequential access.
+			 */
+			if (stream->seq_until_processed != InvalidBlockNumber && no_wait)
+				flags = READ_BUFFERS_ISSUE_ADVICE;
+		}
+		else
+		{
+			/* Random jump: start tracking new region. */
+			stream->seq_until_processed = stream->pending_read_blocknum;
+			if (no_wait)
+				flags = READ_BUFFERS_ISSUE_ADVICE;
+		}
+	}
 
 	/* Compute the remaining portion of the per-backend buffer limit. */
 	if (stream->temporary)
@@ -359,7 +380,7 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
 }
 
 static void
-read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
+read_stream_look_ahead(ReadStream *stream)
 {
 	while (stream->ios_in_progress < stream->max_ios &&
 		   stream->pinned_buffers + stream->pending_read_nblocks < stream->distance)
@@ -370,8 +391,7 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
 
 		if (stream->pending_read_nblocks == stream->io_combine_limit)
 		{
-			read_stream_start_pending_read(stream, suppress_advice);
-			suppress_advice = false;
+			read_stream_start_pending_read(stream);
 			continue;
 		}
 
@@ -404,15 +424,13 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
 		/* We have to start the pending read before we can build another. */
 		while (stream->pending_read_nblocks > 0)
 		{
-			if (!read_stream_start_pending_read(stream, suppress_advice) ||
+			if (!read_stream_start_pending_read(stream) ||
 				stream->ios_in_progress == stream->max_ios)
 			{
 				/* And we've hit a buffer or I/O limit.  Rewind and wait. */
 				read_stream_unget_block(stream, blocknum);
 				return;
 			}
-
-			suppress_advice = false;
 		}
 
 		/* This is the start of a new pending read. */
@@ -436,7 +454,7 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
 		  stream->pinned_buffers == 0) ||
 		 stream->distance == 0) &&
 		stream->ios_in_progress < stream->max_ios)
-		read_stream_start_pending_read(stream, suppress_advice);
+		read_stream_start_pending_read(stream);
 
 	/*
 	 * There should always be something pinned when we leave this function,
@@ -612,6 +630,8 @@ read_stream_begin_impl(int flags,
 	stream->callback = callback;
 	stream->callback_private_data = callback_private_data;
 	stream->buffered_blocknum = InvalidBlockNumber;
+	stream->seq_blocknum = InvalidBlockNumber;
+	stream->seq_until_processed = InvalidBlockNumber;
 	stream->temporary = SmgrIsTemp(smgr);
 
 	/*
@@ -792,7 +812,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 		 * space for more, but if we're just starting up we'll need to crank
 		 * the handle to get started.
 		 */
-		read_stream_look_ahead(stream, true);
+		read_stream_look_ahead(stream);
 
 		/* End of stream reached? */
 		if (stream->pinned_buffers == 0)
@@ -837,6 +857,15 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 			distance = stream->distance * 2;
 			distance = Min(distance, stream->max_pinned_buffers);
 			stream->distance = distance;
+
+			/*
+			 * If we've caught up with the first advice issued for the current
+			 * sequential region, cancel further advice until the next random
+			 * jump.  The kernel should be able to see the pattern now that
+			 * we're actually making sequential preadv() calls.
+			 */
+			if (stream->ios[io_index].op.blocknum == stream->seq_until_processed)
+				stream->seq_until_processed = InvalidBlockNumber;
 		}
 		else
 		{
@@ -898,7 +927,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 		stream->oldest_buffer_index = 0;
 
 	/* Prepare for the next call. */
-	read_stream_look_ahead(stream, false);
+	read_stream_look_ahead(stream);
 
 #ifndef READ_STREAM_DISABLE_FAST_PATH
 	/* See if we can take the fast path for all-cached scans next time. */
-- 
2.34.1

v36-0004-Look-ahead-more-when-sequential-in-read_stream.c.patchtext/x-patch; charset=US-ASCII; name=v36-0004-Look-ahead-more-when-sequential-in-read_stream.c.patchDownload
From eca9547db66991aa47d096617a89b3eddddac647 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Wed, 19 Feb 2025 01:25:40 +1300
Subject: [PATCH v36 4/9] Look ahead more when sequential in read_stream.c.

Previously, sequential reads would cause the look-ahead distance to
fall back to io_combine_limit, on the basis that kernel read-ahead
should start helping.  It also meant that we'd have to ramp the distance
back up when a sequential region was followed by a burst of random
jumps, with little hope of avoiding a stall, which is not a good
trade-off and is incompatible with AIO plans (you have to look ahead if
you have to start real I/O).

Simplify the algorithm: now only cache hits make the look-ahead distance
drop off, and cache misses still make it grow rapidly.  Random vs
sequential heuristics are no longer taken into consideration while
making that decision.

Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CA%2BhUKGK_%3D4CVmMHvsHjOVrK6t4F%3DLBpFzsrr3R%2BaJYN8kcTfWg%40mail.gmail.com
---
 src/backend/storage/aio/read_stream.c | 92 ++++++++++-----------------
 1 file changed, 33 insertions(+), 59 deletions(-)

diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index a8a96baf8c1..57cde89cfdc 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -17,30 +17,12 @@
  * pending read.  When that isn't possible, the existing pending read is sent
  * to StartReadBuffers() so that a new one can begin to form.
  *
- * The algorithm for controlling the look-ahead distance tries to classify the
- * stream into three ideal behaviors:
+ * The algorithm for controlling the look-ahead distance is based on recent
+ * cache hits and misses:
  *
- * A) No I/O is necessary, because the requested blocks are fully cached
- * already.  There is no benefit to looking ahead more than one block, so
- * distance is 1.  This is the default initial assumption.
- *
- * B) I/O is necessary, but read-ahead advice is undesirable because the
- * access is sequential and we can rely on the kernel's read-ahead heuristics,
- * or impossible because direct I/O is enabled, or the system doesn't support
- * read-ahead advice.  There is no benefit in looking ahead more than
- * io_combine_limit, because in this case the only goal is larger read system
- * calls.  Looking further ahead would pin many buffers and perform
- * speculative work for no benefit.
- *
- * C) I/O is necessary, it appears to be random, and this system supports
- * read-ahead advice.  We'll look further ahead in order to reach the
- * configured level of I/O concurrency.
- *
- * The distance increases rapidly and decays slowly, so that it moves towards
- * those levels as different I/O patterns are discovered.  For example, a
- * sequential scan of fully cached data doesn't bother looking ahead, but a
- * sequential scan that hits a region of uncached blocks will start issuing
- * increasingly wide read calls until it plateaus at io_combine_limit.
+ * When no I/O is necessary, there is no point in looking ahead more than one
+ * block.  This is the default initial assumption.  Otherwise rapidly increase
+ * the distance to try to benefit from I/O combining and I/O concurrency.
  *
  * The main data structure is a circular queue of buffers of size
  * max_pinned_buffers plus some extra space for technical reasons, ready to be
@@ -336,7 +318,7 @@ read_stream_start_pending_read(ReadStream *stream)
 	/* Remember whether we need to wait before returning this buffer. */
 	if (!need_wait)
 	{
-		/* Look-ahead distance decays, no I/O necessary (behavior A). */
+		/* Look-ahead distance decays, no I/O necessary. */
 		if (stream->distance > 1)
 			stream->distance--;
 	}
@@ -517,6 +499,15 @@ read_stream_begin_impl(int flags,
 	else
 		max_ios = get_tablespace_io_concurrency(tablespace_id);
 
+	/*
+	 * XXX Since we don't have asynchronous I/O yet, if direct I/O is enabled
+	 * then just behave as though I/O concurrency is set to 0.  Otherwise we
+	 * would look ahead pinning many buffers for no benefit, for lack of
+	 * advice and AIO.
+	 */
+	if (io_direct_flags & IO_DIRECT_DATA)
+		max_ios = 0;
+
 	/* Cap to INT16_MAX to avoid overflowing below */
 	max_ios = Min(max_ios, PG_INT16_MAX);
 
@@ -637,7 +628,7 @@ read_stream_begin_impl(int flags,
 	/*
 	 * Skip the initial ramp-up phase if the caller says we're going to be
 	 * reading the whole relation.  This way we start out assuming we'll be
-	 * doing full io_combine_limit sized reads (behavior B).
+	 * doing full io_combine_limit sized reads.
 	 */
 	if (flags & READ_STREAM_FULL)
 		stream->distance = Min(max_pinned_buffers, stream->io_combine_limit);
@@ -728,10 +719,10 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 #ifndef READ_STREAM_DISABLE_FAST_PATH
 
 	/*
-	 * A fast path for all-cached scans (behavior A).  This is the same as the
-	 * usual algorithm, but it is specialized for no I/O and no per-buffer
-	 * data, so we can skip the queue management code, stay in the same buffer
-	 * slot and use singular StartReadBuffer().
+	 * A fast path for all-cached scans.  This is the same as the usual
+	 * algorithm, but it is specialized for no I/O and no per-buffer data, so
+	 * we can skip the queue management code, stay in the same buffer slot and
+	 * use singular StartReadBuffer().
 	 */
 	if (likely(stream->fast_path))
 	{
@@ -851,37 +842,20 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 		if (++stream->oldest_io_index == stream->max_ios)
 			stream->oldest_io_index = 0;
 
-		if (stream->ios[io_index].op.flags & READ_BUFFERS_ISSUE_ADVICE)
-		{
-			/* Distance ramps up fast (behavior C). */
-			distance = stream->distance * 2;
-			distance = Min(distance, stream->max_pinned_buffers);
-			stream->distance = distance;
+		/* Look-ahead distance ramps up quickly after we do I/O. */
+		distance = stream->distance * 2;
+		distance = Min(distance, stream->max_pinned_buffers);
+		stream->distance = distance;
 
-			/*
-			 * If we've caught up with the first advice issued for the current
-			 * sequential region, cancel further advice until the next random
-			 * jump.  The kernel should be able to see the pattern now that
-			 * we're actually making sequential preadv() calls.
-			 */
-			if (stream->ios[io_index].op.blocknum == stream->seq_until_processed)
-				stream->seq_until_processed = InvalidBlockNumber;
-		}
-		else
-		{
-			/* No advice; move towards io_combine_limit (behavior B). */
-			if (stream->distance > stream->io_combine_limit)
-			{
-				stream->distance--;
-			}
-			else
-			{
-				distance = stream->distance * 2;
-				distance = Min(distance, stream->io_combine_limit);
-				distance = Min(distance, stream->max_pinned_buffers);
-				stream->distance = distance;
-			}
-		}
+		/*
+		 * If we've caught up with the first advice issued for the current
+		 * sequential region, cancel further advice until the next random
+		 * jump.  The kernel should be able to see the pattern now that we're
+		 * actually making sequential preadv() calls.
+		 */
+		if (stream->advice_enabled &&
+			stream->ios[io_index].op.blocknum == stream->seq_until_processed)
+			stream->seq_until_processed = InvalidBlockNumber;
 	}
 
 #ifdef CLOBBER_FREED_MEMORY
-- 
2.34.1

v36-0006-Support-buffer-forwarding-in-StartReadBuffers.patchtext/x-patch; charset=US-ASCII; name=v36-0006-Support-buffer-forwarding-in-StartReadBuffers.patchDownload
From 3f83ee5e01ad8fda7048e146d112dcd400bef78b Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 10 Feb 2025 21:55:40 +1300
Subject: [PATCH v36 6/9] Support buffer forwarding in StartReadBuffers().

Sometimes we have to perform a short read because we hit a cached block
that ends a contiguous run of blocks requiring I/O.  We don't want
StartReadBuffers() to have to start more than one I/O, so we stop there.
We also don't want to have to unpin the cached block (and repin it
later), so previously we'd silently pretend the hit was part of the I/O,
and just leave it out of the read from disk.  Now, we'll "forward" it to
the next call.  We still write it to the buffers[] array for the caller
to pass back to us later, but it's not included in *nblocks.

This policy means that we no longer mix hits and misses in a single
operation's results, so we avoid the requirement to call
WaitReadBuffers(), which might stall, before the caller can make use of
the hits.  The caller will get the hit in the next call instead, and
know that it doesn't have to wait.  That's important for later work on
out-of-order read streams that minimize I/O stalls.

This also makes life easier for proposed work on true AIO, which
occasionally needs to split a large I/O after pinning all the buffers,
while the current coding only ever forwards a single bookending hit.

This API is natural for read_stream.c: it just leaves forwarded buffers
where they are in its circular queue, where the next call will pick them
up and continue, minimizing pin churn.

If we ever think of a good reason to disable this feature, i.e. for
other users of StartReadBuffers() that don't want to deal with forwarded
buffers, then we could add a flag for that.  For now read_steam.c is the
only user.

Discussion: https://postgr.es/m/CA%2BhUKGK_%3D4CVmMHvsHjOVrK6t4F%3DLBpFzsrr3R%2BaJYN8kcTfWg%40mail.gmail.com
---
 src/backend/storage/buffer/bufmgr.c | 128 ++++++++++++++++++++--------
 src/include/storage/bufmgr.h        |   1 -
 2 files changed, 91 insertions(+), 38 deletions(-)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index a6138e79306..d56bff96cec 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1257,10 +1257,10 @@ StartReadBuffersImpl(ReadBuffersOperation *operation,
 					 Buffer *buffers,
 					 BlockNumber blockNum,
 					 int *nblocks,
-					 int flags)
+					 int flags,
+					 bool allow_forwarding)
 {
 	int			actual_nblocks = *nblocks;
-	int			io_buffers_len = 0;
 	int			maxcombine = 0;
 
 	Assert(*nblocks > 0);
@@ -1270,30 +1270,80 @@ StartReadBuffersImpl(ReadBuffersOperation *operation,
 	{
 		bool		found;
 
-		buffers[i] = PinBufferForBlock(operation->rel,
-									   operation->smgr,
-									   operation->persistence,
-									   operation->forknum,
-									   blockNum + i,
-									   operation->strategy,
-									   &found);
+		if (allow_forwarding && buffers[i] != InvalidBuffer)
+		{
+			BufferDesc *bufHdr;
+
+			/*
+			 * This is a buffer that was pinned by an earlier call to
+			 * StartReadBuffers(), but couldn't be handled in one operation at
+			 * that time.  The operation was split, and the caller has passed
+			 * an already pinned buffer back to us to handle the rest of the
+			 * operation.  It must continue at the expected block number.
+			 */
+			Assert(BufferGetBlockNumber(buffers[i]) == blockNum + i);
+
+			/*
+			 * It might be an already valid buffer (a hit) that followed the
+			 * final contiguous block of an earlier I/O (a miss) marking the
+			 * end of it, or a buffer that some other backend has since made
+			 * valid by performing the I/O for us, in which case we can handle
+			 * it as a hit now.  It is safe to check for a BM_VALID flag with
+			 * a relaxed load, because we got a fresh view of it while pinning
+			 * it in the previous call.
+			 *
+			 * On the other hand if we don't see BM_VALID yet, it must be an
+			 * I/O that was split by the previous call and we need to try to
+			 * start a new I/O from this block.  We're also racing against any
+			 * other backend that might start the I/O or even manage to mark
+			 * it BM_VALID after this check, BM_VALID after this check, but
+			 * StartBufferIO() will handle those cases.
+			 */
+			if (BufferIsLocal(buffers[i]))
+				bufHdr = GetLocalBufferDescriptor(-buffers[i] - 1);
+			else
+				bufHdr = GetBufferDescriptor(buffers[i] - 1);
+			found = pg_atomic_read_u32(&bufHdr->state) & BM_VALID;
+		}
+		else
+		{
+			buffers[i] = PinBufferForBlock(operation->rel,
+										   operation->smgr,
+										   operation->persistence,
+										   operation->forknum,
+										   blockNum + i,
+										   operation->strategy,
+										   &found);
+		}
 
 		if (found)
 		{
 			/*
-			 * Terminate the read as soon as we get a hit.  It could be a
-			 * single buffer hit, or it could be a hit that follows a readable
-			 * range.  We don't want to create more than one readable range,
-			 * so we stop here.
+			 * We have a hit.  If it's the first block in the requested range,
+			 * we can return it immediately and report that WaitReadBuffers()
+			 * does not need to be called.  If the initial value of *nblocks
+			 * was larger, the caller will have to call again for the rest.
 			 */
-			actual_nblocks = i + 1;
+			if (i == 0)
+			{
+				*nblocks = 1;
+				return false;
+			}
+
+			/*
+			 * Otherwise we already have an I/O to perform, but this block
+			 * can't be included as it is already valid.  Split the I/O here.
+			 * There may or may not be more blocks requiring I/O after this
+			 * one, we haven't checked, but it can't be contiguous with this
+			 * hit in the way.  We'll leave this buffer pinned, forwarding it
+			 * to the next call, avoiding the need to unpin it here and re-pin
+			 * it in the next call.
+			 */
+			actual_nblocks = i;
 			break;
 		}
 		else
 		{
-			/* Extend the readable range to cover this block. */
-			io_buffers_len++;
-
 			/*
 			 * Check how many blocks we can cover with the same IO. The smgr
 			 * implementation might e.g. be limited due to a segment boundary.
@@ -1314,15 +1364,11 @@ StartReadBuffersImpl(ReadBuffersOperation *operation,
 	}
 	*nblocks = actual_nblocks;
 
-	if (likely(io_buffers_len == 0))
-		return false;
-
 	/* Populate information needed for I/O. */
 	operation->buffers = buffers;
 	operation->blocknum = blockNum;
 	operation->flags = flags;
 	operation->nblocks = actual_nblocks;
-	operation->io_buffers_len = io_buffers_len;
 
 	if (flags & READ_BUFFERS_ISSUE_ADVICE)
 	{
@@ -1337,7 +1383,7 @@ StartReadBuffersImpl(ReadBuffersOperation *operation,
 		smgrprefetch(operation->smgr,
 					 operation->forknum,
 					 blockNum,
-					 operation->io_buffers_len);
+					 actual_nblocks);
 	}
 
 	/* Indicate that WaitReadBuffers() should be called. */
@@ -1351,11 +1397,21 @@ StartReadBuffersImpl(ReadBuffersOperation *operation,
  * actual number, which may be fewer than requested.  Caller sets some of the
  * members of operation; see struct definition.
  *
+ * The initial contents of the elements of buffers up to *nblocks should
+ * either be InvalidBuffer or an already-pinned buffer that was left by an
+ * preceding call to StartReadBuffers() that had to be split.  On return, some
+ * elements of buffers may hold pinned buffers beyond the number indicated by
+ * the updated value of *nblocks.  Operations are split on boundaries known to
+ * smgr (eg md.c segment boundaries that require crossing into a different
+ * underlying file), or when already cached blocks are found in the buffer
+ * that prevent the formation of a contiguous read.
+ *
  * If false is returned, no I/O is necessary.  If true is returned, one I/O
  * has been started, and WaitReadBuffers() must be called with the same
  * operation object before the buffers are accessed.  Along with the operation
  * object, the caller-supplied array of buffers must remain valid until
- * WaitReadBuffers() is called.
+ * WaitReadBuffers() is called, and any forwarded buffers must also be
+ * preserved for a future call unless explicitly released.
  *
  * Currently the I/O is only started with optional operating system advice if
  * requested by the caller with READ_BUFFERS_ISSUE_ADVICE, and the real I/O
@@ -1369,13 +1425,18 @@ StartReadBuffers(ReadBuffersOperation *operation,
 				 int *nblocks,
 				 int flags)
 {
-	return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags);
+	return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags,
+								true /* expect forwarded buffers */ );
 }
 
 /*
  * Single block version of the StartReadBuffers().  This might save a few
  * instructions when called from another translation unit, because it is
  * specialized for nblocks == 1.
+ *
+ * This version does not support "forwarded" buffers: they cannot be created
+ * by reading only one block, and the current contents of *buffer is ignored
+ * on entry.
  */
 bool
 StartReadBuffer(ReadBuffersOperation *operation,
@@ -1386,7 +1447,8 @@ StartReadBuffer(ReadBuffersOperation *operation,
 	int			nblocks = 1;
 	bool		result;
 
-	result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags);
+	result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags,
+								  false /* single block, no forwarding */ );
 	Assert(nblocks == 1);		/* single block can't be short */
 
 	return result;
@@ -1416,24 +1478,16 @@ WaitReadBuffers(ReadBuffersOperation *operation)
 	IOObject	io_object;
 	char		persistence;
 
-	/*
-	 * Currently operations are only allowed to include a read of some range,
-	 * with an optional extra buffer that is already pinned at the end.  So
-	 * nblocks can be at most one more than io_buffers_len.
-	 */
-	Assert((operation->nblocks == operation->io_buffers_len) ||
-		   (operation->nblocks == operation->io_buffers_len + 1));
-
 	/* Find the range of the physical read we need to perform. */
-	nblocks = operation->io_buffers_len;
-	if (nblocks == 0)
-		return;					/* nothing to do */
-
+	nblocks = operation->nblocks;
 	buffers = &operation->buffers[0];
 	blocknum = operation->blocknum;
 	forknum = operation->forknum;
 	persistence = operation->persistence;
 
+	Assert(nblocks > 0);
+	Assert(nblocks <= MAX_IO_COMBINE_LIMIT);
+
 	if (persistence == RELPERSISTENCE_TEMP)
 	{
 		io_context = IOCONTEXT_NORMAL;
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 74b5afe8a1a..307f36af384 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -130,7 +130,6 @@ struct ReadBuffersOperation
 	BlockNumber blocknum;
 	int			flags;
 	int16		nblocks;
-	int16		io_buffers_len;
 };
 
 typedef struct ReadBuffersOperation ReadBuffersOperation;
-- 
2.34.1

v36-0007-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchtext/x-patch; charset=US-ASCII; name=v36-0007-Separate-TBM-Shared-Private-Iterator-and-TBMIter.patchDownload
From ff4e659846982bfa4ed4492a9f33a69b36d2961f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 20 Feb 2025 12:30:26 -0500
Subject: [PATCH v36 7/9] Separate TBM[Shared|Private]Iterator and
 TBMIterateResult

Remove the TBMIterateResult member from the TBMPrivateIterator and
TBMSharedIterator and make tbm_[shared|private_]iterate() take a
TBMIterateResult as a parameter.

This allows tidbitmap API users to manage multiple TBMIterateResults per
scan. This is required for bitmap heap scan to use the read stream API,
with which there may be multiple I/Os in flight at once, each one with a
TBMIterateResult.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/gin/ginget.c           | 33 ++++----
 src/backend/access/gin/ginscan.c          |  2 +-
 src/backend/access/heap/heapam_handler.c  | 28 +++----
 src/backend/executor/nodeBitmapHeapscan.c | 39 +++++----
 src/backend/nodes/tidbitmap.c             | 96 ++++++++++++-----------
 src/include/access/gin_private.h          |  7 +-
 src/include/nodes/tidbitmap.h             |  6 +-
 7 files changed, 110 insertions(+), 101 deletions(-)

diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 4a56f19390d..f29ccd3c2d1 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -332,8 +332,8 @@ restartScanEntry:
 	entry->list = NULL;
 	entry->nlist = 0;
 	entry->matchBitmap = NULL;
-	entry->matchResult = NULL;
 	entry->matchNtuples = -1;
+	entry->matchResult.blockno = InvalidBlockNumber;
 	entry->reduceResult = false;
 	entry->predictNumberResult = 0;
 
@@ -827,20 +827,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 		{
 			/*
 			 * If we've exhausted all items on this block, move to next block
-			 * in the bitmap.
+			 * in the bitmap. tbm_private_iterate() sets matchResult.blockno
+			 * to InvalidBlockNumber when the bitmap is exhausted.
 			 */
-			while (entry->matchResult == NULL ||
-				   (!entry->matchResult->lossy &&
+			while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
+				   (!entry->matchResult.lossy &&
 					entry->offset >= entry->matchNtuples) ||
-				   entry->matchResult->blockno < advancePastBlk ||
+				   entry->matchResult.blockno < advancePastBlk ||
 				   (ItemPointerIsLossyPage(&advancePast) &&
-					entry->matchResult->blockno == advancePastBlk))
+					entry->matchResult.blockno == advancePastBlk))
 			{
-				entry->matchResult =
-					tbm_private_iterate(entry->matchIterator);
-
-				if (entry->matchResult == NULL)
+				if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult))
 				{
+					Assert(!BlockNumberIsValid(entry->matchResult.blockno));
 					ItemPointerSetInvalid(&entry->curItem);
 					tbm_end_private_iterate(entry->matchIterator);
 					entry->matchIterator = NULL;
@@ -849,14 +848,14 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 				}
 
 				/* Exact pages need their tuple offsets extracted. */
-				if (!entry->matchResult->lossy)
-					entry->matchNtuples = tbm_extract_page_tuple(entry->matchResult,
+				if (!entry->matchResult.lossy)
+					entry->matchNtuples = tbm_extract_page_tuple(&entry->matchResult,
 																 entry->matchOffsets,
 																 TBM_MAX_TUPLES_PER_PAGE);
 
 				/*
 				 * Reset counter to the beginning of entry->matchResult. Note:
-				 * entry->offset is still greater than entry->matchNtuples if
+				 * entry->offset is still greater than matchResult.ntuples if
 				 * matchResult is lossy.  So, on next call we will get next
 				 * result from TIDBitmap.
 				 */
@@ -869,10 +868,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			 * We're now on the first page after advancePast which has any
 			 * items on it. If it's a lossy result, return that.
 			 */
-			if (entry->matchResult->lossy)
+			if (entry->matchResult.lossy)
 			{
 				ItemPointerSetLossyPage(&entry->curItem,
-										entry->matchResult->blockno);
+										entry->matchResult.blockno);
 
 				/*
 				 * We might as well fall out of the loop; we could not
@@ -889,7 +888,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			Assert(entry->matchNtuples > -1);
 
 			/* Skip over any offsets <= advancePast, and return that. */
-			if (entry->matchResult->blockno == advancePastBlk)
+			if (entry->matchResult.blockno == advancePastBlk)
 			{
 				Assert(entry->matchNtuples > 0);
 
@@ -910,7 +909,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
 			}
 
 			ItemPointerSet(&entry->curItem,
-						   entry->matchResult->blockno,
+						   entry->matchResult.blockno,
 						   entry->matchOffsets[entry->offset]);
 			entry->offset++;
 
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index f6cdd098a02..c2d1771bd77 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -111,7 +111,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	ItemPointerSetMin(&scanEntry->curItem);
 	scanEntry->matchBitmap = NULL;
 	scanEntry->matchIterator = NULL;
-	scanEntry->matchResult = NULL;
+	scanEntry->matchResult.blockno = InvalidBlockNumber;
 	scanEntry->matchNtuples = -1;
 	scanEntry->list = NULL;
 	scanEntry->nlist = 0;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index d74f0fbc5cd..bd49ff969f5 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult *tbmres;
+	TBMIterateResult tbmres;
 	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			noffsets = -1;
 
@@ -2142,14 +2142,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	{
 		CHECK_FOR_INTERRUPTS();
 
-		tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
-
-		if (tbmres == NULL)
+		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
 			return false;
 
 		/* Exact pages need their tuple offsets extracted. */
-		if (!tbmres->lossy)
-			noffsets = tbm_extract_page_tuple(tbmres, offsets,
+		if (!tbmres.lossy)
+			noffsets = tbm_extract_page_tuple(&tbmres, offsets,
 											  TBM_MAX_TUPLES_PER_PAGE);
 
 		/*
@@ -2161,11 +2159,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		 * reachable by the index.
 		 */
 	} while (!IsolationIsSerializable() &&
-			 tbmres->blockno >= hscan->rs_nblocks);
+			 tbmres.blockno >= hscan->rs_nblocks);
 
 	/* Got a valid block */
-	*blockno = tbmres->blockno;
-	*recheck = tbmres->recheck;
+	*blockno = tbmres.blockno;
+	*recheck = tbmres.recheck;
 
 	/*
 	 * We can skip fetching the heap page if we don't need any fields from the
@@ -2173,11 +2171,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 * page are visible to our transaction.
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		!tbmres.recheck &&
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres->lossy);
+		Assert(!tbmres.lossy);
 		Assert(bscan->rs_empty_tuples_pending >= 0);
 		Assert(noffsets > -1);
 
@@ -2186,7 +2184,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 		return true;
 	}
 
-	block = tbmres->blockno;
+	block = tbmres.blockno;
 
 	/*
 	 * Acquire pin on the target heap page, trading in any pin we held before.
@@ -2215,7 +2213,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres->lossy)
+	if (!tbmres.lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,7 +2277,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres->lossy)
+	if (tbmres.lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be0d24d901b..3b4ea0f6144 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 {
 #ifdef USE_PREFETCH
 	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult *tbmpre;
+	TBMIterateResult tbmpre;
 
 	if (pstate == NULL)
 	{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 		}
 		else if (!tbm_exhausted(prefetch_iterator))
 		{
-			tbmpre = tbm_iterate(prefetch_iterator);
-			node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-				InvalidBlockNumber;
+			tbm_iterate(prefetch_iterator, &tbmpre);
+			node->prefetch_blockno = tbmpre.blockno;
 		}
 		return;
 	}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 			 */
 			if (!tbm_exhausted(prefetch_iterator))
 			{
-				tbmpre = tbm_iterate(prefetch_iterator);
-				node->prefetch_blockno = tbmpre ? tbmpre->blockno :
-					InvalidBlockNumber;
+				tbm_iterate(prefetch_iterator, &tbmpre);
+				node->prefetch_blockno = tbmpre.blockno;
 			}
 		}
 	}
@@ -441,17 +439,18 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (node->prefetch_pages < node->prefetch_target)
 			{
-				TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+				TBMIterateResult tbmpre;
 				bool		skip_fetch;
 
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
 					/* No more pages to prefetch */
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/*
 				 * If we expect not to have to actually read this heap page,
@@ -460,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				 * prefetch_pages?)
 				 */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 
@@ -481,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 		{
 			while (1)
 			{
-				TBMIterateResult *tbmpre;
+				TBMIterateResult tbmpre;
 				bool		do_prefetch = false;
 				bool		skip_fetch;
 
@@ -500,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 				if (!do_prefetch)
 					return;
 
-				tbmpre = tbm_iterate(prefetch_iterator);
-				if (tbmpre == NULL)
+				if (!tbm_iterate(prefetch_iterator, &tbmpre))
 				{
+					Assert(!BlockNumberIsValid(tbmpre.blockno));
 					/* No more pages to prefetch */
 					tbm_end_iterate(prefetch_iterator);
 					break;
 				}
 
-				node->prefetch_blockno = tbmpre->blockno;
+				node->prefetch_blockno = tbmpre.blockno;
 
 				/* As above, skip prefetch if we expect not to need page */
 				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre->recheck &&
+							  !tbmpre.recheck &&
 							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre->blockno,
+											 tbmpre.blockno,
 											 &node->pvmbuffer));
 
 				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
 			}
 		}
 	}
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 3d835024caa..41031aa8f2f 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
-	TBMIterateResult output;
 };
 
 /*
@@ -213,7 +212,6 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
-	TBMIterateResult output;
 };
 
 /* Local function prototypes */
@@ -957,21 +955,28 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 /*
  * tbm_private_iterate - scan through next page of a TIDBitmap
  *
- * Returns a TBMIterateResult representing one page, or NULL if there are
- * no more pages to scan.  Pages are guaranteed to be delivered in numerical
- * order.  If lossy is true, then the bitmap is "lossy" and failed to
- * remember the exact tuples to look at on this page --- the caller must
- * examine all tuples on the page and check if they meet the intended
- * condition.  result->ntuples is set to -1 when the bitmap is lossy.
- * If result->recheck is true, only the indicated tuples need
- * be examined, but the condition must be rechecked anyway.  (For ease of
- * testing, recheck is always set true when lossy is true.)
+ * Caller must pass in a TBMIterateResult to be filled.
+ *
+ * Pages are guaranteed to be delivered in numerical order.
+ *
+ * Returns false when there are no more pages to scan and true otherwise. When
+ * there are no more pages to scan, tbmres->blockno is set to
+ * InvalidBlockNumber.
+ *
+ * If lossy is true, then the bitmap is "lossy" and failed to remember
+ * the exact tuples to look at on this page --- the caller must examine all
+ * tuples on the page and check if they meet the intended condition. If lossy
+ * is false, the caller must later extract the tuple offsets from the page
+ * pointed to by internal_page with tbm_extract_page_tuple.
+ *
+ * If tbmres->recheck is true, only the indicated tuples need be examined, but
+ * the condition must be rechecked anyway.  (For ease of testing, recheck is
+ * always set true when lossy is true.)
  */
-TBMIterateResult *
-tbm_private_iterate(TBMPrivateIterator *iterator)
+bool
+tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 {
 	TIDBitmap  *tbm = iterator->tbm;
-	TBMIterateResult *output = &(iterator->output);
 
 	Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
 
@@ -1009,12 +1014,12 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 			chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			iterator->schunkbit++;
-			return output;
+			return true;
 		}
 	}
 
@@ -1028,16 +1033,17 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
 		else
 			page = tbm->spages[iterator->spageptr];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		iterator->spageptr++;
-		return output;
+		return true;
 	}
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1047,10 +1053,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
  *	across multiple processes.  We need to acquire the iterator LWLock,
  *	before accessing the shared members.
  */
-TBMIterateResult *
-tbm_shared_iterate(TBMSharedIterator *iterator)
+bool
+tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMIterateResult *output = &iterator->output;
 	TBMSharedIteratorState *istate = iterator->state;
 	PagetableEntry *ptbase = NULL;
 	int		   *idxpages = NULL;
@@ -1101,14 +1106,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
 		{
 			/* Return a lossy page indicator from the chunk */
-			output->blockno = chunk_blockno;
-			output->lossy = true;
-			output->recheck = true;
-			output->internal_page = NULL;
+			tbmres->blockno = chunk_blockno;
+			tbmres->lossy = true;
+			tbmres->recheck = true;
+			tbmres->internal_page = NULL;
 			istate->schunkbit++;
 
 			LWLockRelease(&istate->lock);
-			return output;
+			return true;
 		}
 	}
 
@@ -1116,21 +1121,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 	{
 		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
 
-		output->internal_page = page;
-		output->blockno = page->blockno;
-		output->lossy = false;
-		output->recheck = page->recheck;
+		tbmres->internal_page = page;
+		tbmres->blockno = page->blockno;
+		tbmres->lossy = false;
+		tbmres->recheck = page->recheck;
 		istate->spageptr++;
 
 		LWLockRelease(&istate->lock);
 
-		return output;
+		return true;
 	}
 
 	LWLockRelease(&istate->lock);
 
 	/* Nothing more in the bitmap */
-	return NULL;
+	tbmres->blockno = InvalidBlockNumber;
+	return false;
 }
 
 /*
@@ -1604,15 +1610,17 @@ tbm_end_iterate(TBMIterator *iterator)
 }
 
 /*
- * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ * Populate the next TBMIterateResult using the shared or private bitmap
+ * iterator. Returns false when there is nothing more to scan.
  */
-TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+bool
+tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
 {
 	Assert(iterator);
+	Assert(tbmres);
 
 	if (iterator->shared)
-		return tbm_shared_iterate(iterator->i.shared_iterator);
+		return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
 	else
-		return tbm_private_iterate(iterator->i.private_iterator);
+		return tbm_private_iterate(iterator->i.private_iterator, tbmres);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 95d8805b66f..aee1f70c22e 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -354,7 +354,12 @@ typedef struct GinScanEntryData
 	/* for a partial-match or full-scan query, we accumulate all TIDs here */
 	TIDBitmap  *matchBitmap;
 	TBMPrivateIterator *matchIterator;
-	TBMIterateResult *matchResult;
+
+	/*
+	 * If blockno is InvalidBlockNumber, all of the other fields in the
+	 * matchResult are meaningless.
+	 */
+	TBMIterateResult matchResult;
 	OffsetNumber matchOffsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			matchNtuples;
 
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index e185635c10b..99f795ceab5 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -101,8 +101,8 @@ extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
-extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
+extern bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
@@ -113,7 +113,7 @@ extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
 									 dsa_area *dsa, dsa_pointer dsp);
 extern void tbm_end_iterate(TBMIterator *iterator);
 
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern bool tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres);
 
 static inline bool
 tbm_exhausted(TBMIterator *iterator)
-- 
2.34.1

v36-0009-Remove-table-AM-callback-scan_bitmap_next_block.patchtext/x-patch; charset=US-ASCII; name=v36-0009-Remove-table-AM-callback-scan_bitmap_next_block.patchDownload
From 5aed6c5df54cd23701a580c591a7dc2ad9f2f44f Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:32:33 -0500
Subject: [PATCH v36 9/9] Remove table AM callback scan_bitmap_next_block

After pushing the bitmap iterator into table-AM specific code (as part
of making bitmap heap scan use the read stream API),
scan_bitmap_next_block() no longer returns the current block number.
Since scan_bitmap_next_block() isn't returning any relevant information
to bitmap table scan code, it makes more sense to get rid of it.

Now, bitmap table scan code only calls table_scan_bitmap_next_tuple(),
and the heap AM implementation of scan_bitmap_next_block() is a local
helper in heapam_handler.c.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me

ci-os-only:
---
 src/backend/access/heap/heapam_handler.c  | 372 ++++++++++++----------
 src/backend/access/table/tableamapi.c     |   3 -
 src/backend/executor/nodeBitmapHeapscan.c |  73 ++---
 src/backend/optimizer/util/plancat.c      |   2 +-
 src/include/access/tableam.h              |  90 ++----
 5 files changed, 244 insertions(+), 296 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index f0da9b6fb84..49267ce8cec 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,6 +56,10 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 
 static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
 
+static bool BitmapHeapScanNextBlock(TableScanDesc scan,
+									bool *recheck,
+									uint64 *lossy_pages, uint64 *exact_pages);
+
 
 /* ------------------------------------------------------------------------
  * Slot related callbacks for heap AM
@@ -2116,198 +2120,44 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
  */
 
 static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
+heapam_scan_bitmap_next_tuple(TableScanDesc scan,
+							  TupleTableSlot *slot,
 							  bool *recheck,
-							  uint64 *lossy_pages, uint64 *exact_pages)
+							  uint64 *lossy_pages,
+							  uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	BlockNumber block;
-	void	   *per_buffer_data;
-	Buffer		buffer;
-	Snapshot	snapshot;
-	int			ntup;
-	TBMIterateResult *tbmres;
-	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
-	int			noffsets = -1;
-
-	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
-	Assert(hscan->rs_read_stream);
-
-	hscan->rs_cindex = 0;
-	hscan->rs_ntuples = 0;
-
-	/* Release buffer containing previous block. */
-	if (BufferIsValid(hscan->rs_cbuf))
-	{
-		ReleaseBuffer(hscan->rs_cbuf);
-		hscan->rs_cbuf = InvalidBuffer;
-	}
-
-	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
-											 &per_buffer_data);
-
-	if (BufferIsInvalid(hscan->rs_cbuf))
-	{
-		if (BufferIsValid(bscan->rs_vmbuffer))
-		{
-			ReleaseBuffer(bscan->rs_vmbuffer);
-			bscan->rs_vmbuffer = InvalidBuffer;
-		}
-
-		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
-		 */
-		*recheck = false;
-		return bscan->rs_empty_tuples_pending > 0;
-	}
-
-	Assert(per_buffer_data);
-
-	tbmres = per_buffer_data;
-
-	Assert(BlockNumberIsValid(tbmres->blockno));
-	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
-
-	/* Exact pages need their tuple offsets extracted. */
-	if (!tbmres->lossy)
-		noffsets = tbm_extract_page_tuple(tbmres, offsets,
-										  TBM_MAX_TUPLES_PER_PAGE);
-
-	*recheck = tbmres->recheck;
-
-	block = hscan->rs_cblock = tbmres->blockno;
-	buffer = hscan->rs_cbuf;
-	snapshot = scan->rs_snapshot;
-
-	ntup = 0;
-
-	/*
-	 * Prune and repair fragmentation for the whole page, if possible.
-	 */
-	heap_page_prune_opt(scan->rs_rd, buffer);
-
-	/*
-	 * We must hold share lock on the buffer content while examining tuple
-	 * visibility.  Afterwards, however, the tuples we have found to be
-	 * visible are guaranteed good as long as we hold the buffer pin.
-	 */
-	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+	OffsetNumber targoffset;
+	Page		page;
+	ItemId		lp;
 
 	/*
-	 * We need two separate strategies for lossy and non-lossy cases.
+	 * Out of range?  If so, nothing more to look at on this page
 	 */
-	if (!tbmres->lossy)
-	{
-		/*
-		 * Bitmap is non-lossy, so we just look through the offsets listed in
-		 * tbmres; but we have to follow any HOT chain starting at each such
-		 * offset.
-		 */
-		int			curslot;
-
-		/* We must have extracted the tuple offsets by now */
-		Assert(noffsets > -1);
-
-		for (curslot = 0; curslot < noffsets; curslot++)
-		{
-			OffsetNumber offnum = offsets[curslot];
-			ItemPointerData tid;
-			HeapTupleData heapTuple;
-
-			ItemPointerSet(&tid, block, offnum);
-			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
-									   &heapTuple, NULL, true))
-				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
-		}
-	}
-	else
+	while (hscan->rs_cindex >= hscan->rs_ntuples)
 	{
 		/*
-		 * Bitmap is lossy, so we must examine each line pointer on the page.
-		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 * Emit empty tuples before advancing to the next block
 		 */
-		Page		page = BufferGetPage(buffer);
-		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
-		OffsetNumber offnum;
-
-		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		if (bscan->rs_empty_tuples_pending > 0)
 		{
-			ItemId		lp;
-			HeapTupleData loctup;
-			bool		valid;
-
-			lp = PageGetItemId(page, offnum);
-			if (!ItemIdIsNormal(lp))
-				continue;
-			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
-			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_rd->rd_id;
-			ItemPointerSet(&loctup.t_self, block, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
-			if (valid)
-			{
-				hscan->rs_vistuples[ntup++] = offnum;
-				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
-								 HeapTupleHeaderGetXmin(loctup.t_data));
-			}
-			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
-												buffer, snapshot);
+			/*
+			 * If we don't have to fetch the tuple, just return nulls.
+			 */
+			ExecStoreAllNullTuple(slot);
+			bscan->rs_empty_tuples_pending--;
+			return true;
 		}
-	}
 
-	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-	Assert(ntup <= MaxHeapTuplesPerPage);
-	hscan->rs_ntuples = ntup;
-
-	if (tbmres->lossy)
-		(*lossy_pages)++;
-	else
-		(*exact_pages)++;
-
-	/*
-	 * Return true to indicate that a valid block was found and the bitmap is
-	 * not exhausted. If there are no visible tuples on this page,
-	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
-	 * return false returning control to this function to advance to the next
-	 * block in the bitmap.
-	 */
-	return true;
-}
-
-static bool
-heapam_scan_bitmap_next_tuple(TableScanDesc scan,
-							  TupleTableSlot *slot)
-{
-	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
-	HeapScanDesc hscan = (HeapScanDesc) bscan;
-	OffsetNumber targoffset;
-	Page		page;
-	ItemId		lp;
-
-	if (bscan->rs_empty_tuples_pending > 0)
-	{
 		/*
-		 * If we don't have to fetch the tuple, just return nulls.
+		 * Returns false if the bitmap is exhausted and there are no further
+		 * blocks we need to scan.
 		 */
-		ExecStoreAllNullTuple(slot);
-		bscan->rs_empty_tuples_pending--;
-		return true;
+		if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
+			return false;
 	}
 
-	/*
-	 * Out of range?  If so, nothing more to look at on this page
-	 */
-	if (hscan->rs_cindex >= hscan->rs_ntuples)
-		return false;
-
 	targoffset = hscan->rs_vistuples[hscan->rs_cindex];
 	page = BufferGetPage(hscan->rs_cbuf);
 	lp = PageGetItemId(page, targoffset);
@@ -2614,6 +2464,177 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
 	}
 }
 
+/*
+ * Helper function get the next block of a bitmap heap scan. Returns true when
+ * it got the next block and saved it in the scan descriptor and false when
+ * the bitmap and or relation are exhausted.
+ */
+static bool
+BitmapHeapScanNextBlock(TableScanDesc scan,
+						bool *recheck,
+						uint64 *lossy_pages, uint64 *exact_pages)
+{
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	BlockNumber block;
+	void	   *per_buffer_data;
+	Buffer		buffer;
+	Snapshot	snapshot;
+	int			ntup;
+	TBMIterateResult *tbmres;
+	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+	int			noffsets = -1;
+
+	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
+
+	hscan->rs_cindex = 0;
+	hscan->rs_ntuples = 0;
+
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
+	{
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
+
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
+
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
+
+		/*
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
+		 */
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
+
+	Assert(per_buffer_data);
+
+	tbmres = per_buffer_data;
+
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
+
+	/* Exact pages need their tuple offsets extracted. */
+	if (!tbmres->lossy)
+		noffsets = tbm_extract_page_tuple(tbmres, offsets,
+										  TBM_MAX_TUPLES_PER_PAGE);
+
+	*recheck = tbmres->recheck;
+
+	block = hscan->rs_cblock = tbmres->blockno;
+	buffer = hscan->rs_cbuf;
+	snapshot = scan->rs_snapshot;
+
+	ntup = 0;
+
+	/*
+	 * Prune and repair fragmentation for the whole page, if possible.
+	 */
+	heap_page_prune_opt(scan->rs_rd, buffer);
+
+	/*
+	 * We must hold share lock on the buffer content while examining tuple
+	 * visibility.  Afterwards, however, the tuples we have found to be
+	 * visible are guaranteed good as long as we hold the buffer pin.
+	 */
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/*
+	 * We need two separate strategies for lossy and non-lossy cases.
+	 */
+	if (!tbmres->lossy)
+	{
+		/*
+		 * Bitmap is non-lossy, so we just look through the offsets listed in
+		 * tbmres; but we have to follow any HOT chain starting at each such
+		 * offset.
+		 */
+		int			curslot;
+
+		/* We must have extracted the tuple offsets by now */
+		Assert(noffsets > -1);
+
+		for (curslot = 0; curslot < noffsets; curslot++)
+		{
+			OffsetNumber offnum = offsets[curslot];
+			ItemPointerData tid;
+			HeapTupleData heapTuple;
+
+			ItemPointerSet(&tid, block, offnum);
+			if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
+									   &heapTuple, NULL, true))
+				hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
+		}
+	}
+	else
+	{
+		/*
+		 * Bitmap is lossy, so we must examine each line pointer on the page.
+		 * But we can ignore HOT chains, since we'll check each tuple anyway.
+		 */
+		Page		page = BufferGetPage(buffer);
+		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
+		OffsetNumber offnum;
+
+		for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
+		{
+			ItemId		lp;
+			HeapTupleData loctup;
+			bool		valid;
+
+			lp = PageGetItemId(page, offnum);
+			if (!ItemIdIsNormal(lp))
+				continue;
+			loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+			loctup.t_len = ItemIdGetLength(lp);
+			loctup.t_tableOid = scan->rs_rd->rd_id;
+			ItemPointerSet(&loctup.t_self, block, offnum);
+			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			if (valid)
+			{
+				hscan->rs_vistuples[ntup++] = offnum;
+				PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot,
+								 HeapTupleHeaderGetXmin(loctup.t_data));
+			}
+			HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
+												buffer, snapshot);
+		}
+	}
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+	Assert(ntup <= MaxHeapTuplesPerPage);
+	hscan->rs_ntuples = ntup;
+
+	if (tbmres->lossy)
+		(*lossy_pages)++;
+	else
+		(*exact_pages)++;
+
+	/*
+	 * Return true to indicate that a valid block was found and the bitmap is
+	 * not exhausted. If there are no visible tuples on this page,
+	 * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will
+	 * return false returning control to this function to advance to the next
+	 * block in the bitmap.
+	 */
+	return true;
+}
 
 /* ------------------------------------------------------------------------
  * Definition of the heap table access method.
@@ -2673,7 +2694,6 @@ static const TableAmRoutine heapam_methods = {
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
-	.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
 	.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
 	.scan_sample_next_block = heapam_scan_sample_next_block,
 	.scan_sample_next_tuple = heapam_scan_sample_next_tuple
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 760a36fd2a1..476663b66aa 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler)
 
 	Assert(routine->relation_estimate_size != NULL);
 
-	/* optional, but one callback implies presence of the other */
-	Assert((routine->scan_bitmap_next_block == NULL) ==
-		   (routine->scan_bitmap_next_tuple == NULL));
 	Assert(routine->scan_sample_next_block != NULL);
 	Assert(routine->scan_sample_next_tuple != NULL);
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 6df34094a13..3e33360c0fc 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -138,69 +138,44 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 static TupleTableSlot *
 BitmapHeapNext(BitmapHeapScanState *node)
 {
-	ExprContext *econtext;
-	TableScanDesc scan;
-	TupleTableSlot *slot;
-
-	/*
-	 * extract necessary information from index scan node
-	 */
-	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-	scan = node->ss.ss_currentScanDesc;
+	ExprContext *econtext = node->ss.ps.ps_ExprContext;
+	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
 
 	/*
 	 * If we haven't yet performed the underlying index scan, do it, and begin
 	 * the iteration over the bitmap.
 	 */
 	if (!node->initialized)
-	{
 		BitmapTableScanSetup(node);
-		scan = node->ss.ss_currentScanDesc;
-		goto new_page;
-	}
 
-	for (;;)
+	while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
+										slot, &node->recheck,
+										&node->stats.lossy_pages,
+										&node->stats.exact_pages))
 	{
-		while (table_scan_bitmap_next_tuple(scan, slot))
-		{
-			/*
-			 * Continuing in previously obtained page.
-			 */
-
-			CHECK_FOR_INTERRUPTS();
+		/*
+		 * Continuing in previously obtained page.
+		 */
+		CHECK_FOR_INTERRUPTS();
 
-			/*
-			 * If we are using lossy info, we have to recheck the qual
-			 * conditions at every tuple.
-			 */
-			if (node->recheck)
+		/*
+		 * If we are using lossy info, we have to recheck the qual conditions
+		 * at every tuple.
+		 */
+		if (node->recheck)
+		{
+			econtext->ecxt_scantuple = slot;
+			if (!ExecQualAndReset(node->bitmapqualorig, econtext))
 			{
-				econtext->ecxt_scantuple = slot;
-				if (!ExecQualAndReset(node->bitmapqualorig, econtext))
-				{
-					/* Fails recheck, so drop it and loop back for another */
-					InstrCountFiltered2(node, 1);
-					ExecClearTuple(slot);
-					continue;
-				}
+				/* Fails recheck, so drop it and loop back for another */
+				InstrCountFiltered2(node, 1);
+				ExecClearTuple(slot);
+				continue;
 			}
-
-			/* OK to return this tuple */
-			return slot;
 		}
 
-new_page:
-
-		/*
-		 * Returns false if the bitmap is exhausted and there are no further
-		 * blocks we need to scan.
-		 */
-		if (!table_scan_bitmap_next_block(scan,
-										  &node->recheck,
-										  &node->stats.lossy_pages,
-										  &node->stats.exact_pages))
-			break;
+		/* OK to return this tuple */
+		return slot;
 	}
 
 	/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..0489ad36644 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -325,7 +325,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->amcanparallel = amroutine->amcanparallel;
 				info->amhasgettuple = (amroutine->amgettuple != NULL);
 				info->amhasgetbitmap = amroutine->amgetbitmap != NULL &&
-					relation->rd_tableam->scan_bitmap_next_block != NULL;
+					relation->rd_tableam->scan_bitmap_next_tuple != NULL;
 				info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
 									  amroutine->amrestrpos != NULL);
 				info->amcostestimate = amroutine->amcostestimate;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 507d4ebe68f..b8cb1e744ad 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -780,43 +780,23 @@ typedef struct TableAmRoutine
 	 */
 
 	/*
-	 * Prepare to fetch / check / return tuples from `blockno` as part of a
-	 * bitmap table scan. `scan` was started via table_beginscan_bm(). Return
-	 * false if the bitmap is exhausted and true otherwise.
-	 *
-	 * This will typically read and pin the target block, and do the necessary
-	 * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
-	 * make sense to perform tuple visibility checks at this time).
-	 *
-	 * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
-	 * incremented by the table AM to indicate whether or not the block's
-	 * representation in the bitmap is lossy.
+	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
+	 * if a visible tuple was found, false otherwise.
 	 *
-	 * `recheck` is set by the table AM to indicate whether or not the tuples
-	 * from this block should be rechecked. Tuples from lossy pages will
-	 * always need to be rechecked, but some non-lossy pages' tuples may also
-	 * require recheck.
+	 * `lossy_pages` is incremented if the bitmap is lossy for the selected
+	 * page; otherwise, `exact_pages` is incremented. These are tracked for
+	 * display in EXPLAIN ANALYZE output.
 	 *
 	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
+	 * This is an optional callback.
 	 */
-	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
+	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
+										   TupleTableSlot *slot,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
 
-	/*
-	 * Fetch the next tuple of a bitmap table scan into `slot` and return true
-	 * if a visible tuple was found, false otherwise.
-	 *
-	 * Optional callback, but either both scan_bitmap_next_block and
-	 * scan_bitmap_next_tuple need to exist, or neither.
-	 */
-	bool		(*scan_bitmap_next_tuple) (TableScanDesc scan,
-										   TupleTableSlot *slot);
-
 	/*
 	 * Prepare to fetch tuples from the next block in a sample scan. Return
 	 * false if the sample scan is finished, true otherwise. `scan` was
@@ -1939,51 +1919,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  */
 
 /*
- * Prepare to fetch / check / return tuples as part of a bitmap table scan.
- * `scan` needs to have been started via table_beginscan_bm(). Returns false
- * if there are no more blocks in the bitmap, true otherwise.
- *
- * `lossy_pages` and `exact_pages` are EXPLAIN counters that can be
- * incremented by the table AM to indicate whether or not the block's
- * representation in the bitmap is lossy.
+ * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs
+ * to have been started via table_beginscan_bm(). Fetch the next tuple of a
+ * bitmap table scan into `slot` and return true if a visible tuple was found,
+ * false otherwise.
  *
- * `recheck` is set by the table AM to indicate whether or not the tuples
- * from this block should be rechecked.
+ * `recheck` is set by the table AM to indicate whether or not the tuple in
+ * `slot` should be rechecked. Tuples from lossy pages will always need to be
+ * rechecked, but some non-lossy pages' tuples may also require recheck.
  *
- * Note, this is an optionally implemented function, therefore should only be
- * used after verifying the presence (at plan time or such).
+ * `lossy_pages` is incremented if the block's representation in the bitmap is
+ * lossy; otherwise, `exact_pages` is incremented.
  */
 static inline bool
-table_scan_bitmap_next_block(TableScanDesc scan,
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+							 TupleTableSlot *slot,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
-{
-	/*
-	 * We don't expect direct calls to table_scan_bitmap_next_block with valid
-	 * CheckXidAlive for catalog or regular tables.  See detailed comments in
-	 * xact.c where these variables are declared.
-	 */
-	if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan))
-		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
-
-	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   recheck,
-														   lossy_pages,
-														   exact_pages);
-}
-
-/*
- * Fetch the next tuple of a bitmap table scan into `slot` and return true if
- * a visible tuple was found, false otherwise.
- * table_scan_bitmap_next_block() needs to previously have selected a
- * block (i.e. returned true), and no previous
- * table_scan_bitmap_next_tuple() for the same block may have
- * returned false.
- */
-static inline bool
-table_scan_bitmap_next_tuple(TableScanDesc scan,
-							 TupleTableSlot *slot)
 {
 	/*
 	 * We don't expect direct calls to table_scan_bitmap_next_tuple with valid
@@ -1994,7 +1947,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
-														   slot);
+														   slot,
+														   recheck,
+														   lossy_pages,
+														   exact_pages);
 }
 
 /*
-- 
2.34.1

v36-0008-BitmapHeapScan-uses-the-read-stream-API.patchtext/x-patch; charset=US-ASCII; name=v36-0008-BitmapHeapScan-uses-the-read-stream-API.patchDownload
From a860b801a4784277ebb53a105ff9d914b92cddbe Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 21 Feb 2025 15:15:47 -0500
Subject: [PATCH v36 8/9] BitmapHeapScan uses the read stream API

Make Bitmap Heap Scan use the read stream API instead of invoking
ReadBuffer() for each block indicated by the bitmap.

The read stream API handles prefetching, so remove all of the explicit
prefetching from bitmap heap scan code.

Now, heap table AM implements a read stream callback which uses the
bitmap iterator to return the next required block to the read stream
code.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
---
 src/backend/access/heap/heapam.c          |  80 +++++
 src/backend/access/heap/heapam_handler.c  |  90 +++---
 src/backend/executor/nodeBitmapHeapscan.c | 341 +---------------------
 src/include/access/tableam.h              |  25 +-
 src/include/nodes/execnodes.h             |  23 +-
 5 files changed, 124 insertions(+), 435 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index fa7935a0ed3..65e44b25b74 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -279,6 +279,72 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
 	return scan->rs_prefetch_block;
 }
 
+/*
+ * Read stream API callback for bitmap heap scans.
+ * Returns the next block the caller wants from the read stream or
+ * InvalidBlockNumber when done.
+ */
+static BlockNumber
+bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
+							void *per_buffer_data)
+{
+	TBMIterateResult *tbmres = per_buffer_data;
+	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
+	HeapScanDesc hscan = (HeapScanDesc) bscan;
+	TableScanDesc sscan = &hscan->rs_base;
+
+	for (;;)
+	{
+		CHECK_FOR_INTERRUPTS();
+
+		/* no more entries in the bitmap */
+		if (!tbm_iterate(&sscan->st.rs_tbmiterator, tbmres))
+			return InvalidBlockNumber;
+
+		/*
+		 * Ignore any claimed entries past what we think is the end of the
+		 * relation. It may have been extended after the start of our scan (we
+		 * only hold an AccessShareLock, and it could be inserts from this
+		 * backend).  We don't take this optimization in SERIALIZABLE
+		 * isolation though, as we need to examine all invisible tuples
+		 * reachable by the index.
+		 */
+		if (!IsolationIsSerializable() &&
+			tbmres->blockno >= hscan->rs_nblocks)
+			continue;
+
+		/*
+		 * We can skip fetching the heap page if we don't need any fields from
+		 * the heap, the bitmap entries don't need rechecking, and all tuples
+		 * on the page are visible to our transaction.
+		 */
+		if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
+			!tbmres->recheck &&
+			VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
+		{
+			OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+			int			noffsets;
+
+			/* can't be lossy in the skip_fetch case */
+			Assert(!tbmres->lossy);
+			Assert(bscan->rs_empty_tuples_pending >= 0);
+
+			/*
+			 * We throw away the offsets, but this is the easiest way to get a
+			 * count of tuples.
+			 */
+			noffsets = tbm_extract_page_tuple(tbmres, offsets, TBM_MAX_TUPLES_PER_PAGE);
+			bscan->rs_empty_tuples_pending += noffsets;
+			continue;
+		}
+
+		return tbmres->blockno;
+	}
+
+	/* not reachable */
+	Assert(false);
+}
+
 /* ----------------
  *		initscan - scan code common to heap_beginscan and heap_rescan
  * ----------------
@@ -1067,6 +1133,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
+	scan->rs_cbuf = InvalidBuffer;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1213,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 														  scan,
 														  0);
 	}
+	else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
+														  scan->rs_strategy,
+														  scan->rs_base.rs_rd,
+														  MAIN_FORKNUM,
+														  bitmapheap_stream_read_next,
+														  scan,
+														  sizeof(TBMIterateResult));
+	}
 
 
 	return (TableScanDesc) scan;
@@ -1180,7 +1257,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	 * unpin scan buffers
 	 */
 	if (BufferIsValid(scan->rs_cbuf))
+	{
 		ReleaseBuffer(scan->rs_cbuf);
+		scan->rs_cbuf = InvalidBuffer;
+	}
 
 	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
 	{
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bd49ff969f5..f0da9b6fb84 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2117,82 +2117,72 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
 
 static bool
 heapam_scan_bitmap_next_block(TableScanDesc scan,
-							  BlockNumber *blockno, bool *recheck,
+							  bool *recheck,
 							  uint64 *lossy_pages, uint64 *exact_pages)
 {
 	BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan;
 	HeapScanDesc hscan = (HeapScanDesc) bscan;
 	BlockNumber block;
+	void	   *per_buffer_data;
 	Buffer		buffer;
 	Snapshot	snapshot;
 	int			ntup;
-	TBMIterateResult tbmres;
+	TBMIterateResult *tbmres;
 	OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
 	int			noffsets = -1;
 
 	Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
+	Assert(hscan->rs_read_stream);
 
 	hscan->rs_cindex = 0;
 	hscan->rs_ntuples = 0;
 
-	*blockno = InvalidBlockNumber;
-	*recheck = true;
-
-	do
+	/* Release buffer containing previous block. */
+	if (BufferIsValid(hscan->rs_cbuf))
 	{
-		CHECK_FOR_INTERRUPTS();
+		ReleaseBuffer(hscan->rs_cbuf);
+		hscan->rs_cbuf = InvalidBuffer;
+	}
 
-		if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
-			return false;
+	hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream,
+											 &per_buffer_data);
 
-		/* Exact pages need their tuple offsets extracted. */
-		if (!tbmres.lossy)
-			noffsets = tbm_extract_page_tuple(&tbmres, offsets,
-											  TBM_MAX_TUPLES_PER_PAGE);
+	if (BufferIsInvalid(hscan->rs_cbuf))
+	{
+		if (BufferIsValid(bscan->rs_vmbuffer))
+		{
+			ReleaseBuffer(bscan->rs_vmbuffer);
+			bscan->rs_vmbuffer = InvalidBuffer;
+		}
 
 		/*
-		 * Ignore any claimed entries past what we think is the end of the
-		 * relation. It may have been extended after the start of our scan (we
-		 * only hold an AccessShareLock, and it could be inserts from this
-		 * backend).  We don't take this optimization in SERIALIZABLE
-		 * isolation though, as we need to examine all invisible tuples
-		 * reachable by the index.
+		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+		 * all empty tuples at the end instead of emitting them per block we
+		 * skip fetching. This is necessary because the streaming read API
+		 * will only return TBMIterateResults for blocks actually fetched.
+		 * When we skip fetching a block, we keep track of how many empty
+		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+		 * all NULL tuples.
 		 */
-	} while (!IsolationIsSerializable() &&
-			 tbmres.blockno >= hscan->rs_nblocks);
+		*recheck = false;
+		return bscan->rs_empty_tuples_pending > 0;
+	}
 
-	/* Got a valid block */
-	*blockno = tbmres.blockno;
-	*recheck = tbmres.recheck;
+	Assert(per_buffer_data);
 
-	/*
-	 * We can skip fetching the heap page if we don't need any fields from the
-	 * heap, the bitmap entries don't need rechecking, and all tuples on the
-	 * page are visible to our transaction.
-	 */
-	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
-		!tbmres.recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
-	{
-		/* can't be lossy in the skip_fetch case */
-		Assert(!tbmres.lossy);
-		Assert(bscan->rs_empty_tuples_pending >= 0);
-		Assert(noffsets > -1);
+	tbmres = per_buffer_data;
 
-		bscan->rs_empty_tuples_pending += noffsets;
+	Assert(BlockNumberIsValid(tbmres->blockno));
+	Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
 
-		return true;
-	}
+	/* Exact pages need their tuple offsets extracted. */
+	if (!tbmres->lossy)
+		noffsets = tbm_extract_page_tuple(tbmres, offsets,
+										  TBM_MAX_TUPLES_PER_PAGE);
 
-	block = tbmres.blockno;
+	*recheck = tbmres->recheck;
 
-	/*
-	 * Acquire pin on the target heap page, trading in any pin we held before.
-	 */
-	hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
-										  scan->rs_rd,
-										  block);
-	hscan->rs_cblock = block;
+	block = hscan->rs_cblock = tbmres->blockno;
 	buffer = hscan->rs_cbuf;
 	snapshot = scan->rs_snapshot;
 
@@ -2213,7 +2203,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	/*
 	 * We need two separate strategies for lossy and non-lossy cases.
 	 */
-	if (!tbmres.lossy)
+	if (!tbmres->lossy)
 	{
 		/*
 		 * Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2277,7 +2267,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	Assert(ntup <= MaxHeapTuplesPerPage);
 	hscan->rs_ntuples = ntup;
 
-	if (tbmres.lossy)
+	if (tbmres->lossy)
 		(*lossy_pages)++;
 	else
 		(*exact_pages)++;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3b4ea0f6144..6df34094a13 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -51,10 +51,6 @@
 static void BitmapTableScanSetup(BitmapHeapScanState *node);
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
-static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
-static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
-static inline void BitmapPrefetch(BitmapHeapScanState *node,
-								  TableScanDesc scan);
 static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
 
 
@@ -62,14 +58,6 @@ static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
  * Do the underlying index scan, build the bitmap, set up the parallel state
  * needed for parallel workers to iterate through the bitmap, and set up the
  * underlying table scan descriptor.
- *
- * For prefetching, we use *two* iterators, one for the pages we are actually
- * scanning and another that runs ahead of the first for prefetching.
- * node->prefetch_pages tracks exactly how many pages ahead the prefetch
- * iterator is.  Also, node->prefetch_target tracks the desired prefetch
- * distance, which starts small and increases up to the
- * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in a
- * scan that stops after a few tuples because of a LIMIT.
  */
 static void
 BitmapTableScanSetup(BitmapHeapScanState *node)
@@ -102,14 +90,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		 */
 		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
 
-#ifdef USE_PREFETCH
-		if (node->prefetch_maximum > 0)
-		{
-			pstate->prefetch_iterator =
-				tbm_prepare_shared_iterate(node->tbm);
-		}
-#endif							/* USE_PREFETCH */
-
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
 	}
@@ -119,15 +99,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 									pstate->tbmiterator :
 									InvalidDsaPointer);
 
-#ifdef USE_PREFETCH
-	if (node->prefetch_maximum > 0)
-		node->prefetch_iterator =
-			tbm_begin_iterate(node->tbm, dsa,
-							  pstate ?
-							  pstate->prefetch_iterator :
-							  InvalidDsaPointer);
-#endif							/* USE_PREFETCH */
-
 	/*
 	 * If this is the first scan of the underlying table, create the table
 	 * scan descriptor and begin the scan.
@@ -158,7 +129,6 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 	node->initialized = true;
 }
 
-
 /* ----------------------------------------------------------------
  *		BitmapHeapNext
  *
@@ -172,10 +142,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 	TableScanDesc scan;
 	TupleTableSlot *slot;
 
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-#endif
-
 	/*
 	 * extract necessary information from index scan node
 	 */
@@ -204,37 +170,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 			CHECK_FOR_INTERRUPTS();
 
-#ifdef USE_PREFETCH
-
-			/*
-			 * Try to prefetch at least a few pages even before we get to the
-			 * second page if we don't stop reading after the first tuple.
-			 */
-			if (!pstate)
-			{
-				if (node->prefetch_target < node->prefetch_maximum)
-					node->prefetch_target++;
-			}
-			else if (pstate->prefetch_target < node->prefetch_maximum)
-			{
-				/* take spinlock while updating shared state */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_target < node->prefetch_maximum)
-					pstate->prefetch_target++;
-				SpinLockRelease(&pstate->mutex);
-			}
-#endif							/* USE_PREFETCH */
-
-			/*
-			 * We issue prefetch requests *after* fetching the current page to
-			 * try to avoid having prefetching interfere with the main I/O.
-			 * Also, this should happen only when we have determined there is
-			 * still something to do on the current page, else we may
-			 * uselessly prefetch the same page we are just about to request
-			 * for real.
-			 */
-			BitmapPrefetch(node, scan);
-
 			/*
 			 * If we are using lossy info, we have to recheck the qual
 			 * conditions at every tuple.
@@ -257,31 +192,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
 
 new_page:
 
-		BitmapAdjustPrefetchIterator(node);
-
 		/*
 		 * Returns false if the bitmap is exhausted and there are no further
 		 * blocks we need to scan.
 		 */
-		if (!table_scan_bitmap_next_block(scan, &node->blockno,
+		if (!table_scan_bitmap_next_block(scan,
 										  &node->recheck,
 										  &node->stats.lossy_pages,
 										  &node->stats.exact_pages))
 			break;
-
-		/*
-		 * If serial, we can error out if the prefetch block doesn't stay
-		 * ahead of the current block.
-		 */
-		if (node->pstate == NULL &&
-			!tbm_exhausted(&node->prefetch_iterator) &&
-			node->prefetch_blockno < node->blockno)
-			elog(ERROR,
-				 "prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
-				 node->prefetch_blockno, node->blockno);
-
-		/* Adjust the prefetch target */
-		BitmapAdjustPrefetchTarget(node);
 	}
 
 	/*
@@ -305,225 +224,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
 	ConditionVariableBroadcast(&pstate->cv);
 }
 
-/*
- *	BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- *	We keep track of how far the prefetch iterator is ahead of the main
- *	iterator in prefetch_pages. For each block the main iterator returns, we
- *	decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-	TBMIterateResult tbmpre;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (node->prefetch_pages > 0)
-		{
-			/* The main iterator has closed the distance by one page */
-			node->prefetch_pages--;
-		}
-		else if (!tbm_exhausted(prefetch_iterator))
-		{
-			tbm_iterate(prefetch_iterator, &tbmpre);
-			node->prefetch_blockno = tbmpre.blockno;
-		}
-		return;
-	}
-
-	/*
-	 * XXX: There is a known issue with keeping the prefetch and current block
-	 * iterators in sync for parallel bitmap table scans. This can lead to
-	 * prefetching blocks that have already been read. See the discussion
-	 * here:
-	 * https://postgr.es/m/20240315211449.en2jcmdqxv5o6tlz%40alap3.anarazel.de
-	 * Note that moving the call site of BitmapAdjustPrefetchIterator()
-	 * exacerbates the effects of this bug.
-	 */
-	if (node->prefetch_maximum > 0)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_pages > 0)
-		{
-			pstate->prefetch_pages--;
-			SpinLockRelease(&pstate->mutex);
-		}
-		else
-		{
-			/* Release the mutex before iterating */
-			SpinLockRelease(&pstate->mutex);
-
-			/*
-			 * In case of shared mode, we can not ensure that the current
-			 * blockno of the main iterator and that of the prefetch iterator
-			 * are same.  It's possible that whatever blockno we are
-			 * prefetching will be processed by another process.  Therefore,
-			 * we don't validate the blockno here as we do in non-parallel
-			 * case.
-			 */
-			if (!tbm_exhausted(prefetch_iterator))
-			{
-				tbm_iterate(prefetch_iterator, &tbmpre);
-				node->prefetch_blockno = tbmpre.blockno;
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max.  Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		if (node->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (node->prefetch_target >= node->prefetch_maximum / 2)
-			node->prefetch_target = node->prefetch_maximum;
-		else if (node->prefetch_target > 0)
-			node->prefetch_target *= 2;
-		else
-			node->prefetch_target++;
-		return;
-	}
-
-	/* Do an unlocked check first to save spinlock acquisitions. */
-	if (pstate->prefetch_target < node->prefetch_maximum)
-	{
-		SpinLockAcquire(&pstate->mutex);
-		if (pstate->prefetch_target >= node->prefetch_maximum)
-			 /* don't increase any further */ ;
-		else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
-			pstate->prefetch_target = node->prefetch_maximum;
-		else if (pstate->prefetch_target > 0)
-			pstate->prefetch_target *= 2;
-		else
-			pstate->prefetch_target++;
-		SpinLockRelease(&pstate->mutex);
-	}
-#endif							/* USE_PREFETCH */
-}
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
-{
-#ifdef USE_PREFETCH
-	ParallelBitmapHeapState *pstate = node->pstate;
-
-	if (pstate == NULL)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (node->prefetch_pages < node->prefetch_target)
-			{
-				TBMIterateResult tbmpre;
-				bool		skip_fetch;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					/* No more pages to prefetch */
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-				node->prefetch_pages++;
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/*
-				 * If we expect not to have to actually read this heap page,
-				 * skip this prefetch call, but continue to run the prefetch
-				 * logic normally.  (Would it be better not to increment
-				 * prefetch_pages?)
-				 */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-
-		return;
-	}
-
-	if (pstate->prefetch_pages < pstate->prefetch_target)
-	{
-		TBMIterator *prefetch_iterator = &node->prefetch_iterator;
-
-		if (!tbm_exhausted(prefetch_iterator))
-		{
-			while (1)
-			{
-				TBMIterateResult tbmpre;
-				bool		do_prefetch = false;
-				bool		skip_fetch;
-
-				/*
-				 * Recheck under the mutex. If some other process has already
-				 * done enough prefetching then we need not to do anything.
-				 */
-				SpinLockAcquire(&pstate->mutex);
-				if (pstate->prefetch_pages < pstate->prefetch_target)
-				{
-					pstate->prefetch_pages++;
-					do_prefetch = true;
-				}
-				SpinLockRelease(&pstate->mutex);
-
-				if (!do_prefetch)
-					return;
-
-				if (!tbm_iterate(prefetch_iterator, &tbmpre))
-				{
-					Assert(!BlockNumberIsValid(tbmpre.blockno));
-					/* No more pages to prefetch */
-					tbm_end_iterate(prefetch_iterator);
-					break;
-				}
-
-				node->prefetch_blockno = tbmpre.blockno;
-
-				/* As above, skip prefetch if we expect not to need page */
-				skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
-							  !tbmpre.recheck &&
-							  VM_ALL_VISIBLE(node->ss.ss_currentRelation,
-											 tbmpre.blockno,
-											 &node->pvmbuffer));
-
-				if (!skip_fetch)
-					PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
-			}
-		}
-	}
-#endif							/* USE_PREFETCH */
-}
-
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */
@@ -580,24 +280,12 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 		table_rescan(node->ss.ss_currentScanDesc, NULL);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/* release bitmaps and buffers if any */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 	node->tbm = NULL;
 	node->initialized = false;
-	node->pvmbuffer = InvalidBuffer;
 	node->recheck = true;
-	/* Only used for serial BHS */
-	node->blockno = InvalidBlockNumber;
-	node->prefetch_blockno = InvalidBlockNumber;
-	node->prefetch_pages = 0;
-	node->prefetch_target = -1;
 
 	ExecScanReScan(&node->ss);
 
@@ -666,17 +354,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		table_endscan(scanDesc);
 	}
 
-	/* If we did not already clean up the prefetch iterator, do so now. */
-	if (!tbm_exhausted(&node->prefetch_iterator))
-		tbm_end_iterate(&node->prefetch_iterator);
-
 	/*
 	 * release bitmaps and buffers if any
 	 */
 	if (node->tbm)
 		tbm_free(node->tbm);
-	if (node->pvmbuffer != InvalidBuffer)
-		ReleaseBuffer(node->pvmbuffer);
 }
 
 /* ----------------------------------------------------------------
@@ -709,18 +391,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
 
 	scanstate->tbm = NULL;
-	scanstate->pvmbuffer = InvalidBuffer;
 
 	/* Zero the statistics counters */
 	memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
 
-	scanstate->prefetch_pages = 0;
-	scanstate->prefetch_target = -1;
 	scanstate->initialized = false;
 	scanstate->pstate = NULL;
 	scanstate->recheck = true;
-	scanstate->blockno = InvalidBlockNumber;
-	scanstate->prefetch_blockno = InvalidBlockNumber;
 
 	/*
 	 * Miscellaneous initialization
@@ -760,13 +437,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	scanstate->bitmapqualorig =
 		ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
 
-	/*
-	 * Maximum number of prefetches for the tablespace if configured,
-	 * otherwise the current value of the effective_io_concurrency GUC.
-	 */
-	scanstate->prefetch_maximum =
-		get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
-
 	scanstate->ss.ss_currentRelation = currentRelation;
 
 	/*
@@ -870,12 +540,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
 		sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
 
 	pstate->tbmiterator = 0;
-	pstate->prefetch_iterator = 0;
 
 	/* Initialize the mutex */
 	SpinLockInit(&pstate->mutex);
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 	pstate->state = BM_INITIAL;
 
 	ConditionVariableInit(&pstate->cv);
@@ -912,17 +579,11 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
 		return;
 
 	pstate->state = BM_INITIAL;
-	pstate->prefetch_pages = 0;
-	pstate->prefetch_target = -1;
 
 	if (DsaPointerIsValid(pstate->tbmiterator))
 		tbm_free_shared_area(dsa, pstate->tbmiterator);
 
-	if (DsaPointerIsValid(pstate->prefetch_iterator))
-		tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
 	pstate->tbmiterator = InvalidDsaPointer;
-	pstate->prefetch_iterator = InvalidDsaPointer;
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 131c050c15f..507d4ebe68f 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -797,28 +797,12 @@ typedef struct TableAmRoutine
 	 * always need to be rechecked, but some non-lossy pages' tuples may also
 	 * require recheck.
 	 *
-	 * `blockno` is the current block and is set by the table AM. The table AM
-	 * is responsible for advancing the main iterator, but the bitmap table
-	 * scan code still advances the prefetch iterator. `blockno` is used by
-	 * bitmap table scan code to validate that the prefetch block stays ahead
-	 * of the current block.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses md.c as its
-	 * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
-	 * blockids directly to the underlying storage. nodeBitmapHeapscan.c
-	 * performs prefetching directly using that interface.  This probably
-	 * needs to be rectified at a later point.
-	 *
-	 * XXX: Currently this may only be implemented if the AM uses the
-	 * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
-	 * perform prefetching.  This probably needs to be rectified at a later
-	 * point.
+	 * Prefetching additional data from the bitmap is left to the table AM.
 	 *
 	 * Optional callback, but either both scan_bitmap_next_block and
 	 * scan_bitmap_next_tuple need to exist, or neither.
 	 */
 	bool		(*scan_bitmap_next_block) (TableScanDesc scan,
-										   BlockNumber *blockno,
 										   bool *recheck,
 										   uint64 *lossy_pages,
 										   uint64 *exact_pages);
@@ -1966,16 +1950,11 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths,
  * `recheck` is set by the table AM to indicate whether or not the tuples
  * from this block should be rechecked.
  *
- * `blockno` is the current block and is set by the table AM and is used by
- * bitmap table scan code to validate that the prefetch block stays ahead of
- * the current block.
- *
  * Note, this is an optionally implemented function, therefore should only be
  * used after verifying the presence (at plan time or such).
  */
 static inline bool
 table_scan_bitmap_next_block(TableScanDesc scan,
-							 BlockNumber *blockno,
 							 bool *recheck,
 							 uint64 *lossy_pages,
 							 uint64 *exact_pages)
@@ -1989,7 +1968,7 @@ table_scan_bitmap_next_block(TableScanDesc scan,
 		elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding");
 
 	return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
-														   blockno, recheck,
+														   recheck,
 														   lossy_pages,
 														   exact_pages);
 }
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 575b0b1bd24..d4d4e655180 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1840,11 +1840,7 @@ typedef enum
 /* ----------------
  *	 ParallelBitmapHeapState information
  *		tbmiterator				iterator for scanning current pages
- *		prefetch_iterator		iterator for prefetching ahead of current page
- *		mutex					mutual exclusion for the prefetching variable
- *								and state
- *		prefetch_pages			# pages prefetch iterator is ahead of current
- *		prefetch_target			current target prefetch distance
+ *		mutex					mutual exclusion for state
  *		state					current state of the TIDBitmap
  *		cv						conditional wait variable
  * ----------------
@@ -1852,10 +1848,7 @@ typedef enum
 typedef struct ParallelBitmapHeapState
 {
 	dsa_pointer tbmiterator;
-	dsa_pointer prefetch_iterator;
 	slock_t		mutex;
-	int			prefetch_pages;
-	int			prefetch_target;
 	SharedBitmapState state;
 	ConditionVariable cv;
 } ParallelBitmapHeapState;
@@ -1879,18 +1872,11 @@ typedef struct SharedBitmapHeapInstrumentation
  *
  *		bitmapqualorig	   execution state for bitmapqualorig expressions
  *		tbm				   bitmap obtained from child index scan(s)
- *		pvmbuffer		   buffer for visibility-map lookups of prefetched pages
  *		stats			   execution statistics
- *		prefetch_iterator  iterator for prefetching ahead of current page
- *		prefetch_pages	   # pages prefetch iterator is ahead of current
- *		prefetch_target    current target prefetch distance
- *		prefetch_maximum   maximum value for prefetch_target
  *		initialized		   is node is ready to iterate
  *		pstate			   shared state for parallel bitmap scan
  *		sinstrument		   statistics for parallel workers
  *		recheck			   do current page's tuples need recheck
- *		blockno			   used to validate pf and current block stay in sync
- *		prefetch_blockno   used to validate pf stays ahead of current block
  * ----------------
  */
 typedef struct BitmapHeapScanState
@@ -1898,18 +1884,11 @@ typedef struct BitmapHeapScanState
 	ScanState	ss;				/* its first field is NodeTag */
 	ExprState  *bitmapqualorig;
 	TIDBitmap  *tbm;
-	Buffer		pvmbuffer;
 	BitmapHeapScanInstrumentation stats;
-	TBMIterator prefetch_iterator;
-	int			prefetch_pages;
-	int			prefetch_target;
-	int			prefetch_maximum;
 	bool		initialized;
 	ParallelBitmapHeapState *pstate;
 	SharedBitmapHeapInstrumentation *sinstrument;
 	bool		recheck;
-	BlockNumber blockno;
-	BlockNumber prefetch_blockno;
 } BitmapHeapScanState;
 
 /* ----------------
-- 
2.34.1

cyclic_eic16_ioc16_ra4096.pngimage/png; name=cyclic_eic16_ioc16_ra4096.pngDownload
�PNG


IHDR�X��%:tEXtSoftwareMatplotlib version3.10.0, https://matplotlib.org/�rXr	pHYsaa�?�i�IDATx���w\TW�����;R��������]�`��R7�I���1�t��/e�F������[�X���b/(�H���?nBlh�A����k��3�>w���s�s,�a��������C99:Q�.""""""R!(A����������TJ�EDDDDDD*%�"""""""�t�
@	�������H�]DDDDDD�P�.""""""R(A����������TJ�EDDDDDD*%�"""""""�t�
@	�������H�]DDDDDD�P�.""""""R(A����������TJ�EDDDDDD*%�"""""""�t�
@	�������H�]DDDDDD�P�.""""""R(A����������TJ�EDDDDDD*%�"""""""�t�
@	�������H�]DDDDDD�P�.""""""R(A����������TJ�EDDDDDD*%�"""""""�t�
@	�������H�]DDDDDD�P�.""""""R(A����������TJ�EDDDDDD*%�"""""""�t�
@	�������H�]DDDDDD�P�."���_~����0�[�z����1b�c���K�b�XX�t��C�b�t�B�.]�S�L�b��g��K�o�.]h��a��7T������@	��H)|��GL�2��ap��!^~�e6m���P�>|���~��]����{�/


?~<���������P������/�+d���}��4l�ggg���/���]�q�������Idd$�=�\�+������b����s��������7>>>2t�P�;vV��;w2d�*U����7�pK�,9�1m6�1M�6������ �u��������DDJ�����\
>��#*W�\!F�:�+��Bxx8M�6ut8��;prr�w��:u�������]�s����7�x���H5j����������~���j�*���^7n��'X�f
YYYT�^����`���~���������h��9U�V�`�M�6��K�U����?NPP���c���������������9o?p��:u������������o��������k��������];���y��'���f�������E���S����������6l�F����Sl������+~�""�]DD�����!�������=G�-HOO'00���xn�����}���X�l+V��u��er�+����?~<�&M��������u��s���l:�����d�<==�H<yyy���U�/��g��������]�2c���n?~<�N�b�����Y���[s��72e����>&L�@ff&[�n�^�z�{����_���_�_��~������S�2}�t|�/RD�"��HD�I+V��U�VxxxP�N>���s��<y2��u#$$wwwbbb����K�	g��m,[�����b���fdd��O��Q#|||����O�>������A����T�-[�����.������u�]������N�
������/]��V�Z0r�H{<g������}�v�?^��i��5����J�*���M���y�������ba���g�o���8;;s���R�|�U��������/���qww�z��6����W��og��!���A��-�9sf�>��A��5�}�v>|�8|}}	�h?����������i��5EEE�����b/�\5�iii�}��������A�&M�:u�ycj����wo~��7{�����}��R�Z�jU\]]/�o��l����^z	OOOrss�Z���8�����oy����V�^^^dgg���w��������E���Y�re�c����|�z����D�|����)��m��u�������3n�8l6�Y�~��G���G��Uqww�N�:���������D�v������U��7�<�O~~>/��u������5j0f����K�+�� �a�7�������E��]��m�9���k�v�:�m�����{����������������=9���QQQ|����������Y3{r��������a)))��w�}���[3x�`l6�N�*u�""W�F�E��������gO���y���)**���^"44����1
4`������0k�,|�Al6=�'N�������^�z�X�w�f���|��DDDp��Q>��S:w�Lbb�}���I�x��G2d�>�(yyyl���5k�p�wp��Q��m��ba��Q��O?q��w����������f��������w�}t�������v�Z�v��K/���/�|��������T�R�G}���0����={6�>�(C���������Y�f%���W_����X����C��IJJ�����y��?~��3gr��*W�\�c��u���j�����O��������A�HHH���Yi�����DGG3|��2[� 11�C���qc���>�N�JAA�5�����k��er���O��Kv����Q����`��i�1����������)S���O������X�|9���+-[���?��W^a��%e����s�E��-Y�~=nnn<��>��T_x��������O<��������x�b���C�-x���prr�'���/��fX�n�V����n�z�������?��.]�������G��k��������9`��)�����c��������y���������*����������Xn�����y���h��}���/U��+��������������#99��ui�^|�E��G��}���/6l�g���u=��w(�Bx�G��k������D�}���IKK�?���u����;��s~~>�*U:�����������$;;��k�������������CDD&L��[n)U�""e���4����0���koKLL4�����������u�^�z�k�.���A�s��g����3�Vk����T����;v�����n24hp�����n�J�*����K��v�m����=�u���1y�����d�0^z����������0j��e�8q��m6������~�Q�j���a���/��^z����Z�j�������/�1}���b���J�{��F�F������i���io;��-Y����)55�J\CiL�6����l���`����������'��������y��K:��;w.��8q�_~�������h������cdgg�a�/6��G9��������.�_�~F�Z��y�������w�i���/������b�o����g~��k�.����lFdd���W�����5"""�o��D�_�^����������G��f�{[ZZ����oFjj��y���^^^%���;w>�<���FXX�go���/'''c���%���'���r�������iii������_�����>{��@�Z���{����g...��m��0�������%��y���u����O��q0`�`���];0�~�m�0���������P���>2���+�u����b1~���R�/"R�4�]D�)V�����3h��� �������Y��<�����������3�w�&++���sww���Z�V�������^�zl����/  ��n��s�00`�ap��q��^�z���U�x���K�������IMMe�������[�
6�C��X������������K:Vi$$$��I�s�l_��222X�x1��r'O��?�����������S������ae��NN'O�d��E�1�#F�p�B�8�T��1w�\��������m���<��#����l�2���X,^z����������_�0�2����c��U+���K���;v,���*�V�b��E�}�����x�o��������������S�N��{w~�����?�������t���K@@@�����si��m�u������;�����<�|�����l��|||��?�a�������[�{�n{��i�����~��%�O�u�P�5]����RPP��?\��>z��s>�{��)��yAA������?�ILL�y��>}8��g��8��� 33�[o���7��������%g��y~������?��p�w�h�"���7n�E�)kJ�E��r��1N�>Mdd�Y������+W��G���	 88�g�}�T	��f����#22www*W�Lpp0[�l)q���z
Z�nMdd$=�P���c�����������K�9r$@��(|�6�b�)�x��T�R�����~��|�
7�t����t���UV{<����0x���zL�$��{L���.��d�C���Q��^�fMn��V�ZU&���w/���g-�m����j��k:��:�X��K�^�w����?��K>|�Y���>����|�k����������Q���>33�����c�W�z/��m����???����I�_���W�~�V�*U���%�g��mg]KTTP��_���3���^Opp�9����{������y��W.���s����`.���>}����>��_~�y����W�9s���k���p;�?""�6m��������X�v-EEE�}m""�C5�"r���k��w�~��������Q777����{��w����j�������u�]�����������K�?::�;v0{�l���GBB}�/��"������?���~�s5n��l.�8;;s�w0i�$>��#V�\��C�J��UTg�'�x���'���[�!���u��fBHH�9��V���		(��^�����y����[����Lb���3y�dF�M�v�����b�p�m���}��233���3~~~�;�:u������
x����:����9�cF��i������9�����,�/WVV�����$;;��P_NN�a�g����		�J�*�\������]5j#G�d��-�����iS���������k����S�N���_�."rJ�E�����g�Uz���cG��g��E~~>3g�,1��S?�8�����x�v�j��wFff�Y�y{{s���r���RPP@ll,����<�������b�Z������R�z�K�:u��u�E�7l�0�y�f���O?�Dppp���R�U��������]�6`N�������.U�F�puu=���C�\&��U�[�l�f��E?3��V�Z��X��?����rEo���&M:��8t�@�=P�;������<>>������;���������,��V�Z�z/Z�t)���L�>�������zvu��a���t������}<�|HII������s�_��8q����|��s�nDDDp�M71c��U�Fppp���X�v�9�T����]�v��.\���':t�=,,���5�L!���)�"rMqvv�W�^��1�}��������?�Y}���SVV�'O>�����g}�>s�?�����~�KOO/����111�Aaa!���������p����c%b�Oi�Yk��9L�8�����z7nL�������HHH���n+�
���b�����y3?���Y�]��BBB����~��9G�����Ui��R�Y+-___�����U�J�'%%�j�*n���29O��}9r��}�������>�:w����0�9�����l�VZ7�t���L�<��H�g�}Pf��_��S���~�^��g~���u����%Z��}���_Y�vm���)������YPP�G}t��s�-�p��A&M�t�m�O��o'V���=z����|P�����y��l��?�p���]�����?��3�<c���������m��E$''s��7_�\�V�b����}��%F�o��V�����?�lo;~�8?��#��u;�DD�J���\s^y����G��y���IG�
��e��_��=qssc��������0i�$BBB�J�Z�h����q��[�.!!!t������3v�XF�I�����������J�0�9WXX:t 44���$>��C���g��0aK�,�M�6�{����������
X�p!�92�'�|���/����i�����Ro��������h��)#G��J�*l���m����e��a�x��'���~����'�|���xn��f���.Z�hAFF3g���O>�I�&����e�.������7�p�5��{��v��=z���Ws���s�W)�t����Yt����_|�+V�������?~<�-�[�n<��#����&00�^|��b�s��g��~1��w�~�)#F�`���������+�8q��y��kW�����oRRR���76�������kWF�\�6k[�l��E�s�N�Tg�&M�0`����x���x�����7�
b���L�4��o��V�Z��9e�F�����1b�%=`��?��3���C�
9r$��U����,Y�???f��@������/���'&&���W�p�B���Js��1|������G}������g�o��J�*1|�py�,_|��%)�gC���������'K�,�C�X�V�o��������i��e�����y��'x������?}��e������O����4��yyy1h����g�����k����g�e��it���G}����z�-5jd_��z�[n�����m����Oh��1���/q�g�y�������8{�1������O(,,<���H�(��ED���e��-ZnnnF����O>����|��9�h������a���o�����������#G�~�����`��*//�x����*U����F����W������~jt���

2����:u�O>�����U"��G�=��Q�F
����3�w�n��?�)���4bbb�[��v��3V�Xa�x���������m4n�������w��a���������c�f�5�0���tc��QF�j�777�z������Kl?��E#,,�T��k�.c��aFXX����jT�V�����o���m�J{M���p��~�z�G��������k�t�MFrrr�>'O�4���n������4��6r�H�r��������Q�sn�WTTd���[F���
777#88������~�z{�K�fm����}��X�l6��>0���WWW�F����?o�����1o������z��i��}���Fll���Z�V-��[n1-Zd�s��	�����c������}�9��[�l1:w�lxxx��U3^}�U�����Y�1+W�4��mkxzzU�V5��c��?����s�����q���gmkVPP`���F�
www�R�JF�-�W^y��{Oi��V���+�����t�bl�����})����Z����[�n5z��ixyy��w�i9r�D������n2���777#""�x�����v��]�v�6���OOO�[�n���k/+v���b��Y�.?~�*U����/��/84��'O���y�������;�����y�f5j��p��[na��=%�����\m4�]DD.j��)X�V���P���_�V���{��Cq�%K�p�m�]���a,]��/���������-A��Z�x1������t������;:$�k�t9�.]��j�*:t���_~I�j������5K	�������H��EDDDDDD*%�"""""""�Vq���l6:���/���������������'�Z�*NN����_g:D�5������T����z���CP�~�����������G����F��AO	�u���v???%�"""""���
D�"""""""�t�
@	�������H�t9'��Jaa����Rruu�����a��������]J0�#G������P��E>DDDDD�RJ���3�yHH^^^J���a���KZZU�TqpD"""""r9�����j�'�AAA�G.���'iii���h�������UH������s///G"����Mk�����\����Y4������������M	�������H�]�S�L!  ����/�L��M/x�#F0h��+������HYP�.W��#�X,�AAA����-[�\�qn��V����X\�^f��%�R.z������9|�0�-�������_�1<==			)����}{L�`�������[Wf��%�R.���	#,,��M����O��~�;���K�X,dff���i�&,{������WV���{������3f�a������=���0��g�e���%����_�t���Q�5j���T�\�^x��9���y��'�V�����i���K�^�#'""""�
��`��t~�t��������YU�OJ���������_R�n�2�o��w�a��)|����X����~����:�=����y��#��g�&77�[o���6u�T\\\X�v-���>���.�}����Q�F�z�j���[�l���7�L���III�������������>�W�v�O���X����/~g�n(A�r1{�l|||��������3g��w���TvO��'��3�Ktt4�|�	����u����S�^=���{���������������Q���{�z��q��w�����{��o�>&O���i����#u����'���n`����bEDDD��1o�a�r���J�����/7(I;%�R.�v���M���ik���W�^�����{�������8|�0m���������e��>�=��cO��=�O?��]w�U�O��mK�?��];RRR�Z�����X�V����_N����l�2v��u�q�������j3xeV"���~���Y���.�8:�>x{{S�n]���}����L�4�q���G��\�]XXX�q���a�x���Y�z5�V�"""��;���9998;;�~�z���K���Qx�v�M�8k����pVkS3hW���?���]�b������������T�T	0�+-�T���5k���EEE�_�����_V�AAA4���'�z����X�fM����W"##qvv�Y�fX�V���.)��kGZ�����N���\���K�������#�8q�?����@��u�Q�/��2���������;�t�G}�	&I���y��wK�
9��������je���g��o�>{�1���~6l��|`�;**�;���a����;���Y3�;��E�h��1����[�����H���`/+]ic����F�J��\��7�*U����K����6m]�t����o���x�����U+����7�\�s<���>|��������]w�����������{��A�*Uh��U�V=��a��q��iZ�n���3�>�(��w�����'3n�8�q<H���i���%�/""""W�c'�y{��_��������uD`��&����F�r����������,���J����Gjj*xx�<0���U��������-q[�.]h��)'NtLp�������c�Y��r.�IN~�T�M�@��a+@����,5��?���a��
���A9������y��w`����IDDDD*(�0���(��&�/#����yi@-j�#�A�n�2+���qa��4 �!��TLJ�E�a��}DDDP�zu�L����^*""""r��������������3�w}b�U���x;��
�pcLkS3H;�G��9���O}D�u��Cxx8��X�ti�#""""NzN>o/H��u�������#x�K]����f9;Y���\�t�R*(�1u���(�����kT�����F�������t��0�EIi�67����hP�������F��l(A����'yuv"�S�P���'{�cH��!�2�]DDDDD�2N����|�vV����w��C]���������]DDDDD�O
�6�X������3��{5�����
�vptr-S�."""""��%��xuN"���u���|yq@��Tvpdr=P�.r^~�ef����M���������i'yuv�������=�qk+��K�Q�.e�j3X��A��<B|=h�7��(((�����a����\�2s��0�/~���f��laD�p�������99:����z��X���~��o7q��_������z����K�.<����=�J�*��I�8u�#G������u���O?`�Z�����������z�������8���Ki��5�����C�����)Sx��W��y3�����)S�����{�!88???�u�������|���i��)�}�xxx\��EDDDD���j�������LY����Gt(������(9�����y[���0��~$+������hN��U����N���1cX�v-�}�<�?�����g�����c������WWW�W���i�

b��U�w�}T�R�[n����"
�����7�|CAAk���b�p����u�V������������o�����~�	>��S�w�Nrr2����������O�����{<DDDD��~I>���II� *�����12������b�_�)��egg���OVV~~~%n���#55����a�.�^��V�A�w�q4;���[�P?~~�S���{�:c��~Z|�.]�Z�,_����j������X����p���T�����i���Y�5jG�!>>������X�t)�;w>���j�W�XA�~�HKK�����^�n]���}����/�����9x� ��e��\�?)��X��Ib��4*y����Q���&.�������A�:]h%����8p$;�F//(U�����r���g��������LPP�5�������f�!������9���������iS1b�z���o�G��r�-T�r��7o&''������O�f��]��k��U��������_��B��(����Pd3pq�0�]8�v���KS���P�.�W��o���D��y�����~�O<�;��C�v��������b��5���'O��Ga��y|��w<��������}����J�*,]����������3EDDD�C����������d�*�k�`��C�G'r6%�rA���$��u�~kS31y�E�M�����:���r�J��o��>ho��(���5�Y�f<��3�k�������m������Zr����9r�...���_��EDDD��V�<����l?r�:����?�.�B���)A��X,��j�12�*���;k�80k���=�\!�\���������'""�/���u��@jj*���8p U�Ve�����0l�0���IMMe��MT�^___z��A�v�4ho��&QQQ:t�9s�0x�`Z�l��K�.�9~��s�X�xOWF���mk�z����E�P)�N^��������1"9���������[o�M�6����M���b�������}���C=����@\\�{��k����7�`�X�;w.�:ub���DEEq�m��w�^{������\'�
y}n=����Gqv�0�]-�>���"���UA��_g.u�K5o�a^�����<{[^sE�X��."""�'��`�o�y{����u�#+�B��B}]��U�+Mq�2��an�	cmji'����uD`�9�k����;+����DT���~�t�rI[��TJ���9;YhW'��EDDDD.���\��M���G��p����k�������K	������\r���h�N>[�JA�
'���&��E��������������H�f�$l8���wp�d>���B����vZ�J�EDDDD��Z�'�����`���x�o47����\�9J�EDDDD��9p"�	?mg�������p�����������2�������H��[P��Kw��_v�_d�b��Z������:s��)A���fl:���s4��3o��bhP������%�"""""�P����Y�l��	@�J�<�7��
�Tg.�%�"""""���N3�������n�<��.w���������]DDDDD���+����O��"���3��:O��G�����q%�R�lV��
r��O(�jN�TDDD�zg37����s(+���*���4��:s'G ����0�!L�	w��?���~�����#����7�p�����>s�L"##����k��L�:��Bff��KDDDDL��g��*�v�������w4c�?�)9��t);�3��a�}�d{�a��
&�c��!!!��S��a����K�^���� 55�!C�0h� 6o������s�=w�b�bG��x��M��+��/OWg�1�E�w���ZN�O4�].�0�0���lV�i`�� ��=���n���������S|���L�2�>}�0i�$~��g�������N�z�x����W�[�n���^+��EDDD���Z�l�n>Z���+���1�w}��Ug.r.J������������};����o��7�x�z������������������O�^�����

����o<�K�,�������������r�~���0�j�0G�'�(]�g��w��������B:t�`osuu�u��$%%q��	Z�jU�>�[�.u�""""Rz�a0����>w;3O��f/h@��
N��S�^N�-[�C=D�V�(**��g��g��$&&��m&������3g��M����Q�F���+�Z�������0V�Z����6l����?���'""""���Y�����=T����>��DS�EJC	z9�7o^���L�BHH����S�Ndee���������n��0y�d������_i��-, 11��J��My��Wy���x���qss+��]�������
�r�~w��������T�N���X�r%�j�����u��1z�h�?���sK�����������v2����`��x�:q�:���6^nJ9DJK���� 00����SXXH�=�}���O��5Y�z5m��e���4j�����^�z���m�6�5kV��Z,��j^��U5�;g����N�2�r����x�'�|���@j����o�Inn.w�}7�������<��S�}��l���)S��Q��\���Wh���������������Uy�w}�x:8�
H��E(Aw���������
6���#���P�ohh(G����sr~��3��K~~>����������2Jrr��o���c�d��G�{�{�0a6���C�r��IZ�l�����T��*U">>������v����s������~E������mGxmn�3�:�&��yq@Z�����*������������:f����
E��9�C=���[���o���^�u�����j�(�"m�#f ��?��R�����~�x<<<������c����c��%�8p )))����d�����^�:ZATDDD�Rl;����~��_n`�iB|�y��&��`%����������r6j�(f���/��B�����aaa���Yb����������]�����=j��\�y�{�1�����W>I����M�����h��AAA�\����z�Q�F94&�����|�Y��o���0�����:�����������lVs����?m~��t���^I��0~�a~���.]JDDD��[�h���+�-"..�;v�o�>��k@�v�x���HKK#$$���???bbb�y^ww��������������q�����f��<���<��3�KDDD��+(�1eU*,����"�5��3}�S�R���n�Yy��y	d4�*�gh)J���C=��_��?������f���OOO�������y��������~�v����m[z��ILLC���7����#<���<��C������{���{��a����\5�`aR��IdOz.
���b���tptW��c��KX������#W%�����?�K�.%�'O���#3�trr"..���|z���G}d��������y��h�����>��c���e�����u`��l��Nb������d�zi^''��s^�{��o�!i�
K_�����k��0�sC�5*;;������+q[^^���DDDh����~"""�we�*���w���}�psv���<��.>�3?�S���kX?�w�Wk	-����p���x���^�~��@C�2��\����V�����d��u�}��L�hj�������c�|&X�v7_h|3�	U�m��X�.J�EDDDD�S�a�dG��$���)����b���	rptTnl��O�����U�B���p�������������.vJ�EDDDD�C)GO���$~I>@��O���--k��:����jNa��X��vW�?F�G@�f>F��X*%�"""""����&.L��_�b��:[��Cu��������XN��������������hy����������K��]��1���Lf����PDDDDJ��j��_�����N�����s}�	�����*������m?@�i����B���Zs�h���=%�R��6+�6p,��^�4i��������8���c�:;��i9����1t�[���U yY��{s��������������������t)S�.d��	�=jo�
���O��V�r����77�r;����HE��X�f'�d�Yg^����{���V5pqvrpt�a��
��s�:
s�v�?F�GB��-�r�W����{����J$�i�i<��1�]x����KF������\�2�z���w��Q�Fx{{S�F
|�Arrr���2e
��?���h|||���7����Z�<��c��1c0���W�����#����7�p������t�R,����Y�fxzz��[7��������������;������+������#+�������/,�q'w���'����������u��O;�g�`��fr\��	�'����F+%�R���W�\�a��^��������u������&�������:�_����:u*nnn�\��O>�'''����m�6�N�����3fL��������o��_��/��o�>�x�	�����S�L���?g��ddd��?�8��1cHHH`���l����u���W/222J�{������Y�j�����[na���|�����3���\�u�����Qd����{���>_�J���[����/�����:_��F���]�<G~gwh|�5������\�,��dBr����������,���J����Gjj*xxx�[�K����{�k�X���W��w�����l6l�p�>������������9�>r�Hv��I�:u����;v,G��j����_���'�������Z�h��38u��*Ub��)�q�����y��'Y�t)]�ve���t���	&��3��k�.j��
�?��O�����y�.��2���'"""��)�yuv";���n�/���sT��#s���o.�vxSq{�(s
{���+�a�9��rq���5�E�%~^�p!���:��o';;���"���������L������9@�*UHKK ++�����M�...�l��>��k�.
��������+�[�&)�O[q�7��whh(^^^���L���k��� """�����xmN��2�/W��#�;����z��~x��[�A����ns����j���R�(A��t�d�k.�o���<��������G�mq�~�.�����������g��������^#00�+Vp��wSPP`O�]]KN��X,�5��4�|.��r�s�l�+rn��d�����L^�J����������#���t���S�bo�'������u�����	�AO�b���Y,�RM5o_�=�^���������P�P�Wm_.[��_����;����������I�����J�*�Y��N�:�������ys���c�{�U�`Nq_�n�G�.����f��o�y{��O�9*��GS7����9��m��-�A~����
���H���r�*(A�2�����������a�R"I�`�>���r��n����0`���q���Ge��	DFFR�~}�}�]233��{{{�����OH��5y��7�������.�+����;;���fZ;������~��#s�����31?��2�J���>�y��\u��K��Q��vy����?���r��I�&�������<��3t����_�a��]�q�q>����qrr����b���dee��L�0�����C9y�$-[�d���T���?EDD�l�K�e��$�m3���p��QkW���3O�nNa��
��������3k�#:��u���5C��_g.u��a�Y����c���
�yH�r9��iw�kON~��d'�]�J�����lS��E��uTg^��?�������5�-���:,���Vq�x4�.e����Va������U�f3�_�7���xN>7����c�v��K��S`��p���fq�z}�����4Z.�%�"""""���������f�yx�����Gt��a���|H�e���]Q��_��f��*��O�
R�.""""R���e�����r_w�������\�����)�����t���Q������Ae�r�S�.""""�@����x�.��|7Ef����j�x�(*��;:�+����6��_����A�a�l(�Ws\|"�L	�������l?l<����s4��3o[;��7 ��5�`WF�Y[��+8u��FD�4k����JU���g�����H9[�7����|��&�f�����W��k���Z;��������������A@
��'R(A)'�2O3�����|o7gFu�dd�p<\����{a�T��%����b���i��k�\P�.""""r��.����]|��.�
mX,ps��<��!����Y� y�Y[�s`���!�|�9Z^)���THJ�EDDDD��0�q�!�����Yy���14�������������8y���vW���^_pvu\|"�t�2�t�R�v���'pt8"""�@��g���ml��	@�O��M�Fa�V���
)����?�a3��*�{������UB	��9�j%���;�Kp0^-[`q�Fk��@�.]h��)'Ntt("""R�d�����L�x/7g�Z��o�������#�����#:�����������
)A�2��`G��N��#�6��0B�}��=�-������ADDD�O^����������t��������~�H���j����l���-��fwB�P��CC��99:�vd/X��GG�H��������^�����K�.�5���GS�rez����/�L��5qww�j��<��#����3f�8F@@S�L`��=X,���[��o���
6d��e%�3w�\�������k������������~��T�V
///5j�7�|c�}��,[��������b�c������BCC:t(��/��LDDD��a��|���,����9]h�E�J��P�������g�eo��M�����������o�������MA�2������Z9:�50�s,p���x�kW���O�K���:u*<�+W�d���?�o���
p��6o�|I�x��'�8q"111����0���T�����?���<��C�w�}���o<���%����G�-x������c��9:�:u���uk��}���i��!c�� 88���L�u��=���{������y������[X�x�%_����\��b��m��s���<��>�T����m6����-����<+A�;���rh�"�%�rA����h��d��'�j]���6����uI������7�������0z�����+5k��u�����F�E\\�1�������/c�����?�N�:���;f���������o��_�Z5�x�	��?�0��������u�����������aaa�~~�!��5c������?��5j���LT�����8RZvo��A��x�:�@�����6�nWy������KX?2���lg���������
H	�\3Z�(�"���of�����]���{��o_����=���kg�oZ�lIRRIII�i�����V+����������������E�|��y3K�,������v���]DD�A�
��wE*-���sDyP��<��>U�=��`�A�2��|�������vs�<$��!�\���Y<=��a�E����������j��S�Z�,�y/���w�yj�`��,\�����|���z�e�������b���t����K>�����[����L�8�F��������)((���rrr0`@���3�T�R�q���������G�S�3���&5xi@�kVrptC�1����'R����6�-�n�6�QD.�t� ��R����:�F�����C�Xp	
��C�r�r����0`�z�!�������N���	������)))����u�_��N�:PTT����5j�����9����r�Jn��&���`��HNN&&&�����
��Z�~��7'!!����K�����Pcg%�&5�0?��S���T���*�37����-O��?)�����fb���1�\���_������g������b)����@J����[r>e��V+m������/��OOOj��@�n����i��V����z
WW������DFF�{����'������?��;����O>�=����������I||<�V��R�J����=z�D���5k��g>>>��C1i�$n��v��C`` ;w���o����>�Y�����\q�N����|��~�]���Sm���^nW���S���ks�<}gq{�fmy�Xp�>��E���6kRf�z����q	
-��J��'��>�L�4�:��qc.\��Y�

��w��F�t���;���'�x��u�&L`��	4i��+V0s�L*W�@��5IHH`��4i��O>����n�?�<��7�W�^t�����0
T��O<���3111�o�>�V����+�Z�����F�1z�hpr��VDD�J�/����]t}{)��3���������<�������Y		����a��fr��-���������P%�"���k!�\�������'++??��������JDD��2�a����z���%8��-�m���������6n�H��MN����ODD�ze�2~n{����F��yi@-��%���������w�WijNao8��^�V�/�
�1�����jaqv����oi&"""�(��d���DV�L ���1������Sgn��Y[�8���vWoh4�L��6sh�"raJ�EDDD�������?'���}�psq���<��.>�W�G�����;31?�T����-ot3xhtT�jp�����������a�kGA��������R8�g����Q����F�U���a����}��N�"s�7\����Z��������t�n����i�6'���OS�����v���+��,���Y[~tkq{Hs
{�[���a�����]DDDD�)GO2vv"�S�P���'{�cH�8W�:s��C�)�[��\�hk&��[i�\��]����W'��DDD����&.L��5������yC8����������_�I�}����R�\��-or+xVr\|"R��������*77OOOG#�*7��6���QDD�zWh����{��0�����j��}��T���>���-�=
r�6gwh0�L�k��h��5J	��9;;@ZZ^^^X��_��Ann.iii�|��9/""r%,����9I�L3��a���?��u+;8����1�����6�E�S���^W�^�"r���K	aaa�$]��������jgZ��$�t�1��x�g���Y1����nNa��=�4��� z�������r���t)�b�P�JBBB(,,tt8RJ���9��ZVn!%�����\�,�h���#���`�_�`�fb~�����:�b4�����E��)A�srvvV�'"""^����k�����d���=�Cx�o4��}�_M4��o����6'W��o��Gt�h��uN	�����\�������$5���B}x�_�������m3��|����J����|*P�"�PJ�EDDD���z���Ida��fN��+����k�������pl�9�}�7��i�9�@��fmyDp� ��H��]DDDD�
Y��pq
SV���j��mW�G�G������0�f����U��5��ph6|C��TxJ�EDDD�B���]��w$�~��.��y�_uC*@���X?6}�O�mg����-��M��"R*J�EDDD��Z��8cg%����Y�`o��C�z!�
�(�f�������~�����~U��\�������H��/=���&2�Q�<\���Q��m-\Yg���x�<7�l�8Ad/���np�N8"ry������H�q2����d��=Xm8;Y��MM��#�J��3/*������S)n��
��A���_�1���5E	�����8��f�~?o�O�xN>#+�B��B}TF*l�
��S��h�@��fmydOp��i);zG�Z�;����v(����<�/�n�C�X,���v�5���Z\��f��7f��."r(A������?%1��#�z��h�H��������O�--�9�G��\���H��
�����\w������H�:�_�GKw2iy*E6�,p[��<~cA>����R��o���E�a�{�@����W
/�xD���]DDDD���f���o�����f�y�:A��?��*~�H�~��?���<\�^��Y[^��F�E�!������������Nd��,jy�l�hz���O���
)�����g0lf�Wehv'4Au�|""�]DDDD��������vfm>������ed�p�]�a���C�h���A������fmy���R���ED.@	���������">Y��O�M~�
�nmY��{�#��
'�6�YS�~2$�+-���w���+���1��\%�""""Rfl6�7���vp$;�����?�������O�
_���Y���ku0�����qec�������H������Jd��L�W������nv���m6����-��V��#����\���[D��)A���HVo����o/7g�Z��o����
���������
�{��k�5k�cnW�+sn�+D	�����\��V���n>Y����V,��:O��G���Jn�A�2��|��������631�.�����%�""""rI�`���L����,���e�J�4���_�:�S�a���a*d�.n����-o0�����""�L	����������������'����}���q���37����-O��B����b&�a
��|""�t����y�9o	����]�p_��e[g~*6
��@�������)�
������'"R�(A���+����������+��6�����	�/�:s���������Z`���@�����J��9��H�]DDDD�bs?���I�<
@����?�f5+��Ir3`���h����U��S�
w��9���U@	��������`cg'�65�0?��S���V��u��������3��\dWohg&�����s��\��������N����|�~?��N����w�������x:�|g���%��6��#��-�����!"r�S�."""r��/����=�������{�lR�����j����0��ofm���PdN����\���H���r�w���t���a��v��s����@����4 ��/��yY��{s�������s
{�[�3�o�."r-R�."""rJ:���Y����@��;O����f�pr��m��C����	Ph&��x@��fb^��F�ED.@	�����u$='��$���}�psq����y�K��/��a�I�}����R�^��9���m�YF����\�������\
�lL]��/J��u��W������u�<���-�=
r�6gw���L�k��h���%R�."""r
3�EIi�67����hX���7�u�%��������O�C���"�-���F����uN	�����5j����������T�qgL�z��������������{(8i�9�B�@��<������%�""""���S��s2_��k��;;qw��Z��������fb~�����:�b4��+_��ED�WJ�EDDD��V_������d��u����l�hj����h�9�}�w��e�9�Bt�?F�;�������t�k���i�:'����:��*~��?��uJ1�]x��0��k��+�C�����rE��bJ�EDDD�b;�N���$�% ����{���V5.^g~l�9�}�7��i�9�@����o]4Z."R�������\�2s��0�/~���f��lad�Fu�������X�I3��|����������aW�DD�,J�EDDD�"EV_���{���-�Gt(���&�����x<�O�M_����������u������9/%�""""W�_�����DR�r�
����
�!�<u�E��4�L��,/n����A���W��.""��]DDD���},���$�h{��\y�g=noU�s�����c��+�M7�,N���-��C��""�t�
*�t!�^���U{(��8Y�.�G�G����:���1��-O]V��[�x���z�^���`�Y����c���
�yHs��e���t�
��j��u�y��d2N��~����n�O����a*l�N���b����"{��>��8�����vGs���B�By���������IE�}3��/�����Z�*��3f��}��X,��z��]�OFFw�y'~~~p��w���S�W!"""W�������
�����S�
�a�]��|D����Z�3��������=39�	�NO��-��x��W��H�p�B[�X�� -7���>����T4z�.'�N��I�&�u�]�����O����<y��gww���y��>|������BF��}����_}Ec�+o��S�����D����+����mk�z��<s��
���3�-P��Y[��/�����;�����00�������7��A�]5�]����>}���O��qww',����&%%1o�<��[G��-������/o��6U�jV�����B>\���W�Rh5pv�0�m-F��$��
�E��'��|�B8�!�;�����p���K��������?308�{�
ih��#��H	z�t�RBBB�T���uc��q�z�j��9@�=prrb��5<�Qa����e���������x�Yg�)*��E�Y`��`�p�P�kw1�-��\���\��fe���������Yl��
*��	H�a�p�p,���%�%�D������%""�]�v������OV�^���3G�!$$��}\\\���#�=n~~>����������5���H���;���I<l�]�]����G�52����h2�,�f���24����:�\D.���#����wN�������w�����'����)7:����^��V*%��m��f��F���qc������K����e���_��W^)�EDD�o������I����������Q�q�m���?�>P|���fmy����~�������X~`9�)��8��_������v����}����_�Ix|����V��!��;l����WP�k��r���������FZZZ�>EEEddd��n��g���������M�5�X�"""r���">Z���V�RPd��w���������,�����Y	��iNc�\������9�����H�A�������Z1$r�ku�
�>�#����	�#Yqz����
L	zu������R�
���#33������E/^��f�M�6�=����Y�����H����7���;8v�,9�/W�Hp���y_q�Z��<z�z8(b��B[!��/#>9�U�V�Wg��^�AuK�����5kq9�y��9N�2��m=�mZ_����S�^Nrrr��s�����T6m�D`` ������+�����]�3fu���W�^DGG��wo���^>��
5j��v�Vp�����`��D~?��C�Sx��jB/�r����M��# ��#���������f��Az^���m���E���F7��K.���c��M*����i�8Q�^n~��7�v�j������������e��N�Jff&U�V�g������%F����+F�E���qrr"..�����~-"""r~N���O����0��b��r�����p��N5����17���C���+��h�"���Ysx��=�#�AuG
������,���!+a:y����\.�Z$N�b��� ��dgg���OVV~~~�GDD���[P��Kw1���4�m�N�E�v�
g��-w��&�����1�UD.lO�R��k&yX���Z{�D�s���:���6�V�&+a:'.�(0�N����]9�n��L8W�e��J�E�8;���SnP�h�RSSY�|9{��%77���`�5kF�v���Pm�����u�36�����9�g~r^L�����[���
���������p�B������o��`�`G&62�j>�J��`�~�~���3(:t���^�qq�
��K�Jd/X��GG��R2I�����>�L�'�R1)A?���������~����P�V����'������N�z�)j����pEDD�A6�� a�w�����N�pw5k�
7_,Mn5G��96H��]���O�g��Yd��[�9Y����
�B��qq*N�l�Os����L�N���i�N~~����\,11X,�k����	�O����):R�7�Kh(��>c�.���4k�777F�ABB�Y[�����z�j���[Z�l�G}��7���hEDD�>��?|H�#?���a�c��V�9N�Fbin��
RD�+�(�{������
��P�P�"�9�0����
� o�2��=w.�������	����{w�.�{�_���v�N�o�):v��`�Z���������?�}���IOOg��=�m���3�L�A���������n) ��[���lwTi�� E�B�O$�������8Ypg�3��wbH�:T���Sq�\t�8Y3g�9=����������;��A�p��wTRnP�(A���E(""r�N����
9�&�{r��y�K]���M��C���������2�|�S��rl����wU���Tw!^!�v�������L�N��ePd��X<<������x�n��������)7�x4��6l����+���c?��#�'O&&&��_~77��ADDD�J��������N����/�k����#����C�K���H����DBJsv�!�����bq�k���B��mq�'���v�9}:Y?��z�����Icb����g_}'W������y���i���w����nc���L�6���\&N���EDD�,���-��������h��4zv�P�wm���jFE*�S���)�'�����^�y
��F�2�� *{V��[sr��;������������M7;��u���������i��)��M�S�N|����\���n�M	������0��z�m2lM����6��em�����n����D��mVE*�0HLOdZ�4~J����\\�\�Q�qQq�km-7��u��J�N���yy��������\��S',���;������f��p�B���@�58��i/"""r��������������,5�Z����[�/h@�SD��d�I���K|J<�3���������c`��z��&k�2�A��}�v���	����@\����D�J	��l��q����G�-[��@jj*����NDDD.��
����hy�9�fsvg�kG����
F$U�=y�O}6��:s�
�0��B|r<�����3^����Q�C���2���uk+( g�"2�sj�Js�����_��������^�Ra(A���'r��w2c��{�9��QO��������Z�I�=��-?\\gZ��^������N��\��;���Mu�"EV~�w�&>9���;����k3$jj �#�����h�Y>{6��,{�W������gO�����DJE��]���<���q�
�R�����\Wm��S��iP`����;����t���|8U`��
jZ�1��S5��a��H1�0������x�]@�5wgwz��bH��7��~�8A��9dN�N~R��8.aa�D��������k���T<A�Z FDD��*8U<Z~hcq{P]�#X����a�i�F��4 ��5+9,d)�����]3IHI`w�n{{d�H�D�_�~���`X���ZE����,\�QX����{��w��X�5#F�J���R�J��A���������H���\�}��Pp�lsr����b$�����$~��
@��;O������prR���#��oG#>9����L��L�=]<���!QChT���sz���d��Y3~����q�c�	����?�q)"������i����7�^�z��];V�^����y������������4����kC���N����`��[�a����w���������B"��~:���f2=e:{������������_7_l��d�_@VB���f����������#:��/A�L��������+�F�*�����p�Bf�����������5�h�9�}�w���PN.P�?�	��(���U�|�h''�����
O��O�JZJ�Ql���G����}�(���O//������!��`�X0��7���t�����k�����:�{�w������������Q�~>>>l����z�;w��i�����8(������\�
O��fb�Mq{@-s���?�'�0X���ks��n~�oT����*<����+������9������7jH\T}"����
@aZ�3g��0���T{_��5	����M�����5\k�T<��uAAA����<���%���G�������u����|�7��i�Y��~_h1jw''��f��$V�<@��;cz�#�yu���8������j���Y�)E�9Z���C���5����0
9�p!�	�����Z�xz���q�x�l�=�����^y�����.]J�6mX�f
���c��I�NDD�V�I3��|���v���b4
���g�
x��|�f6�\�����Z��������2c���L���C��&�M����Wx/�\�R���2��5s&�?-����q�������w�_��#�/��1���h���3}�t���Y�b�=a�2t<�\�m��p���g��m����N��%�������0��<sd�O�0��M�@����'����C+��<�_�������������#�R����IN$|G����m�b?�spen�	��X�k�v�u�8�j��3�3�
�(�f�������~���0h>�����a,�����I�>~
��*~�4 ���U�&R���:����LO��������!�5�k������F���d&L�����fG|�v�?6����h��(7�x��������;IKK�f����S�N�JDD����x�<�����=����K����r�$��I���cT�q������e
�Ug.R.�lE�r�RXqp�}������u2$r�����96cY����A�1�#������h}'@	������q������N4�X,X�X�BDDDJ��v�1k�S���V1G��
����kfn�����k�a��:[��C��������.@��v0� 	�	���G�N���[��bH�������;��<�f�!kz�V�
|�v����?���h�P�������?�I��-�3gU�T�������H�
Sa�Wp���z��a��G��s,)��������0������	�����W��Q"WZ�����������C�00��J��Tw������cy�92=���s�eg��������[�8yz:�JD*>%����B||�Y�����H)Xa�O��������	5G���J�.x�e��xuv";�r�����ch_��^D�g�'!%�;g���noo[�-C����F7\�])�� c�T2����l��R�
�c�<���q	"W%���Mv���]DD�Rd���Sa���s���N7���^p����]�r7;�%;�:�@o7�1��Z�����JF/r]+��x�b���Ysx��=�#������K
�EE�Z���	�9�d	��[,nn��x#q�x�m��I�W�K��~�a�q�9B�F�pu-�a�q���LDD���A�|��|�B��������|8F\�0Y����(����C���������<�=O���\){����b����?���������T��N�����6�]�f����1��=6$ .��}q��w�e�\����8��?���aW�"q�JADD�T���?���<T����-��\�.z�"��o����;8�k��u��s����s�����[�Y�w!����v�7{{�g�#38r0�|�a;u��y���>������9��@�cc��W�� �r��G#������DDD*�R~6k�S��+�M��# �N��"�8��Nd���D���B�:E_��EdW�.�����{Y�Y8Y��X�#q�qt��g�3�7l�P�Gd�����k���	�������k,n�NDJO	���u��kDDD�+�����
��������<z����p��O���$& ����n����5Ug.R����X�w���lL�ho�#�n,�#�F���dN�����)������V-������&\CCq	"�%��k�.&N�HRR111<�����S������
������������R�hy��K:dv^!.�����Z
��,m[��="	��h�HYJ>�L|r<�w��d�9K���L���5�U;�Td�����������9+����_���������)J�/`���8��M���CV�\I�
�5k7�x��#�BN��_���A�������������qI����[��w� �T���y�4uC|�2z��Zna.���'>9�-�����zW%.*�Au�B���M�f��z����g����w/���q	"�--w��5�W�^L�0�D��O?����a��"�|ZBDD��f��K���?���l���&w���!�/���w�3vv"I������c�ZOSeE�JRz����I����S�X\�Z�+C"���j[���d��CV�t��m���%$�A��<����� ����������'2������d7nL^^��"�|z���Yr��=�7L�{��k�1�-o0\=/����s?7�y�����<\�#���j��:s���T�)���%!9�m��	w
��E�qS��r����dM���?��Q`�`����]	����C,.�\{�QnP��Ux���l����}��M������l����|���[���Mn5����>|N~.���+R)��p���mj����V����a���������.:
���=j�`H�Z�����!�&}��?Pt�����QQ��o�\*Ur�e��9(A��{���������w��}{��A��7x�������e8u6}��@����j-������u���������;8��@���<�/�za�3�;N�d�������=c��=�/�!QCPg�''�����&��_�}��������8<�h�7�
JS�/�0&N��;����C��Z�*O>�$�<��U���i,""�!��=+����Y`�cz��/4��L������M�`��ml=h��GT�����t��*�f�T�a���fR��g�}������o$.2�!-�������d���-'�����w�v������N���Q��
*%��t���-�������^�""������9Z��R�^��9��a��������e�O����9�����G�G2�]8n.�3�Y�Y��=���xvf������C\Tj����������@~Jq�j���L��A�V�����*������HMM��������yJJ
������;.8�s1����-O���4s�|��31���LNu*������?�wSPd�����&��E��F�D.�alL�H|r<�. ������;��{1$jM*5���d~�<��.�"s���;��z�W�VX������H	��1������E���Y�g�}���K����_�>��5G����������fp/�Y`6����ys�v�N�	D��A�8 ��*��T�y���5���vg�
Y)�!�C�W�����tv���c��}<7& 6�~}q��gz�����q#:t8��m���5������a���fm������?]����-GB��P�����f0vV"�dP3��g�F��A���E.�a�v�7�%Oc���������'��{3$j1��7������6�����M7;��$���M	�X,{���eeea�Z���\lV��
r��O(�jN������-���yZbq{hCh1�\����LC:�y�	?mg�fs�TwFu������8_��"rF��t�h��������h�D
�Ox��l'��o�9>�isQ8��������X|:w�����+�+I	�t����_�o��gg����j���_��nppt""rMJ�	����C�m~U����f��oM�?Vr�������[��h9��+�,�����"�������������(�s�\�l��5�������)��u�^.^����!QC�*"k��NB��}�����M@\,����K�r�U�/ 11�N�:@��X�|9���,^���
:8�K��ED*�����0�����)��o��2�0~�t�7�m�p�9u�uD /���a����V?}�;g���������A
5����c�e5������`�����_����������G��QnP�(A��C�����y�f<==i��1�F�"00���]�ED*(�&6,9r~.�n�VwC�6e>Z~�����2k�eP��'����O�0%
"a�YY}x5	�	,���"�-�q��_�~�B�Q���|�,�YY��z�j�\,~={�����+���r��G	�uF/B�
j�\�����>":^��d�����L�x/7g�Z��o���Uu�"r��Q~��?����S�_�5	nB\d=�P8o1������d��%4���<�Z��\��T<�A����������{�n�M�F�j����/���P���\>�
�l���!eX[���-�P�
�����|�t��EP��WgL�z����\�|�6++� >%�_���0�����2��@bk�j�q2?J����0
���-�����N@l���aq�`"bR�~			:�;���
6��o����������;w��#��J^�Zb&�;��d�'���1��[3����4�kY�/��q��2;����p�a~���S�s4��u�<�9C����R��3��5��9b��=:����?\*UrD�"R�)A��q����'�0l�0���[{{�7n�#���a@Z�9B��3���X�7��"{B��0�d����Y���k�/��~?�����X��U�=x�o4WQ���9�����/�'����J�hy�{�9Z^�Ak��zy����������GL���������c�:u:���������HDD*��S��$�7���%o�e&��7B�v��^|[�7�X��B�$���������_���<�����
0�tu��.u��cm<�4�V���<������9�c����[��&�n,2���1����8|��y���w���������~������������s'���%�W�XA������T<���%_{V����6��d&�u{@`���3n����A�����wXTW��������"��]c���5�5�o�I6�l6�����v7����M5����wc���
��PDz����c���;��y�<�0�2�2��s�9?;bI���n>����),s�3��=��c����W�.*w����z���zv+��?�yq}���4�u_����9{�X���GF:�,��z���LJ/"��
�%�s�=<�������X,��=���[y���x�����'""f)/����x�:V�x`��,����O(����88��s��o�����9rn_H��e�8���g�-2��'D������|[J^
����(yY%Y���
������}�F���)��.%v��,����M@�d|����jV|�T�/��'���p0b����<x0���<��c<��Cf�����R5���F(/�:fuw��oJy��W�G��vU�R;x6��>O`�qg�h����c�3�k8V�������X�����x��m����wc&�����x��J���H;���w�n�=������kFt����e(++#99���������?������e��C�6H�0���������������C�����q.��?�<���Na��f�CZq����x�o�"�s�3?q>��.&���X��#�sC�x���#�g���W�9���	�~"�qqx�jeVt��F����]�2xxxM^^�W��]�vt����X""r���U]�~t��W�� �OU)�xe���@i�������k�)(u�?�k8O�iOD������KYur���U�W���x�0��$&���m��W>����A77|�!0n
��bqw7)���*��p�
70x�`|�A���������0�����)S��(""W�a��_U-��������z������9g�0V&����C�<����K�^�M�� ����/9;��I��������`�X1���n�������U�.x�nE`�&N��qc���H=��~	7n��g�`���8rrrx���y��WT�EDj��LH^sa�|
g��"z\�m�u_��pZ/}���G�scC�<y<�=q�#4�\����bV�\E|b<_g|]y�M�5�1���k(��,Yf|Z}}�7��)qxu��������O�rss	
r�<,_��)S������q���okr:�,��u^��������^��z������f%�I����U�|�#�nV���_mMO��K�u$�����������TlC"3���������G��U~�O���M�o�H���""��;�%DFF�u�V���X�|9s�� ;;///�����*��c�.�'_���7�\5Jq�\����0�q<���B����"�����
l=���$�_��g>�sO�iOd����ELST^��+�O�g_f�T��n���������#���p�-,����	���G���������<��#�t�M������C����;w67���T1�H��-e���~�j������p�����R��y��%���x���h<������2����������YqEL�p>����Yz|)���������C������	��/E��X<<���!`J
���b��_D�{������k)))�9�r{��K���LN��i+�3J����R�w���������
�}�����?������n~���������=#+G�E����B�_F|b<	�*�����&���SJ���TdT]9���#S�7[@��E\����QA�g�"�Z�0����|���eU������������M��s��X[m��b��������K[=I�a�$>1�e��Q\Q�������L;A���)����sl���O�@`\^���]����]������x������B�o�Nff&�����d""�Py1��R�
Z����6�6����7��wq���~��k�r.�F~Y>K�-e~�|g����_����3��?��(*��j�����=��
����W���|�
�w$$$��Y3�M���	����v��[QQABB�7o���>����|��&'�c�OV]�~|#\)��Q�xk�
��6H�?^��y"��a�=����xV�XA��������������';(;������9�,�t=������B*�����w�^����q��7�����f������"�w���w��������ED�TE�l�*��G����p��h�%��������*�u^���w�n�-�e��%�'����\y�-�#�3���(��������N���G�Y."u���_���`��}�<y���b7nL�n�h�����~6�3���
��%?��
��Yl����R>
B���(��d���U�|��$�K�#[�&^l~b���:�0vg�f~�|V�\I��O�'���{�����ggW~�w�N��ot,6�fE��
\�F�/�j���[7�u�fv���^g���K�����!U��������I���[d {N�`�j+�S�_��r.uBNI��.&>)���UkKt�j��g[�r�q����0i�'����I�ED�=t�6
3!y���'����o�@��.�%	M���jV�e�e���N�wN��������k�����7	���	��v
3+��3��i;�O�g����;�{�������'C�V`��Fi"����
J��8|���_[E���O:�:H��9�<i%��M�q`�@h�,��G@��;]��:���+K��|����<>�Sz6������&�8�EF~	!~^�n��s����g����O���������7#|��g7���m�8%�	p
2)���9T�ED��+������<y��~�I����^V�99M�YP�V&2wg
<���=���_�������jdBR���a8�������Y{j-�4�����:�gW�]�#����09�N�����[*�""r��V��~j;���~�j��Q�����d�V�yo�	��6��RgA�%�'c��cr:��/�8�E���O��L�������V�	�����m��-��K@��bF`��8""*�""�#J�����R�����U+�G�7sr��0Xq0���&%�9��K��M���dW��������'����*����|��Lk�l?��%���M&p�$�#"LL."�zT�/a������b����E������i���	�DD�������O~	s��Z�*�����������%	l?�@��'O��gr���G.uHza:�� i���XS3�3&�����b7OO�F�"pJ>�{c�'�B���T*����E��g��������F����sy��7X�f
09���(/���Jy����������<j ��R����/��Va���x�Y�����bH+\d��HmT��`��-�'����F��6y>�~�m����G+�����������M{,���(��p	M�4��o�o���u8<������1g����>�x�	6o�lrZ��(�D����7BE��^�<������2-��+)�����y{]2�e����w����Dz��N��H-HeA�&-$�(�R��g"�����I��� &N$ n2^m���ZD����a��i�Spp0[�l��w�\���?�������A����cN��(//���rss��_�E���2H����g&V?���^(�����99k	�0X�?����LN1�"yn|4=���N���;��xz#�����f0z��2#9���NAI��d�
���	�����!X<��Hm�n�z4�~	>|�{�������Q///m""�+��s���Upl=�T���Y����!@?�.���9��$��'������L��y�R���?���,J^��b���Ay7�����E���r�h���g��������ZD�nPA��[n��������~�^�z�s�N^{�5n��V6l�@����)"R�^�wV�%O?P�x�������C�;����VZn	o�8��������m�7��n��G���]��r{9�N�c~�|������[�A��L>�O����H�������L���{7
T��\E*����?����P�|�M�����BCC����O<��Q����53���w� y���]%��:h����Jy�.�����2;��t��?Jq��
����6�a�g.�WJ^
����(yY%����
n<J��9����<|����)S�=
�����ED�.�A�Lyy�7��>7C�LD���~]5J~�k��_��c����ph������a,�{�7�8��\�"z=����h�E�N�g*���6e-���lO�@�b��$����Df��n��L�D��Ix4onRb�V�
\�F�/���Se���������(�����U+�G��.��R�S�yyI_�����c�3�K�.��Z�x�q�'�g���d�fcqt;S��h�?Ky>�����A��8������'""5E����y���X�f
|�b�o����9<i��������Z
s��1�����u���b�\~�E{���a��C[q���x���H�Rj/e��U�'��+}��w�f�~��*��y�oO`\����P;���A�n��vRRRx�������\c������)������DW���l�������*xg�1���(%�,���)���/����$����Or������Qn0�\���I9�sGk@��8%��hS3���
�%m���M�6��[7���H]d�����K~r+8�����8WZo3Z���H���e���=gxc�a���{:�n����`r:��W\Q��+�O�g��=`�9w$x��`n��@X,4����)q��������""�
�K�����e�""W��Nl�*�9)����Zq=j�k��Z�u2��>O`�i����A�<=������)�5�d!>1�����_�O@���06����B���H�&p������ZDD.J��z�-�|�I����\+�����u�y�z�Jg9�(�:f����Jy�V���GNg��/�d�s���k��k���
E�E,?������������Q�1=��X��a�X���=���)�����Yqi*��0}�t���h��>>>��W�����eR2qi�p���R~>�������[�����
K+�����k�1�*���g��������e����'�����(,/$"���}0<��O~P�w��L���l~~������~	o����D���=}���r.�V^Xu����]X�m4�]>]��������#��w�3������@�p�3�VPV������4���	x��?d{���S���ck����	���g���f��G�n��6�#�������U+�g�~�7�j���C�K%�,������	8�@T#�������g..�0�?X9Z^R^Dt��C���p+w�`��;t�s��A���kw��L�;��������})��'"�DA$�v����P�[u�b����Jyhg�\OS��/��/���4�<����6��?
O7�3��_���cK�O��H����os�J�l{�y�Z8e
'������ED�jRA���
���JHH���]1����n��#�H�������V\?�u���AU���p�	2'�T�_R�������)�;�Z��>��uL[�j����0�{n/����8�{i1�
���N8��
�?n�s��.]t��H���k��%(��K��u����n�������������T.\��I�*���/�����orrr0`���?h��M�9YYY<��C|���X�V�L�����g|}}�ZN�z�(���0J���W?��Y������`�H���;>��Xy���2�n�s��i�D�d���-�e��%�'����D�t�q��!	�K�����C��8�F����mbb��T��c��!�}�
���+w�y'qqq�;���o��������-Z��s�1z�h��r��|�M7�����U�(//��;���{�e���W-�H�c���j.���`T�b�g��,��c�/������<��K�'p8-������o�QFq)�a�;c7����<���R4��~�J��g��[X��'0y2���f��c1�0;�++))a��}ddd�p8��8q��zL��Rm�0�����o~�c�=@nn.������{��1�C����;����X�|9c���������_�����#  ���\�����$����7�� �����U��G��]rU'2ym�!V&�����#1m��onZ@\GvI6��.f~�|Nd��q�a�z%�]�1g���/&���8�����+tD��R7p=A�����s��������cWs����IKK#&&�����������[�1c[�n%00������`�Z��};�'O��c���RZZZ���-|'R'�;R5�<e+8*���7p���f������E���[\���&���'(���n���Gb�������D��w��$>1��)�i�Y��}�8A�U�#^��L�#`�8l������_�C=��i�x���	
�v����9G���5BCC+����R����AAA��\������Y��rb8�p�K(Hwna������
����Q������v����|,7-VT���y�?�J$��9�|h�`���6��g.��|�y>;����y���
��� �T�9��@�'N 0.����+"".E����y��G�i9���z�)}���������\6�m��' �l�}���Dk�����2��Nl{��#�<�������Z�\~�*6%���%	$��:��g�u`X���L�k�a8������x������
b�9������IV+
 0n
���a���""R�
�%L�:���������E�I�&��aaa�������[��s222�}^EEYYY��1���xzjdPj�������w���Ku�?��PZ�,�������^%o><|j,�\=G����C�9������#�2�w3�m�g.�:Wt���~F|b<�i������9��:�=��qS�t=�����""r���_����7�M���M����3�������~uU�N�-h��	k���,�yyyl�������~�������]����'����p��O���C��8������s��o��UwY��Y?�hmFA����k���2��&�����a�f�pk��<<�
>Z�O�cw������O������T����5�]��d���?6��)qx����DD����_�'�|���+���b�����\-�O*�$'W��?~�={�D�f�x��Gx��Wh��M�6k����+�w�����X����y����y���1c�e��.R�����e�?��H�q�s�7/�@Z��������V'�ST@L����V��&���,�0���Y���g������������������������""R+��_�3�<��Y�x��'�Z��2�����a��U~�����n����{�����B���^rrr8p ��/�����?��d��X�V�L��_���+�%��
�/���3��E�Zk��^Yz���<�v�~<;�����L��
G��lf~�|�:��~�<��A���sl��	�4���qx�la^X����%�s��k>�&i�C�U�o�����y�-q.'�VRz>�,=���s5����m��+7�3��� y��'�p:���I4��f�F77��
# n2��aq�����>��G�&�p�m�1w�\�~�i����OQ��A0���,������h,�z��xku"mO��0p�Y�c@��o�3��U�(g����'��xp3C��yn�AHn�9�mZ0e
&����yaED�NRA�����o���+���������hR2�z�������5!bw����%�U8�p�I��:�������P�����5oWj����,HZ��Ci�7�a�~u��C�����8e
^�:i�7�fT�/a���t���T;�7g�k����%9����I����r�����a�=���Kq,��a�<7��[569��'��r��ZG��yd����}^M0hPZu�O���M�od�o�	#""r���_��u��� R?,�
��^p�h����{A:��:/k��y�r8-�W�bsr&�}=xlT;�]���?zJ�8�w��I�Y�w!�we1e��f��E�N���L��G�����H���."�g�����b���B�5j!�Z�|A)\��';Rp�a�r��<0�~^�g.�^���5)kXp(��/�1l����
�N�p��h������+��EDD��RA����8�{�=���������,��T"������I���/A�s���VZa��/O��5���:������'c;�������>8�{������}>=�����
��{v�D��8����`^P�T��#  �r~y���EjV�	��60��e:�{��D�3����t^[v�������s����R�^��URQ�����|��xm�������:n	��������][�����\��A���^z��{��7����e��GA��w|��f���(�l//I`����y���vL������5������x�[@�]�;l�ua�j�w�`�L�o�,��q��G�"l6�����������P\�a��� �3h���-�T���/�+�0��Sx�Y�gPK�����XK����bV�X�����C�9��:n�����iL������."r��
\�~k���B��m�?g9�����T�k��r;�n9����Rpa�����<���
��UH��da����]�����x�����[�������h8e*���i[T�UT����Ej��e����q�f}��#��0�8��k�q:���Mxn|4�529��EE�E,?��M�?���D�4�/�:�����f�?z�
�*""rT�@��m��gee�P�:*�0,��y��=��6s��e�:���$����g`/�����Fh��\u	��l���/[���K�7����Q ���@����h����"""W�
��5k�Vq����a�L(���������G�����G���4�^�V~1�������SPV���%|��}Zm9��D�����������0�`���
+""r�7�0c��:�H��K�W@���u��
�����T�J���g�1�^��2gK��-��c������0���b�{8��f��2:�U���$l��L��[�����T�/B��E��5/�����3>���N$a��K��/s&�9��{�@�M�f*Hru������"�|@��g��R�PkEO���'���xEG��YDD�<���*�"���O���:oOz����G.j��^^�����=���xbL{&v
WI�+f{3��n���X���+�Zv����u������������"""5H�"��D��3�a�C��������#���[���a��g�v������{PK�=4�W�Lni._���3������������x�
�N��{x�y!EDDL��."5#?��%�6�=cv"���2;��x�w6����G�)=��xl;B��LN'��a�:����o�WtO�����j6,���|��4����jnX������WQ
��yg�q[���q��p,�{�7�&5��^����h�4
47��j�%��\�.�����+�aEU�
�F1�B&�a��3/�����QA�k�0`�cpj;x��O�K[��]'�yyI{N����c;0�s�3���0v���9o�n?]�T��R�����Q������11�����RA�kk�`�`���w�qk��{gr�y���,�{�6��;���]�����,<����N�gK������V(��-o����Gaq�v�"""���."���M��I����M��q����
��p�m<Fi��n��oF�%�O����q��]F���1��9U��ya��N��v3��-8���"""��
��\�'a�m���������NTo9�>�����_
@�A<7>�N�n ?MF�i��}���mr	�]����J��t��A����i"""?�
��\}e�0�&(:a]a�_A���b��,^�<��grh���c;0�c�
�\6����
s8=�}Zl?E���c���2m]&�������"""u�
��\]��=���A0��
��f��wNe��/�t*��n<4�5�h�������9{�_}�G��o�iZ9
/���N��At��a:�lkjF��D]D�������7|M�NT��V���d���8e������lKc_O��I-P^^������y��/�6��� ���4�y�GN�b�zDDD�6t�z�,�5/;o��=D�37O=bw��:��W$�Y��g>�u#�M�0��Imp��N���g�~M�<G�hyZSlF���G��(���"""u�
��\�����������D�����yyI	�y�h����v �C����%����k��(Z�9Gsiq��o�u��-�1��HS3����'*�"r��s���P�Q �wf'�N�/��e�Xq0?/7��[�5���jr:qU�a��e%I�C�/�����!������4�<���������"""��
��\���YG! ��nf����J����d���ev6��{7��#��@�{��������-KV�QL���3�ld�t��-3��u�|��T�E��������f|��f'����9;S���D��0�Mc�M�P?���+2��8�E<���O��):��������4�v�������&""�T�E���7���y{���{��5�%9���$p8-���
xn\4C�k��|O���|������OA!�?�NI�z�����35����|�
���<g���:o|:M17Ou<��W�b�!�<�ow~����F�n�<s�b�������7��c�\�?��I��1��
�[�M�)"""?L]D~���sT�@�Q0�Y��9�E��eml=A����j���Q<��@]�\�v;E_����9�������E�7r��D�G���e/���@����2~��<L����7����O��."?ME|z+���Fm`����� ?O���';R���D����>���v�u�V���V�$����HO���-4��g���(�����'��`�b|2�f�S�-�nM��0����z��M��-"?��C�V������W���\�
��xeII�	�����i�������+9���������������r#i�w��7�>@�'������3|�/�fJv�r*�"r�v�v�����B�6f'��3
xui������;��j��^��i�y�a���|�lT/�\���?�M�����>�]����-�a��,"""��
��\�[���1/@�Q��������$>�v��9�����yhD���W}S�sn�9?x��������g2��m���
��D]D~\N�s�����Z��G�NT���|��$o�N"��9�<�C(O�mO�`�3�����u�u+=c��yDDD��������9Wl/��&]`��@�n�,�a��H�,=��s��o��s��������,%G9���X,���s}����T�E���s���}��f��S�J�����$�MI�4j��oF�cz�HlV���������qv�Gx&��pX�b|:����^}j2����� t�a[������?����e���U�|��$<lV�������K���������I������*x���|Wk��&3�,��/�|{y@���h\#�����"""r������%��������	Q���S��U8�`�	��&���
b;6�����j��G>[���c�H�t6��}�GvAe�>�����q��>�f��X}r5t<�m��4��z�,?x��w����EDD�0t���$�`@�;��]f'�5�`UB:�-;���ED�����h��jdr:�)��|��.����8t ��vr�$�?����SM�T+�1Q1���x���I�ad�Bv�0���������Y*�"R]q|2J��Y?���\�C�y��$�/�����'��n���M5��0��m�����X�[��n�=�,��n��6��������aX�0vg��\�9�}���C#�"""��
��Tq�a�=p>���
�����\^fA)X����)�y�nV���_k���~��ue))���C���xd�`N5�=|	�0�1����
[_�c��6z5�u�������o�"Re������`���bv"�VZa��-'���d
J����u	����Di����QXH�_pz���O���x��hy1�1`��<9w�����."N��a������;�w35�+3��xm�aR�����4
�����jdr:�V��������)]���
�q���������i=�Fnj=���������t*�"�{����<������8���K�~<�?O��m���X5��N*?s�s��qn�<<����p�!l�����XF���A�X,�@DDD~>t������	*��u�x��D.)#���[q�y�Nc��f��[��!�h�y�u������+95�l_'`1���y��h+��u���[�m��x�<��+"""u�~���*���[!���)��]MI���n>����),�p}�p�mOD�����j2�������G�X�[qY����(z�|��E�� ���"""R7����g����/��f��@���0X�?����LN1�"yn|4=���N����t�/�'=~.g��7�������1��{����v��T�E�������X �����D.c��^�<��Nf������5\���Gi)���p�������0�J�a{;�C;�s�-<�|>�Z�_DDDj�
�H}t�KX�[���A�Xs������\q�����n��!��wpK�=t�mg%�6�
�}�[A	��5��{5$b�4�u�J�_��YEDD�~RA�orN��[�Q�`��f'2]q��o:�?����9�<�G��nO�/�������$��E�}:������/��tq�>v0#����&��Z��~0�kH]�>)+��7AQ&4���
���Z�0X��,o|q���%��j�s���hn8�"FY�6pf��8��
���(s�m-�����7�@���y��WDDDPA�??�������

�Ne��)���$��Sr����1��%L��b%����'�.Y�{^V 1���O��I��2���-�
*"""r*�"�����`u�>��ff'2���b�X~��������/����A-�r�<���";����9����=�;��6u�Q:�C����q��mODDD\�~S��V����c����Ee�����x��rL�����nG�����6FE�6qv�GTl������������oF������xzi[<�T�E���d��0��m��n��(��`��3���0�y��n����`r:��J��97o.Y�-�=�p^�~�	l�������}w�77��������.R������P��}a����E�v������{:�� o����NM4�������t)��~���1�y	{�l�d%/�:
��g����anX�+��.RW9�0��L���!����r:���}q�%��[j�z������1�������N��[I�7��u���������V�6������n�>�f��*T�E��u�B�
p����o�������
��>�o:NY�s���^�<:��~�f���Pz�8����p>���+���`���>�b�c�4��� DDD��QA����Mp���W��an����0�q<���B����"��Y��������#��w�3������@�p�3wu����X��O?��������6u��9�����SQ1x�y�VDDD�RA�kR������?]n07�U��@*�>O 5�����/^�MC^^���3yD5�����Vf8��I����^���+�������jD��70�}�f��*�"uIa&��	*���p��ev�+��@*���;����p�G�+?��t�W#�pk�(<�4��U��>M������)n�Y��3A����1���u#3C{b�X�
+"""R�T�E�
{9|z��@PK��.XkwQ�;f}���r�]7���7#���W��]������+I��1|}p��y���nG�7�X�X|=|�
+"""b"t��b�Spr3x���O���������Y�.k�!�D����0(����ys(X�[I�@s�� b�&DO�E@s������t��`�{������B���������r�S��k�<5���I�����s����@��������{&S��c��Wx����\m*�"�]�6X�����g��s�\E���[����
"��()!�R?������7�w�����-�1�Fn5�O��/"""�CT�Ej���0�p�C�$��������
�Y�w6��y�I�s�5�Y�aP�o������l���,��f���!c'2��4~����""""��
�HmU^�\��0B;���/��E����gy}�a�����m�/��X��bq��K_�]��\{��|����`;�
8/a?���(����~7�j������
+"""R�����F���{�;f��f��"{O����v���iCo�������`���Aora��NafE�7ee�]G���T|��a`J�`{;��"�<�F�k3������+"""Rk����F[��?�
nxF���g��+��G��uk�][���\D,�S#����x�%��9/k����c%		���G������+G���>���.7po�NXj��""""�@]��I^
��w����ln��������O���I�������	����o6��~��t�z�"+�����	��)���,_���J���p#/6������T�Ej��G!�N0���}���~2�0X����K�������������^��l�H��9�n����(�����	������fa��R """r�����%y��L(����a�j��pG��yi�A�$� ���'��gR���\���I$kA<Y�-��S�Hn[�{�3zc�����=u	����H
PA�
Xp/d�p��!�y����e���U�|��$<���;�%�mEO��I��r�,%m�l,G��K�s|`S'�C;2p��<�|4>�>���g���Hm��5H�l�0�#�kbv��Rnw�����iu���������v 2H���~�%��P�n#�
;��
�Z[���!�FOeF�)4�ofv\�zK]��\��=�/���<�ic�9^^�@R�����M�xaBG-�V�J�#k�|�/���|.����Dl���m�0�t��-a}�Ym��t�����y����u��y.���B^]���C4�q���������E���|��}A���p����=�6w�pzP���'Z��`nX�F]�U��97By�1��NtI�%��mm2�n9N����j��~�yxD|���W�E��q.~.���b-��n�=�,|���f����!�6
���VDDDD~�
��+����� '������5_�v�A��S�~�2��6���G�:���tu[YJ
���`��,�y	��F���#0��t�7��U$qu���H}��8�	<|a�'�dv���y"�Y����<Z6n�s���>��du������+H���������x���
����3x��xyk�����Hm��.�jv;����/�`n��8�S����d_*~^n<<�
��k�����tu�a��������X���y�������>������S�����""""��
��+I�Ku���gn��(.������s�QJ�X,0�W3~3�-�}k����E��3�,����s��u.�g�6�
]���ML���9O���""""��
����=soG9t��3;Q%�0�|_*�/;Djn	}Z���h:�k%���Q\L���d��C���Xg)/���,�F����e��4i����""""r������b�{f@HG��������O�2���|u2��@o���1���R���0���!k~<���a-r��������'���0��T�������H��.b6�����_�wC��1x���yF~	����v��0����/�����-�r���N(OO'�������%�,�-�����d
���>3x5j$>�>���kN]�l���}s�b�i�APS��V�����mm2����'w�����4	�25[]�(-�`�Z2���l�,P���Y���1�#�qg�ID�G�WDDDDj�
��������:o�~
Z5-�a�>��+K8y���Mx~BGzF54-W]`%�=?��%�c-p~-��������b�i*����jq��
""""R�T�]��/���Y�����];>@II	���o�3g����=���~���P3���:�����}~aZ���|^^����L��<y2�=��G`�j���U��I�������R�%��~�����!�w:/��������""""b:t��cGV�^]���[�S��_���K�2o�<x�����c��-fD�+Q�sn��h���LX�+���?�J���)�6+wj�/����S?~����
�����M[�8��`G[���ML3�N�U`+�������+�o�.����&M��uRnn.����={6�����:t`��m���������p��_�����?�������`����*���rb;6���h�H���%��=>Y�a�-���'����n��al�i�17�~���������D���Dxx8^^^�����_�f���k�.�������<�}��4k���[��`A/--���������k�o���wpd)�<a���W�{YoN���%ILw���M�x~|4�[7��uAEv6y�/!c�\�#G�%��
`cg'�d��<�r
�4�_DDDD.M��������{�v�������Y�4h --
�}Nhh(iii?�����������>�
o8oOx����/}"��W�bUB:
}�ytT;f�����E�.�QQA��M��O��
X*�TXag[;{�s=����C�&���D���3��v�.]���QQQ|���x{{���|���x��G+?���#2R[7�"� ,��y��/���5�e�K����d���ev6��[�E�������H���49��8�h��\�y	��&��������6��#��a�07������J*�.,00��m�������#)++#''��(zzz�E�����O����,Q�����Bh1F�|����a��4o.?Bf�s���6�y~|4mB������yy�-[��ys�t��`��aS'G�5����<�j!>!���ZO��p��Qn��z�����;k��a��)9r������grR�${��
rNB��0�=�]���W'���y��8Gz[4n���:0�}V��M�������?���k��W`�����v�&,f,�O�7�]����F��<��cL�0���(��=�/���fc���p�]w�������?=�����
��n��p|#�7���O�5�Rgs����Y��,~�n�jDn��7�3���'�Y�����X2��hyJ0��b�hhOF����b�v�ySNDDDDD.E���>}��3gr��y���8p ��m#88�?��OX�V�L�Bii)�G�����69�\����8o��B����).��������dJ�X,0��H~3��~���C���/��s��R�g?��W^���-�J�A�x���D�F�VDDDD�<�a��!�����@nn.���f���N�������>C���_�0��K��e�8�[@��A<?!�NW�����A���d/�'w�J��e8,����-�<	���S���uX-��@DDD�&u��t�k!/���,���������8p&�Y�d��l"�yjl{�u����(;}�����\0R3�%�g�`}+�C:2��t�l>__s�����H���.r������� 
�;��w�z�Fa������G���)����?�5�n�����}���QTD�����?����+�/��-,��D�!q��f-Z��TDDDDD]��2X�k8��a�l��:[��U8x����eM2���������	����v;E_����9������'��� a��w��`9_,�Z����hnaSW7�GcB�~�7�~�����k�o�"W��w`�l�X���]���a�=��+Kq<����0!���_��]I������������������@yj*��-&s������[��@�%�g�ah�i��b�^�5���*�"W��u����Q�B�aW��I����$�MI�4�����vL����~�3�[����zp������tN��a�n������l������%�����]=�i;l7��L��v&��|*�"WC�1�w;v�z#����.����V'�����6+wl��Z���~u2������^�F�r���
 ���+?>�6vq�6l�:M���Cp����������n*�"W�4>�Jr �'����U�+�>���V%�ST���P�����\���C���e����o���;��1����o5����k$���������.�S9�p�K(H�!�y���o��1�{�������K�'p$=����<?�#����������n��}w����DDDD�VSA�)��' �l���n0�#����r��W�%���s�@w��{7��v��g�M*���]��?���=BBU�EDDD��SA�\	���[q�|�G�����+(�������������n��#1m���:�k�0(����9�)\�K�O���Y��t.���^}j4���������.r9v�����9X�$�����]���>��s.��Am���h��^�=�k�����Y���9���v���$���nnTxZ�Q���}����h\#����������\e*�"����������8�k1���u2��>?����D5���q��t�W�hE;v�����Y����(���-A�!3y��D�d����G�m����U������1�����EDDDDDjt��Q�~E������Y��Y�}=�xhxkn�O��S.�-O��#�g��++���u=<����������*�`�x����N��4@�/d����O:�������*�"��7�g�WRn�_����G).�c����Mylt;B�~�j����pP�};��|D���X+Xq��o�h!ips���Z�'�3������a������s��#��F�EDDD�NQA������?p���!�?�\�l��4^[v�39�\��&t�s��������y�, }�G��d����0������c���n���.��Ym�j���1�
���q���_^�����6��e��	�8�@X�O����.au~��7����O��MX�l@��s�<eh;��Y�c�q�1;������KQA���/�������1�o-g��c����F�������^�V~1��
i��G���"3���I��#�R3������<�z��4��
��TDDDD�����\���a�L~����\�������C��w���V�]O~i������Dz���2��m����Q�~V�7�F��Fta��[x9*O���qEDDDD\�
����lx�y{����2��?���!����r�w��S�?���H�A5���Tdf��)s>�=�y�H�m��	�0���o �?���"""""��
������?��=��=�b�k1.�)��,�n��X�����[9���86n�j7p��hy'+Y�z2d�m��t0�Vw��������J*�"��������>�[v�"5�����[\�����k��B���s�����ss?�#-�-��O��f0��4�4hbnP�:@]��R������:��_����K��o\�y��p8(�r+'?�l���n�z���6
b�2|����G�������\E*�"�H;�o��bh=&�
V+�%��y��"�����v*��#���d~:����P?1��B��7sKt����"""""�D] �8|%��n����O���w_&�����n�x�������/�p��a������h���n�����w01�G���]DDDD�l*�"����d(H���p������_�;%p��>�K8o|q��bq���&Dc���[q�g�|H��O�����e��D�������;:\�����9EDDDD�t���s��)�}�(��)^��6��0h�a�7��qk�(�lV�7�a��	��k�����f���2y�7q�����l/���_v��C��;�����QEDDDD�%�a��9J����<����������9/kO�

B�r�l~�&�39��vl��	���iv����Yd��������G��3285�}r����\~���# ips�M��������cbJ�i��G#�R?��!�H�����W���g��K�wdD���~��jq������M9��?�����q��o���mR,������VfG�T���q8��!q9VO�(~�M�
�Y-�=������v�4��38>�?��_�Of���������q����6���9EDDDD��jg��V>��`���%�����yurg:���K{���M�8��;4�~�|�/������9G��"��*"""""���.�J������m+�_y���1��+��#�����?z���ip���nj���h:�p/����U/s��@��K�`�E��_���[pt���q��y����v;���������064�9Z���~S&3�NB\|��������.t��Ne�x������`���1���&��h��,=�����EK�=_D���GZI��B���so�@���9EDDDD��SA�:����?���sM<�X��j1�:�iw��W-X���I[������]I�;��h����L����w�����QEDDDD�*p��"�3�:������5�=����N~��t���`����J�R9��_����b���G"m����������Xj��y�4t�Sr��xc�a>�q�V�3���&
(�h9����l97�vN�^���E����v8�/����������__s�������5��.u�a,�s�W��|a�c~�7	�(���X�n��\I����-�|~��4�pb37rb{�{���3���EDDDD����K�w�\�}v�-������G����;�������uF�
��+���i��~���|/8�'��71j��x�y�TDDDDDj�
��Z�v�Y���O��������	��c���z"�������Q(<�������u�g�r���(w�������-���EDDDD�<*�R+}y4�g���B�
��q��Z~;���F�rajN�n'��O9����s���-O�A��[;`&�6wSs�������T��V9_P����`���<y~|4�;c�w;��pS<4nsM2T���o��SS�kF����{T;'��q���x,�H@N9M.�������C�;���n������I]j��`��S���ar���X��>Q<6�^n��!8�l0c6D��&96�X��?�9�f���7p<|��?��������=K�7���p��7����S���J�"""""b.�a��!�����@nn.���f��,���<�p?;Od�!���&w�{�;��~6�	,V��>DO�&96���_���7/�Bo+������[xa�8�3%8��K�EDDDD��6v��N#�������um��x�
�����GG�����q�Y�'m����L��5+��eX��?�z9�����������4��^�����b�&yDDDDD��QA���H�}v�SY����������c_��s��yz�z���[=��y�=������5�!"""""u�
����0�q<���B����"��BF^	��$�t_*a^�8�#�;6����8���<r�����s.�"����k�CDDDDD�6t�q��2��RsK*�k����v�,��J~iV�1���_���oz|��	���#_�w/<�2�ap~��w|7�%����j�kvUs�����H���.5j��T��h7���iy%��y
��Mxurg:E|�R��'3�^
��9��_�r^��A��Q�h1���4�&_ ��w����8���cf\�,"""""R���K��;f}���r�m��n���?nY\-3>���|�S����/l��q~�J�}�o�J�j�?P����7�a�������q�N��Y����{��������\.t�1;�gU���b��+�u2�~�}��Y�p2eB�.0�p���<%G9>�?�.[�g~)~�?��J��.��� 77�������c3T������_������<"""""R���K����t9�������<7�Z�������h�����E���!^I���|aO�@O����w����E?�M�Qq����z��)��5�w���������SA��wy#���++��7�����,����u
���m�8=���m�Vn�����6V�cz�o���2�_�h����{�c����MDDDDD�'t�1�[�EZn�E��[�&�-��(��������,�
�.����>C��x2������������7��=o��w�+��������\1t�16��&Ds�G��@��������Y-����_��5��7�CH�����W�"m�l_��(��-�������w�d����,D'"""""bt�Q������=��z�/L�&�S|�8\Vw��!D����4�����G��%X�����[��+��g2#�B�^�����������.5.�S#����x�%��9/k�Y/���v����w�u�E���yrN���8�����e��.V�F�!��-��tnV��."""""�M�ELa�Z�������7����t�Z��QQA��Md��O��uX������`{;��������~*����!"""""r����������v�a�@��+�;F��d-\�q>p�[O
s���
����o�����[�M/"""""reT��FyE�>��l
n���i�e������������_�=>%_����\��������0�G�N��3s�!""""""W�
����w_#��RQXu�����n���Dq���<�4���C�s!9��nea]W�����<���������������.5*���8����rk5��b��4���>�9�U�&�u����C�M����h���s������\k*�Rc��2N��!���s�ft������hk�X����i�n�����r����""""""5D]jL���p+�����I�1Sy��4�����DDDDDD\�
����c_s9c�����O�g�yWb5;���A
.���F��8��������QA��7"�L?p��q���<ODDDDD��QA��#��b}�������P��1����S��DDDDDDL��.5�f�1����c��,�������qV���:6����""""""&�"qR�b�b�����t$��������x����EDDDDD�!t�q1Q1������+:G�O0=Bzh�\DDDDD�5t1��j�W�^f�q��.""""""�T�EDDDDDD\�
��������PAq*�""""""".@]DDDDDD�����������t��.""""""�T�EDDDDDD\�
��������PAq*�""""""".���R�� //��$"""""b�o:�7A���^����irq����C��?��+���g������b1;�����<"##9u����f���@�i������sZ��9����^�a���Oxx8V�f?����3V���M��C.�����t�=�u����G�i����n��z�4r�Z�g��.""""""�T�E\���'/�����fG��D�i������sZ��9����J]�E�DDDDDDD\�F�EDDDDDD\�
��������PAq*�""""""".@]�E����X,�j��o���X�m���	&��ba��E������?OXX���������dNX�,?���~���{�����V.����N�^����#$$�I�&q���j��������Q#|}}�2e
���&%��q9����C��z����LJ,?���]�t�������_|Qy\�S��T�E\H��IMM��o���fG�������]���������|�M������;��}�v4h����)))���r�~�9���������Oj0��T6l��`��m�Z����rF�Eaaa�9���������7o6l���������Z~��<���sO����o�iRb�1M�6�w���v�����b���\��<x��T�&m�&�"^|�E-Z��={��"W��ba���L�4	p�����������{���\BCCy����1c��i�r|�9�zNN��F���8w�!!!l��������Kpp0�g�f���>|�:�u�V���krb��}^�9���[7�z�-s������{�N�����IAq!III�����eKn��&RRR��$W����IKK#&&�����������[ML&Wj��������];���~��?ov$�	rss�/��v������k�}��4k�L��Z����7>��c7nL�N�x���(**2#��Dv��9s�PXXH�~��:�:���"���O�{�=��kGjj*�f�b��A8p???���U���@hhh��CCC+�I�K\\-Z�����<����3��[�b����'?��p��#�0`�:u�8_�V;W����b�+��7�HTT�������'�x�#G��`��������~��QRR���/.$::�={��u*u�
���3fL��.]���O������O����LL&"����	�;w�K�.�j�����3b����x��8p�����c~�y���{+ow�����0F����Gi��UM�����];���Cnn.����v�ml����X"��.qqQ����m����d���U��I���0���^yLj��-[��qc�vk�|�%K��n�:�6mZy�&M(++#''���z��?��^L�>}�zua�n���={������kW���?�u*u�
���*((��������E��-Z��I��YSy_^^��o�_�~&&�������?^�]f>� .d����h�����={���^��z��RRR�Zua?��^�7���Z{8JKK�:�:K������{�	&���gy����l��9��h�T�9~�8{��!((�f����#���+���MZ�h�s�=Gxxx�U���\�9

b��YL�2�&M�p��Q�qZ�n����ML-���0{�l>��3���*�����M@@w�u�>�(AAA�����C��_?���~�y=z�(�g�f���4j��}����_������K����<��S�3�f���������Y�~=+V���T�.CD\�������0�������0�O�n$''�K~�u����������0��a<��sFhh����i�1�8r������.���F�2���
www#**����{���4�c�%\�����������/��
>>>�������T�B�����5%%�<x�dxzz�[�6~��������t��wQQQ����l�1�X�re�q�N�.�>�""""""".@s�EDDDDDD\�
��������PAq*�""""""".@]DDDDDD�����������t��."""�,�-2;���H���.""�"n��v,��w���=��X,n����z�'N`�X��g��
)"""��
�������d��9W�WRR����i�����DDD�ZSAq!=z� 22�T��`��5kF���+�[�|9$00�F�1~�x�=Zy�E�t�������C+�����t��OOO���x���e���d��������M/^\���3f������r�-����Yy<>>���;���M�F���������|DDD�2ts��w�������w�}�;����9���<���|��W�Y�������q8������W���ZY������p�����~/^L����=��Y������oc�����n"++����N�������X�|9����p�
���2s�L���N:��������0�k���C,��1EDD\����NNN����������#�o��S�Nq��w�{��������$88������S'N�8A�-�������[�y�q����+�`�Xx��gy����|}}���/�����W^a��M�X���sN�>]������={r��	�����7GDD�p3;����T��q�x���0�q����q�j�$%%�����}�v233+G�SRR����E7##��g�2b��K~�.]�T�n�����ddd�w�^��[�����>�����5�#F��sgF���Q��:u*
6�I���H]DD��y���s��������	�������7���8:u�DYY�>����e}mww�j[,��?0a��x���}^XX6��U�V���_�r�J������3��}���y�"""rq��.""��bcc)++������GW;v��y�9���>��#������������n�W����G���Y�f�����G<H���i��u��4h8���5k_�5,\��gM��B#�""".�f�q��������aC5j����/���HII��'��vNHH���,_���M����E@@/��"��w!!!�3���|�l��C=tY�x����3s�L�q���HNNf��9��?��\�n��Q����}�v��;G���7FDD��������������{�[�V�����]�����������_�777����������p���zn��6�z�-�~�m:v�����IJJ��L���l������Q����3�<����X�V�����q#c���m��<�����`��1W����������������������PAq*�""""""".@]DDDDDD�����������t��.""""""�T�EDDDDDD\�
��������PAq*�""""""".@]DDDDDD�����������t��.""""""�T�EDDDDDD\�
��������PAq*�""""""".@]DDDDDD�����������t��.""""""�T�EDDDDDD\�
���������pq�I���:IEND�B`�
#224Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#223)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Mar 13, 2025 at 5:41 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Overall, I feel pretty good about merging this once Thomas merges the
read stream patches.

This was committed in 944e81bf99db2b5b70b, 2b73a8cd33b745c, and
c3953226a07527a1e2.
I've marked it as committed in the CF app.

As we continue to test the feature in the coming weeks, we can enhance
the read stream API with any updates needed.

- Melanie

#225Andres Freund
andres@anarazel.de
In reply to: Melanie Plageman (#224)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-03-15 10:43:45 -0400, Melanie Plageman wrote:

On Thu, Mar 13, 2025 at 5:41 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Overall, I feel pretty good about merging this once Thomas merges the
read stream patches.

This was committed in 944e81bf99db2b5b70b, 2b73a8cd33b745c, and
c3953226a07527a1e2.
I've marked it as committed in the CF app.

As we continue to test the feature in the coming weeks, we can enhance
the read stream API with any updates needed.

Really excited about this. This work has made read streams way better, making
it much easier to add future read stream users to other places!

Greetings,

Andres Freund

#226Jakub Wartak
jakub.wartak@enterprisedb.com
In reply to: Melanie Plageman (#222)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Mar 13, 2025 at 9:34 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Thu, Mar 13, 2025 at 5:46 AM Jakub Wartak
<jakub.wartak@enterprisedb.com> wrote:

Cool, anything > 1 is just better. Just quick question, so now we have:

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 16
#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10

Shouldn't maintenance be now also at the same value (16) instead of
10? Also, fc34b0d9de27 (5 years ago by Thomas) states about m_io_c:
"Use the new setting in heapam.c instead of the hard-coded formula
effective_io_concurrency + 10 introduced by commit 558a9165e08.", so
there was always assumption that m_io_c > e_io_c (?) Now it's kind of
inconsistent to see bitmap heap scans pushing more IOPs than
recovery(!)/ANALYZE/VACUUM or am I missing something? No pressure to
change, just asking what Your thoughts are.

Yea, I'm not really sure what if any relationship the two GUCs should
have to one another.
As long as they are in the same ballpark, since
they are tuning for the same machine, I don't see any reason their
values need to be adjusted together. However, if it is confusing for
maintenance_io_concurrency default to be 10 while
effective_io_concurrency default is 16, I'm happy to change it.

Hi Melanie,

dunno, I've just asked if it isn't suspicious to anyone except me else
that e_io_c > m_io_c rather than e_io_c <= m_io_c. My understanding
was always that to tune max IO queue depth you would do this:
a. up to N backends (up to max_connections; usually much lower) * e_io_c
b. autovacuum_max_workers * m_io_c
c. just one (standby/recovering) * m_io_c

The thing (for me) is: if we are allowing for much higher IOPS "a"
scenario, then why standby cannot use just the same (if not higher)
IOPS for prefetching in "c" scenario. After all, it is a much more
critical and sensitive thing (lag).

I just don't quite know what I would write in the commit message. "it seemed confusing that they weren't the same?"

"To keep with the historical legacy of maintenance_io_concurrency
being traditionally higher than effective_io_concurrency ..."
OK, so right, nobody else commented on this, so maybe it's just me and
it was just a question after all.

-J.

#227Melanie Plageman
melanieplageman@gmail.com
In reply to: Jakub Wartak (#226)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 17, 2025 at 3:44 AM Jakub Wartak
<jakub.wartak@enterprisedb.com> wrote:

dunno, I've just asked if it isn't suspicious to anyone except me else
that e_io_c > m_io_c rather than e_io_c <= m_io_c. My understanding
was always that to tune max IO queue depth you would do this:
a. up to N backends (up to max_connections; usually much lower) * e_io_c
b. autovacuum_max_workers * m_io_c
c. just one (standby/recovering) * m_io_c

The thing (for me) is: if we are allowing for much higher IOPS "a"
scenario, then why standby cannot use just the same (if not higher)
IOPS for prefetching in "c" scenario. After all, it is a much more
critical and sensitive thing (lag).

This sounds quite reasonable to me. Given I just changed the default
effective_io_concurrency to 16, what value would you say is reasonable
for maintenance_io_concurrency? I based the eic change off of
experimentation -- seeing where the benefits flatlined for a certain
class of query on a couple different kinds of machines with different
IO latencies. I don't feel strongly that we need to be as rigorous for
maintenance_io_concurrency, but I'm also not sure 160 seems reasonable
(which would be the same ratio as before).

- Melanie

#228Andres Freund
andres@anarazel.de
In reply to: Melanie Plageman (#227)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-03-17 14:52:02 -0400, Melanie Plageman wrote:

I don't feel strongly that we need to be as rigorous for
maintenance_io_concurrency, but I'm also not sure 160 seems reasonable
(which would be the same ratio as before).

I'd lean towards just setting them to the same value for now.

Greetings,

Andres Freund

#229Melanie Plageman
melanieplageman@gmail.com
In reply to: Andres Freund (#228)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 17, 2025 at 2:55 PM Andres Freund <andres@anarazel.de> wrote:

On 2025-03-17 14:52:02 -0400, Melanie Plageman wrote:

I don't feel strongly that we need to be as rigorous for
maintenance_io_concurrency, but I'm also not sure 160 seems reasonable
(which would be the same ratio as before).

I'd lean towards just setting them to the same value for now.

Cool, here's the patch I intend to commit. I had a bit of trouble
clearly explaining the situation in the commit message which is why I
didn't directly commit it. If no one has ideas on how to clarify it
by tomorrow, I'll just push it.

- Melanie

Attachments:

Increase-default-maintenance_io_concurrency-to-16.patchtext/x-patch; charset=US-ASCII; name=Increase-default-maintenance_io_concurrency-to-16.patchDownload
From babd220052bcef744e38302e35c6eaee8364027d Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 17 Mar 2025 17:08:49 -0400
Subject: [PATCH v1] Increase default maintenance_io_concurrency to 16

Since its introduction in fc34b0d9de27a, the default
maintenance_io_concurrency has been larger than the default
effective_io_concurrency. This made sense at the time because
maintenance_io_concurrency controlled I/O prefetching done on behalf of
many client sessions (such as in recovery).

ff79b5b2ab increased effective_io_concurrency to 16, so
we'll increase maintenance_io_concurrency as well.

For now, though, we'll keep the defaults of effective_io_concurrency and
maintenance_io_concurrency equal to one another (16).

Since 9256822608f and c3e775e608f, maintenance_io_concurrency also
controls the I/O concurrency of each vacuum worker. Since many
autovacuum workers may be simultaneously issuing I/Os, an appropriate
default value for maintenance_io_concurrency is likely closer to that of
the default effective_io_concurrency rather than the previous ratio
(10x).

Suggested-by: Jakub Wartak <jakub.wartak@enterprisedb.com>
Discussion: https://postgr.es/m/CAKZiRmxdHQaU%2B2Zpe6d%3Dx%3D0vigJ1sfWwwVYLJAf%3Dud_wQ_VcUw%40mail.gmail.com
---
 doc/src/sgml/config.sgml                      | 8 ++++----
 src/backend/utils/misc/postgresql.conf.sample | 2 +-
 src/include/storage/bufmgr.h                  | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 3d62c8bd274..a3aae67746b 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2617,10 +2617,10 @@ include_dir 'conf.d'
          for maintenance work that is done on behalf of many client sessions.
         </para>
         <para>
-         The default is 10 on supported systems, otherwise 0.  This value can
-         be overridden for tables in a particular tablespace by setting the
-         tablespace parameter of the same name (see
-         <xref linkend="sql-altertablespace"/>).
+         The default is <literal>16</literal> on supported systems, otherwise
+         <literal>0</literal>.  This value can be overridden for tables in a
+         particular tablespace by setting the tablespace parameter of the same
+         name (see <xref linkend="sql-altertablespace"/>).
         </para>
        </listitem>
       </varlistentry>
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 8de86e0c945..613d5b3ee39 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -199,7 +199,7 @@
 
 #backend_flush_after = 0		# measured in pages, 0 disables
 #effective_io_concurrency = 16		# 1-1000; 0 disables prefetching
-#maintenance_io_concurrency = 10	# 1-1000; 0 disables prefetching
+#maintenance_io_concurrency = 16	# 1-1000; 0 disables prefetching
 #io_combine_limit = 128kB		# usually 1-32 blocks (depends on OS)
 
 # - Worker Processes -
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 79a89f87fcc..7f5def6bada 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -153,7 +153,7 @@ extern PGDLLIMPORT bool track_io_timing;
 /* only applicable when prefetching is available */
 #ifdef USE_PREFETCH
 #define DEFAULT_EFFECTIVE_IO_CONCURRENCY 16
-#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10
+#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 16
 #else
 #define DEFAULT_EFFECTIVE_IO_CONCURRENCY 0
 #define DEFAULT_MAINTENANCE_IO_CONCURRENCY 0
-- 
2.34.1

#230Jakub Wartak
jakub.wartak@enterprisedb.com
In reply to: Melanie Plageman (#229)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 17, 2025 at 10:46 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

On Mon, Mar 17, 2025 at 2:55 PM Andres Freund <andres@anarazel.de> wrote:

On 2025-03-17 14:52:02 -0400, Melanie Plageman wrote:

I don't feel strongly that we need to be as rigorous for
maintenance_io_concurrency, but I'm also not sure 160 seems reasonable
(which would be the same ratio as before).

I'd lean towards just setting them to the same value for now.

Cool, here's the patch I intend to commit. I had a bit of trouble
clearly explaining the situation in the commit message which is why I
didn't directly commit it. If no one has ideas on how to clarify it
by tomorrow, I'll just push it.

Hi Melanie, same (160 is probably way too high for default m_io_c on
default/small systems with s_b=128MB, but the same value is probably
fine), so +1.

One may say that higher m_io_c may hurt , but at least for
startup/recovery performance see image [1]/messages/by-id/attachment/116928/trandomuuids-without-FPW-1.5kTPS_lagOverSize.csv-comments.png (from thread [2]/messages/by-id/VI1PR0701MB69608CBCE44D80857E59572EF6CA0@VI1PR0701MB6960.eurprd07.prod.outlook.com) - it
shows running it on NVMe with m_io_c=128 and being faster than
default =10 and later Tomas V. pushed it even into value of "500" [3]/messages/by-id/c5d52837-6256-0556-ac8c-d6d3d558820a@enterprisedb.com.
Hope that helps.

-J.

[1]: /messages/by-id/attachment/116928/trandomuuids-without-FPW-1.5kTPS_lagOverSize.csv-comments.png
[2]: /messages/by-id/VI1PR0701MB69608CBCE44D80857E59572EF6CA0@VI1PR0701MB6960.eurprd07.prod.outlook.com
[3]: /messages/by-id/c5d52837-6256-0556-ac8c-d6d3d558820a@enterprisedb.com

#231Alexander Lakhin
exclusion@gmail.com
In reply to: Melanie Plageman (#224)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hello Melanie,

15.03.2025 16:43, Melanie Plageman wrote:

On Thu, Mar 13, 2025 at 5:41 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Overall, I feel pretty good about merging this once Thomas merges the
read stream patches.

This was committed in 944e81bf99db2b5b70b, 2b73a8cd33b745c, and
c3953226a07527a1e2.
I've marked it as committed in the CF app.

It looks like that change made the bitmapops test unstable (on slow animals?): [1]https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=skink&amp;dt=2025-03-16%2010%3A34%3A17, [2]https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=flaviventris&amp;dt=2025-03-17%2020%3A07%3A43, [3]https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=skink&amp;dt=2025-03-17%2001%3A16%3A02.
I've reproduced such test failures when running
TESTS=$(printf 'bitmapops %.0s' `seq 50`) make -s check-tests
under Valgrind:
...
ok 17        - bitmapops                               52719 ms
not ok 18    - bitmapops                               57566 ms
ok 19        - bitmapops                               60179 ms
ok 20        - bitmapops                               32927 ms
ok 21        - bitmapops                               45127 ms
ok 22        - bitmapops                               42924 ms
ok 23        - bitmapops                               61035 ms
ok 24        - bitmapops                               56316 ms
ok 25        - bitmapops                               52874 ms
not ok 26    - bitmapops                               67468 ms
ok 27        - bitmapops                               55605 ms
ok 28        - bitmapops                               24021 ms
...

diff -U3 /home/vagrant/postgresql/src/test/regress/expected/bitmapops.out 
/home/vagrant/postgresql/src/test/regress/results/bitmapops.out
--- /home/vagrant/postgresql/src/test/regress/expected/bitmapops.out 2025-03-16 01:37:52.716885600 -0700
+++ /home/vagrant/postgresql/src/test/regress/results/bitmapops.out 2025-03-22 03:47:54.014702406 -0700
@@ -24,14 +24,14 @@
  SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1;
   count
  -------
-    23
+    18
  (1 row)

 -- Test bitmap-or.
 SELECT count(*) FROM bmscantest WHERE a = 1 OR b = 1;
  count
 -------
-  2485
+  1044
 (1 row)

  -- clean up
diff -U3 /home/vagrant/postgresql/src/test/regress/expected/bitmapops.out 
/home/vagrant/postgresql/src/test/regress/results/bitmapops.out
--- /home/vagrant/postgresql/src/test/regress/expected/bitmapops.out 2025-03-16 01:37:52.716885600 -0700
+++ /home/vagrant/postgresql/src/test/regress/results/bitmapops.out 2025-03-22 03:54:53.129549597 -0700
@@ -31,7 +31,7 @@
  SELECT count(*) FROM bmscantest WHERE a = 1 OR b = 1;
   count
  -------
-  2485
+  1044
  (1 row)

git bisect for this deviation has pointed at 2b73a8cd3.

[1]: https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=skink&amp;dt=2025-03-16%2010%3A34%3A17
[2]: https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=flaviventris&amp;dt=2025-03-17%2020%3A07%3A43
[3]: https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=skink&amp;dt=2025-03-17%2001%3A16%3A02

Best regards,
Alexander Lakhin
Neon (https://neon.tech)

#232Andres Freund
andres@anarazel.de
In reply to: Alexander Lakhin (#231)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-03-22 22:00:00 +0200, Alexander Lakhin wrote:

15.03.2025 16:43, Melanie Plageman wrote:

On Thu, Mar 13, 2025 at 5:41 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Overall, I feel pretty good about merging this once Thomas merges the
read stream patches.

This was committed in 944e81bf99db2b5b70b, 2b73a8cd33b745c, and
c3953226a07527a1e2.
I've marked it as committed in the CF app.

It looks like that change made the bitmapops test unstable (on slow animals?): [1], [2], [3].
I've reproduced such test failures when running
TESTS=$(printf 'bitmapops %.0s' `seq 50`) make -s check-tests
under Valgrind:
...
ok 17        - bitmapops                               52719 ms
not ok 18    - bitmapops                               57566 ms
ok 19        - bitmapops                               60179 ms
ok 20        - bitmapops                               32927 ms
ok 21        - bitmapops                               45127 ms
ok 22        - bitmapops                               42924 ms
ok 23        - bitmapops                               61035 ms
ok 24        - bitmapops                               56316 ms
ok 25        - bitmapops                               52874 ms
not ok 26    - bitmapops                               67468 ms
ok 27        - bitmapops                               55605 ms
ok 28        - bitmapops                               24021 ms
...

diff -U3 /home/vagrant/postgresql/src/test/regress/expected/bitmapops.out
/home/vagrant/postgresql/src/test/regress/results/bitmapops.out
--- /home/vagrant/postgresql/src/test/regress/expected/bitmapops.out 2025-03-16 01:37:52.716885600 -0700
+++ /home/vagrant/postgresql/src/test/regress/results/bitmapops.out 2025-03-22 03:47:54.014702406 -0700
@@ -24,14 +24,14 @@
 SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1;
  count
 -------
-    23
+    18
 (1 row)

Is it possible that this is the bug reported here:
/messages/by-id/873c33c5-ef9e-41f6-80b2-2f5e11869f1c@garret.ru

I.e. that the all-visible logic in bitmap heapscans is fundamentally broken?

I can reproduce different results on a fast machien by just putting a VACUUM
FREEZE bmscantest after the CREATE INDEXes in bitmapops.sql. After I disable
the all-visible logic in bitmapheap_stream_read_next(), I can't observe such a
difference anymore.

Greetings,

Andres Freund

#233Andres Freund
andres@anarazel.de
In reply to: Andres Freund (#232)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-03-22 16:14:11 -0400, Andres Freund wrote:

On 2025-03-22 22:00:00 +0200, Alexander Lakhin wrote:

@@ -24,14 +24,14 @@
�SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1;
� count
�-------
-��� 23
+��� 18
�(1 row)

Is it possible that this is the bug reported here:
/messages/by-id/873c33c5-ef9e-41f6-80b2-2f5e11869f1c@garret.ru

I.e. that the all-visible logic in bitmap heapscans is fundamentally broken?

I can reproduce different results on a fast machien by just putting a VACUUM
FREEZE bmscantest after the CREATE INDEXes in bitmapops.sql. After I disable
the all-visible logic in bitmapheap_stream_read_next(), I can't observe such a
difference anymore.

Hm, it's clearly related to the all-visible path, but I think the bug is
actually independent of what was reported there. The bug you reported is
perfectly reproducible, without any concurrency, after all.

Here's a smaller reproducer:

CREATE TABLE bmscantest (a int, t text);

INSERT INTO bmscantest
SELECT (r%53), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
FROM generate_series(1,70000) r;

CREATE INDEX i_bmtest_a ON bmscantest(a);
set enable_indexscan=false;
set enable_seqscan=false;

-- Lower work_mem to trigger use of lossy bitmaps
set work_mem = 64;

SELECT count(*) FROM bmscantest WHERE a = 1;
vacuum freeze bmscantest;
SELECT count(*) FROM bmscantest WHERE a = 1;

-- clean up
DROP TABLE bmscantest;

The first SELECT reports 1321, the second 572 tuples.

Greetings,

Andres Freund

#234Andres Freund
andres@anarazel.de
In reply to: Andres Freund (#233)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-03-22 16:42:42 -0400, Andres Freund wrote:

Hm, it's clearly related to the all-visible path, but I think the bug is
actually independent of what was reported there. The bug you reported is
perfectly reproducible, without any concurrency, after all.

Here's a smaller reproducer:

CREATE TABLE bmscantest (a int, t text);

INSERT INTO bmscantest
SELECT (r%53), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
FROM generate_series(1,70000) r;

CREATE INDEX i_bmtest_a ON bmscantest(a);
set enable_indexscan=false;
set enable_seqscan=false;

-- Lower work_mem to trigger use of lossy bitmaps
set work_mem = 64;

SELECT count(*) FROM bmscantest WHERE a = 1;
vacuum freeze bmscantest;
SELECT count(*) FROM bmscantest WHERE a = 1;

-- clean up
DROP TABLE bmscantest;

The first SELECT reports 1321, the second 572 tuples.

The problem is that sometimes recheck is performed for pending empty
tuples. The comment about empty tuples says:

/*
* Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
* all empty tuples at the end instead of emitting them per block we
* skip fetching. This is necessary because the streaming read API
* will only return TBMIterateResults for blocks actually fetched.
* When we skip fetching a block, we keep track of how many empty
* tuples to emit at the end of the BitmapHeapScan. We do not recheck
* all NULL tuples.
*/
*recheck = false;
return bscan->rs_empty_tuples_pending > 0;

But we actually emit empty tuples at each page boundary:

/*
* Out of range? If so, nothing more to look at on this page
*/
while (hscan->rs_cindex >= hscan->rs_ntuples)
{
/*
* Emit empty tuples before advancing to the next block
*/
if (bscan->rs_empty_tuples_pending > 0)
{
/*
* If we don't have to fetch the tuple, just return nulls.
*/
ExecStoreAllNullTuple(slot);
bscan->rs_empty_tuples_pending--;
return true;
}

/*
* Returns false if the bitmap is exhausted and there are no further
* blocks we need to scan.
*/
if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
return false;
}

So we don't just process tuples at the end of the scan, but at each page
boundary.

This leads to wrong results whenever there is a rs_empty_tuples_pending > 0
after a previous page that needed rechecks, because nothing will reset
*recheck = false.

And indeed, if I add a *recheck = false in that inside the
/*
* Emit empty tuples before advancing to the next block
*/
if (bscan->rs_empty_tuples_pending > 0)
{
the problem goes away.

A fix should do slightly more, given that the "at the end" comment is wrong.

But I'm wondering if it's worth fixing it, or if we should just rip the logic
out alltogether, due to the whole VM checking being unsound as we learned in
the thread I referenced earlie, without even bothering to fix the bug here.

Greetings,

Andres Freund

#235Melanie Plageman
melanieplageman@gmail.com
In reply to: Andres Freund (#234)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sat, Mar 22, 2025 at 5:04 PM Andres Freund <andres@anarazel.de> wrote:

The problem is that sometimes recheck is performed for pending empty
tuples. The comment about empty tuples says:

/*
* Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
* all empty tuples at the end instead of emitting them per block we
* skip fetching. This is necessary because the streaming read API
* will only return TBMIterateResults for blocks actually fetched.
* When we skip fetching a block, we keep track of how many empty
* tuples to emit at the end of the BitmapHeapScan. We do not recheck
* all NULL tuples.
*/
*recheck = false;
return bscan->rs_empty_tuples_pending > 0;

But we actually emit empty tuples at each page boundary:

/*
* Out of range? If so, nothing more to look at on this page
*/
while (hscan->rs_cindex >= hscan->rs_ntuples)
{
/*
* Emit empty tuples before advancing to the next block
*/
if (bscan->rs_empty_tuples_pending > 0)
{
/*
* If we don't have to fetch the tuple, just return nulls.
*/
ExecStoreAllNullTuple(slot);
bscan->rs_empty_tuples_pending--;
return true;
}

/*
* Returns false if the bitmap is exhausted and there are no further
* blocks we need to scan.
*/
if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages))
return false;
}

So we don't just process tuples at the end of the scan, but at each page
boundary.

Whoops! I think an earlier version of the patch did emit all the empty
tuples at the end, but I changed the control flow without moving the
recheck = false and removing/modifying that comment. Quite
embarrassing.

This leads to wrong results whenever there is a rs_empty_tuples_pending > 0
after a previous page that needed rechecks, because nothing will reset
*recheck = false.

And indeed, if I add a *recheck = false in that inside the
/*
* Emit empty tuples before advancing to the next block
*/
if (bscan->rs_empty_tuples_pending > 0)
{
the problem goes away.

A fix should do slightly more, given that the "at the end" comment is wrong.

But I'm wondering if it's worth fixing it, or if we should just rip the logic
out alltogether, due to the whole VM checking being unsound as we learned in
the thread I referenced earlie, without even bothering to fix the bug here.

Perhaps it is better I just fix it since ripping out the skip fetch
optimization has to be backported and even though that will look very
different on master than on backbranches, I wonder if people will look
for a "clean" commit on master which removes the feature.

- Melanie

#236Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#235)
1 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Sun, Mar 23, 2025 at 1:27 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Perhaps it is better I just fix it since ripping out the skip fetch
optimization has to be backported and even though that will look very
different on master than on backbranches, I wonder if people will look
for a "clean" commit on master which removes the feature.

This is the patch I intend to commit to fix this assuming my CI passes
and there are no objections. I did add a bit of coverage for this in
bitmapops.sql. I'm not sure if that is the right thing to do since
that coverage should be removed when we remove skip fetch and there is
no point in adding the extra query and vacuum freeze if we don't have
the skip fetch optimization.

- Melanie

Attachments:

Fix-bitmapheapscan-incorrect-recheck-of-NULL-tupl.patchtext/x-patch; charset=US-ASCII; name=Fix-bitmapheapscan-incorrect-recheck-of-NULL-tupl.patchDownload
From a924f04e8875ec2ba207e647eb1ecbbb5fff789a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 24 Mar 2025 11:49:49 -0400
Subject: [PATCH v1] Fix bitmapheapscan incorrect recheck of NULL tuples

The bitmap heap scan skip fetch optimization skips fetching the heap
block when a page is set all-visible in the visibility map and no
columns from the table are needed to satisfy the query.

2b73a8cd33b and c3953226a07 changed the control flow of bitmap heap scan
to use the read stream API. The read stream API returns buffers
containing blocks to the user. To make this work with the skip fetch
optimization, we keep a count of the empty tuples we need to emit for
all the blocks skipped and only emit the empty tuples after processing
the next block fetched from the heap or at the end of the scan.

It's incorrect to recheck NULL tuples, so we must set `recheck` to false
before yielding control back to BitmapHeapNext(). This was done before
emitting any remaining empty tuples at the end of the scan but not for
empty tuples emitted during the scan. This meant that if a page fetched
from the heap did require recheck and set `recheck` to true and then we
emitted empty tuples for subsequent blocks, we would get wrong results.

Fix this by always setting `recheck` to false before emitting empty
tuples.

Reported-by: Alexander Lakhin <exclusion@gmail.com>
Tested-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/496f7acd-881c-4df3-9bd3-8f8534dfec26%40gmail.com
---
 src/backend/access/heap/heapam_handler.c | 28 ++++++++++++++++++------
 src/test/regress/expected/bitmapops.out  | 14 ++++++++++--
 src/test/regress/sql/bitmapops.sql       | 10 +++++++--
 3 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 4da4dc84580..24d3765aa20 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2147,6 +2147,19 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 			 */
 			ExecStoreAllNullTuple(slot);
 			bscan->rs_empty_tuples_pending--;
+
+			/*
+			 * We do not recheck all NULL tuples. Because the streaming read
+			 * API only yields TBMIterateResults for blocks actually fetched
+			 * from the heap, we must unset `recheck` ourselves here to ensure
+			 * correct results.
+			 *
+			 * Our read stream callback accrues a count of empty tuples to
+			 * emit and then emits them after emitting tuples from the next
+			 * fetched block. If no blocks need fetching, we'll emit the
+			 * accrued count at the end of the scan.
+			 */
+			*recheck = false;
 			return true;
 		}
 
@@ -2510,13 +2523,14 @@ BitmapHeapScanNextBlock(TableScanDesc scan,
 		}
 
 		/*
-		 * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
-		 * all empty tuples at the end instead of emitting them per block we
-		 * skip fetching. This is necessary because the streaming read API
-		 * will only return TBMIterateResults for blocks actually fetched.
-		 * When we skip fetching a block, we keep track of how many empty
-		 * tuples to emit at the end of the BitmapHeapScan. We do not recheck
-		 * all NULL tuples.
+		 * The bitmap is exhausted. Now emit any remaining empty tuples. The
+		 * read stream API only returns TBMIterateResults for blocks actually
+		 * fetched from the heap. Our callback will accrue a count of empty
+		 * tuples to emit for all blocks we skipped fetching. So, if we skip
+		 * fetching heap blocks at the end of the relation (or no heap blocks
+		 * are fetched) we need to ensure we emit empty tuples before ending
+		 * the scan. We don't recheck empty tuples so ensure `recheck` is
+		 * unset.
 		 */
 		*recheck = false;
 		return bscan->rs_empty_tuples_pending > 0;
diff --git a/src/test/regress/expected/bitmapops.out b/src/test/regress/expected/bitmapops.out
index 3570973e3ca..64068e0469c 100644
--- a/src/test/regress/expected/bitmapops.out
+++ b/src/test/regress/expected/bitmapops.out
@@ -8,7 +8,7 @@
 -- there's a maximum number of a,b combinations in the table.
 -- That allows us to test all the different combinations of
 -- lossy and non-lossy pages with the minimum amount of data
-CREATE TABLE bmscantest (a int, b int, t text);
+CREATE TABLE bmscantest (a int, b int, t text) WITH (autovacuum_enabled = false);
 INSERT INTO bmscantest
   SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
   FROM generate_series(1,70000) r;
@@ -20,7 +20,17 @@ set enable_indexscan=false;
 set enable_seqscan=false;
 -- Lower work_mem to trigger use of lossy bitmaps
 set work_mem = 64;
--- Test bitmap-and.
+-- Test bitmap-and without the skip fetch optimization.
+SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1;
+ count 
+-------
+    23
+(1 row)
+
+-- Test that we return correct results when using the skip fetch optimization
+-- VACUUM FREEZE will set all the pages in the relation all-visible, enabling
+-- the optimization.
+VACUUM (FREEZE) bmscantest;
 SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1;
  count 
 -------
diff --git a/src/test/regress/sql/bitmapops.sql b/src/test/regress/sql/bitmapops.sql
index 498f4721b51..1b175f6ff96 100644
--- a/src/test/regress/sql/bitmapops.sql
+++ b/src/test/regress/sql/bitmapops.sql
@@ -12,7 +12,7 @@
 -- That allows us to test all the different combinations of
 -- lossy and non-lossy pages with the minimum amount of data
 
-CREATE TABLE bmscantest (a int, b int, t text);
+CREATE TABLE bmscantest (a int, b int, t text) WITH (autovacuum_enabled = false);
 
 INSERT INTO bmscantest
   SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
@@ -29,8 +29,14 @@ set enable_seqscan=false;
 -- Lower work_mem to trigger use of lossy bitmaps
 set work_mem = 64;
 
+-- Test bitmap-and without the skip fetch optimization.
+SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1;
+
+-- Test that we return correct results when using the skip fetch optimization
+-- VACUUM FREEZE will set all the pages in the relation all-visible, enabling
+-- the optimization.
+VACUUM (FREEZE) bmscantest;
 
--- Test bitmap-and.
 SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1;
 
 -- Test bitmap-or.
-- 
2.34.1

#237Melanie Plageman
melanieplageman@gmail.com
In reply to: Melanie Plageman (#236)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Mar 24, 2025 at 12:14 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

This is the patch I intend to commit to fix this assuming my CI passes
and there are no objections.

And pushed in aea916fe555a3

- Melanie

#238Thomas Munro
thomas.munro@gmail.com
In reply to: Melanie Plageman (#183)
2 attachment(s)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Feb 13, 2025 at 1:40 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

I had a crack at this one a few weeks back, and wanted to share some
thoughts. Getting sequential block range allocation work was easy
(0001), but ramp-down at this level as a parallel query fairness
strategy seems to be fundamentally incompatible with AIO. 0002 was an
abandoned attempt before I got lost for a while researching the
futility of it all. See further down. I gave up for v18.

Of course we already have this problem in v18, but 0001 would magnify
it. Whether gaining I/O combining is worth losing some parallel
fairness, IDK, but it can wait...

With just the 0001 patch, io_workers=1 and two parallel processes, you
can trace the IO worker to see the ramp-up in each parallel worker and
the maximised I/O combining, but also the abrupt and unfair
end-of-scan:

tmunro@x1:~/projects/postgresql/build$ strace -p 377335 -e
trace=preadv,pread64 -s0
strace: Process 377335 attached
pread64(16, ""..., 8192, 720896) = 8192
pread64(16, ""..., 8192, 729088) = 8192
pread64(16, ""..., 16384, 737280) = 16384
pread64(16, ""..., 16384, 753664) = 16384
pread64(16, ""..., 32768, 802816) = 32768
pread64(16, ""..., 32768, 770048) = 32768
pread64(16, ""..., 65536, 835584) = 65536
pread64(16, ""..., 65536, 901120) = 65536
pread64(16, ""..., 131072, 966656) = 131072
pread64(16, ""..., 131072, 1228800) = 131072
pread64(16, ""..., 131072, 1097728) = 131072
pread64(16, ""..., 131072, 1490944) = 131072
pread64(16, ""..., 131072, 1359872) = 131072
pread64(16, ""..., 131072, 1753088) = 131072
pread64(16, ""..., 131072, 1884160) = 131072
pread64(16, ""..., 131072, 1622016) = 131072
pread64(16, ""..., 131072, 2015232) = 131072
preadv(16, [...], 7, 2146304) = 131072
preadv(16, [...], 7, 2277376) = 131072
pread64(16, ""..., 131072, 2539520) = 131072
pread64(16, ""..., 131072, 2408448) = 131072
pread64(16, ""..., 98304, 2801664) = 98304
pread64(16, ""..., 131072, 2670592) = 131072

For real parallel query fairness, I wonder if we should think about a
work stealing approach. Let me sketch out a simple idea first, and
explain why it's still not enough, and then sketch out a bigger idea:

Imagine a thing called WorkQueueSet in shared memory that contains a
WorkQueue for each worker, and then a function
wqs_get_next_object(&state->tidbitmap_wqs, &object) that looks in your
own backend's queue first, and if there is nothing, it calls a
registered callback that tries to fill your queue up (the current TBM
iterator logic becomes that callback in this case, and the per-backend
WorkQueue replaces the little array that I added in the attached 0001
patch), and if that doesn't work it tries to steal from everyone
else's queue, and if that fails then there really is no more work to
be done and your scan is finished. That should be perfectly fair, not
just approximately fair under certain assumptions (that are now false)
like ramp down schemes. *If* we can figure out how to make the
interlocking so lightweight that the common case of consuming from
your own uncontended work queue is practically as fast as reading out
of a local array... (I have a few ideas about that part but this is
already long enough...)

But that only provides ramp-down for the block number ranges
*entering* each worker's ReadStream. Our goal is to make the workers
run out of work as close in time as possible, and their work begins
when buffers *exit* each worker's ReadStream. Thought experiment:
what if we could also steal blocks/buffers that someone else's
ReadStream holds, whether already valid, referenced by an inflight
I/O, or waiting to be combined with more blocks in the pending read?
The buffer manager can already deal with any and all races at its
level and do the right thing, but we'd somehow need to make sure the
theft victim doesn't also process that block. The ReadStream's buffer
queue could be integrated with your backend's WorkQueue in a
WorkQueueSet in shared memory, so that others can steal your stuff,
and read_stream_next_buffer() would have to discard anything that has
been stolen between entering and exiting the stream. The common
non-stolen case would have to be extremely cheap, read barriers and
ordering tricks I guess. (This is basically a new take on an idea I
have mentioned before, parallel-aware ReadStream, except that all
previous versions collapsed in a heap of lock contention and other
design problems. Work stealing seems to offer a way to keep
everything almost as it is now, except in a few weird corner cases at
end-of-stream when new magic fires up only if required. It also seems
to be such a broadly useful technique that I'd want a general purpose
thing, not just a ReadStream internal trick.)

Putting both things together, I'm wondering about *two* levels of
WorkQueueSet for stuff like Seq Scan and BHS.

1. Preserve I/O combining opportunities: The ReadStream's block
number callback uses WorkQueueSet to hand out block numbers as
described a couple of paragraphs above (perhaps
WORK_QUEUE_TYPE_BLOCK_RANGE would be a built-in mode with queue
elements [blockno, nblocks] so you can consume from them and dequeue
once depleted to implement tableam.c's parallel seq block allocator,
with the callback working just as it does now except with the
ramp-down part removed, and tidbitmap.c would use WORK_QUEUE_TYPE_BLOB
to traffic TBMWorkQueueItem objects replacing the current
TBMIteratorResult).

2. Fairness: The ReadStream is put into a mode that attaches to your
backend's WorkQueue in a second WorkQueueSet, and uses it for buffers
and per-buffer-data. This allowing other ReadStreams in other
processes attached to the same WorkQueueSet to steal stuff. In the
common case, there's no stealing, but at stream end you get perfect
fairness.

I suspect that a generic work stealing component would find many other
uses. I can think of quite a few, but here's one: It might be able to
fix the PHJ unmatched scan unfairness problem, within the constraints
of our existing executor model. Thought experiment: PHJ_BATCH_PROBE
and PHJ_BATCH_SCAN are merged into one phase. Each worker emits
already joined tuples from a WorkQueueSet (IDK how they hold tuples
exactly, this is hand-waving level). The callback that pulls those
tuples into your backend's WorkQueue does the actual joining and sets
the match bit, which has the crucial property that you can know when
all all bits are set without waiting, and then the callback can switch
to feeding unmatched tuples into the work queue for FULL/RIGHT joins,
and every worker can participate. No weird
detach-and-drop-to-single-process, no wait, no deadlock risk. The
callback's batch size would become a new source of unfairness when
performing the join, so perhaps you need two levels of WorkQueueSet,
one for pre-joined tuples and one for post-joined tuples, and only
when both are completely exhausted do you have all match bits (there
is a small extra complication: I think you need a concept of 'dequeued
but busy' when moving items from pre-joined to post-joined, and a CV
so you can wait for that condition to clear, or something like that,
but that's a guaranteed-progress wait and only used in a very rare
edge case; if I'm making in mistake in all this it may be related to
this type of thing, but I'm not seeing anything unsolvable). Note
that I didn't say you could take over other workers' scans, which we
definitely *can't* do with our current executor model, I'm just saying
that if there is no stealable work left, matching must be finished.
If that sounds expensive, one thought is that it also provides a tidy
solution to my old conundrum "how to do batch-oriented outer scan with
the timing and control needed to drive software memory prefetching",
ie without falling down the executor volcano by calling ExecProcNode()
between prefetches; I strongly suspect that would provide so much
speedup that it could easily pay for the cost of the extra steps,
again assuming we can make the uncontended case blindingly fast.
Maybe, IDK, I could be missing things...

Anyway, that was a long explanation for why I didn't come up with an
easy patch to teach PBHS not to destroy I/O combining opportunities
for v18 :-) The short version is that 0001 does address the immediate
problem we identified, but also helped me see the bigger picture a
little bit more clearly and find a few interesting connections.
Parallel query and I/O streaming are just not the best of friends,
yet. R&D needed.

Attachments:

0001-Teach-Parallel-Bitmap-Heap-Scan-to-combine-I-O.patchtext/x-patch; charset=US-ASCII; name=0001-Teach-Parallel-Bitmap-Heap-Scan-to-combine-I-O.patchDownload
From 836c406337edda3a7e440d020d7d5a229f7e1099 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Tue, 18 Mar 2025 22:27:36 +1300
Subject: [PATCH 1/2] Teach Parallel Bitmap Heap Scan to combine I/O.

As 56788d21 did for parallel sequential scans, make TIDBitmap preserve
locality when giving block numbers to parallel workers, instead of
generating a stream of little islands with gaps in between.

Now it will fetch at least 8 block numbers from the shared bitmap at
once and then more if required keep opportunities to combine I/O.  The
exception is at the start of the scan, following a common pattern for
such things.

XXX Not done: ramp down at the end of the scan, for fair parallel work
allocation.

Even when no I/O is involved, it didn't seem ideal to hand out single
blocks under an exclusive lock.

XXX But 8 was chosen arbitrarily.

Discussion: https://postgr.es/m/CAAKRu_YhYy6Te5ZNiijtayr6mM-7O0B3UXm7mFOCN8U%3DiFgoxg%40mail.gmail.com
---
 src/backend/nodes/tidbitmap.c | 228 ++++++++++++++++++++++++----------
 1 file changed, 161 insertions(+), 67 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 41031aa8f2f..d9e6a957de4 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -44,6 +44,7 @@
 #include "common/int.h"
 #include "nodes/bitmapset.h"
 #include "nodes/tidbitmap.h"
+#include "storage/bufmgr.h"
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
@@ -74,6 +75,14 @@
 /* number of active words for a lossy chunk: */
 #define WORDS_PER_CHUNK  ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1)
 
+/*
+ * The number of blocks to fetch at once when iterating through a shared
+ * bitmap in a parallel query to reduce lock contention.  The number actually
+ * fetched may be higher if trailing sequential neighbors are included to
+ * encourage I/O combining.
+ */
+#define TBM_SHARED_FETCH 8
+
 /*
  * The hashtable entries are represented by this data structure.  For
  * an exact page, blockno is the page number and bit k of the bitmap
@@ -212,6 +221,12 @@ struct TBMSharedIterator
 	PTEntryArray *ptbase;		/* pagetable element array */
 	PTIterationArray *ptpages;	/* sorted exact page index list */
 	PTIterationArray *ptchunks; /* sorted lossy page index list */
+
+	/* Results fetched from shared memory in bulk, ready to be consumed. */
+	int			result_index;
+	int			result_count;
+	int			result_capacity;
+	TBMIterateResult results[FLEXIBLE_ARRAY_MEMBER];
 };
 
 /* Local function prototypes */
@@ -1046,6 +1061,34 @@ tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 	return false;
 }
 
+/*
+ * Decide whether to claim a candidate block for the current batch or stop
+ * here without including it.
+ */
+static inline bool
+tbm_shared_iterate_include_block_p(TBMSharedIterator *iterator,
+								   BlockNumber candidate_blockno,
+								   BlockNumber *next_blockno,
+								   int *seq_count)
+{
+	/* Track the length of the current sequential cluster of blocks. */
+	if (candidate_blockno == *next_blockno)
+		*seq_count += 1;
+	else
+		*seq_count = 1;
+	*next_blockno = candidate_blockno + 1;
+
+	/* If we haven't reached the target batch size yet, then definitely. */
+	if (iterator->result_count < TBM_SHARED_FETCH)
+		return true;
+
+	/*
+	 * We're prepared to go bigger, but only to avoid an arbitrary break in a
+	 * potential combined I/O.
+	 */
+	return *seq_count > 1 && *seq_count <= io_combine_limit;
+}
+
 /*
  *	tbm_shared_iterate - scan through next page of a TIDBitmap
  *
@@ -1056,87 +1099,128 @@ tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 bool
 tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 {
-	TBMSharedIteratorState *istate = iterator->state;
-	PagetableEntry *ptbase = NULL;
-	int		   *idxpages = NULL;
-	int		   *idxchunks = NULL;
-
-	if (iterator->ptbase != NULL)
-		ptbase = iterator->ptbase->ptentry;
-	if (iterator->ptpages != NULL)
-		idxpages = iterator->ptpages->index;
-	if (iterator->ptchunks != NULL)
-		idxchunks = iterator->ptchunks->index;
+	TBMSharedIteratorState *istate;
+	TBMIterateResult *result;
+	PagetableEntry *ptbase;
+	int		   *idxpages;
+	int		   *idxchunks;
+	int			max_results;
+	int			seq_count;
+	BlockNumber next_blockno;
+
+	/* Return results fetched earlier until they run out. */
+	if (iterator->result_index < iterator->result_count)
+	{
+		*tbmres = iterator->results[iterator->result_index++];
+		return true;
+	}
+
+	/* Prepare to fetch a new batch of results from shared memory. */
+	istate = iterator->state;
+	ptbase = iterator->ptbase->ptentry;
+	idxpages = iterator->ptpages ? iterator->ptpages->index : NULL;
+	idxchunks = iterator->ptchunks ? iterator->ptchunks->index : NULL;
+
+	/* Ramp up from size 1 in case there is a small LIMIT. */
+	if (iterator->result_count == 0)
+		max_results = 1;		/* first time caller */
+	else if (iterator->result_count < iterator->result_capacity / 2)
+		max_results = iterator->result_count * 2;	/* ramp up */
+	else
+		max_results = iterator->result_capacity;	/* saturated */
+
+	/* Write first result in caller's object directly. */
+	result = tbmres;
+	iterator->result_index = 1;
+	iterator->result_count = 0;
+	next_blockno = InvalidBlockNumber;
+	seq_count = 0;
 
 	/* Acquire the LWLock before accessing the shared members */
 	LWLockAcquire(&istate->lock, LW_EXCLUSIVE);
 
-	/*
-	 * If lossy chunk pages remain, make sure we've advanced schunkptr/
-	 * schunkbit to the next set bit.
-	 */
-	while (istate->schunkptr < istate->nchunks)
+	do
 	{
-		PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]];
-		int			schunkbit = istate->schunkbit;
-
-		tbm_advance_schunkbit(chunk, &schunkbit);
-		if (schunkbit < PAGES_PER_CHUNK)
+		/*
+		 * If lossy chunk pages remain, make sure we've advanced schunkptr/
+		 * schunkbit to the next set bit.
+		 */
+		while (istate->schunkptr < istate->nchunks)
 		{
-			istate->schunkbit = schunkbit;
-			break;
-		}
-		/* advance to next chunk */
-		istate->schunkptr++;
-		istate->schunkbit = 0;
-	}
+			PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]];
+			int			schunkbit = istate->schunkbit;
 
-	/*
-	 * If both chunk and per-page data remain, must output the numerically
-	 * earlier page.
-	 */
-	if (istate->schunkptr < istate->nchunks)
-	{
-		PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]];
-		BlockNumber chunk_blockno;
-
-		chunk_blockno = chunk->blockno + istate->schunkbit;
+			tbm_advance_schunkbit(chunk, &schunkbit);
+			if (schunkbit < PAGES_PER_CHUNK)
+			{
+				istate->schunkbit = schunkbit;
+				break;
+			}
+			/* advance to next chunk */
+			istate->schunkptr++;
+			istate->schunkbit = 0;
+		}
 
-		if (istate->spageptr >= istate->npages ||
-			chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
+		/*
+		 * If both chunk and per-page data remain, must output the numerically
+		 * earlier page.
+		 */
+		if (istate->schunkptr < istate->nchunks)
 		{
-			/* Return a lossy page indicator from the chunk */
-			tbmres->blockno = chunk_blockno;
-			tbmres->lossy = true;
-			tbmres->recheck = true;
-			tbmres->internal_page = NULL;
-			istate->schunkbit++;
+			PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]];
+			BlockNumber chunk_blockno;
 
-			LWLockRelease(&istate->lock);
-			return true;
-		}
-	}
-
-	if (istate->spageptr < istate->npages)
-	{
-		PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
+			chunk_blockno = chunk->blockno + istate->schunkbit;
 
-		tbmres->internal_page = page;
-		tbmres->blockno = page->blockno;
-		tbmres->lossy = false;
-		tbmres->recheck = page->recheck;
-		istate->spageptr++;
+			if (istate->spageptr >= istate->npages ||
+				chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
+			{
+				if (!tbm_shared_iterate_include_block_p(iterator,
+														chunk_blockno,
+														&next_blockno,
+														&seq_count))
+					break;
+
+				/* Return a lossy page indicator from the chunk */
+				result->blockno = chunk_blockno;
+				result->lossy = true;
+				result->recheck = true;
+				result->internal_page = NULL;
+				istate->schunkbit++;
+				result = &iterator->results[++iterator->result_count];
+				continue;
+			}
+		}
 
-		LWLockRelease(&istate->lock);
+		if (istate->spageptr < istate->npages)
+		{
+			PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
+
+			if (!tbm_shared_iterate_include_block_p(iterator,
+													page->blockno,
+													&next_blockno,
+													&seq_count))
+				break;
+
+			result->internal_page = page;
+			result->blockno = page->blockno;
+			result->lossy = false;
+			result->recheck = page->recheck;
+			istate->spageptr++;
+			result = &iterator->results[++iterator->result_count];
+			continue;
+		}
 
-		return true;
+		/* Nothing more in the bitmap. */
+		Assert(istate->spageptr == istate->npages);
+		Assert(istate->schunkptr == istate->nchunks);
+		break;
 	}
+	while (iterator->result_count < max_results);
 
 	LWLockRelease(&istate->lock);
 
-	/* Nothing more in the bitmap */
-	tbmres->blockno = InvalidBlockNumber;
-	return false;
+	return iterator->result_count > 0;
 }
 
 /*
@@ -1466,12 +1550,22 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 {
 	TBMSharedIterator *iterator;
 	TBMSharedIteratorState *istate;
+	int			result_capacity;
 
 	/*
-	 * Create the TBMSharedIterator struct, with enough trailing space to
-	 * serve the needs of the TBMIterateResult sub-struct.
+	 * How many blocks to fetch from the shared bitmap at a time, allowing
+	 * extra space for trailing sequential blocks.
+	 */
+	result_capacity = TBM_SHARED_FETCH + io_combine_limit - 1;
+
+	/*
+	 * Create the TBMSharedIterator struct, with enough trailing space for the
+	 * above.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
+	iterator = (TBMSharedIterator *)
+		palloc0(offsetof(TBMSharedIterator, results) +
+				sizeof(iterator->results[0]) * result_capacity);
+	iterator->result_capacity = result_capacity;
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
-- 
2.39.5

0002-XXX-attempt-at-rampdown-in-PBHS.patchtext/x-patch; charset=US-ASCII; name=0002-XXX-attempt-at-rampdown-in-PBHS.patchDownload
From 7f4cc9ae6a2c7d2363b09132f523a18414d9eb41 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Tue, 8 Apr 2025 00:50:18 +1200
Subject: [PATCH 2/2] XXX attempt at rampdown in PBHS

Might have a few fundamental issues...
---
 src/backend/executor/nodeBitmapHeapscan.c |   7 +-
 src/backend/nodes/tidbitmap.c             | 132 +++++++++++++++++++++-
 src/include/nodes/tidbitmap.h             |   2 +-
 3 files changed, 136 insertions(+), 5 deletions(-)

diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index bf24f3d7fe0..f594ebc1a34 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -75,6 +75,8 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 	}
 	else if (BitmapShouldInitializeSharedState(pstate))
 	{
+		int backends;
+
 		/*
 		 * The leader will immediately come out of the function, but others
 		 * will be blocked until leader populates the TBM and wakes them up.
@@ -83,12 +85,15 @@ BitmapTableScanSetup(BitmapHeapScanState *node)
 		if (!node->tbm || !IsA(node->tbm, TIDBitmap))
 			elog(ERROR, "unrecognized result from subplan");
 
+		/* How many backends are expected to iterate over the TBM? */
+		backends = node->ss.ps.state->es_parallel_workers_launched;
+
 		/*
 		 * Prepare to iterate over the TBM. This will return the dsa_pointer
 		 * of the iterator state which will be used by multiple processes to
 		 * iterate jointly.
 		 */
-		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
+		pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm, backends);
 
 		/* We have initialized the shared state so wake up others. */
 		BitmapDoneInitializingSharedState(pstate);
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index d9e6a957de4..39a71648db9 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -44,6 +44,7 @@
 #include "common/int.h"
 #include "nodes/bitmapset.h"
 #include "nodes/tidbitmap.h"
+#include "port/pg_bitutils.h"
 #include "storage/bufmgr.h"
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
@@ -78,8 +79,8 @@
 /*
  * The number of blocks to fetch at once when iterating through a shared
  * bitmap in a parallel query to reduce lock contention.  The number actually
- * fetched may be higher if trailing sequential neighbors are included to
- * encourage I/O combining.
+ * fetched may be lower during ramp-up/ramp-down, or higher if trailing
+ * sequential neighbors are included to encourage I/O combining.
  */
 #define TBM_SHARED_FETCH 8
 
@@ -200,6 +201,12 @@ typedef struct TBMSharedIteratorState
 	int			spageptr;		/* next spages index */
 	int			schunkptr;		/* next schunks index */
 	int			schunkbit;		/* next bit to check in current schunk */
+
+	int			backends;		/* expected number of backends */
+	int			log2_backends;	/* log2 for fast approximate division */
+	int			schunkpages;	/* number of pages left, -1 = not yet known */
+	int			schunkcounted;	/* index of the highest page counted */
+	int			schunksubtotal; /* counted so far */
 } TBMSharedIteratorState;
 
 /*
@@ -766,7 +773,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
  * into pagetable array.
  */
 dsa_pointer
-tbm_prepare_shared_iterate(TIDBitmap *tbm)
+tbm_prepare_shared_iterate(TIDBitmap *tbm, int backends)
 {
 	dsa_pointer dp;
 	TBMSharedIteratorState *istate;
@@ -900,6 +907,13 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm)
 	istate->schunkptr = 0;
 	istate->spageptr = 0;
 
+	/* Initialize the ramp-down control state */
+	istate->backends = backends;
+	istate->log2_backends = pg_ceil_log2_32(backends);
+	istate->schunkpages = -1;
+	istate->schunksubtotal = 0;
+	istate->schunkcounted = istate->nchunks;
+
 	tbm->iterating = TBM_ITERATING_SHARED;
 
 	return dp;
@@ -1089,6 +1103,100 @@ tbm_shared_iterate_include_block_p(TBMSharedIterator *iterator,
 	return *seq_count > 1 && *seq_count <= io_combine_limit;
 }
 
+/*
+ * Count pages in one more tail chunk, until we have enough information to
+ * implement fair ramp-down.  How many it takes depends on their density and
+ * how many backends there are to ramp down.  Returns true when work is done.
+ */
+static bool
+tbm_shared_iterate_popcount(TBMSharedIterator *iterator)
+{
+	TBMSharedIteratorState *istate = iterator->state;
+	PagetableEntry *ptbase = iterator->ptbase->ptentry;
+	int		   *idxchunks;
+	int			ramp_down_pages;
+	int			exact_pages;
+
+	if (iterator->ptchunks == NULL)
+	{
+		istate->schunkpages = 0;	/* no chunks */
+		return true;
+	}
+	idxchunks = iterator->ptchunks->index;
+
+	Assert(LWLockHeldByMeInMode(&istate->lock, LW_EXCLUSIVE));
+	Assert(istate->schunkpages == -1);
+	Assert(istate->schunkbit == 0);
+
+	/* The number of pages needed to ramp down by halving. */
+	ramp_down_pages = pg_nextpower2_32(iterator->result_capacity) - 1;
+	ramp_down_pages *= 2;		/* double counting */
+	ramp_down_pages *= 1 << istate->log2_backends;	/* partial scan */
+
+	/* We always know the number of exact pages left to scan. */
+	exact_pages = istate->npages - istate->spageptr;
+
+	if (exact_pages >= ramp_down_pages ||
+		istate->schunkptr == istate->schunkcounted)
+	{
+		/*
+		 * If the remaining exact pages are already enough, or the scan has
+		 * caught up with the counting (low memory limit), we stop counting.
+		 * Note that we pessimistically assumed that every page might appear
+		 * in a chunk *and* a page entry.  The ramp-down will start too soon
+		 * and happen more gently as they get deduplicated by the scan if
+		 * that's really true, but that's OK.
+		 */
+		istate->schunkpages = istate->schunksubtotal;
+	}
+	else
+	{
+		int			chunk;
+
+		/* Count the pages in one more chunk. */
+		chunk = --istate->schunkcounted;
+		istate->schunksubtotal +=
+			pg_popcount((char *) ptbase[idxchunks[chunk]].words,
+						sizeof(ptbase[idxchunks[chunk]].words));
+
+		/* Have we counted enough pages yet? */
+		if (exact_pages + istate->schunksubtotal >= ramp_down_pages)
+			istate->schunkpages = istate->schunksubtotal;
+	}
+
+	if (istate->schunkpages != -1)
+		elog(DEBUG1, "tidbitmap counted %d bits in %d tail chunks",
+			 istate->schunkpages, istate->nchunks - istate->schunkcounted);
+
+	return istate->schunkpages != -1;
+}
+
+/*
+ * For two backends we want approximately ..., 4, 4, 2, 2, 1, 1 as we approach
+ * the end of the scan.  It doesn't matter what order they are really claimed
+ * in as the unfairness risk of being wrong decreases as we approach one.
+ */
+static inline BlockNumber
+tbm_shared_iterate_ramp_down(TBMSharedIteratorState *istate, int max_results)
+{
+	BlockNumber pages;
+	BlockNumber partial_pages;
+	BlockNumber clamp;
+
+	Assert(istate->schunkpages >= 0);
+	pages = (istate->npages - istate->spageptr) + istate->schunkpages;
+	partial_pages = pages >> istate->log2_backends;
+	clamp = partial_pages / 2;
+	if (clamp < 1)
+		clamp = 1;
+
+	if (max_results > clamp)
+		elog(DEBUG1, "pages = %d, partial_pages = %d, log2_backends = %d, clamped %d->%d", pages, partial_pages, istate->log2_backends, max_results, clamp);
+	Assert(pages > 0);
+
+	return Min(max_results, clamp);
+}
+
 /*
  *	tbm_shared_iterate - scan through next page of a TIDBitmap
  *
@@ -1139,6 +1247,13 @@ tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 	/* Acquire the LWLock before accessing the shared members */
 	LWLockAcquire(&istate->lock, LW_EXCLUSIVE);
 
+	/*
+	 * Ramp down at the end of scan for fair block distribution if we have
+	 * enough information.  Otherwise see below.
+	 */
+	if (istate->schunkpages != -1)
+		max_results = tbm_shared_iterate_ramp_down(istate, max_results);
+
 	do
 	{
 		/*
@@ -1161,6 +1276,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 			istate->schunkbit = 0;
 		}
 
+		/*
+		 * When starting a new chunk, also popcount one more tail chunk, if we
+		 * haven't counted enough to implement fair ramp-down yet.
+		 */
+		if (istate->schunkbit == 0 && istate->schunkpages == -1)
+			if (tbm_shared_iterate_popcount(iterator))
+				max_results = tbm_shared_iterate_ramp_down(istate, max_results);
+
 		/*
 		 * If both chunk and per-page data remain, must output the numerically
 		 * earlier page.
@@ -1187,6 +1310,8 @@ tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 				result->recheck = true;
 				result->internal_page = NULL;
 				istate->schunkbit++;
+				if (istate->schunkpages > 0)
+					istate->schunkpages--;
 				result = &iterator->results[++iterator->result_count];
 				continue;
 			}
@@ -1214,6 +1339,7 @@ tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 		/* Nothing more in the bitmap. */
 		Assert(istate->spageptr == istate->npages);
 		Assert(istate->schunkptr == istate->nchunks);
+		Assert(istate->schunkpages == 0);
 		break;
 	}
 	while (iterator->result_count < max_results);
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 99f795ceab5..8ec07cda5c1 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -100,7 +100,7 @@ extern int	tbm_extract_page_tuple(TBMIterateResult *iteritem,
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
 extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
-extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
+extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm, int backends);
 extern bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres);
 extern bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres);
 extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
-- 
2.39.5

#239James Hunter
james.hunter.pg@gmail.com
In reply to: Thomas Munro (#238)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Mon, Apr 7, 2025 at 7:34 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Thu, Feb 13, 2025 at 1:40 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

I had a crack at this one a few weeks back, and wanted to share some
thoughts.

Fwiw, I've had reasonably good results, in a similar situation, by
just batching + double-buffering.

Since you're using AIO (as Melanie points out) there should be no real
penalty to having a single worker request the next batch of blocks,
when the current block is used up.

Then you can separate "reading" from "prefetching": whoever reads the
last block in the current batch, prefetches the next batch.

This way, you could preserve your existing "reading" logic, and you
wouldn't need to create several new, related queues.

James

#240Thomas Munro
thomas.munro@gmail.com
In reply to: James Hunter (#239)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Apr 9, 2025 at 1:46 PM James Hunter <james.hunter.pg@gmail.com> wrote:

On Mon, Apr 7, 2025 at 7:34 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Thu, Feb 13, 2025 at 1:40 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

I had a crack at this one a few weeks back, and wanted to share some
thoughts.

Fwiw, I've had reasonably good results, in a similar situation, by
just batching + double-buffering.

Since you're using AIO (as Melanie points out) there should be no real
penalty to having a single worker request the next batch of blocks,
when the current block is used up.

Then you can separate "reading" from "prefetching": whoever reads the
last block in the current batch, prefetches the next batch.

I'm trying to understand. IIUC you're suggesting putting the blocks
coming *out* of a worker's ReadStream into a single common shmem queue
for any worker to consume (can't do this for block numbers coming *in*
to the ReadStreams or you're describing what we already have in
master, all mechanical sympathy for I/O out the window). Don't you
have to release the buffers you just streamed after putting their the
block numbers in a common shmem queue, hope they don't get evicted,
repin them when you pop one out, and also contend on the queue for
every block? What if you go to that queue to find a block, find it is
empty, but actually another backend still has an I/O in progress that
you have no way of knowing about? Suppose you do know about it
somehow, so now you have to wait for it to complete the IO before you
can help, but generally speaking it's against the law to wait for
parallel workers unless you can prove they'll come back (for example
there might be another node in the plan where they are waiting for
*you*, deadlock, game over), and even if you could wait safely. If
you don't wait, you just threw parallel fairness out the window.
Hence desire to make all relevant materials for progress at
end-of-scan eligible for work stealing.

What I'm speculating about is not a true generalised work stealing or
scheduling system (take for example Intel TBB[1]https://en.wikipedia.org/wiki/Threading_Building_Blocks and various other
parallel computing architectures going back decades), so I'm using the
term pretty loosely: we can't generally chop all of our executor work
up into tiny tasks and have any thread run any of them at any time to
make progress (that'd be a nice goal but you basically have to blow
the executor up with dynamite and then reassemble all the atoms into
coroutines/continuations/tasks (or various similar-ish concepts) to
achieve something like that, probably after you first make all of
PostgreSQL multi-threaded unless you want to do it with your shoelaces
tied together, and then take a very long holiday). Probably by
mentioning work stealing I made it sound more complicated than
necessary, but hear me out:

A tiny, delimited, node-local kind of work stealing could replace (now
non-viable) ramp-down schemes, but workers would only have to fight
over the remaining scraps once their own queue can't be refilled. The
two key things I'm interested in here are: (1) per-worker queues
preserve block locality in the "first level" WorkQueueSet I was
talking about, to feed io_combine_limit-friendly block number streams
into their ReadStreams and only disturb that when data runs out and
stealing becomes necessary for the last few blocks in the scan, and
(2) at both levels a known-in-advance finite space can hold the
maximum possible unfair allocation to each worker, with certain
caveats. Those are: this logic only kicks in at end of scan when you
can be guaranteed to "get them all" without ever having to wait for
data buffered in the executor state of some other worker (data that is
completely unreachable to peers in our executor model), assuming, and
this is a hard requirement, they are coming from the same source in
all workers (in this case the shared memory bitmap, which you lock
while advancing the shared iterator, and a subgoal of 0001 was to
amortise that locking). It means there's a finite known number of
items that other workers can possibly have in their per-worker queue
that you definitely have enough space for, so wait-free progress
towards the global end-of-scan is guaranteed in every worker after it
reaches the point of stealing. For something a bit like the 0001
patch I posted, it can't be more than _BATCH_SIZE + io_combine_limit
-1 for the lower WorkQueueSet that feeds block numbers into each
worker's ReadStream. Something like Parallel Seq Scan involves an
extra curveball: I don't think you can do it with individual blocks or
IO sized chunks because that would be huge and inefficient. PSS works
with massive block ranges that could be 1MB or whatever IIRC (good),
but I think you could probably represent those ranges as special queue
items {blockno, nblocks} and modify them in place until depleted. For
the second-level WorkQueueSet I was handwaving about, well the
ReadStream queue is also of fixed size, so if your own ReadStream
can't pull any more blocks out of the lower WorkQueueSet to chew on
(including stealing), and it can't steal any buffers from peer
ReadStreams connected to the same second-level WorkQueueSet, then the
scan truly is finished. You never gave up I/O combining until the
end, and you never gave up the ability to distribute the final
parallel granules of work (here: pages, could be/should be tuples but
let's not get carried away) one-at-a-time to whoever could help, you
didn't have to do any new cache line ping pong until the last few
blocks, and no one ever had to wait for a peer.

I admit this all sounds kinda complicated and maybe there is a much
simpler way to achieve the twin goals of maximising I/O combining AND
parallel query fairness. I should probably try stuff before
speculating much more. My main goal in writing these brain dumps was
to highlight at least what I think the problem to be solved is, as I
understood it so far anyway, after a first round of failure at
teaching PBHS the new ways. Maybe the particular idea sketched out
above sucks or doesn't work for some reason, IDK, but I hope at least
the framing might be useful... not too many have had the privilege and
pain of working on both parallel query and the new I/O stuff, and the
feature collision is new territory, so I wanted to share some ideas
about the problem space and solicit better ideas :-)

[1]: https://en.wikipedia.org/wiki/Threading_Building_Blocks

#241James Hunter
james.hunter.pg@gmail.com
In reply to: Thomas Munro (#240)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Apr 9, 2025 at 11:00 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Wed, Apr 9, 2025 at 1:46 PM James Hunter <james.hunter.pg@gmail.com> wrote:

On Mon, Apr 7, 2025 at 7:34 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Thu, Feb 13, 2025 at 1:40 PM Melanie Plageman
<melanieplageman@gmail.com> wrote:

Thomas mentioned this to me off-list, and I think he's right. We
likely need to rethink the way parallel bitmap heap scan workers get
block assignments for reading and prefetching to make it more similar
to parallel sequential scan. The workers should probably get
assignments of a range of blocks. On master, each worker does end up
issuing reads/fadvises for a bunch of blocks in a row -- even though
that isn't the intent of the parallel bitmap table scan
implementation. We are losing some of that with the patch -- but only
because it is behaving as you would expect given the implementation
and design. I don't consider that a blocker, though.

I had a crack at this one a few weeks back, and wanted to share some
thoughts.

Fwiw, I've had reasonably good results, in a similar situation, by
just batching + double-buffering.

Since you're using AIO (as Melanie points out) there should be no real
penalty to having a single worker request the next batch of blocks,
when the current block is used up.

Then you can separate "reading" from "prefetching": whoever reads the
last block in the current batch, prefetches the next batch.

I'm trying to understand. IIUC you're suggesting putting the blocks
coming *out* of a worker's ReadStream into a single common shmem queue
for any worker to consume (can't do this for block numbers coming *in*
to the ReadStreams or you're describing what we already have in
master, all mechanical sympathy for I/O out the window).

I am looking at the pre-streaming code, in PG 17, as I am not familiar
with the PG 18 "streaming" code. Back in PG 17, nodeBitmapHeapscan.c
maintained two shared TBM iterators, for PQ. One of the iterators was
the actual, "fetch" iterator; the other was the "prefetch" iterator,
which kept some distance ahead of the "fetch" iterator (to hide read
latency).

In general, I find PG's "streaming" interface to be an awkward way of
thinking about prefetching. But in this specific case, what are you
trying to solve? Is it contention on the shared "iteration" state? Or
is it finding an efficient way to issue lots of async reads?

Or is it trying to issue async reads for blocks laid out consecutively
on disk? (Is that what you mean by "mechanical sympathy for I/O"?)

Don't you
have to release the buffers you just streamed after putting their the
block numbers in a common shmem queue, hope they don't get evicted,
repin them when you pop one out,

Yes, sure. If they do get evicted, then you were prefetching too far
ahead, right? Unpinning + repinning keeps the buffer pool more "fair,"
at the cost of atomic updates + contention. CPUs are happy to evict
prefetched data, they don't care if you've had the chance to use them.

and also contend on the queue for
every block?

No, because you can read a batch of blocks out to process-local
memory, at one time. Use the standard pattern: lock shared state, read
a batch of work from shared state to local state, unlock shared state.
Contention is amortized over the batch; by picking a reasonable batch
size, you typically make contention small enough that it doesn't
matter.

What if you go to that queue to find a block, find it is
empty, but actually another backend still has an I/O in progress that
you have no way of knowing about?

Any time you try to read a buffer from the buffer pool, there's a
chance some other backend still has an I/O in progress on it, right?
Existing PG code just has everyone wait for the I/O to complete. This
ends up being what you want to do, anyway...

Suppose you do know about it
somehow, so now you have to wait for it to complete the IO before you
can help, but generally speaking it's against the law to wait for
parallel workers unless you can prove they'll come back (for example
there might be another node in the plan where they are waiting for
*you*, deadlock, game over), and even if you could wait safely.

My confusion here is probably due to my unfamiliarity with how you're
handling async I/Os, but once some backend has issued an aync I/O,
don't most async I/O frameworks complete the I/O on their own?
Certainly the O/S is going to memcpy() the block into some destination
address.

Why can't the first backend to wait for I/O completion also be
responsible for setting the buffer header bits appropriately?
Basically, let whatever backend first needs the block be responsible
for processing the I/O completion.

Since waiting for an I/O completion is a blocking, synchronous
operation, how is deadlock possible?

If
you don't wait, you just threw parallel fairness out the window.
Hence desire to make all relevant materials for progress at
end-of-scan eligible for work stealing.

I may have misunderstood the context of this discussion, but isn't
this all about *async* I/O? (If it's not async, what does "prefetch"
mean?) With async I/O, there's no reason why the entity that issues
the I/O also has to process its completion. (MySQL, for example, IIRC,
uses a dedicated thread pool to process completions.)

You just need *some* backend to issue a batch of async reads, on
behalf of *all* backends. And then whenever a particular backend needs
one of the blocks including in that async batch of reads, it waits for
the async read to complete. And if there's no outstanding async read,
then (I think this can be handled fairly well using existing PG code)
it just issues a new, synchronous read.

I think this is just what "prefetch" means. For example, if you ask
the CPU to prefetch address 0xf00 into L1 cache, the CPU doesn't worry
about whether that address was actually loaded in time, or whether it
gets read by the same or a different thread. You have an in-flight,
async operation; and then whenever someone needs the result, they
block (or not) depending on whether the async operation already
completed.

What I'm speculating about is not a true generalised work stealing or
scheduling system (take for example Intel TBB[1] and various other
parallel computing architectures going back decades), so I'm using the
term pretty loosely: we can't generally chop all of our executor work
up into tiny tasks and have any thread run any of them at any time to
make progress (that'd be a nice goal but you basically have to blow
the executor up with dynamite and then reassemble all the atoms into
coroutines/continuations/tasks (or various similar-ish concepts) to
achieve something like that, probably after you first make all of
PostgreSQL multi-threaded unless you want to do it with your shoelaces
tied together, and then take a very long holiday). Probably by
mentioning work stealing I made it sound more complicated than
necessary, but hear me out:

I don't have an opinion about chopping up (CPU) work , but my point is
that I/Os go to a different resource -- they have a different queue.
So you don't usually *need* to chop up *I/O* work. Assuming you can
saturate I/O bandwidth / fill the I/O queue using a single thread,
then you don't need to worry about all of the above -- at least not
for I/Os! And, for CPU, you can typically get away with maintaining a
single global queue, and just copying (sequential) batches of work
from the global queue into thread- or process- local memory.

Why do you want to chop up and reassemble work? Is this CPU work or I/O work?

A tiny, delimited, node-local kind of work stealing could replace (now
non-viable) ramp-down schemes,

I guess, for I/Os, the only work-stealing I think about is to handle
I/O completions. And that part, at least, can be done (as sketched
above) by having backends complete async I/Os inside ReadBuffer().

I admit this all sounds kinda complicated and maybe there is a much
simpler way to achieve the twin goals of maximising I/O combining AND
parallel query fairness.

I tend to think that the two goals are so much in conflict, that it's
not worth trying to apply cleverness to get them to agree on things...
What I mean is, if you have to take inputs from multiple parties,
combine them, sort them, and then produce a Run-Length-Encoding of the
result, then there's always going to be lots of contention. And you'll
also have to deal with increased latency: should I wait to see if more
blocks come in, to see if it lets me combine I/Os, or should I send
the batch now?

But, if you just do the most naive thing possible (which is my
suggestion!), then whatever backend's turn it is to advance the
prefetch iterator, it advances it by (let's say) 50 blocks. It can
then try to combine those 50 blocks, with no contention or added
complexity. Might that be sufficient?

I think that, generally, there are only a few techniques that work
consistently for concurrency / async operations. And these techniques
are necessarily primitive, they are blunt tools. It sounds like you
are working on a subtle, complex, refined solution... and I am just
doubtful that any such solution will end up being efficient. It is
hard to create a complex concurrent execution model that's also fast.

For example, simple batching is the solution to a lot of problems. Any
time you process a batch of stuff, you amortize any fixed costs over
the size of the batch. This is a blunt tool, but it always works.

Also, work stealing is great, and one of the nicest ways to steal work
is the "async/await" or "coroutines" model, where someone -- we don't
care who! -- sends an async request; and then, at some point in the
future, someone (else? we don't care!) waits for that async request to
complete. And if there's more work to be done, to complete the async
request, then whoever waits first does that work. So you steal work
from the thread/process that needs that work to be done -- very nice.
This is also a blunt tool, but it works.

With PG, specifically, waiting for a read into buffer pool to complete
seems to go through the same interface as actually performing that
read. So this helps you out for prefetch -- which is always
best-effort, it's not the prefetch operation's job to ensure that the
prefetched data doesn't get evicted -- because you really don't even
need to track async reads after you've issued them! This lets PG
prefetch behave like CPU prefetch.

James

#242Thomas Munro
thomas.munro@gmail.com
In reply to: James Hunter (#241)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Fri, Apr 11, 2025 at 5:50 AM James Hunter <james.hunter.pg@gmail.com> wrote:

I am looking at the pre-streaming code, in PG 17, as I am not familiar
with the PG 18 "streaming" code. Back in PG 17, nodeBitmapHeapscan.c
maintained two shared TBM iterators, for PQ. One of the iterators was
the actual, "fetch" iterator; the other was the "prefetch" iterator,
which kept some distance ahead of the "fetch" iterator (to hide read
latency).

We're talking at cross-purposes.

The new streaming BHS isn't just issuing probabilistic hints about
future access obtained from a second iterator. It has just one shared
iterator connected up to the workers' ReadStreams. Each worker pulls
a disjoint set of blocks out of its stream, possibly running a bunch
of IOs in the background as required. The stream replaces the old
ReadBuffer() call, and the old PrefetchBuffer() call and a bunch of
dubious iterator synchronisation logic are deleted. These are now
real IOs running in the background and for the *exact* blocks you will
consume; posix_fadvise() was just a stepping towards AIO that
tolerated sloppy synchronisation including being entirely wrong. If
you additionally teach the iterator to work in batches, as my 0001
patch (which I didn't propose for v18) showed, then one worker might
end up processing (say) 10 blocks at end-of-scan while all the other
workers have finished the node, and maybe the whole query. That'd be
unfair. "Ramp-down" ... 8, 4, 2, 1 has been used in one or two other
places in parallel-aware nodes with internal batching as a kind of
fudge to help them finish CPU work around the same time if you're
lucky, and my 0002 patch shows that NOT working here. I suspect the
concept itself is defunct: it no longer narrows the CPU work
completion time range across workers at all well due to the elastic
streams sitting in between. Any naive solution that requires
cooperation/waiting for another worker to hand over final scraps of
work originally allocated to it (and I don't mean the IO completion
part, that all just works just fine as you say, a lot of engineering
went into the buffer manager to make that true, for AIO but also in
the preceding decades... what I mean here is: how do you even know
which block to read?) is probably a deadlock risk. Essays have been
written on the topic if you are interested.

All the rest of our conversation makes no sense without that context :-)

I admit this all sounds kinda complicated and maybe there is a much
simpler way to achieve the twin goals of maximising I/O combining AND
parallel query fairness.

I tend to think that the two goals are so much in conflict, that it's
not worth trying to apply cleverness to get them to agree on things...

I don't give up so easily :-)

#243James Hunter
james.hunter.pg@gmail.com
In reply to: Thomas Munro (#242)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Apr 10, 2025 at 8:15 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Fri, Apr 11, 2025 at 5:50 AM James Hunter <james.hunter.pg@gmail.com> wrote:

I am looking at the pre-streaming code, in PG 17, as I am not familiar
with the PG 18 "streaming" code. Back in PG 17, nodeBitmapHeapscan.c
maintained two shared TBM iterators, for PQ. One of the iterators was
the actual, "fetch" iterator; the other was the "prefetch" iterator,
which kept some distance ahead of the "fetch" iterator (to hide read
latency).

We're talking at cross-purposes.

The new streaming BHS isn't just issuing probabilistic hints about
future access obtained from a second iterator. It has just one shared
iterator connected up to the workers' ReadStreams. Each worker pulls
a disjoint set of blocks out of its stream, possibly running a bunch
of IOs in the background as required. The stream replaces the old
ReadBuffer() call, and the old PrefetchBuffer() call and a bunch of
dubious iterator synchronisation logic are deleted.

Thanks for the clarification -- I realize I am very late to this
conversation (as I rejoined a PostgreSQL-related team only within the
past year), but I think this whole "ReadStream" project is misguided.

Of course, late feedback is a burden, but I think our discussion here
(and, in the future, if you try to "ReadStream" BTree index pages,
themselves) illustrates my point. In this specific case, you are
proposing a lot of complexity, but it's not at all clear to me: why?

I see two orthogonal problems, in processing Bitmap Heap pages in
parallel: (1) we need to prefetch enough pages, far enough in advance,
to hide read latency; (2) later, every parallel worker needs to be
given a set of pages to process, in a way that minimizes contention.

The easiest way to hand out work to parallel workers (and often the
best) is to maintain a single, shared, global work queue. Just put
whatever pages you prefetch into a FIFO queue, and let each worker
pull one piece of "work" off that queue. In this was, there's no
"ramp-down" problem.

If you find that contention on this shared queue becomes a bottleneck,
then you just pull *n* pieces of work, in a batch. Then the
"ramp-down" problem is limited to "n", instead of just 1. Often, one
can find a suitable value of n that simultaneously makes contention
effectively zero, while avoiding "ramp-down" problems; say n = 10.

So much for popping from the shared queue. Pushing to the shared queue
is also easy, because you have async reads. Anytime a worker pops a
(batch of) work item(s) off the shared queue, it checks to see if the
queue is still large enough. If not, it issues the appropriate
prefetch / "ReadStream" calls.

A single shared queue is easiest, but sometimes there's no way to
prevent it from becoming a bottleneck. In that case, one typically
partitions the input at startup, gives each worker its own partition,
and waits for all workers to complete. In this, second, model, workers
are entirely independent, so there is no contention: we scale out
perfectly. The problem, as you've pointed out, is that one worker
might finish its own work long before another; and then the worker
that finished its work is idle and therefore wasted.

This is why a single shared queue is so nice, because it avoids
workers being idle. But I am confused by your proposal, which seems to
be trying to get the behavior of a single shared queue, but
implemented with the added complexity of multiple queues.

Why not just use a single queue?

These are now
real IOs running in the background and for the *exact* blocks you will
consume; posix_fadvise() was just a stepping towards AIO that
tolerated sloppy synchronisation including being entirely wrong.

It has never been clear to me why prefetching the exact blocks you'll
later consume is seen as a *benefit*, rather than a *cost*. I'm not
aware of any prefetch interface, other than PG's "ReadStream," that
insists on this. But that's a separate discussion...

If
you additionally teach the iterator to work in batches, as my 0001
patch (which I didn't propose for v18) showed, then one worker might
end up processing (say) 10 blocks at end-of-scan while all the other
workers have finished the node, and maybe the whole query.

The standard solution to the problem you describe here is to pick a
batch size small enough that you don't care. For example, no matter
what you do, it will always be possible for one worker to end up
processing *1* extra block, end of scan. If 1 is OK, but 10 is too
large, then I would try 5. AFAIU, the argument for larger batches is
to reduce contention; and the argument for smaller batches is to
reduce amount of time workers are idle, at end of query. The problem
seems amenable to a static solution -- there should be a value of n
that satisfies both restrictions.

Otherwise, we'd implicitly be saying that contention is very slow,
compared to the time it takes a worker to process a block; while also
saying that it takes workers a long time to process each block.

For example, if you figure 10 us to process each block, then a batch
of size n = 10 gives each worker 100 us of CPU time, between when it
needs to acquire the global mutex, to get the next batch of work. Does
this make contention low enough? And then, if you figure that a
parallel query has to run >= 100 ms, to make PQ worthwhile, then the
"idle" time is at most 100 us / 100 ms = 0.1 percent, and therefore
inconsequential.

That'd be
unfair. "Ramp-down" ... 8, 4, 2, 1 has been used in one or two other
places in parallel-aware nodes with internal batching as a kind of
fudge to help them finish CPU work around the same time if you're
lucky, and my 0002 patch shows that NOT working here. I suspect the
concept itself is defunct: it no longer narrows the CPU work
completion time range across workers at all well due to the elastic
streams sitting in between.

I think you are arguing that a single shared queue won't work, but
it's not clear to me why it won't. Maybe the problem is these elastic
streams?

What I don't understand is -- and I apologize again for interjecting
myself into this conversation so late -- why do you want or need
multiple streams? Logically, every PG scan is a single stream of
blocks, and parallel workers just pull batches of work off that single
stream.

Suppose the "ReadStream" order for a Bitmap Heap Scan is blocks: 0, 2,
1, 3, 4, 6, 5, 7, 8, 10, 9, 11, ... Why would we want or need to
affinitize reads to a particular worker? These are the blocks to be
read; this is the order in which they need to be read. Any worker can
issue any read, because we are using async I/O.

Any naive solution that requires
cooperation/waiting for another worker to hand over final scraps of
work originally allocated to it (and I don't mean the IO completion
part, that all just works just fine as you say, a lot of engineering
went into the buffer manager to make that true, for AIO but also in
the preceding decades...

You have lost me here. Every fork() / join() algorithm requires
waiting for a worker to hand over the final scraps of work allocated
to it, and AFAIK, no one has ever worried about deadlock risk from
fork() / join()...

what I mean here is: how do you even know
which block to read?) is probably a deadlock risk. Essays have been
written on the topic if you are interested.

I think this may be where we are talking at cross purposes. Well,
reading a block is an async operation, right? And a parallel Bitmap
Heap Scan visits exactly the same pages as its serial variant.

Every worker acquires the shared queue's mutex. It pops n blocks off
the shared queue. If the shared queue is now too small, it iterates
the "ReadStream" to get *m* more page IDs, issues async reads for
those pages, and pushes them on the shared queue. The worker then
releases the mutex.

If by "read" you mean, "issue an async read," then you know which
block to read by visiting the (shared) "ReadStream".

if, instead, you mean, "process a block," then you know because you
popped it off the shared queue.

All the rest of our conversation makes no sense without that context :-)

I think I am still missing something, but I am not sure what. For
example, I can't see how deadlock would be a problem...

I admit this all sounds kinda complicated and maybe there is a much
simpler way to achieve the twin goals of maximising I/O combining AND
parallel query fairness.

I tend to think that the two goals are so much in conflict, that it's
not worth trying to apply cleverness to get them to agree on things...

I don't give up so easily :-)

Now that I think about the problem more -- "maximizing I/O combining"
is orthogonal to "parallel query fairness," right?

Parallel query fairness involves splitting up CPU via small batches.
Maximizing I/O combining involves making I/O more efficient, by
issuing large batches.

However, there's no reason I can see why the *I/O batch* needs to
resemble the *CPU batch*. If maximizing I/O combining leads me to
issue a batch of 1,000 reads at a time, then so what? These are all
async reads! The "unlucky" worker issues its 1,000 reads, then gets on
with its life.

If parallel query fairness leads me to *process* a batch of 10 blocks
at a time -- then, again, so what? CPU and I/O are independent
resources.

Why not just prefetch / read-stream 1,000 blocks at a time, while
processing (using CPU) 10 blocks at a time? Wouldn't that achieve your
twin goals, without requiring multiple queues / streams / etc.?

Thanks,
James

#244Andres Freund
andres@anarazel.de
In reply to: James Hunter (#243)
Re: BitmapHeapScan streaming read user and prelim refactoring

Hi,

On 2025-04-14 09:58:19 -0700, James Hunter wrote:

Of course, late feedback is a burden, but I think our discussion here
(and, in the future, if you try to "ReadStream" BTree index pages,
themselves) illustrates my point.

FWIW, it's quite conceivable that we'll want to use non-readstream prefetching
for some cases where "heuristic" prefetching is easier. I think prefetching of
btree pages is one of those cases.

The read stream based API provides a single point of adjusting the readahead
logic, implementing read-combining etc, without needing to know about that in
the user of the read stream.

I see two orthogonal problems, in processing Bitmap Heap pages in
parallel: (1) we need to prefetch enough pages, far enough in advance,
to hide read latency; (2) later, every parallel worker needs to be
given a set of pages to process, in a way that minimizes contention.

The easiest way to hand out work to parallel workers (and often the
best) is to maintain a single, shared, global work queue. Just put
whatever pages you prefetch into a FIFO queue, and let each worker
pull one piece of "work" off that queue. In this was, there's no
"ramp-down" problem.

If you just issue prefetch requests separately you'll get no read combining -
and it turns out that that is a really rather significant loss, both on the
storage layer and just due to the syscall overhead. So you do need to perform
batching when issuing IO. Which in turn requires a bit of rampup logic etc.

If you find that contention on this shared queue becomes a bottleneck,
then you just pull *n* pieces of work, in a batch. Then the
"ramp-down" problem is limited to "n", instead of just 1. Often, one
can find a suitable value of n that simultaneously makes contention
effectively zero, while avoiding "ramp-down" problems; say n = 10.

So much for popping from the shared queue. Pushing to the shared queue
is also easy, because you have async reads. Anytime a worker pops a
(batch of) work item(s) off the shared queue, it checks to see if the
queue is still large enough. If not, it issues the appropriate
prefetch / "ReadStream" calls.

A single shared queue is easiest, but sometimes there's no way to
prevent it from becoming a bottleneck. In that case, one typically
partitions the input at startup, gives each worker its own partition,
and waits for all workers to complete. In this, second, model, workers
are entirely independent, so there is no contention: we scale out
perfectly. The problem, as you've pointed out, is that one worker
might finish its own work long before another; and then the worker
that finished its work is idle and therefore wasted.

This is why a single shared queue is so nice, because it avoids
workers being idle. But I am confused by your proposal, which seems to
be trying to get the behavior of a single shared queue, but
implemented with the added complexity of multiple queues.

Why not just use a single queue?

Accessing buffers in a maximally interleaved way, which is what a single queue
would give you, adds a good bit of overhead when you have a lot of memory,
because e.g. TLB hit rate is minimized.

These are now
real IOs running in the background and for the *exact* blocks you will
consume; posix_fadvise() was just a stepping towards AIO that
tolerated sloppy synchronisation including being entirely wrong.

It has never been clear to me why prefetching the exact blocks you'll
later consume is seen as a *benefit*, rather than a *cost*. I'm not
aware of any prefetch interface, other than PG's "ReadStream," that
insists on this. But that's a separate discussion...

It (randomly ordered):

a) reduces wasted IO

b) makes things like IO combining a lot easier

c) makes it a lot easier to adaptively control readahead distance, because you
have information about
1) the # in-flight IOs
2) the # completed IOs
3) current position
4) reada

d) provides *per-stream* control over readahead. You want to be only as
aggressive about prefetching as you need to be, which very well can differ
between different parts of a query tree.

e) provides one central point to implement readahead logic

As I said above, that's not to say that we'll only ever want to do readahead
via a the read stream interface.

Greetings,

Andres Freund

#245Robert Haas
robertmhaas@gmail.com
In reply to: Thomas Munro (#242)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Thu, Apr 10, 2025 at 11:15 PM Thomas Munro <thomas.munro@gmail.com> wrote:

The new streaming BHS isn't just issuing probabilistic hints about
future access obtained from a second iterator. It has just one shared
iterator connected up to the workers' ReadStreams. Each worker pulls
a disjoint set of blocks out of its stream, possibly running a bunch
of IOs in the background as required.

It feels to me like the problem here is that the shared iterator is
connected to unshared read-streams. If you make a shared read-stream
object and connect the shared iterator to that instead, does that
solve this whole problem, or is there more to it?

--
Robert Haas
EDB: http://www.enterprisedb.com

#246James Hunter
james.hunter.pg@gmail.com
In reply to: Andres Freund (#244)
Re: BitmapHeapScan streaming read user and prelim refactoring

Thanks for the comments!

On Tue, Apr 15, 2025 at 3:11 AM Andres Freund <andres@anarazel.de> wrote:

Hi,

On 2025-04-14 09:58:19 -0700, James Hunter wrote:

I see two orthogonal problems, in processing Bitmap Heap pages in
parallel: (1) we need to prefetch enough pages, far enough in advance,
to hide read latency; (2) later, every parallel worker needs to be
given a set of pages to process, in a way that minimizes contention.

The easiest way to hand out work to parallel workers (and often the
best) is to maintain a single, shared, global work queue. Just put
whatever pages you prefetch into a FIFO queue, and let each worker
pull one piece of "work" off that queue. In this was, there's no
"ramp-down" problem.

If you just issue prefetch requests separately you'll get no read combining -
and it turns out that that is a really rather significant loss, both on the
storage layer and just due to the syscall overhead. So you do need to perform
batching when issuing IO. Which in turn requires a bit of rampup logic etc.

Right, so if you need to do batching anyway, contention on a shared
queue will be minimal, because it's amortized over the batch size.

I agree about ramp *up* logic, I just don't see the need for ramp *down* logic.

This is why a single shared queue is so nice, because it avoids
workers being idle. But I am confused by your proposal, which seems to
be trying to get the behavior of a single shared queue, but
implemented with the added complexity of multiple queues.

Why not just use a single queue?

Accessing buffers in a maximally interleaved way, which is what a single queue
would give you, adds a good bit of overhead when you have a lot of memory,
because e.g. TLB hit rate is minimized.

Well that's trade-off, right? As you point out, you need to do
batching when issuing reads, to allow for read combining. The larger
your batch, the more reads you can combine -- the more efficient your
I/O, etc. But the larger your batch, the less locality you get in
memory.

You always have to choose a batch size large enough to hide I/O
latency, plus allow, I guess, for read combining. I suspect that will
blow out your TLB more than letting 8 parallel workers share the same
queue.

Not to mention the complexity (as Thomas has described very nicely, in
this thread) of trying to partition+affinitize async read requests to
individual parallel workers. (Consider "ramp-down" for a moment: the
"problem" here is just that one parallel worker issued a batch of
async reads , near the end of the query; and since the worker is
affinitized to the async read, all other workers pack up and go home,
leaving a single worker to process this last batch. If, instead, we
just used a single queue, then there would be no need for "ramp-down"
logic, because async reads would go into a single queue/pool, and not
be affinitized to a single, "unlucky" worker.)

It has never been clear to me why prefetching the exact blocks you'll
later consume is seen as a *benefit*, rather than a *cost*. I'm not
aware of any prefetch interface, other than PG's "ReadStream," that
insists on this. But that's a separate discussion...

...

As I said above, that's not to say that we'll only ever want to do readahead
via a the read stream interface.

Well that's my point: since, I believe, we'll ultimately want a
"heuristic" prefetch, which will be incompatible with the new read
stream interface... we'll end up writing and supporting two different
prefetch interfaces.

It has never been clear to me that the advantages of having this
second, read-stream, prefetch interface outweigh the costs of having
to write and maintain two separate interfaces, to do pretty much the
same thing. If we *didn't* need the "heuristic" interface, then I
could be convinced that the "read-stream" interface was a good choice.
But since we'll (eventually) need the "heuristic" interface, anyway,
it's not clear to me that the benefits outweigh the costs of
implementing this "read-stream" interface, as well.

Thanks,
James

#247Thomas Munro
thomas.munro@gmail.com
In reply to: Robert Haas (#245)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Tue, Apr 15, 2025 at 5:44 AM Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Apr 10, 2025 at 11:15 PM Thomas Munro <thomas.munro@gmail.com> wrote:

The new streaming BHS isn't just issuing probabilistic hints about
future access obtained from a second iterator. It has just one shared
iterator connected up to the workers' ReadStreams. Each worker pulls
a disjoint set of blocks out of its stream, possibly running a bunch
of IOs in the background as required.

It feels to me like the problem here is that the shared iterator is
connected to unshared read-streams. If you make a shared read-stream
object and connect the shared iterator to that instead, does that
solve this whole problem, or is there more to it?

More or less, yeah, just put the whole ReadStream object in shared
memory, pin an LWLock on it and call it a parallel-aware or shared
ReadStream. But how do you make the locking not terrible?

My "work stealing" brain dump was imagining a way to achieve the same
net effect, except NOT have to acquire an exclusive lock for every
buffer you pull out of the stream. I was speculating that we could
achieve zero locking for most of the stream without any cache line
ping pong, but a cunning read barrier scheme could detect when you've
been flipped into a slower coordination mode by another backend and
need to turn on some locking and fight over the last handful of
buffers. And I was also observing that if you can figure out to make
it general and reusable enough, we have more unsolved problems like
this in unrelated parallel query code not even involving streams.
It's a tiny more approachable subset of the old "data buffered in
other workers" problem, as I think you called it once.

#248Robert Haas
robertmhaas@gmail.com
In reply to: Thomas Munro (#247)
Re: BitmapHeapScan streaming read user and prelim refactoring

On Wed, Apr 16, 2025 at 12:31 AM Thomas Munro <thomas.munro@gmail.com> wrote:

More or less, yeah, just put the whole ReadStream object in shared
memory, pin an LWLock on it and call it a parallel-aware or shared
ReadStream. But how do you make the locking not terrible?

My "work stealing" brain dump was imagining a way to achieve the same
net effect, except NOT have to acquire an exclusive lock for every
buffer you pull out of the stream. I was speculating that we could
achieve zero locking for most of the stream without any cache line
ping pong, but a cunning read barrier scheme could detect when you've
been flipped into a slower coordination mode by another backend and
need to turn on some locking and fight over the last handful of
buffers. And I was also observing that if you can figure out to make
it general and reusable enough, we have more unsolved problems like
this in unrelated parallel query code not even involving streams.
It's a tiny more approachable subset of the old "data buffered in
other workers" problem, as I think you called it once.

Maybe the work stealing stuff can hide inside the ReadStream? e.g. a
ParallelReadStream is really one ReadStream per participant, each with
a separate lock. Mostly you only touch your own, but if necessary you
can poke your fingers into other people's ReadStreams.

--
Robert Haas
EDB: http://www.enterprisedb.com